summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
0 files changed, 0 insertions, 0 deletions
/td>.mailmap13
-rw-r--r--CREDITS8
-rw-r--r--Documentation/ABI/stable/sysfs-driver-dma-idxd6
-rw-r--r--Documentation/ABI/testing/configfs-tsm82
-rw-r--r--Documentation/ABI/testing/configfs-usb-gadget-uac22
-rw-r--r--Documentation/ABI/testing/debugfs-driver-habanalabs82
-rw-r--r--Documentation/ABI/testing/debugfs-driver-qat24
-rw-r--r--Documentation/ABI/testing/sysfs-bus-cdx66
-rw-r--r--Documentation/ABI/testing/sysfs-bus-cxl30
-rw-r--r--Documentation/ABI/testing/sysfs-bus-i3c4
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio75
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio-adc-mcp356453
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio-resolver-ad2s121027
-rw-r--r--Documentation/ABI/testing/sysfs-bus-optee-devices9
-rw-r--r--Documentation/ABI/testing/sysfs-bus-papr-pmem2
-rw-r--r--Documentation/ABI/testing/sysfs-bus-usb9
-rw-r--r--Documentation/ABI/testing/sysfs-bus-vdpa4
-rw-r--r--Documentation/ABI/testing/sysfs-class-firmware14
-rw-r--r--Documentation/ABI/testing/sysfs-class-firmware-attributes30
-rw-r--r--Documentation/ABI/testing/sysfs-class-led9
-rw-r--r--Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia14
-rw-r--r--Documentation/ABI/testing/sysfs-class-usb_power_delivery7
-rw-r--r--Documentation/ABI/testing/sysfs-devices-system-cpu3
-rw-r--r--Documentation/ABI/testing/sysfs-driver-habanalabs64
-rw-r--r--Documentation/ABI/testing/sysfs-driver-intel-m10-bmc4
-rw-r--r--Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update14
-rw-r--r--Documentation/ABI/testing/sysfs-driver-qat48
-rw-r--r--Documentation/ABI/testing/sysfs-driver-qat_ras41
-rw-r--r--Documentation/ABI/testing/sysfs-driver-qat_rl226
-rw-r--r--Documentation/ABI/testing/sysfs-firmware-dmi-entries2
-rw-r--r--Documentation/ABI/testing/sysfs-kernel-mm-damon7
-rw-r--r--Documentation/ABI/testing/sysfs-tty15
-rw-r--r--Documentation/PCI/pci-error-recovery.rst4
-rw-r--r--Documentation/RCU/Design/Expedited-Grace-Periods/Expedited-Grace-Periods.rst2
-rw-r--r--Documentation/RCU/Design/Memory-Ordering/TreeRCU-callback-registry.svg9
-rw-r--r--Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-fqs.svg4
-rw-r--r--Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp.svg13
-rw-r--r--Documentation/RCU/Design/Memory-Ordering/TreeRCU-hotplug.svg4
-rw-r--r--Documentation/RCU/Design/Requirements/Requirements.rst4
-rw-r--r--Documentation/RCU/listRCU.rst9
-rw-r--r--Documentation/RCU/whatisRCU.rst4
-rw-r--r--Documentation/accel/qaic/qaic.rst10
-rw-r--r--Documentation/admin-guide/cgroup-v1/memory.rst1
-rw-r--r--Documentation/admin-guide/cgroup-v2.rst178
-rw-r--r--Documentation/admin-guide/dynamic-debug-howto.rst2
-rw-r--r--Documentation/admin-guide/efi-stub.rst2
-rw-r--r--Documentation/admin-guide/hw-vuln/mds.rst34
-rw-r--r--Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst13
-rw-r--r--Documentation/admin-guide/hw-vuln/srso.rst24
-rw-r--r--Documentation/admin-guide/hw-vuln/tsx_async_abort.rst33
-rw-r--r--Documentation/admin-guide/kdump/kdump.rst37
-rw-r--r--Documentation/admin-guide/kdump/vmcoreinfo.rst30
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt119
-rw-r--r--Documentation/admin-guide/laptops/thinkpad-acpi.rst20
-rw-r--r--Documentation/admin-guide/media/mgb4.rst374
-rw-r--r--Documentation/admin-guide/media/pci-cardlist.rst1
-rw-r--r--Documentation/admin-guide/media/v4l-drivers.rst1
-rw-r--r--Documentation/admin-guide/media/visl.rst6
-rw-r--r--Documentation/admin-guide/mm/damon/usage.rst124
-rw-r--r--Documentation/admin-guide/mm/ksm.rst11
-rw-r--r--Documentation/admin-guide/mm/memory-hotplug.rst12
-rw-r--r--Documentation/admin-guide/mm/pagemap.rst89
-rw-r--r--Documentation/admin-guide/mm/userfaultfd.rst35
-rw-r--r--Documentation/admin-guide/module-signing.rst17
-rw-r--r--Documentation/admin-guide/perf/ampere_cspmu.rst29
-rw-r--r--Documentation/admin-guide/perf/index.rst1
-rw-r--r--Documentation/admin-guide/pm/intel_idle.rst17
-rw-r--r--Documentation/admin-guide/pstore-blk.rst8
-rw-r--r--Documentation/admin-guide/spkguide.txt11
-rw-r--r--Documentation/admin-guide/sysctl/fs.rst16
-rw-r--r--Documentation/admin-guide/sysctl/kernel.rst26
-rw-r--r--Documentation/admin-guide/sysctl/net.rst1
-rw-r--r--Documentation/admin-guide/sysctl/vm.rst4
-rw-r--r--Documentation/arch/arm64/cpu-feature-registers.rst2
-rw-r--r--Documentation/arch/arm64/elf_hwcaps.rst15
-rw-r--r--Documentation/arch/ia64/aliasing.rst246
-rw-r--r--Documentation/arch/ia64/efirtc.rst144
-rw-r--r--Documentation/arch/ia64/err_inject.rst1067
-rw-r--r--Documentation/arch/ia64/features.rst3
-rw-r--r--Documentation/arch/ia64/fsys.rst303
-rw-r--r--Documentation/arch/ia64/ia64.rst49
-rw-r--r--Documentation/arch/ia64/index.rst19
-rw-r--r--Documentation/arch/ia64/irq-redir.rst80
-rw-r--r--Documentation/arch/ia64/mca.rst198
-rw-r--r--Documentation/arch/ia64/serial.rst165
-rw-r--r--Documentation/arch/index.rst5
-rw-r--r--Documentation/arch/loongarch/introduction.rst4
-rw-r--r--Documentation/arch/powerpc/associativity.rst (renamed from Documentation/powerpc/associativity.rst)0
-rw-r--r--Documentation/arch/powerpc/booting.rst (renamed from Documentation/powerpc/booting.rst)0
-rw-r--r--Documentation/arch/powerpc/bootwrapper.rst (renamed from Documentation/powerpc/bootwrapper.rst)0
-rw-r--r--Documentation/arch/powerpc/cpu_families.rst (renamed from Documentation/powerpc/cpu_families.rst)0
-rw-r--r--Documentation/arch/powerpc/cpu_features.rst (renamed from Documentation/powerpc/cpu_features.rst)0
-rw-r--r--Documentation/arch/powerpc/cxl.rst (renamed from Documentation/powerpc/cxl.rst)0
-rw-r--r--Documentation/arch/powerpc/cxlflash.rst (renamed from Documentation/powerpc/cxlflash.rst)2
-rw-r--r--Documentation/arch/powerpc/dawr-power9.rst (renamed from Documentation/powerpc/dawr-power9.rst)0
-rw-r--r--Documentation/arch/powerpc/dexcr.rst (renamed from Documentation/powerpc/dexcr.rst)0
-rw-r--r--Documentation/arch/powerpc/dscr.rst (renamed from Documentation/powerpc/dscr.rst)0
-rw-r--r--Documentation/arch/powerpc/eeh-pci-error-recovery.rst (renamed from Documentation/powerpc/eeh-pci-error-recovery.rst)0
-rw-r--r--Documentation/arch/powerpc/elf_hwcaps.rst (renamed from Documentation/powerpc/elf_hwcaps.rst)6
-rw-r--r--Documentation/arch/powerpc/elfnote.rst (renamed from Documentation/powerpc/elfnote.rst)0
-rw-r--r--Documentation/arch/powerpc/features.rst (renamed from Documentation/powerpc/features.rst)0
-rw-r--r--Documentation/arch/powerpc/firmware-assisted-dump.rst (renamed from Documentation/powerpc/firmware-assisted-dump.rst)0
-rw-r--r--Documentation/arch/powerpc/hvcs.rst (renamed from Documentation/powerpc/hvcs.rst)0
-rw-r--r--Documentation/arch/powerpc/imc.rst (renamed from Documentation/powerpc/imc.rst)0
-rw-r--r--Documentation/arch/powerpc/index.rst (renamed from Documentation/powerpc/index.rst)1
-rw-r--r--Documentation/arch/powerpc/isa-versions.rst (renamed from Documentation/powerpc/isa-versions.rst)0
-rw-r--r--Documentation/arch/powerpc/kasan.txt (renamed from Documentation/powerpc/kasan.txt)0
-rw-r--r--Documentation/arch/powerpc/kaslr-booke32.rst (renamed from Documentation/powerpc/kaslr-booke32.rst)0
-rw-r--r--Documentation/arch/powerpc/kvm-nested.rst634
-rw-r--r--Documentation/arch/powerpc/mpc52xx.rst (renamed from Documentation/powerpc/mpc52xx.rst)0
-rw-r--r--Documentation/arch/powerpc/papr_hcalls.rst (renamed from Documentation/powerpc/papr_hcalls.rst)0
-rw-r--r--Documentation/arch/powerpc/pci_iov_resource_on_powernv.rst (renamed from Documentation/powerpc/pci_iov_resource_on_powernv.rst)0
-rw-r--r--Documentation/arch/powerpc/pmu-ebb.rst (renamed from Documentation/powerpc/pmu-ebb.rst)0
-rw-r--r--Documentation/arch/powerpc/ptrace.rst (renamed from Documentation/powerpc/ptrace.rst)0
-rw-r--r--Documentation/arch/powerpc/qe_firmware.rst (renamed from Documentation/powerpc/qe_firmware.rst)0
-rw-r--r--Documentation/arch/powerpc/syscall64-abi.rst (renamed from Documentation/powerpc/syscall64-abi.rst)0
-rw-r--r--Documentation/arch/powerpc/transactional_memory.rst (renamed from Documentation/powerpc/transactional_memory.rst)0
-rw-r--r--Documentation/arch/powerpc/ultravisor.rst (renamed from Documentation/powerpc/ultravisor.rst)0
-rw-r--r--Documentation/arch/powerpc/vas-api.rst (renamed from Documentation/powerpc/vas-api.rst)0
-rw-r--r--Documentation/arch/powerpc/vcpudispatch_stats.rst (renamed from Documentation/powerpc/vcpudispatch_stats.rst)0
-rw-r--r--Documentation/arch/powerpc/vmemmap_dedup.rst (renamed from Documentation/powerpc/vmemmap_dedup.rst)0
-rw-r--r--Documentation/arch/riscv/acpi.rst (renamed from Documentation/riscv/acpi.rst)0
-rw-r--r--Documentation/arch/riscv/boot-image-header.rst (renamed from Documentation/riscv/boot-image-header.rst)0
-rw-r--r--Documentation/arch/riscv/boot.rst (renamed from Documentation/riscv/boot.rst)0
-rw-r--r--Documentation/arch/riscv/features.rst (renamed from Documentation/riscv/features.rst)0
-rw-r--r--Documentation/arch/riscv/hwprobe.rst (renamed from Documentation/riscv/hwprobe.rst)6
-rw-r--r--Documentation/arch/riscv/index.rst (renamed from Documentation/riscv/index.rst)0
-rw-r--r--Documentation/arch/riscv/patch-acceptance.rst (renamed from Documentation/riscv/patch-acceptance.rst)0
-rw-r--r--Documentation/arch/riscv/uabi.rst (renamed from Documentation/riscv/uabi.rst)20
-rw-r--r--Documentation/arch/riscv/vector.rst (renamed from Documentation/riscv/vector.rst)0
-rw-r--r--Documentation/arch/riscv/vm-layout.rst (renamed from Documentation/riscv/vm-layout.rst)0
-rw-r--r--Documentation/arch/sh/index.rst6
-rw-r--r--Documentation/arch/x86/amd-memory-encryption.rst2
-rw-r--r--Documentation/arch/x86/amd_hsmp.rst18
-rw-r--r--Documentation/arch/x86/boot.rst2
-rw-r--r--Documentation/arch/x86/iommu.rst2
-rw-r--r--Documentation/arch/x86/resctrl.rst38
-rw-r--r--Documentation/arch/x86/topology.rst12
-rw-r--r--Documentation/block/blk-mq.rst2
-rw-r--r--Documentation/block/ioprio.rst3
-rw-r--r--Documentation/bpf/kfuncs.rst6
-rw-r--r--Documentation/bpf/libbpf/program_types.rst10
-rw-r--r--Documentation/bpf/prog_flow_dissector.rst2
-rw-r--r--Documentation/bpf/standardization/instruction-set.rst8
-rw-r--r--Documentation/core-api/cpu_hotplug.rst6
-rw-r--r--Documentation/core-api/debugging-via-ohci1394.rst6
-rw-r--r--Documentation/core-api/maple_tree.rst2
-rw-r--r--Documentation/core-api/workqueue.rst4
-rw-r--r--Documentation/crypto/devel-algos.rst4
-rw-r--r--Documentation/dev-tools/kasan.rst7
-rw-r--r--Documentation/dev-tools/kcsan.rst4
-rw-r--r--Documentation/dev-tools/kmsan.rst6
-rw-r--r--Documentation/dev-tools/kselftest.rst6
-rw-r--r--Documentation/dev-tools/ubsan.rst6
-rw-r--r--Documentation/devicetree/bindings/Makefile2
-rw-r--r--Documentation/devicetree/bindings/arm/amd,pensando.yaml26
-rw-r--r--Documentation/devicetree/bindings/arm/amlogic.yaml3
-rw-r--r--Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml34
-rw-r--r--Documentation/devicetree/bindings/arm/arm,integrator.yaml39
-rw-r--r--Documentation/devicetree/bindings/arm/arm,realview.yaml37
-rw-r--r--Documentation/devicetree/bindings/arm/arm,versatile.yaml40
-rw-r--r--Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml1
-rw-r--r--Documentation/devicetree/bindings/arm/atmel-at91.yaml7
-rw-r--r--Documentation/devicetree/bindings/arm/cpus.yaml5
-rw-r--r--Documentation/devicetree/bindings/arm/fsl.yaml43
-rw-r--r--Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml16
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek.yaml16
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek/mediatek,mt7622-wed.yaml1
-rw-r--r--Documentation/devicetree/bindings/arm/psci.yaml1
-rw-r--r--Documentation/devicetree/bindings/arm/qcom.yaml45
-rw-r--r--Documentation/devicetree/bindings/arm/rockchip.yaml25
-rw-r--r--Documentation/devicetree/bindings/arm/sti.yaml23
-rw-r--r--Documentation/devicetree/bindings/arm/stm32/stm32.yaml1
-rw-r--r--Documentation/devicetree/bindings/arm/sunxi.yaml16
-rw-r--r--Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml393
-rw-r--r--Documentation/devicetree/bindings/ata/nvidia,tegra-ahci.yaml2
-rw-r--r--Documentation/devicetree/bindings/cache/qcom,llcc.yaml10
-rw-r--r--Documentation/devicetree/bindings/clock/amlogic,s4-peripherals-clkc.yaml96
-rw-r--r--Documentation/devicetree/bindings/clock/amlogic,s4-pll-clkc.yaml49
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,hfpll.txt3
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml1
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm4450-gcc.yaml55
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml8
-rw-r--r--Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml1
-rw-r--r--Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml4
-rw-r--r--Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml8
-rw-r--r--Documentation/devicetree/bindings/crypto/fsl-imx-sahara.yaml43
-rw-r--r--Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml1
-rw-r--r--Documentation/devicetree/bindings/crypto/qcom,prng.yaml28
-rw-r--r--Documentation/devicetree/bindings/devfreq/event/rockchip,dfi.yaml74
-rw-r--r--Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt18
-rw-r--r--Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/bridge/analogix,anx7814.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml115
-rw-r--r--Documentation/devicetree/bindings/display/fsl,lcdif.yaml20
-rw-r--r--Documentation/devicetree/bindings/display/ilitek,ili9486.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/lvds-data-mapping.yaml84
-rw-r--r--Documentation/devicetree/bindings/display/lvds.yaml77
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/msm/dp-controller.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/msm/gmu.yaml47
-rw-r--r--Documentation/devicetree/bindings/display/msm/gpu.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,msm8998-mdss.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sc7180-mdss.yaml8
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sc7280-mdss.yaml10
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sc8280xp-mdss.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sdm845-mdss.yaml8
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm6115-mdss.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm6125-mdss.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm6350-mdss.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm6375-mdss.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8250-mdss.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml8
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.yaml8
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8550-mdss.yaml8
-rw-r--r--Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/jdi,lpm102a188a.yaml94
-rw-r--r--Documentation/devicetree/bindings/display/panel/leadtek,ltk050h3146w.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/panel/newvision,nv3051d.yaml5
-rw-r--r--Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml118
-rw-r--r--Documentation/devicetree/bindings/display/panel/panel-simple.yaml40
-rw-r--r--Documentation/devicetree/bindings/display/panel/raydium,rm692e5.yaml73
-rw-r--r--Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/renesas,shmobile-lcdc.yaml130
-rw-r--r--Documentation/devicetree/bindings/display/rockchip/rockchip,dw-mipi-dsi.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/sitronix,st7735r.yaml5
-rw-r--r--Documentation/devicetree/bindings/display/solomon,ssd-common.yaml42
-rw-r--r--Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml28
-rw-r--r--Documentation/devicetree/bindings/display/solomon,ssd132x.yaml89
-rw-r--r--Documentation/devicetree/bindings/dma/qcom,gpi.yaml2
-rw-r--r--Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dma-1.0.yaml3
-rw-r--r--Documentation/devicetree/bindings/eeprom/at24.yaml5
-rw-r--r--Documentation/devicetree/bindings/firmware/arm,scmi.yaml15
-rw-r--r--Documentation/devicetree/bindings/firmware/qcom,scm.yaml10
-rw-r--r--Documentation/devicetree/bindings/gpio/fsl-imx-gpio.yaml8
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-vf610.yaml40
-rw-r--r--Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt38
-rw-r--r--Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml73
-rw-r--r--Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml21
-rw-r--r--Documentation/devicetree/bindings/hwmon/adi,ltc2991.yaml128
-rw-r--r--Documentation/devicetree/bindings/hwmon/adi,max31827.yaml66
-rw-r--r--Documentation/devicetree/bindings/hwmon/ina3221.txt54
-rw-r--r--Documentation/devicetree/bindings/hwmon/npcm750-pwm-fan.txt6
-rw-r--r--Documentation/devicetree/bindings/hwmon/pmbus/infineon,tda38640.yaml49
-rw-r--r--Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml1
-rw-r--r--Documentation/devicetree/bindings/hwmon/ti,ina3221.yaml121
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt135
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml172
-rw-r--r--Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml2
-rw-r--r--Documentation/devicetree/bindings/i3c/i3c.yaml10
-rw-r--r--Documentation/devicetree/bindings/iio/accel/kionix,kx022a.yaml14
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml20
-rw-r--r--Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml205
-rw-r--r--Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml6
-rw-r--r--Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml3
-rw-r--r--Documentation/devicetree/bindings/iio/adc/ti,twl6030-gpadc.yaml43
-rw-r--r--Documentation/devicetree/bindings/iio/addac/adi,ad74115.yaml3
-rw-r--r--Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml12
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5758.yaml3
-rw-r--r--Documentation/devicetree/bindings/iio/health/ti,afe4403.yaml3
-rw-r--r--Documentation/devicetree/bindings/iio/health/ti,afe4404.yaml3
-rw-r--r--Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml5
-rw-r--r--Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml3
-rw-r--r--Documentation/devicetree/bindings/iio/light/rohm,bu27010.yaml1
-rw-r--r--Documentation/devicetree/bindings/iio/pressure/rohm,bm1390.yaml52
-rw-r--r--Documentation/devicetree/bindings/iio/resolver/adi,ad2s1210.yaml177
-rw-r--r--Documentation/devicetree/bindings/input/fsl,scu-key.yaml2
-rw-r--r--Documentation/devicetree/bindings/input/qcom,pm8921-keypad.yaml89
-rw-r--r--Documentation/devicetree/bindings/input/qcom,pm8xxx-keypad.txt90
-rw-r--r--Documentation/devicetree/bindings/input/syna,rmi4.yaml2
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml3
-rw-r--r--Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt2
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,msm8939.yaml74
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,msm8996.yaml126
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,qcm2290.yaml60
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,rpm-common.yaml28
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml250
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml1
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,sdm660.yaml108
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,sdx75-rpmh.yaml92
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/qcom,mpm.yaml4
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml1
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml2
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-mswi.yaml43
-rw-r--r--Documentation/devicetree/bindings/iommu/arm,smmu.yaml2
-rw-r--r--Documentation/devicetree/bindings/leds/backlight/common.yaml17
-rw-r--r--Documentation/devicetree/bindings/leds/backlight/led-backlight.yaml19
-rw-r--r--Documentation/devicetree/bindings/leds/backlight/max8925-backlight.txt10
-rw-r--r--Documentation/devicetree/bindings/leds/backlight/mps,mp3309c.yaml73
-rw-r--r--Documentation/devicetree/bindings/leds/backlight/pwm-backlight.yaml20
-rw-r--r--Documentation/devicetree/bindings/leds/common.yaml4
-rw-r--r--Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml5
-rw-r--r--Documentation/devicetree/bindings/leds/kinetic,ktd202x.yaml171
-rw-r--r--Documentation/devicetree/bindings/leds/register-bit-led.yaml2
-rw-r--r--Documentation/devicetree/bindings/mailbox/fsl,mu.yaml5
-rw-r--r--Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml2
-rw-r--r--Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml1
-rw-r--r--Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml6
-rw-r--r--Documentation/devicetree/bindings/media/amlogic,meson6-ir.yaml1
-rw-r--r--Documentation/devicetree/bindings/media/cdns,csi2rx.yaml1
-rw-r--r--Documentation/devicetree/bindings/media/i2c/hynix,hi846.yaml7
-rw-r--r--Documentation/devicetree/bindings/media/i2c/onnn,mt9m114.yaml114
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml8
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml6
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov5640.yaml7
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov5642.yaml141
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov5693.yaml2
-rw-r--r--Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml2
-rw-r--r--Documentation/devicetree/bindings/media/i2c/sony,imx415.yaml10
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml1
-rw-r--r--Documentation/devicetree/bindings/media/nokia,n900-ir20
-rw-r--r--Documentation/devicetree/bindings/media/nuvoton,npcm-ece.yaml43
-rw-r--r--Documentation/devicetree/bindings/media/nuvoton,npcm-vcd.yaml72
-rw-r--r--Documentation/devicetree/bindings/media/qcom,sdm845-venus-v2.yaml8
-rw-r--r--Documentation/devicetree/bindings/media/rockchip-vpu.yaml7
-rw-r--r--Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml15
-rw-r--r--Documentation/devicetree/bindings/media/samsung,fimc.yaml27
-rw-r--r--Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml100
-rw-r--r--Documentation/devicetree/bindings/media/video-interfaces.yaml1
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/ingenic,nemc.yaml1
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml2
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/rockchip,rk3399-dmc.yaml2
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml2
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/xlnx,versal-ddrmc-edac.yaml57
-rw-r--r--Documentation/devicetree/bindings/mfd/arm,dev-platforms-syscon.yaml67
-rw-r--r--Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml18
-rw-r--r--Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/max8925.txt64
-rw-r--r--Documentation/devicetree/bindings/mfd/max8998.txt125
-rw-r--r--Documentation/devicetree/bindings/mfd/maxim,max5970.yaml5
-rw-r--r--Documentation/devicetree/bindings/mfd/maxim,max8925.yaml145
-rw-r--r--Documentation/devicetree/bindings/mfd/maxim,max8998.yaml324
-rw-r--r--Documentation/devicetree/bindings/mfd/mediatek,mt6357.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/mt6397.txt4
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml11
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml1
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml26
-rw-r--r--Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml4
-rw-r--r--Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml4
-rw-r--r--Documentation/devicetree/bindings/mfd/rockchip,rk809.yaml6
-rw-r--r--Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml3
-rw-r--r--Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml4
-rw-r--r--Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/syscon.yaml4
-rw-r--r--Documentation/devicetree/bindings/mfd/ti,lp87524-q1.yaml1
-rw-r--r--Documentation/devicetree/bindings/mfd/ti,lp87561-q1.yaml1
-rw-r--r--Documentation/devicetree/bindings/mfd/ti,lp87565-q1.yaml1
-rw-r--r--Documentation/devicetree/bindings/mfd/ti,twl.yaml67
-rw-r--r--Documentation/devicetree/bindings/mfd/twl-family.txt46
-rw-r--r--Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml5
-rw-r--r--Documentation/devicetree/bindings/mmc/npcm,sdhci.yaml45
-rw-r--r--Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml2
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-msm.yaml11
-rw-r--r--Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/mtd.yaml7
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml19
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml1
-rw-r--r--Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/brcm,asp-v2.0.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/dsa/brcm,sf2.yaml1
-rw-r--r--Documentation/devicetree/bindings/net/dsa/dsa.yaml11
-rw-r--r--Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml10
-rw-r--r--Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml22
-rw-r--r--Documentation/devicetree/bindings/net/dsa/microchip,lan937x.yaml3
-rw-r--r--Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml4
-rw-r--r--Documentation/devicetree/bindings/net/dsa/qca8k.yaml1
-rw-r--r--Documentation/devicetree/bindings/net/dsa/realtek.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/dsa/renesas,rzn1-a5psw.yaml10
-rw-r--r--Documentation/devicetree/bindings/net/engleder,tsnep.yaml1
-rw-r--r--Documentation/devicetree/bindings/net/ethernet-controller.yaml4
-rw-r--r--Documentation/devicetree/bindings/net/ethernet-switch.yaml14
-rw-r--r--Documentation/devicetree/bindings/net/fsl,fec.yaml1
-rw-r--r--Documentation/devicetree/bindings/net/loongson,ls1b-gmac.yaml114
-rw-r--r--Documentation/devicetree/bindings/net/loongson,ls1c-emac.yaml113
-rw-r--r--Documentation/devicetree/bindings/net/microchip,lan95xx.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/mscc,vsc7514-switch.yaml46
-rw-r--r--Documentation/devicetree/bindings/net/nxp,tja11xx.yaml1
-rw-r--r--Documentation/devicetree/bindings/net/renesas,ether.yaml3
-rw-r--r--Documentation/devicetree/bindings/net/renesas,etheravb.yaml3
-rw-r--r--Documentation/devicetree/bindings/net/snps,dwmac.yaml5
-rw-r--r--Documentation/devicetree/bindings/net/ti,cc1352p7.yaml51
-rw-r--r--Documentation/devicetree/bindings/net/ti,cpsw-switch.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml8
-rw-r--r--Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml5
-rw-r--r--Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/amlogic,meson6-efuse.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/apple,efuses.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/nvmem-deprecated-cells.yaml28
-rw-r--r--Documentation/devicetree/bindings/nvmem/nvmem.yaml9
-rw-r--r--Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/qcom,sec-qfprom.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/u-boot,env.yaml2
-rw-r--r--Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml36
-rw-r--r--Documentation/devicetree/bindings/pci/rcar-gen4-pci-ep.yaml115
-rw-r--r--Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml127
-rw-r--r--Documentation/devicetree/bindings/pci/snps,dw-pcie-common.yaml4
-rw-r--r--Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml4
-rw-r--r--Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml4
-rw-r--r--Documentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml2
-rw-r--r--Documentation/devicetree/bindings/pci/xlnx,xdma-host.yaml114
-rw-r--r--Documentation/devicetree/bindings/perf/riscv,pmu.yaml2
-rw-r--r--Documentation/devicetree/bindings/phy/marvell,pxa1928-usb-phy.yaml47
-rw-r--r--Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml1
-rw-r--r--Documentation/devicetree/bindings/phy/mediatek,mt7628-usbphy.yaml74
-rw-r--r--Documentation/devicetree/bindings/phy/phy-stih407-usb.txt24
-rw-r--r--Documentation/devicetree/bindings/phy/pxa1928-usb-phy.txt18
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,ipq5332-usb-hsphy.yaml4
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml2
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-usb3-phy.yaml287
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml2
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml57
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml7
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,snps-eusb2-repeater.yaml21
-rw-r--r--Documentation/devicetree/bindings/phy/ralink-usb-phy.txt23
-rw-r--r--Documentation/devicetree/bindings/phy/st,stih407-usb2-phy.yaml63
-rw-r--r--Documentation/devicetree/bindings/pinctrl/amlogic,meson-pinctrl-a1.yaml1
-rw-r--r--Documentation/devicetree/bindings/pinctrl/brcm,bcm6318-pinctrl.yaml5
-rw-r--r--Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.yaml25
-rw-r--r--Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.yaml5
-rw-r--r--Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.yaml5
-rw-r--r--Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.yaml7
-rw-r--r--Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.yaml7
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nuvoton,npcm845-pinctrl.yaml217
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nxp,s32g2-siul2-pinctrl.yaml2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-tlmm.yaml3
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8226-pinctrl.yaml4
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sa8775p-tlmm.yaml1
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml4
-rw-r--r--Documentation/devicetree/bindings/pinctrl/realtek,rtd1315e-pinctrl.yaml188
-rw-r--r--Documentation/devicetree/bindings/pinctrl/realtek,rtd1319d-pinctrl.yaml187
-rw-r--r--Documentation/devicetree/bindings/pinctrl/realtek,rtd1619b-pinctrl.yaml186
-rw-r--r--Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml21
-rw-r--r--Documentation/devicetree/bindings/pinctrl/renesas,rzv2m-pinctrl.yaml1
-rw-r--r--Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml3
-rw-r--r--Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml3
-rw-r--r--Documentation/devicetree/bindings/power/mediatek,power-controller.yaml6
-rw-r--r--Documentation/devicetree/bindings/power/power-domain.yaml17
-rw-r--r--Documentation/devicetree/bindings/power/qcom,rpmpd.yaml82
-rw-r--r--Documentation/devicetree/bindings/power/reset/gpio-poweroff.yaml6
-rw-r--r--Documentation/devicetree/bindings/power/reset/syscon-poweroff.yaml10
-rw-r--r--Documentation/devicetree/bindings/power/supply/max8925_battery.txt18
-rw-r--r--Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml31
-rw-r--r--Documentation/devicetree/bindings/power/supply/mitsumi,mm8013.yaml38
-rw-r--r--Documentation/devicetree/bindings/power/supply/qcom,pm8916-bms-vm.yaml83
-rw-r--r--Documentation/devicetree/bindings/power/supply/qcom,pm8916-lbc.yaml128
-rw-r--r--Documentation/devicetree/bindings/power/supply/sbs,sbs-manager.yaml6
-rw-r--r--Documentation/devicetree/bindings/power/supply/stericsson,ab8500-battery.txt34
-rw-r--r--Documentation/devicetree/bindings/pwm/imx-pwm.yaml10
-rw-r--r--Documentation/devicetree/bindings/pwm/mxs-pwm.yaml13
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml1
-rw-r--r--Documentation/devicetree/bindings/regulator/adi,max77503-regulator.yaml50
-rw-r--r--Documentation/devicetree/bindings/regulator/da9210.txt29
-rw-r--r--Documentation/devicetree/bindings/regulator/dlg,da9210.yaml52
-rw-r--r--Documentation/devicetree/bindings/regulator/fixed-regulator.yaml5
-rw-r--r--Documentation/devicetree/bindings/regulator/maxim,max20086.yaml1
-rw-r--r--Documentation/devicetree/bindings/regulator/maxim,max77826.yaml2
-rw-r--r--Documentation/devicetree/bindings/regulator/mediatek,mt6358-regulator.yaml250
-rw-r--r--Documentation/devicetree/bindings/regulator/mps,mpq2286.yaml59
-rw-r--r--Documentation/devicetree/bindings/regulator/mt6358-regulator.txt350
-rw-r--r--Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml2
-rw-r--r--Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml12
-rw-r--r--Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.yaml68
-rw-r--r--Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml176
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml20
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,msm8996-mss-pil.yaml2
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml81
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml145
-rw-r--r--Documentation/devicetree/bindings/remoteproc/renesas,rcar-rproc.yaml2
-rw-r--r--Documentation/devicetree/bindings/remoteproc/ti,pru-rproc.yaml23
-rw-r--r--Documentation/devicetree/bindings/reserved-memory/framebuffer.yaml52
-rw-r--r--Documentation/devicetree/bindings/reserved-memory/memory-region.yaml40
-rw-r--r--Documentation/devicetree/bindings/reserved-memory/qcom,rmtfs-mem.yaml11
-rw-r--r--Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt2
-rw-r--r--Documentation/devicetree/bindings/reserved-memory/reserved-memory.yaml181
-rw-r--r--Documentation/devicetree/bindings/reserved-memory/shared-dma-pool.yaml97
-rw-r--r--Documentation/devicetree/bindings/riscv/cpus.yaml1
-rw-r--r--Documentation/devicetree/bindings/riscv/extensions.yaml12
-rw-r--r--Documentation/devicetree/bindings/riscv/sophgo.yaml32
-rw-r--r--Documentation/devicetree/bindings/rng/amlogic,meson-rng.yaml1
-rw-r--r--Documentation/devicetree/bindings/rng/st,stm32-rng.yaml20
-rw-r--r--Documentation/devicetree/bindings/rtc/amlogic,meson6-rtc.yaml1
-rw-r--r--Documentation/devicetree/bindings/rtc/cirrus,ep9301-rtc.yaml42
-rw-r--r--Documentation/devicetree/bindings/rtc/epson,rtc7301.txt16
-rw-r--r--Documentation/devicetree/bindings/rtc/epson,rtc7301.yaml51
-rw-r--r--Documentation/devicetree/bindings/rtc/maxim,mcp795.txt11
-rw-r--r--Documentation/devicetree/bindings/rtc/microcrystal,rv3032.yaml2
-rw-r--r--Documentation/devicetree/bindings/rtc/mstar,ssd202d-rtc.yaml35
-rw-r--r--Documentation/devicetree/bindings/rtc/nxp,pcf2123.yaml47
-rw-r--r--Documentation/devicetree/bindings/rtc/nxp,pcf8523.txt18
-rw-r--r--Documentation/devicetree/bindings/rtc/nxp,pcf8523.yaml45
-rw-r--r--Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt17
-rw-r--r--Documentation/devicetree/bindings/rtc/trivial-rtc.yaml2
-rw-r--r--Documentation/devicetree/bindings/serial/esp,esp32-acm.yaml42
-rw-r--r--Documentation/devicetree/bindings/serial/esp,esp32-uart.yaml51
-rw-r--r--Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml2
-rw-r--r--Documentation/devicetree/bindings/serial/fsl-mxs-auart.yaml13
-rw-r--r--Documentation/devicetree/bindings/serial/maxim,max310x.txt48
-rw-r--r--Documentation/devicetree/bindings/serial/maxim,max310x.yaml74
-rw-r--r--Documentation/devicetree/bindings/serial/nvidia,tegra20-hsuart.yaml10
-rw-r--r--Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt118
-rw-r--r--Documentation/devicetree/bindings/serial/nxp,sc16is7xx.yaml127
-rw-r--r--Documentation/devicetree/bindings/serial/qcom,msm-uart.yaml4
-rw-r--r--Documentation/devicetree/bindings/serial/qcom,msm-uartdm.yaml4
-rw-r--r--Documentation/devicetree/bindings/serial/renesas,em-uart.yaml14
-rw-r--r--Documentation/devicetree/bindings/serial/renesas,hscif.yaml4
-rw-r--r--Documentation/devicetree/bindings/serial/renesas,scif.yaml1
-rw-r--r--Documentation/devicetree/bindings/serial/renesas,scifa.yaml4
-rw-r--r--Documentation/devicetree/bindings/serial/renesas,scifb.yaml4
-rw-r--r--Documentation/devicetree/bindings/serial/rs485.yaml4
-rw-r--r--Documentation/devicetree/bindings/serial/samsung_uart.yaml8
-rw-r--r--Documentation/devicetree/bindings/serial/serial.yaml18
-rw-r--r--Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml37
-rw-r--r--Documentation/devicetree/bindings/soc/mediatek/mediatek,mt7986-wo-ccif.yaml1
-rw-r--r--Documentation/devicetree/bindings/soc/mediatek/mtk-svs.yaml1
-rw-r--r--Documentation/devicetree/bindings/soc/nuvoton/nuvoton,gfxi.yaml39
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml2
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml19
-rw-r--r--Documentation/devicetree/bindings/soc/renesas/renesas,rzg2l-sysc.yaml1
-rw-r--r--Documentation/devicetree/bindings/soc/renesas/renesas.yaml28
-rw-r--r--Documentation/devicetree/bindings/soc/rockchip/grf.yaml1
-rw-r--r--Documentation/devicetree/bindings/soc/sti/st,sti-syscon.yaml46
-rw-r--r--Documentation/devicetree/bindings/soc/tegra/nvidia,tegra20-pmc.yaml416
-rw-r--r--Documentation/devicetree/bindings/sound/audio-graph-port.yaml20
-rw-r--r--Documentation/devicetree/bindings/sound/audio-graph.yaml9
-rw-r--r--Documentation/devicetree/bindings/sound/awinic,aw87390.yaml58
-rw-r--r--Documentation/devicetree/bindings/sound/awinic,aw88395.yaml33
-rw-r--r--Documentation/devicetree/bindings/sound/cirrus,cs42l43.yaml6
-rw-r--r--Documentation/devicetree/bindings/sound/dai-params.yaml11
-rw-r--r--Documentation/devicetree/bindings/sound/dialog,da7219.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/mediatek,mt8188-afe.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/nxp,tfa9879.yaml44
-rw-r--r--Documentation/devicetree/bindings/sound/pcm512x.txt9
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml18
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,sm8250.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/realtek,rt5616.yaml49
-rw-r--r--Documentation/devicetree/bindings/sound/richtek,rtq9128.yaml61
-rw-r--r--Documentation/devicetree/bindings/sound/rt5616.txt32
-rw-r--r--Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml76
-rw-r--r--Documentation/devicetree/bindings/sound/tas5805m.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/tfa9879.txt23
-rw-r--r--Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/wm8782.txt7
-rw-r--r--Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml16
-rw-r--r--Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml2
-rw-r--r--Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml2
-rw-r--r--Documentation/devicetree/bindings/spi/arm,pl022-peripheral-props.yaml61
-rw-r--r--Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml1
-rw-r--r--Documentation/devicetree/bindings/spi/qcom,spi-qup.yaml13
-rw-r--r--Documentation/devicetree/bindings/spi/renesas,rzv2m-csi.yaml9
-rw-r--r--Documentation/devicetree/bindings/spi/rockchip-sfc.yaml2
-rw-r--r--Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml2
-rw-r--r--Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml6
-rw-r--r--Documentation/devicetree/bindings/spi/spi-pl022.yaml51
-rw-r--r--Documentation/devicetree/bindings/spi/st,stm32-spi.yaml20
-rw-r--r--Documentation/devicetree/bindings/thermal/fsl,scu-thermal.yaml4
-rw-r--r--Documentation/devicetree/bindings/thermal/imx-thermal.yaml7
-rw-r--r--Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml1
-rw-r--r--Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.yaml5
-rw-r--r--Documentation/devicetree/bindings/thermal/qcom-tsens.yaml1
-rw-r--r--Documentation/devicetree/bindings/thermal/thermal-zones.yaml2
-rw-r--r--Documentation/devicetree/bindings/timer/cirrus,ep9301-timer.yaml49
-rw-r--r--Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml31
-rw-r--r--Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml67
-rw-r--r--Documentation/devicetree/bindings/timer/sifive,clint.yaml1
-rw-r--r--Documentation/devicetree/bindings/timer/thead,c900-aclint-mtimer.yaml43
-rw-r--r--Documentation/devicetree/bindings/trivial-devices.yaml6
-rw-r--r--Documentation/devicetree/bindings/ufs/qcom,ufs.yaml2
-rw-r--r--Documentation/devicetree/bindings/ufs/ufs-common.yaml35
-rw-r--r--Documentation/devicetree/bindings/usb/ci-hdrc-usb2.yaml7
-rw-r--r--Documentation/devicetree/bindings/usb/fcs,fsa4480.yaml43
-rw-r--r--Documentation/devicetree/bindings/usb/genesys,gl850g.yaml3
-rw-r--r--Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml2
-rw-r--r--Documentation/devicetree/bindings/usb/microchip,usb5744.yaml7
-rw-r--r--Documentation/devicetree/bindings/usb/nxp,ptn36502.yaml94
-rw-r--r--Documentation/devicetree/bindings/usb/qcom,dwc3.yaml11
-rw-r--r--Documentation/devicetree/bindings/usb/realtek,rtd-dwc3.yaml80
-rw-r--r--Documentation/devicetree/bindings/usb/realtek,rtd-type-c.yaml82
-rw-r--r--Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml62
-rw-r--r--Documentation/devicetree/bindings/usb/snps,dwc3.yaml56
-rw-r--r--Documentation/devicetree/bindings/usb/ti,tps6598x.yaml86
-rw-r--r--Documentation/devicetree/bindings/usb/usb-hcd.yaml2
-rw-r--r--Documentation/devicetree/bindings/usb/vialab,vl817.yaml1
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.yaml28
-rw-r--r--Documentation/devicetree/bindings/watchdog/amlogic,meson-gxbb-wdt.yaml12
-rw-r--r--Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt18
-rw-r--r--Documentation/devicetree/bindings/watchdog/atmel,at91rm9200-wdt.yaml33
-rw-r--r--Documentation/devicetree/bindings/watchdog/atmel-at91rm9200-wdt.txt9
-rw-r--r--Documentation/devicetree/bindings/watchdog/cnxt,cx92755-wdt.yaml45
-rw-r--r--Documentation/devicetree/bindings/watchdog/da9062-wdt.txt34
-rw-r--r--Documentation/devicetree/bindings/watchdog/digicolor-wdt.txt25
-rw-r--r--Documentation/devicetree/bindings/watchdog/dlg,da9062-watchdog.yaml50
-rw-r--r--Documentation/devicetree/bindings/watchdog/fsl,scu-wdt.yaml4
-rw-r--r--Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml5
-rw-r--r--Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml2
-rw-r--r--Documentation/devicetree/bindings/writing-schema.rst5
-rw-r--r--Documentation/doc-guide/contributing.rst4
-rw-r--r--Documentation/driver-api/80211/mac80211.rst2
-rw-r--r--Documentation/driver-api/dma-buf.rst32
-rw-r--r--Documentation/driver-api/dpll.rst551
-rw-r--r--Documentation/driver-api/driver-model/devres.rst14
-rw-r--r--Documentation/driver-api/gpio/consumer.rst4
-rw-r--r--Documentation/driver-api/i3c/protocol.rst4
-rw-r--r--Documentation/driver-api/index.rst1
-rw-r--r--Documentation/driver-api/media/camera-sensor.rst192
-rw-r--r--Documentation/driver-api/media/drivers/ccs/ccs.rst10
-rw-r--r--Documentation/driver-api/media/v4l2-core.rst1
-rw-r--r--Documentation/driver-api/media/v4l2-dev.rst8
-rw-r--r--Documentation/driver-api/media/v4l2-videobuf.rst403
-rw-r--r--Documentation/driver-api/pps.rst16
-rw-r--r--Documentation/driver-api/pwm.rst6
-rw-r--r--Documentation/driver-api/thermal/intel_dptf.rst64
-rw-r--r--Documentation/driver-api/tty/index.rst1
-rw-r--r--Documentation/driver-api/tty/tty_ioctl.rst10
-rw-r--r--Documentation/driver-api/usb/dma.rst48
-rw-r--r--Documentation/features/core/cBPF-JIT/arch-support.txt1
-rw-r--r--Documentation/features/core/eBPF-JIT/arch-support.txt1
-rw-r--r--Documentation/features/core/generic-idle-thread/arch-support.txt1
-rw-r--r--Documentation/features/core/jump-labels/arch-support.txt1
-rw-r--r--Documentation/features/core/thread-info-in-task/arch-support.txt1
-rw-r--r--Documentation/features/core/tracehook/arch-support.txt1
-rw-r--r--Documentation/features/debug/KASAN/arch-support.txt1
-rw-r--r--Documentation/features/debug/debug-vm-pgtable/arch-support.txt1
-rw-r--r--Documentation/features/debug/gcov-profile-all/arch-support.txt1
-rw-r--r--Documentation/features/debug/kcov/arch-support.txt1
-rw-r--r--Documentation/features/debug/kgdb/arch-support.txt1
-rw-r--r--Documentation/features/debug/kmemleak/arch-support.txt1
-rw-r--r--Documentation/features/debug/kprobes-on-ftrace/arch-support.txt1
-rw-r--r--Documentation/features/debug/kprobes/arch-support.txt1
-rw-r--r--Documentation/features/debug/kretprobes/arch-support.txt1
-rw-r--r--Documentation/features/debug/optprobes/arch-support.txt1
-rw-r--r--Documentation/features/debug/stackprotector/arch-support.txt1
-rw-r--r--Documentation/features/debug/uprobes/arch-support.txt1
-rw-r--r--Documentation/features/debug/user-ret-profiler/arch-support.txt1
-rw-r--r--Documentation/features/io/dma-contiguous/arch-support.txt1
-rw-r--r--Documentation/features/locking/cmpxchg-local/arch-support.txt1
-rw-r--r--Documentation/features/locking/lockdep/arch-support.txt1
-rw-r--r--Documentation/features/locking/queued-rwlocks/arch-support.txt1
-rw-r--r--Documentation/features/locking/queued-spinlocks/arch-support.txt1
-rw-r--r--Documentation/features/perf/kprobes-event/arch-support.txt1
-rw-r--r--Documentation/features/perf/perf-regs/arch-support.txt1
-rw-r--r--Documentation/features/perf/perf-stackdump/arch-support.txt1
-rw-r--r--Documentation/features/sched/membarrier-sync-core/arch-support.txt1
-rw-r--r--Documentation/features/sched/numa-balancing/arch-support.txt1
-rw-r--r--Documentation/features/seccomp/seccomp-filter/arch-support.txt1
-rw-r--r--Documentation/features/time/arch-tick-broadcast/arch-support.txt1
-rw-r--r--Documentation/features/time/clockevents/arch-support.txt1
-rw-r--r--Documentation/features/time/context-tracking/arch-support.txt1
-rw-r--r--Documentation/features/time/irq-time-acct/arch-support.txt1
-rw-r--r--Documentation/features/time/virt-cpuacct/arch-support.txt1
-rw-r--r--Documentation/features/vm/ELF-ASLR/arch-support.txt1
-rw-r--r--Documentation/features/vm/PG_uncached/arch-support.txt1
-rw-r--r--Documentation/features/vm/THP/arch-support.txt1
-rw-r--r--Documentation/features/vm/TLB/arch-support.txt1
-rw-r--r--Documentation/features/vm/huge-vmap/arch-support.txt1
-rw-r--r--Documentation/features/vm/ioremap_prot/arch-support.txt1
-rw-r--r--Documentation/features/vm/pte_special/arch-support.txt1
-rw-r--r--Documentation/filesystems/erofs.rst6
-rw-r--r--Documentation/filesystems/files.rst53
-rw-r--r--Documentation/filesystems/fscrypt.rst121
-rw-r--r--Documentation/filesystems/fuse-io.rst3
-rw-r--r--Documentation/filesystems/nfs/exporting.rst14
-rw-r--r--Documentation/filesystems/overlayfs.rst46
-rw-r--r--Documentation/filesystems/porting.rst16
-rw-r--r--Documentation/filesystems/proc.rst8
-rw-r--r--Documentation/filesystems/xfs-online-fsck-design.rst2
-rw-r--r--Documentation/firmware-guide/acpi/enumeration.rst43
-rw-r--r--Documentation/gpu/amdgpu/driver-misc.rst18
-rw-r--r--Documentation/gpu/amdgpu/thermal.rst30
-rw-r--r--Documentation/gpu/automated_testing.rst20
-rw-r--r--Documentation/gpu/drivers.rst1
-rw-r--r--Documentation/gpu/drm-kms.rst2
-rw-r--r--Documentation/gpu/drm-mm.rst20
-rw-r--r--Documentation/gpu/drm-uapi.rst92
-rw-r--r--Documentation/gpu/drm-usage-stats.rst1
-rw-r--r--Documentation/gpu/drm-vm-bind-async.rst309
-rw-r--r--Documentation/gpu/i915.rst29
-rw-r--r--Documentation/gpu/implementation_guidelines.rst9
-rw-r--r--Documentation/gpu/index.rst1
-rw-r--r--Documentation/gpu/panfrost.rst40
-rw-r--r--Documentation/gpu/rfc/xe.rst93
-rw-r--r--Documentation/hwmon/adt7475.rst3
-rw-r--r--Documentation/hwmon/aquacomputer_d5next.rst7
-rw-r--r--Documentation/hwmon/asus_ec_sensors.rst1
-rw-r--r--Documentation/hwmon/index.rst2
-rw-r--r--Documentation/hwmon/ltc2991.rst43
-rw-r--r--Documentation/hwmon/max31827.rst4
-rw-r--r--Documentation/hwmon/nct6683.rst1
-rw-r--r--Documentation/hwmon/powerz.rst30
-rw-r--r--Documentation/hwmon/sch5627.rst10
-rw-r--r--Documentation/i2c/busses/i2c-i801.rst1
-rw-r--r--Documentation/i2c/fault-codes.rst4
-rw-r--r--Documentation/kbuild/kbuild.rst6
-rw-r--r--Documentation/kbuild/makefiles.rst13
-rw-r--r--Documentation/maintainer/maintainer-entry-profile.rst2
-rw-r--r--Documentation/memory-barriers.txt7
-rw-r--r--Documentation/misc-devices/eeprom.rst107
-rw-r--r--Documentation/misc-devices/index.rst1
-rw-r--r--Documentation/mm/damon/design.rst26
-rw-r--r--Documentation/mm/overcommit-accounting.rst3
-rw-r--r--Documentation/mm/page_tables.rst127
-rw-r--r--Documentation/mm/vmemmap_dedup.rst2
-rw-r--r--Documentation/netlink/genetlink-c.yaml45
-rw-r--r--Documentation/netlink/genetlink-legacy.yaml51
-rw-r--r--Documentation/netlink/genetlink.yaml39
-rw-r--r--Documentation/netlink/netlink-raw.yaml23
-rw-r--r--Documentation/netlink/specs/devlink.yaml1580
-rw-r--r--Documentation/netlink/specs/dpll.yaml510
-rw-r--r--Documentation/netlink/specs/ethtool.yaml3
-rw-r--r--Documentation/netlink/specs/handshake.yaml8
-rw-r--r--Documentation/netlink/specs/mptcp.yaml393
-rw-r--r--Documentation/netlink/specs/netdev.yaml21
-rw-r--r--Documentation/netlink/specs/nfsd.yaml89
-rw-r--r--Documentation/networking/device_drivers/appletalk/cops.rst80
-rw-r--r--Documentation/networking/device_drivers/appletalk/index.rst18
-rw-r--r--Documentation/networking/device_drivers/ethernet/index.rst1
-rw-r--r--Documentation/networking/device_drivers/ethernet/intel/idpf.rst160
-rw-r--r--Documentation/networking/device_drivers/ethernet/mellanox/mlx5/kconfig.rst2
-rw-r--r--Documentation/networking/device_drivers/ethernet/neterion/s2io.rst4
-rw-r--r--Documentation/networking/device_drivers/index.rst2
-rw-r--r--Documentation/networking/device_drivers/qlogic/index.rst18
-rw-r--r--Documentation/networking/device_drivers/qlogic/qlge.rst118
-rw-r--r--Documentation/networking/devlink/i40e.rst59
-rw-r--r--Documentation/networking/devlink/index.rst29
-rw-r--r--Documentation/networking/dsa/b53.rst14
-rw-r--r--Documentation/networking/dsa/bcm_sf2.rst2
-rw-r--r--Documentation/networking/dsa/configuration.rst102
-rw-r--r--Documentation/networking/dsa/dsa.rst162
-rw-r--r--Documentation/networking/dsa/lan9303.rst2
-rw-r--r--Documentation/networking/dsa/sja1105.rst6
-rw-r--r--Documentation/networking/filter.rst4
-rw-r--r--Documentation/networking/index.rst2
-rw-r--r--Documentation/networking/ip-sysctl.rst41
-rw-r--r--Documentation/networking/ipddp.rst78
-rw-r--r--Documentation/networking/mptcp-sysctl.rst11
-rw-r--r--Documentation/networking/msg_zerocopy.rst13
-rw-r--r--Documentation/networking/netconsole.rst22
-rw-r--r--Documentation/networking/page_pool.rst4
-rw-r--r--Documentation/networking/pktgen.rst12
-rw-r--r--Documentation/networking/representors.rst8
-rw-r--r--Documentation/networking/scaling.rst42
-rw-r--r--Documentation/networking/sfp-phylink.rst10
-rw-r--r--Documentation/networking/smc-sysctl.rst6
-rw-r--r--Documentation/networking/tcp_ao.rst444
-rw-r--r--Documentation/networking/xdp-rx-metadata.rst7
-rw-r--r--Documentation/process/7.AdvancedTopics.rst18
-rw-r--r--Documentation/process/backporting.rst604
-rw-r--r--Documentation/process/changes.rst2
-rw-r--r--Documentation/process/embargoed-hardware-issues.rst19
-rw-r--r--Documentation/process/index.rst3
-rw-r--r--Documentation/process/maintainer-netdev.rst35
-rw-r--r--Documentation/process/security-bugs.rst35
-rw-r--r--Documentation/process/stable-kernel-rules.rst13
-rw-r--r--Documentation/process/submitting-patches.rst10
-rw-r--r--Documentation/rust/general-information.rst2
-rw-r--r--Documentation/rust/index.rst19
-rw-r--r--Documentation/scheduler/sched-arch.rst4
-rw-r--r--Documentation/scheduler/sched-capacity.rst13
-rw-r--r--Documentation/scheduler/sched-energy.rst29
-rw-r--r--Documentation/scheduler/sched-rt-group.rst40
-rw-r--r--Documentation/security/index.rst1
-rw-r--r--Documentation/security/snp-tdx-threat-model.rst253
-rw-r--r--Documentation/sound/soc/codec-to-codec.rst8
-rw-r--r--Documentation/sound/soc/dpcm.rst3
-rw-r--r--Documentation/sphinx/cdomain.py4
-rw-r--r--Documentation/sphinx/kernel_abi.py2
-rw-r--r--Documentation/sphinx/kernel_feat.py2
-rw-r--r--Documentation/sphinx/kerneldoc.py4
-rw-r--r--Documentation/sphinx/kfigure.py2
-rwxr-xr-xDocumentation/sphinx/maintainers_include.py8
-rw-r--r--Documentation/subsystem-apis.rst2
-rw-r--r--Documentation/trace/coresight/coresight.rst2
-rw-r--r--Documentation/trace/fprobe.rst8
-rw-r--r--Documentation/trace/fprobetrace.rst8
-rw-r--r--Documentation/trace/kprobes.rst1
-rw-r--r--Documentation/trace/kprobetrace.rst8
-rw-r--r--Documentation/trace/postprocess/trace-vmscan-postprocess.pl42
-rw-r--r--Documentation/trace/user_events.rst21
-rw-r--r--Documentation/translations/it_IT/riscv/patch-acceptance.rst2
-rw-r--r--Documentation/translations/sp_SP/process/embargoed-hardware-issues.rst341
-rw-r--r--Documentation/translations/sp_SP/process/index.rst2
-rw-r--r--Documentation/translations/sp_SP/process/security-bugs.rst103
-rw-r--r--Documentation/translations/zh_CN/arch/index.rst3
-rw-r--r--Documentation/translations/zh_CN/arch/loongarch/introduction.rst4
-rw-r--r--Documentation/translations/zh_CN/arch/riscv/boot-image-header.rst (renamed from Documentation/translations/zh_CN/riscv/boot-image-header.rst)4
-rw-r--r--Documentation/translations/zh_CN/arch/riscv/index.rst (renamed from Documentation/translations/zh_CN/riscv/index.rst)4
-rw-r--r--Documentation/translations/zh_CN/arch/riscv/patch-acceptance.rst (renamed from Documentation/translations/zh_CN/riscv/patch-acceptance.rst)4
-rw-r--r--Documentation/translations/zh_CN/arch/riscv/vm-layout.rst (renamed from Documentation/translations/zh_CN/riscv/vm-layout.rst)4
-rw-r--r--Documentation/translations/zh_CN/core-api/cpu_hotplug.rst6
-rw-r--r--Documentation/translations/zh_CN/core-api/workqueue.rst2
-rw-r--r--Documentation/translations/zh_CN/index.rst5
-rw-r--r--Documentation/translations/zh_CN/maintainer/maintainer-entry-profile.rst2
-rw-r--r--Documentation/translations/zh_CN/scheduler/sched-arch.rst5
-rw-r--r--Documentation/translations/zh_CN/subsystem-apis.rst110
-rw-r--r--Documentation/translations/zh_CN/video4linux/v4l2-framework.txt12
-rw-r--r--Documentation/translations/zh_TW/admin-guide/README.rst164
-rw-r--r--Documentation/translations/zh_TW/admin-guide/bootconfig.rst294
-rw-r--r--Documentation/translations/zh_TW/admin-guide/bug-bisect.rst10
-rw-r--r--Documentation/translations/zh_TW/admin-guide/bug-hunting.rst38
-rw-r--r--Documentation/translations/zh_TW/admin-guide/clearing-warn-once.rst4
-rw-r--r--Documentation/translations/zh_TW/admin-guide/cpu-load.rst8
-rw-r--r--Documentation/translations/zh_TW/admin-guide/cputopology.rst97
-rw-r--r--Documentation/translations/zh_TW/admin-guide/index.rst137
-rw-r--r--Documentation/translations/zh_TW/admin-guide/init.rst36
-rw-r--r--Documentation/translations/zh_TW/admin-guide/lockup-watchdogs.rst67
-rw-r--r--Documentation/translations/zh_TW/admin-guide/mm/damon/index.rst30
-rw-r--r--Documentation/translations/zh_TW/admin-guide/mm/damon/lru_sort.rst264
-rw-r--r--Documentation/translations/zh_TW/admin-guide/mm/damon/reclaim.rst229
-rw-r--r--Documentation/translations/zh_TW/admin-guide/mm/damon/start.rst125
-rw-r--r--Documentation/translations/zh_TW/admin-guide/mm/damon/usage.rst592
-rw-r--r--Documentation/translations/zh_TW/admin-guide/mm/index.rst50
-rw-r--r--Documentation/translations/zh_TW/admin-guide/mm/ksm.rst199
-rw-r--r--Documentation/translations/zh_TW/admin-guide/reporting-issues.rst727
-rw-r--r--Documentation/translations/zh_TW/admin-guide/reporting-regressions.rst371
-rw-r--r--Documentation/translations/zh_TW/admin-guide/security-bugs.rst26
-rw-r--r--Documentation/translations/zh_TW/admin-guide/sysrq.rst281
-rw-r--r--Documentation/translations/zh_TW/admin-guide/tainted-kernels.rst84
-rw-r--r--Documentation/translations/zh_TW/admin-guide/unicode.rst10
-rw-r--r--Documentation/translations/zh_TW/arch/arm/Booting176
-rw-r--r--Documentation/translations/zh_TW/arch/arm/kernel_user_helpers.txt285
-rw-r--r--Documentation/translations/zh_TW/arch/arm64/amu.rst6
-rw-r--r--Documentation/translations/zh_TW/arch/arm64/booting.txt28
-rw-r--r--Documentation/translations/zh_TW/arch/arm64/elf_hwcaps.rst10
-rw-r--r--Documentation/translations/zh_TW/arch/arm64/legacy_instructions.txt14
-rw-r--r--Documentation/translations/zh_TW/arch/arm64/memory.txt16
-rw-r--r--Documentation/translations/zh_TW/arch/arm64/perf.rst2
-rw-r--r--Documentation/translations/zh_TW/arch/arm64/silicon-errata.txt28
-rw-r--r--Documentation/translations/zh_TW/arch/arm64/tagged-pointers.txt10
-rw-r--r--Documentation/translations/zh_TW/arch/index.rst29
-rw-r--r--Documentation/translations/zh_TW/arch/loongarch/booting.rst49
-rw-r--r--Documentation/translations/zh_TW/arch/loongarch/features.rst9
-rw-r--r--Documentation/translations/zh_TW/arch/loongarch/index.rst28
-rw-r--r--Documentation/translations/zh_TW/arch/loongarch/introduction.rst354
-rw-r--r--Documentation/translations/zh_TW/arch/loongarch/irq-chip-model.rst158
-rw-r--r--Documentation/translations/zh_TW/arch/mips/booting.rst35
-rw-r--r--Documentation/translations/zh_TW/arch/mips/features.rst14
-rw-r--r--Documentation/translations/zh_TW/arch/mips/index.rst30
-rw-r--r--Documentation/translations/zh_TW/arch/mips/ingenic-tcu.rst73
-rw-r--r--Documentation/translations/zh_TW/arch/openrisc/index.rst33
-rw-r--r--Documentation/translations/zh_TW/arch/openrisc/openrisc_port.rst128
-rw-r--r--Documentation/translations/zh_TW/arch/openrisc/todo.rst24
-rw-r--r--Documentation/translations/zh_TW/arch/parisc/debugging.rst46
-rw-r--r--Documentation/translations/zh_TW/arch/parisc/index.rst32
-rw-r--r--Documentation/translations/zh_TW/arch/parisc/registers.rst157
-rw-r--r--Documentation/translations/zh_TW/cpu-freq/core.rst38
-rw-r--r--Documentation/translations/zh_TW/cpu-freq/cpu-drivers.rst158
-rw-r--r--Documentation/translations/zh_TW/cpu-freq/cpufreq-stats.rst52
-rw-r--r--Documentation/translations/zh_TW/cpu-freq/index.rst13
-rw-r--r--Documentation/translations/zh_TW/dev-tools/gcov.rst265
-rw-r--r--Documentation/translations/zh_TW/dev-tools/gdb-kernel-debugging.rst168
-rw-r--r--Documentation/translations/zh_TW/dev-tools/index.rst43
-rw-r--r--Documentation/translations/zh_TW/dev-tools/kasan.rst463
-rw-r--r--Documentation/translations/zh_TW/dev-tools/sparse.rst (renamed from Documentation/translations/zh_TW/sparse.txt)4
-rw-r--r--Documentation/translations/zh_TW/dev-tools/testing-overview.rst162
-rw-r--r--Documentation/translations/zh_TW/filesystems/debugfs.rst47
-rw-r--r--Documentation/translations/zh_TW/filesystems/index.rst2
-rw-r--r--Documentation/translations/zh_TW/filesystems/sysfs.txt14
-rw-r--r--Documentation/translations/zh_TW/filesystems/tmpfs.rst35
-rw-r--r--Documentation/translations/zh_TW/filesystems/virtiofs.rst9
-rw-r--r--Documentation/translations/zh_TW/index.rst7
-rw-r--r--Documentation/translations/zh_TW/process/1.Intro.rst78
-rw-r--r--Documentation/translations/zh_TW/process/2.Process.rst130
-rw-r--r--Documentation/translations/zh_TW/process/3.Early-stage.rst44
-rw-r--r--Documentation/translations/zh_TW/process/4.Coding.rst104
-rw-r--r--Documentation/translations/zh_TW/process/5.Posting.rst80
-rw-r--r--Documentation/translations/zh_TW/process/6.Followthrough.rst46
-rw-r--r--Documentation/translations/zh_TW/process/7.AdvancedTopics.rst56
-rw-r--r--Documentation/translations/zh_TW/process/8.Conclusion.rst14
-rw-r--r--Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst52
-rw-r--r--Documentation/translations/zh_TW/process/code-of-conduct.rst18
-rw-r--r--Documentation/translations/zh_TW/process/coding-style.rst405
-rw-r--r--Documentation/translations/zh_TW/process/development-process.rst2
-rw-r--r--Documentation/translations/zh_TW/process/email-clients.rst279
-rw-r--r--Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst76
-rw-r--r--Documentation/translations/zh_TW/process/index.rst5
-rw-r--r--Documentation/translations/zh_TW/process/kernel-driver-statement.rst2
-rw-r--r--Documentation/translations/zh_TW/process/license-rules.rst54
-rw-r--r--Documentation/translations/zh_TW/process/management-style.rst60
-rw-r--r--Documentation/translations/zh_TW/process/stable-api-nonsense.rst86
-rw-r--r--Documentation/translations/zh_TW/process/stable-kernel-rules.rst36
-rw-r--r--Documentation/translations/zh_TW/process/submit-checklist.rst92
-rw-r--r--Documentation/translations/zh_TW/process/submitting-patches.rst749
-rw-r--r--Documentation/translations/zh_TW/process/volatile-considered-harmful.rst32
-rw-r--r--Documentation/usb/gadget-testing.rst2
-rw-r--r--Documentation/usb/gadget_uvc.rst2
-rw-r--r--Documentation/userspace-api/dma-buf-alloc-exchange.rst389
-rw-r--r--Documentation/userspace-api/index.rst1
-rw-r--r--Documentation/userspace-api/landlock.rst99
-rw-r--r--Documentation/userspace-api/media/drivers/camera-sensor.rst104
-rw-r--r--Documentation/userspace-api/media/drivers/index.rst2
-rw-r--r--Documentation/userspace-api/media/drivers/npcm-video.rst66
-rw-r--r--Documentation/userspace-api/media/gen-errors.rst4
-rw-r--r--Documentation/userspace-api/media/v4l/buffer.rst4
-rw-r--r--Documentation/userspace-api/media/v4l/control.rst4
-rw-r--r--Documentation/userspace-api/media/v4l/dev-subdev.rst49
-rw-r--r--Documentation/userspace-api/media/v4l/dv-timings.rst21
-rw-r--r--Documentation/userspace-api/media/v4l/pixfmt-reserved.rst7
-rw-r--r--Documentation/userspace-api/media/v4l/pixfmt-srggb12p.rst4
-rw-r--r--Documentation/userspace-api/media/v4l/subdev-formats.rst72
-rw-r--r--Documentation/userspace-api/netlink/genetlink-legacy.rst16
-rw-r--r--Documentation/userspace-api/netlink/specs.rst23
-rw-r--r--Documentation/virt/kvm/api.rst158
-rw-r--r--Documentation/virt/kvm/arm/index.rst1
-rw-r--r--Documentation/virt/kvm/arm/vcpu-features.rst48
-rw-r--r--Documentation/virt/kvm/devices/arm-vgic-v3.rst7
-rw-r--r--Documentation/virt/kvm/x86/mmu.rst43
-rw-r--r--MAINTAINERS808
-rw-r--r--Makefile50
-rw-r--r--arch/Kconfig1
-rw-r--r--arch/alpha/include/asm/bitops.h20
-rw-r--r--arch/alpha/include/asm/local.h33
-rw-r--r--arch/alpha/kernel/proto.h2
-rw-r--r--arch/alpha/kernel/setup.c8
-rw-r--r--arch/alpha/kernel/sys_miata.c17
-rw-r--r--arch/alpha/kernel/sys_sio.c8
-rw-r--r--arch/alpha/kernel/syscalls/syscall.tbl6
-rw-r--r--arch/arc/include/asm/kprobes.h3
-rw-r--r--arch/arc/kernel/troubleshoot.c6
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/Kconfig.debug12
-rw-r--r--arch/arm/Makefile7
-rw-r--r--arch/arm/boot/dts/allwinner/Makefile1
-rw-r--r--arch/arm/boot/dts/allwinner/sun8i-r40.dtsi2
-rw-r--r--arch/arm/boot/dts/allwinner/sun8i-v3s-anbernic-rg-nano.dts276
-rw-r--r--arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi35
-rw-r--r--arch/arm/boot/dts/aspeed/Makefile1
-rw-r--r--arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtjade.dts66
-rw-r--r--arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtmitchell.dts302
-rw-r--r--arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-minerva-cmc.dts265
-rw-r--r--arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-bonnell.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm-ns.dtsi34
-rw-r--r--arch/arm/boot/dts/broadcom/bcm2711-rpi-400.dts4
-rw-r--r--arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp-common.dtsi8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm4708-luxul-xap-1510.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm4708-luxul-xwc-1000.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm4708-netgear-r6250.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm4708-smartrg-sr400ac.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-600dhp2.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm47081-luxul-xap-1410.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm47081-luxul-xwr-1200.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts11
-rw-r--r--arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts38
-rw-r--r--arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts18
-rw-r--r--arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts24
-rw-r--r--arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-890l.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm47094-luxul-abr-4500.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm47094-luxul-xap-1610.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm47094-luxul-xbr-4500.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm47094-luxul-xwc-2000.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3100.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3150-v1.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts8
-rw-r--r--arch/arm/boot/dts/broadcom/bcm5301x.dtsi34
-rw-r--r--arch/arm/boot/dts/broadcom/bcm953012er.dts8
-rw-r--r--arch/arm/boot/dts/intel/ixp/Makefile3
-rw-r--r--arch/arm/boot/dts/intel/ixp/intel-ixp42x-dlink-dsm-g600.dts2
-rw-r--r--arch/arm/boot/dts/intel/ixp/intel-ixp42x-freecom-fsg-3.dts2
-rw-r--r--arch/arm/boot/dts/intel/ixp/intel-ixp42x-iomega-nas100d.dts2
-rw-r--r--arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-nslu2.dts4
-rw-r--r--arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-wrv54g.dts2
-rw-r--r--arch/arm/boot/dts/intel/ixp/intel-ixp42x-usrobotics-usr8200.dts229
-rw-r--r--arch/arm/boot/dts/mediatek/mt2701-evb.dts2
-rw-r--r--arch/arm/boot/dts/mediatek/mt6323.dtsi58
-rw-r--r--arch/arm/boot/dts/mediatek/mt7623n.dtsi4
-rw-r--r--arch/arm/boot/dts/mediatek/mt7629-rfb.dts2
-rw-r--r--arch/arm/boot/dts/microchip/Makefile2
-rw-r--r--arch/arm/boot/dts/microchip/at91-sam9x60_curiosity.dts4
-rw-r--r--arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts600
-rw-r--r--arch/arm/boot/dts/microchip/sama5d4.dtsi2
-rw-r--r--arch/arm/boot/dts/nuvoton/nuvoton-npcm730-gsj.dts4
-rw-r--r--arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts2
-rw-r--r--arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus.dts4
-rw-r--r--arch/arm/boot/dts/nvidia/tegra20-acer-a500-picasso.dts2
-rw-r--r--arch/arm/boot/dts/nvidia/tegra20-asus-tf101.dts2
-rw-r--r--arch/arm/boot/dts/nvidia/tegra30-asus-lvds-display.dtsi2
-rw-r--r--arch/arm/boot/dts/nvidia/tegra30-asus-tf700t.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/Makefile3
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx25.dtsi7
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx27-phytec-phycard-s-som.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx27-phytec-phycore-som.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4-lvds.dts97
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4-rgb.dts112
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4.dtsi45
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53.dtsi4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-b650v3.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-pistachio.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-skov-reve-mi1010ait-1cp1.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-var-mx6customboard.dts247
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi46
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-gw5910.dtsi1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-gw5912.dtsi1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi569
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ul-pico.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi6
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-aster.dts1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-eval-v3.dts1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris-v2.dts3
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris.dts1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull-colibri-eval-v3.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-aster.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-eval-v3.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris-v2.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-emmc.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-nand.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri.dtsi5
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-aster.dts1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-eval-v3.dts1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris-v2.dts1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris.dts1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx7s.dtsi15
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi9
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx23-evk.dts2
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx23-sansa.dts2
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx23-xfi3.dts2
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx23.dtsi4
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-apf28dev.dts2
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-cfa10049.dts2
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-cfa10055.dts2
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-cfa10057.dts2
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-cfa10058.dts2
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-eukrea-mbmx28lc.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-evk.dts2
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-m28cu3.dts2
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-m28evk.dts2
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts6
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-xea.dts1
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28.dtsi6
-rw-r--r--arch/arm/boot/dts/nxp/vf/vfxxx.dtsi27
-rw-r--r--arch/arm/boot/dts/qcom/qcom-apq8026-samsung-matisse-wifi.dts4
-rw-r--r--arch/arm/boot/dts/qcom/qcom-apq8060-dragonboard.dts1
-rw-r--r--arch/arm/boot/dts/qcom/qcom-apq8064-asus-nexus7-flo.dts1
-rw-r--r--arch/arm/boot/dts/qcom/qcom-apq8064-ifc6410.dts1
-rw-r--r--arch/arm/boot/dts/qcom/qcom-apq8064.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dts55
-rw-r--r--arch/arm/boot/dts/qcom/qcom-ipq8064-v1.0.dtsi122
-rw-r--r--arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi14
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8226.dtsi65
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8974.dtsi32
-rw-r--r--arch/arm/boot/dts/qcom/qcom-sdx55.dtsi32
-rw-r--r--arch/arm/boot/dts/qcom/qcom-sdx65-mtp.dts4
-rw-r--r--arch/arm/boot/dts/qcom/qcom-sdx65.dtsi7
-rw-r--r--arch/arm/boot/dts/renesas/r7s72100-genmai.dts82
-rw-r--r--arch/arm/boot/dts/renesas/r7s72100-gr-peach.dts6
-rw-r--r--arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts71
-rw-r--r--arch/arm/boot/dts/renesas/r7s72100.dtsi7
-rw-r--r--arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts5
-rw-r--r--arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts2
-rw-r--r--arch/arm/boot/dts/renesas/r8a7778-bockw.dts34
-rw-r--r--arch/arm/boot/dts/renesas/r8a7779-marzen.dts32
-rw-r--r--arch/arm/boot/dts/renesas/r8a7779.dtsi7
-rw-r--r--arch/arm/boot/dts/renesas/r8a7790-lager.dts5
-rw-r--r--arch/arm/boot/dts/renesas/r8a7791-koelsch.dts5
-rw-r--r--arch/arm/boot/dts/renesas/r8a7792-blanche.dts34
-rw-r--r--arch/arm/boot/dts/renesas/r8a7792-wheat.dts34
-rw-r--r--arch/arm/boot/dts/renesas/r8a7792.dtsi7
-rw-r--r--arch/arm/boot/dts/renesas/r8a7794-alt.dts5
-rw-r--r--arch/arm/boot/dts/rockchip/rk3128.dtsi81
-rw-r--r--arch/arm/boot/dts/rockchip/rk322x.dtsi6
-rw-r--r--arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts4
-rw-r--r--arch/arm/boot/dts/rockchip/rv1126-pinctrl.dtsi16
-rw-r--r--arch/arm/boot/dts/rockchip/rv1126.dtsi22
-rw-r--r--arch/arm/boot/dts/samsung/exynos4210.dtsi12
-rw-r--r--arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi41
-rw-r--r--arch/arm/boot/dts/samsung/exynos4412-galaxy-s3.dtsi43
-rw-r--r--arch/arm/boot/dts/samsung/exynos4412-midas.dtsi8
-rw-r--r--arch/arm/boot/dts/samsung/exynos4412-n710x.dts39
-rw-r--r--arch/arm/boot/dts/samsung/exynos4412-odroidu3.dts13
-rw-r--r--arch/arm/boot/dts/samsung/exynos4412-odroidx.dts9
-rw-r--r--arch/arm/boot/dts/samsung/exynos5422-odroidxu3-audio.dtsi19
-rw-r--r--arch/arm/boot/dts/samsung/exynos5422-odroidxu4.dts2
-rw-r--r--arch/arm/boot/dts/samsung/s5pv210-fascinate4g.dts33
-rw-r--r--arch/arm/boot/dts/samsung/s5pv210-galaxys.dts37
-rw-r--r--arch/arm/boot/dts/st/Makefile1
-rw-r--r--arch/arm/boot/dts/st/spear1310-evb.dts2
-rw-r--r--arch/arm/boot/dts/st/spear1340-evb.dts2
-rw-r--r--arch/arm/boot/dts/st/ste-href-tvk1281618-r2.dtsi4
-rw-r--r--arch/arm/boot/dts/st/stih407-family.dtsi1
-rw-r--r--arch/arm/boot/dts/st/stih418-b2264.dts16
-rw-r--r--arch/arm/boot/dts/st/stm32746g-eval.dts3
-rw-r--r--arch/arm/boot/dts/st/stm32f7-pinctrl.dtsi23
-rw-r--r--arch/arm/boot/dts/st/stm32f746-disco.dts3
-rw-r--r--arch/arm/boot/dts/st/stm32f769-disco.dts3
-rw-r--r--arch/arm/boot/dts/st/stm32mp131.dtsi19
-rw-r--r--arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi342
-rw-r--r--arch/arm/boot/dts/st/stm32mp157c-osd32mp1-red.dts225
-rw-r--r--arch/arm/boot/dts/st/stm32mp15xc-lxa-tac.dtsi4
-rw-r--r--arch/arm/boot/dts/st/stm32mp15xx-osd32.dtsi6
-rw-r--r--arch/arm/boot/dts/ti/omap/am335x-pocketbeagle.dts57
-rw-r--r--arch/arm/boot/dts/ti/omap/am3517-evm.dts35
-rw-r--r--arch/arm/boot/dts/ti/omap/am3517.dtsi1
-rw-r--r--arch/arm/boot/dts/ti/omap/motorola-mapphone-common.dtsi20
-rw-r--r--arch/arm/boot/dts/ti/omap/omap3-devkit8000-common.dtsi4
-rw-r--r--arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi2
-rw-r--r--arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts55
-rw-r--r--arch/arm/boot/dts/ti/omap/omap4-l4-abe.dtsi6
-rw-r--r--arch/arm/boot/dts/ti/omap/omap4-l4.dtsi2
-rw-r--r--arch/arm/boot/dts/ti/omap/omap5-l4-abe.dtsi6
-rw-r--r--arch/arm/common/sa1111.c27
-rw-r--r--arch/arm/configs/aspeed_g4_defconfig1
-rw-r--r--arch/arm/configs/aspeed_g5_defconfig8
-rw-r--r--arch/arm/configs/exynos_defconfig3
-rw-r--r--arch/arm/configs/hardening.config7
-rw-r--r--arch/arm/configs/keystone_defconfig1
-rw-r--r--arch/arm/configs/multi_v7_defconfig8
-rw-r--r--arch/arm/configs/omap2plus_defconfig9
-rw-r--r--arch/arm/configs/pxa_defconfig1
-rw-r--r--arch/arm/configs/s5pv210_defconfig1
-rw-r--r--arch/arm/configs/shmobile_defconfig2
-rw-r--r--arch/arm/configs/tegra_defconfig1
-rw-r--r--arch/arm/crypto/nhpoly1305-neon-glue.c9
-rw-r--r--arch/arm/include/asm/arm_pmuv3.h48
-rw-r--r--arch/arm/include/asm/dma.h3
-rw-r--r--arch/arm/include/asm/domain.h2
-rw-r--r--arch/arm/include/asm/exception.h4
-rw-r--r--arch/arm/include/asm/kexec.h4
-rw-r--r--arch/arm/include/asm/kprobes.h2
-rw-r--r--arch/arm/include/asm/setup.h5
-rw-r--r--arch/arm/include/asm/traps.h3
-rw-r--r--arch/arm/include/asm/uaccess.h15
-rw-r--r--arch/arm/include/asm/vga.h1
-rw-r--r--arch/arm/kernel/Makefile2
-rw-r--r--arch/arm/kernel/atags_parse.c20
-rw-r--r--arch/arm/kernel/devtree.c1
-rw-r--r--arch/arm/kernel/efi.c6
-rw-r--r--arch/arm/kernel/isa.c4
-rw-r--r--arch/arm/kernel/setup.c12
-rw-r--r--arch/arm/lib/memset.S1
-rw-r--r--arch/arm/mach-imx/mmdc.c7
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c96
-rw-r--r--arch/arm/mach-omap1/board-palmte.c5
-rw-r--r--arch/arm/mach-omap1/timer32k.c14
-rw-r--r--arch/arm/mach-omap2/board-n8x0.c10
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c2
-rw-r--r--arch/arm/mach-omap2/pdata-quirks.c10
-rw-r--r--arch/arm/mach-shmobile/pm-rcar-gen2.c5
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7779.c9
-rw-r--r--arch/arm/mach-shmobile/smp-sh73a0.c10
-rw-r--r--arch/arm/net/bpf_jit_32.c280
-rw-r--r--arch/arm/net/bpf_jit_32.h4
-rw-r--r--arch/arm/tools/syscall.tbl6
-rw-r--r--arch/arm/vdso/Makefile25
-rw-r--r--arch/arm/xen/enlighten.c28
-rw-r--r--arch/arm64/Kconfig5
-rw-r--r--arch/arm64/Kconfig.platforms12
-rw-r--r--arch/arm64/Makefile11
-rw-r--r--arch/arm64/boot/dts/allwinner/Makefile2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1-manta.dts35
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1.dtsi138
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-pi.dts63
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi7
-rw-r--r--arch/arm64/boot/dts/amd/Makefile1
-rw-r--r--arch/arm64/boot/dts/amd/amd-overdrive-rev-b0.dts1
-rw-r--r--arch/arm64/boot/dts/amd/amd-overdrive-rev-b1.dts1
-rw-r--r--arch/arm64/boot/dts/amd/elba-16core.dtsi197
-rw-r--r--arch/arm64/boot/dts/amd/elba-asic-common.dtsi70
-rw-r--r--arch/arm64/boot/dts/amd/elba-asic.dts28
-rw-r--r--arch/arm64/boot/dts/amd/elba-flash-parts.dtsi117
-rw-r--r--arch/arm64/boot/dts/amd/elba.dtsi191
-rw-r--r--arch/arm64/boot/dts/amlogic/Makefile3
-rw-r--r--arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi28
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts147
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-a1.dtsi369
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-axg.dtsi13
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12.dtsi40
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts341
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts10
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-a311d-libretech-cc.dts121
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts10
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6.dts10
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts60
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts39
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-libretech-cottonwood.dtsi614
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts6
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-s4.dtsi20
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-sm1-s905d3-libretech-cc.dts89
-rw-r--r--arch/arm64/boot/dts/apm/apm-shadowcat.dtsi2
-rw-r--r--arch/arm64/boot/dts/apm/apm-storm.dtsi2
-rw-r--r--arch/arm64/boot/dts/bitmain/bm1880.dtsi6
-rw-r--r--arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts2
-rw-r--r--arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi27
-rw-r--r--arch/arm64/boot/dts/exynos/exynos7.dtsi1
-rw-r--r--arch/arm64/boot/dts/exynos/exynos850-e850-96.dts73
-rw-r--r--arch/arm64/boot/dts/exynos/exynos850.dtsi30
-rw-r--r--arch/arm64/boot/dts/freescale/Makefile19
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1043a-tqmls1043a-mbls10xxa.dts49
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1043a-tqmls1043a.dtsi32
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi14
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1046a-tqmls1046a-mbls10xxa.dts56
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1046a-tqmls1046a.dtsi42
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1088a-tqmls1088a-mbls10xxa.dts64
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1088a-tqmls1088a.dtsi42
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi46
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi7
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts376
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-lx2162a-sr-som.dtsi73
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi16
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi98
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi42
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi117
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi36
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi33
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-evk.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi38
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl.dtsi8
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi76
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-ddr4-evk.dts1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-phg.dts5
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts489
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx-lvds-tm070jvhg33.dtso45
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi5
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi11
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts3
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts3
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts3
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi38
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-bsh-smm-s2.dts1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-lvds-tm070jvhg33.dtso45
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl.dtsi5
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts3
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts65
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-debix-model-a.dts3
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-debix-som-a-bmb-08.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts70
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi154
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts154
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi13
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw71xx.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi10
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx-imx219.dtso80
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp.dtsi150
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi7
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts14
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-thor96.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx-lvds-tm070jvhg33.dtso49
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq.dtsi108
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-apalis.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-mek.dts26
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi67
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-mek.dts26
-rw-r--r--arch/arm64/boot/dts/freescale/imx8ulp.dtsi29
-rw-r--r--arch/arm64/boot/dts/freescale/imx8x-colibri-iris-v2.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts15
-rw-r--r--arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx93.dtsi173
-rw-r--r--arch/arm64/boot/dts/freescale/mba8mx.dtsi93
-rw-r--r--arch/arm64/boot/dts/freescale/tqmls104xa-mbls10xxa-fman.dtsi104
-rw-r--r--arch/arm64/boot/dts/freescale/tqmls1088a-mbls10xxa-mc.dtsi146
-rw-r--r--arch/arm64/boot/dts/freescale/tqmls10xxa-mbls10xxa.dtsi136
-rw-r--r--arch/arm64/boot/dts/freescale/tqmls10xxa.dtsi58
-rw-r--r--arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi4
-rw-r--r--arch/arm64/boot/dts/marvell/armada-3720-eDPU.dts47
-rw-r--r--arch/arm64/boot/dts/marvell/armada-3720-espressobin.dtsi2
-rw-r--r--arch/arm64/boot/dts/marvell/armada-3720-uDPU.dtsi8
-rw-r--r--arch/arm64/boot/dts/marvell/cn9130-crb.dtsi4
-rw-r--r--arch/arm64/boot/dts/marvell/cn9130-db.dtsi4
-rw-r--r--arch/arm64/boot/dts/mediatek/Makefile3
-rw-r--r--arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts101
-rw-r--r--arch/arm64/boot/dts/mediatek/mt6795.dtsi253
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts8
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts8
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7622.dtsi2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts12
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7986a.dtsi26
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8173-evb.dts4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-evb.dts52
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi8
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi126
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts12
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183.dtsi242
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8186.dtsi44
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada-audio-rt1015p-rt5682.dtsi19
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada-audio-rt1015p.dtsi26
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada-audio-rt5682.dtsi21
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts19
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r5-sku2.dts64
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts19
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r4.dts77
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi30
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi35
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8195-demo.dts41
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8195.dtsi7
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8365.dtsi210
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts901
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra132.dtsi2
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra210-smaug.dts66
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi33
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi53
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts1
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi33
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts13
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi1
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234.dtsi52
-rw-r--r--arch/arm64/boot/dts/qcom/Makefile12
-rw-r--r--arch/arm64/boot/dts/qcom/apq8016-sbc-usb-host.dtso8
-rw-r--r--arch/arm64/boot/dts/qcom/apq8016-sbc.dts30
-rw-r--r--arch/arm64/boot/dts/qcom/apq8039-t2.dts8
-rw-r--r--arch/arm64/boot/dts/qcom/apq8096-db820c.dts34
-rw-r--r--arch/arm64/boot/dts/qcom/ipq5018.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/ipq5332-rdp468.dts23
-rw-r--r--arch/arm64/boot/dts/qcom/ipq5332.dtsi57
-rw-r--r--arch/arm64/boot/dts/qcom/ipq6018.dtsi36
-rw-r--r--arch/arm64/boot/dts/qcom/ipq8074.dtsi69
-rw-r--r--arch/arm64/boot/dts/qcom/ipq9574.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts21
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-gt5-common.dtsi12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-gt510.dts86
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts64
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-j5-common.dtsi51
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-j5.dts5
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-j5x.dts15
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-ufi.dtsi33
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916.dtsi41
-rw-r--r--arch/arm64/boot/dts/qcom/msm8939-longcheer-l9100.dts334
-rw-r--r--arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/msm8939-sony-xperia-kanuti-tulip.dts8
-rw-r--r--arch/arm64/boot/dts/qcom/msm8939.dtsi39
-rw-r--r--arch/arm64/boot/dts/qcom/msm8976.dtsi15
-rw-r--r--arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts6
-rw-r--r--arch/arm64/boot/dts/qcom/msm8994-msft-lumia-octagon.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/msm8994.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi36
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts18
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996.dtsi3
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-fxtec-pro1.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-mtp.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-xiaomi-sagit.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998.dtsi33
-rw-r--r--arch/arm64/boot/dts/qcom/pm6150.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/pm7250b.dtsi14
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150b.dtsi40
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150l.dtsi10
-rw-r--r--arch/arm64/boot/dts/qcom/pm8350c.dtsi6
-rw-r--r--arch/arm64/boot/dts/qcom/pm8916.dtsi3
-rw-r--r--arch/arm64/boot/dts/qcom/pmr735d_a.dtsi (renamed from arch/arm64/boot/dts/qcom/pmr735d.dtsi)45
-rw-r--r--arch/arm64/boot/dts/qcom/pmr735d_b.dtsi59
-rw-r--r--arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts667
-rw-r--r--arch/arm64/boot/dts/qcom/qrb2210-rb1.dts147
-rw-r--r--arch/arm64/boot/dts/qcom/qrb5165-rb5.dts125
-rw-r--r--arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sa8775p-ride.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sa8775p.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi3
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dts13
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r10.dts29
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r5.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r9.dts7
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r10.dts45
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r4.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r9.dts11
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-kb.dts23
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-lte.dts27
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10.dts19
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-kb.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-lte.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-kb.dts5
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-lte.dts5
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9.dts5
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-lte-parade.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-lte-ti.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-parade.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-ti.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360.dtsi13
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-rt5682i-sku.dtsi38
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-rt5682s-sku.dtsi38
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe-rt5682s.dts17
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx-rt5682s.dts15
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi27
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180.dtsi187
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi24
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-crd-r3.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280.dtsi239
-rw-r--r--arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts3
-rw-r--r--arch/arm64/boot/dts/qcom/sc8180x-primus.dts3
-rw-r--r--arch/arm64/boot/dts/qcom/sc8180x.dtsi177
-rw-r--r--arch/arm64/boot/dts/qcom/sdm630.dtsi68
-rw-r--r--arch/arm64/boot/dts/qcom/sdm670.dtsi3
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi32
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-mtp.dts90
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-akari.dts170
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-akatsuki.dts168
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-apollo.dts170
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi91
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845.dtsi130
-rw-r--r--arch/arm64/boot/dts/qcom/sdx75-idp.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts59
-rw-r--r--arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/sm6125.dtsi257
-rw-r--r--arch/arm64/boot/dts/qcom/sm7125-xiaomi-common.dtsi423
-rw-r--r--arch/arm64/boot/dts/qcom/sm7125-xiaomi-joyeuse.dts16
-rw-r--r--arch/arm64/boot/dts/qcom/sm7125.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts35
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150.dtsi117
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi5
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250.dtsi554
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350-hdk.dts81
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350-mtp.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350.dtsi5
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-hdk.dts24
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-qrd.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450.dtsi90
-rw-r--r--arch/arm64/boot/dts/qcom/sm8550-mtp.dts7
-rw-r--r--arch/arm64/boot/dts/qcom/sm8550-qrd.dts50
-rw-r--r--arch/arm64/boot/dts/qcom/sm8550.dtsi48
-rw-r--r--arch/arm64/boot/dts/renesas/Makefile38
-rw-r--r--arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/ebisu.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/hihope-rev4.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774a1.dtsi4
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774b1.dtsi4
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774c0.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774e1.dtsi4
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77951.dtsi4
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77960.dtsi4
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77961.dtsi4
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77965.dtsi4
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77990.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77995.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi24
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f0.dtsi134
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts240
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f4.dtsi12
-rw-r--r--arch/arm64/boot/dts/renesas/r9a08g045.dtsi170
-rw-r--r--arch/arm64/boot/dts/renesas/r9a08g045s33-smarc.dts18
-rw-r--r--arch/arm64/boot/dts/renesas/r9a08g045s33.dtsi14
-rw-r--r--arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi14
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi20
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi20
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2ul-smarc.dtsi24
-rw-r--r--arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi142
-rw-r--r--arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi28
-rw-r--r--arch/arm64/boot/dts/renesas/salvator-common.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-audio-graph-card-mix+split.dtsi16
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-audio-graph-card.dtsi17
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-audio-graph-card2-mix+split.dtsi13
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-audio-graph-card2.dtsi4
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card-mix+split.dtsi57
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card.dtsi27
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card2-mix+split.dtsi108
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card2.dtsi14
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-kf-simple-audio-card-mix+split.dtsi152
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-kf-simple-audio-card.dtsi77
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-simple-audio-card-mix+split.dtsi8
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-simple-audio-card.dtsi8
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb.dtsi2
-rw-r--r--arch/arm64/boot/dts/rockchip/Makefile5
-rw-r--r--arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts12
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328.dtsi2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi3
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet-dumo.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi1
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi1
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399.dtsi17
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-powkiddy-rgb30.dts161
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk356x.dtsi9
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts136
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts28
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts848
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts1137
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts145
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dts21
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi614
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts84
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts662
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi46
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s.dtsi60
-rw-r--r--arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi2
-rw-r--r--arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi4
-rw-r--r--arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi2
-rw-r--r--arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi54
-rw-r--r--arch/arm64/boot/dts/st/stm32mp251.dtsi19
-rw-r--r--arch/arm64/boot/dts/st/stm32mp257f-ev1.dts27
-rw-r--r--arch/arm64/boot/dts/ti/Makefile11
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-main.dtsi12
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-verdin-wifi.dtsi6
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi1
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62.dtsi3
-rw-r--r--arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts34
-rw-r--r--arch/arm64/boot/dts/ti/k3-am625-sk.dts27
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a-main.dtsi60
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a7-sk.dts189
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p-main.dtsi766
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi190
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi47
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi69
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p.dtsi7
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p5-sk.dts510
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi16
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-main.dtsi37
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi11
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-evm.dts37
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-sk.dts29
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts84
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi12
-rw-r--r--arch/arm64/boot/dts/ti/k3-am65-main.dtsi38
-rw-r--r--arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-am654-base-board.dts7
-rw-r--r--arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso145
-rw-r--r--arch/arm64/boot/dts/ti/k3-am654-idk.dtso296
-rw-r--r--arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts56
-rw-r--r--arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi208
-rw-r--r--arch/arm64/boot/dts/ti/k3-am69-sk.dts536
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-main.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi9
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-main.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi9
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi232
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi82
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi208
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-evm.dts117
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi497
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi40
-rw-r--r--arch/arm64/boot/dts/ti/k3-serdes.h2
-rw-r--r--arch/arm64/configs/defconfig20
-rw-r--r--arch/arm64/configs/hardening.config22
-rw-r--r--arch/arm64/crypto/nhpoly1305-neon-glue.c9
-rw-r--r--arch/arm64/crypto/sha1-ce-core.S8
-rw-r--r--arch/arm64/crypto/sha1-ce-glue.c21
-rw-r--r--arch/arm64/crypto/sha2-ce-core.S8
-rw-r--r--arch/arm64/crypto/sha2-ce-glue.c39
-rw-r--r--arch/arm64/crypto/sha256-glue.c26
-rw-r--r--arch/arm64/crypto/sha512-ce-core.S8
-rw-r--r--arch/arm64/crypto/sha512-ce-glue.c26
-rw-r--r--arch/arm64/crypto/sha512-glue.c12
-rw-r--r--arch/arm64/include/asm/Kbuild2
-rw-r--r--arch/arm64/include/asm/alternative-macros.h8
-rw-r--r--arch/arm64/include/asm/arch_gicv3.h8
-rw-r--r--arch/arm64/include/asm/archrandom.h2
-rw-r--r--arch/arm64/include/asm/arm_pmuv3.h25
-rw-r--r--arch/arm64/include/asm/cacheflush.h2
-rw-r--r--arch/arm64/include/asm/cpu.h6
-rw-r--r--arch/arm64/include/asm/cpucaps.h67
-rw-r--r--arch/arm64/include/asm/cpufeature.h98
-rw-r--r--arch/arm64/include/asm/cputype.h3
-rw-r--r--arch/arm64/include/asm/crash_core.h10
-rw-r--r--arch/arm64/include/asm/fpsimd.h36
-rw-r--r--arch/arm64/include/asm/hwcap.h3
-rw-r--r--arch/arm64/include/asm/irq.h3
-rw-r--r--arch/arm64/include/asm/irqflags.h20
-rw-r--r--arch/arm64/include/asm/kprobes.h2
-rw-r--r--arch/arm64/include/asm/kvm_arm.h8
-rw-r--r--arch/arm64/include/asm/kvm_emulate.h19
-rw-r--r--arch/arm64/include/asm/kvm_host.h63
-rw-r--r--arch/arm64/include/asm/kvm_hyp.h7
-rw-r--r--arch/arm64/include/asm/kvm_mmu.h47
-rw-r--r--arch/arm64/include/asm/kvm_nested.h3
-rw-r--r--arch/arm64/include/asm/lse.h9
-rw-r--r--arch/arm64/include/asm/mmu.h2
-rw-r--r--arch/arm64/include/asm/mmu_context.h28
-rw-r--r--arch/arm64/include/asm/module.h3
-rw-r--r--arch/arm64/include/asm/mte.h4
-rw-r--r--arch/arm64/include/asm/pgtable-prot.h6
-rw-r--r--arch/arm64/include/asm/pgtable.h40
-rw-r--r--arch/arm64/include/asm/setup.h17
-rw-r--r--arch/arm64/include/asm/smp.h4
-rw-r--r--arch/arm64/include/asm/spectre.h2
-rw-r--r--arch/arm64/include/asm/stage2_pgtable.h4
-rw-r--r--arch/arm64/include/asm/syscall_wrapper.h1
-rw-r--r--arch/arm64/include/asm/sysreg.h45
-rw-r--r--arch/arm64/include/asm/tlb.h5
-rw-r--r--arch/arm64/include/asm/tlbflush.h15
-rw-r--r--arch/arm64/include/asm/traps.h54
-rw-r--r--arch/arm64/include/asm/unistd.h2
-rw-r--r--arch/arm64/include/asm/unistd32.h12
-rw-r--r--arch/arm64/include/asm/vectors.h2
-rw-r--r--arch/arm64/include/uapi/asm/hwcap.h3
-rw-r--r--arch/arm64/include/uapi/asm/kvm.h32
-rw-r--r--arch/arm64/kernel/acpi_parking_protocol.c2
-rw-r--r--arch/arm64/kernel/armv8_deprecated.c8
-rw-r--r--arch/arm64/kernel/cpu_errata.c17
-rw-r--r--arch/arm64/kernel/cpufeature.c322
-rw-r--r--arch/arm64/kernel/cpuinfo.c3
-rw-r--r--arch/arm64/kernel/efi.c7
-rw-r--r--arch/arm64/kernel/fpsimd.c151
-rw-r--r--arch/arm64/kernel/idle.c4
-rw-r--r--arch/arm64/kernel/image-vars.h2
-rw-r--r--arch/arm64/kernel/module-plts.c13
-rw-r--r--arch/arm64/kernel/mte.c8
-rw-r--r--arch/arm64/kernel/process.c3
-rw-r--r--arch/arm64/kernel/proton-pack.c2
-rw-r--r--arch/arm64/kernel/smp.c148
-rw-r--r--arch/arm64/kernel/suspend.c13
-rw-r--r--arch/arm64/kernel/sys_compat.c2
-rw-r--r--arch/arm64/kernel/traps.c50
-rw-r--r--arch/arm64/kernel/vdso.c2
-rw-r--r--arch/arm64/kernel/vdso/Makefile10
-rw-r--r--arch/arm64/kernel/vdso32/Makefile10
-rw-r--r--arch/arm64/kvm/arch_timer.c19
-rw-r--r--arch/arm64/kvm/arm.c204
-rw-r--r--arch/arm64/kvm/emulate-nested.c79
-rw-r--r--arch/arm64/kvm/guest.c6
-rw-r--r--arch/arm64/kvm/hyp/include/hyp/switch.h17
-rw-r--r--arch/arm64/kvm/hyp/include/nvhe/fixed_config.h3
-rw-r--r--arch/arm64/kvm/hyp/nvhe/ffa.c10
-rw-r--r--arch/arm64/kvm/hyp/nvhe/mem_protect.c8
-rw-r--r--arch/arm64/kvm/hyp/nvhe/pkvm.c4
-rw-r--r--arch/arm64/kvm/hyp/nvhe/switch.c2
-rw-r--r--arch/arm64/kvm/hyp/pgtable.c8
-rw-r--r--arch/arm64/kvm/hyp/vhe/switch.c78
-rw-r--r--arch/arm64/kvm/hyp/vhe/sysreg-sr.c11
-rw-r--r--arch/arm64/kvm/hyp/vhe/tlb.c18
-rw-r--r--arch/arm64/kvm/hypercalls.c36
-rw-r--r--arch/arm64/kvm/mmio.c4
-rw-r--r--arch/arm64/kvm/mmu.c35
-rw-r--r--arch/arm64/kvm/pkvm.c2
-rw-r--r--arch/arm64/kvm/pmu-emul.c145
-rw-r--r--arch/arm64/kvm/pmu.c4
-rw-r--r--arch/arm64/kvm/reset.c56
-rw-r--r--arch/arm64/kvm/sys_regs.c361
-rw-r--r--arch/arm64/kvm/trace_arm.h25
-rw-r--r--arch/arm64/kvm/vgic/vgic-debug.c6
-rw-r--r--arch/arm64/kvm/vgic/vgic-irqfd.c2
-rw-r--r--arch/arm64/kvm/vgic/vgic-its.c49
-rw-r--r--arch/arm64/kvm/vgic/vgic-kvm-device.c11
-rw-r--r--arch/arm64/kvm/vgic/vgic-mmio-v3.c150
-rw-r--r--arch/arm64/kvm/vgic/vgic-v3.c2
-rw-r--r--arch/arm64/kvm/vgic/vgic-v4.c4
-rw-r--r--arch/arm64/kvm/vgic/vgic.c12
-rw-r--r--arch/arm64/kvm/vmid.c11
-rw-r--r--arch/arm64/lib/delay.c2
-rw-r--r--arch/arm64/mm/fault.c2
-rw-r--r--arch/arm64/mm/hugetlbpage.c3
-rw-r--r--arch/arm64/mm/init.c151
-rw-r--r--arch/arm64/mm/kasan_init.c6
-rw-r--r--arch/arm64/mm/mmap.c2
-rw-r--r--arch/arm64/mm/mmu.c3
-rw-r--r--arch/arm64/mm/pageattr.c7
-rw-r--r--arch/arm64/mm/proc.S3
-rw-r--r--arch/arm64/net/bpf_jit_comp.c2
-rw-r--r--arch/arm64/tools/Makefile4
-rw-r--r--arch/arm64/tools/cpucaps2
-rwxr-xr-xarch/arm64/tools/gen-cpucaps.awk6
-rw-r--r--arch/arm64/tools/sysreg8
-rw-r--r--arch/csky/abiv1/alignment.c1
-rw-r--r--arch/csky/kernel/setup.c12
-rw-r--r--arch/csky/kernel/vdso/Makefile10
-rw-r--r--arch/hexagon/include/asm/ptrace.h25
-rw-r--r--arch/hexagon/include/uapi/asm/ptrace.h13
-rw-r--r--arch/hexagon/kernel/Makefile2
-rw-r--r--arch/hexagon/kernel/screen_info.c3
-rw-r--r--arch/ia64/Kbuild3
-rw-r--r--arch/ia64/Kconfig394
-rw-r--r--arch/ia64/Kconfig.debug55
-rw-r--r--arch/ia64/Makefile82
-rw-r--r--arch/ia64/configs/bigsur_defconfig102
-rw-r--r--arch/ia64/configs/generic_defconfig206
-rw-r--r--arch/ia64/configs/gensparse_defconfig184
-rw-r--r--arch/ia64/configs/tiger_defconfig169
-rw-r--r--arch/ia64/configs/zx1_defconfig148
-rw-r--r--arch/ia64/hp/common/Makefile10
-rw-r--r--arch/ia64/hp/common/aml_nfw.c232
-rw-r--r--arch/ia64/hp/common/sba_iommu.c2155
-rw-r--r--arch/ia64/include/asm/Kbuild6
-rw-r--r--arch/ia64/include/asm/acenv.h49
-rw-r--r--arch/ia64/include/asm/acpi-ext.h17
-rw-r--r--arch/ia64/include/asm/acpi.h110
-rw-r--r--arch/ia64/include/asm/asm-offsets.h1
-rw-r--r--arch/ia64/include/asm/asm-prototypes.h30
-rw-r--r--arch/ia64/include/asm/asmmacro.h136
-rw-r--r--arch/ia64/include/asm/atomic.h216
-rw-r--r--arch/ia64/include/asm/barrier.h79
-rw-r--r--arch/ia64/include/asm/bitops.h453
-rw-r--r--arch/ia64/include/asm/bug.h19
-rw-r--r--arch/ia64/include/asm/cache.h30
-rw-r--r--arch/ia64/include/asm/cacheflush.h39
-rw-r--r--arch/ia64/include/asm/checksum.h63
-rw-r--r--arch/ia64/include/asm/clocksource.h11
-rw-r--r--arch/ia64/include/asm/cmpxchg.h33
-rw-r--r--arch/ia64/include/asm/cpu.h23
-rw-r--r--arch/ia64/include/asm/cputime.h21
-rw-r--r--arch/ia64/include/asm/current.h18
-rw-r--r--arch/ia64/include/asm/cyclone.h16
-rw-r--r--arch/ia64/include/asm/delay.h89
-rw-r--r--arch/ia64/include/asm/device.h14
-rw-r--r--arch/ia64/include/asm/div64.h1
-rw-r--r--arch/ia64/include/asm/dma-mapping.h16
-rw-r--r--arch/ia64/include/asm/dma.h17
-rw-r--r--arch/ia64/include/asm/dmi.h15
-rw-r--r--arch/ia64/include/asm/early_ioremap.h11
-rw-r--r--arch/ia64/include/asm/efi.h13
-rw-r--r--arch/ia64/include/asm/elf.h233
-rw-r--r--arch/ia64/include/asm/emergency-restart.h6
-rw-r--r--arch/ia64/include/asm/esi.h30
-rw-r--r--arch/ia64/include/asm/exception.h23
-rw-r--r--arch/ia64/include/asm/extable.h12
-rw-r--r--arch/ia64/include/asm/fb.h43
-rw-r--r--arch/ia64/include/asm/fpswa.h74
-rw-r--r--arch/ia64/include/asm/ftrace.h28
-rw-r--r--arch/ia64/include/asm/futex.h109
-rw-r--r--arch/ia64/include/asm/gcc_intrin.h13
-rw-r--r--arch/ia64/include/asm/hardirq.h27
-rw-r--r--arch/ia64/include/asm/hugetlb.h34
-rw-r--r--arch/ia64/include/asm/hw_irq.h167
-rw-r--r--arch/ia64/include/asm/idle.h8
-rw-r--r--arch/ia64/include/asm/intrinsics.h13
-rw-r--r--arch/ia64/include/asm/io.h271
-rw-r--r--arch/ia64/include/asm/iommu.h22
-rw-r--r--arch/ia64/include/asm/iosapic.h106
-rw-r--r--arch/ia64/include/asm/irq.h37
-rw-r--r--arch/ia64/include/asm/irq_regs.h1
-rw-r--r--arch/ia64/include/asm/irq_remapping.h5
-rw-r--r--arch/ia64/include/asm/irqflags.h95
-rw-r--r--arch/ia64/include/asm/kdebug.h45
-rw-r--r--arch/ia64/include/asm/kexec.h46
-rw-r--r--arch/ia64/include/asm/kprobes.h116
-rw-r--r--arch/ia64/include/asm/kregs.h166
-rw-r--r--arch/ia64/include/asm/libata-portmap.h9
-rw-r--r--arch/ia64/include/asm/linkage.h19
-rw-r--r--arch/ia64/include/asm/local.h1
-rw-r--r--arch/ia64/include/asm/mca.h185
-rw-r--r--arch/ia64/include/asm/mca_asm.h245
-rw-r--r--arch/ia64/include/asm/meminit.h59
-rw-r--r--arch/ia64/include/asm/mman.h18
-rw-r--r--arch/ia64/include/asm/mmiowb.h17
-rw-r--r--arch/ia64/include/asm/mmu.h14
-rw-r--r--arch/ia64/include/asm/mmu_context.h194
-rw-r--r--arch/ia64/include/asm/mmzone.h35
-rw-r--r--arch/ia64/include/asm/module.h35
-rw-r--r--arch/ia64/include/asm/module.lds.h14
-rw-r--r--arch/ia64/include/asm/msidef.h43
-rw-r--r--arch/ia64/include/asm/native/inst.h119
-rw-r--r--arch/ia64/include/asm/native/irq.h20
-rw-r--r--arch/ia64/include/asm/native/patchlist.h24
-rw-r--r--arch/ia64/include/asm/nodedata.h63
-rw-r--r--arch/ia64/include/asm/numa.h83
-rw-r--r--arch/ia64/include/asm/page.h208
-rw-r--r--arch/ia64/include/asm/pal.h1827
-rw-r--r--arch/ia64/include/asm/param.h18
-rw-r--r--arch/ia64/include/asm/parport.h20
-rw-r--r--arch/ia64/include/asm/patch.h28
-rw-r--r--arch/ia64/include/asm/pci.h66
-rw-r--r--arch/ia64/include/asm/percpu.h53
-rw-r--r--arch/ia64/include/asm/pgalloc.h64
-rw-r--r--arch/ia64/include/asm/pgtable.h545
-rw-r--r--arch/ia64/include/asm/processor.h660
-rw-r--r--arch/ia64/include/asm/ptrace.h146
-rw-r--r--arch/ia64/include/asm/sal.h919
-rw-r--r--arch/ia64/include/asm/sections.h33
-rw-r--r--arch/ia64/include/asm/serial.h17
-rw-r--r--arch/ia64/include/asm/shmparam.h13
-rw-r--r--arch/ia64/include/asm/signal.h33
-rw-r--r--arch/ia64/include/asm/smp.h103
-rw-r--r--arch/ia64/include/asm/sn/intr.h15
-rw-r--r--arch/ia64/include/asm/sn/sn_sal.h124
-rw-r--r--arch/ia64/include/asm/sparsemem.h28
-rw-r--r--arch/ia64/include/asm/spinlock.h265
-rw-r--r--arch/ia64/include/asm/spinlock_types.h22
-rw-r--r--arch/ia64/include/asm/string.h22
-rw-r--r--arch/ia64/include/asm/switch_to.h71
-rw-r--r--arch/ia64/include/asm/syscall.h65
-rw-r--r--arch/ia64/include/asm/thread_info.h131
-rw-r--r--arch/ia64/include/asm/timex.h47
-rw-r--r--arch/ia64/include/asm/tlb.h50
-rw-r--r--arch/ia64/include/asm/tlbflush.h128
-rw-r--r--arch/ia64/include/asm/topology.h56
-rw-r--r--arch/ia64/include/asm/types.h32
-rw-r--r--arch/ia64/include/asm/uaccess.h265
-rw-r--r--arch/ia64/include/asm/uncached.h9
-rw-r--r--arch/ia64/include/asm/unistd.h38
-rw-r--r--arch/ia64/include/asm/unwind.h234
-rw-r--r--arch/ia64/include/asm/user.h53
-rw-r--r--arch/ia64/include/asm/ustack.h12
-rw-r--r--arch/ia64/include/asm/uv/uv.h30
-rw-r--r--arch/ia64/include/asm/uv/uv_hub.h315
-rw-r--r--arch/ia64/include/asm/uv/uv_mmrs.h825
-rw-r--r--arch/ia64/include/asm/vermagic.h15
-rw-r--r--arch/ia64/include/asm/vga.h26
-rw-r--r--arch/ia64/include/asm/vmalloc.h4
-rw-r--r--arch/ia64/include/asm/xor.h30
-rw-r--r--arch/ia64/include/asm/xtp.h46
-rw-r--r--arch/ia64/include/uapi/asm/Kbuild2
-rw-r--r--arch/ia64/include/uapi/asm/auxvec.h14
-rw-r--r--arch/ia64/include/uapi/asm/bitsperlong.h9
-rw-r--r--arch/ia64/include/uapi/asm/break.h23
-rw-r--r--arch/ia64/include/uapi/asm/byteorder.h7
-rw-r--r--arch/ia64/include/uapi/asm/cmpxchg.h138
-rw-r--r--arch/ia64/include/uapi/asm/fcntl.h15
-rw-r--r--arch/ia64/include/uapi/asm/fpu.h67
-rw-r--r--arch/ia64/include/uapi/asm/gcc_intrin.h619
-rw-r--r--arch/ia64/include/uapi/asm/ia64regs.h101
-rw-r--r--arch/ia64/include/uapi/asm/intrinsics.h82
-rw-r--r--arch/ia64/include/uapi/asm/mman.h17
-rw-r--r--arch/ia64/include/uapi/asm/param.h30
-rw-r--r--arch/ia64/include/uapi/asm/posix_types.h9
-rw-r--r--arch/ia64/include/uapi/asm/ptrace.h248
-rw-r--r--arch/ia64/include/uapi/asm/ptrace_offsets.h269
-rw-r--r--arch/ia64/include/uapi/asm/resource.h8
-rw-r--r--arch/ia64/include/uapi/asm/rse.h67
-rw-r--r--arch/ia64/include/uapi/asm/setup.h25
-rw-r--r--arch/ia64/include/uapi/asm/sigcontext.h71
-rw-r--r--arch/ia64/include/uapi/asm/siginfo.h28
-rw-r--r--arch/ia64/include/uapi/asm/signal.h98
-rw-r--r--arch/ia64/include/uapi/asm/stat.h52
-rw-r--r--arch/ia64/include/uapi/asm/statfs.h21
-rw-r--r--arch/ia64/include/uapi/asm/swab.h35
-rw-r--r--arch/ia64/include/uapi/asm/types.h32
-rw-r--r--arch/ia64/include/uapi/asm/ucontext.h13
-rw-r--r--arch/ia64/include/uapi/asm/unistd.h22
-rw-r--r--arch/ia64/include/uapi/asm/ustack.h13
-rwxr-xr-xarch/ia64/install.sh30
-rw-r--r--arch/ia64/kernel/Makefile46
-rw-r--r--arch/ia64/kernel/Makefile.gate29
-rw-r--r--arch/ia64/kernel/acpi-ext.c101
-rw-r--r--arch/ia64/kernel/acpi.c913
-rw-r--r--arch/ia64/kernel/asm-offsets.c289
-rw-r--r--arch/ia64/kernel/audit.c63
-rw-r--r--arch/ia64/kernel/brl_emu.c217
-rw-r--r--arch/ia64/kernel/crash.c257
-rw-r--r--arch/ia64/kernel/crash_dump.c27
-rw-r--r--arch/ia64/kernel/cyclone.c125
-rw-r--r--arch/ia64/kernel/dma-mapping.c9
-rw-r--r--arch/ia64/kernel/efi.c1360
-rw-r--r--arch/ia64/kernel/efi_stub.S87
-rw-r--r--arch/ia64/kernel/elfcore.c77
-rw-r--r--arch/ia64/kernel/entry.S1427
-rw-r--r--arch/ia64/kernel/entry.h83
-rw-r--r--arch/ia64/kernel/err_inject.c273
-rw-r--r--arch/ia64/kernel/esi.c193
-rw-r--r--arch/ia64/kernel/esi_stub.S99
-rw-r--r--arch/ia64/kernel/fsys.S837
-rw-r--r--arch/ia64/kernel/fsyscall_gtod_data.h30
-rw-r--r--arch/ia64/kernel/ftrace.c196
-rw-r--r--arch/ia64/kernel/gate-data.S3
-rw-r--r--arch/ia64/kernel/gate.S380
-rw-r--r--arch/ia64/kernel/gate.lds.S108
-rw-r--r--arch/ia64/kernel/head.S1167
-rw-r--r--arch/ia64/kernel/iosapic.c1137
-rw-r--r--arch/ia64/kernel/irq.c181
-rw-r--r--arch/ia64/kernel/irq.h3
-rw-r--r--arch/ia64/kernel/irq_ia64.c645
-rw-r--r--arch/ia64/kernel/irq_lsapic.c45
-rw-r--r--arch/ia64/kernel/ivt.S1688
-rw-r--r--arch/ia64/kernel/kprobes.c911
-rw-r--r--arch/ia64/kernel/machine_kexec.c163
-rw-r--r--arch/ia64/kernel/mca.c2111
-rw-r--r--arch/ia64/kernel/mca_asm.S1123
-rw-r--r--arch/ia64/kernel/mca_drv.c796
-rw-r--r--arch/ia64/kernel/mca_drv.h123
-rw-r--r--arch/ia64/kernel/mca_drv_asm.S56
-rw-r--r--arch/ia64/kernel/minstate.h251
-rw-r--r--arch/ia64/kernel/module.c959
-rw-r--r--arch/ia64/kernel/msi_ia64.c198
-rw-r--r--arch/ia64/kernel/numa.c73
-rw-r--r--arch/ia64/kernel/pal.S306
-rw-r--r--arch/ia64/kernel/palinfo.c942
-rw-r--r--arch/ia64/kernel/patch.c237
-rw-r--r--arch/ia64/kernel/pci-dma.c33
-rw-r--r--arch/ia64/kernel/perfmon_itanium.h116
-rw-r--r--arch/ia64/kernel/process.c611
-rw-r--r--arch/ia64/kernel/ptrace.c2012
-rw-r--r--arch/ia64/kernel/relocate_kernel.S321
-rw-r--r--arch/ia64/kernel/sal.c400
-rw-r--r--arch/ia64/kernel/salinfo.c646
-rw-r--r--arch/ia64/kernel/setup.c1081
-rw-r--r--arch/ia64/kernel/sigframe.h26
-rw-r--r--arch/ia64/kernel/signal.c412
-rw-r--r--arch/ia64/kernel/smp.c335
-rw-r--r--arch/ia64/kernel/smpboot.c839
-rw-r--r--arch/ia64/kernel/stacktrace.c40
-rw-r--r--arch/ia64/kernel/sys_ia64.c197
-rw-r--r--arch/ia64/kernel/syscalls/Makefile32
-rw-r--r--arch/ia64/kernel/syscalls/syscall.tbl375
-rw-r--r--arch/ia64/kernel/time.c463
-rw-r--r--arch/ia64/kernel/topology.c410
-rw-r--r--arch/ia64/kernel/traps.c612
-rw-r--r--arch/ia64/kernel/unaligned.c1560
-rw-r--r--arch/ia64/kernel/uncached.c273
-rw-r--r--arch/ia64/kernel/unwind.c2320
-rw-r--r--arch/ia64/kernel/unwind_decoder.c460
-rw-r--r--arch/ia64/kernel/unwind_i.h165
-rw-r--r--arch/ia64/kernel/vmlinux.lds.S224
-rw-r--r--arch/ia64/lib/Makefile48
-rw-r--r--arch/ia64/lib/checksum.c102
-rw-r--r--arch/ia64/lib/clear_page.S79
-rw-r--r--arch/ia64/lib/clear_user.S212
-rw-r--r--arch/ia64/lib/copy_page.S101
-rw-r--r--arch/ia64/lib/copy_page_mck.S188
-rw-r--r--arch/ia64/lib/copy_user.S613
-rw-r--r--arch/ia64/lib/csum_partial_copy.c98
-rw-r--r--arch/ia64/lib/do_csum.S324
-rw-r--r--arch/ia64/lib/flush.S119
-rw-r--r--arch/ia64/lib/idiv32.S86
-rw-r--r--arch/ia64/lib/idiv64.S83
-rw-r--r--arch/ia64/lib/io.c51
-rw-r--r--arch/ia64/lib/ip_fast_csum.S148
-rw-r--r--arch/ia64/lib/memcpy.S304
-rw-r--r--arch/ia64/lib/memcpy_mck.S659
-rw-r--r--arch/ia64/lib/memset.S365
-rw-r--r--arch/ia64/lib/strlen.S195
-rw-r--r--arch/ia64/lib/strncpy_from_user.S47
-rw-r--r--arch/ia64/lib/strnlen_user.S48
-rw-r--r--arch/ia64/lib/xor.S181
-rw-r--r--arch/ia64/mm/Makefile11
-rw-r--r--arch/ia64/mm/contig.c208
-rw-r--r--arch/ia64/mm/discontig.c635
-rw-r--r--arch/ia64/mm/extable.c24
-rw-r--r--arch/ia64/mm/fault.c251
-rw-r--r--arch/ia64/mm/hugetlbpage.c186
-rw-r--r--arch/ia64/mm/init.c532
-rw-r--r--arch/ia64/mm/ioremap.c94
-rw-r--r--arch/ia64/mm/numa.c80
-rw-r--r--arch/ia64/mm/tlb.c591
-rw-r--r--arch/ia64/pci/Makefile5
-rw-r--r--arch/ia64/pci/fixup.c80
-rw-r--r--arch/ia64/pci/pci.c576
-rwxr-xr-xarch/ia64/scripts/check-gas16
-rw-r--r--arch/ia64/scripts/check-gas-asm.S2
-rw-r--r--arch/ia64/scripts/check-model.c1
-rw-r--r--arch/ia64/scripts/check-segrel.S5
-rw-r--r--arch/ia64/scripts/check-segrel.lds13
-rw-r--r--arch/ia64/scripts/check-serialize.S2
-rw-r--r--arch/ia64/scripts/check-text-align.S7
-rwxr-xr-xarch/ia64/scripts/toolchain-flags54
-rw-r--r--arch/ia64/scripts/unwcheck.py65
-rw-r--r--arch/ia64/uv/Makefile12
-rw-r--r--arch/ia64/uv/kernel/Makefile12
-rw-r--r--arch/ia64/uv/kernel/setup.c120
-rw-r--r--arch/loongarch/Kbuild2
-rw-r--r--arch/loongarch/Kconfig7
-rw-r--r--arch/loongarch/Makefile11
-rw-r--r--arch/loongarch/configs/loongson3_defconfig2
-rw-r--r--arch/loongarch/crypto/crc32-loongarch.c2
-rw-r--r--arch/loongarch/include/asm/asmmacro.h3
-rw-r--r--arch/loongarch/include/asm/atomic.h88
-rw-r--r--arch/loongarch/include/asm/efi.h2
-rw-r--r--arch/loongarch/include/asm/elf.h2
-rw-r--r--arch/loongarch/include/asm/inst.h29
-rw-r--r--arch/loongarch/include/asm/io.h5
-rw-r--r--arch/loongarch/include/asm/kvm_csr.h211
-rw-r--r--arch/loongarch/include/asm/kvm_host.h237
-rw-r--r--arch/loongarch/include/asm/kvm_mmu.h139
-rw-r--r--arch/loongarch/include/asm/kvm_types.h11
-rw-r--r--arch/loongarch/include/asm/kvm_vcpu.h93
-rw-r--r--arch/loongarch/include/asm/linkage.h8
-rw-r--r--arch/loongarch/include/asm/local.h27
-rw-r--r--arch/loongarch/include/asm/loongarch.h24
-rw-r--r--arch/loongarch/include/asm/percpu.h13
-rw-r--r--arch/loongarch/include/asm/pgalloc.h1
-rw-r--r--arch/loongarch/include/asm/pgtable-bits.h4
-rw-r--r--arch/loongarch/include/asm/setup.h2
-rw-r--r--arch/loongarch/include/uapi/asm/kvm.h108
-rw-r--r--arch/loongarch/kernel/Makefile2
-rw-r--r--arch/loongarch/kernel/asm-offsets.c32
-rw-r--r--arch/loongarch/kernel/efi.c8
-rw-r--r--arch/loongarch/kernel/entry.S4
-rw-r--r--arch/loongarch/kernel/genex.S16
-rw-r--r--arch/loongarch/kernel/image-vars.h2
-rw-r--r--arch/loongarch/kernel/relocate.c10
-rw-r--r--arch/loongarch/kernel/setup.c17
-rw-r--r--arch/loongarch/kernel/smp.c3
-rw-r--r--arch/loongarch/kernel/stacktrace.c2
-rw-r--r--arch/loongarch/kernel/time.c23
-rw-r--r--arch/loongarch/kernel/unwind.c1
-rw-r--r--arch/loongarch/kernel/unwind_prologue.c2
-rw-r--r--arch/loongarch/kvm/Kconfig40
-rw-r--r--arch/loongarch/kvm/Makefile22
-rw-r--r--arch/loongarch/kvm/exit.c696
-rw-r--r--arch/loongarch/kvm/interrupt.c183
-rw-r--r--arch/loongarch/kvm/main.c420
-rw-r--r--arch/loongarch/kvm/mmu.c914
-rw-r--r--arch/loongarch/kvm/switch.S250
-rw-r--r--arch/loongarch/kvm/timer.c197
-rw-r--r--arch/loongarch/kvm/tlb.c32
-rw-r--r--arch/loongarch/kvm/trace.h162
-rw-r--r--arch/loongarch/kvm/vcpu.c939
-rw-r--r--arch/loongarch/kvm/vm.c94
-rw-r--r--arch/loongarch/mm/init.c9
-rw-r--r--arch/loongarch/mm/pgtable.c4
-rw-r--r--arch/loongarch/mm/tlbex.S36
-rw-r--r--arch/loongarch/net/bpf_jit.c161
-rw-r--r--arch/loongarch/vdso/Makefile10
-rw-r--r--arch/m68k/68000/entry.S7
-rw-r--r--arch/m68k/68000/ints.c5
-rw-r--r--arch/m68k/68000/ints.h7
-rw-r--r--arch/m68k/68000/timers.c2
-rw-r--r--arch/m68k/Kconfig9
-rw-r--r--arch/m68k/Kconfig.cpu12
-rw-r--r--arch/m68k/Kconfig.machine4
-rw-r--r--arch/m68k/amiga/amiga.h5
-rw-r--r--arch/m68k/amiga/amisound.c2
-rw-r--r--arch/m68k/amiga/config.c4
-rw-r--r--arch/m68k/amiga/pcmcia.c3
-rw-r--r--arch/m68k/apollo/apollo.h4
-rw-r--r--arch/m68k/apollo/config.c45
-rw-r--r--arch/m68k/apollo/dn_ints.c8
-rw-r--r--arch/m68k/atari/ataints.c3
-rw-r--r--arch/m68k/atari/atakeyb.c2
-rw-r--r--arch/m68k/atari/atari.h15
-rw-r--r--arch/m68k/atari/atasound.c1
-rw-r--r--arch/m68k/atari/config.c13
-rw-r--r--arch/m68k/atari/stdma.c1
-rw-r--r--arch/m68k/atari/stram.c2
-rw-r--r--arch/m68k/atari/time.c2
-rw-r--r--arch/m68k/bvme6000/config.c7
-rw-r--r--arch/m68k/coldfire/entry.S7
-rw-r--r--arch/m68k/coldfire/intc.c4
-rw-r--r--arch/m68k/coldfire/vectors.c2
-rw-r--r--arch/m68k/coldfire/vectors.h3
-rw-r--r--arch/m68k/configs/amiga_defconfig1
-rw-r--r--arch/m68k/configs/apollo_defconfig2
-rw-r--r--arch/m68k/configs/atari_defconfig1
-rw-r--r--arch/m68k/configs/bvme6000_defconfig2
-rw-r--r--arch/m68k/configs/hp300_defconfig2
-rw-r--r--arch/m68k/configs/mac_defconfig1
-rw-r--r--arch/m68k/configs/multi_defconfig1
-rw-r--r--arch/m68k/configs/mvme147_defconfig2
-rw-r--r--arch/m68k/configs/mvme16x_defconfig2
-rw-r--r--arch/m68k/configs/q40_defconfig1
-rw-r--r--arch/m68k/configs/sun3_defconfig2
-rw-r--r--arch/m68k/configs/sun3x_defconfig2
-rw-r--r--arch/m68k/configs/virt_defconfig3
-rw-r--r--arch/m68k/emu/natfeat.c9
-rw-r--r--arch/m68k/emu/nfeth.c2
-rw-r--r--arch/m68k/fpsp040/slogn.S88
-rw-r--r--arch/m68k/hp300/time.c2
-rw-r--r--arch/m68k/ifpsp060/Makefile6
-rw-r--r--arch/m68k/include/asm/bitops.h21
-rw-r--r--arch/m68k/include/asm/dvma.h8
-rw-r--r--arch/m68k/include/asm/fb.h19
-rw-r--r--arch/m68k/include/asm/io_mm.h24
-rw-r--r--arch/m68k/include/asm/irq.h5
-rw-r--r--arch/m68k/include/asm/kexec.h4
-rw-r--r--arch/m68k/include/asm/mcfgpio.h8
-rw-r--r--arch/m68k/include/asm/nettel.h5
-rw-r--r--arch/m68k/include/asm/oplib.h4
-rw-r--r--arch/m68k/include/asm/page_mm.h45
-rw-r--r--arch/m68k/include/asm/pgtable.h9
-rw-r--r--arch/m68k/include/asm/pgtable_no.h1
-rw-r--r--arch/m68k/include/asm/raw_io.h32
-rw-r--r--arch/m68k/include/asm/sun3_pgalloc.h10
-rw-r--r--arch/m68k/include/asm/syscalls.h19
-rw-r--r--arch/m68k/include/asm/tlbflush.h73
-rw-r--r--arch/m68k/kernel/Makefile4
-rw-r--r--arch/m68k/kernel/dma.c34
-rw-r--r--arch/m68k/kernel/early_printk.c4
-rw-r--r--arch/m68k/kernel/entry.S7
-rw-r--r--arch/m68k/kernel/head.S8
-rw-r--r--arch/m68k/kernel/ints.c2
-rw-r--r--arch/m68k/kernel/ints.h7
-rw-r--r--arch/m68k/kernel/process.c1
-rw-r--r--arch/m68k/kernel/process.h8
-rw-r--r--arch/m68k/kernel/ptrace.c2
-rw-r--r--arch/m68k/kernel/ptrace.h6
-rw-r--r--arch/m68k/kernel/setup_mm.c2
-rw-r--r--arch/m68k/kernel/signal.c4
-rw-r--r--arch/m68k/kernel/signal.h7
-rw-r--r--arch/m68k/kernel/sys_m68k.c4
-rw-r--r--arch/m68k/kernel/syscalls/syscall.tbl6
-rw-r--r--arch/m68k/kernel/traps.c19
-rw-r--r--arch/m68k/kernel/traps.h10
-rw-r--r--arch/m68k/kernel/uboot.c13
-rw-r--r--arch/m68k/kernel/vectors.c3
-rw-r--r--arch/m68k/kernel/vectors.h3
-rw-r--r--arch/m68k/lib/Makefile3
-rw-r--r--arch/m68k/lib/ashldi3.c61
-rw-r--r--arch/m68k/lib/ashrdi3.c62
-rw-r--r--arch/m68k/lib/lshrdi3.c61
-rw-r--r--arch/m68k/lib/muldi3.c1
-rw-r--r--arch/m68k/mac/baboon.c2
-rw-r--r--arch/m68k/mac/config.c14
-rw-r--r--arch/m68k/mac/iop.c2
-rw-r--r--arch/m68k/mac/mac.h25
-rw-r--r--arch/m68k/mac/macboing.c11
-rw-r--r--arch/m68k/mac/misc.c5
-rw-r--r--arch/m68k/mac/oss.c2
-rw-r--r--arch/m68k/mac/psc.c2
-rw-r--r--arch/m68k/mac/via.c2
-rw-r--r--arch/m68k/math-emu/fp_arith.c49
-rw-r--r--arch/m68k/math-emu/fp_arith.h49
-rw-r--r--arch/m68k/math-emu/fp_log.c46
-rw-r--r--arch/m68k/math-emu/fp_log.h44
-rw-r--r--arch/m68k/math-emu/fp_trig.c54
-rw-r--r--arch/m68k/math-emu/fp_trig.h25
-rw-r--r--arch/m68k/math-emu/multi_arith.h8
-rw-r--r--arch/m68k/mm/fault.c2
-rw-r--r--arch/m68k/mm/fault.h7
-rw-r--r--arch/m68k/mm/hwtest.c2
-rw-r--r--arch/m68k/mm/mcfmmu.c3
-rw-r--r--arch/m68k/mm/sun3kmap.c6
-rw-r--r--arch/m68k/mm/sun3mmu.c2
-rw-r--r--arch/m68k/mvme147/config.c7
-rw-r--r--arch/m68k/mvme16x/config.c10
-rw-r--r--arch/m68k/mvme16x/mvme16x.h6
-rw-r--r--arch/m68k/q40/config.c11
-rw-r--r--arch/m68k/q40/q40.h6
-rw-r--r--arch/m68k/q40/q40ints.c2
-rw-r--r--arch/m68k/sun3/config.c13
-rw-r--r--arch/m68k/sun3/idprom.c4
-rw-r--r--arch/m68k/sun3/intersil.c1
-rw-r--r--arch/m68k/sun3/leds.c2
-rw-r--r--arch/m68k/sun3/mmu_emu.c43
-rw-r--r--arch/m68k/sun3/prom/printf.c5
-rw-r--r--arch/m68k/sun3/sun3.h22
-rw-r--r--arch/m68k/sun3/sun3dvma.c17
-rw-r--r--arch/m68k/sun3/sun3ints.c12
-rw-r--r--arch/m68k/sun3x/config.c6
-rw-r--r--arch/m68k/sun3x/dvma.c5
-rw-r--r--arch/m68k/sun3x/prom.c2
-rw-r--r--arch/microblaze/kernel/syscalls/syscall.tbl6
-rw-r--r--arch/mips/Kbuild.platforms1
-rw-r--r--arch/mips/Kconfig24
-rw-r--r--arch/mips/Makefile.postlink3
-rw-r--r--arch/mips/ar7/Makefile11
-rw-r--r--arch/mips/ar7/Platform5
-rw-r--r--arch/mips/ar7/clock.c439
-rw-r--r--arch/mips/ar7/gpio.c332
-rw-r--r--arch/mips/ar7/irq.c165
-rw-r--r--arch/mips/ar7/memory.c51
-rw-r--r--arch/mips/ar7/platform.c722
-rw-r--r--arch/mips/ar7/prom.c256
-rw-r--r--arch/mips/ar7/setup.c93
-rw-r--r--arch/mips/ar7/time.c31
-rw-r--r--arch/mips/boot/compressed/uart-16550.c5
-rw-r--r--arch/mips/boot/dts/ingenic/jz4725b.dtsi1
-rw-r--r--arch/mips/boot/dts/ingenic/jz4770.dtsi1
-rw-r--r--arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi3
-rw-r--r--arch/mips/boot/dts/loongson/ls7a-pch.dtsi3
-rw-r--r--arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc1.dts2
-rw-r--r--arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts2
-rw-r--r--arch/mips/boot/dts/ralink/mt7621.dtsi5
-rw-r--r--arch/mips/cavium-octeon/smp.c4
-rw-r--r--arch/mips/configs/ar7_defconfig119
-rw-r--r--arch/mips/configs/fuloong2e_defconfig1
-rw-r--r--arch/mips/configs/jazz_defconfig4
-rw-r--r--arch/mips/configs/lemote2f_defconfig3
-rw-r--r--arch/mips/configs/malta_defconfig5
-rw-r--r--arch/mips/configs/malta_kvm_defconfig5
-rw-r--r--arch/mips/configs/maltaup_xpa_defconfig5
-rw-r--r--arch/mips/configs/rm200_defconfig4
-rw-r--r--arch/mips/crypto/crc32-mips.c2
-rw-r--r--arch/mips/include/asm/bitops.h25
-rw-r--r--arch/mips/include/asm/fb.h11
-rw-r--r--arch/mips/include/asm/kexec.h2
-rw-r--r--arch/mips/include/asm/kprobes.h2
-rw-r--r--arch/mips/include/asm/local.h27
-rw-r--r--arch/mips/include/asm/mach-ar7/ar7.h191
-rw-r--r--arch/mips/include/asm/mach-ar7/irq.h16
-rw-r--r--arch/mips/include/asm/mach-ar7/prom.h12
-rw-r--r--arch/mips/include/asm/mach-ar7/spaces.h22
-rw-r--r--arch/mips/include/asm/mach-loongson32/dma.h21
-rw-r--r--arch/mips/include/asm/mach-loongson32/nand.h26
-rw-r--r--arch/mips/include/asm/mach-loongson32/platform.h3
-rw-r--r--arch/mips/include/asm/mach-loongson64/boot_param.h9
-rw-r--r--arch/mips/include/asm/pgalloc.h1
-rw-r--r--arch/mips/include/asm/smp-ops.h2
-rw-r--r--arch/mips/include/asm/smp.h2
-rw-r--r--arch/mips/jazz/setup.c9
-rw-r--r--arch/mips/kernel/Makefile2
-rw-r--r--arch/mips/kernel/process.c25
-rw-r--r--arch/mips/kernel/relocate_kernel.S1
-rw-r--r--arch/mips/kernel/setup.c14
-rw-r--r--arch/mips/kernel/smp-bmips.c4
-rw-r--r--arch/mips/kernel/smp-cps.c10
-rw-r--r--arch/mips/kernel/smp.c4
-rw-r--r--arch/mips/kernel/syscalls/syscall_n32.tbl6
-rw-r--r--arch/mips/kernel/syscalls/syscall_n64.tbl6
-rw-r--r--arch/mips/kernel/syscalls/syscall_o32.tbl6
-rw-r--r--arch/mips/kvm/mmu.c3
-rw-r--r--arch/mips/lib/bitops.c14
-rw-r--r--arch/mips/loongson32/common/platform.c2
-rw-r--r--arch/mips/loongson32/ls1b/board.c2
-rw-r--r--arch/mips/loongson64/env.c10
-rw-r--r--arch/mips/loongson64/init.c47
-rw-r--r--arch/mips/loongson64/reset.c4
-rw-r--r--arch/mips/loongson64/smp.c2
-rw-r--r--arch/mips/mm/cache.c2
-rw-r--r--arch/mips/mti-malta/malta-setup.c4
-rw-r--r--arch/mips/pci/fixup-lantiq.c2
-rw-r--r--arch/mips/sibyte/swarm/setup.c27
-rw-r--r--arch/mips/sni/setup.c18
-rw-r--r--arch/nios2/kernel/setup.c5
-rw-r--r--arch/parisc/Kconfig15
-rw-r--r--arch/parisc/Makefile8
-rw-r--r--arch/parisc/boot/Makefile2
-rw-r--r--arch/parisc/configs/generic-64bit_defconfig1
-rw-r--r--arch/parisc/include/asm/alternative.h9
-rw-r--r--arch/parisc/include/asm/assembly.h1
-rw-r--r--arch/parisc/include/asm/bug.h38
-rw-r--r--arch/parisc/include/asm/elf.h10
-rw-r--r--arch/parisc/include/asm/jump_label.h8
-rw-r--r--arch/parisc/include/asm/ldcw.h2
-rw-r--r--arch/parisc/include/asm/processor.h3
-rw-r--r--arch/parisc/include/asm/uaccess.h1
-rw-r--r--arch/parisc/include/uapi/asm/errno.h2
-rw-r--r--arch/parisc/include/uapi/asm/pdc.h28
-rw-r--r--arch/parisc/kernel/drivers.c4
-rw-r--r--arch/parisc/kernel/entry.S88
-rw-r--r--arch/parisc/kernel/firmware.c14
-rw-r--r--arch/parisc/kernel/head.S5
-rw-r--r--arch/parisc/kernel/processor.c8
-rw-r--r--arch/parisc/kernel/setup.c3
-rw-r--r--arch/parisc/kernel/smp.c8
-rw-r--r--arch/parisc/kernel/sys_parisc.c2
-rw-r--r--arch/parisc/kernel/syscalls/syscall.tbl6
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S1
-rw-r--r--arch/powerpc/Kconfig3
-rw-r--r--arch/powerpc/Kconfig.debug14
-rw-r--r--arch/powerpc/Makefile.postlink3
-rwxr-xr-xarch/powerpc/boot/install.sh16
-rw-r--r--arch/powerpc/configs/44x/sam440ep_defconfig1
-rw-r--r--arch/powerpc/configs/debug.config4
-rw-r--r--arch/powerpc/configs/g5_defconfig4
-rw-r--r--arch/powerpc/configs/hardening.config10
-rw-r--r--arch/powerpc/configs/pmac32_defconfig2
-rw-r--r--arch/powerpc/configs/ppc64e_defconfig4
-rw-r--r--arch/powerpc/configs/ppc6xx_defconfig5
-rw-r--r--arch/powerpc/configs/skiroot_defconfig1
-rw-r--r--arch/powerpc/include/asm/bitops.h21
-rw-r--r--arch/powerpc/include/asm/book3s/32/pgtable.h83
-rw-r--r--arch/powerpc/include/asm/book3s/32/tlbflush.h2
-rw-r--r--arch/powerpc/include/asm/book3s/64/pgtable.h37
-rw-r--r--arch/powerpc/include/asm/book3s/pgtable.h33
-rw-r--r--arch/powerpc/include/asm/code-patching.h1
-rw-r--r--arch/powerpc/include/asm/cpm1.h5
-rw-r--r--arch/powerpc/include/asm/cpm2.h4
-rw-r--r--arch/powerpc/include/asm/fb.h13
-rw-r--r--arch/powerpc/include/asm/fixmap.h16
-rw-r--r--arch/powerpc/include/asm/guest-state-buffer.h995
-rw-r--r--arch/powerpc/include/asm/hvcall.h30
-rw-r--r--arch/powerpc/include/asm/imc-pmu.h16
-rw-r--r--arch/powerpc/include/asm/io.h2
-rw-r--r--arch/powerpc/include/asm/kexec.h8
-rw-r--r--arch/powerpc/include/asm/kprobes.h2
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h220
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_64.h8
-rw-r--r--arch/powerpc/include/asm/kvm_booke.h10
-rw-r--r--arch/powerpc/include/asm/kvm_host.h22
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h110
-rw-r--r--arch/powerpc/include/asm/local.h12
-rw-r--r--arch/powerpc/include/asm/machdep.h13
-rw-r--r--arch/powerpc/include/asm/nohash/32/mmu-8xx.h1
-rw-r--r--arch/powerpc/include/asm/nohash/32/pgtable.h201
-rw-r--r--arch/powerpc/include/asm/nohash/32/pte-40x.h21
-rw-r--r--arch/powerpc/include/asm/nohash/32/pte-44x.h20
-rw-r--r--arch/powerpc/include/asm/nohash/32/pte-85xx.h20
-rw-r--r--arch/powerpc/include/asm/nohash/32/pte-8xx.h99
-rw-r--r--arch/powerpc/include/asm/nohash/64/pgtable.h120
-rw-r--r--arch/powerpc/include/asm/nohash/pgtable.h215
-rw-r--r--arch/powerpc/include/asm/nohash/pte-e500.h41
-rw-r--r--arch/powerpc/include/asm/opal.h2
-rw-r--r--arch/powerpc/include/asm/paravirt.h47
-rw-r--r--arch/powerpc/include/asm/pci.h4
-rw-r--r--arch/powerpc/include/asm/pgtable-masks.h32
-rw-r--r--arch/powerpc/include/asm/pgtable.h41
-rw-r--r--arch/powerpc/include/asm/plpar_wrappers.h267
-rw-r--r--arch/powerpc/include/asm/ptrace.h17
-rw-r--r--arch/powerpc/include/asm/uaccess.h2
-rw-r--r--arch/powerpc/kernel/btext.c360
-rw-r--r--arch/powerpc/kernel/crash_dump.c12
-rw-r--r--arch/powerpc/kernel/eeh_driver.c4
-rw-r--r--arch/powerpc/kernel/entry_32.S8
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S6
-rw-r--r--arch/powerpc/kernel/fadump.c2
-rw-r--r--arch/powerpc/kernel/fpu.S13
-rw-r--r--arch/powerpc/kernel/head_40x.S19
-rw-r--r--arch/powerpc/kernel/head_44x.S40
-rw-r--r--arch/powerpc/kernel/head_85xx.S14
-rw-r--r--arch/powerpc/kernel/head_book3s_32.S63
-rw-r--r--arch/powerpc/kernel/idle.c1
-rw-r--r--arch/powerpc/kernel/io.c12
-rw-r--r--arch/powerpc/kernel/iommu.c61
-rw-r--r--arch/powerpc/kernel/paca.c2
-rw-r--r--arch/powerpc/kernel/pci-common.c3
-rw-r--r--arch/powerpc/kernel/process.c32
-rw-r--r--arch/powerpc/kernel/prom_init.c2
-rw-r--r--arch/powerpc/kernel/ptrace/ptrace.c5
-rw-r--r--arch/powerpc/kernel/rtas-proc.c2
-rw-r--r--arch/powerpc/kernel/setup-common.c19
-rw-r--r--arch/powerpc/kernel/setup_64.c2
-rw-r--r--arch/powerpc/kernel/signal.c5
-rw-r--r--arch/powerpc/kernel/signal.h7
-rw-r--r--arch/powerpc/kernel/smp.c6
-rw-r--r--arch/powerpc/kernel/syscalls/syscall.tbl6
-rw-r--r--arch/powerpc/kernel/trace/ftrace_entry.S4
-rw-r--r--arch/powerpc/kernel/traps.c6
-rw-r--r--arch/powerpc/kernel/vector.S2
-rw-r--r--arch/powerpc/kexec/core.c5
-rw-r--r--arch/powerpc/kexec/core_64.c4
-rw-r--r--arch/powerpc/kexec/file_load_64.c14
-rw-r--r--arch/powerpc/kvm/Makefile4
-rw-r--r--arch/powerpc/kvm/book3s.c38
-rw-r--r--arch/powerpc/kvm/book3s_64_entry.S2
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_hv.c7
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_radix.c31
-rw-r--r--arch/powerpc/kvm/book3s_64_vio.c12
-rw-r--r--arch/powerpc/kvm/book3s_hv.c358
-rw-r--r--arch/powerpc/kvm/book3s_hv.h76
-rw-r--r--arch/powerpc/kvm/book3s_hv_builtin.c11
-rw-r--r--arch/powerpc/kvm/book3s_hv_nested.c44
-rw-r--r--arch/powerpc/kvm/book3s_hv_nestedv2.c994
-rw-r--r--arch/powerpc/kvm/book3s_hv_p9_entry.c4
-rw-r--r--arch/powerpc/kvm/book3s_hv_ras.c4
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_mmu.c8
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_xics.c4
-rw-r--r--arch/powerpc/kvm/book3s_hv_uvmem.c2
-rw-r--r--arch/powerpc/kvm/book3s_xive.c12
-rw-r--r--arch/powerpc/kvm/book3s_xive_native.c2
-rw-r--r--arch/powerpc/kvm/emulate_loadstore.c6
-rw-r--r--arch/powerpc/kvm/guest-state-buffer.c621
-rw-r--r--arch/powerpc/kvm/powerpc.c76
-rw-r--r--arch/powerpc/kvm/test-guest-state-buffer.c328
-rw-r--r--arch/powerpc/lib/code-patching.c146
-rw-r--r--arch/powerpc/lib/qspinlock.c119
-rw-r--r--arch/powerpc/mm/book3s32/hash_low.S32
-rw-r--r--arch/powerpc/mm/book3s32/mmu.c6
-rw-r--r--arch/powerpc/mm/book3s64/pgtable.c10
-rw-r--r--arch/powerpc/mm/book3s64/radix_tlb.c9
-rw-r--r--arch/powerpc/mm/drmem.c2
-rw-r--r--arch/powerpc/mm/fault.c9
-rw-r--r--arch/powerpc/mm/init_32.c1
-rw-r--r--arch/powerpc/mm/ioremap.c6
-rw-r--r--arch/powerpc/mm/mem.c10
-rw-r--r--arch/powerpc/mm/nohash/40x.c19
-rw-r--r--arch/powerpc/mm/nohash/8xx.c2
-rw-r--r--arch/powerpc/mm/nohash/book3e_pgtable.c2
-rw-r--r--arch/powerpc/mm/nohash/e500.c6
-rw-r--r--arch/powerpc/mm/nohash/e500_hugetlbpage.c3
-rw-r--r--arch/powerpc/mm/nohash/kaslr_booke.c2
-rw-r--r--arch/powerpc/mm/pgtable.c58
-rw-r--r--arch/powerpc/mm/ptdump/8xx.c5
-rw-r--r--arch/powerpc/mm/ptdump/shared.c14
-rw-r--r--arch/powerpc/net/bpf_jit.h18
-rw-r--r--arch/powerpc/net/bpf_jit_comp.c149
-rw-r--r--arch/powerpc/net/bpf_jit_comp32.c15
-rw-r--r--arch/powerpc/net/bpf_jit_comp64.c10
-rw-r--r--arch/powerpc/perf/core-book3s.c5
-rw-r--r--arch/powerpc/perf/hv-24x7.c2
-rw-r--r--arch/powerpc/perf/imc-pmu.c13
-rw-r--r--arch/powerpc/perf/power6-pmu.c46
-rw-r--r--arch/powerpc/platforms/4xx/soc.c2
-rw-r--r--arch/powerpc/platforms/83xx/misc.c2
-rw-r--r--arch/powerpc/platforms/8xx/cpm1.c1
-rw-r--r--arch/powerpc/platforms/book3s/vas-api.c34
-rw-r--r--arch/powerpc/platforms/cell/spufs/coredump.c11
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c2
-rw-r--r--arch/powerpc/platforms/powermac/Kconfig1
-rw-r--r--arch/powerpc/platforms/powermac/feature.c3
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c4
-rw-r--r--arch/powerpc/platforms/powermac/smp.c4
-rw-r--r--arch/powerpc/platforms/powernv/opal-fadump.h2
-rw-r--r--arch/powerpc/platforms/pseries/Kconfig6
-rw-r--r--arch/powerpc/platforms/pseries/Makefile1
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c3
-rw-r--r--arch/powerpc/platforms/pseries/hvCall.S8
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c8
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c12
-rw-r--r--arch/powerpc/platforms/pseries/mobility.c1
-rw-r--r--arch/powerpc/platforms/pseries/plpks.c4
-rw-r--r--arch/powerpc/platforms/pseries/plpks_sed_ops.c131
-rw-r--r--arch/powerpc/platforms/pseries/rtas-work-area.c1
-rw-r--r--arch/powerpc/platforms/pseries/vas.c55
-rw-r--r--arch/powerpc/platforms/pseries/vas.h2
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c10
-rw-r--r--arch/powerpc/sysdev/mpic.c2
-rw-r--r--arch/powerpc/sysdev/xive/native.c2
-rwxr-xr-xarch/powerpc/tools/gcc-check-mprofile-kernel.sh11
-rw-r--r--arch/riscv/Kconfig29
-rw-r--r--arch/riscv/Kconfig.debug1
-rw-r--r--arch/riscv/Kconfig.errata1
-rw-r--r--arch/riscv/Kconfig.socs6
-rw-r--r--arch/riscv/Makefile14
-rw-r--r--arch/riscv/Makefile.postlink3
-rw-r--r--arch/riscv/boot/Makefile1
-rw-r--r--arch/riscv/boot/dts/Makefile1
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-common-regulators.dtsi2
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1-dongshan-nezha-stu.dts2
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-480p.dts2
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-720p.dts2
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel.dtsi2
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts2
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv.dts2
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1-mangopi-mq-pro.dts2
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts2
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi2
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1s-mangopi-mq.dts2
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1s.dtsi45
-rw-r--r--arch/riscv/boot/dts/allwinner/sunxi-d1-t113.dtsi2
-rw-r--r--arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi2
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts7
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-m100pfsevp.dts7
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-polarberry.dts7
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-sev-kit.dts7
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-tysom-m.dts7
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs.dtsi16
-rw-r--r--arch/riscv/boot/dts/renesas/r9a07g043f.dtsi13
-rw-r--r--arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi23
-rw-r--r--arch/riscv/boot/dts/renesas/rzfive-smarc.dtsi56
-rw-r--r--arch/riscv/boot/dts/sifive/fu540-c000.dtsi15
-rw-r--r--arch/riscv/boot/dts/sifive/fu740-c000.dtsi15
-rw-r--r--arch/riscv/boot/dts/sophgo/Makefile3
-rw-r--r--arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts38
-rw-r--r--arch/riscv/boot/dts/sophgo/cv1800b.dtsi122
-rw-r--r--arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi2000
-rw-r--r--arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts19
-rw-r--r--arch/riscv/boot/dts/sophgo/sg2042.dtsi325
-rw-r--r--arch/riscv/boot/dts/starfive/jh7100.dtsi6
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-pinfunc.h4
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi113
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110.dtsi93
-rw-r--r--arch/riscv/boot/dts/thead/th1520.dtsi13
-rw-r--r--arch/riscv/configs/defconfig57
-rw-r--r--arch/riscv/errata/andes/Makefile4
-rw-r--r--arch/riscv/errata/andes/errata.c20
-rw-r--r--arch/riscv/include/asm/acpi.h6
-rw-r--r--arch/riscv/include/asm/asm-prototypes.h1
-rw-r--r--arch/riscv/include/asm/asm.h41
-rw-r--r--arch/riscv/include/asm/bitops.h266
-rw-r--r--arch/riscv/include/asm/cpufeature.h103
-rw-r--r--arch/riscv/include/asm/crash_core.h11
-rw-r--r--arch/riscv/include/asm/csr.h18
-rw-r--r--arch/riscv/include/asm/elf.h2
-rw-r--r--arch/riscv/include/asm/entry-common.h14
-rw-r--r--arch/riscv/include/asm/errata_list.h20
-rw-r--r--arch/riscv/include/asm/ftrace.h21
-rw-r--r--arch/riscv/include/asm/hwcap.h77
-rw-r--r--arch/riscv/include/asm/hwprobe.h7
-rw-r--r--arch/riscv/include/asm/insn-def.h8
-rw-r--r--arch/riscv/include/asm/irq_stack.h3
-rw-r--r--arch/riscv/include/asm/kprobes.h11
-rw-r--r--arch/riscv/include/asm/kvm_host.h18
-rw-r--r--arch/riscv/include/asm/kvm_vcpu_sbi.h7
-rw-r--r--arch/riscv/include/asm/page.h4
-rw-r--r--arch/riscv/include/asm/pgtable-32.h3
-rw-r--r--arch/riscv/include/asm/pgtable-64.h14
-rw-r--r--arch/riscv/include/asm/pgtable-bits.h4
-rw-r--r--arch/riscv/include/asm/pgtable.h6
-rw-r--r--arch/riscv/include/asm/processor.h11
-rw-r--r--arch/riscv/include/asm/sbi.h10
-rw-r--r--arch/riscv/include/asm/scs.h54
-rw-r--r--arch/riscv/include/asm/switch_to.h2
-rw-r--r--arch/riscv/include/asm/thread_info.h16
-rw-r--r--arch/riscv/include/asm/tlb.h8
-rw-r--r--arch/riscv/include/asm/tlbflush.h15
-rw-r--r--arch/riscv/include/asm/uprobes.h13
-rw-r--r--arch/riscv/include/asm/vdso/processor.h2
-rw-r--r--arch/riscv/include/asm/vector.h2
-rw-r--r--arch/riscv/include/uapi/asm/elf.h5
-rw-r--r--arch/riscv/include/uapi/asm/hwprobe.h4
-rw-r--r--arch/riscv/include/uapi/asm/kvm.h12
-rw-r--r--arch/riscv/kernel/Makefile3
-rw-r--r--arch/riscv/kernel/acpi.c87
-rw-r--r--arch/riscv/kernel/asm-offsets.c9
-rw-r--r--arch/riscv/kernel/compat_vdso/Makefile10
-rw-r--r--arch/riscv/kernel/copy-unaligned.S8
-rw-r--r--arch/riscv/kernel/cpu.c33
-rw-r--r--arch/riscv/kernel/cpufeature.c111
-rw-r--r--arch/riscv/kernel/crash_core.c4
-rw-r--r--arch/riscv/kernel/entry.S141
-rw-r--r--arch/riscv/kernel/fpu.S129
-rw-r--r--arch/riscv/kernel/head.S49
-rw-r--r--arch/riscv/kernel/hibernate-asm.S12
-rw-r--r--arch/riscv/kernel/image-vars.h2
-rw-r--r--arch/riscv/kernel/irq.c60
-rw-r--r--arch/riscv/kernel/kexec_relocate.S52
-rw-r--r--arch/riscv/kernel/mcount-dyn.S20
-rw-r--r--arch/riscv/kernel/mcount.S18
-rw-r--r--arch/riscv/kernel/module.c662
-rw-r--r--arch/riscv/kernel/probes/rethook_trampoline.S4
-rw-r--r--arch/riscv/kernel/probes/simulate-insn.c2
-rw-r--r--arch/riscv/kernel/probes/uprobes.c6
-rw-r--r--arch/riscv/kernel/process.c18
-rw-r--r--arch/riscv/kernel/sbi.c32
-rw-r--r--arch/riscv/kernel/setup.c29
-rw-r--r--arch/riscv/kernel/signal.c92
-rw-r--r--arch/riscv/kernel/smpboot.c5
-rw-r--r--arch/riscv/kernel/suspend_entry.S9
-rw-r--r--arch/riscv/kernel/sys_riscv.c46
-rw-r--r--arch/riscv/kernel/tests/Kconfig.debug35
-rw-r--r--arch/riscv/kernel/tests/Makefile1
-rw-r--r--arch/riscv/kernel/tests/module_test/Makefile15
-rw-r--r--arch/riscv/kernel/tests/module_test/test_module_linking_main.c88
-rw-r--r--arch/riscv/kernel/tests/module_test/test_set16.S23
-rw-r--r--arch/riscv/kernel/tests/module_test/test_set32.S20
-rw-r--r--arch/riscv/kernel/tests/module_test/test_set6.S23
-rw-r--r--arch/riscv/kernel/tests/module_test/test_set8.S23
-rw-r--r--arch/riscv/kernel/tests/module_test/test_sub16.S20
-rw-r--r--arch/riscv/kernel/tests/module_test/test_sub32.S20
-rw-r--r--arch/riscv/kernel/tests/module_test/test_sub6.S20
-rw-r--r--arch/riscv/kernel/tests/module_test/test_sub64.S25
-rw-r--r--arch/riscv/kernel/tests/module_test/test_sub8.S20
-rw-r--r--arch/riscv/kernel/tests/module_test/test_uleb128.S31
-rw-r--r--arch/riscv/kernel/traps.c126
-rw-r--r--arch/riscv/kernel/traps_misaligned.c381
-rw-r--r--arch/riscv/kernel/vdso/Makefile12
-rw-r--r--arch/riscv/kernel/vdso/flush_icache.S4
-rw-r--r--arch/riscv/kernel/vdso/getcpu.S4
-rw-r--r--arch/riscv/kernel/vdso/hwprobe.c2
-rw-r--r--arch/riscv/kernel/vdso/rt_sigreturn.S4
-rw-r--r--arch/riscv/kernel/vdso/sys_hwprobe.S4
-rw-r--r--arch/riscv/kernel/vdso/vdso.lds.S30
-rw-r--r--arch/riscv/kernel/vector.c1
-rw-r--r--arch/riscv/kvm/aia.c2
-rw-r--r--arch/riscv/kvm/main.c2
-rw-r--r--arch/riscv/kvm/tlb.c2
-rw-r--r--arch/riscv/kvm/vcpu.c76
-rw-r--r--arch/riscv/kvm/vcpu_fp.c2
-rw-r--r--arch/riscv/kvm/vcpu_onereg.c74
-rw-r--r--arch/riscv/kvm/vcpu_sbi.c61
-rw-r--r--arch/riscv/kvm/vcpu_sbi_replace.c32
-rw-r--r--arch/riscv/kvm/vcpu_vector.c2
-rw-r--r--arch/riscv/lib/clear_page.S32
-rw-r--r--arch/riscv/lib/memcpy.S6
-rw-r--r--arch/riscv/lib/memmove.S57
-rw-r--r--arch/riscv/lib/memset.S6
-rw-r--r--arch/riscv/lib/uaccess.S11
-rw-r--r--arch/riscv/mm/Makefile1
-rw-r--r--arch/riscv/mm/cache-ops.c17
-rw-r--r--arch/riscv/mm/cacheflush.c25
-rw-r--r--arch/riscv/mm/dma-noncoherent.c23
-rw-r--r--arch/riscv/mm/fault.c2
-rw-r--r--arch/riscv/mm/hugetlbpage.c19
-rw-r--r--arch/riscv/mm/init.c155
-rw-r--r--arch/riscv/mm/pageattr.c270
-rw-r--r--arch/riscv/mm/pmem.c4
-rw-r--r--arch/riscv/mm/ptdump.c56
-rw-r--r--arch/riscv/mm/tlbflush.c181
-rw-r--r--arch/riscv/net/bpf_jit_comp64.c18
-rw-r--r--arch/riscv/purgatory/Makefile8
-rw-r--r--arch/riscv/purgatory/entry.S16
-rw-r--r--arch/s390/Kconfig2
-rw-r--r--arch/s390/Makefile6
-rw-r--r--arch/s390/appldata/appldata_base.c4
-rw-r--r--arch/s390/boot/ipl_parm.c8
-rw-r--r--arch/s390/boot/startup.c46
-rw-r--r--arch/s390/boot/vmem.c41
-rw-r--r--arch/s390/configs/debug_defconfig1
-rw-r--r--arch/s390/hypfs/inode.c4
-rw-r--r--arch/s390/include/asm/asm-extable.h27
-rw-r--r--arch/s390/include/asm/bitops.h10
-rw-r--r--arch/s390/include/asm/ctl_reg.h146
-rw-r--r--arch/s390/include/asm/ctlreg.h251
-rw-r--r--arch/s390/include/asm/fault.h28
-rw-r--r--arch/s390/include/asm/fpu/internal.h1
-rw-r--r--arch/s390/include/asm/irq.h23
-rw-r--r--arch/s390/include/asm/kprobes.h5
-rw-r--r--arch/s390/include/asm/kvm_host.h7
-rw-r--r--arch/s390/include/asm/lowcore.h15
-rw-r--r--arch/s390/include/asm/mmu.h2
-rw-r--r--arch/s390/include/asm/mmu_context.h11
-rw-r--r--arch/s390/include/asm/page-states.h59
-rw-r--r--arch/s390/include/asm/page.h1
-rw-r--r--arch/s390/include/asm/pci.h11
-rw-r--r--arch/s390/include/asm/pci_clp.h3
-rw-r--r--arch/s390/include/asm/pci_dma.h121
-rw-r--r--arch/s390/include/asm/pgalloc.h1
-rw-r--r--arch/s390/include/asm/pgtable.h3
-rw-r--r--arch/s390/include/asm/processor.h1
-rw-r--r--arch/s390/include/asm/setup.h3
-rw-r--r--arch/s390/include/asm/smp.h1
-rw-r--r--arch/s390/include/asm/stacktrace.h7
-rw-r--r--arch/s390/include/asm/tlb.h13
-rw-r--r--arch/s390/include/asm/uaccess.h1
-rw-r--r--arch/s390/include/asm/word-at-a-time.h64
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/crash_dump.c6
-rw-r--r--arch/s390/kernel/ctlreg.c121
-rw-r--r--arch/s390/kernel/debug.c1
-rw-r--r--arch/s390/kernel/diag.c3
-rw-r--r--arch/s390/kernel/early.c23
-rw-r--r--arch/s390/kernel/guarded_storage.c6
-rw-r--r--arch/s390/kernel/ipl.c3
-rw-r--r--arch/s390/kernel/irq.c4
-rw-r--r--arch/s390/kernel/kprobes.c21
-rw-r--r--arch/s390/kernel/machine_kexec.c6
-rw-r--r--arch/s390/kernel/nmi.c24
-rw-r--r--arch/s390/kernel/perf_cpum_cf.c2
-rw-r--r--arch/s390/kernel/perf_event.c41
-rw-r--r--arch/s390/kernel/perf_pai_crypto.c149
-rw-r--r--arch/s390/kernel/perf_pai_ext.c11
-rw-r--r--arch/s390/kernel/ptrace.c47
-rw-r--r--arch/s390/kernel/setup.c27
-rw-r--r--arch/s390/kernel/smp.c134
-rw-r--r--arch/s390/kernel/stacktrace.c43
-rw-r--r--arch/s390/kernel/syscalls/syscall.tbl6
-rw-r--r--arch/s390/kernel/time.c4
-rw-r--r--arch/s390/kernel/topology.c3
-rw-r--r--arch/s390/kernel/vdso32/Makefile10
-rw-r--r--arch/s390/kernel/vdso64/Makefile10
-rw-r--r--arch/s390/kvm/gaccess.c52
-rw-r--r--arch/s390/kvm/interrupt.c16
-rw-r--r--arch/s390/kvm/kvm-s390.c17
-rw-r--r--arch/s390/kvm/priv.c2
-rw-r--r--arch/s390/kvm/trace-s390.h23
-rw-r--r--arch/s390/kvm/vsie.c9
-rw-r--r--arch/s390/lib/uaccess.c15
-rw-r--r--arch/s390/mm/cmm.c1
-rw-r--r--arch/s390/mm/dump_pagetables.c2
-rw-r--r--arch/s390/mm/extable.c18
-rw-r--r--arch/s390/mm/fault.c458
-rw-r--r--arch/s390/mm/gmap.c26
-rw-r--r--arch/s390/mm/init.c8
-rw-r--r--arch/s390/mm/maccess.c2
-rw-r--r--arch/s390/mm/page-states.c200
-rw-r--r--arch/s390/mm/pageattr.c2
-rw-r--r--arch/s390/mm/pgalloc.c303
-rw-r--r--arch/s390/mm/pgtable.c2
-rw-r--r--arch/s390/mm/vmem.c15
-rw-r--r--arch/s390/net/bpf_jit_comp.c292
-rw-r--r--arch/s390/pci/Makefile2
-rw-r--r--arch/s390/pci/pci.c37
-rw-r--r--arch/s390/pci/pci_bus.c5
-rw-r--r--arch/s390/pci/pci_debug.c12
-rw-r--r--arch/s390/pci/pci_dma.c735
-rw-r--r--arch/s390/pci/pci_event.c17
-rw-r--r--arch/s390/pci/pci_sysfs.c19
-rw-r--r--arch/sh/Kconfig12
-rw-r--r--arch/sh/Kconfig.debug11
-rw-r--r--arch/sh/boards/Kconfig7
-rw-r--r--arch/sh/boards/Makefile1
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c2
-rw-r--r--arch/sh/boards/mach-microdev/Makefile6
-rw-r--r--arch/sh/boards/mach-microdev/fdc37c93xapm.c157
-rw-r--r--arch/sh/boards/mach-microdev/io.c123
-rw-r--r--arch/sh/boards/mach-microdev/irq.c150
-rw-r--r--arch/sh/boards/mach-microdev/setup.c197
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c2
-rw-r--r--arch/sh/configs/microdev_defconfig42
-rw-r--r--arch/sh/drivers/Makefile1
-rw-r--r--arch/sh/drivers/pci/common.c11
-rw-r--r--arch/sh/drivers/superhyway/Makefile7
-rw-r--r--arch/sh/drivers/superhyway/ops-sh4-202.c168
-rw-r--r--arch/sh/include/asm/cmpxchg.h9
-rw-r--r--arch/sh/include/asm/io.h4
-rw-r--r--arch/sh/include/asm/kexec.h4
-rw-r--r--arch/sh/include/asm/kprobes.h2
-rw-r--r--arch/sh/include/asm/machvec.h5
-rw-r--r--arch/sh/include/mach-common/mach/microdev.h69
-rw-r--r--arch/sh/kernel/Makefile2
-rw-r--r--arch/sh/kernel/cpu/sh4/Makefile4
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh4-202.c174
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh4-202.c139
-rw-r--r--arch/sh/kernel/ioport.c13
-rw-r--r--arch/sh/kernel/machine_kexec.c2
-rw-r--r--arch/sh/kernel/reboot.c4
-rw-r--r--arch/sh/kernel/setup.c7
-rw-r--r--arch/sh/kernel/syscalls/syscall.tbl6
-rw-r--r--arch/sparc/Makefile5
-rw-r--r--arch/sparc/crypto/crc32c_glue.c45
-rw-r--r--arch/sparc/include/asm/fb.h15
-rw-r--r--arch/sparc/include/asm/kprobes.h2
-rw-r--r--arch/sparc/kernel/cpumap.c2
-rw-r--r--arch/sparc/kernel/setup_32.c13
-rw-r--r--arch/sparc/kernel/setup_64.c13
-rw-r--r--arch/sparc/kernel/syscalls/syscall.tbl6
-rw-r--r--arch/sparc/lib/checksum_32.S2
-rw-r--r--arch/sparc/vdso/Makefile27
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/x86/Kconfig56
-rw-r--r--arch/x86/Makefile12
-rw-r--r--arch/x86/Makefile.postlink3
-rw-r--r--arch/x86/boot/Makefile2
-rw-r--r--arch/x86/boot/compressed/acpi.c16
-rw-r--r--arch/x86/boot/compressed/cmdline.c4
-rw-r--r--arch/x86/boot/compressed/ident_map_64.c7
-rw-r--r--arch/x86/boot/compressed/kaslr.c26
-rw-r--r--arch/x86/boot/compressed/mem.c6
-rw-r--r--arch/x86/boot/compressed/misc.c24
-rw-r--r--arch/x86/boot/compressed/misc.h1
-rw-r--r--arch/x86/boot/compressed/pgtable_64.c9
-rw-r--r--arch/x86/boot/compressed/sev.c14
-rw-r--r--arch/x86/boot/compressed/tdx.c6
-rw-r--r--arch/x86/boot/compressed/vmlinux.lds.S6
-rw-r--r--arch/x86/boot/header.S213
-rw-r--r--arch/x86/boot/setup.ld14
-rw-r--r--arch/x86/boot/tools/build.c273
-rw-r--r--arch/x86/coco/tdx/tdcall.S234
-rw-r--r--arch/x86/coco/tdx/tdx-shared.c28
-rw-r--r--arch/x86/coco/tdx/tdx.c162
-rw-r--r--arch/x86/configs/hardening.config14
-rw-r--r--arch/x86/configs/i386_defconfig1
-rw-r--r--arch/x86/configs/x86_64_defconfig1
-rw-r--r--arch/x86/crypto/aesni-intel_asm.S4
-rw-r--r--arch/x86/crypto/aesni-intel_avx-x86_64.S4
-rw-r--r--arch/x86/crypto/aesni-intel_glue.c52
-rw-r--r--arch/x86/crypto/nhpoly1305-avx2-glue.c9
-rw-r--r--arch/x86/crypto/nhpoly1305-sse2-glue.c9
-rw-r--r--arch/x86/crypto/sha1_ssse3_glue.c12
-rw-r--r--arch/x86/crypto/sha256_ssse3_glue.c44
-rw-r--r--arch/x86/entry/common.c206
-rw-r--r--arch/x86/entry/entry.S2
-rw-r--r--arch/x86/entry/entry_32.S2
-rw-r--r--arch/x86/entry/entry_64.S84
-rw-r--r--arch/x86/entry/entry_64_compat.S88
-rw-r--r--arch/x86/entry/syscalls/syscall_32.tbl6
-rw-r--r--arch/x86/entry/syscalls/syscall_64.tbl5
-rw-r--r--arch/x86/entry/thunk_32.S2
-rw-r--r--arch/x86/entry/thunk_64.S2
-rw-r--r--arch/x86/entry/vdso/Makefile30
-rw-r--r--arch/x86/entry/vdso/vdso32-setup.c1
-rw-r--r--arch/x86/entry/vdso/vsgx.S1
-rw-r--r--arch/x86/events/amd/uncore.c1060
-rw-r--r--arch/x86/events/core.c6
-rw-r--r--arch/x86/events/intel/core.c475
-rw-r--r--arch/x86/events/intel/cstate.c3
-rw-r--r--arch/x86/events/intel/ds.c4
-rw-r--r--arch/x86/events/intel/pt.c8
-rw-r--r--arch/x86/events/intel/uncore.c2
-rw-r--r--arch/x86/events/perf_event.h37
-rw-r--r--arch/x86/events/rapl.c22
-rw-r--r--arch/x86/events/utils.c5
-rw-r--r--arch/x86/hyperv/hv_init.c25
-rw-r--r--arch/x86/hyperv/hv_vtl.c2
-rw-r--r--arch/x86/hyperv/ivm.c12
-rw-r--r--arch/x86/include/asm/Kbuild1
-rw-r--r--arch/x86/include/asm/acpi.h14
-rw-r--r--arch/x86/include/asm/alternative.h4
-rw-r--r--arch/x86/include/asm/apic.h44
-rw-r--r--arch/x86/include/asm/bitops.h20
-rw-r--r--arch/x86/include/asm/boot.h2
-rw-r--r--arch/x86/include/asm/cacheinfo.h3
-rw-r--r--arch/x86/include/asm/cmpxchg.h6
-rw-r--r--arch/x86/include/asm/cpu.h22
-rw-r--r--arch/x86/include/asm/cpufeatures.h1
-rw-r--r--arch/x86/include/asm/crash_core.h42
-rw-r--r--arch/x86/include/asm/elf.h3
-rw-r--r--arch/x86/include/asm/fb.h10
-rw-r--r--arch/x86/include/asm/fpu/api.h3
-rw-r--r--arch/x86/include/asm/hw_irq.h6
-rw-r--r--arch/x86/include/asm/i8259.h2
-rw-r--r--arch/x86/include/asm/ia32.h23
-rw-r--r--arch/x86/include/asm/idtentry.h4
-rw-r--r--arch/x86/include/asm/init.h2
-rw-r--r--arch/x86/include/asm/intel-family.h2
-rw-r--r--arch/x86/include/asm/kprobes.h2
-rw-r--r--arch/x86/include/asm/kvm-x86-ops.h3
-rw-r--r--arch/x86/include/asm/kvm_host.h23
-rw-r--r--arch/x86/include/asm/local.h33
-rw-r--r--arch/x86/include/asm/mce.h2
-rw-r--r--arch/x86/include/asm/mem_encrypt.h4
-rw-r--r--arch/x86/include/asm/microcode.h21
-rw-r--r--arch/x86/include/asm/mpspec.h2
-rw-r--r--arch/x86/include/asm/mshyperv.h4
-rw-r--r--arch/x86/include/asm/msr-index.h23
-rw-r--r--arch/x86/include/asm/nospec-branch.h71
-rw-r--r--arch/x86/include/asm/numa.h7
-rw-r--r--arch/x86/include/asm/percpu.h110
-rw-r--r--arch/x86/include/asm/perf_event.h9
-rw-r--r--arch/x86/include/asm/pgtable.h8
-rw-r--r--arch/x86/include/asm/preempt.h4
-rw-r--r--arch/x86/include/asm/processor.h63
-rw-r--r--arch/x86/include/asm/prom.h5
-rw-r--r--arch/x86/include/asm/proto.h7
-rw-r--r--arch/x86/include/asm/setup.h1
-rw-r--r--arch/x86/include/asm/shared/tdx.h90
-rw-r--r--arch/x86/include/asm/smp.h5
-rw-r--r--arch/x86/include/asm/sparsemem.h2
-rw-r--r--arch/x86/include/asm/spec-ctrl.h11
-rw-r--r--arch/x86/include/asm/svm.h7
-rw-r--r--arch/x86/include/asm/syscall.h6
-rw-r--r--arch/x86/include/asm/tdx.h13
-rw-r--r--arch/x86/include/asm/topology.h12
-rw-r--r--arch/x86/include/asm/uaccess.h2
-rw-r--r--arch/x86/include/asm/x86_init.h2
-rw-r--r--arch/x86/include/asm/xen/hypervisor.h9
-rw-r--r--arch/x86/include/uapi/asm/amd_hsmp.h109
-rw-r--r--arch/x86/kernel/Makefile1
-rw-r--r--arch/x86/kernel/acpi/boot.c41
-rw-r--r--arch/x86/kernel/alternative.c13
-rw-r--r--arch/x86/kernel/amd_nb.c12
-rw-r--r--arch/x86/kernel/apic/apic.c29
-rw-r--r--arch/x86/kernel/apic/apic_common.c4
-rw-r--r--arch/x86/kernel/apic/apic_flat_64.c10
-rw-r--r--arch/x86/kernel/apic/apic_noop.c8
-rw-r--r--arch/x86/kernel/apic/apic_numachip.c16
-rw-r--r--arch/x86/kernel/apic/bigsmp_32.c6
-rw-r--r--arch/x86/kernel/apic/ipi.c13
-rw-r--r--arch/x86/kernel/apic/local.h7
-rw-r--r--arch/x86/kernel/apic/msi.c8
-rw-r--r--arch/x86/kernel/apic/probe_32.c12
-rw-r--r--arch/x86/kernel/apic/x2apic_cluster.c1
-rw-r--r--arch/x86/kernel/apic/x2apic_phys.c7
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c8
-rw-r--r--arch/x86/kernel/asm-offsets.c33
-rw-r--r--arch/x86/kernel/callthunks.c5
-rw-r--r--arch/x86/kernel/cpu/Makefile2
-rw-r--r--arch/x86/kernel/cpu/amd.c56
-rw-r--r--arch/x86/kernel/cpu/bugs.c95
-rw-r--r--arch/x86/kernel/cpu/cacheinfo.c49
-rw-r--r--arch/x86/kernel/cpu/common.c134
-rw-r--r--arch/x86/kernel/cpu/cpu.h3
-rw-r--r--arch/x86/kernel/cpu/debugfs.c58
-rw-r--r--arch/x86/kernel/cpu/hygon.c48
-rw-r--r--arch/x86/kernel/cpu/intel.c14
-rw-r--r--arch/x86/kernel/cpu/mce/amd.c68
-rw-r--r--arch/x86/kernel/cpu/mce/apei.c4
-rw-r--r--arch/x86/kernel/cpu/mce/core.c36
-rw-r--r--arch/x86/kernel/cpu/mce/intel.c20
-rw-r--r--arch/x86/kernel/cpu/mce/internal.h4
-rw-r--r--arch/x86/kernel/cpu/microcode/amd.c188
-rw-r--r--arch/x86/kernel/cpu/microcode/core.c683
-rw-r--r--arch/x86/kernel/cpu/microcode/intel.c681
-rw-r--r--arch/x86/kernel/cpu/microcode/internal.h49
-rw-r--r--arch/x86/kernel/cpu/mshyperv.c5
-rw-r--r--arch/x86/kernel/cpu/proc.c8
-rw-r--r--arch/x86/kernel/cpu/resctrl/core.c11
-rw-r--r--arch/x86/kernel/cpu/resctrl/ctrlmondata.c14
-rw-r--r--arch/x86/kernel/cpu/resctrl/internal.h31
-rw-r--r--arch/x86/kernel/cpu/resctrl/monitor.c10
-rw-r--r--arch/x86/kernel/cpu/resctrl/rdtgroup.c281
-rw-r--r--arch/x86/kernel/cpu/topology.c13
-rw-r--r--arch/x86/kernel/cpu/zhaoxin.c14
-rw-r--r--arch/x86/kernel/devicetree.c6
-rw-r--r--arch/x86/kernel/fpu/core.c5
-rw-r--r--arch/x86/kernel/fpu/xstate.c13
-rw-r--r--arch/x86/kernel/fpu/xstate.h3
-rw-r--r--arch/x86/kernel/ftrace_32.S2
-rw-r--r--arch/x86/kernel/ftrace_64.S2
-rw-r--r--arch/x86/kernel/head32.c120
-rw-r--r--arch/x86/kernel/head64.c17
-rw-r--r--arch/x86/kernel/head_32.S12
-rw-r--r--arch/x86/kernel/head_64.S7
-rw-r--r--arch/x86/kernel/hpet.c4
-rw-r--r--arch/x86/kernel/i8259.c38
-rw-r--r--arch/x86/kernel/idt.c9
-rw-r--r--arch/x86/kernel/irqflags.S2
-rw-r--r--arch/x86/kernel/itmt.c1
-rw-r--r--arch/x86/kernel/kvm.c6
-rw-r--r--arch/x86/kernel/nmi.c22
-rw-r--r--arch/x86/kernel/setup.c153
-rw-r--r--arch/x86/kernel/sev-shared.c53
-rw-r--r--arch/x86/kernel/sev.c43
-rw-r--r--arch/x86/kernel/signal_64.c6
-rw-r--r--arch/x86/kernel/smp.c39
-rw-r--r--arch/x86/kernel/smpboot.c140
-rw-r--r--arch/x86/kernel/topology.c2
-rw-r--r--arch/x86/kernel/tsc_sync.c10
-rw-r--r--arch/x86/kernel/unwind_orc.c2
-rw-r--r--arch/x86/kernel/vmlinux.lds.S7
-rw-r--r--arch/x86/kernel/vsmp_64.c2
-rw-r--r--arch/x86/kvm/Kconfig11
-rw-r--r--arch/x86/kvm/cpuid.c18
-rw-r--r--arch/x86/kvm/cpuid.h3
-rw-r--r--arch/x86/kvm/debugfs.c1
-rw-r--r--arch/x86/kvm/hyperv.c10
-rw-r--r--arch/x86/kvm/lapic.c38
-rw-r--r--arch/x86/kvm/mmu.h7
-rw-r--r--arch/x86/kvm/mmu/mmu.c55
-rw-r--r--arch/x86/kvm/mtrr.c2
-rw-r--r--arch/x86/kvm/pmu.c27
-rw-r--r--arch/x86/kvm/pmu.h6
-rw-r--r--arch/x86/kvm/smm.c1
-rw-r--r--arch/x86/kvm/svm/avic.c5
-rw-r--r--arch/x86/kvm/svm/nested.c3
-rw-r--r--arch/x86/kvm/svm/pmu.c2
-rw-r--r--arch/x86/kvm/svm/svm.c73
-rw-r--r--arch/x86/kvm/vmx/pmu_intel.c4
-rw-r--r--arch/x86/kvm/vmx/vmx.c45
-rw-r--r--arch/x86/kvm/x86.c293
-rw-r--r--arch/x86/kvm/x86.h1
-rw-r--r--arch/x86/kvm/xen.c59
-rw-r--r--arch/x86/lib/checksum_32.S2
-rw-r--r--arch/x86/lib/clear_page_64.S2
-rw-r--r--arch/x86/lib/cmpxchg8b_emu.S2
-rw-r--r--arch/x86/lib/copy_mc.c8
-rw-r--r--arch/x86/lib/copy_page_64.S2
-rw-r--r--arch/x86/lib/copy_user_64.S2
-rw-r--r--arch/x86/lib/copy_user_uncached_64.S2
-rw-r--r--arch/x86/lib/csum-wrappers_64.c5
-rw-r--r--arch/x86/lib/getuser.S2
-rw-r--r--arch/x86/lib/hweight.S22
-rw-r--r--arch/x86/lib/memcpy_64.S2
-rw-r--r--arch/x86/lib/memmove_32.S2
-rw-r--r--arch/x86/lib/memmove_64.S2
-rw-r--r--arch/x86/lib/memset_64.S2
-rw-r--r--arch/x86/lib/putuser.S3
-rw-r--r--arch/x86/lib/retpoline.S188
-rw-r--r--arch/x86/mm/maccess.c19
-rw-r--r--arch/x86/mm/mem_encrypt.c34
-rw-r--r--arch/x86/mm/mem_encrypt_amd.c47
-rw-r--r--arch/x86/mm/numa.c94
-rw-r--r--arch/x86/mm/pgtable.c3
-rw-r--r--arch/x86/mm/pti.c58
-rw-r--r--arch/x86/net/bpf_jit_comp.c194
-rw-r--r--arch/x86/pci/fixup.c59
-rw-r--r--arch/x86/platform/uv/uv_nmi.c104
-rw-r--r--arch/x86/platform/uv/uv_time.c2
-rw-r--r--arch/x86/um/vdso/Makefile12
-rw-r--r--arch/x86/video/fbdev.c15
-rw-r--r--arch/x86/virt/Makefile (renamed from arch/ia64/kernel/.gitignore)3
-rw-r--r--arch/x86/virt/vmx/Makefile2
-rw-r--r--arch/x86/virt/vmx/tdx/Makefile2
-rw-r--r--arch/x86/virt/vmx/tdx/seamcall.S61
-rw-r--r--arch/x86/virt/vmx/tdx/tdxcall.S226
-rw-r--r--arch/x86/xen/apic.c10
-rw-r--r--arch/x86/xen/enlighten.c6
-rw-r--r--arch/x86/xen/enlighten_pv.c2
-rw-r--r--arch/x86/xen/xen-asm.S2
-rw-r--r--arch/x86/xen/xen-ops.h2
-rw-r--r--arch/xtensa/kernel/setup.c12
-rw-r--r--arch/xtensa/kernel/syscalls/syscall.tbl6
-rw-r--r--block/Kconfig1
-rw-r--r--block/badblocks.c1618
-rw-r--r--block/bdev.c73
-rw-r--r--block/blk-cgroup.c13
-rw-r--r--block/blk-cgroup.h2
-rw-r--r--block/blk-core.c10
-rw-r--r--block/blk-flush.c11
-rw-r--r--block/blk-mq-debugfs.c1
-rw-r--r--block/blk-mq.c134
-rw-r--r--block/blk-mq.h57
-rw-r--r--block/blk-pm.c33
-rw-r--r--block/blk-sysfs.c2
-rw-r--r--block/blk-throttle.c8
-rw-r--r--block/disk-events.c18
-rw-r--r--block/fops.c65
-rw-r--r--block/genhd.c19
-rw-r--r--block/ioctl.c11
-rw-r--r--block/partitions/core.c43
-rw-r--r--block/partitions/ibm.c98
-rw-r--r--block/sed-opal.c25
-rw-r--r--certs/Kconfig22
-rw-r--r--crypto/Kconfig87
-rw-r--r--crypto/Makefile6
-rw-r--r--crypto/adiantum.c80
-rw-r--r--crypto/aead.c6
-rw-r--r--crypto/ahash.c409
-rw-r--r--crypto/api.c2
-rw-r--r--crypto/arc4.c60
-rw-r--r--crypto/asymmetric_keys/Kconfig3
-rw-r--r--crypto/asymmetric_keys/Makefile3
-rw-r--r--crypto/asymmetric_keys/mscode_parser.c19
-rw-r--r--crypto/asymmetric_keys/pkcs7.asn17
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.c22
-rw-r--r--crypto/asymmetric_keys/pkcs8.asn16
-rw-r--r--crypto/asymmetric_keys/public_key.c13
-rw-r--r--crypto/asymmetric_keys/restrict.c4
-rw-r--r--crypto/asymmetric_keys/selftest.c13
-rw-r--r--crypto/asymmetric_keys/signature.c2
-rw-r--r--crypto/asymmetric_keys/x509.asn17
-rw-r--r--crypto/asymmetric_keys/x509_akid.asn129
-rw-r--r--crypto/asymmetric_keys/x509_cert_parser.c36
-rw-r--r--crypto/asymmetric_keys/x509_parser.h9
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c8
-rw-r--r--crypto/authenc.c20
-rw-r--r--crypto/authencesn.c28
-rw-r--r--crypto/cbc.c163
-rw-r--r--crypto/ccm.c29
-rw-r--r--crypto/chacha20poly1305.c11
-rw-r--r--crypto/cmac.c39
-rw-r--r--crypto/cryptd.c14
-rw-r--r--crypto/crypto_engine.c8
-rw-r--r--crypto/ctr.c14
-rw-r--r--crypto/cts.c12
-rw-r--r--crypto/deflate.c61
-rw-r--r--crypto/drbg.c2
-rw-r--r--crypto/ecb.c190
-rw-r--r--crypto/essiv.c20
-rw-r--r--crypto/gcm.c12
-rw-r--r--crypto/hash.h14
-rw-r--r--crypto/hash_info.c6
-rw-r--r--crypto/hctr2.c11
-rw-r--r--crypto/hmac.c56
-rw-r--r--crypto/jitterentropy-kcapi.c17
-rw-r--r--crypto/jitterentropy.c344
-rw-r--r--crypto/jitterentropy.h5
-rw-r--r--crypto/lrw.c12
-rw-r--r--crypto/lskcipher.c634
-rw-r--r--crypto/pcrypt.c4
-rw-r--r--crypto/rsa-pkcs1pad.c27
-rw-r--r--crypto/rsaprivkey.asn17
-rw-r--r--crypto/rsapubkey.asn17
-rw-r--r--crypto/shash.c379
-rw-r--r--crypto/skcipher.c81
-rw-r--r--crypto/skcipher.h28
-rw-r--r--crypto/testmgr.c57
-rw-r--r--crypto/testmgr.h155
-rw-r--r--crypto/vmac.c1
-rw-r--r--crypto/xcbc.c32
-rw-r--r--crypto/xts.c33
-rw-r--r--drivers/Kconfig6
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/accel/drm_accel.c56
-rw-r--r--drivers/accel/habanalabs/common/command_buffer.c5
-rw-r--r--drivers/accel/habanalabs/common/command_submission.c488
-rw-r--r--drivers/accel/habanalabs/common/context.c9
-rw-r--r--drivers/accel/habanalabs/common/debugfs.c22
-rw-r--r--drivers/accel/habanalabs/common/device.c425
-rw-r--r--drivers/accel/habanalabs/common/firmware_if.c45
-rw-r--r--drivers/accel/habanalabs/common/habanalabs.h212
-rw-r--r--drivers/accel/habanalabs/common/habanalabs_drv.c186
-rw-r--r--drivers/accel/habanalabs/common/habanalabs_ioctl.c112
-rw-r--r--drivers/accel/habanalabs/common/irq.c180
-rw-r--r--drivers/accel/habanalabs/common/memory.c308
-rw-r--r--drivers/accel/habanalabs/gaudi/gaudi.c17
-rw-r--r--drivers/accel/habanalabs/gaudi/gaudiP.h2
-rw-r--r--drivers/accel/habanalabs/gaudi/gaudi_coresight.c12
-rw-r--r--drivers/accel/habanalabs/gaudi2/gaudi2.c487
-rw-r--r--drivers/accel/habanalabs/gaudi2/gaudi2P.h4
-rw-r--r--drivers/accel/habanalabs/gaudi2/gaudi2_coresight.c46
-rw-r--r--drivers/accel/habanalabs/gaudi2/gaudi2_security.c21
-rw-r--r--drivers/accel/habanalabs/goya/goya.c10
-rw-r--r--drivers/accel/habanalabs/goya/goyaP.h2
-rw-r--r--drivers/accel/habanalabs/goya/goya_coresight.c10
-rw-r--r--drivers/accel/habanalabs/include/gaudi/gaudi_fw_if.h32
-rw-r--r--drivers/accel/habanalabs/include/gaudi2/gaudi2_async_events.h7
-rw-r--r--drivers/accel/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h16
-rw-r--r--drivers/accel/ivpu/Makefile3
-rw-r--r--drivers/accel/ivpu/TODO11
-rw-r--r--drivers/accel/ivpu/ivpu_debugfs.c50
-rw-r--r--drivers/accel/ivpu/ivpu_debugfs.h8
-rw-r--r--drivers/accel/ivpu/ivpu_drv.c100
-rw-r--r--drivers/accel/ivpu/ivpu_drv.h19
-rw-r--r--drivers/accel/ivpu/ivpu_fw.c33
-rw-r--r--drivers/accel/ivpu/ivpu_fw.h2
-rw-r--r--drivers/accel/ivpu/ivpu_fw_log.c6
-rw-r--r--drivers/accel/ivpu/ivpu_gem.c30
-rw-r--r--drivers/accel/ivpu/ivpu_gem.h27
-rw-r--r--drivers/accel/ivpu/ivpu_hw.h8
-rw-r--r--drivers/accel/ivpu/ivpu_hw_37xx.c204
-rw-r--r--drivers/accel/ivpu/ivpu_hw_37xx_reg.h187
-rw-r--r--drivers/accel/ivpu/ivpu_hw_40xx.c16
-rw-r--r--drivers/accel/ivpu/ivpu_hw_reg_io.h32
-rw-r--r--drivers/accel/ivpu/ivpu_ipc.c53
-rw-r--r--drivers/accel/ivpu/ivpu_job.c11
-rw-r--r--drivers/accel/ivpu/ivpu_job.h2
-rw-r--r--drivers/accel/ivpu/ivpu_jsm_msg.c82
-rw-r--r--drivers/accel/ivpu/ivpu_jsm_msg.h2
-rw-r--r--drivers/accel/ivpu/ivpu_mmu.c146
-rw-r--r--drivers/accel/ivpu/ivpu_mmu_context.c27
-rw-r--r--drivers/accel/ivpu/ivpu_mmu_context.h2
-rw-r--r--drivers/accel/ivpu/ivpu_pm.c31
-rw-r--r--drivers/accel/ivpu/ivpu_pm.h3
-rw-r--r--drivers/accel/qaic/qaic.h13
-rw-r--r--drivers/accel/qaic/qaic_data.c187
-rw-r--r--drivers/accel/qaic/qaic_drv.c119
-rw-r--r--drivers/accessibility/speakup/kobjects.c25
-rw-r--r--drivers/acpi/Kconfig7
-rw-r--r--drivers/acpi/ac.c98
-rw-r--r--drivers/acpi/acpi_fpdt.c45
-rw-r--r--drivers/acpi/acpi_lpss.c21
-rw-r--r--drivers/acpi/acpi_pad.c84
-rw-r--r--drivers/acpi/acpi_processor.c1
-rw-r--r--drivers/acpi/acpi_video.c18
-rw-r--r--drivers/acpi/apei/erst.c41
-rw-r--r--drivers/acpi/apei/ghes.c23
-rw-r--r--drivers/acpi/arm64/amba.c2
-rw-r--r--drivers/acpi/battery.c2
-rw-r--r--drivers/acpi/bus.c6
-rw-r--r--drivers/acpi/device_pm.c13
-rw-r--r--drivers/acpi/device_sysfs.c24
-rw-r--r--drivers/acpi/ec.c21
-rw-r--r--drivers/acpi/hed.c2
-rw-r--r--drivers/acpi/irq.c7
-rw-r--r--drivers/acpi/nfit/core.c22
-rw-r--r--drivers/acpi/numa/Kconfig4
-rw-r--r--drivers/acpi/numa/hmat.c146
-rw-r--r--drivers/acpi/numa/srat.c11
-rw-r--r--drivers/acpi/osi.c2
-rw-r--r--drivers/acpi/osl.c30
-rw-r--r--drivers/acpi/pci_root.c6
-rw-r--r--drivers/acpi/prmt.c2
-rw-r--r--drivers/acpi/processor_core.c2
-rw-r--r--drivers/acpi/processor_idle.c2
-rw-r--r--drivers/acpi/property.c20
-rw-r--r--drivers/acpi/resource.c117
-rw-r--r--drivers/acpi/riscv/rhct.c93
-rw-r--r--drivers/acpi/scan.c20
-rw-r--r--drivers/acpi/tables.c173
-rw-r--r--drivers/acpi/thermal.c863
-rw-r--r--drivers/acpi/utils.c102
-rw-r--r--drivers/acpi/video_detect.c84
-rw-r--r--drivers/acpi/x86/s2idle.c5
-rw-r--r--drivers/acpi/x86/utils.c3
-rw-r--r--drivers/amba/bus.c5
-rw-r--r--drivers/android/binder.c2
-rw-r--r--drivers/android/binder_alloc.c30
-rw-r--r--drivers/android/binderfs.c10
-rw-r--r--drivers/ata/ahci.c6
-rw-r--r--drivers/ata/ahci_imx.c10
-rw-r--r--drivers/ata/ahci_xgene.c11
-rw-r--r--drivers/ata/libahci.c2
-rw-r--r--drivers/ata/libata-core.c169
-rw-r--r--drivers/ata/libata-eh.c54
-rw-r--r--drivers/ata/libata-sata.c5
-rw-r--r--drivers/ata/libata-scsi.c65
-rw-r--r--drivers/ata/libata-sff.c10
-rw-r--r--drivers/ata/libata.h2
-rw-r--r--drivers/ata/pata_cs5520.c2
-rw-r--r--drivers/ata/pata_falcon.c11
-rw-r--r--drivers/ata/pata_gayle.c11
-rw-r--r--drivers/ata/pata_isapnp.c3
-rw-r--r--drivers/ata/sata_mv.c9
-rw-r--r--drivers/atm/fore200e.c8
-rw-r--r--drivers/atm/iphase.c20
-rw-r--r--drivers/atm/solos-pci.c8
-rw-r--r--drivers/auxdisplay/panel.c7
-rw-r--r--drivers/base/cacheinfo.c51
-rw-r--r--drivers/base/class.c6
-rw-r--r--drivers/base/core.c1
-rw-r--r--drivers/base/cpu.c6
-rw-r--r--drivers/base/dd.c2
-rw-r--r--drivers/base/devcoredump.c3
-rw-r--r--drivers/base/firmware_loader/fallback.c10
-rw-r--r--drivers/base/firmware_loader/fallback.h4
-rw-r--r--drivers/base/firmware_loader/fallback_table.c1
-rw-r--r--drivers/base/firmware_loader/firmware.h1
-rw-r--r--drivers/base/firmware_loader/main.c9
-rw-r--r--drivers/base/memory.c18
-rw-r--r--drivers/base/platform.c71
-rw-r--r--drivers/base/power/common.c21
-rw-r--r--drivers/base/power/domain.c44
-rw-r--r--drivers/base/regmap/regcache.c29
-rw-r--r--drivers/base/regmap/regmap-debugfs.c2
-rw-r--r--drivers/base/regmap/regmap-kunit.c68
-rw-r--r--drivers/base/regmap/regmap.c18
-rw-r--r--drivers/base/test/Kconfig4
-rw-r--r--drivers/base/test/property-entry-test.c4
-rw-r--r--drivers/block/aoe/aoenet.c3
-rw-r--r--drivers/block/ataflop.c4
-rw-r--r--drivers/block/drbd/drbd_int.h4
-rw-r--r--drivers/block/drbd/drbd_nl.c65
-rw-r--r--drivers/block/floppy.c4
-rw-r--r--drivers/block/nbd.c128
-rw-r--r--drivers/block/null_blk/main.c47
-rw-r--r--drivers/block/pktcdvd.c76
-rw-r--r--drivers/block/rnbd/rnbd-srv.c27
-rw-r--r--drivers/block/rnbd/rnbd-srv.h2
-rw-r--r--drivers/block/ublk_drv.c342
-rw-r--r--drivers/block/virtio_blk.c6
-rw-r--r--drivers/block/xen-blkback/blkback.c4
-rw-r--r--drivers/block/xen-blkback/common.h4
-rw-r--r--drivers/block/xen-blkback/xenbus.c40
-rw-r--r--drivers/block/zram/zram_drv.c31
-rw-r--r--drivers/block/zram/zram_drv.h2
-rw-r--r--drivers/bluetooth/btmtksdio.c44
-rw-r--r--drivers/bluetooth/btqca.c68
-rw-r--r--drivers/bluetooth/btqca.h5
-rw-r--r--drivers/bluetooth/btrtl.c10
-rw-r--r--drivers/bluetooth/btusb.c11
-rw-r--r--drivers/bluetooth/hci_bcm4377.c5
-rw-r--r--drivers/bluetooth/hci_qca.c11
-rw-r--r--drivers/bluetooth/hci_vhci.c3
-rw-r--r--drivers/bus/Kconfig2
-rw-r--r--drivers/bus/fsl-mc/dprc.c12
-rw-r--r--drivers/bus/vexpress-config.c2
-rw-r--r--drivers/cache/Kconfig2
-rw-r--r--drivers/cdrom/cdrom.c1
-rw-r--r--drivers/cdx/Makefile2
-rw-r--r--drivers/cdx/cdx.c296
-rw-r--r--drivers/cdx/cdx.h22
-rw-r--r--drivers/cdx/controller/cdx_controller.c24
-rw-r--r--drivers/cdx/controller/mc_cdx_pcol.h54
-rw-r--r--drivers/cdx/controller/mcdi_functions.c89
-rw-r--r--drivers/cdx/controller/mcdi_functions.h31
-rw-r--r--drivers/char/Kconfig4
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/agp/Kconfig16
-rw-r--r--drivers/char/agp/Makefile2
-rw-r--r--drivers/char/agp/hp-agp.c550
-rw-r--r--drivers/char/agp/i460-agp.c659
-rw-r--r--drivers/char/agp/parisc-agp.c16
-rw-r--r--drivers/char/hpet.c33
-rw-r--r--drivers/char/hw_random/Kconfig2
-rw-r--r--drivers/char/hw_random/bcm2835-rng.c4
-rw-r--r--drivers/char/hw_random/core.c6
-rw-r--r--drivers/char/hw_random/geode-rng.c6
-rw-r--r--drivers/char/hw_random/hisi-rng.c2
-rw-r--r--drivers/char/hw_random/imx-rngc.c10
-rw-r--r--drivers/char/hw_random/ks-sa-rng.c26
-rw-r--r--drivers/char/hw_random/meson-rng.c80
-rw-r--r--drivers/char/hw_random/mpfs-rng.c2
-rw-r--r--drivers/char/hw_random/n2-drv.c10
-rw-r--r--drivers/char/hw_random/nomadik-rng.c1
-rw-r--r--drivers/char/hw_random/octeon-rng.c6
-rw-r--r--drivers/char/hw_random/st-rng.c1
-rw-r--r--drivers/char/hw_random/stm32-rng.c511
-rw-r--r--drivers/char/hw_random/xgene-rng.c1
-rw-r--r--drivers/char/hw_random/xiphera-trng.c2
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c11
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c1
-rw-r--r--drivers/char/ipmi/ipmi_ssif.c2
-rw-r--r--drivers/char/mem.c16
-rw-r--r--drivers/char/mspec.c295
-rw-r--r--drivers/char/random.c1
-rw-r--r--drivers/char/sonypi.c2
-rw-r--r--drivers/char/virtio_console.c2
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c138
-rw-r--r--drivers/clk/.kunitconfig1
-rw-r--r--drivers/clk/Kconfig16
-rw-r--r--drivers/clk/Makefile2
-rw-r--r--drivers/clk/analogbits/Kconfig2
-rw-r--r--drivers/clk/analogbits/wrpll-cln28hpc.c8
-rw-r--r--drivers/clk/at91/clk-utmi.c12
-rw-r--r--drivers/clk/clk-asm9260.c6
-rw-r--r--drivers/clk/clk-cdce925.c67
-rw-r--r--drivers/clk/clk-fractional-divider.c27
-rw-r--r--drivers/clk/clk-fractional-divider_test.c147
-rw-r--r--drivers/clk/clk-gate.c2
-rw-r--r--drivers/clk/clk-gate_test.c30
-rw-r--r--drivers/clk/clk-lochnagar.c9
-rw-r--r--drivers/clk/clk-npcm7xx.c2
-rw-r--r--drivers/clk/clk-renesas-pcie.c2
-rw-r--r--drivers/clk/clk-scmi.c96
-rw-r--r--drivers/clk/clk-si514.c2
-rw-r--r--drivers/clk/clk-si521xx.c6
-rw-r--r--drivers/clk/clk-si5341.c2
-rw-r--r--drivers/clk/clk-si5351.c6
-rw-r--r--drivers/clk/clk-si544.c53
-rw-r--r--drivers/clk/clk-si570.c69
-rw-r--r--drivers/clk/clk-twl.c197
-rw-r--r--drivers/clk/clk-versaclock3.c8
-rw-r--r--drivers/clk/clk-versaclock5.c2
-rw-r--r--drivers/clk/clk-versaclock7.c2
-rw-r--r--drivers/clk/clk.c86
-rw-r--r--drivers/clk/clk_test.c130
-rw-r--r--drivers/clk/davinci/da8xx-cfgchip.c8
-rw-r--r--drivers/clk/davinci/pll.c10
-rw-r--r--drivers/clk/davinci/psc.c10
-rw-r--r--drivers/clk/imx/Kconfig1
-rw-r--r--drivers/clk/imx/clk-imx6sx.c14
-rw-r--r--drivers/clk/imx/clk-imx8-acm.c33
-rw-r--r--drivers/clk/imx/clk-imx8dxl-rsrc.c3
-rw-r--r--drivers/clk/imx/clk-imx8mq.c17
-rw-r--r--drivers/clk/imx/clk-imx8qm-rsrc.c5
-rw-r--r--drivers/clk/imx/clk-imx8qxp-lpcg.h1
-rw-r--r--drivers/clk/imx/clk-imx8qxp-rsrc.c4
-rw-r--r--drivers/clk/imx/clk-imx8qxp.c13
-rw-r--r--drivers/clk/imx/clk-scu.c20
-rw-r--r--drivers/clk/keystone/pll.c15
-rw-r--r--drivers/clk/mediatek/clk-mt2701.c8
-rw-r--r--drivers/clk/mediatek/clk-mt6765.c6
-rw-r--r--drivers/clk/mediatek/clk-mt6779.c4
-rw-r--r--drivers/clk/mediatek/clk-mt6797.c6
-rw-r--r--drivers/clk/mediatek/clk-mt7629-eth.c4
-rw-r--r--drivers/clk/mediatek/clk-mt7629.c6
-rw-r--r--drivers/clk/mediatek/clk-pll.c6
-rw-r--r--drivers/clk/meson/Kconfig25
-rw-r--r--drivers/clk/meson/Makefile2
-rw-r--r--drivers/clk/meson/s4-peripherals.c3813
-rw-r--r--drivers/clk/meson/s4-peripherals.h56
-rw-r--r--drivers/clk/meson/s4-pll.c867
-rw-r--r--drivers/clk/meson/s4-pll.h38
-rw-r--r--drivers/clk/qcom/Kconfig18
-rw-r--r--drivers/clk/qcom/Makefile2
-rw-r--r--drivers/clk/qcom/apss-ipq-pll.c4
-rw-r--r--drivers/clk/qcom/apss-ipq6018.c61
-rw-r--r--drivers/clk/qcom/camcc-sm8550.c3565
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.c92
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.h3
-rw-r--r--drivers/clk/qcom/clk-cbf-8996.c12
-rw-r--r--drivers/clk/qcom/clk-hfpll.c4
-rw-r--r--drivers/clk/qcom/clk-hfpll.h1
-rw-r--r--drivers/clk/qcom/clk-rcg2.c14
-rw-r--r--drivers/clk/qcom/clk-rpmh.c21
-rw-r--r--drivers/clk/qcom/clk-smd-rpm.c16
-rw-r--r--drivers/clk/qcom/gcc-ipq5018.c6
-rw-r--r--drivers/clk/qcom/gcc-ipq5332.c4
-rw-r--r--drivers/clk/qcom/gcc-ipq6018.c27
-rw-r--r--drivers/clk/qcom/gcc-ipq8074.c6
-rw-r--r--drivers/clk/qcom/gcc-ipq9574.c4
-rw-r--r--drivers/clk/qcom/gcc-msm8960.c13
-rw-r--r--drivers/clk/qcom/gcc-msm8974.c10
-rw-r--r--drivers/clk/qcom/gcc-msm8996.c237
-rw-r--r--drivers/clk/qcom/gcc-sm4450.c2898
-rw-r--r--drivers/clk/qcom/gcc-sm8150.c2
-rw-r--r--drivers/clk/qcom/gpucc-sm8550.c10
-rw-r--r--drivers/clk/qcom/hfpll.c59
-rw-r--r--drivers/clk/qcom/kpss-xcc.c9
-rw-r--r--drivers/clk/qcom/krait-cc.c14
-rw-r--r--drivers/clk/qcom/mmcc-msm8960.c16
-rw-r--r--drivers/clk/qcom/mmcc-msm8974.c18
-rw-r--r--drivers/clk/qcom/mmcc-msm8998.c7
-rw-r--r--drivers/clk/qcom/mmcc-sdm660.c8
-rw-r--r--drivers/clk/qcom/videocc-sm8550.c10
-rw-r--r--drivers/clk/ralink/clk-mtmips.c20
-rw-r--r--drivers/clk/renesas/Kconfig7
-rw-r--r--drivers/clk/renesas/Makefile1
-rw-r--r--drivers/clk/renesas/r8a7795-cpg-mssr.c4
-rw-r--r--drivers/clk/renesas/r9a06g032-clocks.c69
-rw-r--r--drivers/clk/renesas/r9a07g043-cpg.c19
-rw-r--r--drivers/clk/renesas/r9a07g044-cpg.c19
-rw-r--r--drivers/clk/renesas/r9a08g045-cpg.c248
-rw-r--r--drivers/clk/renesas/rcar-cpg-lib.c15
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.c467
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.h39
-rw-r--r--drivers/clk/rockchip/clk-rk3128.c24
-rw-r--r--drivers/clk/rockchip/clk-rk3399.c9
-rw-r--r--drivers/clk/rockchip/clk-rk3568.c1
-rw-r--r--drivers/clk/samsung/clk-exynos-clkout.c8
-rw-r--r--drivers/clk/sifive/Kconfig2
-rw-r--r--drivers/clk/sifive/sifive-prci.c10
-rw-r--r--drivers/clk/socfpga/clk-agilex.c12
-rw-r--r--drivers/clk/socfpga/clk-gate.c27
-rw-r--r--drivers/clk/socfpga/clk-s10.c6
-rw-r--r--drivers/clk/socfpga/stratix10-clk.h4
-rw-r--r--drivers/clk/sprd/composite.h36
-rw-r--r--drivers/clk/sprd/div.c6
-rw-r--r--drivers/clk/sprd/div.h17
-rw-r--r--drivers/clk/stm32/clk-stm32-core.c2
-rw-r--r--drivers/clk/ti/adpll.c14
-rw-r--r--drivers/clk/ti/clk-44xx.c5
-rw-r--r--drivers/clk/ti/clk-54xx.c4
-rw-r--r--drivers/clk/ti/divider.c8
-rw-r--r--drivers/clk/visconti/pll.c6
-rw-r--r--drivers/clk/visconti/pll.h4
-rw-r--r--drivers/clocksource/Kconfig11
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/arm_arch_timer.c36
-rw-r--r--drivers/clocksource/timer-atmel-tcb.c1
-rw-r--r--drivers/clocksource/timer-ep93xx.c190
-rw-r--r--drivers/clocksource/timer-imx-gpt.c18
-rw-r--r--drivers/clocksource/timer-riscv.c23
-rw-r--r--drivers/clocksource/timer-sun5i.c4
-rw-r--r--drivers/clocksource/timer-ti-dm.c36
-rw-r--r--drivers/comedi/Kconfig45
-rw-r--r--drivers/comedi/drivers.c3
-rw-r--r--drivers/comedi/drivers/8255.c2
-rw-r--r--drivers/comedi/drivers/8255_pci.c15
-rw-r--r--drivers/comedi/drivers/adl_pci9111.c8
-rw-r--r--drivers/comedi/drivers/adl_pci9118.c8
-rw-r--r--drivers/comedi/drivers/adv_pci1710.c8
-rw-r--r--drivers/comedi/drivers/adv_pci_dio.c14
-rw-r--r--drivers/comedi/drivers/aio_aio12_8.c10
-rw-r--r--drivers/comedi/drivers/amplc_dio200_common.c104
-rw-r--r--drivers/comedi/drivers/amplc_dio200_pci.c12
-rw-r--r--drivers/comedi/drivers/amplc_pc236_common.c2
-rw-r--r--drivers/comedi/drivers/amplc_pci224.c8
-rw-r--r--drivers/comedi/drivers/amplc_pci230.c10
-rw-r--r--drivers/comedi/drivers/cb_das16_cs.c8
-rw-r--r--drivers/comedi/drivers/cb_pcidas.c23
-rw-r--r--drivers/comedi/drivers/cb_pcidas64.c7
-rw-r--r--drivers/comedi/drivers/cb_pcidda.c2
-rw-r--r--drivers/comedi/drivers/cb_pcimdas.c12
-rw-r--r--drivers/comedi/drivers/cb_pcimdda.c2
-rw-r--r--drivers/comedi/drivers/comedi_8254.c234
-rw-r--r--drivers/comedi/drivers/comedi_8255.c123
-rw-r--r--drivers/comedi/drivers/daqboard2000.c4
-rw-r--r--drivers/comedi/drivers/das08.c11
-rw-r--r--drivers/comedi/drivers/das16.c10
-rw-r--r--drivers/comedi/drivers/das16m1.c22
-rw-r--r--drivers/comedi/drivers/das1800.c8
-rw-r--r--drivers/comedi/drivers/das6402.c8
-rw-r--r--drivers/comedi/drivers/das800.c8
-rw-r--r--drivers/comedi/drivers/dmm32at.c3
-rw-r--r--drivers/comedi/drivers/me4000.c6
-rw-r--r--drivers/comedi/drivers/ni_at_a2150.c8
-rw-r--r--drivers/comedi/drivers/ni_at_ao.c8
-rw-r--r--drivers/comedi/drivers/ni_atmio16d.c2
-rw-r--r--drivers/comedi/drivers/ni_daq_dio24.c2
-rw-r--r--drivers/comedi/drivers/ni_labpc_common.c51
-rw-r--r--drivers/comedi/drivers/ni_mio_common.c74
-rw-r--r--drivers/comedi/drivers/pcl711.c8
-rw-r--r--drivers/comedi/drivers/pcl724.c6
-rw-r--r--drivers/comedi/drivers/pcl812.c10
-rw-r--r--drivers/comedi/drivers/pcl816.c8
-rw-r--r--drivers/comedi/drivers/pcl818.c8
-rw-r--r--drivers/comedi/drivers/pcm3724.c2
-rw-r--r--drivers/comedi/drivers/rtd520.c6
-rw-r--r--drivers/connector/cn_proc.c2
-rw-r--r--drivers/counter/counter-chrdev.c4
-rw-r--r--drivers/counter/microchip-tcb-capture.c2
-rw-r--r--drivers/cpufreq/Kconfig11
-rw-r--r--drivers/cpufreq/Kconfig.arm6
-rw-r--r--drivers/cpufreq/Makefile1
-rw-r--r--drivers/cpufreq/amd-pstate.c71
-rw-r--r--drivers/cpufreq/cpufreq-dt-platdev.c7
-rw-r--r--drivers/cpufreq/cpufreq.c7
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c3
-rw-r--r--drivers/cpufreq/cpufreq_stats.c14
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c76
-rw-r--r--drivers/cpufreq/ia64-acpi-cpufreq.c353
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c2
-rw-r--r--drivers/cpufreq/intel_pstate.c6
-rw-r--r--drivers/cpufreq/pmac32-cpufreq.c7
-rw-r--r--drivers/cpufreq/qcom-cpufreq-nvmem.c337
-rw-r--r--drivers/cpufreq/scmi-cpufreq.c52
-rw-r--r--drivers/cpufreq/tegra194-cpufreq.c153
-rw-r--r--drivers/cpufreq/ti-cpufreq.c1
-rw-r--r--drivers/cpuidle/dt_idle_states.c4
-rw-r--r--drivers/crypto/Kconfig1
-rw-r--r--drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c7
-rw-r--r--drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c11
-rw-r--r--drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c11
-rw-r--r--drivers/crypto/amcc/crypto4xx_core.c6
-rw-r--r--drivers/crypto/amlogic/amlogic-gxl-core.c5
-rw-r--r--drivers/crypto/aspeed/aspeed-acry.c6
-rw-r--r--drivers/crypto/aspeed/aspeed-hace.c16
-rw-r--r--drivers/crypto/atmel-aes.c6
-rw-r--r--drivers/crypto/atmel-sha.c8
-rw-r--r--drivers/crypto/atmel-tdes.c6
-rw-r--r--drivers/crypto/axis/artpec6_crypto.c8
-rw-r--r--drivers/crypto/bcm/cipher.c5
-rw-r--r--drivers/crypto/caam/caamalg.c3
-rw-r--r--drivers/crypto/caam/caamalg_qi2.c3
-rw-r--r--drivers/crypto/caam/jr.c22
-rw-r--r--drivers/crypto/cavium/nitrox/nitrox_hal.c2
-rw-r--r--drivers/crypto/ccp/dbc.c74
-rw-r--r--drivers/crypto/ccp/dbc.h29
-rw-r--r--drivers/crypto/ccp/psp-dev.c122
-rw-r--r--drivers/crypto/ccp/psp-dev.h55
-rw-r--r--drivers/crypto/ccp/sev-dev.c14
-rw-r--r--drivers/crypto/ccp/sp-dev.h4
-rw-r--r--drivers/crypto/ccp/sp-pci.c22
-rw-r--r--drivers/crypto/ccp/sp-platform.c6
-rw-r--r--drivers/crypto/ccp/tee-dev.c48
-rw-r--r--drivers/crypto/ccp/tee-dev.h15
-rw-r--r--drivers/crypto/ccree/cc_driver.c6
-rw-r--r--drivers/crypto/chelsio/chcr_algo.c9
-rw-r--r--drivers/crypto/exynos-rng.c6
-rw-r--r--drivers/crypto/gemini/sl3516-ce-core.c6
-rw-r--r--drivers/crypto/hifn_795x.c11
-rw-r--r--drivers/crypto/hisilicon/debugfs.c75
-rw-r--r--drivers/crypto/hisilicon/hpre/hpre_crypto.c25
-rw-r--r--drivers/crypto/hisilicon/hpre/hpre_main.c21
-rw-r--r--drivers/crypto/hisilicon/qm.c508
-rw-r--r--drivers/crypto/hisilicon/qm_common.h6
-rw-r--r--drivers/crypto/hisilicon/sec/sec_drv.c6
-rw-r--r--drivers/crypto/hisilicon/sec2/sec_crypto.c32
-rw-r--r--drivers/crypto/hisilicon/sec2/sec_main.c29
-rw-r--r--drivers/crypto/hisilicon/trng/trng.c6
-rw-r--r--drivers/crypto/hisilicon/zip/zip_crypto.c290
-rw-r--r--drivers/crypto/hisilicon/zip/zip_main.c23
-rw-r--r--drivers/crypto/img-hash.c6
-rw-r--r--drivers/crypto/inside-secure/safexcel.c6
-rw-r--r--drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c6
-rw-r--r--drivers/crypto/intel/keembay/keembay-ocs-aes-core.c6
-rw-r--r--drivers/crypto/intel/keembay/keembay-ocs-ecc.c6
-rw-r--r--drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c15
-rw-r--r--drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c245
-rw-r--r--drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h30
-rw-r--r--drivers/crypto/intel/qat/qat_4xxx/adf_drv.c36
-rw-r--r--drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c1
-rw-r--r--drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c1
-rw-r--r--drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c1
-rw-r--r--drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c1
-rw-r--r--drivers/crypto/intel/qat/qat_c62x/adf_drv.c1
-rw-r--r--drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c1
-rw-r--r--drivers/crypto/intel/qat/qat_common/Makefile10
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_accel_devices.h61
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_admin.c156
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_admin.h27
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_aer.c3
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_cfg_services.c20
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_cfg_services.h24
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h1
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_clock.c1
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_cnv_dbgfs.c300
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_cnv_dbgfs.h11
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_common_drv.h20
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_dbgfs.c6
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_fw_counters.c3
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h7
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c27
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h50
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c266
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c1566
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_gen4_ras.h825
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_gen4_timer.c1
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_heartbeat.c1
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.c1
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_init.c63
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_isr.c18
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs.c48
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs.h12
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_rl.c1169
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_rl.h176
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_rl_admin.c97
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_rl_admin.h18
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_sysfs.c112
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_sysfs_ras_counters.c112
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_sysfs_ras_counters.h27
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_sysfs_rl.c451
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_sysfs_rl.h11
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_transport_debug.c4
-rw-r--r--drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h82
-rw-r--r--drivers/crypto/intel/qat/qat_common/icp_qat_hw.h2
-rw-r--r--drivers/crypto/intel/qat/qat_common/qat_algs_send.c46
-rw-r--r--drivers/crypto/intel/qat/qat_common/qat_comp_algs.c129
-rw-r--r--drivers/crypto/intel/qat/qat_common/qat_uclo.c2
-rw-r--r--drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c1
-rw-r--r--drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c1
-rw-r--r--drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c1
-rw-r--r--drivers/crypto/marvell/cesa/cesa.c6
-rw-r--r--drivers/crypto/mxs-dcp.c8
-rw-r--r--drivers/crypto/n2_core.c12
-rw-r--r--drivers/crypto/omap-aes.c6
-rw-r--r--drivers/crypto/omap-des.c6
-rw-r--r--drivers/crypto/omap-sham.c22
-rw-r--r--drivers/crypto/qce/core.c5
-rw-r--r--drivers/crypto/qcom-rng.c71
-rw-r--r--drivers/crypto/rockchip/rk3288_crypto.c5
-rw-r--r--drivers/crypto/rockchip/rk3288_crypto_ahash.c3
-rw-r--r--drivers/crypto/s5p-sss.c12
-rw-r--r--drivers/crypto/sa2ul.c6
-rw-r--r--drivers/crypto/sahara.c6
-rw-r--r--drivers/crypto/starfive/jh7110-hash.c13
-rw-r--r--drivers/crypto/stm32/stm32-crc32.c17
-rw-r--r--drivers/crypto/stm32/stm32-cryp.c16
-rw-r--r--drivers/crypto/stm32/stm32-hash.c20
-rw-r--r--drivers/crypto/talitos.c23
-rw-r--r--drivers/crypto/virtio/virtio_crypto_common.h3
-rw-r--r--drivers/crypto/virtio/virtio_crypto_core.c14
-rw-r--r--drivers/crypto/vmx/aesp8-ppc.pl141
-rw-r--r--drivers/crypto/xilinx/zynqmp-aes-gcm.c6
-rw-r--r--drivers/crypto/xilinx/zynqmp-sha.c7
-rw-r--r--drivers/cxl/acpi.c3
-rw-r--r--drivers/cxl/core/core.h2
-rw-r--r--drivers/cxl/core/hdm.c98
-rw-r--r--drivers/cxl/core/mbox.c60
-rw-r--r--drivers/cxl/core/memdev.c188
-rw-r--r--drivers/cxl/core/pci.c284
-rw-r--r--drivers/cxl/core/pmu.c2
-rw-r--r--drivers/cxl/core/port.c188
-rw-r--r--drivers/cxl/core/region.c271
-rw-r--r--drivers/cxl/core/regs.c73
-rw-r--r--drivers/cxl/cxl.h38
-rw-r--r--drivers/cxl/cxlmem.h17
-rw-r--r--drivers/cxl/mem.c7
-rw-r--r--drivers/cxl/pci.c107
-rw-r--r--drivers/cxl/port.c3
-rw-r--r--drivers/dax/bus.c2
-rw-r--r--drivers/dax/kmem.c62
-rw-r--r--drivers/devfreq/devfreq.c14
-rw-r--r--drivers/devfreq/event/exynos-ppmu.c13
-rw-r--r--drivers/devfreq/event/rockchip-dfi.c814
-rw-r--r--drivers/devfreq/mtk-cci-devfreq.c9
-rw-r--r--drivers/devfreq/rk3399_dmc.c10
-rw-r--r--drivers/dma-buf/dma-fence-unwrap.c13
-rw-r--r--drivers/dma-buf/dma-resv.c2
-rw-r--r--drivers/dma-buf/st-dma-fence-chain.c12
-rw-r--r--drivers/dma-buf/st-dma-fence.c4
-rw-r--r--drivers/dma-buf/sync_file.c9
-rw-r--r--drivers/dma/Kconfig2
-rw-r--r--drivers/dma/altera-msgdma.c6
-rw-r--r--drivers/dma/apple-admac.c8
-rw-r--r--drivers/dma/at_hdmac.c8
-rw-r--r--drivers/dma/at_xdmac.c6
-rw-r--r--drivers/dma/bcm-sba-raid.c6
-rw-r--r--drivers/dma/bcm2835-dma.c6
-rw-r--r--drivers/dma/bestcomm/bestcomm.c6
-rw-r--r--drivers/dma/dma-axi-dmac.c11
-rw-r--r--drivers/dma/dma-jz4780.c6
-rw-r--r--drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c162
-rw-r--r--drivers/dma/dw-axi-dmac/dw-axi-dmac.h6
-rw-r--r--drivers/dma/dw/platform.c6
-rw-r--r--drivers/dma/ep93xx_dma.c2
-rw-r--r--drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c1
-rw-r--r--drivers/dma/fsl-edma-common.c26
-rw-r--r--drivers/dma/fsl-edma-common.h16
-rw-r--r--drivers/dma/fsl-edma-main.c39
-rw-r--r--drivers/dma/fsl-qdma.c5
-rw-r--r--drivers/dma/fsl_raid.c6
-rw-r--r--drivers/dma/fsldma.c6
-rw-r--r--drivers/dma/hisi_dma.c2
-rw-r--r--drivers/dma/idma64.c6
-rw-r--r--drivers/dma/idxd/Makefile6
-rw-r--r--drivers/dma/idxd/cdev.c7
-rw-r--r--drivers/dma/idxd/device.c5
-rw-r--r--drivers/dma/idxd/dma.c6
-rw-r--r--drivers/dma/idxd/idxd.h9
-rw-r--r--drivers/dma/idxd/irq.c4
-rw-r--r--drivers/dma/idxd/registers.h12
-rw-r--r--drivers/dma/idxd/submit.c14
-rw-r--r--drivers/dma/idxd/sysfs.c34
-rw-r--r--drivers/dma/img-mdc-dma.c6
-rw-r--r--drivers/dma/imx-dma.c6
-rw-r--r--drivers/dma/imx-sdma.c5
-rw-r--r--drivers/dma/k3dma.c30
-rw-r--r--drivers/dma/mcf-edma-main.c6
-rw-r--r--drivers/dma/mediatek/mtk-cqdma.c6
-rw-r--r--drivers/dma/mediatek/mtk-hsdma.c6
-rw-r--r--drivers/dma/mediatek/mtk-uart-apdma.c9
-rw-r--r--drivers/dma/mmp_pdma.c10
-rw-r--r--drivers/dma/mmp_tdma.c35
-rw-r--r--drivers/dma/moxart-dma.c11
-rw-r--r--drivers/dma/mpc512x_dma.c6
-rw-r--r--drivers/dma/mv_xor.c11
-rw-r--r--drivers/dma/mv_xor_v2.c6
-rw-r--r--drivers/dma/nbpfaxi.c6
-rw-r--r--drivers/dma/owl-dma.c6
-rw-r--r--drivers/dma/ppc4xx/adma.c5
-rw-r--r--drivers/dma/pxa_dma.c26
-rw-r--r--drivers/dma/qcom/bam_dma.c8
-rw-r--r--drivers/dma/qcom/hidma.c8
-rw-r--r--drivers/dma/qcom/qcom_adm.c6
-rw-r--r--drivers/dma/sa11x0-dma.c12
-rw-r--r--drivers/dma/sf-pdma/sf-pdma.c6
-rw-r--r--drivers/dma/sf-pdma/sf-pdma.h2
-rw-r--r--drivers/dma/sh/rcar-dmac.c6
-rw-r--r--drivers/dma/sh/rz-dmac.c6
-rw-r--r--drivers/dma/sh/shdmac.c6
-rw-r--r--drivers/dma/sh/usb-dmac.c8
-rw-r--r--drivers/dma/sprd-dma.c22
-rw-r--r--drivers/dma/st_fdma.c18
-rw-r--r--drivers/dma/st_fdma.h2
-rw-r--r--drivers/dma/ste_dma40.c1
-rw-r--r--drivers/dma/stm32-dma.c38
-rw-r--r--drivers/dma/stm32-mdma.c46
-rw-r--r--drivers/dma/sun4i-dma.c6
-rw-r--r--drivers/dma/sun6i-dma.c6
-rw-r--r--drivers/dma/tegra186-gpc-dma.c8
-rw-r--r--drivers/dma/tegra20-apb-dma.c6
-rw-r--r--drivers/dma/tegra210-adma.c8
-rw-r--r--drivers/dma/ti/cppi41.c5
-rw-r--r--drivers/dma/ti/edma.c12
-rw-r--r--drivers/dma/ti/k3-psil-am62.c12
-rw-r--r--drivers/dma/ti/k3-psil-am62a.c12
-rw-r--r--drivers/dma/ti/omap-dma.c11
-rw-r--r--drivers/dma/timb_dma.c5
-rw-r--r--drivers/dma/txx9dmac.c10
-rw-r--r--drivers/dma/uniphier-xdmac.c8
-rw-r--r--drivers/dma/xgene-dma.c6
-rw-r--r--drivers/dma/xilinx/xdma-regs.h2
-rw-r--r--drivers/dma/xilinx/xdma.c187
-rw-r--r--drivers/dma/xilinx/xilinx_dma.c8
-rw-r--r--drivers/dma/xilinx/xilinx_dpdma.c6
-rw-r--r--drivers/dma/xilinx/zynqmp_dma.c6
-rw-r--r--drivers/dpll/Kconfig7
-rw-r--r--drivers/dpll/Makefile9
-rw-r--r--drivers/dpll/dpll_core.c798
-rw-r--r--drivers/dpll/dpll_core.h89
-rw-r--r--drivers/dpll/dpll_netlink.c1433
-rw-r--r--drivers/dpll/dpll_netlink.h13
-rw-r--r--drivers/dpll/dpll_nl.c164
-rw-r--r--drivers/dpll/dpll_nl.h51
-rw-r--r--drivers/edac/Kconfig12
-rw-r--r--drivers/edac/Makefile1
-rw-r--r--drivers/edac/edac_mc_sysfs.c4
-rw-r--r--drivers/edac/versal_edac.c1069
-rw-r--r--drivers/extcon/Kconfig11
-rw-r--r--drivers/extcon/Makefile1
-rw-r--r--drivers/extcon/extcon-max77693.c7
-rw-r--r--drivers/extcon/extcon-max77843.c7
-rw-r--r--drivers/extcon/extcon-rtk-type-c.c1794
-rw-r--r--drivers/firewire/core-device.c11
-rw-r--r--drivers/firewire/core.h2
-rw-r--r--drivers/firewire/sbp2.c5
-rw-r--r--drivers/firmware/Kconfig41
-rw-r--r--drivers/firmware/Makefile4
-rw-r--r--drivers/firmware/arm_ffa/bus.c16
-rw-r--r--drivers/firmware/arm_ffa/driver.c794
-rw-r--r--drivers/firmware/arm_scmi/Kconfig12
-rw-r--r--drivers/firmware/arm_scmi/Makefile1
-rw-r--r--drivers/firmware/arm_scmi/clock.c402
-rw-r--r--drivers/firmware/arm_scmi/driver.c1
-rw-r--r--drivers/firmware/arm_scmi/perf.c128
-rw-r--r--drivers/firmware/arm_scmi/powercap.c4
-rw-r--r--drivers/firmware/arm_scmi/smc.c35
-rw-r--r--drivers/firmware/arm_scpi.c13
-rw-r--r--drivers/firmware/efi/Kconfig6
-rw-r--r--drivers/firmware/efi/efi-init.c14
-rw-r--r--drivers/firmware/efi/efi.c21
-rw-r--r--drivers/firmware/efi/libstub/Makefile9
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-entry.c8
-rw-r--r--drivers/firmware/efi/libstub/loongarch-stub.c4
-rw-r--r--drivers/firmware/efi/libstub/loongarch.c6
-rw-r--r--drivers/firmware/efi/libstub/x86-stub.c84
-rw-r--r--drivers/firmware/efi/unaccepted_memory.c84
-rw-r--r--drivers/firmware/imx/Kconfig6
-rw-r--r--drivers/firmware/imx/imx-dsp.c2
-rw-r--r--drivers/firmware/meson/meson_sm.c25
-rw-r--r--drivers/firmware/pcdp.c135
-rw-r--r--drivers/firmware/pcdp.h108
-rw-r--r--drivers/firmware/qcom/Kconfig56
-rw-r--r--drivers/firmware/qcom/Makefile9
-rw-r--r--drivers/firmware/qcom/qcom_qseecom.c120
-rw-r--r--drivers/firmware/qcom/qcom_qseecom_uefisecapp.c871
-rw-r--r--drivers/firmware/qcom/qcom_scm-legacy.c (renamed from drivers/firmware/qcom_scm-legacy.c)0
-rw-r--r--drivers/firmware/qcom/qcom_scm-smc.c (renamed from drivers/firmware/qcom_scm-smc.c)0
-rw-r--r--drivers/firmware/qcom/qcom_scm.c (renamed from drivers/firmware/qcom_scm.c)448
-rw-r--r--drivers/firmware/qcom/qcom_scm.h (renamed from drivers/firmware/qcom_scm.h)16
-rw-r--r--drivers/firmware/qemu_fw_cfg.c2
-rw-r--r--drivers/firmware/raspberrypi.c1
-rw-r--r--drivers/firmware/tegra/bpmp-debugfs.c4
-rw-r--r--drivers/firmware/tegra/bpmp.c30
-rw-r--r--drivers/firmware/ti_sci.c69
-rw-r--r--drivers/firmware/xilinx/zynqmp.c2
-rw-r--r--drivers/fpga/altera-hps2fpga.c12
-rw-r--r--drivers/fpga/altera-ps-spi.c46
-rw-r--r--drivers/fpga/tests/Kconfig4
-rw-r--r--drivers/fpga/tests/fpga-region-test.c2
-rw-r--r--drivers/fpga/versal-fpga.c2
-rw-r--r--drivers/fpga/xilinx-pr-decoupler.c17
-rw-r--r--drivers/gpio/Kconfig8
-rw-r--r--drivers/gpio/gpio-altera.c6
-rw-r--r--drivers/gpio/gpio-amdpt.c6
-rw-r--r--drivers/gpio/gpio-aspeed.c6
-rw-r--r--drivers/gpio/gpio-brcmstb.c6
-rw-r--r--drivers/gpio/gpio-cadence.c6
-rw-r--r--drivers/gpio/gpio-davinci.c9
-rw-r--r--drivers/gpio/gpio-dln2.c6
-rw-r--r--drivers/gpio/gpio-dwapb.c1
-rw-r--r--drivers/gpio/gpio-eic-sprd.c73
-rw-r--r--drivers/gpio/gpio-em.c9
-rw-r--r--drivers/gpio/gpio-f7188x.c138
-rw-r--r--drivers/gpio/gpio-ftgpio010.c6
-rw-r--r--drivers/gpio/gpio-fxl6408.c2
-rw-r--r--drivers/gpio/gpio-grgpio.c6
-rw-r--r--drivers/gpio/gpio-hisi.c2
-rw-r--r--drivers/gpio/gpio-ljca.c246
-rw-r--r--drivers/gpio/gpio-loongson-64bit.c119
-rw-r--r--drivers/gpio/gpio-lpc18xx.c6
-rw-r--r--drivers/gpio/gpio-mb86s7x.c7
-rw-r--r--drivers/gpio/gpio-mm-lantiq.c6
-rw-r--r--drivers/gpio/gpio-mmio.c4
-rw-r--r--drivers/gpio/gpio-mockup.c88
-rw-r--r--drivers/gpio/gpio-mpc5200.c8
-rw-r--r--drivers/gpio/gpio-mpc8xxx.c6
-rw-r--r--drivers/gpio/gpio-mvebu.c15
-rw-r--r--drivers/gpio/gpio-omap.c9
-rw-r--r--drivers/gpio/gpio-pca953x.c305
-rw-r--r--drivers/gpio/gpio-pxa.c4
-rw-r--r--drivers/gpio/gpio-rcar.c9
-rw-r--r--drivers/gpio/gpio-rockchip.c10
-rw-r--r--drivers/gpio/gpio-sim.c76
-rw-r--r--drivers/gpio/gpio-tb10x.c6
-rw-r--r--drivers/gpio/gpio-tegra.c13
-rw-r--r--drivers/gpio/gpio-ts5500.c6
-rw-r--r--drivers/gpio/gpio-uniphier.c6
-rw-r--r--drivers/gpio/gpio-vf610.c67
-rw-r--r--drivers/gpio/gpio-xgene-sb.c7
-rw-r--r--drivers/gpio/gpio-xgs-iproc.c6
-rw-r--r--drivers/gpio/gpio-xilinx.c6
-rw-r--r--drivers/gpio/gpio-zynq.c5
-rw-r--r--drivers/gpio/gpiolib-acpi.c71
-rw-r--r--drivers/gpio/gpiolib-cdev.c7
-rw-r--r--drivers/gpio/gpiolib-of.c90
-rw-r--r--drivers/gpio/gpiolib-swnode.c33
-rw-r--r--drivers/gpio/gpiolib-sysfs.c17
-rw-r--r--drivers/gpio/gpiolib.c286
-rw-r--r--drivers/gpio/gpiolib.h14
-rw-r--r--drivers/gpu/drm/Kconfig7
-rw-r--r--drivers/gpu/drm/Makefile2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Makefile25
-rw-r--r--drivers/gpu/drm/amd/amdgpu/aldebaran.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h111
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c54
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c54
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c40
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c48
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c138
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c25
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c624
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c210
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c37
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell.h12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c144
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c166
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.h11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c35
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c217
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h32
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c45
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c207
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c352
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h115
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c41
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c169
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c631
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h45
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c92
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h30
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c30
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c93
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h37
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c35
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c878
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.h228
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c35
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c25
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h50
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c130
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h42
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c656
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.h91
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c73
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c28
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c243
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/athub_v1_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/athub_v2_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/athub_v2_1.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/athub_v3_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atom.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atombios_encoders.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik_sdma.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v10_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v11_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v6_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v8_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/df_v4_6_2.c34
-rw-r--r--drivers/gpu/drm/amd/amdgpu/df_v4_6_2.h31
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c160
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c203
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c93
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c185
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.c516
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.h29
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c271
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c215
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c33
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c34
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c428
-rw-r--r--drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ih_v6_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/imu_v11_0.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c623
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.h35
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v10_1.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v11_0.c62
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c166
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c589
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.h29
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmsch_v4_0.h12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/navi10_ih.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c372
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_11.h33
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c24
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nv.c20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v10_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v11_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v13_0.c110
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c75
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c62
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c25
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c58
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c115
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_dma.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smuio_v13_0.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15.c49
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15_common.h14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc21.c50
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h62
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v12_0.c389
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v12_0.h130
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v8_10.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c424
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.h30
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v2_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v3_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v4_0.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c80
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c1779
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.h35
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vega20_ih.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vpe_6_1_fw_if.h217
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c291
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vpe_v6_1.h29
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_chardev.c22
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.c97
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device.c19
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c129
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c10
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_migrate.c8
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c28
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c3
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_priv.h6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c7
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c57
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_svm.c198
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_svm.h6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.c64
-rw-r--r--drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c7
-rw-r--r--drivers/gpu/drm/amd/display/Makefile1
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c392
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c48
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c62
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c1
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c135
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c51
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c561
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c4
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c53
-rw-r--r--drivers/gpu/drm/amd/display/dc/Makefile7
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/Makefile9
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/bw_fixed.c (renamed from drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c)13
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/calcs_logger.h (renamed from drivers/gpu/drm/amd/display/dc/dml/calcs/calcs_logger.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/custom_float.c (renamed from drivers/gpu/drm/amd/display/dc/dml/calcs/custom_float.c)90
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c (renamed from drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c54
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile8
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dce120/dce120_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dalsmc.h11
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c64
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c154
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c1146
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.h63
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c471
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h203
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c538
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_debug.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c1713
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c55
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h92
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c228
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h12
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dp_types.h62
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_helper.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_hw_types.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_stream.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h25
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_abm.h24
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_audio.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce100/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce112/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce120/Makefile1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce80/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h12
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h33
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h216
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h24
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h64
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c37
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn201/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/Makefile1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c104
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn302/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn302/dcn302_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn303/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn303/dcn303_dccg.h18
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.c45
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.h18
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.c20
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.h18
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h18
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/Makefile4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c55
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.h40
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c27
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c177
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h169
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c50
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c54
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/Makefile20
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c805
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h190
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c267
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.h137
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.c526
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.h326
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.c53
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.h57
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.c60
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.h59
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.c58
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.h61
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubbub.c611
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubbub.h155
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubp.c241
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubp.h75
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.c171
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.h (renamed from drivers/gpu/drm/amd/display/dc/link/accessories/link_fpga.h)16
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.c59
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.h75
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.c53
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.h67
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c290
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.h74
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c559
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.h196
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c2148
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.h310
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/Makefile9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dc_features.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c46
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c826
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c81
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c589
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h44
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/Makefile97
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/cmntypes.h94
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c10315
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.h201
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/display_mode_core_structs.h1972
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/display_mode_lib_defines.h77
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/display_mode_util.c798
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/display_mode_util.h76
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c1008
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.h50
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_types.h42
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h125
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c915
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.h52
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_policy.c310
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_policy.h47
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c1265
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.h41
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c486
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.h144
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c747
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h232
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml_assert.h32
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml_depedencies.h33
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml_display_rq_dlg_calc.c585
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml_display_rq_dlg_calc.h63
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml_logging.h31
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hdcp/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/Makefile183
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h)36
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce100/dce100_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c)4
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce100/dce100_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c)30
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce112/dce112_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c)4
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce112/dce112_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c)4
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce80/dce80_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c)6
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce80/dce80_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c)40
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c)200
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h)11
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c)2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c)2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c)68
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h)3
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hwseq.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hwseq.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn302/dcn302_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dcn302/dcn302_hwseq.c)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn302/dcn302_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dcn302/dcn302_hwseq.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c64
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.h37
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c)13
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c)7
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h)0
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c)173
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h (renamed from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h)12
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c1227
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h87
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h (renamed from drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h)81
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h (renamed from drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h)2
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_types.h39
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h18
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h19
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/optc.h219
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h54
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/link.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/resource.h285
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/Makefile9
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dce60/irq_service_dce60.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn201/irq_service_dcn201.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c33
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.h19
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c427
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.h34
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/irq_service.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq_types.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/Makefile4
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c136
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/accessories/link_fpga.c95
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_detection.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dpms.c63
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_factory.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c71
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/os_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/dmub/dmub_srv.h74
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h243
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/Makefile1
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn303.c19
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn303.h19
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c64
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h17
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c552
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.h282
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c144
-rw-r--r--drivers/gpu/drm/amd/display/include/dal_types.h2
-rw-r--r--drivers/gpu/drm/amd/display/include/ddc_service_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/include/logger_types.h143
-rw-r--r--drivers/gpu/drm/amd/display/include/signal_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.c115
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c9
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_stats.h2
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.c22
-rw-r--r--drivers/gpu/drm/amd/include/amd_shared.h7
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_offset.h15255
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h53412
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_0_0_offset.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_5_0_offset.h10000
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_5_0_sh_mask.h36579
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_3_3_0_offset.h1395
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_3_3_0_sh_mask.h6722
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/mp/mp_13_0_2_sh_mask.h28
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/mp/mp_13_0_6_sh_mask.h28
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/mp/mp_14_0_0_offset.h359
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/mp/mp_14_0_0_sh_mask.h534
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h9402
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h57886
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/umc/umc_12_0_0_offset.h33
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/umc/umc_12_0_0_sh_mask.h95
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_4_0_0_offset.h422
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_4_0_0_sh_mask.h882
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_4_0_5_offset.h1797
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_4_0_5_sh_mask.h8614
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/vpe/vpe_6_1_0_offset.h1553
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/vpe/vpe_6_1_0_sh_mask.h4393
-rw-r--r--drivers/gpu/drm/amd/include/ivsrcid/vpe/irqsrcs_vpe_6_1.h40
-rw-r--r--drivers/gpu/drm/amd/include/kgd_kfd_interface.h16
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h185
-rw-r--r--drivers/gpu/drm/amd/include/pptable.h4
-rw-r--r--drivers/gpu/drm/amd/include/soc15_hw_ip.h1
-rw-r--r--drivers/gpu/drm/amd/include/soc15_ih_clientid.h2
-rw-r--r--drivers/gpu/drm/amd/include/umsch_mm_4_0_api_def.h437
-rw-r--r--drivers/gpu/drm/amd/pm/Makefile1
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_dpm.c66
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_pm.c995
-rw-r--r--drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h21
-rw-r--r--drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c2
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c3
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h20
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h2
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_pptable.h24
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c4
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/Makefile2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c256
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h51
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_6.h91
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h237
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h14
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_ppsmc.h10
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_pmfw.h157
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h143
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h23
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h6
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h230
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c305
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c108
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c160
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c36
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c95
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c8
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c296
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c54
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c579
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c1035
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c495
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c18
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/Makefile30
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c1729
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c1139
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.h28
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c6
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_internal.h3
-rw-r--r--drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c2
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_drv.c9
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_kms.c7
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_kms.h1
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c9
-rw-r--r--drivers/gpu/drm/arm/hdlcd_drv.c6
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.c6
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c8
-rw-r--r--drivers/gpu/drm/aspeed/aspeed_gfx_drv.c7
-rw-r--r--drivers/gpu/drm/ast/ast_dp.c70
-rw-r--r--drivers/gpu/drm/ast/ast_dp501.c38
-rw-r--r--drivers/gpu/drm/ast/ast_drv.c6
-rw-r--r--drivers/gpu/drm/ast/ast_drv.h96
-rw-r--r--drivers/gpu/drm/ast/ast_i2c.c20
-rw-r--r--drivers/gpu/drm/ast/ast_main.c24
-rw-r--r--drivers/gpu/drm/ast/ast_mm.c4
-rw-r--r--drivers/gpu/drm/ast/ast_mode.c262
-rw-r--r--drivers/gpu/drm/ast/ast_post.c26
-rw-r--r--drivers/gpu/drm/ast/ast_reg.h99
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c6
-rw-r--r--drivers/gpu/drm/bridge/Kconfig3
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511.h16
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_cec.c14
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c108
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7533.c7
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c11
-rw-r--r--drivers/gpu/drm/bridge/analogix/anx7625.c3
-rw-r--r--drivers/gpu/drm/bridge/cadence/Kconfig1
-rw-r--r--drivers/gpu/drm/bridge/chipone-icn6211.c2
-rw-r--r--drivers/gpu/drm/bridge/imx/Kconfig11
-rw-r--r--drivers/gpu/drm/bridge/imx/Makefile1
-rw-r--r--drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c917
-rw-r--r--drivers/gpu/drm/bridge/ite-it66121.c33
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt8912b.c22
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9211.c2
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9611uxc.c12
-rw-r--r--drivers/gpu/drm/bridge/lvds-codec.c12
-rw-r--r--drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c57
-rw-r--r--drivers/gpu/drm/bridge/panel.c2
-rw-r--r--drivers/gpu/drm/bridge/samsung-dsim.c80
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c6
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi.c2
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c99
-rw-r--r--drivers/gpu/drm/bridge/tc358767.c2
-rw-r--r--drivers/gpu/drm/bridge/tc358768.c383
-rw-r--r--drivers/gpu/drm/bridge/ti-dlpc3433.c2
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi83.c2
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi86.c15
-rw-r--r--drivers/gpu/drm/ci/arm.config1
-rw-r--r--drivers/gpu/drm/ci/arm64.config2
-rw-r--r--drivers/gpu/drm/ci/build.sh8
-rw-r--r--drivers/gpu/drm/ci/build.yml1
-rw-r--r--drivers/gpu/drm/ci/gitlab-ci.yml38
-rwxr-xr-xdrivers/gpu/drm/ci/igt_runner.sh31
-rw-r--r--drivers/gpu/drm/ci/image-tags.yml6
-rwxr-xr-xdrivers/gpu/drm/ci/lava-submit.sh6
-rw-r--r--drivers/gpu/drm/ci/test.yml34
-rw-r--r--drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt12
-rw-r--r--drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt20
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-amly-fails.txt9
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt32
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-apl-fails.txt11
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt1
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-cml-fails.txt14
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt38
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-glk-fails.txt17
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt41
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt7
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt25
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt1
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-tgl-flakes.txt5
-rw-r--r--drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt1
-rw-r--r--drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt0
-rw-r--r--drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt5
-rw-r--r--drivers/gpu/drm/ci/xfails/mediatek-mt8183-flakes.txt14
-rw-r--r--drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt14
-rw-r--r--drivers/gpu/drm/ci/xfails/meson-g12b-flakes.txt4
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-apq8016-flakes.txt4
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt2
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt4
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sc7180-fails.txt15
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sc7180-flakes.txt24
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sc7180-skips.txt18
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt9
-rw-r--r--drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt19
-rw-r--r--drivers/gpu/drm/ci/xfails/requirements.txt17
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt6
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3288-flakes.txt9
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt40
-rw-r--r--drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt28
-rwxr-xr-xdrivers/gpu/drm/ci/xfails/update-xfails.py204
-rw-r--r--drivers/gpu/drm/ci/xfails/virtio_gpu-none-flakes.txt0
-rw-r--r--drivers/gpu/drm/display/drm_dp_cec.c23
-rw-r--r--drivers/gpu/drm/display/drm_dp_helper.c47
-rw-r--r--drivers/gpu/drm/display/drm_dp_mst_topology.c170
-rw-r--r--drivers/gpu/drm/drm_atomic.c4
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c98
-rw-r--r--drivers/gpu/drm/drm_auth.c3
-rw-r--r--drivers/gpu/drm/drm_bridge.c4
-rw-r--r--drivers/gpu/drm/drm_bridge_connector.c38
-rw-r--r--drivers/gpu/drm/drm_buddy.c138
-rw-r--r--drivers/gpu/drm/drm_client.c17
-rw-r--r--drivers/gpu/drm/drm_connector.c17
-rw-r--r--drivers/gpu/drm/drm_crtc.c8
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h2
-rw-r--r--drivers/gpu/drm/drm_debugfs.c188
-rw-r--r--drivers/gpu/drm/drm_drv.c28
-rw-r--r--drivers/gpu/drm/drm_edid.c46
-rw-r--r--drivers/gpu/drm/drm_file.c48
-rw-r--r--drivers/gpu/drm/drm_fourcc.c8
-rw-r--r--drivers/gpu/drm/drm_framebuffer.c68
-rw-r--r--drivers/gpu/drm/drm_gem.c6
-rw-r--r--drivers/gpu/drm/drm_gpuvm.c (renamed from drivers/gpu/drm/drm_gpuva_mgr.c)409
-rw-r--r--drivers/gpu/drm/drm_internal.h27
-rw-r--r--drivers/gpu/drm/drm_ioc32.c4
-rw-r--r--drivers/gpu/drm/drm_ioctl.c3
-rw-r--r--drivers/gpu/drm/drm_lease.c4
-rw-r--r--drivers/gpu/drm/drm_mode_config.c2
-rw-r--r--drivers/gpu/drm/drm_panel_orientation_quirks.c6
-rw-r--r--drivers/gpu/drm/drm_prime.c33
-rw-r--r--drivers/gpu/drm/drm_syncobj.c3
-rw-r--r--drivers/gpu/drm/drm_sysfs.c22
-rw-r--r--drivers/gpu/drm/drm_vblank_work.c3
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_sched.c1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dma.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c2
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c8
-rw-r--r--drivers/gpu/drm/gma500/gma_display.h1
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_lvds_i2c.c2
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.h9
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_drv.h14
-rw-r--r--drivers/gpu/drm/gma500/psb_irq.c5
-rw-r--r--drivers/gpu/drm/gud/gud_pipe.c2
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c6
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c9
-rw-r--r--drivers/gpu/drm/hyperv/hyperv_drm_drv.c13
-rw-r--r--drivers/gpu/drm/i915/Makefile49
-rw-r--r--drivers/gpu/drm/i915/display/g4x_dp.c10
-rw-r--r--drivers/gpu/drm/i915/display/g4x_dp.h26
-rw-r--r--drivers/gpu/drm/i915/display/g4x_hdmi.c6
-rw-r--r--drivers/gpu/drm/i915/display/g4x_hdmi.h12
-rw-r--r--drivers/gpu/drm/i915/display/hsw_ips.c1
-rw-r--r--drivers/gpu/drm/i915/display/hsw_ips.h35
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_plane.c1
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_plane.h23
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_wm.h17
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi.c20
-rw-r--r--drivers/gpu/drm/i915/display/intel_acpi.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic_plane.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_audio.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_audio.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_bios.c26
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c119
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.c156
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_color_regs.h286
-rw-r--r--drivers/gpu/drm/i915/display/intel_combo_phy.c17
-rw-r--r--drivers/gpu/drm/i915/display/intel_connector.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_connector.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_crt.c71
-rw-r--r--drivers/gpu/drm/i915/display/intel_crt.h14
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.c118
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc_state_dump.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.c217
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.h17
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h13
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c40
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c517
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.h11
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_core.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_debugfs.c38
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.c156
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.h41
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_driver.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_irq.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.c10
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_map.c63
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_well.c52
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_well.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h57
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_wa.c48
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_wa.h13
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c1126
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.h39
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux.c49
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux_regs.h80
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_hdcp.c87
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_link_training.c47
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c242
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpio_phy.h96
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll.c57
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.c987
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.h33
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpt.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_drrs.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.c235
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.h9
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb_regs.h31
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsi_vbt.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_dvo.c19
-rw-r--r--drivers/gpu/drm/i915/display/intel_dvo.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb.c82
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb_pin.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc.c181
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_fdi.c169
-rw-r--r--drivers/gpu/drm/i915/display/intel_fdi.h8
-rw-r--r--drivers/gpu/drm/i915/display/intel_frontbuffer.c35
-rw-r--r--drivers/gpu/drm/i915/display/intel_frontbuffer.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_gmbus.c7
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp.c41
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp_gsc.c617
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp_gsc.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c590
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.h72
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.c127
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug.c87
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug_irq.c24
-rw-r--r--drivers/gpu/drm/i915/display/intel_link_bw.c212
-rw-r--r--drivers/gpu/drm/i915/display/intel_link_bw.h37
-rw-r--r--drivers/gpu/drm/i915/display/intel_lpe_audio.h18
-rw-r--r--drivers/gpu/drm/i915/display/intel_lspcon.c29
-rw-r--r--drivers/gpu/drm/i915/display/intel_lvds.c38
-rw-r--r--drivers/gpu/drm/i915/display/intel_lvds.h19
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_verify.c134
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_verify.h11
-rw-r--r--drivers/gpu/drm/i915/display/intel_overlay.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_overlay.h35
-rw-r--r--drivers/gpu/drm/i915/display/intel_panel.c19
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch_display.h53
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch_refclk.c7
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch_refclk.h23
-rw-r--r--drivers/gpu/drm/i915/display/intel_plane_initial.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_pmdemand.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c82
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo.c393
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo.h13
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo_regs.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_snps_phy.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_snps_phy.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.h8
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.c77
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_tv.c10
-rw-r--r--drivers/gpu/drm/i915/display/intel_tv.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_vblank.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_vblank.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc.c630
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc_regs.h397
-rw-r--r--drivers/gpu/drm/i915/display/intel_vga.c18
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr.c18
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_wm.c2
-rw-r--r--drivers/gpu/drm/i915/display/skl_scaler.c2
-rw-r--r--drivers/gpu/drm/i915/display/skl_universal_plane.c22
-rw-r--r--drivers/gpu/drm/i915/display/skl_watermark.c40
-rw-r--r--drivers/gpu/drm/i915/display/skl_watermark.h6
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi.c148
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi.h13
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi_pll.h9
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_clflush.c3
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_context.c1
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_create.c4
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_domain.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c24
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_mman.c7
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object.c1
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object.h89
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object_frontbuffer.h103
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_phys.c1
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_shrinker.c73
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c39
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/mock_context.c2
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_engine_cs.c17
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_ppgtt.c36
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine.h2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_cs.c74
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_pm.c2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_regs.h1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_types.h13
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_user.c56
-rw-r--r--drivers/gpu/drm/i915/gt/intel_execlists_submission.c4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ggtt.c300
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gsc.c11
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt.c88
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt.h72
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_mcr.c50
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_mcr.h1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_pm.c20
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_pm.h1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_print.h3
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_regs.h11
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gtt.c5
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gtt.h9
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc.c74
-rw-r--r--drivers/gpu/drm/i915/gt/intel_mocs.c25
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rc6.c25
-rw-r--r--drivers/gpu/drm/i915/gt/intel_reset.c62
-rw-r--r--drivers/gpu/drm/i915/gt/intel_reset.h2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rps.c2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_tlb.c16
-rw-r--r--drivers/gpu/drm/i915/gt/intel_workarounds.c420
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_migrate.c6
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_tlb.c11
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h33
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c8
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.c20
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.h6
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc.c70
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc.h39
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c4
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c46
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h2
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h2
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c63
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h2
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c254
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc.c7
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c40
-rw-r--r--drivers/gpu/drm/i915/gvt/gvt.h9
-rw-r--r--drivers/gpu/drm/i915/gvt/interrupt.c17
-rw-r--r--drivers/gpu/drm/i915/gvt/interrupt.h31
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/mmio_context.c8
-rw-r--r--drivers/gpu/drm/i915/gvt/mmio_context.h10
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c12
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs_params.c9
-rw-r--r--drivers/gpu/drm/i915/i915_driver.c24
-rw-r--r--drivers/gpu/drm/i915/i915_driver.h4
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h90
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c2
-rw-r--r--drivers/gpu/drm/i915/i915_getparam.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c15
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.h12
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c2
-rw-r--r--drivers/gpu/drm/i915/i915_params.c5
-rw-r--r--drivers/gpu/drm/i915/i915_params.h1
-rw-r--r--drivers/gpu/drm/i915/i915_pci.c5
-rw-r--r--drivers/gpu/drm/i915/i915_perf.c138
-rw-r--r--drivers/gpu/drm/i915/i915_perf_types.h6
-rw-r--r--drivers/gpu/drm/i915/i915_pmu.c18
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h290
-rw-r--r--drivers/gpu/drm/i915/i915_scatterlist.h10
-rw-r--r--drivers/gpu/drm/i915/i915_ttm_buddy_manager.c23
-rw-r--r--drivers/gpu/drm/i915/i915_vma.c1
-rw-r--r--drivers/gpu/drm/i915/i915_vma_resource.c2
-rw-r--r--drivers/gpu/drm/i915/intel_clock_gating.c60
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.c50
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.h6
-rw-r--r--drivers/gpu/drm/i915/intel_gvt_mmio_table.c4
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.c1
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.h4
-rw-r--r--drivers/gpu/drm/i915/intel_step.c6
-rw-r--r--drivers/gpu/drm/i915/intel_step.h1
-rw-r--r--drivers/gpu/drm/i915/intel_wakeref.c52
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp.c40
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp.h2
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h4
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.c17
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.h10
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_huc.c4
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_pm.c18
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_pm.h5
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_tee.c29
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_types.h9
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_request.c2
-rw-r--r--drivers/gpu/drm/i915/selftests/igt_live_test.c9
-rw-r--r--drivers/gpu/drm/i915/selftests/igt_live_test.h3
-rw-r--r--drivers/gpu/drm/i915/selftests/igt_spinner.c3
-rw-r--r--drivers/gpu/drm/i915/selftests/mock_gem_device.c3
-rw-r--r--drivers/gpu/drm/i915/soc/intel_gmch.c14
-rw-r--r--drivers/gpu/drm/i915/soc/intel_gmch.h2
-rw-r--r--drivers/gpu/drm/i915/soc/intel_pch.c12
-rw-r--r--drivers/gpu/drm/i915/soc/intel_pch.h2
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-drv.c8
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-kms.c7
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-kms.h1
-rw-r--r--drivers/gpu/drm/imx/ipuv3/dw_hdmi-imx.c6
-rw-r--r--drivers/gpu/drm/imx/ipuv3/imx-drm-core.c13
-rw-r--r--drivers/gpu/drm/imx/ipuv3/imx-ldb.c5
-rw-r--r--drivers/gpu/drm/imx/ipuv3/imx-tve.c5
-rw-r--r--drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c5
-rw-r--r--drivers/gpu/drm/imx/ipuv3/parallel-display.c6
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-drm-drv.c70
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-ipu.c5
-rw-r--r--drivers/gpu/drm/lima/lima_sched.c4
-rw-r--r--drivers/gpu/drm/logicvc/Kconfig2
-rw-r--r--drivers/gpu/drm/logicvc/logicvc_drm.c9
-rw-r--r--drivers/gpu/drm/loongson/lsdc_drv.c6
-rw-r--r--drivers/gpu/drm/loongson/lsdc_pixpll.c6
-rw-r--r--drivers/gpu/drm/mcde/mcde_drv.c9
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_aal.c87
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_drv.h5
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_gamma.c203
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dp.c42
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dp_reg.h23
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi.c9
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_crtc.c97
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_crtc.h6
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c34
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h17
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c52
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.h15
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_gem.c15
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_plane.c41
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dsi.c48
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.c8
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx.xml.h9
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c209
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.h3
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h8
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c655
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c69
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h65
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_hfi.c88
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c39
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c7
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h32
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h14
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h12
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h48
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c55
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c62
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c53
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h20
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c160
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h20
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c58
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c41
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c21
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h12
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c23
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c21
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c20
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c145
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c69
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h72
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c30
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h4
-rw-r--r--drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c118
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c114
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_ctrl.c13
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c71
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.h1
-rw-r--r--drivers/gpu/drm/msm/dp/dp_drm.c24
-rw-r--r--drivers/gpu/drm/msm/dp/dp_drm.h2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_link.c42
-rw-r--r--drivers/gpu/drm/msm/dp/dp_panel.c130
-rw-r--r--drivers/gpu/drm/msm/dp/dp_panel.h11
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c40
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.h5
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.xml.h1
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c66
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c30
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c2
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c28
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h5
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_bridge.c30
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_hpd.c3
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy.c6
-rw-r--r--drivers/gpu/drm/msm/msm_debugfs.c12
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c373
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h21
-rw-r--r--drivers/gpu/drm/msm/msm_gem_shrinker.c33
-rw-r--r--drivers/gpu/drm/msm/msm_kms.c345
-rw-r--r--drivers/gpu/drm/msm/msm_kms.h3
-rw-r--r--drivers/gpu/drm/msm/msm_mdss.c8
-rw-r--r--drivers/gpu/drm/msm/msm_ringbuffer.c5
-rw-r--r--drivers/gpu/drm/msm/msm_ringbuffer.h2
-rw-r--r--drivers/gpu/drm/nouveau/Kconfig1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.c2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/core.c1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c681
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.h6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/head.h1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/headc57d.c14
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl0080.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/class.h21
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/conn.h20
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0011.h21
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0012.h249
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/outp.h96
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/device.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/event.h4
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h7
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h6
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/layout.h6
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/memory.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h19
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h4
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h19
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/nvenc.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/nvjpg.h8
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/ofa.h9
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h4
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h6
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h435
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h9
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h11
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/alloc/alloc_channel.h170
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/class/cl0000.h38
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/class/cl0005.h38
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/class/cl0080.h43
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/class/cl2080.h35
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/class/cl2080_notification.h62
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/class/cl84a0.h33
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/class/cl90f1.h31
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/class/clc0b5sw.h34
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl0073/ctrl0073common.h39
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl0073/ctrl0073dfp.h166
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl0073/ctrl0073dp.h335
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl0073/ctrl0073specific.h216
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl0073/ctrl0073system.h65
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl0080/ctrl0080fifo.h57
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl0080/ctrl0080gpu.h48
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl0080/ctrl0080gr.h31
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080bios.h40
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080ce.h35
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080event.h41
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080fb.h51
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080fifo.h52
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080gpu.h100
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080gr.h41
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080internal.h162
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl90f1.h95
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrla06f/ctrla06fgpfifo.h42
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/nvlimits.h33
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/sdk/nvidia/inc/nvos.h148
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/shared/msgq/inc/msgq/msgq_priv.h97
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/common/uproc/os/common/include/libos_init_args.h52
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/arch/nvalloc/common/inc/gsp/gsp_fw_sr_meta.h79
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/arch/nvalloc/common/inc/gsp/gsp_fw_wpr_meta.h170
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/arch/nvalloc/common/inc/rmRiscvUcode.h82
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/arch/nvalloc/common/inc/rmgspseq.h100
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/generated/g_allclasses.h33
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/generated/g_chipset_nvoc.h38
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/generated/g_fbsr_nvoc.h31
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/generated/g_gpu_nvoc.h35
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/generated/g_kernel_channel_nvoc.h62
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/generated/g_kernel_fifo_nvoc.h119
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/generated/g_mem_desc_nvoc.h32
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/generated/g_os_nvoc.h44
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/generated/g_rpc-structures.h124
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/generated/g_sdk-structures.h45
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/inc/kernel/gpu/gpu_acpi_data.h74
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/inc/kernel/gpu/gpu_engine_type.h86
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/inc/kernel/gpu/gsp/gsp_fw_heap.h33
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/inc/kernel/gpu/gsp/gsp_init_args.h57
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/inc/kernel/gpu/gsp/gsp_static_config.h174
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/inc/kernel/gpu/intr/engine_idx.h57
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/inc/kernel/gpu/nvbitmask.h33
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/inc/kernel/os/nv_memory_type.h31
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/kernel/inc/vgpu/rpc_global_enums.h262
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/kernel/inc/vgpu/rpc_headers.h51
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/535.113.01/nvidia/kernel/inc/vgpu/sdk-structures.h40
-rw-r--r--drivers/gpu/drm/nouveau/include/nvrm/nvtypes.h24
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c90
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c13
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c251
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_debugfs.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c13
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c345
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h30
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_exec.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sched.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_svm.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_uvmm.c42
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_uvmm.h8
-rw-r--r--drivers/gpu/drm/nouveau/nvif/client.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvif/conn.c36
-rw-r--r--drivers/gpu/drm/nouveau/nvif/disp.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvif/outp.c412
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/event.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/firmware.c77
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/memory.c15
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/r535.c108
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/tu102.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/base.c190
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/user.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ad102.c52
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c154
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c362
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c17
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c38
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h17
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c184
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c147
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h43
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c1671
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c112
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c460
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/falcon.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/r535.c664
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ad102.c46
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/r535.c508
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ad102.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga100.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga102.c16
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/r535.c110
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/tu102.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvenc/Kbuild5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvenc/ad102.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvenc/base.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvenc/ga102.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvenc/priv.h5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvenc/r535.c110
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvenc/tu102.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvjpg/Kbuild5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvjpg/ad102.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvjpg/ga100.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvjpg/priv.h8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvjpg/r535.c107
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ofa/Kbuild6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ofa/ad102.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ofa/ga100.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ofa/ga102.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ofa/priv.h8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ofa/r535.c107
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/r535.c54
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/base.c16
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/ga100.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/tu102.c28
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/r535.c186
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/tu102.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bus/gf100.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/devinit/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/devinit/ga100.c15
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c51
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu102.c16
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/r535.c87
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c46
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gm107.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gpio/ga102.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ad102.c57
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c78
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c359
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga100.c74
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c148
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h57
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c2316
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c198
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu116.c57
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm200.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c49
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c45
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c27
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/r535.c333
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/ga102.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp102.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/r535.c123
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/privring/gm200.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/gp100.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/top/ga100.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/r535.c50
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c5
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c8
-rw-r--r--drivers/gpu/drm/panel/Kconfig29
-rw-r--r--drivers/gpu/drm/panel/Makefile3
-rw-r--r--drivers/gpu/drm/panel/panel-arm-versatile.c2
-rw-r--r--drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c9
-rw-r--r--drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c9
-rw-r--r--drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c385
-rw-r--r--drivers/gpu/drm/panel/panel-edp.c29
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9322.c8
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9882t.c779
-rw-r--r--drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c9
-rw-r--r--drivers/gpu/drm/panel/panel-jdi-lpm102a188a.c551
-rw-r--r--drivers/gpu/drm/panel/panel-jdi-lt070me05000.c4
-rw-r--r--drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c97
-rw-r--r--drivers/gpu/drm/panel/panel-newvision-nv3051d.c7
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt35950.c9
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt36523.c16
-rw-r--r--drivers/gpu/drm/panel/panel-orisetech-otm8009a.c17
-rw-r--r--drivers/gpu/drm/panel/panel-raydium-rm68200.c38
-rw-r--r--drivers/gpu/drm/panel/panel-raydium-rm692e5.c423
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6e63m0.c25
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c10
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-sofef00.c9
-rw-r--r--drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c10
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c130
-rw-r--r--drivers/gpu/drm/panel/panel-sitronix-st7703.c125
-rw-r--r--drivers/gpu/drm/panel/panel-sony-td4353-jdi.c9
-rw-r--r--drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c18
-rw-r--r--drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c11
-rw-r--r--drivers/gpu/drm/panel/panel-tpo-tpg110.c2
-rw-r--r--drivers/gpu/drm/panel/panel-truly-nt35597.c20
-rw-r--r--drivers/gpu/drm/panel/panel-visionox-r66451.c16
-rw-r--r--drivers/gpu/drm/panel/panel-visionox-rm69299.c8
-rw-r--r--drivers/gpu/drm/panel/panel-visionox-vtdr6130.c9
-rw-r--r--drivers/gpu/drm/panfrost/Makefile2
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_debugfs.c21
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_debugfs.h14
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_devfreq.c23
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_devfreq.h3
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_device.c2
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_device.h15
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_drv.c66
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_gem.c30
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_gem.h7
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c29
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_gpu.c45
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_gpu.h4
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_job.c29
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_job.h5
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_mmu.c5
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_regs.h5
-rw-r--r--drivers/gpu/drm/pl111/pl111_drv.c7
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c3
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c18
-rw-r--r--drivers/gpu/drm/radeon/atombios.h42
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c7
-rw-r--r--drivers/gpu/drm/radeon/pptable.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon.h4
-rw-r--r--drivers/gpu/drm/radeon/radeon_bios.c20
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c111
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c2
-rw-r--r--drivers/gpu/drm/renesas/shmobile/Kconfig3
-rw-r--r--drivers/gpu/drm/renesas/shmobile/Makefile3
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_backlight.c82
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_backlight.h19
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c650
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.h27
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c185
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.h18
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.c77
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.h9
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.c326
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.h5
-rw-r--r--drivers/gpu/drm/rockchip/cdn-dp-core.c17
-rw-r--r--drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c23
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_gem.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c74
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.h1
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop2.c122
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop2.h3
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_lvds.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop2_reg.c57
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop_reg.c121
-rw-r--r--drivers/gpu/drm/scheduler/sched_entity.c18
-rw-r--r--drivers/gpu/drm/scheduler/sched_main.c76
-rw-r--r--drivers/gpu/drm/solomon/Kconfig12
-rw-r--r--drivers/gpu/drm/solomon/ssd130x-i2c.c18
-rw-r--r--drivers/gpu/drm/solomon/ssd130x-spi.c27
-rw-r--r--drivers/gpu/drm/solomon/ssd130x.c728
-rw-r--r--drivers/gpu/drm/solomon/ssd130x.h21
-rw-r--r--drivers/gpu/drm/sti/sti_drv.c7
-rw-r--r--drivers/gpu/drm/stm/drv.c7
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c6
-rw-r--r--drivers/gpu/drm/tegra/dc.c9
-rw-r--r--drivers/gpu/drm/tegra/drm.h3
-rw-r--r--drivers/gpu/drm/tegra/dsi.c1
-rw-r--r--drivers/gpu/drm/tegra/gem.c32
-rw-r--r--drivers/gpu/drm/tegra/hdmi.c3
-rw-r--r--drivers/gpu/drm/tegra/hub.c2
-rw-r--r--drivers/gpu/drm/tegra/rgb.c16
-rw-r--r--drivers/gpu/drm/tegra/sor.c1
-rw-r--r--drivers/gpu/drm/tests/drm_format_helper_test.c1097
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c11
-rw-r--r--drivers/gpu/drm/tiny/bochs.c6
-rw-r--r--drivers/gpu/drm/tiny/cirrus.c6
-rw-r--r--drivers/gpu/drm/tiny/repaper.c2
-rw-r--r--drivers/gpu/drm/tiny/simpledrm.c107
-rw-r--r--drivers/gpu/drm/ttm/ttm_device.c8
-rw-r--r--drivers/gpu/drm/ttm/ttm_pool.c40
-rw-r--r--drivers/gpu/drm/tve200/tve200_drv.c7
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.h2
-rw-r--r--drivers/gpu/drm/v3d/v3d_sched.c5
-rw-r--r--drivers/gpu/drm/vboxvideo/vbox_drv.c10
-rw-r--r--drivers/gpu/drm/vc4/tests/vc4_mock_crtc.c2
-rw-r--r--drivers/gpu/drm/vc4/tests/vc4_mock_output.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c36
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h2
-rw-r--r--drivers/gpu/drm/vc4/vc4_regs.h2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.c2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h9
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_bo.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_bo.h17
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c12
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_gem.c24
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c12
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_shader.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_surface.c37
-rw-r--r--drivers/gpu/host1x/channel.c26
-rw-r--r--drivers/gpu/host1x/channel.h4
-rw-r--r--drivers/gpu/host1x/context.c4
-rw-r--r--drivers/gpu/host1x/dev.c32
-rw-r--r--drivers/gpu/host1x/dev.h3
-rw-r--r--drivers/gpu/host1x/hw/intr_hw.c46
-rw-r--r--drivers/greybus/Kconfig11
-rw-r--r--drivers/greybus/Makefile2
-rw-r--r--drivers/greybus/gb-beagleplay.c501
-rw-r--r--drivers/hid/Kconfig8
-rw-r--r--drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c7
-rw-r--r--drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h3
-rw-r--r--drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h21
-rw-r--r--drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c9
-rw-r--r--drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h15
-rw-r--r--drivers/hid/hid-apple.c4
-rw-r--r--drivers/hid/hid-asus.c27
-rw-r--r--drivers/hid/hid-core.c12
-rw-r--r--drivers/hid/hid-cp2112.c10
-rw-r--r--drivers/hid/hid-debug.c3
-rw-r--r--drivers/hid/hid-glorious.c16
-rw-r--r--drivers/hid/hid-ids.h14
-rw-r--r--drivers/hid/hid-lenovo.c119
-rw-r--r--drivers/hid/hid-logitech-dj.c11
-rw-r--r--drivers/hid/hid-logitech-hidpp.c174
-rw-r--r--drivers/hid/hid-mcp2221.c4
-rw-r--r--drivers/hid/hid-multitouch.c15
-rw-r--r--drivers/hid/hid-nintendo.c133
-rw-r--r--drivers/hid/hid-nvidia-shield.c21
-rw-r--r--drivers/hid/hid-picolcd_fb.c73
-rw-r--r--drivers/hid/hid-prodikeys.c8
-rw-r--r--drivers/hid/hid-quirks.c3
-rw-r--r--drivers/hid/hid-rmi.c10
-rw-r--r--drivers/hid/hid-uclogic-core-test.c7
-rw-r--r--drivers/hid/hid-uclogic-params-test.c16
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-acpi.c5
-rw-r--r--drivers/hid/usbhid/hid-core.c11
-rw-r--r--drivers/hte/Kconfig5
-rw-r--r--drivers/hte/hte-tegra194-test.c4
-rw-r--r--drivers/hte/hte-tegra194.c56
-rw-r--r--drivers/hte/hte.c15
-rw-r--r--drivers/hv/hv_common.c1
-rw-r--r--drivers/hv/vmbus_drv.c6
-rw-r--r--drivers/hwmon/Kconfig26
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/abituguru.c6
-rw-r--r--drivers/hwmon/abituguru3.c5
-rw-r--r--drivers/hwmon/acpi_power_meter.c9
-rw-r--r--drivers/hwmon/adt7475.c68
-rw-r--r--drivers/hwmon/aquacomputer_d5next.c72
-rw-r--r--drivers/hwmon/asus-ec-sensors.c12
-rw-r--r--drivers/hwmon/asus_wmi_sensors.c2
-rw-r--r--drivers/hwmon/axi-fan-control.c29
-rw-r--r--drivers/hwmon/coretemp.c2
-rw-r--r--drivers/hwmon/corsair-psu.c18
-rw-r--r--drivers/hwmon/da9052-hwmon.c6
-rw-r--r--drivers/hwmon/dme1737.c6
-rw-r--r--drivers/hwmon/f71805f.c6
-rw-r--r--drivers/hwmon/f71882fg.c5
-rw-r--r--drivers/hwmon/fam15h_power.c7
-rw-r--r--drivers/hwmon/hs3001.c2
-rw-r--r--drivers/hwmon/i5k_amb.c5
-rw-r--r--drivers/hwmon/ibmpowernv.c2
-rw-r--r--drivers/hwmon/ina238.c3
-rw-r--r--drivers/hwmon/ina3221.c33
-rw-r--r--drivers/hwmon/ltc2991.c437
-rw-r--r--drivers/hwmon/ltc2992.c6
-rw-r--r--drivers/hwmon/max197.c6
-rw-r--r--drivers/hwmon/max31827.c130
-rw-r--r--drivers/hwmon/mc13783-adc.c6
-rw-r--r--drivers/hwmon/nct6683.c3
-rw-r--r--drivers/hwmon/nct6775-core.c12
-rw-r--r--drivers/hwmon/nct6775-platform.c4
-rw-r--r--drivers/hwmon/npcm750-pwm-fan.c2
-rw-r--r--drivers/hwmon/nzxt-kraken2.c4
-rw-r--r--drivers/hwmon/occ/p9_sbe.c6
-rw-r--r--drivers/hwmon/pc87360.c6
-rw-r--r--drivers/hwmon/pc87427.c6
-rw-r--r--drivers/hwmon/pmbus/max31785.c188
-rw-r--r--drivers/hwmon/pmbus/mp2975.c10
-rw-r--r--drivers/hwmon/pmbus/mpq7932.c19
-rw-r--r--drivers/hwmon/pmbus/pmbus.h24
-rw-r--r--drivers/hwmon/pmbus/tda38640.c154
-rw-r--r--drivers/hwmon/powerz.c275
-rw-r--r--drivers/hwmon/sch5627.c267
-rw-r--r--drivers/hwmon/sch5636.c6
-rw-r--r--drivers/hwmon/sch56xx-common.c171
-rw-r--r--drivers/hwmon/sch56xx-common.h6
-rw-r--r--drivers/hwmon/sht15.c6
-rw-r--r--drivers/hwmon/sis5595.c6
-rw-r--r--drivers/hwmon/tmp513.c52
-rw-r--r--drivers/hwmon/ultra45_env.c6
-rw-r--r--drivers/hwmon/via-cputemp.c5
-rw-r--r--drivers/hwmon/via686a.c6
-rw-r--r--drivers/hwmon/vt1211.c6
-rw-r--r--drivers/hwmon/vt8231.c6
-rw-r--r--drivers/hwmon/w83627hf.c6
-rw-r--r--drivers/hwmon/w83781d.c7
-rw-r--r--drivers/hwmon/xgene-hwmon.c22
-rw-r--r--drivers/hwtracing/coresight/coresight-etm-perf.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x-core.c6
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-etr.c27
-rw-r--r--drivers/hwtracing/coresight/ultrasoc-smb.c58
-rw-r--r--drivers/hwtracing/coresight/ultrasoc-smb.h6
-rw-r--r--drivers/hwtracing/ptt/hisi_ptt.c14
-rw-r--r--drivers/i2c/busses/Kconfig12
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-aspeed.c3
-rw-r--r--drivers/i2c/busses/i2c-at91-core.c10
-rw-r--r--drivers/i2c/busses/i2c-axxia.c8
-rw-r--r--drivers/i2c/busses/i2c-bcm-iproc.c133
-rw-r--r--drivers/i2c/busses/i2c-brcmstb.c23
-rw-r--r--drivers/i2c/busses/i2c-cp2615.c4
-rw-r--r--drivers/i2c/busses/i2c-designware-common.c16
-rw-r--r--drivers/i2c/busses/i2c-designware-master.c19
-rw-r--r--drivers/i2c/busses/i2c-exynos5.c80
-rw-r--r--drivers/i2c/busses/i2c-gpio.c7
-rw-r--r--drivers/i2c/busses/i2c-i801.c110
-rw-r--r--drivers/i2c/busses/i2c-ljca.c343
-rw-r--r--drivers/i2c/busses/i2c-mt65xx.c12
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c11
-rw-r--r--drivers/i2c/busses/i2c-ocores.c4
-rw-r--r--drivers/i2c/busses/i2c-omap.c8
-rw-r--r--drivers/i2c/busses/i2c-powermac.c2
-rw-r--r--drivers/i2c/busses/i2c-pxa.c83
-rw-r--r--drivers/i2c/busses/i2c-qcom-geni.c1
-rw-r--r--drivers/i2c/busses/i2c-rcar.c180
-rw-r--r--drivers/i2c/busses/i2c-riic.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c7
-rw-r--r--drivers/i2c/busses/i2c-stm32f4.c32
-rw-r--r--drivers/i2c/busses/i2c-stm32f7.c98
-rw-r--r--drivers/i2c/busses/i2c-sun6i-p2wi.c5
-rw-r--r--drivers/i2c/busses/i2c-xgene-slimpro.c16
-rw-r--r--drivers/i2c/i2c-atr.c2
-rw-r--r--drivers/i2c/i2c-core-base.c19
-rw-r--r--drivers/i2c/i2c-core.h2
-rw-r--r--drivers/i2c/i2c-dev.c22
-rw-r--r--drivers/i2c/muxes/i2c-demux-pinctrl.c14
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpio.c19
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpmux.c2
-rw-r--r--drivers/i2c/muxes/i2c-mux-pinctrl.c2
-rw-r--r--drivers/i3c/master.c59
-rw-r--r--drivers/i3c/master/dw-i3c-master.c2
-rw-r--r--drivers/i3c/master/i3c-master-cdns.c8
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/cmd_v1.c1
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/core.c14
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/dat_v1.c29
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/dma.c21
-rw-r--r--drivers/i3c/master/svc-i3c-master.c60
-rw-r--r--drivers/idle/intel_idle.c18
-rw-r--r--drivers/iio/accel/Kconfig10
-rw-r--r--drivers/iio/accel/adxl345.h21
-rw-r--r--drivers/iio/accel/adxl345_core.c47
-rw-r--r--drivers/iio/accel/adxl345_i2c.c20
-rw-r--r--drivers/iio/accel/adxl345_spi.c20
-rw-r--r--drivers/iio/accel/bma180.c27
-rw-r--r--drivers/iio/accel/fxls8962af.h1
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c6
-rw-r--r--drivers/iio/accel/kionix-kx022a-i2c.c24
-rw-r--r--drivers/iio/accel/kionix-kx022a-spi.c19
-rw-r--r--drivers/iio/accel/kionix-kx022a.c351
-rw-r--r--drivers/iio/accel/kionix-kx022a.h114
-rw-r--r--drivers/iio/accel/mma8452.c28
-rw-r--r--drivers/iio/accel/msa311.c2
-rw-r--r--drivers/iio/accel/mxc4005.c8
-rw-r--r--drivers/iio/adc/Kconfig29
-rw-r--r--drivers/iio/adc/Makefile2
-rw-r--r--drivers/iio/adc/ab8500-gpadc.c6
-rw-r--r--drivers/iio/adc/ad4130.c15
-rw-r--r--drivers/iio/adc/ad7192.c298
-rw-r--r--drivers/iio/adc/at91-sama5d2_adc.c6
-rw-r--r--drivers/iio/adc/at91_adc.c114
-rw-r--r--drivers/iio/adc/axp20x_adc.c6
-rw-r--r--drivers/iio/adc/bcm_iproc_adc.c6
-rw-r--r--drivers/iio/adc/dln2-adc.c5
-rw-r--r--drivers/iio/adc/ep93xx_adc.c6
-rw-r--r--drivers/iio/adc/exynos_adc.c30
-rw-r--r--drivers/iio/adc/fsl-imx25-gcq.c6
-rw-r--r--drivers/iio/adc/hx711.c6
-rw-r--r--drivers/iio/adc/imx8qxp-adc.c10
-rw-r--r--drivers/iio/adc/imx93_adc.c6
-rw-r--r--drivers/iio/adc/ltc2309.c246
-rw-r--r--drivers/iio/adc/ltc2497.c5
-rw-r--r--drivers/iio/adc/max1363.c87
-rw-r--r--drivers/iio/adc/mcp3564.c1513
-rw-r--r--drivers/iio/adc/mcp3911.c562
-rw-r--r--drivers/iio/adc/meson_saradc.c22
-rw-r--r--drivers/iio/adc/mp2629_adc.c6
-rw-r--r--drivers/iio/adc/mt6577_auxadc.c72
-rw-r--r--drivers/iio/adc/mxs-lradc-adc.c6
-rw-r--r--drivers/iio/adc/npcm_adc.c6
-rw-r--r--drivers/iio/adc/palmas_gpadc.c2
-rw-r--r--drivers/iio/adc/qcom-pm8xxx-xoadc.c6
-rw-r--r--drivers/iio/adc/rcar-gyroadc.c6
-rw-r--r--drivers/iio/adc/spear_adc.c64
-rw-r--r--drivers/iio/adc/stm32-adc-core.c12
-rw-r--r--drivers/iio/adc/stm32-adc.c8
-rw-r--r--drivers/iio/adc/stm32-dfsdm-adc.c6
-rw-r--r--drivers/iio/adc/stm32-dfsdm-core.c6
-rw-r--r--drivers/iio/adc/sun4i-gpadc-iio.c8
-rw-r--r--drivers/iio/adc/ti-adc081c.c12
-rw-r--r--drivers/iio/adc/ti-ads1015.c7
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c6
-rw-r--r--drivers/iio/adc/twl4030-madc.c6
-rw-r--r--drivers/iio/adc/twl6030-gpadc.c16
-rw-r--r--drivers/iio/adc/vf610_adc.c6
-rw-r--r--drivers/iio/adc/xilinx-xadc-core.c39
-rw-r--r--drivers/iio/adc/xilinx-xadc.h2
-rw-r--r--drivers/iio/addac/Kconfig3
-rw-r--r--drivers/iio/addac/ad74413r.c24
-rw-r--r--drivers/iio/addac/stx104.c61
-rw-r--r--drivers/iio/afe/iio-rescale.c19
-rw-r--r--drivers/iio/amplifiers/hmc425a.c17
-rw-r--r--drivers/iio/chemical/atlas-ezo-sensor.c6
-rw-r--r--drivers/iio/chemical/atlas-sensor.c32
-rw-r--r--drivers/iio/chemical/sgp30.c24
-rw-r--r--drivers/iio/chemical/vz89x.c16
-rw-r--r--drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c6
-rw-r--r--drivers/iio/dac/ad3552r.c4
-rw-r--r--drivers/iio/dac/dpot-dac.c6
-rw-r--r--drivers/iio/dac/lpc18xx_dac.c6
-rw-r--r--drivers/iio/dac/mcp4725.c42
-rw-r--r--drivers/iio/dac/stm32-dac-core.c15
-rw-r--r--drivers/iio/dac/stm32-dac.c9
-rw-r--r--drivers/iio/dac/ti-dac5571.c48
-rw-r--r--drivers/iio/dac/vf610_dac.c6
-rw-r--r--drivers/iio/frequency/adf4350.c75
-rw-r--r--drivers/iio/frequency/admv1013.c4
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c6
-rw-r--r--drivers/iio/humidity/hid-sensor-humidity.c6
-rw-r--r--drivers/iio/humidity/si7005.c7
-rw-r--r--drivers/iio/iio_core.h3
-rw-r--r--drivers/iio/imu/adis16475.c238
-rw-r--r--drivers/iio/imu/bno055/Kconfig2
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_aux.c13
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c3
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h2
-rw-r--r--drivers/iio/industrialio-core.c4
-rw-r--r--drivers/iio/industrialio-event.c55
-rw-r--r--drivers/iio/light/cm3605.c6
-rw-r--r--drivers/iio/light/hid-sensor-als.c136
-rw-r--r--drivers/iio/light/hid-sensor-prox.c6
-rw-r--r--drivers/iio/light/lm3533-als.c6
-rw-r--r--drivers/iio/light/opt4001.c2
-rw-r--r--drivers/iio/light/vcnl4000.c1
-rw-r--r--drivers/iio/magnetometer/ak8975.c97
-rw-r--r--drivers/iio/magnetometer/hid-sensor-magn-3d.c6
-rw-r--r--drivers/iio/magnetometer/yamaha-yas530.c4
-rw-r--r--drivers/iio/orientation/hid-sensor-incl-3d.c6
-rw-r--r--drivers/iio/orientation/hid-sensor-rotation.c6
-rw-r--r--drivers/iio/position/hid-sensor-custom-intel-hinge.c6
-rw-r--r--drivers/iio/potentiometer/ad5110.c21
-rw-r--r--drivers/iio/potentiometer/ds1803.c13
-rw-r--r--drivers/iio/pressure/Kconfig9
-rw-r--r--drivers/iio/pressure/Makefile1
-rw-r--r--drivers/iio/pressure/bmp280-core.c2
-rw-r--r--drivers/iio/pressure/dps310.c8
-rw-r--r--drivers/iio/pressure/hid-sensor-press.c6
-rw-r--r--drivers/iio/pressure/ms5611_core.c2
-rw-r--r--drivers/iio/pressure/ms5637.c6
-rw-r--r--drivers/iio/pressure/rohm-bm1390.c934
-rw-r--r--drivers/iio/proximity/cros_ec_mkbp_proximity.c6
-rw-r--r--drivers/iio/proximity/irsd200.c6
-rw-r--r--drivers/iio/proximity/srf04.c6
-rw-r--r--drivers/iio/proximity/sx9310.c46
-rw-r--r--drivers/iio/resolver/Kconfig13
-rw-r--r--drivers/iio/resolver/Makefile1
-rw-r--r--drivers/iio/resolver/ad2s1210.c1519
-rw-r--r--drivers/iio/temperature/hid-sensor-temperature.c6
-rw-r--r--drivers/iio/temperature/mlx90614.c2
-rw-r--r--drivers/iio/temperature/tmp117.c94
-rw-r--r--drivers/iio/trigger/iio-trig-interrupt.c6
-rw-r--r--drivers/iio/trigger/stm32-timer-trigger.c6
-rw-r--r--drivers/infiniband/core/cache.c2
-rw-r--r--drivers/infiniband/core/core_priv.h1
-rw-r--r--drivers/infiniband/core/device.c4
-rw-r--r--drivers/infiniband/core/iwcm.c1
-rw-r--r--drivers/infiniband/core/lag.c3
-rw-r--r--drivers/infiniband/core/nldev.c92
-rw-r--r--drivers/infiniband/core/rw.c2
-rw-r--r--drivers/infiniband/core/sa_query.c4
-rw-r--r--drivers/infiniband/core/sysfs.c14
-rw-r--r--drivers/infiniband/core/ucma.c1
-rw-r--r--drivers/infiniband/core/umem.c6
-rw-r--r--drivers/infiniband/core/user_mad.c4
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c3
-rw-r--r--drivers/infiniband/core/uverbs_std_types_device.c3
-rw-r--r--drivers/infiniband/core/verbs.c9
-rw-r--r--drivers/infiniband/hw/bnxt_re/main.c175
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_tlv.h2
-rw-r--r--drivers/infiniband/hw/bnxt_re/roce_hsi.h58
-rw-r--r--drivers/infiniband/hw/hfi1/affinity.c2
-rw-r--r--drivers/infiniband/hw/hfi1/affinity.h2
-rw-r--r--drivers/infiniband/hw/hfi1/aspm.h2
-rw-r--r--drivers/infiniband/hw/hfi1/chip.c11
-rw-r--r--drivers/infiniband/hw/hfi1/chip.h2
-rw-r--r--drivers/infiniband/hw/hfi1/chip_registers.h2
-rw-r--r--drivers/infiniband/hw/hfi1/common.h2
-rw-r--r--drivers/infiniband/hw/hfi1/debugfs.c2
-rw-r--r--drivers/infiniband/hw/hfi1/debugfs.h2
-rw-r--r--drivers/infiniband/hw/hfi1/device.c2
-rw-r--r--drivers/infiniband/hw/hfi1/device.h2
-rw-r--r--drivers/infiniband/hw/hfi1/driver.c2
-rw-r--r--drivers/infiniband/hw/hfi1/efivar.c4
-rw-r--r--drivers/infiniband/hw/hfi1/efivar.h2
-rw-r--r--drivers/infiniband/hw/hfi1/eprom.c2
-rw-r--r--drivers/infiniband/hw/hfi1/eprom.h2
-rw-r--r--drivers/infiniband/hw/hfi1/exp_rcv.c2
-rw-r--r--drivers/infiniband/hw/hfi1/exp_rcv.h2
-rw-r--r--drivers/infiniband/hw/hfi1/fault.c2
-rw-r--r--drivers/infiniband/hw/hfi1/fault.h2
-rw-r--r--drivers/infiniband/hw/hfi1/file_ops.c4
-rw-r--r--drivers/infiniband/hw/hfi1/firmware.c2
-rw-r--r--drivers/infiniband/hw/hfi1/hfi.h2
-rw-r--r--drivers/infiniband/hw/hfi1/init.c3
-rw-r--r--drivers/infiniband/hw/hfi1/intr.c2
-rw-r--r--drivers/infiniband/hw/hfi1/iowait.h2
-rw-r--r--drivers/infiniband/hw/hfi1/ipoib_tx.c2
-rw-r--r--drivers/infiniband/hw/hfi1/mad.c2
-rw-r--r--drivers/infiniband/hw/hfi1/mad.h2
-rw-r--r--drivers/infiniband/hw/hfi1/mmu_rb.c2
-rw-r--r--drivers/infiniband/hw/hfi1/mmu_rb.h2
-rw-r--r--drivers/infiniband/hw/hfi1/opa_compat.h2
-rw-r--r--drivers/infiniband/hw/hfi1/pcie.c11
-rw-r--r--drivers/infiniband/hw/hfi1/pio.c2
-rw-r--r--drivers/infiniband/hw/hfi1/pio.h2
-rw-r--r--drivers/infiniband/hw/hfi1/pio_copy.c2
-rw-r--r--drivers/infiniband/hw/hfi1/platform.c2
-rw-r--r--drivers/infiniband/hw/hfi1/platform.h2
-rw-r--r--drivers/infiniband/hw/hfi1/qp.c2
-rw-r--r--drivers/infiniband/hw/hfi1/qp.h2
-rw-r--r--drivers/infiniband/hw/hfi1/qsfp.c2
-rw-r--r--drivers/infiniband/hw/hfi1/qsfp.h2
-rw-r--r--drivers/infiniband/hw/hfi1/rc.c2
-rw-r--r--drivers/infiniband/hw/hfi1/ruc.c2
-rw-r--r--drivers/infiniband/hw/hfi1/sdma.c2
-rw-r--r--drivers/infiniband/hw/hfi1/sdma.h2
-rw-r--r--drivers/infiniband/hw/hfi1/sdma_txreq.h2
-rw-r--r--drivers/infiniband/hw/hfi1/sysfs.c2
-rw-r--r--drivers/infiniband/hw/hfi1/trace.c2
-rw-r--r--drivers/infiniband/hw/hfi1/trace.h2
-rw-r--r--drivers/infiniband/hw/hfi1/trace_ctxts.h2
-rw-r--r--drivers/infiniband/hw/hfi1/trace_dbg.h2
-rw-r--r--drivers/infiniband/hw/hfi1/trace_ibhdrs.h2
-rw-r--r--drivers/infiniband/hw/hfi1/trace_misc.h2
-rw-r--r--drivers/infiniband/hw/hfi1/trace_mmu.h2
-rw-r--r--drivers/infiniband/hw/hfi1/trace_rc.h2
-rw-r--r--drivers/infiniband/hw/hfi1/trace_rx.h2
-rw-r--r--drivers/infiniband/hw/hfi1/trace_tx.h2
-rw-r--r--drivers/infiniband/hw/hfi1/uc.c2
-rw-r--r--drivers/infiniband/hw/hfi1/ud.c2
-rw-r--r--drivers/infiniband/hw/hfi1/user_exp_rcv.c2
-rw-r--r--drivers/infiniband/hw/hfi1/user_exp_rcv.h4
-rw-r--r--drivers/infiniband/hw/hfi1/user_pages.c2
-rw-r--r--drivers/infiniband/hw/hfi1/user_sdma.c2
-rw-r--r--drivers/infiniband/hw/hfi1/user_sdma.h2
-rw-r--r--drivers/infiniband/hw/hfi1/verbs.c2
-rw-r--r--drivers/infiniband/hw/hfi1/verbs.h2
-rw-r--r--drivers/infiniband/hw/hfi1/verbs_txreq.c2
-rw-r--r--drivers/infiniband/hw/hfi1/verbs_txreq.h2
-rw-r--r--drivers/infiniband/hw/hfi1/vnic.h2
-rw-r--r--drivers/infiniband/hw/hfi1/vnic_main.c2
-rw-r--r--drivers/infiniband/hw/hfi1/vnic_sdma.c2
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_ah.c13
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_device.h6
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v2.c103
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_main.c24
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_qp.c2
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_restrack.c49
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_srq.c85
-rw-r--r--drivers/infiniband/hw/irdma/cm.c2
-rw-r--r--drivers/infiniband/hw/irdma/cm.h2
-rw-r--r--drivers/infiniband/hw/irdma/ctrl.c2
-rw-r--r--drivers/infiniband/hw/irdma/defs.h2
-rw-r--r--drivers/infiniband/hw/irdma/hmc.c2
-rw-r--r--drivers/infiniband/hw/irdma/hmc.h2
-rw-r--r--drivers/infiniband/hw/irdma/hw.c18
-rw-r--r--drivers/infiniband/hw/irdma/i40iw_hw.c2
-rw-r--r--drivers/infiniband/hw/irdma/i40iw_hw.h2
-rw-r--r--drivers/infiniband/hw/irdma/i40iw_if.c4
-rw-r--r--drivers/infiniband/hw/irdma/icrdma_hw.c2
-rw-r--r--drivers/infiniband/hw/irdma/icrdma_hw.h2
-rw-r--r--drivers/infiniband/hw/irdma/irdma.h2
-rw-r--r--drivers/infiniband/hw/irdma/main.c4
-rw-r--r--drivers/infiniband/hw/irdma/main.h4
-rw-r--r--drivers/infiniband/hw/irdma/osdep.h2
-rw-r--r--drivers/infiniband/hw/irdma/pble.c2
-rw-r--r--drivers/infiniband/hw/irdma/pble.h2
-rw-r--r--drivers/infiniband/hw/irdma/protos.h2
-rw-r--r--drivers/infiniband/hw/irdma/puda.c2
-rw-r--r--drivers/infiniband/hw/irdma/puda.h2
-rw-r--r--drivers/infiniband/hw/irdma/trace.c2
-rw-r--r--drivers/infiniband/hw/irdma/trace.h2
-rw-r--r--drivers/infiniband/hw/irdma/trace_cm.h2
-rw-r--r--drivers/infiniband/hw/irdma/type.h2
-rw-r--r--drivers/infiniband/hw/irdma/uda.c2
-rw-r--r--drivers/infiniband/hw/irdma/uda.h2
-rw-r--r--drivers/infiniband/hw/irdma/uda_d.h2
-rw-r--r--drivers/infiniband/hw/irdma/uk.c2
-rw-r--r--drivers/infiniband/hw/irdma/user.h2
-rw-r--r--drivers/infiniband/hw/irdma/utils.c2
-rw-r--r--drivers/infiniband/hw/irdma/verbs.c269
-rw-r--r--drivers/infiniband/hw/irdma/verbs.h5
-rw-r--r--drivers/infiniband/hw/irdma/ws.c2
-rw-r--r--drivers/infiniband/hw/irdma/ws.h2
-rw-r--r--drivers/infiniband/hw/mlx5/mad.c13
-rw-r--r--drivers/infiniband/hw/mlx5/main.c27
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h21
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c326
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c29
-rw-r--r--drivers/infiniband/hw/mlx5/umr.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.h2
-rw-r--r--drivers/infiniband/hw/qib/qib_file_ops.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_fs.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c2
-rw-r--r--drivers/infiniband/hw/usnic/usnic_uiom.h2
-rw-r--r--drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c12
-rw-r--r--drivers/infiniband/sw/rdmavt/ah.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/ah.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/cq.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/cq.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/mad.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/mad.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/mcast.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/mcast.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/mmap.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/mmap.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/mr.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/mr.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/pd.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/pd.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/qp.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/qp.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/rc.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/srq.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/srq.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/trace.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/trace.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/trace_cq.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/trace_mr.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/trace_qp.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/trace_rc.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/trace_rvt.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/trace_tx.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/vt.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/vt.h2
-rw-r--r--drivers/infiniband/sw/siw/iwarp.h2
-rw-r--r--drivers/infiniband/sw/siw/siw.h4
-rw-r--r--drivers/infiniband/sw/siw/siw_cm.c2
-rw-r--r--drivers/infiniband/sw/siw/siw_cm.h2
-rw-r--r--drivers/infiniband/sw/siw/siw_cq.c2
-rw-r--r--drivers/infiniband/sw/siw/siw_main.c2
-rw-r--r--drivers/infiniband/sw/siw/siw_mem.c2
-rw-r--r--drivers/infiniband/sw/siw/siw_mem.h2
-rw-r--r--drivers/infiniband/sw/siw/siw_qp.c2
-rw-r--r--drivers/infiniband/sw/siw/siw_qp_rx.c2
-rw-r--r--drivers/infiniband/sw/siw/siw_qp_tx.c2
-rw-r--r--drivers/infiniband/sw/siw/siw_verbs.c2
-rw-r--r--drivers/infiniband/sw/siw/siw_verbs.h2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ethtool.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c3
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt.c14
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-srv.c37
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs.c2
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.h2
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c3
-rw-r--r--drivers/input/evdev.c2
-rw-r--r--drivers/input/input-leds.c2
-rw-r--r--drivers/input/joystick/walkera0701.c13
-rw-r--r--drivers/input/joystick/xpad.c4
-rw-r--r--drivers/input/keyboard/adp5520-keys.c6
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c16
-rw-r--r--drivers/input/keyboard/ep93xx_keypad.c6
-rw-r--r--drivers/input/keyboard/iqs62x-keys.c6
-rw-r--r--drivers/input/keyboard/matrix_keypad.c6
-rw-r--r--drivers/input/keyboard/omap-keypad.c6
-rw-r--r--drivers/input/keyboard/omap4-keypad.c6
-rw-r--r--drivers/input/keyboard/samsung-keypad.c6
-rw-r--r--drivers/input/keyboard/sh_keysc.c6
-rw-r--r--drivers/input/keyboard/spear-keyboard.c6
-rw-r--r--drivers/input/keyboard/stmpe-keypad.c6
-rw-r--r--drivers/input/keyboard/tegra-kbc.c7
-rw-r--r--drivers/input/misc/88pm80x_onkey.c5
-rw-r--r--drivers/input/misc/axp20x-pek.c11
-rw-r--r--drivers/input/misc/da9052_onkey.c6
-rw-r--r--drivers/input/misc/da9055_onkey.c6
-rw-r--r--drivers/input/misc/ideapad_slidebar.c6
-rw-r--r--drivers/input/misc/iqs269a.c10
-rw-r--r--drivers/input/misc/kxtj9.c29
-rw-r--r--drivers/input/misc/m68kspkr.c6
-rw-r--r--drivers/input/misc/max8997_haptic.c6
-rw-r--r--drivers/input/misc/mc13783-pwrbutton.c6
-rw-r--r--drivers/input/misc/palmas-pwrbutton.c6
-rw-r--r--drivers/input/misc/pcap_keys.c6
-rw-r--r--drivers/input/misc/pcf50633-input.c6
-rw-r--r--drivers/input/misc/pcspkr.c6
-rw-r--r--drivers/input/misc/pm8941-pwrkey.c6
-rw-r--r--drivers/input/misc/powermate.c1
-rw-r--r--drivers/input/misc/soc_button_array.c6
-rw-r--r--drivers/input/misc/sparcspkr.c12
-rw-r--r--drivers/input/misc/wistron_btns.c6
-rw-r--r--drivers/input/misc/wm831x-on.c6
-rw-r--r--drivers/input/mouse/cyapa.c14
-rw-r--r--drivers/input/mouse/elantech.c1
-rw-r--r--drivers/input/mouse/navpoint.c6
-rw-r--r--drivers/input/mouse/psmouse-smbus.c19
-rw-r--r--drivers/input/mouse/synaptics.c2
-rw-r--r--drivers/input/rmi4/rmi_bus.c2
-rw-r--r--drivers/input/rmi4/rmi_f34.c2
-rw-r--r--drivers/input/rmi4/rmi_smbus.c50
-rw-r--r--drivers/input/serio/altera_ps2.c6
-rw-r--r--drivers/input/serio/ams_delta_serio.c6
-rw-r--r--drivers/input/serio/apbps2.c6
-rw-r--r--drivers/input/serio/arc_ps2.c6
-rw-r--r--drivers/input/serio/ct82c710.c6
-rw-r--r--drivers/input/serio/i8042-acpipnpio.h8
-rw-r--r--drivers/input/serio/i8042-sparcio.h6
-rw-r--r--drivers/input/serio/i8042.c6
-rw-r--r--drivers/input/serio/i8042.h2
-rw-r--r--drivers/input/serio/ioc3kbd.c6
-rw-r--r--drivers/input/serio/maceps2.c6
-rw-r--r--drivers/input/serio/olpc_apsp.c6
-rw-r--r--drivers/input/serio/ps2-gpio.c5
-rw-r--r--drivers/input/serio/q40kbd.c6
-rw-r--r--drivers/input/serio/rpckbd.c6
-rw-r--r--drivers/input/serio/sun4i-ps2.c6
-rw-r--r--drivers/input/serio/xilinx_ps2.c6
-rw-r--r--drivers/input/touchscreen/ad7877.c12
-rw-r--r--drivers/input/touchscreen/ad7879-i2c.c7
-rw-r--r--drivers/input/touchscreen/ad7879-spi.c7
-rw-r--r--drivers/input/touchscreen/ad7879.c10
-rw-r--r--drivers/input/touchscreen/ad7879.h3
-rw-r--r--drivers/input/touchscreen/ads7846.c18
-rw-r--r--drivers/input/touchscreen/cyttsp5.c19
-rw-r--r--drivers/input/touchscreen/da9052_tsi.c6
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c10
-rw-r--r--drivers/input/touchscreen/elants_i2c.c15
-rw-r--r--drivers/input/touchscreen/exc3000.c12
-rw-r--r--drivers/input/touchscreen/goodix.c19
-rw-r--r--drivers/input/touchscreen/hideep.c15
-rw-r--r--drivers/input/touchscreen/hycon-hy46xx.c10
-rw-r--r--drivers/input/touchscreen/ili210x.c15
-rw-r--r--drivers/input/touchscreen/ilitek_ts_i2c.c12
-rw-r--r--drivers/input/touchscreen/iqs5xx.c10
-rw-r--r--drivers/input/touchscreen/mainstone-wm97xx.c6
-rw-r--r--drivers/input/touchscreen/mc13783_ts.c6
-rw-r--r--drivers/input/touchscreen/melfas_mip4.c13
-rw-r--r--drivers/input/touchscreen/pcap_ts.c6
-rw-r--r--drivers/input/touchscreen/raydium_i2c_ts.c16
-rw-r--r--drivers/input/touchscreen/rohm_bu21023.c12
-rw-r--r--drivers/input/touchscreen/s6sy761.c10
-rw-r--r--drivers/input/touchscreen/stmfts.c10
-rw-r--r--drivers/input/touchscreen/stmpe-ts.c6
-rw-r--r--drivers/input/touchscreen/sun4i-ts.c6
-rw-r--r--drivers/input/touchscreen/ti_am335x_tsc.c5
-rw-r--r--drivers/input/touchscreen/tsc2004.c7
-rw-r--r--drivers/input/touchscreen/tsc2005.c7
-rw-r--r--drivers/input/touchscreen/tsc200x-core.c18
-rw-r--r--drivers/input/touchscreen/tsc200x-core.h1
-rw-r--r--drivers/input/touchscreen/wdt87xx_i2c.c16
-rw-r--r--drivers/input/touchscreen/wm831x-ts.c6
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c6
-rw-r--r--drivers/interconnect/imx/imx.h9
-rw-r--r--drivers/interconnect/qcom/Kconfig9
-rw-r--r--drivers/interconnect/qcom/Makefile2
-rw-r--r--drivers/interconnect/qcom/icc-rpm-clocks.c6
-rw-r--r--drivers/interconnect/qcom/icc-rpm.c90
-rw-r--r--drivers/interconnect/qcom/icc-rpm.h15
-rw-r--r--drivers/interconnect/qcom/icc-rpmh.c4
-rw-r--r--drivers/interconnect/qcom/icc-rpmh.h2
-rw-r--r--drivers/interconnect/qcom/msm8974.c4
-rw-r--r--drivers/interconnect/qcom/msm8996.c8
-rw-r--r--drivers/interconnect/qcom/osm-l3.c3
-rw-r--r--drivers/interconnect/qcom/qcm2290.c9
-rw-r--r--drivers/interconnect/qcom/qdu1000.c3
-rw-r--r--drivers/interconnect/qcom/sa8775p.c2
-rw-r--r--drivers/interconnect/qcom/sc7180.c3
-rw-r--r--drivers/interconnect/qcom/sc7280.c3
-rw-r--r--drivers/interconnect/qcom/sc8180x.c3
-rw-r--r--drivers/interconnect/qcom/sc8280xp.c3
-rw-r--r--drivers/interconnect/qcom/sdm660.c4
-rw-r--r--drivers/interconnect/qcom/sdm670.c3
-rw-r--r--drivers/interconnect/qcom/sdm845.c3
-rw-r--r--drivers/interconnect/qcom/sdx55.c2
-rw-r--r--drivers/interconnect/qcom/sdx65.c2
-rw-r--r--drivers/interconnect/qcom/sdx75.c1107
-rw-r--r--drivers/interconnect/qcom/sdx75.h97
-rw-r--r--drivers/interconnect/qcom/sm6350.c3
-rw-r--r--drivers/interconnect/qcom/sm8150.c3
-rw-r--r--drivers/interconnect/qcom/sm8250.c3
-rw-r--r--drivers/interconnect/qcom/sm8350.c3
-rw-r--r--drivers/interconnect/qcom/sm8450.c2
-rw-r--r--drivers/interconnect/qcom/sm8550.c2
-rw-r--r--drivers/iommu/Kconfig19
-rw-r--r--drivers/iommu/Makefile1
-rw-r--r--drivers/iommu/amd/Kconfig10
-rw-r--r--drivers/iommu/amd/Makefile1
-rw-r--r--drivers/iommu/amd/amd_iommu.h35
-rw-r--r--drivers/iommu/amd/amd_iommu_types.h64
-rw-r--r--drivers/iommu/amd/init.c117
-rw-r--r--drivers/iommu/amd/io_pgtable.c68
-rw-r--r--drivers/iommu/amd/io_pgtable_v2.c8
-rw-r--r--drivers/iommu/amd/iommu.c724
-rw-r--r--drivers/iommu/amd/iommu_v2.c996
-rw-r--r--drivers/iommu/apple-dart.c138
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c71
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c251
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h17
-rw-r--r--drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c2
-rw-r--r--drivers/iommu/arm/arm-smmu/qcom_iommu.c45
-rw-r--r--drivers/iommu/dma-iommu.c200
-rw-r--r--drivers/iommu/exynos-iommu.c83
-rw-r--r--drivers/iommu/fsl_pamu_domain.c41
-rw-r--r--drivers/iommu/intel/Kconfig3
-rw-r--r--drivers/iommu/intel/Makefile2
-rw-r--r--drivers/iommu/intel/debugfs.c215
-rw-r--r--drivers/iommu/intel/dmar.c18
-rw-r--r--drivers/iommu/intel/iommu.c189
-rw-r--r--drivers/iommu/intel/iommu.h81
-rw-r--r--drivers/iommu/intel/nested.c117
-rw-r--r--drivers/iommu/intel/pasid.c221
-rw-r--r--drivers/iommu/intel/pasid.h6
-rw-r--r--drivers/iommu/intel/svm.c26
-rw-r--r--drivers/iommu/iommu.c521
-rw-r--r--drivers/iommu/iommufd/Makefile1
-rw-r--r--drivers/iommu/iommufd/device.c188
-rw-r--r--drivers/iommu/iommufd/hw_pagetable.c306
-rw-r--r--drivers/iommu/iommufd/io_pagetable.c200
-rw-r--r--drivers/iommu/iommufd/ioas.c14
-rw-r--r--drivers/iommu/iommufd/iommufd_private.h152
-rw-r--r--drivers/iommu/iommufd/iommufd_test.h39
-rw-r--r--drivers/iommu/iommufd/iova_bitmap.c (renamed from drivers/vfio/iova_bitmap.c)5
-rw-r--r--drivers/iommu/iommufd/main.c163
-rw-r--r--drivers/iommu/iommufd/pages.c2
-rw-r--r--drivers/iommu/iommufd/selftest.c347
-rw-r--r--drivers/iommu/iommufd/vfio_compat.c24
-rw-r--r--drivers/iommu/iova.c95
-rw-r--r--drivers/iommu/ipmmu-vmsa.c72
-rw-r--r--drivers/iommu/msm_iommu.c35
-rw-r--r--drivers/iommu/mtk_iommu.c35
-rw-r--r--drivers/iommu/mtk_iommu_v1.c28
-rw-r--r--drivers/iommu/of_iommu.c14
-rw-r--r--drivers/iommu/omap-iommu.c69
-rw-r--r--drivers/iommu/omap-iommu.h2
-rw-r--r--drivers/iommu/rockchip-iommu.c59
-rw-r--r--drivers/iommu/s390-iommu.c424
-rw-r--r--drivers/iommu/sprd-iommu.c36
-rw-r--r--drivers/iommu/sun50i-iommu.c80
-rw-r--r--drivers/iommu/tegra-gart.c371
-rw-r--r--drivers/iommu/tegra-smmu.c58
-rw-r--r--drivers/iommu/virtio-iommu.c4
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c20
-rw-r--r--drivers/irqchip/irq-gic-v3.c102
-rw-r--r--drivers/irqchip/irq-imx-intmux.c2
-rw-r--r--drivers/irqchip/irq-ls-scfg-msi.c12
-rw-r--r--drivers/irqchip/irq-renesas-rzg2l.c1
-rw-r--r--drivers/irqchip/irq-sifive-plic.c7
-rw-r--r--drivers/isdn/capi/kcapi.c4
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c2
-rw-r--r--drivers/isdn/mISDN/clock.c2
-rw-r--r--drivers/leds/Kconfig1
-rw-r--r--drivers/leds/blink/leds-lgm-sso.c6
-rw-r--r--drivers/leds/flash/leds-aat1290.c6
-rw-r--r--drivers/leds/flash/leds-ktd2692.c6
-rw-r--r--drivers/leds/flash/leds-lm3601x.c2
-rw-r--r--drivers/leds/flash/leds-max77693.c6
-rw-r--r--drivers/leds/flash/leds-mt6360.c7
-rw-r--r--drivers/leds/flash/leds-mt6370-flash.c2
-rw-r--r--drivers/leds/flash/leds-qcom-flash.c5
-rw-r--r--drivers/leds/flash/leds-rt8515.c6
-rw-r--r--drivers/leds/flash/leds-sgm3140.c6
-rw-r--r--drivers/leds/led-class.c14
-rw-r--r--drivers/leds/led-core.c17
-rw-r--r--drivers/leds/leds-88pm860x.c6
-rw-r--r--drivers/leds/leds-adp5520.c6
-rw-r--r--drivers/leds/leds-aw200xx.c4
-rw-r--r--drivers/leds/leds-clevo-mail.c5
-rw-r--r--drivers/leds/leds-cr0014114.c2
-rw-r--r--drivers/leds/leds-da903x.c6
-rw-r--r--drivers/leds/leds-da9052.c6
-rw-r--r--drivers/leds/leds-el15203000.c2
-rw-r--r--drivers/leds/leds-gpio.c56
-rw-r--r--drivers/leds/leds-lm3533.c6
-rw-r--r--drivers/leds/leds-lm3692x.c2
-rw-r--r--drivers/leds/leds-lm3697.c2
-rw-r--r--drivers/leds/leds-lp3952.c4
-rw-r--r--drivers/leds/leds-lp5521.c2
-rw-r--r--drivers/leds/leds-lp55xx-common.c4
-rw-r--r--drivers/leds/leds-mc13783.c6
-rw-r--r--drivers/leds/leds-mlxreg.c6
-rw-r--r--drivers/leds/leds-mt6323.c6
-rw-r--r--drivers/leds/leds-nic78bx.c6
-rw-r--r--drivers/leds/leds-pca955x.c69
-rw-r--r--drivers/leds/leds-powernv.c5
-rw-r--r--drivers/leds/leds-pwm.c2
-rw-r--r--drivers/leds/leds-rb532.c5
-rw-r--r--drivers/leds/leds-regulator.c5
-rw-r--r--drivers/leds/leds-sc27xx-bltc.c10
-rw-r--r--drivers/leds/leds-sunfire.c8
-rw-r--r--drivers/leds/leds-tca6507.c8
-rw-r--r--drivers/leds/leds-turris-omnia.c362
-rw-r--r--drivers/leds/leds-wm831x-status.c6
-rw-r--r--drivers/leds/leds-wm8350.c5
-rw-r--r--drivers/leds/rgb/Kconfig13
-rw-r--r--drivers/leds/rgb/Makefile1
-rw-r--r--drivers/leds/rgb/leds-ktd202x.c625
-rw-r--r--drivers/leds/rgb/leds-mt6370-rgb.c2
-rw-r--r--drivers/leds/rgb/leds-qcom-lpg.c9
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c8
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio-core.c4
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c7
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c8
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio.h6
-rw-r--r--drivers/leds/trigger/Kconfig5
-rw-r--r--drivers/leds/trigger/ledtrig-cpu.c4
-rw-r--r--drivers/leds/trigger/ledtrig-gpio.c137
-rw-r--r--drivers/leds/trigger/ledtrig-netdev.c17
-rw-r--r--drivers/macintosh/mac_hid.c1
-rw-r--r--drivers/macintosh/macio-adb.c1
-rw-r--r--drivers/mailbox/bcm-pdc-mailbox.c10
-rw-r--r--drivers/mailbox/imx-mailbox.c32
-rw-r--r--drivers/mailbox/mailbox-sti.c8
-rw-r--r--drivers/mailbox/mtk-cmdq-mailbox.c80
-rw-r--r--drivers/mailbox/pcc.c91
-rw-r--r--drivers/mailbox/ti-msgmgr.c12
-rw-r--r--drivers/mailbox/zynqmp-ipi-mailbox.c2
-rw-r--r--drivers/mcb/mcb-core.c17
-rw-r--r--drivers/mcb/mcb-parse.c4
-rw-r--r--drivers/md/bcache/Kconfig10
-rw-r--r--drivers/md/bcache/Makefile4
-rw-r--r--drivers/md/bcache/bcache.h7
-rw-r--r--drivers/md/bcache/btree.c54
-rw-r--r--drivers/md/bcache/journal.c20
-rw-r--r--drivers/md/bcache/movinggc.c16
-rw-r--r--drivers/md/bcache/request.c74
-rw-r--r--drivers/md/bcache/request.h2
-rw-r--r--drivers/md/bcache/super.c140
-rw-r--r--drivers/md/bcache/sysfs.c5
-rw-r--r--drivers/md/bcache/util.h3
-rw-r--r--drivers/md/bcache/writeback.c40
-rw-r--r--drivers/md/dm-bio-prison-v1.c2
-rw-r--r--drivers/md/dm-bufio.c115
-rw-r--r--drivers/md/dm-cache-metadata.c8
-rw-r--r--drivers/md/dm-crypt.c30
-rw-r--r--drivers/md/dm-delay.c119
-rw-r--r--drivers/md/dm-flakey.c2
-rw-r--r--drivers/md/dm-integrity.c30
-rw-r--r--drivers/md/dm-ioctl.c4
-rw-r--r--drivers/md/dm-linear.c2
-rw-r--r--drivers/md/dm-log-userspace-base.c2
-rw-r--r--drivers/md/dm-raid.c19
-rw-r--r--drivers/md/dm-stats.c2
-rw-r--r--drivers/md/dm-stripe.c4
-rw-r--r--drivers/md/dm-table.c23
-rw-r--r--drivers/md/dm-target.c106
-rw-r--r--drivers/md/dm-verity-fec.c7
-rw-r--r--drivers/md/dm-verity-target.c30
-rw-r--r--drivers/md/dm-verity.h8
-rw-r--r--drivers/md/dm-zoned-metadata.c28
-rw-r--r--drivers/md/dm.c141
-rw-r--r--drivers/md/dm.h2
-rw-r--r--drivers/md/md-autodetect.c4
-rw-r--r--drivers/md/md-bitmap.c61
-rw-r--r--drivers/md/md-cluster.c15
-rw-r--r--drivers/md/md-linear.c28
-rw-r--r--drivers/md/md-linear.h2
-rw-r--r--drivers/md/md.c989
-rw-r--r--drivers/md/md.h74
-rw-r--r--drivers/md/raid1.c6
-rw-r--r--drivers/md/raid10.c3
-rw-r--r--drivers/md/raid5-cache.c64
-rw-r--r--drivers/md/raid5.c133
-rw-r--r--drivers/md/raid5.h2
-rw-r--r--drivers/media/cec/core/cec-adap.c5
-rw-r--r--drivers/media/cec/core/cec-notifier.c5
-rw-r--r--drivers/media/cec/platform/Kconfig2
-rw-r--r--drivers/media/cec/platform/Makefile2
-rw-r--r--drivers/media/cec/platform/cros-ec/cros-ec-cec.c387
-rw-r--r--drivers/media/common/siano/smsdvb-debugfs.c22
-rw-r--r--drivers/media/common/videobuf2/frame_vector.c2
-rw-r--r--drivers/media/common/videobuf2/videobuf2-core.c2
-rw-r--r--drivers/media/common/videobuf2/videobuf2-dma-contig.c13
-rw-r--r--drivers/media/common/videobuf2/videobuf2-vmalloc.c10
-rw-r--r--drivers/media/dvb-frontends/drx39xyj/drxj.c6
-rw-r--r--drivers/media/dvb-frontends/m88ds3103.c3
-rw-r--r--drivers/media/i2c/Kconfig11
-rw-r--r--drivers/media/i2c/Makefile1
-rw-r--r--drivers/media/i2c/adp1653.c28
-rw-r--r--drivers/media/i2c/adv7180.c65
-rw-r--r--drivers/media/i2c/ar0521.c30
-rw-r--r--drivers/media/i2c/ccs/ccs-core.c431
-rw-r--r--drivers/media/i2c/ccs/ccs-quirk.h4
-rw-r--r--drivers/media/i2c/ccs/ccs.h4
-rw-r--r--drivers/media/i2c/cx25840/cx25840-core.c3694
-rw-r--r--drivers/media/i2c/ds90ub913.c2
-rw-r--r--drivers/media/i2c/ds90ub953.c2
-rw-r--r--drivers/media/i2c/ds90ub960.c2
-rw-r--r--drivers/media/i2c/hi556.c114
-rw-r--r--drivers/media/i2c/hi846.c34
-rw-r--r--drivers/media/i2c/hi847.c57
-rw-r--r--drivers/media/i2c/imx208.c61
-rw-r--r--drivers/media/i2c/imx214.c40
-rw-r--r--drivers/media/i2c/imx219.c1279
-rw-r--r--drivers/media/i2c/imx258.c40
-rw-r--r--drivers/media/i2c/imx296.c16
-rw-r--r--drivers/media/i2c/imx319.c44
-rw-r--r--drivers/media/i2c/imx334.c66
-rw-r--r--drivers/media/i2c/imx335.c9
-rw-r--r--drivers/media/i2c/imx355.c45
-rw-r--r--drivers/media/i2c/imx412.c9
-rw-r--r--drivers/media/i2c/imx415.c45
-rw-r--r--drivers/media/i2c/max9286.c2
-rw-r--r--drivers/media/i2c/msp3400-driver.c2
-rw-r--r--drivers/media/i2c/mt9m001.c6
-rw-r--r--drivers/media/i2c/mt9m111.c13
-rw-r--r--drivers/media/i2c/mt9m114.c2481
-rw-r--r--drivers/media/i2c/mt9v011.c6
-rw-r--r--drivers/media/i2c/mt9v032.c26
-rw-r--r--drivers/media/i2c/mt9v111.c14
-rw-r--r--drivers/media/i2c/og01a1b.c55
-rw-r--r--drivers/media/i2c/ov01a10.c59
-rw-r--r--drivers/media/i2c/ov02a10.c2
-rw-r--r--drivers/media/i2c/ov08d10.c52
-rw-r--r--drivers/media/i2c/ov08x40.c44
-rw-r--r--drivers/media/i2c/ov13858.c44
-rw-r--r--drivers/media/i2c/ov13b10.c98
-rw-r--r--drivers/media/i2c/ov2640.c21
-rw-r--r--drivers/media/i2c/ov2659.c16
-rw-r--r--drivers/media/i2c/ov2685.c19
-rw-r--r--drivers/media/i2c/ov2740.c168
-rw-r--r--drivers/media/i2c/ov4689.c9
-rw-r--r--drivers/media/i2c/ov5640.c24
-rw-r--r--drivers/media/i2c/ov5647.c6
-rw-r--r--drivers/media/i2c/ov5670.c36
-rw-r--r--drivers/media/i2c/ov5675.c44
-rw-r--r--drivers/media/i2c/ov5693.c9
-rw-r--r--drivers/media/i2c/ov5695.c25
-rw-r--r--drivers/media/i2c/ov7251.c8
-rw-r--r--drivers/media/i2c/ov7670.c72
-rw-r--r--drivers/media/i2c/ov772x.c4
-rw-r--r--drivers/media/i2c/ov7740.c30
-rw-r--r--drivers/media/i2c/ov8856.c47
-rw-r--r--drivers/media/i2c/ov8858.c10
-rw-r--r--drivers/media/i2c/ov9282.c9
-rw-r--r--drivers/media/i2c/ov9734.c50
-rw-r--r--drivers/media/i2c/rdacm20.c3
-rw-r--r--drivers/media/i2c/st-vgxy61.c9
-rw-r--r--drivers/media/i2c/tc358746.c6
-rw-r--r--drivers/media/i2c/tvp514x.c49
-rw-r--r--drivers/media/i2c/video-i2c.c12
-rw-r--r--drivers/media/mc/mc-entity.c15
-rw-r--r--drivers/media/pci/Kconfig1
-rw-r--r--drivers/media/pci/Makefile1
-rw-r--r--drivers/media/pci/bt8xx/bttv-cards.c1
-rw-r--r--drivers/media/pci/bt8xx/bttv-driver.c1
-rw-r--r--drivers/media/pci/bt8xx/dvb-bt8xx.c14
-rw-r--r--drivers/media/pci/cobalt/cobalt-driver.c11
-rw-r--r--drivers/media/pci/cobalt/cobalt-v4l2.c8
-rw-r--r--drivers/media/pci/cx18/cx18-driver.h2
-rw-r--r--drivers/media/pci/cx18/cx18-mailbox.c2
-rw-r--r--drivers/media/pci/intel/ipu-bridge.c4
-rw-r--r--drivers/media/pci/intel/ivsc/Kconfig12
-rw-r--r--drivers/media/pci/intel/ivsc/mei_ace.c9
-rw-r--r--drivers/media/pci/intel/ivsc/mei_csi.c5
-rw-r--r--drivers/media/pci/mgb4/Kconfig18
-rw-r--r--drivers/media/pci/mgb4/Makefile6
-rw-r--r--drivers/media/pci/mgb4/mgb4_cmt.c244
-rw-r--r--drivers/media/pci/mgb4/mgb4_cmt.h17
-rw-r--r--drivers/media/pci/mgb4/mgb4_core.c696
-rw-r--r--drivers/media/pci/mgb4/mgb4_core.h74
-rw-r--r--drivers/media/pci/mgb4/mgb4_dma.c123
-rw-r--r--drivers/media/pci/mgb4/mgb4_dma.h18
-rw-r--r--drivers/media/pci/mgb4/mgb4_i2c.c140
-rw-r--r--drivers/media/pci/mgb4/mgb4_i2c.h35
-rw-r--r--drivers/media/pci/mgb4/mgb4_io.h33
-rw-r--r--drivers/media/pci/mgb4/mgb4_regs.c30
-rw-r--r--drivers/media/pci/mgb4/mgb4_regs.h35
-rw-r--r--drivers/media/pci/mgb4/mgb4_sysfs.h18
-rw-r--r--drivers/media/pci/mgb4/mgb4_sysfs_in.c772
-rw-r--r--drivers/media/pci/mgb4/mgb4_sysfs_out.c740
-rw-r--r--drivers/media/pci/mgb4/mgb4_sysfs_pci.c71
-rw-r--r--drivers/media/pci/mgb4/mgb4_trigger.c208
-rw-r--r--drivers/media/pci/mgb4/mgb4_trigger.h8
-rw-r--r--drivers/media/pci/mgb4/mgb4_vin.c939
-rw-r--r--drivers/media/pci/mgb4/mgb4_vin.h69
-rw-r--r--drivers/media/pci/mgb4/mgb4_vout.c602
-rw-r--r--drivers/media/pci/mgb4/mgb4_vout.h65
-rw-r--r--drivers/media/pci/zoran/zoran.h2
-rw-r--r--drivers/media/platform/Kconfig1
-rw-r--r--drivers/media/platform/Makefile1
-rw-r--r--drivers/media/platform/allegro-dvt/allegro-mail.c2
-rw-r--r--drivers/media/platform/allegro-dvt/allegro-mail.h2
-rw-r--r--drivers/media/platform/amphion/vpu_defs.h1
-rw-r--r--drivers/media/platform/amphion/vpu_helpers.c1
-rw-r--r--drivers/media/platform/amphion/vpu_malone.c1
-rw-r--r--drivers/media/platform/amphion/vpu_msgs.c31
-rw-r--r--drivers/media/platform/aspeed/aspeed-video.c15
-rw-r--r--drivers/media/platform/cadence/Kconfig2
-rw-r--r--drivers/media/platform/cadence/cdns-csi2rx.c180
-rw-r--r--drivers/media/platform/cadence/cdns-csi2tx.c6
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c5
-rw-r--r--drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c2
-rw-r--r--drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c1
-rw-r--r--drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c2
-rw-r--r--drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c2
-rw-r--r--drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c56
-rw-r--r--drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c21
-rw-r--r--drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_pm.c18
-rw-r--r--drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_pm.h3
-rw-r--r--drivers/media/platform/mediatek/vcodec/encoder/venc_drv_if.c8
-rw-r--r--drivers/media/platform/mediatek/vcodec/encoder/venc_vpu_if.c5
-rw-r--r--drivers/media/platform/microchip/microchip-isc-base.c6
-rw-r--r--drivers/media/platform/nuvoton/Kconfig15
-rw-r--r--drivers/media/platform/nuvoton/Makefile2
-rw-r--r--drivers/media/platform/nuvoton/npcm-regs.h152
-rw-r--r--drivers/media/platform/nuvoton/npcm-video.c1831
-rw-r--r--drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.h11
-rw-r--r--drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c36
-rw-r--r--drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h1
-rw-r--r--drivers/media/platform/nxp/imx-mipi-csis.c2
-rw-r--r--drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c4
-rw-r--r--drivers/media/platform/qcom/camss/camss-csid-4-1.c8
-rw-r--r--drivers/media/platform/qcom/camss/camss-csid-4-7.c8
-rw-r--r--drivers/media/platform/qcom/camss/camss-csid-gen2.c33
-rw-r--r--drivers/media/platform/qcom/camss/camss-csid.c39
-rw-r--r--drivers/media/platform/qcom/camss/camss-csid.h4
-rw-r--r--drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c10
-rw-r--r--drivers/media/platform/qcom/camss/camss-csiphy.c95
-rw-r--r--drivers/media/platform/qcom/camss/camss-csiphy.h4
-rw-r--r--drivers/media/platform/qcom/camss/camss-ispif.c52
-rw-r--r--drivers/media/platform/qcom/camss/camss-ispif.h4
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-170.c73
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-4-1.c18
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-4-7.c18
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-4-8.c18
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-480.c61
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe.c228
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe.h15
-rw-r--r--drivers/media/platform/qcom/camss/camss-video.c81
-rw-r--r--drivers/media/platform/qcom/camss/camss.c482
-rw-r--r--drivers/media/platform/qcom/camss/camss.h34
-rw-r--r--drivers/media/platform/qcom/venus/core.c10
-rw-r--r--drivers/media/platform/qcom/venus/hfi_cmds.h2
-rw-r--r--drivers/media/platform/qcom/venus/hfi_msgs.c2
-rw-r--r--drivers/media/platform/qcom/venus/hfi_parser.c15
-rw-r--r--drivers/media/platform/qcom/venus/hfi_venus.c10
-rw-r--r--drivers/media/platform/qcom/venus/pm_helpers.c2
-rw-r--r--drivers/media/platform/renesas/rcar-isp.c2
-rw-r--r--drivers/media/platform/renesas/rcar-vin/rcar-csi2.c2
-rw-r--r--drivers/media/platform/renesas/rcar_drif.c3
-rw-r--r--drivers/media/platform/renesas/renesas-ceu.c6
-rw-r--r--drivers/media/platform/renesas/vsp1/vsp1_pipe.c2
-rw-r--r--drivers/media/platform/renesas/vsp1/vsp1_rpf.c10
-rw-r--r--drivers/media/platform/renesas/vsp1/vsp1_rwpf.c8
-rw-r--r--drivers/media/platform/renesas/vsp1/vsp1_rwpf.h4
-rw-r--r--drivers/media/platform/renesas/vsp1/vsp1_wpf.c29
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c24
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-common.h18
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c107
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c261
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-params.c4
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h620
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c251
-rw-r--r--drivers/media/platform/samsung/exynos4-is/fimc-is.c33
-rw-r--r--drivers/media/platform/samsung/s3c-camif/camif-capture.c6
-rw-r--r--drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c2
-rw-r--r--drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c26
-rw-r--r--drivers/media/platform/ti/Kconfig12
-rw-r--r--drivers/media/platform/ti/Makefile1
-rw-r--r--drivers/media/platform/ti/am437x/am437x-vpfe.c4
-rw-r--r--drivers/media/platform/ti/j721e-csi2rx/Makefile2
-rw-r--r--drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c1159
-rw-r--r--drivers/media/platform/ti/omap3isp/ispstat.c2
-rw-r--r--drivers/media/platform/verisilicon/hantro_drv.c8
-rw-r--r--drivers/media/platform/verisilicon/hantro_postproc.c2
-rw-r--r--drivers/media/platform/verisilicon/rockchip_av1_filmgrain.c2
-rw-r--r--drivers/media/platform/verisilicon/rockchip_vpu_hw.c2
-rw-r--r--drivers/media/platform/xilinx/xilinx-dma.c5
-rw-r--r--drivers/media/platform/xilinx/xilinx-vipp.c17
-rw-r--r--drivers/media/radio/radio-isa.c2
-rw-r--r--drivers/media/radio/radio-miropcm20.c4
-rw-r--r--drivers/media/radio/radio-si476x.c4
-rw-r--r--drivers/media/radio/radio-wl1273.c2
-rw-r--r--drivers/media/rc/Kconfig10
-rw-r--r--drivers/media/rc/Makefile1
-rw-r--r--drivers/media/rc/ati_remote.c2
-rw-r--r--drivers/media/rc/imon.c6
-rw-r--r--drivers/media/rc/ir-rx51.c285
-rw-r--r--drivers/media/rc/ir-sharp-decoder.c8
-rw-r--r--drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c1
-rw-r--r--drivers/media/rc/keymaps/rc-alink-dtu-m.c1
-rw-r--r--drivers/media/rc/keymaps/rc-anysee.c1
-rw-r--r--drivers/media/rc/keymaps/rc-apac-viewcomp.c1
-rw-r--r--drivers/media/rc/keymaps/rc-astrometa-t2hybrid.c1
-rw-r--r--drivers/media/rc/keymaps/rc-asus-pc39.c1
-rw-r--r--drivers/media/rc/keymaps/rc-asus-ps3-100.c1
-rw-r--r--drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c1
-rw-r--r--drivers/media/rc/keymaps/rc-ati-x10.c1
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia-a16d.c1
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia-cardbus.c1
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia-dvbt.c1
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia-m135a.c1
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c1
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia-rm-ks.c1
-rw-r--r--drivers/media/rc/keymaps/rc-avermedia.c1
-rw-r--r--drivers/media/rc/keymaps/rc-avertv-303.c1
-rw-r--r--drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c1
-rw-r--r--drivers/media/rc/keymaps/rc-beelink-gs1.c1
-rw-r--r--drivers/media/rc/keymaps/rc-beelink-mxiii.c1
-rw-r--r--drivers/media/rc/keymaps/rc-behold-columbus.c1
-rw-r--r--drivers/media/rc/keymaps/rc-behold.c1
-rw-r--r--drivers/media/rc/keymaps/rc-budget-ci-old.c1
-rw-r--r--drivers/media/rc/keymaps/rc-cinergy-1400.c1
-rw-r--r--drivers/media/rc/keymaps/rc-cinergy.c1
-rw-r--r--drivers/media/rc/keymaps/rc-ct-90405.c1
-rw-r--r--drivers/media/rc/keymaps/rc-d680-dmb.c1
-rw-r--r--drivers/media/rc/keymaps/rc-dib0700-nec.c1
-rw-r--r--drivers/media/rc/keymaps/rc-dib0700-rc5.c1
-rw-r--r--drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c1
-rw-r--r--drivers/media/rc/keymaps/rc-digittrade.c1
-rw-r--r--drivers/media/rc/keymaps/rc-dm1105-nec.c1
-rw-r--r--drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c1
-rw-r--r--drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c1
-rw-r--r--drivers/media/rc/keymaps/rc-dreambox.c1
-rw-r--r--drivers/media/rc/keymaps/rc-dtt200u.c1
-rw-r--r--drivers/media/rc/keymaps/rc-dvbsky.c1
-rw-r--r--drivers/media/rc/keymaps/rc-dvico-mce.c1
-rw-r--r--drivers/media/rc/keymaps/rc-dvico-portable.c1
-rw-r--r--drivers/media/rc/keymaps/rc-em-terratec.c1
-rw-r--r--drivers/media/rc/keymaps/rc-encore-enltv-fm53.c1
-rw-r--r--drivers/media/rc/keymaps/rc-encore-enltv.c1
-rw-r--r--drivers/media/rc/keymaps/rc-encore-enltv2.c1
-rw-r--r--drivers/media/rc/keymaps/rc-evga-indtube.c1
-rw-r--r--drivers/media/rc/keymaps/rc-eztv.c1
-rw-r--r--drivers/media/rc/keymaps/rc-flydvb.c1
-rw-r--r--drivers/media/rc/keymaps/rc-flyvideo.c1
-rw-r--r--drivers/media/rc/keymaps/rc-fusionhdtv-mce.c1
-rw-r--r--drivers/media/rc/keymaps/rc-gadmei-rm008z.c1
-rw-r--r--drivers/media/rc/keymaps/rc-geekbox.c1
-rw-r--r--drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c1
-rw-r--r--drivers/media/rc/keymaps/rc-gotview7135.c1
-rw-r--r--drivers/media/rc/keymaps/rc-hauppauge.c1
-rw-r--r--drivers/media/rc/keymaps/rc-hisi-poplar.c1
-rw-r--r--drivers/media/rc/keymaps/rc-hisi-tv-demo.c1
-rw-r--r--drivers/media/rc/keymaps/rc-imon-mce.c1
-rw-r--r--drivers/media/rc/keymaps/rc-imon-pad.c1
-rw-r--r--drivers/media/rc/keymaps/rc-imon-rsc.c1
-rw-r--r--drivers/media/rc/keymaps/rc-iodata-bctv7e.c1
-rw-r--r--drivers/media/rc/keymaps/rc-it913x-v1.c1
-rw-r--r--drivers/media/rc/keymaps/rc-it913x-v2.c1
-rw-r--r--drivers/media/rc/keymaps/rc-kaiomy.c1
-rw-r--r--drivers/media/rc/keymaps/rc-khadas.c1
-rw-r--r--drivers/media/rc/keymaps/rc-khamsin.c1
-rw-r--r--drivers/media/rc/keymaps/rc-kworld-315u.c1
-rw-r--r--drivers/media/rc/keymaps/rc-kworld-pc150u.c1
-rw-r--r--drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c1
-rw-r--r--drivers/media/rc/keymaps/rc-leadtek-y04g0051.c1
-rw-r--r--drivers/media/rc/keymaps/rc-lme2510.c1
-rw-r--r--drivers/media/rc/keymaps/rc-manli.c1
-rw-r--r--drivers/media/rc/keymaps/rc-mecool-kii-pro.c1
-rw-r--r--drivers/media/rc/keymaps/rc-mecool-kiii-pro.c1
-rw-r--r--drivers/media/rc/keymaps/rc-medion-x10.c1
-rw-r--r--drivers/media/rc/keymaps/rc-minix-neo.c1
-rw-r--r--drivers/media/rc/keymaps/rc-msi-digivox-ii.c1
-rw-r--r--drivers/media/rc/keymaps/rc-msi-digivox-iii.c1
-rw-r--r--drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c1
-rw-r--r--drivers/media/rc/keymaps/rc-msi-tvanywhere.c1
-rw-r--r--drivers/media/rc/keymaps/rc-nebula.c1
-rw-r--r--drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c1
-rw-r--r--drivers/media/rc/keymaps/rc-norwood.c1
-rw-r--r--drivers/media/rc/keymaps/rc-npgtech.c1
-rw-r--r--drivers/media/rc/keymaps/rc-odroid.c1
-rw-r--r--drivers/media/rc/keymaps/rc-pctv-sedna.c1
-rw-r--r--drivers/media/rc/keymaps/rc-pine64.c1
-rw-r--r--drivers/media/rc/keymaps/rc-pinnacle-color.c1
-rw-r--r--drivers/media/rc/keymaps/rc-pinnacle-grey.c1
-rw-r--r--drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c1
-rw-r--r--drivers/media/rc/keymaps/rc-pixelview-002t.c1
-rw-r--r--drivers/media/rc/keymaps/rc-pixelview-mk12.c1
-rw-r--r--drivers/media/rc/keymaps/rc-pixelview-new.c1
-rw-r--r--drivers/media/rc/keymaps/rc-pixelview.c1
-rw-r--r--drivers/media/rc/keymaps/rc-powercolor-real-angel.c1
-rw-r--r--drivers/media/rc/keymaps/rc-proteus-2309.c1
-rw-r--r--drivers/media/rc/keymaps/rc-purpletv.c1
-rw-r--r--drivers/media/rc/keymaps/rc-pv951.c1
-rw-r--r--drivers/media/rc/keymaps/rc-rc6-mce.c1
-rw-r--r--drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c1
-rw-r--r--drivers/media/rc/keymaps/rc-reddo.c1
-rw-r--r--drivers/media/rc/keymaps/rc-snapstream-firefly.c1
-rw-r--r--drivers/media/rc/keymaps/rc-streamzap.c1
-rw-r--r--drivers/media/rc/keymaps/rc-su3000.c1
-rw-r--r--drivers/media/rc/keymaps/rc-tanix-tx3mini.c1
-rw-r--r--drivers/media/rc/keymaps/rc-tanix-tx5max.c1
-rw-r--r--drivers/media/rc/keymaps/rc-tbs-nec.c1
-rw-r--r--drivers/media/rc/keymaps/rc-technisat-ts35.c1
-rw-r--r--drivers/media/rc/keymaps/rc-technisat-usb2.c1
-rw-r--r--drivers/media/rc/keymaps/rc-terratec-cinergy-c-pci.c1
-rw-r--r--drivers/media/rc/keymaps/rc-terratec-cinergy-s2-hd.c1
-rw-r--r--drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c1
-rw-r--r--drivers/media/rc/keymaps/rc-terratec-slim-2.c1
-rw-r--r--drivers/media/rc/keymaps/rc-terratec-slim.c1
-rw-r--r--drivers/media/rc/keymaps/rc-tevii-nec.c1
-rw-r--r--drivers/media/rc/keymaps/rc-tivo.c1
-rw-r--r--drivers/media/rc/keymaps/rc-total-media-in-hand-02.c1
-rw-r--r--drivers/media/rc/keymaps/rc-total-media-in-hand.c1
-rw-r--r--drivers/media/rc/keymaps/rc-trekstor.c1
-rw-r--r--drivers/media/rc/keymaps/rc-tt-1500.c1
-rw-r--r--drivers/media/rc/keymaps/rc-twinhan-dtv-cab-ci.c1
-rw-r--r--drivers/media/rc/keymaps/rc-twinhan1027.c1
-rw-r--r--drivers/media/rc/keymaps/rc-vega-s9x.c1
-rw-r--r--drivers/media/rc/keymaps/rc-videomate-m1f.c1
-rw-r--r--drivers/media/rc/keymaps/rc-videomate-s350.c1
-rw-r--r--drivers/media/rc/keymaps/rc-videomate-tv-pvr.c1
-rw-r--r--drivers/media/rc/keymaps/rc-videostrong-kii-pro.c1
-rw-r--r--drivers/media/rc/keymaps/rc-wetek-hub.c1
-rw-r--r--drivers/media/rc/keymaps/rc-wetek-play2.c1
-rw-r--r--drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c1
-rw-r--r--drivers/media/rc/keymaps/rc-winfast.c1
-rw-r--r--drivers/media/rc/keymaps/rc-x96max.c1
-rw-r--r--drivers/media/rc/keymaps/rc-xbox-360.c1
-rw-r--r--drivers/media/rc/keymaps/rc-xbox-dvd.c1
-rw-r--r--drivers/media/rc/keymaps/rc-zx-irdec.c1
-rw-r--r--drivers/media/rc/lirc_dev.c6
-rw-r--r--drivers/media/rc/meson-ir.c522
-rw-r--r--drivers/media/rc/pwm-ir-tx.c1
-rw-r--r--drivers/media/test-drivers/vidtv/vidtv_mux.c7
-rw-r--r--drivers/media/test-drivers/vidtv/vidtv_psi.c45
-rw-r--r--drivers/media/test-drivers/vivid/vivid-core.c2
-rw-r--r--drivers/media/test-drivers/vivid/vivid-rds-gen.c2
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-417.c9
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-core.c7
-rw-r--r--drivers/media/usb/cx231xx/cx231xx.h3
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9035.c13
-rw-r--r--drivers/media/usb/dvb-usb/gp8psk.c2
-rw-r--r--drivers/media/usb/gspca/cpia1.c3
-rw-r--r--drivers/media/usb/siano/smsusb.c4
-rw-r--r--drivers/media/v4l2-core/Kconfig16
-rw-r--r--drivers/media/v4l2-core/Makefile5
-rw-r--r--drivers/media/v4l2-core/v4l2-event.c2
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c1
-rw-r--r--drivers/media/v4l2-core/v4l2-subdev.c62
-rw-r--r--drivers/media/v4l2-core/videobuf-core.c1198
-rw-r--r--drivers/media/v4l2-core/videobuf-dma-contig.c402
-rw-r--r--drivers/media/v4l2-core/videobuf-dma-sg.c681
-rw-r--r--drivers/media/v4l2-core/videobuf-vmalloc.c326
-rw-r--r--drivers/memory/atmel-ebi.c16
-rw-r--r--drivers/memory/brcmstb_memc.c9
-rw-r--r--drivers/memory/fsl-corenet-cf.c11
-rw-r--r--drivers/memory/tegra/mc.c34
-rw-r--r--drivers/memory/tegra/tegra20.c28
-rw-r--r--drivers/memory/tegra/tegra234.c64
-rw-r--r--drivers/memstick/host/jmb38x_ms.c2
-rw-r--r--drivers/message/fusion/mptctl.c19
-rw-r--r--drivers/message/fusion/mptfc.c94
-rw-r--r--drivers/message/fusion/mptsas.c16
-rw-r--r--drivers/message/fusion/mptscsih.c55
-rw-r--r--drivers/message/fusion/mptscsih.h1
-rw-r--r--drivers/mfd/arizona-i2c.c11
-rw-r--r--drivers/mfd/arizona-spi.c3
-rw-r--r--drivers/mfd/atmel-hlcdc.c1
-rw-r--r--drivers/mfd/axp20x.c66
-rw-r--r--drivers/mfd/db8500-prcmu.c4
-rw-r--r--drivers/mfd/dln2.c1
-rw-r--r--drivers/mfd/hi6421-pmic-core.c9
-rw-r--r--drivers/mfd/intel-lpss-pci.c13
-rw-r--r--drivers/mfd/iqs62x.c2
-rw-r--r--drivers/mfd/lochnagar-i2c.c9
-rw-r--r--drivers/mfd/lp87565.c9
-rw-r--r--drivers/mfd/lpc_ich.c127
-rw-r--r--drivers/mfd/madera-i2c.c9
-rw-r--r--drivers/mfd/max14577.c14
-rw-r--r--drivers/mfd/max77541.c6
-rw-r--r--drivers/mfd/max77620.c6
-rw-r--r--drivers/mfd/max77686.c2
-rw-r--r--drivers/mfd/max8907.c4
-rw-r--r--drivers/mfd/max8997.c12
-rw-r--r--drivers/mfd/max8998.c12
-rw-r--r--drivers/mfd/mc13xxx-spi.c14
-rw-r--r--drivers/mfd/mfd-core.c17
-rw-r--r--drivers/mfd/motorola-cpcap.c7
-rw-r--r--drivers/mfd/mxs-lradc.c9
-rw-r--r--drivers/mfd/palmas.c60
-rw-r--r--drivers/mfd/qcom-spmi-pmic.c109
-rw-r--r--drivers/mfd/qcom_rpm.c8
-rw-r--r--drivers/mfd/rk8xx-core.c7
-rw-r--r--drivers/mfd/rk8xx-i2c.c6
-rw-r--r--drivers/mfd/rn5t618.c11
-rw-r--r--drivers/mfd/stm32-timers.c46
-rw-r--r--drivers/mfd/tps65086.c2
-rw-r--r--drivers/mfd/tps65090.c2
-rw-r--r--drivers/mfd/tps65218.c2
-rw-r--r--drivers/mfd/tps6586x.c52
-rw-r--r--drivers/mfd/tps65910.c13
-rw-r--r--drivers/mfd/tps65912-core.c2
-rw-r--r--drivers/mfd/twl-core.c18
-rw-r--r--drivers/mfd/twl4030-power.c9
-rw-r--r--drivers/mfd/twl6030-irq.c10
-rw-r--r--drivers/mfd/wcd934x.c2
-rw-r--r--drivers/mfd/wm831x-i2c.c16
-rw-r--r--drivers/mfd/wm831x-spi.c16
-rw-r--r--drivers/mfd/wm8994-core.c11
-rw-r--r--drivers/misc/Kconfig2
-rw-r--r--drivers/misc/bcm-vk/bcm_vk_msg.c2
-rw-r--r--drivers/misc/bcm-vk/bcm_vk_msg.h2
-rw-r--r--drivers/misc/c2port/core.c2
-rw-r--r--drivers/misc/cxl/file.c21
-rw-r--r--drivers/misc/eeprom/Kconfig14
-rw-r--r--drivers/misc/eeprom/Makefile1
-rw-r--r--drivers/misc/eeprom/at24.c42
-rw-r--r--drivers/misc/eeprom/eeprom.c214
-rw-r--r--drivers/misc/eeprom/idt_89hpesx.c11
-rw-r--r--drivers/misc/fastrpc.c34
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c2
-rw-r--r--drivers/misc/ibmvmc.c6
-rw-r--r--drivers/misc/lkdtm/bugs.c30
-rw-r--r--drivers/misc/lkdtm/cfi.c13
-rw-r--r--drivers/misc/mei/bus.c92
-rw-r--r--drivers/misc/mei/client.c24
-rw-r--r--drivers/misc/mei/dma-ring.c6
-rw-r--r--drivers/misc/mei/hbm.c6
-rw-r--r--drivers/misc/mei/hw-me-regs.h3
-rw-r--r--drivers/misc/mei/hw-me.c77
-rw-r--r--drivers/misc/mei/hw-me.h4
-rw-r--r--drivers/misc/mei/hw.h12
-rw-r--r--drivers/misc/mei/init.c27
-rw-r--r--drivers/misc/mei/interrupt.c6
-rw-r--r--drivers/misc/mei/main.c8
-rw-r--r--drivers/misc/mei/mei_dev.h51
-rw-r--r--drivers/misc/mei/pxp/mei_pxp.c85
-rw-r--r--drivers/misc/ocxl/file.c27
-rw-r--r--drivers/misc/pci_endpoint_test.c8
-rw-r--r--drivers/misc/phantom.c24
-rw-r--r--drivers/misc/pvpanic/pvpanic-mmio.c58
-rw-r--r--drivers/misc/pvpanic/pvpanic-pci.c58
-rw-r--r--drivers/misc/pvpanic/pvpanic.c76
-rw-r--r--drivers/misc/pvpanic/pvpanic.h10
-rw-r--r--drivers/misc/sgi-gru/gru.h4
-rw-r--r--drivers/misc/sgi-gru/gru_instructions.h12
-rw-r--r--drivers/misc/sgi-gru/grufile.c72
-rw-r--r--drivers/misc/sgi-gru/gruhandles.c6
-rw-r--r--drivers/misc/sgi-gru/grumain.c4
-rw-r--r--drivers/misc/sgi-xp/xp.h2
-rw-r--r--drivers/misc/sgi-xp/xp_uv.c24
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c33
-rw-r--r--drivers/misc/sgi-xp/xpc_uv.c85
-rw-r--r--drivers/misc/ti-st/st_core.c7
-rw-r--r--drivers/misc/ti-st/st_kim.c5
-rw-r--r--drivers/misc/uacce/uacce.c17
-rw-r--r--drivers/misc/vmw_balloon.c38
-rw-r--r--drivers/mmc/core/block.c37
-rw-r--r--drivers/mmc/core/card.h4
-rw-r--r--drivers/mmc/core/core.c9
-rw-r--r--drivers/mmc/core/debugfs.c51
-rw-r--r--drivers/mmc/core/mmc.c15
-rw-r--r--drivers/mmc/core/queue.c6
-rw-r--r--drivers/mmc/core/quirks.h7
-rw-r--r--drivers/mmc/core/sdio.c8
-rw-r--r--drivers/mmc/host/Kconfig12
-rw-r--r--drivers/mmc/host/Makefile1
-rw-r--r--drivers/mmc/host/atmel-mci.c9
-rw-r--r--drivers/mmc/host/cqhci-core.c44
-rw-r--r--drivers/mmc/host/dw_mmc-starfive.c137
-rw-r--r--drivers/mmc/host/jz4740_mmc.c15
-rw-r--r--drivers/mmc/host/meson-gx-mmc.c1
-rw-r--r--drivers/mmc/host/mmc_hsq.c22
-rw-r--r--drivers/mmc/host/mmc_hsq.h11
-rw-r--r--drivers/mmc/host/mmci.c3
-rw-r--r--drivers/mmc/host/mmci.h2
-rw-r--r--drivers/mmc/host/mtk-sd.c6
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c52
-rw-r--r--drivers/mmc/host/sdhci-npcm.c94
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c5
-rw-r--r--drivers/mmc/host/sdhci-pci-gli.c188
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c38
-rw-r--r--drivers/mmc/host/sdhci-sprd.c26
-rw-r--r--drivers/mmc/host/sdhci_am654.c2
-rw-r--r--drivers/mmc/host/vub300.c23
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c20
-rw-r--r--drivers/mtd/chips/map_ram.c8
-rw-r--r--drivers/mtd/devices/bcm47xxsflash.c6
-rw-r--r--drivers/mtd/devices/block2mtd.c51
-rw-r--r--drivers/mtd/devices/docg3.c5
-rw-r--r--drivers/mtd/devices/phram.c6
-rw-r--r--drivers/mtd/devices/powernv_flash.c6
-rw-r--r--drivers/mtd/devices/spear_smi.c6
-rw-r--r--drivers/mtd/devices/st_spi_fsm.c6
-rw-r--r--drivers/mtd/hyperbus/hbmc-am654.c6
-rw-r--r--drivers/mtd/hyperbus/rpc-if.c6
-rw-r--r--drivers/mtd/lpddr/lpddr2_nvm.c6
-rw-r--r--drivers/mtd/lpddr/lpddr_cmds.c2
-rw-r--r--drivers/mtd/maps/lantiq-flash.c6
-rw-r--r--drivers/mtd/maps/physmap-core.c26
-rw-r--r--drivers/mtd/maps/plat-ram.c8
-rw-r--r--drivers/mtd/maps/pxa2xx-flash.c5
-rw-r--r--drivers/mtd/maps/sa1100-flash.c6
-rw-r--r--drivers/mtd/maps/sun_uflash.c6
-rw-r--r--drivers/mtd/mtdcore.c5
-rw-r--r--drivers/mtd/mtdpart.c6
-rw-r--r--drivers/mtd/nand/raw/arasan-nand-controller.c18
-rw-r--r--drivers/mtd/nand/raw/atmel/nand-controller.c2
-rw-r--r--drivers/mtd/nand/raw/cadence-nand-controller.c14
-rw-r--r--drivers/mtd/nand/raw/denali.h2
-rw-r--r--drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c14
-rw-r--r--drivers/mtd/nand/raw/intel-nand-controller.c10
-rw-r--r--drivers/mtd/nand/raw/internals.h1
-rw-r--r--drivers/mtd/nand/raw/marvell_nand.c25
-rw-r--r--drivers/mtd/nand/raw/meson_nand.c5
-rw-r--r--drivers/mtd/nand/raw/mtk_nand.c2
-rw-r--r--drivers/mtd/nand/raw/nand_base.c4
-rw-r--r--drivers/mtd/nand/raw/nand_jedec.c3
-rw-r--r--drivers/mtd/nand/raw/nand_onfi.c3
-rw-r--r--drivers/mtd/nand/raw/omap2.c8
-rw-r--r--drivers/mtd/nand/raw/pl35x-nand-controller.c9
-rw-r--r--drivers/mtd/nand/raw/qcom_nandc.c2
-rw-r--r--drivers/mtd/nand/raw/renesas-nand-controller.c2
-rw-r--r--drivers/mtd/nand/raw/rockchip-nand-controller.c5
-rw-r--r--drivers/mtd/nand/raw/sh_flctl.c3
-rw-r--r--drivers/mtd/nand/raw/sunxi_nand.c2
-rw-r--r--drivers/mtd/nand/raw/tegra_nand.c4
-rw-r--r--drivers/mtd/nand/raw/vf610_nfc.c10
-rw-r--r--drivers/mtd/nand/raw/xway_nand.c1
-rw-r--r--drivers/mtd/nand/spi/Makefile2
-rw-r--r--drivers/mtd/nand/spi/core.c1
-rw-r--r--drivers/mtd/nand/spi/foresee.c95
-rw-r--r--drivers/mtd/nand/spi/micron.c2
-rw-r--r--drivers/mtd/nand/spi/winbond.c45
-rw-r--r--drivers/mtd/nand/spi/xtx.c134
-rw-r--r--drivers/mtd/parsers/Kconfig5
-rw-r--r--drivers/mtd/parsers/Makefile1
-rw-r--r--drivers/mtd/parsers/ar7part.c129
-rw-r--r--drivers/mtd/spi-nor/Makefile2
-rw-r--r--drivers/mtd/spi-nor/atmel.c121
-rw-r--r--drivers/mtd/spi-nor/catalyst.c24
-rw-r--r--drivers/mtd/spi-nor/controllers/hisi-sfc.c5
-rw-r--r--drivers/mtd/spi-nor/controllers/nxp-spifi.c6
-rw-r--r--drivers/mtd/spi-nor/core.c63
-rw-r--r--drivers/mtd/spi-nor/core.h138
-rw-r--r--drivers/mtd/spi-nor/eon.c74
-rw-r--r--drivers/mtd/spi-nor/esmt.c29
-rw-r--r--drivers/mtd/spi-nor/everspin.c28
-rw-r--r--drivers/mtd/spi-nor/fujitsu.c21
-rw-r--r--drivers/mtd/spi-nor/gigadevice.c82
-rw-r--r--drivers/mtd/spi-nor/intel.c23
-rw-r--r--drivers/mtd/spi-nor/issi.c118
-rw-r--r--drivers/mtd/spi-nor/macronix.c220
-rw-r--r--drivers/mtd/spi-nor/micron-st.c423
-rw-r--r--drivers/mtd/spi-nor/spansion.c392
-rw-r--r--drivers/mtd/spi-nor/sst.c164
-rw-r--r--drivers/mtd/spi-nor/swp.c13
-rw-r--r--drivers/mtd/spi-nor/sysfs.c6
-rw-r--r--drivers/mtd/spi-nor/winbond.c288
-rw-r--r--drivers/mtd/spi-nor/xilinx.c32
-rw-r--r--drivers/mtd/spi-nor/xmc.c19
-rw-r--r--drivers/mtd/ubi/block.c4
-rw-r--r--drivers/mtd/ubi/build.c25
-rw-r--r--drivers/mtd/ubi/cdev.c3
-rw-r--r--drivers/mtd/ubi/eba.c3
-rw-r--r--drivers/mtd/ubi/fastmap-wl.c112
-rw-r--r--drivers/mtd/ubi/fastmap.c66
-rw-r--r--drivers/mtd/ubi/ubi.h10
-rw-r--r--drivers/mtd/ubi/wl.c48
-rw-r--r--drivers/mtd/ubi/wl.h6
-rw-r--r--drivers/net/Kconfig9
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/Space.c6
-rw-r--r--drivers/net/amt.c1
-rw-r--r--drivers/net/appletalk/Kconfig102
-rw-r--r--drivers/net/appletalk/Makefile7
-rw-r--r--drivers/net/appletalk/cops.c1005
-rw-r--r--drivers/net/appletalk/cops.h61
-rw-r--r--drivers/net/appletalk/cops_ffdrv.h532
-rw-r--r--drivers/net/appletalk/cops_ltdrv.h241
-rw-r--r--drivers/net/appletalk/ipddp.c345
-rw-r--r--drivers/net/appletalk/ipddp.h28
-rw-r--r--drivers/net/arcnet/arcdevice.h2
-rw-r--r--drivers/net/arcnet/com20020-pci.c89
-rw-r--r--drivers/net/bareudp.c45
-rw-r--r--drivers/net/bonding/bond_main.c8
-rw-r--r--drivers/net/bonding/bond_netlink.c2
-rw-r--r--drivers/net/can/Kconfig3
-rw-r--r--drivers/net/can/at91_can.c984
-rw-r--r--drivers/net/can/dev/dev.c51
-rw-r--r--drivers/net/can/dev/rx-offload.c2
-rw-r--r--drivers/net/can/dev/skb.c6
-rw-r--r--drivers/net/can/flexcan/flexcan-core.c46
-rw-r--r--drivers/net/can/flexcan/flexcan.h2
-rw-r--r--drivers/net/can/m_can/tcan4x5x-core.c2
-rw-r--r--drivers/net/can/sja1000/peak_pci.c2
-rw-r--r--drivers/net/can/sja1000/sja1000.c10
-rw-r--r--drivers/net/can/usb/etas_es58x/es58x_core.c1
-rw-r--r--drivers/net/can/usb/etas_es58x/es58x_core.h6
-rw-r--r--drivers/net/can/usb/etas_es58x/es58x_devlink.c57
-rw-r--r--drivers/net/dsa/b53/b53_common.c4
-rw-r--r--drivers/net/dsa/b53/b53_mdio.c2
-rw-r--r--drivers/net/dsa/b53/b53_mmap.c6
-rw-r--r--drivers/net/dsa/b53/b53_srab.c8
-rw-r--r--drivers/net/dsa/bcm_sf2.c67
-rw-r--r--drivers/net/dsa/bcm_sf2.h2
-rw-r--r--drivers/net/dsa/bcm_sf2_cfp.c4
-rw-r--r--drivers/net/dsa/dsa_loop.c9
-rw-r--r--drivers/net/dsa/hirschmann/hellcreek.c8
-rw-r--r--drivers/net/dsa/lan9303-core.c4
-rw-r--r--drivers/net/dsa/lan9303_mdio.c4
-rw-r--r--drivers/net/dsa/lantiq_gswip.c45
-rw-r--r--drivers/net/dsa/microchip/Makefile2
-rw-r--r--drivers/net/dsa/microchip/ksz8795.c86
-rw-r--r--drivers/net/dsa/microchip/ksz8795_reg.h21
-rw-r--r--drivers/net/dsa/microchip/ksz9477.c274
-rw-r--r--drivers/net/dsa/microchip/ksz9477.h43
-rw-r--r--drivers/net/dsa/microchip/ksz9477_acl.c1436
-rw-r--r--drivers/net/dsa/microchip/ksz9477_i2c.c5
-rw-r--r--drivers/net/dsa/microchip/ksz9477_reg.h20
-rw-r--r--drivers/net/dsa/microchip/ksz9477_tc_flower.c281
-rw-r--r--drivers/net/dsa/microchip/ksz_common.c661
-rw-r--r--drivers/net/dsa/microchip/ksz_common.h42
-rw-r--r--drivers/net/dsa/microchip/ksz_ptp.c2
-rw-r--r--drivers/net/dsa/microchip/ksz_spi.c5
-rw-r--r--drivers/net/dsa/mt7530-mmio.c7
-rw-r--r--drivers/net/dsa/mt7530.c32
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c30
-rw-r--r--drivers/net/dsa/mv88e6xxx/pcs-639x.c33
-rw-r--r--drivers/net/dsa/mv88e6xxx/ptp.c4
-rw-r--r--drivers/net/dsa/ocelot/felix.c68
-rw-r--r--drivers/net/dsa/ocelot/felix.h6
-rw-r--r--drivers/net/dsa/ocelot/ocelot_ext.c8
-rw-r--r--drivers/net/dsa/ocelot/seville_vsc9953.c8
-rw-r--r--drivers/net/dsa/qca/qca8k-8xxx.c65
-rw-r--r--drivers/net/dsa/qca/qca8k-common.c7
-rw-r--r--drivers/net/dsa/qca/qca8k-leds.c6
-rw-r--r--drivers/net/dsa/qca/qca8k.h2
-rw-r--r--drivers/net/dsa/realtek/realtek-smi.c36
-rw-r--r--drivers/net/dsa/realtek/realtek.h2
-rw-r--r--drivers/net/dsa/realtek/rtl8365mb.c5
-rw-r--r--drivers/net/dsa/realtek/rtl8366-core.c8
-rw-r--r--drivers/net/dsa/realtek/rtl8366rb.c44
-rw-r--r--drivers/net/dsa/rzn1_a5psw.c8
-rw-r--r--drivers/net/dsa/sja1105/sja1105_clocking.c21
-rw-r--r--drivers/net/dsa/sja1105/sja1105_main.c4
-rw-r--r--drivers/net/dsa/vitesse-vsc73xx-core.c49
-rw-r--r--drivers/net/dsa/vitesse-vsc73xx-platform.c8
-rw-r--r--drivers/net/dsa/xrs700x/xrs700x.c30
-rw-r--r--drivers/net/dummy.c1
-rw-r--r--drivers/net/eql.c1
-rw-r--r--drivers/net/ethernet/8390/ax88796.c6
-rw-r--r--drivers/net/ethernet/8390/mcf8390.c5
-rw-r--r--drivers/net/ethernet/8390/ne.c5
-rw-r--r--drivers/net/ethernet/actions/owl-emac.c6
-rw-r--r--drivers/net/ethernet/adi/adin1110.c2
-rw-r--r--drivers/net/ethernet/aeroflex/greth.c6
-rw-r--r--drivers/net/ethernet/allwinner/sun4i-emac.c5
-rw-r--r--drivers/net/ethernet/altera/altera_tse.h2
-rw-r--r--drivers/net/ethernet/altera/altera_tse_main.c19
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_eth_com.c3
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_netdev.c55
-rw-r--r--drivers/net/ethernet/amd/au1000_eth.c6
-rw-r--r--drivers/net/ethernet/amd/pds_core/adminq.c2
-rw-r--r--drivers/net/ethernet/amd/pds_core/core.c50
-rw-r--r--drivers/net/ethernet/amd/pds_core/core.h9
-rw-r--r--drivers/net/ethernet/amd/pds_core/dev.c19
-rw-r--r--drivers/net/ethernet/amd/pds_core/devlink.c33
-rw-r--r--drivers/net/ethernet/amd/pds_core/main.c50
-rw-r--r--drivers/net/ethernet/amd/sunlance.c6
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-drv.c14
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c11
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-mdio.c14
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-platform.c48
-rw-r--r--drivers/net/ethernet/apm/xgene-v2/main.c6
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.c23
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.h3
-rw-r--r--drivers/net/ethernet/apple/macmace.c6
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_ptp.c10
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_ptp.h4
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_ring.c23
-rw-r--r--drivers/net/ethernet/arc/emac_arc.c6
-rw-r--r--drivers/net/ethernet/arc/emac_rockchip.c5
-rw-r--r--drivers/net/ethernet/asix/ax88796c_ioctl.c2
-rw-r--r--drivers/net/ethernet/atheros/ag71xx.c8
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c.h3
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c80
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.c4
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl2.c2
-rw-r--r--drivers/net/ethernet/broadcom/asp2/bcmasp.c8
-rw-r--r--drivers/net/ethernet/broadcom/bcm4908_enet.c6
-rw-r--r--drivers/net/ethernet/broadcom/bcm63xx_enet.c14
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c8
-rw-r--r--drivers/net/ethernet/broadcom/bgmac-platform.c6
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/Makefile1
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c313
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h23
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c106
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c697
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h545
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c241
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.h30
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.h14
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c5
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c26
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c1
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.c26
-rw-r--r--drivers/net/ethernet/broadcom/sb1250-mac.c6
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c192
-rw-r--r--drivers/net/ethernet/broadcom/tg3.h7
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.c2
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.h1
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c6
-rw-r--r--drivers/net/ethernet/calxeda/xgmac.c6
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_ethtool.c18
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_main.c2
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c3
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_device.c11
-rw-r--r--drivers/net/ethernet/cavium/octeon/octeon_mgmt.c5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/l2t.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/sge.c15
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/clip_tbl.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32_parse.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sched.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/smt.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/sge.c2
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/ch_ipsec/chcr_ipsec.c2
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/ch_ipsec/chcr_ipsec.h1
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c43
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.h36
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h1
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c2
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c36
-rw-r--r--drivers/net/ethernet/cirrus/cs89x0.c5
-rw-r--r--drivers/net/ethernet/cirrus/ep93xx_eth.c8
-rw-r--r--drivers/net/ethernet/cirrus/mac89x0.c5
-rw-r--r--drivers/net/ethernet/cortina/gemini.c57
-rw-r--r--drivers/net/ethernet/cortina/gemini.h4
-rw-r--r--drivers/net/ethernet/davicom/dm9000.c6
-rw-r--r--drivers/net/ethernet/dec/tulip/tulip.h2
-rw-r--r--drivers/net/ethernet/dnet.c6
-rw-r--r--drivers/net/ethernet/engleder/tsnep.h2
-rw-r--r--drivers/net/ethernet/engleder/tsnep_hw.h2
-rw-r--r--drivers/net/ethernet/engleder/tsnep_main.c121
-rw-r--r--drivers/net/ethernet/ethoc.c6
-rw-r--r--drivers/net/ethernet/ezchip/nps_enet.c2
-rw-r--r--drivers/net/ethernet/faraday/ftgmac100.c5
-rw-r--r--drivers/net/ethernet/faraday/ftmac100.c5
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c16
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h2
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c7
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c11
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.c4
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.h2
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_qos.c2
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c196
-rw-r--r--drivers/net/ethernet/freescale/fman/fman_memac.c11
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c18
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mii-fec.c10
-rw-r--r--drivers/net/ethernet/freescale/fsl_pq_mdio.c12
-rw-r--r--drivers/net/ethernet/google/gve/gve_main.c12
-rw-r--r--drivers/net/ethernet/google/gve/gve_rx.c22
-rw-r--r--drivers/net/ethernet/google/gve/gve_tx.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hip04_eth.c6
-rw-r--r--drivers/net/ethernet/hisilicon/hisi_femac.c6
-rw-r--r--drivers/net/ethernet/hisilicon/hix5hd2_gmac.c17
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c29
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c6
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_enet.c58
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_enet.h3
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hnae3.h5
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c1
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c12
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_enet.c5
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c116
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c194
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h18
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c25
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h1
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c7
-rw-r--r--drivers/net/ethernet/hisilicon/hns_mdio.c5
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_devlink.c217
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_tx.c8
-rw-r--r--drivers/net/ethernet/i825xx/sni_82596.c5
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_main.c10
-rw-r--r--drivers/net/ethernet/ibm/emac/core.c6
-rw-r--r--drivers/net/ethernet/ibm/emac/mal.c8
-rw-r--r--drivers/net/ethernet/ibm/emac/rgmii.c6
-rw-r--r--drivers/net/ethernet/ibm/emac/tah.c6
-rw-r--r--drivers/net/ethernet/ibm/emac/zmii.c6
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.c2
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c5
-rw-r--r--drivers/net/ethernet/intel/Kconfig14
-rw-r--r--drivers/net/ethernet/intel/Makefile1
-rw-r--r--drivers/net/ethernet/intel/e100.c2
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c2
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c8
-rw-r--r--drivers/net/ethernet/intel/i40e/Makefile3
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e.h214
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq.c8
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq.h3
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_alloc.h24
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_client.c1
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_common.c73
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_dcb.c4
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ddp.c31
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_debug.h47
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_debugfs.c3
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_devlink.c235
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_devlink.h18
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_diag.h5
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ethtool.c16
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_hmc.c16
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_hmc.h4
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_io.h16
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c9
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c129
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_nvm.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_osdep.h59
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_prototype.h12
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ptp.c3
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_register.h5
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c20
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.h1
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx_common.h2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_type.h62
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c20
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h4
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_xsk.c26
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_xsk.h4
-rw-r--r--drivers/net/ethernet/intel/iavf/Makefile2
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf.h47
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_client.c578
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_client.h169
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_common.c32
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_ethtool.c47
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_fdir.h15
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_main.c430
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_prototype.h2
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_txrx.c46
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_txrx.h1
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_type.h12
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_virtchnl.c186
-rw-r--r--drivers/net/ethernet/intel/ice/Makefile2
-rw-r--r--drivers/net/ethernet/intel/ice/ice.h23
-rw-r--r--drivers/net/ethernet/intel/ice/ice_adminq_cmd.h306
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.c756
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.h51
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ddp.c538
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ddp.h27
-rw-r--r--drivers/net/ethernet/intel/ice/ice_devids.h10
-rw-r--r--drivers/net/ethernet/intel/ice/ice_dpll.c2117
-rw-r--r--drivers/net/ethernet/intel/ice/ice_dpll.h113
-rw-r--r--drivers/net/ethernet/intel/ice/ice_eswitch_br.c6
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool.c228
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool.h8
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c24
-rw-r--r--drivers/net/ethernet/intel/ice/ice_flow.c5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_flow.h3
-rw-r--r--drivers/net/ethernet/intel/ice/ice_gnss.c3
-rw-r--r--drivers/net/ethernet/intel/ice/ice_hw_autogen.h53
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lag.c301
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lag.h4
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.c52
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c112
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.c721
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.h46
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_hw.c812
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_hw.h97
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sched.c56
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sched.h6
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sriov.c314
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sriov.h17
-rw-r--r--drivers/net/ethernet/intel/ice/ice_switch.c63
-rw-r--r--drivers/net/ethernet/intel/ice/ice_tc_lib.c114
-rw-r--r--drivers/net/ethernet/intel/ice/ice_txrx.c3
-rw-r--r--drivers/net/ethernet/intel/ice/ice_txrx.h1
-rw-r--r--drivers/net/ethernet/intel/ice/ice_txrx_lib.c2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_type.h29
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vf_lib.c22
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vf_lib.h9
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.c11
-rw-r--r--drivers/net/ethernet/intel/ice/ice_virtchnl.c101
-rw-r--r--drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c29
-rw-r--r--drivers/net/ethernet/intel/ice/ice_xsk.c22
-rw-r--r--drivers/net/ethernet/intel/idpf/Makefile18
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf.h968
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_controlq.c621
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_controlq.h130
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_controlq_api.h169
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_controlq_setup.c171
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_dev.c165
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_devids.h10
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_ethtool.c1369
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_lan_pf_regs.h124
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_lan_txrx.h293
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_lan_vf_regs.h128
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_lib.c2379
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_main.c279
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_mem.h20
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c1183
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_txrx.c4294
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_txrx.h1023
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_vf_dev.c163
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_virtchnl.c3798
-rw-r--r--drivers/net/ethernet/intel/idpf/virtchnl2.h1273
-rw-r--r--drivers/net/ethernet/intel/idpf/virtchnl2_lan_desc.h451
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c10
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c55
-rw-r--r--drivers/net/ethernet/intel/igbvf/netdev.c2
-rw-r--r--drivers/net/ethernet/intel/igc/igc_ethtool.c40
-rw-r--r--drivers/net/ethernet/intel/igc/igc_main.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c31
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c2
-rw-r--r--drivers/net/ethernet/korina.c6
-rw-r--r--drivers/net/ethernet/lantiq_etop.c6
-rw-r--r--drivers/net/ethernet/lantiq_xrx200.c6
-rw-r--r--drivers/net/ethernet/litex/litex_liteeth.c6
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c11
-rw-r--r--drivers/net/ethernet/marvell/mvmdio.c6
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c36
-rw-r--r--drivers/net/ethernet/marvell/mvneta_bm.c6
-rw-r--r--drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c12
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c168
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_config.h22
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c24
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h18
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_main.c245
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_main.h13
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h4
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_rx.h3
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_tx.h4
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.c8
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/mbox.h13
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/mcs.c18
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/mcs.h2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/mcs_reg.h31
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/npc.h8
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/ptp.c86
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rpm.c11
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.c3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.h1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c7
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c53
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c474
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c12
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c63
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c62
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.c4
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c13
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c18
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c6
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c20
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c126
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c31
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_struct.h34
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c178
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c62
-rw-r--r--drivers/net/ethernet/marvell/pxa168_eth.c5
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.c11
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.h2
-rw-r--r--drivers/net/ethernet/mediatek/mtk_ppe.c4
-rw-r--r--drivers/net/ethernet/mediatek/mtk_ppe.h19
-rw-r--r--drivers/net/ethernet/mediatek/mtk_ppe_offload.c12
-rw-r--r--drivers/net/ethernet/mediatek/mtk_wed.c1432
-rw-r--r--drivers/net/ethernet/mediatek/mtk_wed.h57
-rw-r--r--drivers/net/ethernet/mediatek/mtk_wed_debugfs.c400
-rw-r--r--drivers/net/ethernet/mediatek/mtk_wed_mcu.c150
-rw-r--r--drivers/net/ethernet/mediatek/mtk_wed_regs.h369
-rw-r--r--drivers/net/ethernet/mediatek/mtk_wed_wo.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/Kconfig8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/Makefile3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/cmd.c134
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/dev.c122
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/devlink.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c51
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c118
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/dpll.c432
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h14
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/devlink.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/fs.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/health.c187
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/health.h14
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c426
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c346
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c32
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/rss.c144
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/rss.h20
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c105
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h12
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c30
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c82
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h47
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c587
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c13
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c15
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_fs.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c127
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.c56
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rx.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_stats.h11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c106
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tx.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eq.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c162
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h15
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c96
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.c52
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c57
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/events.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c29
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/health.c129
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c24
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c42
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c47
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c27
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/ipsec_fs_roce.c542
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/ipsec_fs_roce.h14
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/main.c33
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h36
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/pci_irq.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/port.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c101
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c26
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c242
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.c69
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c36
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c115
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/cmd.h43
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.c178
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c70
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h15
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_env.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_linecard_dev.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_thermal.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/i2c.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/pci.c37
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/reg.h20
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c95
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c30
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c69
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c2
-rw-r--r--drivers/net/ethernet/micrel/ks8842.c5
-rw-r--r--drivers/net/ethernet/micrel/ks8851_par.c6
-rw-r--r--drivers/net/ethernet/microchip/lan743x_ethtool.c3
-rw-r--r--drivers/net/ethernet/microchip/lan743x_main.c51
-rw-r--r--drivers/net/ethernet/microchip/lan743x_main.h8
-rw-r--r--drivers/net/ethernet/microchip/lan743x_ptp.c9
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_main.c7
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c3
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_main.c6
-rw-r--r--drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c2
-rw-r--r--drivers/net/ethernet/microsoft/mana/mana_en.c5
-rw-r--r--drivers/net/ethernet/moxa/moxart_ether.c6
-rw-r--r--drivers/net/ethernet/mscc/ocelot_vsc7514.c6
-rw-r--r--drivers/net/ethernet/natsemi/jazzsonic.c6
-rw-r--r--drivers/net/ethernet/natsemi/macsonic.c6
-rw-r--r--drivers/net/ethernet/natsemi/xtsonic.c6
-rw-r--r--drivers/net/ethernet/netronome/nfp/crypto/ipsec.c45
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/cmsg.c10
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/conntrack.c19
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/main.h2
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/metadata.c2
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/offload.c24
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/qos_conf.c20
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c127
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfd3/dp.c2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfd3/xsk.c2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfdk/dp.c2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_repr.h2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c2
-rw-r--r--drivers/net/ethernet/ni/nixge.c11
-rw-r--r--drivers/net/ethernet/nxp/lpc_eth.c6
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_dev.h5
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_lif.c28
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_main.c4
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_txrx.c77
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c2
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_cxt.c1
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_debug.c7
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_devlink.c6
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_ll2.c7
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_ethtool.c46
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac.c6
-rw-r--r--drivers/net/ethernet/qualcomm/qca_debug.c17
-rw-r--r--drivers/net/ethernet/qualcomm/qca_spi.c20
-rw-r--r--drivers/net/ethernet/realtek/r8169_main.c68
-rw-r--r--drivers/net/ethernet/renesas/Kconfig9
-rw-r--r--drivers/net/ethernet/renesas/Makefile4
-rw-r--r--drivers/net/ethernet/renesas/ravb_main.c75
-rw-r--r--drivers/net/ethernet/renesas/rswitch.c89
-rw-r--r--drivers/net/ethernet/renesas/rswitch.h2
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c6
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c6
-rw-r--r--drivers/net/ethernet/seeq/sgiseeq.c6
-rw-r--r--drivers/net/ethernet/sfc/efx_channels.c2
-rw-r--r--drivers/net/ethernet/sfc/mae.c62
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c3
-rw-r--r--drivers/net/ethernet/sfc/ptp.c27
-rw-r--r--drivers/net/ethernet/sfc/siena/efx_channels.c2
-rw-r--r--drivers/net/ethernet/sfc/tc.c375
-rw-r--r--drivers/net/ethernet/sfc/tc.h8
-rw-r--r--drivers/net/ethernet/sfc/tc_conntrack.c91
-rw-r--r--drivers/net/ethernet/sgi/ioc3-eth.c6
-rw-r--r--drivers/net/ethernet/sgi/meth.c6
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c6
-rw-r--r--drivers/net/ethernet/smsc/smc91x.h19
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.c6
-rw-r--r--drivers/net/ethernet/socionext/netsec.c8
-rw-r--r--drivers/net/ethernet/socionext/sni_ave.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Kconfig13
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Makefile1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c15
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c15
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c13
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c33
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c34
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c27
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c19
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c209
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c19
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c25
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c53
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c14
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c16
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c14
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c130
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c23
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c18
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac5.c45
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac5.h4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c17
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.h4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/mmc_core.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c78
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c73
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h5
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c34
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c1
-rw-r--r--drivers/net/ethernet/sun/niu.c5
-rw-r--r--drivers/net/ethernet/sun/sunbmac.c6
-rw-r--r--drivers/net/ethernet/sun/sunqe.c6
-rw-r--r--drivers/net/ethernet/sunplus/spl2sw_driver.c6
-rw-r--r--drivers/net/ethernet/ti/Kconfig14
-rw-r--r--drivers/net/ethernet/ti/Makefile8
-rw-r--r--drivers/net/ethernet/ti/am65-cpsw-nuss.c4
-rw-r--r--drivers/net/ethernet/ti/cpmac.c1251
-rw-r--r--drivers/net/ethernet/ti/cpsw_priv.c2
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c40
-rw-r--r--drivers/net/ethernet/ti/davinci_mdio.c6
-rw-r--r--drivers/net/ethernet/ti/icssg/icss_iep.c2
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_config.c18
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_prueth.c64
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_prueth.h2
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_stats.c9
-rw-r--r--drivers/net/ethernet/ti/k3-cppi-desc-pool.c10
-rw-r--r--drivers/net/ethernet/ti/netcp_core.c5
-rw-r--r--drivers/net/ethernet/ti/netcp_ethss.c4
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_wireless.c2
-rw-r--r--drivers/net/ethernet/toshiba/spider_net.c2
-rw-r--r--drivers/net/ethernet/toshiba/tc35815.c10
-rw-r--r--drivers/net/ethernet/tundra/tsi108_eth.c6
-rw-r--r--drivers/net/ethernet/via/via-rhine.c6
-rw-r--r--drivers/net/ethernet/via/via-velocity.c6
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_ethtool.c169
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_ethtool.h8
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_hw.c199
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_hw.h9
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_lib.c22
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_type.h82
-rw-r--r--drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c5
-rw-r--r--drivers/net/ethernet/wangxun/ngbe/ngbe_hw.c2
-rw-r--r--drivers/net/ethernet/wangxun/ngbe/ngbe_main.c11
-rw-r--r--drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c119
-rw-r--r--drivers/net/ethernet/wangxun/ngbe/ngbe_type.h3
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c5
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c110
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_hw.h1
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_main.c14
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c56
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_type.h6
-rw-r--r--drivers/net/ethernet/wiznet/w5100-spi.c12
-rw-r--r--drivers/net/ethernet/wiznet/w5100.c10
-rw-r--r--drivers/net/ethernet/wiznet/w5300.c5
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c5
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c8
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_emaclite.c8
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c77
-rw-r--r--drivers/net/fjes/fjes_main.c2
-rw-r--r--drivers/net/geneve.c205
-rw-r--r--drivers/net/gtp.c9
-rw-r--r--drivers/net/hamradio/Kconfig15
-rw-r--r--drivers/net/hamradio/baycom_epp.c4
-rw-r--r--drivers/net/hyperv/Kconfig1
-rw-r--r--drivers/net/hyperv/netvsc.c18
-rw-r--r--drivers/net/hyperv/netvsc_drv.c66
-rw-r--r--drivers/net/ieee802154/adf7242.c5
-rw-r--r--drivers/net/ieee802154/ca8210.c17
-rw-r--r--drivers/net/ifb.c1
-rw-r--r--drivers/net/ipa/ipa_power.c2
-rw-r--r--drivers/net/ipa/reg/gsi_reg-v5.0.c2
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c47
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c1
-rw-r--r--drivers/net/macsec.c8
-rw-r--r--drivers/net/macvlan.c2
-rw-r--r--drivers/net/macvtap.c1
-rw-r--r--drivers/net/mctp/Kconfig9
-rw-r--r--drivers/net/mctp/Makefile1
-rw-r--r--drivers/net/mctp/mctp-i3c.c755
-rw-r--r--drivers/net/mdio/acpi_mdio.c1
-rw-r--r--drivers/net/mdio/fwnode_mdio.c1
-rw-r--r--drivers/net/mdio/mdio-aspeed.c7
-rw-r--r--drivers/net/mdio/mdio-bcm-iproc.c6
-rw-r--r--drivers/net/mdio/mdio-bcm-unimac.c6
-rw-r--r--drivers/net/mdio/mdio-bitbang.c1
-rw-r--r--drivers/net/mdio/mdio-gpio.c6
-rw-r--r--drivers/net/mdio/mdio-hisi-femac.c6
-rw-r--r--drivers/net/mdio/mdio-ipq4019.c6
-rw-r--r--drivers/net/mdio/mdio-ipq8064.c7
-rw-r--r--drivers/net/mdio/mdio-moxart.c6
-rw-r--r--drivers/net/mdio/mdio-mscc-miim.c6
-rw-r--r--drivers/net/mdio/mdio-mux-bcm-iproc.c6
-rw-r--r--drivers/net/mdio/mdio-mux-bcm6368.c6
-rw-r--r--drivers/net/mdio/mdio-mux-gpio.c5
-rw-r--r--drivers/net/mdio/mdio-mux-meson-g12a.c6
-rw-r--r--drivers/net/mdio/mdio-mux-meson-gxl.c6
-rw-r--r--drivers/net/mdio/mdio-mux-mmioreg.c6
-rw-r--r--drivers/net/mdio/mdio-mux-multiplexer.c6
-rw-r--r--drivers/net/mdio/mdio-mux.c47
-rw-r--r--drivers/net/mdio/mdio-octeon.c5
-rw-r--r--drivers/net/mdio/mdio-sun4i.c6
-rw-r--r--drivers/net/mdio/mdio-xgene.c27
-rw-r--r--drivers/net/mdio/of_mdio.c1
-rw-r--r--drivers/net/netconsole.c155
-rw-r--r--drivers/net/netdevsim/bpf.c4
-rw-r--r--drivers/net/netdevsim/bus.c12
-rw-r--r--drivers/net/netdevsim/health.c118
-rw-r--r--drivers/net/netdevsim/netdev.c1
-rw-r--r--drivers/net/netkit.c960
-rw-r--r--drivers/net/pcs/pcs-xpcs.c29
-rw-r--r--drivers/net/pcs/pcs-xpcs.h2
-rw-r--r--drivers/net/phy/Kconfig4
-rw-r--r--drivers/net/phy/amd.c33
-rw-r--r--drivers/net/phy/ax88796b.c2
-rw-r--r--drivers/net/phy/bcm-phy-ptp.c1
-rw-r--r--drivers/net/phy/bcm7xxx.c3
-rw-r--r--drivers/net/phy/bcm87xx.c1
-rw-r--r--drivers/net/phy/broadcom.c154
-rw-r--r--drivers/net/phy/dp83867.c137
-rw-r--r--drivers/net/phy/micrel.c22
-rw-r--r--drivers/net/phy/mscc/mscc_macsec.c6
-rw-r--r--drivers/net/phy/nxp-tja11xx.c6
-rw-r--r--drivers/net/phy/phy.c207
-rw-r--r--drivers/net/phy/phylink.c47
-rw-r--r--drivers/net/phy/sfp.c42
-rw-r--r--drivers/net/phy/smsc.c6
-rw-r--r--drivers/net/ppp/ppp_generic.c4
-rw-r--r--drivers/net/ppp/ppp_synctty.c6
-rw-r--r--drivers/net/ppp/pppoe.c2
-rw-r--r--drivers/net/sungem_phy.c1
-rw-r--r--drivers/net/tap.c1
-rw-r--r--drivers/net/team/team.c4
-rw-r--r--drivers/net/tun.c7
-rw-r--r--drivers/net/usb/aqc111.c8
-rw-r--r--drivers/net/usb/ax88179_178a.c4
-rw-r--r--drivers/net/usb/dm9601.c7
-rw-r--r--drivers/net/usb/lan78xx.c2
-rw-r--r--drivers/net/usb/qmi_wwan.c1
-rw-r--r--drivers/net/usb/r8152.c416
-rw-r--r--drivers/net/usb/smsc95xx.c6
-rw-r--r--drivers/net/usb/sr9800.c4
-rw-r--r--drivers/net/veth.c74
-rw-r--r--drivers/net/virtio_net.c272
-rw-r--r--drivers/net/vrf.c39
-rw-r--r--drivers/net/vxlan/vxlan_core.c450
-rw-r--r--drivers/net/vxlan/vxlan_mdb.c190
-rw-r--r--drivers/net/vxlan/vxlan_private.h2
-rw-r--r--drivers/net/wan/ixp4xx_hss.c4
-rw-r--r--drivers/net/wireguard/cookie.c2
-rw-r--r--drivers/net/wireguard/device.c4
-rw-r--r--drivers/net/wireguard/netlink.c2
-rw-r--r--drivers/net/wireguard/noise.c2
-rw-r--r--drivers/net/wireguard/receive.c12
-rw-r--r--drivers/net/wireguard/send.c3
-rw-r--r--drivers/net/wireless/ath/ar5523/ar5523.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c49
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c16
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c26
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c18
-rw-r--r--drivers/net/wireless/ath/ath10k/spectral.c26
-rw-r--r--drivers/net/wireless/ath/ath11k/Makefile3
-rw-r--r--drivers/net/wireless/ath/ath11k/ahb.c10
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c121
-rw-r--r--drivers/net/wireless/ath/ath11k/core.h23
-rw-r--r--drivers/net/wireless/ath/ath11k/debugfs.c8
-rw-r--r--drivers/net/wireless/ath/ath11k/debugfs_sta.c30
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_rx.c39
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_tx.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/fw.c168
-rw-r--r--drivers/net/wireless/ath/ath11k/fw.h27
-rw-r--r--drivers/net/wireless/ath/ath11k/hal.c8
-rw-r--r--drivers/net/wireless/ath/ath11k/hal_rx.c31
-rw-r--r--drivers/net/wireless/ath/ath11k/hal_rx.h18
-rw-r--r--drivers/net/wireless/ath/ath11k/hal_tx.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/hif.h54
-rw-r--r--drivers/net/wireless/ath/ath11k/htc.h12
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c118
-rw-r--r--drivers/net/wireless/ath/ath11k/mhi.c19
-rw-r--r--drivers/net/wireless/ath/ath11k/pci.c24
-rw-r--r--drivers/net/wireless/ath/ath11k/pcic.c6
-rw-r--r--drivers/net/wireless/ath/ath11k/peer.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.c54
-rw-r--r--drivers/net/wireless/ath/ath11k/reg.c11
-rw-r--r--drivers/net/wireless/ath/ath11k/reg.h3
-rw-r--r--drivers/net/wireless/ath/ath11k/spectral.c28
-rw-r--r--drivers/net/wireless/ath/ath11k/thermal.c22
-rw-r--r--drivers/net/wireless/ath/ath11k/thermal.h8
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.c70
-rw-r--r--drivers/net/wireless/ath/ath12k/core.c137
-rw-r--r--drivers/net/wireless/ath/ath12k/core.h31
-rw-r--r--drivers/net/wireless/ath/ath12k/debug.c2
-rw-r--r--drivers/net/wireless/ath/ath12k/dp.c1
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_mon.c16
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.c55
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_tx.c16
-rw-r--r--drivers/net/wireless/ath/ath12k/hal.c12
-rw-r--r--drivers/net/wireless/ath/ath12k/hal_rx.c2
-rw-r--r--drivers/net/wireless/ath/ath12k/hif.h18
-rw-r--r--drivers/net/wireless/ath/ath12k/hw.c24
-rw-r--r--drivers/net/wireless/ath/ath12k/hw.h6
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c311
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/mhi.c12
-rw-r--r--drivers/net/wireless/ath/ath12k/pci.c4
-rw-r--r--drivers/net/wireless/ath/ath12k/peer.h3
-rw-r--r--drivers/net/wireless/ath/ath12k/qmi.c12
-rw-r--r--drivers/net/wireless/ath/ath12k/qmi.h1
-rw-r--r--drivers/net/wireless/ath/ath12k/reg.c14
-rw-r--r--drivers/net/wireless/ath/ath12k/reg.h6
-rw-r--r--drivers/net/wireless/ath/ath12k/rx_desc.h91
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.c131
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.h28
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c6
-rw-r--r--drivers/net/wireless/ath/ath5k/led.c3
-rw-r--r--drivers/net/wireless/ath/ath5k/pci.c4
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c8
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c4
-rw-r--r--drivers/net/wireless/ath/ath6kl/txrx.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c34
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_debug.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c10
-rw-r--r--drivers/net/wireless/ath/dfs_pattern_detector.c21
-rw-r--r--drivers/net/wireless/ath/wcn36xx/dxe.c6
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.c20
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.h2
-rw-r--r--drivers/net/wireless/ath/wcn36xx/testmode.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c3
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c2
-rw-r--r--drivers/net/wireless/atmel/atmel.c72
-rw-r--r--drivers/net/wireless/broadcom/b43/dma.c4
-rw-r--r--drivers/net/wireless/broadcom/b43/pio.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c6
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c6
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h2
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2100.c20
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2200.c23
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw.h2
-rw-r--r--drivers/net/wireless/intel/iwlegacy/4965-mac.c2
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/ax210.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/bz.c16
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/sc.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/commands.h33
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/dev.h14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/main.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/rs.h12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/tt.h9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/tx.c9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.c44
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/commands.h30
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/d3.h46
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h38
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/debug.h22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h68
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/offload.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/power.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rfi.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rx.h16
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/stats.h153
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h78
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/txq.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.c203
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/debugfs.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/file.h32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/img.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/notif-wait.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/rs.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/runtime.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.c50
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.h17
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-csr.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c90
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-fh.h13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c83
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h19
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-prph.h20
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/constants.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c177
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c76
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c148
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c141
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/link.c30
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c28
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c572
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c16
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c264
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h176
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/nvm.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c44
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c72
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/power.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.h23
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c157
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c335
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c39
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tdls.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c198
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.h21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tt.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c130
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c61
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/internal.h59
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/rx.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c46
-rw-r--r--drivers/net/wireless/intel/iwlwifi/queue/tx.c9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/queue/tx.h8
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap.h1
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_download.c3
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_ioctl.c228
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_main.c3
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_wlan.h2
-rw-r--r--drivers/net/wireless/intersil/p54/p54.h2
-rw-r--r--drivers/net/wireless/legacy/ray_cs.c6
-rw-r--r--drivers/net/wireless/marvell/mwifiex/11h.c4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c3
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.h4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.c322
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sdio.c10
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sdio.h4
-rw-r--r--drivers/net/wireless/mediatek/mt76/Kconfig1
-rw-r--r--drivers/net/wireless/mediatek/mt76/Makefile1
-rw-r--r--drivers/net/wireless/mediatek/mt76/debugfs.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/dma.c14
-rw-r--r--drivers/net/wireless/mediatek/mt76/eeprom.c7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mac80211.c64
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76.h36
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/beacon.c76
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/core.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/init.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/mac.c52
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/main.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/regs.h5
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/init.c5
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/main.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mcu.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac.h6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h18
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c28
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c191
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h60
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c11
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c13
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_util.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/init.c33
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mac.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/main.c53
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mcu.c79
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mcu.h18
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mmio.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/regs.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/soc.c5
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/init.c57
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mac.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/main.c78
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mcu.c156
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mcu.h13
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h18
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/pci.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/usb.c12
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/Kconfig30
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/Makefile9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c319
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/init.c235
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/mac.c1452
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/mac.h23
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/main.c1454
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/mcu.c3174
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/mcu.h537
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h309
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/pci.c586
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c148
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c53
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/regs.h92
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/usb.c332
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt792x.h38
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt792x_core.c30
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt792x_dma.c49
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt792x_usb.c9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/init.c53
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mac.c111
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/main.c65
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mcu.c359
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mcu.h37
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/regs.h8
-rw-r--r--drivers/net/wireless/mediatek/mt76/tx.c108
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/tx.c2
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/usb.c1
-rw-r--r--drivers/net/wireless/microchip/wilc1000/cfg80211.c4
-rw-r--r--drivers/net/wireless/microchip/wilc1000/netdev.c20
-rw-r--r--drivers/net/wireless/microchip/wilc1000/netdev.h2
-rw-r--r--drivers/net/wireless/microchip/wilc1000/wlan.c2
-rw-r--r--drivers/net/wireless/purelifi/plfxlc/mac.c2
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/cfg80211.c4
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/commands.c5
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/core.c2
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/event.c4
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800.h18
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800lib.c314
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800mmio.c3
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00.h6
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00dev.c2
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.c18
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/ps.c17
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c9
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c34
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c18
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c16
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c16
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/wifi.h15
-rw-r--r--drivers/net/wireless/realtek/rtw88/debug.c4
-rw-r--r--drivers/net/wireless/realtek/rtw88/debug.h12
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.c74
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.h3
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.h10
-rw-r--r--drivers/net/wireless/realtek/rtw88/ps.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/reg.h23
-rw-r--r--drivers/net/wireless/realtek/rtw88/regd.c24
-rw-r--r--drivers/net/wireless/realtek/rtw88/regd.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c.c67
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c.h1
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c_table.c1154
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822c_table.c1239
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822cu.c4
-rw-r--r--drivers/net/wireless/realtek/rtw88/usb.c9
-rw-r--r--drivers/net/wireless/realtek/rtw89/chan.c1576
-rw-r--r--drivers/net/wireless/realtek/rtw89/chan.h34
-rw-r--r--drivers/net/wireless/realtek/rtw89/coex.c25
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.c465
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.h429
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.c286
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c712
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.h144
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.c211
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.h49
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac80211.c19
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac_be.c397
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.c3
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c515
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.h136
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy_be.c576
-rw-r--r--drivers/net/wireless/realtek/rtw89/reg.h409
-rw-r--r--drivers/net/wireless/realtek/rtw89/regd.c4
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b.c29
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_table.c1337
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_table.h3
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a.c28
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a_table.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a_table.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b.c37
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_table.c333
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_table.h3
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c.c57
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c107
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h3
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_rfk_table.c42
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_table.c3782
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_table.h3
-rw-r--r--drivers/net/wireless/realtek/rtw89/txrx.h271
-rw-r--r--drivers/net/wireless/realtek/rtw89/wow.c4
-rw-r--r--drivers/net/wireless/silabs/wfx/data_tx.c125
-rw-r--r--drivers/net/wireless/silabs/wfx/data_tx.h21
-rw-r--r--drivers/net/wireless/silabs/wfx/hif_tx.c43
-rw-r--r--drivers/net/wireless/silabs/wfx/hif_tx.h1
-rw-r--r--drivers/net/wireless/silabs/wfx/main.c5
-rw-r--r--drivers/net/wireless/silabs/wfx/queue.c38
-rw-r--r--drivers/net/wireless/silabs/wfx/queue.h1
-rw-r--r--drivers/net/wireless/silabs/wfx/scan.c66
-rw-r--r--drivers/net/wireless/silabs/wfx/scan.h6
-rw-r--r--drivers/net/wireless/silabs/wfx/sta.c41
-rw-r--r--drivers/net/wireless/silabs/wfx/sta.h1
-rw-r--r--drivers/net/wireless/silabs/wfx/wfx.h8
-rw-r--r--drivers/net/wireless/st/cw1200/txrx.c4
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c2
-rw-r--r--drivers/net/wireless/ti/wl1251/tx.c6
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c6
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c7
-rw-r--r--drivers/net/wireless/ti/wlcore/boot.c5
-rw-r--r--drivers/net/wireless/ti/wlcore/event.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c16
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h2
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim.c58
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim.h19
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.h2
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_imem.c17
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_imem.h2
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_imem_ops.h4
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_mux.h2
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_pcie.c4
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_pm.h2
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_port.c17
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_port.h2
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_trace.c8
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_trace.h2
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_wwan.c21
-rw-r--r--drivers/net/wwan/rpmsg_wwan_ctrl.c2
-rw-r--r--drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c2
-rw-r--r--drivers/net/wwan/t7xx/t7xx_state_monitor.c3
-rw-r--r--drivers/net/wwan/t7xx/t7xx_state_monitor.h2
-rw-r--r--drivers/net/wwan/wwan_core.c9
-rw-r--r--drivers/net/xen-netback/interface.c12
-rw-r--r--drivers/nfc/virtual_ncidev.c7
-rw-r--r--drivers/nvdimm/badrange.c4
-rw-r--r--drivers/nvdimm/nd.h2
-rw-r--r--drivers/nvdimm/of_pmem.c8
-rw-r--r--drivers/nvdimm/region_devs.c10
-rw-r--r--drivers/nvme/Makefile2
-rw-r--r--drivers/nvme/common/Kconfig12
-rw-r--r--drivers/nvme/common/Makefile6
-rw-r--r--drivers/nvme/common/auth.c91
-rw-r--r--drivers/nvme/common/keyring.c185
-rw-r--r--drivers/nvme/host/Kconfig29
-rw-r--r--drivers/nvme/host/Makefile2
-rw-r--r--drivers/nvme/host/auth.c48
-rw-r--r--drivers/nvme/host/core.c129
-rw-r--r--drivers/nvme/host/fabrics.c69
-rw-r--r--drivers/nvme/host/fabrics.h9
-rw-r--r--drivers/nvme/host/fc.c19
-rw-r--r--drivers/nvme/host/ioctl.c38
-rw-r--r--drivers/nvme/host/nvme.h16
-rw-r--r--drivers/nvme/host/pci.c34
-rw-r--r--drivers/nvme/host/rdma.c27
-rw-r--r--drivers/nvme/host/sysfs.c27
-rw-r--r--drivers/nvme/host/tcp.c216
-rw-r--r--drivers/nvme/target/Kconfig27
-rw-r--r--drivers/nvme/target/auth.c31
-rw-r--r--drivers/nvme/target/configfs.c131
-rw-r--r--drivers/nvme/target/fabrics-cmd-auth.c11
-rw-r--r--drivers/nvme/target/fabrics-cmd.c4
-rw-r--r--drivers/nvme/target/fc.c3
-rw-r--r--drivers/nvme/target/io-cmd-bdev.c20
-rw-r--r--drivers/nvme/target/loop.c4
-rw-r--r--drivers/nvme/target/nvmet.h12
-rw-r--r--drivers/nvme/target/tcp.c350
-rw-r--r--drivers/nvmem/apple-efuses.c1
-rw-r--r--drivers/nvmem/core.c16
-rw-r--r--drivers/nvmem/imx-ocotp-scu.c1
-rw-r--r--drivers/nvmem/imx-ocotp.c7
-rw-r--r--drivers/nvmem/meson-efuse.c1
-rw-r--r--drivers/nvmem/meson-mx-efuse.c1
-rw-r--r--drivers/nvmem/microchip-otpc.c1
-rw-r--r--drivers/nvmem/mtk-efuse.c1
-rw-r--r--drivers/nvmem/mxs-ocotp.c10
-rw-r--r--drivers/nvmem/qcom-spmi-sdam.c1
-rw-r--r--drivers/nvmem/qfprom.c7
-rw-r--r--drivers/nvmem/rave-sp-eeprom.c1
-rw-r--r--drivers/nvmem/rockchip-efuse.c1
-rw-r--r--drivers/nvmem/sc27xx-efuse.c1
-rw-r--r--drivers/nvmem/sec-qfprom.c1
-rw-r--r--drivers/nvmem/sprd-efuse.c1
-rw-r--r--drivers/nvmem/stm32-romem.c8
-rw-r--r--drivers/nvmem/sunplus-ocotp.c1
-rw-r--r--drivers/nvmem/sunxi_sid.c1
-rw-r--r--drivers/nvmem/uniphier-efuse.c1
-rw-r--r--drivers/nvmem/zynqmp_nvmem.c1
-rw-r--r--drivers/of/address.c85
-rw-r--r--drivers/of/dynamic.c5
-rw-r--r--drivers/of/platform.c2
-rw-r--r--drivers/of/property.c2
-rw-r--r--drivers/of/unittest-data/overlay_bad_unresolved.dtso2
-rw-r--r--drivers/of/unittest-data/tests-address.dtsi101
-rw-r--r--drivers/of/unittest.c77
-rw-r--r--drivers/opp/core.c231
-rw-r--r--drivers/opp/debugfs.c2
-rw-r--r--drivers/opp/of.c74
-rw-r--r--drivers/opp/opp.h4
-rw-r--r--drivers/parisc/power.c67
-rw-r--r--drivers/parisc/sba_iommu.c2
-rw-r--r--drivers/parport/parport_gsc.c2
-rw-r--r--drivers/parport/parport_pc.c21
-rw-r--r--drivers/parport/procfs.c81
-rw-r--r--drivers/parport/share.c26
-rw-r--r--drivers/pci/Kconfig2
-rw-r--r--drivers/pci/ats.c7
-rw-r--r--drivers/pci/controller/Kconfig11
-rw-r--r--drivers/pci/controller/Makefile1
-rw-r--r--drivers/pci/controller/cadence/pcie-cadence-ep.c9
-rw-r--r--drivers/pci/controller/cadence/pcie-cadence-plat.c5
-rw-r--r--drivers/pci/controller/dwc/Kconfig25
-rw-r--r--drivers/pci/controller/dwc/Makefile1
-rw-r--r--drivers/pci/controller/dwc/pci-exynos.c4
-rw-r--r--drivers/pci/controller/dwc/pci-keystone.c8
-rw-r--r--drivers/pci/controller/dwc/pci-layerscape-ep.c2
-rw-r--r--drivers/pci/controller/dwc/pci-layerscape.c2
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-ep.c52
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-host.c3
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.c102
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.h9
-rw-r--r--drivers/pci/controller/dwc/pcie-kirin.c4
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom-ep.c48
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom.c55
-rw-r--r--drivers/pci/controller/dwc/pcie-rcar-gen4.c527
-rw-r--r--drivers/pci/controller/dwc/pcie-tegra194.c27
-rw-r--r--drivers/pci/controller/mobiveil/pcie-mobiveil-host.c2
-rw-r--r--drivers/pci/controller/pci-hyperv.c2
-rw-r--r--drivers/pci/controller/pci-loongson.c46
-rw-r--r--drivers/pci/controller/pci-mvebu.c2
-rw-r--r--drivers/pci/controller/pci-xgene.c7
-rw-r--r--drivers/pci/controller/pcie-iproc.c2
-rw-r--r--drivers/pci/controller/pcie-rcar-ep.c2
-rw-r--r--drivers/pci/controller/pcie-rcar-host.c2
-rw-r--r--drivers/pci/controller/pcie-xilinx-common.h31
-rw-r--r--drivers/pci/controller/pcie-xilinx-cpm.c38
-rw-r--r--drivers/pci/controller/pcie-xilinx-dma-pl.c814
-rw-r--r--drivers/pci/controller/pcie-xilinx-nwl.c18
-rw-r--r--drivers/pci/controller/vmd.c12
-rw-r--r--drivers/pci/endpoint/pci-epc-core.c13
-rw-r--r--drivers/pci/hotplug/Kconfig12
-rw-r--r--drivers/pci/hotplug/Makefile1
-rw-r--r--drivers/pci/hotplug/acpiphp_ampere_altra.c127
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c3
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c9
-rw-r--r--drivers/pci/hotplug/cpqphp_ctrl.c6
-rw-r--r--drivers/pci/hotplug/cpqphp_pci.c22
-rw-r--r--drivers/pci/hotplug/ibmphp.h5
-rw-r--r--drivers/pci/hotplug/ibmphp_pci.c2
-rw-r--r--drivers/pci/hotplug/pciehp_core.c3
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c5
-rw-r--r--drivers/pci/hotplug/pnv_php.c3
-rw-r--r--drivers/pci/msi/msi.c10
-rw-r--r--drivers/pci/p2pdma.c3
-rw-r--r--drivers/pci/pci-acpi.c15
-rw-r--r--drivers/pci/pci-sysfs.c43
-rw-r--r--drivers/pci/pci.c69
-rw-r--r--drivers/pci/pci.h3
-rw-r--r--drivers/pci/pcie/Kconfig9
-rw-r--r--drivers/pci/pcie/aer.c214
-rw-r--r--drivers/pci/pcie/aspm.c149
-rw-r--r--drivers/pci/pcie/dpc.c42
-rw-r--r--drivers/pci/pcie/pme.c4
-rw-r--r--drivers/pci/pcie/portdrv.c7
-rw-r--r--drivers/pci/pcie/ptm.c5
-rw-r--r--drivers/pci/probe.c14
-rw-r--r--drivers/pci/quirks.c75
-rw-r--r--drivers/pci/search.c31
-rw-r--r--drivers/pci/setup-bus.c2
-rw-r--r--drivers/pci/vc.c9
-rw-r--r--drivers/pci/vgaarb.c16
-rw-r--r--drivers/pcmcia/cs.c1
-rw-r--r--drivers/pcmcia/ds.c14
-rw-r--r--drivers/pcmcia/pcmcia_resource.c2
-rw-r--r--drivers/pcmcia/tcic.c2
-rw-r--r--drivers/perf/amlogic/meson_g12_ddr_pmu.c1
-rw-r--r--drivers/perf/arm-cmn.c154
-rw-r--r--drivers/perf/arm_cspmu/Kconfig19
-rw-r--r--drivers/perf/arm_cspmu/Makefile8
-rw-r--r--drivers/perf/arm_cspmu/ampere_cspmu.c272
-rw-r--r--drivers/perf/arm_cspmu/arm_cspmu.c212
-rw-r--r--drivers/perf/arm_cspmu/arm_cspmu.h32
-rw-r--r--drivers/perf/arm_cspmu/nvidia_cspmu.c34
-rw-r--r--drivers/perf/arm_cspmu/nvidia_cspmu.h17
-rw-r--r--drivers/perf/arm_pmuv3.c53
-rw-r--r--drivers/perf/hisilicon/hisi_pcie_pmu.c9
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_pa_pmu.c4
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c4
-rw-r--r--drivers/perf/hisilicon/hns3_pmu.c8
-rw-r--r--drivers/perf/qcom_l3_pmu.c4
-rw-r--r--drivers/perf/riscv_pmu.c3
-rw-r--r--drivers/perf/riscv_pmu_sbi.c17
-rw-r--r--drivers/perf/xgene_pmu.c37
-rw-r--r--drivers/phy/Kconfig3
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/allwinner/phy-sun4i-usb.c2
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns-usb3.c9
-rw-r--r--drivers/phy/freescale/phy-fsl-lynx-28g.c27
-rw-r--r--drivers/phy/marvell/phy-berlin-usb.c7
-rw-r--r--drivers/phy/mediatek/phy-mtk-mipi-dsi-mt8183.c2
-rw-r--r--drivers/phy/motorola/phy-cpcap-usb.c7
-rw-r--r--drivers/phy/motorola/phy-mapphone-mdm6600.c38
-rw-r--r--drivers/phy/qualcomm/phy-qcom-apq8064-sata.c2
-rw-r--r--drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c146
-rw-r--r--drivers/phy/qualcomm/phy-qcom-m31.c62
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-combo.c54
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcie.c37
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-misc-v4.h17
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v6.h28
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-v5_20.h2
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6.h20
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-ufs.c142
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-usb.c249
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp.h8
-rw-r--r--drivers/phy/ralink/phy-ralink-usb.c9
-rw-r--r--drivers/phy/realtek/Kconfig27
-rw-r--r--drivers/phy/realtek/Makefile3
-rw-r--r--drivers/phy/realtek/phy-rtk-usb2.c1331
-rw-r--r--drivers/phy/realtek/phy-rtk-usb3.c767
-rw-r--r--drivers/phy/renesas/r8a779f0-ether-serdes.c16
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-usb2.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-pcie.c11
-rw-r--r--drivers/phy/rockchip/phy-rockchip-usb.c10
-rw-r--r--drivers/phy/sunplus/phy-sunplus-usb2.c2
-rw-r--r--drivers/phy/ti/phy-dm816x-usb.c11
-rw-r--r--drivers/phy/ti/phy-gmii-sel.c5
-rw-r--r--drivers/phy/ti/phy-omap-control.c9
-rw-r--r--drivers/phy/ti/phy-omap-usb2.c11
-rw-r--r--drivers/phy/ti/phy-ti-pipe3.c14
-rw-r--r--drivers/pinctrl/Kconfig1
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c19
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c19
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c7
-rw-r--r--drivers/pinctrl/bcm/pinctrl-iproc-gpio.c6
-rw-r--r--drivers/pinctrl/bcm/pinctrl-ns.c8
-rw-r--r--drivers/pinctrl/berlin/berlin-bg2.c8
-rw-r--r--drivers/pinctrl/berlin/berlin-bg2cd.c8
-rw-r--r--drivers/pinctrl/berlin/berlin-bg2q.c8
-rw-r--r--drivers/pinctrl/berlin/berlin-bg4ct.c9
-rw-r--r--drivers/pinctrl/berlin/berlin.c8
-rw-r--r--drivers/pinctrl/berlin/pinctrl-as370.c9
-rw-r--r--drivers/pinctrl/cirrus/Kconfig3
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-cs42l43.c9
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-lochnagar.c2
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-madera-core.c6
-rw-r--r--drivers/pinctrl/core.c145
-rw-r--r--drivers/pinctrl/freescale/pinctrl-mxs.c13
-rw-r--r--drivers/pinctrl/intel/pinctrl-baytrail.c32
-rw-r--r--drivers/pinctrl/intel/pinctrl-broxton.c3
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c161
-rw-r--r--drivers/pinctrl/intel/pinctrl-denverton.c7
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c200
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.h2
-rw-r--r--drivers/pinctrl/intel/pinctrl-lynxpoint.c38
-rw-r--r--drivers/pinctrl/intel/pinctrl-merrifield.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-moorefield.c2
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-moore.c18
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt7981.c16
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.c10
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-paris.c8
-rw-r--r--drivers/pinctrl/meson/Kconfig6
-rw-r--r--drivers/pinctrl/meson/Makefile1
-rw-r--r--drivers/pinctrl/meson/pinctrl-amlogic-t7.c1611
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-38x.c9
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-39x.c9
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-ap806.c5
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-cp110.c6
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-xp.c9
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-dove.c6
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-kirkwood.c7
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-orion.c7
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-abx500.c14
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-nomadik.c10
-rw-r--r--drivers/pinctrl/nuvoton/Kconfig17
-rw-r--r--drivers/pinctrl/nuvoton/Makefile1
-rw-r--r--drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c29
-rw-r--r--drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c2486
-rw-r--r--drivers/pinctrl/nuvoton/pinctrl-wpcm450.c18
-rw-r--r--drivers/pinctrl/nxp/pinctrl-s32cc.c4
-rw-r--r--drivers/pinctrl/pinconf-generic.c16
-rw-r--r--drivers/pinctrl/pinconf.c14
-rw-r--r--drivers/pinctrl/pinctrl-amd.c6
-rw-r--r--drivers/pinctrl/pinctrl-artpec6.c6
-rw-r--r--drivers/pinctrl/pinctrl-as3722.c14
-rw-r--r--drivers/pinctrl/pinctrl-at91.c11
-rw-r--r--drivers/pinctrl/pinctrl-axp209.c7
-rw-r--r--drivers/pinctrl/pinctrl-cy8c95x0.c9
-rw-r--r--drivers/pinctrl/pinctrl-da9062.c7
-rw-r--r--drivers/pinctrl/pinctrl-ingenic.c19
-rw-r--r--drivers/pinctrl/pinctrl-lantiq.h1
-rw-r--r--drivers/pinctrl/pinctrl-mcp23s08.h8
-rw-r--r--drivers/pinctrl/pinctrl-mcp23s08_i2c.c93
-rw-r--r--drivers/pinctrl/pinctrl-mcp23s08_spi.c97
-rw-r--r--drivers/pinctrl/pinctrl-ocelot.c10
-rw-r--r--drivers/pinctrl/pinctrl-rk805.c10
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c6
-rw-r--r--drivers/pinctrl/pinctrl-single.c21
-rw-r--r--drivers/pinctrl/pinctrl-st.c13
-rw-r--r--drivers/pinctrl/pinctrl-stmfx.c16
-rw-r--r--drivers/pinctrl/pinctrl-sx150x.c7
-rw-r--r--drivers/pinctrl/pinctrl-tb10x.c6
-rw-r--r--drivers/pinctrl/pinctrl-utils.c6
-rw-r--r--drivers/pinctrl/pinctrl-xway.c11
-rw-r--r--drivers/pinctrl/pinmux.c6
-rw-r--r--drivers/pinctrl/qcom/pinctrl-apq8064.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-apq8084.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq4019.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq5018.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq5332.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq6018.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq8064.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq8074.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq9574.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-lpass-lpi.c21
-rw-r--r--drivers/pinctrl/qcom/pinctrl-lpass-lpi.h2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-mdm9607.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-mdm9615.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.c4
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.h2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8226.c22
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8660.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8909.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8916.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8953.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8960.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8976.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8994.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8996.c16
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8998.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8x74.c14
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qcm2290.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qcs404.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qdf2xxx.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qdu1000.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sa8775p.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc7180.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc7280.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc8180x.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc8280xp-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc8280xp.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm660.c16
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm670.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm845.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdx55.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdx65.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdx75.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6115-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6115.c14
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6125.c19
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6350.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6375.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm7150.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8150.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8250.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8350-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8350.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8450-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8450.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8550-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8550.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-gpio.c5
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-mpp.c5
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c6
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c6
-rw-r--r--drivers/pinctrl/realtek/Kconfig23
-rw-r--r--drivers/pinctrl/realtek/Makefile6
-rw-r--r--drivers/pinctrl/realtek/pinctrl-rtd.c596
-rw-r--r--drivers/pinctrl/realtek/pinctrl-rtd.h124
-rw-r--r--drivers/pinctrl/realtek/pinctrl-rtd1315e.c1440
-rw-r--r--drivers/pinctrl/realtek/pinctrl-rtd1319d.c1610
-rw-r--r--drivers/pinctrl/realtek/pinctrl-rtd1619b.c1601
-rw-r--r--drivers/pinctrl/renesas/Kconfig1
-rw-r--r--drivers/pinctrl/renesas/gpio.c8
-rw-r--r--drivers/pinctrl/renesas/pfc-r8a7778.c38
-rw-r--r--drivers/pinctrl/renesas/pfc-r8a7779.c2
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzg2l.c719
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzn1.c6
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzv2m.c4
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.c2
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.h2
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c56
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.h4
-rw-r--r--drivers/pinctrl/spear/pinctrl-plgpio.c8
-rw-r--r--drivers/pinctrl/sprd/pinctrl-sprd-sc9860.c2
-rw-r--r--drivers/pinctrl/sprd/pinctrl-sprd.c3
-rw-r--r--drivers/pinctrl/sprd/pinctrl-sprd.h2
-rw-r--r--drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c14
-rw-r--r--drivers/pinctrl/starfive/pinctrl-starfive-jh7110-aon.c4
-rw-r--r--drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c4
-rw-r--r--drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c56
-rw-r--r--drivers/pinctrl/starfive/pinctrl-starfive-jh7110.h4
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32.c33
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c380
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra.c27
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra.h2
-rw-r--r--drivers/pinctrl/ti/pinctrl-ti-iodelay.c29
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-uniphier-core.c2
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wmt.c9
-rw-r--r--drivers/platform/chrome/Kconfig6
-rw-r--r--drivers/platform/chrome/Makefile5
-rw-r--r--drivers/platform/chrome/cros_ec.c116
-rw-r--r--drivers/platform/chrome/cros_ec.h6
-rw-r--r--drivers/platform/chrome/cros_ec_chardev.c6
-rw-r--r--drivers/platform/chrome/cros_ec_debugfs.c6
-rw-r--r--drivers/platform/chrome/cros_ec_lightbar.c6
-rw-r--r--drivers/platform/chrome/cros_ec_lpc.c28
-rw-r--r--drivers/platform/chrome/cros_ec_proto.c2
-rw-r--r--drivers/platform/chrome/cros_ec_proto_test.c3
-rw-r--r--drivers/platform/chrome/cros_ec_proto_test_util.c (renamed from drivers/platform/chrome/cros_kunit_util.c)4
-rw-r--r--drivers/platform/chrome/cros_ec_proto_test_util.h (renamed from drivers/platform/chrome/cros_kunit_util.h)0
-rw-r--r--drivers/platform/chrome/cros_ec_sysfs.c6
-rw-r--r--drivers/platform/chrome/cros_ec_typec.c46
-rw-r--r--drivers/platform/chrome/cros_ec_vbc.c6
-rw-r--r--drivers/platform/chrome/cros_typec_switch.c5
-rw-r--r--drivers/platform/chrome/cros_typec_vdm.c2
-rw-r--r--drivers/platform/chrome/cros_typec_vdm.h2
-rw-r--r--drivers/platform/chrome/cros_usbpd_logger.c6
-rw-r--r--drivers/platform/chrome/cros_usbpd_notify.c12
-rw-r--r--drivers/platform/chrome/wilco_ec/core.c5
-rw-r--r--drivers/platform/chrome/wilco_ec/debugfs.c6
-rw-r--r--drivers/platform/chrome/wilco_ec/event.c2
-rw-r--r--drivers/platform/chrome/wilco_ec/telemetry.c6
-rw-r--r--drivers/platform/mellanox/mlxbf-bootctl.c45
-rw-r--r--drivers/platform/mellanox/mlxbf-pmc.c700
-rw-r--r--drivers/platform/mellanox/mlxbf-tmfifo.c27
-rw-r--r--drivers/platform/mellanox/mlxreg-hotplug.c6
-rw-r--r--drivers/platform/mellanox/mlxreg-io.c6
-rw-r--r--drivers/platform/mellanox/mlxreg-lc.c8
-rw-r--r--drivers/platform/mellanox/nvsw-sn2201.c6
-rw-r--r--drivers/platform/surface/aggregator/core.c5
-rw-r--r--drivers/platform/surface/surface3-wmi.c5
-rw-r--r--drivers/platform/surface/surface_acpi_notify.c16
-rw-r--r--drivers/platform/surface/surface_aggregator_cdev.c5
-rw-r--r--drivers/platform/surface/surface_aggregator_registry.c5
-rw-r--r--drivers/platform/surface/surface_dtx.c5
-rw-r--r--drivers/platform/surface/surface_gpe.c6
-rw-r--r--drivers/platform/surface/surface_hotplug.c6
-rw-r--r--drivers/platform/surface/surface_platform_profile.c3
-rw-r--r--drivers/platform/x86/Kconfig13
-rw-r--r--drivers/platform/x86/Makefile3
-rw-r--r--drivers/platform/x86/acer-wmi.c2
-rw-r--r--drivers/platform/x86/amd/hsmp.c241
-rw-r--r--drivers/platform/x86/amd/pmc/pmc-quirks.c73
-rw-r--r--drivers/platform/x86/amd/pmc/pmc.c119
-rw-r--r--drivers/platform/x86/apple-gmux.c14
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c80
-rw-r--r--drivers/platform/x86/asus-wireless.c12
-rw-r--r--drivers/platform/x86/asus-wmi.c206
-rw-r--r--drivers/platform/x86/asus-wmi.h10
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/biosattr-interface.c2
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/bioscfg.c26
-rw-r--r--drivers/platform/x86/ideapad-laptop.c11
-rw-r--r--drivers/platform/x86/inspur_platform_profile.c216
-rw-r--r--drivers/platform/x86/intel/bytcrc_pwrsrc.c5
-rw-r--r--drivers/platform/x86/intel/ifs/core.c15
-rw-r--r--drivers/platform/x86/intel/ifs/ifs.h64
-rw-r--r--drivers/platform/x86/intel/ifs/load.c166
-rw-r--r--drivers/platform/x86/intel/ifs/runtest.c72
-rw-r--r--drivers/platform/x86/intel/int3472/clk_and_regulator.c54
-rw-r--r--drivers/platform/x86/intel/int3472/common.h7
-rw-r--r--drivers/platform/x86/intel/int3472/discrete.c103
-rw-r--r--drivers/platform/x86/intel/int3472/led.c24
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_mmio.c21
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c21
-rw-r--r--drivers/platform/x86/intel/telemetry/core.c4
-rw-r--r--drivers/platform/x86/intel/tpmi.c81
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c8
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c18
-rw-r--r--drivers/platform/x86/intel/vbtn.c19
-rw-r--r--drivers/platform/x86/intel_ips.c30
-rw-r--r--drivers/platform/x86/mlx-platform.c34
-rw-r--r--drivers/platform/x86/msi-ec.c486
-rw-r--r--drivers/platform/x86/msi-ec.h4
-rw-r--r--drivers/platform/x86/sel3350-platform.c6
-rw-r--r--drivers/platform/x86/siemens/simatic-ipc-batt-apollolake.c6
-rw-r--r--drivers/platform/x86/siemens/simatic-ipc-batt-elkhartlake.c6
-rw-r--r--drivers/platform/x86/siemens/simatic-ipc-batt-f7188x.c6
-rw-r--r--drivers/platform/x86/siemens/simatic-ipc-batt.c9
-rw-r--r--drivers/platform/x86/siemens/simatic-ipc-batt.h4
-rw-r--r--drivers/platform/x86/sony-laptop.c2
-rw-r--r--drivers/platform/x86/think-lmi.c214
-rw-r--r--drivers/platform/x86/think-lmi.h16
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c102
-rw-r--r--drivers/platform/x86/wmi.c268
-rw-r--r--drivers/platform/x86/x86-android-tablets/asus.c1
-rw-r--r--drivers/platform/x86/x86-android-tablets/core.c132
-rw-r--r--drivers/platform/x86/x86-android-tablets/lenovo.c29
-rw-r--r--drivers/platform/x86/x86-android-tablets/other.c11
-rw-r--r--drivers/platform/x86/x86-android-tablets/x86-android-tablets.h7
-rw-r--r--drivers/platform/x86/xo15-ebook.c9
-rw-r--r--drivers/pmdomain/Kconfig21
-rw-r--r--drivers/pmdomain/Makefile1
-rw-r--r--drivers/pmdomain/actions/Kconfig (renamed from drivers/soc/actions/Kconfig)0
-rw-r--r--drivers/pmdomain/actions/owl-sps.c16
-rw-r--r--drivers/pmdomain/amlogic/Kconfig39
-rw-r--r--drivers/pmdomain/amlogic/meson-ee-pwrc.c2
-rw-r--r--drivers/pmdomain/amlogic/meson-secure-pwrc.c127
-rw-r--r--drivers/pmdomain/apple/Kconfig18
-rw-r--r--drivers/pmdomain/arm/Makefile4
-rw-r--r--drivers/pmdomain/arm/scmi_perf_domain.c184
-rw-r--r--drivers/pmdomain/arm/scmi_pm_domain.c (renamed from drivers/firmware/arm_scmi/scmi_pm_domain.c)0
-rw-r--r--drivers/pmdomain/bcm/Kconfig42
-rw-r--r--drivers/pmdomain/bcm/bcm2835-power.c2
-rw-r--r--drivers/pmdomain/imx/Kconfig29
-rw-r--r--drivers/pmdomain/imx/gpc.c8
-rw-r--r--drivers/pmdomain/imx/scu-pd.c3
-rw-r--r--drivers/pmdomain/mediatek/Kconfig29
-rw-r--r--drivers/pmdomain/mediatek/mt6795-pm-domains.h16
-rw-r--r--drivers/pmdomain/mediatek/mt8167-pm-domains.h20
-rw-r--r--drivers/pmdomain/mediatek/mt8173-pm-domains.h16
-rw-r--r--drivers/pmdomain/mediatek/mt8183-pm-domains.h125
-rw-r--r--drivers/pmdomain/mediatek/mt8186-pm-domains.h236
-rw-r--r--drivers/pmdomain/mediatek/mt8188-pm-domains.h223
-rw-r--r--drivers/pmdomain/mediatek/mt8192-pm-domains.h112
-rw-r--r--drivers/pmdomain/mediatek/mt8195-pm-domains.h199
-rw-r--r--drivers/pmdomain/mediatek/mt8365-pm-domains.h197
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.c157
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.h51
-rw-r--r--drivers/pmdomain/qcom/Kconfig41
-rw-r--r--drivers/pmdomain/qcom/cpr.c7
-rw-r--r--drivers/pmdomain/qcom/rpmhpd.c83
-rw-r--r--drivers/pmdomain/qcom/rpmpd.c99
-rw-r--r--drivers/pmdomain/renesas/Kconfig109
-rw-r--r--drivers/pmdomain/renesas/rmobile-sysc.c2
-rw-r--r--drivers/pmdomain/rockchip/Kconfig16
-rw-r--r--drivers/pmdomain/rockchip/pm-domains.c13
-rw-r--r--drivers/pmdomain/samsung/Kconfig8
-rw-r--r--drivers/pmdomain/st/Kconfig5
-rw-r--r--drivers/pmdomain/st/Makefile2
-rw-r--r--drivers/pmdomain/starfive/Kconfig (renamed from drivers/soc/starfive/Kconfig)4
-rw-r--r--drivers/pmdomain/starfive/jh71xx-pmu.c139
-rw-r--r--drivers/pmdomain/sunxi/Kconfig10
-rw-r--r--drivers/pmdomain/tegra/Kconfig6
-rw-r--r--drivers/pmdomain/ti/Kconfig22
-rw-r--r--drivers/pmdomain/ti/Makefile2
-rw-r--r--drivers/pmdomain/ti/ti_sci_pm_domains.c8
-rw-r--r--drivers/pmdomain/xilinx/Kconfig10
-rw-r--r--drivers/pnp/pnpacpi/core.c7
-rw-r--r--drivers/pnp/pnpbios/rsparser.c4
-rw-r--r--drivers/power/reset/Kconfig2
-rw-r--r--drivers/power/reset/axxia-reset.c7
-rw-r--r--drivers/power/reset/gpio-poweroff.c82
-rw-r--r--drivers/power/reset/msm-poweroff.c7
-rw-r--r--drivers/power/reset/nvmem-reboot-mode.c4
-rw-r--r--drivers/power/reset/st-poweroff.c7
-rw-r--r--drivers/power/reset/syscon-poweroff.c29
-rw-r--r--drivers/power/reset/vexpress-poweroff.c11
-rw-r--r--drivers/power/reset/xgene-reboot.c7
-rw-r--r--drivers/power/supply/88pm860x_battery.c8
-rw-r--r--drivers/power/supply/Kconfig34
-rw-r--r--drivers/power/supply/Makefile3
-rw-r--r--drivers/power/supply/ab8500_btemp.c6
-rw-r--r--drivers/power/supply/ab8500_chargalg.c6
-rw-r--r--drivers/power/supply/ab8500_charger.c6
-rw-r--r--drivers/power/supply/ab8500_fg.c6
-rw-r--r--drivers/power/supply/acer_a500_battery.c6
-rw-r--r--drivers/power/supply/act8945a_charger.c6
-rw-r--r--drivers/power/supply/axp20x_ac_power.c2
-rw-r--r--drivers/power/supply/axp20x_usb_power.c2
-rw-r--r--drivers/power/supply/bq24190_charger.c2
-rw-r--r--drivers/power/supply/bq24257_charger.c76
-rw-r--r--drivers/power/supply/bq2515x_charger.c67
-rw-r--r--drivers/power/supply/bq256xx_charger.c52
-rw-r--r--drivers/power/supply/bq25980_charger.c2
-rw-r--r--drivers/power/supply/charger-manager.c12
-rw-r--r--drivers/power/supply/cpcap-battery.c6
-rw-r--r--drivers/power/supply/cpcap-charger.c19
-rw-r--r--drivers/power/supply/da9030_battery.c6
-rw-r--r--drivers/power/supply/da9052-battery.c6
-rw-r--r--drivers/power/supply/da9150-charger.c6
-rw-r--r--drivers/power/supply/goldfish_battery.c5
-rw-r--r--drivers/power/supply/ipaq_micro_battery.c6
-rw-r--r--drivers/power/supply/isp1704_charger.c6
-rw-r--r--drivers/power/supply/lp8788-charger.c6
-rw-r--r--drivers/power/supply/max14577_charger.c6
-rw-r--r--drivers/power/supply/max17040_battery.c27
-rw-r--r--drivers/power/supply/max17042_battery.c6
-rw-r--r--drivers/power/supply/max77650-charger.c6
-rw-r--r--drivers/power/supply/max77693_charger.c6
-rw-r--r--drivers/power/supply/max8925_power.c5
-rw-r--r--drivers/power/supply/mm8013.c317
-rw-r--r--drivers/power/supply/mt6370-charger.c4
-rw-r--r--drivers/power/supply/pcf50633-charger.c6
-rw-r--r--drivers/power/supply/pm8916_bms_vm.c305
-rw-r--r--drivers/power/supply/pm8916_lbc.c381
-rw-r--r--drivers/power/supply/power_supply_core.c10
-rw-r--r--drivers/power/supply/power_supply_sysfs.c12
-rw-r--r--drivers/power/supply/qcom_battmgr.c8
-rw-r--r--drivers/power/supply/qcom_pmi8998_charger.c3
-rw-r--r--drivers/power/supply/qcom_smbb.c6
-rw-r--r--drivers/power/supply/rk817_charger.c13
-rw-r--r--drivers/power/supply/rt5033_charger.c320
-rw-r--r--drivers/power/supply/rx51_battery.c6
-rw-r--r--drivers/power/supply/sbs-battery.c8
-rw-r--r--drivers/power/supply/sc2731_charger.c6
-rw-r--r--drivers/power/supply/surface_battery.c2
-rw-r--r--drivers/power/supply/surface_charger.c2
-rw-r--r--drivers/power/supply/tps65090-charger.c6
-rw-r--r--drivers/power/supply/tps65217_charger.c8
-rw-r--r--drivers/power/supply/twl4030_charger.c6
-rw-r--r--drivers/power/supply/twl4030_madc_battery.c6
-rw-r--r--drivers/power/supply/wm831x_backup.c6
-rw-r--r--drivers/power/supply/wm831x_power.c5
-rw-r--r--drivers/power/supply/wm8350_power.c5
-rw-r--r--drivers/power/supply/wm97xx_battery.c5
-rw-r--r--drivers/powercap/dtpm_cpu.c23
-rw-r--r--drivers/powercap/dtpm_devfreq.c11
-rw-r--r--drivers/powercap/intel_rapl_common.c2
-rw-r--r--drivers/ptp/Kconfig1
-rw-r--r--drivers/ptp/ptp_chardev.c133
-rw-r--r--drivers/ptp/ptp_clock.c54
-rw-r--r--drivers/ptp/ptp_ocp.c369
-rw-r--r--drivers/ptp/ptp_private.h37
-rw-r--r--drivers/ptp/ptp_sysfs.c16
-rw-r--r--drivers/pwm/Kconfig20
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/core.c55
-rw-r--r--drivers/pwm/pwm-ab8500.c1
-rw-r--r--drivers/pwm/pwm-apple.c1
-rw-r--r--drivers/pwm/pwm-atmel-hlcdc.c1
-rw-r--r--drivers/pwm/pwm-atmel-tcb.c1
-rw-r--r--drivers/pwm/pwm-atmel.c3
-rw-r--r--drivers/pwm/pwm-bcm-iproc.c38
-rw-r--r--drivers/pwm/pwm-bcm-kona.c1
-rw-r--r--drivers/pwm/pwm-bcm2835.c34
-rw-r--r--drivers/pwm/pwm-berlin.c63
-rw-r--r--drivers/pwm/pwm-brcmstb.c49
-rw-r--r--drivers/pwm/pwm-clk.c1
-rw-r--r--drivers/pwm/pwm-clps711x.c1
-rw-r--r--drivers/pwm/pwm-crc.c5
-rw-r--r--drivers/pwm/pwm-cros-ec.c67
-rw-r--r--drivers/pwm/pwm-dwc-core.c184
-rw-r--r--drivers/pwm/pwm-dwc.c197
-rw-r--r--drivers/pwm/pwm-dwc.h60
-rw-r--r--drivers/pwm/pwm-ep93xx.c1
-rw-r--r--drivers/pwm/pwm-fsl-ftm.c1
-rw-r--r--drivers/pwm/pwm-hibvt.c1
-rw-r--r--drivers/pwm/pwm-img.c1
-rw-r--r--drivers/pwm/pwm-imx-tpm.c30
-rw-r--r--drivers/pwm/pwm-imx1.c1
-rw-r--r--drivers/pwm/pwm-imx27.c1
-rw-r--r--drivers/pwm/pwm-intel-lgm.c1
-rw-r--r--drivers/pwm/pwm-iqs620a.c1
-rw-r--r--drivers/pwm/pwm-jz4740.c46
-rw-r--r--drivers/pwm/pwm-keembay.c1
-rw-r--r--drivers/pwm/pwm-lp3943.c22
-rw-r--r--drivers/pwm/pwm-lpc18xx-sct.c1
-rw-r--r--drivers/pwm/pwm-lpc32xx.c1
-rw-r--r--drivers/pwm/pwm-lpss.c1
-rw-r--r--drivers/pwm/pwm-mediatek.c1
-rw-r--r--drivers/pwm/pwm-meson.c1
-rw-r--r--drivers/pwm/pwm-microchip-core.c1
-rw-r--r--drivers/pwm/pwm-mtk-disp.c25
-rw-r--r--drivers/pwm/pwm-mxs.c1
-rw-r--r--drivers/pwm/pwm-ntxec.c1
-rw-r--r--drivers/pwm/pwm-omap-dmtimer.c3
-rw-r--r--drivers/pwm/pwm-pca9685.c1
-rw-r--r--drivers/pwm/pwm-pxa.c3
-rw-r--r--drivers/pwm/pwm-raspberrypi-poe.c1
-rw-r--r--drivers/pwm/pwm-rcar.c1
-rw-r--r--drivers/pwm/pwm-renesas-tpu.c23
-rw-r--r--drivers/pwm/pwm-rockchip.c1
-rw-r--r--drivers/pwm/pwm-rz-mtu3.c1
-rw-r--r--drivers/pwm/pwm-samsung.c152
-rw-r--r--drivers/pwm/pwm-sifive.c1
-rw-r--r--drivers/pwm/pwm-sl28cpld.c1
-rw-r--r--drivers/pwm/pwm-spear.c41
-rw-r--r--drivers/pwm/pwm-sprd.c29
-rw-r--r--drivers/pwm/pwm-sti.c30
-rw-r--r--drivers/pwm/pwm-stm32-lp.c1
-rw-r--r--drivers/pwm/pwm-stm32.c1
-rw-r--r--drivers/pwm/pwm-stmpe.c1
-rw-r--r--drivers/pwm/pwm-sun4i.c1
-rw-r--r--drivers/pwm/pwm-sunplus.c1
-rw-r--r--drivers/pwm/pwm-tegra.c1
-rw-r--r--drivers/pwm/pwm-tiecap.c1
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c1
-rw-r--r--drivers/pwm/pwm-twl-led.c2
-rw-r--r--drivers/pwm/pwm-twl.c2
-rw-r--r--drivers/pwm/pwm-visconti.c1
-rw-r--r--drivers/pwm/pwm-vt8500.c43
-rw-r--r--drivers/pwm/pwm-xilinx.c1
-rw-r--r--drivers/rapidio/devices/rio_mport_cdev.c16
-rw-r--r--drivers/rapidio/rio_cm.c18
-rw-r--r--drivers/regulator/Kconfig10
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/da9062-regulator.c2
-rw-r--r--drivers/regulator/da9063-regulator.c2
-rw-r--r--drivers/regulator/da9121-regulator.c15
-rw-r--r--drivers/regulator/da9210-regulator.c12
-rw-r--r--drivers/regulator/fan53555.c9
-rw-r--r--drivers/regulator/fixed.c50
-rw-r--r--drivers/regulator/lochnagar-regulator.c8
-rw-r--r--drivers/regulator/ltc3589.c61
-rw-r--r--drivers/regulator/max1586.c9
-rw-r--r--drivers/regulator/max20086-regulator.c65
-rw-r--r--drivers/regulator/max5970-regulator.c145
-rw-r--r--drivers/regulator/max77503-regulator.c137
-rw-r--r--drivers/regulator/mc13xxx.h2
-rw-r--r--drivers/regulator/mp5416.c10
-rw-r--r--drivers/regulator/mp886x.c14
-rw-r--r--drivers/regulator/mt6358-regulator.c494
-rw-r--r--drivers/regulator/palmas-regulator.c8
-rw-r--r--drivers/regulator/pv88080-regulator.c58
-rw-r--r--drivers/regulator/qcom-labibb-regulator.c7
-rw-r--r--drivers/regulator/qcom-rpmh-regulator.c21
-rw-r--r--drivers/regulator/qcom_rpm-regulator.c7
-rw-r--r--drivers/regulator/qcom_spmi-regulator.c103
-rw-r--r--drivers/regulator/rk808-regulator.c2
-rw-r--r--drivers/regulator/stm32-booster.c5
-rw-r--r--drivers/regulator/sy8824x.c26
-rw-r--r--drivers/regulator/ti-abb-regulator.c22
-rw-r--r--drivers/regulator/tps51632-regulator.c11
-rw-r--r--drivers/remoteproc/mtk_common.h39
-rw-r--r--drivers/remoteproc/mtk_scp.c536
-rw-r--r--drivers/remoteproc/mtk_scp_ipi.c4
-rw-r--r--drivers/remoteproc/qcom_q6v5_mss.c1
-rw-r--r--drivers/remoteproc/qcom_q6v5_pas.c19
-rw-r--r--drivers/remoteproc/st_remoteproc.c16
-rw-r--r--drivers/remoteproc/stm32_rproc.c4
-rw-r--r--drivers/remoteproc/xlnx_r5_remoteproc.c110
-rw-r--r--drivers/reset/core.c4
-rw-r--r--drivers/rpmsg/rpmsg_core.c2
-rw-r--r--drivers/rpmsg/rpmsg_ns.c2
-rw-r--r--drivers/rpmsg/virtio_rpmsg_bus.c6
-rw-r--r--drivers/rtc/Kconfig13
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/nvmem.c1
-rw-r--r--drivers/rtc/rtc-at91rm9200.c14
-rw-r--r--drivers/rtc/rtc-brcmstb-waketimer.c47
-rw-r--r--drivers/rtc/rtc-efi.c2
-rw-r--r--drivers/rtc/rtc-ep93xx.c8
-rw-r--r--drivers/rtc/rtc-imxdi.c14
-rw-r--r--drivers/rtc/rtc-mv.c14
-rw-r--r--drivers/rtc/rtc-omap.c8
-rw-r--r--drivers/rtc/rtc-pcap.c6
-rw-r--r--drivers/rtc/rtc-pcf85363.c2
-rw-r--r--drivers/rtc/rtc-pxa.c13
-rw-r--r--drivers/rtc/rtc-r7301.c35
-rw-r--r--drivers/rtc/rtc-sh.c16
-rw-r--r--drivers/rtc/rtc-ssd202d.c249
-rw-r--r--drivers/s390/block/dasd.c36
-rw-r--r--drivers/s390/block/dasd_genhd.c45
-rw-r--r--drivers/s390/block/dasd_int.h4
-rw-r--r--drivers/s390/block/dasd_ioctl.c2
-rw-r--r--drivers/s390/char/diag_ftp.c2
-rw-r--r--drivers/s390/char/sclp.c14
-rw-r--r--drivers/s390/char/sclp_cmd.c3
-rw-r--r--drivers/s390/char/sclp_early.c2
-rw-r--r--drivers/s390/char/sclp_early_core.c7
-rw-r--r--drivers/s390/cio/chp.c2
-rw-r--r--drivers/s390/cio/chsc.c8
-rw-r--r--drivers/s390/cio/crw.c4
-rw-r--r--drivers/s390/cio/css.c6
-rw-r--r--drivers/s390/cio/isc.c4
-rw-r--r--drivers/s390/crypto/ap_bus.c68
-rw-r--r--drivers/s390/crypto/ap_bus.h4
-rw-r--r--drivers/s390/crypto/ap_queue.c94
-rw-r--r--drivers/s390/crypto/zcrypt_api.c10
-rw-r--r--drivers/s390/crypto/zcrypt_card.c4
-rw-r--r--drivers/s390/crypto/zcrypt_cex4.c4
-rw-r--r--drivers/s390/crypto/zcrypt_error.h18
-rw-r--r--drivers/s390/crypto/zcrypt_queue.c5
-rw-r--r--drivers/s390/net/Kconfig5
-rw-r--r--drivers/s390/net/ctcm_main.c4
-rw-r--r--drivers/s390/net/ism_drv.c93
-rw-r--r--drivers/s390/net/qeth_core_main.c4
-rw-r--r--drivers/scsi/Kconfig15
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c38
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c127
-rw-r--r--drivers/scsi/be2iscsi/be_main.c1
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc.h1
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_hwi.c14
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c94
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.c2
-rw-r--r--drivers/scsi/device_handler/scsi_dh_hp_sw.c79
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c21
-rw-r--r--drivers/scsi/elx/efct/efct_lio.c5
-rw-r--r--drivers/scsi/esas2r/esas2r_ioctl.c16
-rw-r--r--drivers/scsi/fnic/fnic_fcs.c11
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas.h3
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c7
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v3_hw.c253
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c489
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.h50
-rw-r--r--drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c3
-rw-r--r--drivers/scsi/imm.c70
-rw-r--r--drivers/scsi/imm.h4
-rw-r--r--drivers/scsi/ipr.c12
-rw-r--r--drivers/scsi/ips.c18
-rw-r--r--drivers/scsi/libfc/fc_lport.c6
-rw-r--r--drivers/scsi/libsas/sas_discover.c2
-rw-r--r--drivers/scsi/libsas/sas_init.c4
-rw-r--r--drivers/scsi/libsas/sas_internal.h12
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c23
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_logmsg.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c18
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/megaraid.c53
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h4
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c4
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c3
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_os.c57
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c4
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c4
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c89
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c285
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h11
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.c59
-rw-r--r--drivers/scsi/pmcraid.c69
-rw-r--r--drivers/scsi/qedf/qedf.h5
-rw-r--r--drivers/scsi/qedf/qedf_io.c75
-rw-r--r--drivers/scsi/qedf/qedf_main.c19
-rw-r--r--drivers/scsi/qla1280.c42
-rw-r--r--drivers/scsi/qla2xxx/qla_dfs.c59
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c19
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c6
-rw-r--r--drivers/scsi/scsi.c2
-rw-r--r--drivers/scsi/scsi_debug.c568
-rw-r--r--drivers/scsi/scsi_lib.c37
-rw-r--r--drivers/scsi/scsi_sysctl.c1
-rw-r--r--drivers/scsi/scsi_transport_spi.c4
-rw-r--r--drivers/scsi/sd.c158
-rw-r--r--drivers/scsi/sg.c1
-rw-r--r--drivers/scsi/snic/snic_scsi.c14
-rw-r--r--drivers/scsi/sr.c3
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c189
-rw-r--r--drivers/sh/Makefile1
-rw-r--r--drivers/sh/superhyway/Makefile8
-rw-r--r--drivers/sh/superhyway/superhyway-sysfs.c54
-rw-r--r--drivers/sh/superhyway/superhyway.c234
-rw-r--r--drivers/soc/Kconfig2
-rw-r--r--drivers/soc/amlogic/Kconfig35
-rw-r--r--drivers/soc/apple/Kconfig13
-rw-r--r--drivers/soc/aspeed/aspeed-lpc-ctrl.c6
-rw-r--r--drivers/soc/aspeed/aspeed-lpc-snoop.c6
-rw-r--r--drivers/soc/aspeed/aspeed-p2a-ctrl.c6
-rw-r--r--drivers/soc/aspeed/aspeed-uart-routing.c6
-rw-r--r--drivers/soc/bcm/Kconfig53
-rw-r--r--drivers/soc/dove/pmu.c5
-rw-r--r--drivers/soc/fsl/dpaa2-console.c6
-rw-r--r--drivers/soc/fsl/qe/qe.c2
-rw-r--r--drivers/soc/fsl/qe/qe_common.c4
-rw-r--r--drivers/soc/fsl/qe/qmc.c6
-rw-r--r--drivers/soc/fsl/qe/tsa.c5
-rw-r--r--drivers/soc/fujitsu/a64fx-diag.c6
-rw-r--r--drivers/soc/hisilicon/kunpeng_hccs.c14
-rw-r--r--drivers/soc/imx/Kconfig19
-rw-r--r--drivers/soc/ixp4xx/ixp4xx-npe.c6
-rw-r--r--drivers/soc/ixp4xx/ixp4xx-qmgr.c5
-rw-r--r--drivers/soc/litex/litex_soc_ctrl.c5
-rw-r--r--drivers/soc/loongson/loongson2_guts.c6
-rw-r--r--drivers/soc/mediatek/Kconfig23
-rw-r--r--drivers/soc/mediatek/mtk-devapc.c6
-rw-r--r--drivers/soc/mediatek/mtk-mmsys.c6
-rw-r--r--drivers/soc/mediatek/mtk-svs.c184
-rw-r--r--drivers/soc/microchip/mpfs-sys-controller.c6
-rw-r--r--drivers/soc/pxa/ssp.c6
-rw-r--r--drivers/soc/qcom/Kconfig37
-rw-r--r--drivers/soc/qcom/apr.c4
-rw-r--r--drivers/soc/qcom/cmd-db.c8
-rw-r--r--drivers/soc/qcom/icc-bwmon.c6
-rw-r--r--drivers/soc/qcom/kryo-l2-accessors.c4
-rw-r--r--drivers/soc/qcom/llcc-qcom.c367
-rw-r--r--drivers/soc/qcom/ocmem.c12
-rw-r--r--drivers/soc/qcom/pdr_interface.c8
-rw-r--r--drivers/soc/qcom/pmic_glink.c6
-rw-r--r--drivers/soc/qcom/pmic_glink_altmode.c46
-rw-r--r--drivers/soc/qcom/qcom-geni-se.c38
-rw-r--r--drivers/soc/qcom/qcom_aoss.c12
-rw-r--r--drivers/soc/qcom/qcom_gsbi.c6
-rw-r--r--drivers/soc/qcom/qcom_stats.c6
-rw-r--r--drivers/soc/qcom/qmi_encdec.c6
-rw-r--r--drivers/soc/qcom/qmi_interface.c20
-rw-r--r--drivers/soc/qcom/rmtfs_mem.c15
-rw-r--r--drivers/soc/qcom/rpmh.c8
-rw-r--r--drivers/soc/qcom/smd-rpm.c2
-rw-r--r--drivers/soc/qcom/smem.c10
-rw-r--r--drivers/soc/qcom/smp2p.c6
-rw-r--r--drivers/soc/qcom/smsm.c6
-rw-r--r--drivers/soc/qcom/socinfo.c17
-rw-r--r--drivers/soc/qcom/wcnss_ctrl.c3
-rw-r--r--drivers/soc/renesas/Kconfig122
-rw-r--r--drivers/soc/renesas/renesas-soc.c15
-rw-r--r--drivers/soc/rockchip/Kconfig12
-rw-r--r--drivers/soc/rockchip/io-domain.c6
-rw-r--r--drivers/soc/samsung/Kconfig4
-rw-r--r--drivers/soc/samsung/exynos-chipid.c6
-rw-r--r--drivers/soc/sifive/Kconfig2
-rw-r--r--drivers/soc/sunxi/Kconfig9
-rw-r--r--drivers/soc/tegra/Kconfig5
-rw-r--r--drivers/soc/tegra/cbb/tegra194-cbb.c6
-rw-r--r--drivers/soc/tegra/pmc.c8
-rw-r--r--drivers/soc/ti/Kconfig12
-rw-r--r--drivers/soc/ti/k3-ringacc.c5
-rw-r--r--drivers/soc/ti/k3-socinfo.c7
-rw-r--r--drivers/soc/ti/knav_dma.c6
-rw-r--r--drivers/soc/ti/knav_qmss_queue.c13
-rw-r--r--drivers/soc/ti/pm33xx.c5
-rw-r--r--drivers/soc/ti/pruss.c6
-rw-r--r--drivers/soc/ti/smartreflex.c5
-rw-r--r--drivers/soc/ti/wkup_m3_ipc.c6
-rw-r--r--drivers/soc/xilinx/Kconfig9
-rw-r--r--drivers/soundwire/Makefile4
-rw-r--r--drivers/soundwire/bus.c43
-rw-r--r--drivers/soundwire/bus_type.c11
-rw-r--r--drivers/soundwire/dmi-quirks.c2
-rw-r--r--drivers/soundwire/intel.c2
-rw-r--r--drivers/soundwire/intel_ace2x.c5
-rw-r--r--drivers/soundwire/irq.c59
-rw-r--r--drivers/soundwire/irq.h43
-rw-r--r--drivers/soundwire/qcom.c18
-rw-r--r--drivers/soundwire/stream.c9
-rw-r--r--drivers/spi/Kconfig15
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/spi-ar934x.c22
-rw-r--r--drivers/spi/spi-armada-3700.c23
-rw-r--r--drivers/spi/spi-aspeed-smc.c16
-rw-r--r--drivers/spi/spi-at91-usart.c22
-rw-r--r--drivers/spi/spi-ath79.c11
-rw-r--r--drivers/spi/spi-axi-spi-engine.c25
-rw-r--r--drivers/spi/spi-bcm2835.c69
-rw-r--r--drivers/spi/spi-bcm2835aux.c23
-rw-r--r--drivers/spi/spi-cadence-quadspi.c45
-rw-r--r--drivers/spi/spi-cadence.c23
-rw-r--r--drivers/spi/spi-cavium-thunderx.c8
-rw-r--r--drivers/spi/spi-davinci.c11
-rw-r--r--drivers/spi/spi-dw-bt1.c23
-rw-r--r--drivers/spi/spi-dw-mmio.c31
-rw-r--r--drivers/spi/spi-fsl-dspi.c12
-rw-r--r--drivers/spi/spi-geni-qcom.c6
-rw-r--r--drivers/spi/spi-lantiq-ssc.c10
-rw-r--r--drivers/spi/spi-ljca.c297
-rw-r--r--drivers/spi/spi-lm70llp.c20
-rw-r--r--drivers/spi/spi-lp8841-rtc.c56
-rw-r--r--drivers/spi/spi-meson-spicc.c121
-rw-r--r--drivers/spi/spi-meson-spifc.c79
-rw-r--r--drivers/spi/spi-microchip-core-qspi.c39
-rw-r--r--drivers/spi/spi-microchip-core.c83
-rw-r--r--drivers/spi/spi-mpc512x-psc.c54
-rw-r--r--drivers/spi/spi-mpc52xx-psc.c38
-rw-r--r--drivers/spi/spi-mpc52xx.c56
-rw-r--r--drivers/spi/spi-mt65xx.c190
-rw-r--r--drivers/spi/spi-mt7621.c50
-rw-r--r--drivers/spi/spi-mtk-nor.c14
-rw-r--r--drivers/spi/spi-mtk-snfi.c67
-rw-r--r--drivers/spi/spi-mux.c2
-rw-r--r--drivers/spi/spi-mxic.c68
-rw-r--r--drivers/spi/spi-mxs.c70
-rw-r--r--drivers/spi/spi-npcm-fiu.c19
-rw-r--r--drivers/spi/spi-npcm-pspi.c68
-rw-r--r--drivers/spi/spi-nxp-fspi.c32
-rw-r--r--drivers/spi/spi-oc-tiny.c30
-rw-r--r--drivers/spi/spi-omap-uwire.c32
-rw-r--r--drivers/spi/spi-omap2-mcspi.c400
-rw-r--r--drivers/spi/spi-orion.c11
-rw-r--r--drivers/spi/spi-pci1xxxx.c2
-rw-r--r--drivers/spi/spi-pic32-sqi.c27
-rw-r--r--drivers/spi/spi-pic32.c8
-rw-r--r--drivers/spi/spi-pl022.c11
-rw-r--r--drivers/spi/spi-qup.c50
-rw-r--r--drivers/spi/spi-rockchip.c30
-rw-r--r--drivers/spi/spi-rzv2m-csi.c127
-rw-r--r--drivers/spi/spi-stm32.c3
-rw-r--r--drivers/spi/spi-tegra20-slink.c2
-rw-r--r--drivers/spi/spi.c65
-rw-r--r--drivers/spi/spidev.c42
-rw-r--r--drivers/spmi/spmi.c9
-rw-r--r--drivers/ssb/Kconfig3
-rw-r--r--drivers/ssb/main.c2
-rw-r--r--drivers/staging/Kconfig4
-rw-r--r--drivers/staging/Makefile2
-rw-r--r--drivers/staging/fbtft/Kconfig6
-rw-r--r--drivers/staging/fbtft/fbtft-core.c99
-rw-r--r--drivers/staging/fbtft/fbtft.h5
-rw-r--r--drivers/staging/fieldbus/anybuss/arcx-anybus.c17
-rw-r--r--drivers/staging/gdm724x/gdm_tty.c1
-rw-r--r--drivers/staging/greybus/audio_manager_private.h7
-rw-r--r--drivers/staging/greybus/authentication.c19
-rw-r--r--drivers/staging/greybus/bootrom.c2
-rw-r--r--drivers/staging/greybus/camera.c13
-rw-r--r--drivers/staging/greybus/fw-management.c19
-rw-r--r--drivers/staging/greybus/pwm.c1
-rw-r--r--drivers/staging/greybus/raw.c23
-rw-r--r--drivers/staging/iio/Kconfig1
-rw-r--r--drivers/staging/iio/Makefile1
-rw-r--r--drivers/staging/iio/frequency/ad9832.c15
-rw-r--r--drivers/staging/iio/frequency/ad9834.c21
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c22
-rw-r--r--drivers/staging/iio/resolver/Kconfig18
-rw-r--r--drivers/staging/iio/resolver/Makefile6
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.c716
-rw-r--r--drivers/staging/ks7010/ks7010_sdio.c4
-rw-r--r--drivers/staging/media/atomisp/Kconfig12
-rw-r--r--drivers/staging/media/atomisp/Makefile16
-rw-r--r--drivers/staging/media/atomisp/TODO3
-rw-r--r--drivers/staging/media/atomisp/i2c/Kconfig12
-rw-r--r--drivers/staging/media/atomisp/i2c/Makefile1
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-gc0310.c26
-rw-r--r--drivers/staging/media/atomisp/i2c/ov5693/Makefile2
-rw-r--r--drivers/staging/media/atomisp/i2c/ov5693/ad5823.h63
-rw-r--r--drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c1763
-rw-r--r--drivers/staging/media/atomisp/i2c/ov5693/ov5693.h1331
-rw-r--r--drivers/staging/media/atomisp/include/linux/atomisp.h10
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_cmd.c44
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_cmd.h13
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat_css20.c15
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c7
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_fops.c7
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_ioctl.c21
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_subdev.c48
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_subdev.h2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_v4l2.c19
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/isys_irq_local.h3
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/isys_irq_private.h2
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/isys_irq_global.h2
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/debug_global.h7
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/dma.c266
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/dma_local.h116
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_formatter.c2
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_system.c446
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/irq.c19
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/irq_local.h8
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/isp.c60
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/isp_local.h31
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/sp.c47
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/sp_local.h26
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/csi_rx_public.h2
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/dma_public.h13
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/irq_public.h10
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/isp_public.h13
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/isys_dma_public.h2
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/isys_irq_public.h2
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/isys_public.h38
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/pixelgen_public.h2
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/sp_public.h16
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/isys_irq.h2
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_acc_types.h6
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_mipi.h16
-rw-r--r--drivers/staging/media/atomisp/pci/input_system_local.h7
-rw-r--r--drivers/staging/media/atomisp/pci/input_system_private.h7
-rw-r--r--drivers/staging/media/atomisp/pci/input_system_public.h4
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c21
-rw-r--r--drivers/staging/media/atomisp/pci/isp2400_input_system_local.h198
-rw-r--r--drivers/staging/media/atomisp/pci/isp2400_input_system_private.h4
-rw-r--r--drivers/staging/media/atomisp/pci/isp2400_input_system_public.h42
-rw-r--r--drivers/staging/media/atomisp/pci/isp2401_input_system_local.h88
-rw-r--r--drivers/staging/media/atomisp/pci/isp2401_input_system_private.h112
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c15
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h85
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/debug/src/ia_css_debug.c1495
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/ifmtr/src/ifmtr.c2
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys_comm.h2
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/csi_rx_rmgr.c2
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/isys_dma_rmgr.c2
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/isys_init.c31
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/isys_stream2mmio_rmgr.c2
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c229
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.c8
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/pipeline/interface/ia_css_pipeline.h2
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/pipeline/src/pipeline.c2
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css.c238
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_internal.h41
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_mipi.c29
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_params.c41
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_sp.c62
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_sp.h4
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-isc-base.c4
-rw-r--r--drivers/staging/media/ipu3/ipu3-css-params.c44
-rw-r--r--drivers/staging/media/ipu3/ipu3.c6
-rw-r--r--drivers/staging/media/omap4iss/iss_csi2.c2
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus.c2
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_hw.c24
-rw-r--r--drivers/staging/media/tegra-video/csi.c4
-rw-r--r--drivers/staging/media/tegra-video/vip.c2
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.c2
-rw-r--r--drivers/staging/pi433/pi433_if.c21
-rw-r--r--drivers/staging/qlge/Kconfig11
-rw-r--r--drivers/staging/qlge/Makefile8
-rw-r--r--drivers/staging/qlge/TODO33
-rw-r--r--drivers/staging/qlge/qlge.h2293
-rw-r--r--drivers/staging/qlge/qlge_dbg.c1311
-rw-r--r--drivers/staging/qlge/qlge_devlink.c167
-rw-r--r--drivers/staging/qlge/qlge_devlink.h9
-rw-r--r--drivers/staging/qlge/qlge_ethtool.c746
-rw-r--r--drivers/staging/qlge/qlge_main.c4845
-rw-r--r--drivers/staging/qlge/qlge_mpi.c1273
-rw-r--r--drivers/staging/rtl8192e/dot11d.c3
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_def.h2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c173
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h3
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h104
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c17
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h62
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_cam.c120
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_cam.h1
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c358
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.h18
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.c309
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.h27
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pci.c2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_ps.c9
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_wx.c273
-rw-r--r--drivers/staging/rtl8192e/rtl819x_BAProc.c292
-rw-r--r--drivers/staging/rtl8192e/rtl819x_HT.h2
-rw-r--r--drivers/staging/rtl8192e/rtl819x_HTProc.c115
-rw-r--r--drivers/staging/rtl8192e/rtl819x_Qos.h130
-rw-r--r--drivers/staging/rtl8192e/rtl819x_TS.h8
-rw-r--r--drivers/staging/rtl8192e/rtl819x_TSProc.c256
-rw-r--r--drivers/staging/rtl8192e/rtllib.h308
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_ccmp.c19
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_tkip.c40
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_wep.c2
-rw-r--r--drivers/staging/rtl8192e/rtllib_debug.h49
-rw-r--r--drivers/staging/rtl8192e/rtllib_module.c8
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c455
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac.c489
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac_wx.c51
-rw-r--r--drivers/staging/rtl8192e/rtllib_tx.c513
-rw-r--r--drivers/staging/rtl8192e/rtllib_wx.c2
-rw-r--r--drivers/staging/rtl8192u/Kconfig12
-rw-r--r--drivers/staging/rtl8192u/Makefile27
-rw-r--r--drivers/staging/rtl8192u/TODO16
-rw-r--r--drivers/staging/rtl8192u/authors1
-rw-r--r--drivers/staging/rtl8192u/changes4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/dot11d.c174
-rw-r--r--drivers/staging/rtl8192u/ieee80211/dot11d.h57
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211.h2385
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c235
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h86
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c421
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c718
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c247
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_module.c287
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c2430
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c3056
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c598
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c839
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c810
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_BA.h54
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c700
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h302
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c1295
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_Qos.h82
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_TS.h102
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c534
-rw-r--r--drivers/staging/rtl8192u/r8180_93cx6.c170
-rw-r--r--drivers/staging/rtl8192u/r8180_93cx6.h25
-rw-r--r--drivers/staging/rtl8192u/r8190_rtl8256.c294
-rw-r--r--drivers/staging/rtl8192u/r8190_rtl8256.h24
-rw-r--r--drivers/staging/rtl8192u/r8192U.h1129
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c4800
-rw-r--r--drivers/staging/rtl8192u/r8192U_debugfs.c188
-rw-r--r--drivers/staging/rtl8192u/r8192U_dm.c2821
-rw-r--r--drivers/staging/rtl8192u/r8192U_dm.h176
-rw-r--r--drivers/staging/rtl8192u/r8192U_hw.h246
-rw-r--r--drivers/staging/rtl8192u/r8192U_wx.c943
-rw-r--r--drivers/staging/rtl8192u/r8192U_wx.h24
-rw-r--r--drivers/staging/rtl8192u/r819xU_cmdpkt.c508
-rw-r--r--drivers/staging/rtl8192u/r819xU_cmdpkt.h190
-rw-r--r--drivers/staging/rtl8192u/r819xU_firmware.c340
-rw-r--r--drivers/staging/rtl8192u/r819xU_firmware.h19
-rw-r--r--drivers/staging/rtl8192u/r819xU_firmware_img.c549
-rw-r--r--drivers/staging/rtl8192u/r819xU_firmware_img.h26
-rw-r--r--drivers/staging/rtl8192u/r819xU_phy.c1646
-rw-r--r--drivers/staging/rtl8192u/r819xU_phy.h81
-rw-r--r--drivers/staging/rtl8192u/r819xU_phyreg.h143
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c6
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c9
-rw-r--r--drivers/staging/rts5208/rtsx.c24
-rw-r--r--drivers/staging/rts5208/rtsx.h66
-rw-r--r--drivers/staging/sm750fb/ddk750_mode.c94
-rw-r--r--drivers/staging/sm750fb/ddk750_mode.h2
-rw-r--r--drivers/staging/sm750fb/sm750_hw.c2
-rw-r--r--drivers/staging/vc04_services/Makefile1
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835.c32
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835.h1
-rw-r--r--drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c31
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c227
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h3
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.c99
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.h57
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c2
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c407
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h67
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c103
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c66
-rw-r--r--drivers/staging/vme_user/vme.c256
-rw-r--r--drivers/staging/vme_user/vme.h6
-rw-r--r--drivers/staging/vme_user/vme_fake.c77
-rw-r--r--drivers/staging/vme_user/vme_tsi148.c9
-rw-r--r--drivers/staging/vme_user/vme_tsi148.h704
-rw-r--r--drivers/staging/vme_user/vme_user.c26
-rw-r--r--drivers/staging/vt6655/baseband.c86
-rw-r--r--drivers/staging/vt6655/card.c194
-rw-r--r--drivers/staging/vt6655/card.h10
-rw-r--r--drivers/staging/vt6655/channel.c28
-rw-r--r--drivers/staging/vt6655/device.h28
-rw-r--r--drivers/staging/vt6655/device_main.c46
-rw-r--r--drivers/staging/vt6655/dpc.c2
-rw-r--r--drivers/staging/vt6655/rf.c18
-rw-r--r--drivers/staging/vt6655/rf.h2
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c2
-rw-r--r--drivers/staging/wlan-ng/p80211conv.c12
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.h3
-rw-r--r--drivers/staging/wlan-ng/prism2fw.c2
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.h12
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c179
-rw-r--r--drivers/target/iscsi/Kconfig9
-rw-r--r--drivers/target/iscsi/iscsi_target.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_configfs.c5
-rw-r--r--drivers/target/iscsi/iscsi_target_erl1.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_tmr.c2
-rw-r--r--drivers/target/loopback/tcm_loop.c4
-rw-r--r--drivers/target/sbp/sbp_target.c3
-rw-r--r--drivers/target/target_core_alua.c1
-rw-r--r--drivers/target/target_core_configfs.c22
-rw-r--r--drivers/target/target_core_device.c1
-rw-r--r--drivers/target/target_core_fabric_configfs.c24
-rw-r--r--drivers/target/target_core_iblock.c19
-rw-r--r--drivers/target/target_core_iblock.h1
-rw-r--r--drivers/target/target_core_pscsi.c26
-rw-r--r--drivers/target/target_core_pscsi.h2
-rw-r--r--drivers/target/target_core_transport.c116
-rw-r--r--drivers/target/target_core_user.c2
-rw-r--r--drivers/target/tcm_fc/tfc_conf.c3
-rw-r--r--drivers/tee/amdtee/core.c10
-rw-r--r--drivers/tee/optee/device.c17
-rw-r--r--drivers/tee/tee_core.c21
-rw-r--r--drivers/thermal/amlogic_thermal.c8
-rw-r--r--drivers/thermal/armada_thermal.c6
-rw-r--r--drivers/thermal/broadcom/bcm2835_thermal.c6
-rw-r--r--drivers/thermal/broadcom/ns-thermal.c6
-rw-r--r--drivers/thermal/da9062-thermal.c5
-rw-r--r--drivers/thermal/dove_thermal.c6
-rw-r--r--drivers/thermal/gov_bang_bang.c27
-rw-r--r--drivers/thermal/gov_fair_share.c35
-rw-r--r--drivers/thermal/gov_power_allocator.c122
-rw-r--r--drivers/thermal/gov_step_wise.c50
-rw-r--r--drivers/thermal/gov_user_space.c8
-rw-r--r--drivers/thermal/hisi_thermal.c6
-rw-r--r--drivers/thermal/imx8mm_thermal.c8
-rw-r--r--drivers/thermal/imx_thermal.c6
-rw-r--r--drivers/thermal/intel/int340x_thermal/Makefile3
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3400_thermal.c5
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3401_thermal.c6
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3402_thermal.c6
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3403_thermal.c6
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3406_thermal.c5
-rw-r--r--drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c78
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device.c85
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device.h33
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c121
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c3
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c179
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c126
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c255
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c136
-rw-r--r--drivers/thermal/intel/intel_powerclamp.c2
-rw-r--r--drivers/thermal/k3_bandgap.c6
-rw-r--r--drivers/thermal/k3_j72xx_bandgap.c6
-rw-r--r--drivers/thermal/kirkwood_thermal.c6
-rw-r--r--drivers/thermal/max77620_thermal.c8
-rw-r--r--drivers/thermal/mediatek/auxadc_thermal.c2
-rw-r--r--drivers/thermal/mediatek/lvts_thermal.c256
-rw-r--r--drivers/thermal/qcom/tsens-v0_1.c6
-rw-r--r--drivers/thermal/qcom/tsens.c6
-rw-r--r--drivers/thermal/qcom/tsens.h2
-rw-r--r--drivers/thermal/rcar_gen3_thermal.c6
-rw-r--r--drivers/thermal/rcar_thermal.c6
-rw-r--r--drivers/thermal/rockchip_thermal.c6
-rw-r--r--drivers/thermal/rzg2l_thermal.c6
-rw-r--r--drivers/thermal/samsung/exynos_tmu.c6
-rw-r--r--drivers/thermal/spear_thermal.c6
-rw-r--r--drivers/thermal/sprd_thermal.c5
-rw-r--r--drivers/thermal/st/stm_thermal.c6
-rw-r--r--drivers/thermal/tegra/soctherm.c6
-rw-r--r--drivers/thermal/tegra/tegra-bpmp-thermal.c6
-rw-r--r--drivers/thermal/thermal_acpi.c3
-rw-r--r--drivers/thermal/thermal_core.c137
-rw-r--r--drivers/thermal/thermal_core.h9
-rw-r--r--drivers/thermal/thermal_helpers.c8
-rw-r--r--drivers/thermal/thermal_sysfs.c3
-rw-r--r--drivers/thermal/thermal_trip.c55
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.c6
-rw-r--r--drivers/thermal/uniphier_thermal.c6
-rw-r--r--drivers/thunderbolt/clx.c47
-rw-r--r--drivers/thunderbolt/dma_test.c14
-rw-r--r--drivers/thunderbolt/icm.c40
-rw-r--r--drivers/thunderbolt/path.c7
-rw-r--r--drivers/thunderbolt/quirks.c3
-rw-r--r--drivers/thunderbolt/retimer.c1
-rw-r--r--drivers/thunderbolt/switch.c346
-rw-r--r--drivers/thunderbolt/tb.c794
-rw-r--r--drivers/thunderbolt/tb.h60
-rw-r--r--drivers/thunderbolt/tb_regs.h19
-rw-r--r--drivers/thunderbolt/tmu.c2
-rw-r--r--drivers/thunderbolt/tunnel.c263
-rw-r--r--drivers/thunderbolt/tunnel.h26
-rw-r--r--drivers/thunderbolt/usb4.c135
-rw-r--r--drivers/thunderbolt/xdomain.c58
-rw-r--r--drivers/tty/hvc/hvc_xen.c39
-rw-r--r--drivers/tty/hvc/hvcs.c4
-rw-r--r--drivers/tty/mxser.c2
-rw-r--r--drivers/tty/n_gsm.c3
-rw-r--r--drivers/tty/n_tty.c77
-rw-r--r--drivers/tty/serdev/core.c24
-rw-r--r--drivers/tty/serial/21285.c8
-rw-r--r--drivers/tty/serial/8250/8250_aspeed_vuart.c33
-rw-r--r--drivers/tty/serial/8250/8250_bcm7271.c69
-rw-r--r--drivers/tty/serial/8250/8250_core.c14
-rw-r--r--drivers/tty/serial/8250/8250_dma.c8
-rw-r--r--drivers/tty/serial/8250/8250_dw.c36
-rw-r--r--drivers/tty/serial/8250/8250_early.c1
-rw-r--r--drivers/tty/serial/8250/8250_exar.c63
-rw-r--r--drivers/tty/serial/8250/8250_fsl.c6
-rw-r--r--drivers/tty/serial/8250/8250_mid.c18
-rw-r--r--drivers/tty/serial/8250/8250_mtk.c8
-rw-r--r--drivers/tty/serial/8250/8250_of.c44
-rw-r--r--drivers/tty/serial/8250/8250_omap.c143
-rw-r--r--drivers/tty/serial/8250/8250_pci.c591
-rw-r--r--drivers/tty/serial/8250/8250_pci1xxxx.c10
-rw-r--r--drivers/tty/serial/8250/8250_port.c118
-rw-r--r--drivers/tty/serial/8250/Kconfig4
-rw-r--r--drivers/tty/serial/8250/Makefile42
-rw-r--r--drivers/tty/serial/Kconfig26
-rw-r--r--drivers/tty/serial/Makefile126
-rw-r--r--drivers/tty/serial/altera_jtaguart.c28
-rw-r--r--drivers/tty/serial/altera_uart.c20
-rw-r--r--drivers/tty/serial/amba-pl010.c20
-rw-r--r--drivers/tty/serial/amba-pl011.c186
-rw-r--r--drivers/tty/serial/apbuart.c8
-rw-r--r--drivers/tty/serial/ar933x_uart.c26
-rw-r--r--drivers/tty/serial/arc_uart.c16
-rw-r--r--drivers/tty/serial/atmel_serial.c24
-rw-r--r--drivers/tty/serial/bcm63xx_uart.c22
-rw-r--r--drivers/tty/serial/cpm_uart.c8
-rw-r--r--drivers/tty/serial/digicolor-usart.c18
-rw-r--r--drivers/tty/serial/dz.c32
-rw-r--r--drivers/tty/serial/esp32_acm.c459
-rw-r--r--drivers/tty/serial/esp32_uart.c784
-rw-r--r--drivers/tty/serial/fsl_linflexuart.c32
-rw-r--r--drivers/tty/serial/fsl_lpuart.c88
-rw-r--r--drivers/tty/serial/icom.c26
-rw-r--r--drivers/tty/serial/imx.c128
-rw-r--r--drivers/tty/serial/ip22zilog.c36
-rw-r--r--drivers/tty/serial/jsm/jsm_neo.c4
-rw-r--r--drivers/tty/serial/jsm/jsm_tty.c16
-rw-r--r--drivers/tty/serial/liteuart.c20
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c26
-rw-r--r--drivers/tty/serial/ma35d1_serial.c35
-rw-r--r--drivers/tty/serial/max310x.c2
-rw-r--r--drivers/tty/serial/mcf.c20
-rw-r--r--drivers/tty/serial/men_z135_uart.c8
-rw-r--r--drivers/tty/serial/meson_uart.c48
-rw-r--r--drivers/tty/serial/milbeaut_usio.c16
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c12
-rw-r--r--drivers/tty/serial/mps2-uart.c16
-rw-r--r--drivers/tty/serial/msm_serial.c38
-rw-r--r--drivers/tty/serial/mvebu-uart.c18
-rw-r--r--drivers/tty/serial/omap-serial.c38
-rw-r--r--drivers/tty/serial/owl-uart.c26
-rw-r--r--drivers/tty/serial/pch_uart.c10
-rw-r--r--drivers/tty/serial/pic32_uart.c20
-rw-r--r--drivers/tty/serial/pmac_zilog.c52
-rw-r--r--drivers/tty/serial/pxa.c30
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c8
-rw-r--r--drivers/tty/serial/rda-uart.c34
-rw-r--r--drivers/tty/serial/rp2.c20
-rw-r--r--drivers/tty/serial/sa1100.c20
-rw-r--r--drivers/tty/serial/samsung_tty.c171
-rw-r--r--drivers/tty/serial/sb1250-duart.c12
-rw-r--r--drivers/tty/serial/sc16is7xx.c95
-rw-r--r--drivers/tty/serial/serial-tegra.c32
-rw-r--r--drivers/tty/serial/serial_core.c142
-rw-r--r--drivers/tty/serial/serial_mctrl_gpio.c4
-rw-r--r--drivers/tty/serial/serial_port.c4
-rw-r--r--drivers/tty/serial/serial_txx9.c26
-rw-r--r--drivers/tty/serial/sh-sci.c68
-rw-r--r--drivers/tty/serial/sifive.c16
-rw-r--r--drivers/tty/serial/sprd_serial.c30
-rw-r--r--drivers/tty/serial/st-asc.c18
-rw-r--r--drivers/tty/serial/stm32-usart.c51
-rw-r--r--drivers/tty/serial/sunhv.c28
-rw-r--r--drivers/tty/serial/sunplus-uart.c26
-rw-r--r--drivers/tty/serial/sunsab.c34
-rw-r--r--drivers/tty/serial/sunsu.c46
-rw-r--r--drivers/tty/serial/sunzilog.c42
-rw-r--r--drivers/tty/serial/timbuart.c8
-rw-r--r--drivers/tty/serial/uartlite.c18
-rw-r--r--drivers/tty/serial/ucc_uart.c4
-rw-r--r--drivers/tty/serial/vt8500_serial.c8
-rw-r--r--drivers/tty/serial/xilinx_uartps.c58
-rw-r--r--drivers/tty/sysrq.c3
-rw-r--r--drivers/tty/tty.h13
-rw-r--r--drivers/tty/tty_buffer.c5
-rw-r--r--drivers/tty/tty_io.c141
-rw-r--r--drivers/tty/tty_ioctl.c234
-rw-r--r--drivers/tty/tty_jobctrl.c17
-rw-r--r--drivers/tty/tty_port.c6
-rw-r--r--drivers/tty/vcc.c16
-rw-r--r--drivers/tty/vt/consolemap.c2
-rw-r--r--drivers/tty/vt/keyboard.c9
-rw-r--r--drivers/tty/vt/vc_screen.c32
-rw-r--r--drivers/tty/vt/vt.c29
-rw-r--r--drivers/ufs/core/ufs-mcq.c5
-rw-r--r--drivers/ufs/core/ufshcd.c283
-rw-r--r--drivers/ufs/host/cdns-pltfrm.c5
-rw-r--r--drivers/ufs/host/tc-dwc-g210-pltfrm.c6
-rw-r--r--drivers/ufs/host/ti-j721e-ufs.c6
-rw-r--r--drivers/ufs/host/ufs-exynos.c15
-rw-r--r--drivers/ufs/host/ufs-hisi.c5
-rw-r--r--drivers/ufs/host/ufs-mediatek.c7
-rw-r--r--drivers/ufs/host/ufs-qcom.c216
-rw-r--r--drivers/ufs/host/ufs-qcom.h20
-rw-r--r--drivers/ufs/host/ufs-renesas.c6
-rw-r--r--drivers/ufs/host/ufs-sprd.c5
-rw-r--r--drivers/ufs/host/ufshcd-pci.c5
-rw-r--r--drivers/ufs/host/ufshcd-pltfrm.c93
-rw-r--r--drivers/ufs/host/ufshcd-pltfrm.h2
-rw-r--r--drivers/usb/Kconfig10
-rw-r--r--drivers/usb/atm/usbatm.c3
-rw-r--r--drivers/usb/c67x00/c67x00-hcd.h1
-rw-r--r--drivers/usb/cdns3/cdnsp-debug.h3
-rw-r--r--drivers/usb/cdns3/cdnsp-gadget.c9
-rw-r--r--drivers/usb/cdns3/cdnsp-gadget.h5
-rw-r--r--drivers/usb/cdns3/cdnsp-ring.c27
-rw-r--r--drivers/usb/cdns3/core.h3
-rw-r--r--drivers/usb/chipidea/Kconfig4
-rw-r--r--drivers/usb/chipidea/Makefile1
-rw-r--r--drivers/usb/chipidea/ci_hdrc_npcm.c114
-rw-r--r--drivers/usb/chipidea/ci_hdrc_tegra.c16
-rw-r--r--drivers/usb/chipidea/ci_hdrc_usb2.c13
-rw-r--r--drivers/usb/chipidea/host.c48
-rw-r--r--drivers/usb/chipidea/otg.c5
-rw-r--r--drivers/usb/core/config.c3
-rw-r--r--drivers/usb/core/devio.c26
-rw-r--r--drivers/usb/core/hcd-pci.c3
-rw-r--r--drivers/usb/core/hub.c52
-rw-r--r--drivers/usb/core/hub.h5
-rw-r--r--drivers/usb/core/port.c22
-rw-r--r--drivers/usb/dwc2/hcd.c2
-rw-r--r--drivers/usb/dwc2/hcd_intr.c15
-rw-r--r--drivers/usb/dwc2/params.c21
-rw-r--r--drivers/usb/dwc3/Kconfig11
-rw-r--r--drivers/usb/dwc3/Makefile1
-rw-r--r--drivers/usb/dwc3/core.c229
-rw-r--r--drivers/usb/dwc3/core.h19
-rw-r--r--drivers/usb/dwc3/drd.c2
-rw-r--r--drivers/usb/dwc3/dwc3-qcom.c69
-rw-r--r--drivers/usb/dwc3/dwc3-rtk.c481
-rw-r--r--drivers/usb/dwc3/dwc3-xilinx.c14
-rw-r--r--drivers/usb/gadget/function/f_fs.c6
-rw-r--r--drivers/usb/gadget/function/f_hid.c7
-rw-r--r--drivers/usb/gadget/function/f_midi.c4
-rw-r--r--drivers/usb/gadget/function/f_ncm.c53
-rw-r--r--drivers/usb/gadget/function/f_tcm.c3
-rw-r--r--drivers/usb/gadget/function/f_uac2.c16
-rw-r--r--drivers/usb/gadget/function/f_uvc.c14
-rw-r--r--drivers/usb/gadget/function/u_ether.c2
-rw-r--r--drivers/usb/gadget/function/u_uac2.h8
-rw-r--r--drivers/usb/gadget/legacy/inode.c19
-rw-r--r--drivers/usb/gadget/legacy/raw_gadget.c91
-rw-r--r--drivers/usb/gadget/udc/aspeed_udc.c19
-rw-r--r--drivers/usb/gadget/udc/at91_udc.c3
-rw-r--r--drivers/usb/gadget/udc/core.c23
-rw-r--r--drivers/usb/gadget/udc/fsl_qe_udc.c10
-rw-r--r--drivers/usb/gadget/udc/fsl_udc_core.c3
-rw-r--r--drivers/usb/gadget/udc/fusb300_udc.c7
-rw-r--r--drivers/usb/gadget/udc/lpc32xx_udc.c3
-rw-r--r--drivers/usb/gadget/udc/m66592-udc.c3
-rw-r--r--drivers/usb/gadget/udc/r8a66597-udc.c3
-rw-r--r--drivers/usb/gadget/udc/udc-xilinx.c20
-rw-r--r--drivers/usb/host/ohci.h2
-rw-r--r--drivers/usb/host/pci-quirks.c144
-rw-r--r--drivers/usb/host/pci-quirks.h34
-rw-r--r--drivers/usb/host/xhci-debugfs.c2
-rw-r--r--drivers/usb/host/xhci-ext-caps.h27
-rw-r--r--drivers/usb/host/xhci-hub.c23
-rw-r--r--drivers/usb/host/xhci-mem.c100
-rw-r--r--drivers/usb/host/xhci-mtk-sch.c411
-rw-r--r--drivers/usb/host/xhci-mtk.h19
-rw-r--r--drivers/usb/host/xhci-pci.c4
-rw-r--r--drivers/usb/host/xhci-plat.c73
-rw-r--r--drivers/usb/host/xhci-ring.c52
-rw-r--r--drivers/usb/host/xhci-trace.h23
-rw-r--r--drivers/usb/host/xhci.c40
-rw-r--r--drivers/usb/host/xhci.h49
-rw-r--r--drivers/usb/misc/Kconfig13
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/onboard_usb_hub.c10
-rw-r--r--drivers/usb/misc/onboard_usb_hub.h9
-rw-r--r--drivers/usb/misc/usb-ljca.c893
-rw-r--r--drivers/usb/misc/usbtest.c2
-rw-r--r--drivers/usb/mon/mon_main.c23
-rw-r--r--drivers/usb/mtu3/mtu3_plat.c18
-rw-r--r--drivers/usb/musb/da8xx.c1
-rw-r--r--drivers/usb/musb/musb_debugfs.c2
-rw-r--r--drivers/usb/musb/musb_dsps.c2
-rw-r--r--drivers/usb/musb/musb_host.c9
-rw-r--r--drivers/usb/serial/option.c14
-rw-r--r--drivers/usb/storage/uas-detect.h4
-rw-r--r--drivers/usb/storage/uas.c4
-rw-r--r--drivers/usb/storage/unusual_cypress.h2
-rw-r--r--drivers/usb/storage/usb.c20
-rw-r--r--drivers/usb/storage/usb.h4
-rw-r--r--drivers/usb/storage/usual-tables.c17
-rw-r--r--drivers/usb/typec/altmodes/displayport.c28
-rw-r--r--drivers/usb/typec/anx7411.c3
-rw-r--r--drivers/usb/typec/class.c113
-rw-r--r--drivers/usb/typec/class.h16
-rw-r--r--drivers/usb/typec/mux/Kconfig10
-rw-r--r--drivers/usb/typec/mux/Makefile1
-rw-r--r--drivers/usb/typec/mux/fsa4480.c71
-rw-r--r--drivers/usb/typec/mux/intel_pmc_mux.c25
-rw-r--r--drivers/usb/typec/mux/ptn36502.c444
-rw-r--r--drivers/usb/typec/pd.c10
-rw-r--r--drivers/usb/typec/port-mapper.c9
-rw-r--r--drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c12
-rw-r--r--drivers/usb/typec/tcpm/tcpci_rt1711h.c46
-rw-r--r--drivers/usb/typec/tcpm/tcpm.c21
-rw-r--r--drivers/usb/typec/tipd/core.c632
-rw-r--r--drivers/usb/typec/tipd/tps6598x.h36
-rw-r--r--drivers/usb/typec/tipd/trace.h92
-rw-r--r--drivers/usb/typec/ucsi/displayport.c2
-rw-r--r--drivers/usb/typec/ucsi/psy.c9
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c2
-rw-r--r--drivers/usb/typec/ucsi/ucsi_ccg.c4
-rw-r--r--drivers/usb/typec/ucsi/ucsi_glink.c54
-rw-r--r--drivers/usb/usbip/stub_dev.c9
-rw-r--r--drivers/usb/usbip/usbip_common.h6
-rw-r--r--drivers/usb/usbip/vhci_hcd.c44
-rw-r--r--drivers/vdpa/mlx5/core/mlx5_vdpa.h32
-rw-r--r--drivers/vdpa/mlx5/core/mr.c209
-rw-r--r--drivers/vdpa/mlx5/core/resources.c6
-rw-r--r--drivers/vdpa/mlx5/net/debug.c5
-rw-r--r--drivers/vdpa/mlx5/net/mlx5_vnet.c214
-rw-r--r--drivers/vdpa/mlx5/net/mlx5_vnet.h11
-rw-r--r--drivers/vdpa/pds/debugfs.c2
-rw-r--r--drivers/vdpa/pds/vdpa_dev.c7
-rw-r--r--drivers/vdpa/vdpa_sim/vdpa_sim.c52
-rw-r--r--drivers/vdpa/vdpa_sim/vdpa_sim_blk.c9
-rw-r--r--drivers/vdpa/vdpa_user/vduse_dev.c40
-rw-r--r--drivers/vfio/Makefile3
-rw-r--r--drivers/vfio/cdx/main.c58
-rw-r--r--drivers/vfio/cdx/private.h2
-rw-r--r--drivers/vfio/pci/mlx5/Kconfig1
-rw-r--r--drivers/vfio/pci/mlx5/cmd.c103
-rw-r--r--drivers/vfio/pci/mlx5/cmd.h28
-rw-r--r--drivers/vfio/pci/mlx5/main.c284
-rw-r--r--drivers/vfio/pci/pds/Kconfig1
-rw-r--r--drivers/vfio/pci/pds/pci_drv.c5
-rw-r--r--drivers/vfio/pci/pds/vfio_dev.c30
-rw-r--r--drivers/vfio/pci/pds/vfio_dev.h2
-rw-r--r--drivers/vfio/vfio_main.c11
-rw-r--r--drivers/vhost/scsi.c7
-rw-r--r--drivers/vhost/vdpa.c80
-rw-r--r--drivers/vhost/vhost.c4
-rw-r--r--drivers/vhost/vsock.c21
-rw-r--r--drivers/video/backlight/pwm_bl.c22
-rw-r--r--drivers/video/console/Kconfig11
-rw-r--r--drivers/video/console/dummycon.c7
-rw-r--r--drivers/video/console/vgacon.c68
-rw-r--r--drivers/video/fbdev/68328fb.c5
-rw-r--r--drivers/video/fbdev/Kconfig132
-rw-r--r--drivers/video/fbdev/Makefile17
-rw-r--r--drivers/video/fbdev/amba-clcd.c5
-rw-r--r--drivers/video/fbdev/amifb.c15
-rw-r--r--drivers/video/fbdev/arkfb.c2
-rw-r--r--drivers/video/fbdev/atafb.c2
-rw-r--r--drivers/video/fbdev/atmel_lcdfb.c18
-rw-r--r--drivers/video/fbdev/aty/atyfb_base.c7
-rw-r--r--drivers/video/fbdev/aty/radeon_base.c2
-rw-r--r--drivers/video/fbdev/au1100fb.c8
-rw-r--r--drivers/video/fbdev/au1200fb.c9
-rw-r--r--drivers/video/fbdev/bw2.c17
-rw-r--r--drivers/video/fbdev/cg14.c19
-rw-r--r--drivers/video/fbdev/cg3.c17
-rw-r--r--drivers/video/fbdev/cg6.c17
-rw-r--r--drivers/video/fbdev/cirrusfb.c2
-rw-r--r--drivers/video/fbdev/cobalt_lcdfb.c2
-rw-r--r--drivers/video/fbdev/controlfb.c5
-rw-r--r--drivers/video/fbdev/core/Kconfig12
-rw-r--r--drivers/video/fbdev/core/Makefile5
-rw-r--r--drivers/video/fbdev/core/cfbcopyarea.c2
-rw-r--r--drivers/video/fbdev/core/fb_chrdev.c3
-rw-r--r--drivers/video/fbdev/core/fb_internal.h17
-rw-r--r--drivers/video/fbdev/core/fb_io_fops.c3
-rw-r--r--drivers/video/fbdev/core/fb_logo.c508
-rw-r--r--drivers/video/fbdev/core/fbcon.c2
-rw-r--r--drivers/video/fbdev/core/fbmem.c542
-rw-r--r--drivers/video/fbdev/core/syscopyarea.c2
-rw-r--r--drivers/video/fbdev/cyber2000fb.c2
-rw-r--r--drivers/video/fbdev/dnfb.c2
-rw-r--r--drivers/video/fbdev/ep93xx-fb.c5
-rw-r--r--drivers/video/fbdev/ffb.c17
-rw-r--r--drivers/video/fbdev/fsl-diu-fb.c2
-rw-r--r--drivers/video/fbdev/gbefb.c7
-rw-r--r--drivers/video/fbdev/hgafb.c2
-rw-r--r--drivers/video/fbdev/hitfb.c4
-rw-r--r--drivers/video/fbdev/hpfb.c2
-rw-r--r--drivers/video/fbdev/hyperv_fb.c58
-rw-r--r--drivers/video/fbdev/i810/i810_main.c2
-rw-r--r--drivers/video/fbdev/imsttfb.c37
-rw-r--r--drivers/video/fbdev/intelfb/intelfbdrv.c4
-rw-r--r--drivers/video/fbdev/leo.c19
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_base.c2
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_crtc2.c4
-rw-r--r--drivers/video/fbdev/mmp/fb/mmpfb.c7
-rw-r--r--drivers/video/fbdev/mmp/hw/mmp_ctrl.h2
-rw-r--r--drivers/video/fbdev/neofb.c2
-rw-r--r--drivers/video/fbdev/nvidia/nvidia.c2
-rw-r--r--drivers/video/fbdev/offb.c8
-rw-r--r--drivers/video/fbdev/omap/omapfb_main.c28
-rw-r--r--drivers/video/fbdev/omap2/omapfb/Kconfig4
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/connector-analog-tv.c7
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/connector-dvi.c7
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/connector-hdmi.c7
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/encoder-opa362.c7
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/encoder-tfp410.c7
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c7
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/panel-dpi.c7
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c7
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/panel-sharp-ls037v7dw01.c7
-rw-r--r--drivers/video/fbdev/omap2/omapfb/omapfb-main.c5
-rw-r--r--drivers/video/fbdev/omap2/omapfb/vrfb.c9
-rw-r--r--drivers/video/fbdev/p9100.c18
-rw-r--r--drivers/video/fbdev/pm2fb.c2
-rw-r--r--drivers/video/fbdev/pm3fb.c2
-rw-r--r--drivers/video/fbdev/pvr2fb.c14
-rw-r--r--drivers/video/fbdev/riva/fbdev.c2
-rw-r--r--drivers/video/fbdev/s1d13xxxfb.c25
-rw-r--r--drivers/video/fbdev/s3fb.c2
-rw-r--r--drivers/video/fbdev/sa1100fb.c7
-rw-r--r--drivers/video/fbdev/savage/savagefb_driver.c6
-rw-r--r--drivers/video/fbdev/sbuslib.h37
-rw-r--r--drivers/video/fbdev/sis/sis_main.c4
-rw-r--r--drivers/video/fbdev/sm501fb.c4
-rw-r--r--drivers/video/fbdev/sm712fb.c1
-rw-r--r--drivers/video/fbdev/smscufx.c85
-rw-r--r--drivers/video/fbdev/stifb.c2
-rw-r--r--drivers/video/fbdev/sunxvr500.c2
-rw-r--r--drivers/video/fbdev/tcx.c20
-rw-r--r--drivers/video/fbdev/tdfxfb.c6
-rw-r--r--drivers/video/fbdev/tgafb.c2
-rw-r--r--drivers/video/fbdev/tridentfb.c2
-rw-r--r--drivers/video/fbdev/udlfb.c89
-rw-r--r--drivers/video/fbdev/uvesafb.c2
-rw-r--r--drivers/video/fbdev/vermilion/vermilion.c5
-rw-r--r--drivers/video/fbdev/vga16fb.c11
-rw-r--r--drivers/video/fbdev/via/viafbdev.c4
-rw-r--r--drivers/video/fbdev/vt8623fb.c2
-rw-r--r--drivers/virt/Kconfig6
-rw-r--r--drivers/virt/Makefile4
-rw-r--r--drivers/virt/acrn/acrn_drv.h2
-rw-r--r--drivers/virt/acrn/hsm.c2
-rw-r--r--drivers/virt/acrn/mm.c2
-rw-r--r--drivers/virt/coco/Kconfig14
-rw-r--r--drivers/virt/coco/Makefile8
-rw-r--r--drivers/virt/coco/sev-guest/Kconfig1
-rw-r--r--drivers/virt/coco/sev-guest/sev-guest.c214
-rw-r--r--drivers/virt/coco/tdx-guest/Kconfig1
-rw-r--r--drivers/virt/coco/tdx-guest/tdx-guest.c229
-rw-r--r--drivers/virt/coco/tsm.c425
-rw-r--r--drivers/virtio/virtio_balloon.c32
-rw-r--r--drivers/virtio/virtio_mmio.c19
-rw-r--r--drivers/virtio/virtio_pci_common.c6
-rw-r--r--drivers/virtio/virtio_pci_modern.c36
-rw-r--r--drivers/virtio/virtio_pci_modern_dev.c11
-rw-r--r--drivers/virtio/virtio_vdpa.c2
-rw-r--r--drivers/vlynq/Kconfig21
-rw-r--r--drivers/vlynq/Makefile6
-rw-r--r--drivers/vlynq/vlynq.c799
-rw-r--r--drivers/w1/slaves/w1_ds250x.c1
-rw-r--r--drivers/watchdog/Kconfig8
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/apple_wdt.c25
-rw-r--r--drivers/watchdog/ar7_wdt.c315
-rw-r--r--drivers/watchdog/aspeed_wdt.c11
-rw-r--r--drivers/watchdog/at91sam9_wdt.c20
-rw-r--r--drivers/watchdog/ath79_wdt.c19
-rw-r--r--drivers/watchdog/gpio_wdt.c16
-rw-r--r--drivers/watchdog/imx7ulp_wdt.c8
-rw-r--r--drivers/watchdog/imx_sc_wdt.c5
-rw-r--r--drivers/watchdog/it87_wdt.c8
-rw-r--r--drivers/watchdog/ixp4xx_wdt.c28
-rw-r--r--drivers/watchdog/marvell_gti_wdt.c14
-rw-r--r--drivers/watchdog/mlx_wdt.c1
-rw-r--r--drivers/watchdog/of_xilinx_wdt.c13
-rw-r--r--drivers/watchdog/sbsa_gwdt.c4
-rw-r--r--drivers/watchdog/st_lpc_wdt.c11
-rw-r--r--drivers/watchdog/sunplus_wdt.c17
-rw-r--r--drivers/watchdog/wdat_wdt.c2
-rw-r--r--drivers/xen/Kconfig8
-rw-r--r--drivers/xen/balloon.c1
-rw-r--r--drivers/xen/events/events_2l.c8
-rw-r--r--drivers/xen/events/events_base.c577
-rw-r--r--drivers/xen/events/events_fifo.c26
-rw-r--r--drivers/xen/events/events_internal.h1
-rw-r--r--drivers/xen/evtchn.c2
-rw-r--r--drivers/xen/grant-table.c10
-rw-r--r--drivers/xen/pcpu.c22
-rw-r--r--drivers/xen/privcmd.c407
-rw-r--r--drivers/xen/swiotlb-xen.c1
-rw-r--r--drivers/xen/xen-front-pgdir-shbuf.c34
-rw-r--r--drivers/xen/xen-pciback/conf_space.c19
-rw-r--r--drivers/xen/xen-pciback/conf_space_capability.c8
-rw-r--r--drivers/xen/xen-pciback/conf_space_header.c21
-rw-r--r--drivers/xen/xen-scsiback.c3
-rw-r--r--drivers/xen/xenbus/xenbus_dev_frontend.c4
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c2
-rw-r--r--drivers/xen/xenbus/xenbus_probe_backend.c17
-rw-r--r--fs/9p/v9fs.c1
-rw-r--r--fs/9p/v9fs_vfs.h1
-rw-r--r--fs/9p/vfs_inode.c6
-rw-r--r--fs/9p/vfs_inode_dotl.c16
-rw-r--r--fs/9p/xattr.c13
-rw-r--r--fs/9p/xattr.h2
-rw-r--r--fs/Kconfig4
-rw-r--r--fs/Makefile1
-rw-r--r--fs/adfs/inode.c13
-rw-r--r--fs/affs/amigaffs.c4
-rw-r--r--fs/affs/inode.c17
-rw-r--r--fs/affs/namei.c1
-rw-r--r--fs/afs/dynroot.c6
-rw-r--r--fs/afs/inode.c8
-rw-r--r--fs/afs/internal.h7
-rw-r--r--fs/afs/main.c2
-rw-r--r--fs/afs/rxrpc.c2
-rw-r--r--fs/afs/server_list.c2
-rw-r--r--fs/afs/super.c4
-rw-r--r--fs/afs/vl_rotate.c10
-rw-r--r--fs/afs/write.c2
-rw-r--r--fs/afs/xattr.c2
-rw-r--r--fs/anon_inodes.c4
-rw-r--r--fs/attr.c4
-rw-r--r--fs/autofs/autofs_i.h20
-rw-r--r--fs/autofs/init.c9
-rw-r--r--fs/autofs/inode.c463
-rw-r--r--fs/autofs/root.c6
-rw-r--r--fs/bad_inode.c2
-rw-r--r--fs/bcachefs/Kconfig95
-rw-r--r--fs/bcachefs/Makefile89
-rw-r--r--fs/bcachefs/acl.c463
-rw-r--r--fs/bcachefs/acl.h60
-rw-r--r--fs/bcachefs/alloc_background.c2159
-rw-r--r--fs/bcachefs/alloc_background.h259
-rw-r--r--fs/bcachefs/alloc_foreground.c1630
-rw-r--r--fs/bcachefs/alloc_foreground.h224
-rw-r--r--fs/bcachefs/alloc_types.h126
-rw-r--r--fs/bcachefs/backpointers.c860
-rw-r--r--fs/bcachefs/backpointers.h140
-rw-r--r--fs/bcachefs/bbpos.h37
-rw-r--r--fs/bcachefs/bbpos_types.h18
-rw-r--r--fs/bcachefs/bcachefs.h1163
-rw-r--r--fs/bcachefs/bcachefs_format.h2429
-rw-r--r--fs/bcachefs/bcachefs_ioctl.h368
-rw-r--r--fs/bcachefs/bkey.c1120
-rw-r--r--fs/bcachefs/bkey.h778
-rw-r--r--fs/bcachefs/bkey_buf.h61
-rw-r--r--fs/bcachefs/bkey_cmp.h129
-rw-r--r--fs/bcachefs/bkey_methods.c459
-rw-r--r--fs/bcachefs/bkey_methods.h179
-rw-r--r--fs/bcachefs/bkey_sort.c201
-rw-r--r--fs/bcachefs/bkey_sort.h54
-rw-r--r--fs/bcachefs/bset.c1592
-rw-r--r--fs/bcachefs/bset.h541
-rw-r--r--fs/bcachefs/btree_cache.c1215
-rw-r--r--fs/bcachefs/btree_cache.h131
-rw-r--r--fs/bcachefs/btree_gc.c2146
-rw-r--r--fs/bcachefs/btree_gc.h114
-rw-r--r--fs/bcachefs/btree_io.c2297
-rw-r--r--fs/bcachefs/btree_io.h225
-rw-r--r--fs/bcachefs/btree_iter.c3244
-rw-r--r--fs/bcachefs/btree_iter.h943
-rw-r--r--fs/bcachefs/btree_journal_iter.c543
-rw-r--r--fs/bcachefs/btree_journal_iter.h65
-rw-r--r--fs/bcachefs/btree_key_cache.c1074
-rw-r--r--fs/bcachefs/btree_key_cache.h48
-rw-r--r--fs/bcachefs/btree_key_cache_types.h34
-rw-r--r--fs/bcachefs/btree_locking.c817
-rw-r--r--fs/bcachefs/btree_locking.h433
-rw-r--r--fs/bcachefs/btree_trans_commit.c1162
-rw-r--r--fs/bcachefs/btree_types.h725
-rw-r--r--fs/bcachefs/btree_update.c949
-rw-r--r--fs/bcachefs/btree_update.h340
-rw-r--r--fs/bcachefs/btree_update_interior.c2463
-rw-r--r--fs/bcachefs/btree_update_interior.h336
-rw-r--r--fs/bcachefs/btree_write_buffer.c375
-rw-r--r--fs/bcachefs/btree_write_buffer.h14
-rw-r--r--fs/bcachefs/btree_write_buffer_types.h44
-rw-r--r--fs/bcachefs/buckets.c2170
-rw-r--r--fs/bcachefs/buckets.h458
-rw-r--r--fs/bcachefs/buckets_types.h92
-rw-r--r--fs/bcachefs/buckets_waiting_for_journal.c166
-rw-r--r--fs/bcachefs/buckets_waiting_for_journal.h15
-rw-r--r--fs/bcachefs/buckets_waiting_for_journal_types.h23
-rw-r--r--fs/bcachefs/chardev.c784
-rw-r--r--fs/bcachefs/chardev.h31
-rw-r--r--fs/bcachefs/checksum.c804
-rw-r--r--fs/bcachefs/checksum.h213
-rw-r--r--fs/bcachefs/clock.c193
-rw-r--r--fs/bcachefs/clock.h38
-rw-r--r--fs/bcachefs/clock_types.h37
-rw-r--r--fs/bcachefs/compress.c732
-rw-r--r--fs/bcachefs/compress.h73
-rw-r--r--fs/bcachefs/counters.c107
-rw-r--r--fs/bcachefs/counters.h17
-rw-r--r--fs/bcachefs/darray.h93
-rw-r--r--fs/bcachefs/data_update.c651
-rw-r--r--fs/bcachefs/data_update.h49
-rw-r--r--fs/bcachefs/debug.c954
-rw-r--r--fs/bcachefs/debug.h32
-rw-r--r--fs/bcachefs/dirent.c580
-rw-r--r--fs/bcachefs/dirent.h71
-rw-r--r--fs/bcachefs/disk_groups.c622
-rw-r--r--fs/bcachefs/disk_groups.h111
-rw-r--r--fs/bcachefs/disk_groups_types.h18
-rw-r--r--fs/bcachefs/ec.c1981
-rw-r--r--fs/bcachefs/ec.h260
-rw-r--r--fs/bcachefs/ec_types.h41
-rw-r--r--fs/bcachefs/errcode.c68
-rw-r--r--fs/bcachefs/errcode.h270
-rw-r--r--fs/bcachefs/error.c299
-rw-r--r--fs/bcachefs/error.h242
-rw-r--r--fs/bcachefs/extent_update.c173
-rw-r--r--fs/bcachefs/extent_update.h12
-rw-r--r--fs/bcachefs/extents.c1511
-rw-r--r--fs/bcachefs/extents.h765
-rw-r--r--fs/bcachefs/extents_types.h40
-rw-r--r--fs/bcachefs/eytzinger.h281
-rw-r--r--fs/bcachefs/fifo.h127
-rw-r--r--fs/bcachefs/fs-common.c501
-rw-r--r--fs/bcachefs/fs-common.h43
-rw-r--r--fs/bcachefs/fs-io-buffered.c1106
-rw-r--r--fs/bcachefs/fs-io-buffered.h27
-rw-r--r--fs/bcachefs/fs-io-direct.c680
-rw-r--r--fs/bcachefs/fs-io-direct.h16
-rw-r--r--fs/bcachefs/fs-io-pagecache.c791
-rw-r--r--fs/bcachefs/fs-io-pagecache.h176
-rw-r--r--fs/bcachefs/fs-io.c1072
-rw-r--r--fs/bcachefs/fs-io.h184
-rw-r--r--fs/bcachefs/fs-ioctl.c572
-rw-r--r--fs/bcachefs/fs-ioctl.h81
-rw-r--r--fs/bcachefs/fs.c1973
-rw-r--r--fs/bcachefs/fs.h209
-rw-r--r--fs/bcachefs/fsck.c2490
-rw-r--r--fs/bcachefs/fsck.h15
-rw-r--r--fs/bcachefs/inode.c1205
-rw-r--r--fs/bcachefs/inode.h217
-rw-r--r--fs/bcachefs/io_misc.c524
-rw-r--r--fs/bcachefs/io_misc.h34
-rw-r--r--fs/bcachefs/io_read.c1210
-rw-r--r--fs/bcachefs/io_read.h158
-rw-r--r--fs/bcachefs/io_write.c1675
-rw-r--r--fs/bcachefs/io_write.h109
-rw-r--r--fs/bcachefs/io_write_types.h96
-rw-r--r--fs/bcachefs/journal.c1439
-rw-r--r--fs/bcachefs/journal.h450
-rw-r--r--fs/bcachefs/journal_io.c1964
-rw-r--r--fs/bcachefs/journal_io.h65
-rw-r--r--fs/bcachefs/journal_reclaim.c867
-rw-r--r--fs/bcachefs/journal_reclaim.h87
-rw-r--r--fs/bcachefs/journal_sb.c219
-rw-r--r--fs/bcachefs/journal_sb.h24
-rw-r--r--fs/bcachefs/journal_seq_blacklist.c320
-rw-r--r--fs/bcachefs/journal_seq_blacklist.h22
-rw-r--r--fs/bcachefs/journal_types.h319
-rw-r--r--fs/bcachefs/keylist.c52
-rw-r--r--fs/bcachefs/keylist.h74
-rw-r--r--fs/bcachefs/keylist_types.h16
-rw-r--r--fs/bcachefs/logged_ops.c112
-rw-r--r--fs/bcachefs/logged_ops.h20
-rw-r--r--fs/bcachefs/lru.c164
-rw-r--r--fs/bcachefs/lru.h69
-rw-r--r--fs/bcachefs/mean_and_variance.c159
-rw-r--r--fs/bcachefs/mean_and_variance.h198
-rw-r--r--fs/bcachefs/mean_and_variance_test.c240
-rw-r--r--fs/bcachefs/migrate.c179
-rw-r--r--fs/bcachefs/migrate.h7
-rw-r--r--fs/bcachefs/move.c1154
-rw-r--r--fs/bcachefs/move.h158
-rw-r--r--fs/bcachefs/move_types.h36
-rw-r--r--fs/bcachefs/movinggc.c431
-rw-r--r--fs/bcachefs/movinggc.h12
-rw-r--r--fs/bcachefs/nocow_locking.c144
-rw-r--r--fs/bcachefs/nocow_locking.h50
-rw-r--r--fs/bcachefs/nocow_locking_types.h20
-rw-r--r--fs/bcachefs/opts.c602
-rw-r--r--fs/bcachefs/opts.h564
-rw-r--r--fs/bcachefs/printbuf.c425
-rw-r--r--fs/bcachefs/printbuf.h284
-rw-r--r--fs/bcachefs/quota.c979
-rw-r--r--fs/bcachefs/quota.h74
-rw-r--r--fs/bcachefs/quota_types.h43
-rw-r--r--fs/bcachefs/rebalance.c464
-rw-r--r--fs/bcachefs/rebalance.h27
-rw-r--r--fs/bcachefs/rebalance_types.h37
-rw-r--r--fs/bcachefs/recovery.c1060
-rw-r--r--fs/bcachefs/recovery.h33
-rw-r--r--fs/bcachefs/recovery_types.h53
-rw-r--r--fs/bcachefs/reflink.c414
-rw-r--r--fs/bcachefs/reflink.h81
-rw-r--r--fs/bcachefs/replicas.c1059
-rw-r--r--fs/bcachefs/replicas.h93
-rw-r--r--fs/bcachefs/replicas_types.h27
-rw-r--r--fs/bcachefs/sb-clean.c398
-rw-r--r--fs/bcachefs/sb-clean.h16
-rw-r--r--fs/bcachefs/sb-errors.c172
-rw-r--r--fs/bcachefs/sb-errors.h270
-rw-r--r--fs/bcachefs/sb-errors_types.h16
-rw-r--r--fs/bcachefs/sb-members.c420
-rw-r--r--fs/bcachefs/sb-members.h227
-rw-r--r--fs/bcachefs/seqmutex.h48
-rw-r--r--fs/bcachefs/siphash.c173
-rw-r--r--fs/bcachefs/siphash.h87
-rw-r--r--fs/bcachefs/six.c920
-rw-r--r--fs/bcachefs/six.h393
-rw-r--r--fs/bcachefs/snapshot.c1713
-rw-r--r--fs/bcachefs/snapshot.h268
-rw-r--r--fs/bcachefs/str_hash.h370
-rw-r--r--fs/bcachefs/subvolume.c437
-rw-r--r--fs/bcachefs/subvolume.h35
-rw-r--r--fs/bcachefs/subvolume_types.h31
-rw-r--r--fs/bcachefs/super-io.c1271
-rw-r--r--fs/bcachefs/super-io.h94
-rw-r--r--fs/bcachefs/super.c2023
-rw-r--r--fs/bcachefs/super.h52
-rw-r--r--fs/bcachefs/super_types.h41
-rw-r--r--fs/bcachefs/sysfs.c1034
-rw-r--r--fs/bcachefs/sysfs.h48
-rw-r--r--fs/bcachefs/tests.c919
-rw-r--r--fs/bcachefs/tests.h15
-rw-r--r--fs/bcachefs/trace.c17
-rw-r--r--fs/bcachefs/trace.h1327
-rw-r--r--fs/bcachefs/two_state_shared_lock.c8
-rw-r--r--fs/bcachefs/two_state_shared_lock.h59
-rw-r--r--fs/bcachefs/util.c1159
-rw-r--r--fs/bcachefs/util.h833
-rw-r--r--fs/bcachefs/varint.c129
-rw-r--r--fs/bcachefs/varint.h11
-rw-r--r--fs/bcachefs/vstructs.h63
-rw-r--r--fs/bcachefs/xattr.c652
-rw-r--r--fs/bcachefs/xattr.h50
-rw-r--r--fs/befs/linuxvfs.c11
-rw-r--r--fs/bfs/dir.c9
-rw-r--r--fs/bfs/inode.c12
-rw-r--r--fs/binfmt_elf.c215
-rw-r--r--fs/binfmt_elf_fdpic.c20
-rw-r--r--fs/binfmt_misc.c388
-rw-r--r--fs/btrfs/backref.c14
-rw-r--r--fs/btrfs/backref.h3
-rw-r--r--fs/btrfs/ctree.c21
-rw-r--r--fs/btrfs/ctree.h3
-rw-r--r--fs/btrfs/delayed-inode.c20
-rw-r--r--fs/btrfs/dev-replace.c14
-rw-r--r--fs/btrfs/file.c18
-rw-r--r--fs/btrfs/inode.c52
-rw-r--r--fs/btrfs/ioctl.c18
-rw-r--r--fs/btrfs/reflink.c2
-rw-r--r--fs/btrfs/relocation.c7
-rw-r--r--fs/btrfs/super.c2
-rw-r--r--fs/btrfs/transaction.c3
-rw-r--r--fs/btrfs/tree-log.c12
-rw-r--r--fs/btrfs/volumes.c109
-rw-r--r--fs/btrfs/volumes.h6
-rw-r--r--fs/btrfs/xattr.c2
-rw-r--r--fs/btrfs/xattr.h2
-rw-r--r--fs/buffer.c129
-rw-r--r--fs/ceph/acl.c12
-rw-r--r--fs/ceph/addr.c309
-rw-r--r--fs/ceph/cache.c2
-rw-r--r--fs/ceph/caps.c767
-rw-r--r--fs/ceph/crypto.c46
-rw-r--r--fs/ceph/debugfs.c10
-rw-r--r--fs/ceph/dir.c242
-rw-r--r--fs/ceph/export.c49
-rw-r--r--fs/ceph/file.c286
-rw-r--r--fs/ceph/inode.c571
-rw-r--r--fs/ceph/ioctl.c21
-rw-r--r--fs/ceph/locks.c57
-rw-r--r--fs/ceph/mds_client.c688
-rw-r--r--fs/ceph/mds_client.h13
-rw-r--r--fs/ceph/mdsmap.c29
-rw-r--r--fs/ceph/mdsmap.h (renamed from include/linux/ceph/mdsmap.h)5
-rw-r--r--fs/ceph/metric.c5
-rw-r--r--fs/ceph/quota.c29
-rw-r--r--fs/ceph/snap.c196
-rw-r--r--fs/ceph/super.c99
-rw-r--r--fs/ceph/super.h25
-rw-r--r--fs/ceph/xattr.c110
-rw-r--r--fs/char_dev.c4
-rw-r--r--fs/coda/coda_linux.c6
-rw-r--r--fs/coda/dir.c2
-rw-r--r--fs/coda/file.c2
-rw-r--r--fs/configfs/inode.c8
-rw-r--r--fs/cramfs/inode.c6
-rw-r--r--fs/crypto/bio.c39
-rw-r--r--fs/crypto/crypto.c163
-rw-r--r--fs/crypto/fname.c6
-rw-r--r--fs/crypto/fscrypt_private.h164
-rw-r--r--fs/crypto/hooks.c4
-rw-r--r--fs/crypto/inline_crypt.c32
-rw-r--r--fs/crypto/keyring.c82
-rw-r--r--fs/crypto/keysetup.c62
-rw-r--r--fs/crypto/keysetup_v1.c22
-rw-r--r--fs/crypto/policy.c83
-rw-r--r--fs/dax.c24
-rw-r--r--fs/dcache.c20
-rw-r--r--fs/debugfs/file.c92
-rw-r--r--fs/debugfs/inode.c66
-rw-r--r--fs/debugfs/internal.h15
-rw-r--r--fs/devpts/inode.c6
-rw-r--r--fs/direct-io.c2
-rw-r--r--fs/dlm/debug_fs.c18
-rw-r--r--fs/dlm/lowcomms.c12
-rw-r--r--fs/dlm/midcomms.c39
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h2
-rw-r--r--fs/ecryptfs/inode.c14
-rw-r--r--fs/efivarfs/file.c2
-rw-r--r--fs/efivarfs/inode.c6
-rw-r--r--fs/efivarfs/internal.h9
-rw-r--r--fs/efivarfs/super.c70
-rw-r--r--fs/efs/inode.c5
-rw-r--r--fs/efs/super.c1
-rw-r--r--fs/erofs/Kconfig9
-rw-r--r--fs/erofs/compress.h6
-rw-r--r--fs/erofs/data.c7
-rw-r--r--fs/erofs/decompressor.c63
-rw-r--r--fs/erofs/decompressor_deflate.c6
-rw-r--r--fs/erofs/decompressor_lzma.c7
-rw-r--r--fs/erofs/inode.c101
-rw-r--r--fs/erofs/internal.h44
-rw-r--r--fs/erofs/super.c102
-rw-r--r--fs/erofs/utils.c27
-rw-r--r--fs/erofs/xattr.c2
-rw-r--r--fs/erofs/xattr.h4
-rw-r--r--fs/erofs/zdata.c1
-rw-r--r--fs/eventpoll.c6
-rw-r--r--fs/exec.c4
-rw-r--r--fs/exfat/dir.c20
-rw-r--r--fs/exfat/exfat_fs.h15
-rw-r--r--fs/exfat/exfat_raw.h19
-rw-r--r--fs/exfat/file.c103
-rw-r--r--fs/exfat/inode.c37
-rw-r--r--fs/exfat/misc.c8
-rw-r--r--fs/exfat/namei.c83
-rw-r--r--fs/exfat/super.c15
-rw-r--r--fs/exportfs/expfs.c57
-rw-r--r--fs/ext2/dir.c220
-rw-r--r--fs/ext2/ext2.h23
-rw-r--r--fs/ext2/file.c1
-rw-r--r--fs/ext2/ialloc.c2
-rw-r--r--fs/ext2/inode.c13
-rw-r--r--fs/ext2/namei.c32
-rw-r--r--fs/ext2/super.c3
-rw-r--r--fs/ext2/xattr.c4
-rw-r--r--fs/ext2/xattr.h2
-rw-r--r--fs/ext4/acl.h5
-rw-r--r--fs/ext4/balloc.c16
-rw-r--r--fs/ext4/crypto.c13
-rw-r--r--fs/ext4/ext4.h32
-rw-r--r--fs/ext4/extents.c25
-rw-r--r--fs/ext4/extents_status.c150
-rw-r--r--fs/ext4/fast_commit.c8
-rw-r--r--fs/ext4/file.c171
-rw-r--r--fs/ext4/fsmap.c9
-rw-r--r--fs/ext4/ialloc.c4
-rw-r--r--fs/ext4/inline.c4
-rw-r--r--fs/ext4/inode.c47
-rw-r--r--fs/ext4/ioctl.c13
-rw-r--r--fs/ext4/mballoc-test.c349
-rw-r--r--fs/ext4/mballoc.c575
-rw-r--r--fs/ext4/move_extent.c11
-rw-r--r--fs/ext4/namei.c13
-rw-r--r--fs/ext4/readpage.c14
-rw-r--r--fs/ext4/resize.c94
-rw-r--r--fs/ext4/super.c85
-rw-r--r--fs/ext4/xattr.c10
-rw-r--r--fs/ext4/xattr.h2
-rw-r--r--fs/f2fs/compress.c63
-rw-r--r--fs/f2fs/data.c35
-rw-r--r--fs/f2fs/dir.c6
-rw-r--r--fs/f2fs/extent_cache.c53
-rw-r--r--fs/f2fs/f2fs.h11
-rw-r--r--fs/f2fs/file.c31
-rw-r--r--fs/f2fs/inline.c2
-rw-r--r--fs/f2fs/inode.c26
-rw-r--r--fs/f2fs/namei.c4
-rw-r--r--fs/f2fs/node.c20
-rw-r--r--fs/f2fs/recovery.c8
-rw-r--r--fs/f2fs/segment.c92
-rw-r--r--fs/f2fs/segment.h4
-rw-r--r--fs/f2fs/super.c158
-rw-r--r--fs/f2fs/xattr.c24
-rw-r--r--fs/f2fs/xattr.h2
-rw-r--r--fs/fat/inode.c25
-rw-r--r--fs/fat/misc.c6
-rw-r--r--fs/fat/nfs.c1
-rw-r--r--fs/fcntl.c2
-rw-r--r--fs/fhandle.c6
-rw-r--r--fs/file.c153
-rw-r--r--fs/file_table.c51
-rw-r--r--fs/freevxfs/vxfs_inode.c6
-rw-r--r--fs/freevxfs/vxfs_super.c2
-rw-r--r--fs/fs-writeback.c41
-rw-r--r--fs/fs_context.c34
-rw-r--r--fs/fsopen.c1
-rw-r--r--fs/fuse/control.c2
-rw-r--r--fs/fuse/dax.c1
-rw-r--r--fs/fuse/dir.c10
-rw-r--r--fs/fuse/file.c8
-rw-r--r--fs/fuse/fuse_i.h21
-rw-r--r--fs/fuse/inode.c117
-rw-r--r--fs/fuse/readdir.c6
-rw-r--r--fs/fuse/xattr.c2
-rw-r--r--fs/gfs2/acl.h8
-rw-r--r--fs/gfs2/aops.c74
-rw-r--r--fs/gfs2/aops.h6
-rw-r--r--fs/gfs2/bmap.c75
-rw-r--r--fs/gfs2/bmap.h38
-rw-r--r--fs/gfs2/dir.c12
-rw-r--r--fs/gfs2/dir.h38
-rw-r--r--fs/gfs2/file.c18
-rw-r--r--fs/gfs2/glock.c31
-rw-r--r--fs/gfs2/glock.h113
-rw-r--r--fs/gfs2/glops.c24
-rw-r--r--fs/gfs2/glops.h4
-rw-r--r--fs/gfs2/incore.h2
-rw-r--r--fs/gfs2/inode.c40
-rw-r--r--fs/gfs2/inode.h60
-rw-r--r--fs/gfs2/log.h46
-rw-r--r--fs/gfs2/lops.h22
-rw-r--r--fs/gfs2/main.c6
-rw-r--r--fs/gfs2/meta_io.c61
-rw-r--r--fs/gfs2/meta_io.h20
-rw-r--r--fs/gfs2/ops_fstype.c37
-rw-r--r--fs/gfs2/quota.c95
-rw-r--r--fs/gfs2/quota.h41
-rw-r--r--fs/gfs2/recovery.h18
-rw-r--r--fs/gfs2/rgrp.c12
-rw-r--r--fs/gfs2/rgrp.h85
-rw-r--r--fs/gfs2/super.c41
-rw-r--r--fs/gfs2/super.h54
-rw-r--r--fs/gfs2/trans.h24
-rw-r--r--fs/gfs2/util.h8
-rw-r--r--fs/gfs2/xattr.c10
-rw-r--r--fs/gfs2/xattr.h12
-rw-r--r--fs/hfs/attr.c2
-rw-r--r--fs/hfs/catalog.c8
-rw-r--r--fs/hfs/hfs_fs.h2
-rw-r--r--fs/hfs/inode.c16
-rw-r--r--fs/hfs/sysdep.c10
-rw-r--r--fs/hfsplus/catalog.c8
-rw-r--r--fs/hfsplus/inode.c22
-rw-r--r--fs/hfsplus/xattr.c2
-rw-r--r--fs/hfsplus/xattr.h2
-rw-r--r--fs/hostfs/hostfs_kern.c12
-rw-r--r--fs/hpfs/dir.c12
-rw-r--r--fs/hpfs/inode.c16
-rw-r--r--fs/hpfs/namei.c22
-rw-r--r--fs/hpfs/super.c10
-rw-r--r--fs/hugetlbfs/inode.c96
-rw-r--r--fs/init.c6
-rw-r--r--fs/inode.c53
-rw-r--r--fs/internal.h22
-rw-r--r--fs/iomap/buffered-io.c67
-rw-r--r--fs/isofs/inode.c4
-rw-r--r--fs/isofs/rock.c18
-rw-r--r--fs/jbd2/commit.c10
-rw-r--r--fs/jbd2/journal.c53
-rw-r--r--fs/jbd2/recovery.c13
-rw-r--r--fs/jffs2/dir.c35
-rw-r--r--fs/jffs2/file.c4
-rw-r--r--fs/jffs2/fs.c20
-rw-r--r--fs/jffs2/os-linux.h4
-rw-r--r--fs/jffs2/super.c1
-rw-r--r--fs/jffs2/xattr.c2
-rw-r--r--fs/jffs2/xattr.h2
-rw-r--r--fs/jfs/inode.c2
-rw-r--r--fs/jfs/jfs_dinode.h2
-rw-r--r--fs/jfs/jfs_dmap.c23
-rw-r--r--fs/jfs/jfs_imap.c31
-rw-r--r--fs/jfs/jfs_incore.h2
-rw-r--r--fs/jfs/jfs_inode.c4
-rw-r--r--fs/jfs/jfs_logmgr.c33
-rw-r--r--fs/jfs/jfs_logmgr.h2
-rw-r--r--fs/jfs/jfs_mount.c3
-rw-r--r--fs/jfs/jfs_txnmgr.c4
-rw-r--r--fs/jfs/jfs_xattr.h2
-rw-r--r--fs/jfs/jfs_xtree.c4
-rw-r--r--fs/jfs/jfs_xtree.h37
-rw-r--r--fs/jfs/namei.c20
-rw-r--r--fs/jfs/super.c3
-rw-r--r--fs/jfs/xattr.c2
-rw-r--r--fs/kernfs/file.c78
-rw-r--r--fs/kernfs/inode.c8
-rw-r--r--fs/kernfs/kernfs-internal.h2
-rw-r--r--fs/kernfs/mount.c7
-rw-r--r--fs/libfs.c99
-rw-r--r--fs/lockd/svc.c7
-rw-r--r--fs/lockd/svclock.c43
-rw-r--r--fs/locks.c16
-rw-r--r--fs/mbcache.c22
-rw-r--r--fs/minix/bitmap.c2
-rw-r--r--fs/minix/dir.c6
-rw-r--r--fs/minix/inode.c17
-rw-r--r--fs/minix/itree_common.c2
-rw-r--r--fs/mnt_idmapping.c2
-rw-r--r--fs/mpage.c3
-rw-r--r--fs/namei.c40
-rw-r--r--fs/namespace.c56
-rw-r--r--fs/nfs/Kconfig2
-rw-r--r--fs/nfs/blocklayout/blocklayout.h2
-rw-r--r--fs/nfs/blocklayout/dev.c76
-rw-r--r--fs/nfs/callback.c46
-rw-r--r--fs/nfs/callback_proc.c2
-rw-r--r--fs/nfs/delegation.c7
-rw-r--r--fs/nfs/delegation.h1
-rw-r--r--fs/nfs/dir.c29
-rw-r--r--fs/nfs/filelayout/filelayout.h2
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c17
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.h2
-rw-r--r--fs/nfs/fscache.h4
-rw-r--r--fs/nfs/inode.c30
-rw-r--r--fs/nfs/nfs.h2
-rw-r--r--fs/nfs/nfs3proc.c3
-rw-r--r--fs/nfs/nfs42proc.c3
-rw-r--r--fs/nfs/nfs42xattr.c87
-rw-r--r--fs/nfs/nfs4_fs.h4
-rw-r--r--fs/nfs/nfs4proc.c66
-rw-r--r--fs/nfs/pnfs.c41
-rw-r--r--fs/nfs/pnfs.h5
-rw-r--r--fs/nfs/proc.c3
-rw-r--r--fs/nfs/super.c31
-rw-r--r--fs/nfs/write.c6
-rw-r--r--fs/nfsd/Makefile3
-rw-r--r--fs/nfsd/auth.c4
-rw-r--r--fs/nfsd/blocklayout.c3
-rw-r--r--fs/nfsd/blocklayoutxdr.c6
-rw-r--r--fs/nfsd/blocklayoutxdr.h4
-rw-r--r--fs/nfsd/cache.h4
-rw-r--r--fs/nfsd/export.c35
-rw-r--r--fs/nfsd/export.h4
-rw-r--r--fs/nfsd/filecache.c50
-rw-r--r--fs/nfsd/flexfilelayoutxdr.c6
-rw-r--r--fs/nfsd/flexfilelayoutxdr.h4
-rw-r--r--fs/nfsd/netlink.c32
-rw-r--r--fs/nfsd/netlink.h22
-rw-r--r--fs/nfsd/netns.h4
-rw-r--r--fs/nfsd/nfs3proc.c9
-rw-r--r--fs/nfsd/nfs4callback.c97
-rw-r--r--fs/nfsd/nfs4layouts.c6
-rw-r--r--fs/nfsd/nfs4proc.c40
-rw-r--r--fs/nfsd/nfs4state.c177
-rw-r--r--fs/nfsd/nfs4xdr.c2636
-rw-r--r--fs/nfsd/nfscache.c118
-rw-r--r--fs/nfsd/nfsctl.c205
-rw-r--r--fs/nfsd/nfsd.h17
-rw-r--r--fs/nfsd/nfsfh.c2
-rw-r--r--fs/nfsd/nfsfh.h3
-rw-r--r--fs/nfsd/nfssvc.c57
-rw-r--r--fs/nfsd/pnfs.h6
-rw-r--r--fs/nfsd/state.h27
-rw-r--r--fs/nfsd/stats.c4
-rw-r--r--fs/nfsd/stats.h18
-rw-r--r--fs/nfsd/trace.h87
-rw-r--r--fs/nfsd/vfs.c82
-rw-r--r--fs/nfsd/vfs.h4
-rw-r--r--fs/nfsd/xdr4.h154
-rw-r--r--fs/nfsd/xdr4cb.h18
-rw-r--r--fs/nilfs2/dir.c6
-rw-r--r--fs/nilfs2/inode.c20
-rw-r--r--fs/nilfs2/mdt.c66
-rw-r--r--fs/nilfs2/page.c76
-rw-r--r--fs/nilfs2/page.h11
-rw-r--r--fs/nilfs2/segment.c7
-rw-r--r--fs/nilfs2/sufile.c42
-rw-r--r--fs/nilfs2/the_nilfs.c6
-rw-r--r--fs/notify/dnotify/dnotify.c12
-rw-r--r--fs/notify/fanotify/fanotify.h4
-rw-r--r--fs/notify/fanotify/fanotify_user.c33
-rw-r--r--fs/notify/inotify/inotify_user.c2
-rw-r--r--fs/nsfs.c2
-rw-r--r--fs/ntfs/aops.c255
-rw-r--r--fs/ntfs/file.c89
-rw-r--r--fs/ntfs/inode.c25
-rw-r--r--fs/ntfs/mft.c2
-rw-r--r--fs/ntfs/namei.c1
-rw-r--r--fs/ntfs3/attrib.c12
-rw-r--r--fs/ntfs3/attrlist.c15
-rw-r--r--fs/ntfs3/bitmap.c4
-rw-r--r--fs/ntfs3/dir.c6
-rw-r--r--fs/ntfs3/file.c41
-rw-r--r--fs/ntfs3/frecord.c19
-rw-r--r--fs/ntfs3/fslog.c6
-rw-r--r--fs/ntfs3/fsntfs.c19
-rw-r--r--fs/ntfs3/index.c3
-rw-r--r--fs/ntfs3/inode.c24
-rw-r--r--fs/ntfs3/namei.c6
-rw-r--r--fs/ntfs3/ntfs.h2
-rw-r--r--fs/ntfs3/ntfs_fs.h6
-rw-r--r--fs/ntfs3/record.c74
-rw-r--r--fs/ntfs3/super.c105
-rw-r--r--fs/ntfs3/xattr.c9
-rw-r--r--fs/ocfs2/acl.c4
-rw-r--r--fs/ocfs2/alloc.c17
-rw-r--r--fs/ocfs2/aops.c25
-rw-r--r--fs/ocfs2/buffer_head_io.c4
-rw-r--r--fs/ocfs2/cluster/heartbeat.c81
-rw-r--r--fs/ocfs2/dir.c9
-rw-r--r--fs/ocfs2/dlmfs/dlmfs.c7
-rw-r--r--fs/ocfs2/dlmglue.c29
-rw-r--r--fs/ocfs2/file.c30
-rw-r--r--fs/ocfs2/inode.c28
-rw-r--r--fs/ocfs2/journal.c2
-rw-r--r--fs/ocfs2/move_extents.c4
-rw-r--r--fs/ocfs2/namei.c24
-rw-r--r--fs/ocfs2/quota_local.c4
-rw-r--r--fs/ocfs2/refcounttree.c12
-rw-r--r--fs/ocfs2/slot_map.c2
-rw-r--r--fs/ocfs2/xattr.c8
-rw-r--r--fs/ocfs2/xattr.h2
-rw-r--r--fs/omfs/inode.c12
-rw-r--r--fs/open.c55
-rw-r--r--fs/openpromfs/inode.c4
-rw-r--r--fs/orangefs/orangefs-kernel.h2
-rw-r--r--fs/orangefs/orangefs-utils.c16
-rw-r--r--fs/orangefs/xattr.c2
-rw-r--r--fs/overlayfs/Makefile2
-rw-r--r--fs/overlayfs/copy_up.c142
-rw-r--r--fs/overlayfs/dir.c64
-rw-r--r--fs/overlayfs/export.c7
-rw-r--r--fs/overlayfs/file.c97
-rw-r--r--fs/overlayfs/inode.c178
-rw-r--r--fs/overlayfs/namei.c52
-rw-r--r--fs/overlayfs/overlayfs.h80
-rw-r--r--fs/overlayfs/params.c416
-rw-r--r--fs/overlayfs/params.h1
-rw-r--r--fs/overlayfs/readdir.c27
-rw-r--r--fs/overlayfs/super.c118
-rw-r--r--fs/overlayfs/util.c123
-rw-r--r--fs/overlayfs/xattrs.c271
-rw-r--r--fs/pipe.c68
-rw-r--r--fs/proc/array.c7
-rw-r--r--fs/proc/base.c56
-rw-r--r--fs/proc/bootconfig.c6
-rw-r--r--fs/proc/fd.c11
-rw-r--r--fs/proc/inode.c13
-rw-r--r--fs/proc/kcore.c3
-rw-r--r--fs/proc/nommu.c2
-rw-r--r--fs/proc/proc_sysctl.c10
-rw-r--r--fs/proc/root.c2
-rw-r--r--fs/proc/self.c2
-rw-r--r--fs/proc/task_mmu.c764
-rw-r--r--fs/proc/task_nommu.c2
-rw-r--r--fs/proc/thread_self.c2
-rw-r--r--fs/pstore/inode.c5
-rw-r--r--fs/pstore/platform.c9
-rw-r--r--fs/qnx4/inode.c6
-rw-r--r--fs/qnx6/inode.c6
-rw-r--r--fs/quota/dquot.c31
-rw-r--r--fs/ramfs/inode.c7
-rw-r--r--fs/reiserfs/inode.c106
-rw-r--r--fs/reiserfs/journal.c56
-rw-r--r--fs/reiserfs/namei.c8
-rw-r--r--fs/reiserfs/procfs.c2
-rw-r--r--fs/reiserfs/reiserfs.h13
-rw-r--r--fs/reiserfs/stree.c5
-rw-r--r--fs/reiserfs/super.c2
-rw-r--r--fs/reiserfs/xattr.c4
-rw-r--r--fs/romfs/super.c5
-rw-r--r--fs/smb/client/cached_dir.c210
-rw-r--r--fs/smb/client/cached_dir.h2
-rw-r--r--fs/smb/client/cifs_debug.c33
-rw-r--r--fs/smb/client/cifs_ioctl.h6
-rw-r--r--fs/smb/client/cifs_spnego.c4
-rw-r--r--fs/smb/client/cifsfs.c175
-rw-r--r--fs/smb/client/cifsfs.h6
-rw-r--r--fs/smb/client/cifsglob.h30
-rw-r--r--fs/smb/client/cifspdu.h30
-rw-r--r--fs/smb/client/cifsproto.h28
-rw-r--r--fs/smb/client/cifssmb.c199
-rw-r--r--fs/smb/client/connect.c79
-rw-r--r--fs/smb/client/dfs.c18
-rw-r--r--fs/smb/client/export.c11
-rw-r--r--fs/smb/client/file.c18
-rw-r--r--fs/smb/client/fs_context.h1
-rw-r--r--fs/smb/client/fscache.h6
-rw-r--r--fs/smb/client/inode.c99
-rw-r--r--fs/smb/client/ioctl.c26
-rw-r--r--fs/smb/client/link.c16
-rw-r--r--fs/smb/client/namespace.c17
-rw-r--r--fs/smb/client/ntlmssp.h4
-rw-r--r--fs/smb/client/readdir.c6
-rw-r--r--fs/smb/client/sess.c276
-rw-r--r--fs/smb/client/smb1ops.c153
-rw-r--r--fs/smb/client/smb2inode.c2
-rw-r--r--fs/smb/client/smb2misc.c28
-rw-r--r--fs/smb/client/smb2ops.c294
-rw-r--r--fs/smb/client/smb2pdu.c236
-rw-r--r--fs/smb/client/smb2pdu.h16
-rw-r--r--fs/smb/client/smb2proto.h12
-rw-r--r--fs/smb/client/smb2transport.c13
-rw-r--r--fs/smb/client/transport.c13
-rw-r--r--fs/smb/client/xattr.c7
-rw-r--r--fs/smb/common/smb2pdu.h44
-rw-r--r--fs/smb/server/connection.c16
-rw-r--r--fs/smb/server/ksmbd_spnego_negtokeninit.asn18
-rw-r--r--fs/smb/server/ksmbd_spnego_negtokentarg.asn17
-rw-r--r--fs/smb/server/ksmbd_work.c51
-rw-r--r--fs/smb/server/mgmt/user_config.h1
-rw-r--r--fs/smb/server/oplock.c118
-rw-r--r--fs/smb/server/oplock.h8
-rw-r--r--fs/smb/server/smb2ops.c9
-rw-r--r--fs/smb/server/smb2pdu.c175
-rw-r--r--fs/smb/server/smb_common.c11
-rw-r--r--fs/smb/server/smbacl.c36
-rw-r--r--fs/smb/server/smbacl.h2
-rw-r--r--fs/smb/server/transport_rdma.c40
-rw-r--r--fs/smb/server/unicode.c187
-rw-r--r--fs/smb/server/vfs.c105
-rw-r--r--fs/smb/server/vfs.h10
-rw-r--r--fs/smb/server/vfs_cache.c37
-rw-r--r--fs/smb/server/vfs_cache.h9
-rw-r--r--fs/squashfs/block.c2
-rw-r--r--fs/squashfs/export.c1
-rw-r--r--fs/squashfs/inode.c6
-rw-r--r--fs/squashfs/squashfs.h2
-rw-r--r--fs/squashfs/xattr.c2
-rw-r--r--fs/stack.c4
-rw-r--r--fs/stat.c10
-rw-r--r--fs/super.c102
-rw-r--r--fs/sysfs/file.c13
-rw-r--r--fs/sysv/dir.c6
-rw-r--r--fs/sysv/ialloc.c2
-rw-r--r--fs/sysv/inode.c12
-rw-r--r--fs/sysv/itree.c2
-rw-r--r--fs/tracefs/event_inode.c1106
-rw-r--r--fs/tracefs/inode.c17
-rw-r--r--fs/tracefs/internal.h54
-rw-r--r--fs/ubifs/auth.c3
-rw-r--r--fs/ubifs/crypto.c3
-rw-r--r--fs/ubifs/debug.c12
-rw-r--r--fs/ubifs/dir.c27
-rw-r--r--fs/ubifs/file.c19
-rw-r--r--fs/ubifs/journal.c13
-rw-r--r--fs/ubifs/replay.c1
-rw-r--r--fs/ubifs/super.c34
-rw-r--r--fs/ubifs/tnc.c1
-rw-r--r--fs/ubifs/ubifs.h4
-rw-r--r--fs/ubifs/xattr.c2
-rw-r--r--fs/udf/ecma_167.h2
-rw-r--r--fs/udf/ialloc.c4
-rw-r--r--fs/udf/inode.c38
-rw-r--r--fs/udf/namei.c16
-rw-r--r--fs/udf/udf_sb.h2
-rw-r--r--fs/ufs/balloc.c20
-rw-r--r--fs/ufs/dir.c6
-rw-r--r--fs/ufs/ialloc.c2
-rw-r--r--fs/ufs/inode.c67
-rw-r--r--fs/ufs/super.c1
-rw-r--r--fs/ufs/util.c34
-rw-r--r--fs/ufs/util.h10
-rw-r--r--fs/userfaultfd.c98
-rw-r--r--fs/vboxsf/utils.c15
-rw-r--r--fs/xattr.c6
-rw-r--r--fs/xfs/Kconfig2
-rw-r--r--fs/xfs/libxfs/xfs_ag.c6
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c27
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c45
-rw-r--r--fs/xfs/libxfs/xfs_defer.c28
-rw-r--r--fs/xfs/libxfs/xfs_defer.h2
-rw-r--r--fs/xfs/libxfs/xfs_format.h34
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.c13
-rw-r--r--fs/xfs/libxfs/xfs_rtbitmap.c809
-rw-r--r--fs/xfs/libxfs/xfs_rtbitmap.h383
-rw-r--r--fs/xfs/libxfs/xfs_sb.c2
-rw-r--r--fs/xfs/libxfs/xfs_sb.h2
-rw-r--r--fs/xfs/libxfs/xfs_trans_inode.c2
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.c10
-rw-r--r--fs/xfs/libxfs/xfs_types.c4
-rw-r--r--fs/xfs/libxfs/xfs_types.h10
-rw-r--r--fs/xfs/scrub/bmap.c2
-rw-r--r--fs/xfs/scrub/fscounters.c2
-rw-r--r--fs/xfs/scrub/inode.c3
-rw-r--r--fs/xfs/scrub/rtbitmap.c28
-rw-r--r--fs/xfs/scrub/rtsummary.c72
-rw-r--r--fs/xfs/scrub/trace.c1
-rw-r--r--fs/xfs/scrub/trace.h15
-rw-r--r--fs/xfs/scrub/xfile.c1
-rw-r--r--fs/xfs/xfs_bmap_util.c81
-rw-r--r--fs/xfs/xfs_buf.c46
-rw-r--r--fs/xfs/xfs_buf.h5
-rw-r--r--fs/xfs/xfs_dquot.c5
-rw-r--r--fs/xfs/xfs_dquot_item_recover.c21
-rw-r--r--fs/xfs/xfs_extent_busy.c3
-rw-r--r--fs/xfs/xfs_file.c63
-rw-r--r--fs/xfs/xfs_fsmap.c15
-rw-r--r--fs/xfs/xfs_icache.c26
-rw-r--r--fs/xfs/xfs_inode.c28
-rw-r--r--fs/xfs/xfs_inode.h17
-rw-r--r--fs/xfs/xfs_inode_item.c7
-rw-r--r--fs/xfs/xfs_inode_item_recover.c46
-rw-r--r--fs/xfs/xfs_ioctl.c35
-rw-r--r--fs/xfs/xfs_ioctl32.h2
-rw-r--r--fs/xfs/xfs_iops.c20
-rw-r--r--fs/xfs/xfs_itable.c12
-rw-r--r--fs/xfs/xfs_linux.h12
-rw-r--r--fs/xfs/xfs_log.c23
-rw-r--r--fs/xfs/xfs_log_recover.c2
-rw-r--r--fs/xfs/xfs_mount.c4
-rw-r--r--fs/xfs/xfs_mount.h10
-rw-r--r--fs/xfs/xfs_notify_failure.c6
-rw-r--r--fs/xfs/xfs_ondisk.h4
-rw-r--r--fs/xfs/xfs_qm.c27
-rw-r--r--fs/xfs/xfs_qm.h2
-rw-r--r--fs/xfs/xfs_reflink.c5
-rw-r--r--fs/xfs/xfs_rtalloc.c650
-rw-r--r--fs/xfs/xfs_rtalloc.h94
-rw-r--r--fs/xfs/xfs_super.c45
-rw-r--r--fs/xfs/xfs_trans.c7
-rw-r--r--fs/xfs/xfs_xattr.c2
-rw-r--r--fs/xfs/xfs_xattr.h2
-rw-r--r--fs/zonefs/super.c10
-rw-r--r--include/acpi/acpi_bus.h13
-rw-r--r--include/acpi/actbl1.h3
-rw-r--r--include/acpi/ghes.h4
-rw-r--r--include/acpi/pcc.h13
-rw-r--r--include/acpi/processor.h5
-rw-r--r--include/asm-generic/Kbuild2
-rw-r--r--include/asm-generic/bitops/instrumented-lock.h28
-rw-r--r--include/asm-generic/bitops/lock.h20
-rw-r--r--include/asm-generic/fb.h12
-rw-r--r--include/asm-generic/pgalloc.h7
-rw-r--r--include/asm-generic/qspinlock.h2
-rw-r--r--include/asm-generic/spinlock.h16
-rw-r--r--include/asm-generic/vmlinux.lds.h6
-rw-r--r--include/crypto/aead.h12
-rw-r--r--include/crypto/akcipher.h4
-rw-r--r--include/crypto/algapi.h5
-rw-r--r--include/crypto/engine.h2
-rw-r--r--include/crypto/hash.h95
-rw-r--r--include/crypto/hash_info.h1
-rw-r--r--include/crypto/internal/hash.h9
-rw-r--r--include/crypto/internal/skcipher.h130
-rw-r--r--include/crypto/sig.h2
-rw-r--r--include/crypto/skcipher.h296
-rw-r--r--include/drm/amd_asic_type.h5
-rw-r--r--include/drm/bridge/dw_mipi_dsi.h16
-rw-r--r--include/drm/bridge/samsung-dsim.h6
-rw-r--r--include/drm/display/drm_dp_helper.h18
-rw-r--r--include/drm/display/drm_dp_mst_helper.h23
-rw-r--r--include/drm/drm_accel.h9
-rw-r--r--include/drm/drm_atomic.h2
-rw-r--r--include/drm/drm_atomic_helper.h2
-rw-r--r--include/drm/drm_bridge.h6
-rw-r--r--include/drm/drm_buddy.h6
-rw-r--r--include/drm/drm_client.h2
-rw-r--r--include/drm/drm_connector.h17
-rw-r--r--include/drm/drm_debugfs.h13
-rw-r--r--include/drm/drm_device.h14
-rw-r--r--include/drm/drm_drv.h8
-rw-r--r--include/drm/drm_edid.h1
-rw-r--r--include/drm/drm_file.h17
-rw-r--r--include/drm/drm_fourcc.h5
-rw-r--r--include/drm/drm_framebuffer.h5
-rw-r--r--include/drm/drm_gem.h9
-rw-r--r--include/drm/drm_gpuvm.h (renamed from include/drm/drm_gpuva_mgr.h)157
-rw-r--r--include/drm/drm_prime.h7
-rw-r--r--include/drm/gpu_scheduler.h12
-rw-r--r--include/drm/i915_pciids.h26
-rw-r--r--include/drm/i915_pxp_tee_interface.h6
-rw-r--r--include/dt-bindings/arm/qcom,ids.h5
-rw-r--r--include/dt-bindings/clock/amlogic,s4-peripherals-clkc.h236
-rw-r--r--include/dt-bindings/clock/amlogic,s4-pll-clkc.h43
-rw-r--r--include/dt-bindings/clock/imx8mp-clock.h1
-rw-r--r--include/dt-bindings/clock/qcom,mmcc-msm8974.h1
-rw-r--r--include/dt-bindings/clock/qcom,sm4450-gcc.h197
-rw-r--r--include/dt-bindings/clock/qcom,sm8550-camcc.h187
-rw-r--r--include/dt-bindings/clock/r9a08g045-cpg.h242
-rw-r--r--include/dt-bindings/gpio/amlogic,t7-periphs-pinctrl.h179
-rw-r--r--include/dt-bindings/interconnect/qcom,sdx75.h102
-rw-r--r--include/dt-bindings/power/amlogic,t7-pwrc.h63
-rw-r--r--include/dt-bindings/power/mediatek,mt8365-power.h19
-rw-r--r--include/dt-bindings/power/qcom,rpmhpd.h2
-rw-r--r--include/dt-bindings/power/qcom-rpmpd.h21
-rw-r--r--include/dt-bindings/power/starfive,jh7110-pmu.h6
-rw-r--r--include/dt-bindings/thermal/mediatek,lvts-thermal.h28
-rw-r--r--include/dt-bindings/watchdog/aspeed-wdt.h92
-rw-r--r--include/kunit/test.h14
-rw-r--r--include/kvm/arm_arch_timer.h9
-rw-r--r--include/kvm/arm_pmu.h28
-rw-r--r--include/kvm/arm_psci.h2
-rw-r--r--include/kvm/arm_vgic.h4
-rw-r--r--include/linux/acpi.h66
-rw-r--r--include/linux/aer.h2
-rw-r--r--include/linux/amd-iommu.h120
-rw-r--r--include/linux/amd-pstate.h4
-rw-r--r--include/linux/arm_ffa.h81
-rw-r--r--include/linux/array_size.h13
-rw-r--r--include/linux/atomic/atomic-arch-fallback.h15
-rw-r--r--include/linux/atomic/atomic-instrumented.h10
-rw-r--r--include/linux/avf/virtchnl.h15
-rw-r--r--include/linux/badblocks.h30
-rw-r--r--include/linux/binfmts.h10
-rw-r--r--include/linux/bitmap-str.h16
-rw-r--r--include/linux/bitmap.h87
-rw-r--r--include/linux/blk-mq.h2
-rw-r--r--include/linux/blk-pm.h1
-rw-r--r--include/linux/blk_types.h4
-rw-r--r--include/linux/blkdev.h11
-rw-r--r--include/linux/bootmem_info.h2
-rw-r--r--include/linux/bpf-cgroup-defs.h5
-rw-r--r--include/linux/bpf-cgroup.h99
-rw-r--r--include/linux/bpf.h73
-rw-r--r--include/linux/bpf_mem_alloc.h1
-rw-r--r--include/linux/bpf_verifier.h60
-rw-r--r--include/linux/brcmphy.h10
-rw-r--r--include/linux/btf.h12
-rw-r--r--include/linux/buffer_head.h81
-rw-r--r--include/linux/buildid.h3
-rw-r--r--include/linux/cacheinfo.h1
-rw-r--r--include/linux/can/dev.h4
-rw-r--r--include/linux/cdx/cdx_bus.h59
-rw-r--r--include/linux/ceph/ceph_debug.h38
-rw-r--r--include/linux/ceph/ceph_fs.h10
-rw-r--r--include/linux/ceph/mon_client.h2
-rw-r--r--include/linux/ceph/osd_client.h2
-rw-r--r--include/linux/cgroup-defs.h7
-rw-r--r--include/linux/cgroup.h12
-rw-r--r--include/linux/cleanup.h39
-rw-r--r--include/linux/clk-provider.h15
-rw-r--r--include/linux/closure.h (renamed from drivers/md/bcache/closure.h)65
-rw-r--r--include/linux/comedi/comedi_8254.h51
-rw-r--r--include/linux/comedi/comedi_8255.h24
-rw-r--r--include/linux/comedi/comedidev.h2
-rw-r--r--include/linux/compat.h1
-rw-r--r--include/linux/compiler-clang.h5
-rw-r--r--include/linux/compiler-gcc.h2
-rw-r--r--include/linux/compiler.h13
-rw-r--r--include/linux/compiler_types.h32
-rw-r--r--include/linux/console.h138
-rw-r--r--include/linux/const.h8
-rw-r--r--include/linux/cpu.h4
-rw-r--r--include/linux/cpufreq.h8
-rw-r--r--include/linux/cpuhotplug.h4
-rw-r--r--include/linux/cpumask.h113
-rw-r--r--include/linux/crash_core.h51
-rw-r--r--include/linux/crash_dump.h8
-rw-r--r--include/linux/cred.h120
-rw-r--r--include/linux/crypto.h30
-rw-r--r--include/linux/damon.h76
-rw-r--r--include/linux/dax.h10
-rw-r--r--include/linux/dcache.h1
-rw-r--r--include/linux/debugfs.h19
-rw-r--r--include/linux/device-mapper.h1
-rw-r--r--include/linux/device.h8
-rw-r--r--include/linux/dma-fence.h34
-rw-r--r--include/linux/dma-mapping.h19
-rw-r--r--include/linux/dmaengine.h2
-rw-r--r--include/linux/dpll.h170
-rw-r--r--include/linux/dsa/sja1105.h2
-rw-r--r--include/linux/efi.h7
-rw-r--r--include/linux/ethtool.h23
-rw-r--r--include/linux/export-internal.h4
-rw-r--r--include/linux/exportfs.h70
-rw-r--r--include/linux/f2fs_fs.h70
-rw-r--r--include/linux/fb.h5
-rw-r--r--include/linux/fdtable.h17
-rw-r--r--include/linux/filter.h67
-rw-r--r--include/linux/firmware/meson/meson_sm.h2
-rw-r--r--include/linux/firmware/qcom/qcom_qseecom.h52
-rw-r--r--include/linux/firmware/qcom/qcom_scm.h123
-rw-r--r--include/linux/firmware/xlnx-zynqmp.h12
-rw-r--r--include/linux/fortify-string.h6
-rw-r--r--include/linux/freelist.h129
-rw-r--r--include/linux/fs.h141
-rw-r--r--include/linux/fs_context.h2
-rw-r--r--include/linux/fs_stack.h6
-rw-r--r--include/linux/fscrypt.h82
-rw-r--r--include/linux/fsnotify.h3
-rw-r--r--include/linux/fw_table.h40
-rw-r--r--include/linux/fwnode.h2
-rw-r--r--include/linux/generic-radix-tree.h68
-rw-r--r--include/linux/gfp.h12
-rw-r--r--include/linux/gpio/consumer.h16
-rw-r--r--include/linux/gpio/driver.h44
-rw-r--r--include/linux/habanalabs/cpucp_if.h (renamed from drivers/accel/habanalabs/include/common/cpucp_if.h)36
-rw-r--r--include/linux/habanalabs/hl_boot_if.h (renamed from drivers/accel/habanalabs/include/common/hl_boot_if.h)7
-rw-r--r--include/linux/hid-sensor-ids.h4
-rw-r--r--include/linux/hid.h7
-rw-r--r--include/linux/highmem.h20
-rw-r--r--include/linux/hisi_acc_qm.h39
-rw-r--r--include/linux/hrtimer.h4
-rw-r--r--include/linux/hugetlb.h63
-rw-r--r--include/linux/hugetlb_cgroup.h11
-rw-r--r--include/linux/hw_random.h1
-rw-r--r--include/linux/i3c/device.h2
-rw-r--r--include/linux/i3c/master.h17
-rw-r--r--include/linux/idr.h6
-rw-r--r--include/linux/ieee80211.h139
-rw-r--r--include/linux/igmp.h2
-rw-r--r--include/linux/iio/iio.h12
-rw-r--r--include/linux/iio/sw_device.h3
-rw-r--r--include/linux/iio/sw_trigger.h3
-rw-r--r--include/linux/init.h3
-rw-r--r--include/linux/input.h2
-rw-r--r--include/linux/input/mt.h2
-rw-r--r--include/linux/intel_tpmi.h6
-rw-r--r--include/linux/interrupt.h2
-rw-r--r--include/linux/io-pgtable.h4
-rw-r--r--include/linux/io_uring.h19
-rw-r--r--include/linux/io_uring_types.h21
-rw-r--r--include/linux/iommu.h185
-rw-r--r--include/linux/ioport.h12
-rw-r--r--include/linux/iosys-map.h4
-rw-r--r--include/linux/iov_iter.h274
-rw-r--r--include/linux/iova_bitmap.h26
-rw-r--r--include/linux/ipv6.h50
-rw-r--r--include/linux/irq.h26
-rw-r--r--include/linux/irqdomain.h2
-rw-r--r--include/linux/iversion.h2
-rw-r--r--include/linux/jbd2.h5
-rw-r--r--include/linux/kasan.h8
-rw-r--r--include/linux/kernel.h7
-rw-r--r--include/linux/kernfs.h1
-rw-r--r--include/linux/kexec.h4
-rw-r--r--include/linux/key.h1
-rw-r--r--include/linux/kprobes.h28
-rw-r--r--include/linux/kstrtox.h5
-rw-r--r--include/linux/kthread.h1
-rw-r--r--include/linux/kvm_host.h2
-rw-r--r--include/linux/libata.h25
-rw-r--r--include/linux/linkmode.h18
-rw-r--r--include/linux/list.h8
-rw-r--r--include/linux/llist.h46
-rw-r--r--include/linux/lockd/lockd.h2
-rw-r--r--include/linux/logic_pio.h3
-rw-r--r--include/linux/lsm_hook_defs.h14
-rw-r--r--include/linux/lwq.h124
-rw-r--r--include/linux/mcb.h1
-rw-r--r--include/linux/mdio.h2
-rw-r--r--include/linux/mei_cl_bus.h12
-rw-r--r--include/linux/memblock.h9
-rw-r--r--include/linux/memcontrol.h93
-rw-r--r--include/linux/memory-tiers.h41
-rw-r--r--include/linux/mempolicy.h58
-rw-r--r--include/linux/mfd/abx500/ab8500.h6
-rw-r--r--include/linux/mfd/core.h2
-rw-r--r--include/linux/mfd/lpc_ich.h7
-rw-r--r--include/linux/mfd/mt6358/registers.h23
-rw-r--r--include/linux/mfd/stm32-timers.h11
-rw-r--r--include/linux/micrel_phy.h4
-rw-r--r--include/linux/migrate.h4
-rw-r--r--include/linux/minmax.h129
-rw-r--r--include/linux/mlx5/device.h3
-rw-r--r--include/linux/mlx5/driver.h20
-rw-r--r--include/linux/mlx5/fs.h1
-rw-r--r--include/linux/mlx5/mlx5_ifc.h148
-rw-r--r--include/linux/mlx5/mlx5_ifc_vdpa.h7
-rw-r--r--include/linux/mlx5/port.h3
-rw-r--r--include/linux/mm.h193
-rw-r--r--include/linux/mm_inline.h43
-rw-r--r--include/linux/mm_types.h93
-rw-r--r--include/linux/mmc/card.h2
-rw-r--r--include/linux/mmc/host.h1
-rw-r--r--include/linux/mmu_notifier.h9
-rw-r--r--include/linux/mmzone.h63
-rw-r--r--include/linux/mnt_idmapping.h3
-rw-r--r--include/linux/mod_devicetable.h14
-rw-r--r--include/linux/module_symbol.h2
-rw-r--r--include/linux/moduleparam.h8
-rw-r--r--include/linux/mount.h4
-rw-r--r--include/linux/msi.h6
-rw-r--r--include/linux/mtd/cfi.h2
-rw-r--r--include/linux/mtd/jedec.h3
-rw-r--r--include/linux/mtd/onfi.h1
-rw-r--r--include/linux/mtd/qinfo.h2
-rw-r--r--include/linux/mtd/rawnand.h2
-rw-r--r--include/linux/mtd/spinand.h1
-rw-r--r--include/linux/namei.h26
-rw-r--r--include/linux/netdevice.h130
-rw-r--r--include/linux/netfilter.h10
-rw-r--r--include/linux/nfs4.h262
-rw-r--r--include/linux/nfs_fs_sb.h1
-rw-r--r--include/linux/nfs_xdr.h2
-rw-r--r--include/linux/numa.h14
-rw-r--r--include/linux/nvme-auth.h7
-rw-r--r--include/linux/nvme-keyring.h28
-rw-r--r--include/linux/nvme-tcp.h6
-rw-r--r--include/linux/nvme.h12
-rw-r--r--include/linux/nvmem-consumer.h6
-rw-r--r--include/linux/nvmem-provider.h4
-rw-r--r--include/linux/objpool.h181
-rw-r--r--include/linux/objtool.h13
-rw-r--r--include/linux/oid_registry.h23
-rw-r--r--include/linux/overflow.h35
-rw-r--r--include/linux/page-flags.h19
-rw-r--r--include/linux/pagemap.h50
-rw-r--r--include/linux/parport.h2
-rw-r--r--include/linux/pci.h66
-rw-r--r--include/linux/pci_ids.h4
-rw-r--r--include/linux/pds/pds_core_if.h1
-rw-r--r--include/linux/percpu.h1
-rw-r--r--include/linux/percpu_counter.h30
-rw-r--r--include/linux/perf/arm_pmuv3.h9
-rw-r--r--include/linux/perf_event.h17
-rw-r--r--include/linux/phy.h1
-rw-r--r--include/linux/phylink.h56
-rw-r--r--include/linux/pinctrl/consumer.h61
-rw-r--r--include/linux/pinctrl/machine.h2
-rw-r--r--include/linux/pipe_fs_i.h22
-rw-r--r--include/linux/pktcdvd.h4
-rw-r--r--include/linux/platform_data/cros_ec_commands.h66
-rw-r--r--include/linux/platform_data/cros_ec_proto.h2
-rw-r--r--include/linux/platform_data/gpio-omap.h3
-rw-r--r--include/linux/platform_data/gsc_hwmon.h2
-rw-r--r--include/linux/platform_data/omap-twl4030.h3
-rw-r--r--include/linux/platform_data/pca953x.h13
-rw-r--r--include/linux/platform_data/shmob_drm.h57
-rw-r--r--include/linux/platform_data/x86/asus-wmi.h7
-rw-r--r--include/linux/pm.h45
-rw-r--r--include/linux/pm_domain.h11
-rw-r--r--include/linux/pm_opp.h40
-rw-r--r--include/linux/pnp.h8
-rw-r--r--include/linux/posix-clock.h35
-rw-r--r--include/linux/power_supply.h1
-rw-r--r--include/linux/preempt.h15
-rw-r--r--include/linux/property.h3
-rw-r--r--include/linux/pseudo_fs.h2
-rw-r--r--include/linux/pwm.h28
-rw-r--r--include/linux/raid/pq.h2
-rw-r--r--include/linux/rcu_notifier.h32
-rw-r--r--include/linux/rcupdate.h2
-rw-r--r--include/linux/rcutiny.h2
-rw-r--r--include/linux/rcutree.h17
-rw-r--r--include/linux/reboot.h3
-rw-r--r--include/linux/regulator/mt6358-regulator.h3
-rw-r--r--include/linux/resctrl.h4
-rw-r--r--include/linux/rethook.h23
-rw-r--r--include/linux/rmap.h4
-rw-r--r--include/linux/rtc.h17
-rw-r--r--include/linux/sched.h16
-rw-r--r--include/linux/sched/coredump.h19
-rw-r--r--include/linux/sched/deadline.h4
-rw-r--r--include/linux/sched/mm.h4
-rw-r--r--include/linux/sched/numa_balancing.h16
-rw-r--r--include/linux/sched/rt.h4
-rw-r--r--include/linux/sched/sd_flags.h7
-rw-r--r--include/linux/sched/signal.h39
-rw-r--r--include/linux/sched/smt.h2
-rw-r--r--include/linux/sched/topology.h10
-rw-r--r--include/linux/sched/types.h2
-rw-r--r--include/linux/sched/vhost_task.h7
-rw-r--r--include/linux/scmi_protocol.h43
-rw-r--r--include/linux/security.h20
-rw-r--r--include/linux/sed-opal-key.h26
-rw-r--r--include/linux/seq_buf.h28
-rw-r--r--include/linux/seq_file.h15
-rw-r--r--include/linux/seqlock.h52
-rw-r--r--include/linux/serial_core.h91
-rw-r--r--include/linux/shmem_fs.h16
-rw-r--r--include/linux/shrinker.h87
-rw-r--r--include/linux/skbuff.h7
-rw-r--r--include/linux/skmsg.h1
-rw-r--r--include/linux/slab.h7
-rw-r--r--include/linux/smp.h2
-rw-r--r--include/linux/soc/mediatek/infracfg.h41
-rw-r--r--include/linux/soc/mediatek/mtk_wed.h76
-rw-r--r--include/linux/soc/qcom/llcc-qcom.h2
-rw-r--r--include/linux/socket.h1
-rw-r--r--include/linux/sockptr.h23
-rw-r--r--include/linux/spi/spi.h29
-rw-r--r--include/linux/spmi.h2
-rw-r--r--include/linux/stackleak.h6
-rw-r--r--include/linux/stmmac.h3
-rw-r--r--include/linux/string.h48
-rw-r--r--include/linux/string_helpers.h4
-rw-r--r--include/linux/stringify.h2
-rw-r--r--include/linux/sunrpc/clnt.h1
-rw-r--r--include/linux/sunrpc/svc.h45
-rw-r--r--include/linux/sunrpc/svc_xprt.h2
-rw-r--r--include/linux/sunrpc/xprt.h3
-rw-r--r--include/linux/superhyway.h107
-rw-r--r--include/linux/surface_aggregator/controller.h2
-rw-r--r--include/linux/swap.h1
-rw-r--r--include/linux/syscalls.h11
-rw-r--r--include/linux/sysctl.h6
-rw-r--r--include/linux/sysfs.h2
-rw-r--r--include/linux/tcp.h57
-rw-r--r--include/linux/thermal.h20
-rw-r--r--include/linux/thunderbolt.h2
-rw-r--r--include/linux/tick.h10
-rw-r--r--include/linux/timer.h3
-rw-r--r--include/linux/topology.h2
-rw-r--r--include/linux/torture.h8
-rw-r--r--include/linux/trace_events.h12
-rw-r--r--include/linux/trace_seq.h2
-rw-r--r--include/linux/tracefs.h73
-rw-r--r--include/linux/tsm.h69
-rw-r--r--include/linux/tty.h25
-rw-r--r--include/linux/ucs2_string.h1
-rw-r--r--include/linux/udp.h66
-rw-r--r--include/linux/uio.h34
-rw-r--r--include/linux/units.h5
-rw-r--r--include/linux/usb.h16
-rw-r--r--include/linux/usb/chipidea.h1
-rw-r--r--include/linux/usb/composite.h8
-rw-r--r--include/linux/usb/gadget.h9
-rw-r--r--include/linux/usb/hcd.h17
-rw-r--r--include/linux/usb/ljca.h145
-rw-r--r--include/linux/usb/pd.h1
-rw-r--r--include/linux/usb/pd_vdo.h1
-rw-r--r--include/linux/usb/phy.h13
-rw-r--r--include/linux/usb/r8152.h1
-rw-r--r--include/linux/usb/renesas_usbhs.h10
-rw-r--r--include/linux/usb/typec.h37
-rw-r--r--include/linux/usb/typec_dp.h28
-rw-r--r--include/linux/usb/typec_tbt.h1
-rw-r--r--include/linux/user_namespace.h8
-rw-r--r--include/linux/userfaultfd_k.h28
-rw-r--r--include/linux/vdpa.h41
-rw-r--r--include/linux/verification.h1
-rw-r--r--include/linux/vfio.h8
-rw-r--r--include/linux/virtio_net.h19
-rw-r--r--include/linux/virtio_pci_modern.h42
-rw-r--r--include/linux/virtio_vsock.h10
-rw-r--r--include/linux/vlynq.h149
-rw-r--r--include/linux/wait.h9
-rw-r--r--include/linux/watch_queue.h2
-rw-r--r--include/linux/workqueue.h46
-rw-r--r--include/media/cec.h2
-rw-r--r--include/media/ipu-bridge.h2
-rw-r--r--include/media/mipi-csi2.h1
-rw-r--r--include/media/v4l2-dev.h2
-rw-r--r--include/media/v4l2-device.h4
-rw-r--r--include/media/v4l2-event.h2
-rw-r--r--include/media/v4l2-mc.h6
-rw-r--r--include/media/v4l2-subdev.h13
-rw-r--r--include/media/videobuf-core.h233
-rw-r--r--include/media/videobuf-dma-contig.h30
-rw-r--r--include/media/videobuf-dma-sg.h102
-rw-r--r--include/media/videobuf-vmalloc.h43
-rw-r--r--include/net/Space.h1
-rw-r--r--include/net/addrconf.h12
-rw-r--r--include/net/af_unix.h1
-rw-r--r--include/net/af_vsock.h7
-rw-r--r--include/net/bluetooth/bluetooth.h2
-rw-r--r--include/net/bluetooth/hci.h3
-rw-r--r--include/net/bluetooth/hci_core.h40
-rw-r--r--include/net/bluetooth/hci_mon.h2
-rw-r--r--include/net/bluetooth/hci_sync.h2
-rw-r--r--include/net/cfg80211.h303
-rw-r--r--include/net/devlink.h69
-rw-r--r--include/net/dropreason-core.h33
-rw-r--r--include/net/dsa.h69
-rw-r--r--include/net/dsa_stubs.h22
-rw-r--r--include/net/dst.h11
-rw-r--r--include/net/flow.h2
-rw-r--r--include/net/flow_offload.h2
-rw-r--r--include/net/genetlink.h2
-rw-r--r--include/net/gro.h2
-rw-r--r--include/net/ieee80211_radiotap.h6
-rw-r--r--include/net/if_inet6.h6
-rw-r--r--include/net/inet_connection_sock.h22
-rw-r--r--include/net/inet_sock.h11
-rw-r--r--include/net/inet_timewait_sock.h3
-rw-r--r--include/net/ip.h15
-rw-r--r--include/net/ip6_route.h19
-rw-r--r--include/net/ip_fib.h2
-rw-r--r--include/net/ipv6.h42
-rw-r--r--include/net/ipv6_stubs.h8
-rw-r--r--include/net/mac80211.h134
-rw-r--r--include/net/macsec.h1
-rw-r--r--include/net/mana/hw_channel.h2
-rw-r--r--include/net/mana/mana.h2
-rw-r--r--include/net/neighbour.h2
-rw-r--r--include/net/net_namespace.h15
-rw-r--r--include/net/netfilter/nf_conntrack.h14
-rw-r--r--include/net/netfilter/nf_conntrack_act_ct.h30
-rw-r--r--include/net/netfilter/nf_conntrack_labels.h2
-rw-r--r--include/net/netfilter/nf_flow_table.h11
-rw-r--r--include/net/netfilter/nf_tables.h71
-rw-r--r--include/net/netkit.h44
-rw-r--r--include/net/netlink.h73
-rw-r--r--include/net/netns/conntrack.h2
-rw-r--r--include/net/netns/ipv4.h3
-rw-r--r--include/net/netns/xfrm.h1
-rw-r--r--include/net/nexthop.h8
-rw-r--r--include/net/page_pool/helpers.h230
-rw-r--r--include/net/page_pool/types.h6
-rw-r--r--include/net/pkt_cls.h6
-rw-r--r--include/net/pkt_sched.h8
-rw-r--r--include/net/regulatory.h1
-rw-r--r--include/net/route.h10
-rw-r--r--include/net/sch_generic.h4
-rw-r--r--include/net/sock.h57
-rw-r--r--include/net/tc_act/tc_ct.h10
-rw-r--r--include/net/tcp.h383
-rw-r--r--include/net/tcp_ao.h369
-rw-r--r--include/net/tcx.h7
-rw-r--r--include/net/tls.h21
-rw-r--r--include/net/udp_tunnel.h30
-rw-r--r--include/net/udplite.h14
-rw-r--r--include/net/xdp.h19
-rw-r--r--include/net/xdp_sock.h18
-rw-r--r--include/net/xfrm.h20
-rw-r--r--include/rdma/ib_mad.h2
-rw-r--r--include/rdma/ib_umem.h9
-rw-r--r--include/rdma/ib_verbs.h9
-rw-r--r--include/scsi/libsas.h17
-rw-r--r--include/scsi/scsi_device.h27
-rw-r--r--include/scsi/scsi_host.h3
-rw-r--r--include/soc/fsl/qe/qe.h2
-rw-r--r--include/soc/rockchip/rk3399_grf.h9
-rw-r--r--include/soc/rockchip/rk3568_grf.h13
-rw-r--r--include/soc/rockchip/rk3588_grf.h18
-rw-r--r--include/soc/rockchip/rockchip_grf.h18
-rw-r--r--include/soc/tegra/bpmp-abi.h2
-rw-r--r--include/soc/tegra/bpmp.h6
-rw-r--r--include/soc/tegra/mc.h26
-rw-r--r--include/sound/cs35l41.h7
-rw-r--r--include/sound/cs35l56.h3
-rw-r--r--include/sound/graph_card.h16
-rw-r--r--include/sound/hda_register.h2
-rw-r--r--include/sound/hdaudio.h5
-rw-r--r--include/sound/hdaudio_ext.h3
-rw-r--r--include/sound/max9768.h4
-rw-r--r--include/sound/opl3.h2
-rw-r--r--include/sound/simple_card.h6
-rw-r--r--include/sound/simple_card_utils.h106
-rw-r--r--include/sound/soc-acpi-intel-match.h2
-rw-r--r--include/sound/soc-acpi.h7
-rw-r--r--include/sound/soc-card.h41
-rw-r--r--include/sound/soc-dai.h1
-rw-r--r--include/sound/soc-dapm.h3
-rw-r--r--include/sound/soc.h47
-rw-r--r--include/sound/sof.h12
-rw-r--r--include/sound/sof/ipc4/header.h32
-rw-r--r--include/sound/tas2781-dsp.h5
-rw-r--r--include/sound/wavefront.h53
-rw-r--r--include/target/target_core_base.h10
-rw-r--r--include/target/target_core_fabric.h19
-rw-r--r--include/trace/events/csd.h8
-rw-r--r--include/trace/events/damon.h45
-rw-r--r--include/trace/events/habanalabs.h45
-rw-r--r--include/trace/events/intel_ifs.h16
-rw-r--r--include/trace/events/migrate.h24
-rw-r--r--include/trace/events/mmflags.h2
-rw-r--r--include/trace/events/mptcp.h2
-rw-r--r--include/trace/events/neigh.h4
-rw-r--r--include/trace/events/rpcrdma.h10
-rw-r--r--include/trace/events/rxrpc.h2
-rw-r--r--include/trace/events/sched.h57
-rw-r--r--include/trace/events/sunrpc.h1
-rw-r--r--include/trace/events/ufs.h15
-rw-r--r--include/trace/events/vmscan.h8
-rw-r--r--include/trace/events/vsock_virtio_transport_common.h12
-rw-r--r--include/uapi/asm-generic/siginfo.h5
-rw-r--r--include/uapi/asm-generic/unistd.h14
-rw-r--r--include/uapi/drm/amdgpu_drm.h36
-rw-r--r--include/uapi/drm/drm.h20
-rw-r--r--include/uapi/drm/drm_fourcc.h2
-rw-r--r--include/uapi/drm/drm_mode.h16
-rw-r--r--include/uapi/drm/habanalabs_accel.h68
-rw-r--r--include/uapi/drm/i915_drm.h8
-rw-r--r--include/uapi/drm/ivpu_accel.h18
-rw-r--r--include/uapi/drm/nouveau_drm.h4
-rw-r--r--include/uapi/drm/qaic_accel.h24
-rw-r--r--include/uapi/linux/bpf.h52
-rw-r--r--include/uapi/linux/counter.h2
-rw-r--r--include/uapi/linux/devlink.h3
-rw-r--r--include/uapi/linux/dpll.h207
-rw-r--r--include/uapi/linux/elf.h2
-rw-r--r--include/uapi/linux/fcntl.h3
-rw-r--r--include/uapi/linux/fs.h59
-rw-r--r--include/uapi/linux/fscrypt.h3
-rw-r--r--include/uapi/linux/fuse.h10
-rw-r--r--include/uapi/linux/futex.h31
-rw-r--r--include/uapi/linux/gsmmux.h1
-rw-r--r--include/uapi/linux/gtp.h2
-rw-r--r--include/uapi/linux/hash_info.h3
-rw-r--r--include/uapi/linux/idxd.h1
-rw-r--r--include/uapi/linux/if_bridge.h18
-rw-r--r--include/uapi/linux/if_link.h32
-rw-r--r--include/uapi/linux/if_packet.h6
-rw-r--r--include/uapi/linux/iio/types.h4
-rw-r--r--include/uapi/linux/io_uring.h20
-rw-r--r--include/uapi/linux/iommufd.h180
-rw-r--r--include/uapi/linux/kfd_ioctl.h3
-rw-r--r--include/uapi/linux/kvm.h11
-rw-r--r--include/uapi/linux/landlock.h55
-rw-r--r--include/uapi/linux/media-bus-format.h3
-rw-r--r--include/uapi/linux/mei.h14
-rw-r--r--include/uapi/linux/mempolicy.h2
-rw-r--r--include/uapi/linux/mptcp.h172
-rw-r--r--include/uapi/linux/mptcp_pm.h150
-rw-r--r--include/uapi/linux/netdev.h16
-rw-r--r--include/uapi/linux/netlink.h5
-rw-r--r--include/uapi/linux/nfsd_netlink.h39
-rw-r--r--include/uapi/linux/nl80211.h43
-rw-r--r--include/uapi/linux/npcm-video.h41
-rw-r--r--include/uapi/linux/pci_regs.h24
-rw-r--r--include/uapi/linux/pkt_sched.h15
-rw-r--r--include/uapi/linux/prctl.h3
-rw-r--r--include/uapi/linux/psp-sev.h1
-rw-r--r--include/uapi/linux/ptp_clock.h2
-rw-r--r--include/uapi/linux/rtnetlink.h18
-rw-r--r--include/uapi/linux/sched/types.h4
-rw-r--r--include/uapi/linux/serial_core.h21
-rw-r--r--include/uapi/linux/serial_reg.h1
-rw-r--r--include/uapi/linux/sev-guest.h4
-rw-r--r--include/uapi/linux/snmp.h8
-rw-r--r--include/uapi/linux/stddef.h2
-rw-r--r--include/uapi/linux/tcp.h118
-rw-r--r--include/uapi/linux/usb/raw_gadget.h14
-rw-r--r--include/uapi/linux/user_events.h11
-rw-r--r--include/uapi/linux/userfaultfd.h9
-rw-r--r--include/uapi/linux/v4l2-controls.h6
-rw-r--r--include/uapi/linux/v4l2-subdev.h2
-rw-r--r--include/uapi/linux/vfio.h47
-rw-r--r--include/uapi/linux/vhost.h8
-rw-r--r--include/uapi/linux/vhost_types.h7
-rw-r--r--include/uapi/linux/videodev2.h1
-rw-r--r--include/uapi/linux/virtio_config.h5
-rw-r--r--include/uapi/linux/virtio_pci.h11
-rw-r--r--include/uapi/linux/vm_sockets.h17
-rw-r--r--include/uapi/linux/xfrm.h3
-rw-r--r--include/uapi/mtd/ubi-user.h4
-rw-r--r--include/uapi/rdma/hns-abi.h12
-rw-r--r--include/uapi/rdma/ib_user_ioctl_verbs.h3
-rw-r--r--include/uapi/rdma/rdma_netlink.h4
-rw-r--r--include/uapi/rdma/siw-abi.h2
-rw-r--r--include/uapi/sound/asequencer.h4
-rw-r--r--include/uapi/xen/privcmd.h22
-rw-r--r--include/ufs/ufs.h3
-rw-r--r--include/ufs/ufshcd.h14
-rw-r--r--include/video/mmp_disp.h2
-rw-r--r--include/video/sticore.h2
-rw-r--r--include/video/uvesafb.h2
-rw-r--r--include/xen/events.h8
-rw-r--r--include/xen/interface/hvm/ioreq.h51
-rw-r--r--init/Kconfig2
-rw-r--r--init/Makefile1
-rw-r--r--init/do_mounts.c2
-rw-r--r--init/init_task.c2
-rw-r--r--init/main.c4
-rw-r--r--init/version.c6
-rw-r--r--io_uring/Makefile4
-rw-r--r--io_uring/cancel.c21
-rw-r--r--io_uring/cancel.h4
-rw-r--r--io_uring/fdinfo.c13
-rw-r--r--io_uring/fs.c2
-rw-r--r--io_uring/futex.c386
-rw-r--r--io_uring/futex.h36
-rw-r--r--io_uring/io_uring.c160
-rw-r--r--io_uring/io_uring.h4
-rw-r--r--io_uring/kbuf.c241
-rw-r--r--io_uring/kbuf.h18
-rw-r--r--io_uring/net.c24
-rw-r--r--io_uring/opdef.c66
-rw-r--r--io_uring/opdef.h2
-rw-r--r--io_uring/openclose.c9
-rw-r--r--io_uring/poll.c20
-rw-r--r--io_uring/rsrc.c39
-rw-r--r--io_uring/rsrc.h7
-rw-r--r--io_uring/rw.c173
-rw-r--r--io_uring/rw.h4
-rw-r--r--io_uring/sqpoll.c12
-rw-r--r--io_uring/uring_cmd.c104
-rw-r--r--io_uring/waitid.c372
-rw-r--r--io_uring/waitid.h15
-rw-r--r--ipc/mqueue.c19
-rw-r--r--ipc/shm.c21
-rw-r--r--kernel/Kconfig.kexec4
-rw-r--r--kernel/acct.c4
-rw-r--r--kernel/audit_tree.c6
-rw-r--r--kernel/audit_watch.c9
-rw-r--r--kernel/auditsc.c8
-rw-r--r--kernel/bpf/arraymap.c58
-rw-r--r--kernel/bpf/bpf_iter.c8
-rw-r--r--kernel/bpf/bpf_struct_ops.c26
-rw-r--r--kernel/bpf/btf.c35
-rw-r--r--kernel/bpf/cgroup.c53
-rw-r--r--kernel/bpf/cgroup_iter.c65
-rw-r--r--kernel/bpf/core.c41
-rw-r--r--kernel/bpf/cpumap.c10
-rw-r--r--kernel/bpf/cpumask.c6
-rw-r--r--kernel/bpf/devmap.c10
-rw-r--r--kernel/bpf/hashtab.c7
-rw-r--r--kernel/bpf/helpers.c142
-rw-r--r--kernel/bpf/inode.c5
-rw-r--r--kernel/bpf/map_iter.c6
-rw-r--r--kernel/bpf/memalloc.c74
-rw-r--r--kernel/bpf/mprog.c10
-rw-r--r--kernel/bpf/offload.c18
-rw-r--r--kernel/bpf/ringbuf.c3
-rw-r--r--kernel/bpf/stackmap.c2
-rw-r--r--kernel/bpf/syscall.c92
-rw-r--r--kernel/bpf/task_iter.c286
-rw-r--r--kernel/bpf/tcx.c12
-rw-r--r--kernel/bpf/trampoline.c4
-rw-r--r--kernel/bpf/verifier.c1799
-rw-r--r--kernel/cgroup/cgroup-v1.c5
-rw-r--r--kernel/cgroup/cgroup.c75
-rw-r--r--kernel/cgroup/cpuset.c1306
-rw-r--r--kernel/cgroup/legacy_freezer.c8
-rw-r--r--kernel/cgroup/rstat.c9
-rw-r--r--kernel/configs/hardening.config98
-rw-r--r--kernel/cpu.c53
-rw-r--r--kernel/crash_core.c190
-rw-r--r--kernel/cred.c271
-rw-r--r--kernel/debug/debug_core.c3
-rw-r--r--kernel/debug/kdb/kdb_main.c7
-rw-r--r--kernel/dma/Kconfig11
-rw-r--r--kernel/dma/debug.c2
-rw-r--r--kernel/dma/direct.c77
-rw-r--r--kernel/dma/direct.h1
-rw-r--r--kernel/dma/mapping.c22
-rw-r--r--kernel/dma/swiotlb.c45
-rw-r--r--kernel/events/core.c255
-rw-r--r--kernel/events/ring_buffer.c6
-rw-r--r--kernel/events/uprobes.c4
-rw-r--r--kernel/exit.c139
-rw-r--r--kernel/exit.h30
-rw-r--r--kernel/fork.c32
-rw-r--r--kernel/freezer.c41
-rw-r--r--kernel/futex/core.c95
-rw-r--r--kernel/futex/futex.h106
-rw-r--r--kernel/futex/pi.c91
-rw-r--r--kernel/futex/requeue.c25
-rw-r--r--kernel/futex/syscalls.c235
-rw-r--r--kernel/futex/waitwake.c129
-rw-r--r--kernel/gcov/fs.c2
-rw-r--r--kernel/groups.c2
-rw-r--r--kernel/irq/debugfs.c1
-rw-r--r--kernel/irq/generic-chip.c31
-rw-r--r--kernel/irq/manage.c15
-rw-r--r--kernel/irq/matrix.c6
-rw-r--r--kernel/irq/msi.c12
-rw-r--r--kernel/kcmp.c4
-rw-r--r--kernel/kcsan/kcsan_test.c9
-rw-r--r--kernel/kcsan/selftest.c9
-rw-r--r--kernel/kexec.c2
-rw-r--r--kernel/kexec_core.c17
-rw-r--r--kernel/kprobes.c93
-rw-r--r--kernel/kthread.c19
-rw-r--r--kernel/livepatch/core.c2
-rw-r--r--kernel/locking/lock_events.c10
-rw-r--r--kernel/locking/lockdep.c3
-rw-r--r--kernel/locking/lockdep_proc.c2
-rw-r--r--kernel/locking/locktorture.c214
-rw-r--r--kernel/locking/mutex.c3
-rw-r--r--kernel/locking/rtmutex.c37
-rw-r--r--kernel/locking/rwbase_rt.c8
-rw-r--r--kernel/locking/rwsem.c8
-rw-r--r--kernel/locking/spinlock_rt.c6
-rw-r--r--kernel/locking/test-ww_mutex.c48
-rw-r--r--kernel/locking/ww_rt_mutex.c2
-rw-r--r--kernel/module/Kconfig25
-rw-r--r--kernel/module/decompress.c8
-rw-r--r--kernel/module/stats.c2
-rw-r--r--kernel/module/sysfs.c2
-rw-r--r--kernel/padata.c8
-rw-r--r--kernel/panic.c22
-rw-r--r--kernel/pid_namespace.c6
-rw-r--r--kernel/power/hibernate.c14
-rw-r--r--kernel/power/power.h2
-rw-r--r--kernel/power/snapshot.c16
-rw-r--r--kernel/power/swap.c41
-rw-r--r--kernel/printk/Makefile2
-rw-r--r--kernel/printk/internal.h31
-rw-r--r--kernel/printk/nbcon.c1029
-rw-r--r--kernel/printk/printk.c162
-rw-r--r--kernel/ptrace.c2
-rw-r--r--kernel/rcu/rcu.h19
-rw-r--r--kernel/rcu/rcu_segcblist.c4
-rw-r--r--kernel/rcu/rcutorture.c37
-rw-r--r--kernel/rcu/refscale.c6
-rw-r--r--kernel/rcu/srcutiny.c1
-rw-r--r--kernel/rcu/srcutree.c74
-rw-r--r--kernel/rcu/tasks.h43
-rw-r--r--kernel/rcu/tiny.c1
-rw-r--r--kernel/rcu/tree.c306
-rw-r--r--kernel/rcu/tree.h4
-rw-r--r--kernel/rcu/tree_exp.h6
-rw-r--r--kernel/rcu/tree_nocb.h19
-rw-r--r--kernel/rcu/tree_stall.h135
-rw-r--r--kernel/rcu/update.c9
-rw-r--r--kernel/reboot.c4
-rw-r--r--kernel/resource.c55
-rw-r--r--kernel/sched/build_utility.c1
-rw-r--r--kernel/sched/core.c738
-rw-r--r--kernel/sched/cpudeadline.c2
-rw-r--r--kernel/sched/cpufreq_schedutil.c66
-rw-r--r--kernel/sched/deadline.c73
-rw-r--r--kernel/sched/debug.c7
-rw-r--r--kernel/sched/fair.c675
-rw-r--r--kernel/sched/features.h1
-rw-r--r--kernel/sched/idle.c4
-rw-r--r--kernel/sched/pelt.c2
-rw-r--r--kernel/sched/psi.c58
-rw-r--r--kernel/sched/rt.c95
-rw-r--r--kernel/sched/sched.h45
-rw-r--r--kernel/sched/stop_task.c4
-rw-r--r--kernel/sched/topology.c215
-rw-r--r--kernel/sched/wait.c60
-rw-r--r--kernel/signal.c82
-rw-r--r--kernel/smp.c39
-rw-r--r--kernel/smpboot.c3
-rw-r--r--kernel/stacktrace.c2
-rw-r--r--kernel/sys.c77
-rw-r--r--kernel/sys_ni.c5
-rw-r--r--kernel/sysctl.c11
-rw-r--r--kernel/taskstats.c5
-rw-r--r--kernel/time/alarmtimer.c11
-rw-r--r--kernel/time/hrtimer.c33
-rw-r--r--kernel/time/posix-clock.c36
-rw-r--r--kernel/time/tick-sched.c222
-rw-r--r--kernel/torture.c75
-rw-r--r--kernel/trace/bpf_trace.c16
-rw-r--r--kernel/trace/fprobe.c36
-rw-r--r--kernel/trace/rethook.c113
-rw-r--r--kernel/trace/ring_buffer.c136
-rw-r--r--kernel/trace/trace.c260
-rw-r--r--kernel/trace/trace.h17
-rw-r--r--kernel/trace/trace_eprobe.c5
-rw-r--r--kernel/trace/trace_events.c362
-rw-r--r--kernel/trace/trace_events_filter.c3
-rw-r--r--kernel/trace/trace_events_hist.c23
-rw-r--r--kernel/trace/trace_events_synth.c2
-rw-r--r--kernel/trace/trace_events_user.c36
-rw-r--r--kernel/trace/trace_fprobe.c9
-rw-r--r--kernel/trace/trace_kprobe.c99
-rw-r--r--kernel/trace/trace_output.c8
-rw-r--r--kernel/trace/trace_probe.h1
-rw-r--r--kernel/trace/trace_seq.c6
-rw-r--r--kernel/trace/trace_syscalls.c4
-rw-r--r--kernel/up.c2
-rw-r--r--kernel/user.c13
-rw-r--r--kernel/user_namespace.c5
-rw-r--r--kernel/watch_queue.c2
-rw-r--r--kernel/watchdog.c7
-rw-r--r--kernel/workqueue.c82
-rw-r--r--lib/Kconfig11
-rw-r--r--lib/Kconfig.debug37
-rw-r--r--lib/Makefile12
-rw-r--r--lib/bitmap-str.c510
-rw-r--r--lib/bitmap.c680
-rw-r--r--lib/closure.c (renamed from drivers/md/bcache/closure.c)50
-rw-r--r--lib/cpumask.c21
-rw-r--r--lib/debugobjects.c2
-rw-r--r--lib/decompress_unxz.c3
-rw-r--r--lib/errname.c7
-rw-r--r--lib/fonts/Kconfig2
-rw-r--r--lib/fw_table.c188
-rw-r--r--lib/generic-radix-tree.c76
-rw-r--r--lib/group_cpus.c22
-rw-r--r--lib/iov_iter.c437
-rw-r--r--lib/kobject_uevent.c8
-rw-r--r--lib/kunit/assert.c14
-rw-r--r--lib/kunit/debugfs.c36
-rw-r--r--lib/kunit/executor.c23
-rw-r--r--lib/kunit/executor_test.c36
-rw-r--r--lib/kunit/kunit-example-test.c5
-rw-r--r--lib/kunit/kunit-test.c56
-rw-r--r--lib/kunit/string-stream-test.c525
-rw-r--r--lib/kunit/string-stream.c100
-rw-r--r--lib/kunit/string-stream.h16
-rw-r--r--lib/kunit/test.c98
-rw-r--r--lib/llist.c28
-rw-r--r--lib/lwq.c158
-rw-r--r--lib/maple_tree.c2
-rw-r--r--lib/nlattr.c22
-rw-r--r--lib/objpool.c297
-rw-r--r--lib/percpu_counter.c79
-rw-r--r--lib/raid6/Makefile4
-rw-r--r--lib/raid6/algos.c4
-rw-r--r--lib/raid6/int.uc9
-rw-r--r--lib/rcuref.c2
-rw-r--r--lib/seq_buf.c28
-rw-r--r--lib/string_helpers.c10
-rw-r--r--lib/test_bitmap.c24
-rw-r--r--lib/test_bpf.c371
-rw-r--r--lib/test_maple_tree.c35
-rw-r--r--lib/test_objpool.c690
-rw-r--r--lib/ucs2_string.c52
-rw-r--r--lib/vsprintf.c25
-rw-r--r--lib/xz/Kconfig5
-rw-r--r--lib/zstd/common/fse_decompress.c2
-rw-r--r--mm/Kconfig28
-rw-r--r--mm/Makefile4
-rw-r--r--mm/bootmem_info.c2
-rw-r--r--mm/cma.c2
-rw-r--r--mm/compaction.c91
-rw-r--r--mm/damon/Kconfig12
-rw-r--r--mm/damon/core-test.h29
-rw-r--r--mm/damon/core.c307
-rw-r--r--mm/damon/dbgfs.c3
-rw-r--r--mm/damon/lru_sort.c6
-rw-r--r--mm/damon/ops-common.c5
-rw-r--r--mm/damon/paddr.c11
-rw-r--r--mm/damon/reclaim.c2
-rw-r--r--mm/damon/sysfs-common.h2
-rw-r--r--mm/damon/sysfs-schemes.c175
-rw-r--r--mm/damon/sysfs-test.h86
-rw-r--r--mm/damon/sysfs.c132
-rw-r--r--mm/damon/vaddr.c22
-rw-r--r--mm/debug_vm_pgtable.c4
-rw-r--r--mm/filemap.c219
-rw-r--r--mm/gup.c16
-rw-r--r--mm/huge_memory.c150
-rw-r--r--mm/hugetlb.c714
-rw-r--r--mm/hugetlb_cgroup.c20
-rw-r--r--mm/hugetlb_vmemmap.c301
-rw-r--r--mm/hugetlb_vmemmap.h31
-rw-r--r--mm/internal.h147
-rw-r--r--mm/kasan/kasan.h1
-rw-r--r--mm/kasan/kasan_test.c19
-rw-r--r--mm/kasan/kasan_test_module.c2
-rw-r--r--mm/kasan/quarantine.c4
-rw-r--r--mm/kasan/report.c6
-rw-r--r--mm/kasan/report_generic.c6
-rw-r--r--mm/kasan/shadow.c2
-rw-r--r--mm/khugepaged.c139
-rw-r--r--mm/kmemleak.c158
-rw-r--r--mm/kmsan/core.c127
-rw-r--r--mm/kmsan/kmsan_test.c109
-rw-r--r--mm/kmsan/shadow.c9
-rw-r--r--mm/ksm.c118
-rw-r--r--mm/madvise.c44
-rw-r--r--mm/memblock.c51
-rw-r--r--mm/memcontrol.c404
-rw-r--r--mm/memfd.c6
-rw-r--r--mm/memory-failure.c29
-rw-r--r--mm/memory-tiers.c175
-rw-r--r--mm/memory.c316
-rw-r--r--mm/memory_hotplug.c23
-rw-r--r--mm/mempolicy.c1048
-rw-r--r--mm/migrate.c239
-rw-r--r--mm/mlock.c95
-rw-r--r--mm/mm_init.c4
-rw-r--r--mm/mmap.c207
-rw-r--r--mm/mmzone.c6
-rw-r--r--mm/mprotect.c58
-rw-r--r--mm/mremap.c107
-rw-r--r--mm/nommu.c13
-rw-r--r--mm/oom_kill.c16
-rw-r--r--mm/page-writeback.c39
-rw-r--r--mm/page_alloc.c343
-rw-r--r--mm/page_io.c8
-rw-r--r--mm/page_owner.c4
-rw-r--r--mm/percpu.c43
-rw-r--r--mm/readahead.c3
-rw-r--r--mm/rmap.c164
-rw-r--r--mm/shmem.c637
-rw-r--r--mm/show_mem.c11
-rw-r--r--mm/shrinker.c809
-rw-r--r--mm/shrinker_debug.c35
-rw-r--r--mm/slab.h15
-rw-r--r--mm/slab_common.c48
-rw-r--r--mm/slub.c73
-rw-r--r--mm/swap.h9
-rw-r--r--mm/swap_state.c92
-rw-r--r--mm/swapfile.c23
-rw-r--r--mm/userfaultfd.c2
-rw-r--r--mm/util.c15
-rw-r--r--mm/vmalloc.c2
-rw-r--r--mm/vmscan.c826
-rw-r--r--mm/vmstat.c30
-rw-r--r--mm/workingset.c35
-rw-r--r--mm/zsmalloc.c29
-rw-r--r--mm/zswap.c19
-rw-r--r--net/802/fddi.c1
-rw-r--r--net/802/garp.c1
-rw-r--r--net/802/mrp.c1
-rw-r--r--net/802/p8022.c1
-rw-r--r--net/802/psnap.c1
-rw-r--r--net/802/stp.c1
-rw-r--r--net/8021q/vlan.c1
-rw-r--r--net/9p/client.c8
-rw-r--r--net/9p/trans_fd.c21
-rw-r--r--net/9p/trans_xen.c15
-rw-r--r--net/Kconfig11
-rw-r--r--net/appletalk/Kconfig30
-rw-r--r--net/appletalk/aarp.c2
-rw-r--r--net/appletalk/ddp.c45
-rw-r--r--net/atm/atm_sysfs.c2
-rw-r--r--net/atm/ioctl.c7
-rw-r--r--net/ax25/af_ax25.c2
-rw-r--r--net/bluetooth/amp.c3
-rw-r--r--net/bluetooth/hci_conn.c132
-rw-r--r--net/bluetooth/hci_core.c3
-rw-r--r--net/bluetooth/hci_event.c140
-rw-r--r--net/bluetooth/hci_sock.c3
-rw-r--r--net/bluetooth/hci_sync.c62
-rw-r--r--net/bluetooth/hci_sysfs.c23
-rw-r--r--net/bluetooth/iso.c38
-rw-r--r--net/bluetooth/l2cap_sock.c2
-rw-r--r--net/bluetooth/msft.c20
-rw-r--r--net/bluetooth/smp.c3
-rw-r--r--net/bpf/test_run.c7
-rw-r--r--net/bridge/br.c1
-rw-r--r--net/bridge/br_device.c3
-rw-r--r--net/bridge/br_fdb.c71
-rw-r--r--net/bridge/br_input.c2
-rw-r--r--net/bridge/br_mdb.c184
-rw-r--r--net/bridge/br_multicast.c5
-rw-r--r--net/bridge/br_netfilter_hooks.c98
-rw-r--r--net/bridge/br_netfilter_ipv6.c6
-rw-r--r--net/bridge/br_netlink.c17
-rw-r--r--net/bridge/br_private.h26
-rw-r--r--net/bridge/netfilter/ebtable_broute.c1
-rw-r--r--net/bridge/netfilter/ebtable_filter.c1
-rw-r--r--net/bridge/netfilter/ebtable_nat.c1
-rw-r--r--net/bridge/netfilter/ebtables.c1
-rw-r--r--net/bridge/netfilter/nf_conntrack_bridge.c3
-rw-r--r--net/can/isotp.c19
-rw-r--r--net/can/j1939/socket.c2
-rw-r--r--net/can/raw.c5
-rw-r--r--net/ceph/messenger.c4
-rw-r--r--net/ceph/messenger_v2.c4
-rw-r--r--net/ceph/mon_client.c2
-rw-r--r--net/core/Makefile1
-rw-r--r--net/core/datagram.c75
-rw-r--r--net/core/dev.c268
-rw-r--r--net/core/dev.h9
-rw-r--r--net/core/dev_addr_lists_test.c1
-rw-r--r--net/core/dev_ioctl.c2
-rw-r--r--net/core/drop_monitor.c4
-rw-r--r--net/core/dst.c10
-rw-r--r--net/core/filter.c134
-rw-r--r--net/core/gso_test.c274
-rw-r--r--net/core/neighbour.c76
-rw-r--r--net/core/netclassid_cgroup.c6
-rw-r--r--net/core/netdev-genl.c12
-rw-r--r--net/core/page_pool.c37
-rw-r--r--net/core/pktgen.c119
-rw-r--r--net/core/rtnetlink.c156
-rw-r--r--net/core/scm.c6
-rw-r--r--net/core/selftests.c10
-rw-r--r--net/core/skbuff.c70
-rw-r--r--net/core/skmsg.c2
-rw-r--r--net/core/sock.c236
-rw-r--r--net/core/stream.c12
-rw-r--r--net/core/xdp.c10
-rw-r--r--net/dccp/ipv4.c8
-rw-r--r--net/dccp/ipv6.c16
-rw-r--r--net/dccp/timer.c4
-rw-r--r--net/devlink/core.c223
-rw-r--r--net/devlink/dev.c60
-rw-r--r--net/devlink/devl_internal.h98
-rw-r--r--net/devlink/dpipe.c14
-rw-r--r--net/devlink/health.c441
-rw-r--r--net/devlink/linecard.c83
-rw-r--r--net/devlink/netlink.c358
-rw-r--r--net/devlink/netlink_gen.c757
-rw-r--r--net/devlink/netlink_gen.h64
-rw-r--r--net/devlink/param.c14
-rw-r--r--net/devlink/port.c66
-rw-r--r--net/devlink/rate.c6
-rw-r--r--net/devlink/region.c8
-rw-r--r--net/devlink/resource.c4
-rw-r--r--net/devlink/sb.c17
-rw-r--r--net/devlink/trap.c9
-rw-r--r--net/dsa/Makefile6
-rw-r--r--net/dsa/conduit.c (renamed from net/dsa/master.c)118
-rw-r--r--net/dsa/conduit.h22
-rw-r--r--net/dsa/dsa.c224
-rw-r--r--net/dsa/dsa.h12
-rw-r--r--net/dsa/master.h22
-rw-r--r--net/dsa/netlink.c22
-rw-r--r--net/dsa/port.c144
-rw-r--r--net/dsa/port.h7
-rw-r--r--net/dsa/slave.h69
-rw-r--r--net/dsa/switch.c20
-rw-r--r--net/dsa/switch.h8
-rw-r--r--net/dsa/tag.c10
-rw-r--r--net/dsa/tag.h26
-rw-r--r--net/dsa/tag_8021q.c22
-rw-r--r--net/dsa/tag_8021q.h2
-rw-r--r--net/dsa/tag_ar9331.c4
-rw-r--r--net/dsa/tag_brcm.c14
-rw-r--r--net/dsa/tag_dsa.c6
-rw-r--r--net/dsa/tag_gswip.c4
-rw-r--r--net/dsa/tag_hellcreek.c4
-rw-r--r--net/dsa/tag_ksz.c20
-rw-r--r--net/dsa/tag_lan9303.c4
-rw-r--r--net/dsa/tag_mtk.c4
-rw-r--r--net/dsa/tag_none.c6
-rw-r--r--net/dsa/tag_ocelot.c22
-rw-r--r--net/dsa/tag_ocelot_8021q.c12
-rw-r--r--net/dsa/tag_qca.c6
-rw-r--r--net/dsa/tag_rtl4_a.c6
-rw-r--r--net/dsa/tag_rtl8_4.c6
-rw-r--r--net/dsa/tag_rzn1_a5psw.c4
-rw-r--r--net/dsa/tag_sja1105.c30
-rw-r--r--net/dsa/tag_trailer.c4
-rw-r--r--net/dsa/tag_xrs700x.c4
-rw-r--r--net/dsa/user.c (renamed from net/dsa/slave.c)1473
-rw-r--r--net/dsa/user.h69
-rw-r--r--net/ethtool/common.c21
-rw-r--r--net/ethtool/netlink.c1
-rw-r--r--net/handshake/genl.c2
-rw-r--r--net/handshake/netlink.c32
-rw-r--r--net/handshake/tlshd.c6
-rw-r--r--net/hsr/hsr_forward.c4
-rw-r--r--net/ipv4/Kconfig17
-rw-r--r--net/ipv4/Makefile2
-rw-r--r--net/ipv4/af_inet.c19
-rw-r--r--net/ipv4/ah4.c19
-rw-r--r--net/ipv4/datagram.c6
-rw-r--r--net/ipv4/esp4.c6
-rw-r--r--net/ipv4/esp4_offload.c6
-rw-r--r--net/ipv4/fib_semantics.c14
-rw-r--r--net/ipv4/fou_bpf.c6
-rw-r--r--net/ipv4/icmp.c2
-rw-r--r--net/ipv4/igmp.c8
-rw-r--r--net/ipv4/inet_connection_sock.c1
-rw-r--r--net/ipv4/inet_diag.c5
-rw-r--r--net/ipv4/inet_hashtables.c26
-rw-r--r--net/ipv4/ip_forward.c4
-rw-r--r--net/ipv4/ip_gre.c11
-rw-r--r--net/ipv4/ip_output.c17
-rw-r--r--net/ipv4/ip_sockglue.c187
-rw-r--r--net/ipv4/ip_vti.c4
-rw-r--r--net/ipv4/netfilter.c2
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c9
-rw-r--r--net/ipv4/netfilter/iptable_nat.c1
-rw-r--r--net/ipv4/netfilter/iptable_raw.c1
-rw-r--r--net/ipv4/netfilter/nf_defrag_ipv4.c1
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.asn18
-rw-r--r--net/ipv4/netfilter/nf_reject_ipv4.c1
-rw-r--r--net/ipv4/ping.c15
-rw-r--r--net/ipv4/proc.c8
-rw-r--r--net/ipv4/raw.c19
-rw-r--r--net/ipv4/raw_diag.c1
-rw-r--r--net/ipv4/route.c56
-rw-r--r--net/ipv4/syncookies.c36
-rw-r--r--net/ipv4/sysctl_net_ipv4.c17
-rw-r--r--net/ipv4/tcp.c328
-rw-r--r--net/ipv4/tcp_ao.c2396
-rw-r--r--net/ipv4/tcp_bbr.c13
-rw-r--r--net/ipv4/tcp_bpf.c12
-rw-r--r--net/ipv4/tcp_diag.c1
-rw-r--r--net/ipv4/tcp_input.c256
-rw-r--r--net/ipv4/tcp_ipv4.c385
-rw-r--r--net/ipv4/tcp_lp.c2
-rw-r--r--net/ipv4/tcp_metrics.c22
-rw-r--r--net/ipv4/tcp_minisocks.c69
-rw-r--r--net/ipv4/tcp_output.c351
-rw-r--r--net/ipv4/tcp_recovery.c2
-rw-r--r--net/ipv4/tcp_sigpool.c358
-rw-r--r--net/ipv4/tcp_timer.c63
-rw-r--r--net/ipv4/udp.c117
-rw-r--r--net/ipv4/udp_diag.c1
-rw-r--r--net/ipv4/udp_offload.c4
-rw-r--r--net/ipv4/udp_tunnel_core.c51
-rw-r--r--net/ipv4/udp_tunnel_nic.c11
-rw-r--r--net/ipv4/udplite.c1
-rw-r--r--net/ipv4/xfrm4_input.c99
-rw-r--r--net/ipv6/Makefile1
-rw-r--r--net/ipv6/addrconf.c63
-rw-r--r--net/ipv6/af_inet6.c20
-rw-r--r--net/ipv6/ah6.c19
-rw-r--r--net/ipv6/datagram.c15
-rw-r--r--net/ipv6/esp6.c6
-rw-r--r--net/ipv6/esp6_offload.c10
-rw-r--r--net/ipv6/icmp.c6
-rw-r--r--net/ipv6/inet6_connection_sock.c2
-rw-r--r--net/ipv6/ioam6_iptunnel.c2
-rw-r--r--net/ipv6/ip6_fib.c6
-rw-r--r--net/ipv6/ip6_flowlabel.c8
-rw-r--r--net/ipv6/ip6_output.c171
-rw-r--r--net/ipv6/ip6_udp_tunnel.c75
-rw-r--r--net/ipv6/ip6_vti.c4
-rw-r--r--net/ipv6/ipv6_sockglue.c242
-rw-r--r--net/ipv6/mcast.c11
-rw-r--r--net/ipv6/ndisc.c6
-rw-r--r--net/ipv6/netfilter.c2
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c9
-rw-r--r--net/ipv6/netfilter/ip6table_nat.c1
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c1
-rw-r--r--net/ipv6/netfilter/nf_defrag_ipv6_hooks.c1
-rw-r--r--net/ipv6/netfilter/nf_reject_ipv6.c1
-rw-r--r--net/ipv6/ping.c6
-rw-r--r--net/ipv6/proc.c3
-rw-r--r--net/ipv6/raw.c18
-rw-r--r--net/ipv6/route.c6
-rw-r--r--net/ipv6/syncookies.c12
-rw-r--r--net/ipv6/tcp_ao.c168
-rw-r--r--net/ipv6/tcp_ipv6.c411
-rw-r--r--net/ipv6/udp.c52
-rw-r--r--net/ipv6/udplite.c1
-rw-r--r--net/ipv6/xfrm6_input.c107
-rw-r--r--net/ipv6/xfrm6_output.c2
-rw-r--r--net/ipv6/xfrm6_policy.c4
-rw-r--r--net/iucv/iucv.c4
-rw-r--r--net/kcm/kcmsock.c1
-rw-r--r--net/l2tp/l2tp_core.c6
-rw-r--r--net/l2tp/l2tp_eth.c34
-rw-r--r--net/l2tp/l2tp_ip6.c6
-rw-r--r--net/llc/llc_input.c10
-rw-r--r--net/llc/llc_s_ac.c3
-rw-r--r--net/llc/llc_station.c3
-rw-r--r--net/mac80211/Kconfig13
-rw-r--r--net/mac80211/Makefile2
-rw-r--r--net/mac80211/agg-rx.c63
-rw-r--r--net/mac80211/agg-tx.c63
-rw-r--r--net/mac80211/airtime.c10
-rw-r--r--net/mac80211/cfg.c490
-rw-r--r--net/mac80211/chan.c156
-rw-r--r--net/mac80211/debugfs.c11
-rw-r--r--net/mac80211/debugfs_key.c20
-rw-r--r--net/mac80211/debugfs_netdev.c243
-rw-r--r--net/mac80211/debugfs_netdev.h15
-rw-r--r--net/mac80211/debugfs_sta.c74
-rw-r--r--net/mac80211/driver-ops.c54
-rw-r--r--net/mac80211/driver-ops.h168
-rw-r--r--net/mac80211/drop.h49
-rw-r--r--net/mac80211/ethtool.c20
-rw-r--r--net/mac80211/ht.c59
-rw-r--r--net/mac80211/ibss.c104
-rw-r--r--net/mac80211/ieee80211_i.h223
-rw-r--r--net/mac80211/iface.c180
-rw-r--r--net/mac80211/key.c152
-rw-r--r--net/mac80211/key.h11
-rw-r--r--net/mac80211/link.c63
-rw-r--r--net/mac80211/main.c93
-rw-r--r--net/mac80211/mesh.c24
-rw-r--r--net/mac80211/mesh_hwmp.c2
-rw-r--r--net/mac80211/mesh_pathtbl.c22
-rw-r--r--net/mac80211/mesh_plink.c6
-rw-r--r--net/mac80211/mesh_ps.c6
-rw-r--r--net/mac80211/mesh_sync.c4
-rw-r--r--net/mac80211/mlme.c709
-rw-r--r--net/mac80211/ocb.c19
-rw-r--r--net/mac80211/offchannel.c120
-rw-r--r--net/mac80211/pm.c13
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c7
-rw-r--r--net/mac80211/rx.c116
-rw-r--r--net/mac80211/s1g.c15
-rw-r--r--net/mac80211/scan.c226
-rw-r--r--net/mac80211/spectmgmt.c13
-rw-r--r--net/mac80211/sta_info.c171
-rw-r--r--net/mac80211/sta_info.h26
-rw-r--r--net/mac80211/status.c111
-rw-r--r--net/mac80211/tdls.c88
-rw-r--r--net/mac80211/tests/Makefile3
-rw-r--r--net/mac80211/tests/elems.c101
-rw-r--r--net/mac80211/tests/module.c10
-rw-r--r--net/mac80211/trace.h11
-rw-r--r--net/mac80211/tx.c73
-rw-r--r--net/mac80211/util.c263
-rw-r--r--net/mac80211/wep.c9
-rw-r--r--net/mac80211/wpa.c42
-rw-r--r--net/mctp/route.c22
-rw-r--r--net/mptcp/Makefile3
-rw-r--r--net/mptcp/ctrl.c16
-rw-r--r--net/mptcp/fastopen.c1
-rw-r--r--net/mptcp/mptcp_diag.c1
-rw-r--r--net/mptcp/mptcp_pm_gen.c179
-rw-r--r--net/mptcp/mptcp_pm_gen.h58
-rw-r--r--net/mptcp/options.c1
-rw-r--r--net/mptcp/pm.c2
-rw-r--r--net/mptcp/pm_netlink.c119
-rw-r--r--net/mptcp/pm_userspace.c89
-rw-r--r--net/mptcp/protocol.c129
-rw-r--r--net/mptcp/protocol.h92
-rw-r--r--net/mptcp/sockopt.c76
-rw-r--r--net/mptcp/subflow.c48
-rw-r--r--net/ncsi/ncsi-aen.c5
-rw-r--r--net/netfilter/core.c6
-rw-r--r--net/netfilter/ipset/ip_set_core.c14
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_dh.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_fo.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_ftp.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_lblc.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_lblcr.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_lc.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_nq.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_ovf.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_pe_sip.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_rr.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_sed.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_sh.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c16
-rw-r--r--net/netfilter/ipvs/ip_vs_twos.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_wlc.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_wrr.c1
-rw-r--r--net/netfilter/nf_bpf_link.c10
-rw-r--r--net/netfilter/nf_conntrack_bpf.c6
-rw-r--r--net/netfilter/nf_conntrack_broadcast.c1
-rw-r--r--net/netfilter/nf_conntrack_core.c76
-rw-r--r--net/netfilter/nf_conntrack_helper.c7
-rw-r--r--net/netfilter/nf_conntrack_labels.c17
-rw-r--r--net/netfilter/nf_conntrack_netlink.c1
-rw-r--r--net/netfilter/nf_conntrack_proto.c1
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c7
-rw-r--r--net/netfilter/nf_flow_table_core.c14
-rw-r--r--net/netfilter/nf_nat_bpf.c6
-rw-r--r--net/netfilter/nf_nat_core.c1
-rw-r--r--net/netfilter/nf_nat_proto.c71
-rw-r--r--net/netfilter/nf_nat_redirect.c27
-rw-r--r--net/netfilter/nf_synproxy_core.c2
-rw-r--r--net/netfilter/nf_tables_api.c692
-rw-r--r--net/netfilter/nf_tables_core.c8
-rw-r--r--net/netfilter/nf_tables_trace.c8
-rw-r--r--net/netfilter/nfnetlink_log.c2
-rw-r--r--net/netfilter/nfnetlink_osf.c1
-rw-r--r--net/netfilter/nfnetlink_queue.c15
-rw-r--r--net/netfilter/nft_byteorder.c5
-rw-r--r--net/netfilter/nft_chain_nat.c1
-rw-r--r--net/netfilter/nft_dynset.c36
-rw-r--r--net/netfilter/nft_exthdr.c4
-rw-r--r--net/netfilter/nft_fib.c9
-rw-r--r--net/netfilter/nft_fwd_netdev.c1
-rw-r--r--net/netfilter/nft_inner.c1
-rw-r--r--net/netfilter/nft_meta.c2
-rw-r--r--net/netfilter/nft_payload.c2
-rw-r--r--net/netfilter/nft_set_bitmap.c53
-rw-r--r--net/netfilter/nft_set_hash.c109
-rw-r--r--net/netfilter/nft_set_pipapo.c81
-rw-r--r--net/netfilter/nft_set_pipapo.h6
-rw-r--r--net/netfilter/nft_set_rbtree.c204
-rw-r--r--net/netfilter/xt_owner.c16
-rw-r--r--net/netfilter/xt_recent.c2
-rw-r--r--net/netlink/diag.c1
-rw-r--r--net/netlink/genetlink.c6
-rw-r--r--net/netlink/policy.c29
-rw-r--r--net/netrom/af_netrom.c2
-rw-r--r--net/nfc/llcp_core.c30
-rw-r--r--net/nfc/nci/core.c5
-rw-r--r--net/nfc/nci/spi.c2
-rw-r--r--net/openvswitch/actions.c27
-rw-r--r--net/openvswitch/conntrack.c2
-rw-r--r--net/openvswitch/flow_table.c7
-rw-r--r--net/openvswitch/flow_table.h2
-rw-r--r--net/openvswitch/meter.h4
-rw-r--r--net/packet/af_packet.c23
-rw-r--r--net/packet/diag.c1
-rw-r--r--net/packet/internal.h4
-rw-r--r--net/psample/psample.c3
-rw-r--r--net/rfkill/core.c5
-rw-r--r--net/rfkill/rfkill-gpio.c4
-rw-r--r--net/rose/af_rose.c6
-rw-r--r--net/rxrpc/conn_client.c7
-rw-r--r--net/rxrpc/conn_object.c2
-rw-r--r--net/rxrpc/input.c61
-rw-r--r--net/rxrpc/local_object.c2
-rw-r--r--net/sched/act_api.c2
-rw-r--r--net/sched/act_ct.c102
-rw-r--r--net/sched/act_gate.c1
-rw-r--r--net/sched/cls_api.c35
-rw-r--r--net/sched/cls_basic.c1
-rw-r--r--net/sched/cls_cgroup.c1
-rw-r--r--net/sched/cls_fw.c1
-rw-r--r--net/sched/cls_route.c38
-rw-r--r--net/sched/cls_u32.c3
-rw-r--r--net/sched/em_meta.c2
-rw-r--r--net/sched/sch_cbs.c1
-rw-r--r--net/sched/sch_choke.c1
-rw-r--r--net/sched/sch_drr.c1
-rw-r--r--net/sched/sch_etf.c1
-rw-r--r--net/sched/sch_ets.c1
-rw-r--r--net/sched/sch_fifo.c1
-rw-r--r--net/sched/sch_fq.c385
-rw-r--r--net/sched/sch_fq_pie.c2
-rw-r--r--net/sched/sch_frag.c4
-rw-r--r--net/sched/sch_generic.c9
-rw-r--r--net/sched/sch_gred.c1
-rw-r--r--net/sched/sch_hfsc.c19
-rw-r--r--net/sched/sch_htb.c1
-rw-r--r--net/sched/sch_ingress.c1
-rw-r--r--net/sched/sch_mqprio.c1
-rw-r--r--net/sched/sch_mqprio_lib.c1
-rw-r--r--net/sched/sch_multiq.c1
-rw-r--r--net/sched/sch_netem.c3
-rw-r--r--net/sched/sch_plug.c1
-rw-r--r--net/sched/sch_prio.c1
-rw-r--r--net/sched/sch_qfq.c5
-rw-r--r--net/sched/sch_red.c1
-rw-r--r--net/sched/sch_sfq.c1
-rw-r--r--net/sched/sch_skbprio.c1
-rw-r--r--net/sched/sch_taprio.c3
-rw-r--r--net/sched/sch_tbf.c1
-rw-r--r--net/sched/sch_teql.c1
-rw-r--r--net/sctp/diag.c1
-rw-r--r--net/sctp/ipv6.c9
-rw-r--r--net/sctp/protocol.c4
-rw-r--r--net/sctp/sm_make_chunk.c2
-rw-r--r--net/smc/Kconfig1
-rw-r--r--net/smc/af_smc.c23
-rw-r--r--net/smc/smc.h5
-rw-r--r--net/smc/smc_cdc.c11
-rw-r--r--net/smc/smc_clc.c9
-rw-r--r--net/smc/smc_clc.h4
-rw-r--r--net/smc/smc_close.c5
-rw-r--r--net/smc/smc_diag.c1
-rw-r--r--net/smc/smc_ib.c7
-rw-r--r--net/smc/smc_ib.h2
-rw-r--r--net/smc/smc_stats.h14
-rw-r--r--net/socket.c114
-rw-r--r--net/sunrpc/auth.c23
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_crypto.c2
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_unseal.c2
-rw-r--r--net/sunrpc/backchannel_rqst.c13
-rw-r--r--net/sunrpc/clnt.c10
-rw-r--r--net/sunrpc/rpc_pipe.c2
-rw-r--r--net/sunrpc/rpcb_clnt.c4
-rw-r--r--net/sunrpc/svc.c155
-rw-r--r--net/sunrpc/svc_xprt.c236
-rw-r--r--net/sunrpc/xprt.c4
-rw-r--r--net/sunrpc/xprtrdma/backchannel.c6
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c3
-rw-r--r--net/sunrpc/xprtsock.c14
-rw-r--r--net/tipc/diag.c1
-rw-r--r--net/tipc/link.c4
-rw-r--r--net/tipc/netlink.c4
-rw-r--r--net/tipc/netlink_compat.c1
-rw-r--r--net/tls/tls.h11
-rw-r--r--net/tls/tls_device.c101
-rw-r--r--net/tls/tls_device_fallback.c23
-rw-r--r--net/tls/tls_main.c72
-rw-r--r--net/tls/tls_sw.c218
-rw-r--r--net/unix/af_unix.c69
-rw-r--r--net/unix/diag.c1
-rw-r--r--net/unix/unix_bpf.c5
-rw-r--r--net/vmw_vsock/af_vsock.c66
-rw-r--r--net/vmw_vsock/diag.c1
-rw-r--r--net/vmw_vsock/virtio_transport.c117
-rw-r--r--net/vmw_vsock/virtio_transport_common.c326
-rw-r--r--net/vmw_vsock/vsock_loopback.c6
-rw-r--r--net/wireless/Kconfig11
-rw-r--r--net/wireless/Makefile1
-rw-r--r--net/wireless/ap.c24
-rw-r--r--net/wireless/chan.c51
-rw-r--r--net/wireless/core.c80
-rw-r--r--net/wireless/core.h65
-rw-r--r--net/wireless/debugfs.c160
-rw-r--r--net/wireless/ibss.c76
-rw-r--r--net/wireless/lib80211_crypt_tkip.c12
-rw-r--r--net/wireless/mesh.c28
-rw-r--r--net/wireless/mlme.c26
-rw-r--r--net/wireless/nl80211.c599
-rw-r--r--net/wireless/nl80211.h7
-rw-r--r--net/wireless/ocb.c43
-rw-r--r--net/wireless/pmsr.c4
-rw-r--r--net/wireless/rdev-ops.h2
-rw-r--r--net/wireless/reg.c99
-rw-r--r--net/wireless/reg.h16
-rw-r--r--net/wireless/scan.c113
-rw-r--r--net/wireless/sme.c82
-rw-r--r--net/wireless/sysfs.c4
-rw-r--r--net/wireless/tests/Makefile3
-rw-r--r--net/wireless/tests/fragmentation.c157
-rw-r--r--net/wireless/tests/module.c10
-rw-r--r--net/wireless/trace.h88
-rw-r--r--net/wireless/util.c60
-rw-r--r--net/wireless/wext-compat.c47
-rw-r--r--net/wireless/wext-sme.c59
-rw-r--r--net/x25/af_x25.c2
-rw-r--r--net/xdp/xsk.c37
-rw-r--r--net/xdp/xsk_buff_pool.c3
-rw-r--r--net/xdp/xsk_diag.c1
-rw-r--r--net/xdp/xsk_queue.c10
-rw-r--r--net/xfrm/Kconfig1
-rw-r--r--net/xfrm/xfrm_algo.c19
-rw-r--r--net/xfrm/xfrm_input.c6
-rw-r--r--net/xfrm/xfrm_interface_bpf.c6
-rw-r--r--net/xfrm/xfrm_interface_core.c26
-rw-r--r--net/xfrm/xfrm_policy.c328
-rw-r--r--rust/Makefile26
-rw-r--r--rust/alloc/alloc.rs21
-rw-r--r--rust/alloc/boxed.rs56
-rw-r--r--rust/alloc/lib.rs13
-rw-r--r--rust/alloc/raw_vec.rs30
-rw-r--r--rust/alloc/vec/drain_filter.rs199
-rw-r--r--rust/alloc/vec/extract_if.rs115
-rw-r--r--rust/alloc/vec/mod.rs110
-rw-r--r--rust/alloc/vec/spec_extend.rs8
-rw-r--r--rust/bindings/bindings_helper.h1
-rw-r--r--rust/compiler_builtins.rs1
-rw-r--r--rust/helpers.c13
-rw-r--r--rust/kernel/error.rs4
-rw-r--r--rust/kernel/init.rs20
-rw-r--r--rust/kernel/lib.rs3
-rw-r--r--rust/kernel/print.rs1
-rw-r--r--rust/kernel/sync/arc.rs48
-rw-r--r--rust/kernel/sync/condvar.rs1
-rw-r--r--rust/kernel/sync/lock.rs1
-rw-r--r--rust/kernel/task.rs2
-rw-r--r--rust/kernel/workqueue.rs679
-rw-r--r--samples/bpf/Makefile19
-rw-r--r--samples/bpf/syscall_tp_kern.c15
-rw-r--r--samples/bpf/syscall_tp_user.c45
-rw-r--r--samples/kprobes/kretprobe_example.c2
-rw-r--r--samples/landlock/sandboxer.c115
-rw-r--r--samples/vfio-mdev/mbochs.c2
-rw-r--r--samples/vfio-mdev/mdpy.c2
-rw-r--r--samples/vfio-mdev/mtty.c829
-rw-r--r--scripts/Makefile.btf19
-rw-r--r--scripts/Makefile.build4
-rw-r--r--scripts/Makefile.host2
-rw-r--r--scripts/Makefile.lib4
-rw-r--r--scripts/Makefile.modfinal5
-rw-r--r--scripts/Makefile.package10
-rw-r--r--scripts/Makefile.userprogs6
-rw-r--r--scripts/Makefile.vdsoinst45
-rw-r--r--scripts/Makefile.vmlinux1
-rw-r--r--scripts/Makefile.vmlinux_o3
-rwxr-xr-xscripts/atomic/gen-atomic-fallback.sh33
-rwxr-xr-xscripts/atomic/gen-atomic-instrumented.sh3
-rwxr-xr-xscripts/checkpatch.pl9
-rwxr-xr-xscripts/checkstack.pl11
-rwxr-xr-xscripts/clang-tools/gen_compile_commands.py8
-rwxr-xr-xscripts/clang-tools/run-clang-tools.py32
-rw-r--r--scripts/const_structs.checkpatch1
-rwxr-xr-xscripts/dtc/dt-extract-compatibles86
-rwxr-xr-xscripts/dummy-tools/gcc10
-rwxr-xr-xscripts/faddr2line24
-rw-r--r--scripts/gcc-plugins/latent_entropy_plugin.c4
-rw-r--r--scripts/gcc-plugins/randomize_layout_plugin.c24
-rw-r--r--scripts/gdb/linux/constants.py.in10
-rw-r--r--scripts/gdb/linux/cpus.py15
-rw-r--r--scripts/gdb/linux/device.py16
-rw-r--r--scripts/gdb/linux/tasks.py18
-rw-r--r--scripts/gdb/linux/vmalloc.py8
-rwxr-xr-xscripts/get_maintainer.pl38
-rwxr-xr-xscripts/headers_install.sh1
-rw-r--r--scripts/kconfig/symbol.c14
-rwxr-xr-xscripts/kernel-doc2
-rwxr-xr-xscripts/min-tool-version.sh2
-rw-r--r--scripts/mod/Makefile4
-rw-r--r--scripts/mod/devicetable-offsets.c7
-rw-r--r--scripts/mod/file2alias.c31
-rw-r--r--scripts/mod/modpost.c207
-rw-r--r--scripts/mod/modpost.h50
-rw-r--r--scripts/mod/symsearch.c199
-rwxr-xr-xscripts/package/mkspec6
-rwxr-xr-xscripts/pahole-flags.sh30
-rwxr-xr-xscripts/remove-stale-files2
-rwxr-xr-xscripts/show_delta3
-rw-r--r--scripts/sign-file.c12
-rw-r--r--security/apparmor/apparmorfs.c56
-rw-r--r--security/apparmor/audit.c75
-rw-r--r--security/apparmor/capability.c33
-rw-r--r--security/apparmor/domain.c193
-rw-r--r--security/apparmor/file.c217
-rw-r--r--security/apparmor/include/apparmor.h3
-rw-r--r--security/apparmor/include/audit.h44
-rw-r--r--security/apparmor/include/capability.h3
-rw-r--r--security/apparmor/include/file.h54
-rw-r--r--security/apparmor/include/ipc.h4
-rw-r--r--security/apparmor/include/lib.h2
-rw-r--r--security/apparmor/include/match.h6
-rw-r--r--security/apparmor/include/mount.h26
-rw-r--r--security/apparmor/include/net.h25
-rw-r--r--security/apparmor/include/perms.h7
-rw-r--r--security/apparmor/include/policy.h68
-rw-r--r--security/apparmor/include/policy_ns.h14
-rw-r--r--security/apparmor/include/resource.h3
-rw-r--r--security/apparmor/include/task.h11
-rw-r--r--security/apparmor/ipc.c53
-rw-r--r--security/apparmor/label.c46
-rw-r--r--security/apparmor/lib.c54
-rw-r--r--security/apparmor/lsm.c418
-rw-r--r--security/apparmor/match.c48
-rw-r--r--security/apparmor/mount.c186
-rw-r--r--security/apparmor/net.c65
-rw-r--r--security/apparmor/policy.c133
-rw-r--r--security/apparmor/policy_compat.c1
-rw-r--r--security/apparmor/policy_ns.c37
-rw-r--r--security/apparmor/policy_unpack.c156
-rw-r--r--security/apparmor/resource.c54
-rw-r--r--security/apparmor/task.c104
-rw-r--r--security/commoncap.c4
-rw-r--r--security/inode.c2
-rw-r--r--security/integrity/Kconfig46
-rw-r--r--security/integrity/evm/evm_main.c3
-rw-r--r--security/integrity/iint.c50
-rw-r--r--security/integrity/ima/ima_api.c5
-rw-r--r--security/integrity/ima/ima_main.c16
-rw-r--r--security/integrity/ima/ima_modsig.c6
-rw-r--r--security/integrity/integrity.h2
-rw-r--r--security/keys/encrypted-keys/encrypted.c2
-rw-r--r--security/keys/internal.h7
-rw-r--r--security/keys/key.c1
-rw-r--r--security/keys/trusted-keys/trusted_core.c20
-rw-r--r--security/keys/trusted-keys/trusted_tee.c64
-rw-r--r--security/landlock/Kconfig1
-rw-r--r--security/landlock/Makefile2
-rw-r--r--security/landlock/fs.c232
-rw-r--r--security/landlock/limits.h6
-rw-r--r--security/landlock/net.c200
-rw-r--r--security/landlock/net.h33
-rw-r--r--security/landlock/ruleset.c405
-rw-r--r--security/landlock/ruleset.h185
-rw-r--r--security/landlock/setup.c2
-rw-r--r--security/landlock/syscalls.c158
-rw-r--r--security/security.c12
-rw-r--r--security/selinux/Kconfig10
-rw-r--r--security/selinux/Makefile2
-rw-r--r--security/selinux/hooks.c16
-rw-r--r--security/selinux/selinuxfs.c2
-rw-r--r--security/selinux/ss/avtab.c37
-rw-r--r--security/selinux/ss/hashtab.c5
-rw-r--r--security/selinux/ss/hashtab.h1
-rw-r--r--security/selinux/ss/policydb.c6
-rw-r--r--security/selinux/ss/sidtab.c2
-rw-r--r--security/tomoyo/tomoyo.c2
-rw-r--r--sound/aoa/aoa-gpio.h1
-rw-r--r--sound/aoa/aoa.h1
-rw-r--r--sound/aoa/codecs/onyx.c1
-rw-r--r--sound/aoa/codecs/onyx.h1
-rw-r--r--sound/aoa/codecs/tas.c2
-rw-r--r--sound/aoa/fabrics/layout.c3
-rw-r--r--sound/aoa/soundbus/core.c2
-rw-r--r--sound/aoa/soundbus/i2sbus/control.c1
-rw-r--r--sound/aoa/soundbus/i2sbus/core.c1
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus.h1
-rw-r--r--sound/aoa/soundbus/i2sbus/interface.h2
-rw-r--r--sound/aoa/soundbus/soundbus.h2
-rw-r--r--sound/arm/pxa2xx-pcm-lib.c8
-rw-r--r--sound/core/control_compat.c2
-rw-r--r--sound/core/info.c21
-rw-r--r--sound/core/pcm.c1
-rw-r--r--sound/core/pcm_native.c8
-rw-r--r--sound/core/rawmidi_compat.c4
-rw-r--r--sound/drivers/aloop.c76
-rw-r--r--sound/drivers/pcmtest.c13
-rw-r--r--sound/hda/ext/hdac_ext_stream.c43
-rw-r--r--sound/hda/hdac_i915.c24
-rw-r--r--sound/hda/hdac_stream.c23
-rw-r--r--sound/hda/intel-dsp-config.c6
-rw-r--r--sound/hda/intel-nhlt.c33
-rw-r--r--sound/oss/dmasound/dmasound_paula.c7
-rw-r--r--sound/pci/asihpi/hpidebug.h9
-rw-r--r--sound/pci/azt3328.c2
-rw-r--r--sound/pci/hda/Kconfig18
-rw-r--r--sound/pci/hda/Makefile4
-rw-r--r--sound/pci/hda/cirrus_scodec.c73
-rw-r--r--sound/pci/hda/cirrus_scodec.h13
-rw-r--r--sound/pci/hda/cirrus_scodec_test.c370
-rw-r--r--sound/pci/hda/cs35l41_hda.c338
-rw-r--r--sound/pci/hda/cs35l41_hda.h3
-rw-r--r--sound/pci/hda/cs35l41_hda_property.c11
-rw-r--r--sound/pci/hda/cs35l56_hda.c24
-rw-r--r--sound/pci/hda/cs35l56_hda_i2c.c4
-rw-r--r--sound/pci/hda/cs35l56_hda_spi.c4
-rw-r--r--sound/pci/hda/hda_codec.c2
-rw-r--r--sound/pci/hda/hda_component.h4
-rw-r--r--sound/pci/hda/hda_controller.c2
-rw-r--r--sound/pci/hda/hda_intel.c84
-rw-r--r--sound/pci/hda/patch_hdmi.c3
-rw-r--r--sound/pci/hda/patch_realtek.c215
-rw-r--r--sound/pci/hda/tas2781_hda_i2c.c21
-rw-r--r--sound/pci/intel8x0m.c2
-rw-r--r--sound/pci/mixart/mixart_core.h70
-rw-r--r--sound/soc/amd/acp-config.c96
-rw-r--r--sound/soc/amd/acp-da7219-max98357a.c28
-rw-r--r--sound/soc/amd/acp-es8336.c6
-rw-r--r--sound/soc/amd/acp-pcm-dma.c2
-rw-r--r--sound/soc/amd/acp-rt5645.c6
-rw-r--r--sound/soc/amd/acp/Kconfig18
-rw-r--r--sound/soc/amd/acp/Makefile4
-rw-r--r--sound/soc/amd/acp/acp-i2s.c45
-rw-r--r--sound/soc/amd/acp/acp-legacy-common.c79
-rw-r--r--sound/soc/amd/acp/acp-legacy-mach.c114
-rw-r--r--sound/soc/amd/acp/acp-mach-common.c86
-rw-r--r--sound/soc/amd/acp/acp-mach.h69
-rw-r--r--sound/soc/amd/acp/acp-pci.c23
-rw-r--r--sound/soc/amd/acp/acp-platform.c29
-rw-r--r--sound/soc/amd/acp/acp-rembrandt.c17
-rw-r--r--sound/soc/amd/acp/acp-renoir.c7
-rw-r--r--sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c444
-rw-r--r--sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.h12
-rw-r--r--sound/soc/amd/acp/acp63.c322
-rw-r--r--sound/soc/amd/acp/acp70.c254
-rw-r--r--sound/soc/amd/acp/amd.h71
-rw-r--r--sound/soc/amd/acp/chip_offset_byte.h1
-rw-r--r--sound/soc/amd/acp3x-rt5682-max9836.c12
-rw-r--r--sound/soc/amd/mach-config.h2
-rw-r--r--sound/soc/amd/ps/pci-ps.c3
-rw-r--r--sound/soc/amd/ps/ps-sdw-dma.c2
-rw-r--r--sound/soc/amd/raven/acp3x-i2s.c2
-rw-r--r--sound/soc/amd/raven/acp3x-pcm-dma.c6
-rw-r--r--sound/soc/amd/vangogh/acp5x-i2s.c2
-rw-r--r--sound/soc/amd/vangogh/acp5x-mach.c12
-rw-r--r--sound/soc/amd/vangogh/acp5x-pcm-dma.c6
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c21
-rw-r--r--sound/soc/apple/mca.c28
-rw-r--r--sound/soc/atmel/atmel-classd.c10
-rw-r--r--sound/soc/atmel/atmel-pcm-dma.c8
-rw-r--r--sound/soc/atmel/atmel-pcm-pdc.c4
-rw-r--r--sound/soc/atmel/atmel-pdmic.c12
-rw-r--r--sound/soc/atmel/atmel_wm8904.c5
-rw-r--r--sound/soc/atmel/mchp-i2s-mcc.c2
-rw-r--r--sound/soc/atmel/mikroe-proto.c2
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c2
-rw-r--r--sound/soc/atmel/sam9x5_wm8731.c2
-rw-r--r--sound/soc/atmel/tse850-pcm5142.c1
-rw-r--r--sound/soc/au1x/db1200.c4
-rw-r--r--sound/soc/au1x/dbdma2.c4
-rw-r--r--sound/soc/au1x/dma.c4
-rw-r--r--sound/soc/au1x/psc-ac97.c2
-rw-r--r--sound/soc/bcm/bcm63xx-pcm-whistler.c28
-rw-r--r--sound/soc/bcm/cygnus-pcm.c24
-rw-r--r--sound/soc/bcm/cygnus-ssp.c2
-rw-r--r--sound/soc/cirrus/edb93xx.c6
-rw-r--r--sound/soc/codecs/88pm860x-codec.c4
-rw-r--r--sound/soc/codecs/Kconfig44
-rw-r--r--sound/soc/codecs/Makefile6
-rw-r--r--sound/soc/codecs/adau1373.c2
-rw-r--r--sound/soc/codecs/adau1701.c1
-rw-r--r--sound/soc/codecs/adau1977-spi.c1
-rw-r--r--sound/soc/codecs/adav80x.c2
-rw-r--r--sound/soc/codecs/ak4104.c2
-rw-r--r--sound/soc/codecs/ak4118.c2
-rw-r--r--sound/soc/codecs/ak4375.c2
-rw-r--r--sound/soc/codecs/ak4458.c2
-rw-r--r--sound/soc/codecs/ak4613.c2
-rw-r--r--sound/soc/codecs/ak4642.c30
-rw-r--r--sound/soc/codecs/ak5386.c7
-rw-r--r--sound/soc/codecs/ak5558.c2
-rw-r--r--sound/soc/codecs/audio-iio-aux.c17
-rw-r--r--sound/soc/codecs/aw87390.c463
-rw-r--r--sound/soc/codecs/aw87390.h85
-rw-r--r--sound/soc/codecs/aw88261.c44
-rw-r--r--sound/soc/codecs/aw88261.h4
-rw-r--r--sound/soc/codecs/aw88395/aw88395.c11
-rw-r--r--sound/soc/codecs/aw88395/aw88395.h2
-rw-r--r--sound/soc/codecs/aw88395/aw88395_device.c47
-rw-r--r--sound/soc/codecs/aw88395/aw88395_device.h6
-rw-r--r--sound/soc/codecs/aw88395/aw88395_lib.c28
-rw-r--r--sound/soc/codecs/aw88395/aw88395_reg.h2
-rw-r--r--sound/soc/codecs/aw88399.c1911
-rw-r--r--sound/soc/codecs/aw88399.h599
-rw-r--r--sound/soc/codecs/cs35l32.c2
-rw-r--r--sound/soc/codecs/cs35l33.c2
-rw-r--r--sound/soc/codecs/cs35l34.c2
-rw-r--r--sound/soc/codecs/cs35l35.c3
-rw-r--r--sound/soc/codecs/cs35l36.c3
-rw-r--r--sound/soc/codecs/cs35l41-i2c.c13
-rw-r--r--sound/soc/codecs/cs35l41-lib.c70
-rw-r--r--sound/soc/codecs/cs35l41-spi.c11
-rw-r--r--sound/soc/codecs/cs35l41.c94
-rw-r--r--sound/soc/codecs/cs35l41.h1
-rw-r--r--sound/soc/codecs/cs35l45-tables.c3
-rw-r--r--sound/soc/codecs/cs35l45.c193
-rw-r--r--sound/soc/codecs/cs35l45.h36
-rw-r--r--sound/soc/codecs/cs35l56-i2c.c3
-rw-r--r--sound/soc/codecs/cs35l56-sdw.c2
-rw-r--r--sound/soc/codecs/cs35l56-shared.c68
-rw-r--r--sound/soc/codecs/cs35l56-spi.c3
-rw-r--r--sound/soc/codecs/cs35l56.c24
-rw-r--r--sound/soc/codecs/cs4270.c2
-rw-r--r--sound/soc/codecs/cs4271.c22
-rw-r--r--sound/soc/codecs/cs42l42-sdw.c1
-rw-r--r--sound/soc/codecs/cs42l42.c1
-rw-r--r--sound/soc/codecs/cs42l43-jack.c40
-rw-r--r--sound/soc/codecs/cs42l43-sdw.c6
-rw-r--r--sound/soc/codecs/cs42l43.c8
-rw-r--r--sound/soc/codecs/cs42l56.c2
-rw-r--r--sound/soc/codecs/cs42xx8-i2c.c16
-rw-r--r--sound/soc/codecs/cs43130.c9
-rw-r--r--sound/soc/codecs/cs4349.c2
-rw-r--r--sound/soc/codecs/cs47l15.c4
-rw-r--r--sound/soc/codecs/cs47l24.c6
-rw-r--r--sound/soc/codecs/cs47l35.c6
-rw-r--r--sound/soc/codecs/cs47l85.c6
-rw-r--r--sound/soc/codecs/cs47l90.c6
-rw-r--r--sound/soc/codecs/cs47l92.c4
-rw-r--r--sound/soc/codecs/da7213.c203
-rw-r--r--sound/soc/codecs/da7213.h64
-rw-r--r--sound/soc/codecs/da7218.c29
-rw-r--r--sound/soc/codecs/da7218.h2
-rw-r--r--sound/soc/codecs/da7219-aad.c22
-rw-r--r--sound/soc/codecs/da7219.c2
-rw-r--r--sound/soc/codecs/da9055.c1
-rw-r--r--sound/soc/codecs/es8316.c52
-rw-r--r--sound/soc/codecs/es8316.h3
-rw-r--r--sound/soc/codecs/es8328.c10
-rw-r--r--sound/soc/codecs/gtm601.c2
-rw-r--r--sound/soc/codecs/hdac_hda.c52
-rw-r--r--sound/soc/codecs/hdac_hda.h1
-rw-r--r--sound/soc/codecs/hdac_hdmi.c13
-rw-r--r--sound/soc/codecs/hdmi-codec.c27
-rw-r--r--sound/soc/codecs/lpass-macro-common.c2
-rw-r--r--sound/soc/codecs/lpass-macro-common.h2
-rw-r--r--sound/soc/codecs/lpass-rx-macro.c6
-rw-r--r--sound/soc/codecs/lpass-tx-macro.c27
-rw-r--r--sound/soc/codecs/lpass-wsa-macro.c7
-rw-r--r--sound/soc/codecs/max9768.c45
-rw-r--r--sound/soc/codecs/max98357a.c1
-rw-r--r--sound/soc/codecs/max98373-i2c.c17
-rw-r--r--sound/soc/codecs/max98373.c35
-rw-r--r--sound/soc/codecs/max98373.h2
-rw-r--r--sound/soc/codecs/max98388.c3
-rw-r--r--sound/soc/codecs/max98396.c1
-rw-r--r--sound/soc/codecs/max98520.c2
-rw-r--r--sound/soc/codecs/max9867.c8
-rw-r--r--sound/soc/codecs/max98927.c2
-rw-r--r--sound/soc/codecs/mt6351.c2
-rw-r--r--sound/soc/codecs/mt6358.c2
-rw-r--r--sound/soc/codecs/mt6359-accdet.c4
-rw-r--r--sound/soc/codecs/mt6359.c2
-rw-r--r--sound/soc/codecs/nau8540.c51
-rw-r--r--sound/soc/codecs/nau8540.h15
-rw-r--r--sound/soc/codecs/nau8821.c3
-rw-r--r--sound/soc/codecs/nau8822.c9
-rw-r--r--sound/soc/codecs/pcm1681.c2
-rw-r--r--sound/soc/codecs/pcm512x-i2c.c4
-rw-r--r--sound/soc/codecs/pcm512x.c36
-rw-r--r--sound/soc/codecs/rt1015.c13
-rw-r--r--sound/soc/codecs/rt298.c1
-rw-r--r--sound/soc/codecs/rt5645.c12
-rw-r--r--sound/soc/codecs/rt5677-spi.c4
-rw-r--r--sound/soc/codecs/rt5682s.c4
-rw-r--r--sound/soc/codecs/rt712-sdca.c14
-rw-r--r--sound/soc/codecs/rt715-sdca.c4
-rw-r--r--sound/soc/codecs/rt715.c6
-rw-r--r--sound/soc/codecs/rtq9128.c780
-rw-r--r--sound/soc/codecs/sgtl5000.c2
-rw-r--r--sound/soc/codecs/sigmadsp.c7
-rw-r--r--sound/soc/codecs/sma1303.c2
-rw-r--r--sound/soc/codecs/sta32x.c3
-rw-r--r--sound/soc/codecs/sta350.c3
-rw-r--r--sound/soc/codecs/tas2780.c2
-rw-r--r--sound/soc/codecs/tas2781-fmwlib.c236
-rw-r--r--sound/soc/codecs/tas5086.c6
-rw-r--r--sound/soc/codecs/tas571x.c15
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c6
-rw-r--r--sound/soc/codecs/tlv320aic32x4-i2c.c19
-rw-r--r--sound/soc/codecs/tlv320aic32x4-spi.c18
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c5
-rw-r--r--sound/soc/codecs/tlv320aic32x4.h3
-rw-r--r--sound/soc/codecs/uda1334.c2
-rw-r--r--sound/soc/codecs/wcd9335.c18
-rw-r--r--sound/soc/codecs/wcd938x-sdw.c27
-rw-r--r--sound/soc/codecs/wcd938x.c80
-rw-r--r--sound/soc/codecs/wm5110.c6
-rw-r--r--sound/soc/codecs/wm8510.c2
-rw-r--r--sound/soc/codecs/wm8523.c2
-rw-r--r--sound/soc/codecs/wm8524.c2
-rw-r--r--sound/soc/codecs/wm8580.c28
-rw-r--r--sound/soc/codecs/wm8711.c2
-rw-r--r--sound/soc/codecs/wm8728.c2
-rw-r--r--sound/soc/codecs/wm8731-i2c.c2
-rw-r--r--sound/soc/codecs/wm8731-spi.c2
-rw-r--r--sound/soc/codecs/wm8737.c2
-rw-r--r--sound/soc/codecs/wm8741.c2
-rw-r--r--sound/soc/codecs/wm8750.c2
-rw-r--r--sound/soc/codecs/wm8753.c2
-rw-r--r--sound/soc/codecs/wm8770.c2
-rw-r--r--sound/soc/codecs/wm8776.c2
-rw-r--r--sound/soc/codecs/wm8782.c63
-rw-r--r--sound/soc/codecs/wm8804.c1
-rw-r--r--sound/soc/codecs/wm8962.c4
-rw-r--r--sound/soc/codecs/wm8974.c6
-rw-r--r--sound/soc/codecs/wm8994.c2
-rw-r--r--sound/soc/codecs/wm8995.c2
-rw-r--r--sound/soc/codecs/wm_adsp.c18
-rw-r--r--sound/soc/codecs/wsa883x.c7
-rw-r--r--sound/soc/dwc/dwc-i2s.c4
-rw-r--r--sound/soc/dwc/dwc-pcm.c4
-rw-r--r--sound/soc/fsl/Kconfig1
-rw-r--r--sound/soc/fsl/efika-audio-fabric.c4
-rw-r--r--sound/soc/fsl/eukrea-tlv320.c6
-rw-r--r--sound/soc/fsl/fsl-asoc-card.c29
-rw-r--r--sound/soc/fsl/fsl_asrc_dma.c10
-rw-r--r--sound/soc/fsl/fsl_aud2htx.c3
-rw-r--r--sound/soc/fsl/fsl_dma.c2
-rw-r--r--sound/soc/fsl/fsl_easrc.c8
-rw-r--r--sound/soc/fsl/fsl_mqs.c2
-rw-r--r--sound/soc/fsl/fsl_rpmsg.c3
-rw-r--r--sound/soc/fsl/fsl_sai.c24
-rw-r--r--sound/soc/fsl/fsl_spdif.c24
-rw-r--r--sound/soc/fsl/fsl_ssi.c16
-rw-r--r--sound/soc/fsl/fsl_xcvr.c14
-rw-r--r--sound/soc/fsl/imx-audmix.c18
-rw-r--r--sound/soc/fsl/imx-audmux.c1
-rw-r--r--sound/soc/fsl/imx-card.c9
-rw-r--r--sound/soc/fsl/imx-hdmi.c4
-rw-r--r--sound/soc/fsl/imx-pcm-rpmsg.c14
-rw-r--r--sound/soc/fsl/imx-rpmsg.c7
-rw-r--r--sound/soc/fsl/imx-sgtl5000.c2
-rw-r--r--sound/soc/fsl/imx-spdif.c2
-rw-r--r--sound/soc/fsl/mpc5200_dma.c25
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c3
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c7
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c8
-rw-r--r--sound/soc/fsl/p1022_ds.c8
-rw-r--r--sound/soc/fsl/p1022_rdk.c8
-rw-r--r--sound/soc/fsl/pcm030-audio-fabric.c3
-rw-r--r--sound/soc/generic/audio-graph-card.c116
-rw-r--r--sound/soc/generic/audio-graph-card2-custom-sample.c32
-rw-r--r--sound/soc/generic/audio-graph-card2.c110
-rw-r--r--sound/soc/generic/simple-card-utils.c221
-rw-r--r--sound/soc/generic/simple-card.c149
-rw-r--r--sound/soc/generic/test-component.c4
-rw-r--r--sound/soc/google/chv3-i2s.c22
-rw-r--r--sound/soc/img/img-i2s-in.c2
-rw-r--r--sound/soc/img/img-i2s-out.c2
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-pcm.c12
-rw-r--r--sound/soc/intel/avs/avs.h38
-rw-r--r--sound/soc/intel/avs/board_selection.c11
-rw-r--r--sound/soc/intel/avs/boards/Kconfig10
-rw-r--r--sound/soc/intel/avs/boards/Makefile2
-rw-r--r--sound/soc/intel/avs/boards/da7219.c21
-rw-r--r--sound/soc/intel/avs/boards/es8336.c26
-rw-r--r--sound/soc/intel/avs/boards/i2s_test.c57
-rw-r--r--sound/soc/intel/avs/boards/max98357a.c18
-rw-r--r--sound/soc/intel/avs/boards/max98373.c20
-rw-r--r--sound/soc/intel/avs/boards/max98927.c20
-rw-r--r--sound/soc/intel/avs/boards/nau8825.c26
-rw-r--r--sound/soc/intel/avs/boards/rt274.c22
-rw-r--r--sound/soc/intel/avs/boards/rt286.c27
-rw-r--r--sound/soc/intel/avs/boards/rt298.c26
-rw-r--r--sound/soc/intel/avs/boards/rt5514.c187
-rw-r--r--sound/soc/intel/avs/boards/rt5663.c26
-rw-r--r--sound/soc/intel/avs/boards/rt5682.c26
-rw-r--r--sound/soc/intel/avs/boards/ssm4567.c22
-rw-r--r--sound/soc/intel/avs/cldma.h4
-rw-r--r--sound/soc/intel/avs/core.c18
-rw-r--r--sound/soc/intel/avs/debugfs.c4
-rw-r--r--sound/soc/intel/avs/ipc.c52
-rw-r--r--sound/soc/intel/avs/loader.c4
-rw-r--r--sound/soc/intel/avs/messages.c112
-rw-r--r--sound/soc/intel/avs/messages.h4
-rw-r--r--sound/soc/intel/avs/path.c31
-rw-r--r--sound/soc/intel/avs/pcm.c78
-rw-r--r--sound/soc/intel/avs/probes.c2
-rw-r--r--sound/soc/intel/avs/registers.h4
-rw-r--r--sound/soc/intel/avs/topology.c102
-rw-r--r--sound/soc/intel/avs/utils.h65
-rw-r--r--sound/soc/intel/boards/Kconfig39
-rw-r--r--sound/soc/intel/boards/Makefile16
-rw-r--r--sound/soc/intel/boards/bdw-rt5650.c6
-rw-r--r--sound/soc/intel/boards/bdw-rt5677.c10
-rw-r--r--sound/soc/intel/boards/bdw_rt286.c8
-rw-r--r--sound/soc/intel/boards/bxt_da7219_max98357a.c8
-rw-r--r--sound/soc/intel/boards/bxt_rt298.c10
-rw-r--r--sound/soc/intel/boards/bytcht_cx2072x.c10
-rw-r--r--sound/soc/intel/boards/bytcht_da7213.c12
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c8
-rw-r--r--sound/soc/intel/boards/bytcht_nocodec.c4
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c10
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c10
-rw-r--r--sound/soc/intel/boards/bytcr_wm5102.c244
-rw-r--r--sound/soc/intel/boards/cht_bsw_max98090_ti.c8
-rw-r--r--sound/soc/intel/boards/cht_bsw_nau8824.c8
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5645.c16
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5672.c10
-rw-r--r--sound/soc/intel/boards/cml_rt1011_rt5682.c12
-rw-r--r--sound/soc/intel/boards/ehl_rt5660.c8
-rw-r--r--sound/soc/intel/boards/glk_rt5682_max98357a.c12
-rw-r--r--sound/soc/intel/boards/hsw_rt5640.c4
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98357a.c8
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98927.c10
-rw-r--r--sound/soc/intel/boards/kbl_rt5660.c8
-rw-r--r--sound/soc/intel/boards/kbl_rt5663_max98927.c12
-rw-r--r--sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c12
-rw-r--r--sound/soc/intel/boards/skl_hda_dsp_generic.c6
-rw-r--r--sound/soc/intel/boards/skl_nau88l25_max98357a.c14
-rw-r--r--sound/soc/intel/boards/skl_nau88l25_ssm4567.c18
-rw-r--r--sound/soc/intel/boards/skl_rt286.c10
-rw-r--r--sound/soc/intel/boards/sof_board_helpers.c204
-rw-r--r--sound/soc/intel/boards/sof_board_helpers.h64
-rw-r--r--sound/soc/intel/boards/sof_cirrus_common.c2
-rw-r--r--sound/soc/intel/boards/sof_cirrus_common.h9
-rw-r--r--sound/soc/intel/boards/sof_cs42l42.c354
-rw-r--r--sound/soc/intel/boards/sof_da7219.c (renamed from sound/soc/intel/boards/sof_da7219_max98373.c)409
-rw-r--r--sound/soc/intel/boards/sof_es8336.c14
-rw-r--r--sound/soc/intel/boards/sof_hdmi_common.h24
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.c8
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.h13
-rw-r--r--sound/soc/intel/boards/sof_nau8825.c373
-rw-r--r--sound/soc/intel/boards/sof_nuvoton_common.c73
-rw-r--r--sound/soc/intel/boards/sof_nuvoton_common.h22
-rw-r--r--sound/soc/intel/boards/sof_pcm512x.c14
-rw-r--r--sound/soc/intel/boards/sof_realtek_common.c8
-rw-r--r--sound/soc/intel/boards/sof_realtek_common.h37
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c730
-rw-r--r--sound/soc/intel/boards/sof_sdw.c324
-rw-r--r--sound/soc/intel/boards/sof_sdw_common.h21
-rw-r--r--sound/soc/intel/boards/sof_sdw_cs42l42.c2
-rw-r--r--sound/soc/intel/boards/sof_sdw_cs42l43.c156
-rw-r--r--sound/soc/intel/boards/sof_sdw_hdmi.c32
-rw-r--r--sound/soc/intel/boards/sof_sdw_maxim.c4
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt5682.c2
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt700.c2
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt711.c2
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt712_sdca.c6
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt_amp.c4
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c10
-rw-r--r--sound/soc/intel/boards/sof_ssp_amp.c339
-rw-r--r--sound/soc/intel/boards/sof_ssp_common.c101
-rw-r--r--sound/soc/intel/boards/sof_ssp_common.h71
-rw-r--r--sound/soc/intel/boards/sof_wm8804.c4
-rw-r--r--sound/soc/intel/catpt/pcm.c12
-rw-r--r--sound/soc/intel/common/Makefile1
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-adl-match.c19
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-arl-match.c51
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cht-match.c43
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-jsl-match.c12
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c150
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-rpl-match.c39
-rw-r--r--sound/soc/intel/keembay/kmb_platform.c17
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c44
-rw-r--r--sound/soc/intel/skylake/skl-sst-ipc.c4
-rw-r--r--sound/soc/intel/skylake/skl-sst-utils.c1
-rw-r--r--sound/soc/intel/skylake/skl.c32
-rw-r--r--sound/soc/kirkwood/armada-370-db.c4
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c2
-rw-r--r--sound/soc/loongson/loongson_card.c4
-rw-r--r--sound/soc/loongson/loongson_dma.c4
-rw-r--r--sound/soc/mediatek/Kconfig2
-rw-r--r--sound/soc/mediatek/common/mtk-afe-fe-dai.c22
-rw-r--r--sound/soc/mediatek/common/mtk-afe-platform-driver.c4
-rw-r--r--sound/soc/mediatek/common/mtk-dsp-sof-common.c113
-rw-r--r--sound/soc/mediatek/common/mtk-dsp-sof-common.h8
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-afe-pcm.c6
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-cs42448.c60
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-wm8960.c6
-rw-r--r--sound/soc/mediatek/mt6797/mt6797-afe-pcm.c6
-rw-r--r--sound/soc/mediatek/mt7986/mt7986-dai-etdm.c23
-rw-r--r--sound/soc/mediatek/mt7986/mt7986-wm8960.c43
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-afe-pcm.c4
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-max98090.c7
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c6
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c8
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650.c10
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-afe-pcm.c6
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c16
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-dai-i2s.c4
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c20
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-afe-gpio.c1
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-afe-pcm.c12
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-dai-adda.c2
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c2
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-dai-i2s.c4
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-dai-src.c4
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-dai-tdm.c2
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-common.c2
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c16
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c63
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-afe-pcm.c8
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-dai-etdm.c4
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-mt6359.c383
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-afe-gpio.c1
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-afe-pcm.c6
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-dai-adda.c4
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-dai-i2s.c4
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c24
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-pcm.c10
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-mt6359.c28
-rw-r--r--sound/soc/meson/aiu-fifo.c2
-rw-r--r--sound/soc/meson/axg-card.c14
-rw-r--r--sound/soc/meson/axg-fifo.c4
-rw-r--r--sound/soc/meson/axg-fifo.h2
-rw-r--r--sound/soc/meson/axg-tdm.h2
-rw-r--r--sound/soc/meson/gx-card.c4
-rw-r--r--sound/soc/meson/meson-card-utils.c10
-rw-r--r--sound/soc/meson/meson-card.h2
-rw-r--r--sound/soc/meson/meson-codec-glue.c2
-rw-r--r--sound/soc/mxs/mxs-saif.c1
-rw-r--r--sound/soc/mxs/mxs-sgtl5000.c7
-rw-r--r--sound/soc/pxa/pxa-ssp.c2
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c4
-rw-r--r--sound/soc/pxa/spitz.c8
-rw-r--r--sound/soc/qcom/apq8016_sbc.c9
-rw-r--r--sound/soc/qcom/apq8096.c10
-rw-r--r--sound/soc/qcom/common.c8
-rw-r--r--sound/soc/qcom/lpass-apq8016.c8
-rw-r--r--sound/soc/qcom/lpass-cdc-dma.c19
-rw-r--r--sound/soc/qcom/lpass-cpu.c49
-rw-r--r--sound/soc/qcom/lpass-ipq806x.c4
-rw-r--r--sound/soc/qcom/lpass-platform.c87
-rw-r--r--sound/soc/qcom/lpass-sc7180.c8
-rw-r--r--sound/soc/qcom/lpass-sc7280.c8
-rw-r--r--sound/soc/qcom/lpass.h4
-rw-r--r--sound/soc/qcom/qdsp6/q6afe-clocks.c1
-rw-r--r--sound/soc/qcom/qdsp6/q6afe-dai.c1
-rw-r--r--sound/soc/qcom/qdsp6/q6afe.c1
-rw-r--r--sound/soc/qcom/qdsp6/q6afe.h2
-rw-r--r--sound/soc/qcom/qdsp6/q6apm-dai.c6
-rw-r--r--sound/soc/qcom/qdsp6/q6apm-lpass-dais.c5
-rw-r--r--sound/soc/qcom/qdsp6/q6apm.h1
-rw-r--r--sound/soc/qcom/qdsp6/q6asm-dai.c13
-rw-r--r--sound/soc/qcom/qdsp6/q6asm.c1
-rw-r--r--sound/soc/qcom/qdsp6/q6asm.h1
-rw-r--r--sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c1
-rw-r--r--sound/soc/qcom/qdsp6/q6prm-clocks.c2
-rw-r--r--sound/soc/qcom/qdsp6/q6routing.c9
-rw-r--r--sound/soc/qcom/sc7180.c216
-rw-r--r--sound/soc/qcom/sc7280.c30
-rw-r--r--sound/soc/qcom/sc8280xp.c27
-rw-r--r--sound/soc/qcom/sdm845.c38
-rw-r--r--sound/soc/qcom/sdw.c8
-rw-r--r--sound/soc/qcom/sm8250.c12
-rw-r--r--sound/soc/qcom/storm.c4
-rw-r--r--sound/soc/rockchip/rk3288_hdmi_analog.c52
-rw-r--r--sound/soc/rockchip/rk3399_gru_sound.c28
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c10
-rw-r--r--sound/soc/rockchip/rockchip_i2s_tdm.c32
-rw-r--r--sound/soc/rockchip/rockchip_max98090.c12
-rw-r--r--sound/soc/rockchip/rockchip_pdm.c7
-rw-r--r--sound/soc/rockchip/rockchip_rt5645.c10
-rw-r--r--sound/soc/samsung/aries_wm8994.c13
-rw-r--r--sound/soc/samsung/arndale.c12
-rw-r--r--sound/soc/samsung/bells.c16
-rw-r--r--sound/soc/samsung/i2s.c14
-rw-r--r--sound/soc/samsung/littlemill.c16
-rw-r--r--sound/soc/samsung/lowland.c4
-rw-r--r--sound/soc/samsung/midas_wm1811.c12
-rw-r--r--sound/soc/samsung/odroid.c9
-rw-r--r--sound/soc/samsung/pcm.c8
-rw-r--r--sound/soc/samsung/smdk_spdif.c4
-rw-r--r--sound/soc/samsung/smdk_wm8994.c32
-rw-r--r--sound/soc/samsung/smdk_wm8994pcm.c6
-rw-r--r--sound/soc/samsung/snow.c5
-rw-r--r--sound/soc/samsung/spdif.c14
-rw-r--r--sound/soc/samsung/speyside.c12
-rw-r--r--sound/soc/samsung/tm2_wm5110.c24
-rw-r--r--sound/soc/samsung/tobermory.c8
-rw-r--r--sound/soc/sh/dma-sh7760.c34
-rw-r--r--sound/soc/sh/fsi.c5
-rw-r--r--sound/soc/sh/migor.c10
-rw-r--r--sound/soc/sh/rcar/core.c8
-rw-r--r--sound/soc/sh/rcar/rsnd.h4
-rw-r--r--sound/soc/sh/rcar/src.c1
-rw-r--r--sound/soc/sh/rcar/ssi.c2
-rw-r--r--sound/soc/sh/rz-ssi.c5
-rw-r--r--sound/soc/soc-component.c25
-rw-r--r--sound/soc/soc-compress.c36
-rw-r--r--sound/soc/soc-core.c20
-rw-r--r--sound/soc/soc-dai.c15
-rw-r--r--sound/soc/soc-dapm.c28
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c10
-rw-r--r--sound/soc/soc-link.c14
-rw-r--r--sound/soc/soc-ops.c2
-rw-r--r--sound/soc/soc-pcm.c116
-rw-r--r--sound/soc/soc-topology.c6
-rw-r--r--sound/soc/soc-utils.c6
-rw-r--r--sound/soc/sof/Kconfig2
-rw-r--r--sound/soc/sof/Makefile6
-rw-r--r--sound/soc/sof/amd/Kconfig9
-rw-r--r--sound/soc/sof/amd/Makefile2
-rw-r--r--sound/soc/sof/amd/acp-loader.c82
-rw-r--r--sound/soc/sof/amd/acp-pcm.c2
-rw-r--r--sound/soc/sof/amd/acp.c4
-rw-r--r--sound/soc/sof/amd/acp.h21
-rw-r--r--sound/soc/sof/amd/acp63.c146
-rw-r--r--sound/soc/sof/amd/pci-acp63.c106
-rw-r--r--sound/soc/sof/amd/pci-rmb.c10
-rw-r--r--sound/soc/sof/amd/pci-rn.c10
-rw-r--r--sound/soc/sof/amd/pci-vangogh.c10
-rw-r--r--sound/soc/sof/core.c17
-rw-r--r--sound/soc/sof/imx/imx8.c26
-rw-r--r--sound/soc/sof/imx/imx8m.c16
-rw-r--r--sound/soc/sof/imx/imx8ulp.c16
-rw-r--r--sound/soc/sof/intel/Kconfig14
-rw-r--r--sound/soc/sof/intel/Makefile3
-rw-r--r--sound/soc/sof/intel/apl.c4
-rw-r--r--sound/soc/sof/intel/bdw.c12
-rw-r--r--sound/soc/sof/intel/byt.c36
-rw-r--r--sound/soc/sof/intel/cnl.c4
-rw-r--r--sound/soc/sof/intel/hda-codec.c1
-rw-r--r--sound/soc/sof/intel/hda-common-ops.c2
-rw-r--r--sound/soc/sof/intel/hda-dai-ops.c26
-rw-r--r--sound/soc/sof/intel/hda-dai.c12
-rw-r--r--sound/soc/sof/intel/hda-dsp.c3
-rw-r--r--sound/soc/sof/intel/hda-loader.c44
-rw-r--r--sound/soc/sof/intel/hda-pcm.c4
-rw-r--r--sound/soc/sof/intel/hda-stream.c4
-rw-r--r--sound/soc/sof/intel/hda.c66
-rw-r--r--sound/soc/sof/intel/hda.h8
-rw-r--r--sound/soc/sof/intel/icl.c4
-rw-r--r--sound/soc/sof/intel/mtl.c3
-rw-r--r--sound/soc/sof/intel/pci-apl.c36
-rw-r--r--sound/soc/sof/intel/pci-cnl.c54
-rw-r--r--sound/soc/sof/intel/pci-icl.c36
-rw-r--r--sound/soc/sof/intel/pci-lnl.c10
-rw-r--r--sound/soc/sof/intel/pci-mtl.c43
-rw-r--r--sound/soc/sof/intel/pci-skl.c20
-rw-r--r--sound/soc/sof/intel/pci-tgl.c144
-rw-r--r--sound/soc/sof/intel/pci-tng.c10
-rw-r--r--sound/soc/sof/intel/telemetry.c95
-rw-r--r--sound/soc/sof/intel/telemetry.h35
-rw-r--r--sound/soc/sof/intel/tgl.c5
-rw-r--r--sound/soc/sof/ipc.c6
-rw-r--r--sound/soc/sof/ipc3-dtrace.c2
-rw-r--r--sound/soc/sof/ipc3-pcm.c6
-rw-r--r--sound/soc/sof/ipc3-topology.c2
-rw-r--r--sound/soc/sof/ipc4-control.c195
-rw-r--r--sound/soc/sof/ipc4-mtrace.c34
-rw-r--r--sound/soc/sof/ipc4-pcm.c118
-rw-r--r--sound/soc/sof/ipc4-priv.h3
-rw-r--r--sound/soc/sof/ipc4-telemetry.c95
-rw-r--r--sound/soc/sof/ipc4-telemetry.h73
-rw-r--r--sound/soc/sof/ipc4-topology.c137
-rw-r--r--sound/soc/sof/ipc4-topology.h56
-rw-r--r--sound/soc/sof/ipc4.c40
-rw-r--r--sound/soc/sof/mediatek/mt8186/mt8186.c31
-rw-r--r--sound/soc/sof/mediatek/mt8195/mt8195.c18
-rw-r--r--sound/soc/sof/nocodec.c2
-rw-r--r--sound/soc/sof/ops.h22
-rw-r--r--sound/soc/sof/pcm.c18
-rw-r--r--sound/soc/sof/sof-acpi-dev.c12
-rw-r--r--sound/soc/sof/sof-acpi-dev.h2
-rw-r--r--sound/soc/sof/sof-audio.c72
-rw-r--r--sound/soc/sof/sof-audio.h2
-rw-r--r--sound/soc/sof/sof-client-ipc-msg-injector.c4
-rw-r--r--sound/soc/sof/sof-client-probes.c6
-rw-r--r--sound/soc/sof/sof-client.c29
-rw-r--r--sound/soc/sof/sof-of-dev.c10
-rw-r--r--sound/soc/sof/sof-of-dev.h2
-rw-r--r--sound/soc/sof/sof-pci-dev.c17
-rw-r--r--sound/soc/sof/sof-priv.h4
-rw-r--r--sound/soc/sof/topology.c4
-rw-r--r--sound/soc/sof/xtensa/core.c11
-rw-r--r--sound/soc/sprd/sprd-pcm-compress.c4
-rw-r--r--sound/soc/sprd/sprd-pcm-dma.c4
-rw-r--r--sound/soc/starfive/Kconfig9
-rw-r--r--sound/soc/starfive/Makefile1
-rw-r--r--sound/soc/starfive/jh7110_pwmdac.c528
-rw-r--r--sound/soc/starfive/jh7110_tdm.c2
-rw-r--r--sound/soc/stm/stm32_adfsdm.c24
-rw-r--r--sound/soc/stm/stm32_i2s.c7
-rw-r--r--sound/soc/stm/stm32_sai.c8
-rw-r--r--sound/soc/stm/stm32_sai_sub.c10
-rw-r--r--sound/soc/stm/stm32_spdifrx.c8
-rw-r--r--sound/soc/sunxi/sun4i-codec.c16
-rw-r--r--sound/soc/sunxi/sun4i-i2s.c2
-rw-r--r--sound/soc/sunxi/sun4i-spdif.c7
-rw-r--r--sound/soc/sunxi/sun50i-codec-analog.c3
-rw-r--r--sound/soc/sunxi/sun50i-dmic.c4
-rw-r--r--sound/soc/sunxi/sun8i-codec-analog.c1
-rw-r--r--sound/soc/sunxi/sun8i-codec.c2
-rw-r--r--sound/soc/tegra/tegra186_asrc.c3
-rw-r--r--sound/soc/tegra/tegra186_dspk.c2
-rw-r--r--sound/soc/tegra/tegra20_spdif.c2
-rw-r--r--sound/soc/tegra/tegra210_adx.c3
-rw-r--r--sound/soc/tegra/tegra210_amx.c13
-rw-r--r--sound/soc/tegra/tegra210_dmic.c2
-rw-r--r--sound/soc/tegra/tegra210_i2s.c2
-rw-r--r--sound/soc/tegra/tegra210_mixer.c3
-rw-r--r--sound/soc/tegra/tegra210_mvc.c3
-rw-r--r--sound/soc/tegra/tegra210_ope.c3
-rw-r--r--sound/soc/tegra/tegra210_peq.c1
-rw-r--r--sound/soc/tegra/tegra210_sfc.c1
-rw-r--r--sound/soc/tegra/tegra30_i2s.c1
-rw-r--r--sound/soc/tegra/tegra_asoc_machine.c15
-rw-r--r--sound/soc/tegra/tegra_audio_graph_card.c24
-rw-r--r--sound/soc/tegra/tegra_pcm.c4
-rw-r--r--sound/soc/tegra/tegra_wm8903.c4
-rw-r--r--sound/soc/ti/Kconfig5
-rw-r--r--sound/soc/ti/ams-delta.c14
-rw-r--r--sound/soc/ti/davinci-evm.c17
-rw-r--r--sound/soc/ti/davinci-mcasp.c9
-rw-r--r--sound/soc/ti/j721e-evm.c12
-rw-r--r--sound/soc/ti/n810.c37
-rw-r--r--sound/soc/ti/omap-abe-twl6040.c10
-rw-r--r--sound/soc/ti/omap-dmic.c2
-rw-r--r--sound/soc/ti/omap-hdmi.c2
-rw-r--r--sound/soc/ti/omap-mcbsp-st.c2
-rw-r--r--sound/soc/ti/omap-mcbsp.c24
-rw-r--r--sound/soc/ti/omap-mcpdm.c4
-rw-r--r--sound/soc/ti/omap-twl4030.c22
-rw-r--r--sound/soc/ti/omap3pandora.c69
-rw-r--r--sound/soc/ti/osk5912.c5
-rw-r--r--sound/soc/ti/rx51.c25
-rw-r--r--sound/soc/uniphier/aio-compress.c22
-rw-r--r--sound/soc/uniphier/aio-cpu.c4
-rw-r--r--sound/soc/uniphier/aio-dma.c12
-rw-r--r--sound/soc/uniphier/aio-ld11.c2
-rw-r--r--sound/soc/uniphier/aio-pxs2.c2
-rw-r--r--sound/soc/uniphier/aio.h2
-rw-r--r--sound/soc/ux500/mop500_ab8500.c14
-rw-r--r--sound/soc/ux500/ux500_pcm.c4
-rw-r--r--sound/soc/xtensa/xtfpga-i2s.c4
-rw-r--r--sound/usb/Makefile2
-rw-r--r--sound/usb/caiaq/device.h2
-rw-r--r--sound/usb/mixer_quirks.c39
-rw-r--r--sound/usb/mixer_scarlett2.c (renamed from sound/usb/mixer_scarlett_gen2.c)610
-rw-r--r--sound/usb/mixer_scarlett2.h7
-rw-r--r--sound/usb/mixer_scarlett_gen2.h7
-rw-r--r--sound/usb/quirks.c2
-rw-r--r--sound/usb/usx2y/usbusx2y.h2
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c2
-rw-r--r--sound/virtio/virtio_pcm.c6
-rw-r--r--sound/virtio/virtio_pcm.h9
-rw-r--r--sound/virtio/virtio_pcm_msg.c79
-rw-r--r--sound/virtio/virtio_pcm_ops.c125
-rw-r--r--tools/arch/arm64/include/.gitignore1
-rw-r--r--tools/arch/arm64/include/asm/cputype.h5
-rw-r--r--tools/arch/arm64/include/asm/gpr-num.h26
-rw-r--r--tools/arch/arm64/include/asm/sysreg.h839
-rw-r--r--tools/arch/arm64/include/uapi/asm/kvm.h32
-rw-r--r--tools/arch/arm64/include/uapi/asm/perf_regs.h10
-rw-r--r--tools/arch/arm64/tools/Makefile38
-rw-r--r--tools/arch/ia64/include/asm/barrier.h59
-rw-r--r--tools/arch/ia64/include/uapi/asm/bitsperlong.h9
-rw-r--r--tools/arch/ia64/include/uapi/asm/mman.h7
-rw-r--r--tools/arch/parisc/include/uapi/asm/errno.h2
-rw-r--r--tools/arch/s390/include/uapi/asm/kvm.h16
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h16
-rw-r--r--tools/arch/x86/include/asm/disabled-features.h16
-rw-r--r--tools/arch/x86/include/asm/msr-index.h23
-rw-r--r--tools/arch/x86/include/uapi/asm/prctl.h12
-rw-r--r--tools/arch/x86/include/uapi/asm/unistd_32.h2
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-cgroup.rst16
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-net.rst8
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-prog.rst8
-rw-r--r--tools/bpf/bpftool/bash-completion/bpftool14
-rw-r--r--tools/bpf/bpftool/btf_dumper.c2
-rw-r--r--tools/bpf/bpftool/cgroup.c16
-rw-r--r--tools/bpf/bpftool/gen.c58
-rw-r--r--tools/bpf/bpftool/link.c15
-rw-r--r--tools/bpf/bpftool/net.c7
-rw-r--r--tools/bpf/bpftool/prog.c7
-rw-r--r--tools/bpf/bpftool/struct_ops.c6
-rw-r--r--tools/build/Makefile.build10
-rw-r--r--tools/build/feature/test-llvm.cpp14
-rw-r--r--tools/crypto/ccp/dbc.c17
-rw-r--r--tools/crypto/ccp/dbc.py8
-rwxr-xr-xtools/crypto/ccp/test_dbc.py45
-rw-r--r--tools/hv/hv_kvp_daemon.c20
-rwxr-xr-xtools/hv/hv_set_ifconfig.sh4
-rw-r--r--tools/iio/iio_event_monitor.c8
-rw-r--r--tools/iio/iio_generic_buffer.c13
-rw-r--r--tools/include/asm-generic/unaligned.h146
-rw-r--r--tools/include/io_uring/mini_liburing.h282
-rw-r--r--tools/include/linux/compiler.h8
-rw-r--r--tools/include/linux/const.h8
-rw-r--r--tools/include/linux/rwsem.h40
-rw-r--r--tools/include/nolibc/Makefile1
-rw-r--r--tools/include/nolibc/arch-aarch64.h3
-rw-r--r--tools/include/nolibc/arch-i386.h4
-rw-r--r--tools/include/nolibc/arch-loongarch.h4
-rw-r--r--tools/include/nolibc/arch-riscv.h3
-rw-r--r--tools/include/nolibc/arch-x86_64.h42
-rw-r--r--tools/include/nolibc/crt.h24
-rw-r--r--tools/include/nolibc/nolibc.h4
-rw-r--r--tools/include/nolibc/stdarg.h16
-rw-r--r--tools/include/nolibc/stdio.h3
-rw-r--r--tools/include/nolibc/string.h36
-rw-r--r--tools/include/nolibc/sys.h57
-rw-r--r--tools/include/perf/arm_pmuv3.h308
-rw-r--r--tools/include/uapi/asm-generic/unistd.h14
-rw-r--r--tools/include/uapi/drm/drm.h20
-rw-r--r--tools/include/uapi/drm/i915_drm.h8
-rw-r--r--tools/include/uapi/linux/bpf.h52
-rw-r--r--tools/include/uapi/linux/fs.h59
-rw-r--r--tools/include/uapi/linux/fscrypt.h3
-rw-r--r--tools/include/uapi/linux/if_link.h141
-rw-r--r--tools/include/uapi/linux/io_uring.h757
-rw-r--r--tools/include/uapi/linux/kvm.h24
-rw-r--r--tools/include/uapi/linux/mount.h3
-rw-r--r--tools/include/uapi/linux/netdev.h16
-rw-r--r--tools/include/uapi/linux/prctl.h3
-rw-r--r--tools/include/uapi/linux/vhost.h8
-rw-r--r--tools/lib/api/io.h1
-rw-r--r--tools/lib/bpf/bpf.c16
-rw-r--r--tools/lib/bpf/bpf.h5
-rw-r--r--tools/lib/bpf/bpf_helpers.h1
-rw-r--r--tools/lib/bpf/bpf_tracing.h2
-rw-r--r--tools/lib/bpf/btf.c160
-rw-r--r--tools/lib/bpf/elf.c143
-rw-r--r--tools/lib/bpf/libbpf.c237
-rw-r--r--tools/lib/bpf/libbpf.h88
-rw-r--r--tools/lib/bpf/libbpf.map8
-rw-r--r--tools/lib/bpf/ringbuf.c85
-rw-r--r--tools/lib/perf/evlist.c9
-rw-r--r--tools/lib/perf/include/internal/evlist.h2
-rw-r--r--tools/lib/perf/include/internal/rc_check.h13
-rw-r--r--tools/mm/page_owner_sort.c217
-rw-r--r--tools/net/ynl/Makefile1
-rw-r--r--tools/net/ynl/Makefile.deps1
-rwxr-xr-xtools/net/ynl/cli.py3
-rw-r--r--tools/net/ynl/generated/Makefile8
-rw-r--r--tools/net/ynl/generated/devlink-user.c3948
-rw-r--r--tools/net/ynl/generated/devlink-user.h3301
-rw-r--r--tools/net/ynl/generated/ethtool-user.c51
-rw-r--r--tools/net/ynl/generated/ethtool-user.h82
-rw-r--r--tools/net/ynl/generated/fou-user.c6
-rw-r--r--tools/net/ynl/generated/fou-user.h2
-rw-r--r--tools/net/ynl/generated/handshake-user.c3
-rw-r--r--tools/net/ynl/generated/handshake-user.h12
-rw-r--r--tools/net/ynl/generated/netdev-user.c19
-rw-r--r--tools/net/ynl/generated/netdev-user.h7
-rw-r--r--tools/net/ynl/generated/nfsd-user.c203
-rw-r--r--tools/net/ynl/generated/nfsd-user.h67
-rw-r--r--tools/net/ynl/lib/nlspec.py6
-rw-r--r--tools/net/ynl/lib/ynl.c12
-rw-r--r--tools/net/ynl/lib/ynl.h22
-rw-r--r--tools/net/ynl/lib/ynl.py77
-rw-r--r--tools/net/ynl/samples/Makefile3
-rw-r--r--tools/net/ynl/samples/netdev.c8
-rwxr-xr-xtools/net/ynl/ynl-gen-c.py310
-rw-r--r--tools/objtool/arch/x86/decode.c6
-rw-r--r--tools/objtool/check.c16
-rw-r--r--tools/objtool/elf.c14
-rw-r--r--tools/objtool/noreturns.h4
-rw-r--r--tools/objtool/objtool.c4
-rw-r--r--tools/perf/Documentation/perf-bench.txt19
-rw-r--r--tools/perf/Documentation/perf-kwork.txt38
-rw-r--r--tools/perf/Documentation/perf-lock.txt7
-rw-r--r--tools/perf/Documentation/perf-record.txt3
-rw-r--r--tools/perf/MANIFEST2
-rw-r--r--tools/perf/Makefile.config85
-rw-r--r--tools/perf/Makefile.perf39
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c35
-rw-r--r--tools/perf/arch/arm/util/pmu.c10
-rw-r--r--tools/perf/arch/arm64/util/arm-spe.c48
-rw-r--r--tools/perf/arch/arm64/util/pmu.c20
-rw-r--r--tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl6
-rw-r--r--tools/perf/arch/powerpc/entry/syscalls/syscall.tbl6
-rw-r--r--tools/perf/arch/powerpc/util/header.c2
-rw-r--r--tools/perf/arch/s390/entry/syscalls/syscall.tbl6
-rw-r--r--tools/perf/arch/s390/util/pmu.c3
-rw-r--r--tools/perf/arch/x86/annotate/instructions.c9
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl5
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c42
-rw-r--r--tools/perf/arch/x86/util/pmu.c145
-rw-r--r--tools/perf/bench/sched-messaging.c102
-rw-r--r--tools/perf/bench/sched-pipe.c132
-rw-r--r--tools/perf/bench/uprobe.c1
-rw-r--r--tools/perf/builtin-buildid-cache.c6
-rw-r--r--tools/perf/builtin-kwork.c760
-rw-r--r--tools/perf/builtin-list.c6
-rw-r--r--tools/perf/builtin-lock.c117
-rw-r--r--tools/perf/builtin-record.c92
-rw-r--r--tools/perf/builtin-report.c15
-rw-r--r--tools/perf/builtin-sched.c2
-rw-r--r--tools/perf/builtin-script.c2
-rw-r--r--tools/perf/builtin-stat.c2
-rw-r--r--tools/perf/builtin-version.c1
-rwxr-xr-xtools/perf/check-headers.sh1
-rw-r--r--tools/perf/dlfilters/dlfilter-test-api-v0.c12
-rw-r--r--tools/perf/dlfilters/dlfilter-test-api-v2.c12
-rw-r--r--tools/perf/perf-completion.sh10
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/ampereone/metrics.json420
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cmn/sys/cmn.json266
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cmn/sys/metric.json74
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/branch.json8
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/bus.json18
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/cache.json155
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/exception.json45
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/fp_operation.json10
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/general.json10
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/instruction.json119
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l1d_cache.json54
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l1i_cache.json14
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l2_cache.json50
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l3_cache.json22
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/ll_cache.json10
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/memory.json21
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/metrics.json233
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/pipeline.json23
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/retired.json30
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/spe.json18
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/spec_operation.json110
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/stall.json30
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/sve.json30
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/tlb.json66
-rw-r--r--tools/perf/pmu-events/arch/arm64/mapfile.csv2
-rw-r--r--tools/perf/pmu-events/arch/nds32/mapfile.csv2
-rw-r--r--tools/perf/pmu-events/arch/powerpc/mapfile.csv8
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power10/datasource.json1787
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power10/metrics.json388
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power10/others.json10
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power10/pmc.json2
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power10/translation.json5
-rw-r--r--tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json8
-rw-r--r--tools/perf/pmu-events/arch/x86/alderlake/adl-metrics.json8
-rw-r--r--tools/perf/pmu-events/arch/x86/alderlake/frontend.json42
-rw-r--r--tools/perf/pmu-events/arch/x86/alderlake/memory.json4
-rw-r--r--tools/perf/pmu-events/arch/x86/alderlake/pipeline.json22
-rw-r--r--tools/perf/pmu-events/arch/x86/alderlake/uncore-interconnect.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/alderlaken/adln-metrics.json6
-rw-r--r--tools/perf/pmu-events/arch/x86/alderlaken/memory.json4
-rw-r--r--tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json16
-rw-r--r--tools/perf/pmu-events/arch/x86/alderlaken/uncore-interconnect.json66
-rw-r--r--tools/perf/pmu-events/arch/x86/bonnell/frontend.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json14
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/uncore-interconnect.json18
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json18
-rw-r--r--tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/cache.json888
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/floating-point.json193
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/frontend.json389
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/memory.json343
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/other.json315
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/pipeline.json975
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-cache.json5988
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-cxl.json450
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-interconnect.json6199
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-io.json3587
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-memory.json3308
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-power.json197
-rw-r--r--tools/perf/pmu-events/arch/x86/emeraldrapids/virtual-memory.json165
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json18
-rw-r--r--tools/perf/pmu-events/arch/x86/icelake/icl-metrics.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/icelakex/icx-metrics.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/ivybridge/cache.json8
-rw-r--r--tools/perf/pmu-events/arch/x86/ivybridge/floating-point.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/ivybridge/frontend.json18
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/cache.json4
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json20
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json18
-rw-r--r--tools/perf/pmu-events/arch/x86/knightslanding/cache.json39
-rw-r--r--tools/perf/pmu-events/arch/x86/knightslanding/floating-point.json8
-rw-r--r--tools/perf/pmu-events/arch/x86/knightslanding/pipeline.json55
-rw-r--r--tools/perf/pmu-events/arch/x86/knightslanding/uncore-cache.json26
-rw-r--r--tools/perf/pmu-events/arch/x86/knightslanding/virtual-memory.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/lunarlake/cache.json219
-rw-r--r--tools/perf/pmu-events/arch/x86/lunarlake/frontend.json27
-rw-r--r--tools/perf/pmu-events/arch/x86/lunarlake/memory.json183
-rw-r--r--tools/perf/pmu-events/arch/x86/lunarlake/other.json62
-rw-r--r--tools/perf/pmu-events/arch/x86/lunarlake/pipeline.json217
-rw-r--r--tools/perf/pmu-events/arch/x86/lunarlake/virtual-memory.json56
-rw-r--r--tools/perf/pmu-events/arch/x86/mapfile.csv38
-rw-r--r--tools/perf/pmu-events/arch/x86/meteorlake/cache.json30
-rw-r--r--tools/perf/pmu-events/arch/x86/meteorlake/frontend.json29
-rw-r--r--tools/perf/pmu-events/arch/x86/meteorlake/memory.json37
-rw-r--r--tools/perf/pmu-events/arch/x86/meteorlake/other.json40
-rw-r--r--tools/perf/pmu-events/arch/x86/meteorlake/pipeline.json68
-rw-r--r--tools/perf/pmu-events/arch/x86/meteorlake/uncore-other.json9
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemep/cache.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemep/floating-point.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemex/cache.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/nehalemex/floating-point.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/rocketlake/rkl-metrics.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/sapphirerapids/frontend.json39
-rw-r--r--tools/perf/pmu-events/arch/x86/sapphirerapids/spr-metrics.json7
-rw-r--r--tools/perf/pmu-events/arch/x86/sapphirerapids/uncore-cache.json20
-rw-r--r--tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/tigerlake/tgl-metrics.json14
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-dp/floating-point.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-sp/cache.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereep-sp/floating-point.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereex/cache.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereex/floating-point.json2
-rw-r--r--tools/perf/pmu-events/arch/x86/westmereex/pipeline.json2
-rw-r--r--tools/perf/pmu-events/empty-pmu-events.c8
-rwxr-xr-xtools/perf/pmu-events/jevents.py124
-rw-r--r--tools/perf/pmu-events/metric.py3
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/attr/system-wide-dummy14
-rw-r--r--tools/perf/tests/attr/test-record-C04
-rw-r--r--tools/perf/tests/attr/test-record-dummy-C055
-rw-r--r--tools/perf/tests/builtin-test.c1
-rw-r--r--tools/perf/tests/code-reading.c10
-rw-r--r--tools/perf/tests/expr.c33
-rw-r--r--tools/perf/tests/hists_link.c4
-rw-r--r--tools/perf/tests/make7
-rw-r--r--tools/perf/tests/parse-events.c51
-rw-r--r--tools/perf/tests/pmu-events.c65
-rw-r--r--tools/perf/tests/pmu.c23
-rwxr-xr-xtools/perf/tests/shell/coresight/asm_pure_loop.sh4
-rwxr-xr-xtools/perf/tests/shell/coresight/memcpy_thread_16k_10.sh4
-rwxr-xr-xtools/perf/tests/shell/coresight/thread_loop_check_tid_10.sh4
-rwxr-xr-xtools/perf/tests/shell/coresight/thread_loop_check_tid_2.sh4
-rwxr-xr-xtools/perf/tests/shell/coresight/unroll_loop_thread_10.sh4
-rw-r--r--tools/perf/tests/shell/lib/coresight.sh2
-rwxr-xr-xtools/perf/tests/shell/lock_contention.sh52
-rwxr-xr-xtools/perf/tests/shell/probe_vfs_getname.sh2
-rwxr-xr-xtools/perf/tests/shell/record+probe_libc_inet_pton.sh2
-rwxr-xr-xtools/perf/tests/shell/record+script_probe_vfs_getname.sh2
-rwxr-xr-xtools/perf/tests/shell/record.sh1
-rwxr-xr-xtools/perf/tests/shell/record_offcpu.sh2
-rwxr-xr-xtools/perf/tests/shell/record_sideband.sh58
-rwxr-xr-xtools/perf/tests/shell/stat+csv_output.sh1
-rwxr-xr-xtools/perf/tests/shell/stat+csv_summary.sh4
-rwxr-xr-xtools/perf/tests/shell/stat+shadow_stat.sh34
-rwxr-xr-xtools/perf/tests/shell/stat+std_output.sh1
-rwxr-xr-xtools/perf/tests/shell/stat_all_metricgroups.sh16
-rwxr-xr-xtools/perf/tests/shell/test_arm_coresight.sh4
-rwxr-xr-xtools/perf/tests/shell/test_intel_pt.sh1
-rwxr-xr-xtools/perf/tests/shell/trace+probe_vfs_getname.sh1
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/tests/thread-maps-share.c9
-rw-r--r--tools/perf/tests/util.c31
-rw-r--r--tools/perf/trace/beauty/include/linux/socket.h1
-rw-r--r--tools/perf/ui/browsers/hists.c6
-rw-r--r--tools/perf/util/Build4
-rw-r--r--tools/perf/util/arm-spe.h4
-rw-r--r--tools/perf/util/bpf-filter.y4
-rw-r--r--tools/perf/util/bpf_counter.c5
-rw-r--r--tools/perf/util/bpf_kwork_top.c308
-rw-r--r--tools/perf/util/bpf_lock_contention.c52
-rw-r--r--tools/perf/util/bpf_off_cpu.c13
-rw-r--r--tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c16
-rw-r--r--tools/perf/util/bpf_skel/kwork_top.bpf.c338
-rw-r--r--tools/perf/util/bpf_skel/lock_contention.bpf.c145
-rw-r--r--tools/perf/util/bpf_skel/lock_data.h3
-rw-r--r--tools/perf/util/bpf_skel/vmlinux/.gitignore1
-rw-r--r--tools/perf/util/branch.c4
-rw-r--r--tools/perf/util/branch.h4
-rw-r--r--tools/perf/util/callchain.c76
-rw-r--r--tools/perf/util/callchain.h18
-rw-r--r--tools/perf/util/cgroup.c63
-rw-r--r--tools/perf/util/cgroup.h5
-rw-r--r--tools/perf/util/cs-etm.c106
-rw-r--r--tools/perf/util/cs-etm.h2
-rw-r--r--tools/perf/util/data.c12
-rw-r--r--tools/perf/util/dlfilter.c36
-rw-r--r--tools/perf/util/dso.c2
-rw-r--r--tools/perf/util/dso.h2
-rw-r--r--tools/perf/util/env.c6
-rw-r--r--tools/perf/util/evlist.c23
-rw-r--r--tools/perf/util/evlist.h1
-rw-r--r--tools/perf/util/evsel.c43
-rw-r--r--tools/perf/util/evsel.h5
-rw-r--r--tools/perf/util/expr.c2
-rw-r--r--tools/perf/util/expr.y2
-rw-r--r--tools/perf/util/header.c60
-rw-r--r--tools/perf/util/hisi-ptt.c4
-rw-r--r--tools/perf/util/hist.c32
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c43
-rw-r--r--tools/perf/util/intel-pt.c2
-rw-r--r--tools/perf/util/intel-pt.h3
-rw-r--r--tools/perf/util/jitdump.c1
-rw-r--r--tools/perf/util/kwork.h61
-rw-r--r--tools/perf/util/lock-contention.h10
-rw-r--r--tools/perf/util/machine.c37
-rw-r--r--tools/perf/util/machine.h1
-rw-r--r--tools/perf/util/map_symbol.c15
-rw-r--r--tools/perf/util/map_symbol.h4
-rw-r--r--tools/perf/util/mem-events.c3
-rw-r--r--tools/perf/util/metricgroup.c4
-rw-r--r--tools/perf/util/parse-events.c213
-rw-r--r--tools/perf/util/parse-events.h34
-rw-r--r--tools/perf/util/parse-events.l6
-rw-r--r--tools/perf/util/parse-events.y68
-rw-r--r--tools/perf/util/pfm.c15
-rw-r--r--tools/perf/util/pmu.c181
-rw-r--r--tools/perf/util/pmu.h34
-rw-r--r--tools/perf/util/pmu.y4
-rw-r--r--tools/perf/util/pmus.c18
-rw-r--r--tools/perf/util/print-events.c28
-rw-r--r--tools/perf/util/python-ext-sources1
-rw-r--r--tools/perf/util/python.c2
-rw-r--r--tools/perf/util/rlimit.c28
-rw-r--r--tools/perf/util/rlimit.h11
-rw-r--r--tools/perf/util/rwsem.c34
-rw-r--r--tools/perf/util/rwsem.h11
-rw-r--r--tools/perf/util/sort.c2
-rw-r--r--tools/perf/util/string.c48
-rw-r--r--tools/perf/util/string2.h1
-rw-r--r--tools/perf/util/svghelper.c5
-rw-r--r--tools/perf/util/symbol-elf.c4
-rw-r--r--tools/perf/util/symbol.c15
-rw-r--r--tools/perf/util/trace-event-info.c3
-rw-r--r--tools/power/cpupower/man/cpupower-powercap-info.12
-rwxr-xr-xtools/power/pm-graph/sleepgraph.py2
-rwxr-xr-xtools/power/x86/amd_pstate_tracer/amd_pstate_trace.py3
-rw-r--r--tools/power/x86/intel-speed-select/isst-config.c213
-rw-r--r--tools/power/x86/intel-speed-select/isst-daemon.c3
-rw-r--r--tools/power/x86/intel-speed-select/isst.h3
-rwxr-xr-xtools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py12
-rw-r--r--tools/power/x86/turbostat/turbostat.c2884
-rw-r--r--tools/scripts/Makefile.include10
-rw-r--r--tools/testing/cxl/Kbuild1
-rw-r--r--tools/testing/cxl/cxl_core_exports.c7
-rw-r--r--tools/testing/cxl/test/cxl.c7
-rw-r--r--tools/testing/cxl/test/mem.c83
-rw-r--r--tools/testing/nvdimm/test/ndtest.c17
-rw-r--r--tools/testing/nvdimm/test/nfit.c14
-rw-r--r--tools/testing/radix-tree/linux.c4
-rw-r--r--tools/testing/selftests/Makefile24
-rw-r--r--tools/testing/selftests/alsa/alsa-local.h10
-rw-r--r--tools/testing/selftests/alsa/conf.c100
-rw-r--r--tools/testing/selftests/alsa/pcm-test.c10
-rwxr-xr-xtools/testing/selftests/amd-pstate/gitsource.sh17
-rwxr-xr-xtools/testing/selftests/amd-pstate/run.sh21
-rwxr-xr-xtools/testing/selftests/amd-pstate/tbench.sh4
-rw-r--r--tools/testing/selftests/arm64/abi/hwcap.c54
-rw-r--r--tools/testing/selftests/arm64/fp/sve-test.S19
-rw-r--r--tools/testing/selftests/arm64/fp/za-fork.c2
-rw-r--r--tools/testing/selftests/bpf/DENYLIST.aarch642
-rw-r--r--tools/testing/selftests/bpf/DENYLIST.s390x26
-rw-r--r--tools/testing/selftests/bpf/Makefile56
-rw-r--r--tools/testing/selftests/bpf/bpf_experimental.h346
-rw-r--r--tools/testing/selftests/bpf/bpf_kfuncs.h14
-rw-r--r--tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c11
-rw-r--r--tools/testing/selftests/bpf/bpf_testmod/bpf_testmod_kfunc.h2
-rw-r--r--tools/testing/selftests/bpf/cgroup_helpers.c38
-rw-r--r--tools/testing/selftests/bpf/config2
-rw-r--r--tools/testing/selftests/bpf/config.x86_641
-rw-r--r--tools/testing/selftests/bpf/liburandom_read.map15
-rw-r--r--tools/testing/selftests/bpf/map_tests/map_in_map_batch_ops.c4
-rw-r--r--tools/testing/selftests/bpf/map_tests/map_percpu_stats.c20
-rw-r--r--tools/testing/selftests/bpf/netlink_helpers.c358
-rw-r--r--tools/testing/selftests/bpf/netlink_helpers.h46
-rw-r--r--tools/testing/selftests/bpf/network_helpers.c34
-rw-r--r--tools/testing/selftests/bpf/network_helpers.h1
-rw-r--r--tools/testing/selftests/bpf/prog_tests/align.c241
-rw-r--r--tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/bpf_iter.c44
-rw-r--r--tools/testing/selftests/bpf/prog_tests/btf.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/cgroup_iter.c33
-rw-r--r--tools/testing/selftests/bpf/prog_tests/connect_ping.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/exceptions.c409
-rw-r--r--tools/testing/selftests/bpf/prog_tests/fib_lookup.c83
-rw-r--r--tools/testing/selftests/bpf/prog_tests/fill_link_info.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/iters.c209
-rw-r--r--tools/testing/selftests/bpf/prog_tests/kprobe_multi_testmod_test.c20
-rw-r--r--tools/testing/selftests/bpf/prog_tests/libbpf_str.c6
-rw-r--r--tools/testing/selftests/bpf/prog_tests/linked_list.c16
-rw-r--r--tools/testing/selftests/bpf/prog_tests/lwt_helpers.h3
-rw-r--r--tools/testing/selftests/bpf/prog_tests/missed.c138
-rw-r--r--tools/testing/selftests/bpf/prog_tests/module_fentry_shadow.c5
-rw-r--r--tools/testing/selftests/bpf/prog_tests/percpu_alloc.c128
-rw-r--r--tools/testing/selftests/bpf/prog_tests/preempted_bpf_ma_op.c89
-rw-r--r--tools/testing/selftests/bpf/prog_tests/queue_stack_map.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/ringbuf.c26
-rw-r--r--tools/testing/selftests/bpf/prog_tests/ringbuf_multi.c15
-rw-r--r--tools/testing/selftests/bpf/prog_tests/section_names.c45
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sock_addr.c612
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sockmap_basic.c8
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sockmap_listen.c189
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sockopt.c113
-rw-r--r--tools/testing/selftests/bpf/prog_tests/tailcalls.c353
-rw-r--r--tools/testing/selftests/bpf/prog_tests/task_under_cgroup.c11
-rw-r--r--tools/testing/selftests/bpf/prog_tests/tc_helpers.h20
-rw-r--r--tools/testing/selftests/bpf/prog_tests/tc_links.c64
-rw-r--r--tools/testing/selftests/bpf/prog_tests/tc_netkit.c687
-rw-r--r--tools/testing/selftests/bpf/prog_tests/tc_opts.c400
-rw-r--r--tools/testing/selftests/bpf/prog_tests/tc_redirect.c317
-rw-r--r--tools/testing/selftests/bpf/prog_tests/test_bpf_ma.c20
-rw-r--r--tools/testing/selftests/bpf/prog_tests/test_bpffs.c11
-rw-r--r--tools/testing/selftests/bpf/prog_tests/timer.c10
-rw-r--r--tools/testing/selftests/bpf/prog_tests/uprobe.c95
-rw-r--r--tools/testing/selftests/bpf/prog_tests/verifier.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/xdp_metadata.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_task_vmas.c (renamed from tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c)0
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_tasks.c (renamed from tools/testing/selftests/bpf/progs/bpf_iter_task.c)0
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_loop_bench.c13
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_misc.h3
-rw-r--r--tools/testing/selftests/bpf/progs/cb_refs.c1
-rw-r--r--tools/testing/selftests/bpf/progs/connect_unix_prog.c40
-rw-r--r--tools/testing/selftests/bpf/progs/exceptions.c368
-rw-r--r--tools/testing/selftests/bpf/progs/exceptions_assert.c135
-rw-r--r--tools/testing/selftests/bpf/progs/exceptions_ext.c72
-rw-r--r--tools/testing/selftests/bpf/progs/exceptions_fail.c349
-rw-r--r--tools/testing/selftests/bpf/progs/getpeername_unix_prog.c39
-rw-r--r--tools/testing/selftests/bpf/progs/getsockname_unix_prog.c39
-rw-r--r--tools/testing/selftests/bpf/progs/iters.c695
-rw-r--r--tools/testing/selftests/bpf/progs/iters_css.c72
-rw-r--r--tools/testing/selftests/bpf/progs/iters_css_task.c102
-rw-r--r--tools/testing/selftests/bpf/progs/iters_task.c41
-rw-r--r--tools/testing/selftests/bpf/progs/iters_task_failure.c105
-rw-r--r--tools/testing/selftests/bpf/progs/iters_task_vma.c44
-rw-r--r--tools/testing/selftests/bpf/progs/linked_list_fail.c4
-rw-r--r--tools/testing/selftests/bpf/progs/missed_kprobe.c30
-rw-r--r--tools/testing/selftests/bpf/progs/missed_kprobe_recursion.c48
-rw-r--r--tools/testing/selftests/bpf/progs/missed_tp_recursion.c41
-rw-r--r--tools/testing/selftests/bpf/progs/percpu_alloc_array.c190
-rw-r--r--tools/testing/selftests/bpf/progs/percpu_alloc_cgrp_local_storage.c109
-rw-r--r--tools/testing/selftests/bpf/progs/percpu_alloc_fail.c164
-rw-r--r--tools/testing/selftests/bpf/progs/preempted_bpf_ma_op.c106
-rw-r--r--tools/testing/selftests/bpf/progs/profiler.inc.h2
-rw-r--r--tools/testing/selftests/bpf/progs/recvmsg_unix_prog.c39
-rw-r--r--tools/testing/selftests/bpf/progs/sendmsg_unix_prog.c40
-rw-r--r--tools/testing/selftests/bpf/progs/strobemeta.h78
-rw-r--r--tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_fentry.c18
-rw-r--r--tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_fexit.c18
-rw-r--r--tools/testing/selftests/bpf/progs/tailcall_poke.c32
-rw-r--r--tools/testing/selftests/bpf/progs/test_bpf_ma.c180
-rw-r--r--tools/testing/selftests/bpf/progs/test_ldsx_insn.c10
-rw-r--r--tools/testing/selftests/bpf/progs/test_sockmap_listen.c7
-rw-r--r--tools/testing/selftests/bpf/progs/test_task_under_cgroup.c28
-rw-r--r--tools/testing/selftests/bpf/progs/test_tc_link.c13
-rw-r--r--tools/testing/selftests/bpf/progs/test_uprobe.c61
-rw-r--r--tools/testing/selftests/bpf/progs/test_vmlinux.c4
-rw-r--r--tools/testing/selftests/bpf/progs/timer.c63
-rw-r--r--tools/testing/selftests/bpf/progs/timer_failure.c47
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_bswap.c5
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_cfg.c62
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_gotol.c5
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c242
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_ldsx.c153
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_loops1.c9
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_movsx.c5
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_precision.c133
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_sdiv.c5
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_subprog_precision.c86
-rw-r--r--tools/testing/selftests/bpf/progs/xdp_hw_metadata.c2
-rw-r--r--tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c88
-rw-r--r--tools/testing/selftests/bpf/progs/xsk_xdp_progs.c22
-rwxr-xr-xtools/testing/selftests/bpf/test_bpftool_synctypes.py9
-rw-r--r--tools/testing/selftests/bpf/test_loader.c4
-rw-r--r--tools/testing/selftests/bpf/test_progs.c2
-rw-r--r--tools/testing/selftests/bpf/test_progs.h2
-rwxr-xr-xtools/testing/selftests/bpf/test_xsk.sh40
-rw-r--r--tools/testing/selftests/bpf/trace_helpers.c134
-rw-r--r--tools/testing/selftests/bpf/trace_helpers.h8
-rw-r--r--tools/testing/selftests/bpf/unpriv_helpers.c33
-rw-r--r--tools/testing/selftests/bpf/urandom_read.c15
-rw-r--r--tools/testing/selftests/bpf/urandom_read_lib1.c22
-rw-r--r--tools/testing/selftests/bpf/verifier/bpf_st_mem.c32
-rw-r--r--tools/testing/selftests/bpf/verifier/calls.c6
-rw-r--r--tools/testing/selftests/bpf/verifier/ld_imm64.c8
-rw-r--r--tools/testing/selftests/bpf/xdp_features.c4
-rw-r--r--tools/testing/selftests/bpf/xdp_hw_metadata.c80
-rw-r--r--tools/testing/selftests/bpf/xsk.c3
-rw-r--r--tools/testing/selftests/bpf/xsk.h2
-rwxr-xr-xtools/testing/selftests/bpf/xsk_prereqs.sh10
-rw-r--r--tools/testing/selftests/bpf/xsk_xdp_common.h12
-rw-r--r--tools/testing/selftests/bpf/xsk_xdp_metadata.h5
-rw-r--r--tools/testing/selftests/bpf/xskxceiver.c1037
-rw-r--r--tools/testing/selftests/bpf/xskxceiver.h57
-rw-r--r--tools/testing/selftests/cachestat/test_cachestat.c2
-rw-r--r--tools/testing/selftests/capabilities/Makefile2
-rw-r--r--tools/testing/selftests/capabilities/test_execve.c8
-rw-r--r--tools/testing/selftests/capabilities/validate_cap.c8
-rw-r--r--tools/testing/selftests/cgroup/.gitignore1
-rw-r--r--tools/testing/selftests/cgroup/Makefile2
-rwxr-xr-xtools/testing/selftests/cgroup/test_cpuset_prs.sh467
-rw-r--r--tools/testing/selftests/cgroup/test_hugetlb_memcg.c234
-rw-r--r--tools/testing/selftests/cgroup/test_zswap.c48
-rw-r--r--tools/testing/selftests/clone3/clone3.c272
-rw-r--r--tools/testing/selftests/clone3/clone3_cap_checkpoint_restore.c2
-rw-r--r--tools/testing/selftests/clone3/clone3_clear_sighand.c4
-rw-r--r--tools/testing/selftests/clone3/clone3_selftests.h13
-rw-r--r--tools/testing/selftests/clone3/clone3_set_tid.c2
-rw-r--r--tools/testing/selftests/core/close_range_test.c28
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/damon/debugfs_attrs.sh0
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/damon/debugfs_duplicate_context_creation.sh0
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/damon/debugfs_empty_targets.sh0
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/damon/debugfs_huge_count_read_write.sh0
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/damon/debugfs_rm_non_contexts.sh0
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/damon/debugfs_schemes.sh0
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/damon/debugfs_target_ids.sh0
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/damon/lru_sort.sh0
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/damon/reclaim.sh0
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/damon/sysfs.sh1
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/damon/sysfs_update_removed_scheme_dir.sh0
-rw-r--r--tools/testing/selftests/dmabuf-heaps/.gitignore1
-rwxr-xr-xtools/testing/selftests/drivers/net/netdevsim/devlink.sh21
-rw-r--r--tools/testing/selftests/dt/.gitignore1
-rw-r--r--tools/testing/selftests/dt/Makefile21
-rw-r--r--tools/testing/selftests/dt/compatible_ignore_list1
-rw-r--r--tools/testing/selftests/dt/ktap_helpers.sh70
-rwxr-xr-xtools/testing/selftests/dt/test_unprobed_devices.sh83
-rw-r--r--tools/testing/selftests/efivarfs/create-read.c2
-rw-r--r--tools/testing/selftests/exec/execveat.c87
-rw-r--r--tools/testing/selftests/firmware/fw_namespace.c4
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_char.tc10
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc7
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc4
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_non_uniq_symbol.tc13
-rw-r--r--tools/testing/selftests/hid/Makefile10
-rw-r--r--tools/testing/selftests/hid/config.common1
-rw-r--r--tools/testing/selftests/hid/progs/hid.c3
-rw-r--r--tools/testing/selftests/hid/progs/hid_bpf_helpers.h77
-rw-r--r--tools/testing/selftests/iommu/iommufd.c379
-rw-r--r--tools/testing/selftests/iommu/iommufd_fail_nth.c7
-rw-r--r--tools/testing/selftests/iommu/iommufd_utils.h232
-rw-r--r--tools/testing/selftests/kselftest.h46
-rw-r--r--tools/testing/selftests/kvm/Makefile28
-rw-r--r--tools/testing/selftests/kvm/aarch64/aarch32_id_regs.c4
-rw-r--r--tools/testing/selftests/kvm/aarch64/debug-exceptions.c12
-rw-r--r--tools/testing/selftests/kvm/aarch64/page_fault_test.c11
-rw-r--r--tools/testing/selftests/kvm/aarch64/set_id_regs.c481
-rw-r--r--tools/testing/selftests/kvm/aarch64/vpmu_counter_access.c670
-rw-r--r--tools/testing/selftests/kvm/include/aarch64/processor.h1
-rw-r--r--tools/testing/selftests/kvm/include/test_util.h8
-rw-r--r--tools/testing/selftests/kvm/include/ucall_common.h2
-rw-r--r--tools/testing/selftests/kvm/include/x86_64/processor.h23
-rw-r--r--tools/testing/selftests/kvm/lib/aarch64/processor.c6
-rw-r--r--tools/testing/selftests/kvm/lib/guest_sprintf.c7
-rw-r--r--tools/testing/selftests/kvm/lib/x86_64/apic.c2
-rw-r--r--tools/testing/selftests/kvm/memslot_perf_test.c9
-rw-r--r--tools/testing/selftests/kvm/riscv/get-reg-list.c233
-rw-r--r--tools/testing/selftests/kvm/x86_64/hwcr_msr_test.c47
-rw-r--r--tools/testing/selftests/kvm/x86_64/hyperv_svm_test.c2
-rw-r--r--tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c4
-rwxr-xr-xtools/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh1
-rw-r--r--tools/testing/selftests/kvm/x86_64/state_test.c110
-rw-r--r--tools/testing/selftests/kvm/x86_64/tsc_scaling_sync.c4
-rw-r--r--tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c4
-rw-r--r--tools/testing/selftests/landlock/base_test.c2
-rw-r--r--tools/testing/selftests/landlock/common.h13
-rw-r--r--tools/testing/selftests/landlock/config4
-rw-r--r--tools/testing/selftests/landlock/fs_test.c69
-rw-r--r--tools/testing/selftests/landlock/net_test.c1738
-rw-r--r--tools/testing/selftests/lib.mk40
-rw-r--r--tools/testing/selftests/lkdtm/config1
-rw-r--r--tools/testing/selftests/lkdtm/tests.txt3
-rw-r--r--tools/testing/selftests/mm/.gitignore3
-rw-r--r--tools/testing/selftests/mm/Makefile6
-rw-r--r--tools/testing/selftests/mm/config1
-rw-r--r--tools/testing/selftests/mm/cow.c3
-rw-r--r--tools/testing/selftests/mm/gup_longterm.c3
-rw-r--r--tools/testing/selftests/mm/hugetlb-madvise.c19
-rw-r--r--tools/testing/selftests/mm/hugetlb_fault_after_madv.c73
-rw-r--r--tools/testing/selftests/mm/ksm_functional_tests.c66
-rw-r--r--tools/testing/selftests/mm/mdwe_test.c137
-rw-r--r--tools/testing/selftests/mm/mremap_dontunmap.c1
-rw-r--r--tools/testing/selftests/mm/mremap_test.c303
-rw-r--r--tools/testing/selftests/mm/pagemap_ioctl.c1664
-rw-r--r--tools/testing/selftests/mm/pkey-helpers.h2
-rwxr-xr-xtools/testing/selftests/mm/run_vmtests.sh12
-rw-r--r--tools/testing/selftests/mm/vm_util.c19
-rw-r--r--tools/testing/selftests/mm/vm_util.h1
-rw-r--r--tools/testing/selftests/net/Makefile3
-rw-r--r--tools/testing/selftests/net/af_unix/diag_uid.c1
-rw-r--r--tools/testing/selftests/net/af_unix/scm_pidfd.c1
-rw-r--r--tools/testing/selftests/net/af_unix/test_unix_oob.c2
-rw-r--r--tools/testing/selftests/net/cmsg_sender.c2
-rwxr-xr-xtools/testing/selftests/net/fdb_flush.sh812
-rwxr-xr-xtools/testing/selftests/net/fib_tests.sh7
-rw-r--r--tools/testing/selftests/net/forwarding/Makefile3
-rwxr-xr-xtools/testing/selftests/net/forwarding/bridge_fdb_learning_limit.sh283
-rwxr-xr-xtools/testing/selftests/net/forwarding/bridge_mdb.sh184
-rw-r--r--tools/testing/selftests/net/io_uring_zerocopy_tx.c268
-rw-r--r--tools/testing/selftests/net/ipsec.c4
-rw-r--r--tools/testing/selftests/net/mptcp/mptcp_connect.c11
-rw-r--r--tools/testing/selftests/net/mptcp/mptcp_inq.c11
-rwxr-xr-xtools/testing/selftests/net/mptcp/mptcp_join.sh46
-rwxr-xr-xtools/testing/selftests/net/mptcp/mptcp_sockopt.sh1
-rwxr-xr-xtools/testing/selftests/net/netns-name.sh87
-rw-r--r--tools/testing/selftests/net/nettest.c5
-rwxr-xr-xtools/testing/selftests/net/openvswitch/openvswitch.sh21
-rw-r--r--tools/testing/selftests/net/openvswitch/ovs-dpctl.py48
-rwxr-xr-xtools/testing/selftests/net/pmtu.sh2
-rwxr-xr-xtools/testing/selftests/net/route_localnet.sh6
-rwxr-xr-xtools/testing/selftests/net/rtnetlink.sh981
-rwxr-xr-xtools/testing/selftests/net/test_vxlan_mdb.sh108
-rw-r--r--tools/testing/selftests/netfilter/Makefile2
-rwxr-xr-xtools/testing/selftests/netfilter/nf_nat_edemux.sh46
-rwxr-xr-xtools/testing/selftests/netfilter/nft_audit.sh52
-rwxr-xr-xtools/testing/selftests/netfilter/xt_string.sh128
-rw-r--r--tools/testing/selftests/nolibc/.gitignore1
-rw-r--r--tools/testing/selftests/nolibc/Makefile57
-rw-r--r--tools/testing/selftests/nolibc/nolibc-test-linkage.c26
-rw-r--r--tools/testing/selftests/nolibc/nolibc-test-linkage.h9
-rw-r--r--tools/testing/selftests/nolibc/nolibc-test.c28
-rw-r--r--tools/testing/selftests/openat2/openat2_test.c2
-rw-r--r--tools/testing/selftests/pidfd/pidfd_fdinfo_test.c2
-rw-r--r--tools/testing/selftests/pidfd/pidfd_test.c12
-rw-r--r--tools/testing/selftests/proc/proc-empty-vm.c182
-rw-r--r--tools/testing/selftests/ptp/ptpchmaskfmt.sh14
-rw-r--r--tools/testing/selftests/ptp/testptp.c19
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/rcutorture/bin/functions.sh29
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck.sh2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh17
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/parse-console.sh9
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/torture.sh2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TRACE021
-rw-r--r--tools/testing/selftests/resctrl/Makefile2
-rw-r--r--tools/testing/selftests/resctrl/cache.c7
-rw-r--r--tools/testing/selftests/resctrl/cat_test.c21
-rw-r--r--tools/testing/selftests/resctrl/cmt_test.c37
-rw-r--r--tools/testing/selftests/resctrl/mba_test.c6
-rw-r--r--tools/testing/selftests/resctrl/mbm_test.c11
-rw-r--r--tools/testing/selftests/resctrl/resctrl.h24
-rw-r--r--tools/testing/selftests/resctrl/resctrl_tests.c180
-rw-r--r--tools/testing/selftests/resctrl/resctrl_val.c86
-rw-r--r--tools/testing/selftests/resctrl/resctrlfs.c162
-rw-r--r--tools/testing/selftests/riscv/hwprobe/Makefile9
-rw-r--r--tools/testing/selftests/riscv/hwprobe/cbo.c228
-rw-r--r--tools/testing/selftests/riscv/hwprobe/hwprobe.c64
-rw-r--r--tools/testing/selftests/riscv/hwprobe/hwprobe.h15
-rw-r--r--tools/testing/selftests/riscv/mm/Makefile6
-rw-r--r--tools/testing/selftests/riscv/mm/mmap_bottomup.c (renamed from tools/testing/selftests/riscv/mm/testcases/mmap_bottomup.c)2
-rw-r--r--tools/testing/selftests/riscv/mm/mmap_default.c (renamed from tools/testing/selftests/riscv/mm/testcases/mmap_default.c)2
-rw-r--r--tools/testing/selftests/riscv/mm/mmap_test.h (renamed from tools/testing/selftests/riscv/mm/testcases/mmap_test.h)0
-rwxr-xr-xtools/testing/selftests/riscv/mm/run_mmap.sh (renamed from tools/testing/selftests/riscv/mm/testcases/run_mmap.sh)0
-rw-r--r--tools/testing/selftests/rseq/param_test.c20
-rw-r--r--tools/testing/selftests/sigaltstack/sas.c2
-rwxr-xr-xtools/testing/selftests/static_keys/test_static_keys.sh8
-rw-r--r--tools/testing/selftests/tc-testing/Makefile2
-rw-r--r--tools/testing/selftests/tc-testing/README65
-rw-r--r--tools/testing/selftests/tc-testing/TdcPlugin.py4
-rw-r--r--tools/testing/selftests/tc-testing/TdcResults.py3
-rw-r--r--tools/testing/selftests/tc-testing/config9
-rw-r--r--tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py194
-rw-r--r--tools/testing/selftests/tc-testing/plugin-lib/rootPlugin.py4
-rw-r--r--tools/testing/selftests/tc-testing/plugin-lib/valgrindPlugin.py5
-rwxr-xr-xtools/testing/selftests/tc-testing/scripts/taprio_wait_for_admin.sh (renamed from tools/testing/selftests/tc-testing/taprio_wait_for_admin.sh)0
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/connmark.json45
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/csum.json69
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/ct.json54
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/ctinfo.json36
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/gact.json75
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/gate.json36
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/ife.json144
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json72
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/mpls.json159
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/nat.json81
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/pedit.json198
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/police.json102
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/sample.json87
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/simple.json27
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json90
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json54
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/tunnel_key.json117
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json108
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/xt.json24
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/bpf.json10
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/fw.json315
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/matchall.json141
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/route.json25
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/u32.json25
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/infra/actions.json144
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/infra/filter.json9
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/cake.json82
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/cbs.json38
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/choke.json30
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/codel.json34
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/drr.json10
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/etf.json18
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/ets.json284
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/fifo.json98
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq.json68
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq_codel.json54
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq_pie.json5
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/gred.json28
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/hfsc.json58
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/hhf.json36
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/htb.json46
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/ingress.json36
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/netem.json62
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/pfifo_fast.json18
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/plug.json30
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/prio.json85
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/qfq.json39
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/red.json34
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/sfb.json48
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/sfq.json40
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/skbprio.json16
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/taprio.json8
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/tbf.json36
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/teql.json34
-rwxr-xr-xtools/testing/selftests/tc-testing/tdc.py250
-rw-r--r--tools/testing/selftests/tdx/.gitignore1
-rw-r--r--tools/testing/selftests/thermal/intel/power_floor/Makefile12
-rw-r--r--tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c108
-rw-r--r--tools/testing/selftests/thermal/intel/workload_hint/Makefile12
-rw-r--r--tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c157
-rw-r--r--tools/testing/selftests/timers/nsleep-lat.c26
-rw-r--r--tools/testing/selftests/timers/posix_timers.c81
-rw-r--r--tools/testing/selftests/uevent/uevent_filtering.c8
-rw-r--r--tools/testing/selftests/user_events/.gitignore4
-rw-r--r--tools/testing/selftests/user_events/abi_test.c69
-rw-r--r--tools/testing/selftests/user_events/dyn_test.c54
-rw-r--r--tools/testing/selftests/x86/Makefile4
-rw-r--r--tools/testing/selftests/x86/lam.c6
-rw-r--r--tools/testing/selftests/x86/nx_stack.c212
-rw-r--r--tools/testing/vsock/.gitignore1
-rw-r--r--tools/testing/vsock/Makefile11
-rw-r--r--tools/testing/vsock/msg_zerocopy_common.c87
-rw-r--r--tools/testing/vsock/msg_zerocopy_common.h18
-rw-r--r--tools/testing/vsock/util.c344
-rw-r--r--tools/testing/vsock/util.h11
-rw-r--r--tools/testing/vsock/vsock_perf.c80
-rw-r--r--tools/testing/vsock/vsock_test.c410
-rw-r--r--tools/testing/vsock/vsock_test_zerocopy.c358
-rw-r--r--tools/testing/vsock/vsock_test_zerocopy.h15
-rw-r--r--tools/testing/vsock/vsock_uring_test.c342
-rw-r--r--tools/thermal/lib/mainloop.c16
-rw-r--r--tools/tracing/rtla/src/utils.c2
-rw-r--r--tools/verification/dot2/dot2k2
-rw-r--r--tools/virtio/linux/dma-mapping.h12
-rw-r--r--usr/include/Makefile6
-rw-r--r--virt/kvm/kvm_main.c18
13454 files changed, 854810 insertions, 287883 deletions
diff --git a/.gitignore b/.gitignore
index 0bbae167bf93..98274e1160d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -74,7 +74,6 @@ modules.order
#
# RPM spec file (make rpm-pkg)
#
-/kernel.spec
/rpmbuild/
#
diff --git a/.mailmap b/.mailmap
index c80903efec75..3ac1c12545f2 100644
--- a/.mailmap
+++ b/.mailmap
@@ -87,6 +87,7 @@ Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@unisoc.com>
Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang7@gmail.com>
Bart Van Assche <bvanassche@acm.org> <bart.vanassche@sandisk.com>
Bart Van Assche <bvanassche@acm.org> <bart.vanassche@wdc.com>
+Bartosz Golaszewski <brgl@bgdev.pl> <bgolaszewski@baylibre.com>
Ben Dooks <ben-linux@fluff.org> <ben.dooks@simtec.co.uk>
Ben Dooks <ben-linux@fluff.org> <ben.dooks@sifive.com>
Ben Gardner <bgardner@wabtec.com>
@@ -94,6 +95,7 @@ Ben M Cahill <ben.m.cahill@intel.com>
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>
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>
@@ -115,6 +117,7 @@ Changbin Du <changbin.du@intel.com> <changbin.du@gmail.com>
Changbin Du <changbin.du@intel.com> <changbin.du@intel.com>
Chao Yu <chao@kernel.org> <chao2.yu@samsung.com>
Chao Yu <chao@kernel.org> <yuchao0@huawei.com>
+Chester Lin <chester62515@gmail.com> <clin@suse.com>
Chris Chiu <chris.chiu@canonical.com> <chiu@endlessm.com>
Chris Chiu <chris.chiu@canonical.com> <chiu@endlessos.org>
Chris Lew <quic_clew@quicinc.com> <clew@codeaurora.org>
@@ -127,6 +130,7 @@ Christian Brauner <brauner@kernel.org> <christian.brauner@ubuntu.com>
Christian Marangi <ansuelsmth@gmail.com>
Christophe Ricard <christophe.ricard@gmail.com>
Christoph Hellwig <hch@lst.de>
+Claudiu Beznea <claudiu.beznea@tuxon.dev> <claudiu.beznea@microchip.com>
Colin Ian King <colin.i.king@gmail.com> <colin.king@canonical.com>
Corey Minyard <minyard@acm.org>
Damian Hobson-Garcia <dhobsong@igel.co.jp>
@@ -262,6 +266,9 @@ Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
Jernej Skrabec <jernej.skrabec@gmail.com> <jernej.skrabec@siol.net>
Jessica Zhang <quic_jesszhan@quicinc.com> <jesszhan@codeaurora.org>
Jilai Wang <quic_jilaiw@quicinc.com> <jilaiw@codeaurora.org>
+Jiri Kosina <jikos@kernel.org> <jikos@jikos.cz>
+Jiri Kosina <jikos@kernel.org> <jkosina@suse.cz>
+Jiri Kosina <jikos@kernel.org> <jkosina@suse.com>
Jiri Pirko <jiri@resnulli.us> <jiri@nvidia.com>
Jiri Pirko <jiri@resnulli.us> <jiri@mellanox.com>
Jiri Pirko <jiri@resnulli.us> <jpirko@redhat.com>
@@ -450,9 +457,10 @@ Oleksandr Natalenko <oleksandr@natalenko.name> <oleksandr@redhat.com>
Oleksij Rempel <linux@rempel-privat.de> <bug-track@fisher-privat.net>
Oleksij Rempel <linux@rempel-privat.de> <external.Oleksij.Rempel@de.bosch.com>
Oleksij Rempel <linux@rempel-privat.de> <fixed-term.Oleksij.Rempel@de.bosch.com>
-Oleksij Rempel <linux@rempel-privat.de> <o.rempel@pengutronix.de>
-Oleksij Rempel <linux@rempel-privat.de> <ore@pengutronix.de>
+Oleksij Rempel <o.rempel@pengutronix.de>
+Oleksij Rempel <o.rempel@pengutronix.de> <ore@pengutronix.de>
Oliver Upton <oliver.upton@linux.dev> <oupton@google.com>
+Ondřej Jirman <megi@xff.cz> <megous@megous.com>
Oza Pawandeep <quic_poza@quicinc.com> <poza@codeaurora.org>
Pali Rohár <pali@kernel.org> <pali.rohar@gmail.com>
Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
@@ -566,6 +574,7 @@ Takashi YOSHII <takashi.yoshii.zj@renesas.com>
Tamizh Chelvam Raja <quic_tamizhr@quicinc.com> <tamizhr@codeaurora.org>
Taniya Das <quic_tdas@quicinc.com> <tdas@codeaurora.org>
Tejun Heo <htejun@gmail.com>
+Tomeu Vizoso <tomeu@tomeuvizoso.net> <tomeu.vizoso@collabora.com>
Thomas Graf <tgraf@suug.ch>
Thomas Körper <socketcan@esd.eu> <thomas.koerper@esd.eu>
Thomas Pedersen <twp@codeaurora.org>
diff --git a/CREDITS b/CREDITS
index f33a33fd2371..81845c39e3cf 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2944,6 +2944,14 @@ D: IPX development and support
N: Venkatesh Pallipadi (Venki)
D: x86/HPET
+N: Antti Palosaari
+E: crope@iki.fi
+D: Various DVB drivers
+W: https://palosaari.fi/linux/
+S: Yliopistokatu 1 D 513
+S: FI-90570 Oulu
+S: FINLAND
+
N: Kyungmin Park
E: kyungmin.park@samsung.com
D: Samsung S5Pv210 and Exynos4210 mobile platforms
diff --git a/Documentation/ABI/stable/sysfs-driver-dma-idxd b/Documentation/ABI/stable/sysfs-driver-dma-idxd
index 825e619250bf..f2ec42949a54 100644
--- a/Documentation/ABI/stable/sysfs-driver-dma-idxd
+++ b/Documentation/ABI/stable/sysfs-driver-dma-idxd
@@ -270,6 +270,12 @@ Description: Shows the operation capability bits displayed in bitmap format
correlates to the operations allowed. It's visible only
on platforms that support the capability.
+What: /sys/bus/dsa/devices/wq<m>.<n>/driver_name
+Date: Sept 8, 2023
+KernelVersion: 6.7.0
+Contact: dmaengine@vger.kernel.org
+Description: Name of driver to be bounded to the wq.
+
What: /sys/bus/dsa/devices/engine<m>.<n>/group_id
Date: Oct 25, 2019
KernelVersion: 5.6.0
diff --git a/Documentation/ABI/testing/configfs-tsm b/Documentation/ABI/testing/configfs-tsm
new file mode 100644
index 000000000000..dd24202b5ba5
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-tsm
@@ -0,0 +1,82 @@
+What: /sys/kernel/config/tsm/report/$name/inblob
+Date: September, 2023
+KernelVersion: v6.7
+Contact: linux-coco@lists.linux.dev
+Description:
+ (WO) Up to 64 bytes of user specified binary data. For replay
+ protection this should include a nonce, but the kernel does not
+ place any restrictions on the content.
+
+What: /sys/kernel/config/tsm/report/$name/outblob
+Date: September, 2023
+KernelVersion: v6.7
+Contact: linux-coco@lists.linux.dev
+Description:
+ (RO) Binary attestation report generated from @inblob and other
+ options The format of the report is implementation specific
+ where the implementation is conveyed via the @provider
+ attribute.
+
+What: /sys/kernel/config/tsm/report/$name/auxblob
+Date: October, 2023
+KernelVersion: v6.7
+Contact: linux-coco@lists.linux.dev
+Description:
+ (RO) Optional supplemental data that a TSM may emit, visibility
+ of this attribute depends on TSM, and may be empty if no
+ auxiliary data is available.
+
+ When @provider is "sev_guest" this file contains the
+ "cert_table" from SEV-ES Guest-Hypervisor Communication Block
+ Standardization v2.03 Section 4.1.8.1 MSG_REPORT_REQ.
+ https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/56421.pdf
+
+What: /sys/kernel/config/tsm/report/$name/provider
+Date: September, 2023
+KernelVersion: v6.7
+Contact: linux-coco@lists.linux.dev
+Description:
+ (RO) A name for the format-specification of @outblob like
+ "sev_guest" [1] or "tdx_guest" [2] in the near term, or a
+ common standard format in the future.
+
+ [1]: SEV Secure Nested Paging Firmware ABI Specification
+ Revision 1.55 Table 22
+ https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/56860.pdf
+
+ [2]: Intel® Trust Domain Extensions Data Center Attestation
+ Primitives : Quote Generation Library and Quote Verification
+ Library Revision 0.8 Appendix 4,5
+ https://download.01.org/intel-sgx/latest/dcap-latest/linux/docs/Intel_TDX_DCAP_Quoting_Library_API.pdf
+
+What: /sys/kernel/config/tsm/report/$name/generation
+Date: September, 2023
+KernelVersion: v6.7
+Contact: linux-coco@lists.linux.dev
+Description:
+ (RO) The value in this attribute increments each time @inblob or
+ any option is written. Userspace can detect conflicts by
+ checking generation before writing to any attribute and making
+ sure the number of writes matches expectations after reading
+ @outblob, or it can prevent conflicts by creating a report
+ instance per requesting context.
+
+What: /sys/kernel/config/tsm/report/$name/privlevel
+Date: September, 2023
+KernelVersion: v6.7
+Contact: linux-coco@lists.linux.dev
+Description:
+ (WO) Attribute is visible if a TSM implementation provider
+ supports the concept of attestation reports for TVMs running at
+ different privilege levels, like SEV-SNP "VMPL", specify the
+ privilege level via this attribute. The minimum acceptable
+ value is conveyed via @privlevel_floor and the maximum
+ acceptable value is TSM_PRIVLEVEL_MAX (3).
+
+What: /sys/kernel/config/tsm/report/$name/privlevel_floor
+Date: September, 2023
+KernelVersion: v6.7
+Contact: linux-coco@lists.linux.dev
+Description:
+ (RO) Indicates the minimum permissible value that can be written
+ to @privlevel.
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uac2 b/Documentation/ABI/testing/configfs-usb-gadget-uac2
index 3371c39f651d..a2bf4fd82a5b 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uac2
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uac2
@@ -35,4 +35,6 @@ Description:
req_number the number of pre-allocated requests
for both capture and playback
function_name name of the interface
+ c_terminal_type code of the capture terminal type
+ p_terminal_type code of the playback terminal type
===================== =======================================
diff --git a/Documentation/ABI/testing/debugfs-driver-habanalabs b/Documentation/ABI/testing/debugfs-driver-habanalabs
index df535780058b..042fd125fbc9 100644
--- a/Documentation/ABI/testing/debugfs-driver-habanalabs
+++ b/Documentation/ABI/testing/debugfs-driver-habanalabs
@@ -1,4 +1,4 @@
-What: /sys/kernel/debug/habanalabs/hl<n>/addr
+What: /sys/kernel/debug/accel/<n>/addr
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -8,34 +8,34 @@ Description: Sets the device address to be used for read or write through
only when the IOMMU is disabled.
The acceptable value is a string that starts with "0x"
-What: /sys/kernel/debug/habanalabs/hl<n>/clk_gate
+What: /sys/kernel/debug/accel/<n>/clk_gate
Date: May 2020
KernelVersion: 5.8
Contact: ogabbay@kernel.org
Description: This setting is now deprecated as clock gating is handled solely by the f/w
-What: /sys/kernel/debug/habanalabs/hl<n>/command_buffers
+What: /sys/kernel/debug/accel/<n>/command_buffers
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Displays a list with information about the currently allocated
command buffers
-What: /sys/kernel/debug/habanalabs/hl<n>/command_submission
+What: /sys/kernel/debug/accel/<n>/command_submission
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Displays a list with information about the currently active
command submissions
-What: /sys/kernel/debug/habanalabs/hl<n>/command_submission_jobs
+What: /sys/kernel/debug/accel/<n>/command_submission_jobs
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Displays a list with detailed information about each JOB (CB) of
each active command submission
-What: /sys/kernel/debug/habanalabs/hl<n>/data32
+What: /sys/kernel/debug/accel/<n>/data32
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -50,7 +50,7 @@ Description: Allows the root user to read or write directly through the
If the IOMMU is disabled, it also allows the root user to read
or write from the host a device VA of a host mapped memory
-What: /sys/kernel/debug/habanalabs/hl<n>/data64
+What: /sys/kernel/debug/accel/<n>/data64
Date: Jan 2020
KernelVersion: 5.6
Contact: ogabbay@kernel.org
@@ -65,7 +65,7 @@ Description: Allows the root user to read or write 64 bit data directly
If the IOMMU is disabled, it also allows the root user to read
or write from the host a device VA of a host mapped memory
-What: /sys/kernel/debug/habanalabs/hl<n>/data_dma
+What: /sys/kernel/debug/accel/<n>/data_dma
Date: Apr 2021
KernelVersion: 5.13
Contact: ogabbay@kernel.org
@@ -79,11 +79,11 @@ Description: Allows the root user to read from the device's internal
a very long time.
This interface doesn't support concurrency in the same device.
In GAUDI and GOYA, this action can cause undefined behavior
- in case the it is done while the device is executing user
+ in case it is done while the device is executing user
workloads.
Only supported on GAUDI at this stage.
-What: /sys/kernel/debug/habanalabs/hl<n>/device
+What: /sys/kernel/debug/accel/<n>/device
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -91,14 +91,14 @@ Description: Enables the root user to set the device to specific state.
Valid values are "disable", "enable", "suspend", "resume".
User can read this property to see the valid values
-What: /sys/kernel/debug/habanalabs/hl<n>/device_release_watchdog_timeout
+What: /sys/kernel/debug/accel/<n>/device_release_watchdog_timeout
Date: Oct 2022
KernelVersion: 6.2
Contact: ttayar@habana.ai
Description: The watchdog timeout value in seconds for a device release upon
certain error cases, after which the device is reset.
-What: /sys/kernel/debug/habanalabs/hl<n>/dma_size
+What: /sys/kernel/debug/accel/<n>/dma_size
Date: Apr 2021
KernelVersion: 5.13
Contact: ogabbay@kernel.org
@@ -108,7 +108,7 @@ Description: Specify the size of the DMA transaction when using DMA to read
When the write is finished, the user can read the "data_dma"
blob
-What: /sys/kernel/debug/habanalabs/hl<n>/dump_razwi_events
+What: /sys/kernel/debug/accel/<n>/dump_razwi_events
Date: Aug 2022
KernelVersion: 5.20
Contact: fkassabri@habana.ai
@@ -117,7 +117,7 @@ Description: Dumps all razwi events to dmesg if exist.
the routine will clear the status register.
Usage: cat dump_razwi_events
-What: /sys/kernel/debug/habanalabs/hl<n>/dump_security_violations
+What: /sys/kernel/debug/accel/<n>/dump_security_violations
Date: Jan 2021
KernelVersion: 5.12
Contact: ogabbay@kernel.org
@@ -125,14 +125,14 @@ Description: Dumps all security violations to dmesg. This will also ack
all security violations meanings those violations will not be
dumped next time user calls this API
-What: /sys/kernel/debug/habanalabs/hl<n>/engines
+What: /sys/kernel/debug/accel/<n>/engines
Date: Jul 2019
KernelVersion: 5.3
Contact: ogabbay@kernel.org
Description: Displays the status registers values of the device engines and
their derived idle status
-What: /sys/kernel/debug/habanalabs/hl<n>/i2c_addr
+What: /sys/kernel/debug/accel/<n>/i2c_addr
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -140,7 +140,7 @@ Description: Sets I2C device address for I2C transaction that is generated
by the device's CPU, Not available when device is loaded with secured
firmware
-What: /sys/kernel/debug/habanalabs/hl<n>/i2c_bus
+What: /sys/kernel/debug/accel/<n>/i2c_bus
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -148,7 +148,7 @@ Description: Sets I2C bus address for I2C transaction that is generated by
the device's CPU, Not available when device is loaded with secured
firmware
-What: /sys/kernel/debug/habanalabs/hl<n>/i2c_data
+What: /sys/kernel/debug/accel/<n>/i2c_data
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -157,7 +157,7 @@ Description: Triggers an I2C transaction that is generated by the device's
reading from the file generates a read transaction, Not available
when device is loaded with secured firmware
-What: /sys/kernel/debug/habanalabs/hl<n>/i2c_len
+What: /sys/kernel/debug/accel/<n>/i2c_len
Date: Dec 2021
KernelVersion: 5.17
Contact: obitton@habana.ai
@@ -165,7 +165,7 @@ Description: Sets I2C length in bytes for I2C transaction that is generated b
the device's CPU, Not available when device is loaded with secured
firmware
-What: /sys/kernel/debug/habanalabs/hl<n>/i2c_reg
+What: /sys/kernel/debug/accel/<n>/i2c_reg
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -173,35 +173,35 @@ Description: Sets I2C register id for I2C transaction that is generated by
the device's CPU, Not available when device is loaded with secured
firmware
-What: /sys/kernel/debug/habanalabs/hl<n>/led0
+What: /sys/kernel/debug/accel/<n>/led0
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Sets the state of the first S/W led on the device, Not available
when device is loaded with secured firmware
-What: /sys/kernel/debug/habanalabs/hl<n>/led1
+What: /sys/kernel/debug/accel/<n>/led1
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Sets the state of the second S/W led on the device, Not available
when device is loaded with secured firmware
-What: /sys/kernel/debug/habanalabs/hl<n>/led2
+What: /sys/kernel/debug/accel/<n>/led2
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Sets the state of the third S/W led on the device, Not available
when device is loaded with secured firmware
-What: /sys/kernel/debug/habanalabs/hl<n>/memory_scrub
+What: /sys/kernel/debug/accel/<n>/memory_scrub
Date: May 2022
KernelVersion: 5.19
Contact: dhirschfeld@habana.ai
Description: Allows the root user to scrub the dram memory. The scrubbing
value can be set using the debugfs file memory_scrub_val.
-What: /sys/kernel/debug/habanalabs/hl<n>/memory_scrub_val
+What: /sys/kernel/debug/accel/<n>/memory_scrub_val
Date: May 2022
KernelVersion: 5.19
Contact: dhirschfeld@habana.ai
@@ -209,7 +209,7 @@ Description: The value to which the dram will be set to when the user
scrubs the dram using 'memory_scrub' debugfs file and
the scrubbing value when using module param 'memory_scrub'
-What: /sys/kernel/debug/habanalabs/hl<n>/mmu
+What: /sys/kernel/debug/accel/<n>/mmu
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -217,19 +217,19 @@ Description: Displays the hop values and physical address for a given ASID
and virtual address. The user should write the ASID and VA into
the file and then read the file to get the result.
e.g. to display info about VA 0x1000 for ASID 1 you need to do:
- echo "1 0x1000" > /sys/kernel/debug/habanalabs/hl0/mmu
+ echo "1 0x1000" > /sys/kernel/debug/accel/0/mmu
-What: /sys/kernel/debug/habanalabs/hl<n>/mmu_error
+What: /sys/kernel/debug/accel/<n>/mmu_error
Date: Mar 2021
KernelVersion: 5.12
Contact: fkassabri@habana.ai
Description: Check and display page fault or access violation mmu errors for
all MMUs specified in mmu_cap_mask.
e.g. to display error info for MMU hw cap bit 9, you need to do:
- echo "0x200" > /sys/kernel/debug/habanalabs/hl0/mmu_error
- cat /sys/kernel/debug/habanalabs/hl0/mmu_error
+ echo "0x200" > /sys/kernel/debug/accel/0/mmu_error
+ cat /sys/kernel/debug/accel/0/mmu_error
-What: /sys/kernel/debug/habanalabs/hl<n>/monitor_dump
+What: /sys/kernel/debug/accel/<n>/monitor_dump
Date: Mar 2022
KernelVersion: 5.19
Contact: osharabi@habana.ai
@@ -243,7 +243,7 @@ Description: Allows the root user to dump monitors status from the device's
This interface doesn't support concurrency in the same device.
Only supported on GAUDI.
-What: /sys/kernel/debug/habanalabs/hl<n>/monitor_dump_trig
+What: /sys/kernel/debug/accel/<n>/monitor_dump_trig
Date: Mar 2022
KernelVersion: 5.19
Contact: osharabi@habana.ai
@@ -253,14 +253,14 @@ Description: Triggers dump of monitor data. The value to trigger the operatio
When the write is finished, the user can read the "monitor_dump"
blob
-What: /sys/kernel/debug/habanalabs/hl<n>/set_power_state
+What: /sys/kernel/debug/accel/<n>/set_power_state
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Sets the PCI power state. Valid values are "1" for D0 and "2"
for D3Hot
-What: /sys/kernel/debug/habanalabs/hl<n>/skip_reset_on_timeout
+What: /sys/kernel/debug/accel/<n>/skip_reset_on_timeout
Date: Jun 2021
KernelVersion: 5.13
Contact: ynudelman@habana.ai
@@ -268,7 +268,7 @@ Description: Sets the skip reset on timeout option for the device. Value of
"0" means device will be reset in case some CS has timed out,
otherwise it will not be reset.
-What: /sys/kernel/debug/habanalabs/hl<n>/state_dump
+What: /sys/kernel/debug/accel/<n>/state_dump
Date: Oct 2021
KernelVersion: 5.15
Contact: ynudelman@habana.ai
@@ -279,7 +279,7 @@ Description: Gets the state dump occurring on a CS timeout or failure.
Writing an integer X discards X state dumps, so that the
next read would return X+1-st newest state dump.
-What: /sys/kernel/debug/habanalabs/hl<n>/stop_on_err
+What: /sys/kernel/debug/accel/<n>/stop_on_err
Date: Mar 2020
KernelVersion: 5.6
Contact: ogabbay@kernel.org
@@ -287,21 +287,21 @@ Description: Sets the stop-on_error option for the device engines. Value of
"0" is for disable, otherwise enable.
Relevant only for GOYA and GAUDI.
-What: /sys/kernel/debug/habanalabs/hl<n>/timeout_locked
+What: /sys/kernel/debug/accel/<n>/timeout_locked
Date: Sep 2021
KernelVersion: 5.16
Contact: obitton@habana.ai
Description: Sets the command submission timeout value in seconds.
-What: /sys/kernel/debug/habanalabs/hl<n>/userptr
+What: /sys/kernel/debug/accel/<n>/userptr
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
-Description: Displays a list with information about the currently user
+Description: Displays a list with information about the current user
pointers (user virtual addresses) that are pinned and mapped
to DMA addresses
-What: /sys/kernel/debug/habanalabs/hl<n>/userptr_lookup
+What: /sys/kernel/debug/accel/<n>/userptr_lookup
Date: Oct 2021
KernelVersion: 5.15
Contact: ogabbay@kernel.org
@@ -309,7 +309,7 @@ Description: Allows to search for specific user pointers (user virtual
addresses) that are pinned and mapped to DMA addresses, and see
their resolution to the specific dma address.
-What: /sys/kernel/debug/habanalabs/hl<n>/vm
+What: /sys/kernel/debug/accel/<n>/vm
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
diff --git a/Documentation/ABI/testing/debugfs-driver-qat b/Documentation/ABI/testing/debugfs-driver-qat
index 6731ffacc5f0..b2db010d851e 100644
--- a/Documentation/ABI/testing/debugfs-driver-qat
+++ b/Documentation/ABI/testing/debugfs-driver-qat
@@ -1,4 +1,4 @@
-What: /sys/kernel/debug/qat_<device>_<BDF>/qat/fw_counters
+What: /sys/kernel/debug/qat_<device>_<BDF>/fw_counters
Date: November 2023
KernelVersion: 6.6
Contact: qat-linux@intel.com
@@ -59,3 +59,25 @@ Description: (RO) Read returns the device health status.
The driver does not monitor for Heartbeat. It is left for a user
to poll the status periodically.
+
+What: /sys/kernel/debug/qat_<device>_<BDF>/pm_status
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description: (RO) Read returns power management information specific to the
+ QAT device.
+
+ This attribute is only available for qat_4xxx devices.
+
+What: /sys/kernel/debug/qat_<device>_<BDF>/cnv_errors
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description: (RO) Read returns, for each Acceleration Engine (AE), the number
+ of errors and the type of the last error detected by the device
+ when performing verified compression.
+ Reported counters::
+
+ <N>: Number of Compress and Verify (CnV) errors and type
+ of the last CnV error detected by Acceleration
+ Engine N.
diff --git a/Documentation/ABI/testing/sysfs-bus-cdx b/Documentation/ABI/testing/sysfs-bus-cdx
index 7af477f49998..8c067ff99e54 100644
--- a/Documentation/ABI/testing/sysfs-bus-cdx
+++ b/Documentation/ABI/testing/sysfs-bus-cdx
@@ -28,14 +28,57 @@ Description:
of a device manufacturer.
Combination of Vendor ID and Device ID identifies a device.
+What: /sys/bus/cdx/devices/.../subsystem_vendor
+Date: July 2023
+Contact: puneet.gupta@amd.com
+Description:
+ Subsystem Vendor ID for this CDX device, in hexadecimal.
+ Subsystem Vendor ID is 16 bit identifier specific to the
+ card manufacturer.
+
+What: /sys/bus/cdx/devices/.../subsystem_device
+Date: July 2023
+Contact: puneet.gupta@amd.com
+Description:
+ Subsystem Device ID for this CDX device, in hexadecimal
+ Subsystem Device ID is 16 bit identifier specific to the
+ card manufacturer.
+
+What: /sys/bus/cdx/devices/.../class
+Date: July 2023
+Contact: puneet.gupta@amd.com
+Description:
+ This file contains the class of the CDX device, in hexadecimal.
+ Class is 24 bit identifier specifies the functionality of the device.
+
+What: /sys/bus/cdx/devices/.../revision
+Date: July 2023
+Contact: puneet.gupta@amd.com
+Description:
+ This file contains the revision field of the CDX device, in hexadecimal.
+ Revision is 8 bit revision identifier of the device.
+
+What: /sys/bus/cdx/devices/.../enable
+Date: October 2023
+Contact: abhijit.gangurde@amd.com
+Description:
+ CDX bus should be disabled before updating the devices in FPGA.
+ Writing n/0/off will attempt to disable the CDX bus and.
+ writing y/1/on will attempt to enable the CDX bus. Reading this file
+ gives the current state of the bus, 1 for enabled and 0 for disabled.
+
+ For example::
+
+ # echo 1 > /sys/bus/cdx/.../enable
+
What: /sys/bus/cdx/devices/.../reset
Date: March 2023
Contact: nipun.gupta@amd.com
Description:
- Writing y/1/on to this file resets the CDX device.
- On resetting the device, the corresponding driver is notified
- twice, once before the device is being reset, and again after
- the reset has been complete.
+ Writing y/1/on to this file resets the CDX device or all devices
+ on the bus. On resetting the device, the corresponding driver is
+ notified twice, once before the device is being reset, and again
+ after the reset has been complete.
For example::
@@ -54,3 +97,18 @@ Description:
For example::
# echo 1 > /sys/bus/cdx/devices/.../remove
+
+What: /sys/bus/cdx/devices/.../modalias
+Date: July 2023
+Contact: nipun.gupta@amd.com
+Description:
+ This attribute indicates the CDX ID of the device.
+ That is in the format:
+ cdx:vXXXXdXXXXsvXXXXsdXXXXcXXXXXX,
+ where:
+
+ - vXXXX contains the vendor ID;
+ - dXXXX contains the device ID;
+ - svXXXX contains the subsystem vendor ID;
+ - sdXXXX contains the subsystem device ID;
+ - cXXXXXX contains the device class.
diff --git a/Documentation/ABI/testing/sysfs-bus-cxl b/Documentation/ABI/testing/sysfs-bus-cxl
index 087f762ebfd5..e76c3600607f 100644
--- a/Documentation/ABI/testing/sysfs-bus-cxl
+++ b/Documentation/ABI/testing/sysfs-bus-cxl
@@ -178,6 +178,21 @@ Description:
hardware decoder target list.
+What: /sys/bus/cxl/devices/portX/decoders_committed
+Date: October, 2023
+KernelVersion: v6.7
+Contact: linux-cxl@vger.kernel.org
+Description:
+ (RO) A memory device is considered active when any of its
+ decoders are in the "committed" state (See CXL 3.0 8.2.4.19.7
+ CXL HDM Decoder n Control Register). Hotplug and destructive
+ operations like "sanitize" are blocked while device is actively
+ decoding a Host Physical Address range. Note that this number
+ may be elevated without any regionX objects active or even
+ enumerated, as this may be due to decoders established by
+ platform firwmare or a previous kernel (kexec).
+
+
What: /sys/bus/cxl/devices/decoderX.Y
Date: June, 2021
KernelVersion: v5.14
@@ -369,6 +384,21 @@ Description:
provided it is currently idle / not bound to a driver.
+What: /sys/bus/cxl/devices/decoderX.Y/qos_class
+Date: May, 2023
+KernelVersion: v6.5
+Contact: linux-cxl@vger.kernel.org
+Description:
+ (RO) For CXL host platforms that support "QoS Telemmetry" this
+ root-decoder-only attribute conveys a platform specific cookie
+ that identifies a QoS performance class for the CXL Window.
+ This class-id can be compared against a similar "qos_class"
+ published for each memory-type that an endpoint supports. While
+ it is not required that endpoints map their local memory-class
+ to a matching platform class, mismatches are not recommended and
+ there are platform specific side-effects that may result.
+
+
What: /sys/bus/cxl/devices/regionZ/uuid
Date: May, 2022
KernelVersion: v6.0
diff --git a/Documentation/ABI/testing/sysfs-bus-i3c b/Documentation/ABI/testing/sysfs-bus-i3c
index 1f4a2662335b..e5248fd67a56 100644
--- a/Documentation/ABI/testing/sysfs-bus-i3c
+++ b/Documentation/ABI/testing/sysfs-bus-i3c
@@ -67,7 +67,7 @@ What: /sys/bus/i3c/devices/i3c-<bus-id>/pid
KernelVersion: 5.0
Contact: linux-i3c@vger.kernel.org
Description:
- PID stands for Provisional ID and is used to uniquely identify
+ PID stands for Provisioned ID and is used to uniquely identify
a device on a bus. This PID contains information about the
vendor, the part and an instance ID so that several devices of
the same type can be connected on the same bus.
@@ -123,7 +123,7 @@ What: /sys/bus/i3c/devices/i3c-<bus-id>/<bus-id>-<device-pid>/pid
KernelVersion: 5.0
Contact: linux-i3c@vger.kernel.org
Description:
- PID stands for Provisional ID and is used to uniquely identify
+ PID stands for Provisioned ID and is used to uniquely identify
a device on a bus. This PID contains information about the
vendor, the part and an instance ID so that several devices of
the same type can be connected on the same bus.
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index a2854dc9a839..19cde14f3869 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -279,6 +279,35 @@ Description:
but should match other such assignments on device).
Units after application of scale and offset are m/s^2.
+What: /sys/bus/iio/devices/iio:deviceX/in_deltaangl_x_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_deltaangl_y_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_deltaangl_z_raw
+KernelVersion: 6.5
+Contact: linux-iio@vger.kernel.org
+Description:
+ Angular displacement between two consecutive samples on x, y or
+ z (may be arbitrarily assigned but should match other such
+ assignments on device).
+ In order to compute the total angular displacement during a
+ desired period of time, the application should sum-up the delta
+ angle samples acquired during that time.
+ Units after application of scale and offset are radians.
+
+What: /sys/bus/iio/devices/iio:deviceX/in_deltavelocity_x_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_deltavelocity_y_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_deltavelocity_z_raw
+KernelVersion: 6.5
+Contact: linux-iio@vger.kernel.org
+Description:
+ The linear velocity change between two consecutive samples on x,
+ y or z (may be arbitrarily assigned but should match other such
+ assignments on device).
+ In order to compute the total linear velocity change during a
+ desired period of time, the application should sum-up the delta
+ velocity samples acquired during that time.
+ Units after application of scale and offset are meters per
+ second.
+
What: /sys/bus/iio/devices/iio:deviceX/in_angl_raw
What: /sys/bus/iio/devices/iio:deviceX/in_anglY_raw
KernelVersion: 4.17
@@ -461,6 +490,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_scale
What: /sys/bus/iio/devices/iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_scale
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance_scale
What: /sys/bus/iio/devices/iio:deviceX/in_countY_scale
+What: /sys/bus/iio/devices/iio:deviceX/in_deltaangl_scale
+What: /sys/bus/iio/devices/iio:deviceX/in_deltavelocity_scale
What: /sys/bus/iio/devices/iio:deviceX/in_angl_scale
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_x_scale
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_y_scale
@@ -1332,6 +1363,12 @@ Description:
What: /sys/.../iio:deviceX/bufferY/in_accel_x_en
What: /sys/.../iio:deviceX/bufferY/in_accel_y_en
What: /sys/.../iio:deviceX/bufferY/in_accel_z_en
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_x_en
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_y_en
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_z_en
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_x_en
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_y_en
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_z_en
What: /sys/.../iio:deviceX/bufferY/in_anglvel_x_en
What: /sys/.../iio:deviceX/bufferY/in_anglvel_y_en
What: /sys/.../iio:deviceX/bufferY/in_anglvel_z_en
@@ -1362,6 +1399,8 @@ Description:
Scan element control for triggered data capture.
What: /sys/.../iio:deviceX/bufferY/in_accel_type
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_type
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_type
What: /sys/.../iio:deviceX/bufferY/in_anglvel_type
What: /sys/.../iio:deviceX/bufferY/in_magn_type
What: /sys/.../iio:deviceX/bufferY/in_incli_type
@@ -1416,6 +1455,12 @@ What: /sys/.../iio:deviceX/bufferY/in_voltage_q_index
What: /sys/.../iio:deviceX/bufferY/in_accel_x_index
What: /sys/.../iio:deviceX/bufferY/in_accel_y_index
What: /sys/.../iio:deviceX/bufferY/in_accel_z_index
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_x_index
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_y_index
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_z_index
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_x_index
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_y_index
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_z_index
What: /sys/.../iio:deviceX/bufferY/in_anglvel_x_index
What: /sys/.../iio:deviceX/bufferY/in_anglvel_y_index
What: /sys/.../iio:deviceX/bufferY/in_anglvel_z_index
@@ -2179,3 +2224,33 @@ Contact: linux-iio@vger.kernel.org
Description:
Number of conditions that must occur, during a running
period, before an event is generated.
+
+What: /sys/bus/iio/devices/iio:deviceX/in_colortemp_raw
+KernelVersion: 6.7
+Contact: linux-iio@vger.kernel.org
+Description:
+ Represents light color temperature, which measures light color
+ temperature in Kelvin.
+
+What: /sys/bus/iio/devices/iio:deviceX/in_chromaticity_x_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_chromaticity_y_raw
+KernelVersion: 6.7
+Contact: linux-iio@vger.kernel.org
+Description:
+ The x and y light color coordinate on the CIE 1931 chromaticity
+ diagram.
+
+What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltageY_mag_either_label
+What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltageY_mag_rising_label
+What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltageY_thresh_falling_label
+What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltageY_thresh_rising_label
+What: /sys/bus/iio/devices/iio:deviceX/events/in_anglvelY_mag_rising_label
+What: /sys/bus/iio/devices/iio:deviceX/events/in_anglY_thresh_rising_label
+What: /sys/bus/iio/devices/iio:deviceX/events/in_phaseY_mag_rising_label
+KernelVersion: 6.7
+Contact: linux-iio@vger.kernel.org
+Description:
+ Optional symbolic label to a device channel event.
+ If a label is defined for this event add that to the event
+ specific attributes. This is useful for userspace to be able to
+ better identify an individual event.
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-adc-mcp3564 b/Documentation/ABI/testing/sysfs-bus-iio-adc-mcp3564
new file mode 100644
index 000000000000..b168aa44b233
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-adc-mcp3564
@@ -0,0 +1,53 @@
+What: /sys/bus/iio/devices/iio:deviceX/boost_current_gain
+KernelVersion: 6.4
+Contact: linux-iio@vger.kernel.org
+Description:
+ This attribute is used to set the gain of the biasing current
+ circuit of the Delta-Sigma modulator. The different BOOST
+ settings are applied to the entire modulator circuit, including
+ the voltage reference buffers.
+
+What: /sys/bus/iio/devices/iio:deviceX/boost_current_gain_available
+KernelVersion: 6.4
+Contact: linux-iio@vger.kernel.org
+Description:
+ Reading returns a list with the possible gain values for
+ the current biasing circuit of the Delta-Sigma modulator.
+
+What: /sys/bus/iio/devices/iio:deviceX/auto_zeroing_mux_enable
+KernelVersion: 6.4
+Contact: linux-iio@vger.kernel.org
+Description:
+ This attribute is used to enable the analog input multiplexer
+ auto-zeroing algorithm (the input multiplexer and the ADC
+ include an offset cancellation algorithm that cancels the offset
+ contribution of the ADC). When the offset cancellation algorithm
+ is enabled, ADC takes two conversions, one with the differential
+ input as VIN+/VIN-, one with VIN+/VIN- inverted. In this case the
+ conversion time is multiplied by two compared to the default
+ case where the algorithm is disabled. This technique allows the
+ cancellation of the ADC offset error and the achievement of
+ ultra-low offset without any digital calibration. The resulting
+ offset is the residue of the difference between the two
+ conversions, which is on the order of magnitude of the noise
+ floor. This offset is effectively canceled at every conversion,
+ so the residual offset error temperature drift is extremely low.
+ Write '1' to enable it, write '0' to disable it.
+
+What: /sys/bus/iio/devices/iio:deviceX/auto_zeroing_ref_enable
+KernelVersion: 6.4
+Contact: linux-iio@vger.kernel.org
+Description:
+ This attribute is used to enable the chopping algorithm for the
+ internal voltage reference buffer. This setting has no effect
+ when external voltage reference is selected.
+ Internal voltage reference buffer injects a certain quantity of
+ 1/f noise into the system that can be modulated with the
+ incoming input signals and can limit the SNR performance at
+ higher Oversampling Ratio values (over 256). To overcome this
+ limitation, the buffer includes an auto-zeroing algorithm that
+ greatly reduces (cancels out) the 1/f noise and cancels the
+ offset value of the reference buffer. As a result, the SNR of
+ the system is not affected by this 1/f noise component of the
+ reference buffer, even at maximum oversampling ratio values.
+ Write '1' to enable it, write '0' to disable it.
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-resolver-ad2s1210 b/Documentation/ABI/testing/sysfs-bus-iio-resolver-ad2s1210
new file mode 100644
index 000000000000..f92c79342b93
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-resolver-ad2s1210
@@ -0,0 +1,27 @@
+What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltage0_mag_rising_reset_max
+KernelVersion: 6.7
+Contact: linux-iio@vger.kernel.org
+Description:
+ Reading returns the current Degradation of Signal Reset Maximum
+ Threshold value in millivolts. Writing sets the value.
+
+What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltage0_mag_rising_reset_max_available
+KernelVersion: 6.7
+Contact: linux-iio@vger.kernel.org
+Description:
+ Reading returns the allowable voltage range for
+ in_altvoltage0_mag_rising_reset_max.
+
+What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltage0_mag_rising_reset_min
+KernelVersion: 6.7
+Contact: linux-iio@vger.kernel.org
+Description:
+ Reading returns the current Degradation of Signal Reset Minimum
+ Threshold value in millivolts. Writing sets the value.
+
+What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltage0_mag_rising_reset_min_available
+KernelVersion: 6.7
+Contact: linux-iio@vger.kernel.org
+Description:
+ Reading returns the allowable voltage range for
+ in_altvoltage0_mag_rising_reset_min.
diff --git a/Documentation/ABI/testing/sysfs-bus-optee-devices b/Documentation/ABI/testing/sysfs-bus-optee-devices
index 0f58701367b6..af31e5a22d89 100644
--- a/Documentation/ABI/testing/sysfs-bus-optee-devices
+++ b/Documentation/ABI/testing/sysfs-bus-optee-devices
@@ -6,3 +6,12 @@ Description:
OP-TEE bus provides reference to registered drivers under this directory. The <uuid>
matches Trusted Application (TA) driver and corresponding TA in secure OS. Drivers
are free to create needed API under optee-ta-<uuid> directory.
+
+What: /sys/bus/tee/devices/optee-ta-<uuid>/need_supplicant
+Date: November 2023
+KernelVersion: 6.7
+Contact: op-tee@lists.trustedfirmware.org
+Description:
+ Allows to distinguish whether an OP-TEE based TA/device requires user-space
+ tee-supplicant to function properly or not. This attribute will be present for
+ devices which depend on tee-supplicant to be running.
diff --git a/Documentation/ABI/testing/sysfs-bus-papr-pmem b/Documentation/ABI/testing/sysfs-bus-papr-pmem
index 46cfe02058fd..34ee8c59ab25 100644
--- a/Documentation/ABI/testing/sysfs-bus-papr-pmem
+++ b/Documentation/ABI/testing/sysfs-bus-papr-pmem
@@ -8,7 +8,7 @@ Description:
more bits set in the dimm-health-bitmap retrieved in
response to H_SCM_HEALTH hcall. The details of the bit
flags returned in response to this hcall is available
- at 'Documentation/powerpc/papr_hcalls.rst' . Below are
+ at 'Documentation/arch/powerpc/papr_hcalls.rst' . Below are
the flags reported in this sysfs file:
* "not_armed"
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index a44bfe020061..2b7108e21977 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -313,6 +313,15 @@ Description:
Inter-Chip SSIC devices support asymmetric lanes up to 4 lanes per
direction. Devices before USB 3.2 are single lane (tx_lanes = 1)
+What: /sys/bus/usb/devices/.../typec
+Date: November 2023
+Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+ Symlink to the USB Type-C partner device. USB Type-C partner
+ represents the component that communicates over the
+ Configuration Channel (CC signal on USB Type-C connectors and
+ cables) with the local port.
+
What: /sys/bus/usb/devices/usbX/bAlternateSetting
Description:
The current interface alternate setting number, in decimal.
diff --git a/Documentation/ABI/testing/sysfs-bus-vdpa b/Documentation/ABI/testing/sysfs-bus-vdpa
index 28a6111202ba..4da53878bff6 100644
--- a/Documentation/ABI/testing/sysfs-bus-vdpa
+++ b/Documentation/ABI/testing/sysfs-bus-vdpa
@@ -1,4 +1,4 @@
-What: /sys/bus/vdpa/driver_autoprobe
+What: /sys/bus/vdpa/drivers_autoprobe
Date: March 2020
Contact: virtualization@lists.linux-foundation.org
Description:
@@ -17,7 +17,7 @@ Description:
Writing a device name to this file will cause the kernel binds
devices to a compatible driver.
- This can be useful when /sys/bus/vdpa/driver_autoprobe is
+ This can be useful when /sys/bus/vdpa/drivers_autoprobe is
disabled.
What: /sys/bus/vdpa/drivers/.../bind
diff --git a/Documentation/ABI/testing/sysfs-class-firmware b/Documentation/ABI/testing/sysfs-class-firmware
index 978d3d500400..fba87a55f3ca 100644
--- a/Documentation/ABI/testing/sysfs-class-firmware
+++ b/Documentation/ABI/testing/sysfs-class-firmware
@@ -1,7 +1,7 @@
What: /sys/class/firmware/.../data
Date: July 2022
KernelVersion: 5.19
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Russ Weight <russ.weight@linux.dev>
Description: The data sysfs file is used for firmware-fallback and for
firmware uploads. Cat a firmware image to this sysfs file
after you echo 1 to the loading sysfs file. When the firmware
@@ -13,7 +13,7 @@ Description: The data sysfs file is used for firmware-fallback and for
What: /sys/class/firmware/.../cancel
Date: July 2022
KernelVersion: 5.19
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Russ Weight <russ.weight@linux.dev>
Description: Write-only. For firmware uploads, write a "1" to this file to
request that the transfer of firmware data to the lower-level
device be canceled. This request will be rejected (EBUSY) if
@@ -23,7 +23,7 @@ Description: Write-only. For firmware uploads, write a "1" to this file to
What: /sys/class/firmware/.../error
Date: July 2022
KernelVersion: 5.19
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Russ Weight <russ.weight@linux.dev>
Description: Read-only. Returns a string describing a failed firmware
upload. This string will be in the form of <STATUS>:<ERROR>,
where <STATUS> will be one of the status strings described
@@ -37,7 +37,7 @@ Description: Read-only. Returns a string describing a failed firmware
What: /sys/class/firmware/.../loading
Date: July 2022
KernelVersion: 5.19
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Russ Weight <russ.weight@linux.dev>
Description: The loading sysfs file is used for both firmware-fallback and
for firmware uploads. Echo 1 onto the loading file to indicate
you are writing a firmware file to the data sysfs node. Echo
@@ -49,7 +49,7 @@ Description: The loading sysfs file is used for both firmware-fallback and
What: /sys/class/firmware/.../remaining_size
Date: July 2022
KernelVersion: 5.19
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Russ Weight <russ.weight@linux.dev>
Description: Read-only. For firmware upload, this file contains the size
of the firmware data that remains to be transferred to the
lower-level device driver. The size value is initialized to
@@ -62,7 +62,7 @@ Description: Read-only. For firmware upload, this file contains the size
What: /sys/class/firmware/.../status
Date: July 2022
KernelVersion: 5.19
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Russ Weight <russ.weight@linux.dev>
Description: Read-only. Returns a string describing the current status of
a firmware upload. The string will be one of the following:
idle, "receiving", "preparing", "transferring", "programming".
@@ -70,7 +70,7 @@ Description: Read-only. Returns a string describing the current status of
What: /sys/class/firmware/.../timeout
Date: July 2022
KernelVersion: 5.19
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Russ Weight <russ.weight@linux.dev>
Description: This file supports the timeout mechanism for firmware
fallback. This file has no affect on firmware uploads. For
more information on timeouts please see the documentation
diff --git a/Documentation/ABI/testing/sysfs-class-firmware-attributes b/Documentation/ABI/testing/sysfs-class-firmware-attributes
index f205d39409a3..9c82c7b42ff8 100644
--- a/Documentation/ABI/testing/sysfs-class-firmware-attributes
+++ b/Documentation/ABI/testing/sysfs-class-firmware-attributes
@@ -383,6 +383,36 @@ Description:
Note that any changes to this attribute requires a reboot
for changes to take effect.
+What: /sys/class/firmware-attributes/*/attributes/save_settings
+Date: August 2023
+KernelVersion: 6.6
+Contact: Mark Pearson <mpearson-lenovo@squebb.ca>
+Description:
+ On Lenovo platforms there is a limitation in the number of times an attribute can be
+ saved. This is an architectural limitation and it limits the number of attributes
+ that can be modified to 48.
+ A solution for this is instead of the attribute being saved after every modification,
+ to allow a user to bulk set the attributes, and then trigger a final save. This allows
+ unlimited attributes.
+
+ Read the attribute to check what save mode is enabled (single or bulk).
+ E.g:
+ # cat /sys/class/firmware-attributes/thinklmi/attributes/save_settings
+ single
+
+ Write the attribute with 'bulk' to enable bulk save mode.
+ Write the attribute with 'single' to enable saving, after every attribute set.
+ The default setting is single mode.
+ E.g:
+ # echo bulk > /sys/class/firmware-attributes/thinklmi/attributes/save_settings
+
+ When in bulk mode write 'save' to trigger a save of all currently modified attributes.
+ Note, once a save has been triggered, in bulk mode, attributes can no longer be set and
+ will return a permissions error. This is to prevent users hitting the 48+ save limitation
+ (which requires entering the BIOS to clear the error condition)
+ E.g:
+ # echo save > /sys/class/firmware-attributes/thinklmi/attributes/save_settings
+
What: /sys/class/firmware-attributes/*/attributes/debug_cmd
Date: July 2021
KernelVersion: 5.14
diff --git a/Documentation/ABI/testing/sysfs-class-led b/Documentation/ABI/testing/sysfs-class-led
index b2ff0012c0f2..2e24ac3bd7ef 100644
--- a/Documentation/ABI/testing/sysfs-class-led
+++ b/Documentation/ABI/testing/sysfs-class-led
@@ -59,15 +59,6 @@ Description:
brightness. Reading this file when no hw brightness change
event has happened will return an ENODATA error.
-What: /sys/class/leds/<led>/color
-Date: June 2023
-KernelVersion: 6.5
-Description:
- Color of the LED.
-
- This is a read-only file. Reading this file returns the color
- of the LED as a string (e.g: "red", "green", "multicolor").
-
What: /sys/class/leds/<led>/trigger
Date: March 2006
KernelVersion: 2.6.17
diff --git a/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia b/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia
index c4d46970c1cf..369b4ae8be5f 100644
--- a/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia
+++ b/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia
@@ -12,3 +12,17 @@ Description: (RW) On the front panel of the Turris Omnia router there is also
able to change this setting from software.
Format: %i
+
+What: /sys/class/leds/<led>/device/gamma_correction
+Date: August 2023
+KernelVersion: 6.6
+Contact: Marek Behún <kabel@kernel.org>
+Description: (RW) Newer versions of the microcontroller firmware of the
+ Turris Omnia router support gamma correction for the RGB LEDs.
+ This feature can be enabled/disabled by writing to this file.
+
+ If the feature is not supported because the MCU firmware is too
+ old, the file always reads as 0, and writing to the file results
+ in the EOPNOTSUPP error.
+
+ Format: %i
diff --git a/Documentation/ABI/testing/sysfs-class-usb_power_delivery b/Documentation/ABI/testing/sysfs-class-usb_power_delivery
index 1bf9d1d7902c..61d233c320ea 100644
--- a/Documentation/ABI/testing/sysfs-class-usb_power_delivery
+++ b/Documentation/ABI/testing/sysfs-class-usb_power_delivery
@@ -124,6 +124,13 @@ Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
The voltage the supply supports in millivolts.
+What: /sys/class/usb_power_delivery/.../source-capabilities/<position>:fixed_supply/peak_current
+Date: October 2023
+Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+ This file shows the value of the Fixed Power Source Peak Current
+ Capability field.
+
What: /sys/class/usb_power_delivery/.../source-capabilities/<position>:fixed_supply/maximum_current
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 7ecd5c8161a6..a1db6db47505 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -354,9 +354,6 @@ Description: Parameters for the CPU cache attributes
- ReadWriteAllocate:
both writeallocate and readallocate
- attributes:
- LEGACY used only on IA64 and is same as write_policy
-
coherency_line_size:
the minimum amount of data in bytes that gets
transferred from memory to cache
diff --git a/Documentation/ABI/testing/sysfs-driver-habanalabs b/Documentation/ABI/testing/sysfs-driver-habanalabs
index 1b98b6503b23..c63ca1ad500d 100644
--- a/Documentation/ABI/testing/sysfs-driver-habanalabs
+++ b/Documentation/ABI/testing/sysfs-driver-habanalabs
@@ -1,4 +1,4 @@
-What: /sys/class/habanalabs/hl<n>/armcp_kernel_ver
+What: /sys/class/accel/accel<n>/device/armcp_kernel_ver
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -6,7 +6,7 @@ Description: Version of the Linux kernel running on the device's CPU.
Will be DEPRECATED in Linux kernel version 5.10, and be
replaced with cpucp_kernel_ver
-What: /sys/class/habanalabs/hl<n>/armcp_ver
+What: /sys/class/accel/accel<n>/device/armcp_ver
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -14,7 +14,7 @@ Description: Version of the application running on the device's CPU
Will be DEPRECATED in Linux kernel version 5.10, and be
replaced with cpucp_ver
-What: /sys/class/habanalabs/hl<n>/clk_max_freq_mhz
+What: /sys/class/accel/accel<n>/device/clk_max_freq_mhz
Date: Jun 2019
KernelVersion: 5.7
Contact: ogabbay@kernel.org
@@ -24,58 +24,58 @@ Description: Allows the user to set the maximum clock frequency, in MHz.
frequency value of the device clock. This property is valid
only for the Gaudi ASIC family
-What: /sys/class/habanalabs/hl<n>/clk_cur_freq_mhz
+What: /sys/class/accel/accel<n>/device/clk_cur_freq_mhz
Date: Jun 2019
KernelVersion: 5.7
Contact: ogabbay@kernel.org
Description: Displays the current frequency, in MHz, of the device clock.
This property is valid only for the Gaudi ASIC family
-What: /sys/class/habanalabs/hl<n>/cpld_ver
+What: /sys/class/accel/accel<n>/device/cpld_ver
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Version of the Device's CPLD F/W
-What: /sys/class/habanalabs/hl<n>/cpucp_kernel_ver
+What: /sys/class/accel/accel<n>/device/cpucp_kernel_ver
Date: Oct 2020
KernelVersion: 5.10
Contact: ogabbay@kernel.org
Description: Version of the Linux kernel running on the device's CPU
-What: /sys/class/habanalabs/hl<n>/cpucp_ver
+What: /sys/class/accel/accel<n>/device/cpucp_ver
Date: Oct 2020
KernelVersion: 5.10
Contact: ogabbay@kernel.org
Description: Version of the application running on the device's CPU
-What: /sys/class/habanalabs/hl<n>/device_type
+What: /sys/class/accel/accel<n>/device/device_type
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Displays the code name of the device according to its type.
The supported values are: "GOYA"
-What: /sys/class/habanalabs/hl<n>/eeprom
+What: /sys/class/accel/accel<n>/device/eeprom
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: A binary file attribute that contains the contents of the
on-board EEPROM
-What: /sys/class/habanalabs/hl<n>/fuse_ver
+What: /sys/class/accel/accel<n>/device/fuse_ver
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Displays the device's version from the eFuse
-What: /sys/class/habanalabs/hl<n>/fw_os_ver
+What: /sys/class/accel/accel<n>/device/fw_os_ver
Date: Dec 2021
KernelVersion: 5.18
Contact: ogabbay@kernel.org
Description: Version of the firmware OS running on the device's CPU
-What: /sys/class/habanalabs/hl<n>/hard_reset
+What: /sys/class/accel/accel<n>/device/hard_reset
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -83,14 +83,14 @@ Description: Interface to trigger a hard-reset operation for the device.
Hard-reset will reset ALL internal components of the device
except for the PCI interface and the internal PLLs
-What: /sys/class/habanalabs/hl<n>/hard_reset_cnt
+What: /sys/class/accel/accel<n>/device/hard_reset_cnt
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Displays how many times the device have undergone a hard-reset
operation since the driver was loaded
-What: /sys/class/habanalabs/hl<n>/high_pll
+What: /sys/class/accel/accel<n>/device/high_pll
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -98,7 +98,7 @@ Description: Allows the user to set the maximum clock frequency for MME, TPC
and IC when the power management profile is set to "automatic".
This property is valid only for the Goya ASIC family
-What: /sys/class/habanalabs/hl<n>/ic_clk
+What: /sys/class/accel/accel<n>/device/ic_clk
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -110,27 +110,27 @@ Description: Allows the user to set the maximum clock frequency, in Hz, of
frequency value of the IC. This property is valid only for the
Goya ASIC family
-What: /sys/class/habanalabs/hl<n>/ic_clk_curr
+What: /sys/class/accel/accel<n>/device/ic_clk_curr
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Displays the current clock frequency, in Hz, of the Interconnect
fabric. This property is valid only for the Goya ASIC family
-What: /sys/class/habanalabs/hl<n>/infineon_ver
+What: /sys/class/accel/accel<n>/device/infineon_ver
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Version of the Device's power supply F/W code. Relevant only to GOYA and GAUDI
-What: /sys/class/habanalabs/hl<n>/max_power
+What: /sys/class/accel/accel<n>/device/max_power
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Allows the user to set the maximum power consumption of the
device in milliwatts.
-What: /sys/class/habanalabs/hl<n>/mme_clk
+What: /sys/class/accel/accel<n>/device/mme_clk
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -142,21 +142,21 @@ Description: Allows the user to set the maximum clock frequency, in Hz, of
frequency value of the MME. This property is valid only for the
Goya ASIC family
-What: /sys/class/habanalabs/hl<n>/mme_clk_curr
+What: /sys/class/accel/accel<n>/device/mme_clk_curr
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Displays the current clock frequency, in Hz, of the MME compute
engine. This property is valid only for the Goya ASIC family
-What: /sys/class/habanalabs/hl<n>/pci_addr
+What: /sys/class/accel/accel<n>/device/pci_addr
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Displays the PCI address of the device. This is needed so the
user would be able to open a device based on its PCI address
-What: /sys/class/habanalabs/hl<n>/pm_mng_profile
+What: /sys/class/accel/accel<n>/device/pm_mng_profile
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -170,19 +170,19 @@ Description: Power management profile. Values are "auto", "manual". In "auto"
ic_clk, mme_clk and tpc_clk. This property is valid only for
the Goya ASIC family
-What: /sys/class/habanalabs/hl<n>/preboot_btl_ver
+What: /sys/class/accel/accel<n>/device/preboot_btl_ver
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Version of the device's preboot F/W code
-What: /sys/class/habanalabs/hl<n>/security_enabled
+What: /sys/class/accel/accel<n>/device/security_enabled
Date: Oct 2022
KernelVersion: 6.1
Contact: obitton@habana.ai
Description: Displays the device's security status
-What: /sys/class/habanalabs/hl<n>/soft_reset
+What: /sys/class/accel/accel<n>/device/soft_reset
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -190,14 +190,14 @@ Description: Interface to trigger a soft-reset operation for the device.
Soft-reset will reset only the compute and DMA engines of the
device
-What: /sys/class/habanalabs/hl<n>/soft_reset_cnt
+What: /sys/class/accel/accel<n>/device/soft_reset_cnt
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Displays how many times the device have undergone a soft-reset
operation since the driver was loaded
-What: /sys/class/habanalabs/hl<n>/status
+What: /sys/class/accel/accel<n>/device/status
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -215,13 +215,13 @@ Description: Status of the card:
a compute-reset which is executed after a device release
(relevant for Gaudi2 only).
-What: /sys/class/habanalabs/hl<n>/thermal_ver
+What: /sys/class/accel/accel<n>/device/thermal_ver
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Version of the Device's thermal daemon
-What: /sys/class/habanalabs/hl<n>/tpc_clk
+What: /sys/class/accel/accel<n>/device/tpc_clk
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
@@ -233,20 +233,20 @@ Description: Allows the user to set the maximum clock frequency, in Hz, of
frequency value of the TPC. This property is valid only for
Goya ASIC family
-What: /sys/class/habanalabs/hl<n>/tpc_clk_curr
+What: /sys/class/accel/accel<n>/device/tpc_clk_curr
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Displays the current clock frequency, in Hz, of the TPC compute
engines. This property is valid only for the Goya ASIC family
-What: /sys/class/habanalabs/hl<n>/uboot_ver
+What: /sys/class/accel/accel<n>/device/uboot_ver
Date: Jan 2019
KernelVersion: 5.1
Contact: ogabbay@kernel.org
Description: Version of the u-boot running on the device's CPU
-What: /sys/class/habanalabs/hl<n>/vrm_ver
+What: /sys/class/accel/accel<n>/device/vrm_ver
Date: Jan 2022
KernelVersion: 5.17
Contact: ogabbay@kernel.org
diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
index a8ab58035c95..c12316dfd973 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
@@ -17,7 +17,7 @@ Description: Read only. Returns the firmware version of Intel MAX10
What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_address
Date: January 2021
KernelVersion: 5.12
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Peter Colberg <peter.colberg@intel.com>
Description: Read only. Returns the first MAC address in a block
of sequential MAC addresses assigned to the board
that is managed by the Intel MAX10 BMC. It is stored in
@@ -28,7 +28,7 @@ Description: Read only. Returns the first MAC address in a block
What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_count
Date: January 2021
KernelVersion: 5.12
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Peter Colberg <peter.colberg@intel.com>
Description: Read only. Returns the number of sequential MAC
addresses assigned to the board managed by the Intel
MAX10 BMC. This value is stored in FLASH and is mirrored
diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
index 0a41afe0ab4c..9051695d2211 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
@@ -1,7 +1,7 @@
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/sr_root_entry_hash
Date: Sep 2022
KernelVersion: 5.20
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Peter Colberg <peter.colberg@intel.com>
Description: Read only. Returns the root entry hash for the static
region if one is programmed, else it returns the
string: "hash not programmed". This file is only
@@ -11,7 +11,7 @@ Description: Read only. Returns the root entry hash for the static
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/pr_root_entry_hash
Date: Sep 2022
KernelVersion: 5.20
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Peter Colberg <peter.colberg@intel.com>
Description: Read only. Returns the root entry hash for the partial
reconfiguration region if one is programmed, else it
returns the string: "hash not programmed". This file
@@ -21,7 +21,7 @@ Description: Read only. Returns the root entry hash for the partial
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/bmc_root_entry_hash
Date: Sep 2022
KernelVersion: 5.20
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Peter Colberg <peter.colberg@intel.com>
Description: Read only. Returns the root entry hash for the BMC image
if one is programmed, else it returns the string:
"hash not programmed". This file is only visible if the
@@ -31,7 +31,7 @@ Description: Read only. Returns the root entry hash for the BMC image
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/sr_canceled_csks
Date: Sep 2022
KernelVersion: 5.20
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Peter Colberg <peter.colberg@intel.com>
Description: Read only. Returns a list of indices for canceled code
signing keys for the static region. The standard bitmap
list format is used (e.g. "1,2-6,9").
@@ -39,7 +39,7 @@ Description: Read only. Returns a list of indices for canceled code
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/pr_canceled_csks
Date: Sep 2022
KernelVersion: 5.20
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Peter Colberg <peter.colberg@intel.com>
Description: Read only. Returns a list of indices for canceled code
signing keys for the partial reconfiguration region. The
standard bitmap list format is used (e.g. "1,2-6,9").
@@ -47,7 +47,7 @@ Description: Read only. Returns a list of indices for canceled code
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/bmc_canceled_csks
Date: Sep 2022
KernelVersion: 5.20
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Peter Colberg <peter.colberg@intel.com>
Description: Read only. Returns a list of indices for canceled code
signing keys for the BMC. The standard bitmap list format
is used (e.g. "1,2-6,9").
@@ -55,7 +55,7 @@ Description: Read only. Returns a list of indices for canceled code
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/flash_count
Date: Sep 2022
KernelVersion: 5.20
-Contact: Russ Weight <russell.h.weight@intel.com>
+Contact: Peter Colberg <peter.colberg@intel.com>
Description: Read only. Returns number of times the secure update
staging area has been flashed.
Format: "%u".
diff --git a/Documentation/ABI/testing/sysfs-driver-qat b/Documentation/ABI/testing/sysfs-driver-qat
index ef6d6c57105e..bbf329cf0d67 100644
--- a/Documentation/ABI/testing/sysfs-driver-qat
+++ b/Documentation/ABI/testing/sysfs-driver-qat
@@ -29,6 +29,8 @@ Description: (RW) Reports the current configuration of the QAT device.
services
* asym;sym: identical to sym;asym
* dc: the device is configured for running compression services
+ * dcc: identical to dc but enables the dc chaining feature,
+ hash then compression. If this is not required chose dc
* sym: the device is configured for running symmetric crypto
services
* asym: the device is configured for running asymmetric crypto
@@ -93,3 +95,49 @@ Description: (RW) This configuration option provides a way to force the device i
0
This attribute is only available for qat_4xxx devices.
+
+What: /sys/bus/pci/devices/<BDF>/qat/rp2srv
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description:
+ (RW) This attribute provides a way for a user to query a
+ specific ring pair for the type of service that it is currently
+ configured for.
+
+ When written to, the value is cached and used to perform the
+ read operation. Allowed values are in the range 0 to N-1, where
+ N is the max number of ring pairs supported by a device. This
+ can be queried using the attribute qat/num_rps.
+
+ A read returns the service associated to the ring pair queried.
+
+ The values are:
+
+ * dc: the ring pair is configured for running compression services
+ * sym: the ring pair is configured for running symmetric crypto
+ services
+ * asym: the ring pair is configured for running asymmetric crypto
+ services
+
+ Example usage::
+
+ # echo 1 > /sys/bus/pci/devices/<BDF>/qat/rp2srv
+ # cat /sys/bus/pci/devices/<BDF>/qat/rp2srv
+ sym
+
+ This attribute is only available for qat_4xxx devices.
+
+What: /sys/bus/pci/devices/<BDF>/qat/num_rps
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description:
+ (RO) Returns the number of ring pairs that a single device has.
+
+ Example usage::
+
+ # cat /sys/bus/pci/devices/<BDF>/qat/num_rps
+ 64
+
+ This attribute is only available for qat_4xxx devices.
diff --git a/Documentation/ABI/testing/sysfs-driver-qat_ras b/Documentation/ABI/testing/sysfs-driver-qat_ras
new file mode 100644
index 000000000000..176dea1e9c0a
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-qat_ras
@@ -0,0 +1,41 @@
+What: /sys/bus/pci/devices/<BDF>/qat_ras/errors_correctable
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description: (RO) Reports the number of correctable errors detected by the device.
+
+ This attribute is only available for qat_4xxx devices.
+
+What: /sys/bus/pci/devices/<BDF>/qat_ras/errors_nonfatal
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description: (RO) Reports the number of non fatal errors detected by the device.
+
+ This attribute is only available for qat_4xxx devices.
+
+What: /sys/bus/pci/devices/<BDF>/qat_ras/errors_fatal
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description: (RO) Reports the number of fatal errors detected by the device.
+
+ This attribute is only available for qat_4xxx devices.
+
+What: /sys/bus/pci/devices/<BDF>/qat_ras/reset_error_counters
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description: (WO) Write to resets all error counters of a device.
+
+ The following example reports how to reset the counters::
+
+ # echo 1 > /sys/bus/pci/devices/<BDF>/qat_ras/reset_error_counters
+ # cat /sys/bus/pci/devices/<BDF>/qat_ras/errors_correctable
+ 0
+ # cat /sys/bus/pci/devices/<BDF>/qat_ras/errors_nonfatal
+ 0
+ # cat /sys/bus/pci/devices/<BDF>/qat_ras/errors_fatal
+ 0
+
+ This attribute is only available for qat_4xxx devices.
diff --git a/Documentation/ABI/testing/sysfs-driver-qat_rl b/Documentation/ABI/testing/sysfs-driver-qat_rl
new file mode 100644
index 000000000000..8c282ae3155d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-qat_rl
@@ -0,0 +1,226 @@
+What: /sys/bus/pci/devices/<BDF>/qat_rl/sla_op
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description:
+ (WO) This attribute is used to perform an operation on an SLA.
+ The supported operations are: add, update, rm, rm_all, and get.
+
+ Input values must be filled through the associated attribute in
+ this group before a write to this file.
+ If the operation completes successfully, the associated
+ attributes will be updated.
+ The associated attributes are: cir, pir, srv, rp, and id.
+
+ Supported operations:
+
+ * add: Creates a new SLA with the provided inputs from user.
+ * Inputs: cir, pir, srv, and rp
+ * Output: id
+
+ * get: Returns the configuration of the specified SLA in id attribute
+ * Inputs: id
+ * Outputs: cir, pir, srv, and rp
+
+ * update: Updates the SLA with new values set in the following attributes
+ * Inputs: id, cir, and pir
+
+ * rm: Removes the specified SLA in the id attribute.
+ * Inputs: id
+
+ * rm_all: Removes all the configured SLAs.
+ * Inputs: None
+
+ This attribute is only available for qat_4xxx devices.
+
+What: /sys/bus/pci/devices/<BDF>/qat_rl/rp
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description:
+ (RW) When read, reports the current assigned ring pairs for the
+ queried SLA.
+ When wrote to, configures the ring pairs associated to a new SLA.
+
+ The value is a 64-bit bit mask and is written/displayed in hex.
+ Each bit of this mask represents a single ring pair i.e.,
+ bit 1 == ring pair id 0; bit 3 == ring pair id 2.
+
+ Selected ring pairs must to be assigned to a single service,
+ i.e. the one provided with the srv attribute. The service
+ assigned to a certain ring pair can be checked by querying
+ the attribute qat/rp2srv.
+
+ The maximum number of ring pairs is 4 per SLA.
+
+ Applicability in sla_op:
+
+ * WRITE: add operation
+ * READ: get operation
+
+ Example usage::
+
+ ## Read
+ # echo 4 > /sys/bus/pci/devices/<BDF>/qat_rl/id
+ # cat /sys/bus/pci/devices/<BDF>/qat_rl/rp
+ 0x5
+
+ ## Write
+ # echo 0x5 > /sys/bus/pci/devices/<BDF>/qat_rl/rp
+
+ This attribute is only available for qat_4xxx devices.
+
+What: /sys/bus/pci/devices/<BDF>/qat_rl/id
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description:
+ (RW) If written to, the value is used to retrieve a particular
+ SLA and operate on it.
+ This is valid only for the following operations: update, rm,
+ and get.
+ A read of this attribute is only guaranteed to have correct data
+ after creation of an SLA.
+
+ Applicability in sla_op:
+
+ * WRITE: rm and update operations
+ * READ: add and get operations
+
+ Example usage::
+
+ ## Read
+ ## Set attributes e.g. cir, pir, srv, etc
+ # echo "add" > /sys/bus/pci/devices/<BDF>/qat_rl/sla_op
+ # cat /sys/bus/pci/devices/<BDF>/qat_rl/id
+ 4
+
+ ## Write
+ # echo 7 > /sys/bus/pci/devices/<BDF>/qat_rl/id
+ # echo "get" > /sys/bus/pci/devices/<BDF>/qat_rl/sla_op
+ # cat /sys/bus/pci/devices/<BDF>/qat_rl/rp
+ 0x5 ## ring pair ID 0 and ring pair ID 2
+
+ This attribute is only available for qat_4xxx devices.
+
+What: /sys/bus/pci/devices/<BDF>/qat_rl/cir
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description:
+ (RW) Committed information rate (CIR). Rate guaranteed to be
+ achieved by a particular SLA. The value is expressed in
+ permille scale, i.e. 1000 refers to the maximum device
+ throughput for a selected service.
+
+ After sending a "get" to sla_op, this will be populated with the
+ CIR for that queried SLA.
+ Write to this file before sending an "add/update" sla_op, to set
+ the SLA to the specified value.
+
+ Applicability in sla_op:
+
+ * WRITE: add and update operations
+ * READ: get operation
+
+ Example usage::
+
+ ## Write
+ # echo 500 > /sys/bus/pci/devices/<BDF>/qat_rl/cir
+ # echo "add" /sys/bus/pci/devices/<BDF>/qat_rl/sla_op
+
+ ## Read
+ # echo 4 > /sys/bus/pci/devices/<BDF>/qat_rl/id
+ # echo "get" > /sys/bus/pci/devices/<BDF>/qat_rl/sla_op
+ # cat /sys/bus/pci/devices/<BDF>/qat_rl/cir
+ 500
+
+ This attribute is only available for qat_4xxx devices.
+
+What: /sys/bus/pci/devices/<BDF>/qat_rl/pir
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description:
+ (RW) Peak information rate (PIR). The maximum rate that can be
+ achieved by that particular SLA. An SLA can reach a value
+ between CIR and PIR when the device is not fully utilized by
+ requests from other users (assigned to different SLAs).
+
+ After sending a "get" to sla_op, this will be populated with the
+ PIR for that queried SLA.
+ Write to this file before sending an "add/update" sla_op, to set
+ the SLA to the specified value.
+
+ Applicability in sla_op:
+
+ * WRITE: add and update operations
+ * READ: get operation
+
+ Example usage::
+
+ ## Write
+ # echo 750 > /sys/bus/pci/devices/<BDF>/qat_rl/pir
+ # echo "add" > /sys/bus/pci/devices/<BDF>/qat_rl/sla_op
+
+ ## Read
+ # echo 4 > /sys/bus/pci/devices/<BDF>/qat_rl/id
+ # echo "get" > /sys/bus/pci/devices/<BDF>/qat_rl/sla_op
+ # cat /sys/bus/pci/devices/<BDF>/qat_rl/pir
+ 750
+
+ This attribute is only available for qat_4xxx devices.
+
+What: /sys/bus/pci/devices/<BDF>/qat_rl/srv
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description:
+ (RW) Service (SRV). Represents the service (sym, asym, dc)
+ associated to an SLA.
+ Can be written to or queried to set/show the SRV type for an SLA.
+ The SRV attribute is used to specify the SRV type before adding
+ an SLA. After an SLA is configured, reports the service
+ associated to that SLA.
+
+ Applicability in sla_op:
+
+ * WRITE: add and update operations
+ * READ: get operation
+
+ Example usage::
+
+ ## Write
+ # echo "dc" > /sys/bus/pci/devices/<BDF>/qat_rl/srv
+ # echo "add" > /sys/bus/pci/devices/<BDF>/qat_rl/sla_op
+ # cat /sys/bus/pci/devices/<BDF>/qat_rl/id
+ 4
+
+ ## Read
+ # echo 4 > /sys/bus/pci/devices/<BDF>/qat_rl/id
+ # echo "get" > /sys/bus/pci/devices/<BDF>/qat_rl/sla_op
+ # cat /sys/bus/pci/devices/<BDF>/qat_rl/srv
+ dc
+
+ This attribute is only available for qat_4xxx devices.
+
+What: /sys/bus/pci/devices/<BDF>/qat_rl/cap_rem
+Date: January 2024
+KernelVersion: 6.7
+Contact: qat-linux@intel.com
+Description:
+ (RW) This file will return the remaining capability for a
+ particular service/sla. This is the remaining value that a new
+ SLA can be set to or a current SLA can be increased with.
+
+ Example usage::
+
+ # echo "asym" > /sys/bus/pci/devices/<BDF>/qat_rl/cap_rem
+ # cat /sys/bus/pci/devices/<BDF>/qat_rl/cap_rem
+ 250
+ # echo 250 > /sys/bus/pci/devices/<BDF>/qat_rl/cir
+ # echo "add" > /sys/bus/pci/devices/<BDF>/qat_rl/sla_op
+ # cat /sys/bus/pci/devices/<BDF>/qat_rl/cap_rem
+ 0
+
+ This attribute is only available for qat_4xxx devices.
diff --git a/Documentation/ABI/testing/sysfs-firmware-dmi-entries b/Documentation/ABI/testing/sysfs-firmware-dmi-entries
index fe0289c87768..b6c23807b804 100644
--- a/Documentation/ABI/testing/sysfs-firmware-dmi-entries
+++ b/Documentation/ABI/testing/sysfs-firmware-dmi-entries
@@ -2,7 +2,7 @@ What: /sys/firmware/dmi/entries/
Date: February 2011
Contact: Mike Waychison <mikew@google.com>
Description:
- Many machines' firmware (x86 and ia64) export DMI /
+ Many machines' firmware (x86 and arm64) export DMI /
SMBIOS tables to the operating system. Getting at this
information is often valuable to userland, especially in
cases where there are OEM extensions used.
diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-damon b/Documentation/ABI/testing/sysfs-kernel-mm-damon
index 420b30f09cf0..b35649a46a2f 100644
--- a/Documentation/ABI/testing/sysfs-kernel-mm-damon
+++ b/Documentation/ABI/testing/sysfs-kernel-mm-damon
@@ -151,6 +151,13 @@ Contact: SeongJae Park <sj@kernel.org>
Description: Writing to and reading from this file sets and gets the action
of the scheme.
+What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/apply_interval_us
+Date: Sep 2023
+Contact: SeongJae Park <sj@kernel.org>
+Description: Writing a value to this file sets the action apply interval of
+ the scheme in microseconds. Reading this file returns the
+ value.
+
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/access_pattern/sz/min
Date: Mar 2022
Contact: SeongJae Park <sj@kernel.org>
diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
index 820e412d38a8..895c47f05f6f 100644
--- a/Documentation/ABI/testing/sysfs-tty
+++ b/Documentation/ABI/testing/sysfs-tty
@@ -87,19 +87,22 @@ What: /sys/class/tty/ttyS<x>/close_delay
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
- Show the closing delay time for this port in ms.
+ Show the closing delay time for this port in centiseconds.
- These sysfs values expose the TIOCGSERIAL interface via
- sysfs rather than via ioctls.
+ These sysfs values expose the TIOCGSERIAL interface via
+ sysfs rather than via ioctls.
What: /sys/class/tty/ttyS<x>/closing_wait
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
- Show the close wait time for this port in ms.
+ Show the close wait time for this port in centiseconds.
- These sysfs values expose the TIOCGSERIAL interface via
- sysfs rather than via ioctls.
+ Waiting forever is represented as 0. If waiting on close is
+ disabled then the value is 65535.
+
+ These sysfs values expose the TIOCGSERIAL interface via
+ sysfs rather than via ioctls.
What: /sys/class/tty/ttyS<x>/custom_divisor
Date: October 2012
diff --git a/Documentation/PCI/pci-error-recovery.rst b/Documentation/PCI/pci-error-recovery.rst
index 0c7552a00c8c..42e1e78353f3 100644
--- a/Documentation/PCI/pci-error-recovery.rst
+++ b/Documentation/PCI/pci-error-recovery.rst
@@ -364,7 +364,7 @@ Note, however, not all failures are truly "permanent". Some are
caused by over-heating, some by a poorly seated card. Many
PCI error events are caused by software bugs, e.g. DMAs to
wild addresses or bogus split transactions due to programming
-errors. See the discussion in Documentation/powerpc/eeh-pci-error-recovery.rst
+errors. See the discussion in Documentation/arch/powerpc/eeh-pci-error-recovery.rst
for additional detail on real-life experience of the causes of
software errors.
@@ -404,7 +404,7 @@ That is, the recovery API only requires that:
.. note::
Implementation details for the powerpc platform are discussed in
- the file Documentation/powerpc/eeh-pci-error-recovery.rst
+ the file Documentation/arch/powerpc/eeh-pci-error-recovery.rst
As of this writing, there is a growing list of device drivers with
patches implementing error recovery. Not all of these patches are in
diff --git a/Documentation/RCU/Design/Expedited-Grace-Periods/Expedited-Grace-Periods.rst b/Documentation/RCU/Design/Expedited-Grace-Periods/Expedited-Grace-Periods.rst
index 93d899d53258..414f8a2012d6 100644
--- a/Documentation/RCU/Design/Expedited-Grace-Periods/Expedited-Grace-Periods.rst
+++ b/Documentation/RCU/Design/Expedited-Grace-Periods/Expedited-Grace-Periods.rst
@@ -181,7 +181,7 @@ operations is carried out at several levels:
of this wait (or series of waits, as the case may be) is to permit a
concurrent CPU-hotplug operation to complete.
#. In the case of RCU-sched, one of the last acts of an outgoing CPU is
- to invoke ``rcu_report_dead()``, which reports a quiescent state for
+ to invoke ``rcutree_report_cpu_dead()``, which reports a quiescent state for
that CPU. However, this is likely paranoia-induced redundancy.
+-----------------------------------------------------------------------+
diff --git a/Documentation/RCU/Design/Memory-Ordering/TreeRCU-callback-registry.svg b/Documentation/RCU/Design/Memory-Ordering/TreeRCU-callback-registry.svg
index 7ac6f9269806..63eff867175a 100644
--- a/Documentation/RCU/Design/Memory-Ordering/TreeRCU-callback-registry.svg
+++ b/Documentation/RCU/Design/Memory-Ordering/TreeRCU-callback-registry.svg
@@ -566,15 +566,6 @@
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcutree_migrate_callbacks()</text>
<text
xml:space="preserve"
- x="8335.4873"
- y="5357.1006"
- font-style="normal"
- font-weight="bold"
- font-size="192"
- id="text202-7-9-6-0"
- style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_migrate_callbacks()</text>
- <text
- xml:space="preserve"
x="8768.4678"
y="6224.9038"
font-style="normal"
diff --git a/Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-fqs.svg b/Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-fqs.svg
index 7ddc094d7f28..d82a77d03d8c 100644
--- a/Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-fqs.svg
+++ b/Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-fqs.svg
@@ -1135,7 +1135,7 @@
font-weight="bold"
font-size="192"
id="text202-7-5-3-27-6-5"
- style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_report_dead()</text>
+ style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcutree_report_cpu_dead()</text>
<text
xml:space="preserve"
x="3745.7725"
@@ -1256,7 +1256,7 @@
font-style="normal"
y="3679.27"
x="-3804.9949"
- xml:space="preserve">rcu_cpu_starting()</text>
+ xml:space="preserve">rcutree_report_cpu_starting()</text>
<g
style="fill:none;stroke-width:0.025in"
id="g3107-7-5-0"
diff --git a/Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp.svg b/Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp.svg
index 069f6f8371c2..53e0dc2a2c79 100644
--- a/Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp.svg
+++ b/Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp.svg
@@ -1448,15 +1448,6 @@
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcutree_migrate_callbacks()</text>
<text
xml:space="preserve"
- x="8335.4873"
- y="5357.1006"
- font-style="normal"
- font-weight="bold"
- font-size="192"
- id="text202-7-9-6-0"
- style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_migrate_callbacks()</text>
- <text
- xml:space="preserve"
x="8768.4678"
y="6224.9038"
font-style="normal"
@@ -3274,7 +3265,7 @@
font-weight="bold"
font-size="192"
id="text202-7-5-3-27-6-5"
- style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_report_dead()</text>
+ style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcutree_report_cpu_dead()</text>
<text
xml:space="preserve"
x="3745.7725"
@@ -3395,7 +3386,7 @@
font-style="normal"
y="3679.27"
x="-3804.9949"
- xml:space="preserve">rcu_cpu_starting()</text>
+ xml:space="preserve">rcutree_report_cpu_starting()</text>
<g
style="fill:none;stroke-width:0.025in"
id="g3107-7-5-0"
diff --git a/Documentation/RCU/Design/Memory-Ordering/TreeRCU-hotplug.svg b/Documentation/RCU/Design/Memory-Ordering/TreeRCU-hotplug.svg
index 2c9310ba29ba..4fa7506082bf 100644
--- a/Documentation/RCU/Design/Memory-Ordering/TreeRCU-hotplug.svg
+++ b/Documentation/RCU/Design/Memory-Ordering/TreeRCU-hotplug.svg
@@ -607,7 +607,7 @@
font-weight="bold"
font-size="192"
id="text202-7-5-3-27-6"
- style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_report_dead()</text>
+ style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcutree_report_cpu_dead()</text>
<text
xml:space="preserve"
x="3745.7725"
@@ -728,7 +728,7 @@
font-style="normal"
y="3679.27"
x="-3804.9949"
- xml:space="preserve">rcu_cpu_starting()</text>
+ xml:space="preserve">rcutree_report_cpu_starting()</text>
<g
style="fill:none;stroke-width:0.025in"
id="g3107-7-5-0"
diff --git a/Documentation/RCU/Design/Requirements/Requirements.rst b/Documentation/RCU/Design/Requirements/Requirements.rst
index f3b605285a87..cccafdaa1f84 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.rst
+++ b/Documentation/RCU/Design/Requirements/Requirements.rst
@@ -1955,12 +1955,12 @@ if offline CPUs block an RCU grace period for too long.
An offline CPU's quiescent state will be reported either:
-1. As the CPU goes offline using RCU's hotplug notifier (rcu_report_dead()).
+1. As the CPU goes offline using RCU's hotplug notifier (rcutree_report_cpu_dead()).
2. When grace period initialization (rcu_gp_init()) detects a
race either with CPU offlining or with a task unblocking on a leaf
``rcu_node`` structure whose CPUs are all offline.
-The CPU-online path (rcu_cpu_starting()) should never need to report
+The CPU-online path (rcutree_report_cpu_starting()) should never need to report
a quiescent state for an offline CPU. However, as a debugging measure,
it does emit a warning if a quiescent state was not already reported
for that CPU.
diff --git a/Documentation/RCU/listRCU.rst b/Documentation/RCU/listRCU.rst
index bdc4bcc5289f..ed5c9d8c9afe 100644
--- a/Documentation/RCU/listRCU.rst
+++ b/Documentation/RCU/listRCU.rst
@@ -8,6 +8,15 @@ One of the most common uses of RCU is protecting read-mostly linked lists
that all of the required memory ordering is provided by the list macros.
This document describes several list-based RCU use cases.
+When iterating a list while holding the rcu_read_lock(), writers may
+modify the list. The reader is guaranteed to see all of the elements
+which were added to the list before they acquired the rcu_read_lock()
+and are still on the list when they drop the rcu_read_unlock().
+Elements which are added to, or removed from the list may or may not
+be seen. If the writer calls list_replace_rcu(), the reader may see
+either the old element or the new element; they will not see both,
+nor will they see neither.
+
Example 1: Read-mostly list: Deferred Destruction
-------------------------------------------------
diff --git a/Documentation/RCU/whatisRCU.rst b/Documentation/RCU/whatisRCU.rst
index e488c8e557a9..60ce02475142 100644
--- a/Documentation/RCU/whatisRCU.rst
+++ b/Documentation/RCU/whatisRCU.rst
@@ -59,8 +59,8 @@ experiment with should focus on Section 2. People who prefer to start
with example uses should focus on Sections 3 and 4. People who need to
understand the RCU implementation should focus on Section 5, then dive
into the kernel source code. People who reason best by analogy should
-focus on Section 6. Section 7 serves as an index to the docbook API
-documentation, and Section 8 is the traditional answer key.
+focus on Section 6 and 7. Section 8 serves as an index to the docbook
+API documentation, and Section 9 is the traditional answer key.
So, start with the section that makes the most sense to you and your
preferred method of learning. If you need to know everything about
diff --git a/Documentation/accel/qaic/qaic.rst b/Documentation/accel/qaic/qaic.rst
index 72a70ab6e3a8..c88502383136 100644
--- a/Documentation/accel/qaic/qaic.rst
+++ b/Documentation/accel/qaic/qaic.rst
@@ -123,6 +123,16 @@ DRM_IOCTL_QAIC_PART_DEV
AIC100 device and can be used for limiting a process to some subset of
resources.
+DRM_IOCTL_QAIC_DETACH_SLICE_BO
+ This IOCTL allows userspace to remove the slicing information from a BO that
+ was originally provided by a call to DRM_IOCTL_QAIC_ATTACH_SLICE_BO. This
+ is the inverse of DRM_IOCTL_QAIC_ATTACH_SLICE_BO. The BO must be idle for
+ DRM_IOCTL_QAIC_DETACH_SLICE_BO to be called. After a successful detach slice
+ operation the BO may have new slicing information attached with a new call
+ to DRM_IOCTL_QAIC_ATTACH_SLICE_BO. After detach slice, the BO cannot be
+ executed until after a new attach slice operation. Combining attach slice
+ and detach slice calls allows userspace to use a BO with multiple workloads.
+
Userspace Client Isolation
==========================
diff --git a/Documentation/admin-guide/cgroup-v1/memory.rst b/Documentation/admin-guide/cgroup-v1/memory.rst
index ff456871bf4b..ca7d9402f6be 100644
--- a/Documentation/admin-guide/cgroup-v1/memory.rst
+++ b/Documentation/admin-guide/cgroup-v1/memory.rst
@@ -551,6 +551,7 @@ memory.stat file includes following statistics:
event happens each time a page is unaccounted from the
cgroup.
swap # of bytes of swap usage
+ swapcached # of bytes of swap cached in memory
dirty # of bytes that are waiting to get written back to the disk.
writeback # of bytes of file/anon cache that are queued for syncing to
disk.
diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index b26b5274eaaf..3f85254f3cef 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -210,6 +210,35 @@ cgroup v2 currently supports the following mount options.
relying on the original semantics (e.g. specifying bogusly
high 'bypass' protection values at higher tree levels).
+ memory_hugetlb_accounting
+ Count HugeTLB memory usage towards the cgroup's overall
+ memory usage for the memory controller (for the purpose of
+ statistics reporting and memory protetion). This is a new
+ behavior that could regress existing setups, so it must be
+ explicitly opted in with this mount option.
+
+ A few caveats to keep in mind:
+
+ * There is no HugeTLB pool management involved in the memory
+ controller. The pre-allocated pool does not belong to anyone.
+ Specifically, when a new HugeTLB folio is allocated to
+ the pool, it is not accounted for from the perspective of the
+ memory controller. It is only charged to a cgroup when it is
+ actually used (for e.g at page fault time). Host memory
+ overcommit management has to consider this when configuring
+ hard limits. In general, HugeTLB pool management should be
+ done via other mechanisms (such as the HugeTLB controller).
+ * Failure to charge a HugeTLB folio to the memory controller
+ results in SIGBUS. This could happen even if the HugeTLB pool
+ still has pages available (but the cgroup limit is hit and
+ reclaim attempt fails).
+ * Charging HugeTLB memory towards the memory controller affects
+ memory protection and reclaim dynamics. Any userspace tuning
+ (of low, min limits for e.g) needs to take this into account.
+ * HugeTLB pages utilized while this option is not selected
+ will not be tracked by the memory controller (even if cgroup
+ v2 is remounted later on).
+
Organizing Processes and Threads
--------------------------------
@@ -364,6 +393,13 @@ constraint, a threaded controller must be able to handle competition
between threads in a non-leaf cgroup and its child cgroups. Each
threaded controller defines how such competitions are handled.
+Currently, the following controllers are threaded and can be enabled
+in a threaded cgroup::
+
+- cpu
+- cpuset
+- perf_event
+- pids
[Un]populated Notification
--------------------------
@@ -1532,6 +1568,15 @@ PAGE_SIZE multiple when read back.
collapsing an existing range of pages. This counter is not
present when CONFIG_TRANSPARENT_HUGEPAGE is not set.
+ thp_swpout (npn)
+ Number of transparent hugepages which are swapout in one piece
+ without splitting.
+
+ thp_swpout_fallback (npn)
+ Number of transparent hugepages which were split before swapout.
+ Usually because failed to allocate some continuous swap space
+ for the huge page.
+
memory.numa_stat
A read-only nested-keyed file which exists on non-root cgroups.
@@ -2023,7 +2068,7 @@ IO Priority
~~~~~~~~~~~
A single attribute controls the behavior of the I/O priority cgroup policy,
-namely the blkio.prio.class attribute. The following values are accepted for
+namely the io.prio.class attribute. The following values are accepted for
that attribute:
no-change
@@ -2052,9 +2097,11 @@ The following numerical values are associated with the I/O priority policies:
+----------------+---+
| no-change | 0 |
+----------------+---+
-| rt-to-be | 2 |
+| promote-to-rt | 1 |
+----------------+---+
-| all-to-idle | 3 |
+| restrict-to-be | 2 |
++----------------+---+
+| idle | 3 |
+----------------+---+
The numerical value that corresponds to each I/O priority class is as follows:
@@ -2074,7 +2121,7 @@ The algorithm to set the I/O priority class for a request is as follows:
- If I/O priority class policy is promote-to-rt, change the request I/O
priority class to IOPRIO_CLASS_RT and change the request I/O priority
level to 4.
-- If I/O priorityt class is not promote-to-rt, translate the I/O priority
+- If I/O priority class policy is not promote-to-rt, translate the I/O priority
class policy into a number, then change the request I/O priority class
into the maximum of the I/O priority class policy number and the numerical
I/O priority class.
@@ -2226,6 +2273,49 @@ Cpuset Interface Files
Its value will be affected by memory nodes hotplug events.
+ cpuset.cpus.exclusive
+ A read-write multiple values file which exists on non-root
+ cpuset-enabled cgroups.
+
+ It lists all the exclusive CPUs that are allowed to be used
+ to create a new cpuset partition. Its value is not used
+ unless the cgroup becomes a valid partition root. See the
+ "cpuset.cpus.partition" section below for a description of what
+ a cpuset partition is.
+
+ When the cgroup becomes a partition root, the actual exclusive
+ CPUs that are allocated to that partition are listed in
+ "cpuset.cpus.exclusive.effective" which may be different
+ from "cpuset.cpus.exclusive". If "cpuset.cpus.exclusive"
+ has previously been set, "cpuset.cpus.exclusive.effective"
+ is always a subset of it.
+
+ Users can manually set it to a value that is different from
+ "cpuset.cpus". The only constraint in setting it is that the
+ list of CPUs must be exclusive with respect to its sibling.
+
+ For a parent cgroup, any one of its exclusive CPUs can only
+ be distributed to at most one of its child cgroups. Having an
+ exclusive CPU appearing in two or more of its child cgroups is
+ not allowed (the exclusivity rule). A value that violates the
+ exclusivity rule will be rejected with a write error.
+
+ The root cgroup is a partition root and all its available CPUs
+ are in its exclusive CPU set.
+
+ cpuset.cpus.exclusive.effective
+ A read-only multiple values file which exists on all non-root
+ cpuset-enabled cgroups.
+
+ This file shows the effective set of exclusive CPUs that
+ can be used to create a partition root. The content of this
+ file will always be a subset of "cpuset.cpus" and its parent's
+ "cpuset.cpus.exclusive.effective" if its parent is not the root
+ cgroup. It will also be a subset of "cpuset.cpus.exclusive"
+ if it is set. If "cpuset.cpus.exclusive" is not set, it is
+ treated to have an implicit value of "cpuset.cpus" in the
+ formation of local partition.
+
cpuset.cpus.partition
A read-write single value file which exists on non-root
cpuset-enabled cgroups. This flag is owned by the parent cgroup
@@ -2239,26 +2329,41 @@ Cpuset Interface Files
"isolated" Partition root without load balancing
========== =====================================
- The root cgroup is always a partition root and its state
- cannot be changed. All other non-root cgroups start out as
- "member".
+ A cpuset partition is a collection of cpuset-enabled cgroups with
+ a partition root at the top of the hierarchy and its descendants
+ except those that are separate partition roots themselves and
+ their descendants. A partition has exclusive access to the
+ set of exclusive CPUs allocated to it. Other cgroups outside
+ of that partition cannot use any CPUs in that set.
+
+ There are two types of partitions - local and remote. A local
+ partition is one whose parent cgroup is also a valid partition
+ root. A remote partition is one whose parent cgroup is not a
+ valid partition root itself. Writing to "cpuset.cpus.exclusive"
+ is optional for the creation of a local partition as its
+ "cpuset.cpus.exclusive" file will assume an implicit value that
+ is the same as "cpuset.cpus" if it is not set. Writing the
+ proper "cpuset.cpus.exclusive" values down the cgroup hierarchy
+ before the target partition root is mandatory for the creation
+ of a remote partition.
+
+ Currently, a remote partition cannot be created under a local
+ partition. All the ancestors of a remote partition root except
+ the root cgroup cannot be a partition root.
+
+ The root cgroup is always a partition root and its state cannot
+ be changed. All other non-root cgroups start out as "member".
When set to "root", the current cgroup is the root of a new
- partition or scheduling domain that comprises itself and all
- its descendants except those that are separate partition roots
- themselves and their descendants.
+ partition or scheduling domain. The set of exclusive CPUs is
+ determined by the value of its "cpuset.cpus.exclusive.effective".
- When set to "isolated", the CPUs in that partition root will
+ When set to "isolated", the CPUs in that partition will
be in an isolated state without any load balancing from the
scheduler. Tasks placed in such a partition with multiple
CPUs should be carefully distributed and bound to each of the
individual CPUs for optimal performance.
- The value shown in "cpuset.cpus.effective" of a partition root
- is the CPUs that the partition root can dedicate to a potential
- new child partition root. The new child subtracts available
- CPUs from its parent "cpuset.cpus.effective".
-
A partition root ("root" or "isolated") can be in one of the
two possible states - valid or invalid. An invalid partition
root is in a degraded state where some state information may
@@ -2281,37 +2386,33 @@ Cpuset Interface Files
In the case of an invalid partition root, a descriptive string on
why the partition is invalid is included within parentheses.
- For a partition root to become valid, the following conditions
+ For a local partition root to be valid, the following conditions
must be met.
- 1) The "cpuset.cpus" is exclusive with its siblings , i.e. they
- are not shared by any of its siblings (exclusivity rule).
- 2) The parent cgroup is a valid partition root.
- 3) The "cpuset.cpus" is not empty and must contain at least
- one of the CPUs from parent's "cpuset.cpus", i.e. they overlap.
- 4) The "cpuset.cpus.effective" cannot be empty unless there is
+ 1) The parent cgroup is a valid partition root.
+ 2) The "cpuset.cpus.exclusive.effective" file cannot be empty,
+ though it may contain offline CPUs.
+ 3) The "cpuset.cpus.effective" cannot be empty unless there is
no task associated with this partition.
- External events like hotplug or changes to "cpuset.cpus" can
- cause a valid partition root to become invalid and vice versa.
- Note that a task cannot be moved to a cgroup with empty
- "cpuset.cpus.effective".
+ For a remote partition root to be valid, all the above conditions
+ except the first one must be met.
- For a valid partition root with the sibling cpu exclusivity
- rule enabled, changes made to "cpuset.cpus" that violate the
- exclusivity rule will invalidate the partition as well as its
- sibling partitions with conflicting cpuset.cpus values. So
- care must be taking in changing "cpuset.cpus".
+ External events like hotplug or changes to "cpuset.cpus" or
+ "cpuset.cpus.exclusive" can cause a valid partition root to
+ become invalid and vice versa. Note that a task cannot be
+ moved to a cgroup with empty "cpuset.cpus.effective".
A valid non-root parent partition may distribute out all its CPUs
- to its child partitions when there is no task associated with it.
+ to its child local partitions when there is no task associated
+ with it.
- Care must be taken to change a valid partition root to
- "member" as all its child partitions, if present, will become
+ Care must be taken to change a valid partition root to "member"
+ as all its child local partitions, if present, will become
invalid causing disruption to tasks running in those child
partitions. These inactivated partitions could be recovered if
their parent is switched back to a partition root with a proper
- set of "cpuset.cpus".
+ value in "cpuset.cpus" or "cpuset.cpus.exclusive".
Poll and inotify events are triggered whenever the state of
"cpuset.cpus.partition" changes. That includes changes caused
@@ -2321,6 +2422,11 @@ Cpuset Interface Files
to "cpuset.cpus.partition" without the need to do continuous
polling.
+ A user can pre-configure certain CPUs to an isolated state
+ with load balancing disabled at boot time with the "isolcpus"
+ kernel boot command line option. If those CPUs are to be put
+ into a partition, they have to be used in an isolated partition.
+
Device controller
-----------------
diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index 0b3d39c610d9..0c526dac8428 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -259,7 +259,7 @@ Debug Messages at Module Initialization Time
When ``modprobe foo`` is called, modprobe scans ``/proc/cmdline`` for
``foo.params``, strips ``foo.``, and passes them to the kernel along with
-params given in modprobe args or ``/etc/modprob.d/*.conf`` files,
+params given in modprobe args or ``/etc/modprobe.d/*.conf`` files,
in the following order:
1. parameters given via ``/etc/modprobe.d/*.conf``::
diff --git a/Documentation/admin-guide/efi-stub.rst b/Documentation/admin-guide/efi-stub.rst
index b24e7c40d832..090f3a185e18 100644
--- a/Documentation/admin-guide/efi-stub.rst
+++ b/Documentation/admin-guide/efi-stub.rst
@@ -15,7 +15,7 @@ between architectures is in drivers/firmware/efi/libstub.
For arm64, there is no compressed kernel support, so the Image itself
masquerades as a PE/COFF image and the EFI stub is linked into the
-kernel. The arm64 EFI stub lives in arch/arm64/kernel/efi-entry.S
+kernel. The arm64 EFI stub lives in drivers/firmware/efi/libstub/arm64.c
and drivers/firmware/efi/libstub/arm64-stub.c.
By using the EFI boot stub it's possible to boot a Linux kernel
diff --git a/Documentation/admin-guide/hw-vuln/mds.rst b/Documentation/admin-guide/hw-vuln/mds.rst
index 48ca0bd85604..48c7b0b72aed 100644
--- a/Documentation/admin-guide/hw-vuln/mds.rst
+++ b/Documentation/admin-guide/hw-vuln/mds.rst
@@ -102,9 +102,19 @@ The possible values in this file are:
* - 'Vulnerable'
- The processor is vulnerable, but no mitigation enabled
* - 'Vulnerable: Clear CPU buffers attempted, no microcode'
- - The processor is vulnerable but microcode is not updated.
-
- The mitigation is enabled on a best effort basis. See :ref:`vmwerv`
+ - The processor is vulnerable but microcode is not updated. The
+ mitigation is enabled on a best effort basis.
+
+ If the processor is vulnerable but the availability of the microcode
+ based mitigation mechanism is not advertised via CPUID, the kernel
+ selects a best effort mitigation mode. This mode invokes the mitigation
+ instructions without a guarantee that they clear the CPU buffers.
+
+ This is done to address virtualization scenarios where the host has the
+ microcode update applied, but the hypervisor is not yet updated to
+ expose the CPUID to the guest. If the host has updated microcode the
+ protection takes effect; otherwise a few CPU cycles are wasted
+ pointlessly.
* - 'Mitigation: Clear CPU buffers'
- The processor is vulnerable and the CPU buffer clearing mitigation is
enabled.
@@ -119,24 +129,6 @@ to the above information:
'SMT Host state unknown' Kernel runs in a VM, Host SMT state unknown
======================== ============================================
-.. _vmwerv:
-
-Best effort mitigation mode
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- If the processor is vulnerable, but the availability of the microcode based
- mitigation mechanism is not advertised via CPUID the kernel selects a best
- effort mitigation mode. This mode invokes the mitigation instructions
- without a guarantee that they clear the CPU buffers.
-
- This is done to address virtualization scenarios where the host has the
- microcode update applied, but the hypervisor is not yet updated to expose
- the CPUID to the guest. If the host has updated microcode the protection
- takes effect otherwise a few cpu cycles are wasted pointlessly.
-
- The state in the mds sysfs file reflects this situation accordingly.
-
-
Mitigation mechanism
-------------------------
diff --git a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
index c98fd11907cc..1302fd1b55e8 100644
--- a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
+++ b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
@@ -225,8 +225,19 @@ The possible values in this file are:
* - 'Vulnerable'
- The processor is vulnerable, but no mitigation enabled
* - 'Vulnerable: Clear CPU buffers attempted, no microcode'
- - The processor is vulnerable, but microcode is not updated. The
+ - The processor is vulnerable but microcode is not updated. The
mitigation is enabled on a best effort basis.
+
+ If the processor is vulnerable but the availability of the microcode
+ based mitigation mechanism is not advertised via CPUID, the kernel
+ selects a best effort mitigation mode. This mode invokes the mitigation
+ instructions without a guarantee that they clear the CPU buffers.
+
+ This is done to address virtualization scenarios where the host has the
+ microcode update applied, but the hypervisor is not yet updated to
+ expose the CPUID to the guest. If the host has updated microcode the
+ protection takes effect; otherwise a few CPU cycles are wasted
+ pointlessly.
* - 'Mitigation: Clear CPU buffers'
- The processor is vulnerable and the CPU buffer clearing mitigation is
enabled.
diff --git a/Documentation/admin-guide/hw-vuln/srso.rst b/Documentation/admin-guide/hw-vuln/srso.rst
index b6cfb51cb0b4..e715bfc09879 100644
--- a/Documentation/admin-guide/hw-vuln/srso.rst
+++ b/Documentation/admin-guide/hw-vuln/srso.rst
@@ -46,12 +46,22 @@ The possible values in this file are:
The processor is not vulnerable
- * 'Vulnerable: no microcode':
+* 'Vulnerable':
+
+ The processor is vulnerable and no mitigations have been applied.
+
+ * 'Vulnerable: No microcode':
The processor is vulnerable, no microcode extending IBPB
functionality to address the vulnerability has been applied.
- * 'Mitigation: microcode':
+ * 'Vulnerable: Safe RET, no microcode':
+
+ The "Safe RET" mitigation (see below) has been applied to protect the
+ kernel, but the IBPB-extending microcode has not been applied. User
+ space tasks may still be vulnerable.
+
+ * 'Vulnerable: Microcode, no safe RET':
Extended IBPB functionality microcode patch has been applied. It does
not address User->Kernel and Guest->Host transitions protection but it
@@ -72,11 +82,11 @@ The possible values in this file are:
(spec_rstack_overflow=microcode)
- * 'Mitigation: safe RET':
+ * 'Mitigation: Safe RET':
- Software-only mitigation. It complements the extended IBPB microcode
- patch functionality by addressing User->Kernel and Guest->Host
- transitions protection.
+ Combined microcode/software mitigation. It complements the
+ extended IBPB microcode patch functionality by addressing
+ User->Kernel and Guest->Host transitions protection.
Selected by default or by spec_rstack_overflow=safe-ret
@@ -129,7 +139,7 @@ an indrect branch prediction barrier after having applied the required
microcode patch for one's system. This mitigation comes also at
a performance cost.
-Mitigation: safe RET
+Mitigation: Safe RET
--------------------
The mitigation works by ensuring all RET instructions speculate to
diff --git a/Documentation/admin-guide/hw-vuln/tsx_async_abort.rst b/Documentation/admin-guide/hw-vuln/tsx_async_abort.rst
index 014167ef8dd1..444f84e22a91 100644
--- a/Documentation/admin-guide/hw-vuln/tsx_async_abort.rst
+++ b/Documentation/admin-guide/hw-vuln/tsx_async_abort.rst
@@ -98,7 +98,19 @@ The possible values in this file are:
* - 'Vulnerable'
- The CPU is affected by this vulnerability and the microcode and kernel mitigation are not applied.
* - 'Vulnerable: Clear CPU buffers attempted, no microcode'
- - The system tries to clear the buffers but the microcode might not support the operation.
+ - The processor is vulnerable but microcode is not updated. The
+ mitigation is enabled on a best effort basis.
+
+ If the processor is vulnerable but the availability of the microcode
+ based mitigation mechanism is not advertised via CPUID, the kernel
+ selects a best effort mitigation mode. This mode invokes the mitigation
+ instructions without a guarantee that they clear the CPU buffers.
+
+ This is done to address virtualization scenarios where the host has the
+ microcode update applied, but the hypervisor is not yet updated to
+ expose the CPUID to the guest. If the host has updated microcode the
+ protection takes effect; otherwise a few CPU cycles are wasted
+ pointlessly.
* - 'Mitigation: Clear CPU buffers'
- The microcode has been updated to clear the buffers. TSX is still enabled.
* - 'Mitigation: TSX disabled'
@@ -106,25 +118,6 @@ The possible values in this file are:
* - 'Not affected'
- The CPU is not affected by this issue.
-.. _ucode_needed:
-
-Best effort mitigation mode
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-If the processor is vulnerable, but the availability of the microcode-based
-mitigation mechanism is not advertised via CPUID the kernel selects a best
-effort mitigation mode. This mode invokes the mitigation instructions
-without a guarantee that they clear the CPU buffers.
-
-This is done to address virtualization scenarios where the host has the
-microcode update applied, but the hypervisor is not yet updated to expose the
-CPUID to the guest. If the host has updated microcode the protection takes
-effect; otherwise a few CPU cycles are wasted pointlessly.
-
-The state in the tsx_async_abort sysfs file reflects this situation
-accordingly.
-
-
Mitigation mechanism
--------------------
diff --git a/Documentation/admin-guide/kdump/kdump.rst b/Documentation/admin-guide/kdump/kdump.rst
index a748e7eb4429..5762e7477a0c 100644
--- a/Documentation/admin-guide/kdump/kdump.rst
+++ b/Documentation/admin-guide/kdump/kdump.rst
@@ -17,7 +17,7 @@ You can use common commands, such as cp, scp or makedumpfile to copy
the memory image to a dump file on the local disk, or across the network
to a remote system.
-Kdump and kexec are currently supported on the x86, x86_64, ppc64, ia64,
+Kdump and kexec are currently supported on the x86, x86_64, ppc64,
s390x, arm and arm64 architectures.
When the system kernel boots, it reserves a small section of memory for
@@ -113,7 +113,7 @@ There are two possible methods of using Kdump.
2) Or use the system kernel binary itself as dump-capture kernel and there is
no need to build a separate dump-capture kernel. This is possible
only with the architectures which support a relocatable kernel. As
- of today, i386, x86_64, ppc64, ia64, arm and arm64 architectures support
+ of today, i386, x86_64, ppc64, arm and arm64 architectures support
relocatable kernel.
Building a relocatable kernel is advantageous from the point of view that
@@ -236,24 +236,6 @@ Dump-capture kernel config options (Arch Dependent, ppc64)
Make and install the kernel and its modules.
-Dump-capture kernel config options (Arch Dependent, ia64)
-----------------------------------------------------------
-
-- No specific options are required to create a dump-capture kernel
- for ia64, other than those specified in the arch independent section
- above. This means that it is possible to use the system kernel
- as a dump-capture kernel if desired.
-
- The crashkernel region can be automatically placed by the system
- kernel at runtime. This is done by specifying the base address as 0,
- or omitting it all together::
-
- crashkernel=256M@0
-
- or::
-
- crashkernel=256M
-
Dump-capture kernel config options (Arch Dependent, arm)
----------------------------------------------------------
@@ -348,11 +330,6 @@ Boot into System Kernel
On ppc64, use "crashkernel=128M@32M".
- On ia64, 256M@256M is a generous value that typically works.
- The region may be automatically placed on ia64, see the
- dump-capture kernel config option notes above.
- If use sparse memory, the size should be rounded to GRANULE boundaries.
-
On s390x, typically use "crashkernel=xxM". The value of xx is dependent
on the memory consumption of the kdump system. In general this is not
dependent on the memory size of the production system.
@@ -383,10 +360,6 @@ For ppc64:
- Use vmlinux
-For ia64:
-
- - Use vmlinux or vmlinuz.gz
-
For s390x:
- Use image or bzImage
@@ -428,14 +401,10 @@ to load dump-capture kernel::
--initrd=<initrd-for-dump-capture-kernel> \
--append="root=<root-dev> <arch-specific-options>"
-Please note, that --args-linux does not need to be specified for ia64.
-It is planned to make this a no-op on that architecture, but for now
-it should be omitted
-
Following are the arch specific command line options to be used while
loading dump-capture kernel.
-For i386, x86_64 and ia64:
+For i386 and x86_64:
"1 irqpoll nr_cpus=1 reset_devices"
diff --git a/Documentation/admin-guide/kdump/vmcoreinfo.rst b/Documentation/admin-guide/kdump/vmcoreinfo.rst
index 599e8d3bcbc3..78e4d2e7ba14 100644
--- a/Documentation/admin-guide/kdump/vmcoreinfo.rst
+++ b/Documentation/admin-guide/kdump/vmcoreinfo.rst
@@ -413,36 +413,6 @@ of a higher page table lookup overhead, and also consumes more page
table space per process. Used to check whether PAE was enabled in the
crash kernel when converting virtual addresses to physical addresses.
-ia64
-====
-
-pgdat_list|(pgdat_list, MAX_NUMNODES)
--------------------------------------
-
-pg_data_t array storing all NUMA nodes information. MAX_NUMNODES
-indicates the number of the nodes.
-
-node_memblk|(node_memblk, NR_NODE_MEMBLKS)
-------------------------------------------
-
-List of node memory chunks. Filled when parsing the SRAT table to obtain
-information about memory nodes. NR_NODE_MEMBLKS indicates the number of
-node memory chunks.
-
-These values are used to compute the number of nodes the crashed kernel used.
-
-node_memblk_s|(node_memblk_s, start_paddr)|(node_memblk_s, size)
-----------------------------------------------------------------
-
-The size of a struct node_memblk_s and the offsets of the
-node_memblk_s's members. Used to compute the number of nodes.
-
-PGTABLE_3|PGTABLE_4
--------------------
-
-User-space tools need to know whether the crash kernel was in 3-level or
-4-level paging mode. Used to distinguish the page table.
-
ARM64
=====
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 0a1731a0f0ef..65731b060e3f 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -580,6 +580,10 @@
named mounts. Specifying both "all" and "named" disables
all v1 hierarchies.
+ cgroup_favordynmods= [KNL] Enable or Disable favordynmods.
+ Format: { "true" | "false" }
+ Defaults to the value of CONFIG_CGROUP_FAVOR_DYNMODS.
+
cgroup.memory= [KNL] Pass options to the cgroup memory controller.
Format: <string>
nosocket -- Disable socket memory accounting.
@@ -1331,6 +1335,7 @@
earlyprintk=dbgp[debugController#]
earlyprintk=pciserial[,force],bus:device.function[,baudrate]
earlyprintk=xdbc[xhciController#]
+ earlyprintk=bios
earlyprintk is useful when the kernel crashes before
the normal console is initialized. It is not enabled by
@@ -1361,6 +1366,8 @@
The sclp output can only be used on s390.
+ The bios output can only be used on SuperH.
+
The optional "force" to "pciserial" enables use of a
PCI device even when its classcode is not of the
UART class.
@@ -1449,7 +1456,7 @@
See comment before function elanfreq_setup() in
arch/x86/kernel/cpu/cpufreq/elanfreq.c.
- elfcorehdr=[size[KMG]@]offset[KMG] [IA64,PPC,SH,X86,S390]
+ elfcorehdr=[size[KMG]@]offset[KMG] [PPC,SH,X86,S390]
Specifies physical address of start of kernel core
image elf header and optionally the size. Generally
kexec loader will pass this option to capture kernel.
@@ -1512,12 +1519,6 @@
floppy= [HW]
See Documentation/admin-guide/blockdev/floppy.rst.
- force_pal_cache_flush
- [IA-64] Avoid check_sal_cache_flush which may hang on
- buggy SAL_CACHE_FLUSH implementations. Using this
- parameter will force ia64_sal_cache_flush to call
- ia64_pal_cache_flush instead of SAL_CACHE_FLUSH.
-
forcepae [X86-32]
Forcefully enable Physical Address Extension (PAE).
Many Pentium M systems disable PAE but may have a
@@ -1893,6 +1894,12 @@
0 -- machine default
1 -- force brightness inversion
+ ia32_emulation= [X86-64]
+ Format: <bool>
+ When true, allows loading 32-bit programs and executing 32-bit
+ syscalls, essentially overriding IA32_EMULATION_DEFAULT_DISABLED at
+ boot time. When false, unconditionally disables IA32 emulation.
+
icn= [HW,ISDN]
Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]]
@@ -2220,7 +2227,7 @@
forcing Dual Address Cycle for PCI cards supporting
greater than 32-bit addressing.
- iommu.strict= [ARM64, X86] Configure TLB invalidation behaviour
+ iommu.strict= [ARM64, X86, S390] Configure TLB invalidation behaviour
Format: { "0" | "1" }
0 - Lazy mode.
Request that DMA unmap operations use deferred
@@ -2913,6 +2920,38 @@
to extract confidential information from the kernel
are also disabled.
+ locktorture.acq_writer_lim= [KNL]
+ Set the time limit in jiffies for a lock
+ acquisition. Acquisitions exceeding this limit
+ will result in a splat once they do complete.
+
+ locktorture.bind_readers= [KNL]
+ Specify the list of CPUs to which the readers are
+ to be bound.
+
+ locktorture.bind_writers= [KNL]
+ Specify the list of CPUs to which the writers are
+ to be bound.
+
+ locktorture.call_rcu_chains= [KNL]
+ Specify the number of self-propagating call_rcu()
+ chains to set up. These are used to ensure that
+ there is a high probability of an RCU grace period
+ in progress at any given time. Defaults to 0,
+ which disables these call_rcu() chains.
+
+ locktorture.long_hold= [KNL]
+ Specify the duration in milliseconds for the
+ occasional long-duration lock hold time. Defaults
+ to 100 milliseconds. Select 0 to disable.
+
+ locktorture.nested_locks= [KNL]
+ Specify the maximum lock nesting depth that
+ locktorture is to exercise, up to a limit of 8
+ (MAX_NESTED_LOCKS). Specify zero to disable.
+ Note that this parameter is ineffective on types
+ of locks that do not support nested acquisition.
+
locktorture.nreaders_stress= [KNL]
Set the number of locking read-acquisition kthreads.
Defaults to being automatically set based on the
@@ -2928,6 +2967,25 @@
Set time (s) between CPU-hotplug operations, or
zero to disable CPU-hotplug testing.
+ locktorture.rt_boost= [KNL]
+ Do periodic testing of real-time lock priority
+ boosting. Select 0 to disable, 1 to boost
+ only rt_mutex, and 2 to boost unconditionally.
+ Defaults to 2, which might seem to be an
+ odd choice, but which should be harmless for
+ non-real-time spinlocks, due to their disabling
+ of preemption. Note that non-realtime mutexes
+ disable boosting.
+
+ locktorture.rt_boost_factor= [KNL]
+ Number that determines how often and for how
+ long priority boosting is exercised. This is
+ scaled down by the number of writers, so that the
+ number of boosts per unit time remains roughly
+ constant as the number of writers increases.
+ On the other hand, the duration of each boost
+ increases with the number of writers.
+
locktorture.shuffle_interval= [KNL]
Set task-shuffle interval (jiffies). Shuffling
tasks allows some CPUs to go into dyntick-idle
@@ -2950,13 +3008,13 @@
locktorture.torture_type= [KNL]
Specify the locking implementation to test.
+ locktorture.verbose= [KNL]
+ Enable additional printk() statements.
+
locktorture.writer_fifo= [KNL]
Run the write-side locktorture kthreads at
sched_set_fifo() real-time priority.
- locktorture.verbose= [KNL]
- Enable additional printk() statements.
-
logibm.irq= [HW,MOUSE] Logitech Bus Mouse Driver
Format: <irq>
@@ -3275,6 +3333,11 @@
mga= [HW,DRM]
+ microcode.force_minrev= [X86]
+ Format: <bool>
+ Enable or disable the microcode minimal revision
+ enforcement for the runtime microcode loader.
+
min_addr=nn[KMG] [KNL,BOOT,IA-64] All physical memory below this
physical address is ignored.
@@ -3533,6 +3596,13 @@
[NFS] set the TCP port on which the NFSv4 callback
channel should listen.
+ nfs.delay_retrans=
+ [NFS] specifies the number of times the NFSv4 client
+ retries the request before returning an EAGAIN error,
+ after a reply of NFS4ERR_DELAY from the server.
+ Only applies if the softerr mount option is enabled,
+ and the specified value is >= 0.
+
nfs.enable_ino64=
[NFS] enable 64-bit inode numbers.
If zero, the NFS client will fake up a 32-bit inode
@@ -4769,6 +4839,13 @@
Set maximum number of finished RCU callbacks to
process in one batch.
+ rcutree.do_rcu_barrier= [KNL]
+ Request a call to rcu_barrier(). This is
+ throttled so that userspace tests can safely
+ hammer on the sysfs variable if they so choose.
+ If triggered before the RCU grace-period machinery
+ is fully active, this will error out with EAGAIN.
+
rcutree.dump_tree= [KNL]
Dump the structure of the rcu_node combining tree
out at early boot. This is used for diagnostic
@@ -5422,6 +5499,12 @@
test until boot completes in order to avoid
interference.
+ refscale.lookup_instances= [KNL]
+ Number of data elements to use for the forms of
+ SLAB_TYPESAFE_BY_RCU testing. A negative number
+ is negated and multiplied by nr_cpu_ids, while
+ zero specifies nr_cpu_ids.
+
refscale.loops= [KNL]
Set the number of loops over the synchronization
primitive under test. Increasing this number
@@ -5611,9 +5694,10 @@
s390_iommu= [HW,S390]
Set s390 IOTLB flushing mode
strict
- With strict flushing every unmap operation will result in
- an IOTLB flush. Default is lazy flushing before reuse,
- which is faster.
+ With strict flushing every unmap operation will result
+ in an IOTLB flush. Default is lazy flushing before
+ reuse, which is faster. Deprecated, equivalent to
+ iommu.strict=1.
s390_iommu_aperture= [KNL,S390]
Specifies the size of the per device DMA address space
@@ -5858,6 +5942,13 @@
This feature may be more efficiently disabled
using the csdlock_debug- kernel parameter.
+ smp.panic_on_ipistall= [KNL]
+ If a csd_lock_timeout extends for more than
+ the specified number of milliseconds, panic the
+ system. By default, let CSD-lock acquisition
+ take as long as they take. Specifying 300,000
+ for this value provides a 5-minute timeout.
+
smsc-ircc2.nopnp [HW] Don't use PNP to discover SMC devices
smsc-ircc2.ircc_cfg= [HW] Device configuration I/O port
smsc-ircc2.ircc_sir= [HW] SIR base I/O port
diff --git a/Documentation/admin-guide/laptops/thinkpad-acpi.rst b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
index e27a1c3f634e..98d304010170 100644
--- a/Documentation/admin-guide/laptops/thinkpad-acpi.rst
+++ b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
@@ -53,6 +53,7 @@ detailed description):
- Lap mode sensor
- Setting keyboard language
- WWAN Antenna type
+ - Auxmac
A compatibility table by model and feature is maintained on the web
site, http://ibm-acpi.sf.net/. I appreciate any success or failure
@@ -1511,6 +1512,25 @@ Currently 2 antenna types are supported as mentioned below:
The property is read-only. If the platform doesn't have support the sysfs
class is not created.
+Auxmac
+------
+
+sysfs: auxmac
+
+Some newer Thinkpads have a feature called MAC Address Pass-through. This
+feature is implemented by the system firmware to provide a system unique MAC,
+that can override a dock or USB ethernet dongle MAC, when connected to a
+network. This property enables user-space to easily determine the MAC address
+if the feature is enabled.
+
+The values of this auxiliary MAC are:
+
+ cat /sys/devices/platform/thinkpad_acpi/auxmac
+
+If the feature is disabled, the value will be 'disabled'.
+
+This property is read-only.
+
Adaptive keyboard
-----------------
diff --git a/Documentation/admin-guide/media/mgb4.rst b/Documentation/admin-guide/media/mgb4.rst
new file mode 100644
index 000000000000..2977f74d7e26
--- /dev/null
+++ b/Documentation/admin-guide/media/mgb4.rst
@@ -0,0 +1,374 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+====================
+mgb4 sysfs interface
+====================
+
+The mgb4 driver provides a sysfs interface, that is used to configure video
+stream related parameters (some of them must be set properly before the v4l2
+device can be opened) and obtain the video device/stream status.
+
+There are two types of parameters - global / PCI card related, found under
+``/sys/class/video4linux/videoX/device`` and module specific found under
+``/sys/class/video4linux/videoX``.
+
+
+Global (PCI card) parameters
+============================
+
+**module_type** (R):
+ Module type.
+
+ | 0 - No module present
+ | 1 - FPDL3
+ | 2 - GMSL
+
+**module_version** (R):
+ Module version number. Zero in case of a missing module.
+
+**fw_type** (R):
+ Firmware type.
+
+ | 1 - FPDL3
+ | 2 - GMSL
+
+**fw_version** (R):
+ Firmware version number.
+
+**serial_number** (R):
+ Card serial number. The format is::
+
+ PRODUCT-REVISION-SERIES-SERIAL
+
+ where each component is a 8b number.
+
+
+Common FPDL3/GMSL input parameters
+==================================
+
+**input_id** (R):
+ Input number ID, zero based.
+
+**oldi_lane_width** (RW):
+ Number of deserializer output lanes.
+
+ | 0 - single
+ | 1 - dual (default)
+
+**color_mapping** (RW):
+ Mapping of the incoming bits in the signal to the colour bits of the pixels.
+
+ | 0 - OLDI/JEIDA
+ | 1 - SPWG/VESA (default)
+
+**link_status** (R):
+ Video link status. If the link is locked, chips are properly connected and
+ communicating at the same speed and protocol. The link can be locked without
+ an active video stream.
+
+ A value of 0 is equivalent to the V4L2_IN_ST_NO_SYNC flag of the V4L2
+ VIDIOC_ENUMINPUT status bits.
+
+ | 0 - unlocked
+ | 1 - locked
+
+**stream_status** (R):
+ Video stream status. A stream is detected if the link is locked, the input
+ pixel clock is running and the DE signal is moving.
+
+ A value of 0 is equivalent to the V4L2_IN_ST_NO_SIGNAL flag of the V4L2
+ VIDIOC_ENUMINPUT status bits.
+
+ | 0 - not detected
+ | 1 - detected
+
+**video_width** (R):
+ Video stream width. This is the actual width as detected by the HW.
+
+ The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in the width
+ field of the v4l2_bt_timings struct.
+
+**video_height** (R):
+ Video stream height. This is the actual height as detected by the HW.
+
+ The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in the height
+ field of the v4l2_bt_timings struct.
+
+**vsync_status** (R):
+ The type of VSYNC pulses as detected by the video format detector.
+
+ The value is equivalent to the flags returned by VIDIOC_QUERY_DV_TIMINGS in
+ the polarities field of the v4l2_bt_timings struct.
+
+ | 0 - active low
+ | 1 - active high
+ | 2 - not available
+
+**hsync_status** (R):
+ The type of HSYNC pulses as detected by the video format detector.
+
+ The value is equivalent to the flags returned by VIDIOC_QUERY_DV_TIMINGS in
+ the polarities field of the v4l2_bt_timings struct.
+
+ | 0 - active low
+ | 1 - active high
+ | 2 - not available
+
+**vsync_gap_length** (RW):
+ If the incoming video signal does not contain synchronization VSYNC and
+ HSYNC pulses, these must be generated internally in the FPGA to achieve
+ the correct frame ordering. This value indicates, how many "empty" pixels
+ (pixels with deasserted Data Enable signal) are necessary to generate the
+ internal VSYNC pulse.
+
+**hsync_gap_length** (RW):
+ If the incoming video signal does not contain synchronization VSYNC and
+ HSYNC pulses, these must be generated internally in the FPGA to achieve
+ the correct frame ordering. This value indicates, how many "empty" pixels
+ (pixels with deasserted Data Enable signal) are necessary to generate the
+ internal HSYNC pulse. The value must be greater than 1 and smaller than
+ vsync_gap_length.
+
+**pclk_frequency** (R):
+ Input pixel clock frequency in kHz.
+
+ The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in
+ the pixelclock field of the v4l2_bt_timings struct.
+
+ *Note: The frequency_range parameter must be set properly first to get
+ a valid frequency here.*
+
+**hsync_width** (R):
+ Width of the HSYNC signal in PCLK clock ticks.
+
+ The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in
+ the hsync field of the v4l2_bt_timings struct.
+
+**vsync_width** (R):
+ Width of the VSYNC signal in PCLK clock ticks.
+
+ The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in
+ the vsync field of the v4l2_bt_timings struct.
+
+**hback_porch** (R):
+ Number of PCLK pulses between deassertion of the HSYNC signal and the first
+ valid pixel in the video line (marked by DE=1).
+
+ The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in
+ the hbackporch field of the v4l2_bt_timings struct.
+
+**hfront_porch** (R):
+ Number of PCLK pulses between the end of the last valid pixel in the video
+ line (marked by DE=1) and assertion of the HSYNC signal.
+
+ The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in
+ the hfrontporch field of the v4l2_bt_timings struct.
+
+**vback_porch** (R):
+ Number of video lines between deassertion of the VSYNC signal and the video
+ line with the first valid pixel (marked by DE=1).
+
+ The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in
+ the vbackporch field of the v4l2_bt_timings struct.
+
+**vfront_porch** (R):
+ Number of video lines between the end of the last valid pixel line (marked
+ by DE=1) and assertion of the VSYNC signal.
+
+ The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in
+ the vfrontporch field of the v4l2_bt_timings struct.
+
+**frequency_range** (RW)
+ PLL frequency range of the OLDI input clock generator. The PLL frequency is
+ derived from the Pixel Clock Frequency (PCLK) and is equal to PCLK if
+ oldi_lane_width is set to "single" and PCLK/2 if oldi_lane_width is set to
+ "dual".
+
+ | 0 - PLL < 50MHz (default)
+ | 1 - PLL >= 50MHz
+
+ *Note: This parameter can not be changed while the input v4l2 device is
+ open.*
+
+
+Common FPDL3/GMSL output parameters
+===================================
+
+**output_id** (R):
+ Output number ID, zero based.
+
+**video_source** (RW):
+ Output video source. If set to 0 or 1, the source is the corresponding card
+ input and the v4l2 output devices are disabled. If set to 2 or 3, the source
+ is the corresponding v4l2 video output device. The default is
+ the corresponding v4l2 output, i.e. 2 for OUT1 and 3 for OUT2.
+
+ | 0 - input 0
+ | 1 - input 1
+ | 2 - v4l2 output 0
+ | 3 - v4l2 output 1
+
+ *Note: This parameter can not be changed while ANY of the input/output v4l2
+ devices is open.*
+
+**display_width** (RW):
+ Display width. There is no autodetection of the connected display, so the
+ proper value must be set before the start of streaming. The default width
+ is 1280.
+
+ *Note: This parameter can not be changed while the output v4l2 device is
+ open.*
+
+**display_height** (RW):
+ Display height. There is no autodetection of the connected display, so the
+ proper value must be set before the start of streaming. The default height
+ is 640.
+
+ *Note: This parameter can not be changed while the output v4l2 device is
+ open.*
+
+**frame_rate** (RW):
+ Output video frame rate in frames per second. The default frame rate is
+ 60Hz.
+
+**hsync_polarity** (RW):
+ HSYNC signal polarity.
+
+ | 0 - active low (default)
+ | 1 - active high
+
+**vsync_polarity** (RW):
+ VSYNC signal polarity.
+
+ | 0 - active low (default)
+ | 1 - active high
+
+**de_polarity** (RW):
+ DE signal polarity.
+
+ | 0 - active low
+ | 1 - active high (default)
+
+**pclk_frequency** (RW):
+ Output pixel clock frequency. Allowed values are between 25000-190000(kHz)
+ and there is a non-linear stepping between two consecutive allowed
+ frequencies. The driver finds the nearest allowed frequency to the given
+ value and sets it. When reading this property, you get the exact
+ frequency set by the driver. The default frequency is 70000kHz.
+
+ *Note: This parameter can not be changed while the output v4l2 device is
+ open.*
+
+**hsync_width** (RW):
+ Width of the HSYNC signal in pixels. The default value is 16.
+
+**vsync_width** (RW):
+ Width of the VSYNC signal in video lines. The default value is 2.
+
+**hback_porch** (RW):
+ Number of PCLK pulses between deassertion of the HSYNC signal and the first
+ valid pixel in the video line (marked by DE=1). The default value is 32.
+
+**hfront_porch** (RW):
+ Number of PCLK pulses between the end of the last valid pixel in the video
+ line (marked by DE=1) and assertion of the HSYNC signal. The default value
+ is 32.
+
+**vback_porch** (RW):
+ Number of video lines between deassertion of the VSYNC signal and the video
+ line with the first valid pixel (marked by DE=1). The default value is 2.
+
+**vfront_porch** (RW):
+ Number of video lines between the end of the last valid pixel line (marked
+ by DE=1) and assertion of the VSYNC signal. The default value is 2.
+
+
+FPDL3 specific input parameters
+===============================
+
+**fpdl3_input_width** (RW):
+ Number of deserializer input lines.
+
+ | 0 - auto (default)
+ | 1 - single
+ | 2 - dual
+
+FPDL3 specific output parameters
+================================
+
+**fpdl3_output_width** (RW):
+ Number of serializer output lines.
+
+ | 0 - auto (default)
+ | 1 - single
+ | 2 - dual
+
+GMSL specific input parameters
+==============================
+
+**gmsl_mode** (RW):
+ GMSL speed mode.
+
+ | 0 - 12Gb/s (default)
+ | 1 - 6Gb/s
+ | 2 - 3Gb/s
+ | 3 - 1.5Gb/s
+
+**gmsl_stream_id** (RW):
+ The GMSL multi-stream contains up to four video streams. This parameter
+ selects which stream is captured by the video input. The value is the
+ zero-based index of the stream. The default stream id is 0.
+
+ *Note: This parameter can not be changed while the input v4l2 device is
+ open.*
+
+**gmsl_fec** (RW):
+ GMSL Forward Error Correction (FEC).
+
+ | 0 - disabled
+ | 1 - enabled (default)
+
+
+====================
+mgb4 mtd partitions
+====================
+
+The mgb4 driver creates a MTD device with two partitions:
+ - mgb4-fw.X - FPGA firmware.
+ - mgb4-data.X - Factory settings, e.g. card serial number.
+
+The *mgb4-fw* partition is writable and is used for FW updates, *mgb4-data* is
+read-only. The *X* attached to the partition name represents the card number.
+Depending on the CONFIG_MTD_PARTITIONED_MASTER kernel configuration, you may
+also have a third partition named *mgb4-flash* available in the system. This
+partition represents the whole, unpartitioned, card's FLASH memory and one should
+not fiddle with it...
+
+====================
+mgb4 iio (triggers)
+====================
+
+The mgb4 driver creates an Industrial I/O (IIO) device that provides trigger and
+signal level status capability. The following scan elements are available:
+
+**activity**:
+ The trigger levels and pending status.
+
+ | bit 1 - trigger 1 pending
+ | bit 2 - trigger 2 pending
+ | bit 5 - trigger 1 level
+ | bit 6 - trigger 2 level
+
+**timestamp**:
+ The trigger event timestamp.
+
+The iio device can operate either in "raw" mode where you can fetch the signal
+levels (activity bits 5 and 6) using sysfs access or in triggered buffer mode.
+In the triggered buffer mode you can follow the signal level changes (activity
+bits 1 and 2) using the iio device in /dev. If you enable the timestamps, you
+will also get the exact trigger event time that can be matched to a video frame
+(every mgb4 video frame has a timestamp with the same clock source).
+
+*Note: although the activity sample always contains all the status bits, it makes
+no sense to get the pending bits in raw mode or the level bits in the triggered
+buffer mode - the values do not represent valid data in such case.*
diff --git a/Documentation/admin-guide/media/pci-cardlist.rst b/Documentation/admin-guide/media/pci-cardlist.rst
index 42528795d4da..7d8e3c8987db 100644
--- a/Documentation/admin-guide/media/pci-cardlist.rst
+++ b/Documentation/admin-guide/media/pci-cardlist.rst
@@ -77,6 +77,7 @@ ipu3-cio2 Intel ipu3-cio2 driver
ivtv Conexant cx23416/cx23415 MPEG encoder/decoder
ivtvfb Conexant cx23415 framebuffer
mantis MANTIS based cards
+mgb4 Digiteq Automotive MGB4 frame grabber
mxb Siemens-Nixdorf 'Multimedia eXtension Board'
netup-unidvb NetUP Universal DVB card
ngene Micronas nGene
diff --git a/Documentation/admin-guide/media/v4l-drivers.rst b/Documentation/admin-guide/media/v4l-drivers.rst
index 1c41f87c3917..61283d67ceef 100644
--- a/Documentation/admin-guide/media/v4l-drivers.rst
+++ b/Documentation/admin-guide/media/v4l-drivers.rst
@@ -17,6 +17,7 @@ Video4Linux (V4L) driver-specific documentation
imx7
ipu3
ivtv
+ mgb4
omap3isp
omap4_camera
philips
diff --git a/Documentation/admin-guide/media/visl.rst b/Documentation/admin-guide/media/visl.rst
index 7d2dc78341c9..4328c6c72d30 100644
--- a/Documentation/admin-guide/media/visl.rst
+++ b/Documentation/admin-guide/media/visl.rst
@@ -78,7 +78,7 @@ The trace events are defined on a per-codec basis, e.g.:
.. code-block:: bash
- $ ls /sys/kernel/debug/tracing/events/ | grep visl
+ $ ls /sys/kernel/tracing/events/ | grep visl
visl_fwht_controls
visl_h264_controls
visl_hevc_controls
@@ -90,13 +90,13 @@ For example, in order to dump HEVC SPS data:
.. code-block:: bash
- $ echo 1 > /sys/kernel/debug/tracing/events/visl_hevc_controls/v4l2_ctrl_hevc_sps/enable
+ $ echo 1 > /sys/kernel/tracing/events/visl_hevc_controls/v4l2_ctrl_hevc_sps/enable
The SPS data will be dumped to the trace buffer, i.e.:
.. code-block:: bash
- $ cat /sys/kernel/debug/tracing/trace
+ $ cat /sys/kernel/tracing/trace
video_parameter_set_id 0
seq_parameter_set_id 0
pic_width_in_luma_samples 1920
diff --git a/Documentation/admin-guide/mm/damon/usage.rst b/Documentation/admin-guide/mm/damon/usage.rst
index 8da1b7281827..da94feb97ed1 100644
--- a/Documentation/admin-guide/mm/damon/usage.rst
+++ b/Documentation/admin-guide/mm/damon/usage.rst
@@ -20,18 +20,18 @@ DAMON provides below interfaces for different users.
you can write and use your personalized DAMON sysfs wrapper programs that
reads/writes the sysfs files instead of you. The `DAMON user space tool
<https://github.com/awslabs/damo>`_ is one example of such programs.
-- *debugfs interface. (DEPRECATED!)*
- :ref:`This <debugfs_interface>` is almost identical to :ref:`sysfs interface
- <sysfs_interface>`. This is deprecated, so users should move to the
- :ref:`sysfs interface <sysfs_interface>`. If you depend on this and cannot
- move, please report your usecase to damon@lists.linux.dev and
- linux-mm@kvack.org.
- *Kernel Space Programming Interface.*
:doc:`This </mm/damon/api>` is for kernel space programmers. Using this,
users can utilize every feature of DAMON most flexibly and efficiently by
writing kernel space DAMON application programs for you. You can even extend
DAMON for various address spaces. For detail, please refer to the interface
:doc:`document </mm/damon/api>`.
+- *debugfs interface. (DEPRECATED!)*
+ :ref:`This <debugfs_interface>` is almost identical to :ref:`sysfs interface
+ <sysfs_interface>`. This is deprecated, so users should move to the
+ :ref:`sysfs interface <sysfs_interface>`. If you depend on this and cannot
+ move, please report your usecase to damon@lists.linux.dev and
+ linux-mm@kvack.org.
.. _sysfs_interface:
@@ -76,7 +76,7 @@ comma (","). ::
│ │ │ │ │ │ │ │ ...
│ │ │ │ │ │ ...
│ │ │ │ │ schemes/nr_schemes
- │ │ │ │ │ │ 0/action
+ │ │ │ │ │ │ 0/action,apply_interval_us
│ │ │ │ │ │ │ access_pattern/
│ │ │ │ │ │ │ │ sz/min,max
│ │ │ │ │ │ │ │ nr_accesses/min,max
@@ -105,14 +105,12 @@ having the root permission could use this directory.
kdamonds/
---------
-The monitoring-related information including request specifications and results
-are called DAMON context. DAMON executes each context with a kernel thread
-called kdamond, and multiple kdamonds could run in parallel.
-
Under the ``admin`` directory, one directory, ``kdamonds``, which has files for
-controlling the kdamonds exist. In the beginning, this directory has only one
-file, ``nr_kdamonds``. Writing a number (``N``) to the file creates the number
-of child directories named ``0`` to ``N-1``. Each directory represents each
+controlling the kdamonds (refer to
+:ref:`design <damon_design_execution_model_and_data_structures>` for more
+details) exists. In the beginning, this directory has only one file,
+``nr_kdamonds``. Writing a number (``N``) to the file creates the number of
+child directories named ``0`` to ``N-1``. Each directory represents each
kdamond.
kdamonds/<N>/
@@ -150,9 +148,10 @@ kdamonds/<N>/contexts/
In the beginning, this directory has only one file, ``nr_contexts``. Writing a
number (``N``) to the file creates the number of child directories named as
-``0`` to ``N-1``. Each directory represents each monitoring context. At the
-moment, only one context per kdamond is supported, so only ``0`` or ``1`` can
-be written to the file.
+``0`` to ``N-1``. Each directory represents each monitoring context (refer to
+:ref:`design <damon_design_execution_model_and_data_structures>` for more
+details). At the moment, only one context per kdamond is supported, so only
+``0`` or ``1`` can be written to the file.
.. _sysfs_contexts:
@@ -270,8 +269,8 @@ schemes/<N>/
------------
In each scheme directory, five directories (``access_pattern``, ``quotas``,
-``watermarks``, ``filters``, ``stats``, and ``tried_regions``) and one file
-(``action``) exist.
+``watermarks``, ``filters``, ``stats``, and ``tried_regions``) and two files
+(``action`` and ``apply_interval``) exist.
The ``action`` file is for setting and getting the scheme's :ref:`action
<damon_design_damos_action>`. The keywords that can be written to and read
@@ -297,6 +296,9 @@ Note that support of each action depends on the running DAMON operations set
- ``stat``: Do nothing but count the statistics.
Supported by all operations sets.
+The ``apply_interval_us`` file is for setting and getting the scheme's
+:ref:`apply_interval <damon_design_damos>` in microseconds.
+
schemes/<N>/access_pattern/
---------------------------
@@ -392,7 +394,7 @@ pages of all memory cgroups except ``/having_care_already``.::
echo N > 1/matching
Note that ``anon`` and ``memcg`` filters are currently supported only when
-``paddr`` `implementation <sysfs_contexts>` is being used.
+``paddr`` :ref:`implementation <sysfs_contexts>` is being used.
Also, memory regions that are filtered out by ``addr`` or ``target`` filters
are not counted as the scheme has tried to those, while regions that filtered
@@ -430,9 +432,9 @@ that reading it returns the total size of the scheme tried regions, and creates
directories named integer starting from ``0`` under this directory. Each
directory contains files exposing detailed information about each of the memory
region that the corresponding scheme's ``action`` has tried to be applied under
-this directory, during next :ref:`aggregation interval
-<sysfs_monitoring_attrs>`. The information includes address range,
-``nr_accesses``, and ``age`` of the region.
+this directory, during next :ref:`apply interval <damon_design_damos>` of the
+corresponding scheme. The information includes address range, ``nr_accesses``,
+and ``age`` of the region.
Writing ``update_schemes_tried_bytes`` to the relevant ``kdamonds/<N>/state``
file will only update the ``total_bytes`` file, and will not create the
@@ -495,6 +497,62 @@ Please note that it's highly recommended to use user space tools like `damo
<https://github.com/awslabs/damo>`_ rather than manually reading and writing
the files as above. Above is only for an example.
+.. _tracepoint:
+
+Tracepoints for Monitoring Results
+==================================
+
+Users can get the monitoring results via the :ref:`tried_regions
+<sysfs_schemes_tried_regions>`. The interface is useful for getting a
+snapshot, but it could be inefficient for fully recording all the monitoring
+results. For the purpose, two trace points, namely ``damon:damon_aggregated``
+and ``damon:damos_before_apply``, are provided. ``damon:damon_aggregated``
+provides the whole monitoring results, while ``damon:damos_before_apply``
+provides the monitoring results for regions that each DAMON-based Operation
+Scheme (:ref:`DAMOS <damon_design_damos>`) is gonna be applied. Hence,
+``damon:damos_before_apply`` is more useful for recording internal behavior of
+DAMOS, or DAMOS target access
+:ref:`pattern <damon_design_damos_access_pattern>` based query-like efficient
+monitoring results recording.
+
+While the monitoring is turned on, you could record the tracepoint events and
+show results using tracepoint supporting tools like ``perf``. For example::
+
+ # echo on > monitor_on
+ # perf record -e damon:damon_aggregated &
+ # sleep 5
+ # kill 9 $(pidof perf)
+ # echo off > monitor_on
+ # perf script
+ kdamond.0 46568 [027] 79357.842179: damon:damon_aggregated: target_id=0 nr_regions=11 122509119488-135708762112: 0 864
+ [...]
+
+Each line of the perf script output represents each monitoring region. The
+first five fields are as usual other tracepoint outputs. The sixth field
+(``target_id=X``) shows the ide of the monitoring target of the region. The
+seventh field (``nr_regions=X``) shows the total number of monitoring regions
+for the target. The eighth field (``X-Y:``) shows the start (``X``) and end
+(``Y``) addresses of the region in bytes. The ninth field (``X``) shows the
+``nr_accesses`` of the region (refer to
+:ref:`design <damon_design_region_based_sampling>` for more details of the
+counter). Finally the tenth field (``X``) shows the ``age`` of the region
+(refer to :ref:`design <damon_design_age_tracking>` for more details of the
+counter).
+
+If the event was ``damon:damos_beofre_apply``, the ``perf script`` output would
+be somewhat like below::
+
+ kdamond.0 47293 [000] 80801.060214: damon:damos_before_apply: ctx_idx=0 scheme_idx=0 target_idx=0 nr_regions=11 121932607488-135128711168: 0 136
+ [...]
+
+Each line of the output represents each monitoring region that each DAMON-based
+Operation Scheme was about to be applied at the traced time. The first five
+fields are as usual. It shows the index of the DAMON context (``ctx_idx=X``)
+of the scheme in the list of the contexts of the context's kdamond, the index
+of the scheme (``scheme_idx=X``) in the list of the schemes of the context, in
+addition to the output of ``damon_aggregated`` tracepoint.
+
+
.. _debugfs_interface:
debugfs Interface (DEPRECATED!)
@@ -790,23 +848,3 @@ directory by putting the name of the context to the ``rm_contexts`` file. ::
Note that ``mk_contexts``, ``rm_contexts``, and ``monitor_on`` files are in the
root directory only.
-
-
-.. _tracepoint:
-
-Tracepoint for Monitoring Results
-=================================
-
-Users can get the monitoring results via the :ref:`tried_regions
-<sysfs_schemes_tried_regions>` or a tracepoint, ``damon:damon_aggregated``.
-While the tried regions directory is useful for getting a snapshot, the
-tracepoint is useful for getting a full record of the results. While the
-monitoring is turned on, you could record the tracepoint events and show
-results using tracepoint supporting tools like ``perf``. For example::
-
- # echo on > monitor_on
- # perf record -e damon:damon_aggregated &
- # sleep 5
- # kill 9 $(pidof perf)
- # echo off > monitor_on
- # perf script
diff --git a/Documentation/admin-guide/mm/ksm.rst b/Documentation/admin-guide/mm/ksm.rst
index 776f244bdae4..e59231ac6bb7 100644
--- a/Documentation/admin-guide/mm/ksm.rst
+++ b/Documentation/admin-guide/mm/ksm.rst
@@ -155,6 +155,15 @@ stable_node_chains_prune_millisecs
scan. It's a noop if not a single KSM page hit the
``max_page_sharing`` yet.
+smart_scan
+ Historically KSM checked every candidate page for each scan. It did
+ not take into account historic information. When smart scan is
+ enabled, pages that have previously not been de-duplicated get
+ skipped. How often these pages are skipped depends on how often
+ de-duplication has already been tried and failed. By default this
+ optimization is enabled. The ``pages_skipped`` metric shows how
+ effective the setting is.
+
The effectiveness of KSM and MADV_MERGEABLE is shown in ``/sys/kernel/mm/ksm/``:
general_profit
@@ -169,6 +178,8 @@ pages_unshared
how many pages unique but repeatedly checked for merging
pages_volatile
how many pages changing too fast to be placed in a tree
+pages_skipped
+ how many pages did the "smart" page scanning algorithm skip
full_scans
how many times all mergeable areas have been scanned
stable_node_chains
diff --git a/Documentation/admin-guide/mm/memory-hotplug.rst b/Documentation/admin-guide/mm/memory-hotplug.rst
index cfe034cf1e87..098f14d83e99 100644
--- a/Documentation/admin-guide/mm/memory-hotplug.rst
+++ b/Documentation/admin-guide/mm/memory-hotplug.rst
@@ -33,7 +33,7 @@ used to expose persistent memory, other performance-differentiated memory and
reserved memory regions as ordinary system RAM to Linux.
Linux only supports memory hot(un)plug on selected 64 bit architectures, such as
-x86_64, arm64, ppc64, s390x and ia64.
+x86_64, arm64, ppc64 and s390x.
Memory Hot(Un)Plug Granularity
------------------------------
@@ -75,7 +75,7 @@ Memory hotunplug consists of two phases:
(1) Offlining memory blocks
(2) Removing the memory from Linux
-In the fist phase, memory is "hidden" from the page allocator again, for
+In the first phase, memory is "hidden" from the page allocator again, for
example, by migrating busy memory to other memory locations and removing all
relevant free pages from the page allocator After this phase, the memory is no
longer visible in memory statistics of the system.
@@ -250,15 +250,15 @@ Observing the State of Memory Blocks
The state (online/offline/going-offline) of a memory block can be observed
either via::
- % cat /sys/device/system/memory/memoryXXX/state
+ % cat /sys/devices/system/memory/memoryXXX/state
Or alternatively (1/0) via::
- % cat /sys/device/system/memory/memoryXXX/online
+ % cat /sys/devices/system/memory/memoryXXX/online
For an online memory block, the managing zone can be observed via::
- % cat /sys/device/system/memory/memoryXXX/valid_zones
+ % cat /sys/devices/system/memory/memoryXXX/valid_zones
Configuring Memory Hot(Un)Plug
==============================
@@ -326,7 +326,7 @@ however, a memory block might span memory holes. A memory block spanning memory
holes cannot be offlined.
For example, assume 1 GiB memory block size. A device for a memory starting at
-0x100000000 is ``/sys/device/system/memory/memory4``::
+0x100000000 is ``/sys/devices/system/memory/memory4``::
(0x100000000 / 1Gib = 4)
diff --git a/Documentation/admin-guide/mm/pagemap.rst b/Documentation/admin-guide/mm/pagemap.rst
index c8f380271cad..fe17cf210426 100644
--- a/Documentation/admin-guide/mm/pagemap.rst
+++ b/Documentation/admin-guide/mm/pagemap.rst
@@ -227,3 +227,92 @@ Before Linux 3.11 pagemap bits 55-60 were used for "page-shift" (which is
always 12 at most architectures). Since Linux 3.11 their meaning changes
after first clear of soft-dirty bits. Since Linux 4.2 they are used for
flags unconditionally.
+
+Pagemap Scan IOCTL
+==================
+
+The ``PAGEMAP_SCAN`` IOCTL on the pagemap file can be used to get or optionally
+clear the info about page table entries. The following operations are supported
+in this IOCTL:
+
+- Scan the address range and get the memory ranges matching the provided criteria.
+ This is performed when the output buffer is specified.
+- Write-protect the pages. The ``PM_SCAN_WP_MATCHING`` is used to write-protect
+ the pages of interest. The ``PM_SCAN_CHECK_WPASYNC`` aborts the operation if
+ non-Async Write Protected pages are found. The ``PM_SCAN_WP_MATCHING`` can be
+ used with or without ``PM_SCAN_CHECK_WPASYNC``.
+- Both of those operations can be combined into one atomic operation where we can
+ get and write protect the pages as well.
+
+Following flags about pages are currently supported:
+
+- ``PAGE_IS_WPALLOWED`` - Page has async-write-protection enabled
+- ``PAGE_IS_WRITTEN`` - Page has been written to from the time it was write protected
+- ``PAGE_IS_FILE`` - Page is file backed
+- ``PAGE_IS_PRESENT`` - Page is present in the memory
+- ``PAGE_IS_SWAPPED`` - Page is in swapped
+- ``PAGE_IS_PFNZERO`` - Page has zero PFN
+- ``PAGE_IS_HUGE`` - Page is THP or Hugetlb backed
+
+The ``struct pm_scan_arg`` is used as the argument of the IOCTL.
+
+ 1. The size of the ``struct pm_scan_arg`` must be specified in the ``size``
+ field. This field will be helpful in recognizing the structure if extensions
+ are done later.
+ 2. The flags can be specified in the ``flags`` field. The ``PM_SCAN_WP_MATCHING``
+ and ``PM_SCAN_CHECK_WPASYNC`` are the only added flags at this time. The get
+ operation is optionally performed depending upon if the output buffer is
+ provided or not.
+ 3. The range is specified through ``start`` and ``end``.
+ 4. The walk can abort before visiting the complete range such as the user buffer
+ can get full etc. The walk ending address is specified in``end_walk``.
+ 5. The output buffer of ``struct page_region`` array and size is specified in
+ ``vec`` and ``vec_len``.
+ 6. The optional maximum requested pages are specified in the ``max_pages``.
+ 7. The masks are specified in ``category_mask``, ``category_anyof_mask``,
+ ``category_inverted`` and ``return_mask``.
+
+Find pages which have been written and WP them as well::
+
+ struct pm_scan_arg arg = {
+ .size = sizeof(arg),
+ .flags = PM_SCAN_CHECK_WPASYNC | PM_SCAN_CHECK_WPASYNC,
+ ..
+ .category_mask = PAGE_IS_WRITTEN,
+ .return_mask = PAGE_IS_WRITTEN,
+ };
+
+Find pages which have been written, are file backed, not swapped and either
+present or huge::
+
+ struct pm_scan_arg arg = {
+ .size = sizeof(arg),
+ .flags = 0,
+ ..
+ .category_mask = PAGE_IS_WRITTEN | PAGE_IS_SWAPPED,
+ .category_inverted = PAGE_IS_SWAPPED,
+ .category_anyof_mask = PAGE_IS_PRESENT | PAGE_IS_HUGE,
+ .return_mask = PAGE_IS_WRITTEN | PAGE_IS_SWAPPED |
+ PAGE_IS_PRESENT | PAGE_IS_HUGE,
+ };
+
+The ``PAGE_IS_WRITTEN`` flag can be considered as a better-performing alternative
+of soft-dirty flag. It doesn't get affected by VMA merging of the kernel and hence
+the user can find the true soft-dirty pages in case of normal pages. (There may
+still be extra dirty pages reported for THP or Hugetlb pages.)
+
+"PAGE_IS_WRITTEN" category is used with uffd write protect-enabled ranges to
+implement memory dirty tracking in userspace:
+
+ 1. The userfaultfd file descriptor is created with ``userfaultfd`` syscall.
+ 2. The ``UFFD_FEATURE_WP_UNPOPULATED`` and ``UFFD_FEATURE_WP_ASYNC`` features
+ are set by ``UFFDIO_API`` IOCTL.
+ 3. The memory range is registered with ``UFFDIO_REGISTER_MODE_WP`` mode
+ through ``UFFDIO_REGISTER`` IOCTL.
+ 4. Then any part of the registered memory or the whole memory region must
+ be write protected using ``PAGEMAP_SCAN`` IOCTL with flag ``PM_SCAN_WP_MATCHING``
+ or the ``UFFDIO_WRITEPROTECT`` IOCTL can be used. Both of these perform the
+ same operation. The former is better in terms of performance.
+ 5. Now the ``PAGEMAP_SCAN`` IOCTL can be used to either just find pages which
+ have been written to since they were last marked and/or optionally write protect
+ the pages as well.
diff --git a/Documentation/admin-guide/mm/userfaultfd.rst b/Documentation/admin-guide/mm/userfaultfd.rst
index 4349a8c2b978..203e26da5f92 100644
--- a/Documentation/admin-guide/mm/userfaultfd.rst
+++ b/Documentation/admin-guide/mm/userfaultfd.rst
@@ -244,6 +244,41 @@ write-protected (so future writes will also result in a WP fault). These ioctls
support a mode flag (``UFFDIO_COPY_MODE_WP`` or ``UFFDIO_CONTINUE_MODE_WP``
respectively) to configure the mapping this way.
+If the userfaultfd context has ``UFFD_FEATURE_WP_ASYNC`` feature bit set,
+any vma registered with write-protection will work in async mode rather
+than the default sync mode.
+
+In async mode, there will be no message generated when a write operation
+happens, meanwhile the write-protection will be resolved automatically by
+the kernel. It can be seen as a more accurate version of soft-dirty
+tracking and it can be different in a few ways:
+
+ - The dirty result will not be affected by vma changes (e.g. vma
+ merging) because the dirty is only tracked by the pte.
+
+ - It supports range operations by default, so one can enable tracking on
+ any range of memory as long as page aligned.
+
+ - Dirty information will not get lost if the pte was zapped due to
+ various reasons (e.g. during split of a shmem transparent huge page).
+
+ - Due to a reverted meaning of soft-dirty (page clean when uffd-wp bit
+ set; dirty when uffd-wp bit cleared), it has different semantics on
+ some of the memory operations. For example: ``MADV_DONTNEED`` on
+ anonymous (or ``MADV_REMOVE`` on a file mapping) will be treated as
+ dirtying of memory by dropping uffd-wp bit during the procedure.
+
+The user app can collect the "written/dirty" status by looking up the
+uffd-wp bit for the pages being interested in /proc/pagemap.
+
+The page will not be under track of uffd-wp async mode until the page is
+explicitly write-protected by ``ioctl(UFFDIO_WRITEPROTECT)`` with the mode
+flag ``UFFDIO_WRITEPROTECT_MODE_WP`` set. Trying to resolve a page fault
+that was tracked by async mode userfaultfd-wp is invalid.
+
+When userfaultfd-wp async mode is used alone, it can be applied to all
+kinds of memory.
+
Memory Poisioning Emulation
---------------------------
diff --git a/Documentation/admin-guide/module-signing.rst b/Documentation/admin-guide/module-signing.rst
index 2898b2703297..a8667a777490 100644
--- a/Documentation/admin-guide/module-signing.rst
+++ b/Documentation/admin-guide/module-signing.rst
@@ -28,10 +28,10 @@ trusted userspace bits.
This facility uses X.509 ITU-T standard certificates to encode the public keys
involved. The signatures are not themselves encoded in any industrial standard
-type. The facility currently only supports the RSA public key encryption
-standard (though it is pluggable and permits others to be used). The possible
-hash algorithms that can be used are SHA-1, SHA-224, SHA-256, SHA-384, and
-SHA-512 (the algorithm is selected by data in the signature).
+type. The built-in facility currently only supports the RSA & NIST P-384 ECDSA
+public key signing standard (though it is pluggable and permits others to be
+used). The possible hash algorithms that can be used are SHA-2 and SHA-3 of
+sizes 256, 384, and 512 (the algorithm is selected by data in the signature).
==========================
@@ -81,11 +81,12 @@ This has a number of options available:
sign the modules with:
=============================== ==========================================
- ``CONFIG_MODULE_SIG_SHA1`` :menuselection:`Sign modules with SHA-1`
- ``CONFIG_MODULE_SIG_SHA224`` :menuselection:`Sign modules with SHA-224`
``CONFIG_MODULE_SIG_SHA256`` :menuselection:`Sign modules with SHA-256`
``CONFIG_MODULE_SIG_SHA384`` :menuselection:`Sign modules with SHA-384`
``CONFIG_MODULE_SIG_SHA512`` :menuselection:`Sign modules with SHA-512`
+ ``CONFIG_MODULE_SIG_SHA3_256`` :menuselection:`Sign modules with SHA3-256`
+ ``CONFIG_MODULE_SIG_SHA3_384`` :menuselection:`Sign modules with SHA3-384`
+ ``CONFIG_MODULE_SIG_SHA3_512`` :menuselection:`Sign modules with SHA3-512`
=============================== ==========================================
The algorithm selected here will also be built into the kernel (rather
@@ -145,6 +146,10 @@ into vmlinux) using parameters in the::
file (which is also generated if it does not already exist).
+One can select between RSA (``MODULE_SIG_KEY_TYPE_RSA``) and ECDSA
+(``MODULE_SIG_KEY_TYPE_ECDSA``) to generate either RSA 4k or NIST
+P-384 keypair.
+
It is strongly recommended that you provide your own x509.genkey file.
Most notably, in the x509.genkey file, the req_distinguished_name section
diff --git a/Documentation/admin-guide/perf/ampere_cspmu.rst b/Documentation/admin-guide/perf/ampere_cspmu.rst
new file mode 100644
index 000000000000..94f93f5aee6c
--- /dev/null
+++ b/Documentation/admin-guide/perf/ampere_cspmu.rst
@@ -0,0 +1,29 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============================================
+Ampere SoC Performance Monitoring Unit (PMU)
+============================================
+
+Ampere SoC PMU is a generic PMU IP that follows Arm CoreSight PMU architecture.
+Therefore, the driver is implemented as a submodule of arm_cspmu driver. At the
+first phase it's used for counting MCU events on AmpereOne.
+
+
+MCU PMU events
+--------------
+
+The PMU driver supports setting filters for "rank", "bank", and "threshold".
+Note, that the filters are per PMU instance rather than per event.
+
+
+Example for perf tool use::
+
+ / # perf list ampere
+
+ ampere_mcu_pmu_0/act_sent/ [Kernel PMU event]
+ <...>
+ ampere_mcu_pmu_1/rd_sent/ [Kernel PMU event]
+ <...>
+
+ / # perf stat -a -e ampere_mcu_pmu_0/act_sent,bank=5,rank=3,threshold=2/,ampere_mcu_pmu_1/rd_sent/ \
+ sleep 1
diff --git a/Documentation/admin-guide/perf/index.rst b/Documentation/admin-guide/perf/index.rst
index f60be04e4e33..a2e6f2c81146 100644
--- a/Documentation/admin-guide/perf/index.rst
+++ b/Documentation/admin-guide/perf/index.rst
@@ -22,3 +22,4 @@ Performance monitor support
nvidia-pmu
meson-ddr-pmu
cxl
+ ampere_cspmu
diff --git a/Documentation/admin-guide/pm/intel_idle.rst b/Documentation/admin-guide/pm/intel_idle.rst
index b799a43da62e..39bd6ecce7de 100644
--- a/Documentation/admin-guide/pm/intel_idle.rst
+++ b/Documentation/admin-guide/pm/intel_idle.rst
@@ -170,7 +170,7 @@ and ``idle=nomwait``. If any of them is present in the kernel command line, the
``MWAIT`` instruction is not allowed to be used, so the initialization of
``intel_idle`` will fail.
-Apart from that there are four module parameters recognized by ``intel_idle``
+Apart from that there are five module parameters recognized by ``intel_idle``
itself that can be set via the kernel command line (they cannot be updated via
sysfs, so that is the only way to change their values).
@@ -216,6 +216,21 @@ are ignored).
The idle states disabled this way can be enabled (on a per-CPU basis) from user
space via ``sysfs``.
+The ``ibrs_off`` module parameter is a boolean flag (defaults to
+false). If set, it is used to control if IBRS (Indirect Branch Restricted
+Speculation) should be turned off when the CPU enters an idle state.
+This flag does not affect CPUs that use Enhanced IBRS which can remain
+on with little performance impact.
+
+For some CPUs, IBRS will be selected as mitigation for Spectre v2 and Retbleed
+security vulnerabilities by default. Leaving the IBRS mode on while idling may
+have a performance impact on its sibling CPU. The IBRS mode will be turned off
+by default when the CPU enters into a deep idle state, but not in some
+shallower ones. Setting the ``ibrs_off`` module parameter will force the IBRS
+mode to off when the CPU is in any one of the available idle states. This may
+help performance of a sibling CPU at the expense of a slightly higher wakeup
+latency for the idle CPU.
+
.. _intel-idle-core-and-package-idle-states:
diff --git a/Documentation/admin-guide/pstore-blk.rst b/Documentation/admin-guide/pstore-blk.rst
index 2d22ead9520e..1bb2a1c292aa 100644
--- a/Documentation/admin-guide/pstore-blk.rst
+++ b/Documentation/admin-guide/pstore-blk.rst
@@ -76,7 +76,7 @@ kmsg_size
~~~~~~~~~
The chunk size in KB for oops/panic front-end. It **MUST** be a multiple of 4.
-It's optional if you do not care oops/panic log.
+It's optional if you do not care about the oops/panic log.
There are multiple chunks for oops/panic front-end depending on the remaining
space except other pstore front-ends.
@@ -88,7 +88,7 @@ pmsg_size
~~~~~~~~~
The chunk size in KB for pmsg front-end. It **MUST** be a multiple of 4.
-It's optional if you do not care pmsg log.
+It's optional if you do not care about the pmsg log.
Unlike oops/panic front-end, there is only one chunk for pmsg front-end.
@@ -100,7 +100,7 @@ console_size
~~~~~~~~~~~~
The chunk size in KB for console front-end. It **MUST** be a multiple of 4.
-It's optional if you do not care console log.
+It's optional if you do not care about the console log.
Similar to pmsg front-end, there is only one chunk for console front-end.
@@ -111,7 +111,7 @@ ftrace_size
~~~~~~~~~~~
The chunk size in KB for ftrace front-end. It **MUST** be a multiple of 4.
-It's optional if you do not care console log.
+It's optional if you do not care about the ftrace log.
Similar to oops front-end, there are multiple chunks for ftrace front-end
depending on the count of cpu processors. Each chunk size is equal to
diff --git a/Documentation/admin-guide/spkguide.txt b/Documentation/admin-guide/spkguide.txt
index 74ea7f391942..0d5965138f8f 100644
--- a/Documentation/admin-guide/spkguide.txt
+++ b/Documentation/admin-guide/spkguide.txt
@@ -7,7 +7,7 @@ Last modified on Mon Sep 27 14:26:31 2010
Document version 1.3
Copyright (c) 2005 Gene Collins
-Copyright (c) 2008 Samuel Thibault
+Copyright (c) 2008, 2023 Samuel Thibault
Copyright (c) 2009, 2010 the Speakup Team
Permission is granted to copy, distribute and/or modify this document
@@ -83,8 +83,7 @@ spkout -- Speak Out
txprt -- Transport
dummy -- Plain text terminal
-Note: Speakup does * NOT * support usb connections! Speakup also does *
-NOT * support the internal Tripletalk!
+Note: Speakup does * NOT * support the internal Tripletalk!
Speakup does support two other synthesizers, but because they work in
conjunction with other software, they must be loaded as modules after
@@ -94,6 +93,12 @@ These are as follows:
decpc -- DecTalk PC (not available at boot up)
soft -- One of several software synthesizers (not available at boot up)
+By default speakup looks for the synthesizer on the ttyS0 serial port. This can
+be changed with the device parameter of the modules, for instance for
+DoubleTalk LT:
+
+speakup_ltlk.dev=ttyUSB0
+
See the sections on loading modules and software synthesizers later in
this manual for further details. It should be noted here that the
speakup.synth boot parameter will have no effect if Speakup has been
diff --git a/Documentation/admin-guide/sysctl/fs.rst b/Documentation/admin-guide/sysctl/fs.rst
index a321b84eccaa..47499a1742bd 100644
--- a/Documentation/admin-guide/sysctl/fs.rst
+++ b/Documentation/admin-guide/sysctl/fs.rst
@@ -42,16 +42,16 @@ pre-allocation or re-sizing of any kernel data structures.
dentry-state
------------
-This file shows the values in ``struct dentry_stat``, as defined in
-``linux/include/linux/dcache.h``::
+This file shows the values in ``struct dentry_stat_t``, as defined in
+``fs/dcache.c``::
struct dentry_stat_t dentry_stat {
- int nr_dentry;
- int nr_unused;
- int age_limit; /* age in seconds */
- int want_pages; /* pages requested by system */
- int nr_negative; /* # of unused negative dentries */
- int dummy; /* Reserved for future use */
+ long nr_dentry;
+ long nr_unused;
+ long age_limit; /* age in seconds */
+ long want_pages; /* pages requested by system */
+ long nr_negative; /* # of unused negative dentries */
+ long dummy; /* Reserved for future use */
};
Dentries are dynamically allocated and deallocated.
diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
index cf33de56da27..6584a1f9bfe3 100644
--- a/Documentation/admin-guide/sysctl/kernel.rst
+++ b/Documentation/admin-guide/sysctl/kernel.rst
@@ -436,7 +436,7 @@ ignore-unaligned-usertrap
On architectures where unaligned accesses cause traps, and where this
feature is supported (``CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN``;
-currently, ``arc``, ``ia64`` and ``loongarch``), controls whether all
+currently, ``arc`` and ``loongarch``), controls whether all
unaligned traps are logged.
= =============================================================
@@ -445,10 +445,7 @@ unaligned traps are logged.
setting.
= =============================================================
-See also `unaligned-trap`_ and `unaligned-dump-stack`_. On ``ia64``,
-this allows system administrators to override the
-``IA64_THREAD_UAC_NOPRINT`` ``prctl`` and avoid logs being flooded.
-
+See also `unaligned-trap`_.
io_uring_disabled
=================
@@ -1182,7 +1179,8 @@ automatically on platforms where it can run (that is,
platforms with asymmetric CPU topologies and having an Energy
Model available). If your platform happens to meet the
requirements for EAS but you do not want to use it, change
-this value to 0.
+this value to 0. On Non-EAS platforms, write operation fails and
+read doesn't return anything.
task_delayacct
===============
@@ -1538,22 +1536,6 @@ See Documentation/admin-guide/kernel-parameters.rst and
Documentation/trace/boottime-trace.rst.
-.. _unaligned-dump-stack:
-
-unaligned-dump-stack (ia64)
-===========================
-
-When logging unaligned accesses, controls whether the stack is
-dumped.
-
-= ===================================================
-0 Do not dump the stack. This is the default setting.
-1 Dump the stack.
-= ===================================================
-
-See also `ignore-unaligned-usertrap`_.
-
-
unaligned-trap
==============
diff --git a/Documentation/admin-guide/sysctl/net.rst b/Documentation/admin-guide/sysctl/net.rst
index 4877563241f3..c7525942f12c 100644
--- a/Documentation/admin-guide/sysctl/net.rst
+++ b/Documentation/admin-guide/sysctl/net.rst
@@ -71,6 +71,7 @@ two flavors of JITs, the newer eBPF JIT currently supported on:
- s390x
- riscv64
- riscv32
+ - loongarch64
And the older cBPF JIT supported on the following archs:
diff --git a/Documentation/admin-guide/sysctl/vm.rst b/Documentation/admin-guide/sysctl/vm.rst
index 45ba1f4dc004..c59889de122b 100644
--- a/Documentation/admin-guide/sysctl/vm.rst
+++ b/Documentation/admin-guide/sysctl/vm.rst
@@ -742,8 +742,8 @@ overcommit_memory
This value contains a flag that enables memory overcommitment.
-When this flag is 0, the kernel attempts to estimate the amount
-of free memory left when userspace requests more memory.
+When this flag is 0, the kernel compares the userspace memory request
+size against total memory plus swap and rejects obvious overcommits.
When this flag is 1, the kernel pretends there is always enough
memory until it actually runs out.
diff --git a/Documentation/arch/arm64/cpu-feature-registers.rst b/Documentation/arch/arm64/cpu-feature-registers.rst
index de6d8a4790e2..44f9bd78539d 100644
--- a/Documentation/arch/arm64/cpu-feature-registers.rst
+++ b/Documentation/arch/arm64/cpu-feature-registers.rst
@@ -268,6 +268,8 @@ infrastructure:
+------------------------------+---------+---------+
| SHA3 | [35-32] | y |
+------------------------------+---------+---------+
+ | B16B16 | [27-24] | y |
+ +------------------------------+---------+---------+
| BF16 | [23-20] | y |
+------------------------------+---------+---------+
| BitPerm | [19-16] | y |
diff --git a/Documentation/arch/arm64/elf_hwcaps.rst b/Documentation/arch/arm64/elf_hwcaps.rst
index 76ff9d7398fd..ced7b335e2e0 100644
--- a/Documentation/arch/arm64/elf_hwcaps.rst
+++ b/Documentation/arch/arm64/elf_hwcaps.rst
@@ -174,7 +174,7 @@ HWCAP2_DCPODP
Functionality implied by ID_AA64ISAR1_EL1.DPB == 0b0010.
HWCAP2_SVE2
- Functionality implied by ID_AA64ZFR0_EL1.SVEVer == 0b0001.
+ Functionality implied by ID_AA64ZFR0_EL1.SVEver == 0b0001.
HWCAP2_SVEAES
Functionality implied by ID_AA64ZFR0_EL1.AES == 0b0001.
@@ -222,7 +222,7 @@ HWCAP2_RNG
Functionality implied by ID_AA64ISAR0_EL1.RNDR == 0b0001.
HWCAP2_BTI
- Functionality implied by ID_AA64PFR0_EL1.BT == 0b0001.
+ Functionality implied by ID_AA64PFR1_EL1.BT == 0b0001.
HWCAP2_MTE
Functionality implied by ID_AA64PFR1_EL1.MTE == 0b0010, as described
@@ -232,7 +232,7 @@ HWCAP2_ECV
Functionality implied by ID_AA64MMFR0_EL1.ECV == 0b0001.
HWCAP2_AFP
- Functionality implied by ID_AA64MFR1_EL1.AFP == 0b0001.
+ Functionality implied by ID_AA64MMFR1_EL1.AFP == 0b0001.
HWCAP2_RPRES
Functionality implied by ID_AA64ISAR2_EL1.RPRES == 0b0001.
@@ -308,6 +308,15 @@ HWCAP2_MOPS
HWCAP2_HBC
Functionality implied by ID_AA64ISAR2_EL1.BC == 0b0001.
+HWCAP2_SVE_B16B16
+ Functionality implied by ID_AA64ZFR0_EL1.B16B16 == 0b0001.
+
+HWCAP2_LRCPC3
+ Functionality implied by ID_AA64ISAR1_EL1.LRCPC == 0b0011.
+
+HWCAP2_LSE128
+ Functionality implied by ID_AA64ISAR0_EL1.Atomic == 0b0011.
+
4. Unused AT_HWCAP bits
-----------------------
diff --git a/Documentation/arch/ia64/aliasing.rst b/Documentation/arch/ia64/aliasing.rst
deleted file mode 100644
index 36a1e1d4842b..000000000000
--- a/Documentation/arch/ia64/aliasing.rst
+++ /dev/null
@@ -1,246 +0,0 @@
-==================================
-Memory Attribute Aliasing on IA-64
-==================================
-
-Bjorn Helgaas <bjorn.helgaas@hp.com>
-
-May 4, 2006
-
-
-Memory Attributes
-=================
-
- Itanium supports several attributes for virtual memory references.
- The attribute is part of the virtual translation, i.e., it is
- contained in the TLB entry. The ones of most interest to the Linux
- kernel are:
-
- == ======================
- WB Write-back (cacheable)
- UC Uncacheable
- WC Write-coalescing
- == ======================
-
- System memory typically uses the WB attribute. The UC attribute is
- used for memory-mapped I/O devices. The WC attribute is uncacheable
- like UC is, but writes may be delayed and combined to increase
- performance for things like frame buffers.
-
- The Itanium architecture requires that we avoid accessing the same
- page with both a cacheable mapping and an uncacheable mapping[1].
-
- The design of the chipset determines which attributes are supported
- on which regions of the address space. For example, some chipsets
- support either WB or UC access to main memory, while others support
- only WB access.
-
-Memory Map
-==========
-
- Platform firmware describes the physical memory map and the
- supported attributes for each region. At boot-time, the kernel uses
- the EFI GetMemoryMap() interface. ACPI can also describe memory
- devices and the attributes they support, but Linux/ia64 currently
- doesn't use this information.
-
- The kernel uses the efi_memmap table returned from GetMemoryMap() to
- learn the attributes supported by each region of physical address
- space. Unfortunately, this table does not completely describe the
- address space because some machines omit some or all of the MMIO
- regions from the map.
-
- The kernel maintains another table, kern_memmap, which describes the
- memory Linux is actually using and the attribute for each region.
- This contains only system memory; it does not contain MMIO space.
-
- The kern_memmap table typically contains only a subset of the system
- memory described by the efi_memmap. Linux/ia64 can't use all memory
- in the system because of constraints imposed by the identity mapping
- scheme.
-
- The efi_memmap table is preserved unmodified because the original
- boot-time information is required for kexec.
-
-Kernel Identity Mappings
-========================
-
- Linux/ia64 identity mappings are done with large pages, currently
- either 16MB or 64MB, referred to as "granules." Cacheable mappings
- are speculative[2], so the processor can read any location in the
- page at any time, independent of the programmer's intentions. This
- means that to avoid attribute aliasing, Linux can create a cacheable
- identity mapping only when the entire granule supports cacheable
- access.
-
- Therefore, kern_memmap contains only full granule-sized regions that
- can referenced safely by an identity mapping.
-
- Uncacheable mappings are not speculative, so the processor will
- generate UC accesses only to locations explicitly referenced by
- software. This allows UC identity mappings to cover granules that
- are only partially populated, or populated with a combination of UC
- and WB regions.
-
-User Mappings
-=============
-
- User mappings are typically done with 16K or 64K pages. The smaller
- page size allows more flexibility because only 16K or 64K has to be
- homogeneous with respect to memory attributes.
-
-Potential Attribute Aliasing Cases
-==================================
-
- There are several ways the kernel creates new mappings:
-
-mmap of /dev/mem
-----------------
-
- This uses remap_pfn_range(), which creates user mappings. These
- mappings may be either WB or UC. If the region being mapped
- happens to be in kern_memmap, meaning that it may also be mapped
- by a kernel identity mapping, the user mapping must use the same
- attribute as the kernel mapping.
-
- If the region is not in kern_memmap, the user mapping should use
- an attribute reported as being supported in the EFI memory map.
-
- Since the EFI memory map does not describe MMIO on some
- machines, this should use an uncacheable mapping as a fallback.
-
-mmap of /sys/class/pci_bus/.../legacy_mem
------------------------------------------
-
- This is very similar to mmap of /dev/mem, except that legacy_mem
- only allows mmap of the one megabyte "legacy MMIO" area for a
- specific PCI bus. Typically this is the first megabyte of
- physical address space, but it may be different on machines with
- several VGA devices.
-
- "X" uses this to access VGA frame buffers. Using legacy_mem
- rather than /dev/mem allows multiple instances of X to talk to
- different VGA cards.
-
- The /dev/mem mmap constraints apply.
-
-mmap of /proc/bus/pci/.../??.?
-------------------------------
-
- This is an MMIO mmap of PCI functions, which additionally may or
- may not be requested as using the WC attribute.
-
- If WC is requested, and the region in kern_memmap is either WC
- or UC, and the EFI memory map designates the region as WC, then
- the WC mapping is allowed.
-
- Otherwise, the user mapping must use the same attribute as the
- kernel mapping.
-
-read/write of /dev/mem
-----------------------
-
- This uses copy_from_user(), which implicitly uses a kernel
- identity mapping. This is obviously safe for things in
- kern_memmap.
-
- There may be corner cases of things that are not in kern_memmap,
- but could be accessed this way. For example, registers in MMIO
- space are not in kern_memmap, but could be accessed with a UC
- mapping. This would not cause attribute aliasing. But
- registers typically can be accessed only with four-byte or
- eight-byte accesses, and the copy_from_user() path doesn't allow
- any control over the access size, so this would be dangerous.
-
-ioremap()
----------
-
- This returns a mapping for use inside the kernel.
-
- If the region is in kern_memmap, we should use the attribute
- specified there.
-
- If the EFI memory map reports that the entire granule supports
- WB, we should use that (granules that are partially reserved
- or occupied by firmware do not appear in kern_memmap).
-
- If the granule contains non-WB memory, but we can cover the
- region safely with kernel page table mappings, we can use
- ioremap_page_range() as most other architectures do.
-
- Failing all of the above, we have to fall back to a UC mapping.
-
-Past Problem Cases
-==================
-
-mmap of various MMIO regions from /dev/mem by "X" on Intel platforms
---------------------------------------------------------------------
-
- The EFI memory map may not report these MMIO regions.
-
- These must be allowed so that X will work. This means that
- when the EFI memory map is incomplete, every /dev/mem mmap must
- succeed. It may create either WB or UC user mappings, depending
- on whether the region is in kern_memmap or the EFI memory map.
-
-mmap of 0x0-0x9FFFF /dev/mem by "hwinfo" on HP sx1000 with VGA enabled
-----------------------------------------------------------------------
-
- The EFI memory map reports the following attributes:
-
- =============== ======= ==================
- 0x00000-0x9FFFF WB only
- 0xA0000-0xBFFFF UC only (VGA frame buffer)
- 0xC0000-0xFFFFF WB only
- =============== ======= ==================
-
- This mmap is done with user pages, not kernel identity mappings,
- so it is safe to use WB mappings.
-
- The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000,
- which uses a granule-sized UC mapping. This granule will cover some
- WB-only memory, but since UC is non-speculative, the processor will
- never generate an uncacheable reference to the WB-only areas unless
- the driver explicitly touches them.
-
-mmap of 0x0-0xFFFFF legacy_mem by "X"
--------------------------------------
-
- If the EFI memory map reports that the entire range supports the
- same attributes, we can allow the mmap (and we will prefer WB if
- supported, as is the case with HP sx[12]000 machines with VGA
- disabled).
-
- If EFI reports the range as partly WB and partly UC (as on sx[12]000
- machines with VGA enabled), we must fail the mmap because there's no
- safe attribute to use.
-
- If EFI reports some of the range but not all (as on Intel firmware
- that doesn't report the VGA frame buffer at all), we should fail the
- mmap and force the user to map just the specific region of interest.
-
-mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled
-------------------------------------------------------------------------
-
- The EFI memory map reports the following attributes::
-
- 0x00000-0xFFFFF WB only (no VGA MMIO hole)
-
- This is a special case of the previous case, and the mmap should
- fail for the same reason as above.
-
-read of /sys/devices/.../rom
-----------------------------
-
- For VGA devices, this may cause an ioremap() of 0xC0000. This
- used to be done with a UC mapping, because the VGA frame buffer
- at 0xA0000 prevents use of a WB granule. The UC mapping causes
- an MCA on HP sx[12]000 chipsets.
-
- We should use WB page table mappings to avoid covering the VGA
- frame buffer.
-
-Notes
-=====
-
- [1] SDM rev 2.2, vol 2, sec 4.4.1.
- [2] SDM rev 2.2, vol 2, sec 4.4.6.
diff --git a/Documentation/arch/ia64/efirtc.rst b/Documentation/arch/ia64/efirtc.rst
deleted file mode 100644
index fd8328408301..000000000000
--- a/Documentation/arch/ia64/efirtc.rst
+++ /dev/null
@@ -1,144 +0,0 @@
-==========================
-EFI Real Time Clock driver
-==========================
-
-S. Eranian <eranian@hpl.hp.com>
-
-March 2000
-
-1. Introduction
-===============
-
-This document describes the efirtc.c driver has provided for
-the IA-64 platform.
-
-The purpose of this driver is to supply an API for kernel and user applications
-to get access to the Time Service offered by EFI version 0.92.
-
-EFI provides 4 calls one can make once the OS is booted: GetTime(),
-SetTime(), GetWakeupTime(), SetWakeupTime() which are all supported by this
-driver. We describe those calls as well the design of the driver in the
-following sections.
-
-2. Design Decisions
-===================
-
-The original ideas was to provide a very simple driver to get access to,
-at first, the time of day service. This is required in order to access, in a
-portable way, the CMOS clock. A program like /sbin/hwclock uses such a clock
-to initialize the system view of the time during boot.
-
-Because we wanted to minimize the impact on existing user-level apps using
-the CMOS clock, we decided to expose an API that was very similar to the one
-used today with the legacy RTC driver (driver/char/rtc.c). However, because
-EFI provides a simpler services, not all ioctl() are available. Also
-new ioctl()s have been introduced for things that EFI provides but not the
-legacy.
-
-EFI uses a slightly different way of representing the time, noticeably
-the reference date is different. Year is the using the full 4-digit format.
-The Epoch is January 1st 1998. For backward compatibility reasons we don't
-expose this new way of representing time. Instead we use something very
-similar to the struct tm, i.e. struct rtc_time, as used by hwclock.
-One of the reasons for doing it this way is to allow for EFI to still evolve
-without necessarily impacting any of the user applications. The decoupling
-enables flexibility and permits writing wrapper code is ncase things change.
-
-The driver exposes two interfaces, one via the device file and a set of
-ioctl()s. The other is read-only via the /proc filesystem.
-
-As of today we don't offer a /proc/sys interface.
-
-To allow for a uniform interface between the legacy RTC and EFI time service,
-we have created the include/linux/rtc.h header file to contain only the
-"public" API of the two drivers. The specifics of the legacy RTC are still
-in include/linux/mc146818rtc.h.
-
-
-3. Time of day service
-======================
-
-The part of the driver gives access to the time of day service of EFI.
-Two ioctl()s, compatible with the legacy RTC calls:
-
- Read the CMOS clock::
-
- ioctl(d, RTC_RD_TIME, &rtc);
-
- Write the CMOS clock::
-
- ioctl(d, RTC_SET_TIME, &rtc);
-
-The rtc is a pointer to a data structure defined in rtc.h which is close
-to a struct tm::
-
- struct rtc_time {
- int tm_sec;
- int tm_min;
- int tm_hour;
- int tm_mday;
- int tm_mon;
- int tm_year;
- int tm_wday;
- int tm_yday;
- int tm_isdst;
- };
-
-The driver takes care of converting back an forth between the EFI time and
-this format.
-
-Those two ioctl()s can be exercised with the hwclock command:
-
-For reading::
-
- # /sbin/hwclock --show
- Mon Mar 6 15:32:32 2000 -0.910248 seconds
-
-For setting::
-
- # /sbin/hwclock --systohc
-
-Root privileges are required to be able to set the time of day.
-
-4. Wakeup Alarm service
-=======================
-
-EFI provides an API by which one can program when a machine should wakeup,
-i.e. reboot. This is very different from the alarm provided by the legacy
-RTC which is some kind of interval timer alarm. For this reason we don't use
-the same ioctl()s to get access to the service. Instead we have
-introduced 2 news ioctl()s to the interface of an RTC.
-
-We have added 2 new ioctl()s that are specific to the EFI driver:
-
- Read the current state of the alarm::
-
- ioctl(d, RTC_WKALM_RD, &wkt)
-
- Set the alarm or change its status::
-
- ioctl(d, RTC_WKALM_SET, &wkt)
-
-The wkt structure encapsulates a struct rtc_time + 2 extra fields to get
-status information::
-
- struct rtc_wkalrm {
-
- unsigned char enabled; /* =1 if alarm is enabled */
- unsigned char pending; /* =1 if alarm is pending */
-
- struct rtc_time time;
- }
-
-As of today, none of the existing user-level apps supports this feature.
-However writing such a program should be hard by simply using those two
-ioctl().
-
-Root privileges are required to be able to set the alarm.
-
-5. References
-=============
-
-Checkout the following Web site for more information on EFI:
-
-http://developer.intel.com/technology/efi/
diff --git a/Documentation/arch/ia64/err_inject.rst b/Documentation/arch/ia64/err_inject.rst
deleted file mode 100644
index 900f71e93a29..000000000000
--- a/Documentation/arch/ia64/err_inject.rst
+++ /dev/null
@@ -1,1067 +0,0 @@
-========================================
-IPF Machine Check (MC) error inject tool
-========================================
-
-IPF Machine Check (MC) error inject tool is used to inject MC
-errors from Linux. The tool is a test bed for IPF MC work flow including
-hardware correctable error handling, OS recoverable error handling, MC
-event logging, etc.
-
-The tool includes two parts: a kernel driver and a user application
-sample. The driver provides interface to PAL to inject error
-and query error injection capabilities. The driver code is in
-arch/ia64/kernel/err_inject.c. The application sample (shown below)
-provides a combination of various errors and calls the driver's interface
-(sysfs interface) to inject errors or query error injection capabilities.
-
-The tool can be used to test Intel IPF machine MC handling capabilities.
-It's especially useful for people who can not access hardware MC injection
-tool to inject error. It's also very useful to integrate with other
-software test suits to do stressful testing on IPF.
-
-Below is a sample application as part of the whole tool. The sample
-can be used as a working test tool. Or it can be expanded to include
-more features. It also can be a integrated into a library or other user
-application to have more thorough test.
-
-The sample application takes err.conf as error configuration input. GCC
-compiles the code. After you install err_inject driver, you can run
-this sample application to inject errors.
-
-Errata: Itanium 2 Processors Specification Update lists some errata against
-the pal_mc_error_inject PAL procedure. The following err.conf has been tested
-on latest Montecito PAL.
-
-err.conf::
-
- #This is configuration file for err_inject_tool.
- #The format of the each line is:
- #cpu, loop, interval, err_type_info, err_struct_info, err_data_buffer
- #where
- # cpu: logical cpu number the error will be inject in.
- # loop: times the error will be injected.
- # interval: In second. every so often one error is injected.
- # err_type_info, err_struct_info: PAL parameters.
- #
- #Note: All values are hex w/o or w/ 0x prefix.
-
-
- #On cpu2, inject only total 0x10 errors, interval 5 seconds
- #corrected, data cache, hier-2, physical addr(assigned by tool code).
- #working on Montecito latest PAL.
- 2, 10, 5, 4101, 95
-
- #On cpu4, inject and consume total 0x10 errors, interval 5 seconds
- #corrected, data cache, hier-2, physical addr(assigned by tool code).
- #working on Montecito latest PAL.
- 4, 10, 5, 4109, 95
-
- #On cpu15, inject and consume total 0x10 errors, interval 5 seconds
- #recoverable, DTR0, hier-2.
- #working on Montecito latest PAL.
- 0xf, 0x10, 5, 4249, 15
-
-The sample application source code:
-
-err_injection_tool.c::
-
- /*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Copyright (C) 2006 Intel Co
- * Fenghua Yu <fenghua.yu@intel.com>
- *
- */
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <sched.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <string.h>
- #include <errno.h>
- #include <time.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/wait.h>
- #include <sys/mman.h>
- #include <sys/shm.h>
-
- #define MAX_FN_SIZE 256
- #define MAX_BUF_SIZE 256
- #define DATA_BUF_SIZE 256
- #define NR_CPUS 512
- #define MAX_TASK_NUM 2048
- #define MIN_INTERVAL 5 // seconds
- #define ERR_DATA_BUFFER_SIZE 3 // Three 8-byte.
- #define PARA_FIELD_NUM 5
- #define MASK_SIZE (NR_CPUS/64)
- #define PATH_FORMAT "/sys/devices/system/cpu/cpu%d/err_inject/"
-
- int sched_setaffinity(pid_t pid, unsigned int len, unsigned long *mask);
-
- int verbose;
- #define vbprintf if (verbose) printf
-
- int log_info(int cpu, const char *fmt, ...)
- {
- FILE *log;
- char fn[MAX_FN_SIZE];
- char buf[MAX_BUF_SIZE];
- va_list args;
-
- sprintf(fn, "%d.log", cpu);
- log=fopen(fn, "a+");
- if (log==NULL) {
- perror("Error open:");
- return -1;
- }
-
- va_start(args, fmt);
- vprintf(fmt, args);
- memset(buf, 0, MAX_BUF_SIZE);
- vsprintf(buf, fmt, args);
- va_end(args);
-
- fwrite(buf, sizeof(buf), 1, log);
- fclose(log);
-
- return 0;
- }
-
- typedef unsigned long u64;
- typedef unsigned int u32;
-
- typedef union err_type_info_u {
- struct {
- u64 mode : 3, /* 0-2 */
- err_inj : 3, /* 3-5 */
- err_sev : 2, /* 6-7 */
- err_struct : 5, /* 8-12 */
- struct_hier : 3, /* 13-15 */
- reserved : 48; /* 16-63 */
- } err_type_info_u;
- u64 err_type_info;
- } err_type_info_t;
-
- typedef union err_struct_info_u {
- struct {
- u64 siv : 1, /* 0 */
- c_t : 2, /* 1-2 */
- cl_p : 3, /* 3-5 */
- cl_id : 3, /* 6-8 */
- cl_dp : 1, /* 9 */
- reserved1 : 22, /* 10-31 */
- tiv : 1, /* 32 */
- trigger : 4, /* 33-36 */
- trigger_pl : 3, /* 37-39 */
- reserved2 : 24; /* 40-63 */
- } err_struct_info_cache;
- struct {
- u64 siv : 1, /* 0 */
- tt : 2, /* 1-2 */
- tc_tr : 2, /* 3-4 */
- tr_slot : 8, /* 5-12 */
- reserved1 : 19, /* 13-31 */
- tiv : 1, /* 32 */
- trigger : 4, /* 33-36 */
- trigger_pl : 3, /* 37-39 */
- reserved2 : 24; /* 40-63 */
- } err_struct_info_tlb;
- struct {
- u64 siv : 1, /* 0 */
- regfile_id : 4, /* 1-4 */
- reg_num : 7, /* 5-11 */
- reserved1 : 20, /* 12-31 */
- tiv : 1, /* 32 */
- trigger : 4, /* 33-36 */
- trigger_pl : 3, /* 37-39 */
- reserved2 : 24; /* 40-63 */
- } err_struct_info_register;
- struct {
- u64 reserved;
- } err_struct_info_bus_processor_interconnect;
- u64 err_struct_info;
- } err_struct_info_t;
-
- typedef union err_data_buffer_u {
- struct {
- u64 trigger_addr; /* 0-63 */
- u64 inj_addr; /* 64-127 */
- u64 way : 5, /* 128-132 */
- index : 20, /* 133-152 */
- : 39; /* 153-191 */
- } err_data_buffer_cache;
- struct {
- u64 trigger_addr; /* 0-63 */
- u64 inj_addr; /* 64-127 */
- u64 way : 5, /* 128-132 */
- index : 20, /* 133-152 */
- reserved : 39; /* 153-191 */
- } err_data_buffer_tlb;
- struct {
- u64 trigger_addr; /* 0-63 */
- } err_data_buffer_register;
- struct {
- u64 reserved; /* 0-63 */
- } err_data_buffer_bus_processor_interconnect;
- u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];
- } err_data_buffer_t;
-
- typedef union capabilities_u {
- struct {
- u64 i : 1,
- d : 1,
- rv : 1,
- tag : 1,
- data : 1,
- mesi : 1,
- dp : 1,
- reserved1 : 3,
- pa : 1,
- va : 1,
- wi : 1,
- reserved2 : 20,
- trigger : 1,
- trigger_pl : 1,
- reserved3 : 30;
- } capabilities_cache;
- struct {
- u64 d : 1,
- i : 1,
- rv : 1,
- tc : 1,
- tr : 1,
- reserved1 : 27,
- trigger : 1,
- trigger_pl : 1,
- reserved2 : 30;
- } capabilities_tlb;
- struct {
- u64 gr_b0 : 1,
- gr_b1 : 1,
- fr : 1,
- br : 1,
- pr : 1,
- ar : 1,
- cr : 1,
- rr : 1,
- pkr : 1,
- dbr : 1,
- ibr : 1,
- pmc : 1,
- pmd : 1,
- reserved1 : 3,
- regnum : 1,
- reserved2 : 15,
- trigger : 1,
- trigger_pl : 1,
- reserved3 : 30;
- } capabilities_register;
- struct {
- u64 reserved;
- } capabilities_bus_processor_interconnect;
- } capabilities_t;
-
- typedef struct resources_s {
- u64 ibr0 : 1,
- ibr2 : 1,
- ibr4 : 1,
- ibr6 : 1,
- dbr0 : 1,
- dbr2 : 1,
- dbr4 : 1,
- dbr6 : 1,
- reserved : 48;
- } resources_t;
-
-
- long get_page_size(void)
- {
- long page_size=sysconf(_SC_PAGESIZE);
- return page_size;
- }
-
- #define PAGE_SIZE (get_page_size()==-1?0x4000:get_page_size())
- #define SHM_SIZE (2*PAGE_SIZE*NR_CPUS)
- #define SHM_VA 0x2000000100000000
-
- int shmid;
- void *shmaddr;
-
- int create_shm(void)
- {
- key_t key;
- char fn[MAX_FN_SIZE];
-
- /* cpu0 is always existing */
- sprintf(fn, PATH_FORMAT, 0);
- if ((key = ftok(fn, 's')) == -1) {
- perror("ftok");
- return -1;
- }
-
- shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT);
- if (shmid == -1) {
- if (errno==EEXIST) {
- shmid = shmget(key, SHM_SIZE, 0);
- if (shmid == -1) {
- perror("shmget");
- return -1;
- }
- }
- else {
- perror("shmget");
- return -1;
- }
- }
- vbprintf("shmid=%d", shmid);
-
- /* connect to the segment: */
- shmaddr = shmat(shmid, (void *)SHM_VA, 0);
- if (shmaddr == (void*)-1) {
- perror("shmat");
- return -1;
- }
-
- memset(shmaddr, 0, SHM_SIZE);
- mlock(shmaddr, SHM_SIZE);
-
- return 0;
- }
-
- int free_shm()
- {
- munlock(shmaddr, SHM_SIZE);
- shmdt(shmaddr);
- semctl(shmid, 0, IPC_RMID);
-
- return 0;
- }
-
- #ifdef _SEM_SEMUN_UNDEFINED
- union semun
- {
- int val;
- struct semid_ds *buf;
- unsigned short int *array;
- struct seminfo *__buf;
- };
- #endif
-
- u32 mode=1; /* 1: physical mode; 2: virtual mode. */
- int one_lock=1;
- key_t key[NR_CPUS];
- int semid[NR_CPUS];
-
- int create_sem(int cpu)
- {
- union semun arg;
- char fn[MAX_FN_SIZE];
- int sid;
-
- sprintf(fn, PATH_FORMAT, cpu);
- sprintf(fn, "%s/%s", fn, "err_type_info");
- if ((key[cpu] = ftok(fn, 'e')) == -1) {
- perror("ftok");
- return -1;
- }
-
- if (semid[cpu]!=0)
- return 0;
-
- /* clear old semaphore */
- if ((sid = semget(key[cpu], 1, 0)) != -1)
- semctl(sid, 0, IPC_RMID);
-
- /* get one semaphore */
- if ((semid[cpu] = semget(key[cpu], 1, IPC_CREAT | IPC_EXCL)) == -1) {
- perror("semget");
- printf("Please remove semaphore with key=0x%lx, then run the tool.\n",
- (u64)key[cpu]);
- return -1;
- }
-
- vbprintf("semid[%d]=0x%lx, key[%d]=%lx\n",cpu,(u64)semid[cpu],cpu,
- (u64)key[cpu]);
- /* initialize the semaphore to 1: */
- arg.val = 1;
- if (semctl(semid[cpu], 0, SETVAL, arg) == -1) {
- perror("semctl");
- return -1;
- }
-
- return 0;
- }
-
- static int lock(int cpu)
- {
- struct sembuf lock;
-
- lock.sem_num = cpu;
- lock.sem_op = 1;
- semop(semid[cpu], &lock, 1);
-
- return 0;
- }
-
- static int unlock(int cpu)
- {
- struct sembuf unlock;
-
- unlock.sem_num = cpu;
- unlock.sem_op = -1;
- semop(semid[cpu], &unlock, 1);
-
- return 0;
- }
-
- void free_sem(int cpu)
- {
- semctl(semid[cpu], 0, IPC_RMID);
- }
-
- int wr_multi(char *fn, unsigned long *data, int size)
- {
- int fd;
- char buf[MAX_BUF_SIZE];
- int ret;
-
- if (size==1)
- sprintf(buf, "%lx", *data);
- else if (size==3)
- sprintf(buf, "%lx,%lx,%lx", data[0], data[1], data[2]);
- else {
- fprintf(stderr,"write to file with wrong size!\n");
- return -1;
- }
-
- fd=open(fn, O_RDWR);
- if (!fd) {
- perror("Error:");
- return -1;
- }
- ret=write(fd, buf, sizeof(buf));
- close(fd);
- return ret;
- }
-
- int wr(char *fn, unsigned long data)
- {
- return wr_multi(fn, &data, 1);
- }
-
- int rd(char *fn, unsigned long *data)
- {
- int fd;
- char buf[MAX_BUF_SIZE];
-
- fd=open(fn, O_RDONLY);
- if (fd<0) {
- perror("Error:");
- return -1;
- }
- read(fd, buf, MAX_BUF_SIZE);
- *data=strtoul(buf, NULL, 16);
- close(fd);
- return 0;
- }
-
- int rd_status(char *path, int *status)
- {
- char fn[MAX_FN_SIZE];
- sprintf(fn, "%s/status", path);
- if (rd(fn, (u64*)status)<0) {
- perror("status reading error.\n");
- return -1;
- }
-
- return 0;
- }
-
- int rd_capabilities(char *path, u64 *capabilities)
- {
- char fn[MAX_FN_SIZE];
- sprintf(fn, "%s/capabilities", path);
- if (rd(fn, capabilities)<0) {
- perror("capabilities reading error.\n");
- return -1;
- }
-
- return 0;
- }
-
- int rd_all(char *path)
- {
- unsigned long err_type_info, err_struct_info, err_data_buffer;
- int status;
- unsigned long capabilities, resources;
- char fn[MAX_FN_SIZE];
-
- sprintf(fn, "%s/err_type_info", path);
- if (rd(fn, &err_type_info)<0) {
- perror("err_type_info reading error.\n");
- return -1;
- }
- printf("err_type_info=%lx\n", err_type_info);
-
- sprintf(fn, "%s/err_struct_info", path);
- if (rd(fn, &err_struct_info)<0) {
- perror("err_struct_info reading error.\n");
- return -1;
- }
- printf("err_struct_info=%lx\n", err_struct_info);
-
- sprintf(fn, "%s/err_data_buffer", path);
- if (rd(fn, &err_data_buffer)<0) {
- perror("err_data_buffer reading error.\n");
- return -1;
- }
- printf("err_data_buffer=%lx\n", err_data_buffer);
-
- sprintf(fn, "%s/status", path);
- if (rd("status", (u64*)&status)<0) {
- perror("status reading error.\n");
- return -1;
- }
- printf("status=%d\n", status);
-
- sprintf(fn, "%s/capabilities", path);
- if (rd(fn,&capabilities)<0) {
- perror("capabilities reading error.\n");
- return -1;
- }
- printf("capabilities=%lx\n", capabilities);
-
- sprintf(fn, "%s/resources", path);
- if (rd(fn, &resources)<0) {
- perror("resources reading error.\n");
- return -1;
- }
- printf("resources=%lx\n", resources);
-
- return 0;
- }
-
- int query_capabilities(char *path, err_type_info_t err_type_info,
- u64 *capabilities)
- {
- char fn[MAX_FN_SIZE];
- err_struct_info_t err_struct_info;
- err_data_buffer_t err_data_buffer;
-
- err_struct_info.err_struct_info=0;
- memset(err_data_buffer.err_data_buffer, -1, ERR_DATA_BUFFER_SIZE*8);
-
- sprintf(fn, "%s/err_type_info", path);
- wr(fn, err_type_info.err_type_info);
- sprintf(fn, "%s/err_struct_info", path);
- wr(fn, 0x0);
- sprintf(fn, "%s/err_data_buffer", path);
- wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE);
-
- // Fire pal_mc_error_inject procedure.
- sprintf(fn, "%s/call_start", path);
- wr(fn, mode);
-
- if (rd_capabilities(path, capabilities)<0)
- return -1;
-
- return 0;
- }
-
- int query_all_capabilities()
- {
- int status;
- err_type_info_t err_type_info;
- int err_sev, err_struct, struct_hier;
- int cap=0;
- u64 capabilities;
- char path[MAX_FN_SIZE];
-
- err_type_info.err_type_info=0; // Initial
- err_type_info.err_type_info_u.mode=0; // Query mode;
- err_type_info.err_type_info_u.err_inj=0;
-
- printf("All capabilities implemented in pal_mc_error_inject:\n");
- sprintf(path, PATH_FORMAT ,0);
- for (err_sev=0;err_sev<3;err_sev++)
- for (err_struct=0;err_struct<5;err_struct++)
- for (struct_hier=0;struct_hier<5;struct_hier++)
- {
- status=-1;
- capabilities=0;
- err_type_info.err_type_info_u.err_sev=err_sev;
- err_type_info.err_type_info_u.err_struct=err_struct;
- err_type_info.err_type_info_u.struct_hier=struct_hier;
-
- if (query_capabilities(path, err_type_info, &capabilities)<0)
- continue;
-
- if (rd_status(path, &status)<0)
- continue;
-
- if (status==0) {
- cap=1;
- printf("For err_sev=%d, err_struct=%d, struct_hier=%d: ",
- err_sev, err_struct, struct_hier);
- printf("capabilities 0x%lx\n", capabilities);
- }
- }
- if (!cap) {
- printf("No capabilities supported.\n");
- return 0;
- }
-
- return 0;
- }
-
- int err_inject(int cpu, char *path, err_type_info_t err_type_info,
- err_struct_info_t err_struct_info,
- err_data_buffer_t err_data_buffer)
- {
- int status;
- char fn[MAX_FN_SIZE];
-
- log_info(cpu, "err_type_info=%lx, err_struct_info=%lx, ",
- err_type_info.err_type_info,
- err_struct_info.err_struct_info);
- log_info(cpu,"err_data_buffer=[%lx,%lx,%lx]\n",
- err_data_buffer.err_data_buffer[0],
- err_data_buffer.err_data_buffer[1],
- err_data_buffer.err_data_buffer[2]);
- sprintf(fn, "%s/err_type_info", path);
- wr(fn, err_type_info.err_type_info);
- sprintf(fn, "%s/err_struct_info", path);
- wr(fn, err_struct_info.err_struct_info);
- sprintf(fn, "%s/err_data_buffer", path);
- wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE);
-
- // Fire pal_mc_error_inject procedure.
- sprintf(fn, "%s/call_start", path);
- wr(fn,mode);
-
- if (rd_status(path, &status)<0) {
- vbprintf("fail: read status\n");
- return -100;
- }
-
- if (status!=0) {
- log_info(cpu, "fail: status=%d\n", status);
- return status;
- }
-
- return status;
- }
-
- static int construct_data_buf(char *path, err_type_info_t err_type_info,
- err_struct_info_t err_struct_info,
- err_data_buffer_t *err_data_buffer,
- void *va1)
- {
- char fn[MAX_FN_SIZE];
- u64 virt_addr=0, phys_addr=0;
-
- vbprintf("va1=%lx\n", (u64)va1);
- memset(&err_data_buffer->err_data_buffer_cache, 0, ERR_DATA_BUFFER_SIZE*8);
-
- switch (err_type_info.err_type_info_u.err_struct) {
- case 1: // Cache
- switch (err_struct_info.err_struct_info_cache.cl_id) {
- case 1: //Virtual addr
- err_data_buffer->err_data_buffer_cache.inj_addr=(u64)va1;
- break;
- case 2: //Phys addr
- sprintf(fn, "%s/virtual_to_phys", path);
- virt_addr=(u64)va1;
- if (wr(fn,virt_addr)<0)
- return -1;
- rd(fn, &phys_addr);
- err_data_buffer->err_data_buffer_cache.inj_addr=phys_addr;
- break;
- default:
- printf("Not supported cl_id\n");
- break;
- }
- break;
- case 2: // TLB
- break;
- case 3: // Register file
- break;
- case 4: // Bus/system interconnect
- default:
- printf("Not supported err_struct\n");
- break;
- }
-
- return 0;
- }
-
- typedef struct {
- u64 cpu;
- u64 loop;
- u64 interval;
- u64 err_type_info;
- u64 err_struct_info;
- u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];
- } parameters_t;
-
- parameters_t line_para;
- int para;
-
- static int empty_data_buffer(u64 *err_data_buffer)
- {
- int empty=1;
- int i;
-
- for (i=0;i<ERR_DATA_BUFFER_SIZE; i++)
- if (err_data_buffer[i]!=-1)
- empty=0;
-
- return empty;
- }
-
- int err_inj()
- {
- err_type_info_t err_type_info;
- err_struct_info_t err_struct_info;
- err_data_buffer_t err_data_buffer;
- int count;
- FILE *fp;
- unsigned long cpu, loop, interval, err_type_info_conf, err_struct_info_conf;
- u64 err_data_buffer_conf[ERR_DATA_BUFFER_SIZE];
- int num;
- int i;
- char path[MAX_FN_SIZE];
- parameters_t parameters[MAX_TASK_NUM]={};
- pid_t child_pid[MAX_TASK_NUM];
- time_t current_time;
- int status;
-
- if (!para) {
- fp=fopen("err.conf", "r");
- if (fp==NULL) {
- perror("Error open err.conf");
- return -1;
- }
-
- num=0;
- while (!feof(fp)) {
- char buf[256];
- memset(buf,0,256);
- fgets(buf, 256, fp);
- count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n",
- &cpu, &loop, &interval,&err_type_info_conf,
- &err_struct_info_conf,
- &err_data_buffer_conf[0],
- &err_data_buffer_conf[1],
- &err_data_buffer_conf[2]);
- if (count!=PARA_FIELD_NUM+3) {
- err_data_buffer_conf[0]=-1;
- err_data_buffer_conf[1]=-1;
- err_data_buffer_conf[2]=-1;
- count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx\n",
- &cpu, &loop, &interval,&err_type_info_conf,
- &err_struct_info_conf);
- if (count!=PARA_FIELD_NUM)
- continue;
- }
-
- parameters[num].cpu=cpu;
- parameters[num].loop=loop;
- parameters[num].interval= interval>MIN_INTERVAL
- ?interval:MIN_INTERVAL;
- parameters[num].err_type_info=err_type_info_conf;
- parameters[num].err_struct_info=err_struct_info_conf;
- memcpy(parameters[num++].err_data_buffer,
- err_data_buffer_conf,ERR_DATA_BUFFER_SIZE*8) ;
-
- if (num>=MAX_TASK_NUM)
- break;
- }
- }
- else {
- parameters[0].cpu=line_para.cpu;
- parameters[0].loop=line_para.loop;
- parameters[0].interval= line_para.interval>MIN_INTERVAL
- ?line_para.interval:MIN_INTERVAL;
- parameters[0].err_type_info=line_para.err_type_info;
- parameters[0].err_struct_info=line_para.err_struct_info;
- memcpy(parameters[0].err_data_buffer,
- line_para.err_data_buffer,ERR_DATA_BUFFER_SIZE*8) ;
-
- num=1;
- }
-
- /* Create semaphore: If one_lock, one semaphore for all processors.
- Otherwise, one semaphore for each processor. */
- if (one_lock) {
- if (create_sem(0)) {
- printf("Can not create semaphore...exit\n");
- free_sem(0);
- return -1;
- }
- }
- else {
- for (i=0;i<num;i++) {
- if (create_sem(parameters[i].cpu)) {
- printf("Can not create semaphore for cpu%d...exit\n",i);
- free_sem(parameters[num].cpu);
- return -1;
- }
- }
- }
-
- /* Create a shm segment which will be used to inject/consume errors on.*/
- if (create_shm()==-1) {
- printf("Error to create shm...exit\n");
- return -1;
- }
-
- for (i=0;i<num;i++) {
- pid_t pid;
-
- current_time=time(NULL);
- log_info(parameters[i].cpu, "\nBegine at %s", ctime(&current_time));
- log_info(parameters[i].cpu, "Configurations:\n");
- log_info(parameters[i].cpu,"On cpu%ld: loop=%lx, interval=%lx(s)",
- parameters[i].cpu,
- parameters[i].loop,
- parameters[i].interval);
- log_info(parameters[i].cpu," err_type_info=%lx,err_struct_info=%lx\n",
- parameters[i].err_type_info,
- parameters[i].err_struct_info);
-
- sprintf(path, PATH_FORMAT, (int)parameters[i].cpu);
- err_type_info.err_type_info=parameters[i].err_type_info;
- err_struct_info.err_struct_info=parameters[i].err_struct_info;
- memcpy(err_data_buffer.err_data_buffer,
- parameters[i].err_data_buffer,
- ERR_DATA_BUFFER_SIZE*8);
-
- pid=fork();
- if (pid==0) {
- unsigned long mask[MASK_SIZE];
- int j, k;
-
- void *va1, *va2;
-
- /* Allocate two memory areas va1 and va2 in shm */
- va1=shmaddr+parameters[i].cpu*PAGE_SIZE;
- va2=shmaddr+parameters[i].cpu*PAGE_SIZE+PAGE_SIZE;
-
- vbprintf("va1=%lx, va2=%lx\n", (u64)va1, (u64)va2);
- memset(va1, 0x1, PAGE_SIZE);
- memset(va2, 0x2, PAGE_SIZE);
-
- if (empty_data_buffer(err_data_buffer.err_data_buffer))
- /* If not specified yet, construct data buffer
- * with va1
- */
- construct_data_buf(path, err_type_info,
- err_struct_info, &err_data_buffer,va1);
-
- for (j=0;j<MASK_SIZE;j++)
- mask[j]=0;
-
- cpu=parameters[i].cpu;
- k = cpu%64;
- j = cpu/64;
- mask[j] = 1UL << k;
-
- if (sched_setaffinity(0, MASK_SIZE*8, mask)==-1) {
- perror("Error sched_setaffinity:");
- return -1;
- }
-
- for (j=0; j<parameters[i].loop; j++) {
- log_info(parameters[i].cpu,"Injection ");
- log_info(parameters[i].cpu,"on cpu%ld: #%d/%ld ",
-
- parameters[i].cpu,j+1, parameters[i].loop);
-
- /* Hold the lock */
- if (one_lock)
- lock(0);
- else
- /* Hold lock on this cpu */
- lock(parameters[i].cpu);
-
- if ((status=err_inject(parameters[i].cpu,
- path, err_type_info,
- err_struct_info, err_data_buffer))
- ==0) {
- /* consume the error for "inject only"*/
- memcpy(va2, va1, PAGE_SIZE);
- memcpy(va1, va2, PAGE_SIZE);
- log_info(parameters[i].cpu,
- "successful\n");
- }
- else {
- log_info(parameters[i].cpu,"fail:");
- log_info(parameters[i].cpu,
- "status=%d\n", status);
- unlock(parameters[i].cpu);
- break;
- }
- if (one_lock)
- /* Release the lock */
- unlock(0);
- /* Release lock on this cpu */
- else
- unlock(parameters[i].cpu);
-
- if (j < parameters[i].loop-1)
- sleep(parameters[i].interval);
- }
- current_time=time(NULL);
- log_info(parameters[i].cpu, "Done at %s", ctime(&current_time));
- return 0;
- }
- else if (pid<0) {
- perror("Error fork:");
- continue;
- }
- child_pid[i]=pid;
- }
- for (i=0;i<num;i++)
- waitpid(child_pid[i], NULL, 0);
-
- if (one_lock)
- free_sem(0);
- else
- for (i=0;i<num;i++)
- free_sem(parameters[i].cpu);
-
- printf("All done.\n");
-
- return 0;
- }
-
- void help()
- {
- printf("err_inject_tool:\n");
- printf("\t-q: query all capabilities. default: off\n");
- printf("\t-m: procedure mode. 1: physical 2: virtual. default: 1\n");
- printf("\t-i: inject errors. default: off\n");
- printf("\t-l: one lock per cpu. default: one lock for all\n");
- printf("\t-e: error parameters:\n");
- printf("\t\tcpu,loop,interval,err_type_info,err_struct_info[,err_data_buffer[0],err_data_buffer[1],err_data_buffer[2]]\n");
- printf("\t\t cpu: logical cpu number the error will be inject in.\n");
- printf("\t\t loop: times the error will be injected.\n");
- printf("\t\t interval: In second. every so often one error is injected.\n");
- printf("\t\t err_type_info, err_struct_info: PAL parameters.\n");
- printf("\t\t err_data_buffer: PAL parameter. Optional. If not present,\n");
- printf("\t\t it's constructed by tool automatically. Be\n");
- printf("\t\t careful to provide err_data_buffer and make\n");
- printf("\t\t sure it's working with the environment.\n");
- printf("\t Note:no space between error parameters.\n");
- printf("\t default: Take error parameters from err.conf instead of command line.\n");
- printf("\t-v: verbose. default: off\n");
- printf("\t-h: help\n\n");
- printf("The tool will take err.conf file as ");
- printf("input to inject single or multiple errors ");
- printf("on one or multiple cpus in parallel.\n");
- }
-
- int main(int argc, char **argv)
- {
- char c;
- int do_err_inj=0;
- int do_query_all=0;
- int count;
- u32 m;
-
- /* Default one lock for all cpu's */
- one_lock=1;
- while ((c = getopt(argc, argv, "m:iqvhle:")) != EOF)
- switch (c) {
- case 'm': /* Procedure mode. 1: phys 2: virt */
- count=sscanf(optarg, "%x", &m);
- if (count!=1 || (m!=1 && m!=2)) {
- printf("Wrong mode number.\n");
- help();
- return -1;
- }
- mode=m;
- break;
- case 'i': /* Inject errors */
- do_err_inj=1;
- break;
- case 'q': /* Query */
- do_query_all=1;
- break;
- case 'v': /* Verbose */
- verbose=1;
- break;
- case 'l': /* One lock per cpu */
- one_lock=0;
- break;
- case 'e': /* error arguments */
- /* Take parameters:
- * #cpu, loop, interval, err_type_info, err_struct_info[, err_data_buffer]
- * err_data_buffer is optional. Recommend not to specify
- * err_data_buffer. Better to use tool to generate it.
- */
- count=sscanf(optarg,
- "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n",
- &line_para.cpu,
- &line_para.loop,
- &line_para.interval,
- &line_para.err_type_info,
- &line_para.err_struct_info,
- &line_para.err_data_buffer[0],
- &line_para.err_data_buffer[1],
- &line_para.err_data_buffer[2]);
- if (count!=PARA_FIELD_NUM+3) {
- line_para.err_data_buffer[0]=-1,
- line_para.err_data_buffer[1]=-1,
- line_para.err_data_buffer[2]=-1;
- count=sscanf(optarg, "%lx, %lx, %lx, %lx, %lx\n",
- &line_para.cpu,
- &line_para.loop,
- &line_para.interval,
- &line_para.err_type_info,
- &line_para.err_struct_info);
- if (count!=PARA_FIELD_NUM) {
- printf("Wrong error arguments.\n");
- help();
- return -1;
- }
- }
- para=1;
- break;
- continue;
- break;
- case 'h':
- help();
- return 0;
- default:
- break;
- }
-
- if (do_query_all)
- query_all_capabilities();
- if (do_err_inj)
- err_inj();
-
- if (!do_query_all && !do_err_inj)
- help();
-
- return 0;
- }
diff --git a/Documentation/arch/ia64/features.rst b/Documentation/arch/ia64/features.rst
deleted file mode 100644
index d7226fdcf5f8..000000000000
--- a/Documentation/arch/ia64/features.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. kernel-feat:: $srctree/Documentation/features ia64
diff --git a/Documentation/arch/ia64/fsys.rst b/Documentation/arch/ia64/fsys.rst
deleted file mode 100644
index a702d2cc94b6..000000000000
--- a/Documentation/arch/ia64/fsys.rst
+++ /dev/null
@@ -1,303 +0,0 @@
-===================================
-Light-weight System Calls for IA-64
-===================================
-
- Started: 13-Jan-2003
-
- Last update: 27-Sep-2003
-
- David Mosberger-Tang
- <davidm@hpl.hp.com>
-
-Using the "epc" instruction effectively introduces a new mode of
-execution to the ia64 linux kernel. We call this mode the
-"fsys-mode". To recap, the normal states of execution are:
-
- - kernel mode:
- Both the register stack and the memory stack have been
- switched over to kernel memory. The user-level state is saved
- in a pt-regs structure at the top of the kernel memory stack.
-
- - user mode:
- Both the register stack and the kernel stack are in
- user memory. The user-level state is contained in the
- CPU registers.
-
- - bank 0 interruption-handling mode:
- This is the non-interruptible state which all
- interruption-handlers start execution in. The user-level
- state remains in the CPU registers and some kernel state may
- be stored in bank 0 of registers r16-r31.
-
-In contrast, fsys-mode has the following special properties:
-
- - execution is at privilege level 0 (most-privileged)
-
- - CPU registers may contain a mixture of user-level and kernel-level
- state (it is the responsibility of the kernel to ensure that no
- security-sensitive kernel-level state is leaked back to
- user-level)
-
- - execution is interruptible and preemptible (an fsys-mode handler
- can disable interrupts and avoid all other interruption-sources
- to avoid preemption)
-
- - neither the memory-stack nor the register-stack can be trusted while
- in fsys-mode (they point to the user-level stacks, which may
- be invalid, or completely bogus addresses)
-
-In summary, fsys-mode is much more similar to running in user-mode
-than it is to running in kernel-mode. Of course, given that the
-privilege level is at level 0, this means that fsys-mode requires some
-care (see below).
-
-
-How to tell fsys-mode
-=====================
-
-Linux operates in fsys-mode when (a) the privilege level is 0 (most
-privileged) and (b) the stacks have NOT been switched to kernel memory
-yet. For convenience, the header file <asm-ia64/ptrace.h> provides
-three macros::
-
- user_mode(regs)
- user_stack(task,regs)
- fsys_mode(task,regs)
-
-The "regs" argument is a pointer to a pt_regs structure. The "task"
-argument is a pointer to the task structure to which the "regs"
-pointer belongs to. user_mode() returns TRUE if the CPU state pointed
-to by "regs" was executing in user mode (privilege level 3).
-user_stack() returns TRUE if the state pointed to by "regs" was
-executing on the user-level stack(s). Finally, fsys_mode() returns
-TRUE if the CPU state pointed to by "regs" was executing in fsys-mode.
-The fsys_mode() macro is equivalent to the expression::
-
- !user_mode(regs) && user_stack(task,regs)
-
-How to write an fsyscall handler
-================================
-
-The file arch/ia64/kernel/fsys.S contains a table of fsyscall-handlers
-(fsyscall_table). This table contains one entry for each system call.
-By default, a system call is handled by fsys_fallback_syscall(). This
-routine takes care of entering (full) kernel mode and calling the
-normal Linux system call handler. For performance-critical system
-calls, it is possible to write a hand-tuned fsyscall_handler. For
-example, fsys.S contains fsys_getpid(), which is a hand-tuned version
-of the getpid() system call.
-
-The entry and exit-state of an fsyscall handler is as follows:
-
-Machine state on entry to fsyscall handler
-------------------------------------------
-
- ========= ===============================================================
- r10 0
- r11 saved ar.pfs (a user-level value)
- r15 system call number
- r16 "current" task pointer (in normal kernel-mode, this is in r13)
- r32-r39 system call arguments
- b6 return address (a user-level value)
- ar.pfs previous frame-state (a user-level value)
- PSR.be cleared to zero (i.e., little-endian byte order is in effect)
- - all other registers may contain values passed in from user-mode
- ========= ===============================================================
-
-Required machine state on exit to fsyscall handler
---------------------------------------------------
-
- ========= ===========================================================
- r11 saved ar.pfs (as passed into the fsyscall handler)
- r15 system call number (as passed into the fsyscall handler)
- r32-r39 system call arguments (as passed into the fsyscall handler)
- b6 return address (as passed into the fsyscall handler)
- ar.pfs previous frame-state (as passed into the fsyscall handler)
- ========= ===========================================================
-
-Fsyscall handlers can execute with very little overhead, but with that
-speed comes a set of restrictions:
-
- * Fsyscall-handlers MUST check for any pending work in the flags
- member of the thread-info structure and if any of the
- TIF_ALLWORK_MASK flags are set, the handler needs to fall back on
- doing a full system call (by calling fsys_fallback_syscall).
-
- * Fsyscall-handlers MUST preserve incoming arguments (r32-r39, r11,
- r15, b6, and ar.pfs) because they will be needed in case of a
- system call restart. Of course, all "preserved" registers also
- must be preserved, in accordance to the normal calling conventions.
-
- * Fsyscall-handlers MUST check argument registers for containing a
- NaT value before using them in any way that could trigger a
- NaT-consumption fault. If a system call argument is found to
- contain a NaT value, an fsyscall-handler may return immediately
- with r8=EINVAL, r10=-1.
-
- * Fsyscall-handlers MUST NOT use the "alloc" instruction or perform
- any other operation that would trigger mandatory RSE
- (register-stack engine) traffic.
-
- * Fsyscall-handlers MUST NOT write to any stacked registers because
- it is not safe to assume that user-level called a handler with the
- proper number of arguments.
-
- * Fsyscall-handlers need to be careful when accessing per-CPU variables:
- unless proper safe-guards are taken (e.g., interruptions are avoided),
- execution may be pre-empted and resumed on another CPU at any given
- time.
-
- * Fsyscall-handlers must be careful not to leak sensitive kernel'
- information back to user-level. In particular, before returning to
- user-level, care needs to be taken to clear any scratch registers
- that could contain sensitive information (note that the current
- task pointer is not considered sensitive: it's already exposed
- through ar.k6).
-
- * Fsyscall-handlers MUST NOT access user-memory without first
- validating access-permission (this can be done typically via
- probe.r.fault and/or probe.w.fault) and without guarding against
- memory access exceptions (this can be done with the EX() macros
- defined by asmmacro.h).
-
-The above restrictions may seem draconian, but remember that it's
-possible to trade off some of the restrictions by paying a slightly
-higher overhead. For example, if an fsyscall-handler could benefit
-from the shadow register bank, it could temporarily disable PSR.i and
-PSR.ic, switch to bank 0 (bsw.0) and then use the shadow registers as
-needed. In other words, following the above rules yields extremely
-fast system call execution (while fully preserving system call
-semantics), but there is also a lot of flexibility in handling more
-complicated cases.
-
-Signal handling
-===============
-
-The delivery of (asynchronous) signals must be delayed until fsys-mode
-is exited. This is accomplished with the help of the lower-privilege
-transfer trap: arch/ia64/kernel/process.c:do_notify_resume_user()
-checks whether the interrupted task was in fsys-mode and, if so, sets
-PSR.lp and returns immediately. When fsys-mode is exited via the
-"br.ret" instruction that lowers the privilege level, a trap will
-occur. The trap handler clears PSR.lp again and returns immediately.
-The kernel exit path then checks for and delivers any pending signals.
-
-PSR Handling
-============
-
-The "epc" instruction doesn't change the contents of PSR at all. This
-is in contrast to a regular interruption, which clears almost all
-bits. Because of that, some care needs to be taken to ensure things
-work as expected. The following discussion describes how each PSR bit
-is handled.
-
-======= =======================================================================
-PSR.be Cleared when entering fsys-mode. A srlz.d instruction is used
- to ensure the CPU is in little-endian mode before the first
- load/store instruction is executed. PSR.be is normally NOT
- restored upon return from an fsys-mode handler. In other
- words, user-level code must not rely on PSR.be being preserved
- across a system call.
-PSR.up Unchanged.
-PSR.ac Unchanged.
-PSR.mfl Unchanged. Note: fsys-mode handlers must not write-registers!
-PSR.mfh Unchanged. Note: fsys-mode handlers must not write-registers!
-PSR.ic Unchanged. Note: fsys-mode handlers can clear the bit, if needed.
-PSR.i Unchanged. Note: fsys-mode handlers can clear the bit, if needed.
-PSR.pk Unchanged.
-PSR.dt Unchanged.
-PSR.dfl Unchanged. Note: fsys-mode handlers must not write-registers!
-PSR.dfh Unchanged. Note: fsys-mode handlers must not write-registers!
-PSR.sp Unchanged.
-PSR.pp Unchanged.
-PSR.di Unchanged.
-PSR.si Unchanged.
-PSR.db Unchanged. The kernel prevents user-level from setting a hardware
- breakpoint that triggers at any privilege level other than
- 3 (user-mode).
-PSR.lp Unchanged.
-PSR.tb Lazy redirect. If a taken-branch trap occurs while in
- fsys-mode, the trap-handler modifies the saved machine state
- such that execution resumes in the gate page at
- syscall_via_break(), with privilege level 3. Note: the
- taken branch would occur on the branch invoking the
- fsyscall-handler, at which point, by definition, a syscall
- restart is still safe. If the system call number is invalid,
- the fsys-mode handler will return directly to user-level. This
- return will trigger a taken-branch trap, but since the trap is
- taken _after_ restoring the privilege level, the CPU has already
- left fsys-mode, so no special treatment is needed.
-PSR.rt Unchanged.
-PSR.cpl Cleared to 0.
-PSR.is Unchanged (guaranteed to be 0 on entry to the gate page).
-PSR.mc Unchanged.
-PSR.it Unchanged (guaranteed to be 1).
-PSR.id Unchanged. Note: the ia64 linux kernel never sets this bit.
-PSR.da Unchanged. Note: the ia64 linux kernel never sets this bit.
-PSR.dd Unchanged. Note: the ia64 linux kernel never sets this bit.
-PSR.ss Lazy redirect. If set, "epc" will cause a Single Step Trap to
- be taken. The trap handler then modifies the saved machine
- state such that execution resumes in the gate page at
- syscall_via_break(), with privilege level 3.
-PSR.ri Unchanged.
-PSR.ed Unchanged. Note: This bit could only have an effect if an fsys-mode
- handler performed a speculative load that gets NaTted. If so, this
- would be the normal & expected behavior, so no special treatment is
- needed.
-PSR.bn Unchanged. Note: fsys-mode handlers may clear the bit, if needed.
- Doing so requires clearing PSR.i and PSR.ic as well.
-PSR.ia Unchanged. Note: the ia64 linux kernel never sets this bit.
-======= =======================================================================
-
-Using fast system calls
-=======================
-
-To use fast system calls, userspace applications need simply call
-__kernel_syscall_via_epc(). For example
-
--- example fgettimeofday() call --
-
--- fgettimeofday.S --
-
-::
-
- #include <asm/asmmacro.h>
-
- GLOBAL_ENTRY(fgettimeofday)
- .prologue
- .save ar.pfs, r11
- mov r11 = ar.pfs
- .body
-
- mov r2 = 0xa000000000020660;; // gate address
- // found by inspection of System.map for the
- // __kernel_syscall_via_epc() function. See
- // below for how to do this for real.
-
- mov b7 = r2
- mov r15 = 1087 // gettimeofday syscall
- ;;
- br.call.sptk.many b6 = b7
- ;;
-
- .restore sp
-
- mov ar.pfs = r11
- br.ret.sptk.many rp;; // return to caller
- END(fgettimeofday)
-
--- end fgettimeofday.S --
-
-In reality, getting the gate address is accomplished by two extra
-values passed via the ELF auxiliary vector (include/asm-ia64/elf.h)
-
- * AT_SYSINFO : is the address of __kernel_syscall_via_epc()
- * AT_SYSINFO_EHDR : is the address of the kernel gate ELF DSO
-
-The ELF DSO is a pre-linked library that is mapped in by the kernel at
-the gate page. It is a proper ELF shared object so, with a dynamic
-loader that recognises the library, you should be able to make calls to
-the exported functions within it as with any other shared library.
-AT_SYSINFO points into the kernel DSO at the
-__kernel_syscall_via_epc() function for historical reasons (it was
-used before the kernel DSO) and as a convenience.
diff --git a/Documentation/arch/ia64/ia64.rst b/Documentation/arch/ia64/ia64.rst
deleted file mode 100644
index b725019a9492..000000000000
--- a/Documentation/arch/ia64/ia64.rst
+++ /dev/null
@@ -1,49 +0,0 @@
-===========================================
-Linux kernel release for the IA-64 Platform
-===========================================
-
- These are the release notes for Linux since version 2.4 for IA-64
- platform. This document provides information specific to IA-64
- ONLY, to get additional information about the Linux kernel also
- read the original Linux README provided with the kernel.
-
-Installing the Kernel
-=====================
-
- - IA-64 kernel installation is the same as the other platforms, see
- original README for details.
-
-
-Software Requirements
-=====================
-
- Compiling and running this kernel requires an IA-64 compliant GCC
- compiler. And various software packages also compiled with an
- IA-64 compliant GCC compiler.
-
-
-Configuring the Kernel
-======================
-
- Configuration is the same, see original README for details.
-
-
-Compiling the Kernel:
-
- - Compiling this kernel doesn't differ from other platform so read
- the original README for details BUT make sure you have an IA-64
- compliant GCC compiler.
-
-IA-64 Specifics
-===============
-
- - General issues:
-
- * Hardly any performance tuning has been done. Obvious targets
- include the library routines (IP checksum, etc.). Less
- obvious targets include making sure we don't flush the TLB
- needlessly, etc.
-
- * SMP locks cleanup/optimization
-
- * IA32 support. Currently experimental. It mostly works.
diff --git a/Documentation/arch/ia64/index.rst b/Documentation/arch/ia64/index.rst
deleted file mode 100644
index 761f2154dfa2..000000000000
--- a/Documentation/arch/ia64/index.rst
+++ /dev/null
@@ -1,19 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==================
-IA-64 Architecture
-==================
-
-.. toctree::
- :maxdepth: 1
-
- ia64
- aliasing
- efirtc
- err_inject
- fsys
- irq-redir
- mca
- serial
-
- features
diff --git a/Documentation/arch/ia64/irq-redir.rst b/Documentation/arch/ia64/irq-redir.rst
deleted file mode 100644
index 6bbbbe4f73ef..000000000000
--- a/Documentation/arch/ia64/irq-redir.rst
+++ /dev/null
@@ -1,80 +0,0 @@
-==============================
-IRQ affinity on IA64 platforms
-==============================
-
-07.01.2002, Erich Focht <efocht@ess.nec.de>
-
-
-By writing to /proc/irq/IRQ#/smp_affinity the interrupt routing can be
-controlled. The behavior on IA64 platforms is slightly different from
-that described in Documentation/core-api/irq/irq-affinity.rst for i386 systems.
-
-Because of the usage of SAPIC mode and physical destination mode the
-IRQ target is one particular CPU and cannot be a mask of several
-CPUs. Only the first non-zero bit is taken into account.
-
-
-Usage examples
-==============
-
-The target CPU has to be specified as a hexadecimal CPU mask. The
-first non-zero bit is the selected CPU. This format has been kept for
-compatibility reasons with i386.
-
-Set the delivery mode of interrupt 41 to fixed and route the
-interrupts to CPU #3 (logical CPU number) (2^3=0x08)::
-
- echo "8" >/proc/irq/41/smp_affinity
-
-Set the default route for IRQ number 41 to CPU 6 in lowest priority
-delivery mode (redirectable)::
-
- echo "r 40" >/proc/irq/41/smp_affinity
-
-The output of the command::
-
- cat /proc/irq/IRQ#/smp_affinity
-
-gives the target CPU mask for the specified interrupt vector. If the CPU
-mask is preceded by the character "r", the interrupt is redirectable
-(i.e. lowest priority mode routing is used), otherwise its route is
-fixed.
-
-
-
-Initialization and default behavior
-===================================
-
-If the platform features IRQ redirection (info provided by SAL) all
-IO-SAPIC interrupts are initialized with CPU#0 as their default target
-and the routing is the so called "lowest priority mode" (actually
-fixed SAPIC mode with hint). The XTP chipset registers are used as hints
-for the IRQ routing. Currently in Linux XTP registers can have three
-values:
-
- - minimal for an idle task,
- - normal if any other task runs,
- - maximal if the CPU is going to be switched off.
-
-The IRQ is routed to the CPU with lowest XTP register value, the
-search begins at the default CPU. Therefore most of the interrupts
-will be handled by CPU #0.
-
-If the platform doesn't feature interrupt redirection IOSAPIC fixed
-routing is used. The target CPUs are distributed in a round robin
-manner. IRQs will be routed only to the selected target CPUs. Check
-with::
-
- cat /proc/interrupts
-
-
-
-Comments
-========
-
-On large (multi-node) systems it is recommended to route the IRQs to
-the node to which the corresponding device is connected.
-For systems like the NEC AzusA we get IRQ node-affinity for free. This
-is because usually the chipsets on each node redirect the interrupts
-only to their own CPUs (as they cannot see the XTP registers on the
-other nodes).
diff --git a/Documentation/arch/ia64/mca.rst b/Documentation/arch/ia64/mca.rst
deleted file mode 100644
index 08270bba44a4..000000000000
--- a/Documentation/arch/ia64/mca.rst
+++ /dev/null
@@ -1,198 +0,0 @@
-=============================================================
-An ad-hoc collection of notes on IA64 MCA and INIT processing
-=============================================================
-
-Feel free to update it with notes about any area that is not clear.
-
----
-
-MCA/INIT are completely asynchronous. They can occur at any time, when
-the OS is in any state. Including when one of the cpus is already
-holding a spinlock. Trying to get any lock from MCA/INIT state is
-asking for deadlock. Also the state of structures that are protected
-by locks is indeterminate, including linked lists.
-
----
-
-The complicated ia64 MCA process. All of this is mandated by Intel's
-specification for ia64 SAL, error recovery and unwind, it is not as
-if we have a choice here.
-
-* MCA occurs on one cpu, usually due to a double bit memory error.
- This is the monarch cpu.
-
-* SAL sends an MCA rendezvous interrupt (which is a normal interrupt)
- to all the other cpus, the slaves.
-
-* Slave cpus that receive the MCA interrupt call down into SAL, they
- end up spinning disabled while the MCA is being serviced.
-
-* If any slave cpu was already spinning disabled when the MCA occurred
- then it cannot service the MCA interrupt. SAL waits ~20 seconds then
- sends an unmaskable INIT event to the slave cpus that have not
- already rendezvoused.
-
-* Because MCA/INIT can be delivered at any time, including when the cpu
- is down in PAL in physical mode, the registers at the time of the
- event are _completely_ undefined. In particular the MCA/INIT
- handlers cannot rely on the thread pointer, PAL physical mode can
- (and does) modify TP. It is allowed to do that as long as it resets
- TP on return. However MCA/INIT events expose us to these PAL
- internal TP changes. Hence curr_task().
-
-* If an MCA/INIT event occurs while the kernel was running (not user
- space) and the kernel has called PAL then the MCA/INIT handler cannot
- assume that the kernel stack is in a fit state to be used. Mainly
- because PAL may or may not maintain the stack pointer internally.
- Because the MCA/INIT handlers cannot trust the kernel stack, they
- have to use their own, per-cpu stacks. The MCA/INIT stacks are
- preformatted with just enough task state to let the relevant handlers
- do their job.
-
-* Unlike most other architectures, the ia64 struct task is embedded in
- the kernel stack[1]. So switching to a new kernel stack means that
- we switch to a new task as well. Because various bits of the kernel
- assume that current points into the struct task, switching to a new
- stack also means a new value for current.
-
-* Once all slaves have rendezvoused and are spinning disabled, the
- monarch is entered. The monarch now tries to diagnose the problem
- and decide if it can recover or not.
-
-* Part of the monarch's job is to look at the state of all the other
- tasks. The only way to do that on ia64 is to call the unwinder,
- as mandated by Intel.
-
-* The starting point for the unwind depends on whether a task is
- running or not. That is, whether it is on a cpu or is blocked. The
- monarch has to determine whether or not a task is on a cpu before it
- knows how to start unwinding it. The tasks that received an MCA or
- INIT event are no longer running, they have been converted to blocked
- tasks. But (and its a big but), the cpus that received the MCA
- rendezvous interrupt are still running on their normal kernel stacks!
-
-* To distinguish between these two cases, the monarch must know which
- tasks are on a cpu and which are not. Hence each slave cpu that
- switches to an MCA/INIT stack, registers its new stack using
- set_curr_task(), so the monarch can tell that the _original_ task is
- no longer running on that cpu. That gives us a decent chance of
- getting a valid backtrace of the _original_ task.
-
-* MCA/INIT can be nested, to a depth of 2 on any cpu. In the case of a
- nested error, we want diagnostics on the MCA/INIT handler that
- failed, not on the task that was originally running. Again this
- requires set_curr_task() so the MCA/INIT handlers can register their
- own stack as running on that cpu. Then a recursive error gets a
- trace of the failing handler's "task".
-
-[1]
- My (Keith Owens) original design called for ia64 to separate its
- struct task and the kernel stacks. Then the MCA/INIT data would be
- chained stacks like i386 interrupt stacks. But that required
- radical surgery on the rest of ia64, plus extra hard wired TLB
- entries with its associated performance degradation. David
- Mosberger vetoed that approach. Which meant that separate kernel
- stacks meant separate "tasks" for the MCA/INIT handlers.
-
----
-
-INIT is less complicated than MCA. Pressing the nmi button or using
-the equivalent command on the management console sends INIT to all
-cpus. SAL picks one of the cpus as the monarch and the rest are
-slaves. All the OS INIT handlers are entered at approximately the same
-time. The OS monarch prints the state of all tasks and returns, after
-which the slaves return and the system resumes.
-
-At least that is what is supposed to happen. Alas there are broken
-versions of SAL out there. Some drive all the cpus as monarchs. Some
-drive them all as slaves. Some drive one cpu as monarch, wait for that
-cpu to return from the OS then drive the rest as slaves. Some versions
-of SAL cannot even cope with returning from the OS, they spin inside
-SAL on resume. The OS INIT code has workarounds for some of these
-broken SAL symptoms, but some simply cannot be fixed from the OS side.
-
----
-
-The scheduler hooks used by ia64 (curr_task, set_curr_task) are layer
-violations. Unfortunately MCA/INIT start off as massive layer
-violations (can occur at _any_ time) and they build from there.
-
-At least ia64 makes an attempt at recovering from hardware errors, but
-it is a difficult problem because of the asynchronous nature of these
-errors. When processing an unmaskable interrupt we sometimes need
-special code to cope with our inability to take any locks.
-
----
-
-How is ia64 MCA/INIT different from x86 NMI?
-
-* x86 NMI typically gets delivered to one cpu. MCA/INIT gets sent to
- all cpus.
-
-* x86 NMI cannot be nested. MCA/INIT can be nested, to a depth of 2
- per cpu.
-
-* x86 has a separate struct task which points to one of multiple kernel
- stacks. ia64 has the struct task embedded in the single kernel
- stack, so switching stack means switching task.
-
-* x86 does not call the BIOS so the NMI handler does not have to worry
- about any registers having changed. MCA/INIT can occur while the cpu
- is in PAL in physical mode, with undefined registers and an undefined
- kernel stack.
-
-* i386 backtrace is not very sensitive to whether a process is running
- or not. ia64 unwind is very, very sensitive to whether a process is
- running or not.
-
----
-
-What happens when MCA/INIT is delivered what a cpu is running user
-space code?
-
-The user mode registers are stored in the RSE area of the MCA/INIT on
-entry to the OS and are restored from there on return to SAL, so user
-mode registers are preserved across a recoverable MCA/INIT. Since the
-OS has no idea what unwind data is available for the user space stack,
-MCA/INIT never tries to backtrace user space. Which means that the OS
-does not bother making the user space process look like a blocked task,
-i.e. the OS does not copy pt_regs and switch_stack to the user space
-stack. Also the OS has no idea how big the user space RSE and memory
-stacks are, which makes it too risky to copy the saved state to a user
-mode stack.
-
----
-
-How do we get a backtrace on the tasks that were running when MCA/INIT
-was delivered?
-
-mca.c:::ia64_mca_modify_original_stack(). That identifies and
-verifies the original kernel stack, copies the dirty registers from
-the MCA/INIT stack's RSE to the original stack's RSE, copies the
-skeleton struct pt_regs and switch_stack to the original stack, fills
-in the skeleton structures from the PAL minstate area and updates the
-original stack's thread.ksp. That makes the original stack look
-exactly like any other blocked task, i.e. it now appears to be
-sleeping. To get a backtrace, just start with thread.ksp for the
-original task and unwind like any other sleeping task.
-
----
-
-How do we identify the tasks that were running when MCA/INIT was
-delivered?
-
-If the previous task has been verified and converted to a blocked
-state, then sos->prev_task on the MCA/INIT stack is updated to point to
-the previous task. You can look at that field in dumps or debuggers.
-To help distinguish between the handler and the original tasks,
-handlers have _TIF_MCA_INIT set in thread_info.flags.
-
-The sos data is always in the MCA/INIT handler stack, at offset
-MCA_SOS_OFFSET. You can get that value from mca_asm.h or calculate it
-as KERNEL_STACK_SIZE - sizeof(struct pt_regs) - sizeof(struct
-ia64_sal_os_state), with 16 byte alignment for all structures.
-
-Also the comm field of the MCA/INIT task is modified to include the pid
-of the original task, for humans to use. For example, a comm field of
-'MCA 12159' means that pid 12159 was running when the MCA was
-delivered.
diff --git a/Documentation/arch/ia64/serial.rst b/Documentation/arch/ia64/serial.rst
deleted file mode 100644
index 1de70c305a79..000000000000
--- a/Documentation/arch/ia64/serial.rst
+++ /dev/null
@@ -1,165 +0,0 @@
-==============
-Serial Devices
-==============
-
-Serial Device Naming
-====================
-
- As of 2.6.10, serial devices on ia64 are named based on the
- order of ACPI and PCI enumeration. The first device in the
- ACPI namespace (if any) becomes /dev/ttyS0, the second becomes
- /dev/ttyS1, etc., and PCI devices are named sequentially
- starting after the ACPI devices.
-
- Prior to 2.6.10, there were confusing exceptions to this:
-
- - Firmware on some machines (mostly from HP) provides an HCDP
- table[1] that tells the kernel about devices that can be used
- as a serial console. If the user specified "console=ttyS0"
- or the EFI ConOut path contained only UART devices, the
- kernel registered the device described by the HCDP as
- /dev/ttyS0.
-
- - If there was no HCDP, we assumed there were UARTs at the
- legacy COM port addresses (I/O ports 0x3f8 and 0x2f8), so
- the kernel registered those as /dev/ttyS0 and /dev/ttyS1.
-
- Any additional ACPI or PCI devices were registered sequentially
- after /dev/ttyS0 as they were discovered.
-
- With an HCDP, device names changed depending on EFI configuration
- and "console=" arguments. Without an HCDP, device names didn't
- change, but we registered devices that might not really exist.
-
- For example, an HP rx1600 with a single built-in serial port
- (described in the ACPI namespace) plus an MP[2] (a PCI device) has
- these ports:
-
- ========== ========== ============ ============ =======
- Type MMIO pre-2.6.10 pre-2.6.10 2.6.10+
- address
- (EFI console (EFI console
- on builtin) on MP port)
- ========== ========== ============ ============ =======
- builtin 0xff5e0000 ttyS0 ttyS1 ttyS0
- MP UPS 0xf8031000 ttyS1 ttyS2 ttyS1
- MP Console 0xf8030000 ttyS2 ttyS0 ttyS2
- MP 2 0xf8030010 ttyS3 ttyS3 ttyS3
- MP 3 0xf8030038 ttyS4 ttyS4 ttyS4
- ========== ========== ============ ============ =======
-
-Console Selection
-=================
-
- EFI knows what your console devices are, but it doesn't tell the
- kernel quite enough to actually locate them. The DIG64 HCDP
- table[1] does tell the kernel where potential serial console
- devices are, but not all firmware supplies it. Also, EFI supports
- multiple simultaneous consoles and doesn't tell the kernel which
- should be the "primary" one.
-
- So how do you tell Linux which console device to use?
-
- - If your firmware supplies the HCDP, it is simplest to
- configure EFI with a single device (either a UART or a VGA
- card) as the console. Then you don't need to tell Linux
- anything; the kernel will automatically use the EFI console.
-
- (This works only in 2.6.6 or later; prior to that you had
- to specify "console=ttyS0" to get a serial console.)
-
- - Without an HCDP, Linux defaults to a VGA console unless you
- specify a "console=" argument.
-
- NOTE: Don't assume that a serial console device will be /dev/ttyS0.
- It might be ttyS1, ttyS2, etc. Make sure you have the appropriate
- entries in /etc/inittab (for getty) and /etc/securetty (to allow
- root login).
-
-Early Serial Console
-====================
-
- The kernel can't start using a serial console until it knows where
- the device lives. Normally this happens when the driver enumerates
- all the serial devices, which can happen a minute or more after the
- kernel starts booting.
-
- 2.6.10 and later kernels have an "early uart" driver that works
- very early in the boot process. The kernel will automatically use
- this if the user supplies an argument like "console=uart,io,0x3f8",
- or if the EFI console path contains only a UART device and the
- firmware supplies an HCDP.
-
-Troubleshooting Serial Console Problems
-=======================================
-
- No kernel output after elilo prints "Uncompressing Linux... done":
-
- - You specified "console=ttyS0" but Linux changed the device
- to which ttyS0 refers. Configure exactly one EFI console
- device[3] and remove the "console=" option.
-
- - The EFI console path contains both a VGA device and a UART.
- EFI and elilo use both, but Linux defaults to VGA. Remove
- the VGA device from the EFI console path[3].
-
- - Multiple UARTs selected as EFI console devices. EFI and
- elilo use all selected devices, but Linux uses only one.
- Make sure only one UART is selected in the EFI console
- path[3].
-
- - You're connected to an HP MP port[2] but have a non-MP UART
- selected as EFI console device. EFI uses the MP as a
- console device even when it isn't explicitly selected.
- Either move the console cable to the non-MP UART, or change
- the EFI console path[3] to the MP UART.
-
- Long pause (60+ seconds) between "Uncompressing Linux... done" and
- start of kernel output:
-
- - No early console because you used "console=ttyS<n>". Remove
- the "console=" option if your firmware supplies an HCDP.
-
- - If you don't have an HCDP, the kernel doesn't know where
- your console lives until the driver discovers serial
- devices. Use "console=uart,io,0x3f8" (or appropriate
- address for your machine).
-
- Kernel and init script output works fine, but no "login:" prompt:
-
- - Add getty entry to /etc/inittab for console tty. Look for
- the "Adding console on ttyS<n>" message that tells you which
- device is the console.
-
- "login:" prompt, but can't login as root:
-
- - Add entry to /etc/securetty for console tty.
-
- No ACPI serial devices found in 2.6.17 or later:
-
- - Turn on CONFIG_PNP and CONFIG_PNPACPI. Prior to 2.6.17, ACPI
- serial devices were discovered by 8250_acpi. In 2.6.17,
- 8250_acpi was replaced by the combination of 8250_pnp and
- CONFIG_PNPACPI.
-
-
-
-[1]
- http://www.dig64.org/specifications/agreement
- The table was originally defined as the "HCDP" for "Headless
- Console/Debug Port." The current version is the "PCDP" for
- "Primary Console and Debug Port Devices."
-
-[2]
- The HP MP (management processor) is a PCI device that provides
- several UARTs. One of the UARTs is often used as a console; the
- EFI Boot Manager identifies it as "Acpi(HWP0002,700)/Pci(...)/Uart".
- The external connection is usually a 25-pin connector, and a
- special dongle converts that to three 9-pin connectors, one of
- which is labelled "Console."
-
-[3]
- EFI console devices are configured using the EFI Boot Manager
- "Boot option maintenance" menu. You may have to interrupt the
- boot sequence to use this menu, and you will have to reset the
- box after changing console configuration.
diff --git a/Documentation/arch/index.rst b/Documentation/arch/index.rst
index 84b80255b851..3f9962e45c09 100644
--- a/Documentation/arch/index.rst
+++ b/Documentation/arch/index.rst
@@ -12,15 +12,14 @@ implementation.
arc/index
arm/index
arm64/index
- ia64/index
loongarch/index
m68k/index
mips/index
nios2/index
openrisc/index
parisc/index
- ../powerpc/index
- ../riscv/index
+ powerpc/index
+ riscv/index
s390/index
sh/index
sparc/index
diff --git a/Documentation/arch/loongarch/introduction.rst b/Documentation/arch/loongarch/introduction.rst
index 8c568cfc2107..5e6db78abeaf 100644
--- a/Documentation/arch/loongarch/introduction.rst
+++ b/Documentation/arch/loongarch/introduction.rst
@@ -375,9 +375,9 @@ Developer web site of Loongson and LoongArch (Software and Documentation):
Documentation of LoongArch ISA:
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-CN.pdf (in Chinese)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.10-CN.pdf (in Chinese)
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-EN.pdf (in English)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.10-EN.pdf (in English)
Documentation of LoongArch ELF psABI:
diff --git a/Documentation/powerpc/associativity.rst b/Documentation/arch/powerpc/associativity.rst
index 4d01c7368561..4d01c7368561 100644
--- a/Documentation/powerpc/associativity.rst
+++ b/Documentation/arch/powerpc/associativity.rst
diff --git a/Documentation/powerpc/booting.rst b/Documentation/arch/powerpc/booting.rst
index 11aa440f98cc..11aa440f98cc 100644
--- a/Documentation/powerpc/booting.rst
+++ b/Documentation/arch/powerpc/booting.rst
diff --git a/Documentation/powerpc/bootwrapper.rst b/Documentation/arch/powerpc/bootwrapper.rst
index cdfa2bc8425f..cdfa2bc8425f 100644
--- a/Documentation/powerpc/bootwrapper.rst
+++ b/Documentation/arch/powerpc/bootwrapper.rst
diff --git a/Documentation/powerpc/cpu_families.rst b/Documentation/arch/powerpc/cpu_families.rst
index eb7e60649b43..eb7e60649b43 100644
--- a/Documentation/powerpc/cpu_families.rst
+++ b/Documentation/arch/powerpc/cpu_families.rst
diff --git a/Documentation/powerpc/cpu_features.rst b/Documentation/arch/powerpc/cpu_features.rst
index b7bcdd2f41bb..b7bcdd2f41bb 100644
--- a/Documentation/powerpc/cpu_features.rst
+++ b/Documentation/arch/powerpc/cpu_features.rst
diff --git a/Documentation/powerpc/cxl.rst b/Documentation/arch/powerpc/cxl.rst
index d2d77057610e..d2d77057610e 100644
--- a/Documentation/powerpc/cxl.rst
+++ b/Documentation/arch/powerpc/cxl.rst
diff --git a/Documentation/powerpc/cxlflash.rst b/Documentation/arch/powerpc/cxlflash.rst
index cea67931b3b9..e8f488acfa41 100644
--- a/Documentation/powerpc/cxlflash.rst
+++ b/Documentation/arch/powerpc/cxlflash.rst
@@ -32,7 +32,7 @@ Introduction
responsible for the initialization of the adapter, setting up the
special path for user space access, and performing error recovery. It
communicates directly the Flash Accelerator Functional Unit (AFU)
- as described in Documentation/powerpc/cxl.rst.
+ as described in Documentation/arch/powerpc/cxl.rst.
The cxlflash driver supports two, mutually exclusive, modes of
operation at the device (LUN) level:
diff --git a/Documentation/powerpc/dawr-power9.rst b/Documentation/arch/powerpc/dawr-power9.rst
index 310f2e0cea81..310f2e0cea81 100644
--- a/Documentation/powerpc/dawr-power9.rst
+++ b/Documentation/arch/powerpc/dawr-power9.rst
diff --git a/Documentation/powerpc/dexcr.rst b/Documentation/arch/powerpc/dexcr.rst
index 615a631f51fa..615a631f51fa 100644
--- a/Documentation/powerpc/dexcr.rst
+++ b/Documentation/arch/powerpc/dexcr.rst
diff --git a/Documentation/powerpc/dscr.rst b/Documentation/arch/powerpc/dscr.rst
index f735ec5375d5..f735ec5375d5 100644
--- a/Documentation/powerpc/dscr.rst
+++ b/Documentation/arch/powerpc/dscr.rst
diff --git a/Documentation/powerpc/eeh-pci-error-recovery.rst b/Documentation/arch/powerpc/eeh-pci-error-recovery.rst
index d6643a91bdf8..d6643a91bdf8 100644
--- a/Documentation/powerpc/eeh-pci-error-recovery.rst
+++ b/Documentation/arch/powerpc/eeh-pci-error-recovery.rst
diff --git a/Documentation/powerpc/elf_hwcaps.rst b/Documentation/arch/powerpc/elf_hwcaps.rst
index 3366e5b18e67..4c896cf077c2 100644
--- a/Documentation/powerpc/elf_hwcaps.rst
+++ b/Documentation/arch/powerpc/elf_hwcaps.rst
@@ -202,7 +202,7 @@ PPC_FEATURE2_VEC_CRYPTO
PPC_FEATURE2_HTM_NOSC
System calls fail if called in a transactional state, see
- Documentation/powerpc/syscall64-abi.rst
+ Documentation/arch/powerpc/syscall64-abi.rst
PPC_FEATURE2_ARCH_3_00
The processor supports the v3.0B / v3.0C userlevel architecture. Processors
@@ -217,11 +217,11 @@ PPC_FEATURE2_DARN
PPC_FEATURE2_SCV
The scv 0 instruction may be used for system calls, see
- Documentation/powerpc/syscall64-abi.rst.
+ Documentation/arch/powerpc/syscall64-abi.rst.
PPC_FEATURE2_HTM_NO_SUSPEND
A limited Transactional Memory facility that does not support suspend is
- available, see Documentation/powerpc/transactional_memory.rst.
+ available, see Documentation/arch/powerpc/transactional_memory.rst.
PPC_FEATURE2_ARCH_3_1
The processor supports the v3.1 userlevel architecture. Processors
diff --git a/Documentation/powerpc/elfnote.rst b/Documentation/arch/powerpc/elfnote.rst
index 3ec8d61e9a33..3ec8d61e9a33 100644
--- a/Documentation/powerpc/elfnote.rst
+++ b/Documentation/arch/powerpc/elfnote.rst
diff --git a/Documentation/powerpc/features.rst b/Documentation/arch/powerpc/features.rst
index aeae73df86b0..aeae73df86b0 100644
--- a/Documentation/powerpc/features.rst
+++ b/Documentation/arch/powerpc/features.rst
diff --git a/Documentation/powerpc/firmware-assisted-dump.rst b/Documentation/arch/powerpc/firmware-assisted-dump.rst
index e363fc48529a..e363fc48529a 100644
--- a/Documentation/powerpc/firmware-assisted-dump.rst
+++ b/Documentation/arch/powerpc/firmware-assisted-dump.rst
diff --git a/Documentation/powerpc/hvcs.rst b/Documentation/arch/powerpc/hvcs.rst
index 6808acde672f..6808acde672f 100644
--- a/Documentation/powerpc/hvcs.rst
+++ b/Documentation/arch/powerpc/hvcs.rst
diff --git a/Documentation/powerpc/imc.rst b/Documentation/arch/powerpc/imc.rst
index 633bcee7dc85..633bcee7dc85 100644
--- a/Documentation/powerpc/imc.rst
+++ b/Documentation/arch/powerpc/imc.rst
diff --git a/Documentation/powerpc/index.rst b/Documentation/arch/powerpc/index.rst
index a50834798454..9749f6dc258f 100644
--- a/Documentation/powerpc/index.rst
+++ b/Documentation/arch/powerpc/index.rst
@@ -26,6 +26,7 @@ powerpc
isa-versions
kaslr-booke32
mpc52xx
+ kvm-nested
papr_hcalls
pci_iov_resource_on_powernv
pmu-ebb
diff --git a/Documentation/powerpc/isa-versions.rst b/Documentation/arch/powerpc/isa-versions.rst
index a8d6b6028b3e..a8d6b6028b3e 100644
--- a/Documentation/powerpc/isa-versions.rst
+++ b/Documentation/arch/powerpc/isa-versions.rst
diff --git a/Documentation/powerpc/kasan.txt b/Documentation/arch/powerpc/kasan.txt
index a4f647e4fffa..a4f647e4fffa 100644
--- a/Documentation/powerpc/kasan.txt
+++ b/Documentation/arch/powerpc/kasan.txt
diff --git a/Documentation/powerpc/kaslr-booke32.rst b/Documentation/arch/powerpc/kaslr-booke32.rst
index 5681c1d1b65b..5681c1d1b65b 100644
--- a/Documentation/powerpc/kaslr-booke32.rst
+++ b/Documentation/arch/powerpc/kaslr-booke32.rst
diff --git a/Documentation/arch/powerpc/kvm-nested.rst b/Documentation/arch/powerpc/kvm-nested.rst
new file mode 100644
index 000000000000..630602a8aa00
--- /dev/null
+++ b/Documentation/arch/powerpc/kvm-nested.rst
@@ -0,0 +1,634 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+====================================
+Nested KVM on POWER
+====================================
+
+Introduction
+============
+
+This document explains how a guest operating system can act as a
+hypervisor and run nested guests through the use of hypercalls, if the
+hypervisor has implemented them. The terms L0, L1, and L2 are used to
+refer to different software entities. L0 is the hypervisor mode entity
+that would normally be called the "host" or "hypervisor". L1 is a
+guest virtual machine that is directly run under L0 and is initiated
+and controlled by L0. L2 is a guest virtual machine that is initiated
+and controlled by L1 acting as a hypervisor.
+
+Existing API
+============
+
+Linux/KVM has had support for Nesting as an L0 or L1 since 2018
+
+The L0 code was added::
+
+ commit 8e3f5fc1045dc49fd175b978c5457f5f51e7a2ce
+ Author: Paul Mackerras <paulus@ozlabs.org>
+ Date: Mon Oct 8 16:31:03 2018 +1100
+ KVM: PPC: Book3S HV: Framework and hcall stubs for nested virtualization
+
+The L1 code was added::
+
+ commit 360cae313702cdd0b90f82c261a8302fecef030a
+ Author: Paul Mackerras <paulus@ozlabs.org>
+ Date: Mon Oct 8 16:31:04 2018 +1100
+ KVM: PPC: Book3S HV: Nested guest entry via hypercall
+
+This API works primarily using a single hcall h_enter_nested(). This
+call made by the L1 to tell the L0 to start an L2 vCPU with the given
+state. The L0 then starts this L2 and runs until an L2 exit condition
+is reached. Once the L2 exits, the state of the L2 is given back to
+the L1 by the L0. The full L2 vCPU state is always transferred from
+and to L1 when the L2 is run. The L0 doesn't keep any state on the L2
+vCPU (except in the short sequence in the L0 on L1 -> L2 entry and L2
+-> L1 exit).
+
+The only state kept by the L0 is the partition table. The L1 registers
+it's partition table using the h_set_partition_table() hcall. All
+other state held by the L0 about the L2s is cached state (such as
+shadow page tables).
+
+The L1 may run any L2 or vCPU without first informing the L0. It
+simply starts the vCPU using h_enter_nested(). The creation of L2s and
+vCPUs is done implicitly whenever h_enter_nested() is called.
+
+In this document, we call this existing API the v1 API.
+
+New PAPR API
+===============
+
+The new PAPR API changes from the v1 API such that the creating L2 and
+associated vCPUs is explicit. In this document, we call this the v2
+API.
+
+h_enter_nested() is replaced with H_GUEST_VCPU_RUN(). Before this can
+be called the L1 must explicitly create the L2 using h_guest_create()
+and any associated vCPUs() created with h_guest_create_vCPU(). Getting
+and setting vCPU state can also be performed using h_guest_{g|s}et
+hcall.
+
+The basic execution flow is for an L1 to create an L2, run it, and
+delete it is:
+
+- L1 and L0 negotiate capabilities with H_GUEST_{G,S}ET_CAPABILITIES()
+ (normally at L1 boot time).
+
+- L1 requests the L0 create an L2 with H_GUEST_CREATE() and receives a token
+
+- L1 requests the L0 create an L2 vCPU with H_GUEST_CREATE_VCPU()
+
+- L1 and L0 communicate the vCPU state using the H_GUEST_{G,S}ET() hcall
+
+- L1 requests the L0 runs the vCPU running H_GUEST_VCPU_RUN() hcall
+
+- L1 deletes L2 with H_GUEST_DELETE()
+
+More details of the individual hcalls follows:
+
+HCALL Details
+=============
+
+This documentation is provided to give an overall understating of the
+API. It doesn't aim to provide all the details required to implement
+an L1 or L0. Latest version of PAPR can be referred to for more details.
+
+All these HCALLs are made by the L1 to the L0.
+
+H_GUEST_GET_CAPABILITIES()
+--------------------------
+
+This is called to get the capabilities of the L0 nested
+hypervisor. This includes capabilities such the CPU versions (eg
+POWER9, POWER10) that are supported as L2s::
+
+ H_GUEST_GET_CAPABILITIES(uint64 flags)
+
+ Parameters:
+ Input:
+ flags: Reserved
+ Output:
+ R3: Return code
+ R4: Hypervisor Supported Capabilities bitmap 1
+
+H_GUEST_SET_CAPABILITIES()
+--------------------------
+
+This is called to inform the L0 of the capabilities of the L1
+hypervisor. The set of flags passed here are the same as
+H_GUEST_GET_CAPABILITIES()
+
+Typically, GET will be called first and then SET will be called with a
+subset of the flags returned from GET. This process allows the L0 and
+L1 to negotiate an agreed set of capabilities::
+
+ H_GUEST_SET_CAPABILITIES(uint64 flags,
+ uint64 capabilitiesBitmap1)
+ Parameters:
+ Input:
+ flags: Reserved
+ capabilitiesBitmap1: Only capabilities advertised through
+ H_GUEST_GET_CAPABILITIES
+ Output:
+ R3: Return code
+ R4: If R3 = H_P2: The number of invalid bitmaps
+ R5: If R3 = H_P2: The index of first invalid bitmap
+
+H_GUEST_CREATE()
+----------------
+
+This is called to create an L2. A unique ID of the L2 created
+(similar to an LPID) is returned, which can be used on subsequent HCALLs to
+identify the L2::
+
+ H_GUEST_CREATE(uint64 flags,
+ uint64 continueToken);
+ Parameters:
+ Input:
+ flags: Reserved
+ continueToken: Initial call set to -1. Subsequent calls,
+ after H_Busy or H_LongBusyOrder has been
+ returned, value that was returned in R4.
+ Output:
+ R3: Return code. Notable:
+ H_Not_Enough_Resources: Unable to create Guest VCPU due to not
+ enough Hypervisor memory. See H_GUEST_CREATE_GET_STATE(flags =
+ takeOwnershipOfVcpuState)
+ R4: If R3 = H_Busy or_H_LongBusyOrder -> continueToken
+
+H_GUEST_CREATE_VCPU()
+---------------------
+
+This is called to create a vCPU associated with an L2. The L2 id
+(returned from H_GUEST_CREATE()) should be passed it. Also passed in
+is a unique (for this L2) vCPUid. This vCPUid is allocated by the
+L1::
+
+ H_GUEST_CREATE_VCPU(uint64 flags,
+ uint64 guestId,
+ uint64 vcpuId);
+ Parameters:
+ Input:
+ flags: Reserved
+ guestId: ID obtained from H_GUEST_CREATE
+ vcpuId: ID of the vCPU to be created. This must be within the
+ range of 0 to 2047
+ Output:
+ R3: Return code. Notable:
+ H_Not_Enough_Resources: Unable to create Guest VCPU due to not
+ enough Hypervisor memory. See H_GUEST_CREATE_GET_STATE(flags =
+ takeOwnershipOfVcpuState)
+
+H_GUEST_GET_STATE()
+-------------------
+
+This is called to get state associated with an L2 (Guest-wide or vCPU specific).
+This info is passed via the Guest State Buffer (GSB), a standard format as
+explained later in this doc, necessary details below:
+
+This can get either L2 wide or vcpu specific information. Examples of
+L2 wide is the timebase offset or process scoped page table
+info. Examples of vCPU specific are GPRs or VSRs. A bit in the flags
+parameter specifies if this call is L2 wide or vCPU specific and the
+IDs in the GSB must match this.
+
+The L1 provides a pointer to the GSB as a parameter to this call. Also
+provided is the L2 and vCPU IDs associated with the state to set.
+
+The L1 writes only the IDs and sizes in the GSB. L0 writes the
+associated values for each ID in the GSB::
+
+ H_GUEST_GET_STATE(uint64 flags,
+ uint64 guestId,
+ uint64 vcpuId,
+ uint64 dataBuffer,
+ uint64 dataBufferSizeInBytes);
+ Parameters:
+ Input:
+ flags:
+ Bit 0: getGuestWideState: Request state of the Guest instead
+ of an individual VCPU.
+ Bit 1: takeOwnershipOfVcpuState Indicate the L1 is taking
+ over ownership of the VCPU state and that the L0 can free
+ the storage holding the state. The VCPU state will need to
+ be returned to the Hypervisor via H_GUEST_SET_STATE prior
+ to H_GUEST_RUN_VCPU being called for this VCPU. The data
+ returned in the dataBuffer is in a Hypervisor internal
+ format.
+ Bits 2-63: Reserved
+ guestId: ID obtained from H_GUEST_CREATE
+ vcpuId: ID of the vCPU pass to H_GUEST_CREATE_VCPU
+ dataBuffer: A L1 real address of the GSB.
+ If takeOwnershipOfVcpuState, size must be at least the size
+ returned by ID=0x0001
+ dataBufferSizeInBytes: Size of dataBuffer
+ Output:
+ R3: Return code
+ R4: If R3 = H_Invalid_Element_Id: The array index of the bad
+ element ID.
+ If R3 = H_Invalid_Element_Size: The array index of the bad
+ element size.
+ If R3 = H_Invalid_Element_Value: The array index of the bad
+ element value.
+
+H_GUEST_SET_STATE()
+-------------------
+
+This is called to set L2 wide or vCPU specific L2 state. This info is
+passed via the Guest State Buffer (GSB), necessary details below:
+
+This can set either L2 wide or vcpu specific information. Examples of
+L2 wide is the timebase offset or process scoped page table
+info. Examples of vCPU specific are GPRs or VSRs. A bit in the flags
+parameter specifies if this call is L2 wide or vCPU specific and the
+IDs in the GSB must match this.
+
+The L1 provides a pointer to the GSB as a parameter to this call. Also
+provided is the L2 and vCPU IDs associated with the state to set.
+
+The L1 writes all values in the GSB and the L0 only reads the GSB for
+this call::
+
+ H_GUEST_SET_STATE(uint64 flags,
+ uint64 guestId,
+ uint64 vcpuId,
+ uint64 dataBuffer,
+ uint64 dataBufferSizeInBytes);
+ Parameters:
+ Input:
+ flags:
+ Bit 0: getGuestWideState: Request state of the Guest instead
+ of an individual VCPU.
+ Bit 1: returnOwnershipOfVcpuState Return Guest VCPU state. See
+ GET_STATE takeOwnershipOfVcpuState
+ Bits 2-63: Reserved
+ guestId: ID obtained from H_GUEST_CREATE
+ vcpuId: ID of the vCPU pass to H_GUEST_CREATE_VCPU
+ dataBuffer: A L1 real address of the GSB.
+ If takeOwnershipOfVcpuState, size must be at least the size
+ returned by ID=0x0001
+ dataBufferSizeInBytes: Size of dataBuffer
+ Output:
+ R3: Return code
+ R4: If R3 = H_Invalid_Element_Id: The array index of the bad
+ element ID.
+ If R3 = H_Invalid_Element_Size: The array index of the bad
+ element size.
+ If R3 = H_Invalid_Element_Value: The array index of the bad
+ element value.
+
+H_GUEST_RUN_VCPU()
+------------------
+
+This is called to run an L2 vCPU. The L2 and vCPU IDs are passed in as
+parameters. The vCPU runs with the state set previously using
+H_GUEST_SET_STATE(). When the L2 exits, the L1 will resume from this
+hcall.
+
+This hcall also has associated input and output GSBs. Unlike
+H_GUEST_{S,G}ET_STATE(), these GSB pointers are not passed in as
+parameters to the hcall (This was done in the interest of
+performance). The locations of these GSBs must be preregistered using
+the H_GUEST_SET_STATE() call with ID 0x0c00 and 0x0c01 (see table
+below).
+
+The input GSB may contain only VCPU specific elements to be set. This
+GSB may also contain zero elements (ie 0 in the first 4 bytes of the
+GSB) if nothing needs to be set.
+
+On exit from the hcall, the output buffer is filled with elements
+determined by the L0. The reason for the exit is contained in GPR4 (ie
+NIP is put in GPR4). The elements returned depend on the exit
+type. For example, if the exit reason is the L2 doing a hcall (GPR4 =
+0xc00), then GPR3-12 are provided in the output GSB as this is the
+state likely needed to service the hcall. If additional state is
+needed, H_GUEST_GET_STATE() may be called by the L1.
+
+To synthesize interrupts in the L2, when calling H_GUEST_RUN_VCPU()
+the L1 may set a flag (as a hcall parameter) and the L0 will
+synthesize the interrupt in the L2. Alternatively, the L1 may
+synthesize the interrupt itself using H_GUEST_SET_STATE() or the
+H_GUEST_RUN_VCPU() input GSB to set the state appropriately::
+
+ H_GUEST_RUN_VCPU(uint64 flags,
+ uint64 guestId,
+ uint64 vcpuId,
+ uint64 dataBuffer,
+ uint64 dataBufferSizeInBytes);
+ Parameters:
+ Input:
+ flags:
+ Bit 0: generateExternalInterrupt: Generate an external interrupt
+ Bit 1: generatePrivilegedDoorbell: Generate a Privileged Doorbell
+ Bit 2: sendToSystemResetâ€: Generate a System Reset Interrupt
+ Bits 3-63: Reserved
+ guestId: ID obtained from H_GUEST_CREATE
+ vcpuId: ID of the vCPU pass to H_GUEST_CREATE_VCPU
+ Output:
+ R3: Return code
+ R4: If R3 = H_Success: The reason L1 VCPU exited (ie. NIA)
+ 0x000: The VCPU stopped running for an unspecified reason. An
+ example of this is the Hypervisor stopping a VCPU running
+ due to an outstanding interrupt for the Host Partition.
+ 0x980: HDEC
+ 0xC00: HCALL
+ 0xE00: HDSI
+ 0xE20: HISI
+ 0xE40: HEA
+ 0xF80: HV Fac Unavail
+ If R3 = H_Invalid_Element_Id, H_Invalid_Element_Size, or
+ H_Invalid_Element_Value: R4 is offset of the invalid element
+ in the input buffer.
+
+H_GUEST_DELETE()
+----------------
+
+This is called to delete an L2. All associated vCPUs are also
+deleted. No specific vCPU delete call is provided.
+
+A flag may be provided to delete all guests. This is used to reset the
+L0 in the case of kdump/kexec::
+
+ H_GUEST_DELETE(uint64 flags,
+ uint64 guestId)
+ Parameters:
+ Input:
+ flags:
+ Bit 0: deleteAllGuests: deletes all guests
+ Bits 1-63: Reserved
+ guestId: ID obtained from H_GUEST_CREATE
+ Output:
+ R3: Return code
+
+Guest State Buffer
+==================
+
+The Guest State Buffer (GSB) is the main method of communicating state
+about the L2 between the L1 and L0 via H_GUEST_{G,S}ET() and
+H_GUEST_VCPU_RUN() calls.
+
+State may be associated with a whole L2 (eg timebase offset) or a
+specific L2 vCPU (eg. GPR state). Only L2 VCPU state maybe be set by
+H_GUEST_VCPU_RUN().
+
+All data in the GSB is big endian (as is standard in PAPR)
+
+The Guest state buffer has a header which gives the number of
+elements, followed by the GSB elements themselves.
+
+GSB header:
+
++----------+----------+-------------------------------------------+
+| Offset | Size | Purpose |
+| Bytes | Bytes | |
++==========+==========+===========================================+
+| 0 | 4 | Number of elements |
++----------+----------+-------------------------------------------+
+| 4 | | Guest state buffer elements |
++----------+----------+-------------------------------------------+
+
+GSB element:
+
++----------+----------+-------------------------------------------+
+| Offset | Size | Purpose |
+| Bytes | Bytes | |
++==========+==========+===========================================+
+| 0 | 2 | ID |
++----------+----------+-------------------------------------------+
+| 2 | 2 | Size of Value |
++----------+----------+-------------------------------------------+
+| 4 | As above | Value |
++----------+----------+-------------------------------------------+
+
+The ID in the GSB element specifies what is to be set. This includes
+archtected state like GPRs, VSRs, SPRs, plus also some meta data about
+the partition like the timebase offset and partition scoped page
+table information.
+
++--------+-------+----+--------+----------------------------------+
+| ID | Size | RW | Thread | Details |
+| | Bytes | | Guest | |
+| | | | Scope | |
++========+=======+====+========+==================================+
+| 0x0000 | | RW | TG | NOP element |
++--------+-------+----+--------+----------------------------------+
+| 0x0001 | 0x08 | R | G | Size of L0 vCPU state. See: |
+| | | | | H_GUEST_GET_STATE: |
+| | | | | flags = takeOwnershipOfVcpuState |
++--------+-------+----+--------+----------------------------------+
+| 0x0002 | 0x08 | R | G | Size Run vCPU out buffer |
++--------+-------+----+--------+----------------------------------+
+| 0x0003 | 0x04 | RW | G | Logical PVR |
++--------+-------+----+--------+----------------------------------+
+| 0x0004 | 0x08 | RW | G | TB Offset (L1 relative) |
++--------+-------+----+--------+----------------------------------+
+| 0x0005 | 0x18 | RW | G |Partition scoped page tbl info: |
+| | | | | |
+| | | | |- 0x00 Addr part scope table |
+| | | | |- 0x08 Num addr bits |
+| | | | |- 0x10 Size root dir |
++--------+-------+----+--------+----------------------------------+
+| 0x0006 | 0x10 | RW | G |Process Table Information: |
+| | | | | |
+| | | | |- 0x0 Addr proc scope table |
+| | | | |- 0x8 Table size. |
++--------+-------+----+--------+----------------------------------+
+| 0x0007-| | | | Reserved |
+| 0x0BFF | | | | |
++--------+-------+----+--------+----------------------------------+
+| 0x0C00 | 0x10 | RW | T |Run vCPU Input Buffer: |
+| | | | | |
+| | | | |- 0x0 Addr of buffer |
+| | | | |- 0x8 Buffer Size. |
++--------+-------+----+--------+----------------------------------+
+| 0x0C01 | 0x10 | RW | T |Run vCPU Output Buffer: |
+| | | | | |
+| | | | |- 0x0 Addr of buffer |
+| | | | |- 0x8 Buffer Size. |
++--------+-------+----+--------+----------------------------------+
+| 0x0C02 | 0x08 | RW | T | vCPU VPA Address |
++--------+-------+----+--------+----------------------------------+
+| 0x0C03-| | | | Reserved |
+| 0x0FFF | | | | |
++--------+-------+----+--------+----------------------------------+
+| 0x1000-| 0x08 | RW | T | GPR 0-31 |
+| 0x101F | | | | |
++--------+-------+----+--------+----------------------------------+
+| 0x1020 | 0x08 | T | T | HDEC expiry TB |
++--------+-------+----+--------+----------------------------------+
+| 0x1021 | 0x08 | RW | T | NIA |
++--------+-------+----+--------+----------------------------------+
+| 0x1022 | 0x08 | RW | T | MSR |
++--------+-------+----+--------+----------------------------------+
+| 0x1023 | 0x08 | RW | T | LR |
++--------+-------+----+--------+----------------------------------+
+| 0x1024 | 0x08 | RW | T | XER |
++--------+-------+----+--------+----------------------------------+
+| 0x1025 | 0x08 | RW | T | CTR |
++--------+-------+----+--------+----------------------------------+
+| 0x1026 | 0x08 | RW | T | CFAR |
++--------+-------+----+--------+----------------------------------+
+| 0x1027 | 0x08 | RW | T | SRR0 |
++--------+-------+----+--------+----------------------------------+
+| 0x1028 | 0x08 | RW | T | SRR1 |
++--------+-------+----+--------+----------------------------------+
+| 0x1029 | 0x08 | RW | T | DAR |
++--------+-------+----+--------+----------------------------------+
+| 0x102A | 0x08 | RW | T | DEC expiry TB |
++--------+-------+----+--------+----------------------------------+
+| 0x102B | 0x08 | RW | T | VTB |
++--------+-------+----+--------+----------------------------------+
+| 0x102C | 0x08 | RW | T | LPCR |
++--------+-------+----+--------+----------------------------------+
+| 0x102D | 0x08 | RW | T | HFSCR |
++--------+-------+----+--------+----------------------------------+
+| 0x102E | 0x08 | RW | T | FSCR |
++--------+-------+----+--------+----------------------------------+
+| 0x102F | 0x08 | RW | T | FPSCR |
++--------+-------+----+--------+----------------------------------+
+| 0x1030 | 0x08 | RW | T | DAWR0 |
++--------+-------+----+--------+----------------------------------+
+| 0x1031 | 0x08 | RW | T | DAWR1 |
++--------+-------+----+--------+----------------------------------+
+| 0x1032 | 0x08 | RW | T | CIABR |
++--------+-------+----+--------+----------------------------------+
+| 0x1033 | 0x08 | RW | T | PURR |
++--------+-------+----+--------+----------------------------------+
+| 0x1034 | 0x08 | RW | T | SPURR |
++--------+-------+----+--------+----------------------------------+
+| 0x1035 | 0x08 | RW | T | IC |
++--------+-------+----+--------+----------------------------------+
+| 0x1036-| 0x08 | RW | T | SPRG 0-3 |
+| 0x1039 | | | | |
++--------+-------+----+--------+----------------------------------+
+| 0x103A | 0x08 | W | T | PPR |
++--------+-------+----+--------+----------------------------------+
+| 0x103B | 0x08 | RW | T | MMCR 0-3 |
+| 0x103E | | | | |
++--------+-------+----+--------+----------------------------------+
+| 0x103F | 0x08 | RW | T | MMCRA |
++--------+-------+----+--------+----------------------------------+
+| 0x1040 | 0x08 | RW | T | SIER |
++--------+-------+----+--------+----------------------------------+
+| 0x1041 | 0x08 | RW | T | SIER 2 |
++--------+-------+----+--------+----------------------------------+
+| 0x1042 | 0x08 | RW | T | SIER 3 |
++--------+-------+----+--------+----------------------------------+
+| 0x1043 | 0x08 | RW | T | BESCR |
++--------+-------+----+--------+----------------------------------+
+| 0x1044 | 0x08 | RW | T | EBBHR |
++--------+-------+----+--------+----------------------------------+
+| 0x1045 | 0x08 | RW | T | EBBRR |
++--------+-------+----+--------+----------------------------------+
+| 0x1046 | 0x08 | RW | T | AMR |
++--------+-------+----+--------+----------------------------------+
+| 0x1047 | 0x08 | RW | T | IAMR |
++--------+-------+----+--------+----------------------------------+
+| 0x1048 | 0x08 | RW | T | AMOR |
++--------+-------+----+--------+----------------------------------+
+| 0x1049 | 0x08 | RW | T | UAMOR |
++--------+-------+----+--------+----------------------------------+
+| 0x104A | 0x08 | RW | T | SDAR |
++--------+-------+----+--------+----------------------------------+
+| 0x104B | 0x08 | RW | T | SIAR |
++--------+-------+----+--------+----------------------------------+
+| 0x104C | 0x08 | RW | T | DSCR |
++--------+-------+----+--------+----------------------------------+
+| 0x104D | 0x08 | RW | T | TAR |
++--------+-------+----+--------+----------------------------------+
+| 0x104E | 0x08 | RW | T | DEXCR |
++--------+-------+----+--------+----------------------------------+
+| 0x104F | 0x08 | RW | T | HDEXCR |
++--------+-------+----+--------+----------------------------------+
+| 0x1050 | 0x08 | RW | T | HASHKEYR |
++--------+-------+----+--------+----------------------------------+
+| 0x1051 | 0x08 | RW | T | HASHPKEYR |
++--------+-------+----+--------+----------------------------------+
+| 0x1052 | 0x08 | RW | T | CTRL |
++--------+-------+----+--------+----------------------------------+
+| 0x1053-| | | | Reserved |
+| 0x1FFF | | | | |
++--------+-------+----+--------+----------------------------------+
+| 0x2000 | 0x04 | RW | T | CR |
++--------+-------+----+--------+----------------------------------+
+| 0x2001 | 0x04 | RW | T | PIDR |
++--------+-------+----+--------+----------------------------------+
+| 0x2002 | 0x04 | RW | T | DSISR |
++--------+-------+----+--------+----------------------------------+
+| 0x2003 | 0x04 | RW | T | VSCR |
++--------+-------+----+--------+----------------------------------+
+| 0x2004 | 0x04 | RW | T | VRSAVE |
++--------+-------+----+--------+----------------------------------+
+| 0x2005 | 0x04 | RW | T | DAWRX0 |
++--------+-------+----+--------+----------------------------------+
+| 0x2006 | 0x04 | RW | T | DAWRX1 |
++--------+-------+----+--------+----------------------------------+
+| 0x2007-| 0x04 | RW | T | PMC 1-6 |
+| 0x200c | | | | |
++--------+-------+----+--------+----------------------------------+
+| 0x200D | 0x04 | RW | T | WORT |
++--------+-------+----+--------+----------------------------------+
+| 0x200E | 0x04 | RW | T | PSPB |
++--------+-------+----+--------+----------------------------------+
+| 0x200F-| | | | Reserved |
+| 0x2FFF | | | | |
++--------+-------+----+--------+----------------------------------+
+| 0x3000-| 0x10 | RW | T | VSR 0-63 |
+| 0x303F | | | | |
++--------+-------+----+--------+----------------------------------+
+| 0x3040-| | | | Reserved |
+| 0xEFFF | | | | |
++--------+-------+----+--------+----------------------------------+
+| 0xF000 | 0x08 | R | T | HDAR |
++--------+-------+----+--------+----------------------------------+
+| 0xF001 | 0x04 | R | T | HDSISR |
++--------+-------+----+--------+----------------------------------+
+| 0xF002 | 0x04 | R | T | HEIR |
++--------+-------+----+--------+----------------------------------+
+| 0xF003 | 0x08 | R | T | ASDR |
++--------+-------+----+--------+----------------------------------+
+
+
+Miscellaneous info
+==================
+
+State not in ptregs/hvregs
+--------------------------
+
+In the v1 API, some state is not in the ptregs/hvstate. This includes
+the vector register and some SPRs. For the L1 to set this state for
+the L2, the L1 loads up these hardware registers before the
+h_enter_nested() call and the L0 ensures they end up as the L2 state
+(by not touching them).
+
+The v2 API removes this and explicitly sets this state via the GSB.
+
+L1 Implementation details: Caching state
+----------------------------------------
+
+In the v1 API, all state is sent from the L1 to the L0 and vice versa
+on every h_enter_nested() hcall. If the L0 is not currently running
+any L2s, the L0 has no state information about them. The only
+exception to this is the location of the partition table, registered
+via h_set_partition_table().
+
+The v2 API changes this so that the L0 retains the L2 state even when
+it's vCPUs are no longer running. This means that the L1 only needs to
+communicate with the L0 about L2 state when it needs to modify the L2
+state, or when it's value is out of date. This provides an opportunity
+for performance optimisation.
+
+When a vCPU exits from a H_GUEST_RUN_VCPU() call, the L1 internally
+marks all L2 state as invalid. This means that if the L1 wants to know
+the L2 state (say via a kvm_get_one_reg() call), it needs call
+H_GUEST_GET_STATE() to get that state. Once it's read, it's marked as
+valid in L1 until the L2 is run again.
+
+Also, when an L1 modifies L2 vcpu state, it doesn't need to write it
+to the L0 until that L2 vcpu runs again. Hence when the L1 updates
+state (say via a kvm_set_one_reg() call), it writes to an internal L1
+copy and only flushes this copy to the L0 when the L2 runs again via
+the H_GUEST_VCPU_RUN() input buffer.
+
+This lazy updating of state by the L1 avoids unnecessary
+H_GUEST_{G|S}ET_STATE() calls.
diff --git a/Documentation/powerpc/mpc52xx.rst b/Documentation/arch/powerpc/mpc52xx.rst
index 5243b1763fad..5243b1763fad 100644
--- a/Documentation/powerpc/mpc52xx.rst
+++ b/Documentation/arch/powerpc/mpc52xx.rst
diff --git a/Documentation/powerpc/papr_hcalls.rst b/Documentation/arch/powerpc/papr_hcalls.rst
index 80d2c0aadab5..80d2c0aadab5 100644
--- a/Documentation/powerpc/papr_hcalls.rst
+++ b/Documentation/arch/powerpc/papr_hcalls.rst
diff --git a/Documentation/powerpc/pci_iov_resource_on_powernv.rst b/Documentation/arch/powerpc/pci_iov_resource_on_powernv.rst
index f5a5793e1613..f5a5793e1613 100644
--- a/Documentation/powerpc/pci_iov_resource_on_powernv.rst
+++ b/Documentation/arch/powerpc/pci_iov_resource_on_powernv.rst
diff --git a/Documentation/powerpc/pmu-ebb.rst b/Documentation/arch/powerpc/pmu-ebb.rst
index 4f474758eb55..4f474758eb55 100644
--- a/Documentation/powerpc/pmu-ebb.rst
+++ b/Documentation/arch/powerpc/pmu-ebb.rst
diff --git a/Documentation/powerpc/ptrace.rst b/Documentation/arch/powerpc/ptrace.rst
index 5629edf4d56e..5629edf4d56e 100644
--- a/Documentation/powerpc/ptrace.rst
+++ b/Documentation/arch/powerpc/ptrace.rst
diff --git a/Documentation/powerpc/qe_firmware.rst b/Documentation/arch/powerpc/qe_firmware.rst
index a358f152b7e7..a358f152b7e7 100644
--- a/Documentation/powerpc/qe_firmware.rst
+++ b/Documentation/arch/powerpc/qe_firmware.rst
diff --git a/Documentation/powerpc/syscall64-abi.rst b/Documentation/arch/powerpc/syscall64-abi.rst
index 56490c4c0c07..56490c4c0c07 100644
--- a/Documentation/powerpc/syscall64-abi.rst
+++ b/Documentation/arch/powerpc/syscall64-abi.rst
diff --git a/Documentation/powerpc/transactional_memory.rst b/Documentation/arch/powerpc/transactional_memory.rst
index 040a20675fd1..040a20675fd1 100644
--- a/Documentation/powerpc/transactional_memory.rst
+++ b/Documentation/arch/powerpc/transactional_memory.rst
diff --git a/Documentation/powerpc/ultravisor.rst b/Documentation/arch/powerpc/ultravisor.rst
index ba6b1bf1cc44..ba6b1bf1cc44 100644
--- a/Documentation/powerpc/ultravisor.rst
+++ b/Documentation/arch/powerpc/ultravisor.rst
diff --git a/Documentation/powerpc/vas-api.rst b/Documentation/arch/powerpc/vas-api.rst
index a9625a2fa0c6..a9625a2fa0c6 100644
--- a/Documentation/powerpc/vas-api.rst
+++ b/Documentation/arch/powerpc/vas-api.rst
diff --git a/Documentation/powerpc/vcpudispatch_stats.rst b/Documentation/arch/powerpc/vcpudispatch_stats.rst
index 5704657a5987..5704657a5987 100644
--- a/Documentation/powerpc/vcpudispatch_stats.rst
+++ b/Documentation/arch/powerpc/vcpudispatch_stats.rst
diff --git a/Documentation/powerpc/vmemmap_dedup.rst b/Documentation/arch/powerpc/vmemmap_dedup.rst
index dc4db59fdf87..dc4db59fdf87 100644
--- a/Documentation/powerpc/vmemmap_dedup.rst
+++ b/Documentation/arch/powerpc/vmemmap_dedup.rst
diff --git a/Documentation/riscv/acpi.rst b/Documentation/arch/riscv/acpi.rst
index 9870a282815b..9870a282815b 100644
--- a/Documentation/riscv/acpi.rst
+++ b/Documentation/arch/riscv/acpi.rst
diff --git a/Documentation/riscv/boot-image-header.rst b/Documentation/arch/riscv/boot-image-header.rst
index df2ffc173e80..df2ffc173e80 100644
--- a/Documentation/riscv/boot-image-header.rst
+++ b/Documentation/arch/riscv/boot-image-header.rst
diff --git a/Documentation/riscv/boot.rst b/Documentation/arch/riscv/boot.rst
index 6077b587a842..6077b587a842 100644
--- a/Documentation/riscv/boot.rst
+++ b/Documentation/arch/riscv/boot.rst
diff --git a/Documentation/riscv/features.rst b/Documentation/arch/riscv/features.rst
index c70ef6ac2368..c70ef6ac2368 100644
--- a/Documentation/riscv/features.rst
+++ b/Documentation/arch/riscv/features.rst
diff --git a/Documentation/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
index a52996b22f75..7b2384de471f 100644
--- a/Documentation/riscv/hwprobe.rst
+++ b/Documentation/arch/riscv/hwprobe.rst
@@ -77,6 +77,9 @@ The following keys are defined:
* :c:macro:`RISCV_HWPROBE_EXT_ZBS`: The Zbs extension is supported, as defined
in version 1.0 of the Bit-Manipulation ISA extensions.
+ * :c:macro:`RISCV_HWPROBE_EXT_ZICBOZ`: The Zicboz extension is supported, as
+ ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
+
* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: A bitmask that contains performance
information about the selected set of processors.
@@ -96,3 +99,6 @@ The following keys are defined:
* :c:macro:`RISCV_HWPROBE_MISALIGNED_UNSUPPORTED`: Misaligned accesses are
not supported at all and will generate a misaligned address fault.
+
+* :c:macro:`RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE`: An unsigned int which
+ represents the size of the Zicboz block in bytes.
diff --git a/Documentation/riscv/index.rst b/Documentation/arch/riscv/index.rst
index 4dab0cb4b900..4dab0cb4b900 100644
--- a/Documentation/riscv/index.rst
+++ b/Documentation/arch/riscv/index.rst
diff --git a/Documentation/riscv/patch-acceptance.rst b/Documentation/arch/riscv/patch-acceptance.rst
index 634aa222b410..634aa222b410 100644
--- a/Documentation/riscv/patch-acceptance.rst
+++ b/Documentation/arch/riscv/patch-acceptance.rst
diff --git a/Documentation/riscv/uabi.rst b/Documentation/arch/riscv/uabi.rst
index 8960fac42c40..54d199dce78b 100644
--- a/Documentation/riscv/uabi.rst
+++ b/Documentation/arch/riscv/uabi.rst
@@ -42,6 +42,26 @@ An example string following the order is::
rv64imadc_zifoo_zigoo_zafoo_sbar_scar_zxmbaz_xqux_xrux
+"isa" and "hart isa" lines in /proc/cpuinfo
+-------------------------------------------
+
+The "isa" line in /proc/cpuinfo describes the lowest common denominator of
+RISC-V ISA extensions recognized by the kernel and implemented on all harts. The
+"hart isa" line, in contrast, describes the set of extensions recognized by the
+kernel on the particular hart being described, even if those extensions may not
+be present on all harts in the system.
+
+In both lines, the presence of an extension guarantees only that the hardware
+has the described capability. Additional kernel support or policy changes may be
+required before an extension's capability is fully usable by userspace programs.
+Similarly, for S-mode extensions, presence in one of these lines does not
+guarantee that the kernel is taking advantage of the extension, or that the
+feature will be visible in guest VMs managed by this kernel.
+
+Inversely, the absence of an extension in these lines does not necessarily mean
+the hardware does not support that feature. The running kernel may not recognize
+the extension, or may have deliberately removed it from the listing.
+
Misaligned accesses
-------------------
diff --git a/Documentation/riscv/vector.rst b/Documentation/arch/riscv/vector.rst
index 75dd88a62e1d..75dd88a62e1d 100644
--- a/Documentation/riscv/vector.rst
+++ b/Documentation/arch/riscv/vector.rst
diff --git a/Documentation/riscv/vm-layout.rst b/Documentation/arch/riscv/vm-layout.rst
index 69ff6da1dbf8..69ff6da1dbf8 100644
--- a/Documentation/riscv/vm-layout.rst
+++ b/Documentation/arch/riscv/vm-layout.rst
diff --git a/Documentation/arch/sh/index.rst b/Documentation/arch/sh/index.rst
index c64776738cf6..01fce7c131f1 100644
--- a/Documentation/arch/sh/index.rst
+++ b/Documentation/arch/sh/index.rst
@@ -43,12 +43,6 @@ mach-x3proto
Busses
======
-SuperHyway
-----------
-
-.. kernel-doc:: drivers/sh/superhyway/superhyway.c
- :export:
-
Maple
-----
diff --git a/Documentation/arch/x86/amd-memory-encryption.rst b/Documentation/arch/x86/amd-memory-encryption.rst
index 934310ce7258..07caa8fff852 100644
--- a/Documentation/arch/x86/amd-memory-encryption.rst
+++ b/Documentation/arch/x86/amd-memory-encryption.rst
@@ -130,4 +130,4 @@ SNP feature support.
More details in AMD64 APM[1] Vol 2: 15.34.10 SEV_STATUS MSR
-[1] https://www.amd.com/system/files/TechDocs/40332.pdf
+[1] https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/24593.pdf
diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 440e4b645a1c..c92bfd55359f 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -41,6 +41,24 @@ In-kernel integration:
* Locking across callers is taken care by the driver.
+HSMP sysfs interface
+====================
+
+1. Metrics table binary sysfs
+
+AMD MI300A MCM provides GET_METRICS_TABLE message to retrieve
+most of the system management information from SMU in one go.
+
+The metrics table is made available as hexadecimal sysfs binary file
+under per socket sysfs directory created at
+/sys/devices/platform/amd_hsmp/socket%d/metrics_bin
+
+Note: lseek() is not supported as entire metrics table is read.
+
+Metrics table definitions will be documented as part of Public PPR.
+The same is defined in the amd_hsmp.h header.
+
+
An example
==========
diff --git a/Documentation/arch/x86/boot.rst b/Documentation/arch/x86/boot.rst
index f5d2f2414de8..22cc7a040dae 100644
--- a/Documentation/arch/x86/boot.rst
+++ b/Documentation/arch/x86/boot.rst
@@ -77,7 +77,7 @@ Protocol 2.14 BURNT BY INCORRECT COMMIT
Protocol 2.15 (Kernel 5.5) Added the kernel_info and kernel_info.setup_type_max.
============= ============================================================
-.. note::
+ .. note::
The protocol version number should be changed only if the setup header
is changed. There is no need to update the version number if boot_params
or kernel_info are changed. Additionally, it is recommended to use
diff --git a/Documentation/arch/x86/iommu.rst b/Documentation/arch/x86/iommu.rst
index 42c7a6faa39a..41fbadfe2221 100644
--- a/Documentation/arch/x86/iommu.rst
+++ b/Documentation/arch/x86/iommu.rst
@@ -5,7 +5,7 @@ x86 IOMMU Support
The architecture specs can be obtained from the below locations.
- Intel: http://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/vt-directed-io-spec.pdf
-- AMD: https://www.amd.com/system/files/TechDocs/48882_IOMMU.pdf
+- AMD: https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/specifications/48882_3_07_PUB.pdf
This guide gives a quick cheat sheet for some basic understanding.
diff --git a/Documentation/arch/x86/resctrl.rst b/Documentation/arch/x86/resctrl.rst
index cb05d90111b4..a6279df64a9d 100644
--- a/Documentation/arch/x86/resctrl.rst
+++ b/Documentation/arch/x86/resctrl.rst
@@ -35,7 +35,7 @@ about the feature from resctrl's info directory.
To use the feature mount the file system::
- # mount -t resctrl resctrl [-o cdp[,cdpl2][,mba_MBps]] /sys/fs/resctrl
+ # mount -t resctrl resctrl [-o cdp[,cdpl2][,mba_MBps][,debug]] /sys/fs/resctrl
mount options are:
@@ -46,6 +46,9 @@ mount options are:
"mba_MBps":
Enable the MBA Software Controller(mba_sc) to specify MBA
bandwidth in MBps
+"debug":
+ Make debug files accessible. Available debug files are annotated with
+ "Available only with debug option".
L2 and L3 CDP are controlled separately.
@@ -124,6 +127,13 @@ related to allocation:
"P":
Corresponding region is pseudo-locked. No
sharing allowed.
+"sparse_masks":
+ Indicates if non-contiguous 1s value in CBM is supported.
+
+ "0":
+ Only contiguous 1s value in CBM is supported.
+ "1":
+ Non-contiguous 1s value in CBM is supported.
Memory bandwidth(MB) subdirectory contains the following files
with respect to allocation:
@@ -299,7 +309,14 @@ All groups contain the following files:
"tasks":
Reading this file shows the list of all tasks that belong to
this group. Writing a task id to the file will add a task to the
- group. If the group is a CTRL_MON group the task is removed from
+ group. Multiple tasks can be added by separating the task ids
+ with commas. Tasks will be assigned sequentially. Multiple
+ failures are not supported. A single failure encountered while
+ attempting to assign a task will cause the operation to abort and
+ already added tasks before the failure will remain in the group.
+ Failures will be logged to /sys/fs/resctrl/info/last_cmd_status.
+
+ If the group is a CTRL_MON group the task is removed from
whichever previous CTRL_MON group owned the task and also from
any MON group that owned the task. If the group is a MON group,
then the task must already belong to the CTRL_MON parent of this
@@ -342,6 +359,10 @@ When control is enabled all CTRL_MON groups will also contain:
file. On successful pseudo-locked region creation the mode will
automatically change to "pseudo-locked".
+"ctrl_hw_id":
+ Available only with debug option. The identifier used by hardware
+ for the control group. On x86 this is the CLOSID.
+
When monitoring is enabled all MON groups will also contain:
"mon_data":
@@ -355,6 +376,10 @@ When monitoring is enabled all MON groups will also contain:
the sum for all tasks in the CTRL_MON group and all tasks in
MON groups. Please see example section for more details on usage.
+"mon_hw_id":
+ Available only with debug option. The identifier used by hardware
+ for the monitor group. On x86 this is the RMID.
+
Resource allocation rules
-------------------------
@@ -445,12 +470,13 @@ For cache resources we describe the portion of the cache that is available
for allocation using a bitmask. The maximum value of the mask is defined
by each cpu model (and may be different for different cache levels). It
is found using CPUID, but is also provided in the "info" directory of
-the resctrl file system in "info/{resource}/cbm_mask". Intel hardware
+the resctrl file system in "info/{resource}/cbm_mask". Some Intel hardware
requires that these masks have all the '1' bits in a contiguous block. So
0x3, 0x6 and 0xC are legal 4-bit masks with two bits set, but 0x5, 0x9
-and 0xA are not. On a system with a 20-bit mask each bit represents 5%
-of the capacity of the cache. You could partition the cache into four
-equal parts with masks: 0x1f, 0x3e0, 0x7c00, 0xf8000.
+and 0xA are not. Check /sys/fs/resctrl/info/{resource}/sparse_masks
+if non-contiguous 1s value is supported. On a system with a 20-bit mask
+each bit represents 5% of the capacity of the cache. You could partition
+the cache into four equal parts with masks: 0x1f, 0x3e0, 0x7c00, 0xf8000.
Memory bandwidth Allocation and monitoring
==========================================
diff --git a/Documentation/arch/x86/topology.rst b/Documentation/arch/x86/topology.rst
index 7f58010ea86a..08ebf9edbfc1 100644
--- a/Documentation/arch/x86/topology.rst
+++ b/Documentation/arch/x86/topology.rst
@@ -55,19 +55,19 @@ Package-related topology information in the kernel:
The number of dies in a package. This information is retrieved via CPUID.
- - cpuinfo_x86.cpu_die_id:
+ - cpuinfo_x86.topo.die_id:
The physical ID of the die. This information is retrieved via CPUID.
- - cpuinfo_x86.phys_proc_id:
+ - cpuinfo_x86.topo.pkg_id:
The physical ID of the package. This information is retrieved via CPUID
and deduced from the APIC IDs of the cores in the package.
Modern systems use this value for the socket. There may be multiple
- packages within a socket. This value may differ from cpu_die_id.
+ packages within a socket. This value may differ from topo.die_id.
- - cpuinfo_x86.logical_proc_id:
+ - cpuinfo_x86.topo.logical_pkg_id:
The logical ID of the package. As we do not trust BIOSes to enumerate the
packages in a consistent way, we introduced the concept of logical package
@@ -79,9 +79,7 @@ Package-related topology information in the kernel:
The maximum possible number of packages in the system. Helpful for per
package facilities to preallocate per package information.
- - cpu_llc_id:
-
- A per-CPU variable containing:
+ - cpuinfo_x86.topo.llc_id:
- On Intel, the first APIC ID of the list of CPUs sharing the Last Level
Cache
diff --git a/Documentation/block/blk-mq.rst b/Documentation/block/blk-mq.rst
index 31f52f326971..fc06761b6ea9 100644
--- a/Documentation/block/blk-mq.rst
+++ b/Documentation/block/blk-mq.rst
@@ -56,7 +56,7 @@ sent to the software queue.
Then, after the requests are processed by software queues, they will be placed
at the hardware queue, a second stage queue where the hardware has direct access
to process those requests. However, if the hardware does not have enough
-resources to accept more requests, blk-mq will places requests on a temporary
+resources to accept more requests, blk-mq will place requests on a temporary
queue, to be sent in the future, when the hardware is able.
Software staging queues
diff --git a/Documentation/block/ioprio.rst b/Documentation/block/ioprio.rst
index f72b0de65af7..a25c6d5df87b 100644
--- a/Documentation/block/ioprio.rst
+++ b/Documentation/block/ioprio.rst
@@ -80,9 +80,6 @@ ionice.c tool::
#elif defined(__x86_64__)
#define __NR_ioprio_set 251
#define __NR_ioprio_get 252
- #elif defined(__ia64__)
- #define __NR_ioprio_set 1274
- #define __NR_ioprio_get 1275
#else
#error "Unsupported arch"
#endif
diff --git a/Documentation/bpf/kfuncs.rst b/Documentation/bpf/kfuncs.rst
index 0d2647fb358d..723408e399ab 100644
--- a/Documentation/bpf/kfuncs.rst
+++ b/Documentation/bpf/kfuncs.rst
@@ -37,16 +37,14 @@ prototype in a header for the wrapper kfunc.
An example is given below::
/* Disables missing prototype warnings */
- __diag_push();
- __diag_ignore_all("-Wmissing-prototypes",
- "Global kfuncs as their definitions will be in BTF");
+ __bpf_kfunc_start_defs();
__bpf_kfunc struct task_struct *bpf_find_get_task_by_vpid(pid_t nr)
{
return find_get_task_by_vpid(nr);
}
- __diag_pop();
+ __bpf_kfunc_end_defs();
A wrapper kfunc is often needed when we need to annotate parameters of the
kfunc. Otherwise one may directly make the kfunc visible to the BPF program by
diff --git a/Documentation/bpf/libbpf/program_types.rst b/Documentation/bpf/libbpf/program_types.rst
index ad4d4d5eecb0..63bb88846e50 100644
--- a/Documentation/bpf/libbpf/program_types.rst
+++ b/Documentation/bpf/libbpf/program_types.rst
@@ -56,6 +56,16 @@ described in more detail in the footnotes.
| | ``BPF_CGROUP_UDP6_RECVMSG`` | ``cgroup/recvmsg6`` | |
+ +----------------------------------------+----------------------------------+-----------+
| | ``BPF_CGROUP_UDP6_SENDMSG`` | ``cgroup/sendmsg6`` | |
+| +----------------------------------------+----------------------------------+-----------+
+| | ``BPF_CGROUP_UNIX_CONNECT`` | ``cgroup/connect_unix`` | |
+| +----------------------------------------+----------------------------------+-----------+
+| | ``BPF_CGROUP_UNIX_SENDMSG`` | ``cgroup/sendmsg_unix`` | |
+| +----------------------------------------+----------------------------------+-----------+
+| | ``BPF_CGROUP_UNIX_RECVMSG`` | ``cgroup/recvmsg_unix`` | |
+| +----------------------------------------+----------------------------------+-----------+
+| | ``BPF_CGROUP_UNIX_GETPEERNAME`` | ``cgroup/getpeername_unix`` | |
+| +----------------------------------------+----------------------------------+-----------+
+| | ``BPF_CGROUP_UNIX_GETSOCKNAME`` | ``cgroup/getsockname_unix`` | |
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
| ``BPF_PROG_TYPE_CGROUP_SOCK`` | ``BPF_CGROUP_INET4_POST_BIND`` | ``cgroup/post_bind4`` | |
+ +----------------------------------------+----------------------------------+-----------+
diff --git a/Documentation/bpf/prog_flow_dissector.rst b/Documentation/bpf/prog_flow_dissector.rst
index 4d86780ab0f1..f24270b8b034 100644
--- a/Documentation/bpf/prog_flow_dissector.rst
+++ b/Documentation/bpf/prog_flow_dissector.rst
@@ -113,7 +113,7 @@ Flags
used by ``eth_get_headlen`` to estimate length of all headers for GRO.
* ``BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL`` - tells BPF flow dissector to
stop parsing as soon as it reaches IPv6 flow label; used by
- ``___skb_get_hash`` and ``__skb_get_hash_symmetric`` to get flow hash.
+ ``___skb_get_hash`` to get flow hash.
* ``BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP`` - tells BPF flow dissector to stop
parsing as soon as it reaches encapsulated headers; used by routing
infrastructure.
diff --git a/Documentation/bpf/standardization/instruction-set.rst b/Documentation/bpf/standardization/instruction-set.rst
index c5d53a6e8c79..245b6defc298 100644
--- a/Documentation/bpf/standardization/instruction-set.rst
+++ b/Documentation/bpf/standardization/instruction-set.rst
@@ -283,6 +283,14 @@ For signed operations (``BPF_SDIV`` and ``BPF_SMOD``), for ``BPF_ALU``,
is first :term:`sign extended<Sign Extend>` from 32 to 64 bits, and then
interpreted as a 64-bit signed value.
+Note that there are varying definitions of the signed modulo operation
+when the dividend or divisor are negative, where implementations often
+vary by language such that Python, Ruby, etc. differ from C, Go, Java,
+etc. This specification requires that signed modulo use truncated division
+(where -13 % 3 == -1) as implemented in C, Go, etc.:
+
+ a % n = a - n * trunc(a / n)
+
The ``BPF_MOVSX`` instruction does a move operation with sign extension.
``BPF_ALU | BPF_MOVSX`` :term:`sign extends<Sign Extend>` 8-bit and 16-bit operands into 32
bit operands, and zeroes the remaining upper 32 bits.
diff --git a/Documentation/core-api/cpu_hotplug.rst b/Documentation/core-api/cpu_hotplug.rst
index 9511e405aabd..dcb0e379e5e8 100644
--- a/Documentation/core-api/cpu_hotplug.rst
+++ b/Documentation/core-api/cpu_hotplug.rst
@@ -40,12 +40,6 @@ Command Line Switches
supplied here is lower than the number of physically available CPUs, then
those CPUs can not be brought online later.
-``additional_cpus=n``
- Use this to limit hotpluggable CPUs. This option sets
- ``cpu_possible_mask = cpu_present_mask + additional_cpus``
-
- This option is limited to the IA64 architecture.
-
``possible_cpus=n``
This option sets ``possible_cpus`` bits in ``cpu_possible_mask``.
diff --git a/Documentation/core-api/debugging-via-ohci1394.rst b/Documentation/core-api/debugging-via-ohci1394.rst
index 981ad4f89fd3..cb3d3228dfc8 100644
--- a/Documentation/core-api/debugging-via-ohci1394.rst
+++ b/Documentation/core-api/debugging-via-ohci1394.rst
@@ -23,9 +23,9 @@ Retrieving a full system memory dump is also possible over the FireWire,
using data transfer rates in the order of 10MB/s or more.
With most FireWire controllers, memory access is limited to the low 4 GB
-of physical address space. This can be a problem on IA64 machines where
-memory is located mostly above that limit, but it is rarely a problem on
-more common hardware such as x86, x86-64 and PowerPC.
+of physical address space. This can be a problem on machines where memory is
+located mostly above that limit, but it is rarely a problem on more common
+hardware such as x86, x86-64 and PowerPC.
At least LSI FW643e and FW643e2 controllers are known to support access to
physical addresses above 4 GB, but this feature is currently not enabled by
diff --git a/Documentation/core-api/maple_tree.rst b/Documentation/core-api/maple_tree.rst
index 45defcf15da7..96f3d5f076b5 100644
--- a/Documentation/core-api/maple_tree.rst
+++ b/Documentation/core-api/maple_tree.rst
@@ -175,7 +175,7 @@ will return the previous entry which occurs before the entry at index.
mas_find() will find the first entry which exists at or above index on
the first call, and the next entry from every subsequent calls.
-mas_find_rev() will find the fist entry which exists at or below the last on
+mas_find_rev() will find the first entry which exists at or below the last on
the first call, and the previous entry from every subsequent calls.
If the user needs to yield the lock during an operation, then the maple state
diff --git a/Documentation/core-api/workqueue.rst b/Documentation/core-api/workqueue.rst
index 5d7b01aed1fe..0046af06531a 100644
--- a/Documentation/core-api/workqueue.rst
+++ b/Documentation/core-api/workqueue.rst
@@ -244,7 +244,7 @@ unbound worker-pools and only one work item could be active at any given
time thus achieving the same ordering property as ST wq.
In the current implementation the above configuration only guarantees
-ST behavior within a given NUMA node. Instead ``alloc_ordered_queue()`` should
+ST behavior within a given NUMA node. Instead ``alloc_ordered_workqueue()`` should
be used to achieve system-wide ST behavior.
@@ -390,7 +390,7 @@ The default affinity scope can be changed with the module parameter
scope can be changed using ``apply_workqueue_attrs()``.
If ``WQ_SYSFS`` is set, the workqueue will have the following affinity scope
-related interface files under its ``/sys/devices/virtual/WQ_NAME/``
+related interface files under its ``/sys/devices/virtual/workqueue/WQ_NAME/``
directory.
``affinity_scope``
diff --git a/Documentation/crypto/devel-algos.rst b/Documentation/crypto/devel-algos.rst
index 3506899ef83e..9b7782f4f6e0 100644
--- a/Documentation/crypto/devel-algos.rst
+++ b/Documentation/crypto/devel-algos.rst
@@ -235,6 +235,4 @@ Specifics Of Asynchronous HASH Transformation
Some of the drivers will want to use the Generic ScatterWalk in case the
implementation needs to be fed separate chunks of the scatterlist which
-contains the input data. The buffer containing the resulting hash will
-always be properly aligned to .cra_alignmask so there is no need to
-worry about this.
+contains the input data.
diff --git a/Documentation/dev-tools/kasan.rst b/Documentation/dev-tools/kasan.rst
index 382818a7197a..858c77fe7dc4 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -1,5 +1,8 @@
-The Kernel Address Sanitizer (KASAN)
-====================================
+.. SPDX-License-Identifier: GPL-2.0
+.. Copyright (C) 2023, Google LLC.
+
+Kernel Address Sanitizer (KASAN)
+================================
Overview
--------
diff --git a/Documentation/dev-tools/kcsan.rst b/Documentation/dev-tools/kcsan.rst
index 3ae866dcc924..94b6802ab0ab 100644
--- a/Documentation/dev-tools/kcsan.rst
+++ b/Documentation/dev-tools/kcsan.rst
@@ -1,8 +1,8 @@
.. SPDX-License-Identifier: GPL-2.0
.. Copyright (C) 2019, Google LLC.
-The Kernel Concurrency Sanitizer (KCSAN)
-========================================
+Kernel Concurrency Sanitizer (KCSAN)
+====================================
The Kernel Concurrency Sanitizer (KCSAN) is a dynamic race detector, which
relies on compile-time instrumentation, and uses a watchpoint-based sampling
diff --git a/Documentation/dev-tools/kmsan.rst b/Documentation/dev-tools/kmsan.rst
index 55fa82212eb2..323eedad53cd 100644
--- a/Documentation/dev-tools/kmsan.rst
+++ b/Documentation/dev-tools/kmsan.rst
@@ -1,9 +1,9 @@
.. SPDX-License-Identifier: GPL-2.0
.. Copyright (C) 2022, Google LLC.
-===================================
-The Kernel Memory Sanitizer (KMSAN)
-===================================
+===============================
+Kernel Memory Sanitizer (KMSAN)
+===============================
KMSAN is a dynamic error detector aimed at finding uses of uninitialized
values. It is based on compiler instrumentation, and is quite similar to the
diff --git a/Documentation/dev-tools/kselftest.rst b/Documentation/dev-tools/kselftest.rst
index deede972f254..ab376b316c36 100644
--- a/Documentation/dev-tools/kselftest.rst
+++ b/Documentation/dev-tools/kselftest.rst
@@ -112,7 +112,7 @@ You can specify multiple tests to skip::
You can also specify a restricted list of tests to run together with a
dedicated skiplist::
- $ make TARGETS="bpf breakpoints size timers" SKIP_TARGETS=bpf kselftest
+ $ make TARGETS="breakpoints size timers" SKIP_TARGETS=size kselftest
See the top-level tools/testing/selftests/Makefile for the list of all
possible targets.
@@ -165,7 +165,7 @@ To see the list of available tests, the `-l` option can be used::
The `-c` option can be used to run all the tests from a test collection, or
the `-t` option for specific single tests. Either can be used multiple times::
- $ ./run_kselftest.sh -c bpf -c seccomp -t timers:posix_timers -t timer:nanosleep
+ $ ./run_kselftest.sh -c size -c seccomp -t timers:posix_timers -t timer:nanosleep
For other features see the script usage output, seen with the `-h` option.
@@ -210,7 +210,7 @@ option is supported, such as::
tests by using variables specified in `Running a subset of selftests`_
section::
- $ make -C tools/testing/selftests gen_tar TARGETS="bpf" FORMAT=.xz
+ $ make -C tools/testing/selftests gen_tar TARGETS="size" FORMAT=.xz
.. _tar's auto-compress: https://www.gnu.org/software/tar/manual/html_node/gzip.html#auto_002dcompress
diff --git a/Documentation/dev-tools/ubsan.rst b/Documentation/dev-tools/ubsan.rst
index 1be6618e232d..2de7c63415da 100644
--- a/Documentation/dev-tools/ubsan.rst
+++ b/Documentation/dev-tools/ubsan.rst
@@ -1,5 +1,7 @@
-The Undefined Behavior Sanitizer - UBSAN
-========================================
+.. SPDX-License-Identifier: GPL-2.0
+
+Undefined Behavior Sanitizer - UBSAN
+====================================
UBSAN is a runtime undefined behaviour checker.
diff --git a/Documentation/devicetree/bindings/Makefile b/Documentation/devicetree/bindings/Makefile
index 8b395893bd85..3e886194b043 100644
--- a/Documentation/devicetree/bindings/Makefile
+++ b/Documentation/devicetree/bindings/Makefile
@@ -6,7 +6,7 @@ DT_MK_SCHEMA ?= dt-mk-schema
DT_SCHEMA_LINT = $(shell which yamllint || \
echo "warning: python package 'yamllint' not installed, skipping" >&2)
-DT_SCHEMA_MIN_VERSION = 2022.3
+DT_SCHEMA_MIN_VERSION = 2023.9
PHONY += check_dtschema_version
check_dtschema_version:
diff --git a/Documentation/devicetree/bindings/arm/amd,pensando.yaml b/Documentation/devicetree/bindings/arm/amd,pensando.yaml
new file mode 100644
index 000000000000..e5c2591834a8
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/amd,pensando.yaml
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/amd,pensando.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: AMD Pensando SoC Platforms
+
+maintainers:
+ - Brad Larson <blarson@amd.com>
+
+properties:
+ $nodename:
+ const: "/"
+ compatible:
+ oneOf:
+
+ - description: Boards with Pensando Elba SoC
+ items:
+ - enum:
+ - amd,pensando-elba-ortano
+ - const: amd,pensando-elba
+
+additionalProperties: true
+
+...
diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index 1c1094cd6b77..caab7ceeda45 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -155,6 +155,7 @@ properties:
- enum:
- bananapi,bpi-m2s
- khadas,vim3
+ - libretech,aml-a311d-cc
- radxa,zero2
- const: amlogic,a311d
- const: amlogic,g12b
@@ -196,6 +197,7 @@ properties:
- hardkernel,odroid-hc4
- haochuangyi,h96-max
- khadas,vim3l
+ - libretech,aml-s905d3-cc
- seirobotics,sei610
- const: amlogic,sm1
@@ -203,6 +205,7 @@ properties:
items:
- enum:
- amlogic,ad401
+ - amlogic,ad402
- const: amlogic,a1
- description: Boards with the Amlogic C3 C302X/C308L SoC
diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml
index 6216cfb0a188..2d5545a2b49c 100644
--- a/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml
@@ -92,11 +92,8 @@ properties:
maxItems: 1
cpu:
- $ref: /schemas/types.yaml#/definitions/phandle
description:
- Handle to cpu this device is associated with. This must appear in the
- base cti node if compatible string arm,coresight-cti-v8-arch is used,
- or may appear in a trig-conns child node when appropriate.
+ Handle to cpu this CTI is associated with.
power-domains:
maxItems: 1
@@ -113,12 +110,12 @@ properties:
description:
defines a phandle reference to an associated CoreSight trace device.
When the associated trace device is enabled, then the respective CTI
- will be enabled. Use in a trig-conns node, or in CTI base node when
- compatible string arm,coresight-cti-v8-arch used. If the associated
- device has not been registered then the node name will be stored as
- the connection name for later resolution. If the associated device is
- not a CoreSight device or not registered then the node name will remain
- the connection name and automatic enabling will not occur.
+ will be enabled. Use in CTI base node when compatible string
+ arm,coresight-cti-v8-arch used. If the associated device has not been
+ registered then the node name will be stored as the connection name for
+ later resolution. If the associated device is not a CoreSight device or
+ not registered then the node name will remain the connection name and
+ automatic enabling will not occur.
# size cells and address cells required if trig-conns node present.
"#size-cells":
@@ -130,6 +127,8 @@ properties:
patternProperties:
'^trig-conns@([0-9]+)$':
type: object
+ additionalProperties: false
+
description:
A trigger connections child node which describes the trigger signals
between this CTI and another hardware device. This device may be a CPU,
@@ -141,6 +140,21 @@ patternProperties:
reg:
maxItems: 1
+ cpu:
+ description:
+ Handle to cpu this trigger connection is associated with.
+
+ arm,cs-dev-assoc:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ defines a phandle reference to an associated CoreSight trace device.
+ When the associated trace device is enabled, then the respective CTI
+ will be enabled. If the associated device has not been registered
+ then the node name will be stored as the connection name for later
+ resolution. If the associated device is not a CoreSight device or
+ not registered then the node name will remain the connection name
+ and automatic enabling will not occur.
+
arm,trig-in-sigs:
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
diff --git a/Documentation/devicetree/bindings/arm/arm,integrator.yaml b/Documentation/devicetree/bindings/arm/arm,integrator.yaml
index 98ff5698ae1f..1bdbd1b7ee38 100644
--- a/Documentation/devicetree/bindings/arm/arm,integrator.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,integrator.yaml
@@ -40,45 +40,6 @@ properties:
items:
- const: arm,integrator-sp
- core-module@10000000:
- type: object
- description: the root node in the Integrator platforms must contain
- a core module child node. They are always at physical address
- 0x10000000 in all the Integrator variants.
- properties:
- compatible:
- items:
- - const: arm,core-module-integrator
- - const: syscon
- - const: simple-mfd
- reg:
- maxItems: 1
-
- required:
- - compatible
- - reg
-
-patternProperties:
- "^syscon@[0-9a-f]+$":
- description: All Integrator boards must provide a system controller as a
- node in the root of the device tree.
- type: object
- properties:
- compatible:
- items:
- - enum:
- - arm,integrator-ap-syscon
- - arm,integrator-cp-syscon
- - arm,integrator-sp-syscon
- - const: syscon
- reg:
- maxItems: 1
-
- required:
- - compatible
- - reg
-
-
required:
- compatible
- core-module@10000000
diff --git a/Documentation/devicetree/bindings/arm/arm,realview.yaml b/Documentation/devicetree/bindings/arm/arm,realview.yaml
index 8d3ed2e4ed31..d1bdee98f9af 100644
--- a/Documentation/devicetree/bindings/arm/arm,realview.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,realview.yaml
@@ -75,43 +75,6 @@ properties:
type: object
description: All RealView boards must provide a syscon system controller
node inside the soc node.
- properties:
- compatible:
- oneOf:
- - items:
- - const: arm,realview-eb11mp-revb-syscon
- - const: arm,realview-eb-syscon
- - const: syscon
- - const: simple-mfd
- - items:
- - const: arm,realview-eb11mp-revc-syscon
- - const: arm,realview-eb-syscon
- - const: syscon
- - const: simple-mfd
- - items:
- - const: arm,realview-eb-syscon
- - const: syscon
- - const: simple-mfd
- - items:
- - const: arm,realview-pb1176-syscon
- - const: syscon
- - const: simple-mfd
- - items:
- - const: arm,realview-pb11mp-syscon
- - const: syscon
- - const: simple-mfd
- - items:
- - const: arm,realview-pba8-syscon
- - const: syscon
- - const: simple-mfd
- - items:
- - const: arm,realview-pbx-syscon
- - const: syscon
- - const: simple-mfd
-
- required:
- - compatible
- - reg
required:
- compatible
diff --git a/Documentation/devicetree/bindings/arm/arm,versatile.yaml b/Documentation/devicetree/bindings/arm/arm,versatile.yaml
index 13e52ba92060..7a3caf6af200 100644
--- a/Documentation/devicetree/bindings/arm/arm,versatile.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,versatile.yaml
@@ -14,6 +14,14 @@ description: |+
with various pluggable interface boards, in essence the Versatile PB version
is a superset of the Versatile AB version.
+ The root node in the Versatile platforms must contain a core module child
+ node. They are always at physical address 0x10000000 in all the Versatile
+ variants.
+
+ When fitted with the IB2 Interface Board, the Versatile AB will present an
+ optional system controller node which controls the extra peripherals on the
+ interface board.
+
properties:
$nodename:
const: '/'
@@ -32,38 +40,6 @@ properties:
items:
- const: arm,versatile-pb
- core-module@10000000:
- type: object
- description: the root node in the Versatile platforms must contain
- a core module child node. They are always at physical address
- 0x10000000 in all the Versatile variants.
- properties:
- compatible:
- items:
- - const: arm,core-module-versatile
- - const: syscon
- - const: simple-mfd
- reg:
- maxItems: 1
-
- required:
- - compatible
- - reg
-
-patternProperties:
- "^syscon@[0-9a-f]+$":
- type: object
- description: When fitted with the IB2 Interface Board, the Versatile
- AB will present an optional system controller node which controls the
- extra peripherals on the interface board.
- properties:
- compatible:
- contains:
- const: arm,versatile-ib2-syscon
- required:
- - compatible
- - reg
-
required:
- compatible
- core-module@10000000
diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
index 68f717670f78..749ee54a3ff8 100644
--- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
+++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
@@ -79,6 +79,7 @@ properties:
- facebook,elbert-bmc
- facebook,fuji-bmc
- facebook,greatlakes-bmc
+ - facebook,minerva-cmc
- facebook,yosemite4-bmc
- ibm,everest-bmc
- ibm,rainier-bmc
diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.yaml b/Documentation/devicetree/bindings/arm/atmel-at91.yaml
index dfb8fd089197..89d75fbb1de4 100644
--- a/Documentation/devicetree/bindings/arm/atmel-at91.yaml
+++ b/Documentation/devicetree/bindings/arm/atmel-at91.yaml
@@ -79,6 +79,13 @@ properties:
- const: atmel,sama5d2
- const: atmel,sama5
+ - description: Microchip SAMA5D29 Curiosity
+ items:
+ - const: microchip,sama5d29-curiosity
+ - const: atmel,sama5d29
+ - const: atmel,sama5d2
+ - const: atmel,sama5
+
- items:
- const: atmel,sama5d27
- const: atmel,sama5d2
diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml
index 0d17cbad9778..ffd526363fda 100644
--- a/Documentation/devicetree/bindings/arm/cpus.yaml
+++ b/Documentation/devicetree/bindings/arm/cpus.yaml
@@ -190,6 +190,7 @@ properties:
- qcom,kryo280
- qcom,kryo360
- qcom,kryo385
+ - qcom,kryo465
- qcom,kryo468
- qcom,kryo485
- qcom,kryo560
@@ -308,7 +309,9 @@ properties:
power-domains property.
For PSCI based platforms, the name corresponding to the index of the PSCI
- PM domain provider, must be "psci".
+ PM domain provider, must be "psci". For SCMI based platforms, the name
+ corresponding to the index of an SCMI performance domain provider, must be
+ "perf".
qcom,saw:
$ref: /schemas/types.yaml#/definitions/phandle
diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 9450b2c8a678..32b195852a75 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -25,8 +25,11 @@ properties:
- description: i.MX23 based Boards
items:
- enum:
+ - creative,x-fi3
- fsl,imx23-evk
+ - fsl,stmp378x-devb
- olimex,imx23-olinuxino
+ - sandisk,sansa_fuze_plus
- const: fsl,imx23
- description: i.MX25 Product Development Kit
@@ -385,6 +388,12 @@ properties:
- const: toradex,apalis_imx6q
- const: fsl,imx6q
+ - description: i.MX6Q Variscite VAR-SOM-MX6 Boards
+ items:
+ - const: variscite,mx6customboard
+ - const: variscite,var-som-imx6q
+ - const: fsl,imx6q
+
- description: TQ-Systems TQMa6Q SoM (variant A) on MBa6x
items:
- const: tq,imx6q-mba6x-a
@@ -975,7 +984,9 @@ properties:
- description: PHYTEC phyCORE-i.MX8MM SoM based boards
items:
- - const: phytec,imx8mm-phyboard-polis-rdk # phyBOARD-Polis RDK
+ - enum:
+ - phytec,imx8mm-phyboard-polis-rdk # phyBOARD-Polis RDK
+ - phytec,imx8mm-phygate-tauri-l # phyGATE-Tauri-L Gateway
- const: phytec,imx8mm-phycore-som # phyCORE-i.MX8MM SoM
- const: fsl,imx8mm
@@ -1389,6 +1400,13 @@ properties:
- fsl,ls1043a-qds
- const: fsl,ls1043a
+ - description: TQ-Systems LS1043A based Boards
+ items:
+ - enum:
+ - tq,ls1043a-tqmls1043a-mbls10xxa
+ - const: tq,ls1043a-tqmls1043a
+ - const: fsl,ls1043a
+
- description: LS1046A based Boards
items:
- enum:
@@ -1397,6 +1415,13 @@ properties:
- fsl,ls1046a-rdb
- const: fsl,ls1046a
+ - description: TQ-Systems LS1046A based Boards
+ items:
+ - enum:
+ - tq,ls1046a-tqmls1046a-mbls10xxa
+ - const: tq,ls1046a-tqmls1046a
+ - const: fsl,ls1046a
+
- description: LS1088A based Boards
items:
- enum:
@@ -1404,6 +1429,13 @@ properties:
- fsl,ls1088a-rdb
- const: fsl,ls1088a
+ - description: TQ-Systems LS1088A based Boards
+ items:
+ - enum:
+ - tq,ls1088a-tqmls1088a-mbls10xxa
+ - const: tq,ls1088a-tqmls1088a
+ - const: fsl,ls1088a
+
- description: LS2080A based Boards
items:
- enum:
@@ -1429,7 +1461,7 @@ properties:
- fsl,lx2162a-qds
- const: fsl,lx2160a
- - description: SolidRun LX2160A based Boards
+ - description: SolidRun LX2160A CEX-7 based Boards
items:
- enum:
- solidrun,clearfog-cx
@@ -1437,6 +1469,13 @@ properties:
- const: solidrun,lx2160a-cex7
- const: fsl,lx2160a
+ - description: SolidRun LX2162A SoM based Boards
+ items:
+ - enum:
+ - solidrun,lx2162a-clearfog
+ - const: solidrun,lx2162a-som
+ - const: fsl,lx2160a
+
- description: S32G2 based Boards
items:
- enum:
diff --git a/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml b/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
index 553dcbc70e35..d60792b1d995 100644
--- a/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
+++ b/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
@@ -16,12 +16,28 @@ properties:
oneOf:
- items:
- enum:
+ - adieng,coyote
+ - arcom,vulcan
+ - dlink,dsm-g600-a
+ - freecom,fsg-3
+ - gateway,7001
+ - gateworks,gw2348
+ - goramo,multilink-router
+ - intel,ixdp425
+ - intel,ixdpg425
+ - iom,nas-100d
- linksys,nslu2
+ - netgear,wg302v1
+ - netgear,wg302v2
+ - usr,8200
- welltech,epbx100
+ - linksys,wrv54g
+ - gemtek,gtwx5715
- const: intel,ixp42x
- items:
- enum:
- gateworks,gw2358
+ - intel,kixrp435
- const: intel,ixp43x
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/arm/mediatek.yaml b/Documentation/devicetree/bindings/arm/mediatek.yaml
index ae12b1cab9fb..a5999b3afc35 100644
--- a/Documentation/devicetree/bindings/arm/mediatek.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek.yaml
@@ -133,11 +133,22 @@ properties:
- enum:
- mediatek,mt8183-evb
- const: mediatek,mt8183
+ - description: Google Hayato rev5
+ items:
+ - const: google,hayato-rev5-sku2
+ - const: google,hayato-sku2
+ - const: google,hayato
+ - const: mediatek,mt8192
- description: Google Hayato
items:
- const: google,hayato-rev1
- const: google,hayato
- const: mediatek,mt8192
+ - description: Google Spherion rev4 (Acer Chromebook 514)
+ items:
+ - const: google,spherion-rev4
+ - const: google,spherion
+ - const: mediatek,mt8192
- description: Google Spherion (Acer Chromebook 514)
items:
- const: google,spherion-rev3
@@ -250,6 +261,11 @@ properties:
- const: mediatek,mt8365
- items:
- enum:
+ - mediatek,mt8395-evk
+ - const: mediatek,mt8395
+ - const: mediatek,mt8195
+ - items:
+ - enum:
- mediatek,mt8516-pumpkin
- const: mediatek,mt8516
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt7622-wed.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt7622-wed.yaml
index 28ded09d72e3..e7720caf31b3 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt7622-wed.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt7622-wed.yaml
@@ -22,6 +22,7 @@ properties:
- mediatek,mt7622-wed
- mediatek,mt7981-wed
- mediatek,mt7986-wed
+ - mediatek,mt7988-wed
- const: syscon
reg:
diff --git a/Documentation/devicetree/bindings/arm/psci.yaml b/Documentation/devicetree/bindings/arm/psci.yaml
index 0c5381e081bd..cbb012e217ab 100644
--- a/Documentation/devicetree/bindings/arm/psci.yaml
+++ b/Documentation/devicetree/bindings/arm/psci.yaml
@@ -101,6 +101,7 @@ properties:
patternProperties:
"^power-domain-":
$ref: /schemas/power/power-domain.yaml#
+ unevaluatedProperties: false
type: object
description: |
diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml
index adbfaea32343..7f80f48a0954 100644
--- a/Documentation/devicetree/bindings/arm/qcom.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom.yaml
@@ -50,6 +50,7 @@ description: |
msm8998
qcs404
qcm2290
+ qcm6490
qdu1000
qrb2210
qrb4210
@@ -79,6 +80,7 @@ description: |
sm6125
sm6350
sm6375
+ sm7125
sm7225
sm8150
sm8250
@@ -189,6 +191,7 @@ properties:
- items:
- enum:
+ - longcheer,l9100
- samsung,a7
- sony,kanuti-tulip
- square,apq8039-t2
@@ -391,6 +394,11 @@ properties:
- const: qcom,qrb2210
- const: qcom,qcm2290
+ - items:
+ - enum:
+ - fairphone,fp5
+ - const: qcom,qcm6490
+
- description: Qualcomm Technologies, Inc. Distributed Unit 1000 platform
items:
- enum:
@@ -479,6 +487,11 @@ properties:
- const: google,lazor-rev8
- const: qcom,sc7180
+ - description: Acer Chromebook Spin 513 (rev9)
+ items:
+ - const: google,lazor-rev9
+ - const: qcom,sc7180
+
- description: Acer Chromebook Spin 513 (newest rev)
items:
- const: google,lazor
@@ -500,6 +513,11 @@ properties:
- const: google,lazor-rev8-sku2
- const: qcom,sc7180
+ - description: Acer Chromebook Spin 513 with KB Backlight (rev9)
+ items:
+ - const: google,lazor-rev9-sku2
+ - const: qcom,sc7180
+
- description: Acer Chromebook Spin 513 with KB Backlight (newest rev)
items:
- const: google,lazor-sku2
@@ -521,9 +539,16 @@ properties:
- const: google,lazor-rev8-sku0
- const: qcom,sc7180
+ - description: Acer Chromebook Spin 513 with LTE (rev9)
+ items:
+ - const: google,lazor-rev9-sku0
+ - const: google,lazor-rev9-sku10
+ - const: qcom,sc7180
+
- description: Acer Chromebook Spin 513 with LTE (newest rev)
items:
- const: google,lazor-sku0
+ - const: google,lazor-sku10
- const: qcom,sc7180
- description: Acer Chromebook 511 (rev4 - rev8)
@@ -535,9 +560,16 @@ properties:
- const: google,lazor-rev8-sku4
- const: qcom,sc7180
+ - description: Acer Chromebook 511 (rev9)
+ items:
+ - const: google,lazor-rev9-sku4
+ - const: google,lazor-rev9-sku15
+ - const: qcom,sc7180
+
- description: Acer Chromebook 511 (newest rev)
items:
- const: google,lazor-sku4
+ - const: google,lazor-sku15
- const: qcom,sc7180
- description: Acer Chromebook 511 without Touchscreen (rev4)
@@ -554,9 +586,16 @@ properties:
- const: google,lazor-rev8-sku6
- const: qcom,sc7180
+ - description: Acer Chromebook 511 without Touchscreen (rev9)
+ items:
+ - const: google,lazor-rev9-sku6
+ - const: google,lazor-rev9-sku18
+ - const: qcom,sc7180
+
- description: Acer Chromebook 511 without Touchscreen (newest rev)
items:
- const: google,lazor-sku6
+ - const: google,lazor-sku18
- const: qcom,sc7180
- description: Google Mrbland with AUO panel (rev0)
@@ -945,6 +984,11 @@ properties:
- items:
- enum:
+ - xiaomi,joyeuse
+ - const: qcom,sm7125
+
+ - items:
+ - enum:
- fairphone,fp4
- const: qcom,sm7225
@@ -1086,6 +1130,7 @@ allOf:
- qcom,sm6115
- qcom,sm6125
- qcom,sm6350
+ - qcom,sm7125
- qcom,sm7225
- qcom,sm8150
- qcom,sm8250
diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
index ca5389862887..5f7c6c4aad8f 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.yaml
+++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
@@ -660,6 +660,11 @@ properties:
- pine64,quartz64-b
- const: rockchip,rk3566
+ - description: Pine64 QuartzPro64
+ items:
+ - const: pine64,quartzpro64
+ - const: rockchip,rk3588
+
- description: Pine64 SoQuartz SoM
items:
- enum:
@@ -669,6 +674,11 @@ properties:
- const: pine64,soquartz
- const: rockchip,rk3566
+ - description: Powkiddy RGB30
+ items:
+ - const: powkiddy,rgb30
+ - const: rockchip,rk3566
+
- description: Radxa Compute Module 3(CM3)
items:
- enum:
@@ -870,6 +880,16 @@ properties:
- const: tronsmart,orion-r68-meta
- const: rockchip,rk3368
+ - description: Turing RK1
+ items:
+ - const: turing,rk1
+ - const: rockchip,rk3588
+
+ - description: Xunlong Orange Pi 5 Plus
+ items:
+ - const: xunlong,orangepi-5-plus
+ - const: rockchip,rk3588
+
- description: Xunlong Orange Pi R1 Plus / LTS
items:
- enum:
@@ -877,6 +897,11 @@ properties:
- xunlong,orangepi-r1-plus-lts
- const: rockchip,rk3328
+ - description: Xunlong Orange Pi 5
+ items:
+ - const: xunlong,orangepi-5
+ - const: rockchip,rk3588s
+
- description: Zkmagic A95X Z2
items:
- const: zkmagic,a95x-z2
diff --git a/Documentation/devicetree/bindings/arm/sti.yaml b/Documentation/devicetree/bindings/arm/sti.yaml
index 3ca054c64377..842def3e3f2b 100644
--- a/Documentation/devicetree/bindings/arm/sti.yaml
+++ b/Documentation/devicetree/bindings/arm/sti.yaml
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/arm/sti.yaml#
@@ -13,13 +13,20 @@ properties:
$nodename:
const: '/'
compatible:
- items:
- - enum:
- - st,stih415
- - st,stih416
- - st,stih407
- - st,stih410
- - st,stih418
+ oneOf:
+ - items:
+ - const: st,stih407-b2120
+ - const: st,stih407
+ - items:
+ - enum:
+ - st,stih410-b2120
+ - st,stih410-b2260
+ - const: st,stih410
+ - items:
+ - enum:
+ - st,stih418-b2199
+ - st,stih418-b2264
+ - const: st,stih418
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
index 4bf28e717a56..df087c81c69e 100644
--- a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
+++ b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
@@ -146,6 +146,7 @@ properties:
- lxa,stm32mp157c-mc1 # Linux Automation MC-1
- lxa,stm32mp157c-tac-gen1 # Linux Automation TAC (Generation 1)
- lxa,stm32mp157c-tac-gen2 # Linux Automation TAC (Generation 2)
+ - oct,stm32mp157c-osd32-red # Octavo OSD32MP1 RED board
- const: oct,stm32mp15xx-osd32
- enum:
- st,stm32mp157
diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index e4dd678f4212..11c5ce941dd7 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -51,6 +51,11 @@ properties:
- const: allwinner,parrot
- const: allwinner,sun8i-a33
+ - description: Anbernic RG-Nano
+ items:
+ - const: anbernic,rg-nano
+ - const: allwinner,sun8i-v3s
+
- description: Amarula A64 Relic
items:
- const: amarula,a64-relic
@@ -151,6 +156,17 @@ properties:
- const: roofull,beelink-x2
- const: allwinner,sun8i-h3
+ - description: BigTreeTech Manta M4/8P
+ items:
+ - const: bigtreetech,cb1-manta
+ - const: bigtreetech,cb1
+ - const: allwinner,sun50i-h616
+
+ - description: BigTreeTech Pi
+ items:
+ - const: bigtreetech,pi
+ - const: allwinner,sun50i-h616
+
- description: Chuwi V7 CW0825
items:
- const: chuwi,v7-cw0825
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml
deleted file mode 100644
index 89191cfdf619..000000000000
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml
+++ /dev/null
@@ -1,393 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/arm/tegra/nvidia,tegra20-pmc.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Tegra Power Management Controller (PMC)
-
-maintainers:
- - Thierry Reding <thierry.reding@gmail.com>
- - Jonathan Hunter <jonathanh@nvidia.com>
-
-properties:
- compatible:
- enum:
- - nvidia,tegra20-pmc
- - nvidia,tegra30-pmc
- - nvidia,tegra114-pmc
- - nvidia,tegra124-pmc
- - nvidia,tegra210-pmc
-
- reg:
- maxItems: 1
- description:
- Offset and length of the register set for the device.
-
- clock-names:
- items:
- - const: pclk
- - const: clk32k_in
- description:
- Must includes entries pclk and clk32k_in.
- pclk is the Tegra clock of that name and clk32k_in is 32KHz clock
- input to Tegra.
-
- clocks:
- maxItems: 2
- description:
- Must contain an entry for each entry in clock-names.
- See ../clocks/clocks-bindings.txt for details.
-
- '#clock-cells':
- const: 1
- description:
- Tegra PMC has clk_out_1, clk_out_2, and clk_out_3.
- PMC also has blink control which allows 32Khz clock output to
- Tegra blink pad.
- Consumer of PMC clock should specify the desired clock by having
- the clock ID in its "clocks" phandle cell with pmc clock provider.
- See include/dt-bindings/soc/tegra-pmc.h for the list of Tegra PMC
- clock IDs.
-
- '#interrupt-cells':
- const: 2
- description:
- Specifies number of cells needed to encode an interrupt source.
- The value must be 2.
-
- interrupt-controller: true
-
- nvidia,invert-interrupt:
- $ref: /schemas/types.yaml#/definitions/flag
- description: Inverts the PMU interrupt signal.
- The PMU is an external Power Management Unit, whose interrupt output
- signal is fed into the PMC. This signal is optionally inverted, and
- then fed into the ARM GIC. The PMC is not involved in the detection
- or handling of this interrupt signal, merely its inversion.
-
- nvidia,core-power-req-active-high:
- $ref: /schemas/types.yaml#/definitions/flag
- description: Core power request active-high.
-
- nvidia,sys-clock-req-active-high:
- $ref: /schemas/types.yaml#/definitions/flag
- description: System clock request active-high.
-
- nvidia,combined-power-req:
- $ref: /schemas/types.yaml#/definitions/flag
- description: combined power request for CPU and Core.
-
- nvidia,cpu-pwr-good-en:
- $ref: /schemas/types.yaml#/definitions/flag
- description:
- CPU power good signal from external PMIC to PMC is enabled.
-
- nvidia,suspend-mode:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [0, 1, 2]
- description:
- The suspend mode that the platform should use.
- Mode 0 is for LP0, CPU + Core voltage off and DRAM in self-refresh
- Mode 1 is for LP1, CPU voltage off and DRAM in self-refresh
- Mode 2 is for LP2, CPU voltage off
-
- nvidia,cpu-pwr-good-time:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: CPU power good time in uSec.
-
- nvidia,cpu-pwr-off-time:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: CPU power off time in uSec.
-
- nvidia,core-pwr-good-time:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- description:
- <Oscillator-stable-time Power-stable-time>
- Core power good time in uSec.
-
- nvidia,core-pwr-off-time:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: Core power off time in uSec.
-
- nvidia,lp0-vec:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- description:
- <start length> Starting address and length of LP0 vector.
- The LP0 vector contains the warm boot code that is executed
- by AVP when resuming from the LP0 state.
- The AVP (Audio-Video Processor) is an ARM7 processor and
- always being the first boot processor when chip is power on
- or resume from deep sleep mode. When the system is resumed
- from the deep sleep mode, the warm boot code will restore
- some PLLs, clocks and then brings up CPU0 for resuming the
- system.
-
- core-supply:
- description:
- Phandle to voltage regulator connected to the SoC Core power rail.
-
- core-domain:
- type: object
- description: |
- The vast majority of hardware blocks of Tegra SoC belong to a
- Core power domain, which has a dedicated voltage rail that powers
- the blocks.
-
- properties:
- operating-points-v2:
- description:
- Should contain level, voltages and opp-supported-hw property.
- The supported-hw is a bitfield indicating SoC speedo or process
- ID mask.
-
- "#power-domain-cells":
- const: 0
-
- required:
- - operating-points-v2
- - "#power-domain-cells"
-
- additionalProperties: false
-
- i2c-thermtrip:
- type: object
- description:
- On Tegra30, Tegra114 and Tegra124 if i2c-thermtrip subnode exists,
- hardware-triggered thermal reset will be enabled.
-
- properties:
- nvidia,i2c-controller-id:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
- ID of I2C controller to send poweroff command to PMU.
- Valid values are described in section 9.2.148
- "APBDEV_PMC_SCRATCH53_0" of the Tegra K1 Technical Reference
- Manual.
-
- nvidia,bus-addr:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: Bus address of the PMU on the I2C bus.
-
- nvidia,reg-addr:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: PMU I2C register address to issue poweroff command.
-
- nvidia,reg-data:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: Poweroff command to write to PMU.
-
- nvidia,pinmux-id:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
- Pinmux used by the hardware when issuing Poweroff command.
- Defaults to 0. Valid values are described in section 12.5.2
- "Pinmux Support" of the Tegra4 Technical Reference Manual.
-
- required:
- - nvidia,i2c-controller-id
- - nvidia,bus-addr
- - nvidia,reg-addr
- - nvidia,reg-data
-
- additionalProperties: false
-
- powergates:
- type: object
- description: |
- This node contains a hierarchy of power domain nodes, which should
- match the powergates on the Tegra SoC. Each powergate node
- represents a power-domain on the Tegra SoC that can be power-gated
- by the Tegra PMC.
- Hardware blocks belonging to a power domain should contain
- "power-domains" property that is a phandle pointing to corresponding
- powergate node.
- The name of the powergate node should be one of the below. Note that
- not every powergate is applicable to all Tegra devices and the following
- list shows which powergates are applicable to which devices.
- Please refer to Tegra TRM for mode details on the powergate nodes to
- use for each power-gate block inside Tegra.
- Name Description Devices Applicable
- 3d 3D Graphics Tegra20/114/124/210
- 3d0 3D Graphics 0 Tegra30
- 3d1 3D Graphics 1 Tegra30
- aud Audio Tegra210
- dfd Debug Tegra210
- dis Display A Tegra114/124/210
- disb Display B Tegra114/124/210
- heg 2D Graphics Tegra30/114/124/210
- iram Internal RAM Tegra124/210
- mpe MPEG Encode All
- nvdec NVIDIA Video Decode Engine Tegra210
- nvjpg NVIDIA JPEG Engine Tegra210
- pcie PCIE Tegra20/30/124/210
- sata SATA Tegra30/124/210
- sor Display interfaces Tegra124/210
- ve2 Video Encode Engine 2 Tegra210
- venc Video Encode Engine All
- vdec Video Decode Engine Tegra20/30/114/124
- vic Video Imaging Compositor Tegra124/210
- xusba USB Partition A Tegra114/124/210
- xusbb USB Partition B Tegra114/124/210
- xusbc USB Partition C Tegra114/124/210
-
- patternProperties:
- "^[a-z0-9]+$":
- type: object
- additionalProperties: false
-
- properties:
- clocks:
- minItems: 1
- maxItems: 8
- description:
- Must contain an entry for each clock required by the PMC
- for controlling a power-gate.
- See ../clocks/clock-bindings.txt document for more details.
-
- resets:
- minItems: 1
- maxItems: 8
- description:
- Must contain an entry for each reset required by the PMC
- for controlling a power-gate.
- See ../reset/reset.txt for more details.
-
- power-domains:
- maxItems: 1
-
- '#power-domain-cells':
- const: 0
- description: Must be 0.
-
- required:
- - clocks
- - resets
- - '#power-domain-cells'
-
- additionalProperties: false
-
-patternProperties:
- "^[a-f0-9]+-[a-f0-9]+$":
- type: object
- description:
- This is a Pad configuration node. On Tegra SOCs a pad is a set of
- pins which are configured as a group. The pin grouping is a fixed
- attribute of the hardware. The PMC can be used to set pad power state
- and signaling voltage. A pad can be either in active or power down mode.
- The support for power state and signaling voltage configuration varies
- depending on the pad in question. 3.3V and 1.8V signaling voltages
- are supported on pins where software controllable signaling voltage
- switching is available.
-
- The pad configuration state nodes are placed under the pmc node and they
- are referred to by the pinctrl client properties. For more information
- see Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
- The pad name should be used as the value of the pins property in pin
- configuration nodes.
-
- The following pads are present on Tegra124 and Tegra132
- audio, bb, cam, comp, csia, csb, cse, dsi, dsib, dsic, dsid, hdmi, hsic,
- hv, lvds, mipi-bias, nand, pex-bias, pex-clk1, pex-clk2, pex-cntrl,
- sdmmc1, sdmmc3, sdmmc4, sys_ddc, uart, usb0, usb1, usb2, usb_bias.
-
- The following pads are present on Tegra210
- audio, audio-hv, cam, csia, csib, csic, csid, csie, csif, dbg,
- debug-nonao, dmic, dp, dsi, dsib, dsic, dsid, emmc, emmc2, gpio, hdmi,
- hsic, lvds, mipi-bias, pex-bias, pex-clk1, pex-clk2, pex-cntrl, sdmmc1,
- sdmmc3, spi, spi-hv, uart, usb0, usb1, usb2, usb3, usb-bias.
-
- properties:
- pins:
- $ref: /schemas/types.yaml#/definitions/string
- description: Must contain name of the pad(s) to be configured.
-
- low-power-enable:
- $ref: /schemas/types.yaml#/definitions/flag
- description: Configure the pad into power down mode.
-
- low-power-disable:
- $ref: /schemas/types.yaml#/definitions/flag
- description: Configure the pad into active mode.
-
- power-source:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
- Must contain either TEGRA_IO_PAD_VOLTAGE_1V8 or
- TEGRA_IO_PAD_VOLTAGE_3V3 to select between signaling voltages.
- The values are defined in
- include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.
- Power state can be configured on all Tegra124 and Tegra132
- pads. None of the Tegra124 or Tegra132 pads support signaling
- voltage switching.
- All of the listed Tegra210 pads except pex-cntrl support power
- state configuration. Signaling voltage switching is supported
- on below Tegra210 pads.
- audio, audio-hv, cam, dbg, dmic, gpio, pex-cntrl, sdmmc1,
- sdmmc3, spi, spi-hv, and uart.
-
- required:
- - pins
-
- additionalProperties: false
-
-required:
- - compatible
- - reg
- - clock-names
- - clocks
- - '#clock-cells'
-
-additionalProperties: false
-
-dependencies:
- "nvidia,suspend-mode": ["nvidia,core-pwr-off-time", "nvidia,cpu-pwr-off-time"]
- "nvidia,core-pwr-off-time": ["nvidia,core-pwr-good-time"]
- "nvidia,cpu-pwr-off-time": ["nvidia,cpu-pwr-good-time"]
-
-examples:
- - |
-
- #include <dt-bindings/clock/tegra210-car.h>
- #include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
- #include <dt-bindings/soc/tegra-pmc.h>
-
- tegra_pmc: pmc@7000e400 {
- compatible = "nvidia,tegra210-pmc";
- reg = <0x7000e400 0x400>;
- core-supply = <&regulator>;
- clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
- clock-names = "pclk", "clk32k_in";
- #clock-cells = <1>;
-
- nvidia,invert-interrupt;
- nvidia,suspend-mode = <0>;
- nvidia,cpu-pwr-good-time = <0>;
- nvidia,cpu-pwr-off-time = <0>;
- nvidia,core-pwr-good-time = <4587 3876>;
- nvidia,core-pwr-off-time = <39065>;
- nvidia,core-power-req-active-high;
- nvidia,sys-clock-req-active-high;
-
- pd_core: core-domain {
- operating-points-v2 = <&core_opp_table>;
- #power-domain-cells = <0>;
- };
-
- powergates {
- pd_audio: aud {
- clocks = <&tegra_car TEGRA210_CLK_APE>,
- <&tegra_car TEGRA210_CLK_APB2APE>;
- resets = <&tegra_car 198>;
- power-domains = <&pd_core>;
- #power-domain-cells = <0>;
- };
-
- pd_xusbss: xusba {
- clocks = <&tegra_car TEGRA210_CLK_XUSB_SS>;
- resets = <&tegra_car TEGRA210_CLK_XUSB_SS>;
- power-domains = <&pd_core>;
- #power-domain-cells = <0>;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/ata/nvidia,tegra-ahci.yaml b/Documentation/devicetree/bindings/ata/nvidia,tegra-ahci.yaml
index 3c7a2425f3e6..a17297cbefcb 100644
--- a/Documentation/devicetree/bindings/ata/nvidia,tegra-ahci.yaml
+++ b/Documentation/devicetree/bindings/ata/nvidia,tegra-ahci.yaml
@@ -151,7 +151,7 @@ allOf:
- interconnects
- power-domains
-additionalProperties: true
+additionalProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml
index 44892aa589fd..580f9a97ddf7 100644
--- a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml
+++ b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml
@@ -20,6 +20,7 @@ description: |
properties:
compatible:
enum:
+ - qcom,qdu1000-llcc
- qcom,sc7180-llcc
- qcom,sc7280-llcc
- qcom,sc8180x-llcc
@@ -44,6 +45,14 @@ properties:
interrupts:
maxItems: 1
+ nvmem-cells:
+ items:
+ - description: Reference to an nvmem node for multi channel DDR
+
+ nvmem-cell-names:
+ items:
+ - const: multi-chan-ddr
+
required:
- compatible
- reg
@@ -92,6 +101,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,qdu1000-llcc
- qcom,sc8180x-llcc
- qcom,sc8280xp-llcc
then:
diff --git a/Documentation/devicetree/bindings/clock/amlogic,s4-peripherals-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,s4-peripherals-clkc.yaml
new file mode 100644
index 000000000000..c229e4f0c1d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,s4-peripherals-clkc.yaml
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2022-2023 Amlogic, Inc. All rights reserved
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/amlogic,s4-peripherals-clkc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic S4 Peripherals Clock Controller
+
+maintainers:
+ - Yu Tu <yu.tu@amlogic.com>
+
+properties:
+ compatible:
+ const: amlogic,s4-peripherals-clkc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ minItems: 14
+ items:
+ - description: input fixed pll div2
+ - description: input fixed pll div2p5
+ - description: input fixed pll div3
+ - description: input fixed pll div4
+ - description: input fixed pll div5
+ - description: input fixed pll div7
+ - description: input hifi pll
+ - description: input gp0 pll
+ - description: input mpll0
+ - description: input mpll1
+ - description: input mpll2
+ - description: input mpll3
+ - description: input hdmi pll
+ - description: input oscillator (usually at 24MHz)
+ - description: input external 32kHz reference (optional)
+
+ clock-names:
+ minItems: 14
+ items:
+ - const: fclk_div2
+ - const: fclk_div2p5
+ - const: fclk_div3
+ - const: fclk_div4
+ - const: fclk_div5
+ - const: fclk_div7
+ - const: hifi_pll
+ - const: gp0_pll
+ - const: mpll0
+ - const: mpll1
+ - const: mpll2
+ - const: mpll3
+ - const: hdmi_pll
+ - const: xtal
+ - const: ext_32k
+
+ "#clock-cells":
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/amlogic,s4-peripherals-clkc.h>
+
+ clkc_periphs: clock-controller@fe000000 {
+ compatible = "amlogic,s4-peripherals-clkc";
+ reg = <0xfe000000 0x49c>;
+ clocks = <&clkc_pll 3>,
+ <&clkc_pll 13>,
+ <&clkc_pll 5>,
+ <&clkc_pll 7>,
+ <&clkc_pll 9>,
+ <&clkc_pll 11>,
+ <&clkc_pll 17>,
+ <&clkc_pll 15>,
+ <&clkc_pll 25>,
+ <&clkc_pll 27>,
+ <&clkc_pll 29>,
+ <&clkc_pll 31>,
+ <&clkc_pll 20>,
+ <&xtal>;
+ clock-names = "fclk_div2", "fclk_div2p5", "fclk_div3", "fclk_div4",
+ "fclk_div5", "fclk_div7", "hifi_pll", "gp0_pll",
+ "mpll0", "mpll1", "mpll2", "mpll3", "hdmi_pll", "xtal";
+ #clock-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/amlogic,s4-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,s4-pll-clkc.yaml
new file mode 100644
index 000000000000..d8932ec26ca8
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,s4-pll-clkc.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2022-2023 Amlogic, Inc. All rights reserved
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/amlogic,s4-pll-clkc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic S4 PLL Clock Controller
+
+maintainers:
+ - Yu Tu <yu.tu@amlogic.com>
+
+properties:
+ compatible:
+ const: amlogic,s4-pll-clkc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: xtal
+
+ "#clock-cells":
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ clkc_pll: clock-controller@fe008000 {
+ compatible = "amlogic,s4-pll-clkc";
+ reg = <0xfe008000 0x1e8>;
+ clocks = <&xtal>;
+ clock-names = "xtal";
+ #clock-cells = <1>;
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,hfpll.txt b/Documentation/devicetree/bindings/clock/qcom,hfpll.txt
index ec02a024424c..5769cbbe76be 100644
--- a/Documentation/devicetree/bindings/clock/qcom,hfpll.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,hfpll.txt
@@ -12,6 +12,9 @@ PROPERTIES
"qcom,hfpll-apq8064", "qcom,hfpll"
"qcom,hfpll-msm8974", "qcom,hfpll"
"qcom,hfpll-msm8960", "qcom,hfpll"
+ "qcom,msm8976-hfpll-a53", "qcom,hfpll"
+ "qcom,msm8976-hfpll-a72", "qcom,hfpll"
+ "qcom,msm8976-hfpll-cci", "qcom,hfpll"
- reg:
Usage: required
diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
index fd14d18309a8..4eb5e59f6772 100644
--- a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
@@ -28,6 +28,7 @@ properties:
- qcom,sdx55-rpmh-clk
- qcom,sdx65-rpmh-clk
- qcom,sdx75-rpmh-clk
+ - qcom,sm4450-rpmh-clk
- qcom,sm6350-rpmh-clk
- qcom,sm8150-rpmh-clk
- qcom,sm8250-rpmh-clk
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm4450-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm4450-gcc.yaml
new file mode 100644
index 000000000000..5953c8d92436
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sm4450-gcc.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,sm4450-gcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Global Clock & Reset Controller on SM4450
+
+maintainers:
+ - Ajit Pandey <quic_ajipan@quicinc.com>
+ - Taniya Das <quic_tdas@quicinc.com>
+
+description: |
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SM4450
+
+ See also:: include/dt-bindings/clock/qcom,sm4450-gcc.h
+
+properties:
+ compatible:
+ const: qcom,sm4450-gcc
+
+ clocks:
+ items:
+ - description: Board XO source
+ - description: Sleep clock source
+ - description: UFS Phy Rx symbol 0 clock source
+ - description: UFS Phy Rx symbol 1 clock source
+ - description: UFS Phy Tx symbol 0 clock source
+ - description: USB3 Phy wrapper pipe clock source
+
+required:
+ - compatible
+ - clocks
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ clock-controller@100000 {
+ compatible = "qcom,sm4450-gcc";
+ reg = <0x00100000 0x001f4200>;
+ clocks = <&rpmhcc RPMH_CXO_CLK>, <&sleep_clk>,
+ <&ufs_mem_phy 0>, <&ufs_mem_phy 1>,
+ <&ufs_mem_phy 2>, <&usb_1_qmpphy>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml
index 8178c35bc348..dc3c18e4ead7 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml
@@ -13,11 +13,15 @@ description: |
Qualcomm camera clock control module provides the clocks, resets and power
domains on SM8450.
- See also:: include/dt-bindings/clock/qcom,sm8450-camcc.h
+ See also::
+ include/dt-bindings/clock/qcom,sm8450-camcc.h
+ include/dt-bindings/clock/qcom,sm8550-camcc.h
properties:
compatible:
- const: qcom,sm8450-camcc
+ enum:
+ - qcom,sm8450-camcc
+ - qcom,sm8550-camcc
clocks:
items:
diff --git a/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml b/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml
index fe2fba18ae84..80a8c7114c31 100644
--- a/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml
+++ b/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml
@@ -27,6 +27,7 @@ properties:
- renesas,r9a07g043-cpg # RZ/G2UL{Type-1,Type-2} and RZ/Five
- renesas,r9a07g044-cpg # RZ/G2{L,LC}
- renesas,r9a07g054-cpg # RZ/V2L
+ - renesas,r9a08g045-cpg # RZ/G3S
- renesas,r9a09g011-cpg # RZ/V2M
reg:
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
index c1d225fcf2d5..56fc71d6a081 100644
--- a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
@@ -23,6 +23,7 @@ properties:
- enum:
- qcom,qcm2290-cpufreq-hw
- qcom,sc7180-cpufreq-hw
+ - qcom,sdm670-cpufreq-hw
- qcom,sdm845-cpufreq-hw
- qcom,sm6115-cpufreq-hw
- qcom,sm6350-cpufreq-hw
@@ -36,11 +37,13 @@ properties:
- qcom,sa8775p-cpufreq-epss
- qcom,sc7280-cpufreq-epss
- qcom,sc8280xp-cpufreq-epss
+ - qcom,sdx75-cpufreq-epss
- qcom,sm6375-cpufreq-epss
- qcom,sm8250-cpufreq-epss
- qcom,sm8350-cpufreq-epss
- qcom,sm8450-cpufreq-epss
- qcom,sm8550-cpufreq-epss
+ - qcom,sm8650-cpufreq-epss
- const: qcom,cpufreq-epss
reg:
@@ -128,6 +131,7 @@ allOf:
- qcom,qdu1000-cpufreq-epss
- qcom,sc7180-cpufreq-hw
- qcom,sc8280xp-cpufreq-epss
+ - qcom,sdm670-cpufreq-hw
- qcom,sdm845-cpufreq-hw
- qcom,sm6115-cpufreq-hw
- qcom,sm6350-cpufreq-hw
diff --git a/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml b/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml
index 7e1bb992ce90..547265b8b118 100644
--- a/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml
+++ b/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml
@@ -27,8 +27,12 @@ select:
enum:
- qcom,apq8064
- qcom,apq8096
+ - qcom,ipq5332
+ - qcom,ipq6018
- qcom,ipq8064
- qcom,ipq8074
+ - qcom,ipq9574
+ - qcom,msm8909
- qcom,msm8939
- qcom,msm8960
- qcom,msm8974
@@ -43,7 +47,9 @@ patternProperties:
- if:
properties:
compatible:
- const: operating-points-v2-kryo-cpu
+ enum:
+ - operating-points-v2-krait-cpu
+ - operating-points-v2-kryo-cpu
then:
$ref: /schemas/opp/opp-v2-kryo-cpu.yaml#
diff --git a/Documentation/devicetree/bindings/crypto/fsl-imx-sahara.yaml b/Documentation/devicetree/bindings/crypto/fsl-imx-sahara.yaml
index d531f3af3ea4..41df80bcdcd9 100644
--- a/Documentation/devicetree/bindings/crypto/fsl-imx-sahara.yaml
+++ b/Documentation/devicetree/bindings/crypto/fsl-imx-sahara.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/crypto/fsl-imx-sahara.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Freescale SAHARA Cryptographic Accelerator included in some i.MX chips
+title: Freescale SAHARA Cryptographic Accelerator
maintainers:
- Steffen Trumtrar <s.trumtrar@pengutronix.de>
@@ -19,19 +19,56 @@ properties:
maxItems: 1
interrupts:
- maxItems: 1
+ items:
+ - description: SAHARA Interrupt for Host 0
+ - description: SAHARA Interrupt for Host 1
+ minItems: 1
+
+ clocks:
+ items:
+ - description: Sahara IPG clock
+ - description: Sahara AHB clock
+
+ clock-names:
+ items:
+ - const: ipg
+ - const: ahb
required:
- compatible
- reg
- interrupts
+ - clocks
+ - clock-names
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx53-sahara
+ then:
+ properties:
+ interrupts:
+ minItems: 2
+ maxItems: 2
+ else:
+ properties:
+ interrupts:
+ maxItems: 1
additionalProperties: false
examples:
- |
+ #include <dt-bindings/clock/imx27-clock.h>
+
crypto@10025000 {
compatible = "fsl,imx27-sahara";
- reg = < 0x10025000 0x800>;
+ reg = <0x10025000 0x800>;
interrupts = <75>;
+ clocks = <&clks IMX27_CLK_SAHARA_IPG_GATE>,
+ <&clks IMX27_CLK_SAHARA_AHB_GATE>;
+ clock-names = "ipg", "ahb";
};
diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
index 7da9aa82d837..ca4f7d1cefaa 100644
--- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
+++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
@@ -13,6 +13,7 @@ properties:
compatible:
items:
- enum:
+ - qcom,sa8775p-inline-crypto-engine
- qcom,sm8450-inline-crypto-engine
- qcom,sm8550-inline-crypto-engine
- const: qcom,inline-crypto-engine
diff --git a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml
index bb42f4588b40..13070db0f70c 100644
--- a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml
+++ b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml
@@ -11,9 +11,17 @@ maintainers:
properties:
compatible:
- enum:
- - qcom,prng # 8916 etc.
- - qcom,prng-ee # 8996 and later using EE
+ oneOf:
+ - enum:
+ - qcom,prng # 8916 etc.
+ - qcom,prng-ee # 8996 and later using EE
+ - items:
+ - enum:
+ - qcom,sa8775p-trng
+ - qcom,sc7280-trng
+ - qcom,sm8450-trng
+ - qcom,sm8550-trng
+ - const: qcom,trng
reg:
maxItems: 1
@@ -28,8 +36,18 @@ properties:
required:
- compatible
- reg
- - clocks
- - clock-names
+
+allOf:
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ const: qcom,trng
+ then:
+ required:
+ - clocks
+ - clock-names
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip,dfi.yaml b/Documentation/devicetree/bindings/devfreq/event/rockchip,dfi.yaml
new file mode 100644
index 000000000000..50d3fabe958d
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/event/rockchip,dfi.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/devfreq/event/rockchip,dfi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip DFI
+
+maintainers:
+ - Sascha Hauer <s.hauer@pengutronix.de>
+
+properties:
+ compatible:
+ enum:
+ - rockchip,rk3399-dfi
+ - rockchip,rk3568-dfi
+ - rockchip,rk3588-dfi
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: pclk_ddr_mon
+
+ interrupts:
+ minItems: 1
+ maxItems: 4
+
+ reg:
+ maxItems: 1
+
+ rockchip,pmu:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the syscon managing the "PMU general register files".
+
+required:
+ - compatible
+ - interrupts
+ - reg
+
+if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - rockchip,rk3399-dfi
+
+then:
+ required:
+ - clocks
+ - clock-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/rk3308-cru.h>
+
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ dfi: dfi@ff630000 {
+ compatible = "rockchip,rk3399-dfi";
+ reg = <0x00 0xff630000 0x00 0x4000>;
+ interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH 0>;
+ rockchip,pmu = <&pmugrf>;
+ clocks = <&cru PCLK_DDR_MON>;
+ clock-names = "pclk_ddr_mon";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
deleted file mode 100644
index 148191b0fc15..000000000000
--- a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-
-* Rockchip rk3399 DFI device
-
-Required properties:
-- compatible: Must be "rockchip,rk3399-dfi".
-- reg: physical base address of each DFI and length of memory mapped region
-- rockchip,pmu: phandle to the syscon managing the "pmu general register files"
-- clocks: phandles for clock specified in "clock-names" property
-- clock-names : the name of clock used by the DFI, must be "pclk_ddr_mon";
-
-Example:
- dfi: dfi@ff630000 {
- compatible = "rockchip,rk3399-dfi";
- reg = <0x00 0xff630000 0x00 0x4000>;
- rockchip,pmu = <&pmugrf>;
- clocks = <&cru PCLK_DDR_MON>;
- clock-names = "pclk_ddr_mon";
- };
diff --git a/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml b/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml
index 987aa83c2649..df20a3c9c744 100644
--- a/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml
@@ -9,6 +9,9 @@ title: Analog Devices ADV7533/35 HDMI Encoders
maintainers:
- Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+allOf:
+ - $ref: /schemas/sound/dai-common.yaml#
+
description: |
The ADV7533 and ADV7535 are HDMI audio and video transmitters
compatible with HDMI 1.4 and DVI 1.0. They support color space
@@ -89,6 +92,9 @@ properties:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [ 1, 2, 3, 4 ]
+ "#sound-dai-cells":
+ const: 0
+
ports:
description:
The ADV7533/35 has two video ports and one audio port.
diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7814.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7814.yaml
index 4a5e5d9d6f90..4509c496731b 100644
--- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7814.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7814.yaml
@@ -17,6 +17,7 @@ properties:
- analogix,anx7808
- analogix,anx7812
- analogix,anx7814
+ - analogix,anx7816
- analogix,anx7818
reg:
diff --git a/Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml b/Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml
new file mode 100644
index 000000000000..d6e51d0cf546
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml
@@ -0,0 +1,115 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/fsl,imx93-mipi-dsi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX93 specific extensions to Synopsys Designware MIPI DSI
+
+maintainers:
+ - Liu Ying <victor.liu@nxp.com>
+
+description: |
+ There is a Synopsys Designware MIPI DSI Host Controller and a Synopsys
+ Designware MIPI DPHY embedded in Freescale i.MX93 SoC. Some configurations
+ and extensions to them are controlled by i.MX93 media blk-ctrl.
+
+allOf:
+ - $ref: snps,dw-mipi-dsi.yaml#
+
+properties:
+ compatible:
+ const: fsl,imx93-mipi-dsi
+
+ clocks:
+ items:
+ - description: apb clock
+ - description: pixel clock
+ - description: PHY configuration clock
+ - description: PHY reference clock
+
+ clock-names:
+ items:
+ - const: pclk
+ - const: pix
+ - const: phy_cfg
+ - const: phy_ref
+
+ interrupts:
+ maxItems: 1
+
+ fsl,media-blk-ctrl:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ i.MX93 media blk-ctrl, as a syscon, controls pixel component bit map
+ configurations from LCDIF display controller to the MIPI DSI host
+ controller and MIPI DPHY PLL related configurations through PLL SoC
+ interface.
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - interrupts
+ - fsl,media-blk-ctrl
+ - power-domains
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/imx93-clock.h>
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/power/fsl,imx93-power.h>
+
+ dsi@4ae10000 {
+ compatible = "fsl,imx93-mipi-dsi";
+ reg = <0x4ae10000 0x10000>;
+ interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX93_CLK_MIPI_DSI_GATE>,
+ <&clk IMX93_CLK_MEDIA_DISP_PIX>,
+ <&clk IMX93_CLK_MIPI_PHY_CFG>,
+ <&clk IMX93_CLK_24M>;
+ clock-names = "pclk", "pix", "phy_cfg", "phy_ref";
+ fsl,media-blk-ctrl = <&media_blk_ctrl>;
+ power-domains = <&media_blk_ctrl IMX93_MEDIABLK_PD_MIPI_DSI>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "raydium,rm67191";
+ reg = <0>;
+ reset-gpios = <&adp5585gpio 6 GPIO_ACTIVE_LOW>;
+ dsi-lanes = <4>;
+ video-mode = <2>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&dsi_out>;
+ };
+ };
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ dsi_to_lcdif: endpoint {
+ remote-endpoint = <&lcdif_to_dsi>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ dsi_out: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
index fc11ab5fc465..1c2be8d6f633 100644
--- a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
+++ b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
@@ -51,7 +51,10 @@ properties:
minItems: 1
interrupts:
- maxItems: 1
+ items:
+ - description: LCDIF DMA interrupt
+ - description: LCDIF Error interrupt
+ minItems: 1
power-domains:
maxItems: 1
@@ -131,6 +134,21 @@ allOf:
then:
required:
- power-domains
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx23-lcdif
+ then:
+ properties:
+ interrupts:
+ minItems: 2
+ maxItems: 2
+ else:
+ properties:
+ interrupts:
+ maxItems: 1
examples:
- |
diff --git a/Documentation/devicetree/bindings/display/ilitek,ili9486.yaml b/Documentation/devicetree/bindings/display/ilitek,ili9486.yaml
index 1f8f2182e2f1..9cc1fd0751cd 100644
--- a/Documentation/devicetree/bindings/display/ilitek,ili9486.yaml
+++ b/Documentation/devicetree/bindings/display/ilitek,ili9486.yaml
@@ -50,10 +50,6 @@ examples:
- |
#include <dt-bindings/gpio/gpio.h>
- backlight: backlight {
- compatible = "gpio-backlight";
- gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
- };
spi {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/display/lvds-data-mapping.yaml b/Documentation/devicetree/bindings/display/lvds-data-mapping.yaml
new file mode 100644
index 000000000000..d68982fe2e9b
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/lvds-data-mapping.yaml
@@ -0,0 +1,84 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/lvds-data-mapping.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LVDS Data Mapping
+
+maintainers:
+ - Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+ - Thierry Reding <thierry.reding@gmail.com>
+
+description: |
+ LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple
+ incompatible data link layers have been used over time to transmit image data
+ to LVDS devices. This bindings supports devices compatible with the following
+ specifications.
+
+ [JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February
+ 1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA)
+ [LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National
+ Semiconductor
+ [VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
+ Electronics Standards Association (VESA)
+
+ Device compatible with those specifications have been marketed under the
+ FPD-Link and FlatLink brands.
+
+properties:
+ data-mapping:
+ enum:
+ - jeida-18
+ - jeida-24
+ - vesa-24
+ description: |
+ The color signals mapping order.
+
+ LVDS data mappings are defined as follows.
+
+ - "jeida-18" - 18-bit data mapping compatible with the [JEIDA], [LDI] and
+ [VESA] specifications. Data are transferred as follows on 3 LVDS lanes.
+
+ Slot 0 1 2 3 4 5 6
+ ________________ _________________
+ Clock \_______________________/
+ ______ ______ ______ ______ ______ ______ ______
+ DATA0 ><__G0__><__R5__><__R4__><__R3__><__R2__><__R1__><__R0__><
+ DATA1 ><__B1__><__B0__><__G5__><__G4__><__G3__><__G2__><__G1__><
+ DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B5__><__B4__><__B3__><__B2__><
+
+ - "jeida-24" - 24-bit data mapping compatible with the [DSIM] and [LDI]
+ specifications. Data are transferred as follows on 4 LVDS lanes.
+
+ Slot 0 1 2 3 4 5 6
+ ________________ _________________
+ Clock \_______________________/
+ ______ ______ ______ ______ ______ ______ ______
+ DATA0 ><__G2__><__R7__><__R6__><__R5__><__R4__><__R3__><__R2__><
+ DATA1 ><__B3__><__B2__><__G7__><__G6__><__G5__><__G4__><__G3__><
+ DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B7__><__B6__><__B5__><__B4__><
+ DATA3 ><_CTL3_><__B1__><__B0__><__G1__><__G0__><__R1__><__R0__><
+
+ - "vesa-24" - 24-bit data mapping compatible with the [VESA] specification.
+ Data are transferred as follows on 4 LVDS lanes.
+
+ Slot 0 1 2 3 4 5 6
+ ________________ _________________
+ Clock \_______________________/
+ ______ ______ ______ ______ ______ ______ ______
+ DATA0 ><__G0__><__R5__><__R4__><__R3__><__R2__><__R1__><__R0__><
+ DATA1 ><__B1__><__B0__><__G5__><__G4__><__G3__><__G2__><__G1__><
+ DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B5__><__B4__><__B3__><__B2__><
+ DATA3 ><_CTL3_><__B7__><__B6__><__G7__><__G6__><__R7__><__R6__><
+
+ Control signals are mapped as follows.
+
+ CTL0: HSync
+ CTL1: VSync
+ CTL2: Data Enable
+ CTL3: 0
+
+additionalProperties: true
+
+...
diff --git a/Documentation/devicetree/bindings/display/lvds.yaml b/Documentation/devicetree/bindings/display/lvds.yaml
index 7cd2ce7e9c33..224db4932011 100644
--- a/Documentation/devicetree/bindings/display/lvds.yaml
+++ b/Documentation/devicetree/bindings/display/lvds.yaml
@@ -6,83 +6,24 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: LVDS Display Common Properties
+allOf:
+ - $ref: lvds-data-mapping.yaml#
+
maintainers:
- Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
- Thierry Reding <thierry.reding@gmail.com>
-description: |+
- LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple
- incompatible data link layers have been used over time to transmit image data
- to LVDS devices. This bindings supports devices compatible with the following
- specifications.
-
- [JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February
- 1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA)
- [LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National
- Semiconductor
- [VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
- Electronics Standards Association (VESA)
-
- Device compatible with those specifications have been marketed under the
- FPD-Link and FlatLink brands.
+description:
+ This binding extends the data mapping defined in lvds-data-mapping.yaml.
+ It supports reversing the bit order on the formats defined there in order
+ to accomodate for even more specialized data formats, since a variety of
+ data formats and layouts is used to drive LVDS displays.
properties:
- data-mapping:
- enum:
- - jeida-18
- - jeida-24
- - vesa-24
- description: |
- The color signals mapping order.
-
- LVDS data mappings are defined as follows.
-
- - "jeida-18" - 18-bit data mapping compatible with the [JEIDA], [LDI] and
- [VESA] specifications. Data are transferred as follows on 3 LVDS lanes.
-
- Slot 0 1 2 3 4 5 6
- ________________ _________________
- Clock \_______________________/
- ______ ______ ______ ______ ______ ______ ______
- DATA0 ><__G0__><__R5__><__R4__><__R3__><__R2__><__R1__><__R0__><
- DATA1 ><__B1__><__B0__><__G5__><__G4__><__G3__><__G2__><__G1__><
- DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B5__><__B4__><__B3__><__B2__><
-
- - "jeida-24" - 24-bit data mapping compatible with the [DSIM] and [LDI]
- specifications. Data are transferred as follows on 4 LVDS lanes.
-
- Slot 0 1 2 3 4 5 6
- ________________ _________________
- Clock \_______________________/
- ______ ______ ______ ______ ______ ______ ______
- DATA0 ><__G2__><__R7__><__R6__><__R5__><__R4__><__R3__><__R2__><
- DATA1 ><__B3__><__B2__><__G7__><__G6__><__G5__><__G4__><__G3__><
- DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B7__><__B6__><__B5__><__B4__><
- DATA3 ><_CTL3_><__B1__><__B0__><__G1__><__G0__><__R1__><__R0__><
-
- - "vesa-24" - 24-bit data mapping compatible with the [VESA] specification.
- Data are transferred as follows on 4 LVDS lanes.
-
- Slot 0 1 2 3 4 5 6
- ________________ _________________
- Clock \_______________________/
- ______ ______ ______ ______ ______ ______ ______
- DATA0 ><__G0__><__R5__><__R4__><__R3__><__R2__><__R1__><__R0__><
- DATA1 ><__B1__><__B0__><__G5__><__G4__><__G3__><__G2__><__G1__><
- DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B5__><__B4__><__B3__><__B2__><
- DATA3 ><_CTL3_><__B7__><__B6__><__G7__><__G6__><__R7__><__R6__><
-
- Control signals are mapped as follows.
-
- CTL0: HSync
- CTL1: VSync
- CTL2: Data Enable
- CTL3: 0
-
data-mirror:
type: boolean
description:
- If set, reverse the bit order described in the data mappings below on all
+ If set, reverse the bit order described in the data mappings on all
data lanes, transmitting bits for slots 6 to 0 instead of 0 to 6.
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml
index ff781f2174a0..2aef1eb32e11 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml
@@ -21,6 +21,8 @@ description: |
properties:
compatible:
enum:
+ - mediatek,mt8188-dp-tx
+ - mediatek,mt8188-edp-tx
- mediatek,mt8195-dp-tx
- mediatek,mt8195-edp-tx
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml
index 12441b937684..ed24b617090b 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml
@@ -10,7 +10,6 @@ maintainers:
- Chun-Kuang Hu <chunkuang.hu@kernel.org>
- Philipp Zabel <p.zabel@pengutronix.de>
- Jitao Shi <jitao.shi@mediatek.com>
- - Xinlei Lee <xinlei.lee@mediatek.com>
description: |
The MediaTek DSI function block is a sink of the display subsystem and can
@@ -30,6 +29,7 @@ properties:
- mediatek,mt8173-dsi
- mediatek,mt8183-dsi
- mediatek,mt8186-dsi
+ - mediatek,mt8188-dsi
- items:
- enum:
- mediatek,mt6795-dsi
diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
index f12558960cd8..dbe398f84ffb 100644
--- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
@@ -114,6 +114,7 @@ properties:
port@1:
$ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
description: Output endpoint of the controller
properties:
endpoint:
diff --git a/Documentation/devicetree/bindings/display/msm/gmu.yaml b/Documentation/devicetree/bindings/display/msm/gmu.yaml
index d65926b4f054..4e1c25b42908 100644
--- a/Documentation/devicetree/bindings/display/msm/gmu.yaml
+++ b/Documentation/devicetree/bindings/display/msm/gmu.yaml
@@ -21,7 +21,7 @@ properties:
compatible:
oneOf:
- items:
- - pattern: '^qcom,adreno-gmu-6[0-9][0-9]\.[0-9]$'
+ - pattern: '^qcom,adreno-gmu-[67][0-9][0-9]\.[0-9]$'
- const: qcom,adreno-gmu
- const: qcom,adreno-gmu-wrapper
@@ -64,6 +64,10 @@ properties:
iommus:
maxItems: 1
+ qcom,qmp:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: Reference to the AOSS side-channel message RAM
+
operating-points-v2: true
opp-table:
@@ -217,6 +221,47 @@ allOf:
properties:
compatible:
contains:
+ enum:
+ - qcom,adreno-gmu-730.1
+ - qcom,adreno-gmu-740.1
+ then:
+ properties:
+ reg:
+ items:
+ - description: Core GMU registers
+ - description: Resource controller registers
+ - description: GMU PDC registers
+ reg-names:
+ items:
+ - const: gmu
+ - const: rscc
+ - const: gmu_pdc
+ clocks:
+ items:
+ - description: GPU AHB clock
+ - description: GMU clock
+ - description: GPU CX clock
+ - description: GPU AXI clock
+ - description: GPU MEMNOC clock
+ - description: GMU HUB clock
+ - description: GPUSS DEMET clock
+ clock-names:
+ items:
+ - const: ahb
+ - const: gmu
+ - const: cxo
+ - const: axi
+ - const: memnoc
+ - const: hub
+ - const: demet
+
+ required:
+ - qcom,qmp
+
+ - if:
+ properties:
+ compatible:
+ contains:
const: qcom,adreno-gmu-wrapper
then:
properties:
diff --git a/Documentation/devicetree/bindings/display/msm/gpu.yaml b/Documentation/devicetree/bindings/display/msm/gpu.yaml
index 56b9b247e8c2..b019db954793 100644
--- a/Documentation/devicetree/bindings/display/msm/gpu.yaml
+++ b/Documentation/devicetree/bindings/display/msm/gpu.yaml
@@ -23,7 +23,7 @@ properties:
The driver is parsing the compat string for Adreno to
figure out the gpu-id and patch level.
items:
- - pattern: '^qcom,adreno-[3-6][0-9][0-9]\.[0-9]$'
+ - pattern: '^qcom,adreno-[3-7][0-9][0-9]\.[0-9]$'
- const: qcom,adreno
- description: |
The driver is parsing the compat string for Imageon to
@@ -203,7 +203,7 @@ allOf:
properties:
compatible:
contains:
- pattern: '^qcom,adreno-6[0-9][0-9]\.[0-9]$'
+ pattern: '^qcom,adreno-[67][0-9][0-9]\.[0-9]$'
then: # Starting with A6xx, the clocks are usually defined in the GMU node
properties:
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,msm8998-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,msm8998-mdss.yaml
index e320ab1de6de..2d9edab5a30d 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,msm8998-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,msm8998-mdss.yaml
@@ -38,12 +38,16 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,msm8998-dpu
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -52,6 +56,8 @@ patternProperties:
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,dsi-phy-10nm-8998
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml
index 4184b84d4c21..5ad155612b6c 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml
@@ -44,18 +44,24 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,qcm2290-dpu
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,dsi-ctrl-6g-qcm2290
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,dsi-phy-14nm-2290
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sc7180-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sc7180-mdss.yaml
index 3b9c103e504a..3432a2407caa 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sc7180-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sc7180-mdss.yaml
@@ -44,18 +44,24 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sc7180-dpu
"^displayport-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sc7180-dp
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -64,6 +70,8 @@ patternProperties:
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,dsi-phy-10nm
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sc7280-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-mdss.yaml
index 43500dad66e7..bbb727831fca 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sc7280-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-mdss.yaml
@@ -44,18 +44,24 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sc7280-dpu
"^displayport-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sc7280-dp
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -64,12 +70,16 @@ patternProperties:
"^edp@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sc7280-edp
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
enum:
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sc8280xp-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sc8280xp-mdss.yaml
index db680fb12b6a..af79406e1604 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sc8280xp-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sc8280xp-mdss.yaml
@@ -34,12 +34,16 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sc8280xp-dpu
"^displayport-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
enum:
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sdm845-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sdm845-mdss.yaml
index d6d7ac1b2ef8..6e8b69e5ec62 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sdm845-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sdm845-mdss.yaml
@@ -42,18 +42,24 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sdm845-dpu
"^displayport-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sdm845-dp
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -62,6 +68,8 @@ patternProperties:
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,dsi-phy-10nm
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm6115-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm6115-mdss.yaml
index 17221b62a642..dde5c2acead5 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm6115-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm6115-mdss.yaml
@@ -32,12 +32,16 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm6115-dpu
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
oneOf:
@@ -50,6 +54,8 @@ patternProperties:
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,dsi-phy-14nm-2290
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm6125-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm6125-mdss.yaml
index 57f0e3647711..671c2c2aa896 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm6125-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm6125-mdss.yaml
@@ -43,12 +43,16 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm6125-dpu
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -57,6 +61,8 @@ patternProperties:
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm6125-dsi-phy-14nm
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm6350-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm6350-mdss.yaml
index db255b1f4c20..e1dcb453762e 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm6350-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm6350-mdss.yaml
@@ -43,12 +43,16 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm6350-dpu
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -57,6 +61,8 @@ patternProperties:
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,dsi-phy-10nm
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm6375-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm6375-mdss.yaml
index 30d36fffaedb..b15c3950f09d 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm6375-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm6375-mdss.yaml
@@ -43,12 +43,16 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm6375-dpu
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -57,6 +61,8 @@ patternProperties:
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm6375-dsi-phy-7nm
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml
index 54cdaa827cd3..a2a8be7f64a9 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml
@@ -47,12 +47,16 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm8150-dpu
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -61,6 +65,8 @@ patternProperties:
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,dsi-phy-7nm
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8250-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8250-mdss.yaml
index e887f031b8be..994975909fea 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8250-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8250-mdss.yaml
@@ -46,12 +46,16 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm8250-dpu
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -60,6 +64,8 @@ patternProperties:
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,dsi-phy-7nm
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml
index 60d4aae1131b..163fc83c1e80 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8350-mdss.yaml
@@ -48,18 +48,24 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm8350-dpu
"^displayport-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm8350-dp
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -68,6 +74,8 @@ patternProperties:
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm8350-dsi-phy-5nm
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.yaml
index bb22940b9385..001b26e65301 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.yaml
@@ -38,12 +38,16 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm8450-dpu
"^displayport-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -52,6 +56,8 @@ patternProperties:
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -60,6 +66,8 @@ patternProperties:
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm8450-dsi-phy-5nm
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8550-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8550-mdss.yaml
index 48aea8005c86..1ea50a2c7c8e 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8550-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8550-mdss.yaml
@@ -38,12 +38,16 @@ properties:
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm8550-dpu
"^displayport-controller@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -52,6 +56,8 @@ patternProperties:
"^dsi@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
items:
@@ -60,6 +66,8 @@ patternProperties:
"^phy@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
const: qcom,sm8550-dsi-phy-4nm
diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml
index 90e323e19edb..3cabbba86581 100644
--- a/Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml
+++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml
@@ -48,10 +48,6 @@ examples:
- |
#include <dt-bindings/gpio/gpio.h>
- backlight: backlight {
- compatible = "gpio-backlight";
- gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
- };
spi {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/display/panel/jdi,lpm102a188a.yaml b/Documentation/devicetree/bindings/display/panel/jdi,lpm102a188a.yaml
new file mode 100644
index 000000000000..2f4d27a309a7
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/jdi,lpm102a188a.yaml
@@ -0,0 +1,94 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/jdi,lpm102a188a.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: JDI LPM102A188A 2560x1800 10.2" DSI Panel
+
+maintainers:
+ - Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
+
+description: |
+ This panel requires a dual-channel DSI host to operate. It supports two modes:
+ - left-right: each channel drives the left or right half of the screen
+ - even-odd: each channel drives the even or odd lines of the screen
+
+ Each of the DSI channels controls a separate DSI peripheral. The peripheral
+ driven by the first link (DSI-LINK1) is considered the primary peripheral
+ and controls the device. The 'link2' property contains a phandle to the
+ peripheral driven by the second link (DSI-LINK2).
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ const: jdi,lpm102a188a
+
+ reg: true
+ enable-gpios: true
+ reset-gpios: true
+ power-supply: true
+ backlight: true
+
+ ddi-supply:
+ description: The regulator that provides IOVCC (1.8V).
+
+ link2:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: |
+ phandle to the DSI peripheral on the secondary link. Note that the
+ presence of this property marks the containing node as DSI-LINK1.
+
+required:
+ - compatible
+ - reg
+
+if:
+ required:
+ - link2
+then:
+ required:
+ - power-supply
+ - ddi-supply
+ - enable-gpios
+ - reset-gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/gpio/tegra-gpio.h>
+
+ dsia: dsi@54300000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0 0x54300000 0x0 0x00040000>;
+
+ link2: panel@0 {
+ compatible = "jdi,lpm102a188a";
+ reg = <0>;
+ };
+ };
+
+ dsib: dsi@54400000{
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0 0x54400000 0x0 0x00040000>;
+ nvidia,ganged-mode = <&dsia>;
+
+ link1: panel@0 {
+ compatible = "jdi,lpm102a188a";
+ reg = <0>;
+ power-supply = <&pplcd_vdd>;
+ ddi-supply = <&pp1800_lcdio>;
+ enable-gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
+ link2 = <&link2>;
+ backlight = <&backlight>;
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/leadtek,ltk050h3146w.yaml b/Documentation/devicetree/bindings/display/panel/leadtek,ltk050h3146w.yaml
index 3f6efbb942da..a40ab887ada7 100644
--- a/Documentation/devicetree/bindings/display/panel/leadtek,ltk050h3146w.yaml
+++ b/Documentation/devicetree/bindings/display/panel/leadtek,ltk050h3146w.yaml
@@ -17,6 +17,7 @@ properties:
enum:
- leadtek,ltk050h3146w
- leadtek,ltk050h3146w-a2
+ - leadtek,ltk050h3148w
reg: true
backlight: true
reset-gpios: true
diff --git a/Documentation/devicetree/bindings/display/panel/newvision,nv3051d.yaml b/Documentation/devicetree/bindings/display/panel/newvision,nv3051d.yaml
index 116c1b6030a2..cce775a87f87 100644
--- a/Documentation/devicetree/bindings/display/panel/newvision,nv3051d.yaml
+++ b/Documentation/devicetree/bindings/display/panel/newvision,nv3051d.yaml
@@ -7,9 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: NewVision NV3051D based LCD panel
description: |
- The NewVision NV3051D is a driver chip used to drive DSI panels. For now,
- this driver only supports the 640x480 panels found in the Anbernic RG353
- based devices.
+ The NewVision NV3051D is a driver chip used to drive DSI panels.
maintainers:
- Chris Morgan <macromorgan@hotmail.com>
@@ -21,6 +19,7 @@ properties:
compatible:
items:
- enum:
+ - anbernic,rg351v-panel
- anbernic,rg353p-panel
- anbernic,rg353v-panel
- const: newvision,nv3051d
diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
index 73674baea75d..f9160d7bac3c 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
@@ -42,6 +42,8 @@ properties:
- lg,acx467akm-7
# LG Corporation 7" WXGA TFT LCD panel
- lg,ld070wx3-sl01
+ # LG Corporation 5" HD TFT LCD panel
+ - lg,lh500wx1-sd03
# One Stop Displays OSD101T2587-53TS 10.1" 1920x1200 panel
- osddisplays,osd101t2587-53ts
# Panasonic 10" WUXGA TFT LCD panel
diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
new file mode 100644
index 000000000000..a5a596ff8e75
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
@@ -0,0 +1,118 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/panel-simple-lvds-dual-ports.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Simple LVDS panels with one power supply and dual LVDS ports
+
+maintainers:
+ - Liu Ying <victor.liu@nxp.com>
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Sam Ravnborg <sam@ravnborg.org>
+
+description: |
+ This binding file is a collection of the LVDS panels that
+ has dual LVDS ports and requires only a single power-supply.
+ The first port receives odd pixels, and the second port receives even pixels.
+ There are optionally a backlight and an enable GPIO.
+ The panel may use an OF graph binding for the association to the display,
+ or it may be a direct child node of the display.
+
+ If the panel is more advanced a dedicated binding file is required.
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+
+ compatible:
+ enum:
+ # compatible must be listed in alphabetical order, ordered by compatible.
+ # The description in the comment is mandatory for each compatible.
+
+ # AU Optronics Corporation 13.3" FHD (1920x1080) TFT LCD panel
+ - auo,g133han01
+ # AU Optronics Corporation 18.5" FHD (1920x1080) TFT LCD panel
+ - auo,g185han01
+ # AU Optronics Corporation 19.0" (1280x1024) TFT LCD panel
+ - auo,g190ean01
+ # Kaohsiung Opto-Electronics Inc. 10.1" WUXGA (1920 x 1200) LVDS TFT LCD panel
+ - koe,tx26d202vm0bwa
+ # NLT Technologies, Ltd. 15.6" FHD (1920x1080) LVDS TFT LCD panel
+ - nlt,nl192108ac18-02d
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: The first sink port.
+
+ properties:
+ dual-lvds-odd-pixels:
+ type: boolean
+ description: The first sink port for odd pixels.
+
+ required:
+ - dual-lvds-odd-pixels
+
+ port@1:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: The second sink port.
+
+ properties:
+ dual-lvds-even-pixels:
+ type: boolean
+ description: The second sink port for even pixels.
+
+ required:
+ - dual-lvds-even-pixels
+
+ required:
+ - port@0
+ - port@1
+
+ backlight: true
+ enable-gpios: true
+ power-supply: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - ports
+ - power-supply
+
+examples:
+ - |
+ panel: panel-lvds {
+ compatible = "koe,tx26d202vm0bwa";
+ power-supply = <&vdd_lcd_reg>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ dual-lvds-odd-pixels;
+ reg = <0>;
+
+ panel_lvds0_in: endpoint {
+ remote-endpoint = <&lvds0_out>;
+ };
+ };
+
+ port@1 {
+ dual-lvds-even-pixels;
+ reg = <1>;
+
+ panel_lvds1_in: endpoint {
+ remote-endpoint = <&lvds1_out>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
index 25b4589d4a58..11422af3477e 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
@@ -21,9 +21,9 @@ description: |
allOf:
- $ref: panel-common.yaml#
+ - $ref: ../lvds-data-mapping.yaml#
properties:
-
compatible:
enum:
# compatible must be listed in alphabetical order, ordered by compatible.
@@ -65,14 +65,8 @@ properties:
- auo,g104sn02
# AU Optronics Corporation 12.1" (1280x800) TFT LCD panel
- auo,g121ean01
- # AU Optronics Corporation 13.3" FHD (1920x1080) TFT LCD panel
- - auo,g133han01
# AU Optronics Corporation 15.6" (1366x768) TFT LCD panel
- auo,g156xtn01
- # AU Optronics Corporation 18.5" FHD (1920x1080) TFT LCD panel
- - auo,g185han01
- # AU Optronics Corporation 19.0" (1280x1024) TFT LCD panel
- - auo,g190ean01
# AU Optronics Corporation 31.5" FHD (1920x1080) TFT LCD panel
- auo,p320hvn03
# AU Optronics Corporation 21.5" FHD (1920x1080) color TFT LCD panel
@@ -204,8 +198,6 @@ properties:
- kingdisplay,kd116n21-30nv-a010
# Kaohsiung Opto-Electronics Inc. 5.7" QVGA (320 x 240) TFT LCD panel
- koe,tx14d24vm1bpa
- # Kaohsiung Opto-Electronics Inc. 10.1" WUXGA (1920 x 1200) LVDS TFT LCD panel
- - koe,tx26d202vm0bwa
# Kaohsiung Opto-Electronics. TX31D200VM0BAA 12.3" HSXGA LVDS panel
- koe,tx31d200vm0baa
# Kyocera Corporation 7" WVGA (800x480) transmissive color TFT
@@ -216,8 +208,6 @@ properties:
- lemaker,bl035-rgb-002
# LG 7" (800x480 pixels) TFT LCD panel
- lg,lb070wv8
- # LG Corporation 5" HD TFT LCD panel
- - lg,lh500wx1-sd03
# LG LP079QX1-SP0V 7.9" (1536x2048 pixels) TFT LCD panel
- lg,lp079qx1-sp0v
# LG 9.7" (2048x1536 pixels) TFT LCD panel
@@ -238,6 +228,8 @@ properties:
- logictechno,lttd800480070-l6wh-rt
# Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel
- mitsubishi,aa070mc01-ca1
+ # Mitsubishi AA084XE01 8.4" XGA TFT LCD panel
+ - mitsubishi,aa084xe01
# Multi-Inno Technology Co.,Ltd MI0700S4T-6 7" 800x480 TFT Resistive Touch Module
- multi-inno,mi0700s4t-6
# Multi-Inno Technology Co.,Ltd MI0800FT-9 8" 800x600 TFT Resistive Touch Module
@@ -254,8 +246,6 @@ properties:
- neweast,wjfh116008a
# Newhaven Display International 480 x 272 TFT LCD panel
- newhaven,nhd-4.3-480272ef-atxl
- # NLT Technologies, Ltd. 15.6" FHD (1920x1080) LVDS TFT LCD panel
- - nlt,nl192108ac18-02d
# New Vision Display 7.0" 800 RGB x 480 TFT LCD panel
- nvd,9128
# OKAYA Electric America, Inc. RS800480T-7X0GP 7" WVGA LCD panel
@@ -357,6 +347,17 @@ properties:
power-supply: true
no-hpd: true
hpd-gpios: true
+ data-mapping: true
+
+if:
+ not:
+ properties:
+ compatible:
+ contains:
+ const: innolux,g101ice-l01
+then:
+ properties:
+ data-mapping: false
additionalProperties: false
@@ -376,3 +377,16 @@ examples:
};
};
};
+ - |
+ panel_lvds: panel-lvds {
+ compatible = "innolux,g101ice-l01";
+ power-supply = <&vcc_lcd_reg>;
+
+ data-mapping = "jeida-24";
+
+ port {
+ panel_in_lvds: endpoint {
+ remote-endpoint = <&ltdc_out_lvds>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/panel/raydium,rm692e5.yaml b/Documentation/devicetree/bindings/display/panel/raydium,rm692e5.yaml
new file mode 100644
index 000000000000..f436ba6738ca
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/raydium,rm692e5.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/raydium,rm692e5.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Raydium RM692E5 based DSI display panels
+
+maintainers:
+ - Konrad Dybcio <konradybcio@kernel.org>
+
+description:
+ The Raydium RM692E5 is a generic DSI Panel IC used to control
+ AMOLED panels.
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: fairphone,fp5-rm692e5-boe
+ - const: raydium,rm692e5
+
+ dvdd-supply:
+ description: Digital voltage rail
+
+ vci-supply:
+ description: Analog voltage rail
+
+ vddio-supply:
+ description: I/O voltage rail
+
+ reg: true
+ port: true
+
+required:
+ - compatible
+ - reg
+ - reset-gpios
+ - dvdd-supply
+ - vci-supply
+ - vddio-supply
+ - port
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ dsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "fairphone,fp5-rm692e5-boe", "raydium,rm692e5";
+ reg = <0>;
+
+ reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>;
+ dvdd-supply = <&vreg_oled_vci>;
+ vci-supply = <&vreg_l12c>;
+ vddio-supply = <&vreg_oled_dvdd>;
+
+ port {
+ panel_in_0: endpoint {
+ remote-endpoint = <&dsi0_out>;
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml b/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
index 5ea74426b1d5..97cccd8a8479 100644
--- a/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
+++ b/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
@@ -22,6 +22,8 @@ properties:
enum:
# Anberic RG353V-V2 5.0" 640x480 TFT LCD panel
- anbernic,rg353v-panel-v2
+ # Powkiddy RGB30 3.0" 720x720 TFT LCD panel
+ - powkiddy,rgb30-panel
# Rocktech JH057N00900 5.5" 720x1440 TFT LCD panel
- rocktech,jh057n00900
# Xingbangda XBD599 5.99" 720x1440 TFT LCD panel
diff --git a/Documentation/devicetree/bindings/display/renesas,shmobile-lcdc.yaml b/Documentation/devicetree/bindings/display/renesas,shmobile-lcdc.yaml
new file mode 100644
index 000000000000..9816c4cacc7d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/renesas,shmobile-lcdc.yaml
@@ -0,0 +1,130 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/renesas,shmobile-lcdc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas SH-Mobile LCD Controller (LCDC)
+
+maintainers:
+ - Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+ - Geert Uytterhoeven <geert+renesas@glider.be>
+
+properties:
+ compatible:
+ enum:
+ - renesas,r8a7740-lcdc # R-Mobile A1
+ - renesas,sh73a0-lcdc # SH-Mobile AG5
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ minItems: 1
+ maxItems: 5
+ description:
+ Only the functional clock is mandatory.
+ Some of the optional clocks are model-dependent (e.g. "video" (a.k.a.
+ "vou" or "dv_clk") is available on R-Mobile A1 only).
+
+ clock-names:
+ minItems: 1
+ items:
+ - const: fck
+ - enum: [ media, lclk, hdmi, video ]
+ - enum: [ media, lclk, hdmi, video ]
+ - enum: [ media, lclk, hdmi, video ]
+ - enum: [ media, lclk, hdmi, video ]
+
+ power-domains:
+ maxItems: 1
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: LCD port (R-Mobile A1 and SH-Mobile AG5)
+ unevaluatedProperties: false
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: HDMI port (R-Mobile A1 LCDC1 and SH-Mobile AG5)
+ unevaluatedProperties: false
+
+ port@2:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: MIPI-DSI port (SH-Mobile AG5)
+ unevaluatedProperties: false
+
+ required:
+ - port@0
+
+ unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - power-domains
+ - ports
+
+additionalProperties: false
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: renesas,r8a7740-lcdc
+ then:
+ properties:
+ ports:
+ properties:
+ port@2: false
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: renesas,sh73a0-lcdc
+ then:
+ properties:
+ ports:
+ required:
+ - port@1
+ - port@2
+
+examples:
+ - |
+ #include <dt-bindings/clock/r8a7740-clock.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ lcd-controller@fe940000 {
+ compatible = "renesas,r8a7740-lcdc";
+ reg = <0xfe940000 0x4000>;
+ interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp1_clks R8A7740_CLK_LCDC0>,
+ <&cpg_clocks R8A7740_CLK_M3>, <&lcdlclk0_clk>,
+ <&vou_clk>;
+ clock-names = "fck", "media", "lclk", "video";
+ power-domains = <&pd_a4lc>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ lcdc0_rgb: endpoint {
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-mipi-dsi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-mipi-dsi.yaml
index 8e8a40879140..ccf79e738fa1 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-mipi-dsi.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-mipi-dsi.yaml
@@ -18,6 +18,7 @@ properties:
- rockchip,rk3288-mipi-dsi
- rockchip,rk3399-mipi-dsi
- rockchip,rk3568-mipi-dsi
+ - rockchip,rv1126-mipi-dsi
- const: snps,dw-mipi-dsi
interrupts:
@@ -77,6 +78,7 @@ allOf:
enum:
- rockchip,px30-mipi-dsi
- rockchip,rk3568-mipi-dsi
+ - rockchip,rv1126-mipi-dsi
then:
properties:
diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml
index df61cb5f5c54..b339b7e708c6 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml
@@ -31,6 +31,7 @@ properties:
- rockchip,rk3368-vop
- rockchip,rk3399-vop-big
- rockchip,rk3399-vop-lit
+ - rockchip,rv1126-vop
reg:
minItems: 1
diff --git a/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml b/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml
index 621f27148419..3b0ebc0db8e0 100644
--- a/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml
+++ b/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml
@@ -54,11 +54,6 @@ examples:
- |
#include <dt-bindings/gpio/gpio.h>
- backlight: backlight {
- compatible = "gpio-backlight";
- gpios = <&gpio 44 GPIO_ACTIVE_HIGH>;
- };
-
spi {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/display/solomon,ssd-common.yaml b/Documentation/devicetree/bindings/display/solomon,ssd-common.yaml
new file mode 100644
index 000000000000..3e6998481a75
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/solomon,ssd-common.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/solomon,ssd-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Common properties for Solomon OLED Display Controllers
+
+maintainers:
+ - Javier Martinez Canillas <javierm@redhat.com>
+
+properties:
+ reg:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ # Only required for SPI
+ dc-gpios:
+ description:
+ GPIO connected to the controller's D/C# (Data/Command) pin,
+ that is needed for 4-wire SPI to tell the controller if the
+ data sent is for a command register or the display data RAM
+ maxItems: 1
+
+ solomon,height:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Height in pixel of the screen driven by the controller.
+ The default value is controller-dependent.
+
+ solomon,width:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Width in pixel of the screen driven by the controller.
+ The default value is controller-dependent.
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml b/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
index 20e2bd15d4d2..3afbb52d1b7f 100644
--- a/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
+++ b/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
@@ -27,38 +27,12 @@ properties:
- solomon,ssd1307
- solomon,ssd1309
- reg:
- maxItems: 1
-
pwms:
maxItems: 1
- reset-gpios:
- maxItems: 1
-
- # Only required for SPI
- dc-gpios:
- description:
- GPIO connected to the controller's D/C# (Data/Command) pin,
- that is needed for 4-wire SPI to tell the controller if the
- data sent is for a command register or the display data RAM
- maxItems: 1
-
vbat-supply:
description: The supply for VBAT
- solomon,height:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
- Height in pixel of the screen driven by the controller.
- The default value is controller-dependent.
-
- solomon,width:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
- Width in pixel of the screen driven by the controller.
- The default value is controller-dependent.
-
solomon,page-offset:
$ref: /schemas/types.yaml#/definitions/uint32
default: 1
@@ -148,7 +122,7 @@ required:
- reg
allOf:
- - $ref: /schemas/spi/spi-peripheral-props.yaml#
+ - $ref: solomon,ssd-common.yaml#
- if:
properties:
diff --git a/Documentation/devicetree/bindings/display/solomon,ssd132x.yaml b/Documentation/devicetree/bindings/display/solomon,ssd132x.yaml
new file mode 100644
index 000000000000..37975ee61c5a
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/solomon,ssd132x.yaml
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/solomon,ssd132x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Solomon SSD132x OLED Display Controllers
+
+maintainers:
+ - Javier Martinez Canillas <javierm@redhat.com>
+
+properties:
+ compatible:
+ enum:
+ - solomon,ssd1322
+ - solomon,ssd1325
+ - solomon,ssd1327
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - $ref: solomon,ssd-common.yaml#
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: solomon,ssd1322
+ then:
+ properties:
+ width:
+ default: 480
+ height:
+ default: 128
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: solomon,ssd1325
+ then:
+ properties:
+ width:
+ default: 128
+ height:
+ default: 80
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: solomon,ssd1327
+ then:
+ properties:
+ width:
+ default: 128
+ height:
+ default: 128
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ oled@3c {
+ compatible = "solomon,ssd1327";
+ reg = <0x3c>;
+ reset-gpios = <&gpio2 7>;
+ };
+
+ };
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ oled@0 {
+ compatible = "solomon,ssd1327";
+ reg = <0x0>;
+ reset-gpios = <&gpio2 7>;
+ dc-gpios = <&gpio2 8>;
+ spi-max-frequency = <10000000>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/dma/qcom,gpi.yaml b/Documentation/devicetree/bindings/dma/qcom,gpi.yaml
index f61145c91b6d..88d0de3d1b46 100644
--- a/Documentation/devicetree/bindings/dma/qcom,gpi.yaml
+++ b/Documentation/devicetree/bindings/dma/qcom,gpi.yaml
@@ -69,6 +69,8 @@ properties:
dma-channel-mask:
maxItems: 1
+ dma-coherent: true
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dma-1.0.yaml b/Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dma-1.0.yaml
index 23ada8f87526..769ce23aaac2 100644
--- a/Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dma-1.0.yaml
+++ b/Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dma-1.0.yaml
@@ -13,6 +13,8 @@ description: |
maintainers:
- Michael Tretter <m.tretter@pengutronix.de>
+ - Harini Katakam <harini.katakam@amd.com>
+ - Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
allOf:
- $ref: ../dma-controller.yaml#
@@ -65,6 +67,7 @@ required:
- interrupts
- clocks
- clock-names
+ - xlnx,bus-width
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/eeprom/at24.yaml b/Documentation/devicetree/bindings/eeprom/at24.yaml
index 98139489d4b5..b6864d0ee81e 100644
--- a/Documentation/devicetree/bindings/eeprom/at24.yaml
+++ b/Documentation/devicetree/bindings/eeprom/at24.yaml
@@ -12,6 +12,7 @@ maintainers:
allOf:
- $ref: /schemas/nvmem/nvmem.yaml
+ - $ref: /schemas/nvmem/nvmem-deprecated-cells.yaml
select:
properties:
@@ -68,10 +69,14 @@ properties:
- items:
pattern: c32$
- items:
+ pattern: c32d-wl$
+ - items:
pattern: cs32$
- items:
pattern: c64$
- items:
+ pattern: c64d-wl$
+ - items:
pattern: cs64$
- items:
pattern: c128$
diff --git a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
index b138f3d23df8..4591523b51a0 100644
--- a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
+++ b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
@@ -38,6 +38,9 @@ properties:
with shmem address(4KB-page, offset) as parameters
items:
- const: arm,scmi-smc-param
+ - description: SCMI compliant firmware with Qualcomm SMC/HVC transport
+ items:
+ - const: qcom,scmi-smc
- description: SCMI compliant firmware with SCMI Virtio transport.
The virtio transport only supports a single device.
items:
@@ -149,8 +152,15 @@ properties:
'#clock-cells':
const: 1
- required:
- - '#clock-cells'
+ '#power-domain-cells':
+ const: 1
+
+ oneOf:
+ - required:
+ - '#clock-cells'
+
+ - required:
+ - '#power-domain-cells'
protocol@14:
$ref: '#/$defs/protocol-node'
@@ -306,6 +316,7 @@ else:
enum:
- arm,scmi-smc
- arm,scmi-smc-param
+ - qcom,scmi-smc
then:
required:
- arm,smc-id
diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
index 4233ea839bfc..0613a37a851a 100644
--- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
@@ -24,6 +24,7 @@ properties:
- qcom,scm-apq8064
- qcom,scm-apq8084
- qcom,scm-ipq4019
+ - qcom,scm-ipq5018
- qcom,scm-ipq5332
- qcom,scm-ipq6018
- qcom,scm-ipq806x
@@ -56,6 +57,7 @@ properties:
- qcom,scm-sm6125
- qcom,scm-sm6350
- qcom,scm-sm6375
+ - qcom,scm-sm7150
- qcom,scm-sm8150
- qcom,scm-sm8250
- qcom,scm-sm8350
@@ -89,6 +91,14 @@ properties:
protocol to handle sleeping SCM calls.
maxItems: 1
+ qcom,sdi-enabled:
+ description:
+ Indicates that the SDI (Secure Debug Image) has been enabled by TZ
+ by default and it needs to be disabled.
+ If not disabled WDT assertion or reboot will cause the board to hang
+ in the debug mode.
+ type: boolean
+
qcom,dload-mode:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
diff --git a/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.yaml b/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.yaml
index d0ca2af89f1e..918776d16ef3 100644
--- a/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.yaml
@@ -19,10 +19,18 @@ properties:
- fsl,imx35-gpio
- fsl,imx7d-gpio
- items:
+ - enum:
+ - fsl,imx27-gpio
+ - const: fsl,imx21-gpio
+ - items:
- const: fsl,imx35-gpio
- const: fsl,imx31-gpio
- items:
- enum:
+ - fsl,imx25-gpio
+ - const: fsl,imx35-gpio
+ - items:
+ - enum:
- fsl,imx50-gpio
- fsl,imx51-gpio
- fsl,imx53-gpio
diff --git a/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml b/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml
index 7c2d152e8617..a27f92950257 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml
+++ b/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml
@@ -20,6 +20,7 @@ description: |
properties:
compatible:
oneOf:
+ - const: fsl,imx8ulp-gpio
- const: fsl,vf610-gpio
- items:
- const: fsl,imx7ulp-gpio
@@ -27,16 +28,18 @@ properties:
- items:
- enum:
- fsl,imx93-gpio
- - fsl,imx8ulp-gpio
- - const: fsl,imx7ulp-gpio
+ - fsl,imx95-gpio
+ - const: fsl,imx8ulp-gpio
reg:
- description: The first reg tuple represents the PORT module, the second tuple
- represents the GPIO module.
+ minItems: 1
maxItems: 2
interrupts:
- maxItems: 1
+ items:
+ - description: GPIO Trustzone non-secure interrupt number
+ - description: GPIO Trustzone secure interrupt number
+ minItems: 1
interrupt-controller: true
@@ -59,7 +62,8 @@ properties:
- const: port
gpio-ranges:
- maxItems: 1
+ minItems: 1
+ maxItems: 4
patternProperties:
"^.+-hog(-[0-9]+)?$":
@@ -77,6 +81,30 @@ required:
- "#gpio-cells"
- gpio-controller
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,vf610-gpio
+ - fsl,imx7ulp-gpio
+ then:
+ properties:
+ interrupts:
+ maxItems: 1
+ reg:
+ items:
+ - description: PORT register base address
+ - description: GPIO register base address
+ else:
+ properties:
+ interrupts:
+ minItems: 2
+ reg:
+ items:
+ - description: GPIO register base address
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
deleted file mode 100644
index 8dc41ed99685..000000000000
--- a/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-Intel IXP4xx XScale Networking Processors GPIO
-
-This GPIO controller is found in the Intel IXP4xx processors.
-It supports 16 GPIO lines.
-
-The interrupt portions of the GPIO controller is hierarchical:
-the synchronous edge detector is part of the GPIO block, but the
-actual enabling/disabling of the interrupt line is done in the
-main IXP4xx interrupt controller which has a 1:1 mapping for
-the first 12 GPIO lines to 12 system interrupts.
-
-The remaining 4 GPIO lines can not be used for receiving
-interrupts.
-
-The interrupt parent of this GPIO controller must be the
-IXP4xx interrupt controller.
-
-Required properties:
-
-- compatible : Should be
- "intel,ixp4xx-gpio"
-- reg : Should contain registers location and length
-- gpio-controller : marks this as a GPIO controller
-- #gpio-cells : Should be 2, see gpio/gpio.txt
-- interrupt-controller : marks this as an interrupt controller
-- #interrupt-cells : a standard two-cell interrupt, see
- interrupt-controller/interrupts.txt
-
-Example:
-
-gpio0: gpio@c8004000 {
- compatible = "intel,ixp4xx-gpio";
- reg = <0xc8004000 0x1000>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
-};
diff --git a/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml
new file mode 100644
index 000000000000..bfcb1f364c3a
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/intel,ixp4xx-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Intel IXP4xx XScale Networking Processors GPIO Controller
+
+description: |
+ This GPIO controller is found in the Intel IXP4xx
+ processors. It supports 16 GPIO lines.
+ The interrupt portions of the GPIO controller is hierarchical.
+ The synchronous edge detector is part of the GPIO block, but the
+ actual enabling/disabling of the interrupt line is done in the
+ main IXP4xx interrupt controller which has a 1-to-1 mapping for
+ the first 12 GPIO lines to 12 system interrupts.
+ The remaining 4 GPIO lines can not be used for receiving
+ interrupts.
+ The interrupt parent of this GPIO controller must be the
+ IXP4xx interrupt controller.
+ GPIO 14 and 15 can be used as clock outputs rather than GPIO,
+ and this can be enabled by a special flag.
+
+maintainers:
+ - Linus Walleij <linus.walleij@linaro.org>
+
+properties:
+ compatible:
+ const: intel,ixp4xx-gpio
+
+ reg:
+ maxItems: 1
+
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 2
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 2
+
+ intel,ixp4xx-gpio14-clkout:
+ description: If defined, enables clock output on GPIO 14
+ instead of GPIO.
+ type: boolean
+
+ intel,ixp4xx-gpio15-clkout:
+ description: If defined, enables clock output on GPIO 15
+ instead of GPIO.
+ type: boolean
+
+required:
+ - compatible
+ - reg
+ - "#gpio-cells"
+ - interrupt-controller
+ - "#interrupt-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ gpio@c8004000 {
+ compatible = "intel,ixp4xx-gpio";
+ reg = <0xc8004000 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml b/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml
index fb86e8ce6349..cf3b1b270aa8 100644
--- a/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml
@@ -11,9 +11,22 @@ maintainers:
properties:
compatible:
- enum:
- - loongson,ls2k-gpio
- - loongson,ls7a-gpio
+ oneOf:
+ - enum:
+ - loongson,ls2k-gpio
+ - loongson,ls2k0500-gpio0
+ - loongson,ls2k0500-gpio1
+ - loongson,ls2k2000-gpio0
+ - loongson,ls2k2000-gpio1
+ - loongson,ls2k2000-gpio2
+ - loongson,ls3a5000-gpio
+ - loongson,ls7a-gpio
+ - items:
+ - const: loongson,ls2k1000-gpio
+ - const: loongson,ls2k-gpio
+ - items:
+ - const: loongson,ls7a1000-gpio
+ - const: loongson,ls7a-gpio
reg:
maxItems: 1
@@ -49,7 +62,7 @@ examples:
#include <dt-bindings/interrupt-controller/irq.h>
gpio0: gpio@1fe00500 {
- compatible = "loongson,ls2k-gpio";
+ compatible = "loongson,ls2k1000-gpio", "loongson,ls2k-gpio";
reg = <0x1fe00500 0x38>;
ngpios = <64>;
#gpio-cells = <2>;
diff --git a/Documentation/devicetree/bindings/hwmon/adi,ltc2991.yaml b/Documentation/devicetree/bindings/hwmon/adi,ltc2991.yaml
new file mode 100644
index 000000000000..011e5b65c79c
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/adi,ltc2991.yaml
@@ -0,0 +1,128 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/hwmon/adi,ltc2991.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices LTC2991 Octal I2C Voltage, Current and Temperature Monitor
+
+maintainers:
+ - Antoniu Miclaus <antoniu.miclaus@analog.com>
+
+description: |
+ The LTC2991 is used to monitor system temperatures, voltages and currents.
+ Through the I2C serial interface, the eight monitors can individually measure
+ supply voltages and can be paired for differential measurements of current
+ sense resistors or temperature sensing transistors.
+
+ Datasheet:
+ https://www.analog.com/en/products/ltc2991.html
+
+properties:
+ compatible:
+ const: adi,ltc2991
+
+ reg:
+ maxItems: 1
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ vcc-supply: true
+
+patternProperties:
+ "^channel@[0-3]$":
+ type: object
+ description:
+ Represents the differential/temperature channels.
+
+ properties:
+ reg:
+ description:
+ The channel number. LTC2991 can monitor 4 currents/temperatures.
+ items:
+ minimum: 0
+ maximum: 3
+
+ shunt-resistor-micro-ohms:
+ description:
+ The value of curent sense resistor in micro ohms. Pin configuration is
+ set for differential input pair.
+
+ adi,temperature-enable:
+ description:
+ Enables temperature readings. Pin configuration is set for remote
+ diode temperature measurement.
+ type: boolean
+
+ required:
+ - reg
+
+ allOf:
+ - if:
+ required:
+ - shunt-resistor-micro-ohms
+ then:
+ properties:
+ adi,temperature-enable: false
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - vcc-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hwmon@48 {
+ compatible = "adi,ltc2991";
+ reg = <0x48>;
+ vcc-supply = <&vcc>;
+ };
+ };
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hwmon@48 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "adi,ltc2991";
+ reg = <0x48>;
+ vcc-supply = <&vcc>;
+
+ channel@0 {
+ reg = <0x0>;
+ shunt-resistor-micro-ohms = <100000>;
+ };
+
+ channel@1 {
+ reg = <0x1>;
+ shunt-resistor-micro-ohms = <100000>;
+ };
+
+ channel@2 {
+ reg = <0x2>;
+ adi,temperature-enable;
+ };
+
+ channel@3 {
+ reg = <0x3>;
+ adi,temperature-enable;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/hwmon/adi,max31827.yaml b/Documentation/devicetree/bindings/hwmon/adi,max31827.yaml
index 2dc8b07b4d3b..f60e06ab7d0a 100644
--- a/Documentation/devicetree/bindings/hwmon/adi,max31827.yaml
+++ b/Documentation/devicetree/bindings/hwmon/adi,max31827.yaml
@@ -32,6 +32,68 @@ properties:
Must have values in the interval (1.6V; 3.6V) in order for the device to
function correctly.
+ adi,comp-int:
+ description:
+ If present interrupt mode is used. If not present comparator mode is used
+ (default).
+ type: boolean
+
+ adi,alarm-pol:
+ description:
+ Sets the alarms active state.
+ - 0 = active low
+ - 1 = active high
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+
+ adi,fault-q:
+ description:
+ Select how many consecutive temperature faults must occur before
+ overtemperature or undertemperature faults are indicated in the
+ corresponding status bits.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [1, 2, 4, 8]
+
+ adi,timeout-enable:
+ description:
+ Enables timeout. Bus timeout resets the I2C-compatible interface when SCL
+ is low for more than 30ms (nominal).
+ type: boolean
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: adi,max31829
+
+ then:
+ properties:
+ adi,alarm-pol:
+ default: 1
+
+ else:
+ properties:
+ adi,alarm-pol:
+ default: 0
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: adi,max31827
+
+ then:
+ properties:
+ adi,fault-q:
+ default: 1
+
+ else:
+ properties:
+ adi,fault-q:
+ default: 4
+
+
required:
- compatible
- reg
@@ -49,6 +111,10 @@ examples:
compatible = "adi,max31827";
reg = <0x42>;
vref-supply = <&reg_vdd>;
+ adi,comp-int;
+ adi,alarm-pol = <0>;
+ adi,fault-q = <1>;
+ adi,timeout-enable;
};
};
...
diff --git a/Documentation/devicetree/bindings/hwmon/ina3221.txt b/Documentation/devicetree/bindings/hwmon/ina3221.txt
deleted file mode 100644
index fa63b6171407..000000000000
--- a/Documentation/devicetree/bindings/hwmon/ina3221.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-Texas Instruments INA3221 Device Tree Bindings
-
-1) ina3221 node
- Required properties:
- - compatible: Must be "ti,ina3221"
- - reg: I2C address
-
- Optional properties:
- - ti,single-shot: This chip has two power modes: single-shot (chip takes one
- measurement and then shuts itself down) and continuous (
- chip takes continuous measurements). The continuous mode is
- more reliable and suitable for hardware monitor type device,
- but the single-shot mode is more power-friendly and useful
- for battery-powered device which cares power consumptions
- while still needs some measurements occasionally.
- If this property is present, the single-shot mode will be
- used, instead of the default continuous one for monitoring.
-
- = The node contains optional child nodes for three channels =
- = Each child node describes the information of input source =
-
- - #address-cells: Required only if a child node is present. Must be 1.
- - #size-cells: Required only if a child node is present. Must be 0.
-
-2) child nodes
- Required properties:
- - reg: Must be 0, 1 or 2, corresponding to IN1, IN2 or IN3 port of INA3221
-
- Optional properties:
- - label: Name of the input source
- - shunt-resistor-micro-ohms: Shunt resistor value in micro-Ohm
-
-Example:
-
-ina3221@40 {
- compatible = "ti,ina3221";
- reg = <0x40>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- input@0 {
- reg = <0x0>;
- status = "disabled";
- };
- input@1 {
- reg = <0x1>;
- shunt-resistor-micro-ohms = <5000>;
- };
- input@2 {
- reg = <0x2>;
- label = "VDD_5V";
- shunt-resistor-micro-ohms = <5000>;
- };
-};
diff --git a/Documentation/devicetree/bindings/hwmon/npcm750-pwm-fan.txt b/Documentation/devicetree/bindings/hwmon/npcm750-pwm-fan.txt
index 8523777f560c..18095ba87a5a 100644
--- a/Documentation/devicetree/bindings/hwmon/npcm750-pwm-fan.txt
+++ b/Documentation/devicetree/bindings/hwmon/npcm750-pwm-fan.txt
@@ -1,12 +1,16 @@
-Nuvoton NPCM7xx PWM and Fan Tacho controller device
+Nuvoton NPCM PWM and Fan Tacho controller device
The Nuvoton BMC NPCM7XX supports 8 Pulse-width modulation (PWM)
controller outputs and 16 Fan tachometer controller inputs.
+The Nuvoton BMC NPCM8XX supports 12 Pulse-width modulation (PWM)
+controller outputs and 16 Fan tachometer controller inputs.
+
Required properties for pwm-fan node
- #address-cells : should be 1.
- #size-cells : should be 0.
- compatible : "nuvoton,npcm750-pwm-fan" for Poleg NPCM7XX.
+ : "nuvoton,npcm845-pwm-fan" for Arbel NPCM8XX.
- reg : specifies physical base address and size of the registers.
- reg-names : must contain:
* "pwm" for the PWM registers.
diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/infineon,tda38640.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/infineon,tda38640.yaml
new file mode 100644
index 000000000000..ded1c115764b
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/infineon,tda38640.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/hwmon/pmbus/infineon,tda38640.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Infineon TDA38640 Synchronous Buck Regulator with SVID and I2C
+
+maintainers:
+ - Naresh Solanki <naresh.solanki@9elements.com>
+
+description: |
+ The Infineon TDA38640 is a 40A Single-voltage Synchronous Buck
+ Regulator with SVID and I2C designed for Industrial use.
+
+ Datasheet: https://www.infineon.com/dgdl/Infineon-TDA38640-0000-DataSheet-v02_04-EN.pdf?fileId=8ac78c8c80027ecd018042f2337f00c9
+
+properties:
+ compatible:
+ enum:
+ - infineon,tda38640
+
+ reg:
+ maxItems: 1
+
+ infineon,en-pin-fixed-level:
+ description:
+ Indicates that the chip EN pin is at fixed level or left
+ unconnected(has internal pull-down).
+ type: boolean
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tda38640@40 {
+ compatible = "infineon,tda38640";
+ reg = <0x40>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml b/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
index 8648877d2d01..378d1f6aeeb3 100644
--- a/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
+++ b/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
@@ -26,6 +26,7 @@ properties:
- ti,ina226
- ti,ina230
- ti,ina231
+ - ti,ina237
- ti,ina238
reg:
diff --git a/Documentation/devicetree/bindings/hwmon/ti,ina3221.yaml b/Documentation/devicetree/bindings/hwmon/ti,ina3221.yaml
new file mode 100644
index 000000000000..5f10f1207d69
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/ti,ina3221.yaml
@@ -0,0 +1,121 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/ti,ina3221.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments INA3221 Current and Voltage Monitor
+
+maintainers:
+ - Jean Delvare <jdelvare@suse.com>
+ - Guenter Roeck <linux@roeck-us.net>
+
+properties:
+ compatible:
+ const: ti,ina3221
+
+ reg:
+ maxItems: 1
+
+ ti,single-shot:
+ description: |
+ This chip has two power modes: single-shot (chip takes one measurement
+ and then shuts itself down) and continuous (chip takes continuous
+ measurements). The continuous mode is more reliable and suitable for
+ hardware monitor type device, but the single-shot mode is more power-
+ friendly and useful for battery-powered device which cares power
+ consumptions while still needs some measurements occasionally.
+
+ If this property is present, the single-shot mode will be used, instead
+ of the default continuous one for monitoring.
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ "#address-cells":
+ description: Required only if a child node is present.
+ const: 1
+
+ "#size-cells":
+ description: Required only if a child node is present.
+ const: 0
+
+patternProperties:
+ "^input@[0-2]$":
+ description: The node contains optional child nodes for three channels.
+ Each child node describes the information of input source. Input channels
+ default to enabled in the chip. Unless channels are explicitly disabled
+ in device-tree, input channels will be enabled.
+ type: object
+ additionalProperties: false
+ properties:
+ reg:
+ description: Must be 0, 1 and 2, corresponding to the IN1, IN2 or IN3
+ ports of the INA3221, respectively.
+ enum: [ 0, 1, 2 ]
+
+ label:
+ description: name of the input source
+
+ shunt-resistor-micro-ohms:
+ description: shunt resistor value in micro-Ohm
+
+ ti,summation-disable:
+ description: |
+ The INA3221 has a critical alert pin that can be controlled by the
+ summation control function. This function adds the single
+ shunt-voltage conversions for the desired channels in order to
+ compare the combined sum to the programmed limit. The Shunt-Voltage
+ Sum Limit register contains the programmed value that is compared
+ to the value in the Shunt-Voltage Sum register in order to
+ determine if the total summed limit is exceeded. If the
+ shunt-voltage sum limit value is exceeded, the critical alert pin
+ is asserted.
+
+ For the summation limit to have a meaningful value, it is necessary
+ to use the same shunt-resistor value on all enabled channels. If
+ this is not the case or if a channel should not be used for
+ triggering the critical alert pin, then this property can be used
+ exclude specific channels from the summation control function.
+ type: boolean
+
+ required:
+ - reg
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-sensor@40 {
+ compatible = "ti,ina3221";
+ reg = <0x40>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ input@0 {
+ reg = <0x0>;
+ /*
+ * Input channels are enabled by default in the device and so
+ * to disable, must be explicitly disabled in device-tree.
+ */
+ status = "disabled";
+ };
+
+ input@1 {
+ reg = <0x1>;
+ shunt-resistor-micro-ohms = <5000>;
+ };
+
+ input@2 {
+ reg = <0x2>;
+ label = "VDD_5V";
+ shunt-resistor-micro-ohms = <5000>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt b/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt
deleted file mode 100644
index 86b2e433a969..000000000000
--- a/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt
+++ /dev/null
@@ -1,135 +0,0 @@
-Pinctrl-based I2C Bus DeMux
-
-This binding describes an I2C bus demultiplexer that uses pin multiplexing to
-route the I2C signals, and represents the pin multiplexing configuration using
-the pinctrl device tree bindings. This may be used to select one I2C IP core at
-runtime which may have a better feature set for a given task than another I2C
-IP core on the SoC. The most simple example is to fall back to GPIO bitbanging
-if your current runtime configuration hits an errata of the internal IP core.
-
- +-------------------------------+
- | SoC |
- | | +-----+ +-----+
- | +------------+ | | dev | | dev |
- | |I2C IP Core1|--\ | +-----+ +-----+
- | +------------+ \-------+ | | |
- | |Pinctrl|--|------+--------+
- | +------------+ +-------+ |
- | |I2C IP Core2|--/ |
- | +------------+ |
- | |
- +-------------------------------+
-
-Required properties:
-- compatible: "i2c-demux-pinctrl"
-- i2c-parent: List of phandles of I2C masters available for selection. The first
- one will be used as default.
-- i2c-bus-name: The name of this bus. Also needed as pinctrl-name for the I2C
- parents.
-
-Furthermore, I2C mux properties and child nodes. See i2c-mux.yaml in this
-directory.
-
-Example:
-
-Here is a snipplet for a bus to be demuxed. It contains various i2c clients for
-HDMI, so the bus is named "i2c-hdmi":
-
- i2chdmi: i2c@8 {
-
- compatible = "i2c-demux-pinctrl";
- i2c-parent = <&gpioi2c>, <&iic2>, <&i2c2>;
- i2c-bus-name = "i2c-hdmi";
- #address-cells = <1>;
- #size-cells = <0>;
-
- ak4643: sound-codec@12 {
- compatible = "asahi-kasei,ak4643";
-
- #sound-dai-cells = <0>;
- reg = <0x12>;
- };
-
- composite-in@20 {
- compatible = "adi,adv7180";
- reg = <0x20>;
- remote = <&vin1>;
-
- port {
- adv7180: endpoint {
- bus-width = <8>;
- remote-endpoint = <&vin1ep0>;
- };
- };
- };
-
- hdmi@39 {
- compatible = "adi,adv7511w";
- reg = <0x39>;
- interrupt-parent = <&gpio1>;
- interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
-
- adi,input-depth = <8>;
- adi,input-colorspace = "rgb";
- adi,input-clock = "1x";
- adi,input-style = <1>;
- adi,input-justification = "evenly";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- adv7511_in: endpoint {
- remote-endpoint = <&du_out_lvds0>;
- };
- };
-
- port@1 {
- reg = <1>;
- adv7511_out: endpoint {
- remote-endpoint = <&hdmi_con>;
- };
- };
- };
- };
- };
-
-And for clarification, here are the snipplets for the i2c-parents:
-
- gpioi2c: i2c@9 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "i2c-gpio";
- gpios = <&gpio5 6 GPIO_ACTIVE_HIGH /* sda */
- &gpio5 5 GPIO_ACTIVE_HIGH /* scl */
- >;
- i2c-gpio,delay-us = <5>;
- };
-
-...
-
-&i2c2 {
- pinctrl-0 = <&i2c2_pins>;
- pinctrl-names = "i2c-hdmi";
-
- clock-frequency = <100000>;
-};
-
-...
-
-&iic2 {
- pinctrl-0 = <&iic2_pins>;
- pinctrl-names = "i2c-hdmi";
-
- clock-frequency = <100000>;
-};
-
-Please note:
-
-- pinctrl properties for the parent I2C controllers need a pinctrl state
- with the same name as i2c-bus-name, not "default"!
-
-- the i2c masters must have their status "disabled". This driver will
- enable them at runtime when needed.
diff --git a/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml b/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml
new file mode 100644
index 000000000000..2c08f2a7cf1e
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml
@@ -0,0 +1,172 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i2c/i2c-demux-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Pinctrl-based I2C Bus Demultiplexer
+
+maintainers:
+ - Wolfram Sang <wsa+renesas@sang-engineering.com>
+
+description: |
+ This binding describes an I2C bus demultiplexer that uses pin multiplexing to
+ route the I2C signals, and represents the pin multiplexing configuration
+ using the pinctrl device tree bindings. This may be used to select one I2C
+ IP core at runtime which may have a better feature set for a given task than
+ another I2C IP core on the SoC. The most simple example is to fall back to
+ GPIO bitbanging if your current runtime configuration hits an errata of the
+ internal IP core.
+
+ +-------------------------------+
+ | SoC |
+ | | +-----+ +-----+
+ | +------------+ | | dev | | dev |
+ | |I2C IP Core1|--\ | +-----+ +-----+
+ | +------------+ \-------+ | | |
+ | |Pinctrl|--|------+--------+
+ | +------------+ +-------+ |
+ | |I2C IP Core2|--/ |
+ | +------------+ |
+ | |
+ +-------------------------------+
+
+allOf:
+ - $ref: i2c-mux.yaml
+ - $ref: /schemas/i2c/i2c-controller.yaml#
+
+properties:
+ compatible:
+ const: i2c-demux-pinctrl
+
+ i2c-parent:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description:
+ List of phandles of I2C masters available for selection. The first one
+ will be used as default.
+
+ i2c-bus-name:
+ $ref: /schemas/types.yaml#/definitions/string
+ description:
+ The name of this bus. Also needed as pinctrl-name for the I2C parents.
+
+required:
+ - compatible
+ - i2c-parent
+ - i2c-bus-name
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ gpioi2c2: i2c-9 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "i2c-gpio";
+ scl-gpios = <&gpio5 5 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ i2c-gpio,delay-us = <5>;
+
+ // The I2C controller must have its status "disabled". The I2C bus
+ // demultiplexer will enable it at runtime when needed.
+ status = "disabled";
+ };
+
+ iic2: i2c@e6520000 {
+ reg = <0xe6520000 0x425>;
+ pinctrl-0 = <&iic2_pins>;
+ // The pinctrl property for the parent I2C controller needs a pinctrl
+ // state with the same name as i2c-bus-name in the I2C bus demultiplexer
+ // node, not "default"!
+ pinctrl-names = "i2c-hdmi";
+
+ clock-frequency = <100000>;
+
+ // The I2C controller must have its status "disabled". The I2C bus
+ // demultiplexer will enable it at runtime when needed.
+ status = "disabled";
+ };
+
+ i2c2: i2c@e6530000 {
+ reg = <0 0xe6530000 0 0x40>;
+ pinctrl-0 = <&i2c2_pins>;
+ // The pinctrl property for the parent I2C controller needs a pinctrl
+ // state with the same name as i2c-bus-name in the I2C bus demultiplexer
+ // node, not "default"!
+ pinctrl-names = "i2c-hdmi";
+
+ clock-frequency = <100000>;
+
+ // The I2C controller must have its status "disabled". The I2C bus
+ // demultiplexer will enable it at runtime when needed.
+ status = "disabled";
+ };
+
+ // Example for a bus to be demuxed. It contains various I2C clients for
+ // HDMI, so the bus is named "i2c-hdmi":
+ i2chdmi: i2c-mux3 {
+ compatible = "i2c-demux-pinctrl";
+ i2c-parent = <&iic2>, <&i2c2>, <&gpioi2c2>;
+ i2c-bus-name = "i2c-hdmi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ak4643: codec@12 {
+ compatible = "asahi-kasei,ak4643";
+ #sound-dai-cells = <0>;
+ reg = <0x12>;
+ };
+
+ composite-in@20 {
+ compatible = "adi,adv7180";
+ reg = <0x20>;
+
+ port {
+ adv7180: endpoint {
+ bus-width = <8>;
+ remote-endpoint = <&vin1ep0>;
+ };
+ };
+ };
+
+ hdmi@39 {
+ compatible = "adi,adv7511w";
+ reg = <0x39>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&cec_clock>;
+ clock-names = "cec";
+
+ avdd-supply = <&fixedregulator1v8>;
+ dvdd-supply = <&fixedregulator1v8>;
+ pvdd-supply = <&fixedregulator1v8>;
+ dvdd-3v-supply = <&fixedregulator3v3>;
+ bgvdd-supply = <&fixedregulator1v8>;
+
+ adi,input-depth = <8>;
+ adi,input-colorspace = "rgb";
+ adi,input-clock = "1x";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ adv7511_in: endpoint {
+ remote-endpoint = <&lvds0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ adv7511_out: endpoint {
+ remote-endpoint = <&hdmi_con_out>;
+ };
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
index 042d4dc636ee..8386cfe21532 100644
--- a/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
+++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
@@ -25,6 +25,7 @@ properties:
- items:
- enum:
+ - qcom,sc7280-cci
- qcom,sdm845-cci
- qcom,sm6350-cci
- qcom,sm8250-cci
@@ -159,6 +160,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,sc7280-cci
- qcom,sm8250-cci
- qcom,sm8450-cci
then:
diff --git a/Documentation/devicetree/bindings/i3c/i3c.yaml b/Documentation/devicetree/bindings/i3c/i3c.yaml
index ab69f4115de4..c816e295d565 100644
--- a/Documentation/devicetree/bindings/i3c/i3c.yaml
+++ b/Documentation/devicetree/bindings/i3c/i3c.yaml
@@ -55,6 +55,12 @@ properties:
May not be supported by all controllers.
+ mctp-controller:
+ type: boolean
+ description: |
+ Indicates that the system is accessible via this bus as an endpoint for
+ MCTP over I3C transport.
+
required:
- "#address-cells"
- "#size-cells"
@@ -119,12 +125,12 @@ patternProperties:
minimum: 0
maximum: 0x7f
- description: |
- First half of the Provisional ID (following the PID
+ First half of the Provisioned ID (following the PID
definition provided by the I3C specification).
Contains the manufacturer ID left-shifted by 1.
- description: |
- Second half of the Provisional ID (following the PID
+ Second half of the Provisioned ID (following the PID
definition provided by the I3C specification).
Contains the ORing of the part ID left-shifted by 16,
diff --git a/Documentation/devicetree/bindings/iio/accel/kionix,kx022a.yaml b/Documentation/devicetree/bindings/iio/accel/kionix,kx022a.yaml
index 986df1a6ff0a..66ea894dbe55 100644
--- a/Documentation/devicetree/bindings/iio/accel/kionix,kx022a.yaml
+++ b/Documentation/devicetree/bindings/iio/accel/kionix,kx022a.yaml
@@ -4,19 +4,23 @@
$id: http://devicetree.org/schemas/iio/accel/kionix,kx022a.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: ROHM/Kionix KX022A Accelerometer
+title: ROHM/Kionix KX022A, KX132-1211 and KX132ACR-LBZ Accelerometers
maintainers:
- Matti Vaittinen <mazziesaccount@gmail.com>
description: |
- KX022A is a 3-axis accelerometer supporting +/- 2G, 4G, 8G and 16G ranges,
- output data-rates from 0.78Hz to 1600Hz and a hardware-fifo buffering.
- KX022A can be accessed either via I2C or SPI.
+ KX022A, KX132ACR-LBZ and KX132-1211 are 3-axis accelerometers supporting
+ +/- 2G, 4G, 8G and 16G ranges, variable output data-rates and a
+ hardware-fifo buffering. These accelerometers can be accessed either
+ via I2C or SPI.
properties:
compatible:
- const: kionix,kx022a
+ enum:
+ - kionix,kx022a
+ - kionix,kx132-1211
+ - rohm,kx132acr-lbz
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml
index 7cc4ddc4e9b7..2aa1f4b063eb 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml
@@ -61,7 +61,7 @@ patternProperties:
required:
- reg
- additionalProperties: true
+ additionalProperties: false
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
diff --git a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml
index 875f394576c2..5cc6a9684077 100644
--- a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml
@@ -4,21 +4,31 @@
$id: http://devicetree.org/schemas/iio/adc/lltc,ltc2497.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Linear Technology / Analog Devices LTC2497 ADC
+title: Linear Technology / Analog Devices LTC2497 and LTC2309 ADC
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
+ - Liam Beguin <liambeguin@gmail.com>
description: |
- 16bit ADC supporting up to 16 single ended or 8 differential inputs.
- I2C interface.
+ LTC2309:
+ low noise, low power, 8-channel, 12-bit successive approximation ADC with an
+ I2C compatible serial interface.
- https://www.analog.com/media/en/technical-documentation/data-sheets/2497fb.pdf
- https://www.analog.com/media/en/technical-documentation/data-sheets/2499fe.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/2309fd.pdf
+
+ LTC2497:
+ LTC2499:
+ 16bit ADC supporting up to 16 single ended or 8 differential inputs.
+ I2C interface.
+
+ https://www.analog.com/media/en/technical-documentation/data-sheets/2497fb.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/2499fe.pdf
properties:
compatible:
enum:
+ - lltc,ltc2309
- lltc,ltc2497
- lltc,ltc2499
diff --git a/Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml b/Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml
new file mode 100644
index 000000000000..675319276197
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml
@@ -0,0 +1,205 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/microchip,mcp3564.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip MCP346X and MCP356X ADC Family
+
+maintainers:
+ - Marius Cristea <marius.cristea@microchip.com>
+
+description: |
+ Bindings for the Microchip family of 153.6 ksps, Low-Noise 16/24-Bit
+ Delta-Sigma ADCs with an SPI interface. Datasheet can be found here:
+ Datasheet for MCP3561, MCP3562, MCP3564 can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP3561-2-4-Family-Data-Sheet-DS20006181C.pdf
+ Datasheet for MCP3561R, MCP3562R, MCP3564R can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3561_2_4R-Data-Sheet-DS200006391C.pdf
+ Datasheet for MCP3461, MCP3462, MCP3464 can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3461-2-4-Two-Four-Eight-Channel-153.6-ksps-Low-Noise-16-Bit-Delta-Sigma-ADC-Data-Sheet-20006180D.pdf
+ Datasheet for MCP3461R, MCP3462R, MCP3464R can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3461-2-4R-Family-Data-Sheet-DS20006404C.pdf
+
+properties:
+ compatible:
+ enum:
+ - microchip,mcp3461
+ - microchip,mcp3462
+ - microchip,mcp3464
+ - microchip,mcp3461r
+ - microchip,mcp3462r
+ - microchip,mcp3464r
+ - microchip,mcp3561
+ - microchip,mcp3562
+ - microchip,mcp3564
+ - microchip,mcp3561r
+ - microchip,mcp3562r
+ - microchip,mcp3564r
+
+ reg:
+ maxItems: 1
+
+ spi-max-frequency:
+ maximum: 20000000
+
+ spi-cpha: true
+
+ spi-cpol: true
+
+ vdd-supply: true
+
+ avdd-supply: true
+
+ clocks:
+ description:
+ Phandle and clock identifier for external sampling clock.
+ If not specified, the internal crystal oscillator will be used.
+ maxItems: 1
+
+ interrupts:
+ description: IRQ line of the ADC
+ maxItems: 1
+
+ drive-open-drain:
+ description:
+ Whether to drive the IRQ signal as push-pull (default) or open-drain. Note
+ that the device requires this pin to become "high", otherwise it will stop
+ converting.
+ type: boolean
+
+ vref-supply:
+ description:
+ Some devices have a specific reference voltage supplied on a different
+ pin to the other supplies. Needed to be able to establish channel scaling
+ unless there is also an internal reference available (e.g. mcp3564r). In
+ case of "r" devices (e. g. mcp3564r), if it does not exists the internal
+ reference will be used.
+
+ microchip,hw-device-address:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 3
+ description:
+ The address is set on a per-device basis by fuses in the factory,
+ configured on request. If not requested, the fuses are set for 0x1.
+ The device address is part of the device markings to avoid
+ potential confusion. This address is coded on two bits, so four possible
+ addresses are available when multiple devices are present on the same
+ SPI bus with only one Chip Select line for all devices.
+ Each device communication starts by a CS falling edge, followed by the
+ clocking of the device address (BITS[7:6] - top two bits of COMMAND BYTE
+ which is first one on the wire).
+
+ "#io-channel-cells":
+ const: 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+patternProperties:
+ "^channel@([0-9]|([1-7][0-9]))$":
+ $ref: adc.yaml
+ type: object
+ unevaluatedProperties: false
+ description: Represents the external channels which are connected to the ADC.
+
+ properties:
+ reg:
+ description: The channel number in single-ended and differential mode.
+ minimum: 0
+ maximum: 79
+
+ required:
+ - reg
+
+dependencies:
+ spi-cpol: [ spi-cpha ]
+ spi-cpha: [ spi-cpol ]
+
+required:
+ - compatible
+ - reg
+ - microchip,hw-device-address
+ - spi-max-frequency
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+ - # External vref, no internal reference
+ if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - microchip,mcp3461
+ - microchip,mcp3462
+ - microchip,mcp3464
+ - microchip,mcp3561
+ - microchip,mcp3562
+ - microchip,mcp3564
+ then:
+ required:
+ - vref-supply
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "microchip,mcp3564r";
+ reg = <0>;
+ vref-supply = <&vref_reg>;
+ spi-cpha;
+ spi-cpol;
+ spi-max-frequency = <10000000>;
+ microchip,hw-device-address = <1>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@0 {
+ /* CH0 to AGND */
+ reg = <0>;
+ label = "CH0";
+ };
+
+ channel@1 {
+ /* CH1 to AGND */
+ reg = <1>;
+ label = "CH1";
+ };
+
+ /* diff-channels */
+ channel@11 {
+ reg = <11>;
+
+ /* CN0, CN1 */
+ diff-channels = <0 1>;
+ label = "CH0_CH1";
+ };
+
+ channel@22 {
+ reg = <0x22>;
+
+ /* CN1, CN2 */
+ diff-channels = <1 2>;
+ label = "CH1_CH3";
+ };
+
+ channel@23 {
+ reg = <0x23>;
+
+ /* CN1, CN3 */
+ diff-channels = <1 3>;
+ label = "CH1_CH3";
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml b/Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml
index f7b3fde4115a..06951ec5f5da 100644
--- a/Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml
@@ -18,7 +18,13 @@ description: |
properties:
compatible:
enum:
+ - microchip,mcp3910
- microchip,mcp3911
+ - microchip,mcp3912
+ - microchip,mcp3913
+ - microchip,mcp3914
+ - microchip,mcp3918
+ - microchip,mcp3919
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml b/Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml
index e004659099c1..d605999ffe28 100644
--- a/Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml
@@ -23,6 +23,9 @@ properties:
reg:
maxItems: 1
+ interrupts:
+ maxItems: 1
+
"#address-cells":
const: 1
diff --git a/Documentation/devicetree/bindings/iio/adc/ti,twl6030-gpadc.yaml b/Documentation/devicetree/bindings/iio/adc/ti,twl6030-gpadc.yaml
new file mode 100644
index 000000000000..e779a8986e0b
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/ti,twl6030-gpadc.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/ti,twl6030-gpadc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: GPADC subsystem in the TWL6030 power module
+
+maintainers:
+ - Andreas Kemnade <andreas@kemnade.info>
+
+description:
+ The GPADC subsystem in the TWL603X consists of a 10-bit ADC
+ combined with a 15-input analog multiplexer in the TWL6030 resp. a
+ 19-input analog muliplexer in the TWL6032.
+
+properties:
+ compatible:
+ enum:
+ - ti,twl6030-gpadc
+ - ti,twl6032-gpadc
+
+ interrupts:
+ maxItems: 1
+
+ "#io-channel-cells":
+ const: 1
+
+required:
+ - compatible
+ - interrupts
+ - "#io-channel-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ gpadc {
+ compatible = "ti,twl6030-gpadc";
+ interrupts = <3>;
+ #io-channel-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/addac/adi,ad74115.yaml b/Documentation/devicetree/bindings/iio/addac/adi,ad74115.yaml
index 2594fa192f93..2a04906531fb 100644
--- a/Documentation/devicetree/bindings/iio/addac/adi,ad74115.yaml
+++ b/Documentation/devicetree/bindings/iio/addac/adi,ad74115.yaml
@@ -32,7 +32,8 @@ properties:
spi-cpol: true
- reset-gpios: true
+ reset-gpios:
+ maxItems: 1
interrupts:
minItems: 1
diff --git a/Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml b/Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml
index 9fda56fa49c3..2ee6080deac7 100644
--- a/Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml
+++ b/Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml
@@ -4,20 +4,26 @@
$id: http://devicetree.org/schemas/iio/amplifiers/adi,hmc425a.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: HMC425A 6-bit Digital Step Attenuator
+title: Analog Devices HMC425A and similar Digital Step Attenuators
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
description: |
- Digital Step Attenuator IIO device with gpio interface.
+ Digital Step Attenuator IIO devices with gpio interface.
+ Offer various frequency and attenuation ranges.
HMC425A 0.5 dB LSB GaAs MMIC 6-BIT DIGITAL POSITIVE CONTROL ATTENUATOR, 2.2 - 8.0 GHz
- https://www.analog.com/media/en/technical-documentation/data-sheets/hmc425A.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/hmc425A.pdf
+
+ HMC540S 1 dB LSB Silicon MMIC 4-Bit Digital Positive Control Attenuator, 0.1 - 8 GHz
+ https://www.analog.com/media/en/technical-documentation/data-sheets/hmc540s.pdf
+
properties:
compatible:
enum:
- adi,hmc425a
+ - adi,hmc540s
vcc-supply: true
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5758.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5758.yaml
index 4e508bfcc9d8..5121685337b5 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,ad5758.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5758.yaml
@@ -78,7 +78,8 @@ properties:
- const: -1000
- const: 22000
- reset-gpios: true
+ reset-gpios:
+ maxItems: 1
adi,dc-dc-ilim-microamp:
enum: [150000, 200000, 250000, 300000, 350000, 400000]
diff --git a/Documentation/devicetree/bindings/iio/health/ti,afe4403.yaml b/Documentation/devicetree/bindings/iio/health/ti,afe4403.yaml
index b9b5beac33b2..5b6cde86b5a5 100644
--- a/Documentation/devicetree/bindings/iio/health/ti,afe4403.yaml
+++ b/Documentation/devicetree/bindings/iio/health/ti,afe4403.yaml
@@ -23,7 +23,8 @@ properties:
maxItems: 1
description: Connected to ADC_RDY pin.
- reset-gpios: true
+ reset-gpios:
+ maxItems: 1
required:
- compatible
diff --git a/Documentation/devicetree/bindings/iio/health/ti,afe4404.yaml b/Documentation/devicetree/bindings/iio/health/ti,afe4404.yaml
index 2958c4ca75b4..167d10bd60af 100644
--- a/Documentation/devicetree/bindings/iio/health/ti,afe4404.yaml
+++ b/Documentation/devicetree/bindings/iio/health/ti,afe4404.yaml
@@ -23,7 +23,8 @@ properties:
maxItems: 1
description: Connected to ADC_RDY pin.
- reset-gpios: true
+ reset-gpios:
+ maxItems: 1
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
index 1db6952ddca5..297b8a1a7ffb 100644
--- a/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
@@ -48,6 +48,11 @@ properties:
mount-matrix: true
+ invensense,level-shifter:
+ type: boolean
+ description: |
+ From ancient platform data struct: false: VLogic, true: VDD
+
i2c-gate:
$ref: /schemas/i2c/i2c-controller.yaml
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml b/Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml
index ee8724ad33ab..28b667a9cb76 100644
--- a/Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml
@@ -93,6 +93,9 @@ properties:
wakeup-source:
$ref: /schemas/types.yaml#/definitions/flag
+ mount-matrix:
+ description: an optional 3x3 mounting rotation matrix
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/iio/light/rohm,bu27010.yaml b/Documentation/devicetree/bindings/iio/light/rohm,bu27010.yaml
index 8376d64a641a..bed42d5d0d94 100644
--- a/Documentation/devicetree/bindings/iio/light/rohm,bu27010.yaml
+++ b/Documentation/devicetree/bindings/iio/light/rohm,bu27010.yaml
@@ -45,5 +45,6 @@ examples:
light-sensor@38 {
compatible = "rohm,bu27010";
reg = <0x38>;
+ vdd-supply = <&vdd>;
};
};
diff --git a/Documentation/devicetree/bindings/iio/pressure/rohm,bm1390.yaml b/Documentation/devicetree/bindings/iio/pressure/rohm,bm1390.yaml
new file mode 100644
index 000000000000..7c4ca6322bf8
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/pressure/rohm,bm1390.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/pressure/rohm,bm1390.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ROHM BM1390 pressure sensor
+
+maintainers:
+ - Matti Vaittinen <mazziesaccount@gmail.com>
+
+description:
+ BM1390GLV-Z is a pressure sensor which performs internal temperature
+ compensation for the MEMS. Pressure range is from 300 hPa to 1300 hPa
+ and sample averaging and IIR filtering is built in. Temperature
+ measurement is also supported.
+
+properties:
+ compatible:
+ const: rohm,bm1390glv-z
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ vdd-supply: true
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pressure-sensor@5d {
+ compatible = "rohm,bm1390glv-z";
+ reg = <0x5d>;
+
+ interrupt-parent = <&gpio1>;
+ interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
+
+ vdd-supply = <&vdd>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/resolver/adi,ad2s1210.yaml b/Documentation/devicetree/bindings/iio/resolver/adi,ad2s1210.yaml
new file mode 100644
index 000000000000..8980b3cd8337
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/resolver/adi,ad2s1210.yaml
@@ -0,0 +1,177 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/resolver/adi,ad2s1210.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD2S1210 Resolver-to-Digital Converter
+
+maintainers:
+ - Michael Hennerich <michael.hennerich@analog.com>
+
+description: |
+ The AD2S1210 is a complete 10-bit to 16-bit resolution tracking
+ resolver-to-digital converter, integrating an on-board programmable
+ sinusoidal oscillator that provides sine wave excitation for
+ resolvers.
+
+ The AD2S1210 allows the user to read the angular position or the
+ angular velocity data directly from the parallel outputs or through
+ the serial interface.
+
+ The mode of operation of the communication channel (parallel or serial) is
+ selected by the A0 and A1 input pins. In normal mode, data is latched by
+ toggling the SAMPLE line and can then be read directly. In configuration mode,
+ data is read or written using a register access scheme (address byte with
+ read/write flag and data byte).
+
+ A1 A0 Result
+ 0 0 Normal mode - position output
+ 0 1 Normal mode - velocity output
+ 1 0 Reserved
+ 1 1 Configuration mode
+
+ In normal mode, the resolution of the digital output is selected using
+ the RES0 and RES1 input pins. In configuration mode, the resolution is
+ selected by setting the RES0 and RES1 bits in the control register.
+
+ RES1 RES0 Resolution (Bits)
+ 0 0 10
+ 0 1 12
+ 1 0 14
+ 1 1 16
+
+ Note on SPI connections: The CS line on the AD2S1210 should hard-wired to
+ logic low and the WR/FSYNC line on the AD2S1210 should be connected to the
+ SPI CSn output of the SPI controller.
+
+ Datasheet:
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad2s1210.pdf
+
+properties:
+ compatible:
+ const: adi,ad2s1210
+
+ reg:
+ maxItems: 1
+
+ spi-max-frequency:
+ maximum: 25000000
+
+ spi-cpha: true
+
+ avdd-supply:
+ description:
+ A 4.75 to 5.25 V regulator that powers the Analog Supply Voltage (AVDD)
+ pin.
+
+ dvdd-supply:
+ description:
+ A 4.75 to 5.25 V regulator that powers the Digital Supply Voltage (DVDD)
+ pin.
+
+ vdrive-supply:
+ description:
+ A 2.3 to 5.25 V regulator that powers the Logic Power Supply Input
+ (VDrive) pin.
+
+ clocks:
+ maxItems: 1
+ description: External oscillator clock (CLKIN).
+
+ reset-gpios:
+ description:
+ GPIO connected to the /RESET pin. As the line needs to be low for the
+ reset to be active, it should be configured as GPIO_ACTIVE_LOW.
+ maxItems: 1
+
+ sample-gpios:
+ description:
+ GPIO connected to the /SAMPLE pin. As the line needs to be low to trigger
+ a sample, it should be configured as GPIO_ACTIVE_LOW.
+ maxItems: 1
+
+ mode-gpios:
+ description:
+ GPIO lines connected to the A0 and A1 pins. These pins select the data
+ transfer mode.
+ minItems: 2
+ maxItems: 2
+
+ resolution-gpios:
+ description:
+ GPIO lines connected to the RES0 and RES1 pins. These pins select the
+ resolution of the digital output. If omitted, it is assumed that the
+ RES0 and RES1 pins are hard-wired to match the assigned-resolution-bits
+ property.
+ minItems: 2
+ maxItems: 2
+
+ fault-gpios:
+ description:
+ GPIO lines connected to the LOT and DOS pins. These pins combined indicate
+ the type of fault present, if any. As these pins a pulled low to indicate
+ a fault condition, they should be configured as GPIO_ACTIVE_LOW.
+ minItems: 2
+ maxItems: 2
+
+ adi,fixed-mode:
+ description:
+ This is used to indicate the selected mode if A0 and A1 are hard-wired
+ instead of connected to GPIOS (i.e. mode-gpios is omitted).
+ $ref: /schemas/types.yaml#/definitions/string
+ enum: [config, velocity, position]
+
+ assigned-resolution-bits:
+ description:
+ Resolution of the digital output required by the application. This
+ determines the precision of the angle and/or the maximum speed that can
+ be measured. If resolution-gpios is omitted, it is assumed that RES0 and
+ RES1 are hard-wired to match this value.
+ enum: [10, 12, 14, 16]
+
+required:
+ - compatible
+ - reg
+ - spi-cpha
+ - avdd-supply
+ - dvdd-supply
+ - vdrive-supply
+ - clocks
+ - sample-gpios
+ - assigned-resolution-bits
+
+oneOf:
+ - required:
+ - mode-gpios
+ - required:
+ - adi,fixed-mode
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ resolver@0 {
+ compatible = "adi,ad2s1210";
+ reg = <0>;
+ spi-max-frequency = <20000000>;
+ spi-cpha;
+ avdd-supply = <&avdd_regulator>;
+ dvdd-supply = <&dvdd_regulator>;
+ vdrive-supply = <&vdrive_regulator>;
+ clocks = <&ext_osc>;
+ sample-gpios = <&gpio0 90 GPIO_ACTIVE_LOW>;
+ mode-gpios = <&gpio0 86 0>, <&gpio0 87 0>;
+ resolution-gpios = <&gpio0 88 0>, <&gpio0 89 0>;
+ assigned-resolution-bits = <16>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/fsl,scu-key.yaml b/Documentation/devicetree/bindings/input/fsl,scu-key.yaml
index e5a3c355ee1f..29921aab9d97 100644
--- a/Documentation/devicetree/bindings/input/fsl,scu-key.yaml
+++ b/Documentation/devicetree/bindings/input/fsl,scu-key.yaml
@@ -24,6 +24,8 @@ properties:
linux,keycodes:
maxItems: 1
+ wakeup-source: true
+
required:
- compatible
- linux,keycodes
diff --git a/Documentation/devicetree/bindings/input/qcom,pm8921-keypad.yaml b/Documentation/devicetree/bindings/input/qcom,pm8921-keypad.yaml
new file mode 100644
index 000000000000..88764adcd696
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/qcom,pm8921-keypad.yaml
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/qcom,pm8921-keypad.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm PM8921 PMIC KeyPad
+
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+allOf:
+ - $ref: input.yaml#
+ - $ref: matrix-keymap.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,pm8058-keypad
+ - qcom,pm8921-keypad
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: key sense
+ - description: key stuck
+
+ wakeup-source:
+ type: boolean
+ description: use any event on keypad as wakeup event
+
+ linux,keypad-wakeup:
+ type: boolean
+ deprecated: true
+ description: legacy version of the wakeup-source property
+
+ debounce:
+ description:
+ Time in microseconds that key must be pressed or
+ released for state change interrupt to trigger.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ scan-delay:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: time in microseconds to pause between successive scans of the
+ matrix array
+
+ row-hold:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: time in nanoseconds to pause between scans of each row in the
+ matrix array.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - linux,keymap
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/input/input.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ pmic {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ keypad@148 {
+ compatible = "qcom,pm8921-keypad";
+ reg = <0x148>;
+ interrupt-parent = <&pmicintc>;
+ interrupts = <74 IRQ_TYPE_EDGE_RISING>, <75 IRQ_TYPE_EDGE_RISING>;
+ linux,keymap = <
+ MATRIX_KEY(0, 0, KEY_VOLUMEUP)
+ MATRIX_KEY(0, 1, KEY_VOLUMEDOWN)
+ MATRIX_KEY(0, 2, KEY_CAMERA_FOCUS)
+ MATRIX_KEY(0, 3, KEY_CAMERA)
+ >;
+ keypad,num-rows = <1>;
+ keypad,num-columns = <5>;
+ debounce = <15>;
+ scan-delay = <32>;
+ row-hold = <91500>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/input/qcom,pm8xxx-keypad.txt b/Documentation/devicetree/bindings/input/qcom,pm8xxx-keypad.txt
deleted file mode 100644
index 4a9dc6ba96b1..000000000000
--- a/Documentation/devicetree/bindings/input/qcom,pm8xxx-keypad.txt
+++ /dev/null
@@ -1,90 +0,0 @@
-Qualcomm PM8xxx PMIC Keypad
-
-PROPERTIES
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be one of:
- "qcom,pm8058-keypad"
- "qcom,pm8921-keypad"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: address of keypad control register
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the first interrupt specifies the key sense interrupt
- and the second interrupt specifies the key stuck interrupt.
- The format of the specifier is defined by the binding
- document describing the node's interrupt parent.
-
-- linux,keymap:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the linux keymap. More information can be found in
- input/matrix-keymap.txt.
-
-- linux,keypad-no-autorepeat:
- Usage: optional
- Value type: <bool>
- Definition: don't enable autorepeat feature.
-
-- wakeup-source:
- Usage: optional
- Value type: <bool>
- Definition: use any event on keypad as wakeup event.
- (Legacy property supported: "linux,keypad-wakeup")
-
-- keypad,num-rows:
- Usage: required
- Value type: <u32>
- Definition: number of rows in the keymap. More information can be found
- in input/matrix-keymap.txt.
-
-- keypad,num-columns:
- Usage: required
- Value type: <u32>
- Definition: number of columns in the keymap. More information can be
- found in input/matrix-keymap.txt.
-
-- debounce:
- Usage: optional
- Value type: <u32>
- Definition: time in microseconds that key must be pressed or release
- for key sense interrupt to trigger.
-
-- scan-delay:
- Usage: optional
- Value type: <u32>
- Definition: time in microseconds to pause between successive scans
- of the matrix array.
-
-- row-hold:
- Usage: optional
- Value type: <u32>
- Definition: time in nanoseconds to pause between scans of each row in
- the matrix array.
-
-EXAMPLE
-
- keypad@148 {
- compatible = "qcom,pm8921-keypad";
- reg = <0x148>;
- interrupt-parent = <&pmicintc>;
- interrupts = <74 1>, <75 1>;
- linux,keymap = <
- MATRIX_KEY(0, 0, KEY_VOLUMEUP)
- MATRIX_KEY(0, 1, KEY_VOLUMEDOWN)
- MATRIX_KEY(0, 2, KEY_CAMERA_FOCUS)
- MATRIX_KEY(0, 3, KEY_CAMERA)
- >;
- keypad,num-rows = <1>;
- keypad,num-columns = <5>;
- debounce = <15>;
- scan-delay = <32>;
- row-hold = <91500>;
- };
diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
index 4d4e1a8e36be..b522c8d3ce0d 100644
--- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml
+++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
@@ -164,6 +164,8 @@ patternProperties:
"^rmi4-f[0-9a-f]+@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
description:
Other functions, not documented yet.
diff --git a/Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml b/Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml
index 4080422a9eb5..037e5d3c447f 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml
@@ -34,6 +34,9 @@ properties:
vdd-supply:
description: Regulator for voltage.
+ vddio-supply:
+ description: Optional Regulator for I/O voltage.
+
reset-gpios:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt b/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt
index f5021214edec..6c201a2ba8ac 100644
--- a/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt
+++ b/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt
@@ -1,7 +1,7 @@
Texas Instruments TWL family (twl4030) pwrbutton module
This module is part of the TWL4030. For more details about the whole
-chip see Documentation/devicetree/bindings/mfd/twl-family.txt.
+chip see Documentation/devicetree/bindings/mfd/ti,twl.yaml.
This module provides a simple power button event via an Interrupt.
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8939.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8939.yaml
new file mode 100644
index 000000000000..fd15ab5014fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8939.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interconnect/qcom,msm8939.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MSM8939 Network-On-Chip interconnect
+
+maintainers:
+ - Konrad Dybcio <konradybcio@kernel.org>
+
+description: |
+ The Qualcomm MSM8939 interconnect providers support adjusting the
+ bandwidth requirements between the various NoC fabrics.
+
+allOf:
+ - $ref: qcom,rpm-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,msm8939-bimc
+ - qcom,msm8939-pcnoc
+ - qcom,msm8939-snoc
+
+ reg:
+ maxItems: 1
+
+patternProperties:
+ '^interconnect-[a-z0-9\-]+$':
+ type: object
+ $ref: qcom,rpm-common.yaml#
+ description:
+ The interconnect providers do not have a separate QoS register space,
+ but share parent's space.
+
+ allOf:
+ - $ref: qcom,rpm-common.yaml#
+
+ properties:
+ compatible:
+ const: qcom,msm8939-snoc-mm
+
+ required:
+ - compatible
+
+ unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+
+ snoc: interconnect@580000 {
+ compatible = "qcom,msm8939-snoc";
+ reg = <0x00580000 0x14000>;
+ #interconnect-cells = <1>;
+ };
+
+ bimc: interconnect@400000 {
+ compatible = "qcom,msm8939-bimc";
+ reg = <0x00400000 0x62000>;
+ #interconnect-cells = <1>;
+
+ snoc_mm: interconnect-snoc {
+ compatible = "qcom,msm8939-snoc-mm";
+ #interconnect-cells = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8996.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8996.yaml
new file mode 100644
index 000000000000..e3f964aaad1b
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8996.yaml
@@ -0,0 +1,126 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interconnect/qcom,msm8996.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MSM8996 Network-On-Chip interconnect
+
+maintainers:
+ - Konrad Dybcio <konradybcio@kernel.org>
+
+description: |
+ The Qualcomm MSM8996 interconnect providers support adjusting the
+ bandwidth requirements between the various NoC fabrics.
+
+properties:
+ compatible:
+ enum:
+ - qcom,msm8996-a0noc
+ - qcom,msm8996-a1noc
+ - qcom,msm8996-a2noc
+ - qcom,msm8996-bimc
+ - qcom,msm8996-cnoc
+ - qcom,msm8996-mnoc
+ - qcom,msm8996-pnoc
+ - qcom,msm8996-snoc
+
+ reg:
+ maxItems: 1
+
+ clock-names:
+ minItems: 1
+ maxItems: 3
+
+ clocks:
+ minItems: 1
+ maxItems: 3
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+allOf:
+ - $ref: qcom,rpm-common.yaml#
+ - if:
+ properties:
+ compatible:
+ const: qcom,msm8996-a0noc
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: Aggregate0 System NoC AXI Clock.
+ - description: Aggregate0 Config NoC AHB Clock.
+ - description: Aggregate0 NoC MPU Clock.
+
+ clock-names:
+ items:
+ - const: aggre0_snoc_axi
+ - const: aggre0_cnoc_ahb
+ - const: aggre0_noc_mpu_cfg
+
+ required:
+ - power-domains
+
+ - if:
+ properties:
+ compatible:
+ const: qcom,msm8996-mnoc
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: CPU-NoC High-performance Bus Clock.
+
+ clock-names:
+ const: iface
+
+ - if:
+ properties:
+ compatible:
+ const: qcom,msm8996-a2noc
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: Aggregate2 NoC UFS AXI Clock
+ - description: UFS AXI Clock
+
+ clock-names:
+ items:
+ - const: aggre2_ufs_axi
+ - const: ufs_axi
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,gcc-msm8996.h>
+ #include <dt-bindings/clock/qcom,mmcc-msm8996.h>
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+
+ bimc: interconnect@408000 {
+ compatible = "qcom,msm8996-bimc";
+ reg = <0x00408000 0x5a000>;
+ #interconnect-cells = <1>;
+ };
+
+ a0noc: interconnect@543000 {
+ compatible = "qcom,msm8996-a0noc";
+ reg = <0x00543000 0x6000>;
+ #interconnect-cells = <1>;
+ clocks = <&gcc GCC_AGGRE0_SNOC_AXI_CLK>,
+ <&gcc GCC_AGGRE0_CNOC_AHB_CLK>,
+ <&gcc GCC_AGGRE0_NOC_MPU_CFG_AHB_CLK>;
+ clock-names = "aggre0_snoc_axi",
+ "aggre0_cnoc_ahb",
+ "aggre0_noc_mpu_cfg";
+ power-domains = <&gcc AGGRE0_NOC_GDSC>;
+ };
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,qcm2290.yaml b/Documentation/devicetree/bindings/interconnect/qcom,qcm2290.yaml
index f65a2fe846de..b6c15314c5c5 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,qcm2290.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,qcm2290.yaml
@@ -13,6 +13,9 @@ description: |
The Qualcomm QCM2290 interconnect providers support adjusting the
bandwidth requirements between the various NoC fabrics.
+allOf:
+ - $ref: qcom,rpm-common.yaml#
+
properties:
reg:
maxItems: 1
@@ -23,19 +26,6 @@ properties:
- qcom,qcm2290-cnoc
- qcom,qcm2290-snoc
- '#interconnect-cells':
- const: 1
-
- clock-names:
- items:
- - const: bus
- - const: bus_a
-
- clocks:
- items:
- - description: Bus Clock
- - description: Bus A Clock
-
# Child node's properties
patternProperties:
'^interconnect-[a-z0-9]+$':
@@ -44,6 +34,9 @@ patternProperties:
The interconnect providers do not have a separate QoS register space,
but share parent's space.
+ allOf:
+ - $ref: qcom,rpm-common.yaml#
+
properties:
compatible:
enum:
@@ -51,35 +44,16 @@ patternProperties:
- qcom,qcm2290-mmrt-virt
- qcom,qcm2290-mmnrt-virt
- '#interconnect-cells':
- const: 1
-
- clock-names:
- items:
- - const: bus
- - const: bus_a
-
- clocks:
- items:
- - description: Bus Clock
- - description: Bus A Clock
-
required:
- compatible
- - '#interconnect-cells'
- - clock-names
- - clocks
- additionalProperties: false
+ unevaluatedProperties: false
required:
- compatible
- reg
- - '#interconnect-cells'
- - clock-names
- - clocks
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
@@ -89,32 +63,20 @@ examples:
compatible = "qcom,qcm2290-snoc";
reg = <0x01880000 0x60200>;
#interconnect-cells = <1>;
- clock-names = "bus", "bus_a";
- clocks = <&rpmcc RPM_SMD_SNOC_CLK>,
- <&rpmcc RPM_SMD_SNOC_A_CLK>;
qup_virt: interconnect-qup {
compatible = "qcom,qcm2290-qup-virt";
#interconnect-cells = <1>;
- clock-names = "bus", "bus_a";
- clocks = <&rpmcc RPM_SMD_QUP_CLK>,
- <&rpmcc RPM_SMD_QUP_A_CLK>;
};
mmnrt_virt: interconnect-mmnrt {
compatible = "qcom,qcm2290-mmnrt-virt";
#interconnect-cells = <1>;
- clock-names = "bus", "bus_a";
- clocks = <&rpmcc RPM_SMD_MMNRT_CLK>,
- <&rpmcc RPM_SMD_MMNRT_A_CLK>;
};
mmrt_virt: interconnect-mmrt {
compatible = "qcom,qcm2290-mmrt-virt";
#interconnect-cells = <1>;
- clock-names = "bus", "bus_a";
- clocks = <&rpmcc RPM_SMD_MMRT_CLK>,
- <&rpmcc RPM_SMD_MMRT_A_CLK>;
};
};
@@ -122,16 +84,10 @@ examples:
compatible = "qcom,qcm2290-cnoc";
reg = <0x01900000 0x8200>;
#interconnect-cells = <1>;
- clock-names = "bus", "bus_a";
- clocks = <&rpmcc RPM_SMD_CNOC_CLK>,
- <&rpmcc RPM_SMD_CNOC_A_CLK>;
};
bimc: interconnect@4480000 {
compatible = "qcom,qcm2290-bimc";
reg = <0x04480000 0x80000>;
#interconnect-cells = <1>;
- clock-names = "bus", "bus_a";
- clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
- <&rpmcc RPM_SMD_BIMC_A_CLK>;
};
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,rpm-common.yaml b/Documentation/devicetree/bindings/interconnect/qcom,rpm-common.yaml
new file mode 100644
index 000000000000..1ea52b091609
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/qcom,rpm-common.yaml
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interconnect/qcom,rpm-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm RPMh Network-On-Chip Interconnect
+
+maintainers:
+ - Konrad Dybcio <konradybcio@kernel.org>
+
+description:
+ RPM interconnect providers support for managing system bandwidth requirements
+ through manual requests based on either predefined values or as indicated by
+ the bus monitor hardware. Each provider node represents a NoC bus master,
+ driven by a dedicated clock source.
+
+properties:
+ '#interconnect-cells':
+ oneOf:
+ - const: 2
+ - const: 1
+ deprecated: true
+
+required:
+ - '#interconnect-cells'
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml b/Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml
index 4f95d512012a..08c1c6b9d7cf 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml
@@ -7,13 +7,16 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm RPM Network-On-Chip Interconnect
maintainers:
- - Georgi Djakov <georgi.djakov@linaro.org>
+ - Georgi Djakov <djakov@kernel.org>
description: |
RPM interconnect providers support system bandwidth requirements through
RPM processor. The provider is able to communicate with the RPM through
the RPM shared memory device.
+allOf:
+ - $ref: qcom,rpm-common.yaml#
+
properties:
reg:
maxItems: 1
@@ -23,259 +26,22 @@ properties:
- qcom,msm8916-bimc
- qcom,msm8916-pcnoc
- qcom,msm8916-snoc
- - qcom,msm8939-bimc
- - qcom,msm8939-pcnoc
- - qcom,msm8939-snoc
- - qcom,msm8996-a0noc
- - qcom,msm8996-a1noc
- - qcom,msm8996-a2noc
- - qcom,msm8996-bimc
- - qcom,msm8996-cnoc
- - qcom,msm8996-mnoc
- - qcom,msm8996-pnoc
- - qcom,msm8996-snoc
- qcom,qcs404-bimc
- qcom,qcs404-pcnoc
- qcom,qcs404-snoc
- - qcom,sdm660-a2noc
- - qcom,sdm660-bimc
- - qcom,sdm660-cnoc
- - qcom,sdm660-gnoc
- - qcom,sdm660-mnoc
- - qcom,sdm660-snoc
-
- '#interconnect-cells':
- description: |
- Value: <1> is one cell in an interconnect specifier for the
- interconnect node id, <2> requires the interconnect node id and an
- extra path tag.
- enum: [ 1, 2 ]
-
- clocks:
- minItems: 2
- maxItems: 7
-
- clock-names:
- minItems: 2
- maxItems: 7
-
- power-domains:
- maxItems: 1
-
-# Child node's properties
-patternProperties:
- '^interconnect-[a-z0-9]+$':
- type: object
- additionalProperties: false
- description:
- snoc-mm is a child of snoc, sharing snoc's register address space.
-
- properties:
- compatible:
- enum:
- - qcom,msm8939-snoc-mm
-
- '#interconnect-cells':
- const: 1
-
- clock-names:
- items:
- - const: bus
- - const: bus_a
-
- clocks:
- items:
- - description: Bus Clock
- - description: Bus A Clock
-
- required:
- - compatible
- - '#interconnect-cells'
- - clock-names
- - clocks
required:
- compatible
- reg
- - '#interconnect-cells'
- - clock-names
- - clocks
-
-additionalProperties: false
-
-allOf:
- - if:
- properties:
- compatible:
- contains:
- enum:
- - qcom,msm8916-bimc
- - qcom,msm8916-pcnoc
- - qcom,msm8916-snoc
- - qcom,msm8939-bimc
- - qcom,msm8939-pcnoc
- - qcom,msm8939-snoc
- - qcom,msm8996-a1noc
- - qcom,msm8996-bimc
- - qcom,msm8996-cnoc
- - qcom,msm8996-pnoc
- - qcom,msm8996-snoc
- - qcom,qcs404-bimc
- - qcom,qcs404-pcnoc
- - qcom,qcs404-snoc
- - qcom,sdm660-bimc
- - qcom,sdm660-cnoc
- - qcom,sdm660-gnoc
- - qcom,sdm660-snoc
-
- then:
- properties:
- clock-names:
- items:
- - const: bus
- - const: bus_a
-
- clocks:
- items:
- - description: Bus Clock
- - description: Bus A Clock
- - if:
- properties:
- compatible:
- contains:
- enum:
- - qcom,msm8996-mnoc
- - qcom,sdm660-mnoc
-
- then:
- properties:
- clock-names:
- items:
- - const: bus
- - const: bus_a
- - const: iface
-
- clocks:
- items:
- - description: Bus Clock.
- - description: Bus A Clock.
- - description: CPU-NoC High-performance Bus Clock.
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- - qcom,msm8996-a0noc
-
- then:
- properties:
- clock-names:
- items:
- - const: aggre0_snoc_axi
- - const: aggre0_cnoc_ahb
- - const: aggre0_noc_mpu_cfg
-
- clocks:
- items:
- - description: Aggregate0 System NoC AXI Clock.
- - description: Aggregate0 Config NoC AHB Clock.
- - description: Aggregate0 NoC MPU Clock.
-
- required:
- - power-domains
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- - qcom,msm8996-a2noc
-
- then:
- properties:
- clock-names:
- items:
- - const: bus
- - const: bus_a
- - const: aggre2_ufs_axi
- - const: ufs_axi
-
- clocks:
- items:
- - description: Bus Clock
- - description: Bus A Clock
- - description: Aggregate2 NoC UFS AXI Clock
- - description: UFS AXI Clock
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- - qcom,sdm660-a2noc
-
- then:
- properties:
- clock-names:
- items:
- - const: bus
- - const: bus_a
- - const: ipa
- - const: ufs_axi
- - const: aggre2_ufs_axi
- - const: aggre2_usb3_axi
- - const: cfg_noc_usb2_axi
-
- clocks:
- items:
- - description: Bus Clock.
- - description: Bus A Clock.
- - description: IPA Clock.
- - description: UFS AXI Clock.
- - description: Aggregate2 UFS AXI Clock.
- - description: Aggregate2 USB3 AXI Clock.
- - description: Config NoC USB2 AXI Clock.
-
- - if:
- not:
- properties:
- compatible:
- contains:
- enum:
- - qcom,msm8939-snoc
- then:
- patternProperties:
- '^interconnect-[a-z0-9]+$': false
+unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmcc.h>
bimc: interconnect@400000 {
- compatible = "qcom,msm8916-bimc";
- reg = <0x00400000 0x62000>;
- #interconnect-cells = <1>;
- clock-names = "bus", "bus_a";
- clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
- <&rpmcc RPM_SMD_BIMC_A_CLK>;
- };
-
- pcnoc: interconnect@500000 {
- compatible = "qcom,msm8916-pcnoc";
- reg = <0x00500000 0x11000>;
- #interconnect-cells = <1>;
- clock-names = "bus", "bus_a";
- clocks = <&rpmcc RPM_SMD_PCNOC_CLK>,
- <&rpmcc RPM_SMD_PCNOC_A_CLK>;
- };
-
- snoc: interconnect@580000 {
- compatible = "qcom,msm8916-snoc";
- reg = <0x00580000 0x14000>;
- #interconnect-cells = <1>;
- clock-names = "bus", "bus_a";
- clocks = <&rpmcc RPM_SMD_SNOC_CLK>,
- <&rpmcc RPM_SMD_SNOC_A_CLK>;
+ compatible = "qcom,msm8916-bimc";
+ reg = <0x00400000 0x62000>;
+ #interconnect-cells = <1>;
};
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml
index a46497af1fd8..74ab080249ff 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml
@@ -113,6 +113,7 @@ allOf:
properties:
compatible:
enum:
+ - qcom,sdx65-mc-virt
- qcom,sm8250-qup-virt
then:
required:
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sdm660.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sdm660.yaml
new file mode 100644
index 000000000000..8f6bc6399626
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/qcom,sdm660.yaml
@@ -0,0 +1,108 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interconnect/qcom,sdm660.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SDM660 Network-On-Chip interconnect
+
+maintainers:
+ - Konrad Dybcio <konradybcio@kernel.org>
+
+description: |
+ The Qualcomm SDM660 interconnect providers support adjusting the
+ bandwidth requirements between the various NoC fabrics.
+
+properties:
+ compatible:
+ enum:
+ - qcom,sdm660-a2noc
+ - qcom,sdm660-bimc
+ - qcom,sdm660-cnoc
+ - qcom,sdm660-gnoc
+ - qcom,sdm660-mnoc
+ - qcom,sdm660-snoc
+
+ reg:
+ maxItems: 1
+
+ clock-names:
+ minItems: 1
+ maxItems: 5
+
+ clocks:
+ minItems: 1
+ maxItems: 5
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+allOf:
+ - $ref: qcom,rpm-common.yaml#
+ - if:
+ properties:
+ compatible:
+ const: qcom,sdm660-mnoc
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: CPU-NoC High-performance Bus Clock.
+
+ clock-names:
+ const: iface
+
+ - if:
+ properties:
+ compatible:
+ const: qcom,sdm660-a2noc
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: IPA Clock.
+ - description: UFS AXI Clock.
+ - description: Aggregate2 UFS AXI Clock.
+ - description: Aggregate2 USB3 AXI Clock.
+ - description: Config NoC USB2 AXI Clock.
+
+ clock-names:
+ items:
+ - const: ipa
+ - const: ufs_axi
+ - const: aggre2_ufs_axi
+ - const: aggre2_usb3_axi
+ - const: cfg_noc_usb2_axi
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,gcc-sdm660.h>
+ #include <dt-bindings/clock/qcom,mmcc-sdm660.h>
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+
+ bimc: interconnect@1008000 {
+ compatible = "qcom,sdm660-bimc";
+ reg = <0x01008000 0x78000>;
+ #interconnect-cells = <1>;
+ };
+
+ a2noc: interconnect@1704000 {
+ compatible = "qcom,sdm660-a2noc";
+ reg = <0x01704000 0xc100>;
+ #interconnect-cells = <1>;
+ clocks = <&rpmcc RPM_SMD_IPA_CLK>,
+ <&gcc GCC_UFS_AXI_CLK>,
+ <&gcc GCC_AGGRE2_UFS_AXI_CLK>,
+ <&gcc GCC_AGGRE2_USB3_AXI_CLK>,
+ <&gcc GCC_CFG_NOC_USB2_AXI_CLK>;
+ clock-names = "ipa",
+ "ufs_axi",
+ "aggre2_ufs_axi",
+ "aggre2_usb3_axi",
+ "cfg_noc_usb2_axi";
+ };
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sdx75-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sdx75-rpmh.yaml
new file mode 100644
index 000000000000..71cf7e252bfc
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/qcom,sdx75-rpmh.yaml
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interconnect/qcom,sdx75-rpmh.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm RPMh Network-On-Chip Interconnect on SDX75
+
+maintainers:
+ - Rohit Agarwal <quic_rohiagar@quicinc.com>
+
+description:
+ RPMh interconnect providers support system bandwidth requirements through
+ RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is
+ able to communicate with the BCM through the Resource State Coordinator (RSC)
+ associated with each execution environment. Provider nodes must point to at
+ least one RPMh device child node pertaining to their RSC and each provider
+ can map to multiple RPMh resources.
+
+properties:
+ compatible:
+ enum:
+ - qcom,sdx75-clk-virt
+ - qcom,sdx75-dc-noc
+ - qcom,sdx75-gem-noc
+ - qcom,sdx75-mc-virt
+ - qcom,sdx75-pcie-anoc
+ - qcom,sdx75-system-noc
+
+ '#interconnect-cells': true
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+required:
+ - compatible
+
+allOf:
+ - $ref: qcom,rpmh-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sdx75-clk-virt
+ - qcom,sdx75-mc-virt
+ then:
+ properties:
+ reg: false
+ else:
+ required:
+ - reg
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sdx75-clk-virt
+ then:
+ properties:
+ clocks:
+ items:
+ - description: RPMH CC QPIC Clock
+ required:
+ - clocks
+ else:
+ properties:
+ clocks: false
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+
+ clk_virt: interconnect-0 {
+ compatible = "qcom,sdx75-clk-virt";
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ clocks = <&rpmhcc RPMH_QPIC_CLK>;
+ };
+
+ system_noc: interconnect@1640000 {
+ compatible = "qcom,sdx75-system-noc";
+ reg = <0x1640000 0x4b400>;
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/qcom,mpm.yaml b/Documentation/devicetree/bindings/interrupt-controller/qcom,mpm.yaml
index 509d20c091af..6a206111d4e0 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/qcom,mpm.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/qcom,mpm.yaml
@@ -62,6 +62,9 @@ properties:
- description: MPM pin number
- description: GIC SPI number for the MPM pin
+ '#power-domain-cells':
+ const: 0
+
required:
- compatible
- reg
@@ -93,4 +96,5 @@ examples:
<86 183>,
<90 260>,
<91 260>;
+ #power-domain-cells = <0>;
};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml
index 4847b04be1a1..86d61896f591 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml
@@ -35,6 +35,7 @@ properties:
- qcom,sdm845-pdc
- qcom,sdx55-pdc
- qcom,sdx65-pdc
+ - qcom,sm4450-pdc
- qcom,sm6350-pdc
- qcom,sm8150-pdc
- qcom,sm8250-pdc
diff --git a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
index dc1f28e55266..0c07e8dda445 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
@@ -65,6 +65,8 @@ properties:
- items:
- enum:
- allwinner,sun20i-d1-plic
+ - sophgo,cv1800b-plic
+ - sophgo,sg2042-plic
- thead,th1520-plic
- const: thead,c900-plic
- items:
diff --git a/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-mswi.yaml b/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-mswi.yaml
new file mode 100644
index 000000000000..065f2544b63b
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-mswi.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/thead,c900-aclint-mswi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sophgo sg2042 CLINT Machine-level Software Interrupt Device
+
+maintainers:
+ - Inochi Amaoto <inochiama@outlook.com>
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - sophgo,sg2042-aclint-mswi
+ - const: thead,c900-aclint-mswi
+
+ reg:
+ maxItems: 1
+
+ interrupts-extended:
+ minItems: 1
+ maxItems: 4095
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts-extended
+
+examples:
+ - |
+ interrupt-controller@94000000 {
+ compatible = "sophgo,sg2042-aclint-mswi", "thead,c900-aclint-mswi";
+ interrupts-extended = <&cpu1intc 3>,
+ <&cpu2intc 3>,
+ <&cpu3intc 3>,
+ <&cpu4intc 3>;
+ reg = <0x94000000 0x00010000>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
index b1b2cf81b42f..aa9e1c0895a5 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
@@ -110,6 +110,7 @@ properties:
- qcom,sdm630-smmu-v2
- qcom,sdm845-smmu-v2
- qcom,sm6350-smmu-v2
+ - qcom,sm7150-smmu-v2
- const: qcom,adreno-smmu
- const: qcom,smmu-v2
- description: Qcom Adreno GPUs on Google Cheza platform
@@ -409,6 +410,7 @@ allOf:
contains:
enum:
- qcom,sm6350-smmu-v2
+ - qcom,sm7150-smmu-v2
- qcom,sm8150-smmu-500
- qcom,sm8250-smmu-500
then:
diff --git a/Documentation/devicetree/bindings/leds/backlight/common.yaml b/Documentation/devicetree/bindings/leds/backlight/common.yaml
index 3b60afbab68b..e0983e44934c 100644
--- a/Documentation/devicetree/bindings/leds/backlight/common.yaml
+++ b/Documentation/devicetree/bindings/leds/backlight/common.yaml
@@ -33,4 +33,21 @@ properties:
due to restrictions in a specific system, such as mounting conditions.
$ref: /schemas/types.yaml#/definitions/uint32
+ brightness-levels:
+ description:
+ Array of distinct brightness levels. The levels must be in the range
+ accepted by the underlying LED device. Typically these are in the range
+ from 0 to 255, but any range starting at 0 will do, as long as they are
+ accepted by the LED.
+ The 0 value means a 0% of brightness (darkest/off), while the last value
+ in the array represents a full 100% brightness (brightest).
+ If this array is not provided, the driver default mapping is used.
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+
+ default-brightness-level:
+ description:
+ The default brightness level (index into the array defined by the
+ "brightness-levels" property).
+ $ref: /schemas/types.yaml#/definitions/uint32
+
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/leds/backlight/led-backlight.yaml b/Documentation/devicetree/bindings/leds/backlight/led-backlight.yaml
index d7b78198abc2..f5554da6bc6c 100644
--- a/Documentation/devicetree/bindings/leds/backlight/led-backlight.yaml
+++ b/Documentation/devicetree/bindings/leds/backlight/led-backlight.yaml
@@ -16,6 +16,9 @@ description:
can also be used to describe a backlight device controlled by the output of
a LED driver.
+allOf:
+ - $ref: common.yaml#
+
properties:
compatible:
const: led-backlight
@@ -26,25 +29,11 @@ properties:
items:
maxItems: 1
- brightness-levels:
- description:
- Array of distinct brightness levels. The levels must be in the range
- accepted by the underlying LED devices. This is used to translate a
- backlight brightness level into a LED brightness level. If it is not
- provided, the identity mapping is used.
- $ref: /schemas/types.yaml#/definitions/uint32-array
-
- default-brightness-level:
- description:
- The default brightness level (index into the array defined by the
- "brightness-levels" property).
- $ref: /schemas/types.yaml#/definitions/uint32
-
required:
- compatible
- leds
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/leds/backlight/max8925-backlight.txt b/Documentation/devicetree/bindings/leds/backlight/max8925-backlight.txt
deleted file mode 100644
index b4cffdaa4137..000000000000
--- a/Documentation/devicetree/bindings/leds/backlight/max8925-backlight.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-88pm860x-backlight bindings
-
-Optional properties:
- - maxim,max8925-dual-string: whether support dual string
-
-Example:
-
- backlights {
- maxim,max8925-dual-string = <0>;
- };
diff --git a/Documentation/devicetree/bindings/leds/backlight/mps,mp3309c.yaml b/Documentation/devicetree/bindings/leds/backlight/mps,mp3309c.yaml
new file mode 100644
index 000000000000..4191e33626f5
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/backlight/mps,mp3309c.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/backlight/mps,mp3309c.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MPS MP3309C backlight
+
+maintainers:
+ - Flavio Suligoi <f.suligoi@asem.it>
+
+description: |
+ The Monolithic Power (MPS) MP3309C is a WLED step-up converter, featuring a
+ programmable switching frequency to optimize efficiency.
+ It supports two different dimming modes:
+
+ - analog mode, via I2C commands (default)
+ - PWM controlled mode.
+
+ The datasheet is available at:
+ https://www.monolithicpower.com/en/mp3309c.html
+
+allOf:
+ - $ref: common.yaml#
+
+properties:
+ compatible:
+ const: mps,mp3309c
+
+ reg:
+ maxItems: 1
+
+ pwms:
+ description: if present, the backlight is controlled in PWM mode.
+ maxItems: 1
+
+ enable-gpios:
+ description: GPIO used to enable the backlight in "analog-i2c" dimming mode.
+ maxItems: 1
+
+ mps,overvoltage-protection-microvolt:
+ description: Overvoltage protection (13.5V, 24V or 35.5V).
+ enum: [ 13500000, 24000000, 35500000 ]
+ default: 35500000
+
+ mps,no-sync-mode:
+ description: disable synchronous rectification mode
+ type: boolean
+
+required:
+ - compatible
+ - reg
+ - max-brightness
+ - default-brightness
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Backlight with PWM control */
+ backlight_pwm: backlight@17 {
+ compatible = "mps,mp3309c";
+ reg = <0x17>;
+ pwms = <&pwm1 0 3333333 0>; /* 300 Hz --> (1/f) * 1*10^9 */
+ max-brightness = <100>;
+ default-brightness = <80>;
+ mps,overvoltage-protection-microvolt = <24000000>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.yaml b/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.yaml
index 535690288990..b71f6454a4ac 100644
--- a/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.yaml
+++ b/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.yaml
@@ -11,6 +11,9 @@ maintainers:
- Daniel Thompson <daniel.thompson@linaro.org>
- Jingoo Han <jingoohan1@gmail.com>
+allOf:
+ - $ref: common.yaml#
+
properties:
compatible:
const: pwm-backlight
@@ -39,21 +42,6 @@ properties:
Delay in ms between disabling the backlight using GPIO and setting PWM
value to 0.
- brightness-levels:
- description:
- Array of distinct brightness levels. Typically these are in the range
- from 0 to 255, but any range starting at 0 will do. The actual brightness
- level (PWM duty cycle) will be interpolated from these values. 0 means a
- 0% duty cycle (darkest/off), while the last value in the array represents
- a 100% duty cycle (brightest).
- $ref: /schemas/types.yaml#/definitions/uint32-array
-
- default-brightness-level:
- description:
- The default brightness level (index into the array defined by the
- "brightness-levels" property).
- $ref: /schemas/types.yaml#/definitions/uint32
-
num-interpolated-steps:
description:
Number of interpolated steps between each value of brightness-levels
@@ -69,7 +57,7 @@ required:
- compatible
- pwms
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/leds/common.yaml b/Documentation/devicetree/bindings/leds/common.yaml
index 5fb7007f3618..c8d0ba5f2327 100644
--- a/Documentation/devicetree/bindings/leds/common.yaml
+++ b/Documentation/devicetree/bindings/leds/common.yaml
@@ -43,7 +43,7 @@ properties:
LED_COLOR_ID available, add a new one.
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
- maximum: 9
+ maximum: 14
function-enumerator:
description:
@@ -191,6 +191,8 @@ properties:
each of them having its own LED assigned (assuming they are not
hardwired). In such cases this property should contain phandle(s) of
related source device(s).
+ Another example is a GPIO line that will be monitored and mirror the
+ state of the line (with or without inversion flags) to the LED.
In many cases LED can be related to more than one device (e.g. one USB LED
vs. multiple USB ports). Each source should be represented by a node in
the device tree and be referenced by a phandle and a set of phandle
diff --git a/Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml b/Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml
index f2a6fa140f38..7526e3149f72 100644
--- a/Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml
+++ b/Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml
@@ -15,7 +15,10 @@ description:
properties:
compatible:
- const: pwm-ir-tx
+ oneOf:
+ - const: pwm-ir-tx
+ - const: nokia,n900-ir
+ deprecated: true
pwms:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/leds/kinetic,ktd202x.yaml b/Documentation/devicetree/bindings/leds/kinetic,ktd202x.yaml
new file mode 100644
index 000000000000..832c030a5acf
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/kinetic,ktd202x.yaml
@@ -0,0 +1,171 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/kinetic,ktd202x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Kinetic KTD2026/7 RGB/White LED Driver
+
+maintainers:
+ - André Apitzsch <git@apitzsch.eu>
+
+description: |
+ The KTD2026/7 is a RGB/White LED driver with I2C interface.
+
+ The data sheet can be found at:
+ https://www.kinet-ic.com/uploads/KTD2026-7-04h.pdf
+
+properties:
+ compatible:
+ enum:
+ - kinetic,ktd2026
+ - kinetic,ktd2027
+
+ reg:
+ maxItems: 1
+
+ vin-supply:
+ description: Regulator providing power to the "VIN" pin.
+
+ vio-supply:
+ description: Regulator providing power for pull-up of the I/O lines.
+ Note that this regulator does not directly connect to KTD2026, but is
+ needed for the correct operation of the status ("ST") and I2C lines.
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ multi-led:
+ type: object
+ $ref: leds-class-multicolor.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ patternProperties:
+ "^led@[0-3]$":
+ type: object
+ $ref: common.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ description: Index of the LED.
+ minimum: 0
+ maximum: 3
+
+ required:
+ - reg
+ - color
+
+ required:
+ - "#address-cells"
+ - "#size-cells"
+
+patternProperties:
+ "^led@[0-3]$":
+ type: object
+ $ref: common.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ description: Index of the LED.
+ minimum: 0
+ maximum: 3
+
+ required:
+ - reg
+
+required:
+ - compatible
+ - reg
+ - "#address-cells"
+ - "#size-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/leds/common.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led-controller@30 {
+ compatible = "kinetic,ktd2026";
+ reg = <0x30>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vin-supply = <&pm8916_l17>;
+ vio-supply = <&pm8916_l6>;
+
+ led@0 {
+ reg = <0>;
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@1 {
+ reg = <1>;
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+
+ led@2 {
+ reg = <2>;
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+ };
+ };
+ - |
+ #include <dt-bindings/leds/common.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led-controller@30 {
+ compatible = "kinetic,ktd2026";
+ reg = <0x30>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vin-supply = <&pm8916_l17>;
+ vio-supply = <&pm8916_l6>;
+
+ multi-led {
+ color = <LED_COLOR_ID_RGB>;
+ function = LED_FUNCTION_STATUS;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/leds/register-bit-led.yaml b/Documentation/devicetree/bindings/leds/register-bit-led.yaml
index ed26ec19ecbd..20930d327ae9 100644
--- a/Documentation/devicetree/bindings/leds/register-bit-led.yaml
+++ b/Documentation/devicetree/bindings/leds/register-bit-led.yaml
@@ -60,7 +60,7 @@ examples:
- |
syscon@10000000 {
- compatible = "arm,realview-pb1176-syscon", "syscon";
+ compatible = "arm,realview-pb1176-syscon", "syscon", "simple-mfd";
reg = <0x10000000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/Documentation/devicetree/bindings/mailbox/fsl,mu.yaml b/Documentation/devicetree/bindings/mailbox/fsl,mu.yaml
index 191c1ce15009..12e7a7d536a3 100644
--- a/Documentation/devicetree/bindings/mailbox/fsl,mu.yaml
+++ b/Documentation/devicetree/bindings/mailbox/fsl,mu.yaml
@@ -72,9 +72,9 @@ properties:
type : Channel type
channel : Channel number
- This MU support 5 type of unidirectional channels, each type
+ This MU support 6 type of unidirectional channels, each type
has 4 channels except RST channel which only has 1 channel.
- A total of 17 channels. Following types are
+ A total of 21 channels. Following types are
supported:
0 - TX channel with 32bit transmit register and IRQ transmit
acknowledgment support.
@@ -82,6 +82,7 @@ properties:
2 - TX doorbell channel. Without own register and no ACK support.
3 - RX doorbell channel.
4 - RST channel
+ 5 - Tx doorbell channel. With S/W ACK from the other side.
const: 2
clocks:
diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
index d2e25ff6db7f..a38413f8d132 100644
--- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
+++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
@@ -125,10 +125,12 @@ allOf:
items:
- description: primary pll parent of the clock driver
- description: XO clock
+ - description: GCC GPLL0 clock source
clock-names:
items:
- const: pll
- const: xo
+ - const: gpll0
- if:
properties:
diff --git a/Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml b/Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
index cc6f66eccc84..a35f9483dc71 100644
--- a/Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
+++ b/Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
@@ -34,6 +34,7 @@ properties:
- qcom,sm8350-ipcc
- qcom,sm8450-ipcc
- qcom,sm8550-ipcc
+ - qcom,sm8650-ipcc
- const: qcom,ipcc
reg:
diff --git a/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml b/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml
index aeaddbf574b0..8b15a0532120 100644
--- a/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml
+++ b/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml
@@ -74,6 +74,10 @@ patternProperties:
type: object # DT nodes are json objects
additionalProperties: false
properties:
+
+ compatible:
+ const: xlnx,zynqmp-ipi-dest-mailbox
+
xlnx,ipi-id:
description:
Remote Xilinx IPI agent ID of which the mailbox is connected to.
@@ -95,6 +99,7 @@ patternProperties:
- const: remote_response_region
required:
+ - compatible
- reg
- reg-names
- "#mbox-cells"
@@ -124,6 +129,7 @@ examples:
ranges;
mailbox: mailbox@ff9905c0 {
+ compatible = "xlnx,zynqmp-ipi-dest-mailbox";
reg = <0x0 0xff9905c0 0x0 0x20>,
<0x0 0xff9905e0 0x0 0x20>,
<0x0 0xff990e80 0x0 0x20>,
diff --git a/Documentation/devicetree/bindings/media/amlogic,meson6-ir.yaml b/Documentation/devicetree/bindings/media/amlogic,meson6-ir.yaml
index 3f9fa92703bb..0f95fe8dd9ac 100644
--- a/Documentation/devicetree/bindings/media/amlogic,meson6-ir.yaml
+++ b/Documentation/devicetree/bindings/media/amlogic,meson6-ir.yaml
@@ -19,6 +19,7 @@ properties:
- amlogic,meson6-ir
- amlogic,meson8b-ir
- amlogic,meson-gxbb-ir
+ - amlogic,meson-s4-ir
- items:
- const: amlogic,meson-gx-ir
- const: amlogic,meson-gxbb-ir
diff --git a/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
index 30a335b10762..2008a47c0580 100644
--- a/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
+++ b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
@@ -18,6 +18,7 @@ properties:
items:
- enum:
- starfive,jh7110-csi2rx
+ - ti,j721e-csi2rx
- const: cdns,csi2rx
reg:
diff --git a/Documentation/devicetree/bindings/media/i2c/hynix,hi846.yaml b/Documentation/devicetree/bindings/media/i2c/hynix,hi846.yaml
index 1e2df8cf2937..60f19e1152b3 100644
--- a/Documentation/devicetree/bindings/media/i2c/hynix,hi846.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/hynix,hi846.yaml
@@ -14,6 +14,9 @@ description: |-
interface and CCI (I2C compatible) control bus. The output format
is raw Bayer.
+allOf:
+ - $ref: /schemas/media/video-interface-devices.yaml#
+
properties:
compatible:
const: hynix,hi846
@@ -86,7 +89,7 @@ required:
- vddd-supply
- port
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
@@ -109,6 +112,8 @@ examples:
vddio-supply = <&reg_camera_vddio>;
reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
shutdown-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>;
+ orientation = <0>;
+ rotation = <0>;
port {
camera_out: endpoint {
diff --git a/Documentation/devicetree/bindings/media/i2c/onnn,mt9m114.yaml b/Documentation/devicetree/bindings/media/i2c/onnn,mt9m114.yaml
new file mode 100644
index 000000000000..f6b87892068a
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/onnn,mt9m114.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/onnn,mt9m114.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: onsemi 1/6-inch 720p CMOS Digital Image Sensor
+
+maintainers:
+ - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+description: |-
+ The onsemi MT9M114 is a 1/6-inch 720p (1.26 Mp) CMOS digital image sensor
+ with an active pixel-array size of 1296H x 976V. It is programmable through
+ an I2C interface and outputs image data over a 8-bit parallel or 1-lane MIPI
+ CSI-2 connection.
+
+properties:
+ compatible:
+ const: onnn,mt9m114
+
+ reg:
+ description: I2C device address
+ enum:
+ - 0x48
+ - 0x5d
+
+ clocks:
+ description: EXTCLK clock signal
+ maxItems: 1
+
+ vdd-supply:
+ description:
+ Core digital voltage supply, 1.8V
+
+ vddio-supply:
+ description:
+ I/O digital voltage supply, 1.8V or 2.8V
+
+ vaa-supply:
+ description:
+ Analog voltage supply, 2.8V
+
+ reset-gpios:
+ description: |-
+ Reference to the GPIO connected to the RESET_BAR pin, if any (active
+ low).
+
+ port:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ additionalProperties: false
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ additionalProperties: false
+
+ properties:
+ bus-type:
+ enum: [4, 5, 6]
+
+ link-frequencies: true
+ remote-endpoint: true
+
+ # The number and mapping of lanes (for CSI-2), and the bus width and
+ # signal polarities (for parallel and BT.656) are fixed and must not
+ # be specified.
+
+ required:
+ - bus-type
+ - link-frequencies
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - vdd-supply
+ - vddio-supply
+ - vaa-supply
+ - port
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/media/video-interfaces.h>
+
+ i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sensor@48 {
+ compatible = "onnn,mt9m114";
+ reg = <0x48>;
+
+ clocks = <&clk24m 0>;
+
+ reset-gpios = <&gpio5 21 GPIO_ACTIVE_LOW>;
+
+ vddio-supply = <&reg_cam_1v8>;
+ vdd-supply = <&reg_cam_1v8>;
+ vaa-supply = <&reg_2p8v>;
+
+ port {
+ endpoint {
+ bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
+ link-frequencies = /bits/ 64 <384000000>;
+ remote-endpoint = <&mipi_csi_in>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml
index 763cebe03dc2..67c1c291327b 100644
--- a/Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml
@@ -68,12 +68,6 @@ properties:
marked GPIO_ACTIVE_LOW.
maxItems: 1
- rotation:
- enum:
- - 0 # Sensor Mounted Upright
- - 180 # Sensor Mounted Upside Down
- default: 0
-
port:
$ref: /schemas/graph.yaml#/$defs/port-base
additionalProperties: false
@@ -114,7 +108,7 @@ required:
- reset-gpios
- port
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml
index 50579c947f3c..d96199031b66 100644
--- a/Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml
@@ -52,10 +52,6 @@ properties:
description:
GPIO connected to the reset pin (active low)
- orientation: true
-
- rotation: true
-
port:
$ref: /schemas/graph.yaml#/$defs/port-base
additionalProperties: false
@@ -95,7 +91,7 @@ required:
- dvdd-supply
- port
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov5640.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov5640.yaml
index a621032f9bd0..2c5e69356658 100644
--- a/Documentation/devicetree/bindings/media/i2c/ovti,ov5640.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov5640.yaml
@@ -44,11 +44,6 @@ properties:
description: >
Reference to the GPIO connected to the reset pin, if any.
- rotation:
- enum:
- - 0
- - 180
-
port:
description: Digital Output Port
$ref: /schemas/graph.yaml#/$defs/port-base
@@ -85,7 +80,7 @@ required:
- DOVDD-supply
- port
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov5642.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov5642.yaml
new file mode 100644
index 000000000000..01f8b2b3fd17
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov5642.yaml
@@ -0,0 +1,141 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/ovti,ov5642.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: OmniVision OV5642 Image Sensor
+
+maintainers:
+ - Fabio Estevam <festevam@gmail.com>
+
+allOf:
+ - $ref: /schemas/media/video-interface-devices.yaml#
+
+properties:
+ compatible:
+ const: ovti,ov5642
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ description: XCLK Input Clock
+
+ AVDD-supply:
+ description: Analog voltage supply, 2.8V.
+
+ DVDD-supply:
+ description: Digital core voltage supply, 1.5V.
+
+ DOVDD-supply:
+ description: Digital I/O voltage supply, 1.8V.
+
+ powerdown-gpios:
+ maxItems: 1
+ description: Reference to the GPIO connected to the powerdown pin, if any.
+
+ reset-gpios:
+ maxItems: 1
+ description: Reference to the GPIO connected to the reset pin, if any.
+
+ port:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ description: |
+ Video output port.
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ bus-type:
+ enum: [5, 6]
+
+ bus-width:
+ enum: [8, 10]
+ default: 10
+
+ data-shift:
+ enum: [0, 2]
+ default: 0
+
+ hsync-active:
+ enum: [0, 1]
+ default: 1
+
+ vsync-active:
+ enum: [0, 1]
+ default: 1
+
+ pclk-sample:
+ enum: [0, 1]
+ default: 1
+
+ allOf:
+ - if:
+ properties:
+ bus-type:
+ const: 6
+ then:
+ properties:
+ hsync-active: false
+ vsync-active: false
+
+ - if:
+ properties:
+ bus-width:
+ const: 10
+ then:
+ properties:
+ data-shift:
+ const: 0
+
+ required:
+ - bus-type
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - port
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/media/video-interfaces.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ camera@3c {
+ compatible = "ovti,ov5642";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ov5642>;
+ clocks = <&clk_ext_camera>;
+ DOVDD-supply = <&vgen4_reg>;
+ AVDD-supply = <&vgen3_reg>;
+ DVDD-supply = <&vgen2_reg>;
+ powerdown-gpios = <&gpio1 19 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
+
+ port {
+ ov5642_to_parallel: endpoint {
+ bus-type = <MEDIA_BUS_TYPE_PARALLEL>;
+ remote-endpoint = <&parallel_from_ov5642>;
+ bus-width = <8>;
+ data-shift = <2>; /* lines 9:2 are used */
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pclk-sample = <1>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov5693.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov5693.yaml
index 6829a4aadd22..3368b3bd8ef2 100644
--- a/Documentation/devicetree/bindings/media/i2c/ovti,ov5693.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov5693.yaml
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Omnivision OV5693/OV5695 CMOS Sensors
maintainers:
- - Tommaso Merciai <tommaso.merciai@amarulasolutions.com>
+ - Tommaso Merciai <tomm.merciai@gmail.com>
description: |
The Omnivision OV5693/OV5695 are high performance, 1/4-inch, 5 megapixel, CMOS
diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml
index e2470dd5920c..60903da84e1f 100644
--- a/Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml
@@ -91,7 +91,7 @@ required:
- vddd-supply
- port
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx415.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx415.yaml
index 642f9b15d359..9a00dab2e8a3 100644
--- a/Documentation/devicetree/bindings/media/i2c/sony,imx415.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/sony,imx415.yaml
@@ -44,14 +44,6 @@ properties:
description: Sensor reset (XCLR) GPIO
maxItems: 1
- flash-leds: true
-
- lens-focus: true
-
- orientation: true
-
- rotation: true
-
port:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
@@ -89,7 +81,7 @@ required:
- ovdd-supply
- port
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
index 289737721c2c..0b71e6f911a8 100644
--- a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
@@ -69,6 +69,7 @@ properties:
maxItems: 1
i2c-alias:
+ $ref: /schemas/types.yaml#/definitions/uint32
description:
The I2C address used for the serializer. Transactions to this
address on the I2C bus where the deserializer resides are
diff --git a/Documentation/devicetree/bindings/media/nokia,n900-ir b/Documentation/devicetree/bindings/media/nokia,n900-ir
deleted file mode 100644
index 13a18ce37dd1..000000000000
--- a/Documentation/devicetree/bindings/media/nokia,n900-ir
+++ /dev/null
@@ -1,20 +0,0 @@
-Device-Tree bindings for LIRC TX driver for Nokia N900(RX51)
-
-Required properties:
- - compatible: should be "nokia,n900-ir".
- - pwms: specifies PWM used for IR signal transmission.
-
-Example node:
-
- pwm9: dmtimer-pwm@9 {
- compatible = "ti,omap-dmtimer-pwm";
- ti,timers = <&timer9>;
- ti,clock-source = <0x00>; /* timer_sys_ck */
- #pwm-cells = <3>;
- };
-
- ir: n900-ir {
- compatible = "nokia,n900-ir";
-
- pwms = <&pwm9 0 26316 0>; /* 38000 Hz */
- };
diff --git a/Documentation/devicetree/bindings/media/nuvoton,npcm-ece.yaml b/Documentation/devicetree/bindings/media/nuvoton,npcm-ece.yaml
new file mode 100644
index 000000000000..b47468e54504
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/nuvoton,npcm-ece.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/nuvoton,npcm-ece.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Nuvoton NPCM Encoding Compression Engine
+
+maintainers:
+ - Joseph Liu <kwliu@nuvoton.com>
+ - Marvin Lin <kflin@nuvoton.com>
+
+description: |
+ Video Encoding Compression Engine (ECE) present on Nuvoton NPCM SoCs.
+
+properties:
+ compatible:
+ enum:
+ - nuvoton,npcm750-ece
+ - nuvoton,npcm845-ece
+
+ reg:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - resets
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/reset/nuvoton,npcm7xx-reset.h>
+
+ ece: video-codec@f0820000 {
+ compatible = "nuvoton,npcm750-ece";
+ reg = <0xf0820000 0x2000>;
+ resets = <&rstc NPCM7XX_RESET_IPSRST2 NPCM7XX_RESET_ECE>;
+ };
diff --git a/Documentation/devicetree/bindings/media/nuvoton,npcm-vcd.yaml b/Documentation/devicetree/bindings/media/nuvoton,npcm-vcd.yaml
new file mode 100644
index 000000000000..c885f559d2e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/nuvoton,npcm-vcd.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/nuvoton,npcm-vcd.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Nuvoton NPCM Video Capture/Differentiation Engine
+
+maintainers:
+ - Joseph Liu <kwliu@nuvoton.com>
+ - Marvin Lin <kflin@nuvoton.com>
+
+description: |
+ Video Capture/Differentiation Engine (VCD) present on Nuvoton NPCM SoCs.
+
+properties:
+ compatible:
+ enum:
+ - nuvoton,npcm750-vcd
+ - nuvoton,npcm845-vcd
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+ nuvoton,sysgcr:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle to access GCR (Global Control Register) registers.
+
+ nuvoton,sysgfxi:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle to access GFXI (Graphics Core Information) registers.
+
+ nuvoton,ece:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle to access ECE (Encoding Compression Engine) registers.
+
+ memory-region:
+ maxItems: 1
+ description:
+ CMA pool to use for buffers allocation instead of the default CMA pool.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - resets
+ - nuvoton,sysgcr
+ - nuvoton,sysgfxi
+ - nuvoton,ece
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/reset/nuvoton,npcm7xx-reset.h>
+
+ vcd: vcd@f0810000 {
+ compatible = "nuvoton,npcm750-vcd";
+ reg = <0xf0810000 0x10000>;
+ interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&rstc NPCM7XX_RESET_IPSRST2 NPCM7XX_RESET_VCD>;
+ nuvoton,sysgcr = <&gcr>;
+ nuvoton,sysgfxi = <&gfxi>;
+ nuvoton,ece = <&ece>;
+ };
diff --git a/Documentation/devicetree/bindings/media/qcom,sdm845-venus-v2.yaml b/Documentation/devicetree/bindings/media/qcom,sdm845-venus-v2.yaml
index d5f80976f4cf..6228fd2b3246 100644
--- a/Documentation/devicetree/bindings/media/qcom,sdm845-venus-v2.yaml
+++ b/Documentation/devicetree/bindings/media/qcom,sdm845-venus-v2.yaml
@@ -48,6 +48,14 @@ properties:
iommus:
maxItems: 2
+ interconnects:
+ maxItems: 2
+
+ interconnect-names:
+ items:
+ - const: video-mem
+ - const: cpu-cfg
+
operating-points-v2: true
opp-table:
type: object
diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml
index 772ec3283bc6..c57e1f488895 100644
--- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml
+++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml
@@ -68,6 +68,13 @@ properties:
iommus:
maxItems: 1
+ resets:
+ items:
+ - description: AXI reset line
+ - description: AXI bus interface unit reset line
+ - description: APB reset line
+ - description: APB bus interface unit reset line
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml b/Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml
index 3691cd4962b2..3a5ff3f47060 100644
--- a/Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml
+++ b/Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml
@@ -75,13 +75,20 @@ properties:
power-domains:
maxItems: 1
+ samsung,pmu-syscon:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Power Management Unit (PMU) system controller interface, used to
+ power/start the ISP.
+
patternProperties:
"^pmu@[0-9a-f]+$":
type: object
additionalProperties: false
+ deprecated: true
description:
Node representing the SoC's Power Management Unit (duplicated with the
- correct PMU node in the SoC).
+ correct PMU node in the SoC). Deprecated, use samsung,pmu-syscon.
properties:
reg:
@@ -131,6 +138,7 @@ required:
- clock-names
- interrupts
- ranges
+ - samsung,pmu-syscon
- '#size-cells'
additionalProperties: false
@@ -179,15 +187,12 @@ examples:
<&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>;
iommu-names = "isp", "drc", "fd", "mcuctl";
power-domains = <&pd_isp>;
+ samsung,pmu-syscon = <&pmu_system_controller>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
- pmu@10020000 {
- reg = <0x10020000 0x3000>;
- };
-
i2c-isp@12140000 {
compatible = "samsung,exynos4212-i2c-isp";
reg = <0x12140000 0x100>;
diff --git a/Documentation/devicetree/bindings/media/samsung,fimc.yaml b/Documentation/devicetree/bindings/media/samsung,fimc.yaml
index b3486c38a05b..7808d61f1fa3 100644
--- a/Documentation/devicetree/bindings/media/samsung,fimc.yaml
+++ b/Documentation/devicetree/bindings/media/samsung,fimc.yaml
@@ -118,7 +118,7 @@ examples:
#clock-cells = <1>;
#address-cells = <1>;
#size-cells = <1>;
- ranges = <0x0 0x0 0x18000000>;
+ ranges = <0x0 0x0 0xba1000>;
clocks = <&clock CLK_SCLK_CAM0>, <&clock CLK_SCLK_CAM1>,
<&clock CLK_PIXELASYNCM0>, <&clock CLK_PIXELASYNCM1>;
@@ -133,9 +133,9 @@ examples:
pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>;
pinctrl-names = "default";
- fimc@11800000 {
+ fimc@0 {
compatible = "samsung,exynos4212-fimc";
- reg = <0x11800000 0x1000>;
+ reg = <0x00000000 0x1000>;
interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clock CLK_FIMC0>,
<&clock CLK_SCLK_FIMC0>;
@@ -152,9 +152,9 @@ examples:
/* ... FIMC 1-3 */
- csis@11880000 {
+ csis@80000 {
compatible = "samsung,exynos4210-csis";
- reg = <0x11880000 0x4000>;
+ reg = <0x00080000 0x4000>;
interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clock CLK_CSIS0>,
<&clock CLK_SCLK_CSIS0>;
@@ -187,9 +187,9 @@ examples:
/* ... CSIS 1 */
- fimc-lite@12390000 {
+ fimc-lite@b90000 {
compatible = "samsung,exynos4212-fimc-lite";
- reg = <0x12390000 0x1000>;
+ reg = <0xb90000 0x1000>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&pd_isp>;
clocks = <&isp_clock CLK_ISP_FIMC_LITE0>;
@@ -199,9 +199,9 @@ examples:
/* ... FIMC-LITE 1 */
- fimc-is@12000000 {
+ fimc-is@800000 {
compatible = "samsung,exynos4212-fimc-is";
- reg = <0x12000000 0x260000>;
+ reg = <0x00800000 0x260000>;
interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&isp_clock CLK_ISP_FIMC_LITE0>,
@@ -237,18 +237,15 @@ examples:
<&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>;
iommu-names = "isp", "drc", "fd", "mcuctl";
power-domains = <&pd_isp>;
+ samsung,pmu-syscon = <&pmu_system_controller>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
- pmu@10020000 {
- reg = <0x10020000 0x3000>;
- };
-
- i2c-isp@12140000 {
+ i2c-isp@940000 {
compatible = "samsung,exynos4212-i2c-isp";
- reg = <0x12140000 0x100>;
+ reg = <0x00940000 0x100>;
clocks = <&isp_clock CLK_ISP_I2C1_ISP>;
clock-names = "i2c_isp";
pinctrl-0 = <&fimc_is_i2c1>;
diff --git a/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml b/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml
new file mode 100644
index 000000000000..f762fdc05e4d
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml
@@ -0,0 +1,100 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/ti,j721e-csi2rx-shim.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI J721E CSI2RX Shim
+
+description: |
+ The TI J721E CSI2RX Shim is a wrapper around Cadence CSI2RX bridge that
+ enables sending captured frames to memory over PSI-L DMA. In the J721E
+ Technical Reference Manual (SPRUIL1B) it is referred to as "SHIM" under the
+ CSI_RX_IF section.
+
+maintainers:
+ - Jai Luthra <j-luthra@ti.com>
+
+properties:
+ compatible:
+ const: ti,j721e-csi2rx-shim
+
+ dmas:
+ maxItems: 1
+
+ dma-names:
+ items:
+ - const: rx0
+
+ reg:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+ ranges: true
+
+ "#address-cells": true
+
+ "#size-cells": true
+
+patternProperties:
+ "^csi-bridge@":
+ type: object
+ description: CSI2 bridge node.
+ $ref: cdns,csi2rx.yaml#
+
+required:
+ - compatible
+ - reg
+ - dmas
+ - dma-names
+ - power-domains
+ - ranges
+ - "#address-cells"
+ - "#size-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+ ti_csi2rx0: ticsi2rx@4500000 {
+ compatible = "ti,j721e-csi2rx-shim";
+ dmas = <&main_udmap 0x4940>;
+ dma-names = "rx0";
+ reg = <0x4500000 0x1000>;
+ power-domains = <&k3_pds 26 TI_SCI_PD_EXCLUSIVE>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ cdns_csi2rx: csi-bridge@4504000 {
+ compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
+ reg = <0x4504000 0x1000>;
+ clocks = <&k3_clks 26 2>, <&k3_clks 26 0>, <&k3_clks 26 2>,
+ <&k3_clks 26 2>, <&k3_clks 26 3>, <&k3_clks 26 3>;
+ clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+ phys = <&dphy0>;
+ phy-names = "dphy";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ csi2_0: port@0 {
+
+ reg = <0>;
+
+ csi2rx0_in_sensor: endpoint {
+ remote-endpoint = <&csi2_cam0>;
+ bus-type = <4>; /* CSI2 DPHY. */
+ clock-lanes = <0>;
+ data-lanes = <1 2>;
+ };
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/video-interfaces.yaml b/Documentation/devicetree/bindings/media/video-interfaces.yaml
index a211d49dc2ac..26e3e7d7c67b 100644
--- a/Documentation/devicetree/bindings/media/video-interfaces.yaml
+++ b/Documentation/devicetree/bindings/media/video-interfaces.yaml
@@ -160,6 +160,7 @@ properties:
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 8
+ uniqueItems: true
items:
# Assume up to 9 physical lane indices
maximum: 8
diff --git a/Documentation/devicetree/bindings/memory-controllers/ingenic,nemc.yaml b/Documentation/devicetree/bindings/memory-controllers/ingenic,nemc.yaml
index b40cec0eb651..ee74a362f4ca 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ingenic,nemc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ingenic,nemc.yaml
@@ -40,6 +40,7 @@ patternProperties:
".*@[0-9]+$":
type: object
$ref: mc-peripheral-props.yaml#
+ additionalProperties: true
required:
- compatible
diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
index 56e62cd0b36a..25f3bb9890ae 100644
--- a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
@@ -80,6 +80,8 @@ properties:
patternProperties:
"flash@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
compatible:
contains:
diff --git a/Documentation/devicetree/bindings/memory-controllers/rockchip,rk3399-dmc.yaml b/Documentation/devicetree/bindings/memory-controllers/rockchip,rk3399-dmc.yaml
index 4e4af3cfc0fe..1f58ee99be28 100644
--- a/Documentation/devicetree/bindings/memory-controllers/rockchip,rk3399-dmc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/rockchip,rk3399-dmc.yaml
@@ -18,7 +18,7 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Node to get DDR loading. Refer to
- Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt.
+ Documentation/devicetree/bindings/devfreq/event/rockchip,dfi.yaml.
clocks:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml b/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml
index b049837ee669..c7a8a041da50 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml
@@ -130,7 +130,7 @@ patternProperties:
bus. The device can be a NAND chip, SRAM device, NOR device
or an ASIC.
$ref: ti,gpmc-child.yaml
-
+ additionalProperties: true
required:
- compatible
diff --git a/Documentation/devicetree/bindings/memory-controllers/xlnx,versal-ddrmc-edac.yaml b/Documentation/devicetree/bindings/memory-controllers/xlnx,versal-ddrmc-edac.yaml
new file mode 100644
index 000000000000..12f8e9f350bc
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/xlnx,versal-ddrmc-edac.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/xlnx,versal-ddrmc-edac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx Versal DDRMC (Integrated DDR Memory Controller)
+
+maintainers:
+ - Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>
+ - Sai Krishna Potthuri <sai.krishna.potthuri@amd.com>
+
+description:
+ The integrated DDR Memory Controllers (DDRMCs) support both DDR4 and LPDDR4/
+ 4X memory interfaces. Versal DDR memory controller has an optional ECC support
+ which correct single bit ECC errors and detect double bit ECC errors.
+
+properties:
+ compatible:
+ const: xlnx,versal-ddrmc
+
+ reg:
+ items:
+ - description: DDR Memory Controller registers
+ - description: NOC registers corresponding to DDR Memory Controller
+
+ reg-names:
+ items:
+ - const: base
+ - const: noc
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ memory-controller@f6150000 {
+ compatible = "xlnx,versal-ddrmc";
+ reg = <0x0 0xf6150000 0x0 0x2000>, <0x0 0xf6070000 0x0 0x20000>;
+ reg-names = "base", "noc";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/arm,dev-platforms-syscon.yaml b/Documentation/devicetree/bindings/mfd/arm,dev-platforms-syscon.yaml
new file mode 100644
index 000000000000..46b164ae0831
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/arm,dev-platforms-syscon.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/arm,dev-platforms-syscon.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Arm Ltd Developer Platforms System Controllers
+
+maintainers:
+ - Linus Walleij <linus.walleij@linaro.org>
+
+description:
+ The Arm Ltd Integrator, Realview, and Versatile families of developer
+ platforms are contain various system controller blocks. Often these blocks
+ are part of a daughterboard or motherboard module.
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - arm,integrator-ap-syscon
+ - arm,integrator-cp-syscon
+ - arm,integrator-sp-syscon
+ - arm,im-pd1-syscon
+ - const: syscon
+ - items:
+ - enum:
+ - arm,core-module-integrator
+ - arm,integrator-ap-syscon
+ - arm,integrator-cp-syscon
+ - arm,integrator-sp-syscon
+ - arm,realview-eb-syscon
+ - arm,realview-pb1176-syscon
+ - arm,realview-pb11mp-syscon
+ - arm,realview-pba8-syscon
+ - arm,realview-pbx-syscon
+ - arm,versatile-ib2-syscon
+ - const: syscon
+ - const: simple-mfd
+ - items:
+ - enum:
+ - arm,realview-eb11mp-revb-syscon
+ - arm,realview-eb11mp-revc-syscon
+ - const: arm,realview-eb-syscon
+ - const: syscon
+ - const: simple-mfd
+
+ reg:
+ maxItems: 1
+
+ ranges: true
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties:
+ type: object
+
+...
diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml
index c14def1b2ad2..9c2a04829da5 100644
--- a/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml
+++ b/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml
@@ -148,47 +148,47 @@ examples:
pinctrl_nand: nand-pins {
function = "nand";
- group = "nand_grp";
+ pins = "nand_grp";
};
pinctrl_gpio35_alt: gpio35_alt-pins {
function = "gpio35_alt";
- pin = "gpio35";
+ pins = "gpio35";
};
pinctrl_dectpd: dectpd-pins {
function = "dectpd";
- group = "dectpd_grp";
+ pins = "dectpd_grp";
};
pinctrl_vdsl_phy_override_0: vdsl_phy_override_0-pins {
function = "vdsl_phy_override_0";
- group = "vdsl_phy_override_0_grp";
+ pins = "vdsl_phy_override_0_grp";
};
pinctrl_vdsl_phy_override_1: vdsl_phy_override_1-pins {
function = "vdsl_phy_override_1";
- group = "vdsl_phy_override_1_grp";
+ pins = "vdsl_phy_override_1_grp";
};
pinctrl_vdsl_phy_override_2: vdsl_phy_override_2-pins {
function = "vdsl_phy_override_2";
- group = "vdsl_phy_override_2_grp";
+ pins = "vdsl_phy_override_2_grp";
};
pinctrl_vdsl_phy_override_3: vdsl_phy_override_3-pins {
function = "vdsl_phy_override_3";
- group = "vdsl_phy_override_3_grp";
+ pins = "vdsl_phy_override_3_grp";
};
pinctrl_dsl_gpio8: dsl_gpio8-pins {
function = "dsl_gpio8";
- group = "dsl_gpio8";
+ pins = "dsl_gpio8";
};
pinctrl_dsl_gpio9: dsl_gpio9-pins {
function = "dsl_gpio9";
- group = "dsl_gpio9";
+ pins = "dsl_gpio9";
};
};
};
diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml
index 4d594739b382..c2941638c8f2 100644
--- a/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml
+++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml
@@ -230,7 +230,7 @@ examples:
pinctrl_nand: nand-pins {
function = "nand";
- group = "nand_grp";
+ pins = "nand_grp";
};
};
};
diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml
index aae83d432880..44e77d77d314 100644
--- a/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml
+++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml
@@ -240,7 +240,7 @@ examples:
pinctrl_uart1: uart1-pins {
function = "uart1";
- group = "uart1_grp";
+ pins = "uart1_grp";
};
};
};
diff --git a/Documentation/devicetree/bindings/mfd/max8925.txt b/Documentation/devicetree/bindings/mfd/max8925.txt
deleted file mode 100644
index 4f0dc6638e5e..000000000000
--- a/Documentation/devicetree/bindings/mfd/max8925.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-* Maxim max8925 Power Management IC
-
-Required parent device properties:
-- compatible : "maxim,max8925"
-- reg : the I2C slave address for the max8925 chip
-- interrupts : IRQ line for the max8925 chip
-- interrupt-controller: describes the max8925 as an interrupt
- controller (has its own domain)
-- #interrupt-cells : should be 1.
- - The cell is the max8925 local IRQ number
-
-Optional parent device properties:
-- maxim,tsc-irq: there are 2 IRQ lines for max8925, one is indicated in
- interrupts property, the other is indicated here.
-
-max8925 consists of a large and varied group of sub-devices:
-
-Device Supply Names Description
------- ------------ -----------
-max8925-onkey : : On key
-max8925-rtc : : RTC
-max8925-regulator : : Regulators
-max8925-backlight : : Backlight
-max8925-touch : : Touchscreen
-max8925-power : : Charger
-
-Example:
-
- pmic: max8925@3c {
- compatible = "maxim,max8925";
- reg = <0x3c>;
- interrupts = <1>;
- interrupt-parent = <&intcmux4>;
- interrupt-controller;
- #interrupt-cells = <1>;
- maxim,tsc-irq = <0>;
-
- regulators {
- SDV1 {
- regulator-min-microvolt = <637500>;
- regulator-max-microvolt = <1425000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- LDO1 {
- regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <3900000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- };
- backlight {
- maxim,max8925-dual-string = <0>;
- };
- charger {
- batt-detect = <0>;
- topoff-threshold = <1>;
- fast-charge = <7>;
- no-temp-support = <0>;
- no-insert-detect = <0>;
- };
- };
diff --git a/Documentation/devicetree/bindings/mfd/max8998.txt b/Documentation/devicetree/bindings/mfd/max8998.txt
deleted file mode 100644
index 4ed52184d081..000000000000
--- a/Documentation/devicetree/bindings/mfd/max8998.txt
+++ /dev/null
@@ -1,125 +0,0 @@
-* Maxim MAX8998, National/TI LP3974 multi-function device
-
-The Maxim MAX8998 is a multi-function device which includes voltage/current
-regulators, real time clock, battery charging controller and several
-other sub-blocks. It is interfaced using an I2C interface. Each sub-block
-is addressed by the host system using different i2c slave address.
-
-PMIC sub-block
---------------
-
-The PMIC sub-block contains a number of voltage and current regulators,
-with controllable parameters and dynamic voltage scaling capability.
-In addition, it includes a real time clock and battery charging controller
-as well. It is accessible at I2C address 0x66.
-
-Required properties:
-- compatible: Should be one of the following:
- - "maxim,max8998" for Maxim MAX8998
- - "national,lp3974" or "ti,lp3974" for National/TI LP3974.
-- reg: Specifies the i2c slave address of the pmic block. It should be 0x66.
-
-Optional properties:
-- interrupts: Interrupt specifiers for two interrupt sources.
- - First interrupt specifier is for main interrupt.
- - Second interrupt specifier is for power-on/-off interrupt.
-- max8998,pmic-buck1-dvs-gpios: GPIO specifiers for two host gpios used
- for buck 1 dvs. The format of the gpio specifier depends on the gpio
- controller.
-- max8998,pmic-buck2-dvs-gpio: GPIO specifier for host gpio used
- for buck 2 dvs. The format of the gpio specifier depends on the gpio
- controller.
-- max8998,pmic-buck1-default-dvs-idx: Default voltage setting selected from
- the possible 4 options selectable by the dvs gpios. The value of this
- property should be 0, 1, 2 or 3. If not specified or out of range,
- a default value of 0 is taken.
-- max8998,pmic-buck2-default-dvs-idx: Default voltage setting selected from
- the possible 2 options selectable by the dvs gpios. The value of this
- property should be 0 or 1. If not specified or out of range, a default
- value of 0 is taken.
-- max8998,pmic-buck-voltage-lock: If present, disallows changing of
- preprogrammed buck dvfs voltages.
-
-Additional properties required if max8998,pmic-buck1-dvs-gpios is defined:
-- max8998,pmic-buck1-dvs-voltage: An array of 4 voltage values in microvolts
- for buck1 regulator that can be selected using dvs gpio.
-
-Additional properties required if max8998,pmic-buck2-dvs-gpio is defined:
-- max8998,pmic-buck2-dvs-voltage: An array of 2 voltage values in microvolts
- for buck2 regulator that can be selected using dvs gpio.
-
-Regulators: All the regulators of MAX8998 to be instantiated shall be
-listed in a child node named 'regulators'. Each regulator is represented
-by a child node of the 'regulators' node.
-
- regulator-name {
- /* standard regulator bindings here */
- };
-
-Following regulators of the MAX8998 PMIC block are supported. Note that
-the 'n' in regulator name, as in LDOn or BUCKn, represents the LDO or BUCK
-number as described in MAX8998 datasheet.
-
- - LDOn
- - valid values for n are 2 to 17
- - Example: LDO2, LDO10, LDO17
- - BUCKn
- - valid values for n are 1 to 4.
- - Example: BUCK1, BUCK2, BUCK3, BUCK4
-
- - ENVICHG: Battery Charging Current Monitor Output. This is a fixed
- voltage type regulator
-
- - ESAFEOUT1: (ldo19)
- - ESAFEOUT2: (ld020)
-
- - CHARGER: main battery charger current control
-
-Standard regulator bindings are used inside regulator subnodes. Check
- Documentation/devicetree/bindings/regulator/regulator.txt
-for more details.
-
-Example:
-
- pmic@66 {
- compatible = "maxim,max8998-pmic";
- reg = <0x66>;
- interrupt-parent = <&wakeup_eint>;
- interrupts = <4 0>, <3 0>;
-
- /* Buck 1 DVS settings */
- max8998,pmic-buck1-default-dvs-idx = <0>;
- max8998,pmic-buck1-dvs-gpios = <&gpx0 0 1 0 0>, /* SET1 */
- <&gpx0 1 1 0 0>; /* SET2 */
- max8998,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
- <1000000>, <950000>;
-
- /* Buck 2 DVS settings */
- max8998,pmic-buck2-default-dvs-idx = <0>;
- max8998,pmic-buck2-dvs-gpio = <&gpx0 0 3 0 0>; /* SET3 */
- max8998,pmic-buck2-dvs-voltage = <1350000>, <1300000>;
-
- /* Regulators to instantiate */
- regulators {
- ldo2_reg: LDO2 {
- regulator-name = "VDD_ALIVE_1.1V";
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- regulator-always-on;
- };
-
- buck1_reg: BUCK1 {
- regulator-name = "VDD_ARM_1.2V";
- regulator-min-microvolt = <950000>;
- regulator-max-microvolt = <1350000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- charger_reg: CHARGER {
- regulator-name = "CHARGER";
- regulator-min-microamp = <90000>;
- regulator-max-microamp = <800000>;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml b/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml
index da67742c5aa9..0da5cae3852e 100644
--- a/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml
+++ b/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml
@@ -45,8 +45,13 @@ properties:
patternProperties:
"^led@[0-3]$":
$ref: /schemas/leds/common.yaml#
+ unevaluatedProperties: false
type: object
+ properties:
+ reg:
+ maximum: 3
+
additionalProperties: false
vss1-supply:
diff --git a/Documentation/devicetree/bindings/mfd/maxim,max8925.yaml b/Documentation/devicetree/bindings/mfd/maxim,max8925.yaml
new file mode 100644
index 000000000000..86dd810851ab
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/maxim,max8925.yaml
@@ -0,0 +1,145 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/maxim,max8925.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MAX8925 PMIC from Maxim Integrated.
+
+maintainers:
+ - Lee Jones <lee@kernel.org>
+
+properties:
+ compatible:
+ const: maxim,max8925
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 1
+ description:
+ The cell is the IRQ number
+
+ maxim,tsc-irq:
+ description: second interrupt from max8925
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ regulators:
+ type: object
+
+ patternProperties:
+ "^SDV[1-3]$|^LDO[1-9]$|^LDO1[0-9]$|^LDO20$":
+ description: regulator configuration for SDV1-3 and LDO1-20
+ $ref: /schemas/regulator/regulator.yaml
+ unevaluatedProperties: false
+
+ additionalProperties: false
+
+ backlight:
+ type: object
+ properties:
+ maxim,max8925-dual-string:
+ description: set to 1 to support dual string
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+ default: 0
+
+ additionalProperties: false
+
+ charger:
+ type: object
+ properties:
+ batt-detect:
+ description: set to 1 if battery detection via ID pin is supported
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+ default: 0
+
+ topoff-threshold:
+ description: charging current in topoff mode, configures bits 5-6 in CHG_CNTL1
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 3
+ default: 0
+
+ fast-charge:
+ description: set charging current in fast mode, configures bits 0-3 in CHG_CNTL1
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+ default: 0
+
+ no-temp-support:
+ description: set to 1 if temperature sensing is not supported
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+ default: 0
+
+ no-insert-detect:
+ description: set to 1 if AC detection is not supported
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+ default: 0
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-controller
+ - "#interrupt-cells"
+ - regulators
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@3c {
+ compatible = "maxim,max8925";
+ reg = <0x3c>;
+ interrupts = <1>;
+ interrupt-parent = <&intcmux4>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ maxim,tsc-irq = <0>;
+
+ regulators {
+ SDV1 {
+ regulator-min-microvolt = <637500>;
+ regulator-max-microvolt = <1425000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDO1 {
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <3900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+
+ backlight {
+ maxim,max8925-dual-string = <0>;
+ };
+
+ charger {
+ batt-detect = <0>;
+ topoff-threshold = <1>;
+ fast-charge = <7>;
+ no-temp-support = <0>;
+ no-insert-detect = <0>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/maxim,max8998.yaml b/Documentation/devicetree/bindings/mfd/maxim,max8998.yaml
new file mode 100644
index 000000000000..f3c3f64fd012
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/maxim,max8998.yaml
@@ -0,0 +1,324 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/maxim,max8998.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim MAX8998, National/TI LP3974 Power Management IC
+
+maintainers:
+ - Krzysztof Kozlowski <krzk@kernel.org>
+
+description:
+ The Maxim MAX8998 is a Power Management IC which includes voltage/current
+ regulators, real time clock, battery charging controller and several other
+ sub-blocks. It is interfaced using an I2C interface. Each sub-block is
+ addressed by the host system using different i2c slave address.
+
+properties:
+ compatible:
+ enum:
+ - maxim,max8998
+ - national,lp3974
+ - ti,lp3974
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ minItems: 1
+ items:
+ - description: Main interrupt
+ - description: Power-on/-off interrupt
+
+ max8998,pmic-buck1-dvs-gpios:
+ maxItems: 2
+ description:
+ Two host gpios used for buck1 DVS.
+
+ max8998,pmic-buck2-dvs-gpio:
+ maxItems: 1
+ description:
+ Host gpio used for buck2 DVS.
+
+ max8998,pmic-buck1-default-dvs-idx:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2, 3]
+ default: 0
+ description:
+ Default voltage setting selected from the possible 4 options selectable
+ by the DVS gpios.
+
+ max8998,pmic-buck2-default-dvs-idx:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+ default: 0
+ description:
+ Default voltage setting selected from the possible 2 options selectable
+ by the DVS GPIOs.
+
+ max8998,pmic-buck-voltage-lock:
+ type: boolean
+ description:
+ If present, disallows changing of preprogrammed buck DVS voltages.
+
+ max8998,pmic-buck1-dvs-voltage:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ maxItems: 4
+ description:
+ Four voltage values in microvolts for buck1 regulator that can be
+ selected using DVS GPIO.
+
+ max8998,pmic-buck2-dvs-voltage:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ maxItems: 2
+ description:
+ Two voltage values in microvolts for buck2 regulator that can be
+ selected using DVS GPIO.
+
+ regulators:
+ type: object
+ additionalProperties: false
+
+ properties:
+ CHARGER:
+ type: object
+ $ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
+ description:
+ CHARGER is main battery charger current control, wrongly represented
+ as regulator.
+
+ properties:
+ regulator-min-microamp:
+ minimum: 90000
+ maximum: 800000
+
+ regulator-max-microamp:
+ minimum: 90000
+ maximum: 800000
+
+ regulator-min-microvolt: false
+ regulator-max-microvolt: false
+
+ required:
+ - regulator-name
+
+ patternProperties:
+ "^(LDO([2-9]|1[0-7])|BUCK[1-4])$":
+ type: object
+ $ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
+
+ required:
+ - regulator-name
+
+ "^(EN32KHz-AP|EN32KHz-CP|ENVICHG|ESAFEOUT[12])$":
+ type: object
+ $ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
+ description: |
+ EN32KHz-AP and EN32KHz-CP are 32768 Hz clocks, wrongly represented as
+ regulators.
+ ENVICHG is a Battery Charging Current Monitor Output.
+
+ properties:
+ regulator-min-microvolt: false
+ regulator-max-microvolt: false
+
+ required:
+ - regulator-name
+
+dependencies:
+ max8998,pmic-buck1-dvs-gpios: [ "max8998,pmic-buck1-dvs-voltage" ]
+ max8998,pmic-buck2-dvs-gpio: [ "max8998,pmic-buck2-dvs-voltage" ]
+
+required:
+ - compatible
+ - reg
+ - regulators
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@66 {
+ compatible = "national,lp3974";
+ reg = <0x66>;
+ interrupts-extended = <&gpx0 7 IRQ_TYPE_LEVEL_LOW>,
+ <&gpx2 7 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lp3974_irq>;
+
+ max8998,pmic-buck1-default-dvs-idx = <0>;
+ max8998,pmic-buck1-dvs-gpios = <&gpx0 5 GPIO_ACTIVE_HIGH>,
+ <&gpx0 6 GPIO_ACTIVE_HIGH>;
+ max8998,pmic-buck1-dvs-voltage = <1100000>, <1000000>,
+ <1100000>, <1000000>;
+ max8998,pmic-buck2-default-dvs-idx = <0>;
+ max8998,pmic-buck2-dvs-gpio = <&gpe2 0 GPIO_ACTIVE_HIGH>;
+ max8998,pmic-buck2-dvs-voltage = <1200000>, <1100000>;
+
+ regulators {
+ LDO2 {
+ regulator-name = "VALIVE_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ LDO3 {
+ regulator-name = "VUSB+MIPI_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ LDO4 {
+ regulator-name = "VADC_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ LDO5 {
+ regulator-name = "VTF_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ LDO6 {
+ regulator-name = "LDO6";
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ };
+
+ LDO7 {
+ regulator-name = "VLCD+VMIPI_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ LDO8 {
+ regulator-name = "VUSB+VDAC_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ LDO9 {
+ regulator-name = "VCC_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ LDO10 {
+ regulator-name = "VPLL_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDO11 {
+ regulator-name = "CAM_AF_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ LDO12 {
+ regulator-name = "PS_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ LDO13 {
+ regulator-name = "VHIC_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ LDO14 {
+ regulator-name = "CAM_I_HOST_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ LDO15 {
+ regulator-name = "CAM_S_DIG+FM33_CORE_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ LDO16 {
+ regulator-name = "CAM_S_ANA_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ LDO17 {
+ regulator-name = "VCC_3.0V_LCD";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ BUCK1 {
+ regulator-name = "VINT_1.1V";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ BUCK2 {
+ regulator-name = "VG3D_1.1V";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-boot-on;
+ };
+
+ BUCK3 {
+ regulator-name = "VCC_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ BUCK4 {
+ regulator-name = "VMEM_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ EN32KHz-AP {
+ regulator-name = "32KHz AP";
+ regulator-always-on;
+ };
+
+ EN32KHz-CP {
+ regulator-name = "32KHz CP";
+ };
+
+ ENVICHG {
+ regulator-name = "VICHG";
+ };
+
+ ESAFEOUT1 {
+ regulator-name = "SAFEOUT1";
+ };
+
+ ESAFEOUT2 {
+ regulator-name = "SAFEOUT2";
+ regulator-boot-on;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6357.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6357.yaml
index fc2a53148e1c..37423c2e0fdf 100644
--- a/Documentation/devicetree/bindings/mfd/mediatek,mt6357.yaml
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6357.yaml
@@ -40,6 +40,7 @@ properties:
regulators:
type: object
$ref: /schemas/regulator/mediatek,mt6357-regulator.yaml
+ unevaluatedProperties: false
description:
List of MT6357 BUCKs and LDOs regulators.
@@ -59,6 +60,7 @@ properties:
keys:
type: object
$ref: /schemas/input/mediatek,pmic-keys.yaml
+ unevaluatedProperties: false
description:
MT6357 power and home keys.
diff --git a/Documentation/devicetree/bindings/mfd/mt6397.txt b/Documentation/devicetree/bindings/mfd/mt6397.txt
index 294693a8906c..10540aa7afa1 100644
--- a/Documentation/devicetree/bindings/mfd/mt6397.txt
+++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
@@ -22,8 +22,9 @@ compatible:
"mediatek,mt6323" for PMIC MT6323
"mediatek,mt6331" for PMIC MT6331 and MT6332
"mediatek,mt6357" for PMIC MT6357
- "mediatek,mt6358" for PMIC MT6358 and MT6366
+ "mediatek,mt6358" for PMIC MT6358
"mediatek,mt6359" for PMIC MT6359
+ "mediatek,mt6366", "mediatek,mt6358" for PMIC MT6366
"mediatek,mt6397" for PMIC MT6397
Optional subnodes:
@@ -40,6 +41,7 @@ Optional subnodes:
- compatible: "mediatek,mt6323-regulator"
see ../regulator/mt6323-regulator.txt
- compatible: "mediatek,mt6358-regulator"
+ - compatible: "mediatek,mt6366-regulator", "mediatek-mt6358-regulator"
see ../regulator/mt6358-regulator.txt
- compatible: "mediatek,mt6397-regulator"
see ../regulator/mt6397-regulator.txt
diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
index 9f03436b1cdc..9fa568603930 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
@@ -58,6 +58,7 @@ properties:
- qcom,pm8350
- qcom,pm8350b
- qcom,pm8350c
+ - qcom,pm8450
- qcom,pm8550
- qcom,pm8550b
- qcom,pm8550ve
@@ -168,6 +169,10 @@ patternProperties:
type: object
$ref: /schemas/thermal/qcom,spmi-temp-alarm.yaml#
+ "^typec@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/usb/qcom,pmic-typec.yaml#
+
"^usb-detect@[0-9a-f]+$":
type: object
$ref: /schemas/extcon/qcom,pm8941-misc.yaml#
@@ -234,13 +239,13 @@ examples:
interrupt-controller;
#interrupt-cells = <4>;
- pmi8998_lsid0: pmic@2 {
+ pmic@2 {
compatible = "qcom,pmi8998", "qcom,spmi-pmic";
reg = <0x2 SPMI_USID>;
#address-cells = <1>;
#size-cells = <0>;
- pmi8998_gpio: gpio@c000 {
+ gpio@c000 {
compatible = "qcom,pmi8998-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
@@ -325,7 +330,7 @@ examples:
};
};
- pm6150_gpio: gpio@c000 {
+ gpio@c000 {
compatible = "qcom,pm6150-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
index 5ad9d5deaaf8..33c3d023a106 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
@@ -27,6 +27,7 @@ properties:
- qcom,sdm845-tcsr
- qcom,sdx55-tcsr
- qcom,sdx65-tcsr
+ - qcom,sm4450-tcsr
- qcom,sm8150-tcsr
- qcom,sm8450-tcsr
- qcom,tcsr-apq8064
diff --git a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml
index 9c51c1b19067..7fe3875a5996 100644
--- a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml
@@ -43,13 +43,37 @@ properties:
interrupt-controller: true
patternProperties:
+ "gpio@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/pinctrl/qcom,pmic-gpio.yaml#
+
+ "keypad@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/input/qcom,pm8921-keypad.yaml#
+
"led@[0-9a-f]+$":
type: object
$ref: /schemas/leds/qcom,pm8058-led.yaml#
+ "mpps@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/pinctrl/qcom,pmic-mpp.yaml#
+
+ "pwrkey@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/input/qcom,pm8921-pwrkey.yaml#
+
"rtc@[0-9a-f]+$":
type: object
- $ref: ../rtc/qcom-pm8xxx-rtc.yaml
+ $ref: /schemas/rtc/qcom-pm8xxx-rtc.yaml#
+
+ "vibrator@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/input/qcom,pm8xxx-vib.yaml#
+
+ "xoadc@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/iio/adc/qcom,pm8018-adc.yaml#
required:
- compatible
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml
index 4992f71b6fc3..44f8188360dd 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml
@@ -42,9 +42,12 @@ properties:
rockchip,system-power-controller:
type: boolean
+ deprecated: true
description:
Telling whether or not this PMIC is controlling the system power.
+ system-power-controller: true
+
wakeup-source:
type: boolean
description:
@@ -80,6 +83,7 @@ properties:
"^(DCDC_REG[1-4]|LDO_REG[1-3])$":
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
unevaluatedProperties: false
allOf:
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml
index cf2500f2e9a0..3c2b06629b75 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml
@@ -29,6 +29,8 @@ properties:
'#gpio-cells':
const: 2
+ system-power-controller: true
+
vcc1-supply:
description:
The input supply for dcdc-reg1.
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
index f5908fa01a61..d2ac6fbd5ce6 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
@@ -37,9 +37,12 @@ properties:
rockchip,system-power-controller:
type: boolean
+ deprecated: true
description:
Telling whether or not this PMIC is controlling the system power.
+ system-power-controller: true
+
wakeup-source:
type: boolean
description:
@@ -107,6 +110,7 @@ properties:
"^(DCDC_REG[1-4]|LDO_REG[1-8]|SWITCH_REG[1-2])$":
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
unevaluatedProperties: false
required:
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk809.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk809.yaml
index 7fb849ac74a7..839c0521f1e5 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk809.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk809.yaml
@@ -37,9 +37,12 @@ properties:
rockchip,system-power-controller:
type: boolean
+ deprecated: true
description:
Telling whether or not this PMIC is controlling the system power.
+ system-power-controller: true
+
wakeup-source:
type: boolean
description:
@@ -86,7 +89,8 @@ properties:
patternProperties:
"^(LDO_REG[1-9]|DCDC_REG[1-5]|SWITCH_REG[1-2])$":
type: object
- $ref: ../regulator/regulator.yaml#
+ $ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
unevaluatedProperties: false
allOf:
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml
index 269fb85b2027..92b1592e8942 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml
@@ -38,9 +38,12 @@ properties:
rockchip,system-power-controller:
type: boolean
+ deprecated: true
description:
Telling whether or not this PMIC is controlling the system power.
+ system-power-controller: true
+
wakeup-source:
type: boolean
description:
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml
index b57c4b005cf4..fd4b9de364aa 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml
@@ -37,9 +37,12 @@ properties:
rockchip,system-power-controller:
type: boolean
+ deprecated: true
description:
Telling whether or not this PMIC is controlling the system power.
+ system-power-controller: true
+
wakeup-source:
type: boolean
description:
@@ -99,6 +102,7 @@ properties:
"^(DCDC_REG[1-4]|DCDC_BOOST|LDO_REG[1-9]|SWITCH_REG|HDMI_SWITCH|OTG_SWITCH)$":
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
unevaluatedProperties: false
required:
diff --git a/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml b/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml
index 5e0002f099e4..cb2a42caabb5 100644
--- a/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml
+++ b/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml
@@ -75,7 +75,7 @@ properties:
unevaluatedProperties: false
db8500_varm:
- description: The voltage for the ARM Cortex A-9 CPU.
+ description: The voltage for the ARM Cortex-A9 CPU.
type: object
$ref: ../regulator/regulator.yaml#
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index 8103154bbb52..084b5c2a2a3c 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -49,6 +49,8 @@ properties:
- hisilicon,peri-subctrl
- hpe,gxp-sysreg
- intel,lgm-syscon
+ - loongson,ls1b-syscon
+ - loongson,ls1c-syscon
- marvell,armada-3700-usb2-host-misc
- mediatek,mt8135-pctl-a-syscfg
- mediatek,mt8135-pctl-b-syscfg
@@ -61,6 +63,7 @@ properties:
- rockchip,px30-qos
- rockchip,rk3036-qos
- rockchip,rk3066-qos
+ - rockchip,rk3128-qos
- rockchip,rk3228-qos
- rockchip,rk3288-qos
- rockchip,rk3368-qos
@@ -69,6 +72,7 @@ properties:
- rockchip,rk3588-qos
- rockchip,rv1126-qos
- starfive,jh7100-sysmain
+ - ti,am654-dss-oldi-io-ctrl
- const: syscon
diff --git a/Documentation/devicetree/bindings/mfd/ti,lp87524-q1.yaml b/Documentation/devicetree/bindings/mfd/ti,lp87524-q1.yaml
index f6cac4b1079c..ae149eb8593d 100644
--- a/Documentation/devicetree/bindings/mfd/ti,lp87524-q1.yaml
+++ b/Documentation/devicetree/bindings/mfd/ti,lp87524-q1.yaml
@@ -37,6 +37,7 @@ properties:
"^buck[0123]$":
type: object
$ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
required:
- buck0
diff --git a/Documentation/devicetree/bindings/mfd/ti,lp87561-q1.yaml b/Documentation/devicetree/bindings/mfd/ti,lp87561-q1.yaml
index dc5a29b5ef7d..5167d6eb904a 100644
--- a/Documentation/devicetree/bindings/mfd/ti,lp87561-q1.yaml
+++ b/Documentation/devicetree/bindings/mfd/ti,lp87561-q1.yaml
@@ -41,6 +41,7 @@ properties:
buck3210:
type: object
$ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
required:
- buck3210
diff --git a/Documentation/devicetree/bindings/mfd/ti,lp87565-q1.yaml b/Documentation/devicetree/bindings/mfd/ti,lp87565-q1.yaml
index 012d25111054..eca430edf608 100644
--- a/Documentation/devicetree/bindings/mfd/ti,lp87565-q1.yaml
+++ b/Documentation/devicetree/bindings/mfd/ti,lp87565-q1.yaml
@@ -47,6 +47,7 @@ properties:
"^buck(10|23)$":
type: object
$ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
required:
- buck10
diff --git a/Documentation/devicetree/bindings/mfd/ti,twl.yaml b/Documentation/devicetree/bindings/mfd/ti,twl.yaml
new file mode 100644
index 000000000000..c04d57ba22b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/ti,twl.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/ti,twl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments TWL family
+
+maintainers:
+ - Andreas Kemnade <andreas@kemnade.info>
+
+description: |
+ The TWLs are Integrated Power Management Chips.
+ Some version might contain much more analog function like
+ USB transceiver or Audio amplifier.
+ These chips are connected to an i2c bus.
+
+properties:
+ compatible:
+ description:
+ TWL4030 for integrated power-management/audio CODEC device used in OMAP3
+ based boards
+ TWL6030/32 for integrated power-management used in OMAP4 based boards
+ enum:
+ - ti,twl4030
+ - ti,twl6030
+ - ti,twl6032
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 1
+
+ "#clock-cells":
+ const: 1
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-controller
+ - "#interrupt-cells"
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@48 {
+ compatible = "ti,twl6030";
+ reg = <0x48>;
+ interrupts = <39>; /* IRQ_SYS_1N cascaded to gic */
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic>;
+ };
+ };
+
diff --git a/Documentation/devicetree/bindings/mfd/twl-family.txt b/Documentation/devicetree/bindings/mfd/twl-family.txt
deleted file mode 100644
index c2f9302965de..000000000000
--- a/Documentation/devicetree/bindings/mfd/twl-family.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-Texas Instruments TWL family
-
-The TWLs are Integrated Power Management Chips.
-Some version might contain much more analog function like
-USB transceiver or Audio amplifier.
-These chips are connected to an i2c bus.
-
-
-Required properties:
-- compatible : Must be "ti,twl4030";
- For Integrated power-management/audio CODEC device used in OMAP3
- based boards
-- compatible : Must be "ti,twl6030";
- For Integrated power-management used in OMAP4 based boards
-- interrupts : This i2c device has an IRQ line connected to the main SoC
-- interrupt-controller : Since the twl support several interrupts internally,
- it is considered as an interrupt controller cascaded to the SoC one.
-- #interrupt-cells = <1>;
-
-Optional node:
-- Child nodes contain in the twl. The twl family is made of several variants
- that support a different number of features.
- The children nodes will thus depend of the capability of the variant.
-
-
-Example:
-/*
- * Integrated Power Management Chip
- * https://www.ti.com/lit/ds/symlink/twl6030.pdf
- */
-twl@48 {
- compatible = "ti,twl6030";
- reg = <0x48>;
- interrupts = <39>; /* IRQ_SYS_1N cascaded to gic */
- interrupt-controller;
- #interrupt-cells = <1>;
- interrupt-parent = <&gic>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- twl_rtc {
- compatible = "ti,twl_rtc";
- interrupts = <11>;
- reg = <0>;
- };
-};
diff --git a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml
index 9ad55746133b..06f1779835a1 100644
--- a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml
+++ b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml
@@ -67,7 +67,10 @@ allOf:
properties:
compatible:
contains:
- const: x-powers,axp305
+ enum:
+ - x-powers,axp15060
+ - x-powers,axp305
+ - x-powers,axp313a
then:
required:
diff --git a/Documentation/devicetree/bindings/mmc/npcm,sdhci.yaml b/Documentation/devicetree/bindings/mmc/npcm,sdhci.yaml
new file mode 100644
index 000000000000..196fdbfa16ed
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/npcm,sdhci.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mmc/npcm,sdhci.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NPCM SDHCI Controller
+
+maintainers:
+ - Tomer Maimon <tmaimon77@gmail.com>
+
+allOf:
+ - $ref: mmc-controller.yaml#
+
+properties:
+ compatible:
+ enum:
+ - nuvoton,npcm750-sdhci
+ - nuvoton,npcm845-sdhci
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ mmc@f0840000 {
+ compatible = "nuvoton,npcm750-sdhci";
+ reg = <0xf0840000 0x200>;
+ interrupts = <0 27 4>;
+ clocks = <&clk 4>;
+ };
diff --git a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml
index 7756a8687eaf..94e228787630 100644
--- a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml
+++ b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml
@@ -59,6 +59,7 @@ properties:
- renesas,sdhi-r9a07g043 # RZ/G2UL
- renesas,sdhi-r9a07g044 # RZ/G2{L,LC}
- renesas,sdhi-r9a07g054 # RZ/V2L
+ - renesas,sdhi-r9a08g045 # RZ/G3S
- renesas,sdhi-r9a09g011 # RZ/V2M
- const: renesas,rcar-gen3-sdhi # R-Car Gen3 or RZ/G2
- items:
@@ -122,6 +123,7 @@ allOf:
- renesas,sdhi-r9a07g043
- renesas,sdhi-r9a07g044
- renesas,sdhi-r9a07g054
+ - renesas,sdhi-r9a08g045
- renesas,sdhi-r9a09g011
then:
properties:
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
index 80141eb7fc6b..86fae733d9a0 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
@@ -58,6 +58,7 @@ properties:
- qcom,sm8350-sdhci
- qcom,sm8450-sdhci
- qcom,sm8550-sdhci
+ - qcom,sm8650-sdhci
- const: qcom,sdhci-msm-v5 # for sdcc version 5.0
reg:
@@ -69,7 +70,7 @@ properties:
maxItems: 4
clocks:
- minItems: 3
+ minItems: 2
items:
- description: Main peripheral bus clock, PCLK/HCLK - AHB Bus clock
- description: SDC MMC clock, MCLK
@@ -85,10 +86,10 @@ properties:
- const: iface
- const: core
- const: xo
- - const: ice
- - const: bus
- - const: cal
- - const: sleep
+ - enum: [ice, bus, cal, sleep]
+ - enum: [ice, bus, cal, sleep]
+ - enum: [ice, bus, cal, sleep]
+ - enum: [ice, bus, cal, sleep]
dma-coherent: true
diff --git a/Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml b/Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml
index 51e1b04e799f..553a75195c2e 100644
--- a/Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml
+++ b/Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml
@@ -55,7 +55,6 @@ required:
- clocks
- clock-names
- interrupts
- - starfive,sysreg
unevaluatedProperties: false
@@ -73,5 +72,4 @@ examples:
fifo-depth = <32>;
fifo-watermark-aligned;
data-addr = <0>;
- starfive,sysreg = <&sys_syscon 0x14 0x1a 0x7c000000>;
};
diff --git a/Documentation/devicetree/bindings/mtd/mtd.yaml b/Documentation/devicetree/bindings/mtd/mtd.yaml
index b82ca03e969c..f322290ee516 100644
--- a/Documentation/devicetree/bindings/mtd/mtd.yaml
+++ b/Documentation/devicetree/bindings/mtd/mtd.yaml
@@ -43,7 +43,12 @@ patternProperties:
deprecated: true
"^otp(-[0-9]+)?$":
- $ref: ../nvmem/nvmem.yaml#
+ type: object
+
+ allOf:
+ - $ref: ../nvmem/nvmem.yaml#
+ - $ref: ../nvmem/nvmem-deprecated-cells.yaml#
+
unevaluatedProperties: false
description: |
diff --git a/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml
index 331e564f29dc..058253d6d889 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml
@@ -29,6 +29,24 @@ properties:
"#size-cells": true
+ compression:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: |
+ Compression algorithm used to store the data in this partition, chosen
+ from a list of well-known algorithms.
+
+ The contents are compressed using this algorithm.
+
+ enum:
+ - none
+ - bzip2
+ - gzip
+ - lzop
+ - lz4
+ - lzma
+ - xz
+ - zstd
+
patternProperties:
"@[0-9a-f]+$":
$ref: partition.yaml#
@@ -64,6 +82,7 @@ examples:
uimage@100000 {
reg = <0x0100000 0x200000>;
+ compress = "lzma";
};
};
diff --git a/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml b/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml
index 5474d63268dc..9518281007af 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml
@@ -19,6 +19,7 @@ maintainers:
allOf:
- $ref: /schemas/mtd/partitions/partition.yaml#
- $ref: /schemas/nvmem/nvmem.yaml#
+ - $ref: /schemas/nvmem/nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
index 4bfac9186886..7fe0352dff0f 100644
--- a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
+++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
@@ -158,6 +158,8 @@ allOf:
patternProperties:
"^ethernet-phy@[0-9a-f]$":
type: object
+ $ref: ethernet-phy.yaml#
+ unevaluatedProperties: false
description:
Integrated PHY node
diff --git a/Documentation/devicetree/bindings/net/brcm,asp-v2.0.yaml b/Documentation/devicetree/bindings/net/brcm,asp-v2.0.yaml
index aa3162c74833..75d8138298fb 100644
--- a/Documentation/devicetree/bindings/net/brcm,asp-v2.0.yaml
+++ b/Documentation/devicetree/bindings/net/brcm,asp-v2.0.yaml
@@ -53,7 +53,7 @@ properties:
const: 0
patternProperties:
- "^port@[0-9]+$":
+ "^port@[0-9a-f]+$":
type: object
$ref: ethernet-controller.yaml#
diff --git a/Documentation/devicetree/bindings/net/dsa/brcm,sf2.yaml b/Documentation/devicetree/bindings/net/dsa/brcm,sf2.yaml
index b06c416893ff..f21bdd0f408d 100644
--- a/Documentation/devicetree/bindings/net/dsa/brcm,sf2.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/brcm,sf2.yaml
@@ -78,6 +78,7 @@ properties:
ports:
type: object
+ additionalProperties: true
patternProperties:
'^port@[0-9a-f]$':
diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.yaml b/Documentation/devicetree/bindings/net/dsa/dsa.yaml
index ec74a660beda..6107189d276a 100644
--- a/Documentation/devicetree/bindings/net/dsa/dsa.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/dsa.yaml
@@ -40,17 +40,8 @@ $defs:
patternProperties:
"^(ethernet-)?ports$":
- type: object
- additionalProperties: false
-
- properties:
- '#address-cells':
- const: 1
- '#size-cells':
- const: 0
-
patternProperties:
- "^(ethernet-)?port@[0-9]+$":
+ "^(ethernet-)?port@[0-9a-f]+$":
description: Ethernet switch ports
$ref: dsa-port.yaml#
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml b/Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml
index e532c6b795f4..1c2444121e60 100644
--- a/Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml
@@ -60,7 +60,7 @@ description: |
Check out example 6.
- - Port 5 can be wired to an external phy. Port 5 becomes a DSA slave.
+ - Port 5 can be wired to an external phy. Port 5 becomes a DSA user port.
For the multi-chip module MT7530, the external phy must be wired TX to TX
to gmac1 of the SoC for this to work. Ubiquiti EdgeRouter X SFP is wired
@@ -154,10 +154,12 @@ properties:
patternProperties:
"^(ethernet-)?ports$":
type: object
+ additionalProperties: true
patternProperties:
- "^(ethernet-)?port@[0-9]+$":
+ "^(ethernet-)?port@[0-6]$":
type: object
+ additionalProperties: true
properties:
reg:
@@ -184,7 +186,7 @@ $defs:
patternProperties:
"^(ethernet-)?ports$":
patternProperties:
- "^(ethernet-)?port@[0-9]+$":
+ "^(ethernet-)?port@[0-6]$":
if:
required: [ ethernet ]
then:
@@ -210,7 +212,7 @@ $defs:
patternProperties:
"^(ethernet-)?ports$":
patternProperties:
- "^(ethernet-)?port@[0-9]+$":
+ "^(ethernet-)?port@[0-6]$":
if:
required: [ ethernet ]
then:
diff --git a/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml b/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
index 03b5567be389..b3029c64d0d5 100644
--- a/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
@@ -38,6 +38,8 @@ properties:
Should be a gpio specifier for a reset line.
maxItems: 1
+ wakeup-source: true
+
microchip,synclko-125:
$ref: /schemas/types.yaml#/definitions/flag
description:
@@ -49,6 +51,26 @@ properties:
Set if the output SYNCLKO clock should be disabled. Do not mix with
microchip,synclko-125.
+ microchip,io-drive-strength-microamp:
+ description:
+ IO Pad Drive Strength
+ enum: [8000, 16000]
+ default: 16000
+
+ microchip,hi-drive-strength-microamp:
+ description:
+ High Speed Drive Strength. Controls drive strength of GMII / RGMII /
+ MII / RMII (except TX_CLK/REFCLKI, COL and CRS) and CLKO_25_125 lines.
+ enum: [2000, 4000, 8000, 12000, 16000, 20000, 24000, 28000]
+ default: 24000
+
+ microchip,lo-drive-strength-microamp:
+ description:
+ Low Speed Drive Strength. Controls drive strength of TX_CLK / REFCLKI,
+ COL, CRS, LEDs, PME_N, NTRP_N, SDO and SDI/SDA/MDIO lines.
+ enum: [2000, 4000, 8000, 12000, 16000, 20000, 24000, 28000]
+ default: 8000
+
interrupts:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/net/dsa/microchip,lan937x.yaml b/Documentation/devicetree/bindings/net/dsa/microchip,lan937x.yaml
index 8d7e878b84dc..9973d64f15a7 100644
--- a/Documentation/devicetree/bindings/net/dsa/microchip,lan937x.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/microchip,lan937x.yaml
@@ -37,8 +37,9 @@ properties:
patternProperties:
"^(ethernet-)?ports$":
+ additionalProperties: true
patternProperties:
- "^(ethernet-)?port@[0-9]+$":
+ "^(ethernet-)?port@[0-7]$":
allOf:
- if:
properties:
diff --git a/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml b/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
index 4d5f5cc6d031..9432565f4f5d 100644
--- a/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
@@ -43,6 +43,7 @@ properties:
# PHY 1.
mdios:
type: object
+ additionalProperties: false
properties:
'#address-cells':
@@ -74,8 +75,9 @@ properties:
patternProperties:
"^(ethernet-)?ports$":
+ additionalProperties: true
patternProperties:
- "^(ethernet-)?port@[0-9]+$":
+ "^(ethernet-)?port@[0-9]$":
allOf:
- if:
properties:
diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.yaml b/Documentation/devicetree/bindings/net/dsa/qca8k.yaml
index df64eebebe18..167398ab253a 100644
--- a/Documentation/devicetree/bindings/net/dsa/qca8k.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.yaml
@@ -73,6 +73,7 @@ $ref: dsa.yaml#
patternProperties:
"^(ethernet-)?ports$":
type: object
+ additionalProperties: true
patternProperties:
"^(ethernet-)?port@[0-6]$":
type: object
diff --git a/Documentation/devicetree/bindings/net/dsa/realtek.yaml b/Documentation/devicetree/bindings/net/dsa/realtek.yaml
index cfd69c2604ea..cce692f57b08 100644
--- a/Documentation/devicetree/bindings/net/dsa/realtek.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/realtek.yaml
@@ -68,6 +68,8 @@ properties:
interrupt-controller:
type: object
+ additionalProperties: false
+
description: |
This defines an interrupt controller with an IRQ line (typically
a GPIO) that will demultiplex and handle the interrupt from the single
diff --git a/Documentation/devicetree/bindings/net/dsa/renesas,rzn1-a5psw.yaml b/Documentation/devicetree/bindings/net/dsa/renesas,rzn1-a5psw.yaml
index 833d2f68daa1..ea285ef3e64f 100644
--- a/Documentation/devicetree/bindings/net/dsa/renesas,rzn1-a5psw.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/renesas,rzn1-a5psw.yaml
@@ -61,17 +61,11 @@ properties:
ethernet-ports:
type: object
- properties:
- '#address-cells':
- const: 1
- '#size-cells':
- const: 0
-
+ additionalProperties: true
patternProperties:
"^(ethernet-)?port@[0-4]$":
type: object
- description: Ethernet switch ports
-
+ additionalProperties: true
properties:
pcs-handle:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/net/engleder,tsnep.yaml b/Documentation/devicetree/bindings/net/engleder,tsnep.yaml
index 82a5d7927ca4..34fd24ff6a71 100644
--- a/Documentation/devicetree/bindings/net/engleder,tsnep.yaml
+++ b/Documentation/devicetree/bindings/net/engleder,tsnep.yaml
@@ -63,6 +63,7 @@ properties:
mdio:
type: object
$ref: mdio.yaml#
+ unevaluatedProperties: false
description: optional node for embedded MDIO controller
required:
diff --git a/Documentation/devicetree/bindings/net/ethernet-controller.yaml b/Documentation/devicetree/bindings/net/ethernet-controller.yaml
index 9f6a5ccbcefe..d14d123ad7a0 100644
--- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml
+++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml
@@ -275,12 +275,12 @@ allOf:
properties:
rx-internal-delay-ps:
description:
- RGMII Receive Clock Delay defined in pico seconds.This is used for
+ RGMII Receive Clock Delay defined in pico seconds. This is used for
controllers that have configurable RX internal delays. If this
property is present then the MAC applies the RX delay.
tx-internal-delay-ps:
description:
- RGMII Transmit Clock Delay defined in pico seconds.This is used for
+ RGMII Transmit Clock Delay defined in pico seconds. This is used for
controllers that have configurable TX internal delays. If this
property is present then the MAC applies the TX delay.
diff --git a/Documentation/devicetree/bindings/net/ethernet-switch.yaml b/Documentation/devicetree/bindings/net/ethernet-switch.yaml
index f1b9075dc7fb..72ac67ca3415 100644
--- a/Documentation/devicetree/bindings/net/ethernet-switch.yaml
+++ b/Documentation/devicetree/bindings/net/ethernet-switch.yaml
@@ -36,7 +36,7 @@ patternProperties:
const: 0
patternProperties:
- "^(ethernet-)?port@[0-9]+$":
+ "^(ethernet-)?port@[0-9a-f]+$":
type: object
description: Ethernet switch ports
@@ -53,14 +53,16 @@ oneOf:
additionalProperties: true
$defs:
- base:
+ ethernet-ports:
description: An ethernet switch without any extra port properties
$ref: '#'
patternProperties:
- "^(ethernet-)?port@[0-9]+$":
- description: Ethernet switch ports
- $ref: ethernet-switch-port.yaml#
- unevaluatedProperties: false
+ "^(ethernet-)?ports$":
+ patternProperties:
+ "^(ethernet-)?port@[0-9a-f]+$":
+ description: Ethernet switch ports
+ $ref: ethernet-switch-port.yaml#
+ unevaluatedProperties: false
...
diff --git a/Documentation/devicetree/bindings/net/fsl,fec.yaml b/Documentation/devicetree/bindings/net/fsl,fec.yaml
index b494e009326e..8948a11c994e 100644
--- a/Documentation/devicetree/bindings/net/fsl,fec.yaml
+++ b/Documentation/devicetree/bindings/net/fsl,fec.yaml
@@ -59,6 +59,7 @@ properties:
- const: fsl,imx6sx-fec
- items:
- enum:
+ - fsl,imx8dxl-fec
- fsl,imx8qxp-fec
- const: fsl,imx8qm-fec
- const: fsl,imx6sx-fec
diff --git a/Documentation/devicetree/bindings/net/loongson,ls1b-gmac.yaml b/Documentation/devicetree/bindings/net/loongson,ls1b-gmac.yaml
new file mode 100644
index 000000000000..c4f3224bad38
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/loongson,ls1b-gmac.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/loongson,ls1b-gmac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Loongson-1B Gigabit Ethernet MAC Controller
+
+maintainers:
+ - Keguang Zhang <keguang.zhang@gmail.com>
+
+description: |
+ Loongson-1B Gigabit Ethernet MAC Controller is based on
+ Synopsys DesignWare MAC (version 3.50a).
+
+ Main features
+ - Dual 10/100/1000Mbps GMAC controllers
+ - Full-duplex operation (IEEE 802.3x flow control automatic transmission)
+ - Half-duplex operation (CSMA/CD Protocol and back-pressure support)
+ - RX Checksum Offload
+ - TX Checksum insertion
+ - MII interface
+ - RGMII interface
+
+select:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - loongson,ls1b-gmac
+ required:
+ - compatible
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - loongson,ls1b-gmac
+ - const: snps,dwmac-3.50a
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: stmmaceth
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-names:
+ items:
+ - const: macirq
+
+ loongson,ls1-syscon:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the syscon containing some extra configurations
+ including PHY interface mode.
+
+ phy-mode:
+ enum:
+ - mii
+ - rgmii-id
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - interrupts
+ - interrupt-names
+ - loongson,ls1-syscon
+
+allOf:
+ - $ref: snps,dwmac.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/loongson,ls1x-clk.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ gmac0: ethernet@1fe10000 {
+ compatible = "loongson,ls1b-gmac", "snps,dwmac-3.50a";
+ reg = <0x1fe10000 0x10000>;
+
+ clocks = <&clkc LS1X_CLKID_AHB>;
+ clock-names = "stmmaceth";
+
+ interrupt-parent = <&intc1>;
+ interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+
+ loongson,ls1-syscon = <&syscon>;
+
+ phy-handle = <&phy0>;
+ phy-mode = "mii";
+ snps,pbl = <1>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+
+ phy0: ethernet-phy@0 {
+ reg = <0x0>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/net/loongson,ls1c-emac.yaml b/Documentation/devicetree/bindings/net/loongson,ls1c-emac.yaml
new file mode 100644
index 000000000000..99001b940b83
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/loongson,ls1c-emac.yaml
@@ -0,0 +1,113 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/loongson,ls1c-emac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Loongson-1C Ethernet MAC Controller
+
+maintainers:
+ - Keguang Zhang <keguang.zhang@gmail.com>
+
+description: |
+ Loongson-1C Ethernet MAC Controller is based on
+ Synopsys DesignWare MAC (version 3.50a).
+
+ Main features
+ - 10/100Mbps
+ - Full-duplex operation (IEEE 802.3x flow control automatic transmission)
+ - Half-duplex operation (CSMA/CD Protocol and back-pressure support)
+ - IEEE 802.1Q VLAN tag detection for reception frames
+ - MII interface
+ - RMII interface
+
+select:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - loongson,ls1c-emac
+ required:
+ - compatible
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - loongson,ls1c-emac
+ - const: snps,dwmac-3.50a
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: stmmaceth
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-names:
+ items:
+ - const: macirq
+
+ loongson,ls1-syscon:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the syscon containing some extra configurations
+ including PHY interface mode.
+
+ phy-mode:
+ enum:
+ - mii
+ - rmii
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - interrupts
+ - interrupt-names
+ - loongson,ls1-syscon
+
+allOf:
+ - $ref: snps,dwmac.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/loongson,ls1x-clk.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ emac: ethernet@1fe10000 {
+ compatible = "loongson,ls1c-emac", "snps,dwmac-3.50a";
+ reg = <0x1fe10000 0x10000>;
+
+ clocks = <&clkc LS1X_CLKID_AHB>;
+ clock-names = "stmmaceth";
+
+ interrupt-parent = <&intc1>;
+ interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+
+ loongson,ls1-syscon = <&syscon>;
+
+ phy-handle = <&phy0>;
+ phy-mode = "mii";
+ snps,pbl = <1>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+
+ phy0: ethernet-phy@13 {
+ reg = <0x13>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/net/microchip,lan95xx.yaml b/Documentation/devicetree/bindings/net/microchip,lan95xx.yaml
index 77c9bbf987e1..accff93d38f8 100644
--- a/Documentation/devicetree/bindings/net/microchip,lan95xx.yaml
+++ b/Documentation/devicetree/bindings/net/microchip,lan95xx.yaml
@@ -44,6 +44,8 @@ properties:
local-mac-address: true
mac-address: true
+ nvmem-cells: true
+ nvmem-cell-names: true
required:
- compatible
diff --git a/Documentation/devicetree/bindings/net/mscc,vsc7514-switch.yaml b/Documentation/devicetree/bindings/net/mscc,vsc7514-switch.yaml
index 8ee2c7d7ff42..86a9c3fc76c8 100644
--- a/Documentation/devicetree/bindings/net/mscc,vsc7514-switch.yaml
+++ b/Documentation/devicetree/bindings/net/mscc,vsc7514-switch.yaml
@@ -24,7 +24,7 @@ allOf:
compatible:
const: mscc,vsc7514-switch
then:
- $ref: ethernet-switch.yaml#
+ $ref: ethernet-switch.yaml#/$defs/ethernet-ports
required:
- interrupts
- interrupt-names
@@ -33,28 +33,18 @@ allOf:
minItems: 21
reg-names:
minItems: 21
- ethernet-ports:
- patternProperties:
- "^port@[0-9a-f]+$":
- $ref: ethernet-switch-port.yaml#
- unevaluatedProperties: false
- if:
properties:
compatible:
const: mscc,vsc7512-switch
then:
- $ref: /schemas/net/dsa/dsa.yaml#
+ $ref: /schemas/net/dsa/dsa.yaml#/$defs/ethernet-ports
properties:
reg:
maxItems: 20
reg-names:
maxItems: 20
- ethernet-ports:
- patternProperties:
- "^port@[0-9a-f]+$":
- $ref: /schemas/net/dsa/dsa-port.yaml#
- unevaluatedProperties: false
properties:
compatible:
@@ -185,7 +175,7 @@ examples:
};
# VSC7512 (DSA)
- |
- ethernet-switch@1{
+ ethernet-switch@1 {
compatible = "mscc,vsc7512-switch";
reg = <0x71010000 0x10000>,
<0x71030000 0x10000>,
@@ -212,22 +202,22 @@ examples:
"port7", "port8", "port9", "port10", "qsys",
"ana", "s0", "s1", "s2";
- ethernet-ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- ethernet = <&mac_sw>;
- phy-handle = <&phy0>;
- phy-mode = "internal";
- };
- port@1 {
- reg = <1>;
- phy-handle = <&phy1>;
- phy-mode = "internal";
- };
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ ethernet = <&mac_sw>;
+ phy-handle = <&phy0>;
+ phy-mode = "internal";
+ };
+ port@1 {
+ reg = <1>;
+ phy-handle = <&phy1>;
+ phy-mode = "internal";
};
};
+ };
...
diff --git a/Documentation/devicetree/bindings/net/nxp,tja11xx.yaml b/Documentation/devicetree/bindings/net/nxp,tja11xx.yaml
index ab8867e6939b..85bfa45f5122 100644
--- a/Documentation/devicetree/bindings/net/nxp,tja11xx.yaml
+++ b/Documentation/devicetree/bindings/net/nxp,tja11xx.yaml
@@ -20,6 +20,7 @@ allOf:
patternProperties:
"^ethernet-phy@[0-9a-f]+$":
type: object
+ additionalProperties: false
description: |
Some packages have multiple PHYs. Secondary PHY should be defines as
subnode of the first (parent) PHY.
diff --git a/Documentation/devicetree/bindings/net/renesas,ether.yaml b/Documentation/devicetree/bindings/net/renesas,ether.yaml
index 06b38c9bc6ec..29355ab98569 100644
--- a/Documentation/devicetree/bindings/net/renesas,ether.yaml
+++ b/Documentation/devicetree/bindings/net/renesas,ether.yaml
@@ -81,9 +81,8 @@ properties:
active-high
patternProperties:
- "^ethernet-phy@[0-9a-f]$":
+ "@[0-9a-f]$":
type: object
- $ref: ethernet-phy.yaml#
required:
- compatible
diff --git a/Documentation/devicetree/bindings/net/renesas,etheravb.yaml b/Documentation/devicetree/bindings/net/renesas,etheravb.yaml
index 3f41294f5997..5d074f27d462 100644
--- a/Documentation/devicetree/bindings/net/renesas,etheravb.yaml
+++ b/Documentation/devicetree/bindings/net/renesas,etheravb.yaml
@@ -109,9 +109,8 @@ properties:
enum: [0, 2000]
patternProperties:
- "^ethernet-phy@[0-9a-f]$":
+ "@[0-9a-f]$":
type: object
- $ref: ethernet-phy.yaml#
required:
- compatible
diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index ddf9522a5dc2..5c2769dc689a 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -394,6 +394,11 @@ properties:
When a PFC frame is received with priorities matching the bitmask,
the queue is blocked from transmitting for the pause time specified
in the PFC frame.
+
+ snps,coe-unsupported:
+ type: boolean
+ description: TX checksum offload is unsupported by the TX queue.
+
allOf:
- if:
required:
diff --git a/Documentation/devicetree/bindings/net/ti,cc1352p7.yaml b/Documentation/devicetree/bindings/net/ti,cc1352p7.yaml
new file mode 100644
index 000000000000..3dde10de4630
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/ti,cc1352p7.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/ti,cc1352p7.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments Simplelink CC1352P7 wireless MCU
+
+description:
+ The CC1352P7 MCU can be connected via SPI or UART.
+
+maintainers:
+ - Ayush Singh <ayushdevel1325@gmail.com>
+
+properties:
+ compatible:
+ const: ti,cc1352p7
+
+ clocks:
+ items:
+ - description: high-frequency main system (MCU and peripherals) clock
+ - description: low-frequency system clock
+
+ clock-names:
+ items:
+ - const: sclk_hf
+ - const: sclk_lf
+
+ reset-gpios:
+ maxItems: 1
+
+ vdds-supply: true
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ serial {
+ mcu {
+ compatible = "ti,cc1352p7";
+ clocks = <&sclk_hf 0>, <&sclk_lf 25>;
+ clock-names = "sclk_hf", "sclk_lf";
+ reset-gpios = <&pio 35 GPIO_ACTIVE_LOW>;
+ vdds-supply = <&vdds>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/net/ti,cpsw-switch.yaml b/Documentation/devicetree/bindings/net/ti,cpsw-switch.yaml
index b04ac4966608..f07ae3173b03 100644
--- a/Documentation/devicetree/bindings/net/ti,cpsw-switch.yaml
+++ b/Documentation/devicetree/bindings/net/ti,cpsw-switch.yaml
@@ -86,7 +86,7 @@ properties:
const: 0
patternProperties:
- "^port@[0-9]+$":
+ "^port@[12]$":
type: object
description: CPSW external ports
diff --git a/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml b/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml
index 311c570165f9..229c8f32019f 100644
--- a/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml
+++ b/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml
@@ -19,6 +19,7 @@ allOf:
properties:
compatible:
enum:
+ - ti,am642-icssg-prueth # for AM64x SoC family
- ti,am654-icssg-prueth # for AM65x SoC family
sram:
@@ -106,6 +107,13 @@ properties:
phandle to system controller node and register offset
to ICSSG control register for RGMII transmit delay
+ ti,half-duplex-capable:
+ type: boolean
+ description:
+ Indicates that the PHY output pin COL is routed to ICSSG GPIO pin
+ (PRGx_PRU0/1_GPIO10) as input so that the ICSSG MII port is
+ capable of half duplex operations.
+
required:
- reg
anyOf:
diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml b/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
index 296001e7f498..4424c3c5e75c 100644
--- a/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
+++ b/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
@@ -12,6 +12,7 @@ maintainers:
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
@@ -23,7 +24,9 @@ properties:
- const: allwinner,sun20i-d1-sid
- const: allwinner,sun50i-a64-sid
- items:
- - const: allwinner,sun50i-a100-sid
+ - enum:
+ - allwinner,sun50i-a100-sid
+ - allwinner,sun50i-h616-sid
- const: allwinner,sun50i-a64-sid
- const: allwinner,sun50i-h5-sid
- const: allwinner,sun50i-h6-sid
diff --git a/Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml b/Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml
index e49c2754ff55..9801fe6f91b5 100644
--- a/Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml
+++ b/Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml
@@ -11,6 +11,7 @@ maintainers:
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/amlogic,meson6-efuse.yaml b/Documentation/devicetree/bindings/nvmem/amlogic,meson6-efuse.yaml
index 84b3dfd21e09..b5cf740f96fa 100644
--- a/Documentation/devicetree/bindings/nvmem/amlogic,meson6-efuse.yaml
+++ b/Documentation/devicetree/bindings/nvmem/amlogic,meson6-efuse.yaml
@@ -12,6 +12,7 @@ maintainers:
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/apple,efuses.yaml b/Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
index e0860b6b85f3..d3abdafdbca0 100644
--- a/Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
+++ b/Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
@@ -16,6 +16,7 @@ maintainers:
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml b/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
index 99e60d713dac..be1314454bec 100644
--- a/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
@@ -16,6 +16,7 @@ description: |
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml b/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml
index 7ec2988b597e..cf5f9e22bb7e 100644
--- a/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml
+++ b/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml
@@ -16,6 +16,7 @@ maintainers:
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml b/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
index a296d348adb4..cc25f2927682 100644
--- a/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
+++ b/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
@@ -16,6 +16,7 @@ description: |
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml b/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml
index a9b822aeaa7e..f43186f98607 100644
--- a/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml
@@ -11,6 +11,7 @@ maintainers:
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/nvmem-deprecated-cells.yaml b/Documentation/devicetree/bindings/nvmem/nvmem-deprecated-cells.yaml
new file mode 100644
index 000000000000..951af28bbfb3
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/nvmem-deprecated-cells.yaml
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/nvmem-deprecated-cells.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVMEM old syntax for fixed cells
+
+maintainers:
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+description: |
+ Before introducing NVMEM layouts all NVMEM (fixed) cells were defined
+ as direct device subnodes. That syntax was replaced by "fixed-layout"
+ and is deprecated now. No new bindings should use it.
+
+patternProperties:
+ "@[0-9a-f]+(,[0-7])?$":
+ type: object
+ allOf:
+ - $ref: layouts/fixed-cell.yaml
+ - properties:
+ compatible: false
+ deprecated: true
+
+additionalProperties: true
+
+...
diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.yaml b/Documentation/devicetree/bindings/nvmem/nvmem.yaml
index 9f921d940142..4fd015d402ce 100644
--- a/Documentation/devicetree/bindings/nvmem/nvmem.yaml
+++ b/Documentation/devicetree/bindings/nvmem/nvmem.yaml
@@ -46,15 +46,6 @@ properties:
container may reference more advanced (dynamic) layout
parsers.
-patternProperties:
- "@[0-9a-f]+(,[0-7])?$":
- type: object
- allOf:
- - $ref: layouts/fixed-cell.yaml
- - properties:
- compatible: false
- deprecated: true
-
additionalProperties: true
examples:
diff --git a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
index 8740938c32eb..8c8f05d9eaf1 100644
--- a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
+++ b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
@@ -11,6 +11,7 @@ maintainers:
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/qcom,sec-qfprom.yaml b/Documentation/devicetree/bindings/nvmem/qcom,sec-qfprom.yaml
index 9b133f783d29..2ada2099946d 100644
--- a/Documentation/devicetree/bindings/nvmem/qcom,sec-qfprom.yaml
+++ b/Documentation/devicetree/bindings/nvmem/qcom,sec-qfprom.yaml
@@ -16,6 +16,7 @@ description:
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml b/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml
index cd980def97b8..068bedf5dbc9 100644
--- a/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml
+++ b/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml
@@ -16,6 +16,7 @@ description: |
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml b/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
index 9c6eff788928..a44d44b32809 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
@@ -49,6 +49,7 @@ required:
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
- if:
properties:
diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml
index c5403e149080..b80fd8d1ae5b 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml
@@ -11,6 +11,7 @@ maintainers:
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml b/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml
index efccc5aacbe0..e27cbae2d63a 100644
--- a/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml
+++ b/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml
@@ -12,6 +12,7 @@ maintainers:
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml b/Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml
index da3f1de7d281..af97eeb8316c 100644
--- a/Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml
@@ -12,6 +12,7 @@ maintainers:
allOf:
- $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml b/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml
index 36d97fb87865..9c36afc7084b 100644
--- a/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml
+++ b/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml
@@ -51,6 +51,8 @@ properties:
ethaddr:
type: object
description: Ethernet interfaces base MAC address.
+ additionalProperties: false
+
properties:
"#nvmem-cell-cells":
description: The first argument is a MAC address offset.
diff --git a/Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml b/Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml
index bbbad31ae4ca..fd04d060c1de 100644
--- a/Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml
+++ b/Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml
@@ -26,7 +26,9 @@ description: |
properties:
compatible:
- const: operating-points-v2-kryo-cpu
+ enum:
+ - operating-points-v2-krait-cpu
+ - operating-points-v2-kryo-cpu
nvmem-cells:
description: |
@@ -47,6 +49,8 @@ patternProperties:
opp-microvolt: true
+ opp-peak-kBps: true
+
opp-supported-hw:
description: |
A single 32 bit bitmap value, representing compatible HW.
@@ -63,14 +67,22 @@ patternProperties:
5: MSM8996SG, speedbin 1
6: MSM8996SG, speedbin 2
7-31: unused
- enum: [0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
- 0x9, 0xd, 0xe, 0xf,
- 0x10, 0x20, 0x30, 0x70]
+
+ Bitmap for IPQ806x SoC:
+ 0: IPQ8062
+ 1: IPQ8064/IPQ8066/IPQ8068
+ 2: IPQ8065/IPQ8069
+ 3-31: unused
+
+ Other platforms use bits directly corresponding to speedbin index.
clock-latency-ns: true
required-opps: true
+ patternProperties:
+ '^opp-microvolt-speed[0-9]+-pvs[0-9]+$': true
+
required:
- opp-hz
@@ -256,6 +268,22 @@ examples:
};
};
+ /* Dummy opp table to give example for named opp-microvolt */
+ opp-table-2 {
+ compatible = "operating-points-v2-krait-cpu";
+ nvmem-cells = <&speedbin_efuse>;
+
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ opp-microvolt-speed0-pvs0 = <1000000 950000 1050000>;
+ opp-microvolt-speed0-pvs1 = <925000 878750 971250>;
+ opp-microvolt-speed0-pvs2 = <875000 831250 918750>;
+ opp-microvolt-speed0-pvs3 = <800000 760000 840000>;
+ opp-supported-hw = <0x7>;
+ clock-latency-ns = <100000>;
+ };
+ };
+
smem {
compatible = "qcom,smem";
memory-region = <&smem_mem>;
diff --git a/Documentation/devicetree/bindings/pci/rcar-gen4-pci-ep.yaml b/Documentation/devicetree/bindings/pci/rcar-gen4-pci-ep.yaml
new file mode 100644
index 000000000000..fe38f62da066
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/rcar-gen4-pci-ep.yaml
@@ -0,0 +1,115 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2022-2023 Renesas Electronics Corp.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/rcar-gen4-pci-ep.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas R-Car Gen4 PCIe Endpoint
+
+maintainers:
+ - Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+
+allOf:
+ - $ref: snps,dw-pcie-ep.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: renesas,r8a779f0-pcie-ep # R-Car S4-8
+ - const: renesas,rcar-gen4-pcie-ep # R-Car Gen4
+
+ reg:
+ maxItems: 7
+
+ reg-names:
+ items:
+ - const: dbi
+ - const: dbi2
+ - const: atu
+ - const: dma
+ - const: app
+ - const: phy
+ - const: addr_space
+
+ interrupts:
+ maxItems: 3
+
+ interrupt-names:
+ items:
+ - const: dma
+ - const: sft_ce
+ - const: app
+
+ clocks:
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: core
+ - const: ref
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+ reset-names:
+ items:
+ - const: pwr
+
+ max-link-speed:
+ maximum: 4
+
+ num-lanes:
+ maximum: 4
+
+ max-functions:
+ maximum: 2
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - interrupt-names
+ - clocks
+ - clock-names
+ - power-domains
+ - resets
+ - reset-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r8a779f0-cpg-mssr.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/power/r8a779f0-sysc.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pcie0_ep: pcie-ep@e65d0000 {
+ compatible = "renesas,r8a779f0-pcie-ep", "renesas,rcar-gen4-pcie-ep";
+ reg = <0 0xe65d0000 0 0x2000>, <0 0xe65d2000 0 0x1000>,
+ <0 0xe65d3000 0 0x2000>, <0 0xe65d5000 0 0x1200>,
+ <0 0xe65d6200 0 0x0e00>, <0 0xe65d7000 0 0x0400>,
+ <0 0xfe000000 0 0x400000>;
+ reg-names = "dbi", "dbi2", "atu", "dma", "app", "phy", "addr_space";
+ interrupts = <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "dma", "sft_ce", "app";
+ clocks = <&cpg CPG_MOD 624>, <&pcie0_clkref>;
+ clock-names = "core", "ref";
+ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
+ resets = <&cpg 624>;
+ reset-names = "pwr";
+ max-link-speed = <4>;
+ num-lanes = <2>;
+ max-functions = /bits/ 8 <2>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml b/Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml
new file mode 100644
index 000000000000..ffb34339b637
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml
@@ -0,0 +1,127 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2022-2023 Renesas Electronics Corp.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/rcar-gen4-pci-host.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas R-Car Gen4 PCIe Host
+
+maintainers:
+ - Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+
+allOf:
+ - $ref: snps,dw-pcie.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: renesas,r8a779f0-pcie # R-Car S4-8
+ - const: renesas,rcar-gen4-pcie # R-Car Gen4
+
+ reg:
+ maxItems: 7
+
+ reg-names:
+ items:
+ - const: dbi
+ - const: dbi2
+ - const: atu
+ - const: dma
+ - const: app
+ - const: phy
+ - const: config
+
+ interrupts:
+ maxItems: 4
+
+ interrupt-names:
+ items:
+ - const: msi
+ - const: dma
+ - const: sft_ce
+ - const: app
+
+ clocks:
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: core
+ - const: ref
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+ reset-names:
+ items:
+ - const: pwr
+
+ max-link-speed:
+ maximum: 4
+
+ num-lanes:
+ maximum: 4
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - interrupt-names
+ - clocks
+ - clock-names
+ - power-domains
+ - resets
+ - reset-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r8a779f0-cpg-mssr.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/power/r8a779f0-sysc.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pcie: pcie@e65d0000 {
+ compatible = "renesas,r8a779f0-pcie", "renesas,rcar-gen4-pcie";
+ reg = <0 0xe65d0000 0 0x1000>, <0 0xe65d2000 0 0x0800>,
+ <0 0xe65d3000 0 0x2000>, <0 0xe65d5000 0 0x1200>,
+ <0 0xe65d6200 0 0x0e00>, <0 0xe65d7000 0 0x0400>,
+ <0 0xfe000000 0 0x400000>;
+ reg-names = "dbi", "dbi2", "atu", "dma", "app", "phy", "config";
+ interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi", "dma", "sft_ce", "app";
+ clocks = <&cpg CPG_MOD 624>, <&pcie0_clkref>;
+ clock-names = "core", "ref";
+ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
+ resets = <&cpg 624>;
+ reset-names = "pwr";
+ max-link-speed = <4>;
+ num-lanes = <2>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ bus-range = <0x00 0xff>;
+ device_type = "pci";
+ ranges = <0x01000000 0 0x00000000 0 0xfe000000 0 0x00400000>,
+ <0x02000000 0 0x30000000 0 0x30000000 0 0x10000000>;
+ dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &gic GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gic GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gic GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gic GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>;
+ snps,enable-cdm-check;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pci/snps,dw-pcie-common.yaml b/Documentation/devicetree/bindings/pci/snps,dw-pcie-common.yaml
index d87e13496834..dc05761c5cf9 100644
--- a/Documentation/devicetree/bindings/pci/snps,dw-pcie-common.yaml
+++ b/Documentation/devicetree/bindings/pci/snps,dw-pcie-common.yaml
@@ -33,11 +33,11 @@ properties:
specific for each activated function, while the rest of the sub-spaces
are common for all of them (if there are more than one).
minItems: 2
- maxItems: 6
+ maxItems: 7
reg-names:
minItems: 2
- maxItems: 6
+ maxItems: 7
interrupts:
description:
diff --git a/Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml b/Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml
index 8fc2151691a4..bbdb01d22848 100644
--- a/Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml
+++ b/Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml
@@ -33,11 +33,11 @@ properties:
normal controller functioning. iATU memory IO region is also required
if the space is unrolled (IP-core version >= 4.80a).
minItems: 2
- maxItems: 5
+ maxItems: 7
reg-names:
minItems: 2
- maxItems: 5
+ maxItems: 7
items:
oneOf:
- description:
diff --git a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
index 8bbdeb8821f8..022055edbf9e 100644
--- a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
@@ -42,11 +42,11 @@ properties:
are required for the normal controller work. iATU memory IO region is
also required if the space is unrolled (IP-core version >= 4.80a).
minItems: 2
- maxItems: 5
+ maxItems: 7
reg-names:
minItems: 2
- maxItems: 5
+ maxItems: 7
items:
oneOf:
- description:
diff --git a/Documentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml b/Documentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml
index 897602559b37..426f90a47f35 100644
--- a/Documentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml
@@ -118,7 +118,7 @@ examples:
compatible = "xlnx,nwl-pcie-2.11";
reg = <0x0 0xfd0e0000 0x0 0x1000>,
<0x0 0xfd480000 0x0 0x1000>,
- <0x80 0x00000000 0x0 0x1000000>;
+ <0x80 0x00000000 0x0 0x10000000>;
reg-names = "breg", "pcireg", "cfg";
ranges = <0x02000000 0x0 0xe0000000 0x0 0xe0000000 0x0 0x10000000>,
<0x43000000 0x00000006 0x0 0x00000006 0x0 0x00000002 0x0>;
diff --git a/Documentation/devicetree/bindings/pci/xlnx,xdma-host.yaml b/Documentation/devicetree/bindings/pci/xlnx,xdma-host.yaml
new file mode 100644
index 000000000000..0aa00b8e49b3
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/xlnx,xdma-host.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/xlnx,xdma-host.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx XDMA PL PCIe Root Port Bridge
+
+maintainers:
+ - Thippeswamy Havalige <thippeswamy.havalige@amd.com>
+
+allOf:
+ - $ref: /schemas/pci/pci-bus.yaml#
+
+properties:
+ compatible:
+ const: xlnx,xdma-host-3.00
+
+ reg:
+ maxItems: 1
+
+ ranges:
+ maxItems: 2
+
+ interrupts:
+ items:
+ - description: interrupt asserted when miscellaneous interrupt is received.
+ - description: msi0 interrupt asserted when an MSI is received.
+ - description: msi1 interrupt asserted when an MSI is received.
+
+ interrupt-names:
+ items:
+ - const: misc
+ - const: msi0
+ - const: msi1
+
+ interrupt-map-mask:
+ items:
+ - const: 0
+ - const: 0
+ - const: 0
+ - const: 7
+
+ interrupt-map:
+ maxItems: 4
+
+ "#interrupt-cells":
+ const: 1
+
+ interrupt-controller:
+ description: identifies the node as an interrupt controller
+ type: object
+ properties:
+ interrupt-controller: true
+
+ "#address-cells":
+ const: 0
+
+ "#interrupt-cells":
+ const: 1
+
+ required:
+ - interrupt-controller
+ - "#address-cells"
+ - "#interrupt-cells"
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - ranges
+ - interrupts
+ - interrupt-map
+ - interrupt-map-mask
+ - "#interrupt-cells"
+ - interrupt-controller
+
+unevaluatedProperties: false
+
+examples:
+
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ pcie@a0000000 {
+ compatible = "xlnx,xdma-host-3.00";
+ reg = <0x0 0xa0000000 0x0 0x10000000>;
+ ranges = <0x2000000 0x0 0xb0000000 0x0 0xb0000000 0x0 0x1000000>,
+ <0x43000000 0x5 0x0 0x5 0x0 0x0 0x1000000>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "misc", "msi0", "msi1";
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0 0 0 1 &pcie_intc_0 0>,
+ <0 0 0 2 &pcie_intc_0 1>,
+ <0 0 0 3 &pcie_intc_0 2>,
+ <0 0 0 4 &pcie_intc_0 3>;
+ pcie_intc_0: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/perf/riscv,pmu.yaml b/Documentation/devicetree/bindings/perf/riscv,pmu.yaml
index c8448de2f2a0..d01c677ad3c7 100644
--- a/Documentation/devicetree/bindings/perf/riscv,pmu.yaml
+++ b/Documentation/devicetree/bindings/perf/riscv,pmu.yaml
@@ -90,7 +90,7 @@ properties:
bitmap of all MHPMCOUNTERx that can monitor the range of events
dependencies:
- "riscv,event-to-mhpmevent": [ "riscv,event-to-mhpmcounters" ]
+ riscv,event-to-mhpmevent: [ "riscv,event-to-mhpmcounters" ]
required:
- compatible
diff --git a/Documentation/devicetree/bindings/phy/marvell,pxa1928-usb-phy.yaml b/Documentation/devicetree/bindings/phy/marvell,pxa1928-usb-phy.yaml
new file mode 100644
index 000000000000..be33f036cda8
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/marvell,pxa1928-usb-phy.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/marvell,pxa1928-usb-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Marvell PXA1928 USB/HSIC PHY
+
+maintainers:
+ - Duje Mihanović <duje.mihanovic@skole.hr>
+
+properties:
+ compatible:
+ enum:
+ - marvell,pxa1928-usb-phy
+ - marvell,pxa1928-hsic-phy
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ '#phy-cells':
+ const: 0
+
+ resets:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/marvell,pxa1928.h>
+
+ usbphy: phy@7000 {
+ compatible = "marvell,pxa1928-usb-phy";
+ reg = <0x7000 0xe0>;
+ clocks = <&apmu PXA1928_CLK_USB>;
+ #phy-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml b/Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml
index a63b20dfa4a5..6703689fcdbe 100644
--- a/Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml
@@ -30,6 +30,7 @@ properties:
- const: mediatek,mt8173-mipi-tx
- items:
- enum:
+ - mediatek,mt8188-mipi-tx
- mediatek,mt8365-mipi-tx
- const: mediatek,mt8183-mipi-tx
- const: mediatek,mt2701-mipi-tx
diff --git a/Documentation/devicetree/bindings/phy/mediatek,mt7628-usbphy.yaml b/Documentation/devicetree/bindings/phy/mediatek,mt7628-usbphy.yaml
new file mode 100644
index 000000000000..ce2c228e3216
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/mediatek,mt7628-usbphy.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/mediatek,mt7628-usbphy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek/Ralink USB PHY
+
+maintainers:
+ - Sergio Paracuellos <sergio.paracuellos@gmail.com>
+
+properties:
+ compatible:
+ enum:
+ - mediatek,mt7620-usbphy
+ - mediatek,mt7628-usbphy
+ - ralink,rt3352-usbphy
+
+ reg:
+ maxItems: 1
+
+ "#phy-cells":
+ const: 0
+
+ ralink,sysctl:
+ description:
+ phandle to a ralink syscon register region.
+ $ref: /schemas/types.yaml#/definitions/phandle
+
+ resets:
+ items:
+ - description: USB Host reset controller
+ - description: USB Device reset controller
+
+ reset-names:
+ items:
+ - const: host
+ - const: device
+
+required:
+ - compatible
+ - "#phy-cells"
+ - ralink,sysctl
+ - resets
+ - reset-names
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: mediatek,mt7628-usbphy
+ then:
+ required:
+ - reg
+ else:
+ properties:
+ reg: false
+
+additionalProperties: false
+
+examples:
+ - |
+ phy@10120000 {
+ compatible = "mediatek,mt7628-usbphy";
+ reg = <0x10120000 0x1000>;
+ #phy-cells = <0>;
+ ralink,sysctl = <&sysc>;
+ resets = <&rstctrl 22>,
+ <&rstctrl 25>;
+ reset-names = "host", "device";
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt b/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt
deleted file mode 100644
index 35f03df00130..000000000000
--- a/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-ST STiH407 USB PHY controller
-
-This file documents the dt bindings for the usb picoPHY driver which is the PHY for both USB2 and USB3
-host controllers (when controlling usb2/1.1 devices) available on STiH407 SoC family from STMicroelectronics.
-
-Required properties:
-- compatible : should be "st,stih407-usb2-phy"
-- st,syscfg : phandle of sysconfig bank plus integer array containing phyparam and phyctrl register offsets
-- resets : list of phandle and reset specifier pairs. There should be two entries, one
- for the whole phy and one for the port
-- reset-names : list of reset signal names. Should be "global" and "port"
-See: Documentation/devicetree/bindings/reset/st,stih407-powerdown.yaml
-See: Documentation/devicetree/bindings/reset/reset.txt
-
-Example:
-
-usb2_picophy0: usbpicophy@f8 {
- compatible = "st,stih407-usb2-phy";
- #phy-cells = <0>;
- st,syscfg = <&syscfg_core 0x100 0xf4>;
- resets = <&softreset STIH407_PICOPHY_SOFTRESET>,
- <&picophyreset STIH407_PICOPHY0_RESET>;
- reset-names = "global", "port";
-};
diff --git a/Documentation/devicetree/bindings/phy/pxa1928-usb-phy.txt b/Documentation/devicetree/bindings/phy/pxa1928-usb-phy.txt
deleted file mode 100644
index da94426aa694..000000000000
--- a/Documentation/devicetree/bindings/phy/pxa1928-usb-phy.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-* Marvell PXA1928 USB and HSIC PHYs
-
-Required properties:
-- compatible: "marvell,pxa1928-usb-phy" or "marvell,pxa1928-hsic-phy"
-- reg: base address and length of the registers
-- clocks - A single clock. From common clock binding.
-- #phys-cells: should be 0. From common phy binding.
-- resets: reference to the reset controller
-
-Example:
-
- usbphy: phy@7000 {
- compatible = "marvell,pxa1928-usb-phy";
- reg = <0x7000 0xe0>;
- clocks = <&apmu_clocks PXA1928_CLK_USB>;
- #phy-cells = <0>;
- };
-
diff --git a/Documentation/devicetree/bindings/phy/qcom,ipq5332-usb-hsphy.yaml b/Documentation/devicetree/bindings/phy/qcom,ipq5332-usb-hsphy.yaml
index 2671a048c926..e77576d06c0e 100644
--- a/Documentation/devicetree/bindings/phy/qcom,ipq5332-usb-hsphy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,ipq5332-usb-hsphy.yaml
@@ -17,7 +17,9 @@ description:
properties:
compatible:
items:
- - const: qcom,ipq5332-usb-hsphy
+ - enum:
+ - qcom,ipq5018-usb-hsphy
+ - qcom,ipq5332-usb-hsphy
"#phy-cells":
const: 0
diff --git a/Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml
index 5073007267ad..634cec5d57ea 100644
--- a/Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml
@@ -70,7 +70,7 @@ examples:
phy@84000 {
compatible = "qcom,ipq6018-qmp-pcie-phy";
- reg = <0x0 0x00084000 0x0 0x1000>;
+ reg = <0x00084000 0x1000>;
clocks = <&gcc GCC_PCIE0_AUX_CLK>,
<&gcc GCC_PCIE0_AHB_CLK>,
diff --git a/Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-usb3-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-usb3-phy.yaml
deleted file mode 100644
index 827109d37041..000000000000
--- a/Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-usb3-phy.yaml
+++ /dev/null
@@ -1,287 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/phy/qcom,msm8996-qmp-usb3-phy.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Qualcomm QMP PHY controller (USB, MSM8996)
-
-maintainers:
- - Vinod Koul <vkoul@kernel.org>
-
-description:
- QMP PHY controller supports physical layer functionality for a number of
- controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
-
- Note that these bindings are for SoCs up to SC8180X. For newer SoCs, see
- qcom,sc8280xp-qmp-usb3-uni-phy.yaml.
-
-properties:
- compatible:
- enum:
- - qcom,ipq6018-qmp-usb3-phy
- - qcom,ipq8074-qmp-usb3-phy
- - qcom,msm8996-qmp-usb3-phy
- - qcom,msm8998-qmp-usb3-phy
- - qcom,sdm845-qmp-usb3-uni-phy
- - qcom,sdx55-qmp-usb3-uni-phy
- - qcom,sdx65-qmp-usb3-uni-phy
- - qcom,sm8150-qmp-usb3-uni-phy
- - qcom,sm8250-qmp-usb3-uni-phy
- - qcom,sm8350-qmp-usb3-uni-phy
-
- reg:
- items:
- - description: serdes
-
- "#address-cells":
- enum: [ 1, 2 ]
-
- "#size-cells":
- enum: [ 1, 2 ]
-
- ranges: true
-
- clocks:
- minItems: 3
- maxItems: 4
-
- clock-names:
- minItems: 3
- maxItems: 4
-
- power-domains:
- maxItems: 1
-
- resets:
- maxItems: 2
-
- reset-names:
- maxItems: 2
-
- vdda-phy-supply: true
-
- vdda-pll-supply: true
-
- vddp-ref-clk-supply: true
-
-patternProperties:
- "^phy@[0-9a-f]+$":
- type: object
- description: single PHY-provider child node
- properties:
- reg:
- minItems: 3
- maxItems: 6
-
- clocks:
- items:
- - description: PIPE clock
-
- clock-names:
- deprecated: true
- items:
- - const: pipe0
-
- "#clock-cells":
- const: 0
-
- clock-output-names:
- maxItems: 1
-
- "#phy-cells":
- const: 0
-
- required:
- - reg
- - clocks
- - "#clock-cells"
- - clock-output-names
- - "#phy-cells"
-
- additionalProperties: false
-
-required:
- - compatible
- - reg
- - "#address-cells"
- - "#size-cells"
- - ranges
- - clocks
- - clock-names
- - resets
- - reset-names
- - vdda-phy-supply
- - vdda-pll-supply
-
-additionalProperties: false
-
-allOf:
- - if:
- properties:
- compatible:
- contains:
- enum:
- - qcom,sdm845-qmp-usb3-uni-phy
- then:
- properties:
- clocks:
- maxItems: 4
- clock-names:
- items:
- - const: aux
- - const: cfg_ahb
- - const: ref
- - const: com_aux
- resets:
- maxItems: 2
- reset-names:
- items:
- - const: phy
- - const: common
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- - qcom,ipq8074-qmp-usb3-phy
- - qcom,msm8996-qmp-usb3-phy
- - qcom,msm8998-qmp-usb3-phy
- - qcom,sdx55-qmp-usb3-uni-phy
- - qcom,sdx65-qmp-usb3-uni-phy
- then:
- properties:
- clocks:
- maxItems: 3
- clock-names:
- items:
- - const: aux
- - const: cfg_ahb
- - const: ref
- resets:
- maxItems: 2
- reset-names:
- items:
- - const: phy
- - const: common
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- - qcom,sm8150-qmp-usb3-uni-phy
- - qcom,sm8250-qmp-usb3-uni-phy
- - qcom,sm8350-qmp-usb3-uni-phy
- then:
- properties:
- clocks:
- maxItems: 4
- clock-names:
- items:
- - const: aux
- - const: ref_clk_src
- - const: ref
- - const: com_aux
- resets:
- maxItems: 2
- reset-names:
- items:
- - const: phy
- - const: common
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- - qcom,msm8998-qmp-usb3-phy
- then:
- patternProperties:
- "^phy@[0-9a-f]+$":
- properties:
- reg:
- items:
- - description: TX lane 1
- - description: RX lane 1
- - description: PCS
- - description: TX lane 2
- - description: RX lane 2
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- - qcom,ipq6018-qmp-usb3-phy
- - qcom,ipq8074-qmp-usb3-phy
- - qcom,sdx55-qmp-usb3-uni-phy
- - qcom,sdx65-qmp-usb3-uni-phy
- - qcom,sm8150-qmp-usb3-uni-phy
- then:
- patternProperties:
- "^phy@[0-9a-f]+$":
- properties:
- reg:
- items:
- - description: TX
- - description: RX
- - description: PCS
- - description: PCS_MISC
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- - qcom,msm8996-qmp-usb3-phy
- - qcom,sm8250-qmp-usb3-uni-phy
- - qcom,sm8350-qmp-usb3-uni-phy
- then:
- patternProperties:
- "^phy@[0-9a-f]+$":
- properties:
- reg:
- items:
- - description: TX
- - description: RX
- - description: PCS
-
-examples:
- - |
- #include <dt-bindings/clock/qcom,gcc-sdm845.h>
- usb_2_qmpphy: phy-wrapper@88eb000 {
- compatible = "qcom,sdm845-qmp-usb3-uni-phy";
- reg = <0x088eb000 0x18c>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x0 0x088eb000 0x2000>;
-
- clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK >,
- <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
- <&gcc GCC_USB3_SEC_CLKREF_CLK>,
- <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "com_aux";
-
- resets = <&gcc GCC_USB3PHY_PHY_SEC_BCR>,
- <&gcc GCC_USB3_PHY_SEC_BCR>;
- reset-names = "phy", "common";
-
- vdda-phy-supply = <&vdda_usb2_ss_1p2>;
- vdda-pll-supply = <&vdda_usb2_ss_core>;
-
- usb_2_ssphy: phy@200 {
- reg = <0x200 0x128>,
- <0x400 0x1fc>,
- <0x800 0x218>,
- <0x600 0x70>;
-
- clocks = <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
-
- #clock-cells = <0>;
- clock-output-names = "usb3_uni_phy_pipe_clk_src";
-
- #phy-cells = <0>;
- };
- };
diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml
index d981d77e82e4..f3a3296c811c 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml
@@ -19,6 +19,7 @@ properties:
- qcom,msm8996-qmp-ufs-phy
- qcom,msm8998-qmp-ufs-phy
- qcom,sa8775p-qmp-ufs-phy
+ - qcom,sc7280-qmp-ufs-phy
- qcom,sc8180x-qmp-ufs-phy
- qcom,sc8280xp-qmp-ufs-phy
- qcom,sdm845-qmp-ufs-phy
@@ -85,6 +86,7 @@ allOf:
contains:
enum:
- qcom,sa8775p-qmp-ufs-phy
+ - qcom,sc7280-qmp-ufs-phy
- qcom,sm8450-qmp-ufs-phy
then:
properties:
diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml
index f99fbbcd68fb..57702f7f2a46 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml
@@ -16,20 +16,34 @@ description:
properties:
compatible:
enum:
+ - qcom,ipq6018-qmp-usb3-phy
+ - qcom,ipq8074-qmp-usb3-phy
- qcom,ipq9574-qmp-usb3-phy
+ - qcom,msm8996-qmp-usb3-phy
+ - qcom,msm8998-qmp-usb3-phy
- qcom,qcm2290-qmp-usb3-phy
- qcom,sa8775p-qmp-usb3-uni-phy
- qcom,sc8280xp-qmp-usb3-uni-phy
+ - qcom,sdm845-qmp-usb3-uni-phy
+ - qcom,sdx55-qmp-usb3-uni-phy
+ - qcom,sdx65-qmp-usb3-uni-phy
+ - qcom,sdx75-qmp-usb3-uni-phy
- qcom,sm6115-qmp-usb3-phy
+ - qcom,sm8150-qmp-usb3-uni-phy
+ - qcom,sm8250-qmp-usb3-uni-phy
+ - qcom,sm8350-qmp-usb3-uni-phy
+
reg:
maxItems: 1
clocks:
- maxItems: 4
+ minItems: 4
+ maxItems: 5
clock-names:
- maxItems: 4
+ minItems: 4
+ maxItems: 5
power-domains:
maxItems: 1
@@ -74,9 +88,18 @@ allOf:
compatible:
contains:
enum:
+ - qcom,ipq6018-qmp-usb3-phy
+ - qcom,ipq8074-qmp-usb3-phy
- qcom,ipq9574-qmp-usb3-phy
+ - qcom,msm8996-qmp-usb3-phy
+ - qcom,msm8998-qmp-usb3-phy
+ - qcom,sdx55-qmp-usb3-uni-phy
+ - qcom,sdx65-qmp-usb3-uni-phy
+ - qcom,sdx75-qmp-usb3-uni-phy
then:
properties:
+ clocks:
+ maxItems: 4
clock-names:
items:
- const: aux
@@ -109,6 +132,9 @@ allOf:
enum:
- qcom,sa8775p-qmp-usb3-uni-phy
- qcom,sc8280xp-qmp-usb3-uni-phy
+ - qcom,sm8150-qmp-usb3-uni-phy
+ - qcom,sm8250-qmp-usb3-uni-phy
+ - qcom,sm8350-qmp-usb3-uni-phy
then:
properties:
clocks:
@@ -119,6 +145,33 @@ allOf:
- const: ref
- const: com_aux
- const: pipe
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sdm845-qmp-usb3-uni-phy
+ then:
+ properties:
+ clocks:
+ maxItems: 5
+ clock-names:
+ items:
+ - const: aux
+ - const: cfg_ahb
+ - const: ref
+ - const: com_aux
+ - const: pipe
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sa8775p-qmp-usb3-uni-phy
+ - qcom,sc8280xp-qmp-usb3-uni-phy
+ then:
required:
- power-domains
diff --git a/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml
index c53bab107b6d..c95828607ab6 100644
--- a/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml
@@ -14,7 +14,12 @@ description:
properties:
compatible:
- const: qcom,sm8550-snps-eusb2-phy
+ oneOf:
+ - items:
+ - enum:
+ - qcom,sdx75-snps-eusb2-phy
+ - const: qcom,sm8550-snps-eusb2-phy
+ - const: qcom,sm8550-snps-eusb2-phy
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-repeater.yaml b/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-repeater.yaml
index 029569d5fcf3..24c733c10e0e 100644
--- a/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-repeater.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-repeater.yaml
@@ -32,6 +32,27 @@ properties:
vdd3-supply: true
+ qcom,tune-usb2-disc-thres:
+ $ref: /schemas/types.yaml#/definitions/uint8
+ description: High-Speed disconnect threshold
+ minimum: 0
+ maximum: 7
+ default: 0
+
+ qcom,tune-usb2-amplitude:
+ $ref: /schemas/types.yaml#/definitions/uint8
+ description: High-Speed trasmit amplitude
+ minimum: 0
+ maximum: 15
+ default: 8
+
+ qcom,tune-usb2-preem:
+ $ref: /schemas/types.yaml#/definitions/uint8
+ description: High-Speed TX pre-emphasis tuning
+ minimum: 0
+ maximum: 7
+ default: 5
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/phy/ralink-usb-phy.txt b/Documentation/devicetree/bindings/phy/ralink-usb-phy.txt
deleted file mode 100644
index 9d2868a437ab..000000000000
--- a/Documentation/devicetree/bindings/phy/ralink-usb-phy.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-Mediatek/Ralink USB PHY
-
-Required properties:
- - compatible: "ralink,rt3352-usbphy"
- "mediatek,mt7620-usbphy"
- "mediatek,mt7628-usbphy"
- - reg: required for "mediatek,mt7628-usbphy", unused otherwise
- - #phy-cells: should be 0
- - ralink,sysctl: a phandle to a ralink syscon register region
- - resets: the two reset controllers for host and device
- - reset-names: the names of the 2 reset controllers
-
-Example:
-
-usbphy: phy {
- compatible = "mediatek,mt7628-usbphy";
- reg = <0x10120000 0x1000>;
- #phy-cells = <0>;
-
- ralink,sysctl = <&sysc>;
- resets = <&rstctrl 22 &rstctrl 25>;
- reset-names = "host", "device";
-};
diff --git a/Documentation/devicetree/bindings/phy/st,stih407-usb2-phy.yaml b/Documentation/devicetree/bindings/phy/st,stih407-usb2-phy.yaml
new file mode 100644
index 000000000000..e45cdd98aab2
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/st,stih407-usb2-phy.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/st,stih407-usb2-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STMicroelectronics STiH407 USB PHY controller
+
+maintainers:
+ - Patrice Chotard <patrice.chotard@foss.st.com>
+
+description:
+ The USB picoPHY device is the PHY for both USB2 and USB3 host controllers
+ (when controlling usb2/1.1 devices) available on STiH407 SoC family from
+ STMicroelectronics.
+
+properties:
+ compatible:
+ const: st,stih407-usb2-phy
+
+ st,syscfg:
+ description: Phandle to the syscfg bank
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ items:
+ - items:
+ - description: phandle to syscfg
+ - description: phyparam register offset
+ - description: phyctrl register offset
+
+ resets:
+ items:
+ - description: Phandle and reset specifier pair for the whole phy.
+ - description: Phandle and reset specifier pair for the port.
+
+ reset-names:
+ items:
+ - const: global
+ - const: port
+
+ "#phy-cells":
+ const: 0
+
+required:
+ - compatible
+ - st,syscfg
+ - resets
+ - reset-names
+ - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/reset/stih407-resets.h>
+ usb-phy {
+ compatible = "st,stih407-usb2-phy";
+ #phy-cells = <0>;
+ st,syscfg = <&syscfg_core 0x100 0xf4>;
+ resets = <&softreset STIH407_PICOPHY_SOFTRESET>,
+ <&picophyreset STIH407_PICOPHY0_RESET>;
+ reset-names = "global", "port";
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/amlogic,meson-pinctrl-a1.yaml b/Documentation/devicetree/bindings/pinctrl/amlogic,meson-pinctrl-a1.yaml
index 4e7a456ea4cc..c7df4cd34197 100644
--- a/Documentation/devicetree/bindings/pinctrl/amlogic,meson-pinctrl-a1.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/amlogic,meson-pinctrl-a1.yaml
@@ -16,6 +16,7 @@ properties:
compatible:
enum:
- amlogic,c3-periphs-pinctrl
+ - amlogic,t7-periphs-pinctrl
- amlogic,meson-a1-periphs-pinctrl
- amlogic,meson-s4-periphs-pinctrl
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,bcm6318-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6318-pinctrl.yaml
index 4478a76171f7..62890a0aead1 100644
--- a/Documentation/devicetree/bindings/pinctrl/brcm,bcm6318-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6318-pinctrl.yaml
@@ -24,6 +24,7 @@ patternProperties:
'-pins$':
type: object
$ref: pinmux-node.yaml#
+ additionalProperties: false
properties:
function:
@@ -37,6 +38,10 @@ patternProperties:
enum: [ gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, gpio7,
gpio8, gpio9, gpio10, gpio11, gpio12, gpio13, gpio40 ]
+ patternProperties:
+ '-pins$':
+ $ref: '#/patternProperties/-pins$'
+
allOf:
- $ref: pinctrl.yaml#
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.yaml
index 73e1caa7c011..7cc0e1650835 100644
--- a/Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.yaml
@@ -24,6 +24,7 @@ patternProperties:
'-pins$':
type: object
$ref: pinmux-node.yaml#
+ unevaluatedProperties: false
properties:
function:
@@ -36,11 +37,15 @@ patternProperties:
pins:
enum: [ gpio0, gpio1, gpio16, gpio17, gpio8, gpio9, gpio18, gpio19,
- gpio22, gpio23, gpio30, gpio31, nand_grp, gpio35
+ gpio22, gpio23, gpio30, gpio31, nand_grp, gpio35,
dectpd_grp, vdsl_phy_override_0_grp,
vdsl_phy_override_1_grp, vdsl_phy_override_2_grp,
vdsl_phy_override_3_grp, dsl_gpio8, dsl_gpio9 ]
+ patternProperties:
+ '-pins$':
+ $ref: '#/patternProperties/-pins$'
+
allOf:
- $ref: pinctrl.yaml#
@@ -122,46 +127,46 @@ examples:
pinctrl_nand: nand-pins {
function = "nand";
- group = "nand_grp";
+ pins = "nand_grp";
};
pinctrl_gpio35_alt: gpio35_alt-pins {
function = "gpio35_alt";
- pin = "gpio35";
+ pins = "gpio35";
};
pinctrl_dectpd: dectpd-pins {
function = "dectpd";
- group = "dectpd_grp";
+ pins = "dectpd_grp";
};
pinctrl_vdsl_phy_override_0: vdsl_phy_override_0-pins {
function = "vdsl_phy_override_0";
- group = "vdsl_phy_override_0_grp";
+ pins = "vdsl_phy_override_0_grp";
};
pinctrl_vdsl_phy_override_1: vdsl_phy_override_1-pins {
function = "vdsl_phy_override_1";
- group = "vdsl_phy_override_1_grp";
+ pins = "vdsl_phy_override_1_grp";
};
pinctrl_vdsl_phy_override_2: vdsl_phy_override_2-pins {
function = "vdsl_phy_override_2";
- group = "vdsl_phy_override_2_grp";
+ pins = "vdsl_phy_override_2_grp";
};
pinctrl_vdsl_phy_override_3: vdsl_phy_override_3-pins {
function = "vdsl_phy_override_3";
- group = "vdsl_phy_override_3_grp";
+ pins = "vdsl_phy_override_3_grp";
};
pinctrl_dsl_gpio8: dsl_gpio8-pins {
function = "dsl_gpio8";
- group = "dsl_gpio8";
+ pins = "dsl_gpio8";
};
pinctrl_dsl_gpio9: dsl_gpio9-pins {
function = "dsl_gpio9";
- group = "dsl_gpio9";
+ pins = "dsl_gpio9";
};
};
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.yaml
index 2750ba42aeb8..f57bb34c3130 100644
--- a/Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.yaml
@@ -24,6 +24,7 @@ patternProperties:
'-pins$':
type: object
$ref: pinmux-node.yaml#
+ unevaluatedProperties: false
properties:
function:
@@ -36,6 +37,10 @@ patternProperties:
gpio20, gpio25, gpio26, gpio27, gpio28, hsspi_cs1,
usb_port1 ]
+ patternProperties:
+ '-pins$':
+ $ref: '#/patternProperties/-pins$'
+
allOf:
- $ref: pinctrl.yaml#
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.yaml
index 2f6c540498bc..ce6fc5380c52 100644
--- a/Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.yaml
@@ -24,15 +24,16 @@ patternProperties:
'-pins$':
type: object
$ref: pinmux-node.yaml#
+ unevaluatedProperties: false
properties:
function:
enum: [ ebi_cs, uart1, serial_led, legacy_led, led, spi_cs, utopia,
pwm_syn_clk, sys_irq ]
- pins:
+ groups:
enum: [ ebi_cs_grp, uart1_grp, serial_led_grp, legacy_led_grp,
- led_grp, spi_cs_grp, utopia_grp, pwm_syn_clk, sys_irq_grp ]
+ led_grp, spi_cs_grp, utopia_grp, pwm_syn_clk_grp, sys_irq_grp ]
allOf:
- $ref: pinctrl.yaml#
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.yaml
index b3044f805753..5f7ed7d3dd49 100644
--- a/Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.yaml
@@ -24,6 +24,7 @@ patternProperties:
'-pins$':
type: object
$ref: pinmux-node.yaml#
+ unevaluatedProperties: false
properties:
function:
@@ -41,6 +42,10 @@ patternProperties:
gpio15, gpio16, gpio17, gpio18, gpio19, gpio20, gpio21,
gpio22, gpio23, gpio24, gpio25, gpio26, gpio27, nand_grp ]
+ patternProperties:
+ '-pins$':
+ $ref: '#/patternProperties/-pins$'
+
allOf:
- $ref: pinctrl.yaml#
@@ -204,6 +209,6 @@ examples:
pinctrl_nand: nand-pins {
function = "nand";
- group = "nand_grp";
+ pins = "nand_grp";
};
};
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.yaml
index 3236871827df..d549e945505b 100644
--- a/Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.yaml
@@ -24,6 +24,7 @@ patternProperties:
'-pins$':
type: object
$ref: pinmux-node.yaml#
+ unevaluatedProperties: false
properties:
function:
@@ -42,6 +43,10 @@ patternProperties:
gpio24, gpio25, gpio26, gpio27, gpio28, gpio29, gpio30,
gpio31, uart1_grp ]
+ patternProperties:
+ '-pins$':
+ $ref: '#/patternProperties/-pins$'
+
allOf:
- $ref: pinctrl.yaml#
@@ -215,6 +220,6 @@ examples:
pinctrl_uart1: uart1-pins {
function = "uart1";
- group = "uart1_grp";
+ pins = "uart1_grp";
};
};
diff --git a/Documentation/devicetree/bindings/pinctrl/nuvoton,npcm845-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/nuvoton,npcm845-pinctrl.yaml
new file mode 100644
index 000000000000..3e8472898800
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nuvoton,npcm845-pinctrl.yaml
@@ -0,0 +1,217 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/nuvoton,npcm845-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Nuvoton NPCM845 Pin Controller and GPIO
+
+maintainers:
+ - Tomer Maimon <tmaimon77@gmail.com>
+
+description:
+ The Nuvoton BMC NPCM8XX Pin Controller multi-function routed through
+ the multiplexing block, Each pin supports GPIO functionality (GPIOx)
+ and multiple functions that directly connect the pin to different
+ hardware blocks.
+
+properties:
+ compatible:
+ const: nuvoton,npcm845-pinctrl
+
+ ranges:
+ maxItems: 1
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 1
+
+ nuvoton,sysgcr:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: a phandle to access GCR registers.
+
+patternProperties:
+ '^gpio@':
+ type: object
+ additionalProperties: false
+
+ description:
+ Eight GPIO banks that each contain 32 GPIOs.
+
+ properties:
+ gpio-controller: true
+
+ '#gpio-cells':
+ const: 2
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ gpio-ranges:
+ maxItems: 1
+
+ required:
+ - gpio-controller
+ - '#gpio-cells'
+ - reg
+ - interrupts
+ - gpio-ranges
+
+ '-mux$':
+ $ref: pinmux-node.yaml#
+
+ properties:
+ groups:
+ description:
+ One or more groups of pins to mux to a certain function
+ items:
+ enum: [ iox1, iox2, smb1d, smb2d, lkgpo1, lkgpo2, ioxh, gspi,
+ smb5b, smb5c, lkgpo0, pspi, jm1, jm2, smb4den, smb4b,
+ smb4c, smb15, smb16, smb17, smb18, smb19, smb20, smb21,
+ smb22, smb23, smb23b, smb4d, smb14, smb5, smb4, smb3,
+ spi0cs1, spi0cs2, spi0cs3, spi1cs0, spi1cs1, spi1cs2,
+ spi1cs3, spi1cs23, smb3c, smb3b, bmcuart0a, uart1, jtag2,
+ bmcuart1, uart2, sg1mdio, bmcuart0b, r1err, r1md, r1oen,
+ r2oen, rmii3, r3oen, smb3d, fanin0, fanin1, fanin2, fanin3,
+ fanin4, fanin5, fanin6, fanin7, fanin8, fanin9, fanin10,
+ fanin11, fanin12, fanin13, fanin14, fanin15, pwm0, pwm1, pwm2,
+ pwm3, r2, r2err, r2md, r3rxer, ga20kbc, smb5d, lpc, espi, rg2,
+ ddr, i3c0, i3c1, i3c2, i3c3, i3c4, i3c5, smb0, smb1, smb2,
+ smb2c, smb2b, smb1c, smb1b, smb8, smb9, smb10, smb11, sd1,
+ sd1pwr, pwm4, pwm5, pwm6, pwm7, pwm8, pwm9, pwm10, pwm11,
+ mmc8, mmc, mmcwp, mmccd, mmcrst, clkout, serirq, lpcclk,
+ scipme, smi, smb6, smb7, spi1, faninx, r1, spi3, spi3cs1,
+ spi3quad, spi3cs2, spi3cs3, nprd_smi, smb0b, smb0c, smb0den,
+ smb0d, ddc, rg2mdio, wdog1, wdog2, smb12, smb13, spix,
+ spixcs1, clkreq, hgpio0, hgpio1, hgpio2, hgpio3, hgpio4,
+ hgpio5, hgpio6, hgpio7 ]
+
+ function:
+ description:
+ The function that a group of pins is muxed to
+ enum: [ iox1, iox2, smb1d, smb2d, lkgpo1, lkgpo2, ioxh, gspi,
+ smb5b, smb5c, lkgpo0, pspi, jm1, jm2, smb4den, smb4b,
+ smb4c, smb15, smb16, smb17, smb18, smb19, smb20, smb21,
+ smb22, smb23, smb23b, smb4d, smb14, smb5, smb4, smb3,
+ spi0cs1, spi0cs2, spi0cs3, spi1cs0, spi1cs1, spi1cs2,
+ spi1cs3, spi1cs23, smb3c, smb3b, bmcuart0a, uart1, jtag2,
+ bmcuart1, uart2, sg1mdio, bmcuart0b, r1err, r1md, r1oen,
+ r2oen, rmii3, r3oen, smb3d, fanin0, fanin1, fanin2, fanin3,
+ fanin4, fanin5, fanin6, fanin7, fanin8, fanin9, fanin10,
+ fanin11, fanin12, fanin13, fanin14, fanin15, pwm0, pwm1, pwm2,
+ pwm3, r2, r2err, r2md, r3rxer, ga20kbc, smb5d, lpc, espi, rg2,
+ ddr, i3c0, i3c1, i3c2, i3c3, i3c4, i3c5, smb0, smb1, smb2,
+ smb2c, smb2b, smb1c, smb1b, smb8, smb9, smb10, smb11, sd1,
+ sd1pwr, pwm4, pwm5, pwm6, pwm7, pwm8, pwm9, pwm10, pwm11,
+ mmc8, mmc, mmcwp, mmccd, mmcrst, clkout, serirq, lpcclk,
+ scipme, smi, smb6, smb7, spi1, faninx, r1, spi3, spi3cs1,
+ spi3quad, spi3cs2, spi3cs3, nprd_smi, smb0b, smb0c, smb0den,
+ smb0d, ddc, rg2mdio, wdog1, wdog2, smb12, smb13, spix,
+ spixcs1, clkreq, hgpio0, hgpio1, hgpio2, hgpio3, hgpio4,
+ hgpio5, hgpio6, hgpio7 ]
+
+ dependencies:
+ groups: [ function ]
+ function: [ groups ]
+
+ additionalProperties: false
+
+ '^pin':
+ $ref: pincfg-node.yaml#
+
+ properties:
+ pins:
+ description:
+ A list of pins to configure in certain ways, such as enabling
+ debouncing
+ items:
+ pattern: '^GPIO([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-6])'
+
+ bias-disable: true
+
+ bias-pull-up: true
+
+ bias-pull-down: true
+
+ input-enable: true
+
+ output-low: true
+
+ output-high: true
+
+ drive-push-pull: true
+
+ drive-open-drain: true
+
+ input-debounce:
+ description:
+ Debouncing periods in microseconds, one period per interrupt
+ bank found in the controller
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 1
+ maxItems: 4
+
+ slew-rate:
+ description: |
+ 0: Low rate
+ 1: High rate
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+
+ drive-strength:
+ enum: [ 0, 1, 2, 4, 8, 12 ]
+
+ additionalProperties: false
+
+allOf:
+ - $ref: pinctrl.yaml#
+
+required:
+ - compatible
+ - ranges
+ - '#address-cells'
+ - '#size-cells'
+ - nuvoton,sysgcr
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/gpio/gpio.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pinctrl: pinctrl@f0010000 {
+ compatible = "nuvoton,npcm845-pinctrl";
+ ranges = <0x0 0x0 0xf0010000 0x8000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ nuvoton,sysgcr = <&gcr>;
+
+ gpio0: gpio@0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0x0 0xb0>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&pinctrl 0 0 32>;
+ };
+
+ fanin0_pin: fanin0-mux {
+ groups = "fanin0";
+ function = "fanin0";
+ };
+
+ pin34_slew: pin34-slew {
+ pins = "GPIO34/I3C4_SDA";
+ bias-disable;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/nxp,s32g2-siul2-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/nxp,s32g2-siul2-pinctrl.yaml
index d49aafd8c5f4..a24286e4def6 100644
--- a/Documentation/devicetree/bindings/pinctrl/nxp,s32g2-siul2-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/nxp,s32g2-siul2-pinctrl.yaml
@@ -9,7 +9,7 @@ title: NXP S32G2 pin controller
maintainers:
- Ghennadi Procopciuc <Ghennadi.Procopciuc@oss.nxp.com>
- - Chester Lin <clin@suse.com>
+ - Chester Lin <chester62515@gmail.com>
description: |
S32G2 pinmux is implemented in SIUL2 (System Integration Unit Lite2),
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-tlmm.yaml
index 2aedb7e7bc8b..5ece3b9d676b 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-tlmm.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-tlmm.yaml
@@ -43,7 +43,8 @@ patternProperties:
"-state$":
oneOf:
- $ref: "#/$defs/qcom-mdm9607-tlmm-state"
- - patternProperties:
+ - additionalProperties: false
+ patternProperties:
".*":
$ref: "#/$defs/qcom-mdm9607-tlmm-state"
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8226-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8226-pinctrl.yaml
index 9efb76509580..a602bf0d27fb 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8226-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8226-pinctrl.yaml
@@ -67,8 +67,8 @@ $defs:
Specify the alternative function to be configured for the specified
pins. Functions are only valid for gpio pins.
enum: [ gpio, cci_i2c0, blsp_uim1, blsp_uim2, blsp_uim3, blsp_uim5,
- blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5, blsp_spi1,
- blsp_spi2, blsp_spi3, blsp_spi5, blsp_uart1, blsp_uart2,
+ blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5, blsp_i2c6,
+ blsp_spi1, blsp_spi2, blsp_spi3, blsp_spi5, blsp_uart1, blsp_uart2,
blsp_uart3, blsp_uart4, blsp_uart5, cam_mclk0, cam_mclk1,
gp0_clk, gp1_clk, sdc3, wlan ]
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sa8775p-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sa8775p-tlmm.yaml
index e119a226a4b1..2173c5255638 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sa8775p-tlmm.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sa8775p-tlmm.yaml
@@ -28,6 +28,7 @@ properties:
gpio-controller: true
"#gpio-cells": true
gpio-ranges: true
+ wakeup-parent: true
gpio-reserved-ranges:
minItems: 1
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml
index 368d44ff5468..c8735ab97e40 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml
@@ -41,6 +41,10 @@ properties:
gpio-ranges:
maxItems: 1
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 88
+
gpio-line-names:
maxItems: 175
diff --git a/Documentation/devicetree/bindings/pinctrl/realtek,rtd1315e-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/realtek,rtd1315e-pinctrl.yaml
new file mode 100644
index 000000000000..fc6c65fea73b
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/realtek,rtd1315e-pinctrl.yaml
@@ -0,0 +1,188 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2023 Realtek Semiconductor Corporation
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/realtek,rtd1315e-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek DHC RTD1315E Pin Controller
+
+maintainers:
+ - TY Chang <tychang@realtek.com>
+
+description:
+ The Realtek DHC RTD1315E is a high-definition media processor SoC. The
+ RTD1315E pin controller is used to control pin function, pull up/down
+ resistor, drive strength, schmitt trigger and power source.
+
+properties:
+ compatible:
+ const: realtek,rtd1315e-pinctrl
+
+ reg:
+ maxItems: 1
+
+patternProperties:
+ '-pins$':
+ type: object
+ allOf:
+ - $ref: pincfg-node.yaml#
+ - $ref: pinmux-node.yaml#
+
+ properties:
+ pins:
+ items:
+ enum: [ gpio_0, gpio_1, emmc_rst_n, emmc_dd_sb, emmc_clk, emmc_cmd,
+ gpio_6, gpio_7, gpio_8, gpio_9, gpio_10, gpio_11, gpio_12,
+ gpio_13, gpio_14, gpio_15, gpio_16, gpio_17, gpio_18, gpio_19,
+ gpio_20, emmc_data_0, emmc_data_1, emmc_data_2, usb_cc2, gpio_25,
+ gpio_26, gpio_27, gpio_28, gpio_29, gpio_30, gpio_31, gpio_32,
+ gpio_33, gpio_34, gpio_35, hif_data, hif_en, hif_rdy, hif_clk,
+ gpio_dummy_40, gpio_dummy_41, gpio_dummy_42, gpio_dummy_43,
+ gpio_dummy_44, gpio_dummy_45, gpio_46, gpio_47, gpio_48, gpio_49,
+ gpio_50, usb_cc1, emmc_data_3, emmc_data_4, ir_rx, ur0_rx, ur0_tx,
+ gpio_57, gpio_58, gpio_59, gpio_60, gpio_61, gpio_62, gpio_dummy_63,
+ gpio_dummy_64, gpio_dummy_65, gpio_66, gpio_67, gpio_68, gpio_69,
+ gpio_70, gpio_71, gpio_72, gpio_dummy_73, emmc_data_5, emmc_data_6,
+ emmc_data_7, gpio_dummy_77, gpio_78, gpio_79, gpio_80, gpio_81,
+ ur2_loc, gspi_loc, hi_width, sf_en, arm_trace_dbg_en,
+ ejtag_aucpu_loc, ejtag_acpu_loc, ejtag_vcpu_loc, ejtag_scpu_loc,
+ dmic_loc, vtc_dmic_loc, vtc_tdm_loc, vtc_i2si_loc, tdm_ai_loc,
+ ai_loc, spdif_loc, hif_en_loc, scan_switch, wd_rset, boot_sel,
+ reset_n, testmode ]
+
+ function:
+ enum: [ gpio, nf, emmc, ao, gspi_loc0, gspi_loc1, uart0, uart1,
+ uart2_loc0, uart2_loc1, i2c0, i2c1, i2c4, i2c5, pcie1,
+ etn_led, etn_phy, spi, pwm0_loc0, pwm0_loc1, pwm1_loc0,
+ pwm1_loc1, pwm2_loc0, pwm2_loc1, pwm3_loc0, pwm3_loc1,
+ spdif_optical_loc0, spdif_optical_loc1, usb_cc1, usb_cc2,
+ sd, dmic_loc0, dmic_loc1, ai_loc0, ai_loc1, tdm_ai_loc0,
+ tdm_ai_loc1, hi_loc0, hi_m, vtc_i2so, vtc_i2si_loc0,
+ vtc_i2si_loc1, vtc_dmic_loc0, vtc_dmic_loc1, vtc_tdm_loc0,
+ vtc_tdm_loc1, dc_fan, pll_test_loc0, pll_test_loc1,
+ ir_rx, uart2_disable, gspi_disable, hi_width_disable,
+ hi_width_1bit, sf_disable, sf_enable, scpu_ejtag_loc0,
+ scpu_ejtag_loc1, scpu_ejtag_loc2, scpu_ejtag_loc3,
+ acpu_ejtag_loc0, acpu_ejtag_loc1, acpu_ejtag_loc2,
+ vcpu_ejtag_loc0, vcpu_ejtag_loc1, vcpu_ejtag_loc2,
+ aucpu_ejtag_loc0, aucpu_ejtag_loc1, aucpu_ejtag_loc2,
+ gpu_ejtag, iso_tristate, dbg_out0, dbg_out1, standby_dbg,
+ spdif, arm_trace_debug_disable, arm_trace_debug_enable,
+ aucpu_ejtag_disable, acpu_ejtag_disable, vcpu_ejtag_disable,
+ scpu_ejtag_disable, vtc_dmic_loc_disable, vtc_tdm_disable,
+ vtc_i2si_disable, tdm_ai_disable, ai_disable, spdif_disable,
+ hif_disable, hif_enable, test_loop, pmic_pwrup ]
+
+ drive-strength:
+ enum: [4, 8]
+
+ bias-pull-down: true
+
+ bias-pull-up: true
+
+ bias-disable: true
+
+ input-schmitt-enable: true
+
+ input-schmitt-disable: true
+
+ drive-push-pull: true
+
+ power-source:
+ description: |
+ Valid arguments are described as below:
+ 0: power supply of 1.8V
+ 1: power supply of 3.3V
+ enum: [0, 1]
+
+ realtek,drive-strength-p:
+ description: |
+ Some of pins can be driven using the P-MOS and N-MOS transistor to
+ achieve finer adjustments. The block-diagram representation is as
+ follows:
+ VDD
+ |
+ ||--+
+ +-----o|| P-MOS-FET
+ | ||--+
+ IN --+ +----- out
+ | ||--+
+ +------|| N-MOS-FET
+ ||--+
+ |
+ GND
+ The driving strength of the P-MOS/N-MOS transistors impacts the
+ waveform's rise/fall times. Greater driving strength results in
+ shorter rise/fall times. Each P-MOS and N-MOS transistor offers
+ 8 configurable levels (0 to 7), with higher values indicating
+ greater driving strength, contributing to achieving the desired
+ speed.
+
+ The realtek,drive-strength-p is used to control the driving strength
+ of the P-MOS output.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+
+ realtek,drive-strength-n:
+ description: |
+ Similar to the realtek,drive-strength-p, the realtek,drive-strength-n
+ is used to control the driving strength of the N-MOS output.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+
+ realtek,duty-cycle:
+ description: |
+ An integer describing the level to adjust output duty cycle, controlling
+ the proportion of positive and negative waveforms in nanoseconds.
+ Valid arguments are described as below:
+ 0: 0ns
+ 2: + 0.25ns
+ 3: + 0.5ns
+ 4: -0.25ns
+ 5: -0.5ns
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 2, 3, 4, 5 ]
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ pinctrl@4e000 {
+ compatible = "realtek,rtd1315e-pinctrl";
+ reg = <0x4e000 0x130>;
+
+ emmc-hs200-pins {
+ pins = "emmc_clk",
+ "emmc_cmd",
+ "emmc_data_0",
+ "emmc_data_1",
+ "emmc_data_2",
+ "emmc_data_3",
+ "emmc_data_4",
+ "emmc_data_5",
+ "emmc_data_6",
+ "emmc_data_7";
+ function = "emmc";
+ realtek,drive-strength-p = <0x2>;
+ realtek,drive-strength-n = <0x2>;
+ };
+
+ i2c-0-pins {
+ pins = "gpio_12",
+ "gpio_13";
+ function = "i2c0";
+ drive-strength = <4>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/realtek,rtd1319d-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/realtek,rtd1319d-pinctrl.yaml
new file mode 100644
index 000000000000..f07361d60acd
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/realtek,rtd1319d-pinctrl.yaml
@@ -0,0 +1,187 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2023 Realtek Semiconductor Corporation
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/realtek,rtd1319d-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek DHC RTD1319D Pin Controller
+
+maintainers:
+ - TY Chang <tychang@realtek.com>
+
+description:
+ The Realtek DHC RTD1319D is a high-definition media processor SoC. The
+ RTD1319D pin controller is used to control pin function, pull up/down
+ resistor, drive strength, schmitt trigger and power source.
+
+properties:
+ compatible:
+ const: realtek,rtd1319d-pinctrl
+
+ reg:
+ maxItems: 1
+
+patternProperties:
+ '-pins$':
+ type: object
+ allOf:
+ - $ref: pincfg-node.yaml#
+ - $ref: pinmux-node.yaml#
+
+ properties:
+ pins:
+ items:
+ enum: [ gpio_0, gpio_1, gpio_2, gpio_3, gpio_4, gpio_5, gpio_6, gpio_7,
+ gpio_8, gpio_9, gpio_10, gpio_11, gpio_12, gpio_13, gpio_14,
+ gpio_15, gpio_16, gpio_17, gpio_18, gpio_19, gpio_20, gpio_21,
+ gpio_22, gpio_23, usb_cc2, gpio_25, gpio_26, gpio_27, gpio_28,
+ gpio_29, gpio_30, gpio_31, gpio_32, gpio_33, gpio_34, gpio_35,
+ hif_data, hif_en, hif_rdy, hif_clk, gpio_40, gpio_41, gpio_42,
+ gpio_43, gpio_44, gpio_45, gpio_46, gpio_47, gpio_48, gpio_49,
+ gpio_50, usb_cc1, gpio_52, gpio_53, ir_rx, ur0_rx, ur0_tx,
+ gpio_57, gpio_58, gpio_59, gpio_60, gpio_61, gpio_62, gpio_63,
+ gpio_64, emmc_rst_n, emmc_dd_sb, emmc_clk, emmc_cmd, emmc_data_0,
+ emmc_data_1, emmc_data_2, emmc_data_3, emmc_data_4, emmc_data_5,
+ emmc_data_6, emmc_data_7, dummy, gpio_78, gpio_79, gpio_80,
+ gpio_81, ur2_loc, gspi_loc, hi_width, sf_en, arm_trace_dbg_en,
+ ejtag_aucpu_loc, ejtag_acpu_loc, ejtag_vcpu_loc, ejtag_scpu_loc,
+ dmic_loc, ejtag_secpu_loc, vtc_dmic_loc, vtc_tdm_loc, vtc_i2si_loc,
+ tdm_ai_loc, ai_loc, spdif_loc, hif_en_loc, sc0_loc, sc1_loc,
+ scan_switch, wd_rset, boot_sel, reset_n, testmode ]
+
+ function:
+ enum: [ gpio, nf, emmc, tp0, tp1, sc0, sc0_data0, sc0_data1, sc0_data2,
+ sc1, sc1_data0, sc1_data1, sc1_data2, ao, gspi_loc0, gspi_loc1,
+ uart0, uart1, uart2_loc0, uart2_loc1, i2c0, i2c1, i2c3, i2c4,
+ i2c5, pcie1, sdio, etn_led, etn_phy, spi, pwm0_loc0, pwm0_loc1,
+ pwm1_loc0, pwm1_loc1, pwm2_loc0, pwm2_loc1, pwm3_loc0, pwm3_loc1,
+ qam_agc_if0, qam_agc_if1, spdif_optical_loc0, spdif_optical_loc1,
+ usb_cc1, usb_cc2, vfd, sd, dmic_loc0, dmic_loc1, ai_loc0, ai_loc1,
+ tdm_ai_loc0, tdm_ai_loc1, hi_loc0, hi_m, vtc_i2so, vtc_i2si_loc0,
+ vtc_i2si_loc1, vtc_dmic_loc0, vtc_dmic_loc1, vtc_tdm_loc0,
+ vtc_tdm_loc1, dc_fan, pll_test_loc0, pll_test_loc1, ir_rx,
+ uart2_disable, gspi_disable, hi_width_disable, hi_width_1bit,
+ sf_disable, sf_enable, scpu_ejtag_loc0, scpu_ejtag_loc1,
+ scpu_ejtag_loc2, acpu_ejtag_loc0, acpu_ejtag_loc1, acpu_ejtag_loc2,
+ vcpu_ejtag_loc0, vcpu_ejtag_loc1, vcpu_ejtag_loc2, secpu_ejtag_loc0,
+ secpu_ejtag_loc1, secpu_ejtag_loc2, aucpu_ejtag_loc0, aucpu_ejtag_loc1,
+ aucpu_ejtag_loc2, iso_tristate, dbg_out0, dbg_out1, standby_dbg,
+ spdif, arm_trace_debug_disable, arm_trace_debug_enable,
+ aucpu_ejtag_disable, acpu_ejtag_disable, vcpu_ejtag_disable,
+ scpu_ejtag_disable, secpu_ejtag_disable, vtc_dmic_loc_disable,
+ vtc_tdm_disable, vtc_i2si_disable, tdm_ai_disable, ai_disable,
+ spdif_disable, hif_disable, hif_enable, test_loop, pmic_pwrup ]
+
+ drive-strength:
+ enum: [4, 8]
+
+ bias-pull-down: true
+
+ bias-pull-up: true
+
+ bias-disable: true
+
+ input-schmitt-enable: true
+
+ input-schmitt-disable: true
+
+ drive-push-pull: true
+
+ power-source:
+ description: |
+ Valid arguments are described as below:
+ 0: power supply of 1.8V
+ 1: power supply of 3.3V
+ enum: [0, 1]
+
+ realtek,drive-strength-p:
+ description: |
+ Some of pins can be driven using the P-MOS and N-MOS transistor to
+ achieve finer adjustments. The block-diagram representation is as
+ follows:
+ VDD
+ |
+ ||--+
+ +-----o|| P-MOS-FET
+ | ||--+
+ IN --+ +----- out
+ | ||--+
+ +------|| N-MOS-FET
+ ||--+
+ |
+ GND
+ The driving strength of the P-MOS/N-MOS transistors impacts the
+ waveform's rise/fall times. Greater driving strength results in
+ shorter rise/fall times. Each P-MOS and N-MOS transistor offers
+ 8 configurable levels (0 to 7), with higher values indicating
+ greater driving strength, contributing to achieving the desired
+ speed.
+
+ The realtek,drive-strength-p is used to control the driving strength
+ of the P-MOS output.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+
+ realtek,drive-strength-n:
+ description: |
+ Similar to the realtek,drive-strength-p, the realtek,drive-strength-n
+ is used to control the driving strength of the N-MOS output.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+
+ realtek,duty-cycle:
+ description: |
+ An integer describing the level to adjust output duty cycle, controlling
+ the proportion of positive and negative waveforms in nanoseconds.
+ Valid arguments are described as below:
+ 0: 0ns
+ 2: + 0.25ns
+ 3: + 0.5ns
+ 4: -0.25ns
+ 5: -0.5ns
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 2, 3, 4, 5 ]
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ pinctrl@4e000 {
+ compatible = "realtek,rtd1319d-pinctrl";
+ reg = <0x4e000 0x130>;
+
+ emmc-hs200-pins {
+ pins = "emmc_clk",
+ "emmc_cmd",
+ "emmc_data_0",
+ "emmc_data_1",
+ "emmc_data_2",
+ "emmc_data_3",
+ "emmc_data_4",
+ "emmc_data_5",
+ "emmc_data_6",
+ "emmc_data_7";
+ function = "emmc";
+ realtek,drive-strength-p = <0x2>;
+ realtek,drive-strength-n = <0x2>;
+ };
+
+ i2c-0-pins {
+ pins = "gpio_12",
+ "gpio_13";
+ function = "i2c0";
+ drive-strength = <4>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/realtek,rtd1619b-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/realtek,rtd1619b-pinctrl.yaml
new file mode 100644
index 000000000000..671e4ec84624
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/realtek,rtd1619b-pinctrl.yaml
@@ -0,0 +1,186 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2023 Realtek Semiconductor Corporation
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/realtek,rtd1619b-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek DHC RTD1619B Pin Controller
+
+maintainers:
+ - TY Chang <tychang@realtek.com>
+
+description:
+ The Realtek DHC RTD1619B is a high-definition media processor SoC. The
+ RTD1619B pin controller is used to control pin function, pull up/down
+ resistor, drive strength, schmitt trigger and power source.
+
+properties:
+ compatible:
+ const: realtek,rtd1619b-pinctrl
+
+ reg:
+ maxItems: 1
+
+patternProperties:
+ '-pins$':
+ type: object
+ allOf:
+ - $ref: pincfg-node.yaml#
+ - $ref: pinmux-node.yaml#
+
+ properties:
+ pins:
+ items:
+ enum: [ gpio_0, gpio_1, gpio_2, gpio_3, gpio_4, gpio_5, gpio_6, gpio_7,
+ gpio_8, gpio_9, gpio_10, gpio_11, gpio_12, gpio_13, gpio_14,
+ gpio_15, gpio_16, gpio_17, gpio_18, gpio_19, gpio_20, gpio_21,
+ gpio_22, gpio_23, usb_cc2, gpio_25, gpio_26, gpio_27, gpio_28,
+ gpio_29, gpio_30, gpio_31, gpio_32, gpio_33, gpio_34, gpio_35,
+ hif_data, hif_en, hif_rdy, hif_clk, gpio_40, gpio_41, gpio_42,
+ gpio_43, gpio_44, gpio_45, gpio_46, gpio_47, gpio_48, gpio_49,
+ gpio_50, usb_cc1, gpio_52, gpio_53, ir_rx, ur0_rx, ur0_tx,
+ gpio_57, gpio_58, gpio_59, gpio_60, gpio_61, gpio_62, gpio_63,
+ gpio_64, gpio_65, gpio_66, gpio_67, gpio_68, gpio_69, gpio_70,
+ gpio_71, gpio_72, gpio_73, gpio_74, gpio_75, gpio_76, emmc_cmd,
+ spi_ce_n, spi_sck, spi_so, spi_si, emmc_rst_n, emmc_dd_sb,
+ emmc_clk, emmc_data_0, emmc_data_1, emmc_data_2, emmc_data_3,
+ emmc_data_4, emmc_data_5, emmc_data_6, emmc_data_7, ur2_loc,
+ gspi_loc, sdio_loc, hi_loc, hi_width, sf_en, arm_trace_dbg_en,
+ pwm_01_open_drain_en_loc0, pwm_23_open_drain_en_loc0,
+ pwm_01_open_drain_en_loc1, pwm_23_open_drain_en_loc1,
+ ejtag_acpu_loc, ejtag_vcpu_loc, ejtag_scpu_loc, dmic_loc,
+ iso_gspi_loc, ejtag_ve3_loc, ejtag_aucpu0_loc, ejtag_aucpu1_loc ]
+
+ function:
+ enum: [ gpio, nf, nf_spi, spi, pmic, spdif, spdif_coaxial, spdif_optical_loc0,
+ spdif_optical_loc1, emmc_spi, emmc, sc1, uart0, uart1, uart2_loc0, uart2_loc1,
+ gspi_loc1, iso_gspi_loc1, i2c0, i2c1, i2c3, i2c4, i2c5, pwm0, pwm1, pwm2,
+ pwm3, etn_led, etn_phy, etn_clk, sc0, vfd, gspi_loc0, iso_gspi_loc0, pcie1,
+ pcie2, sd, sdio_loc0, sdio_loc1, hi, hi_m, dc_fan, pll_test_loc0, pll_test_loc1,
+ usb_cc1, usb_cc2, ir_rx, tdm_ai_loc0, tdm_ai_loc1, dmic_loc0, dmic_loc1,
+ ai_loc0, ai_loc1, tp0, tp1, ao, uart2_disable, gspi_disable, sdio_disable,
+ hi_loc_disable, hi_loc0, hi_width_disable, hi_width_1bit, vtc_i2si_loc0,
+ vtc_tdm_loc0, vtc_dmic_loc0, vtc_i2si_loc1, vtc_tdm_loc1, vtc_dmic_loc1,
+ vtc_i2so, ve3_ejtag_loc0, aucpu0_ejtag_loc0, aucpu1_ejtag_loc0, ve3_ejtag_loc1,
+ aucpu0_ejtag_loc1, aucpu1_ejtag_loc1, ve3_ejtag_loc2, aucpu0_ejtag_loc2,
+ aucpu1_ejtag_loc2, scpu_ejtag_loc0, acpu_ejtag_loc0, vcpu_ejtag_loc0,
+ scpu_ejtag_loc1, acpu_ejtag_loc1, vcpu_ejtag_loc1, scpu_ejtag_loc2,
+ acpu_ejtag_loc2, vcpu_ejtag_loc2, ve3_ejtag_disable, aucpu0_ejtag_disable,
+ aucpu1_ejtag_disable, acpu_ejtag_disable, vcpu_ejtag_disable,
+ scpu_ejtag_disable, iso_gspi_disable, sf_disable, sf_enable,
+ arm_trace_debug_disable, arm_trace_debug_enable, pwm_normal, pwm_open_drain,
+ standby_dbg, test_loop_dis ]
+
+ drive-strength:
+ enum: [4, 8]
+
+ bias-pull-down: true
+
+ bias-pull-up: true
+
+ bias-disable: true
+
+ input-schmitt-enable: true
+
+ input-schmitt-disable: true
+
+ drive-push-pull: true
+
+ power-source:
+ description: |
+ Valid arguments are described as below:
+ 0: power supply of 1.8V
+ 1: power supply of 3.3V
+ enum: [0, 1]
+
+ realtek,drive-strength-p:
+ description: |
+ Some of pins can be driven using the P-MOS and N-MOS transistor to
+ achieve finer adjustments. The block-diagram representation is as
+ follows:
+ VDD
+ |
+ ||--+
+ +-----o|| P-MOS-FET
+ | ||--+
+ IN --+ +----- out
+ | ||--+
+ +------|| N-MOS-FET
+ ||--+
+ |
+ GND
+ The driving strength of the P-MOS/N-MOS transistors impacts the
+ waveform's rise/fall times. Greater driving strength results in
+ shorter rise/fall times. Each P-MOS and N-MOS transistor offers
+ 8 configurable levels (0 to 7), with higher values indicating
+ greater driving strength, contributing to achieving the desired
+ speed.
+
+ The realtek,drive-strength-p is used to control the driving strength
+ of the P-MOS output.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+
+ realtek,drive-strength-n:
+ description: |
+ Similar to the realtek,drive-strength-p, the realtek,drive-strength-n
+ is used to control the driving strength of the N-MOS output.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+
+ realtek,duty-cycle:
+ description: |
+ An integer describing the level to adjust output duty cycle, controlling
+ the proportion of positive and negative waveforms in nanoseconds.
+ Valid arguments are described as below:
+ 0: 0ns
+ 2: + 0.25ns
+ 3: + 0.5ns
+ 4: -0.25ns
+ 5: -0.5ns
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 2, 3, 4, 5 ]
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ pinctrl@4e000 {
+ compatible = "realtek,rtd1619b-pinctrl";
+ reg = <0x4e000 0x130>;
+
+ emmc-hs200-pins {
+ pins = "emmc_clk",
+ "emmc_cmd",
+ "emmc_data_0",
+ "emmc_data_1",
+ "emmc_data_2",
+ "emmc_data_3",
+ "emmc_data_4",
+ "emmc_data_5",
+ "emmc_data_6",
+ "emmc_data_7";
+ function = "emmc";
+ realtek,drive-strength-p = <0x2>;
+ realtek,drive-strength-n = <0x2>;
+ };
+
+ i2c-0-pins {
+ pins = "gpio_12",
+ "gpio_13";
+ function = "i2c0";
+ drive-strength = <4>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
index 145c5442f268..b5ca40d0e251 100644
--- a/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
@@ -25,6 +25,7 @@ properties:
- enum:
- renesas,r9a07g043-pinctrl # RZ/G2UL{Type-1,Type-2} and RZ/Five
- renesas,r9a07g044-pinctrl # RZ/G2{L,LC}
+ - renesas,r9a08g045-pinctrl # RZ/G3S
- items:
- enum:
@@ -73,10 +74,26 @@ properties:
additionalProperties:
anyOf:
- type: object
+ additionalProperties: false
allOf:
- $ref: pincfg-node.yaml#
- $ref: pinmux-node.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - renesas,r9a08g045-pinctrl
+ then:
+ properties:
+ drive-strength: false
+ output-impedance-ohms: false
+ slew-rate: false
+ else:
+ properties:
+ drive-strength-microamp: false
+
description:
Pin controller client devices use pin configuration subnodes (children
and grandchildren) for desired pin configuration.
@@ -91,6 +108,10 @@ additionalProperties:
pins: true
drive-strength:
enum: [ 2, 4, 8, 12 ]
+ drive-strength-microamp:
+ enum: [ 1900, 2200, 4000, 4400, 4500, 4700, 5200, 5300, 5700,
+ 5800, 6000, 6050, 6100, 6550, 6800, 7000, 8000, 9000,
+ 10000 ]
output-impedance-ohms:
enum: [ 33, 50, 66, 100 ]
power-source:
diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,rzv2m-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/renesas,rzv2m-pinctrl.yaml
index cb81a17bd0b1..5fa5d31f8866 100644
--- a/Documentation/devicetree/bindings/pinctrl/renesas,rzv2m-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/renesas,rzv2m-pinctrl.yaml
@@ -53,6 +53,7 @@ properties:
additionalProperties:
anyOf:
- type: object
+ additionalProperties: false
allOf:
- $ref: pincfg-node.yaml#
- $ref: pinmux-node.yaml#
diff --git a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml
index 10c335efe619..20e806dce1ec 100644
--- a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml
@@ -115,6 +115,8 @@ additionalProperties:
type: object
additionalProperties:
type: object
+ additionalProperties: false
+
properties:
rockchip,pins:
$ref: /schemas/types.yaml#/definitions/uint32-matrix
diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
index 2120ef71a78d..e1eb45a9eda4 100644
--- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
@@ -48,7 +48,8 @@ properties:
description: Phandle+args to the syscon node which includes IRQ mux selection.
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- - items:
+ - minItems: 2
+ items:
- description: syscon node which includes IRQ mux selection
- description: The offset of the IRQ mux selection register
- description: The field mask of IRQ mux, needed if different of 0xf
diff --git a/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml b/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml
index d80bbedfe3aa..dab3d92bc273 100644
--- a/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml
+++ b/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml
@@ -12,7 +12,7 @@ maintainers:
- Jianxin Pan <jianxin.pan@amlogic.com>
description: |+
- Secure Power Domains used in Meson A1/C1/S4 & C3 SoCs, and should be the child node
+ Secure Power Domains used in Meson A1/C1/S4 & C3/T7 SoCs, and should be the child node
of secure-monitor.
properties:
@@ -21,6 +21,7 @@ properties:
- amlogic,meson-a1-pwrc
- amlogic,meson-s4-pwrc
- amlogic,c3-pwrc
+ - amlogic,t7-pwrc
"#power-domain-cells":
const: 1
diff --git a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
index c9acef80f452..8985e2df8a56 100644
--- a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
+++ b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
@@ -31,6 +31,7 @@ properties:
- mediatek,mt8188-power-controller
- mediatek,mt8192-power-controller
- mediatek,mt8195-power-controller
+ - mediatek,mt8365-power-controller
'#power-domain-cells':
const: 1
@@ -88,6 +89,7 @@ $defs:
"include/dt-bindings/power/mediatek,mt8188-power.h" - for MT8188 type power domain.
"include/dt-bindings/power/mt8192-power.h" - for MT8192 type power domain.
"include/dt-bindings/power/mt8195-power.h" - for MT8195 type power domain.
+ "include/dt-bindings/power/mediatek,mt8365-power.h" - for MT8365 type power domain.
maxItems: 1
clocks:
@@ -115,6 +117,10 @@ $defs:
$ref: /schemas/types.yaml#/definitions/phandle
description: phandle to the device containing the INFRACFG register range.
+ mediatek,infracfg-nao:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle to the device containing the INFRACFG-NAO register range.
+
mediatek,smi:
$ref: /schemas/types.yaml#/definitions/phandle
description: phandle to the device containing the SMI register range.
diff --git a/Documentation/devicetree/bindings/power/power-domain.yaml b/Documentation/devicetree/bindings/power/power-domain.yaml
index d1235e562041..8fdb529d560b 100644
--- a/Documentation/devicetree/bindings/power/power-domain.yaml
+++ b/Documentation/devicetree/bindings/power/power-domain.yaml
@@ -13,8 +13,9 @@ maintainers:
description: |+
System on chip designs are often divided into multiple PM domains that can be
- used for power gating of selected IP blocks for power saving by reduced leakage
- current.
+ used for power gating of selected IP blocks for power saving by reduced
+ leakage current. Moreover, in some cases the similar PM domains may also be
+ capable of scaling performance for a group of IP blocks.
This device tree binding can be used to bind PM domain consumer devices with
their PM domains provided by PM domain providers. A PM domain provider can be
@@ -25,7 +26,7 @@ description: |+
properties:
$nodename:
- pattern: "^(power-controller|power-domain)([@-].*)?$"
+ pattern: "^(power-controller|power-domain|performance-domain)([@-].*)?$"
domain-idle-states:
$ref: /schemas/types.yaml#/definitions/phandle-array
@@ -44,11 +45,11 @@ properties:
operating-points-v2:
description:
- Phandles to the OPP tables of power domains provided by a power domain
- provider. If the provider provides a single power domain only or all
- the power domains provided by the provider have identical OPP tables,
- then this shall contain a single phandle. Refer to ../opp/opp-v2-base.yaml
- for more information.
+ Phandles to the OPP tables of power domains that are capable of scaling
+ performance, provided by a power domain provider. If the provider provides
+ a single power domain only or all the power domains provided by the
+ provider have identical OPP tables, then this shall contain a single
+ phandle. Refer to ../opp/opp-v2-base.yaml for more information.
"#power-domain-cells":
description:
diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
index 9b03c41d3604..da9c5846f4e1 100644
--- a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
+++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
@@ -15,42 +15,52 @@ description:
properties:
compatible:
- enum:
- - qcom,mdm9607-rpmpd
- - qcom,msm8226-rpmpd
- - qcom,msm8909-rpmpd
- - qcom,msm8916-rpmpd
- - qcom,msm8939-rpmpd
- - qcom,msm8953-rpmpd
- - qcom,msm8976-rpmpd
- - qcom,msm8994-rpmpd
- - qcom,msm8996-rpmpd
- - qcom,msm8998-rpmpd
- - qcom,qcm2290-rpmpd
- - qcom,qcs404-rpmpd
- - qcom,qdu1000-rpmhpd
- - qcom,sa8155p-rpmhpd
- - qcom,sa8540p-rpmhpd
- - qcom,sa8775p-rpmhpd
- - qcom,sdm660-rpmpd
- - qcom,sc7180-rpmhpd
- - qcom,sc7280-rpmhpd
- - qcom,sc8180x-rpmhpd
- - qcom,sc8280xp-rpmhpd
- - qcom,sdm670-rpmhpd
- - qcom,sdm845-rpmhpd
- - qcom,sdx55-rpmhpd
- - qcom,sdx65-rpmhpd
- - qcom,sdx75-rpmhpd
- - qcom,sm6115-rpmpd
- - qcom,sm6125-rpmpd
- - qcom,sm6350-rpmhpd
- - qcom,sm6375-rpmpd
- - qcom,sm8150-rpmhpd
- - qcom,sm8250-rpmhpd
- - qcom,sm8350-rpmhpd
- - qcom,sm8450-rpmhpd
- - qcom,sm8550-rpmhpd
+ oneOf:
+ - enum:
+ - qcom,mdm9607-rpmpd
+ - qcom,msm8226-rpmpd
+ - qcom,msm8909-rpmpd
+ - qcom,msm8916-rpmpd
+ - qcom,msm8917-rpmpd
+ - qcom,msm8939-rpmpd
+ - qcom,msm8953-rpmpd
+ - qcom,msm8976-rpmpd
+ - qcom,msm8994-rpmpd
+ - qcom,msm8996-rpmpd
+ - qcom,msm8998-rpmpd
+ - qcom,qcm2290-rpmpd
+ - qcom,qcs404-rpmpd
+ - qcom,qdu1000-rpmhpd
+ - qcom,qm215-rpmpd
+ - qcom,sa8155p-rpmhpd
+ - qcom,sa8540p-rpmhpd
+ - qcom,sa8775p-rpmhpd
+ - qcom,sc7180-rpmhpd
+ - qcom,sc7280-rpmhpd
+ - qcom,sc8180x-rpmhpd
+ - qcom,sc8280xp-rpmhpd
+ - qcom,sc8380xp-rpmhpd
+ - qcom,sdm660-rpmpd
+ - qcom,sdm670-rpmhpd
+ - qcom,sdm845-rpmhpd
+ - qcom,sdx55-rpmhpd
+ - qcom,sdx65-rpmhpd
+ - qcom,sdx75-rpmhpd
+ - qcom,sm6115-rpmpd
+ - qcom,sm6125-rpmpd
+ - qcom,sm6350-rpmhpd
+ - qcom,sm6375-rpmpd
+ - qcom,sm7150-rpmhpd
+ - qcom,sm8150-rpmhpd
+ - qcom,sm8250-rpmhpd
+ - qcom,sm8350-rpmhpd
+ - qcom,sm8450-rpmhpd
+ - qcom,sm8550-rpmhpd
+ - qcom,sm8650-rpmhpd
+ - items:
+ - enum:
+ - qcom,msm8937-rpmpd
+ - const: qcom,msm8917-rpmpd
'#power-domain-cells':
const: 1
diff --git a/Documentation/devicetree/bindings/power/reset/gpio-poweroff.yaml b/Documentation/devicetree/bindings/power/reset/gpio-poweroff.yaml
index b54ec003a1e0..a4b437fce37c 100644
--- a/Documentation/devicetree/bindings/power/reset/gpio-poweroff.yaml
+++ b/Documentation/devicetree/bindings/power/reset/gpio-poweroff.yaml
@@ -18,6 +18,9 @@ description: >
Finally the operating system assumes the power off failed if
the system is still running after waiting some time (timeout-ms).
+allOf:
+ - $ref: restart-handler.yaml#
+
properties:
compatible:
const: gpio-poweroff
@@ -40,6 +43,9 @@ properties:
default: 100
description: Delay to wait after driving gpio inactive
+ priority:
+ default: 0
+
timeout-ms:
default: 3000
description: Time to wait before assuming the power off sequence failed.
diff --git a/Documentation/devicetree/bindings/power/reset/syscon-poweroff.yaml b/Documentation/devicetree/bindings/power/reset/syscon-poweroff.yaml
index 3412fe7e1e80..d342b113fca2 100644
--- a/Documentation/devicetree/bindings/power/reset/syscon-poweroff.yaml
+++ b/Documentation/devicetree/bindings/power/reset/syscon-poweroff.yaml
@@ -15,6 +15,9 @@ description: |+
defined by the register map pointed by syscon reference plus the offset
with the value and mask defined in the poweroff node.
Default will be little endian mode, 32 bit access only.
+ The SYSCON register map is normally retrieved from the parental dt-node. So
+ the SYSCON poweroff node should be represented as a sub-node of a "syscon",
+ "simple-mfd" node.
properties:
compatible:
@@ -30,7 +33,10 @@ properties:
regmap:
$ref: /schemas/types.yaml#/definitions/phandle
- description: Phandle to the register map node.
+ deprecated: true
+ description:
+ Phandle to the register map node. This property is deprecated in favor of
+ the syscon-poweroff node being a child of a system controller node.
value:
$ref: /schemas/types.yaml#/definitions/uint32
@@ -38,7 +44,6 @@ properties:
required:
- compatible
- - regmap
- offset
additionalProperties: false
@@ -56,7 +61,6 @@ examples:
- |
poweroff {
compatible = "syscon-poweroff";
- regmap = <&regmapnode>;
offset = <0x0>;
mask = <0x7a>;
};
diff --git a/Documentation/devicetree/bindings/power/supply/max8925_battery.txt b/Documentation/devicetree/bindings/power/supply/max8925_battery.txt
deleted file mode 100644
index d7e3e0c0f71d..000000000000
--- a/Documentation/devicetree/bindings/power/supply/max8925_battery.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-max8925-battery bindings
-~~~~~~~~~~~~~~~~
-
-Optional properties :
- - batt-detect: whether support battery detect
- - topoff-threshold: set charging current in topoff mode
- - fast-charge: set charging current in fast mode
- - no-temp-support: whether support temperature protection detect
- - no-insert-detect: whether support insert detect
-
-Example:
- charger {
- batt-detect = <0>;
- topoff-threshold = <1>;
- fast-charge = <7>;
- no-temp-support = <0>;
- no-insert-detect = <0>;
- };
diff --git a/Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml b/Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml
index 2627cd3eed83..377cbb2c2c1f 100644
--- a/Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml
+++ b/Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml
@@ -55,6 +55,14 @@ properties:
interrupts:
maxItems: 1
+ io-channels:
+ items:
+ - description: battery temperature
+
+ io-channel-names:
+ items:
+ - const: temp
+
wakeup-source:
type: boolean
description: |
@@ -95,3 +103,26 @@ examples:
wakeup-source;
};
};
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fuel-gauge@36 {
+ compatible = "maxim,max17043";
+ reg = <0x36>;
+
+ interrupt-parent = <&gpio>;
+ interrupts = <144 IRQ_TYPE_EDGE_FALLING>;
+
+ monitored-battery = <&battery>;
+ power-supplies = <&charger>;
+
+ io-channels = <&adc 8>;
+ io-channel-names = "temp";
+
+ maxim,alert-low-soc-level = <10>;
+ wakeup-source;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/power/supply/mitsumi,mm8013.yaml b/Documentation/devicetree/bindings/power/supply/mitsumi,mm8013.yaml
new file mode 100644
index 000000000000..6865640cbdfa
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/mitsumi,mm8013.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/supply/mitsumi,mm8013.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mitsumi MM8013 fuel gauge
+
+maintainers:
+ - Konrad Dybcio <konradybcio@kernel.org>
+
+allOf:
+ - $ref: power-supply.yaml#
+
+properties:
+ compatible:
+ const: mitsumi,mm8013
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fuel-gauge@55 {
+ compatible = "mitsumi,mm8013";
+ reg = <0x55>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/power/supply/qcom,pm8916-bms-vm.yaml b/Documentation/devicetree/bindings/power/supply/qcom,pm8916-bms-vm.yaml
new file mode 100644
index 000000000000..ad764e69ab57
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/qcom,pm8916-bms-vm.yaml
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/supply/qcom,pm8916-bms-vm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Voltage Mode BMS
+
+maintainers:
+ - Nikita Travkin <nikita@trvn.ru>
+
+description:
+ Voltage Mode BMS is a hardware block found in some Qualcomm PMICs
+ such as pm8916. This block performs battery voltage monitoring.
+
+allOf:
+ - $ref: power-supply.yaml#
+
+properties:
+ compatible:
+ const: qcom,pm8916-bms-vm
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: BMS FSM left S3 mode
+ - description: BMS FSM entered S2 mode
+ - description: OCV measured in S3 mode
+ - description: OCV below threshold
+ - description: FIFO update done
+ - description: BMS FSM switched state
+
+ interrupt-names:
+ items:
+ - const: cv_leave
+ - const: cv_enter
+ - const: ocv_good
+ - const: ocv_thr
+ - const: fifo
+ - const: state_chg
+
+ monitored-battery: true
+
+ power-supplies: true
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-names
+ - monitored-battery
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ pmic {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ battery@4000 {
+ compatible = "qcom,pm8916-bms-vm";
+ reg = <0x4000>;
+ interrupts = <0x0 0x40 0 IRQ_TYPE_EDGE_RISING>,
+ <0x0 0x40 1 IRQ_TYPE_EDGE_RISING>,
+ <0x0 0x40 2 IRQ_TYPE_EDGE_RISING>,
+ <0x0 0x40 3 IRQ_TYPE_EDGE_RISING>,
+ <0x0 0x40 4 IRQ_TYPE_EDGE_RISING>,
+ <0x0 0x40 5 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "cv_leave",
+ "cv_enter",
+ "ocv_good",
+ "ocv_thr",
+ "fifo",
+ "state_chg";
+
+ monitored-battery = <&battery>;
+ power-supplies = <&pm8916_charger>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/power/supply/qcom,pm8916-lbc.yaml b/Documentation/devicetree/bindings/power/supply/qcom,pm8916-lbc.yaml
new file mode 100644
index 000000000000..cdf14e5ed119
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/qcom,pm8916-lbc.yaml
@@ -0,0 +1,128 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/supply/qcom,pm8916-lbc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Linear Battery Charger
+
+maintainers:
+ - Nikita Travkin <nikita@trvn.ru>
+
+description:
+ Linear Battery Charger hardware block, found in some Qualcomm PMICs
+ such as pm8916. Implements a simple, autonomous CC/CV charger.
+
+allOf:
+ - $ref: power-supply.yaml#
+
+properties:
+ compatible:
+ const: qcom,pm8916-lbc
+
+ reg:
+ items:
+ - description: Charger
+ - description: Battery
+ - description: USB
+ - description: MISC
+
+ reg-names:
+ items:
+ - const: chgr
+ - const: bat_if
+ - const: usb
+ - const: misc
+
+ interrupts:
+ items:
+ - description: Battery detection
+ - description: Fast charging
+ - description: Charging failed
+ - description: Charging done
+ - description: Battery present
+ - description: Battery temperature OK
+ - description: USB coarse detection
+ - description: USB IN valid
+ - description: Charger gone
+ - description: Overtemperature
+
+ interrupt-names:
+ items:
+ - const: vbat_det
+ - const: fast_chg
+ - const: chg_fail
+ - const: chg_done
+ - const: bat_pres
+ - const: temp_ok
+ - const: coarse_det
+ - const: usb_vbus
+ - const: chg_gone
+ - const: overtemp
+
+ qcom,fast-charge-safe-voltage:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 4000000
+ maximum: 4775000
+ description:
+ Maximum safe battery voltage in uV; May be pre-set by bootloader,
+ in which case, setting this will harmlessly fail.
+
+ qcom,fast-charge-safe-current:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 90000
+ maximum: 1440000
+ description:
+ Maximum safe battery charge current in uA; May be pre-set by
+ bootloader, in which case setting this will harmlessly fail.
+
+ monitored-battery: true
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-names
+ - qcom,fast-charge-safe-voltage
+ - qcom,fast-charge-safe-current
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ pmic {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ charger@1000 {
+ compatible = "qcom,pm8916-lbc";
+ reg = <0x1000>, <0x1200>, <0x1300>, <0x1600>;
+ reg-names = "chgr", "bat_if", "usb", "misc";
+
+ interrupts = <0x0 0x10 0 IRQ_TYPE_EDGE_BOTH>,
+ <0x0 0x10 5 IRQ_TYPE_EDGE_BOTH>,
+ <0x0 0x10 6 IRQ_TYPE_EDGE_BOTH>,
+ <0x0 0x10 7 IRQ_TYPE_EDGE_BOTH>,
+ <0x0 0x12 0 IRQ_TYPE_EDGE_BOTH>,
+ <0x0 0x12 1 IRQ_TYPE_EDGE_BOTH>,
+ <0x0 0x13 0 IRQ_TYPE_EDGE_BOTH>,
+ <0x0 0x13 1 IRQ_TYPE_EDGE_BOTH>,
+ <0x0 0x13 2 IRQ_TYPE_EDGE_BOTH>,
+ <0x0 0x13 4 IRQ_TYPE_EDGE_BOTH>;
+ interrupt-names = "vbat_det",
+ "fast_chg",
+ "chg_fail",
+ "chg_done",
+ "bat_pres",
+ "temp_ok",
+ "coarse_det",
+ "usb_vbus",
+ "chg_gone",
+ "overtemp";
+ monitored-battery = <&battery>;
+
+ qcom,fast-charge-safe-current = <900000>;
+ qcom,fast-charge-safe-voltage = <4300000>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/power/supply/sbs,sbs-manager.yaml b/Documentation/devicetree/bindings/power/supply/sbs,sbs-manager.yaml
index f255f3858d08..2e21846463ba 100644
--- a/Documentation/devicetree/bindings/power/supply/sbs,sbs-manager.yaml
+++ b/Documentation/devicetree/bindings/power/supply/sbs,sbs-manager.yaml
@@ -47,6 +47,12 @@ patternProperties:
"^i2c@[1-4]$":
type: object
$ref: /schemas/i2c/i2c-controller.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ minimum: 1
+ maximum: 4
examples:
- |
diff --git a/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-battery.txt b/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-battery.txt
deleted file mode 100644
index ee125cb0e46d..000000000000
--- a/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-battery.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-AB85000 PMIC contains a node, which contains shared
-information about the battery connected to the PMIC.
-The node has no compatible property.
-
-Properties of this node are:
-
-thermistor-on-batctrl:
- A boolean value indicating thermistor interface to battery
-
- Note:
- 'btemp' and 'batctrl' are the pins interfaced for battery temperature
- measurement, 'btemp' signal is used when NTC(negative temperature
- coefficient) resister is interfaced external to battery whereas
- 'batctrl' pin is used when NTC resister is internal to battery.
-
- Example:
- ab8500_battery: ab8500_battery {
- thermistor-on-batctrl;
- };
- indicates: NTC resister is internal to battery, 'batctrl' is used
- for thermal measurement.
-
- The absence of property 'thermal-on-batctrl' indicates
- NTC resister is external to battery and 'btemp' signal is used
- for thermal measurement.
-
-battery-type:
- This shall be the battery manufacturing technology type,
- allowed types are:
- "UNKNOWN" "NiMH" "LION" "LIPO" "LiFe" "NiCd" "LiMn"
- Example:
- ab8500_battery: ab8500_battery {
- stericsson,battery-type = "LIPO";
- }
diff --git a/Documentation/devicetree/bindings/pwm/imx-pwm.yaml b/Documentation/devicetree/bindings/pwm/imx-pwm.yaml
index c01dff3b7f84..a84a240a61dc 100644
--- a/Documentation/devicetree/bindings/pwm/imx-pwm.yaml
+++ b/Documentation/devicetree/bindings/pwm/imx-pwm.yaml
@@ -14,12 +14,10 @@ allOf:
properties:
"#pwm-cells":
- description: |
- Should be 2 for i.MX1 and 3 for i.MX27 and newer SoCs. See pwm.yaml
- in this directory for a description of the cells format.
- enum:
- - 2
- - 3
+ description:
+ The only third cell flag supported by this binding is
+ PWM_POLARITY_INVERTED. fsl,imx1-pwm does not support this flags.
+ const: 3
compatible:
oneOf:
diff --git a/Documentation/devicetree/bindings/pwm/mxs-pwm.yaml b/Documentation/devicetree/bindings/pwm/mxs-pwm.yaml
index 6ffbed204c25..8f50e23ca8c9 100644
--- a/Documentation/devicetree/bindings/pwm/mxs-pwm.yaml
+++ b/Documentation/devicetree/bindings/pwm/mxs-pwm.yaml
@@ -15,12 +15,19 @@ allOf:
properties:
compatible:
- enum:
- - fsl,imx23-pwm
+ oneOf:
+ - const: fsl,imx23-pwm
+ - items:
+ - enum:
+ - fsl,imx28-pwm
+ - const: fsl,imx23-pwm
reg:
maxItems: 1
+ clocks:
+ maxItems: 1
+
"#pwm-cells":
const: 3
@@ -31,6 +38,7 @@ properties:
required:
- compatible
- reg
+ - clocks
- fsl,pwm-number
additionalProperties: false
@@ -40,6 +48,7 @@ examples:
pwm@80064000 {
compatible = "fsl,imx23-pwm";
reg = <0x80064000 0x2000>;
+ clocks = <&clks 30>;
#pwm-cells = <3>;
fsl,pwm-number = <8>;
};
diff --git a/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml b/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml
index f2d1dc7e7b3f..65bfb492b3a4 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml
+++ b/Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml
@@ -32,6 +32,7 @@ properties:
- rockchip,rk3308-pwm
- rockchip,rk3568-pwm
- rockchip,rk3588-pwm
+ - rockchip,rv1126-pwm
- const: rockchip,rk3328-pwm
reg:
diff --git a/Documentation/devicetree/bindings/regulator/adi,max77503-regulator.yaml b/Documentation/devicetree/bindings/regulator/adi,max77503-regulator.yaml
new file mode 100644
index 000000000000..aa581e550be2
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/adi,max77503-regulator.yaml
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright (c) 2023 Analog Devices, Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/adi,max77503-regulator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices MAX77503 Buck Converter
+
+maintainers:
+ - Gokhan Celik <Gokhan.Celik@analog.com>
+
+description: |
+ The Analog Devices MAX77503 is a single channel 14V input, 1.5A
+ high-efficiency buck converter. This converter has 94% efficiency
+ for 2-Cell/3-Cell battery applications.
+
+allOf:
+ - $ref: regulator.yaml#
+
+properties:
+ compatible:
+ enum:
+ - adi,max77503
+
+ reg:
+ description: I2C address of the device
+ items:
+ - enum: [0x1e, 0x24, 0x37]
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ regulator@1e {
+ compatible = "adi,max77503";
+ reg = <0x1e>;
+
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <5000000>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/regulator/da9210.txt b/Documentation/devicetree/bindings/regulator/da9210.txt
deleted file mode 100644
index 58065ca9e3b4..000000000000
--- a/Documentation/devicetree/bindings/regulator/da9210.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-* Dialog Semiconductor DA9210 Multi-phase 12A DCDC BUCK Converter
-
-Required properties:
-
-- compatible: must be "dlg,da9210"
-- reg: the i2c slave address of the regulator. It should be 0x68.
-
-Optional properties:
-
-- interrupts: a reference to the DA9210 interrupt, if available.
-
-Any standard regulator properties can be used to configure the single da9210
-DCDC.
-
-Example:
-
- da9210@68 {
- compatible = "dlg,da9210";
- reg = <0x68>;
-
- interrupt-parent = <...>;
- interrupts = <...>;
-
- regulator-min-microvolt = <300000>;
- regulator-max-microvolt = <1570000>;
- regulator-min-microamp = <1600000>;
- regulator-max-microamp = <4600000>;
- regulator-boot-on;
- };
diff --git a/Documentation/devicetree/bindings/regulator/dlg,da9210.yaml b/Documentation/devicetree/bindings/regulator/dlg,da9210.yaml
new file mode 100644
index 000000000000..81f23de36de4
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/dlg,da9210.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/dlg,da9210.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Dialog Semiconductor DA9210 Multi-Phase 12A DC-DC Buck Converter
+
+maintainers:
+ - Support Opensource <support.opensource@diasemi.com>
+
+allOf:
+ - $ref: regulator.yaml#
+
+properties:
+ compatible:
+ const: dlg,da9210
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ regulator@68 {
+ compatible = "dlg,da9210";
+ reg = <0x68>;
+
+ interrupt-parent = <&irqc0>;
+ interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1570000>;
+ regulator-min-microamp = <1600000>;
+ regulator-max-microamp = <4600000>;
+ regulator-boot-on;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml b/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml
index ac0281b1cceb..ce7751b9129c 100644
--- a/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml
@@ -100,6 +100,11 @@ properties:
vin-supply:
description: Input supply phandle.
+ interrupts:
+ maxItems: 1
+ description:
+ Interrupt signaling a critical under-voltage event.
+
required:
- compatible
- regulator-name
diff --git a/Documentation/devicetree/bindings/regulator/maxim,max20086.yaml b/Documentation/devicetree/bindings/regulator/maxim,max20086.yaml
index 05f72391185e..7394c0a339c5 100644
--- a/Documentation/devicetree/bindings/regulator/maxim,max20086.yaml
+++ b/Documentation/devicetree/bindings/regulator/maxim,max20086.yaml
@@ -43,6 +43,7 @@ properties:
"^OUT[1-4]$":
type: object
$ref: regulator.yaml#
+ unevaluatedProperties: false
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/regulator/maxim,max77826.yaml b/Documentation/devicetree/bindings/regulator/maxim,max77826.yaml
index 78c0b63243f7..6d6bbfbd26d4 100644
--- a/Documentation/devicetree/bindings/regulator/maxim,max77826.yaml
+++ b/Documentation/devicetree/bindings/regulator/maxim,max77826.yaml
@@ -30,10 +30,12 @@ properties:
"^LDO([1-9]|1[0-5])$":
type: object
$ref: regulator.yaml#
+ unevaluatedProperties: false
"^BUCK|BUCKBOOST$":
type: object
$ref: regulator.yaml#
+ unevaluatedProperties: false
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6358-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6358-regulator.yaml
new file mode 100644
index 000000000000..c50402fcba72
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6358-regulator.yaml
@@ -0,0 +1,250 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/mediatek,mt6358-regulator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT6358 Regulator
+
+maintainers:
+ - Zhiyong Tao <zhiyong.tao@mediatek.com>
+
+description:
+ Regulator node of the PMIC. This node should under the PMIC's device node.
+ All voltage regulators provided by the PMIC are described as sub-nodes of
+ this node.
+
+properties:
+ compatible:
+ oneOf:
+ - const: mediatek,mt6358-regulator
+ - items:
+ - const: mediatek,mt6366-regulator
+ - const: mediatek,mt6358-regulator
+
+ vsys-ldo1-supply:
+ description: Supply for LDOs vfe28, vxo22, vcn28, vaux18, vaud28, vsim1, vusb, vbif28
+ vsys-ldo2-supply:
+ description: Supply for LDOs vldo28 (MT6358 only), vio28, vmc, vmch, vsim2
+ vsys-ldo3-supply:
+ description: Supply for LDOs vcn33, vcama[12] (MT6358 only), vemc, vibr
+ vsys-vcore-supply:
+ description: Supply for buck regulator vcore
+ vsys-vdram1-supply:
+ description: Supply for buck regulator vdram1
+ vsys-vgpu-supply:
+ description: Supply for buck regulator vgpu
+ vsys-vmodem-supply:
+ description: Supply for buck regulator vmodem
+ vsys-vpa-supply:
+ description: Supply for buck regulator vpa
+ vsys-vproc11-supply:
+ description: Supply for buck regulator vproc11
+ vsys-vproc12-supply:
+ description: Supply for buck regulator vproc12
+ vsys-vs1-supply:
+ description: Supply for buck regulator vs1
+ vsys-vs2-supply:
+ description: Supply for buck regulator vs2
+ vs1-ldo1-supply:
+ description:
+ Supply for LDOs vrf18, vefuse, vcn18, vcamio (MT6358 only), vio18, vm18 (MT6366 only)
+ vs2-ldo1-supply:
+ description: Supply for LDOs vdram2, vmddr (MT6366 only)
+ vs2-ldo2-supply:
+ description: Supply for LDOs vrf12, va12
+ vs2-ldo3-supply:
+ description:
+ Supply for LDOs vsram-core (MT6366 only), vsram-gpu, vsram-others, vsram-proc11, vsram-proc12
+ vs2-ldo4-supply:
+ description: Supply for LDO vcamd
+
+patternProperties:
+ "^(buck_)?v(core|dram1|gpu|modem|pa|proc1[12]|s[12])$":
+ description: Buck regulators
+ type: object
+ $ref: regulator.yaml#
+ properties:
+ regulator-allowed-modes:
+ description: |
+ Buck regulatpr operating modes allowed. Valid values below.
+ Users should use the macros from dt-bindings/regulator/mediatek,mt6397-regulator.h
+ 0 (MT6397_BUCK_MODE_AUTO): Auto PFM/PWM mode
+ 1 (MT6397_BUCK_MODE_FORCE_PWM): Forced PWM mode
+ items:
+ enum: [0, 1]
+ unevaluatedProperties: false
+
+ "^(ldo_)?v(a|rf)12$":
+ description: LDOs with fixed 1.2V output and 0~100/10mV tuning
+ type: object
+ $ref: regulator.yaml#
+ properties:
+ regulator-allowed-modes: false
+ unevaluatedProperties: false
+
+ "^(ldo_)?v((aux|cn|io|rf)18|camio)$":
+ description:
+ LDOs with fixed 1.8V output and 0~100/10mV tuning (vcn18 on MT6366 has variable output)
+ type: object
+ $ref: regulator.yaml#
+ properties:
+ regulator-allowed-modes: false
+ unevaluatedProperties: false
+
+ "^(ldo_)?vxo22$":
+ description: LDOs with fixed 2.2V output and 0~100/10mV tuning
+ type: object
+ $ref: regulator.yaml#
+ properties:
+ regulator-allowed-modes: false
+ unevaluatedProperties: false
+
+ "^(ldo_)?v(aud|bif|cn|fe|io)28$":
+ description: LDOs with fixed 2.8V output and 0~100/10mV tuning
+ type: object
+ $ref: regulator.yaml#
+ properties:
+ regulator-allowed-modes: false
+ unevaluatedProperties: false
+
+ "^(ldo_)?vusb$":
+ description: LDOs with fixed 3.0V output and 0~100/10mV tuning
+ type: object
+ $ref: regulator.yaml#
+ properties:
+ regulator-allowed-modes: false
+ unevaluatedProperties: false
+
+ "^(ldo_)?vsram[_-](core|gpu|others|proc1[12])$":
+ description: LDOs with variable output
+ type: object
+ $ref: regulator.yaml#
+ properties:
+ regulator-allowed-modes: false
+ unevaluatedProperties: false
+
+ "^(ldo_)?v(cama[12]|camd|cn33|dram2|efuse|emc|ibr|ldo28|m18|mc|mch|mddr|sim[12])$":
+ description: LDOs with variable output and 0~100/10mV tuning
+ type: object
+ $ref: regulator.yaml#
+ properties:
+ regulator-allowed-modes: false
+ unevaluatedProperties: false
+
+required:
+ - compatible
+
+additionalProperties: false
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ const: mediatek,mt6358-regulator
+ then:
+ patternProperties:
+ # Old regulator node name scheme (with prefix and underscores) only
+ # ([^y-] is used to avoid matching -supply
+ "^(?<!buck_)(?<!ldo_)v.*[^y-](?!-supply)$": false
+ "^ldo_vsram-": false
+ # vsram_core regulator doesn't exist on MT6358
+ "^ldo_vsram[-_]core$": false
+
+ properties:
+ # vm18 and vmddr regulators don't exist on MT6358
+ ldo_vm18: false
+ ldo_vmddr: false
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: mediatek,mt6366-regulator
+ then:
+ patternProperties:
+ # Prefer cleaned up regulator node names
+ "^(buck|ldo)_": false
+ # Don't allow underscores
+ "^vsram_": false
+ # vcam* regulators don't exist on MT6366
+ "^vcam": false
+
+ properties:
+ # vldo28 regulator doesn't exist on MT6366
+ vldo28: false
+ # vs2_ldo4 supply pin doesn't exist on MT6366
+ vs2-ldo4-supply: false
+
+examples:
+ - |
+ #include <dt-bindings/regulator/mediatek,mt6397-regulator.h>
+
+ regulator {
+ compatible = "mediatek,mt6358-regulator";
+
+ buck_vgpu {
+ regulator-name = "vgpu";
+ regulator-min-microvolt = <625000>;
+ regulator-max-microvolt = <900000>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <200>;
+ regulator-allowed-modes = <MT6397_BUCK_MODE_AUTO
+ MT6397_BUCK_MODE_FORCE_PWM>;
+ };
+
+ ldo_vsram_gpu {
+ regulator-name = "vsram_gpu";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <240>;
+ };
+ };
+
+ - |
+ #include <dt-bindings/regulator/mediatek,mt6397-regulator.h>
+
+ regulator {
+ compatible = "mediatek,mt6366-regulator", "mediatek,mt6358-regulator";
+
+ vdram1 {
+ regulator-name = "pp1125_emi_vdd2";
+ regulator-min-microvolt = <1125000>;
+ regulator-max-microvolt = <1125000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <0>;
+ regulator-allowed-modes = <MT6397_BUCK_MODE_AUTO
+ MT6397_BUCK_MODE_FORCE_PWM>;
+ regulator-always-on;
+ };
+
+ vproc11 {
+ regulator-name = "ppvar_dvdd_proc_bc_mt6366";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <200>;
+ regulator-allowed-modes = <MT6397_BUCK_MODE_AUTO
+ MT6397_BUCK_MODE_FORCE_PWM>;
+ regulator-always-on;
+ };
+
+ vmddr {
+ regulator-name = "pm0750_emi_vmddr";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <750000>;
+ regulator-enable-ramp-delay = <325>;
+ regulator-always-on;
+ };
+
+ vsram-proc11 {
+ regulator-name = "pp0900_dvdd_sram_bc";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <1120000>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <240>;
+ regulator-always-on;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/regulator/mps,mpq2286.yaml b/Documentation/devicetree/bindings/regulator/mps,mpq2286.yaml
new file mode 100644
index 000000000000..1296f9b30862
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/mps,mpq2286.yaml
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/mps,mpq2286.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Monolithic Power System MPQ2286 PMIC
+
+maintainers:
+ - Saravanan Sekar <saravanan@linumiz.com>
+
+properties:
+ compatible:
+ enum:
+ - mps,mpq2286
+
+ reg:
+ maxItems: 1
+
+ regulators:
+ type: object
+
+ properties:
+ buck:
+ type: object
+ $ref: regulator.yaml#
+
+ unevaluatedProperties: false
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - regulators
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@3 {
+ compatible = "mps,mpq2286";
+ reg = <0x3>;
+
+ regulators {
+ buck {
+ regulator-name = "buck";
+ regulator-min-microvolt = <1600000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt b/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt
deleted file mode 100644
index b6384306db5c..000000000000
--- a/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt
+++ /dev/null
@@ -1,350 +0,0 @@
-MediaTek MT6358 Regulator
-
-All voltage regulators provided by the MT6358 PMIC are described as the
-subnodes of the MT6358 regulators node. Each regulator is named according
-to its regulator type, buck_<name> and ldo_<name>. The definition for each
-of these nodes is defined using the standard binding for regulators at
-Documentation/devicetree/bindings/regulator/regulator.txt.
-
-The valid names for regulators are::
-BUCK:
- buck_vdram1, buck_vcore, buck_vpa, buck_vproc11, buck_vproc12, buck_vgpu,
- buck_vs2, buck_vmodem, buck_vs1
-LDO:
- ldo_vdram2, ldo_vsim1, ldo_vibr, ldo_vrf12, ldo_vio18, ldo_vusb, ldo_vcamio,
- ldo_vcamd, ldo_vcn18, ldo_vfe28, ldo_vsram_proc11, ldo_vcn28, ldo_vsram_others,
- ldo_vsram_gpu, ldo_vxo22, ldo_vefuse, ldo_vaux18, ldo_vmch, ldo_vbif28,
- ldo_vsram_proc12, ldo_vcama1, ldo_vemc, ldo_vio28, ldo_va12, ldo_vrf18,
- ldo_vcn33, ldo_vcama2, ldo_vmc, ldo_vldo28, ldo_vaud28, ldo_vsim2
-
-Example:
-
- pmic {
- compatible = "mediatek,mt6358";
-
- mt6358regulator: mt6358regulator {
- compatible = "mediatek,mt6358-regulator";
-
- mt6358_vdram1_reg: buck_vdram1 {
- regulator-compatible = "buck_vdram1";
- regulator-name = "vdram1";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <2087500>;
- regulator-ramp-delay = <12500>;
- regulator-enable-ramp-delay = <0>;
- regulator-always-on;
- };
-
- mt6358_vcore_reg: buck_vcore {
- regulator-name = "vcore";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1293750>;
- regulator-ramp-delay = <6250>;
- regulator-enable-ramp-delay = <200>;
- regulator-always-on;
- };
-
- mt6358_vpa_reg: buck_vpa {
- regulator-name = "vpa";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <3650000>;
- regulator-ramp-delay = <50000>;
- regulator-enable-ramp-delay = <250>;
- };
-
- mt6358_vproc11_reg: buck_vproc11 {
- regulator-name = "vproc11";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1293750>;
- regulator-ramp-delay = <6250>;
- regulator-enable-ramp-delay = <200>;
- regulator-always-on;
- };
-
- mt6358_vproc12_reg: buck_vproc12 {
- regulator-name = "vproc12";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1293750>;
- regulator-ramp-delay = <6250>;
- regulator-enable-ramp-delay = <200>;
- regulator-always-on;
- };
-
- mt6358_vgpu_reg: buck_vgpu {
- regulator-name = "vgpu";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1293750>;
- regulator-ramp-delay = <6250>;
- regulator-enable-ramp-delay = <200>;
- };
-
- mt6358_vs2_reg: buck_vs2 {
- regulator-name = "vs2";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <2087500>;
- regulator-ramp-delay = <12500>;
- regulator-enable-ramp-delay = <0>;
- regulator-always-on;
- };
-
- mt6358_vmodem_reg: buck_vmodem {
- regulator-name = "vmodem";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1293750>;
- regulator-ramp-delay = <6250>;
- regulator-enable-ramp-delay = <900>;
- regulator-always-on;
- };
-
- mt6358_vs1_reg: buck_vs1 {
- regulator-name = "vs1";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <2587500>;
- regulator-ramp-delay = <12500>;
- regulator-enable-ramp-delay = <0>;
- regulator-always-on;
- };
-
- mt6358_vdram2_reg: ldo_vdram2 {
- regulator-name = "vdram2";
- regulator-min-microvolt = <600000>;
- regulator-max-microvolt = <1800000>;
- regulator-enable-ramp-delay = <3300>;
- };
-
- mt6358_vsim1_reg: ldo_vsim1 {
- regulator-name = "vsim1";
- regulator-min-microvolt = <1700000>;
- regulator-max-microvolt = <3100000>;
- regulator-enable-ramp-delay = <540>;
- };
-
- mt6358_vibr_reg: ldo_vibr {
- regulator-name = "vibr";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <3300000>;
- regulator-enable-ramp-delay = <60>;
- };
-
- mt6358_vrf12_reg: ldo_vrf12 {
- compatible = "regulator-fixed";
- regulator-name = "vrf12";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- regulator-enable-ramp-delay = <120>;
- };
-
- mt6358_vio18_reg: ldo_vio18 {
- compatible = "regulator-fixed";
- regulator-name = "vio18";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-enable-ramp-delay = <2700>;
- regulator-always-on;
- };
-
- mt6358_vusb_reg: ldo_vusb {
- regulator-name = "vusb";
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3100000>;
- regulator-enable-ramp-delay = <270>;
- regulator-always-on;
- };
-
- mt6358_vcamio_reg: ldo_vcamio {
- compatible = "regulator-fixed";
- regulator-name = "vcamio";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vcamd_reg: ldo_vcamd {
- regulator-name = "vcamd";
- regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <1800000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vcn18_reg: ldo_vcn18 {
- compatible = "regulator-fixed";
- regulator-name = "vcn18";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vfe28_reg: ldo_vfe28 {
- compatible = "regulator-fixed";
- regulator-name = "vfe28";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vsram_proc11_reg: ldo_vsram_proc11 {
- regulator-name = "vsram_proc11";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1293750>;
- regulator-ramp-delay = <6250>;
- regulator-enable-ramp-delay = <240>;
- regulator-always-on;
- };
-
- mt6358_vcn28_reg: ldo_vcn28 {
- compatible = "regulator-fixed";
- regulator-name = "vcn28";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vsram_others_reg: ldo_vsram_others {
- regulator-name = "vsram_others";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1293750>;
- regulator-ramp-delay = <6250>;
- regulator-enable-ramp-delay = <240>;
- regulator-always-on;
- };
-
- mt6358_vsram_gpu_reg: ldo_vsram_gpu {
- regulator-name = "vsram_gpu";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1293750>;
- regulator-ramp-delay = <6250>;
- regulator-enable-ramp-delay = <240>;
- };
-
- mt6358_vxo22_reg: ldo_vxo22 {
- compatible = "regulator-fixed";
- regulator-name = "vxo22";
- regulator-min-microvolt = <2200000>;
- regulator-max-microvolt = <2200000>;
- regulator-enable-ramp-delay = <120>;
- regulator-always-on;
- };
-
- mt6358_vefuse_reg: ldo_vefuse {
- regulator-name = "vefuse";
- regulator-min-microvolt = <1700000>;
- regulator-max-microvolt = <1900000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vaux18_reg: ldo_vaux18 {
- compatible = "regulator-fixed";
- regulator-name = "vaux18";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vmch_reg: ldo_vmch {
- regulator-name = "vmch";
- regulator-min-microvolt = <2900000>;
- regulator-max-microvolt = <3300000>;
- regulator-enable-ramp-delay = <60>;
- };
-
- mt6358_vbif28_reg: ldo_vbif28 {
- compatible = "regulator-fixed";
- regulator-name = "vbif28";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vsram_proc12_reg: ldo_vsram_proc12 {
- regulator-name = "vsram_proc12";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1293750>;
- regulator-ramp-delay = <6250>;
- regulator-enable-ramp-delay = <240>;
- regulator-always-on;
- };
-
- mt6358_vcama1_reg: ldo_vcama1 {
- regulator-name = "vcama1";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3000000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vemc_reg: ldo_vemc {
- regulator-name = "vemc";
- regulator-min-microvolt = <2900000>;
- regulator-max-microvolt = <3300000>;
- regulator-enable-ramp-delay = <60>;
- regulator-always-on;
- };
-
- mt6358_vio28_reg: ldo_vio28 {
- compatible = "regulator-fixed";
- regulator-name = "vio28";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_va12_reg: ldo_va12 {
- compatible = "regulator-fixed";
- regulator-name = "va12";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- regulator-enable-ramp-delay = <270>;
- regulator-always-on;
- };
-
- mt6358_vrf18_reg: ldo_vrf18 {
- compatible = "regulator-fixed";
- regulator-name = "vrf18";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-enable-ramp-delay = <120>;
- };
-
- mt6358_vcn33_reg: ldo_vcn33 {
- regulator-name = "vcn33";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3500000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vcama2_reg: ldo_vcama2 {
- regulator-name = "vcama2";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3000000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vmc_reg: ldo_vmc {
- regulator-name = "vmc";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-enable-ramp-delay = <60>;
- };
-
- mt6358_vldo28_reg: ldo_vldo28 {
- regulator-name = "vldo28";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <3000000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vaud28_reg: ldo_vaud28 {
- compatible = "regulator-fixed";
- regulator-name = "vaud28";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- regulator-enable-ramp-delay = <270>;
- };
-
- mt6358_vsim2_reg: ldo_vsim2 {
- regulator-name = "vsim2";
- regulator-min-microvolt = <1700000>;
- regulator-max-microvolt = <3100000>;
- regulator-enable-ramp-delay = <540>;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml b/Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml
index eb61e04ef852..b5181719daa1 100644
--- a/Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml
+++ b/Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml
@@ -48,10 +48,12 @@ properties:
"^LDO[1-4]$":
type: object
$ref: regulator.yaml#
+ unevaluatedProperties: false
"^BUCK|BOOST$":
type: object
$ref: regulator.yaml#
+ unevaluatedProperties: false
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml
index 127a6f39b7f0..acd37f28ef53 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml
@@ -50,6 +50,7 @@ description: |
For PM8550, smps1 - smps6, ldo1 - ldo17, bob1 - bob2
For PM8998, smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2
For PMI8998, bob
+ For PMC8380, smps1 - smps8, ldo1 - lodo3
For PMR735A, smps1 - smps3, ldo1 - ldo7
For PMX55, smps1 - smps7, ldo1 - ldo16
For PMX65, smps1 - smps8, ldo1 - ldo21
@@ -78,6 +79,7 @@ properties:
- qcom,pm8998-rpmh-regulators
- qcom,pmc8180-rpmh-regulators
- qcom,pmc8180c-rpmh-regulators
+ - qcom,pmc8380-rpmh-regulators
- qcom,pmg1110-rpmh-regulators
- qcom,pmi8998-rpmh-regulators
- qcom,pmm8155au-rpmh-regulators
@@ -368,6 +370,16 @@ allOf:
properties:
compatible:
enum:
+ - qcom,pmc8380-rpmh-regulators
+ then:
+ patternProperties:
+ "^vdd-l[1-3]-supply$": true
+ "^vdd-s[1-8]-supply$": true
+
+ - if:
+ properties:
+ compatible:
+ enum:
- qcom,pmg1110-rpmh-regulators
then:
properties:
diff --git a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.yaml
index bdf34c2de96b..7a1b7d2abbd4 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.yaml
@@ -17,12 +17,15 @@ properties:
- qcom,pm660l-regulators
- qcom,pm8004-regulators
- qcom,pm8005-regulators
+ - qcom,pm8019-regulators
- qcom,pm8226-regulators
- qcom,pm8841-regulators
+ - qcom,pm8909-regulators
- qcom,pm8916-regulators
- qcom,pm8941-regulators
- qcom,pm8950-regulators
- qcom,pm8994-regulators
+ - qcom,pma8084-regulators
- qcom,pmi8994-regulators
- qcom,pmp8074-regulators
- qcom,pms405-regulators
@@ -32,7 +35,7 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle
patternProperties:
- "^(5vs[1-2]|(l|s)[1-9][0-9]?|lvs[1-3])$":
+ "^(5vs[1-2]|(l|s)[1-9][0-9]?|lvs[1-4])$":
description: List of regulators and its properties
type: object
$ref: regulator.yaml#
@@ -181,6 +184,25 @@ allOf:
compatible:
contains:
enum:
+ - qcom,pm8019-regulators
+ then:
+ properties:
+ vdd_l1-supply: true
+ vdd_l2_l3-supply: true
+ vdd_l4_l5_l6-supply: true
+ vdd_l7_l8_l11-supply: true
+ vdd_l9-supply: true
+ vdd_l10-supply: true
+ vdd_l12-supply: true
+ vdd_l13_l14-supply: true
+ patternProperties:
+ "^vdd_s[1-4]-supply$": true
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,pm8226-regulators
then:
properties:
@@ -211,6 +233,24 @@ allOf:
compatible:
contains:
enum:
+ - qcom,pm8909-regulators
+ then:
+ properties:
+ vdd_s1-supply: true
+ vdd_s2-supply: true
+ vdd_l1-supply: true
+ vdd_l2_l5-supply: true
+ vdd_l3_l6_l10-supply: true
+ vdd_l4_l7-supply: true
+ vdd_l8_l11_l15_l18-supply: true
+ vdd_l9_l12_l14_l17-supply: true
+ vdd_l13-supply: true
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,pm8916-regulators
then:
properties:
@@ -300,6 +340,32 @@ allOf:
compatible:
contains:
enum:
+ - qcom,pma8084-regulators
+ then:
+ properties:
+ vdd_l1_l11-supply: true
+ vdd_l2_l3_l4_l27-supply: true
+ vdd_l5_l7-supply: true
+ vdd_l6_l12_l14_l15_l26-supply: true
+ vdd_l8-supply: true
+ vdd_l9_l10_l13_l20_l23_l24-supply: true
+ vdd_l16_l25-supply: true
+ vdd_l17-supply: true
+ vdd_l18-supply: true
+ vdd_l19-supply: true
+ vdd_l21-supply: true
+ vdd_l22-supply: true
+ vdd_lvs1_2-supply: true
+ vdd_lvs3_4-supply: true
+ vdd_5vs1-supply: true
+ patternProperties:
+ "^vdd_s([1-9]|1[0-2])-supply$": true
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,pmi8994-regulators
then:
properties:
diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
index 895415772d1d..09102dda4942 100644
--- a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
@@ -21,6 +21,7 @@ properties:
- mediatek,mt8188-scp
- mediatek,mt8192-scp
- mediatek,mt8195-scp
+ - mediatek,mt8195-scp-dual
reg:
description:
@@ -31,10 +32,7 @@ properties:
reg-names:
minItems: 2
- items:
- - const: sram
- - const: cfg
- - const: l1tcm
+ maxItems: 3
clocks:
description:
@@ -58,6 +56,93 @@ properties:
memory-region:
maxItems: 1
+ cros-ec-rpmsg:
+ $ref: /schemas/mfd/google,cros-ec.yaml
+ description:
+ This subnode represents the rpmsg device. The properties
+ of this node are defined by the individual bindings for
+ the rpmsg devices.
+
+ required:
+ - mediatek,rpmsg-name
+
+ unevaluatedProperties: false
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 1
+
+ ranges:
+ description:
+ Standard ranges definition providing address translations for
+ local SCP SRAM address spaces to bus addresses.
+
+patternProperties:
+ "^scp@[a-f0-9]+$":
+ type: object
+ description:
+ The MediaTek SCP integrated to SoC might be a multi-core version.
+ The other cores are represented as child nodes of the boot core.
+ There are some integration differences for the IP like the usage of
+ address translator for translating SoC bus addresses into address space
+ for the processor.
+
+ Each SCP core has own cache memory. The SRAM and L1TCM are shared by
+ cores. The power of cache, SRAM and L1TCM power should be enabled
+ before booting SCP cores. The size of cache, SRAM, and L1TCM are varied
+ on differnt SoCs.
+
+ The SCP cores do not use an MMU, but has a set of registers to
+ control the translations between 32-bit CPU addresses into system bus
+ addresses. Cache and memory access settings are provided through a
+ Memory Protection Unit (MPU), programmable only from the SCP.
+
+ properties:
+ compatible:
+ enum:
+ - mediatek,scp-core
+
+ reg:
+ description: The base address and size of SRAM.
+ maxItems: 1
+
+ reg-names:
+ const: sram
+
+ interrupts:
+ maxItems: 1
+
+ firmware-name:
+ $ref: /schemas/types.yaml#/definitions/string
+ description:
+ If present, name (or relative path) of the file within the
+ firmware search path containing the firmware image used when
+ initializing sub cores of multi-core SCP.
+
+ memory-region:
+ maxItems: 1
+
+ cros-ec-rpmsg:
+ $ref: /schemas/mfd/google,cros-ec.yaml
+ description:
+ This subnode represents the rpmsg device. The properties
+ of this node are defined by the individual bindings for
+ the rpmsg devices.
+
+ required:
+ - mediatek,rpmsg-name
+
+ unevaluatedProperties: false
+
+ required:
+ - compatible
+ - reg
+ - reg-names
+
+ additionalProperties: false
+
required:
- compatible
- reg
@@ -87,23 +172,39 @@ allOf:
reg:
maxItems: 2
reg-names:
+ items:
+ - const: sram
+ - const: cfg
+ - if:
+ properties:
+ compatible:
+ enum:
+ - mediatek,mt8192-scp
+ - mediatek,mt8195-scp
+ then:
+ properties:
+ reg:
+ maxItems: 3
+ reg-names:
+ items:
+ - const: sram
+ - const: cfg
+ - const: l1tcm
+ - if:
+ properties:
+ compatible:
+ enum:
+ - mediatek,mt8195-scp-dual
+ then:
+ properties:
+ reg:
maxItems: 2
+ reg-names:
+ items:
+ - const: cfg
+ - const: l1tcm
-additionalProperties:
- type: object
- description:
- Subnodes of the SCP represent rpmsg devices. The names of the devices
- are not important. The properties of these nodes are defined by the
- individual bindings for the rpmsg devices.
- properties:
- mediatek,rpmsg-name:
- $ref: /schemas/types.yaml#/definitions/string-array
- description:
- Contains the name for the rpmsg device. Used to match
- the subnode to rpmsg device announced by SCP.
-
- required:
- - mediatek,rpmsg-name
+additionalProperties: false
examples:
- |
@@ -118,7 +219,42 @@ examples:
clocks = <&infracfg CLK_INFRA_SCPSYS>;
clock-names = "main";
- cros_ec {
+ cros-ec-rpmsg {
+ compatible = "google,cros-ec-rpmsg";
mediatek,rpmsg-name = "cros-ec-rpmsg";
};
};
+
+ - |
+ scp@10500000 {
+ compatible = "mediatek,mt8195-scp-dual";
+ reg = <0x10720000 0xe0000>,
+ <0x10700000 0x8000>;
+ reg-names = "cfg", "l1tcm";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x10500000 0x100000>;
+
+ scp@0 {
+ compatible = "mediatek,scp-core";
+ reg = <0x0 0xa0000>;
+ reg-names = "sram";
+
+ cros-ec-rpmsg {
+ compatible = "google,cros-ec-rpmsg";
+ mediatek,rpmsg-name = "cros-ec-rpmsg";
+ };
+ };
+
+ scp@a0000 {
+ compatible = "mediatek,scp-core";
+ reg = <0xa0000 0x20000>;
+ reg-names = "sram";
+
+ cros-ec-rpmsg {
+ compatible = "google,cros-ec-rpmsg";
+ mediatek,rpmsg-name = "cros-ec-rpmsg";
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml
index a2b0079de039..661c2b425da3 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml
@@ -66,7 +66,9 @@ allOf:
- qcom,msm8953-adsp-pil
- qcom,msm8974-adsp-pil
- qcom,msm8996-adsp-pil
+ - qcom,msm8996-slpi-pil
- qcom,msm8998-adsp-pas
+ - qcom,msm8998-slpi-pas
- qcom,sdm845-adsp-pas
- qcom,sdm845-cdsp-pas
- qcom,sdm845-slpi-pas
@@ -84,24 +86,6 @@ allOf:
compatible:
contains:
enum:
- - qcom,msm8996-slpi-pil
- - qcom,msm8998-slpi-pas
- then:
- properties:
- clocks:
- items:
- - description: XO clock
- - description: AGGRE2 clock
- clock-names:
- items:
- - const: xo
- - const: aggre2
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- qcom,msm8226-adsp-pil
- qcom,msm8953-adsp-pil
- qcom,msm8974-adsp-pil
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,msm8996-mss-pil.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,msm8996-mss-pil.yaml
index 0643faae2c39..971734085d51 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,msm8996-mss-pil.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,msm8996-mss-pil.yaml
@@ -220,7 +220,6 @@ allOf:
- description: GCC MSS GPLL0 clock
- description: GCC MSS SNOC_AXI clock
- description: GCC MSS MNOC_AXI clock
- - description: RPM PNOC clock
- description: RPM QDSS clock
clock-names:
items:
@@ -231,7 +230,6 @@ allOf:
- const: gpll0_mss
- const: snoc_axi
- const: mnoc_axi
- - const: pnoc
- const: qdss
glink-edge: false
required:
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml
index 689d5d535331..f10f329677d8 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml
@@ -16,6 +16,7 @@ description:
properties:
compatible:
enum:
+ - qcom,sc7180-adsp-pas
- qcom,sc7180-mpss-pas
- qcom,sc7280-mpss-pas
@@ -30,26 +31,6 @@ properties:
items:
- const: xo
- interrupts:
- minItems: 6
-
- interrupt-names:
- minItems: 6
-
- power-domains:
- minItems: 2
- items:
- - description: CX power domain
- - description: MX power domain
- - description: MSS power domain
-
- power-domain-names:
- minItems: 2
- items:
- - const: cx
- - const: mx
- - const: mss
-
memory-region:
maxItems: 1
description: Reference to the reserved-memory for the Hexagon core
@@ -75,19 +56,69 @@ allOf:
properties:
compatible:
enum:
+ - qcom,sc7180-adsp-pas
+ then:
+ properties:
+ interrupts:
+ maxItems: 5
+ interrupt-names:
+ maxItems: 5
+ else:
+ properties:
+ interrupts:
+ minItems: 6
+ interrupt-names:
+ minItems: 6
+
+ - if:
+ properties:
+ compatible:
+ enum:
+ - qcom,sc7180-adsp-pas
+ then:
+ properties:
+ power-domains:
+ items:
+ - description: LCX power domain
+ - description: LMX power domain
+ power-domain-names:
+ items:
+ - const: lcx
+ - const: lmx
+
+ - if:
+ properties:
+ compatible:
+ enum:
- qcom,sc7180-mpss-pas
then:
properties:
power-domains:
- minItems: 3
+ items:
+ - description: CX power domain
+ - description: MX power domain
+ - description: MSS power domain
power-domain-names:
- minItems: 3
- else:
+ items:
+ - const: cx
+ - const: mx
+ - const: mss
+
+ - if:
+ properties:
+ compatible:
+ enum:
+ - qcom,sc7280-mpss-pas
+ then:
properties:
power-domains:
- maxItems: 2
+ items:
+ - description: CX power domain
+ - description: MX power domain
power-domain-names:
- maxItems: 2
+ items:
+ - const: cx
+ - const: mx
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml
new file mode 100644
index 000000000000..3e4a03eb4532
--- /dev/null
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml
@@ -0,0 +1,145 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/remoteproc/qcom,sm6375-pas.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SM6375 Peripheral Authentication Service
+
+maintainers:
+ - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description:
+ Qualcomm SM6375 SoC Peripheral Authentication Service loads and boots
+ firmware on the Qualcomm DSP Hexagon cores.
+
+properties:
+ compatible:
+ enum:
+ - qcom,sm6375-adsp-pas
+ - qcom,sm6375-cdsp-pas
+ - qcom,sm6375-mpss-pas
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: XO clock
+
+ clock-names:
+ items:
+ - const: xo
+
+ memory-region:
+ maxItems: 1
+ description: Reference to the reserved-memory for the Hexagon core
+
+ firmware-name:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: Firmware name for the Hexagon core
+
+ smd-edge: false
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - $ref: /schemas/remoteproc/qcom,pas-common.yaml#
+ - if:
+ properties:
+ compatible:
+ enum:
+ - qcom,sm6375-adsp-pas
+ - qcom,sm6375-cdsp-pas
+ then:
+ properties:
+ interrupts:
+ maxItems: 5
+ interrupt-names:
+ maxItems: 5
+ else:
+ properties:
+ interrupts:
+ minItems: 6
+ interrupt-names:
+ minItems: 6
+
+ - if:
+ properties:
+ compatible:
+ enum:
+ - qcom,sm6375-adsp-pas
+ then:
+ properties:
+ power-domains:
+ items:
+ - description: LCX power domain
+ - description: LMX power domain
+ power-domain-names:
+ items:
+ - const: lcx
+ - const: lmx
+
+ - if:
+ properties:
+ compatible:
+ enum:
+ - qcom,sm6375-cdsp-pas
+ - qcom,sm6375-mpss-pas
+ then:
+ properties:
+ power-domains:
+ items:
+ - description: CX power domain
+ power-domain-names:
+ items:
+ - const: cx
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/mailbox/qcom-ipcc.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ remoteproc_adsp: remoteproc@a400000 {
+ compatible = "qcom,sm6375-adsp-pas";
+ reg = <0x0a400000 0x100>;
+
+ interrupts-extended = <&intc GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
+ <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog", "fatal", "ready",
+ "handover", "stop-ack";
+
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "xo";
+
+ power-domains = <&rpmpd SM6375_VDD_LPI_CX>,
+ <&rpmpd SM6375_VDD_LPI_MX>;
+ power-domain-names = "lcx", "lmx";
+
+ memory-region = <&pil_adsp_mem>;
+
+ qcom,smem-states = <&smp2p_adsp_out 0>;
+ qcom,smem-state-names = "stop";
+
+ glink-edge {
+ interrupts-extended = <&ipcc IPCC_CLIENT_LPASS
+ IPCC_MPROC_SIGNAL_GLINK_QMP
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_LPASS
+ IPCC_MPROC_SIGNAL_GLINK_QMP>;
+
+ label = "lpass";
+ qcom,remote-pid = <2>;
+
+ /* ... */
+ };
+ };
diff --git a/Documentation/devicetree/bindings/remoteproc/renesas,rcar-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/renesas,rcar-rproc.yaml
index 4bea679a0f61..5c280117dc93 100644
--- a/Documentation/devicetree/bindings/remoteproc/renesas,rcar-rproc.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/renesas,rcar-rproc.yaml
@@ -31,7 +31,7 @@ properties:
remoteproc device. This is variable and describes the memories shared with
the remote processor (e.g. remoteproc firmware and carveouts, rpmsg
vrings, ...).
- (see ../reserved-memory/reserved-memory.yaml)
+ (see reserved-memory/reserved-memory.yaml in dtschema project)
required:
- compatible
diff --git a/Documentation/devicetree/bindings/remoteproc/ti,pru-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/ti,pru-rproc.yaml
index baccd98754a9..faf16cf14085 100644
--- a/Documentation/devicetree/bindings/remoteproc/ti,pru-rproc.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/ti,pru-rproc.yaml
@@ -66,6 +66,17 @@ properties:
Should contain the name of the default firmware image
file located on the firmware search path.
+ interrupts:
+ maxItems: 1
+ description:
+ Interrupt specifiers enable the virtio/rpmsg communication between MPU
+ and the PRU/RTU cores. For the values of the interrupt cells please refer
+ to interrupt-controller/ti,pruss-intc.yaml schema.
+
+ interrupt-names:
+ items:
+ - const: vring
+
if:
properties:
compatible:
@@ -171,6 +182,9 @@ examples:
<0x22400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-pru0_0-fw";
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <16 2 2>;
+ interrupt-names = "vring";
};
rtu0_0: rtu@4000 {
@@ -180,6 +194,9 @@ examples:
<0x23400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-rtu0_0-fw";
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <20 4 4>;
+ interrupt-names = "vring";
};
tx_pru0_0: txpru@a000 {
@@ -198,6 +215,9 @@ examples:
<0x24400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-pru0_1-fw";
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <18 3 3>;
+ interrupt-names = "vring";
};
rtu0_1: rtu@6000 {
@@ -207,6 +227,9 @@ examples:
<0x23c00 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-rtu0_1-fw";
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <22 5 5>;
+ interrupt-names = "vring";
};
tx_pru0_1: txpru@c000 {
diff --git a/Documentation/devicetree/bindings/reserved-memory/framebuffer.yaml b/Documentation/devicetree/bindings/reserved-memory/framebuffer.yaml
deleted file mode 100644
index 851ec24d6142..000000000000
--- a/Documentation/devicetree/bindings/reserved-memory/framebuffer.yaml
+++ /dev/null
@@ -1,52 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/reserved-memory/framebuffer.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: /reserved-memory framebuffer node
-
-maintainers:
- - devicetree-spec@vger.kernel.org
-
-allOf:
- - $ref: reserved-memory.yaml
-
-properties:
- compatible:
- const: framebuffer
- description: >
- This indicates a region of memory meant to be used as a framebuffer for
- a set of display devices. It can be used by an operating system to keep
- the framebuffer from being overwritten and use it as the backing memory
- for a display device (such as simple-framebuffer).
-
-unevaluatedProperties: false
-
-examples:
- - |
- / {
- compatible = "foo";
- model = "foo";
- #address-cells = <1>;
- #size-cells = <1>;
-
- chosen {
- framebuffer {
- compatible = "simple-framebuffer";
- memory-region = <&fb>;
- };
- };
-
- reserved-memory {
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- fb: framebuffer@80000000 {
- compatible = "framebuffer";
- reg = <0x80000000 0x007e9000>;
- };
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/reserved-memory/memory-region.yaml b/Documentation/devicetree/bindings/reserved-memory/memory-region.yaml
deleted file mode 100644
index 592f180e6b0d..000000000000
--- a/Documentation/devicetree/bindings/reserved-memory/memory-region.yaml
+++ /dev/null
@@ -1,40 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/reserved-memory/memory-region.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Reserved Memory Region
-
-maintainers:
- - devicetree-spec@vger.kernel.org
-
-description: |
- Regions in the /reserved-memory node may be referenced by other device
- nodes by adding a memory-region property to the device node.
-
-select: true
-
-properties:
- memory-region:
- $ref: /schemas/types.yaml#/definitions/phandle-array
- description: >
- Phandle to a /reserved-memory child node assigned to the device.
-
- memory-region-names:
- $ref: /schemas/types.yaml#/definitions/string-array
- description: >
- A list of names, one for each corresponding entry in the
- memory-region property
-
-additionalProperties: true
-
-examples:
- - |
- fb0: video@12300000 {
- /* ... */
- reg = <0x12300000 0x1000>;
- memory-region = <&display_reserved>;
- };
-
-...
diff --git a/Documentation/devicetree/bindings/reserved-memory/qcom,rmtfs-mem.yaml b/Documentation/devicetree/bindings/reserved-memory/qcom,rmtfs-mem.yaml
index bab982f00485..46407e9c1d4f 100644
--- a/Documentation/devicetree/bindings/reserved-memory/qcom,rmtfs-mem.yaml
+++ b/Documentation/devicetree/bindings/reserved-memory/qcom,rmtfs-mem.yaml
@@ -26,6 +26,17 @@ properties:
description: >
identifier of the client to use this region for buffers
+ qcom,use-guard-pages:
+ type: boolean
+ description: >
+ Indicates that the firmware, or hardware, does not gracefully handle
+ memory protection of this region when placed adjacent to other protected
+ memory regions, and that padding around the used portion of the memory
+ region is necessary.
+
+ When this is set, the first and last page should be left unused, and the
+ effective size of the region will thereby shrink with two pages.
+
qcom,vmid:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: >
diff --git a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
index 1810701a8509..8ce72996d500 100644
--- a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
+++ b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
@@ -1 +1 @@
-This file has been moved to reserved-memory.yaml.
+This file has been moved to reserved-memory.yaml in the dtschema repository.
diff --git a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.yaml b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.yaml
deleted file mode 100644
index c680e397cfd2..000000000000
--- a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.yaml
+++ /dev/null
@@ -1,181 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/reserved-memory/reserved-memory.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: /reserved-memory Child Node Common
-
-maintainers:
- - devicetree-spec@vger.kernel.org
-
-description: >
- Reserved memory is specified as a node under the /reserved-memory node. The
- operating system shall exclude reserved memory from normal usage one can
- create child nodes describing particular reserved (excluded from normal use)
- memory regions. Such memory regions are usually designed for the special
- usage by various device drivers.
-
- Each child of the reserved-memory node specifies one or more regions
- of reserved memory. Each child node may either use a 'reg' property to
- specify a specific range of reserved memory, or a 'size' property with
- optional constraints to request a dynamically allocated block of
- memory.
-
- Following the generic-names recommended practice, node names should
- reflect the purpose of the node (ie. "framebuffer" or "dma-pool").
- Unit address (@<address>) should be appended to the name if the node
- is a static allocation.
-
-properties:
- reg: true
-
- size:
- oneOf:
- - $ref: /schemas/types.yaml#/definitions/uint32
- - $ref: /schemas/types.yaml#/definitions/uint64
- description: >
- Length based on parent's \#size-cells. Size in bytes of memory to
- reserve.
-
- alignment:
- oneOf:
- - $ref: /schemas/types.yaml#/definitions/uint32
- - $ref: /schemas/types.yaml#/definitions/uint64
- description: >
- Length based on parent's \#size-cells. Address boundary for
- alignment of allocation.
-
- alloc-ranges:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- description: >
- Address and Length pairs. Specifies regions of memory that are
- acceptable to allocate from.
-
- iommu-addresses:
- $ref: /schemas/types.yaml#/definitions/phandle-array
- description: >
- A list of phandle and specifier pairs that describe static IO virtual
- address space mappings and carveouts associated with a given reserved
- memory region. The phandle in the first cell refers to the device for
- which the mapping or carveout is to be created.
-
- The specifier consists of an address/size pair and denotes the IO
- virtual address range of the region for the given device. The exact
- format depends on the values of the "#address-cells" and "#size-cells"
- properties of the device referenced via the phandle.
-
- When used in combination with a "reg" property, an IOVA mapping is to
- be established for this memory region. One example where this can be
- useful is to create an identity mapping for physical memory that the
- firmware has configured some hardware to access (such as a bootsplash
- framebuffer).
-
- If no "reg" property is specified, the "iommu-addresses" property
- defines carveout regions in the IOVA space for the given device. This
- can be useful if a certain memory region should not be mapped through
- the IOMMU.
-
- no-map:
- type: boolean
- description: >
- Indicates the operating system must not create a virtual mapping
- of the region as part of its standard mapping of system memory,
- nor permit speculative access to it under any circumstances other
- than under the control of the device driver using the region.
-
- reusable:
- type: boolean
- description: >
- The operating system can use the memory in this region with the
- limitation that the device driver(s) owning the region need to be
- able to reclaim it back. Typically that means that the operating
- system can use that region to store volatile or cached data that
- can be otherwise regenerated or migrated elsewhere.
-
-allOf:
- - if:
- required:
- - no-map
-
- then:
- not:
- required:
- - reusable
-
- - if:
- required:
- - reusable
-
- then:
- not:
- required:
- - no-map
-
-oneOf:
- - oneOf:
- - required:
- - reg
-
- - required:
- - size
-
- - oneOf:
- # IOMMU reservations
- - required:
- - iommu-addresses
-
- # IOMMU mappings
- - required:
- - reg
- - iommu-addresses
-
-additionalProperties: true
-
-examples:
- - |
- / {
- compatible = "foo";
- model = "foo";
-
- #address-cells = <2>;
- #size-cells = <2>;
-
- reserved-memory {
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- adsp_resv: reservation-adsp {
- /*
- * Restrict IOVA mappings for ADSP buffers to the 512 MiB region
- * from 0x40000000 - 0x5fffffff. Anything outside is reserved by
- * the ADSP for I/O memory and private memory allocations.
- */
- iommu-addresses = <&adsp 0x0 0x00000000 0x00 0x40000000>,
- <&adsp 0x0 0x60000000 0xff 0xa0000000>;
- };
-
- fb: framebuffer@90000000 {
- reg = <0x0 0x90000000 0x0 0x00800000>;
- iommu-addresses = <&dc0 0x0 0x90000000 0x0 0x00800000>;
- };
- };
-
- bus@0 {
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x0 0x0 0x0 0x40000000>;
-
- adsp: adsp@2990000 {
- reg = <0x2990000 0x2000>;
- memory-region = <&adsp_resv>;
- };
-
- dc0: display@15200000 {
- reg = <0x15200000 0x10000>;
- memory-region = <&fb>;
- };
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/reserved-memory/shared-dma-pool.yaml b/Documentation/devicetree/bindings/reserved-memory/shared-dma-pool.yaml
deleted file mode 100644
index 457de0920cd1..000000000000
--- a/Documentation/devicetree/bindings/reserved-memory/shared-dma-pool.yaml
+++ /dev/null
@@ -1,97 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/reserved-memory/shared-dma-pool.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: /reserved-memory DMA pool
-
-maintainers:
- - devicetree-spec@vger.kernel.org
-
-allOf:
- - $ref: reserved-memory.yaml
-
-properties:
- compatible:
- oneOf:
- - const: shared-dma-pool
- description: >
- This indicates a region of memory meant to be used as a shared
- pool of DMA buffers for a set of devices. It can be used by an
- operating system to instantiate the necessary pool management
- subsystem if necessary.
-
- - const: restricted-dma-pool
- description: >
- This indicates a region of memory meant to be used as a pool
- of restricted DMA buffers for a set of devices. The memory
- region would be the only region accessible to those devices.
- When using this, the no-map and reusable properties must not
- be set, so the operating system can create a virtual mapping
- that will be used for synchronization. The main purpose for
- restricted DMA is to mitigate the lack of DMA access control
- on systems without an IOMMU, which could result in the DMA
- accessing the system memory at unexpected times and/or
- unexpected addresses, possibly leading to data leakage or
- corruption. The feature on its own provides a basic level of
- protection against the DMA overwriting buffer contents at
- unexpected times. However, to protect against general data
- leakage and system memory corruption, the system needs to
- provide way to lock down the memory access, e.g., MPU. Note
- that since coherent allocation needs remapping, one must set
- up another device coherent pool by shared-dma-pool and use
- dma_alloc_from_dev_coherent instead for atomic coherent
- allocation.
-
- linux,cma-default:
- type: boolean
- description: >
- If this property is present, then Linux will use the region for
- the default pool of the contiguous memory allocator.
-
- linux,dma-default:
- type: boolean
- description: >
- If this property is present, then Linux will use the region for
- the default pool of the consistent DMA allocator.
-
-if:
- properties:
- compatible:
- contains:
- const: restricted-dma-pool
-then:
- properties:
- no-map: false
- reusable: false
-
-unevaluatedProperties: false
-
-examples:
- - |
- reserved-memory {
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- /* global autoconfigured region for contiguous allocations */
- linux,cma {
- compatible = "shared-dma-pool";
- reusable;
- size = <0x4000000>;
- alignment = <0x2000>;
- linux,cma-default;
- };
-
- display_reserved: framebuffer@78000000 {
- reg = <0x78000000 0x800000>;
- };
-
- restricted_dma_reserved: restricted-dma-pool@50000000 {
- compatible = "restricted-dma-pool";
- reg = <0x50000000 0x4000000>;
- };
- };
-
-...
diff --git a/Documentation/devicetree/bindings/riscv/cpus.yaml b/Documentation/devicetree/bindings/riscv/cpus.yaml
index 97e8441eda1c..f392e367d673 100644
--- a/Documentation/devicetree/bindings/riscv/cpus.yaml
+++ b/Documentation/devicetree/bindings/riscv/cpus.yaml
@@ -47,6 +47,7 @@ properties:
- sifive,u74-mc
- thead,c906
- thead,c910
+ - thead,c920
- const: riscv
- items:
- enum:
diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml
index cc1f546fdbdc..c91ab0e46648 100644
--- a/Documentation/devicetree/bindings/riscv/extensions.yaml
+++ b/Documentation/devicetree/bindings/riscv/extensions.yaml
@@ -128,6 +128,12 @@ properties:
changes to interrupts as frozen at commit ccbddab ("Merge pull
request #42 from riscv/jhauser-2023-RC4") of riscv-aia.
+ - const: smstateen
+ description: |
+ The standard Smstateen extension for controlling access to CSRs
+ added by other RISC-V extensions in H/S/VS/U/VU modes and as
+ ratified at commit a28bfae (Ratified (#7)) of riscv-state-enable.
+
- const: ssaia
description: |
The standard Ssaia supervisor-level extension for the advanced
@@ -212,6 +218,12 @@ properties:
ratified in the 20191213 version of the unprivileged ISA
specification.
+ - const: zicond
+ description:
+ The standard Zicond extension for conditional arithmetic and
+ conditional-select/move operations as ratified in commit 95cf1f9
+ ("Add changes requested by Ved during signoff") of riscv-zicond.
+
- const: zicsr
description: |
The standard Zicsr extension for control and status register
diff --git a/Documentation/devicetree/bindings/riscv/sophgo.yaml b/Documentation/devicetree/bindings/riscv/sophgo.yaml
new file mode 100644
index 000000000000..86748c5390be
--- /dev/null
+++ b/Documentation/devicetree/bindings/riscv/sophgo.yaml
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/riscv/sophgo.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sophgo SoC-based boards
+
+maintainers:
+ - Chao Wei <chao.wei@sophgo.com>
+ - Chen Wang <unicorn_wang@outlook.com>
+
+description:
+ Sophgo SoC-based boards
+
+properties:
+ $nodename:
+ const: '/'
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - milkv,duo
+ - const: sophgo,cv1800b
+ - items:
+ - enum:
+ - milkv,pioneer
+ - const: sophgo,sg2042
+
+additionalProperties: true
+
+...
diff --git a/Documentation/devicetree/bindings/rng/amlogic,meson-rng.yaml b/Documentation/devicetree/bindings/rng/amlogic,meson-rng.yaml
index 457a6e43d810..afa52af442a7 100644
--- a/Documentation/devicetree/bindings/rng/amlogic,meson-rng.yaml
+++ b/Documentation/devicetree/bindings/rng/amlogic,meson-rng.yaml
@@ -14,6 +14,7 @@ properties:
compatible:
enum:
- amlogic,meson-rng
+ - amlogic,meson-s4-rng
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml b/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml
index 187b172d0cca..717f6b321f88 100644
--- a/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml
+++ b/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml
@@ -15,7 +15,9 @@ maintainers:
properties:
compatible:
- const: st,stm32-rng
+ enum:
+ - st,stm32-rng
+ - st,stm32mp13-rng
reg:
maxItems: 1
@@ -30,11 +32,27 @@ properties:
type: boolean
description: If set enable the clock detection management
+ st,rng-lock-conf:
+ type: boolean
+ description: If set, the RNG configuration in RNG_CR, RNG_HTCR and
+ RNG_NSCR will be locked.
+
required:
- compatible
- reg
- clocks
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - st,stm32-rng
+ then:
+ properties:
+ st,rng-lock-conf: false
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/rtc/amlogic,meson6-rtc.yaml b/Documentation/devicetree/bindings/rtc/amlogic,meson6-rtc.yaml
index 8bf7d3a9be98..3a4551253e3e 100644
--- a/Documentation/devicetree/bindings/rtc/amlogic,meson6-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/amlogic,meson6-rtc.yaml
@@ -13,6 +13,7 @@ maintainers:
allOf:
- $ref: rtc.yaml#
- $ref: /schemas/nvmem/nvmem.yaml#
+ - $ref: /schemas/nvmem/nvmem-deprecated-cells.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/rtc/cirrus,ep9301-rtc.yaml b/Documentation/devicetree/bindings/rtc/cirrus,ep9301-rtc.yaml
new file mode 100644
index 000000000000..a95f6af2b1c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/cirrus,ep9301-rtc.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/cirrus,ep9301-rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cirrus EP93xx Real Time Clock controller
+
+maintainers:
+ - Hartley Sweeten <hsweeten@visionengravers.com>
+ - Alexander Sverdlin <alexander.sverdlin@gmail.com>
+
+allOf:
+ - $ref: rtc.yaml#
+
+properties:
+ compatible:
+ oneOf:
+ - const: cirrus,ep9301-rtc
+ - items:
+ - enum:
+ - cirrus,ep9302-rtc
+ - cirrus,ep9307-rtc
+ - cirrus,ep9312-rtc
+ - cirrus,ep9315-rtc
+ - const: cirrus,ep9301-rtc
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ rtc@80920000 {
+ compatible = "cirrus,ep9301-rtc";
+ reg = <0x80920000 0x100>;
+ };
diff --git a/Documentation/devicetree/bindings/rtc/epson,rtc7301.txt b/Documentation/devicetree/bindings/rtc/epson,rtc7301.txt
deleted file mode 100644
index 5f9df3f1467c..000000000000
--- a/Documentation/devicetree/bindings/rtc/epson,rtc7301.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-EPSON TOYOCOM RTC-7301SF/DG
-
-Required properties:
-
-- compatible: Should be "epson,rtc7301sf" or "epson,rtc7301dg"
-- reg: Specifies base physical address and size of the registers.
-- interrupts: A single interrupt specifier.
-
-Example:
-
-rtc: rtc@44a00000 {
- compatible = "epson,rtc7301dg";
- reg = <0x44a00000 0x10000>;
- interrupt-parent = <&axi_intc_0>;
- interrupts = <3 2>;
-};
diff --git a/Documentation/devicetree/bindings/rtc/epson,rtc7301.yaml b/Documentation/devicetree/bindings/rtc/epson,rtc7301.yaml
new file mode 100644
index 000000000000..bdb5cadb31cc
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/epson,rtc7301.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/epson,rtc7301.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Epson Toyocom RTC-7301SF/DG
+
+description:
+ The only difference between the two variants is the packaging.
+ The DG variant is a DIL package, and the SF variant is a flat
+ package.
+
+maintainers:
+ - Akinobu Mita <akinobu.mita@gmail.com>
+
+properties:
+ compatible:
+ enum:
+ - epson,rtc7301dg
+ - epson,rtc7301sf
+
+ reg:
+ maxItems: 1
+
+ reg-io-width:
+ description:
+ The size (in bytes) of the IO accesses that should be performed
+ on the device.
+ enum: [1, 4]
+ default: 4
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ rtc: rtc@44a00000 {
+ compatible = "epson,rtc7301dg";
+ reg = <0x44a00000 0x10000>;
+ reg-io-width = <4>;
+ interrupt-parent = <&axi_intc_0>;
+ interrupts = <3 2>;
+ };
diff --git a/Documentation/devicetree/bindings/rtc/maxim,mcp795.txt b/Documentation/devicetree/bindings/rtc/maxim,mcp795.txt
deleted file mode 100644
index a59fdd8c236d..000000000000
--- a/Documentation/devicetree/bindings/rtc/maxim,mcp795.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-* Maxim MCP795 SPI Serial Real-Time Clock
-
-Required properties:
-- compatible: Should contain "maxim,mcp795".
-- reg: SPI address for chip
-
-Example:
- mcp795: rtc@0 {
- compatible = "maxim,mcp795";
- reg = <0>;
- };
diff --git a/Documentation/devicetree/bindings/rtc/microcrystal,rv3032.yaml b/Documentation/devicetree/bindings/rtc/microcrystal,rv3032.yaml
index 27a9de10f0af..7680089d1d92 100644
--- a/Documentation/devicetree/bindings/rtc/microcrystal,rv3032.yaml
+++ b/Documentation/devicetree/bindings/rtc/microcrystal,rv3032.yaml
@@ -38,6 +38,8 @@ properties:
- 3000
- 4400
+ wakeup-source: true
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/rtc/mstar,ssd202d-rtc.yaml b/Documentation/devicetree/bindings/rtc/mstar,ssd202d-rtc.yaml
new file mode 100644
index 000000000000..4c1f22ef5a2c
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/mstar,ssd202d-rtc.yaml
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/mstar,ssd202d-rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mstar SSD202D Real Time Clock
+
+maintainers:
+ - Daniel Palmer <daniel@0x0f.com>
+ - Romain Perier <romain.perier@gmail.com>
+
+allOf:
+ - $ref: rtc.yaml#
+
+properties:
+ compatible:
+ enum:
+ - mstar,ssd202d-rtc
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ rtc@6800 {
+ compatible = "mstar,ssd202d-rtc";
+ reg = <0x6800 0x200>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf2123.yaml b/Documentation/devicetree/bindings/rtc/nxp,pcf2123.yaml
new file mode 100644
index 000000000000..96e377a4d1bc
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/nxp,pcf2123.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/nxp,pcf2123.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP PCF2123 SPI Real Time Clock
+
+maintainers:
+ - Javier Carrasco <javier.carrasco.cruz@gmail.com>
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+ - $ref: rtc.yaml#
+
+properties:
+ compatible:
+ enum:
+ - nxp,pcf2123
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@3 {
+ compatible = "nxp,pcf2123";
+ reg = <3>;
+ interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_LOW>;
+ spi-cs-high;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf8523.txt b/Documentation/devicetree/bindings/rtc/nxp,pcf8523.txt
deleted file mode 100644
index 0b1080c60f63..000000000000
--- a/Documentation/devicetree/bindings/rtc/nxp,pcf8523.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-* NXP PCF8523 Real Time Clock
-
-Required properties:
-- compatible: Should contain "nxp,pcf8523".
-- reg: I2C address for chip.
-
-Optional property:
-- quartz-load-femtofarads: The capacitive load of the quartz(x-tal),
- expressed in femto Farad (fF). Valid values are 7000 and 12500.
- Default value (if no value is specified) is 12500fF.
-
-Example:
-
-pcf8523: rtc@68 {
- compatible = "nxp,pcf8523";
- reg = <0x68>;
- quartz-load-femtofarads = <7000>;
-};
diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf8523.yaml b/Documentation/devicetree/bindings/rtc/nxp,pcf8523.yaml
new file mode 100644
index 000000000000..d11c8bc16bc0
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/nxp,pcf8523.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/nxp,pcf8523.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP PCF8523 Real Time Clock
+
+maintainers:
+ - Sam Ravnborg <sam@ravnborg.org>
+
+allOf:
+ - $ref: rtc.yaml#
+
+properties:
+ compatible:
+ const: nxp,pcf8523
+
+ reg:
+ maxItems: 1
+
+ quartz-load-femtofarads:
+ description:
+ The capacitive load of the crystal, expressed in femto Farad (fF).
+ enum: [ 7000, 12500 ]
+ default: 12500
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@68 {
+ compatible = "nxp,pcf8523";
+ reg = <0x68>;
+ quartz-load-femtofarads = <7000>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt b/Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt
deleted file mode 100644
index 7371f525a687..000000000000
--- a/Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-NXP PCF2123 SPI Real Time Clock
-
-Required properties:
-- compatible: should be: "nxp,pcf2123"
- or "microcrystal,rv2123"
-- reg: should be the SPI slave chipselect address
-
-Optional properties:
-- spi-cs-high: PCF2123 needs chipselect high
-
-Example:
-
-pcf2123: rtc@3 {
- compatible = "nxp,pcf2123"
- reg = <3>
- spi-cs-high;
-};
diff --git a/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml b/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml
index 2a65f31ac5a0..c9e3c5262c21 100644
--- a/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml
@@ -45,6 +45,8 @@ properties:
- isil,isl1208
# Intersil ISL1218 Low Power RTC with Battery Backed SRAM
- isil,isl1218
+ # SPI-BUS INTERFACE REAL TIME CLOCK MODULE
+ - maxim,mcp795
# Real Time Clock Module with I2C-Bus
- microcrystal,rv3029
# Real Time Clock
diff --git a/Documentation/devicetree/bindings/serial/esp,esp32-acm.yaml b/Documentation/devicetree/bindings/serial/esp,esp32-acm.yaml
new file mode 100644
index 000000000000..77fbb2c72171
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/esp,esp32-acm.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/serial/esp,esp32-acm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ESP32S3 ACM gadget controller
+
+maintainers:
+ - Max Filippov <jcmvbkbc@gmail.com>
+
+description:
+ Fixed function USB CDC-ACM gadget controller of the Espressif ESP32S3 SoC.
+
+allOf:
+ - $ref: serial.yaml#
+
+properties:
+ compatible:
+ const: esp,esp32s3-acm
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ serial@60038000 {
+ compatible = "esp,esp32s3-acm";
+ reg = <0x60038000 0x1000>;
+ interrupts = <96 3 0>;
+ };
diff --git a/Documentation/devicetree/bindings/serial/esp,esp32-uart.yaml b/Documentation/devicetree/bindings/serial/esp,esp32-uart.yaml
new file mode 100644
index 000000000000..2a80ca997a0c
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/esp,esp32-uart.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/serial/esp,esp32-uart.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ESP32xx UART controllers
+
+maintainers:
+ - Max Filippov <jcmvbkbc@gmail.com>
+
+description:
+ ESP32 UART controller is a part of the ESP32 SoC.
+ ESP32S3 UART controller is a part of the ESP32S3 SoC.
+ Both SoCs are produced by Espressif Systems Co. Ltd.
+
+allOf:
+ - $ref: serial.yaml#
+
+properties:
+ compatible:
+ enum:
+ - esp,esp32-uart
+ - esp,esp32s3-uart
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+
+additionalProperties: false
+
+examples:
+ - |
+ serial@60000000 {
+ compatible = "esp,esp32s3-uart";
+ reg = <0x60000000 0x80>;
+ interrupts = <27 1 0>;
+ clocks = <&serial_clk>;
+ };
diff --git a/Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml b/Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml
index 40414247d61a..83035553044a 100644
--- a/Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml
@@ -70,6 +70,8 @@ properties:
interrupts:
maxItems: 1
+ wakeup-source: true
+
fsl,dte-mode:
$ref: /schemas/types.yaml#/definitions/flag
description: |
diff --git a/Documentation/devicetree/bindings/serial/fsl-mxs-auart.yaml b/Documentation/devicetree/bindings/serial/fsl-mxs-auart.yaml
index 6a400a5e6fc7..da032effffe6 100644
--- a/Documentation/devicetree/bindings/serial/fsl-mxs-auart.yaml
+++ b/Documentation/devicetree/bindings/serial/fsl-mxs-auart.yaml
@@ -14,10 +14,13 @@ allOf:
properties:
compatible:
- enum:
- - fsl,imx23-auart
- - fsl,imx28-auart
- - alphascale,asm9260-auart
+ oneOf:
+ - const: fsl,imx23-auart
+ - const: alphascale,asm9260-auart
+ - items:
+ - enum:
+ - fsl,imx28-auart
+ - const: fsl,imx23-auart
reg:
maxItems: 1
@@ -82,7 +85,7 @@ examples:
};
auart0: serial@8006a000 {
- compatible = "fsl,imx28-auart";
+ compatible = "fsl,imx28-auart", "fsl,imx23-auart";
reg = <0x8006a000 0x2000>;
interrupts = <112>;
dmas = <&dma_apbx 8>, <&dma_apbx 9>;
diff --git a/Documentation/devicetree/bindings/serial/maxim,max310x.txt b/Documentation/devicetree/bindings/serial/maxim,max310x.txt
deleted file mode 100644
index 79e10a05a96a..000000000000
--- a/Documentation/devicetree/bindings/serial/maxim,max310x.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-* Maxim MAX310X advanced Universal Asynchronous Receiver-Transmitter (UART)
-
-Required properties:
-- compatible: Should be one of the following:
- - "maxim,max3107" for Maxim MAX3107,
- - "maxim,max3108" for Maxim MAX3108,
- - "maxim,max3109" for Maxim MAX3109,
- - "maxim,max14830" for Maxim MAX14830.
-- reg: SPI chip select number.
-- interrupts: Specifies the interrupt source of the parent interrupt
- controller. The format of the interrupt specifier depends on the
- parent interrupt controller.
-- clocks: phandle to the IC source clock.
-- clock-names: Should be "xtal" if clock is an external crystal or
- "osc" if an external clock source is used.
-
-Optional properties:
-- gpio-controller: Marks the device node as a GPIO controller.
-- #gpio-cells: Should be two. The first cell is the GPIO number and
- the second cell is used to specify the GPIO polarity:
- 0 = active high,
- 1 = active low.
-
-Example:
-
-/ {
- clocks {
- spi_uart_clk: osc_max14830 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <3686400>;
- };
-
- };
-};
-
-&spi0 {
- max14830: max14830@0 {
- compatible = "maxim,max14830";
- reg = <0>;
- clocks = <&spi_uart_clk>;
- clock-names = "osc";
- interrupt-parent = <&gpio3>;
- interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
- gpio-controller;
- #gpio-cells = <2>;
- };
-};
diff --git a/Documentation/devicetree/bindings/serial/maxim,max310x.yaml b/Documentation/devicetree/bindings/serial/maxim,max310x.yaml
new file mode 100644
index 000000000000..889eeaca64a0
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/maxim,max310x.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/serial/maxim,max310x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim MAX310X Advanced Universal Asynchronous Receiver-Transmitter (UART)
+
+maintainers:
+ - Hugo Villeneuve <hvilleneuve@dimonoff.com>
+
+properties:
+ compatible:
+ enum:
+ - maxim,max3107
+ - maxim,max3108
+ - maxim,max3109
+ - maxim,max14830
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ enum:
+ - xtal # External crystal
+ - osc # External clock source
+
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 2
+
+ gpio-line-names:
+ minItems: 1
+ maxItems: 16
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+ - $ref: /schemas/serial/serial.yaml#
+ - $ref: /schemas/serial/rs485.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ serial@2c {
+ compatible = "maxim,max3107";
+ reg = <0x2c>;
+ clocks = <&xtal4m>;
+ clock-names = "xtal";
+ interrupt-parent = <&gpio3>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/serial/nvidia,tegra20-hsuart.yaml b/Documentation/devicetree/bindings/serial/nvidia,tegra20-hsuart.yaml
index 04d55fecf47c..a5d67563cd53 100644
--- a/Documentation/devicetree/bindings/serial/nvidia,tegra20-hsuart.yaml
+++ b/Documentation/devicetree/bindings/serial/nvidia,tegra20-hsuart.yaml
@@ -91,11 +91,6 @@ properties:
- description: range upper bound
- description: adjustment (in permyriad, i.e. 0.01%)
-allOf:
- - $ref: serial.yaml
-
-unevaluatedProperties: false
-
required:
- compatible
- reg
@@ -106,6 +101,11 @@ required:
- dmas
- dma-names
+allOf:
+ - $ref: serial.yaml
+
+unevaluatedProperties: false
+
examples:
- |
#include <dt-bindings/clock/tegra30-car.h>
diff --git a/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt b/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt
deleted file mode 100644
index 1a7e4bff0456..000000000000
--- a/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt
+++ /dev/null
@@ -1,118 +0,0 @@
-* NXP SC16IS7xx advanced Universal Asynchronous Receiver-Transmitter (UART)
-* i2c as bus
-
-Required properties:
-- compatible: Should be one of the following:
- - "nxp,sc16is740" for NXP SC16IS740,
- - "nxp,sc16is741" for NXP SC16IS741,
- - "nxp,sc16is750" for NXP SC16IS750,
- - "nxp,sc16is752" for NXP SC16IS752,
- - "nxp,sc16is760" for NXP SC16IS760,
- - "nxp,sc16is762" for NXP SC16IS762.
-- reg: I2C address of the SC16IS7xx device.
-- interrupts: Should contain the UART interrupt
-- clocks: Reference to the IC source clock.
- OR (when there is no clock provider visible to the platform)
-- clock-frequency: The source clock frequency for the IC.
-
-Optional properties:
-- gpio-controller: Marks the device node as a GPIO controller.
-- #gpio-cells: Should be two. The first cell is the GPIO number and
- the second cell is used to specify the GPIO polarity:
- 0 = active high,
- 1 = active low.
-- irda-mode-ports: An array that lists the indices of the port that
- should operate in IrDA mode.
-- nxp,modem-control-line-ports: An array that lists the indices of the port that
- should have shared GPIO lines configured as
- modem control lines.
-
-Example:
- sc16is750: sc16is750@51 {
- compatible = "nxp,sc16is750";
- reg = <0x51>;
- clocks = <&clk20m>;
- interrupt-parent = <&gpio3>;
- interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
- gpio-controller;
- #gpio-cells = <2>;
- };
-
- sc16is752: sc16is752@53 {
- compatible = "nxp,sc16is752";
- reg = <0x53>;
- clocks = <&clk20m>;
- interrupt-parent = <&gpio3>;
- interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
- nxp,modem-control-line-ports = <1>; /* Port 1 as modem control lines */
- gpio-controller; /* Port 0 as GPIOs */
- #gpio-cells = <2>;
- };
-
- sc16is752: sc16is752@54 {
- compatible = "nxp,sc16is752";
- reg = <0x54>;
- clocks = <&clk20m>;
- interrupt-parent = <&gpio3>;
- interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
- nxp,modem-control-line-ports = <0 1>; /* Ports 0 and 1 as modem control lines */
- };
-
-* spi as bus
-
-Required properties:
-- compatible: Should be one of the following:
- - "nxp,sc16is740" for NXP SC16IS740,
- - "nxp,sc16is741" for NXP SC16IS741,
- - "nxp,sc16is750" for NXP SC16IS750,
- - "nxp,sc16is752" for NXP SC16IS752,
- - "nxp,sc16is760" for NXP SC16IS760,
- - "nxp,sc16is762" for NXP SC16IS762.
-- reg: SPI chip select number.
-- interrupts: Specifies the interrupt source of the parent interrupt
- controller. The format of the interrupt specifier depends on the
- parent interrupt controller.
-- clocks: phandle to the IC source clock.
-
-Optional properties:
-- gpio-controller: Marks the device node as a GPIO controller.
-- #gpio-cells: Should be two. The first cell is the GPIO number and
- the second cell is used to specify the GPIO polarity:
- 0 = active high,
- 1 = active low.
-- irda-mode-ports: An array that lists the indices of the port that
- should operate in IrDA mode.
-- nxp,modem-control-line-ports: An array that lists the indices of the port that
- should have shared GPIO lines configured as
- modem control lines.
-
-Example:
- sc16is750: sc16is750@0 {
- compatible = "nxp,sc16is750";
- reg = <0>;
- clocks = <&clk20m>;
- interrupt-parent = <&gpio3>;
- interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
- gpio-controller;
- #gpio-cells = <2>;
- };
-
- sc16is752: sc16is752@1 {
- compatible = "nxp,sc16is752";
- reg = <1>;
- clocks = <&clk20m>;
- interrupt-parent = <&gpio3>;
- interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
- nxp,modem-control-line-ports = <1>; /* Port 1 as modem control lines */
- gpio-controller; /* Port 0 as GPIOs */
- #gpio-cells = <2>;
- };
-
- sc16is752: sc16is752@2 {
- compatible = "nxp,sc16is752";
- reg = <2>;
- clocks = <&clk20m>;
- interrupt-parent = <&gpio3>;
- interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
- nxp,modem-control-line-ports = <0 1>; /* Ports 0 and 1 as modem control lines */
- };
diff --git a/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.yaml b/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.yaml
new file mode 100644
index 000000000000..5dec15b7e7c3
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.yaml
@@ -0,0 +1,127 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/serial/nxp,sc16is7xx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP SC16IS7xx Advanced Universal Asynchronous Receiver-Transmitter (UART)
+
+maintainers:
+ - Hugo Villeneuve <hvilleneuve@dimonoff.com>
+
+properties:
+ compatible:
+ enum:
+ - nxp,sc16is740
+ - nxp,sc16is741
+ - nxp,sc16is750
+ - nxp,sc16is752
+ - nxp,sc16is760
+ - nxp,sc16is762
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-frequency:
+ description:
+ When there is no clock provider visible to the platform, this
+ is the source crystal or external clock frequency for the IC in Hz.
+ minimum: 1
+ maximum: 80000000
+
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 2
+
+ gpio-line-names:
+ minItems: 1
+ maxItems: 8
+
+ irda-mode-ports:
+ description: |
+ An array that lists the indices of the port that should operate in IrDA
+ mode:
+ 0: port A
+ 1: port B
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 1
+ maxItems: 2
+ items:
+ minimum: 0
+ maximum: 1
+
+ nxp,modem-control-line-ports:
+ description: |
+ An array that lists the indices of the port that should have shared GPIO
+ lines configured as modem control lines:
+ 0: port A
+ 1: port B
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 1
+ maxItems: 2
+ items:
+ minimum: 0
+ maximum: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+ - $ref: /schemas/serial/serial.yaml#
+ - $ref: /schemas/serial/rs485.yaml#
+
+oneOf:
+ - required:
+ - clocks
+ - required:
+ - clock-frequency
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ serial@51 {
+ compatible = "nxp,sc16is750";
+ reg = <0x51>;
+ clocks = <&clk20m>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ serial@53 {
+ compatible = "nxp,sc16is752";
+ reg = <0x53>;
+ clocks = <&clk20m>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+ nxp,modem-control-line-ports = <1>; /* Port 1 as modem control lines */
+ gpio-controller; /* Port 0 as GPIOs */
+ #gpio-cells = <2>;
+ };
+
+ serial@54 {
+ compatible = "nxp,sc16is752";
+ reg = <0x54>;
+ clocks = <&clk20m>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+ nxp,modem-control-line-ports = <0 1>; /* Ports 0 and 1 as modem control lines */
+ };
+ };
diff --git a/Documentation/devicetree/bindings/serial/qcom,msm-uart.yaml b/Documentation/devicetree/bindings/serial/qcom,msm-uart.yaml
index a052aaef21f4..ea6abfe2d95e 100644
--- a/Documentation/devicetree/bindings/serial/qcom,msm-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/qcom,msm-uart.yaml
@@ -40,11 +40,11 @@ required:
- interrupts
- reg
-unevaluatedProperties: false
-
allOf:
- $ref: /schemas/serial/serial.yaml#
+unevaluatedProperties: false
+
examples:
- |
serial@a9c00000 {
diff --git a/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.yaml b/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.yaml
index 484b9a51f6a9..ee52bf8e8917 100644
--- a/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.yaml
+++ b/Documentation/devicetree/bindings/serial/qcom,msm-uartdm.yaml
@@ -78,8 +78,6 @@ required:
- interrupts
- reg
-unevaluatedProperties: false
-
allOf:
- $ref: /schemas/serial/serial.yaml#
@@ -97,6 +95,8 @@ allOf:
reg:
maxItems: 1
+unevaluatedProperties: false
+
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
diff --git a/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml b/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml
index 3fc2601f1338..89f1eb0f2c5a 100644
--- a/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml
@@ -38,6 +38,13 @@ properties:
- const: sclk
- const: pclk
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+
allOf:
- $ref: serial.yaml#
@@ -53,13 +60,6 @@ allOf:
clock-names:
minItems: 2
-required:
- - compatible
- - reg
- - interrupts
- - clocks
- - clock-names
-
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/serial/renesas,hscif.yaml b/Documentation/devicetree/bindings/serial/renesas,hscif.yaml
index 1c7f1276aed6..2046e2dc0a3d 100644
--- a/Documentation/devicetree/bindings/serial/renesas,hscif.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,hscif.yaml
@@ -111,8 +111,6 @@ required:
- clock-names
- power-domains
-unevaluatedProperties: false
-
if:
properties:
compatible:
@@ -125,6 +123,8 @@ then:
required:
- resets
+unevaluatedProperties: false
+
examples:
- |
#include <dt-bindings/clock/r8a7795-cpg-mssr.h>
diff --git a/Documentation/devicetree/bindings/serial/renesas,scif.yaml b/Documentation/devicetree/bindings/serial/renesas,scif.yaml
index 99030fc18c45..4610a5bd580c 100644
--- a/Documentation/devicetree/bindings/serial/renesas,scif.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,scif.yaml
@@ -79,6 +79,7 @@ properties:
- enum:
- renesas,scif-r9a07g043 # RZ/G2UL and RZ/Five
- renesas,scif-r9a07g054 # RZ/V2L
+ - renesas,scif-r9a08g045 # RZ/G3S
- const: renesas,scif-r9a07g044 # RZ/G2{L,LC} fallback
reg:
diff --git a/Documentation/devicetree/bindings/serial/renesas,scifa.yaml b/Documentation/devicetree/bindings/serial/renesas,scifa.yaml
index 499507678cdf..c98657cf4666 100644
--- a/Documentation/devicetree/bindings/serial/renesas,scifa.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,scifa.yaml
@@ -77,8 +77,6 @@ required:
- clock-names
- power-domains
-unevaluatedProperties: false
-
if:
properties:
compatible:
@@ -89,6 +87,8 @@ then:
required:
- resets
+unevaluatedProperties: false
+
examples:
- |
#include <dt-bindings/clock/r8a7790-cpg-mssr.h>
diff --git a/Documentation/devicetree/bindings/serial/renesas,scifb.yaml b/Documentation/devicetree/bindings/serial/renesas,scifb.yaml
index 810d8a991fdd..fb695b3111ac 100644
--- a/Documentation/devicetree/bindings/serial/renesas,scifb.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,scifb.yaml
@@ -77,8 +77,6 @@ required:
- clock-names
- power-domains
-unevaluatedProperties: false
-
if:
properties:
compatible:
@@ -89,6 +87,8 @@ then:
required:
- resets
+unevaluatedProperties: false
+
examples:
- |
#include <dt-bindings/clock/r8a7740-clock.h>
diff --git a/Documentation/devicetree/bindings/serial/rs485.yaml b/Documentation/devicetree/bindings/serial/rs485.yaml
index 303a443d9e29..9418fd66a8e9 100644
--- a/Documentation/devicetree/bindings/serial/rs485.yaml
+++ b/Documentation/devicetree/bindings/serial/rs485.yaml
@@ -29,6 +29,10 @@ properties:
default: 0
maximum: 100
+ rs485-rts-active-high:
+ description: drive RTS high when sending (this is the default).
+ $ref: /schemas/types.yaml#/definitions/flag
+
rs485-rts-active-low:
description: drive RTS low when sending (default is high).
$ref: /schemas/types.yaml#/definitions/flag
diff --git a/Documentation/devicetree/bindings/serial/samsung_uart.yaml b/Documentation/devicetree/bindings/serial/samsung_uart.yaml
index 8bd88d5cbb11..ac60ab1e35e3 100644
--- a/Documentation/devicetree/bindings/serial/samsung_uart.yaml
+++ b/Documentation/devicetree/bindings/serial/samsung_uart.yaml
@@ -24,9 +24,6 @@ properties:
- enum:
- apple,s5l-uart
- axis,artpec8-uart
- - samsung,s3c2410-uart
- - samsung,s3c2412-uart
- - samsung,s3c2440-uart
- samsung,s3c6400-uart
- samsung,s5pv210-uart
- samsung,exynos4210-uart
@@ -86,8 +83,6 @@ required:
- interrupts
- reg
-unevaluatedProperties: false
-
allOf:
- $ref: serial.yaml#
@@ -96,7 +91,6 @@ allOf:
compatible:
contains:
enum:
- - samsung,s3c2410-uart
- samsung,s5pv210-uart
then:
properties:
@@ -128,6 +122,8 @@ allOf:
- const: uart
- const: clk_uart_baud0
+unevaluatedProperties: false
+
examples:
- |
#include <dt-bindings/clock/samsung,s3c64xx-clock.h>
diff --git a/Documentation/devicetree/bindings/serial/serial.yaml b/Documentation/devicetree/bindings/serial/serial.yaml
index ea277560a596..65804ca274ae 100644
--- a/Documentation/devicetree/bindings/serial/serial.yaml
+++ b/Documentation/devicetree/bindings/serial/serial.yaml
@@ -87,16 +87,8 @@ properties:
description:
TX FIFO threshold configuration (in bytes).
-if:
- required:
- - uart-has-rtscts
-then:
- properties:
- cts-gpios: false
- rts-gpios: false
-
patternProperties:
- "^bluetooth|gnss|gps|mcu$":
+ "^(bluetooth|bluetooth-gnss|gnss|gps|mcu)$":
if:
type: object
then:
@@ -136,6 +128,14 @@ patternProperties:
required:
- compatible
+if:
+ required:
+ - uart-has-rtscts
+then:
+ properties:
+ cts-gpios: false
+ rts-gpios: false
+
additionalProperties: true
examples:
diff --git a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml
index ec888f48cac8..e802e25923aa 100644
--- a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml
+++ b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml
@@ -64,6 +64,7 @@ patternProperties:
description:
A channel managed by this controller
type: object
+ additionalProperties: false
properties:
reg:
@@ -100,6 +101,32 @@ patternProperties:
Channel assigned Rx time-slots within the Rx time-slots routed by the
TSA to this cell.
+ compatible:
+ items:
+ - enum:
+ - fsl,mpc885-scc-qmc-hdlc
+ - fsl,mpc866-scc-qmc-hdlc
+ - const: fsl,cpm1-scc-qmc-hdlc
+ - const: fsl,qmc-hdlc
+
+ fsl,framer:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ phandle to the framer node. The framer is in charge of an E1/T1 line
+ interface connected to the TDM bus. It can be used to get the E1/T1 line
+ status such as link up/down.
+
+ allOf:
+ - if:
+ properties:
+ compatible:
+ not:
+ contains:
+ const: fsl,qmc-hdlc
+ then:
+ properties:
+ fsl,framer: false
+
required:
- reg
- fsl,tx-ts-mask
@@ -137,7 +164,7 @@ examples:
channel@16 {
/* Ch16 : First 4 even TS from all routed from TSA */
reg = <16>;
- fsl,mode = "transparent";
+ fsl,operational-mode = "transparent";
fsl,reverse-data;
fsl,tx-ts-mask = <0x00000000 0x000000aa>;
fsl,rx-ts-mask = <0x00000000 0x000000aa>;
@@ -146,7 +173,7 @@ examples:
channel@17 {
/* Ch17 : First 4 odd TS from all routed from TSA */
reg = <17>;
- fsl,mode = "transparent";
+ fsl,operational-mode = "transparent";
fsl,reverse-data;
fsl,tx-ts-mask = <0x00000000 0x00000055>;
fsl,rx-ts-mask = <0x00000000 0x00000055>;
@@ -154,9 +181,13 @@ examples:
channel@19 {
/* Ch19 : 8 TS (TS 8..15) from all routed from TSA */
+ compatible = "fsl,mpc885-scc-qmc-hdlc",
+ "fsl,cpm1-scc-qmc-hdlc",
+ "fsl,qmc-hdlc";
reg = <19>;
- fsl,mode = "hdlc";
+ fsl,operational-mode = "hdlc";
fsl,tx-ts-mask = <0x00000000 0x0000ff00>;
fsl,rx-ts-mask = <0x00000000 0x0000ff00>;
+ fsl,framer = <&framer>;
};
};
diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mt7986-wo-ccif.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mt7986-wo-ccif.yaml
index f0fa92b04b32..3b212f26abc5 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mt7986-wo-ccif.yaml
+++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mt7986-wo-ccif.yaml
@@ -20,6 +20,7 @@ properties:
items:
- enum:
- mediatek,mt7986-wo-ccif
+ - mediatek,mt7988-wo-ccif
- const: syscon
reg:
diff --git a/Documentation/devicetree/bindings/soc/mediatek/mtk-svs.yaml b/Documentation/devicetree/bindings/soc/mediatek/mtk-svs.yaml
index f21eb907ee90..7eda63d5682f 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/mtk-svs.yaml
+++ b/Documentation/devicetree/bindings/soc/mediatek/mtk-svs.yaml
@@ -22,6 +22,7 @@ properties:
compatible:
enum:
- mediatek,mt8183-svs
+ - mediatek,mt8188-svs
- mediatek,mt8192-svs
reg:
diff --git a/Documentation/devicetree/bindings/soc/nuvoton/nuvoton,gfxi.yaml b/Documentation/devicetree/bindings/soc/nuvoton/nuvoton,gfxi.yaml
new file mode 100644
index 000000000000..0222a43977ab
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/nuvoton/nuvoton,gfxi.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/nuvoton/nuvoton,gfxi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Graphics Core Information block in Nuvoton SoCs
+
+maintainers:
+ - Joseph Liu <kwliu@nuvoton.com>
+ - Marvin Lin <kflin@nuvoton.com>
+
+description:
+ The Graphics Core Information (GFXI) are a block of registers in Nuvoton SoCs
+ that analyzes Graphics core behavior and provides information in registers.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - nuvoton,npcm750-gfxi
+ - nuvoton,npcm845-gfxi
+ - const: syscon
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ gfxi: gfxi@e000 {
+ compatible = "nuvoton,npcm750-gfxi", "syscon";
+ reg = <0xe000 0x100>;
+ };
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml
index 8a4b7ba3aaf6..7b031ef09669 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml
@@ -52,6 +52,8 @@ properties:
iommus:
maxItems: 1
+ dma-coherent: true
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml
index bceb479f74c5..422921cf1f82 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml
@@ -35,6 +35,12 @@ properties:
'#size-cells':
const: 0
+ orientation-gpios:
+ description: Array of input gpios for the Type-C connector orientation indication.
+ The GPIO indication is used to detect the orientation of the Type-C connector.
+ The array should contain a gpio entry for each PMIC Glink connector, in reg order.
+ It is defined that GPIO active level means "CC2" or Reversed/Flipped orientation.
+
patternProperties:
'^connector@\d$':
$ref: /schemas/connector/usb-connector.yaml#
@@ -44,6 +50,19 @@ patternProperties:
required:
- compatible
+allOf:
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sm8450-pmic-glink
+ - qcom,sm8550-pmic-glink
+ then:
+ properties:
+ orientation-gpios: false
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/soc/renesas/renesas,rzg2l-sysc.yaml b/Documentation/devicetree/bindings/soc/renesas/renesas,rzg2l-sysc.yaml
index e52e176d8cb3..4386b2c3fa4d 100644
--- a/Documentation/devicetree/bindings/soc/renesas/renesas,rzg2l-sysc.yaml
+++ b/Documentation/devicetree/bindings/soc/renesas/renesas,rzg2l-sysc.yaml
@@ -23,6 +23,7 @@ properties:
- renesas,r9a07g043-sysc # RZ/G2UL and RZ/Five
- renesas,r9a07g044-sysc # RZ/G2{L,LC}
- renesas,r9a07g054-sysc # RZ/V2L
+ - renesas,r9a08g045-sysc # RZ/G3S
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/soc/renesas/renesas.yaml b/Documentation/devicetree/bindings/soc/renesas/renesas.yaml
index 53b95f348f8e..16ca3ff7b1ae 100644
--- a/Documentation/devicetree/bindings/soc/renesas/renesas.yaml
+++ b/Documentation/devicetree/bindings/soc/renesas/renesas.yaml
@@ -302,7 +302,7 @@ properties:
- description: R-Car E3 (R8A77990)
items:
- enum:
- - renesas,ebisu # Ebisu (RTP0RC77990SEB0010S)
+ - renesas,ebisu # Ebisu (RTP0RC77990SEB0010S), Ebisu-4D (RTP0RC77990SEB0020S)
- const: renesas,r8a77990
- description: R-Car D3 (R8A77995)
@@ -335,6 +335,13 @@ properties:
- const: renesas,spider-cpu
- const: renesas,r8a779f0
+ - description: R-Car S4-8 (R8A779F4)
+ items:
+ - enum:
+ - renesas,s4sk # R-Car S4 Starter Kit board (Y-ASK-RCAR-S4-1000BASE-T#WS12)
+ - const: renesas,r8a779f4
+ - const: renesas,r8a779f0
+
- description: R-Car V4H (R8A779G0)
items:
- enum:
@@ -474,6 +481,25 @@ properties:
- renesas,rzv2mevk2 # RZ/V2M Eval Board v2.0
- const: renesas,r9a09g011
+ - description: RZ/G3S (R9A08G045)
+ items:
+ - enum:
+ - renesas,r9a08g045s33 # PCIe support
+ - const: renesas,r9a08g045
+
+ - description: RZ/G3S SMARC Module (SoM)
+ items:
+ - const: renesas,rzg3s-smarcm # RZ/G3S SMARC Module (SoM)
+ - const: renesas,r9a08g045s33 # PCIe support
+ - const: renesas,r9a08g045
+
+ - description: RZ SMARC Carrier-II Evaluation Kit
+ items:
+ - const: renesas,smarc2-evk # RZ SMARC Carrier-II EVK
+ - const: renesas,rzg3s-smarcm # RZ/G3S SMARC SoM
+ - const: renesas,r9a08g045s33 # PCIe support
+ - const: renesas,r9a08g045
+
additionalProperties: true
...
diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
index e4fa6a07b4fa..1309bf5ae0cd 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
+++ b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
@@ -233,6 +233,7 @@ allOf:
- rockchip,rk3399-grf
- rockchip,rk3399-pmugrf
- rockchip,rk3568-pmugrf
+ - rockchip,rk3588-pmugrf
- rockchip,rv1108-grf
- rockchip,rv1108-pmugrf
diff --git a/Documentation/devicetree/bindings/soc/sti/st,sti-syscon.yaml b/Documentation/devicetree/bindings/soc/sti/st,sti-syscon.yaml
new file mode 100644
index 000000000000..5f97d9ff17fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/sti/st,sti-syscon.yaml
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/sti/st,sti-syscon.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STMicroelectronics STi platform sysconfig
+
+maintainers:
+ - Patrice Chotard <patrice.chotard@foss.st.com>
+
+description: |
+ Binding for the various sysconfig nodes used within the STi
+ platform device-tree to point to some common configuration
+ registers used by other nodes.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - st,stih407-core-syscfg
+ - st,stih407-flash-syscfg
+ - st,stih407-front-syscfg
+ - st,stih407-lpm-syscfg
+ - st,stih407-rear-syscfg
+ - st,stih407-sbc-reg-syscfg
+ - st,stih407-sbc-syscfg
+ - const: syscon
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ syscfg_sbc: syscon@9620000 {
+ compatible = "st,stih407-sbc-syscfg", "syscon";
+ reg = <0x9620000 0x1000>;
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/soc/tegra/nvidia,tegra20-pmc.yaml b/Documentation/devicetree/bindings/soc/tegra/nvidia,tegra20-pmc.yaml
new file mode 100644
index 000000000000..b86f6f53ca95
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/tegra/nvidia,tegra20-pmc.yaml
@@ -0,0 +1,416 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/tegra/nvidia,tegra20-pmc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Tegra Power Management Controller (PMC)
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jonathan Hunter <jonathanh@nvidia.com>
+
+properties:
+ compatible:
+ enum:
+ - nvidia,tegra20-pmc
+ - nvidia,tegra30-pmc
+ - nvidia,tegra114-pmc
+ - nvidia,tegra124-pmc
+ - nvidia,tegra210-pmc
+
+ reg:
+ maxItems: 1
+
+ clock-names:
+ items:
+ # Tegra clock of the same name
+ - const: pclk
+ # 32 KHz clock input
+ - const: clk32k_in
+
+ clocks:
+ maxItems: 2
+
+ '#clock-cells':
+ const: 1
+ description: |
+ Tegra PMC has clk_out_1, clk_out_2, and clk_out_3. PMC also has blink
+ control which allows 32Khz clock output to Tegra blink pad.
+
+ Consumer of PMC clock should specify the desired clock by having the
+ clock ID in its "clocks" phandle cell with PMC clock provider. See
+ include/dt-bindings/soc/tegra-pmc.h for the list of Tegra PMC clock IDs.
+
+ '#interrupt-cells':
+ const: 2
+ description: Specifies number of cells needed to encode an interrupt
+ source.
+
+ interrupt-controller: true
+
+ nvidia,invert-interrupt:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: Inverts the PMU interrupt signal. The PMU is an external Power
+ Management Unit, whose interrupt output signal is fed into the PMC. This
+ signal is optionally inverted, and then fed into the ARM GIC. The PMC is
+ not involved in the detection or handling of this interrupt signal,
+ merely its inversion.
+
+ nvidia,core-power-req-active-high:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: core power request active-high
+
+ nvidia,sys-clock-req-active-high:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: system clock request active-high
+
+ nvidia,combined-power-req:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: combined power request for CPU and core
+
+ nvidia,cpu-pwr-good-en:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: CPU power good signal from external PMIC to PMC is enabled
+
+ nvidia,suspend-mode:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: the suspend mode that the platform should use
+ oneOf:
+ - description: LP0, CPU + Core voltage off and DRAM in self-refresh
+ const: 0
+ - description: LP1, CPU voltage off and DRAM in self-refresh
+ const: 1
+ - description: LP2, CPU voltage off
+ const: 2
+
+ nvidia,cpu-pwr-good-time:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: CPU power good time in microseconds
+
+ nvidia,cpu-pwr-off-time:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: CPU power off time in microseconds
+
+ nvidia,core-pwr-good-time:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description: core power good time in microseconds
+ items:
+ - description: oscillator stable time
+ - description: power stable time
+
+ nvidia,core-pwr-off-time:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: core power off time in microseconds
+
+ nvidia,lp0-vec:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description: |
+ Starting address and length of LP0 vector. The LP0 vector contains the
+ warm boot code that is executed by AVP when resuming from the LP0 state.
+ The AVP (Audio-Video Processor) is an ARM7 processor and always being
+ the first boot processor when chip is power on or resume from deep sleep
+ mode. When the system is resumed from the deep sleep mode, the warm boot
+ code will restore some PLLs, clocks and then brings up CPU0 for resuming
+ the system.
+ items:
+ - description: starting address of LP0 vector
+ - description: length of LP0 vector
+
+ core-supply:
+ description: phandle to voltage regulator connected to the SoC core power
+ rail
+
+ core-domain:
+ type: object
+ description: The vast majority of hardware blocks of Tegra SoC belong to a
+ core power domain, which has a dedicated voltage rail that powers the
+ blocks.
+ additionalProperties: false
+ properties:
+ operating-points-v2:
+ description: Should contain level, voltages and opp-supported-hw
+ property. The supported-hw is a bitfield indicating SoC speedo or
+ process ID mask.
+
+ "#power-domain-cells":
+ const: 0
+
+ required:
+ - operating-points-v2
+ - "#power-domain-cells"
+
+ i2c-thermtrip:
+ type: object
+ description: On Tegra30, Tegra114 and Tegra124 if i2c-thermtrip subnode
+ exists, hardware-triggered thermal reset will be enabled.
+ additionalProperties: false
+ properties:
+ nvidia,i2c-controller-id:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: ID of I2C controller to send poweroff command to PMU.
+ Valid values are described in section 9.2.148 "APBDEV_PMC_SCRATCH53_0"
+ of the Tegra K1 Technical Reference Manual.
+
+ nvidia,bus-addr:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: bus address of the PMU on the I2C bus
+
+ nvidia,reg-addr:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: PMU I2C register address to issue poweroff command
+
+ nvidia,reg-data:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: power-off command to write to PMU
+
+ nvidia,pinmux-id:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Pinmux used by the hardware when issuing power-off command.
+ Defaults to 0. Valid values are described in section 12.5.2 "Pinmux
+ Support" of the Tegra4 Technical Reference Manual.
+
+ required:
+ - nvidia,i2c-controller-id
+ - nvidia,bus-addr
+ - nvidia,reg-addr
+ - nvidia,reg-data
+
+ powergates:
+ type: object
+ additionalProperties: false
+ description: |
+ This node contains a hierarchy of power domain nodes, which should match
+ the powergates on the Tegra SoC. Each powergate node represents a power-
+ domain on the Tegra SoC that can be power-gated by the Tegra PMC.
+
+ Hardware blocks belonging to a power domain should contain "power-domains"
+ property that is a phandle pointing to corresponding powergate node.
+
+ The name of the powergate node should be one of the below. Note that not
+ every powergate is applicable to all Tegra devices and the following list
+ shows which powergates are applicable to which devices.
+
+ Please refer to Tegra TRM for mode details on the powergate nodes to use
+ for each power-gate block inside Tegra.
+
+ Name Description Devices Applicable
+ --------------------------------------------------------------
+ 3d 3D Graphics Tegra20/114/124/210
+ 3d0 3D Graphics 0 Tegra30
+ 3d1 3D Graphics 1 Tegra30
+ aud Audio Tegra210
+ dfd Debug Tegra210
+ dis Display A Tegra114/124/210
+ disb Display B Tegra114/124/210
+ heg 2D Graphics Tegra30/114/124/210
+ iram Internal RAM Tegra124/210
+ mpe MPEG Encode All
+ nvdec NVIDIA Video Decode Engine Tegra210
+ nvjpg NVIDIA JPEG Engine Tegra210
+ pcie PCIE Tegra20/30/124/210
+ sata SATA Tegra30/124/210
+ sor Display interfaces Tegra124/210
+ ve2 Video Encode Engine 2 Tegra210
+ venc Video Encode Engine All
+ vdec Video Decode Engine Tegra20/30/114/124
+ vic Video Imaging Compositor Tegra124/210
+ xusba USB Partition A Tegra114/124/210
+ xusbb USB Partition B Tegra114/124/210
+ xusbc USB Partition C Tegra114/124/210
+
+ patternProperties:
+ "^[a-z0-9]+$":
+ type: object
+ additionalProperties: false
+ properties:
+ clocks:
+ minItems: 1
+ maxItems: 10
+
+ resets:
+ minItems: 1
+ maxItems: 8
+
+ power-domains:
+ maxItems: 1
+
+ '#power-domain-cells':
+ const: 0
+ description: Must be 0.
+
+ required:
+ - clocks
+ - resets
+ - '#power-domain-cells'
+
+ pinmux:
+ type: object
+ additionalProperties:
+ type: object
+ description: |
+ This is a pad configuration node. On Tegra SoCs a pad is a set of pins
+ which are configured as a group. The pin grouping is a fixed attribute
+ of the hardware. The PMC can be used to set pad power state and
+ signaling voltage. A pad can be either in active or power down mode.
+ The support for power state and signaling voltage configuration varies
+ depending on the pad in question. 3.3V and 1.8V signaling voltages are
+ supported on pins where software controllable signaling voltage
+ switching is available.
+
+ The pad configuration state nodes are placed under the pmc node and
+ they are referred to by the pinctrl client properties. For more
+ information see:
+
+ Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+
+ The pad name should be used as the value of the pins property in pin
+ configuration nodes.
+
+ The following pads are present on Tegra124 and Tegra132:
+
+ audio, bb, cam, comp, csia, csb, cse, dsi, dsib, dsic, dsid, hdmi,
+ hsic, hv, lvds, mipi-bias, nand, pex-bias, pex-clk1, pex-clk2,
+ pex-cntrl, sdmmc1, sdmmc3, sdmmc4, sys_ddc, uart, usb0, usb1, usb2,
+ usb_bias
+
+ The following pads are present on Tegra210:
+
+ audio, audio-hv, cam, csia, csib, csic, csid, csie, csif, dbg,
+ debug-nonao, dmic, dp, dsi, dsib, dsic, dsid, emmc, emmc2, gpio,
+ hdmi, hsic, lvds, mipi-bias, pex-bias, pex-clk1, pex-clk2, pex-cntrl,
+ sdmmc1, sdmmc3, spi, spi-hv, uart, usb0, usb1, usb2, usb3, usb-bias
+ additionalProperties: false
+ properties:
+ pins:
+ $ref: /schemas/types.yaml#/definitions/string-array
+ description: Must contain name of the pad(s) to be configured.
+
+ low-power-enable:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: Configure the pad into power down mode.
+
+ low-power-disable:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: Configure the pad into active mode.
+
+ power-source:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ Must contain either TEGRA_IO_PAD_VOLTAGE_1V8 or
+ TEGRA_IO_PAD_VOLTAGE_3V3 to select between signaling voltages. The
+ values are defined in:
+
+ include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
+
+ Power state can be configured on all Tegra124 and Tegra132 pads.
+ None of the Tegra124 or Tegra132 pads support signaling voltage
+ switching. All of the listed Tegra210 pads except pex-cntrl support
+ power state configuration. Signaling voltage switching is supported
+ on the following Tegra210 pads:
+
+ audio, audio-hv, cam, dbg, dmic, gpio, pex-cntrl, sdmmc1, sdmmc3,
+ spi, spi-hv, uart
+
+ required:
+ - pins
+
+required:
+ - compatible
+ - reg
+ - clock-names
+ - clocks
+ - '#clock-cells'
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: nvidia,tegra124-pmc
+ then:
+ properties:
+ pinmux:
+ additionalProperties:
+ type: object
+ properties:
+ pins:
+ items:
+ enum: [ audio, bb, cam, comp, csia, csb, cse, dsi, dsib,
+ dsic, dsid, hdmi, hsic, hv, lvds, mipi-bias, nand,
+ pex-bias, pex-clk1, pex-clk2, pex-cntrl, sdmmc1,
+ sdmmc3, sdmmc4, sys_ddc, uart, usb0, usb1, usb2,
+ usb_bias ]
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: nvidia,tegra210-pmc
+ then:
+ properties:
+ pinmux:
+ additionalProperties:
+ type: object
+ properties:
+ pins:
+ items:
+ enum: [ audio, audio-hv, cam, csia, csib, csic, csid, csie,
+ csif, dbg, debug-nonao, dmic, dp, dsi, dsib, dsic,
+ dsid, emmc, emmc2, gpio, hdmi, hsic, lvds, mipi-bias,
+ pex-bias, pex-clk1, pex-clk2, pex-cntrl, sdmmc1,
+ sdmmc3, spi, spi-hv, uart, usb0, usb1, usb2, usb3,
+ usb-bias ]
+
+additionalProperties: false
+
+dependencies:
+ "nvidia,suspend-mode": ["nvidia,core-pwr-off-time", "nvidia,cpu-pwr-off-time"]
+ "nvidia,core-pwr-off-time": ["nvidia,core-pwr-good-time"]
+ "nvidia,cpu-pwr-off-time": ["nvidia,cpu-pwr-good-time"]
+
+examples:
+ - |
+ #include <dt-bindings/clock/tegra210-car.h>
+ #include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
+ #include <dt-bindings/soc/tegra-pmc.h>
+
+ pmc@7000e400 {
+ compatible = "nvidia,tegra210-pmc";
+ reg = <0x7000e400 0x400>;
+ core-supply = <&regulator>;
+ clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
+ clock-names = "pclk", "clk32k_in";
+ #clock-cells = <1>;
+
+ nvidia,invert-interrupt;
+ nvidia,suspend-mode = <0>;
+ nvidia,cpu-pwr-good-time = <0>;
+ nvidia,cpu-pwr-off-time = <0>;
+ nvidia,core-pwr-good-time = <4587 3876>;
+ nvidia,core-pwr-off-time = <39065>;
+ nvidia,core-power-req-active-high;
+ nvidia,sys-clock-req-active-high;
+
+ pd_core: core-domain {
+ operating-points-v2 = <&core_opp_table>;
+ #power-domain-cells = <0>;
+ };
+
+ powergates {
+ pd_audio: aud {
+ clocks = <&tegra_car TEGRA210_CLK_APE>,
+ <&tegra_car TEGRA210_CLK_APB2APE>;
+ resets = <&tegra_car 198>;
+ power-domains = <&pd_core>;
+ #power-domain-cells = <0>;
+ };
+
+ pd_xusbss: xusba {
+ clocks = <&tegra_car TEGRA210_CLK_XUSB_SS>;
+ resets = <&tegra_car TEGRA210_CLK_XUSB_SS>;
+ power-domains = <&pd_core>;
+ #power-domain-cells = <0>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml
index fa9f9a853365..60b5e3fd1115 100644
--- a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml
+++ b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml
@@ -13,19 +13,17 @@ select: false
definitions:
port-base:
- $ref: /schemas/graph.yaml#/$defs/port-base
+ allOf:
+ - $ref: /schemas/graph.yaml#/$defs/port-base
+ - $ref: /schemas/sound/dai-params.yaml#
properties:
- convert-rate:
- $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate
- convert-channels:
- $ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels
- convert-sample-format:
- $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format
mclk-fs:
$ref: simple-card.yaml#/definitions/mclk-fs
endpoint-base:
- $ref: /schemas/graph.yaml#/$defs/endpoint-base
+ allOf:
+ - $ref: /schemas/graph.yaml#/$defs/endpoint-base
+ - $ref: /schemas/sound/dai-params.yaml#
properties:
mclk-fs:
$ref: simple-card.yaml#/definitions/mclk-fs
@@ -68,12 +66,6 @@ definitions:
- pdm
- msb
- lsb
- convert-rate:
- $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate
- convert-channels:
- $ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels
- convert-sample-format:
- $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format
dai-tdm-slot-num:
description: Number of slots in use.
diff --git a/Documentation/devicetree/bindings/sound/audio-graph.yaml b/Documentation/devicetree/bindings/sound/audio-graph.yaml
index ed31e04ff6a6..71f52f7e55f6 100644
--- a/Documentation/devicetree/bindings/sound/audio-graph.yaml
+++ b/Documentation/devicetree/bindings/sound/audio-graph.yaml
@@ -9,6 +9,9 @@ title: Audio Graph
maintainers:
- Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+allOf:
+ - $ref: /schemas/sound/dai-params.yaml#
+
properties:
dais:
$ref: /schemas/types.yaml#/definitions/phandle-array
@@ -30,12 +33,6 @@ properties:
widget ("Microphone", "Line", "Headphone", "Speaker"), the
second being the machine specific name for the widget.
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
- convert-rate:
- $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate
- convert-channels:
- $ref: /schemas/sound/dai-params.yaml#/$defs/dai-channels
- convert-sample-format:
- $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-format
pa-gpios:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/sound/awinic,aw87390.yaml b/Documentation/devicetree/bindings/sound/awinic,aw87390.yaml
new file mode 100644
index 000000000000..ba9d8767c5d5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/awinic,aw87390.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/awinic,aw87390.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Awinic Aw87390 Audio Amplifier
+
+maintainers:
+ - Weidong Wang <wangweidong.a@awinic.com>
+
+description:
+ The awinic aw87390 is specifically designed to improve
+ the musical output dynamic range, enhance the overall
+ sound quallity, which is a new high efficiency, low
+ noise, constant large volume, 6th Smart K audio amplifier.
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: awinic,aw87390
+
+ reg:
+ maxItems: 1
+
+ "#sound-dai-cells":
+ const: 0
+
+ awinic,audio-channel:
+ description:
+ It is used to distinguish multiple PA devices, so that different
+ configurations can be loaded to different PA devices
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+
+required:
+ - compatible
+ - reg
+ - "#sound-dai-cells"
+ - awinic,audio-channel
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ audio-codec@58 {
+ compatible = "awinic,aw87390";
+ reg = <0x58>;
+ #sound-dai-cells = <0>;
+ awinic,audio-channel = <0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
index 4051c2538caf..ac5f2e0f42cb 100644
--- a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
+++ b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
@@ -14,14 +14,12 @@ description:
digital Smart K audio amplifier with an integrated 10.25V
smart boost convert.
-allOf:
- - $ref: dai-common.yaml#
-
properties:
compatible:
enum:
- awinic,aw88395
- awinic,aw88261
+ - awinic,aw88399
reg:
maxItems: 1
@@ -32,11 +30,36 @@ properties:
reset-gpios:
maxItems: 1
+ awinic,audio-channel:
+ description:
+ It is used to distinguish multiple PA devices, so that different
+ configurations can be loaded to different PA devices
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+
+ awinic,sync-flag:
+ description:
+ Flag bit used to keep the phase synchronized in the case of multiple PA
+ $ref: /schemas/types.yaml#/definitions/flag
+
required:
- compatible
- reg
- '#sound-dai-cells'
- - reset-gpios
+ - awinic,audio-channel
+
+allOf:
+ - $ref: dai-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - awinic,aw88261
+ then:
+ properties:
+ reset-gpios: false
unevaluatedProperties: false
@@ -51,5 +74,7 @@ examples:
reg = <0x34>;
#sound-dai-cells = <0>;
reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
+ awinic,audio-channel = <0>;
+ awinic,sync-flag;
};
};
diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs42l43.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs42l43.yaml
index 7a6de938b11d..7f9d8c7a635a 100644
--- a/Documentation/devicetree/bindings/sound/cirrus,cs42l43.yaml
+++ b/Documentation/devicetree/bindings/sound/cirrus,cs42l43.yaml
@@ -82,8 +82,8 @@ properties:
description:
Current at which the headset micbias sense clamp will engage, 0 to
disable.
- enum: [ 0, 14, 23, 41, 50, 60, 68, 86, 95 ]
- default: 0
+ enum: [ 0, 14, 24, 43, 52, 61, 71, 90, 99 ]
+ default: 14
cirrus,bias-ramp-ms:
description:
@@ -97,7 +97,7 @@ properties:
Time in microseconds the type detection will run for. Long values will
cause more audible effects, but give more accurate detection.
enum: [ 20, 100, 1000, 10000, 50000, 75000, 100000, 200000 ]
- default: 10000
+ default: 1000
cirrus,button-automute:
type: boolean
diff --git a/Documentation/devicetree/bindings/sound/dai-params.yaml b/Documentation/devicetree/bindings/sound/dai-params.yaml
index f5fb71f9b603..cd8508175564 100644
--- a/Documentation/devicetree/bindings/sound/dai-params.yaml
+++ b/Documentation/devicetree/bindings/sound/dai-params.yaml
@@ -11,15 +11,14 @@ maintainers:
select: false
-$defs:
-
- dai-channels:
+properties:
+ convert-channels:
description: Number of audio channels used by DAI
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 1
maximum: 32
- dai-sample-format:
+ convert-sample-format:
description: Audio sample format used by DAI
$ref: /schemas/types.yaml#/definitions/string
enum:
@@ -29,12 +28,10 @@ $defs:
- s24_3le
- s32_le
- dai-sample-rate:
+ convert-rate:
description: Audio sample rate used by DAI
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 8000
maximum: 192000
-properties: {}
-
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/sound/dialog,da7219.yaml b/Documentation/devicetree/bindings/sound/dialog,da7219.yaml
index eb7d219e2c86..19137abdba3e 100644
--- a/Documentation/devicetree/bindings/sound/dialog,da7219.yaml
+++ b/Documentation/devicetree/bindings/sound/dialog,da7219.yaml
@@ -89,6 +89,7 @@ properties:
da7219_aad:
type: object
+ additionalProperties: false
description:
Configuration of advanced accessory detection.
properties:
diff --git a/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml b/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml
index ff5cd9241941..b522ed7dcc51 100644
--- a/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml
@@ -33,6 +33,7 @@ patternProperties:
description:
A DAI managed by this controller
type: object
+ additionalProperties: false
properties:
reg:
diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8188-afe.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8188-afe.yaml
index 90520f89208b..77af276ed2a2 100644
--- a/Documentation/devicetree/bindings/sound/mediatek,mt8188-afe.yaml
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt8188-afe.yaml
@@ -29,7 +29,7 @@ properties:
maxItems: 1
description: |
Shared memory region for AFE memif. A "shared-dma-pool".
- See ../reserved-memory/reserved-memory.yaml for details.
+ See dtschema reserved-memory/shared-dma-pool.yaml for details.
mediatek,topckgen:
$ref: /schemas/types.yaml#/definitions/phandle
diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
index 43b3b67bdf3b..4c8c95057ef7 100644
--- a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
@@ -17,6 +17,7 @@ properties:
enum:
- mediatek,mt8188-mt6359-evb
- mediatek,mt8188-nau8825
+ - mediatek,mt8188-rt5682s
audio-routing:
description:
diff --git a/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml b/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml
index d80083df03eb..bdf7b0960533 100644
--- a/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml
+++ b/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml
@@ -17,6 +17,7 @@ properties:
enum:
- mediatek,mt8186-mt6366-rt1019-rt5682s-sound
- mediatek,mt8186-mt6366-rt5682s-max98360-sound
+ - mediatek,mt8186-mt6366-rt5650-sound
mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle
diff --git a/Documentation/devicetree/bindings/sound/nxp,tfa9879.yaml b/Documentation/devicetree/bindings/sound/nxp,tfa9879.yaml
new file mode 100644
index 000000000000..df26248573ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nxp,tfa9879.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/nxp,tfa9879.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP TFA9879 class-D audio amplifier
+
+maintainers:
+ - Peter Rosin <peda@axentia.se>
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: nxp,tfa9879
+
+ reg:
+ maxItems: 1
+
+ "#sound-dai-cells":
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - '#sound-dai-cells'
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ amplifier@6c {
+ compatible = "nxp,tfa9879";
+ reg = <0x6c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ #sound-dai-cells = <0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/pcm512x.txt b/Documentation/devicetree/bindings/sound/pcm512x.txt
index 3aae3b41bd8e..77006a4aec4a 100644
--- a/Documentation/devicetree/bindings/sound/pcm512x.txt
+++ b/Documentation/devicetree/bindings/sound/pcm512x.txt
@@ -1,12 +1,12 @@
-PCM512x audio CODECs
+PCM512x and TAS575x audio CODECs/amplifiers
These devices support both I2C and SPI (configured with pin strapping
-on the board).
+on the board). The TAS575x devices only support I2C.
Required properties:
- - compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141" or
- "ti,pcm5142"
+ - compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141",
+ "ti,pcm5142", "ti,tas5754" or "ti,tas5756"
- reg : the I2C address of the device for I2C, the chip select
number for SPI.
@@ -25,6 +25,7 @@ Optional properties:
through <6>. The device will be configured for clock input on the
given pll-in pin and PLL output on the given pll-out pin. An
external connection from the pll-out pin to the SCLK pin is assumed.
+ Caution: the TAS-desvices only support gpios 1,2 and 3
Examples:
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml
index 4156981fe02b..962701e9eb42 100644
--- a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml
@@ -13,6 +13,7 @@ properties:
compatible:
enum:
- qcom,sc7280-lpass-tx-macro
+ - qcom,sm6115-lpass-tx-macro
- qcom,sm8250-lpass-tx-macro
- qcom,sm8450-lpass-tx-macro
- qcom,sm8550-lpass-tx-macro
@@ -101,6 +102,23 @@ allOf:
properties:
compatible:
enum:
+ - qcom,sm6115-lpass-tx-macro
+ then:
+ properties:
+ clocks:
+ minItems: 4
+ maxItems: 4
+ clock-names:
+ items:
+ - const: mclk
+ - const: npl
+ - const: dcodec
+ - const: fsgen
+
+ - if:
+ properties:
+ compatible:
+ enum:
- qcom,sm8550-lpass-tx-macro
then:
properties:
diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
index 262de7a60a73..e082a4fe095d 100644
--- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
@@ -25,6 +25,7 @@ properties:
- qcom,apq8016-sbc-sndcard
- qcom,msm8916-qdsp6-sndcard
- qcom,qrb5165-rb5-sndcard
+ - qcom,sc7180-qdsp6-sndcard
- qcom,sc8280xp-sndcard
- qcom,sdm845-sndcard
- qcom,sm8250-sndcard
diff --git a/Documentation/devicetree/bindings/sound/realtek,rt5616.yaml b/Documentation/devicetree/bindings/sound/realtek,rt5616.yaml
new file mode 100644
index 000000000000..248320804e5f
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/realtek,rt5616.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/realtek,rt5616.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek rt5616 ALSA SoC audio codec driver
+
+description: |
+ Pins on the device (for linking into audio routes) for RT5616:
+
+ * IN1P
+ * IN2P
+ * IN2N
+ * LOUTL
+ * LOUTR
+ * HPOL
+ * HPOR
+
+maintainers:
+ - Bard Liao <bardliao@realtek.com>
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: realtek,rt5616
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ audio-codec@1b {
+ compatible = "realtek,rt5616";
+ reg = <0x1b>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/richtek,rtq9128.yaml b/Documentation/devicetree/bindings/sound/richtek,rtq9128.yaml
new file mode 100644
index 000000000000..d54686a19ab7
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/richtek,rtq9128.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/richtek,rtq9128.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Richtek RTQ9128 Automative Audio Power Amplifier
+
+maintainers:
+ - ChiYuan Huang <cy_huang@richtek.com>
+
+description:
+ The RTQ9128 is a ultra-low output noise, high-efficiency, four-channel
+ class-D audio power amplifier and delivering 4x75W into 4OHm at 10%
+ THD+N from a 25V supply in automotive applications.
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ - richtek,rtq9128
+
+ reg:
+ maxItems: 1
+
+ enable-gpios:
+ maxItems: 1
+
+ richtek,tdm-input-data2-select:
+ type: boolean
+ description:
+ By default, if TDM mode is used, TDM data input will select 'DATA1' pin
+ as the data source. This option will configure TDM data input source from
+ 'DATA1' to 'DATA2' pin.
+
+ '#sound-dai-cells':
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - '#sound-dai-cells'
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ speaker@1a {
+ compatible = "richtek,rtq9128";
+ reg = <0x1a>;
+ enable-gpios = <&gpio 26 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/rt5616.txt b/Documentation/devicetree/bindings/sound/rt5616.txt
deleted file mode 100644
index 540a4bf252e4..000000000000
--- a/Documentation/devicetree/bindings/sound/rt5616.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-RT5616 audio CODEC
-
-This device supports I2C only.
-
-Required properties:
-
-- compatible : "realtek,rt5616".
-
-- reg : The I2C address of the device.
-
-Optional properties:
-
-- clocks: The phandle of the master clock to the CODEC.
-
-- clock-names: Should be "mclk".
-
-Pins on the device (for linking into audio routes) for RT5616:
-
- * IN1P
- * IN2P
- * IN2N
- * LOUTL
- * LOUTR
- * HPOL
- * HPOR
-
-Example:
-
-rt5616: codec@1b {
- compatible = "realtek,rt5616";
- reg = <0x1b>;
-};
diff --git a/Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml b/Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml
new file mode 100644
index 000000000000..e2b4db6aa2fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/starfive,jh7110-pwmdac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 PWM-DAC Controller
+
+description:
+ The PWM-DAC Controller uses PWM square wave generators plus RC filters to
+ form a DAC for audio play in StarFive JH7110 SoC. This audio play controller
+ supports 16 bit audio format, up to 48K sampling frequency, up to left and
+ right dual channels.
+
+maintainers:
+ - Hal Feng <hal.feng@starfivetech.com>
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: starfive,jh7110-pwmdac
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: PWMDAC APB
+ - description: PWMDAC CORE
+
+ clock-names:
+ items:
+ - const: apb
+ - const: core
+
+ resets:
+ maxItems: 1
+ description: PWMDAC APB
+
+ dmas:
+ maxItems: 1
+ description: TX DMA Channel
+
+ dma-names:
+ const: tx
+
+ "#sound-dai-cells":
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - resets
+ - dmas
+ - dma-names
+ - "#sound-dai-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ pwmdac@100b0000 {
+ compatible = "starfive,jh7110-pwmdac";
+ reg = <0x100b0000 0x1000>;
+ clocks = <&syscrg 157>,
+ <&syscrg 158>;
+ clock-names = "apb", "core";
+ resets = <&syscrg 96>;
+ dmas = <&dma 22>;
+ dma-names = "tx";
+ #sound-dai-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/tas5805m.yaml b/Documentation/devicetree/bindings/sound/tas5805m.yaml
index 63edf52f061c..12c41974274e 100644
--- a/Documentation/devicetree/bindings/sound/tas5805m.yaml
+++ b/Documentation/devicetree/bindings/sound/tas5805m.yaml
@@ -37,6 +37,8 @@ properties:
generated from TI's PPC3 tool.
$ref: /schemas/types.yaml#/definitions/string
+additionalProperties: false
+
examples:
- |
i2c {
@@ -52,5 +54,4 @@ examples:
ti,dsp-config-name = "mono_pbtl_48khz";
};
};
-
-additionalProperties: true
+...
diff --git a/Documentation/devicetree/bindings/sound/tfa9879.txt b/Documentation/devicetree/bindings/sound/tfa9879.txt
deleted file mode 100644
index 1620e6848436..000000000000
--- a/Documentation/devicetree/bindings/sound/tfa9879.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-NXP TFA9879 class-D audio amplifier
-
-Required properties:
-
-- compatible : "nxp,tfa9879"
-
-- reg : the I2C address of the device
-
-- #sound-dai-cells : must be 0.
-
-Example:
-
-&i2c1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c1>;
-
- amp: amp@6c {
- #sound-dai-cells = <0>;
- compatible = "nxp,tfa9879";
- reg = <0x6c>;
- };
-};
-
diff --git a/Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml b/Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml
index b6a4360ab845..0b4f003989a4 100644
--- a/Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml
@@ -60,6 +60,7 @@ properties:
ports:
$ref: audio-graph-port.yaml#/definitions/port-base
+ unevaluatedProperties: false
properties:
port@0:
$ref: audio-graph-port.yaml#
diff --git a/Documentation/devicetree/bindings/sound/wm8782.txt b/Documentation/devicetree/bindings/sound/wm8782.txt
index 256cdec6ec4d..1a28f3280972 100644
--- a/Documentation/devicetree/bindings/sound/wm8782.txt
+++ b/Documentation/devicetree/bindings/sound/wm8782.txt
@@ -8,10 +8,17 @@ Required properties:
- Vdda-supply : phandle to a regulator for the analog power supply (2.7V - 5.5V)
- Vdd-supply : phandle to a regulator for the digital power supply (2.7V - 3.6V)
+Optional properties:
+
+ - wlf,fsampen:
+ FSAMPEN pin value, 0 for low, 1 for high, 2 for disconnected.
+ Defaults to 0 if left unspecified.
+
Example:
wm8782: stereo-adc {
compatible = "wlf,wm8782";
Vdda-supply = <&vdda_supply>;
Vdd-supply = <&vdd_supply>;
+ wlf,fsampen = <2>; /* 192KHz */
};
diff --git a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml
index 7d60a9654912..3591c8c49bfe 100644
--- a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml
+++ b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml
@@ -209,17 +209,6 @@ properties:
label:
maxItems: 1
-patternProperties:
- "^.*@[0-9a-f],[0-9a-f]$":
- type: object
- additionalProperties: true
- description:
- Child nodes for a standalone audio codec or speaker amplifier IC.
- It has RX and TX Soundwire secondary devices.
- properties:
- compatible:
- pattern: "^sdw[0-9a-f]{1}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{2}$"
-
required:
- compatible
- reg
@@ -240,7 +229,10 @@ oneOf:
- required:
- qcom,ports-sinterval
-additionalProperties: false
+allOf:
+ - $ref: soundwire-controller.yaml#
+
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml
index a6f34bdd1d3c..e1ab3f523ad6 100644
--- a/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml
@@ -46,6 +46,8 @@ properties:
patternProperties:
"^.*@[0-9a-f]+":
type: object
+ additionalProperties: true
+
properties:
reg:
items:
diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
index 28b8ace63044..3b47b68b92cb 100644
--- a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
@@ -68,6 +68,8 @@ properties:
patternProperties:
"^.*@[0-9a-f]+":
type: object
+ additionalProperties: true
+
properties:
reg:
items:
diff --git a/Documentation/devicetree/bindings/spi/arm,pl022-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/arm,pl022-peripheral-props.yaml
new file mode 100644
index 000000000000..bb8b6863b109
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/arm,pl022-peripheral-props.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/arm,pl022-peripheral-props.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Peripheral-specific properties for Arm PL022 SPI controller
+
+maintainers:
+ - Linus Walleij <linus.walleij@linaro.org>
+
+select: false
+
+properties:
+ pl022,interface:
+ description: SPI interface type
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum:
+ - 0 # SPI
+ - 1 # Texas Instruments Synchronous Serial Frame Format
+ - 2 # Microwire (Half Duplex)
+
+ pl022,com-mode:
+ description: Specifies the transfer mode
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum:
+ - 0 # interrupt mode
+ - 1 # polling mode
+ - 2 # DMA mode
+ default: 1
+
+ pl022,rx-level-trig:
+ description: Rx FIFO watermark level
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 4
+
+ pl022,tx-level-trig:
+ description: Tx FIFO watermark level
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 4
+
+ pl022,ctrl-len:
+ description: Microwire interface - Control length
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0x03
+ maximum: 0x1f
+
+ pl022,wait-state:
+ description: Microwire interface - Wait state
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+
+ pl022,duplex:
+ description: Microwire interface - Full/Half duplex
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+
+additionalProperties: true
+...
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml b/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
index 9ae1611175f2..48e97e240265 100644
--- a/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
+++ b/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
@@ -50,6 +50,7 @@ properties:
patternProperties:
"@[0-9a-f]+$":
type: object
+ additionalProperties: true
properties:
spi-rx-bus-width:
diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-qup.yaml b/Documentation/devicetree/bindings/spi/qcom,spi-qup.yaml
index 93f14dd01afc..88be13268962 100644
--- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.yaml
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.yaml
@@ -44,9 +44,17 @@ properties:
- const: tx
- const: rx
+ interconnects:
+ maxItems: 1
+
interrupts:
maxItems: 1
+ operating-points-v2: true
+
+ power-domains:
+ maxItems: 1
+
reg:
maxItems: 1
@@ -62,7 +70,9 @@ unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-msm8996.h>
+ #include <dt-bindings/interconnect/qcom,msm8996.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
spi@7575000 {
compatible = "qcom,spi-qup-v2.2.1";
@@ -76,6 +86,9 @@ examples:
pinctrl-1 = <&blsp1_spi1_sleep>;
dmas = <&blsp1_dma 12>, <&blsp1_dma 13>;
dma-names = "tx", "rx";
+ power-domains = <&rpmpd MSM8996_VDDCX>;
+ operating-points-v2 = <&spi_opp_table>;
+ interconnects = <&pnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
#address-cells = <1>;
#size-cells = <0>;
};
diff --git a/Documentation/devicetree/bindings/spi/renesas,rzv2m-csi.yaml b/Documentation/devicetree/bindings/spi/renesas,rzv2m-csi.yaml
index e59183e53690..bed829837df1 100644
--- a/Documentation/devicetree/bindings/spi/renesas,rzv2m-csi.yaml
+++ b/Documentation/devicetree/bindings/spi/renesas,rzv2m-csi.yaml
@@ -39,6 +39,12 @@ properties:
power-domains:
maxItems: 1
+ renesas,csi-no-ss:
+ type: boolean
+ description:
+ The CSI Slave Selection (SS) pin won't be used to enable transmission and
+ reception. Only available when in target mode.
+
required:
- compatible
- reg
@@ -50,6 +56,9 @@ required:
- '#address-cells'
- '#size-cells'
+dependencies:
+ renesas,csi-no-ss: [ spi-slave ]
+
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/spi/rockchip-sfc.yaml b/Documentation/devicetree/bindings/spi/rockchip-sfc.yaml
index 339fb39529f3..ac1503de0478 100644
--- a/Documentation/devicetree/bindings/spi/rockchip-sfc.yaml
+++ b/Documentation/devicetree/bindings/spi/rockchip-sfc.yaml
@@ -47,6 +47,8 @@ properties:
patternProperties:
"^flash@[0-3]$":
type: object
+ additionalProperties: true
+
properties:
reg:
minimum: 0
diff --git a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
index a47cb144b09f..6348a387a21c 100644
--- a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
+++ b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
@@ -160,6 +160,8 @@ properties:
patternProperties:
"^.*@[0-9a-f]+$":
type: object
+ additionalProperties: true
+
properties:
reg:
minimum: 0
diff --git a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
index 782a014b63a7..15938f81fdce 100644
--- a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
@@ -113,8 +113,14 @@ properties:
minItems: 2
maxItems: 4
+ st,spi-midi-ns:
+ description: |
+ Only for STM32H7, (Master Inter-Data Idleness) minimum time
+ delay in nanoseconds inserted between two consecutive data frames.
+
# The controller specific properties go here.
allOf:
+ - $ref: arm,pl022-peripheral-props.yaml#
- $ref: cdns,qspi-nor-peripheral-props.yaml#
- $ref: samsung,spi-peripheral-props.yaml#
- $ref: nvidia,tegra210-quad-peripheral-props.yaml#
diff --git a/Documentation/devicetree/bindings/spi/spi-pl022.yaml b/Documentation/devicetree/bindings/spi/spi-pl022.yaml
index 5e5a704a766e..7f174b7d0a26 100644
--- a/Documentation/devicetree/bindings/spi/spi-pl022.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-pl022.yaml
@@ -74,57 +74,6 @@ properties:
resets:
maxItems: 1
-patternProperties:
- "^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-f]+$":
- type: object
- # SPI slave nodes must be children of the SPI master node and can
- # contain the following properties.
- properties:
- pl022,interface:
- description: SPI interface type
- $ref: /schemas/types.yaml#/definitions/uint32
- enum:
- - 0 # SPI
- - 1 # Texas Instruments Synchronous Serial Frame Format
- - 2 # Microwire (Half Duplex)
-
- pl022,com-mode:
- description: Specifies the transfer mode
- $ref: /schemas/types.yaml#/definitions/uint32
- enum:
- - 0 # interrupt mode
- - 1 # polling mode
- - 2 # DMA mode
- default: 1
-
- pl022,rx-level-trig:
- description: Rx FIFO watermark level
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 0
- maximum: 4
-
- pl022,tx-level-trig:
- description: Tx FIFO watermark level
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 0
- maximum: 4
-
- pl022,ctrl-len:
- description: Microwire interface - Control length
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 0x03
- maximum: 0x1f
-
- pl022,wait-state:
- description: Microwire interface - Wait state
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [0, 1]
-
- pl022,duplex:
- description: Microwire interface - Full/Half duplex
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [0, 1]
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml
index 9ca1a843c820..ae0f082bd377 100644
--- a/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml
@@ -18,15 +18,6 @@ maintainers:
allOf:
- $ref: spi-controller.yaml#
- - if:
- properties:
- compatible:
- contains:
- const: st,stm32f4-spi
-
- then:
- properties:
- st,spi-midi-ns: false
properties:
compatible:
@@ -59,17 +50,6 @@ properties:
- const: rx
- const: tx
-patternProperties:
- "^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-f]+$":
- type: object
- # SPI slave nodes must be children of the SPI master node and can
- # contain the following properties.
- properties:
- st,spi-midi-ns:
- description: |
- Only for STM32H7, (Master Inter-Data Idleness) minimum time
- delay in nanoseconds inserted between two consecutive data frames.
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/thermal/fsl,scu-thermal.yaml b/Documentation/devicetree/bindings/thermal/fsl,scu-thermal.yaml
index 3721c8c8ec64..e02d04d4f71e 100644
--- a/Documentation/devicetree/bindings/thermal/fsl,scu-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/fsl,scu-thermal.yaml
@@ -18,7 +18,9 @@ allOf:
properties:
compatible:
items:
- - const: fsl,imx8qxp-sc-thermal
+ - enum:
+ - fsl,imx8dxl-sc-thermal
+ - fsl,imx8qxp-sc-thermal
- const: fsl,imx-sc-thermal
'#thermal-sensor-cells':
diff --git a/Documentation/devicetree/bindings/thermal/imx-thermal.yaml b/Documentation/devicetree/bindings/thermal/imx-thermal.yaml
index 3aecea77869f..808d987bd8d1 100644
--- a/Documentation/devicetree/bindings/thermal/imx-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/imx-thermal.yaml
@@ -60,6 +60,9 @@ properties:
clocks:
maxItems: 1
+ "#thermal-sensor-cells":
+ const: 0
+
required:
- compatible
- interrupts
@@ -67,6 +70,9 @@ required:
- nvmem-cells
- nvmem-cell-names
+allOf:
+ - $ref: thermal-sensor.yaml#
+
additionalProperties: false
examples:
@@ -104,5 +110,6 @@ examples:
nvmem-cells = <&tempmon_calib>, <&tempmon_temp_grade>;
nvmem-cell-names = "calib", "temp_grade";
clocks = <&clks IMX6SX_CLK_PLL3_USB_OTG>;
+ #thermal-sensor-cells = <0>;
};
};
diff --git a/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml
index fe9ae4c425c0..e6665af52ee6 100644
--- a/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml
@@ -18,6 +18,7 @@ description: |
properties:
compatible:
enum:
+ - mediatek,mt7988-lvts-ap
- mediatek,mt8192-lvts-ap
- mediatek,mt8192-lvts-mcu
- mediatek,mt8195-lvts-ap
diff --git a/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.yaml b/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.yaml
index 04a2ba1aa946..b0237d236021 100644
--- a/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.yaml
+++ b/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.yaml
@@ -68,7 +68,12 @@ properties:
patternProperties:
"^(light|heavy|oc1)$":
type: object
+ additionalProperties: false
+
properties:
+ "#cooling-cells":
+ const: 2
+
nvidia,priority:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 1
diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
index 27e9e16e6455..437b74732886 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
@@ -51,6 +51,7 @@ properties:
- qcom,msm8996-tsens
- qcom,msm8998-tsens
- qcom,qcm2290-tsens
+ - qcom,sa8775p-tsens
- qcom,sc7180-tsens
- qcom,sc7280-tsens
- qcom,sc8180x-tsens
diff --git a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
index 4f3acdc4dec0..4a8dabc48170 100644
--- a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
+++ b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/base.yaml#
title: Thermal zone
maintainers:
- - Amit Kucheria <amitk@kernel.org>
+ - Daniel Lezcano <daniel.lezcano@linaro.org>
description: |
Thermal management is achieved in devicetree by describing the sensor hardware
diff --git a/Documentation/devicetree/bindings/timer/cirrus,ep9301-timer.yaml b/Documentation/devicetree/bindings/timer/cirrus,ep9301-timer.yaml
new file mode 100644
index 000000000000..e463e11e259d
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/cirrus,ep9301-timer.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/timer/cirrus,ep9301-timer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cirrus Logic EP93xx timer
+
+maintainers:
+ - Alexander Sverdlin <alexander.sverdlin@gmail.com>
+ - Nikita Shubin <nikita.shubin@maquefel.me>
+
+properties:
+ compatible:
+ oneOf:
+ - const: cirrus,ep9301-timer
+ - items:
+ - enum:
+ - cirrus,ep9302-timer
+ - cirrus,ep9307-timer
+ - cirrus,ep9312-timer
+ - cirrus,ep9315-timer
+ - const: cirrus,ep9301-timer
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ timer@80810000 {
+ compatible = "cirrus,ep9301-timer";
+ reg = <0x80810000 0x100>;
+ interrupt-parent = <&vic1>;
+ interrupts = <19>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml b/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml
index dbe1267af06a..e2607377cbae 100644
--- a/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml
+++ b/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml
@@ -36,7 +36,9 @@ properties:
- fsl,imxrt1170-gpt
- const: fsl,imx6dl-gpt
- items:
- - const: fsl,imx6ul-gpt
+ - enum:
+ - fsl,imx6ul-gpt
+ - fsl,imx7d-gpt
- const: fsl,imx6sx-gpt
reg:
@@ -46,14 +48,18 @@ properties:
maxItems: 1
clocks:
+ minItems: 2
items:
- description: SoC GPT ipg clock
- description: SoC GPT per clock
+ - description: SoC GPT osc per clock
clock-names:
+ minItems: 2
items:
- const: ipg
- const: per
+ - const: osc_per
required:
- compatible
@@ -62,6 +68,29 @@ required:
- clocks
- clock-names
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx6dl-gpt
+ - fsl,imx6q-gpt
+ then:
+ properties:
+ clocks:
+ minItems: 2
+ maxItems: 3
+ clock-names:
+ minItems: 2
+ maxItems: 3
+ else:
+ properties:
+ clocks:
+ maxItems: 2
+ clock-names:
+ maxItems: 2
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml b/Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml
index bffdab0b0185..3931054b42fb 100644
--- a/Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml
+++ b/Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml
@@ -11,8 +11,8 @@ maintainers:
description: |
This hardware block consists of eight 16-bit timer channels and one
- 32- bit timer channel. It supports the following specifications:
- - Pulse input/output: 28 lines max.
+ 32-bit timer channel. It supports the following specifications:
+ - Pulse input/output: 28 lines max
- Pulse input 3 lines
- Count clock 11 clocks for each channel (14 clocks for MTU0, 12 clocks
for MTU2, and 10 clocks for MTU5, four clocks for MTU1-MTU2 combination
@@ -23,11 +23,11 @@ description: |
- Input capture function (noise filter setting available)
- Counter-clearing operation
- Simultaneous writing to multiple timer counters (TCNT)
- (excluding MTU8).
+ (excluding MTU8)
- Simultaneous clearing on compare match or input capture
- (excluding MTU8).
+ (excluding MTU8)
- Simultaneous input and output to registers in synchronization with
- counter operations (excluding MTU8).
+ counter operations (excluding MTU8)
- Up to 12-phase PWM output in combination with synchronous operation
(excluding MTU8)
- [MTU0 MTU3, MTU4, MTU6, MTU7, and MTU8]
@@ -40,26 +40,26 @@ description: |
- [MTU3, MTU4, MTU6, and MTU7]
- Through interlocked operation of MTU3/4 and MTU6/7, the positive and
negative signals in six phases (12 phases in total) can be output in
- complementary PWM and reset-synchronized PWM operation.
+ complementary PWM and reset-synchronized PWM operation
- In complementary PWM mode, values can be transferred from buffer
registers to temporary registers at crests and troughs of the timer-
counter values or when the buffer registers (TGRD registers in MTU4
- and MTU7) are written to.
- - Double-buffering selectable in complementary PWM mode.
+ and MTU7) are written to
+ - Double-buffering selectable in complementary PWM mode
- [MTU3 and MTU4]
- Through interlocking with MTU0, a mode for driving AC synchronous
motors (brushless DC motors) by using complementary PWM output and
reset-synchronized PWM output is settable and allows the selection
- of two types of waveform output (chopping or level).
+ of two types of waveform output (chopping or level)
- [MTU5]
- - Capable of operation as a dead-time compensation counter.
+ - Capable of operation as a dead-time compensation counter
- [MTU0/MTU5, MTU1, MTU2, and MTU8]
- 32-bit phase counting mode specifiable by combining MTU1 and MTU2 and
- through interlocked operation with MTU0/MTU5 and MTU8.
+ through interlocked operation with MTU0/MTU5 and MTU8
- Interrupt-skipping function
- In complementary PWM mode, interrupts on crests and troughs of counter
values and triggers to start conversion by the A/D converter can be
- skipped.
+ skipped
- Interrupt sources: 43 sources.
- Buffer operation:
- Automatic transfer of register data (transfer from the buffer
@@ -68,9 +68,9 @@ description: |
- A/D converter start triggers can be generated
- A/D converter start request delaying function enables A/D converter
to be started with any desired timing and to be synchronized with
- PWM output.
+ PWM output
- Low power consumption function
- - The MTU3a can be placed in the module-stop state.
+ - The MTU3a can be placed in the module-stop state
There are two phase counting modes. 16-bit phase counting mode in which
MTU1 and MTU2 operate independently, and cascade connection 32-bit phase
@@ -109,6 +109,7 @@ properties:
compatible:
items:
- enum:
+ - renesas,r9a07g043-mtu3 # RZ/{G2UL,Five}
- renesas,r9a07g044-mtu3 # RZ/G2{L,LC}
- renesas,r9a07g054-mtu3 # RZ/V2L
- const: renesas,rz-mtu3
@@ -169,27 +170,27 @@ properties:
- const: tgib0
- const: tgic0
- const: tgid0
- - const: tgiv0
+ - const: tciv0
- const: tgie0
- const: tgif0
- const: tgia1
- const: tgib1
- - const: tgiv1
- - const: tgiu1
+ - const: tciv1
+ - const: tciu1
- const: tgia2
- const: tgib2
- - const: tgiv2
- - const: tgiu2
+ - const: tciv2
+ - const: tciu2
- const: tgia3
- const: tgib3
- const: tgic3
- const: tgid3
- - const: tgiv3
+ - const: tciv3
- const: tgia4
- const: tgib4
- const: tgic4
- const: tgid4
- - const: tgiv4
+ - const: tciv4
- const: tgiu5
- const: tgiv5
- const: tgiw5
@@ -197,18 +198,18 @@ properties:
- const: tgib6
- const: tgic6
- const: tgid6
- - const: tgiv6
+ - const: tciv6
- const: tgia7
- const: tgib7
- const: tgic7
- const: tgid7
- - const: tgiv7
+ - const: tciv7
- const: tgia8
- const: tgib8
- const: tgic8
- const: tgid8
- - const: tgiv8
- - const: tgiu8
+ - const: tciv8
+ - const: tciu8
clocks:
maxItems: 1
@@ -285,16 +286,16 @@ examples:
<GIC_SPI 211 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 212 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 213 IRQ_TYPE_EDGE_RISING>;
- interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", "tgiv0", "tgie0",
+ interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", "tciv0", "tgie0",
"tgif0",
- "tgia1", "tgib1", "tgiv1", "tgiu1",
- "tgia2", "tgib2", "tgiv2", "tgiu2",
- "tgia3", "tgib3", "tgic3", "tgid3", "tgiv3",
- "tgia4", "tgib4", "tgic4", "tgid4", "tgiv4",
+ "tgia1", "tgib1", "tciv1", "tciu1",
+ "tgia2", "tgib2", "tciv2", "tciu2",
+ "tgia3", "tgib3", "tgic3", "tgid3", "tciv3",
+ "tgia4", "tgib4", "tgic4", "tgid4", "tciv4",
"tgiu5", "tgiv5", "tgiw5",
- "tgia6", "tgib6", "tgic6", "tgid6", "tgiv6",
- "tgia7", "tgib7", "tgic7", "tgid7", "tgiv7",
- "tgia8", "tgib8", "tgic8", "tgid8", "tgiv8", "tgiu8";
+ "tgia6", "tgib6", "tgic6", "tgid6", "tciv6",
+ "tgia7", "tgib7", "tgic7", "tgid7", "tciv7",
+ "tgia8", "tgib8", "tgic8", "tgid8", "tciv8", "tciu8";
clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>;
power-domains = <&cpg>;
resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>;
diff --git a/Documentation/devicetree/bindings/timer/sifive,clint.yaml b/Documentation/devicetree/bindings/timer/sifive,clint.yaml
index a0185e15a42f..e8be6c470364 100644
--- a/Documentation/devicetree/bindings/timer/sifive,clint.yaml
+++ b/Documentation/devicetree/bindings/timer/sifive,clint.yaml
@@ -37,6 +37,7 @@ properties:
- items:
- enum:
- allwinner,sun20i-d1-clint
+ - sophgo,cv1800b-clint
- thead,th1520-clint
- const: thead,c900-clint
- items:
diff --git a/Documentation/devicetree/bindings/timer/thead,c900-aclint-mtimer.yaml b/Documentation/devicetree/bindings/timer/thead,c900-aclint-mtimer.yaml
new file mode 100644
index 000000000000..fbd235650e52
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/thead,c900-aclint-mtimer.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/timer/thead,c900-aclint-mtimer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sophgo CLINT Timer
+
+maintainers:
+ - Inochi Amaoto <inochiama@outlook.com>
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - sophgo,sg2042-aclint-mtimer
+ - const: thead,c900-aclint-mtimer
+
+ reg:
+ maxItems: 1
+
+ interrupts-extended:
+ minItems: 1
+ maxItems: 4095
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts-extended
+
+examples:
+ - |
+ timer@ac000000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ interrupts-extended = <&cpu1intc 7>,
+ <&cpu2intc 7>,
+ <&cpu3intc 7>,
+ <&cpu4intc 7>;
+ reg = <0xac000000 0x00010000>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml
index 430a814f64a5..c3190f2a168a 100644
--- a/Documentation/devicetree/bindings/trivial-devices.yaml
+++ b/Documentation/devicetree/bindings/trivial-devices.yaml
@@ -151,8 +151,6 @@ properties:
- infineon,slb9645tt
# Infineon SLB9673 I2C TPM 2.0
- infineon,slb9673
- # Infineon TDA38640 Voltage Regulator
- - infineon,tda38640
# Infineon TLV493D-A1B6 I2C 3D Magnetic Sensor
- infineon,tlv493d-a1b6
# Infineon Multi-phase Digital VR Controller xdpe11280
@@ -311,8 +309,6 @@ properties:
- nuvoton,w83773g
# OKI ML86V7667 video decoder
- oki,ml86v7667
- # OV5642: Color CMOS QSXGA (5-megapixel) Image Sensor with OmniBSI and Embedded TrueFocus
- - ovti,ov5642
# 48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch
- plx,pex8648
# Pulsedlight LIDAR range-finding sensor
@@ -348,6 +344,8 @@ properties:
# Silicon Labs SI3210 Programmable CMOS SLIC/CODEC with SPI interface
- silabs,si3210
# Relative Humidity and Temperature Sensors
+ - silabs,si7005
+ # Relative Humidity and Temperature Sensors
- silabs,si7020
# Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
- skyworks,sky81452
diff --git a/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml b/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml
index 462ead5a1cec..2cf3d016db42 100644
--- a/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml
+++ b/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml
@@ -36,6 +36,7 @@ properties:
- qcom,sm8350-ufshc
- qcom,sm8450-ufshc
- qcom,sm8550-ufshc
+ - qcom,sm8650-ufshc
- const: qcom,ufshc
- const: jedec,ufs-2.0
@@ -122,6 +123,7 @@ allOf:
- qcom,sm8350-ufshc
- qcom,sm8450-ufshc
- qcom,sm8550-ufshc
+ - qcom,sm8650-ufshc
then:
properties:
clocks:
diff --git a/Documentation/devicetree/bindings/ufs/ufs-common.yaml b/Documentation/devicetree/bindings/ufs/ufs-common.yaml
index bbaee4f5f7b2..985ea8f64de8 100644
--- a/Documentation/devicetree/bindings/ufs/ufs-common.yaml
+++ b/Documentation/devicetree/bindings/ufs/ufs-common.yaml
@@ -20,11 +20,25 @@ properties:
items:
- description: Minimum frequency for given clock in Hz
- description: Maximum frequency for given clock in Hz
+ deprecated: true
description: |
+ Preferred is operating-points-v2.
+
Array of <min max> operating frequencies in Hz stored in the same order
- as the clocks property. If this property is not defined or a value in the
- array is "0" then it is assumed that the frequency is set by the parent
- clock or a fixed rate clock source.
+ as the clocks property. If either this property or operating-points-v2 is
+ not defined or a value in the array is "0" then it is assumed that the
+ frequency is set by the parent clock or a fixed rate clock source.
+
+ operating-points-v2:
+ description:
+ Preferred over freq-table-hz.
+ If present, each OPP must contain array of frequencies stored in the same
+ order for each clock. If clock frequency in the array is "0" then it is
+ assumed that the frequency is set by the parent clock or a fixed rate
+ clock source.
+
+ opp-table:
+ type: object
interrupts:
maxItems: 1
@@ -75,8 +89,23 @@ properties:
dependencies:
freq-table-hz: [ clocks ]
+ operating-points-v2: [ clocks, clock-names ]
required:
- interrupts
+allOf:
+ - if:
+ required:
+ - freq-table-hz
+ then:
+ properties:
+ operating-points-v2: false
+ - if:
+ required:
+ - operating-points-v2
+ then:
+ properties:
+ freq-table-hz: false
+
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.yaml b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.yaml
index 1394557517b1..b7e664f7395b 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.yaml
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.yaml
@@ -15,7 +15,9 @@ properties:
oneOf:
- enum:
- chipidea,usb2
+ - fsl,imx27-usb
- lsi,zevio-usb
+ - nuvoton,npcm750-udc
- nvidia,tegra20-ehci
- nvidia,tegra20-udc
- nvidia,tegra30-ehci
@@ -66,6 +68,10 @@ properties:
- items:
- const: xlnx,zynq-usb-2.20a
- const: chipidea,usb2
+ - items:
+ - enum:
+ - nuvoton,npcm845-udc
+ - const: nuvoton,npcm750-udc
reg:
minItems: 1
@@ -388,6 +394,7 @@ allOf:
enum:
- chipidea,usb2
- lsi,zevio-usb
+ - nuvoton,npcm750-udc
- nvidia,tegra20-udc
- nvidia,tegra30-udc
- nvidia,tegra114-udc
diff --git a/Documentation/devicetree/bindings/usb/fcs,fsa4480.yaml b/Documentation/devicetree/bindings/usb/fcs,fsa4480.yaml
index f6e7a5c1ff0b..f9410eb76a62 100644
--- a/Documentation/devicetree/bindings/usb/fcs,fsa4480.yaml
+++ b/Documentation/devicetree/bindings/usb/fcs,fsa4480.yaml
@@ -11,8 +11,12 @@ maintainers:
properties:
compatible:
- enum:
- - fcs,fsa4480
+ oneOf:
+ - const: fcs,fsa4480
+ - items:
+ - enum:
+ - ocs,ocp96011
+ - const: fcs,fsa4480
reg:
maxItems: 1
@@ -32,10 +36,43 @@ properties:
type: boolean
port:
- $ref: /schemas/graph.yaml#/properties/port
+ $ref: /schemas/graph.yaml#/$defs/port-base
description:
A port node to link the FSA4480 to a TypeC controller for the purpose of
handling altmode muxing and orientation switching.
+ unevaluatedProperties: false
+
+ properties:
+ endpoint:
+ $ref: /schemas/graph.yaml#/$defs/endpoint-base
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ Specifies how the AUX+/- lines are connected to SBU1/2.
+ oneOf:
+ - items:
+ - const: 0
+ - const: 1
+ description: |
+ Default AUX/SBU layout (FSA4480)
+ - AUX+ connected to SBU2
+ - AUX- connected to SBU1
+ Default AUX/SBU layout (OCP96011)
+ - AUX+ connected to SBU1
+ - AUX- connected to SBU2
+ - items:
+ - const: 1
+ - const: 0
+ description: |
+ Swapped AUX/SBU layout (FSA4480)
+ - AUX+ connected to SBU1
+ - AUX- connected to SBU2
+ Swapped AUX/SBU layout (OCP96011)
+ - AUX+ connected to SBU2
+ - AUX- connected to SBU1
required:
- compatible
diff --git a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml
index d0927f6768a4..ee08b9c3721f 100644
--- a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml
+++ b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/usb/genesys,gl850g.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Genesys Logic GL850G USB 2.0 hub controller
+title: Genesys Logic USB hub controller
maintainers:
- Icenowy Zheng <uwu@icenowy.me>
@@ -18,6 +18,7 @@ properties:
- usb5e3,608
- usb5e3,610
- usb5e3,620
+ - usb5e3,626
reg: true
diff --git a/Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml b/Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml
index f196beb826d8..d3b2b666ec2a 100644
--- a/Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml
+++ b/Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml
@@ -19,6 +19,7 @@ properties:
compatible:
items:
- enum:
+ - nxp,cbdtu02043
- onnn,fsusb43l10x
- pericom,pi3usb102
- const: gpio-sbu-mux
@@ -50,7 +51,6 @@ required:
- compatible
- enable-gpios
- select-gpios
- - mode-switch
- orientation-switch
- port
diff --git a/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml b/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml
index ff3a1707ef57..6d4cfd943f58 100644
--- a/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml
+++ b/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml
@@ -36,7 +36,11 @@ properties:
vdd-supply:
description:
- VDD power supply to the hub
+ 3V3 power supply to the hub
+
+ vdd2-supply:
+ description:
+ 1V2 power supply to the hub
peer-hub:
$ref: /schemas/types.yaml#/definitions/phandle
@@ -62,6 +66,7 @@ allOf:
properties:
reset-gpios: false
vdd-supply: false
+ vdd2-supply: false
peer-hub: false
i2c-bus: false
else:
diff --git a/Documentation/devicetree/bindings/usb/nxp,ptn36502.yaml b/Documentation/devicetree/bindings/usb/nxp,ptn36502.yaml
new file mode 100644
index 000000000000..eee548ac1abe
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/nxp,ptn36502.yaml
@@ -0,0 +1,94 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/nxp,ptn36502.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP PTN36502 Type-C USB 3.1 Gen 1 and DisplayPort v1.2 combo redriver
+
+maintainers:
+ - Luca Weiss <luca.weiss@fairphone.com>
+
+properties:
+ compatible:
+ enum:
+ - nxp,ptn36502
+
+ reg:
+ maxItems: 1
+
+ vdd18-supply:
+ description: Power supply for VDD18 pin
+
+ retimer-switch:
+ description: Flag the port as possible handle of SuperSpeed signals retiming
+ type: boolean
+
+ orientation-switch:
+ description: Flag the port as possible handler of orientation switching
+ type: boolean
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Super Speed (SS) Output endpoint to the Type-C connector
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Super Speed (SS) Input endpoint from the Super-Speed PHY
+
+ port@2:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ Sideband Use (SBU) AUX lines endpoint to the Type-C connector for the purpose of
+ handling altmode muxing and orientation switching.
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ typec-mux@1a {
+ compatible = "nxp,ptn36502";
+ reg = <0x1a>;
+
+ vdd18-supply = <&usb_redrive_1v8>;
+
+ retimer-switch;
+ orientation-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ usb_con_ss: endpoint {
+ remote-endpoint = <&typec_con_ss>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ phy_con_ss: endpoint {
+ remote-endpoint = <&usb_phy_ss>;
+ };
+ };
+ port@2 {
+ reg = <2>;
+ usb_con_sbu: endpoint {
+ remote-endpoint = <&typec_dp_aux>;
+ };
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
index 67591057f234..915c8205623b 100644
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
@@ -14,6 +14,7 @@ properties:
items:
- enum:
- qcom,ipq4019-dwc3
+ - qcom,ipq5018-dwc3
- qcom,ipq5332-dwc3
- qcom,ipq6018-dwc3
- qcom,ipq8064-dwc3
@@ -34,6 +35,7 @@ properties:
- qcom,sdm845-dwc3
- qcom,sdx55-dwc3
- qcom,sdx65-dwc3
+ - qcom,sdx75-dwc3
- qcom,sm4250-dwc3
- qcom,sm6115-dwc3
- qcom,sm6125-dwc3
@@ -180,6 +182,8 @@ allOf:
- qcom,sdm670-dwc3
- qcom,sdm845-dwc3
- qcom,sdx55-dwc3
+ - qcom,sdx65-dwc3
+ - qcom,sdx75-dwc3
- qcom,sm6350-dwc3
then:
properties:
@@ -238,6 +242,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,ipq5018-dwc3
- qcom,ipq5332-dwc3
- qcom,msm8994-dwc3
- qcom,qcs404-dwc3
@@ -363,6 +368,7 @@ allOf:
- qcom,sdm845-dwc3
- qcom,sdx55-dwc3
- qcom,sdx65-dwc3
+ - qcom,sdx75-dwc3
- qcom,sm4250-dwc3
- qcom,sm6125-dwc3
- qcom,sm6350-dwc3
@@ -411,6 +417,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,ipq5018-dwc3
- qcom,ipq5332-dwc3
- qcom,sdm660-dwc3
then:
@@ -514,8 +521,8 @@ examples:
interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 486 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 488 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 489 IRQ_TYPE_LEVEL_HIGH>;
+ <GIC_SPI 488 IRQ_TYPE_EDGE_BOTH>,
+ <GIC_SPI 489 IRQ_TYPE_EDGE_BOTH>;
interrupt-names = "hs_phy_irq", "ss_phy_irq",
"dm_hs_phy_irq", "dp_hs_phy_irq";
diff --git a/Documentation/devicetree/bindings/usb/realtek,rtd-dwc3.yaml b/Documentation/devicetree/bindings/usb/realtek,rtd-dwc3.yaml
new file mode 100644
index 000000000000..345d0132d4a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/realtek,rtd-dwc3.yaml
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2023 Realtek Semiconductor Corporation
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/realtek,rtd-dwc3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek DWC3 USB SoC Controller Glue
+
+maintainers:
+ - Stanley Chang <stanley_chang@realtek.com>
+
+description:
+ The Realtek DHC SoC embeds a DWC3 USB IP Core configured for USB 2.0
+ and USB 3.0 in host or dual-role mode.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - realtek,rtd1295-dwc3
+ - realtek,rtd1315e-dwc3
+ - realtek,rtd1319-dwc3
+ - realtek,rtd1319d-dwc3
+ - realtek,rtd1395-dwc3
+ - realtek,rtd1619-dwc3
+ - realtek,rtd1619b-dwc3
+ - const: realtek,rtd-dwc3
+
+ reg:
+ items:
+ - description: Address and length of register set for wrapper of dwc3 core.
+ - description: Address and length of register set for pm control.
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 1
+
+ ranges: true
+
+patternProperties:
+ "^usb@[0-9a-f]+$":
+ $ref: snps,dwc3.yaml#
+ description: Required child node
+
+required:
+ - compatible
+ - reg
+ - "#address-cells"
+ - "#size-cells"
+ - ranges
+
+additionalProperties: false
+
+examples:
+ - |
+ usb@98013e00 {
+ compatible = "realtek,rtd1319d-dwc3", "realtek,rtd-dwc3";
+ reg = <0x98013e00 0x140>, <0x98013f60 0x4>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ usb@98050000 {
+ compatible = "snps,dwc3";
+ reg = <0x98050000 0x9000>;
+ interrupts = <0 94 4>;
+ phys = <&usb2phy &usb3phy>;
+ phy-names = "usb2-phy", "usb3-phy";
+ dr_mode = "otg";
+ usb-role-switch;
+ role-switch-default-mode = "host";
+ snps,dis_u2_susphy_quirk;
+ snps,parkmode-disable-ss-quirk;
+ snps,parkmode-disable-hs-quirk;
+ maximum-speed = "high-speed";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/usb/realtek,rtd-type-c.yaml b/Documentation/devicetree/bindings/usb/realtek,rtd-type-c.yaml
new file mode 100644
index 000000000000..6142b0b5b534
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/realtek,rtd-type-c.yaml
@@ -0,0 +1,82 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2023 Realtek Semiconductor Corporation
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/realtek,rtd-type-c.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek DHC RTD SoCs USB Type-C Connector detection
+
+maintainers:
+ - Stanley Chang <stanley_chang@realtek.com>
+
+description:
+ Realtek digital home center (DHC) RTD series SoCs include a type c module.
+ This module is able to detect the state of type c connector.
+
+properties:
+ compatible:
+ enum:
+ - realtek,rtd1295-type-c
+ - realtek,rtd1312c-type-c
+ - realtek,rtd1315e-type-c
+ - realtek,rtd1319-type-c
+ - realtek,rtd1319d-type-c
+ - realtek,rtd1395-type-c
+ - realtek,rtd1619-type-c
+ - realtek,rtd1619b-type-c
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ nvmem-cell-names:
+ items:
+ - const: usb-cal
+
+ nvmem-cells:
+ maxItems: 1
+ description:
+ The phandle to nvmem cell that contains the trimming data.
+ The type c parameter trimming data specified via efuse.
+ If unspecified, default value is used.
+
+ realtek,rd-ctrl-gpios:
+ description: The gpio node to control external Rd on board.
+ maxItems: 1
+
+ connector:
+ $ref: /schemas/connector/usb-connector.yaml#
+ description: Properties for usb c connector.
+ type: object
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ type-c@7220 {
+ compatible = "realtek,rtd1619b-type-c";
+ reg = <0x7220 0x20>;
+ interrupts = <0 60 IRQ_TYPE_LEVEL_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_cc1_pins>, <&usb_cc2_pins>;
+ nvmem-cells = <&otp_usb_cal>;
+ nvmem-cell-names = "usb-cal";
+
+ connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ data-role = "dual";
+ power-role = "dual";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml b/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml
index 291844c8f3e1..c4924113f9bd 100644
--- a/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml
@@ -15,14 +15,11 @@ description:
Phy documentation is provided in the following places.
USB2.0 PHY
- Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.yaml
+ Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
Type-C PHY
Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
-allOf:
- - $ref: snps,dwc3.yaml#
-
select:
properties:
compatible:
@@ -30,6 +27,7 @@ select:
enum:
- rockchip,rk3328-dwc3
- rockchip,rk3568-dwc3
+ - rockchip,rk3588-dwc3
required:
- compatible
@@ -39,6 +37,7 @@ properties:
- enum:
- rockchip,rk3328-dwc3
- rockchip,rk3568-dwc3
+ - rockchip,rk3588-dwc3
- const: snps,dwc3
reg:
@@ -58,7 +57,9 @@ properties:
Master/Core clock, must to be >= 62.5 MHz for SS
operation and >= 30MHz for HS operation
- description:
- Controller grf clock
+ Controller grf clock OR UTMI clock
+ - description:
+ PIPE clock
clock-names:
minItems: 3
@@ -66,7 +67,10 @@ properties:
- const: ref_clk
- const: suspend_clk
- const: bus_clk
- - const: grf_clk
+ - enum:
+ - grf_clk
+ - utmi
+ - const: pipe
power-domains:
maxItems: 1
@@ -86,6 +90,52 @@ required:
- clocks
- clock-names
+allOf:
+ - $ref: snps,dwc3.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3328-dwc3
+ then:
+ properties:
+ clocks:
+ minItems: 3
+ maxItems: 4
+ clock-names:
+ minItems: 3
+ items:
+ - const: ref_clk
+ - const: suspend_clk
+ - const: bus_clk
+ - const: grf_clk
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3568-dwc3
+ then:
+ properties:
+ clocks:
+ maxItems: 3
+ clock-names:
+ maxItems: 3
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3588-dwc3
+ then:
+ properties:
+ clock-names:
+ minItems: 3
+ items:
+ - const: ref_clk
+ - const: suspend_clk
+ - const: bus_clk
+ - const: utmi
+ - const: pipe
+
examples:
- |
#include <dt-bindings/clock/rk3328-cru.h>
diff --git a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
index a696f23730d3..ee5af4b381b1 100644
--- a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
@@ -310,6 +310,62 @@ properties:
maximum: 62
deprecated: true
+ snps,rx-thr-num-pkt:
+ description:
+ USB RX packet threshold count. In host mode, this field specifies
+ the space that must be available in the RX FIFO before the core can
+ start the corresponding USB RX transaction (burst).
+ In device mode, this field specifies the space that must be
+ available in the RX FIFO before the core can send ERDY for a
+ flow-controlled endpoint. It is only used for SuperSpeed.
+ The valid values for this field are from 1 to 15. (DWC3 SuperSpeed
+ USB 3.0 Controller Databook)
+ $ref: /schemas/types.yaml#/definitions/uint8
+ minimum: 1
+ maximum: 15
+
+ snps,rx-max-burst:
+ description:
+ Max USB RX burst size. In host mode, this field specifies the
+ Maximum Bulk IN burst the DWC_usb3 core can perform. When the system
+ bus is slower than the USB, RX FIFO can overrun during a long burst.
+ You can program a smaller value to this field to limit the RX burst
+ size that the core can perform. It only applies to SS Bulk,
+ Isochronous, and Interrupt IN endpoints in the host mode.
+ In device mode, this field specifies the NUMP value that is sent in
+ ERDY for an OUT endpoint.
+ The valid values for this field are from 1 to 16. (DWC3 SuperSpeed
+ USB 3.0 Controller Databook)
+ $ref: /schemas/types.yaml#/definitions/uint8
+ minimum: 1
+ maximum: 16
+
+ snps,tx-thr-num-pkt:
+ description:
+ USB TX packet threshold count. This field specifies the number of
+ packets that must be in the TXFIFO before the core can start
+ transmission for the corresponding USB transaction (burst).
+ This count is valid in both host and device modes. It is only used
+ for SuperSpeed operation.
+ Valid values are from 1 to 15. (DWC3 SuperSpeed USB 3.0 Controller
+ Databook)
+ $ref: /schemas/types.yaml#/definitions/uint8
+ minimum: 1
+ maximum: 15
+
+ snps,tx-max-burst:
+ description:
+ Max USB TX burst size. When the system bus is slower than the USB,
+ TX FIFO can underrun during a long burst. Program a smaller value
+ to this field to limit the TX burst size that the core can execute.
+ In Host mode, it only applies to SS Bulk, Isochronous, and Interrupt
+ OUT endpoints. This value is not used in device mode.
+ Valid values are from 1 to 16. (DWC3 SuperSpeed USB 3.0 Controller
+ Databook)
+ $ref: /schemas/types.yaml#/definitions/uint8
+ minimum: 1
+ maximum: 16
+
snps,rx-thr-num-pkt-prd:
description:
Periodic ESS RX packet threshold count (host mode only). Set this and
diff --git a/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml b/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml
index 5497a60cddbc..323d664ae06a 100644
--- a/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml
+++ b/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml
@@ -20,8 +20,23 @@ properties:
enum:
- ti,tps6598x
- apple,cd321x
+ - ti,tps25750
+
reg:
- maxItems: 1
+ minItems: 1
+ items:
+ - description: main PD controller address
+ - description: |
+ I2C slave address field in PBMs input data
+ which is used as the device address when writing the
+ patch for TPS25750.
+ The patch address can be any value except 0x00, 0x20,
+ 0x21, 0x22, and 0x23
+
+ reg-names:
+ items:
+ - const: main
+ - const: patch-address
wakeup-source: true
@@ -32,11 +47,46 @@ properties:
items:
- const: irq
+ connector:
+ $ref: /schemas/connector/usb-connector.yaml#
+
+ firmware-name:
+ description: |
+ Should contain the name of the default patch binary
+ file located on the firmware search path which is
+ used to switch the controller into APP mode.
+ This is used when tps25750 doesn't have an EEPROM
+ connected to it.
+ maxItems: 1
+
required:
- compatible
- reg
-additionalProperties: true
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: ti,tps25750
+ then:
+ properties:
+ reg:
+ maxItems: 2
+
+ connector:
+ required:
+ - data-role
+
+ required:
+ - connector
+ - reg-names
+ else:
+ properties:
+ reg:
+ maxItems: 1
+
+additionalProperties: false
examples:
- |
@@ -68,4 +118,36 @@ examples:
};
};
};
+
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ typec@21 {
+ compatible = "ti,tps25750";
+ reg = <0x21>, <0x0f>;
+ reg-names = "main", "patch-address";
+
+ interrupt-parent = <&msmgpio>;
+ interrupts = <100 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ firmware-name = "tps25750.bin";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&typec_pins>;
+
+ typec_con0: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ data-role = "dual";
+ port {
+ typec_ep0: endpoint {
+ remote-endpoint = <&otg_ep>;
+ };
+ };
+ };
+ };
+ };
...
diff --git a/Documentation/devicetree/bindings/usb/usb-hcd.yaml b/Documentation/devicetree/bindings/usb/usb-hcd.yaml
index 692dd60e3f73..45a19d4928af 100644
--- a/Documentation/devicetree/bindings/usb/usb-hcd.yaml
+++ b/Documentation/devicetree/bindings/usb/usb-hcd.yaml
@@ -41,7 +41,7 @@ examples:
- |
usb {
phys = <&usb2_phy1>, <&usb3_phy1>;
- phy-names = "usb";
+ phy-names = "usb2", "usb3";
#address-cells = <1>;
#size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/usb/vialab,vl817.yaml b/Documentation/devicetree/bindings/usb/vialab,vl817.yaml
index 76db9071b352..c815010ba9c2 100644
--- a/Documentation/devicetree/bindings/usb/vialab,vl817.yaml
+++ b/Documentation/devicetree/bindings/usb/vialab,vl817.yaml
@@ -37,7 +37,6 @@ properties:
required:
- compatible
- reg
- - reset-gpios
- vdd-supply
- peer-hub
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 573578db9509..309b94c328c8 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -59,6 +59,8 @@ patternProperties:
description: AD Holdings Plc.
"^adi,.*":
description: Analog Devices, Inc.
+ "^adieng,.*":
+ description: ADI Engineering, Inc.
"^advantech,.*":
description: Advantech Corporation
"^aeroflexgaisler,.*":
@@ -127,6 +129,8 @@ patternProperties:
description: Arasan Chip Systems
"^archermind,.*":
description: ArcherMind Technology (Nanjing) Co., Ltd.
+ "^arcom,.*":
+ description: Arcom Controllers
"^arctic,.*":
description: Arctic Sand
"^arcx,.*":
@@ -194,6 +198,8 @@ patternProperties:
description: Shanghai Belling Co., Ltd.
"^bhf,.*":
description: Beckhoff Automation GmbH & Co. KG
+ "^bigtreetech,.*":
+ description: Shenzhen BigTree Tech Co., LTD
"^bitmain,.*":
description: Bitmain Technologies
"^blutek,.*":
@@ -484,6 +490,8 @@ patternProperties:
description: FocalTech Systems Co.,Ltd
"^forlinx,.*":
description: Baoding Forlinx Embedded Technology Co., Ltd.
+ "^freecom,.*":
+ description: Freecom Gmbh
"^frida,.*":
description: Shenzhen Frida LCD Co., Ltd.
"^friendlyarm,.*":
@@ -496,6 +504,8 @@ patternProperties:
description: FX Technology Ltd.
"^gardena,.*":
description: GARDENA GmbH
+ "^gateway,.*":
+ description: Gateway Communications
"^gateworks,.*":
description: Gateworks Corporation
"^gcw,.*":
@@ -510,6 +520,8 @@ patternProperties:
description: GE Fanuc Intelligent Platforms Embedded Systems, Inc.
"^gemei,.*":
description: Gemei Digital Technology Co., Ltd.
+ "^gemtek,.*":
+ description: Gemtek Technology Co., Ltd.
"^genesys,.*":
description: Genesys Logic, Inc.
"^geniatech,.*":
@@ -530,6 +542,8 @@ patternProperties:
description: Shenzhen Huiding Technology Co., Ltd.
"^google,.*":
description: Google, Inc.
+ "^goramo,.*":
+ description: Goramo Gorecki
"^gplus,.*":
description: GPLUS
"^grinn,.*":
@@ -805,6 +819,8 @@ patternProperties:
description: Mantix Display Technology Co.,Ltd.
"^mapleboard,.*":
description: Mapleboard.org
+ "^marantec,.*":
+ description: Marantec electronics GmbH
"^marvell,.*":
description: Marvell Technology Group Ltd.
"^maxbotix,.*":
@@ -863,6 +879,8 @@ patternProperties:
description: MikroElektronika d.o.o.
"^mikrotik,.*":
description: MikroTik
+ "^milkv,.*":
+ description: MilkV Technology Co., Ltd
"^miniand,.*":
description: Miniand Tech
"^minix,.*":
@@ -871,6 +889,8 @@ patternProperties:
description: MiraMEMS Sensing Technology Co., Ltd.
"^mitsubishi,.*":
description: Mitsubishi Electric Corporation
+ "^mitsumi,.*":
+ description: Mitsumi Electric Co., Ltd.
"^mixel,.*":
description: Mixel, Inc.
"^miyoo,.*":
@@ -1081,6 +1101,8 @@ patternProperties:
description: Powertip Tech. Corp.
"^powervr,.*":
description: PowerVR (deprecated, use img)
+ "^powkiddy,.*":
+ description: Powkiddy
"^primux,.*":
description: Primux Trading, S.L.
"^probox2,.*":
@@ -1273,6 +1295,8 @@ patternProperties:
description: Solomon Systech Limited
"^sony,.*":
description: Sony Corporation
+ "^sophgo,.*":
+ description: Sophgo Technology Inc.
"^sourceparts,.*":
description: Source Parts Inc.
"^spansion,.*":
@@ -1420,6 +1444,8 @@ patternProperties:
description: Truly Semiconductors Limited
"^tsd,.*":
description: Theobroma Systems Design und Consulting GmbH
+ "^turing,.*":
+ description: Turing Machines, Inc.
"^tyan,.*":
description: Tyan Computer Corporation
"^u-blox,.*":
@@ -1444,6 +1470,8 @@ patternProperties:
description: United Radiant Technology Corporation
"^usi,.*":
description: Universal Scientific Industrial Co., Ltd.
+ "^usr,.*":
+ description: U.S. Robotics Corporation
"^utoo,.*":
description: Aigo Digital Technology Co., Ltd.
"^v3,.*":
diff --git a/Documentation/devicetree/bindings/watchdog/amlogic,meson-gxbb-wdt.yaml b/Documentation/devicetree/bindings/watchdog/amlogic,meson-gxbb-wdt.yaml
index 443e2e7ab467..69845ec32e81 100644
--- a/Documentation/devicetree/bindings/watchdog/amlogic,meson-gxbb-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/amlogic,meson-gxbb-wdt.yaml
@@ -15,9 +15,15 @@ allOf:
properties:
compatible:
- enum:
- - amlogic,meson-gxbb-wdt
- - amlogic,t7-wdt
+ oneOf:
+ - enum:
+ - amlogic,meson-gxbb-wdt
+ - amlogic,t7-wdt
+ - items:
+ - enum:
+ - amlogic,c3-wdt
+ - amlogic,s4-wdt
+ - const: amlogic,t7-wdt
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
index a8197632d6d2..3208adb3e52e 100644
--- a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
@@ -47,7 +47,15 @@ Optional properties for AST2500-compatible watchdogs:
is configured as push-pull, then set the pulse
polarity to active-high. The default is active-low.
-Example:
+Optional properties for AST2500- and AST2600-compatible watchdogs:
+ - aspeed,reset-mask: A bitmask indicating which peripherals will be reset if
+ the watchdog timer expires. On AST2500 this should be a
+ single word defined using the AST2500_WDT_RESET_* macros;
+ on AST2600 this should be a two-word array with the first
+ word defined using the AST2600_WDT_RESET1_* macros and the
+ second word defined using the AST2600_WDT_RESET2_* macros.
+
+Examples:
wdt1: watchdog@1e785000 {
compatible = "aspeed,ast2400-wdt";
@@ -55,3 +63,11 @@ Example:
aspeed,reset-type = "system";
aspeed,external-signal;
};
+
+ #include <dt-bindings/watchdog/aspeed-wdt.h>
+ wdt2: watchdog@1e785040 {
+ compatible = "aspeed,ast2600-wdt";
+ reg = <0x1e785040 0x40>;
+ aspeed,reset-mask = <AST2600_WDT_RESET1_DEFAULT
+ (AST2600_WDT_RESET2_DEFAULT & ~AST2600_WDT_RESET2_LPC)>;
+ };
diff --git a/Documentation/devicetree/bindings/watchdog/atmel,at91rm9200-wdt.yaml b/Documentation/devicetree/bindings/watchdog/atmel,at91rm9200-wdt.yaml
new file mode 100644
index 000000000000..7af3571d89f2
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/atmel,at91rm9200-wdt.yaml
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/watchdog/atmel,at91rm9200-wdt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Atmel AT91RM9200 System Timer Watchdog
+
+maintainers:
+ - Nicolas Ferre <nicolas.ferre@microchip.com>
+
+allOf:
+ - $ref: watchdog.yaml#
+
+properties:
+ compatible:
+ const: atmel,at91rm9200-wdt
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ watchdog@fffffd00 {
+ compatible = "atmel,at91rm9200-wdt";
+ reg = <0xfffffd00 0x10>;
+ };
diff --git a/Documentation/devicetree/bindings/watchdog/atmel-at91rm9200-wdt.txt b/Documentation/devicetree/bindings/watchdog/atmel-at91rm9200-wdt.txt
deleted file mode 100644
index d4d86cf8f9eb..000000000000
--- a/Documentation/devicetree/bindings/watchdog/atmel-at91rm9200-wdt.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-Atmel AT91RM9200 System Timer Watchdog
-
-Required properties:
-- compatible: must be "atmel,at91sam9260-wdt".
-
-Example:
- watchdog@fffffd00 {
- compatible = "atmel,at91rm9200-wdt";
- };
diff --git a/Documentation/devicetree/bindings/watchdog/cnxt,cx92755-wdt.yaml b/Documentation/devicetree/bindings/watchdog/cnxt,cx92755-wdt.yaml
new file mode 100644
index 000000000000..1844d7e026fe
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/cnxt,cx92755-wdt.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/watchdog/cnxt,cx92755-wdt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Conexant Digicolor SoCs Watchdog timer
+
+description: |
+ The watchdog functionality in Conexant Digicolor SoCs relies on the so called
+ "Agent Communication" block. This block includes the eight programmable system
+ timer counters. The first timer (called "Timer A") is the only one that can be
+ used as watchdog.
+
+allOf:
+ - $ref: watchdog.yaml#
+
+maintainers:
+ - Baruch Siach <baruch@tkos.co.il>
+
+properties:
+ compatible:
+ const: cnxt,cx92755-wdt
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ watchdog@f0000fc0 {
+ compatible = "cnxt,cx92755-wdt";
+ reg = <0xf0000fc0 0x8>;
+ clocks = <&main_clk>;
+ timeout-sec = <15>;
+ };
diff --git a/Documentation/devicetree/bindings/watchdog/da9062-wdt.txt b/Documentation/devicetree/bindings/watchdog/da9062-wdt.txt
deleted file mode 100644
index 354314d854ef..000000000000
--- a/Documentation/devicetree/bindings/watchdog/da9062-wdt.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-* Dialog Semiconductor DA9062/61 Watchdog Timer
-
-Required properties:
-
-- compatible: should be one of the following valid compatible string lines:
- "dlg,da9061-watchdog", "dlg,da9062-watchdog"
- "dlg,da9062-watchdog"
-
-Optional properties:
-- dlg,use-sw-pm: Add this property to disable the watchdog during suspend.
- Only use this option if you can't use the watchdog automatic suspend
- function during a suspend (see register CONTROL_B).
-- dlg,wdt-sd: Set what happens on watchdog timeout. If this bit is set the
- watchdog timeout triggers SHUTDOWN, if cleared the watchdog triggers
- POWERDOWN. Can be 0 or 1. Only use this option if you want to change the
- default chip's OTP setting for WATCHDOG_SD bit. If this property is NOT
- set the WATCHDOG_SD bit and on timeout watchdog behavior will match the
- chip's OTP settings.
-
-Example: DA9062
-
- pmic0: da9062@58 {
- watchdog {
- compatible = "dlg,da9062-watchdog";
- };
- };
-
-Example: DA9061 using a fall-back compatible for the DA9062 watchdog driver
-
- pmic0: da9061@58 {
- watchdog {
- compatible = "dlg,da9061-watchdog", "dlg,da9062-watchdog";
- };
- };
diff --git a/Documentation/devicetree/bindings/watchdog/digicolor-wdt.txt b/Documentation/devicetree/bindings/watchdog/digicolor-wdt.txt
deleted file mode 100644
index a882967e17d4..000000000000
--- a/Documentation/devicetree/bindings/watchdog/digicolor-wdt.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-Conexant Digicolor SoCs Watchdog timer
-
-The watchdog functionality in Conexant Digicolor SoCs relies on the so called
-"Agent Communication" block. This block includes the eight programmable system
-timer counters. The first timer (called "Timer A") is the only one that can be
-used as watchdog.
-
-Required properties:
-
-- compatible : Should be "cnxt,cx92755-wdt"
-- reg : Specifies base physical address and size of the registers
-- clocks : phandle; specifies the clock that drives the timer
-
-Optional properties:
-
-- timeout-sec : Contains the watchdog timeout in seconds
-
-Example:
-
- watchdog@f0000fc0 {
- compatible = "cnxt,cx92755-wdt";
- reg = <0xf0000fc0 0x8>;
- clocks = <&main_clk>;
- timeout-sec = <15>;
- };
diff --git a/Documentation/devicetree/bindings/watchdog/dlg,da9062-watchdog.yaml b/Documentation/devicetree/bindings/watchdog/dlg,da9062-watchdog.yaml
new file mode 100644
index 000000000000..f058628bb632
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/dlg,da9062-watchdog.yaml
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/watchdog/dlg,da9062-watchdog.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Dialog Semiconductor DA9062/61 Watchdog Timer
+
+maintainers:
+ - Steve Twiss <stwiss.opensource@diasemi.com>
+
+allOf:
+ - $ref: watchdog.yaml#
+
+properties:
+ compatible:
+ enum:
+ - dlg,da9061-watchdog
+ - dlg,da9062-watchdog
+
+ dlg,use-sw-pm:
+ type: boolean
+ description:
+ Add this property to disable the watchdog during suspend.
+ Only use this option if you can't use the watchdog automatic suspend
+ function during a suspend (see register CONTROL_B).
+
+ dlg,wdt-sd:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+ description:
+ Set what happens on watchdog timeout. If this bit is set the
+ watchdog timeout triggers SHUTDOWN, if cleared the watchdog triggers
+ POWERDOWN. Can be 0 or 1. Only use this option if you want to change the
+ default chip's OTP setting for WATCHDOG_SD bit. If this property is NOT
+ set the WATCHDOG_SD bit and on timeout watchdog behavior will match the
+ chip's OTP settings.
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ watchdog {
+ compatible = "dlg,da9062-watchdog";
+ dlg,use-sw-pm;
+ dlg,wdt-sd = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/watchdog/fsl,scu-wdt.yaml b/Documentation/devicetree/bindings/watchdog/fsl,scu-wdt.yaml
index 47701248cd8d..8b7aa922249b 100644
--- a/Documentation/devicetree/bindings/watchdog/fsl,scu-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/fsl,scu-wdt.yaml
@@ -18,7 +18,9 @@ allOf:
properties:
compatible:
items:
- - const: fsl,imx8qxp-sc-wdt
+ - enum:
+ - fsl,imx8dxl-sc-wdt
+ - fsl,imx8qxp-sc-wdt
- const: fsl,imx-sc-wdt
required:
diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml b/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
index 4b7ed1355701..9c50766bf690 100644
--- a/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
@@ -30,6 +30,11 @@ properties:
clocks:
maxItems: 1
+ fsl,ext-reset-output:
+ description:
+ When set, wdog can generate external reset from the wdog_any pin.
+ type: boolean
+
required:
- compatible
- interrupts
diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml
index 5046dfa55f13..c12bc852aedc 100644
--- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml
@@ -21,6 +21,8 @@ properties:
- qcom,apss-wdt-ipq5018
- qcom,apss-wdt-ipq5332
- qcom,apss-wdt-ipq9574
+ - qcom,apss-wdt-msm8226
+ - qcom,apss-wdt-msm8974
- qcom,apss-wdt-msm8994
- qcom,apss-wdt-qcm2290
- qcom,apss-wdt-qcs404
diff --git a/Documentation/devicetree/bindings/writing-schema.rst b/Documentation/devicetree/bindings/writing-schema.rst
index 4a381d20f2b4..0a6cf19a1459 100644
--- a/Documentation/devicetree/bindings/writing-schema.rst
+++ b/Documentation/devicetree/bindings/writing-schema.rst
@@ -159,11 +159,14 @@ It is possible to run both in a single command::
make dt_binding_check dtbs_check
It is also possible to run checks with a subset of matching schema files by
-setting the ``DT_SCHEMA_FILES`` variable to a specific schema file or pattern.
+setting the ``DT_SCHEMA_FILES`` variable to 1 or more specific schema files or
+patterns (partial match of a fixed string). Each file or pattern should be
+separated by ':'.
::
make dt_binding_check DT_SCHEMA_FILES=trivial-devices.yaml
+ make dt_binding_check DT_SCHEMA_FILES=trivial-devices.yaml:rtc.yaml
make dt_binding_check DT_SCHEMA_FILES=/gpio/
make dtbs_check DT_SCHEMA_FILES=trivial-devices.yaml
diff --git a/Documentation/doc-guide/contributing.rst b/Documentation/doc-guide/contributing.rst
index d4793826ad9a..662c7a840cd5 100644
--- a/Documentation/doc-guide/contributing.rst
+++ b/Documentation/doc-guide/contributing.rst
@@ -138,6 +138,10 @@ times, but it's highly important. If we can actually eliminate warnings
from the documentation build, then we can start expecting developers to
avoid adding new ones.
+In addition to warnings from the regular documentation build, you can also
+run ``make refcheckdocs`` to find references to nonexistent documentation
+files.
+
Languishing kerneldoc comments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/driver-api/80211/mac80211.rst b/Documentation/driver-api/80211/mac80211.rst
index 67d2e58b45e4..e38a220401f5 100644
--- a/Documentation/driver-api/80211/mac80211.rst
+++ b/Documentation/driver-api/80211/mac80211.rst
@@ -120,7 +120,7 @@ functions/definitions
ieee80211_rx
ieee80211_rx_ni
ieee80211_rx_irqsafe
- ieee80211_tx_status
+ ieee80211_tx_status_skb
ieee80211_tx_status_ni
ieee80211_tx_status_irqsafe
ieee80211_rts_get
diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst
index f92a32d095d9..0c153d79ccc4 100644
--- a/Documentation/driver-api/dma-buf.rst
+++ b/Documentation/driver-api/dma-buf.rst
@@ -5,14 +5,30 @@ The dma-buf subsystem provides the framework for sharing buffers for
hardware (DMA) access across multiple device drivers and subsystems, and
for synchronizing asynchronous hardware access.
-This is used, for example, by drm "prime" multi-GPU support, but is of
-course not limited to GPU use cases.
-
-The three main components of this are: (1) dma-buf, representing a
-sg_table and exposed to userspace as a file descriptor to allow passing
-between devices, (2) fence, which provides a mechanism to signal when
-one device has finished access, and (3) reservation, which manages the
-shared or exclusive fence(s) associated with the buffer.
+As an example, it is used extensively by the DRM subsystem to exchange
+buffers between processes, contexts, library APIs within the same
+process, and also to exchange buffers with other subsystems such as
+V4L2.
+
+This document describes the way in which kernel subsystems can use and
+interact with the three main primitives offered by dma-buf:
+
+ - dma-buf, representing a sg_table and exposed to userspace as a file
+ descriptor to allow passing between processes, subsystems, devices,
+ etc;
+ - dma-fence, providing a mechanism to signal when an asynchronous
+ hardware operation has completed; and
+ - dma-resv, which manages a set of dma-fences for a particular dma-buf
+ allowing implicit (kernel-ordered) synchronization of work to
+ preserve the illusion of coherent access
+
+
+Userspace API principles and use
+--------------------------------
+
+For more details on how to design your subsystem's API for dma-buf use, please
+see Documentation/userspace-api/dma-buf-alloc-exchange.rst.
+
Shared DMA Buffers
------------------
diff --git a/Documentation/driver-api/dpll.rst b/Documentation/driver-api/dpll.rst
new file mode 100644
index 000000000000..e3d593841aa7
--- /dev/null
+++ b/Documentation/driver-api/dpll.rst
@@ -0,0 +1,551 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===============================
+The Linux kernel dpll subsystem
+===============================
+
+DPLL
+====
+
+PLL - Phase Locked Loop is an electronic circuit which syntonizes clock
+signal of a device with an external clock signal. Effectively enabling
+device to run on the same clock signal beat as provided on a PLL input.
+
+DPLL - Digital Phase Locked Loop is an integrated circuit which in
+addition to plain PLL behavior incorporates a digital phase detector
+and may have digital divider in the loop. As a result, the frequency on
+DPLL's input and output may be configurable.
+
+Subsystem
+=========
+
+The main purpose of dpll subsystem is to provide general interface
+to configure devices that use any kind of Digital PLL and could use
+different sources of input signal to synchronize to, as well as
+different types of outputs.
+The main interface is NETLINK_GENERIC based protocol with an event
+monitoring multicast group defined.
+
+Device object
+=============
+
+Single dpll device object means single Digital PLL circuit and bunch of
+connected pins.
+It reports the supported modes of operation and current status to the
+user in response to the `do` request of netlink command
+``DPLL_CMD_DEVICE_GET`` and list of dplls registered in the subsystem
+with `dump` netlink request of the same command.
+Changing the configuration of dpll device is done with `do` request of
+netlink ``DPLL_CMD_DEVICE_SET`` command.
+A device handle is ``DPLL_A_ID``, it shall be provided to get or set
+configuration of particular device in the system. It can be obtained
+with a ``DPLL_CMD_DEVICE_GET`` `dump` request or
+a ``DPLL_CMD_DEVICE_ID_GET`` `do` request, where the one must provide
+attributes that result in single device match.
+
+Pin object
+==========
+
+A pin is amorphic object which represents either input or output, it
+could be internal component of the device, as well as externally
+connected.
+The number of pins per dpll vary, but usually multiple pins shall be
+provided for a single dpll device.
+Pin's properties, capabilities and status is provided to the user in
+response to `do` request of netlink ``DPLL_CMD_PIN_GET`` command.
+It is also possible to list all the pins that were registered in the
+system with `dump` request of ``DPLL_CMD_PIN_GET`` command.
+Configuration of a pin can be changed by `do` request of netlink
+``DPLL_CMD_PIN_SET`` command.
+Pin handle is a ``DPLL_A_PIN_ID``, it shall be provided to get or set
+configuration of particular pin in the system. It can be obtained with
+``DPLL_CMD_PIN_GET`` `dump` request or ``DPLL_CMD_PIN_ID_GET`` `do`
+request, where user provides attributes that result in single pin match.
+
+Pin selection
+=============
+
+In general, selected pin (the one which signal is driving the dpll
+device) can be obtained from ``DPLL_A_PIN_STATE`` attribute, and only
+one pin shall be in ``DPLL_PIN_STATE_CONNECTED`` state for any dpll
+device.
+
+Pin selection can be done either manually or automatically, depending
+on hardware capabilities and active dpll device work mode
+(``DPLL_A_MODE`` attribute). The consequence is that there are
+differences for each mode in terms of available pin states, as well as
+for the states the user can request for a dpll device.
+
+In manual mode (``DPLL_MODE_MANUAL``) the user can request or receive
+one of following pin states:
+
+- ``DPLL_PIN_STATE_CONNECTED`` - the pin is used to drive dpll device
+- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin is not used to drive dpll
+ device
+
+In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can request or
+receive one of following pin states:
+
+- ``DPLL_PIN_STATE_SELECTABLE`` - the pin shall be considered as valid
+ input for automatic selection algorithm
+- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin shall be not considered as
+ a valid input for automatic selection algorithm
+
+In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can only receive
+pin state ``DPLL_PIN_STATE_CONNECTED`` once automatic selection
+algorithm locks a dpll device with one of the inputs.
+
+Shared pins
+===========
+
+A single pin object can be attached to multiple dpll devices.
+Then there are two groups of configuration knobs:
+
+1) Set on a pin - the configuration affects all dpll devices pin is
+ registered to (i.e., ``DPLL_A_PIN_FREQUENCY``),
+2) Set on a pin-dpll tuple - the configuration affects only selected
+ dpll device (i.e., ``DPLL_A_PIN_PRIO``, ``DPLL_A_PIN_STATE``,
+ ``DPLL_A_PIN_DIRECTION``).
+
+MUX-type pins
+=============
+
+A pin can be MUX-type, it aggregates child pins and serves as a pin
+multiplexer. One or more pins are registered with MUX-type instead of
+being directly registered to a dpll device.
+Pins registered with a MUX-type pin provide user with additional nested
+attribute ``DPLL_A_PIN_PARENT_PIN`` for each parent they were registered
+with.
+If a pin was registered with multiple parent pins, they behave like a
+multiple output multiplexer. In this case output of a
+``DPLL_CMD_PIN_GET`` would contain multiple pin-parent nested
+attributes with current state related to each parent, like::
+
+ 'pin': [{{
+ 'clock-id': 282574471561216,
+ 'module-name': 'ice',
+ 'capabilities': 4,
+ 'id': 13,
+ 'parent-pin': [
+ {'parent-id': 2, 'state': 'connected'},
+ {'parent-id': 3, 'state': 'disconnected'}
+ ],
+ 'type': 'synce-eth-port'
+ }}]
+
+Only one child pin can provide its signal to the parent MUX-type pin at
+a time, the selection is done by requesting change of a child pin state
+on desired parent, with the use of ``DPLL_A_PIN_PARENT`` nested
+attribute. Example of netlink `set state on parent pin` message format:
+
+ ========================== =============================================
+ ``DPLL_A_PIN_ID`` child pin id
+ ``DPLL_A_PIN_PARENT_PIN`` nested attribute for requesting configuration
+ related to parent pin
+ ``DPLL_A_PIN_PARENT_ID`` parent pin id
+ ``DPLL_A_PIN_STATE`` requested pin state on parent
+ ========================== =============================================
+
+Pin priority
+============
+
+Some devices might offer a capability of automatic pin selection mode
+(enum value ``DPLL_MODE_AUTOMATIC`` of ``DPLL_A_MODE`` attribute).
+Usually, automatic selection is performed on the hardware level, which
+means only pins directly connected to the dpll can be used for automatic
+input pin selection.
+In automatic selection mode, the user cannot manually select a input
+pin for the device, instead the user shall provide all directly
+connected pins with a priority ``DPLL_A_PIN_PRIO``, the device would
+pick a highest priority valid signal and use it to control the DPLL
+device. Example of netlink `set priority on parent pin` message format:
+
+ ============================ =============================================
+ ``DPLL_A_PIN_ID`` configured pin id
+ ``DPLL_A_PIN_PARENT_DEVICE`` nested attribute for requesting configuration
+ related to parent dpll device
+ ``DPLL_A_PIN_PARENT_ID`` parent dpll device id
+ ``DPLL_A_PIN_PRIO`` requested pin prio on parent dpll
+ ============================ =============================================
+
+Child pin of MUX-type pin is not capable of automatic input pin selection,
+in order to configure active input of a MUX-type pin, the user needs to
+request desired pin state of the child pin on the parent pin,
+as described in the ``MUX-type pins`` chapter.
+
+Phase offset measurement and adjustment
+========================================
+
+Device may provide ability to measure a phase difference between signals
+on a pin and its parent dpll device. If pin-dpll phase offset measurement
+is supported, it shall be provided with ``DPLL_A_PIN_PHASE_OFFSET``
+attribute for each parent dpll device.
+
+Device may also provide ability to adjust a signal phase on a pin.
+If pin phase adjustment is supported, minimal and maximal values that pin
+handle shall be provide to the user on ``DPLL_CMD_PIN_GET`` respond
+with ``DPLL_A_PIN_PHASE_ADJUST_MIN`` and ``DPLL_A_PIN_PHASE_ADJUST_MAX``
+attributes. Configured phase adjust value is provided with
+``DPLL_A_PIN_PHASE_ADJUST`` attribute of a pin, and value change can be
+requested with the same attribute with ``DPLL_CMD_PIN_SET`` command.
+
+ =============================== ======================================
+ ``DPLL_A_PIN_ID`` configured pin id
+ ``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase adjustment
+ ``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase adjustment
+ ``DPLL_A_PIN_PHASE_ADJUST`` attr configured value of phase
+ adjustment on parent dpll device
+ ``DPLL_A_PIN_PARENT_DEVICE`` nested attribute for requesting
+ configuration on given parent dpll
+ device
+ ``DPLL_A_PIN_PARENT_ID`` parent dpll device id
+ ``DPLL_A_PIN_PHASE_OFFSET`` attr measured phase difference
+ between a pin and parent dpll device
+ =============================== ======================================
+
+All phase related values are provided in pico seconds, which represents
+time difference between signals phase. The negative value means that
+phase of signal on pin is earlier in time than dpll's signal. Positive
+value means that phase of signal on pin is later in time than signal of
+a dpll.
+
+Phase adjust (also min and max) values are integers, but measured phase
+offset values are fractional with 3-digit decimal places and shell be
+divided with ``DPLL_PIN_PHASE_OFFSET_DIVIDER`` to get integer part and
+modulo divided to get fractional part.
+
+Configuration commands group
+============================
+
+Configuration commands are used to get information about registered
+dpll devices (and pins), as well as set configuration of device or pins.
+As dpll devices must be abstracted and reflect real hardware,
+there is no way to add new dpll device via netlink from user space and
+each device should be registered by its driver.
+
+All netlink commands require ``GENL_ADMIN_PERM``. This is to prevent
+any spamming/DoS from unauthorized userspace applications.
+
+List of netlink commands with possible attributes
+=================================================
+
+Constants identifying command types for dpll device uses a
+``DPLL_CMD_`` prefix and suffix according to command purpose.
+The dpll device related attributes use a ``DPLL_A_`` prefix and
+suffix according to attribute purpose.
+
+ ==================================== =================================
+ ``DPLL_CMD_DEVICE_ID_GET`` command to get device ID
+ ``DPLL_A_MODULE_NAME`` attr module name of registerer
+ ``DPLL_A_CLOCK_ID`` attr Unique Clock Identifier
+ (EUI-64), as defined by the
+ IEEE 1588 standard
+ ``DPLL_A_TYPE`` attr type of dpll device
+ ==================================== =================================
+
+ ==================================== =================================
+ ``DPLL_CMD_DEVICE_GET`` command to get device info or
+ dump list of available devices
+ ``DPLL_A_ID`` attr unique dpll device ID
+ ``DPLL_A_MODULE_NAME`` attr module name of registerer
+ ``DPLL_A_CLOCK_ID`` attr Unique Clock Identifier
+ (EUI-64), as defined by the
+ IEEE 1588 standard
+ ``DPLL_A_MODE`` attr selection mode
+ ``DPLL_A_MODE_SUPPORTED`` attr available selection modes
+ ``DPLL_A_LOCK_STATUS`` attr dpll device lock status
+ ``DPLL_A_TEMP`` attr device temperature info
+ ``DPLL_A_TYPE`` attr type of dpll device
+ ==================================== =================================
+
+ ==================================== =================================
+ ``DPLL_CMD_DEVICE_SET`` command to set dpll device config
+ ``DPLL_A_ID`` attr internal dpll device index
+ ``DPLL_A_MODE`` attr selection mode to configure
+ ==================================== =================================
+
+Constants identifying command types for pins uses a
+``DPLL_CMD_PIN_`` prefix and suffix according to command purpose.
+The pin related attributes use a ``DPLL_A_PIN_`` prefix and suffix
+according to attribute purpose.
+
+ ==================================== =================================
+ ``DPLL_CMD_PIN_ID_GET`` command to get pin ID
+ ``DPLL_A_PIN_MODULE_NAME`` attr module name of registerer
+ ``DPLL_A_PIN_CLOCK_ID`` attr Unique Clock Identifier
+ (EUI-64), as defined by the
+ IEEE 1588 standard
+ ``DPLL_A_PIN_BOARD_LABEL`` attr pin board label provided
+ by registerer
+ ``DPLL_A_PIN_PANEL_LABEL`` attr pin panel label provided
+ by registerer
+ ``DPLL_A_PIN_PACKAGE_LABEL`` attr pin package label provided
+ by registerer
+ ``DPLL_A_PIN_TYPE`` attr type of a pin
+ ==================================== =================================
+
+ ==================================== ==================================
+ ``DPLL_CMD_PIN_GET`` command to get pin info or dump
+ list of available pins
+ ``DPLL_A_PIN_ID`` attr unique a pin ID
+ ``DPLL_A_PIN_MODULE_NAME`` attr module name of registerer
+ ``DPLL_A_PIN_CLOCK_ID`` attr Unique Clock Identifier
+ (EUI-64), as defined by the
+ IEEE 1588 standard
+ ``DPLL_A_PIN_BOARD_LABEL`` attr pin board label provided
+ by registerer
+ ``DPLL_A_PIN_PANEL_LABEL`` attr pin panel label provided
+ by registerer
+ ``DPLL_A_PIN_PACKAGE_LABEL`` attr pin package label provided
+ by registerer
+ ``DPLL_A_PIN_TYPE`` attr type of a pin
+ ``DPLL_A_PIN_FREQUENCY`` attr current frequency of a pin
+ ``DPLL_A_PIN_FREQUENCY_SUPPORTED`` nested attr provides supported
+ frequencies
+ ``DPLL_A_PIN_ANY_FREQUENCY_MIN`` attr minimum value of frequency
+ ``DPLL_A_PIN_ANY_FREQUENCY_MAX`` attr maximum value of frequency
+ ``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase
+ adjustment
+ ``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase
+ adjustment
+ ``DPLL_A_PIN_PHASE_ADJUST`` attr configured value of phase
+ adjustment on parent device
+ ``DPLL_A_PIN_PARENT_DEVICE`` nested attr for each parent device
+ the pin is connected with
+ ``DPLL_A_PIN_PARENT_ID`` attr parent dpll device id
+ ``DPLL_A_PIN_PRIO`` attr priority of pin on the
+ dpll device
+ ``DPLL_A_PIN_STATE`` attr state of pin on the parent
+ dpll device
+ ``DPLL_A_PIN_DIRECTION`` attr direction of a pin on the
+ parent dpll device
+ ``DPLL_A_PIN_PHASE_OFFSET`` attr measured phase difference
+ between a pin and parent dpll
+ ``DPLL_A_PIN_PARENT_PIN`` nested attr for each parent pin
+ the pin is connected with
+ ``DPLL_A_PIN_PARENT_ID`` attr parent pin id
+ ``DPLL_A_PIN_STATE`` attr state of pin on the parent
+ pin
+ ``DPLL_A_PIN_CAPABILITIES`` attr bitmask of pin capabilities
+ ==================================== ==================================
+
+ ==================================== =================================
+ ``DPLL_CMD_PIN_SET`` command to set pins configuration
+ ``DPLL_A_PIN_ID`` attr unique a pin ID
+ ``DPLL_A_PIN_FREQUENCY`` attr requested frequency of a pin
+ ``DPLL_A_PIN_PHASE_ADJUST`` attr requested value of phase
+ adjustment on parent device
+ ``DPLL_A_PIN_PARENT_DEVICE`` nested attr for each parent dpll
+ device configuration request
+ ``DPLL_A_PIN_PARENT_ID`` attr parent dpll device id
+ ``DPLL_A_PIN_DIRECTION`` attr requested direction of a pin
+ ``DPLL_A_PIN_PRIO`` attr requested priority of pin on
+ the dpll device
+ ``DPLL_A_PIN_STATE`` attr requested state of pin on
+ the dpll device
+ ``DPLL_A_PIN_PARENT_PIN`` nested attr for each parent pin
+ configuration request
+ ``DPLL_A_PIN_PARENT_ID`` attr parent pin id
+ ``DPLL_A_PIN_STATE`` attr requested state of pin on
+ parent pin
+ ==================================== =================================
+
+Netlink dump requests
+=====================
+
+The ``DPLL_CMD_DEVICE_GET`` and ``DPLL_CMD_PIN_GET`` commands are
+capable of dump type netlink requests, in which case the response is in
+the same format as for their ``do`` request, but every device or pin
+registered in the system is returned.
+
+SET commands format
+===================
+
+``DPLL_CMD_DEVICE_SET`` - to target a dpll device, the user provides
+``DPLL_A_ID``, which is unique identifier of dpll device in the system,
+as well as parameter being configured (``DPLL_A_MODE``).
+
+``DPLL_CMD_PIN_SET`` - to target a pin user must provide a
+``DPLL_A_PIN_ID``, which is unique identifier of a pin in the system.
+Also configured pin parameters must be added.
+If ``DPLL_A_PIN_FREQUENCY`` is configured, this affects all the dpll
+devices that are connected with the pin, that is why frequency attribute
+shall not be enclosed in ``DPLL_A_PIN_PARENT_DEVICE``.
+Other attributes: ``DPLL_A_PIN_PRIO``, ``DPLL_A_PIN_STATE`` or
+``DPLL_A_PIN_DIRECTION`` must be enclosed in
+``DPLL_A_PIN_PARENT_DEVICE`` as their configuration relates to only one
+of parent dplls, targeted by ``DPLL_A_PIN_PARENT_ID`` attribute which is
+also required inside that nest.
+For MUX-type pins the ``DPLL_A_PIN_STATE`` attribute is configured in
+similar way, by enclosing required state in ``DPLL_A_PIN_PARENT_PIN``
+nested attribute and targeted parent pin id in ``DPLL_A_PIN_PARENT_ID``.
+
+In general, it is possible to configure multiple parameters at once, but
+internally each parameter change will be invoked separately, where order
+of configuration is not guaranteed by any means.
+
+Configuration pre-defined enums
+===============================
+
+.. kernel-doc:: include/uapi/linux/dpll.h
+
+Notifications
+=============
+
+dpll device can provide notifications regarding status changes of the
+device, i.e. lock status changes, input/output changes or other alarms.
+There is one multicast group that is used to notify user-space apps via
+netlink socket: ``DPLL_MCGRP_MONITOR``
+
+Notifications messages:
+
+ ============================== =====================================
+ ``DPLL_CMD_DEVICE_CREATE_NTF`` dpll device was created
+ ``DPLL_CMD_DEVICE_DELETE_NTF`` dpll device was deleted
+ ``DPLL_CMD_DEVICE_CHANGE_NTF`` dpll device has changed
+ ``DPLL_CMD_PIN_CREATE_NTF`` dpll pin was created
+ ``DPLL_CMD_PIN_DELETE_NTF`` dpll pin was deleted
+ ``DPLL_CMD_PIN_CHANGE_NTF`` dpll pin has changed
+ ============================== =====================================
+
+Events format is the same as for the corresponding get command.
+Format of ``DPLL_CMD_DEVICE_`` events is the same as response of
+``DPLL_CMD_DEVICE_GET``.
+Format of ``DPLL_CMD_PIN_`` events is same as response of
+``DPLL_CMD_PIN_GET``.
+
+Device driver implementation
+============================
+
+Device is allocated by dpll_device_get() call. Second call with the
+same arguments will not create new object but provides pointer to
+previously created device for given arguments, it also increases
+refcount of that object.
+Device is deallocated by dpll_device_put() call, which first
+decreases the refcount, once refcount is cleared the object is
+destroyed.
+
+Device should implement set of operations and register device via
+dpll_device_register() at which point it becomes available to the
+users. Multiple driver instances can obtain reference to it with
+dpll_device_get(), as well as register dpll device with their own
+ops and priv.
+
+The pins are allocated separately with dpll_pin_get(), it works
+similarly to dpll_device_get(). Function first creates object and then
+for each call with the same arguments only the object refcount
+increases. Also dpll_pin_put() works similarly to dpll_device_put().
+
+A pin can be registered with parent dpll device or parent pin, depending
+on hardware needs. Each registration requires registerer to provide set
+of pin callbacks, and private data pointer for calling them:
+
+- dpll_pin_register() - register pin with a dpll device,
+- dpll_pin_on_pin_register() - register pin with another MUX type pin.
+
+Notifications of adding or removing dpll devices are created within
+subsystem itself.
+Notifications about registering/deregistering pins are also invoked by
+the subsystem.
+Notifications about status changes either of dpll device or a pin are
+invoked in two ways:
+
+- after successful change was requested on dpll subsystem, the subsystem
+ calls corresponding notification,
+- requested by device driver with dpll_device_change_ntf() or
+ dpll_pin_change_ntf() when driver informs about the status change.
+
+The device driver using dpll interface is not required to implement all
+the callback operation. Nevertheless, there are few required to be
+implemented.
+Required dpll device level callback operations:
+
+- ``.mode_get``,
+- ``.lock_status_get``.
+
+Required pin level callback operations:
+
+- ``.state_on_dpll_get`` (pins registered with dpll device),
+- ``.state_on_pin_get`` (pins registered with parent pin),
+- ``.direction_get``.
+
+Every other operation handler is checked for existence and
+``-EOPNOTSUPP`` is returned in case of absence of specific handler.
+
+The simplest implementation is in the OCP TimeCard driver. The ops
+structures are defined like this:
+
+.. code-block:: c
+
+ static const struct dpll_device_ops dpll_ops = {
+ .lock_status_get = ptp_ocp_dpll_lock_status_get,
+ .mode_get = ptp_ocp_dpll_mode_get,
+ .mode_supported = ptp_ocp_dpll_mode_supported,
+ };
+
+ static const struct dpll_pin_ops dpll_pins_ops = {
+ .frequency_get = ptp_ocp_dpll_frequency_get,
+ .frequency_set = ptp_ocp_dpll_frequency_set,
+ .direction_get = ptp_ocp_dpll_direction_get,
+ .direction_set = ptp_ocp_dpll_direction_set,
+ .state_on_dpll_get = ptp_ocp_dpll_state_get,
+ };
+
+The registration part is then looks like this part:
+
+.. code-block:: c
+
+ clkid = pci_get_dsn(pdev);
+ bp->dpll = dpll_device_get(clkid, 0, THIS_MODULE);
+ if (IS_ERR(bp->dpll)) {
+ err = PTR_ERR(bp->dpll);
+ dev_err(&pdev->dev, "dpll_device_alloc failed\n");
+ goto out;
+ }
+
+ err = dpll_device_register(bp->dpll, DPLL_TYPE_PPS, &dpll_ops, bp);
+ if (err)
+ goto out;
+
+ for (i = 0; i < OCP_SMA_NUM; i++) {
+ bp->sma[i].dpll_pin = dpll_pin_get(clkid, i, THIS_MODULE, &bp->sma[i].dpll_prop);
+ if (IS_ERR(bp->sma[i].dpll_pin)) {
+ err = PTR_ERR(bp->dpll);
+ goto out_dpll;
+ }
+
+ err = dpll_pin_register(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops,
+ &bp->sma[i]);
+ if (err) {
+ dpll_pin_put(bp->sma[i].dpll_pin);
+ goto out_dpll;
+ }
+ }
+
+In the error path we have to rewind every allocation in the reverse order:
+
+.. code-block:: c
+
+ while (i) {
+ --i;
+ dpll_pin_unregister(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops, &bp->sma[i]);
+ dpll_pin_put(bp->sma[i].dpll_pin);
+ }
+ dpll_device_put(bp->dpll);
+
+More complex example can be found in Intel's ICE driver or nVidia's mlx5 driver.
+
+SyncE enablement
+================
+For SyncE enablement it is required to allow control over dpll device
+for a software application which monitors and configures the inputs of
+dpll device in response to current state of a dpll device and its
+inputs.
+In such scenario, dpll device input signal shall be also configurable
+to drive dpll with signal recovered from the PHY netdevice.
+This is done by exposing a pin to the netdevice - attaching pin to the
+netdevice itself with
+``netdev_dpll_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin)``.
+Exposed pin id handle ``DPLL_A_PIN_ID`` is then identifiable by the user
+as it is attached to rtnetlink respond to get ``RTM_NEWLINK`` command in
+nested attribute ``IFLA_DPLL_PIN``.
diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst
index 8be086b3f829..c5f99d834ec5 100644
--- a/Documentation/driver-api/driver-model/devres.rst
+++ b/Documentation/driver-api/driver-model/devres.rst
@@ -322,10 +322,8 @@ IOMAP
devm_platform_ioremap_resource_byname()
devm_platform_get_and_ioremap_resource()
devm_iounmap()
- pcim_iomap()
- pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
- pcim_iomap_table() : array of mapped addresses indexed by BAR
- pcim_iounmap()
+
+ Note: For the PCI devices the specific pcim_*() functions may be used, see below.
IRQ
devm_free_irq()
@@ -392,8 +390,16 @@ PCI
devm_pci_alloc_host_bridge() : managed PCI host bridge allocation
devm_pci_remap_cfgspace() : ioremap PCI configuration space
devm_pci_remap_cfg_resource() : ioremap PCI configuration space resource
+
pcim_enable_device() : after success, all PCI ops become managed
+ pcim_iomap() : do iomap() on a single BAR
+ pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
+ pcim_iomap_regions_request_all() : do request_region() on all and iomap() on multiple BARs
+ pcim_iomap_table() : array of mapped addresses indexed by BAR
+ pcim_iounmap() : do iounmap() on a single BAR
+ pcim_iounmap_regions() : do iounmap() and release_region() on multiple BARs
pcim_pin_device() : keep PCI device enabled after release
+ pcim_set_mwi() : enable Memory-Write-Invalidate PCI transaction
PHY
devm_usb_get_phy()
diff --git a/Documentation/driver-api/gpio/consumer.rst b/Documentation/driver-api/gpio/consumer.rst
index de6fc79ad6f0..3e588b9d678c 100644
--- a/Documentation/driver-api/gpio/consumer.rst
+++ b/Documentation/driver-api/gpio/consumer.rst
@@ -29,6 +29,10 @@ warnings. These stubs are used for two use cases:
will use it under other compile-time configurations. In this case the
consumer must make sure not to call into these functions, or the user will
be met with console warnings that may be perceived as intimidating.
+ Combining truly optional GPIOLIB usage with calls to
+ ``[devm_]gpiod_get_optional()`` is a *bad idea*, and will result in weird
+ error messages. Use the ordinary getter functions with optional GPIOLIB:
+ some open coding of error handling should be expected when you do this.
All the functions that work with the descriptor-based GPIO interface are
prefixed with ``gpiod_``. The ``gpio_`` prefix is used for the legacy
diff --git a/Documentation/driver-api/i3c/protocol.rst b/Documentation/driver-api/i3c/protocol.rst
index 02653defa011..23a0b93c62b1 100644
--- a/Documentation/driver-api/i3c/protocol.rst
+++ b/Documentation/driver-api/i3c/protocol.rst
@@ -71,8 +71,8 @@ During DAA, each I3C device reports 3 important things:
related capabilities
* DCR: Device Characteristic Register. This 8-bit register describes the
functionalities provided by the device
-* Provisional ID: A 48-bit unique identifier. On a given bus there should be no
- Provisional ID collision, otherwise the discovery mechanism may fail.
+* Provisioned ID: A 48-bit unique identifier. On a given bus there should be no
+ Provisioned ID collision, otherwise the discovery mechanism may fail.
I3C slave events
================
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index 1e16a40da3ba..f549a68951d7 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -114,6 +114,7 @@ available subsections can be seen below.
zorro
hte/index
wmi
+ dpll
.. only:: subproject and html
diff --git a/Documentation/driver-api/media/camera-sensor.rst b/Documentation/driver-api/media/camera-sensor.rst
index 93f4f2536c25..6456145f96ed 100644
--- a/Documentation/driver-api/media/camera-sensor.rst
+++ b/Documentation/driver-api/media/camera-sensor.rst
@@ -1,8 +1,14 @@
.. SPDX-License-Identifier: GPL-2.0
+.. _media_writing_camera_sensor_drivers:
+
Writing camera sensor drivers
=============================
+This document covers the in-kernel APIs only. For the best practices on
+userspace API implementation in camera sensor drivers, please see
+:ref:`media_using_camera_sensor_drivers`.
+
CSI-2 and parallel (BT.601 and BT.656) busses
---------------------------------------------
@@ -13,7 +19,7 @@ Handling clocks
Camera sensors have an internal clock tree including a PLL and a number of
divisors. The clock tree is generally configured by the driver based on a few
-input parameters that are specific to the hardware:: the external clock frequency
+input parameters that are specific to the hardware: the external clock frequency
and the link frequency. The two parameters generally are obtained from system
firmware. **No other frequencies should be used in any circumstances.**
@@ -32,110 +38,61 @@ can rely on this frequency being used.
Devicetree
~~~~~~~~~~
-The currently preferred way to achieve this is using ``assigned-clocks``,
-``assigned-clock-parents`` and ``assigned-clock-rates`` properties. See
-``Documentation/devicetree/bindings/clock/clock-bindings.txt`` for more
-information. The driver then gets the frequency using ``clk_get_rate()``.
+The preferred way to achieve this is using ``assigned-clocks``,
+``assigned-clock-parents`` and ``assigned-clock-rates`` properties. See the
+`clock device tree bindings
+<https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/clock/clock.yaml>`_
+for more information. The driver then gets the frequency using
+``clk_get_rate()``.
This approach has the drawback that there's no guarantee that the frequency
hasn't been modified directly or indirectly by another driver, or supported by
the board's clock tree to begin with. Changes to the Common Clock Framework API
are required to ensure reliability.
-Frame size
-----------
-
-There are two distinct ways to configure the frame size produced by camera
-sensors.
-
-Freely configurable camera sensor drivers
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Freely configurable camera sensor drivers expose the device's internal
-processing pipeline as one or more sub-devices with different cropping and
-scaling configurations. The output size of the device is the result of a series
-of cropping and scaling operations from the device's pixel array's size.
-
-An example of such a driver is the CCS driver (see ``drivers/media/i2c/ccs``).
-
-Register list based drivers
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Register list based drivers generally, instead of able to configure the device
-they control based on user requests, are limited to a number of preset
-configurations that combine a number of different parameters that on hardware
-level are independent. How a driver picks such configuration is based on the
-format set on a source pad at the end of the device's internal pipeline.
-
-Most sensor drivers are implemented this way, see e.g.
-``drivers/media/i2c/imx319.c`` for an example.
-
-Frame interval configuration
-----------------------------
-
-There are two different methods for obtaining possibilities for different frame
-intervals as well as configuring the frame interval. Which one to implement
-depends on the type of the device.
-
-Raw camera sensors
-~~~~~~~~~~~~~~~~~~
-
-Instead of a high level parameter such as frame interval, the frame interval is
-a result of the configuration of a number of camera sensor implementation
-specific parameters. Luckily, these parameters tend to be the same for more or
-less all modern raw camera sensors.
-
-The frame interval is calculated using the following equation::
-
- frame interval = (analogue crop width + horizontal blanking) *
- (analogue crop height + vertical blanking) / pixel rate
-
-The formula is bus independent and is applicable for raw timing parameters on
-large variety of devices beyond camera sensors. Devices that have no analogue
-crop, use the full source image size, i.e. pixel array size.
-
-Horizontal and vertical blanking are specified by ``V4L2_CID_HBLANK`` and
-``V4L2_CID_VBLANK``, respectively. The unit of the ``V4L2_CID_HBLANK`` control
-is pixels and the unit of the ``V4L2_CID_VBLANK`` is lines. The pixel rate in
-the sensor's **pixel array** is specified by ``V4L2_CID_PIXEL_RATE`` in the same
-sub-device. The unit of that control is pixels per second.
-
-Register list based drivers need to implement read-only sub-device nodes for the
-purpose. Devices that are not register list based need these to configure the
-device's internal processing pipeline.
-
-The first entity in the linear pipeline is the pixel array. The pixel array may
-be followed by other entities that are there to allow configuring binning,
-skipping, scaling or digital crop :ref:`v4l2-subdev-selections`.
-
-USB cameras etc. devices
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-USB video class hardware, as well as many cameras offering a similar higher
-level interface natively, generally use the concept of frame interval (or frame
-rate) on device level in firmware or hardware. This means lower level controls
-implemented by raw cameras may not be used on uAPI (or even kAPI) to control the
-frame interval on these devices.
-
Power management
----------------
-Always use runtime PM to manage the power states of your device. Camera sensor
-drivers are in no way special in this respect: they are responsible for
-controlling the power state of the device they otherwise control as well. In
-general, the device must be powered on at least when its registers are being
-accessed and when it is streaming.
-
-Existing camera sensor drivers may rely on the old
-struct v4l2_subdev_core_ops->s_power() callback for bridge or ISP drivers to
-manage their power state. This is however **deprecated**. If you feel you need
-to begin calling an s_power from an ISP or a bridge driver, instead please add
-runtime PM support to the sensor driver you are using. Likewise, new drivers
-should not use s_power.
-
-Please see examples in e.g. ``drivers/media/i2c/ov8856.c`` and
-``drivers/media/i2c/ccs/ccs-core.c``. The two drivers work in both ACPI
-and DT based systems.
+Camera sensors are used in conjunction with other devices to form a camera
+pipeline. They must obey the rules listed herein to ensure coherent power
+management over the pipeline.
+
+Camera sensor drivers are responsible for controlling the power state of the
+device they otherwise control as well. They shall use runtime PM to manage
+power states. Runtime PM shall be enabled at probe time and disabled at remove
+time. Drivers should enable runtime PM autosuspend.
+
+The runtime PM handlers shall handle clocks, regulators, GPIOs, and other
+system resources required to power the sensor up and down. For drivers that
+don't use any of those resources (such as drivers that support ACPI systems
+only), the runtime PM handlers may be left unimplemented.
+
+In general, the device shall be powered on at least when its registers are
+being accessed and when it is streaming. Drivers should use
+``pm_runtime_resume_and_get()`` when starting streaming and
+``pm_runtime_put()`` or ``pm_runtime_put_autosuspend()`` when stopping
+streaming. They may power the device up at probe time (for example to read
+identification registers), but should not keep it powered unconditionally after
+probe.
+
+At system suspend time, the whole camera pipeline must stop streaming, and
+restart when the system is resumed. This requires coordination between the
+camera sensor and the rest of the camera pipeline. Bridge drivers are
+responsible for this coordination, and instruct camera sensors to stop and
+restart streaming by calling the appropriate subdev operations
+(``.s_stream()``, ``.enable_streams()`` or ``.disable_streams()``). Camera
+sensor drivers shall therefore **not** keep track of the streaming state to
+stop streaming in the PM suspend handler and restart it in the resume handler.
+Drivers should in general not implement the system PM handlers.
+
+Camera sensor drivers shall **not** implement the subdev ``.s_power()``
+operation, as it is deprecated. While this operation is implemented in some
+existing drivers as they predate the deprecation, new drivers shall use runtime
+PM instead. If you feel you need to begin calling ``.s_power()`` from an ISP or
+a bridge driver, instead add runtime PM support to the sensor driver you are
+using and drop its ``.s_power()`` handler.
+
+Please also see :ref:`examples <media-camera-sensor-examples>`.
Control framework
~~~~~~~~~~~~~~~~~
@@ -155,21 +112,36 @@ access the device.
Rotation, orientation and flipping
----------------------------------
-Some systems have the camera sensor mounted upside down compared to its natural
-mounting rotation. In such cases, drivers shall expose the information to
-userspace with the :ref:`V4L2_CID_CAMERA_SENSOR_ROTATION
-<v4l2-camera-sensor-rotation>` control.
-
-Sensor drivers shall also report the sensor's mounting orientation with the
-:ref:`V4L2_CID_CAMERA_SENSOR_ORIENTATION <v4l2-camera-sensor-orientation>`.
-
Use ``v4l2_fwnode_device_parse()`` to obtain rotation and orientation
information from system firmware and ``v4l2_ctrl_new_fwnode_properties()`` to
register the appropriate controls.
-Sensor drivers that have any vertical or horizontal flips embedded in the
-register programming sequences shall initialize the V4L2_CID_HFLIP and
-V4L2_CID_VFLIP controls with the values programmed by the register sequences.
-The default values of these controls shall be 0 (disabled). Especially these
-controls shall not be inverted, independently of the sensor's mounting
-rotation.
+.. _media-camera-sensor-examples:
+
+Example drivers
+---------------
+
+Features implemented by sensor drivers vary, and depending on the set of
+supported features and other qualities, particular sensor drivers better serve
+the purpose of an example. The following drivers are known to be good examples:
+
+.. flat-table:: Example sensor drivers
+ :header-rows: 0
+ :widths: 1 1 1 2
+
+ * - Driver name
+ - File(s)
+ - Driver type
+ - Example topic
+ * - CCS
+ - ``drivers/media/i2c/ccs/``
+ - Freely configurable
+ - Power management (ACPI and DT), UAPI
+ * - imx219
+ - ``drivers/media/i2c/imx219.c``
+ - Register list based
+ - Power management (DT), UAPI, mode selection
+ * - imx319
+ - ``drivers/media/i2c/imx319.c``
+ - Register list based
+ - Power management (ACPI and DT)
diff --git a/Documentation/driver-api/media/drivers/ccs/ccs.rst b/Documentation/driver-api/media/drivers/ccs/ccs.rst
index 7389204afcb8..776eec72bc80 100644
--- a/Documentation/driver-api/media/drivers/ccs/ccs.rst
+++ b/Documentation/driver-api/media/drivers/ccs/ccs.rst
@@ -30,7 +30,7 @@ that purpose, selection target ``V4L2_SEL_TGT_COMPOSE`` is supported on the
sink pad (0).
Additionally, if a device has no scaler or digital crop functionality, the
-source pad (1) expses another digital crop selection rectangle that can only
+source pad (1) exposes another digital crop selection rectangle that can only
crop at the end of the lines and frames.
Scaler
@@ -78,6 +78,14 @@ For SMIA (non-++) compliant devices the static data file name is
vvvv or vv denotes MIPI and SMIA manufacturer IDs respectively, mmmm model ID
and rrrr or rr revision number.
+CCS tools
+~~~~~~~~~
+
+`CCS tools <https://github.com/MIPI-Alliance/ccs-tools/>`_ is a set of
+tools for working with CCS static data files. CCS tools includes a
+definition of the human-readable CCS static data YAML format and includes a
+program to convert it to a binary.
+
Register definition generator
-----------------------------
diff --git a/Documentation/driver-api/media/v4l2-core.rst b/Documentation/driver-api/media/v4l2-core.rst
index 239045ecc8f4..58cba831ade5 100644
--- a/Documentation/driver-api/media/v4l2-core.rst
+++ b/Documentation/driver-api/media/v4l2-core.rst
@@ -13,7 +13,6 @@ Video4Linux devices
v4l2-subdev
v4l2-event
v4l2-controls
- v4l2-videobuf
v4l2-videobuf2
v4l2-dv-timings
v4l2-flash-led-class
diff --git a/Documentation/driver-api/media/v4l2-dev.rst b/Documentation/driver-api/media/v4l2-dev.rst
index 99e3b5fa7444..d5cb19b21a9f 100644
--- a/Documentation/driver-api/media/v4l2-dev.rst
+++ b/Documentation/driver-api/media/v4l2-dev.rst
@@ -157,14 +157,6 @@ changing the e.g. exposure of the webcam.
Of course, you can always do all the locking yourself by leaving both lock
pointers at ``NULL``.
-If you use the old :ref:`videobuf framework <vb_framework>` then you must
-pass the :c:type:`video_device`->lock to the videobuf queue initialize
-function: if videobuf has to wait for a frame to arrive, then it will
-temporarily unlock the lock and relock it afterwards. If your driver also
-waits in the code, then you should do the same to allow other
-processes to access the device node while the first process is waiting for
-something.
-
In the case of :ref:`videobuf2 <vb2_framework>` you will need to implement the
``wait_prepare()`` and ``wait_finish()`` callbacks to unlock/lock if applicable.
If you use the ``queue->lock`` pointer, then you can use the helper functions
diff --git a/Documentation/driver-api/media/v4l2-videobuf.rst b/Documentation/driver-api/media/v4l2-videobuf.rst
deleted file mode 100644
index 4b1d84eefeb8..000000000000
--- a/Documentation/driver-api/media/v4l2-videobuf.rst
+++ /dev/null
@@ -1,403 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. _vb_framework:
-
-Videobuf Framework
-==================
-
-Author: Jonathan Corbet <corbet@lwn.net>
-
-Current as of 2.6.33
-
-.. note::
-
- The videobuf framework was deprecated in favor of videobuf2. Shouldn't
- be used on new drivers.
-
-Introduction
-------------
-
-The videobuf layer functions as a sort of glue layer between a V4L2 driver
-and user space. It handles the allocation and management of buffers for
-the storage of video frames. There is a set of functions which can be used
-to implement many of the standard POSIX I/O system calls, including read(),
-poll(), and, happily, mmap(). Another set of functions can be used to
-implement the bulk of the V4L2 ioctl() calls related to streaming I/O,
-including buffer allocation, queueing and dequeueing, and streaming
-control. Using videobuf imposes a few design decisions on the driver
-author, but the payback comes in the form of reduced code in the driver and
-a consistent implementation of the V4L2 user-space API.
-
-Buffer types
-------------
-
-Not all video devices use the same kind of buffers. In fact, there are (at
-least) three common variations:
-
- - Buffers which are scattered in both the physical and (kernel) virtual
- address spaces. (Almost) all user-space buffers are like this, but it
- makes great sense to allocate kernel-space buffers this way as well when
- it is possible. Unfortunately, it is not always possible; working with
- this kind of buffer normally requires hardware which can do
- scatter/gather DMA operations.
-
- - Buffers which are physically scattered, but which are virtually
- contiguous; buffers allocated with vmalloc(), in other words. These
- buffers are just as hard to use for DMA operations, but they can be
- useful in situations where DMA is not available but virtually-contiguous
- buffers are convenient.
-
- - Buffers which are physically contiguous. Allocation of this kind of
- buffer can be unreliable on fragmented systems, but simpler DMA
- controllers cannot deal with anything else.
-
-Videobuf can work with all three types of buffers, but the driver author
-must pick one at the outset and design the driver around that decision.
-
-[It's worth noting that there's a fourth kind of buffer: "overlay" buffers
-which are located within the system's video memory. The overlay
-functionality is considered to be deprecated for most use, but it still
-shows up occasionally in system-on-chip drivers where the performance
-benefits merit the use of this technique. Overlay buffers can be handled
-as a form of scattered buffer, but there are very few implementations in
-the kernel and a description of this technique is currently beyond the
-scope of this document.]
-
-Data structures, callbacks, and initialization
-----------------------------------------------
-
-Depending on which type of buffers are being used, the driver should
-include one of the following files:
-
-.. code-block:: none
-
- <media/videobuf-dma-sg.h> /* Physically scattered */
- <media/videobuf-vmalloc.h> /* vmalloc() buffers */
- <media/videobuf-dma-contig.h> /* Physically contiguous */
-
-The driver's data structure describing a V4L2 device should include a
-struct videobuf_queue instance for the management of the buffer queue,
-along with a list_head for the queue of available buffers. There will also
-need to be an interrupt-safe spinlock which is used to protect (at least)
-the queue.
-
-The next step is to write four simple callbacks to help videobuf deal with
-the management of buffers:
-
-.. code-block:: none
-
- struct videobuf_queue_ops {
- int (*buf_setup)(struct videobuf_queue *q,
- unsigned int *count, unsigned int *size);
- int (*buf_prepare)(struct videobuf_queue *q,
- struct videobuf_buffer *vb,
- enum v4l2_field field);
- void (*buf_queue)(struct videobuf_queue *q,
- struct videobuf_buffer *vb);
- void (*buf_release)(struct videobuf_queue *q,
- struct videobuf_buffer *vb);
- };
-
-buf_setup() is called early in the I/O process, when streaming is being
-initiated; its purpose is to tell videobuf about the I/O stream. The count
-parameter will be a suggested number of buffers to use; the driver should
-check it for rationality and adjust it if need be. As a practical rule, a
-minimum of two buffers are needed for proper streaming, and there is
-usually a maximum (which cannot exceed 32) which makes sense for each
-device. The size parameter should be set to the expected (maximum) size
-for each frame of data.
-
-Each buffer (in the form of a struct videobuf_buffer pointer) will be
-passed to buf_prepare(), which should set the buffer's size, width, height,
-and field fields properly. If the buffer's state field is
-VIDEOBUF_NEEDS_INIT, the driver should pass it to:
-
-.. code-block:: none
-
- int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
- struct v4l2_framebuffer *fbuf);
-
-Among other things, this call will usually allocate memory for the buffer.
-Finally, the buf_prepare() function should set the buffer's state to
-VIDEOBUF_PREPARED.
-
-When a buffer is queued for I/O, it is passed to buf_queue(), which should
-put it onto the driver's list of available buffers and set its state to
-VIDEOBUF_QUEUED. Note that this function is called with the queue spinlock
-held; if it tries to acquire it as well things will come to a screeching
-halt. Yes, this is the voice of experience. Note also that videobuf may
-wait on the first buffer in the queue; placing other buffers in front of it
-could again gum up the works. So use list_add_tail() to enqueue buffers.
-
-Finally, buf_release() is called when a buffer is no longer intended to be
-used. The driver should ensure that there is no I/O active on the buffer,
-then pass it to the appropriate free routine(s):
-
-.. code-block:: none
-
- /* Scatter/gather drivers */
- int videobuf_dma_unmap(struct videobuf_queue *q,
- struct videobuf_dmabuf *dma);
- int videobuf_dma_free(struct videobuf_dmabuf *dma);
-
- /* vmalloc drivers */
- void videobuf_vmalloc_free (struct videobuf_buffer *buf);
-
- /* Contiguous drivers */
- void videobuf_dma_contig_free(struct videobuf_queue *q,
- struct videobuf_buffer *buf);
-
-One way to ensure that a buffer is no longer under I/O is to pass it to:
-
-.. code-block:: none
-
- int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr);
-
-Here, vb is the buffer, non_blocking indicates whether non-blocking I/O
-should be used (it should be zero in the buf_release() case), and intr
-controls whether an interruptible wait is used.
-
-File operations
----------------
-
-At this point, much of the work is done; much of the rest is slipping
-videobuf calls into the implementation of the other driver callbacks. The
-first step is in the open() function, which must initialize the
-videobuf queue. The function to use depends on the type of buffer used:
-
-.. code-block:: none
-
- void videobuf_queue_sg_init(struct videobuf_queue *q,
- struct videobuf_queue_ops *ops,
- struct device *dev,
- spinlock_t *irqlock,
- enum v4l2_buf_type type,
- enum v4l2_field field,
- unsigned int msize,
- void *priv);
-
- void videobuf_queue_vmalloc_init(struct videobuf_queue *q,
- struct videobuf_queue_ops *ops,
- struct device *dev,
- spinlock_t *irqlock,
- enum v4l2_buf_type type,
- enum v4l2_field field,
- unsigned int msize,
- void *priv);
-
- void videobuf_queue_dma_contig_init(struct videobuf_queue *q,
- struct videobuf_queue_ops *ops,
- struct device *dev,
- spinlock_t *irqlock,
- enum v4l2_buf_type type,
- enum v4l2_field field,
- unsigned int msize,
- void *priv);
-
-In each case, the parameters are the same: q is the queue structure for the
-device, ops is the set of callbacks as described above, dev is the device
-structure for this video device, irqlock is an interrupt-safe spinlock to
-protect access to the data structures, type is the buffer type used by the
-device (cameras will use V4L2_BUF_TYPE_VIDEO_CAPTURE, for example), field
-describes which field is being captured (often V4L2_FIELD_NONE for
-progressive devices), msize is the size of any containing structure used
-around struct videobuf_buffer, and priv is a private data pointer which
-shows up in the priv_data field of struct videobuf_queue. Note that these
-are void functions which, evidently, are immune to failure.
-
-V4L2 capture drivers can be written to support either of two APIs: the
-read() system call and the rather more complicated streaming mechanism. As
-a general rule, it is necessary to support both to ensure that all
-applications have a chance of working with the device. Videobuf makes it
-easy to do that with the same code. To implement read(), the driver need
-only make a call to one of:
-
-.. code-block:: none
-
- ssize_t videobuf_read_one(struct videobuf_queue *q,
- char __user *data, size_t count,
- loff_t *ppos, int nonblocking);
-
- ssize_t videobuf_read_stream(struct videobuf_queue *q,
- char __user *data, size_t count,
- loff_t *ppos, int vbihack, int nonblocking);
-
-Either one of these functions will read frame data into data, returning the
-amount actually read; the difference is that videobuf_read_one() will only
-read a single frame, while videobuf_read_stream() will read multiple frames
-if they are needed to satisfy the count requested by the application. A
-typical driver read() implementation will start the capture engine, call
-one of the above functions, then stop the engine before returning (though a
-smarter implementation might leave the engine running for a little while in
-anticipation of another read() call happening in the near future).
-
-The poll() function can usually be implemented with a direct call to:
-
-.. code-block:: none
-
- unsigned int videobuf_poll_stream(struct file *file,
- struct videobuf_queue *q,
- poll_table *wait);
-
-Note that the actual wait queue eventually used will be the one associated
-with the first available buffer.
-
-When streaming I/O is done to kernel-space buffers, the driver must support
-the mmap() system call to enable user space to access the data. In many
-V4L2 drivers, the often-complex mmap() implementation simplifies to a
-single call to:
-
-.. code-block:: none
-
- int videobuf_mmap_mapper(struct videobuf_queue *q,
- struct vm_area_struct *vma);
-
-Everything else is handled by the videobuf code.
-
-The release() function requires two separate videobuf calls:
-
-.. code-block:: none
-
- void videobuf_stop(struct videobuf_queue *q);
- int videobuf_mmap_free(struct videobuf_queue *q);
-
-The call to videobuf_stop() terminates any I/O in progress - though it is
-still up to the driver to stop the capture engine. The call to
-videobuf_mmap_free() will ensure that all buffers have been unmapped; if
-so, they will all be passed to the buf_release() callback. If buffers
-remain mapped, videobuf_mmap_free() returns an error code instead. The
-purpose is clearly to cause the closing of the file descriptor to fail if
-buffers are still mapped, but every driver in the 2.6.32 kernel cheerfully
-ignores its return value.
-
-ioctl() operations
-------------------
-
-The V4L2 API includes a very long list of driver callbacks to respond to
-the many ioctl() commands made available to user space. A number of these
-- those associated with streaming I/O - turn almost directly into videobuf
-calls. The relevant helper functions are:
-
-.. code-block:: none
-
- int videobuf_reqbufs(struct videobuf_queue *q,
- struct v4l2_requestbuffers *req);
- int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b);
- int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b);
- int videobuf_dqbuf(struct videobuf_queue *q, struct v4l2_buffer *b,
- int nonblocking);
- int videobuf_streamon(struct videobuf_queue *q);
- int videobuf_streamoff(struct videobuf_queue *q);
-
-So, for example, a VIDIOC_REQBUFS call turns into a call to the driver's
-vidioc_reqbufs() callback which, in turn, usually only needs to locate the
-proper struct videobuf_queue pointer and pass it to videobuf_reqbufs().
-These support functions can replace a great deal of buffer management
-boilerplate in a lot of V4L2 drivers.
-
-The vidioc_streamon() and vidioc_streamoff() functions will be a bit more
-complex, of course, since they will also need to deal with starting and
-stopping the capture engine.
-
-Buffer allocation
------------------
-
-Thus far, we have talked about buffers, but have not looked at how they are
-allocated. The scatter/gather case is the most complex on this front. For
-allocation, the driver can leave buffer allocation entirely up to the
-videobuf layer; in this case, buffers will be allocated as anonymous
-user-space pages and will be very scattered indeed. If the application is
-using user-space buffers, no allocation is needed; the videobuf layer will
-take care of calling get_user_pages() and filling in the scatterlist array.
-
-If the driver needs to do its own memory allocation, it should be done in
-the vidioc_reqbufs() function, *after* calling videobuf_reqbufs(). The
-first step is a call to:
-
-.. code-block:: none
-
- struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf);
-
-The returned videobuf_dmabuf structure (defined in
-<media/videobuf-dma-sg.h>) includes a couple of relevant fields:
-
-.. code-block:: none
-
- struct scatterlist *sglist;
- int sglen;
-
-The driver must allocate an appropriately-sized scatterlist array and
-populate it with pointers to the pieces of the allocated buffer; sglen
-should be set to the length of the array.
-
-Drivers using the vmalloc() method need not (and cannot) concern themselves
-with buffer allocation at all; videobuf will handle those details. The
-same is normally true of contiguous-DMA drivers as well; videobuf will
-allocate the buffers (with dma_alloc_coherent()) when it sees fit. That
-means that these drivers may be trying to do high-order allocations at any
-time, an operation which is not always guaranteed to work. Some drivers
-play tricks by allocating DMA space at system boot time; videobuf does not
-currently play well with those drivers.
-
-As of 2.6.31, contiguous-DMA drivers can work with a user-supplied buffer,
-as long as that buffer is physically contiguous. Normal user-space
-allocations will not meet that criterion, but buffers obtained from other
-kernel drivers, or those contained within huge pages, will work with these
-drivers.
-
-Filling the buffers
--------------------
-
-The final part of a videobuf implementation has no direct callback - it's
-the portion of the code which actually puts frame data into the buffers,
-usually in response to interrupts from the device. For all types of
-drivers, this process works approximately as follows:
-
- - Obtain the next available buffer and make sure that somebody is actually
- waiting for it.
-
- - Get a pointer to the memory and put video data there.
-
- - Mark the buffer as done and wake up the process waiting for it.
-
-Step (1) above is done by looking at the driver-managed list_head structure
-- the one which is filled in the buf_queue() callback. Because starting
-the engine and enqueueing buffers are done in separate steps, it's possible
-for the engine to be running without any buffers available - in the
-vmalloc() case especially. So the driver should be prepared for the list
-to be empty. It is equally possible that nobody is yet interested in the
-buffer; the driver should not remove it from the list or fill it until a
-process is waiting on it. That test can be done by examining the buffer's
-done field (a wait_queue_head_t structure) with waitqueue_active().
-
-A buffer's state should be set to VIDEOBUF_ACTIVE before being mapped for
-DMA; that ensures that the videobuf layer will not try to do anything with
-it while the device is transferring data.
-
-For scatter/gather drivers, the needed memory pointers will be found in the
-scatterlist structure described above. Drivers using the vmalloc() method
-can get a memory pointer with:
-
-.. code-block:: none
-
- void *videobuf_to_vmalloc(struct videobuf_buffer *buf);
-
-For contiguous DMA drivers, the function to use is:
-
-.. code-block:: none
-
- dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
-
-The contiguous DMA API goes out of its way to hide the kernel-space address
-of the DMA buffer from drivers.
-
-The final step is to set the size field of the relevant videobuf_buffer
-structure to the actual size of the captured image, set state to
-VIDEOBUF_DONE, then call wake_up() on the done queue. At this point, the
-buffer is owned by the videobuf layer and the driver should not touch it
-again.
-
-Developers who are interested in more information can go into the relevant
-header files; there are a few low-level functions declared there which have
-not been talked about here. Note also that all of these calls are exported
-GPL-only, so they will not be available to non-GPL kernel modules.
diff --git a/Documentation/driver-api/pps.rst b/Documentation/driver-api/pps.rst
index 2d6b99766ee8..78dded03e5d8 100644
--- a/Documentation/driver-api/pps.rst
+++ b/Documentation/driver-api/pps.rst
@@ -200,11 +200,17 @@ Generators
Sometimes one needs to be able not only to catch PPS signals but to produce
them also. For example, running a distributed simulation, which requires
-computers' clock to be synchronized very tightly. One way to do this is to
-invent some complicated hardware solutions but it may be neither necessary
-nor affordable. The cheap way is to load a PPS generator on one of the
-computers (master) and PPS clients on others (slaves), and use very simple
-cables to deliver signals using parallel ports, for example.
+computers' clock to be synchronized very tightly.
+
+
+Parallel port generator
+------------------------
+
+One way to do this is to invent some complicated hardware solutions but it
+may be neither necessary nor affordable. The cheap way is to load a PPS
+generator on one of the computers (master) and PPS clients on others
+(slaves), and use very simple cables to deliver signals using parallel
+ports, for example.
Parallel port cable pinout::
diff --git a/Documentation/driver-api/pwm.rst b/Documentation/driver-api/pwm.rst
index 3fdc95f7a1d1..bb264490a87a 100644
--- a/Documentation/driver-api/pwm.rst
+++ b/Documentation/driver-api/pwm.rst
@@ -111,13 +111,13 @@ channel that was exported. The following properties will then be available:
duty_cycle
The active time of the PWM signal (read/write).
- Value is in nanoseconds and must be less than the period.
+ Value is in nanoseconds and must be less than or equal to the period.
polarity
Changes the polarity of the PWM signal (read/write).
Writes to this property only work if the PWM chip supports changing
- the polarity. The polarity can only be changed if the PWM is not
- enabled. Value is the string "normal" or "inversed".
+ the polarity.
+ Value is the string "normal" or "inversed".
enable
Enable/disable the PWM signal (read/write).
diff --git a/Documentation/driver-api/thermal/intel_dptf.rst b/Documentation/driver-api/thermal/intel_dptf.rst
index 9ab4316322a1..8fb8c5b2d685 100644
--- a/Documentation/driver-api/thermal/intel_dptf.rst
+++ b/Documentation/driver-api/thermal/intel_dptf.rst
@@ -164,6 +164,16 @@ ABI.
``power_limit_1_tmax_us`` (RO)
Maximum powercap sysfs constraint_1_time_window_us for Intel RAPL
+``power_floor_status`` (RO)
+ When set to 1, the power floor of the system in the current
+ configuration has been reached. It needs to be reconfigured to allow
+ power to be reduced any further.
+
+``power_floor_enable`` (RW)
+ When set to 1, enable reading and notification of the power floor
+ status. Notifications are triggered for the power_floor_status
+ attribute value changes.
+
:file:`/sys/bus/pci/devices/0000\:00\:04.0/`
``tcc_offset_degree_celsius`` (RW)
@@ -315,3 +325,57 @@ DPTF Fan Control
----------------------------------------
Refer to Documentation/admin-guide/acpi/fan_performance_states.rst
+
+Workload Type Hints
+----------------------------------------
+
+The firmware in Meteor Lake processor generation is capable of identifying
+workload type and passing hints regarding it to the OS. A special sysfs
+interface is provided to allow user space to obtain workload type hints from
+the firmware and control the rate at which they are provided.
+
+User space can poll attribute "workload_type_index" for the current hint or
+can receive a notification whenever the value of this attribute is updated.
+
+file:`/sys/bus/pci/devices/0000:00:04.0/workload_hint/`
+Segment 0, bus 0, device 4, function 0 is reserved for the processor thermal
+device on all Intel client processors. So, the above path doesn't change
+based on the processor generation.
+
+``workload_hint_enable`` (RW)
+ Enable firmware to send workload type hints to user space.
+
+``notification_delay_ms`` (RW)
+ Minimum delay in milliseconds before firmware will notify OS. This is
+ for the rate control of notifications. This delay is between changing
+ the workload type prediction in the firmware and notifying the OS about
+ the change. The default delay is 1024 ms. The delay of 0 is invalid.
+ The delay is rounded up to the nearest power of 2 to simplify firmware
+ programming of the delay value. The read of notification_delay_ms
+ attribute shows the effective value used.
+
+``workload_type_index`` (RO)
+ Predicted workload type index. User space can get notification of
+ change via existing sysfs attribute change notification mechanism.
+
+ The supported index values and their meaning for the Meteor Lake
+ processor generation are as follows:
+
+ 0 - Idle: System performs no tasks, power and idle residency are
+ consistently low for long periods of time.
+
+ 1 – Battery Life: Power is relatively low, but the processor may
+ still be actively performing a task, such as video playback for
+ a long period of time.
+
+ 2 – Sustained: Power level that is relatively high for a long period
+ of time, with very few to no periods of idleness, which will
+ eventually exhaust RAPL Power Limit 1 and 2.
+
+ 3 – Bursty: Consumes a relatively constant average amount of power, but
+ periods of relative idleness are interrupted by bursts of
+ activity. The bursts are relatively short and the periods of
+ relative idleness between them typically prevent RAPL Power
+ Limit 1 from being exhausted.
+
+ 4 – Unknown: Can't classify.
diff --git a/Documentation/driver-api/tty/index.rst b/Documentation/driver-api/tty/index.rst
index 2d32606a4278..b490da11f257 100644
--- a/Documentation/driver-api/tty/index.rst
+++ b/Documentation/driver-api/tty/index.rst
@@ -36,6 +36,7 @@ In-detail description of the named TTY structures is in separate documents:
tty_struct
tty_ldisc
tty_buffer
+ tty_ioctl
tty_internals
Writing TTY Driver
diff --git a/Documentation/driver-api/tty/tty_ioctl.rst b/Documentation/driver-api/tty/tty_ioctl.rst
new file mode 100644
index 000000000000..3ff1ac5e07f1
--- /dev/null
+++ b/Documentation/driver-api/tty/tty_ioctl.rst
@@ -0,0 +1,10 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=================
+TTY IOCTL Helpers
+=================
+
+.. kernel-doc:: drivers/tty/tty_ioctl.c
+
+.. kernel-doc:: include/linux/tty.h
+ :identifiers: tty_get_baud_rate
diff --git a/Documentation/driver-api/usb/dma.rst b/Documentation/driver-api/usb/dma.rst
index d32c27e11b90..02f6825ff830 100644
--- a/Documentation/driver-api/usb/dma.rst
+++ b/Documentation/driver-api/usb/dma.rst
@@ -93,44 +93,18 @@ DMA address space of the device. However, most buffers passed to your
driver can safely be used with such DMA mapping. (See the first section
of Documentation/core-api/dma-api-howto.rst, titled "What memory is DMA-able?")
-- When you're using scatterlists, you can map everything at once. On some
- systems, this kicks in an IOMMU and turns the scatterlists into single
- DMA transactions::
+- When you have the scatterlists which have been mapped for the USB controller,
+ you could use the new ``usb_sg_*()`` calls, which would turn scatterlist
+ into URBs::
- int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
- struct scatterlist *sg, int nents);
+ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ unsigned pipe, unsigned period, struct scatterlist *sg,
+ int nents, size_t length, gfp_t mem_flags);
- void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
- struct scatterlist *sg, int n_hw_ents);
+ void usb_sg_wait(struct usb_sg_request *io);
- void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
- struct scatterlist *sg, int n_hw_ents);
+ void usb_sg_cancel(struct usb_sg_request *io);
- It's probably easier to use the new ``usb_sg_*()`` calls, which do the DMA
- mapping and apply other tweaks to make scatterlist i/o be fast.
-
-- Some drivers may prefer to work with the model that they're mapping large
- buffers, synchronizing their safe re-use. (If there's no re-use, then let
- usbcore do the map/unmap.) Large periodic transfers make good examples
- here, since it's cheaper to just synchronize the buffer than to unmap it
- each time an urb completes and then re-map it on during resubmission.
-
- These calls all work with initialized urbs: ``urb->dev``, ``urb->pipe``,
- ``urb->transfer_buffer``, and ``urb->transfer_buffer_length`` must all be
- valid when these calls are used (``urb->setup_packet`` must be valid too
- if urb is a control request)::
-
- struct urb *usb_buffer_map (struct urb *urb);
-
- void usb_buffer_dmasync (struct urb *urb);
-
- void usb_buffer_unmap (struct urb *urb);
-
- The calls manage ``urb->transfer_dma`` for you, and set
- ``URB_NO_TRANSFER_DMA_MAP`` so that usbcore won't map or unmap the buffer.
- They cannot be used for setup_packet buffers in control requests.
-
-Note that several of those interfaces are currently commented out, since
-they don't have current users. See the source code. Other than the dmasync
-calls (where the underlying DMA primitives have changed), most of them can
-easily be commented back in if you want to use them.
+ When the USB controller doesn't support DMA, the ``usb_sg_init()`` would try
+ to submit URBs in PIO way as long as the page in scatterlists is not in the
+ Highmem, which could be very rare in modern architectures.
diff --git a/Documentation/features/core/cBPF-JIT/arch-support.txt b/Documentation/features/core/cBPF-JIT/arch-support.txt
index 0a1f5bb7eeb9..937840080de7 100644
--- a/Documentation/features/core/cBPF-JIT/arch-support.txt
+++ b/Documentation/features/core/cBPF-JIT/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | TODO |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/core/eBPF-JIT/arch-support.txt b/Documentation/features/core/eBPF-JIT/arch-support.txt
index 6c0f3d759e6a..7434b43c2ff8 100644
--- a/Documentation/features/core/eBPF-JIT/arch-support.txt
+++ b/Documentation/features/core/eBPF-JIT/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/core/generic-idle-thread/arch-support.txt b/Documentation/features/core/generic-idle-thread/arch-support.txt
index 0b94099cf6ac..0735cb5367b4 100644
--- a/Documentation/features/core/generic-idle-thread/arch-support.txt
+++ b/Documentation/features/core/generic-idle-thread/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | ok |
- | ia64: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/core/jump-labels/arch-support.txt b/Documentation/features/core/jump-labels/arch-support.txt
index 94d9dece580f..ccada815569f 100644
--- a/Documentation/features/core/jump-labels/arch-support.txt
+++ b/Documentation/features/core/jump-labels/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/core/thread-info-in-task/arch-support.txt b/Documentation/features/core/thread-info-in-task/arch-support.txt
index 97c65ed2ac23..2afeb6bf6e64 100644
--- a/Documentation/features/core/thread-info-in-task/arch-support.txt
+++ b/Documentation/features/core/thread-info-in-task/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/core/tracehook/arch-support.txt b/Documentation/features/core/tracehook/arch-support.txt
index aed5679da651..a72330e25542 100644
--- a/Documentation/features/core/tracehook/arch-support.txt
+++ b/Documentation/features/core/tracehook/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | ok |
- | ia64: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/debug/KASAN/arch-support.txt b/Documentation/features/debug/KASAN/arch-support.txt
index c4581c2edb28..39c6e78c0cbe 100644
--- a/Documentation/features/debug/KASAN/arch-support.txt
+++ b/Documentation/features/debug/KASAN/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/debug/debug-vm-pgtable/arch-support.txt b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt
index 9ec5d13f4939..bbf029f095cb 100644
--- a/Documentation/features/debug/debug-vm-pgtable/arch-support.txt
+++ b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/debug/gcov-profile-all/arch-support.txt b/Documentation/features/debug/gcov-profile-all/arch-support.txt
index dc4014f7e1f8..63494bddc263 100644
--- a/Documentation/features/debug/gcov-profile-all/arch-support.txt
+++ b/Documentation/features/debug/gcov-profile-all/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | ok |
diff --git a/Documentation/features/debug/kcov/arch-support.txt b/Documentation/features/debug/kcov/arch-support.txt
index de84cefbcdd3..4449e1f55cd8 100644
--- a/Documentation/features/debug/kcov/arch-support.txt
+++ b/Documentation/features/debug/kcov/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/debug/kgdb/arch-support.txt b/Documentation/features/debug/kgdb/arch-support.txt
index 5e91ec78c80b..f287f16ce0ec 100644
--- a/Documentation/features/debug/kgdb/arch-support.txt
+++ b/Documentation/features/debug/kgdb/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | ok |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | ok |
diff --git a/Documentation/features/debug/kmemleak/arch-support.txt b/Documentation/features/debug/kmemleak/arch-support.txt
index 4e205ef70363..f45149cfa313 100644
--- a/Documentation/features/debug/kmemleak/arch-support.txt
+++ b/Documentation/features/debug/kmemleak/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | ok |
diff --git a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
index 38a0a54b79f5..02febc883588 100644
--- a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
+++ b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | TODO |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/debug/kprobes/arch-support.txt b/Documentation/features/debug/kprobes/arch-support.txt
index aad83b57587a..1ea27aedd098 100644
--- a/Documentation/features/debug/kprobes/arch-support.txt
+++ b/Documentation/features/debug/kprobes/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/debug/kretprobes/arch-support.txt b/Documentation/features/debug/kretprobes/arch-support.txt
index 61380010a4a7..022be42e64f9 100644
--- a/Documentation/features/debug/kretprobes/arch-support.txt
+++ b/Documentation/features/debug/kretprobes/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/debug/optprobes/arch-support.txt b/Documentation/features/debug/optprobes/arch-support.txt
index 83a4639a5c0a..92f5d0f444fa 100644
--- a/Documentation/features/debug/optprobes/arch-support.txt
+++ b/Documentation/features/debug/optprobes/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | TODO |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/debug/stackprotector/arch-support.txt b/Documentation/features/debug/stackprotector/arch-support.txt
index 4c64c5d596f7..de8f43f2e5d6 100644
--- a/Documentation/features/debug/stackprotector/arch-support.txt
+++ b/Documentation/features/debug/stackprotector/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/debug/uprobes/arch-support.txt b/Documentation/features/debug/uprobes/arch-support.txt
index 24c8423b0abc..0c698003ce9c 100644
--- a/Documentation/features/debug/uprobes/arch-support.txt
+++ b/Documentation/features/debug/uprobes/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/debug/user-ret-profiler/arch-support.txt b/Documentation/features/debug/user-ret-profiler/arch-support.txt
index 059110a5fa6e..3e431767581d 100644
--- a/Documentation/features/debug/user-ret-profiler/arch-support.txt
+++ b/Documentation/features/debug/user-ret-profiler/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | TODO |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/io/dma-contiguous/arch-support.txt b/Documentation/features/io/dma-contiguous/arch-support.txt
index bfe0921a3853..3c6ce35d704f 100644
--- a/Documentation/features/io/dma-contiguous/arch-support.txt
+++ b/Documentation/features/io/dma-contiguous/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | ok |
diff --git a/Documentation/features/locking/cmpxchg-local/arch-support.txt b/Documentation/features/locking/cmpxchg-local/arch-support.txt
index 68329e96dffa..2c3a4b91f16d 100644
--- a/Documentation/features/locking/cmpxchg-local/arch-support.txt
+++ b/Documentation/features/locking/cmpxchg-local/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/locking/lockdep/arch-support.txt b/Documentation/features/locking/lockdep/arch-support.txt
index a36e231670d7..b6b00469f7d0 100644
--- a/Documentation/features/locking/lockdep/arch-support.txt
+++ b/Documentation/features/locking/lockdep/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | ok |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | ok |
diff --git a/Documentation/features/locking/queued-rwlocks/arch-support.txt b/Documentation/features/locking/queued-rwlocks/arch-support.txt
index 5deb845477e4..b286a5fff283 100644
--- a/Documentation/features/locking/queued-rwlocks/arch-support.txt
+++ b/Documentation/features/locking/queued-rwlocks/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/locking/queued-spinlocks/arch-support.txt b/Documentation/features/locking/queued-spinlocks/arch-support.txt
index 2d3961bfef5d..22f2990392ff 100644
--- a/Documentation/features/locking/queued-spinlocks/arch-support.txt
+++ b/Documentation/features/locking/queued-spinlocks/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/perf/kprobes-event/arch-support.txt b/Documentation/features/perf/kprobes-event/arch-support.txt
index 641a7d2ff2a3..713a69fcd697 100644
--- a/Documentation/features/perf/kprobes-event/arch-support.txt
+++ b/Documentation/features/perf/kprobes-event/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | ok |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/perf/perf-regs/arch-support.txt b/Documentation/features/perf/perf-regs/arch-support.txt
index 33866eb242c1..09431518b0e8 100644
--- a/Documentation/features/perf/perf-regs/arch-support.txt
+++ b/Documentation/features/perf/perf-regs/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/perf/perf-stackdump/arch-support.txt b/Documentation/features/perf/perf-stackdump/arch-support.txt
index c8e4c7c65012..f9db4dd8ef79 100644
--- a/Documentation/features/perf/perf-stackdump/arch-support.txt
+++ b/Documentation/features/perf/perf-stackdump/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/sched/membarrier-sync-core/arch-support.txt b/Documentation/features/sched/membarrier-sync-core/arch-support.txt
index 23260ca44946..d96b778b87ed 100644
--- a/Documentation/features/sched/membarrier-sync-core/arch-support.txt
+++ b/Documentation/features/sched/membarrier-sync-core/arch-support.txt
@@ -35,7 +35,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/sched/numa-balancing/arch-support.txt b/Documentation/features/sched/numa-balancing/arch-support.txt
index 532cc67cdf92..984601c7c479 100644
--- a/Documentation/features/sched/numa-balancing/arch-support.txt
+++ b/Documentation/features/sched/numa-balancing/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | .. |
| hexagon: | .. |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | .. |
| microblaze: | .. |
diff --git a/Documentation/features/seccomp/seccomp-filter/arch-support.txt b/Documentation/features/seccomp/seccomp-filter/arch-support.txt
index 3a7237b989cd..13feb679649e 100644
--- a/Documentation/features/seccomp/seccomp-filter/arch-support.txt
+++ b/Documentation/features/seccomp/seccomp-filter/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | ok |
| microblaze: | TODO |
diff --git a/Documentation/features/time/arch-tick-broadcast/arch-support.txt b/Documentation/features/time/arch-tick-broadcast/arch-support.txt
index 9bffac80019e..ccba965e8d07 100644
--- a/Documentation/features/time/arch-tick-broadcast/arch-support.txt
+++ b/Documentation/features/time/arch-tick-broadcast/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/time/clockevents/arch-support.txt b/Documentation/features/time/clockevents/arch-support.txt
index 625160048f68..4d4bfac52970 100644
--- a/Documentation/features/time/clockevents/arch-support.txt
+++ b/Documentation/features/time/clockevents/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | ok |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | ok |
diff --git a/Documentation/features/time/context-tracking/arch-support.txt b/Documentation/features/time/context-tracking/arch-support.txt
index 72bc5bad0348..891be9f61903 100644
--- a/Documentation/features/time/context-tracking/arch-support.txt
+++ b/Documentation/features/time/context-tracking/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/time/irq-time-acct/arch-support.txt b/Documentation/features/time/irq-time-acct/arch-support.txt
index ceb036610d09..3d10075a8a8a 100644
--- a/Documentation/features/time/irq-time-acct/arch-support.txt
+++ b/Documentation/features/time/irq-time-acct/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | .. |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/time/virt-cpuacct/arch-support.txt b/Documentation/features/time/virt-cpuacct/arch-support.txt
index c063dffd5261..21f11d47ef72 100644
--- a/Documentation/features/time/virt-cpuacct/arch-support.txt
+++ b/Documentation/features/time/virt-cpuacct/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/vm/ELF-ASLR/arch-support.txt b/Documentation/features/vm/ELF-ASLR/arch-support.txt
index 47909c3dd602..57406c0d5353 100644
--- a/Documentation/features/vm/ELF-ASLR/arch-support.txt
+++ b/Documentation/features/vm/ELF-ASLR/arch-support.txt
@@ -13,7 +13,6 @@
| arm64: | ok |
| csky: | ok |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/vm/PG_uncached/arch-support.txt b/Documentation/features/vm/PG_uncached/arch-support.txt
index 5acd64b97dba..5a7508b8c967 100644
--- a/Documentation/features/vm/PG_uncached/arch-support.txt
+++ b/Documentation/features/vm/PG_uncached/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | TODO |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | ok |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/vm/THP/arch-support.txt b/Documentation/features/vm/THP/arch-support.txt
index 9dd7d75d0465..b4a5ce16940d 100644
--- a/Documentation/features/vm/THP/arch-support.txt
+++ b/Documentation/features/vm/THP/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | .. |
| hexagon: | .. |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | .. |
| microblaze: | .. |
diff --git a/Documentation/features/vm/TLB/arch-support.txt b/Documentation/features/vm/TLB/arch-support.txt
index 76208db88f3b..8fd22073a847 100644
--- a/Documentation/features/vm/TLB/arch-support.txt
+++ b/Documentation/features/vm/TLB/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | TODO |
| m68k: | .. |
| microblaze: | .. |
diff --git a/Documentation/features/vm/huge-vmap/arch-support.txt b/Documentation/features/vm/huge-vmap/arch-support.txt
index 34647d9bdca4..2d6de7b04538 100644
--- a/Documentation/features/vm/huge-vmap/arch-support.txt
+++ b/Documentation/features/vm/huge-vmap/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/vm/ioremap_prot/arch-support.txt b/Documentation/features/vm/ioremap_prot/arch-support.txt
index a24149e59d73..1638c2cb17f1 100644
--- a/Documentation/features/vm/ioremap_prot/arch-support.txt
+++ b/Documentation/features/vm/ioremap_prot/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/features/vm/pte_special/arch-support.txt b/Documentation/features/vm/pte_special/arch-support.txt
index d2b22a06945e..3f777f8b67d5 100644
--- a/Documentation/features/vm/pte_special/arch-support.txt
+++ b/Documentation/features/vm/pte_special/arch-support.txt
@@ -12,7 +12,6 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
- | ia64: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
diff --git a/Documentation/filesystems/erofs.rst b/Documentation/filesystems/erofs.rst
index f200d7874495..cc4626d6ee4f 100644
--- a/Documentation/filesystems/erofs.rst
+++ b/Documentation/filesystems/erofs.rst
@@ -91,6 +91,10 @@ compatibility checking tool (fsck.erofs), and a debugging tool (dump.erofs):
- git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git
+For more information, please also refer to the documentation site:
+
+- https://erofs.docs.kernel.org
+
Bugs and patches are welcome, please kindly help us and send to the following
linux-erofs mailing list:
@@ -199,7 +203,7 @@ may not. All metadatas can be now observed in two different spaces (views):
| |
|__________________| 64 bytes
- Xattrs, extents, data inline are followed by the corresponding inode with
+ Xattrs, extents, data inline are placed after the corresponding inode with
proper alignment, and they could be optional for different data mappings.
_currently_ total 5 data layouts are supported:
diff --git a/Documentation/filesystems/files.rst b/Documentation/filesystems/files.rst
index bcf84459917f..9e38e4c221ca 100644
--- a/Documentation/filesystems/files.rst
+++ b/Documentation/filesystems/files.rst
@@ -62,7 +62,7 @@ the fdtable structure -
be held.
4. To look up the file structure given an fd, a reader
- must use either lookup_fd_rcu() or files_lookup_fd_rcu() APIs. These
+ must use either lookup_fdget_rcu() or files_lookup_fdget_rcu() APIs. These
take care of barrier requirements due to lock-free lookup.
An example::
@@ -70,43 +70,22 @@ the fdtable structure -
struct file *file;
rcu_read_lock();
- file = lookup_fd_rcu(fd);
- if (file) {
- ...
- }
- ....
+ file = lookup_fdget_rcu(fd);
rcu_read_unlock();
-
-5. Handling of the file structures is special. Since the look-up
- of the fd (fget()/fget_light()) are lock-free, it is possible
- that look-up may race with the last put() operation on the
- file structure. This is avoided using atomic_long_inc_not_zero()
- on ->f_count::
-
- rcu_read_lock();
- file = files_lookup_fd_rcu(files, fd);
if (file) {
- if (atomic_long_inc_not_zero(&file->f_count))
- *fput_needed = 1;
- else
- /* Didn't get the reference, someone's freed */
- file = NULL;
+ ...
+ fput(file);
}
- rcu_read_unlock();
....
- return file;
-
- atomic_long_inc_not_zero() detects if refcounts is already zero or
- goes to zero during increment. If it does, we fail
- fget()/fget_light().
-6. Since both fdtable and file structures can be looked up
+5. Since both fdtable and file structures can be looked up
lock-free, they must be installed using rcu_assign_pointer()
API. If they are looked up lock-free, rcu_dereference()
must be used. However it is advisable to use files_fdtable()
- and lookup_fd_rcu()/files_lookup_fd_rcu() which take care of these issues.
+ and lookup_fdget_rcu()/files_lookup_fdget_rcu() which take care of these
+ issues.
-7. While updating, the fdtable pointer must be looked up while
+6. While updating, the fdtable pointer must be looked up while
holding files->file_lock. If ->file_lock is dropped, then
another thread expand the files thereby creating a new
fdtable and making the earlier fdtable pointer stale.
@@ -126,3 +105,19 @@ the fdtable structure -
Since locate_fd() can drop ->file_lock (and reacquire ->file_lock),
the fdtable pointer (fdt) must be loaded after locate_fd().
+On newer kernels rcu based file lookup has been switched to rely on
+SLAB_TYPESAFE_BY_RCU instead of call_rcu(). It isn't sufficient anymore
+to just acquire a reference to the file in question under rcu using
+atomic_long_inc_not_zero() since the file might have already been
+recycled and someone else might have bumped the reference. In other
+words, callers might see reference count bumps from newer users. For
+this is reason it is necessary to verify that the pointer is the same
+before and after the reference count increment. This pattern can be seen
+in get_file_rcu() and __files_get_rcu().
+
+In addition, it isn't possible to access or check fields in struct file
+without first aqcuiring a reference on it under rcu lookup. Not doing
+that was always very dodgy and it was only usable for non-pointer data
+in struct file. With SLAB_TYPESAFE_BY_RCU it is necessary that callers
+either first acquire a reference or they must hold the files_lock of the
+fdtable.
diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst
index a624e92f2687..1b84f818e574 100644
--- a/Documentation/filesystems/fscrypt.rst
+++ b/Documentation/filesystems/fscrypt.rst
@@ -261,9 +261,9 @@ DIRECT_KEY policies
The Adiantum encryption mode (see `Encryption modes and usage`_) is
suitable for both contents and filenames encryption, and it accepts
-long IVs --- long enough to hold both an 8-byte logical block number
-and a 16-byte per-file nonce. Also, the overhead of each Adiantum key
-is greater than that of an AES-256-XTS key.
+long IVs --- long enough to hold both an 8-byte data unit index and a
+16-byte per-file nonce. Also, the overhead of each Adiantum key is
+greater than that of an AES-256-XTS key.
Therefore, to improve performance and save memory, for Adiantum a
"direct key" configuration is supported. When the user has enabled
@@ -300,8 +300,8 @@ IV_INO_LBLK_32 policies
IV_INO_LBLK_32 policies work like IV_INO_LBLK_64, except that for
IV_INO_LBLK_32, the inode number is hashed with SipHash-2-4 (where the
-SipHash key is derived from the master key) and added to the file
-logical block number mod 2^32 to produce a 32-bit IV.
+SipHash key is derived from the master key) and added to the file data
+unit index mod 2^32 to produce a 32-bit IV.
This format is optimized for use with inline encryption hardware
compliant with the eMMC v5.2 standard, which supports only 32 IV bits
@@ -451,31 +451,62 @@ acceleration is recommended:
Contents encryption
-------------------
-For file contents, each filesystem block is encrypted independently.
-Starting from Linux kernel 5.5, encryption of filesystems with block
-size less than system's page size is supported.
-
-Each block's IV is set to the logical block number within the file as
-a little endian number, except that:
-
-- With CBC mode encryption, ESSIV is also used. Specifically, each IV
- is encrypted with AES-256 where the AES-256 key is the SHA-256 hash
- of the file's data encryption key.
-
-- With `DIRECT_KEY policies`_, the file's nonce is appended to the IV.
- Currently this is only allowed with the Adiantum encryption mode.
-
-- With `IV_INO_LBLK_64 policies`_, the logical block number is limited
- to 32 bits and is placed in bits 0-31 of the IV. The inode number
- (which is also limited to 32 bits) is placed in bits 32-63.
-
-- With `IV_INO_LBLK_32 policies`_, the logical block number is limited
- to 32 bits and is placed in bits 0-31 of the IV. The inode number
- is then hashed and added mod 2^32.
-
-Note that because file logical block numbers are included in the IVs,
-filesystems must enforce that blocks are never shifted around within
-encrypted files, e.g. via "collapse range" or "insert range".
+For contents encryption, each file's contents is divided into "data
+units". Each data unit is encrypted independently. The IV for each
+data unit incorporates the zero-based index of the data unit within
+the file. This ensures that each data unit within a file is encrypted
+differently, which is essential to prevent leaking information.
+
+Note: the encryption depending on the offset into the file means that
+operations like "collapse range" and "insert range" that rearrange the
+extent mapping of files are not supported on encrypted files.
+
+There are two cases for the sizes of the data units:
+
+* Fixed-size data units. This is how all filesystems other than UBIFS
+ work. A file's data units are all the same size; the last data unit
+ is zero-padded if needed. By default, the data unit size is equal
+ to the filesystem block size. On some filesystems, users can select
+ a sub-block data unit size via the ``log2_data_unit_size`` field of
+ the encryption policy; see `FS_IOC_SET_ENCRYPTION_POLICY`_.
+
+* Variable-size data units. This is what UBIFS does. Each "UBIFS
+ data node" is treated as a crypto data unit. Each contains variable
+ length, possibly compressed data, zero-padded to the next 16-byte
+ boundary. Users cannot select a sub-block data unit size on UBIFS.
+
+In the case of compression + encryption, the compressed data is
+encrypted. UBIFS compression works as described above. f2fs
+compression works a bit differently; it compresses a number of
+filesystem blocks into a smaller number of filesystem blocks.
+Therefore a f2fs-compressed file still uses fixed-size data units, and
+it is encrypted in a similar way to a file containing holes.
+
+As mentioned in `Key hierarchy`_, the default encryption setting uses
+per-file keys. In this case, the IV for each data unit is simply the
+index of the data unit in the file. However, users can select an
+encryption setting that does not use per-file keys. For these, some
+kind of file identifier is incorporated into the IVs as follows:
+
+- With `DIRECT_KEY policies`_, the data unit index is placed in bits
+ 0-63 of the IV, and the file's nonce is placed in bits 64-191.
+
+- With `IV_INO_LBLK_64 policies`_, the data unit index is placed in
+ bits 0-31 of the IV, and the file's inode number is placed in bits
+ 32-63. This setting is only allowed when data unit indices and
+ inode numbers fit in 32 bits.
+
+- With `IV_INO_LBLK_32 policies`_, the file's inode number is hashed
+ and added to the data unit index. The resulting value is truncated
+ to 32 bits and placed in bits 0-31 of the IV. This setting is only
+ allowed when data unit indices and inode numbers fit in 32 bits.
+
+The byte order of the IV is always little endian.
+
+If the user selects FSCRYPT_MODE_AES_128_CBC for the contents mode, an
+ESSIV layer is automatically included. In this case, before the IV is
+passed to AES-128-CBC, it is encrypted with AES-256 where the AES-256
+key is the SHA-256 hash of the file's contents encryption key.
Filenames encryption
--------------------
@@ -544,7 +575,8 @@ follows::
__u8 contents_encryption_mode;
__u8 filenames_encryption_mode;
__u8 flags;
- __u8 __reserved[4];
+ __u8 log2_data_unit_size;
+ __u8 __reserved[3];
__u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
};
@@ -586,6 +618,29 @@ This structure must be initialized as follows:
The DIRECT_KEY, IV_INO_LBLK_64, and IV_INO_LBLK_32 flags are
mutually exclusive.
+- ``log2_data_unit_size`` is the log2 of the data unit size in bytes,
+ or 0 to select the default data unit size. The data unit size is
+ the granularity of file contents encryption. For example, setting
+ ``log2_data_unit_size`` to 12 causes file contents be passed to the
+ underlying encryption algorithm (such as AES-256-XTS) in 4096-byte
+ data units, each with its own IV.
+
+ Not all filesystems support setting ``log2_data_unit_size``. ext4
+ and f2fs support it since Linux v6.7. On filesystems that support
+ it, the supported nonzero values are 9 through the log2 of the
+ filesystem block size, inclusively. The default value of 0 selects
+ the filesystem block size.
+
+ The main use case for ``log2_data_unit_size`` is for selecting a
+ data unit size smaller than the filesystem block size for
+ compatibility with inline encryption hardware that only supports
+ smaller data unit sizes. ``/sys/block/$disk/queue/crypto/`` may be
+ useful for checking which data unit sizes are supported by a
+ particular system's inline encryption hardware.
+
+ Leave this field zeroed unless you are certain you need it. Using
+ an unnecessarily small data unit size reduces performance.
+
- For v2 encryption policies, ``__reserved`` must be zeroed.
- For v1 encryption policies, ``master_key_descriptor`` specifies how
@@ -1079,8 +1134,8 @@ The caller must zero all input fields, then fill in ``key_spec``:
On success, 0 is returned and the kernel fills in the output fields:
- ``status`` indicates whether the key is absent, present, or
- incompletely removed. Incompletely removed means that the master
- secret has been removed, but some files are still in use; i.e.,
+ incompletely removed. Incompletely removed means that removal has
+ been initiated, but some files are still in use; i.e.,
`FS_IOC_REMOVE_ENCRYPTION_KEY`_ returned 0 but set the informational
status flag FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY.
diff --git a/Documentation/filesystems/fuse-io.rst b/Documentation/filesystems/fuse-io.rst
index 255a368fe534..6464de4266ad 100644
--- a/Documentation/filesystems/fuse-io.rst
+++ b/Documentation/filesystems/fuse-io.rst
@@ -15,7 +15,8 @@ The direct-io mode can be selected with the FOPEN_DIRECT_IO flag in the
FUSE_OPEN reply.
In direct-io mode the page cache is completely bypassed for reads and writes.
-No read-ahead takes place. Shared mmap is disabled.
+No read-ahead takes place. Shared mmap is disabled by default. To allow shared
+mmap, the FUSE_DIRECT_IO_ALLOW_MMAP flag may be enabled in the FUSE_INIT reply.
In cached mode reads may be satisfied from the page cache, and data may be
read-ahead by the kernel to fill the cache. The cache is always kept consistent
diff --git a/Documentation/filesystems/nfs/exporting.rst b/Documentation/filesystems/nfs/exporting.rst
index 4b30daee399a..f04ce1215a03 100644
--- a/Documentation/filesystems/nfs/exporting.rst
+++ b/Documentation/filesystems/nfs/exporting.rst
@@ -122,12 +122,9 @@ are exportable by setting the s_export_op field in the struct
super_block. This field must point to a "struct export_operations"
struct which has the following members:
- encode_fh (optional)
+ encode_fh (mandatory)
Takes a dentry and creates a filehandle fragment which may later be used
- to find or create a dentry for the same object. The default
- implementation creates a filehandle fragment that encodes a 32bit inode
- and generation number for the inode encoded, and if necessary the
- same information for the parent.
+ to find or create a dentry for the same object.
fh_to_dentry (mandatory)
Given a filehandle fragment, this should find the implied object and
@@ -241,3 +238,10 @@ following flags are defined:
all of an inode's dirty data on last close. Exports that behave this
way should set EXPORT_OP_FLUSH_ON_CLOSE so that NFSD knows to skip
waiting for writeback when closing such files.
+
+ EXPORT_OP_ASYNC_LOCK - Indicates a capable filesystem to do async lock
+ requests from lockd. Only set EXPORT_OP_ASYNC_LOCK if the filesystem has
+ it's own ->lock() functionality as core posix_lock_file() implementation
+ has no async lock request handling yet. For more information about how to
+ indicate an async lock request from a ->lock() file_operations struct, see
+ fs/locks.c and comment for the function vfs_lock_file().
diff --git a/Documentation/filesystems/overlayfs.rst b/Documentation/filesystems/overlayfs.rst
index cdefbe73d85c..0407f361f32a 100644
--- a/Documentation/filesystems/overlayfs.rst
+++ b/Documentation/filesystems/overlayfs.rst
@@ -339,6 +339,19 @@ The specified lower directories will be stacked beginning from the
rightmost one and going left. In the above example lower1 will be the
top, lower2 the middle and lower3 the bottom layer.
+Note: directory names containing colons can be provided as lower layer by
+escaping the colons with a single backslash. For example:
+
+ mount -t overlay overlay -olowerdir=/a\:lower\:\:dir /merged
+
+Since kernel version v6.8, directory names containing colons can also
+be configured as lower layer using the "lowerdir+" mount options and the
+fsconfig syscall from new mount api. For example:
+
+ fsconfig(fs_fd, FSCONFIG_SET_STRING, "lowerdir+", "/a:lower::dir", 0);
+
+In the latter case, colons in lower layer directory names will be escaped
+as an octal characters (\072) when displayed in /proc/self/mountinfo.
Metadata only copy up
---------------------
@@ -404,6 +417,16 @@ Only the data of the files in the "data-only" lower layers may be visible
when a "metacopy" file in one of the lower layers above it, has a "redirect"
to the absolute path of the "lower data" file in the "data-only" lower layer.
+Since kernel version v6.8, "data-only" lower layers can also be added using
+the "datadir+" mount options and the fsconfig syscall from new mount api.
+For example:
+
+ fsconfig(fs_fd, FSCONFIG_SET_STRING, "lowerdir+", "/l1", 0);
+ fsconfig(fs_fd, FSCONFIG_SET_STRING, "lowerdir+", "/l2", 0);
+ fsconfig(fs_fd, FSCONFIG_SET_STRING, "lowerdir+", "/l3", 0);
+ fsconfig(fs_fd, FSCONFIG_SET_STRING, "datadir+", "/do1", 0);
+ fsconfig(fs_fd, FSCONFIG_SET_STRING, "datadir+", "/do2", 0);
+
fs-verity support
----------------------
@@ -492,6 +515,29 @@ directory tree on the same or different underlying filesystem, and even
to a different machine. With the "inodes index" feature, trying to mount
the copied layers will fail the verification of the lower root file handle.
+Nesting overlayfs mounts
+------------------------
+
+It is possible to use a lower directory that is stored on an overlayfs
+mount. For regular files this does not need any special care. However, files
+that have overlayfs attributes, such as whiteouts or "overlay.*" xattrs will be
+interpreted by the underlying overlayfs mount and stripped out. In order to
+allow the second overlayfs mount to see the attributes they must be escaped.
+
+Overlayfs specific xattrs are escaped by using a special prefix of
+"overlay.overlay.". So, a file with a "trusted.overlay.overlay.metacopy" xattr
+in the lower dir will be exposed as a regular file with a
+"trusted.overlay.metacopy" xattr in the overlayfs mount. This can be nested by
+repeating the prefix multiple time, as each instance only removes one prefix.
+
+A lower dir with a regular whiteout will always be handled by the overlayfs
+mount, so to support storing an effective whiteout file in an overlayfs mount an
+alternative form of whiteout is supported. This form is a regular, zero-size
+file with the "overlay.whiteout" xattr set, inside a directory with the
+"overlay.whiteouts" xattr set. Such whiteouts are never created by overlayfs,
+but can be used by userspace tools (like containers) that generate lower layers.
+These alternative whiteouts can be escaped using the standard xattr escape
+mechanism in order to properly nest to any depth.
Non-standard behavior
---------------------
diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index 4d05b9862451..878e72b2f8b7 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1045,3 +1045,19 @@ filesystem type is now moved to a later point when the devices are closed:
As this is a VFS level change it has no practical consequences for filesystems
other than that all of them must use one of the provided kill_litter_super(),
kill_anon_super(), or kill_block_super() helpers.
+
+---
+
+**mandatory**
+
+Lock ordering has been changed so that s_umount ranks above open_mutex again.
+All places where s_umount was taken under open_mutex have been fixed up.
+
+---
+
+**mandatory**
+
+export_operations ->encode_fh() no longer has a default implementation to
+encode FILEID_INO32_GEN* file handles.
+Filesystems that used the default implementation may use the generic helper
+generic_encode_ino32_fh() explicitly.
diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst
index 2b59cff8be17..49ef12df631b 100644
--- a/Documentation/filesystems/proc.rst
+++ b/Documentation/filesystems/proc.rst
@@ -689,9 +689,15 @@ files are there, and which are missing.
File Content
============ ===============================================================
apm Advanced power management info
+ bootconfig Kernel command line obtained from boot config,
+ and, if there were kernel parameters from the
+ boot loader, a "# Parameters from bootloader:"
+ line followed by a line containing those
+ parameters prefixed by "# ". (5.5)
buddyinfo Kernel memory allocator information (see text) (2.5)
bus Directory containing bus specific information
- cmdline Kernel command line
+ cmdline Kernel command line, both from bootloader and embedded
+ in the kernel image
cpuinfo Info about the CPU
devices Available devices (block and character)
dma Used DMS channels
diff --git a/Documentation/filesystems/xfs-online-fsck-design.rst b/Documentation/filesystems/xfs-online-fsck-design.rst
index 1625d1131093..a0678101a7d0 100644
--- a/Documentation/filesystems/xfs-online-fsck-design.rst
+++ b/Documentation/filesystems/xfs-online-fsck-design.rst
@@ -1585,7 +1585,7 @@ The transaction sequence looks like this:
2. The second transaction contains a physical update to the free space btrees
of AG 3 to release the former BMBT block and a second physical update to the
free space btrees of AG 7 to release the unmapped file space.
- Observe that the the physical updates are resequenced in the correct order
+ Observe that the physical updates are resequenced in the correct order
when possible.
Attached to the transaction is a an extent free done (EFD) log item.
The EFD contains a pointer to the EFI logged in transaction #1 so that log
diff --git a/Documentation/firmware-guide/acpi/enumeration.rst b/Documentation/firmware-guide/acpi/enumeration.rst
index 56d9913a3370..d79f69390991 100644
--- a/Documentation/firmware-guide/acpi/enumeration.rst
+++ b/Documentation/firmware-guide/acpi/enumeration.rst
@@ -64,6 +64,49 @@ If the driver needs to perform more complex initialization like getting and
configuring GPIOs it can get its ACPI handle and extract this information
from ACPI tables.
+ACPI device objects
+===================
+
+Generally speaking, there are two categories of devices in a system in which
+ACPI is used as an interface between the platform firmware and the OS: Devices
+that can be discovered and enumerated natively, through a protocol defined for
+the specific bus that they are on (for example, configuration space in PCI),
+without the platform firmware assistance, and devices that need to be described
+by the platform firmware so that they can be discovered. Still, for any device
+known to the platform firmware, regardless of which category it falls into,
+there can be a corresponding ACPI device object in the ACPI Namespace in which
+case the Linux kernel will create a struct acpi_device object based on it for
+that device.
+
+Those struct acpi_device objects are never used for binding drivers to natively
+discoverable devices, because they are represented by other types of device
+objects (for example, struct pci_dev for PCI devices) that are bound to by
+device drivers (the corresponding struct acpi_device object is then used as
+an additional source of information on the configuration of the given device).
+Moreover, the core ACPI device enumeration code creates struct platform_device
+objects for the majority of devices that are discovered and enumerated with the
+help of the platform firmware and those platform device objects can be bound to
+by platform drivers in direct analogy with the natively enumerable devices
+case. Therefore it is logically inconsistent and so generally invalid to bind
+drivers to struct acpi_device objects, including drivers for devices that are
+discovered with the help of the platform firmware.
+
+Historically, ACPI drivers that bound directly to struct acpi_device objects
+were implemented for some devices enumerated with the help of the platform
+firmware, but this is not recommended for any new drivers. As explained above,
+platform device objects are created for those devices as a rule (with a few
+exceptions that are not relevant here) and so platform drivers should be used
+for handling them, even though the corresponding ACPI device objects are the
+only source of device configuration information in that case.
+
+For every device having a corresponding struct acpi_device object, the pointer
+to it is returned by the ACPI_COMPANION() macro, so it is always possible to
+get to the device configuration information stored in the ACPI device object
+this way. Accordingly, struct acpi_device can be regarded as a part of the
+interface between the kernel and the ACPI Namespace, whereas device objects of
+other types (for example, struct pci_dev or struct platform_device) are used
+for interacting with the rest of the system.
+
DMA support
===========
diff --git a/Documentation/gpu/amdgpu/driver-misc.rst b/Documentation/gpu/amdgpu/driver-misc.rst
index 4321c38fef21..e40e15f89fd3 100644
--- a/Documentation/gpu/amdgpu/driver-misc.rst
+++ b/Documentation/gpu/amdgpu/driver-misc.rst
@@ -26,12 +26,30 @@ serial_number
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
:doc: serial_number
+fru_id
+-------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
+ :doc: fru_id
+
+manufacturer
+-------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
+ :doc: manufacturer
+
unique_id
---------
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
:doc: unique_id
+board_info
+----------
+
+.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+ :doc: board_info
+
Accelerated Processing Units (APU) Info
---------------------------------------
diff --git a/Documentation/gpu/amdgpu/thermal.rst b/Documentation/gpu/amdgpu/thermal.rst
index 5e27e4eb3959..2f6166f81e6a 100644
--- a/Documentation/gpu/amdgpu/thermal.rst
+++ b/Documentation/gpu/amdgpu/thermal.rst
@@ -64,6 +64,36 @@ gpu_metrics
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
:doc: gpu_metrics
+fan_curve
+---------
+
+.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
+ :doc: fan_curve
+
+acoustic_limit_rpm_threshold
+----------------------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
+ :doc: acoustic_limit_rpm_threshold
+
+acoustic_target_rpm_threshold
+-----------------------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
+ :doc: acoustic_target_rpm_threshold
+
+fan_target_temperature
+----------------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
+ :doc: fan_target_temperature
+
+fan_minimum_pwm
+---------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
+ :doc: fan_minimum_pwm
+
GFXOFF
======
diff --git a/Documentation/gpu/automated_testing.rst b/Documentation/gpu/automated_testing.rst
index 469b6fb65c30..240e29d5ba68 100644
--- a/Documentation/gpu/automated_testing.rst
+++ b/Documentation/gpu/automated_testing.rst
@@ -67,6 +67,19 @@ Lists the tests that for a given driver on a specific hardware revision are
known to behave unreliably. These tests won't cause a job to fail regardless of
the result. They will still be run.
+Each new flake entry must be associated with a link to the email reporting the
+bug to the author of the affected driver, the board name or Device Tree name of
+the board, the first kernel version affected, and an approximation of the
+failure rate.
+
+They should be provided under the following format::
+
+ # Bug Report: $LORE_OR_PATCHWORK_URL
+ # Board Name: broken-board.dtb
+ # Version: 6.6-rc1
+ # Failure Rate: 100
+ flaky-test
+
drivers/gpu/drm/ci/${DRIVER_NAME}-${HW_REVISION}-skips.txt
-----------------------------------------------------------
@@ -86,10 +99,13 @@ https://gitlab.freedesktop.org/janedoe/linux/-/settings/ci_cd), change the
CI/CD configuration file from .gitlab-ci.yml to
drivers/gpu/drm/ci/gitlab-ci.yml.
-3. Next time you push to this repository, you will see a CI pipeline being
+3. Request to be added to the drm/ci-ok group so that your user has the
+necessary privileges to run the CI on https://gitlab.freedesktop.org/drm/ci-ok
+
+4. Next time you push to this repository, you will see a CI pipeline being
created (eg. https://gitlab.freedesktop.org/janedoe/linux/-/pipelines)
-4. The various jobs will be run and when the pipeline is finished, all jobs
+5. The various jobs will be run and when the pipeline is finished, all jobs
should be green unless a regression has been found.
diff --git a/Documentation/gpu/drivers.rst b/Documentation/gpu/drivers.rst
index 3a52f48215a3..45a12e552091 100644
--- a/Documentation/gpu/drivers.rst
+++ b/Documentation/gpu/drivers.rst
@@ -18,6 +18,7 @@ GPU Driver Documentation
xen-front
afbc
komeda-kms
+ panfrost
.. only:: subproject and html
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index a0c83fc48126..270d320407c7 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -360,6 +360,8 @@ Format Functions Reference
.. kernel-doc:: drivers/gpu/drm/drm_fourcc.c
:export:
+.. _kms_dumb_buffer_objects:
+
Dumb Buffer Objects
===================
diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst
index c19b34b1c0ed..602010cb6894 100644
--- a/Documentation/gpu/drm-mm.rst
+++ b/Documentation/gpu/drm-mm.rst
@@ -466,40 +466,40 @@ DRM MM Range Allocator Function References
.. kernel-doc:: drivers/gpu/drm/drm_mm.c
:export:
-DRM GPU VA Manager
-==================
+DRM GPUVM
+=========
Overview
--------
-.. kernel-doc:: drivers/gpu/drm/drm_gpuva_mgr.c
+.. kernel-doc:: drivers/gpu/drm/drm_gpuvm.c
:doc: Overview
Split and Merge
---------------
-.. kernel-doc:: drivers/gpu/drm/drm_gpuva_mgr.c
+.. kernel-doc:: drivers/gpu/drm/drm_gpuvm.c
:doc: Split and Merge
Locking
-------
-.. kernel-doc:: drivers/gpu/drm/drm_gpuva_mgr.c
+.. kernel-doc:: drivers/gpu/drm/drm_gpuvm.c
:doc: Locking
Examples
--------
-.. kernel-doc:: drivers/gpu/drm/drm_gpuva_mgr.c
+.. kernel-doc:: drivers/gpu/drm/drm_gpuvm.c
:doc: Examples
-DRM GPU VA Manager Function References
---------------------------------------
+DRM GPUVM Function References
+-----------------------------
-.. kernel-doc:: include/drm/drm_gpuva_mgr.h
+.. kernel-doc:: include/drm/drm_gpuvm.h
:internal:
-.. kernel-doc:: drivers/gpu/drm/drm_gpuva_mgr.c
+.. kernel-doc:: drivers/gpu/drm/drm_gpuvm.c
:export:
DRM Buddy Allocator
diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst
index 65fb3036a580..370d820be248 100644
--- a/Documentation/gpu/drm-uapi.rst
+++ b/Documentation/gpu/drm-uapi.rst
@@ -285,6 +285,83 @@ for GPU1 and GPU2 from different vendors, and a third handler for
mmapped regular files. Threads cause additional pain with signal
handling as well.
+Device reset
+============
+
+The GPU stack is really complex and is prone to errors, from hardware bugs,
+faulty applications and everything in between the many layers. Some errors
+require resetting the device in order to make the device usable again. This
+section describes the expectations for DRM and usermode drivers when a
+device resets and how to propagate the reset status.
+
+Device resets can not be disabled without tainting the kernel, which can lead to
+hanging the entire kernel through shrinkers/mmu_notifiers. Userspace role in
+device resets is to propagate the message to the application and apply any
+special policy for blocking guilty applications, if any. Corollary is that
+debugging a hung GPU context require hardware support to be able to preempt such
+a GPU context while it's stopped.
+
+Kernel Mode Driver
+------------------
+
+The KMD is responsible for checking if the device needs a reset, and to perform
+it as needed. Usually a hang is detected when a job gets stuck executing. KMD
+should keep track of resets, because userspace can query any time about the
+reset status for a specific context. This is needed to propagate to the rest of
+the stack that a reset has happened. Currently, this is implemented by each
+driver separately, with no common DRM interface. Ideally this should be properly
+integrated at DRM scheduler to provide a common ground for all drivers. After a
+reset, KMD should reject new command submissions for affected contexts.
+
+User Mode Driver
+----------------
+
+After command submission, UMD should check if the submission was accepted or
+rejected. After a reset, KMD should reject submissions, and UMD can issue an
+ioctl to the KMD to check the reset status, and this can be checked more often
+if the UMD requires it. After detecting a reset, UMD will then proceed to report
+it to the application using the appropriate API error code, as explained in the
+section below about robustness.
+
+Robustness
+----------
+
+The only way to try to keep a graphical API context working after a reset is if
+it complies with the robustness aspects of the graphical API that it is using.
+
+Graphical APIs provide ways to applications to deal with device resets. However,
+there is no guarantee that the app will use such features correctly, and a
+userspace that doesn't support robust interfaces (like a non-robust
+OpenGL context or API without any robustness support like libva) leave the
+robustness handling entirely to the userspace driver. There is no strong
+community consensus on what the userspace driver should do in that case,
+since all reasonable approaches have some clear downsides.
+
+OpenGL
+~~~~~~
+
+Apps using OpenGL should use the available robust interfaces, like the
+extension ``GL_ARB_robustness`` (or ``GL_EXT_robustness`` for OpenGL ES). This
+interface tells if a reset has happened, and if so, all the context state is
+considered lost and the app proceeds by creating new ones. There's no consensus
+on what to do to if robustness is not in use.
+
+Vulkan
+~~~~~~
+
+Apps using Vulkan should check for ``VK_ERROR_DEVICE_LOST`` for submissions.
+This error code means, among other things, that a device reset has happened and
+it needs to recreate the contexts to keep going.
+
+Reporting causes of resets
+--------------------------
+
+Apart from propagating the reset through the stack so apps can recover, it's
+really useful for driver developers to learn more about what caused the reset in
+the first place. DRM devices should make use of devcoredump to store relevant
+information about the reset, so this information can be added to user bug
+reports.
+
.. _drm_driver_ioctl:
IOCTL Support on Device Nodes
@@ -450,12 +527,12 @@ VBlank event handling
The DRM core exposes two vertical blank related ioctls:
-DRM_IOCTL_WAIT_VBLANK
+:c:macro:`DRM_IOCTL_WAIT_VBLANK`
This takes a struct drm_wait_vblank structure as its argument, and
it is used to block or request a signal when a specified vblank
event occurs.
-DRM_IOCTL_MODESET_CTL
+:c:macro:`DRM_IOCTL_MODESET_CTL`
This was only used for user-mode-settind drivers around modesetting
changes to allow the kernel to update the vblank interrupt after
mode setting, since on many devices the vertical blank counter is
@@ -478,11 +555,18 @@ The index is used in cases where a densely packed identifier for a CRTC is
needed, for instance a bitmask of CRTC's. The member possible_crtcs of struct
drm_mode_get_plane is an example.
-DRM_IOCTL_MODE_GETRESOURCES populates a structure with an array of CRTC ID's,
-and the CRTC index is its position in this array.
+:c:macro:`DRM_IOCTL_MODE_GETRESOURCES` populates a structure with an array of
+CRTC ID's, and the CRTC index is its position in this array.
.. kernel-doc:: include/uapi/drm/drm.h
:internal:
.. kernel-doc:: include/uapi/drm/drm_mode.h
:internal:
+
+
+dma-buf interoperability
+========================
+
+Please see Documentation/userspace-api/dma-buf-alloc-exchange.rst for
+information on how dma-buf is integrated and exposed within DRM.
diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/gpu/drm-usage-stats.rst
index 044e6b2ed1be..7aca5c7a7b1d 100644
--- a/Documentation/gpu/drm-usage-stats.rst
+++ b/Documentation/gpu/drm-usage-stats.rst
@@ -169,3 +169,4 @@ Driver specific implementations
-------------------------------
:ref:`i915-usage-stats`
+:ref:`panfrost-usage-stats`
diff --git a/Documentation/gpu/drm-vm-bind-async.rst b/Documentation/gpu/drm-vm-bind-async.rst
new file mode 100644
index 000000000000..3d709d02099c
--- /dev/null
+++ b/Documentation/gpu/drm-vm-bind-async.rst
@@ -0,0 +1,309 @@
+.. SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+====================
+Asynchronous VM_BIND
+====================
+
+Nomenclature:
+=============
+
+* ``VRAM``: On-device memory. Sometimes referred to as device local memory.
+
+* ``gpu_vm``: A virtual GPU address space. Typically per process, but
+ can be shared by multiple processes.
+
+* ``VM_BIND``: An operation or a list of operations to modify a gpu_vm using
+ an IOCTL. The operations include mapping and unmapping system- or
+ VRAM memory.
+
+* ``syncobj``: A container that abstracts synchronization objects. The
+ synchronization objects can be either generic, like dma-fences or
+ driver specific. A syncobj typically indicates the type of the
+ underlying synchronization object.
+
+* ``in-syncobj``: Argument to a VM_BIND IOCTL, the VM_BIND operation waits
+ for these before starting.
+
+* ``out-syncobj``: Argument to a VM_BIND_IOCTL, the VM_BIND operation
+ signals these when the bind operation is complete.
+
+* ``dma-fence``: A cross-driver synchronization object. A basic
+ understanding of dma-fences is required to digest this
+ document. Please refer to the ``DMA Fences`` section of the
+ :doc:`dma-buf doc </driver-api/dma-buf>`.
+
+* ``memory fence``: A synchronization object, different from a dma-fence.
+ A memory fence uses the value of a specified memory location to determine
+ signaled status. A memory fence can be awaited and signaled by both
+ the GPU and CPU. Memory fences are sometimes referred to as
+ user-fences, userspace-fences or gpu futexes and do not necessarily obey
+ the dma-fence rule of signaling within a "reasonable amount of time".
+ The kernel should thus avoid waiting for memory fences with locks held.
+
+* ``long-running workload``: A workload that may take more than the
+ current stipulated dma-fence maximum signal delay to complete and
+ which therefore needs to set the gpu_vm or the GPU execution context in
+ a certain mode that disallows completion dma-fences.
+
+* ``exec function``: An exec function is a function that revalidates all
+ affected gpu_vmas, submits a GPU command batch and registers the
+ dma_fence representing the GPU command's activity with all affected
+ dma_resvs. For completeness, although not covered by this document,
+ it's worth mentioning that an exec function may also be the
+ revalidation worker that is used by some drivers in compute /
+ long-running mode.
+
+* ``bind context``: A context identifier used for the VM_BIND
+ operation. VM_BIND operations that use the same bind context can be
+ assumed, where it matters, to complete in order of submission. No such
+ assumptions can be made for VM_BIND operations using separate bind contexts.
+
+* ``UMD``: User-mode driver.
+
+* ``KMD``: Kernel-mode driver.
+
+
+Synchronous / Asynchronous VM_BIND operation
+============================================
+
+Synchronous VM_BIND
+___________________
+With Synchronous VM_BIND, the VM_BIND operations all complete before the
+IOCTL returns. A synchronous VM_BIND takes neither in-fences nor
+out-fences. Synchronous VM_BIND may block and wait for GPU operations;
+for example swap-in or clearing, or even previous binds.
+
+Asynchronous VM_BIND
+____________________
+Asynchronous VM_BIND accepts both in-syncobjs and out-syncobjs. While the
+IOCTL may return immediately, the VM_BIND operations wait for the in-syncobjs
+before modifying the GPU page-tables, and signal the out-syncobjs when
+the modification is done in the sense that the next exec function that
+awaits for the out-syncobjs will see the change. Errors are reported
+synchronously.
+In low-memory situations the implementation may block, performing the
+VM_BIND synchronously, because there might not be enough memory
+immediately available for preparing the asynchronous operation.
+
+If the VM_BIND IOCTL takes a list or an array of operations as an argument,
+the in-syncobjs needs to signal before the first operation starts to
+execute, and the out-syncobjs signal after the last operation
+completes. Operations in the operation list can be assumed, where it
+matters, to complete in order.
+
+Since asynchronous VM_BIND operations may use dma-fences embedded in
+out-syncobjs and internally in KMD to signal bind completion, any
+memory fences given as VM_BIND in-fences need to be awaited
+synchronously before the VM_BIND ioctl returns, since dma-fences,
+required to signal in a reasonable amount of time, can never be made
+to depend on memory fences that don't have such a restriction.
+
+The purpose of an Asynchronous VM_BIND operation is for user-mode
+drivers to be able to pipeline interleaved gpu_vm modifications and
+exec functions. For long-running workloads, such pipelining of a bind
+operation is not allowed and any in-fences need to be awaited
+synchronously. The reason for this is twofold. First, any memory
+fences gated by a long-running workload and used as in-syncobjs for the
+VM_BIND operation will need to be awaited synchronously anyway (see
+above). Second, any dma-fences used as in-syncobjs for VM_BIND
+operations for long-running workloads will not allow for pipelining
+anyway since long-running workloads don't allow for dma-fences as
+out-syncobjs, so while theoretically possible the use of them is
+questionable and should be rejected until there is a valuable use-case.
+Note that this is not a limitation imposed by dma-fence rules, but
+rather a limitation imposed to keep KMD implementation simple. It does
+not affect using dma-fences as dependencies for the long-running
+workload itself, which is allowed by dma-fence rules, but rather for
+the VM_BIND operation only.
+
+An asynchronous VM_BIND operation may take substantial time to
+complete and signal the out_fence. In particular if the operation is
+deeply pipelined behind other VM_BIND operations and workloads
+submitted using exec functions. In that case, UMD might want to avoid a
+subsequent VM_BIND operation to be queued behind the first one if
+there are no explicit dependencies. In order to circumvent such a queue-up, a
+VM_BIND implementation may allow for VM_BIND contexts to be
+created. For each context, VM_BIND operations will be guaranteed to
+complete in the order they were submitted, but that is not the case
+for VM_BIND operations executing on separate VM_BIND contexts. Instead
+KMD will attempt to execute such VM_BIND operations in parallel but
+leaving no guarantee that they will actually be executed in
+parallel. There may be internal implicit dependencies that only KMD knows
+about, for example page-table structure changes. A way to attempt
+to avoid such internal dependencies is to have different VM_BIND
+contexts use separate regions of a VM.
+
+Also for VM_BINDS for long-running gpu_vms the user-mode driver should typically
+select memory fences as out-fences since that gives greater flexibility for
+the kernel mode driver to inject other operations into the bind /
+unbind operations. Like for example inserting breakpoints into batch
+buffers. The workload execution can then easily be pipelined behind
+the bind completion using the memory out-fence as the signal condition
+for a GPU semaphore embedded by UMD in the workload.
+
+There is no difference in the operations supported or in
+multi-operation support between asynchronous VM_BIND and synchronous VM_BIND.
+
+Multi-operation VM_BIND IOCTL error handling and interrupts
+===========================================================
+
+The VM_BIND operations of the IOCTL may error for various reasons, for
+example due to lack of resources to complete and due to interrupted
+waits.
+In these situations UMD should preferably restart the IOCTL after
+taking suitable action.
+If UMD has over-committed a memory resource, an -ENOSPC error will be
+returned, and UMD may then unbind resources that are not used at the
+moment and rerun the IOCTL. On -EINTR, UMD should simply rerun the
+IOCTL and on -ENOMEM user-space may either attempt to free known
+system memory resources or fail. In case of UMD deciding to fail a
+bind operation, due to an error return, no additional action is needed
+to clean up the failed operation, and the VM is left in the same state
+as it was before the failing IOCTL.
+Unbind operations are guaranteed not to return any errors due to
+resource constraints, but may return errors due to, for example,
+invalid arguments or the gpu_vm being banned.
+In the case an unexpected error happens during the asynchronous bind
+process, the gpu_vm will be banned, and attempts to use it after banning
+will return -ENOENT.
+
+Example: The Xe VM_BIND uAPI
+============================
+
+Starting with the VM_BIND operation struct, the IOCTL call can take
+zero, one or many such operations. A zero number means only the
+synchronization part of the IOCTL is carried out: an asynchronous
+VM_BIND updates the syncobjects, whereas a sync VM_BIND waits for the
+implicit dependencies to be fulfilled.
+
+.. code-block:: c
+
+ struct drm_xe_vm_bind_op {
+ /**
+ * @obj: GEM object to operate on, MBZ for MAP_USERPTR, MBZ for UNMAP
+ */
+ __u32 obj;
+
+ /** @pad: MBZ */
+ __u32 pad;
+
+ union {
+ /**
+ * @obj_offset: Offset into the object for MAP.
+ */
+ __u64 obj_offset;
+
+ /** @userptr: user virtual address for MAP_USERPTR */
+ __u64 userptr;
+ };
+
+ /**
+ * @range: Number of bytes from the object to bind to addr, MBZ for UNMAP_ALL
+ */
+ __u64 range;
+
+ /** @addr: Address to operate on, MBZ for UNMAP_ALL */
+ __u64 addr;
+
+ /**
+ * @tile_mask: Mask for which tiles to create binds for, 0 == All tiles,
+ * only applies to creating new VMAs
+ */
+ __u64 tile_mask;
+
+ /* Map (parts of) an object into the GPU virtual address range.
+ #define XE_VM_BIND_OP_MAP 0x0
+ /* Unmap a GPU virtual address range */
+ #define XE_VM_BIND_OP_UNMAP 0x1
+ /*
+ * Map a CPU virtual address range into a GPU virtual
+ * address range.
+ */
+ #define XE_VM_BIND_OP_MAP_USERPTR 0x2
+ /* Unmap a gem object from the VM. */
+ #define XE_VM_BIND_OP_UNMAP_ALL 0x3
+ /*
+ * Make the backing memory of an address range resident if
+ * possible. Note that this doesn't pin backing memory.
+ */
+ #define XE_VM_BIND_OP_PREFETCH 0x4
+
+ /* Make the GPU map readonly. */
+ #define XE_VM_BIND_FLAG_READONLY (0x1 << 16)
+ /*
+ * Valid on a faulting VM only, do the MAP operation immediately rather
+ * than deferring the MAP to the page fault handler.
+ */
+ #define XE_VM_BIND_FLAG_IMMEDIATE (0x1 << 17)
+ /*
+ * When the NULL flag is set, the page tables are setup with a special
+ * bit which indicates writes are dropped and all reads return zero. In
+ * the future, the NULL flags will only be valid for XE_VM_BIND_OP_MAP
+ * operations, the BO handle MBZ, and the BO offset MBZ. This flag is
+ * intended to implement VK sparse bindings.
+ */
+ #define XE_VM_BIND_FLAG_NULL (0x1 << 18)
+ /** @op: Operation to perform (lower 16 bits) and flags (upper 16 bits) */
+ __u32 op;
+
+ /** @mem_region: Memory region to prefetch VMA to, instance not a mask */
+ __u32 region;
+
+ /** @reserved: Reserved */
+ __u64 reserved[2];
+ };
+
+
+The VM_BIND IOCTL argument itself, looks like follows. Note that for
+synchronous VM_BIND, the num_syncs and syncs fields must be zero. Here
+the ``exec_queue_id`` field is the VM_BIND context discussed previously
+that is used to facilitate out-of-order VM_BINDs.
+
+.. code-block:: c
+
+ struct drm_xe_vm_bind {
+ /** @extensions: Pointer to the first extension struct, if any */
+ __u64 extensions;
+
+ /** @vm_id: The ID of the VM to bind to */
+ __u32 vm_id;
+
+ /**
+ * @exec_queue_id: exec_queue_id, must be of class DRM_XE_ENGINE_CLASS_VM_BIND
+ * and exec queue must have same vm_id. If zero, the default VM bind engine
+ * is used.
+ */
+ __u32 exec_queue_id;
+
+ /** @num_binds: number of binds in this IOCTL */
+ __u32 num_binds;
+
+ /* If set, perform an async VM_BIND, if clear a sync VM_BIND */
+ #define XE_VM_BIND_IOCTL_FLAG_ASYNC (0x1 << 0)
+
+ /** @flag: Flags controlling all operations in this ioctl. */
+ __u32 flags;
+
+ union {
+ /** @bind: used if num_binds == 1 */
+ struct drm_xe_vm_bind_op bind;
+
+ /**
+ * @vector_of_binds: userptr to array of struct
+ * drm_xe_vm_bind_op if num_binds > 1
+ */
+ __u64 vector_of_binds;
+ };
+
+ /** @num_syncs: amount of syncs to wait for or to signal on completion. */
+ __u32 num_syncs;
+
+ /** @pad2: MBZ */
+ __u32 pad2;
+
+ /** @syncs: pointer to struct drm_xe_sync array */
+ __u64 syncs;
+
+ /** @reserved: Reserved */
+ __u64 reserved[2];
+ };
diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst
index 378e825754d5..0ca1550fd9dc 100644
--- a/Documentation/gpu/i915.rst
+++ b/Documentation/gpu/i915.rst
@@ -267,19 +267,22 @@ i915 driver.
Intel GPU Basics
----------------
-An Intel GPU has multiple engines. There are several engine types.
-
-- RCS engine is for rendering 3D and performing compute, this is named
- `I915_EXEC_RENDER` in user space.
-- BCS is a blitting (copy) engine, this is named `I915_EXEC_BLT` in user
- space.
-- VCS is a video encode and decode engine, this is named `I915_EXEC_BSD`
- in user space
-- VECS is video enhancement engine, this is named `I915_EXEC_VEBOX` in user
- space.
-- The enumeration `I915_EXEC_DEFAULT` does not refer to specific engine;
- instead it is to be used by user space to specify a default rendering
- engine (for 3D) that may or may not be the same as RCS.
+An Intel GPU has multiple engines. There are several engine types:
+
+- Render Command Streamer (RCS). An engine for rendering 3D and
+ performing compute.
+- Blitting Command Streamer (BCS). An engine for performing blitting and/or
+ copying operations.
+- Video Command Streamer. An engine used for video encoding and decoding. Also
+ sometimes called 'BSD' in hardware documentation.
+- Video Enhancement Command Streamer (VECS). An engine for video enhancement.
+ Also sometimes called 'VEBOX' in hardware documentation.
+- Compute Command Streamer (CCS). An engine that has access to the media and
+ GPGPU pipelines, but not the 3D pipeline.
+- Graphics Security Controller (GSCCS). A dedicated engine for internal
+ communication with GSC controller on security related tasks like
+ High-bandwidth Digital Content Protection (HDCP), Protected Xe Path (PXP),
+ and HuC firmware authentication.
The Intel GPU family is a family of integrated GPU's using Unified
Memory Access. For having the GPU "do work", user space will feed the
diff --git a/Documentation/gpu/implementation_guidelines.rst b/Documentation/gpu/implementation_guidelines.rst
new file mode 100644
index 000000000000..138e637dcc6b
--- /dev/null
+++ b/Documentation/gpu/implementation_guidelines.rst
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+===========================================================
+Misc DRM driver uAPI- and feature implementation guidelines
+===========================================================
+
+.. toctree::
+
+ drm-vm-bind-async
diff --git a/Documentation/gpu/index.rst b/Documentation/gpu/index.rst
index e45ff0915246..37e383ccf73f 100644
--- a/Documentation/gpu/index.rst
+++ b/Documentation/gpu/index.rst
@@ -18,6 +18,7 @@ GPU Driver Developer's Guide
vga-switcheroo
vgaarbiter
automated_testing
+ implementation_guidelines
todo
rfc/index
diff --git a/Documentation/gpu/panfrost.rst b/Documentation/gpu/panfrost.rst
new file mode 100644
index 000000000000..b80e41f4b2c5
--- /dev/null
+++ b/Documentation/gpu/panfrost.rst
@@ -0,0 +1,40 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+=========================
+ drm/Panfrost Mali Driver
+=========================
+
+.. _panfrost-usage-stats:
+
+Panfrost DRM client usage stats implementation
+==============================================
+
+The drm/Panfrost driver implements the DRM client usage stats specification as
+documented in :ref:`drm-client-usage-stats`.
+
+Example of the output showing the implemented key value pairs and entirety of
+the currently possible format options:
+
+::
+ pos: 0
+ flags: 02400002
+ mnt_id: 27
+ ino: 531
+ drm-driver: panfrost
+ drm-client-id: 14
+ drm-engine-fragment: 1846584880 ns
+ drm-cycles-fragment: 1424359409
+ drm-maxfreq-fragment: 799999987 Hz
+ drm-curfreq-fragment: 799999987 Hz
+ drm-engine-vertex-tiler: 71932239 ns
+ drm-cycles-vertex-tiler: 52617357
+ drm-maxfreq-vertex-tiler: 799999987 Hz
+ drm-curfreq-vertex-tiler: 799999987 Hz
+ drm-total-memory: 290 MiB
+ drm-shared-memory: 0 MiB
+ drm-active-memory: 226 MiB
+ drm-resident-memory: 36496 KiB
+ drm-purgeable-memory: 128 KiB
+
+Possible `drm-engine-` key names are: `fragment`, and `vertex-tiler`.
+`drm-curfreq-` values convey the current operating frequency for that engine.
diff --git a/Documentation/gpu/rfc/xe.rst b/Documentation/gpu/rfc/xe.rst
index 2516fe141db6..c29113a0ac30 100644
--- a/Documentation/gpu/rfc/xe.rst
+++ b/Documentation/gpu/rfc/xe.rst
@@ -67,14 +67,8 @@ platforms.
When the time comes for Xe, the protection will be lifted on Xe and kept in i915.
-Xe driver will be protected with both STAGING Kconfig and force_probe. Changes in
-the uAPI are expected while the driver is behind these protections. STAGING will
-be removed when the driver uAPI gets to a mature state where we can guarantee the
-‘no regression’ rule. Then force_probe will be lifted only for future platforms
-that will be productized with Xe driver, but not with i915.
-
-Xe – Pre-Merge Goals
-====================
+Xe – Pre-Merge Goals - Work-in-Progress
+=======================================
Drm_scheduler
-------------
@@ -94,41 +88,6 @@ depend on any other patch touching drm_scheduler itself that was not yet merged
through drm-misc. This, by itself, already includes the reach of an agreement for
uniform 1 to 1 relationship implementation / usage across drivers.
-GPU VA
-------
-Two main goals of Xe are meeting together here:
-
-1) Have an uAPI that aligns with modern UMD needs.
-
-2) Early upstream engagement.
-
-RedHat engineers working on Nouveau proposed a new DRM feature to handle keeping
-track of GPU virtual address mappings. This is still not merged upstream, but
-this aligns very well with our goals and with our VM_BIND. The engagement with
-upstream and the port of Xe towards GPUVA is already ongoing.
-
-As a key measurable result, Xe needs to be aligned with the GPU VA and working in
-our tree. Missing Nouveau patches should *not* block Xe and any needed GPUVA
-related patch should be independent and present on dri-devel or acked by
-maintainers to go along with the first Xe pull request towards drm-next.
-
-DRM_VM_BIND
------------
-Nouveau, and Xe are all implementing ‘VM_BIND’ and new ‘Exec’ uAPIs in order to
-fulfill the needs of the modern uAPI. Xe merge should *not* be blocked on the
-development of a common new drm_infrastructure. However, the Xe team needs to
-engage with the community to explore the options of a common API.
-
-As a key measurable result, the DRM_VM_BIND needs to be documented in this file
-below, or this entire block deleted if the consensus is for independent drivers
-vm_bind ioctls.
-
-Although having a common DRM level IOCTL for VM_BIND is not a requirement to get
-Xe merged, it is mandatory to enforce the overall locking scheme for all major
-structs and list (so vm and vma). So, a consensus is needed, and possibly some
-common helpers. If helpers are needed, they should be also documented in this
-document.
-
ASYNC VM_BIND
-------------
Although having a common DRM level IOCTL for VM_BIND is not a requirement to get
@@ -138,8 +97,8 @@ memory fences. Ideally with helper support so people don't get it wrong in all
possible ways.
As a key measurable result, the benefits of ASYNC VM_BIND and a discussion of
-various flavors, error handling and a sample API should be documented here or in
-a separate document pointed to by this document.
+various flavors, error handling and sample API suggestions are documented in
+:doc:`The ASYNC VM_BIND document </gpu/drm-vm-bind-async>`.
Userptr integration and vm_bind
-------------------------------
@@ -212,6 +171,14 @@ This item ties into the GPUVA, VM_BIND, and even long-running compute support.
As a key measurable result, we need to have a community consensus documented in
this document and the Xe driver prepared for the changes, if necessary.
+Xe – uAPI high level overview
+=============================
+
+...Warning: To be done in follow up patches after/when/where the main consensus in various items are individually reached.
+
+Xe – Pre-Merge Goals - Completed
+================================
+
Dev_coredump
------------
@@ -229,7 +196,37 @@ infrastructure with overall possible improvements, like multiple file support
for better organization of the dumps, snapshot support, dmesg extra print,
and whatever may make sense and help the overall infrastructure.
-Xe – uAPI high level overview
-=============================
+DRM_VM_BIND
+-----------
+Nouveau, and Xe are all implementing ‘VM_BIND’ and new ‘Exec’ uAPIs in order to
+fulfill the needs of the modern uAPI. Xe merge should *not* be blocked on the
+development of a common new drm_infrastructure. However, the Xe team needs to
+engage with the community to explore the options of a common API.
-...Warning: To be done in follow up patches after/when/where the main consensus in various items are individually reached.
+As a key measurable result, the DRM_VM_BIND needs to be documented in this file
+below, or this entire block deleted if the consensus is for independent drivers
+vm_bind ioctls.
+
+Although having a common DRM level IOCTL for VM_BIND is not a requirement to get
+Xe merged, it is mandatory to enforce the overall locking scheme for all major
+structs and list (so vm and vma). So, a consensus is needed, and possibly some
+common helpers. If helpers are needed, they should be also documented in this
+document.
+
+GPU VA
+------
+Two main goals of Xe are meeting together here:
+
+1) Have an uAPI that aligns with modern UMD needs.
+
+2) Early upstream engagement.
+
+RedHat engineers working on Nouveau proposed a new DRM feature to handle keeping
+track of GPU virtual address mappings. This is still not merged upstream, but
+this aligns very well with our goals and with our VM_BIND. The engagement with
+upstream and the port of Xe towards GPUVA is already ongoing.
+
+As a key measurable result, Xe needs to be aligned with the GPU VA and working in
+our tree. Missing Nouveau patches should *not* block Xe and any needed GPUVA
+related patch should be independent and present on dri-devel or acked by
+maintainers to go along with the first Xe pull request towards drm-next.
diff --git a/Documentation/hwmon/adt7475.rst b/Documentation/hwmon/adt7475.rst
index ef3ea1ea9bc1..f90f769d82d6 100644
--- a/Documentation/hwmon/adt7475.rst
+++ b/Documentation/hwmon/adt7475.rst
@@ -90,7 +90,7 @@ ADT7476:
ADT7490:
* 6 voltage inputs
- * 1 Imon input (not implemented)
+ * 1 Imon input
* PECI support (not implemented)
* 2 GPIO pins (not implemented)
* system acoustics optimizations (not implemented)
@@ -107,6 +107,7 @@ in2 VCC (4) VCC (4) VCC (4) VCC (3)
in3 5VIN (20) 5VIN (20)
in4 12VIN (21) 12VIN (21)
in5 VTT (8)
+in6 Imon (19)
==== =========== =========== ========= ==========
Special Features
diff --git a/Documentation/hwmon/aquacomputer_d5next.rst b/Documentation/hwmon/aquacomputer_d5next.rst
index 94dc2d93d180..cb073c79479c 100644
--- a/Documentation/hwmon/aquacomputer_d5next.rst
+++ b/Documentation/hwmon/aquacomputer_d5next.rst
@@ -16,6 +16,8 @@ Supported devices:
* Aquacomputer Aquastream XT watercooling pump
* Aquacomputer Aquastream Ultimate watercooling pump
* Aquacomputer Poweradjust 3 fan controller
+* Aquacomputer High Flow USB flow meter
+* Aquacomputer MPS Flow devices
Author: Aleksa Savic
@@ -73,6 +75,11 @@ It also exposes pressure and flow speed readings.
The Poweradjust 3 controller exposes a single external temperature sensor.
+The High Flow USB exposes an internal and external temperature sensor, and a flow meter.
+
+The MPS Flow devices expose the same entries as the High Flow USB because they have
+the same USB product ID and report sensors equivalently.
+
Depending on the device, not all sysfs and debugfs entries will be available.
Writing to virtual temperature sensors is not currently supported.
diff --git a/Documentation/hwmon/asus_ec_sensors.rst b/Documentation/hwmon/asus_ec_sensors.rst
index 7e3cd5b6686f..0bf99ba406dd 100644
--- a/Documentation/hwmon/asus_ec_sensors.rst
+++ b/Documentation/hwmon/asus_ec_sensors.rst
@@ -15,6 +15,7 @@ Supported boards:
* ROG CROSSHAIR VIII HERO
* ROG CROSSHAIR VIII IMPACT
* ROG CROSSHAIR X670E HERO
+ * ROG CROSSHAIR X670E GENE
* ROG MAXIMUS XI HERO
* ROG MAXIMUS XI HERO (WI-FI)
* ROG STRIX B550-E GAMING
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 88dadea85cfc..72f4e6065bae 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -121,6 +121,7 @@ Hardware Monitoring Kernel Drivers
ltc2947
ltc2978
ltc2990
+ ltc2991
ltc3815
ltc4151
ltc4215
@@ -178,6 +179,7 @@ Hardware Monitoring Kernel Drivers
peci-cputemp
peci-dimmtemp
pmbus
+ powerz
powr1220
pxe1610
pwm-fan
diff --git a/Documentation/hwmon/ltc2991.rst b/Documentation/hwmon/ltc2991.rst
new file mode 100644
index 000000000000..15d8b4d7e471
--- /dev/null
+++ b/Documentation/hwmon/ltc2991.rst
@@ -0,0 +1,43 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver ltc2991
+=====================
+
+Supported chips:
+
+ * Analog Devices LTC2991
+
+ Prefix: 'ltc2991'
+
+ Addresses scanned: I2C 0x48 - 0x4f
+
+ Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/2991ff.pdf
+
+Authors:
+
+ - Antoniu Miclaus <antoniu.miclaus@analog.com>
+
+
+Description
+-----------
+
+This driver supports hardware monitoring for Analog Devices LTC2991 Octal I2C
+Voltage, Current and Temperature Monitor.
+
+The LTC2991 is used to monitor system temperatures, voltages and currents.
+Through the I2C serial interface, the eight monitors can individually measure
+supply voltages and can be paired for differential measurements of current sense
+resistors or temperature sensing transistors. Additional measurements include
+internal temperatureand internal VCC.
+
+
+sysfs-Interface
+---------------
+
+The following attributes are supported. Limits are read-only.
+
+=============== =================
+inX_input: voltage input
+currX_input: current input
+tempX_input: temperature input
+=============== =================
diff --git a/Documentation/hwmon/max31827.rst b/Documentation/hwmon/max31827.rst
index b0971d05b8a4..9a1055a007cf 100644
--- a/Documentation/hwmon/max31827.rst
+++ b/Documentation/hwmon/max31827.rst
@@ -73,8 +73,8 @@ the conversion frequency to 1 conv/s. The conversion time varies depending on
the resolution. The conversion time doubles with every bit of increased
resolution. For 10 bit resolution 35ms are needed, while for 12 bit resolution
(default) 140ms. When chip is in shutdown mode and a read operation is
-requested, one-shot is triggered, the device waits for 140 (conversion time) + 1
-(error) ms, and only after that is the temperature value register read.
+requested, one-shot is triggered, the device waits for 140 (conversion time) ms,
+and only after that is the temperature value register read.
The LSB of the temperature values is 0.0625 degrees Celsius, but the values of
the temperatures are displayed in milli-degrees. This means, that some data is
diff --git a/Documentation/hwmon/nct6683.rst b/Documentation/hwmon/nct6683.rst
index 2e1408d174bd..3e7f6ee779c2 100644
--- a/Documentation/hwmon/nct6683.rst
+++ b/Documentation/hwmon/nct6683.rst
@@ -62,5 +62,6 @@ Intel DH87RL NCT6683D EC firmware version 1.0 build 04/03/13
Intel DH87MC NCT6683D EC firmware version 1.0 build 04/03/13
Intel DB85FL NCT6683D EC firmware version 1.0 build 04/03/13
ASRock X570 NCT6683D EC firmware version 1.0 build 06/28/19
+ASRock X670E NCT6686D EC firmware version 1.0 build 05/19/22
MSI B550 NCT6687D EC firmware version 1.0 build 05/07/20
=============== ===============================================
diff --git a/Documentation/hwmon/powerz.rst b/Documentation/hwmon/powerz.rst
new file mode 100644
index 000000000000..317084e0b76b
--- /dev/null
+++ b/Documentation/hwmon/powerz.rst
@@ -0,0 +1,30 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+Kernel driver POWERZ
+====================
+
+Supported chips:
+
+ * ChargerLAB POWER-Z KM003C
+
+ Prefix: 'powerz'
+
+ Addresses scanned: -
+
+Author:
+
+ - Thomas Weißschuh <linux@weissschuh.net>
+
+Description
+-----------
+
+This driver implements support for the ChargerLAB POWER-Z USB-C power testing
+family.
+
+The device communicates with the custom protocol over USB.
+
+The channel labels exposed via hwmon match the labels used by the on-device
+display and the official POWER-Z PC software.
+
+As current can flow in both directions through the tester the sign of the
+channel "curr1_input" (label "IBUS") indicates the direction.
diff --git a/Documentation/hwmon/sch5627.rst b/Documentation/hwmon/sch5627.rst
index ecb4fc84d045..8639dff234fc 100644
--- a/Documentation/hwmon/sch5627.rst
+++ b/Documentation/hwmon/sch5627.rst
@@ -33,3 +33,13 @@ The hardware monitoring part of the SMSC SCH5627 is accessed by talking
through an embedded microcontroller. An application note describing the
protocol for communicating with the microcontroller is available upon
request. Please mail me if you want a copy.
+
+
+Controlling fan speed
+---------------------
+
+The SCH5627 allows for partially controlling the fan speed. If a temperature
+channel excedes tempX_max, all fans are forced to maximum speed. The same is not
+true for tempX_crit, presumably some other measures to cool down the system are
+take in this case.
+In which way the value of fanX_min affects the fan speed is currently unknown.
diff --git a/Documentation/i2c/busses/i2c-i801.rst b/Documentation/i2c/busses/i2c-i801.rst
index e76e68ccf718..10eced6c2e46 100644
--- a/Documentation/i2c/busses/i2c-i801.rst
+++ b/Documentation/i2c/busses/i2c-i801.rst
@@ -47,6 +47,7 @@ Supported adapters:
* Intel Alder Lake (PCH)
* Intel Raptor Lake (PCH)
* Intel Meteor Lake (SOC and PCH)
+ * Intel Birch Stream (SOC)
Datasheets: Publicly available at the Intel website
diff --git a/Documentation/i2c/fault-codes.rst b/Documentation/i2c/fault-codes.rst
index 80b14e718b52..b0864d1268bd 100644
--- a/Documentation/i2c/fault-codes.rst
+++ b/Documentation/i2c/fault-codes.rst
@@ -39,6 +39,10 @@ Also, codes returned by adapter probe methods follow rules which are
specific to their host bus (such as PCI, or the platform bus).
+EAFNOSUPPORT
+ Returned by I2C adapters not supporting 10 bit addresses when
+ they are requested to use such an address.
+
EAGAIN
Returned by I2C adapters when they lose arbitration in master
transmit mode: some other master was transmitting different
diff --git a/Documentation/kbuild/kbuild.rst b/Documentation/kbuild/kbuild.rst
index bd906407e307..9c8d1d046ea5 100644
--- a/Documentation/kbuild/kbuild.rst
+++ b/Documentation/kbuild/kbuild.rst
@@ -243,6 +243,12 @@ The output directory is often set using "O=..." on the commandline.
The value can be overridden in which case the default value is ignored.
+INSTALL_DTBS_PATH
+-----------------
+INSTALL_DTBS_PATH specifies where to install device tree blobs for
+relocations required by build roots. This is not defined in the
+makefile but the argument can be passed to make if needed.
+
KBUILD_ABS_SRCTREE
--------------------------------------------------
Kbuild uses a relative path to point to the tree when possible. For instance,
diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
index e67eb261c9b0..ad118b7a1806 100644
--- a/Documentation/kbuild/makefiles.rst
+++ b/Documentation/kbuild/makefiles.rst
@@ -53,7 +53,7 @@ knowledge about the kernel Makefiles, plus detailed knowledge about the
public interface for kbuild.
*Arch developers* are people who work on an entire architecture, such
-as sparc or ia64. Arch developers need to know about the arch Makefile
+as sparc or x86. Arch developers need to know about the arch Makefile
as well as kbuild Makefiles.
*Kbuild developers* are people who work on the kernel build system itself.
@@ -937,6 +937,10 @@ Example::
# net/bpfilter/Makefile
bpfilter_umh-userldflags += -static
+To specify libraries linked to a userspace program, you can use
+``<executable>-userldlibs``. The ``userldlibs`` syntax specifies libraries
+linked to all userspace programs created in the current Makefile.
+
When linking bpfilter_umh, it will be passed the extra option -static.
From command line, :ref:`USERCFLAGS and USERLDFLAGS <userkbuildflags>` will also be used.
@@ -1623,6 +1627,13 @@ INSTALL_MOD_STRIP
INSTALL_MOD_STRIP value will be used as the option(s) to the strip
command.
+INSTALL_DTBS_PATH
+ This variable specifies a prefix for relocations required by build
+ roots. It defines a place for installing the device tree blobs. Like
+ INSTALL_MOD_PATH, it isn't defined in the Makefile, but can be passed
+ by the user if desired. Otherwise it defaults to the kernel install
+ path.
+
Makefile language
=================
diff --git a/Documentation/maintainer/maintainer-entry-profile.rst b/Documentation/maintainer/maintainer-entry-profile.rst
index 6b64072d4bf2..7ad4bfc2cc03 100644
--- a/Documentation/maintainer/maintainer-entry-profile.rst
+++ b/Documentation/maintainer/maintainer-entry-profile.rst
@@ -101,7 +101,7 @@ to do something different in the near future.
../doc-guide/maintainer-profile
../nvdimm/maintainer-entry-profile
- ../riscv/patch-acceptance
+ ../arch/riscv/patch-acceptance
../driver-api/media/maintainer-entry-profile
../driver-api/vfio-pci-device-specific-driver-acceptance
../nvme/feature-and-quirk-policy
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 06e14efd8662..d414e145f912 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -396,6 +396,10 @@ Memory barriers come in four basic varieties:
(2) Address-dependency barriers (historical).
+ [!] This section is marked as HISTORICAL: For more up-to-date
+ information, including how compiler transformations related to pointer
+ comparisons can sometimes cause problems, see
+ Documentation/RCU/rcu_dereference.rst.
An address-dependency barrier is a weaker form of read barrier. In the
case where two loads are performed such that the second depends on the
@@ -556,6 +560,9 @@ There are certain things that the Linux kernel memory barriers do not guarantee:
ADDRESS-DEPENDENCY BARRIERS (HISTORICAL)
----------------------------------------
+[!] This section is marked as HISTORICAL: For more up-to-date information,
+including how compiler transformations related to pointer comparisons can
+sometimes cause problems, see Documentation/RCU/rcu_dereference.rst.
As of v4.15 of the Linux kernel, an smp_mb() was added to READ_ONCE() for
DEC Alpha, which means that about the only people who need to pay attention
diff --git a/Documentation/misc-devices/eeprom.rst b/Documentation/misc-devices/eeprom.rst
deleted file mode 100644
index 008249675ccc..000000000000
--- a/Documentation/misc-devices/eeprom.rst
+++ /dev/null
@@ -1,107 +0,0 @@
-====================
-Kernel driver eeprom
-====================
-
-Supported chips:
-
- * Any EEPROM chip in the designated address range
-
- Prefix: 'eeprom'
-
- Addresses scanned: I2C 0x50 - 0x57
-
- Datasheets: Publicly available from:
-
- Atmel (www.atmel.com),
- Catalyst (www.catsemi.com),
- Fairchild (www.fairchildsemi.com),
- Microchip (www.microchip.com),
- Philips (www.semiconductor.philips.com),
- Rohm (www.rohm.com),
- ST (www.st.com),
- Xicor (www.xicor.com),
- and others.
-
- ========= ============= ============================================
- Chip Size (bits) Address
- ========= ============= ============================================
- 24C01 1K 0x50 (shadows at 0x51 - 0x57)
- 24C01A 1K 0x50 - 0x57 (Typical device on DIMMs)
- 24C02 2K 0x50 - 0x57
- 24C04 4K 0x50, 0x52, 0x54, 0x56
- (additional data at 0x51, 0x53, 0x55, 0x57)
- 24C08 8K 0x50, 0x54 (additional data at 0x51, 0x52,
- 0x53, 0x55, 0x56, 0x57)
- 24C16 16K 0x50 (additional data at 0x51 - 0x57)
- Sony 2K 0x57
-
- Atmel 34C02B 2K 0x50 - 0x57, SW write protect at 0x30-37
- Catalyst 34FC02 2K 0x50 - 0x57, SW write protect at 0x30-37
- Catalyst 34RC02 2K 0x50 - 0x57, SW write protect at 0x30-37
- Fairchild 34W02 2K 0x50 - 0x57, SW write protect at 0x30-37
- Microchip 24AA52 2K 0x50 - 0x57, SW write protect at 0x30-37
- ST M34C02 2K 0x50 - 0x57, SW write protect at 0x30-37
- ========= ============= ============================================
-
-
-Authors:
- - Frodo Looijaard <frodol@dds.nl>,
- - Philip Edelbrock <phil@netroedge.com>,
- - Jean Delvare <jdelvare@suse.de>,
- - Greg Kroah-Hartman <greg@kroah.com>,
- - IBM Corp.
-
-Description
------------
-
-This is a simple EEPROM module meant to enable reading the first 256 bytes
-of an EEPROM (on a SDRAM DIMM for example). However, it will access serial
-EEPROMs on any I2C adapter. The supported devices are generically called
-24Cxx, and are listed above; however the numbering for these
-industry-standard devices may vary by manufacturer.
-
-This module was a programming exercise to get used to the new project
-organization laid out by Frodo, but it should be at least completely
-effective for decoding the contents of EEPROMs on DIMMs.
-
-DIMMS will typically contain a 24C01A or 24C02, or the 34C02 variants.
-The other devices will not be found on a DIMM because they respond to more
-than one address.
-
-DDC Monitors may contain any device. Often a 24C01, which responds to all 8
-addresses, is found.
-
-Recent Sony Vaio laptops have an EEPROM at 0x57. We couldn't get the
-specification, so it is guess work and far from being complete.
-
-The Microchip 24AA52/24LCS52, ST M34C02, and others support an additional
-software write protect register at 0x30 - 0x37 (0x20 less than the memory
-location). The chip responds to "write quick" detection at this address but
-does not respond to byte reads. If this register is present, the lower 128
-bytes of the memory array are not write protected. Any byte data write to
-this address will write protect the memory array permanently, and the
-device will no longer respond at the 0x30-37 address. The eeprom driver
-does not support this register.
-
-Lacking functionality
----------------------
-
-* Full support for larger devices (24C04, 24C08, 24C16). These are not
- typically found on a PC. These devices will appear as separate devices at
- multiple addresses.
-
-* Support for really large devices (24C32, 24C64, 24C128, 24C256, 24C512).
- These devices require two-byte address fields and are not supported.
-
-* Enable Writing. Again, no technical reason why not, but making it easy
- to change the contents of the EEPROMs (on DIMMs anyway) also makes it easy
- to disable the DIMMs (potentially preventing the computer from booting)
- until the values are restored somehow.
-
-Use
----
-
-After inserting the module (and any other required SMBus/i2c modules), you
-should have some EEPROM directories in ``/sys/bus/i2c/devices/*`` of names such
-as "0-0050". Inside each of these is a series of files, the eeprom file
-contains the binary data from EEPROM.
diff --git a/Documentation/misc-devices/index.rst b/Documentation/misc-devices/index.rst
index ecc40fbbcfb8..7de16797987a 100644
--- a/Documentation/misc-devices/index.rst
+++ b/Documentation/misc-devices/index.rst
@@ -17,7 +17,6 @@ fit into other categories.
ad525x_dpot
apds990x
bh1770glc
- eeprom
c2port
dw-xdata-pcie
ibmvmc
diff --git a/Documentation/mm/damon/design.rst b/Documentation/mm/damon/design.rst
index a20383d01a95..1f7e0586b5fa 100644
--- a/Documentation/mm/damon/design.rst
+++ b/Documentation/mm/damon/design.rst
@@ -154,6 +154,8 @@ The monitoring overhead of this mechanism will arbitrarily increase as the
size of the target workload grows.
+.. _damon_design_region_based_sampling:
+
Region Based Sampling
~~~~~~~~~~~~~~~~~~~~~
@@ -163,9 +165,10 @@ assumption (pages in a region have the same access frequencies) is kept, only
one page in the region is required to be checked. Thus, for each ``sampling
interval``, DAMON randomly picks one page in each region, waits for one
``sampling interval``, checks whether the page is accessed meanwhile, and
-increases the access frequency of the region if so. Therefore, the monitoring
-overhead is controllable by setting the number of regions. DAMON allows users
-to set the minimum and the maximum number of regions for the trade-off.
+increases the access frequency counter of the region if so. The counter is
+called ``nr_regions`` of the region. Therefore, the monitoring overhead is
+controllable by setting the number of regions. DAMON allows users to set the
+minimum and the maximum number of regions for the trade-off.
This scheme, however, cannot preserve the quality of the output if the
assumption is not guaranteed.
@@ -190,6 +193,8 @@ In this way, DAMON provides its best-effort quality and minimal overhead while
keeping the bounds users set for their trade-off.
+.. _damon_design_age_tracking:
+
Age Tracking
~~~~~~~~~~~~
@@ -254,7 +259,8 @@ works, DAMON provides a feature called Data Access Monitoring-based Operation
Schemes (DAMOS). It lets users specify their desired schemes at a high
level. For such specifications, DAMON starts monitoring, finds regions having
the access pattern of interest, and applies the user-desired operation actions
-to the regions as soon as found.
+to the regions, for every user-specified time interval called
+``apply_interval``.
.. _damon_design_damos_action:
@@ -471,3 +477,15 @@ modules for proactive reclamation and LRU lists manipulation are provided. For
more detail, please read the usage documents for those
(:doc:`/admin-guide/mm/damon/reclaim` and
:doc:`/admin-guide/mm/damon/lru_sort`).
+
+
+.. _damon_design_execution_model_and_data_structures:
+
+Execution Model and Data Structures
+===================================
+
+The monitoring-related information including the monitoring request
+specification and DAMON-based operation schemes are stored in a data structure
+called DAMON ``context``. DAMON executes each context with a kernel thread
+called ``kdamond``. Multiple kdamonds could run in parallel, for different
+types of monitoring.
diff --git a/Documentation/mm/overcommit-accounting.rst b/Documentation/mm/overcommit-accounting.rst
index a4895d6fc1c2..e2263477f6d5 100644
--- a/Documentation/mm/overcommit-accounting.rst
+++ b/Documentation/mm/overcommit-accounting.rst
@@ -8,8 +8,7 @@ The Linux kernel supports the following overcommit handling modes
Heuristic overcommit handling. Obvious overcommits of address
space are refused. Used for a typical system. It ensures a
seriously wild allocation fails while allowing overcommit to
- reduce swap usage. root is allowed to allocate slightly more
- memory in this mode. This is the default.
+ reduce swap usage. This is the default.
1
Always overcommit. Appropriate for some scientific
diff --git a/Documentation/mm/page_tables.rst b/Documentation/mm/page_tables.rst
index 7840c1891751..be47b192a596 100644
--- a/Documentation/mm/page_tables.rst
+++ b/Documentation/mm/page_tables.rst
@@ -152,3 +152,130 @@ Page table handling code that wishes to be architecture-neutral, such as the
virtual memory manager, will need to be written so that it traverses all of the
currently five levels. This style should also be preferred for
architecture-specific code, so as to be robust to future changes.
+
+
+MMU, TLB, and Page Faults
+=========================
+
+The `Memory Management Unit (MMU)` is a hardware component that handles virtual
+to physical address translations. It may use relatively small caches in hardware
+called `Translation Lookaside Buffers (TLBs)` and `Page Walk Caches` to speed up
+these translations.
+
+When CPU accesses a memory location, it provides a virtual address to the MMU,
+which checks if there is the existing translation in the TLB or in the Page
+Walk Caches (on architectures that support them). If no translation is found,
+MMU uses the page walks to determine the physical address and create the map.
+
+The dirty bit for a page is set (i.e., turned on) when the page is written to.
+Each page of memory has associated permission and dirty bits. The latter
+indicate that the page has been modified since it was loaded into memory.
+
+If nothing prevents it, eventually the physical memory can be accessed and the
+requested operation on the physical frame is performed.
+
+There are several reasons why the MMU can't find certain translations. It could
+happen because the CPU is trying to access memory that the current task is not
+permitted to, or because the data is not present into physical memory.
+
+When these conditions happen, the MMU triggers page faults, which are types of
+exceptions that signal the CPU to pause the current execution and run a special
+function to handle the mentioned exceptions.
+
+There are common and expected causes of page faults. These are triggered by
+process management optimization techniques called "Lazy Allocation" and
+"Copy-on-Write". Page faults may also happen when frames have been swapped out
+to persistent storage (swap partition or file) and evicted from their physical
+locations.
+
+These techniques improve memory efficiency, reduce latency, and minimize space
+occupation. This document won't go deeper into the details of "Lazy Allocation"
+and "Copy-on-Write" because these subjects are out of scope as they belong to
+Process Address Management.
+
+Swapping differentiates itself from the other mentioned techniques because it's
+undesirable since it's performed as a means to reduce memory under heavy
+pressure.
+
+Swapping can't work for memory mapped by kernel logical addresses. These are a
+subset of the kernel virtual space that directly maps a contiguous range of
+physical memory. Given any logical address, its physical address is determined
+with simple arithmetic on an offset. Accesses to logical addresses are fast
+because they avoid the need for complex page table lookups at the expenses of
+frames not being evictable and pageable out.
+
+If the kernel fails to make room for the data that must be present in the
+physical frames, the kernel invokes the out-of-memory (OOM) killer to make room
+by terminating lower priority processes until pressure reduces under a safe
+threshold.
+
+Additionally, page faults may be also caused by code bugs or by maliciously
+crafted addresses that the CPU is instructed to access. A thread of a process
+could use instructions to address (non-shared) memory which does not belong to
+its own address space, or could try to execute an instruction that want to write
+to a read-only location.
+
+If the above-mentioned conditions happen in user-space, the kernel sends a
+`Segmentation Fault` (SIGSEGV) signal to the current thread. That signal usually
+causes the termination of the thread and of the process it belongs to.
+
+This document is going to simplify and show an high altitude view of how the
+Linux kernel handles these page faults, creates tables and tables' entries,
+check if memory is present and, if not, requests to load data from persistent
+storage or from other devices, and updates the MMU and its caches.
+
+The first steps are architecture dependent. Most architectures jump to
+`do_page_fault()`, whereas the x86 interrupt handler is defined by the
+`DEFINE_IDTENTRY_RAW_ERRORCODE()` macro which calls `handle_page_fault()`.
+
+Whatever the routes, all architectures end up to the invocation of
+`handle_mm_fault()` which, in turn, (likely) ends up calling
+`__handle_mm_fault()` to carry out the actual work of allocating the page
+tables.
+
+The unfortunate case of not being able to call `__handle_mm_fault()` means
+that the virtual address is pointing to areas of physical memory which are not
+permitted to be accessed (at least from the current context). This
+condition resolves to the kernel sending the above-mentioned SIGSEGV signal
+to the process and leads to the consequences already explained.
+
+`__handle_mm_fault()` carries out its work by calling several functions to
+find the entry's offsets of the upper layers of the page tables and allocate
+the tables that it may need.
+
+The functions that look for the offset have names like `*_offset()`, where the
+"*" is for pgd, p4d, pud, pmd, pte; instead the functions to allocate the
+corresponding tables, layer by layer, are called `*_alloc`, using the
+above-mentioned convention to name them after the corresponding types of tables
+in the hierarchy.
+
+The page table walk may end at one of the middle or upper layers (PMD, PUD).
+
+Linux supports larger page sizes than the usual 4KB (i.e., the so called
+`huge pages`). When using these kinds of larger pages, higher level pages can
+directly map them, with no need to use lower level page entries (PTE). Huge
+pages contain large contiguous physical regions that usually span from 2MB to
+1GB. They are respectively mapped by the PMD and PUD page entries.
+
+The huge pages bring with them several benefits like reduced TLB pressure,
+reduced page table overhead, memory allocation efficiency, and performance
+improvement for certain workloads. However, these benefits come with
+trade-offs, like wasted memory and allocation challenges.
+
+At the very end of the walk with allocations, if it didn't return errors,
+`__handle_mm_fault()` finally calls `handle_pte_fault()`, which via `do_fault()`
+performs one of `do_read_fault()`, `do_cow_fault()`, `do_shared_fault()`.
+"read", "cow", "shared" give hints about the reasons and the kind of fault it's
+handling.
+
+The actual implementation of the workflow is very complex. Its design allows
+Linux to handle page faults in a way that is tailored to the specific
+characteristics of each architecture, while still sharing a common overall
+structure.
+
+To conclude this high altitude view of how Linux handles page faults, let's
+add that the page faults handler can be disabled and enabled respectively with
+`pagefault_disable()` and `pagefault_enable()`.
+
+Several code path make use of the latter two functions because they need to
+disable traps into the page faults handler, mostly to prevent deadlocks.
diff --git a/Documentation/mm/vmemmap_dedup.rst b/Documentation/mm/vmemmap_dedup.rst
index 59891f72420e..593ede6d314b 100644
--- a/Documentation/mm/vmemmap_dedup.rst
+++ b/Documentation/mm/vmemmap_dedup.rst
@@ -211,7 +211,7 @@ the device (altmap).
The following page sizes are supported in DAX: PAGE_SIZE (4K on x86_64),
PMD_SIZE (2M on x86_64) and PUD_SIZE (1G on x86_64).
-For powerpc equivalent details see Documentation/powerpc/vmemmap_dedup.rst
+For powerpc equivalent details see Documentation/arch/powerpc/vmemmap_dedup.rst
The differences with HugeTLB are relatively minor.
diff --git a/Documentation/netlink/genetlink-c.yaml b/Documentation/netlink/genetlink-c.yaml
index 9806c44f604c..c58f7153fcf8 100644
--- a/Documentation/netlink/genetlink-c.yaml
+++ b/Documentation/netlink/genetlink-c.yaml
@@ -13,6 +13,11 @@ $defs:
type: [ string, integer ]
pattern: ^[0-9A-Za-z_]+( - 1)?$
minimum: 0
+ len-or-limit:
+ # literal int or limit based on fixed-width type e.g. u8-min, u16-max, etc.
+ type: [ string, integer ]
+ pattern: ^[su](8|16|32|64)-(min|max)$
+ minimum: 0
# Schema for specs
title: Protocol
@@ -26,10 +31,6 @@ properties:
type: string
doc:
type: string
- version:
- description: Generic Netlink family version. Default is 1.
- type: integer
- minimum: 1
protocol:
description: Schema compatibility level. Default is "genetlink".
enum: [ genetlink, genetlink-c ]
@@ -46,6 +47,12 @@ properties:
max-by-define:
description: Makes the number of attributes and commands be specified by a define, not an enum value.
type: boolean
+ cmd-max-name:
+ description: Name of the define for the last operation in the list.
+ type: string
+ cmd-cnt-name:
+ description: The explicit name for constant holding the count of operations (last operation + 1).
+ type: string
# End genetlink-c
definitions:
@@ -142,13 +149,14 @@ properties:
type: array
items:
type: object
- required: [ name, type ]
+ required: [ name ]
additionalProperties: False
properties:
name:
type: string
type: &attr-type
- enum: [ unused, pad, flag, binary, u8, u16, u32, u64, s32, s64,
+ enum: [ unused, pad, flag, binary,
+ uint, sint, u8, u16, u32, u64, s32, s64,
string, nest, array-nest, nest-type-value ]
doc:
description: Documentation of the attribute.
@@ -187,13 +195,19 @@ properties:
type: string
min:
description: Min value for an integer attribute.
- type: integer
+ $ref: '#/$defs/len-or-limit'
+ max:
+ description: Max value for an integer attribute.
+ $ref: '#/$defs/len-or-limit'
min-len:
description: Min length for a binary attribute.
$ref: '#/$defs/len-or-define'
max-len:
description: Max length for a string or a binary attribute.
$ref: '#/$defs/len-or-define'
+ exact-len:
+ description: Exact length for a string or a binary attribute.
+ $ref: '#/$defs/len-or-define'
sub-type: *attr-type
display-hint: &display-hint
description: |
@@ -215,6 +229,18 @@ properties:
not:
required: [ name-prefix ]
+ # type property is only required if not in subset definition
+ if:
+ properties:
+ subset-of:
+ not:
+ type: string
+ then:
+ properties:
+ attributes:
+ items:
+ required: [ type ]
+
operations:
description: Operations supported by the protocol.
type: object
@@ -275,6 +301,11 @@ properties:
type: array
items:
enum: [ strict, dump, dump-strict ]
+ config-cond:
+ description: |
+ Name of the kernel config option gating the presence of
+ the operation, without the 'CONFIG_' prefix.
+ type: string
do: &subop-type
description: Main command handler.
type: object
diff --git a/Documentation/netlink/genetlink-legacy.yaml b/Documentation/netlink/genetlink-legacy.yaml
index 12a0a045605d..938703088306 100644
--- a/Documentation/netlink/genetlink-legacy.yaml
+++ b/Documentation/netlink/genetlink-legacy.yaml
@@ -13,6 +13,11 @@ $defs:
type: [ string, integer ]
pattern: ^[0-9A-Za-z_]+( - 1)?$
minimum: 0
+ len-or-limit:
+ # literal int or limit based on fixed-width type e.g. u8-min, u16-max, etc.
+ type: [ string, integer ]
+ pattern: ^[su](8|16|32|64)-(min|max)$
+ minimum: 0
# Schema for specs
title: Protocol
@@ -26,10 +31,6 @@ properties:
type: string
doc:
type: string
- version:
- description: Generic Netlink family version. Default is 1.
- type: integer
- minimum: 1
protocol:
description: Schema compatibility level. Default is "genetlink".
enum: [ genetlink, genetlink-c, genetlink-legacy ] # Trim
@@ -46,6 +47,12 @@ properties:
max-by-define:
description: Makes the number of attributes and commands be specified by a define, not an enum value.
type: boolean
+ cmd-max-name:
+ description: Name of the define for the last operation in the list.
+ type: string
+ cmd-cnt-name:
+ description: The explicit name for constant holding the count of operations (last operation + 1).
+ type: string
# End genetlink-c
# Start genetlink-legacy
kernel-policy:
@@ -53,6 +60,10 @@ properties:
Defines if the input policy in the kernel is global, per-operation, or split per operation type.
Default is split.
enum: [ split, per-op, global ]
+ version:
+ description: Generic Netlink family version. Default is 1.
+ type: integer
+ minimum: 1
# End genetlink-legacy
definitions:
@@ -180,14 +191,15 @@ properties:
type: array
items:
type: object
- required: [ name, type ]
+ required: [ name ]
additionalProperties: False
properties:
name:
type: string
type: &attr-type
description: The netlink attribute type
- enum: [ unused, pad, flag, binary, u8, u16, u32, u64, s32, s64,
+ enum: [ unused, pad, flag, binary, bitfield32,
+ uint, sint, u8, u16, u32, u64, s32, s64,
string, nest, array-nest, nest-type-value ]
doc:
description: Documentation of the attribute.
@@ -226,13 +238,19 @@ properties:
type: string
min:
description: Min value for an integer attribute.
- type: integer
+ $ref: '#/$defs/len-or-limit'
+ max:
+ description: Max value for an integer attribute.
+ $ref: '#/$defs/len-or-limit'
min-len:
description: Min length for a binary attribute.
$ref: '#/$defs/len-or-define'
max-len:
description: Max length for a string or a binary attribute.
$ref: '#/$defs/len-or-define'
+ exact-len:
+ description: Exact length for a string or a binary attribute.
+ $ref: '#/$defs/len-or-define'
sub-type: *attr-type
display-hint: *display-hint
# Start genetlink-c
@@ -254,6 +272,18 @@ properties:
not:
required: [ name-prefix ]
+ # type property is only required if not in subset definition
+ if:
+ properties:
+ subset-of:
+ not:
+ type: string
+ then:
+ properties:
+ attributes:
+ items:
+ required: [ type ]
+
operations:
description: Operations supported by the protocol.
type: object
@@ -316,12 +346,17 @@ properties:
description: Command flags.
type: array
items:
- enum: [ admin-perm ]
+ enum: [ admin-perm, uns-admin-perm ]
dont-validate:
description: Kernel attribute validation flags.
type: array
items:
enum: [ strict, dump, dump-strict ]
+ config-cond:
+ description: |
+ Name of the kernel config option gating the presence of
+ the operation, without the 'CONFIG_' prefix.
+ type: string
# Start genetlink-legacy
fixed-header: *fixed-header
# End genetlink-legacy
diff --git a/Documentation/netlink/genetlink.yaml b/Documentation/netlink/genetlink.yaml
index 3d338c48bf21..3283bf458ff1 100644
--- a/Documentation/netlink/genetlink.yaml
+++ b/Documentation/netlink/genetlink.yaml
@@ -13,6 +13,11 @@ $defs:
type: [ string, integer ]
pattern: ^[0-9A-Za-z_]+( - 1)?$
minimum: 0
+ len-or-limit:
+ # literal int or limit based on fixed-width type e.g. u8-min, u16-max, etc.
+ type: [ string, integer ]
+ pattern: ^[su](8|16|32|64)-(min|max)$
+ minimum: 0
# Schema for specs
title: Protocol
@@ -26,10 +31,6 @@ properties:
type: string
doc:
type: string
- version:
- description: Generic Netlink family version. Default is 1.
- type: integer
- minimum: 1
protocol:
description: Schema compatibility level. Default is "genetlink".
enum: [ genetlink ]
@@ -115,13 +116,14 @@ properties:
type: array
items:
type: object
- required: [ name, type ]
+ required: [ name ]
additionalProperties: False
properties:
name:
type: string
type: &attr-type
- enum: [ unused, pad, flag, binary, u8, u16, u32, u64, s32, s64,
+ enum: [ unused, pad, flag, binary,
+ uint, sint, u8, u16, u32, u64, s32, s64,
string, nest, array-nest, nest-type-value ]
doc:
description: Documentation of the attribute.
@@ -160,13 +162,19 @@ properties:
type: string
min:
description: Min value for an integer attribute.
- type: integer
+ $ref: '#/$defs/len-or-limit'
+ max:
+ description: Max value for an integer attribute.
+ $ref: '#/$defs/len-or-limit'
min-len:
description: Min length for a binary attribute.
$ref: '#/$defs/len-or-define'
max-len:
description: Max length for a string or a binary attribute.
$ref: '#/$defs/len-or-define'
+ exact-len:
+ description: Exact length for a string or a binary attribute.
+ $ref: '#/$defs/len-or-define'
sub-type: *attr-type
display-hint: &display-hint
description: |
@@ -184,6 +192,18 @@ properties:
not:
required: [ name-prefix ]
+ # type property is only required if not in subset definition
+ if:
+ properties:
+ subset-of:
+ not:
+ type: string
+ then:
+ properties:
+ attributes:
+ items:
+ required: [ type ]
+
operations:
description: Operations supported by the protocol.
type: object
@@ -244,6 +264,11 @@ properties:
type: array
items:
enum: [ strict, dump, dump-strict ]
+ config-cond:
+ description: |
+ Name of the kernel config option gating the presence of
+ the operation, without the 'CONFIG_' prefix.
+ type: string
do: &subop-type
description: Main command handler.
type: object
diff --git a/Documentation/netlink/netlink-raw.yaml b/Documentation/netlink/netlink-raw.yaml
index 896797876414..775cce8c548a 100644
--- a/Documentation/netlink/netlink-raw.yaml
+++ b/Documentation/netlink/netlink-raw.yaml
@@ -47,6 +47,12 @@ properties:
max-by-define:
description: Makes the number of attributes and commands be specified by a define, not an enum value.
type: boolean
+ cmd-max-name:
+ description: Name of the define for the last operation in the list.
+ type: string
+ cmd-cnt-name:
+ description: The explicit name for constant holding the count of operations (last operation + 1).
+ type: string
# End genetlink-c
# Start genetlink-legacy
kernel-policy:
@@ -187,7 +193,7 @@ properties:
type: array
items:
type: object
- required: [ name, type ]
+ required: [ name ]
additionalProperties: False
properties:
name:
@@ -240,6 +246,9 @@ properties:
max-len:
description: Max length for a string or a binary attribute.
$ref: '#/$defs/len-or-define'
+ exact-len:
+ description: Exact length for a string or a binary attribute.
+ $ref: '#/$defs/len-or-define'
sub-type: *attr-type
display-hint: *display-hint
# Start genetlink-c
@@ -261,6 +270,18 @@ properties:
not:
required: [ name-prefix ]
+ # type property is only required if not in subset definition
+ if:
+ properties:
+ subset-of:
+ not:
+ type: string
+ then:
+ properties:
+ attributes:
+ items:
+ required: [ type ]
+
operations:
description: Operations supported by the protocol.
type: object
diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml
index d1ebcd927149..572d83a414d0 100644
--- a/Documentation/netlink/specs/devlink.yaml
+++ b/Documentation/netlink/specs/devlink.yaml
@@ -15,6 +15,165 @@ definitions:
name: ingress
-
name: egress
+ -
+ type: enum
+ name: port-type
+ entries:
+ -
+ name: notset
+ -
+ name: auto
+ -
+ name: eth
+ -
+ name: ib
+ -
+ type: enum
+ name: port-flavour
+ entries:
+ -
+ name: physical
+ -
+ name: cpu
+ -
+ name: dsa
+ -
+ name: pci_pf
+ -
+ name: pci_vf
+ -
+ name: virtual
+ -
+ name: unused
+ -
+ name: pci_sf
+ -
+ type: enum
+ name: port-fn-state
+ entries:
+ -
+ name: inactive
+ -
+ name: active
+ -
+ type: enum
+ name: port-fn-opstate
+ entries:
+ -
+ name: detached
+ -
+ name: attached
+ -
+ type: enum
+ name: port-fn-attr-cap
+ entries:
+ -
+ name: roce-bit
+ -
+ name: migratable-bit
+ -
+ name: ipsec-crypto-bit
+ -
+ name: ipsec-packet-bit
+ -
+ type: enum
+ name: sb-threshold-type
+ entries:
+ -
+ name: static
+ -
+ name: dynamic
+ -
+ type: enum
+ name: eswitch-mode
+ entries:
+ -
+ name: legacy
+ -
+ name: switchdev
+ -
+ type: enum
+ name: eswitch-inline-mode
+ entries:
+ -
+ name: none
+ -
+ name: link
+ -
+ name: network
+ -
+ name: transport
+ -
+ type: enum
+ name: eswitch-encap-mode
+ entries:
+ -
+ name: none
+ -
+ name: basic
+ -
+ type: enum
+ name: dpipe-match-type
+ entries:
+ -
+ name: field-exact
+ -
+ type: enum
+ name: dpipe-action-type
+ entries:
+ -
+ name: field-modify
+ -
+ type: enum
+ name: dpipe-field-mapping-type
+ entries:
+ -
+ name: none
+ -
+ name: ifindex
+ -
+ type: enum
+ name: resource-unit
+ entries:
+ -
+ name: entry
+ -
+ type: enum
+ name: reload-action
+ entries:
+ -
+ name: driver-reinit
+ value: 1
+ -
+ name: fw-activate
+ -
+ type: enum
+ name: param-cmode
+ entries:
+ -
+ name: runtime
+ -
+ name: driverinit
+ -
+ name: permanent
+ -
+ type: enum
+ name: flash-overwrite
+ entries:
+ -
+ name: settings-bit
+ -
+ name: identifiers-bit
+ -
+ type: enum
+ name: trap-action
+ entries:
+ -
+ name: drop
+ -
+ name: trap
+ -
+ name: mirror
attribute-sets:
-
@@ -31,6 +190,17 @@ attribute-sets:
-
name: port-index
type: u32
+ -
+ name: port-type
+ type: u16
+ enum: port-type
+
+ # TODO: fill in the attributes in between
+
+ -
+ name: port-split-count
+ type: u32
+ value: 9
# TODO: fill in the attributes in between
@@ -45,18 +215,224 @@ attribute-sets:
name: sb-pool-index
type: u16
value: 17
-
-
name: sb-pool-type
type: u8
enum: sb-pool-type
+ -
+ name: sb-pool-size
+ type: u32
+ -
+ name: sb-pool-threshold-type
+ type: u8
+ enum: sb-threshold-type
+ -
+ name: sb-threshold
+ type: u32
+ -
+ name: sb-tc-index
+ type: u16
+ value: 22
# TODO: fill in the attributes in between
-
- name: sb-tc-index
+ name: eswitch-mode
type: u16
- value: 22
+ value: 25
+ enum: eswitch-mode
+
+ -
+ name: eswitch-inline-mode
+ type: u16
+ enum: eswitch-inline-mode
+ -
+ name: dpipe-tables
+ type: nest
+ nested-attributes: dl-dpipe-tables
+ -
+ name: dpipe-table
+ type: nest
+ multi-attr: true
+ nested-attributes: dl-dpipe-table
+ -
+ name: dpipe-table-name
+ type: string
+ -
+ name: dpipe-table-size
+ type: u64
+ -
+ name: dpipe-table-matches
+ type: nest
+ nested-attributes: dl-dpipe-table-matches
+ -
+ name: dpipe-table-actions
+ type: nest
+ nested-attributes: dl-dpipe-table-actions
+ -
+ name: dpipe-table-counters-enabled
+ type: u8
+ -
+ name: dpipe-entries
+ type: nest
+ nested-attributes: dl-dpipe-entries
+ -
+ name: dpipe-entry
+ type: nest
+ multi-attr: true
+ nested-attributes: dl-dpipe-entry
+ -
+ name: dpipe-entry-index
+ type: u64
+ -
+ name: dpipe-entry-match-values
+ type: nest
+ nested-attributes: dl-dpipe-entry-match-values
+ -
+ name: dpipe-entry-action-values
+ type: nest
+ nested-attributes: dl-dpipe-entry-action-values
+ -
+ name: dpipe-entry-counter
+ type: u64
+ -
+ name: dpipe-match
+ type: nest
+ multi-attr: true
+ nested-attributes: dl-dpipe-match
+ -
+ name: dpipe-match-value
+ type: nest
+ multi-attr: true
+ nested-attributes: dl-dpipe-match-value
+ -
+ name: dpipe-match-type
+ type: u32
+ enum: dpipe-match-type
+ -
+ name: dpipe-action
+ type: nest
+ multi-attr: true
+ nested-attributes: dl-dpipe-action
+ -
+ name: dpipe-action-value
+ type: nest
+ multi-attr: true
+ nested-attributes: dl-dpipe-action-value
+ -
+ name: dpipe-action-type
+ type: u32
+ enum: dpipe-action-type
+ -
+ name: dpipe-value
+ type: binary
+ -
+ name: dpipe-value-mask
+ type: binary
+ -
+ name: dpipe-value-mapping
+ type: u32
+ -
+ name: dpipe-headers
+ type: nest
+ nested-attributes: dl-dpipe-headers
+ -
+ name: dpipe-header
+ type: nest
+ multi-attr: true
+ nested-attributes: dl-dpipe-header
+ -
+ name: dpipe-header-name
+ type: string
+ -
+ name: dpipe-header-id
+ type: u32
+ -
+ name: dpipe-header-fields
+ type: nest
+ nested-attributes: dl-dpipe-header-fields
+ -
+ name: dpipe-header-global
+ type: u8
+ -
+ name: dpipe-header-index
+ type: u32
+ -
+ name: dpipe-field
+ type: nest
+ multi-attr: true
+ nested-attributes: dl-dpipe-field
+ -
+ name: dpipe-field-name
+ type: string
+ -
+ name: dpipe-field-id
+ type: u32
+ -
+ name: dpipe-field-bitwidth
+ type: u32
+ -
+ name: dpipe-field-mapping-type
+ type: u32
+ enum: dpipe-field-mapping-type
+ -
+ name: pad
+ type: pad
+ -
+ name: eswitch-encap-mode
+ type: u8
+ value: 62
+ enum: eswitch-encap-mode
+ -
+ name: resource-list
+ type: nest
+ nested-attributes: dl-resource-list
+ -
+ name: resource
+ type: nest
+ multi-attr: true
+ nested-attributes: dl-resource
+ -
+ name: resource-name
+ type: string
+ -
+ name: resource-id
+ type: u64
+ -
+ name: resource-size
+ type: u64
+ -
+ name: resource-size-new
+ type: u64
+ -
+ name: resource-size-valid
+ type: u8
+ -
+ name: resource-size-min
+ type: u64
+ -
+ name: resource-size-max
+ type: u64
+ -
+ name: resource-size-gran
+ type: u64
+ -
+ name: resource-unit
+ type: u8
+ enum: resource-unit
+ -
+ name: resource-occ
+ type: u64
+ -
+ name: dpipe-table-resource-id
+ type: u64
+ -
+ name: dpipe-table-resource-units
+ type: u64
+ -
+ name: port-flavour
+ type: u16
+ enum: port-flavour
# TODO: fill in the attributes in between
@@ -68,16 +444,40 @@ attribute-sets:
# TODO: fill in the attributes in between
-
+ name: param-type
+ type: u8
+ value: 83
+
+ # TODO: fill in the attributes in between
+
+ -
+ name: param-value-cmode
+ type: u8
+ enum: param-cmode
+ value: 87
+ -
name: region-name
type: string
- value: 88
# TODO: fill in the attributes in between
-
+ name: region-snapshot-id
+ type: u32
+ value: 92
+
+ # TODO: fill in the attributes in between
+
+ -
+ name: region-chunk-addr
+ type: u64
+ value: 96
+ -
+ name: region-chunk-len
+ type: u64
+ -
name: info-driver-name
type: string
- value: 98
-
name: info-serial-number
type: string
@@ -106,6 +506,29 @@ attribute-sets:
# TODO: fill in the attributes in between
-
+ name: fmsg
+ type: nest
+ nested-attributes: dl-fmsg
+ value: 106
+ -
+ name: fmsg-obj-nest-start
+ type: flag
+ -
+ name: fmsg-pair-nest-start
+ type: flag
+ -
+ name: fmsg-arr-nest-start
+ type: flag
+ -
+ name: fmsg-nest-end
+ type: flag
+ -
+ name: fmsg-obj-name
+ type: string
+
+ # TODO: fill in the attributes in between
+
+ -
name: health-reporter-name
type: string
value: 115
@@ -113,9 +536,36 @@ attribute-sets:
# TODO: fill in the attributes in between
-
+ name: health-reporter-graceful-period
+ type: u64
+ value: 120
+ -
+ name: health-reporter-auto-recover
+ type: u8
+ -
+ name: flash-update-file-name
+ type: string
+ -
+ name: flash-update-component
+ type: string
+
+ # TODO: fill in the attributes in between
+
+ -
+ name: port-pci-pf-number
+ type: u16
+ value: 127
+
+ # TODO: fill in the attributes in between
+
+ -
name: trap-name
type: string
value: 130
+ -
+ name: trap-action
+ type: u8
+ enum: trap-action
# TODO: fill in the attributes in between
@@ -131,23 +581,68 @@ attribute-sets:
# TODO: fill in the attributes in between
-
- name: trap-policer-id
+ name: netns-fd
+ type: u32
+ value: 138
+ -
+ name: netns-pid
+ type: u32
+ -
+ name: netns-id
type: u32
- value: 142
# TODO: fill in the attributes in between
-
- name: reload-action
+ name: health-reporter-auto-dump
type: u8
- value: 153
+ value: 141
+ -
+ name: trap-policer-id
+ type: u32
+ -
+ name: trap-policer-rate
+ type: u64
+ -
+ name: trap-policer-burst
+ type: u64
+ -
+ name: port-function
+ type: nest
+ nested-attributes: dl-port-function
# TODO: fill in the attributes in between
-
+ name: port-controller-number
+ type: u32
+ value: 150
+
+ # TODO: fill in the attributes in between
+
+ -
+ name: flash-update-overwrite-mask
+ type: bitfield32
+ enum: flash-overwrite
+ enum-as-flags: True
+ value: 152
+ -
+ name: reload-action
+ type: u8
+ enum: reload-action
+ -
+ name: reload-actions-performed
+ type: bitfield32
+ enum: reload-action
+ enum-as-flags: True
+ -
+ name: reload-limits
+ type: bitfield32
+ enum: reload-action
+ enum-as-flags: True
+ -
name: dev-stats
type: nest
- value: 156
nested-attributes: dl-dev-stats
-
name: reload-stats
@@ -182,9 +677,25 @@ attribute-sets:
# TODO: fill in the attributes in between
-
+ name: port-pci-sf-number
+ type: u32
+ value: 164
+
+ # TODO: fill in the attributes in between
+
+ -
+ name: rate-tx-share
+ type: u64
+ value: 166
+ -
+ name: rate-tx-max
+ type: u64
+ -
name: rate-node-name
type: string
- value: 168
+ -
+ name: rate-parent-node-name
+ type: string
# TODO: fill in the attributes in between
@@ -193,60 +704,329 @@ attribute-sets:
type: u32
value: 171
+ # TODO: fill in the attributes in between
+
+ -
+ name: linecard-type
+ type: string
+ value: 173
+
+ # TODO: fill in the attributes in between
+
+ -
+ name: selftests
+ type: nest
+ value: 176
+ nested-attributes: dl-selftest-id
+ -
+ name: rate-tx-priority
+ type: u32
+ -
+ name: rate-tx-weight
+ type: u32
+ -
+ name: region-direct
+ type: flag
+
-
name: dl-dev-stats
subset-of: devlink
attributes:
-
name: reload-stats
- type: nest
-
name: remote-reload-stats
- type: nest
-
name: dl-reload-stats
subset-of: devlink
attributes:
-
name: reload-action-info
- type: nest
-
name: dl-reload-act-info
subset-of: devlink
attributes:
-
name: reload-action
- type: u8
-
name: reload-action-stats
- type: nest
-
name: dl-reload-act-stats
subset-of: devlink
attributes:
-
name: reload-stats-entry
- type: nest
-
name: dl-reload-stats-entry
subset-of: devlink
attributes:
-
name: reload-stats-limit
- type: u8
-
name: reload-stats-value
- type: u32
-
name: dl-info-version
subset-of: devlink
attributes:
-
name: info-version-name
- type: string
-
name: info-version-value
- type: string
+ -
+ name: dl-port-function
+ name-prefix: devlink-port-fn-attr-
+ attr-max-name: devlink-port-function-attr-max
+ attributes:
+ -
+ name-prefix: devlink-port-function-attr-
+ name: hw-addr
+ type: binary
+ value: 1
+ -
+ name: state
+ type: u8
+ enum: port-fn-state
+ -
+ name: opstate
+ type: u8
+ enum: port-fn-opstate
+ -
+ name: caps
+ type: bitfield32
+ enum: port-fn-attr-cap
+ enum-as-flags: True
+
+ -
+ name: dl-dpipe-tables
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-table
+
+ -
+ name: dl-dpipe-table
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-table-name
+ -
+ name: dpipe-table-size
+ -
+ name: dpipe-table-name
+ -
+ name: dpipe-table-size
+ -
+ name: dpipe-table-matches
+ -
+ name: dpipe-table-actions
+ -
+ name: dpipe-table-counters-enabled
+ -
+ name: dpipe-table-resource-id
+ -
+ name: dpipe-table-resource-units
+
+ -
+ name: dl-dpipe-table-matches
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-match
+
+ -
+ name: dl-dpipe-table-actions
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-action
+
+ -
+ name: dl-dpipe-entries
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-entry
+
+ -
+ name: dl-dpipe-entry
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-entry-index
+ -
+ name: dpipe-entry-match-values
+ -
+ name: dpipe-entry-action-values
+ -
+ name: dpipe-entry-counter
+
+ -
+ name: dl-dpipe-entry-match-values
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-match-value
+
+ -
+ name: dl-dpipe-entry-action-values
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-action-value
+
+ -
+ name: dl-dpipe-match
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-match-type
+ -
+ name: dpipe-header-id
+ -
+ name: dpipe-header-global
+ -
+ name: dpipe-header-index
+ -
+ name: dpipe-field-id
+
+ -
+ name: dl-dpipe-match-value
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-match
+ -
+ name: dpipe-value
+ -
+ name: dpipe-value-mask
+ -
+ name: dpipe-value-mapping
+
+ -
+ name: dl-dpipe-action
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-action-type
+ -
+ name: dpipe-header-id
+ -
+ name: dpipe-header-global
+ -
+ name: dpipe-header-index
+ -
+ name: dpipe-field-id
+
+ -
+ name: dl-dpipe-action-value
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-action
+ -
+ name: dpipe-value
+ -
+ name: dpipe-value-mask
+ -
+ name: dpipe-value-mapping
+
+ -
+ name: dl-dpipe-headers
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-header
+
+ -
+ name: dl-dpipe-header
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-header-name
+ -
+ name: dpipe-header-id
+ -
+ name: dpipe-header-global
+ -
+ name: dpipe-header-fields
+
+ -
+ name: dl-dpipe-header-fields
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-field
+
+ -
+ name: dl-dpipe-field
+ subset-of: devlink
+ attributes:
+ -
+ name: dpipe-field-name
+ -
+ name: dpipe-field-id
+ -
+ name: dpipe-field-bitwidth
+ -
+ name: dpipe-field-mapping-type
+
+ -
+ name: dl-resource
+ subset-of: devlink
+ attributes:
+ # -
+ # name: resource-list
+ # This is currently unsupported due to circular dependency
+ -
+ name: resource-name
+ -
+ name: resource-id
+ -
+ name: resource-size
+ -
+ name: resource-size-new
+ -
+ name: resource-size-valid
+ -
+ name: resource-size-min
+ -
+ name: resource-size-max
+ -
+ name: resource-size-gran
+ -
+ name: resource-unit
+ -
+ name: resource-occ
+
+ -
+ name: dl-resource-list
+ subset-of: devlink
+ attributes:
+ -
+ name: resource
+
+ -
+ name: dl-fmsg
+ subset-of: devlink
+ attributes:
+ -
+ name: fmsg-obj-nest-start
+ -
+ name: fmsg-pair-nest-start
+ -
+ name: fmsg-arr-nest-start
+ -
+ name: fmsg-nest-end
+ -
+ name: fmsg-obj-name
+
+ -
+ name: dl-selftest-id
+ name-prefix: devlink-attr-selftest-id-
+ attributes:
+ -
+ name: flash
+ type: flag
operations:
enum-model: directional
@@ -255,10 +1035,7 @@ operations:
name: get
doc: Get devlink instances.
attribute-set: devlink
- dont-validate:
- - strict
- - dump
-
+ dont-validate: [ strict, dump ]
do:
pre: devlink-nl-pre-doit
post: devlink-nl-post-doit
@@ -273,7 +1050,6 @@ operations:
- bus-name
- dev-name
- reload-failed
- - reload-action
- dev-stats
dump:
reply: *get-reply
@@ -282,9 +1058,7 @@ operations:
name: port-get
doc: Get devlink port instances.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit-port
post: devlink-nl-post-doit
@@ -303,16 +1077,90 @@ operations:
reply:
value: 3 # due to a bug, port dump returns DEVLINK_CMD_NEW
attributes: *port-id-attrs
+ -
+ name: port-set
+ doc: Set devlink port instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - port-index
+ - port-type
+ - port-function
+
+ -
+ name: port-new
+ doc: Create devlink port instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - port-index
+ - port-flavour
+ - port-pci-pf-number
+ - port-pci-sf-number
+ - port-controller-number
+ reply:
+ value: 7
+ attributes: *port-id-attrs
- # TODO: fill in the operations in between
+ -
+ name: port-del
+ doc: Delete devlink port instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port
+ post: devlink-nl-post-doit
+ request:
+ attributes: *port-id-attrs
+
+ -
+ name: port-split
+ doc: Split devlink port instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - port-index
+ - port-split-count
+
+ -
+ name: port-unsplit
+ doc: Unplit devlink port instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port
+ post: devlink-nl-post-doit
+ request:
+ attributes: *port-id-attrs
-
name: sb-get
doc: Get shared buffer instances.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit
post: devlink-nl-post-doit
@@ -323,22 +1171,18 @@ operations:
- dev-name
- sb-index
reply: &sb-get-reply
- value: 11
+ value: 13
attributes: *sb-id-attrs
dump:
request:
attributes: *dev-id-attrs
reply: *sb-get-reply
- # TODO: fill in the operations in between
-
-
name: sb-pool-get
doc: Get shared buffer pool instances.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit
post: devlink-nl-post-doit
@@ -350,22 +1194,36 @@ operations:
- sb-index
- sb-pool-index
reply: &sb-pool-get-reply
- value: 15
+ value: 17
attributes: *sb-pool-id-attrs
dump:
request:
attributes: *dev-id-attrs
reply: *sb-pool-get-reply
- # TODO: fill in the operations in between
+ -
+ name: sb-pool-set
+ doc: Set shared buffer pool instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - sb-index
+ - sb-pool-index
+ - sb-pool-threshold-type
+ - sb-pool-size
-
name: sb-port-pool-get
doc: Get shared buffer port-pool combinations and threshold.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit-port
post: devlink-nl-post-doit
@@ -378,22 +1236,36 @@ operations:
- sb-index
- sb-pool-index
reply: &sb-port-pool-get-reply
- value: 19
+ value: 21
attributes: *sb-port-pool-id-attrs
dump:
request:
attributes: *dev-id-attrs
reply: *sb-port-pool-get-reply
- # TODO: fill in the operations in between
+ -
+ name: sb-port-pool-set
+ doc: Set shared buffer port-pool combinations and threshold.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - port-index
+ - sb-index
+ - sb-pool-index
+ - sb-threshold
-
name: sb-tc-pool-bind-get
doc: Get shared buffer port-TC to pool bindings and threshold.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit-port
post: devlink-nl-post-doit
@@ -407,48 +1279,271 @@ operations:
- sb-pool-type
- sb-tc-index
reply: &sb-tc-pool-bind-get-reply
- value: 23
+ value: 25
attributes: *sb-tc-pool-bind-id-attrs
dump:
request:
attributes: *dev-id-attrs
reply: *sb-tc-pool-bind-get-reply
- # TODO: fill in the operations in between
+ -
+ name: sb-tc-pool-bind-set
+ doc: Set shared buffer port-TC to pool bindings and threshold.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - port-index
+ - sb-index
+ - sb-pool-index
+ - sb-pool-type
+ - sb-tc-index
+ - sb-threshold
+
+ -
+ name: sb-occ-snapshot
+ doc: Take occupancy snapshot of shared buffer.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ value: 27
+ attributes:
+ - bus-name
+ - dev-name
+ - sb-index
+
+ -
+ name: sb-occ-max-clear
+ doc: Clear occupancy watermarks of shared buffer.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - sb-index
+
+ -
+ name: eswitch-get
+ doc: Get eswitch attributes.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes: *dev-id-attrs
+ reply:
+ value: 29
+ attributes: &eswitch-attrs
+ - bus-name
+ - dev-name
+ - eswitch-mode
+ - eswitch-inline-mode
+ - eswitch-encap-mode
+
+ -
+ name: eswitch-set
+ doc: Set eswitch attributes.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes: *eswitch-attrs
+
+ -
+ name: dpipe-table-get
+ doc: Get dpipe table attributes.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - dpipe-table-name
+ reply:
+ value: 31
+ attributes:
+ - bus-name
+ - dev-name
+ - dpipe-tables
+
+ -
+ name: dpipe-entries-get
+ doc: Get dpipe entries attributes.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - dpipe-table-name
+ reply:
+ attributes:
+ - bus-name
+ - dev-name
+ - dpipe-entries
+
+ -
+ name: dpipe-headers-get
+ doc: Get dpipe headers attributes.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ reply:
+ attributes:
+ - bus-name
+ - dev-name
+ - dpipe-headers
+
+ -
+ name: dpipe-table-counters-set
+ doc: Set dpipe counter attributes.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - dpipe-table-name
+ - dpipe-table-counters-enabled
+
+ -
+ name: resource-set
+ doc: Set resource attributes.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - resource-id
+ - resource-size
+
+ -
+ name: resource-dump
+ doc: Get resource attributes.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ reply:
+ value: 36
+ attributes:
+ - bus-name
+ - dev-name
+ - resource-list
+
+ -
+ name: reload
+ doc: Reload devlink.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - reload-action
+ - reload-limits
+ - netns-pid
+ - netns-fd
+ - netns-id
+ reply:
+ attributes:
+ - bus-name
+ - dev-name
+ - reload-actions-performed
-
name: param-get
doc: Get param instances.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit
post: devlink-nl-post-doit
request:
- value: 38
attributes: &param-id-attrs
- bus-name
- dev-name
- param-name
reply: &param-get-reply
- value: 38
attributes: *param-id-attrs
dump:
request:
attributes: *dev-id-attrs
reply: *param-get-reply
- # TODO: fill in the operations in between
+ -
+ name: param-set
+ doc: Set param instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - param-name
+ - param-type
+ # param-value-data is missing here as the type is variable
+ - param-value-cmode
-
name: region-get
doc: Get region instances.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit-port-optional
post: devlink-nl-post-doit
@@ -467,16 +1562,97 @@ operations:
attributes: *dev-id-attrs
reply: *region-get-reply
- # TODO: fill in the operations in between
+ -
+ name: region-new
+ doc: Create region snapshot.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port-optional
+ post: devlink-nl-post-doit
+ request:
+ value: 44
+ attributes: &region-snapshot-id-attrs
+ - bus-name
+ - dev-name
+ - port-index
+ - region-name
+ - region-snapshot-id
+ reply:
+ value: 44
+ attributes: *region-snapshot-id-attrs
+
+ -
+ name: region-del
+ doc: Delete region snapshot.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port-optional
+ post: devlink-nl-post-doit
+ request:
+ attributes: *region-snapshot-id-attrs
+
+ -
+ name: region-read
+ doc: Read region data.
+ attribute-set: devlink
+ dont-validate: [ dump-strict ]
+ flags: [ admin-perm ]
+ dump:
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - port-index
+ - region-name
+ - region-snapshot-id
+ - region-direct
+ - region-chunk-addr
+ - region-chunk-len
+ reply:
+ value: 46
+ attributes:
+ - bus-name
+ - dev-name
+ - port-index
+ - region-name
+
+ -
+ name: port-param-get
+ doc: Get port param instances.
+ attribute-set: devlink
+ dont-validate: [ strict, dump-strict ]
+ do:
+ pre: devlink-nl-pre-doit-port
+ post: devlink-nl-post-doit
+ request:
+ attributes: *port-id-attrs
+ reply:
+ attributes: *port-id-attrs
+ dump:
+ reply:
+ attributes: *port-id-attrs
+
+ -
+ name: port-param-set
+ doc: Set port param instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port
+ post: devlink-nl-post-doit
+ request:
+ attributes: *port-id-attrs
-
name: info-get
doc: Get device information, like driver name, hardware and firmware versions etc.
attribute-set: devlink
- dont-validate:
- - strict
- - dump
-
+ dont-validate: [ strict, dump ]
do:
pre: devlink-nl-pre-doit
post: devlink-nl-post-doit
@@ -500,9 +1676,7 @@ operations:
name: health-reporter-get
doc: Get health reporter instances.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit-port-optional
post: devlink-nl-post-doit
@@ -519,15 +1693,97 @@ operations:
attributes: *port-id-attrs
reply: *health-reporter-get-reply
- # TODO: fill in the operations in between
+ -
+ name: health-reporter-set
+ doc: Set health reporter instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port-optional
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - port-index
+ - health-reporter-name
+ - health-reporter-graceful-period
+ - health-reporter-auto-recover
+ - health-reporter-auto-dump
+
+ -
+ name: health-reporter-recover
+ doc: Recover health reporter instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port-optional
+ post: devlink-nl-post-doit
+ request:
+ attributes: *health-reporter-id-attrs
+
+ -
+ name: health-reporter-diagnose
+ doc: Diagnose health reporter instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port-optional
+ post: devlink-nl-post-doit
+ request:
+ attributes: *health-reporter-id-attrs
+
+ -
+ name: health-reporter-dump-get
+ doc: Dump health reporter instances.
+ attribute-set: devlink
+ dont-validate: [ dump-strict ]
+ flags: [ admin-perm ]
+ dump:
+ request:
+ attributes: *health-reporter-id-attrs
+ reply:
+ value: 56
+ attributes:
+ - fmsg
+
+ -
+ name: health-reporter-dump-clear
+ doc: Clear dump of health reporter instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port-optional
+ post: devlink-nl-post-doit
+ request:
+ attributes: *health-reporter-id-attrs
+
+ -
+ name: flash-update
+ doc: Flash update devlink instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - flash-update-file-name
+ - flash-update-component
+ - flash-update-overwrite-mask
-
name: trap-get
doc: Get trap instances.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit
post: devlink-nl-post-doit
@@ -538,22 +1794,34 @@ operations:
- dev-name
- trap-name
reply: &trap-get-reply
- value: 61
+ value: 63
attributes: *trap-id-attrs
dump:
request:
attributes: *dev-id-attrs
reply: *trap-get-reply
- # TODO: fill in the operations in between
+ -
+ name: trap-set
+ doc: Set trap instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - trap-name
+ - trap-action
-
name: trap-group-get
doc: Get trap group instances.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit
post: devlink-nl-post-doit
@@ -564,22 +1832,35 @@ operations:
- dev-name
- trap-group-name
reply: &trap-group-get-reply
- value: 65
+ value: 67
attributes: *trap-group-id-attrs
dump:
request:
attributes: *dev-id-attrs
reply: *trap-group-get-reply
- # TODO: fill in the operations in between
+ -
+ name: trap-group-set
+ doc: Set trap group instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - trap-group-name
+ - trap-action
+ - trap-policer-id
-
name: trap-policer-get
doc: Get trap policer instances.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit
post: devlink-nl-post-doit
@@ -590,22 +1871,48 @@ operations:
- dev-name
- trap-policer-id
reply: &trap-policer-get-reply
- value: 69
+ value: 71
attributes: *trap-policer-id-attrs
dump:
request:
attributes: *dev-id-attrs
reply: *trap-policer-get-reply
- # TODO: fill in the operations in between
+ -
+ name: trap-policer-set
+ doc: Get trap policer instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - trap-policer-id
+ - trap-policer-rate
+ - trap-policer-burst
+
+ -
+ name: health-reporter-test
+ doc: Test health reporter instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit-port-optional
+ post: devlink-nl-post-doit
+ request:
+ value: 73
+ attributes: *health-reporter-id-attrs
-
name: rate-get
doc: Get rate instances.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit
post: devlink-nl-post-doit
@@ -617,22 +1924,73 @@ operations:
- port-index
- rate-node-name
reply: &rate-get-reply
- value: 74
+ value: 76
attributes: *rate-id-attrs
dump:
request:
attributes: *dev-id-attrs
reply: *rate-get-reply
- # TODO: fill in the operations in between
+ -
+ name: rate-set
+ doc: Set rate instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - rate-node-name
+ - rate-tx-share
+ - rate-tx-max
+ - rate-tx-priority
+ - rate-tx-weight
+ - rate-parent-node-name
+
+ -
+ name: rate-new
+ doc: Create rate instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - rate-node-name
+ - rate-tx-share
+ - rate-tx-max
+ - rate-tx-priority
+ - rate-tx-weight
+ - rate-parent-node-name
+
+ -
+ name: rate-del
+ doc: Delete rate instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - rate-node-name
-
name: linecard-get
doc: Get line card instances.
attribute-set: devlink
- dont-validate:
- - strict
-
+ dont-validate: [ strict ]
do:
pre: devlink-nl-pre-doit
post: devlink-nl-post-doit
@@ -643,23 +2001,34 @@ operations:
- dev-name
- linecard-index
reply: &linecard-get-reply
- value: 78
+ value: 80
attributes: *linecard-id-attrs
dump:
request:
attributes: *dev-id-attrs
reply: *linecard-get-reply
- # TODO: fill in the operations in between
+ -
+ name: linecard-set
+ doc: Set line card instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - linecard-index
+ - linecard-type
-
name: selftests-get
doc: Get device selftest instances.
attribute-set: devlink
- dont-validate:
- - strict
- - dump
-
+ dont-validate: [ strict, dump ]
do:
pre: devlink-nl-pre-doit
post: devlink-nl-post-doit
@@ -671,3 +2040,18 @@ operations:
attributes: *dev-id-attrs
dump:
reply: *selftests-get-reply
+
+ -
+ name: selftests-run
+ doc: Run device selftest instances.
+ attribute-set: devlink
+ dont-validate: [ strict ]
+ flags: [ admin-perm ]
+ do:
+ pre: devlink-nl-pre-doit
+ post: devlink-nl-post-doit
+ request:
+ attributes:
+ - bus-name
+ - dev-name
+ - selftests
diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml
new file mode 100644
index 000000000000..cf8abe1c0550
--- /dev/null
+++ b/Documentation/netlink/specs/dpll.yaml
@@ -0,0 +1,510 @@
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+
+name: dpll
+
+doc: DPLL subsystem.
+
+definitions:
+ -
+ type: enum
+ name: mode
+ doc: |
+ working modes a dpll can support, differentiates if and how dpll selects
+ one of its inputs to syntonize with it, valid values for DPLL_A_MODE
+ attribute
+ entries:
+ -
+ name: manual
+ doc: input can be only selected by sending a request to dpll
+ value: 1
+ -
+ name: automatic
+ doc: highest prio input pin auto selected by dpll
+ render-max: true
+ -
+ type: enum
+ name: lock-status
+ doc: |
+ provides information of dpll device lock status, valid values for
+ DPLL_A_LOCK_STATUS attribute
+ entries:
+ -
+ name: unlocked
+ doc: |
+ dpll was not yet locked to any valid input (or forced by setting
+ DPLL_A_MODE to DPLL_MODE_DETACHED)
+ value: 1
+ -
+ name: locked
+ doc: |
+ dpll is locked to a valid signal, but no holdover available
+ -
+ name: locked-ho-acq
+ doc: |
+ dpll is locked and holdover acquired
+ -
+ name: holdover
+ doc: |
+ dpll is in holdover state - lost a valid lock or was forced
+ by disconnecting all the pins (latter possible only
+ when dpll lock-state was already DPLL_LOCK_STATUS_LOCKED_HO_ACQ,
+ if dpll lock-state was not DPLL_LOCK_STATUS_LOCKED_HO_ACQ, the
+ dpll's lock-state shall remain DPLL_LOCK_STATUS_UNLOCKED)
+ render-max: true
+ -
+ type: const
+ name: temp-divider
+ value: 1000
+ doc: |
+ temperature divider allowing userspace to calculate the
+ temperature as float with three digit decimal precision.
+ Value of (DPLL_A_TEMP / DPLL_TEMP_DIVIDER) is integer part of
+ temperature value.
+ Value of (DPLL_A_TEMP % DPLL_TEMP_DIVIDER) is fractional part of
+ temperature value.
+ -
+ type: enum
+ name: type
+ doc: type of dpll, valid values for DPLL_A_TYPE attribute
+ entries:
+ -
+ name: pps
+ doc: dpll produces Pulse-Per-Second signal
+ value: 1
+ -
+ name: eec
+ doc: dpll drives the Ethernet Equipment Clock
+ render-max: true
+ -
+ type: enum
+ name: pin-type
+ doc: |
+ defines possible types of a pin, valid values for DPLL_A_PIN_TYPE
+ attribute
+ entries:
+ -
+ name: mux
+ doc: aggregates another layer of selectable pins
+ value: 1
+ -
+ name: ext
+ doc: external input
+ -
+ name: synce-eth-port
+ doc: ethernet port PHY's recovered clock
+ -
+ name: int-oscillator
+ doc: device internal oscillator
+ -
+ name: gnss
+ doc: GNSS recovered clock
+ render-max: true
+ -
+ type: enum
+ name: pin-direction
+ doc: |
+ defines possible direction of a pin, valid values for
+ DPLL_A_PIN_DIRECTION attribute
+ entries:
+ -
+ name: input
+ doc: pin used as a input of a signal
+ value: 1
+ -
+ name: output
+ doc: pin used to output the signal
+ render-max: true
+ -
+ type: const
+ name: pin-frequency-1-hz
+ value: 1
+ -
+ type: const
+ name: pin-frequency-10-khz
+ value: 10000
+ -
+ type: const
+ name: pin-frequency-77_5-khz
+ value: 77500
+ -
+ type: const
+ name: pin-frequency-10-mhz
+ value: 10000000
+ -
+ type: enum
+ name: pin-state
+ doc: |
+ defines possible states of a pin, valid values for
+ DPLL_A_PIN_STATE attribute
+ entries:
+ -
+ name: connected
+ doc: pin connected, active input of phase locked loop
+ value: 1
+ -
+ name: disconnected
+ doc: pin disconnected, not considered as a valid input
+ -
+ name: selectable
+ doc: pin enabled for automatic input selection
+ render-max: true
+ -
+ type: flags
+ name: pin-capabilities
+ doc: |
+ defines possible capabilities of a pin, valid flags on
+ DPLL_A_PIN_CAPABILITIES attribute
+ entries:
+ -
+ name: direction-can-change
+ doc: pin direction can be changed
+ -
+ name: priority-can-change
+ doc: pin priority can be changed
+ -
+ name: state-can-change
+ doc: pin state can be changed
+ -
+ type: const
+ name: phase-offset-divider
+ value: 1000
+ doc: |
+ phase offset divider allows userspace to calculate a value of
+ measured signal phase difference between a pin and dpll device
+ as a fractional value with three digit decimal precision.
+ Value of (DPLL_A_PHASE_OFFSET / DPLL_PHASE_OFFSET_DIVIDER) is an
+ integer part of a measured phase offset value.
+ Value of (DPLL_A_PHASE_OFFSET % DPLL_PHASE_OFFSET_DIVIDER) is a
+ fractional part of a measured phase offset value.
+
+attribute-sets:
+ -
+ name: dpll
+ enum-name: dpll_a
+ attributes:
+ -
+ name: id
+ type: u32
+ -
+ name: module-name
+ type: string
+ -
+ name: pad
+ type: pad
+ -
+ name: clock-id
+ type: u64
+ -
+ name: mode
+ type: u32
+ enum: mode
+ -
+ name: mode-supported
+ type: u32
+ enum: mode
+ multi-attr: true
+ -
+ name: lock-status
+ type: u32
+ enum: lock-status
+ -
+ name: temp
+ type: s32
+ -
+ name: type
+ type: u32
+ enum: type
+ -
+ name: pin
+ enum-name: dpll_a_pin
+ attributes:
+ -
+ name: id
+ type: u32
+ -
+ name: parent-id
+ type: u32
+ -
+ name: module-name
+ type: string
+ -
+ name: pad
+ type: pad
+ -
+ name: clock-id
+ type: u64
+ -
+ name: board-label
+ type: string
+ -
+ name: panel-label
+ type: string
+ -
+ name: package-label
+ type: string
+ -
+ name: type
+ type: u32
+ enum: pin-type
+ -
+ name: direction
+ type: u32
+ enum: pin-direction
+ -
+ name: frequency
+ type: u64
+ -
+ name: frequency-supported
+ type: nest
+ multi-attr: true
+ nested-attributes: frequency-range
+ -
+ name: frequency-min
+ type: u64
+ -
+ name: frequency-max
+ type: u64
+ -
+ name: prio
+ type: u32
+ -
+ name: state
+ type: u32
+ enum: pin-state
+ -
+ name: capabilities
+ type: u32
+ -
+ name: parent-device
+ type: nest
+ multi-attr: true
+ nested-attributes: pin-parent-device
+ -
+ name: parent-pin
+ type: nest
+ multi-attr: true
+ nested-attributes: pin-parent-pin
+ -
+ name: phase-adjust-min
+ type: s32
+ -
+ name: phase-adjust-max
+ type: s32
+ -
+ name: phase-adjust
+ type: s32
+ -
+ name: phase-offset
+ type: s64
+ -
+ name: pin-parent-device
+ subset-of: pin
+ attributes:
+ -
+ name: parent-id
+ -
+ name: direction
+ -
+ name: prio
+ -
+ name: state
+ -
+ name: phase-offset
+ -
+ name: pin-parent-pin
+ subset-of: pin
+ attributes:
+ -
+ name: parent-id
+ -
+ name: state
+ -
+ name: frequency-range
+ subset-of: pin
+ attributes:
+ -
+ name: frequency-min
+ -
+ name: frequency-max
+
+operations:
+ enum-name: dpll_cmd
+ list:
+ -
+ name: device-id-get
+ doc: |
+ Get id of dpll device that matches given attributes
+ attribute-set: dpll
+ flags: [ admin-perm ]
+
+ do:
+ pre: dpll-lock-doit
+ post: dpll-unlock-doit
+ request:
+ attributes:
+ - module-name
+ - clock-id
+ - type
+ reply:
+ attributes:
+ - id
+
+ -
+ name: device-get
+ doc: |
+ Get list of DPLL devices (dump) or attributes of a single dpll device
+ attribute-set: dpll
+ flags: [ admin-perm ]
+
+ do:
+ pre: dpll-pre-doit
+ post: dpll-post-doit
+ request:
+ attributes:
+ - id
+ reply: &dev-attrs
+ attributes:
+ - id
+ - module-name
+ - mode
+ - mode-supported
+ - lock-status
+ - temp
+ - clock-id
+ - type
+
+ dump:
+ pre: dpll-lock-dumpit
+ post: dpll-unlock-dumpit
+ reply: *dev-attrs
+
+ -
+ name: device-set
+ doc: Set attributes for a DPLL device
+ attribute-set: dpll
+ flags: [ admin-perm ]
+
+ do:
+ pre: dpll-pre-doit
+ post: dpll-post-doit
+ request:
+ attributes:
+ - id
+ -
+ name: device-create-ntf
+ doc: Notification about device appearing
+ notify: device-get
+ mcgrp: monitor
+ -
+ name: device-delete-ntf
+ doc: Notification about device disappearing
+ notify: device-get
+ mcgrp: monitor
+ -
+ name: device-change-ntf
+ doc: Notification about device configuration being changed
+ notify: device-get
+ mcgrp: monitor
+ -
+ name: pin-id-get
+ doc: |
+ Get id of a pin that matches given attributes
+ attribute-set: pin
+ flags: [ admin-perm ]
+
+ do:
+ pre: dpll-lock-doit
+ post: dpll-unlock-doit
+ request:
+ attributes:
+ - module-name
+ - clock-id
+ - board-label
+ - panel-label
+ - package-label
+ - type
+ reply:
+ attributes:
+ - id
+
+ -
+ name: pin-get
+ doc: |
+ Get list of pins and its attributes.
+ - dump request without any attributes given - list all the pins in the
+ system
+ - dump request with target dpll - list all the pins registered with
+ a given dpll device
+ - do request with target dpll and target pin - single pin attributes
+ attribute-set: pin
+ flags: [ admin-perm ]
+
+ do:
+ pre: dpll-pin-pre-doit
+ post: dpll-pin-post-doit
+ request:
+ attributes:
+ - id
+ reply: &pin-attrs
+ attributes:
+ - id
+ - board-label
+ - panel-label
+ - package-label
+ - type
+ - frequency
+ - frequency-supported
+ - capabilities
+ - parent-device
+ - parent-pin
+ - phase-adjust-min
+ - phase-adjust-max
+ - phase-adjust
+
+ dump:
+ pre: dpll-lock-dumpit
+ post: dpll-unlock-dumpit
+ request:
+ attributes:
+ - id
+ reply: *pin-attrs
+
+ -
+ name: pin-set
+ doc: Set attributes of a target pin
+ attribute-set: pin
+ flags: [ admin-perm ]
+
+ do:
+ pre: dpll-pin-pre-doit
+ post: dpll-pin-post-doit
+ request:
+ attributes:
+ - id
+ - frequency
+ - direction
+ - prio
+ - state
+ - parent-device
+ - parent-pin
+ - phase-adjust
+ -
+ name: pin-create-ntf
+ doc: Notification about pin appearing
+ notify: pin-get
+ mcgrp: monitor
+ -
+ name: pin-delete-ntf
+ doc: Notification about pin disappearing
+ notify: pin-get
+ mcgrp: monitor
+ -
+ name: pin-change-ntf
+ doc: Notification about pin configuration being changed
+ notify: pin-get
+ mcgrp: monitor
+
+mcast-groups:
+ list:
+ -
+ name: monitor
diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml
index 837b565577ca..5c7a65b009b4 100644
--- a/Documentation/netlink/specs/ethtool.yaml
+++ b/Documentation/netlink/specs/ethtool.yaml
@@ -818,13 +818,10 @@ attribute-sets:
attributes:
-
name: hist-bkt-low
- type: u32
-
name: hist-bkt-hi
- type: u32
-
name: hist-val
- type: u64
-
name: stats
attributes:
diff --git a/Documentation/netlink/specs/handshake.yaml b/Documentation/netlink/specs/handshake.yaml
index 6d89e30f5fd5..b934cc513e3d 100644
--- a/Documentation/netlink/specs/handshake.yaml
+++ b/Documentation/netlink/specs/handshake.yaml
@@ -34,16 +34,16 @@ attribute-sets:
attributes:
-
name: cert
- type: u32
+ type: s32
-
name: privkey
- type: u32
+ type: s32
-
name: accept
attributes:
-
name: sockfd
- type: u32
+ type: s32
-
name: handler-class
type: u32
@@ -79,7 +79,7 @@ attribute-sets:
type: u32
-
name: sockfd
- type: u32
+ type: s32
-
name: remote-auth
type: u32
diff --git a/Documentation/netlink/specs/mptcp.yaml b/Documentation/netlink/specs/mptcp.yaml
new file mode 100644
index 000000000000..49f90cfb4698
--- /dev/null
+++ b/Documentation/netlink/specs/mptcp.yaml
@@ -0,0 +1,393 @@
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+
+name: mptcp_pm
+protocol: genetlink-legacy
+doc: Multipath TCP.
+
+c-family-name: mptcp-pm-name
+c-version-name: mptcp-pm-ver
+max-by-define: true
+kernel-policy: per-op
+cmd-cnt-name: --mptcp-pm-cmd-after-last
+
+definitions:
+ -
+ type: enum
+ name: event-type
+ enum-name: mptcp-event-type
+ name-prefix: mptcp-event-
+ entries:
+ -
+ name: unspec
+ doc: unused event
+ -
+ name: created
+ doc:
+ token, family, saddr4 | saddr6, daddr4 | daddr6, sport, dport
+ A new MPTCP connection has been created. It is the good time to
+ allocate memory and send ADD_ADDR if needed. Depending on the
+ traffic-patterns it can take a long time until the
+ MPTCP_EVENT_ESTABLISHED is sent.
+ -
+ name: established
+ doc:
+ token, family, saddr4 | saddr6, daddr4 | daddr6, sport, dport
+ A MPTCP connection is established (can start new subflows).
+ -
+ name: closed
+ doc:
+ token
+ A MPTCP connection has stopped.
+ -
+ name: announced
+ value: 6
+ doc:
+ token, rem_id, family, daddr4 | daddr6 [, dport]
+ A new address has been announced by the peer.
+ -
+ name: removed
+ doc:
+ token, rem_id
+ An address has been lost by the peer.
+ -
+ name: sub-established
+ value: 10
+ doc:
+ token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 | daddr6, sport,
+ dport, backup, if_idx [, error]
+ A new subflow has been established. 'error' should not be set.
+ -
+ name: sub-closed
+ doc:
+ token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 | daddr6, sport,
+ dport, backup, if_idx [, error]
+ A subflow has been closed. An error (copy of sk_err) could be set if an
+ error has been detected for this subflow.
+ -
+ name: sub-priority
+ value: 13
+ doc:
+ token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 | daddr6, sport,
+ dport, backup, if_idx [, error]
+ The priority of a subflow has changed. 'error' should not be set.
+ -
+ name: listener-created
+ value: 15
+ doc:
+ family, sport, saddr4 | saddr6
+ A new PM listener is created.
+ -
+ name: listener-closed
+ doc:
+ family, sport, saddr4 | saddr6
+ A PM listener is closed.
+
+attribute-sets:
+ -
+ name: address
+ name-prefix: mptcp-pm-addr-attr-
+ attributes:
+ -
+ name: unspec
+ type: unused
+ value: 0
+ -
+ name: family
+ type: u16
+ -
+ name: id
+ type: u8
+ -
+ name: addr4
+ type: u32
+ byte-order: big-endian
+ -
+ name: addr6
+ type: binary
+ checks:
+ exact-len: 16
+ -
+ name: port
+ type: u16
+ byte-order: big-endian
+ -
+ name: flags
+ type: u32
+ -
+ name: if-idx
+ type: s32
+ -
+ name: subflow-attribute
+ name-prefix: mptcp-subflow-attr-
+ attributes:
+ -
+ name: unspec
+ type: unused
+ value: 0
+ -
+ name: token-rem
+ type: u32
+ -
+ name: token-loc
+ type: u32
+ -
+ name: relwrite-seq
+ type: u32
+ -
+ name: map-seq
+ type: u64
+ -
+ name: map-sfseq
+ type: u32
+ -
+ name: ssn-offset
+ type: u32
+ -
+ name: map-datalen
+ type: u16
+ -
+ name: flags
+ type: u32
+ -
+ name: id-rem
+ type: u8
+ -
+ name: id-loc
+ type: u8
+ -
+ name: pad
+ type: pad
+ -
+ name: endpoint
+ name-prefix: mptcp-pm-endpoint-
+ attributes:
+ -
+ name: addr
+ type: nest
+ nested-attributes: address
+ -
+ name: attr
+ name-prefix: mptcp-pm-attr-
+ attr-cnt-name: --mptcp-attr-after-last
+ attributes:
+ -
+ name: unspec
+ type: unused
+ value: 0
+ -
+ name: addr
+ type: nest
+ nested-attributes: address
+ -
+ name: rcv-add-addrs
+ type: u32
+ -
+ name: subflows
+ type: u32
+ -
+ name: token
+ type: u32
+ -
+ name: loc-id
+ type: u8
+ -
+ name: addr-remote
+ type: nest
+ nested-attributes: address
+ -
+ name: event-attr
+ enum-name: mptcp-event-attr
+ name-prefix: mptcp-attr-
+ attributes:
+ -
+ name: unspec
+ type: unused
+ value: 0
+ -
+ name: token
+ type: u32
+ -
+ name: family
+ type: u16
+ -
+ name: loc-id
+ type: u8
+ -
+ name: rem-id
+ type: u8
+ -
+ name: saddr4
+ type: u32
+ byte-order: big-endian
+ -
+ name: saddr6
+ type: binary
+ checks:
+ min-len: 16
+ -
+ name: daddr4
+ type: u32
+ byte-order: big-endian
+ -
+ name: daddr6
+ type: binary
+ checks:
+ min-len: 16
+ -
+ name: sport
+ type: u16
+ byte-order: big-endian
+ -
+ name: dport
+ type: u16
+ byte-order: big-endian
+ -
+ name: backup
+ type: u8
+ -
+ name: error
+ type: u8
+ -
+ name: flags
+ type: u16
+ -
+ name: timeout
+ type: u32
+ -
+ name: if_idx
+ type: u32
+ -
+ name: reset-reason
+ type: u32
+ -
+ name: reset-flags
+ type: u32
+ -
+ name: server-side
+ type: u8
+
+operations:
+ list:
+ -
+ name: unspec
+ doc: unused
+ value: 0
+ -
+ name: add-addr
+ doc: Add endpoint
+ attribute-set: endpoint
+ dont-validate: [ strict ]
+ flags: [ uns-admin-perm ]
+ do: &add-addr-attrs
+ request:
+ attributes:
+ - addr
+ -
+ name: del-addr
+ doc: Delete endpoint
+ attribute-set: endpoint
+ dont-validate: [ strict ]
+ flags: [ uns-admin-perm ]
+ do: *add-addr-attrs
+ -
+ name: get-addr
+ doc: Get endpoint information
+ attribute-set: endpoint
+ dont-validate: [ strict ]
+ flags: [ uns-admin-perm ]
+ do: &get-addr-attrs
+ request:
+ attributes:
+ - addr
+ reply:
+ attributes:
+ - addr
+ dump:
+ reply:
+ attributes:
+ - addr
+ -
+ name: flush-addrs
+ doc: flush addresses
+ attribute-set: endpoint
+ dont-validate: [ strict ]
+ flags: [ uns-admin-perm ]
+ do: *add-addr-attrs
+ -
+ name: set-limits
+ doc: Set protocol limits
+ attribute-set: attr
+ dont-validate: [ strict ]
+ flags: [ uns-admin-perm ]
+ do: &mptcp-limits
+ request:
+ attributes:
+ - rcv-add-addrs
+ - subflows
+ -
+ name: get-limits
+ doc: Get protocol limits
+ attribute-set: attr
+ dont-validate: [ strict ]
+ do: &mptcp-get-limits
+ request:
+ attributes:
+ - rcv-add-addrs
+ - subflows
+ reply:
+ attributes:
+ - rcv-add-addrs
+ - subflows
+ -
+ name: set-flags
+ doc: Change endpoint flags
+ attribute-set: attr
+ dont-validate: [ strict ]
+ flags: [ uns-admin-perm ]
+ do: &mptcp-set-flags
+ request:
+ attributes:
+ - addr
+ - token
+ - addr-remote
+ -
+ name: announce
+ doc: announce new sf
+ attribute-set: attr
+ dont-validate: [ strict ]
+ flags: [ uns-admin-perm ]
+ do: &announce-add
+ request:
+ attributes:
+ - addr
+ - token
+ -
+ name: remove
+ doc: announce removal
+ attribute-set: attr
+ dont-validate: [ strict ]
+ flags: [ uns-admin-perm ]
+ do:
+ request:
+ attributes:
+ - token
+ - loc-id
+ -
+ name: subflow-create
+ doc: todo
+ attribute-set: attr
+ dont-validate: [ strict ]
+ flags: [ uns-admin-perm ]
+ do: &sf-create
+ request:
+ attributes:
+ - addr
+ - token
+ - addr-remote
+ -
+ name: subflow-destroy
+ doc: todo
+ attribute-set: attr
+ dont-validate: [ strict ]
+ flags: [ uns-admin-perm ]
+ do: *sf-create
diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml
index 1c7284fd535b..14511b13f305 100644
--- a/Documentation/netlink/specs/netdev.yaml
+++ b/Documentation/netlink/specs/netdev.yaml
@@ -42,6 +42,19 @@ definitions:
doc:
This feature informs if netdev implements non-linear XDP buffer
support in ndo_xdp_xmit callback.
+ -
+ type: flags
+ name: xdp-rx-metadata
+ render-max: true
+ entries:
+ -
+ name: timestamp
+ doc:
+ Device is capable of exposing receive HW timestamp via bpf_xdp_metadata_rx_timestamp().
+ -
+ name: hash
+ doc:
+ Device is capable of exposing receive packet hash via bpf_xdp_metadata_rx_hash().
attribute-sets:
-
@@ -61,13 +74,18 @@ attribute-sets:
doc: Bitmask of enabled xdp-features.
type: u64
enum: xdp-act
- enum-as-flags: true
-
name: xdp-zc-max-segs
doc: max fragment count supported by ZC driver
type: u32
checks:
min: 1
+ -
+ name: xdp-rx-metadata-features
+ doc: Bitmask of supported XDP receive metadata features.
+ See Documentation/networking/xdp-rx-metadata.rst for more details.
+ type: u64
+ enum: xdp-rx-metadata
operations:
list:
@@ -84,6 +102,7 @@ operations:
- ifindex
- xdp-features
- xdp-zc-max-segs
+ - xdp-rx-metadata-features
dump:
reply: *dev-all
-
diff --git a/Documentation/netlink/specs/nfsd.yaml b/Documentation/netlink/specs/nfsd.yaml
new file mode 100644
index 000000000000..05acc73e2e33
--- /dev/null
+++ b/Documentation/netlink/specs/nfsd.yaml
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+
+name: nfsd
+protocol: genetlink
+uapi-header: linux/nfsd_netlink.h
+
+doc: NFSD configuration over generic netlink.
+
+attribute-sets:
+ -
+ name: rpc-status
+ attributes:
+ -
+ name: xid
+ type: u32
+ byte-order: big-endian
+ -
+ name: flags
+ type: u32
+ -
+ name: prog
+ type: u32
+ -
+ name: version
+ type: u8
+ -
+ name: proc
+ type: u32
+ -
+ name: service_time
+ type: s64
+ -
+ name: pad
+ type: pad
+ -
+ name: saddr4
+ type: u32
+ byte-order: big-endian
+ display-hint: ipv4
+ -
+ name: daddr4
+ type: u32
+ byte-order: big-endian
+ display-hint: ipv4
+ -
+ name: saddr6
+ type: binary
+ display-hint: ipv6
+ -
+ name: daddr6
+ type: binary
+ display-hint: ipv6
+ -
+ name: sport
+ type: u16
+ byte-order: big-endian
+ -
+ name: dport
+ type: u16
+ byte-order: big-endian
+ -
+ name: compound-ops
+ type: u32
+ multi-attr: true
+
+operations:
+ list:
+ -
+ name: rpc-status-get
+ doc: dump pending nfsd rpc
+ attribute-set: rpc-status
+ dump:
+ pre: nfsd-nl-rpc-status-get-start
+ post: nfsd-nl-rpc-status-get-done
+ reply:
+ attributes:
+ - xid
+ - flags
+ - prog
+ - version
+ - proc
+ - service_time
+ - saddr4
+ - daddr4
+ - saddr6
+ - daddr6
+ - sport
+ - dport
+ - compound-ops
diff --git a/Documentation/networking/device_drivers/appletalk/cops.rst b/Documentation/networking/device_drivers/appletalk/cops.rst
deleted file mode 100644
index 964ba80599a9..000000000000
--- a/Documentation/networking/device_drivers/appletalk/cops.rst
+++ /dev/null
@@ -1,80 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-========================================
-The COPS LocalTalk Linux driver (cops.c)
-========================================
-
-By Jay Schulist <jschlst@samba.org>
-
-This driver has two modes and they are: Dayna mode and Tangent mode.
-Each mode corresponds with the type of card. It has been found
-that there are 2 main types of cards and all other cards are
-the same and just have different names or only have minor differences
-such as more IO ports. As this driver is tested it will
-become more clear exactly what cards are supported.
-
-Right now these cards are known to work with the COPS driver. The
-LT-200 cards work in a somewhat more limited capacity than the
-DL200 cards, which work very well and are in use by many people.
-
-TANGENT driver mode:
- - Tangent ATB-II, Novell NL-1000, Daystar Digital LT-200
-
-DAYNA driver mode:
- - Dayna DL2000/DaynaTalk PC (Half Length), COPS LT-95,
- - Farallon PhoneNET PC III, Farallon PhoneNET PC II
-
-Other cards possibly supported mode unknown though:
- - Dayna DL2000 (Full length)
-
-The COPS driver defaults to using Dayna mode. To change the driver's
-mode if you built a driver with dual support use board_type=1 or
-board_type=2 for Dayna or Tangent with insmod.
-
-Operation/loading of the driver
-===============================
-
-Use modprobe like this: /sbin/modprobe cops.o (IO #) (IRQ #)
-If you do not specify any options the driver will try and use the IO = 0x240,
-IRQ = 5. As of right now I would only use IRQ 5 for the card, if autoprobing.
-
-To load multiple COPS driver Localtalk cards you can do one of the following::
-
- insmod cops io=0x240 irq=5
- insmod -o cops2 cops io=0x260 irq=3
-
-Or in lilo.conf put something like this::
-
- append="ether=5,0x240,lt0 ether=3,0x260,lt1"
-
-Then bring up the interface with ifconfig. It will look something like this::
-
- lt0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-F7-00-00-00-00-00-00-00-00
- inet addr:192.168.1.2 Bcast:192.168.1.255 Mask:255.255.255.0
- UP BROADCAST RUNNING NOARP MULTICAST MTU:600 Metric:1
- RX packets:0 errors:0 dropped:0 overruns:0 frame:0
- TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 coll:0
-
-Netatalk Configuration
-======================
-
-You will need to configure atalkd with something like the following to make
-it work with the cops.c driver.
-
-* For single LTalk card use::
-
- dummy -seed -phase 2 -net 2000 -addr 2000.10 -zone "1033"
- lt0 -seed -phase 1 -net 1000 -addr 1000.50 -zone "1033"
-
-* For multiple cards, Ethernet and LocalTalk::
-
- eth0 -seed -phase 2 -net 3000 -addr 3000.20 -zone "1033"
- lt0 -seed -phase 1 -net 1000 -addr 1000.50 -zone "1033"
-
-* For multiple LocalTalk cards, and an Ethernet card.
-
-* Order seems to matter here, Ethernet last::
-
- lt0 -seed -phase 1 -net 1000 -addr 1000.10 -zone "LocalTalk1"
- lt1 -seed -phase 1 -net 2000 -addr 2000.20 -zone "LocalTalk2"
- eth0 -seed -phase 2 -net 3000 -addr 3000.30 -zone "EtherTalk"
diff --git a/Documentation/networking/device_drivers/appletalk/index.rst b/Documentation/networking/device_drivers/appletalk/index.rst
deleted file mode 100644
index c196baeb0856..000000000000
--- a/Documentation/networking/device_drivers/appletalk/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-
-AppleTalk Device Drivers
-========================
-
-Contents:
-
-.. toctree::
- :maxdepth: 2
-
- cops
-
-.. only:: subproject and html
-
- Indices
- =======
-
- * :ref:`genindex`
diff --git a/Documentation/networking/device_drivers/ethernet/index.rst b/Documentation/networking/device_drivers/ethernet/index.rst
index 9827e816084b..43de285b8a92 100644
--- a/Documentation/networking/device_drivers/ethernet/index.rst
+++ b/Documentation/networking/device_drivers/ethernet/index.rst
@@ -32,6 +32,7 @@ Contents:
intel/e1000
intel/e1000e
intel/fm10k
+ intel/idpf
intel/igb
intel/igbvf
intel/ixgbe
diff --git a/Documentation/networking/device_drivers/ethernet/intel/idpf.rst b/Documentation/networking/device_drivers/ethernet/intel/idpf.rst
new file mode 100644
index 000000000000..adb16e2abd21
--- /dev/null
+++ b/Documentation/networking/device_drivers/ethernet/intel/idpf.rst
@@ -0,0 +1,160 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+==========================================================================
+idpf Linux* Base Driver for the Intel(R) Infrastructure Data Path Function
+==========================================================================
+
+Intel idpf Linux driver.
+Copyright(C) 2023 Intel Corporation.
+
+.. contents::
+
+The idpf driver serves as both the Physical Function (PF) and Virtual Function
+(VF) driver for the Intel(R) Infrastructure Data Path Function.
+
+Driver information can be obtained using ethtool, lspci, and ip.
+
+For questions related to hardware requirements, refer to the documentation
+supplied with your Intel adapter. All hardware requirements listed apply to use
+with Linux.
+
+
+Identifying Your Adapter
+========================
+For information on how to identify your adapter, and for the latest Intel
+network drivers, refer to the Intel Support website:
+http://www.intel.com/support
+
+
+Additional Features and Configurations
+======================================
+
+ethtool
+-------
+The driver utilizes the ethtool interface for driver configuration and
+diagnostics, as well as displaying statistical information. The latest ethtool
+version is required for this functionality. If you don't have one yet, you can
+obtain it at:
+https://kernel.org/pub/software/network/ethtool/
+
+
+Viewing Link Messages
+---------------------
+Link messages will not be displayed to the console if the distribution is
+restricting system messages. In order to see network driver link messages on
+your console, set dmesg to eight by entering the following::
+
+ # dmesg -n 8
+
+.. note::
+ This setting is not saved across reboots.
+
+
+Jumbo Frames
+------------
+Jumbo Frames support is enabled by changing the Maximum Transmission Unit (MTU)
+to a value larger than the default value of 1500.
+
+Use the ip command to increase the MTU size. For example, enter the following
+where <ethX> is the interface number::
+
+ # ip link set mtu 9000 dev <ethX>
+ # ip link set up dev <ethX>
+
+.. note::
+ The maximum MTU setting for jumbo frames is 9706. This corresponds to the
+ maximum jumbo frame size of 9728 bytes.
+
+.. note::
+ This driver will attempt to use multiple page sized buffers to receive
+ each jumbo packet. This should help to avoid buffer starvation issues when
+ allocating receive packets.
+
+.. note::
+ Packet loss may have a greater impact on throughput when you use jumbo
+ frames. If you observe a drop in performance after enabling jumbo frames,
+ enabling flow control may mitigate the issue.
+
+
+Performance Optimization
+========================
+Driver defaults are meant to fit a wide variety of workloads, but if further
+optimization is required, we recommend experimenting with the following
+settings.
+
+
+Interrupt Rate Limiting
+-----------------------
+This driver supports an adaptive interrupt throttle rate (ITR) mechanism that
+is tuned for general workloads. The user can customize the interrupt rate
+control for specific workloads, via ethtool, adjusting the number of
+microseconds between interrupts.
+
+To set the interrupt rate manually, you must disable adaptive mode::
+
+ # ethtool -C <ethX> adaptive-rx off adaptive-tx off
+
+For lower CPU utilization:
+ - Disable adaptive ITR and lower Rx and Tx interrupts. The examples below
+ affect every queue of the specified interface.
+
+ - Setting rx-usecs and tx-usecs to 80 will limit interrupts to about
+ 12,500 interrupts per second per queue::
+
+ # ethtool -C <ethX> adaptive-rx off adaptive-tx off rx-usecs 80
+ tx-usecs 80
+
+For reduced latency:
+ - Disable adaptive ITR and ITR by setting rx-usecs and tx-usecs to 0
+ using ethtool::
+
+ # ethtool -C <ethX> adaptive-rx off adaptive-tx off rx-usecs 0
+ tx-usecs 0
+
+Per-queue interrupt rate settings:
+ - The following examples are for queues 1 and 3, but you can adjust other
+ queues.
+
+ - To disable Rx adaptive ITR and set static Rx ITR to 10 microseconds or
+ about 100,000 interrupts/second, for queues 1 and 3::
+
+ # ethtool --per-queue <ethX> queue_mask 0xa --coalesce adaptive-rx off
+ rx-usecs 10
+
+ - To show the current coalesce settings for queues 1 and 3::
+
+ # ethtool --per-queue <ethX> queue_mask 0xa --show-coalesce
+
+
+
+Virtualized Environments
+------------------------
+In addition to the other suggestions in this section, the following may be
+helpful to optimize performance in VMs.
+
+ - Using the appropriate mechanism (vcpupin) in the VM, pin the CPUs to
+ individual LCPUs, making sure to use a set of CPUs included in the
+ device's local_cpulist: /sys/class/net/<ethX>/device/local_cpulist.
+
+ - Configure as many Rx/Tx queues in the VM as available. (See the idpf driver
+ documentation for the number of queues supported.) For example::
+
+ # ethtool -L <virt_interface> rx <max> tx <max>
+
+
+Support
+=======
+For general information, go to the Intel support website at:
+http://www.intel.com/support/
+
+If an issue is identified with the released source code on a supported kernel
+with a supported adapter, email the specific information related to the issue
+to intel-wired-lan@lists.osuosl.org.
+
+
+Trademarks
+==========
+Intel is a trademark or registered trademark of Intel Corporation or its
+subsidiaries in the United States and/or other countries.
+
+* Other names and brands may be claimed as the property of others.
diff --git a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/kconfig.rst b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/kconfig.rst
index 0a42c3395ffa..20d3b7e87049 100644
--- a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/kconfig.rst
+++ b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/kconfig.rst
@@ -67,7 +67,7 @@ Enabling the driver and kconfig options
| Enables :ref:`IPSec XFRM cryptography-offload acceleration <xfrm_device>`.
-**CONFIG_MLX5_EN_MACSEC=(y/n)**
+**CONFIG_MLX5_MACSEC=(y/n)**
| Build support for MACsec cryptography-offload acceleration in the NIC.
diff --git a/Documentation/networking/device_drivers/ethernet/neterion/s2io.rst b/Documentation/networking/device_drivers/ethernet/neterion/s2io.rst
index c5673ec4559b..d731b5a98561 100644
--- a/Documentation/networking/device_drivers/ethernet/neterion/s2io.rst
+++ b/Documentation/networking/device_drivers/ethernet/neterion/s2io.rst
@@ -64,8 +64,8 @@ c. Multi-buffer receive mode. Scattering of packet across multiple
IBM xSeries).
d. MSI/MSI-X. Can be enabled on platforms which support this feature
- (IA64, Xeon) resulting in noticeable performance improvement(up to 7%
- on certain platforms).
+ resulting in noticeable performance improvement (up to 7% on certain
+ platforms).
e. Statistics. Comprehensive MAC-level and software statistics displayed
using "ethtool -S" option.
diff --git a/Documentation/networking/device_drivers/index.rst b/Documentation/networking/device_drivers/index.rst
index 601eacaf12f3..0dd30a84ce25 100644
--- a/Documentation/networking/device_drivers/index.rst
+++ b/Documentation/networking/device_drivers/index.rst
@@ -8,7 +8,6 @@ Contents:
.. toctree::
:maxdepth: 2
- appletalk/index
atm/index
cable/index
can/index
@@ -16,7 +15,6 @@ Contents:
ethernet/index
fddi/index
hamradio/index
- qlogic/index
wifi/index
wwan/index
diff --git a/Documentation/networking/device_drivers/qlogic/index.rst b/Documentation/networking/device_drivers/qlogic/index.rst
deleted file mode 100644
index ad05b04286e4..000000000000
--- a/Documentation/networking/device_drivers/qlogic/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-
-QLogic QLGE Device Drivers
-===============================================
-
-Contents:
-
-.. toctree::
- :maxdepth: 2
-
- qlge
-
-.. only:: subproject and html
-
- Indices
- =======
-
- * :ref:`genindex`
diff --git a/Documentation/networking/device_drivers/qlogic/qlge.rst b/Documentation/networking/device_drivers/qlogic/qlge.rst
deleted file mode 100644
index 0b888253d152..000000000000
--- a/Documentation/networking/device_drivers/qlogic/qlge.rst
+++ /dev/null
@@ -1,118 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=======================================
-QLogic QLGE 10Gb Ethernet device driver
-=======================================
-
-This driver use drgn and devlink for debugging.
-
-Dump kernel data structures in drgn
------------------------------------
-
-To dump kernel data structures, the following Python script can be used
-in drgn:
-
-.. code-block:: python
-
- def align(x, a):
- """the alignment a should be a power of 2
- """
- mask = a - 1
- return (x+ mask) & ~mask
-
- def struct_size(struct_type):
- struct_str = "struct {}".format(struct_type)
- return sizeof(Object(prog, struct_str, address=0x0))
-
- def netdev_priv(netdevice):
- NETDEV_ALIGN = 32
- return netdevice.value_() + align(struct_size("net_device"), NETDEV_ALIGN)
-
- name = 'xxx'
- qlge_device = None
- netdevices = prog['init_net'].dev_base_head.address_of_()
- for netdevice in list_for_each_entry("struct net_device", netdevices, "dev_list"):
- if netdevice.name.string_().decode('ascii') == name:
- print(netdevice.name)
-
- ql_adapter = Object(prog, "struct ql_adapter", address=netdev_priv(qlge_device))
-
-The struct ql_adapter will be printed in drgn as follows,
-
- >>> ql_adapter
- (struct ql_adapter){
- .ricb = (struct ricb){
- .base_cq = (u8)0,
- .flags = (u8)120,
- .mask = (__le16)26637,
- .hash_cq_id = (u8 [1024]){ 172, 142, 255, 255 },
- .ipv6_hash_key = (__le32 [10]){},
- .ipv4_hash_key = (__le32 [4]){},
- },
- .flags = (unsigned long)0,
- .wol = (u32)0,
- .nic_stats = (struct nic_stats){
- .tx_pkts = (u64)0,
- .tx_bytes = (u64)0,
- .tx_mcast_pkts = (u64)0,
- .tx_bcast_pkts = (u64)0,
- .tx_ucast_pkts = (u64)0,
- .tx_ctl_pkts = (u64)0,
- .tx_pause_pkts = (u64)0,
- ...
- },
- .active_vlans = (unsigned long [64]){
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52780853100545, 18446744073709551615,
- 18446619461681283072, 0, 42949673024, 2147483647,
- },
- .rx_ring = (struct rx_ring [17]){
- {
- .cqicb = (struct cqicb){
- .msix_vect = (u8)0,
- .reserved1 = (u8)0,
- .reserved2 = (u8)0,
- .flags = (u8)0,
- .len = (__le16)0,
- .rid = (__le16)0,
- ...
- },
- .cq_base = (void *)0x0,
- .cq_base_dma = (dma_addr_t)0,
- }
- ...
- }
- }
-
-coredump via devlink
---------------------
-
-
-And the coredump obtained via devlink in json format looks like,
-
-.. code:: shell
-
- $ devlink health dump show DEVICE reporter coredump -p -j
- {
- "Core Registers": {
- "segment": 1,
- "values": [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]
- },
- "Test Logic Regs": {
- "segment": 2,
- "values": [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]
- },
- "RMII Registers": {
- "segment": 3,
- "values": [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]
- },
- ...
- "Sem Registers": {
- "segment": 50,
- "values": [ 0,0,0,0 ]
- }
- }
-
-When the module parameter qlge_force_coredump is set to be true, the MPI
-RISC reset before coredumping. So coredumping will much longer since
-devlink tool has to wait for 5 secs for the resetting to be
-finished.
diff --git a/Documentation/networking/devlink/i40e.rst b/Documentation/networking/devlink/i40e.rst
new file mode 100644
index 000000000000..d3cb5bb5197e
--- /dev/null
+++ b/Documentation/networking/devlink/i40e.rst
@@ -0,0 +1,59 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+====================
+i40e devlink support
+====================
+
+This document describes the devlink features implemented by the ``i40e``
+device driver.
+
+Info versions
+=============
+
+The ``i40e`` driver reports the following versions
+
+.. list-table:: devlink info versions implemented
+ :widths: 5 5 5 90
+
+ * - Name
+ - Type
+ - Example
+ - Description
+ * - ``board.id``
+ - fixed
+ - K15190-000
+ - The Product Board Assembly (PBA) identifier of the board.
+ * - ``fw.mgmt``
+ - running
+ - 9.130
+ - 2-digit version number of the management firmware that controls the
+ PHY, link, etc.
+ * - ``fw.mgmt.api``
+ - running
+ - 1.15
+ - 2-digit version number of the API exported over the AdminQ by the
+ management firmware. Used by the driver to identify what commands
+ are supported.
+ * - ``fw.mgmt.build``
+ - running
+ - 73618
+ - Build number of the source for the management firmware.
+ * - ``fw.undi``
+ - running
+ - 1.3429.0
+ - Version of the Option ROM containing the UEFI driver. The version is
+ reported in ``major.minor.patch`` format. The major version is
+ incremented whenever a major breaking change occurs, or when the
+ minor version would overflow. The minor version is incremented for
+ non-breaking changes and reset to 1 when the major version is
+ incremented. The patch version is normally 0 but is incremented when
+ a fix is delivered as a patch against an older base Option ROM.
+ * - ``fw.psid.api``
+ - running
+ - 9.30
+ - Version defining the format of the flash contents.
+ * - ``fw.bundle_id``
+ - running
+ - 0x8000e5f3
+ - Unique identifier of the firmware image file that was loaded onto
+ the device. Also referred to as the EETRACK identifier of the NVM.
diff --git a/Documentation/networking/devlink/index.rst b/Documentation/networking/devlink/index.rst
index b49749e2b9a6..e14d7a701b72 100644
--- a/Documentation/networking/devlink/index.rst
+++ b/Documentation/networking/devlink/index.rst
@@ -18,6 +18,34 @@ netlink commands.
Drivers are encouraged to use the devlink instance lock for their own needs.
+Drivers need to be cautious when taking devlink instance lock and
+taking RTNL lock at the same time. Devlink instance lock needs to be taken
+first, only after that RTNL lock could be taken.
+
+Nested instances
+----------------
+
+Some objects, like linecards or port functions, could have another
+devlink instances created underneath. In that case, drivers should make
+sure to respect following rules:
+
+ - Lock ordering should be maintained. If driver needs to take instance
+ lock of both nested and parent instances at the same time, devlink
+ instance lock of the parent instance should be taken first, only then
+ instance lock of the nested instance could be taken.
+ - Driver should use object-specific helpers to setup the
+ nested relationship:
+
+ - ``devl_nested_devlink_set()`` - called to setup devlink -> nested
+ devlink relationship (could be user for multiple nested instances.
+ - ``devl_port_fn_devlink_set()`` - called to setup port function ->
+ nested devlink relationship.
+ - ``devlink_linecard_nested_dl_set()`` - called to setup linecard ->
+ nested devlink relationship.
+
+The nested devlink info is exposed to the userspace over object-specific
+attributes of devlink netlink.
+
Interface documentation
-----------------------
@@ -52,6 +80,7 @@ parameters, info versions, and other features it supports.
bnxt
etas_es58x
hns3
+ i40e
ionic
ice
mlx4
diff --git a/Documentation/networking/dsa/b53.rst b/Documentation/networking/dsa/b53.rst
index b41637cdb82b..1cb3ff648f88 100644
--- a/Documentation/networking/dsa/b53.rst
+++ b/Documentation/networking/dsa/b53.rst
@@ -52,7 +52,7 @@ VLAN programming would basically change the CPU port's default PVID and make
it untagged, undesirable.
In difference to the configuration described in :ref:`dsa-vlan-configuration`
-the default VLAN 1 has to be removed from the slave interface configuration in
+the default VLAN 1 has to be removed from the user interface configuration in
single port and gateway configuration, while there is no need to add an extra
VLAN configuration in the bridge showcase.
@@ -68,13 +68,13 @@ By default packages are tagged with vid 1:
ip link add link eth0 name eth0.2 type vlan id 2
ip link add link eth0 name eth0.3 type vlan id 3
- # The master interface needs to be brought up before the slave ports.
+ # The conduit interface needs to be brought up before the user ports.
ip link set eth0 up
ip link set eth0.1 up
ip link set eth0.2 up
ip link set eth0.3 up
- # bring up the slave interfaces
+ # bring up the user interfaces
ip link set wan up
ip link set lan1 up
ip link set lan2 up
@@ -113,11 +113,11 @@ bridge
# tag traffic on CPU port
ip link add link eth0 name eth0.1 type vlan id 1
- # The master interface needs to be brought up before the slave ports.
+ # The conduit interface needs to be brought up before the user ports.
ip link set eth0 up
ip link set eth0.1 up
- # bring up the slave interfaces
+ # bring up the user interfaces
ip link set wan up
ip link set lan1 up
ip link set lan2 up
@@ -149,12 +149,12 @@ gateway
ip link add link eth0 name eth0.1 type vlan id 1
ip link add link eth0 name eth0.2 type vlan id 2
- # The master interface needs to be brought up before the slave ports.
+ # The conduit interface needs to be brought up before the user ports.
ip link set eth0 up
ip link set eth0.1 up
ip link set eth0.2 up
- # bring up the slave interfaces
+ # bring up the user interfaces
ip link set wan up
ip link set lan1 up
ip link set lan2 up
diff --git a/Documentation/networking/dsa/bcm_sf2.rst b/Documentation/networking/dsa/bcm_sf2.rst
index dee234039e1e..d2571435696f 100644
--- a/Documentation/networking/dsa/bcm_sf2.rst
+++ b/Documentation/networking/dsa/bcm_sf2.rst
@@ -67,7 +67,7 @@ MDIO indirect accesses
----------------------
Due to a limitation in how Broadcom switches have been designed, external
-Broadcom switches connected to a SF2 require the use of the DSA slave MDIO bus
+Broadcom switches connected to a SF2 require the use of the DSA user MDIO bus
in order to properly configure them. By default, the SF2 pseudo-PHY address, and
an external switch pseudo-PHY address will both be snooping for incoming MDIO
transactions, since they are at the same address (30), resulting in some kind of
diff --git a/Documentation/networking/dsa/configuration.rst b/Documentation/networking/dsa/configuration.rst
index d2934c40f0f1..6cc4ded3cc23 100644
--- a/Documentation/networking/dsa/configuration.rst
+++ b/Documentation/networking/dsa/configuration.rst
@@ -31,38 +31,38 @@ at https://www.kernel.org/pub/linux/utils/net/iproute2/
Through DSA every port of a switch is handled like a normal linux Ethernet
interface. The CPU port is the switch port connected to an Ethernet MAC chip.
-The corresponding linux Ethernet interface is called the master interface.
-All other corresponding linux interfaces are called slave interfaces.
+The corresponding linux Ethernet interface is called the conduit interface.
+All other corresponding linux interfaces are called user interfaces.
-The slave interfaces depend on the master interface being up in order for them
-to send or receive traffic. Prior to kernel v5.12, the state of the master
+The user interfaces depend on the conduit interface being up in order for them
+to send or receive traffic. Prior to kernel v5.12, the state of the conduit
interface had to be managed explicitly by the user. Starting with kernel v5.12,
the behavior is as follows:
-- when a DSA slave interface is brought up, the master interface is
+- when a DSA user interface is brought up, the conduit interface is
automatically brought up.
-- when the master interface is brought down, all DSA slave interfaces are
+- when the conduit interface is brought down, all DSA user interfaces are
automatically brought down.
In this documentation the following Ethernet interfaces are used:
*eth0*
- the master interface
+ the conduit interface
*eth1*
- another master interface
+ another conduit interface
*lan1*
- a slave interface
+ a user interface
*lan2*
- another slave interface
+ another user interface
*lan3*
- a third slave interface
+ a third user interface
*wan*
- A slave interface dedicated for upstream traffic
+ A user interface dedicated for upstream traffic
Further Ethernet interfaces can be configured similar.
The configured IPs and networks are:
@@ -96,11 +96,11 @@ without using a VLAN based configuration.
ip addr add 192.0.2.5/30 dev lan2
ip addr add 192.0.2.9/30 dev lan3
- # For kernels earlier than v5.12, the master interface needs to be
- # brought up manually before the slave ports.
+ # For kernels earlier than v5.12, the conduit interface needs to be
+ # brought up manually before the user ports.
ip link set eth0 up
- # bring up the slave interfaces
+ # bring up the user interfaces
ip link set lan1 up
ip link set lan2 up
ip link set lan3 up
@@ -108,11 +108,11 @@ without using a VLAN based configuration.
*bridge*
.. code-block:: sh
- # For kernels earlier than v5.12, the master interface needs to be
- # brought up manually before the slave ports.
+ # For kernels earlier than v5.12, the conduit interface needs to be
+ # brought up manually before the user ports.
ip link set eth0 up
- # bring up the slave interfaces
+ # bring up the user interfaces
ip link set lan1 up
ip link set lan2 up
ip link set lan3 up
@@ -134,11 +134,11 @@ without using a VLAN based configuration.
*gateway*
.. code-block:: sh
- # For kernels earlier than v5.12, the master interface needs to be
- # brought up manually before the slave ports.
+ # For kernels earlier than v5.12, the conduit interface needs to be
+ # brought up manually before the user ports.
ip link set eth0 up
- # bring up the slave interfaces
+ # bring up the user interfaces
ip link set wan up
ip link set lan1 up
ip link set lan2 up
@@ -178,14 +178,14 @@ configuration.
ip link add link eth0 name eth0.2 type vlan id 2
ip link add link eth0 name eth0.3 type vlan id 3
- # For kernels earlier than v5.12, the master interface needs to be
- # brought up manually before the slave ports.
+ # For kernels earlier than v5.12, the conduit interface needs to be
+ # brought up manually before the user ports.
ip link set eth0 up
ip link set eth0.1 up
ip link set eth0.2 up
ip link set eth0.3 up
- # bring up the slave interfaces
+ # bring up the user interfaces
ip link set lan1 up
ip link set lan2 up
ip link set lan3 up
@@ -221,12 +221,12 @@ configuration.
# tag traffic on CPU port
ip link add link eth0 name eth0.1 type vlan id 1
- # For kernels earlier than v5.12, the master interface needs to be
- # brought up manually before the slave ports.
+ # For kernels earlier than v5.12, the conduit interface needs to be
+ # brought up manually before the user ports.
ip link set eth0 up
ip link set eth0.1 up
- # bring up the slave interfaces
+ # bring up the user interfaces
ip link set lan1 up
ip link set lan2 up
ip link set lan3 up
@@ -261,13 +261,13 @@ configuration.
ip link add link eth0 name eth0.1 type vlan id 1
ip link add link eth0 name eth0.2 type vlan id 2
- # For kernels earlier than v5.12, the master interface needs to be
- # brought up manually before the slave ports.
+ # For kernels earlier than v5.12, the conduit interface needs to be
+ # brought up manually before the user ports.
ip link set eth0 up
ip link set eth0.1 up
ip link set eth0.2 up
- # bring up the slave interfaces
+ # bring up the user interfaces
ip link set wan up
ip link set lan1 up
ip link set lan2 up
@@ -380,22 +380,22 @@ affinities according to the available CPU ports.
Secondly, it is possible to perform load balancing between CPU ports on a per
packet basis, rather than statically assigning user ports to CPU ports.
-This can be achieved by placing the DSA masters under a LAG interface (bonding
+This can be achieved by placing the DSA conduits under a LAG interface (bonding
or team). DSA monitors this operation and creates a mirror of this software LAG
-on the CPU ports facing the physical DSA masters that constitute the LAG slave
+on the CPU ports facing the physical DSA conduits that constitute the LAG slave
devices.
To make use of multiple CPU ports, the firmware (device tree) description of
-the switch must mark all the links between CPU ports and their DSA masters
+the switch must mark all the links between CPU ports and their DSA conduits
using the ``ethernet`` reference/phandle. At startup, only a single CPU port
-and DSA master will be used - the numerically first port from the firmware
+and DSA conduit will be used - the numerically first port from the firmware
description which has an ``ethernet`` property. It is up to the user to
-configure the system for the switch to use other masters.
+configure the system for the switch to use other conduits.
DSA uses the ``rtnl_link_ops`` mechanism (with a "dsa" ``kind``) to allow
-changing the DSA master of a user port. The ``IFLA_DSA_MASTER`` u32 netlink
-attribute contains the ifindex of the master device that handles each slave
-device. The DSA master must be a valid candidate based on firmware node
+changing the DSA conduit of a user port. The ``IFLA_DSA_CONDUIT`` u32 netlink
+attribute contains the ifindex of the conduit device that handles each user
+device. The DSA conduit must be a valid candidate based on firmware node
information, or a LAG interface which contains only slaves which are valid
candidates.
@@ -403,7 +403,7 @@ Using iproute2, the following manipulations are possible:
.. code-block:: sh
- # See the DSA master in current use
+ # See the DSA conduit in current use
ip -d link show dev swp0
(...)
dsa master eth0
@@ -414,7 +414,7 @@ Using iproute2, the following manipulations are possible:
ip link set swp2 type dsa master eth1
ip link set swp3 type dsa master eth0
- # CPU ports in LAG, using explicit assignment of the DSA master
+ # CPU ports in LAG, using explicit assignment of the DSA conduit
ip link add bond0 type bond mode balance-xor && ip link set bond0 up
ip link set eth1 down && ip link set eth1 master bond0
ip link set swp0 type dsa master bond0
@@ -426,7 +426,7 @@ Using iproute2, the following manipulations are possible:
(...)
dsa master bond0
- # CPU ports in LAG, relying on implicit migration of the DSA master
+ # CPU ports in LAG, relying on implicit migration of the DSA conduit
ip link add bond0 type bond mode balance-xor && ip link set bond0 up
ip link set eth0 down && ip link set eth0 master bond0
ip link set eth1 down && ip link set eth1 master bond0
@@ -435,24 +435,24 @@ Using iproute2, the following manipulations are possible:
dsa master bond0
Notice that in the case of CPU ports under a LAG, the use of the
-``IFLA_DSA_MASTER`` netlink attribute is not strictly needed, but rather, DSA
-reacts to the ``IFLA_MASTER`` attribute change of its present master (``eth0``)
+``IFLA_DSA_CONDUIT`` netlink attribute is not strictly needed, but rather, DSA
+reacts to the ``IFLA_MASTER`` attribute change of its present conduit (``eth0``)
and migrates all user ports to the new upper of ``eth0``, ``bond0``. Similarly,
when ``bond0`` is destroyed using ``RTM_DELLINK``, DSA migrates the user ports
-that were assigned to this interface to the first physical DSA master which is
+that were assigned to this interface to the first physical DSA conduit which is
eligible, based on the firmware description (it effectively reverts to the
startup configuration).
In a setup with more than 2 physical CPU ports, it is therefore possible to mix
-static user to CPU port assignment with LAG between DSA masters. It is not
-possible to statically assign a user port towards a DSA master that has any
-upper interfaces (this includes LAG devices - the master must always be the LAG
+static user to CPU port assignment with LAG between DSA conduits. It is not
+possible to statically assign a user port towards a DSA conduit that has any
+upper interfaces (this includes LAG devices - the conduit must always be the LAG
in this case).
-Live changing of the DSA master (and thus CPU port) affinity of a user port is
+Live changing of the DSA conduit (and thus CPU port) affinity of a user port is
permitted, in order to allow dynamic redistribution in response to traffic.
-Physical DSA masters are allowed to join and leave at any time a LAG interface
-used as a DSA master; however, DSA will reject a LAG interface as a valid
-candidate for being a DSA master unless it has at least one physical DSA master
+Physical DSA conduits are allowed to join and leave at any time a LAG interface
+used as a DSA conduit; however, DSA will reject a LAG interface as a valid
+candidate for being a DSA conduit unless it has at least one physical DSA conduit
as a slave device.
diff --git a/Documentation/networking/dsa/dsa.rst b/Documentation/networking/dsa/dsa.rst
index a94ddf83348a..7b2e69cd7ef0 100644
--- a/Documentation/networking/dsa/dsa.rst
+++ b/Documentation/networking/dsa/dsa.rst
@@ -25,7 +25,7 @@ presence of a management port connected to an Ethernet controller capable of
receiving Ethernet frames from the switch. This is a very common setup for all
kinds of Ethernet switches found in Small Home and Office products: routers,
gateways, or even top-of-rack switches. This host Ethernet controller will
-be later referred to as "master" and "cpu" in DSA terminology and code.
+be later referred to as "conduit" and "cpu" in DSA terminology and code.
The D in DSA stands for Distributed, because the subsystem has been designed
with the ability to configure and manage cascaded switches on top of each other
@@ -35,7 +35,7 @@ of multiple switches connected to each other is called a "switch tree".
For each front-panel port, DSA creates specialized network devices which are
used as controlling and data-flowing endpoints for use by the Linux networking
-stack. These specialized network interfaces are referred to as "slave" network
+stack. These specialized network interfaces are referred to as "user" network
interfaces in DSA terminology and code.
The ideal case for using DSA is when an Ethernet switch supports a "switch tag"
@@ -56,12 +56,16 @@ Note that DSA does not currently create network interfaces for the "cpu" and
- the "cpu" port is the Ethernet switch facing side of the management
controller, and as such, would create a duplication of feature, since you
- would get two interfaces for the same conduit: master netdev, and "cpu" netdev
+ would get two interfaces for the same conduit: conduit netdev, and "cpu" netdev
- the "dsa" port(s) are just conduits between two or more switches, and as such
cannot really be used as proper network interfaces either, only the
downstream, or the top-most upstream interface makes sense with that model
+NB: for the past 15 years, the DSA subsystem had been making use of the terms
+"master" (rather than "conduit") and "slave" (rather than "user"). These terms
+have been removed from the DSA codebase and phased out of the uAPI.
+
Switch tagging protocols
------------------------
@@ -80,14 +84,14 @@ methods of the ``struct dsa_device_ops`` structure, which are detailed below.
Tagging protocols generally fall in one of three categories:
1. The switch-specific frame header is located before the Ethernet header,
- shifting to the right (from the perspective of the DSA master's frame
+ shifting to the right (from the perspective of the DSA conduit's frame
parser) the MAC DA, MAC SA, EtherType and the entire L2 payload.
2. The switch-specific frame header is located before the EtherType, keeping
- the MAC DA and MAC SA in place from the DSA master's perspective, but
+ the MAC DA and MAC SA in place from the DSA conduit's perspective, but
shifting the 'real' EtherType and L2 payload to the right.
3. The switch-specific frame header is located at the tail of the packet,
keeping all frame headers in place and not altering the view of the packet
- that the DSA master's frame parser has.
+ that the DSA conduit's frame parser has.
A tagging protocol may tag all packets with switch tags of the same length, or
the tag length might vary (for example packets with PTP timestamps might
@@ -95,7 +99,7 @@ require an extended switch tag, or there might be one tag length on TX and a
different one on RX). Either way, the tagging protocol driver must populate the
``struct dsa_device_ops::needed_headroom`` and/or ``struct dsa_device_ops::needed_tailroom``
with the length in octets of the longest switch frame header/trailer. The DSA
-framework will automatically adjust the MTU of the master interface to
+framework will automatically adjust the MTU of the conduit interface to
accommodate for this extra size in order for DSA user ports to support the
standard MTU (L2 payload length) of 1500 octets. The ``needed_headroom`` and
``needed_tailroom`` properties are also used to request from the network stack,
@@ -140,18 +144,18 @@ adding or removing the ``ETH_P_EDSA`` EtherType and some padding octets).
It is possible to construct cascaded setups of DSA switches even if their
tagging protocols are not compatible with one another. In this case, there are
no DSA links in this fabric, and each switch constitutes a disjoint DSA switch
-tree. The DSA links are viewed as simply a pair of a DSA master (the out-facing
+tree. The DSA links are viewed as simply a pair of a DSA conduit (the out-facing
port of the upstream DSA switch) and a CPU port (the in-facing port of the
downstream DSA switch).
The tagging protocol of the attached DSA switch tree can be viewed through the
-``dsa/tagging`` sysfs attribute of the DSA master::
+``dsa/tagging`` sysfs attribute of the DSA conduit::
cat /sys/class/net/eth0/dsa/tagging
If the hardware and driver are capable, the tagging protocol of the DSA switch
tree can be changed at runtime. This is done by writing the new tagging
-protocol name to the same sysfs device attribute as above (the DSA master and
+protocol name to the same sysfs device attribute as above (the DSA conduit and
all attached switch ports must be down while doing this).
It is desirable that all tagging protocols are testable with the ``dsa_loop``
@@ -159,7 +163,7 @@ mockup driver, which can be attached to any network interface. The goal is that
any network interface should be capable of transmitting the same packet in the
same way, and the tagger should decode the same received packet in the same way
regardless of the driver used for the switch control path, and the driver used
-for the DSA master.
+for the DSA conduit.
The transmission of a packet goes through the tagger's ``xmit`` function.
The passed ``struct sk_buff *skb`` has ``skb->data`` pointing at
@@ -183,44 +187,44 @@ virtual DSA user network interface corresponding to the physical front-facing
switch port that the packet was received on.
Since tagging protocols in category 1 and 2 break software (and most often also
-hardware) packet dissection on the DSA master, features such as RPS (Receive
-Packet Steering) on the DSA master would be broken. The DSA framework deals
+hardware) packet dissection on the DSA conduit, features such as RPS (Receive
+Packet Steering) on the DSA conduit would be broken. The DSA framework deals
with this by hooking into the flow dissector and shifting the offset at which
-the IP header is to be found in the tagged frame as seen by the DSA master.
+the IP header is to be found in the tagged frame as seen by the DSA conduit.
This behavior is automatic based on the ``overhead`` value of the tagging
protocol. If not all packets are of equal size, the tagger can implement the
``flow_dissect`` method of the ``struct dsa_device_ops`` and override this
default behavior by specifying the correct offset incurred by each individual
RX packet. Tail taggers do not cause issues to the flow dissector.
-Checksum offload should work with category 1 and 2 taggers when the DSA master
+Checksum offload should work with category 1 and 2 taggers when the DSA conduit
driver declares NETIF_F_HW_CSUM in vlan_features and looks at csum_start and
csum_offset. For those cases, DSA will shift the checksum start and offset by
-the tag size. If the DSA master driver still uses the legacy NETIF_F_IP_CSUM
+the tag size. If the DSA conduit driver still uses the legacy NETIF_F_IP_CSUM
or NETIF_F_IPV6_CSUM in vlan_features, the offload might only work if the
offload hardware already expects that specific tag (perhaps due to matching
-vendors). DSA slaves inherit those flags from the master port, and it is up to
+vendors). DSA user ports inherit those flags from the conduit, and it is up to
the driver to correctly fall back to software checksum when the IP header is not
where the hardware expects. If that check is ineffective, the packets might go
to the network without a proper checksum (the checksum field will have the
pseudo IP header sum). For category 3, when the offload hardware does not
already expect the switch tag in use, the checksum must be calculated before any
-tag is inserted (i.e. inside the tagger). Otherwise, the DSA master would
+tag is inserted (i.e. inside the tagger). Otherwise, the DSA conduit would
include the tail tag in the (software or hardware) checksum calculation. Then,
when the tag gets stripped by the switch during transmission, it will leave an
incorrect IP checksum in place.
Due to various reasons (most common being category 1 taggers being associated
-with DSA-unaware masters, mangling what the master perceives as MAC DA), the
-tagging protocol may require the DSA master to operate in promiscuous mode, to
+with DSA-unaware conduits, mangling what the conduit perceives as MAC DA), the
+tagging protocol may require the DSA conduit to operate in promiscuous mode, to
receive all frames regardless of the value of the MAC DA. This can be done by
-setting the ``promisc_on_master`` property of the ``struct dsa_device_ops``.
-Note that this assumes a DSA-unaware master driver, which is the norm.
+setting the ``promisc_on_conduit`` property of the ``struct dsa_device_ops``.
+Note that this assumes a DSA-unaware conduit driver, which is the norm.
-Master network devices
-----------------------
+Conduit network devices
+-----------------------
-Master network devices are regular, unmodified Linux network device drivers for
+Conduit network devices are regular, unmodified Linux network device drivers for
the CPU/management Ethernet interface. Such a driver might occasionally need to
know whether DSA is enabled (e.g.: to enable/disable specific offload features),
but the DSA subsystem has been proven to work with industry standard drivers:
@@ -232,14 +236,14 @@ Ethernet switch.
Networking stack hooks
----------------------
-When a master netdev is used with DSA, a small hook is placed in the
+When a conduit netdev is used with DSA, a small hook is placed in the
networking stack is in order to have the DSA subsystem process the Ethernet
switch specific tagging protocol. DSA accomplishes this by registering a
specific (and fake) Ethernet type (later becoming ``skb->protocol``) with the
networking stack, this is also known as a ``ptype`` or ``packet_type``. A typical
Ethernet Frame receive sequence looks like this:
-Master network device (e.g.: e1000e):
+Conduit network device (e.g.: e1000e):
1. Receive interrupt fires:
@@ -269,16 +273,16 @@ Master network device (e.g.: e1000e):
- inspect and strip switch tag protocol to determine originating port
- locate per-port network device
- - invoke ``eth_type_trans()`` with the DSA slave network device
+ - invoke ``eth_type_trans()`` with the DSA user network device
- invoked ``netif_receive_skb()``
-Past this point, the DSA slave network devices get delivered regular Ethernet
+Past this point, the DSA user network devices get delivered regular Ethernet
frames that can be processed by the networking stack.
-Slave network devices
----------------------
+User network devices
+--------------------
-Slave network devices created by DSA are stacked on top of their master network
+User network devices created by DSA are stacked on top of their conduit network
device, each of these network interfaces will be responsible for being a
controlling and data-flowing end-point for each front-panel port of the switch.
These interfaces are specialized in order to:
@@ -289,31 +293,31 @@ These interfaces are specialized in order to:
Wake-on-LAN, register dumps...
- manage external/internal PHY: link, auto-negotiation, etc.
-These slave network devices have custom net_device_ops and ethtool_ops function
+These user network devices have custom net_device_ops and ethtool_ops function
pointers which allow DSA to introduce a level of layering between the networking
stack/ethtool and the switch driver implementation.
-Upon frame transmission from these slave network devices, DSA will look up which
+Upon frame transmission from these user network devices, DSA will look up which
switch tagging protocol is currently registered with these network devices and
invoke a specific transmit routine which takes care of adding the relevant
switch tag in the Ethernet frames.
-These frames are then queued for transmission using the master network device
+These frames are then queued for transmission using the conduit network device
``ndo_start_xmit()`` function. Since they contain the appropriate switch tag, the
Ethernet switch will be able to process these incoming frames from the
management interface and deliver them to the physical switch port.
When using multiple CPU ports, it is possible to stack a LAG (bonding/team)
-device between the DSA slave devices and the physical DSA masters. The LAG
-device is thus also a DSA master, but the LAG slave devices continue to be DSA
-masters as well (just with no user port assigned to them; this is needed for
-recovery in case the LAG DSA master disappears). Thus, the data path of the LAG
-DSA master is used asymmetrically. On RX, the ``ETH_P_XDSA`` handler, which
-calls ``dsa_switch_rcv()``, is invoked early (on the physical DSA master;
-LAG slave). Therefore, the RX data path of the LAG DSA master is not used.
-On the other hand, TX takes place linearly: ``dsa_slave_xmit`` calls
-``dsa_enqueue_skb``, which calls ``dev_queue_xmit`` towards the LAG DSA master.
-The latter calls ``dev_queue_xmit`` towards one physical DSA master or the
+device between the DSA user devices and the physical DSA conduits. The LAG
+device is thus also a DSA conduit, but the LAG slave devices continue to be DSA
+conduits as well (just with no user port assigned to them; this is needed for
+recovery in case the LAG DSA conduit disappears). Thus, the data path of the LAG
+DSA conduit is used asymmetrically. On RX, the ``ETH_P_XDSA`` handler, which
+calls ``dsa_switch_rcv()``, is invoked early (on the physical DSA conduit;
+LAG slave). Therefore, the RX data path of the LAG DSA conduit is not used.
+On the other hand, TX takes place linearly: ``dsa_user_xmit`` calls
+``dsa_enqueue_skb``, which calls ``dev_queue_xmit`` towards the LAG DSA conduit.
+The latter calls ``dev_queue_xmit`` towards one physical DSA conduit or the
other, and in both cases, the packet exits the system through a hardware path
towards the switch.
@@ -352,11 +356,11 @@ perspective::
|| swp0 | | swp1 | | swp2 | | swp3 ||
++------+-+------+-+------+-+------++
-Slave MDIO bus
---------------
+User MDIO bus
+-------------
-In order to be able to read to/from a switch PHY built into it, DSA creates a
-slave MDIO bus which allows a specific switch driver to divert and intercept
+In order to be able to read to/from a switch PHY built into it, DSA creates an
+user MDIO bus which allows a specific switch driver to divert and intercept
MDIO reads/writes towards specific PHY addresses. In most MDIO-connected
switches, these functions would utilize direct or indirect PHY addressing mode
to return standard MII registers from the switch builtin PHYs, allowing the PHY
@@ -364,7 +368,7 @@ library and/or to return link status, link partner pages, auto-negotiation
results, etc.
For Ethernet switches which have both external and internal MDIO buses, the
-slave MII bus can be utilized to mux/demux MDIO reads and writes towards either
+user MII bus can be utilized to mux/demux MDIO reads and writes towards either
internal or external MDIO devices this switch might be connected to: internal
PHYs, external PHYs, or even external switches.
@@ -381,10 +385,10 @@ DSA data structures are defined in ``include/net/dsa.h`` as well as
- ``dsa_platform_data``: platform device configuration data which can reference
a collection of dsa_chip_data structures if multiple switches are cascaded,
- the master network device this switch tree is attached to needs to be
+ the conduit network device this switch tree is attached to needs to be
referenced
-- ``dsa_switch_tree``: structure assigned to the master network device under
+- ``dsa_switch_tree``: structure assigned to the conduit network device under
``dsa_ptr``, this structure references a dsa_platform_data structure as well as
the tagging protocol supported by the switch tree, and which receive/transmit
function hooks should be invoked, information about the directly attached
@@ -392,7 +396,7 @@ DSA data structures are defined in ``include/net/dsa.h`` as well as
referenced to address individual switches in the tree.
- ``dsa_switch``: structure describing a switch device in the tree, referencing
- a ``dsa_switch_tree`` as a backpointer, slave network devices, master network
+ a ``dsa_switch_tree`` as a backpointer, user network devices, conduit network
device, and a reference to the backing``dsa_switch_ops``
- ``dsa_switch_ops``: structure referencing function pointers, see below for a
@@ -404,7 +408,7 @@ Design limitations
Lack of CPU/DSA network devices
-------------------------------
-DSA does not currently create slave network devices for the CPU or DSA ports, as
+DSA does not currently create user network devices for the CPU or DSA ports, as
described before. This might be an issue in the following cases:
- inability to fetch switch CPU port statistics counters using ethtool, which
@@ -419,7 +423,7 @@ described before. This might be an issue in the following cases:
Common pitfalls using DSA setups
--------------------------------
-Once a master network device is configured to use DSA (dev->dsa_ptr becomes
+Once a conduit network device is configured to use DSA (dev->dsa_ptr becomes
non-NULL), and the switch behind it expects a tagging protocol, this network
interface can only exclusively be used as a conduit interface. Sending packets
directly through this interface (e.g.: opening a socket using this interface)
@@ -440,7 +444,7 @@ DSA currently leverages the following subsystems:
MDIO/PHY library
----------------
-Slave network devices exposed by DSA may or may not be interfacing with PHY
+User network devices exposed by DSA may or may not be interfacing with PHY
devices (``struct phy_device`` as defined in ``include/linux/phy.h)``, but the DSA
subsystem deals with all possible combinations:
@@ -450,7 +454,7 @@ subsystem deals with all possible combinations:
- special, non-autonegotiated or non MDIO-managed PHY devices: SFPs, MoCA; a.k.a
fixed PHYs
-The PHY configuration is done by the ``dsa_slave_phy_setup()`` function and the
+The PHY configuration is done by the ``dsa_user_phy_setup()`` function and the
logic basically looks like this:
- if Device Tree is used, the PHY device is looked up using the standard
@@ -463,7 +467,7 @@ logic basically looks like this:
and connected transparently using the special fixed MDIO bus driver
- finally, if the PHY is built into the switch, as is very common with
- standalone switch packages, the PHY is probed using the slave MII bus created
+ standalone switch packages, the PHY is probed using the user MII bus created
by DSA
@@ -472,7 +476,7 @@ SWITCHDEV
DSA directly utilizes SWITCHDEV when interfacing with the bridge layer, and
more specifically with its VLAN filtering portion when configuring VLANs on top
-of per-port slave network devices. As of today, the only SWITCHDEV objects
+of per-port user network devices. As of today, the only SWITCHDEV objects
supported by DSA are the FDB and VLAN objects.
Devlink
@@ -589,8 +593,8 @@ is torn down when the first switch unregisters.
It is mandatory for DSA switch drivers to implement the ``shutdown()`` callback
of their respective bus, and call ``dsa_switch_shutdown()`` from it (a minimal
version of the full teardown performed by ``dsa_unregister_switch()``).
-The reason is that DSA keeps a reference on the master net device, and if the
-driver for the master device decides to unbind on shutdown, DSA's reference
+The reason is that DSA keeps a reference on the conduit net device, and if the
+driver for the conduit device decides to unbind on shutdown, DSA's reference
will block that operation from finalizing.
Either ``dsa_switch_shutdown()`` or ``dsa_unregister_switch()`` must be called,
@@ -615,7 +619,7 @@ Switch configuration
tag formats.
- ``change_tag_protocol``: when the default tagging protocol has compatibility
- problems with the master or other issues, the driver may support changing it
+ problems with the conduit or other issues, the driver may support changing it
at runtime, either through a device tree property or through sysfs. In that
case, further calls to ``get_tag_protocol`` should report the protocol in
current use.
@@ -643,22 +647,22 @@ Switch configuration
PHY cannot be found. In this case, probing of the DSA switch continues
without that particular port.
-- ``port_change_master``: method through which the affinity (association used
+- ``port_change_conduit``: method through which the affinity (association used
for traffic termination purposes) between a user port and a CPU port can be
changed. By default all user ports from a tree are assigned to the first
available CPU port that makes sense for them (most of the times this means
the user ports of a tree are all assigned to the same CPU port, except for H
topologies as described in commit 2c0b03258b8b). The ``port`` argument
- represents the index of the user port, and the ``master`` argument represents
- the new DSA master ``net_device``. The CPU port associated with the new
- master can be retrieved by looking at ``struct dsa_port *cpu_dp =
- master->dsa_ptr``. Additionally, the master can also be a LAG device where
- all the slave devices are physical DSA masters. LAG DSA masters also have a
- valid ``master->dsa_ptr`` pointer, however this is not unique, but rather a
- duplicate of the first physical DSA master's (LAG slave) ``dsa_ptr``. In case
- of a LAG DSA master, a further call to ``port_lag_join`` will be emitted
+ represents the index of the user port, and the ``conduit`` argument represents
+ the new DSA conduit ``net_device``. The CPU port associated with the new
+ conduit can be retrieved by looking at ``struct dsa_port *cpu_dp =
+ conduit->dsa_ptr``. Additionally, the conduit can also be a LAG device where
+ all the slave devices are physical DSA conduits. LAG DSA also have a
+ valid ``conduit->dsa_ptr`` pointer, however this is not unique, but rather a
+ duplicate of the first physical DSA conduit's (LAG slave) ``dsa_ptr``. In case
+ of a LAG DSA conduit, a further call to ``port_lag_join`` will be emitted
separately for the physical CPU ports associated with the physical DSA
- masters, requesting them to create a hardware LAG associated with the LAG
+ conduits, requesting them to create a hardware LAG associated with the LAG
interface.
PHY devices and link management
@@ -670,16 +674,16 @@ PHY devices and link management
should return a 32-bit bitmask of "flags" that is private between the switch
driver and the Ethernet PHY driver in ``drivers/net/phy/\*``.
-- ``phy_read``: Function invoked by the DSA slave MDIO bus when attempting to read
+- ``phy_read``: Function invoked by the DSA user MDIO bus when attempting to read
the switch port MDIO registers. If unavailable, return 0xffff for each read.
For builtin switch Ethernet PHYs, this function should allow reading the link
status, auto-negotiation results, link partner pages, etc.
-- ``phy_write``: Function invoked by the DSA slave MDIO bus when attempting to write
+- ``phy_write``: Function invoked by the DSA user MDIO bus when attempting to write
to the switch port MDIO registers. If unavailable return a negative error
code.
-- ``adjust_link``: Function invoked by the PHY library when a slave network device
+- ``adjust_link``: Function invoked by the PHY library when a user network device
is attached to a PHY device. This function is responsible for appropriately
configuring the switch port link parameters: speed, duplex, pause based on
what the ``phy_device`` is providing.
@@ -698,14 +702,14 @@ Ethtool operations
typically return statistics strings, private flags strings, etc.
- ``get_ethtool_stats``: ethtool function used to query per-port statistics and
- return their values. DSA overlays slave network devices general statistics:
+ return their values. DSA overlays user network devices general statistics:
RX/TX counters from the network device, with switch driver specific statistics
per port
- ``get_sset_count``: ethtool function used to query the number of statistics items
- ``get_wol``: ethtool function used to obtain Wake-on-LAN settings per-port, this
- function may for certain implementations also query the master network device
+ function may for certain implementations also query the conduit network device
Wake-on-LAN settings if this interface needs to participate in Wake-on-LAN
- ``set_wol``: ethtool function used to configure Wake-on-LAN settings per-port,
@@ -747,13 +751,13 @@ Power management
should resume all Ethernet switch activities and re-configure the switch to be
in a fully active state
-- ``port_enable``: function invoked by the DSA slave network device ndo_open
+- ``port_enable``: function invoked by the DSA user network device ndo_open
function when a port is administratively brought up, this function should
fully enable a given switch port. DSA takes care of marking the port with
``BR_STATE_BLOCKING`` if the port is a bridge member, or ``BR_STATE_FORWARDING`` if it
was not, and propagating these changes down to the hardware
-- ``port_disable``: function invoked by the DSA slave network device ndo_close
+- ``port_disable``: function invoked by the DSA user network device ndo_close
function when a port is administratively brought down, this function should
fully disable a given switch port. DSA takes care of marking the port with
``BR_STATE_DISABLED`` and propagating changes to the hardware if this port is
diff --git a/Documentation/networking/dsa/lan9303.rst b/Documentation/networking/dsa/lan9303.rst
index e3c820db28ad..ab81b4e0139e 100644
--- a/Documentation/networking/dsa/lan9303.rst
+++ b/Documentation/networking/dsa/lan9303.rst
@@ -4,7 +4,7 @@ LAN9303 Ethernet switch driver
The LAN9303 is a three port 10/100 Mbps ethernet switch with integrated phys for
the two external ethernet ports. The third port is an RMII/MII interface to a
-host master network interface (e.g. fixed link).
+host conduit network interface (e.g. fixed link).
Driver details
diff --git a/Documentation/networking/dsa/sja1105.rst b/Documentation/networking/dsa/sja1105.rst
index e0219c1452ab..8ab60eef07d4 100644
--- a/Documentation/networking/dsa/sja1105.rst
+++ b/Documentation/networking/dsa/sja1105.rst
@@ -79,7 +79,7 @@ The hardware tags all traffic internally with a port-based VLAN (pvid), or it
decodes the VLAN information from the 802.1Q tag. Advanced VLAN classification
is not possible. Once attributed a VLAN tag, frames are checked against the
port's membership rules and dropped at ingress if they don't match any VLAN.
-This behavior is available when switch ports are enslaved to a bridge with
+This behavior is available when switch ports join a bridge with
``vlan_filtering 1``.
Normally the hardware is not configurable with respect to VLAN awareness, but
@@ -122,7 +122,7 @@ on egress. Using ``vlan_filtering=1``, the behavior is the other way around:
offloaded flows can be steered to TX queues based on the VLAN PCP, but the DSA
net devices are no longer able to do that. To inject frames into a hardware TX
queue with VLAN awareness active, it is necessary to create a VLAN
-sub-interface on the DSA master port, and send normal (0x8100) VLAN-tagged
+sub-interface on the DSA conduit port, and send normal (0x8100) VLAN-tagged
towards the switch, with the VLAN PCP bits set appropriately.
Management traffic (having DMAC 01-80-C2-xx-xx-xx or 01-19-1B-xx-xx-xx) is the
@@ -389,7 +389,7 @@ MDIO bus and PHY management
The SJA1105 does not have an MDIO bus and does not perform in-band AN either.
Therefore there is no link state notification coming from the switch device.
A board would need to hook up the PHYs connected to the switch to any other
-MDIO bus available to Linux within the system (e.g. to the DSA master's MDIO
+MDIO bus available to Linux within the system (e.g. to the DSA conduit's MDIO
bus). Link state management then works by the driver manually keeping in sync
(over SPI commands) the MAC link speed with the settings negotiated by the PHY.
diff --git a/Documentation/networking/filter.rst b/Documentation/networking/filter.rst
index f69da5074860..7d8c5380492f 100644
--- a/Documentation/networking/filter.rst
+++ b/Documentation/networking/filter.rst
@@ -650,8 +650,8 @@ before a conversion to the new layout is being done behind the scenes!
Currently, the classic BPF format is being used for JITing on most
32-bit architectures, whereas x86-64, aarch64, s390x, powerpc64,
-sparc64, arm32, riscv64, riscv32 perform JIT compilation from eBPF
-instruction set.
+sparc64, arm32, riscv64, riscv32, loongarch64 perform JIT compilation
+from eBPF instruction set.
Testing
-------
diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst
index 5b75c3f7a137..683eb42309cc 100644
--- a/Documentation/networking/index.rst
+++ b/Documentation/networking/index.rst
@@ -59,7 +59,6 @@ Contents:
gtp
ila
ioam6-sysctl
- ipddp
ip_dynaddr
ipsec
ip-sysctl
@@ -107,6 +106,7 @@ Contents:
sysfs-tagging
tc-actions-env-rules
tc-queue-filters
+ tcp_ao
tcp-thin
team
timestamping
diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
index a66054d0763a..4dfe0d9a57bb 100644
--- a/Documentation/networking/ip-sysctl.rst
+++ b/Documentation/networking/ip-sysctl.rst
@@ -745,6 +745,13 @@ tcp_comp_sack_nr - INTEGER
Default : 44
+tcp_backlog_ack_defer - BOOLEAN
+ If set, user thread processing socket backlog tries sending
+ one ACK for the whole queue. This helps to avoid potential
+ long latencies at end of a TCP socket syscall.
+
+ Default : true
+
tcp_slow_start_after_idle - BOOLEAN
If set, provide RFC2861 behavior and time out the congestion
window after an idle period. An idle period is defined at
@@ -1176,6 +1183,19 @@ tcp_plb_cong_thresh - INTEGER
Default: 128
+tcp_pingpong_thresh - INTEGER
+ The number of estimated data replies sent for estimated incoming data
+ requests that must happen before TCP considers that a connection is a
+ "ping-pong" (request-response) connection for which delayed
+ acknowledgments can provide benefits.
+
+ This threshold is 1 by default, but some applications may need a higher
+ threshold for optimal performance.
+
+ Possible Values: 1 - 255
+
+ Default: 1
+
UDP variables
=============
@@ -2304,6 +2324,17 @@ accept_ra_pinfo - BOOLEAN
- enabled if accept_ra is enabled.
- disabled if accept_ra is disabled.
+ra_honor_pio_life - BOOLEAN
+ Whether to use RFC4862 Section 5.5.3e to determine the valid
+ lifetime of an address matching a prefix sent in a Router
+ Advertisement Prefix Information Option.
+
+ - If enabled, the PIO valid lifetime will always be honored.
+ - If disabled, RFC4862 section 5.5.3e is used to determine
+ the valid lifetime of the address.
+
+ Default: 0 (disabled)
+
accept_ra_rt_info_min_plen - INTEGER
Minimum prefix length of Route Information in RA.
@@ -2471,12 +2502,18 @@ use_tempaddr - INTEGER
* -1 (for point-to-point devices and loopback devices)
temp_valid_lft - INTEGER
- valid lifetime (in seconds) for temporary addresses.
+ valid lifetime (in seconds) for temporary addresses. If less than the
+ minimum required lifetime (typically 5 seconds), temporary addresses
+ will not be created.
Default: 172800 (2 days)
temp_prefered_lft - INTEGER
- Preferred lifetime (in seconds) for temporary addresses.
+ Preferred lifetime (in seconds) for temporary addresses. If
+ temp_prefered_lft is less than the minimum required lifetime (typically
+ 5 seconds), the preferred lifetime is the minimum required. If
+ temp_prefered_lft is greater than temp_valid_lft, the preferred lifetime
+ is temp_valid_lft.
Default: 86400 (1 day)
diff --git a/Documentation/networking/ipddp.rst b/Documentation/networking/ipddp.rst
deleted file mode 100644
index be7091b77927..000000000000
--- a/Documentation/networking/ipddp.rst
+++ /dev/null
@@ -1,78 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=========================================================
-AppleTalk-IP Decapsulation and AppleTalk-IP Encapsulation
-=========================================================
-
-Documentation ipddp.c
-
-This file is written by Jay Schulist <jschlst@samba.org>
-
-Introduction
-------------
-
-AppleTalk-IP (IPDDP) is the method computers connected to AppleTalk
-networks can use to communicate via IP. AppleTalk-IP is simply IP datagrams
-inside AppleTalk packets.
-
-Through this driver you can either allow your Linux box to communicate
-IP over an AppleTalk network or you can provide IP gatewaying functions
-for your AppleTalk users.
-
-You can currently encapsulate or decapsulate AppleTalk-IP on LocalTalk,
-EtherTalk and PPPTalk. The only limit on the protocol is that of what
-kernel AppleTalk layer and drivers are available.
-
-Each mode requires its own user space software.
-
-Compiling AppleTalk-IP Decapsulation/Encapsulation
-==================================================
-
-AppleTalk-IP decapsulation needs to be compiled into your kernel. You
-will need to turn on AppleTalk-IP driver support. Then you will need to
-select ONE of the two options; IP to AppleTalk-IP encapsulation support or
-AppleTalk-IP to IP decapsulation support. If you compile the driver
-statically you will only be able to use the driver for the function you have
-enabled in the kernel. If you compile the driver as a module you can
-select what mode you want it to run in via a module loading param.
-ipddp_mode=1 for AppleTalk-IP encapsulation and ipddp_mode=2 for
-AppleTalk-IP to IP decapsulation.
-
-Basic instructions for user space tools
-=======================================
-
-I will briefly describe the operation of the tools, but you will
-need to consult the supporting documentation for each set of tools.
-
-Decapsulation - You will need to download a software package called
-MacGate. In this distribution there will be a tool called MacRoute
-which enables you to add routes to the kernel for your Macs by hand.
-Also the tool MacRegGateWay is included to register the
-proper IP Gateway and IP addresses for your machine. Included in this
-distribution is a patch to netatalk-1.4b2+asun2.0a17.2 (available from
-ftp.u.washington.edu/pub/user-supported/asun/) this patch is optional
-but it allows automatic adding and deleting of routes for Macs. (Handy
-for locations with large Mac installations)
-
-Encapsulation - You will need to download a software daemon called ipddpd.
-This software expects there to be an AppleTalk-IP gateway on the network.
-You will also need to add the proper routes to route your Linux box's IP
-traffic out the ipddp interface.
-
-Common Uses of ipddp.c
-----------------------
-Of course AppleTalk-IP decapsulation and encapsulation, but specifically
-decapsulation is being used most for connecting LocalTalk networks to
-IP networks. Although it has been used on EtherTalk networks to allow
-Macs that are only able to tunnel IP over EtherTalk.
-
-Encapsulation has been used to allow a Linux box stuck on a LocalTalk
-network to use IP. It should work equally well if you are stuck on an
-EtherTalk only network.
-
-Further Assistance
--------------------
-You can contact me (Jay Schulist <jschlst@samba.org>) with any
-questions regarding decapsulation or encapsulation. Bradford W. Johnson
-<johns393@maroon.tc.umn.edu> originally wrote the ipddp.c driver for IP
-encapsulation in AppleTalk.
diff --git a/Documentation/networking/mptcp-sysctl.rst b/Documentation/networking/mptcp-sysctl.rst
index 15f1919d640c..69975ce25a02 100644
--- a/Documentation/networking/mptcp-sysctl.rst
+++ b/Documentation/networking/mptcp-sysctl.rst
@@ -25,6 +25,17 @@ add_addr_timeout - INTEGER (seconds)
Default: 120
+close_timeout - INTEGER (seconds)
+ Set the make-after-break timeout: in absence of any close or
+ shutdown syscall, MPTCP sockets will maintain the status
+ unchanged for such time, after the last subflow removal, before
+ moving to TCP_CLOSE.
+
+ The default value matches TCP_TIMEWAIT_LEN. This is a per-namespace
+ sysctl.
+
+ Default: 60
+
checksum_enabled - BOOLEAN
Control whether DSS checksum can be enabled.
diff --git a/Documentation/networking/msg_zerocopy.rst b/Documentation/networking/msg_zerocopy.rst
index b3ea96af9b49..78fb70e748b7 100644
--- a/Documentation/networking/msg_zerocopy.rst
+++ b/Documentation/networking/msg_zerocopy.rst
@@ -7,7 +7,8 @@ Intro
=====
The MSG_ZEROCOPY flag enables copy avoidance for socket send calls.
-The feature is currently implemented for TCP and UDP sockets.
+The feature is currently implemented for TCP, UDP and VSOCK (with
+virtio transport) sockets.
Opportunity and Caveats
@@ -174,7 +175,9 @@ read_notification() call in the previous snippet. A notification
is encoded in the standard error format, sock_extended_err.
The level and type fields in the control data are protocol family
-specific, IP_RECVERR or IPV6_RECVERR.
+specific, IP_RECVERR or IPV6_RECVERR (for TCP or UDP socket).
+For VSOCK socket, cmsg_level will be SOL_VSOCK and cmsg_type will be
+VSOCK_RECVERR.
Error origin is the new type SO_EE_ORIGIN_ZEROCOPY. ee_errno is zero,
as explained before, to avoid blocking read and write system calls on
@@ -235,12 +238,15 @@ Implementation
Loopback
--------
+For TCP and UDP:
Data sent to local sockets can be queued indefinitely if the receive
process does not read its socket. Unbound notification latency is not
acceptable. For this reason all packets generated with MSG_ZEROCOPY
that are looped to a local socket will incur a deferred copy. This
includes looping onto packet sockets (e.g., tcpdump) and tun devices.
+For VSOCK:
+Data path sent to local sockets is the same as for non-local sockets.
Testing
=======
@@ -254,3 +260,6 @@ instance when run with msg_zerocopy.sh between a veth pair across
namespaces, the test will not show any improvement. For testing, the
loopback restriction can be temporarily relaxed by making
skb_orphan_frags_rx identical to skb_orphan_frags.
+
+For VSOCK type of socket example can be found in
+tools/testing/vsock/vsock_test_zerocopy.c.
diff --git a/Documentation/networking/netconsole.rst b/Documentation/networking/netconsole.rst
index 7a9de0568e84..390730a74332 100644
--- a/Documentation/networking/netconsole.rst
+++ b/Documentation/networking/netconsole.rst
@@ -99,9 +99,6 @@ Dynamic reconfiguration:
Dynamic reconfigurability is a useful addition to netconsole that enables
remote logging targets to be dynamically added, removed, or have their
parameters reconfigured at runtime from a configfs-based userspace interface.
-[ Note that the parameters of netconsole targets that were specified/created
-from the boot/module option are not exposed via this interface, and hence
-cannot be modified dynamically. ]
To include this feature, select CONFIG_NETCONSOLE_DYNAMIC when building the
netconsole module (or kernel, if netconsole is built-in).
@@ -155,6 +152,25 @@ You can also update the local interface dynamically. This is especially
useful if you want to use interfaces that have newly come up (and may not
have existed when netconsole was loaded / initialized).
+Netconsole targets defined at boot time (or module load time) with the
+`netconsole=` param are assigned the name `cmdline<index>`. For example, the
+first target in the parameter is named `cmdline0`. You can control and modify
+these targets by creating configfs directories with the matching name.
+
+Let's suppose you have two netconsole targets defined at boot time::
+
+ netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc;4444@10.0.0.1/eth1,9353@10.0.0.3/12:34:56:78:9a:bc
+
+You can modify these targets in runtime by creating the following targets::
+
+ mkdir cmdline0
+ cat cmdline0/remote_ip
+ 10.0.0.2
+
+ mkdir cmdline1
+ cat cmdline1/remote_ip
+ 10.0.0.3
+
Extended console:
=================
diff --git a/Documentation/networking/page_pool.rst b/Documentation/networking/page_pool.rst
index 215ebc92752c..60993cb56b32 100644
--- a/Documentation/networking/page_pool.rst
+++ b/Documentation/networking/page_pool.rst
@@ -58,7 +58,9 @@ a page will cause no race conditions is enough.
.. kernel-doc:: include/net/page_pool/helpers.h
:identifiers: page_pool_put_page page_pool_put_full_page
- page_pool_recycle_direct page_pool_dev_alloc_pages
+ page_pool_recycle_direct page_pool_free_va
+ page_pool_dev_alloc_pages page_pool_dev_alloc_frag
+ page_pool_dev_alloc page_pool_dev_alloc_va
page_pool_get_dma_addr page_pool_get_dma_dir
.. kernel-doc:: net/core/page_pool.c
diff --git a/Documentation/networking/pktgen.rst b/Documentation/networking/pktgen.rst
index 1225f0f63ff0..c945218946e1 100644
--- a/Documentation/networking/pktgen.rst
+++ b/Documentation/networking/pktgen.rst
@@ -178,6 +178,7 @@ Examples::
IPSEC # IPsec encapsulation (needs CONFIG_XFRM)
NODE_ALLOC # node specific memory allocation
NO_TIMESTAMP # disable timestamping
+ SHARED # enable shared SKB
pgset 'flag ![name]' Clear a flag to determine behaviour.
Note that you might need to use single quote in
interactive mode, so that your shell wouldn't expand
@@ -288,6 +289,16 @@ To avoid breaking existing testbed scripts for using AH type and tunnel mode,
you can use "pgset spi SPI_VALUE" to specify which transformation mode
to employ.
+Disable shared SKB
+==================
+By default, SKBs sent by pktgen are shared (user count > 1).
+To test with non-shared SKBs, remove the "SHARED" flag by simply setting::
+
+ pg_set "flag !SHARED"
+
+However, if the "clone_skb" or "burst" parameters are configured, the skb
+still needs to be held by pktgen for further access. Hence the skb must be
+shared.
Current commands and configuration options
==========================================
@@ -357,6 +368,7 @@ Current commands and configuration options
IPSEC
NODE_ALLOC
NO_TIMESTAMP
+ SHARED
spi (ipsec)
diff --git a/Documentation/networking/representors.rst b/Documentation/networking/representors.rst
index ee1f5cd54496..decb39c19b9e 100644
--- a/Documentation/networking/representors.rst
+++ b/Documentation/networking/representors.rst
@@ -162,9 +162,11 @@ How are representors identified?
The representor netdevice should *not* directly refer to a PCIe device (e.g.
through ``net_dev->dev.parent`` / ``SET_NETDEV_DEV()``), either of the
representee or of the switchdev function.
-Instead, it should implement the ``ndo_get_devlink_port()`` netdevice op, which
-the kernel uses to provide the ``phys_switch_id`` and ``phys_port_name`` sysfs
-nodes. (Some legacy drivers implement ``ndo_get_port_parent_id()`` and
+Instead, the driver should use the ``SET_NETDEV_DEVLINK_PORT`` macro to
+assign a devlink port instance to the netdevice before registering the
+netdevice; the kernel uses the devlink port to provide the ``phys_switch_id``
+and ``phys_port_name`` sysfs nodes.
+(Some legacy drivers implement ``ndo_get_port_parent_id()`` and
``ndo_get_phys_port_name()`` directly, but this is deprecated.) See
:ref:`Documentation/networking/devlink/devlink-port.rst <devlink_port>` for the
details of this API.
diff --git a/Documentation/networking/scaling.rst b/Documentation/networking/scaling.rst
index 92c9fb46d6a2..03ae19a689fc 100644
--- a/Documentation/networking/scaling.rst
+++ b/Documentation/networking/scaling.rst
@@ -105,6 +105,48 @@ a separate CPU. For interrupt handling, HT has shown no benefit in
initial tests, so limit the number of queues to the number of CPU cores
in the system.
+Dedicated RSS contexts
+~~~~~~~~~~~~~~~~~~~~~~
+
+Modern NICs support creating multiple co-existing RSS configurations
+which are selected based on explicit matching rules. This can be very
+useful when application wants to constrain the set of queues receiving
+traffic for e.g. a particular destination port or IP address.
+The example below shows how to direct all traffic to TCP port 22
+to queues 0 and 1.
+
+To create an additional RSS context use::
+
+ # ethtool -X eth0 hfunc toeplitz context new
+ New RSS context is 1
+
+Kernel reports back the ID of the allocated context (the default, always
+present RSS context has ID of 0). The new context can be queried and
+modified using the same APIs as the default context::
+
+ # ethtool -x eth0 context 1
+ RX flow hash indirection table for eth0 with 13 RX ring(s):
+ 0: 0 1 2 3 4 5 6 7
+ 8: 8 9 10 11 12 0 1 2
+ [...]
+ # ethtool -X eth0 equal 2 context 1
+ # ethtool -x eth0 context 1
+ RX flow hash indirection table for eth0 with 13 RX ring(s):
+ 0: 0 1 0 1 0 1 0 1
+ 8: 0 1 0 1 0 1 0 1
+ [...]
+
+To make use of the new context direct traffic to it using an n-tuple
+filter::
+
+ # ethtool -N eth0 flow-type tcp6 dst-port 22 context 1
+ Added rule with ID 1023
+
+When done, remove the context and the rule::
+
+ # ethtool -N eth0 delete 1023
+ # ethtool -X eth0 context 1 delete
+
RPS: Receive Packet Steering
============================
diff --git a/Documentation/networking/sfp-phylink.rst b/Documentation/networking/sfp-phylink.rst
index 55b65f607a64..8054d33f449f 100644
--- a/Documentation/networking/sfp-phylink.rst
+++ b/Documentation/networking/sfp-phylink.rst
@@ -200,10 +200,12 @@ this documentation.
when the in-band link state changes - otherwise the link will never
come up.
- The :c:func:`validate` method should mask the supplied supported mask,
- and ``state->advertising`` with the supported ethtool link modes.
- These are the new ethtool link modes, so bitmask operations must be
- used. For an example, see ``drivers/net/ethernet/marvell/mvneta.c``.
+ The :c:func:`mac_get_caps` method is optional, and if provided should
+ return the phylink MAC capabilities that are supported for the passed
+ ``interface`` mode. In general, there is no need to implement this method.
+ Phylink will use these capabilities in combination with permissible
+ capabilities for ``interface`` to determine the allowable ethtool link
+ modes.
The :c:func:`mac_link_state` method is used to read the link state
from the MAC, and report back the settings that the MAC is currently
diff --git a/Documentation/networking/smc-sysctl.rst b/Documentation/networking/smc-sysctl.rst
index 6d8acdbe9be1..769149d98773 100644
--- a/Documentation/networking/smc-sysctl.rst
+++ b/Documentation/networking/smc-sysctl.rst
@@ -44,18 +44,16 @@ smcr_testlink_time - INTEGER
wmem - INTEGER
Initial size of send buffer used by SMC sockets.
- The default value inherits from net.ipv4.tcp_wmem[1].
The minimum value is 16KiB and there is no hard limit for max value, but
only allowed 512KiB for SMC-R and 1MiB for SMC-D.
- Default: 16K
+ Default: 64KiB
rmem - INTEGER
Initial size of receive buffer (RMB) used by SMC sockets.
- The default value inherits from net.ipv4.tcp_rmem[1].
The minimum value is 16KiB and there is no hard limit for max value, but
only allowed 512KiB for SMC-R and 1MiB for SMC-D.
- Default: 128K
+ Default: 64KiB
diff --git a/Documentation/networking/tcp_ao.rst b/Documentation/networking/tcp_ao.rst
new file mode 100644
index 000000000000..8a58321acce7
--- /dev/null
+++ b/Documentation/networking/tcp_ao.rst
@@ -0,0 +1,444 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+========================================================
+TCP Authentication Option Linux implementation (RFC5925)
+========================================================
+
+TCP Authentication Option (TCP-AO) provides a TCP extension aimed at verifying
+segments between trusted peers. It adds a new TCP header option with
+a Message Authentication Code (MAC). MACs are produced from the content
+of a TCP segment using a hashing function with a password known to both peers.
+The intent of TCP-AO is to deprecate TCP-MD5 providing better security,
+key rotation and support for variety of hashing algorithms.
+
+1. Introduction
+===============
+
+.. table:: Short and Limited Comparison of TCP-AO and TCP-MD5
+
+ +----------------------+------------------------+-----------------------+
+ | | TCP-MD5 | TCP-AO |
+ +======================+========================+=======================+
+ |Supported hashing |MD5 |Must support HMAC-SHA1 |
+ |algorithms |(cryptographically weak)|(chosen-prefix attacks)|
+ | | |and CMAC-AES-128 (only |
+ | | |side-channel attacks). |
+ | | |May support any hashing|
+ | | |algorithm. |
+ +----------------------+------------------------+-----------------------+
+ |Length of MACs (bytes)|16 |Typically 12-16. |
+ | | |Other variants that fit|
+ | | |TCP header permitted. |
+ +----------------------+------------------------+-----------------------+
+ |Number of keys per |1 |Many |
+ |TCP connection | | |
+ +----------------------+------------------------+-----------------------+
+ |Possibility to change |Non-practical (both |Supported by protocol |
+ |an active key |peers have to change | |
+ | |them during MSL) | |
+ +----------------------+------------------------+-----------------------+
+ |Protection against |No |Yes: ignoring them |
+ |ICMP 'hard errors' | |by default on |
+ | | |established connections|
+ +----------------------+------------------------+-----------------------+
+ |Protection against |No |Yes: pseudo-header |
+ |traffic-crossing | |includes TCP ports. |
+ |attack | | |
+ +----------------------+------------------------+-----------------------+
+ |Protection against |No |Sequence Number |
+ |replayed TCP segments | |Extension (SNE) and |
+ | | |Initial Sequence |
+ | | |Numbers (ISNs) |
+ +----------------------+------------------------+-----------------------+
+ |Supports |Yes |No. ISNs+SNE are needed|
+ |Connectionless Resets | |to correctly sign RST. |
+ +----------------------+------------------------+-----------------------+
+ |Standards |RFC 2385 |RFC 5925, RFC 5926 |
+ +----------------------+------------------------+-----------------------+
+
+
+1.1 Frequently Asked Questions (FAQ) with references to RFC 5925
+----------------------------------------------------------------
+
+Q: Can either SendID or RecvID be non-unique for the same 4-tuple
+(srcaddr, srcport, dstaddr, dstport)?
+
+A: No [3.1]::
+
+ >> The IDs of MKTs MUST NOT overlap where their TCP connection
+ identifiers overlap.
+
+Q: Can Master Key Tuple (MKT) for an active connection be removed?
+
+A: No, unless it's copied to Transport Control Block (TCB) [3.1]::
+
+ It is presumed that an MKT affecting a particular connection cannot
+ be destroyed during an active connection -- or, equivalently, that
+ its parameters are copied to an area local to the connection (i.e.,
+ instantiated) and so changes would affect only new connections.
+
+Q: If an old MKT needs to be deleted, how should it be done in order
+to not remove it for an active connection? (As it can be still in use
+at any moment later)
+
+A: Not specified by RFC 5925, seems to be a problem for key management
+to ensure that no one uses such MKT before trying to remove it.
+
+Q: Can an old MKT exist forever and be used by another peer?
+
+A: It can, it's a key management task to decide when to remove an old key [6.1]::
+
+ Deciding when to start using a key is a performance issue. Deciding
+ when to remove an MKT is a security issue. Invalid MKTs are expected
+ to be removed. TCP-AO provides no mechanism to coordinate their removal,
+ as we consider this a key management operation.
+
+also [6.1]::
+
+ The only way to avoid reuse of previously used MKTs is to remove the MKT
+ when it is no longer considered permitted.
+
+Linux TCP-AO will try its best to prevent you from removing a key that's
+being used, considering it a key management failure. But since keeping
+an outdated key may become a security issue and as a peer may
+unintentionally prevent the removal of an old key by always setting
+it as RNextKeyID - a forced key removal mechanism is provided, where
+userspace has to supply KeyID to use instead of the one that's being removed
+and the kernel will atomically delete the old key, even if the peer is
+still requesting it. There are no guarantees for force-delete as the peer
+may yet not have the new key - the TCP connection may just break.
+Alternatively, one may choose to shut down the socket.
+
+Q: What happens when a packet is received on a new connection with no known
+MKT's RecvID?
+
+A: RFC 5925 specifies that by default it is accepted with a warning logged, but
+the behaviour can be configured by the user [7.5.1.a]::
+
+ If the segment is a SYN, then this is the first segment of a new
+ connection. Find the matching MKT for this segment, using the segment's
+ socket pair and its TCP-AO KeyID, matched against the MKT's TCP connection
+ identifier and the MKT's RecvID.
+
+ i. If there is no matching MKT, remove TCP-AO from the segment.
+ Proceed with further TCP handling of the segment.
+ NOTE: this presumes that connections that do not match any MKT
+ should be silently accepted, as noted in Section 7.3.
+
+[7.3]::
+
+ >> A TCP-AO implementation MUST allow for configuration of the behavior
+ of segments with TCP-AO but that do not match an MKT. The initial default
+ of this configuration SHOULD be to silently accept such connections.
+ If this is not the desired case, an MKT can be included to match such
+ connections, or the connection can indicate that TCP-AO is required.
+ Alternately, the configuration can be changed to discard segments with
+ the AO option not matching an MKT.
+
+[10.2.b]::
+
+ Connections not matching any MKT do not require TCP-AO. Further, incoming
+ segments with TCP-AO are not discarded solely because they include
+ the option, provided they do not match any MKT.
+
+Note that Linux TCP-AO implementation differs in this aspect. Currently, TCP-AO
+segments with unknown key signatures are discarded with warnings logged.
+
+Q: Does the RFC imply centralized kernel key management in any way?
+(i.e. that a key on all connections MUST be rotated at the same time?)
+
+A: Not specified. MKTs can be managed in userspace, the only relevant part to
+key changes is [7.3]::
+
+ >> All TCP segments MUST be checked against the set of MKTs for matching
+ TCP connection identifiers.
+
+Q: What happens when RNextKeyID requested by a peer is unknown? Should
+the connection be reset?
+
+A: It should not, no action needs to be performed [7.5.2.e]::
+
+ ii. If they differ, determine whether the RNextKeyID MKT is ready.
+
+ 1. If the MKT corresponding to the segment’s socket pair and RNextKeyID
+ is not available, no action is required (RNextKeyID of a received
+ segment needs to match the MKT’s SendID).
+
+Q: How current_key is set and when does it change? It is a user-triggered
+change, or is it by a request from the remote peer? Is it set by the user
+explicitly, or by a matching rule?
+
+A: current_key is set by RNextKeyID [6.1]::
+
+ Rnext_key is changed only by manual user intervention or MKT management
+ protocol operation. It is not manipulated by TCP-AO. Current_key is updated
+ by TCP-AO when processing received TCP segments as discussed in the segment
+ processing description in Section 7.5. Note that the algorithm allows
+ the current_key to change to a new MKT, then change back to a previously
+ used MKT (known as "backing up"). This can occur during an MKT change when
+ segments are received out of order, and is considered a feature of TCP-AO,
+ because reordering does not result in drops.
+
+[7.5.2.e.ii]::
+
+ 2. If the matching MKT corresponding to the segment’s socket pair and
+ RNextKeyID is available:
+
+ a. Set current_key to the RNextKeyID MKT.
+
+Q: If both peers have multiple MKTs matching the connection's socket pair
+(with different KeyIDs), how should the sender/receiver pick KeyID to use?
+
+A: Some mechanism should pick the "desired" MKT [3.3]::
+
+ Multiple MKTs may match a single outgoing segment, e.g., when MKTs
+ are being changed. Those MKTs cannot have conflicting IDs (as noted
+ elsewhere), and some mechanism must determine which MKT to use for each
+ given outgoing segment.
+
+ >> An outgoing TCP segment MUST match at most one desired MKT, indicated
+ by the segment’s socket pair. The segment MAY match multiple MKTs, provided
+ that exactly one MKT is indicated as desired. Other information in
+ the segment MAY be used to determine the desired MKT when multiple MKTs
+ match; such information MUST NOT include values in any TCP option fields.
+
+Q: Can TCP-MD5 connection migrate to TCP-AO (and vice-versa):
+
+A: No [1]::
+
+ TCP MD5-protected connections cannot be migrated to TCP-AO because TCP MD5
+ does not support any changes to a connection’s security algorithm
+ once established.
+
+Q: If all MKTs are removed on a connection, can it become a non-TCP-AO signed
+connection?
+
+A: [7.5.2] doesn't have the same choice as SYN packet handling in [7.5.1.i]
+that would allow accepting segments without a sign (which would be insecure).
+While switching to non-TCP-AO connection is not prohibited directly, it seems
+what the RFC means. Also, there's a requirement for TCP-AO connections to
+always have one current_key [3.3]::
+
+ TCP-AO requires that every protected TCP segment match exactly one MKT.
+
+[3.3]::
+
+ >> An incoming TCP segment including TCP-AO MUST match exactly one MKT,
+ indicated solely by the segment’s socket pair and its TCP-AO KeyID.
+
+[4.4]::
+
+ One or more MKTs. These are the MKTs that match this connection’s
+ socket pair.
+
+Q: Can a non-TCP-AO connection become a TCP-AO-enabled one?
+
+A: No: for already established non-TCP-AO connection it would be impossible
+to switch using TCP-AO as the traffic key generation requires the initial
+sequence numbers. Paraphrasing, starting using TCP-AO would require
+re-establishing the TCP connection.
+
+2. In-kernel MKTs database vs database in userspace
+===================================================
+
+Linux TCP-AO support is implemented using ``setsockopt()s``, in a similar way
+to TCP-MD5. It means that a userspace application that wants to use TCP-AO
+should perform ``setsockopt()`` on a TCP socket when it wants to add,
+remove or rotate MKTs. This approach moves the key management responsibility
+to userspace as well as decisions on corner cases, i.e. what to do if
+the peer doesn't respect RNextKeyID; moving more code to userspace, especially
+responsible for the policy decisions. Besides, it's flexible and scales well
+(with less locking needed than in the case of an in-kernel database). One also
+should keep in mind that mainly intended users are BGP processes, not any
+random applications, which means that compared to IPsec tunnels,
+no transparency is really needed and modern BGP daemons already have
+``setsockopt()s`` for TCP-MD5 support.
+
+.. table:: Considered pros and cons of the approaches
+
+ +----------------------+------------------------+-----------------------+
+ | | ``setsockopt()`` | in-kernel DB |
+ +======================+========================+=======================+
+ | Extendability | ``setsockopt()`` | Netlink messages are |
+ | | commands should be | simple and extendable |
+ | | extendable syscalls | |
+ +----------------------+------------------------+-----------------------+
+ | Required userspace | BGP or any application | could be transparent |
+ | changes | that wants TCP-AO needs| as tunnels, providing |
+ | | to perform | something like |
+ | | ``setsockopt()s`` | ``ip tcpao add key`` |
+ | | and do key management | (delete/show/rotate) |
+ +----------------------+------------------------+-----------------------+
+ |MKTs removal or adding| harder for userspace | harder for kernel |
+ +----------------------+------------------------+-----------------------+
+ | Dump-ability | ``getsockopt()`` | Netlink .dump() |
+ | | | callback |
+ +----------------------+------------------------+-----------------------+
+ | Limits on kernel | equal |
+ | resources/memory | |
+ +----------------------+------------------------+-----------------------+
+ | Scalability | contention on | contention on |
+ | | ``TCP_LISTEN`` sockets | the whole database |
+ +----------------------+------------------------+-----------------------+
+ | Monitoring & warnings| ``TCP_DIAG`` | same Netlink socket |
+ +----------------------+------------------------+-----------------------+
+ | Matching of MKTs | half-problem: only | hard |
+ | | listen sockets | |
+ +----------------------+------------------------+-----------------------+
+
+
+3. uAPI
+=======
+
+Linux provides a set of ``setsockopt()s`` and ``getsockopt()s`` that let
+userspace manage TCP-AO on a per-socket basis. In order to add/delete MKTs
+``TCP_AO_ADD_KEY`` and ``TCP_AO_DEL_KEY`` TCP socket options must be used
+It is not allowed to add a key on an established non-TCP-AO connection
+as well as to remove the last key from TCP-AO connection.
+
+``setsockopt(TCP_AO_DEL_KEY)`` command may specify ``tcp_ao_del::current_key``
++ ``tcp_ao_del::set_current`` and/or ``tcp_ao_del::rnext``
++ ``tcp_ao_del::set_rnext`` which makes such delete "forced": it
+provides userspace a way to delete a key that's being used and atomically set
+another one instead. This is not intended for normal use and should be used
+only when the peer ignores RNextKeyID and keeps requesting/using an old key.
+It provides a way to force-delete a key that's not trusted but may break
+the TCP-AO connection.
+
+The usual/normal key-rotation can be performed with ``setsockopt(TCP_AO_INFO)``.
+It also provides a uAPI to change per-socket TCP-AO settings, such as
+ignoring ICMPs, as well as clear per-socket TCP-AO packet counters.
+The corresponding ``getsockopt(TCP_AO_INFO)`` can be used to get those
+per-socket TCP-AO settings.
+
+Another useful command is ``getsockopt(TCP_AO_GET_KEYS)``. One can use it
+to list all MKTs on a TCP socket or use a filter to get keys for a specific
+peer and/or sndid/rcvid, VRF L3 interface or get current_key/rnext_key.
+
+To repair TCP-AO connections ``setsockopt(TCP_AO_REPAIR)`` is available,
+provided that the user previously has checkpointed/dumped the socket with
+``getsockopt(TCP_AO_REPAIR)``.
+
+A tip here for scaled TCP_LISTEN sockets, that may have some thousands TCP-AO
+keys, is: use filters in ``getsockopt(TCP_AO_GET_KEYS)`` and asynchronous
+delete with ``setsockopt(TCP_AO_DEL_KEY)``.
+
+Linux TCP-AO also provides a bunch of segment counters that can be helpful
+with troubleshooting/debugging issues. Every MKT has good/bad counters
+that reflect how many packets passed/failed verification.
+Each TCP-AO socket has the following counters:
+- for good segments (properly signed)
+- for bad segments (failed TCP-AO verification)
+- for segments with unknown keys
+- for segments where an AO signature was expected, but wasn't found
+- for the number of ignored ICMPs
+
+TCP-AO per-socket counters are also duplicated with per-netns counters,
+exposed with SNMP. Those are ``TCPAOGood``, ``TCPAOBad``, ``TCPAOKeyNotFound``,
+``TCPAORequired`` and ``TCPAODroppedIcmps``.
+
+RFC 5925 very permissively specifies how TCP port matching can be done for
+MKTs::
+
+ TCP connection identifier. A TCP socket pair, i.e., a local IP
+ address, a remote IP address, a TCP local port, and a TCP remote port.
+ Values can be partially specified using ranges (e.g., 2-30), masks
+ (e.g., 0xF0), wildcards (e.g., "*"), or any other suitable indication.
+
+Currently Linux TCP-AO implementation doesn't provide any TCP port matching.
+Probably, port ranges are the most flexible for uAPI, but so far
+not implemented.
+
+4. ``setsockopt()`` vs ``accept()`` race
+========================================
+
+In contrast with TCP-MD5 established connection which has just one key,
+TCP-AO connections may have many keys, which means that accepted connections
+on a listen socket may have any amount of keys as well. As copying all those
+keys on a first properly signed SYN would make the request socket bigger, that
+would be undesirable. Currently, the implementation doesn't copy keys
+to request sockets, but rather look them up on the "parent" listener socket.
+
+The result is that when userspace removes TCP-AO keys, that may break
+not-yet-established connections on request sockets as well as not removing
+keys from sockets that were already established, but not yet ``accept()``'ed,
+hanging in the accept queue.
+
+The reverse is valid as well: if userspace adds a new key for a peer on
+a listener socket, the established sockets in accept queue won't
+have the new keys.
+
+At this moment, the resolution for the two races:
+``setsockopt(TCP_AO_ADD_KEY)`` vs ``accept()``
+and ``setsockopt(TCP_AO_DEL_KEY)`` vs ``accept()`` is delegated to userspace.
+This means that it's expected that userspace would check the MKTs on the socket
+that was returned by ``accept()`` to verify that any key rotation that
+happened on listen socket is reflected on the newly established connection.
+
+This is a similar "do-nothing" approach to TCP-MD5 from the kernel side and
+may be changed later by introducing new flags to ``tcp_ao_add``
+and ``tcp_ao_del``.
+
+Note that this race is rare for it needs TCP-AO key rotation to happen
+during the 3-way handshake for the new TCP connection.
+
+5. Interaction with TCP-MD5
+===========================
+
+A TCP connection can not migrate between TCP-AO and TCP-MD5 options. The
+established sockets that have either AO or MD5 keys are restricted for
+adding keys of the other option.
+
+For listening sockets the picture is different: BGP server may want to receive
+both TCP-AO and (deprecated) TCP-MD5 clients. As a result, both types of keys
+may be added to TCP_CLOSED or TCP_LISTEN sockets. It's not allowed to add
+different types of keys for the same peer.
+
+6. SNE Linux implementation
+===========================
+
+RFC 5925 [6.2] describes the algorithm of how to extend TCP sequence numbers
+with SNE. In short: TCP has to track the previous sequence numbers and set
+sne_flag when the current SEQ number rolls over. The flag is cleared when
+both current and previous SEQ numbers cross 0x7fff, which is 32Kb.
+
+In times when sne_flag is set, the algorithm compares SEQ for each packet with
+0x7fff and if it's higher than 32Kb, it assumes that the packet should be
+verified with SNE before the increment. As a result, there's
+this [0; 32Kb] window, when packets with (SNE - 1) can be accepted.
+
+Linux implementation simplifies this a bit: as the network stack already tracks
+the first SEQ byte that ACK is wanted for (snd_una) and the next SEQ byte that
+is wanted (rcv_nxt) - that's enough information for a rough estimation
+on where in the 4GB SEQ number space both sender and receiver are.
+When they roll over to zero, the corresponding SNE gets incremented.
+
+tcp_ao_compute_sne() is called for each TCP-AO segment. It compares SEQ numbers
+from the segment with snd_una or rcv_nxt and fits the result into a 2GB window around them,
+detecting SEQ numbers rolling over. That simplifies the code a lot and only
+requires SNE numbers to be stored on every TCP-AO socket.
+
+The 2GB window at first glance seems much more permissive compared to
+RFC 5926. But that is only used to pick the correct SNE before/after
+a rollover. It allows more TCP segment replays, but yet all regular
+TCP checks in tcp_sequence() are applied on the verified segment.
+So, it trades a bit more permissive acceptance of replayed/retransmitted
+segments for the simplicity of the algorithm and what seems better behaviour
+for large TCP windows.
+
+7. Links
+========
+
+RFC 5925 The TCP Authentication Option
+ https://www.rfc-editor.org/rfc/pdfrfc/rfc5925.txt.pdf
+
+RFC 5926 Cryptographic Algorithms for the TCP Authentication Option (TCP-AO)
+ https://www.rfc-editor.org/rfc/pdfrfc/rfc5926.txt.pdf
+
+Draft "SHA-2 Algorithm for the TCP Authentication Option (TCP-AO)"
+ https://datatracker.ietf.org/doc/html/draft-nayak-tcp-sha2-03
+
+RFC 2385 Protection of BGP Sessions via the TCP MD5 Signature Option
+ https://www.rfc-editor.org/rfc/pdfrfc/rfc2385.txt.pdf
+
+:Author: Dmitry Safonov <dima@arista.com>
diff --git a/Documentation/networking/xdp-rx-metadata.rst b/Documentation/networking/xdp-rx-metadata.rst
index 25ce72af81c2..205696780b78 100644
--- a/Documentation/networking/xdp-rx-metadata.rst
+++ b/Documentation/networking/xdp-rx-metadata.rst
@@ -105,6 +105,13 @@ bpf_tail_call
Adding programs that access metadata kfuncs to the ``BPF_MAP_TYPE_PROG_ARRAY``
is currently not supported.
+Supported Devices
+=================
+
+It is possible to query which kfunc the particular netdev implements via
+netlink. See ``xdp-rx-metadata-features`` attribute set in
+``Documentation/netlink/specs/netdev.yaml``.
+
Example
=======
diff --git a/Documentation/process/7.AdvancedTopics.rst b/Documentation/process/7.AdvancedTopics.rst
index bf7cbfb4caa5..43291704338e 100644
--- a/Documentation/process/7.AdvancedTopics.rst
+++ b/Documentation/process/7.AdvancedTopics.rst
@@ -146,6 +146,7 @@ pull. The git request-pull command can be helpful in this regard; it will
format the request as other developers expect, and will also check to be
sure that you have remembered to push those changes to the public server.
+.. _development_advancedtopics_reviews:
Reviewing patches
-----------------
@@ -167,6 +168,12 @@ comments as questions rather than criticisms. Asking "how does the lock
get released in this path?" will always work better than stating "the
locking here is wrong."
+Another technique that is useful in case of a disagreement is to ask for others
+to chime in. If a discussion reaches a stalemate after a few exchanges,
+then call for opinions of other reviewers or maintainers. Often those in
+agreement with a reviewer remain silent unless called upon.
+The opinion of multiple people carries exponentially more weight.
+
Different developers will review code from different points of view. Some
are mostly concerned with coding style and whether code lines have trailing
white space. Others will focus primarily on whether the change implemented
@@ -176,3 +183,14 @@ security issues, duplication of code found elsewhere, adequate
documentation, adverse effects on performance, user-space ABI changes, etc.
All types of review, if they lead to better code going into the kernel, are
welcome and worthwhile.
+
+There is no strict requirement to use specific tags like ``Reviewed-by``.
+In fact reviews in plain English are more informative and encouraged
+even when a tag is provided, e.g. "I looked at aspects A, B and C of this
+submission and it looks good to me."
+Some form of a review message or reply is obviously necessary otherwise
+maintainers will not know that the reviewer has looked at the patch at all!
+
+Last but not least patch review may become a negative process, focused
+on pointing out problems. Please throw in a compliment once in a while,
+particularly for newbies!
diff --git a/Documentation/process/backporting.rst b/Documentation/process/backporting.rst
new file mode 100644
index 000000000000..e1a6ea0a1e8a
--- /dev/null
+++ b/Documentation/process/backporting.rst
@@ -0,0 +1,604 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================================
+Backporting and conflict resolution
+===================================
+
+:Author: Vegard Nossum <vegard.nossum@oracle.com>
+
+.. contents::
+ :local:
+ :depth: 3
+ :backlinks: none
+
+Introduction
+============
+
+Some developers may never really have to deal with backporting patches,
+merging branches, or resolving conflicts in their day-to-day work, so
+when a merge conflict does pop up, it can be daunting. Luckily,
+resolving conflicts is a skill like any other, and there are many useful
+techniques you can use to make the process smoother and increase your
+confidence in the result.
+
+This document aims to be a comprehensive, step-by-step guide to
+backporting and conflict resolution.
+
+Applying the patch to a tree
+============================
+
+Sometimes the patch you are backporting already exists as a git commit,
+in which case you just cherry-pick it directly using
+``git cherry-pick``. However, if the patch comes from an email, as it
+often does for the Linux kernel, you will need to apply it to a tree
+using ``git am``.
+
+If you've ever used ``git am``, you probably already know that it is
+quite picky about the patch applying perfectly to your source tree. In
+fact, you've probably had nightmares about ``.rej`` files and trying to
+edit the patch to make it apply.
+
+It is strongly recommended to instead find an appropriate base version
+where the patch applies cleanly and *then* cherry-pick it over to your
+destination tree, as this will make git output conflict markers and let
+you resolve conflicts with the help of git and any other conflict
+resolution tools you might prefer to use. For example, if you want to
+apply a patch that just arrived on LKML to an older stable kernel, you
+can apply it to the most recent mainline kernel and then cherry-pick it
+to your older stable branch.
+
+It's generally better to use the exact same base as the one the patch
+was generated from, but it doesn't really matter that much as long as it
+applies cleanly and isn't too far from the original base. The only
+problem with applying the patch to the "wrong" base is that it may pull
+in more unrelated changes in the context of the diff when cherry-picking
+it to the older branch.
+
+A good reason to prefer ``git cherry-pick`` over ``git am`` is that git
+knows the precise history of an existing commit, so it will know when
+code has moved around and changed the line numbers; this in turn makes
+it less likely to apply the patch to the wrong place (which can result
+in silent mistakes or messy conflicts).
+
+If you are using `b4`_. and you are applying the patch directly from an
+email, you can use ``b4 am`` with the options ``-g``/``--guess-base``
+and ``-3``/``--prep-3way`` to do some of this automatically (see the
+`b4 presentation`_ for more information). However, the rest of this
+article will assume that you are doing a plain ``git cherry-pick``.
+
+.. _b4: https://people.kernel.org/monsieuricon/introducing-b4-and-patch-attestation
+.. _b4 presentation: https://youtu.be/mF10hgVIx9o?t=2996
+
+Once you have the patch in git, you can go ahead and cherry-pick it into
+your source tree. Don't forget to cherry-pick with ``-x`` if you want a
+written record of where the patch came from!
+
+Note that if you are submiting a patch for stable, the format is
+slightly different; the first line after the subject line needs tobe
+either::
+
+ commit <upstream commit> upstream
+
+or::
+
+ [ Upstream commit <upstream commit> ]
+
+Resolving conflicts
+===================
+
+Uh-oh; the cherry-pick failed with a vaguely threatening message::
+
+ CONFLICT (content): Merge conflict
+
+What to do now?
+
+In general, conflicts appear when the context of the patch (i.e., the
+lines being changed and/or the lines surrounding the changes) doesn't
+match what's in the tree you are trying to apply the patch *to*.
+
+For backports, what likely happened was that the branch you are
+backporting from contains patches not in the branch you are backporting
+to. However, the reverse is also possible. In any case, the result is a
+conflict that needs to be resolved.
+
+If your attempted cherry-pick fails with a conflict, git automatically
+edits the files to include so-called conflict markers showing you where
+the conflict is and how the two branches have diverged. Resolving the
+conflict typically means editing the end result in such a way that it
+takes into account these other commits.
+
+Resolving the conflict can be done either by hand in a regular text
+editor or using a dedicated conflict resolution tool.
+
+Many people prefer to use their regular text editor and edit the
+conflict directly, as it may be easier to understand what you're doing
+and to control the final result. There are definitely pros and cons to
+each method, and sometimes there's value in using both.
+
+We will not cover using dedicated merge tools here beyond providing some
+pointers to various tools that you could use:
+
+- `Emacs Ediff mode <https://www.emacswiki.org/emacs/EdiffMode>`__
+- `vimdiff/gvimdiff <https://linux.die.net/man/1/vimdiff>`__
+- `KDiff3 <http://kdiff3.sourceforge.net/>`__
+- `TortoiseMerge <https://tortoisesvn.net/TortoiseMerge.html>`__
+- `Meld <https://meldmerge.org/help/>`__
+- `P4Merge <https://www.perforce.com/products/helix-core-apps/merge-diff-tool-p4merge>`__
+- `Beyond Compare <https://www.scootersoftware.com/>`__
+- `IntelliJ <https://www.jetbrains.com/help/idea/resolve-conflicts.html>`__
+- `VSCode <https://code.visualstudio.com/docs/editor/versioncontrol>`__
+
+To configure git to work with these, see ``git mergetool --help`` or
+the official `git-mergetool documentation`_.
+
+.. _git-mergetool documentation: https://git-scm.com/docs/git-mergetool
+
+Prerequisite patches
+--------------------
+
+Most conflicts happen because the branch you are backporting to is
+missing some patches compared to the branch you are backporting *from*.
+In the more general case (such as merging two independent branches),
+development could have happened on either branch, or the branches have
+simply diverged -- perhaps your older branch had some other backports
+applied to it that themselves needed conflict resolutions, causing a
+divergence.
+
+It's important to always identify the commit or commits that caused the
+conflict, as otherwise you cannot be confident in the correctness of
+your resolution. As an added bonus, especially if the patch is in an
+area you're not that famliar with, the changelogs of these commits will
+often give you the context to understand the code and potential problems
+or pitfalls with your conflict resolution.
+
+git log
+~~~~~~~
+
+A good first step is to look at ``git log`` for the file that has the
+conflict -- this is usually sufficient when there aren't a lot of
+patches to the file, but may get confusing if the file is big and
+frequently patched. You should run ``git log`` on the range of commits
+between your currently checked-out branch (``HEAD``) and the parent of
+the patch you are picking (``<commit>``), i.e.::
+
+ git log HEAD..<commit>^ -- <path>
+
+Even better, if you want to restrict this output to a single function
+(because that's where the conflict appears), you can use the following
+syntax::
+
+ git log -L:'\<function\>':<path> HEAD..<commit>^
+
+.. note::
+ The ``\<`` and ``\>`` around the function name ensure that the
+ matches are anchored on a word boundary. This is important, as this
+ part is actually a regex and git only follows the first match, so
+ if you use ``-L:thread_stack:kernel/fork.c`` it may only give you
+ results for the function ``try_release_thread_stack_to_cache`` even
+ though there are many other functions in that file containing the
+ string ``thread_stack`` in their names.
+
+Another useful option for ``git log`` is ``-G``, which allows you to
+filter on certain strings appearing in the diffs of the commits you are
+listing::
+
+ git log -G'regex' HEAD..<commit>^ -- <path>
+
+This can also be a handy way to quickly find when something (e.g. a
+function call or a variable) was changed, added, or removed. The search
+string is a regular expression, which means you can potentially search
+for more specific things like assignments to a specific struct member::
+
+ git log -G'\->index\>.*='
+
+git blame
+~~~~~~~~~
+
+Another way to find prerequisite commits (albeit only the most recent
+one for a given conflict) is to run ``git blame``. In this case, you
+need to run it against the parent commit of the patch you are
+cherry-picking and the file where the conflict appared, i.e.::
+
+ git blame <commit>^ -- <path>
+
+This command also accepts the ``-L`` argument (for restricting the
+output to a single function), but in this case you specify the filename
+at the end of the command as usual::
+
+ git blame -L:'\<function\>' <commit>^ -- <path>
+
+Navigate to the place where the conflict occurred. The first column of
+the blame output is the commit ID of the patch that added a given line
+of code.
+
+It might be a good idea to ``git show`` these commits and see if they
+look like they might be the source of the conflict. Sometimes there will
+be more than one of these commits, either because multiple commits
+changed different lines of the same conflict area *or* because multiple
+subsequent patches changed the same line (or lines) multiple times. In
+the latter case, you may have to run ``git blame`` again and specify the
+older version of the file to look at in order to dig further back in
+the history of the file.
+
+Prerequisite vs. incidental patches
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Having found the patch that caused the conflict, you need to determine
+whether it is a prerequisite for the patch you are backporting or
+whether it is just incidental and can be skipped. An incidental patch
+would be one that touches the same code as the patch you are
+backporting, but does not change the semantics of the code in any
+material way. For example, a whitespace cleanup patch is completely
+incidental -- likewise, a patch that simply renames a function or a
+variable would be incidental as well. On the other hand, if the function
+being changed does not even exist in your current branch then this would
+not be incidental at all and you need to carefully consider whether the
+patch adding the function should be cherry-picked first.
+
+If you find that there is a necessary prerequisite patch, then you need
+to stop and cherry-pick that instead. If you've already resolved some
+conflicts in a different file and don't want to do it again, you can
+create a temporary copy of that file.
+
+To abort the current cherry-pick, go ahead and run
+``git cherry-pick --abort``, then restart the cherry-picking process
+with the commit ID of the prerequisite patch instead.
+
+Understanding conflict markers
+------------------------------
+
+Combined diffs
+~~~~~~~~~~~~~~
+
+Let's say you've decided against picking (or reverting) additional
+patches and you just want to resolve the conflict. Git will have
+inserted conflict markers into your file. Out of the box, this will look
+something like::
+
+ <<<<<<< HEAD
+ this is what's in your current tree before cherry-picking
+ =======
+ this is what the patch wants it to be after cherry-picking
+ >>>>>>> <commit>... title
+
+This is what you would see if you opened the file in your editor.
+However, if you were to run ``git diff`` without any arguments, the
+output would look something like this::
+
+ $ git diff
+ [...]
+ ++<<<<<<<< HEAD
+ +this is what's in your current tree before cherry-picking
+ ++========
+ + this is what the patch wants it to be after cherry-picking
+ ++>>>>>>>> <commit>... title
+
+When you are resolving a conflict, the behavior of ``git diff`` differs
+from its normal behavior. Notice the two columns of diff markers
+instead of the usual one; this is a so-called "`combined diff`_", here
+showing the 3-way diff (or diff-of-diffs) between
+
+#. the current branch (before cherry-picking) and the current working
+ directory, and
+#. the current branch (before cherry-picking) and the file as it looks
+ after the original patch has been applied.
+
+.. _combined diff: https://git-scm.com/docs/diff-format#_combined_diff_format
+
+
+Better diffs
+~~~~~~~~~~~~
+
+3-way combined diffs include all the other changes that happened to the
+file between your current branch and the branch you are cherry-picking
+from. While this is useful for spotting other changes that you need to
+take into account, this also makes the output of ``git diff`` somewhat
+intimidating and difficult to read. You may instead prefer to run
+``git diff HEAD`` (or ``git diff --ours``) which shows only the diff
+between the current branch before cherry-picking and the current working
+directory. It looks like this::
+
+ $ git diff HEAD
+ [...]
+ +<<<<<<<< HEAD
+ this is what's in your current tree before cherry-picking
+ +========
+ +this is what the patch wants it to be after cherry-picking
+ +>>>>>>>> <commit>... title
+
+As you can see, this reads just like any other diff and makes it clear
+which lines are in the current branch and which lines are being added
+because they are part of the merge conflict or the patch being
+cherry-picked.
+
+Merge styles and diff3
+~~~~~~~~~~~~~~~~~~~~~~
+
+The default conflict marker style shown above is known as the ``merge``
+style. There is also another style available, known as the ``diff3``
+style, which looks like this::
+
+ <<<<<<< HEAD
+ this is what is in your current tree before cherry-picking
+ ||||||| parent of <commit> (title)
+ this is what the patch expected to find there
+ =======
+ this is what the patch wants it to be after being applied
+ >>>>>>> <commit> (title)
+
+As you can see, this has 3 parts instead of 2, and includes what git
+expected to find there but didn't. It is *highly recommended* to use
+this conflict style as it makes it much clearer what the patch actually
+changed; i.e., it allows you to compare the before-and-after versions
+of the file for the commit you are cherry-picking. This allows you to
+make better decisions about how to resolve the conflict.
+
+To change conflict marker styles, you can use the following command::
+
+ git config merge.conflictStyle diff3
+
+There is a third option, ``zdiff3``, introduced in `Git 2.35`_,
+which has the same 3 sections as ``diff3``, but where common lines have
+been trimmed off, making the conflict area smaller in some cases.
+
+.. _Git 2.35: https://github.blog/2022-01-24-highlights-from-git-2-35/
+
+Iterating on conflict resolutions
+---------------------------------
+
+The first step in any conflict resolution process is to understand the
+patch you are backporting. For the Linux kernel this is especially
+important, since an incorrect change can lead to the whole system
+crashing -- or worse, an undetected security vulnerability.
+
+Understanding the patch can be easy or difficult depending on the patch
+itself, the changelog, and your familiarity with the code being changed.
+However, a good question for every change (or every hunk of the patch)
+might be: "Why is this hunk in the patch?" The answers to these
+questions will inform your conflict resolution.
+
+Resolution process
+~~~~~~~~~~~~~~~~~~
+
+Sometimes the easiest thing to do is to just remove all but the first
+part of the conflict, leaving the file essentially unchanged, and apply
+the changes by hand. Perhaps the patch is changing a function call
+argument from ``0`` to ``1`` while a conflicting change added an
+entirely new (and insignificant) parameter to the end of the parameter
+list; in that case, it's easy enough to change the argument from ``0``
+to ``1`` by hand and leave the rest of the arguments alone. This
+technique of manually applying changes is mostly useful if the conflict
+pulled in a lot of unrelated context that you don't really need to care
+about.
+
+For particularly nasty conflicts with many conflict markers, you can use
+``git add`` or ``git add -i`` to selectively stage your resolutions to
+get them out of the way; this also lets you use ``git diff HEAD`` to
+always see what remains to be resolved or ``git diff --cached`` to see
+what your patch looks like so far.
+
+Dealing with file renames
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+One of the most annoying things that can happen while backporting a
+patch is discovering that one of the files being patched has been
+renamed, as that typically means git won't even put in conflict markers,
+but will just throw up its hands and say (paraphrased): "Unmerged path!
+You do the work..."
+
+There are generally a few ways to deal with this. If the patch to the
+renamed file is small, like a one-line change, the easiest thing is to
+just go ahead and apply the change by hand and be done with it. On the
+other hand, if the change is big or complicated, you definitely don't
+want to do it by hand.
+
+As a first pass, you can try something like this, which will lower the
+rename detection threshold to 30% (by default, git uses 50%, meaning
+that two files need to have at least 50% in common for it to consider
+an add-delete pair to be a potential rename)::
+
+ git cherry-pick -strategy=recursive -Xrename-threshold=30
+
+Sometimes the right thing to do will be to also backport the patch that
+did the rename, but that's definitely not the most common case. Instead,
+what you can do is to temporarily rename the file in the branch you're
+backporting to (using ``git mv`` and committing the result), restart the
+attempt to cherry-pick the patch, rename the file back (``git mv`` and
+committing again), and finally squash the result using ``git rebase -i``
+(see the `rebase tutorial`_) so it appears as a single commit when you
+are done.
+
+.. _rebase tutorial: https://medium.com/@slamflipstrom/a-beginners-guide-to-squashing-commits-with-git-rebase-8185cf6e62ec
+
+Gotchas
+-------
+
+Function arguments
+~~~~~~~~~~~~~~~~~~
+
+Pay attention to changing function arguments! It's easy to gloss over
+details and think that two lines are the same but actually they differ
+in some small detail like which variable was passed as an argument
+(especially if the two variables are both a single character that look
+the same, like i and j).
+
+Error handling
+~~~~~~~~~~~~~~
+
+If you cherry-pick a patch that includes a ``goto`` statement (typically
+for error handling), it is absolutely imperative to double check that
+the target label is still correct in the branch you are backporting to.
+The same goes for added ``return``, ``break``, and ``continue``
+statements.
+
+Error handling is typically located at the bottom of the function, so it
+may not be part of the conflict even though could have been changed by
+other patches.
+
+A good way to ensure that you review the error paths is to always use
+``git diff -W`` and ``git show -W`` (AKA ``--function-context``) when
+inspecting your changes. For C code, this will show you the whole
+function that's being changed in a patch. One of the things that often
+go wrong during backports is that something else in the function changed
+on either of the branches that you're backporting from or to. By
+including the whole function in the diff you get more context and can
+more easily spot problems that might otherwise go unnoticed.
+
+Refactored code
+~~~~~~~~~~~~~~~
+
+Something that happens quite often is that code gets refactored by
+"factoring out" a common code sequence or pattern into a helper
+function. When backporting patches to an area where such a refactoring
+has taken place, you effectively need to do the reverse when
+backporting: a patch to a single location may need to be applied to
+multiple locations in the backported version. (One giveaway for this
+scenario is that a function was renamed -- but that's not always the
+case.)
+
+To avoid incomplete backports, it's worth trying to figure out if the
+patch fixes a bug that appears in more than one place. One way to do
+this would be to use ``git grep``. (This is actually a good idea to do
+in general, not just for backports.) If you do find that the same kind
+of fix would apply to other places, it's also worth seeing if those
+places exist upstream -- if they don't, it's likely the patch may need
+to be adjusted. ``git log`` is your friend to figure out what happened
+to these areas as ``git blame`` won't show you code that has been
+removed.
+
+If you do find other instances of the same pattern in the upstream tree
+and you're not sure whether it's also a bug, it may be worth asking the
+patch author. It's not uncommon to find new bugs during backporting!
+
+Verifying the result
+====================
+
+colordiff
+---------
+
+Having committed a conflict-free new patch, you can now compare your
+patch to the original patch. It is highly recommended that you use a
+tool such as `colordiff`_ that can show two files side by side and color
+them according to the changes between them::
+
+ colordiff -yw -W 200 <(git diff -W <upstream commit>^-) <(git diff -W HEAD^-) | less -SR
+
+.. _colordiff: https://www.colordiff.org/
+
+Here, ``-y`` means to do a side-by-side comparison; ``-w`` ignores
+whitespace, and ``-W 200`` sets the width of the output (as otherwise it
+will use 130 by default, which is often a bit too little).
+
+The ``rev^-`` syntax is a handy shorthand for ``rev^..rev``, essentially
+giving you just the diff for that single commit; also see
+the official `git rev-parse documentation`_.
+
+.. _git rev-parse documentation: https://git-scm.com/docs/git-rev-parse#_other_rev_parent_shorthand_notations
+
+Again, note the inclusion of ``-W`` for ``git diff``; this ensures that
+you will see the full function for any function that has changed.
+
+One incredibly important thing that colordiff does is to highlight lines
+that are different. For example, if an error-handling ``goto`` has
+changed labels between the original and backported patch, colordiff will
+show these side-by-side but highlighted in a different color. Thus, it
+is easy to see that the two ``goto`` statements are jumping to different
+labels. Likewise, lines that were not modified by either patch but
+differ in the context will also be highlighted and thus stand out during
+a manual inspection.
+
+Of course, this is just a visual inspection; the real test is building
+and running the patched kernel (or program).
+
+Build testing
+-------------
+
+We won't cover runtime testing here, but it can be a good idea to build
+just the files touched by the patch as a quick sanity check. For the
+Linux kernel you can build single files like this, assuming you have the
+``.config`` and build environment set up correctly::
+
+ make path/to/file.o
+
+Note that this won't discover linker errors, so you should still do a
+full build after verifying that the single file compiles. By compiling
+the single file first you can avoid having to wait for a full build *in
+case* there are compiler errors in any of the files you've changed.
+
+Runtime testing
+---------------
+
+Even a successful build or boot test is not necessarily enough to rule
+out a missing dependency somewhere. Even though the chances are small,
+there could be code changes where two independent changes to the same
+file result in no conflicts, no compile-time errors, and runtime errors
+only in exceptional cases.
+
+One concrete example of this was a pair of patches to the system call
+entry code where the first patch saved/restored a register and a later
+patch made use of the same register somewhere in the middle of this
+sequence. Since there was no overlap between the changes, one could
+cherry-pick the second patch, have no conflicts, and believe that
+everything was fine, when in fact the code was now scribbling over an
+unsaved register.
+
+Although the vast majority of errors will be caught during compilation
+or by superficially exercising the code, the only way to *really* verify
+a backport is to review the final patch with the same level of scrutiny
+as you would (or should) give to any other patch. Having unit tests and
+regression tests or other types of automatic testing can help increase
+the confidence in the correctness of a backport.
+
+Submitting backports to stable
+==============================
+
+As the stable maintainers try to cherry-pick mainline fixes onto their
+stable kernels, they may send out emails asking for backports when when
+encountering conflicts, see e.g.
+<https://lore.kernel.org/stable/2023101528-jawed-shelving-071a@gregkh/>.
+These emails typically include the exact steps you need to cherry-pick
+the patch to the correct tree and submit the patch.
+
+One thing to make sure is that your changelog conforms to the expected
+format::
+
+ <original patch title>
+
+ [ Upstream commit <mainline rev> ]
+
+ <rest of the original changelog>
+ [ <summary of the conflicts and their resolutions> ]
+ Signed-off-by: <your name and email>
+
+The "Upstream commit" line is sometimes slightly different depending on
+the stable version. Older version used this format::
+
+ commit <mainline rev> upstream.
+
+It is most common to indicate the kernel version the patch applies to
+in the email subject line (using e.g.
+``git send-email --subject-prefix='PATCH 6.1.y'``), but you can also put
+it in the Signed-off-by:-area or below the ``---`` line.
+
+The stable maintainers expect separate submissions for each active
+stable version, and each submission should also be tested separately.
+
+A few final words of advice
+===========================
+
+1) Approach the backporting process with humility.
+2) Understand the patch you are backporting; this means reading both
+ the changelog and the code.
+3) Be honest about your confidence in the result when submitting the
+ patch.
+4) Ask relevant maintainers for explicit acks.
+
+Examples
+========
+
+The above shows roughly the idealized process of backporting a patch.
+For a more concrete example, see this video tutorial where two patches
+are backported from mainline to stable:
+`Backporting Linux Kernel Patches`_.
+
+.. _Backporting Linux Kernel Patches: https://youtu.be/sBR7R1V2FeA
diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst
index b48da698d6f2..bb96ca0f774b 100644
--- a/Documentation/process/changes.rst
+++ b/Documentation/process/changes.rst
@@ -31,7 +31,7 @@ you probably needn't concern yourself with pcmciautils.
====================== =============== ========================================
GNU C 5.1 gcc --version
Clang/LLVM (optional) 11.0.0 clang --version
-Rust (optional) 1.71.1 rustc --version
+Rust (optional) 1.73.0 rustc --version
bindgen (optional) 0.65.1 bindgen --version
GNU make 3.82 make --version
bash 4.2 bash --version
diff --git a/Documentation/process/embargoed-hardware-issues.rst b/Documentation/process/embargoed-hardware-issues.rst
index ac7c52f130c9..31000f075707 100644
--- a/Documentation/process/embargoed-hardware-issues.rst
+++ b/Documentation/process/embargoed-hardware-issues.rst
@@ -25,15 +25,15 @@ Contact
The Linux kernel hardware security team is separate from the regular Linux
kernel security team.
-The team only handles the coordination of embargoed hardware security
-issues. Reports of pure software security bugs in the Linux kernel are not
+The team only handles developing fixes for embargoed hardware security
+issues. Reports of pure software security bugs in the Linux kernel are not
handled by this team and the reporter will be guided to contact the regular
Linux kernel security team (:ref:`Documentation/admin-guide/
<securitybugs>`) instead.
The team can be contacted by email at <hardware-security@kernel.org>. This
-is a private list of security officers who will help you to coordinate an
-issue according to our documented process.
+is a private list of security officers who will help you to coordinate a
+fix according to our documented process.
The list is encrypted and email to the list can be sent by either PGP or
S/MIME encrypted and must be signed with the reporter's PGP key or S/MIME
@@ -132,11 +132,11 @@ other hardware could be affected.
The hardware security team will provide an incident-specific encrypted
mailing-list which will be used for initial discussion with the reporter,
-further disclosure and coordination.
+further disclosure, and coordination of fixes.
The hardware security team will provide the disclosing party a list of
developers (domain experts) who should be informed initially about the
-issue after confirming with the developers that they will adhere to this
+issue after confirming with the developers that they will adhere to this
Memorandum of Understanding and the documented process. These developers
form the initial response team and will be responsible for handling the
issue after initial contact. The hardware security team is supporting the
@@ -209,13 +209,18 @@ five work days this is taken as silent acknowledgement.
After acknowledgement or resolution of an objection the expert is disclosed
by the incident team and brought into the development process.
+List participants may not communicate about the issue outside of the
+private mailing list. List participants may not use any shared resources
+(e.g. employer build farms, CI systems, etc) when working on patches.
+
Coordinated release
"""""""""""""""""""
The involved parties will negotiate the date and time where the embargo
ends. At that point the prepared mitigations are integrated into the
-relevant kernel trees and published.
+relevant kernel trees and published. There is no pre-notification process:
+fixes are published in public and available to everyone at the same time.
While we understand that hardware security issues need coordinated embargo
time, the embargo time should be constrained to the minimum time which is
diff --git a/Documentation/process/index.rst b/Documentation/process/index.rst
index b501cd977053..a1daa309b58d 100644
--- a/Documentation/process/index.rst
+++ b/Documentation/process/index.rst
@@ -66,12 +66,13 @@ lack of a better place.
:maxdepth: 1
applying-patches
+ backporting
adding-syscalls
magic-number
volatile-considered-harmful
botching-up-ioctls
clang-format
- ../riscv/patch-acceptance
+ ../arch/riscv/patch-acceptance
../core-api/unaligned-memory-access
.. only:: subproject and html
diff --git a/Documentation/process/maintainer-netdev.rst b/Documentation/process/maintainer-netdev.rst
index 09dcf6377c27..84ee60fceef2 100644
--- a/Documentation/process/maintainer-netdev.rst
+++ b/Documentation/process/maintainer-netdev.rst
@@ -193,9 +193,23 @@ Review timelines
Generally speaking, the patches get triaged quickly (in less than
48h). But be patient, if your patch is active in patchwork (i.e. it's
listed on the project's patch list) the chances it was missed are close to zero.
-Asking the maintainer for status updates on your
-patch is a good way to ensure your patch is ignored or pushed to the
-bottom of the priority list.
+
+The high volume of development on netdev makes reviewers move on
+from discussions relatively quickly. New comments and replies
+are very unlikely to arrive after a week of silence. If a patch
+is no longer active in patchwork and the thread went idle for more
+than a week - clarify the next steps and/or post the next version.
+
+For RFC postings specifically, if nobody responded in a week - reviewers
+either missed the posting or have no strong opinions. If the code is ready,
+repost as a PATCH.
+
+Emails saying just "ping" or "bump" are considered rude. If you can't figure
+out the status of the patch from patchwork or where the discussion has
+landed - describe your best guess and ask if it's correct. For example::
+
+ I don't understand what the next steps are. Person X seems to be unhappy
+ with A, should I do B and repost the patches?
.. _Changes requested:
@@ -441,6 +455,21 @@ in a way which would break what would normally be considered uAPI.
new ``netdevsim`` features must be accompanied by selftests under
``tools/testing/selftests/``.
+Reviewer guidance
+-----------------
+
+Reviewing other people's patches on the list is highly encouraged,
+regardless of the level of expertise. For general guidance and
+helpful tips please see :ref:`development_advancedtopics_reviews`.
+
+It's safe to assume that netdev maintainers know the community and the level
+of expertise of the reviewers. The reviewers should not be concerned about
+their comments impeding or derailing the patch flow.
+
+Less experienced reviewers are highly encouraged to do more in-depth
+review of submissions and not focus exclusively on trivial or subjective
+matters like code formatting, tags etc.
+
Testimonials / feedback
-----------------------
diff --git a/Documentation/process/security-bugs.rst b/Documentation/process/security-bugs.rst
index 5a6993795bd2..692a3ba56cca 100644
--- a/Documentation/process/security-bugs.rst
+++ b/Documentation/process/security-bugs.rst
@@ -66,15 +66,32 @@ lifted, in perpetuity.
Coordination with other groups
------------------------------
-The kernel security team strongly recommends that reporters of potential
-security issues NEVER contact the "linux-distros" mailing list until
-AFTER discussing it with the kernel security team. Do not Cc: both
-lists at once. You may contact the linux-distros mailing list after a
-fix has been agreed on and you fully understand the requirements that
-doing so will impose on you and the kernel community.
-
-The different lists have different goals and the linux-distros rules do
-not contribute to actually fixing any potential security problems.
+While the kernel security team solely focuses on getting bugs fixed,
+other groups focus on fixing issues in distros and coordinating
+disclosure between operating system vendors. Coordination is usually
+handled by the "linux-distros" mailing list and disclosure by the
+public "oss-security" mailing list, both of which are closely related
+and presented in the linux-distros wiki:
+<https://oss-security.openwall.org/wiki/mailing-lists/distros>
+
+Please note that the respective policies and rules are different since
+the 3 lists pursue different goals. Coordinating between the kernel
+security team and other teams is difficult since for the kernel security
+team occasional embargoes (as subject to a maximum allowed number of
+days) start from the availability of a fix, while for "linux-distros"
+they start from the initial post to the list regardless of the
+availability of a fix.
+
+As such, the kernel security team strongly recommends that as a reporter
+of a potential security issue you DO NOT contact the "linux-distros"
+mailing list UNTIL a fix is accepted by the affected code's maintainers
+and you have read the distros wiki page above and you fully understand
+the requirements that contacting "linux-distros" will impose on you and
+the kernel community. This also means that in general it doesn't make
+sense to Cc: both lists at once, except maybe for coordination if and
+while an accepted fix has not yet been merged. In other words, until a
+fix is accepted do not Cc: "linux-distros", and after it's merged do not
+Cc: the kernel security team.
CVE assignment
--------------
diff --git a/Documentation/process/stable-kernel-rules.rst b/Documentation/process/stable-kernel-rules.rst
index 41f1e07abfdf..1704f1c686d0 100644
--- a/Documentation/process/stable-kernel-rules.rst
+++ b/Documentation/process/stable-kernel-rules.rst
@@ -101,6 +101,19 @@ comment:
git cherry-pick fd21073
git cherry-pick <this commit>
+ Note that for a patch series, you do not have to list as prerequisites the
+ patches present in the series itself. For example, if you have the following
+ patch series:
+
+ .. code-block:: none
+
+ patch1
+ patch2
+
+ where patch2 depends on patch1, you do not have to list patch1 as
+ prerequisite of patch2 if you have already marked patch1 for stable
+ inclusion.
+
* For patches that may have kernel version prerequisites specify them using
the following format in the sign-off area:
diff --git a/Documentation/process/submitting-patches.rst b/Documentation/process/submitting-patches.rst
index efac910e2659..86d346bcb8ef 100644
--- a/Documentation/process/submitting-patches.rst
+++ b/Documentation/process/submitting-patches.rst
@@ -327,6 +327,8 @@ politely and address the problems they have pointed out. When sending a next
version, add a ``patch changelog`` to the cover letter or to individual patches
explaining difference against previous submission (see
:ref:`the_canonical_patch_format`).
+Notify people that commented on your patch about new versions by adding them to
+the patches CC list.
See Documentation/process/email-clients.rst for recommendations on email
clients and mailing list etiquette.
@@ -366,10 +368,10 @@ busy people and may not get to your patch right away.
Once upon a time, patches used to disappear into the void without comment,
but the development process works more smoothly than that now. You should
-receive comments within a week or so; if that does not happen, make sure
-that you have sent your patches to the right place. Wait for a minimum of
-one week before resubmitting or pinging reviewers - possibly longer during
-busy times like merge windows.
+receive comments within a few weeks (typically 2-3); if that does not
+happen, make sure that you have sent your patches to the right place.
+Wait for a minimum of one week before resubmitting or pinging reviewers
+- possibly longer during busy times like merge windows.
It's also ok to resend the patch or the patch series after a couple of
weeks with the word "RESEND" added to the subject line::
diff --git a/Documentation/rust/general-information.rst b/Documentation/rust/general-information.rst
index 49029ee82e55..081397827a7e 100644
--- a/Documentation/rust/general-information.rst
+++ b/Documentation/rust/general-information.rst
@@ -29,7 +29,7 @@ target with the same invocation used for compilation, e.g.::
To read the docs locally in your web browser, run e.g.::
- xdg-open rust/doc/kernel/index.html
+ xdg-open Documentation/output/rust/rustdoc/kernel/index.html
To learn about how to write the documentation, please see coding-guidelines.rst.
diff --git a/Documentation/rust/index.rst b/Documentation/rust/index.rst
index e599be2cec9b..965f2db529e0 100644
--- a/Documentation/rust/index.rst
+++ b/Documentation/rust/index.rst
@@ -6,6 +6,25 @@ Rust
Documentation related to Rust within the kernel. To start using Rust
in the kernel, please read the quick-start.rst guide.
+
+The Rust experiment
+-------------------
+
+The Rust support was merged in v6.1 into mainline in order to help in
+determining whether Rust as a language was suitable for the kernel, i.e. worth
+the tradeoffs.
+
+Currently, the Rust support is primarily intended for kernel developers and
+maintainers interested in the Rust support, so that they can start working on
+abstractions and drivers, as well as helping the development of infrastructure
+and tools.
+
+If you are an end user, please note that there are currently no in-tree
+drivers/modules suitable or intended for production use, and that the Rust
+support is still in development/experimental, especially for certain kernel
+configurations.
+
+
.. only:: rustdoc and html
You can also browse `rustdoc documentation <rustdoc/kernel/index.html>`_.
diff --git a/Documentation/scheduler/sched-arch.rst b/Documentation/scheduler/sched-arch.rst
index 505cd27f9a92..ed07efea7d02 100644
--- a/Documentation/scheduler/sched-arch.rst
+++ b/Documentation/scheduler/sched-arch.rst
@@ -10,7 +10,7 @@ Context switch
By default, the switch_to arch function is called with the runqueue
locked. This is usually not a problem unless switch_to may need to
take the runqueue lock. This is usually due to a wake up operation in
-the context switch. See arch/ia64/include/asm/switch_to.h for an example.
+the context switch.
To request the scheduler call switch_to with the runqueue unlocked,
you must `#define __ARCH_WANT_UNLOCKED_CTXSW` in a header file
@@ -68,7 +68,5 @@ Possible arch/ problems
Possible arch problems I found (and either tried to fix or didn't):
-ia64 - is safe_halt call racy vs interrupts? (does it sleep?) (See #4a)
-
sparc - IRQs on at this point(?), change local_irq_save to _disable.
- TODO: needs secondary CPUs to disable preempt (See #1)
diff --git a/Documentation/scheduler/sched-capacity.rst b/Documentation/scheduler/sched-capacity.rst
index e2c1cf743158..de414b33dd2a 100644
--- a/Documentation/scheduler/sched-capacity.rst
+++ b/Documentation/scheduler/sched-capacity.rst
@@ -39,14 +39,15 @@ per Hz, leading to::
-------------------
Two different capacity values are used within the scheduler. A CPU's
-``capacity_orig`` is its maximum attainable capacity, i.e. its maximum
-attainable performance level. A CPU's ``capacity`` is its ``capacity_orig`` to
-which some loss of available performance (e.g. time spent handling IRQs) is
-subtracted.
+``original capacity`` is its maximum attainable capacity, i.e. its maximum
+attainable performance level. This original capacity is returned by
+the function arch_scale_cpu_capacity(). A CPU's ``capacity`` is its ``original
+capacity`` to which some loss of available performance (e.g. time spent
+handling IRQs) is subtracted.
Note that a CPU's ``capacity`` is solely intended to be used by the CFS class,
-while ``capacity_orig`` is class-agnostic. The rest of this document will use
-the term ``capacity`` interchangeably with ``capacity_orig`` for the sake of
+while ``original capacity`` is class-agnostic. The rest of this document will use
+the term ``capacity`` interchangeably with ``original capacity`` for the sake of
brevity.
1.3 Platform examples
diff --git a/Documentation/scheduler/sched-energy.rst b/Documentation/scheduler/sched-energy.rst
index fc853c8cc346..70e2921ef725 100644
--- a/Documentation/scheduler/sched-energy.rst
+++ b/Documentation/scheduler/sched-energy.rst
@@ -359,32 +359,9 @@ in milli-Watts or in an 'abstract scale'.
6.3 - Energy Model complexity
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The task wake-up path is very latency-sensitive. When the EM of a platform is
-too complex (too many CPUs, too many performance domains, too many performance
-states, ...), the cost of using it in the wake-up path can become prohibitive.
-The energy-aware wake-up algorithm has a complexity of:
-
- C = Nd * (Nc + Ns)
-
-with: Nd the number of performance domains; Nc the number of CPUs; and Ns the
-total number of OPPs (ex: for two perf. domains with 4 OPPs each, Ns = 8).
-
-A complexity check is performed at the root domain level, when scheduling
-domains are built. EAS will not start on a root domain if its C happens to be
-higher than the completely arbitrary EM_MAX_COMPLEXITY threshold (2048 at the
-time of writing).
-
-If you really want to use EAS but the complexity of your platform's Energy
-Model is too high to be used with a single root domain, you're left with only
-two possible options:
-
- 1. split your system into separate, smaller, root domains using exclusive
- cpusets and enable EAS locally on each of them. This option has the
- benefit to work out of the box but the drawback of preventing load
- balance between root domains, which can result in an unbalanced system
- overall;
- 2. submit patches to reduce the complexity of the EAS wake-up algorithm,
- hence enabling it to cope with larger EMs in reasonable time.
+EAS does not impose any complexity limit on the number of PDs/OPPs/CPUs but
+restricts the number of CPUs to EM_MAX_NUM_CPUS to prevent overflows during
+the energy estimation.
6.4 - Schedutil governor
diff --git a/Documentation/scheduler/sched-rt-group.rst b/Documentation/scheduler/sched-rt-group.rst
index 655a096ec8fb..d685609ed3d7 100644
--- a/Documentation/scheduler/sched-rt-group.rst
+++ b/Documentation/scheduler/sched-rt-group.rst
@@ -39,10 +39,10 @@ Most notable:
1.1 The problem
---------------
-Realtime scheduling is all about determinism, a group has to be able to rely on
+Real-time scheduling is all about determinism, a group has to be able to rely on
the amount of bandwidth (eg. CPU time) being constant. In order to schedule
-multiple groups of realtime tasks, each group must be assigned a fixed portion
-of the CPU time available. Without a minimum guarantee a realtime group can
+multiple groups of real-time tasks, each group must be assigned a fixed portion
+of the CPU time available. Without a minimum guarantee a real-time group can
obviously fall short. A fuzzy upper limit is of no use since it cannot be
relied upon. Which leaves us with just the single fixed portion.
@@ -50,14 +50,14 @@ relied upon. Which leaves us with just the single fixed portion.
----------------
CPU time is divided by means of specifying how much time can be spent running
-in a given period. We allocate this "run time" for each realtime group which
-the other realtime groups will not be permitted to use.
+in a given period. We allocate this "run time" for each real-time group which
+the other real-time groups will not be permitted to use.
-Any time not allocated to a realtime group will be used to run normal priority
+Any time not allocated to a real-time group will be used to run normal priority
tasks (SCHED_OTHER). Any allocated run time not used will also be picked up by
SCHED_OTHER.
-Let's consider an example: a frame fixed realtime renderer must deliver 25
+Let's consider an example: a frame fixed real-time renderer must deliver 25
frames a second, which yields a period of 0.04s per frame. Now say it will also
have to play some music and respond to input, leaving it with around 80% CPU
time dedicated for the graphics. We can then give this group a run time of 0.8
@@ -70,7 +70,7 @@ needs only about 3% CPU time to do so, it can do with a 0.03 * 0.005s =
of 0.00015s.
The remaining CPU time will be used for user input and other tasks. Because
-realtime tasks have explicitly allocated the CPU time they need to perform
+real-time tasks have explicitly allocated the CPU time they need to perform
their tasks, buffer underruns in the graphics or audio can be eliminated.
NOTE: the above example is not fully implemented yet. We still
@@ -87,18 +87,20 @@ lack an EDF scheduler to make non-uniform periods usable.
The system wide settings are configured under the /proc virtual file system:
/proc/sys/kernel/sched_rt_period_us:
- The scheduling period that is equivalent to 100% CPU bandwidth
+ The scheduling period that is equivalent to 100% CPU bandwidth.
/proc/sys/kernel/sched_rt_runtime_us:
- A global limit on how much time realtime scheduling may use. Even without
- CONFIG_RT_GROUP_SCHED enabled, this will limit time reserved to realtime
- processes. With CONFIG_RT_GROUP_SCHED it signifies the total bandwidth
- available to all realtime groups.
+ A global limit on how much time real-time scheduling may use. This is always
+ less or equal to the period_us, as it denotes the time allocated from the
+ period_us for the real-time tasks. Even without CONFIG_RT_GROUP_SCHED enabled,
+ this will limit time reserved to real-time processes. With
+ CONFIG_RT_GROUP_SCHED=y it signifies the total bandwidth available to all
+ real-time groups.
* Time is specified in us because the interface is s32. This gives an
operating range from 1us to about 35 minutes.
* sched_rt_period_us takes values from 1 to INT_MAX.
- * sched_rt_runtime_us takes values from -1 to (INT_MAX - 1).
+ * sched_rt_runtime_us takes values from -1 to sched_rt_period_us.
* A run time of -1 specifies runtime == period, ie. no limit.
@@ -108,7 +110,7 @@ The system wide settings are configured under the /proc virtual file system:
The default values for sched_rt_period_us (1000000 or 1s) and
sched_rt_runtime_us (950000 or 0.95s). This gives 0.05s to be used by
SCHED_OTHER (non-RT tasks). These defaults were chosen so that a run-away
-realtime tasks will not lock up the machine but leave a little time to recover
+real-time tasks will not lock up the machine but leave a little time to recover
it. By setting runtime to -1 you'd get the old behaviour back.
By default all bandwidth is assigned to the root group and new groups get the
@@ -116,10 +118,10 @@ period from /proc/sys/kernel/sched_rt_period_us and a run time of 0. If you
want to assign bandwidth to another group, reduce the root group's bandwidth
and assign some or all of the difference to another group.
-Realtime group scheduling means you have to assign a portion of total CPU
-bandwidth to the group before it will accept realtime tasks. Therefore you will
-not be able to run realtime tasks as any user other than root until you have
-done that, even if the user has the rights to run processes with realtime
+Real-time group scheduling means you have to assign a portion of total CPU
+bandwidth to the group before it will accept real-time tasks. Therefore you will
+not be able to run real-time tasks as any user other than root until you have
+done that, even if the user has the rights to run processes with real-time
priority!
diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst
index 6ed8d2fa6f9e..59f8fc106cb0 100644
--- a/Documentation/security/index.rst
+++ b/Documentation/security/index.rst
@@ -6,6 +6,7 @@ Security Documentation
:maxdepth: 1
credentials
+ snp-tdx-threat-model
IMA-templates
keys/index
lsm
diff --git a/Documentation/security/snp-tdx-threat-model.rst b/Documentation/security/snp-tdx-threat-model.rst
new file mode 100644
index 000000000000..ec66f2ed80c9
--- /dev/null
+++ b/Documentation/security/snp-tdx-threat-model.rst
@@ -0,0 +1,253 @@
+======================================================
+Confidential Computing in Linux for x86 virtualization
+======================================================
+
+.. contents:: :local:
+
+By: Elena Reshetova <elena.reshetova@intel.com> and Carlos Bilbao <carlos.bilbao@amd.com>
+
+Motivation
+==========
+
+Kernel developers working on confidential computing for virtualized
+environments in x86 operate under a set of assumptions regarding the Linux
+kernel threat model that differ from the traditional view. Historically,
+the Linux threat model acknowledges attackers residing in userspace, as
+well as a limited set of external attackers that are able to interact with
+the kernel through various networking or limited HW-specific exposed
+interfaces (USB, thunderbolt). The goal of this document is to explain
+additional attack vectors that arise in the confidential computing space
+and discuss the proposed protection mechanisms for the Linux kernel.
+
+Overview and terminology
+========================
+
+Confidential Computing (CoCo) is a broad term covering a wide range of
+security technologies that aim to protect the confidentiality and integrity
+of data in use (vs. data at rest or data in transit). At its core, CoCo
+solutions provide a Trusted Execution Environment (TEE), where secure data
+processing can be performed and, as a result, they are typically further
+classified into different subtypes depending on the SW that is intended
+to be run in TEE. This document focuses on a subclass of CoCo technologies
+that are targeting virtualized environments and allow running Virtual
+Machines (VM) inside TEE. From now on in this document will be referring
+to this subclass of CoCo as 'Confidential Computing (CoCo) for the
+virtualized environments (VE)'.
+
+CoCo, in the virtualization context, refers to a set of HW and/or SW
+technologies that allow for stronger security guarantees for the SW running
+inside a CoCo VM. Namely, confidential computing allows its users to
+confirm the trustworthiness of all SW pieces to include in its reduced
+Trusted Computing Base (TCB) given its ability to attest the state of these
+trusted components.
+
+While the concrete implementation details differ between technologies, all
+available mechanisms aim to provide increased confidentiality and
+integrity for the VM's guest memory and execution state (vCPU registers),
+more tightly controlled guest interrupt injection, as well as some
+additional mechanisms to control guest-host page mapping. More details on
+the x86-specific solutions can be found in
+:doc:`Intel Trust Domain Extensions (TDX) </arch/x86/tdx>` and
+`AMD Memory Encryption <https://www.amd.com/system/files/techdocs/sev-snp-strengthening-vm-isolation-with-integrity-protection-and-more.pdf>`_.
+
+The basic CoCo guest layout includes the host, guest, the interfaces that
+communicate guest and host, a platform capable of supporting CoCo VMs, and
+a trusted intermediary between the guest VM and the underlying platform
+that acts as a security manager. The host-side virtual machine monitor
+(VMM) typically consists of a subset of traditional VMM features and
+is still in charge of the guest lifecycle, i.e. create or destroy a CoCo
+VM, manage its access to system resources, etc. However, since it
+typically stays out of CoCo VM TCB, its access is limited to preserve the
+security objectives.
+
+In the following diagram, the "<--->" lines represent bi-directional
+communication channels or interfaces between the CoCo security manager and
+the rest of the components (data flow for guest, host, hardware) ::
+
+ +-------------------+ +-----------------------+
+ | CoCo guest VM |<---->| |
+ +-------------------+ | |
+ | Interfaces | | CoCo security manager |
+ +-------------------+ | |
+ | Host VMM |<---->| |
+ +-------------------+ | |
+ | |
+ +--------------------+ | |
+ | CoCo platform |<--->| |
+ +--------------------+ +-----------------------+
+
+The specific details of the CoCo security manager vastly diverge between
+technologies. For example, in some cases, it will be implemented in HW
+while in others it may be pure SW.
+
+Existing Linux kernel threat model
+==================================
+
+The overall components of the current Linux kernel threat model are::
+
+ +-----------------------+ +-------------------+
+ | |<---->| Userspace |
+ | | +-------------------+
+ | External attack | | Interfaces |
+ | vectors | +-------------------+
+ | |<---->| Linux Kernel |
+ | | +-------------------+
+ +-----------------------+ +-------------------+
+ | Bootloader/BIOS |
+ +-------------------+
+ +-------------------+
+ | HW platform |
+ +-------------------+
+
+There is also communication between the bootloader and the kernel during
+the boot process, but this diagram does not represent it explicitly. The
+"Interfaces" box represents the various interfaces that allow
+communication between kernel and userspace. This includes system calls,
+kernel APIs, device drivers, etc.
+
+The existing Linux kernel threat model typically assumes execution on a
+trusted HW platform with all of the firmware and bootloaders included on
+its TCB. The primary attacker resides in the userspace, and all of the data
+coming from there is generally considered untrusted, unless userspace is
+privileged enough to perform trusted actions. In addition, external
+attackers are typically considered, including those with access to enabled
+external networks (e.g. Ethernet, Wireless, Bluetooth), exposed hardware
+interfaces (e.g. USB, Thunderbolt), and the ability to modify the contents
+of disks offline.
+
+Regarding external attack vectors, it is interesting to note that in most
+cases external attackers will try to exploit vulnerabilities in userspace
+first, but that it is possible for an attacker to directly target the
+kernel; particularly if the host has physical access. Examples of direct
+kernel attacks include the vulnerabilities CVE-2019-19524, CVE-2022-0435
+and CVE-2020-24490.
+
+Confidential Computing threat model and its security objectives
+===============================================================
+
+Confidential Computing adds a new type of attacker to the above list: a
+potentially misbehaving host (which can also include some part of a
+traditional VMM or all of it), which is typically placed outside of the
+CoCo VM TCB due to its large SW attack surface. It is important to note
+that this doesn’t imply that the host or VMM are intentionally
+malicious, but that there exists a security value in having a small CoCo
+VM TCB. This new type of adversary may be viewed as a more powerful type
+of external attacker, as it resides locally on the same physical machine
+(in contrast to a remote network attacker) and has control over the guest
+kernel communication with most of the HW::
+
+ +------------------------+
+ | CoCo guest VM |
+ +-----------------------+ | +-------------------+ |
+ | |<--->| | Userspace | |
+ | | | +-------------------+ |
+ | External attack | | | Interfaces | |
+ | vectors | | +-------------------+ |
+ | |<--->| | Linux Kernel | |
+ | | | +-------------------+ |
+ +-----------------------+ | +-------------------+ |
+ | | Bootloader/BIOS | |
+ +-----------------------+ | +-------------------+ |
+ | |<--->+------------------------+
+ | | | Interfaces |
+ | | +------------------------+
+ | CoCo security |<--->| Host/Host-side VMM |
+ | manager | +------------------------+
+ | | +------------------------+
+ | |<--->| CoCo platform |
+ +-----------------------+ +------------------------+
+
+While traditionally the host has unlimited access to guest data and can
+leverage this access to attack the guest, the CoCo systems mitigate such
+attacks by adding security features like guest data confidentiality and
+integrity protection. This threat model assumes that those features are
+available and intact.
+
+The **Linux kernel CoCo VM security objectives** can be summarized as follows:
+
+1. Preserve the confidentiality and integrity of CoCo guest's private
+memory and registers.
+
+2. Prevent privileged escalation from a host into a CoCo guest Linux kernel.
+While it is true that the host (and host-side VMM) requires some level of
+privilege to create, destroy, or pause the guest, part of the goal of
+preventing privileged escalation is to ensure that these operations do not
+provide a pathway for attackers to gain access to the guest's kernel.
+
+The above security objectives result in two primary **Linux kernel CoCo
+VM assets**:
+
+1. Guest kernel execution context.
+2. Guest kernel private memory.
+
+The host retains full control over the CoCo guest resources, and can deny
+access to them at any time. Examples of resources include CPU time, memory
+that the guest can consume, network bandwidth, etc. Because of this, the
+host Denial of Service (DoS) attacks against CoCo guests are beyond the
+scope of this threat model.
+
+The **Linux CoCo VM attack surface** is any interface exposed from a CoCo
+guest Linux kernel towards an untrusted host that is not covered by the
+CoCo technology SW/HW protection. This includes any possible
+side-channels, as well as transient execution side channels. Examples of
+explicit (not side-channel) interfaces include accesses to port I/O, MMIO
+and DMA interfaces, access to PCI configuration space, VMM-specific
+hypercalls (towards Host-side VMM), access to shared memory pages,
+interrupts allowed to be injected into the guest kernel by the host, as
+well as CoCo technology-specific hypercalls, if present. Additionally, the
+host in a CoCo system typically controls the process of creating a CoCo
+guest: it has a method to load into a guest the firmware and bootloader
+images, the kernel image together with the kernel command line. All of this
+data should also be considered untrusted until its integrity and
+authenticity is established via attestation.
+
+The table below shows a threat matrix for the CoCo guest Linux kernel but
+does not discuss potential mitigation strategies. The matrix refers to
+CoCo-specific versions of the guest, host and platform.
+
+.. list-table:: CoCo Linux guest kernel threat matrix
+ :widths: auto
+ :align: center
+ :header-rows: 1
+
+ * - Threat name
+ - Threat description
+
+ * - Guest malicious configuration
+ - A misbehaving host modifies one of the following guest's
+ configuration:
+
+ 1. Guest firmware or bootloader
+
+ 2. Guest kernel or module binaries
+
+ 3. Guest command line parameters
+
+ This allows the host to break the integrity of the code running
+ inside a CoCo guest, and violates the CoCo security objectives.
+
+ * - CoCo guest data attacks
+ - A misbehaving host retains full control of the CoCo guest's data
+ in-transit between the guest and the host-managed physical or
+ virtual devices. This allows any attack against confidentiality,
+ integrity or freshness of such data.
+
+ * - Malformed runtime input
+ - A misbehaving host injects malformed input via any communication
+ interface used by the guest's kernel code. If the code is not
+ prepared to handle this input correctly, this can result in a host
+ --> guest kernel privilege escalation. This includes traditional
+ side-channel and/or transient execution attack vectors.
+
+ * - Malicious runtime input
+ - A misbehaving host injects a specific input value via any
+ communication interface used by the guest's kernel code. The
+ difference with the previous attack vector (malformed runtime input)
+ is that this input is not malformed, but its value is crafted to
+ impact the guest's kernel security. Examples of such inputs include
+ providing a malicious time to the guest or the entropy to the guest
+ random number generator. Additionally, the timing of such events can
+ be an attack vector on its own, if it results in a particular guest
+ kernel action (i.e. processing of a host-injected interrupt).
+ resistant to supplied host input.
+
diff --git a/Documentation/sound/soc/codec-to-codec.rst b/Documentation/sound/soc/codec-to-codec.rst
index 4eaa9a0c41fc..0418521b6e03 100644
--- a/Documentation/sound/soc/codec-to-codec.rst
+++ b/Documentation/sound/soc/codec-to-codec.rst
@@ -70,7 +70,8 @@ file:
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.ignore_suspend = 1,
- .params = &dsp_codec_params,
+ .c2c_params = &dsp_codec_params,
+ .num_c2c_params = 1,
},
{
.name = "DSP-CODEC",
@@ -81,12 +82,13 @@ file:
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.ignore_suspend = 1,
- .params = &dsp_codec_params,
+ .c2c_params = &dsp_codec_params,
+ .num_c2c_params = 1,
},
Above code snippet is motivated from sound/soc/samsung/speyside.c.
-Note the "params" callback which lets the dapm know that this
+Note the "c2c_params" callback which lets the dapm know that this
dai_link is a codec to codec connection.
In dapm core a route is created between cpu_dai playback widget
diff --git a/Documentation/sound/soc/dpcm.rst b/Documentation/sound/soc/dpcm.rst
index 77f67ded53de..2d7ad1d91504 100644
--- a/Documentation/sound/soc/dpcm.rst
+++ b/Documentation/sound/soc/dpcm.rst
@@ -368,7 +368,8 @@ The machine driver sets some additional parameters to the DAI link i.e.
.codec_name = "modem",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
- .params = &dai_params,
+ .c2c_params = &dai_params,
+ .num_c2c_params = 1,
}
< ... more DAI links here ... >
diff --git a/Documentation/sphinx/cdomain.py b/Documentation/sphinx/cdomain.py
index a99716bf44b5..4eb150bf509c 100644
--- a/Documentation/sphinx/cdomain.py
+++ b/Documentation/sphinx/cdomain.py
@@ -93,7 +93,7 @@ def markup_ctype_refs(match):
#
RE_expr = re.compile(r':c:(expr|texpr):`([^\`]+)`')
def markup_c_expr(match):
- return '\ ``' + match.group(2) + '``\ '
+ return '\\ ``' + match.group(2) + '``\\ '
#
# Parse Sphinx 3.x C markups, replacing them by backward-compatible ones
@@ -151,7 +151,7 @@ class CObject(Base_CObject):
def handle_func_like_macro(self, sig, signode):
u"""Handles signatures of function-like macros.
- If the objtype is 'function' and the the signature ``sig`` is a
+ If the objtype is 'function' and the signature ``sig`` is a
function-like macro, the name of the macro is returned. Otherwise
``False`` is returned. """
diff --git a/Documentation/sphinx/kernel_abi.py b/Documentation/sphinx/kernel_abi.py
index b5feb5b1d905..49797c55479c 100644
--- a/Documentation/sphinx/kernel_abi.py
+++ b/Documentation/sphinx/kernel_abi.py
@@ -138,7 +138,7 @@ class KernelCmd(Directive):
code_block += "\n " + l
lines = code_block + "\n\n"
- line_regex = re.compile("^\.\. LINENO (\S+)\#([0-9]+)$")
+ line_regex = re.compile(r"^\.\. LINENO (\S+)\#([0-9]+)$")
ln = 0
n = 0
f = fname
diff --git a/Documentation/sphinx/kernel_feat.py b/Documentation/sphinx/kernel_feat.py
index 27b701ed3681..b5fa2f0542a5 100644
--- a/Documentation/sphinx/kernel_feat.py
+++ b/Documentation/sphinx/kernel_feat.py
@@ -104,7 +104,7 @@ class KernelFeat(Directive):
lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
- line_regex = re.compile("^\.\. FILE (\S+)$")
+ line_regex = re.compile(r"^\.\. FILE (\S+)$")
out_lines = ""
diff --git a/Documentation/sphinx/kerneldoc.py b/Documentation/sphinx/kerneldoc.py
index 9395892c7ba3..7acf09963daa 100644
--- a/Documentation/sphinx/kerneldoc.py
+++ b/Documentation/sphinx/kerneldoc.py
@@ -130,7 +130,7 @@ class KernelDocDirective(Directive):
result = ViewList()
lineoffset = 0;
- line_regex = re.compile("^\.\. LINENO ([0-9]+)$")
+ line_regex = re.compile(r"^\.\. LINENO ([0-9]+)$")
for line in lines:
match = line_regex.search(line)
if match:
@@ -138,7 +138,7 @@ class KernelDocDirective(Directive):
lineoffset = int(match.group(1)) - 1
# we must eat our comments since the upset the markup
else:
- doc = env.srcdir + "/" + env.docname + ":" + str(self.lineno)
+ doc = str(env.srcdir) + "/" + env.docname + ":" + str(self.lineno)
result.append(line, doc + ": " + filename, lineoffset)
lineoffset += 1
diff --git a/Documentation/sphinx/kfigure.py b/Documentation/sphinx/kfigure.py
index cefdbb7e7523..13e885bbd499 100644
--- a/Documentation/sphinx/kfigure.py
+++ b/Documentation/sphinx/kfigure.py
@@ -309,7 +309,7 @@ def convert_image(img_node, translator, src_fname=None):
if dst_fname:
# the builder needs not to copy one more time, so pop it if exists.
translator.builder.images.pop(img_node['uri'], None)
- _name = dst_fname[len(translator.builder.outdir) + 1:]
+ _name = dst_fname[len(str(translator.builder.outdir)) + 1:]
if isNewer(dst_fname, src_fname):
kernellog.verbose(app,
diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py
index 328b3631a585..dcad0fff4723 100755
--- a/Documentation/sphinx/maintainers_include.py
+++ b/Documentation/sphinx/maintainers_include.py
@@ -77,7 +77,7 @@ class MaintainersInclude(Include):
line = line.rstrip()
# Linkify all non-wildcard refs to ReST files in Documentation/.
- pat = '(Documentation/([^\s\?\*]*)\.rst)'
+ pat = r'(Documentation/([^\s\?\*]*)\.rst)'
m = re.search(pat, line)
if m:
# maintainers.rst is in a subdirectory, so include "../".
@@ -90,11 +90,11 @@ class MaintainersInclude(Include):
output = "| %s" % (line.replace("\\", "\\\\"))
# Look for and record field letter to field name mappings:
# R: Designated *reviewer*: FullName <address@domain>
- m = re.search("\s(\S):\s", line)
+ m = re.search(r"\s(\S):\s", line)
if m:
field_letter = m.group(1)
if field_letter and not field_letter in fields:
- m = re.search("\*([^\*]+)\*", line)
+ m = re.search(r"\*([^\*]+)\*", line)
if m:
fields[field_letter] = m.group(1)
elif subsystems:
@@ -112,7 +112,7 @@ class MaintainersInclude(Include):
field_content = ""
# Collapse whitespace in subsystem name.
- heading = re.sub("\s+", " ", line)
+ heading = re.sub(r"\s+", " ", line)
output = output + "%s\n%s" % (heading, "~" * len(heading))
field_prev = ""
else:
diff --git a/Documentation/subsystem-apis.rst b/Documentation/subsystem-apis.rst
index 90a0535a932a..930dc23998a0 100644
--- a/Documentation/subsystem-apis.rst
+++ b/Documentation/subsystem-apis.rst
@@ -35,6 +35,7 @@ Human interfaces
sound/index
gpu/index
fb/index
+ leds/index
Networking interfaces
---------------------
@@ -70,7 +71,6 @@ Storage interfaces
fpga/index
i2c/index
iio/index
- leds/index
pcmcia/index
spi/index
w1/index
diff --git a/Documentation/trace/coresight/coresight.rst b/Documentation/trace/coresight/coresight.rst
index 4a71ea6cb390..826e59a698da 100644
--- a/Documentation/trace/coresight/coresight.rst
+++ b/Documentation/trace/coresight/coresight.rst
@@ -130,7 +130,7 @@ Misc:
Device Tree Bindings
--------------------
-See Documentation/devicetree/bindings/arm/arm,coresight-\*.yaml for details.
+See ``Documentation/devicetree/bindings/arm/arm,coresight-*.yaml`` for details.
As of this writing drivers for ITM, STMs and CTIs are not provided but are
expected to be added as the solution matures.
diff --git a/Documentation/trace/fprobe.rst b/Documentation/trace/fprobe.rst
index 7a895514b537..196f52386aaa 100644
--- a/Documentation/trace/fprobe.rst
+++ b/Documentation/trace/fprobe.rst
@@ -91,9 +91,9 @@ The prototype of the entry/exit callback function are as follows:
.. code-block:: c
- int entry_callback(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs, void *entry_data);
+ int entry_callback(struct fprobe *fp, unsigned long entry_ip, unsigned long ret_ip, struct pt_regs *regs, void *entry_data);
- void exit_callback(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs, void *entry_data);
+ void exit_callback(struct fprobe *fp, unsigned long entry_ip, unsigned long ret_ip, struct pt_regs *regs, void *entry_data);
Note that the @entry_ip is saved at function entry and passed to exit handler.
If the entry callback function returns !0, the corresponding exit callback will be cancelled.
@@ -108,6 +108,10 @@ If the entry callback function returns !0, the corresponding exit callback will
Note that this may not be the actual entry address of the function but
the address where the ftrace is instrumented.
+@ret_ip
+ This is the return address that the traced function will return to,
+ somewhere in the caller. This can be used at both entry and exit.
+
@regs
This is the `pt_regs` data structure at the entry and exit. Note that
the instruction pointer of @regs may be different from the @entry_ip
diff --git a/Documentation/trace/fprobetrace.rst b/Documentation/trace/fprobetrace.rst
index 8e9bebcf0a2e..e35e6b18df40 100644
--- a/Documentation/trace/fprobetrace.rst
+++ b/Documentation/trace/fprobetrace.rst
@@ -59,8 +59,12 @@ Synopsis of fprobe-events
and bitfield are supported.
(\*1) This is available only when BTF is enabled.
- (\*2) only for the probe on function entry (offs == 0).
- (\*3) only for return probe.
+ (\*2) only for the probe on function entry (offs == 0). Note, this argument access
+ is best effort, because depending on the argument type, it may be passed on
+ the stack. But this only support the arguments via registers.
+ (\*3) only for return probe. Note that this is also best effort. Depending on the
+ return value type, it might be passed via a pair of registers. But this only
+ accesses one register.
(\*4) this is useful for fetching a field of data structures.
(\*5) "u" means user-space dereference.
diff --git a/Documentation/trace/kprobes.rst b/Documentation/trace/kprobes.rst
index fc7ce76eab65..f825970a1495 100644
--- a/Documentation/trace/kprobes.rst
+++ b/Documentation/trace/kprobes.rst
@@ -315,7 +315,6 @@ architectures:
- i386 (Supports jump optimization)
- x86_64 (AMD-64, EM64T) (Supports jump optimization)
- ppc64
-- ia64 (Does not support probes on instruction slot1.)
- sparc64 (Return probes not yet implemented.)
- arm
- ppc
diff --git a/Documentation/trace/kprobetrace.rst b/Documentation/trace/kprobetrace.rst
index 8a2dfee38145..bf9cecb69fc9 100644
--- a/Documentation/trace/kprobetrace.rst
+++ b/Documentation/trace/kprobetrace.rst
@@ -61,8 +61,12 @@ Synopsis of kprobe_events
(x8/x16/x32/x64), "char", "string", "ustring", "symbol", "symstr"
and bitfield are supported.
- (\*1) only for the probe on function entry (offs == 0).
- (\*2) only for return probe.
+ (\*1) only for the probe on function entry (offs == 0). Note, this argument access
+ is best effort, because depending on the argument type, it may be passed on
+ the stack. But this only support the arguments via registers.
+ (\*2) only for return probe. Note that this is also best effort. Depending on the
+ return value type, it might be passed via a pair of registers. But this only
+ accesses one register.
(\*3) this is useful for fetching a field of data structures.
(\*4) "u" means user-space dereference. See :ref:`user_mem_access`.
diff --git a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
index e24c009789a0..048dc0dbce64 100644
--- a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
+++ b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
@@ -107,14 +107,14 @@ GetOptions(
);
# Defaults for dynamically discovered regex's
-my $regex_direct_begin_default = 'order=([0-9]*) may_writepage=([0-9]*) gfp_flags=([A-Z_|]*)';
+my $regex_direct_begin_default = 'order=([0-9]*) gfp_flags=([A-Z_|]*)';
my $regex_direct_end_default = 'nr_reclaimed=([0-9]*)';
my $regex_kswapd_wake_default = 'nid=([0-9]*) order=([0-9]*)';
my $regex_kswapd_sleep_default = 'nid=([0-9]*)';
-my $regex_wakeup_kswapd_default = 'nid=([0-9]*) zid=([0-9]*) order=([0-9]*) gfp_flags=([A-Z_|]*)';
-my $regex_lru_isolate_default = 'isolate_mode=([0-9]*) classzone_idx=([0-9]*) order=([0-9]*) nr_requested=([0-9]*) nr_scanned=([0-9]*) nr_skipped=([0-9]*) nr_taken=([0-9]*) lru=([a-z_]*)';
+my $regex_wakeup_kswapd_default = 'nid=([0-9]*) order=([0-9]*) gfp_flags=([A-Z_|]*)';
+my $regex_lru_isolate_default = 'classzone=([0-9]*) order=([0-9]*) nr_requested=([0-9]*) nr_scanned=([0-9]*) nr_skipped=([0-9]*) nr_taken=([0-9]*) lru=([a-z_]*)';
my $regex_lru_shrink_inactive_default = 'nid=([0-9]*) nr_scanned=([0-9]*) nr_reclaimed=([0-9]*) nr_dirty=([0-9]*) nr_writeback=([0-9]*) nr_congested=([0-9]*) nr_immediate=([0-9]*) nr_activate_anon=([0-9]*) nr_activate_file=([0-9]*) nr_ref_keep=([0-9]*) nr_unmap_fail=([0-9]*) priority=([0-9]*) flags=([A-Z_|]*)';
-my $regex_lru_shrink_active_default = 'lru=([A-Z_]*) nr_scanned=([0-9]*) nr_rotated=([0-9]*) priority=([0-9]*)';
+my $regex_lru_shrink_active_default = 'lru=([A-Z_]*) nr_taken=([0-9]*) nr_active=([0-9]*) nr_deactivated=([0-9]*) nr_referenced=([0-9]*) priority=([0-9]*) flags=([A-Z_|]*)' ;
my $regex_writepage_default = 'page=([0-9a-f]*) pfn=([0-9]*) flags=([A-Z_|]*)';
# Dyanically discovered regex
@@ -184,8 +184,7 @@ sub generate_traceevent_regex {
$regex_direct_begin = generate_traceevent_regex(
"vmscan/mm_vmscan_direct_reclaim_begin",
$regex_direct_begin_default,
- "order", "may_writepage",
- "gfp_flags");
+ "order", "gfp_flags");
$regex_direct_end = generate_traceevent_regex(
"vmscan/mm_vmscan_direct_reclaim_end",
$regex_direct_end_default,
@@ -201,11 +200,11 @@ $regex_kswapd_sleep = generate_traceevent_regex(
$regex_wakeup_kswapd = generate_traceevent_regex(
"vmscan/mm_vmscan_wakeup_kswapd",
$regex_wakeup_kswapd_default,
- "nid", "zid", "order", "gfp_flags");
+ "nid", "order", "gfp_flags");
$regex_lru_isolate = generate_traceevent_regex(
"vmscan/mm_vmscan_lru_isolate",
$regex_lru_isolate_default,
- "isolate_mode", "classzone_idx", "order",
+ "classzone", "order",
"nr_requested", "nr_scanned", "nr_skipped", "nr_taken",
"lru");
$regex_lru_shrink_inactive = generate_traceevent_regex(
@@ -218,11 +217,10 @@ $regex_lru_shrink_inactive = generate_traceevent_regex(
$regex_lru_shrink_active = generate_traceevent_regex(
"vmscan/mm_vmscan_lru_shrink_active",
$regex_lru_shrink_active_default,
- "nid", "zid",
- "lru",
- "nr_scanned", "nr_rotated", "priority");
+ "nid", "nr_taken", "nr_active", "nr_deactivated", "nr_referenced",
+ "priority", "flags");
$regex_writepage = generate_traceevent_regex(
- "vmscan/mm_vmscan_writepage",
+ "vmscan/mm_vmscan_write_folio",
$regex_writepage_default,
"page", "pfn", "flags");
@@ -371,7 +369,7 @@ EVENT_PROCESS:
print " $regex_wakeup_kswapd\n";
next;
}
- my $order = $3;
+ my $order = $2;
$perprocesspid{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD_PERORDER}[$order]++;
} elsif ($tracepoint eq "mm_vmscan_lru_isolate") {
$details = $6;
@@ -381,18 +379,14 @@ EVENT_PROCESS:
print " $regex_lru_isolate/o\n";
next;
}
- my $isolate_mode = $1;
- my $nr_scanned = $5;
- my $file = $8;
-
- # To closer match vmstat scanning statistics, only count isolate_both
- # and isolate_inactive as scanning. isolate_active is rotation
- # isolate_inactive == 1
- # isolate_active == 2
- # isolate_both == 3
- if ($isolate_mode != 2) {
+ my $nr_scanned = $4;
+ my $lru = $7;
+
+ # To closer match vmstat scanning statistics, only count
+ # inactive lru as scanning
+ if ($lru =~ /inactive_/) {
$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
- if ($file =~ /_file/) {
+ if ($lru =~ /_file/) {
$perprocesspid{$process_pid}->{HIGH_NR_FILE_SCANNED} += $nr_scanned;
} else {
$perprocesspid{$process_pid}->{HIGH_NR_ANON_SCANNED} += $nr_scanned;
diff --git a/Documentation/trace/user_events.rst b/Documentation/trace/user_events.rst
index f9530d0ac5d3..d8f12442aaa6 100644
--- a/Documentation/trace/user_events.rst
+++ b/Documentation/trace/user_events.rst
@@ -14,6 +14,11 @@ Programs can view status of the events via
/sys/kernel/tracing/user_events_status and can both register and write
data out via /sys/kernel/tracing/user_events_data.
+Programs can also use /sys/kernel/tracing/dynamic_events to register and
+delete user based events via the u: prefix. The format of the command to
+dynamic_events is the same as the ioctl with the u: prefix applied. This
+requires CAP_PERFMON due to the event persisting, otherwise -EPERM is returned.
+
Typically programs will register a set of events that they wish to expose to
tools that can read trace_events (such as ftrace and perf). The registration
process tells the kernel which address and bit to reflect if any tool has
@@ -45,7 +50,7 @@ This command takes a packed struct user_reg as an argument::
/* Input: Enable size in bytes at address */
__u8 enable_size;
- /* Input: Flags for future use, set to 0 */
+ /* Input: Flags to use, if any */
__u16 flags;
/* Input: Address to update when enabled */
@@ -69,7 +74,7 @@ The struct user_reg requires all the above inputs to be set appropriately.
This must be 4 (32-bit) or 8 (64-bit). 64-bit values are only allowed to be
used on 64-bit kernels, however, 32-bit can be used on all kernels.
-+ flags: The flags to use, if any. For the initial version this must be 0.
++ flags: The flags to use, if any.
Callers should first attempt to use flags and retry without flags to ensure
support for lower versions of the kernel. If a flag is not supported -EINVAL
is returned.
@@ -80,6 +85,13 @@ The struct user_reg requires all the above inputs to be set appropriately.
+ name_args: The name and arguments to describe the event, see command format
for details.
+The following flags are currently supported.
+
++ USER_EVENT_REG_PERSIST: The event will not delete upon the last reference
+ closing. Callers may use this if an event should exist even after the
+ process closes or unregisters the event. Requires CAP_PERFMON otherwise
+ -EPERM is returned.
+
Upon successful registration the following is set.
+ write_index: The index to use for this file descriptor that represents this
@@ -141,7 +153,10 @@ event (in both user and kernel space). User programs should use a separate file
to request deletes than the one used for registration due to this.
**NOTE:** By default events will auto-delete when there are no references left
-to the event. Flags in the future may change this logic.
+to the event. If programs do not want auto-delete, they must use the
+USER_EVENT_REG_PERSIST flag when registering the event. Once that flag is used
+the event exists until DIAG_IOCSDEL is invoked. Both register and delete of an
+event that persists requires CAP_PERFMON, otherwise -EPERM is returned.
Unregistering
-------------
diff --git a/Documentation/translations/it_IT/riscv/patch-acceptance.rst b/Documentation/translations/it_IT/riscv/patch-acceptance.rst
index edf67252b3fb..2d7afb1f6959 100644
--- a/Documentation/translations/it_IT/riscv/patch-acceptance.rst
+++ b/Documentation/translations/it_IT/riscv/patch-acceptance.rst
@@ -1,6 +1,6 @@
.. include:: ../disclaimer-ita.rst
-:Original: :doc:`../../../riscv/patch-acceptance`
+:Original: :doc:`../../../arch/riscv/patch-acceptance`
:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
arch/riscv linee guida alla manutenzione per gli sviluppatori
diff --git a/Documentation/translations/sp_SP/process/embargoed-hardware-issues.rst b/Documentation/translations/sp_SP/process/embargoed-hardware-issues.rst
new file mode 100644
index 000000000000..c261b428b3f0
--- /dev/null
+++ b/Documentation/translations/sp_SP/process/embargoed-hardware-issues.rst
@@ -0,0 +1,341 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-sp.rst
+
+:Original: Documentation/process/embargoed-hardware-issues.rst
+:Translator: Avadhut Naik <avadhut.naik@amd.com>
+
+Problemas de hardware embargados
+================================
+
+Alcance
+-------
+
+Los problemas de hardware que resultan en problemas de seguridad son una
+categoría diferente de errores de seguridad que los errores de software
+puro que solo afectan al kernel de Linux.
+
+Los problemas de hardware como Meltdown, Spectre, L1TF, etc. deben
+tratarse de manera diferente porque usualmente afectan a todos los
+sistemas operativos (“OSâ€) y, por lo tanto, necesitan coordinación entre
+vendedores diferentes de OS, distribuciones, vendedores de hardware y
+otras partes. Para algunos de los problemas, las mitigaciones de software
+pueden depender de actualizaciones de microcódigo o firmware, los cuales
+necesitan una coordinación adicional.
+
+.. _Contacto:
+
+Contacto
+--------
+
+El equipo de seguridad de hardware del kernel de Linux es separado del
+equipo regular de seguridad del kernel de Linux.
+
+El equipo solo maneja la coordinación de los problemas de seguridad de
+hardware embargados. Los informes de errores de seguridad de software puro
+en el kernel de Linux no son manejados por este equipo y el "reportero"
+(quien informa del error) será guiado a contactar el equipo de seguridad
+del kernel de Linux (:doc:`errores de seguridad <security-bugs>`) en su
+lugar.
+
+El equipo puede contactar por correo electrónico en
+<hardware-security@kernel.org>. Esta es una lista privada de oficiales de
+seguridad que lo ayudarán a coordinar un problema de acuerdo con nuestro
+proceso documentado.
+
+La lista esta encriptada y el correo electrónico a la lista puede ser
+enviado por PGP o S/MIME encriptado y debe estar firmado con la llave de
+PGP del reportero o el certificado de S/MIME. La llave de PGP y el
+certificado de S/MIME de la lista están disponibles en las siguientes
+URLs:
+
+ - PGP: https://www.kernel.org/static/files/hardware-security.asc
+ - S/MIME: https://www.kernel.org/static/files/hardware-security.crt
+
+Si bien los problemas de seguridad del hardware a menudo son manejados por
+el vendedor de hardware afectado, damos la bienvenida al contacto de
+investigadores o individuos que hayan identificado una posible falla de
+hardware.
+
+Oficiales de seguridad de hardware
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+El equipo actual de oficiales de seguridad de hardware:
+
+ - Linus Torvalds (Linux Foundation Fellow)
+ - Greg Kroah-Hartman (Linux Foundation Fellow)
+ - Thomas Gleixner (Linux Foundation Fellow)
+
+Operación de listas de correo
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Las listas de correo encriptadas que se utilizan en nuestro proceso están
+alojados en la infraestructura de IT de la Fundación Linux. Al proporcionar
+este servicio, los miembros del personal de operaciones de IT de la
+Fundación Linux técnicamente tienen la capacidad de acceder a la
+información embargada, pero están obligados a la confidencialidad por su
+contrato de trabajo. El personal de IT de la Fundación Linux también es
+responsable para operar y administrar el resto de la infraestructura de
+kernel.org.
+
+El actual director de infraestructura de proyecto de IT de la Fundación
+Linux es Konstantin Ryabitsev.
+
+Acuerdos de no divulgación
+--------------------------
+
+El equipo de seguridad de hardware del kernel de Linux no es un organismo
+formal y, por lo tanto, no puede firmar cualquier acuerdo de no
+divulgación. La comunidad del kernel es consciente de la naturaleza
+delicada de tales problemas y ofrece un Memorando de Entendimiento en su
+lugar.
+
+Memorando de Entendimiento
+--------------------------
+
+La comunidad del kernel de Linux tiene una comprensión profunda del
+requisito de mantener los problemas de seguridad de hardware bajo embargo
+para la coordinación entre diferentes vendedores de OS, distribuidores,
+vendedores de hardware y otras partes.
+
+La comunidad del kernel de Linux ha manejado con éxito los problemas de
+seguridad del hardware en el pasado y tiene los mecanismos necesarios para
+permitir el desarrollo compatible con la comunidad bajo restricciones de
+embargo.
+
+La comunidad del kernel de Linux tiene un equipo de seguridad de hardware
+dedicado para el contacto inicial, el cual supervisa el proceso de manejo
+de tales problemas bajo las reglas de embargo.
+
+El equipo de seguridad de hardware identifica a los desarrolladores
+(expertos en dominio) que formarán el equipo de respuesta inicial para un
+problema en particular. El equipo de respuesta inicial puede involucrar
+más desarrolladores (expertos en dominio) para abordar el problema de la
+mejor manera técnica.
+
+Todos los desarrolladores involucrados se comprometen a adherirse a las
+reglas del embargo y a mantener confidencial la información recibida. La
+violación de la promesa conducirá a la exclusión inmediata del problema
+actual y la eliminación de todas las listas de correo relacionadas.
+Además, el equipo de seguridad de hardware también excluirá al
+delincuente de problemas futuros. El impacto de esta consecuencia es un
+elemento de disuasión altamente efectivo en nuestra comunidad. En caso de
+que ocurra una violación, el equipo de seguridad de hardware informará a
+las partes involucradas inmediatamente. Si usted o alguien tiene
+conocimiento de una posible violación, por favor, infórmelo inmediatamente
+a los oficiales de seguridad de hardware.
+
+Proceso
+^^^^^^^
+
+Debido a la naturaleza distribuida globalmente del desarrollo del kernel
+de Linux, las reuniones cara a cara hacen imposible abordar los
+problemas de seguridad del hardware. Las conferencias telefónicas son
+difíciles de coordinar debido a las zonas horarias y otros factores y
+solo deben usarse cuando sea absolutamente necesario. El correo
+electrónico encriptado ha demostrado ser el método de comunicación más
+efectivo y seguro para estos tipos de problemas.
+
+Inicio de la divulgación
+""""""""""""""""""""""""
+
+La divulgación comienza contactado al equipo de seguridad de hardware del
+kernel de Linux por correo electrónico. Este contacto inicial debe
+contener una descripción del problema y una lista de cualquier hardware
+afectado conocido. Si su organización fabrica o distribuye el hardware
+afectado, le animamos a considerar también que otro hardware podría estar
+afectado.
+
+El equipo de seguridad de hardware proporcionará una lista de correo
+encriptada específica para el incidente que se utilizará para la discusión
+inicial con el reportero, la divulgación adicional y la coordinación.
+
+El equipo de seguridad de hardware proporcionará a la parte reveladora una
+lista de desarrolladores (expertos de dominios) a quienes se debe informar
+inicialmente sobre el problema después de confirmar con los
+desarrolladores que se adherirán a este Memorando de Entendimiento y al
+proceso documentado. Estos desarrolladores forman el equipo de respuesta
+inicial y serán responsables de manejar el problema después del contacto
+inicial. El equipo de seguridad de hardware apoyará al equipo de
+respuesta, pero no necesariamente involucrandose en el proceso de desarrollo
+de mitigación.
+
+Si bien los desarrolladores individuales pueden estar cubiertos por un
+acuerdo de no divulgación a través de su empleador, no pueden firmar
+acuerdos individuales de no divulgación en su papel de desarrolladores
+del kernel de Linux. Sin embargo, aceptarán adherirse a este proceso
+documentado y al Memorando de Entendimiento.
+
+La parte reveladora debe proporcionar una lista de contactos para todas
+las demás entidades ya que han sido, o deberían ser, informadas sobre el
+problema. Esto sirve para varios propósitos:
+
+ - La lista de entidades divulgadas permite la comunicación en toda la
+ industria, por ejemplo, otros vendedores de OS, vendedores de HW, etc.
+
+ - Las entidades divulgadas pueden ser contactadas para nombrar a expertos
+ que deben participar en el desarrollo de la mitigación.
+
+ - Si un experto que se requiere para manejar un problema es empleado por
+ una entidad cotizada o un miembro de una entidad cotizada, los equipos
+ de respuesta pueden solicitar la divulgación de ese experto a esa
+ entidad. Esto asegura que el experto también forme parte del equipo de
+ respuesta de la entidad.
+
+Divulgación
+"""""""""""
+
+La parte reveladora proporcionará información detallada al equipo de
+respuesta inicial a través de la lista de correo encriptada especifica.
+
+Según nuestra experiencia, la documentación técnica de estos problemas
+suele ser un punto de partida suficiente y es mejor hacer aclaraciones
+técnicas adicionales a través del correo electrónico.
+
+Desarrollo de la mitigación
+"""""""""""""""""""""""""""
+
+El equipo de respuesta inicial configura una lista de correo encriptada o
+reutiliza una existente si es apropiada.
+
+El uso de una lista de correo está cerca del proceso normal de desarrollo
+de Linux y se ha utilizado con éxito en el desarrollo de mitigación para
+varios problemas de seguridad de hardware en el pasado.
+
+La lista de correo funciona en la misma manera que el desarrollo normal de
+Linux. Los parches se publican, discuten y revisan y, si se acuerda, se
+aplican a un repositorio git no público al que solo pueden acceder los
+desarrolladores participantes a través de una conexión segura. El
+repositorio contiene la rama principal de desarrollo en comparación con
+el kernel principal y las ramas backport para versiones estables del
+kernel según sea necesario.
+
+El equipo de respuesta inicial identificará a más expertos de la
+comunidad de desarrolladores del kernel de Linux según sea necesario. La
+incorporación de expertos puede ocurrir en cualquier momento del proceso
+de desarrollo y debe manejarse de manera oportuna.
+
+Si un experto es empleado por o es miembro de una entidad en la lista de
+divulgación proporcionada por la parte reveladora, entonces se solicitará
+la participación de la entidad pertinente.
+
+Si no es así, entonces se informará a la parte reveladora sobre la
+participación de los expertos. Los expertos están cubiertos por el
+Memorando de Entendimiento y se solicita a la parte reveladora que
+reconozca la participación. En caso de que la parte reveladora tenga una
+razón convincente para objetar, entonces esta objeción debe plantearse
+dentro de los cinco días laborables y resolverse con el equipo de
+incidente inmediatamente. Si la parte reveladora no reacciona dentro de
+los cinco días laborables, esto se toma como un reconocimiento silencioso.
+
+Después del reconocimiento o la resolución de una objeción, el experto es
+revelado por el equipo de incidente y se incorpora al proceso de
+desarrollo.
+
+Lanzamiento coordinado
+""""""""""""""""""""""
+
+Las partes involucradas negociarán la fecha y la hora en la que termina el
+embargo. En ese momento, las mitigaciones preparadas se integran en los
+árboles de kernel relevantes y se publican.
+
+Si bien entendemos que los problemas de seguridad del hardware requieren
+un tiempo de embargo coordinado, el tiempo de embargo debe limitarse al
+tiempo mínimo que se requiere para que todas las partes involucradas
+desarrollen, prueben y preparen las mitigaciones. Extender el tiempo de
+embargo artificialmente para cumplir con las fechas de discusión de la
+conferencia u otras razones no técnicas está creando más trabajo y carga
+para los desarrolladores y los equipos de respuesta involucrados, ya que
+los parches necesitan mantenerse actualizados para seguir el desarrollo en
+curso del kernel upstream, lo cual podría crear cambios conflictivos.
+
+Asignación de CVE
+"""""""""""""""""
+
+Ni el equipo de seguridad de hardware ni el equipo de respuesta inicial
+asignan CVEs, ni se requieren para el proceso de desarrollo. Si los CVEs
+son proporcionados por la parte reveladora, pueden usarse con fines de
+documentación.
+
+Embajadores del proceso
+-----------------------
+
+Para obtener asistencia con este proceso, hemos establecido embajadores
+en varias organizaciones, que pueden responder preguntas o proporcionar
+orientación sobre el proceso de reporte y el manejo posterior. Los
+embajadores no están involucrados en la divulgación de un problema en
+particular, a menos que lo solicite un equipo de respuesta o una parte
+revelada involucrada. La lista de embajadores actuales:
+
+ ============= ========================================================
+ 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 Z Christian Borntraeger <borntraeger@de.ibm.com>
+ Intel Tony Luck <tony.luck@intel.com>
+ Qualcomm Trilok Soni <tsoni@codeaurora.org>
+ Samsung Javier González <javier.gonz@samsung.com>
+
+ Microsoft James Morris <jamorris@linux.microsoft.com>
+ Xen Andrew Cooper <andrew.cooper3@citrix.com>
+
+ Canonical John Johansen <john.johansen@canonical.com>
+ Debian Ben Hutchings <ben@decadent.org.uk>
+ Oracle Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+ Red Hat Josh Poimboeuf <jpoimboe@redhat.com>
+ SUSE Jiri Kosina <jkosina@suse.cz>
+
+ Google Kees Cook <keescook@chromium.org>
+
+ LLVM Nick Desaulniers <ndesaulniers@google.com>
+ ============= ========================================================
+
+Si quiere que su organización se añada a la lista de embajadores, por
+favor póngase en contacto con el equipo de seguridad de hardware. El
+embajador nominado tiene que entender y apoyar nuestro proceso
+completamente y está idealmente bien conectado en la comunidad del kernel
+de Linux.
+
+Listas de correo encriptadas
+----------------------------
+
+Usamos listas de correo encriptadas para la comunicación. El principio de
+funcionamiento de estas listas es que el correo electrónico enviado a la
+lista se encripta con la llave PGP de la lista o con el certificado S/MIME
+de la lista. El software de lista de correo descifra el correo electrónico
+y lo vuelve a encriptar individualmente para cada suscriptor con la llave
+PGP del suscriptor o el certificado S/MIME. Los detalles sobre el software
+de la lista de correo y la configuración que se usa para asegurar la
+seguridad de las listas y la protección de los datos se pueden encontrar
+aquí: https://korg.wiki.kernel.org/userdoc/remail.
+
+Llaves de lista
+^^^^^^^^^^^^^^^
+
+Para el contacto inicial, consulte :ref:`Contacto`. Para las listas de
+correo especificas de incidentes, la llave y el certificado S/MIME se
+envían a los suscriptores por correo electrónico desde la lista
+especifica.
+
+Suscripción a listas específicas de incidentes
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+La suscripción es manejada por los equipos de respuesta. Las partes
+reveladas que quieren participar en la comunicación envían una lista de
+suscriptores potenciales al equipo de respuesta para que el equipo de
+respuesta pueda validar las solicitudes de suscripción.
+
+Cada suscriptor necesita enviar una solicitud de suscripción al equipo de
+respuesta por correo electrónico. El correo electrónico debe estar firmado
+con la llave PGP del suscriptor o el certificado S/MIME. Si se usa una
+llave PGP, debe estar disponible desde un servidor de llave publica y esta
+idealmente conectada a la red de confianza PGP del kernel de Linux. Véase
+también: https://www.kernel.org/signature.html.
+
+El equipo de respuesta verifica que la solicitud del suscriptor sea válida
+y añade al suscriptor a la lista. Después de la suscripción, el suscriptor
+recibirá un correo electrónico de la lista que está firmado con la llave
+PGP de la lista o el certificado S/MIME de la lista. El cliente de correo
+electrónico del suscriptor puede extraer la llave PGP o el certificado
+S/MIME de la firma, de modo que el suscriptor pueda enviar correo
+electrónico encriptado a la lista.
diff --git a/Documentation/translations/sp_SP/process/index.rst b/Documentation/translations/sp_SP/process/index.rst
index 09bfece0f52f..d6f3ccfb160e 100644
--- a/Documentation/translations/sp_SP/process/index.rst
+++ b/Documentation/translations/sp_SP/process/index.rst
@@ -22,3 +22,5 @@
adding-syscalls
researcher-guidelines
contribution-maturity-model
+ security-bugs
+ embargoed-hardware-issues
diff --git a/Documentation/translations/sp_SP/process/security-bugs.rst b/Documentation/translations/sp_SP/process/security-bugs.rst
new file mode 100644
index 000000000000..d07c7e579b52
--- /dev/null
+++ b/Documentation/translations/sp_SP/process/security-bugs.rst
@@ -0,0 +1,103 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-sp.rst
+
+:Original: Documentation/process/security-bugs.rst
+:Translator: Avadhut Naik <avadhut.naik@amd.com>
+
+Errores de seguridad
+====================
+
+Los desarrolladores del kernel de Linux se toman la seguridad muy en
+serio. Como tal, nos gustaría saber cuándo se encuentra un error de
+seguridad para que pueda ser corregido y divulgado lo más rápido posible.
+Por favor, informe sobre los errores de seguridad al equipo de seguridad
+del kernel de Linux.
+
+Contacto
+--------
+
+El equipo de seguridad del kernel de Linux puede ser contactado por correo
+electrónico en <security@kernel.org>. Esta es una lista privada de
+oficiales de seguridad que ayudarán a verificar el informe del error y
+desarrollarán y publicarán una corrección. Si ya tiene una corrección, por
+favor, inclúyala con su informe, ya que eso puede acelerar considerablemente
+el proceso. Es posible que el equipo de seguridad traiga ayuda adicional
+de mantenedores del área para comprender y corregir la vulnerabilidad de
+seguridad.
+
+Como ocurre con cualquier error, cuanta más información se proporcione,
+más fácil será diagnosticarlo y corregirlo. Por favor, revise el
+procedimiento descrito en 'Documentation/admin-guide/reporting-issues.rst'
+si no tiene claro que información es útil. Cualquier código de explotación
+es muy útil y no será divulgado sin el consentimiento del "reportero" (el
+que envia el error) a menos que ya se haya hecho público.
+
+Por favor, envíe correos electrónicos en texto plano sin archivos
+adjuntos cuando sea posible. Es mucho más difícil tener una discusión
+citada en contexto sobre un tema complejo si todos los detalles están
+ocultos en archivos adjuntos. Piense en ello como un
+:doc:`envío de parche regular <submitting-patches>` (incluso si no tiene
+un parche todavía) describa el problema y el impacto, enumere los pasos
+de reproducción, y sígalo con una solución propuesta, todo en texto plano.
+
+
+Divulgación e información embargada
+-----------------------------------
+
+La lista de seguridad no es un canal de divulgación. Para eso, ver
+Coordinación debajo. Una vez que se ha desarrollado una solución robusta,
+comienza el proceso de lanzamiento. Las soluciones para errores conocidos
+públicamente se lanzan inmediatamente.
+
+Aunque nuestra preferencia es lanzar soluciones para errores no divulgados
+públicamente tan pronto como estén disponibles, esto puede postponerse a
+petición del reportero o una parte afectada por hasta 7 días calendario
+desde el inicio del proceso de lanzamiento, con una extensión excepcional
+a 14 días de calendario si se acuerda que la criticalidad del error requiere
+más tiempo. La única razón válida para aplazar la publicación de una
+solución es para acomodar la logística de QA y los despliegues a gran
+escala que requieren coordinación de lanzamiento.
+
+Si bien la información embargada puede compartirse con personas de
+confianza para desarrollar una solución, dicha información no se publicará
+junto con la solución o en cualquier otro canal de divulgación sin el
+permiso del reportero. Esto incluye, pero no se limita al informe original
+del error y las discusiones de seguimiento (si las hay), exploits,
+información sobre CVE o la identidad del reportero.
+
+En otras palabras, nuestro único interés es solucionar los errores. Toda
+otra información presentada a la lista de seguridad y cualquier discusión
+de seguimiento del informe se tratan confidencialmente incluso después de
+que se haya levantado el embargo, en perpetuidad.
+
+Coordinación con otros grupos
+-----------------------------
+
+El equipo de seguridad del kernel recomienda encarecidamente que los
+reporteros de posibles problemas de seguridad NUNCA contacten la lista
+de correo “linux-distros†hasta DESPUES de discutirlo con el equipo de
+seguridad del kernel. No Cc: ambas listas a la vez. Puede ponerse en
+contacto con la lista de correo linux-distros después de que se haya
+acordado una solución y comprenda completamente los requisitos que al
+hacerlo le impondrá a usted y la comunidad del kernel.
+
+Las diferentes listas tienen diferentes objetivos y las reglas de
+linux-distros no contribuyen en realidad a solucionar ningún problema de
+seguridad potencial.
+
+Asignación de CVE
+-----------------
+
+El equipo de seguridad no asigna CVEs, ni los requerimos para informes o
+correcciones, ya que esto puede complicar innecesariamente el proceso y
+puede retrasar el manejo de errores. Si un reportero desea que se le
+asigne un identificador CVE, debe buscar uno por sí mismo, por ejemplo,
+poniéndose en contacto directamente con MITRE. Sin embargo, en ningún
+caso se retrasará la inclusión de un parche para esperar a que llegue un
+identificador CVE.
+
+Acuerdos de no divulgación
+--------------------------
+
+El equipo de seguridad del kernel de Linux no es un organismo formal y,
+por lo tanto, no puede firmar cualquier acuerdo de no divulgación.
diff --git a/Documentation/translations/zh_CN/arch/index.rst b/Documentation/translations/zh_CN/arch/index.rst
index e3d273d7d599..71186d9df7c9 100644
--- a/Documentation/translations/zh_CN/arch/index.rst
+++ b/Documentation/translations/zh_CN/arch/index.rst
@@ -10,7 +10,7 @@
mips/index
arm64/index
- ../riscv/index
+ ../arch/riscv/index
openrisc/index
parisc/index
loongarch/index
@@ -18,7 +18,6 @@
TODOList:
* arm/index
-* ia64/index
* m68k/index
* nios2/index
* powerpc/index
diff --git a/Documentation/translations/zh_CN/arch/loongarch/introduction.rst b/Documentation/translations/zh_CN/arch/loongarch/introduction.rst
index 59d6bf33050c..bf463c5a4c51 100644
--- a/Documentation/translations/zh_CN/arch/loongarch/introduction.rst
+++ b/Documentation/translations/zh_CN/arch/loongarch/introduction.rst
@@ -338,9 +338,9 @@ Loongson与LoongArch的开å‘者网站(软件与文档资æºï¼‰ï¼š
LoongArch指令集架构的文档:
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-CN.pdf (中文版)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.10-CN.pdf (中文版)
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-EN.pdf (英文版)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.10-EN.pdf (英文版)
LoongArch的ELF psABI文档:
diff --git a/Documentation/translations/zh_CN/riscv/boot-image-header.rst b/Documentation/translations/zh_CN/arch/riscv/boot-image-header.rst
index 0234c28a7114..779b5172fe24 100644
--- a/Documentation/translations/zh_CN/riscv/boot-image-header.rst
+++ b/Documentation/translations/zh_CN/arch/riscv/boot-image-header.rst
@@ -1,6 +1,6 @@
-.. include:: ../disclaimer-zh_CN.rst
+.. include:: ../../disclaimer-zh_CN.rst
-:Original: Documentation/riscv/boot-image-header.rst
+:Original: Documentation/arch/riscv/boot-image-header.rst
:翻译:
diff --git a/Documentation/translations/zh_CN/riscv/index.rst b/Documentation/translations/zh_CN/arch/riscv/index.rst
index 131e405aa857..3b041c116169 100644
--- a/Documentation/translations/zh_CN/riscv/index.rst
+++ b/Documentation/translations/zh_CN/arch/riscv/index.rst
@@ -1,8 +1,8 @@
.. SPDX-License-Identifier: GPL-2.0
-.. include:: ../disclaimer-zh_CN.rst
+.. include:: ../../disclaimer-zh_CN.rst
-:Original: Documentation/riscv/index.rst
+:Original: Documentation/arch/riscv/index.rst
:翻译:
diff --git a/Documentation/translations/zh_CN/riscv/patch-acceptance.rst b/Documentation/translations/zh_CN/arch/riscv/patch-acceptance.rst
index d180d24717bf..c8eb230ca8ee 100644
--- a/Documentation/translations/zh_CN/riscv/patch-acceptance.rst
+++ b/Documentation/translations/zh_CN/arch/riscv/patch-acceptance.rst
@@ -1,8 +1,8 @@
.. SPDX-License-Identifier: GPL-2.0
-.. include:: ../disclaimer-zh_CN.rst
+.. include:: ../../disclaimer-zh_CN.rst
-:Original: Documentation/riscv/patch-acceptance.rst
+:Original: Documentation/arch/riscv/patch-acceptance.rst
:翻译:
diff --git a/Documentation/translations/zh_CN/riscv/vm-layout.rst b/Documentation/translations/zh_CN/arch/riscv/vm-layout.rst
index 91884e2dfff8..4b9f4dcf6c19 100644
--- a/Documentation/translations/zh_CN/riscv/vm-layout.rst
+++ b/Documentation/translations/zh_CN/arch/riscv/vm-layout.rst
@@ -1,7 +1,7 @@
.. SPDX-License-Identifier: GPL-2.0
-.. include:: ../disclaimer-zh_CN.rst
+.. include:: ../../disclaimer-zh_CN.rst
-:Original: Documentation/riscv/vm-layout.rst
+:Original: Documentation/arch/riscv/vm-layout.rst
:翻译:
diff --git a/Documentation/translations/zh_CN/core-api/cpu_hotplug.rst b/Documentation/translations/zh_CN/core-api/cpu_hotplug.rst
index 4772a900c37a..bc0d7ea6d834 100644
--- a/Documentation/translations/zh_CN/core-api/cpu_hotplug.rst
+++ b/Documentation/translations/zh_CN/core-api/cpu_hotplug.rst
@@ -49,12 +49,6 @@ CPUçƒ­æ‹”æ’æ”¯æŒçš„一个更新颖的用途是它在SMPçš„æš‚åœæ¢å¤æ”¯æŒä¸
é™åˆ¶å†…核将支æŒçš„CPU总é‡ã€‚如果这里æä¾›çš„æ•°é‡ä½ŽäºŽå®žé™…å¯ç”¨çš„CPUæ•°é‡ï¼Œé‚£ä¹ˆå…¶ä»–CPU
以åŽå°±ä¸èƒ½ä¸Šçº¿äº†ã€‚
-``additional_cpus=n``
- 使用它æ¥é™åˆ¶å¯çƒ­æ’拔的CPU。该选项设置
- ``cpu_possible_mask = cpu_present_mask + additional_cpus``
-
- 这个选项åªé™äºŽIA64架构。
-
``possible_cpus=n``
这个选项设置 ``cpu_possible_mask`` 中的 ``possible_cpus`` ä½ã€‚
diff --git a/Documentation/translations/zh_CN/core-api/workqueue.rst b/Documentation/translations/zh_CN/core-api/workqueue.rst
index 6c1b5ec31d75..7fac6f75d078 100644
--- a/Documentation/translations/zh_CN/core-api/workqueue.rst
+++ b/Documentation/translations/zh_CN/core-api/workqueue.rst
@@ -202,7 +202,7 @@ workqueue将自动创建与属性相匹é…çš„åŽå¤‡å·¥ä½œè€…æ± ã€‚è°ƒèŠ‚å¹¶å‘æ°
åŒçš„æŽ’åºå±žæ€§ã€‚
在目å‰çš„实现中,上述é…ç½®åªä¿è¯äº†ç‰¹å®šNUMA节点内的ST行为。相å,
-``alloc_ordered_queue()`` 应该被用æ¥å®žçŽ°å…¨ç³»ç»Ÿçš„ST行为。
+``alloc_ordered_workqueue()`` 应该被用æ¥å®žçŽ°å…¨ç³»ç»Ÿçš„ST行为。
执行场景示例
diff --git a/Documentation/translations/zh_CN/index.rst b/Documentation/translations/zh_CN/index.rst
index 299704c0818d..6ccec9657cc6 100644
--- a/Documentation/translations/zh_CN/index.rst
+++ b/Documentation/translations/zh_CN/index.rst
@@ -52,12 +52,9 @@
core-api/index
driver-api/index
+ subsystem-apis
å†…æ ¸ä¸­çš„é” <locking/index>
-TODOList:
-
-* subsystem-apis
-
å¼€å‘工具和æµç¨‹
--------------
diff --git a/Documentation/translations/zh_CN/maintainer/maintainer-entry-profile.rst b/Documentation/translations/zh_CN/maintainer/maintainer-entry-profile.rst
index a1ee99c4786e..0f5acfb1012e 100644
--- a/Documentation/translations/zh_CN/maintainer/maintainer-entry-profile.rst
+++ b/Documentation/translations/zh_CN/maintainer/maintainer-entry-profile.rst
@@ -89,4 +89,4 @@
../doc-guide/maintainer-profile
../../../nvdimm/maintainer-entry-profile
- ../../../riscv/patch-acceptance
+ ../../../arch/riscv/patch-acceptance
diff --git a/Documentation/translations/zh_CN/scheduler/sched-arch.rst b/Documentation/translations/zh_CN/scheduler/sched-arch.rst
index ce3f39d9b3cb..b2ac3c743a3a 100644
--- a/Documentation/translations/zh_CN/scheduler/sched-arch.rst
+++ b/Documentation/translations/zh_CN/scheduler/sched-arch.rst
@@ -20,8 +20,7 @@
==========
1. è¿è¡Œé˜Ÿåˆ—é”
默认情况下,switch_to arch函数在调用时é”定了è¿è¡Œé˜Ÿåˆ—ã€‚è¿™é€šå¸¸ä¸æ˜¯ä¸€ä¸ªé—®é¢˜ï¼Œé™¤éž
-switch_toå¯èƒ½éœ€è¦èŽ·å–è¿è¡Œé˜Ÿåˆ—é”。这通常是由于上下文切æ¢ä¸­çš„唤醒æ“作造æˆçš„。è§
-arch/ia64/include/asm/switch_to.h的例å­ã€‚
+switch_toå¯èƒ½éœ€è¦èŽ·å–è¿è¡Œé˜Ÿåˆ—é”。这通常是由于上下文切æ¢ä¸­çš„唤醒æ“作造æˆçš„。
ä¸ºäº†è¦æ±‚调度器在è¿è¡Œé˜Ÿåˆ—è§£é”的情况下调用switch_to,你必须在头文件
中`#define __ARCH_WANT_UNLOCKED_CTXSW`(通常是定义switch_to的那个文件)。
@@ -68,7 +67,5 @@ arch/x86/kernel/process.c有轮询和ç¡çœ ç©ºé—²å‡½æ•°çš„例å­ã€‚
我å‘现的å¯èƒ½çš„arch问题(并试图解决或没有解决)。:
-ia64 - safe_halt的调用与中断相比,是å¦å¾ˆè’谬? (它ç¡çœ äº†å—) (å‚考 #4a)
-
sparc - 在这一点上,IRQ是开ç€çš„(?),把local_irq_save改为_disable。
- 待办事项: 需è¦ç¬¬äºŒä¸ªCPUæ¥ç¦ç”¨æŠ¢å  (å‚考 #1)
diff --git a/Documentation/translations/zh_CN/subsystem-apis.rst b/Documentation/translations/zh_CN/subsystem-apis.rst
new file mode 100644
index 000000000000..47780bb0772f
--- /dev/null
+++ b/Documentation/translations/zh_CN/subsystem-apis.rst
@@ -0,0 +1,110 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ./disclaimer-zh_CN.rst
+
+:Original: Documentation/subsystem-apis.rst
+
+:翻译:
+
+ å”艺舟 Tang Yizhou <tangyeechou@gmail.com>
+
+==============
+内核å­ç³»ç»Ÿæ–‡æ¡£
+==============
+
+这些书ç±ä»Žå†…核开å‘者的角度,详细介ç»äº†ç‰¹å®šå†…æ ¸å­ç³»ç»Ÿ
+的如何工作。这里的大部分信æ¯ç›´æŽ¥å–自内核æºä»£ç ï¼Œå¹¶
+æ ¹æ®éœ€è¦æ·»åŠ äº†è¡¥å……ææ–™ï¼ˆæˆ–者至少是我们设法添加的 - å¯
+能 *䏿˜¯* æ‰€æœ‰çš„ææ–™éƒ½æœ‰éœ€è¦ï¼‰ã€‚
+
+核心å­ç³»ç»Ÿ
+----------
+
+.. toctree::
+ :maxdepth: 1
+
+ core-api/index
+ driver-api/index
+ mm/index
+ power/index
+ scheduler/index
+ locking/index
+
+TODOList:
+
+* timers/index
+
+人机接å£
+--------
+
+.. toctree::
+ :maxdepth: 1
+
+ sound/index
+
+TODOList:
+
+* input/index
+* hid/index
+* gpu/index
+* fb/index
+
+网络接å£
+--------
+
+.. toctree::
+ :maxdepth: 1
+
+ infiniband/index
+
+TODOList:
+
+* networking/index
+* netlabel/index
+* isdn/index
+* mhi/index
+
+存储接å£
+--------
+
+.. toctree::
+ :maxdepth: 1
+
+ filesystems/index
+
+TODOList:
+
+* block/index
+* cdrom/index
+* scsi/index
+* target/index
+
+**Fixme**: è¿™é‡Œè¿˜éœ€è¦æ›´å¤šçš„分类组织工作。
+
+.. toctree::
+ :maxdepth: 1
+
+ accounting/index
+ cpu-freq/index
+ iio/index
+ virt/index
+ PCI/index
+ peci/index
+
+TODOList:
+
+* fpga/index
+* i2c/index
+* leds/index
+* pcmcia/index
+* spi/index
+* w1/index
+* watchdog/index
+* hwmon/index
+* accel/index
+* security/index
+* crypto/index
+* bpf/index
+* usb/index
+* misc-devices/index
+* wmi/index
diff --git a/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt b/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt
index a88fcbc11eca..9cc97ec75d7a 100644
--- a/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt
+++ b/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt
@@ -768,18 +768,6 @@ const char *video_device_node_name(struct video_device *vdev);
此功能,而éžè®¿é—® video_device::num å’Œ video_device::minor 域。
-视频缓冲辅助函数
----------------
-
-v4l2 核心 API æä¾›äº†ä¸€ä¸ªå¤„ç†è§†é¢‘缓冲的标准方法(称为“videobufâ€)。
-这些方法使驱动å¯ä»¥é€šè¿‡ç»Ÿä¸€çš„æ–¹å¼å®žçް read()ã€mmap() å’Œ overlay()。
-ç›®å‰åœ¨è®¾å¤‡ä¸Šæ”¯æŒè§†é¢‘缓冲的方法有分散/èšé›† DMA(videobuf-dma-sg)ã€
-线性 DMA(videobuf-dma-contig)以åŠå¤§å¤šç”¨äºŽ USB 设备的用 vmalloc
-分é…的缓冲(videobuf-vmalloc)。
-
-请å‚阅 Documentation/driver-api/media/v4l2-videobuf.rst,以获得更多关于 videobuf
-层的使用信æ¯ã€‚
-
v4l2_fh 结构体
-------------
diff --git a/Documentation/translations/zh_TW/admin-guide/README.rst b/Documentation/translations/zh_TW/admin-guide/README.rst
index 7fc56e1e3348..4cb581f5994a 100644
--- a/Documentation/translations/zh_TW/admin-guide/README.rst
+++ b/Documentation/translations/zh_TW/admin-guide/README.rst
@@ -9,16 +9,16 @@
峿ƒ³æˆ Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <src.res.211@gmail.com>
-Linux內核5.x版本 <http://kernel.org/>
+Linux內核6.x版本 <http://kernel.org/>
=========================================
-以下是Linux版本5的發行註記。仔細閱讀它們,
+以下是Linux版本6的發行註記。仔細閱讀它們,
它們會告訴你這些都是什麼,解釋如何安è£å…§æ ¸ï¼Œä»¥åŠé‡åˆ°å•題時該如何åšã€‚
什麼是Linux?
---------------
- Linux是Unix作業系統的克隆版本,由Linus Torvalds在一個鬆散的網絡黑客
+ Linux是Unixæ“作系統的克隆版本,由Linus Torvalds在一個鬆散的網絡黑客
(Hacker,無貶義)團隊的幫助下從頭開始編寫。它旨在實ç¾å…¼å®¹POSIXå’Œ
單一UNIXè¦ç¯„。
@@ -28,7 +28,7 @@ Linux內核5.x版本 <http://kernel.org/>
Linux在GNU通用公共許å¯è­‰ï¼Œç‰ˆæœ¬2(GNU GPLv2)下分發,詳見隨附的COPYING文件。
-它能在什麼樣的硬體上é‹è¡Œï¼Ÿ
+它能在什麼樣的硬件上é‹è¡Œï¼Ÿ
-----------------------------
é›–ç„¶Linuxæœ€åˆæ˜¯çˆ²32ä½çš„x86 PC機(386或更高版本)開發的,但今天它也能é‹è¡Œåœ¨
@@ -40,16 +40,16 @@ Linux內核5.x版本 <http://kernel.org/>
單元(PMMU)和一個移æ¤çš„GNU C編譯器(gccï¼›GNU Compiler Collection,GCC的一
部分)。Linux也被移æ¤åˆ°è¨±å¤šæ²’有PMMU的體系架構中,儘管功能顯然å—到了一定的
é™åˆ¶ã€‚
- Linux也被移æ¤åˆ°äº†å…¶è‡ªå·±ä¸Šã€‚ç¾åœ¨å¯ä»¥å°‡å…§æ ¸ä½œçˆ²ç”¨æˆ¶ç©ºé–“應用程å¼é‹è¡Œâ€”—這被
+ Linux也被移æ¤åˆ°äº†å…¶è‡ªå·±ä¸Šã€‚ç¾åœ¨å¯ä»¥å°‡å…§æ ¸ä½œçˆ²ç”¨æˆ¶ç©ºé–“應用程åºé‹è¡Œâ€”—這被
稱爲用戶模å¼Linux(UML)。
文檔
-----
-網際網路上和書ç±ä¸Šéƒ½æœ‰å¤§é‡çš„電孿–‡æª”,既有Linux專屬文檔,也有與一般UNIXå•題相關
+因特網上和書ç±ä¸Šéƒ½æœ‰å¤§é‡çš„電孿–‡æª”,既有Linux專屬文檔,也有與一般UNIXå•題相關
的文檔。我建議在任何Linux FTP站點上查找LDP(Linux文檔項目)書ç±çš„æ–‡æª”å­ç›®éŒ„。
æœ¬è‡ªè¿°æ–‡ä»¶ä¸¦ä¸æ˜¯é—œæ–¼ç³»çµ±çš„æ–‡æª”:有更好的å¯ç”¨è³‡æºã€‚
- - 網際網路上和書ç±ä¸Šéƒ½æœ‰å¤§é‡çš„(電å­ï¼‰æ–‡æª”,既有Linux專屬文檔,也有與普通
+ - 因特網上和書ç±ä¸Šéƒ½æœ‰å¤§é‡çš„(電å­ï¼‰æ–‡æª”,既有Linux專屬文檔,也有與普通
UNIXå•題相關的文檔。我建議在任何有LDP(Linux文檔項目)書ç±çš„Linux FTP
站點上查找文檔å­ç›®éŒ„ã€‚æœ¬è‡ªè¿°æ–‡ä»¶ä¸¦ä¸æ˜¯é—œæ–¼ç³»çµ±çš„æ–‡æª”:有更好的å¯ç”¨è³‡æºã€‚
@@ -58,33 +58,33 @@ Linux內核5.x版本 <http://kernel.org/>
:ref:`Documentation/process/changes.rst <changes>` 文件,它包å«äº†å‡ç´šå…§æ ¸
å¯èƒ½æœƒå°Žè‡´çš„å•題的相關信æ¯ã€‚
-安è£å…§æ ¸åŽŸå§‹ç¢¼
+安è£å…§æ ¸æºä»£ç¢¼
---------------
- - 如果您è¦å®‰è£å®Œæ•´çš„原始碼,請把內核tar檔案包放在您有權é™çš„目錄中(例如您
+ - 如果您è¦å®‰è£å®Œæ•´çš„æºä»£ç¢¼ï¼Œè«‹æŠŠå…§æ ¸tar檔案包放在您有權é™çš„目錄中(例如您
的主目錄)並將其解包::
- xz -cd linux-5.x.tar.xz | tar xvf -
+ xz -cd linux-6.x.tar.xz | tar xvf -
- 將「Xã€æ›¿æ›æˆæœ€æ–°å…§æ ¸çš„版本號。
+ 將“Xâ€æ›¿æ›æˆæœ€æ–°å…§æ ¸çš„版本號。
- ã€ä¸è¦ã€‘使用 /usr/src/linux 目錄ï¼é€™è£¡æœ‰ä¸€çµ„庫頭文件使用的內核頭文件
+ ã€ä¸è¦ã€‘使用 /usr/src/linux 目錄ï¼é€™è£æœ‰ä¸€çµ„庫頭文件使用的內核頭文件
(通常是ä¸å®Œæ•´çš„)。它們應該與庫匹é…ï¼Œè€Œä¸æ˜¯è¢«å…§æ ¸çš„變化æžå¾—一團糟。
- - 您還å¯ä»¥é€šéŽæ‰“補ä¸åœ¨5.x版本之間å‡ç´šã€‚補ä¸ä»¥xzæ ¼å¼åˆ†ç™¼ã€‚è¦é€šéŽæ‰“補ä¸é€²è¡Œ
- 安è£ï¼Œè«‹ç²å–æ‰€æœ‰è¼ƒæ–°çš„è£œä¸æ–‡ä»¶ï¼Œé€²å…¥å…§æ ¸åŽŸå§‹ç¢¼ï¼ˆlinux-5.x)的目錄並
+ - 您還å¯ä»¥é€šéŽæ‰“補ä¸åœ¨6.x版本之間å‡ç´šã€‚補ä¸ä»¥xzæ ¼å¼åˆ†ç™¼ã€‚è¦é€šéŽæ‰“補ä¸é€²è¡Œ
+ 安è£ï¼Œè«‹ç²å–æ‰€æœ‰è¼ƒæ–°çš„è£œä¸æ–‡ä»¶ï¼Œé€²å…¥å…§æ ¸æºä»£ç¢¼ï¼ˆlinux-6.x)的目錄並
執行::
- xz -cd ../patch-5.x.xz | patch -p1
+ xz -cd ../patch-6.x.xz | patch -p1
- è«‹ã€æŒ‰é †åºã€‘æ›¿æ›æ‰€æœ‰å¤§æ–¼ç•¶å‰åŽŸå§‹ç¢¼æ¨¹ç‰ˆæœ¬çš„ã€Œxã€ï¼Œé€™æ¨£å°±å¯ä»¥äº†ã€‚您å¯èƒ½æƒ³è¦
+ è«‹ã€æŒ‰é †åºã€‘æ›¿æ›æ‰€æœ‰å¤§æ–¼ç•¶å‰æºä»£ç¢¼æ¨¹ç‰ˆæœ¬çš„“xâ€ï¼Œé€™æ¨£å°±å¯ä»¥äº†ã€‚您å¯èƒ½æƒ³è¦
刪除備份文件(文件å類似xxx~ 或 xxx.orig)ï¼Œä¸¦ç¢ºä¿æ²’有失敗的補ä¸ï¼ˆæ–‡ä»¶å
類似xxx# 或 xxx.rejï¼‰ã€‚å¦‚æžœæœ‰ï¼Œä¸æ˜¯ä½ å°±æ˜¯æˆ‘犯了錯誤。
- 與5.x內核的補ä¸ä¸åŒï¼Œ5.x.y內核(也稱爲穩定版內核)的補ä¸ä¸æ˜¯å¢žé‡çš„,而是
- 直接應用於基本的5.x內核。例如,如果您的基本內核是5.0,並且希望應用5.0.3
- 補ä¸ï¼Œå‰‡ä¸æ‡‰å…ˆæ‡‰ç”¨5.0.1å’Œ5.0.2的補ä¸ã€‚類似地,如果您é‹è¡Œçš„æ˜¯5.0.2內核,
- 並且希望跳轉到5.0.3,那麼在應用5.0.3補ä¸ä¹‹å‰ï¼Œå¿…須首先撤銷5.0.2補ä¸
+ 與6.x內核的補ä¸ä¸åŒï¼Œ6.x.y內核(也稱爲穩定版內核)的補ä¸ä¸æ˜¯å¢žé‡çš„,而是
+ 直接應用於基本的6.x內核。例如,如果您的基本內核是6.0,並且希望應用6.0.3
+ 補ä¸ï¼Œå‰‡ä¸æ‡‰å…ˆæ‡‰ç”¨6.0.1å’Œ6.0.2的補ä¸ã€‚類似地,如果您é‹è¡Œçš„æ˜¯6.0.2內核,
+ 並且希望跳轉到6.0.3,那麼在應用6.0.3補ä¸ä¹‹å‰ï¼Œå¿…須首先撤銷6.0.2補ä¸
(å³patch -R)。更多關於這方é¢çš„內容,請閱讀
:ref:`Documentation/process/applying-patches.rst <applying_patches>` 。
@@ -93,7 +93,7 @@ Linux內核5.x版本 <http://kernel.org/>
linux/scripts/patch-kernel linux
- 上é¢å‘½ä»¤ä¸­çš„ç¬¬ä¸€å€‹åƒæ•¸æ˜¯å…§æ ¸åŽŸå§‹ç¢¼çš„ä½ç½®ã€‚è£œä¸æ˜¯åœ¨ç•¶å‰ç›®éŒ„應用的,但是
+ 上é¢å‘½ä»¤ä¸­çš„ç¬¬ä¸€å€‹åƒæ•¸æ˜¯å…§æ ¸æºä»£ç¢¼çš„ä½ç½®ã€‚è£œä¸æ˜¯åœ¨ç•¶å‰ç›®éŒ„應用的,但是
å¯ä»¥å°‡å¦ä¸€å€‹ç›®éŒ„æŒ‡å®šçˆ²ç¬¬äºŒå€‹åƒæ•¸ã€‚
- ç¢ºä¿æ²’æœ‰éŽæ™‚çš„ .o 文件和ä¾è³´é …::
@@ -101,30 +101,30 @@ Linux內核5.x版本 <http://kernel.org/>
cd linux
make mrproper
- ç¾åœ¨æ‚¨æ‡‰è©²å·²ç¶“正確安è£äº†åŽŸå§‹ç¢¼ã€‚
+ ç¾åœ¨æ‚¨æ‡‰è©²å·²ç¶“正確安è£äº†æºä»£ç¢¼ã€‚
-è»Ÿé«”è¦æ±‚
+è»Ÿä»¶è¦æ±‚
---------
- 編譯和é‹è¡Œ5.x內核需è¦å„種軟體包的最新版本。請åƒè€ƒ
+ 編譯和é‹è¡Œ6.x內核需è¦å„種軟件包的最新版本。請åƒè€ƒ
:ref:`Documentation/process/changes.rst <changes>`
- ä¾†äº†è§£æœ€ä½Žç‰ˆæœ¬è¦æ±‚以åŠå¦‚何å‡ç´šè»Ÿé«”包。請注æ„,使用éŽèˆŠç‰ˆæœ¬çš„這些包å¯èƒ½æœƒ
+ ä¾†äº†è§£æœ€ä½Žç‰ˆæœ¬è¦æ±‚以åŠå¦‚何å‡ç´šè»Ÿä»¶åŒ…。請注æ„,使用éŽèˆŠç‰ˆæœ¬çš„這些包å¯èƒ½æœƒ
導致很難追蹤的間接錯誤,因此ä¸è¦ä»¥çˆ²åœ¨ç”Ÿæˆæˆ–æ“作éŽç¨‹ä¸­å‡ºç¾æ˜Žé¡¯å•題時å¯ä»¥
åªæ›´æ–°åŒ…。
爲內核建立目錄
---------------
- ç·¨è­¯å…§æ ¸æ™‚ï¼Œé»˜èªæƒ…æ³ä¸‹æ‰€æœ‰è¼¸å‡ºæ–‡ä»¶éƒ½å°‡èˆ‡å…§æ ¸åŽŸå§‹ç¢¼æ”¾åœ¨ä¸€èµ·ã€‚ä½¿ç”¨
+ ç·¨è­¯å…§æ ¸æ™‚ï¼Œé»˜èªæƒ…æ³ä¸‹æ‰€æœ‰è¼¸å‡ºæ–‡ä»¶éƒ½å°‡èˆ‡å…§æ ¸æºä»£ç¢¼æ”¾åœ¨ä¸€èµ·ã€‚使用
``make O=output/dir`` é¸é …å¯ä»¥çˆ²è¼¸å‡ºæ–‡ä»¶ï¼ˆåŒ…括 .config)指定備用ä½ç½®ã€‚
例如::
- kernel source code: /usr/src/linux-5.x
+ kernel source code: /usr/src/linux-6.x
build directory: /home/name/build/kernel
è¦é…置和構建內核,請使用::
- cd /usr/src/linux-5.x
+ cd /usr/src/linux-6.x
make O=/home/name/build/kernel menuconfig
make O=/home/name/build/kernel
sudo make O=/home/name/build/kernel modules_install install
@@ -136,7 +136,7 @@ Linux內核5.x版本 <http://kernel.org/>
å³ä½¿åªå‡ç´šä¸€å€‹å°ç‰ˆæœ¬ï¼Œä¹Ÿä¸è¦è·³éŽæ­¤æ­¥é©Ÿã€‚æ¯å€‹ç‰ˆæœ¬ä¸­éƒ½æœƒæ·»åŠ æ–°çš„é…ç½®é¸é …,
如果é…置文件沒有按é å®šè¨­ç½®ï¼Œå°±æœƒå‡ºç¾å¥‡æ€ªçš„å•題。如果您想以最少的工作é‡
- å°‡ç¾æœ‰é…ç½®å‡ç´šåˆ°æ–°ç‰ˆæœ¬ï¼Œè«‹ä½¿ç”¨ ``makeoldconfig`` ï¼Œå®ƒåªæœƒè©¢å•您新é…ç½®
+ å°‡ç¾æœ‰é…ç½®å‡ç´šåˆ°æ–°ç‰ˆæœ¬ï¼Œè«‹ä½¿ç”¨ ``make oldconfig`` ï¼Œå®ƒåªæœƒè©¢å•您新é…ç½®
é¸é …的答案。
- å…¶ä»–é…置命令包括::
@@ -164,17 +164,17 @@ Linux內核5.x版本 <http://kernel.org/>
"make ${PLATFORM}_defconfig"
使用arch/$arch/configs/${PLATFORM}_defconfig中
的默èªé¸é …值創建一個./.config文件。
- 用「makehelpã€ä¾†ç²å–您體系架構中所有å¯ç”¨å¹³å°çš„列表。
+ 用“make helpâ€ä¾†ç²å–您體系架構中所有å¯ç”¨å¹³è‡ºçš„列表。
"make allyesconfig"
- 通éŽå„˜å¯èƒ½å°‡é¸é …值設置爲「yã€ï¼Œå‰µå»ºä¸€å€‹
+ 通éŽå„˜å¯èƒ½å°‡é¸é …值設置爲“yâ€ï¼Œå‰µå»ºä¸€å€‹
./.config文件。
"make allmodconfig"
- 通éŽå„˜å¯èƒ½å°‡é¸é …值設置爲「mã€ï¼Œå‰µå»ºä¸€å€‹
+ 通éŽå„˜å¯èƒ½å°‡é¸é …值設置爲“mâ€ï¼Œå‰µå»ºä¸€å€‹
./.config文件。
- "make allnoconfig" 通éŽå„˜å¯èƒ½å°‡é¸é …值設置爲「nã€ï¼Œå‰µå»ºä¸€å€‹
+ "make allnoconfig" 通éŽå„˜å¯èƒ½å°‡é¸é …值設置爲“nâ€ï¼Œå‰µå»ºä¸€å€‹
./.config文件。
"make randconfig" 通éŽéš¨æ©Ÿè¨­ç½®é¸é …值來創建./.config文件。
@@ -182,7 +182,7 @@ Linux內核5.x版本 <http://kernel.org/>
"make localmodconfig" 基於當å‰é…置和加載的模塊(lsmod)創建é…置。ç¦ç”¨
已加載的模塊ä¸éœ€è¦çš„任何模塊é¸é …。
- è¦çˆ²å¦ä¸€å°è¨ˆç®—機創建localmodconfig,請將該計算機
+ è¦çˆ²å¦ä¸€è‡ºè¨ˆç®—機創建localmodconfig,請將該計算機
çš„lsmod存儲到一個文件中,並將其作爲lsmodåƒæ•¸å‚³å…¥ã€‚
此外,通éŽåœ¨åƒæ•¸LMC_KEEP中指定模塊的路徑,å¯ä»¥å°‡
@@ -200,9 +200,10 @@ Linux內核5.x版本 <http://kernel.org/>
"make localyesconfig" 與localmodconfigé¡žä¼¼ï¼Œåªæ˜¯å®ƒæœƒå°‡æ‰€æœ‰æ¨¡å¡Šé¸é …轉æ›
爲內置(=y)。你å¯ä»¥åŒæ™‚通éŽLMC_KEEPä¿ç•™æ¨¡å¡Šã€‚
- "make kvmconfig" 爲kvm客體內核支æŒå•“用其他é¸é …。
+ "make kvm_guest.config"
+ 爲kvm客戶機內核支æŒå•“用其他é¸é …。
- "make xenconfig" 爲xen dom0客體內核支æŒå•“用其他é¸é …。
+ "make xen.config" 爲xen dom0客戶機內核支æŒå•“用其他é¸é …。
"make tinyconfig" é…置儘å¯èƒ½å°çš„內核。
@@ -218,10 +219,10 @@ Linux內核5.x版本 <http://kernel.org/>
這種情æ³ä¸‹ï¼Œæ•¸å­¸ä»¿çœŸæ°¸é ä¸æœƒè¢«ä½¿ç”¨ã€‚內核會ç¨å¾®å¤§ä¸€é»žï¼Œä½†ä¸ç®¡
æ˜¯å¦æœ‰æ•¸å­¸å”處ç†å™¨ï¼Œéƒ½å¯ä»¥åœ¨ä¸åŒçš„æ©Ÿå™¨ä¸Šå·¥ä½œã€‚
- - 「kernel hackingã€é…置細節通常會導致更大或更慢的內核(或兩者
+ - “kernel hackingâ€é…置細節通常會導致更大或更慢的內核(或兩者
兼而有之),甚至å¯ä»¥é€šéŽé…置一些例程來主動嘗試破壞壞代碼以發ç¾
å…§æ ¸å•題,從而é™ä½Žå…§æ ¸çš„穩定性(kmalloc())。因此,您å¯èƒ½æ‡‰è©²
- 用於研究「開發ã€ã€ã€Œå¯¦é©—ã€æˆ–「調試ã€ç‰¹æ€§ç›¸é—œå•題。
+ 用於研究“開發â€ã€â€œå¯¦é©—â€æˆ–“調試â€ç‰¹æ€§ç›¸é—œå•題。
編譯內核
---------
@@ -229,10 +230,8 @@ Linux內核5.x版本 <http://kernel.org/>
- ç¢ºä¿æ‚¨è‡³å°‘有gcc 5.1å¯ç”¨ã€‚
有關更多信æ¯ï¼Œè«‹åƒé–± :ref:`Documentation/process/changes.rst <changes>` 。
- 請注æ„,您ä»ç„¶å¯ä»¥ä½¿ç”¨æ­¤å…§æ ¸é‹è¡Œa.out用戶程åºã€‚
-
- 執行 ``make`` 來創建壓縮內核映åƒã€‚如果您安è£äº†lilo以é©é…å…§æ ¸makefile,
- 那麼也å¯ä»¥é€²è¡Œ ``makeinstall`` ,但是您å¯èƒ½éœ€è¦å…ˆæª¢æŸ¥ç‰¹å®šçš„lilo設置。
+ 那麼也å¯ä»¥é€²è¡Œ ``make install`` ,但是您å¯èƒ½éœ€è¦å…ˆæª¢æŸ¥ç‰¹å®šçš„lilo設置。
實際安è£å¿…須以root身份執行,但任何正常構建都ä¸éœ€è¦ã€‚
無須徒然使用root身份。
@@ -242,8 +241,8 @@ Linux內核5.x版本 <http://kernel.org/>
- 詳細的內核編譯/生æˆè¼¸å‡ºï¼š
通常,內核構建系統在相當安éœçš„æ¨¡å¼ä¸‹é‹è¡Œï¼ˆä½†ä¸æ˜¯å®Œå…¨å®‰éœï¼‰ã€‚但是有時您或
- 其他內核開發人員需è¦çœ‹åˆ°ç·¨è­¯ã€é€£çµæˆ–其他命令的執行éŽç¨‹ã€‚爲此,å¯ä½¿ç”¨
- 「verboseï¼ˆè©³ç´°ï¼‰ã€æ§‹å»ºæ¨¡å¼ã€‚
+ 其他內核開發人員需è¦çœ‹åˆ°ç·¨è­¯ã€éˆæŽ¥æˆ–其他命令的執行éŽç¨‹ã€‚爲此,å¯ä½¿ç”¨
+ “verboseï¼ˆè©³ç´°ï¼‰â€æ§‹å»ºæ¨¡å¼ã€‚
å‘ ``make`` å‘½ä»¤å‚³éž ``V=1`` 來實ç¾ï¼Œä¾‹å¦‚::
make V=1 all
@@ -255,15 +254,15 @@ Linux內核5.x版本 <http://kernel.org/>
與工作內核版本號相åŒçš„æ–°å…§æ ¸ï¼Œè«‹åœ¨é€²è¡Œ ``make modules_install`` 安è£
之å‰å‚™ä»½modules目錄。
- 或者,在編譯之å‰ï¼Œä½¿ç”¨å…§æ ¸é…ç½®é¸é …「LOCALVERSIONã€å‘常è¦å…§æ ¸ç‰ˆæœ¬é™„加
- 一個唯一的後綴。LOCALVERSIONå¯ä»¥åœ¨ã€ŒGeneral Setupã€èœå–®ä¸­è¨­ç½®ã€‚
+ 或者,在編譯之å‰ï¼Œä½¿ç”¨å…§æ ¸é…ç½®é¸é …“LOCALVERSIONâ€å‘常è¦å…§æ ¸ç‰ˆæœ¬é™„加
+ 一個唯一的後綴。LOCALVERSIONå¯ä»¥åœ¨â€œGeneral Setupâ€èœå–®ä¸­è¨­ç½®ã€‚
- 爲了引導新內核,您需è¦å°‡å…§æ ¸æ˜ åƒï¼ˆä¾‹å¦‚編譯後的
.../linux/arch/x86/boot/bzImage)複製到常è¦å¯å¼•導內核的ä½ç½®ã€‚
- ä¸å†æ”¯æŒåœ¨æ²’有LILO等啓動è£è¼‰ç¨‹åºå¹«åŠ©çš„æƒ…æ³ä¸‹ç›´æŽ¥å¾žè»Ÿç›¤å¼•導內核。
- 如果從硬碟引導Linux,很å¯èƒ½ä½¿ç”¨LILO,它使用/etc/lilo.conf文件中
+ 如果從硬盤引導Linux,很å¯èƒ½ä½¿ç”¨LILO,它使用/etc/lilo.conf文件中
æŒ‡å®šçš„å…§æ ¸æ˜ åƒæ–‡ä»¶ã€‚å…§æ ¸æ˜ åƒæ–‡ä»¶é€šå¸¸æ˜¯/vmlinuzã€/boot/vmlinuzã€
/bzImage或/boot/bzImage。使用新內核å‰ï¼Œè«‹ä¿å­˜èˆŠæ˜ åƒçš„副本,並複製
新映åƒè¦†è“‹èˆŠæ˜ åƒã€‚然後您ã€å¿…é ˆé‡æ–°é‹è¡ŒLILO】來更新加載映射ï¼å¦å‰‡ï¼Œ
@@ -284,68 +283,13 @@ Linux內核5.x版本 <http://kernel.org/>
è‹¥é‡åˆ°å•題
-----------
- - 如果您發ç¾äº†ä¸€äº›å¯èƒ½ç”±æ–¼å…§æ ¸ç¼ºé™·æ‰€å°Žè‡´çš„å•題,請檢查MAINTAINERS(維護者)
- æ–‡ä»¶çœ‹çœ‹æ˜¯å¦æœ‰äººèˆ‡ä»¤æ‚¨é‡åˆ°éº»ç…©çš„內核部分相關。如果無人在此列出,那麼第二
- 個最好的方案就是把它們發給我(torvalds@linux-foundation.org),也å¯èƒ½ç™¼é€
- 到任何其他相關的郵件列表或新èžçµ„。
-
- - 在所有的缺陷報告中,ã€è«‹ã€‘告訴我們您在說什麼內核,如何復ç¾å•é¡Œï¼Œä»¥åŠæ‚¨çš„
- 設置是什麼的(使用您的常識)。如果å•題是新的,請告訴我;如果å•題是舊的,
- 請嘗試告訴我您什麼時候首次注æ„到它。
-
- - 如果缺陷導致如下消æ¯::
-
- unable to handle kernel paging request at address C0000010
- Oops: 0002
- EIP: 0010:XXXXXXXX
- eax: xxxxxxxx ebx: xxxxxxxx ecx: xxxxxxxx edx: xxxxxxxx
- esi: xxxxxxxx edi: xxxxxxxx ebp: xxxxxxxx
- ds: xxxx es: xxxx fs: xxxx gs: xxxx
- Pid: xx, process nr: xx
- xx xx xx xx xx xx xx xx xx xx
-
- 或者類似的內核調試信æ¯é¡¯ç¤ºåœ¨å±å¹•上或在系統日誌里,請ã€å¦‚實】複製它。
- å¯èƒ½å°ä½ ä¾†èªªè½‰å„²ï¼ˆdump)看起來ä¸å¯ç†è§£ï¼Œä½†å®ƒç¢ºå¯¦åŒ…å«å¯èƒ½æœ‰åŠ©æ–¼èª¿è©¦å•題的
- ä¿¡æ¯ã€‚轉儲上方的文本也很é‡è¦ï¼šå®ƒèªªæ˜Žäº†å…§æ ¸è½‰å„²ä»£ç¢¼çš„原因(在上é¢çš„示例中,
- 是由於內核指é‡éŒ¯èª¤ï¼‰ã€‚更多關於如何ç†è§£è½‰å„²çš„ä¿¡æ¯ï¼Œè«‹åƒè¦‹
- Documentation/admin-guide/bug-hunting.rst。
-
- - 如果使用 CONFIG_KALLSYMS 編譯內核,則å¯ä»¥æŒ‰åŽŸæ¨£ç™¼é€è½‰å„²ï¼Œå¦å‰‡å¿…須使用
- ``ksymoops`` 程åºä¾†ç†è§£è½‰å„²ï¼ˆä½†é€šå¸¸é¦–é¸ä½¿ç”¨CONFIG_KALLSYMS編譯)。
- 此實用程åºå¯å¾ž
- https://www.kernel.org/pub/linux/utils/kernel/ksymoops/ 下載。
- 或者,您å¯ä»¥æ‰‹å‹•執行轉儲查找:
-
- - 在調試åƒä¸Šé¢é€™æ¨£çš„轉儲時,如果您å¯ä»¥æŸ¥æ‰¾EIP值的å«ç¾©ï¼Œé€™å°‡éžå¸¸æœ‰å¹«åŠ©ã€‚
- å六進ä½å€¼æœ¬èº«å°æˆ‘æˆ–å…¶ä»–ä»»ä½•äººéƒ½æ²’æœ‰å¤ªå¤§å¹«åŠ©ï¼šå®ƒæœƒå–æ±ºæ–¼ç‰¹å®šçš„內核設置。
- 您應該åšçš„æ˜¯å¾žEIP行ç²å–å六進ä½å€¼ï¼ˆå¿½ç•¥ ``0010:`` ),然後在內核å字列表
- ä¸­æŸ¥æ‰¾å®ƒï¼Œä»¥æŸ¥çœ‹å“ªå€‹å…§æ ¸å‡½æ•¸åŒ…å«æœ‰å•題的地å€ã€‚
-
- è¦æ‰¾åˆ°å…§æ ¸å‡½æ•¸åï¼Œæ‚¨éœ€è¦æ‰¾åˆ°èˆ‡é¡¯ç¤ºç—‡ç‹€çš„內核相關è¯çš„ç³»çµ±äºŒé€²ä½æ–‡ä»¶ã€‚就是
- 文件「linux/vmlinuxã€ã€‚è¦æå–å字列表並將其與內核崩潰中的EIP進行匹é…,
- 請執行::
-
- nm vmlinux | sort | less
-
- 這將爲您æä¾›ä¸€å€‹æŒ‰å‡åºæŽ’åºçš„內核地å€åˆ—è¡¨ï¼Œå¾žä¸­å¾ˆå®¹æ˜“æ‰¾åˆ°åŒ…å«æœ‰å•題的地å€
- 的函數。請注æ„ï¼Œå…§æ ¸èª¿è©¦æ¶ˆæ¯æä¾›çš„åœ°å€ä¸ä¸€å®šèˆ‡å‡½æ•¸åœ°å€å®Œå…¨åŒ¹é…(事實上,
- 這是ä¸å¯èƒ½çš„),因此您ä¸èƒ½åªã€Œgrepã€åˆ—表:ä¸éŽåˆ—表將爲您æä¾›æ¯å€‹å…§æ ¸å‡½æ•¸
- çš„èµ·é»žï¼Œå› æ­¤é€šéŽæŸ¥æ‰¾èµ·å§‹åœ°å€ä½Žæ–¼ä½ æ­£åœ¨æœç´¢çš„地å€ï¼Œä½†å¾Œä¸€å€‹å‡½æ•¸çš„高於的
- 函數,你會找到您想è¦çš„。實際上,在您的å•題報告中加入一些「上下文ã€å¯èƒ½æ˜¯
- 一個好主æ„,給出相關的上下幾行。
-
- 如果您由於æŸäº›åŽŸå› ç„¡æ³•å®Œæˆä¸Šè¿°æ“作(如您使用é ç·¨è­¯çš„å…§æ ¸æ˜ åƒæˆ–類似的映åƒï¼‰ï¼Œ
- 請儘å¯èƒ½å¤šåœ°å‘Šè¨´æˆ‘您的相關設置信æ¯ï¼Œé€™æœƒæœ‰æ‰€å¹«åŠ©ã€‚æœ‰é—œè©³ç´°ä¿¡æ¯è«‹é–±è®€
- 『Documentation/admin-guide/reporting-issues.rstã€ã€‚
-
- - 或者,您å¯ä»¥åœ¨æ­£åœ¨é‹è¡Œçš„內核上使用gdb(åªè®€çš„ï¼›å³ä¸èƒ½æ›´æ”¹å€¼æˆ–設置斷點)。
- 爲此,請首先使用-g編譯內核;é©ç•¶åœ°ç·¨è¼¯arch/x86/Makefile,然後執行 ``make
- clean`` 。您還需è¦å•“用CONFIG_PROC_FSï¼ˆé€šéŽ ``make config`` )。
-
- ä½¿ç”¨æ–°å…§æ ¸é‡æ–°å•“動後,執行 ``gdb vmlinux /proc/kcore`` 。ç¾åœ¨å¯ä»¥ä½¿ç”¨æ‰€æœ‰
- 普通的gdb命令。查找系統崩潰點的命令是 ``l *0xXXXXXXXX`` (將xxx替æ›çˆ²EIP
- 值)。
-
- 用gdbç„¡æ³•èª¿è©¦ä¸€å€‹ç•¶å‰æœªé‹è¡Œçš„內核是由於gdb(錯誤地)忽略了編譯內核的起始
- åç§»é‡ã€‚
+如果您發ç¾äº†ä¸€äº›å¯èƒ½ç”±æ–¼å…§æ ¸ç¼ºé™·æ‰€å°Žè‡´çš„å•題,請åƒé–±ï¼š
+Documentation/translations/zh_CN/admin-guide/reporting-issues.rst 。
+
+想è¦ç†è§£å…§æ ¸éŒ¯èª¤å ±å‘Šï¼Œè«‹åƒé–±ï¼š
+Documentation/translations/zh_CN/admin-guide/bug-hunting.rst 。
+
+更多用GDB調試內核的信æ¯ï¼Œè«‹åƒé–±ï¼š
+Documentation/translations/zh_CN/dev-tools/gdb-kernel-debugging.rst
+和 Documentation/dev-tools/kgdb.rst 。
diff --git a/Documentation/translations/zh_TW/admin-guide/bootconfig.rst b/Documentation/translations/zh_TW/admin-guide/bootconfig.rst
new file mode 100644
index 000000000000..abac5aa60f67
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/bootconfig.rst
@@ -0,0 +1,294 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/bootconfig.rst
+
+:譯者: 峿ƒ³æˆ Wu XiangCheng <bobwxc@email.cn>
+
+========
+引導é…ç½®
+========
+
+:作者: Masami Hiramatsu <mhiramat@kernel.org>
+
+概述
+====
+
+引導é…ç½®æ“´å±•äº†ç¾æœ‰çš„內核命令行,以一種更有效率的方å¼åœ¨å¼•導內核時進一步支æŒ
+éµå€¼æ•¸æ“šã€‚這å…許管ç†å“¡å‚³éžä¸€ä»½çµæ§‹åŒ–é—œéµå­—çš„é…置文件。
+
+é…置文件語法
+============
+
+引導é…置文件的語法採用éžå¸¸ç°¡å–®çš„éµå€¼çµæ§‹ã€‚æ¯å€‹é—œéµå­—由點連接的單詞組æˆï¼Œéµ
+和值由 ``=`` 連接。值以分號( ``;`` )或æ›è¡Œç¬¦ï¼ˆ ``\n`` )çµå°¾ã€‚數組值中æ¯
+個元素由逗號( ``,`` )分隔。::
+
+ KEY[.WORD[...]] = VALUE[, VALUE2[...]][;]
+
+與內核命令行語法ä¸åŒï¼Œé€—號和 ``=`` 周åœå…許有空格。
+
+é—œéµå­—åªå…許包å«å­—æ¯ã€æ•¸å­—ã€é€£å­—符( ``-`` )和下劃線( ``_`` )。值å¯åŒ…å«
+坿‰“å°å­—符和空格,但分號( ``;`` ï¼‰ã€æ›è¡Œç¬¦ï¼ˆ ``\n`` )ã€é€—號( ``,`` )ã€
+井號( ``#`` )和å³å¤§æ‹¬è™Ÿï¼ˆ ``}`` )等分隔符除外。
+
+如果你需è¦åœ¨å€¼ä¸­ä½¿ç”¨é€™äº›åˆ†éš”符,å¯ä»¥ç”¨é›™å¼•號( ``"VALUE"`` )或單引號
+( ``'VALUE'`` )括起來。注æ„,引號無法轉義。
+
+éµçš„值å¯ä»¥çˆ²ç©ºæˆ–ä¸å­˜åœ¨ã€‚這些éµç”¨æ–¼æª¢æŸ¥è©²éµæ˜¯å¦å­˜åœ¨ï¼ˆé¡žä¼¼å¸ƒçˆ¾å€¼ï¼‰ã€‚
+
+éµå€¼èªžæ³•
+--------
+
+引導é…置文件語法å…許用戶通éŽå¤§æ‹¬è™Ÿåˆä½µéµå部分相åŒçš„é—œéµå­—。例如::
+
+ foo.bar.baz = value1
+ foo.bar.qux.quux = value2
+
+也å¯ä»¥å¯«æˆ::
+
+ foo.bar {
+ baz = value1
+ qux.quux = value2
+ }
+
+或者更緊湊一些,寫æˆ::
+
+ foo.bar { baz = value1; qux.quux = value2 }
+
+在這兩種樣å¼ä¸­ï¼Œå¼•å°Žè§£æžæ™‚相åŒçš„é—œéµå­—都會自動åˆä½µã€‚å› æ­¤å¯ä»¥è¿½åŠ é¡žä¼¼çš„æ¨¹æˆ–
+éµå€¼ã€‚
+
+相åŒé—œéµå­—的值
+--------------
+
+ç¦æ­¢å…©å€‹æˆ–多個值或數組共享åŒä¸€å€‹é—œéµå­—。例如::
+
+ foo = bar, baz
+ foo = qux # !錯誤! 我們ä¸å¯ä»¥é‡å®šç¾©ç›¸åŒçš„é—œéµå­—
+
+å¦‚æžœä½ æƒ³è¦æ›´æ–°å€¼ï¼Œå¿…須顯å¼ä½¿ç”¨è¦†è“‹æ“作符 ``:=`` 。例如::
+
+ foo = bar, baz
+ foo := qux
+
+這樣 ``foo`` é—œéµå­—的值就變æˆäº† ``qux`` ã€‚é€™å°æ–¼é€šéŽæ·»åŠ ï¼ˆéƒ¨åˆ†ï¼‰è‡ªå®šç¾©å¼•å°Ž
+é…置來覆蓋默èªå€¼éžå¸¸æœ‰ç”¨ï¼Œå…於解æžé»˜èªå¼•å°Žé…置。
+
+如果你想å°ç¾æœ‰é—œéµå­—追加值作爲數組æˆå“¡ï¼Œå¯ä»¥ä½¿ç”¨ ``+=`` æ“作符。例如::
+
+ foo = bar, baz
+ foo += qux
+
+這樣, ``foo`` é—œéµå­—å°±åŒæ™‚æ“æœ‰äº† ``bar`` , ``baz`` å’Œ ``qux`` 。
+
+此外,父關éµå­—下å¯åŒæ™‚存在值和å­é—œéµå­—。
+例如,下列é…置是å¯è¡Œçš„。::
+
+ foo = value1
+ foo.bar = value2
+ foo := value3 # 這會更新foo的值。
+
+注æ„,裸值ä¸èƒ½ç›´æŽ¥æ”¾é€²çµæ§‹åŒ–é—œéµå­—中,必須在大括號外定義它。例如::
+
+ foo {
+ bar = value1
+ bar {
+ baz = value2
+ qux = value3
+ }
+ }
+
+åŒæ™‚,關éµå­—ä¸‹å€¼ç¯€é»žçš„é †åºæ˜¯å›ºå®šçš„。如果值和å­é—œéµå­—åŒæ™‚å­˜åœ¨ï¼Œå€¼æ°¸é æ˜¯è©²é—œ
+éµå­—的第一個å­ç¯€é»žã€‚因此如果用戶先指定å­é—œéµå­—,如::
+
+ foo.bar = value1
+ foo = value2
+
+則在程åºï¼ˆå’Œ/proc/bootconfig)中,它會按如下顯示::
+
+ foo = value2
+ foo.bar = value1
+
+註釋
+----
+
+é…置語法接å—shell腳本風格的註釋。註釋以井號( ``#`` )開始,到æ›è¡Œç¬¦
+( ``\n`` ï¼‰çµæŸã€‚
+
+::
+
+ # comment line
+ foo = value # value is set to foo.
+ bar = 1, # 1st element
+ 2, # 2nd element
+ 3 # 3rd element
+
+會被解æžçˆ²::
+
+ foo = value
+ bar = 1, 2, 3
+
+注æ„ä½ ä¸èƒ½æŠŠè¨»é‡‹æ”¾åœ¨å€¼å’Œåˆ†éš”符( ``,`` 或 ``;`` )之間。如下é…置語法是錯誤的::
+
+ key = 1 # comment
+ ,2
+
+
+/proc/bootconfig
+================
+
+/proc/bootconfig是引導é…置的用戶空間接å£ã€‚與/proc/cmdlineä¸åŒï¼Œæ­¤æ–‡ä»¶å…§å®¹ä»¥
+éµå€¼åˆ—表樣å¼é¡¯ç¤ºã€‚
+æ¯å€‹éµå€¼å°ä¸€è¡Œï¼Œæ¨£å¼å¦‚下::
+
+ KEY[.WORDS...] = "[VALUE]"[,"VALUE2"...]
+
+
+用引導é…置引導內核
+==================
+
+用引導é…置引導內核有兩種方法:將引導é…置附加到initrdé¡åƒæˆ–直接嵌入內核中。
+
+*initrd: initial RAM disk,åˆå§‹å…§å­˜ç£ç›¤*
+
+將引導é…置附加到initrd
+----------------------
+
+ç”±æ–¼é»˜èªæƒ…æ³ä¸‹å¼•å°Žé…置文件是用initrd加載的,因此它將被添加到initrd(initramfs)
+é¡åƒæ–‡ä»¶çš„æœ«å°¾ï¼Œå…¶ä¸­åŒ…å«å¡«å……ã€å¤§å°ã€æ ¡é©—值和12字節幻數,如下所示::
+
+ [initrd][bootconfig][padding][size(le32)][checksum(le32)][#BOOTCONFIG\n]
+
+大å°å’Œæ ¡é©—值爲å°ç«¯åºå­˜æ”¾çš„32ä½ç„¡ç¬¦è™Ÿå€¼ã€‚
+
+當引導é…置被加到initrdé¡åƒæ™‚ï¼Œæ•´å€‹æ–‡ä»¶å¤§å°æœƒå°é½Šåˆ°4字節。空字符( ``\0`` )
+會填補å°é½Šç©ºéš™ã€‚å› æ­¤ ``size`` 就是引導é…置文件的長度+填充的字節。
+
+Linux內核在內存中解碼initrdé¡åƒçš„æœ€å¾Œéƒ¨åˆ†ä»¥ç²å–引導é…置數據。由於這種“æ¹è² å¼â€
+的方法,åªè¦å¼•導加載器傳éžäº†æ­£ç¢ºçš„initrd文件大å°ï¼Œå°±ç„¡éœ€æ›´æ”¹æˆ–更新引導加載器
+和內核é¡åƒæœ¬èº«ã€‚如果引導加載器æ„外傳éžäº†æ›´é•·çš„大å°ï¼Œå…§æ ¸å°‡ç„¡æ³•找到引導é…置數
+據。
+
+Linux內核在tools/bootconfig下æä¾›äº† ``bootconfig`` å‘½ä»¤ä¾†å®Œæˆæ­¤æ“作,管ç†å“¡
+å¯ä»¥ç”¨å®ƒå¾žinitrdé¡åƒä¸­åˆªé™¤æˆ–追加é…置文件。你å¯ä»¥ç”¨ä»¥ä¸‹å‘½ä»¤ä¾†æ§‹å»ºå®ƒ::
+
+ # make -C tools/bootconfig
+
+è¦å‘initrdé¡åƒæ·»åŠ ä½ çš„å¼•å°Žé…置文件,請按如下命令æ“作(舊數據會自動移除)::
+
+ # tools/bootconfig/bootconfig -a your-config /boot/initrd.img-X.Y.Z
+
+è¦å¾žé¡åƒä¸­ç§»é™¤é…置,å¯ä»¥ä½¿ç”¨-dé¸é …::
+
+ # tools/bootconfig/bootconfig -d /boot/initrd.img-X.Y.Z
+
+然後在內核命令行上添加 ``bootconfig`` 告訴內核去initrd文件末尾尋找內核é…置。
+
+將引導é…置嵌入內核
+------------------
+
+如果你ä¸èƒ½ä½¿ç”¨initrd,也å¯ä»¥é€šéŽKconfigé¸é …將引導é…置文件嵌入內核中。在此情
+æ³ä¸‹ï¼Œä½ éœ€è¦ç”¨ä»¥ä¸‹é¸é …釿–°ç·¨è­¯å…§æ ¸::
+
+ CONFIG_BOOT_CONFIG_EMBED=y
+ CONFIG_BOOT_CONFIG_EMBED_FILE="/引導é…ç½®/文件/çš„/路徑"
+
+``CONFIG_BOOT_CONFIG_EMBED_FILE`` 需è¦å¾žæºç¢¼æ¨¹æˆ–å°è±¡æ¨¹é–‹å§‹çš„引導é…置文件的
+絕å°/相å°è·¯å¾‘。內核會將其嵌入作爲默èªå¼•å°Žé…置。
+
+與將引導é…置附加到initrd一樣,你也需è¦åœ¨å…§æ ¸å‘½ä»¤è¡Œä¸Šæ·»åŠ  ``bootconfig`` 告訴
+內核去啓用內嵌的引導é…置。
+
+注æ„,å³ä½¿ä½ å·²ç¶“設置了此é¸é …,ä»å¯ç”¨é™„加到initrd的其他引導é…置覆蓋內嵌的引導
+é…置。
+
+通éŽå¼•å°Žé…置傳éžå…§æ ¸åƒæ•¸
+========================
+
+除了內核命令行,引導é…置也å¯ä»¥ç”¨æ–¼å‚³éžå…§æ ¸åƒæ•¸ã€‚所有 ``kernel`` é—œéµå­—下的éµ
+值å°éƒ½å°‡ç›´æŽ¥å‚³éžçµ¦å…§æ ¸å‘½ä»¤è¡Œã€‚此外, ``init`` 下的éµå€¼å°å°‡é€šéŽå‘½ä»¤è¡Œå‚³éžçµ¦
+inité€²ç¨‹ã€‚åƒæ•¸æŒ‰ä»¥ä¸‹é †åºèˆ‡ç”¨æˆ¶çµ¦å®šçš„å…§æ ¸å‘½ä»¤è¡Œå­—ç¬¦ä¸²ç›¸é€£ï¼Œå› æ­¤å‘½ä»¤è¡Œåƒæ•¸å¯ä»¥
+覆蓋引導é…ç½®åƒæ•¸ï¼ˆé€™å–決於å­ç³»çµ±å¦‚何處ç†åƒæ•¸ï¼Œä½†é€šå¸¸å‰é¢çš„åƒæ•¸å°‡è¢«å¾Œé¢çš„åƒæ•¸
+覆蓋)::
+
+ [bootconfig params][cmdline params] -- [bootconfig init params][cmdline init params]
+
+如果引導é…置文件給出的kernel/initåƒæ•¸æ˜¯::
+
+ kernel {
+ root = 01234567-89ab-cdef-0123-456789abcd
+ }
+ init {
+ splash
+ }
+
+這將被複制到內核命令行字符串中,如下所示::
+
+ root="01234567-89ab-cdef-0123-456789abcd" -- splash
+
+如果用戶給出的其他命令行是::
+
+ ro bootconfig -- quiet
+
+則最後的內核命令行如下::
+
+ root="01234567-89ab-cdef-0123-456789abcd" ro bootconfig -- splash quiet
+
+
+é…置文件的é™åˆ¶
+==============
+
+ç•¶å‰æœ€å¤§çš„é…ç½®å¤§å°æ˜¯32KB,關éµå­—ç¸½æ•¸ï¼ˆä¸æ˜¯éµå€¼æ¢ç›®ï¼‰å¿…須少於1024個節點。
+注æ„ï¼šé€™ä¸æ˜¯æ¢ç›®æ•¸è€Œæ˜¯ç¯€é»žæ•¸ï¼Œæ¢ç›®å¿…須消耗超éŽ2個節點(一個關éµå­—和一個值)。
+所以從ç†è«–上講最多512個éµå€¼å°ã€‚如果關éµå­—å¹³å‡åŒ…å«3å€‹å–®è©žï¼Œå‰‡å¯æœ‰256個éµå€¼å°ã€‚
+在大多數情æ³ä¸‹ï¼Œé…置項的數é‡å°‡å°‘æ–¼100個æ¢ç›®ï¼Œå°æ–¼8KB,因此這應該足夠了。如果
+節點數超éŽ1024,解æžå™¨å°‡è¿”回錯誤,å³ä½¿æ–‡ä»¶å¤§å°å°æ–¼32KB。(請注æ„,此最大尺寸
+ä¸åŒ…括填充的空字符。)
+無論如何,因爲 ``bootconfig`` 命令在附加啓動é…置到initrdæ˜ åƒæ™‚會驗證它,用戶
+å¯ä»¥åœ¨å¼•å°Žä¹‹å‰æ³¨æ„到它。
+
+
+引導é…ç½®API
+===========
+
+用戶å¯ä»¥æŸ¥è©¢æˆ–éæ­·éµå€¼å°ï¼Œä¹Ÿå¯ä»¥æŸ¥æ‰¾ï¼ˆå‰ç¶´ï¼‰æ ¹é—œéµå­—節點,並在查找該節點下的
+éµå€¼ã€‚
+
+如果您有一個關éµå­—字符串,則å¯ä»¥ç›´æŽ¥ä½¿ç”¨ xbc_find_value() 查詢該éµçš„值。如果
+你想知é“引導é…ç½®è£æœ‰å“ªäº›é—œéµå­—,å¯ä»¥ä½¿ç”¨ xbc_for_each_key_value() 迭代éµå€¼å°ã€‚
+請注æ„,您需è¦ä½¿ç”¨ xbc_array_for_each_value() è¨ªå•æ•¸çµ„的值,例如::
+
+ vnode = NULL;
+ xbc_find_value("key.word", &vnode);
+ if (vnode && xbc_node_is_array(vnode))
+ xbc_array_for_each_value(vnode, value) {
+ printk("%s ", value);
+ }
+
+如果您想查找具有å‰ç¶´å­—符串的éµï¼Œå¯ä»¥ä½¿ç”¨ xbc_find_node() 通éŽå‰ç¶´å­—符串查找
+節點,然後用 xbc_node_for_each_key_value() 迭代å‰ç¶´ç¯€é»žä¸‹çš„éµã€‚
+
+但最典型的用法是ç²å–å‰ç¶´ä¸‹çš„命å值或å‰ç¶´ä¸‹çš„命忕¸çµ„,例如::
+
+ root = xbc_find_node("key.prefix");
+ value = xbc_node_find_value(root, "option", &vnode);
+ ...
+ xbc_node_for_each_array_value(root, "array-option", value, anode) {
+ ...
+ }
+
+這將訪å•值“key.prefix.optionâ€çš„值和“key.prefix.array-optionâ€çš„æ•¸çµ„。
+
+鎖是ä¸éœ€è¦çš„,因爲在åˆå§‹åŒ–之後é…ç½®åªè®€ã€‚如果需è¦ä¿®æ”¹ï¼Œå¿…須複製所有數據和關éµå­—。
+
+
+å‡½æ•¸èˆ‡çµæ§‹é«”
+============
+
+相關定義的kernel-docåƒè¦‹ï¼š
+
+ - include/linux/bootconfig.h
+ - lib/bootconfig.c
+
diff --git a/Documentation/translations/zh_TW/admin-guide/bug-bisect.rst b/Documentation/translations/zh_TW/admin-guide/bug-bisect.rst
index b448dbf5ac87..3f10a9f8f223 100644
--- a/Documentation/translations/zh_TW/admin-guide/bug-bisect.rst
+++ b/Documentation/translations/zh_TW/admin-guide/bug-bisect.rst
@@ -17,14 +17,14 @@
引言
=====
-始終嘗試由來自kernel.org的原始碼構建的最新內核。如果您沒有信心這樣åšï¼Œè«‹å°‡
+始終嘗試由來自kernel.orgçš„æºä»£ç¢¼æ§‹å»ºçš„æœ€æ–°å…§æ ¸ã€‚如果您沒有信心這樣åšï¼Œè«‹å°‡
éŒ¯èª¤å ±å‘Šçµ¦æ‚¨çš„ç™¼è¡Œç‰ˆä¾›æ‡‰å•†ï¼Œè€Œä¸æ˜¯å…§æ ¸é–‹ç™¼äººå“¡ã€‚
找到缺陷(bug)並ä¸ç¸½æ˜¯é‚£éº¼å®¹æ˜“,ä¸éŽä»ç„¶å¾—去找。如果你找ä¸åˆ°å®ƒï¼Œä¸è¦æ”¾æ£„。
-儘å¯èƒ½å¤šçš„å‘相關維護人員報告您發ç¾çš„ä¿¡æ¯ã€‚è«‹åƒé–±MAINTAINERS文件以了解您所
+儘å¯èƒ½å¤šçš„å‘相關維護人員報告您發ç¾çš„ä¿¡æ¯ã€‚è«‹åƒé–±MAINTAINERS文件以瞭解您所
關注的å­ç³»çµ±çš„維護人員。
-在æäº¤éŒ¯èª¤å ±å‘Šä¹‹å‰ï¼Œè«‹é–±è®€ã€ŒDocumentation/admin-guide/reporting-issues.rstã€ã€‚
+在æäº¤éŒ¯èª¤å ±å‘Šä¹‹å‰ï¼Œè«‹é–±è®€â€œDocumentation/admin-guide/reporting-issues.rstâ€ã€‚
設備未出ç¾ï¼ˆDevices not appearing)
====================================
@@ -38,7 +38,7 @@
æ“作步驟:
-- 從git原始碼構建內核
+- 從gitæºä»£ç¢¼æ§‹å»ºå…§æ ¸
- 以此開始二分 [#f1]_::
$ git bisect start
@@ -76,7 +76,7 @@
如需進一步åƒè€ƒï¼Œè«‹é–±è®€ï¼š
- ``git-bisect`` 的手冊é 
-- `Fighting regressions with git bisect(用git bisect解決回歸)
+- `Fighting regressions with git bisect(用git bisect解決迴歸)
<https://www.kernel.org/pub/software/scm/git/docs/git-bisect-lk2009.html>`_
- `Fully automated bisecting with "git bisect run"(使用git bisect run
來全自動二分) <https://lwn.net/Articles/317154>`_
diff --git a/Documentation/translations/zh_TW/admin-guide/bug-hunting.rst b/Documentation/translations/zh_TW/admin-guide/bug-hunting.rst
index 9a3de3bff5e7..631fd2650929 100644
--- a/Documentation/translations/zh_TW/admin-guide/bug-hunting.rst
+++ b/Documentation/translations/zh_TW/admin-guide/bug-hunting.rst
@@ -48,8 +48,8 @@
[<c1549f43>] ? sysenter_past_esp+0x40/0x6a
---[ end trace 6ebc60ef3981792f ]---
-這樣的堆棧跟蹤æä¾›äº†è¶³å¤ çš„ä¿¡æ¯ä¾†è­˜åˆ¥å…§æ ¸åŽŸå§‹ç¢¼ä¸­ç™¼ç”ŸéŒ¯èª¤çš„é‚£ä¸€è¡Œã€‚æ ¹æ“šå•題的
-åš´é‡æ€§ï¼Œå®ƒé‚„å¯èƒ½åŒ…å« **「Oopsã€** 一詞,比如::
+這樣的堆棧跟蹤æä¾›äº†è¶³å¤ çš„ä¿¡æ¯ä¾†è­˜åˆ¥å…§æ ¸æºä»£ç¢¼ä¸­ç™¼ç”ŸéŒ¯èª¤çš„那一行。根據å•題的
+åš´é‡æ€§ï¼Œå®ƒé‚„å¯èƒ½åŒ…å« **“Oopsâ€** 一詞,比如::
BUG: unable to handle kernel NULL pointer dereference at (null)
IP: [<c06969d4>] iret_exc+0x7d0/0xa59
@@ -58,17 +58,17 @@
...
儘管有 **Oops** æˆ–å…¶ä»–é¡žåž‹çš„å †æ£§è·Ÿè¹¤ï¼Œä½†é€šå¸¸éœ€è¦æ‰¾åˆ°å‡ºå•題的行來識別和處ç†ç¼º
-陷。在本章中,我們將åƒè€ƒã€ŒOopsã€ä¾†äº†è§£éœ€è¦åˆ†æžçš„å„種堆棧跟蹤。
+陷。在本章中,我們將åƒè€ƒâ€œOopsâ€ä¾†äº†è§£éœ€è¦åˆ†æžçš„å„種堆棧跟蹤。
如果內核是用 ``CONFIG_DEBUG_INFO`` 編譯的,那麼å¯ä»¥ä½¿ç”¨æ–‡ä»¶ï¼š
`scripts/decode_stacktrace.sh` 。
-連çµçš„æ¨¡å¡Š
+éˆæŽ¥çš„æ¨¡å¡Š
-----------
-å—到汙染或正在加載/å¸è¼‰çš„æ¨¡å¡Šç”¨ã€Œï¼ˆâ€¦ï¼‰ã€æ¨™è¨˜ï¼Œæ±™æŸ“標誌在
-`Documentation/admin-guide/tainted-kernels.rst` 文件中進行了æè¿°ï¼Œã€Œæ­£åœ¨è¢«åŠ 
-載ã€ç”¨ã€Œ+ã€æ¨™è¨»ï¼Œã€Œæ­£åœ¨è¢«å¸è¼‰ã€ç”¨ã€Œ-ã€æ¨™è¨»ã€‚
+å—到污染或正在加載/å¸è¼‰çš„æ¨¡å¡Šç”¨â€œï¼ˆâ€¦ï¼‰â€æ¨™è¨˜ï¼Œæ±¡æŸ“標誌在
+`Documentation/admin-guide/tainted-kernels.rst` 文件中進行了æè¿°ï¼Œâ€œæ­£åœ¨è¢«åŠ 
+載â€ç”¨â€œ+â€æ¨™è¨»ï¼Œâ€œæ­£åœ¨è¢«å¸è¼‰â€ç”¨â€œ-â€æ¨™è¨»ã€‚
Oops消æ¯åœ¨å“ªï¼Ÿ
@@ -81,19 +81,19 @@ syslog文件,通常是 ``/var/log/messages`` ï¼ˆå–æ±ºæ–¼ ``/etc/syslog.conf``
有時 ``klogd`` 會掛掉,這種情æ³ä¸‹æ‚¨å¯ä»¥é‹è¡Œ ``dmesg > file`` 從內核緩è¡å€
è®€å–æ•¸æ“šä¸¦ä¿å­˜å®ƒã€‚或者您å¯ä»¥ ``cat /proc/kmsg > file`` ï¼Œä½†æ˜¯æ‚¨å¿…é ˆé©æ™‚
-ä¸­æ–·ä»¥åœæ­¢å‚³è¼¸ï¼Œå› çˆ² ``kmsg`` 是一個「永無止境的文件ã€ã€‚
+ä¸­æ–·ä»¥åœæ­¢å‚³è¼¸ï¼Œå› çˆ² ``kmsg`` 是一個“永無止境的文件â€ã€‚
-如果機器嚴é‡å´©æ½°ï¼Œç„¡æ³•輸入命令或ç£ç¢Ÿä¸å¯ç”¨ï¼Œé‚£é‚„有三個é¸é …:
+如果機器嚴é‡å´©æ½°ï¼Œç„¡æ³•輸入命令或ç£ç›¤ä¸å¯ç”¨ï¼Œé‚£é‚„有三個é¸é …:
(1) 手動複製å±å¹•ä¸Šçš„æ–‡æœ¬ï¼Œä¸¦åœ¨æ©Ÿå™¨é‡æ–°å•“動後輸入。很難å—,但這是çªç„¶å´©æ½°ä¸‹
- å”¯ä¸€çš„é¸æ“‡ã€‚或者你å¯ä»¥ç”¨æ•¸ä½ç›¸æ©Ÿæ‹ä¸‹å±å¹•——雖然ä¸é‚£éº¼å¥½ï¼Œä½†ç¸½æ¯”什麼都沒
- æœ‰å¥½ã€‚å¦‚æžœæ¶ˆæ¯æ»¾å‹•超出控制å°é ‚部,使用更高解æžåº¦ï¼ˆä¾‹å¦‚ ``vga=791`` )
- 引導啓動將å…è¨±æ‚¨é–±è®€æ›´å¤šæ–‡æœ¬ã€‚ï¼ˆè­¦å‘Šï¼šé€™éœ€è¦ ``vesafb`` ,因此å°ã€Œæ—©æœŸã€
+ å”¯ä¸€çš„é¸æ“‡ã€‚或者你å¯ä»¥ç”¨æ•¸ç¢¼ç›¸æ©Ÿæ‹ä¸‹å±å¹•——雖然ä¸é‚£éº¼å¥½ï¼Œä½†ç¸½æ¯”什麼都沒
+ æœ‰å¥½ã€‚å¦‚æžœæ¶ˆæ¯æ»¾å‹•超出控制檯頂部,使用更高分辨率(例如 ``vga=791`` )
+ 引導啓動將å…è¨±æ‚¨é–±è®€æ›´å¤šæ–‡æœ¬ã€‚ï¼ˆè­¦å‘Šï¼šé€™éœ€è¦ ``vesafb`` ,因此å°â€œæ—©æœŸâ€
的Oppses沒有幫助)
(2) 從串å£çµ‚端啓動(åƒè¦‹
:ref:`Documentation/admin-guide/serial-console.rst <serial_console>` ),
- 在å¦ä¸€å°æ©Ÿå™¨ä¸Šé‹è¡Œæ•¸æ“šæ©Ÿç„¶å¾Œç”¨ä½ å–œæ­¡çš„é€šä¿¡ç¨‹åºæ•ç²è¼¸å‡ºã€‚
+ 在å¦ä¸€è‡ºæ©Ÿå™¨ä¸Šé‹è¡Œèª¿åˆ¶è§£èª¿å™¨ç„¶å¾Œç”¨ä½ å–œæ­¡çš„é€šä¿¡ç¨‹åºæ•ç²è¼¸å‡ºã€‚
Minicomé‹è¡Œè‰¯å¥½ã€‚
(3) 使用Kdump(åƒé–± Documentation/admin-guide/kdump/kdump.rst ),使用
@@ -103,7 +103,7 @@ syslog文件,通常是 ``/var/log/messages`` ï¼ˆå–æ±ºæ–¼ ``/etc/syslog.conf``
找到缺陷ä½ç½®
-------------
-如果你能指出缺陷在內核原始碼中的ä½ç½®ï¼Œå‰‡å ±å‘Šç¼ºé™·çš„æ•ˆæžœæœƒéžå¸¸å¥½ã€‚這有兩種方法。
+如果你能指出缺陷在內核æºä»£ç¢¼ä¸­çš„ä½ç½®ï¼Œå‰‡å ±å‘Šç¼ºé™·çš„æ•ˆæžœæœƒéžå¸¸å¥½ã€‚這有兩種方法。
通常來說使用 ``gdb`` 會比較容易,ä¸éŽå…§æ ¸éœ€è¦ç”¨èª¿è©¦ä¿¡æ¯ä¾†é ç·¨è­¯ã€‚
gdb
@@ -187,7 +187,7 @@ GNU 調試器(GNU debugger, ``gdb`` )是從 ``vmlinux`` 文件中找出OOP
objdump
^^^^^^^^
-è¦èª¿è©¦å…§æ ¸ï¼Œè«‹ä½¿ç”¨objdump並從崩潰輸出中查找å六進ä½å移,以找到有效的代碼/匯
+è¦èª¿è©¦å…§æ ¸ï¼Œè«‹ä½¿ç”¨objdump並從崩潰輸出中查找å六進制å移,以找到有效的代碼/匯
編行。如果沒有調試符號,您將看到所示例程的彙編程åºä»£ç¢¼ï¼Œä½†æ˜¯å¦‚果內核有調試
符號,C代碼也將å¯è¦‹ï¼ˆèª¿è©¦ç¬¦è™Ÿå¯ä»¥åœ¨å…§æ ¸é…ç½®èœå–®çš„hacking項中啓用)。例如::
@@ -197,7 +197,7 @@ objdump
您需è¦è™•於內核樹的頂層以便此ç²å¾—您的C文件。
-如果您無法訪å•原始碼,ä»ç„¶å¯ä»¥ä½¿ç”¨ä»¥ä¸‹æ–¹æ³•調試一些崩潰轉儲(如Dave Millerçš„
+å¦‚æžœæ‚¨ç„¡æ³•è¨ªå•æºä»£ç¢¼ï¼Œä»ç„¶å¯ä»¥ä½¿ç”¨ä»¥ä¸‹æ–¹æ³•調試一些崩潰轉儲(如Dave Millerçš„
示例崩潰轉儲輸出所示)::
EIP is at +0x14/0x4c0
@@ -234,9 +234,9 @@ objdump
報告缺陷
---------
-一旦你通éŽå®šä½ç¼ºé™·æ‰¾åˆ°äº†å…¶ç™¼ç”Ÿçš„地方,你å¯ä»¥å˜—試自己修復它或者å‘上游報告它。
+一旦你通éŽå®šä½ç¼ºé™·æ‰¾åˆ°äº†å…¶ç™¼ç”Ÿçš„地方,你å¯ä»¥å˜—試自己修復它或者å‘上éŠå ±å‘Šå®ƒã€‚
-爲了å‘上游報告,您應該找出用於開發å—影響代碼的郵件列表。這å¯ä»¥ä½¿ç”¨ ``get_maintainer.pl`` 。
+爲了å‘上éŠå ±å‘Šï¼Œæ‚¨æ‡‰è©²æ‰¾å‡ºç”¨æ–¼é–‹ç™¼å—影響代碼的郵件列表。這å¯ä»¥ä½¿ç”¨ ``get_maintainer.pl`` 。
例如,您在gspcaçš„sonixj.c文件中發ç¾ä¸€å€‹ç¼ºé™·ï¼Œå‰‡å¯ä»¥é€šéŽä»¥ä¸‹æ–¹æ³•找到它的維護者::
@@ -251,7 +251,7 @@ objdump
請注æ„它將指出:
-- 最後接觸原始碼的開發人員(如果這是在git樹中完æˆçš„)。在上é¢çš„例å­ä¸­æ˜¯Tejun
+- 最後接觸æºä»£ç¢¼çš„開發人員(如果這是在git樹中完æˆçš„)。在上é¢çš„例å­ä¸­æ˜¯Tejun
å’ŒBhaktipriya(在這個特定的案例中,沒有人真正åƒèˆ‡é€™å€‹æ–‡ä»¶çš„開發);
- 驅動維護人員(Hans Verkuil);
- å­ç³»çµ±ç¶­è­·äººå“¡ï¼ˆMauro Carvalho Chehab);
diff --git a/Documentation/translations/zh_TW/admin-guide/clearing-warn-once.rst b/Documentation/translations/zh_TW/admin-guide/clearing-warn-once.rst
index bd0c08aab8ea..6961006b4a2d 100644
--- a/Documentation/translations/zh_TW/admin-guide/clearing-warn-once.rst
+++ b/Documentation/translations/zh_TW/admin-guide/clearing-warn-once.rst
@@ -7,10 +7,10 @@
清除 WARN_ONCE
--------------
-WARN_ONCE / WARN_ON_ONCE / printk_once 僅僅列å°ä¸€æ¬¡æ¶ˆæ¯.
+WARN_ONCE / WARN_ON_ONCE / printk_once 僅僅打å°ä¸€æ¬¡æ¶ˆæ¯.
echo 1 > /sys/kernel/debug/clear_warn_once
-å¯ä»¥æ¸…é™¤é€™ç¨®ç‹€æ…‹ä¸¦ä¸”å†æ¬¡å…許列å°ä¸€æ¬¡å‘Šè­¦ä¿¡æ¯ï¼Œé€™å°æ–¼é‹è¡Œæ¸¬è©¦é›†å¾Œé‡ç¾å•題
+å¯ä»¥æ¸…é™¤é€™ç¨®ç‹€æ…‹ä¸¦ä¸”å†æ¬¡å…許打å°ä¸€æ¬¡å‘Šè­¦ä¿¡æ¯ï¼Œé€™å°æ–¼é‹è¡Œæ¸¬è©¦é›†å¾Œé‡ç¾å•題
很有用。
diff --git a/Documentation/translations/zh_TW/admin-guide/cpu-load.rst b/Documentation/translations/zh_TW/admin-guide/cpu-load.rst
index 9e04aeac1a5c..cc046f3b7ffa 100644
--- a/Documentation/translations/zh_TW/admin-guide/cpu-load.rst
+++ b/Documentation/translations/zh_TW/admin-guide/cpu-load.rst
@@ -20,13 +20,13 @@ Linux通éŽ``/proc/stat``å’Œ``/proc/uptime``導出å„種信æ¯ï¼Œç”¨æˆ¶ç©ºé–“å·¥
...
-這裡系統èªçˆ²åœ¨é»˜èªæŽ¡æ¨£å‘¨æœŸå…§æœ‰10.01%的時間工作在用戶空間,2.92%的時
+這è£ç³»çµ±èªçˆ²åœ¨é»˜èªæŽ¡æ¨£é€±æœŸå…§æœ‰10.01%的時間工作在用戶空間,2.92%的時
間用在系統空間,總體上有81.63%的時間是空閒的。
大多數情æ³ä¸‹``/proc/stat``的信æ¯å¹¾ä¹ŽçœŸå¯¦å映了系統信æ¯ï¼Œç„¶è€Œï¼Œç”±æ–¼å…§
核採集這些數據的方å¼/æ™‚é–“çš„ç‰¹é»žï¼Œæœ‰æ™‚é€™äº›ä¿¡æ¯æ ¹æœ¬ä¸å¯é ã€‚
-é‚£éº¼é€™äº›ä¿¡æ¯æ˜¯å¦‚何被æœé›†çš„呢?æ¯ç•¶æ™‚間中斷觸發時,內核查看此刻é‹è¡Œçš„
+é‚£éº¼é€™äº›ä¿¡æ¯æ˜¯å¦‚何被è’集的呢?æ¯ç•¶æ™‚間中斷觸發時,內核查看此刻é‹è¡Œçš„
進程類型,並增加與此類型/ç‹€æ…‹é€²ç¨‹å°æ‡‰çš„計數器的值。這種方法的å•題是
在兩次時間中斷之間系統(進程)能夠在多種狀態之間切æ›å¤šæ¬¡ï¼Œè€Œè¨ˆæ•¸å™¨åª
增加最後一種狀態下的計數。
@@ -34,7 +34,7 @@ Linux通éŽ``/proc/stat``å’Œ``/proc/uptime``導出å„種信æ¯ï¼Œç”¨æˆ¶ç©ºé–“å·¥
舉例
---
-å‡è¨­ç³»çµ±æœ‰ä¸€å€‹é€²ç¨‹ä»¥å¦‚下方å¼å‘¨æœŸæ€§åœ°å ç”¨cpu::
+å‡è¨­ç³»çµ±æœ‰ä¸€å€‹é€²ç¨‹ä»¥å¦‚下方å¼é€±æœŸæ€§åœ°ä½”用cpu::
兩個時é˜ä¸­æ–·ä¹‹é–“的時間線
|-----------------------|
@@ -46,7 +46,7 @@ Linux通éŽ``/proc/stat``å’Œ``/proc/uptime``導出å„種信æ¯ï¼Œç”¨æˆ¶ç©ºé–“å·¥
在上é¢çš„æƒ…æ³ä¸‹ï¼Œæ ¹æ“š``/proc/stat``的信æ¯ï¼ˆç”±æ–¼ç•¶ç³»çµ±è™•於空閒狀態時,
時間中斷經常會發生)系統的負載將會是0
-大家能夠想åƒå…§æ ¸çš„這種行爲會發生在許多情æ³ä¸‹ï¼Œé€™å°‡å°Žè‡´``/proc/stat``
+大家能夠想象內核的這種行爲會發生在許多情æ³ä¸‹ï¼Œé€™å°‡å°Žè‡´``/proc/stat``
ä¸­å­˜åœ¨ç›¸ç•¶å¤æ€ªçš„ä¿¡æ¯::
/* gcc -o hog smallhog.c */
diff --git a/Documentation/translations/zh_TW/admin-guide/cputopology.rst b/Documentation/translations/zh_TW/admin-guide/cputopology.rst
new file mode 100644
index 000000000000..5c46d1b3b065
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/cputopology.rst
@@ -0,0 +1,97 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/cputopology.rst
+
+:翻譯:
+
+ å”è—舟 Tang Yizhou <tangyeechou@gmail.com>
+
+==========================
+如何通éŽsysfså°‡CPU拓撲導出
+==========================
+
+CPU拓撲信æ¯é€šéŽsysfs導出。顯示的項(屬性)和æŸäº›æž¶æ§‹çš„/proc/cpuinfoè¼¸å‡ºç›¸ä¼¼ã€‚å®ƒå€‘ä½æ–¼
+/sys/devices/system/cpu/cpuX/topology/。請閱讀ABI文件:
+Documentation/ABI/stable/sysfs-devices-system-cpu。
+
+drivers/base/topology.cæ˜¯é«”ç³»çµæ§‹ä¸­æ€§çš„,它導出了這些屬性。然而,dieã€clusterã€bookã€
+drawé€™äº›å±¤æ¬¡çµæ§‹ç›¸é—œçš„æ–‡ä»¶åƒ…åœ¨é«”ç³»çµæ§‹æä¾›äº†ä¸‹æ–‡æè¿°çš„å®çš„æ¢ä»¶ä¸‹è¢«å‰µå»ºã€‚
+
+å°æ–¼æ”¯æŒé€™å€‹ç‰¹æ€§çš„é«”ç³»çµæ§‹ï¼Œå®ƒå¿…須在include/asm-XXX/topology.h中定義這些å®ä¸­çš„一部分::
+
+ #define topology_physical_package_id(cpu)
+ #define topology_die_id(cpu)
+ #define topology_cluster_id(cpu)
+ #define topology_core_id(cpu)
+ #define topology_book_id(cpu)
+ #define topology_drawer_id(cpu)
+ #define topology_sibling_cpumask(cpu)
+ #define topology_core_cpumask(cpu)
+ #define topology_cluster_cpumask(cpu)
+ #define topology_die_cpumask(cpu)
+ #define topology_book_cpumask(cpu)
+ #define topology_drawer_cpumask(cpu)
+
+``**_id macros`` 的類型是int。
+``**_cpumask macros`` 的類型是 ``(const) struct cpumask *`` 。後者和æ°ç•¶çš„
+``**_siblings`` sysfså±¬æ€§å°æ‡‰ï¼ˆé™¤äº†topology_sibling_cpumask(),它和thread_siblings
+å°æ‡‰ï¼‰ã€‚
+
+çˆ²äº†åœ¨æ‰€æœ‰é«”ç³»çµæ§‹ä¸Šä¿æŒä¸€è‡´ï¼Œinclude/linux/topology.hæä¾›äº†ä¸Šè¿°æ‰€æœ‰å®çš„默èªå®šç¾©ï¼Œä»¥é˜²
+它們未在include/asm-XXX/topology.h中定義:
+
+1) topology_physical_package_id: -1
+2) topology_die_id: -1
+3) topology_cluster_id: -1
+4) topology_core_id: 0
+5) topology_book_id: -1
+6) topology_drawer_id: -1
+7) topology_sibling_cpumask: 僅入åƒCPU
+8) topology_core_cpumask: 僅入åƒCPU
+9) topology_cluster_cpumask: 僅入åƒCPU
+10) topology_die_cpumask: 僅入åƒCPU
+11) topology_book_cpumask: 僅入åƒCPU
+12) topology_drawer_cpumask: 僅入åƒCPU
+
+此外,CPU拓撲信æ¯ç”±/sys/devices/system/cpuæä¾›ï¼ŒåŒ…å«ä¸‹è¿°æ–‡ä»¶ã€‚è¼¸å‡ºå°æ‡‰çš„å…§éƒ¨æ•¸æ“šæºæ”¾åœ¨
+方括號("[]")中。
+
+ =========== ==================================================================
+ kernel_max: å…§æ ¸é…ç½®å…許的最大CPU下標值。[NR_CPUS-1]
+
+ offline: ç”±æ–¼ç†±æ’æ‹”移除或者超éŽå…§æ ¸å…許的CPU上é™ï¼ˆä¸Šæ–‡æè¿°çš„kernel_max)
+ 導致未上線的CPU。[~cpu_online_mask + cpus >= NR_CPUS]
+
+ online: 在線的CPU,å¯ä¾›èª¿åº¦ä½¿ç”¨ã€‚[cpu_online_mask]
+
+ possible: 已被分é…資æºçš„CPU,如果它們CPU實際存在,å¯ä»¥ä¸Šç·šã€‚
+ [cpu_possible_mask]
+
+ present: 被系統識別實際存在的CPU。[cpu_present_mask]
+ =========== ==================================================================
+
+上述輸出的格å¼å’Œcpulist_parse()兼容[åƒè¦‹ <linux/cpumask.h>]。下é¢çµ¦äº›ä¾‹å­ã€‚
+
+在本例中,系統中有64個CPU,但是CPU 32-63è¶…éŽäº†kernel_max值,因爲NR_CPUSé…置項是32,
+å–值範åœè¢«é™åˆ¶çˆ²0..31。此外注æ„CPU2å’Œ4-31未上線,但是å¯ä»¥ä¸Šç·šï¼Œå› çˆ²å®ƒå€‘åŒæ™‚存在於
+presentå’Œpossible::
+
+ kernel_max: 31
+ offline: 2,4-31,32-63
+ online: 0-1,3
+ possible: 0-31
+ present: 0-31
+
+在本例中,NR_CPUSé…置項是128,但內核啓動時設置possible_cpus=144。系統中有4個CPU,
+CPU2被手動設置下線(也是唯一一個å¯ä»¥ä¸Šç·šçš„CPU)::
+
+ kernel_max: 127
+ offline: 2,4-127,128-143
+ online: 0-1,3
+ possible: 0-127
+ present: 0-3
+
+閱讀Documentation/core-api/cpu_hotplug.rstå¯çž­è§£é–‹æ©Ÿåƒæ•¸possible_cpus=NUMï¼ŒåŒæ™‚é‚„
+å¯ä»¥çž­è§£å„種cpumask的信æ¯ã€‚
+
diff --git a/Documentation/translations/zh_TW/admin-guide/index.rst b/Documentation/translations/zh_TW/admin-guide/index.rst
index 2804d619201d..aba8939351e0 100644
--- a/Documentation/translations/zh_TW/admin-guide/index.rst
+++ b/Documentation/translations/zh_TW/admin-guide/index.rst
@@ -3,13 +3,14 @@
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../admin-guide/index`
-:Translator: 胡皓文 Hu Haowen <src.res.211@gmail.com>
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+ 胡皓文 Hu Haowen <src.res.211@gmail.com>
Linux 內核用戶和管ç†å“¡æŒ‡å—
==========================
䏋颿˜¯ä¸€çµ„隨時間添加到內核中的é¢å‘用戶的文檔的集åˆã€‚到目å‰çˆ²æ­¢ï¼Œé‚„沒有一個
-æ•´é«”çš„é †åºæˆ–組織 - é€™äº›ææ–™ä¸æ˜¯ä¸€å€‹å–®ä¸€çš„,連貫的文件ï¼å¹¸é‹çš„è©±ï¼Œæƒ…æ³æœƒéš¨è‘—
+æ•´é«”çš„é †åºæˆ–組織 - é€™äº›ææ–™ä¸æ˜¯ä¸€å€‹å–®ä¸€çš„,連貫的文件ï¼å¹¸é‹çš„è©±ï¼Œæƒ…æ³æœƒéš¨ç€
時間的推移而迅速改善。
這個åˆå§‹éƒ¨åˆ†åŒ…å«ç¸½é«”ä¿¡æ¯ï¼ŒåŒ…括æè¿°å…§æ ¸çš„README, é—œæ–¼å…§æ ¸åƒæ•¸çš„æ–‡æª”等。
@@ -21,15 +22,15 @@ Linux 內核用戶和管ç†å“¡æŒ‡å—
Todolist:
- kernel-parameters
- devices
- sysctl/index
+* kernel-parameters
+* devices
+* sysctl/index
本節介紹CPUæ¼æ´žåŠå…¶ç·©è§£æŽªæ–½ã€‚
Todolist:
- hw-vuln/index
+* hw-vuln/index
下é¢çš„一組文檔,é‡å°çš„æ˜¯è©¦åœ–跟蹤å•題和bug的用戶。
@@ -37,6 +38,7 @@ Todolist:
:maxdepth: 1
reporting-issues
+ reporting-regressions
security-bugs
bug-hunting
bug-bisect
@@ -45,18 +47,17 @@ Todolist:
Todolist:
- reporting-bugs
- ramoops
- dynamic-debug-howto
- kdump/index
- perf/index
+* ramoops
+* dynamic-debug-howto
+* kdump/index
+* perf/index
-這是應用程å¼é–‹ç™¼äººå“¡æ„Ÿèˆˆè¶£çš„章節的開始。å¯ä»¥åœ¨é€™è£¡æ‰¾åˆ°æ¶µè“‹å…§æ ¸ABIå„個
+這是應用程åºé–‹ç™¼äººå“¡æ„Ÿèˆˆè¶£çš„章節的開始。å¯ä»¥åœ¨é€™è£æ‰¾åˆ°æ¶µè“‹å…§æ ¸ABIå„個
æ–¹é¢çš„æ–‡æª”。
Todolist:
- sysfs-rules
+* sysfs-rules
本手冊的其餘部分包括å„種指å—,介紹如何根據您的喜好é…置內核的特定行爲。
@@ -64,67 +65,67 @@ Todolist:
.. toctree::
:maxdepth: 1
+ bootconfig
clearing-warn-once
cpu-load
+ cputopology
+ lockup-watchdogs
unicode
+ sysrq
+ mm/index
Todolist:
- acpi/index
- aoe/index
- auxdisplay/index
- bcache
- binderfs
- binfmt-misc
- blockdev/index
- bootconfig
- braille-console
- btmrvl
- cgroup-v1/index
- cgroup-v2
- cifs/index
- cputopology
- dell_rbu
- device-mapper/index
- edid
- efi-stub
- ext4
- nfs/index
- gpio/index
- highuid
- hw_random
- initrd
- iostats
- java
- jfs
- kernel-per-CPU-kthreads
- laptops/index
- lcd-panel-cgram
- ldm
- lockup-watchdogs
- LSM/index
- md
- media/index
- mm/index
- module-signing
- mono
- namespaces/index
- numastat
- parport
- perf-security
- pm/index
- pnp
- rapidio
- ras
- rtc
- serial-console
- svga
- sysrq
- thunderbolt
- ufs
- vga-softcursor
- video-output
- xfs
+* acpi/index
+* aoe/index
+* auxdisplay/index
+* bcache
+* binderfs
+* binfmt-misc
+* blockdev/index
+* braille-console
+* btmrvl
+* cgroup-v1/index
+* cgroup-v2
+* cifs/index
+* dell_rbu
+* device-mapper/index
+* edid
+* efi-stub
+* ext4
+* nfs/index
+* gpio/index
+* highuid
+* hw_random
+* initrd
+* iostats
+* java
+* jfs
+* kernel-per-CPU-kthreads
+* laptops/index
+* lcd-panel-cgram
+* ldm
+* LSM/index
+* md
+* media/index
+* module-signing
+* mono
+* namespaces/index
+* numastat
+* parport
+* perf-security
+* pm/index
+* pnp
+* rapidio
+* ras
+* rtc
+* serial-console
+* svga
+* thunderbolt
+* ufs
+* vga-softcursor
+* video-output
+* xfs
.. only:: subproject and html
diff --git a/Documentation/translations/zh_TW/admin-guide/init.rst b/Documentation/translations/zh_TW/admin-guide/init.rst
index db3fdf611080..be6e34f5f7fa 100644
--- a/Documentation/translations/zh_TW/admin-guide/init.rst
+++ b/Documentation/translations/zh_TW/admin-guide/init.rst
@@ -9,8 +9,8 @@
峿ƒ³æˆ Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <src.res.211@gmail.com>
-解釋「No working init found.ã€å•“動掛起消æ¯
-==========================================
+解釋“No working init found.â€å•“動掛起消æ¯
+=========================================
:作者:
@@ -18,41 +18,41 @@
Cristian Souza <cristianmsbr at gmail period com>
-本文檔æä¾›äº†åŠ è¼‰åˆå§‹åŒ–二進ä½ï¼ˆinit binary)失敗的一些高層級原因(大致按執行
+本文檔æä¾›äº†åŠ è¼‰åˆå§‹åŒ–二進制(init binary)失敗的一些高層級原因(大致按執行
é †åºåˆ—出)。
-1) **無法掛載根文件系統Unable to mount root FS** :請設置「debugã€å…§æ ¸åƒæ•¸ï¼ˆåœ¨
+1) **無法掛載根文件系統Unable to mount root FS** :請設置“debugâ€å…§æ ¸åƒæ•¸ï¼ˆåœ¨
引導加載程åºbootloaderé…置文件或CONFIG_CMDLINE)以ç²å–更詳細的內核消æ¯ã€‚
-2) **åˆå§‹åŒ–二進ä½ä¸å­˜åœ¨æ–¼æ ¹æ–‡ä»¶ç³»çµ±ä¸Šinit binary doesn't exist on rootfs** :
+2) **åˆå§‹åŒ–二進制ä¸å­˜åœ¨æ–¼æ ¹æ–‡ä»¶ç³»çµ±ä¸Šinit binary doesn't exist on rootfs** :
ç¢ºä¿æ‚¨çš„æ ¹æ–‡ä»¶ç³»çµ±é¡žåž‹æ­£ç¢ºï¼ˆä¸¦ä¸” ``root=`` å…§æ ¸åƒæ•¸æŒ‡å‘正確的分å€ï¼‰ï¼›æ“有
- 所需的驅動程åºï¼Œä¾‹å¦‚SCSI或USB等存儲硬體;文件系統(ext3ã€jffs2等)是內建的
+ 所需的驅動程åºï¼Œä¾‹å¦‚SCSI或USB等存儲硬件;文件系統(ext3ã€jffs2等)是內建的
(或者作爲模塊由initrdé åŠ è¼‰ï¼‰ã€‚
-3) **控制å°è¨­å‚™æå£žBroken console device** : ``console= setup`` 中å¯èƒ½å­˜åœ¨
- è¡çª --> åˆå§‹æŽ§åˆ¶å°ä¸å¯ç”¨ï¼ˆinitial console unavailable)。例如,由於串行
- IRQå•題(如缺少基於中斷的é…置)導致的æŸäº›ä¸²è¡ŒæŽ§åˆ¶å°ä¸å¯é ã€‚嘗試使用ä¸åŒçš„
+3) **控制檯設備æå£žBroken console device** : ``console= setup`` 中å¯èƒ½å­˜åœ¨
+ è¡çª --> åˆå§‹æŽ§åˆ¶æª¯ä¸å¯ç”¨ï¼ˆinitial console unavailable)。例如,由於串行
+ IRQå•題(如缺少基於中斷的é…置)導致的æŸäº›ä¸²è¡ŒæŽ§åˆ¶æª¯ä¸å¯é ã€‚嘗試使用ä¸åŒçš„
``console= device`` æˆ–åƒ ``netconsole=`` 。
-4) **二進ä½å­˜åœ¨ä½†ä¾è³´é …ä¸å¯ç”¨Binary exists but dependencies not available** :
- 例如åˆå§‹åŒ–二進ä½çš„必需庫ä¾è³´é …ï¼Œåƒ ``/lib/ld-linux.so.2`` 丟失或æå£žã€‚使用
+4) **二進制存在但ä¾è³´é …ä¸å¯ç”¨Binary exists but dependencies not available** :
+ 例如åˆå§‹åŒ–二進制的必需庫ä¾è³´é …ï¼Œåƒ ``/lib/ld-linux.so.2`` 丟失或æå£žã€‚使用
``readelf -d <INIT>|grep NEEDED`` 找出需è¦å“ªäº›åº«ã€‚
-5) **無法加載二進ä½Binary cannot be loaded** :請確ä¿äºŒé€²ä½çš„é«”ç³»çµæ§‹èˆ‡æ‚¨çš„
- 硬體匹é…。例如i386ä¸åŒ¹é…x86_64,或者嘗試在ARM硬體上加載x86。如果您嘗試在
- 此處加載éžäºŒé€²ä½æ–‡ä»¶ï¼ˆshell腳本?),您應該確ä¿è…³æœ¬åœ¨å…¶å·¥ä½œé ­ï¼ˆshebang
+5) **無法加載二進制Binary cannot be loaded** :請確ä¿äºŒé€²åˆ¶çš„é«”ç³»çµæ§‹èˆ‡æ‚¨çš„
+ 硬件匹é…。例如i386ä¸åŒ¹é…x86_64,或者嘗試在ARM硬件上加載x86。如果您嘗試在
+ 此處加載éžäºŒé€²åˆ¶æ–‡ä»¶ï¼ˆshell腳本?),您應該確ä¿è…³æœ¬åœ¨å…¶å·¥ä½œé ­ï¼ˆshebang
header)行 ``#!/...`` 中指定能正常工作的解釋器(包括其庫ä¾è³´é …)。在處ç†
- 腳本之å‰ï¼Œæœ€å¥½å…ˆæ¸¬è©¦ä¸€å€‹ç°¡å–®çš„éžè…³æœ¬äºŒé€²ä½æ–‡ä»¶ï¼Œæ¯”如 ``/bin/sh`` ,並確èª
+ 腳本之å‰ï¼Œæœ€å¥½å…ˆæ¸¬è©¦ä¸€å€‹ç°¡å–®çš„éžè…³æœ¬äºŒé€²åˆ¶æ–‡ä»¶ï¼Œæ¯”如 ``/bin/sh`` ,並確èª
它能æˆåŠŸåŸ·è¡Œã€‚è¦äº†è§£æ›´å¤šä¿¡æ¯ï¼Œè«‹å°‡ä»£ç¢¼æ·»åŠ åˆ° ``init/main.c`` 以顯示
kernel_execve()的返回值。
-ç•¶æ‚¨ç™¼ç¾æ–°çš„失敗原因時,請擴展本解釋(畢竟加載åˆå§‹åŒ–äºŒé€²ä½æ˜¯ä¸€å€‹ **é—œéµ** 且
+ç•¶æ‚¨ç™¼ç¾æ–°çš„失敗原因時,請擴展本解釋(畢竟加載åˆå§‹åŒ–二進制是一個 **é—œéµ** 且
è‰±é›£çš„éŽæ¸¡æ­¥é©Ÿï¼Œéœ€è¦å„˜å¯èƒ½ç„¡ç—›åœ°é€²è¡Œï¼‰ï¼Œç„¶å¾Œå‘LKMLæäº¤ä¸€å€‹è£œä¸ã€‚
待辦事項:
- 通éŽä¸€å€‹å¯ä»¥å­˜å„² ``kernel_execve()`` çµæžœå€¼çš„çµæ§‹é«”數組實ç¾å„種
- ``run_init_process()`` 調用,並在失敗時通éŽç–Šä»£ **所有** çµæžœä¾†è¨˜éŒ„一切
+ ``run_init_process()`` 調用,並在失敗時通éŽè¿­ä»£ **所有** çµæžœä¾†è¨˜éŒ„一切
(éžå¸¸é‡è¦çš„å¯ç”¨æ€§ä¿®å¾©ï¼‰ã€‚
-- è©¦è‘—ä½¿å¯¦ç¾æœ¬èº«åœ¨ä¸€èˆ¬æƒ…æ³ä¸‹æ›´æœ‰å¹«åŠ©ï¼Œä¾‹å¦‚åœ¨å—影響的地方æä¾›é¡å¤–的錯誤消æ¯ã€‚
+- 試ç€ä½¿å¯¦ç¾æœ¬èº«åœ¨ä¸€èˆ¬æƒ…æ³ä¸‹æ›´æœ‰å¹«åŠ©ï¼Œä¾‹å¦‚åœ¨å—影響的地方æä¾›é¡å¤–的錯誤消æ¯ã€‚
diff --git a/Documentation/translations/zh_TW/admin-guide/lockup-watchdogs.rst b/Documentation/translations/zh_TW/admin-guide/lockup-watchdogs.rst
new file mode 100644
index 000000000000..f65b0c96e8e3
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/lockup-watchdogs.rst
@@ -0,0 +1,67 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/lockup-watchdogs.rst
+:Translator: Hailong Liu <liu.hailong6@zte.com.cn>
+
+.. _tw_lockup-watchdogs:
+
+
+=================================================
+Softlockup與hardlockup檢測機制(åˆå:nmi_watchdog)
+=================================================
+
+Linux中內核實ç¾äº†ä¸€ç¨®ç”¨ä»¥æª¢æ¸¬ç³»çµ±ç™¼ç”Ÿsoftlockupå’Œhardlockup的看門狗機制。
+
+Softlockup是一種會引發系統在內核態中一直循環超éŽ20秒(詳見下é¢â€œå¯¦ç¾â€å°ç¯€ï¼‰å°Žè‡´
+其他任務沒有機會得到é‹è¡Œçš„BUG。一旦檢測到'softlockup'ç™¼ç”Ÿï¼Œé»˜èªæƒ…æ³ä¸‹ç³»çµ±æœƒæ‰“
+å°ç•¶å‰å †æ£§è·Ÿè¹¤ä¿¡æ¯ä¸¦é€²å…¥éŽ–å®šç‹€æ…‹ã€‚ä¹Ÿå¯é…置使其在檢測到'softlockup'後進入panic
+狀態;通éŽsysctl命令設置“kernel.softlockup_panicâ€ã€ä½¿ç”¨å…§æ ¸å•“å‹•åƒæ•¸
+“softlockup_panicâ€ï¼ˆè©³è¦‹Documentation/admin-guide/kernel-parameters.rst)以åŠä½¿
+能內核編譯é¸é …“BOOTPARAM_SOFTLOCKUP_PANICâ€éƒ½å¯å¯¦ç¾é€™ç¨®é…置。
+
+而'hardlockup'是一種會引發系統在內核態一直循環超éŽ10ç§’é˜ï¼ˆè©³è¦‹"實ç¾"å°ç¯€ï¼‰å°Žè‡´å…¶
+他中斷沒有機會é‹è¡Œçš„缺陷。與'softlockup'情æ³é¡žä¼¼ï¼Œé™¤äº†ä½¿ç”¨sysctl命令設置
+'hardlockup_panic'ã€ä½¿èƒ½å…§æ ¸é¸é …“BOOTPARAM_HARDLOCKUP_PANICâ€ä»¥åŠä½¿ç”¨å…§æ ¸åƒæ•¸
+"nmi_watchdog"(詳見:â€Documentation/admin-guide/kernel-parameters.rst“)外,一旦檢
+測到'hardlockup'é»˜èªæƒ…æ³ä¸‹ç³»çµ±æ‰“å°ç•¶å‰å †æ£§è·Ÿè¹¤ä¿¡æ¯ï¼Œç„¶å¾Œé€²å…¥éŽ–å®šç‹€æ…‹ã€‚
+
+這個panicé¸é …也å¯ä»¥èˆ‡panic_timeoutçµåˆä½¿ç”¨ï¼ˆé€™å€‹panic_timeout是通éŽç¨å…·è¿·æƒ‘性的
+sysctl命令"kernel.panic"來設置),使系統在panic指定時間後自動é‡å•“。
+
+實ç¾
+====
+
+Softlockupå’Œhardlockup分別建立在hrtimer(高精度定時器)å’Œperf兩個å­ç³»çµ±ä¸Šè€Œå¯¦ç¾ã€‚
+這也就æ„味ç€ç†è«–上任何架構åªè¦å¯¦ç¾äº†é€™å…©å€‹å­ç³»çµ±å°±æ”¯æŒé€™å…©ç¨®æª¢æ¸¬æ©Ÿåˆ¶ã€‚
+
+Hrtimer用於週期性產生中斷並喚醒watchdog線程;NMI perf事件則以â€watchdog_thresh“
+(編譯時默èªåˆå§‹åŒ–爲10秒,也å¯é€šéŽâ€watchdog_thresh“這個sysctl接å£ä¾†é€²è¡Œé…置修改)
+爲間隔週期產生以檢測 hardlockups。如果一個CPU在這個時間段內沒有檢測到hrtimer中
+斷髮生,'hardlockup 檢測器'(å³NMI perf事件處ç†å‡½æ•¸)將會視系統é…ç½®è€Œé¸æ“‡ç”¢ç”Ÿå…§æ ¸
+警告或者直接panic。
+
+而watchdog線程本質上是一個高優先級內核線程,æ¯èª¿åº¦ä¸€æ¬¡å°±å°æ™‚間戳進行一次更新。
+如果時間戳在2*watchdog_thresh(這個是softlockup的觸發門é™)這段時間都未更新,那麼
+"softlocup 檢測器"(內部hrtimer定時器回調函數)æœƒå°‡ç›¸é—œçš„èª¿è©¦ä¿¡æ¯æ‰“å°åˆ°ç³»çµ±æ—¥èªŒä¸­ï¼Œ
+然後如果系統é…置了進入panicæµç¨‹å‰‡é€²å…¥panic,å¦å‰‡å…§æ ¸ç¹¼çºŒåŸ·è¡Œã€‚
+
+Hrtimer定時器的週期是2*watchdog_thresh/5,也就是說在hardlockup被觸發å‰hrtimer有
+2~3次機會產生時é˜ä¸­æ–·ã€‚
+
+如上所述,內核相當於爲系統管ç†å“¡æä¾›äº†ä¸€å€‹å¯èª¿ç¯€hrtimer定時器和perf事件週期長度
+的調節旋鈕。如何通éŽé€™å€‹æ—‹éˆ•爲特定使用場景é…置一個åˆç†çš„週期值è¦å°lockups檢測的
+響應速度和lockups檢測開銷這二者之間進行權衡。
+
+é»˜èªæƒ…æ³ä¸‹æ‰€æœ‰åœ¨ç·šcpu上都會é‹è¡Œä¸€å€‹watchdog線程。ä¸éŽåœ¨å…§æ ¸é…置了â€NO_HZ_FULL“的
+情æ³ä¸‹watchdog線程默èªåªæœƒé‹è¡Œåœ¨ç®¡å®¶(housekeeping)cpu上,而â€nohz_fullâ€œå•“å‹•åƒæ•¸æŒ‡
+定的cpuä¸Šå‰‡ä¸æœƒæœ‰watchdog線程é‹è¡Œã€‚試想,如果我們å…許watchdog線程在â€nohz_full“指
+定的cpu上é‹è¡Œï¼Œé€™äº›cpu上必須得é‹è¡Œæ™‚é˜å®šæ™‚器來激發watchdog線程調度;這樣一來就會
+使â€nohz_full“ä¿è­·ç”¨æˆ¶ç¨‹åºå…å—內核干擾的功能失效。當然,副作用就是â€nohz_full“指定
+çš„cpuå³ä½¿åœ¨å…§æ ¸ç”¢ç”Ÿäº†lockupå•題我們也無法檢測到。ä¸éŽï¼Œè‡³å°‘我們å¯ä»¥å…許watchdog
+線程在管家(non-tickless)核上繼續é‹è¡Œä»¥ä¾¿æˆ‘們能繼續正常的監測這些cpus上的lockups
+事件。
+
+ä¸è«–哪種情æ³éƒ½å¯ä»¥é€šéŽsysctl命令kernel.watchdog_cpumask來尿²’有é‹è¡Œwatchdog線程
+çš„cpu集åˆé€²è¡Œèª¿ç¯€ã€‚å°æ–¼nohz_full而言,如果nohz_full cpu上有異常掛ä½çš„æƒ…æ³ï¼Œé€šéŽ
+é€™ç¨®æ–¹å¼æ‰“開這些cpu上的watchdog進行調試å¯èƒ½æœƒæœ‰æ‰€ä½œç”¨ã€‚
+
diff --git a/Documentation/translations/zh_TW/admin-guide/mm/damon/index.rst b/Documentation/translations/zh_TW/admin-guide/mm/damon/index.rst
new file mode 100644
index 000000000000..a472eb3c708b
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/mm/damon/index.rst
@@ -0,0 +1,30 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/mm/damon/index.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+:æ ¡è­¯:
+
+============
+監測數據訪å•
+============
+
+:doc:`DAMON </mm/damon/index>` å…許輕é‡ç´šçš„æ•¸æ“šè¨ªå•監測。使用DAMON,
+用戶å¯ä»¥åˆ†æžä»–å€‘ç³»çµ±çš„å…§å­˜è¨ªå•æ¨¡å¼ï¼Œä¸¦å„ªåŒ–它們。
+
+.. toctree::
+ :maxdepth: 2
+
+ start
+ usage
+ reclaim
+ lru_sort
+
+
+
+
+
diff --git a/Documentation/translations/zh_TW/admin-guide/mm/damon/lru_sort.rst b/Documentation/translations/zh_TW/admin-guide/mm/damon/lru_sort.rst
new file mode 100644
index 000000000000..1ffc4b6b1d12
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/mm/damon/lru_sort.rst
@@ -0,0 +1,264 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/mm/damon/lru_sort.rst
+
+:翻譯:
+
+ 臧雷剛 Leigang Zang <zangleigang@hisilicon.com>
+
+:æ ¡è­¯:
+
+==================
+基於DAMONçš„LRU排åº
+==================
+
+基於DAMONçš„LRUæŽ’åºæ˜¯ä¸€å€‹éœæ…‹çš„內核模塊,旨在用於以主動的ã€è¼•é‡ç´šçš„æ•¸æ“šè¨ªå•模型
+爲基礎的é é¢å„ªå…ˆç´šè™•ç†çš„LRUéˆè¡¨ä¸Šï¼Œä»¥ä½¿å¾—LRUä¸Šçš„æ•¸æ“šè¨ªå•æ¨¡åž‹æ›´çˆ²å¯ä¿¡ã€‚
+
+哪è£éœ€è¦ä¸»å‹•çš„LRU排åº
+=====================
+
+在一個大型系統中,以é çˆ²ç²’åº¦çš„è¨ªå•æª¢æ¸¬æœƒæœ‰æ¯”較顯著的開銷,LRUé€šå¸¸ä¸æœƒä¸»å‹•去排åºï¼Œ
+而是å°éƒ¨åˆ†ç‰¹æ®Šäº‹ä»¶é€²è¡Œéƒ¨åˆ†çš„ã€éŸ¿æ‡‰å¼çš„æŽ’åºï¼Œä¾‹å¦‚:特殊的用戶請求,系統調用或者
+內存壓力。這導致,在有些場景下,LRUä¸èƒ½å¤ å®Œç¾Žçš„作爲一個å¯ä¿¡çš„æ•¸æ“šè¨ªå•模型,比如
+在內存壓力下å°ç›®æ¨™å…§å­˜é€²è¡Œå›žæ”¶ã€‚
+
+因爲DAMON能夠儘å¯èƒ½æº–ç¢ºçš„è­˜åˆ¥æ•¸æ“šè¨ªå•æ¨¡åž‹ï¼ŒåŒæ™‚åªå¼•起用戶指定範åœçš„開銷,主動的
+執行DAMON_LRU_SORT讓LRU變得更爲å¯ä¿¡æ˜¯æœ‰ç›Šçš„,而且這隻需è¦è¼ƒå°‘å’Œå¯æŽ§çš„é–‹éŠ·ã€‚
+
+這是如何工作的
+==============
+
+DAMON_LRU_SORT使用DAMON尋找熱é ï¼ˆç¯„åœå…§çš„é é¢è¨ªå•頻率高於用戶指定的閾值)和冷é 
+(範åœå…§çš„é é¢åœ¨è¶…éŽç”¨æˆ¶æŒ‡å®šçš„æ™‚間無訪å•),並æé«˜ç†±é å’Œé™ä½Žå†·é åœ¨LRU中的優先級。
+爲了é¿å…在排åºéŽç¨‹ä½”用更多的CPU計算資æºï¼Œå¯ä»¥è¨­ç½®ä¸€å€‹CPU佔用時間的約æŸå€¼ã€‚在約
+æŸä¸‹ï¼Œåˆ†åˆ¥æå‡æˆ–者é™ä½Žæ›´å¤šçš„熱é å’Œå†·é ã€‚系統管ç†å“¡ä¹Ÿå¯ä»¥é…置三個內存水ä½ä»¥æŽ§åˆ¶
+在何種æ¢ä»¶ä¸‹è‡ªå‹•æ¿€æ´»æˆ–è€…åœæ­¢é€™ç¨®æ©Ÿåˆ¶ã€‚
+
+冷熱閾值和CPUç´„æŸçš„默èªå€¼æ˜¯æ¯”較ä¿å®ˆçš„。這æ„味ç€ï¼Œåœ¨é»˜èªåƒæ•¸ä¸‹ï¼Œæ¨¡å¡Šå¯ä»¥å»£æ³›ä¸”ç„¡
+è² ä½œç”¨çš„ä½¿ç”¨åœ¨å¸¸è¦‹ç’°å¢ƒä¸­ï¼ŒåŒæ™‚åœ¨åªæ¶ˆè€—一å°éƒ¨åˆ†CPU時間的情æ³ä¸‹ï¼Œçµ¦æœ‰å…§å­˜å£“力的系
+çµ±æä¾›ä¸€å®šæ°´å¹³çš„冷熱識別。
+
+接å£ï¼šæ¨¡å¡Šåƒæ•¸
+==============
+
+使用此特性,你首先需è¦ç¢ºèªä½ çš„系統中é‹è¡Œçš„內核在編譯時啓用了
+``CONFIG_DAMON_LRU_SORT=y``.
+
+爲了讓系統管ç†å“¡æ‰“開或者關閉並且調節指定的系統,DAMON_LRU_SORTè¨­è¨ˆäº†æ¨¡å¡Šåƒæ•¸ã€‚
+這æ„味ç€ï¼Œä½ å¯ä»¥æ·»åŠ  ``damon_lru_sort.<parameter>=<value>`` 到內核的啓動命令行
+åƒæ•¸ï¼Œæˆ–者在 ``/sys/modules/damon_lru_sort/parameters/<parameter>`` 寫入正確的
+值。
+
+下邊是æ¯å€‹åƒæ•¸çš„æè¿°
+
+enabled
+-------
+
+打開或者關閉DAMON_LRU_SORT.
+
+ä½ å¯ä»¥é€šéŽè¨­ç½®é€™å€‹åƒæ•¸çˆ² ``Y`` 來打開DAMON_LRU_SORT。設置爲 ``N`` 關閉
+DAMON_LRU_SORT。注æ„,在基於水ä½çš„æ¿€æ´»çš„æƒ…æ³ä¸‹ï¼ŒDAMON_LRU_SORT有å¯èƒ½ä¸æœƒçœŸæ­£åŽ»
+監測或者åšLRU排åºã€‚å°é€™ç¨®æƒ…æ³ï¼Œåƒè€ƒä¸‹æ–¹é—œæ–¼æ°´ä½çš„æè¿°ã€‚
+
+commit_inputs
+-------------
+
+讓DAMON_LRU_SORT冿¬¡è®€å–è¼¸å…¥åƒæ•¸ï¼Œé™¤äº† ``enabled`` 。
+
+在DAMON_LRU_SORTé‹è¡Œæ™‚ï¼Œæ–°çš„è¼¸å…¥åƒæ•¸é»˜èªä¸æœƒè¢«æ‡‰ç”¨ã€‚ä¸€æ—¦é€™å€‹åƒæ•¸è¢«è¨­ç½®çˆ² ``Y``
+,DAMON_LRU_SORTæœƒå†æ¬¡è®€å–除了 ``enabled`` ä¹‹å¤–çš„åƒæ•¸ã€‚讀å–完æˆå¾Œï¼Œé€™å€‹åƒæ•¸æœƒè¢«
+設置爲 ``N`` ã€‚å¦‚æžœåœ¨è®€å–æ™‚ç™¼ç¾æœ‰ç„¡æ•ˆåƒæ•¸ï¼ŒDAMON_LRU_SORT會被關閉。
+
+hot_thres_access_freq
+---------------------
+
+熱點內存å€åŸŸçš„訪å•頻率閾值,åƒåˆ†æ¯”。
+
+如果一個內存å€åŸŸçš„訪å•頻率大於等於這個值,DAMON_LRU_SORT把這個å€åŸŸçœ‹ä½œç†±å€ï¼Œä¸¦
+在LRU上把這個å€åŸŸæ¨™è¨˜çˆ²å·²è¨ªå•ï¼Œå› äº›åœ¨å…§å­˜å£“åŠ›ä¸‹é€™éƒ¨åˆ†å…§å­˜ä¸æœƒè¢«å›žæ”¶ã€‚默èªçˆ²50%。
+
+cold_min_age
+------------
+
+用於識別冷內存å€åŸŸçš„æ™‚é–“é–¾å€¼ï¼Œå–®ä½æ˜¯å¾®ç§’。
+
+如果一個內存å€åŸŸåœ¨é€™å€‹æ™‚間內未被訪å•éŽï¼ŒDAMON_LRU_SORT把這個å€åŸŸçœ‹ä½œå†·å€ï¼Œä¸¦åœ¨
+LRU上把這個å€åŸŸæ¨™è¨˜çˆ²æœªè¨ªå•,因此在內存壓力下這些內存會首先被回收。默èªå€¼çˆ²120
+秒。
+
+quota_ms
+--------
+
+嘗試LRUéˆè¡¨æŽ’åºçš„æ™‚é–“é™åˆ¶ï¼Œå–®ä½æ˜¯æ¯«ç§’。
+
+DAMON_LRU_SORT在一個時間窗å£å…§ï¼ˆquota_reset_interval_ms)內最多嘗試這麼長時間來
+å°LRU進行排åºã€‚這個å¯ä»¥ç”¨ä¾†ä½œçˆ²CPU計算資æºçš„ç´„æŸã€‚如果值爲0,則表示無é™åˆ¶ã€‚
+
+默èª10毫秒。
+
+quota_reset_interval_ms
+-----------------------
+
+é…é¡è¨ˆæ™‚é‡ç½®é€±æœŸï¼Œæ¯«ç§’。
+
+é…é¡è¨ˆæ™‚é‡ç½®é€±æœŸã€‚å³ï¼Œåœ¨quota_reset_interval_ms毫秒內,DAMON_LRU_SORTå°LRU進行
+排åºä¸æœƒè¶…éŽquota_ms或者quota_sz。
+
+默èª1秒。
+
+wmarks_interval
+---------------
+
+æ°´ä½çš„æª¢æŸ¥é€±æœŸï¼Œå–®ä½æ˜¯å¾®ç§’。
+
+ç•¶DAMON_LRU_SORT使能但是由於水ä½è€Œä¸æ´»èºæ™‚檢查水ä½å‰æœ€å°çš„等待時間。默èªå€¼5秒。
+
+wmarks_high
+-----------
+
+空閒內存高水ä½ï¼Œåƒåˆ†æ¯”。
+
+如果空閒內存水ä½é«˜æ–¼é€™å€‹å€¼ï¼ŒDAMON_LRU_SORTåœæ­¢å·¥ä½œï¼Œä¸åšä»»ä½•事,除了週期性的檢
+查水ä½ã€‚默èª200(20%)。
+
+wmarks_mid
+----------
+
+空閒內存中間水ä½ï¼Œåƒåˆ†æ¯”。
+
+如果空閒內存水ä½åœ¨é€™å€‹å€¼èˆ‡ä½Žæ°´ä½ä¹‹é–“,DAMON_LRU_SORT開始工作,開始檢測並å°LRUéˆ
+表進行排åºã€‚默èª150(15%)。
+
+wmarks_low
+----------
+
+空閒內存低水ä½ï¼Œåƒåˆ†æ¯”。
+
+å¦‚æžœç©ºé–’å…§å­˜å°æ–¼é€™å€‹å€¼ï¼ŒDAMON_LRU_SORTä¸å†å·¥ä½œï¼Œä¸åšä»»ä½•事,除了週期性的檢查水
+線。默èª50(5%)。
+
+sample_interval
+---------------
+
+監測的採樣週期,微秒。
+
+DAMONå°å†·å…§å­˜ç›£æ¸¬çš„æŽ¡æ¨£é€±æœŸã€‚更多細節請åƒè€ƒDAMON文檔 (:doc:`usage`) 。默èª5
+毫秒。
+
+aggr_interval
+-------------
+
+監測的收集週期,微秒。
+
+DAMONå°å†·å…§å­˜é€²è¡Œæ”¶é›†çš„æ™‚間週期。更多細節請åƒè€ƒDAMON文檔 (:doc:`usage`) 。默èª
+100毫秒。
+
+min_nr_regions
+--------------
+
+最å°ç›£æ¸¬å€åŸŸæ•¸é‡ã€‚
+
+å°å†·å…§å­˜å€åŸŸç›£æ¸¬çš„æœ€å°æ•¸é‡ã€‚這個值å¯ä»¥ä½œçˆ²ç›£æ¸¬è³ªé‡çš„下é™ã€‚ä¸éŽï¼Œé€™å€‹å€¼è¨­ç½®çš„éŽ
+大會增加開銷。更多細節請åƒè€ƒDAMON文檔 (:doc:`usage`) 。默èªå€¼çˆ²10。
+
+max_nr_regions
+--------------
+
+最大監測å€åŸŸæ•¸é‡ã€‚
+
+å°å†·å…§å­˜å€åŸŸç›£æ¸¬çš„æœ€å¤§æ•¸é‡ã€‚這個值å¯ä»¥ä½œçˆ²ç›£æ¸¬è³ªé‡çš„上é™ã€‚然而,這個值設置的éŽ
+ä½Žæœƒå°Žè‡´ç›£æ¸¬çµæžœè®Šå·®ã€‚更多細節請åƒè€ƒDAMON文檔 (:doc:`usage`) 。默èªå€¼çˆ²1000。
+
+monitor_region_start
+--------------------
+
+目標內存å€åŸŸçš„起始物ç†åœ°å€ã€‚
+
+DAMON_LRU_SORTè¦è™•ç†çš„目標內存å€åŸŸçš„起始物ç†åœ°å€ã€‚默èªï¼Œä½¿ç”¨ç³»çµ±æœ€å¤§å…§å­˜ã€‚
+
+monitor_region_end
+------------------
+
+目標內存å€åŸŸçš„çµæŸç‰©ç†åœ°å€ã€‚
+
+DAMON_LRU_SORTè¦è™•ç†çš„目標內存å€åŸŸçš„çµæŸç‰©ç†åœ°å€ã€‚默èªï¼Œä½¿ç”¨ç³»çµ±æœ€å¤§å…§å­˜ã€‚
+
+kdamond_pid
+-----------
+
+DAMON線程的PID。
+
+如果DAMON_LRU_SORT是使能的,這個表示任務線程的PID。其它情æ³çˆ²-1。
+
+nr_lru_sort_tried_hot_regions
+-----------------------------
+
+被嘗試進行LRU排åºçš„熱內存å€åŸŸçš„æ•¸é‡ã€‚
+
+bytes_lru_sort_tried_hot_regions
+--------------------------------
+
+被嘗試進行LRU排åºçš„熱內存å€åŸŸçš„大å°ï¼ˆå­—節)。
+
+nr_lru_sorted_hot_regions
+-------------------------
+
+æˆåŠŸé€²è¡ŒLRU排åºçš„熱內存å€åŸŸçš„æ•¸é‡ã€‚
+
+bytes_lru_sorted_hot_regions
+----------------------------
+
+æˆåŠŸé€²è¡ŒLRU排åºçš„熱內存å€åŸŸçš„大å°ï¼ˆå­—節)。
+
+nr_hot_quota_exceeds
+--------------------
+
+熱å€åŸŸæ™‚é–“ç´„æŸè¶…éŽé™åˆ¶çš„æ¬¡æ•¸ã€‚
+
+nr_lru_sort_tried_cold_regions
+------------------------------
+
+被嘗試進行LRU排åºçš„冷內存å€åŸŸçš„æ•¸é‡ã€‚
+
+bytes_lru_sort_tried_cold_regions
+---------------------------------
+
+被嘗試進行LRU排åºçš„冷內存å€åŸŸçš„大å°ï¼ˆå­—節)。
+
+nr_lru_sorted_cold_regions
+--------------------------
+
+æˆåŠŸé€²è¡ŒLRU排åºçš„冷內存å€åŸŸçš„æ•¸é‡ã€‚
+
+bytes_lru_sorted_cold_regions
+-----------------------------
+
+æˆåŠŸé€²è¡ŒLRU排åºçš„冷內存å€åŸŸçš„大å°ï¼ˆå­—節)。
+
+nr_cold_quota_exceeds
+---------------------
+
+冷å€åŸŸæ™‚é–“ç´„æŸè¶…éŽé™åˆ¶çš„æ¬¡æ•¸ã€‚
+
+Example
+=======
+
+如下是一個é‹è¡Œæ™‚的命令示例,使DAMON_LRU_SORT查找訪å•頻率超éŽ50%çš„å€åŸŸä¸¦å°å…¶é€²è¡Œ
+LRU的優先級的æå‡ï¼ŒåŒæ™‚é™ä½Žé‚£äº›è¶…éŽ120秒無人訪å•的內存å€åŸŸçš„優先級。優先級的處
+ç†è¢«é™åˆ¶åœ¨æœ€å¤š1%çš„CPU以é¿å…DAMON_LRU_SORT消費éŽå¤šCPU時間。在系統空閒內存超éŽ50%
+時DAMON_LRU_SORTåœæ­¢å·¥ä½œï¼Œä¸¦åœ¨ä½Žæ–¼40%æ™‚é‡æ–°é–‹å§‹å·¥ä½œã€‚如果DAMON_RECLAIM沒有å–å¾—
+進展且空閒內存低於20%ï¼Œå†æ¬¡è®“DAMON_LRU_SORTåœæ­¢å·¥ä½œï¼Œä»¥æ­¤å›žé€€åˆ°ä»¥LRUéˆè¡¨çˆ²åŸºç¤Ž
+以é é¢çˆ²å–®ä½çš„內存回收上。 ::
+
+ # cd /sys/modules/damon_lru_sort/parameters
+ # echo 500 > hot_thres_access_freq
+ # echo 120000000 > cold_min_age
+ # echo 10 > quota_ms
+ # echo 1000 > quota_reset_interval_ms
+ # echo 500 > wmarks_high
+ # echo 400 > wmarks_mid
+ # echo 200 > wmarks_low
+ # echo Y > enabled
+
diff --git a/Documentation/translations/zh_TW/admin-guide/mm/damon/reclaim.rst b/Documentation/translations/zh_TW/admin-guide/mm/damon/reclaim.rst
new file mode 100644
index 000000000000..efed29c40e44
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/mm/damon/reclaim.rst
@@ -0,0 +1,229 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/mm/damon/reclaim.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+:æ ¡è­¯:
+
+===============
+基於DAMON的回收
+===============
+
+基於DAMON的回收(DAMON_RECLAIMï¼‰æ˜¯ä¸€å€‹éœæ…‹çš„內核模塊,旨在用於輕度內存壓力下的主動和輕
+é‡ç´šçš„å›žæ”¶ã€‚å®ƒçš„ç›®çš„ä¸æ˜¯å–代基於LRU列表的é é¢å›žæ”¶ï¼Œè€Œæ˜¯æœ‰é¸æ“‡åœ°ç”¨æ–¼ä¸åŒç¨‹åº¦çš„內存壓力和è¦
+求。
+
+哪些地方需è¦ä¸»å‹•回收?
+======================
+
+在一般的內存超é‡ä½¿ç”¨ï¼ˆover-committed systems,虛擬化相關術語)的系統上,主動回收冷é 
+有助於節çœå…§å­˜å’Œæ¸›å°‘å»¶é²é«˜å³¯ï¼Œé€™äº›å»¶é²æ˜¯ç”±ç›´æŽ¥å›žæ”¶é€²ç¨‹æˆ–kswapdçš„CPUæ¶ˆè€—å¼•èµ·çš„ï¼ŒåŒæ™‚åªç”¢
+生最å°çš„æ€§èƒ½ä¸‹é™ [1]_ [2]_ 。
+
+基於空閒é å ±å‘Š [3]_ 的內存éŽåº¦æ‰¿è«¾çš„虛擬化系統就是很好的例å­ã€‚在這樣的系統中,客戶機
+å‘ä¸»æ©Ÿå ±å‘Šä»–å€‘çš„ç©ºé–’å…§å­˜ï¼Œè€Œä¸»æ©Ÿå‰‡å°‡å ±å‘Šçš„å…§å­˜é‡æ–°åˆ†é…給其他客戶。因此,系統的內存得到了充
+分的利用。然而,客戶å¯èƒ½ä¸é‚£éº¼ç¯€çœå…§å­˜ï¼Œä¸»è¦æ˜¯å› çˆ²ä¸€äº›å…§æ ¸å­ç³»çµ±å’Œç”¨æˆ¶ç©ºé–“應用程åºè¢«è¨­è¨ˆçˆ²
+使用盡å¯èƒ½å¤šçš„內存。然後,客戶機å¯èƒ½åªå‘主機報告少é‡çš„內存是空閒的,導致系統的內存利用率下é™ã€‚
+在客戶中é‹è¡Œä¸»å‹•回收å¯ä»¥ç·©è§£é€™å€‹å•題。
+
+它是如何工作的?
+================
+
+DAMON_RECLAIM找到在特定時間內沒有被訪å•的內存å€åŸŸä¸¦åˆ†é ã€‚爲了é¿å…å®ƒåœ¨åˆ†é æ“作中消耗éŽå¤š
+çš„CPU,å¯ä»¥é…置一個速度é™åˆ¶ã€‚在這個速度é™åˆ¶ä¸‹ï¼Œå®ƒé¦–先分é å‡ºé‚£äº›æ²’有被訪å•éŽçš„å…§å­˜å€åŸŸã€‚ç³»
+統管ç†å“¡é‚„å¯ä»¥é…置在什麼情æ³ä¸‹é€™å€‹æ–¹æ¡ˆæ‡‰è©²è‡ªå‹•激活和åœç”¨ä¸‰å€‹å…§å­˜å£“力水ä½ã€‚
+
+接å£: æ¨¡å¡Šåƒæ•¸
+==============
+
+è¦ä½¿ç”¨é€™å€‹åŠŸèƒ½ï¼Œä½ é¦–å…ˆè¦ç¢ºä¿ä½ çš„系統é‹è¡Œåœ¨ä¸€å€‹ä»¥ ``CONFIG_DAMON_RECLAIM=y`` 構建的內
+核上。
+
+爲了讓系統管ç†å“¡å•“用或ç¦ç”¨å®ƒï¼Œä½µçˆ²çµ¦å®šçš„系統進行調整,DAMON_RECLAIMåˆ©ç”¨äº†æ¨¡å¡Šåƒæ•¸ã€‚也就
+是說,你å¯ä»¥æŠŠ ``damon_reclaim.<parameter>=<value>`` 放在內核啓動命令行上,或者把
+é©ç•¶çš„值寫入 ``/sys/module/damon_reclaim/parameters/<parameter>`` 文件。
+
+䏋颿˜¯æ¯å€‹åƒæ•¸çš„æè¿°ã€‚
+
+enabled
+-------
+
+啓用或ç¦ç”¨DAMON_RECLAIM。
+
+ä½ å¯ä»¥é€šéŽæŠŠé€™å€‹åƒæ•¸çš„值設置爲 ``Y`` 來啓用DAMON_RCLAIM,把它設置爲 ``N`` å¯ä»¥ç¦ç”¨
+DAMON_RECLAIM。注æ„,由於基於水ä½çš„æ¿€æ´»æ¢ä»¶ï¼ŒDAMON_RECLAIMä¸èƒ½é€²è¡ŒçœŸæ­£çš„監測和回收。
+這一點請åƒè€ƒä¸‹é¢é—œæ–¼æ°´ä½åƒæ•¸çš„æè¿°ã€‚
+
+min_age
+-------
+
+識別冷內存å€åŸŸçš„æ™‚é–“é–¾å€¼ï¼Œå–®ä½æ˜¯å¾®ç§’。
+
+如果一個內存å€åŸŸåœ¨é€™å€‹æ™‚間或更長的時間內沒有被訪å•,DAMON_RECLAIM會將該å€åŸŸè­˜åˆ¥çˆ²å†·çš„,
+並回收它。
+
+默èªçˆ²120秒。
+
+quota_ms
+--------
+
+回收的時間é™åˆ¶ï¼Œä»¥æ¯«ç§’爲單ä½ã€‚
+
+DAMON_RECLAIM 試圖在一個時間窗å£ï¼ˆquota_reset_interval_ms)內åªä½¿ç”¨åˆ°é€™å€‹æ™‚間,以
+嘗試回收冷é ã€‚這å¯ä»¥ç”¨ä¾†é™åˆ¶DAMON_RECLAIMçš„CPU消耗。如果該值爲零,則該é™åˆ¶è¢«ç¦ç”¨ã€‚
+
+默èªçˆ²10ms。
+
+quota_sz
+--------
+
+回收的內存大å°é™åˆ¶ï¼Œå–®ä½çˆ²å­—節。
+
+DAMON_RECLAIM æ”¶å–在一個時間窗å£ï¼ˆquota_reset_interval_ms)內試圖回收的內存é‡ï¼Œä¸¦
+使其ä¸è¶…éŽé€™å€‹é™åˆ¶ã€‚這å¯ä»¥ç”¨ä¾†é™åˆ¶CPUå’ŒIO的消耗。如果該值爲零,則é™åˆ¶è¢«ç¦ç”¨ã€‚
+
+é»˜èªæƒ…æ³ä¸‹æ˜¯128 MiB。
+
+quota_reset_interval_ms
+-----------------------
+
+時間/大å°é…顿”¶å–é‡ç½®é–“隔,單ä½çˆ²æ¯«ç§’。
+
+時間(quota_ms)和大å°ï¼ˆquota_sz)的é…é¡çš„目標é‡ç½®é–“隔。也就是說,DAMON_RECLAIM在
+嘗試回收‘ä¸â€™è¶…éŽquota_ms毫秒或quota_sz字節的內存。
+
+默èªçˆ²1秒。
+
+wmarks_interval
+---------------
+
+ç•¶DAMON_RECLAIM被啓用但由於其水ä½è¦å‰‡è€Œä¸æ´»èºæ™‚,在檢查水ä½ä¹‹å‰çš„æœ€å°ç­‰å¾…時間。
+
+wmarks_high
+-----------
+
+高水ä½çš„å¯ç”¨å…§å­˜çŽ‡ï¼ˆæ¯åƒå­—節)。
+
+如果系統的å¯ç”¨å…§å­˜ï¼ˆä»¥æ¯åƒå­—節爲單ä½ï¼‰é«˜æ–¼é€™å€‹æ•¸å€¼ï¼ŒDAMON_RECLAIMå°±æœƒè®Šå¾—ä¸æ´»èºï¼Œæ‰€ä»¥
+它什麼也ä¸åšï¼Œåªæ˜¯å®šæœŸæª¢æŸ¥æ°´ä½ã€‚
+
+wmarks_mid
+----------
+
+中間水ä½çš„å¯ç”¨å…§å­˜çŽ‡ï¼ˆæ¯åƒå­—節)。
+
+如果系統的空閒內存(以æ¯åƒå­—節爲單ä½ï¼‰åœ¨é€™å€‹å’Œä½Žæ°´ä½ç·šä¹‹é–“,DAMON_RECLAIM就會被激活,
+因此開始監測和回收。
+
+wmarks_low
+----------
+
+低水ä½çš„å¯ç”¨å…§å­˜çŽ‡ï¼ˆæ¯åƒå­—節)。
+
+如果系統的空閒內存(以æ¯åƒå­—節爲單ä½ï¼‰ä½Žæ–¼é€™å€‹æ•¸å€¼ï¼ŒDAMON_RECLAIMå°±æœƒè®Šå¾—ä¸æ´»èºï¼Œæ‰€ä»¥
+它除了定期檢查水ä½å¤–什麼都ä¸åšã€‚在這種情æ³ä¸‹ï¼Œç³»çµ±æœƒé€€å›žåˆ°åŸºæ–¼LRU列表的é é¢ç²’度回收é‚輯。
+
+sample_interval
+---------------
+
+ç›£æ¸¬çš„æŽ¡æ¨£é–“éš”ï¼Œå–®ä½æ˜¯å¾®ç§’。
+
+DAMON用於監測冷內存的採樣間隔。更多細節請åƒè€ƒDAMON文檔 (:doc:`usage`) 。
+
+aggr_interval
+-------------
+
+監測的èšé›†é–“éš”ï¼Œå–®ä½æ˜¯å¾®ç§’。
+
+DAMONå°å†·å…§å­˜ç›£æ¸¬çš„èšé›†é–“隔。更多細節請åƒè€ƒDAMON文檔 (:doc:`usage`)。
+
+min_nr_regions
+--------------
+
+監測å€åŸŸçš„æœ€å°æ•¸é‡ã€‚
+
+DAMON用於冷內存監測的最å°ç›£æ¸¬å€åŸŸæ•¸ã€‚這å¯ä»¥ç”¨ä¾†è¨­ç½®ç›£æ¸¬è³ªé‡çš„下é™ã€‚但是,設
+置的太高å¯èƒ½æœƒå°Žè‡´ç›£æ¸¬é–‹éŠ·çš„å¢žåŠ ã€‚æ›´å¤šç´°ç¯€è«‹åƒè€ƒDAMON文檔 (:doc:`usage`) 。
+
+max_nr_regions
+--------------
+
+監測å€åŸŸçš„æœ€å¤§æ•¸é‡ã€‚
+
+DAMON用於冷內存監測的最大監測å€åŸŸæ•¸ã€‚這å¯ä»¥ç”¨ä¾†è¨­ç½®ç›£æ¸¬é–‹éŠ·çš„ä¸Šé™å€¼ã€‚但是,
+設置得太低å¯èƒ½æœƒå°Žè‡´ç›£æ¸¬è³ªé‡ä¸å¥½ã€‚更多細節請åƒè€ƒDAMON文檔 (:doc:`usage`) 。
+
+monitor_region_start
+--------------------
+
+目標內存å€åŸŸçš„物ç†åœ°å€èµ·é»žã€‚
+
+DAMON_RECLAIMå°‡å°å…¶é€²è¡Œå·¥ä½œçš„å…§å­˜å€åŸŸçš„起始物ç†åœ°å€ã€‚也就是說,DAMON_RECLAIM
+將在這個å€åŸŸä¸­æ‰¾åˆ°å†·çš„å…§å­˜å€åŸŸä¸¦é€²è¡Œå›žæ”¶ã€‚é»˜èªæƒ…æ³ä¸‹ï¼Œè©²å€åŸŸä½¿ç”¨æœ€å¤§ç³»çµ±å…§å­˜å€ã€‚
+
+monitor_region_end
+------------------
+
+目標內存å€åŸŸçš„çµæŸç‰©ç†åœ°å€ã€‚
+
+DAMON_RECLAIMå°‡å°å…¶é€²è¡Œå·¥ä½œçš„å…§å­˜å€åŸŸçš„æœ«ç«¯ç‰©ç†åœ°å€ã€‚也就是說,DAMON_RECLAIMå°‡
+在這個å€åŸŸå…§æ‰¾åˆ°å†·çš„å…§å­˜å€åŸŸä¸¦é€²è¡Œå›žæ”¶ã€‚é»˜èªæƒ…æ³ä¸‹ï¼Œè©²å€åŸŸä½¿ç”¨æœ€å¤§ç³»çµ±å…§å­˜å€ã€‚
+
+kdamond_pid
+-----------
+
+DAMON線程的PID。
+
+如果DAMON_RECLAIM被啓用,這將æˆçˆ²å·¥ä½œç·šç¨‹çš„PID。å¦å‰‡ï¼Œçˆ²-1。
+
+nr_reclaim_tried_regions
+------------------------
+
+試圖通éŽDAMON_RECLAIM回收的內存å€åŸŸçš„æ•¸é‡ã€‚
+
+bytes_reclaim_tried_regions
+---------------------------
+
+試圖通éŽDAMON_RECLAIM回收的內存å€åŸŸçš„總字節數。
+
+nr_reclaimed_regions
+--------------------
+
+通éŽDAMON_RECLAIMæˆåŠŸå›žæ”¶çš„å…§å­˜å€åŸŸçš„æ•¸é‡ã€‚
+
+bytes_reclaimed_regions
+-----------------------
+
+通éŽDAMON_RECLAIMæˆåŠŸå›žæ”¶çš„å…§å­˜å€åŸŸçš„總字節數。
+
+nr_quota_exceeds
+----------------
+
+è¶…éŽæ™‚é–“/空間é…é¡é™åˆ¶çš„æ¬¡æ•¸ã€‚
+
+例å­
+====
+
+下é¢çš„é‹è¡Œç¤ºä¾‹å‘½ä»¤ä½¿DAMON_RECLAIM找到30秒或更長時間沒有訪å•的內存å€åŸŸä¸¦â€œå›žæ”¶â€ï¼Ÿ
+爲了é¿å…DAMON_RECLAIMåœ¨åˆ†é æ“作中消耗éŽå¤šçš„CPU時間,回收被é™åˆ¶åœ¨æ¯ç§’1GiB以內。
+å®ƒé‚„è¦æ±‚DAMON_RECLAIM在系統的å¯ç”¨å…§å­˜çŽ‡è¶…éŽ50%時ä¸åšä»»ä½•事情,但如果它低於40%時
+就開始真正的工作。如果DAMON_RECLAIM沒有å–得進展,因此空閒內存率低於20%ï¼Œå®ƒæœƒè¦æ±‚
+DAMON_RECLAIM冿¬¡ä»€éº¼éƒ½ä¸åšï¼Œé€™æ¨£æˆ‘們就å¯ä»¥é€€å›žåˆ°åŸºæ–¼LRU列表的é é¢ç²’度回收了::
+
+ # cd /sys/module/damon_reclaim/parameters
+ # echo 30000000 > min_age
+ # echo $((1 * 1024 * 1024 * 1024)) > quota_sz
+ # echo 1000 > quota_reset_interval_ms
+ # echo 500 > wmarks_high
+ # echo 400 > wmarks_mid
+ # echo 200 > wmarks_low
+ # echo Y > enabled
+
+.. [1] https://research.google/pubs/pub48551/
+.. [2] https://lwn.net/Articles/787611/
+.. [3] https://www.kernel.org/doc/html/latest/mm/free_page_reporting.html
+
diff --git a/Documentation/translations/zh_TW/admin-guide/mm/damon/start.rst b/Documentation/translations/zh_TW/admin-guide/mm/damon/start.rst
new file mode 100644
index 000000000000..1822956be0e0
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/mm/damon/start.rst
@@ -0,0 +1,125 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/mm/damon/start.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+:æ ¡è­¯:
+
+========
+入門指å—
+========
+
+æœ¬æ–‡é€šéŽæ¼”示DAMON的默èªç”¨æˆ¶ç©ºé–“工具,簡è¦åœ°ä»‹ç´¹çž­å¦‚何使用DAMON。請注æ„,爲了簡潔
+èµ·è¦‹ï¼Œæœ¬æ–‡æª”åªæè¿°äº†å®ƒçš„éƒ¨åˆ†åŠŸèƒ½ã€‚æ›´å¤šç´°ç¯€è«‹åƒè€ƒè©²å·¥å…·çš„使用文檔。
+`doc <https://github.com/awslabs/damo/blob/next/USAGE.md>`_ .
+
+
+剿æ¢ä»¶
+========
+
+å…§æ ¸
+----
+
+首先,你è¦ç¢ºä¿ä½ ç•¶å‰ç³»çµ±ä¸­è·‘的內核構建時é¸å®šäº†é€™å€‹åŠŸèƒ½é¸é … ``CONFIG_DAMON_*=y``.
+
+
+用戶空間工具
+------------
+
+在演示中,我們將使用DAMON的默èªç”¨æˆ¶ç©ºé–“工具,稱爲DAMON Operator(DAMO)。它å¯ä»¥åœ¨
+https://github.com/awslabs/damo找到。下é¢çš„例å­å‡è¨­DAMO在你的$PATH上。當然,但
+這䏦䏿˜¯å¼·åˆ¶æ€§çš„。
+
+因爲DAMO使用了DAMONçš„sysfs接å£ï¼ˆè©³æƒ…è«‹åƒè€ƒ:doc:`usage`),你應該確ä¿
+:doc:`sysfs </filesystems/sysfs>` 被掛載。
+
+è¨˜éŒ„æ•¸æ“šè¨ªå•æ¨¡å¼
+================
+
+下é¢çš„命令記錄了一個程åºçš„å…§å­˜è¨ªå•æ¨¡å¼ï¼Œä¸¦å°‡ç›£æ¸¬çµæžœä¿å­˜åˆ°æ–‡ä»¶ä¸­ã€‚ ::
+
+ $ git clone https://github.com/sjp38/masim
+ $ cd masim; make; ./masim ./configs/zigzag.cfg &
+ $ sudo damo record -o damon.data $(pidof masim)
+
+命令的å‰å…©è¡Œä¸‹è¼‰äº†ä¸€å€‹äººå·¥å…§å­˜è¨ªå•生æˆå™¨ç¨‹åºä¸¦åœ¨å¾Œè‡ºé‹è¡Œã€‚生æˆå™¨å°‡é‡è¤‡åœ°é€ä¸€è¨ªå•兩個
+100 MiB大å°çš„å…§å­˜å€åŸŸã€‚ä½ å¯ä»¥ç”¨ä½ çš„çœŸå¯¦å·¥ä½œè² è¼‰ä¾†ä»£æ›¿å®ƒã€‚æœ€å¾Œä¸€è¡Œè¦æ±‚ ``damo`` å°‡
+è¨ªå•æ¨¡å¼è¨˜éŒ„在 ``damon.data`` 文件中。
+
+
+將記錄的模å¼å¯è¦–化
+==================
+
+ä½ å¯ä»¥åœ¨heatmap中直觀地看到這種模å¼ï¼Œé¡¯ç¤ºå“ªå€‹å…§å­˜å€åŸŸï¼ˆX軸)何時被訪å•(Y軸)以åŠè¨ª
+å•的頻率(數字)。::
+
+ $ sudo damo report heats --heatmap stdout
+ 22222222222222222222222222222222222222211111111111111111111111111111111111111100
+ 44444444444444444444444444444444444444434444444444444444444444444444444444443200
+ 44444444444444444444444444444444444444433444444444444444444444444444444444444200
+ 33333333333333333333333333333333333333344555555555555555555555555555555555555200
+ 33333333333333333333333333333333333344444444444444444444444444444444444444444200
+ 22222222222222222222222222222222222223355555555555555555555555555555555555555200
+ 00000000000000000000000000000000000000288888888888888888888888888888888888888400
+ 00000000000000000000000000000000000000288888888888888888888888888888888888888400
+ 33333333333333333333333333333333333333355555555555555555555555555555555555555200
+ 88888888888888888888888888888888888888600000000000000000000000000000000000000000
+ 88888888888888888888888888888888888888600000000000000000000000000000000000000000
+ 33333333333333333333333333333333333333444444444444444444444444444444444444443200
+ 00000000000000000000000000000000000000288888888888888888888888888888888888888400
+ [...]
+ # access_frequency: 0 1 2 3 4 5 6 7 8 9
+ # x-axis: space (139728247021568-139728453431248: 196.848 MiB)
+ # y-axis: time (15256597248362-15326899978162: 1 m 10.303 s)
+ # resolution: 80x40 (2.461 MiB and 1.758 s for each character)
+
+你也å¯ä»¥ç›´è§€åœ°çœ‹åˆ°å·¥ä½œé›†çš„大å°åˆ†ä½ˆï¼ŒæŒ‰å¤§å°æŽ’åºã€‚::
+
+ $ sudo damo report wss --range 0 101 10
+ # <percentile> <wss>
+ # target_id 18446632103789443072
+ # avr: 107.708 MiB
+ 0 0 B | |
+ 10 95.328 MiB |**************************** |
+ 20 95.332 MiB |**************************** |
+ 30 95.340 MiB |**************************** |
+ 40 95.387 MiB |**************************** |
+ 50 95.387 MiB |**************************** |
+ 60 95.398 MiB |**************************** |
+ 70 95.398 MiB |**************************** |
+ 80 95.504 MiB |**************************** |
+ 90 190.703 MiB |********************************************************* |
+ 100 196.875 MiB |***********************************************************|
+
+在上述命令中使用 ``--sortby`` é¸é …,å¯ä»¥é¡¯ç¤ºå·¥ä½œé›†çš„大尿˜¯å¦‚何按時間順åºè®ŠåŒ–的。::
+
+ $ sudo damo report wss --range 0 101 10 --sortby time
+ # <percentile> <wss>
+ # target_id 18446632103789443072
+ # avr: 107.708 MiB
+ 0 3.051 MiB | |
+ 10 190.703 MiB |***********************************************************|
+ 20 95.336 MiB |***************************** |
+ 30 95.328 MiB |***************************** |
+ 40 95.387 MiB |***************************** |
+ 50 95.332 MiB |***************************** |
+ 60 95.320 MiB |***************************** |
+ 70 95.398 MiB |***************************** |
+ 80 95.398 MiB |***************************** |
+ 90 95.340 MiB |***************************** |
+ 100 95.398 MiB |***************************** |
+
+
+æ•¸æ“šè¨ªå•æ¨¡å¼æ„ŸçŸ¥çš„內存管ç†
+==========================
+
+以下三個命令使æ¯ä¸€å€‹å¤§å°>=4K的內存å€åŸŸåœ¨ä½ çš„工作負載中沒有被訪å•>=60ç§’ï¼Œå°±æœƒè¢«æ›æŽ‰ã€‚ ::
+
+ $ echo "#min-size max-size min-acc max-acc min-age max-age action" > test_scheme
+ $ echo "4K max 0 0 60s max pageout" >> test_scheme
+ $ damo schemes -c test_scheme <pid of your workload>
+
diff --git a/Documentation/translations/zh_TW/admin-guide/mm/damon/usage.rst b/Documentation/translations/zh_TW/admin-guide/mm/damon/usage.rst
new file mode 100644
index 000000000000..6dee719a32ea
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/mm/damon/usage.rst
@@ -0,0 +1,592 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/mm/damon/usage.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+:æ ¡è­¯:
+
+========
+詳細用法
+========
+
+DAMON 爲ä¸åŒçš„用戶æä¾›äº†ä¸‹é¢é€™äº›æŽ¥å£ã€‚
+
+- *DAMON用戶空間工具。*
+ `這 <https://github.com/awslabs/damo>`_ 爲有這特權的人, 如系統管ç†å“¡ï¼Œå¸Œæœ›æœ‰ä¸€å€‹å‰›å¥½
+ å¯ä»¥å·¥ä½œçš„人性化界é¢ã€‚
+ 使用它,用戶å¯ä»¥ä»¥äººæ€§åŒ–的方å¼ä½¿ç”¨DAMON的主è¦åŠŸèƒ½ã€‚ä¸éŽï¼Œå®ƒå¯èƒ½ä¸æœƒçˆ²ç‰¹æ®Šæƒ…æ³é€²è¡Œé«˜åº¦èª¿æ•´ã€‚
+ å®ƒåŒæ™‚支æŒè™›æ“¬å’Œç‰©ç†åœ°å€ç©ºé–“的監測。更多細節,請åƒè€ƒå®ƒçš„ `使用文檔
+ <https://github.com/awslabs/damo/blob/next/USAGE.md>`_。
+- *sysfs接å£ã€‚*
+ :ref:`這 <sysfs_interface>` 是爲那些希望更高級的使用DAMON的特權用戶空間程åºå“¡æº–備的。
+ 使用它,用戶å¯ä»¥é€šéŽè®€å–和寫入特殊的sysfs文件來使用DAMON的主è¦åŠŸèƒ½ã€‚å› æ­¤ï¼Œä½ å¯ä»¥ç·¨å¯«å’Œä½¿
+ 用你個性化的DAMON sysfs包è£ç¨‹åºï¼Œä»£æ›¿ä½ è®€/寫sysfs文件。 `DAMON用戶空間工具
+ <https://github.com/awslabs/damo>`_ 就是這種程åºçš„ä¸€å€‹ä¾‹å­ å®ƒåŒæ™‚支æŒè™›æ“¬å’Œç‰©ç†åœ°å€
+ 空間的監測。注æ„,這個界é¢åªæä¾›ç°¡å–®çš„ç›£æ¸¬çµæžœ :ref:`統計 <damos_stats>`ã€‚å°æ–¼è©³ç´°çš„監測
+ çµæžœï¼ŒDAMONæä¾›äº†ä¸€å€‹:ref:`跟蹤點 <tracepoint>`。
+- *debugfs interface.*
+ :ref:`這 <debugfs_interface>` 幾乎與:ref:`sysfs interface <sysfs_interface>` 接
+ å£ç›¸åŒã€‚這將在下一個LTS內核發佈後被移除,所以用戶應該轉移到
+ :ref:`sysfs interface <sysfs_interface>`。
+- *內核空間編程接å£ã€‚*
+ :doc:`這 </mm/damon/api>` 這是爲內核空間程åºå“¡æº–備的。使用它,用戶å¯ä»¥é€šéŽçˆ²ä½ ç·¨å¯«å…§
+ 核空間的DAMON應用程åºï¼Œæœ€éˆæ´»æœ‰æ•ˆåœ°åˆ©ç”¨DAMONçš„æ¯ä¸€å€‹åŠŸèƒ½ã€‚ä½ ç”šè‡³å¯ä»¥çˆ²å„種地å€ç©ºé–“擴展DAMON。
+ 詳細情æ³è«‹åƒè€ƒæŽ¥å£ :doc:`文件 </mm/damon/api>`。
+
+sysfs接å£
+=========
+DAMONçš„sysfsæŽ¥å£æ˜¯åœ¨å®šç¾© ``CONFIG_DAMON_SYSFS`` 時建立的。它在其sysfs目錄下創建多
+個目錄和文件, ``<sysfs>/kernel/mm/damon/`` 。你å¯ä»¥é€šéŽå°è©²ç›®éŒ„下的文件進行寫入和
+讀å–來控制DAMON。
+
+å°æ–¼ä¸€å€‹ç°¡çŸ­çš„例å­ï¼Œç”¨æˆ¶å¯ä»¥ç›£æ¸¬ä¸€å€‹çµ¦å®šå·¥ä½œè² è¼‰çš„虛擬地å€ç©ºé–“,如下所示::
+
+ # cd /sys/kernel/mm/damon/admin/
+ # echo 1 > kdamonds/nr_kdamonds && echo 1 > kdamonds/0/contexts/nr_contexts
+ # echo vaddr > kdamonds/0/contexts/0/operations
+ # echo 1 > kdamonds/0/contexts/0/targets/nr_targets
+ # echo $(pidof <workload>) > kdamonds/0/contexts/0/targets/0/pid_target
+ # echo on > kdamonds/0/state
+
+æ–‡ä»¶å±¤æ¬¡çµæ§‹
+------------
+
+DAMON sysfs接å£çš„æ–‡ä»¶å±¤æ¬¡çµæ§‹å¦‚下圖所示。在下圖中,父å­é—œä¿‚用縮進表示,æ¯å€‹ç›®éŒ„有
+``/`` 後綴,æ¯å€‹ç›®éŒ„中的文件用逗號(",")分開。 ::
+
+ /sys/kernel/mm/damon/admin
+ │ kdamonds/nr_kdamonds
+ │ │ 0/state,pid
+ │ │ │ contexts/nr_contexts
+ │ │ │ │ 0/operations
+ │ │ │ │ │ monitoring_attrs/
+ │ │ │ │ │ │ intervals/sample_us,aggr_us,update_us
+ │ │ │ │ │ │ nr_regions/min,max
+ │ │ │ │ │ targets/nr_targets
+ │ │ │ │ │ │ 0/pid_target
+ │ │ │ │ │ │ │ regions/nr_regions
+ │ │ │ │ │ │ │ │ 0/start,end
+ │ │ │ │ │ │ │ │ ...
+ │ │ │ │ │ │ ...
+ │ │ │ │ │ schemes/nr_schemes
+ │ │ │ │ │ │ 0/action
+ │ │ │ │ │ │ │ access_pattern/
+ │ │ │ │ │ │ │ │ sz/min,max
+ │ │ │ │ │ │ │ │ nr_accesses/min,max
+ │ │ │ │ │ │ │ │ age/min,max
+ │ │ │ │ │ │ │ quotas/ms,bytes,reset_interval_ms
+ │ │ │ │ │ │ │ │ weights/sz_permil,nr_accesses_permil,age_permil
+ │ │ │ │ │ │ │ watermarks/metric,interval_us,high,mid,low
+ │ │ │ │ │ │ │ stats/nr_tried,sz_tried,nr_applied,sz_applied,qt_exceeds
+ │ │ │ │ │ │ │ tried_regions/
+ │ │ │ │ │ │ │ │ 0/start,end,nr_accesses,age
+ │ │ │ │ │ │ │ │ ...
+ │ │ │ │ │ │ ...
+ │ │ │ │ ...
+ │ │ ...
+
+æ ¹
+--
+
+DAMON sysfs接å£çš„æ ¹æ˜¯ ``<sysfs>/kernel/mm/damon/`` ,它有一個å爲 ``admin`` çš„
+目錄。該目錄包å«ç‰¹æ¬Šç”¨æˆ¶ç©ºé–“ç¨‹åºæŽ§åˆ¶DAMONçš„æ–‡ä»¶ã€‚æ“æœ‰æ ¹æ¬Šé™çš„用戶空間工具或deamonså¯ä»¥
+使用這個目錄。
+
+kdamonds/
+---------
+
+與監測相關的信æ¯åŒ…æ‹¬è«‹æ±‚è¦æ ¼å’Œçµæžœè¢«ç¨±çˆ²DAMON上下文。DAMON用一個å«åškdamond的內核線程
+執行æ¯å€‹ä¸Šä¸‹æ–‡ï¼Œå¤šå€‹kdamondså¯ä»¥ä¸¦è¡Œé‹è¡Œã€‚
+
+在 ``admin`` 目錄下,有一個目錄,å³``kdamonds``,它有控制kdamonds的文件存在。在開始
+æ™‚ï¼Œé€™å€‹ç›®éŒ„åªæœ‰ä¸€å€‹æ–‡ä»¶ï¼Œ``nr_kdamonds``。å‘該文件寫入一個數字(``N``),就會創建å爲
+``0`` 到 ``N-1`` çš„å­ç›®éŒ„數é‡ã€‚æ¯å€‹ç›®éŒ„代表æ¯å€‹kdamond。
+
+kdamonds/<N>/
+-------------
+
+在æ¯å€‹kdamond目錄中,存在兩個文件(``state`` å’Œ ``pid`` )和一個目錄( ``contexts`` )。
+
+è®€å– ``state`` 時,如果kdamondç•¶å‰æ­£åœ¨é‹è¡Œï¼Œå‰‡è¿”回 ``on`` ,如果沒有é‹è¡Œå‰‡è¿”回 ``off`` 。
+寫入 ``on`` 或 ``off`` 使kdamondè™•æ–¼ç‹€æ…‹ã€‚å‘ ``state`` 文件寫 ``update_schemes_stats`` ,
+æ›´æ–°kdamondçš„æ¯å€‹åŸºæ–¼DAMONçš„æ“作方案的統計文件的內容。關於統計信æ¯çš„細節,請åƒè€ƒ
+:ref:`stats section <sysfs_schemes_stats>`. 將 ``update_schemes_tried_regions`` 寫到
+``state`` 文件,爲kdamondçš„æ¯å€‹åŸºæ–¼DAMONçš„æ“作方案,更新基於DAMONçš„æ“作方案動作的嘗試å€åŸŸç›®éŒ„。
+å°‡`clear_schemes_tried_regions`寫入`state`文件,清除kdamondçš„æ¯å€‹åŸºæ–¼DAMONçš„æ“作方案的動作
+嘗試å€åŸŸç›®éŒ„。 關於基於DAMONçš„æ“作方案動作嘗試å€åŸŸç›®éŒ„的細節,請åƒè€ƒ:ref:tried_regions 部分
+<sysfs_schemes_tried_regions>`。
+
+如果狀態爲 ``on``ï¼Œè®€å– ``pid`` 顯示kdamond線程的pid。
+
+``contexts`` ç›®éŒ„åŒ…å«æŽ§åˆ¶é€™å€‹kdamondè¦åŸ·è¡Œçš„監測上下文的文件。
+
+kdamonds/<N>/contexts/
+----------------------
+
+åœ¨é–‹å§‹æ™‚ï¼Œé€™å€‹ç›®éŒ„åªæœ‰ä¸€å€‹æ–‡ä»¶ï¼Œå³ ``nr_contexts`` 。å‘該文件寫入一個數字( ``N`` ),就會創
+建å爲``0`` 到 ``N-1`` çš„å­ç›®éŒ„數é‡ã€‚æ¯å€‹ç›®éŒ„代表æ¯å€‹ç›£æ¸¬èƒŒæ™¯ã€‚ç›®å‰ï¼Œæ¯å€‹kdamondåªæ”¯æŒ
+ä¸€å€‹ä¸Šä¸‹æ–‡ï¼Œæ‰€ä»¥åªæœ‰ ``0`` 或 ``1`` å¯ä»¥è¢«å¯«å…¥æ–‡ä»¶ã€‚
+
+contexts/<N>/
+-------------
+
+在æ¯å€‹ä¸Šä¸‹æ–‡ç›®éŒ„中,存在一個文件(``operations``)和三個目錄(``monitoring_attrs``,
+``targets``, 和 ``schemes``)。
+
+DAMON支æŒå¤šç¨®é¡žåž‹çš„監測æ“作,包括å°è™›æ“¬åœ°å€ç©ºé–“和物ç†åœ°å€ç©ºé–“的監測。你å¯ä»¥é€šéŽå‘文件
+中寫入以下關éµè©žä¹‹ä¸€ï¼Œä¸¦å¾žæ–‡ä»¶ä¸­è®€å–,來設置和ç²å–DAMON將爲上下文使用何種類型的監測æ“作。
+
+ - vaddr: 監測特定進程的虛擬地å€ç©ºé–“
+ - paddr: 監視系統的物ç†åœ°å€ç©ºé–“
+
+contexts/<N>/monitoring_attrs/
+------------------------------
+
+用於指定監測屬性的文件,包括所需的監測質é‡å’Œæ•ˆçŽ‡ï¼Œéƒ½åœ¨ ``monitoring_attrs`` 目錄中。
+å…·é«”ä¾†èªªï¼Œé€™å€‹ç›®éŒ„ä¸‹æœ‰å…©å€‹ç›®éŒ„ï¼Œå³ ``intervals`` å’Œ ``nr_regions`` 。
+
+在 ``intervals`` 目錄下,存在DAMON的採樣間隔(``sample_us``)ã€èšé›†é–“éš”(``aggr_us``)
+和更新間隔(``update_us``)三個文件。你å¯ä»¥é€šéŽå¯«å…¥å’Œè®€å‡ºé€™äº›æ–‡ä»¶ä¾†è¨­ç½®å’Œç²å–微秒級的值。
+
+在 ``nr_regions`` 目錄下,有兩個文件分別用於DAMON監測å€åŸŸçš„下é™å’Œä¸Šé™ï¼ˆ``min`` å’Œ ``max`` ),
+這兩個文件控制ç€ç›£æ¸¬çš„開銷。你å¯ä»¥é€šéŽå‘這些文件的寫入和讀出來設置和ç²å–這些值。
+
+關於間隔和監測å€åŸŸç¯„åœçš„æ›´å¤šç´°ç¯€ï¼Œè«‹åƒè€ƒè¨­è¨ˆæ–‡ä»¶ (:doc:`/mm/damon/design`)。
+
+contexts/<N>/targets/
+---------------------
+
+åœ¨é–‹å§‹æ™‚ï¼Œé€™å€‹ç›®éŒ„åªæœ‰ä¸€å€‹æ–‡ä»¶ ``nr_targets`` 。å‘該文件寫入一個數字(``N``),就å¯ä»¥å‰µå»º
+å爲 ``0`` 到 ``N-1`` çš„å­ç›®éŒ„的數é‡ã€‚æ¯å€‹ç›®éŒ„代表æ¯å€‹ç›£æ¸¬ç›®æ¨™ã€‚
+
+targets/<N>/
+------------
+
+在æ¯å€‹ç›®æ¨™ç›®éŒ„中,存在一個文件(``pid_target``)和一個目錄(``regions``)。
+
+如果你把 ``vaddr`` 寫到 ``contexts/<N>/operations`` 中,æ¯å€‹ç›®æ¨™æ‡‰è©²æ˜¯ä¸€å€‹é€²ç¨‹ã€‚ä½ 
+å¯ä»¥é€šéŽå°‡é€²ç¨‹çš„pid寫到 ``pid_target`` 文件中來指定DAMON的進程。
+
+targets/<N>/regions
+-------------------
+
+當使用 ``vaddr`` 監測æ“作集時( ``vaddr`` 被寫入 ``contexts/<N>/operations`` æ–‡
+件),DAMON自動設置和更新監測目標å€åŸŸï¼Œé€™æ¨£å°±å¯ä»¥è¦†è“‹ç›®æ¨™é€²ç¨‹çš„æ•´å€‹å…§å­˜æ˜ å°„。然而,用戶å¯
+能希望將åˆå§‹ç›£æ¸¬å€åŸŸè¨­ç½®çˆ²ç‰¹å®šçš„地å€ç¯„åœã€‚
+
+相å,當使用 ``paddr`` 監測æ“作集時,DAMON䏿œƒè‡ªå‹•設置和更新監測目標å€åŸŸï¼ˆ ``paddr``
+被寫入 ``contexts/<N>/operations`` 中)。因此,在這種情æ³ä¸‹ï¼Œç”¨æˆ¶æ‡‰è©²è‡ªå·±è¨­ç½®ç›£æ¸¬ç›®æ¨™
+å€åŸŸã€‚
+
+在這種情æ³ä¸‹ï¼Œç”¨æˆ¶å¯ä»¥æŒ‰ç…§è‡ªå·±çš„æ„é¡˜æ˜Žç¢ºè¨­ç½®åˆå§‹ç›£æ¸¬ç›®æ¨™å€åŸŸï¼Œå°‡é©ç•¶çš„值寫入該目錄下的文件。
+
+é–‹å§‹æ™‚ï¼Œé€™å€‹ç›®éŒ„åªæœ‰ä¸€å€‹æ–‡ä»¶ï¼Œ ``nr_regions`` 。å‘該文件寫入一個數字(``N``),就å¯ä»¥å‰µ
+建å爲 ``0`` 到 ``N-1`` çš„å­ç›®éŒ„。æ¯å€‹ç›®éŒ„代表æ¯å€‹åˆå§‹ç›£æ¸¬ç›®æ¨™å€åŸŸã€‚
+
+regions/<N>/
+------------
+
+在æ¯å€‹å€åŸŸç›®éŒ„中,你會發ç¾å…©å€‹æ–‡ä»¶ï¼ˆ ``start`` å’Œ ``end`` )。你å¯ä»¥é€šéŽå‘文件寫入
+和從文件中讀出,分別設置和ç²å¾—åˆå§‹ç›£æ¸¬ç›®æ¨™å€åŸŸçš„èµ·å§‹å’ŒçµæŸåœ°å€ã€‚
+
+æ¯å€‹å€åŸŸä¸æ‡‰è©²èˆ‡å…¶ä»–å€åŸŸé‡ç–Šã€‚ 目錄“Nâ€çš„â€œçµæŸâ€æ‡‰ç­‰æ–¼æˆ–å°æ–¼ç›®éŒ„“N+1â€çš„“開始â€ã€‚
+
+contexts/<N>/schemes/
+---------------------
+
+å°æ–¼ä¸€ç‰ˆçš„基於DAMONçš„æ•¸æ“šè¨ªå•æ„ŸçŸ¥çš„內存管ç†å„ªåŒ–,用戶通常希望系統å°ç‰¹å®šè¨ªå•模å¼çš„å…§å­˜å€
+åŸŸæ‡‰ç”¨å…§å­˜ç®¡ç†æ“作。DAMONå¾žç”¨æˆ¶é‚£è£æŽ¥æ”¶é€™ç¨®å½¢å¼åŒ–çš„æ“作方案,並將這些方案應用於目標內存
+å€åŸŸã€‚用戶å¯ä»¥é€šéŽè®€å–和寫入這個目錄下的文件來ç²å¾—和設置這些方案。
+
+åœ¨é–‹å§‹æ™‚ï¼Œé€™å€‹ç›®éŒ„åªæœ‰ä¸€å€‹æ–‡ä»¶ï¼Œ``nr_schemes``。å‘該文件寫入一個數字(``N``),就å¯ä»¥
+創建å爲``0``到``N-1``çš„å­ç›®éŒ„的數é‡ã€‚æ¯å€‹ç›®éŒ„代表æ¯å€‹åŸºæ–¼DAMONçš„æ“作方案。
+
+schemes/<N>/
+------------
+
+在æ¯å€‹æ–¹æ¡ˆç›®éŒ„中,存在五個目錄(``access_pattern``ã€``quotas``ã€``watermarks``ã€
+``stats`` 和 ``tried_regions``)和一個文件(``action``)。
+
+``action`` 文件用於設置和ç²å–ä½ æƒ³æ‡‰ç”¨æ–¼å…·æœ‰ç‰¹å®šè¨ªå•æ¨¡å¼çš„å…§å­˜å€åŸŸçš„動作。å¯ä»¥å¯«å…¥æ–‡ä»¶
+和從文件中讀å–的關éµè©žåŠå…¶å«ç¾©å¦‚下。
+
+ - ``willneed``: å°æœ‰ ``MADV_WILLNEED`` çš„å€åŸŸèª¿ç”¨ ``madvise()`` 。
+ - ``cold``: å°å…·æœ‰ ``MADV_COLD`` çš„å€åŸŸèª¿ç”¨ ``madvise()`` 。
+ - ``pageout``: 爲具有 ``MADV_PAGEOUT`` çš„å€åŸŸèª¿ç”¨ ``madvise()`` 。
+ - ``hugepage``: 爲帶有 ``MADV_HUGEPAGE`` çš„å€åŸŸèª¿ç”¨ ``madvise()`` 。
+ - ``nohugepage``: 爲帶有 ``MADV_NOHUGEPAGE`` çš„å€åŸŸèª¿ç”¨ ``madvise()``。
+ - ``lru_prio``: 在其LRU列表上å°å€åŸŸé€²è¡Œå„ªå…ˆæŽ’åºã€‚
+ - ``lru_deprio``: å°å€åŸŸçš„LRU列表進行é™ä½Žå„ªå…ˆè™•ç†ã€‚
+ - ``stat``: 什麼都ä¸åšï¼Œåªè¨ˆç®—統計數據
+
+schemes/<N>/access_pattern/
+---------------------------
+
+æ¯å€‹åŸºæ–¼DAMONçš„æ“ä½œæ–¹æ¡ˆçš„ç›®æ¨™è¨ªå•æ¨¡å¼ç”±ä¸‰å€‹ç¯„åœæ§‹æˆï¼ŒåŒ…括以字節爲單ä½çš„å€åŸŸå¤§å°ã€æ¯å€‹
+èšåˆå€é–“çš„ç›£æ¸¬è¨ªå•æ¬¡æ•¸å’Œå€åŸŸå¹´é½¡çš„èšåˆå€é–“數。
+
+在 ``access_pattern`` 目錄下,存在三個目錄( ``sz``, ``nr_accesses``, 和 ``age`` ),
+æ¯å€‹ç›®éŒ„有兩個文件(``min`` å’Œ ``max`` )。你å¯ä»¥é€šéŽå‘ ``sz``, ``nr_accesses``, å’Œ
+``age`` 目錄下的 ``min`` å’Œ ``max`` 文件分別寫入和讀å–來設置和ç²å–çµ¦å®šæ–¹æ¡ˆçš„è¨ªå•æ¨¡å¼ã€‚
+
+schemes/<N>/quotas/
+-------------------
+
+æ¯å€‹ ``動作`` 的最佳 ``ç›®æ¨™è¨ªå•æ¨¡å¼`` å–æ±ºæ–¼å·¥ä½œè² è¼‰ï¼Œæ‰€ä»¥ä¸å®¹æ˜“找到。更糟糕的是,將æŸäº›å‹•作
+çš„æ–¹æ¡ˆè¨­ç½®å¾—éŽæ–¼æ¿€é€²æœƒé€ æˆåš´é‡çš„開銷。爲了é¿å…這種開銷,用戶å¯ä»¥çˆ²æ¯å€‹æ–¹æ¡ˆé™åˆ¶æ™‚間和大å°é…é¡ã€‚
+具體來說,用戶å¯ä»¥è¦æ±‚DAMON儘é‡åªä½¿ç”¨ç‰¹å®šçš„æ™‚間(``時間é…é¡``)來應用動作,並且在給定的時間間
+隔(``é‡ç½®é–“éš”``)內,åªå°å…·æœ‰ç›®æ¨™è¨ªå•模å¼çš„å…§å­˜å€åŸŸæ‡‰ç”¨å‹•作,而ä¸ä½¿ç”¨ç‰¹å®šæ•¸é‡ï¼ˆ``大å°é…é¡``)。
+
+ç•¶é è¨ˆè¶…éŽé…é¡é™åˆ¶æ™‚,DAMON會根據 ``ç›®æ¨™è¨ªå•æ¨¡å¼`` 的大å°ã€è¨ªå•é »çŽ‡å’Œå¹´é½¡ï¼Œå°æ‰¾åˆ°çš„å…§å­˜å€åŸŸ
+進行優先排åºã€‚爲了進行個性化的優先排åºï¼Œç”¨æˆ¶å¯ä»¥çˆ²é€™ä¸‰å€‹å±¬æ€§è¨­ç½®æ¬Šé‡ã€‚
+
+在 ``quotas`` 目錄下,存在三個文件(``ms``, ``bytes``, ``reset_interval_ms``)和一個
+目錄(``weights``),其中有三個文件(``sz_permil``, ``nr_accesses_permil``, 和
+``age_permil``)。
+
+ä½ å¯ä»¥è¨­ç½®ä»¥æ¯«ç§’爲單ä½çš„ ``時間é…é¡`` ,以字節爲單ä½çš„ ``大å°é…é¡`` ,以åŠä»¥æ¯«ç§’爲單ä½çš„ ``é‡
+置間隔`` ,分別å‘這三個文件寫入數值。你還å¯ä»¥é€šéŽå‘ ``weights`` 目錄下的三個文件寫入數值來設
+置大å°ã€è¨ªå•頻率和年齡的優先權,單ä½çˆ²åƒåˆ†ä¹‹ä¸€ã€‚
+
+schemes/<N>/watermarks/
+-----------------------
+
+爲了便於根據系統狀態激活和åœç”¨æ¯å€‹æ–¹æ¡ˆï¼ŒDAMONæä¾›äº†ä¸€å€‹ç¨±çˆ²æ°´ä½çš„功能。該功能接收五個值,稱爲
+``度é‡`` ã€``é–“éš”`` ã€``高`` ã€``中`` ã€``低`` 。``度é‡å€¼`` 是指å¯ä»¥æ¸¬é‡çš„系統度é‡å€¼ï¼Œå¦‚
+自由內存比率。如果系統的度é‡å€¼ ``高`` æ–¼memoent的高值或 ``低`` 於低值,則該方案被åœç”¨ã€‚如果
+該值低於 ``中`` ,則該方案被激活。
+
+在水ä½ç›®éŒ„下,存在五個文件(``metric``, ``interval_us``,``high``, ``mid``, and ``low``)
+用於設置æ¯å€‹å€¼ã€‚ä½ å¯ä»¥é€šéŽå‘這些文件的寫入來分別設置和ç²å–這五個值。
+
+å¯ä»¥å¯«å…¥ ``metric`` 文件的關éµè©žå’Œå«ç¾©å¦‚下。
+
+ - none: 忽略水ä½
+ - free_mem_rate: 系統的自由內存率(åƒåˆ†æ¯”)。
+
+``interval`` 應以微秒爲單ä½å¯«å…¥ã€‚
+
+schemes/<N>/stats/
+------------------
+
+DAMON統計æ¯å€‹æ–¹æ¡ˆè¢«å˜—試應用的å€åŸŸçš„總數é‡å’Œå­—節數,æ¯å€‹æ–¹æ¡ˆè¢«æˆåŠŸæ‡‰ç”¨çš„å€åŸŸçš„兩個數字,以åŠ
+è¶…éŽé…é¡é™åˆ¶çš„總數é‡ã€‚這些統計數據å¯ç”¨æ–¼åœ¨ç·šåˆ†æžæˆ–調整方案。
+
+å¯ä»¥é€šéŽè®€å– ``stats`` 目錄下的文件(``nr_tried``, ``sz_tried``, ``nr_applied``,
+``sz_applied``, å’Œ ``qt_exceeds``)ï¼‰åˆ†åˆ¥æª¢ç´¢é€™äº›çµ±è¨ˆæ•¸æ“šã€‚é€™äº›æ–‡ä»¶ä¸æ˜¯å¯¦æ™‚更新的,所以
+ä½ æ‡‰è©²è¦æ±‚DAMON sysfs接å£é€šéŽåœ¨ç›¸é—œçš„ ``kdamonds/<N>/state`` 文件中寫入一個特殊的關éµå­—
+``update_schemes_stats`` 來更新統計信æ¯çš„æ–‡ä»¶å…§å®¹ã€‚
+
+schemes/<N>/tried_regions/
+--------------------------
+
+當一個特殊的關éµå­— ``update_schemes_tried_regions`` 被寫入相關的 ``kdamonds/<N>/state``
+文件時,DAMON會在這個目錄下創建從 ``0`` 開始命å的整數目錄。æ¯å€‹ç›®éŒ„包å«çš„æ–‡ä»¶æš´éœ²äº†é—œæ–¼æ¯å€‹
+å…§å­˜å€åŸŸçš„詳細信æ¯ï¼Œåœ¨ä¸‹ä¸€å€‹ :ref:`èšé›†å€é–“ <sysfs_monitoring_attrs>`,相應的方案的 ``動作``
+已經嘗試在這個目錄下應用。這些信æ¯åŒ…括地å€ç¯„åœã€``nr_accesses`` 以åŠå€åŸŸçš„ ``年齡`` 。
+
+ç•¶å¦ä¸€å€‹ç‰¹æ®Šçš„é—œéµå­— ``clear_schemes_tried_regions`` 被寫入相關的 ``kdamonds/<N>/state``
+文件時,這些目錄將被刪除。
+
+tried_regions/<N>/
+------------------
+
+在æ¯å€‹å€åŸŸç›®éŒ„中,你會發ç¾å››å€‹æ–‡ä»¶(``start``, ``end``, ``nr_accesses``, and ``age``)。
+讀å–這些文件將顯示相應的基於DAMONçš„æ“作方案 ``動作`` 試圖應用的å€åŸŸçš„é–‹å§‹å’ŒçµæŸåœ°å€ã€``nr_accesses``
+和 ``年齡`` 。
+
+用例
+~~~~
+
+下é¢çš„命令應用了一個方案:â€å¦‚果一個大å°çˆ²[4KiB, 8KiB]的內存å€åŸŸåœ¨[10, 20]çš„èšåˆæ™‚間間隔內
+顯示出æ¯ä¸€å€‹èšåˆæ™‚é–“é–“éš”[0, 5]的訪å•é‡ï¼Œè«‹åˆ†é è©²å€åŸŸã€‚å°æ–¼åˆ†é ï¼Œæ¯ç§’最多隻能使用10ms,而且æ¯
+秒分é ä¸èƒ½è¶…éŽ1GiB。在這一é™åˆ¶ä¸‹ï¼Œé¦–先分é å‡ºå…·æœ‰è¼ƒé•·å¹´é½¡çš„å…§å­˜å€åŸŸã€‚å¦å¤–,æ¯5ç§’é˜æª¢æŸ¥ä¸€æ¬¡ç³»çµ±
+çš„å¯ç”¨å…§å­˜çŽ‡ï¼Œç•¶å¯ç”¨å…§å­˜çŽ‡ä½Žæ–¼50%時開始監測和分é ï¼Œä½†å¦‚æžœå¯ç”¨å…§å­˜çŽ‡å¤§æ–¼60%,或低於30%,則åœ
+止監測。“ ::
+
+ # cd <sysfs>/kernel/mm/damon/admin
+ # # populate directories
+ # echo 1 > kdamonds/nr_kdamonds; echo 1 > kdamonds/0/contexts/nr_contexts;
+ # echo 1 > kdamonds/0/contexts/0/schemes/nr_schemes
+ # cd kdamonds/0/contexts/0/schemes/0
+ # # set the basic access pattern and the action
+ # echo 4096 > access_pattern/sz/min
+ # echo 8192 > access_pattern/sz/max
+ # echo 0 > access_pattern/nr_accesses/min
+ # echo 5 > access_pattern/nr_accesses/max
+ # echo 10 > access_pattern/age/min
+ # echo 20 > access_pattern/age/max
+ # echo pageout > action
+ # # set quotas
+ # echo 10 > quotas/ms
+ # echo $((1024*1024*1024)) > quotas/bytes
+ # echo 1000 > quotas/reset_interval_ms
+ # # set watermark
+ # echo free_mem_rate > watermarks/metric
+ # echo 5000000 > watermarks/interval_us
+ # echo 600 > watermarks/high
+ # echo 500 > watermarks/mid
+ # echo 300 > watermarks/low
+
+請注æ„,我們強烈建議使用用戶空間的工具,如 `damo <https://github.com/awslabs/damo>`_ ,
+è€Œä¸æ˜¯åƒä¸Šé¢é‚£æ¨£æ‰‹å‹•è®€å¯«æ–‡ä»¶ã€‚ä»¥ä¸Šåªæ˜¯ä¸€å€‹ä¾‹å­ã€‚
+
+debugfs接å£
+===========
+
+.. note::
+
+ DAMON debugfs接å£å°‡åœ¨ä¸‹ä¸€å€‹LTS內核發佈後被移除,所以用戶應該轉移到
+ :ref:`sysfs接å£<sysfs_interface>`。
+
+DAMON導出了八個文件, ``attrs``, ``target_ids``, ``init_regions``,
+``schemes``, ``monitor_on``, ``kdamond_pid``, ``mk_contexts`` 和
+``rm_contexts`` under its debugfs directory, ``<debugfs>/damon/``.
+
+
+屬性
+----
+
+用戶å¯ä»¥é€šéŽè®€å–和寫入 ``attrs`` 文件ç²å¾—和設置 ``採樣間隔`` 〠``èšé›†é–“éš”`` 〠``æ›´æ–°é–“éš”``
+以åŠç›£æ¸¬ç›®æ¨™å€åŸŸçš„æœ€å°/最大數é‡ã€‚è¦è©³ç´°çž­è§£ç›£æ¸¬å±¬æ€§ï¼Œè«‹åƒè€ƒ `:doc:/mm/damon/design` 。例如,
+下é¢çš„命令將這些值設置爲5msã€100msã€1000msã€10å’Œ1000ï¼Œç„¶å¾Œå†æ¬¡æª¢æŸ¥::
+
+ # cd <debugfs>/damon
+ # echo 5000 100000 1000000 10 1000 > attrs
+ # cat attrs
+ 5000 100000 1000000 10 1000
+
+
+目標ID
+------
+
+一些類型的地å€ç©ºé–“支æŒå¤šå€‹ç›£æ¸¬ç›®æ¨™ã€‚例如,虛擬內存地å€ç©ºé–“的監測å¯ä»¥æœ‰å¤šå€‹é€²ç¨‹ä½œçˆ²ç›£æ¸¬ç›®æ¨™ã€‚用戶
+å¯ä»¥é€šéŽå¯«å…¥ç›®æ¨™çš„相關id值來設置目標,並通éŽè®€å– ``target_ids`` 文件來ç²å¾—ç•¶å‰ç›®æ¨™çš„id。在監
+測虛擬地å€ç©ºé–“的情æ³ä¸‹ï¼Œé€™äº›å€¼æ‡‰è©²æ˜¯ç›£æ¸¬ç›®æ¨™é€²ç¨‹çš„pid。例如,下é¢çš„命令將pid爲42å’Œ4242的進程設
+çˆ²ç›£æ¸¬ç›®æ¨™ï¼Œä¸¦å†æ¬¡æª¢æŸ¥::
+
+ # cd <debugfs>/damon
+ # echo 42 4242 > target_ids
+ # cat target_ids
+ 42 4242
+
+用戶還å¯ä»¥é€šéŽåœ¨æ–‡ä»¶ä¸­å¯«å…¥ä¸€å€‹ç‰¹æ®Šçš„é—œéµå­— "paddr\n" 來監測系統的物ç†å…§å­˜åœ°å€ç©ºé–“。因爲物ç†åœ°
+å€ç©ºé–“ç›£æ¸¬ä¸æ”¯æŒå¤šå€‹ç›®æ¨™ï¼Œè®€å–文件會顯示一個å‡å€¼ï¼Œå³ ``42`` ,如下圖所示::
+
+ # cd <debugfs>/damon
+ # echo paddr > target_ids
+ # cat target_ids
+ 42
+
+請注æ„,設置目標ID並ä¸å•“動監測。
+
+
+åˆå§‹ç›£æ¸¬ç›®æ¨™å€åŸŸ
+----------------
+
+在虛擬地å€ç©ºé–“監測的情æ³ä¸‹ï¼ŒDAMON自動設置和更新監測的目標å€åŸŸï¼Œé€™æ¨£å°±å¯ä»¥è¦†è“‹ç›®æ¨™é€²ç¨‹çš„æ•´å€‹
+內存映射。然而,用戶å¯èƒ½å¸Œæœ›å°‡ç›£æ¸¬å€åŸŸé™åˆ¶åœ¨ç‰¹å®šçš„地å€ç¯„åœå…§ï¼Œå¦‚å †ã€æ£§æˆ–特定的文件映射å€åŸŸã€‚
+或者,一些用戶å¯ä»¥çŸ¥é“他們工作負載的åˆå§‹è¨ªå•模å¼ï¼Œå› æ­¤å¸Œæœ›çˆ²â€œè‡ªé©æ‡‰å€åŸŸèª¿æ•´â€è¨­ç½®æœ€ä½³åˆå§‹å€åŸŸã€‚
+
+相比之下,DAMON在物ç†å…§å­˜ç›£æ¸¬çš„æƒ…æ³ä¸‹ä¸æœƒè‡ªå‹•設置和更新監測目標å€åŸŸã€‚因此,用戶應該自己設置
+監測目標å€åŸŸã€‚
+
+在這種情æ³ä¸‹ï¼Œç”¨æˆ¶å¯ä»¥é€šéŽåœ¨ ``init_regions`` 文件中寫入é©ç•¶çš„值,明確地設置他們想è¦çš„åˆ
+始監測目標å€åŸŸã€‚輸入應該是一個由三個整數組æˆçš„隊列,用空格隔開,代表一個å€åŸŸçš„å½¢å¼å¦‚下::
+
+ <target idx> <start address> <end address>
+
+目標idx應該是 ``target_ids`` 文件中目標的索引,從 ``0`` 開始,å€åŸŸæ‡‰è©²æŒ‰ç…§åœ°å€é †åºå‚³éžã€‚
+例如,下é¢çš„命令將設置幾個地å€ç¯„åœï¼Œ ``1-100`` å’Œ ``100-200`` 作爲pid 42çš„åˆå§‹ç›£æ¸¬ç›®æ¨™
+å€åŸŸï¼Œé€™æ˜¯ ``target_ids`` 中的第一個(索引 ``0`` ),å¦å¤–幾個地å€ç¯„åœï¼Œ ``20-40`` å’Œ
+``50-100`` 作爲pid 4242的地å€ï¼Œé€™æ˜¯ ``target_ids`` 中的第二個(索引 ``1`` )::
+
+ # cd <debugfs>/damon
+ # cat target_ids
+ 42 4242
+ # echo "0 1 100 \
+ 0 100 200 \
+ 1 20 40 \
+ 1 50 100" > init_regions
+
+請注æ„ï¼Œé€™åªæ˜¯è¨­ç½®äº†åˆå§‹çš„監測目標å€åŸŸã€‚在虛擬內存監測的情æ³ä¸‹ï¼ŒDAMON會在一個 ``æ›´æ–°é–“éš”``
+後自動更新å€åŸŸçš„邊界。因此,在這種情æ³ä¸‹ï¼Œå¦‚果用戶ä¸å¸Œæœ›æ›´æ–°çš„話,應該把 ``æ›´æ–°é–“éš”`` 設
+置得足夠大。
+
+
+方案
+----
+
+å°æ–¼é€šå¸¸çš„基於DAMONçš„æ•¸æ“šè¨ªå•æ„ŸçŸ¥çš„內存管ç†å„ªåŒ–ï¼Œç”¨æˆ¶åªæ˜¯å¸Œæœ›ç³»çµ±å°ç‰¹å®šè¨ªå•模å¼çš„å…§å­˜å€åŸŸæ‡‰ç”¨å…§
+å­˜ç®¡ç†æ“作。DAMONå¾žç”¨æˆ¶é‚£è£æŽ¥æ”¶é€™ç¨®å½¢å¼åŒ–çš„æ“作方案,並將這些方案應用到目標進程中。
+
+用戶å¯ä»¥é€šéŽè®€å–和寫入 ``scheme`` debugfs文件來ç²å¾—和設置這些方案。讀å–該文件還å¯ä»¥é¡¯ç¤ºæ¯å€‹
+方案的統計數據。在文件中,æ¯ä¸€å€‹æ–¹æ¡ˆéƒ½æ‡‰è©²åœ¨æ¯ä¸€è¡Œä¸­ä»¥ä¸‹åˆ—å½¢å¼è¡¨ç¤ºå‡ºä¾†::
+
+ <target access pattern> <action> <quota> <watermarks>
+
+ä½ å¯ä»¥é€šéŽç°¡å–®åœ°åœ¨æ–‡ä»¶ä¸­å¯«å…¥ä¸€å€‹ç©ºå­—符串來ç¦ç”¨æ–¹æ¡ˆã€‚
+
+ç›®æ¨™è¨ªå•æ¨¡å¼
+~~~~~~~~~~~~
+
+``<ç›®æ¨™è¨ªå•æ¨¡å¼>`` æ˜¯ç”±ä¸‰å€‹ç¯„åœæ§‹æˆçš„,形å¼å¦‚下::
+
+ min-size max-size min-acc max-acc min-age max-age
+
+具體來說,å€åŸŸå¤§å°çš„字節數( `min-size` å’Œ `max-size` ),訪å•頻率的æ¯èšåˆå€é–“çš„ç›£æ¸¬è¨ªå•æ¬¡
+數( `min-acc` å’Œ `max-acc` ),å€åŸŸå¹´é½¡çš„èšåˆå€é–“數( `min-age` å’Œ `max-age` )都被指定。
+請注æ„ï¼Œé€™äº›ç¯„åœæ˜¯å°é–‰å€é–“。
+
+動作
+~~~~
+
+``<action>`` 是一個é å®šç¾©çš„內存管ç†å‹•作的整數,DAMONå°‡æ‡‰ç”¨æ–¼å…·æœ‰ç›®æ¨™è¨ªå•æ¨¡å¼çš„å€åŸŸã€‚支æŒ
+的數字和它們的å«ç¾©å¦‚下::
+
+ - 0: Call ``madvise()`` for the region with ``MADV_WILLNEED``
+ - 1: Call ``madvise()`` for the region with ``MADV_COLD``
+ - 2: Call ``madvise()`` for the region with ``MADV_PAGEOUT``
+ - 3: Call ``madvise()`` for the region with ``MADV_HUGEPAGE``
+ - 4: Call ``madvise()`` for the region with ``MADV_NOHUGEPAGE``
+ - 5: Do nothing but count the statistics
+
+é…é¡
+~~~~
+
+æ¯å€‹ ``動作`` 的最佳 ``ç›®æ¨™è¨ªå•æ¨¡å¼`` å–æ±ºæ–¼å·¥ä½œè² è¼‰ï¼Œæ‰€ä»¥ä¸å®¹æ˜“找到。更糟糕的是,將æŸå€‹
+å‹•ä½œçš„æ–¹æ¡ˆè¨­ç½®å¾—éŽæ–¼æ¿€é€²æœƒå°Žè‡´åš´é‡çš„開銷。爲了é¿å…這種開銷,用戶å¯ä»¥é€šéŽä¸‹é¢è¡¨æ ¼ä¸­çš„ ``<quota>``
+來é™åˆ¶æ–¹æ¡ˆçš„æ™‚間和大å°é…é¡::
+
+ <ms> <sz> <reset interval> <priority weights>
+
+這使得DAMON在 ``<reset interval>`` 毫秒內,儘é‡åªç”¨ ``<ms>`` æ¯«ç§’çš„æ™‚é–“å° ``目標訪
+啿¨¡å¼`` 的內存å€åŸŸæ‡‰ç”¨å‹•作,並在 ``<reset interval>`` å…§åªå°æœ€å¤š<sz>字節的內存å€åŸŸæ‡‰
+用動作。將 ``<ms>`` å’Œ ``<sz>`` 都設置爲零,å¯ä»¥ç¦ç”¨é…é¡é™åˆ¶ã€‚
+
+ç•¶é è¨ˆè¶…éŽé…é¡é™åˆ¶æ™‚,DAMON會根據 ``ç›®æ¨™è¨ªå•æ¨¡å¼`` 的大å°ã€è¨ªå•頻率和年齡,å°ç™¼ç¾çš„å…§å­˜
+å€åŸŸé€²è¡Œå„ªå…ˆæŽ’åºã€‚爲了實ç¾å€‹æ€§åŒ–的優先級,用戶å¯ä»¥åœ¨ ``<優先級權é‡>`` 中設置這三個屬性的
+權é‡ï¼Œå…·é«”å½¢å¼å¦‚下::
+
+ <size weight> <access frequency weight> <age weight>
+
+æ°´ä½
+~~~~
+
+æœ‰äº›æ–¹æ¡ˆéœ€è¦æ ¹æ“šç³»çµ±ç‰¹å®šæŒ‡æ¨™çš„ç•¶å‰å€¼ä¾†é‹è¡Œï¼Œå¦‚è‡ªç”±å…§å­˜æ¯”çŽ‡ã€‚å°æ–¼é€™ç¨®æƒ…æ³ï¼Œç”¨æˆ¶å¯ä»¥çˆ²è©²æ¢
+件指定水ä½ã€‚::
+
+ <metric> <check interval> <high mark> <middle mark> <low mark>
+
+``<metric>`` 是一個é å®šç¾©çš„æ•´æ•¸ï¼Œç”¨æ–¼è¦æª¢æŸ¥çš„度é‡ã€‚支æŒçš„æ•¸å­—和它們的å«ç¾©å¦‚下。
+
+ - 0: 忽視水ä½
+ - 1: 系統空閒內存率 (åƒåˆ†æ¯”)
+
+æ¯éš” ``<檢查間隔>`` 微秒檢查一次公制的值。
+
+如果該值高於 ``<高標>`` 或低於 ``<低標>`` ,該方案被åœç”¨ã€‚如果該值低於 ``<中標>`` ,
+該方案將被激活。
+
+統計數據
+~~~~~~~~
+
+它還統計æ¯å€‹æ–¹æ¡ˆè¢«å˜—試應用的å€åŸŸçš„總數é‡å’Œå­—節數,æ¯å€‹æ–¹æ¡ˆè¢«æˆåŠŸæ‡‰ç”¨çš„å€åŸŸçš„兩個數é‡ï¼Œä»¥
+åŠè¶…éŽé…é¡é™åˆ¶çš„總數é‡ã€‚這些統計數據å¯ç”¨æ–¼åœ¨ç·šåˆ†æžæˆ–調整方案。
+
+統計數據å¯ä»¥é€šéŽè®€å–方案文件來顯示。讀å–該文件將顯示你在æ¯ä¸€è¡Œä¸­è¼¸å…¥çš„æ¯å€‹ ``方案`` ,
+統計的五個數字將被加在æ¯ä¸€è¡Œçš„æœ«å°¾ã€‚
+
+例å­
+~~~~
+
+下é¢çš„命令應用了一個方案:â€å¦‚果一個大å°çˆ²[4KiB, 8KiB]的內存å€åŸŸåœ¨[10, 20]çš„èšåˆæ™‚é–“
+間隔內顯示出æ¯ä¸€å€‹èšåˆæ™‚é–“é–“éš”[0, 5]的訪å•é‡ï¼Œè«‹åˆ†é å‡ºè©²å€åŸŸã€‚å°æ–¼åˆ†é ï¼Œæ¯ç§’最多隻能使
+用10ms,而且æ¯ç§’分é ä¸èƒ½è¶…éŽ1GiB。在這一é™åˆ¶ä¸‹ï¼Œé¦–先分é å‡ºå…·æœ‰è¼ƒé•·å¹´é½¡çš„å…§å­˜å€åŸŸã€‚å¦å¤–,
+æ¯5ç§’é˜æª¢æŸ¥ä¸€æ¬¡ç³»çµ±çš„å¯ç”¨å…§å­˜çŽ‡ï¼Œç•¶å¯ç”¨å…§å­˜çŽ‡ä½Žæ–¼50%時開始監測和分é ï¼Œä½†å¦‚æžœå¯ç”¨å…§å­˜çއ
+大於60%,或低於30%ï¼Œå‰‡åœæ­¢ç›£æ¸¬â€œ::
+
+ # cd <debugfs>/damon
+ # scheme="4096 8192 0 5 10 20 2" # target access pattern and action
+ # scheme+=" 10 $((1024*1024*1024)) 1000" # quotas
+ # scheme+=" 0 0 100" # prioritization weights
+ # scheme+=" 1 5000000 600 500 300" # watermarks
+ # echo "$scheme" > schemes
+
+
+開關
+----
+
+除éžä½ æ˜Žç¢ºåœ°å•“動監測,å¦å‰‡å¦‚ä¸Šæ‰€è¿°çš„æ–‡ä»¶è¨­ç½®ä¸æœƒç”¢ç”Ÿæ•ˆæžœã€‚ä½ å¯ä»¥é€šéŽå¯«å…¥å’Œè®€å– ``monitor_on``
+文件來啓動ã€åœæ­¢å’Œæª¢æŸ¥ç›£æ¸¬çš„ç•¶å‰ç‹€æ…‹ã€‚寫入 ``on`` 該文件å¯ä»¥å•“å‹•å°æœ‰å±¬æ€§çš„目標的監測。寫入
+``off`` è©²æ–‡ä»¶å‰‡åœæ­¢é€™äº›ç›®æ¨™ã€‚如果æ¯å€‹ç›®æ¨™é€²ç¨‹è¢«çµ‚止,DAMONä¹Ÿæœƒåœæ­¢ã€‚下é¢çš„示例命令開啓ã€é—œ
+閉和檢查DAMON的狀態::
+
+ # cd <debugfs>/damon
+ # echo on > monitor_on
+ # echo off > monitor_on
+ # cat monitor_on
+ off
+
+請注æ„,當監測開啓時,你ä¸èƒ½å¯«åˆ°ä¸Šè¿°çš„debugfs文件。如果你在DAMONé‹è¡Œæ™‚寫到這些文件,將會返
+回一個錯誤代碼,如 ``-EBUSY`` 。
+
+
+監測線程PID
+-----------
+
+DAMON通éŽä¸€å€‹å«åškdamond的內核線程來進行請求監測。你å¯ä»¥é€šéŽè®€å– ``kdamond_pid`` 文件ç²
+得該線程的 ``pid`` 。當監測被 ``關閉`` 時,讀å–è©²æ–‡ä»¶ä¸æœƒè¿”回任何信æ¯::
+
+ # cd <debugfs>/damon
+ # cat monitor_on
+ off
+ # cat kdamond_pid
+ none
+ # echo on > monitor_on
+ # cat kdamond_pid
+ 18594
+
+
+使用多個監測線程
+----------------
+
+æ¯å€‹ç›£æ¸¬ä¸Šä¸‹æ–‡éƒ½æœƒå‰µå»ºä¸€å€‹ ``kdamond`` 線程。你å¯ä»¥ä½¿ç”¨ ``mk_contexts`` å’Œ ``rm_contexts``
+文件爲多個 ``kdamond`` 需è¦çš„用例創建和刪除監測上下文。
+
+將新上下文的å稱寫入 ``mk_contexts`` 文件,在 ``DAMON debugfs`` 目錄上創建一個該å稱的目錄。
+該目錄將有該上下文的 ``DAMON debugfs`` 文件::
+
+ # cd <debugfs>/damon
+ # ls foo
+ # ls: cannot access 'foo': No such file or directory
+ # echo foo > mk_contexts
+ # ls foo
+ # attrs init_regions kdamond_pid schemes target_ids
+
+如果ä¸å†éœ€è¦ä¸Šä¸‹æ–‡ï¼Œä½ å¯ä»¥é€šéŽæŠŠä¸Šä¸‹æ–‡çš„å字放到 ``rm_contexts`` 文件中來刪除它和相應的目錄::
+
+ # echo foo > rm_contexts
+ # ls foo
+ # ls: cannot access 'foo': No such file or directory
+
+注æ„, ``mk_contexts`` 〠``rm_contexts`` å’Œ ``monitor_on`` 文件åªåœ¨æ ¹ç›®éŒ„下。
+
+
+ç›£æ¸¬çµæžœçš„監測點
+================
+
+DAMON通éŽä¸€å€‹tracepoint ``damon:damon_aggregated`` æä¾›ç›£æ¸¬çµæžœ. 當監測開啓時,你å¯
+以記錄追蹤點事件,並使用追蹤點支æŒå·¥å…·å¦‚perfé¡¯ç¤ºçµæžœã€‚比如說::
+
+ # echo on > monitor_on
+ # perf record -e damon:damon_aggregated &
+ # sleep 5
+ # kill 9 $(pidof perf)
+ # echo off > monitor_on
+ # perf script
+
diff --git a/Documentation/translations/zh_TW/admin-guide/mm/index.rst b/Documentation/translations/zh_TW/admin-guide/mm/index.rst
new file mode 100644
index 000000000000..0b04d925b68c
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/mm/index.rst
@@ -0,0 +1,50 @@
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/mm/index.rst
+
+:翻譯:
+
+ å¾é‘« xu xin <xu.xin16@zte.com.cn>
+
+
+========
+內存管ç†
+========
+
+Linux內存管ç†å­ç³»çµ±ï¼Œé¡§åæ€ç¾©ï¼Œæ˜¯è² è²¬ç³»çµ±ä¸­çš„內存管ç†ã€‚它包括了虛擬內存與請求
+分é çš„實ç¾ï¼Œå…§æ ¸å…§éƒ¨çµæ§‹å’Œç”¨æˆ¶ç©ºé–“程åºçš„內存分é…ã€å°‡æ–‡ä»¶æ˜ å°„到進程地å€ç©ºé–“以
+åŠè¨±å¤šå…¶ä»–很酷的事情。
+
+Linuxå…§å­˜ç®¡ç†æ˜¯ä¸€å€‹å…·æœ‰è¨±å¤šå¯é…置設置的複雜系統, 且這些設置中的大多數都å¯ä»¥é€š
+éŽ ``/proc`` 文件系統ç²å¾—,並且å¯ä»¥ä½¿ç”¨ ``sysctl`` 進行查詢和調整。這些API接
+å£è¢«æè¿°åœ¨Documentation/admin-guide/sysctl/vm.rst文件和 `man 5 proc`_ 中。
+
+.. _man 5 proc: http://man7.org/linux/man-pages/man5/proc.5.html
+
+Linuxå…§å­˜ç®¡ç†æœ‰å®ƒè‡ªå·±çš„術語,如果你還ä¸ç†Ÿæ‚‰å®ƒï¼Œè«‹è€ƒæ…®é–±è®€ä¸‹é¢åƒè€ƒï¼š
+Documentation/admin-guide/mm/concepts.rst.
+
+在此目錄下,我們詳細æè¿°çž­å¦‚何與Linux內存管ç†ä¸­çš„å„種機制交互。
+
+.. toctree::
+ :maxdepth: 1
+
+ damon/index
+ ksm
+
+Todolist:
+* concepts
+* cma_debugfs
+* hugetlbpage
+* idle_page_tracking
+* memory-hotplug
+* nommu-mmap
+* numa_memory_policy
+* numaperf
+* pagemap
+* soft-dirty
+* swap_numa
+* transhuge
+* userfaultfd
+* zswap
+
diff --git a/Documentation/translations/zh_TW/admin-guide/mm/ksm.rst b/Documentation/translations/zh_TW/admin-guide/mm/ksm.rst
new file mode 100644
index 000000000000..1b4944b3cf61
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/mm/ksm.rst
@@ -0,0 +1,199 @@
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/mm/ksm.rst
+
+:翻譯:
+
+ å¾é‘« xu xin <xu.xin16@zte.com.cn>
+
+
+============
+å…§æ ¸åŒé åˆä½µ
+============
+
+
+概述
+====
+
+KSM是一種能節çœå…§å­˜çš„æ•¸æ“šåŽ»é‡åŠŸèƒ½ï¼Œç”±CONFIG_KSM=y啓用,並在2.6.32版本時被添
+加到Linux內核。詳見 ``mm/ksm.c`` 的實ç¾ï¼Œä»¥åŠhttp://lwn.net/Articles/306704
+å’Œhttps://lwn.net/Articles/330589
+
+KSM最åˆç›®çš„æ˜¯çˆ²äº†èˆ‡KVM(å³è‘—å的內核共享內存)一起使用而開發的,通éŽå…±äº«è™›æ“¬æ©Ÿ
+之間的公共數據,將更多虛擬機放入物ç†å…§å­˜ã€‚ä½†å®ƒå°æ–¼ä»»ä½•會生æˆå¤šå€‹ç›¸åŒæ•¸æ“šå¯¦ä¾‹çš„
+應用程åºéƒ½æ˜¯å¾ˆæœ‰ç”¨çš„。
+
+KSM的守護進程ksmd會定期掃æé‚£äº›å·²è¨»å†Šçš„用戶內存å€åŸŸï¼ŒæŸ¥æ‰¾å…§å®¹ç›¸åŒçš„é é¢ï¼Œé€™äº›
+é é¢å¯ä»¥è¢«å–®å€‹å¯«ä¿è­·é é¢æ›¿æ›ï¼ˆå¦‚æžœé€²ç¨‹ä»¥å¾Œæƒ³è¦æ›´æ–°å…¶å…§å®¹ï¼Œå°‡è‡ªå‹•複製)。使用:
+引用:`sysfs intraface <ksm_sysfs>` 接å£ä¾†é…ç½®KSM守護程åºåœ¨å–®å€‹éŽç¨‹ä¸­æ‰€æŽƒæçš„é 
+數以åŠå…©å€‹éŽç¨‹ä¹‹é–“的間隔時間。
+
+KSMåªåˆä¸¦åŒ¿åï¼ˆç§æœ‰ï¼‰é é¢ï¼Œå¾žä¸åˆä¸¦é ç·©å­˜ï¼ˆæ–‡ä»¶ï¼‰é é¢ã€‚KSMçš„åˆä½µé é¢æœ€åˆåªèƒ½è¢«
+鎖定在內核內存中,但ç¾åœ¨å¯ä»¥å°±åƒå…¶ä»–用戶é é¢ä¸€æ¨£è¢«æ›å‡ºï¼ˆä½†ç•¶å®ƒå€‘被交æ›å›žä¾†æ™‚å…±
+享會被破壞: ksmdå¿…é ˆé‡æ–°ç™¼ç¾å®ƒå€‘çš„èº«ä»½ä¸¦å†æ¬¡åˆä½µï¼‰ã€‚
+
+以madvise控制KSM
+================
+
+KSM僅在特定的地å€ç©ºé–“å€åŸŸæ™‚é‹è¡Œï¼Œå³æ‡‰ç”¨ç¨‹åºé€šéŽä½¿ç”¨å¦‚下所示的madvise(2)系統調
+用來請求æŸå¡Šåœ°å€æˆçˆ²å¯èƒ½çš„åˆä½µå€™é¸è€…的地å€ç©ºé–“::
+
+ int madvise(addr, length, MADV_MERGEABLE)
+
+應用程åºç•¶ç„¶ä¹Ÿå¯ä»¥é€šéŽèª¿ç”¨::
+
+ int madvise(addr, length, MADV_UNMERGEABLE)
+
+來喿¶ˆè©²è«‹æ±‚,並æ¢å¾©çˆ²éžå…±äº«é é¢ï¼šæ­¤æ™‚KSM將去除åˆä½µåœ¨è©²ç¯„åœå…§çš„任何åˆä½µé ã€‚注æ„:
+這個去除åˆä½µçš„調用å¯èƒ½çªç„¶éœ€è¦çš„å…§å­˜é‡è¶…éŽå¯¦éš›å¯ç”¨çš„å…§å­˜é‡-那麼å¯èƒ½æœƒå‡ºç¾EAGAIN
+失敗,但更å¯èƒ½æœƒå–šé†’OOM killer。
+
+如果KSM未被é…置到正在é‹è¡Œçš„內核中,則madvise MADV_MERGEABLE å’Œ MADV_UNMERGEABLE
+çš„èª¿ç”¨åªæœƒä»¥EINVAL 失敗。如果正在é‹è¡Œçš„內核是用CONFIG_KSM=yæ–¹å¼æ§‹å»ºçš„,那麼這些
+調用通常會æˆåŠŸï¼šå³ä½¿KSM守護程åºç•¶å‰æ²’有é‹è¡Œï¼ŒMADV_MERGEABLE ä»ç„¶æœƒåœ¨KSM守護程åº
+啓動時註冊範åœï¼Œå³ä½¿è©²ç¯„åœä¸èƒ½åŒ…å«KSM實際å¯ä»¥åˆä½µçš„任何é é¢ï¼Œå³ä½¿MADV_UNMERGEABLE
+應用於從未標記爲MADV_MERGEABLE的範åœã€‚
+
+如果一塊內存å€åŸŸå¿…須被拆分爲至少一個新的MADV_MERGEABLEå€åŸŸæˆ–MADV_UNMERGEABLEå€åŸŸï¼Œ
+ç•¶è©²é€²ç¨‹å°‡è¶…éŽ ``vm.max_map_count`` 的設定,則madviseå¯èƒ½è¿”回ENOMEM。(請åƒé–±æ–‡æª”
+Documentation/admin-guide/sysctl/vm.rst)。
+
+與其他madvise調用一樣,它們在用戶地å€ç©ºé–“的映射å€åŸŸä¸Šä½¿ç”¨ï¼šå¦‚果指定的範åœåŒ…嫿œª
+映射的間隙(儘管在中間的映射å€åŸŸå·¥ä½œï¼‰ï¼Œå®ƒå€‘將報告ENOMEM,如果沒有足夠的內存用於
+å…§éƒ¨çµæ§‹ï¼Œå‰‡å¯èƒ½æœƒå› EAGAIN而失敗。
+
+KSM守護進程sysfs接å£
+====================
+
+KSM守護進程å¯ä»¥ç”±``/sys/kernel/mm/ksm/`` 中的sysfs文件控制,所有人都å¯ä»¥è®€å–,但
+åªèƒ½ç”±rootç”¨æˆ¶å¯«å…¥ã€‚å„æŽ¥å£è§£é‡‹å¦‚下:
+
+
+pages_to_scan
+ ksmd進程進入ç¡çœ å‰è¦æŽƒæçš„é æ•¸ã€‚
+ 例如, ``echo 100 > /sys/kernel/mm/ksm/pages_to_scan``
+
+ 默èªå€¼ï¼š100ï¼ˆè©²å€¼è¢«é¸æ“‡ç”¨æ–¼æ¼”示目的)
+
+sleep_millisecs
+ ksmd在下次掃æå‰æ‡‰ä¼‘眠多少毫秒
+ 例如, ``echo 20 > /sys/kernel/mm/ksm/sleep_millisecs``
+
+ 默èªå€¼ï¼š20ï¼ˆè©²å€¼è¢«é¸æ“‡ç”¨æ–¼æ¼”示目的)
+
+merge_across_nodes
+ 指定是å¦å¯ä»¥åˆä½µä¾†è‡ªä¸åŒNUMA節點的é é¢ã€‚當設置爲0時,ksm僅åˆä½µåœ¨ç‰©ç†ä¸Šä½
+ æ–¼åŒä¸€NUMA節點的內存å€åŸŸä¸­çš„é é¢ã€‚這é™ä½Žäº†è¨ªå•共享é é¢çš„å»¶é²ã€‚在有明顯的
+ NUMAè·é›¢ä¸Šï¼Œå…·æœ‰æ›´å¤šç¯€é»žçš„系統å¯èƒ½å—益於設置該值爲0時的更低延é²ã€‚è€Œå°æ–¼
+ 需è¦å°å…§å­˜ä½¿ç”¨é‡æœ€å°åŒ–的較å°ç³»çµ±ä¾†èªªï¼Œè¨­ç½®è©²å€¼çˆ²1(默èªè¨­ç½®ï¼‰å‰‡å¯èƒ½æœƒå—
+ 益於更大共享é é¢ã€‚在決定使用哪種設置之å‰ï¼Œæ‚¨å¯èƒ½å¸Œæœ›æ¯”較系統在æ¯ç¨®è¨­ç½®ä¸‹
+ 的性能。 ``merge_across_nodes`` 僅當系統中沒有ksm共享é é¢æ™‚,æ‰èƒ½è¢«æ›´æ”¹è¨­
+ 置:首先將接å£`run` 設置爲2從而å°é é€²è¡ŒåŽ»åˆä½µï¼Œç„¶å¾Œåœ¨ä¿®æ”¹
+ ``merge_across_nodes`` 後å†å°‡â€˜run’åˆè¨­ç½®çˆ²1ï¼Œä»¥æ ¹æ“šæ–°è¨­ç½®ä¾†é‡æ–°åˆä½µã€‚
+
+ 默èªå€¼ï¼š1(如早期的發佈版本一樣åˆä½µè·¨ç«™é»žï¼‰
+
+run
+ * 設置爲0å¯åœæ­¢ksmdé‹è¡Œï¼Œä½†ä¿ç•™åˆä½µé é¢ï¼Œ
+ * 設置爲1å¯é‹è¡Œksmd,例如, ``echo 1 > /sys/kernel/mm/ksm/run`` ,
+ * 設置爲2å¯åœæ­¢ksmdé‹è¡Œï¼Œä¸¦ä¸”å°æ‰€æœ‰ç›®å‰å·²åˆä½µçš„é é€²è¡ŒåŽ»åˆä½µï¼Œä½†ä¿ç•™å¯åˆä½µ
+ å€åŸŸä»¥ä¾›ä¸‹æ¬¡é‹è¡Œã€‚
+
+ 默èªå€¼ï¼š0(必須設置爲1æ‰èƒ½æ¿€æ´»KSM,除éžç¦ç”¨äº†CONFIG_SYSFS)
+
+use_zero_pages
+ æŒ‡å®šæ˜¯å¦æ‡‰ç•¶ç‰¹æ®Šè™•ç†ç©ºé ï¼ˆå³é‚£äº›åƒ…å«zero的已分é…é ï¼‰ã€‚當該值設置爲1時,
+ 空é èˆ‡å…§æ ¸é›¶é åˆä½µï¼Œè€Œä¸æ˜¯åƒé€šå¸¸æƒ…æ³ä¸‹é‚£æ¨£ç©ºé è‡ªèº«å½¼æ­¤åˆä½µã€‚這å¯ä»¥æ ¹æ“š
+ 工作負載的ä¸åŒï¼Œåœ¨å…·æœ‰ç€è‰²é›¶é çš„æž¶æ§‹ä¸Šå¯ä»¥æé«˜æ€§èƒ½ã€‚啓用此設置時應å°å¿ƒï¼Œ
+ 因爲它å¯èƒ½æœƒé™ä½ŽæŸäº›å·¥ä½œè² è¼‰çš„KSM性能,比如,當待åˆä½µçš„候é¸é é¢çš„æ ¡é©—å’Œ
+ 與空é é¢çš„æ ¡é©—å’Œæ°å¥½åŒ¹é…的時候。此設置å¯éš¨æ™‚更改,僅å°é‚£äº›æ›´æ”¹å¾Œå†åˆä½µ
+ çš„é é¢æœ‰æ•ˆã€‚
+
+ 默èªå€¼ï¼š0ï¼ˆå¦‚åŒæ—©æœŸç‰ˆæœ¬çš„KSM正常表ç¾ï¼‰
+
+max_page_sharing
+ 單個KSMé é¢å…許的最大共享站點數。這將強制執行é‡è¤‡æ•¸æ“šæ¶ˆé™¤é™åˆ¶ï¼Œä»¥é¿å…涉
+ åŠé歷共享KSMé é¢çš„虛擬映射的虛擬內存æ“作的高延é²ã€‚最å°å€¼çˆ²2,因爲新創
+ 建的KSMé é¢å°‡è‡³å°‘有兩個共享者。該值越高,KSMåˆä½µå…§å­˜çš„速度越快,去é‡
+ å› å­ä¹Ÿè¶Šé«˜ï¼Œä½†æ˜¯å°æ–¼ä»»ä½•給定的KSMé é¢ï¼Œè™›æ“¬æ˜ å°„的最壞情æ³é歷的速度也會
+ è¶Šæ…¢ã€‚æ¸›æ…¢äº†é€™ç¨®éæ­·é€Ÿåº¦å°±æ„味ç€åœ¨äº¤æ›ã€å£“縮ã€NUMA平衡和é é¢é·ç§»æœŸé–“,
+ æŸäº›è™›æ“¬å…§å­˜æ“作將有更高的延é²ï¼Œå¾žè€Œé™ä½Žé€™äº›è™›æ“¬å…§å­˜æ“作調用者的響應能力。
+ å…¶ä»–ä»»å‹™å¦‚æžœä¸æ¶‰åŠåŸ·è¡Œè™›æ“¬æ˜ å°„éæ­·çš„VMæ“作,其任務調度延é²ä¸å—æ­¤åƒæ•¸çš„å½±
+ éŸ¿ï¼Œå› çˆ²é€™äº›éæ­·æœ¬èº«æ˜¯èª¿åº¦å‹å¥½çš„。
+
+stable_node_chains_prune_millisecs
+ 指定KSM檢查特定é é¢çš„元數據的頻率(å³é‚£äº›é”åˆ°éŽæ™‚ä¿¡æ¯æ•¸æ“šåŽ»é‡é™åˆ¶æ¨™æº–çš„
+ é é¢ï¼‰å–®ä½æ˜¯æ¯«ç§’。較å°çš„æ¯«ç§’值將以更低的延é²ä¾†é‡‹æ”¾KSM元數據,但它們將使
+ ksmdåœ¨æŽƒææœŸé–“使用更多CPU。如果還沒有一個KSMé é¢é”到 ``max_page_sharing``
+ 標準,那就沒有什麼用。
+
+KSM與MADV_MERGEABLEçš„å·¥ä½œæœ‰æ•ˆæ€§é«”ç¾æ–¼ ``/sys/kernel/mm/ksm/`` 路徑下的接å£ï¼š
+
+pages_shared
+ è¡¨ç¤ºå¤šå°‘å…±äº«é æ­£åœ¨è¢«ä½¿ç”¨
+pages_sharing
+ 表示還有多少站點正在共享這些共享é ï¼Œå³ç¯€çœäº†å¤šå°‘
+pages_unshared
+ è¡¨ç¤ºæœ‰å¤šå°‘é æ˜¯å”¯ä¸€çš„,但被å覆檢查以進行åˆä½µ
+pages_volatile
+ 表示有多少é å› è®ŠåŒ–太快而無法放在tree中
+full_scans
+ 表示所有å¯åˆä½µå€åŸŸå·²æŽƒæå¤šå°‘次
+stable_node_chains
+ é”到 ``max_page_sharing`` é™åˆ¶çš„KSMé æ•¸
+stable_node_dups
+ é‡è¤‡çš„KSMé æ•¸
+
+比值 ``pages_sharing/pages_shared`` 的最大值å—é™åˆ¶æ–¼ ``max_page_sharing``
+çš„è¨­å®šã€‚è¦æƒ³å¢žåŠ è©²æ¯”å€¼ï¼Œå‰‡ç›¸æ‡‰åœ°è¦å¢žåŠ  ``max_page_sharing`` 的值。
+
+監測KSM的收益
+=============
+
+KSMå¯ä»¥é€šéŽåˆä½µç›¸åŒçš„é é¢ä¾†ç¯€çœå…§å­˜ï¼Œä½†ä¹Ÿæœƒæ¶ˆè€—é¡å¤–的內存,因爲它需è¦ç”Ÿæˆä¸€äº›rmap_items
+來ä¿å­˜æ¯å€‹æŽƒæé é¢çš„ç°¡è¦rmapä¿¡æ¯ã€‚其中有些é é¢å¯èƒ½æœƒè¢«åˆä½µï¼Œä½†æœ‰äº›é é¢åœ¨è¢«æª¢æŸ¥å¹¾æ¬¡
+後å¯èƒ½ç„¡æ³•被åˆä½µï¼Œé€™äº›éƒ½æ˜¯ç„¡ç›Šçš„內存消耗。
+
+1) 如何確定KSM在全系統範åœå…§æ˜¯ç¯€çœå…§å­˜é‚„æ˜¯æ¶ˆè€—å…§å­˜ï¼Ÿé€™è£æœ‰ä¸€å€‹ç°¡å–®çš„近似計算方法供åƒè€ƒ::
+
+ general_profit =~ pages_sharing * sizeof(page) - (all_rmap_items) *
+ sizeof(rmap_item);
+
+ 其中all_rmap_itemså¯ä»¥é€šéŽå° ``pages_sharing`` 〠``pages_shared`` 〠``pages_unshared``
+ å’Œ ``pages_volatile`` 的求和而輕鬆ç²å¾—。
+
+2) 單一進程中KSM的收益也å¯ä»¥é€šéŽä»¥ä¸‹è¿‘似的計算得到::
+
+ process_profit =~ ksm_merging_pages * sizeof(page) -
+ ksm_rmap_items * sizeof(rmap_item).
+
+ 其中ksm_merging_pages顯示在 ``/proc/<pid>/`` 目錄下,而ksm_rmap_items
+ 顯示在 ``/proc/<pid>/ksm_stat`` 。
+
+從應用的角度來看, ``ksm_rmap_items`` å’Œ ``ksm_merging_pages`` 的高比例æ„
+味ç€ä¸å¥½çš„madvise-applied策略,所以開發者或管ç†å“¡å¿…é ˆé‡æ–°è€ƒæ…®å¦‚何改變madvisç­–
+略。舉個例å­ä¾›åƒè€ƒï¼Œä¸€å€‹é é¢çš„大å°é€šå¸¸æ˜¯4K,而rmap_item的大å°åœ¨32ä½CPU架構上分
+別是32B,在64ä½CPU架構上是64B。所以如果 ``ksm_rmap_items/ksm_merging_pages``
+的比例在64ä½CPU上超éŽ64,或者在32ä½CPU上超éŽ128,那麼應用程åºçš„madvise策略應
+該被放棄,因爲ksm收益大約爲零或負值。
+
+監控KSM事件
+===========
+
+在/proc/vmstat中有一些計數器,å¯ä»¥ç”¨ä¾†ç›£æŽ§KSM事件。KSMå¯èƒ½æœ‰åŠ©æ–¼ç¯€çœå…§å­˜ï¼Œé€™æ˜¯
+一種權衡,因爲它å¯èƒ½æœƒåœ¨KSM COW或複製中的交æ›ä¸Šé­å—å»¶é²ã€‚這些事件å¯ä»¥å¹«åŠ©ç”¨æˆ¶è©•ä¼°
+æ˜¯å¦æˆ–如何使用KSM。例如,如果cow_ksm增加得太快,用戶å¯ä»¥æ¸›å°‘madvise(, , MADV_MERGEABLE)
+的範åœã€‚
+
+cow_ksm
+ åœ¨æ¯æ¬¡KSMé é¢è§¸ç™¼å¯«æ™‚æ‹·è²ï¼ˆCOW)時都會被éžå¢žï¼Œç•¶ç”¨æˆ¶è©¦åœ–寫入KSMé é¢æ™‚,
+ 我們必須åšä¸€å€‹æ‹·è²ã€‚
+
+ksm_swpin_copy
+ 在æ›å…¥æ™‚ï¼Œæ¯æ¬¡KSMé è¢«è¤‡åˆ¶æ™‚都會被éžå¢žã€‚請注æ„,KSMé åœ¨æ›å…¥æ™‚å¯èƒ½æœƒè¢«è¤‡
+ 制,因爲do_swap_page()ä¸èƒ½åšæ‰€æœ‰çš„éŽ–ï¼Œè€Œéœ€è¦é‡çµ„一個跨anon_vmaçš„KSMé ã€‚
+
+--
+Izik Eidus,
+Hugh Dickins, 2009年11月17日。
+
diff --git a/Documentation/translations/zh_TW/admin-guide/reporting-issues.rst b/Documentation/translations/zh_TW/admin-guide/reporting-issues.rst
index ea51342879c0..fe5a5a07d51a 100644
--- a/Documentation/translations/zh_TW/admin-guide/reporting-issues.rst
+++ b/Documentation/translations/zh_TW/admin-guide/reporting-issues.rst
@@ -1,13 +1,6 @@
.. SPDX-License-Identifier: (GPL-2.0+ OR CC-BY-4.0)
-..
- If you want to distribute this text under CC-BY-4.0 only, please use 'The
- Linux kernel developers' for author attribution and link this as source:
- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/Documentation/admin-guide/reporting-issues.rst
-..
- Note: Only the content of this RST file as found in the Linux kernel sources
- is available under CC-BY-4.0, as versions of this text that were processed
- (for example by the kernel's build system) might contain content taken from
- files which use a more restrictive license.
+.. See the bottom of this file for additional redistribution information.
+
.. include:: ../disclaimer-zh_TW.rst
@@ -26,14 +19,16 @@
簡明指å—ï¼ˆäº¦å³ å¤ªé•·ä¸çœ‹ï¼‰
==========================
-您é¢è‡¨çš„æ˜¯å¦çˆ²åŒç³»åˆ—穩定版或長期支æŒå…§æ ¸çš„æ™®é€šå…§æ ¸çš„回歸?是å¦ä»ç„¶å—支æŒï¼Ÿ
+您é¢è‡¨çš„æ˜¯å¦çˆ²åŒç³»åˆ—穩定版或長期支æŒå…§æ ¸çš„æ™®é€šå…§æ ¸çš„迴歸?是å¦ä»ç„¶å—支æŒï¼Ÿ
è«‹æœç´¢ `LKML內核郵件列表 <https://lore.kernel.org/lkml/>`_ å’Œ
`Linux穩定版郵件列表 <https://lore.kernel.org/stable/>`_ 存檔中匹é…的報告並
加入討論。如果找ä¸åˆ°åŒ¹é…的報告,請安è£è©²ç³»åˆ—的最新版本。如果它ä»ç„¶å‡ºç¾å•題,
-報告給穩定版郵件列表(stable@vger.kernel.org)。
+請報告給穩定版郵件列表(stable@vger.kernel.org)並抄é€å›žæ­¸éƒµä»¶åˆ—表
+(regressions@lists.linux.devï¼‰ï¼›ç†æƒ³æƒ…æ³ä¸‹ï¼Œé‚„å¯ä»¥æŠ„é€ç¶­è­·è€…和相關å­ç³»çµ±çš„
+郵件列表。
在所有其他情æ³ä¸‹ï¼Œè«‹å„˜å¯èƒ½çŒœæ¸¬æ˜¯å“ªå€‹å…§æ ¸éƒ¨åˆ†å°Žè‡´äº†å•題。查看MAINTAINERS文件,
-了解開發人員希望如何得知å•題,大多數情æ³ä¸‹ï¼Œå ±å‘Šå•題都是通éŽé›»å­éƒµä»¶å’ŒæŠ„é€
+瞭解開發人員希望如何得知å•題,大多數情æ³ä¸‹ï¼Œå ±å‘Šå•題都是通éŽé›»å­éƒµä»¶å’ŒæŠ„é€
相關郵件列表進行的。檢查報告目的地的存檔中是å¦å·²æœ‰åŒ¹é…的報告;也請æœç´¢
`LKML <https://lore.kernel.org/lkml/>`_ 和網絡。如果找ä¸åˆ°å¯åŠ å…¥çš„è¨Žè«–ï¼Œè«‹
å®‰è£ `最新的主線內核 <https://kernel.org/>`_ 。如果ä»å­˜åœ¨å•題,請發é€å ±å‘Šã€‚
@@ -45,21 +40,22 @@
**通用æé†’** :當安è£å’Œæ¸¬è©¦ä¸Šè¿°å…§æ ¸æ™‚,請確ä¿å®ƒæ˜¯æ™®é€šçš„(å³ï¼šæ²’有補ä¸ï¼Œä¹Ÿæ²’
有使用附加模塊)。還è¦ç¢ºä¿å®ƒæ˜¯åœ¨ä¸€å€‹æ­£å¸¸çš„環境中構建和é‹è¡Œï¼Œä¸¦ä¸”在å•題發生
-之剿²’有被汙染(tainted)。
+之剿²’有被污染(tainted)。
-åœ¨ç·¨å¯«å ±å‘Šæ™‚ï¼Œè¦æ¶µè“‹èˆ‡å•題相關的所有信æ¯ï¼Œå¦‚使用的內核和發行版。在碰見回歸時,
-嘗試給出引入它的更改的æäº¤ID,二分å¯ä»¥æ‰¾åˆ°å®ƒã€‚å¦‚æžœæ‚¨åŒæ™‚é¢è‡¨Linux內核的多個
-å•題,請分別報告æ¯å€‹å•題。
+ç•¶ä½ åŒæ™‚é¢è‡¨Linux內核的多個å•é¡Œæ™‚ï¼Œè«‹åˆ†åˆ¥å ±å‘Šã€‚åœ¨ç·¨å¯«å ±å‘Šæ™‚ï¼Œè¦æ¶µè“‹èˆ‡å•題
+相關的所有信æ¯ï¼Œå¦‚使用的內核和發行版。如果碰見迴歸,請把報告抄é€å›žæ­¸éƒµä»¶åˆ—表
+(regressions@lists.linux.dev)。也請試試用二分法找出æºé ­ï¼›å¦‚æžœæˆåŠŸæ‰¾åˆ°ï¼Œè«‹
+在報告中寫上它的æäº¤ID並抄é€sign-off-byéˆä¸­çš„æ‰€æœ‰äººã€‚
一旦報告發出,請回答任何出ç¾çš„å•題,並儘å¯èƒ½åœ°æä¾›å¹«åŠ©ã€‚é€™åŒ…æ‹¬é€šéŽä¸æ™‚釿–°
-測試新版本並發é€ç‹€æ…‹æ›´æ–°ä¾†æŽ¨å‹•進展。
+測試新版本併發é€ç‹€æ…‹æ›´æ–°ä¾†æŽ¨å‹•進展。
如何å‘內核維護人員報告å•é¡Œçš„é€æ­¥æŒ‡å—
=====================================
-上é¢çš„ç°¡æ˜ŽæŒ‡å—æ¦‚述了如何å‘Linux內核開發人員報告å•é¡Œã€‚å°æ–¼å·²ç¶“熟悉å‘自由和開
-æºè»Ÿé«”(FLOSS)項目報告å•題的人來說,這å¯èƒ½æ˜¯ä»–們所需è¦çš„å…¨éƒ¨å…§å®¹ã€‚å°æ–¼å…¶ä»–
+上é¢çš„ç°¡æ˜ŽæŒ‡å—æ¦‚述瞭如何å‘Linux內核開發人員報告å•é¡Œã€‚å°æ–¼å·²ç¶“熟悉å‘自由和開
+æºè»Ÿä»¶ï¼ˆFLOSS)項目報告å•題的人來說,這å¯èƒ½æ˜¯ä»–們所需è¦çš„å…¨éƒ¨å…§å®¹ã€‚å°æ–¼å…¶ä»–
人,本部分更爲詳細,並一步一步地æè¿°ã€‚爲了便於閱讀,它ä»ç„¶å„˜é‡ç°¡æ½”,並çœç•¥
äº†è¨±å¤šç´°ç¯€ï¼›é€™äº›åœ¨é€æ­¥æŒ‡å—後的åƒè€ƒç« ç¯€ä¸­é€²è¡Œäº†æè¿°ï¼Œè©²ç« ç¯€æ›´è©³ç´°åœ°è§£é‡‹äº†æ¯
個步驟。
@@ -68,16 +64,16 @@
儘早æ„識到看起來åƒLinux內核毛病的å•題å¯èƒ½å¯¦éš›ä¸Šæ˜¯ç”±å…¶ä»–原因引起的。這些步驟
å¯ä»¥ç¢ºä¿ä½ æœ€çµ‚䏿œƒè¦ºå¾—在這一éŽç¨‹ä¸­æŠ•入的時間是浪費:
- * 您是å¦é¢è‡¨ç¡¬é«”或軟體供應商æä¾›çš„Linux內核的å•é¡Œï¼Ÿé‚£éº¼åŸºæœ¬ä¸Šæ‚¨æœ€å¥½åœæ­¢é–±è®€
+ * 您是å¦é¢è‡¨ç¡¬ä»¶æˆ–軟件供應商æä¾›çš„Linux內核的å•é¡Œï¼Ÿé‚£éº¼åŸºæœ¬ä¸Šæ‚¨æœ€å¥½åœæ­¢é–±è®€
æœ¬æ–‡æª”ï¼Œè½‰è€Œå‘æ‚¨çš„供應商報告å•é¡Œï¼Œé™¤éžæ‚¨é¡˜æ„è‡ªå·±å®‰è£æœ€æ–°çš„Linux版本。尋找
和解決å•題往往需è¦å¾Œè€…。
- * 使用您喜愛的網絡æœå°‹å¼•擎å°ç¾æœ‰å ±å‘Šé€²è¡Œç²—ç•¥æœç´¢ï¼›æ­¤å¤–,請檢查
+ * 使用您喜愛的網絡æœç´¢å¼•擎å°ç¾æœ‰å ±å‘Šé€²è¡Œç²—ç•¥æœç´¢ï¼›æ­¤å¤–,請檢查
`Linux內核郵件列表(LKML) <https://lore.kernel.org/lkml/>`_ 的存檔。如果
找到匹é…çš„å ±å‘Šï¼Œè«‹åŠ å…¥è¨Žè«–è€Œä¸æ˜¯ç™¼é€æ–°å ±å‘Šã€‚
- * 看看你正在處ç†çš„å•題是å¦çˆ²å›žæ­¸å•題ã€å®‰å…¨å•題或éžå¸¸åš´é‡çš„å•題:這些都是需
- è¦åœ¨æŽ¥ä¸‹ä¾†çš„一些步驟中特別處ç†çš„「高優先級å•題ã€ã€‚
+ * 看看你正在處ç†çš„å•題是å¦çˆ²è¿´æ­¸å•題ã€å®‰å…¨å•題或éžå¸¸åš´é‡çš„å•題:這些都是需
+ è¦åœ¨æŽ¥ä¸‹ä¾†çš„一些步驟中特別處ç†çš„“高優先級å•題â€ã€‚
* 確ä¿ä¸æ˜¯å…§æ ¸ç’°å¢ƒå°Žè‡´äº†æ‚¨é¢è‡¨çš„å•題。
@@ -86,15 +82,15 @@
* ç¢ºä¿æ‚¨çš„ç³»çµ±ä¸æœƒé€šéŽå‹•態構建é¡å¤–的內核模塊來增強其內核,åƒDKMS這樣的解決
方案å¯èƒ½åœ¨æ‚¨ä¸çŸ¥æƒ…的情æ³ä¸‹å°±åœ¨æœ¬åœ°é€²è¡Œäº†é€™æ¨£çš„工作。
- * ç•¶å•題發生時,檢查您的內核是å¦è¢«ã€Œæ±™æŸ“ã€ï¼Œå› çˆ²ä½¿å…§æ ¸è¨­ç½®é€™å€‹æ¨™èªŒçš„事件å¯èƒ½
+ * ç•¶å•題發生時,檢查您的內核是å¦è¢«â€œæ±¡æŸ“â€ï¼Œå› çˆ²ä½¿å…§æ ¸è¨­ç½®é€™å€‹æ¨™èªŒçš„事件å¯èƒ½
會導致您é¢è‡¨çš„å•題。
* 粗略地寫下如何é‡ç¾é€™å€‹å•é¡Œã€‚å¦‚æžœæ‚¨åŒæ™‚處ç†å¤šå€‹å•題,請爲æ¯å€‹å•題單ç¨å¯«æ³¨
釋,並確ä¿å®ƒå€‘在新啓動的系統上ç¨ç«‹å‡ºç¾ã€‚這是必è¦çš„,因爲æ¯å€‹å•題都需è¦åˆ†
別報告給內核開發人員,除éžå®ƒå€‘åš´é‡ç³¾çºåœ¨ä¸€èµ·ã€‚
- * 如果您正é¢è‡¨ç©©å®šç‰ˆæˆ–長期支æŒç‰ˆæœ¬ç·šçš„回歸(例如從5.10.4更新到5.10.5時出ç¾
- 故障),請查看後文「報告穩定版和長期支æŒå…§æ ¸ç·šçš„回歸ã€å°ç¯€ã€‚
+ * 如果您正é¢è‡¨ç©©å®šç‰ˆæˆ–長期支æŒç‰ˆæœ¬ç·šçš„迴歸(例如從5.10.4更新到5.10.5時出ç¾
+ 故障),請查看後文“報告穩定版和長期支æŒå…§æ ¸ç·šçš„è¿´æ­¸â€å°ç¯€ã€‚
* 定ä½å¯èƒ½å¼•èµ·å•é¡Œçš„é©…å‹•ç¨‹åºæˆ–å…§æ ¸å­ç³»çµ±ã€‚找出其開發人員期望的報告的方å¼å’Œ
ä½ç½®ã€‚注æ„:大多數情æ³ä¸‹ä¸æœƒæ˜¯ bugzilla.kernel.org,因爲å•題通常需è¦é€š
@@ -105,61 +101,62 @@
在完æˆé€™äº›æº–備之後,你將進入主è¦éƒ¨åˆ†ï¼š
- * é™¤éžæ‚¨å·²ç¶“在é‹è¡Œæœ€æ–°çš„「主線ã€Linux內核,å¦å‰‡æœ€å¥½åœ¨å ±å‘Šæµç¨‹å‰å®‰è£å®ƒã€‚在æŸäº›
- 情æ³ä¸‹ï¼Œä½¿ç”¨æœ€æ–°çš„「穩定版ã€Linux進行測試和報告也是å¯ä»¥æŽ¥å—的替代方案;在
+ * é™¤éžæ‚¨å·²ç¶“在é‹è¡Œæœ€æ–°çš„“主線â€Linux內核,å¦å‰‡æœ€å¥½åœ¨å ±å‘Šæµç¨‹å‰å®‰è£å®ƒã€‚在æŸäº›
+ 情æ³ä¸‹ï¼Œä½¿ç”¨æœ€æ–°çš„“穩定版â€Linux進行測試和報告也是å¯ä»¥æŽ¥å—的替代方案;在
åˆä½µçª—壿œŸé–“,這實際上å¯èƒ½æ˜¯æœ€å¥½çš„æ–¹æ³•,但在開發階段最好還是暫åœå¹¾å¤©ã€‚ç„¡è«–
- 你鏿“‡ä»€éº¼ç‰ˆæœ¬ï¼Œæœ€å¥½ä½¿ç”¨ã€Œæ™®é€šã€æ§‹å»ºã€‚忽略這些建議會大大增加您的報告被拒絕
+ 你鏿“‡ä»€éº¼ç‰ˆæœ¬ï¼Œæœ€å¥½ä½¿ç”¨â€œæ™®é€šâ€æ§‹å»ºã€‚忽略這些建議會大大增加您的報告被拒絕
或忽略的風險。
- * ç¢ºä¿æ‚¨å‰›å‰›å®‰è£çš„內核在é‹è¡Œæ™‚䏿œƒã€Œæ±™æŸ“ã€è‡ªå·±ã€‚
+ * ç¢ºä¿æ‚¨å‰›å‰›å®‰è£çš„內核在é‹è¡Œæ™‚䏿œƒâ€œæ±¡æŸ“â€è‡ªå·±ã€‚
* 在您剛剛安è£çš„內核中復ç¾é€™å€‹å•題。如果它沒有出ç¾ï¼Œè«‹æŸ¥çœ‹ä¸‹æ–¹åªç™¼ç”Ÿåœ¨
穩定版和長期支æŒå…§æ ¸çš„å•題的說明。
- * 優化你的筆記:試著找到並寫出最直接的復ç¾å•é¡Œçš„æ–¹æ³•ã€‚ç¢ºä¿æœ€çµ‚çµæžœåŒ…嫿‰€æœ‰
+ * å„ªåŒ–ä½ çš„ç­†è¨˜ï¼šè©¦ç€æ‰¾åˆ°ä¸¦å¯«å‡ºæœ€ç›´æŽ¥çš„復ç¾å•é¡Œçš„æ–¹æ³•ã€‚ç¢ºä¿æœ€çµ‚çµæžœåŒ…嫿‰€æœ‰
é‡è¦çš„ç´°ç¯€ï¼ŒåŒæ™‚讓第一次è½èªªçš„人容易閱讀和ç†è§£ã€‚如果您在此éŽç¨‹ä¸­å­¸åˆ°äº†ä¸€
些æ±è¥¿ï¼Œè«‹è€ƒæ…®å†æ¬¡æœç´¢é—œæ–¼è©²å•é¡Œçš„ç¾æœ‰å ±å‘Šã€‚
- * 如果失敗涉åŠã€Œpanicã€ã€ã€ŒOopsã€ã€ã€Œwarningã€æˆ–「BUGã€ï¼Œè«‹è€ƒæ…®è§£ç¢¼å…§æ ¸æ—¥èªŒä»¥æŸ¥æ‰¾è§¸
+ * 如果失敗涉åŠâ€œpanicâ€ã€â€œOopsâ€ã€â€œwarningâ€æˆ–“BUGâ€ï¼Œè«‹è€ƒæ…®è§£ç¢¼å…§æ ¸æ—¥èªŒä»¥æŸ¥æ‰¾è§¸
發錯誤的代碼行。
- * 如果您的å•題是回歸å•題,請儘å¯èƒ½ç¸®å°å¼•å…¥å•題時的範åœã€‚
+ * 如果您的å•題是迴歸å•題,請儘å¯èƒ½ç¸®å°å¼•å…¥å•題時的範åœã€‚
* 通éŽè©³ç´°æè¿°å•題來開始編寫報告。記得包括以下æ¢ç›®ï¼šæ‚¨çˆ²å¾©ç¾è€Œå®‰è£çš„æœ€æ–°å…§
核版本ã€ä½¿ç”¨çš„Linux發行版以åŠé—œæ–¼å¦‚何復ç¾è©²å•題的說明。如果å¯èƒ½ï¼Œå°‡å…§æ ¸
- 構建é…置(.config)和 ``dmesg`` 的輸出放在網上的æŸå€‹åœ°æ–¹ï¼Œä¸¦é€£çµåˆ°å®ƒã€‚包
+ 構建é…置(.config)和 ``dmesg`` 的輸出放在網上的æŸå€‹åœ°æ–¹ï¼Œä¸¦éˆæŽ¥åˆ°å®ƒã€‚包
嫿ˆ–上傳所有其他å¯èƒ½ç›¸é—œçš„ä¿¡æ¯ï¼Œå¦‚Oops的輸出/截圖或來自 ``lspci`` 的輸出
。一旦你寫完了這個主è¦éƒ¨åˆ†ï¼Œè«‹åœ¨ä¸Šæ–¹æ’入一個正常長度的段è½å¿«é€Ÿæ¦‚è¿°å•題和
影響。å†åœ¨æ­¤ä¹‹ä¸Šæ·»åŠ ä¸€å€‹ç°¡å–®æè¿°å•題的å¥å­ï¼Œä»¥å¾—到人們的閱讀。ç¾åœ¨çµ¦å‡ºä¸€
個更短的æè¿°æ€§æ¨™é¡Œæˆ–主題。然後就å¯ä»¥åƒMAINTAINERSæ–‡ä»¶å‘Šè¨´ä½ çš„é‚£æ¨£ç™¼é€æˆ–
- æäº¤å ±å‘Šäº†ï¼Œé™¤éžä½ åœ¨è™•ç†ä¸€å€‹ã€Œé«˜å„ªå…ˆç´šå•題ã€ï¼šå®ƒå€‘éœ€è¦æŒ‰ç…§ä¸‹é¢ã€Œé«˜å„ªå…ˆç´šå•
- 題的特殊處ç†ã€æ‰€è¿°ç‰¹åˆ¥é—œç…§ã€‚
+ æäº¤å ±å‘Šäº†ï¼Œé™¤éžä½ åœ¨è™•ç†ä¸€å€‹â€œé«˜å„ªå…ˆç´šå•題â€ï¼šå®ƒå€‘éœ€è¦æŒ‰ç…§ä¸‹é¢â€œé«˜å„ªå…ˆç´šå•
+ 題的特殊處ç†â€æ‰€è¿°ç‰¹åˆ¥é—œç…§ã€‚
* ç­‰å¾…åˆ¥äººçš„åæ‡‰ï¼Œç¹¼çºŒæŽ¨é€²äº‹æƒ…,直到你能夠接å—é€™æ¨£æˆ–é‚£æ¨£çš„çµæžœã€‚因此,請公
é–‹å’ŒåŠæ™‚地回應任何詢å•。測試æå‡ºçš„ä¿®å¾©ã€‚ç©æ¥µåœ°æ¸¬è©¦ï¼šè‡³å°‘釿–°æ¸¬è©¦æ¯å€‹æ–°ä¸»
線版本的首個候é¸ç‰ˆæœ¬ï¼ˆRCï¼‰ï¼Œä¸¦å ±å‘Šä½ çš„çµæžœã€‚å¦‚æžœå‡ºç¾æ‹–延,就å‹å¥½åœ°æé†’一
- 下。如果你沒有得到任何幫助或者未能滿æ„,請試著自己幫助自己。
+ 下。如果你沒有得到任何幫助或者未能滿æ„,請試ç€è‡ªå·±å¹«åŠ©è‡ªå·±ã€‚
-報告穩定版和長期支æŒå…§æ ¸ç·šçš„回歸
+報告穩定版和長期支æŒå…§æ ¸ç·šçš„è¿´æ­¸
----------------------------------
-如果您發ç¾äº†ç©©å®šç‰ˆæˆ–長期支æŒå…§æ ¸ç‰ˆæœ¬ç·šä¸­çš„回歸å•題並按上述æµç¨‹è·³åˆ°é€™è£¡ï¼Œé‚£éº¼
+如果您發ç¾äº†ç©©å®šç‰ˆæˆ–長期支æŒå…§æ ¸ç‰ˆæœ¬ç·šä¸­çš„è¿´æ­¸å•題並按上述æµç¨‹è·³åˆ°é€™è£ï¼Œé‚£éº¼
請閱讀本å°ç¯€ã€‚å³ä¾‹å¦‚您在從5.10.4更新到5.10.5時出ç¾äº†å•題(從5.9.15到5.10.5則
-䏿˜¯ï¼‰ã€‚開發人員希望儘快修復此類回歸,因此有一個簡化æµç¨‹ä¾†å ±å‘Šå®ƒå€‘:
+䏿˜¯ï¼‰ã€‚開發人員希望儘快修復此類迴歸,因此有一個簡化æµç¨‹ä¾†å ±å‘Šå®ƒå€‘:
* 檢查內核開發人員是å¦ä»ç„¶ç¶­è­·ä½ é—œå¿ƒçš„Linux內核版本線:去 `kernel.org 的首é 
- <https://kernel.org/>`_ ï¼Œç¢ºä¿æ­¤ç‰¹å®šç‰ˆæœ¬ç·šçš„æœ€æ–°ç‰ˆæ²’有「[EOL]ã€æ¨™è¨˜ã€‚
+ <https://kernel.org/>`_ ï¼Œç¢ºä¿æ­¤ç‰¹å®šç‰ˆæœ¬ç·šçš„æœ€æ–°ç‰ˆæ²’有“[EOL]â€æ¨™è¨˜ã€‚
* 檢查 `Linux穩定版郵件列表 <https://lore.kernel.org/stable/>`_ ä¸­çš„ç¾æœ‰å ±å‘Šã€‚
- * å¾žç‰¹å®šçš„ç‰ˆæœ¬ç·šå®‰è£æœ€æ–°ç‰ˆæœ¬ä½œçˆ²ç´”淨內核。確ä¿é€™å€‹å…§æ ¸æ²’有被汙染,並且ä»ç„¶
- 存在å•題,因爲å•題å¯èƒ½å·²ç¶“在那裡被修復了。如果您第一次發ç¾ä¾›æ‡‰å•†å…§æ ¸çš„å•題,
+ * å¾žç‰¹å®šçš„ç‰ˆæœ¬ç·šå®‰è£æœ€æ–°ç‰ˆæœ¬ä½œçˆ²ç´”淨內核。確ä¿é€™å€‹å…§æ ¸æ²’有被污染,並且ä»ç„¶
+ 存在å•題,因爲å•題å¯èƒ½å·²ç¶“在那è£è¢«ä¿®å¾©äº†ã€‚如果您第一次發ç¾ä¾›æ‡‰å•†å…§æ ¸çš„å•題,
請檢查已知最新版本的普通構建是å¦å¯ä»¥æ­£å¸¸é‹è¡Œã€‚
- * å‘Linux穩定版郵件列表發é€ä¸€å€‹ç°¡çŸ­çš„å•題報告(stable@vger.kernel.org)。大致
- æè¿°å•題,並解釋如何復ç¾ã€‚講清楚首個出ç¾å•題的版本和最後一個工作正常的版本。
- 然後等待進一步的指示。
+ * å‘Linux穩定版郵件列表發é€ä¸€å€‹ç°¡çŸ­çš„å•題報告(stable@vger.kernel.org)並抄é€
+ Linux迴歸郵件列表(regressions@lists.linux.dev);如果你懷疑是由æŸå­ç³»çµ±
+ 引起的,請抄é€å…¶ç¶­è­·äººå“¡å’Œå­ç³»çµ±éƒµä»¶åˆ—表。大致æè¿°å•題,並解釋如何復ç¾ã€‚
+ 講清楚首個出ç¾å•題的版本和最後一個工作正常的版本。然後等待進一步的指示。
下é¢çš„åƒè€ƒç« ç¯€éƒ¨åˆ†è©³ç´°è§£é‡‹äº†é€™äº›æ­¥é©Ÿä¸­çš„æ¯ä¸€æ­¥ã€‚
@@ -167,14 +164,14 @@
報告åªç™¼ç”Ÿåœ¨è¼ƒèˆŠå…§æ ¸ç‰ˆæœ¬ç·šçš„å•題
----------------------------------
-若您嘗試了上述的最新主線內核,但未能在那裡復ç¾å•題,那麼本å°ç¯€é©ç”¨æ–¼æ‚¨ï¼›ä»¥ä¸‹
+若您嘗試了上述的最新主線內核,但未能在那è£å¾©ç¾å•題,那麼本å°ç¯€é©ç”¨æ–¼æ‚¨ï¼›ä»¥ä¸‹
æµç¨‹æœ‰åŠ©æ–¼ä½¿å•題在ä»ç„¶æ”¯æŒçš„穩定版或長期支æŒç‰ˆæœ¬ç·šï¼Œæˆ–者定期基於最新穩定版或
長期支æŒå…§æ ¸çš„供應商內核中得到修復。如果是這種情æ³ï¼Œè«‹åŸ·è¡Œä»¥ä¸‹æ­¥é©Ÿï¼š
* è«‹åšå¥½æº–備,接下來的幾個步驟å¯èƒ½ç„¡æ³•在舊版本中解決å•題:修復å¯èƒ½å¤ªå¤§æˆ–太
- 冒險,無法移æ¤åˆ°é‚£è£¡ã€‚
+ 冒險,無法移æ¤åˆ°é‚£è£ã€‚
- * 執行å‰ç¯€ã€Œå ±å‘Šç©©å®šç‰ˆå’Œé•·æœŸæ”¯æŒå…§æ ¸ç·šçš„回歸ã€ä¸­çš„å‰ä¸‰å€‹æ­¥é©Ÿã€‚
+ * 執行å‰ç¯€â€œå ±å‘Šç©©å®šç‰ˆå’Œé•·æœŸæ”¯æŒå…§æ ¸ç·šçš„è¿´æ­¸â€ä¸­çš„å‰ä¸‰å€‹æ­¥é©Ÿã€‚
* 在Linux內核版本控制系統中æœç´¢ä¿®å¾©ä¸»ç·šå•題的更改,因爲它的æäº¤æ¶ˆæ¯å¯èƒ½æœƒ
告訴你修復是å¦å·²ç¶“計劃好了支æŒã€‚如果你沒有找到,æœç´¢é©ç•¶çš„郵件列表,尋找
@@ -219,14 +216,14 @@
ç¢ºä¿æ‚¨ä½¿ç”¨çš„æ˜¯ä¸Šæ¸¸Linuxå…§æ ¸
----------------------------
- *您是å¦é¢è‡¨ç¡¬é«”或軟體供應商æä¾›çš„Linux內核的å•é¡Œï¼Ÿé‚£éº¼åŸºæœ¬ä¸Šæ‚¨æœ€å¥½åœæ­¢é–±
+ *您是å¦é¢è‡¨ç¡¬ä»¶æˆ–軟件供應商æä¾›çš„Linux內核的å•é¡Œï¼Ÿé‚£éº¼åŸºæœ¬ä¸Šæ‚¨æœ€å¥½åœæ­¢é–±
è®€æœ¬æ–‡æª”ï¼Œè½‰è€Œå‘æ‚¨çš„供應商報告å•é¡Œï¼Œé™¤éžæ‚¨é¡˜æ„è‡ªå·±å®‰è£æœ€æ–°çš„Linux版本。
尋找和解決å•題往往需è¦å¾Œè€…。*
-與大多數程å¼è¨­è¨ˆå¸«ä¸€æ¨£ï¼ŒLinux內核開發人員ä¸å–œæ­¡èŠ±æ™‚é–“è™•ç†ä»–們維護的原始碼中根本
-䏿œƒç™¼ç”Ÿçš„å•é¡Œçš„å ±å‘Šã€‚é€™åªæœƒæµªè²»æ¯å€‹äººçš„æ™‚間,尤其是你的時間。ä¸å¹¸çš„æ˜¯ï¼Œç•¶
+與大多數程åºå“¡ä¸€æ¨£ï¼ŒLinux內核開發人員ä¸å–œæ­¡èŠ±æ™‚é–“è™•ç†ä»–們維護的æºä»£ç¢¼ä¸­æ ¹æœ¬
+䏿œƒç™¼ç”Ÿçš„å•題的報告。這隻會浪費æ¯å€‹äººçš„æ™‚間,尤其是你的時間。ä¸å¹¸çš„æ˜¯ï¼Œç•¶
涉åŠåˆ°å…§æ ¸æ™‚,這樣的情æ³å¾ˆå®¹æ˜“發生,並且常常導致雙方氣餒。這是因爲幾乎所有é 
-è£åœ¨è¨­å‚™ï¼ˆå°å¼æ©Ÿã€ç­†è¨˜æœ¬é›»è…¦ã€æ™ºæ…§åž‹æ‰‹æ©Ÿã€è·¯ç”±å™¨ç­‰ï¼‰ä¸Šçš„Linux內核,以åŠå¤§å¤šæ•¸
+è£åœ¨è¨­å‚™ï¼ˆè‡ºå¼æ©Ÿã€ç­†è¨˜æœ¬é›»è…¦ã€æ™ºèƒ½æ‰‹æ©Ÿã€è·¯ç”±å™¨ç­‰ï¼‰ä¸Šçš„Linux內核,以åŠå¤§å¤šæ•¸
ç”±Linux發行商æä¾›çš„內核,都與由kernel.org發行的官方Linux內核相è·ç”šé ï¼šå¾žLinux
開發的角度來看,這些供應商æä¾›çš„內核通常是å¤è€çš„æˆ–者經éŽäº†å¤§é‡ä¿®æ”¹ï¼Œé€šå¸¸å…©é»ž
兼具。
@@ -235,19 +232,19 @@
å¯èƒ½å·²ç¶“ç”±Linux內核開發人員在數月或數年å‰ä¿®å¾©ï¼›æ­¤å¤–,供應商的修改和增強å¯èƒ½
會導致您é¢è‡¨çš„å•題,å³ä½¿å®ƒå€‘çœ‹èµ·ä¾†å¾ˆå°æˆ–者完全ä¸ç›¸é—œã€‚這就是爲什麼您應該å‘
供應商報告這些內核的å•題。它的開發者應該查看報告,如果它是一個上游å•題,直接
-於上游修復或將報告轉發到那裡。在實è¸ä¸­ï¼Œé€™æœ‰æ™‚行ä¸é€šã€‚因此,您å¯èƒ½éœ€è¦è€ƒæ…®
+於上游修復或將報告轉發到那è£ã€‚在實è¸ä¸­ï¼Œé€™æœ‰æ™‚行ä¸é€šã€‚因此,您å¯èƒ½éœ€è¦è€ƒæ…®
通éŽè‡ªå·±å®‰è£æœ€æ–°çš„Linux內核內核來繞éŽä¾›æ‡‰å•†ã€‚å¦‚æžœå¦‚æžœæ‚¨é¸æ“‡æ­¤æ–¹æ³•,那麼本指
å—後é¢çš„æ­¥é©Ÿå°‡è§£é‡‹å¦‚何在排除了其他å¯èƒ½å°Žè‡´æ‚¨çš„å•題的原因後執行此æ“作。
-注æ„剿®µä½¿ç”¨çš„詞語是「大多數ã€ï¼Œå› çˆ²æœ‰æ™‚候開發人員實際上願æ„處ç†ä¾›æ‡‰å•†å…§æ ¸å‡ºç¾
+注æ„剿®µä½¿ç”¨çš„詞語是“大多數â€ï¼Œå› çˆ²æœ‰æ™‚候開發人員實際上願æ„處ç†ä¾›æ‡‰å•†å…§æ ¸å‡ºç¾
çš„å•題報告。他們是å¦é€™éº¼åšå¾ˆå¤§ç¨‹åº¦ä¸Šå–決於開發人員和相關å•題。如果發行版åª
根據最近的Linux版本å°å…§æ ¸é€²è¡Œäº†è¼ƒå°ä¿®æ”¹ï¼Œé‚£éº¼æ©Ÿæœƒå°±æ¯”è¼ƒå¤§ï¼›ä¾‹å¦‚å°æ–¼Debian
GNU/Linux Sid或Fedora Rawhide所æä¾›çš„主線內核。一些開發人員還將接å—基於最新
穩定內核的發行版內核å•題報告,åªè¦å®ƒæ”¹å‹•ä¸å¤§ï¼›ä¾‹å¦‚Arch Linuxã€å¸¸è¦Fedora版本
å’ŒopenSUSE Turboweed。但是請記ä½ï¼Œæ‚¨æœ€å¥½ä½¿ç”¨ä¸»ç·šLinux,並é¿å…在此æµç¨‹ä¸­ä½¿ç”¨
-穩定版內核,如「安è£ä¸€å€‹æ–°çš„內核進行測試ã€ä¸€ç¯€ä¸­æ‰€è©³è¿°ã€‚
+穩定版內核,如“安è£ä¸€å€‹æ–°çš„內核進行測試â€ä¸€ç¯€ä¸­æ‰€è©³è¿°ã€‚
-當然,您å¯ä»¥å¿½ç•¥æ‰€æœ‰é€™äº›å»ºè­°ï¼Œä¸¦å‘上游Linux開發人員報告舊的或經éŽå¤§é‡ä¿®æ”¹çš„
+當然,您å¯ä»¥å¿½ç•¥æ‰€æœ‰é€™äº›å»ºè­°ï¼Œä¸¦å‘上éŠLinux開發人員報告舊的或經éŽå¤§é‡ä¿®æ”¹çš„
供應商內核的å•題。但是注æ„,這樣的報告經常被拒絕或忽視,所以自行å°å¿ƒè€ƒæ…®ä¸€ä¸‹ã€‚
ä¸éŽé€™é‚„是比根本ä¸å ±å‘Šå•題è¦å¥½ï¼šæœ‰æ™‚候這樣的報告會直接或間接地幫助解決之後的
å•題。
@@ -256,64 +253,61 @@ GNU/Linux Sid或Fedora Rawhide所æä¾›çš„主線內核。一些開發人員還å°
æœç´¢ç¾æœ‰å ±å‘Šï¼ˆç¬¬ä¸€éƒ¨åˆ†ï¼‰
-------------------------
- *使用您喜愛的網絡æœå°‹å¼•擎å°ç¾æœ‰å ±å‘Šé€²è¡Œç²—ç•¥æœç´¢ï¼›æ­¤å¤–,請檢查Linuxå…§æ ¸
+ *使用您喜愛的網絡æœç´¢å¼•擎å°ç¾æœ‰å ±å‘Šé€²è¡Œç²—ç•¥æœç´¢ï¼›æ­¤å¤–,請檢查Linuxå…§æ ¸
郵件列表(LKML)的存檔。如果找到匹é…çš„å ±å‘Šï¼Œè«‹åŠ å…¥è¨Žè«–è€Œä¸æ˜¯ç™¼é€æ–°å ±å‘Šã€‚*
報告一個別人已經æå‡ºçš„å•é¡Œï¼Œå°æ¯å€‹äººä¾†èªªéƒ½æ˜¯æµªè²»æ™‚間,尤其是作爲報告人的你。
æ‰€ä»¥å¾¹åº•æª¢æŸ¥æ˜¯å¦æœ‰äººå·²ç¶“報告了這個å•題,這å°ä½ è‡ªå·±æ˜¯æœ‰åˆ©çš„。在æµç¨‹ä¸­çš„這一步,
-å¯ä»¥åªåŸ·è¡Œä¸€å€‹ç²—略的æœç´¢ï¼šä¸€æ—¦æ‚¨çŸ¥é“您的å•題需è¦å ±å‘Šåˆ°å“ªè£¡ï¼Œç¨å¾Œçš„æ­¥é©Ÿå°‡å‘Šè¨´
+å¯ä»¥åªåŸ·è¡Œä¸€å€‹ç²—略的æœç´¢ï¼šä¸€æ—¦æ‚¨çŸ¥é“您的å•題需è¦å ±å‘Šåˆ°å“ªè£ï¼Œç¨å¾Œçš„æ­¥é©Ÿå°‡å‘Šè¨´
您如何詳細æœç´¢ã€‚儘管如此,ä¸è¦å€‰ä¿ƒå®Œæˆé€™ä¸€æ­¥ï¼Œå®ƒå¯ä»¥ç¯€çœæ‚¨çš„æ™‚間和減少麻煩。
-åªéœ€å…ˆç”¨ä½ æœ€å–œæ­¡çš„æœå°‹å¼•æ“Žåœ¨ç¶²éš›ç¶²è·¯ä¸Šæœç´¢ã€‚ç„¶å¾Œå†æœç´¢Linux內核郵件列表(LKML)
+åªéœ€å…ˆç”¨ä½ æœ€å–œæ­¡çš„æœç´¢å¼•æ“Žåœ¨äº’è¯ç¶²ä¸Šæœç´¢ã€‚ç„¶å¾Œå†æœç´¢Linux內核郵件列表(LKML)
存檔。
-如果æœç´¢çµæžœå¯¦åœ¨å¤ªå¤šï¼Œå¯ä»¥è€ƒæ…®è®“ä½ çš„æœå°‹å¼•擎將æœç´¢æ™‚間範åœé™åˆ¶åœ¨éŽåŽ»çš„ä¸€å€‹
-月或一年。而且無論你在哪裡æœç´¢ï¼Œä¸€å®šè¦ç”¨æ°ç•¶çš„æœç´¢é—œéµè©žï¼›ä¹Ÿè¦è®ŠåŒ–幾次關éµ
-è©žã€‚åŒæ™‚,試著從別人的角度看å•題:這將幫助你想出其他的關éµè©žã€‚å¦å¤–,一定ä¸
+如果æœç´¢çµæžœå¯¦åœ¨å¤ªå¤šï¼Œå¯ä»¥è€ƒæ…®è®“ä½ çš„æœç´¢å¼•擎將æœç´¢æ™‚間範åœé™åˆ¶åœ¨éŽåŽ»çš„ä¸€å€‹
+æœˆæˆ–ä¸€å¹´ã€‚è€Œä¸”ç„¡è«–ä½ åœ¨å“ªè£æœç´¢ï¼Œä¸€å®šè¦ç”¨æ°ç•¶çš„æœç´¢é—œéµè©žï¼›ä¹Ÿè¦è®ŠåŒ–幾次關éµ
+è©žã€‚åŒæ™‚,試ç€å¾žåˆ¥äººçš„角度看å•題:這將幫助你想出其他的關éµè©žã€‚å¦å¤–,一定ä¸
è¦åŒæ™‚使用éŽå¤šçš„é—œéµè©žã€‚è¨˜ä½æœç´¢æ™‚è¦åŒæ™‚嘗試包å«å’Œä¸åŒ…å«å…§æ ¸é©…動程åºçš„å稱
-或å—影響的硬體組件的å稱等信æ¯ã€‚但其確切的å“牌å稱(比如說「è¯ç¢©ç´…é­” Radeon
-RX 5700 XT Gaming OCã€ï¼‰å¾€å¾€å¹«åŠ©ä¸å¤§ï¼Œå› çˆ²å®ƒå¤ªå…·é«”了。相å,嘗試æœç´¢è¡“語,如
-型號(Radeon 5700 或 Radeon 5000)和核心代號(「Naviã€æˆ–「Navi10ã€ï¼‰ï¼Œä»¥åŠåŒ…å«
-å’Œä¸åŒ…å«å…¶è£½é€ å•†ï¼ˆã€ŒAMDã€ï¼‰ã€‚
+或å—影響的硬件組件的å稱等信æ¯ã€‚但其確切的å“牌å稱(比如說“è¯ç¢©ç´…é­” Radeon
+RX 5700 XT Gaming OCâ€ï¼‰å¾€å¾€å¹«åŠ©ä¸å¤§ï¼Œå› çˆ²å®ƒå¤ªå…·é«”了。相å,嘗試æœç´¢è¡“語,如
+型號(Radeon 5700 或 Radeon 5000)和核心代號(“Naviâ€æˆ–“Navi10â€ï¼‰ï¼Œä»¥åŠåŒ…å«
+å’Œä¸åŒ…å«å…¶è£½é€ å•†ï¼ˆâ€œAMDâ€ï¼‰ã€‚
如果你發ç¾äº†é—œæ–¼ä½ çš„å•é¡Œçš„ç¾æœ‰å ±å‘Šï¼Œè«‹åŠ å…¥è¨Žè«–ï¼Œå› çˆ²ä½ å¯èƒ½æœƒæä¾›æœ‰åƒ¹å€¼çš„é¡
外信æ¯ã€‚這一點很é‡è¦ï¼Œå³ä½¿æ˜¯åœ¨ä¿®å¾©ç¨‹åºå·²ç¶“準備好或處於最後階段,因爲開發人
-å“¡å¯èƒ½æœƒå°‹æ‰¾èƒ½å¤ æä¾›é¡å¤–ä¿¡æ¯æˆ–測試建議修復程åºçš„人。跳到「發布報告後的責任ã€
-一節,了解有關如何正確åƒèˆ‡çš„細節。
+å“¡å¯èƒ½æœƒå°‹æ‰¾èƒ½å¤ æä¾›é¡å¤–ä¿¡æ¯æˆ–測試建議修復程åºçš„人。跳到“發佈報告後的責任â€
+一節,瞭解有關如何正確åƒèˆ‡çš„細節。
注æ„,æœç´¢ `bugzilla.kernel.org <https://bugzilla.kernel.org/>`_ 網站å¯èƒ½
也是一個好主æ„,因爲這å¯èƒ½æœƒæä¾›æœ‰åƒ¹å€¼çš„見解或找到匹é…的報告。如果您發ç¾å¾Œè€…,
-請記ä½ï¼šå¤§å¤šæ•¸å­ç³»çµ±éƒ½å¸Œæœ›åœ¨ä¸åŒçš„ä½ç½®å ±å‘Šï¼Œå¦‚下é¢ã€Œä½ éœ€è¦å°‡å•題報告到何處ã€
+請記ä½ï¼šå¤§å¤šæ•¸å­ç³»çµ±éƒ½å¸Œæœ›åœ¨ä¸åŒçš„ä½ç½®å ±å‘Šï¼Œå¦‚下é¢â€œä½ éœ€è¦å°‡å•題報告到何處â€
一節中所述。因此本應處ç†é€™å€‹å•題的開發人員甚至å¯èƒ½ä¸çŸ¥é“bugzilla的工單。所以
請檢查工單中的å•題是å¦å·²ç¶“按照本文檔所述得到報告,如果沒有,請考慮這樣åšã€‚
高優先級的å•題?
-----------------
- *看看你正在處ç†çš„å•é¡Œæ˜¯å¦æ˜¯å›žæ­¸å•題ã€å®‰å…¨å•題或éžå¸¸åš´é‡çš„å•題:這些都是
- 需è¦åœ¨æŽ¥ä¸‹ä¾†çš„一些步驟中特別處ç†çš„「高優先級å•題ã€ã€‚*
+ *看看你正在處ç†çš„å•é¡Œæ˜¯å¦æ˜¯è¿´æ­¸å•題ã€å®‰å…¨å•題或éžå¸¸åš´é‡çš„å•題:這些都是
+ 需è¦åœ¨æŽ¥ä¸‹ä¾†çš„一些步驟中特別處ç†çš„“高優先級å•題â€ã€‚*
Linus Torvalds和主è¦çš„Linux內核開發人員希望看到一些å•題儘快得到解決,因此在
-報告éŽç¨‹ä¸­æœ‰ä¸€äº›ã€Œé«˜å„ªå…ˆç´šå•題ã€çš„處ç†ç•¥æœ‰ä¸åŒã€‚有三種情æ³ç¬¦åˆæ¢ä»¶:回歸ã€å®‰å…¨
+報告éŽç¨‹ä¸­æœ‰ä¸€äº›â€œé«˜å„ªå…ˆç´šå•題â€çš„處ç†ç•¥æœ‰ä¸åŒã€‚有三種情æ³ç¬¦åˆæ¢ä»¶:è¿´æ­¸ã€å®‰å…¨
å•題和éžå¸¸åš´é‡çš„å•題。
-如果在舊版本的Linux內核中工作的æ±è¥¿ä¸èƒ½åœ¨æ–°ç‰ˆæœ¬çš„Linux內核中工作,或者æŸç¨®
-程度上在新版本的Linux內核中工作得更差,那麼你就需è¦è™•ç†ã€Œå›žæ­¸ã€ã€‚因此,當一個
-在Linux 5.7中表ç¾è‰¯å¥½çš„WiFi驅動程åºåœ¨5.8中表ç¾ä¸ä½³æˆ–根本ä¸èƒ½å·¥ä½œæ™‚,這是一
-種回歸。如果應用程å¼åœ¨æ–°çš„內核中出ç¾ä¸ç©©å®šçš„ç¾è±¡ï¼Œé€™ä¹Ÿæ˜¯ä¸€ç¨®å›žæ­¸ï¼Œé€™å¯èƒ½æ˜¯
-由於內核和用戶空間之間的接å£ï¼ˆå¦‚procfså’Œsysfs)發生ä¸å…¼å®¹çš„æ›´æ”¹é€ æˆçš„。顯著
-的性能é™ä½Žæˆ–功耗增加也å¯ä»¥ç¨±çˆ²å›žæ­¸ã€‚但是請記ä½:新內核需è¦ä½¿ç”¨èˆ‡èˆŠå…§æ ¸ç›¸ä¼¼çš„
-é…置來構建(åƒè¦‹ä¸‹é¢å¦‚何實ç¾é€™ä¸€é»žï¼‰ã€‚é€™æ˜¯å› çˆ²å…§æ ¸é–‹ç™¼äººå“¡åœ¨å¯¦ç¾æ–°ç‰¹æ€§æ™‚有
-時無法é¿å…ä¸å…¼å®¹æ€§ï¼›ä½†æ˜¯çˆ²äº†é¿å…回歸,這些特性必須在構建é…置期間顯å¼åœ°å•“用。
+如果æŸå€‹æ‡‰ç”¨ç¨‹åºæˆ–實際用例在原先的Linux內核上é‹è¡Œè‰¯å¥½ï¼Œä½†åœ¨ä½¿ç”¨é¡žä¼¼é…置編譯的
+è¼ƒæ–°ç‰ˆæœ¬ä¸Šæ•ˆæžœæ›´å·®ã€æˆ–者根本ä¸èƒ½ç”¨ï¼Œé‚£éº¼ä½ å°±éœ€è¦è™•ç†è¿´æ­¸å•題。
+Documentation/admin-guide/reporting-regressions.rst å°æ­¤é€²è¡Œäº†æ›´è©³ç´°çš„解釋。
+它還æä¾›äº†å¾ˆå¤šä½ å¯èƒ½æƒ³çŸ¥é“的關於迴歸的其他信æ¯ï¼›ä¾‹å¦‚,它解釋瞭如何將您的å•題
+添加到迴歸跟蹤列表中,以確ä¿å®ƒä¸æœƒè¢«å¿½ç•¥ã€‚
什麼是安全å•題留給您自己判斷。在繼續之å‰ï¼Œè«‹è€ƒæ…®é–±è®€
-「Documentation/translations/zh_TW/admin-guide/security-bugs.rstã€ï¼Œ
-因爲它æä¾›äº†å¦‚何最æ°ç•¶åœ°è™•ç†å®‰å…¨å•題的é¡å¤–細節。
+Documentation/translations/zh_CN/admin-guide/security-bugs.rst ,
+因爲它æä¾›çž­å¦‚何最æ°ç•¶åœ°è™•ç†å®‰å…¨å•題的é¡å¤–細節。
-當發生了完全無法接å—的糟糕事情時,此å•題就是一個「éžå¸¸åš´é‡çš„å•題ã€ã€‚例如,
-Linux內核破壞了它處ç†çš„æ•¸æ“šæˆ–æå£žäº†å®ƒé‹è¡Œçš„硬體。當內核çªç„¶é¡¯ç¤ºéŒ¯èª¤æ¶ˆæ¯
-(「kernel panicã€ï¼‰ä¸¦åœæ­¢å·¥ä½œï¼Œæˆ–è€…æ ¹æœ¬æ²’æœ‰ä»»ä½•åœæ­¢ä¿¡æ¯æ™‚,您也在處ç†ä¸€å€‹åš´é‡
-çš„å•題。注æ„:ä¸è¦æ··æ·†ã€Œpanicã€ï¼ˆå…§æ ¸åœæ­¢è‡ªèº«çš„致命錯誤)和「Oopsã€ï¼ˆå¯æ¢å¾©éŒ¯èª¤ï¼‰ï¼Œ
+當發生了完全無法接å—的糟糕事情時,此å•題就是一個“éžå¸¸åš´é‡çš„å•題â€ã€‚例如,
+Linux內核破壞了它處ç†çš„æ•¸æ“šæˆ–æå£žäº†å®ƒé‹è¡Œçš„硬件。當內核çªç„¶é¡¯ç¤ºéŒ¯èª¤æ¶ˆæ¯
+(“kernel panicâ€ï¼‰ä¸¦åœæ­¢å·¥ä½œï¼Œæˆ–è€…æ ¹æœ¬æ²’æœ‰ä»»ä½•åœæ­¢ä¿¡æ¯æ™‚,您也在處ç†ä¸€å€‹åš´é‡
+çš„å•題。注æ„:ä¸è¦æ··æ·†â€œpanicâ€ï¼ˆå…§æ ¸åœæ­¢è‡ªèº«çš„致命錯誤)和“Oopsâ€ï¼ˆå¯æ¢å¾©éŒ¯èª¤ï¼‰ï¼Œ
因爲顯示後者之後內核ä»ç„¶åœ¨é‹è¡Œã€‚
@@ -325,22 +319,22 @@ Linux內核破壞了它處ç†çš„æ•¸æ“šæˆ–æå£žäº†å®ƒé‹è¡Œçš„硬體。當內核
看起來很åƒå…§æ ¸å•題的å•題有時是由構建或é‹è¡Œæ™‚環境引起的。很難完全排除這種å•
é¡Œï¼Œä½†ä½ æ‡‰è©²å„˜é‡æ¸›å°‘這種å•題:
- * 構建內核時,請使用經éŽé©—è­‰çš„å·¥å…·ï¼Œå› çˆ²ç·¨è­¯å™¨æˆ–äºŒé€²ä½æ–‡ä»¶ä¸­çš„錯誤å¯èƒ½æœƒå°Ž
+ * 構建內核時,請使用經éŽé©—證的工具,因爲編譯器或二進制文件中的錯誤å¯èƒ½æœƒå°Ž
致內核出ç¾éŒ¯èª¤è¡Œçˆ²ã€‚
* ç¢ºä¿æ‚¨çš„計算機組件在其設計è¦ç¯„å…§é‹è¡Œï¼›é€™å°è™•ç†å™¨ã€å…§å­˜å’Œä¸»æ¿å°¤çˆ²é‡è¦ã€‚å› 
此,當é¢è‡¨æ½›åœ¨çš„å…§æ ¸å•é¡Œæ™‚ï¼Œåœæ­¢ä½Žé›»å£“或超頻。
- * 儘é‡ç¢ºä¿ä¸æ˜¯ç¡¬é«”故障導致了你的å•題。例如,內存æå£žæœƒå°Žè‡´å¤§é‡çš„å•題,這些
+ * 儘é‡ç¢ºä¿ä¸æ˜¯ç¡¬ä»¶æ•…障導致了你的å•題。例如,內存æå£žæœƒå°Žè‡´å¤§é‡çš„å•題,這些
å•題會表ç¾çˆ²çœ‹èµ·ä¾†åƒå…§æ ¸å•題。
* 如果你正在處ç†ä¸€å€‹æ–‡ä»¶ç³»çµ±å•題,你å¯èƒ½éœ€è¦ç”¨ ``fsck`` 檢查一下文件系統,
因爲它å¯èƒ½æœƒä»¥æŸç¨®æ–¹å¼è¢«æå£žï¼Œå¾žè€Œå°Žè‡´ç„¡æ³•é æœŸçš„內核行爲。
- * 在處ç†å›žæ­¸å•題時,è¦ç¢ºä¿æ²’æœ‰åœ¨æ›´æ–°å…§æ ¸çš„åŒæ™‚發生了其他變化。例如,這個å•
- 題å¯èƒ½æ˜¯ç”±åŒæ™‚更新的其他軟體引起的。也有å¯èƒ½æ˜¯åœ¨ä½ ç¬¬ä¸€æ¬¡é‡å•“進入新內核時,
- æŸå€‹ç¡¬é«”å·§åˆåœ°å£žäº†ã€‚更新系統 BIOS 或改變 BIOS 設置中的æŸäº›å…§å®¹ä¹Ÿæœƒå°Žè‡´
- 一些看起來很åƒå…§æ ¸å›žæ­¸çš„å•題。
+ * 在處ç†è¿´æ­¸å•題時,è¦ç¢ºä¿æ²’æœ‰åœ¨æ›´æ–°å…§æ ¸çš„åŒæ™‚發生了其他變化。例如,這個å•
+ 題å¯èƒ½æ˜¯ç”±åŒæ™‚更新的其他軟件引起的。也有å¯èƒ½æ˜¯åœ¨ä½ ç¬¬ä¸€æ¬¡é‡å•“進入新內核時,
+ æŸå€‹ç¡¬ä»¶å·§åˆåœ°å£žäº†ã€‚更新系統 BIOS 或改變 BIOS 設置中的æŸäº›å…§å®¹ä¹Ÿæœƒå°Žè‡´
+ 一些看起來很åƒå…§æ ¸è¿´æ­¸çš„å•題。
爲緊急情æ³åšå¥½æº–å‚™
@@ -349,8 +343,8 @@ Linux內核破壞了它處ç†çš„æ•¸æ“šæˆ–æå£žäº†å®ƒé‹è¡Œçš„硬體。當內核
*創建一個全新的備份,並將系統修復和還原工具放在手邊*
我得æé†’您,您正在和計算機打交é“ï¼Œè¨ˆç®—æ©Ÿæœ‰æ™‚æœƒå‡ºç¾æ„想ä¸åˆ°çš„事情,尤其是當
-您折騰其作業系統的內核等關éµéƒ¨ä»¶æ™‚。而這就是你在這個éŽç¨‹ä¸­è¦åšçš„事情。因此,
-一定è¦å‰µå»ºä¸€å€‹å…¨æ–°çš„備份;還è¦ç¢ºä¿ä½ æ‰‹é ­æœ‰ä¿®å¾©æˆ–é‡è£ä½œæ¥­ç³»çµ±çš„æ‰€æœ‰å·¥å…·ï¼Œ
+您折騰其æ“作系統的內核等關éµéƒ¨ä»¶æ™‚。而這就是你在這個éŽç¨‹ä¸­è¦åšçš„事情。因此,
+一定è¦å‰µå»ºä¸€å€‹å…¨æ–°çš„備份;還è¦ç¢ºä¿ä½ æ‰‹é ­æœ‰ä¿®å¾©æˆ–é‡è£æ“作系統的所有工具,
ä»¥åŠæ¢å¾©å‚™ä»½æ‰€éœ€çš„一切。
@@ -366,67 +360,67 @@ Linux內核破壞了它處ç†çš„æ•¸æ“šæˆ–æå£žäº†å®ƒé‹è¡Œçš„硬體。當內核
çš„ä»»ä½•æ¨¡å¡Šã€‚ç„¶å¾Œé‡æ–°å•“å‹•å†ç¹¼çºŒã€‚
注æ„,你å¯èƒ½ä¸çŸ¥é“ä½ çš„ç³»çµ±æ­£åœ¨ä½¿ç”¨é€™äº›è§£æ±ºæ–¹æ¡ˆä¹‹ä¸€ï¼šç•¶ä½ å®‰è£ Nvidia 專有圖
-形驅動程åºã€VirtualBox æˆ–å…¶ä»–éœ€è¦ Linux 內核以外的模塊支æŒçš„軟體時,它們通
-常會éœé»˜è¨­ç½®ã€‚這就是爲什麼你å¯èƒ½éœ€è¦å¸è¼‰é€™äº›è»Ÿé«”的軟體包,以擺脫任何第三方
+形驅動程åºã€VirtualBox æˆ–å…¶ä»–éœ€è¦ Linux 內核以外的模塊支æŒçš„軟件時,它們通
+常會éœé»˜è¨­ç½®ã€‚這就是爲什麼你å¯èƒ½éœ€è¦å¸è¼‰é€™äº›è»Ÿä»¶çš„軟件包,以擺脫任何第三方
內核模塊。
-æª¢æ¸¬ã€Œæ±™æŸ“ã€æ¨™èªŒ
+æª¢æŸ¥â€œæ±¡æŸ“â€æ¨™èªŒ
----------------
- *ç•¶å•題發生時,檢查您的內核是å¦è¢«ã€Œæ±™æŸ“ã€ï¼Œå› çˆ²ä½¿å…§æ ¸è¨­ç½®é€™å€‹æ¨™èªŒçš„事件å¯
+ *ç•¶å•題發生時,檢查您的內核是å¦è¢«â€œæ±¡æŸ“â€ï¼Œå› çˆ²ä½¿å…§æ ¸è¨­ç½®é€™å€‹æ¨™èªŒçš„事件å¯
能會導致您é¢è‡¨çš„å•題。*
-ç•¶æŸäº›å¯èƒ½æœƒå°Žè‡´çœ‹èµ·ä¾†å®Œå…¨ä¸ç›¸é—œçš„後續錯誤的事情發生時,內核會用「汙染
-(taintï¼‰ã€æ¨™èªŒæ¨™è¨˜è‡ªå·±ã€‚如果您的內核å—到汙染,那麼您é¢è‡¨çš„å¯èƒ½æ˜¯é€™æ¨£çš„錯誤。
+ç•¶æŸäº›å¯èƒ½æœƒå°Žè‡´çœ‹èµ·ä¾†å®Œå…¨ä¸ç›¸é—œçš„後續錯誤的事情發生時,內核會用“污染
+(taintï¼‰â€æ¨™èªŒæ¨™è¨˜è‡ªå·±ã€‚如果您的內核å—到污染,那麼您é¢è‡¨çš„å¯èƒ½æ˜¯é€™æ¨£çš„錯誤。
因此在投入更多時間到這個éŽç¨‹ä¸­ä¹‹å‰ï¼Œå„˜æ—©æŽ’除此情æ³å¯èƒ½å°ä½ æœ‰å¥½è™•。這是這個
-步驟出ç¾åœ¨é€™è£¡çš„唯一原因,因爲這個éŽç¨‹ç¨å¾Œæœƒå‘Šè¨´æ‚¨å®‰è£æœ€æ–°çš„主線內核;然後
-您將需è¦å†æ¬¡æª¢æŸ¥æ±™æŸ“標誌,因爲當它出å•題的時候內核報告會關注它。
+步驟出ç¾åœ¨é€™è£çš„唯一原因,因爲這個éŽç¨‹ç¨å¾Œæœƒå‘Šè¨´æ‚¨å®‰è£æœ€æ–°çš„主線內核;然後
+您將需è¦å†æ¬¡æª¢æŸ¥æ±¡æŸ“標誌,因爲當它出å•題的時候內核報告會關注它。
-在正在é‹è¡Œçš„ç³»çµ±ä¸Šæª¢æŸ¥å…§æ ¸æ˜¯å¦æ±™æŸ“éžå¸¸å®¹æ˜“:如果 ``cat /proc/sys/kernel/tainted``
-返回「0ã€ï¼Œé‚£éº¼å…§æ ¸æ²’有被汙染,一切正常。在æŸäº›æƒ…æ³ä¸‹ç„¡æ³•檢查該文件;這就是
-爲什麼當內核報告內部å•題(「kernel bugã€ï¼‰ã€å¯æ¢å¾©éŒ¯èª¤ï¼ˆã€Œkernel Oopsã€ï¼‰æˆ–åœæ­¢
-æ“作å‰ä¸å¯æ¢å¾©çš„錯誤(「kernel panicã€ï¼‰æ™‚,它也會æåˆ°æ±™æŸ“狀態。當其中一個錯
-誤發生時,查看列å°çš„錯誤消æ¯çš„頂部,æœç´¢ä»¥ã€ŒCPU:ã€é–‹é ­çš„行。如果發ç¾å•題時內
-核未被汙染,那麼它應該以「Not infectedã€çµæŸï¼›å¦‚果你看到「Tainted:ã€ä¸”後跟一些
-空格和字æ¯ï¼Œé‚£å°±è¢«æ±™æŸ“了。
+在正在é‹è¡Œçš„ç³»çµ±ä¸Šæª¢æŸ¥å…§æ ¸æ˜¯å¦æ±¡æŸ“éžå¸¸å®¹æ˜“:如果 ``cat /proc/sys/kernel/tainted``
+返回“0â€ï¼Œé‚£éº¼å…§æ ¸æ²’有被污染,一切正常。在æŸäº›æƒ…æ³ä¸‹ç„¡æ³•檢查該文件;這就是
+爲什麼當內核報告內部å•題(“kernel bugâ€ï¼‰ã€å¯æ¢å¾©éŒ¯èª¤ï¼ˆâ€œkernel Oopsâ€ï¼‰æˆ–åœæ­¢
+æ“作å‰ä¸å¯æ¢å¾©çš„錯誤(“kernel panicâ€ï¼‰æ™‚,它也會æåˆ°æ±¡æŸ“狀態。當其中一個錯
+誤發生時,查看打å°çš„錯誤消æ¯çš„頂部,æœç´¢ä»¥â€œCPU:â€é–‹é ­çš„行。如果發ç¾å•題時內
+核未被污染,那麼它應該以“Not infectedâ€çµæŸï¼›å¦‚果你看到“Tainted:â€ä¸”後跟一些
+空格和字æ¯ï¼Œé‚£å°±è¢«æ±¡æŸ“了。
-如果你的內核被汙染了,請閱讀「Documentation/translations/zh_TW/admin-guide/tainted-kernels.rstã€
-以找出原因。設法消除汙染因素。通常是由以下三種因素之一引起的:
+如果你的內核被污染了,請閱讀 Documentation/translations/zh_CN/admin-guide/tainted-kernels.rst
+以找出原因。設法消除污染因素。通常是由以下三種因素之一引起的:
- 1. ç™¼ç”Ÿäº†ä¸€å€‹å¯æ¢å¾©çš„錯誤(「kernel Oopsã€ï¼‰ï¼Œå…§æ ¸æ±™æŸ“了自己,因爲內核知é“在
+ 1. ç™¼ç”Ÿäº†ä¸€å€‹å¯æ¢å¾©çš„錯誤(“kernel Oopsâ€ï¼‰ï¼Œå…§æ ¸æ±¡æŸ“了自己,因爲內核知é“在
此之後它å¯èƒ½æœƒå‡ºç¾å¥‡æ€ªçš„行爲錯亂。在這種情æ³ä¸‹ï¼Œæª¢æŸ¥æ‚¨çš„內核或系統日誌,
並尋找以下列文字開頭的部分::
Oops: 0000 [#1] SMP
- 如方括號中的「#1ã€æ‰€ç¤ºï¼Œé€™æ˜¯è‡ªå•“動以來的第一次Oops。æ¯å€‹Oops和此後發生的
+ 如方括號中的“#1â€æ‰€ç¤ºï¼Œé€™æ˜¯è‡ªå•“動以來的第一次Oops。æ¯å€‹Oops和此後發生的
任何其他å•題都å¯èƒ½æ˜¯é¦–個Oops的後續å•題,å³ä½¿é€™å…©å€‹å•題看起來完全ä¸ç›¸é—œã€‚
é€šéŽæ¶ˆé™¤é¦–個Oops的原因並在之後復ç¾è©²å•題,å¯ä»¥æŽ’除這種情æ³ã€‚有時僅僅
釿–°å•“動就足夠了,有時更改é…ç½®å¾Œé‡æ–°å•“å‹•å¯ä»¥æ¶ˆé™¤Oops。但是在這個æµç¨‹ä¸­
ä¸è¦èŠ±è²»å¤ªå¤šæ™‚é–“åœ¨é€™ä¸€é»žä¸Šï¼Œå› çˆ²å¼•èµ·Oops的原因å¯èƒ½å·²ç¶“在您ç¨å¾Œå°‡æŒ‰æµç¨‹
安è£çš„æ–°Linux內核版本中修復了。
- 2. 您的系統使用的軟體安è£äº†è‡ªå·±çš„內核模塊,例如Nvidiaçš„å°ˆæœ‰åœ–å½¢é©…å‹•ç¨‹åºæˆ–
- VirtualBox。當內核從外部æºï¼ˆå³ä½¿å®ƒå€‘是開æºçš„)加載此類模塊時,它會汙染
+ 2. 您的系統使用的軟件安è£äº†è‡ªå·±çš„內核模塊,例如Nvidiaçš„å°ˆæœ‰åœ–å½¢é©…å‹•ç¨‹åºæˆ–
+ VirtualBox。當內核從外部æºï¼ˆå³ä½¿å®ƒå€‘是開æºçš„)加載此類模塊時,它會污染
自己:它們有時會在ä¸ç›¸é—œçš„å…§æ ¸å€åŸŸå°Žè‡´éŒ¯èª¤ï¼Œå¾žè€Œå¯èƒ½å°Žè‡´æ‚¨é¢è‡¨çš„å•題。
因此,當您想è¦å‘Linux內核開發人員報告å•題時,您必須阻止這些模塊加載。
- 大多數情æ³ä¸‹æœ€ç°¡å–®çš„æ–¹æ³•是:臨時å¸è¼‰é€™äº›è»Ÿé«”,包括它們å¯èƒ½å·²ç¶“安è£çš„ä»»
+ 大多數情æ³ä¸‹æœ€ç°¡å–®çš„æ–¹æ³•是:臨時å¸è¼‰é€™äº›è»Ÿä»¶ï¼ŒåŒ…括它們å¯èƒ½å·²ç¶“安è£çš„ä»»
ä½•æ¨¡å¡Šã€‚ä¹‹å¾Œé‡æ–°å•“動。
- 3. 當內核加載é§ç•™åœ¨Linux內核原始碼staging樹中的模塊時,它也會汙染自身。這
+ 3. 當內核加載é§ç•™åœ¨Linuxå…§æ ¸æºä»£ç¢¼staging樹中的模塊時,它也會污染自身。這
是一個特殊的å€åŸŸï¼Œä»£ç¢¼ï¼ˆä¸»è¦æ˜¯é©…動程åºï¼‰é‚„沒有é”到正常Linux內核的質é‡
- 標準。當您報告此種模塊的å•題時,內核å—到汙染顯然是沒有å•題的;åªéœ€ç¢ºä¿
- å•é¡Œæ¨¡å¡Šæ˜¯é€ æˆæ±™æŸ“的唯一原因。如果å•題發生在一個ä¸ç›¸é—œçš„å€åŸŸï¼Œé‡æ–°å•“å‹•
+ 標準。當您報告此種模塊的å•題時,內核å—到污染顯然是沒有å•題的;åªéœ€ç¢ºä¿
+ å•é¡Œæ¨¡å¡Šæ˜¯é€ æˆæ±¡æŸ“的唯一原因。如果å•題發生在一個ä¸ç›¸é—œçš„å€åŸŸï¼Œé‡æ–°å•“å‹•
ä¸¦é€šéŽæŒ‡å®š ``foo.blacklist=1`` ä½œçˆ²å…§æ ¸åƒæ•¸è‡¨æ™‚阻止該模塊被加載(用有
- å•é¡Œçš„æ¨¡å¡Šåæ›¿æ›ã€Œfooã€ï¼‰ã€‚
+ å•é¡Œçš„æ¨¡å¡Šåæ›¿æ›â€œfooâ€ï¼‰ã€‚
記錄如何é‡ç¾å•題
------------------
*粗略地寫下如何é‡ç¾é€™å€‹å•é¡Œã€‚å¦‚æžœæ‚¨åŒæ™‚處ç†å¤šå€‹å•題,請爲æ¯å€‹å•題單ç¨å¯«
- 注釋,並確ä¿å®ƒå€‘在新啓動的系統上ç¨ç«‹å‡ºç¾ã€‚這是必è¦çš„,因爲æ¯å€‹å•題都需
+ 註釋,並確ä¿å®ƒå€‘在新啓動的系統上ç¨ç«‹å‡ºç¾ã€‚這是必è¦çš„,因爲æ¯å€‹å•題都需
è¦åˆ†åˆ¥å ±å‘Šçµ¦å…§æ ¸é–‹ç™¼äººå“¡ï¼Œé™¤éžå®ƒå€‘åš´é‡ç³¾çºåœ¨ä¸€èµ·ã€‚*
å¦‚æžœä½ åŒæ™‚處ç†å¤šå€‹å•題,必須分別報告æ¯å€‹å•題,因爲它們å¯èƒ½ç”±ä¸åŒçš„開發人員
@@ -438,20 +432,20 @@ Linux內核破壞了它處ç†çš„æ•¸æ“šæˆ–æå£žäº†å®ƒé‹è¡Œçš„硬體。當內核
注æ„:報告åªç™¼ç”ŸéŽä¸€æ¬¡çš„å•é¡Œå¾€å¾€æ˜¯æ²’æœ‰çµæžœçš„,因爲它們å¯èƒ½æ˜¯ç”±æ–¼å®‡å®™è¼»å°„å°Ž
致的ä½ç¿»è½‰ã€‚所以你應該嘗試通éŽé‡ç¾å•題來排除這種情æ³ï¼Œç„¶å¾Œå†ç¹¼çºŒã€‚如果你有
-足夠的經驗來å€åˆ†ç”±æ–¼ç¡¬é«”故障引起的一次性錯誤和難以é‡ç¾çš„罕見內核å•題,å¯ä»¥
+足夠的經驗來å€åˆ†ç”±æ–¼ç¡¬ä»¶æ•…障引起的一次性錯誤和難以é‡ç¾çš„罕見內核å•題,å¯ä»¥
忽略這個建議。
-穩定版或長期支æŒå…§æ ¸çš„回歸?
+穩定版或長期支æŒå…§æ ¸çš„迴歸?
-----------------------------
- *如果您正é¢è‡¨ç©©å®šç‰ˆæˆ–長期支æŒç‰ˆæœ¬ç·šçš„回歸(例如從5.10.4更新到5.10.5時出ç¾
- 故障),請查看後文「報告穩定版和長期支æŒå…§æ ¸ç·šçš„回歸ã€å°ç¯€ã€‚*
+ *如果您正é¢è‡¨ç©©å®šç‰ˆæˆ–長期支æŒç‰ˆæœ¬ç·šçš„迴歸(例如從5.10.4更新到5.10.5時出ç¾
+ 故障),請查看後文“報告穩定版和長期支æŒå…§æ ¸ç·šçš„è¿´æ­¸â€å°ç¯€ã€‚*
-穩定版和長期支æŒå…§æ ¸ç‰ˆæœ¬ç·šä¸­çš„回歸是Linux開發人員éžå¸¸å¸Œæœ›è§£æ±ºçš„å•題,這樣的
-å•é¡Œç”šè‡³æ¯”ä¸»ç·šé–‹ç™¼åˆ†æ”¯ä¸­çš„å›žæ­¸æ›´ä¸æ‡‰å‡ºç¾ï¼Œå› çˆ²å®ƒå€‘會很快影響到很多人。開發人員
-希望儘快了解此類å•題,因此有一個簡化æµç¨‹ä¾†å ±å‘Šé€™äº›å•題。注æ„,使用更新內核版
-本線的回歸(比如從5.9.15切æ›åˆ°5.10.5æ™‚å‡ºç¾æ•…障)ä¸ç¬¦åˆæ¢ä»¶ã€‚
+穩定版和長期支æŒå…§æ ¸ç‰ˆæœ¬ç·šä¸­çš„迴歸是Linux開發人員éžå¸¸å¸Œæœ›è§£æ±ºçš„å•題,這樣的
+å•é¡Œç”šè‡³æ¯”ä¸»ç·šé–‹ç™¼åˆ†æ”¯ä¸­çš„è¿´æ­¸æ›´ä¸æ‡‰å‡ºç¾ï¼Œå› çˆ²å®ƒå€‘會很快影響到很多人。開發人員
+希望儘快瞭解此類å•題,因此有一個簡化æµç¨‹ä¾†å ±å‘Šé€™äº›å•題。注æ„,使用更新內核版
+本線的迴歸(比如從5.9.15切æ›åˆ°5.10.5æ™‚å‡ºç¾æ•…障)ä¸ç¬¦åˆæ¢ä»¶ã€‚
你需è¦å°‡å•題報告到何處
@@ -462,9 +456,9 @@ Linux內核破壞了它處ç†çš„æ•¸æ“šæˆ–æå£žäº†å®ƒé‹è¡Œçš„硬體。當內核
éŽéƒµä»¶ç™¼é€çµ¦ç¶­è­·äººå“¡å’Œå…¬å…±éƒµä»¶åˆ—表。*
將報告發é€çµ¦åˆé©çš„人是至關é‡è¦çš„,因爲Linux內核是一個大項目,大多數開發人員
-åªç†Ÿæ‚‰å…¶ä¸­çš„一å°éƒ¨åˆ†ã€‚例如,相當多的程å¼è¨­è¨ˆå¸«åªé—œå¿ƒä¸€å€‹é©…動程åºï¼Œæ¯”如一個WiFi
-晶片驅動程åºï¼›å®ƒçš„開發人員å¯èƒ½å°ç–é çš„æˆ–ä¸ç›¸é—œçš„「å­ç³»çµ±ã€ï¼ˆå¦‚TCP堆棧ã€
-PCIe/PCIå­ç³»çµ±ã€å…§å­˜ç®¡ç†æˆ–文件系統)的內部知識了解很少或完全ä¸äº†è§£ã€‚
+åªç†Ÿæ‚‰å…¶ä¸­çš„一å°éƒ¨åˆ†ã€‚例如,相當多的程åºå“¡åªé—œå¿ƒä¸€å€‹é©…動程åºï¼Œæ¯”如一個WiFi
+芯片驅動程åºï¼›å®ƒçš„開發人員å¯èƒ½å°ç–é çš„æˆ–ä¸ç›¸é—œçš„“å­ç³»çµ±â€ï¼ˆå¦‚TCP堆棧ã€
+PCIe/PCIå­ç³»çµ±ã€å…§å­˜ç®¡ç†æˆ–文件系統)的內部知識瞭解很少或完全ä¸çž­è§£ã€‚
å•題在於:Linux內核缺少一個,å¯ä»¥ç°¡å–®åœ°å°‡å•題歸檔並讓需è¦äº†è§£å®ƒçš„開發人員了
解它的,中心化缺陷跟蹤器。這就是爲什麼你必須找到正確的途徑來自己報告å•題。
@@ -476,10 +470,10 @@ PCIe/PCIå­ç³»çµ±ã€å…§å­˜ç®¡ç†æˆ–文件系統)的內部知識了解很少或
爲了說明如何使用 :ref:`MAINTAINERS <maintainers>` 文件,讓我們å‡è¨­æ‚¨çš„筆記
本電腦中的WiFi在更新內核後çªç„¶å‡ºç¾äº†éŒ¯èª¤è¡Œçˆ²ã€‚這種情æ³ä¸‹å¯èƒ½æ˜¯WiFié©…å‹•çš„å•
-題。顯然,它也å¯èƒ½ç”±æ–¼é©…動基於的æŸäº›ä»£ç¢¼ï¼Œä½†é™¤éžä½ æ‡·ç–‘有這樣的æ±è¥¿æœƒé™„著在
-驅動程åºä¸Šã€‚如果真的是其他的å•題,驅動程åºçš„開發人員會讓åˆé©çš„人åƒèˆ‡é€²ä¾†ã€‚
+題。顯然,它也å¯èƒ½ç”±æ–¼é©…動基於的æŸäº›ä»£ç¢¼ï¼Œä½†é™¤éžä½ æ‡·ç–‘有這樣的æ±è¥¿æœƒé™„ç€åœ¨
+驅動程åºä¸Šã€‚如果真的是其他的å•題,驅動程åºçš„開發人員會讓åˆé©çš„人蔘與進來。
-éºæ†¾çš„æ˜¯ï¼Œæ²’有通用且簡單的辦法來檢查哪個代碼驅動了特定硬體組件。
+éºæ†¾çš„æ˜¯ï¼Œæ²’有通用且簡單的辦法來檢查哪個代碼驅動了特定硬件組件。
在WiFi驅動出ç¾å•題的情æ³ä¸‹ï¼Œä½ å¯èƒ½æƒ³æŸ¥çœ‹ ``lspci -k`` 的輸出,因爲它列出了
PCI/PCIe總線上的設備和驅動它的內核模塊::
@@ -492,19 +486,19 @@ PCI/PCIe總線上的設備和驅動它的內核模塊::
Kernel modules: ath10k_pci
[...]
-但如果你的WiFi晶片通éŽUSB或其他內部總線連接,這種方法就行ä¸é€šäº†ã€‚在這種情æ³
+但如果你的WiFi芯片通éŽUSB或其他內部總線連接,這種方法就行ä¸é€šäº†ã€‚在這種情æ³
下,您å¯èƒ½éœ€è¦æª¢æŸ¥æ‚¨çš„WiFi管ç†å™¨æˆ– ``ip link`` 的輸出。尋找有å•題的網絡接å£
-çš„å稱,它å¯èƒ½é¡žä¼¼æ–¼ã€Œwlp58s0ã€ã€‚æ­¤å稱å¯ä»¥ç”¨ä¾†æ‰¾åˆ°é©…動它的模塊::
+çš„å稱,它å¯èƒ½é¡žä¼¼æ–¼â€œwlp58s0â€ã€‚æ­¤å稱å¯ä»¥ç”¨ä¾†æ‰¾åˆ°é©…動它的模塊::
[user@something ~]$ realpath --relative-to=/sys/module//sys/class/net/wlp58s0/device/driver/module
ath10k_pci
如果這些技巧ä¸èƒ½é€²ä¸€æ­¥å¹«åŠ©æ‚¨ï¼Œè«‹å˜—è©¦åœ¨ç¶²ä¸Šæœç´¢å¦‚何縮å°ç›¸é—œé©…å‹•ç¨‹åºæˆ–å­ç³»çµ±
-的範åœã€‚如果你ä¸ç¢ºå®šæ˜¯å“ªä¸€å€‹ï¼šè©¦è‘—猜一下,å³ä½¿ä½ çŒœå¾—ä¸å¥½ï¼Œä¹Ÿæœƒæœ‰äººæœƒå¹«åЩ你
+的範åœã€‚如果你ä¸ç¢ºå®šæ˜¯å“ªä¸€å€‹ï¼šè©¦ç€çŒœä¸€ä¸‹ï¼Œå³ä½¿ä½ çŒœå¾—ä¸å¥½ï¼Œä¹Ÿæœƒæœ‰äººæœƒå¹«åЩ你
的。
一旦您知é“äº†ç›¸æ‡‰çš„é©…å‹•ç¨‹åºæˆ–å­ç³»çµ±ï¼Œæ‚¨å°±å¸Œæœ›åœ¨MAINTAINERS文件中æœç´¢å®ƒã€‚如果
-是「ath10k_pciã€ï¼Œæ‚¨ä¸æœƒæ‰¾åˆ°ä»»ä½•æ±è¥¿ï¼Œå› çˆ²å稱太具體了。有時你需è¦åœ¨ç¶²ä¸Šå°‹æ‰¾
+是“ath10k_pciâ€ï¼Œæ‚¨ä¸æœƒæ‰¾åˆ°ä»»ä½•æ±è¥¿ï¼Œå› çˆ²å稱太具體了。有時你需è¦åœ¨ç¶²ä¸Šå°‹æ‰¾
幫助;但在此之å‰ï¼Œè«‹å˜—試使用一個ç¨çŸ­æˆ–修改éŽçš„å稱來æœç´¢MAINTAINERS文件,因
爲這樣你å¯èƒ½æœƒç™¼ç¾é¡žä¼¼é€™æ¨£çš„æ±è¥¿::
@@ -516,23 +510,23 @@ PCI/PCIe總線上的設備和驅動它的內核模塊::
SCM: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
Files: drivers/net/wireless/ath/ath10k/
-注æ„:如果您閱讀在Linux原始碼樹的根目錄中找到的原始維護者文件,則行æè¿°å°‡æ˜¯
-縮寫。例如,「Mail:(郵件)ã€å°‡æ˜¯ã€ŒM:ã€ï¼Œã€ŒMailing list:(郵件列表)ã€å°‡æ˜¯ã€ŒLã€ï¼Œ
-「Status:(狀態)ã€å°‡æ˜¯ã€ŒS:ã€ã€‚此文件頂部有一段解釋了這些和其他縮寫。
+注æ„:如果您閱讀在Linuxæºä»£ç¢¼æ¨¹çš„æ ¹ç›®éŒ„中找到的原始維護者文件,則行æè¿°å°‡æ˜¯
+縮寫。例如,“Mail:(郵件)â€å°‡æ˜¯â€œM:â€ï¼Œâ€œMailing list:(郵件列表)â€å°‡æ˜¯â€œLâ€ï¼Œ
+“Status:(狀態)â€å°‡æ˜¯â€œS:â€ã€‚此文件頂部有一段解釋了這些和其他縮寫。
-首先查看「Statusã€ç‹€æ…‹è¡Œã€‚ç†æƒ³æƒ…æ³ä¸‹ï¼Œå®ƒæ‡‰è©²å¾—到「Supported(支æŒï¼‰ã€æˆ–
-「Maintained(維護)ã€ã€‚如果狀態爲「Obsoleteï¼ˆéŽæ™‚的)ã€ï¼Œé‚£éº¼ä½ åœ¨ä½¿ç”¨ä¸€äº›éŽæ™‚çš„
-方法,需è¦è½‰æ›åˆ°æ–°çš„è§£æ±ºæ–¹æ¡ˆä¸Šã€‚æœ‰æ™‚å€™ï¼Œåªæœ‰åœ¨æ„Ÿåˆ°æœ‰å‹•åŠ›æ™‚ï¼Œæ‰æœƒæœ‰äººçˆ²ä»£ç¢¼
-æä¾›ã€ŒOdd Fixesã€ã€‚如果碰見「Orphanã€ï¼Œä½ å°±å®Œå…¨ä¸èµ°é‹äº†ï¼Œå› çˆ²å†ä¹Ÿæ²’有人關心代碼
-了,åªå‰©ä¸‹é€™äº›é¸é …:準備好與å•題共存,自己修復它,或者找一個願æ„修復它的程å¼è¨­è¨ˆå¸«ã€‚
+首先查看“Statusâ€ç‹€æ…‹è¡Œã€‚ç†æƒ³æƒ…æ³ä¸‹ï¼Œå®ƒæ‡‰è©²å¾—到“Supported(支æŒï¼‰â€æˆ–
+“Maintained(維護)â€ã€‚如果狀態爲“Obsoleteï¼ˆéŽæ™‚的)â€ï¼Œé‚£éº¼ä½ åœ¨ä½¿ç”¨ä¸€äº›éŽæ™‚çš„
+方法,需è¦è½‰æ›åˆ°æ–°çš„è§£æ±ºæ–¹æ¡ˆä¸Šã€‚æœ‰æ™‚å€™ï¼Œåªæœ‰åœ¨æ„Ÿåˆ°æœ‰å‹•力時,纔會有人爲代碼
+æä¾›â€œOdd Fixesâ€ã€‚如果碰見“Orphanâ€ï¼Œä½ å°±å®Œå…¨ä¸èµ°é‹äº†ï¼Œå› çˆ²å†ä¹Ÿæ²’有人關心代碼
+了,åªå‰©ä¸‹é€™äº›é¸é …:準備好與å•題共存,自己修復它,或者找一個願æ„修復它的程åºå“¡ã€‚
-檢查狀態後,尋找以「bug:ã€é–‹é ­çš„一行:它將告訴你在哪裡å¯ä»¥æ‰¾åˆ°å­ç³»çµ±ç‰¹å®šçš„缺
+檢查狀態後,尋找以“bug:â€é–‹é ­çš„一行:它將告訴你在哪è£å¯ä»¥æ‰¾åˆ°å­ç³»çµ±ç‰¹å®šçš„缺
陷跟蹤器來æäº¤ä½ çš„å•題。上é¢çš„例孿²’有此行。大多數部分都是這樣,因爲 Linux
內核的開發完全是由郵件驅動的。很少有å­ç³»çµ±ä½¿ç”¨ç¼ºé™·è·Ÿè¹¤å™¨ï¼Œä¸”å…¶ä¸­åªæœ‰ä¸€éƒ¨åˆ†
ä¾è³´æ–¼ bugzilla.kernel.org。
-在這種以åŠå…¶ä»–很多情æ³ä¸‹ï¼Œä½ å¿…須尋找以「Mail:ã€é–‹é ­çš„行。這些行æåˆ°äº†ç‰¹å®šä»£ç¢¼
-的維護者的å字和電å­éƒµä»¶åœ°å€ã€‚也å¯ä»¥æŸ¥æ‰¾ä»¥ã€ŒMailing list:ã€é–‹é ­çš„行,它告訴你
+在這種以åŠå…¶ä»–很多情æ³ä¸‹ï¼Œä½ å¿…須尋找以“Mail:â€é–‹é ­çš„行。這些行æåˆ°äº†ç‰¹å®šä»£ç¢¼
+的維護者的å字和電å­éƒµä»¶åœ°å€ã€‚也å¯ä»¥æŸ¥æ‰¾ä»¥â€œMailing list:â€é–‹é ­çš„行,它告訴你
開發代碼的公共郵件列表。你的報告之後需è¦é€šéŽéƒµä»¶ç™¼åˆ°é€™äº›åœ°å€ã€‚å¦å¤–ï¼Œå°æ–¼æ‰€æœ‰
通éŽé›»å­éƒµä»¶ç™¼é€çš„å•é¡Œå ±å‘Šï¼Œä¸€å®šè¦æŠ„é€ Linux Kernel Mailing List(LKML)
<linux-kernel@vger.kernel.org>。在以後通éŽéƒµä»¶ç™¼é€å•題報告時,ä¸è¦éºæ¼ä»»ä½•
@@ -544,8 +538,8 @@ PCI/PCIe總線上的設備和驅動它的內核模塊::
~~~~~~~~~~~~~~~~~~~~
å°æ–¼æ‰‹é ­æœ‰Linuxæºç¢¼çš„人來說,有第二個å¯ä»¥æ‰¾åˆ°åˆé©çš„å ±å‘Šåœ°é»žçš„é¸æ“‡ï¼šè…³æœ¬
-「scripts/get_maintainer.plã€ï¼Œå®ƒå˜—試找到所有è¦è¯ç¹«çš„人。它會查詢MAINTAINERS
-文件,並需è¦ç”¨ç›¸é—œåŽŸå§‹ç¢¼çš„è·¯å¾‘ä¾†èª¿ç”¨ã€‚å°æ–¼ç·¨è­¯æˆæ¨¡å¡Šçš„驅動程åºï¼Œç¶“常å¯ä»¥ç”¨
+“scripts/get_maintainer.plâ€ï¼Œå®ƒå˜—試找到所有è¦è¯ç¹«çš„人。它會查詢MAINTAINERS
+文件,並需è¦ç”¨ç›¸é—œæºä»£ç¢¼çš„è·¯å¾‘ä¾†èª¿ç”¨ã€‚å°æ–¼ç·¨è­¯æˆæ¨¡å¡Šçš„驅動程åºï¼Œç¶“常å¯ä»¥ç”¨
這樣的命令找到::
$ modinfo ath10k_pci | grep filename | sed 's!/lib/modules/.*/kernel/!!; s!filename:!!; s!\.ko\(\|\.xz\)!!'
@@ -561,13 +555,13 @@ PCI/PCIe總線上的設備和驅動它的內核模塊::
netdev@vger.kernel.org (open list:NETWORKING DRIVERS)
linux-kernel@vger.kernel.org (open list)
-ä¸è¦æŠŠä½ çš„報告發給所有的人。發é€çµ¦ç¶­è­·è€…,腳本稱之爲「supporter:ã€ï¼›å¦å¤–抄é€
+ä¸è¦æŠŠä½ çš„報告發給所有的人。發é€çµ¦ç¶­è­·è€…,腳本稱之爲“supporter:â€ï¼›å¦å¤–抄é€
ä»£ç¢¼æœ€ç›¸é—œçš„éƒµä»¶åˆ—è¡¨ï¼Œä»¥åŠ Linux 內核郵件列表(LKML)。在此例中,你需è¦å°‡å ±
-告發é€çµ¦ 「Some Human <shuman@example.com>〠,並抄é€
-「ath10k@lists.infradead.orgã€å’Œã€Œlinux-kernel@vger.kernel.orgã€ã€‚
+告發é€çµ¦ “Some Human <shuman@example.com>†,並抄é€
+“ath10k@lists.infradead.orgâ€å’Œâ€œlinux-kernel@vger.kernel.orgâ€ã€‚
-注æ„:如果你用 git 克隆了 Linux 原始碼,你å¯èƒ½éœ€è¦ç”¨--git 冿¬¡èª¿ç”¨
-get_maintainer.pl。腳本會查看æäº¤æ­·å²ï¼Œä»¥æ‰¾åˆ°æœ€è¿‘哪些人åƒèˆ‡äº†ç›¸é—œä»£ç¢¼çš„編寫,
+注æ„:如果你用 git 克隆了 Linux æºä»£ç¢¼ï¼Œä½ å¯èƒ½éœ€è¦ç”¨--git 冿¬¡èª¿ç”¨
+get_maintainer.pl。腳本會查看æäº¤æ­·å²ï¼Œä»¥æ‰¾åˆ°æœ€è¿‘哪些人蔘與了相關代碼的編寫,
因爲他們å¯èƒ½æœƒæä¾›å¹«åŠ©ã€‚ä½†è¦å°å¿ƒä½¿ç”¨é€™äº›çµæžœï¼Œå› çˆ²å®ƒå¾ˆå®¹æ˜“讓你誤入歧途。
例如,這種情æ³å¸¸å¸¸æœƒç™¼ç”Ÿåœ¨å¾ˆå°‘被修改的地方(比如è€èˆŠçš„æˆ–未維護的驅動程åºï¼‰ï¼š
æœ‰æ™‚é€™æ¨£çš„ä»£ç¢¼æœƒåœ¨æ¨¹ç´šæ¸…ç†æœŸé–“被根本ä¸é—œå¿ƒæ­¤é©…動程åºçš„開發者修改。
@@ -580,73 +574,74 @@ get_maintainer.pl。腳本會查看æäº¤æ­·å²ï¼Œä»¥æ‰¾åˆ°æœ€è¿‘哪些人åƒèˆ‡
如果找到匹é…çš„å ±å‘Šï¼Œè«‹åŠ å…¥è¨Žè«–è€Œä¸æ˜¯ç™¼é€æ–°å ±å‘Šã€‚*
如剿‰€è¿°ï¼šå ±å‘Šä¸€å€‹åˆ¥äººå·²ç¶“æå‡ºçš„å•é¡Œï¼Œå°æ¯å€‹äººä¾†èªªéƒ½æ˜¯æµªè²»æ™‚間,尤其是作爲報告
-äººçš„ä½ ã€‚é€™å°±æ˜¯çˆ²ä»€éº¼ä½ æ‡‰è©²å†æ¬¡æœç´¢ç¾æœ‰çš„報告。ç¾åœ¨ä½ å·²ç¶“知é“å•題需è¦å ±å‘Šåˆ°å“ªè£¡ã€‚
+äººçš„ä½ ã€‚é€™å°±æ˜¯çˆ²ä»€éº¼ä½ æ‡‰è©²å†æ¬¡æœç´¢ç¾æœ‰çš„報告。ç¾åœ¨ä½ å·²ç¶“知é“å•題需è¦å ±å‘Šåˆ°å“ªè£ã€‚
如果是郵件列表,那麼一般在 `lore.kernel.org <https://lore.kernel.org/>`_ å¯ä»¥
找到相應存檔。
但有些列表é‹è¡Œåœ¨å…¶ä»–地方。例如å‰é¢æ­¥é©Ÿä¸­ç•¶ä¾‹å­çš„ath10k WiFi驅動程åºå°±æ˜¯é€™ç¨®
-情æ³ã€‚但是你通常å¯ä»¥åœ¨ç¶²ä¸Šå¾ˆå®¹æ˜“地找到這些列表的檔案。例如æœç´¢ã€Œarchive
-ath10k@lists.infradead.orgã€ï¼Œå°‡å¼•導您到ath10k郵件列表的信æ¯é ï¼Œè©²é é¢é ‚部連çµ
+情æ³ã€‚但是你通常å¯ä»¥åœ¨ç¶²ä¸Šå¾ˆå®¹æ˜“地找到這些列表的檔案。例如æœç´¢â€œarchive
+ath10k@lists.infradead.orgâ€ï¼Œå°‡å¼•導您到ath10k郵件列表的信æ¯é ï¼Œè©²é é¢é ‚éƒ¨éˆæŽ¥
到其 `列表存檔 <https://lists.infradead.org/pipermail/ath10k/>`_ ã€‚éºæ†¾çš„æ˜¯ï¼Œ
-é€™å€‹åˆ—è¡¨å’Œå…¶ä»–ä¸€äº›åˆ—è¡¨ç¼ºä¹æœç´¢å…¶å­˜æª”的功能。在這種情æ³ä¸‹å¯ä»¥ä½¿ç”¨å¸¸è¦çš„網際網路
-æœå°‹å¼•擎,並添加類似「site:lists.infadead.org/pipermail/ath10k/ã€é€™
-樣的æœç´¢æ¢ä»¶ï¼Œé€™æœƒæŠŠçµæžœé™åˆ¶åœ¨è©²é€£çµä¸­çš„æª”案。
+é€™å€‹åˆ—è¡¨å’Œå…¶ä»–ä¸€äº›åˆ—è¡¨ç¼ºä¹æœç´¢å…¶å­˜æª”的功能。在這種情æ³ä¸‹å¯ä»¥ä½¿ç”¨å¸¸è¦çš„互è¯ç¶²
+æœç´¢å¼•擎,並添加類似“site:lists.infadead.org/pipermail/ath10k/â€é€™
+樣的æœç´¢æ¢ä»¶ï¼Œé€™æœƒæŠŠçµæžœé™åˆ¶åœ¨è©²éˆæŽ¥ä¸­çš„æª”案。
-也請進一步æœç´¢ç¶²çµ¡ã€LKMLå’Œbugzilla.kernel.org網站。
+也請進一步æœç´¢ç¶²çµ¡ã€LKMLå’Œbugzilla.kernel.org網站。如果你的報告需è¦ç™¼é€åˆ°ç¼ºé™·
+跟蹤器中,那麼您å¯èƒ½é‚„éœ€è¦æª¢æŸ¥å­ç³»çµ±çš„郵件列表存檔,因爲å¯èƒ½æœ‰äººåªåœ¨é‚£è£å ±å‘Šäº†å®ƒã€‚
-有關如何æœç´¢ä»¥åŠåœ¨æ‰¾åˆ°åŒ¹é…報告時如何æ“作的詳細信æ¯ï¼Œè«‹åƒé–±ä¸Šé¢çš„「æœç´¢ç¾æœ‰å ±å‘Š
-(第一部分)ã€ã€‚
+有關如何æœç´¢ä»¥åŠåœ¨æ‰¾åˆ°åŒ¹é…報告時如何æ“作的詳細信æ¯ï¼Œè«‹åƒé–±ä¸Šé¢çš„“æœç´¢ç¾æœ‰å ±å‘Š
+(第一部分)â€ã€‚
-ä¸è¦æ€¥è‘—完æˆå ±å‘ŠéŽç¨‹çš„這一步:花30到60分é˜ç”šè‡³æ›´å¤šçš„æ™‚é–“å¯ä»¥çˆ²ä½ å’Œå…¶ä»–äººç¯€çœ /
+ä¸è¦æ€¥ç€å®Œæˆå ±å‘ŠéŽç¨‹çš„這一步:花30到60分é˜ç”šè‡³æ›´å¤šçš„æ™‚é–“å¯ä»¥çˆ²ä½ å’Œå…¶ä»–äººç¯€çœ /
減少相當多的時間和麻煩。
安è£ä¸€å€‹æ–°çš„內核進行測試
--------------------------
- *é™¤éžæ‚¨å·²ç¶“在é‹è¡Œæœ€æ–°çš„「主線ã€Linux內核,å¦å‰‡æœ€å¥½åœ¨å ±å‘Šæµç¨‹å‰å®‰è£å®ƒã€‚在
- æŸäº›æƒ…æ³ä¸‹ï¼Œä½¿ç”¨æœ€æ–°çš„「穩定版ã€Linux進行測試和報告也是å¯ä»¥æŽ¥å—的替代方案;
+ *é™¤éžæ‚¨å·²ç¶“在é‹è¡Œæœ€æ–°çš„“主線â€Linux內核,å¦å‰‡æœ€å¥½åœ¨å ±å‘Šæµç¨‹å‰å®‰è£å®ƒã€‚在
+ æŸäº›æƒ…æ³ä¸‹ï¼Œä½¿ç”¨æœ€æ–°çš„“穩定版â€Linux進行測試和報告也是å¯ä»¥æŽ¥å—的替代方案;
在åˆä½µçª—壿œŸé–“,這實際上å¯èƒ½æ˜¯æœ€å¥½çš„æ–¹æ³•,但在開發階段最好還是暫åœå¹¾å¤©ã€‚
- ç„¡è«–ä½ é¸æ“‡ä»€éº¼ç‰ˆæœ¬ï¼Œæœ€å¥½ä½¿ç”¨ã€Œæ™®é€šã€æ§‹å»ºã€‚忽略這些建議會大大增加您的報告
+ ç„¡è«–ä½ é¸æ“‡ä»€éº¼ç‰ˆæœ¬ï¼Œæœ€å¥½ä½¿ç”¨â€œæ™®é€šâ€æ§‹å»ºã€‚忽略這些建議會大大增加您的報告
被拒絕或忽略的風險。*
-正如第一步的詳細解釋中所æåˆ°çš„:與大多數程å¼è¨­è¨ˆå¸«ä¸€æ¨£ï¼Œèˆ‡å¤§å¤šæ•¸ç¨‹å¼è¨­è¨ˆå¸«ä¸€æ¨£ï¼ŒLinux
-內核開發人員ä¸å–œæ­¡èŠ±æ™‚é–“è™•ç†ä»–å€‘ç¶­è­·çš„åŽŸå§‹ç¢¼ä¸­æ ¹æœ¬ä¸æœƒç™¼ç”Ÿçš„å•題的報告。這隻
+正如第一步的詳細解釋中所æåˆ°çš„:與大多數程åºå“¡ä¸€æ¨£ï¼Œèˆ‡å¤§å¤šæ•¸ç¨‹åºå“¡ä¸€æ¨£ï¼ŒLinux
+內核開發人員ä¸å–œæ­¡èŠ±æ™‚é–“è™•ç†ä»–們維護的æºä»£ç¢¼ä¸­æ ¹æœ¬ä¸æœƒç™¼ç”Ÿçš„å•題的報告。這隻
會浪費æ¯å€‹äººçš„æ™‚間,尤其是你的時間。這就是爲什麼在報告å•題之å‰ï¼Œæ‚¨å¿…須先確èª
å•題ä»ç„¶å­˜åœ¨æ–¼æœ€æ–°çš„ä¸Šæ¸¸ä»£ç¢¼ä¸­ï¼Œé€™ç¬¦åˆæ¯å€‹äººçš„利益。您å¯ä»¥å¿½ç•¥æ­¤å»ºè­°ï¼Œä½†å¦‚å‰
æ‰€è¿°ï¼šé€™æ¨£åšæœƒæ¥µå¤§åœ°å¢žåŠ å•題報告被拒絕或被忽略的風險。
-內核「最新上游ã€çš„範åœé€šå¸¸æŒ‡ï¼š
+內核“最新上游â€çš„範åœé€šå¸¸æŒ‡ï¼š
* 安è£ä¸€å€‹ä¸»ç·šå…§æ ¸ï¼›æœ€æ–°çš„穩定版內核也å¯ä»¥æ˜¯ä¸€å€‹é¸æ“‡ï¼Œä½†å¤§å¤šæ•¸æ™‚候都最好é¿å…。
- 長期支æŒå…§æ ¸ï¼ˆæœ‰æ™‚稱爲「LTSå…§æ ¸ã€ï¼‰ä¸é©åˆæ­¤æµç¨‹ã€‚下一å°ç¯€å°‡æ›´è©³ç´°åœ°è§£é‡‹æ‰€æœ‰
+ 長期支æŒå…§æ ¸ï¼ˆæœ‰æ™‚稱爲“LTSå…§æ ¸â€ï¼‰ä¸é©åˆæ­¤æµç¨‹ã€‚下一å°ç¯€å°‡æ›´è©³ç´°åœ°è§£é‡‹æ‰€æœ‰
這些。
* 下一å°ç¯€æè¿°ç²å–和安è£é€™æ¨£ä¸€å€‹å…§æ ¸çš„æ–¹æ³•。它還指出了使用é ç·¨è­¯å…§æ ¸æ˜¯å¯ä»¥çš„,
- 但普通的內核更好,這æ„味著:它是直接使用從 `kernel.org <https://kernel.org/>`_
- ç²å¾—çš„Linux原始碼構建並且沒有任何方å¼ä¿®æ”¹æˆ–增強。
+ 但普通的內核更好,這æ„味ç€ï¼šå®ƒæ˜¯ç›´æŽ¥ä½¿ç”¨å¾ž `kernel.org <https://kernel.org/>`_
+ ç²å¾—çš„Linuxæºä»£ç¢¼æ§‹å»ºä¸¦ä¸”沒有任何方å¼ä¿®æ”¹æˆ–增強。
鏿“‡é©åˆæ¸¬è©¦çš„版本
~~~~~~~~~~~~~~~~~~~~
-å‰å¾€ `kernel.org <https://kernel.org/>`_ 來決定使用哪個版本。忽略那個寫著
-「Latest release最新版本ã€çš„巨大黃色按鈕,往下看有一個表格。在表格的頂部,你會
-看到一行以「mainlineã€é–‹é ­çš„字樣,大多數情æ³ä¸‹å®ƒæœƒæŒ‡å‘一個版本號類似「5.8-rc2ã€
-çš„é ç™¼å¸ƒç‰ˆæœ¬ã€‚如果是這樣的話,你將需è¦ä½¿ç”¨é€™å€‹ä¸»ç·šå…§æ ¸é€²è¡Œæ¸¬è©¦ã€‚ä¸è¦è®“「rcã€
-嚇到你,這些「開發版內核ã€å¯¦éš›ä¸Šéžå¸¸å¯é â€”—而且你已經按照上é¢çš„æŒ‡ç¤ºåšäº†å‚™ä»½ï¼Œ
+å‰å¾€ `kernel.org <https://kernel.org/>`_ 來決定使用哪個版本。忽略那個寫ç€
+“Latest release最新版本â€çš„巨大黃色按鈕,往下看有一個表格。在表格的頂部,你會
+看到一行以“mainlineâ€é–‹é ­çš„字樣,大多數情æ³ä¸‹å®ƒæœƒæŒ‡å‘一個版本號類似“5.8-rc2â€
+çš„é ç™¼ä½ˆç‰ˆæœ¬ã€‚如果是這樣的話,你將需è¦ä½¿ç”¨é€™å€‹ä¸»ç·šå…§æ ¸é€²è¡Œæ¸¬è©¦ã€‚ä¸è¦è®““rcâ€
+嚇到你,這些“開發版內核â€å¯¦éš›ä¸Šéžå¸¸å¯é â€”—而且你已經按照上é¢çš„æŒ‡ç¤ºåšäº†å‚™ä»½ï¼Œ
䏿˜¯å—Žï¼Ÿ
-大概æ¯ä¹åˆ°å周,「mainlineã€å¯èƒ½æœƒçµ¦ä½ æŒ‡å‡ºä¸€å€‹ç‰ˆæœ¬è™Ÿé¡žä¼¼ã€Œ5.7ã€çš„æ­£å¼ç‰ˆæœ¬ã€‚如果
-碰見這種情æ³ï¼Œè«‹è€ƒæ…®æš«åœå ±å‘ŠéŽç¨‹ï¼Œç›´åˆ°ä¸‹ä¸€å€‹ç‰ˆæœ¬çš„第一個é ç™¼å¸ƒï¼ˆ5.8-rc1)出
-ç¾åœ¨ `kernel.org <https://kernel.org/>`_ 上。這是因爲 Linux 的開發周期正在
-兩周的「åˆä½µçª—å£ã€å…§ã€‚大部分的改動和所有干擾性的改動都會在這段時間內被åˆä½µåˆ°
+大概æ¯ä¹åˆ°å週,“mainlineâ€å¯èƒ½æœƒçµ¦ä½ æŒ‡å‡ºä¸€å€‹ç‰ˆæœ¬è™Ÿé¡žä¼¼â€œ5.7â€çš„æ­£å¼ç‰ˆæœ¬ã€‚如果
+碰見這種情æ³ï¼Œè«‹è€ƒæ…®æš«åœå ±å‘ŠéŽç¨‹ï¼Œç›´åˆ°ä¸‹ä¸€å€‹ç‰ˆæœ¬çš„第一個é ç™¼ä½ˆï¼ˆ5.8-rc1)出
+ç¾åœ¨ `kernel.org <https://kernel.org/>`_ 上。這是因爲 Linux 的開發週期正在
+兩週的“åˆä½µçª—å£â€å…§ã€‚大部分的改動和所有干擾性的改動都會在這段時間內被åˆä½µåˆ°
下一個版本中。在此期間使用主線是比較å±éšªçš„。內核開發者通常也很忙,å¯èƒ½æ²’有
多餘的時間來處ç†å•題報告。這也是很有å¯èƒ½åœ¨åˆä½µçª—å£ä¸­æ‡‰ç”¨äº†è¨±å¤šä¿®æ”¹ä¾†ä¿®å¾©ä½ 
-所é¢è‡¨çš„å•é¡Œï¼›é€™å°±æ˜¯çˆ²ä»€éº¼ä½ å¾ˆå¿«å°±å¾—ç”¨ä¸€å€‹æ–°çš„å…§æ ¸ç‰ˆæœ¬é‡æ–°æ¸¬è©¦ï¼Œå°±åƒä¸‹é¢ã€Œç™¼
-布報告後的責任ã€ä¸€ç¯€ä¸­æ‰€è¿°çš„那樣。
+所é¢è‡¨çš„å•é¡Œï¼›é€™å°±æ˜¯çˆ²ä»€éº¼ä½ å¾ˆå¿«å°±å¾—ç”¨ä¸€å€‹æ–°çš„å…§æ ¸ç‰ˆæœ¬é‡æ–°æ¸¬è©¦ï¼Œå°±åƒä¸‹é¢â€œç™¼
+布報告後的責任â€ä¸€ç¯€ä¸­æ‰€è¿°çš„那樣。
-這就是爲什麼è¦ç­‰åˆ°åˆä½µçª—å£çµæŸå¾Œæ‰åŽ»åšã€‚但是如果你處ç†çš„æ˜¯ä¸€äº›ä¸æ‡‰è©²ç­‰å¾…çš„
+這就是爲什麼è¦ç­‰åˆ°åˆä½µçª—å£çµæŸå¾Œçº”去åšã€‚但是如果你處ç†çš„æ˜¯ä¸€äº›ä¸æ‡‰è©²ç­‰å¾…çš„
æ±è¥¿ï¼Œå‰‡ç„¡éœ€é€™æ¨£åšã€‚在這種情æ³ä¸‹ï¼Œå¯ä»¥è€ƒæ…®é€šéŽ git ç²å–最新的主線內核(見下
文),或者使用 kernel.org 上æä¾›çš„æœ€æ–°ç©©å®šç‰ˆæœ¬ã€‚如果 mainline 因爲æŸäº›åŽŸå› 
ä¸ç„¡æ³•正常工作,那麼使用它也是å¯ä»¥æŽ¥å—的。總的來說:用它來é‡ç¾å•題也比完全
@@ -657,7 +652,7 @@ ath10k@lists.infradead.orgã€ï¼Œå°‡å¼•導您到ath10k郵件列表的信æ¯é ï¼Œ
需è¦å…ˆåœ¨ä¸»ç·šä¿®å¾©ï¼Œç„¶å¾Œæ‰èƒ½å¾—到回傳,這å¯èƒ½éœ€è¦å¹¾å¤©æˆ–幾周。å¦ä¸€å€‹åŽŸå› æ˜¯ï¼šæ‚¨
å¸Œæœ›çš„ä¿®å¾©å°æ–¼å›žå‚³ä¾†èªªå¯èƒ½å¤ªé›£æˆ–å¤ªå†’éšªï¼›å› æ­¤å†æ¬¡å ±å‘Šå•題ä¸å¤ªå¯èƒ½æ”¹è®Šä»»ä½•事情。
-這些方é¢ä¹Ÿéƒ¨åˆ†è¡¨æ˜Žäº†çˆ²ä»€éº¼é•·æœŸæ”¯æŒå…§æ ¸ï¼ˆæœ‰æ™‚稱爲「LTSå…§æ ¸ã€ï¼‰ä¸é©åˆå ±å‘Šæµç¨‹ï¼š
+這些方é¢ä¹Ÿéƒ¨åˆ†è¡¨æ˜Žäº†çˆ²ä»€éº¼é•·æœŸæ”¯æŒå…§æ ¸ï¼ˆæœ‰æ™‚稱爲“LTSå…§æ ¸â€ï¼‰ä¸é©åˆå ±å‘Šæµç¨‹ï¼š
它們與當å‰ä»£ç¢¼çš„è·é›¢å¤ªé ã€‚å› æ­¤ï¼Œå…ˆåŽ»æ¸¬è©¦ä¸»ç·šï¼Œç„¶å¾Œå†æŒ‰æµç¨‹èµ°ï¼šå¦‚果主線沒有
出ç¾å•題,æµç¨‹å°‡æŒ‡å°Žæ‚¨å¦‚何在舊版本線中修復它。
@@ -669,31 +664,31 @@ ath10k@lists.infradead.orgã€ï¼Œå°‡å¼•導您到ath10k郵件列表的信æ¯é ï¼Œ
**使用é ç·¨è­¯çš„å…§æ ¸** ï¼šé€™å¾€å¾€æ˜¯æœ€å¿«é€Ÿã€æœ€ç°¡å–®ã€æœ€å®‰å…¨çš„æ–¹æ³•——尤其是在你ä¸ç†Ÿ
悉 Linux 內核的情æ³ä¸‹ã€‚å•題是:發行商或附加存儲庫æä¾›çš„大多數版本都是從修改
-éŽçš„LinuxåŽŸå§‹ç¢¼æ§‹å»ºçš„ã€‚å› æ­¤å®ƒå€‘ä¸æ˜¯æ™®é€šçš„,通常ä¸é©åˆæ–¼æ¸¬è©¦å’Œå•題報告:這些
+éŽçš„Linuxæºä»£ç¢¼æ§‹å»ºçš„ã€‚å› æ­¤å®ƒå€‘ä¸æ˜¯æ™®é€šçš„,通常ä¸é©åˆæ–¼æ¸¬è©¦å’Œå•題報告:這些
更改å¯èƒ½æœƒå°Žè‡´æ‚¨é¢è‡¨çš„å•題或以æŸç¨®æ–¹å¼å½±éŸ¿å•題。
但是如果您使用的是æµè¡Œçš„Linux發行版,那麼您就很幸é‹äº†ï¼šå°æ–¼å¤§éƒ¨åˆ†çš„發行版,
您å¯ä»¥åœ¨ç¶²ä¸Šæ‰¾åˆ°åŒ…嫿œ€æ–°ä¸»ç·šæˆ–穩定版本Linux內核包的存儲庫。使用這些是完全å¯
-以的,åªè¦å¾žå­˜å„²åº«çš„æè¿°ä¸­ç¢ºèªå®ƒå€‘是普通的或者至少接近普通。此外,請確ä¿è»Ÿé«”
-包包å«kernel.org上æä¾›çš„æœ€æ–°ç‰ˆæœ¬å…§æ ¸ã€‚如果這些軟體包的時間超éŽä¸€å‘¨ï¼Œé‚£éº¼å®ƒå€‘
-å¯èƒ½å°±ä¸åˆé©äº†ï¼Œå› çˆ²æ–°çš„主線和穩定版內核通常至少æ¯å‘¨ç™¼å¸ƒä¸€æ¬¡ã€‚
+以的,åªè¦å¾žå­˜å„²åº«çš„æè¿°ä¸­ç¢ºèªå®ƒå€‘是普通的或者至少接近普通。此外,請確ä¿è»Ÿä»¶
+包包å«kernel.org上æä¾›çš„æœ€æ–°ç‰ˆæœ¬å…§æ ¸ã€‚如果這些軟件包的時間超éŽä¸€é€±ï¼Œé‚£éº¼å®ƒå€‘
+å¯èƒ½å°±ä¸åˆé©äº†ï¼Œå› çˆ²æ–°çš„主線和穩定版內核通常至少æ¯é€±ç™¼ä½ˆä¸€æ¬¡ã€‚
請注æ„,您以後å¯èƒ½éœ€è¦æ‰‹å‹•æ§‹å»ºè‡ªå·±çš„å…§æ ¸ï¼šæœ‰æ™‚é€™æ˜¯èª¿è©¦æˆ–æ¸¬è©¦ä¿®å¾©ç¨‹åºæ‰€å¿…需的,
å¦‚å¾Œæ–‡æ‰€è¿°ã€‚é‚„è¦æ³¨æ„,é ç·¨è­¯çš„å…§æ ¸å¯èƒ½ç¼ºå°‘在出ç¾panicã€Oopsã€warning或BUG時
-解碼內核列å°çš„æ¶ˆæ¯æ‰€éœ€çš„調試符號;如果您計劃解碼這些消æ¯ï¼Œæœ€å¥½è‡ªå·±ç·¨è­¯å…§æ ¸
-(有關詳細信æ¯ï¼Œè«‹åƒé–±æœ¬å°ç¯€çµå°¾å’Œã€Œè§£ç¢¼å¤±æ•—ä¿¡æ¯ã€å°ç¯€ï¼‰ã€‚
+解碼內核打å°çš„æ¶ˆæ¯æ‰€éœ€çš„調試符號;如果您計劃解碼這些消æ¯ï¼Œæœ€å¥½è‡ªå·±ç·¨è­¯å…§æ ¸
+(有關詳細信æ¯ï¼Œè«‹åƒé–±æœ¬å°ç¯€çµå°¾å’Œâ€œè§£ç¢¼å¤±æ•—ä¿¡æ¯â€å°ç¯€ï¼‰ã€‚
**使用git** :熟悉 git 的開發者和有經驗的 Linux 用戶通常最好直接從
`kernel.org 上的官方開發倉庫
<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/>`_
-中ç²å–最新的 Linux 內核原始碼。這些很å¯èƒ½æ¯”最新的主線é ç™¼å¸ƒç‰ˆæœ¬æ›´æ–°ä¸€äº›ã€‚ä¸
-用擔心:它們和正å¼çš„é ç™¼å¸ƒç‰ˆæœ¬ä¸€æ¨£å¯é ï¼Œé™¤éžå…§æ ¸çš„é–‹ç™¼å‘¨æœŸç›®å‰æ­£è™•æ–¼åˆä½µçª—
+中ç²å–最新的 Linux å…§æ ¸æºä»£ç¢¼ã€‚這些很å¯èƒ½æ¯”最新的主線é ç™¼ä½ˆç‰ˆæœ¬æ›´æ–°ä¸€äº›ã€‚ä¸
+用擔心:它們和正å¼çš„é ç™¼ä½ˆç‰ˆæœ¬ä¸€æ¨£å¯é ï¼Œé™¤éžå…§æ ¸çš„é–‹ç™¼é€±æœŸç›®å‰æ­£è™•æ–¼åˆä½µçª—
å£ä¸­ã€‚ä¸éŽå³ä¾¿å¦‚此,它們也是相當å¯é çš„。
**å¸¸è¦æ–¹æ³•** :ä¸ç†Ÿæ‚‰ git 的人通常最好從 `kernel.org <https://kernel.org/>`_
下載æºç¢¼çš„tar 存檔包。
-如何實際構建一個內核並ä¸åœ¨é€™è£¡æè¿°ï¼Œå› çˆ²è¨±å¤šç¶²ç«™å·²ç¶“解釋了必è¦çš„æ­¥é©Ÿã€‚如果
+如何實際構建一個內核並ä¸åœ¨é€™è£æè¿°ï¼Œå› çˆ²è¨±å¤šç¶²ç«™å·²ç¶“解釋了必è¦çš„æ­¥é©Ÿã€‚如果
你是新手,å¯ä»¥è€ƒæ…®æŒ‰ç…§é‚£äº›å»ºè­°ä½¿ç”¨ ``make localmodconfig`` 來åšï¼Œå®ƒå°‡å˜—試ç²
å–ä½ ç•¶å‰å…§æ ¸çš„é…置,然後根據你的系統進行一些調整。這樣åšä¸¦ä¸èƒ½ä½¿ç·¨è­¯å‡ºä¾†çš„
內核更好,但å¯ä»¥æ›´å¿«åœ°ç·¨è­¯ã€‚
@@ -702,19 +697,19 @@ ath10k@lists.infradead.orgã€ï¼Œå°‡å¼•導您到ath10k郵件列表的信æ¯é ï¼Œ
啓用 CONFIG_KALLSYMS é¸é …。此外,還å¯ä»¥å•“用 CONFIG_DEBUG_KERNEL å’Œ
CONFIG_DEBUG_INFO;後者是相關é¸é …ï¼Œä½†åªæœ‰å•“用å‰è€…æ‰èƒ½é–‹å•“。請注æ„,
CONFIG_DEBUG_INFO æœƒéœ€è¦æ›´å¤šå„²å­˜ç©ºé–“來構建內核。但這是值得的,因爲這些é¸é …å°‡
-å…許您ç¨å¾Œç²¾ç¢ºå®šä½è§¸ç™¼å•題的確切代碼行。下é¢çš„「解碼失敗信æ¯ã€ä¸€ç¯€å°æ­¤é€²è¡Œäº†æ›´
+å…許您ç¨å¾Œç²¾ç¢ºå®šä½è§¸ç™¼å•題的確切代碼行。下é¢çš„“解碼失敗信æ¯â€ä¸€ç¯€å°æ­¤é€²è¡Œäº†æ›´
詳細的解釋。
但請記ä½ï¼šå§‹çµ‚記錄é‡åˆ°çš„å•題,以防難以é‡ç¾ã€‚ç™¼é€æœªè§£ç¢¼çš„報告總比ä¸å ±å‘Šè¦å¥½ã€‚
-æª¢æŸ¥ã€Œæ±™æŸ“ã€æ¨™èªŒ
+æª¢æŸ¥â€œæ±¡æŸ“â€æ¨™èªŒ
----------------
- *ç¢ºä¿æ‚¨å‰›å‰›å®‰è£çš„內核在é‹è¡Œæ™‚䏿œƒã€Œæ±™æŸ“ã€è‡ªå·±ã€‚*
+ *ç¢ºä¿æ‚¨å‰›å‰›å®‰è£çš„內核在é‹è¡Œæ™‚䏿œƒâ€œæ±¡æŸ“â€è‡ªå·±ã€‚*
正如上é¢å·²ç¶“詳細介紹éŽçš„:當發生一些å¯èƒ½æœƒå°Žè‡´ä¸€äº›çœ‹èµ·ä¾†å®Œå…¨ä¸ç›¸é—œçš„後續錯
-èª¤çš„äº‹æƒ…æ™‚ï¼Œå…§æ ¸æœƒè¨­ç½®ä¸€å€‹ã€Œæ±™æŸ“ã€æ¨™èªŒã€‚é€™å°±æ˜¯çˆ²ä»€éº¼ä½ éœ€è¦æª¢æŸ¥ä½ å‰›å‰›å®‰è£çš„å…§
+èª¤çš„äº‹æƒ…æ™‚ï¼Œå…§æ ¸æœƒè¨­ç½®ä¸€å€‹â€œæ±¡æŸ“â€æ¨™èªŒã€‚é€™å°±æ˜¯çˆ²ä»€éº¼ä½ éœ€è¦æª¢æŸ¥ä½ å‰›å‰›å®‰è£çš„å…§
æ ¸æ˜¯å¦æœ‰è¨­ç½®æ­¤æ¨™èªŒã€‚如果有的話,幾乎在任何情æ³ä¸‹ä½ éƒ½éœ€è¦åœ¨å ±å‘Šå•題之å‰å…ˆæ¶ˆ
除它。詳細的æ“作方法請看上é¢çš„章節。
@@ -729,43 +724,43 @@ CONFIG_DEBUG_INFO æœƒéœ€è¦æ›´å¤šå„²å­˜ç©ºé–“來構建內核。但這是值得çš
å¯ä»¥è€ƒæ…®ä½¿ç”¨æ­¤ç‰ˆæœ¬ç·šï¼Œæ”¾æ£„報告å•題。但是請記ä½ï¼Œåªè¦å®ƒæ²’有在 `kernel.org
<https://kernel.org/>`_ 的穩定版和長期版(以åŠç”±é€™äº›ç‰ˆæœ¬è¡ç”Ÿå‡ºä¾†çš„廠商內核)
中得到修復,其他用戶å¯èƒ½ä»ç„¶æœƒå—到它的困擾。如果你喜歡使用其中的一個,或
-è€…åªæ˜¯æƒ³å¹«åŠ©å®ƒå€‘çš„ç”¨æˆ¶ï¼Œè«‹å‰å¾€ä¸‹é¢çš„「報告åªç™¼ç”Ÿåœ¨è¼ƒèˆŠå…§æ ¸ç‰ˆæœ¬ç·šçš„å•題ã€ä¸€ç¯€ã€‚
+è€…åªæ˜¯æƒ³å¹«åŠ©å®ƒå€‘çš„ç”¨æˆ¶ï¼Œè«‹å‰å¾€ä¸‹é¢çš„“報告åªç™¼ç”Ÿåœ¨è¼ƒèˆŠå…§æ ¸ç‰ˆæœ¬ç·šçš„å•題â€ä¸€ç¯€ã€‚
優化復ç¾å•題的æè¿°
--------------------
- *優化你的筆記:試著找到並寫出最直接的復ç¾å•é¡Œçš„æ–¹æ³•ã€‚ç¢ºä¿æœ€çµ‚çµæžœåŒ…嫿‰€
+ *å„ªåŒ–ä½ çš„ç­†è¨˜ï¼šè©¦ç€æ‰¾åˆ°ä¸¦å¯«å‡ºæœ€ç›´æŽ¥çš„復ç¾å•é¡Œçš„æ–¹æ³•ã€‚ç¢ºä¿æœ€çµ‚çµæžœåŒ…嫿‰€
有é‡è¦çš„ç´°ç¯€ï¼ŒåŒæ™‚讓第一次è½èªªçš„人容易閱讀和ç†è§£ã€‚如果您在此éŽç¨‹ä¸­å­¸åˆ°
了一些æ±è¥¿ï¼Œè«‹è€ƒæ…®å†æ¬¡æœç´¢é—œæ–¼è©²å•é¡Œçš„ç¾æœ‰å ±å‘Šã€‚*
éŽæ–¼è¤‡é›œçš„報告會讓別人很難ç†è§£ã€‚å› æ­¤è«‹å„˜é‡æ‰¾åˆ°ä¸€å€‹å¯ä»¥ç›´æŽ¥æè¿°ã€æ˜“於以書é¢
å½¢å¼ç†è§£çš„å†ç¾æ–¹æ³•ã€‚åŒ…å«æ‰€æœ‰é‡è¦çš„ç´°ç¯€ï¼Œä½†åŒæ™‚也è¦å„˜é‡ä¿æŒç°¡çŸ­ã€‚
-在這在å‰é¢çš„æ­¥é©Ÿä¸­ï¼Œä½ å¾ˆå¯èƒ½å·²ç¶“了解了一些關於你所é¢è‡¨çš„å•題的點。利用這些
+在這在å‰é¢çš„æ­¥é©Ÿä¸­ï¼Œä½ å¾ˆå¯èƒ½å·²ç¶“瞭解了一些關於你所é¢è‡¨çš„å•題的點。利用這些
çŸ¥è­˜ï¼Œå†æ¬¡æœç´¢å¯ä»¥è½‰è€ŒåŠ å…¥çš„ç¾æœ‰å ±å‘Šã€‚
解碼失敗信æ¯
-------------
- *如果失敗涉åŠã€Œpanicã€ã€ã€ŒOopsã€ã€ã€Œwarningã€æˆ–「BUGã€ï¼Œè«‹è€ƒæ…®è§£ç¢¼å…§æ ¸æ—¥èªŒä»¥æŸ¥æ‰¾
+ *如果失敗涉åŠâ€œpanicâ€ã€â€œOopsâ€ã€â€œwarningâ€æˆ–“BUGâ€ï¼Œè«‹è€ƒæ…®è§£ç¢¼å…§æ ¸æ—¥èªŒä»¥æŸ¥æ‰¾
觸發錯誤的代碼行。*
-當內核檢測到內部å•題時,它會記錄一些有關已執行代碼的信æ¯ã€‚這使得在原始碼中精
+當內核檢測到內部å•題時,它會記錄一些有關已執行代碼的信æ¯ã€‚這使得在æºä»£ç¢¼ä¸­ç²¾
確定ä½è§¸ç™¼å•題的行並顯示如何調用它æˆçˆ²å¯èƒ½ã€‚ä½†åªæœ‰åœ¨é…置內核時啓用了
CONFIG_DEBUG_INFO å’Œ CONFIG_KALLSYMSé¸é …時,這種方法æ‰èµ·æ•ˆã€‚如果已啓用此é¸é …,
-請考慮解碼內核日誌中的信æ¯ã€‚這將使我們更容易ç†è§£æ˜¯ä»€éº¼å°Žè‡´äº†ã€Œpanicã€ã€ã€ŒOopsã€ã€
-「warningã€æˆ–「BUGã€ï¼Œå¾žè€Œå¢žåŠ äº†æœ‰äººæä¾›ä¿®å¾©çš„æ©ŸçŽ‡ã€‚
+請考慮解碼內核日誌中的信æ¯ã€‚這將使我們更容易ç†è§£æ˜¯ä»€éº¼å°Žè‡´äº†â€œpanicâ€ã€â€œOopsâ€ã€
+“warningâ€æˆ–“BUGâ€ï¼Œå¾žè€Œå¢žåŠ äº†æœ‰äººæä¾›ä¿®å¾©çš„幾率。
-解碼å¯ä»¥é€šéŽLinux原始碼樹中的腳本來完æˆã€‚如果您é‹è¡Œçš„內核是之å‰è‡ªå·±ç·¨è­¯çš„,
+解碼å¯ä»¥é€šéŽLinuxæºä»£ç¢¼æ¨¹ä¸­çš„腳本來完æˆã€‚如果您é‹è¡Œçš„內核是之å‰è‡ªå·±ç·¨è­¯çš„,
這樣這樣調用它::
[user@something ~]$ sudo dmesg | ./linux-5.10.5/scripts/decode_stacktrace.sh ./linux-5.10.5/vmlinux
/usr/lib/debug/lib/modules/5.10.10-4.1.x86_64/vmlinux /usr/src/kernels/5.10.10-4.1.x86_64/
如果您é‹è¡Œçš„æ˜¯æ‰“包好的普通內核,則å¯èƒ½éœ€è¦å®‰è£å¸¶æœ‰èª¿è©¦ç¬¦è™Ÿçš„相應包。然後按以下
-æ–¹å¼èª¿ç”¨è…³æœ¬ï¼ˆå¦‚果發行版未打包,則å¯èƒ½éœ€è¦å¾žLinux原始碼ç²å–)::
+æ–¹å¼èª¿ç”¨è…³æœ¬ï¼ˆå¦‚果發行版未打包,則å¯èƒ½éœ€è¦å¾žLinuxæºä»£ç¢¼ç²å–)::
[user@something ~]$ sudo dmesg | ./linux-5.10.5/scripts/decode_stacktrace.sh \
/usr/lib/debug/lib/modules/5.10.10-4.1.x86_64/vmlinux /usr/src/kernels/5.10.10-4.1.x86_64/
@@ -778,10 +773,10 @@ CONFIG_DEBUG_INFO å’Œ CONFIG_KALLSYMSé¸é …時,這種方法æ‰èµ·æ•ˆã€‚如果å
[ 68.387301] RIP: 0010:test_module_init (/home/username/linux-5.10.5/test-module/test-module.c:16) test_module
-在本例中,執行的代碼是從文件「~/linux-5.10.5/test-module/test-module.cã€æ§‹å»ºçš„,
+在本例中,執行的代碼是從文件“~/linux-5.10.5/test-module/test-module.câ€æ§‹å»ºçš„,
錯誤出ç¾åœ¨ç¬¬16行的指令中。
-該腳本也會如此解碼以「Call traceã€é–‹é ­çš„部分中æåˆ°çš„地å€ï¼Œè©²éƒ¨åˆ†é¡¯ç¤ºå‡ºç¾å•題的
+該腳本也會如此解碼以“Call traceâ€é–‹é ­çš„部分中æåˆ°çš„地å€ï¼Œè©²éƒ¨åˆ†é¡¯ç¤ºå‡ºç¾å•題的
函數的路徑。此外,腳本還會顯示內核正在執行的代碼部分的彙編輸出。
注æ„,如果你沒法åšåˆ°é€™ä¸€é»žï¼Œåªéœ€è·³éŽé€™ä¸€æ­¥ï¼Œä¸¦åœ¨å ±å‘Šä¸­èªªæ˜ŽåŽŸå› ã€‚å¦‚æžœä½ å¹¸é‹çš„
@@ -790,60 +785,60 @@ CONFIG_DEBUG_INFO å’Œ CONFIG_KALLSYMSé¸é …時,這種方法æ‰èµ·æ•ˆã€‚如果å
別擔心,如果您碰到的情æ³éœ€è¦é€™æ¨£åšï¼Œé–‹ç™¼äººå“¡æœƒå‘Šè¨´æ‚¨è©²æ€Žéº¼åšã€‚
-å°å›žæ­¸çš„特別關照
+å°è¿´æ­¸çš„特別關照
-----------------
- *如果您的å•題是回歸å•題,請儘å¯èƒ½ç¸®å°å¼•å…¥å•題時的範åœã€‚*
+ *如果您的å•題是迴歸å•題,請儘å¯èƒ½ç¸®å°å¼•å…¥å•題時的範åœã€‚*
Linux 首席開發者 Linus Torvalds èªçˆ² Linux 內核永é ä¸æ‡‰æƒ¡åŒ–,這就是爲什麼他
-èªçˆ²å›žæ­¸æ˜¯ä¸å¯æŽ¥å—的,並希望看到它們被迅速修復。這就是爲什麼引入了回歸的改
-動導致的å•題若無法通éŽå…¶ä»–æ–¹å¼å¿«é€Ÿè§£æ±ºï¼Œé€šå¸¸æœƒè¢«è¿…速撤銷。因此,報告回歸有
-點åƒã€ŒçŽ‹ç‚¸ã€ï¼Œæœƒè¿…速得到修復。但è¦åšåˆ°é€™ä¸€é»žï¼Œéœ€è¦çŸ¥é“導致回歸的變化。通常情
+èªçˆ²è¿´æ­¸æ˜¯ä¸å¯æŽ¥å—的,並希望看到它們被迅速修復。這就是爲什麼引入了迴歸的改
+動導致的å•題若無法通éŽå…¶ä»–æ–¹å¼å¿«é€Ÿè§£æ±ºï¼Œé€šå¸¸æœƒè¢«è¿…速撤銷。因此,報告迴歸有
+點åƒâ€œçŽ‹ç‚¸â€ï¼Œæœƒè¿…速得到修復。但è¦åšåˆ°é€™ä¸€é»žï¼Œéœ€è¦çŸ¥é“導致迴歸的變化。通常情
æ³ä¸‹ï¼Œè¦ç”±å ±å‘Šè€…來追查罪é­ç¦é¦–,因爲維護者往往沒有時間或手頭設置ä¸ä¾¿ä¾†è‡ªè¡Œ
é‡ç¾å®ƒã€‚
-有一個å«åšã€ŒäºŒåˆ†ã€çš„éŽç¨‹å¯ä»¥ä¾†å°‹æ‰¾è®ŠåŒ–,這在
-「Documentation/translations/zh_TW/admin-guide/bug-bisect.rstã€æ–‡æª”中進行了詳細
+有一個å«åšâ€œäºŒåˆ†â€çš„éŽç¨‹å¯ä»¥ä¾†å°‹æ‰¾è®ŠåŒ–,這在
+Documentation/translations/zh_CN/admin-guide/bug-bisect.rst 文檔中進行了詳細
çš„æè¿°ï¼Œé€™å€‹éŽç¨‹é€šå¸¸éœ€è¦ä½ æ§‹å»ºå到二å個內核é¡åƒï¼Œæ¯æ¬¡éƒ½å˜—試在構建下一個é¡åƒ
-之å‰é‡ç¾å•題。是的,這需è¦èŠ±è²»ä¸€äº›æ™‚é–“ï¼Œä½†ä¸ç”¨æ“”心,它比大多數人想åƒçš„è¦å¿«å¾—多。
-多虧了「binary searchäºŒé€²ä½æœç´¢ã€ï¼Œé€™å°‡å¼•導你在原始碼管ç†ç³»çµ±ä¸­æ‰¾åˆ°å°Žè‡´å›žæ­¸çš„æäº¤ã€‚
+之å‰é‡ç¾å•題。是的,這需è¦èŠ±è²»ä¸€äº›æ™‚é–“ï¼Œä½†ä¸ç”¨æ“”心,它比大多數人想象的è¦å¿«å¾—多。
+多虧了“binary search二分æœç´¢â€ï¼Œé€™å°‡å¼•導你在æºä»£ç¢¼ç®¡ç†ç³»çµ±ä¸­æ‰¾åˆ°å°Žè‡´è¿´æ­¸çš„æäº¤ã€‚
一旦你找到它,就在網上æœç´¢å…¶ä¸»é¡Œã€æäº¤ID和縮短的æäº¤ID(æäº¤IDçš„å‰12個字符)。
å¦‚æžœæœ‰çš„è©±ï¼Œé€™å°‡å¼•å°Žæ‚¨æ‰¾åˆ°é—œæ–¼å®ƒçš„ç¾æœ‰å ±å‘Šã€‚
éœ€è¦æ³¨æ„的是,二分法需è¦ä¸€é»žç«…é–€ï¼Œä¸æ˜¯æ¯å€‹äººéƒ½æ‡‚得訣竅,也需è¦ç›¸ç•¶å¤šçš„努力,
䏿˜¯æ¯å€‹äººéƒ½é¡˜æ„投入。儘管如此,還是強烈建議自己進行一次二分。如果你真的
-ä¸èƒ½æˆ–è€…ä¸æƒ³èµ°é€™æ¢è·¯ï¼Œè‡³å°‘è¦æ‰¾å‡ºæ˜¯å“ªå€‹ä¸»ç·šå…§æ ¸å¼•入的回歸。比如說從 5.5.15
+ä¸èƒ½æˆ–è€…ä¸æƒ³èµ°é€™æ¢è·¯ï¼Œè‡³å°‘è¦æ‰¾å‡ºæ˜¯å“ªå€‹ä¸»ç·šå…§æ ¸å¼•入的迴歸。比如說從 5.5.15
切æ›åˆ° 5.8.4 的時候出ç¾äº†ä¸€äº›å•題,那麼至少å¯ä»¥å˜—試一下相近的所有的主線版本
(5.6ã€5.7 å’Œ 5.8)來檢查它是什麼時候出ç¾çš„。除éžä½ æƒ³åœ¨ä¸€å€‹ç©©å®šç‰ˆæˆ–長期支æŒ
-內核中找到一個回歸,å¦å‰‡è¦é¿å…測試那些編號有三段的版本(5.6.12ã€5.7.8),因
-çˆ²é‚£æœƒä½¿çµæžœé›£ä»¥è§£é‡‹ï¼Œå¯èƒ½æœƒè®“你的測試變得無用。一旦你找到了引入回歸的主è¦
+內核中找到一個迴歸,å¦å‰‡è¦é¿å…測試那些編號有三段的版本(5.6.12ã€5.7.8),因
+çˆ²é‚£æœƒä½¿çµæžœé›£ä»¥è§£é‡‹ï¼Œå¯èƒ½æœƒè®“你的測試變得無用。一旦你找到了引入迴歸的主è¦
版本,就å¯ä»¥æ”¾å¿ƒåœ°ç¹¼çºŒå ±å‘Šäº†ã€‚但請記ä½ï¼šåœ¨ä¸çŸ¥é“罪é­ç¦é¦–的情æ³ä¸‹ï¼Œé–‹ç™¼äººå“¡
是å¦èƒ½å¤ æä¾›å¹«åЩ喿±ºæ–¼æ‰‹é ­çš„å•題。有時他們å¯èƒ½æœƒå¾žå ±å‘Šä¸­ç¢ºèªæ˜¯ä»€éº¼å‡ºç¾äº†å•
題,並能修復它;有時他們å¯èƒ½ç„¡æ³•æä¾›å¹«åŠ©ï¼Œé™¤éžä½ é€²è¡ŒäºŒåˆ†ã€‚
-當處ç†å›žæ­¸å•題時,請確ä¿ä½ æ‰€é¢è‡¨çš„å•é¡ŒçœŸçš„æ˜¯ç”±å…§æ ¸å¼•èµ·çš„ï¼Œè€Œä¸æ˜¯ç”±å…¶ä»–æ±è¥¿
+當處ç†è¿´æ­¸å•題時,請確ä¿ä½ æ‰€é¢è‡¨çš„å•é¡ŒçœŸçš„æ˜¯ç”±å…§æ ¸å¼•èµ·çš„ï¼Œè€Œä¸æ˜¯ç”±å…¶ä»–æ±è¥¿
引起的,如上文所述。
-在整個éŽç¨‹ä¸­ï¼Œè«‹è¨˜ä½ï¼šåªæœ‰ç•¶èˆŠå…§æ ¸å’Œæ–°å…§æ ¸çš„é…置相似時,å•題æ‰ç®—回歸。最好
-的方法是:把é…置文件(``.config``)從舊的工作內核直接複製到你嘗試的æ¯å€‹æ–°å…§
-核版本。之後é‹è¡Œ ``make oldnoconfig`` ä¾†èª¿æ•´å®ƒä»¥é©æ‡‰æ–°ç‰ˆæœ¬çš„需è¦ï¼Œè€Œä¸å•“用
-任何新的功能,因爲那些功能也å¯èƒ½å°Žè‡´å›žæ­¸ã€‚
+在整個éŽç¨‹ä¸­ï¼Œè«‹è¨˜ä½ï¼šåªæœ‰ç•¶èˆŠå…§æ ¸å’Œæ–°å…§æ ¸çš„é…置相似時,å•題纔算迴歸。這å¯ä»¥
+é€šéŽ ``make olddefconfig`` 來實ç¾ï¼Œè©³ç´°è§£é‡‹åƒè¦‹
+Documentation/admin-guide/reporting-regressions.rst ;它還æä¾›äº†å¤§é‡å…¶ä»–您
+å¯èƒ½å¸Œæœ›çž­è§£çš„æœ‰é—œå›žæ­¸çš„ä¿¡æ¯ã€‚
-撰寫並發é€å ±å‘Š
+撰寫併發é€å ±å‘Š
---------------
*通éŽè©³ç´°æè¿°å•題來開始編寫報告。記得包括以下æ¢ç›®ï¼šæ‚¨çˆ²å¾©ç¾è€Œå®‰è£çš„æœ€æ–°
內核版本ã€ä½¿ç”¨çš„Linux發行版以åŠé—œæ–¼å¦‚何復ç¾è©²å•題的說明。如果å¯èƒ½ï¼Œå°‡å…§
- 核構建é…置(.config)和 ``dmesg`` 的輸出放在網上的æŸå€‹åœ°æ–¹ï¼Œä¸¦é€£çµåˆ°å®ƒã€‚
+ 核構建é…置(.config)和 ``dmesg`` 的輸出放在網上的æŸå€‹åœ°æ–¹ï¼Œä¸¦éˆæŽ¥åˆ°å®ƒã€‚
åŒ…å«æˆ–上傳所有其他å¯èƒ½ç›¸é—œçš„ä¿¡æ¯ï¼Œå¦‚Oops的輸出/截圖或來自 ``lspci``
的輸出。一旦你寫完了這個主è¦éƒ¨åˆ†ï¼Œè«‹åœ¨ä¸Šæ–¹æ’入一個正常長度的段è½å¿«é€Ÿæ¦‚
è¿°å•題和影響。å†åœ¨æ­¤ä¹‹ä¸Šæ·»åŠ ä¸€å€‹ç°¡å–®æè¿°å•題的å¥å­ï¼Œä»¥å¾—到人們的閱讀。
ç¾åœ¨çµ¦å‡ºä¸€å€‹æ›´çŸ­çš„æè¿°æ€§æ¨™é¡Œæˆ–主題。然後就å¯ä»¥åƒMAINTAINERS文件告訴你的
- é‚£æ¨£ç™¼é€æˆ–æäº¤å ±å‘Šäº†ï¼Œé™¤éžä½ åœ¨è™•ç†ä¸€å€‹ã€Œé«˜å„ªå…ˆç´šå•題ã€ï¼šå®ƒå€‘éœ€è¦æŒ‰ç…§ä¸‹é¢
- 「高優先級å•題的特殊處ç†ã€æ‰€è¿°ç‰¹åˆ¥é—œç…§ã€‚*
+ é‚£æ¨£ç™¼é€æˆ–æäº¤å ±å‘Šäº†ï¼Œé™¤éžä½ åœ¨è™•ç†ä¸€å€‹â€œé«˜å„ªå…ˆç´šå•題â€ï¼šå®ƒå€‘éœ€è¦æŒ‰ç…§ä¸‹é¢
+ “高優先級å•題的特殊處ç†â€æ‰€è¿°ç‰¹åˆ¥é—œç…§ã€‚*
-ç¾åœ¨ä½ å·²ç¶“準備好了一切,是時候寫你的報告了。上文å‰è¨€ä¸­é€£çµçš„三篇文檔å°å¦‚何
+ç¾åœ¨ä½ å·²ç¶“準備好了一切,是時候寫你的報告了。上文å‰è¨€ä¸­éˆæŽ¥çš„三篇文檔å°å¦‚何
寫報告åšäº†éƒ¨åˆ†è§£é‡‹ã€‚é€™å°±æ˜¯çˆ²ä»€éº¼æœ¬æ–‡å°‡åªæåˆ°ä¸€äº›åŸºæœ¬çš„å…§å®¹ä»¥åŠ Linux 內核特
有的æ±è¥¿ã€‚
@@ -855,7 +850,7 @@ Linux 首席開發者 Linus Torvalds èªçˆ² Linux 內核永é ä¸æ‡‰æƒ¡åŒ–,這
æ¯ä»½å ±å‘Šéƒ½æ‡‰æåŠçš„事項
~~~~~~~~~~~~~~~~~~~~~~~~
-詳細æè¿°ä½ çš„å•題是如何發生在你安è£çš„æ–°ç´”淨內核上的。試著包å«ä½ ä¹‹å‰å¯«çš„和優
+詳細æè¿°ä½ çš„å•題是如何發生在你安è£çš„æ–°ç´”淨內核上的。試ç€åŒ…å«ä½ ä¹‹å‰å¯«çš„和優
化éŽçš„分步說明,概述你和其他人如何é‡ç¾é€™å€‹å•題;在極少數無法é‡ç¾çš„æƒ…æ³ä¸‹ï¼Œ
å„˜é‡æè¿°ä½ åšäº†ä»€éº¼ä¾†è§¸ç™¼å®ƒã€‚
@@ -864,19 +859,19 @@ Linux 首席開發者 Linus Torvalds èªçˆ² Linux 內核永é ä¸æ‡‰æƒ¡åŒ–,這
* ``cat /proc/version`` çš„è¼¸å‡ºï¼Œå…¶ä¸­åŒ…å« Linux 內核版本號和構建時的編譯器。
- * 機器正在é‹è¡Œçš„ Linux 發行版( ``hostnamectl | grep 「Operating System「`` )
+ * 機器正在é‹è¡Œçš„ Linux 發行版( ``hostnamectl | grep “Operating System“`` )
- * CPU 和作業系統的架構( ``uname -mi`` )
+ * CPU å’Œæ“作系統的架構( ``uname -mi`` )
- * 如果您正在處ç†å›žæ­¸ï¼Œä¸¦é€²è¡Œäº†äºŒåˆ†ï¼Œè«‹æåŠå°Žè‡´å›žæ­¸çš„變更的主題和æäº¤ID。
+ * 如果您正在處ç†è¿´æ­¸ï¼Œä¸¦é€²è¡Œäº†äºŒåˆ†ï¼Œè«‹æåŠå°Žè‡´è¿´æ­¸çš„變更的主題和æäº¤ID。
-許多情æ³ä¸‹ï¼Œè®“讀你報告的人多了解兩件事也是明智之舉:
+許多情æ³ä¸‹ï¼Œè®“讀你報告的人多瞭解兩件事也是明智之舉:
- * 用於構建 Linux 內核的é…置(「.configã€æ–‡ä»¶ï¼‰
+ * 用於構建 Linux 內核的é…置(“.configâ€æ–‡ä»¶ï¼‰
- * 內核的信æ¯ï¼Œä½ å¾ž ``dmesg`` 得到的信æ¯å¯«åˆ°ä¸€å€‹æ–‡ä»¶é‡Œã€‚確ä¿å®ƒä»¥åƒã€ŒLinux
+ * 內核的信æ¯ï¼Œä½ å¾ž ``dmesg`` 得到的信æ¯å¯«åˆ°ä¸€å€‹æ–‡ä»¶è£ã€‚確ä¿å®ƒä»¥åƒâ€œLinux
version 5.8-1 (foobar@example.com) (gcc (GCC) 10.2.1, GNU ld version
- 2.34) #1 SMP Mon Aug 3 14:54:37 UTC 2020ã€é€™æ¨£çš„行開始,如果沒有,那麼第
+ 2.34) #1 SMP Mon Aug 3 14:54:37 UTC 2020â€é€™æ¨£çš„行開始,如果沒有,那麼第
一次啓動階段的é‡è¦ä¿¡æ¯å·²ç¶“被丟棄了。在這種情æ³ä¸‹ï¼Œå¯ä»¥è€ƒæ…®ä½¿ç”¨
``journalctl -b 0 -k`` ;或者你也å¯ä»¥é‡å•“,é‡ç¾é€™å€‹å•題,然後調用
``dmesg`` 。
@@ -887,39 +882,39 @@ Linux 首席開發者 Linus Torvalds èªçˆ² Linux 內核永é ä¸æ‡‰æƒ¡åŒ–,這
* 將文件上傳到æŸå€‹å…¬é–‹çš„地方(你的網站,公共文件粘貼æœå‹™ï¼Œåœ¨
`bugzilla.kernel.org <https://bugzilla.kernel.org/>`_ 上創建的工單……),
- 並在你的報告中放上連çµã€‚ç†æƒ³æƒ…æ³ä¸‹è«‹ä½¿ç”¨å…許這些文件ä¿å­˜å¾ˆå¤šå¹´çš„地方,因
+ ä¸¦åœ¨ä½ çš„å ±å‘Šä¸­æ”¾ä¸ŠéŠæŽ¥ã€‚ç†æƒ³æƒ…æ³ä¸‹è«‹ä½¿ç”¨å…許這些文件ä¿å­˜å¾ˆå¤šå¹´çš„地方,因
爲它們å¯èƒ½åœ¨å¾ˆå¤šå¹´å¾Œå°åˆ¥äººæœ‰ç”¨ï¼›ä¾‹å¦‚ 5 年或 10 年後,一個開發者正在修改
一些代碼,而這些代碼正是爲了修復你的å•題。
- * 把文件放在一邊,然後說明你會在他人回復時å†å–®ç¨ç™¼é€ã€‚åªè¦è¨˜å¾—報告發出去後,
+ * 把文件放在一邊,然後說明你會在他人回覆時å†å–®ç¨ç™¼é€ã€‚åªè¦è¨˜å¾—報告發出去後,
真正åšåˆ°é€™ä¸€é»žå°±å¯ä»¥äº†ã€‚;-)
æä¾›é€™äº›æ±è¥¿å¯èƒ½æ˜¯æ˜Žæ™ºçš„
~~~~~~~~~~~~~~~~~~~~~~~~~~
-根據å•題的ä¸åŒï¼Œä½ å¯èƒ½éœ€è¦æä¾›æ›´å¤šçš„背景數據。這裡有一些關於æä¾›ä»€éº¼æ¯”較好
+根據å•題的ä¸åŒï¼Œä½ å¯èƒ½éœ€è¦æä¾›æ›´å¤šçš„èƒŒæ™¯æ•¸æ“šã€‚é€™è£æœ‰ä¸€äº›é—œæ–¼æä¾›ä»€éº¼æ¯”較好
的建議:
- * 如果你處ç†çš„æ˜¯å…§æ ¸çš„「warningã€ã€ã€ŒOOPSã€æˆ–「panicã€ï¼Œè«‹åŒ…å«å®ƒã€‚如果你ä¸èƒ½è¤‡è£½
- 粘貼它,試著用netconsole網絡終端é ç¨‹è·Ÿè¹¤æˆ–者至少æ‹ä¸€å¼µå±å¹•的照片。
+ * 如果你處ç†çš„æ˜¯å…§æ ¸çš„“warningâ€ã€â€œOOPSâ€æˆ–“panicâ€ï¼Œè«‹åŒ…å«å®ƒã€‚如果你ä¸èƒ½è¤‡è£½
+ 粘貼它,試ç€ç”¨netconsole網絡終端é ç¨‹è·Ÿè¹¤æˆ–者至少æ‹ä¸€å¼µå±å¹•的照片。
- * 如果å•題å¯èƒ½èˆ‡ä½ çš„電腦硬體有關,請說明你使用的是什麼系統。例如,如果你的
- 顝塿œ‰å•題,請æåŠå®ƒçš„製造商,顯å¡çš„型號,以åŠä½¿ç”¨çš„æ™¶ç‰‡ã€‚如果是筆記本電
- 腦,請æåŠå®ƒçš„型號å稱,但儘é‡ç¢ºä¿æ„義明確。例如「戴爾 XPS 13ã€å°±ä¸å¾ˆæ˜Žç¢ºï¼Œ
+ * 如果å•題å¯èƒ½èˆ‡ä½ çš„電腦硬件有關,請說明你使用的是什麼系統。例如,如果你的
+ 顝塿œ‰å•題,請æåŠå®ƒçš„製造商,顯å¡çš„型號,以åŠä½¿ç”¨çš„芯片。如果是筆記本電
+ 腦,請æåŠå®ƒçš„型號å稱,但儘é‡ç¢ºä¿æ„義明確。例如“戴爾 XPS 13â€å°±ä¸å¾ˆæ˜Žç¢ºï¼Œ
因爲它å¯èƒ½æ˜¯ 2012 年的那款,那款除了看起來和ç¾åœ¨éŠ·å”®çš„æ²’æœ‰ä»€éº¼ä¸åŒä¹‹å¤–,
兩者沒有任何共åŒä¹‹è™•。因此,在這種情æ³ä¸‹ï¼Œè¦åŠ ä¸Šæº–ç¢ºçš„åž‹è™Ÿï¼Œä¾‹å¦‚ 2019
- 年內推出的 XPS 13 型號爲「9380ã€æˆ–「7390ã€ã€‚åƒã€Œè¯æƒ³ Thinkpad T590ã€é€™æ¨£çš„åå­—
+ 年內推出的 XPS 13 型號爲“9380â€æˆ–“7390â€ã€‚åƒâ€œè¯æƒ³ Thinkpad T590â€é€™æ¨£çš„åå­—
也有些å«ç³Šä¸æ¸…:這款筆記本有帶ç¨ç«‹é¡¯å¡å’Œä¸å¸¶çš„å­åž‹è™Ÿï¼Œæ‰€ä»¥è¦å„˜é‡æ‰¾åˆ°æº–確
的型號å稱或註明主è¦éƒ¨ä»¶ã€‚
- * 說明正在使用的相關軟體。如果你在加載模塊時é‡åˆ°äº†å•題,你è¦èªªæ˜Žæ­£åœ¨ä½¿ç”¨çš„
+ * 說明正在使用的相關軟件。如果你在加載模塊時é‡åˆ°äº†å•題,你è¦èªªæ˜Žæ­£åœ¨ä½¿ç”¨çš„
kmodã€systemd å’Œ udev 的版本。如果其中一個 DRM 驅動出ç¾å•題,你è¦èªªæ˜Ž
libdrm å’Œ Mesa 的版本;還è¦èªªæ˜Žä½ çš„ Wayland åˆæˆå™¨æˆ– X-Server åŠå…¶é©…動。
如果你有文件系統å•題,請註明相應的文件系統實用程åºçš„版本(e2fsprogs,
btrfs-progs, xfsprogs……)。
* 從內核中收集å¯èƒ½æœ‰ç”¨çš„é¡å¤–ä¿¡æ¯ã€‚例如, ``lspci -nn`` 的輸出å¯ä»¥å¹«åŠ©åˆ¥äºº
- 識別你使用的硬體。如果你的硬體有å•題,你甚至å¯ä»¥çµ¦å‡º ``sudo lspci -vvv``
+ 識別你使用的硬件。如果你的硬件有å•題,你甚至å¯ä»¥çµ¦å‡º ``sudo lspci -vvv``
çš„çµæžœï¼Œå› çˆ²å®ƒæä¾›äº†çµ„件是如何é…置的信æ¯ã€‚å°æ–¼ä¸€äº›å•題,å¯èƒ½æœ€å¥½åŒ…å«
``/proc/cpuinfo`` , ``/proc/ioports`` , ``/proc/iomem`` ,
``/proc/modules`` 或 ``/proc/scsi/scsi`` 等文件的內容。一些å­ç³»çµ±é‚„æ
@@ -936,7 +931,7 @@ Linux 首席開發者 Linus Torvalds èªçˆ² Linux 內核永é ä¸æ‡‰æƒ¡åŒ–,這
~~~~~~~~~~~~~~~~~~~~~~
ç¾åœ¨ä½ å·²ç¶“準備好了報告的詳細部分,讓我們進入最é‡è¦çš„部分:開頭幾å¥ã€‚ç¾åœ¨åˆ°
-報告的最å‰é¢ï¼Œåœ¨ä½ å‰›æ‰å¯«çš„部分之å‰åŠ ä¸Šé¡žä¼¼ã€ŒThe detailed description:ã€ï¼ˆè©³ç´°
+報告的最å‰é¢ï¼Œåœ¨ä½ å‰›çº”寫的部分之å‰åŠ ä¸Šé¡žä¼¼â€œThe detailed description:â€ï¼ˆè©³ç´°
æè¿°ï¼‰é€™æ¨£çš„內容,並在最å‰é¢æ’入兩個新行。ç¾åœ¨å¯«ä¸€å€‹æ­£å¸¸é•·åº¦çš„æ®µè½ï¼Œå¤§è‡´æ¦‚
述這個å•題。去掉所有枯燥的細節,把é‡é»žæ”¾åœ¨è®€è€…需è¦çŸ¥é“的關éµéƒ¨åˆ†ï¼Œä»¥è®“人了
解這是怎麼回事;如果你èªçˆ²é€™å€‹ç¼ºé™·å½±éŸ¿äº†å¾ˆå¤šç”¨æˆ¶ï¼Œå°±æä¸€ä¸‹é€™é»žä¾†å¸å¼•大家關
@@ -946,10 +941,10 @@ Linux 首席開發者 Linus Torvalds èªçˆ² Linux 內核永é ä¸æ‡‰æƒ¡åŒ–,這
è¦æ›´åŠ æŠ½è±¡ï¼Œçˆ²å ±å‘Šå¯«ä¸€å€‹æ›´çŸ­çš„ä¸»é¡Œ/標題。
ç¾åœ¨ä½ å·²ç¶“寫好了這部分,請花點時間來優化它,因爲它是你的報告中最é‡è¦çš„部分:
-å¾ˆå¤šäººæœƒå…ˆè®€é€™éƒ¨åˆ†ï¼Œç„¶å¾Œæ‰æœƒæ±ºå®šæ˜¯å¦å€¼å¾—花時間閱讀其他部分。
+很多人會先讀這部分,然後纔會決定是å¦å€¼å¾—花時間閱讀其他部分。
ç¾åœ¨å°±åƒ :ref:`MAINTAINERS <maintainers>` ç¶­è­·è€…æ–‡ä»¶å‘Šè¨´ä½ çš„é‚£æ¨£ç™¼é€æˆ–æäº¤
-報告,除éžå®ƒæ˜¯å‰é¢æ¦‚述的那些「高優先級å•題ã€ä¹‹ä¸€ï¼šåœ¨é€™ç¨®æƒ…æ³ä¸‹ï¼Œè«‹å…ˆé–±è®€ä¸‹ä¸€
+報告,除éžå®ƒæ˜¯å‰é¢æ¦‚述的那些“高優先級å•題â€ä¹‹ä¸€ï¼šåœ¨é€™ç¨®æƒ…æ³ä¸‹ï¼Œè«‹å…ˆé–±è®€ä¸‹ä¸€
å°ç¯€ï¼Œç„¶å¾Œå†ç™¼é€å ±å‘Šã€‚
高優先級å•題的特殊處ç†
@@ -960,11 +955,19 @@ Linux 首席開發者 Linus Torvalds èªçˆ² Linux 內核永é ä¸æ‡‰æƒ¡åŒ–,這
**éžå¸¸åš´é‡çš„缺陷** :確ä¿åœ¨ä¸»é¡Œæˆ–工單標題以åŠç¬¬ä¸€æ®µä¸­æ˜Žé¡¯æ¨™å‡º severeness
(éžå¸¸åš´é‡çš„)。
-**回歸** :如果å•題是一個回歸,請在郵件的主題或缺陷跟蹤器的標題中添加
-[REGRESSION]。如果您沒有進行二分,請至少註明您測試的最新主線版本(比如 5.7)
-和出ç¾å•題的最新版本(比如 5.8)。如果您æˆåŠŸåœ°é€²è¡Œäº†äºŒåˆ†ï¼Œè«‹è¨»æ˜Žå°Žè‡´å›žæ­¸
-çš„æäº¤ID和主題。也請添加該變更的作者到你的報告中;如果您需è¦å°‡æ‚¨çš„缺陷æäº¤
-到缺陷跟蹤器中,請將報告以ç§äººéƒµä»¶çš„å½¢å¼è½‰ç™¼çµ¦ä»–,並註明報告æäº¤åœ°é»žã€‚
+**è¿´æ­¸** :報告的主題應以“[REGRESSION]â€é–‹é ­ã€‚
+
+如果您æˆåŠŸç”¨äºŒåˆ†æ³•å®šä½äº†å•題,請使用引入迴歸之更改的標題作爲主題的第二部分。
+請在報告中寫明“罪é­ç¦é¦–â€çš„æäº¤ID。如果未能æˆåŠŸäºŒåˆ†ï¼Œè«‹åœ¨å ±å‘Šä¸­è¬›æ˜Žæœ€å¾Œä¸€å€‹
+正常工作的版本(例如5.7)和最先發生å•題的版本(例如5.8-rc1)。
+
+通éŽéƒµä»¶ç™¼é€å ±å‘Šæ™‚,請抄é€Linux迴歸郵件列表(regressions@lists.linux.dev)。
+å¦‚æžœå ±å‘Šéœ€è¦æäº¤åˆ°æŸå€‹web追蹤器,請繼續æäº¤ï¼›ä¸¦åœ¨æäº¤å¾Œï¼Œé€šéŽéƒµä»¶å°‡å ±å‘Šè½‰ç™¼
+至迴歸列表;抄é€ç›¸é—œå­ç³»çµ±çš„維護人員和郵件列表。請確ä¿å ±å‘Šæ˜¯å…§è¯è½‰ç™¼çš„,ä¸è¦
+把它作爲附件。å¦å¤–請在頂部添加一個簡短的說明,在那è£å¯«ä¸Šå·¥å–®çš„ç¶²å€ã€‚
+
+在郵寄或轉發報告時,如果æˆåŠŸäºŒåˆ†ï¼Œéœ€è¦å°‡â€œç½ªé­ç¦é¦–â€çš„ä½œè€…æ·»åŠ åˆ°æ”¶ä»¶äººä¸­ï¼›åŒæ™‚
+抄é€signed-off-byéˆä¸­çš„æ¯å€‹äººï¼Œæ‚¨å¯ä»¥åœ¨æäº¤æ¶ˆæ¯çš„æœ«å°¾æ‰¾åˆ°ã€‚
**安全å•題** ï¼šå°æ–¼é€™ç¨®å•é¡Œï¼Œä½ å°‡å¿…é ˆè©•ä¼°ï¼šå¦‚æžœç´°ç¯€è¢«å…¬é–‹æŠ«éœ²ï¼Œæ˜¯å¦æœƒå°å…¶ä»–
ç”¨æˆ¶ç”¢ç”ŸçŸ­æœŸé¢¨éšªã€‚å¦‚æžœä¸æœƒï¼Œåªéœ€æŒ‰ç…§æ‰€è¿°ç¹¼çºŒå ±å‘Šå•題。如果有此風險,你需è¦
@@ -972,47 +975,47 @@ Linux 首席開發者 Linus Torvalds èªçˆ² Linux 內核永é ä¸æ‡‰æƒ¡åŒ–,這
* 如果 MAINTAINERS 文件指示您通éŽéƒµä»¶å ±å‘Šå•題,請ä¸è¦æŠ„é€ä»»ä½•公共郵件列表。
- * 如果你應該在缺陷跟蹤器中æäº¤å•題,請確ä¿å°‡å·¥å–®æ¨™è¨˜çˆ²ã€Œç§æœ‰ã€æˆ–「安全å•題ã€ã€‚
+ * 如果你應該在缺陷跟蹤器中æäº¤å•題,請確ä¿å°‡å·¥å–®æ¨™è¨˜çˆ²â€œç§æœ‰â€æˆ–“安全å•題â€ã€‚
如果缺陷跟蹤器沒有æä¾›ä¿æŒå ±å‘Šç§å¯†æ€§çš„æ–¹æ³•,那就別想了,把你的報告以ç§äºº
郵件的形å¼ç™¼é€çµ¦ç¶­è­·è€…å§ã€‚
-在這兩種情æ³ä¸‹ï¼Œéƒ½ä¸€å®šè¦å°‡å ±å‘Šç™¼åˆ° MAINTAINERS 文件中「安全è¯çµ¡ã€éƒ¨åˆ†åˆ—出的
+在這兩種情æ³ä¸‹ï¼Œéƒ½ä¸€å®šè¦å°‡å ±å‘Šç™¼åˆ° MAINTAINERS 文件中“安全è¯çµ¡â€éƒ¨åˆ†åˆ—出的
地å€ã€‚ç†æƒ³çš„æƒ…æ³æ˜¯åœ¨ç™¼é€å ±å‘Šçš„æ™‚候直接抄é€ä»–們。如果您在缺陷跟蹤器中æäº¤äº†
-報告,請將報告的文本轉發到這些地å€ï¼›ä½†è«‹åœ¨å ±å‘Šçš„頂部加上注釋,表明您æäº¤äº†
-報告,並附上工單連çµã€‚
+報告,請將報告的文本轉發到這些地å€ï¼›ä½†è«‹åœ¨å ±å‘Šçš„頂部加上註釋,表明您æäº¤äº†
+å ±å‘Šï¼Œä¸¦é™„ä¸Šå·¥å–®éˆæŽ¥ã€‚
-更多信æ¯è«‹åƒè¦‹ã€ŒDocumentation/translations/zh_TW/admin-guide/security-bugs.rstã€ã€‚
+更多信æ¯è«‹åƒè¦‹ Documentation/translations/zh_CN/admin-guide/security-bugs.rst 。
-發布報告後的責任
+發佈報告後的責任
------------------
*ç­‰å¾…åˆ¥äººçš„åæ‡‰ï¼Œç¹¼çºŒæŽ¨é€²äº‹æƒ…,直到你能夠接å—é€™æ¨£æˆ–é‚£æ¨£çš„çµæžœã€‚因此,請
å…¬é–‹å’ŒåŠæ™‚地回應任何詢å•。測試æå‡ºçš„ä¿®å¾©ã€‚ç©æ¥µåœ°æ¸¬è©¦ï¼šè‡³å°‘釿–°æ¸¬è©¦æ¯å€‹
新主線版本的首個候é¸ç‰ˆæœ¬ï¼ˆRCï¼‰ï¼Œä¸¦å ±å‘Šä½ çš„çµæžœã€‚å¦‚æžœå‡ºç¾æ‹–延,就å‹å¥½åœ°
- æé†’一下。如果你沒有得到任何幫助或者未能滿æ„,請試著自己幫助自己。*
+ æé†’一下。如果你沒有得到任何幫助或者未能滿æ„,請試ç€è‡ªå·±å¹«åŠ©è‡ªå·±ã€‚*
如果你的報告éžå¸¸å„ªç§€ï¼Œè€Œä¸”你真的很幸é‹ï¼Œé‚£éº¼æŸå€‹é–‹ç™¼è€…å¯èƒ½æœƒç«‹å³ç™¼ç¾å°Žè‡´å•
題的原因;然後他們å¯èƒ½æœƒå¯«ä¸€å€‹è£œä¸ä¾†ä¿®å¾©ã€æ¸¬è©¦å®ƒï¼Œä¸¦ç›´æŽ¥ç™¼é€çµ¦ä¸»ç·šé›†æˆï¼ŒåŒ
-時標記它以便以後回溯到需è¦å®ƒçš„穩定版和長期支æŒå…§æ ¸ã€‚那麼你需è¦åšçš„就是回復
-一å¥ã€ŒThank you very muchã€ï¼ˆéžå¸¸æ„Ÿè¬ï¼‰ï¼Œç„¶å¾Œåœ¨ç™¼å¸ƒå¾Œæ›ä¸Šä¿®å¾©å¥½çš„版本。
+時標記它以便以後回溯到需è¦å®ƒçš„穩定版和長期支æŒå…§æ ¸ã€‚那麼你需è¦åšçš„就是回覆
+一å¥â€œThank you very muchâ€ï¼ˆéžå¸¸æ„Ÿè¬ï¼‰ï¼Œç„¶å¾Œåœ¨ç™¼ä½ˆå¾Œæ›ä¸Šä¿®å¾©å¥½çš„版本。
-ä½†é€™ç¨®ç†æƒ³ç‹€æ³å¾ˆå°‘發生。這就是爲什麼你把報告拿出來之後工作æ‰é–‹å§‹ã€‚ä½ è¦åšçš„
-事情è¦è¦–情æ³è€Œå®šï¼Œä½†é€šå¸¸æœƒæ˜¯ä¸‹é¢åˆ—出的事情。但在深入研究細節之å‰ï¼Œé€™è£¡æœ‰å¹¾
+ä½†é€™ç¨®ç†æƒ³ç‹€æ³å¾ˆå°‘發生。這就是爲什麼你把報告拿出來之後工作纔開始。你è¦åšçš„
+事情è¦è¦–情æ³è€Œå®šï¼Œä½†é€šå¸¸æœƒæ˜¯ä¸‹é¢åˆ—出的事情。但在深入研究細節之å‰ï¼Œé€™è£æœ‰å¹¾
ä»¶é‡è¦çš„事情,你需è¦è¨˜ä½é€™éƒ¨åˆ†çš„éŽç¨‹ã€‚
關於進一步互動的一般建議
~~~~~~~~~~~~~~~~~~~~~~~~~~
-**總是公開回復** :當你在缺陷跟蹤器中æäº¤å•題時,一定è¦åœ¨é‚£è£¡å›žå¾©ï¼Œä¸è¦ç§ä¸‹
-è¯ç¹«ä»»ä½•é–‹ç™¼è€…ã€‚å°æ–¼éƒµä»¶å ±å‘Šï¼Œåœ¨å›žå¾©æ‚¨æ”¶åˆ°çš„任何郵件時,總是使用「全部回復ã€
+**總是公開回復** :當你在缺陷跟蹤器中æäº¤å•題時,一定è¦åœ¨é‚£è£å›žè¦†ï¼Œä¸è¦ç§ä¸‹
+è¯ç¹«ä»»ä½•é–‹ç™¼è€…ã€‚å°æ–¼éƒµä»¶å ±å‘Šï¼Œåœ¨å›žè¦†æ‚¨æ”¶åˆ°çš„任何郵件時,總是使用“全部回覆â€
功能。這包括帶有任何你å¯èƒ½æƒ³è¦æ·»åŠ åˆ°ä½ çš„å ±å‘Šä¸­çš„é¡å¤–數據的郵件:進入郵件應
-用程åºã€Œå·²ç™¼é€ã€æ–‡ä»¶å¤¾ï¼Œä¸¦åœ¨éƒµä»¶ä¸Šä½¿ç”¨ã€Œå…¨éƒ¨å›žå¾©ã€ä¾†å›žå¾©å ±å‘Šã€‚這種方法å¯ä»¥ç¢ºä¿
-公共郵件列表和其他所有åƒèˆ‡è€…éƒ½èƒ½åŠæ™‚了解情æ³ï¼›å®ƒé‚„èƒ½ä¿æŒéƒµä»¶ç·šç¨‹çš„完整性,
+用程åºâ€œå·²ç™¼é€â€æ–‡ä»¶å¤¾ï¼Œä¸¦åœ¨éƒµä»¶ä¸Šä½¿ç”¨â€œå…¨éƒ¨å›žè¦†â€ä¾†å›žå¾©å ±å‘Šã€‚這種方法å¯ä»¥ç¢ºä¿
+公共郵件列表和其他所有åƒèˆ‡è€…éƒ½èƒ½åŠæ™‚瞭解情æ³ï¼›å®ƒé‚„èƒ½ä¿æŒéƒµä»¶ç·šç¨‹çš„完整性,
這尿–¼éƒµä»¶åˆ—表將所有相關郵件歸爲一類是éžå¸¸é‡è¦çš„。
-åªæœ‰å…©ç¨®æƒ…æ³ä¸é©åˆåœ¨ç¼ºé™·è·Ÿè¹¤å™¨æˆ–「全部回復ã€ä¸­ç™¼è¡¨è©•論:
+åªæœ‰å…©ç¨®æƒ…æ³ä¸é©åˆåœ¨ç¼ºé™·è·Ÿè¹¤å™¨æˆ–“全部回覆â€ä¸­ç™¼è¡¨è©•論:
* 有人讓你ç§ä¸‹ç™¼æ±è¥¿ã€‚
@@ -1022,32 +1025,32 @@ Linux 首席開發者 Linus Torvalds èªçˆ² Linux 內核永é ä¸æ‡‰æƒ¡åŒ–,這
**在請求解釋或幫助之å‰å…ˆç ”究一下** :在這部分éŽç¨‹ä¸­ï¼Œæœ‰äººå¯èƒ½æœƒå‘Šè¨´ä½ ç”¨å°šæœª
掌æ¡çš„æŠ€èƒ½åšä¸€äº›äº‹æƒ…。例如你å¯èƒ½æœƒè¢«è¦æ±‚使用一些你從未è½èªªéŽçš„æ¸¬è©¦å·¥å…·ï¼›æˆ–
-者你å¯èƒ½æœƒè¢«è¦æ±‚在 Linux 內核原始碼上應用一個補ä¸ä¾†æ¸¬è©¦å®ƒæ˜¯å¦æœ‰å¹«åŠ©ã€‚åœ¨æŸäº›
-情æ³ä¸‹ï¼Œç™¼å€‹å›žå¾©è©¢å•如何åšå°±å¯ä»¥äº†ã€‚但在走這æ¢è·¯ä¹‹å‰ï¼Œå„˜é‡é€šéŽåœ¨ç¶²éš›ç¶²è·¯ä¸Šæœ
+者你å¯èƒ½æœƒè¢«è¦æ±‚在 Linux å…§æ ¸æºä»£ç¢¼ä¸Šæ‡‰ç”¨ä¸€å€‹è£œä¸ä¾†æ¸¬è©¦å®ƒæ˜¯å¦æœ‰å¹«åŠ©ã€‚åœ¨æŸäº›
+情æ³ä¸‹ï¼Œç™¼å€‹å›žè¦†è©¢å•如何åšå°±å¯ä»¥äº†ã€‚但在走這æ¢è·¯ä¹‹å‰ï¼Œå„˜é‡é€šéŽåœ¨äº’è¯ç¶²ä¸Šæœ
索自行找到答案;或者考慮在其他地方詢å•å»ºè­°ã€‚æ¯”å¦‚è©¢å•æœ‹å‹ï¼Œæˆ–者到你平時常去
çš„èŠå¤©å®¤æˆ–論壇發帖諮詢。
**è¦æœ‰è€å¿ƒ** :如果你真的很幸é‹ï¼Œä½ å¯èƒ½æœƒåœ¨å¹¾å€‹å°æ™‚內收到å°ä½ çš„報告的答覆。
但大多數情æ³ä¸‹æœƒèŠ±è²»æ›´å¤šçš„æ™‚é–“ï¼Œå› çˆ²ç¶­è­·è€…åˆ†æ•£åœ¨å…¨çƒå„地,因此å¯èƒ½åœ¨ä¸åŒçš„
-時å€â€”—在那裡他們已經享å—è‘—é é›¢éµç›¤çš„夜晚。
+時å€â€”—在那è£ä»–們已經享å—ç€é é›¢éµç›¤çš„夜晚。
一般來說,內核開發者需è¦ä¸€åˆ°äº”個工作日來回復報告。有時會花費更長的時間,因
爲他們å¯èƒ½æ­£å¿™æ–¼åˆä½µçª—å£ã€å…¶ä»–工作ã€åƒåŠ é–‹ç™¼è€…æœƒè­°ï¼Œæˆ–è€…åªæ˜¯åœ¨äº«å—一個漫長
的暑å‡ã€‚
-「高優先級的å•題ã€ï¼ˆè¦‹ä¸Šé¢çš„解釋)例外:維護者應該儘快解決這些å•題;這就是爲
+“高優先級的å•題â€ï¼ˆè¦‹ä¸Šé¢çš„解釋)例外:維護者應該儘快解決這些å•題;這就是爲
什麼你應該最多等待一個星期(如果是緊急的事情,則åªéœ€å…©å¤©ï¼‰ï¼Œç„¶å¾Œå†ç™¼é€å‹å¥½
çš„æé†’。
-有時維護者å¯èƒ½æ²’æœ‰åŠæ™‚回復;有時候å¯èƒ½æœƒå‡ºç¾åˆ†æ­§ï¼Œä¾‹å¦‚一個å•題是å¦ç¬¦åˆå›žæ­¸
+有時維護者å¯èƒ½æ²’æœ‰åŠæ™‚回覆;有時候å¯èƒ½æœƒå‡ºç¾åˆ†æ­§ï¼Œä¾‹å¦‚一個å•題是å¦ç¬¦åˆè¿´æ­¸
çš„æ¢ä»¶ã€‚在這種情æ³ä¸‹ï¼Œåœ¨éƒµä»¶åˆ—表上æå‡ºä½ çš„顧慮,並請求其他人公開或ç§ä¸‹å›žå¾©
如何繼續推進。如果失敗了,å¯èƒ½æ‡‰è©²è®“更高級別的維護者介入。如果是 WiFi 驅動,
那就是無線維護者;如果沒有更高級別的維護者,或者其他一切努力都失敗了,那
這å¯èƒ½æ˜¯ä¸€ç¨®ç½•見的ã€å¯ä»¥è®“ Linus Torvalds åƒèˆ‡é€²ä¾†çš„æƒ…æ³ã€‚
-**主動測試** :æ¯ç•¶ä¸€å€‹æ–°çš„主線內核版本的第一個é ç™¼å¸ƒç‰ˆæœ¬ï¼ˆrc1)發布的時候,
+**主動測試** :æ¯ç•¶ä¸€å€‹æ–°çš„主線內核版本的第一個é ç™¼ä½ˆç‰ˆæœ¬ï¼ˆrc1)發佈的時候,
去檢查一下這個å•題是å¦å¾—åˆ°äº†è§£æ±ºï¼Œæˆ–è€…æ˜¯å¦æœ‰ä»€éº¼é‡è¦çš„變化。在工單中或在
-回復報告的郵件中æåŠçµæžœï¼ˆç¢ºä¿æ‰€æœ‰åƒèˆ‡è¨Žè«–的人都被抄é€ï¼‰ã€‚這將表明你的承諾
+回覆報告的郵件中æåŠçµæžœï¼ˆç¢ºä¿æ‰€æœ‰åƒèˆ‡è¨Žè«–的人都被抄é€ï¼‰ã€‚這將表明你的承諾
和你願æ„幫忙。如果å•題æŒçºŒå­˜åœ¨ï¼Œå®ƒä¹Ÿæœƒæé†’開發者確ä¿ä»–們䏿œƒå¿˜è¨˜å®ƒã€‚其他一
些ä¸å®šæœŸçš„釿–°æ¸¬è©¦ï¼ˆä¾‹å¦‚用rc3ã€rc5 和最終版本)也是一個好主æ„ï¼Œä½†åªæœ‰åœ¨ç›¸é—œ
çš„æ±è¥¿ç™¼ç”Ÿè®ŠåŒ–或者你正在寫什麼æ±è¥¿çš„æ™‚候æ‰å ±å‘Šä½ çš„çµæžœã€‚
@@ -1057,10 +1060,10 @@ Linux 首席開發者 Linus Torvalds èªçˆ² Linux 內核永é ä¸æ‡‰æƒ¡åŒ–,這
查詢和測試請求
~~~~~~~~~~~~~~~
-如果你的報告得到了回復則需履行以下責任:
+如果你的報告得到了回覆則需履行以下責任:
**檢查與你打交é“的人** :大多數情æ³ä¸‹ï¼Œæœƒæ˜¯ç¶­è­·è€…或特定代碼å€åŸŸçš„開發人員å°
-你的報告åšå‡ºå›žæ‡‰ã€‚但由於å•題通常是公開報告的,所以回復的å¯èƒ½æ˜¯ä»»ä½•人——包括
+你的報告åšå‡ºå›žæ‡‰ã€‚但由於å•題通常是公開報告的,所以回覆的å¯èƒ½æ˜¯ä»»ä½•人——包括
那些想è¦å¹«å¿™çš„人,但最後å¯èƒ½æœƒç”¨ä»–們的å•題或請求引導你完全å離軌é“。這很少
ç™¼ç”Ÿï¼Œä½†é€™æ˜¯å¿«é€Ÿä¸Šç¶²æœæœçœ‹ä½ æ­£åœ¨èˆ‡èª°äº’動是明智之舉的許多原因之一。通éŽé€™æ¨£
åšï¼Œä½ ä¹Ÿå¯ä»¥çŸ¥é“你的報告是å¦è¢«æ­£ç¢ºçš„人è½åˆ°ï¼Œå› çˆ²å¦‚果討論沒有導致滿æ„çš„å•題
@@ -1086,63 +1089,63 @@ Linux 首席開發者 Linus Torvalds èªçˆ² Linux 內核永é ä¸æ‡‰æƒ¡åŒ–,這
å ±å‘Šåˆ°é”æ™‚,維護者剛剛離開éµç›¤ä¸€æ®µæ™‚間,或者有更é‡è¦çš„事情è¦è™•ç†ã€‚在寫æé†’
信的時候,è¦å–„æ„地å•一下,是å¦é‚„需è¦ä½ é€™é‚Šæä¾›ä»€éº¼ä¾†è®“äº‹æƒ…æŽ¨é€²ä¸‹åŽ»ã€‚å¦‚æžœå ±
告是通éŽéƒµä»¶ç™¼å‡ºä¾†çš„,那就在郵件的第一行回覆你的åˆå§‹éƒµä»¶ï¼ˆè¦‹ä¸Šæ–‡ï¼‰ï¼Œå…¶ä¸­åŒ…
-括下方的原始報告的完整引用:這是少數幾種情æ³ä¸‹ï¼Œé€™æ¨£çš„「TOFUã€ï¼ˆText Over,
+括下方的原始報告的完整引用:這是少數幾種情æ³ä¸‹ï¼Œé€™æ¨£çš„“TOFUâ€ï¼ˆText Over,
Fullquote Underæ–‡å­—åœ¨ä¸Šï¼Œå®Œæ•´å¼•ç”¨åœ¨ä¸‹ï¼‰æ˜¯æ­£ç¢ºçš„åšæ³•,因爲這樣所有的收件人都
會以é©ç•¶çš„é †åºç«‹å³è®“細節到手頭上來。
-在æé†’之後,å†ç­‰ä¸‰å‘¨çš„回覆。如果你ä»ç„¶æ²’有得到é©ç•¶çš„åé¥‹ï¼Œä½ é¦–å…ˆæ‡‰è©²é‡æ–°è€ƒ
+在æé†’之後,å†ç­‰ä¸‰é€±çš„回覆。如果你ä»ç„¶æ²’有得到é©ç•¶çš„åé¥‹ï¼Œä½ é¦–å…ˆæ‡‰è©²é‡æ–°è€ƒ
慮你的方法。你是å¦å¯èƒ½å˜—è©¦æŽ¥è§¸äº†éŒ¯èª¤çš„äººï¼Ÿæ˜¯ä¸æ˜¯å ±å‘Šä¹Ÿè¨±ä»¤äººå感或者太混亂,
以至於人們決定完全é é›¢å®ƒï¼ŸæŽ’除這些因素的最好方法是:把報告給一兩個熟悉
FLOSS å•題報告的人看,詢å•他們的æ„è¦‹ã€‚åŒæ™‚徵求他們關於如何繼續推進的建議。
-這å¯èƒ½æ„味著:準備一份更好的報告,讓這些人在你發出去之å‰å°å®ƒé€²è¡Œå¯©æŸ¥ã€‚這樣
+這å¯èƒ½æ„味ç€ï¼šæº–備一份更好的報告,讓這些人在你發出去之å‰å°å®ƒé€²è¡Œå¯©æŸ¥ã€‚這樣
的方法完全å¯ä»¥ï¼›åªéœ€èªªæ˜Žé€™æ˜¯é—œæ–¼é€™å€‹å•題的第二份改進的報告,並附上第一份報
-告的連çµã€‚
+å‘Šçš„éˆæŽ¥ã€‚
如果報告是æ°ç•¶çš„,你å¯ä»¥ç™¼é€ç¬¬äºŒå°æé†’信;在其中詢å•爲什麼報告沒有得到任何
-å›žå¾©ã€‚ç¬¬äºŒå°æé†’éƒµä»¶çš„å¥½æ™‚æ©Ÿæ˜¯åœ¨æ–° Linux 內核版本的首個é ç™¼å¸ƒç‰ˆæœ¬ï¼ˆ'rc1')
-發布後ä¸ä¹…ï¼Œå› çˆ²ç„¡è«–å¦‚ä½•ä½ éƒ½æ‡‰è©²åœ¨é‚£å€‹æ™‚å€™é‡æ–°æ¸¬è©¦ä¸¦æä¾›ç‹€æ…‹æ›´æ–°ï¼ˆè¦‹ä¸Šæ–‡ï¼‰ã€‚
+å›žè¦†ã€‚ç¬¬äºŒå°æé†’éƒµä»¶çš„å¥½æ™‚æ©Ÿæ˜¯åœ¨æ–° Linux 內核版本的首個é ç™¼ä½ˆç‰ˆæœ¬ï¼ˆ'rc1')
+發佈後ä¸ä¹…ï¼Œå› çˆ²ç„¡è«–å¦‚ä½•ä½ éƒ½æ‡‰è©²åœ¨é‚£å€‹æ™‚å€™é‡æ–°æ¸¬è©¦ä¸¦æä¾›ç‹€æ…‹æ›´æ–°ï¼ˆè¦‹ä¸Šæ–‡ï¼‰ã€‚
-如果第二次æé†’çš„çµæžœåˆåœ¨ä¸€å‘¨å…§æ²’æœ‰ä»»ä½•åæ‡‰ï¼Œå¯ä»¥å˜—試è¯ç¹«ä¸Šç´šç¶­è­·è€…è©¢å•æ„見:
+如果第二次æé†’çš„çµæžœåˆåœ¨ä¸€é€±å…§æ²’æœ‰ä»»ä½•åæ‡‰ï¼Œå¯ä»¥å˜—試è¯ç¹«ä¸Šç´šç¶­è­·è€…è©¢å•æ„見:
å³ä½¿å†å¿™çš„ç¶­è­·è€…åœ¨é€™æ™‚å€™ä¹Ÿè‡³å°‘æ‡‰è©²ç™¼éŽæŸç¨®ç¢ºèªã€‚
記ä½è¦åšå¥½å¤±æœ›çš„æº–å‚™ï¼šç†æƒ³ç‹€æ³ä¸‹ç¶­è­·è€…æœ€å¥½å°æ¯ä¸€å€‹å•題報告åšå‡ºå›žæ‡‰ï¼Œä½†ä»–們
-åªæœ‰ç¾©å‹™è§£æ±ºä¹‹å‰åˆ—出的「高優先級å•題ã€ã€‚所以,如果你得到的回覆是「è¬è¬ä½ çš„報告,
-æˆ‘ç›®å‰æœ‰æ›´é‡è¦çš„å•題è¦è™•ç†ï¼Œåœ¨å¯é è¦‹çš„æœªä¾†æ²’有時間去研究這個å•題ã€ï¼Œé‚£è«‹ä¸
+åªæœ‰ç¾©å‹™è§£æ±ºä¹‹å‰åˆ—出的“高優先級å•題â€ã€‚所以,如果你得到的回覆是“è¬è¬ä½ çš„報告,
+æˆ‘ç›®å‰æœ‰æ›´é‡è¦çš„å•題è¦è™•ç†ï¼Œåœ¨å¯é è¦‹çš„æœªä¾†æ²’有時間去研究這個å•題â€ï¼Œé‚£è«‹ä¸
è¦å¤ªæ²®å–ªã€‚
也有å¯èƒ½åœ¨ç¼ºé™·è·Ÿè¹¤å™¨æˆ–列表中進行了一些討論之後,什麼都沒有發生,æé†’也無助
於激勵大家進行修復。這種情æ³å¯èƒ½æ˜¯æ¯€æ»…性的,但在 Linux 內核開發中確實會發生。
-這些和其他得ä¸åˆ°å¹«åŠ©çš„åŽŸå› åœ¨æœ¬æ–‡çµå°¾è™•的「爲什麼有些å•題在被報告後沒有得到
-任何回應或者ä»ç„¶æ²’有修復ã€ä¸­é€²è¡Œäº†è§£é‡‹ã€‚
+這些和其他得ä¸åˆ°å¹«åŠ©çš„åŽŸå› åœ¨æœ¬æ–‡çµå°¾è™•的“爲什麼有些å•題在被報告後沒有得到
+任何回應或者ä»ç„¶æ²’有修復â€ä¸­é€²è¡Œäº†è§£é‡‹ã€‚
如果你沒有得到任何幫助或å•題最終沒有得到解決,ä¸è¦æ²®å–ªï¼šLinux 內核是 FLOSS,
-因此你ä»ç„¶å¯ä»¥è‡ªå·±å¹«åŠ©è‡ªå·±ã€‚ä¾‹å¦‚ï¼Œä½ å¯ä»¥è©¦è‘—找到其他å—影響的人,和他們一
+因此你ä»ç„¶å¯ä»¥è‡ªå·±å¹«åŠ©è‡ªå·±ã€‚ä¾‹å¦‚ï¼Œä½ å¯ä»¥è©¦ç€æ‰¾åˆ°å…¶ä»–å—影響的人,和他們一
èµ·åˆä½œä¾†è§£æ±ºé€™å€‹å•題。這樣的團隊å¯ä»¥ä¸€èµ·æº–備一份新的報告,æåˆ°åœ˜éšŠæœ‰å¤šå°‘人,
爲什麼你們èªçˆ²é€™æ˜¯æ‡‰è©²å¾—到解決的事情。也許你們還å¯ä»¥ä¸€èµ·ç¸®å°ç¢ºåˆ‡åŽŸå› æˆ–å¼•
-å…¥å›žæ­¸çš„è®ŠåŒ–ï¼Œé€™å¾€å¾€æœƒä½¿ä¿®å¾©æ›´å®¹æ˜“ã€‚è€Œä¸”å¦‚æžœé‹æ°£å¥½çš„話,團隊中å¯èƒ½æœƒæœ‰æ‡‚點
-編程的人,也許能寫出一個修複方案。
+å…¥è¿´æ­¸çš„è®ŠåŒ–ï¼Œé€™å¾€å¾€æœƒä½¿ä¿®å¾©æ›´å®¹æ˜“ã€‚è€Œä¸”å¦‚æžœé‹æ°£å¥½çš„話,團隊中å¯èƒ½æœƒæœ‰æ‡‚點
+編程的人,也許能寫出一個修復方案。
-「報告穩定版和長期支æŒå…§æ ¸ç·šçš„回歸ã€çš„åƒè€ƒ
+“報告穩定版和長期支æŒå…§æ ¸ç·šçš„è¿´æ­¸â€çš„åƒè€ƒ
------------------------------------------
-本å°ç¯€æä¾›äº†åœ¨ç©©å®šç‰ˆå’Œé•·æœŸæ”¯æŒå…§æ ¸ç·šä¸­é¢å°å›žæ­¸æ™‚需è¦åŸ·è¡Œçš„æ­¥é©Ÿçš„詳細信æ¯ã€‚
+本å°ç¯€æä¾›äº†åœ¨ç©©å®šç‰ˆå’Œé•·æœŸæ”¯æŒå…§æ ¸ç·šä¸­é¢å°è¿´æ­¸æ™‚需è¦åŸ·è¡Œçš„æ­¥é©Ÿçš„詳細信æ¯ã€‚
確ä¿ç‰¹å®šç‰ˆæœ¬ç·šä»ç„¶å—支æŒ
~~~~~~~~~~~~~~~~~~~~~~~~~
*檢查內核開發人員是å¦ä»ç„¶ç¶­è­·ä½ é—œå¿ƒçš„Linux內核版本線:去 kernel.org çš„
- 首é ï¼Œç¢ºä¿æ­¤ç‰¹å®šç‰ˆæœ¬ç·šçš„æœ€æ–°ç‰ˆæ²’有「[EOL]ã€æ¨™è¨˜ã€‚*
+ 首é ï¼Œç¢ºä¿æ­¤ç‰¹å®šç‰ˆæœ¬ç·šçš„æœ€æ–°ç‰ˆæ²’有“[EOL]â€æ¨™è¨˜ã€‚*
å¤§å¤šæ•¸å…§æ ¸ç‰ˆæœ¬ç·šåªæ”¯æŒä¸‰å€‹æœˆå·¦å³ï¼Œå› çˆ²å»¶é•·ç¶­è­·æ™‚間會帶來相當多的工作。因此,
æ¯å¹´åªæœƒé¸æ“‡ä¸€å€‹ç‰ˆæœ¬ä¾†æ”¯æŒè‡³å°‘å…©å¹´ï¼ˆé€šå¸¸æ˜¯å…­å¹´ï¼‰ã€‚é€™å°±æ˜¯çˆ²ä»€éº¼ä½ éœ€è¦æª¢æŸ¥
內核開發者是å¦é‚„支æŒä½ é—œå¿ƒçš„版本線。
-注æ„,如果 `kernel.org <https://kernel.org/>`_ 在首é ä¸Šåˆ—出了兩個「穩定ã€ç‰ˆæœ¬ï¼Œ
+注æ„,如果 `kernel.org <https://kernel.org/>`_ 在首é ä¸Šåˆ—出了兩個“穩定â€ç‰ˆæœ¬ï¼Œ
你應該考慮切æ›åˆ°è¼ƒæ–°çš„版本,而忘掉較舊的版本:å°å®ƒçš„æ”¯æŒå¯èƒ½å¾ˆå¿«å°±æœƒçµæŸã€‚
-ç„¶å¾Œï¼Œå®ƒå°‡è¢«æ¨™è¨˜çˆ²ã€Œç”Ÿå‘½å‘¨æœŸçµæŸã€ï¼ˆEOL)。é”到這個程度的版本線ä»ç„¶æœƒåœ¨
-`kernel.org <https://kernel.org/>`_ 首é ä¸Šè¢«é¡¯ç¤ºä¸€å…©å‘¨ï¼Œä½†ä¸é©åˆç”¨æ–¼æ¸¬è©¦å’Œ
+ç„¶å¾Œï¼Œå®ƒå°‡è¢«æ¨™è¨˜çˆ²â€œç”Ÿå‘½é€±æœŸçµæŸâ€ï¼ˆEOL)。é”到這個程度的版本線ä»ç„¶æœƒåœ¨
+`kernel.org <https://kernel.org/>`_ 首é ä¸Šè¢«é¡¯ç¤ºä¸€å…©é€±ï¼Œä½†ä¸é©åˆç”¨æ–¼æ¸¬è©¦å’Œ
報告。
æœç´¢ç©©å®šç‰ˆéƒµä»¶åˆ—表
@@ -1158,57 +1161,63 @@ FLOSS å•題報告的人看,詢å•他們的æ„è¦‹ã€‚åŒæ™‚徵求他們關於å¦
用最新版本復ç¾å•題
~~~~~~~~~~~~~~~~~~~
- *å¾žç‰¹å®šçš„ç‰ˆæœ¬ç·šå®‰è£æœ€æ–°ç‰ˆæœ¬ä½œçˆ²ç´”淨內核。確ä¿é€™å€‹å…§æ ¸æ²’有被汙染,並且ä»
- 然存在å•題,因爲å•題å¯èƒ½å·²ç¶“在那裡被修復了。*
+ *å¾žç‰¹å®šçš„ç‰ˆæœ¬ç·šå®‰è£æœ€æ–°ç‰ˆæœ¬ä½œçˆ²ç´”淨內核。確ä¿é€™å€‹å…§æ ¸æ²’有被污染,並且ä»
+ 然存在å•題,因爲å•題å¯èƒ½å·²ç¶“在那è£è¢«ä¿®å¾©äº†ã€‚*
在投入更多時間到這個éŽç¨‹ä¸­ä¹‹å‰ï¼Œä½ è¦æª¢æŸ¥é€™å€‹å•題是å¦åœ¨ä½ é—œæ³¨çš„版本線的最新
-ç‰ˆæœ¬ä¸­å·²ç¶“å¾—åˆ°äº†ä¿®å¾©ã€‚é€™å€‹å…§æ ¸éœ€è¦æ˜¯ç´”淨的,在å•題發生之å‰ä¸æ‡‰è©²è¢«æ±™æŸ“,正
+ç‰ˆæœ¬ä¸­å·²ç¶“å¾—åˆ°äº†ä¿®å¾©ã€‚é€™å€‹å…§æ ¸éœ€è¦æ˜¯ç´”淨的,在å•題發生之å‰ä¸æ‡‰è©²è¢«æ±¡æŸ“,正
如上é¢å·²ç¶“在測試主線的éŽç¨‹ä¸­è©³ç´°ä»‹ç´¹éŽçš„一樣。
-æ‚¨æ˜¯å¦æ˜¯ç¬¬ä¸€æ¬¡æ³¨æ„到供應商內核的回歸?供應商的更改å¯èƒ½æœƒç™¼ç”Ÿè®ŠåŒ–。你需è¦é‡æ–°
+æ‚¨æ˜¯å¦æ˜¯ç¬¬ä¸€æ¬¡æ³¨æ„到供應商內核的迴歸?供應商的更改å¯èƒ½æœƒç™¼ç”Ÿè®ŠåŒ–。你需è¦é‡æ–°
檢查排除來這個å•題。當您從5.10.4-vendor.42更新到5.10.5-vendor.43時,記錄æå£ž
的信æ¯ã€‚然後在測試了å‰ä¸€æ®µä¸­æ‰€è¿°çš„æœ€æ–°5.10版本之後,檢查Linux 5.10.4的普通版本
-是å¦ä¹Ÿå¯ä»¥æ­£å¸¸å·¥ä½œã€‚如果å•題在那裡出ç¾ï¼Œé‚£å°±ä¸ç¬¦åˆä¸Šæ¸¸å›žæ­¸çš„æ¢ä»¶ï¼Œæ‚¨éœ€è¦åˆ‡æ›
+是å¦ä¹Ÿå¯ä»¥æ­£å¸¸å·¥ä½œã€‚如果å•題在那è£å‡ºç¾ï¼Œé‚£å°±ä¸ç¬¦åˆä¸Šæ¸¸è¿´æ­¸çš„æ¢ä»¶ï¼Œæ‚¨éœ€è¦åˆ‡æ›
å›žä¸»é€æ­¥æŒ‡å—來報告å•題。
-報告回歸
+報告迴歸
~~~~~~~~~~
- *å‘Linux穩定版郵件列表發é€ä¸€å€‹ç°¡çŸ­çš„å•題報告(stable@vger.kernel.org)。
- 大致æè¿°å•題,並解釋如何復ç¾ã€‚講清楚首個出ç¾å•題的版本和最後一個工作正常
- 的版本。然後等待進一步的指示。*
+ *å‘Linux穩定版郵件列表發é€ä¸€å€‹ç°¡çŸ­çš„å•題報告(stable@vger.kernel.org)並
+ 抄é€Linux迴歸郵件列表(regressions@lists.linux.dev);如果你懷疑是由æŸ
+ å­ç³»çµ±å¼•起的,請抄é€å…¶ç¶­è­·äººå“¡å’Œå­ç³»çµ±éƒµä»¶åˆ—表。大致æè¿°å•題,並解釋如
+ 何復ç¾ã€‚講清楚首個出ç¾å•題的版本和最後一個工作正常的版本。然後等待進一
+ 步的指示。*
-當報告在穩定版或長期支æŒå…§æ ¸ç·šå…§ç™¼ç”Ÿçš„回歸(例如在從5.10.4更新到5.10.5時),
-一份簡短的報告足以快速報告å•題。因此åªéœ€è¦ç²—略的æè¿°ã€‚
+當報告在穩定版或長期支æŒå…§æ ¸ç·šå…§ç™¼ç”Ÿçš„迴歸(例如在從5.10.4更新到5.10.5時),
+一份簡短的報告足以快速報告å•題。因此åªéœ€å‘穩定版和迴歸郵件列表發é€ç²—略的æè¿°ï¼›
+ä¸éŽå¦‚果你懷疑æŸå­ç³»çµ±å°Žè‡´æ­¤å•題的話,請一併抄é€å…¶ç¶­è­·äººå“¡å’Œå­ç³»çµ±éƒµä»¶åˆ—表,
+這會加快進程。
-但是請注æ„,如果您能夠指明引入å•題的確切版本,這將å°é–‹ç™¼äººå“¡æœ‰å¾ˆå¤§å¹«åŠ©ã€‚å› æ­¤
-如果有時間的話,請嘗試使用普通內核找到該版本。讓我們å‡è¨­ç™¼è¡Œç‰ˆç™¼å¸ƒLinuxå…§æ ¸
+請注æ„,如果您能夠指明引入å•題的確切版本,這將å°é–‹ç™¼äººå“¡æœ‰å¾ˆå¤§å¹«åŠ©ã€‚å› æ­¤
+如果有時間的話,請嘗試使用普通內核找到該版本。讓我們å‡è¨­ç™¼è¡Œç‰ˆç™¼ä½ˆLinuxå…§æ ¸
5.10.5到5.10.8的更新時發生了故障。那麼按照上é¢çš„æŒ‡ç¤ºï¼ŒåŽ»æª¢æŸ¥è©²ç‰ˆæœ¬ç·šä¸­çš„æœ€æ–°
內核,比如5.10.9。如果å•題出ç¾ï¼Œè«‹å˜—試普通5.10.5,以確ä¿ä¾›æ‡‰å•†æ‡‰ç”¨çš„補ä¸ä¸æœƒ
干擾。如果å•題沒有出ç¾ï¼Œé‚£éº¼å˜—試5.10.7,然後直到5.10.8或5.10.6ï¼ˆå–æ±ºæ–¼çµæžœï¼‰
找到第一個引入å•題的版本。在報告中寫明這一點,並指出5.10.9ä»ç„¶å­˜åœ¨æ•…障。
-å‰ä¸€æ®µåŸºæœ¬ç²—ç•¥åœ°æ¦‚è¿°äº†ã€ŒäºŒåˆ†ã€æ–¹æ³•。一旦報告出來,您å¯èƒ½æœƒè¢«è¦æ±‚åšä¸€å€‹æ­£ç¢ºçš„
+å‰ä¸€æ®µåŸºæœ¬ç²—ç•¥åœ°æ¦‚è¿°äº†â€œäºŒåˆ†â€æ–¹æ³•。一旦報告出來,您å¯èƒ½æœƒè¢«è¦æ±‚åšä¸€å€‹æ­£ç¢ºçš„
報告,因爲它å…許精確地定ä½å°Žè‡´å•題的確切更改(然後很容易被æ¢å¾©ä»¥å¿«é€Ÿä¿®å¾©å•題)。
-因此如果時間å…許,考慮立å³é€²è¡Œé©ç•¶çš„二分。有關如何詳細信æ¯ï¼Œè«‹åƒé–±ã€Œå°å›žæ­¸çš„
-特別關照ã€éƒ¨åˆ†å’Œæ–‡æª”「Documentation/translations/zh_TW/admin-guide/bug-bisect.rstã€ã€‚
+因此如果時間å…許,考慮立å³é€²è¡Œé©ç•¶çš„二分。有關如何詳細信æ¯ï¼Œè«‹åƒé–±â€œå°è¿´æ­¸çš„
+特別關照â€éƒ¨åˆ†å’Œæ–‡æª” Documentation/translations/zh_CN/admin-guide/bug-bisect.rst 。
+如果æˆåŠŸäºŒåˆ†çš„è©±ï¼Œè«‹å°‡â€œç½ªé­ç¦é¦–â€çš„ä½œè€…æ·»åŠ åˆ°æ”¶ä»¶äººä¸­ï¼›åŒæ™‚æŠ„é€æ‰€æœ‰åœ¨
+signed-off-byéˆä¸­çš„人,您å¯ä»¥åœ¨æäº¤æ¶ˆæ¯çš„æœ«å°¾æ‰¾åˆ°ã€‚
-「報告僅在舊內核版本線中發生的å•題ã€çš„åƒè€ƒ
-------------------------------------------
+“報告僅在舊內核版本線中發生的å•題â€çš„åƒè€ƒ
+----------------------------------------
-本節詳細介紹了如果無法用主線內核é‡ç¾å•題,但希望在舊版本線(åˆç¨±ç©©å®šç‰ˆå…§æ ¸å’Œ
+本節詳細介紹瞭如果無法用主線內核é‡ç¾å•題,但希望在舊版本線(åˆç¨±ç©©å®šç‰ˆå…§æ ¸å’Œ
長期支æŒå…§æ ¸ï¼‰ä¸­ä¿®å¾©å•é¡Œæ™‚éœ€è¦æŽ¡å–的步驟。
有些修復太複雜
~~~~~~~~~~~~~~~
*è«‹åšå¥½æº–備,接下來的幾個步驟å¯èƒ½ç„¡æ³•在舊版本中解決å•題:修復å¯èƒ½å¤ªå¤§æˆ–
- 太冒險,無法移æ¤åˆ°é‚£è£¡ã€‚*
+ 太冒險,無法移æ¤åˆ°é‚£è£ã€‚*
å³ä½¿æ˜¯å¾®å°çš„ã€çœ‹ä¼¼æ˜Žé¡¯çš„代碼變化,有時也會帶來新的ã€å®Œå…¨æ„想ä¸åˆ°çš„å•題。穩
定版和長期支æŒå…§æ ¸çš„維護者éžå¸¸æ¸…楚這一點,因此他們åªå°é€™äº›å…§æ ¸é€²è¡Œç¬¦åˆ
-「Documentation/translations/zh_TW/process/stable-kernel-rules.rstã€ä¸­æ‰€åˆ—出的
+Documentation/translations/zh_CN/process/stable-kernel-rules.rst 中所列出的
è¦å‰‡çš„修改。
複雜或有風險的修改ä¸ç¬¦åˆæ¢ä»¶ï¼Œå› æ­¤åªèƒ½æ‡‰ç”¨æ–¼ä¸»ç·šã€‚其他的修復很容易被回溯到
@@ -1220,7 +1229,7 @@ FLOSS å•題報告的人看,詢å•他們的æ„è¦‹ã€‚åŒæ™‚徵求他們關於å¦
通用準備
~~~~~~~~~~
- *執行上é¢ã€Œå ±å‘Šåƒ…在舊內核版本線中發生的å•題ã€ä¸€ç¯€ä¸­çš„å‰ä¸‰å€‹æ­¥é©Ÿã€‚*
+ *執行上é¢â€œå ±å‘Šåƒ…在舊內核版本線中發生的å•題â€ä¸€ç¯€ä¸­çš„å‰ä¸‰å€‹æ­¥é©Ÿã€‚*
您需è¦åŸ·è¡Œæœ¬æŒ‡å—å¦ä¸€ç¯€ä¸­å·²ç¶“æè¿°çš„幾個步驟。這些步驟將讓您:
@@ -1242,21 +1251,21 @@ FLOSS å•題報告的人看,詢å•他們的æ„è¦‹ã€‚åŒæ™‚徵求他們關於å¦
在許多情æ³ä¸‹ï¼Œä½ æ‰€è™•ç†çš„å•題會發生在主線上,但已在主線上得到了解決。修正它
çš„æäº¤ä¹Ÿéœ€è¦è¢«å›žæº¯æ‰èƒ½è§£æ±ºé€™å€‹å•é¡Œã€‚é€™å°±æ˜¯çˆ²ä»€éº¼ä½ è¦æœç´¢å®ƒæˆ–任何相關討論。
- * 首先嘗試在存放 Linux 內核原始碼的 Git 倉庫中找到修復。你å¯ä»¥é€šéŽ
+ * 首先åšè©¦åœ¨å­˜æ”¾ Linux å…§æ ¸æºä»£ç¢¼çš„ Git 倉庫中找到修復。你å¯ä»¥é€šéŽ
`kernel.org 上的網é 
<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/>`_
或 `GitHub 上的é¡åƒ <https://github.com/torvalds/linux>`_ 來實ç¾ï¼›å¦‚果你
有一個本地克隆,你也å¯ä»¥åœ¨å‘½ä»¤è¡Œç”¨ ``git log --grep=<pattern>`` 來æœç´¢ã€‚
- 如果你找到了修復,請查看æäº¤æ¶ˆæ¯çš„尾部是å¦åŒ…å«äº†é¡žä¼¼é€™æ¨£çš„「穩定版標籤ã€ï¼š
+ 如果你找到了修復,請查看æäº¤æ¶ˆæ¯çš„尾部是å¦åŒ…å«äº†é¡žä¼¼é€™æ¨£çš„“穩定版標籤â€ï¼š
Cc: <stable@vger.kernel.org> # 5.4+
åƒä¸Šé¢é€™è¡Œï¼Œé–‹ç™¼è€…標記了安全修復å¯ä»¥å›žå‚³åˆ° 5.4 åŠä»¥å¾Œçš„版本。大多數情æ³
- ä¸‹ï¼Œå®ƒæœƒåœ¨å…©å‘¨å…§è¢«æ‡‰ç”¨åˆ°é‚£è£¡ï¼Œä½†æœ‰æ™‚éœ€è¦æ›´é•·çš„æ™‚間。
+ 下,它會在兩週內被應用到那è£ï¼Œä½†æœ‰æ™‚éœ€è¦æ›´é•·çš„æ™‚間。
* 如果æäº¤æ²’有告訴你任何æ±è¥¿ï¼Œæˆ–者你找ä¸åˆ°ä¿®å¾©ï¼Œè«‹å†æ‰¾æ‰¾é—œæ–¼é€™å€‹å•題的討論。
- 用你最喜歡的æœå°‹å¼•擎æœç´¢ç¶²çµ¡ï¼Œä»¥åŠ `Linux kernel developers mailing
+ 用你最喜歡的æœç´¢å¼•擎æœç´¢ç¶²çµ¡ï¼Œä»¥åŠ `Linux kernel developers mailing
list 內核開發者郵件列表 <https://lore.kernel.org/lkml/>`_ 的檔案。也å¯ä»¥
閱讀上é¢çš„ `定ä½å°Žè‡´å•題的內核å€åŸŸ` 一節,然後按照說明找到導致å•題的å­ç³»
統:它的缺陷跟蹤器或郵件列表存檔中å¯èƒ½æœ‰ä½ è¦æ‰¾çš„答案。
@@ -1286,41 +1295,41 @@ FLOSS å•題報告的人看,詢å•他們的æ„è¦‹ã€‚åŒæ™‚徵求他們關於å¦
爲什麼有些å•é¡Œåœ¨å ±å‘Šå¾Œæ²’æœ‰ä»»ä½•å›žæ‡‰æˆ–ä»æœªè§£æ±ºï¼Ÿ
===============================================
-ç•¶å‘ Linux 開發者報告å•é¡Œæ™‚ï¼Œè¦æ³¨æ„åªæœ‰ã€Œé«˜å„ªå…ˆç´šçš„å•題ã€ï¼ˆå›žæ­¸ã€å®‰å…¨å•題ã€åš´
+ç•¶å‘ Linux 開發者報告å•é¡Œæ™‚ï¼Œè¦æ³¨æ„åªæœ‰â€œé«˜å„ªå…ˆç´šçš„å•題â€ï¼ˆè¿´æ­¸ã€å®‰å…¨å•題ã€åš´
é‡å•題)æ‰ä¸€å®šæœƒå¾—到解決。如果維護者或其他人都失敗了,Linus Torvalds 他自己
會確ä¿é€™ä¸€é»žã€‚他們和其他內核開發者也會解決很多其他å•題。但是è¦çŸ¥é“,有時他
們也會ä¸èƒ½æˆ–ä¸é¡˜å¹«å¿™ï¼›æœ‰æ™‚甚至沒有人發報告給他們。
最好的解釋就是那些內核開發者常常是在業餘時間爲 Linux å…§æ ¸åšå‡ºè²¢ç»ã€‚內核中的
-ä¸å°‘驅動程åºéƒ½æ˜¯ç”±é€™æ¨£çš„程å¼è¨­è¨ˆå¸«ç·¨å¯«çš„ï¼Œå¾€å¾€åªæ˜¯å› çˆ²ä»–們想讓自己的硬體å¯ä»¥åœ¨
-自己喜歡的作業系統上使用。
+ä¸å°‘驅動程åºéƒ½æ˜¯ç”±é€™æ¨£çš„程åºå“¡ç·¨å¯«çš„ï¼Œå¾€å¾€åªæ˜¯å› çˆ²ä»–們想讓自己的硬件å¯ä»¥åœ¨
+自己喜歡的æ“作系統上使用。
-這些程å¼è¨­è¨ˆå¸«å¤§å¤šæ•¸æ™‚候會很樂æ„修復別人報告的å•題。但是沒有人å¯ä»¥å¼·è¿«ä»–們這樣
+這些程åºå“¡å¤§å¤šæ•¸æ™‚候會很樂æ„修復別人報告的å•題。但是沒有人å¯ä»¥å¼·è¿«ä»–們這樣
åšï¼Œå› çˆ²ä»–們是自願貢ç»çš„。
還有一些情æ³ä¸‹ï¼Œé€™äº›é–‹ç™¼è€…真的很想解決一個å•題,但å»ä¸èƒ½è§£æ±ºï¼šæœ‰æ™‚他們缺ä¹
-硬體編程文檔來解決å•題。這種情æ³å¾€å¾€ç”±æ–¼å…¬é–‹çš„æ–‡æª”å¤ªç°¡é™‹ï¼Œæˆ–è€…é©…å‹•ç¨‹åºæ˜¯é€š
+硬件編程文檔來解決å•題。這種情æ³å¾€å¾€ç”±æ–¼å…¬é–‹çš„æ–‡æª”å¤ªç°¡é™‹ï¼Œæˆ–è€…é©…å‹•ç¨‹åºæ˜¯é€š
éŽé€†å‘工程編寫的。
-æ¥­é¤˜é–‹ç™¼è€…é²æ—©ä¹Ÿæœƒä¸å†é—œå¿ƒæŸé©…動。也許他們的測試硬體壞了,被更高級的玩æ„å–
-代了,或者是太è€äº†ä»¥è‡³æ–¼åªèƒ½åœ¨è¨ˆç®—機åšç‰©é¤¨è£¡æ‰¾åˆ°ã€‚有時開發者根本就ä¸é—œå¿ƒä»–
+æ¥­é¤˜é–‹ç™¼è€…é²æ—©ä¹Ÿæœƒä¸å†é—œå¿ƒæŸé©…動。也許他們的測試硬件壞了,被更高級的玩æ„å–
+代了,或者是太è€äº†ä»¥è‡³æ–¼åªèƒ½åœ¨è¨ˆç®—機åšç‰©é¤¨è£æ‰¾åˆ°ã€‚有時開發者根本就ä¸é—œå¿ƒä»–
們的代碼和 Linux 了,因爲在他們的生活中一些ä¸åŒçš„æ±è¥¿è®Šå¾—æ›´é‡è¦äº†ã€‚在æŸäº›æƒ…
æ³ä¸‹ï¼Œæ²’æœ‰äººé¡˜æ„æŽ¥æ‰‹ç¶­è­·è€…çš„å·¥ä½œâ€”â€”ä¹Ÿæ²’æœ‰äººå¯ä»¥è¢«å¼·è¿«ï¼Œå› çˆ²å° Linux 內核的貢
ç»æ˜¯è‡ªé¡˜çš„ã€‚ç„¶è€Œè¢«éºæ£„的驅動程åºä»ç„¶å­˜åœ¨æ–¼å…§æ ¸ä¸­ï¼šå®ƒå€‘å°äººå€‘ä»ç„¶æœ‰ç”¨ï¼Œåˆªé™¤
-它們å¯èƒ½å°Žè‡´å›žæ­¸ã€‚
+它們å¯èƒ½å°Žè‡´è¿´æ­¸ã€‚
å°æ–¼é‚£äº›çˆ² Linux 內核工作而ç²å¾—報酬的開發者來說,情æ³ä¸¦æ²’有什麼ä¸åŒã€‚這些人
ç¾åœ¨è²¢ç»äº†å¤§éƒ¨åˆ†çš„è®Šæ›´ã€‚ä½†æ˜¯ä»–å€‘çš„åƒ±ä¸»é²æ—©ä¹Ÿæœƒåœæ­¢é—œæ³¨ä»–們的代碼或者讓程åº
-員專注於其他事情。例如,硬體廠商主è¦é€šéŽéŠ·å”®æ–°ç¡¬é«”ä¾†è³ºéŒ¢ï¼›å› æ­¤ï¼Œä»–å€‘ä¸­çš„ä¸
+員專注於其他事情。例如,硬件廠商主è¦é€šéŽéŠ·å”®æ–°ç¡¬ä»¶ä¾†è³ºéŒ¢ï¼›å› æ­¤ï¼Œä»–å€‘ä¸­çš„ä¸
少人並沒有投入太多時間和精力來維護他們多年å‰å°±åœæ­¢éŠ·å”®çš„æ±è¥¿çš„ Linux 內核驅
å‹•ã€‚ä¼æ¥­ç´š Linux 發行商往往æŒçºŒç¶­è­·çš„æ™‚間比較長,但在新版本中往往會把å°è€èˆŠ
-å’Œç¨€æœ‰ç¡¬é«”çš„æ”¯æŒæ”¾åœ¨ä¸€é‚Šï¼Œä»¥é™åˆ¶ç¯„åœã€‚ä¸€æ—¦å…¬å¸æ‹‹æ£„了一些代碼,往往由業餘貢
+å’Œç¨€æœ‰ç¡¬ä»¶çš„æ”¯æŒæ”¾åœ¨ä¸€é‚Šï¼Œä»¥é™åˆ¶ç¯„åœã€‚ä¸€æ—¦å…¬å¸æ‹‹æ£„了一些代碼,往往由業餘貢
ç»è€…æŽ¥æ‰‹ï¼Œä½†æ­£å¦‚ä¸Šé¢æåˆ°çš„ï¼šä»–å€‘é²æ—©ä¹Ÿæœƒæ”¾ä¸‹ä»£ç¢¼ã€‚
優先級是一些å•題沒有被修復的å¦ä¸€å€‹åŽŸå› ï¼Œå› çˆ²ç¶­è­·è€…ç›¸ç•¶å¤šçš„æ™‚å€™æ˜¯è¢«è¿«è¨­ç½®é€™
些優先級的,因爲在 Linux 上工作的時間是有é™çš„ã€‚å°æ–¼æ¥­é¤˜æ™‚間或者僱主給予他們
的開發人員用於上游內核維護工作的時間也是如此。有時維護人員也會被報告淹沒,
-å³ä½¿ä¸€å€‹é©…動程åºå¹¾ä¹Žå®Œç¾Žåœ°å·¥ä½œã€‚爲了ä¸è¢«å®Œå…¨çºä½ï¼Œç¨‹å¼è¨­è¨ˆå¸«å¯èƒ½åˆ¥ç„¡é¸æ“‡ï¼Œåªèƒ½
+å³ä½¿ä¸€å€‹é©…動程åºå¹¾ä¹Žå®Œç¾Žåœ°å·¥ä½œã€‚爲了ä¸è¢«å®Œå…¨çºä½ï¼Œç¨‹åºå“¡å¯èƒ½åˆ¥ç„¡é¸æ“‡ï¼Œåªèƒ½
å°å•題報告進行優先級排åºè€Œæ‹’絕其中的一些報告。
ä¸éŽé€™äº›éƒ½ä¸ç”¨å¤ªéŽæ“”å¿ƒï¼Œå¾ˆå¤šé©…å‹•éƒ½æœ‰ç©æ¥µçš„維護者,他們å°å„˜å¯èƒ½å¤šçš„解決å•題
@@ -1330,8 +1339,32 @@ FLOSS å•題報告的人看,詢å•他們的æ„è¦‹ã€‚åŒæ™‚徵求他們關於å¦
çµæŸèªž
=======
-與其他å…è²»/自由&é–‹æºè»Ÿé«”(Free/Libre & Open Source Software,FLOSS)相比,
-å‘ Linux 內核開發者報告å•題是很難的:這個文檔的長度和複雜性以åŠå­—裡行間的內
+與其他å…è²»/自由&é–‹æºè»Ÿä»¶ï¼ˆFree/Libre & Open Source Software,FLOSS)相比,
+å‘ Linux 內核開發者報告å•題是很難的:這個文檔的長度和複雜性以åŠå­—è£è¡Œé–“的內
涵都說明了這一點。但目å‰å°±æ˜¯é€™æ¨£äº†ã€‚這篇文字的主è¦ä½œè€…希望通éŽè¨˜éŒ„ç¾ç‹€ä¾†çˆ²
ä»¥å¾Œæ”¹å–„é€™ç¨®ç‹€æ³æ‰“下一些基礎。
+
+..
+ end-of-content
+..
+ This English version of this document is maintained by Thorsten Leemhuis
+ <linux@leemhuis.info>. If you spot a typo or small mistake, feel free to
+ let him know directly and he'll fix it. For translation problems, please
+ contact with translators. You are free to do the same in a mostly informal
+ way if you want to contribute changes to the text, but for copyright
+ reasons please CC linux-doc@vger.kernel.org and "sign-off" your
+ contribution as Documentation/process/submitting-patches.rst outlines in
+ the section "Sign your work - the Developer's Certificate of Origin".
+..
+ This text is available under GPL-2.0+ or CC-BY-4.0, as stated at the top
+ of the file. If you want to distribute this text under CC-BY-4.0 only,
+ please use "The Linux kernel developers" for author attribution and link
+ this as source:
+ https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/Documentation/admin-guide/reporting-issues.rst
+..
+ Note: Only the content of this RST file as found in the Linux kernel sources
+ is available under CC-BY-4.0, as versions of this text that were processed
+ (for example by the kernel's build system) might contain content taken from
+ files which use a more restrictive license.
+
diff --git a/Documentation/translations/zh_TW/admin-guide/reporting-regressions.rst b/Documentation/translations/zh_TW/admin-guide/reporting-regressions.rst
new file mode 100644
index 000000000000..d7dcb2a26564
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/reporting-regressions.rst
@@ -0,0 +1,371 @@
+.. SPDX-License-Identifier: (GPL-2.0+ OR CC-BY-4.0)
+.. ã€é‡åˆ†ç™¼ä¿¡æ¯åƒè¦‹æœ¬æ–‡ä»¶çµå°¾ã€‘
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/reporting-regressions.rst
+
+:譯者:
+
+ 峿ƒ³æˆ Wu XiangCheng <bobwxc@email.cn>
+
+
+============
+報告迴歸å•題
+============
+
+“*我們拒絕出ç¾è¿´æ­¸*â€æ˜¯Linux內核開發的首è¦è¦å‰‡ï¼›Linux的發起者和領è»é–‹ç™¼è€…Linus
+Torvalds立下了此è¦å‰‡ä¸¦ç¢ºä¿å®ƒè¢«è½å¯¦ã€‚
+
+本文檔æè¿°äº†é€™æ¢è¦å‰‡å°ç”¨æˆ¶çš„æ„ç¾©ï¼Œä»¥åŠLinux內核開發模型如何確ä¿è§£æ±ºæ‰€æœ‰è¢«å ±å‘Š
+的迴歸;關於內核開發者如何處ç†çš„æ–¹é¢åƒè¦‹ Documentation/process/handling-regressions.rst 。
+
+
+本文é‡é»žï¼ˆäº¦å³â€œå¤ªé•·ä¸çœ‹â€ï¼‰
+==========================
+
+#. 如果æŸç¨‹åºåœ¨åŽŸå…ˆçš„Linux內核上é‹è¡Œè‰¯å¥½ï¼Œä½†åœ¨è¼ƒæ–°ç‰ˆæœ¬ä¸Šæ•ˆæžœæ›´å·®ã€æˆ–者根本ä¸
+ 能用,那麼你就碰見迴歸å•題了。注æ„,新內核需è¦ä½¿ç”¨é¡žä¼¼é…置編譯;更多相關細
+ 節åƒè¦‹ä¸‹æ–¹ã€‚
+
+#. 按照 Documentation/translations/zh_CN/admin-guide/reporting-issues.rst 中
+ 所說的報告你的å•題,該文檔已經包å«äº†æ‰€æœ‰é—œæ–¼è¿´æ­¸çš„é‡è¦æ–¹é¢ï¼Œçˆ²äº†æ–¹ä¾¿èµ·è¦‹ä¹Ÿ
+ 複製到了下é¢ã€‚兩個é‡é»žï¼šåœ¨å ±å‘Šä¸»é¡Œä¸­ä½¿ç”¨â€œ[REGRESSION]â€é–‹é ­ä¸¦æŠ„逿ˆ–轉發到
+ `迴歸郵件列表 <https://lore.kernel.org/regressions/>`_
+ (regressions@lists.linux.dev)。
+
+#. å¯é¸ä½†æ˜¯å»ºè­°ï¼šåœ¨ç™¼é€æˆ–轉發報告時,指明該回歸發生的起點,以便Linux內核迴歸
+ 追蹤機器人“regzbotâ€å¯ä»¥è¿½è¹¤æ­¤å•題::
+
+ #regzbot introduced v5.13..v5.14-rc1
+
+
+與用戶相關的所有Linux內核迴歸細節
+=================================
+
+
+基本é‡é»ž
+--------
+
+
+什麼是“迴歸â€ä»¥åŠä»€éº¼æ˜¯â€œç„¡è¿´æ­¸è¦å‰‡â€ï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+如果æŸç¨‹åº/實例在原先的Linux內核上é‹è¡Œè‰¯å¥½ï¼Œä½†åœ¨è¼ƒæ–°ç‰ˆæœ¬ä¸Šæ•ˆæžœæ›´å·®ã€æˆ–者根本
+ä¸èƒ½ç”¨ï¼Œé‚£éº¼ä½ å°±ç¢°è¦‹è¿´æ­¸å•題了。“無迴歸è¦å‰‡â€ä¸å…許出ç¾é€™ç¨®æƒ…æ³ã€‚如果å¶ç„¶ç™¼
+生了,導致å•題的開發者應當迅速修復å•題。
+
+也就是說,若Linux 5.13中的WiFi驅動程åºé‹è¡Œè‰¯å¥½ï¼Œä½†æ˜¯åœ¨5.14版本上å»ä¸èƒ½ç”¨ã€é€Ÿ
+度明顯變慢或出ç¾éŒ¯èª¤ï¼Œé‚£å°±å‡ºç¾äº†è¿´æ­¸ã€‚å¦‚æžœæŸæ­£å¸¸å·¥ä½œçš„æ‡‰ç”¨ç¨‹åºçªç„¶åœ¨æ–°å…§æ ¸ä¸Š
+出ç¾ä¸ç©©å®šï¼Œé€™ä¹Ÿæ˜¯è¿´æ­¸ï¼›é€™äº›å•題å¯èƒ½æ˜¯ç”±æ–¼procfsã€sysfs或Linuxæä¾›çµ¦ç”¨æˆ¶ç©ºé–“
+軟件的許多其他接å£ä¹‹ä¸€çš„變化。但請記ä½ï¼Œå‰è¿°ä¾‹å­ä¸­çš„5.14需è¦ä½¿ç”¨é¡žä¼¼æ–¼5.13çš„
+é…置構建。這å¯ä»¥ç”¨ ``make olddefconfig`` 實ç¾ï¼Œè©³ç´°è§£é‡‹è¦‹ä¸‹ã€‚
+
+æ³¨æ„æœ¬ç¯€ç¬¬ä¸€å¥è©±ä¸­çš„“實例â€ï¼šå³ä½¿é–‹ç™¼è€…需è¦éµå¾ªâ€œç„¡è¿´æ­¸â€è¦å‰‡ï¼Œä½†ä»å¯è‡ªç”±åœ°æ”¹
+變內核的任何方é¢ï¼Œç”šè‡³æ˜¯å°Žå‡ºåˆ°ç”¨æˆ¶ç©ºé–“çš„API或ABI,åªè¦åˆ¥ç ´å£žç¾æœ‰çš„æ‡‰ç”¨ç¨‹åºæˆ–
+用例。
+
+還需注æ„,“無迴歸â€è¦å‰‡åªé™åˆ¶å…§æ ¸æä¾›çµ¦ç”¨æˆ¶ç©ºé–“的接å£ã€‚它ä¸é©ç”¨æ–¼å…§æ ¸å…§éƒ¨æŽ¥
+å£ï¼Œæ¯”如一些外部開發的驅動程åºç”¨ä¾†æ’入鉤å­åˆ°å…§æ ¸çš„æ¨¡å¡ŠAPI。
+
+如何報告迴歸?
+~~~~~~~~~~~~~~
+
+åªéœ€æŒ‰ç…§ Documentation/translations/zh_CN/admin-guide/reporting-issues.rst 中
+所說的報告你的å•題,該文檔已經包å«äº†è¦é»žã€‚下é¢å¹¾é»žæ¦‚述了一下åªåœ¨è¿´æ­¸ä¸­é‡è¦çš„
+æ–¹é¢ï¼š
+
+ * 在檢查å¯åŠ å…¥è¨Žè«–çš„ç¾æœ‰å ±å‘Šæ™‚,別忘了æœç´¢ `Linux迴歸郵件列表
+ <https://lore.kernel.org/regressions/>`_ å’Œ `regzbotç¶²é ç•Œé¢
+ <https://linux-regtracking.leemhuis.info/regzbot/>`_ 。
+
+ * 在報告主題的開頭加上“[REGRESSION]â€ã€‚
+
+ * 在你的報告中明確最後一個正常工作的內核版本和首個出å•題的版本。如若å¯èƒ½ï¼Œ
+ 用二分法嘗試找出導致迴歸的變更,更多細節見下。
+
+ * 記得把報告發到Linux迴歸郵件列表(regressions@lists.linux.dev)。
+
+ * 如果通éŽéƒµä»¶å ±å‘Šè¿´æ­¸ï¼Œè«‹æŠ„é€å›žæ­¸åˆ—表。
+
+ * 如果你使用æŸäº›ç¼ºé™·è¿½è¹¤å™¨å ±å‘Šè¿´æ­¸ï¼Œè«‹é€šéŽéƒµä»¶è½‰ç™¼å·²æäº¤çš„報告到迴歸列表,
+ 並抄é€ç¶­è­·è€…以åŠå‡ºå•題的相關å­ç³»çµ±çš„郵件列表。
+
+ 如果是穩定版或長期支æŒç‰ˆç³»åˆ—(如v5.15.3…v5.15.5)的迴歸,請記得抄é€
+ `Linux穩定版郵件列表 <https://lore.kernel.org/stable/>`_ (stable@vger.kernel.org)。
+
+ 如果你æˆåŠŸåœ°åŸ·è¡Œäº†äºŒåˆ†ï¼Œè«‹æŠ„é€è‚‡äº‹æäº¤çš„ä¿¡æ¯ä¸­æ‰€æœ‰ç°½äº†â€œSigned-off-by:â€çš„人。
+
+在抄é€ä½ çš„報告到列表時,也請記得通知å‰è¿°çš„Linux內核迴歸追蹤機器人。åªéœ€åœ¨éƒµä»¶
+中包å«å¦‚下片段::
+
+ #regzbot introduced: v5.13..v5.14-rc1
+
+Regzbot會就將你的郵件視爲在æŸå€‹ç‰¹å®šç‰ˆæœ¬å€é–“的迴歸報告。上例中å³linux v5.13ä»
+然正常,而Linux 5.14-rc1是首個您é‡åˆ°å•題的版本。如果你執行了二分以查找導致回
+歸的æäº¤ï¼Œè«‹ä½¿ç”¨æŒ‡å®šè‚‡äº‹æäº¤çš„id代替::
+
+ #regzbot introduced: 1f2e3d4c5d
+
+添加這樣的“regzbot命令â€å°ä½ æ˜¯æœ‰å¥½è™•的,它會確ä¿å ±å‘Šä¸æœƒè¢«å¿½ç•¥ã€‚如果你çœç•¥äº†
+它,Linux內核的迴歸跟蹤者會把你的迴歸告訴regzbot,åªè¦ä½ ç™¼é€äº†ä¸€å€‹å‰¯æœ¬åˆ°è¿´æ­¸
+éƒµä»¶åˆ—è¡¨ã€‚ä½†æ˜¯è¿´æ­¸è·Ÿè¹¤è€…åªæœ‰ä¸€å€‹äººï¼Œæœ‰æ™‚ä¸å¾—ä¸ä¼‘æ¯æˆ–甚至å¶çˆ¾äº«å—å¯ä»¥é é›¢é›»è…¦
+的時光(è½èµ·ä¾†å¾ˆç˜‹ç‹‚)。因此,ä¾è³´æ­¤äººæ‰‹å‹•將回歸添加到 `已追蹤且尚未解決的
+Linux內核迴歸列表 <https://linux-regtracking.leemhuis.info/regzbot/>`_ 和
+regzbot發é€çš„æ¯é€±è¿´æ­¸å ±å‘Šï¼Œå¯èƒ½æœƒå‡ºç¾å»¶é²ã€‚ 這樣的延誤會導致Linus Torvalds
+åœ¨æ±ºå®šâ€œç¹¼çºŒé–‹ç™¼é‚„æ˜¯ç™¼ä½ˆæ–°ç‰ˆæœ¬ï¼Ÿâ€æ™‚忽略嚴é‡çš„迴歸。
+
+真的修復了所有的迴歸嗎?
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+幾乎所有都是,åªè¦å¼•èµ·å•題的變更(肇事æäº¤ï¼‰è¢«å¯é å®šä½ã€‚也有些迴歸å¯ä»¥ä¸ç”¨é€™
+樣,但通常是必須的。
+
+èª°éœ€è¦æ‰¾å‡ºè¿´æ­¸çš„æ ¹æœ¬åŽŸå› ï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+å—影響代碼å€åŸŸçš„開發者應該自行嘗試定ä½å•題所在。但僅é ä»–們的努力往往是ä¸å¯
+能åšåˆ°çš„,很多å•題åªç™¼ç”Ÿåœ¨é–‹ç™¼è€…的無法接觸的其他特定外部環境中——例如特定的
+硬件平臺ã€å›ºä»¶ã€Linux發行版ã€ç³»çµ±çš„é…置或應用程åºã€‚這就是爲什麼最終往往是報
+告者定ä½è‚‡äº‹æäº¤ï¼›æœ‰æ™‚用戶甚至需è¦å†é‹è¡Œé¡å¤–測試以查明確切的根本原因。開發
+者應該æä¾›å»ºè­°å’Œå¯èƒ½çš„幫助,以使普通用戶更容易完æˆè©²æµç¨‹ã€‚
+
+如何找到罪é­ç¦é¦–?
+~~~~~~~~~~~~~~~~~~
+
+如 Documentation/translations/zh_CN/admin-guide/reporting-issues.rst (簡è¦ï¼‰
+和 Documentation/translations/zh_CN/admin-guide/bug-bisect.rst (詳細)中所
+述,執行二分。è½èµ·ä¾†å·¥ä½œé‡å¾ˆå¤§ï¼Œä½†å¤§éƒ¨åˆ†æƒ…æ³ä¸‹å¾ˆå¿«å°±èƒ½æ‰¾åˆ°ç½ªé­ç¦é¦–。如果這很
+困難或å¯é åœ°é‡ç¾å•題很耗時,請考慮與其他å—影響的用戶åˆä½œï¼Œä¸€èµ·ç¸®å°æœç´¢ç¯„åœã€‚
+
+當出ç¾è¿´æ­¸æ™‚我å¯ä»¥å‘誰尋求建議?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+發é€éƒµä»¶åˆ°è¿´æ­¸éƒµä»¶åˆ—表(regressions@lists.linux.devï¼‰åŒæ™‚抄é€Linux內核的迴歸
+跟蹤者(regressions@leemhuis.info);如果å•題需è¦ä¿å¯†è™•ç†ï¼Œå¯ä»¥çœç•¥åˆ—表。
+
+
+關於迴歸的更多細節
+------------------
+
+
+“無迴歸è¦å‰‡â€çš„目標是什麼?
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+用戶應該放心å‡ç´šå…§æ ¸ç‰ˆæœ¬ï¼Œè€Œä¸å¿…擔心有程åºå¯èƒ½å´©æ½°ã€‚這符åˆå…§æ ¸é–‹ç™¼è€…的利益,
+å¯ä»¥ä½¿æ›´æ–°æœ‰å¸å¼•力:他們ä¸å¸Œæœ›ç”¨æˆ¶åœç•™åœ¨åœæ­¢ç¶­è­·æˆ–è¶…éŽä¸€å¹´åŠçš„穩定/長期Linux
+ç‰ˆæœ¬ç³»åˆ—ä¸Šã€‚é€™ä¹Ÿç¬¦åˆæ‰€æœ‰äººçš„利益,因爲 `那些系列å¯èƒ½å«æœ‰å·²çŸ¥çš„缺陷ã€å®‰å…¨å•題
+或其他後續版本已經修復的å•題
+<http://www.kroah.com/log/blog/2018/08/24/what-stable-kernel-should-i-use/>`_ 。
+此外,內核開發者希望使用戶測試最新的é ç™¼è¡Œç‰ˆæˆ–常è¦ç™¼è¡Œç‰ˆè®Šå¾—簡單而有å¸å¼•力。
+é€™åŒæ¨£ç¬¦åˆæ‰€æœ‰äººçš„利益,如果新版本出來後很快就有相關報告,會使追蹤和修復å•題
+更容易。
+
+實際中“無迴歸â€è¦å‰‡çœŸçš„å¯è¡Œå—Žï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+這䏿˜¯å¥çŽ©ç¬‘è©±ï¼Œè«‹è¦‹Linux創建者和主è¦é–‹ç™¼äººå“¡Linus Torvalds在郵件列表中的許
+多發言,其中一些在 Documentation/process/handling-regressions.rst 中被引用。
+
+æ­¤è¦å‰‡çš„ä¾‹å¤–æƒ…æ³æ¥µçˆ²ç½•見;之å‰ç•¶é–‹ç™¼è€…èªçˆ²æŸå€‹ç‰¹å®šçš„æƒ…æ³æœ‰å¿…è¦æ´å¼•例外時,
+基本都被證明錯了。
+
+誰來確ä¿â€œç„¡è¿´æ­¸â€è¢«è½å¯¦ï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+ç…§çœ‹å’Œæ”¯æ’æ¨¹çš„å­ç³»çµ±ç¶­è­·è€…應該關心這一點——例如,Linus Torvalds之於主線,
+Greg Kroah-Hartman等人之於å„種穩定/長期系列。
+
+他們都得到了別人的幫助,以確ä¿è¿´æ­¸å ±å‘Šä¸æœƒè¢«éºæ¼ã€‚其中之一是Thorsten
+Leemhuisï¼Œä»–ç›®å‰æ“”ä»»Linux內核的“迴歸跟蹤者â€ï¼›çˆ²äº†åšå¥½é€™é …工作,他使用了
+regzbot——Linuxå…§æ ¸è¿´æ­¸è·Ÿè¹¤æ©Ÿå™¨äººã€‚æ‰€ä»¥é€™å°±æ˜¯çˆ²ä»€éº¼è¦æŠ„é€æˆ–轉發你的報告到
+迴歸郵件列表來通知這些人,已經最好在你的郵件中包å«â€œregzbot命令â€ä¾†ç«‹å³è¿½è¹¤å®ƒã€‚
+
+迴歸通常多久能修復?
+~~~~~~~~~~~~~~~~~~~~
+
+開發者應該儘快修復任何被報告的迴歸,以æä¾›åŠæ™‚爲å—影響的用戶æä¾›è§£æ±ºæ–¹æ¡ˆï¼Œä¸¦
+防止更多用戶é‡åˆ°å•題;然而,開發人員需è¦èŠ±è¶³å¤ çš„æ™‚é–“å’Œæ³¨æ„力確ä¿è¿´æ­¸ä¿®å¾©ä¸æœƒ
+造æˆé¡å¤–çš„æå®³ã€‚
+
+å› æ­¤ï¼Œç­”æ¡ˆå–æ±ºæ–¼å„種因素,如迴歸的影響ã€å­˜åœ¨æ™‚é•·æˆ–å‡ºç¾æ–¼å“ªå€‹Linux版本系列。
+但最終,大多數的迴歸應該在兩週內修復。
+
+ç•¶å•題å¯ä»¥é€šéŽå‡ç´šæŸäº›è»Ÿä»¶è§£æ±ºæ™‚,是迴歸嗎?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+基本都是。如果開發人員告訴您其他情æ³ï¼Œè«‹è«®è©¢ä¸Šè¿°è¿´æ­¸è·Ÿè¹¤è€…。
+
+當新內核變慢或能耗增加,是迴歸嗎?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+是的,但有一些差別。在微型基準測試中變慢5%ä¸å¤ªå¯èƒ½è¢«è¦–爲迴歸,除éžå®ƒä¹Ÿæœƒå°
+å»£æ³›åŸºæº–æ¸¬è©¦çš„çµæžœç”¢ç”Ÿè¶…éŽ1%的影響。如果有疑å•,請尋求建議。
+
+當更新Linux時外部內核模塊崩潰了,是迴歸嗎?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ä¸ï¼Œå› çˆ²â€œç„¡è¿´æ­¸â€è¦å‰‡åƒ…陿–¼Linuxå…§æ ¸æä¾›çµ¦ç”¨æˆ¶ç©ºé–“的接å£å’Œæœå‹™ã€‚因此,它ä¸åŒ…括
+構建或é‹è¡Œå¤–部開發的內核模塊,因爲它們在內核空間中é‹è¡Œèˆ‡æŽ›é€²å…§æ ¸ä½¿ç”¨çš„內部接
+å£å¶çˆ¾æœƒè®ŠåŒ–。
+
+如何處ç†å®‰å…¨ä¿®å¾©å¼•起的迴歸?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+在極爲罕見的情æ³ä¸‹ï¼Œå®‰å…¨å•題無法在ä¸å¼•起迴歸的情æ³ä¸‹ä¿®å¾©ï¼›é€™äº›ä¿®å¾©éƒ½è¢«æ”¾æ£„了,
+因爲它們終究會引起å•題。幸é‹çš„æ˜¯é€™ç¨®å…©é›£å¢ƒåœ°åŸºæœ¬éƒ½å¯ä»¥é¿å…,å—影響å€åŸŸçš„主è¦
+開發者以åŠLinus Torvalds本人通常都會努力在ä¸å¼•入迴歸的情æ³ä¸‹è§£æ±ºå®‰å…¨å•題。
+
+如果你ä»ç„¶é¢è‡¨æ­¤ç¨®æƒ…æ³ï¼Œè«‹æŸ¥çœ‹éƒµä»¶åˆ—è¡¨æª”æ¡ˆæ˜¯å¦æœ‰äººç›¡åŠ›é¿å…éŽè¿´æ­¸ã€‚如果沒有,
+請報告它;如有疑å•,請如上所述尋求建議。
+
+當修復迴歸時ä¸å¯é¿å…會引入å¦ä¸€å€‹ï¼Œå¦‚何處ç†ï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+å¾ˆéºæ†¾é€™ç¨®äº‹ç¢ºå¯¦æœƒå‡ºç¾ï¼Œä½†å¹¸é‹çš„æ˜¯ä¸¦ä¸ç¶“常出ç¾ï¼›å¦‚果發生了,å—影響代碼å€çš„資
+深開發者應當調查該å•題以找到é¿å…迴歸的解決方法,至少é¿å…它們的影響。如果你é‡
+到這樣的情æ³ï¼Œå¦‚上所述:檢查之å‰çš„è¨Žè«–æ˜¯å¦æœ‰äººå·²ç¶“盡了最大努力,如有疑å•è«‹å°‹
+求建議。
+
+å°æç¤ºï¼šå¦‚æžœäººå€‘åœ¨æ¯å€‹é–‹ç™¼é€±æœŸä¸­å®šæœŸçµ¦å‡ºä¸»ç·šé ç™¼ä½ˆï¼ˆå³v5.15-rc1或-rc3)以供
+測試,則å¯ä»¥é¿å…這種情æ³ã€‚爲了更好地解釋,å¯ä»¥è¨­æƒ³ä¸€å€‹åœ¨Linux v5.14å’Œv5.15-rc1
+之間集æˆçš„æ›´æ”¹ï¼Œè©²æ›´æ”¹å°Žè‡´äº†è¿´æ­¸ï¼Œä½†åŒæ™‚是應用於5.15-rc1的其他改進的強ä¾è³´ã€‚
+如果有人在5.15發佈之å‰å°±ç™¼ç¾ä¸¦å ±å‘Šäº†é€™å€‹å•題,那麼所有更改都å¯ä»¥ç›´æŽ¥æ’¤éŠ·ï¼Œå¾ž
+而解決迴歸å•題。而就在幾天或幾周後,此解決方案變æˆäº†ä¸å¯èƒ½ï¼Œå› çˆ²ä¸€äº›è»Ÿä»¶å¯èƒ½
+已經開始ä¾è³´æ–¼å¾ŒçºŒæ›´æ”¹ä¹‹ä¸€ï¼šæ’¤éŠ·æ‰€æœ‰æ›´æ”¹å°‡å°Žè‡´ä¸Šè¿°ç”¨æˆ¶è»Ÿä»¶å‡ºç¾è¿´æ­¸ï¼Œé€™æ˜¯ä¸å¯
+接å—的。
+
+若我所ä¾è³´çš„功能在數月å‰è¢«ç§»é™¤äº†ï¼Œæ˜¯è¿´æ­¸å—Žï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+是的,但如å‰ç¯€æ‰€è¿°ï¼Œé€šå¸¸å¾ˆé›£ä¿®å¾©æ­¤é¡žè¿´æ­¸ã€‚因此需è¦é€æ¡ˆè™•ç†ã€‚這也是定期測試主
+ç·šé ç™¼ä½ˆå°æ‰€æœ‰äººæœ‰å¥½è™•çš„å¦ä¸€å€‹åŽŸå› ã€‚
+
+如果我似乎是唯一å—影響的人,是å¦ä»é©ç”¨â€œç„¡è¿´æ­¸â€è¦å‰‡ï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+é©ç”¨ï¼Œä½†åƒ…陿–¼å¯¦éš›ä½¿ç”¨ï¼šLinuxé–‹ç™¼äººå“¡å¸Œæœ›èƒ½å¤ è‡ªç”±åœ°å–æ¶ˆé‚£äº›åªèƒ½åœ¨é–£æ¨“å’Œåšç‰©
+館中找到的硬件的支æŒã€‚
+
+請注æ„,有時爲了å–得進展,ä¸å¾—ä¸å‡ºç¾è¿´æ­¸â€”—後者也是防止Linuxåœæ»¯ä¸å‰æ‰€å¿…需
+的。因此如果迴歸所影響的用戶很少,那麼爲了他們和其他人更大的利益,還是讓事情
+éŽåŽ»å§ã€‚尤其是存在æŸç¨®è¦é¿è¿´æ­¸çš„簡單方法,例如更新一些軟件或者使用專門爲此目
+çš„å‰µå»ºçš„å…§æ ¸åƒæ•¸ã€‚
+
+è¿´æ­¸è¦å‰‡æ˜¯å¦ä¹Ÿé©ç”¨æ–¼staging樹中的代碼?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ä¸ï¼Œåƒè¦‹ `é©ç”¨æ–¼æ‰€æœ‰staging代碼é…ç½®é¸é …的幫助文本
+<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/staging/Kconfig>`_ ,
+å…¶æ—©å·²è²æ˜Ž::
+
+ 請注æ„ï¼šé€™äº›é©…å‹•æ­£åœ¨ç©æ¥µé–‹ç™¼ä¸­ï¼Œå¯èƒ½ç„¡æ³•正常工作,並å¯èƒ½åŒ…嫿œƒåœ¨ä¸ä¹…çš„
+ 將來發生變化的用戶接å£ã€‚
+
+é›–ç„¶staging開發人員通常堅æŒâ€œç„¡è¿´æ­¸â€çš„原則,但有時爲了å–得進展也會é•背它。這就
+是爲什麼當staging樹的WiFi驅動被基本推倒é‡ä¾†æ™‚,有些用戶ä¸å¾—ä¸è™•ç†è¿´æ­¸ï¼ˆé€šå¸¸å¯
+以忽略)。
+
+爲什麼較新版本必須“使用相似é…置編譯â€ï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+因爲Linux內核開發人員有時會集æˆå·²çŸ¥çš„æœƒå°Žè‡´è¿´æ­¸çš„變更,但使它們æˆçˆ²å¯é¸çš„,並
+在內核的默èªé…置下ç¦ç”¨å®ƒå€‘。這一技巧å…許進步,å¦å‰‡â€œç„¡è¿´æ­¸â€è¦å‰‡å°‡å°Žè‡´åœæ»¯ã€‚
+
+例如,試想一個新的å¯ä»¥é˜»æ­¢æƒ¡æ„軟件濫用æŸå€‹å…§æ ¸çš„æŽ¥å£çš„å®‰å…¨ç‰¹æ€§ï¼ŒåŒæ™‚åˆéœ€è¦æ»¿è¶³
+å¦ä¸€å€‹å¾ˆç½•見的應用程åºã€‚上述的方法å¯ä½¿å…©æ–¹éƒ½æ»¿æ„:使用這些應用程åºçš„人å¯ä»¥é—œé–‰
+æ–°çš„å®‰å…¨åŠŸèƒ½ï¼Œè€Œå…¶ä»–ä¸æœƒé‡åˆ°éº»ç…©çš„人å¯ä»¥å•“用它。
+
+如何創建與舊內核相似的é…置?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+用一個已知良好的內核啓動機器,並用 ``make olddefconfig`` é…置新版的Linux。這
+會讓內核的構建腳本從正在é‹è¡Œçš„內核中摘錄é…置文件(“.configâ€æ–‡ä»¶ï¼‰ï¼Œä½œçˆ²å³å°‡ç·¨
+譯的新版本的基礎é…ç½®ï¼›åŒæ™‚將所有新的é…ç½®é¸é …設爲默èªå€¼ï¼Œä»¥ç¦ç”¨å¯èƒ½å°Žè‡´è¿´æ­¸çš„
+新功能。
+
+如何報告在é ç·¨è­¯çš„æ™®é€šå…§æ ¸ä¸­ç™¼ç¾çš„迴歸?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+您需è¦ç¢ºä¿æ–°çš„內核是用與舊版相似的é…置編譯(見上文),因爲那些構建它們的人å¯
+能啓用了一些已知的與新內核ä¸å…¼å®¹çš„特性。如有疑å•,請å‘內核的æä¾›è€…報告å•題並
+尋求建議。
+
+
+用“regzbotâ€è¿½è¹¤è¿´æ­¸çš„æ›´å¤šä¿¡æ¯
+-----------------------------
+
+什麼是迴歸追蹤?爲啥我需è¦é—œå¿ƒå®ƒï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+åƒâ€œç„¡è¿´æ­¸â€é€™æ¨£çš„è¦å‰‡éœ€è¦æœ‰äººä¾†ç¢ºä¿å®ƒå€‘被éµå®ˆï¼Œå¦å‰‡æœƒè¢«æœ‰æ„/ç„¡æ„æ‰“破。歷å²è­‰
+æ˜Žçž­é€™ä¸€é»žå°æ–¼Linux內核開發也é©ç”¨ã€‚這就是爲什麼Linux內核的迴歸跟蹤者Thorsten
+Leemhuis,,和å¦ä¸€äº›äººç›¡åŠ›é—œæ³¨æ‰€æœ‰çš„è¿´æ­¸ç›´åˆ°ä»–å€‘è§£æ±ºã€‚ä»–å€‘å¾žæœªçˆ²æ­¤ç²å¾—報酬,
+因此這項工作是在盡最大努力的基礎上完æˆçš„。
+
+爲什麼/如何使用機器人追蹤Linux內核迴歸?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+由於Linux內核開發éŽç¨‹çš„分佈å¼å’Œé¬†æ•£çµæ§‹ï¼Œå®Œå…¨æ‰‹å‹•跟蹤迴歸已經被證明是相當困難
+的。因此Linux內核的迴歸跟蹤者開發了regzbot來促進這項工作,其長期目標是儘å¯èƒ½çˆ²
+所有相關人員自動化迴歸跟蹤。
+
+Regzbot通éŽç›£è¦–跟蹤的迴歸報告的回覆來工作。此外,它還查找用“Link:â€æ¨™ç±¤å¼•用這
+些報告的補ä¸ï¼›å°é€™äº›è£œä¸çš„回覆也會被跟蹤。çµåˆé€™äº›æ•¸æ“šï¼Œå¯ä»¥å¾ˆå¥½åœ°çž­è§£ç•¶å‰ä¿®
+復éŽç¨‹çš„狀態。
+
+如何查看regzbotç•¶å‰è¿½è¹¤çš„迴歸?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+åƒè¦‹ `regzbot在線 <https://linux-regtracking.leemhuis.info/regzbot/>`_ 。
+
+何種å•題å¯ä»¥ç”±regzbot追蹤?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+該機器人åªçˆ²äº†è·Ÿè¹¤è¿´æ­¸ï¼Œå› æ­¤è«‹ä¸è¦è®“regzbot涉åŠå¸¸è¦å•é¡Œã€‚ä½†æ˜¯å°æ–¼Linux內核的
+迴歸跟蹤者來說,讓regzbot跟蹤嚴é‡å•題也å¯ä»¥ï¼Œå¦‚æœ‰é—œæŽ›èµ·ã€æå£žæ•¸æ“šæˆ–å…§éƒ¨éŒ¯èª¤
+(Panicã€Oopsã€BUG()ã€warning…)的報告。
+
+如何修改被追蹤迴歸的相關信æ¯ï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+在直接或間接回復報告郵件時使用“regzbot命令â€å³å¯ã€‚最簡單的方法是:在“已發é€â€æ–‡
+件夾或郵件列表存檔中找到報告,然後使用郵件客戶端的“全部回覆â€åŠŸèƒ½å°å…¶é€²è¡Œå›žè¦†ã€‚
+在該郵件中的ç¨ç«‹æ®µè½ä¸­å¯ä½¿ç”¨ä»¥ä¸‹å‘½ä»¤ä¹‹ä¸€ï¼ˆå³ä½¿ç”¨ç©ºè¡Œå°‡é€™äº›å‘½ä»¤ä¸­çš„一個或多個與
+其餘郵件文本分隔開)。
+
+ * 更新迴歸引入起點,例如在執行二分之後::
+
+ #regzbot introduced: 1f2e3d4c5d
+
+ * 設置或更新標題::
+
+ #regzbot title: foo
+
+ * 監視討論或bugzilla.kernel.org上有關討論或修復的工單::
+
+ #regzbot monitor: https://lore.kernel.org/r/30th.anniversary.repost@klaava.Helsinki.FI/
+ #regzbot monitor: https://bugzilla.kernel.org/show_bug.cgi?id=123456789
+
+ * 標記一個有更多相關細節的地方,例如有關但主題ä¸åŒçš„éƒµä»¶åˆ—è¡¨å¸–å­æˆ–缺陷追蹤器中的工單::
+
+ #regzbot link: https://bugzilla.kernel.org/show_bug.cgi?id=123456789
+
+ * 標記迴歸已失效::
+
+ #regzbot invalid: wasn't a regression, problem has always existed
+
+Regzbot還支æŒå…¶ä»–一些主è¦ç”±é–‹ç™¼äººå“¡æˆ–迴歸追蹤人員使用的命令。命令的更多細節請
+åƒè€ƒ `å…¥é–€æŒ‡å— <https://gitlab.com/knurd42/regzbot/-/blob/main/docs/getting_started.md>`_
+å’Œ `åƒè€ƒæ‰‹å†Š <https://gitlab.com/knurd42/regzbot/-/blob/main/docs/reference.md>`_ 。
+
+..
+ æ­£æ–‡çµæŸ
+..
+ 如本文件開頭所述,本文以GPL-2.0+或CC-BY-4.0許å¯ç™¼è¡Œã€‚如您想僅在CC-BY-4.0許
+ å¯ä¸‹é‡åˆ†ç™¼æœ¬æ–‡ï¼Œè«‹ç”¨â€œLinux內核開發者â€ä½œçˆ²ä½œè€…ï¼Œä¸¦ç”¨å¦‚ä¸‹éˆæŽ¥ä½œçˆ²ä¾†æºï¼š
+ https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/Documentation/translations/zh_CN/admin-guide/reporting-regressions.rst
+..
+ 注æ„:本RSTæ–‡ä»¶å…§å®¹åªæœ‰åœ¨ä¾†è‡ªLinuxå…§æ ¸æºä»£ç¢¼æ™‚是使用CC-BY-4.0許å¯çš„,因爲經
+ éŽè™•ç†çš„版本(如經內核的構建系統)å¯èƒ½åŒ…å«ä¾†è‡ªä½¿ç”¨æ›´åš´æ ¼è¨±å¯è­‰çš„æ–‡ä»¶çš„內容。
+
diff --git a/Documentation/translations/zh_TW/admin-guide/security-bugs.rst b/Documentation/translations/zh_TW/admin-guide/security-bugs.rst
index 65c8dd24c96d..c0e9fc247695 100644
--- a/Documentation/translations/zh_TW/admin-guide/security-bugs.rst
+++ b/Documentation/translations/zh_TW/admin-guide/security-bugs.rst
@@ -19,17 +19,17 @@ Linux內核開發人員éžå¸¸é‡è¦–安全性。因此我們想知é“何時發ç¾
-----
å¯ä»¥é€šéŽé›»å­éƒµä»¶<security@kernel.org>è¯ç¹«Linux內核安全團隊。這是一個安全人員
-çš„ç§æœ‰åˆ—表,他們將幫助驗證錯誤報告並開發和發布修復程åºã€‚如果您已經有了一個
+çš„ç§æœ‰åˆ—表,他們將幫助驗證錯誤報告並開發和發佈修復程åºã€‚如果您已經有了一個
修復,請將其包å«åœ¨æ‚¨çš„報告中,這樣å¯ä»¥å¤§å¤§åŠ å¿«é€²ç¨‹ã€‚å®‰å…¨åœ˜éšŠå¯èƒ½æœƒå¾žå€åŸŸç¶­è­·
-人員那裡ç²å¾—é¡å¤–的幫助,以ç†è§£å’Œä¿®å¾©å®‰å…¨æ¼æ´žã€‚
+人員那è£ç²å¾—é¡å¤–的幫助,以ç†è§£å’Œä¿®å¾©å®‰å…¨æ¼æ´žã€‚
與任何缺陷一樣,æä¾›çš„ä¿¡æ¯è¶Šå¤šï¼Œè¨ºæ–·å’Œä¿®å¾©å°±è¶Šå®¹æ˜“ã€‚å¦‚æžœæ‚¨ä¸æ¸…æ¥šå“ªäº›ä¿¡æ¯æœ‰ç”¨ï¼Œ
-請查看「Documentation/translations/zh_TW/admin-guide/reporting-issues.rstã€ä¸­
+請查看“Documentation/translations/zh_CN/admin-guide/reporting-issues.rstâ€ä¸­
æ¦‚è¿°çš„æ­¥é©Ÿã€‚ä»»ä½•åˆ©ç”¨æ¼æ´žçš„æ”»æ“Šä»£ç¢¼éƒ½éžå¸¸æœ‰ç”¨ï¼Œæœªç¶“å ±å‘Šè€…åŒæ„䏿œƒå°å¤–發布,除
éžå·²ç¶“公開。
-請儘å¯èƒ½ç™¼é€ç„¡é™„件的純文本電å­éƒµä»¶ã€‚如果所有的細節都è—在附件里,那麼就很難å°
-一個複雜的å•é¡Œé€²è¡Œä¸Šä¸‹æ–‡å¼•ç”¨çš„è¨Žè«–ã€‚æŠŠå®ƒæƒ³åƒæˆä¸€å€‹
+請儘å¯èƒ½ç™¼é€ç„¡é™„件的純文本電å­éƒµä»¶ã€‚如果所有的細節都è—在附件è£ï¼Œé‚£éº¼å°±å¾ˆé›£å°
+一個複雜的å•題進行上下文引用的討論。把它想象æˆä¸€å€‹
:doc:`常è¦çš„è£œä¸æäº¤ <../process/submitting-patches>` (å³ä½¿ä½ é‚„沒有補ä¸ï¼‰ï¼š
æè¿°å•é¡Œå’Œå½±éŸ¿ï¼Œåˆ—å‡ºå¾©ç¾æ­¥é©Ÿï¼Œç„¶å¾Œçµ¦å‡ºä¸€å€‹å»ºè­°çš„解決方案,所有這些都是純文本的。
@@ -38,15 +38,15 @@ Linux內核開發人員éžå¸¸é‡è¦–安全性。因此我們想知é“何時發ç¾
å®‰å…¨åˆ—è¡¨ä¸æ˜¯å…¬é–‹æ¸ é“。爲此,請åƒè¦‹ä¸‹é¢çš„å”作。
-一旦開發出了å¥å£¯çš„補ä¸ï¼Œç™¼å¸ƒéŽç¨‹å°±é–‹å§‹äº†ã€‚å°å…¬é–‹çš„缺陷的修復會立å³ç™¼å¸ƒã€‚
+一旦開發出了å¥å£¯çš„補ä¸ï¼Œç™¼ä½ˆéŽç¨‹å°±é–‹å§‹äº†ã€‚å°å…¬é–‹çš„缺陷的修復會立å³ç™¼ä½ˆã€‚
-å„˜ç®¡æˆ‘å€‘å‚¾å‘æ–¼åœ¨æœªå…¬é–‹ç¼ºé™·çš„修復å¯ç”¨æ™‚å³ç™¼å¸ƒè£œä¸ï¼Œä½†æ‡‰å ±å‘Šè€…或å—影響方的請求,
-這å¯èƒ½æœƒè¢«æŽ¨é²åˆ°ç™¼å¸ƒéŽç¨‹é–‹å§‹å¾Œçš„7æ—¥å…§ï¼Œå¦‚æžœæ ¹æ“šç¼ºé™·çš„åš´é‡æ€§éœ€è¦æ›´å¤šçš„æ™‚間,
-則å¯é¡å¤–延長到14天。推é²ç™¼å¸ƒä¿®å¾©çš„å”¯ä¸€æœ‰æ•ˆåŽŸå› æ˜¯çˆ²äº†é©æ‡‰QAçš„é‚輯和需è¦ç™¼å¸ƒ
+å„˜ç®¡æˆ‘å€‘å‚¾å‘æ–¼åœ¨æœªå…¬é–‹ç¼ºé™·çš„修復å¯ç”¨æ™‚å³ç™¼ä½ˆè£œä¸ï¼Œä½†æ‡‰å ±å‘Šè€…或å—影響方的請求,
+這å¯èƒ½æœƒè¢«æŽ¨é²åˆ°ç™¼ä½ˆéŽç¨‹é–‹å§‹å¾Œçš„7æ—¥å…§ï¼Œå¦‚æžœæ ¹æ“šç¼ºé™·çš„åš´é‡æ€§éœ€è¦æ›´å¤šçš„æ™‚間,
+則å¯é¡å¤–延長到14天。推é²ç™¼ä½ˆä¿®å¾©çš„å”¯ä¸€æœ‰æ•ˆåŽŸå› æ˜¯çˆ²äº†é©æ‡‰QAçš„é‚輯和需è¦ç™¼ä½ˆ
å”èª¿çš„å¤§è¦æ¨¡éƒ¨ç½²ã€‚
é›–ç„¶å¯èƒ½èˆ‡å—信任的個人共享å—é™ä¿¡æ¯ä»¥é–‹ç™¼ä¿®å¾©ï¼Œä½†æœªç¶“報告者許å¯ï¼Œæ­¤é¡žä¿¡æ¯ä¸æœƒ
-與修復程åºä¸€èµ·ç™¼å¸ƒæˆ–發布在任何其他披露渠é“上。這包括但ä¸é™æ–¼åŽŸå§‹éŒ¯èª¤å ±å‘Šå’Œ
+與修復程åºä¸€èµ·ç™¼ä½ˆæˆ–發佈在任何其他披露渠é“上。這包括但ä¸é™æ–¼åŽŸå§‹éŒ¯èª¤å ±å‘Šå’Œ
å¾ŒçºŒè¨Žè«–ï¼ˆå¦‚æœ‰ï¼‰ã€æ¼æ´žã€CVEä¿¡æ¯æˆ–報告者的身份。
æ›å¥è©±èªªï¼Œæˆ‘們唯一感興趣的是修復缺陷。æäº¤çµ¦å®‰å…¨åˆ—表的所有其他資料以åŠå°å ±å‘Š
@@ -57,10 +57,10 @@ Linux內核開發人員éžå¸¸é‡è¦–安全性。因此我們想知é“何時發ç¾
å°æ•感缺陷(例如那些å¯èƒ½å°Žè‡´æ¬Šé™æå‡çš„缺陷)的修復å¯èƒ½éœ€è¦èˆ‡ç§æœ‰éƒµä»¶åˆ—表
<linux-distros@vs.openwall.org>進行å”調,以便分發供應商åšå¥½æº–備,在公開披露
-ä¸Šæ¸¸è£œä¸æ™‚發布一個已修復的內核。發行版將需è¦ä¸€äº›æ™‚間來測試建議的補ä¸ï¼Œé€šå¸¸
-æœƒè¦æ±‚至少幾天的é™åˆ¶ï¼Œè€Œä¾›æ‡‰å•†æ›´æ–°ç™¼å¸ƒæ›´å‚¾å‘於周二至周四。若åˆé©ï¼Œå®‰å…¨åœ˜éšŠ
+ä¸Šæ¸¸è£œä¸æ™‚發佈一個已修復的內核。發行版將需è¦ä¸€äº›æ™‚間來測試建議的補ä¸ï¼Œé€šå¸¸
+æœƒè¦æ±‚至少幾天的é™åˆ¶ï¼Œè€Œä¾›æ‡‰å•†æ›´æ–°ç™¼å¸ƒæ›´å‚¾å‘於週二至週四。若åˆé©ï¼Œå®‰å…¨åœ˜éšŠ
å¯ä»¥å”助這種å”調,或者報告者å¯ä»¥å¾žä¸€é–‹å§‹å°±åŒ…括linux發行版。在這種情æ³ä¸‹ï¼Œè«‹
-記ä½åœ¨é›»å­éƒµä»¶ä¸»é¡Œè¡Œå‰é¢åŠ ä¸Šã€Œ[vs]ã€ï¼Œå¦‚linux發行版wiki中所述:
+記ä½åœ¨é›»å­éƒµä»¶ä¸»é¡Œè¡Œå‰é¢åŠ ä¸Šâ€œ[vs]â€ï¼Œå¦‚linux發行版wiki中所述:
<http://oss-security.openwall.org/wiki/mailing-lists/distros#how-to-use-the-lists>。
CVE分é…
diff --git a/Documentation/translations/zh_TW/admin-guide/sysrq.rst b/Documentation/translations/zh_TW/admin-guide/sysrq.rst
new file mode 100644
index 000000000000..4a08db00a495
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/sysrq.rst
@@ -0,0 +1,281 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/sysrq.rst
+
+:翻譯:
+
+ 黃è»è¯ Junhua Huang <huang.junhua@zte.com.cn>
+
+:æ ¡è­¯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+.. _tw_admin-guide_sysrq:
+
+Linux 魔法系統請求éµé§­å®¢
+========================
+
+é‡å° sysrq.c 的文檔說明
+
+什麼是魔法 SysRq éµï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~
+
+它是一個你å¯ä»¥è¼¸å…¥çš„具有魔法般的組åˆéµã€‚
+無論內核在åšä»€éº¼ï¼Œå…§æ ¸éƒ½æœƒéŸ¿æ‡‰ SysRq éµçš„輸入,除éžå…§æ ¸å®Œå…¨å¡æ­»ã€‚
+
+如何使能魔法 SysRq éµï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~
+
+在é…置內核時,我們需è¦è¨­ç½® 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' 爲 'Y'。
+ç•¶é‹è¡Œä¸€å€‹ç·¨è­¯é€² sysrq 功能的內核時,/proc/sys/kernel/sysrq 控制ç€è¢«
+SysRq éµèª¿ç”¨çš„功能許å¯ã€‚這個文件的默èªå€¼ç”± CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE
+é…置符號設定,文件本身默èªè¨­ç½®çˆ² 1。以下是 /proc/sys/kernel/sysrq 中å¯èƒ½çš„
+值列表:
+
+ - 0 - 完全ä¸ä½¿èƒ½ SysRq éµ
+ - 1 - 使能 SysRq éµçš„全部功能
+ - >1 - å°æ–¼å…許的 SysRq éµåŠŸèƒ½çš„æ¯”ç‰¹æŽ©ç¢¼ï¼ˆåƒè¦‹ä¸‹é¢æ›´è©³ç´°çš„功能æè¿°ï¼‰::
+
+ 2 = 0x2 - ä½¿èƒ½å°æŽ§åˆ¶æª¯æ—¥èªŒè¨˜éŒ„ç´šåˆ¥çš„æŽ§åˆ¶
+ 4 = 0x4 - 使能å°éµç›¤çš„æŽ§åˆ¶ (SAK, unraw)
+ 8 = 0x8 - 使能å°é€²ç¨‹çš„調試導出等
+ 16 = 0x10 - ä½¿èƒ½åŒæ­¥å‘½ä»¤
+ 32 = 0x20 - ä½¿èƒ½é‡æ–°æŽ›è¼‰åªè®€
+ 64 = 0x40 - 使能å°é€²ç¨‹çš„信號æ“作 (term, kill, oom-kill)
+ 128 = 0x80 - å…許é‡å•“ã€æ–·é›»
+ 256 = 0x100 - å…許讓所有實時任務變普通任務
+
+ä½ å¯ä»¥é€šéŽå¦‚下命令把值設置到這個文件中::
+
+ echo "number" >/proc/sys/kernel/sysrq
+
+這è£è¢«å¯«å…¥çš„ number å¯ä»¥æ˜¯ 10 é€²åˆ¶æ•¸ï¼Œæˆ–è€…æ˜¯å¸¶ç€ 0x å‰ç¶´çš„ 16 進制數。
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 必須是以 16 進制數寫入。
+
+注æ„,``/proc/sys/kernel/sysrq`` 的值隻影響通éŽéµç›¤è§¸ç™¼ SySRq çš„èª¿ç”¨ï¼Œå°æ–¼
+é€šéŽ ``/proc/sysrq-trigger`` 的任何æ“作調用都是å…許的
+(通éŽå…·æœ‰ç³»çµ±æ¬Šé™çš„用戶)。
+
+如何使用魔法 SysRq éµï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~
+
+在 x86 架構上
+ ä½ å¯ä»¥æŒ‰ä¸‹éµç›¤çµ„åˆéµ :kbd:`ALT-SysRq-<command key>`。
+
+ .. note::
+ 一些éµç›¤å¯èƒ½æ²’有標識 'SySRq' éµã€‚'SySRq' éµä¹Ÿè¢«ç•¶åš 'Print Screen'éµã€‚
+ åŒæ™‚有些éµç›¤ç„¡æ³•處ç†åŒæ™‚按下這麼多éµï¼Œå› æ­¤ä½ å¯ä»¥å…ˆæŒ‰ä¸‹éµç›¤ :kbd:`Alt` éµï¼Œ
+ 然後按下éµç›¤ :kbd:`SysRq` éµï¼Œå†é‡‹æ”¾éµç›¤ :kbd:`SysRq` éµï¼Œä¹‹å¾ŒæŒ‰ä¸‹éµç›¤ä¸Šå‘½ä»¤éµ
+ :kbd:`<command key>`,最後釋放所有éµã€‚
+
+在 SPARC 架構上
+ ä½ å¯ä»¥æŒ‰ä¸‹éµç›¤çµ„åˆéµ :kbd:`ALT-STOP-<command key>` 。
+
+在串行控制檯(åªé‡å° PC 類型的標準串å£ï¼‰
+ ä½ å¯ä»¥ç™¼ä¸€å€‹ ``BREAK`` ,然後在 5 秒內發é€ä¸€å€‹å‘½ä»¤éµï¼Œ
+ ç™¼é€ ``BREAK`` 兩次將被翻譯爲一個正常的 BREAK æ“作。
+
+在 PowerPC 架構上
+ 按下éµç›¤çµ„åˆéµ :kbd:`ALT - Print Screen` (或者 :kbd:`F13`) - :kbd:`<命令éµ>` 。
+ :kbd:`Print Screen` (或者 :kbd:`F13`) - :kbd:`<命令éµ>` 或許也能實ç¾ã€‚
+
+在其他架構上
+ 如果你知é“其他架構的組åˆéµï¼Œè«‹å‘Šè¨´æˆ‘,我å¯ä»¥æŠŠå®ƒå€‘添加到這部分。
+
+在所有架構上
+ 寫一個字符到 /proc/sysrq-trigger 文件,例如::
+
+ echo t > /proc/sysrq-trigger
+
+é€™å€‹å‘½ä»¤éµ :kbd:`<command key>` 是å€åˆ†å¤§å°å¯«çš„。
+
+什麼是命令éµï¼Ÿ
+~~~~~~~~~~~~~~
+
+=========== ================================================================
+å‘½ä»¤éµ åŠŸèƒ½
+=========== ================================================================
+``b`` 將立å³é‡å•“ç³»çµ±ï¼Œä¸æœƒåŒæ­¥æˆ–者å¸è¼‰ç£ç›¤ã€‚
+
+``c`` 將執行系統 crash,如果é…置了系統 crashdump,將執行 crashdump。
+
+``d`` é¡¯ç¤ºæ‰€æœ‰æŒæœ‰çš„鎖。
+
+``e`` ç™¼é€ SIGTERM 信號給所有進程,除了 init 進程。
+
+``f`` 將調用 oom killer 殺掉一個éŽåº¦ä½”用內存的進程,如果什麼任務都沒殺,
+ ä¹Ÿä¸æœƒ panic。
+
+``g`` kgdb 使用(內核調試器)。
+
+``h`` 將會顯示幫助。(實際上除了這è£åˆ—舉的éµï¼Œå…¶ä»–的都將顯示幫助,
+ 但是 ``h`` 容易記ä½ï¼‰:-)
+
+``i`` ç™¼é€ SIGKILL 給所有進程,除了 init 進程。
+
+``j`` 強制性的 “解å‡å®ƒâ€ - 用於被 FIFREEZE ioctl æ“作å‡ä½çš„æ–‡ä»¶ç³»çµ±ã€‚
+
+``k`` 安全訪å•祕鑰(SAK)殺掉在當å‰è™›æ“¬æŽ§åˆ¶æª¯çš„æ‰€æœ‰ç¨‹åºï¼Œæ³¨æ„:åƒè€ƒ
+ ä¸‹é¢ SAK 節é‡è¦è«–述。
+
+``l`` 顯示所有活動 cpu 的棧回溯。
+
+``m`` 將導出當å‰å…§å­˜ä¿¡æ¯åˆ°ä½ çš„æŽ§åˆ¶æª¯ã€‚
+
+``n`` ç”¨æ–¼ä½¿æ‰€æœ‰å¯¦æ™‚ä»»å‹™è®Šæˆæ™®é€šä»»å‹™ã€‚
+
+``o`` 將關閉系統(如果é…置和支æŒçš„話)。
+
+``p`` 將導出當å‰å¯„存器和標誌ä½åˆ°æŽ§åˆ¶æª¯ã€‚
+
+``q`` 將導出æ¯å€‹ cpu 上所有已è£å‚™çš„é«˜ç²¾åº¦å®šæ™‚å™¨ï¼ˆä¸æ˜¯å®Œæ•´çš„
+ time_list 文件顯示的 timers)和所有時é˜äº‹ä»¶è¨­å‚™çš„詳細信æ¯ã€‚
+
+``r`` 關閉éµç›¤çš„原始模å¼ï¼Œè¨­ç½®çˆ²è½‰æ›æ¨¡å¼ã€‚
+
+``s`` å°‡å˜—è©¦åŒæ­¥æ‰€æœ‰çš„已掛載文件系統。
+
+``t`` å°‡å°Žå‡ºç•¶å‰æ‰€æœ‰ä»»å‹™åˆ—表和它們的信æ¯åˆ°æŽ§åˆ¶æª¯ã€‚
+
+``u`` å°‡å˜—è©¦é‡æ–°æŽ›è¼‰å·²æŽ›è¼‰æ–‡ä»¶ç³»çµ±çˆ²åªè®€ã€‚
+
+``v`` 強制æ¢å¾©å¹€ç·©å­˜æŽ§åˆ¶æª¯ã€‚
+``v`` 觸發 ETM 緩存導出 [ARM 架構特有]
+
+``w`` 導出處於ä¸å¯ä¸­æ–·ç‹€æ…‹ï¼ˆé˜»å¡žï¼‰çš„任務。
+
+``x`` 在 ppc/powerpc 架構上用於 xmon 接å£ã€‚
+ 在 sparc64 架構上用於顯示全局的 PMU(性能監控單元)寄存器。
+ 在 MIPS 架構上導出所有的 tlb æ¢ç›®ã€‚
+
+``y`` 顯示全局 cpu 寄存器 [SPARC-64 架構特有]
+
+``z`` 導出 ftrace 緩存信æ¯
+
+``0``-``9`` 設置控制檯日誌級別,該級別控制什麼樣的內核信æ¯å°‡è¢«æ‰“å°åˆ°ä½ çš„
+ 控制檯。(比如 ``0`` ï¼Œå°‡ä½¿å¾—åªæœ‰ç·Šæ€¥ä¿¡æ¯ï¼Œåƒ PANICs or OOPSes
+ æ‰èƒ½åˆ°ä½ çš„æŽ§åˆ¶æª¯ã€‚)
+=========== ================================================================
+
+好了,我能用他們åšä»€éº¼å‘¢ï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+嗯,當你的 X æœå‹™ç«¯æˆ–者 svgalib 程åºå´©æ½°ï¼Œunraw(r) éžåŽŸå§‹æ¨¡å¼å‘½ä»¤éµæ˜¯éžå¸¸
+方便的。
+
+sak(k)(安全訪å•ç¥•é‘°ï¼‰åœ¨ä½ å˜—è©¦ç™»é™¸çš„åŒæ™‚ï¼Œåˆæƒ³ç¢ºä¿ç•¶å‰æŽ§åˆ¶æª¯æ²’有å¯ä»¥ç²å–ä½ çš„
+密碼的特洛伊木馬程åºé‹è¡Œæ™‚是有用的。它會殺掉給定控制檯的所有程åºï¼Œé€™æ¨£ä½ 
+å°±å¯ä»¥ç¢ºèªç•¶å‰çš„登陸æç¤ºç¨‹åºæ˜¯å¯¦éš›ä¾†è‡ª init 進程的程åºï¼Œè€Œä¸æ˜¯æŸäº›ç‰¹æ´›ä¼Š
+木馬程åºã€‚
+
+.. important::
+
+ 在其實際的形å¼ä¸­ï¼Œåœ¨å…¼å®¹ C2 å®‰å…¨æ¨™æº–çš„ç³»çµ±ä¸Šï¼Œå®ƒä¸æ˜¯ä¸€å€‹çœŸæ­£çš„ SAK,
+ å®ƒä¹Ÿä¸æ‡‰è©²èª¤èªçˆ²æ­¤ã€‚
+
+似乎其他人發ç¾å…¶å¯ä»¥ä½œçˆ²ï¼ˆç³»çµ±çµ‚ç«¯è¯æ©Ÿéµï¼‰ç•¶ä½ æƒ³é€€å‡ºä¸€å€‹ç¨‹åºï¼Œ
+åŒæ™‚䏿œƒè®“ä½ åˆ‡æ›æŽ§åˆ¶æª¯çš„æ–¹æ³•ã€‚ï¼ˆæ¯”å¦‚ï¼ŒX æœå‹™ç«¯æˆ–者 svgalib 程åºï¼‰
+
+``reboot(b)`` 是個好方法,當你ä¸èƒ½é—œé–‰æ©Ÿå™¨æ™‚ï¼Œå®ƒç­‰åŒæ–¼æŒ‰ä¸‹"復ä½"按鈕。
+
+``crash(c)`` å¯ä»¥ç”¨æ–¼æ‰‹å‹•觸發一個 crashdump,當系統å¡ä½æ™‚。
+注æ„ç•¶ crashdump 機制ä¸å¯ç”¨æ™‚ï¼Œé€™å€‹åªæ˜¯è§¸ç™¼ä¸€å€‹å…§æ ¸ crash。
+
+``sync(s)`` 在拔掉å¯ç§»å‹•介質之å‰ï¼Œæˆ–è€…åœ¨ä½¿ç”¨ä¸æä¾›å„ªé›…é—œæ©Ÿçš„
+æ•‘æ´ shell 之後很方便 -- 它將確ä¿ä½ çš„æ•¸æ“šè¢«å®‰å…¨åœ°å¯«å…¥ç£ç›¤ã€‚注æ„,在你看到
+å±å¹•ä¸Šå‡ºç¾ "OK" å’Œ "Done" 之å‰ï¼ŒåŒæ­¥é‚„沒有發生。
+
+``umount(u)`` å¯ä»¥ç”¨ä¾†æ¨™è¨˜æ–‡ä»¶ç³»çµ±æ­£å¸¸å¸è¼‰ï¼Œå¾žæ­£åœ¨é‹è¡Œçš„系統角度來看,它們將
+è¢«é‡æ–°æŽ›è¼‰çˆ²åªè®€ã€‚這個釿–°æŽ›è¼‰å‹•作直到你看到 "OK" å’Œ "Done" ä¿¡æ¯å‡ºç¾åœ¨å±å¹•上
+纔算完æˆã€‚
+
+日誌級別 ``0`` - ``9`` 用於當你的控制檯被大é‡çš„內核信æ¯è¡æ“Šï¼Œä½ ä¸æƒ³çœ‹è¦‹çš„æ™‚候。
+鏿“‡ ``0`` å°‡ç¦æ­¢é™¤äº†æœ€ç·Šæ€¥çš„內核信æ¯å¤–的所有的內核信æ¯è¼¸å‡ºåˆ°æŽ§åˆ¶æª¯ã€‚(但是如果
+syslogd/klogd 進程是é‹è¡Œçš„,它們ä»å°‡è¢«è¨˜éŒ„。)
+
+``term(e)`` å’Œ ``kill(i)`` 用於當你有些有點失控的進程,你無法通éŽå…¶ä»–æ–¹å¼æ®ºæŽ‰
+它們的時候,特別是它正在創建其他進程。
+
+"just thaw ``it(j)`` " 用於當你的系統由於一個 FIFREEZE ioctl 調用而產生的文件
+系統å‡çµï¼Œè€Œå°Žè‡´çš„ä¸éŸ¿æ‡‰æ™‚。
+
+有的時候 SysRq éµåœ¨ä½¿ç”¨å®ƒä¹‹å¾Œï¼Œçœ‹èµ·ä¾†åƒæ˜¯â€œå¡ä½â€äº†ï¼Œæˆ‘能åšäº›ä»€éº¼ï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+這也會發生在我這,我發ç¾è¼•敲éµç›¤å…©å´çš„ shiftã€alt å’Œ control éµï¼Œç„¶å¾Œå†æ¬¡æ•²æ“Š
+一個無效的 SysRq éµåºåˆ—å¯ä»¥è§£æ±ºå•題。(比如,åƒéµç›¤çµ„åˆéµ :kbd:`alt-sysrq-z` )
+切æ›åˆ°å¦ä¸€å€‹è™›æ“¬æŽ§åˆ¶æª¯ï¼ˆéµç›¤æ“作 :kbd:`ALT+Fn` ),然後å†åˆ‡å›žä¾†æ‡‰è©²ä¹Ÿæœ‰å¹«åŠ©ã€‚
+
+我敲擊了 SysRq éµï¼Œä½†åƒæ˜¯ä»€éº¼éƒ½æ²’發生,發生了什麼錯誤?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+有一些éµç›¤å°æ–¼ SysRq éµè¨­ç½®äº†ä¸åŒçš„éµå€¼ï¼Œè€Œä¸æ˜¯æå‰å®šç¾©çš„ 99
+(查看在 ``include/uapi/linux/input-event-codes.h`` 文件中 ``KEY_SYSRQ`` 的定義)
+或者就根本沒有 SysRq éµã€‚在這些場景下,執行 ``showkey -s`` 命令來找到一個åˆé©
+的掃æç¢¼åºåˆ—,然後使用 ``setkeycodes <sequence> 99`` 命令映射這個åºåˆ—值到通用
+çš„ SysRq éµç·¨ç¢¼ä¸Šï¼ˆæ¯”如 ``setkeycodes e05b 99`` )。最好將這個命令放在啓動腳本
+中。
+哦,順便說一å¥ï¼Œä½ åç§’é˜ä¸è¼¸å…¥ä»»ä½•æ±è¥¿å°±å°‡é€€å‡º “showkeyâ€ã€‚
+
+我想添加一個 SysRq éµäº‹ä»¶åˆ°ä¸€å€‹æ¨¡å¡Šä¸­ï¼Œå¦‚何去åšå‘¢ï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+çˆ²äº†è¨»å†Šä¸€å€‹åŸºç¤Žå‡½æ•¸åˆ°é€™å€‹è¡¨ä¸­ï¼Œé¦–å…ˆä½ å¿…é ˆåŒ…å« ``include/linux/sysrq.h`` é ­
+文件,這個頭文件定義了你所需è¦çš„æ‰€æœ‰æ±è¥¿ã€‚然後你必須創建一個 ``sysrq_key_op``
+çµæ§‹é«”,然後åˆå§‹åŒ–它,使用如下內容,A) 你將使用的這個éµçš„處ç†å‡½æ•¸ï¼Œ B) 一個
+help_msg 字符串,在 SysRq 鵿‰“å°å¹«åŠ©ä¿¡æ¯æ™‚將打å°å‡ºä¾†ï¼ŒC) 一個 action_msg å­—
+符串,就在你的處ç†å‡½æ•¸èª¿ç”¨å‰æ‰“å°å‡ºä¾†ã€‚你的處ç†å‡½æ•¸å¿…須符åˆåœ¨ 'sysrq.h' 文件中
+的函數原型。
+
+在 ``sysrq_key_op`` çµæ§‹é«”被創建後,你å¯ä»¥èª¿ç”¨å…§æ ¸å‡½æ•¸
+``register_sysrq_key(int key, const struct sysrq_key_op *op_p);``,
+該函數在表中的 'key' å°æ‡‰ä½ç½®å…§å®¹æ˜¯ç©ºçš„æƒ…æ³ä¸‹ï¼Œå°‡é€šéŽ ``op_p`` 指é‡è¨»å†Šé€™å€‹æ“作
+函數到表中 'key' å°æ‡‰ä½ç½®ä¸Šã€‚在模塊å¸è¼‰çš„æ™‚候,你必須調用
+``unregister_sysrq_key(int key, const struct sysrq_key_op *op_p)`` 函數,該函數
+åªæœ‰åœ¨ç•¶å‰è©²éµå°æ‡‰çš„處ç†å‡½æ•¸è¢«è¨»å†Šåˆ°äº† 'key' å°æ‡‰ä½ç½®æ™‚,纔會移除 'op_p' 指é‡
+å°æ‡‰çš„éµå€¼æ“作函數。這是爲了防止在你註冊之後,該ä½ç½®è¢«æ”¹å¯«çš„æƒ…æ³ã€‚
+
+魔法 SysRq éµç³»çµ±çš„å·¥ä½œåŽŸç†æ˜¯å°‡éµå°æ‡‰æ“作函數註冊到éµçš„æ“ä½œæŸ¥æ‰¾è¡¨ï¼Œ
+該表定義在 'drivers/tty/sysrq.c' 文件中。
+該éµè¡¨æœ‰è¨±å¤šåœ¨ç·¨è­¯æ™‚候就註冊進去的æ“作函數,但是是å¯è®Šçš„。
+並且有兩個函數作爲æ“作該表的接å£è¢«å°Žå‡º::
+
+ register_sysrq_key 和 unregister_sysrq_key.
+
+當然,永é ä¸è¦åœ¨è¡¨ä¸­ç•™ä¸‹ç„¡æ•ˆæŒ‡é‡ï¼Œå³ï¼Œç•¶ä½ çš„æ¨¡å¡Šå­˜åœ¨èª¿ç”¨ register_sysrq_key()
+函數,它一定è¦èª¿ç”¨ unregister_sysrq_key() 來清除它使用éŽçš„ SysRq éµè¡¨æ¢ç›®ã€‚
+è¡¨ä¸­çš„ç©ºæŒ‡é‡æ˜¯å®‰å…¨çš„。:)
+
+å¦‚æžœå°æ–¼æŸç¨®åŽŸå› ï¼Œåœ¨ handle_sysrq 調用的處ç†å‡½æ•¸ä¸­ï¼Œä½ èªçˆ²æœ‰å¿…è¦èª¿ç”¨
+handle_sysrq 函數時,你必須æ„識到當å‰ä½ è™•æ–¼ä¸€å€‹éŽ–ä¸­ï¼ˆä½ åŒæ™‚也處於一箇中斷處ç†
+函數中,這æ„味ç€ä¸èƒ½ç¡çœ ï¼‰ã€‚所以這時你必須使用 ``__handle_sysrq_nolock`` 替代。
+
+當我敲擊一個 SysRq 組åˆéµæ™‚ï¼Œåªæœ‰æ¨™é¡Œæ‰“å°å‡ºç¾åœ¨æŽ§åˆ¶æª¯ï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+SysRq éµçš„輸出和所有其他控制檯輸出一樣,å—制於控制檯日誌級別控制。
+這æ„味ç€ï¼Œå¦‚果內核以發行版內核中常見的 "quiet" æ–¹å¼å•“動,則輸出å¯èƒ½ä¸æœƒå‡ºç¾åœ¨å¯¦éš›
+的控制檯上,å³ä½¿å®ƒæœƒå‡ºç¾åœ¨ dmesg 緩存中,也å¯ä»¥é€šéŽ dmesg 命令和 ``/proc/kmsg``
+文件的消費訪å•到。作爲一個特例,來自 sysrq 命令的標題行將被傳éžçµ¦æ‰€æœ‰æŽ§åˆ¶æª¯
+使用者,就好åƒç•¶å‰æ—¥èªŒç´šåˆ¥æ˜¯æœ€å¤§çš„一樣。如果åªç™¼å‡ºæ¨™é¡Œé ­ï¼Œå‰‡å¹¾ä¹Žå¯ä»¥è‚¯å®šå…§æ ¸æ—¥èªŒ
+ç´šåˆ¥å¤ªä½Žã€‚å¦‚æžœä½ éœ€è¦æŽ§åˆ¶æª¯ä¸Šçš„è¼¸å‡ºï¼Œé‚£éº¼ä½ å°‡éœ€è¦è‡¨æ™‚æé«˜æŽ§åˆ¶æª¯æ—¥èªŒç´šåˆ¥ï¼Œé€šéŽä½¿ç”¨
+éµç›¤çµ„åˆéµ :kbd:`alt-sysrq-8` 或者::
+
+ echo 8 > /proc/sysrq-trigger
+
+在觸發了你感興趣的 SysRq éµå‘½ä»¤å¾Œï¼Œè¨˜å¾—æ¢å¾©æ—¥èªŒç´šåˆ¥åˆ°æ­£å¸¸æƒ…æ³ã€‚
+
+我有很多å•題時,å¯ä»¥è«‹æ•™èª°ï¼Ÿ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+請教在內核郵件列表上的人,郵箱:
+ linux-kernel@vger.kernel.org
+
+致è¬
+~~~~
+
+- Mydraal <vulpyne@vulpyne.net> 撰寫了該文件
+- Adam Sulmicki <adam@cfar.umd.edu> 進行了更新
+- Jeremy M. Dolan <jmd@turbogeek.org> 在 2001/01/28 10:15:59 進行了更新
+- Crutcher Dunnavant <crutcher+kernel@datastacks.com> 添加éµè¨»å†Šéƒ¨åˆ†
+
diff --git a/Documentation/translations/zh_TW/admin-guide/tainted-kernels.rst b/Documentation/translations/zh_TW/admin-guide/tainted-kernels.rst
index ebe3812ead82..47629f6b05de 100644
--- a/Documentation/translations/zh_TW/admin-guide/tainted-kernels.rst
+++ b/Documentation/translations/zh_TW/admin-guide/tainted-kernels.rst
@@ -9,27 +9,27 @@
峿ƒ³æˆ Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <src.res.211@gmail.com>
-å—æ±™æŸ“的內核
+å—æ±¡æŸ“的內核
-------------
-當發生一些在ç¨å¾Œèª¿æŸ¥å•題時å¯èƒ½ç›¸é—œçš„äº‹ä»¶æ™‚ï¼Œå…§æ ¸æœƒå°‡è‡ªå·±æ¨™è¨˜çˆ²ã€Œå—æ±™æŸ“
-(tainted)ã€çš„。ä¸ç”¨å¤ªéŽæ“”心,大多數情æ³ä¸‹é‹è¡Œå—汙染的內核沒有å•題;這些信æ¯
-主è¦åœ¨æœ‰äººæƒ³èª¿æŸ¥æŸå€‹å•é¡Œæ™‚æ‰æœ‰æ„義的,因爲å•題的真正原因å¯èƒ½æ˜¯å°Žè‡´å…§æ ¸å—汙染
-çš„äº‹ä»¶ã€‚é€™å°±æ˜¯çˆ²ä»€éº¼ä¾†è‡ªå—æ±™æŸ“內核的缺陷報告常常被開發人員忽略,因此請嘗試用
-æœªå—æ±™æŸ“的內核é‡ç¾å•題。
+當發生一些在ç¨å¾Œèª¿æŸ¥å•題時å¯èƒ½ç›¸é—œçš„äº‹ä»¶æ™‚ï¼Œå…§æ ¸æœƒå°‡è‡ªå·±æ¨™è¨˜çˆ²â€œå—æ±¡æŸ“
+(tainted)â€çš„。ä¸ç”¨å¤ªéŽæ“”心,大多數情æ³ä¸‹é‹è¡Œå—污染的內核沒有å•題;這些信æ¯
+主è¦åœ¨æœ‰äººæƒ³èª¿æŸ¥æŸå€‹å•題時纔有æ„義的,因爲å•題的真正原因å¯èƒ½æ˜¯å°Žè‡´å…§æ ¸å—污染
+çš„äº‹ä»¶ã€‚é€™å°±æ˜¯çˆ²ä»€éº¼ä¾†è‡ªå—æ±¡æŸ“內核的缺陷報告常常被開發人員忽略,因此請嘗試用
+æœªå—æ±¡æŸ“的內核é‡ç¾å•題。
-請注æ„,å³ä½¿åœ¨æ‚¨æ¶ˆé™¤å°Žè‡´æ±™æŸ“的原因(亦å³å¸è¼‰å°ˆæœ‰å…§æ ¸æ¨¡å¡Šï¼‰ä¹‹å¾Œï¼Œå…§æ ¸ä»å°‡ä¿æŒ
-汙染狀態,以表示內核ä»ç„¶ä¸å¯ä¿¡ã€‚這也是爲什麼內核在注æ„到內部å•題(「kernel
-bugã€ï¼‰ã€å¯æ¢å¾©éŒ¯èª¤ï¼ˆã€Œkernel oopsã€ï¼‰æˆ–ä¸å¯æ¢å¾©éŒ¯èª¤ï¼ˆã€Œkernel panicã€ï¼‰æ™‚會列å°
-å—æ±™æŸ“狀態,並將有關此的調試信æ¯å¯«å…¥æ—¥èªŒ ``dmesg`` 輸出。也å¯ä»¥é€šéŽ
-``/proc/`` 中的文件在é‹è¡Œæ™‚æª¢æŸ¥å—æ±™æŸ“的狀態。
+請注æ„,å³ä½¿åœ¨æ‚¨æ¶ˆé™¤å°Žè‡´æ±¡æŸ“的原因(亦å³å¸è¼‰å°ˆæœ‰å…§æ ¸æ¨¡å¡Šï¼‰ä¹‹å¾Œï¼Œå…§æ ¸ä»å°‡ä¿æŒ
+污染狀態,以表示內核ä»ç„¶ä¸å¯ä¿¡ã€‚這也是爲什麼內核在注æ„到內部å•題(“kernel
+bugâ€ï¼‰ã€å¯æ¢å¾©éŒ¯èª¤ï¼ˆâ€œkernel oopsâ€ï¼‰æˆ–ä¸å¯æ¢å¾©éŒ¯èª¤ï¼ˆâ€œkernel panicâ€ï¼‰æ™‚會打å°
+å—æ±¡æŸ“狀態,並將有關此的調試信æ¯å¯«å…¥æ—¥èªŒ ``dmesg`` 輸出。也å¯ä»¥é€šéŽ
+``/proc/`` 中的文件在é‹è¡Œæ™‚æª¢æŸ¥å—æ±¡æŸ“的狀態。
-BUGã€Oops或Panics消æ¯ä¸­çš„æ±™æŸ“標誌
+BUGã€Oops或Panics消æ¯ä¸­çš„æ±¡æŸ“標誌
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-在頂部以「CPU:ã€é–‹é ­çš„一行中å¯ä»¥æ‰¾åˆ°å—汙染的狀態;內核是å¦å—到汙染和原因會顯示
-在進程ID(「PID:ã€ï¼‰å’Œè§¸ç™¼äº‹ä»¶å‘½ä»¤çš„縮寫å稱(「Comm:ã€ï¼‰ä¹‹å¾Œ::
+在頂部以“CPU:â€é–‹é ­çš„一行中å¯ä»¥æ‰¾åˆ°å—污染的狀態;內核是å¦å—到污染和原因會顯示
+在進程ID(“PID:â€ï¼‰å’Œè§¸ç™¼äº‹ä»¶å‘½ä»¤çš„縮寫å稱(“Comm:â€ï¼‰ä¹‹å¾Œ::
BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
Oops: 0002 [#1] SMP PTI
@@ -38,27 +38,27 @@ BUGã€Oops或Panics消æ¯ä¸­çš„æ±™æŸ“標誌
RIP: 0010:my_oops_init+0x13/0x1000 [kpanic]
[...]
-如果內核在事件發生時沒有被汙染,您將在那裡看到「Not-tainted:ã€ï¼›å¦‚果被汙染,那
-麼它將是「Tainted:ã€ä»¥åŠå­—æ¯æˆ–空格。在上é¢çš„例å­ä¸­ï¼Œå®ƒçœ‹èµ·ä¾†æ˜¯é€™æ¨£çš„::
+如果內核在事件發生時沒有被污染,您將在那è£çœ‹åˆ°â€œNot-tainted:â€ï¼›å¦‚果被污染,那
+麼它將是“Tainted:â€ä»¥åŠå­—æ¯æˆ–空格。在上é¢çš„例å­ä¸­ï¼Œå®ƒçœ‹èµ·ä¾†æ˜¯é€™æ¨£çš„::
Tainted: P W O
下表解釋了這些字符的å«ç¾©ã€‚在本例中,由於加載了專有模塊( ``P`` ),出ç¾äº†
警告( ``W`` ),並且加載了外部構建的模塊( ``O`` ),所以內核早些時候å—到
-了汙染。è¦è§£ç¢¼å…¶ä»–字符,請使用下表。
+了污染。è¦è§£ç¢¼å…¶ä»–字符,請使用下表。
-解碼é‹è¡Œæ™‚的汙染狀態
+解碼é‹è¡Œæ™‚的污染狀態
~~~~~~~~~~~~~~~~~~~~~
-在é‹è¡Œæ™‚,您å¯ä»¥é€šéŽè®€å– ``cat /proc/sys/kernel/tainted`` ä¾†æŸ¥è©¢å—æ±™æŸ“狀態。
-如果返回 ``0`` ,則內核沒有å—到汙染;任何其他數字都表示å—到汙染的原因。解碼
+在é‹è¡Œæ™‚,您å¯ä»¥é€šéŽè®€å– ``cat /proc/sys/kernel/tainted`` ä¾†æŸ¥è©¢å—æ±¡æŸ“狀態。
+如果返回 ``0`` ,則內核沒有å—到污染;任何其他數字都表示å—到污染的原因。解碼
這個數字的最簡單方法是使用腳本 ``tools/debugging/kernel-chktaint`` ,您的
發行版å¯èƒ½æœƒå°‡å…¶ä½œçˆ²å爲 ``linux-tools`` 或 ``kernel-tools`` 的包的一部分æ
供;如果沒有,您å¯ä»¥å¾ž
`git.kernel.org <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/tools/debugging/kernel-chktaint>`_
網站下載此腳本並用 ``sh kernel-chktaint`` 執行,它會在上é¢å¼•用的日誌中有類似
-語å¥çš„æ©Ÿå™¨ä¸Šåˆ—å°é€™æ¨£çš„內容::
+語å¥çš„æ©Ÿå™¨ä¸Šæ‰“å°é€™æ¨£çš„內容::
Kernel is Tainted for following reasons:
* Proprietary module was loaded (#0)
@@ -69,19 +69,19 @@ BUGã€Oops或Panics消æ¯ä¸­çš„æ±™æŸ“標誌
a more details explanation of the various taint flags.
Raw taint value as int/string: 4609/'P W O '
-你也å¯ä»¥è©¦è‘—è‡ªå·±è§£ç¢¼é€™å€‹æ•¸å­—ã€‚å¦‚æžœå…§æ ¸è¢«æ±™æŸ“çš„åŽŸå› åªæœ‰ä¸€å€‹ï¼Œé‚£éº¼é€™å¾ˆç°¡å–®ï¼Œ
+你也å¯ä»¥è©¦ç€è‡ªå·±è§£ç¢¼é€™å€‹æ•¸å­—ã€‚å¦‚æžœå…§æ ¸è¢«æ±¡æŸ“çš„åŽŸå› åªæœ‰ä¸€å€‹ï¼Œé‚£éº¼é€™å¾ˆç°¡å–®ï¼Œ
在本例中您å¯ä»¥é€šéŽä¸‹è¡¨æ‰¾åˆ°æ•¸å­—。如果你需è¦è§£ç¢¼æœ‰å¤šå€‹åŽŸå› çš„æ•¸å­—ï¼Œå› çˆ²å®ƒæ˜¯ä¸€
-個ä½åŸŸï¼ˆbitfield),其中æ¯å€‹ä½è¡¨ç¤ºä¸€å€‹ç‰¹å®šé¡žåž‹çš„æ±™æŸ“的存在或ä¸å­˜åœ¨ï¼Œæœ€å¥½è®“
+個ä½åŸŸï¼ˆbitfield),其中æ¯å€‹ä½è¡¨ç¤ºä¸€å€‹ç‰¹å®šé¡žåž‹çš„æ±¡æŸ“的存在或ä¸å­˜åœ¨ï¼Œæœ€å¥½è®“
å‰é¢æåˆ°çš„腳本來處ç†ã€‚但是如果您需è¦å¿«é€Ÿçœ‹ä¸€ä¸‹ï¼Œå¯ä»¥ä½¿ç”¨é€™å€‹shell命令來檢查
設置了哪些ä½::
$ for i in $(seq 18); do echo $(($i-1)) $(($(cat /proc/sys/kernel/tainted)>>($i-1)&1));done
-汙染狀態代碼表
+污染狀態代碼表
~~~~~~~~~~~~~~~
=== ===== ====== ========================================================
- ä½ æ—¥èªŒ 數字 內核被汙染的原因
+ ä½ æ—¥èªŒ 數字 內核被污染的原因
=== ===== ====== ========================================================
0 G/P 1 已加載專用模塊
1 _/F 2 模塊被強制加載
@@ -89,23 +89,23 @@ BUGã€Oops或Panics消æ¯ä¸­çš„æ±™æŸ“標誌
3 _/R 8 模塊被強制å¸è¼‰
4 _/M 16 處ç†å™¨å ±å‘Šäº†æ©Ÿå™¨æª¢æ¸¬ç•°å¸¸ï¼ˆMCE)
5 _/B 32 å¼•ç”¨äº†éŒ¯èª¤çš„é æˆ–æŸäº›æ„å¤–çš„é æ¨™èªŒ
- 6 _/U 64 用戶空間應用程å¼è«‹æ±‚的汙染
+ 6 _/U 64 用戶空間應用程åºè«‹æ±‚的污染
7 _/D 128 å…§æ ¸æœ€è¿‘æ­»æ©Ÿäº†ï¼Œå³æ›¾å‡ºç¾OOPS或BUG
8 _/A 256 ACPI表被用戶覆蓋
9 _/W 512 內核發出警告
10 _/C 1024 已加載staging驅動程åº
- 11 _/I 2048 已應用平å°å›ºä»¶ç¼ºé™·çš„解決方案
- 12 _/O 4096 已加載外部構建(「樹外ã€ï¼‰æ¨¡å¡Š
+ 11 _/I 2048 已應用平臺固件缺陷的解決方案
+ 12 _/O 4096 已加載外部構建(“樹外â€ï¼‰æ¨¡å¡Š
13 _/E 8192 已加載未簽å的模塊
14 _/L 16384 發生軟鎖定
15 _/K 32768 內核已實時打補ä¸
- 16 _/X 65536 備用汙染,爲發行版定義並使用
+ 16 _/X 65536 備用污染,爲發行版定義並使用
17 _/T 131072 å…§æ ¸æ˜¯ç”¨çµæ§‹éš¨æ©ŸåŒ–æ’件構建的
=== ===== ====== ========================================================
-註:字符 ``_`` 表示空白,以便於閱讀表。
+注:字符 ``_`` 表示空白,以便於閱讀表。
-汙染的更詳細解釋
+污染的更詳細解釋
~~~~~~~~~~~~~~~~~
0) ``G`` 加載的所有模塊都有GPL或兼容許å¯è­‰ï¼Œ ``P`` 加載了任何專有模塊。
@@ -115,14 +115,14 @@ BUGã€Oops或Panics消æ¯ä¸­çš„æ±™æŸ“標誌
1) ``F`` 任何模塊被 ``insmod -f`` 強制加載, ``' '`` 所有模塊正常加載。
- 2) ``S`` å…§æ ¸é‹è¡Œåœ¨ä¸åˆè¦ç¯„的處ç†å™¨æˆ–系統上:硬體已é‹è¡Œåœ¨ä¸å—支æŒçš„é…置中,
- 因此無法ä¿è­‰æ­£ç¢ºåŸ·è¡Œã€‚內核將被汙染,例如:
+ 2) ``S`` å…§æ ¸é‹è¡Œåœ¨ä¸åˆè¦ç¯„的處ç†å™¨æˆ–系統上:硬件已é‹è¡Œåœ¨ä¸å—支æŒçš„é…置中,
+ 因此無法ä¿è­‰æ­£ç¢ºåŸ·è¡Œã€‚內核將被污染,例如:
- 在x86上:PAE是通éŽintel CPU(如Pentium M)上的forcepae強制執行的,這些
CPUä¸å ±å‘ŠPAE,但å¯èƒ½æœ‰åŠŸèƒ½å¯¦ç¾ï¼ŒSMP內核在éžå®˜æ–¹æ”¯æŒçš„SMP Athlon CPU上
é‹è¡Œï¼ŒMSR被暴露到用戶空間中。
- 在arm上:在æŸäº›CPU(如Keystone 2)上é‹è¡Œçš„內核,沒有啓用æŸäº›å…§æ ¸ç‰¹æ€§ã€‚
- - 在arm64上:CPU之間存在ä¸åŒ¹é…的硬體特性,引導加載程åºä»¥ä¸åŒçš„æ¨¡å¼å¼•å°ŽCPU。
+ - 在arm64上:CPU之間存在ä¸åŒ¹é…的硬件特性,引導加載程åºä»¥ä¸åŒçš„æ¨¡å¼å¼•å°ŽCPU。
- æŸäº›é©…å‹•ç¨‹åºæ­£åœ¨è¢«ç”¨åœ¨ä¸å—支æŒçš„é«”ç³»çµæ§‹ä¸Šï¼ˆä¾‹å¦‚x86_64以外的其他系統
上的scsi/snic,éžx86/x86_64/itanium上的scsi/ips,已經æå£žäº†arm64上
irqchip/irq-gic的固件設置…)。
@@ -131,22 +131,22 @@ BUGã€Oops或Panics消æ¯ä¸­çš„æ±™æŸ“標誌
4) ``M`` 任何處ç†å™¨å ±å‘Šäº†æ©Ÿå™¨æª¢æ¸¬ç•°å¸¸ï¼Œ ``' '`` 未發生機器檢測異常。
- 5) ``B`` é é¢é‡‹æ”¾å‡½æ•¸ç™¼ç¾éŒ¯èª¤çš„é é¢å¼•用或æŸäº›æ„外的é é¢æ¨™èªŒã€‚這表示硬體å•題
- æˆ–å…§æ ¸éŒ¯èª¤ï¼›æ—¥èªŒä¸­æ‡‰è©²æœ‰å…¶ä»–ä¿¡æ¯æŒ‡ç¤ºç™¼ç”Ÿæ­¤æ±™æŸ“的原因。
+ 5) ``B`` é é¢é‡‹æ”¾å‡½æ•¸ç™¼ç¾éŒ¯èª¤çš„é é¢å¼•用或æŸäº›æ„外的é é¢æ¨™èªŒã€‚這表示硬件å•題
+ æˆ–å…§æ ¸éŒ¯èª¤ï¼›æ—¥èªŒä¸­æ‡‰è©²æœ‰å…¶ä»–ä¿¡æ¯æŒ‡ç¤ºç™¼ç”Ÿæ­¤æ±¡æŸ“的原因。
- 6) ``U`` 用戶或用戶應用程å¼ç‰¹æ„è«‹æ±‚è¨­ç½®å—æ±™æŸ“標誌,å¦å‰‡æ‡‰çˆ² ``' '`` 。
+ 6) ``U`` 用戶或用戶應用程åºç‰¹æ„è«‹æ±‚è¨­ç½®å—æ±¡æŸ“標誌,å¦å‰‡æ‡‰çˆ² ``' '`` 。
7) ``D`` 內核最近死機了,å³å‡ºç¾äº†OOPS或BUG。
8) ``A`` ACPI表被é‡å¯«ã€‚
- 9) ``W`` 內核之å‰å·²ç™¼å‡ºéŽè­¦å‘Šï¼ˆå„˜ç®¡æœ‰äº›è­¦å‘Šå¯èƒ½æœƒè¨­ç½®æ›´å…·é«”的汙染標誌)。
+ 9) ``W`` 內核之å‰å·²ç™¼å‡ºéŽè­¦å‘Šï¼ˆå„˜ç®¡æœ‰äº›è­¦å‘Šå¯èƒ½æœƒè¨­ç½®æ›´å…·é«”的污染標誌)。
10) ``C`` 已加載staging驅動程åºã€‚
- 11) ``I`` 內核正在處ç†å¹³å°å›ºä»¶ï¼ˆBIOS或類似軟體)中的嚴é‡éŒ¯èª¤ã€‚
+ 11) ``I`` 內核正在處ç†å¹³è‡ºå›ºä»¶ï¼ˆBIOS或類似軟件)中的嚴é‡éŒ¯èª¤ã€‚
- 12) ``O`` 已加載外部構建(「樹外ã€ï¼‰æ¨¡å¡Šã€‚
+ 12) ``O`` 已加載外部構建(“樹外â€ï¼‰æ¨¡å¡Šã€‚
13) ``E`` åœ¨æ”¯æŒæ¨¡å¡Šç°½å的內核中加載了未簽å的模塊。
@@ -154,8 +154,8 @@ BUGã€Oops或Panics消æ¯ä¸­çš„æ±™æŸ“標誌
15) ``K`` 內核已經實時打了補ä¸ã€‚
- 16) ``X`` 備用汙染,由Linux發行版定義和使用。
+ 16) ``X`` 備用污染,由Linux發行版定義和使用。
17) ``T`` 內核構建時使用了randstructæ’件,它å¯ä»¥æœ‰æ„生æˆéžå¸¸ä¸å°‹å¸¸çš„å…§æ ¸çµæ§‹
- 布局(甚至是性能病態的布局),這在調試時éžå¸¸æœ‰ç”¨ã€‚於構建時設置。
+ 佈局(甚至是性能病態的佈局),這在調試時éžå¸¸æœ‰ç”¨ã€‚於構建時設置。
diff --git a/Documentation/translations/zh_TW/admin-guide/unicode.rst b/Documentation/translations/zh_TW/admin-guide/unicode.rst
index 7908b369b85b..a2b48b5d0a64 100644
--- a/Documentation/translations/zh_TW/admin-guide/unicode.rst
+++ b/Documentation/translations/zh_TW/admin-guide/unicode.rst
@@ -37,15 +37,15 @@ IBMPC_MAP IBM code page 437 ESC ( U
USER_MAP User defined ESC ( K
=============== =============================== ================
-特別是 ESC ( U ä¸å†æ˜¯ã€Œç›´é€šå­—é«”ã€ï¼Œå› çˆ²å­—é«”å¯èƒ½èˆ‡IBM字符集完全ä¸åŒã€‚
+特別是 ESC ( U ä¸å†æ˜¯â€œç›´é€šå­—é«”â€ï¼Œå› çˆ²å­—é«”å¯èƒ½èˆ‡IBM字符集完全ä¸åŒã€‚
例如,å³ä½¿åŠ è¼‰äº†ä¸€å€‹Latin-1字體,也å…許使用塊圖形(block graphics)。
請注æ„,儘管這些代碼與ISO 2022類似,但這些代碼åŠå…¶ç”¨é€”都與ISO 2022ä¸åŒ¹é…ï¼›
Linux有兩個八ä½ä»£ç¢¼ï¼ˆG0å’ŒG1),而ISO 2022有四個七ä½ä»£ç¢¼ï¼ˆG0-G3)。
-根據Unicode標準/ISO 10646,U+F000到U+F8FF被ä¿ç•™ç”¨æ–¼ä½œæ¥­ç³»çµ±ç¯„åœå…§çš„分é…
-(Unicode標準將其稱爲「團體å€åŸŸï¼ˆCorporate Zone)ã€ï¼Œå› çˆ²é€™å°æ–¼Linuxæ˜¯ä¸æº–確
-的,所以我們稱之爲「Linuxå€åŸŸã€ï¼‰ã€‚鏿“‡U+F000作爲起點,因爲它å…許直接映射
+根據Unicode標準/ISO 10646,U+F000到U+F8FF被ä¿ç•™ç”¨æ–¼æ“作系統範åœå…§çš„分é…
+(Unicode標準將其稱爲“團體å€åŸŸï¼ˆCorporate Zone)â€ï¼Œå› çˆ²é€™å°æ–¼Linuxæ˜¯ä¸æº–確
+的,所以我們稱之爲“Linuxå€åŸŸâ€ï¼‰ã€‚鏿“‡U+F000作爲起點,因爲它å…許直接映射
å€åŸŸä»¥2çš„å¤§å€æ•¸é–‹å§‹ï¼ˆä»¥é˜²éœ€è¦1024或2048個字符的字體)。這就留下U+E000到
U+EFFF作爲最終用戶å€ã€‚
@@ -87,7 +87,7 @@ U+F813 KEYBOARD SYMBOL SOLID APPLE
克林貢(Klingon)語支æŒ
------------------------
-1996年,Linux是世界上第一個添加å°äººå·¥èªžè¨€å…‹æž—貢支æŒçš„作業系統,克林貢是由
+1996年,Linux是世界上第一個添加å°äººå·¥èªžè¨€å…‹æž—貢支æŒçš„æ“ä½œç³»çµ±ï¼Œå…‹æž—è²¢æ˜¯ç”±
Marc Okrand爲《星際迷航》電視連續劇創造的。這種編碼後來被徵募Unicode註冊表
(ConScript Unicode Registry,CSUR)採用,並建議(但最終被拒絕)ç´å…¥Unicode
å¹³é¢ä¸€ã€‚ä¸éŽï¼Œå®ƒä»ç„¶æ˜¯Linuxå€åŸŸä¸­çš„Linux/CSURç§æœ‰åˆ†é…。
diff --git a/Documentation/translations/zh_TW/arch/arm/Booting b/Documentation/translations/zh_TW/arch/arm/Booting
new file mode 100644
index 000000000000..a5375f262de2
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/arm/Booting
@@ -0,0 +1,176 @@
+Chinese translated version of Documentation/arch/arm/booting.rst
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly. However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help. Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Russell King <linux@arm.linux.org.uk>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arch/arm/booting.rst 的中文翻譯
+
+如果想評論或更新本文的內容,請直接è¯ç¹«åŽŸæ–‡æª”çš„ç¶­è­·è€…ã€‚å¦‚æžœä½ ä½¿ç”¨è‹±æ–‡
+äº¤æµæœ‰å›°é›£çš„話,也å¯ä»¥å‘中文版維護者求助。如果本翻譯更新ä¸åŠæ™‚或者翻
+譯存在å•題,請è¯ç¹«ä¸­æ–‡ç‰ˆç¶­è­·è€…。
+
+英文版維護者: Russell King <linux@arm.linux.org.uk>
+中文版維護者: 傅煒 Fu Wei <tekkamanninja@gmail.com>
+中文版翻譯者: 傅煒 Fu Wei <tekkamanninja@gmail.com>
+中文版校譯者: 傅煒 Fu Wei <tekkamanninja@gmail.com>
+
+以下爲正文
+---------------------------------------------------------------------
+
+ å•“å‹• ARM Linux
+ ==============
+
+作者:Russell King
+日期:2002年5月18日
+
+以下文檔é©ç”¨æ–¼ 2.4.18-rmk6 åŠä»¥ä¸Šç‰ˆæœ¬ã€‚
+
+爲了啓動 ARM Linux,你需è¦ä¸€å€‹å¼•å°Žè£è¼‰ç¨‹åºï¼ˆboot loader),
+它是一個在主內核啓動å‰é‹è¡Œçš„一個å°ç¨‹åºã€‚引導è£è¼‰ç¨‹åºéœ€è¦åˆå§‹åŒ–å„種
+設備,並最終調用 Linux 內核,將信æ¯å‚³éžçµ¦å…§æ ¸ã€‚
+
+從本質上講,引導è£è¼‰ç¨‹åºæ‡‰æä¾›ï¼ˆè‡³å°‘)以下功能:
+
+1ã€è¨­ç½®å’Œåˆå§‹åŒ– RAM。
+2ã€åˆå§‹åŒ–一個串å£ã€‚
+3ã€æª¢æ¸¬æ©Ÿå™¨çš„類型(machine type)。
+4ã€è¨­ç½®å…§æ ¸æ¨™ç±¤åˆ—表(tagged list)。
+5ã€èª¿ç”¨å…§æ ¸æ˜ åƒã€‚
+
+
+1ã€è¨­ç½®å’Œåˆå§‹åŒ– RAM
+-------------------
+
+ç¾æœ‰çš„引導加載程åº: 強制
+新開發的引導加載程åº: 強制
+
+引導è£è¼‰ç¨‹åºæ‡‰è©²æ‰¾åˆ°ä¸¦åˆå§‹åŒ–ç³»çµ±ä¸­æ‰€æœ‰å…§æ ¸ç”¨æ–¼ä¿æŒç³»çµ±è®Šé‡æ•¸æ“šçš„ RAM。
+這個æ“作的執行是設備ä¾è³´çš„。(它å¯èƒ½ä½¿ç”¨å…§éƒ¨ç®—法來自動定ä½å’Œè¨ˆç®—所有
+RAM,或å¯èƒ½ä½¿ç”¨å°é€™å€‹è¨­å‚™å·²çŸ¥çš„ RAM ä¿¡æ¯ï¼Œé‚„å¯èƒ½ä½¿ç”¨ä»»ä½•引導è£è¼‰ç¨‹åº
+è¨­è¨ˆè€…æƒ³åˆ°çš„åŒ¹é…æ–¹æ³•。)
+
+
+2ã€åˆå§‹åŒ–一個串å£
+-----------------------------
+
+ç¾æœ‰çš„引導加載程åº: å¯é¸ã€å»ºè­°
+新開發的引導加載程åº: å¯é¸ã€å»ºè­°
+
+å¼•å°ŽåŠ è¼‰ç¨‹åºæ‡‰è©²åˆå§‹åŒ–並使能一個目標æ¿ä¸Šçš„串å£ã€‚這å…許內核串å£é©…å‹•
+自動檢測哪個串å£ç”¨æ–¼å…§æ ¸æŽ§åˆ¶æª¯ã€‚(一般用於調試或與目標æ¿é€šä¿¡ã€‚)
+
+作爲替代方案,引導加載程åºä¹Ÿå¯ä»¥é€šéŽæ¨™ç±¤åˆ—表傳éžç›¸é—œçš„'console='
+é¸é …給內核以指定æŸå€‹ä¸²å£ï¼Œè€Œä¸²å£æ•¸æ“šæ ¼å¼çš„é¸é …在以下文檔中æè¿°ï¼š
+
+ Documentation/admin-guide/kernel-parameters.rst。
+
+
+3ã€æª¢æ¸¬æ©Ÿå™¨é¡žåž‹
+--------------------------
+
+ç¾æœ‰çš„引導加載程åº: å¯é¸
+新開發的引導加載程åº: 強制
+
+å¼•å°ŽåŠ è¼‰ç¨‹åºæ‡‰è©²é€šéŽæŸäº›æ–¹å¼æª¢æ¸¬è‡ªèº«æ‰€è™•的機器類型。這是一個硬件
+ä»£ç¢¼æˆ–é€šéŽæŸ¥çœ‹æ‰€é€£æŽ¥çš„硬件用æŸäº›ç®—法得到,這些超出了本文檔的範åœã€‚
+å¼•å°ŽåŠ è¼‰ç¨‹åºæœ€çµ‚必須能æä¾›ä¸€å€‹ MACH_TYPE_xxx 值給內核。
+(詳見 linux/arch/arm/tools/mach-types )。
+
+4ã€è¨­ç½®å•“動數據
+------------------
+
+ç¾æœ‰çš„引導加載程åº: å¯é¸ã€å¼·çƒˆå»ºè­°
+新開發的引導加載程åº: 強制
+
+引導加載程åºå¿…é ˆæä¾›æ¨™ç±¤åˆ—表或者 dtb 映åƒä»¥å‚³éžé…置數據給內核。啓動
+數據的物ç†åœ°å€é€šéŽå¯„存器 r2 傳éžçµ¦å…§æ ¸ã€‚
+
+4aã€è¨­ç½®å…§æ ¸æ¨™ç±¤åˆ—表
+--------------------------------
+
+bootloader 必須創建和åˆå§‹åŒ–內核標籤列表。一個有效的標籤列表以
+ATAG_CORE 標籤開始,並以 ATAG_NONE æ¨™ç±¤çµæŸã€‚ATAG_CORE 標籤å¯ä»¥æ˜¯
+空的,也å¯ä»¥æ˜¯éžç©ºã€‚一個空 ATAG_CORE 標籤其 size 域設置爲
+‘2’(0x00000002)。ATAG_NONE 標籤的 size 域必須設置爲零。
+
+在列表中å¯ä»¥ä¿å­˜ä»»æ„數é‡çš„æ¨™ç±¤ã€‚å°æ–¼ä¸€å€‹é‡è¤‡çš„æ¨™ç±¤æ˜¯è¿½åŠ åˆ°ä¹‹å‰æ¨™ç±¤
+所攜帶的信æ¯ä¹‹å¾Œï¼Œé‚„是會覆蓋原來的信æ¯ï¼Œæ˜¯æœªå®šç¾©çš„。æŸäº›æ¨™ç±¤çš„行爲
+是å‰è€…,其他是後者。
+
+bootloader 必須傳éžä¸€å€‹ç³»çµ±å…§å­˜çš„ä½ç½®å’Œæœ€å°å€¼ï¼Œä»¥åŠæ ¹æ–‡ä»¶ç³»çµ±ä½ç½®ã€‚
+因此,最å°çš„æ¨™ç±¤åˆ—表如下所示:
+
+ +-----------+
+åŸºåœ°å€ -> | ATAG_CORE | |
+ +-----------+ |
+ | ATAG_MEM | | 地å€å¢žé•·æ–¹å‘
+ +-----------+ |
+ | ATAG_NONE | |
+ +-----------+ v
+
+標籤列表應該ä¿å­˜åœ¨ç³»çµ±çš„ RAM 中。
+
+標籤列表必須置於內核自解壓和 initrd'bootp' 程åºéƒ½ä¸æœƒè¦†è“‹çš„å…§å­˜å€ã€‚
+建議放在 RAM 的頭 16KiB 中。
+
+4bã€è¨­ç½®è¨­å‚™æ¨¹
+-------------------------
+
+bootloader 必須以 64bit 地å€å°é½Šçš„å½¢å¼åŠ è¼‰ä¸€å€‹è¨­å‚™æ¨¹æ˜ åƒ(dtb)到系統
+RAM 中,並用啓動數據åˆå§‹åŒ–它。dtb æ ¼å¼åœ¨æ–‡æª”
+https://www.devicetree.org/specifications/ 中。內核將會在
+dtb 物ç†åœ°å€è™•查找 dtb 魔數值(0xd00dfeed),以確定 dtb 是å¦å·²ç¶“代替
+標籤列表被傳éžé€²ä¾†ã€‚
+
+bootloader 必須傳éžä¸€å€‹ç³»çµ±å…§å­˜çš„ä½ç½®å’Œæœ€å°å€¼ï¼Œä»¥åŠæ ¹æ–‡ä»¶ç³»çµ±ä½ç½®ã€‚
+dtb å¿…é ˆç½®æ–¼å…§æ ¸è‡ªè§£å£“ä¸æœƒè¦†è“‹çš„å…§å­˜å€ã€‚建議將其放置於 RAM 的頭 16KiB
+中。但是ä¸å¯å°‡å…¶æ”¾ç½®æ–¼â€œ0â€ç‰©ç†åœ°å€è™•,因爲內核èªçˆ²ï¼šr2 中爲 0,æ„味ç€
+沒有標籤列表和 dtb 傳éžéŽä¾†ã€‚
+
+5ã€èª¿ç”¨å…§æ ¸æ˜ åƒ
+---------------------------
+
+ç¾æœ‰çš„引導加載程åº: 強制
+新開發的引導加載程åº: 強制
+
+èª¿ç”¨å…§æ ¸æ˜ åƒ zImage æœ‰å…©å€‹é¸æ“‡ã€‚如果 zImge ä¿å­˜åœ¨ flash 中,且是爲了
+在 flash 中直接é‹è¡Œè€Œè¢«æ­£ç¢ºéˆæŽ¥çš„。這樣引導加載程åºå°±å¯ä»¥åœ¨ flash 中
+直接調用 zImage。
+
+zImage 也å¯ä»¥è¢«æ”¾åœ¨ç³»çµ± RAM(任æ„ä½ç½®ï¼‰ä¸­è¢«èª¿ç”¨ã€‚注æ„:內核使用映åƒ
+基地å€çš„å‰ 16KB RAM 空間來ä¿å­˜é è¡¨ã€‚建議將映åƒç½®æ–¼ RAM çš„ 32KB 處。
+
+å°æ–¼ä»¥ä¸Šä»»æ„一種情æ³ï¼Œéƒ½å¿…須符åˆä»¥ä¸‹å•“動狀態:
+
+- åœæ­¢æ‰€æœ‰ DMA è¨­å‚™ï¼Œé€™æ¨£å…§å­˜æ•¸æ“šå°±ä¸æœƒå› çˆ²è™›å‡ç¶²çµ¡åŒ…或ç£ç›¤æ•¸æ“šè€Œè¢«ç ´å£žã€‚
+ 這å¯èƒ½å¯ä»¥ç¯€çœä½ è¨±å¤šçš„調試時間。
+
+- CPU 寄存器é…ç½®
+ r0 = 0,
+ r1 = ï¼ˆåœ¨ä¸Šé¢ 3 中ç²å–的)機器類型碼。
+ r2 = 標籤列表在系統 RAM 中的物ç†åœ°å€ï¼Œæˆ–
+ 設備樹塊(dtb)在系統 RAM 中的物ç†åœ°å€
+
+- CPU 模å¼
+ 所有形å¼çš„ä¸­æ–·å¿…é ˆè¢«ç¦æ­¢ (IRQs å’Œ FIQs)
+ CPU 必須處於 SVC 模å¼ã€‚(å°æ–¼ Angel 調試有特例存在)
+
+- 緩存,MMUs
+ MMU 必須關閉。
+ 指令緩存開啓或關閉都å¯ä»¥ã€‚
+ 數據緩存必須關閉。
+
+- å¼•å°ŽåŠ è¼‰ç¨‹åºæ‡‰è©²é€šéŽç›´æŽ¥è·³è½‰åˆ°å…§æ ¸æ˜ åƒçš„ç¬¬ä¸€æ¢æŒ‡ä»¤ä¾†èª¿ç”¨å…§æ ¸æ˜ åƒã€‚
+
+ å°æ–¼æ”¯æŒ ARM 指令集的 CPUï¼Œè·³å…¥å…§æ ¸å…¥å£æ™‚必須處在 ARM 狀態,å³ä½¿
+ å°æ–¼ Thumb-2 內核也是如此。
+
+ å°æ–¼åƒ…æ”¯æŒ Thumb 指令集的 CPU,比如 Cortex-M 系列的 CPU,跳入
+ å…§æ ¸å…¥å£æ™‚必須處於 Thumb 狀態。
+
diff --git a/Documentation/translations/zh_TW/arch/arm/kernel_user_helpers.txt b/Documentation/translations/zh_TW/arch/arm/kernel_user_helpers.txt
new file mode 100644
index 000000000000..4c0bff97af31
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/arm/kernel_user_helpers.txt
@@ -0,0 +1,285 @@
+Chinese translated version of Documentation/arch/arm/kernel_user_helpers.rst
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly. However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help. Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Nicolas Pitre <nicolas.pitre@linaro.org>
+ Dave Martin <dave.martin@linaro.org>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arch/arm/kernel_user_helpers.rst 的中文翻譯
+
+如果想評論或更新本文的內容,請直接è¯ç¹«åŽŸæ–‡æª”çš„ç¶­è­·è€…ã€‚å¦‚æžœä½ ä½¿ç”¨è‹±æ–‡
+äº¤æµæœ‰å›°é›£çš„話,也å¯ä»¥å‘中文版維護者求助。如果本翻譯更新ä¸åŠæ™‚或者翻
+譯存在å•題,請è¯ç¹«ä¸­æ–‡ç‰ˆç¶­è­·è€…。
+英文版維護者: Nicolas Pitre <nicolas.pitre@linaro.org>
+ Dave Martin <dave.martin@linaro.org>
+中文版維護者: 傅煒 Fu Wei <tekkamanninja@gmail.com>
+中文版翻譯者: 傅煒 Fu Wei <tekkamanninja@gmail.com>
+中文版校譯者: 宋冬生 Dongsheng Song <dongshneg.song@gmail.com>
+ å‚…ç…’ Fu Wei <tekkamanninja@gmail.com>
+
+
+以下爲正文
+---------------------------------------------------------------------
+å…§æ ¸æä¾›çš„用戶空間輔助代碼
+=========================
+
+在內核內存空間的固定地å€è™•,有一個由內核æä¾›ä¸¦å¯å¾žç”¨æˆ¶ç©ºé–“訪å•的代碼
+段。它用於å‘用戶空間æä¾›å› åœ¨è¨±å¤š ARM CPU 中未實ç¾çš„特性和/或指令而需
+å…§æ ¸æä¾›å¹«åŠ©çš„æŸäº›æ“作。這些代碼直接在用戶模å¼ä¸‹åŸ·è¡Œçš„æƒ³æ³•是爲了ç²å¾—
+最佳效率,但那些與內核計數器è¯ç¹«éŽæ–¼ç·Šå¯†çš„部分,則被留給了用戶庫實ç¾ã€‚
+事實上,此代碼甚至å¯èƒ½å› ä¸åŒçš„ CPU è€Œç•°ï¼Œé€™å–æ±ºæ–¼å…¶å¯ç”¨çš„æŒ‡ä»¤é›†æˆ–它
+是å¦çˆ² SMP 系統。æ›å¥è©±èªªï¼Œå…§æ ¸ä¿ç•™åœ¨ä¸ä½œå‡ºè­¦å‘Šçš„æƒ…æ³ä¸‹æ ¹æ“šéœ€è¦æ›´æ”¹
+é€™äº›ä»£ç¢¼çš„æ¬Šåˆ©ã€‚åªæœ‰æœ¬æ–‡æª”æè¿°çš„å…¥å£åŠå…¶çµæžœæ˜¯ä¿è­‰ç©©å®šçš„。
+
+這與完全æˆç†Ÿçš„ VDSO 實ç¾ä¸åŒï¼ˆä½†å…©è€…並ä¸è¡çªï¼‰ï¼Œå„˜ç®¡å¦‚此,VDSO å¯é˜»æ­¢
+æŸäº›é€šéŽå¸¸é‡é«˜æ•ˆè·³è½‰åˆ°é‚£äº›ä»£ç¢¼æ®µçš„彙編技巧。且由於那些代碼段在返回用戶
+代碼å‰åƒ…使用少é‡çš„代碼週期,則一個 VDSO 間接é ç¨‹èª¿ç”¨å°‡æœƒåœ¨é€™äº›ç°¡å–®çš„
+æ“ä½œä¸Šå¢žåŠ ä¸€å€‹å¯æ¸¬é‡çš„開銷。
+
+在å°é‚£äº›æ“有原生支æŒçš„æ–°åž‹è™•ç†å™¨é€²è¡Œä»£ç¢¼å„ªåŒ–時,僅在已爲其他æ“作使用
+äº†é¡žä¼¼çš„æ–°å¢žæŒ‡ä»¤ï¼Œè€Œå°Žè‡´äºŒé€²åˆ¶çµæžœå·²èˆ‡æ—©æœŸ ARM 處ç†å™¨ä¸å…¼å®¹çš„æƒ…æ³ä¸‹ï¼Œ
+ç”¨æˆ¶ç©ºé–“æ‰æ‡‰ç¹žéŽé€™äº›è¼”助代碼,並在內è¯å‡½æ•¸ä¸­å¯¦ç¾é€™äº›æ“作(無論是通éŽ
+編譯器在代碼中直接放置,還是作爲庫函數調用實ç¾çš„一部分)。也就是說,
+å¦‚æžœä½ ç·¨è­¯çš„ä»£ç¢¼ä¸æœƒçˆ²äº†å…¶ä»–目的使用新指令,則ä¸è¦åƒ…爲了é¿å…使用這些
+內核輔助代碼,導致二進制程åºç„¡æ³•在早期處ç†å™¨ä¸Šé‹è¡Œã€‚
+
+新的輔助代碼å¯èƒ½éš¨ç€æ™‚間的推移而增加,所以新內核中的æŸäº›è¼”助代碼在舊
+內核中å¯èƒ½ä¸å­˜åœ¨ã€‚因此,程åºå¿…須在å°ä»»ä½•輔助代碼調用å‡è¨­æ˜¯å®‰å…¨ä¹‹å‰ï¼Œ
+檢測 __kuser_helper_version çš„å€¼ï¼ˆè¦‹ä¸‹æ–‡ï¼‰ã€‚ç†æƒ³æƒ…æ³ä¸‹ï¼Œé€™ç¨®æª¢æ¸¬æ‡‰è©²
+åªåœ¨é€²ç¨‹å•“å‹•æ™‚åŸ·è¡Œä¸€æ¬¡ï¼›å¦‚æžœå…§æ ¸ç‰ˆæœ¬ä¸æ”¯æŒæ‰€éœ€è¼”助代碼,則該進程å¯å„˜æ—©
+中止執行。
+
+kuser_helper_version
+--------------------
+
+ä½ç½®: 0xffff0ffc
+
+åƒè€ƒè²æ˜Ž:
+
+ extern int32_t __kuser_helper_version;
+
+定義:
+
+ 這個å€åŸŸåŒ…å«äº†ç•¶å‰é‹è¡Œå…§æ ¸å¯¦ç¾çš„輔助代碼版本號。用戶空間å¯ä»¥é€šéŽè®€
+ å–æ­¤ç‰ˆæœ¬è™Ÿä»¥ç¢ºå®šç‰¹å®šçš„輔助代碼是å¦å­˜åœ¨ã€‚
+
+使用範例:
+
+#define __kuser_helper_version (*(int32_t *)0xffff0ffc)
+
+void check_kuser_version(void)
+{
+ if (__kuser_helper_version < 2) {
+ fprintf(stderr, "can't do atomic operations, kernel too old\n");
+ abort();
+ }
+}
+
+注æ„:
+
+ 用戶空間å¯ä»¥å‡è¨­é€™å€‹åŸŸçš„值䏿œƒåœ¨ä»»ä½•單個進程的生存期內改變。也就
+ 是說,這個域å¯ä»¥åƒ…在庫的åˆå§‹åŒ–階段或進程啓動階段讀å–一次。
+
+kuser_get_tls
+-------------
+
+ä½ç½®: 0xffff0fe0
+
+åƒè€ƒåŽŸåž‹:
+
+ void * __kuser_get_tls(void);
+
+輸入:
+
+ lr = 返回地å€
+
+輸出:
+
+ r0 = TLS 值
+
+被篡改的寄存器:
+
+ ç„¡
+
+定義:
+
+ ç²å–之å‰é€šéŽ __ARM_NR_set_tls 系統調用設置的 TLS 值。
+
+使用範例:
+
+typedef void * (__kuser_get_tls_t)(void);
+#define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
+
+void foo()
+{
+ void *tls = __kuser_get_tls();
+ printf("TLS = %p\n", tls);
+}
+
+注æ„:
+
+ - 僅在 __kuser_helper_version >= 1 時,此輔助代碼存在
+ (從內核版本 2.6.12 開始)。
+
+kuser_cmpxchg
+-------------
+
+ä½ç½®: 0xffff0fc0
+
+åƒè€ƒåŽŸåž‹:
+
+ int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
+
+輸入:
+
+ r0 = oldval
+ r1 = newval
+ r2 = ptr
+ lr = 返回地å€
+
+輸出:
+
+ r0 = æˆåŠŸä»£ç¢¼ (零或éžé›¶)
+ C flag = 如果 r0 == 0 則置 1,如果 r0 != 0 則清零。
+
+被篡改的寄存器:
+
+ r3, ip, flags
+
+定義:
+
+ 僅在 *ptr 爲 oldval 時原å­ä¿å­˜ newval æ–¼ *ptr 中。
+ 如果 *ptr 被改變,則返回值爲零,å¦å‰‡çˆ²éžé›¶å€¼ã€‚
+ 如果 *ptr 被改變,則 C flag 也會被置 1,以實ç¾èª¿ç”¨ä»£ç¢¼ä¸­çš„彙編
+ 優化。
+
+使用範例:
+
+typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
+#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
+
+int atomic_add(volatile int *ptr, int val)
+{
+ int old, new;
+
+ do {
+ old = *ptr;
+ new = old + val;
+ } while(__kuser_cmpxchg(old, new, ptr));
+
+ return new;
+}
+
+注æ„:
+
+ - 這個例程已根據需è¦åŒ…å«äº†å…§å­˜å±éšœã€‚
+
+ - 僅在 __kuser_helper_version >= 2 時,此輔助代碼存在
+ (從內核版本 2.6.12 開始)。
+
+kuser_memory_barrier
+--------------------
+
+ä½ç½®: 0xffff0fa0
+
+åƒè€ƒåŽŸåž‹:
+
+ void __kuser_memory_barrier(void);
+
+輸入:
+
+ lr = 返回地å€
+
+輸出:
+
+ ç„¡
+
+被篡改的寄存器:
+
+ ç„¡
+
+定義:
+
+ 應用於任何需è¦å…§å­˜å±éšœä»¥é˜²æ­¢æ‰‹å‹•數據修改帶來的一致性å•題,以åŠ
+ __kuser_cmpxchg 中。
+
+使用範例:
+
+typedef void (__kuser_dmb_t)(void);
+#define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
+
+注æ„:
+
+ - 僅在 __kuser_helper_version >= 3 時,此輔助代碼存在
+ (從內核版本 2.6.15 開始)。
+
+kuser_cmpxchg64
+---------------
+
+ä½ç½®: 0xffff0f60
+
+åƒè€ƒåŽŸåž‹:
+
+ int __kuser_cmpxchg64(const int64_t *oldval,
+ const int64_t *newval,
+ volatile int64_t *ptr);
+
+輸入:
+
+ r0 = æŒ‡å‘ oldval
+ r1 = æŒ‡å‘ newval
+ r2 = 指å‘目標值
+ lr = 返回地å€
+
+輸出:
+
+ r0 = æˆåŠŸä»£ç¢¼ (零或éžé›¶)
+ C flag = 如果 r0 == 0 則置 1,如果 r0 != 0 則清零。
+
+被篡改的寄存器:
+
+ r3, lr, flags
+
+定義:
+
+ 僅在 *ptr 等於 *oldval 指å‘çš„ 64 ä½å€¼æ™‚,原å­ä¿å­˜ *newval
+ 指å‘çš„ 64 ä½å€¼æ–¼ *ptr 中。如果 *ptr 被改變,則返回值爲零,
+ å¦å‰‡çˆ²éžé›¶å€¼ã€‚
+
+ 如果 *ptr 被改變,則 C flag 也會被置 1,以實ç¾èª¿ç”¨ä»£ç¢¼ä¸­çš„彙編
+ 優化。
+
+使用範例:
+
+typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
+ const int64_t *newval,
+ volatile int64_t *ptr);
+#define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
+
+int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
+{
+ int64_t old, new;
+
+ do {
+ old = *ptr;
+ new = old + val;
+ } while(__kuser_cmpxchg64(&old, &new, ptr));
+
+ return new;
+}
+
+注æ„:
+
+ - 這個例程已根據需è¦åŒ…å«äº†å…§å­˜å±éšœã€‚
+
+ - 由於這個éŽç¨‹çš„代碼長度(此輔助代碼跨越 2 個常è¦çš„ kuser “槽â€ï¼‰ï¼Œ
+ å› æ­¤ 0xffff0f80 ä¸è¢«ä½œçˆ²æœ‰æ•ˆçš„å…¥å£é»žã€‚
+
+ - 僅在 __kuser_helper_version >= 5 時,此輔助代碼存在
+ (從內核版本 3.1 開始)。
+
diff --git a/Documentation/translations/zh_TW/arch/arm64/amu.rst b/Documentation/translations/zh_TW/arch/arm64/amu.rst
index 21ac0db63889..1b451eae2bee 100644
--- a/Documentation/translations/zh_TW/arch/arm64/amu.rst
+++ b/Documentation/translations/zh_TW/arch/arm64/amu.rst
@@ -28,11 +28,11 @@ AArch64 Linux 中擴展的活動監控單元
AMUv1 架構實ç¾äº†ä¸€å€‹ç”±4個固定的64ä½äº‹ä»¶è¨ˆæ•¸å™¨çµ„æˆçš„計數器組。
- - CPU å‘¨æœŸè¨ˆæ•¸å™¨ï¼šåŒ CPU 的頻率增長
+ - CPU é€±æœŸè¨ˆæ•¸å™¨ï¼šåŒ CPU 的頻率增長
- 常é‡è¨ˆæ•¸å™¨ï¼šåŒå›ºå®šçš„系統時é˜é »çŽ‡å¢žé•·
- 淘汰指令計數器: åŒæ¯æ¬¡æž¶æ§‹æŒ‡ä»¤åŸ·è¡Œå¢žé•·
- - å…§å­˜åœé “周期計數器:計算由在時é˜åŸŸå…§çš„æœ€å¾Œä¸€ç´šç·©å­˜ä¸­æœªå‘½ä¸­è€Œå¼•èµ·
- 的指令調度åœé “周期數
+ - å…§å­˜åœé “週期計數器:計算由在時é˜åŸŸå…§çš„æœ€å¾Œä¸€ç´šç·©å­˜ä¸­æœªå‘½ä¸­è€Œå¼•èµ·
+ 的指令調度åœé “週期數
當處於 WFI 或者 WFE ç‹€æ…‹æ™‚ï¼Œè¨ˆæ•¸å™¨ä¸æœƒå¢žé•·ã€‚
diff --git a/Documentation/translations/zh_TW/arch/arm64/booting.txt b/Documentation/translations/zh_TW/arch/arm64/booting.txt
index 3cc8f593e006..be0de91ecebd 100644
--- a/Documentation/translations/zh_TW/arch/arm64/booting.txt
+++ b/Documentation/translations/zh_TW/arch/arm64/booting.txt
@@ -41,8 +41,8 @@ AArch64 異常模型由多個異常級(EL0 - EL3)組æˆï¼Œå°æ–¼ EL0 å’Œ EL1
æœ‰å°æ‡‰çš„安全和éžå®‰å…¨æ¨¡å¼ã€‚EL2 是系統管ç†ç´šï¼Œä¸”僅存在於éžå®‰å…¨æ¨¡å¼ä¸‹ã€‚
EL3 是最高特權級,且僅存在於安全模å¼ä¸‹ã€‚
-基於本文檔的目的,我們將簡單地使用『引導è£è¼‰ç¨‹åºã€ï¼ˆã€Žboot loaderã€ï¼‰
-這個術語來定義在將控制權交給 Linux å…§æ ¸å‰ CPU 上執行的所有軟體。
+基於本文檔的目的,我們將簡單地使用‘引導è£è¼‰ç¨‹åºâ€™ï¼ˆâ€˜boot loader’)
+這個術語來定義在將控制權交給 Linux å…§æ ¸å‰ CPU 上執行的所有軟件。
這å¯èƒ½åŒ…å«å®‰å…¨ç›£æŽ§å’Œç³»çµ±ç®¡ç†ä»£ç¢¼ï¼Œæˆ–者它å¯èƒ½åªæ˜¯ä¸€äº›ç”¨æ–¼æº–備最å°å•“å‹•
環境的指令。
@@ -74,7 +74,7 @@ RAM,或å¯èƒ½ä½¿ç”¨å°é€™å€‹è¨­å‚™å·²çŸ¥çš„ RAM ä¿¡æ¯ï¼Œé‚„å¯èƒ½æ˜¯å¼•å°Žè£
數據塊將在使能緩存的情æ³ä¸‹ä»¥ 2MB 粒度被映射,故其ä¸èƒ½è¢«ç½®æ–¼å¿…須以特定
屬性映射的2Må€åŸŸå…§ã€‚
-註: v4.2 之å‰çš„ç‰ˆæœ¬åŒæ™‚è¦æ±‚設備樹數據塊被置於從內核映åƒä»¥ä¸‹
+注: v4.2 之å‰çš„ç‰ˆæœ¬åŒæ™‚è¦æ±‚設備樹數據塊被置於從內核映åƒä»¥ä¸‹
text_offset 字節處算起第一個 512MB 內。
3ã€è§£å£“內核映åƒ
@@ -106,7 +106,7 @@ AArch64 å…§æ ¸ç•¶å‰æ²’有æä¾›è‡ªè§£å£“代碼,因此如果使用了壓縮內
u32 res5; /* ä¿ç•™ (用於 PE COFF å移) */
-映åƒé ­æ³¨é‡‹ï¼š
+映åƒé ­è¨»é‡‹ï¼š
- 自 v3.17 起,除éžå¦æœ‰èªªæ˜Žï¼Œæ‰€æœ‰åŸŸéƒ½æ˜¯å°ç«¯æ¨¡å¼ã€‚
@@ -143,7 +143,7 @@ AArch64 å…§æ ¸ç•¶å‰æ²’有æä¾›è‡ªè§£å£“代碼,因此如果使用了壓縮內
字節處,並從該處被調用。2MB å°é½ŠåŸºå€å’Œå…§æ ¸æ˜ åƒèµ·å§‹åœ°å€ä¹‹é–“çš„å€åŸŸå°æ–¼
內核來說沒有特殊æ„義,且å¯èƒ½è¢«ç”¨æ–¼å…¶ä»–目的。
從映åƒèµ·å§‹åœ°å€ç®—起,最少必須準備 image_size 字節的空閒內存供內核使用。
-註: v4.6 之å‰çš„版本無法使用內核映åƒç‰©ç†å移以下的內存,所以當時建議
+注: v4.6 之å‰çš„版本無法使用內核映åƒç‰©ç†å移以下的內存,所以當時建議
將映åƒå„˜é‡æ”¾ç½®åœ¨é è¿‘系統內存起始的地方。
任何æä¾›çµ¦å…§æ ¸çš„內存(甚至在映åƒèµ·å§‹åœ°å€ä¹‹å‰ï¼‰ï¼Œè‹¥æœªå¾žå…§æ ¸ä¸­æ¨™è¨˜çˆ²ä¿ç•™
@@ -151,7 +151,7 @@ AArch64 å…§æ ¸ç•¶å‰æ²’有æä¾›è‡ªè§£å£“代碼,因此如果使用了壓縮內
在跳轉入內核å‰ï¼Œå¿…須符åˆä»¥ä¸‹ç‹€æ…‹ï¼š
-- åœæ­¢æ‰€æœ‰ DMA è¨­å‚™ï¼Œé€™æ¨£å…§å­˜æ•¸æ“šå°±ä¸æœƒå› çˆ²è™›å‡ç¶²çµ¡åŒ…或ç£ç¢Ÿæ•¸æ“šè€Œ
+- åœæ­¢æ‰€æœ‰ DMA è¨­å‚™ï¼Œé€™æ¨£å…§å­˜æ•¸æ“šå°±ä¸æœƒå› çˆ²è™›å‡ç¶²çµ¡åŒ…或ç£ç›¤æ•¸æ“šè€Œ
被破壞。這å¯èƒ½å¯ä»¥ç¯€çœä½ è¨±å¤šçš„調試時間。
- 主 CPU 通用寄存器設置
@@ -175,7 +175,7 @@ AArch64 å…§æ ¸ç•¶å‰æ²’有æä¾›è‡ªè§£å£“代碼,因此如果使用了壓縮內
而ä¸é€šéŽè™›æ“¬åœ°å€æ“ä½œç¶­è­·æ§‹æž¶ç·©å­˜çš„ç³»çµ±ç·©å­˜ï¼ˆä¸æŽ¨è–¦ï¼‰ï¼Œå¿…é ˆè¢«é…置且
ç¦ç”¨ã€‚
- *è­¯è€…è¨»ï¼šå°æ–¼ PoC 以åŠç·©å­˜ç›¸é—œå…§å®¹ï¼Œè«‹åƒè€ƒ ARMv8 æ§‹æž¶åƒè€ƒæ‰‹å†Š
+ *è­¯è€…æ³¨ï¼šå°æ–¼ PoC 以åŠç·©å­˜ç›¸é—œå…§å®¹ï¼Œè«‹åƒè€ƒ ARMv8 æ§‹æž¶åƒè€ƒæ‰‹å†Š
ARM DDI 0487A
- 架構計時器
@@ -189,7 +189,7 @@ AArch64 å…§æ ¸ç•¶å‰æ²’有æä¾›è‡ªè§£å£“代碼,因此如果使用了壓縮內
接收。
- 系統寄存器
- 在進入內核映åƒçš„異常級中,所有構架中å¯å¯«çš„系統寄存器必須通éŽè»Ÿé«”
+ 在進入內核映åƒçš„異常級中,所有構架中å¯å¯«çš„系統寄存器必須通éŽè»Ÿä»¶
在一個更高的異常級別下åˆå§‹åŒ–,以防止在 未知 狀態下é‹è¡Œã€‚
å°æ–¼æ“有 GICv3 中斷控制器並以 v3 模å¼é‹è¡Œçš„系統:
@@ -214,14 +214,14 @@ AArch64 å…§æ ¸ç•¶å‰æ²’有æä¾›è‡ªè§£å£“代碼,因此如果使用了壓縮內
引導è£è¼‰ç¨‹åºå¿…須在æ¯å€‹ CPU 處於以下狀態時跳入內核入å£ï¼š
- 主 CPU 必須直接跳入內核映åƒçš„ç¬¬ä¸€æ¢æŒ‡ä»¤ã€‚é€šéŽæ­¤ CPU 傳éžçš„設備樹
- 數據塊必須在æ¯å€‹ CPU 節點中包å«ä¸€å€‹ 『enable-method〠屬性,所
+ 數據塊必須在æ¯å€‹ CPU 節點中包å«ä¸€å€‹ ‘enable-method’ 屬性,所
支æŒçš„ enable-method 請見下文。
引導è£è¼‰ç¨‹åºå¿…須生æˆé€™äº›è¨­å‚™æ¨¹å±¬æ€§ï¼Œä¸¦åœ¨è·³å…¥å…§æ ¸å…¥å£ä¹‹å‰å°‡å…¶æ’å…¥
數據塊。
-- enable-method 爲 「spin-table〠的 CPU 必須在它們的 CPU
- 節點中包å«ä¸€å€‹ 『cpu-release-addr〠屬性。這個屬性標識了一個
+- enable-method 爲 “spin-table†的 CPU 必須在它們的 CPU
+ 節點中包å«ä¸€å€‹ ‘cpu-release-addr’ 屬性。這個屬性標識了一個
64 ä½è‡ªç„¶å°é½Šä¸”åˆå§‹åŒ–爲零的內存ä½ç½®ã€‚
這些 CPU 必須在內存ä¿ç•™å€ï¼ˆé€šéŽè¨­å‚™æ¨¹ä¸­çš„ /memreserve/ 域傳éž
@@ -231,15 +231,15 @@ AArch64 å…§æ ¸ç•¶å‰æ²’有æä¾›è‡ªè§£å£“代碼,因此如果使用了壓縮內
時,CPU 必須跳入此值所指å‘的地å€ã€‚此值爲一個單ç¨çš„ 64 ä½å°ç«¯å€¼ï¼Œ
å› æ­¤ CPU 須在跳轉å‰å°‡æ‰€è®€å–的值轉æ›çˆ²å…¶æœ¬èº«çš„端模å¼ã€‚
-- enable-method 爲 「psci〠的 CPU ä¿æŒåœ¨å…§æ ¸å¤–(比如,在
+- enable-method 爲 “psci†的 CPU ä¿æŒåœ¨å…§æ ¸å¤–(比如,在
memory 節點中æè¿°çˆ²å…§æ ¸ç©ºé–“的內存å€å¤–,或在通éŽè¨­å‚™æ¨¹ /memreserve/
域中æè¿°çˆ²å…§æ ¸ä¿ç•™å€çš„空間中)。內核將會發起在 ARM 文檔(編號
- ARM DEN 0022A:用於 ARM 上的電æºç‹€æ…‹å”調接å£ç³»çµ±è»Ÿé«”)中æè¿°çš„
+ ARM DEN 0022A:用於 ARM 上的電æºç‹€æ…‹å”調接å£ç³»çµ±è»Ÿä»¶ï¼‰ä¸­æè¿°çš„
CPU_ON 調用來將 CPU 帶入內核。
*譯者注: ARM DEN 0022A 已更新到 ARM DEN 0022C。
- 設備樹必須包å«ä¸€å€‹ 『psci〠節點,請åƒè€ƒä»¥ä¸‹æ–‡æª”:
+ 設備樹必須包å«ä¸€å€‹ ‘psci’ 節點,請åƒè€ƒä»¥ä¸‹æ–‡æª”:
Documentation/devicetree/bindings/arm/psci.yaml
diff --git a/Documentation/translations/zh_TW/arch/arm64/elf_hwcaps.rst b/Documentation/translations/zh_TW/arch/arm64/elf_hwcaps.rst
index ca7ff749a67b..d2c1c2f23812 100644
--- a/Documentation/translations/zh_TW/arch/arm64/elf_hwcaps.rst
+++ b/Documentation/translations/zh_TW/arch/arm64/elf_hwcaps.rst
@@ -17,11 +17,11 @@ ARM64 ELF hwcaps
1. 簡介
-------
-有些硬體或軟體功能僅在æŸäº› CPU 實ç¾ä¸Šå’Œ/或在具體æŸå€‹å…§æ ¸é…置上å¯ç”¨ï¼Œä½†
+有些硬件或軟件功能僅在æŸäº› CPU 實ç¾ä¸Šå’Œ/或在具體æŸå€‹å…§æ ¸é…置上å¯ç”¨ï¼Œä½†
å°æ–¼è™•æ–¼ EL0 的用戶空間代碼沒有å¯ç”¨çš„æž¶æ§‹ç™¼ç¾æ©Ÿåˆ¶ã€‚內核通éŽåœ¨è¼”助å‘é‡è¡¨
公開一組稱爲 hwcaps 的標誌而把這些功能暴露給用戶空間。
-用戶空間軟體å¯ä»¥é€šéŽç²å–輔助å‘é‡çš„ AT_HWCAP 或 AT_HWCAP2 æ¢ç›®ä¾†æ¸¬è©¦åŠŸèƒ½ï¼Œ
+用戶空間軟件å¯ä»¥é€šéŽç²å–輔助å‘é‡çš„ AT_HWCAP 或 AT_HWCAP2 æ¢ç›®ä¾†æ¸¬è©¦åŠŸèƒ½ï¼Œ
並測試是å¦è¨­ç½®äº†ç›¸é—œæ¨™èªŒï¼Œä¾‹å¦‚::
bool floating_point_is_present(void)
@@ -33,7 +33,7 @@ ARM64 ELF hwcaps
return false;
}
-如果軟體ä¾è³´æ–¼ hwcap æè¿°çš„功能,在嘗試使用該功能å‰å‰‡æ‡‰æª¢æŸ¥ç›¸é—œçš„ hwcap
+如果軟件ä¾è³´æ–¼ hwcap æè¿°çš„功能,在嘗試使用該功能å‰å‰‡æ‡‰æª¢æŸ¥ç›¸é—œçš„ hwcap
標誌以驗證該功能是å¦å­˜åœ¨ã€‚
ä¸èƒ½é€šéŽå…¶ä»–æ–¹å¼æŽ¢æŸ¥é€™äº›åŠŸèƒ½ã€‚ç•¶ä¸€å€‹åŠŸèƒ½ä¸å¯ç”¨æ™‚,嘗試使用它å¯èƒ½å°Žè‡´ä¸å¯
@@ -44,8 +44,8 @@ ARM64 ELF hwcaps
----------------
大多數 hwcaps æ—¨åœ¨èªªæ˜Žé€šéŽæž¶æ§‹ ID 寄存器(處於 EL0 的用戶空間代碼無法訪å•)
-æè¿°çš„功能的存在。這些 hwcap é€šéŽ ID 寄存器欄ä½å®šç¾©ï¼Œä¸¦ä¸”應根據 ARM 體系
-çµæ§‹åƒè€ƒæ‰‹å†Šï¼ˆARM ARM)中定義的欄ä½ä¾†è§£é‡‹èªªæ˜Žã€‚
+æè¿°çš„功能的存在。這些 hwcap é€šéŽ ID 寄存器字段定義,並且應根據 ARM 體系
+çµæ§‹åƒè€ƒæ‰‹å†Šï¼ˆARM ARM)中定義的字段來解釋說明。
這些 hwcaps 以下é¢çš„å½¢å¼æè¿°::
diff --git a/Documentation/translations/zh_TW/arch/arm64/legacy_instructions.txt b/Documentation/translations/zh_TW/arch/arm64/legacy_instructions.txt
index c2d02cd5017d..7d1f0593d7ca 100644
--- a/Documentation/translations/zh_TW/arch/arm64/legacy_instructions.txt
+++ b/Documentation/translations/zh_TW/arch/arm64/legacy_instructions.txt
@@ -31,7 +31,7 @@ Documentation/arch/arm64/legacy_instructions.rst 的中文翻譯
以下爲正文
---------------------------------------------------------------------
Linux 內核在 arm64 ä¸Šçš„ç§»æ¤æä¾›äº†ä¸€å€‹åŸºç¤Žæ¡†æž¶ï¼Œä»¥æ”¯æŒæ§‹æž¶ä¸­æ­£åœ¨è¢«æ·˜æ±°æˆ–已廢棄指令的模擬執行。
-這個基礎框架的代碼使用未定義指令鉤å­ï¼ˆhooksï¼‰ä¾†æ”¯æŒæ¨¡æ“¬ã€‚如果指令存在,它也å…許在硬體中啓用該指令。
+這個基礎框架的代碼使用未定義指令鉤å­ï¼ˆhooksï¼‰ä¾†æ”¯æŒæ¨¡æ“¬ã€‚如果指令存在,它也å…許在硬件中啓用該指令。
模擬模å¼å¯é€šéŽå¯« sysctl 節點(/proc/sys/abi)來控制。
ä¸åŒçš„執行方å¼åŠ sysctl 節點的相應值,解釋如下:
@@ -42,18 +42,18 @@ Linux 內核在 arm64 ä¸Šçš„ç§»æ¤æä¾›äº†ä¸€å€‹åŸºç¤Žæ¡†æž¶ï¼Œä»¥æ”¯æŒæ§‹æž¶ä
* Emulate(模擬)
值: 1
- 使用軟體模擬方å¼ã€‚爲解決軟體é·ç§»å•題,這種模擬指令模å¼çš„使用是被跟蹤的,並會發出速率é™åˆ¶è­¦å‘Šã€‚
+ 使用軟件模擬方å¼ã€‚爲解決軟件é·ç§»å•題,這種模擬指令模å¼çš„使用是被跟蹤的,並會發出速率é™åˆ¶è­¦å‘Šã€‚
它是那些構架中正在被淘汰的指令,如 CP15 barriers(隔離指令),的默èªè™•ç†æ–¹å¼ã€‚
-* Hardware Execution(硬體執行)
+* Hardware Execution(硬件執行)
值: 2
- 雖然標記爲正在被淘汰,但一些實ç¾å¯èƒ½æä¾›ç¡¬é«”執行這些指令的使能/ç¦ç”¨æ“作。
- 使用硬體執行一般會有更好的性能,但將無法收集é‹è¡Œæ™‚å°æ­£è¢«æ·˜æ±°æŒ‡ä»¤çš„使用統計數據。
+ 雖然標記爲正在被淘汰,但一些實ç¾å¯èƒ½æä¾›ç¡¬ä»¶åŸ·è¡Œé€™äº›æŒ‡ä»¤çš„使能/ç¦ç”¨æ“作。
+ 使用硬件執行一般會有更好的性能,但將無法收集é‹è¡Œæ™‚å°æ­£è¢«æ·˜æ±°æŒ‡ä»¤çš„使用統計數據。
默èªåŸ·è¡Œæ¨¡å¼ä¾è³´æ–¼æŒ‡ä»¤åœ¨æ§‹æž¶ä¸­ç‹€æ…‹ã€‚正在被淘汰的指令應該以模擬(Emulateï¼‰ä½œçˆ²é»˜èªæ¨¡å¼ï¼Œ
而已廢棄的指令必須默èªä½¿ç”¨æœªå®šç¾©ï¼ˆUndef)模å¼
-注æ„:指令模擬å¯èƒ½ç„¡æ³•æ‡‰å°æ‰€æœ‰æƒ…æ³ã€‚更多詳情請åƒè€ƒå–®ç¨çš„æŒ‡ä»¤æ³¨é‡‹ã€‚
+注æ„:指令模擬å¯èƒ½ç„¡æ³•æ‡‰å°æ‰€æœ‰æƒ…æ³ã€‚更多詳情請åƒè€ƒå–®ç¨çš„æŒ‡ä»¤è¨»é‡‹ã€‚
å—æ”¯æŒçš„éºç•™æŒ‡ä»¤
-------------
@@ -71,7 +71,7 @@ Linux 內核在 arm64 ä¸Šçš„ç§»æ¤æä¾›äº†ä¸€å€‹åŸºç¤Žæ¡†æž¶ï¼Œä»¥æ”¯æŒæ§‹æž¶ä
節點: /proc/sys/abi/setend
狀態: æ­£è¢«æ·˜æ±°ï¼Œä¸æŽ¨è–¦ä½¿ç”¨
默èªåŸ·è¡Œæ–¹å¼: Emulate (1)*
-註:爲了使能這個特性,系統中的所有 CPU 必須在 EL0 æ”¯æŒæ··åˆå­—節åºã€‚
+注:爲了使能這個特性,系統中的所有 CPU 必須在 EL0 æ”¯æŒæ··åˆå­—節åºã€‚
如果一個新的 CPU ï¼ˆä¸æ”¯æŒæ··åˆå­—節åºï¼‰ 在使能這個特性後被熱æ’入系統,
在應用中å¯èƒ½æœƒå‡ºç¾ä¸å¯é æœŸçš„çµæžœã€‚
diff --git a/Documentation/translations/zh_TW/arch/arm64/memory.txt b/Documentation/translations/zh_TW/arch/arm64/memory.txt
index 0280200e791f..e41c518e71c6 100644
--- a/Documentation/translations/zh_TW/arch/arm64/memory.txt
+++ b/Documentation/translations/zh_TW/arch/arm64/memory.txt
@@ -28,17 +28,17 @@ Documentation/arch/arm64/memory.rst 的中文翻譯
以下爲正文
---------------------------------------------------------------------
- Linux 在 AArch64 中的內存布局
+ Linux 在 AArch64 中的內存佈局
===========================
作者: Catalin Marinas <catalin.marinas@arm.com>
-本文檔æè¿° AArch64 Linux 內核所使用的虛擬內存布局。此構架å¯ä»¥å¯¦ç¾
+本文檔æè¿° AArch64 Linux 內核所使用的虛擬內存佈局。此構架å¯ä»¥å¯¦ç¾
é å¤§å°çˆ² 4KB çš„ 4 級轉æ›è¡¨å’Œé å¤§å°çˆ² 64KB çš„ 3 級轉æ›è¡¨ã€‚
AArch64 Linux 使用 3 級或 4 級轉æ›è¡¨ï¼Œå…¶é å¤§å°é…置爲 4KBï¼Œå°æ–¼ç”¨æˆ¶å’Œå…§æ ¸
分別都有 39-bit (512GB) 或 48-bit (256TB) 的虛擬地å€ç©ºé–“。
-å°æ–¼é å¤§å°çˆ² 64KBçš„é…置,僅使用 2 級轉æ›è¡¨ï¼Œæœ‰ 42-bit (4TB) 的虛擬地å€ç©ºé–“,但內存布局相åŒã€‚
+å°æ–¼é å¤§å°çˆ² 64KBçš„é…置,僅使用 2 級轉æ›è¡¨ï¼Œæœ‰ 42-bit (4TB) 的虛擬地å€ç©ºé–“,但內存佈局相åŒã€‚
用戶地å€ç©ºé–“çš„ 63:48 ä½çˆ² 0,而內核地å€ç©ºé–“的相應ä½çˆ² 1。TTBRx çš„
鏿“‡ç”±è™›æ“¬åœ°å€çš„ 63 ä½çµ¦å‡ºã€‚swapper_pg_dir 僅包å«å…§æ ¸ï¼ˆå…¨å±€ï¼‰æ˜ å°„,
@@ -46,7 +46,7 @@ AArch64 Linux 使用 3 級或 4 級轉æ›è¡¨ï¼Œå…¶é å¤§å°é…置爲 4KBï¼Œå°æ–
TTBR1 中,且從ä¸å¯«å…¥ TTBR0。
-AArch64 Linux 在é å¤§å°çˆ² 4KB,並使用 3 級轉æ›è¡¨æ™‚的內存布局:
+AArch64 Linux 在é å¤§å°çˆ² 4KB,並使用 3 級轉æ›è¡¨æ™‚的內存佈局:
èµ·å§‹åœ°å€ çµæŸåœ°å€ å¤§å° ç”¨é€”
-----------------------------------------------------------------------
@@ -54,7 +54,7 @@ AArch64 Linux 在é å¤§å°çˆ² 4KB,並使用 3 級轉æ›è¡¨æ™‚的內存布局ï¼
ffffff8000000000 ffffffffffffffff 512GB 內核空間
-AArch64 Linux 在é å¤§å°çˆ² 4KB,並使用 4 級轉æ›è¡¨æ™‚的內存布局:
+AArch64 Linux 在é å¤§å°çˆ² 4KB,並使用 4 級轉æ›è¡¨æ™‚的內存佈局:
èµ·å§‹åœ°å€ çµæŸåœ°å€ å¤§å° ç”¨é€”
-----------------------------------------------------------------------
@@ -62,7 +62,7 @@ AArch64 Linux 在é å¤§å°çˆ² 4KB,並使用 4 級轉æ›è¡¨æ™‚的內存布局ï¼
ffff000000000000 ffffffffffffffff 256TB 內核空間
-AArch64 Linux 在é å¤§å°çˆ² 64KB,並使用 2 級轉æ›è¡¨æ™‚的內存布局:
+AArch64 Linux 在é å¤§å°çˆ² 64KB,並使用 2 級轉æ›è¡¨æ™‚的內存佈局:
èµ·å§‹åœ°å€ çµæŸåœ°å€ å¤§å° ç”¨é€”
-----------------------------------------------------------------------
@@ -70,7 +70,7 @@ AArch64 Linux 在é å¤§å°çˆ² 64KB,並使用 2 級轉æ›è¡¨æ™‚的內存布局ï
fffffc0000000000 ffffffffffffffff 4TB 內核空間
-AArch64 Linux 在é å¤§å°çˆ² 64KB,並使用 3 級轉æ›è¡¨æ™‚的內存布局:
+AArch64 Linux 在é å¤§å°çˆ² 64KB,並使用 3 級轉æ›è¡¨æ™‚的內存佈局:
èµ·å§‹åœ°å€ çµæŸåœ°å€ å¤§å° ç”¨é€”
-----------------------------------------------------------------------
@@ -78,7 +78,7 @@ AArch64 Linux 在é å¤§å°çˆ² 64KB,並使用 3 級轉æ›è¡¨æ™‚的內存布局ï
ffff000000000000 ffffffffffffffff 256TB 內核空間
-更詳細的內核虛擬內存布局,請åƒé–±å…§æ ¸å•“å‹•ä¿¡æ¯ã€‚
+更詳細的內核虛擬內存佈局,請åƒé–±å…§æ ¸å•“å‹•ä¿¡æ¯ã€‚
4KB é å¤§å°çš„轉æ›è¡¨æŸ¥æ‰¾ï¼š
diff --git a/Documentation/translations/zh_TW/arch/arm64/perf.rst b/Documentation/translations/zh_TW/arch/arm64/perf.rst
index 645f3944a0f4..405d5f66964f 100644
--- a/Documentation/translations/zh_TW/arch/arm64/perf.rst
+++ b/Documentation/translations/zh_TW/arch/arm64/perf.rst
@@ -59,7 +59,7 @@ EL2(VHE 內核 或 non-VHE 虛擬機監控器)。
KVM 客戶機å¯èƒ½é‹è¡Œåœ¨ EL0(用戶空間)和 EL1(內核)。
-由於宿主機和客戶機之間é‡ç–Šçš„異常級別,我們ä¸èƒ½åƒ…僅ä¾é  PMU 的硬體異
+由於宿主機和客戶機之間é‡ç–Šçš„異常級別,我們ä¸èƒ½åƒ…僅ä¾é  PMU 的硬件異
å¸¸éŽæ¿¾æ©Ÿåˆ¶-因此我們必須啓用/ç¦ç”¨å°æ–¼å®¢æˆ¶æ©Ÿé€²å…¥å’Œé€€å‡ºçš„計數。而這在
VHE å’Œ non-VHE 系統上表ç¾ä¸åŒã€‚
diff --git a/Documentation/translations/zh_TW/arch/arm64/silicon-errata.txt b/Documentation/translations/zh_TW/arch/arm64/silicon-errata.txt
index f6f41835a54a..70371807ca83 100644
--- a/Documentation/translations/zh_TW/arch/arm64/silicon-errata.txt
+++ b/Documentation/translations/zh_TW/arch/arm64/silicon-errata.txt
@@ -28,39 +28,39 @@ Documentation/arch/arm64/silicon-errata.rst 的中文翻譯
以下爲正文
---------------------------------------------------------------------
- 晶片勘誤和軟體補救措施
+ 芯片勘誤和軟件補救措施
==================
作者: Will Deacon <will.deacon@arm.com>
日期: 2015年11月27日
-一個ä¸å¹¸çš„ç¾å¯¦ï¼šç¡¬é«”經常帶有一些所謂的「瑕疵(errata)ã€ï¼Œå°Žè‡´å…¶åœ¨
-æŸäº›ç‰¹å®šæƒ…æ³ä¸‹æœƒé•背構架定義的行爲。就基於 ARM 的硬體而言,這些瑕疵
+一個ä¸å¹¸çš„ç¾å¯¦ï¼šç¡¬ä»¶ç¶“常帶有一些所謂的“瑕疵(errata)â€ï¼Œå°Žè‡´å…¶åœ¨
+æŸäº›ç‰¹å®šæƒ…æ³ä¸‹æœƒé•背構架定義的行爲。就基於 ARM 的硬件而言,這些瑕疵
大體å¯åˆ†çˆ²ä»¥ä¸‹å¹¾é¡žï¼š
A 類:無å¯è¡Œè£œæ•‘措施的嚴é‡ç¼ºé™·ã€‚
B é¡žï¼šæœ‰å¯æŽ¥å—的補救措施的é‡å¤§æˆ–åš´é‡ç¼ºé™·ã€‚
C 類:在正常æ“ä½œä¸­ä¸æœƒé¡¯ç¾çš„å°ç‘•疵。
-更多資訊,請在 infocenter.arm.com (需註冊)中查閱「軟體開發者勘誤
-筆記ã€ï¼ˆã€ŒSoftware Developers Errata Noticeã€ï¼‰æ–‡æª”。
+更多資訊,請在 infocenter.arm.com (需註冊)中查閱“軟件開發者勘誤
+筆記â€ï¼ˆâ€œSoftware Developers Errata Noticeâ€ï¼‰æ–‡æª”。
-å°æ–¼ Linux 而言,B 類缺陷å¯èƒ½éœ€è¦ä½œæ¥­ç³»çµ±çš„æŸäº›ç‰¹åˆ¥è™•ç†ã€‚例如,é¿å…
+å°æ–¼ Linux 而言,B 類缺陷å¯èƒ½éœ€è¦æ“作系統的æŸäº›ç‰¹åˆ¥è™•ç†ã€‚例如,é¿å…
一個特殊的代碼åºåˆ—,或是以一種特定的方å¼é…置處ç†å™¨ã€‚在æŸç¨®ä¸å¤ªå¸¸è¦‹çš„
情æ³ä¸‹ï¼Œçˆ²å°‡ A 類缺陷當作 C 類處ç†ï¼Œå¯èƒ½éœ€è¦ç”¨é¡žä¼¼çš„æ‰‹æ®µã€‚這些手段被
-統稱爲「軟體補救措施ã€ï¼Œä¸”僅在少數情æ³éœ€è¦ï¼ˆä¾‹å¦‚,那些需è¦ä¸€å€‹é‹è¡Œåœ¨
+統稱爲“軟件補救措施â€ï¼Œä¸”僅在少數情æ³éœ€è¦ï¼ˆä¾‹å¦‚,那些需è¦ä¸€å€‹é‹è¡Œåœ¨
éžå®‰å…¨ç•°å¸¸ç´šçš„補救措施 *並且* 能被 Linux 觸發的情æ³ï¼‰ã€‚
-å°æ–¼å°šåœ¨è¨Žè«–中的å¯èƒ½å°æœªå—瑕疵影響的系統產生干擾的軟體補救措施,有一個
-相應的內核é…置(Kconfig)é¸é …被加在 「內核特性(Kernel Features)ã€->
-「基於å¯é¸æ–¹æ³•框架的 ARM 瑕疵補救措施(ARM errata workarounds via
+å°æ–¼å°šåœ¨è¨Žè«–中的å¯èƒ½å°æœªå—瑕疵影響的系統產生干擾的軟件補救措施,有一個
+相應的內核é…置(Kconfig)é¸é …被加在 “內核特性(Kernel Features)â€->
+“基於å¯é¸æ–¹æ³•框架的 ARM 瑕疵補救措施(ARM errata workarounds via
the alternatives framework)"。這些é¸é …被默èªé–‹å•“,若探測到å—影響的CPU,
補ä¸å°‡åœ¨é‹è¡Œæ™‚被使用。至於å°ç³»çµ±é‹è¡Œå½±éŸ¿è¼ƒå°çš„補救措施,內核é…ç½®é¸é …
-並ä¸å­˜åœ¨ï¼Œä¸”代碼以æŸç¨®è¦é¿ç‘•疵的方å¼è¢«æ§‹é€ ï¼ˆå¸¶æ³¨é‡‹çˆ²å®œï¼‰ã€‚
+並ä¸å­˜åœ¨ï¼Œä¸”代碼以æŸç¨®è¦é¿ç‘•疵的方å¼è¢«æ§‹é€ ï¼ˆå¸¶è¨»é‡‹çˆ²å®œï¼‰ã€‚
-é€™ç¨®åšæ³•å°æ–¼åœ¨ä»»æ„內核原始碼樹中準確地判斷出哪個瑕疵已被軟體方法所補救
-ç¨å¾®æœ‰é»žéº»ç…©ï¼Œæ‰€ä»¥åœ¨ Linux 內核中此文件作爲軟體補救措施的註冊表,
-並將在新的軟體補救措施被æäº¤å’Œå‘後移æ¤ï¼ˆbackported)到穩定內核時被更新。
+é€™ç¨®åšæ³•å°æ–¼åœ¨ä»»æ„å…§æ ¸æºä»£ç¢¼æ¨¹ä¸­æº–確地判斷出哪個瑕疵已被軟件方法所補救
+ç¨å¾®æœ‰é»žéº»ç…©ï¼Œæ‰€ä»¥åœ¨ Linux 內核中此文件作爲軟件補救措施的註冊表,
+並將在新的軟件補救措施被æäº¤å’Œå‘後移æ¤ï¼ˆbackported)到穩定內核時被更新。
| 實ç¾è€… | å—影響的組件 | 勘誤編號 | å…§æ ¸é…ç½® |
+----------------+-----------------+-----------------+-------------------------+
diff --git a/Documentation/translations/zh_TW/arch/arm64/tagged-pointers.txt b/Documentation/translations/zh_TW/arch/arm64/tagged-pointers.txt
index c0be1d1e0d01..9812d99549ba 100644
--- a/Documentation/translations/zh_TW/arch/arm64/tagged-pointers.txt
+++ b/Documentation/translations/zh_TW/arch/arm64/tagged-pointers.txt
@@ -36,14 +36,14 @@ Documentation/arch/arm64/tagged-pointers.rst 的中文翻譯
AArch64 Linux 中的潛在用途。
å…§æ ¸æä¾›çš„地å€è½‰æ›è¡¨é…ç½®ä½¿é€šéŽ TTBR0 完æˆçš„虛擬地å€è½‰æ›ï¼ˆå³ç”¨æˆ¶ç©ºé–“
-映射),其虛擬地å€çš„æœ€é«˜ 8 ä½ï¼ˆ63:56)會被轉æ›ç¡¬é«”所忽略。這種機制
-讓這些ä½å¯ä¾›æ‡‰ç”¨ç¨‹å¼è‡ªç”±ä½¿ç”¨ï¼Œå…¶æ³¨æ„事項如下:
+映射),其虛擬地å€çš„æœ€é«˜ 8 ä½ï¼ˆ63:56)會被轉æ›ç¡¬ä»¶æ‰€å¿½ç•¥ã€‚這種機制
+讓這些ä½å¯ä¾›æ‡‰ç”¨ç¨‹åºè‡ªç”±ä½¿ç”¨ï¼Œå…¶æ³¨æ„事項如下:
(1) å…§æ ¸è¦æ±‚所有傳éžåˆ° EL1 的用戶空間地å€å¸¶æœ‰ 0x00 標記。
- 這æ„味著任何攜帶用戶空間虛擬地å€çš„系統調用(syscall)
+ 這æ„味ç€ä»»ä½•攜帶用戶空間虛擬地å€çš„系統調用(syscall)
åƒæ•¸ *å¿…é ˆ* 在陷入內核å‰ä½¿å®ƒå€‘的最高字節被清零。
- (2) éžé›¶æ¨™è¨˜åœ¨å‚³éžä¿¡è™Ÿæ™‚ä¸è¢«ä¿å­˜ã€‚這æ„味著在應用程å¼ä¸­åˆ©ç”¨äº†
+ (2) éžé›¶æ¨™è¨˜åœ¨å‚³éžä¿¡è™Ÿæ™‚ä¸è¢«ä¿å­˜ã€‚這æ„味ç€åœ¨æ‡‰ç”¨ç¨‹åºä¸­åˆ©ç”¨äº†
標記的信號處ç†å‡½æ•¸ç„¡æ³•ä¾è³´ siginfo_t 的用戶空間虛擬
åœ°å€æ‰€æ”œå¸¶çš„包å«å…¶å…§éƒ¨åŸŸä¿¡æ¯çš„æ¨™è¨˜ã€‚æ­¤è¦å‰‡çš„一個例外是
當信號是在調試觀察點的異常處ç†ç¨‹åºä¸­ç”¢ç”Ÿçš„,此時標記的
@@ -53,5 +53,5 @@ AArch64 Linux 中的潛在用途。
的高字節,C 編譯器很å¯èƒ½ç„¡æ³•判斷它們是ä¸åŒçš„。
此構架會阻止å°å¸¶æ¨™è¨˜çš„ PC 指é‡çš„利用,因此在異常返回時,其高字節
-將被設置æˆä¸€å€‹çˆ² 「55〠的擴展符。
+將被設置æˆä¸€å€‹çˆ² “55†的擴展符。
diff --git a/Documentation/translations/zh_TW/arch/index.rst b/Documentation/translations/zh_TW/arch/index.rst
new file mode 100644
index 000000000000..7c0490589465
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/index.rst
@@ -0,0 +1,29 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+處ç†å™¨é«”ç³»çµæ§‹
+==============
+
+以下文檔æä¾›äº†å…·é«”架構實ç¾çš„編程細節。
+
+.. toctree::
+ :maxdepth: 2
+
+ mips/index
+ arm64/index
+ openrisc/index
+ parisc/index
+ loongarch/index
+
+TODOList:
+
+* arm/index
+* m68k/index
+* nios2/index
+* powerpc/index
+* s390/index
+* sh/index
+* sparc/index
+* x86/index
+* xtensa/index
+* ../riscv/index
+
diff --git a/Documentation/translations/zh_TW/arch/loongarch/booting.rst b/Documentation/translations/zh_TW/arch/loongarch/booting.rst
new file mode 100644
index 000000000000..88291090cea1
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/loongarch/booting.rst
@@ -0,0 +1,49 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/loongarch/booting.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+====================
+å•“å‹• Linux/LoongArch
+====================
+
+:作者: å¸å»¶é¨° <siyanteng@loongson.cn>
+:日期: 2022年11月18日
+
+BootLoader傳éžçµ¦å…§æ ¸çš„ä¿¡æ¯
+==========================
+
+LoongArch支æŒACPIå’ŒFDT啓動,需è¦å‚³éžçµ¦å…§æ ¸çš„ä¿¡æ¯åŒ…括memmapã€initrdã€cmdlineã€å¯
+é¸çš„ACPI/FDT表等。
+
+內核在 `kernel_entry` å…¥å£è™•被傳éžä»¥ä¸‹åƒæ•¸:
+
+ - a0 = efi_boot: `efi_boot` 是一個標誌,表示這個啓動環境是å¦å®Œå…¨ç¬¦åˆUEFI
+ çš„è¦æ±‚。
+
+ - a1 = cmdline: `cmdline` 是一個指å‘內核命令行的指é‡ã€‚
+
+ - a2 = systemtable: `systemtable` 指å‘EFI的系統表,在這個階段涉åŠçš„æ‰€æœ‰
+ 指é‡éƒ½æ˜¯ç‰©ç†åœ°å€ã€‚
+
+Linux/LoongArchå…§æ ¸é¡åƒæ–‡ä»¶é ­
+=============================
+
+å…§æ ¸é¡åƒæ˜¯EFIé¡åƒã€‚作爲PE文件,它們有一個64å­—ç¯€çš„é ­éƒ¨çµæ§‹é«”,如下所示::
+
+ u32 MZ_MAGIC /* "MZ", MS-DOS é ­ */
+ u32 res0 = 0 /* ä¿ç•™ */
+ u64 kernel_entry /* 內核入å£é»ž */
+ u64 _end - _text /* å…§æ ¸é¡åƒæœ‰æ•ˆå¤§å° */
+ u64 load_offset /* 加載內核é¡åƒç›¸å°å…§å­˜èµ·å§‹åœ°å€çš„åç§»é‡ */
+ u64 res1 = 0 /* ä¿ç•™ */
+ u64 res2 = 0 /* ä¿ç•™ */
+ u64 res3 = 0 /* ä¿ç•™ */
+ u32 LINUX_PE_MAGIC /* 魔術數 */
+ u32 pe_header - _head /* 到PEé ­çš„åç§»é‡ */
+
diff --git a/Documentation/translations/zh_TW/arch/loongarch/features.rst b/Documentation/translations/zh_TW/arch/loongarch/features.rst
new file mode 100644
index 000000000000..b64e430f55ae
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/loongarch/features.rst
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/loongarch/features.rst
+:Translator: Huacai Chen <chenhuacai@loongson.cn>
+
+.. kernel-feat:: $srctree/Documentation/features loongarch
+
diff --git a/Documentation/translations/zh_TW/arch/loongarch/index.rst b/Documentation/translations/zh_TW/arch/loongarch/index.rst
new file mode 100644
index 000000000000..7281e050fe1c
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/loongarch/index.rst
@@ -0,0 +1,28 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/loongarch/index.rst
+:Translator: Huacai Chen <chenhuacai@loongson.cn>
+
+=================
+LoongArché«”ç³»çµæ§‹
+=================
+
+.. toctree::
+ :maxdepth: 2
+ :numbered:
+
+ introduction
+ booting
+ irq-chip-model
+
+ features
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
+
diff --git a/Documentation/translations/zh_TW/arch/loongarch/introduction.rst b/Documentation/translations/zh_TW/arch/loongarch/introduction.rst
new file mode 100644
index 000000000000..a5603f9b0a1b
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/loongarch/introduction.rst
@@ -0,0 +1,354 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/loongarch/introduction.rst
+:Translator: Huacai Chen <chenhuacai@loongson.cn>
+
+=============
+LoongArch介紹
+=============
+
+LoongArch是一種新的RISC ISA,在一定程度上類似於MIPS和RISC-V。LoongArch指令集
+包括一個精簡32ä½ç‰ˆï¼ˆLA32R)ã€ä¸€å€‹æ¨™æº–32ä½ç‰ˆï¼ˆLA32S)ã€ä¸€å€‹64ä½ç‰ˆï¼ˆLA64)。
+LoongArch定義了四個特權級(PLV0~PLV3),其中PLV0是最高特權級,用於內核;而PLV3
+是最低特權級,用於應用程åºã€‚本文檔介紹了LoongArch的寄存器ã€åŸºç¤ŽæŒ‡ä»¤é›†ã€è™›æ“¬å…§
+存以åŠå…¶ä»–一些主題。
+
+寄存器
+======
+
+LoongArch的寄存器包括通用寄存器(GPRsï¼‰ã€æµ®é»žå¯„存器(FPRs)ã€å‘é‡å¯„存器(VRs)
+和用於特權模å¼ï¼ˆPLV0)的控制狀態寄存器(CSRs)。
+
+通用寄存器
+----------
+
+LoongArch包括32個通用寄存器( ``$r0`` ~ ``$r31`` ),LA32中æ¯å€‹å¯„存器爲32ä½å¯¬ï¼Œ
+LA64中æ¯å€‹å¯„存器爲64ä½å¯¬ã€‚ ``$r0`` 的內容總是固定爲0ï¼Œè€Œå…¶ä»–å¯„å­˜å™¨åœ¨é«”ç³»çµæ§‹å±¤é¢
+沒有特殊功能。( ``$r1`` 算是一個例外,在BLæŒ‡ä»¤ä¸­å›ºå®šç”¨ä½œéˆæŽ¥è¿”å›žå¯„å­˜å™¨ã€‚ï¼‰
+
+內核使用了一套LoongArch寄存器約定,定義在LoongArch ELF psABIè¦ç¯„中,詳細æè¿°åƒè¦‹
+:ref:`åƒè€ƒæ–‡ç» <loongarch-references-zh_TW>`:
+
+================= =============== =================== ==========
+寄存器å 別å 用途 è·¨èª¿ç”¨ä¿æŒ
+================= =============== =================== ==========
+``$r0`` ``$zero`` 常é‡0 ä¸ä½¿ç”¨
+``$r1`` ``$ra`` è¿”å›žåœ°å€ å¦
+``$r2`` ``$tp`` TLS/ç·šç¨‹ä¿¡æ¯æŒ‡é‡ ä¸ä½¿ç”¨
+``$r3`` ``$sp`` æ£§æŒ‡é‡ æ˜¯
+``$r4``-``$r11`` ``$a0``-``$a7`` åƒæ•¸å¯„存器 å¦
+``$r4``-``$r5`` ``$v0``-``$v1`` 返回值 å¦
+``$r12``-``$r20`` ``$t0``-``$t8`` 臨時寄存器 å¦
+``$r21`` ``$u0`` æ¯CPU變é‡åŸºåœ°å€ ä¸ä½¿ç”¨
+``$r22`` ``$fp`` å¹€æŒ‡é‡ æ˜¯
+``$r23``-``$r31`` ``$s0``-``$s8`` éœæ…‹å¯„存器 是
+================= =============== =================== ==========
+
+.. note::
+ 注æ„: ``$r21`` 寄存器在ELF psABI中ä¿ç•™æœªä½¿ç”¨ï¼Œä½†æ˜¯åœ¨Linux內核用於ä¿
+ å­˜æ¯CPU變é‡åŸºåœ°å€ã€‚該寄存器沒有ABI命å,ä¸éŽåœ¨å…§æ ¸ä¸­ç¨±çˆ² ``$u0`` 。在
+ 一些éºç•™ä»£ç¢¼ä¸­æœ‰æ™‚å¯èƒ½è¦‹åˆ° ``$v0`` å’Œ ``$v1`` ,它們是 ``$a0`` å’Œ
+ ``$a1`` 的別å,屬於已經廢棄的用法。
+
+浮點寄存器
+----------
+
+當系統中存在FPU時,LoongArch有32個浮點寄存器( ``$f0`` ~ ``$f31`` )。在LA64
+çš„CPU核上,æ¯å€‹å¯„存器å‡çˆ²64ä½å¯¬ã€‚
+
+浮點寄存器的使用約定與LoongArch ELF psABIè¦ç¯„çš„æè¿°ç›¸åŒï¼š
+
+================= ================== =================== ==========
+寄存器å 別å 用途 è·¨èª¿ç”¨ä¿æŒ
+================= ================== =================== ==========
+``$f0``-``$f7`` ``$fa0``-``$fa7`` åƒæ•¸å¯„存器 å¦
+``$f0``-``$f1`` ``$fv0``-``$fv1`` 返回值 å¦
+``$f8``-``$f23`` ``$ft0``-``$ft15`` 臨時寄存器 å¦
+``$f24``-``$f31`` ``$fs0``-``$fs7`` éœæ…‹å¯„存器 是
+================= ================== =================== ==========
+
+.. note::
+ 注æ„:在一些éºç•™ä»£ç¢¼ä¸­æœ‰æ™‚å¯èƒ½è¦‹åˆ° ``$fv0`` å’Œ ``$fv1`` ,它們是
+ ``$fa0`` å’Œ ``$fa1`` 的別å,屬於已經廢棄的用法。
+
+
+å‘é‡å¯„存器
+----------
+
+LoongArchç¾æœ‰å…©ç¨®å‘釿“´å±•:
+
+- 128ä½å‘釿“´å±•LSX(全稱Loongson SIMD eXtention),
+- 256ä½å‘釿“´å±•LASX(全稱Loongson Advanced SIMD eXtention)。
+
+LSX使用 ``$v0`` ~ ``$v31`` å‘é‡å¯„存器,而LASX則使用 ``$x0`` ~ ``$x31`` 。
+
+浮點寄存器和å‘é‡å¯„存器是複用的,比如:在一個實ç¾äº†LSXå’ŒLASX的核上, ``$x0`` çš„
+低128ä½èˆ‡ ``$v0`` 共用, ``$v0`` 的低64ä½èˆ‡ ``$f0`` å…±ç”¨ï¼Œå…¶ä»–å¯„å­˜å™¨ä¾æ­¤é¡žæŽ¨ã€‚
+
+控制狀態寄存器
+--------------
+
+控制狀態寄存器åªèƒ½åœ¨ç‰¹æ¬Šæ¨¡å¼ï¼ˆPLV0)下訪å•:
+
+================= ==================================== ==========
+åœ°å€ å…¨ç¨±æè¿° 簡稱
+================= ==================================== ==========
+0x0 ç•¶å‰æ¨¡å¼ä¿¡æ¯ CRMD
+0x1 ç•°å¸¸å‰æ¨¡å¼ä¿¡æ¯ PRMD
+0x2 擴展部件使能 EUEN
+0x3 雜項控制 MISC
+0x4 異常é…ç½® ECFG
+0x5 異常狀態 ESTAT
+0x6 ç•°å¸¸è¿”å›žåœ°å€ ERA
+0x7 出錯(Faulting)è™›æ“¬åœ°å€ BADV
+0x8 出錯(Faulting)指令字 BADI
+0xC 異常入å£åœ°å€ EENTRY
+0x10 TLB索引 TLBIDX
+0x11 TLBè¡¨é …é«˜ä½ TLBEHI
+0x12 TLB表項低ä½0 TLBELO0
+0x13 TLB表項低ä½1 TLBELO1
+0x18 地å€ç©ºé–“標識符 ASID
+0x19 低åŠåœ°å€ç©ºé–“é å…¨å±€ç›®éŒ„åŸºå€ PGDL
+0x1A 高åŠåœ°å€ç©ºé–“é å…¨å±€ç›®éŒ„åŸºå€ PGDH
+0x1B é å…¨å±€ç›®éŒ„åŸºå€ PGD
+0x1C é è¡¨é歷控制低åŠéƒ¨åˆ† PWCL
+0x1D é è¡¨é歷控制高åŠéƒ¨åˆ† PWCH
+0x1E STLBé å¤§å° STLBPS
+0x1F 縮減虛地å€é…ç½® RVACFG
+0x20 CPU編號 CPUID
+0x21 特權資æºé…置信æ¯1 PRCFG1
+0x22 特權資æºé…置信æ¯2 PRCFG2
+0x23 特權資æºé…置信æ¯3 PRCFG3
+0x30+n (0≤n≤15) 數據ä¿å­˜å¯„存器 SAVEn
+0x40 定時器編號 TID
+0x41 定時器é…ç½® TCFG
+0x42 定時器值 TVAL
+0x43 計時器補償 CNTC
+0x44 定時器中斷清除 TICLR
+0x60 LLBit相關控制 LLBCTL
+0x80 實ç¾ç›¸é—œæŽ§åˆ¶1 IMPCTL1
+0x81 實ç¾ç›¸é—œæŽ§åˆ¶2 IMPCTL2
+0x88 TLBé‡å¡«ç•°å¸¸å…¥å£åœ°å€ TLBRENTRY
+0x89 TLBé‡å¡«ç•°å¸¸å‡ºéŒ¯(Faulting)è™›åœ°å€ TLBRBADV
+0x8A TLBé‡å¡«ç•°å¸¸è¿”å›žåœ°å€ TLBRERA
+0x8B TLBé‡å¡«ç•°å¸¸æ•¸æ“šä¿å­˜ TLBRSAVE
+0x8C TLBé‡å¡«ç•°å¸¸è¡¨é …低ä½0 TLBRELO0
+0x8D TLBé‡å¡«ç•°å¸¸è¡¨é …低ä½1 TLBRELO1
+0x8E TLBé‡å¡«ç•°å¸¸è¡¨é …é«˜ä½ TLBEHI
+0x8F TLBé‡å¡«ç•°å¸¸å‰æ¨¡å¼ä¿¡æ¯ TLBRPRMD
+0x90 機器錯誤控制 MERRCTL
+0x91 機器錯誤信æ¯1 MERRINFO1
+0x92 機器錯誤信æ¯2 MERRINFO2
+0x93 機器錯誤異常入å£åœ°å€ MERRENTRY
+0x94 æ©Ÿå™¨éŒ¯èª¤ç•°å¸¸è¿”å›žåœ°å€ MERRERA
+0x95 機器錯誤異常數據ä¿å­˜ MERRSAVE
+0x98 高速緩存標籤 CTAG
+0x180+n (0≤n≤3) 直接映射é…置窗å£n DMWn
+0x200+2n (0≤n≤31) 性能監測é…ç½®n PMCFGn
+0x201+2n (0≤n≤31) 性能監測計數器n PMCNTn
+0x300 內存讀寫監視點整體控制 MWPC
+0x301 內存讀寫監視點整體狀態 MWPS
+0x310+8n (0≤n≤7) 內存讀寫監視點né…ç½®1 MWPnCFG1
+0x311+8n (0≤n≤7) 內存讀寫監視點né…ç½®2 MWPnCFG2
+0x312+8n (0≤n≤7) 內存讀寫監視點né…ç½®3 MWPnCFG3
+0x313+8n (0≤n≤7) 內存讀寫監視點né…ç½®4 MWPnCFG4
+0x380 å–æŒ‡ç›£è¦–點整體控制 FWPC
+0x381 å–æŒ‡ç›£è¦–點整體狀態 FWPS
+0x390+8n (0≤n≤7) å–æŒ‡ç›£è¦–點né…ç½®1 FWPnCFG1
+0x391+8n (0≤n≤7) å–æŒ‡ç›£è¦–點né…ç½®2 FWPnCFG2
+0x392+8n (0≤n≤7) å–æŒ‡ç›£è¦–點né…ç½®3 FWPnCFG3
+0x393+8n (0≤n≤7) å–æŒ‡ç›£è¦–點né…ç½®4 FWPnCFG4
+0x500 調試寄存器 DBG
+0x501 èª¿è©¦ç•°å¸¸è¿”å›žåœ°å€ DERA
+0x502 調試數據ä¿å­˜ DSAVE
+================= ==================================== ==========
+
+ERA,TLBRERA,MERRERA和DERA有時也分別稱爲EPC,TLBREPC,MERREPC和DEPC。
+
+基礎指令集
+==========
+
+指令格å¼
+--------
+
+LoongArch的指令字長爲32ä½ï¼Œä¸€å…±æœ‰9種基本指令格å¼ï¼ˆä»¥åŠä¸€äº›è®Šé«”):
+
+=========== ==========================
+æ ¼å¼å稱 指令構æˆ
+=========== ==========================
+2R Opcode + Rj + Rd
+3R Opcode + Rk + Rj + Rd
+4R Opcode + Ra + Rk + Rj + Rd
+2RI8 Opcode + I8 + Rj + Rd
+2RI12 Opcode + I12 + Rj + Rd
+2RI14 Opcode + I14 + Rj + Rd
+2RI16 Opcode + I16 + Rj + Rd
+1RI21 Opcode + I21L + Rj + I21H
+I26 Opcode + I26L + I26H
+=========== ==========================
+
+Opcode是指令æ“作碼,Rjå’ŒRkæ˜¯æºæ“作數(寄存器),Rd是目標æ“作數(寄存器),Ra是
+4R-typeæ ¼å¼ç‰¹æœ‰çš„附加æ“作數(寄存器)。I8/I12/I14/I16/I21/I26分別是8ä½/12ä½/14ä½/
+16ä½/21ä½/26ä½çš„ç«‹å³æ•¸ã€‚其中較長的21ä½å’Œ26ä½ç«‹å³æ•¸åœ¨æŒ‡ä»¤å­—中被分割爲高ä½éƒ¨åˆ†èˆ‡ä½Žä½
+部分,所以你們在這è£çš„æ ¼å¼æè¿°ä¸­èƒ½å¤ çœ‹åˆ°I21L/I21Hå’ŒI26L/I26H這樣帶後綴的表述。
+
+指令列表
+--------
+
+爲了簡便起見,我們在此åªç¾…列一下指令å稱(助記符),需è¦è©³ç´°ä¿¡æ¯è«‹é–±è®€
+:ref:`åƒè€ƒæ–‡ç» <loongarch-references-zh_TW>` 中的文檔。
+
+1. ç®—è¡“é‹ç®—指令::
+
+ ADD.W SUB.W ADDI.W ADD.D SUB.D ADDI.D
+ SLT SLTU SLTI SLTUI
+ AND OR NOR XOR ANDN ORN ANDI ORI XORI
+ MUL.W MULH.W MULH.WU DIV.W DIV.WU MOD.W MOD.WU
+ MUL.D MULH.D MULH.DU DIV.D DIV.DU MOD.D MOD.DU
+ PCADDI PCADDU12I PCADDU18I
+ LU12I.W LU32I.D LU52I.D ADDU16I.D
+
+2. ç§»ä½é‹ç®—指令::
+
+ SLL.W SRL.W SRA.W ROTR.W SLLI.W SRLI.W SRAI.W ROTRI.W
+ SLL.D SRL.D SRA.D ROTR.D SLLI.D SRLI.D SRAI.D ROTRI.D
+
+3. ä½åŸŸæ“作指令::
+
+ EXT.W.B EXT.W.H CLO.W CLO.D SLZ.W CLZ.D CTO.W CTO.D CTZ.W CTZ.D
+ BYTEPICK.W BYTEPICK.D BSTRINS.W BSTRINS.D BSTRPICK.W BSTRPICK.D
+ REVB.2H REVB.4H REVB.2W REVB.D REVH.2W REVH.D BITREV.4B BITREV.8B BITREV.W BITREV.D
+ MASKEQZ MASKNEZ
+
+4. 分支轉移指令::
+
+ BEQ BNE BLT BGE BLTU BGEU BEQZ BNEZ B BL JIRL
+
+5. 訪存讀寫指令::
+
+ LD.B LD.BU LD.H LD.HU LD.W LD.WU LD.D ST.B ST.H ST.W ST.D
+ LDX.B LDX.BU LDX.H LDX.HU LDX.W LDX.WU LDX.D STX.B STX.H STX.W STX.D
+ LDPTR.W LDPTR.D STPTR.W STPTR.D
+ PRELD PRELDX
+
+6. åŽŸå­æ“作指令::
+
+ LL.W SC.W LL.D SC.D
+ AMSWAP.W AMSWAP.D AMADD.W AMADD.D AMAND.W AMAND.D AMOR.W AMOR.D AMXOR.W AMXOR.D
+ AMMAX.W AMMAX.D AMMIN.W AMMIN.D
+
+7. 柵障指令::
+
+ IBAR DBAR
+
+8. 特殊指令::
+
+ SYSCALL BREAK CPUCFG NOP IDLE ERTN(ERET) DBCL(DBGCALL) RDTIMEL.W RDTIMEH.W RDTIME.D
+ ASRTLE.D ASRTGT.D
+
+9. 特權指令::
+
+ CSRRD CSRWR CSRXCHG
+ IOCSRRD.B IOCSRRD.H IOCSRRD.W IOCSRRD.D IOCSRWR.B IOCSRWR.H IOCSRWR.W IOCSRWR.D
+ CACOP TLBP(TLBSRCH) TLBRD TLBWR TLBFILL TLBCLR TLBFLUSH INVTLB LDDIR LDPTE
+
+虛擬內存
+========
+
+LoongArchå¯ä»¥ä½¿ç”¨ç›´æŽ¥æ˜ å°„è™›æ“¬å…§å­˜å’Œåˆ†é æ˜ å°„虛擬內存。
+
+直接映射虛擬內存通éŽCSR.DMWn(n=0~3)來進行é…置,虛擬地å€ï¼ˆVA)和物ç†åœ°å€ï¼ˆPA)
+之間有簡單的映射關係::
+
+ VA = PA + 固定åç§»
+
+åˆ†é æ˜ å°„的虛擬地å€ï¼ˆVA)和物ç†åœ°å€ï¼ˆPA)有任æ„的映射關係,這種關係記錄在TLBå’Œé 
+表中。LoongArchçš„TLB包括一個全相è¯çš„MTLB(Multiple Page Size TLB,多樣é å¤§å°TLB)
+和一個組相è¯çš„STLB(Single Page Size TLB,單一é å¤§å°TLB)。
+
+缺çœç‹€æ…‹ä¸‹ï¼ŒLA32的整個虛擬地å€ç©ºé–“é…置如下:
+
+============ =========================== ===========================
+倿®µå 地å€ç¯„åœ å±¬æ€§
+============ =========================== ===========================
+``UVRANGE`` ``0x00000000 - 0x7FFFFFFF`` åˆ†é æ˜ å°„, å¯ç·©å­˜, PLV0~3
+``KPRANGE0`` ``0x80000000 - 0x9FFFFFFF`` 直接映射, éžç·©å­˜, PLV0
+``KPRANGE1`` ``0xA0000000 - 0xBFFFFFFF`` 直接映射, å¯ç·©å­˜, PLV0
+``KVRANGE`` ``0xC0000000 - 0xFFFFFFFF`` åˆ†é æ˜ å°„, å¯ç·©å­˜, PLV0
+============ =========================== ===========================
+
+用戶態(PLV3)åªèƒ½è¨ªå•UVRANGEï¼Œå°æ–¼ç›´æŽ¥æ˜ å°„çš„KPRANGE0å’ŒKPRANGE1,將虛擬地å€çš„第
+30~31使¸…零就等於物ç†åœ°å€ã€‚例如:物ç†åœ°å€0x00001000å°æ‡‰çš„éžç·©å­˜ç›´æŽ¥æ˜ å°„虛擬地å€
+是0x80001000,而其å¯ç·©å­˜ç›´æŽ¥æ˜ å°„è™›æ“¬åœ°å€æ˜¯0xA0001000。
+
+缺çœç‹€æ…‹ä¸‹ï¼ŒLA64的整個虛擬地å€ç©ºé–“é…置如下:
+
+============ ====================== ==================================
+倿®µå 地å€ç¯„åœ å±¬æ€§
+============ ====================== ==================================
+``XUVRANGE`` ``0x0000000000000000 - åˆ†é æ˜ å°„, å¯ç·©å­˜, PLV0~3
+ 0x3FFFFFFFFFFFFFFF``
+``XSPRANGE`` ``0x4000000000000000 - 直接映射, å¯ç·©å­˜ / éžç·©å­˜, PLV0
+ 0x7FFFFFFFFFFFFFFF``
+``XKPRANGE`` ``0x8000000000000000 - 直接映射, å¯ç·©å­˜ / éžç·©å­˜, PLV0
+ 0xBFFFFFFFFFFFFFFF``
+``XKVRANGE`` ``0xC000000000000000 - åˆ†é æ˜ å°„, å¯ç·©å­˜, PLV0
+ 0xFFFFFFFFFFFFFFFF``
+============ ====================== ==================================
+
+用戶態(PLV3)åªèƒ½è¨ªå•XUVRANGEï¼Œå°æ–¼ç›´æŽ¥æ˜ å°„çš„XSPRANGEå’ŒXKPRANGE,將虛擬地å€çš„第
+60~63使¸…零就等於物ç†åœ°å€ï¼Œè€Œå…¶ç·©å­˜å±¬æ€§æ˜¯é€šéŽè™›æ“¬åœ°å€çš„第60~61ä½é…置的(0表示強åº
+éžç·©å­˜ï¼Œ1表示一致å¯ç·©å­˜ï¼Œ2表示弱åºéžç·©å­˜ï¼‰ã€‚
+
+ç›®å‰ï¼Œæˆ‘們僅用XKPRANGE來進行直接映射,XSPRANGEä¿ç•™çµ¦ä»¥å¾Œç”¨ã€‚
+
+此處給出一個直接映射的例å­ï¼šç‰©ç†åœ°å€0x00000000_00001000的強åºéžç·©å­˜ç›´æŽ¥æ˜ å°„虛擬地å€
+(在XKPRANGE中)是0x80000000_00001000,其一致å¯ç·©å­˜ç›´æŽ¥æ˜ å°„虛擬地å€ï¼ˆåœ¨XKPRANGE中)
+是0x90000000_00001000,而其弱åºéžç·©å­˜ç›´æŽ¥æ˜ å°„虛擬地å€ï¼ˆåœ¨XKPRANGE中)是0xA0000000_
+00001000。
+
+Loongson與LoongArch的關係
+=========================
+
+LoongArch是一種RISC指令集架構(ISA),ä¸åŒæ–¼ç¾å­˜çš„任何一種ISA,而Loongson(å³é¾
+芯)是一個處ç†å™¨å®¶æ—。é¾èŠ¯åŒ…æ‹¬ä¸‰å€‹ç³»åˆ—ï¼šLoongson-1(é¾èН1號)是32ä½è™•ç†å™¨ç³»åˆ—,
+Loongson-2(é¾èН2號)是低端64ä½è™•ç†å™¨ç³»åˆ—,而Loongson-3(é¾èН3號)是高端64ä½è™•ç†
+器系列。舊的é¾èŠ¯è™•ç†å™¨åŸºæ–¼MIPS架構,而新的é¾èŠ¯è™•ç†å™¨åŸºæ–¼LoongArch架構。以é¾èН3號
+爲例:é¾èН3A1000/3B1500/3A2000/3A3000/3A4000都是兼容MIPS的,而é¾èН3A5000(以åŠå°‡
+來的型號)都是基於LoongArch的。
+
+.. _loongarch-references-zh_TW:
+
+åƒè€ƒæ–‡ç»
+========
+
+Loongson官方網站(é¾èŠ¯ä¸­ç§‘æŠ€è¡“è‚¡ä»½æœ‰é™å…¬å¸ï¼‰ï¼š
+
+ http://www.loongson.cn/
+
+Loongson與LoongArch的開發者網站(軟件與文檔資æºï¼‰ï¼š
+
+ http://www.loongnix.cn/
+
+ https://github.com/loongson/
+
+ https://loongson.github.io/LoongArch-Documentation/
+
+LoongArch指令集架構的文檔:
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-CN.pdf (中文版)
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-EN.pdf (英文版)
+
+LoongArch的ELF psABI文檔:
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.01-CN.pdf (中文版)
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.01-EN.pdf (英文版)
+
+Loongson與LoongArchçš„Linuxå…§æ ¸æºç¢¼å€‰åº«ï¼š
+
+ https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git
+
diff --git a/Documentation/translations/zh_TW/arch/loongarch/irq-chip-model.rst b/Documentation/translations/zh_TW/arch/loongarch/irq-chip-model.rst
new file mode 100644
index 000000000000..dbe9595bbf16
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/loongarch/irq-chip-model.rst
@@ -0,0 +1,158 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/loongarch/irq-chip-model.rst
+:Translator: Huacai Chen <chenhuacai@loongson.cn>
+
+==================================
+LoongArch的IRQ芯片模型(層級關係)
+==================================
+
+ç›®å‰ï¼ŒåŸºæ–¼LoongArch的處ç†å™¨ï¼ˆå¦‚é¾èН3A5000)åªèƒ½èˆ‡LS7A芯片組é…åˆå·¥ä½œã€‚LoongArch計算機
+中的中斷控制器(å³IRQ芯片)包括CPUINTC(CPU Core Interrupt Controller)ã€LIOINTC(
+Legacy I/O Interrupt Controller)ã€EIOINTC(Extended I/O Interrupt Controller)ã€
+HTVECINTC(Hyper-Transport Vector Interrupt Controller)ã€PCH-PIC(LS7A芯片組的主中
+斷控制器)ã€PCH-LPC(LS7A芯片組的LPC中斷控制器)和PCH-MSI(MSI中斷控制器)。
+
+CPUINTC是一種CPU內部的æ¯å€‹æ ¸æœ¬åœ°çš„中斷控制器,LIOINTC/EIOINTC/HTVECINTC是CPU內部的
+全局中斷控制器(æ¯å€‹èŠ¯ç‰‡ä¸€å€‹ï¼Œæ‰€æœ‰æ ¸å…±äº«ï¼‰ï¼Œè€ŒPCH-PIC/PCH-LPC/PCH-MSI是CPU外部的中
+斷控制器(在é…套芯片組è£é¢ï¼‰ã€‚這些中斷控制器(或者說IRQ芯片)以一種層次樹的組織形å¼
+ç´šè¯åœ¨ä¸€èµ·ï¼Œä¸€å…±æœ‰å…©ç¨®å±¤ç´šé—œä¿‚模型(傳統IRQ模型和擴展IRQ模型)。
+
+傳統IRQ模型
+===========
+
+在這種模型è£é¢ï¼ŒIPI(Inter-Processor Interrupt)和CPU本地時é˜ä¸­æ–·ç›´æŽ¥ç™¼é€åˆ°CPUINTC,
+CPU串å£ï¼ˆUARTs)中斷髮é€åˆ°LIOINTC,而其他所有設備的中斷則分別發é€åˆ°æ‰€é€£æŽ¥çš„PCH-PIC/
+PCH-LPC/PCH-MSI,然後被HTVECINTC統一收集,å†ç™¼é€åˆ°LIOINTC,最後到é”CPUINTC::
+
+ +-----+ +---------+ +-------+
+ | IPI | --> | CPUINTC | <-- | Timer |
+ +-----+ +---------+ +-------+
+ ^
+ |
+ +---------+ +-------+
+ | LIOINTC | <-- | UARTs |
+ +---------+ +-------+
+ ^
+ |
+ +-----------+
+ | HTVECINTC |
+ +-----------+
+ ^ ^
+ | |
+ +---------+ +---------+
+ | PCH-PIC | | PCH-MSI |
+ +---------+ +---------+
+ ^ ^ ^
+ | | |
+ +---------+ +---------+ +---------+
+ | PCH-LPC | | Devices | | Devices |
+ +---------+ +---------+ +---------+
+ ^
+ |
+ +---------+
+ | Devices |
+ +---------+
+
+擴展IRQ模型
+===========
+
+在這種模型è£é¢ï¼ŒIPI(Inter-Processor Interrupt)和CPU本地時é˜ä¸­æ–·ç›´æŽ¥ç™¼é€åˆ°CPUINTC,
+CPU串å£ï¼ˆUARTs)中斷髮é€åˆ°LIOINTC,而其他所有設備的中斷則分別發é€åˆ°æ‰€é€£æŽ¥çš„PCH-PIC/
+PCH-LPC/PCH-MSI,然後被EIOINTC統一收集,å†ç›´æŽ¥åˆ°é”CPUINTC::
+
+ +-----+ +---------+ +-------+
+ | IPI | --> | CPUINTC | <-- | Timer |
+ +-----+ +---------+ +-------+
+ ^ ^
+ | |
+ +---------+ +---------+ +-------+
+ | EIOINTC | | LIOINTC | <-- | UARTs |
+ +---------+ +---------+ +-------+
+ ^ ^
+ | |
+ +---------+ +---------+
+ | PCH-PIC | | PCH-MSI |
+ +---------+ +---------+
+ ^ ^ ^
+ | | |
+ +---------+ +---------+ +---------+
+ | PCH-LPC | | Devices | | Devices |
+ +---------+ +---------+ +---------+
+ ^
+ |
+ +---------+
+ | Devices |
+ +---------+
+
+ACPI相關的定義
+==============
+
+CPUINTC::
+
+ ACPI_MADT_TYPE_CORE_PIC;
+ struct acpi_madt_core_pic;
+ enum acpi_madt_core_pic_version;
+
+LIOINTC::
+
+ ACPI_MADT_TYPE_LIO_PIC;
+ struct acpi_madt_lio_pic;
+ enum acpi_madt_lio_pic_version;
+
+EIOINTC::
+
+ ACPI_MADT_TYPE_EIO_PIC;
+ struct acpi_madt_eio_pic;
+ enum acpi_madt_eio_pic_version;
+
+HTVECINTC::
+
+ ACPI_MADT_TYPE_HT_PIC;
+ struct acpi_madt_ht_pic;
+ enum acpi_madt_ht_pic_version;
+
+PCH-PIC::
+
+ ACPI_MADT_TYPE_BIO_PIC;
+ struct acpi_madt_bio_pic;
+ enum acpi_madt_bio_pic_version;
+
+PCH-MSI::
+
+ ACPI_MADT_TYPE_MSI_PIC;
+ struct acpi_madt_msi_pic;
+ enum acpi_madt_msi_pic_version;
+
+PCH-LPC::
+
+ ACPI_MADT_TYPE_LPC_PIC;
+ struct acpi_madt_lpc_pic;
+ enum acpi_madt_lpc_pic_version;
+
+åƒè€ƒæ–‡ç»
+========
+
+é¾èН3A5000的文檔:
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-3A5000-usermanual-1.02-CN.pdf (中文版)
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-3A5000-usermanual-1.02-EN.pdf (英文版)
+
+é¾èНLS7A芯片組的文檔:
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-7A1000-usermanual-2.00-CN.pdf (中文版)
+
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-7A1000-usermanual-2.00-EN.pdf (英文版)
+
+.. note::
+ - CPUINTC:å³ã€Šé¾èŠ¯æž¶æ§‹åƒè€ƒæ‰‹å†Šå·ä¸€ã€‹ç¬¬7.4節所æè¿°çš„CSR.ECFG/CSR.ESTAT寄存器åŠå…¶
+ 中斷控制é‚輯;
+ - LIOINTC:å³ã€Šé¾èН3A5000處ç†å™¨ä½¿ç”¨æ‰‹å†Šã€‹ç¬¬11.1節所æè¿°çš„“傳統I/O中斷â€ï¼›
+ - EIOINTC:å³ã€Šé¾èН3A5000處ç†å™¨ä½¿ç”¨æ‰‹å†Šã€‹ç¬¬11.2節所æè¿°çš„“擴展I/O中斷â€ï¼›
+ - HTVECINTC:å³ã€Šé¾èН3A5000處ç†å™¨ä½¿ç”¨æ‰‹å†Šã€‹ç¬¬14.3節所æè¿°çš„“HyperTransport中斷â€ï¼›
+ - PCH-PIC/PCH-MSI:å³ã€Šé¾èН7A1000橋片用戶手冊》第5章所æè¿°çš„“中斷控制器â€ï¼›
+ - PCH-LPC:å³ã€Šé¾èН7A1000橋片用戶手冊》第24.3節所æè¿°çš„“LPC中斷â€ã€‚
+
diff --git a/Documentation/translations/zh_TW/arch/mips/booting.rst b/Documentation/translations/zh_TW/arch/mips/booting.rst
new file mode 100644
index 000000000000..7e104abf5a51
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/mips/booting.rst
@@ -0,0 +1,35 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/mips/booting.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+.. _tw_booting:
+
+BMIPS設備樹引導
+------------------------
+
+ 一些bootloadersåªæ”¯æŒåœ¨å…§æ ¸é¡åƒé–‹å§‹åœ°å€è™•的單一入å£é»žã€‚而其它
+ bootloaders將跳轉到ELF的開始地å€è™•。兩種方案都支æŒçš„;因爲
+ CONFIG_BOOT_RAW=y and CONFIG_NO_EXCEPT_FILL=y, æ‰€ä»¥ç¬¬ä¸€æ¢æŒ‡ä»¤
+ 會立å³è·³è½‰åˆ°kernel_entry()å…¥å£è™•執行。
+
+ 與arch/arm情æ³(b)類似,dt感知的引導加載程åºéœ€è¦è¨­ç½®ä»¥ä¸‹å¯„存器:
+
+ a0 : 0
+
+ a1 : 0xffffffff
+
+ a2 : RAM中指å‘è¨­å‚™æ¨¹å¡Šçš„ç‰©ç†æŒ‡é‡(在chapterII中定義)。
+ 設備樹å¯ä»¥ä½æ–¼å‰512MB物ç†åœ°å€ç©ºé–“(0x00000000 -
+ 0x1fffffff)的任何ä½ç½®ï¼Œä»¥64ä½é‚Šç•Œå°é½Šã€‚
+
+ 傳統bootloaders䏿œƒä½¿ç”¨é€™æ¨£çš„約定,並且它們ä¸å‚³å…¥DT塊。
+ 在這種情æ³ä¸‹ï¼ŒLinux將通éŽé¸ä¸­CONFIG_DT_*查找DTB。
+
+ 以上約定åªåœ¨32ä½ç³»çµ±ä¸­å®šç¾©ï¼Œå› çˆ²ç›®å‰æ²’有任何64ä½çš„BMIPS實ç¾ã€‚
+
diff --git a/Documentation/translations/zh_TW/arch/mips/features.rst b/Documentation/translations/zh_TW/arch/mips/features.rst
new file mode 100644
index 000000000000..f69410420035
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/mips/features.rst
@@ -0,0 +1,14 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/mips/features.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+.. _tw_features:
+
+.. kernel-feat:: $srctree/Documentation/features mips
+
diff --git a/Documentation/translations/zh_TW/arch/mips/index.rst b/Documentation/translations/zh_TW/arch/mips/index.rst
new file mode 100644
index 000000000000..4b7d28806489
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/mips/index.rst
@@ -0,0 +1,30 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/mips/index.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+===========================
+MIPS特性文檔
+===========================
+
+.. toctree::
+ :maxdepth: 2
+ :numbered:
+
+ booting
+ ingenic-tcu
+
+ features
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
+
diff --git a/Documentation/translations/zh_TW/arch/mips/ingenic-tcu.rst b/Documentation/translations/zh_TW/arch/mips/ingenic-tcu.rst
new file mode 100644
index 000000000000..4385c0f3e9cd
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/mips/ingenic-tcu.rst
@@ -0,0 +1,73 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/mips/ingenic-tcu.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+.. _tw_ingenic-tcu:
+
+===============================================
+囿­£ JZ47xx SoC定時器/計數器硬件單元
+===============================================
+
+囿­£ JZ47xx SoC中的定時器/計數器單元(TCU)是一個多功能硬件塊。它有多é”
+8個通é“,å¯ä»¥ç”¨ä½œè¨ˆæ•¸å™¨ï¼Œè¨ˆæ™‚器,或脈è¡å¯¬åº¦èª¿è£½å™¨ã€‚
+
+- JZ4725B, JZ4750, JZ4755 åªæœ‰ï¼–個TCU通é“。其它SoC都有8個通é“。
+
+- JZ4725B引入了一個ç¨ç«‹çš„通é“,稱爲æ“作系統計時器(OST)。這是一個32ä½å¯
+ 編程定時器。在JZ4760BåŠä»¥ä¸Šåž‹è™Ÿä¸Šï¼Œå®ƒæ˜¯64ä½çš„。
+
+- æ¯å€‹TCU通é“éƒ½æœ‰è‡ªå·±çš„æ™‚é˜æºï¼Œå¯ä»¥é€šéŽ TCSR 寄存器設置通é“的父級時é˜
+ æºï¼ˆpclkã€extã€rtc)ã€é–‹é—œä»¥åŠåˆ†é »ã€‚
+
+ - 看門狗和OST硬件模塊在它們的寄存器空間中也有相åŒå½¢å¼çš„TCSR寄存器。
+ - 用於關閉/é–‹å•“çš„ TCU 寄存器也å¯ä»¥é—œé–‰/開啓看門狗和 OST 時é˜ã€‚
+
+- æ¯å€‹TCU通é“在兩種模å¼çš„其中一種模å¼ä¸‹é‹è¡Œï¼š
+
+ - æ¨¡å¼ TCU1:通é“無法在ç¡çœ æ¨¡å¼ä¸‹é‹è¡Œï¼Œä½†æ›´æ˜“æ–¼æ“作。
+ - æ¨¡å¼ TCU2:通é“å¯ä»¥åœ¨ç¡çœ æ¨¡å¼ä¸‹é‹è¡Œï¼Œä½†æ“作比 TCU1 通é“複雜一些。
+
+- æ¯å€‹ TCU 通é“的模å¼å–決於使用的SoC:
+
+ - 在最è€çš„SoC(高於JZ4740),八個通é“都é‹è¡Œåœ¨TCU1模å¼ã€‚
+ - 在 JZ4725B,通é“5é‹è¡Œåœ¨TCU2,其它通é“則é‹è¡Œåœ¨TCU1。
+ - 在最新的SoC(JZ4750åŠä¹‹å¾Œï¼‰ï¼Œé€šé“1-2é‹è¡Œåœ¨TCU2,其它通é“則é‹è¡Œ
+ 在TCU1。
+
+- æ¯å€‹é€šé“都å¯ä»¥ç”Ÿæˆä¸­æ–·ã€‚有些通é“共享一æ¢ä¸­æ–·ç·šï¼Œè€Œæœ‰äº›æ²’有,其在SoCåž‹
+ 號之間的變更:
+
+ - 在很è€çš„SoC(JZ4740åŠæ›´ä½Žï¼‰ï¼Œé€šé“0和通é“1有它們自己的中斷線;通
+ é“2-7共享最後一æ¢ä¸­æ–·ç·šã€‚
+ - 在 JZ4725B,通é“0有它自己的中斷線;通é“1-5共享一æ¢ä¸­æ–·ç·šï¼›OST
+ 使用最後一æ¢ä¸­æ–·ç·šã€‚
+ - 在比較新的SoC(JZ4750åŠä»¥å¾Œï¼‰ï¼Œé€šé“5有它自己的中斷線;通
+ é“0-4和(如果是8通é“)6-7全部共享一æ¢ä¸­æ–·ç·šï¼›OST使用最後一æ¢ä¸­
+ 斷線。
+
+實ç¾
+====
+
+TCU硬件的功能分佈在多個驅動程åºï¼š
+
+============== ===================================
+æ™‚é˜ drivers/clk/ingenic/tcu.c
+中斷 drivers/irqchip/irq-ingenic-tcu.c
+定時器 drivers/clocksource/ingenic-timer.c
+OST drivers/clocksource/ingenic-ost.c
+脈è¡å¯¬åº¦èª¿è£½å™¨ drivers/pwm/pwm-jz4740.c
+看門狗 drivers/watchdog/jz4740_wdt.c
+============== ===================================
+
+因爲å¯ä»¥å¾žç›¸åŒçš„寄存器控制屬於ä¸åŒé©…動程åºå’Œæ¡†æž¶çš„TCUçš„å„種功能,所以
+所有這些驅動程åºéƒ½é€šéŽç›¸åŒçš„æŽ§åˆ¶ç¸½ç·šé€šç”¨æŽ¥å£è¨ªå•它們的寄存器。
+
+有關TCU驅動程åºçš„設備樹ç¶å®šçš„æ›´å¤šä¿¡æ¯ï¼Œè«‹åƒé–±:
+Documentation/devicetree/bindings/timer/ingenic,tcu.yaml.
+
diff --git a/Documentation/translations/zh_TW/arch/openrisc/index.rst b/Documentation/translations/zh_TW/arch/openrisc/index.rst
new file mode 100644
index 000000000000..7585960783fc
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/openrisc/index.rst
@@ -0,0 +1,33 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/openrisc/index.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+.. _tw_openrisc_index:
+
+=================
+OpenRISC 體系架構
+=================
+
+.. toctree::
+ :maxdepth: 2
+
+ openrisc_port
+ todo
+
+Todolist:
+ features
+
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
+
diff --git a/Documentation/translations/zh_TW/arch/openrisc/openrisc_port.rst b/Documentation/translations/zh_TW/arch/openrisc/openrisc_port.rst
new file mode 100644
index 000000000000..422fe9f7a3f2
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/openrisc/openrisc_port.rst
@@ -0,0 +1,128 @@
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/openrisc/openrisc_port.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+.. _tw_openrisc_port:
+
+==============
+OpenRISC Linux
+==============
+
+這是Linuxå°OpenRISC類微處ç†å™¨çš„ç§»æ¤ï¼›å…·é«”來說,最早移æ¤ç›®æ¨™æ˜¯32ä½
+OpenRISC 1000系列(或1k)。
+
+關於OpenRISC處ç†å™¨å’Œæ­£åœ¨é€²è¡Œä¸­çš„開發的信æ¯:
+
+ ======= =============================
+ 網站 https://openrisc.io
+ 郵箱 openrisc@lists.librecores.org
+ ======= =============================
+
+---------------------------------------------------------------------
+
+OpenRISC工具éˆå’ŒLinux的構建指å—
+===============================
+
+爲了構建和é‹è¡ŒLinux for OpenRISC,你至少需è¦ä¸€å€‹åŸºæœ¬çš„工具éˆï¼Œæˆ–許
+é‚„éœ€è¦æž¶æ§‹æ¨¡æ“¬å™¨ã€‚ é€™è£æ¦‚述了準備就ä½é€™äº›éƒ¨åˆ†çš„æ­¥é©Ÿã€‚
+
+1) 工具éˆ
+
+工具éˆäºŒé€²åˆ¶æ–‡ä»¶å¯ä»¥å¾žopenrisc.io或我們的github發佈é é¢ç²å¾—。ä¸åŒ
+工具éˆçš„æ§‹å»ºæŒ‡å—å¯ä»¥åœ¨openrisc.io或Staffordçš„å·¥å…·éˆæ§‹å»ºå’Œç™¼ä½ˆè…³æœ¬
+中找到。
+
+ ====== =================================================
+ 二進制 https://github.com/openrisc/or1k-gcc/releases
+ å·¥å…·éˆ https://openrisc.io/software
+ 構建 https://github.com/stffrdhrn/or1k-toolchain-build
+ ====== =================================================
+
+2) 構建
+
+åƒå¾€å¸¸ä¸€æ¨£æ§‹å»ºLinuxå…§æ ¸::
+
+ make ARCH=openrisc CROSS_COMPILE="or1k-linux-" defconfig
+ make ARCH=openrisc CROSS_COMPILE="or1k-linux-"
+
+3) 在FPGA上é‹è¡Œï¼ˆå¯é¸)
+
+OpenRISC社å€é€šå¸¸ä½¿ç”¨FuseSoCä¾†ç®¡ç†æ§‹å»ºå’Œç·¨ç¨‹SoC到FPGA中。 䏋颿˜¯ç”¨
+OpenRISC SoCå°De0 Nano開發æ¿é€²è¡Œç·¨ç¨‹çš„一個例å­ã€‚ 在構建éŽç¨‹ä¸­ï¼Œ
+FPGA RTL是從FuseSoC IP核庫中下載的代碼,並使用FPGA供應商工具構建。
+二進制文件用openocd加載到電路æ¿ä¸Šã€‚
+
+::
+
+ git clone https://github.com/olofk/fusesoc
+ cd fusesoc
+ sudo pip install -e .
+
+ fusesoc init
+ fusesoc build de0_nano
+ fusesoc pgm de0_nano
+
+ openocd -f interface/altera-usb-blaster.cfg \
+ -f board/or1k_generic.cfg
+
+ telnet localhost 4444
+ > init
+ > halt; load_image vmlinux ; reset
+
+4) 在模擬器上é‹è¡Œï¼ˆå¯é¸ï¼‰
+
+QEMU是一個處ç†å™¨ä»¿çœŸå™¨ï¼Œæˆ‘們推薦它來模擬OpenRISC平臺。 請按照QEMUç¶²
+站上的OpenRISC說明,讓Linux在QEMU上é‹è¡Œã€‚ ä½ å¯ä»¥è‡ªå·±æ§‹å»ºQEMU,但你的
+Linux發行版å¯èƒ½æä¾›äº†æ”¯æŒOpenRISC的二進制包。
+
+ ============= ======================================================
+ qemu openrisc https://wiki.qemu.org/Documentation/Platforms/OpenRISC
+ ============= ======================================================
+
+---------------------------------------------------------------------
+
+術語表
+======
+
+代碼中使用了以下符號約定以將範åœé™åˆ¶åœ¨å¹¾å€‹ç‰¹å®šè™•ç†å™¨å¯¦ç¾ä¸Šï¼š
+
+========= =======================
+openrisc: OpenRISC類型處ç†å™¨
+or1k: OpenRISC 1000系列處ç†å™¨
+or1200: OpenRISC 1200處ç†å™¨
+========= =======================
+
+---------------------------------------------------------------------
+
+æ­·å²
+====
+
+2003-11-18 Matjaz Breskvar (phoenix@bsemi.com)
+ å°‡linuxåˆæ­¥ç§»æ¤åˆ°OpenRISC或32架構。
+ 所有的核心功能都實ç¾äº†ï¼Œä¸¦ä¸”å¯ä»¥ä½¿ç”¨ã€‚
+
+2003-12-08 Matjaz Breskvar (phoenix@bsemi.com)
+ 徹底改變TLB失誤處ç†ã€‚
+ é‡å¯«ç•°å¸¸è™•ç†ã€‚
+ 在默èªçš„initrd中實ç¾äº†sash-3.6的所有功能。
+ 大幅改進的版本。
+
+2004-04-10 Matjaz Breskvar (phoenix@bsemi.com)
+ 大é‡çš„bug修復。
+ 支æŒä»¥å¤ªç¶²ï¼Œhttpå’Œtelnetæœå‹™å™¨åŠŸèƒ½ã€‚
+ å¯ä»¥é‹è¡Œè¨±å¤šæ¨™æº–çš„linux應用程åºã€‚
+
+2004-06-26 Matjaz Breskvar (phoenix@bsemi.com)
+ ç§»æ¤åˆ°2.6.x。
+
+2004-11-30 Matjaz Breskvar (phoenix@bsemi.com)
+ 大é‡çš„bug修復和增強功能。
+ 增加了opencores framebuffer驅動。
+
+2010-10-09 Jonas Bonn (jonas@southpole.se)
+ é‡å¤§é‡å¯«ï¼Œä½¿å…¶èˆ‡ä¸Šæ¸¸çš„Linux 2.6.36看齊。
+
diff --git a/Documentation/translations/zh_TW/arch/openrisc/todo.rst b/Documentation/translations/zh_TW/arch/openrisc/todo.rst
new file mode 100644
index 000000000000..df261b9e3002
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/openrisc/todo.rst
@@ -0,0 +1,24 @@
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/openrisc/todo.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+.. _tw_openrisc_todo.rst:
+
+========
+待辦事項
+========
+
+OpenRISC Linux的移æ¤å·²ç¶“完全投入使用,並且從 2.6.35 é–‹å§‹å°±ä¸€ç›´åœ¨ä¸Šæ¸¸åŒæ­¥ã€‚
+然而,還有一些剩餘的項目需è¦åœ¨æœªä¾†å¹¾å€‹æœˆå…§å®Œæˆã€‚ 䏋颿˜¯ä¸€å€‹å³å°‡é€²è¡Œèª¿æŸ¥çš„已知
+ä¸ç›¡å®Œç¾Žçš„é …ç›®åˆ—è¡¨ï¼Œå³æˆ‘們的待辦事項列表。
+
+- 實ç¾å…¶é¤˜çš„DMA API……dma_map_sg等。
+
+- 完æˆé‡å‘½å清ç†å·¥ä½œâ€¦â€¦ä»£ç¢¼ä¸­æåˆ°äº†or32,這是架構的一個è€å字。 我們
+ 已經確定的å字是or1k,這個改變正在以緩慢ç©ç´¯çš„æ–¹å¼é€²è¡Œã€‚ ç›®å‰ï¼Œor32相當
+ 於or1k。
+
diff --git a/Documentation/translations/zh_TW/arch/parisc/debugging.rst b/Documentation/translations/zh_TW/arch/parisc/debugging.rst
new file mode 100644
index 000000000000..c9ee804aebbd
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/parisc/debugging.rst
@@ -0,0 +1,46 @@
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/parisc/debugging.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+.. _tw_parisc_debugging:
+
+=================
+調試PA-RISC
+=================
+
+好å§ï¼Œé€™è£æœ‰ä¸€äº›é—œæ–¼èª¿è©¦linux/parisc的較底層部分的信æ¯ã€‚
+
+
+1. 絕å°åœ°å€
+=====================
+
+很多彙編代碼目å‰é‹è¡Œåœ¨å¯¦æ¨¡å¼ä¸‹ï¼Œé€™æ„å‘³ç€æœƒä½¿ç”¨çµ•å°åœ°å€ï¼Œè€Œä¸æ˜¯åƒå…§æ ¸å…¶ä»–
+部分那樣使用虛擬地å€ã€‚è¦å°‡çµ•å°åœ°å€è½‰æ›çˆ²è™›æ“¬åœ°å€ï¼Œä½ å¯ä»¥åœ¨System.map中查
+找,添加__PAGE_OFFSETï¼ˆç›®å‰æ˜¯0x10000000)。
+
+
+2. HPMCs
+========
+
+當實模å¼çš„代碼試圖訪å•ä¸å­˜åœ¨çš„內存時,會出ç¾HPMC(high priority machine
+checkï¼‰è€Œä¸æ˜¯å…§æ ¸oops。若è¦èª¿è©¦HPMC,請嘗試找到系統響應程åº/請求程åºåœ°å€ã€‚
+系統請求程åºåœ°å€æ‡‰è©²èˆ‡ï¼ˆæŸï¼‰è™•ç†å™¨çš„HPA(I/O範åœå…§çš„高地å€ï¼‰ç›¸åŒ¹é…;系統響應程
+åºåœ°å€æ˜¯å¯¦æ¨¡å¼ä»£ç¢¼è©¦åœ–訪å•的地å€ã€‚
+
+系統響應程åºåœ°å€çš„典型值是大於__PAGE_OFFSET (0x10000000)的地å€ï¼Œé€™æ„味ç€
+在實模å¼è©¦åœ–訪å•它之å‰ï¼Œè™›æ“¬åœ°å€æ²’有被翻譯æˆç‰©ç†åœ°å€ã€‚
+
+
+3. 有趣的Qä½
+============
+
+æŸäº›éžå¸¸é—œéµçš„代碼必須清除PSW中的Qä½ã€‚ç•¶Qä½è¢«æ¸…除時,CPU䏿œƒæ›´æ–°ä¸­æ–·è™•ç†
+ç¨‹åºæ‰€è®€å–的寄存器,以找出機器被中斷的ä½ç½®â€”—所以如果你在清除Qä½çš„æŒ‡ä»¤å’Œå†
+次設置Qä½çš„RFI之間é‡åˆ°ä¸­æ–·ï¼Œä½ ä¸çŸ¥é“它到底發生在哪è£ã€‚如果你幸é‹çš„話,IAOQ
+æœƒæŒ‡å‘æ¸…除Qä½çš„æŒ‡ä»¤ï¼Œå¦‚果你ä¸å¹¸é‹çš„話,它會指å‘任何地方。通常Qä½çš„å•題會
+表ç¾çˆ²ç„¡æ³•解釋的系統掛起或物ç†å…§å­˜è¶Šç•Œã€‚
+
diff --git a/Documentation/translations/zh_TW/arch/parisc/index.rst b/Documentation/translations/zh_TW/arch/parisc/index.rst
new file mode 100644
index 000000000000..35941bf68c88
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/parisc/index.rst
@@ -0,0 +1,32 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/parisc/index.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+.. _tw_parisc_index:
+
+====================
+PA-RISC體系架構
+====================
+
+.. toctree::
+ :maxdepth: 2
+
+ debugging
+ registers
+
+Todolist:
+
+ features
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
+
diff --git a/Documentation/translations/zh_TW/arch/parisc/registers.rst b/Documentation/translations/zh_TW/arch/parisc/registers.rst
new file mode 100644
index 000000000000..695acb21134a
--- /dev/null
+++ b/Documentation/translations/zh_TW/arch/parisc/registers.rst
@@ -0,0 +1,157 @@
+.. include:: ../../disclaimer-zh_TW.rst
+
+:Original: Documentation/arch/parisc/registers.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+.. _tw_parisc_registers:
+
+=========================
+Linux/PA-RISC的寄存器用法
+=========================
+
+[ 用星號表示目å‰å°šæœªå¯¦ç¾çš„計劃用途。 ]
+
+ABI約定的通用寄存器
+===================
+
+控制寄存器
+----------
+
+============================ =================================
+CR 0 (æ¢å¾©è¨ˆæ•¸å™¨) 用於ptrace
+CR 1-CR 7(無定義) 未使用
+CR 8 (Protection ID) æ¯é€²ç¨‹å€¼*
+CR 9, 12, 13 (PIDS) 未使用
+CR10 (CCR) FPUå»¶é²ä¿å­˜*
+CR11 按照ABIçš„è¦å®šï¼ˆSAR)
+CR14 (中斷å‘é‡) åˆå§‹åŒ–爲 fault_vector
+CR15 (EIEM) 所有ä½åˆå§‹åŒ–爲1*
+CR16 (間隔計時器) 讀å–週期數/寫入開始時間間隔計時器
+CR17-CR22 ä¸­æ–·åƒæ•¸
+CR19 中斷指令寄存器
+CR20 中斷空間寄存器
+CR21 中斷åç§»é‡å¯„存器
+CR22 中斷 PSW
+CR23 (EIRR) è®€å–æœªæ±ºä¸­æ–·/寫入清除ä½
+CR24 (TR 0) 內核空間é ç›®éŒ„指é‡
+CR25 (TR 1) 用戶空間é ç›®éŒ„指é‡
+CR26 (TR 2) ä¸ä½¿ç”¨
+CR27 (TR 3) 線程æè¿°ç¬¦æŒ‡é‡
+CR28 (TR 4) ä¸ä½¿ç”¨
+CR29 (TR 5) ä¸ä½¿ç”¨
+CR30 (TR 6) ç•¶å‰ / 0
+CR31 (TR 7) 臨時寄存器,在ä¸åŒåœ°æ–¹ä½¿ç”¨
+============================ =================================
+
+空間寄存器(內核模å¼ï¼‰
+----------------------
+
+======== ==============================
+SR0 臨時空間寄存器
+SR4-SR7 設置爲0
+SR1 臨時空間寄存器
+SR2 å…§æ ¸ä¸æ‡‰è©²ç ´å£žå®ƒ
+SR3 用於用戶空間訪å•(當å‰é€²ç¨‹ï¼‰
+======== ==============================
+
+空間寄存器(用戶模å¼ï¼‰
+----------------------
+
+======== ============================
+SR0 臨時空間寄存器
+SR1 臨時空間寄存器
+SR2 ä¿å­˜Linux gateway page的空間
+SR3 在內核中ä¿å­˜ç”¨æˆ¶åœ°å€ç©ºé–“的值
+SR4-SR7 定義了用戶/內核的短地å€ç©ºé–“
+======== ============================
+
+
+處ç†å™¨ç‹€æ…‹å­—
+------------
+
+====================== ================================================
+W (64ä½åœ°å€ï¼‰ 0
+E (å°å°¾ç«¯ï¼‰ 0
+S (安全間隔計時器) 0
+T (產生分支陷阱) 0
+H (高特權級陷阱) 0
+L (低特權級陷阱) 0
+N ï¼ˆæ’¤éŠ·ä¸‹ä¸€æ¢æŒ‡ä»¤ï¼‰ 被C代碼使用
+X (數據存儲中斷ç¦ç”¨ï¼‰ 0
+B (產生分支) 被C代碼使用
+C (代碼地å€è½‰è­¯ï¼‰ 1, 在執行實模å¼ä»£ç¢¼æ™‚爲0
+V (除法步長校正) 被C代碼使用
+M (HPMC 掩碼) 0, 在執行HPMCæ“作*時爲1
+C/B (進/借 ä½ï¼‰ 被C代碼使用
+O (有åºå¼•用) 1*
+F (性能監視器) 0
+R (回收計數器陷阱) 0
+Q (收集中斷狀態) 1 (在rfi之å‰çš„代碼中爲0)
+P (ä¿è­·æ¨™è­˜ç¬¦ï¼‰ 1*
+D (數據地å€è½‰è­¯ï¼‰ 1, 在執行實模å¼ä»£ç¢¼æ™‚爲0
+I (外部中斷掩碼) ç”±cli()/sti()å®ä½¿ç”¨ã€‚
+====================== ================================================
+
+“隱形â€å¯„存器(影å­å¯„存器)
+---------------------------
+
+============= ===================
+PSW W 默èªå€¼ 0
+PSW E 默èªå€¼ 0
+å½±å­å¯„存器 被中斷處ç†ä»£ç¢¼ä½¿ç”¨
+TOCå•“ç”¨ä½ 1
+============= ===================
+
+----------------------------------------------------------
+
+PA-RISC架構定義了7個寄存器作爲“影å­å¯„存器â€ã€‚這些寄存器在
+RETURN FROM INTERRUPTION AND RESTOREæŒ‡ä»¤ä¸­ä½¿ç”¨ï¼Œé€šéŽæ¶ˆ
+除中斷處ç†ç¨‹åºä¸­å°ä¸€èˆ¬å¯„存器(GR)的ä¿å­˜å’Œæ¢å¾©çš„需è¦ä¾†æ¸›
+少狀態ä¿å­˜å’Œæ¢å¾©æ™‚間。影å­å¯„存器是GRs 1, 8, 9, 16, 17,
+24和25。
+
+-------------------------------------------------------------------------
+
+寄存器使用說明,最åˆç”±John Marvinæä¾›ï¼Œä¸¦ç”±Randolph Chungæä¾›ä¸€äº›è£œå……說明。
+
+å°æ–¼é€šç”¨å¯„存器:
+
+r1,r2,r19-r26,r28,r29 & r31å¯ä»¥åœ¨ä¸ä¿å­˜å®ƒå€‘的情æ³ä¸‹è¢«ä½¿ç”¨ã€‚當然,如果你
+關心它們,在調用å¦ä¸€å€‹ç¨‹åºä¹‹å‰ï¼Œä½ ä¹Ÿéœ€è¦ä¿å­˜å®ƒå€‘。上é¢çš„一些寄存器確實
+有特殊的å«ç¾©ï¼Œä½ æ‡‰è©²æ³¨æ„一下:
+
+ r1:
+ addil指令是硬性è¦å®šå°‡å…¶çµæžœæ”¾åœ¨r1ä¸­ï¼Œæ‰€ä»¥å¦‚æžœä½ ä½¿ç”¨é€™æ¢æŒ‡ä»¤è¦
+ 注æ„這點。
+
+ r2:
+ 這就是返回指é‡ã€‚ä¸€èˆ¬ä¾†èªªï¼Œä½ ä¸æƒ³ä½¿ç”¨å®ƒï¼Œå› çˆ²ä½ éœ€è¦é€™å€‹æŒ‡é‡ä¾†è¿”
+ 回給你的調用者。然而,它與這組寄存器組åˆåœ¨ä¸€èµ·ï¼Œå› çˆ²èª¿ç”¨è€…ä¸èƒ½
+ ä¾è³´ä½ è¿”回時的值是相åŒçš„,也就是說,你å¯ä»¥å°‡r2複製到å¦ä¸€å€‹å¯„å­˜
+ 器,並在作廢r2後通éŽè©²å¯„å­˜å™¨è¿”å›žï¼Œé€™æ‡‰è©²ä¸æœƒçµ¦èª¿ç”¨ç¨‹åºå¸¶ä¾†å•題。
+
+ r19-r22:
+ 這些通常被èªçˆ²æ˜¯è‡¨æ™‚寄存器。
+ 請注æ„,在64ä½ä¸­å®ƒå€‘是arg7-arg4。
+
+ r23-r26:
+ 這些是arg3-arg0,也就是說,如果你ä¸å†é—œå¿ƒå‚³å…¥çš„值,你å¯ä»¥ä½¿ç”¨
+ 它們。
+
+ r28,r29:
+ 這倆是ret0和ret1。它們是你傳入返回值的地方。r28是主返回值。當返回
+ å°çµæ§‹é«”時,r29也å¯ä»¥ç”¨ä¾†å°‡æ•¸æ“šå‚³å›žçµ¦èª¿ç”¨ç¨‹åºã€‚
+
+ r30:
+ 棧指é‡
+
+ r31:
+ bleæŒ‡ä»¤å°‡è¿”å›žæŒ‡é‡æ”¾åœ¨é€™è£ã€‚
+
+
+ r3-r18,r27,r30需è¦è¢«ä¿å­˜å’Œæ¢å¾©ã€‚r3-r18åªæ˜¯ä¸€èˆ¬ç”¨é€”的寄存器。
+ r27是數據指é‡ï¼Œç”¨ä¾†ä½¿å°å…¨å±€è®Šé‡çš„引用更容易。r30是棧指é‡ã€‚
+
diff --git a/Documentation/translations/zh_TW/cpu-freq/core.rst b/Documentation/translations/zh_TW/cpu-freq/core.rst
index f1951e1b23bb..4f98d1e9f34b 100644
--- a/Documentation/translations/zh_TW/cpu-freq/core.rst
+++ b/Documentation/translations/zh_TW/cpu-freq/core.rst
@@ -1,13 +1,15 @@
.. SPDX-License-Identifier: GPL-2.0
-
.. include:: ../disclaimer-zh_TW.rst
-:Original: :doc:`../../../cpu-freq/core`
-:Translator: Yanteng Si <siyanteng@loongson.cn>
- Hu Haowen <src.res.211@gmail.com>
+:Original: Documentation/cpu-freq/core.rst
+
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
-.. _tw_core.rst:
+:æ ¡è­¯:
+ å”è—舟 Tang Yizhou <tangyeechou@gmail.com>
====================================
CPUFreq核心和CPUFreq通知器的通用說明
@@ -29,10 +31,10 @@ CPUFreq核心和CPUFreq通知器的通用說明
======================
cpufreqæ ¸å¿ƒä»£ç¢¼ä½æ–¼drivers/cpufreq/cpufreq.c中。這些cpufreq代碼爲CPUFreq架構的驅
-動程åºï¼ˆé‚£äº›æ“作硬體切æ›é »çŽ‡çš„ä»£ç¢¼ï¼‰ä»¥åŠ "通知器 "æä¾›äº†ä¸€å€‹æ¨™æº–化的接å£ã€‚
-é€™äº›æ˜¯è¨­å‚™é©…å‹•ç¨‹åºæˆ–需è¦äº†è§£ç­–略變化的其它內核部分(如 ACPI 熱é‡ç®¡ç†ï¼‰æˆ–所有頻率更改(除
-計時代碼外),甚至需è¦å¼·åˆ¶ç¢ºå®šé€Ÿåº¦é™åˆ¶çš„通知器(如 ARM 架構上的 LCD 驅動程åºï¼‰ã€‚
-此外, 內核 "常數" loops_per_jiffy會根據頻率變化而更新。
+動程åºï¼ˆé‚£äº›åŸ·è¡Œç¡¬ä»¶é »çŽ‡åˆ‡æ›çš„ä»£ç¢¼ï¼‰ä»¥åŠ "通知器" æä¾›äº†ä¸€å€‹æ¨™æº–化的接å£ã€‚
+包括設備驅動程åºï¼›éœ€è¦äº†è§£ç­–略變化(如 ACPI 熱é‡ç®¡ç†ï¼‰ï¼Œæˆ–所有頻率變化(如計時代碼),
+甚至需è¦å¼·åˆ¶é™åˆ¶çˆ²æŒ‡å®šé »çŽ‡ï¼ˆå¦‚ ARM 架構上的 LCD 驅動程åºï¼‰çš„其它內核組件。
+此外,內核 "常數" loops_per_jiffy 會根據頻率變化而更新。
cpufreq策略的引用計數由 cpufreq_cpu_get å’Œ cpufreq_cpu_put 來完æˆï¼Œä»¥ç¢ºä¿ cpufreq é©…
動程åºè¢«æ­£ç¢ºåœ°è¨»å†Šåˆ°æ ¸å¿ƒä¸­ï¼Œä¸¦ä¸”驅動程åºåœ¨ cpufreq_put_cpu 被調用之å‰ä¸æœƒè¢«å¸è¼‰ã€‚這也ä¿è­‰
@@ -41,10 +43,10 @@ cpufreq策略的引用計數由 cpufreq_cpu_get å’Œ cpufreq_cpu_put 來完æˆï¼Œ
2. CPUFreq 通知器
====================
-CPUFreqé€šçŸ¥å™¨ç¬¦åˆæ¨™æº–的內核通知器接å£ã€‚
+CPUFreq通知器éµå¾ªæ¨™æº–的內核通知器接å£ã€‚
關於通知器的細節請åƒé–± linux/include/linux/notifier.h。
-這裡有兩個ä¸åŒçš„CPUfreq通知器 - 策略通知器和轉æ›é€šçŸ¥å™¨ã€‚
+é€™è£æœ‰å…©å€‹ä¸åŒçš„CPUfreq通知器 - 策略通知器和轉æ›é€šçŸ¥å™¨ã€‚
2.1 CPUFreq策略通知器
@@ -62,27 +64,27 @@ CPUFreqé€šçŸ¥å™¨ç¬¦åˆæ¨™æº–的內核通知器接å£ã€‚
2.2 CPUFreq轉æ›é€šçŸ¥å™¨
--------------------------------
-ç•¶CPUfreq驅動切æ›CPU核心頻率時,策略中的æ¯å€‹åœ¨ç·šCPU都會收到兩次通知,這些變化沒有任何外部干
+ç•¶CPUfreq驅動切æ›CPU核心頻率時,策略中的æ¯å€‹åœ¨ç·šCPU都會收到兩次通知,這些變化沒有任何外部幹
é ã€‚
ç¬¬äºŒå€‹åƒæ•¸æŒ‡å®šéšŽæ®µ - CPUFREQ_PRECHANGE or CPUFREQ_POSTCHANGE.
ç¬¬ä¸‰å€‹åƒæ•¸æ˜¯ä¸€å€‹åŒ…å«å¦‚ä¸‹å€¼çš„çµæ§‹é«”cpufreq_freqs:
-===== ====================
-cpu å—影響cpu的編號
+====== ===============================
+policy 指å‘struct cpufreq_policy的指é‡
old 舊頻率
new 新頻率
flags cpufreq驅動的標誌
-===== ====================
+====== ===============================
3. 嫿œ‰Operating Performance Point (OPP)çš„CPUFreq表的生æˆ
==================================================================
關於OPP的細節請åƒé–± Documentation/power/opp.rst
dev_pm_opp_init_cpufreq_table -
- 這個功能æä¾›äº†ä¸€å€‹éš¨æ™‚å¯ç”¨çš„轉æ›ç¨‹åºï¼Œç”¨ä¾†å°‡OPP層關於å¯ç”¨é »çŽ‡çš„å…§éƒ¨ä¿¡æ¯ç¿»è­¯æˆä¸€ç¨®å®¹æ˜“æä¾›çµ¦
- cpufreq的格å¼ã€‚
+ 這個函數æä¾›äº†ä¸€å€‹éš¨æ™‚å¯ç”¨çš„轉æ›ä¾‹ç¨‹ï¼Œç”¨ä¾†å°‡OPP層關於å¯ç”¨é »çŽ‡çš„å…§éƒ¨ä¿¡æ¯ç¿»è­¯æˆä¸€ç¨®
+ cpufreq易於處ç†çš„æ ¼å¼ã€‚
.. Warning::
@@ -101,7 +103,7 @@ dev_pm_opp_init_cpufreq_table -
.. note::
- è©²å‡½æ•¸åªæœ‰åœ¨CONFIG_PM_OPP之外還啓用了CONFIG_CPU_FREQ時æ‰å¯ç”¨ã€‚
+ è©²å‡½æ•¸åªæœ‰åœ¨CONFIG_PM_OPP之外還啓用了CONFIG_CPU_FREQ時纔å¯ç”¨ã€‚
dev_pm_opp_free_cpufreq_table
釋放dev_pm_opp_init_cpufreq_table分é…的表。
diff --git a/Documentation/translations/zh_TW/cpu-freq/cpu-drivers.rst b/Documentation/translations/zh_TW/cpu-freq/cpu-drivers.rst
index 671b1bf0e2c5..add3de2d4523 100644
--- a/Documentation/translations/zh_TW/cpu-freq/cpu-drivers.rst
+++ b/Documentation/translations/zh_TW/cpu-freq/cpu-drivers.rst
@@ -2,12 +2,15 @@
.. include:: ../disclaimer-zh_TW.rst
-:Original: :doc:`../../../cpu-freq/cpu-drivers`
-:Translator: Yanteng Si <siyanteng@loongson.cn>
- Hu Haowen <src.res.211@gmail.com>
+:Original: Documentation/cpu-freq/cpu-drivers.rst
-.. _tw_cpu-drivers.rst:
+:翻譯:
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+:æ ¡è­¯:
+
+ å”è—舟 Tang Yizhou <tangyeechou@gmail.com>
=======================================
如何實ç¾ä¸€å€‹æ–°çš„CPUFreq處ç†å™¨é©…動程åºï¼Ÿ
@@ -37,15 +40,15 @@
1. 怎麼åšï¼Ÿ
===========
-如此,你剛剛得到了一個全新的CPU/晶片組åŠå…¶æ•¸æ“šæ‰‹å†Šï¼Œä¸¦å¸Œæœ›çˆ²é€™å€‹CPU/晶片組添加cpufreq
-支æŒï¼Ÿå¾ˆå¥½ï¼Œé€™è£¡æœ‰ä¸€äº›è‡³é—œé‡è¦çš„æç¤ºï¼š
+如果,你剛剛得到了一個全新的CPU/芯片組åŠå…¶æ•¸æ“šæ‰‹å†Šï¼Œä¸¦å¸Œæœ›çˆ²é€™å€‹CPU/芯片組添加cpufreq
+支æŒï¼Ÿå¾ˆå¥½ï¼Œé€™è£æœ‰ä¸€äº›è‡³é—œé‡è¦çš„æç¤ºï¼š
1.1 åˆå§‹åŒ–
----------
-首先,在__initcall_level_7 (module_init())或更é å¾Œçš„函數中檢查這個內核是å¦
-é‹è¡Œåœ¨æ­£ç¢ºçš„CPU和正確的晶片組上。如果是,則使用cpufreq_register_driver()å‘
+首先,在 __initcall level 7 (module_init())或更é å¾Œçš„函數中檢查這個內核是å¦
+é‹è¡Œåœ¨æ­£ç¢ºçš„CPU和正確的芯片組上。如果是,則使用cpufreq_register_driver()å‘
CPUfreq核心層註冊一個cpufreq_driverçµæ§‹é«”。
çµæ§‹é«”cpufreq_driver應該包å«ä»€éº¼æˆå“¡?
@@ -59,11 +62,11 @@ CPUfreq核心層註冊一個cpufreq_driverçµæ§‹é«”。
.setpolicy 或 .fast_switch 或 .target 或 .target_index - 差異見
下文。
-並且å¯é¸æ“‡
+其它å¯é¸æˆå“¡
- .flags - cpufreq核的æç¤ºã€‚
+ .flags - 給cpufreq核心的æç¤ºã€‚
- .driver_data - cpufreq驅動程åºçš„特定數據。
+ .driver_data - cpufreq驅動程åºçš„特有數據。
.get_intermediate å’Œ target_intermediate - 用於在改變CPU頻率時切æ›åˆ°ç©©å®š
的頻率。
@@ -72,18 +75,18 @@ CPUfreq核心層註冊一個cpufreq_driverçµæ§‹é«”。
.bios_limit - 返回HW/BIOSå°CPU的最大頻率é™åˆ¶å€¼ã€‚
- .exit - 一個指å‘per-policy清ç†å‡½æ•¸çš„æŒ‡é‡ï¼Œè©²å‡½æ•¸åœ¨cpuç†±æ’æ‹”éŽç¨‹çš„CPU_POST_DEAD
+ .exit - 一個指å‘per-policy清ç†å‡½æ•¸çš„æŒ‡é‡ï¼Œè©²å‡½æ•¸åœ¨CPUç†±æ’æ‹”éŽç¨‹çš„CPU_POST_DEAD
階段被調用。
.suspend - 一個指å‘per-policyæš«åœå‡½æ•¸çš„æŒ‡é‡ï¼Œè©²å‡½æ•¸åœ¨é—œä¸­æ–·ä¸”åœ¨è©²ç­–ç•¥çš„èª¿ç¯€å™¨åœæ­¢
後被調用。
- .resume - 一個指å‘per-policyæ¢å¾©å‡½æ•¸çš„æŒ‡é‡ï¼Œè©²å‡½æ•¸åœ¨é—œä¸­æ–·ä¸”在調節器å†ä¸€æ¬¡é–‹å§‹å‰è¢«
+ .resume - 一個指å‘per-policyæ¢å¾©å‡½æ•¸çš„æŒ‡é‡ï¼Œè©²å‡½æ•¸åœ¨é—œä¸­æ–·ä¸”在調節器å†ä¸€æ¬¡å•“å‹•å‰è¢«
調用。
.ready - 一個指å‘per-policy準備函數的指é‡ï¼Œè©²å‡½æ•¸åœ¨ç­–略完全åˆå§‹åŒ–之後被調用。
- .attr - 一個指å‘NULLçµå°¾çš„"struct freq_attr"列表的指é‡ï¼Œè©²å‡½æ•¸å…許導出值到
+ .attr - 一個指å‘NULLçµå°¾çš„"struct freq_attr"列表的指é‡ï¼Œè©²åˆ—表å…許導出值到
sysfs。
.boost_enabled - 如果設置,則啓用æå‡(boost)頻率。
@@ -94,95 +97,93 @@ CPUfreq核心層註冊一個cpufreq_driverçµæ§‹é«”。
1.2 Per-CPU åˆå§‹åŒ–
------------------
-æ¯ç•¶ä¸€å€‹æ–°çš„CPU被註冊到設備模型中,或者在cpufreq驅動註冊自己之後,如果此CPUçš„cpufreqç­–
-ç•¥ä¸å­˜åœ¨ï¼Œå‰‡æœƒèª¿ç”¨per-policyçš„åˆå§‹åŒ–函數cpufreq_driver.init。請注æ„,.init()å’Œ.exit()程åº
-åªå°ç­–ç•¥èª¿ç”¨ä¸€æ¬¡ï¼Œè€Œä¸æ˜¯å°ç­–略管ç†çš„æ¯å€‹CPU調用一次。它需è¦ä¸€å€‹ ``struct cpufreq_policy
+æ¯ç•¶ä¸€å€‹æ–°çš„CPU被註冊到設備模型中,或者當cpufreq驅動註冊自身之後,如果此CPUçš„cpufreqç­–
+ç•¥ä¸å­˜åœ¨ï¼Œå‰‡æœƒèª¿ç”¨per-policyçš„åˆå§‹åŒ–函數cpufreq_driver.init。請注æ„,.init()å’Œ.exit()例程
+åªçˆ²æŸå€‹ç­–ç•¥èª¿ç”¨ä¸€æ¬¡ï¼Œè€Œä¸æ˜¯å°è©²ç­–略管ç†çš„æ¯å€‹CPU調用一次。它需è¦ä¸€å€‹ ``struct cpufreq_policy
*policy`` ä½œçˆ²åƒæ•¸ã€‚ç¾åœ¨è©²æ€Žéº¼åšå‘¢ï¼Ÿ
如果有必è¦ï¼Œè«‹åœ¨ä½ çš„CPU上激活CPUfreq功能支æŒã€‚
-然後,驅動程åºå¿…須填寫以下數值:
+然後,驅動程åºå¿…須填寫以下值:
+-----------------------------------+--------------------------------------+
-|policy->cpuinfo.min_freq 和 | |
-|policy->cpuinfo.max_freq | 該CPU支æŒçš„æœ€ä½Žå’Œæœ€é«˜é »çŽ‡ï¼ˆkHz) |
-| | |
-| | |
+|policy->cpuinfo.min_freqå’Œ | 該CPU支æŒçš„æœ€ä½Žå’Œæœ€é«˜é »çŽ‡ï¼ˆkHz) |
+|policy->cpuinfo.max_freq | |
+| | |
+-----------------------------------+--------------------------------------+
-|policy->cpuinfo.transition_latency | |
-| | CPUåœ¨å…©å€‹é »çŽ‡ä¹‹é–“åˆ‡æ›æ‰€éœ€çš„æ™‚間,以 |
-| | ç´ç§’爲單ä½ï¼ˆå¦‚é©ç”¨ï¼Œå¦å‰‡æŒ‡å®š |
-| | CPUFREQ_ETERNAL) |
+|policy->cpuinfo.transition_latency | CPUåœ¨å…©å€‹é »çŽ‡ä¹‹é–“åˆ‡æ›æ‰€éœ€çš„æ™‚間,以 |
+| | ç´ç§’爲單ä½ï¼ˆå¦‚ä¸é©ç”¨ï¼Œè¨­å®šçˆ² |
+| | CPUFREQ_ETERNAL) |
+| | |
+-----------------------------------+--------------------------------------+
-|policy->cur | 該CPUç•¶å‰çš„工作頻率(如é©ç”¨) |
-| | |
+|policy->cur | 該CPUç•¶å‰çš„工作頻率(如é©ç”¨) |
+| | |
+-----------------------------------+--------------------------------------+
-|policy->min, | |
-|policy->max, | |
-|policy->policy and, if necessary, | |
-|policy->governor | 必須包å«è©²cpuçš„ 「默èªç­–ç•¥ã€ã€‚ç¨å¾Œ |
-| | 會用這些值調用 |
-| | cpufreq_driver.verify and either |
-| | cpufreq_driver.setpolicy or |
-| | cpufreq_driver.target/target_index |
-| | |
+|policy->min, | 必須包å«è©²CPUçš„"默èªç­–ç•¥"。ç¨å¾Œ |
+|policy->max, | 會用這些值調用 |
+|policy->policy and, if necessary, | cpufreq_driver.verify和下é¢å‡½æ•¸ |
+|policy->governor | 之一:cpufreq_driver.setpolicy或 |
+| | cpufreq_driver.target/target_index |
+| | |
+-----------------------------------+--------------------------------------+
-|policy->cpus | 用與這個CPU一起åšDVFSçš„(在線+離線) |
-| | CPU(å³èˆ‡å®ƒå…±äº«æ™‚é˜/電壓軌)的掩碼更新 |
-| | 這個 |
-| | |
+|policy->cpus | 該policy通éŽDVFS框架影響的全部CPU |
+| | (å³èˆ‡æœ¬CPU共享"時é˜/電壓"å°)æ§‹æˆ |
+| | 掩碼(åŒæ™‚包å«åœ¨ç·šå’Œé›¢ç·šCPU),用掩碼 |
+| | 更新本字段 |
+| | |
+-----------------------------------+--------------------------------------+
-å°æ–¼è¨­ç½®å…¶ä¸­çš„一些值(cpuinfo.min[max]_freq, policy->min[max]),頻率表助手å¯èƒ½æœƒæœ‰å¹«
+å°æ–¼è¨­ç½®å…¶ä¸­çš„一些值(cpuinfo.min[max]_freq, policy->min[max]),頻率表輔助函數å¯èƒ½æœƒæœ‰å¹«
助。關於它們的更多信æ¯ï¼Œè«‹åƒè¦‹ç¬¬2節。
1.3 é©—è­‰
--------
-當用戶決定設置一個新的策略(ç”± 「policy,governor,min,max組æˆã€)時,必須å°é€™å€‹ç­–略進行驗證,
+當用戶決定設置一個新的策略(ç”±"policy,governor,min,max組æˆ")時,必須å°é€™å€‹ç­–略進行驗證,
以便糾正ä¸å…¼å®¹çš„值。爲了驗證這些值,cpufreq_verify_within_limits(``struct cpufreq_policy
*policy``, ``unsigned int min_freq``, ``unsigned int max_freq``)函數å¯èƒ½æœƒæœ‰å¹«åŠ©ã€‚
-關於頻率表助手的詳細內容請åƒè¦‹ç¬¬2節。
+關於頻率表輔助函數的詳細內容請åƒè¦‹ç¬¬2節。
您需è¦ç¢ºä¿è‡³å°‘有一個有效頻率(或工作範åœï¼‰åœ¨ policy->min å’Œ policy->max 範åœå…§ã€‚如果有必
-è¦ï¼Œå…ˆå¢žåŠ policy->maxï¼Œåªæœ‰åœ¨æ²’有辦法的情æ³ä¸‹ï¼Œæ‰æ¸›å°‘policy->min。
+è¦ï¼Œå…ˆå¢žå¤§policy->maxï¼Œåªæœ‰åœ¨æ²’有解決方案的情æ³ä¸‹ï¼Œæ‰æ¸›å°policy->min。
1.4 target 或 target_index 或 setpolicy 或 fast_switch?
-------------------------------------------------------
-大多數cpufreq驅動甚至大多數cpu頻率å‡é™ç®—法åªå…許將CPU頻率設置爲é å®šç¾©çš„å›ºå®šå€¼ã€‚å°æ–¼é€™äº›ï¼Œä½ 
+大多數cpufreq驅動甚至大多數CPU頻率å‡é™ç®—法åªå…許將CPU頻率設置爲é å®šç¾©çš„å›ºå®šå€¼ã€‚å°æ–¼é€™äº›ï¼Œä½ 
å¯ä»¥ä½¿ç”¨->target(),->target_index()或->fast_switch()回調。
-有些cpufreq功能的處ç†å™¨å¯ä»¥è‡ªå·±åœ¨æŸäº›é™åˆ¶ä¹‹é–“切æ›é »çŽ‡ã€‚é€™äº›æ‡‰ä½¿ç”¨->setpolicy()回調。
+有些具有硬件調頻能力的處ç†å™¨å¯ä»¥è‡ªè¡Œä¾æ“šæŸäº›é™åˆ¶ä¾†åˆ‡æ›CPU頻率。它們應使用->setpolicy()回調。
1.5. target/target_index
------------------------
-target_indexèª¿ç”¨æœ‰å…©å€‹åƒæ•¸ï¼š``struct cpufreq_policy * policy``å’Œ``unsigned int``
-索引(於列出的頻率表)。
+target_indexèª¿ç”¨æœ‰å…©å€‹åƒæ•¸ï¼š ``struct cpufreq_policy * policy`` å’Œ ``unsigned int``
+索引(用於索引頻率表項)。
-當調用這裡時,CPUfreq驅動必須設置新的頻率。實際頻率必須由freq_table[index].frequency決定。
+ç•¶èª¿ç”¨é€™è£æ™‚,CPUfreq驅動必須設置新的頻率。實際頻率必須由freq_table[index].frequency決定。
-它應該總是在錯誤的情æ³ä¸‹æ¢å¾©åˆ°ä¹‹å‰çš„頻率(å³policy->restore_freq),å³ä½¿æˆ‘們之å‰åˆ‡æ›åˆ°ä¸­é–“頻率。
+在發生錯誤的情æ³ä¸‹ç¸½æ˜¯æ‡‰è©²æ¢å¾©åˆ°ä¹‹å‰çš„頻率(å³policy->restore_freq),å³ä½¿æˆ‘們已經切æ›åˆ°äº†
+中間頻率。
已棄用
----------
-ç›®æ¨™èª¿ç”¨æœ‰ä¸‰å€‹åƒæ•¸ã€‚``struct cpufreq_policy * policy``, unsigned int target_frequency,
+targetèª¿ç”¨æœ‰ä¸‰å€‹åƒæ•¸ã€‚``struct cpufreq_policy * policy``, unsigned int target_frequency,
unsigned int relation.
-CPUfreq驅動在調用這裡時必須設置新的頻率。實際的頻率必須使用以下è¦å‰‡ä¾†ç¢ºå®šã€‚
+CPUfreqé©…å‹•åœ¨èª¿ç”¨é€™è£æ™‚必須設置新的頻率。實際的頻率必須使用以下è¦å‰‡ä¾†ç¢ºå®šã€‚
-- 緊跟 "目標頻率"。
+- 儘é‡è²¼è¿‘"目標頻率"。
- policy->min <= new_freq <= policy->max (這必須是有效的!!!)
- 如果 relation==CPUFREQ_REL_Lï¼Œå˜—è©¦é¸æ“‡ä¸€å€‹é«˜æ–¼æˆ–等於 target_freq çš„ new_freq。("L代表
最低,但ä¸èƒ½ä½Žæ–¼")
- 如果 relation==CPUFREQ_REL_Hï¼Œå˜—è©¦é¸æ“‡ä¸€å€‹ä½Žæ–¼æˆ–等於 target_freq çš„ new_freq。("H代表
最高,但ä¸èƒ½é«˜æ–¼")
-這裡,頻率表助手å¯èƒ½æœƒå¹«åЩ你--詳見第2節。
+這è£ï¼Œé »çŽ‡è¡¨è¼”åŠ©å‡½æ•¸å¯èƒ½æœƒå¹«åЩ你 -- 詳見第2節。
1.6. fast_switch
----------------
@@ -196,51 +197,52 @@ CPUfreq驅動在調用這裡時必須設置新的頻率。實際的頻率必須ä
1.7 setpolicy
-------------
-setpolicy調用åªéœ€è¦ä¸€å€‹``struct cpufreq_policy * policy``ä½œçˆ²åƒæ•¸ã€‚需è¦å°‡è™•ç†å™¨å…§æˆ–晶片組內動態頻
+setpolicy調用åªéœ€è¦ä¸€å€‹ ``struct cpufreq_policy * policy`` ä½œçˆ²åƒæ•¸ã€‚需è¦å°‡è™•ç†å™¨å…§æˆ–芯片組內動態頻
率切æ›çš„下é™è¨­ç½®çˆ²policy->min,上é™è¨­ç½®çˆ²policy->max,如果支æŒçš„話,當policy->policy爲
-CPUFREQ_POLICY_PERFORMANCEæ™‚é¸æ“‡é¢å‘性能的設置,當CPUFREQ_POLICY_POWERSAVEæ™‚é¸æ“‡é¢å‘çœé›»çš„設置。
+CPUFREQ_POLICY_PERFORMANCEæ™‚é¸æ“‡é¢å‘性能的設置,爲CPUFREQ_POLICY_POWERSAVEæ™‚é¸æ“‡é¢å‘çœé›»çš„設置。
也å¯ä»¥æŸ¥çœ‹drivers/cpufreq/longrun.c中的åƒè€ƒå¯¦ç¾ã€‚
1.8 get_intermediate 和 target_intermediate
--------------------------------------------
-僅é©ç”¨æ–¼ target_index() å’Œ CPUFREQ_ASYNC_NOTIFICATION 未設置的驅動。
+僅é©ç”¨æ–¼æœªè¨­ç½® target_index() å’Œ CPUFREQ_ASYNC_NOTIFICATION 的驅動。
-get_intermediateæ‡‰è©²è¿”å›žä¸€å€‹å¹³å°æƒ³è¦åˆ‡æ›åˆ°çš„穩定的中間頻率,target_intermediate()應該將CPU設置爲
-該頻率,然後å†è·³è½‰åˆ°'index'å°æ‡‰çš„頻率。核心會負責發é€é€šçŸ¥ï¼Œé©…å‹•ä¸å¿…在target_intermediate()或
-target_index()中處ç†ã€‚
+get_intermediate應該返回一個平臺想è¦åˆ‡æ›åˆ°çš„穩定的中間頻率,target_intermediate()應該將CPU設置爲
+該頻率,然後å†è·³è½‰åˆ°'index'å°æ‡‰çš„頻率。cpufreq核心會負責發é€é€šçŸ¥ï¼Œé©…å‹•ä¸å¿…在
+target_intermediate()或target_index()中處ç†å®ƒå€‘。
-在驅動程åºä¸æƒ³å› çˆ²æŸå€‹ç›®æ¨™é »çŽ‡åˆ‡æ›åˆ°ä¸­é–“頻率的情æ³ä¸‹ï¼Œå®ƒå€‘å¯ä»¥å¾žget_intermediate()中返回'0'。在這種情æ³
-下,核心將直接調用->target_index()。
+在驅動程åºä¸æƒ³çˆ²æŸå€‹ç›®æ¨™é »çŽ‡åˆ‡æ›åˆ°ä¸­é–“頻率的情æ³ä¸‹ï¼Œå®ƒå€‘å¯ä»¥è®“get_intermediate()返回'0'。
+在這種情æ³ä¸‹ï¼Œcpufreq核心將直接調用->target_index()。
-注æ„:->target_index()應該在失敗的情æ³ä¸‹æ¢å¾©åˆ°policy->restore_freq,因爲core會爲此發é€é€šçŸ¥ã€‚
+注æ„:->target_index()應該在發生失敗的情æ³ä¸‹å°‡é »çއæ¢å¾©åˆ°policy->restore_freq,
+因爲cpufreq核心會爲此發é€é€šçŸ¥ã€‚
-2. 頻率表助手
-=============
+2. 頻率表輔助函數
+=================
-由於大多數cpufreq處ç†å™¨åªå…許被設置爲幾個特定的頻率,因此,一個帶有一些函數的 「頻率表ã€å¯èƒ½æœƒè¼”助處ç†å™¨é©…å‹•
-程åºçš„一些工作。這樣的 "頻率表" 由一個cpufreq_frequency_tableæ¢ç›®æ§‹æˆçš„æ•¸çµ„組æˆï¼Œ"driver_data" 中包
-å«äº†é©…動程åºçš„具體數值,"frequency" 中包å«äº†ç›¸æ‡‰çš„é »çŽ‡ï¼Œä¸¦è¨­ç½®äº†æ¨™èªŒã€‚åœ¨è¡¨çš„æœ€å¾Œï¼Œéœ€è¦æ·»åР䏀個
-cpufreq_frequency_tableæ¢ç›®ï¼Œé »çŽ‡è¨­ç½®çˆ²CPUFREQ_TABLE_END。而如果想跳éŽè¡¨ä¸­çš„一個æ¢ç›®ï¼Œå‰‡å°‡é »çŽ‡è¨­ç½®çˆ²
-CPUFREQ_ENTRY_INVALID。這些æ¢ç›®ä¸éœ€è¦æŒ‰ç…§ä»»ä½•ç‰¹å®šçš„é †åºæŽ’åºï¼Œä½†å¦‚果它們是cpufreq 核心會å°å®ƒå€‘進行快速的DVFS,
+由於大多數支æŒcpufreq的處ç†å™¨åªå…許被設置爲幾個特定的頻率,因此,"頻率表"和一些相關函數å¯èƒ½æœƒè¼”助處ç†å™¨é©…å‹•
+程åºçš„一些工作。這樣的"頻率表"是一個由struct cpufreq_frequency_tableçš„æ¢ç›®æ§‹æˆçš„æ•¸çµ„,"driver_data"æˆå“¡åŒ…
+å«é©…動程åºçš„專用值,"frequency"æˆå“¡åŒ…å«äº†ç›¸æ‡‰çš„頻率,此外還有標誌æˆå“¡ã€‚åœ¨è¡¨çš„æœ€å¾Œï¼Œéœ€è¦æ·»åР䏀個
+cpufreq_frequency_tableæ¢ç›®ï¼Œé »çŽ‡è¨­ç½®çˆ²CPUFREQ_TABLE_END。如果想跳éŽè¡¨ä¸­çš„一個æ¢ç›®ï¼Œå‰‡å°‡é »çŽ‡è¨­ç½®çˆ²
+CPUFREQ_ENTRY_INVALID。這些æ¢ç›®ä¸éœ€è¦æŒ‰ç…§ä»»ä½•ç‰¹å®šçš„é †åºæŽ’åºï¼Œå¦‚果排åºäº†ï¼Œcpufreq核心執行DVFS會更快一點,
因爲æœç´¢æœ€ä½³åŒ¹é…會更快。
-如果策略在其policy->freq_table欄ä½ä¸­åŒ…å«ä¸€å€‹æœ‰æ•ˆçš„æŒ‡é‡ï¼Œcpufreq表就會被核心自動驗證。
+如果在policy->freq_table字段中包å«ä¸€å€‹æœ‰æ•ˆçš„頻率表指é‡ï¼Œé »çŽ‡è¡¨å°±æœƒè¢«cpufreq核心自動驗證。
cpufreq_frequency_table_verify()ä¿è­‰è‡³å°‘有一個有效的頻率在policy->minå’Œpolicy->max範åœå…§ï¼Œä¸¦ä¸”所有其他
-標準都被滿足。這å°->verify調用很有幫助。
+準則都被滿足。這å°->verify調用很有幫助。
-cpufreq_frequency_table_target()æ˜¯å°æ‡‰æ–¼->target階段的頻率表助手。åªè¦æŠŠæ•¸å€¼å‚³éžçµ¦é€™å€‹å‡½æ•¸ï¼Œé€™å€‹å‡½æ•¸å°±æœƒè¿”
+cpufreq_frequency_table_target()æ˜¯å°æ‡‰æ–¼->target階段的頻率表輔助函數。åªè¦æŠŠå€¼å‚³éžçµ¦é€™å€‹å‡½æ•¸ï¼Œé€™å€‹å‡½æ•¸å°±æœƒè¿”
回包å«CPUè¦è¨­ç½®çš„頻率的頻率表æ¢ç›®ã€‚
-以下å®å¯ä»¥ä½œçˆ²cpufreq_frequency_table的疊代器。
+以下å®å¯ä»¥ä½œçˆ²cpufreq_frequency_table的迭代器。
cpufreq_for_each_entry(pos, table) - éæ­·é »çŽ‡è¡¨çš„æ‰€æœ‰æ¢ç›®ã€‚
cpufreq_for_each_valid_entry(pos, table) - è©²å‡½æ•¸éæ­·æ‰€æœ‰æ¢ç›®ï¼Œä¸åŒ…括CPUFREQ_ENTRY_INVALID頻率。
-ä½¿ç”¨åƒæ•¸ "pos"-一個``cpufreq_frequency_table * `` 作爲循環變é‡ï¼Œä½¿ç”¨åƒæ•¸ "table"-作爲你想疊代
-的``cpufreq_frequency_table * `` 。
+ä½¿ç”¨åƒæ•¸"pos" -- 一個 ``cpufreq_frequency_table *`` 作爲循環指é‡ï¼Œä½¿ç”¨åƒæ•¸"table" -- 作爲你想迭代
+的 ``cpufreq_frequency_table *`` 。
例如::
@@ -251,6 +253,6 @@ cpufreq_for_each_valid_entry(pos, table) - è©²å‡½æ•¸éæ­·æ‰€æœ‰æ¢ç›®ï¼Œä¸åŒ…æ
pos->frequency = ...
}
-如果你需è¦åœ¨driver_freq_table中處ç†posçš„ä½ç½®ï¼Œä¸è¦æ¸›åŽ»æŒ‡é‡ï¼Œå› çˆ²å®ƒçš„代價相當高。相å,使用å®
+如果你需è¦åœ¨driver_freq_table中處ç†posçš„ä½ç½®ï¼Œä¸è¦åšæŒ‡é‡æ¸›æ³•,因爲它的代價相當高。作爲替代,使用å®
cpufreq_for_each_entry_idx() 和 cpufreq_for_each_valid_entry_idx() 。
diff --git a/Documentation/translations/zh_TW/cpu-freq/cpufreq-stats.rst b/Documentation/translations/zh_TW/cpu-freq/cpufreq-stats.rst
index 49088becd5fa..01ec8c837fe9 100644
--- a/Documentation/translations/zh_TW/cpu-freq/cpufreq-stats.rst
+++ b/Documentation/translations/zh_TW/cpu-freq/cpufreq-stats.rst
@@ -2,18 +2,21 @@
.. include:: ../disclaimer-zh_TW.rst
-:Original: :doc:`../../../cpu-freq/cpufreq-stats`
-:Translator: Yanteng Si <siyanteng@loongson.cn>
- Hu Haowen <src.res.211@gmail.com>
+:Original: Documentation/cpu-freq/cpufreq-stats.rst
-.. _tw_cpufreq-stats.rst:
+:翻譯:
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+
+:æ ¡è­¯:
+
+ å”è—舟 Tang Yizhou <tangyeechou@gmail.com>
==========================================
sysfs CPUFreq Stats的一般說明
==========================================
-用戶信æ¯
+爲使用者準備的信æ¯
作者: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
@@ -28,17 +31,16 @@ sysfs CPUFreq Stats的一般說明
1. 簡介
===============
-cpufreq-stats是一個爲æ¯å€‹CPUæä¾›CPU頻率統計的驅動。
-這些統計數據在/sysfs中以一堆åªè®€æŽ¥å£çš„å½¢å¼æä¾›ã€‚é€™å€‹æŽ¥å£ï¼ˆåœ¨é…置好後)將出ç¾åœ¨
-/sysfs(<sysfs root>/devices/system/cpu/cpuX/cpufreq/stats/)中cpufreq下的一個單
-ç¨çš„目錄中,æä¾›çµ¦æ¯å€‹CPU。
-å„種統計數據將在此目錄下形æˆåªè®€æ–‡ä»¶ã€‚
+cpufreq-stats是一種爲æ¯å€‹CPUæä¾›CPU頻率統計的驅動。
+這些統計數據以/sysfs中一系列åªè®€æŽ¥å£çš„å½¢å¼å‘ˆç¾ã€‚cpufreq-stats接å£ï¼ˆè‹¥å·²é…置)將爲æ¯å€‹CPU生æˆ
+/sysfs(<sysfs root>/devices/system/cpu/cpuX/cpufreq/stats/)中cpufreq目錄下的stats目錄。
+å„項統計數據將在stats目錄下形æˆå°æ‡‰çš„åªè®€æ–‡ä»¶ã€‚
-此驅動是ç¨ç«‹æ–¼ä»»ä½•å¯èƒ½é‹è¡Œåœ¨ä½ æ‰€ç”¨CPU上的特定cpufreq_driver而設計的。因此,它將與所有
-cpufreq_driver一起工作。
+此驅動是以ç¨ç«‹æ–¼ä»»ä½•å¯èƒ½é‹è¡Œåœ¨ä½ æ‰€ç”¨CPU上的特定cpufreq_driver的方å¼è¨­è¨ˆçš„。因此,它將能和任何
+cpufreq_driverå”åŒå·¥ä½œã€‚
-2. æä¾›çš„統計數據(舉例說明)
+2. å·²æä¾›çš„統計數據(有例å­)
=====================================
cpufreq statsæä¾›äº†ä»¥ä¸‹çµ±è¨ˆæ•¸æ“šï¼ˆåœ¨ä¸‹é¢è©³ç´°è§£é‡‹ï¼‰ã€‚
@@ -47,8 +49,8 @@ cpufreq statsæä¾›äº†ä»¥ä¸‹çµ±è¨ˆæ•¸æ“šï¼ˆåœ¨ä¸‹é¢è©³ç´°è§£é‡‹ï¼‰ã€‚
- total_trans
- trans_table
-所有的統計數據將從統計驅動被載入的時間(或統計被é‡ç½®çš„æ™‚間)開始,到æŸä¸€çµ±è¨ˆæ•¸æ“šè¢«è®€å–的時間爲止。
-é¡¯ç„¶ï¼Œçµ±è¨ˆé©…å‹•ä¸æœƒæœ‰ä»»ä½•關於統計驅動載入之å‰çš„頻率轉æ›ä¿¡æ¯ã€‚
+所有統計數據來自以下時間範åœï¼šå¾žçµ±è¨ˆé©…動被加載的時間(或統計數據被é‡ç½®çš„æ™‚間)開始,到æŸä¸€çµ±è¨ˆæ•¸æ“šè¢«è®€å–的時間爲止。
+é¡¯ç„¶ï¼Œçµ±è¨ˆé©…å‹•ä¸æœƒä¿å­˜å®ƒè¢«åŠ è¼‰ä¹‹å‰çš„任何頻率轉æ›ä¿¡æ¯ã€‚
::
@@ -63,14 +65,14 @@ cpufreq statsæä¾›äº†ä»¥ä¸‹çµ±è¨ˆæ•¸æ“šï¼ˆåœ¨ä¸‹é¢è©³ç´°è§£é‡‹ï¼‰ã€‚
- **reset**
-åªå¯«å±¬æ€§ï¼Œå¯ç”¨æ–¼é‡ç½®çµ±è¨ˆè¨ˆæ•¸å™¨ã€‚這尿–¼è©•ä¼°ä¸åŒèª¿ç¯€å™¨ä¸‹çš„系統行爲éžå¸¸æœ‰ç”¨ï¼Œä¸”無需é‡å•“。
+åªå¯«å±¬æ€§ï¼Œå¯ç”¨æ–¼é‡ç½®çµ±è¨ˆè¨ˆæ•¸å™¨ã€‚這尿–¼è©•ä¼°ä¸åŒèª¿ç¯€å™¨çš„系統行爲éžå¸¸æœ‰ç”¨ï¼Œä¸”無需é‡å•“。
- **time_in_state**
-此項給出了這個CPU所支æŒçš„æ¯å€‹é »çŽ‡æ‰€èŠ±è²»çš„æ™‚é–“ã€‚cat輸出的æ¯ä¸€è¡Œéƒ½æœƒæœ‰"<frequency>
-<time>"å°ï¼Œè¡¨ç¤ºé€™å€‹CPU在<frequency>上花費了<time>個usertimeå–®ä½çš„æ™‚間。這裡的
-usertime單使˜¯10mS(類似於/proc中輸出的其他時間)。
+此文件給出了在本CPU支æŒçš„æ¯å€‹é »çŽ‡ä¸Šåˆ†åˆ¥èŠ±è²»çš„æ™‚é–“ã€‚cat輸出的æ¯ä¸€è¡Œéƒ½æ˜¯ä¸€å€‹"<frequency>
+<time>"å°ï¼Œè¡¨ç¤ºé€™å€‹CPU在<frequency>上花費了<time>個usertimeå–®ä½çš„æ™‚間。輸出的æ¯ä¸€è¡Œå°æ‡‰
+一個CPU支æŒçš„頻率。這è£usertime單使˜¯10mS(類似於/proc導出的其它時間)。
::
@@ -84,7 +86,7 @@ usertime單使˜¯10mS(類似於/proc中輸出的其他時間)。
- **total_trans**
-給出了這個CPU上頻率轉æ›çš„總次數。cat的輸出將有一個單一的計數,這就是頻率轉æ›çš„總數。
+此文件給出了這個CPU頻率轉æ›çš„總次數。cat的輸出是一個計數值,它就是頻率轉æ›çš„總次數。
::
@@ -93,10 +95,10 @@ usertime單使˜¯10mS(類似於/proc中輸出的其他時間)。
- **trans_table**
-這將æä¾›æ‰€æœ‰CPU頻率轉æ›çš„細粒度信æ¯ã€‚這裡的cat輸出是一個二維矩陣,其中一個æ¢ç›®<i, j>(第
+本文件æä¾›æ‰€æœ‰CPU頻率轉æ›çš„細粒度信æ¯ã€‚這è£çš„cat輸出是一個二維矩陣,其中一個æ¢ç›®<i, j>(第
i行,第j列)代表從Freq_i到Freq_jçš„è½‰æ›æ¬¡æ•¸ã€‚Freq_i行和Freq_j列éµå¾ªé©…å‹•æœ€åˆæä¾›çµ¦cpufreq
-核的頻率表的排åºé †åºï¼Œå› æ­¤å¯ä»¥æŽ’åºï¼ˆå‡åºæˆ–é™åºï¼‰æˆ–䏿ޒåºã€‚ 這裡的輸出也包å«äº†æ¯è¡Œæ¯åˆ—的實際
-頻率值,以便更好地閱讀。
+核心的頻率表的排列順åºï¼Œå› æ­¤å¯ä»¥å·²æŽ’åºï¼ˆå‡åºæˆ–é™åºï¼‰æˆ–未排åºã€‚這è£çš„輸出也包å«äº†å¯¦éš›
+頻率值,分別按行和按列顯示,以便更好地閱讀。
如果轉æ›è¡¨å¤§æ–¼PAGE_SIZEï¼Œè®€å–æ™‚將返回一個-EFBIG錯誤。
@@ -114,7 +116,7 @@ i行,第j列)代表從Freq_i到Freq_jçš„è½‰æ›æ¬¡æ•¸ã€‚Freq_i行和Freq_j列
3. é…ç½®cpufreq-stats
============================
-è¦åœ¨ä½ çš„內核中é…ç½®cpufreq-stats::
+按以下方å¼åœ¨ä½ çš„內核中é…ç½®cpufreq-stats::
Config Main Menu
Power management options (ACPI, APM) --->
@@ -123,7 +125,7 @@ i行,第j列)代表從Freq_i到Freq_jçš„è½‰æ›æ¬¡æ•¸ã€‚Freq_i行和Freq_j列
[*] CPU frequency translation statistics
-"CPU Frequency scaling" (CONFIG_CPU_FREQ) 應該被啓用以é…ç½®cpufreq-stats。
+"CPU Frequency scaling" (CONFIG_CPU_FREQ) 應該被啓用,以支æŒé…ç½®cpufreq-stats。
"CPU frequency translation statistics" (CONFIG_CPU_FREQ_STAT)æä¾›äº†åŒ…括
time_in_stateã€total_transå’Œtrans_table的統計數據。
diff --git a/Documentation/translations/zh_TW/cpu-freq/index.rst b/Documentation/translations/zh_TW/cpu-freq/index.rst
index c6cf825b57a5..a9df16870b21 100644
--- a/Documentation/translations/zh_TW/cpu-freq/index.rst
+++ b/Documentation/translations/zh_TW/cpu-freq/index.rst
@@ -2,12 +2,13 @@
.. include:: ../disclaimer-zh_TW.rst
-:Original: :doc:`../../../cpu-freq/index`
-:Translator: Yanteng Si <siyanteng@loongson.cn>
- Hu Haowen <src.res.211@gmail.com>
+:Original: Documentation/cpu-freq/index.rst
-.. _tw_index.rst:
+:翻譯:
+
+ å¸å»¶é¨° Yanteng Si <siyanteng@loongson.cn>
+.. _tw_index.rst:
=======================================================
Linux CPUFreq - Linux(TM)內核中的CPU頻率和電壓å‡é™ä»£ç¢¼
@@ -28,10 +29,10 @@ Author: Dominik Brodowski <linux@brodo.de>
郵件列表
------------
-這裡有一個 CPU 頻率變化的 CVS æäº¤å’Œé€šç”¨åˆ—表,您å¯ä»¥åœ¨é€™è£¡å ±å‘Šbugã€å•題或æäº¤è£œä¸ã€‚è¦ç™¼
+é€™è£æœ‰ä¸€å€‹ CPU 頻率變化的 CVS æäº¤å’Œé€šç”¨åˆ—表,您å¯ä»¥åœ¨é€™è£å ±å‘Šbugã€å•題或æäº¤è£œä¸ã€‚è¦ç™¼
布消æ¯ï¼Œè«‹ç™¼é€é›»å­éƒµä»¶åˆ° linux-pm@vger.kernel.org。
-連çµ
+éˆæŽ¥
-----
FTP檔案:
* ftp://ftp.linux.org.uk/pub/linux/cpufreq/
diff --git a/Documentation/translations/zh_TW/dev-tools/gcov.rst b/Documentation/translations/zh_TW/dev-tools/gcov.rst
new file mode 100644
index 000000000000..ce1c9a97de16
--- /dev/null
+++ b/Documentation/translations/zh_TW/dev-tools/gcov.rst
@@ -0,0 +1,265 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/dev-tools/gcov.rst
+:Translator: è¶™è»å¥Ž Bernard Zhao <bernard@vivo.com>
+
+在Linuxå…§æ ¸è£ä½¿ç”¨gcovåšä»£ç¢¼è¦†è“‹çŽ‡æª¢æŸ¥
+=====================================
+
+gcovåˆ†æžæ ¸å¿ƒæ”¯æŒåœ¨Linux內核中啓用GCC的覆蓋率測試工具 gcov_ ,Linuxå…§æ ¸
+é‹è¡Œæ™‚的代碼覆蓋率數據會以gcov兼容的格å¼å°Žå‡ºåˆ°â€œgcovâ€debugfs目錄中,å¯
+以通éŽgcovçš„ ``-o`` é¸é …(如下示例)ç²å¾—指定文件的代碼é‹è¡Œè¦†è“‹çŽ‡çµ±è¨ˆæ•¸æ“š
+(需è¦è·³è½‰åˆ°å…§æ ¸ç·¨è­¯è·¯å¾‘ä¸‹ä¸¦ä¸”è¦æœ‰root權é™ï¼‰::
+
+ # cd /tmp/linux-out
+ # gcov -o /sys/kernel/debug/gcov/tmp/linux-out/kernel spinlock.c
+
+這將在當å‰ç›®éŒ„中創建帶有執行計數註釋的æºä»£ç¢¼æ–‡ä»¶ã€‚
+在ç²å¾—這些統計文件後,å¯ä»¥ä½¿ç”¨åœ–形化的gcovå‰ç«¯å·¥å…·ï¼ˆæ¯”如 lcov_ ),來實ç¾
+自動化處ç†Linux內核的覆蓋率é‹è¡Œæ•¸æ“šï¼ŒåŒæ™‚ç”Ÿæˆæ˜“於閱讀的HTMLæ ¼å¼æ–‡ä»¶ã€‚
+
+å¯èƒ½çš„用途:
+
+* 調試(用來判斷æ¯ä¸€è¡Œçš„代碼是å¦å·²ç¶“é‹è¡ŒéŽï¼‰
+* 測試改進(如何修改測試代碼,儘å¯èƒ½åœ°è¦†è“‹åˆ°æ²’有é‹è¡ŒéŽçš„代碼)
+* 內核最å°åŒ–é…ç½®ï¼ˆå°æ–¼æŸä¸€å€‹é¸é …é…置,如果關è¯çš„代碼從來沒有é‹è¡ŒéŽï¼Œ
+ 是å¦é‚„需è¦é€™å€‹é…置)
+
+.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
+.. _lcov: http://ltp.sourceforge.net/coverage/lcov.php
+
+
+準備
+----
+
+內核打開如下é…ç½®::
+
+ CONFIG_DEBUG_FS=y
+ CONFIG_GCOV_KERNEL=y
+
+ç²å–æ•´å€‹å…§æ ¸çš„è¦†è“‹çŽ‡æ•¸æ“šï¼Œé‚„éœ€è¦æ‰“é–‹::
+
+ CONFIG_GCOV_PROFILE_ALL=y
+
+éœ€è¦æ³¨æ„的是,整個內核開啓覆蓋率統計會造æˆå…§æ ¸é¡åƒæ–‡ä»¶å°ºå¯¸çš„增大,
+åŒæ™‚å…§æ ¸é‹è¡Œä¹Ÿæœƒè®Šæ…¢ä¸€äº›ã€‚
+å¦å¤–ï¼Œä¸¦ä¸æ˜¯æ‰€æœ‰çš„æž¶æ§‹éƒ½æ”¯æŒæ•´å€‹å…§æ ¸é–‹å•“覆蓋率統計。
+
+代碼é‹è¡Œè¦†è“‹çŽ‡æ•¸æ“šåªåœ¨debugfs掛載完æˆå¾Œçº”å¯ä»¥è¨ªå•::
+
+ mount -t debugfs none /sys/kernel/debug
+
+
+定製化
+------
+
+如果è¦å–®ç¨é‡å°æŸä¸€å€‹è·¯å¾‘或者文件進行代碼覆蓋率統計,å¯ä»¥åœ¨å…§æ ¸ç›¸æ‡‰è·¯
+徑的Makefile中增加如下的é…ç½®:
+
+- å–®ç¨çµ±è¨ˆå–®å€‹æ–‡ä»¶ï¼ˆä¾‹å¦‚main.o)::
+
+ GCOV_PROFILE_main.o := y
+
+- å–®ç¨çµ±è¨ˆæŸä¸€å€‹è·¯å¾‘::
+
+ GCOV_PROFILE := y
+
+如果è¦åœ¨æ•´å€‹å…§æ ¸çš„覆蓋率統計(開啓CONFIG_GCOV_PROFILE_ALLï¼‰ä¸­å–®ç¨æŽ’é™¤
+æŸä¸€å€‹æ–‡ä»¶æˆ–者路徑,å¯ä»¥ä½¿ç”¨å¦‚下的方法::
+
+ GCOV_PROFILE_main.o := n
+
+和::
+
+ GCOV_PROFILE := n
+
+此機制僅支æŒéˆæŽ¥åˆ°å…§æ ¸é¡åƒæˆ–編譯爲內核模塊的文件。
+
+
+相關文件
+--------
+
+gcov功能需è¦åœ¨debugfs中創建如下文件:
+
+``/sys/kernel/debug/gcov``
+ gcov相關功能的根路徑
+
+``/sys/kernel/debug/gcov/reset``
+ 免局復使–‡ä»¶:å‘該文件寫入數據後會將所有的gcov統計數據清0
+
+``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcda``
+ gcov工具å¯ä»¥è­˜åˆ¥çš„覆蓋率統計數據文件,å‘該文件寫入數據後
+ 會將本文件的gcov統計數據清0
+
+``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcno``
+ gcov工具需è¦çš„軟連接文件(指å‘編譯時生æˆçš„ä¿¡æ¯çµ±è¨ˆæ–‡ä»¶ï¼‰ï¼Œé€™å€‹æ–‡ä»¶æ˜¯
+ 在gcc編譯時如果é…置了é¸é … ``-ftest-coverage`` 時生æˆçš„。
+
+
+é‡å°æ¨¡å¡Šçš„統計
+--------------
+
+內核中的模塊會動態的加載和å¸è¼‰ï¼Œæ¨¡å¡Šå¸è¼‰æ™‚å°æ‡‰çš„æ•¸æ“šæœƒè¢«æ¸…é™¤æŽ‰ã€‚
+gcovæä¾›äº†ä¸€ç¨®æ©Ÿåˆ¶ï¼Œé€šéŽä¿ç•™ç›¸é—œæ•¸æ“šçš„副本來收集這部分å¸è¼‰æ¨¡å¡Šçš„覆蓋率數據。
+模塊å¸è¼‰å¾Œé€™äº›å‚™ä»½æ•¸æ“šåœ¨debugfs中會繼續存在。
+ä¸€æ—¦é€™å€‹æ¨¡å¡Šé‡æ–°åŠ è¼‰ï¼Œæ¨¡å¡Šé—œè¯çš„é‹è¡Œçµ±è¨ˆæœƒè¢«åˆå§‹åŒ–æˆdebugfs中備份的數據。
+
+å¯ä»¥é€šéŽå°å…§æ ¸åƒæ•¸gcov_persist的修改來åœç”¨gcovå°æ¨¡å¡Šçš„備份機制::
+
+ gcov_persist = 0
+
+在é‹è¡Œæ™‚,用戶還å¯ä»¥é€šéŽå¯«å…¥æ¨¡å¡Šçš„æ•¸æ“šæ–‡ä»¶æˆ–è€…å¯«å…¥gcov復使–‡ä»¶ä¾†ä¸Ÿæ£„å·²å¸
+載模塊的數據。
+
+
+編譯機和測試機分離
+------------------
+
+gcovçš„å…§æ ¸åˆ†æžæ’æ¨æ”¯æŒå…§æ ¸çš„編譯和é‹è¡Œæ˜¯åœ¨åŒä¸€è‡ºæ©Ÿå™¨ä¸Šï¼Œä¹Ÿå¯ä»¥ç·¨è­¯å’Œé‹
+行是在ä¸åŒçš„æ©Ÿå™¨ä¸Šã€‚
+如果內核編譯和é‹è¡Œæ˜¯ä¸åŒçš„æ©Ÿå™¨ï¼Œé‚£éº¼éœ€è¦é¡å¤–çš„æº–å‚™å·¥ä½œï¼Œé€™å–æ±ºæ–¼gcov工具
+是在哪è£ä½¿ç”¨çš„:
+
+.. _gcov-test_zh:
+
+a) è‹¥gcové‹è¡Œåœ¨æ¸¬è©¦æ©Ÿä¸Š
+
+ 測試機上é¢gcov工具的版本必須è¦è·Ÿå…§æ ¸ç·¨è­¯æ©Ÿå™¨ä½¿ç”¨çš„gcc版本相兼容,
+ åŒæ™‚下é¢çš„æ–‡ä»¶è¦å¾žç·¨è­¯æ©Ÿæ‹·è²åˆ°æ¸¬è©¦æ©Ÿä¸Š:
+
+ 從æºä»£ç¢¼ä¸­:
+ - 所有的C文件和頭文件
+
+ 從編譯目錄中:
+ - 所有的C文件和頭文件
+ - 所有的.gcda文件和.gcno文件
+ - æ‰€æœ‰ç›®éŒ„çš„éˆæŽ¥
+
+ ç‰¹åˆ¥éœ€è¦æ³¨æ„,測試機器上é¢çš„ç›®éŒ„çµæ§‹è·Ÿç·¨è­¯æ©Ÿå™¨ä¸Šé¢çš„目錄機構必須
+ 完全一致。
+ å¦‚æžœæ–‡ä»¶æ˜¯è»ŸéˆæŽ¥ï¼Œéœ€è¦æ›¿æ›æˆçœŸæ­£çš„目錄文件(這是由make的當å‰å·¥ä½œ
+ 目錄變é‡CURDIR引起的)。
+
+.. _gcov-build_zh:
+
+b) è‹¥gcové‹è¡Œåœ¨ç·¨è­¯æ©Ÿä¸Š
+
+ 測試用例é‹è¡ŒçµæŸå¾Œï¼Œå¦‚下的文件需è¦å¾žæ¸¬è©¦æ©Ÿä¸­æ‹·è²åˆ°ç·¨è­¯æ©Ÿä¸Š:
+
+ 從sysfs中的gcov目錄中:
+ - 所有的.gcda文件
+ - 所有的.gcnoæ–‡ä»¶è»ŸéˆæŽ¥
+
+ 這些文件å¯ä»¥æ‹·è²åˆ°ç·¨è­¯æ©Ÿçš„ä»»æ„目錄下,gcov使用-oé¸é …指定拷è²çš„
+ 目錄。
+
+ æ¯”å¦‚ä¸€å€‹æ˜¯ç¤ºä¾‹çš„ç›®éŒ„çµæ§‹å¦‚下::
+
+ /tmp/linux: å…§æ ¸æºç¢¼ç›®éŒ„
+ /tmp/out: 內核編譯文件路徑(make O=指定)
+ /tmp/coverage: å¾žæ¸¬è©¦æ©Ÿå™¨ä¸Šé¢æ‹·è²çš„æ•¸æ“šæ–‡ä»¶è·¯å¾‘
+
+ [user@build] cd /tmp/out
+ [user@build] gcov -o /tmp/coverage/tmp/out/init main.c
+
+
+關於編譯器的注æ„事項
+--------------------
+
+GCCå’ŒLLVM gcov工具ä¸ä¸€å®šå…¼å®¹ã€‚
+如果編譯器是GCC,使用 gcov_ 來處ç†.gcnoå’Œ.gcda文件,如果是Clang編譯器,
+則使用 llvm-cov_ 。
+
+.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
+.. _llvm-cov: https://llvm.org/docs/CommandGuide/llvm-cov.html
+
+GCCå’ŒClang gcov之間的版本差異由Kconfig處ç†çš„。
+kconfig會根據編譯工具éˆçš„æª¢æŸ¥è‡ªå‹•鏿“‡åˆé©çš„gcovæ ¼å¼ã€‚
+
+å•題定ä½
+--------
+
+å¯èƒ½å‡ºç¾çš„å•題1
+ ç·¨è­¯åˆ°éˆæŽ¥éšŽæ®µå ±éŒ¯çµ‚æ­¢
+
+å•題原因
+ åˆ†æžæ¨™èªŒæŒ‡å®šåœ¨äº†æºæ–‡ä»¶ä½†æ˜¯æ²’æœ‰éˆæŽ¥åˆ°ä¸»å…§æ ¸ï¼Œæˆ–è€…å®¢è£½åŒ–äº†éˆæŽ¥ç¨‹åº
+
+解決方法
+ 通éŽåœ¨ç›¸æ‡‰çš„Makefile中使用 ``GCOV_PROFILE := n``
+ 或者 ``GCOV_PROFILE_basename.o := n`` ä¾†å°‡éˆæŽ¥å ±éŒ¯çš„æ–‡ä»¶æŽ’é™¤æŽ‰
+
+å¯èƒ½å‡ºç¾çš„å•題2
+ 從sysfs複製的文件顯示爲空或ä¸å®Œæ•´
+
+å•題原因
+ 由於seq_file的工作方å¼ï¼ŒæŸäº›å·¥å…·ï¼ˆä¾‹å¦‚cp或tar)å¯èƒ½ç„¡æ³•正確地從
+ sysfs複製文件。
+
+解決方法
+ 使用 ``cat`` è®€å– ``.gcda`` 文件,使用 ``cp -d`` è¤‡è£½éˆæŽ¥ï¼Œæˆ–è€…ä½¿ç”¨é™„éŒ„B
+ 中所示的機制。
+
+
+附錄A:collect_on_build.sh
+--------------------------
+
+用於在編譯機上收集覆蓋率元文件的示例腳本
+(見 :ref:`編譯機和測試機分離 a. <gcov-test_zh>` )
+
+.. code-block:: sh
+
+ #!/bin/bash
+
+ KSRC=$1
+ KOBJ=$2
+ DEST=$3
+
+ if [ -z "$KSRC" ] || [ -z "$KOBJ" ] || [ -z "$DEST" ]; then
+ echo "Usage: $0 <ksrc directory> <kobj directory> <output.tar.gz>" >&2
+ exit 1
+ fi
+
+ KSRC=$(cd $KSRC; printf "all:\n\t@echo \${CURDIR}\n" | make -f -)
+ KOBJ=$(cd $KOBJ; printf "all:\n\t@echo \${CURDIR}\n" | make -f -)
+
+ find $KSRC $KOBJ \( -name '*.gcno' -o -name '*.[ch]' -o -type l \) -a \
+ -perm /u+r,g+r | tar cfz $DEST -P -T -
+
+ if [ $? -eq 0 ] ; then
+ echo "$DEST successfully created, copy to test system and unpack with:"
+ echo " tar xfz $DEST -P"
+ else
+ echo "Could not create file $DEST"
+ fi
+
+
+附錄B:collect_on_test.sh
+-------------------------
+
+用於在測試機上收集覆蓋率數據文件的示例腳本
+(見 :ref:`編譯機和測試機分離 b. <gcov-build_zh>` )
+
+.. code-block:: sh
+
+ #!/bin/bash -e
+
+ DEST=$1
+ GCDA=/sys/kernel/debug/gcov
+
+ if [ -z "$DEST" ] ; then
+ echo "Usage: $0 <output.tar.gz>" >&2
+ exit 1
+ fi
+
+ TEMPDIR=$(mktemp -d)
+ echo Collecting data..
+ find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \;
+ find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \;
+ find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \;
+ tar czf $DEST -C $TEMPDIR sys
+ rm -rf $TEMPDIR
+
+ echo "$DEST successfully created, copy to build system and unpack with:"
+ echo " tar xfz $DEST"
+
diff --git a/Documentation/translations/zh_TW/dev-tools/gdb-kernel-debugging.rst b/Documentation/translations/zh_TW/dev-tools/gdb-kernel-debugging.rst
new file mode 100644
index 000000000000..c881e8872b19
--- /dev/null
+++ b/Documentation/translations/zh_TW/dev-tools/gdb-kernel-debugging.rst
@@ -0,0 +1,168 @@
+.. highlight:: none
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/dev-tools/gdb-kernel-debugging.rst
+:Translator: 高超 gao chao <gaochao49@huawei.com>
+
+通éŽgdb調試內核和模塊
+=====================
+
+Kgdb內核調試器ã€QEMU等虛擬機管ç†ç¨‹åºæˆ–基於JTAG的硬件接å£ï¼Œæ”¯æŒåœ¨é‹è¡Œæ™‚使用gdb
+調試Linuxå…§æ ¸åŠå…¶æ¨¡å¡Šã€‚Gdbæä¾›äº†ä¸€å€‹å¼·å¤§çš„python腳本接å£ï¼Œå…§æ ¸ä¹Ÿæä¾›äº†ä¸€å¥—
+輔助腳本以簡化典型的內核調試步驟。本文檔爲如何啓用和使用這些腳本æä¾›äº†ä¸€å€‹ç°¡è¦çš„æ•™ç¨‹ã€‚
+此教程基於QEMU/KVM虛擬機,但文中示例也é©ç”¨æ–¼å…¶ä»–gdb stub。
+
+
+環境é…ç½®è¦æ±‚
+------------
+
+- gdb 7.2+ (推薦版本: 7.4+) 且開啓pythonæ”¯æŒ (通常發行版上都已支æŒ)
+
+設置
+----
+
+- 創建一個QEMU/KVMçš„linux虛擬機(詳情請åƒè€ƒ www.linux-kvm.org å’Œ www.qemu.org )。
+ å°æ–¼äº¤å‰é–‹ç™¼ï¼Œhttps://landley.net/aboriginal/bin æä¾›äº†ä¸€äº›é¡åƒå’Œå·¥å…·éˆï¼Œ
+ å¯ä»¥å¹«åŠ©æ­å»ºäº¤å‰é–‹ç™¼ç’°å¢ƒã€‚
+
+- 編譯內核時開啓CONFIG_GDB_SCRIPTS,關閉CONFIG_DEBUG_INFO_REDUCED。
+ 如果架構支æŒCONFIG_FRAME_POINTERï¼Œè«‹ä¿æŒé–‹å•“。
+
+- 在guest環境上安è£è©²å…§æ ¸ã€‚如有必è¦ï¼Œé€šéŽåœ¨å…§æ ¸command line中添加“nokaslrâ€ä¾†é—œé–‰KASLR。
+ 此外,QEMUå…許通éŽ-kernelã€-appendã€-initrd這些命令行é¸é …直接啓動內核。
+ 但這通常僅在ä¸ä¾è³´å…§æ ¸æ¨¡å¡Šæ™‚纔有效。有關此模å¼çš„æ›´å¤šè©³ç´°ä¿¡æ¯ï¼Œè«‹åƒé–±QEMU文檔。
+ 在這種情æ³ä¸‹ï¼Œå¦‚果架構支æŒKASLR,應該在ç¦ç”¨CONFIG_RANDOMIZE_BASE的情æ³ä¸‹æ§‹å»ºå…§æ ¸ã€‚
+
+- 啓用QEMU/KVMçš„gdb stub,å¯ä»¥é€šéŽå¦‚下方å¼å¯¦ç¾
+
+ - 在VM啓動時,通éŽåœ¨QEMU命令行中添加“-sâ€åƒæ•¸
+
+ 或
+
+ - 在é‹è¡Œæ™‚通éŽå¾žQEMU監視控制檯發é€â€œgdbserverâ€
+
+- 切æ›åˆ°/path/to/linux-build(å…§æ ¸æºç¢¼ç·¨è­¯)目錄
+
+- 啓動gdb:gdb vmlinux
+
+ 注æ„:æŸäº›ç™¼è¡Œç‰ˆå¯èƒ½æœƒå°‡gdb腳本的自動加載é™åˆ¶åœ¨å·²çŸ¥çš„安全目錄中。
+ 如果gdb報告拒絕加載vmlinux-gdb.py(相關命令找ä¸åˆ°ï¼‰ï¼Œè«‹å°‡::
+
+ add-auto-load-safe-path /path/to/linux-build
+
+ 添加到~/.gdbinit。更多詳細信æ¯ï¼Œè«‹åƒé–±gdb幫助信æ¯ã€‚
+
+- 連接到已啓動的guest環境::
+
+ (gdb) target remote :1234
+
+
+使用Linuxæä¾›çš„gdb腳本的示例
+----------------------------
+
+- 加載模塊(以åŠä¸»å…§æ ¸ï¼‰ç¬¦è™Ÿ::
+
+ (gdb) lx-symbols
+ loading vmlinux
+ scanning for modules in /home/user/linux/build
+ loading @0xffffffffa0020000: /home/user/linux/build/net/netfilter/xt_tcpudp.ko
+ loading @0xffffffffa0016000: /home/user/linux/build/net/netfilter/xt_pkttype.ko
+ loading @0xffffffffa0002000: /home/user/linux/build/net/netfilter/xt_limit.ko
+ loading @0xffffffffa00ca000: /home/user/linux/build/net/packet/af_packet.ko
+ loading @0xffffffffa003c000: /home/user/linux/build/fs/fuse/fuse.ko
+ ...
+ loading @0xffffffffa0000000: /home/user/linux/build/drivers/ata/ata_generic.ko
+
+- å°ä¸€äº›å°šæœªåŠ è¼‰çš„æ¨¡å¡Šä¸­çš„å‡½æ•¸å‡½æ•¸è¨­ç½®æ–·é»žï¼Œä¾‹å¦‚::
+
+ (gdb) b btrfs_init_sysfs
+ Function "btrfs_init_sysfs" not defined.
+ Make breakpoint pending on future shared library load? (y or [n]) y
+ Breakpoint 1 (btrfs_init_sysfs) pending.
+
+- 繼續執行::
+
+ (gdb) c
+
+- åŠ è¼‰æ¨¡å¡Šä¸¦ä¸”èƒ½è§€å¯Ÿåˆ°æ­£åœ¨åŠ è¼‰çš„ç¬¦è™Ÿä»¥åŠæ–·é»žå‘½ä¸­::
+
+ loading @0xffffffffa0034000: /home/user/linux/build/lib/libcrc32c.ko
+ loading @0xffffffffa0050000: /home/user/linux/build/lib/lzo/lzo_compress.ko
+ loading @0xffffffffa006e000: /home/user/linux/build/lib/zlib_deflate/zlib_deflate.ko
+ loading @0xffffffffa01b1000: /home/user/linux/build/fs/btrfs/btrfs.ko
+
+ Breakpoint 1, btrfs_init_sysfs () at /home/user/linux/fs/btrfs/sysfs.c:36
+ 36 btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj);
+
+- 查看內核的日誌緩è¡å€::
+
+ (gdb) lx-dmesg
+ [ 0.000000] Initializing cgroup subsys cpuset
+ [ 0.000000] Initializing cgroup subsys cpu
+ [ 0.000000] Linux version 3.8.0-rc4-dbg+ (...
+ [ 0.000000] Command line: root=/dev/sda2 resume=/dev/sda1 vga=0x314
+ [ 0.000000] e820: BIOS-provided physical RAM map:
+ [ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
+ [ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
+ ....
+
+- 查看當å‰task structçµæ§‹é«”的字段(僅x86å’Œarm64支æŒï¼‰::
+
+ (gdb) p $lx_current().pid
+ $1 = 4998
+ (gdb) p $lx_current().comm
+ $2 = "modprobe\000\000\000\000\000\000\000"
+
+- å°ç•¶å‰æˆ–指定的CPU使用per-cpu函數::
+
+ (gdb) p $lx_per_cpu("runqueues").nr_running
+ $3 = 1
+ (gdb) p $lx_per_cpu("runqueues", 2).nr_running
+ $4 = 0
+
+- 使用container_of查看更多hrtimersä¿¡æ¯::
+
+ (gdb) set $next = $lx_per_cpu("hrtimer_bases").clock_base[0].active.next
+ (gdb) p *$container_of($next, "struct hrtimer", "node")
+ $5 = {
+ node = {
+ node = {
+ __rb_parent_color = 18446612133355256072,
+ rb_right = 0x0 <irq_stack_union>,
+ rb_left = 0x0 <irq_stack_union>
+ },
+ expires = {
+ tv64 = 1835268000000
+ }
+ },
+ _softexpires = {
+ tv64 = 1835268000000
+ },
+ function = 0xffffffff81078232 <tick_sched_timer>,
+ base = 0xffff88003fd0d6f0,
+ state = 1,
+ start_pid = 0,
+ start_site = 0xffffffff81055c1f <hrtimer_start_range_ns+20>,
+ start_comm = "swapper/2\000\000\000\000\000\000"
+ }
+
+
+命令和輔助調試功能列表
+----------------------
+
+命令和輔助調試功能å¯èƒ½æœƒéš¨ç€æ™‚間的推移而改進,此文顯示的是åˆå§‹ç‰ˆæœ¬çš„部分示例::
+
+ (gdb) apropos lx
+ function lx_current -- Return current task
+ function lx_module -- Find module by name and return the module variable
+ function lx_per_cpu -- Return per-cpu variable
+ function lx_task_by_pid -- Find Linux task by PID and return the task_struct variable
+ function lx_thread_info -- Calculate Linux thread_info from task variable
+ lx-dmesg -- Print Linux kernel log buffer
+ lx-lsmod -- List currently loaded modules
+ lx-symbols -- (Re-)load symbols of Linux kernel and currently loaded modules
+
+å¯ä»¥é€šéŽâ€œhelp <command-name>â€æˆ–“help function <function-name>â€å‘½ä»¤
+ç²å–指定命令或指定調試功能的更多詳細信æ¯ã€‚
+
diff --git a/Documentation/translations/zh_TW/dev-tools/index.rst b/Documentation/translations/zh_TW/dev-tools/index.rst
new file mode 100644
index 000000000000..0d38e5f80e54
--- /dev/null
+++ b/Documentation/translations/zh_TW/dev-tools/index.rst
@@ -0,0 +1,43 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/dev-tools/index.rst
+:Translator: è¶™è»å¥Ž Bernard Zhao <bernard@vivo.com>
+
+============
+內核開發工具
+============
+
+本文檔是有關內核開發工具文檔的åˆé›†ã€‚
+ç›®å‰é€™äº›æ–‡æª”已經整ç†åœ¨ä¸€èµ·ï¼Œä¸éœ€è¦å†èŠ±è²»é¡å¤–的精力。
+歡迎任何補ä¸ã€‚
+
+æœ‰é—œæ¸¬è©¦å°ˆç”¨å·¥å…·çš„ç°¡è¦æ¦‚述,åƒè¦‹
+Documentation/translations/zh_TW/dev-tools/testing-overview.rst
+
+.. class:: toc-title
+
+ 目錄
+
+.. toctree::
+ :maxdepth: 2
+
+ testing-overview
+ sparse
+ gcov
+ kasan
+ gdb-kernel-debugging
+
+Todolist:
+
+ - coccinelle
+ - kcov
+ - ubsan
+ - kmemleak
+ - kcsan
+ - kfence
+ - kgdb
+ - kselftest
+ - kunit/index
+
diff --git a/Documentation/translations/zh_TW/dev-tools/kasan.rst b/Documentation/translations/zh_TW/dev-tools/kasan.rst
new file mode 100644
index 000000000000..979eb84bc58f
--- /dev/null
+++ b/Documentation/translations/zh_TW/dev-tools/kasan.rst
@@ -0,0 +1,463 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/dev-tools/kasan.rst
+:Translator: è¬å®¶å…µ Wan Jiabing <wanjiabing@vivo.com>
+
+å…§æ ¸åœ°å€æ¶ˆæ¯’劑(KASAN)
+=====================
+
+概述
+----
+
+Kernel Address SANitizer(KASAN)是一種動態內存安全錯誤檢測工具,主è¦åŠŸèƒ½æ˜¯
+檢查內存越界訪å•和使用已釋放內存的å•題。
+
+KASAN有三種模å¼:
+
+1. 通用KASAN
+2. 基於軟件標籤的KASAN
+3. 基於硬件標籤的KASAN
+
+用CONFIG_KASAN_GENERIC啓用的通用KASAN,是用於調試的模å¼ï¼Œé¡žä¼¼æ–¼ç”¨æˆ¶ç©º
+é–“çš„ASan。這種模å¼åœ¨è¨±å¤šCPU架構上都被支æŒï¼Œä½†å®ƒæœ‰æ˜Žé¡¯çš„æ€§èƒ½å’Œå…§å­˜é–‹éŠ·ã€‚
+
+基於軟件標籤的KASAN或SW_TAGS KASAN,通éŽCONFIG_KASAN_SW_TAGS啓用,
+å¯ä»¥ç”¨æ–¼èª¿è©¦å’Œè‡ªæˆ‘測試,類似於用戶空間HWASan。這種模å¼åªæ”¯æŒarm64,但其
+é©åº¦çš„內存開銷å…許在內存å—é™çš„設備上用真實的工作負載進行測試。
+
+基於硬件標籤的KASAN或HW_TAGS KASAN,用CONFIG_KASAN_HW_TAGS啓用,被
+用作ç¾å ´å…§å­˜éŒ¯èª¤æª¢æ¸¬å™¨æˆ–作爲安全緩解的模å¼ã€‚這種模å¼åªåœ¨æ”¯æŒMTE(內存標籤
+擴展)的arm64 CPU上工作,但它的內存和性能開銷很低,因此å¯ä»¥åœ¨ç”Ÿç”¢ä¸­ä½¿ç”¨ã€‚
+
+關於æ¯ç¨®KASAN模å¼çš„內存和性能影響的細節,請åƒè¦‹ç›¸æ‡‰çš„Kconfigé¸é …çš„æè¿°ã€‚
+
+通用模å¼å’ŒåŸºæ–¼è»Ÿä»¶æ¨™ç±¤çš„æ¨¡å¼é€šå¸¸è¢«ç¨±çˆ²è»Ÿä»¶æ¨¡å¼ã€‚基於軟件標籤的模å¼å’ŒåŸºæ–¼
+硬件標籤的模å¼è¢«ç¨±çˆ²åŸºæ–¼æ¨™ç±¤çš„æ¨¡å¼ã€‚
+
+支æŒ
+----
+
+體系架構
+~~~~~~~~
+
+在x86_64ã€armã€arm64ã€powerpcã€riscvã€s390ã€xtensaå’Œloongarch上支æŒé€šç”¨KASAN,
+而基於標籤的KASAN模å¼åªåœ¨arm64上支æŒã€‚
+
+編譯器
+~~~~~~
+
+軟件KASAN模å¼ä½¿ç”¨ç·¨è­¯æ™‚工具在æ¯å€‹å…§å­˜è¨ªå•之剿’入有效性檢查,因此需è¦ä¸€å€‹
+æä¾›æ”¯æŒçš„編譯器版本。基於硬件標籤的模å¼ä¾é ç¡¬ä»¶ä¾†åŸ·è¡Œé€™äº›æª¢æŸ¥ï¼Œä½†ä»ç„¶éœ€è¦
+一個支æŒå…§å­˜æ¨™ç±¤æŒ‡ä»¤çš„編譯器版本。
+
+通用KASAN需è¦GCC 8.3.0版本或更高版本,或者內核支æŒçš„任何Clang版本。
+
+基於軟件標籤的KASAN需è¦GCC 11+或者內核支æŒçš„任何Clang版本。
+
+基於硬件標籤的KASAN需è¦GCC 10+或Clang 12+。
+
+內存類型
+~~~~~~~~
+
+通用KASAN支æŒåœ¨æ‰€æœ‰çš„slabã€page_allocã€vmapã€vmallocã€å †æ£§å’Œå…¨å±€å…§å­˜
+中查找錯誤。
+
+基於軟件標籤的KASAN支æŒslabã€page_allocã€vmalloc和堆棧內存。
+
+基於硬件標籤的KASAN支æŒslabã€page_allocå’Œä¸å¯åŸ·è¡Œçš„vmalloc內存。
+
+å°æ–¼slab,兩種軟件KASAN模å¼éƒ½æ”¯æŒSLUBå’ŒSLAB分é…器,而基於硬件標籤的
+KASANåªæ”¯æŒSLUB。
+
+用法
+----
+
+è¦å•“用KASAN,請使用以下命令é…置內核::
+
+ CONFIG_KASAN=y
+
+åŒæ™‚在 ``CONFIG_KASAN_GENERIC`` (啓用通用KASAN模å¼), ``CONFIG_KASAN_SW_TAGS``
+(啓用基於硬件標籤的KASAN模å¼),和 ``CONFIG_KASAN_HW_TAGS`` (啓用基於硬件標籤
+çš„KASAN模å¼)ä¹‹é–“é€²è¡Œé¸æ“‡ã€‚
+
+å°æ–¼è»Ÿä»¶æ¨¡å¼ï¼Œé‚„å¯ä»¥åœ¨ ``CONFIG_KASAN_OUTLINE`` å’Œ ``CONFIG_KASAN_INLINE``
+ä¹‹é–“é€²è¡Œé¸æ“‡ã€‚outlineå’Œinlineæ˜¯ç·¨è­¯å™¨æ’æ¨é¡žåž‹ã€‚å‰è€…產生較å°çš„二進制文件,
+而後者快2å€ã€‚
+
+è¦å°‡å—影響的slabå°è±¡çš„allocå’Œfree堆棧跟蹤包å«åˆ°å ±å‘Šä¸­ï¼Œè«‹å•“用
+``CONFIG_STACKTRACE`` 。è¦åŒ…括å—影響物ç†é é¢çš„分é…和釋放堆棧跟蹤的話,
+請啓用 ``CONFIG_PAGE_OWNER`` 並使用 ``page_owner=on`` 進行引導。
+
+å•“å‹•åƒæ•¸
+~~~~~~~~
+
+KASANå—到通用 ``panic_on_warn`` å‘½ä»¤è¡Œåƒæ•¸çš„影響。當它被啓用時,KASAN
+在打å°å‡ºéŒ¯èª¤å ±å‘Šå¾Œæœƒä½¿å…§æ ¸ææ…Œã€‚
+
+é»˜èªæƒ…æ³ä¸‹ï¼ŒKASANåªå°ç¬¬ä¸€å€‹ç„¡æ•ˆçš„å…§å­˜è¨ªå•æ‰“å°éŒ¯èª¤å ±å‘Šã€‚使用
+``kasan_multi_shot``,KASANå°æ¯ä¸€å€‹ç„¡æ•ˆçš„訪å•都打å°ä¸€ä»½å ±å‘Šã€‚這會ç¦ç”¨
+了KASAN報告的 ``panic_on_warn``。
+
+å¦å¤–,ç¨ç«‹æ–¼ ``panic_on_warn`` 〠``kasan.fault=`` bootåƒæ•¸å¯ä»¥ç”¨
+ä¾†æŽ§åˆ¶ææ…Œå’Œå ±å‘Šè¡Œçˆ²ã€‚
+
+- ``kasan.fault=report`` 或 ``=panic`` 控制是å¦åªæ‰“å°KASAN report或
+ åŒæ™‚ä½¿å…§æ ¸ææ…Œï¼ˆé»˜èªï¼š ``report`` )。å³ä½¿ ``kasan_multi_shot`` 被
+ å•“ç”¨ï¼Œææ…Œä¹Ÿæœƒç™¼ç”Ÿã€‚
+
+基於軟件和硬件標籤的KASAN模å¼ï¼ˆè¦‹ä¸‹é¢é—œæ–¼å„種模å¼çš„éƒ¨åˆ†ï¼‰æ”¯æŒæ”¹è®Šå †æ£§è·Ÿ
+蹤收集行爲:
+
+- ``kasan.stacktrace=off`` 或 ``=on`` ç¦ç”¨æˆ–啓用分é…和釋放堆棧痕
+ 跡的收集(默èªï¼š ``on`` )。
+
+- ``kasan.stack_ring_size=<number of entries>`` 指定堆棧環的æ¢
+ 目數(默èªï¼š ``32768`` )。
+
+基於硬件標籤的KASANæ¨¡å¼æ˜¯çˆ²äº†åœ¨ç”Ÿç”¢ä¸­ä½œçˆ²ä¸€ç¨®å®‰å…¨ç·©è§£æŽªæ–½ä½¿ç”¨ã€‚因此,它
+支æŒé¡å¤–çš„å•“å‹•åƒæ•¸ï¼Œå…許完全ç¦ç”¨KASAN或控制其功能。
+
+- ``kasan=off`` 或 ``=on`` 控制KASAN是å¦è¢«å•“用(默èªï¼š ``on`` )。
+
+- ``kasan.mode=sync``, ``=async`` or ``=asymm`` 控制KASAN是å¦
+ 被é…ç½®çˆ²åŒæ­¥ã€ç•°æ­¥æˆ–éžå°ç¨±çš„執行模å¼ï¼ˆé»˜èªï¼š ``åŒæ­¥`` )。
+ åŒæ­¥æ¨¡å¼ï¼šç•¶æ¨™ç±¤æª¢æŸ¥ç•°å¸¸ç™¼ç”Ÿæ™‚ï¼Œæœƒç«‹å³æª¢æ¸¬åˆ°ä¸è‰¯è¨ªå•。
+ 異步模å¼ï¼šä¸è‰¯è¨ªå•的檢測是延é²çš„。當標籤檢查異常發生時,信æ¯è¢«å­˜å„²åœ¨ç¡¬
+ ä»¶ä¸­ï¼ˆå°æ–¼arm64來說是在TFSR_EL1寄存器中)。內核週期性地檢查硬件,並\
+ 且åªåœ¨é€™äº›æª¢æŸ¥ä¸­å ±å‘Šæ¨™ç±¤ç•°å¸¸ã€‚
+ éžå°ç¨±æ¨¡å¼ï¼šè®€å–æ™‚åŒæ­¥æª¢æ¸¬ä¸è‰¯è¨ªå•,寫入時異步檢測。
+
+- ``kasan.vmalloc=off`` or ``=on`` ç¦ç”¨æˆ–啓用vmalloc分é…的標記(默èªï¼š ``on`` )。
+
+錯誤報告
+~~~~~~~~
+
+典型的KASAN報告如下所示::
+
+ ==================================================================
+ BUG: KASAN: slab-out-of-bounds in kmalloc_oob_right+0xa8/0xbc [test_kasan]
+ Write of size 1 at addr ffff8801f44ec37b by task insmod/2760
+
+ CPU: 1 PID: 2760 Comm: insmod Not tainted 4.19.0-rc3+ #698
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
+ Call Trace:
+ dump_stack+0x94/0xd8
+ print_address_description+0x73/0x280
+ kasan_report+0x144/0x187
+ __asan_report_store1_noabort+0x17/0x20
+ kmalloc_oob_right+0xa8/0xbc [test_kasan]
+ kmalloc_tests_init+0x16/0x700 [test_kasan]
+ do_one_initcall+0xa5/0x3ae
+ do_init_module+0x1b6/0x547
+ load_module+0x75df/0x8070
+ __do_sys_init_module+0x1c6/0x200
+ __x64_sys_init_module+0x6e/0xb0
+ do_syscall_64+0x9f/0x2c0
+ entry_SYSCALL_64_after_hwframe+0x44/0xa9
+ RIP: 0033:0x7f96443109da
+ RSP: 002b:00007ffcf0b51b08 EFLAGS: 00000202 ORIG_RAX: 00000000000000af
+ RAX: ffffffffffffffda RBX: 000055dc3ee521a0 RCX: 00007f96443109da
+ RDX: 00007f96445cff88 RSI: 0000000000057a50 RDI: 00007f9644992000
+ RBP: 000055dc3ee510b0 R08: 0000000000000003 R09: 0000000000000000
+ R10: 00007f964430cd0a R11: 0000000000000202 R12: 00007f96445cff88
+ R13: 000055dc3ee51090 R14: 0000000000000000 R15: 0000000000000000
+
+ Allocated by task 2760:
+ save_stack+0x43/0xd0
+ kasan_kmalloc+0xa7/0xd0
+ kmem_cache_alloc_trace+0xe1/0x1b0
+ kmalloc_oob_right+0x56/0xbc [test_kasan]
+ kmalloc_tests_init+0x16/0x700 [test_kasan]
+ do_one_initcall+0xa5/0x3ae
+ do_init_module+0x1b6/0x547
+ load_module+0x75df/0x8070
+ __do_sys_init_module+0x1c6/0x200
+ __x64_sys_init_module+0x6e/0xb0
+ do_syscall_64+0x9f/0x2c0
+ entry_SYSCALL_64_after_hwframe+0x44/0xa9
+
+ Freed by task 815:
+ save_stack+0x43/0xd0
+ __kasan_slab_free+0x135/0x190
+ kasan_slab_free+0xe/0x10
+ kfree+0x93/0x1a0
+ umh_complete+0x6a/0xa0
+ call_usermodehelper_exec_async+0x4c3/0x640
+ ret_from_fork+0x35/0x40
+
+ The buggy address belongs to the object at ffff8801f44ec300
+ which belongs to the cache kmalloc-128 of size 128
+ The buggy address is located 123 bytes inside of
+ 128-byte region [ffff8801f44ec300, ffff8801f44ec380)
+ The buggy address belongs to the page:
+ page:ffffea0007d13b00 count:1 mapcount:0 mapping:ffff8801f7001640 index:0x0
+ flags: 0x200000000000100(slab)
+ raw: 0200000000000100 ffffea0007d11dc0 0000001a0000001a ffff8801f7001640
+ raw: 0000000000000000 0000000080150015 00000001ffffffff 0000000000000000
+ page dumped because: kasan: bad access detected
+
+ Memory state around the buggy address:
+ ffff8801f44ec200: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb
+ ffff8801f44ec280: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
+ >ffff8801f44ec300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03
+ ^
+ ffff8801f44ec380: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb
+ ffff8801f44ec400: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
+ ==================================================================
+
+報告標題總çµäº†ç™¼ç”Ÿçš„錯誤類型以åŠå°Žè‡´è©²éŒ¯èª¤çš„訪å•類型。緊隨其後的是錯誤訪å•çš„
+å †æ£§è·Ÿè¹¤ã€æ‰€è¨ªå•內存分é…ä½ç½®çš„å †æ£§è·Ÿè¹¤ï¼ˆå°æ–¼è¨ªå•了slabå°è±¡çš„æƒ…æ³ï¼‰ä»¥åŠå°è±¡
+被釋放的ä½ç½®çš„å †æ£§è·Ÿè¹¤ï¼ˆå°æ–¼è¨ªå•已釋放內存的å•題報告)。接下來是å°è¨ªå•çš„
+slabå°è±¡çš„æè¿°ä»¥åŠé—œæ–¼è¨ªå•的內存é çš„ä¿¡æ¯ã€‚
+
+最後,報告展示了訪å•地å€å‘¨åœçš„內存狀態。在內部,KASANå–®ç¨è·Ÿè¹¤æ¯å€‹å…§å­˜é¡†ç²’çš„
+內存狀態,根據KASAN模å¼åˆ†çˆ²8或16個å°é½Šå­—節。報告的內存狀態部分中的æ¯å€‹æ•¸å­—
+都顯示了åœç¹žè¨ªå•地å€çš„其中一個內存顆粒的狀態。
+
+å°æ–¼é€šç”¨KASAN,æ¯å€‹å…§å­˜é¡†ç²’的大å°çˆ²8個字節。æ¯å€‹é¡†ç²’的狀態被編碼在一個影å­å­—節
+中。這8個字節å¯ä»¥æ˜¯å¯è¨ªå•的,部分訪å•的,已釋放的或æˆçˆ²Redzone的一部分。KASAN
+å°æ¯å€‹å½±å­å­—節使用以下編碼:00è¡¨ç¤ºå°æ‡‰å…§å­˜å€åŸŸçš„æ‰€æœ‰8個字節都å¯ä»¥è¨ªå•;數字N
+(1 <= N <= 7)表示å‰N個字節å¯è¨ªå•,其他(8 - N)個字節ä¸å¯è¨ªå•;任何負值都表示
+ç„¡æ³•è¨ªå•æ•´å€‹8字節。KASAN使用ä¸åŒçš„負值來å€åˆ†ä¸åŒé¡žåž‹çš„ä¸å¯è¨ªå•內存,如redzones
+或已釋放的內存(åƒè¦‹ mm/kasan/kasan.h)。
+
+在上é¢çš„報告中,箭頭指å‘å½±å­å­—節 ``03`` ,表示訪å•çš„åœ°å€æ˜¯éƒ¨åˆ†å¯è¨ªå•的。
+
+å°æ–¼åŸºæ–¼æ¨™ç±¤çš„KASAN模å¼ï¼Œå ±å‘Šæœ€å¾Œçš„部分顯示了訪å•地å€å‘¨åœçš„內存標籤
+(åƒè€ƒ `實施細則`_ 章節)。
+
+請注æ„,KASAN錯誤標題(如 ``slab-out-of-bounds`` 或 ``use-after-free`` )
+æ˜¯å„˜é‡æŽ¥è¿‘çš„:KASANæ ¹æ“šå…¶æ“æœ‰çš„æœ‰é™ä¿¡æ¯æ‰“å°å‡ºæœ€å¯èƒ½çš„錯誤類型。錯誤的實際類型
+å¯èƒ½æœƒæœ‰æ‰€ä¸åŒã€‚
+
+通用KASAN還報告兩個輔助調用堆棧跟蹤。這些堆棧跟蹤指å‘代碼中與å°è±¡äº¤äº’但ä¸ç›´æŽ¥
+出ç¾åœ¨éŒ¯èª¤è¨ªå•堆棧跟蹤中的ä½ç½®ã€‚ç›®å‰ï¼Œé€™åŒ…括 call_rcu() 和排隊的工作隊列。
+
+實施細則
+--------
+
+通用KASAN
+~~~~~~~~~
+
+軟件KASAN模å¼ä½¿ç”¨å½±å­å…§å­˜ä¾†è¨˜éŒ„æ¯å€‹å…§å­˜å­—節是å¦å¯ä»¥å®‰å…¨è¨ªå•,並使用編譯時工具
+åœ¨æ¯æ¬¡å…§å­˜è¨ªå•之剿’入影å­å…§å­˜æª¢æŸ¥ã€‚
+
+通用KASANå°‡1/8的內核內存專用於其影å­å…§å­˜ï¼ˆ16TB以覆蓋x86_64上的128TB),並使用
+具有比例和åç§»é‡çš„直接映射將內存地å€è½‰æ›çˆ²å…¶ç›¸æ‡‰çš„å½±å­åœ°å€ã€‚
+
+這是將地å€è½‰æ›çˆ²å…¶ç›¸æ‡‰å½±å­åœ°å€çš„函數::
+
+ static inline void *kasan_mem_to_shadow(const void *addr)
+ {
+ return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT)
+ + KASAN_SHADOW_OFFSET;
+ }
+
+åœ¨é€™è£ ``KASAN_SHADOW_SCALE_SHIFT = 3`` 。
+
+編譯時工具用於æ’å…¥å…§å­˜è¨ªå•æª¢æŸ¥ã€‚ç·¨è­¯å™¨åœ¨æ¯æ¬¡è¨ªå•大å°çˆ²1ã€2ã€4ã€8或16的內存之å‰
+æ’入函數調用( ``__asan_load*(addr)`` , ``__asan_store*(addr)``)。這些函數通éŽ
+檢查相應的影å­å…§å­˜ä¾†æª¢æŸ¥å…§å­˜è¨ªå•æ˜¯å¦æœ‰æ•ˆã€‚
+
+使用inlineæ’æ¨ï¼Œç·¨è­¯å™¨ä¸é€²è¡Œå‡½æ•¸èª¿ç”¨ï¼Œè€Œæ˜¯ç›´æŽ¥æ’入代碼來檢查影å­å…§å­˜ã€‚æ­¤é¸é …
+顯著地增大了內核體ç©ï¼Œä½†èˆ‡outlineæ’æ¨å…§æ ¸ç›¸æ¯”,它æä¾›äº†x1.1-x2的性能æå‡ã€‚
+
+通用KASAN是唯一一種通éŽéš”離延é²é‡æ–°ä½¿ç”¨å·²é‡‹æ”¾å°è±¡çš„æ¨¡å¼
+(åƒè¦‹ mm/kasan/quarantine.c 以瞭解實ç¾ï¼‰ã€‚
+
+基於軟件標籤的KASAN模å¼
+~~~~~~~~~~~~~~~~~~~~~~~
+
+基於軟件標籤的KASANä½¿ç”¨è»Ÿä»¶å…§å­˜æ¨™ç±¤æ–¹æ³•ä¾†æª¢æŸ¥è¨ªå•æœ‰æ•ˆæ€§ã€‚ç›®å‰åƒ…é‡å°arm64架構實ç¾ã€‚
+
+基於軟件標籤的KASAN使用arm64 CPU的頂部字節忽略(TBI)特性在內核指é‡çš„頂部字節中
+å­˜å„²ä¸€å€‹æŒ‡é‡æ¨™ç±¤ã€‚它使用影å­å…§å­˜ä¾†å­˜å„²èˆ‡æ¯å€‹16字節內存單元相關的內存標籤(因此,
+它將內核內存的1/16專用於影å­å…§å­˜)。
+
+åœ¨æ¯æ¬¡å…§å­˜åˆ†é…時,基於軟件標籤的KASAN都會生æˆä¸€å€‹éš¨æ©Ÿæ¨™ç±¤ï¼Œç”¨é€™å€‹æ¨™ç±¤æ¨™è¨˜åˆ†é…
+的內存,並將相åŒçš„æ¨™ç±¤åµŒå…¥åˆ°è¿”回的指é‡ä¸­ã€‚
+
+基於軟件標籤的KASANä½¿ç”¨ç·¨è­¯æ™‚å·¥å…·åœ¨æ¯æ¬¡å…§å­˜è¨ªå•之剿’å…¥æª¢æŸ¥ã€‚é€™äº›æª¢æŸ¥ç¢ºä¿æ­£åœ¨
+訪å•的內存的標籤等於用於訪å•該內存的指é‡çš„æ¨™ç±¤ã€‚如果標籤ä¸åŒ¹é…,基於軟件標籤
+çš„KASAN會打å°éŒ¯èª¤å ±å‘Šã€‚
+
+基於軟件標籤的KASANä¹Ÿæœ‰å…©ç¨®æ’æ¨æ¨¡å¼ï¼ˆoutline,發出回調來檢查內存訪å•ï¼›inline,
+執行內è¯çš„å½±å­å…§å­˜æª¢æŸ¥ï¼‰ã€‚使用outlineæ’æ¨æ¨¡å¼ï¼Œæœƒå¾žåŸ·è¡Œè¨ªå•檢查的函數打å°éŒ¯èª¤
+報告。使用inlineæ’æ¨ï¼Œç·¨è­¯å™¨æœƒç™¼å‡º ``brk`` 指令,並使用專用的 ``brk`` 處ç†ç¨‹åº
+來打å°éŒ¯èª¤å ±å‘Šã€‚
+
+基於軟件標籤的KASAN使用0xFFä½œçˆ²åŒ¹é…æ‰€æœ‰æŒ‡é‡æ¨™ç±¤ï¼ˆä¸æª¢æŸ¥é€šéŽå¸¶æœ‰0xFFæŒ‡é‡æ¨™ç±¤
+的指é‡é€²è¡Œçš„訪å•)。值0xFEç•¶å‰ä¿ç•™ç”¨æ–¼æ¨™è¨˜å·²é‡‹æ”¾çš„å…§å­˜å€åŸŸã€‚
+
+
+基於硬件標籤的KASAN模å¼
+~~~~~~~~~~~~~~~~~~~~~~~
+
+基於硬件標籤的KASAN在概念上類似於軟件模å¼ï¼Œä½†å®ƒæ˜¯ä½¿ç”¨ç¡¬ä»¶å…§å­˜æ¨™ç±¤ä½œçˆ²æ”¯æŒè€Œ
+䏿˜¯ç·¨è­¯å™¨æ’æ¨å’Œå½±å­å…§å­˜ã€‚
+
+基於硬件標籤的KASANç›®å‰åƒ…é‡å°arm64架構實ç¾ï¼Œä¸¦ä¸”基於ARMv8.5指令集架構中引入
+的arm64內存標記擴展(MTE)和最高字節忽略(TBI)。
+
+特殊的arm64æŒ‡ä»¤ç”¨æ–¼çˆ²æ¯æ¬¡å…§å­˜åˆ†é…指定內存標籤。相åŒçš„æ¨™ç±¤è¢«æŒ‡å®šçµ¦æŒ‡å‘這些分é…
+的指é‡ã€‚åœ¨æ¯æ¬¡å…§å­˜è¨ªå•æ™‚ï¼Œç¡¬ä»¶ç¢ºä¿æ­£åœ¨è¨ªå•的內存的標籤等於用於訪å•該內存的指é‡
+的標籤。如果標籤ä¸åŒ¹é…ï¼Œå‰‡æœƒç”Ÿæˆæ•…障並打å°å ±å‘Šã€‚
+
+基於硬件標籤的KASAN使用0xFFä½œçˆ²åŒ¹é…æ‰€æœ‰æŒ‡é‡æ¨™ç±¤ï¼ˆä¸æª¢æŸ¥é€šéŽå¸¶æœ‰0xFFæŒ‡é‡æ¨™ç±¤çš„
+指é‡é€²è¡Œçš„訪å•)。值0xFEç•¶å‰ä¿ç•™ç”¨æ–¼æ¨™è¨˜å·²é‡‹æ”¾çš„å…§å­˜å€åŸŸã€‚
+
+å¦‚æžœç¡¬ä»¶ä¸æ”¯æŒMTE(ARMv8.5之å‰ï¼‰ï¼Œå‰‡ä¸æœƒå•“用基於硬件標籤的KASAN。在這種情æ³ä¸‹ï¼Œ
+所有KASANå¼•å°Žåƒæ•¸éƒ½å°‡è¢«å¿½ç•¥ã€‚
+
+請注æ„,啓用CONFIG_KASAN_HW_TAGS始終會導致啓用內核中的TBI。å³ä½¿æä¾›äº†
+``kasan.mode=off`` æˆ–ç¡¬ä»¶ä¸æ”¯æŒMTE(但支æŒTBI)。
+
+基於硬件標籤的KASANåªå ±å‘Šç¬¬ä¸€å€‹ç™¼ç¾çš„錯誤。之後,MTE標籤檢查將被ç¦ç”¨ã€‚
+
+å½±å­å…§å­˜
+--------
+
+本節的內容åªé©ç”¨æ–¼è»Ÿä»¶KASAN模å¼ã€‚
+
+內核將內存映射到地å€ç©ºé–“的幾個ä¸åŒéƒ¨åˆ†ã€‚內核虛擬地å€çš„範åœå¾ˆå¤§ï¼šæ²’有足夠的真實
+內存來支æŒå…§æ ¸å¯ä»¥è¨ªå•çš„æ¯å€‹åœ°å€çš„真實影å­å€åŸŸã€‚因此,KASANåªçˆ²åœ°å€ç©ºé–“çš„æŸäº›
+部分映射真實的影å­ã€‚
+
+默èªè¡Œçˆ²
+~~~~~~~~
+
+é»˜èªæƒ…æ³ä¸‹ï¼Œé«”ç³»çµæ§‹åƒ…將實際內存映射到用於線性映射的陰影å€åŸŸï¼ˆä»¥åŠå¯èƒ½çš„å…¶ä»–
+å°å€åŸŸï¼‰ã€‚å°æ–¼æ‰€æœ‰å…¶ä»–å€åŸŸ —— 例如vmallocå’Œvmemmap空間 —— 一個åªè®€é é¢è¢«æ˜ å°„
+到陰影å€åŸŸä¸Šã€‚這個åªè®€çš„å½±å­é é¢è²æ˜Žæ‰€æœ‰å…§å­˜è¨ªå•都是å…許的。
+
+這給模塊帶來了一個å•題:它們ä¸å­˜åœ¨æ–¼ç·šæ€§æ˜ å°„中,而是存在於專用的模塊空間中。
+通éŽé€£æŽ¥æ¨¡å¡Šåˆ†é…器,KASAN臨時映射真實的影å­å…§å­˜ä»¥è¦†è“‹å®ƒå€‘。例如,這å…許檢測
+å°æ¨¡å¡Šå…¨å±€è®Šé‡çš„無效訪å•。
+
+這也造æˆäº†èˆ‡ ``VMAP_STACK`` çš„ä¸å…¼å®¹ï¼šå¦‚æžœå †æ£§ä½æ–¼vmalloc空間中,它將被分é…
+åªè®€é é¢çš„å½±å­å…§å­˜ï¼Œä¸¦ä¸”內核在嘗試爲堆棧變é‡è¨­ç½®å½±å­æ•¸æ“šæ™‚æœƒå‡ºéŒ¯ã€‚
+
+CONFIG_KASAN_VMALLOC
+~~~~~~~~~~~~~~~~~~~~
+
+使用 ``CONFIG_KASAN_VMALLOC`` ,KASANå¯ä»¥ä»¥æ›´å¤§çš„內存使用爲代價覆蓋vmalloc
+空間。目å‰ï¼Œé€™åœ¨arm64ã€x86ã€riscvã€s390å’Œpowerpcä¸Šå—æ”¯æŒã€‚
+
+這通éŽé€£æŽ¥åˆ°vmallocå’Œvmap並動態分é…真實的影å­å…§å­˜ä¾†æ”¯æŒæ˜ å°„。
+
+vmalloc空間中的大多數映射都很å°ï¼Œéœ€è¦ä¸åˆ°ä¸€æ•´é çš„陰影空間。因此,爲æ¯å€‹æ˜ å°„
+分é…一個完整的影å­é é¢å°‡æ˜¯ä¸€ç¨®æµªè²»ã€‚此外,爲了確ä¿ä¸åŒçš„æ˜ å°„使用ä¸åŒçš„å½±å­
+é é¢ï¼Œæ˜ å°„必須與 ``KASAN_GRANULE_SIZE * PAGE_SIZE`` å°é½Šã€‚
+
+相å,KASAN跨多個映射共享後備空間。當vmalloc空間中的映射使用影å­å€åŸŸçš„特定
+é é¢æ™‚,它會分é…一個後備é é¢ã€‚æ­¤é é¢ç¨å¾Œå¯ä»¥ç”±å…¶ä»–vmalloc映射共享。
+
+KASAN連接到vmapåŸºç¤Žæž¶æ§‹ä»¥æ‡¶æ¸…ç†æœªä½¿ç”¨çš„å½±å­å…§å­˜ã€‚
+
+爲了é¿å…äº¤æ›æ˜ å°„的困難,KASANé æ¸¬è¦†è“‹vmalloc空間的陰影å€åŸŸéƒ¨åˆ†å°‡ä¸æœƒè¢«æ—©æœŸ
+的陰影é é¢è¦†è“‹ï¼Œä½†æ˜¯å°‡ä¸æœƒè¢«æ˜ å°„ã€‚é€™å°‡éœ€è¦æ›´æ”¹ç‰¹å®šæ–¼arch的代碼。
+
+這å…許在x86ä¸Šæ”¯æŒ ``VMAP_STACK`` ,並且å¯ä»¥ç°¡åŒ–å°æ²’有固定模塊å€åŸŸçš„æž¶æ§‹çš„æ”¯æŒã€‚
+
+å°æ–¼é–‹ç™¼è€…
+----------
+
+忽略訪å•
+~~~~~~~~
+
+軟件KASAN模å¼ä½¿ç”¨ç·¨è­¯å™¨æ’æ¨ä¾†æ’入有效性檢查。此類檢測å¯èƒ½èˆ‡å…§æ ¸çš„æŸäº›éƒ¨åˆ†
+ä¸å…¼å®¹ï¼Œå› æ­¤éœ€è¦ç¦ç”¨ã€‚
+
+內核的其他部分å¯èƒ½æœƒè¨ªå•已分é…å°è±¡çš„元數據。通常,KASAN會檢測並報告此類訪å•,
+但在æŸäº›æƒ…æ³ä¸‹ï¼ˆä¾‹å¦‚,在內存分é…å™¨ä¸­ï¼‰ï¼Œé€™äº›è¨ªå•æ˜¯æœ‰æ•ˆçš„。
+
+å°æ–¼è»Ÿä»¶KASAN模å¼ï¼Œè¦ç¦ç”¨ç‰¹å®šæ–‡ä»¶æˆ–目錄的檢測,請將 ``KASAN_SANITIZE`` 添加
+到相應的內核Makefile中:
+
+- å°æ–¼å–®å€‹æ–‡ä»¶(例如,main.o)::
+
+ KASAN_SANITIZE_main.o := n
+
+- å°æ–¼ä¸€å€‹ç›®éŒ„下的所有文件::
+
+ KASAN_SANITIZE := n
+
+å°æ–¼è»Ÿä»¶KASAN模å¼ï¼Œè¦åœ¨æ¯å€‹å‡½æ•¸çš„基礎上ç¦ç”¨æª¢æ¸¬ï¼Œè«‹ä½¿ç”¨KASAN特定的
+``__no_sanitize_address`` 函數屬性或通用的 ``noinstr`` 。
+
+請注æ„,ç¦ç”¨ç·¨è­¯å™¨æ’æ¨ï¼ˆåŸºæ–¼æ¯å€‹æ–‡ä»¶æˆ–æ¯å€‹å‡½æ•¸ï¼‰æœƒä½¿KASAN忽略在軟件KASAN模å¼
+的代碼中直接發生的訪å•ã€‚ç•¶è¨ªå•æ˜¯é–“接發生的(通éŽèª¿ç”¨æª¢æ¸¬å‡½æ•¸ï¼‰æˆ–使用沒有編譯器
+æ’æ¨çš„åŸºæ–¼ç¡¬ä»¶æ¨™ç±¤çš„æ¨¡å¼æ™‚,它沒有幫助。
+
+å°æ–¼è»Ÿä»¶KASAN模å¼ï¼Œè¦åœ¨ç•¶å‰ä»»å‹™çš„一部分內核代碼中ç¦ç”¨KASAN報告,請使用
+``kasan_disable_current()``/``kasan_enable_current()`` 部分註釋這部分代碼。
+這也會ç¦ç”¨é€šéŽå‡½æ•¸èª¿ç”¨ç™¼ç”Ÿçš„間接訪å•的報告。
+
+å°æ–¼åŸºæ–¼æ¨™ç±¤çš„KASAN模å¼ï¼Œè¦ç¦ç”¨è¨ªå•檢查,請使用 ``kasan_reset_tag()`` 或
+``page_kasan_tag_reset()`` 。請注æ„ï¼Œé€šéŽ ``page_kasan_tag_reset()``
+臨時ç¦ç”¨è¨ªå•檢查需è¦é€šéŽ ``page_kasan_tag`` / ``page_kasan_tag_set`` ä¿
+存和æ¢å¾©æ¯é KASAN標籤。
+
+測試
+~~~~
+
+有一些KASAN測試å¯ä»¥é©—è­‰KASANæ˜¯å¦æ­£å¸¸å·¥ä½œä¸¦å¯ä»¥æª¢æ¸¬æŸäº›é¡žåž‹çš„å…§å­˜æå£žã€‚
+測試由兩部分組æˆ:
+
+1. 與KUnit測試框架集æˆçš„æ¸¬è©¦ã€‚使用 ``CONFIG_KASAN_KUNIT_TEST`` 啓用。
+這些測試å¯ä»¥é€šéŽå¹¾ç¨®ä¸åŒçš„æ–¹å¼è‡ªå‹•é‹è¡Œå’Œéƒ¨åˆ†é©—證;請åƒé–±ä¸‹é¢çš„說明。
+
+2. 與KUnitä¸å…¼å®¹çš„æ¸¬è©¦ã€‚使用 ``CONFIG_KASAN_MODULE_TEST`` 啓用並且åªèƒ½ä½œçˆ²æ¨¡å¡Š
+é‹è¡Œã€‚這些測試åªèƒ½é€šéŽåŠ è¼‰å…§æ ¸æ¨¡å¡Šä¸¦æª¢æŸ¥å…§æ ¸æ—¥èªŒä»¥ç²å–KASAN報告來手動驗證。
+
+如果檢測到錯誤,æ¯å€‹KUnit兼容的KASAN測試都會打å°å¤šå€‹KASAN報告之一,然後測試打å°
+其編號和狀態。
+
+當測試通éŽ::
+
+ ok 28 - kmalloc_double_kzfree
+
+當由於 ``kmalloc`` 失敗而導致測試失敗時::
+
+ # kmalloc_large_oob_right: ASSERTION FAILED at lib/test_kasan.c:163
+ Expected ptr is not null, but is
+ not ok 4 - kmalloc_large_oob_right
+
+當由於缺少KASAN報告而導致測試失敗時::
+
+ # kmalloc_double_kzfree: EXPECTATION FAILED at lib/test_kasan.c:974
+ KASAN failure expected in "kfree_sensitive(ptr)", but none occurred
+ not ok 44 - kmalloc_double_kzfree
+
+
+æœ€å¾Œæ‰“å°æ‰€æœ‰KASAN測試的累ç©ç‹€æ…‹ã€‚æˆåŠŸ::
+
+ ok 1 - kasan
+
+或者,如果其中一項測試失敗::
+
+ not ok 1 - kasan
+
+有幾種方法å¯ä»¥é‹è¡Œèˆ‡KUnit兼容的KASAN測試。
+
+1. å¯åŠ è¼‰æ¨¡å¡Š
+
+ 啓用 ``CONFIG_KUNIT`` 後,KASAN-KUnit測試å¯ä»¥æ§‹å»ºçˆ²å¯åŠ è¼‰æ¨¡å¡Šï¼Œä¸¦é€šéŽä½¿ç”¨
+ ``insmod`` 或 ``modprobe`` 加載 ``test_kasan.ko`` 來é‹è¡Œã€‚
+
+2. å…§ç½®
+
+ 通éŽå…§ç½® ``CONFIG_KUNIT`` ,也å¯ä»¥å…§ç½®KASAN-KUnit測試。在這種情æ³ä¸‹ï¼Œ
+ 測試將在啓動時作爲後期åˆå§‹åŒ–調用é‹è¡Œã€‚
+
+3. 使用kunit_tool
+
+ 通éŽå…§ç½® ``CONFIG_KUNIT`` å’Œ ``CONFIG_KASAN_KUNIT_TEST`` ,還å¯ä»¥ä½¿ç”¨
+ ``kunit_tool`` ä»¥æ›´æ˜“è®€çš„æ–¹å¼æŸ¥çœ‹KUnitæ¸¬è©¦çµæžœã€‚這䏿œƒæ‰“å°é€šéŽæ¸¬è©¦
+ çš„KASAN報告。有關 ``kunit_tool`` 更多最新信æ¯ï¼Œè«‹åƒé–±
+ `KUnit文檔 <https://www.kernel.org/doc/html/latest/dev-tools/kunit/index.html>`_ 。
+
+.. _KUnit: https://www.kernel.org/doc/html/latest/dev-tools/kunit/index.html
+
diff --git a/Documentation/translations/zh_TW/sparse.txt b/Documentation/translations/zh_TW/dev-tools/sparse.rst
index 35d3d1d748e6..11d64709d6a4 100644
--- a/Documentation/translations/zh_TW/sparse.txt
+++ b/Documentation/translations/zh_TW/dev-tools/sparse.rst
@@ -27,7 +27,7 @@ Copyright 2006 Bob Copeland <me@bobcopeland.com>
使用 sparse 工具åšé¡žåž‹æª¢æŸ¥
~~~~~~~~~~~~~~~~~~~~~~~~~~
-"__bitwise" 是一種類型屬性,所以你應該這樣使用它:
+"__bitwise" 是一種類型屬性,所以你應該這樣使用它::
typedef int __bitwise pm_request_t;
@@ -47,7 +47,7 @@ Copyright 2006 Bob Copeland <me@bobcopeland.com>
å¦ç™½ä¾†èªªï¼Œä½ ä¸¦ä¸éœ€è¦ä½¿ç”¨æžšèˆ‰é¡žåž‹ã€‚上é¢é‚£äº›å¯¦éš›éƒ½å¯ä»¥æ¿ƒç¸®æˆä¸€å€‹ç‰¹æ®Šçš„"int
__bitwise"類型。
-所以更簡單的辦法åªè¦é€™æ¨£åšï¼š
+所以更簡單的辦法åªè¦é€™æ¨£åš::
typedef int __bitwise pm_request_t;
diff --git a/Documentation/translations/zh_TW/dev-tools/testing-overview.rst b/Documentation/translations/zh_TW/dev-tools/testing-overview.rst
new file mode 100644
index 000000000000..fb3f691f46c3
--- /dev/null
+++ b/Documentation/translations/zh_TW/dev-tools/testing-overview.rst
@@ -0,0 +1,162 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/dev-tools/testing-overview.rst
+:Translator: 胡皓文 Hu Haowen <src.res.211@gmail.com>
+
+============
+內核測試指å—
+============
+
+有許多ä¸åŒçš„工具å¯ä»¥ç”¨æ–¼æ¸¬è©¦Linux內核,因此瞭解什麼時候使用它們å¯èƒ½
+很困難。本文檔粗略概述了它們之間的å€åˆ¥ï¼Œä¸¦é—¡é‡‹äº†å®ƒå€‘是怎樣糅åˆåœ¨ä¸€èµ·
+的。
+
+編寫和é‹è¡Œæ¸¬è©¦
+==============
+
+大多數內核測試都是用kselftest或KUnit框架之一編寫的。它們都讓é‹è¡Œæ¸¬è©¦
+更加簡化,併爲編寫新測試æä¾›å¹«åŠ©ã€‚
+
+如果你想驗證內核的行爲——尤其是內核的特定部分——那你就è¦ä½¿ç”¨kUnit或
+kselftest。
+
+KUnitå’Œkselftestçš„å€åˆ¥
+----------------------
+
+.. note::
+ ç”±æ–¼æœ¬æ–‡æ®µä¸­éƒ¨åˆ†è¡“èªžå°šç„¡è¼ƒå¥½çš„å°æ‡‰ä¸­æ–‡é‡‹ç¾©ï¼Œå¯èƒ½å°Žè‡´èˆ‡åŽŸæ–‡å«ç¾©
+ 存在些許差異,因此建議讀者çµåˆåŽŸæ–‡
+ (Documentation/dev-tools/testing-overview.rst)輔助閱讀。
+ 如å°éƒ¨åˆ†ç¿»è­¯æœ‰ç•°è­°æˆ–有更好的翻譯æ„見,歡迎è¯ç¹«è­¯è€…進行修訂。
+
+KUnit(Documentation/dev-tools/kunit/index.rstï¼‰æ˜¯ç”¨æ–¼â€œç™½ç®±â€æ¸¬
+試的一個完整的內核內部系統:因爲測試代碼是內核的一部分,所以它能夠訪
+å•用戶空間ä¸èƒ½è¨ªå•åˆ°çš„å…§éƒ¨çµæ§‹å’ŒåŠŸèƒ½ã€‚
+
+因此,KUnit測試最好é‡å°å…§æ ¸ä¸­è¼ƒå°çš„ã€è‡ªåŒ…å«çš„部分,以便能夠ç¨ç«‹åœ°æ¸¬
+è©¦ã€‚â€œå–®å…ƒâ€æ¸¬è©¦çš„æ¦‚念亦是如此。
+
+比如,一個KUnit測試å¯èƒ½æ¸¬è©¦ä¸€å€‹å–®ç¨çš„內核功能(甚至通éŽä¸€å€‹å‡½æ•¸æ¸¬è©¦
+ä¸€å€‹å–®ä¸€çš„ä»£ç¢¼è·¯å¾‘ï¼Œä¾‹å¦‚ä¸€å€‹éŒ¯èª¤è™•ç†æ¡ˆä¾‹ï¼‰ï¼Œè€Œä¸æ˜¯æ•´å€‹åœ°æ¸¬è©¦ä¸€å€‹ç‰¹æ€§ã€‚
+
+這也使得KUnit測試構建和é‹è¡Œéžå¸¸åœ°å¿«ï¼Œå¾žè€Œèƒ½å¤ ä½œçˆ²é–‹ç™¼æµç¨‹çš„一部分被
+é »ç¹åœ°é‹è¡Œã€‚
+
+有關更詳細的介紹,請åƒé–±KUnit測試代碼風格指å—
+Documentation/dev-tools/kunit/style.rst
+
+kselftest(Documentation/dev-tools/kselftest.rst),相å°ä¾†èªªï¼Œå¤§é‡ç”¨
+於用戶空間,並且通常測試用戶空間的腳本或程åºã€‚
+
+é€™ä½¿å¾—ç·¨å¯«è¤‡é›œçš„æ¸¬è©¦ï¼Œæˆ–è€…éœ€è¦æ“作更多全局系統狀態的測試更加容易(諸
+如生æˆé€²ç¨‹ä¹‹é¡žï¼‰ã€‚然而,從kselftest直接調用內核函數是ä¸è¡Œçš„。這也就
+æ„味ç€åªæœ‰é€šéŽæŸç¨®æ–¹å¼ï¼ˆå¦‚系統調用ã€é©…å‹•è¨­å‚™ã€æ–‡ä»¶ç³»çµ±ç­‰ï¼‰å°Žå‡ºåˆ°äº†ç”¨
+戶空間的內核功能æ‰èƒ½ä½¿ç”¨kselftest來測試。爲此,有些測試包å«äº†ä¸€å€‹ä¼´
+生的內核模塊用於導出更多的信æ¯å’ŒåŠŸèƒ½ã€‚ä¸éŽï¼Œå°æ–¼åŸºæœ¬ä¸Šæˆ–者完全在內核
+中é‹è¡Œçš„æ¸¬è©¦ï¼ŒKUnitå¯èƒ½æ˜¯æ›´ä½³å·¥å…·ã€‚
+
+kselftest也因此éžå¸¸é©åˆæ–¼å…¨éƒ¨åŠŸèƒ½çš„æ¸¬è©¦ï¼Œå› çˆ²é€™äº›åŠŸèƒ½æœƒå°‡æŽ¥å£æš´éœ²åˆ°
+ç”¨æˆ¶ç©ºé–“ï¼Œå¾žè€Œèƒ½å¤ è¢«æ¸¬è©¦ï¼Œè€Œä¸æ˜¯å±•ç¾å¯¦ç¾ç´°ç¯€ã€‚“systemâ€æ¸¬è©¦å’Œ
+“end-to-endâ€æ¸¬è©¦äº¦æ˜¯å¦‚此。
+
+比如,一個新的系統調用應該伴隨有新的kselftest測試。
+
+代碼覆蓋率工具
+==============
+
+支æŒå…©ç¨®ä¸åŒä»£ç¢¼ä¹‹é–“的覆蓋率測é‡å·¥å…·ã€‚它們å¯ä»¥ç”¨ä¾†é©—證一項測試執行的
+確切函數或代碼行。這有助於決定內核被測試了多少,或用來查找åˆé©çš„æ¸¬è©¦
+中沒有覆蓋到的極端情æ³ã€‚
+
+Documentation/translations/zh_CN/dev-tools/gcov.rst 是GCC的覆蓋率測試
+工具,能用於ç²å–內核的全局或æ¯å€‹æ¨¡å¡Šçš„覆蓋率。與KCOVä¸åŒçš„æ˜¯ï¼Œé€™å€‹å·¥å…·
+ä¸è¨˜éŒ„æ¯å€‹ä»»å‹™çš„覆蓋率。覆蓋率數據å¯ä»¥é€šéŽdebugfs讀å–,並通éŽå¸¸è¦çš„
+gcov工具進行解釋。
+
+Documentation/dev-tools/kcov.rst 是能夠構建在內核之中,用於在æ¯å€‹ä»»å‹™
+çš„å±¤é¢æ•æ‰è¦†è“‹çŽ‡çš„ä¸€å€‹åŠŸèƒ½ã€‚å› æ­¤ï¼Œå®ƒå°æ–¼æ¨¡ç³Šæ¸¬è©¦å’Œé—œæ–¼ä»£ç¢¼åŸ·è¡ŒæœŸé–“ä¿¡
+æ¯çš„其它情æ³éžå¸¸æœ‰ç”¨ï¼Œæ¯”如在一個單一系統調用è£ä½¿ç”¨å®ƒå°±å¾ˆæœ‰ç”¨ã€‚
+
+動態分æžå·¥å…·
+============
+
+內核也支æŒè¨±å¤šå‹•態分æžå·¥å…·ï¼Œç”¨ä»¥æª¢æ¸¬æ­£åœ¨é‹è¡Œçš„內核中出ç¾çš„多種類型的
+å•題。這些工具通常æ¯å€‹åŽ»å°‹æ‰¾ä¸€é¡žä¸åŒçš„ç¼ºé™·ï¼Œæ¯”å¦‚éžæ³•內存訪å•,數據競
+爭等併發å•題,或整型溢出等其他未定義行爲。
+
+如下所示:
+
+* kmemleak檢測å¯èƒ½çš„內存泄æ¼ã€‚åƒé–±
+ Documentation/dev-tools/kmemleak.rst
+* KASANæª¢æ¸¬éžæ³•內存訪å•,如數組越界和釋放後é‡ç”¨ï¼ˆUAF)。åƒé–±
+ Documentation/dev-tools/kasan.rst
+* UBSAN檢測C標準中未定義的行爲,如整型溢出。åƒé–±
+ Documentation/dev-tools/ubsan.rst
+* KCSAN檢測數據競爭。åƒé–± Documentation/dev-tools/kcsan.rst
+* KFENCE是一個低開銷的內存å•題檢測器,比KASANæ›´å¿«ä¸”èƒ½è¢«ç”¨æ–¼æ‰¹é‡æ§‹å»ºã€‚
+ åƒé–± Documentation/dev-tools/kfence.rst
+* lockdep是一個鎖定正確性檢測器。åƒé–±
+ Documentation/locking/lockdep-design.rst
+* 除此以外,在內核中還有一些其它的調試工具,大多數能在
+ lib/Kconfig.debug 中找到。
+
+é€™äº›å·¥å…·å‚¾å‘æ–¼å°å…§æ ¸é€²è¡Œæ•´é«”測試,並且ä¸åƒkselftestå’ŒKUnit一樣“傳éžâ€ã€‚
+它們å¯ä»¥é€šéŽåœ¨å•“用這些工具時é‹è¡Œå…§æ ¸æ¸¬è©¦ä»¥èˆ‡kselftest或KUnitçµåˆèµ·ä¾†ï¼š
+之後你就能確ä¿é€™äº›éŒ¯èª¤åœ¨æ¸¬è©¦éŽç¨‹ä¸­éƒ½ä¸æœƒç™¼ç”Ÿäº†ã€‚
+
+一些工具與KUnitå’Œkselftest集æˆï¼Œä¸¦ä¸”在檢測到å•題時會自動打斷測試。
+
+éœæ…‹åˆ†æžå·¥å…·
+============
+
+除了測試é‹è¡Œä¸­çš„內核,我們還å¯ä»¥ä½¿ç”¨**éœæ…‹åˆ†æž**工具直接分æžå…§æ ¸çš„æºä»£
+碼(**在編譯時**)。內核中常用的工具å…許人們檢查整個æºä»£ç¢¼æ¨¹æˆ–其中的特
+定文件。它們使得在開發éŽç¨‹ä¸­æ›´å®¹æ˜“發ç¾å’Œä¿®å¾©å•題。
+
+ Sparseå¯ä»¥é€šéŽåŸ·è¡Œé¡žåž‹æª¢æŸ¥ã€éŽ–æª¢æŸ¥ã€å€¼ç¯„åœæª¢æŸ¥ä¾†å¹«åŠ©æ¸¬è©¦å…§æ ¸ï¼Œæ­¤å¤–é‚„
+ å¯ä»¥åœ¨æª¢æŸ¥ä»£ç¢¼æ™‚報告å„種錯誤和警告。關於如何使用它的細節,請åƒé–±
+ Documentation/translations/zh_CN/dev-tools/sparse.rst。
+
+ Smatch擴展了Sparse,並æä¾›äº†å°ç·¨ç¨‹é‚輯錯誤的é¡å¤–檢查,如開關語å¥ä¸­
+ 缺少斷點,錯誤檢查中未使用的返回值,忘記在錯誤路徑的返回中設置錯誤代
+ 碼等。Smatch也有é‡å°æ›´åš´é‡å•題的測試,如整數溢出ã€ç©ºæŒ‡é‡è§£é™¤å¼•用和內
+ 存泄æ¼ã€‚見項目é é¢http://smatch.sourceforge.net/。
+
+ Coccinelle是我們å¯ä»¥ä½¿ç”¨çš„å¦ä¸€å€‹éœæ…‹åˆ†æžå™¨ã€‚Coccinelle經常被用來
+ 幫助æºä»£ç¢¼çš„釿§‹å’Œä¸¦è¡Œæ¼”化,但它也å¯ä»¥å¹«åŠ©é¿å…常見代碼模å¼ä¸­å‡ºç¾çš„æŸ
+ 些錯誤。å¯ç”¨çš„æ¸¬è©¦é¡žåž‹åŒ…括API測試ã€å…§æ ¸è¿­ä»£å™¨çš„æ­£ç¢ºä½¿ç”¨æ¸¬è©¦ã€è‡ªç”±æ“
+ 作的åˆç†æ€§æª¢æŸ¥ã€éŽ–å®šè¡Œçˆ²çš„åˆ†æžï¼Œä»¥åŠå·²çŸ¥çš„æœ‰åŠ©æ–¼ä¿æŒå…§æ ¸ä½¿ç”¨ä¸€è‡´æ€§çš„
+ 進一步測試。詳情請見Documentation/dev-tools/coccinelle.rst。
+
+ ä¸éŽè¦æ³¨æ„çš„æ˜¯ï¼Œéœæ…‹åˆ†æžå·¥å…·å­˜åœ¨**å‡é™½æ€§**çš„å•題。在試圖修復錯誤和警
+ 告之å‰ï¼Œéœ€è¦ä»”細評估它們。
+
+何時使用Sparse和Smatch
+----------------------
+
+Sparseåšé¡žåž‹æª¢æŸ¥ï¼Œä¾‹å¦‚驗證註釋的變é‡ä¸æœƒå°Žè‡´ç„¡ç¬¦è™Ÿçš„錯誤,檢測
+``__user`` 指é‡ä½¿ç”¨ä¸ç•¶çš„地方,以åŠåˆ†æžç¬¦è™Ÿåˆå§‹åŒ–器的兼容性。
+
+Smatch進行æµç¨‹åˆ†æžï¼Œå¦‚æžœå…許建立函數數據庫,它還會進行跨函數分æžã€‚
+Smatch試圖回答一些å•題,比如這個緩è¡å€æ˜¯åœ¨å“ªè£åˆ†é…的?它有多大?這
+個索引å¯ä»¥ç”±ç”¨æˆ¶æŽ§åˆ¶å—Žï¼Ÿé€™å€‹è®Šé‡æ¯”那個變é‡å¤§å—Žï¼Ÿ
+
+一般來說,在Smatch中寫檢查比在Sparse中寫檢查è¦å®¹æ˜“。儘管如此,
+Sparseå’ŒSmatch的檢查還是有一些é‡ç–Šçš„地方。
+
+Smatch和Coccinelle的強項
+------------------------
+
+Coccinelleå¯èƒ½æ˜¯æœ€å®¹æ˜“寫檢查的。它在é è™•ç†å™¨ä¹‹å‰å·¥ä½œï¼Œæ‰€ä»¥ç”¨Coccinelle
+檢查å®ä¸­çš„錯誤更容易。Coccinelle還能爲你創建補ä¸ï¼Œé€™æ˜¯å…¶ä»–工具無法åšåˆ°çš„。
+
+例如,用Coccinelleä½ å¯ä»¥å¾ž ``kmalloc_array(x, size, GFP_KERNEL)``
+到 ``kmalloc_array(x, size, GFP_KERNEL)`` é€²è¡Œå¤§è¦æ¨¡è½‰æ›ï¼Œé€™çœŸçš„很
+æœ‰ç”¨ã€‚å¦‚æžœä½ åªæ˜¯å‰µå»ºä¸€å€‹Smatch警告,並試圖把轉æ›çš„工作推給維護者,他們會很
+惱ç«ã€‚ä½ å°‡ä¸å¾—ä¸çˆ²æ¯å€‹è­¦å‘Šçˆ­è«–是å¦çœŸçš„å¯ä»¥æº¢å‡ºã€‚
+
+Coccinelleä¸å°è®Šé‡å€¼é€²è¡Œåˆ†æžï¼Œè€Œé€™æ­£æ˜¯Smatch的強項。å¦ä¸€æ–¹é¢ï¼ŒCoccinelle
+å…許你用簡單的方法åšç°¡å–®çš„事情。
+
diff --git a/Documentation/translations/zh_TW/filesystems/debugfs.rst b/Documentation/translations/zh_TW/filesystems/debugfs.rst
index ddf801943c92..78e2e08af95e 100644
--- a/Documentation/translations/zh_TW/filesystems/debugfs.rst
+++ b/Documentation/translations/zh_TW/filesystems/debugfs.rst
@@ -2,7 +2,7 @@
.. include:: ../disclaimer-zh_TW.rst
-:Original: :doc:`../../../filesystems/debugfs`
+:Original: Documentation/filesystems/debugfs.rst
=======
Debugfs
@@ -11,20 +11,19 @@ Debugfs
譯者
::
- ä¸­æ–‡ç‰ˆç¶­è­·è€…ï¼šç¾…æ¥šæˆ Chucheng Luo <luochucheng@vivo.com>
- ä¸­æ–‡ç‰ˆç¿»è­¯è€…ï¼šç¾…æ¥šæˆ Chucheng Luo <luochucheng@vivo.com>
- 中文版校譯者: ç¾…æ¥šæˆ Chucheng Luo <luochucheng@vivo.com>
+ 中文版維護者: ç¾…æ¥šæˆ Chucheng Luo <luochucheng@vivo.com>
+ 中文版翻譯者: ç¾…æ¥šæˆ Chucheng Luo <luochucheng@vivo.com>
+ 中文版校譯者: ç¾…æ¥šæˆ Chucheng Luo <luochucheng@vivo.com>
ç¹é«”中文版校譯者: 胡皓文 Hu Haowen <src.res.211@gmail.com>
版權所有2020 ç¾…æ¥šæˆ <luochucheng@vivo.com>
-版權所有2021 胡皓文 Hu Haowen <src.res.211@gmail.com>
Debugfs是內核開發人員在用戶空間ç²å–ä¿¡æ¯çš„簡單方法。與/procä¸åŒï¼Œprocåªæä¾›é€²ç¨‹
-ä¿¡æ¯ã€‚也ä¸åƒsysfs,具有嚴格的「æ¯å€‹æ–‡ä»¶ä¸€å€‹å€¼ã€Œçš„è¦å‰‡ã€‚debugfs根本沒有è¦å‰‡,開發
-人員å¯ä»¥åœ¨é€™è£¡æ”¾ç½®ä»–們想è¦çš„任何信æ¯ã€‚debugfs文件系統也ä¸èƒ½ç”¨ä½œç©©å®šçš„ABI接å£ã€‚
+ä¿¡æ¯ã€‚也ä¸åƒsysfs,具有嚴格的“æ¯å€‹æ–‡ä»¶ä¸€å€‹å€¼â€œçš„è¦å‰‡ã€‚debugfs根本沒有è¦å‰‡,開發
+人員å¯ä»¥åœ¨é€™è£æ”¾ç½®ä»–們想è¦çš„任何信æ¯ã€‚debugfs文件系統也ä¸èƒ½ç”¨ä½œç©©å®šçš„ABI接å£ã€‚
從ç†è«–上講,debugfs導出文件的時候沒有任何約æŸã€‚但是[1]實際情æ³ä¸¦ä¸ç¸½æ˜¯é‚£éº¼
簡單。å³ä½¿æ˜¯debugfs接å£ï¼Œä¹Ÿæœ€å¥½æ ¹æ“šéœ€è¦é€²è¡Œè¨­è¨ˆ,並儘é‡ä¿æŒæŽ¥å£ä¸è®Šã€‚
@@ -34,8 +33,8 @@ Debugfs通常使用以下命令安è£::
mount -t debugfs none /sys/kernel/debug
(或等效的/etc/fstab行)。
-debugfs根目錄默èªåƒ…å¯ç”±root用戶訪å•ã€‚è¦æ›´æ”¹å°æ–‡ä»¶æ¨¹çš„訪å•,請使用「 uidã€ï¼Œã€Œ gidã€
-和「 modeã€æŽ›è¼‰é¸é …。請注æ„,debugfs API僅按照GPLå”議導出到模塊。
+debugfs根目錄默èªåƒ…å¯ç”±root用戶訪å•ã€‚è¦æ›´æ”¹å°æ–‡ä»¶æ¨¹çš„訪å•,請使用“ uidâ€ï¼Œâ€œ gidâ€
+和“ modeâ€æŽ›è¼‰é¸é …。請注æ„,debugfs API僅按照GPLå”議導出到模塊。
使用debugfs的代碼應包å«<linux/debugfs.h>。然後,首先是創建至少一個目錄來ä¿å­˜
一組debugfs文件::
@@ -54,8 +53,8 @@ debugfs根目錄默èªåƒ…å¯ç”±root用戶訪å•ã€‚è¦æ›´æ”¹å°æ–‡ä»¶æ¨¹çš„訪å•
struct dentry *parent, void *data,
const struct file_operations *fops);
-在這裡,name是è¦å‰µå»ºçš„æ–‡ä»¶çš„å稱,modeæè¿°äº†è¨ªå•文件應具有的權é™ï¼Œparent指å‘
-應該ä¿å­˜æ–‡ä»¶çš„目錄,data將存儲在產生的inodeçµæ§‹é«”çš„i_private欄ä½ä¸­ï¼Œè€Œfops是
+在這è£ï¼Œname是è¦å‰µå»ºçš„æ–‡ä»¶çš„å稱,modeæè¿°äº†è¨ªå•文件應具有的權é™ï¼Œparent指å‘
+應該ä¿å­˜æ–‡ä»¶çš„目錄,data將存儲在產生的inodeçµæ§‹é«”çš„i_private字段中,而fops是
一組文件æ“ä½œå‡½æ•¸ï¼Œé€™äº›å‡½æ•¸ä¸­å¯¦ç¾æ–‡ä»¶æ“作的具體行爲。至少,read()和/或
write()æ“作應æä¾›ï¼›å…¶ä»–å¯ä»¥æ ¹æ“šéœ€è¦åŒ…æ‹¬åœ¨å…§ã€‚åŒæ¨£çš„,返回值將是指å‘創建文件
çš„dentry指é‡ï¼ŒéŒ¯èª¤æ™‚返回ERR_PTR(-ERRORï¼‰ï¼Œç³»çµ±ä¸æ”¯æŒdebugfs時返回值爲ERR_PTR
@@ -81,7 +80,7 @@ file_size是åˆå§‹æ–‡ä»¶å¤§å°ã€‚å…¶ä»–åƒæ•¸è·Ÿå‡½æ•¸debugfs_create_file的相å
struct dentry *parent, u64 *value);
這些文件支æŒè®€å–和寫入給定值。如果æŸå€‹æ–‡ä»¶ä¸æ”¯æŒå¯«å…¥ï¼Œåªéœ€æ ¹æ“šéœ€è¦è¨­ç½®mode
-åƒæ•¸ä½ã€‚這些文件中的值以å進ä½è¡¨ç¤ºï¼›å¦‚果需è¦ä½¿ç”¨å六進ä½ï¼Œå¯ä»¥ä½¿ç”¨ä»¥ä¸‹å‡½æ•¸
+åƒæ•¸ä½ã€‚這些文件中的值以å進制表示;如果需è¦ä½¿ç”¨å六進制,å¯ä»¥ä½¿ç”¨ä»¥ä¸‹å‡½æ•¸
替代::
void debugfs_create_x8(const char *name, umode_t mode,
@@ -93,7 +92,7 @@ file_size是åˆå§‹æ–‡ä»¶å¤§å°ã€‚å…¶ä»–åƒæ•¸è·Ÿå‡½æ•¸debugfs_create_file的相å
void debugfs_create_x64(const char *name, umode_t mode,
struct dentry *parent, u64 *value);
-é€™äº›åŠŸèƒ½åªæœ‰åœ¨é–‹ç™¼äººå“¡çŸ¥é“導出值的大å°çš„æ™‚å€™æ‰æœ‰ç”¨ã€‚æŸäº›æ•¸æ“šé¡žåž‹åœ¨ä¸åŒçš„æž¶æ§‹ä¸Š
+é€™äº›åŠŸèƒ½åªæœ‰åœ¨é–‹ç™¼äººå“¡çŸ¥é“導出值的大å°çš„æ™‚候纔有用。æŸäº›æ•¸æ“šé¡žåž‹åœ¨ä¸åŒçš„æž¶æ§‹ä¸Š
有ä¸åŒçš„寬度,這樣會使情æ³è®Šå¾—有些複雜。在這種特殊情æ³ä¸‹å¯ä»¥ä½¿ç”¨ä»¥ä¸‹å‡½æ•¸::
void debugfs_create_size_t(const char *name, umode_t mode,
@@ -101,7 +100,7 @@ file_size是åˆå§‹æ–‡ä»¶å¤§å°ã€‚å…¶ä»–åƒæ•¸è·Ÿå‡½æ•¸debugfs_create_file的相å
ä¸å‡ºæ‰€æ–™ï¼Œæ­¤å‡½æ•¸å°‡å‰µå»ºä¸€å€‹debugfs文件來表示類型爲size_t的變é‡ã€‚
-åŒæ¨£åœ°ï¼Œä¹Ÿæœ‰å°Žå‡ºç„¡ç¬¦è™Ÿé•·æ•´åž‹è®Šé‡çš„函數,分別以å進ä½å’Œå六進ä½è¡¨ç¤ºå¦‚下::
+åŒæ¨£åœ°ï¼Œä¹Ÿæœ‰å°Žå‡ºç„¡ç¬¦è™Ÿé•·æ•´åž‹è®Šé‡çš„函數,分別以å進制和å六進制表示如下::
struct dentry *debugfs_create_ulong(const char *name, umode_t mode,
struct dentry *parent,
@@ -125,7 +124,7 @@ file_size是åˆå§‹æ–‡ä»¶å¤§å°ã€‚å…¶ä»–åƒæ•¸è·Ÿå‡½æ•¸debugfs_create_file的相å
è®€å–æ­¤æ–‡ä»¶å°‡ç²å¾—atomic_t值,寫入此文件將設置atomic_t值。
-å¦ä¸€å€‹é¸æ“‡æ˜¯é€šéŽä»¥ä¸‹çµæ§‹é«”和函數導出一個任æ„äºŒé€²ä½æ•¸æ“šå¡Š::
+å¦ä¸€å€‹é¸æ“‡æ˜¯é€šéŽä»¥ä¸‹çµæ§‹é«”和函數導出一個任æ„二進制數據塊::
struct debugfs_blob_wrapper {
void *data;
@@ -136,10 +135,10 @@ file_size是åˆå§‹æ–‡ä»¶å¤§å°ã€‚å…¶ä»–åƒæ•¸è·Ÿå‡½æ•¸debugfs_create_file的相å
struct dentry *parent,
struct debugfs_blob_wrapper *blob);
-è®€å–æ­¤æ–‡ä»¶å°‡è¿”å›žç”±æŒ‡é‡æŒ‡å‘debugfs_blob_wrapperçµæ§‹é«”的數據。一些驅動使用「blobsã€
-ä½œçˆ²ä¸€ç¨®è¿”å›žå¹¾è¡Œï¼ˆéœæ…‹ï¼‰æ ¼å¼åŒ–文本的簡單方法。這個函數å¯ç”¨æ–¼å°Žå‡ºäºŒé€²ä½ä¿¡æ¯ï¼Œä½†
+è®€å–æ­¤æ–‡ä»¶å°‡è¿”å›žç”±æŒ‡é‡æŒ‡å‘debugfs_blob_wrapperçµæ§‹é«”的數據。一些驅動使用“blobsâ€
+ä½œçˆ²ä¸€ç¨®è¿”å›žå¹¾è¡Œï¼ˆéœæ…‹ï¼‰æ ¼å¼åŒ–文本的簡單方法。這個函數å¯ç”¨æ–¼å°Žå‡ºäºŒé€²åˆ¶ä¿¡æ¯ï¼Œä½†
似乎在主線中沒有任何代碼這樣åšã€‚請注æ„,使用debugfs_create_blob()命令創建的
-所有文件是åªè®€çš„。
+所有文件是隻讀的。
如果您è¦è½‰å„²ä¸€å€‹å¯„存器塊(在開發éŽç¨‹ä¸­ç¶“常會這麼åšï¼Œä½†æ˜¯é€™æ¨£çš„調試代碼很少上傳
到主線中。Debugfsæä¾›å…©å€‹å‡½æ•¸ï¼šä¸€å€‹ç”¨æ–¼å‰µå»ºåƒ…寄存器文件,å¦ä¸€å€‹æŠŠä¸€å€‹å¯„存器塊
@@ -163,7 +162,7 @@ file_size是åˆå§‹æ–‡ä»¶å¤§å°ã€‚å…¶ä»–åƒæ•¸è·Ÿå‡½æ•¸debugfs_create_file的相å
void debugfs_print_regs32(struct seq_file *s, struct debugfs_reg32 *regs,
int nregs, void __iomem *base, char *prefix);
-「baseã€åƒæ•¸å¯èƒ½çˆ²0,但您å¯èƒ½éœ€è¦ä½¿ç”¨__stringify構建reg32數組,實際上有許多寄存器
+“baseâ€åƒæ•¸å¯èƒ½çˆ²0,但您å¯èƒ½éœ€è¦ä½¿ç”¨__stringify構建reg32數組,實際上有許多寄存器
å稱(å®ï¼‰æ˜¯å¯„存器塊在基å€ä¸Šçš„字節åç§»é‡ã€‚
如果è¦åœ¨debugfs中轉儲u32數組,å¯ä»¥ä½¿ç”¨ä»¥ä¸‹å‡½æ•¸å‰µå»ºæ–‡ä»¶::
@@ -172,7 +171,7 @@ file_size是åˆå§‹æ–‡ä»¶å¤§å°ã€‚å…¶ä»–åƒæ•¸è·Ÿå‡½æ•¸debugfs_create_file的相å
struct dentry *parent,
u32 *array, u32 elements);
-「arrayã€åƒæ•¸æä¾›æ•¸æ“šï¼Œè€Œã€Œelementsã€åƒæ•¸çˆ²æ•¸çµ„中元素的數é‡ã€‚注æ„:數組創建後,數組
+“arrayâ€åƒæ•¸æä¾›æ•¸æ“šï¼Œè€Œâ€œelementsâ€åƒæ•¸çˆ²æ•¸çµ„中元素的數é‡ã€‚注æ„:數組創建後,數組
大å°ç„¡æ³•更改。
有一個函數來創建與設備相關的seq_file::
@@ -183,8 +182,8 @@ file_size是åˆå§‹æ–‡ä»¶å¤§å°ã€‚å…¶ä»–åƒæ•¸è·Ÿå‡½æ•¸debugfs_create_file的相å
int (*read_fn)(struct seq_file *s,
void *data));
-「devã€åƒæ•¸æ˜¯èˆ‡æ­¤debugfs文件相關的設備,並且「read_fnã€æ˜¯ä¸€å€‹å‡½æ•¸æŒ‡é‡ï¼Œé€™å€‹å‡½æ•¸åœ¨
-列å°seq_file內容的時候被回調。
+“devâ€åƒæ•¸æ˜¯èˆ‡æ­¤debugfs文件相關的設備,並且“read_fnâ€æ˜¯ä¸€å€‹å‡½æ•¸æŒ‡é‡ï¼Œé€™å€‹å‡½æ•¸åœ¨
+打å°seq_file內容的時候被回調。
還有一些其他的é¢å‘目錄的函數::
@@ -199,7 +198,7 @@ file_size是åˆå§‹æ–‡ä»¶å¤§å°ã€‚å…¶ä»–åƒæ•¸è·Ÿå‡½æ•¸debugfs_create_file的相å
調用debugfs_rename()å°‡çˆ²ç¾æœ‰çš„debugfs文件é‡å‘½å,å¯èƒ½åŒæ™‚切æ›ç›®éŒ„。 new_name
函數調用之å‰ä¸èƒ½å­˜åœ¨ï¼›è¿”回值爲old_dentryï¼Œå…¶ä¸­åŒ…å«æ›´æ–°çš„ä¿¡æ¯ã€‚å¯ä»¥ä½¿ç”¨
-debugfs_create_symlink()創建符號連çµã€‚
+debugfs_create_symlinkï¼ˆï¼‰å‰µå»ºç¬¦è™ŸéˆæŽ¥ã€‚
所有debugfs用戶必須考慮的一件事是:
@@ -219,6 +218,6 @@ dentry值å¯ä»¥çˆ²NULL或錯誤值,在這種情æ³ä¸‹ï¼Œä¸æœƒæœ‰ä»»ä½•文件è
å¦‚æžœå°‡å°æ‡‰é ‚層目錄的dentry傳éžçµ¦ä»¥ä¸Šå‡½æ•¸ï¼Œå‰‡è©²ç›®éŒ„ä¸‹çš„æ•´å€‹å±¤æ¬¡çµæ§‹å°‡æœƒè¢«åˆªé™¤ã€‚
-注釋:
+註釋:
[1] http://lwn.net/Articles/309298/
diff --git a/Documentation/translations/zh_TW/filesystems/index.rst b/Documentation/translations/zh_TW/filesystems/index.rst
index 789e742fa3c5..d7f9d61f654c 100644
--- a/Documentation/translations/zh_TW/filesystems/index.rst
+++ b/Documentation/translations/zh_TW/filesystems/index.rst
@@ -12,7 +12,7 @@
Linux Kernel中的文件系統
========================
-這份正在開發的手冊或許在未來æŸå€‹è¼ç…Œçš„æ—¥å­è£¡ä»¥æ˜“懂的形å¼å°‡Linux虛擬\
+這份正在開發的手冊或許在未來æŸå€‹è¼ç…Œçš„æ—¥å­è£ä»¥æ˜“懂的形å¼å°‡Linux虛擬\
文件系統(VFS)層以åŠåŸºæ–¼å…¶ä¸Šçš„å„種文件系統如何工作呈ç¾çµ¦å¤§å®¶ã€‚ç•¶å‰\
å¯ä»¥çœ‹åˆ°ä¸‹é¢çš„內容。
diff --git a/Documentation/translations/zh_TW/filesystems/sysfs.txt b/Documentation/translations/zh_TW/filesystems/sysfs.txt
index a84eba2af9d3..ebe90651fc3b 100644
--- a/Documentation/translations/zh_TW/filesystems/sysfs.txt
+++ b/Documentation/translations/zh_TW/filesystems/sysfs.txt
@@ -61,7 +61,7 @@ Documentation/core-api/kobject.rst 文檔以ç²å¾—更多關於 kobject 接å£çš„
任何 kobject 在系統中註冊,就會有一個目錄在 sysfs 中被創建。這個
目錄是作爲該 kobject 的父å°è±¡æ‰€åœ¨ç›®éŒ„çš„å­ç›®éŒ„創建的,以準確地傳éž
-內核的å°è±¡å±¤æ¬¡åˆ°ç”¨æˆ¶ç©ºé–“。sysfs 中的頂層目錄代表著內核å°è±¡å±¤æ¬¡çš„
+內核的å°è±¡å±¤æ¬¡åˆ°ç”¨æˆ¶ç©ºé–“。sysfs 中的頂層目錄代表ç€å…§æ ¸å°è±¡å±¤æ¬¡çš„
å…±åŒç¥–先;例如:æŸäº›å°è±¡å±¬æ–¼æŸå€‹å­ç³»çµ±ã€‚
Sysfs 在與其目錄關è¯çš„ kernfs_node å°è±¡ä¸­å…§éƒ¨ä¿å­˜ä¸€å€‹æŒ‡å‘實ç¾
@@ -198,7 +198,7 @@ Sysfs å°‡æœƒçˆ²æ¯æ¬¡è®€å¯«æ“作調用一次這個方法。這使得這些方æ³
䏿œƒä¸å¤ªé«˜ã€‚
這使得用戶空間å¯ä»¥å±€éƒ¨åœ°è®€å’Œä»»æ„çš„å‘剿œç´¢æ•´å€‹æ–‡ä»¶ã€‚如果用戶空間
- å‘後æœç´¢åˆ°é›¶æˆ–使用『0ã€å移執行一個pread(2)æ“作,show()方法將
+ å‘後æœç´¢åˆ°é›¶æˆ–使用‘0’å移執行一個pread(2)æ“作,show()方法將
冿¬¡è¢«èª¿ç”¨ï¼Œä»¥é‡æ–°å¡«å……緩存。
- 在寫方é¢ï¼ˆwrite(2)),sysfs 希望在第一次寫æ“作時得到整個緩è¡å€ã€‚
@@ -253,7 +253,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
(注æ„:真正的實ç¾ä¸å…許用戶空間設置設備å。)
-頂層目錄布局
+頂層目錄佈局
~~~~~~~~~~~~
sysfs ç›®éŒ„çš„å®‰æŽ’é¡¯ç¤ºäº†å…§æ ¸æ•¸æ“šçµæ§‹ä¹‹é–“的關係。
@@ -272,23 +272,23 @@ fs/
devices/ 包å«äº†ä¸€å€‹è¨­å‚™æ¨¹çš„æ–‡ä»¶ç³»çµ±è¡¨ç¤ºã€‚他直接映射了內部的內核
è¨­å‚™æ¨¹ï¼Œåæ˜ äº†è¨­å‚™çš„å±¤æ¬¡çµæ§‹ã€‚
-bus/ 包å«äº†å…§æ ¸ä¸­å„種總線類型的平é¢ç›®éŒ„布局。æ¯å€‹ç¸½ç·šç›®éŒ„包å«å…©å€‹
+bus/ 包å«äº†å…§æ ¸ä¸­å„種總線類型的平é¢ç›®éŒ„佈局。æ¯å€‹ç¸½ç·šç›®éŒ„包å«å…©å€‹
å­ç›®éŒ„:
devices/
drivers/
-devices/ 包å«äº†ç³»çµ±ä¸­å‡ºç¾çš„æ¯å€‹è¨­å‚™çš„ç¬¦è™Ÿé€£çµï¼Œä»–å€‘æŒ‡å‘ root/ 下的
+devices/ 包å«äº†ç³»çµ±ä¸­å‡ºç¾çš„æ¯å€‹è¨­å‚™çš„ç¬¦è™ŸéˆæŽ¥ï¼Œä»–å€‘æŒ‡å‘ root/ 下的
設備目錄。
-drivers/ 包å«äº†æ¯å€‹å·²çˆ²ç‰¹å®šç¸½ç·šä¸Šçš„設備而掛載的驅動程åºçš„目錄(這裡
+drivers/ 包å«äº†æ¯å€‹å·²çˆ²ç‰¹å®šç¸½ç·šä¸Šçš„設備而掛載的驅動程åºçš„目錄(這è£
å‡å®šé©…動沒有跨越多個總線類型)。
fs/ 包å«äº†ä¸€å€‹çˆ²æ–‡ä»¶ç³»çµ±è¨­ç«‹çš„目錄。ç¾åœ¨æ¯å€‹æƒ³è¦å°Žå‡ºå±¬æ€§çš„æ–‡ä»¶ç³»çµ±å¿…é ˆ
在 fs/ ä¸‹å‰µå»ºè‡ªå·±çš„å±¤æ¬¡çµæ§‹(åƒè¦‹Documentation/filesystems/fuse.rst)。
dev/ 包å«å…©å€‹å­ç›®éŒ„: char/ å’Œ block/。在這兩個å­ç›®éŒ„中,有以
-<major>:<minor> æ ¼å¼å‘½å的符號連çµã€‚é€™äº›ç¬¦è™Ÿé€£çµæŒ‡å‘ sysfs 目錄
+<major>:<minor> æ ¼å¼å‘½åçš„ç¬¦è™ŸéˆæŽ¥ã€‚é€™äº›ç¬¦è™ŸéˆæŽ¥æŒ‡å‘ sysfs 目錄
中相應的設備。/sys/dev æä¾›ä¸€å€‹é€šéŽä¸€å€‹ stat(2) æ“ä½œçµæžœï¼ŒæŸ¥æ‰¾
設備 sysfs 接å£å¿«æ·çš„æ–¹æ³•。
diff --git a/Documentation/translations/zh_TW/filesystems/tmpfs.rst b/Documentation/translations/zh_TW/filesystems/tmpfs.rst
index 2c8439b2b77e..aed61cc3064d 100644
--- a/Documentation/translations/zh_TW/filesystems/tmpfs.rst
+++ b/Documentation/translations/zh_TW/filesystems/tmpfs.rst
@@ -4,8 +4,7 @@
:Original: Documentation/filesystems/tmpfs.rst
-Translated by Wang Qing <wangqing@vivo.com>
-and Hu Haowen <src.res.211@gmail.com>
+translated by Wang Qing<wangqing@vivo.com>
=====
Tmpfs
@@ -13,18 +12,18 @@ Tmpfs
Tmpfs是一個將所有文件都ä¿å­˜åœ¨è™›æ“¬å…§å­˜ä¸­çš„æ–‡ä»¶ç³»çµ±ã€‚
-tmpfs中的所有內容都是臨時的,也就是說沒有任何文件會在硬碟上創建。
+tmpfs中的所有內容都是臨時的,也就是說沒有任何文件會在硬盤上創建。
如果å¸è¼‰tmpfs實例,所有ä¿å­˜åœ¨å…¶ä¸­çš„æ–‡ä»¶éƒ½æœƒä¸Ÿå¤±ã€‚
-tmpfs將所有文件ä¿å­˜åœ¨å…§æ ¸ç·©å­˜ä¸­ï¼Œéš¨è‘—文件內容增長或縮å°å¯ä»¥å°‡ä¸éœ€è¦çš„
-é é¢swap出去。它具有最大é™åˆ¶ï¼Œå¯ä»¥é€šéŽã€Œmount -o remount ...ã€èª¿æ•´ã€‚
+tmpfs將所有文件ä¿å­˜åœ¨å…§æ ¸ç·©å­˜ä¸­ï¼Œéš¨ç€æ–‡ä»¶å…§å®¹å¢žé•·æˆ–縮å°å¯ä»¥å°‡ä¸éœ€è¦çš„
+é é¢swap出去。它具有最大é™åˆ¶ï¼Œå¯ä»¥é€šéŽâ€œmount -o remount ...â€èª¿æ•´ã€‚
å’Œramfs(創建tmpfs的模æ¿ï¼‰ç›¸æ¯”,tmpfs包å«äº¤æ›å’Œé™åˆ¶æª¢æŸ¥ã€‚å’Œtmpfs相似的å¦
-一個æ±è¥¿æ˜¯RAMç£ç¢Ÿï¼ˆ/dev/ram*),å¯ä»¥åœ¨ç‰©ç†RAM中模擬固定大å°çš„硬碟,並在
+一個æ±è¥¿æ˜¯RAMç£ç›¤ï¼ˆ/dev/ram*),å¯ä»¥åœ¨ç‰©ç†RAM中模擬固定大å°çš„硬盤,並在
此之上創建一個普通的文件系統。Ramdisks無法swap,因此無法調整它們的大å°ã€‚
由於tmpfs完全ä¿å­˜æ–¼é é¢ç·©å­˜å’Œswap中,因此所有tmpfsé é¢å°‡åœ¨/proc/meminfo
-中顯示爲「Shmemã€ï¼Œè€Œåœ¨free(1)中顯示爲「Sharedã€ã€‚請注æ„,這些計數還包括
+中顯示爲“Shmemâ€ï¼Œè€Œåœ¨free(1)中顯示爲“Sharedâ€ã€‚請注æ„,這些計數還包括
共享內存(shmem,請åƒé–±ipcs(1))。ç²å¾—計數的最å¯é æ–¹æ³•是使用df(1)å’Œdu(1)。
tmpfs具有以下用途:
@@ -45,7 +44,7 @@ tmpfs具有以下用途:
tmpfsçš„å‰èº«(shm fs)æ‰èƒ½ä½¿ç”¨SYSV共享內存)
3) 很多人(包括我)都覺的在/tmpå’Œ/var/tmp上掛載éžå¸¸æ–¹ä¾¿ï¼Œä¸¦å…·æœ‰è¼ƒå¤§çš„
- swap分å€ã€‚ç›®å‰å¾ªç’°æŽ›è¼‰tmpfså¯ä»¥æ­£å¸¸å·¥ä½œï¼Œæ‰€ä»¥å¤§å¤šæ•¸ç™¼å¸ƒéƒ½æ‡‰ç•¶å¯ä»¥
+ swap分å€ã€‚ç›®å‰å¾ªç’°æŽ›è¼‰tmpfså¯ä»¥æ­£å¸¸å·¥ä½œï¼Œæ‰€ä»¥å¤§å¤šæ•¸ç™¼ä½ˆéƒ½æ‡‰ç•¶å¯ä»¥
使用mkinitrd通éŽ/tmp訪å•/tmp。
4) 也許還有更多我ä¸çŸ¥é“的地方:-)
@@ -58,11 +57,11 @@ size tmpfs實例分é…的字節數é™åˆ¶ã€‚默èªå€¼æ˜¯ä¸swap時物ç†RAM
如果tmpfs實例éŽå¤§ï¼Œæ©Ÿå™¨å°‡æ­»éŽ–ï¼Œå› çˆ²OOM處ç†å°‡ç„¡æ³•釋放該內存。
nr_blocks 與size相åŒï¼Œä½†ä»¥PAGE_SIZE爲單ä½ã€‚
nr_inodes tmpfs實例的最大inode個數。默èªå€¼æ˜¯ç‰©ç†å…§å­˜é æ•¸çš„一åŠï¼Œæˆ–者
- (有高端內存的機器)低端內存RAMçš„é æ•¸ï¼ŒäºŒè€…以較低者為準。
+ (有高端內存的機器)低端內存RAMçš„é æ•¸ï¼ŒäºŒè€…以較低者爲準。
========= ===========================================================
é€™äº›åƒæ•¸æŽ¥å—後綴k,m或g表示åƒï¼Œå…†å’Œåƒå…†å­—節,å¯ä»¥åœ¨remount時更改。
-sizeåƒæ•¸ä¹ŸæŽ¥å—後綴%用來é™åˆ¶tmpfs實例å ç”¨ç‰©ç†RAM的百分比:
+sizeåƒæ•¸ä¹ŸæŽ¥å—後綴%用來é™åˆ¶tmpfs實例佔用物ç†RAM的百分比:
未指定size或nr_blocks時,默èªå€¼çˆ²size=50ï¼…
如果nr_blocks=0(或size=0),block個數將ä¸å—é™åˆ¶ï¼›å¦‚æžœnr_inodes=0,
@@ -71,26 +70,26 @@ inode個數將ä¸å—é™åˆ¶ã€‚é€™æ¨£æŽ›è¼‰é€šå¸¸æ˜¯ä¸æ˜Žæ™ºçš„,因爲它å…許
場景下的訪å•。
tmpfs具有爲所有文件設置NUMA內存分é…策略掛載é¸é …(如果啓用了CONFIG_NUMA),
-å¯ä»¥é€šéŽã€Œmount -o remount ...ã€èª¿æ•´
+å¯ä»¥é€šéŽâ€œmount -o remount ...â€èª¿æ•´
======================== =========================
mpol=default 採用進程分é…ç­–ç•¥
(è«‹åƒé–± set_mempolicy(2))
mpol=prefer:Node 傾å‘從給定的節點分é…
-mpol=bind:NodeList åªå…許從指定的éŠè¡¨åˆ†é…
+mpol=bind:NodeList åªå…許從指定的éˆè¡¨åˆ†é…
mpol=interleave 傾呿–¼ä¾æ¬¡å¾žæ¯å€‹ç¯€é»žåˆ†é…
mpol=interleave:NodeList 便¬¡å¾žæ¯å€‹ç¯€é»žåˆ†é…
mpol=local 優先本地節點分é…å…§å­˜
======================== =========================
-NodeListæ ¼å¼æ˜¯ä»¥é€—號分隔的å進使•¸å­—表示大å°å’Œç¯„åœï¼Œæœ€å¤§å’Œæœ€å°ç¯„åœæ˜¯ç”¨-
-分隔符的å進使•¸ä¾†è¡¨ç¤ºã€‚例如,mpol=bind0-3,5,7,9-15
+NodeListæ ¼å¼æ˜¯ä»¥é€—號分隔的å進制數字表示大å°å’Œç¯„åœï¼Œæœ€å¤§å’Œæœ€å°ç¯„åœæ˜¯ç”¨-
+分隔符的å進制數來表示。例如,mpol=bind0-3,5,7,9-15
帶有有效NodeList的內存策略將按指定格å¼ä¿å­˜ï¼Œåœ¨å‰µå»ºæ–‡ä»¶æ™‚使用。當任務在該
文件系統上創建文件時,會使用到掛載時的內存策略NodeListé¸é …,如果設置的話,
由調用任務的cpuset[è«‹åƒè¦‹Documentation/admin-guide/cgroup-v1/cpusets.rst]
以åŠä¸‹é¢åˆ—出的å¯é¸æ¨™èªŒç´„æŸã€‚如果NodeLists爲設置爲空集,則文件的內存策略將
-æ¢å¾©çˆ²ã€Œé»˜èªã€ç­–略。
+æ¢å¾©çˆ²â€œé»˜èªâ€ç­–略。
NUMA內存分é…策略有å¯é¸æ¨™èªŒï¼Œå¯ä»¥ç”¨æ–¼æ¨¡å¼çµåˆã€‚在掛載tmpfs時指定這些å¯é¸
標誌å¯ä»¥åœ¨NodeList之å‰ç”Ÿæ•ˆã€‚
@@ -107,12 +106,12 @@ Documentation/admin-guide/mm/numa_memory_policy.rst列出所有å¯ç”¨çš„å…§å­˜
請注æ„ï¼Œå¦‚æžœå…§æ ¸ä¸æ”¯æŒNUMA,那麼使用mpolé¸é …掛載tmpfs將會失敗;nodelist指定ä¸
在線的節點也會失敗。如果您的系統ä¾è³´æ–¼æ­¤ï¼Œä½†å…§æ ¸æœƒé‹è¡Œä¸å¸¶NUMA功能(也許是安全
revoceryå…§æ ¸),或者具有較少的節點在線,建議從自動模å¼ä¸­çœç•¥mpolé¸é …掛載é¸é …。
-å¯ä»¥åœ¨ä»¥å¾Œé€šéŽã€Œmount -o remount,mpol=Policy:NodeList MountPointã€æ·»åŠ åˆ°æŽ›è¼‰é»žã€‚
+å¯ä»¥åœ¨ä»¥å¾Œé€šéŽâ€œmount -o remount,mpol=Policy:NodeList MountPointâ€æ·»åŠ åˆ°æŽ›è¼‰é»žã€‚
è¦æŒ‡å®šåˆå§‹æ ¹ç›®éŒ„,å¯ä»¥ä½¿ç”¨å¦‚下掛載é¸é …:
==== ====================
-æ¨¡å¼ æ¬Šé™ç”¨å…«é€²ä½æ•¸å­—表示
+æ¨¡å¼ æ¬Šé™ç”¨å…«é€²åˆ¶æ•¸å­—表示
uid 用戶ID
gid 組ID
==== ====================
@@ -129,7 +128,7 @@ inode32 使用32ä½inode
在32ä½å…§æ ¸ä¸Šï¼Œé»˜èªæ˜¯inode32,掛載時指定inode64會被拒絕。
在64ä½å…§æ ¸ä¸Šï¼Œé»˜èªé…置是CONFIG_TMPFS_INODE64。inode64é¿å…了單個設備上å¯èƒ½æœ‰å¤šå€‹
-具有相åŒinode編號的文件;比如32使‡‰ç”¨ç¨‹å¼ä½¿ç”¨glibc如果長期訪å•tmpfs,一旦é”到33
+具有相åŒinode編號的文件;比如32使‡‰ç”¨ç¨‹åºä½¿ç”¨glibc如果長期訪å•tmpfs,一旦é”到33
ä½inode編號,就有EOVERFLOW失敗的å±éšªï¼Œç„¡æ³•打開大於2GiB的文件,並返回EINVAL。
所以'mount -t tmpfs -o size=10G,nr_inodes=10k,mode=700 tmpfs /mytmpfs'將在
diff --git a/Documentation/translations/zh_TW/filesystems/virtiofs.rst b/Documentation/translations/zh_TW/filesystems/virtiofs.rst
index 086fce5839dd..6150ad964e78 100644
--- a/Documentation/translations/zh_TW/filesystems/virtiofs.rst
+++ b/Documentation/translations/zh_TW/filesystems/virtiofs.rst
@@ -10,7 +10,6 @@
中文版維護者: 王文虎 Wang Wenhu <wenhu.wang@vivo.com>
中文版翻譯者: 王文虎 Wang Wenhu <wenhu.wang@vivo.com>
中文版校譯者: 王文虎 Wang Wenhu <wenhu.wang@vivo.com>
- 中文版校譯者: 王文虎 Wang Wenhu <wenhu.wang@vivo.com>
ç¹é«”中文版校譯者:胡皓文 Hu Haowen <src.res.211@gmail.com>
===========================================
@@ -21,7 +20,7 @@ virtiofs: virtio-fs 主機<->客機共享文件系統
介紹
====
-Linuxçš„virtiofs文件系統實ç¾äº†ä¸€å€‹åŠè™›æ“¬åŒ–VIRTIO類型「virtio-fsã€è¨­å‚™çš„驅動,通éŽè©²\
+Linuxçš„virtiofs文件系統實ç¾äº†ä¸€å€‹åŠè™›æ“¬åŒ–VIRTIO類型“virtio-fsâ€è¨­å‚™çš„驅動,通éŽè©²\
類型設備實ç¾å®¢æ©Ÿ<->主機文件系統共享。它å…許客機掛載一個已經導出到主機的目錄。
客機通常需è¦è¨ªå•主機或者é ç¨‹ç³»çµ±ä¸Šçš„æ–‡ä»¶ã€‚ä½¿ç”¨å ´æ™¯åŒ…æ‹¬ï¼šåœ¨æ–°å®¢æ©Ÿå®‰è£æ™‚讓文件å°å…¶\
@@ -42,12 +41,12 @@ Linuxçš„virtiofs文件系統實ç¾äº†ä¸€å€‹åŠè™›æ“¬åŒ–VIRTIO類型「virtio-fsã
guest# mount -t virtiofs myfs /mnt
-請查閱 https://virtio-fs.gitlab.io/ 了解é…ç½®QEMUå’Œvirtiofsd守護程åºçš„詳細信æ¯ã€‚
+請查閱 https://virtio-fs.gitlab.io/ çž­è§£é…ç½®QEMUå’Œvirtiofsd守護程åºçš„詳細信æ¯ã€‚
內幕
====
由於virtio-fs設備將FUSEå”議用於文件系統請求,因此Linuxçš„virtiofs文件系統與FUSEæ–‡\
-件系統客戶端緊密集æˆåœ¨ä¸€èµ·ã€‚客機充當FUSE客戶端而主機充當FUSE伺æœå™¨ï¼Œå…§æ ¸èˆ‡ç”¨æˆ¶ç©º\
+件系統客戶端緊密集æˆåœ¨ä¸€èµ·ã€‚客機充當FUSE客戶端而主機充當FUSEæœå‹™å™¨ï¼Œå…§æ ¸èˆ‡ç”¨æˆ¶ç©º\
間之間的/dev/fuse接å£ç”±virtio-fs設備接å£ä»£æ›¿ã€‚
FUSE請求被置於虛擬隊列中由主機處ç†ã€‚主機填充緩è¡å€ä¸­çš„響應部分,而客機處ç†è«‹æ±‚的完æˆéƒ¨åˆ†ã€‚
@@ -55,7 +54,7 @@ FUSE請求被置於虛擬隊列中由主機處ç†ã€‚主機填充緩è¡å€ä¸­çš„é
å°‡/dev/fuse映射到虛擬隊列需è¦è§£æ±º/dev/fuseå’Œè™›æ“¬éšŠåˆ—ä¹‹é–“èªžç¾©ä¸Šçš„å·®ç•°ã€‚æ¯æ¬¡è®€å–\
/dev/fuse設備時,FUSE客戶端都å¯ä»¥é¸æ“‡è¦å‚³è¼¸çš„請求,從而å¯ä»¥ä½¿æŸäº›è«‹æ±‚優先於其他\
請求。虛擬隊列有其隊列語義,無法更改已入隊請求的順åºã€‚在虛擬隊列已滿的情æ³ä¸‹å°¤
-å…¶é—œéµï¼Œå› çˆ²æ­¤æ™‚ä¸å¯èƒ½åŠ å…¥é«˜å„ªå…ˆç´šçš„è«‹æ±‚ã€‚çˆ²äº†è§£æ±ºæ­¤å·®ç•°ï¼Œvirtio-fs設備採用「hiprioã€\
+å…¶é—œéµï¼Œå› çˆ²æ­¤æ™‚ä¸å¯èƒ½åŠ å…¥é«˜å„ªå…ˆç´šçš„è«‹æ±‚ã€‚çˆ²äº†è§£æ±ºæ­¤å·®ç•°ï¼Œvirtio-fs設備採用“hiprioâ€\
(高優先級)虛擬隊列,專門用於有別於普通請求的高優先級請求。
diff --git a/Documentation/translations/zh_TW/index.rst b/Documentation/translations/zh_TW/index.rst
index d1cf0b4d8e46..563ac9bfc66b 100644
--- a/Documentation/translations/zh_TW/index.rst
+++ b/Documentation/translations/zh_TW/index.rst
@@ -55,11 +55,11 @@ TODOList:
:maxdepth: 1
process/license-rules
+ dev-tools/index
TODOList:
* doc-guide/index
-* dev-tools/index
* dev-tools/testing-overview
* kernel-hacking/index
* rust/index
@@ -101,9 +101,10 @@ TODOList:
é«”ç³»çµæ§‹æ–‡æª”
------------
-TODOList:
+.. toctree::
+ :maxdepth: 1
-* arch/index
+ arch/index
其他文檔
--------
diff --git a/Documentation/translations/zh_TW/process/1.Intro.rst b/Documentation/translations/zh_TW/process/1.Intro.rst
index f236fe95a6c6..6e754ac48964 100644
--- a/Documentation/translations/zh_TW/process/1.Intro.rst
+++ b/Documentation/translations/zh_TW/process/1.Intro.rst
@@ -22,12 +22,12 @@
--------
本節的其餘部分涵蓋了內核開發的éŽç¨‹ï¼Œä»¥åŠé–‹ç™¼äººå“¡åŠå…¶åƒ±ä¸»åœ¨é€™æ–¹é¢å¯èƒ½é‡åˆ°çš„
-å„種å•題。有很多原因使內核代碼應被åˆä½µåˆ°æ­£å¼çš„(「主線ã€ï¼‰å…§æ ¸ä¸­ï¼ŒåŒ…括å°ç”¨æˆ¶
+å„種å•題。有很多原因使內核代碼應被åˆä½µåˆ°æ­£å¼çš„(“主線â€ï¼‰å…§æ ¸ä¸­ï¼ŒåŒ…括å°ç”¨æˆ¶
的自動å¯ç”¨æ€§ã€å¤šç¨®å½¢å¼çš„ç¤¾å€æ”¯æŒä»¥åŠå½±éŸ¿å…§æ ¸é–‹ç™¼æ–¹å‘的能力。æä¾›çµ¦Linuxå…§æ ¸
的代碼必須在與GPL兼容的許å¯è­‰ä¸‹å¯ç”¨ã€‚
-:ref:`tw_development_process` 介紹了開發éŽç¨‹ã€å…§æ ¸ç™¼å¸ƒå‘¨æœŸå’Œåˆä½µçª—å£çš„æ©Ÿåˆ¶ã€‚
-涵蓋了補ä¸é–‹ç™¼ã€å¯©æŸ¥å’Œåˆä½µå‘¨æœŸä¸­çš„å„個階段。還有一些關於工具和郵件列表的討論?
+:ref:`tw_development_process` 介紹了開發éŽç¨‹ã€å…§æ ¸ç™¼ä½ˆé€±æœŸå’Œåˆä¸¦çª—å£çš„æ©Ÿåˆ¶ã€‚
+涵蓋了補ä¸é–‹ç™¼ã€å¯©æŸ¥å’Œåˆä¸¦é€±æœŸä¸­çš„å„個階段。還有一些關於工具和郵件列表的討論?
é¼“å‹µå¸Œæœ›é–‹å§‹å…§æ ¸é–‹ç™¼çš„é–‹ç™¼äººå“¡è·Ÿè¹¤ä¸¦ä¿®å¾©ç¼ºé™·ä»¥ä½œçˆ²åˆæ­¥ç·´ç¿’。
@@ -38,39 +38,39 @@
陷阱。也涵蓋了å°è£œä¸çš„ä¸€äº›è¦æ±‚,並且介紹了一些工具,這些工具有助於確ä¿å…§æ ¸
è£œä¸æ˜¯æ­£ç¢ºçš„。
-:ref:`tw_development_posting` æè¿°ç™¼å¸ƒè£œä¸ä»¥ä¾›è©•審的éŽç¨‹ã€‚爲了讓開發社å€èƒ½
+:ref:`tw_development_posting` æè¿°ç™¼ä½ˆè£œä¸ä»¥ä¾›è©•審的éŽç¨‹ã€‚爲了讓開發社å€èƒ½
èªçœŸå°å¾…,補ä¸å¿…須被正確格å¼åŒ–å’Œæè¿°ï¼Œä¸¦ä¸”必須發é€åˆ°æ­£ç¢ºçš„地方。éµå¾ªæœ¬ç¯€ä¸­çš„
å»ºè­°æœ‰åŠ©æ–¼ç¢ºä¿æ‚¨çš„工作能被較好地接ç´ã€‚
-:ref:`tw_development_followthrough` 介紹了發布補ä¸ä¹‹å¾Œç™¼ç”Ÿçš„事情;工作在這時
+:ref:`tw_development_followthrough` 介紹了發佈補ä¸ä¹‹å¾Œç™¼ç”Ÿçš„事情;工作在這時
é‚„é é æ²’有完æˆã€‚與審閱者一起工作是開發éŽç¨‹ä¸­çš„一個é‡è¦éƒ¨åˆ†ï¼›æœ¬ç¯€æä¾›äº†ä¸€äº›
關於如何在這個é‡è¦éšŽæ®µé¿å…å•題的æç¤ºã€‚當補ä¸è¢«åˆä½µåˆ°ä¸»ç·šä¸­æ™‚ï¼Œé–‹ç™¼äººå“¡è¦æ³¨æ„
ä¸è¦å‡å®šä»»å‹™å·²ç¶“完æˆã€‚
-:ref:`tw_development_advancedtopics` 介紹了兩個「高級ã€ä¸»é¡Œï¼šä½¿ç”¨Git管ç†è£œä¸
-和查看其他人發布的補ä¸ã€‚
+:ref:`tw_development_advancedtopics` 介紹了兩個“高級â€ä¸»é¡Œï¼šä½¿ç”¨Git管ç†è£œä¸
+和查看其他人發佈的補ä¸ã€‚
:ref:`tw_development_conclusion` 總çµäº†æœ‰é—œå…§æ ¸é–‹ç™¼çš„æ›´å¤šä¿¡æ¯ï¼Œé™„帶有相關資æº
-連çµã€‚
+éˆæŽ¥ã€‚
這個文檔是關於什麼的
--------------------
Linux內核有超éŽ800è¬è¡Œä»£ç¢¼ï¼Œæ¯å€‹ç‰ˆæœ¬çš„è²¢ç»è€…è¶…éŽ1000人,是ç¾å­˜æœ€å¤§ã€æœ€æ´»èºçš„
-å…費軟體項目之一。從1991年開始,這個內核已經發展æˆçˆ²ä¸€å€‹æœ€å¥½çš„作業系統組件,
-é‹è¡Œåœ¨è¢–çæ•¸ä½éŸ³æ¨‚æ’­æ”¾å™¨ã€æ¡Œä¸Šåž‹é›»è…¦ã€ç¾å­˜æœ€å¤§çš„è¶…ç´šè¨ˆç®—æ©Ÿä»¥åŠæ‰€æœ‰é¡žåž‹çš„系統上。
+å…費軟件項目之一。從1991年開始,這個內核已經發展æˆçˆ²ä¸€å€‹æœ€å¥½çš„æ“ä½œç³»çµ±çµ„ä»¶ï¼Œ
+é‹è¡Œåœ¨è¢–çæ•¸å­—音樂播放器ã€è‡ºå¼é›»è…¦ã€ç¾å­˜æœ€å¤§çš„è¶…ç´šè¨ˆç®—æ©Ÿä»¥åŠæ‰€æœ‰é¡žåž‹çš„系統上。
它是一種é©ç”¨æ–¼å¹¾ä¹Žä»»ä½•情æ³çš„å¥å£¯ã€é«˜æ•ˆå’Œå¯æ“´å±•的解決方案。
-隨著Linux的發展,希望åƒèˆ‡å…¶é–‹ç™¼çš„開發人員(和公å¸ï¼‰çš„æ•¸é‡ä¹Ÿåœ¨å¢žåŠ ã€‚ç¡¬é«”ä¾›æ‡‰å•†
+隨ç€Linux的發展,希望åƒèˆ‡å…¶é–‹ç™¼çš„開發人員(和公å¸ï¼‰çš„æ•¸é‡ä¹Ÿåœ¨å¢žåŠ ã€‚ç¡¬ä»¶ä¾›æ‡‰å•†
希望確ä¿Linux能夠很好地支æŒä»–們的產å“,使這些產å“å°Linux用戶具有å¸å¼•力。嵌入
å¼ç³»çµ±ä¾›æ‡‰å•†ä½¿ç”¨Linux作爲集æˆç”¢å“的組件,希望Linux能夠儘å¯èƒ½åœ°å‹ä»»æ‰‹é ­çš„任務。
-分銷商和其他基於Linux的軟體供應商切實關心Linuxå…§æ ¸çš„åŠŸèƒ½ã€æ€§èƒ½å’Œå¯é æ€§ã€‚最終
+分銷商和其他基於Linux的軟件供應商切實關心Linuxå…§æ ¸çš„åŠŸèƒ½ã€æ€§èƒ½å’Œå¯é æ€§ã€‚最終
用戶也常常希望修改Linux,使之能更好地滿足他們的需求。
Linux最引人注目的特性之一是這些開發人員å¯ä»¥è¨ªå•å®ƒï¼›ä»»ä½•å…·å‚™å¿…è¦æŠ€èƒ½çš„äººéƒ½å¯ä»¥
-改進Linux並影響其開發方å‘。專有產å“ä¸èƒ½æä¾›é€™ç¨®é–‹æ”¾æ€§ï¼Œé€™æ˜¯è‡ªç”±è»Ÿé«”的一個特點。
-如果有什麼ä¸åŒçš„話,那就是內核比大多數其他自由軟體項目更開放。一個典型的三個
-月內核開發周期å¯ä»¥æ¶‰åŠ1000多個開發人員,他們爲100多個ä¸åŒçš„å…¬å¸ï¼ˆæˆ–者根本ä¸
+改進Linux並影響其開發方å‘。專有產å“ä¸èƒ½æä¾›é€™ç¨®é–‹æ”¾æ€§ï¼Œé€™æ˜¯è‡ªç”±è»Ÿä»¶çš„一個特點。
+如果有什麼ä¸åŒçš„話,那就是內核比大多數其他自由軟件項目更開放。一個典型的三個
+月內核開發週期å¯ä»¥æ¶‰åŠ1000多個開發人員,他們爲100多個ä¸åŒçš„å…¬å¸ï¼ˆæˆ–者根本ä¸
隸屬公å¸ï¼‰å·¥ä½œã€‚
與內核開發社å€åˆä½œä¸¦ä¸æ˜¯ç‰¹åˆ¥å›°é›£ã€‚ä½†å„˜ç®¡å¦‚æ­¤ï¼Œä»æœ‰è¨±å¤šæ½›åœ¨çš„è²¢ç»è€…在嘗試åš
@@ -79,7 +79,7 @@ Linux最引人注目的特性之一是這些開發人員å¯ä»¥è¨ªå•它;任何
éŽç¨‹èˆ‡å°ˆæœ‰çš„é–‹ç™¼æ¨¡å¼æœ‰å¾ˆå¤§çš„ä¸åŒä¹Ÿå°±ä¸è¶³çˆ²å¥‡äº†ã€‚
å°æ–¼æ–°é–‹ç™¼äººå“¡ä¾†èªªï¼Œå…§æ ¸çš„開發éŽç¨‹å¯èƒ½æœƒè®“äººæ„Ÿåˆ°å¥‡æ€ªå’Œææ‡¼ï¼Œä½†é€™èƒŒå¾Œæœ‰å……分的
-ç†ç”±å’Œå …實的經驗。一個ä¸äº†è§£å…§æ ¸ç¤¾å€å·¥ä½œæ–¹å¼çš„開發人員(或者更糟的是,他們
+ç†ç”±å’Œå …實的經驗。一個ä¸çž­è§£å…§æ ¸ç¤¾å€å·¥ä½œæ–¹å¼çš„開發人員(或者更糟的是,他們
試圖拋棄或è¦é¿ä¹‹ï¼‰æœƒå¾—到令人沮喪的體驗。開發社å€åœ¨å¹«åŠ©é‚£äº›è©¦åœ–å­¸ç¿’çš„äººçš„åŒæ™‚,
沒有時間幫助那些ä¸é¡˜æ„å‚¾è½æˆ–ä¸é—œå¿ƒé–‹ç™¼éŽç¨‹çš„人。
@@ -102,20 +102,20 @@ Andrew Morton, Andrew Price, Tsugikazu Shibata 和 Jochen Voß 。
--------------------
有些公å¸å’Œé–‹ç™¼äººå“¡å¶çˆ¾æœƒæƒ³ï¼Œçˆ²ä»€éº¼ä»–們è¦è²»å¿ƒå­¸ç¿’如何與內核社å€åˆä½œï¼Œä¸¦å°‡ä»£ç¢¼
-æ”¾å…¥ä¸»ç·šå…§æ ¸ï¼ˆã€Œä¸»ç·šã€æ˜¯ç”±Linus Torvalds維護的內核,Linux發行商將其用作基礎)。
+æ”¾å…¥ä¸»ç·šå…§æ ¸ï¼ˆâ€œä¸»ç·šâ€æ˜¯ç”±Linus Torvalds維護的內核,Linux發行商將其用作基礎)。
在短期內,貢ç»ä»£ç¢¼çœ‹èµ·ä¾†åƒæ˜¯ä¸€ç¨®å¯ä»¥é¿å…的開銷;維護ç¨ç«‹ä»£ç¢¼ä¸¦ç›´æŽ¥æ”¯æŒç”¨æˆ¶
-ä¼¼ä¹Žæ›´å®¹æ˜“ã€‚äº‹å¯¦ä¸Šï¼Œä¿æŒä»£ç¢¼ç¨ç«‹ï¼ˆã€Œæ¨¹å¤–ã€ï¼‰æ˜¯åœ¨ç¶“濟上是錯誤的。
+ä¼¼ä¹Žæ›´å®¹æ˜“ã€‚äº‹å¯¦ä¸Šï¼Œä¿æŒä»£ç¢¼ç¨ç«‹ï¼ˆâ€œæ¨¹å¤–â€ï¼‰æ˜¯åœ¨ç¶“濟上是錯誤的。
çˆ²äº†èªªæ˜Žæ¨¹å¤–ä»£ç¢¼æˆæœ¬ï¼Œä¸‹é¢çµ¦å‡ºå…§æ ¸é–‹ç™¼éŽç¨‹çš„一些相關方é¢ï¼›æœ¬æ–‡ç¨å¾Œå°‡æ›´è©³ç´°åœ°
討論其中的大部分內容。請考慮:
- 所有Linux用戶都å¯ä»¥ä½¿ç”¨åˆä½µåˆ°ä¸»ç·šå…§æ ¸ä¸­çš„代碼。它將自動出ç¾åœ¨æ‰€æœ‰å•“用它的
- 發行版上。無需驅動程åºç£ç¢Ÿã€é¡å¤–下載,也ä¸éœ€è¦çˆ²å¤šå€‹ç™¼è¡Œç‰ˆçš„多個版本æä¾›
+ 發行版上。無需驅動程åºç£ç›¤ã€é¡å¤–下載,也ä¸éœ€è¦çˆ²å¤šå€‹ç™¼è¡Œç‰ˆçš„多個版本æä¾›
支æŒï¼›é€™ä¸€åˆ‡å°‡æ–¹ä¾¿æ‰€æœ‰é–‹ç™¼äººå“¡å’Œç”¨æˆ¶ã€‚併入主線解決了大é‡çš„分發和支æŒå•題。
- ç•¶å…§æ ¸é–‹ç™¼äººå“¡åŠªåŠ›ç¶­è­·ä¸€å€‹ç©©å®šçš„ç”¨æˆ¶ç©ºé–“æŽ¥å£æ™‚,內核內部APIè™•æ–¼ä¸æ–·è®ŠåŒ–之中。
ä¸ç¶­æŒç©©å®šçš„å…§éƒ¨æŽ¥å£æ˜¯ä¸€å€‹æ…Žé‡çš„設計決策;它å…許在任何時候進行基本的改進,
- 並產出更高質é‡çš„ä»£ç¢¼ã€‚ä½†è©²ç­–ç•¥å°Žè‡´çµæžœæ˜¯ï¼Œè‹¥è¦ä½¿ç”¨æ–°çš„內核,任何樹外代碼都
+ 併產出更高質é‡çš„ä»£ç¢¼ã€‚ä½†è©²ç­–ç•¥å°Žè‡´çµæžœæ˜¯ï¼Œè‹¥è¦ä½¿ç”¨æ–°çš„內核,任何樹外代碼都
éœ€è¦æŒçºŒçš„維護。維護樹外代碼會需è¦å¤§é‡çš„工作æ‰èƒ½ä½¿ä»£ç¢¼ä¿æŒæ­£å¸¸é‹è¡Œã€‚
相åï¼Œä½æ–¼ä¸»ç·šä¸­çš„代碼ä¸éœ€è¦é€™æ¨£åšï¼Œå› çˆ²åŸºæœ¬è¦å‰‡è¦æ±‚進行API更改的任何開發
@@ -140,60 +140,60 @@ Andrew Morton, Andrew Price, Tsugikazu Shibata 和 Jochen Voß 。
- ä»£ç¢¼çš„è²¢ç»æ˜¯ä½¿æ•´å€‹æµç¨‹å·¥ä½œçš„æ ¹æœ¬ã€‚通éŽè²¢ç»ä»£ç¢¼ï¼Œæ‚¨å¯ä»¥å‘內核添加新功能,並
æä¾›å…¶ä»–內核開發人員使用的功能和示例。如果您已經爲Linux開發了代碼(或者正在
- 考慮這樣åšï¼‰ï¼Œé‚£éº¼æ‚¨é¡¯ç„¶å°é€™å€‹å¹³å°çš„æŒçºŒæˆåŠŸæ„Ÿèˆˆè¶£ï¼›è²¢ç»ä»£ç¢¼æ˜¯ç¢ºä¿æˆåŠŸçš„
+ 考慮這樣åšï¼‰ï¼Œé‚£éº¼æ‚¨é¡¯ç„¶å°é€™å€‹å¹³è‡ºçš„æŒçºŒæˆåŠŸæ„Ÿèˆˆè¶£ï¼›è²¢ç»ä»£ç¢¼æ˜¯ç¢ºä¿æˆåŠŸçš„
最好方法之一。
-上述所有ç†ç”±éƒ½é©ç”¨æ–¼ä»»ä½•樹外內核代碼,包括以專有的ã€åƒ…二進ä½å½¢å¼åˆ†ç™¼çš„代碼。
-然而,在考慮任何類型的純二進ä½å…§æ ¸ä»£ç¢¼åˆ†å¸ƒä¹‹å‰ï¼Œé‚„需è¦è€ƒæ…®å…¶ä»–因素。包括:
+上述所有ç†ç”±éƒ½é©ç”¨æ–¼ä»»ä½•樹外內核代碼,包括以專有的ã€åƒ…二進制形å¼åˆ†ç™¼çš„代碼。
+然而,在考慮任何類型的純二進制內核代碼分佈之å‰ï¼Œé‚„需è¦è€ƒæ…®å…¶ä»–因素。包括:
- åœç¹žå°ˆæœ‰å…§æ ¸æ¨¡å¡Šåˆ†ç™¼çš„æ³•律å•題其實較爲模糊;相當多的內核版權所有者èªçˆ²ï¼Œ
- 大多數僅二進ä½çš„æ¨¡å¡Šæ˜¯å…§æ ¸çš„æ´¾ç”Ÿç”¢å“,因此,它們的分發é•å了GNU通用公共
+ 大多數僅二進制的模塊是內核的派生產å“,因此,它們的分發é•å了GNU通用公共
許å¯è­‰ï¼ˆä¸‹é¢å°‡è©³ç´°ä»‹ç´¹ï¼‰ã€‚æœ¬æ–‡ä½œè€…ä¸æ˜¯å¾‹å¸«ï¼Œæœ¬æ–‡æª”中的任何內容都ä¸å¯èƒ½è¢«
- 視爲法律建議。å°é–‰åŽŸå§‹ç¢¼æ¨¡å¡Šçš„çœŸå¯¦æ³•å¾‹åœ°ä½åªèƒ½ç”±æ³•院決定。但ä¸ç®¡æ€Žæ¨£ï¼Œå›°æ“¾
+ 視爲法律建議。å°é–‰æºä»£ç¢¼æ¨¡å¡Šçš„真實法律地ä½åªèƒ½ç”±æ³•院決定。但ä¸ç®¡æ€Žæ¨£ï¼Œå›°æ“¾
這些模塊的ä¸ç¢ºå®šæ€§ä»ç„¶å­˜åœ¨ã€‚
-- äºŒé€²ä½æ¨¡å¡Šå¤§å¤§å¢žåŠ äº†èª¿è©¦å…§æ ¸å•é¡Œçš„é›£åº¦ï¼Œä»¥è‡³æ–¼å¤§å¤šæ•¸å…§æ ¸é–‹ç™¼äººå“¡ç”šè‡³éƒ½ä¸æœƒ
- 嘗試。因此,åªåˆ†ç™¼äºŒé€²ä½æ¨¡å¡Šå°‡ä½¿æ‚¨çš„用戶更難從社å€ç²å¾—支æŒã€‚
+- 二進制模塊大大增加了調試內核å•é¡Œçš„é›£åº¦ï¼Œä»¥è‡³æ–¼å¤§å¤šæ•¸å…§æ ¸é–‹ç™¼äººå“¡ç”šè‡³éƒ½ä¸æœƒ
+ 嘗試。因此,åªåˆ†ç™¼äºŒé€²åˆ¶æ¨¡å¡Šå°‡ä½¿æ‚¨çš„用戶更難從社å€ç²å¾—支æŒã€‚
-- å°æ–¼åƒ…二進ä½çš„æ¨¡å¡Šçš„發行者來說,支æŒä¹Ÿæ›´åŠ å›°é›£ï¼Œä»–å€‘å¿…é ˆçˆ²ä»–å€‘å¸Œæœ›æ”¯æŒçš„
+- å°æ–¼åƒ…二進制的模塊的發行者來說,支æŒä¹Ÿæ›´åŠ å›°é›£ï¼Œä»–å€‘å¿…é ˆçˆ²ä»–å€‘å¸Œæœ›æ”¯æŒçš„
æ¯å€‹ç™¼è¡Œç‰ˆå’Œæ¯å€‹å…§æ ¸ç‰ˆæœ¬æä¾›ä¸åŒç‰ˆæœ¬çš„æ¨¡å¡Šã€‚爲了æä¾›è¼ƒçˆ²å…¨é¢çš„覆蓋範åœï¼Œ
å¯èƒ½éœ€è¦ä¸€å€‹æ¨¡å¡Šçš„å¹¾åå€‹æ§‹å»ºï¼Œä¸¦ä¸”æ¯æ¬¡å‡ç´šå…§æ ¸æ™‚,您的用戶都必須單ç¨å‡ç´š
這些模塊。
-- ä¸Šé¢æåˆ°çš„é—œæ–¼ä»£ç¢¼è©•å¯©çš„æ‰€æœ‰å•題都更加存在於å°é–‰åŽŸå§‹ç¢¼ä¸­ã€‚ç”±æ–¼è©²ä»£ç¢¼æ ¹æœ¬
+- ä¸Šé¢æåˆ°çš„é—œæ–¼ä»£ç¢¼è©•å¯©çš„æ‰€æœ‰å•題都更加存在於å°é–‰æºä»£ç¢¼ä¸­ã€‚由於該代碼根本
ä¸å¯å¾—,因此社å€ç„¡æ³•å°å…¶é€²è¡Œå¯©æŸ¥ï¼Œæ¯«ç„¡ç–‘å•,它將存在嚴é‡å•題。
尤其是嵌入å¼ç³»çµ±çš„製造商,å¯èƒ½æœƒå‚¾å‘於忽視本節中所說的大部分內容;因爲他們
-相信自己正在商用一種使用å‡çµå…§æ ¸ç‰ˆæœ¬çš„ç¨ç«‹ç”¢å“,在發布後ä¸éœ€è¦å†é€²è¡Œé–‹ç™¼ã€‚
+相信自己正在商用一種使用å‡çµå…§æ ¸ç‰ˆæœ¬çš„ç¨ç«‹ç”¢å“,在發佈後ä¸éœ€è¦å†é€²è¡Œé–‹ç™¼ã€‚
這個論點忽略了廣泛的代碼審查的價值以åŠå…許用戶å‘ç”¢å“æ·»åŠ åŠŸèƒ½çš„åƒ¹å€¼ã€‚ä½†é€™äº›
-產å“的商業壽命有é™ï¼Œä¹‹å¾Œå¿…須發布新版本的產å“。在這一點上,代碼在主線上並得到
-良好維護的供應商將能夠更好地å ä½ï¼Œä»¥ä½¿æ–°ç”¢å“快速上市。
+產å“的商業壽命有é™ï¼Œä¹‹å¾Œå¿…須發佈新版本的產å“。在這一點上,代碼在主線上並得到
+良好維護的供應商將能夠更好地佔ä½ï¼Œä»¥ä½¿æ–°ç”¢å“快速上市。
許å¯
----
代碼是根據一些許å¯è­‰æä¾›çµ¦Linux內核的,但是所有代碼都必須與GNU通用公共許å¯
證(GPLV2)的版本2兼容,該版本是覆蓋整個內核分發的許å¯è­‰ã€‚在實è¸ä¸­ï¼Œé€™æ„味
-著所有代碼貢ç»éƒ½ç”±GPLv2(å¯é¸åœ°ï¼Œèªžè¨€å…許在更高版本的GPL下分發)或3å­å¥BSD
+ç€æ‰€æœ‰ä»£ç¢¼è²¢ç»éƒ½ç”±GPLv2(å¯é¸åœ°ï¼Œèªžè¨€å…許在更高版本的GPL下分發)或3å­å¥BSD
許å¯ï¼ˆNew BSD License,譯者注)覆蓋。任何ä¸åŒ…å«åœ¨å…¼å®¹è¨±å¯è­‰ä¸­çš„è²¢ç»éƒ½ä¸æœƒ
被接å—到內核中。
è²¢ç»çµ¦å…§æ ¸çš„代碼ä¸éœ€è¦ï¼ˆæˆ–請求)版權分é…。åˆä½µåˆ°ä¸»ç·šå…§æ ¸ä¸­çš„æ‰€æœ‰ä»£ç¢¼éƒ½ä¿ç•™
其原始所有權;因此,內核ç¾åœ¨æ“有數åƒå€‹æ‰€æœ‰è€…。
-é€™ç¨®æ‰€æœ‰æ¬Šçµæ§‹ä¹Ÿæš—示著,任何改變內核許å¯çš„嘗試都註定會失敗。很少有實際情æ³
+é€™ç¨®æ‰€æœ‰æ¬Šçµæ§‹ä¹Ÿæš—示ç€ï¼Œä»»ä½•改變內核許å¯çš„嘗試都註定會失敗。很少有實際情æ³
å¯ä»¥ç²å¾—æ‰€æœ‰ç‰ˆæ¬Šæ‰€æœ‰è€…çš„åŒæ„(或者從內核中刪除他們的代碼)。因此,尤其是在
å¯é è¦‹çš„將來,許å¯è­‰ä¸å¤§å¯èƒ½é·ç§»åˆ°GPL的版本3。
-所有貢ç»çµ¦å…§æ ¸çš„ä»£ç¢¼éƒ½å¿…é ˆæ˜¯åˆæ³•çš„å…è²»è»Ÿé«”ã€‚å› æ­¤ï¼Œä¸æŽ¥å—匿å(或化å)貢ç»
-者的代碼。所有貢ç»è€…都需è¦åœ¨ä»–們的代碼上「sign off(簽發)ã€ï¼Œè²æ˜Žä»£ç¢¼å¯ä»¥
-在GPL下與內核一起分發。無法æä¾›æœªè¢«å…¶æ‰€æœ‰è€…許å¯çˆ²å…費軟體的代碼,或å¯èƒ½çˆ²
+所有貢ç»çµ¦å…§æ ¸çš„ä»£ç¢¼éƒ½å¿…é ˆæ˜¯åˆæ³•çš„å…è²»è»Ÿä»¶ã€‚å› æ­¤ï¼Œä¸æŽ¥å—匿å(或化å)貢ç»
+者的代碼。所有貢ç»è€…都需è¦åœ¨ä»–們的代碼上“sign off(簽發)â€ï¼Œè²æ˜Žä»£ç¢¼å¯ä»¥
+在GPL下與內核一起分發。無法æä¾›æœªè¢«å…¶æ‰€æœ‰è€…許å¯çˆ²å…費軟件的代碼,或å¯èƒ½çˆ²
內核造æˆç‰ˆæ¬Šç›¸é—œå•題的代碼(例如,由缺ä¹é©ç•¶ä¿è­·çš„åå‘工程工作派生的代碼)
ä¸èƒ½è¢«æŽ¥å—。
有關版權å•題的æå•在Linux開發郵件列表中很常見。這樣的å•題通常會得到ä¸å°‘答案,
-但請記ä½ï¼Œå›žç­”這些å•é¡Œçš„äººä¸æ˜¯å¾‹å¸«ï¼Œä¸èƒ½æä¾›æ³•律諮詢。如果您有關於Linux原始碼
-的法律å•題,沒有什麼å¯ä»¥ä»£æ›¿è«®è©¢äº†è§£é€™ä¸€é ˜åŸŸçš„律師。ä¾è³´å¾žæŠ€è¡“郵件列表中ç²å¾—
+但請記ä½ï¼Œå›žç­”這些å•é¡Œçš„äººä¸æ˜¯å¾‹å¸«ï¼Œä¸èƒ½æä¾›æ³•律諮詢。如果您有關於Linuxæºä»£ç¢¼
+的法律å•題,沒有什麼å¯ä»¥ä»£æ›¿è«®è©¢çž­è§£é€™ä¸€é ˜åŸŸçš„律師。ä¾è³´å¾žæŠ€è¡“郵件列表中ç²å¾—
的答案是一件冒險的事情。
diff --git a/Documentation/translations/zh_TW/process/2.Process.rst b/Documentation/translations/zh_TW/process/2.Process.rst
index 17bb4e07d171..49385d65c216 100644
--- a/Documentation/translations/zh_TW/process/2.Process.rst
+++ b/Documentation/translations/zh_TW/process/2.Process.rst
@@ -26,8 +26,8 @@
總覽
----
-內核開發人員使用一個鬆散的基於時間的發布éŽç¨‹ï¼Œæ¯å…©åˆ°ä¸‰å€‹æœˆç™¼å¸ƒä¸€æ¬¡æ–°çš„主è¦
-內核版本。最近的發布歷å²è¨˜éŒ„如下:
+內核開發人員使用一個鬆散的基於時間的發佈éŽç¨‹ï¼Œæ¯å…©åˆ°ä¸‰å€‹æœˆç™¼ä½ˆä¸€æ¬¡æ–°çš„主è¦
+內核版本。最近的發佈歷å²è¨˜éŒ„如下:
====== =================
5.0 2019年3月3日
@@ -42,33 +42,33 @@
版本包å«å¤§ç´„13000個變更集,變更了幾åè¬è¡Œä»£ç¢¼ã€‚因此,5.x是Linux內核開發的å‰
æ²¿ï¼›å…§æ ¸ä½¿ç”¨æ»¾å‹•é–‹ç™¼æ¨¡åž‹ï¼Œä¸æ–·é›†æˆé‡å¤§è®ŠåŒ–。
-å°æ–¼æ¯å€‹ç‰ˆæœ¬çš„補ä¸åˆä½µï¼Œéµå¾ªä¸€å€‹ç›¸å°ç°¡å–®çš„è¦å‰‡ã€‚在æ¯å€‹é–‹ç™¼å‘¨æœŸçš„開頭,「åˆä½µ
-窗å£ã€è¢«æ‰“開。這時,被èªçˆ²è¶³å¤ ç©©å®šï¼ˆä¸¦ä¸”è¢«é–‹ç™¼ç¤¾å€æŽ¥å—)的代碼被åˆä½µåˆ°ä¸»ç·šå…§
-æ ¸ä¸­ã€‚åœ¨é€™æ®µæ™‚é–“å…§ï¼Œæ–°é–‹ç™¼å‘¨æœŸçš„å¤§éƒ¨åˆ†è®Šæ›´ï¼ˆä»¥åŠæ‰€æœ‰ä¸»è¦è®Šæ›´ï¼‰å°‡ä»¥æŽ¥è¿‘æ¯å¤©
-1000次變更(「補ä¸ã€æˆ–「變更集ã€ï¼‰çš„速度åˆä½µã€‚
+å°æ–¼æ¯å€‹ç‰ˆæœ¬çš„補ä¸åˆä½µï¼Œéµå¾ªä¸€å€‹ç›¸å°ç°¡å–®çš„è¦å‰‡ã€‚在æ¯å€‹é–‹ç™¼é€±æœŸçš„開頭,“åˆä½µ
+窗å£â€è¢«æ‰“開。這時,被èªçˆ²è¶³å¤ ç©©å®šï¼ˆä¸¦ä¸”è¢«é–‹ç™¼ç¤¾å€æŽ¥å—)的代碼被åˆä½µåˆ°ä¸»ç·šå…§
+æ ¸ä¸­ã€‚åœ¨é€™æ®µæ™‚é–“å…§ï¼Œæ–°é–‹ç™¼é€±æœŸçš„å¤§éƒ¨åˆ†è®Šæ›´ï¼ˆä»¥åŠæ‰€æœ‰ä¸»è¦è®Šæ›´ï¼‰å°‡ä»¥æŽ¥è¿‘æ¯å¤©
+1000次變更(“補ä¸â€æˆ–“變更集â€ï¼‰çš„速度åˆä½µã€‚
(順便說一å¥ï¼Œå€¼å¾—注æ„的是,åˆä½µçª—壿œŸé–“集æˆçš„æ›´æ”¹ä¸¦ä¸æ˜¯æ†‘空產生的;它們是經
æå‰æ”¶é›†ã€æ¸¬è©¦å’Œåˆ†ç´šçš„。ç¨å¾Œå°‡è©³ç´°æè¿°è©²éŽç¨‹çš„工作方å¼ã€‚)
-åˆä½µçª—壿ŒçºŒå¤§ç´„å…©å‘¨ã€‚åœ¨é€™æ®µæ™‚é–“çµæŸæ™‚,LinusTorvaldså°‡è²æ˜Žçª—å£å·²é—œé–‰ï¼Œä¸¦
-釋放第一個「rcã€å…§æ ¸ã€‚ä¾‹å¦‚ï¼Œå°æ–¼ç›®æ¨™çˆ²5.6的內核,在åˆä½µçª—å£çµæŸæ™‚發生的釋放
+åˆä½µçª—壿ŒçºŒå¤§ç´„å…©é€±ã€‚åœ¨é€™æ®µæ™‚é–“çµæŸæ™‚,Linus Torvaldså°‡è²æ˜Žçª—å£å·²é—œé–‰ï¼Œä¸¦
+釋放第一個“rcâ€å…§æ ¸ã€‚ä¾‹å¦‚ï¼Œå°æ–¼ç›®æ¨™çˆ²5.6的內核,在åˆä½µçª—å£çµæŸæ™‚發生的釋放
將被稱爲5.6-rc1。-rc1 版本是一個信號,表示åˆä½µæ–°ç‰¹æ€§çš„æ™‚間已經éŽåŽ»ï¼Œç©©å®šä¸‹ä¸€
個內核的時間已經到來。
在接下來的6到10å‘¨å…§ï¼Œåªæœ‰ä¿®å¾©å•é¡Œçš„è£œä¸æ‰æ‡‰è©²æäº¤çµ¦ä¸»ç·šã€‚有時會å…許更大的
更改,但這種情æ³å¾ˆå°‘發生;試圖在åˆä½µçª—å£å¤–åˆä½µæ–°åŠŸèƒ½çš„é–‹ç™¼äººå“¡å¾€å¾€å—ä¸åˆ°
å‹å¥½çš„æŽ¥å¾…。一般來說,如果您錯éŽäº†çµ¦å®šç‰¹æ€§çš„åˆä½µçª—å£ï¼Œæœ€å¥½çš„åšæ³•是等待下一
-個開發周期。(å¶çˆ¾æœƒå°æœªæ”¯æŒç¡¬é«”的驅動程åºé€²è¡Œä¾‹å¤–ï¼›å¦‚æžœå®ƒå€‘ä¸æ”¹è®Šå·²æœ‰ä»£ç¢¼ï¼Œ
-則䏿œƒå°Žè‡´å›žæ­¸ï¼Œæ‡‰è©²å¯ä»¥éš¨æ™‚被安全地加入)。
+個開發週期。(å¶çˆ¾æœƒå°æœªæ”¯æŒç¡¬ä»¶çš„驅動程åºé€²è¡Œä¾‹å¤–ï¼›å¦‚æžœå®ƒå€‘ä¸æ”¹è®Šå·²æœ‰ä»£ç¢¼ï¼Œ
+則䏿œƒå°Žè‡´è¿´æ­¸ï¼Œæ‡‰è©²å¯ä»¥éš¨æ™‚被安全地加入)。
-隨著修復程åºé€²å…¥ä¸»ç·šï¼Œè£œä¸é€Ÿåº¦å°‡éš¨è‘—時間的推移而變慢。Linus大約æ¯å‘¨ç™¼å¸ƒä¸€æ¬¡
-æ–°çš„-rc內核;在內核被èªçˆ²è¶³å¤ ç©©å®šä¸¦æœ€çµ‚發布å‰ï¼Œä¸€èˆ¬æœƒé”到-rc6到-rc9之間。
+隨ç€ä¿®å¾©ç¨‹åºé€²å…¥ä¸»ç·šï¼Œè£œä¸é€Ÿåº¦å°‡éš¨ç€æ™‚間的推移而變慢。Linus大約æ¯é€±ç™¼ä½ˆä¸€æ¬¡
+æ–°çš„-rc內核;在內核被èªçˆ²è¶³å¤ ç©©å®šä¸¦æœ€çµ‚發佈å‰ï¼Œä¸€èˆ¬æœƒé”到-rc6到-rc9之間。
然後,整個éŽç¨‹åˆé‡æ–°é–‹å§‹äº†ã€‚
-例如,這裡是5.4的開發周期進行情æ³ï¼ˆ2019年):
+ä¾‹å¦‚ï¼Œé€™è£æ˜¯5.4的開發週期進行情æ³ï¼ˆ2019年):
============== ==============================
- 乿œˆ 15 5.3 穩定版發布
+ 乿œˆ 15 5.3 穩定版發佈
乿œˆ 30 5.4-rc1 åˆä½µçª—å£é—œé–‰
åæœˆ 6 5.4-rc2
åæœˆ 13 5.4-rc3
@@ -77,26 +77,26 @@
å一月 3 5.4-rc6
å一月 10 5.4-rc7
å一月 17 5.4-rc8
- å一月 24 5.4 穩定版發布
+ å一月 24 5.4 穩定版發佈
============== ==============================
-é–‹ç™¼äººå“¡å¦‚ä½•æ±ºå®šä½•æ™‚çµæŸé–‹ç™¼å‘¨æœŸä¸¦å‰µå»ºç©©å®šç‰ˆæœ¬ï¼Ÿæœ€é‡è¦çš„æŒ‡æ¨™æ˜¯ä»¥å‰ç‰ˆæœ¬çš„
-å›žæ­¸åˆ—è¡¨ã€‚ä¸æ­¡è¿Žå‡ºç¾ä»»ä½•錯誤,但是那些破壞了以å‰èƒ½å·¥ä½œçš„系統的錯誤被èªçˆ²æ˜¯
-特別嚴é‡çš„ã€‚å› æ­¤ï¼Œå°Žè‡´å›žæ­¸çš„è£œä¸æ˜¯ä¸å—歡迎的,很å¯èƒ½åœ¨ç©©å®šæœŸå…§åˆªé™¤ã€‚
+é–‹ç™¼äººå“¡å¦‚ä½•æ±ºå®šä½•æ™‚çµæŸé–‹ç™¼é€±æœŸä¸¦å‰µå»ºç©©å®šç‰ˆæœ¬ï¼Ÿæœ€é‡è¦çš„æŒ‡æ¨™æ˜¯ä»¥å‰ç‰ˆæœ¬çš„
+è¿´æ­¸åˆ—è¡¨ã€‚ä¸æ­¡è¿Žå‡ºç¾ä»»ä½•錯誤,但是那些破壞了以å‰èƒ½å·¥ä½œçš„系統的錯誤被èªçˆ²æ˜¯
+特別嚴é‡çš„ã€‚å› æ­¤ï¼Œå°Žè‡´è¿´æ­¸çš„è£œä¸æ˜¯ä¸å—歡迎的,很å¯èƒ½åœ¨ç©©å®šæœŸå…§åˆªé™¤ã€‚
-開發人員的目標是在穩定發布之å‰ä¿®å¾©æ‰€æœ‰å·²çŸ¥çš„回歸。在ç¾å¯¦ä¸–界中,這種完美是
+開發人員的目標是在穩定發佈之å‰ä¿®å¾©æ‰€æœ‰å·²çŸ¥çš„迴歸。在ç¾å¯¦ä¸–界中,這種完美是
很難實ç¾çš„ï¼›åœ¨é€™ç¨®è¦æ¨¡çš„項目中,變數太多了。需è¦èªªæ˜Žçš„æ˜¯ï¼Œå»¶é²æœ€çµ‚ç‰ˆæœ¬åªæœƒ
-使å•題變得更糟;等待下一個åˆä½µçª—å£çš„æ›´æ”¹å°‡è®Šå¤šï¼Œå°Žè‡´ä¸‹æ¬¡å‡ºç¾æ›´å¤šçš„回歸錯誤。
-因此,大多數5.x內核都有一些已知的回歸錯誤,ä¸éŽï¼Œå¸Œæœ›æ²’有一個是嚴é‡çš„。
+使å•題變得更糟;等待下一個åˆä½µçª—å£çš„æ›´æ”¹å°‡è®Šå¤šï¼Œå°Žè‡´ä¸‹æ¬¡å‡ºç¾æ›´å¤šçš„迴歸錯誤。
+因此,大多數5.x內核都有一些已知的迴歸錯誤,ä¸éŽï¼Œå¸Œæœ›æ²’有一個是嚴é‡çš„。
-一旦一個穩定的版本發布,它的æŒçºŒç¶­è­·å·¥ä½œå°±è¢«ç§»äº¤çµ¦ã€Œç©©å®šåœ˜éšŠã€ï¼Œç›®å‰ç”±
-Greg Kroah-Hartman領導。穩定團隊將使用5.x.y編號方案ä¸å®šæœŸåœ°ç™¼å¸ƒç©©å®šç‰ˆæœ¬çš„
+一旦一個穩定的版本發佈,它的æŒçºŒç¶­è­·å·¥ä½œå°±è¢«ç§»äº¤çµ¦â€œç©©å®šåœ˜éšŠâ€ï¼Œç›®å‰ç”±
+Greg Kroah-Hartman領導。穩定團隊將使用5.x.y編號方案ä¸å®šæœŸåœ°ç™¼ä½ˆç©©å®šç‰ˆæœ¬çš„
更新。è¦åˆå…¥æ›´æ–°ç‰ˆæœ¬ï¼Œè£œä¸å¿…須(1)修復一個é‡è¦çš„缺陷,且(2)已經åˆä½µåˆ°
-下一個開發版本主線中。內核通常會在其åˆå§‹ç‰ˆæœ¬å¾Œçš„一個以上的開發周期內收到
+下一個開發版本主線中。內核通常會在其åˆå§‹ç‰ˆæœ¬å¾Œçš„一個以上的開發週期內收到
穩定版更新。例如,5.2內核的歷å²å¦‚下(2019年):
============== ===============================
- 七月 7 5.2 穩定版發布
+ 七月 7 5.2 穩定版發佈
七月 13 5.2.1
七月 21 5.2.2
七月 26 5.2.3
@@ -108,7 +108,7 @@ Greg Kroah-Hartman領導。穩定團隊將使用5.x.y編號方案ä¸å®šæœŸåœ°ç™¼
5.2.21是5.2版本的最終穩定更新。
-有些內核被指定爲「長期ã€å…§æ ¸ï¼›å®ƒå€‘將得到更長時間的支æŒã€‚在本文中,當å‰çš„長期
+有些內核被指定爲“長期â€å…§æ ¸ï¼›å®ƒå€‘將得到更長時間的支æŒã€‚在本文中,當å‰çš„長期
å…§æ ¸åŠå…¶ç¶­è­·è€…是:
====== ================================ ================
@@ -121,9 +121,9 @@ Greg Kroah-Hartman領導。穩定團隊將使用5.x.y編號方案ä¸å®šæœŸåœ°ç™¼
====== ================================ ================
長期支æŒå…§æ ¸çš„鏿“‡ç´”ç²¹æ˜¯ç¶­è­·äººå“¡æ˜¯å¦æœ‰éœ€æ±‚和時間來維護該版本的å•題。
-ç›®å‰é‚„沒有爲å³å°‡ç™¼å¸ƒçš„任何特定版本æä¾›é•·æœŸæ”¯æŒçš„已知計劃。
+ç›®å‰é‚„沒有爲å³å°‡ç™¼ä½ˆçš„任何特定版本æä¾›é•·æœŸæ”¯æŒçš„已知計劃。
-補ä¸çš„生命周期
+補ä¸çš„生命週期
--------------
補ä¸ä¸æœƒç›´æŽ¥å¾žé–‹ç™¼äººå“¡çš„éµç›¤é€²å…¥ä¸»ç·šå…§æ ¸ã€‚相å,有一個ç¨å¾®è¤‡é›œï¼ˆå¦‚果有些éž
@@ -140,7 +140,7 @@ Greg Kroah-Hartman領導。穩定團隊將使用5.x.y編號方案ä¸å®šæœŸåœ°ç™¼
æ˜¯åœ¨ä¸æ¶‰åŠç¤¾å€çš„æƒ…æ³ä¸‹å®Œæˆçš„,但是如果å¯èƒ½çš„話,最好是在公開的情æ³ä¸‹å®Œæˆ
這項工作;這樣å¯ä»¥ç¯€çœå¾ˆå¤šç¨å¾Œå†é‡æ–°è¨­è¨ˆçš„æ™‚間。
-- 早期評審。補ä¸è¢«ç™¼å¸ƒåˆ°ç›¸é—œçš„郵件列表中,列表中的開發人員會回復他們å¯èƒ½æœ‰
+- 早期評審。補ä¸è¢«é«®å¸ƒåˆ°ç›¸é—œçš„郵件列表中,列表中的開發人員會回覆他們å¯èƒ½æœ‰
的任何評論。如果一切順利的話,這個éŽç¨‹æ‡‰è©²æœƒç™¼ç¾è£œä¸çš„任何主è¦å•題。
- æ›´å»£æ³›çš„è©•å¯©ã€‚ç•¶è£œä¸æŽ¥è¿‘æº–å‚™å¥½ç´å…¥ä¸»ç·šæ™‚,它應該被相關的å­ç³»çµ±ç¶­è­·äººå“¡
@@ -153,48 +153,48 @@ Greg Kroah-Hartman領導。穩定團隊將使用5.x.y編號方案ä¸å®šæœŸåœ°ç™¼
如果您的補ä¸å¾—åˆ°äº†éœ€è¦æ›´æ”¹çš„å饋,那麼您應該進行這些更改,或者解釋爲何
䏿‡‰è©²é€²è¡Œé€™äº›æ›´æ”¹ã€‚å¦‚æžœæ‚¨çš„è£œä¸æ²’有評審æ„見,也沒有被其相應的å­ç³»çµ±æˆ–
驅動程åºç¶­è­·è€…接å—,那麼您應該堅æŒä¸æ‡ˆåœ°å°‡è£œä¸æ›´æ–°åˆ°ç•¶å‰å…§æ ¸ä½¿å…¶å¯è¢«æ­£å¸¸
- æ‡‰ç”¨ï¼Œä¸¦ä¸æ–·åœ°ç™¼é€å®ƒä»¥ä¾›å¯©æŸ¥å’Œåˆä½µã€‚
+ æ‡‰ç”¨ï¼Œä¸¦ä¸æ–·åœ°ç™¼é€å®ƒä»¥ä¾›å¯©æŸ¥å’Œåˆä¸¦ã€‚
- åˆä½µåˆ°ä¸»ç·šã€‚最終,一個æˆåŠŸçš„è£œä¸å°‡è¢«åˆä½µåˆ°ç”±LinusTorvalds管ç†çš„主線存儲庫
中。此時å¯èƒ½æœƒå‡ºç¾æ›´å¤šçš„è©•è«–å’Œ/或å•題;å°é–‹ç™¼äººå“¡ä¾†èªªæ‡‰å°é€™äº›å•題並解決
出ç¾çš„任何å•題ä»å¾ˆé‡è¦ã€‚
-- 穩定版發布。大é‡ç”¨æˆ¶å¯èƒ½å—此補ä¸å½±éŸ¿ï¼Œå› æ­¤å¯èƒ½å†æ¬¡å‡ºç¾æ–°çš„å•題。
+- 穩定版發佈。大é‡ç”¨æˆ¶å¯èƒ½å—此補ä¸å½±éŸ¿ï¼Œå› æ­¤å¯èƒ½å†æ¬¡å‡ºç¾æ–°çš„å•題。
- 長期維護。雖然開發人員在åˆä½µä»£ç¢¼å¾Œå¯èƒ½æœƒå¿˜è¨˜ä»£ç¢¼ï¼Œä½†é€™ç¨®è¡Œçˆ²å¾€å¾€æœƒçµ¦é–‹ç™¼
社å€ç•™ä¸‹ä¸è‰¯å°è±¡ã€‚åˆä½µä»£ç¢¼æ¶ˆé™¤äº†ä¸€äº›ç¶­è­·è² æ“”,因爲其他人將修復由API更改
引起的å•題。但是,如果代碼è¦é•·æœŸä¿æŒå¯ç”¨ï¼ŒåŽŸå§‹é–‹ç™¼äººå“¡æ‡‰è©²ç¹¼çºŒçˆ²ä»£ç¢¼è² è²¬ã€‚
-內核開發人員(或他們的僱主)犯的最大錯誤之一是試圖將æµç¨‹ç°¡åŒ–爲一個「åˆä½µåˆ°
-ä¸»ç·šã€æ­¥é©Ÿã€‚這種方法總是會讓所有相關人員感到沮喪。
+內核開發人員(或他們的僱主)犯的最大錯誤之一是試圖將æµç¨‹ç°¡åŒ–爲一個“åˆä½µåˆ°
+ä¸»ç·šâ€æ­¥é©Ÿã€‚這種方法總是會讓所有相關人員感到沮喪。
補ä¸å¦‚何進入內核
----------------
-åªæœ‰ä¸€å€‹äººå¯ä»¥å°‡è£œä¸åˆä½µåˆ°ä¸»ç·šå…§æ ¸å­˜å„²åº«ä¸­ï¼šLinusTorvalds。但是,在進入
+åªæœ‰ä¸€å€‹äººå¯ä»¥å°‡è£œä¸åˆä½µåˆ°ä¸»ç·šå…§æ ¸å­˜å„²åº«ä¸­ï¼šLinus Torvalds。但是,在進入
2.6.38內核的9500多個補ä¸ä¸­ï¼Œåªæœ‰112個(大約1.3%)是由Linusè‡ªå·±ç›´æŽ¥é¸æ“‡çš„。
內核項目已經發展到一個沒有一個開發人員å¯ä»¥åœ¨æ²’有支æŒçš„æƒ…æ³ä¸‹æª¢æŸ¥å’Œé¸æ“‡æ¯å€‹
補ä¸çš„è¦æ¨¡ã€‚內核開發人員處ç†é€™ç¨®å¢žé•·çš„æ–¹å¼æ˜¯ä½¿ç”¨åœç¹žä¿¡ä»»éˆæ§‹å»ºçš„助ç†ç³»çµ±ã€‚
內核代碼庫在é‚輯上被分解爲一組å­ç³»çµ±ï¼šç¶²çµ¡ã€ç‰¹å®šé«”ç³»çµæ§‹æ”¯æŒã€å…§å­˜ç®¡ç†ã€è¦–
頻設備等。大多數å­ç³»çµ±éƒ½æœ‰ä¸€å€‹æŒ‡å®šçš„維護人員,其總體負責該å­ç³»çµ±ä¸­çš„代碼。
-這些å­ç³»çµ±ç¶­è­·è€…(鬆散地)是他們所管ç†çš„內核部分的「守門員ã€ï¼›ä»–們(通常)
+這些å­ç³»çµ±ç¶­è­·è€…(鬆散地)是他們所管ç†çš„內核部分的“守門員â€ï¼›ä»–們(通常)
會接å—一個補ä¸ä»¥åŒ…å«åˆ°ä¸»ç·šå…§æ ¸ä¸­ã€‚
-å­ç³»çµ±ç¶­è­·äººå“¡æ¯å€‹äººéƒ½ç®¡ç†è‘—自己版本的內核原始碼樹,通常(並éžç¸½æ˜¯ï¼‰ä½¿ç”¨Git。
+å­ç³»çµ±ç¶­è­·äººå“¡æ¯å€‹äººéƒ½ç®¡ç†ç€è‡ªå·±ç‰ˆæœ¬çš„å…§æ ¸æºä»£ç¢¼æ¨¹ï¼Œé€šå¸¸ï¼ˆä¸¦éžç¸½æ˜¯ï¼‰ä½¿ç”¨Git。
Git等工具(以åŠQuilt或Mercurial等相關工具)å…許維護人員跟蹤補ä¸åˆ—表,包括作者
ä¿¡æ¯å’Œå…¶ä»–元數據。在任何給定的時間,維護人員都å¯ä»¥ç¢ºå®šä»–或她的存儲庫中的哪
些補ä¸åœ¨ä¸»ç·šä¸­æ‰¾ä¸åˆ°ã€‚
-ç•¶åˆä½µçª—壿‰“é–‹æ™‚ï¼Œé ‚ç´šç¶­è­·äººå“¡å°‡è¦æ±‚Linus從存儲庫中「拉出ã€ä»–們爲åˆä½µé¸æ“‡
+ç•¶åˆä¸¦çª—壿‰“é–‹æ™‚ï¼Œé ‚ç´šç¶­è­·äººå“¡å°‡è¦æ±‚Linus從存儲庫中“拉出â€ä»–們爲åˆä½µé¸æ“‡
的補ä¸ã€‚如果LinusåŒæ„ï¼Œè£œä¸æµå°‡æµå‘他的存儲庫,æˆçˆ²ä¸»ç·šå…§æ ¸çš„一部分。
Linuså°æ‹‰å–中接收到的特定補ä¸çš„關注程度å„ä¸ç›¸åŒã€‚很明顯,有時他看起來很
-關注。但是一般來說,Linus相信å­ç³»çµ±ç¶­è­·äººå“¡ä¸æœƒå‘上游發é€å£žè£œä¸ã€‚
+關注。但是一般來說,Linus相信å­ç³»çµ±ç¶­è­·äººå“¡ä¸æœƒå‘上éŠç™¼é€å£žè£œä¸ã€‚
-å­ç³»çµ±ç¶­è­·äººå“¡åéŽä¾†ä¹Ÿå¯ä»¥å¾žå…¶ä»–維護人員那裡ç²å–補ä¸ã€‚例如,網絡樹是由首先
+å­ç³»çµ±ç¶­è­·äººå“¡åéŽä¾†ä¹Ÿå¯ä»¥å¾žå…¶ä»–維護人員那è£ç²å–補ä¸ã€‚例如,網絡樹是由首先
在專用於網絡設備驅動程åºã€ç„¡ç·šç¶²çµ¡ç­‰çš„æ¨¹ä¸­ç©ç´¯çš„è£œä¸æ§‹å»ºçš„。此存儲éˆå¯ä»¥
-ä»»æ„長,但很少超éŽå…©å€‹æˆ–三個連çµã€‚由於éˆä¸­çš„æ¯å€‹ç¶­è­·è€…éƒ½ä¿¡ä»»é‚£äº›ç®¡ç†è¼ƒä½Ž
-級別樹的維護者,所以這個éŽç¨‹ç¨±çˆ²ã€Œä¿¡ä»»éˆã€ã€‚
+ä»»æ„長,但很少超éŽå…©å€‹æˆ–ä¸‰å€‹éˆæŽ¥ã€‚ç”±æ–¼éˆä¸­çš„æ¯å€‹ç¶­è­·è€…éƒ½ä¿¡ä»»é‚£äº›ç®¡ç†è¼ƒä½Ž
+級別樹的維護者,所以這個éŽç¨‹ç¨±çˆ²â€œä¿¡ä»»éˆâ€ã€‚
顯然,在這樣的系統中,ç²å–內核補ä¸å–決於找到正確的維護者。直接å‘Linus發é€
補ä¸é€šå¸¸ä¸æ˜¯æ­£ç¢ºçš„æ–¹æ³•。
@@ -204,30 +204,30 @@ Next 樹
å­ç³»çµ±æ¨¹éˆå¼•å°Žè£œä¸æµåˆ°å…§æ ¸ï¼Œä½†å®ƒä¹Ÿæå‡ºäº†ä¸€å€‹æœ‰è¶£çš„å•題:如果有人想查看爲
下一個åˆä½µçª—壿º–å‚™çš„æ‰€æœ‰è£œä¸æ€Žéº¼è¾¦ï¼Ÿé–‹ç™¼äººå“¡å°‡æ„Ÿèˆˆè¶£çš„æ˜¯ï¼Œé‚„有什麼其他的
-更改有待解決,以了解是å¦å­˜åœ¨éœ€è¦æ“”心的è¡çªï¼›ä¾‹å¦‚,更改核心內核函數原型的
+更改有待解決,以瞭解是å¦å­˜åœ¨éœ€è¦æ“”心的è¡çªï¼›ä¾‹å¦‚,更改核心內核函數原型的
修補程åºå°‡èˆ‡ä½¿ç”¨è©²å‡½æ•¸èˆŠå½¢å¼çš„任何其他修補程åºè¡çªã€‚審查人員和測試人員希望
在所有這些變更到é”主線內核之å‰ï¼Œèƒ½å¤ è¨ªå•它們的集æˆå½¢å¼çš„變更。您å¯ä»¥å¾žæ‰€æœ‰
相關的å­ç³»çµ±æ¨¹ä¸­æå–更改,但這將是一項複雜且容易出錯的工作。
-解決方案以-next樹的形å¼å‡ºç¾ï¼Œåœ¨é€™è£¡å­ç³»çµ±æ¨¹è¢«æ”¶é›†ä»¥ä¾›æ¸¬è©¦å’Œå¯©æŸ¥ã€‚這些樹中
-ç”±Andrew Morton維護的較è€çš„一個,被稱爲「-mmã€ï¼ˆç”¨æ–¼å…§å­˜ç®¡ç†ï¼Œå‰µå»ºæ™‚爲此)。
+解決方案以-next樹的形å¼å‡ºç¾ï¼Œåœ¨é€™è£å­ç³»çµ±æ¨¹è¢«æ”¶é›†ä»¥ä¾›æ¸¬è©¦å’Œå¯©æŸ¥ã€‚這些樹中
+ç”±Andrew Morton維護的較è€çš„一個,被稱爲“-mmâ€ï¼ˆç”¨æ–¼å…§å­˜ç®¡ç†ï¼Œå‰µå»ºæ™‚爲此)。
-mm 樹集æˆäº†ä¸€é•·ä¸²å­ç³»çµ±æ¨¹ä¸­çš„補ä¸ï¼›å®ƒé‚„包å«ä¸€äº›æ—¨åœ¨å¹«åŠ©èª¿è©¦çš„è£œä¸ã€‚
除此之外,-mm 還包å«å¤§é‡ç”±Andrewç›´æŽ¥é¸æ“‡çš„補ä¸ã€‚這些補ä¸å¯èƒ½å·²ç¶“發布在郵件
列表上,或者它們å¯èƒ½æ‡‰ç”¨æ–¼å…§æ ¸ä¸­æœªæŒ‡å®šå­ç³»çµ±æ¨¹çš„éƒ¨åˆ†ã€‚åŒæ™‚,-mm 作爲最後
手段的å­ç³»çµ±æ¨¹ï¼›å¦‚果沒有其他明顯的路徑å¯ä»¥è®“補ä¸é€²å…¥ä¸»ç·šï¼Œé‚£éº¼å®ƒå¾ˆå¯èƒ½æœ€
çµ‚é¸æ“‡-mm 樹。累ç©åœ¨-mm 中的å„ç¨®è£œä¸æœ€çµ‚將被轉發到é©ç•¶çš„å­ç³»çµ±æ¨¹ï¼Œæˆ–者直接
-發é€åˆ°Linus。在典型的開發周期中,大約5-10%的補ä¸é€šéŽ-mm 進入主線。
+發é€åˆ°Linus。在典型的開發週期中,大約5-10%的補ä¸é€šéŽ-mm 進入主線。
-ç•¶å‰-mm 補ä¸å¯åœ¨ã€Œmmotmã€ï¼ˆ-mm of the moment)目錄中找到:
+ç•¶å‰-mm 補ä¸å¯åœ¨â€œmmotmâ€ï¼ˆ-mm of the moment)目錄中找到:
https://www.ozlabs.org/~akpm/mmotm/
然而,使用MMOTM樹å¯èƒ½æœƒå分令人頭疼;它甚至å¯èƒ½ç„¡æ³•編譯。
-下一個周期補ä¸åˆä½µçš„ä¸»è¦æ¨¹æ˜¯linux-next,由Stephen Rothwell 維護。根據設計
+下一個週期補ä¸åˆä½µçš„ä¸»è¦æ¨¹æ˜¯linux-next,由Stephen Rothwell 維護。根據設計
linux-next 是下一個åˆä½µçª—å£é—œé–‰å¾Œä¸»ç·šçš„快照。linux-next樹在Linux-kernel å’Œ
-Linux-next 郵件列表中發布,å¯å¾žä»¥ä¸‹ä½ç½®ä¸‹è¼‰ï¼š
+Linux-next 郵件列表中發佈,å¯å¾žä»¥ä¸‹ä½ç½®ä¸‹è¼‰ï¼š
https://www.kernel.org/pub/linux/kernel/next/
@@ -237,7 +237,7 @@ Linux-next 已經æˆçˆ²å…§æ ¸é–‹ç™¼éŽç¨‹ä¸­ä¸å¯æˆ–缺的一部分;在一個
Staging 樹
----------
-內核原始碼樹包å«drivers/staging/ç›®éŒ„ï¼Œå…¶ä¸­æœ‰è¨±å¤šé©…å‹•ç¨‹åºæˆ–文件系統的å­ç›®éŒ„
+å…§æ ¸æºä»£ç¢¼æ¨¹åŒ…å«drivers/staging/ç›®éŒ„ï¼Œå…¶ä¸­æœ‰è¨±å¤šé©…å‹•ç¨‹åºæˆ–文件系統的å­ç›®éŒ„
正在被添加到內核樹中。它們在ä»ç„¶éœ€è¦æ›´å¤šçš„修正的時候å¯ä»¥ä¿ç•™åœ¨driver/staging/
目錄中;一旦完æˆï¼Œå°±å¯ä»¥å°‡å®ƒå€‘移到內核中。這是一種跟蹤ä¸ç¬¦åˆLinux內核編碼或
è³ªé‡æ¨™æº–的驅動程åºçš„æ–¹æ³•,人們å¯èƒ½å¸Œæœ›ä½¿ç”¨å®ƒå€‘並跟蹤開發。
@@ -251,7 +251,7 @@ Greg Kroah Hartman ç›®å‰è² è²¬ç¶­è­·staging 樹。ä»éœ€è¦ä¿®æ­£çš„驅動程åº
Staging 是一種讓新的驅動程åºé€²å…¥ä¸»ç·šçš„相å°å®¹æ˜“的方法,它們會幸é‹åœ°å¼•èµ·å…¶ä»–
開發人員的注æ„,並迅速改進。然而,進入staging䏦䏿˜¯æ•…事的çµå°¾ï¼›staging中
沒有看到常è¦é€²å±•çš„ä»£ç¢¼æœ€çµ‚å°‡è¢«åˆªé™¤ã€‚ç¶“éŠ·å•†ä¹Ÿå‚¾å‘æ–¼ç›¸å°ä¸é¡˜æ„使用stagingé©…å‹•
-程åºã€‚因此,在æˆçˆ²ä¸€å€‹åˆé©çš„主線驅動的路上,staging 僅是一個中轉站。
+程åºã€‚因此,在æˆçˆ²ä¸€å€‹åˆé©çš„主線驅動的路上,staging 僅是一箇中轉站。
工具
----
@@ -260,9 +260,9 @@ Staging 是一種讓新的驅動程åºé€²å…¥ä¸»ç·šçš„相å°å®¹æ˜“的方法,它
能力。如果沒有é©ç•¶å¼·å¤§çš„工具,整個系統將無法在任何地方正常工作。關於如何使用
這些工具的教程é é è¶…出了本文檔的範åœï¼Œä½†é‚„是用一點篇幅介紹一些關éµé»žã€‚
-到目å‰çˆ²æ­¢ï¼Œå…§æ ¸ç¤¾å€ä½¿ç”¨çš„主è¦åŽŸå§‹ç¢¼ç®¡ç†ç³»çµ±æ˜¯git。Git是在自由軟體社å€ä¸­é–‹ç™¼
-的許多分布å¼ç‰ˆæœ¬æŽ§åˆ¶ç³»çµ±ä¹‹ä¸€ã€‚它éžå¸¸é©åˆå…§æ ¸é–‹ç™¼ï¼Œå› çˆ²å®ƒåœ¨è™•ç†å¤§åž‹å­˜å„²åº«å’Œ
-大é‡è£œä¸æ™‚性能éžå¸¸å¥½ã€‚它也以難以學習和使用而著稱,儘管隨著時間的推移它變得
+到目å‰çˆ²æ­¢ï¼Œå…§æ ¸ç¤¾å€ä½¿ç”¨çš„ä¸»è¦æºä»£ç¢¼ç®¡ç†ç³»çµ±æ˜¯git。Git是在自由軟件社å€ä¸­é–‹ç™¼
+的許多分佈å¼ç‰ˆæœ¬æŽ§åˆ¶ç³»çµ±ä¹‹ä¸€ã€‚它éžå¸¸é©åˆå…§æ ¸é–‹ç™¼ï¼Œå› çˆ²å®ƒåœ¨è™•ç†å¤§åž‹å­˜å„²åº«å’Œ
+大é‡è£œä¸æ™‚性能éžå¸¸å¥½ã€‚å®ƒä¹Ÿä»¥é›£ä»¥å­¸ç¿’å’Œä½¿ç”¨è€Œè‘—ç¨±ï¼Œå„˜ç®¡éš¨ç€æ™‚間的推移它變得
æ›´å¥½äº†ã€‚å°æ–¼å…§æ ¸é–‹ç™¼äººå“¡ä¾†èªªï¼Œå°Gitçš„æŸç¨®ç†Ÿæ‚‰å¹¾ä¹Žæ˜¯ä¸€ç¨®è¦æ±‚ï¼›å³ä½¿ä»–們ä¸å°‡å®ƒ
用於自己的工作,他們也需è¦Git來跟上其他開發人員(以åŠä¸»ç·šï¼‰æ­£åœ¨åšçš„事情。
@@ -270,7 +270,7 @@ Staging 是一種讓新的驅動程åºé€²å…¥ä¸»ç·šçš„相å°å®¹æ˜“的方法,它
https://git-scm.com/
-æ­¤é é¢åŒ…å«äº†æ–‡æª”和教程的連çµã€‚
+æ­¤é é¢åŒ…å«äº†æ–‡æª”å’Œæ•™ç¨‹çš„éˆæŽ¥ã€‚
在ä¸ä½¿ç”¨git的內核開發人員中,最æµè¡Œçš„鏿“‡å¹¾ä¹Žè‚¯å®šæ˜¯Mercurial:
@@ -282,16 +282,16 @@ Mercurial與Git共享許多特性,但它æä¾›äº†ä¸€å€‹ç•Œé¢ï¼Œè¨±å¤šäººè¦ºå¾
https://savannah.nongnu.org/projects/quilt
-Quilt 是一個補ä¸ç®¡ç†ç³»çµ±ï¼Œè€Œä¸æ˜¯åŽŸå§‹ç¢¼ç®¡ç†ç³»çµ±ã€‚å®ƒä¸æœƒéš¨è‘—時間的推移跟蹤歷å²ï¼›
+Quilt 是一個補ä¸ç®¡ç†ç³»çµ±ï¼Œè€Œä¸æ˜¯æºä»£ç¢¼ç®¡ç†ç³»çµ±ã€‚å®ƒä¸æœƒéš¨ç€æ™‚間的推移跟蹤歷å²ï¼›
相å,它é¢å‘æ ¹æ“šä¸æ–·ç™¼å±•的代碼庫跟蹤一組特定的更改。一些主è¦çš„å­ç³»çµ±ç¶­è­·äººå“¡
-使用Quiltä¾†ç®¡ç†æ‰“ç®—å‘上游移動的補ä¸ã€‚å°æ–¼æŸäº›æ¨¹çš„管ç†ï¼ˆä¾‹å¦‚-mm),quilt 是
+使用Quiltä¾†ç®¡ç†æ‰“ç®—å‘上éŠç§»å‹•的補ä¸ã€‚å°æ–¼æŸäº›æ¨¹çš„管ç†ï¼ˆä¾‹å¦‚-mm),quilt 是
最好的工具。
郵件列表
--------
大é‡çš„Linux內核開發工作是通éŽéƒµä»¶åˆ—表完æˆçš„。如果ä¸åŠ å…¥è‡³å°‘ä¸€å€‹æŸå€‹åˆ—表,
-就很難æˆçˆ²ç¤¾å€ä¸­çš„ä¸€å€‹ã€Œå…¨åŠŸèƒ½ã€æˆå“¡ã€‚但是,Linux郵件列表å°é–‹ç™¼äººå“¡ä¾†èªªä¹Ÿæ˜¯
+就很難æˆçˆ²ç¤¾å€ä¸­çš„ä¸€å€‹â€œå…¨åŠŸèƒ½â€æˆå“¡ã€‚但是,Linux郵件列表å°é–‹ç™¼äººå“¡ä¾†èªªä¹Ÿæ˜¯
一個潛在的å±éšªï¼Œä»–們å¯èƒ½æœƒè¢«ä¸€å †é›»å­éƒµä»¶æ·¹æ²’ã€é•åLinux列表上使用的約定,
或者兩者兼而有之。
@@ -316,14 +316,14 @@ redhat.com/mailman/listinfo。
- ä¸è¦å›žå¾©æŒ‘事的人。如果有人試圖激起憤怒,請忽略他們。
-- 當回復Linux內核電å­éƒµä»¶ï¼ˆæˆ–其他列表上的電å­éƒµä»¶ï¼‰æ™‚,請爲所有相關人員ä¿ç•™
+- 當回覆Linux內核電å­éƒµä»¶ï¼ˆæˆ–其他列表上的電å­éƒµä»¶ï¼‰æ™‚,請爲所有相關人員ä¿ç•™
Cc: 抄é€é ­ã€‚如果沒有確實的ç†ç”±ï¼ˆå¦‚æ˜Žç¢ºçš„è«‹æ±‚ï¼‰ï¼Œå‰‡ä¸æ‡‰åˆªé™¤æ”¶ä»¶äººã€‚一定è¦
確ä¿ä½ è¦å›žå¾©çš„人在抄é€åˆ—表中。這個慣例也使你ä¸å¿…åœ¨å›žè¦†éƒµä»¶æ™‚æ˜Žç¢ºè¦æ±‚被抄é€ã€‚
- 在æå‡ºå•題之å‰ï¼Œæœç´¢åˆ—表存檔(和整個網絡)。有些開發人員å¯èƒ½æœƒå°é‚£äº›é¡¯ç„¶
沒有完æˆå®¶åº­ä½œæ¥­çš„人感到ä¸è€ç…©ã€‚
-- é¿å…頂部回復(把你的答案放在你è¦å›žå¾©çš„引文上é¢çš„åšæ³•)。這會讓你的回答更難
+- é¿å…頂部回覆(把你的答案放在你è¦å›žå¾©çš„引文上é¢çš„åšæ³•)。這會讓你的回答更難
ç†è§£ï¼Œå°è±¡ä¹Ÿå¾ˆå·®ã€‚
- 在正確的郵件列表發å•。linux-kernel å¯èƒ½æ˜¯é€šç”¨çš„è¨Žè«–å ´æ‰€ï¼Œä½†å®ƒä¸æ˜¯å°‹æ‰¾æ‰€æœ‰
@@ -332,7 +332,7 @@ redhat.com/mailman/listinfo。
最後一點——找到正確的郵件列表——是開發人員常出錯的地方。在linux-kernel上
æå‡ºèˆ‡ç¶²çµ¡ç›¸é—œçš„å•題的人幾乎肯定會收到一個禮貌的建議,轉到netdev列表上æå‡ºï¼Œ
因爲這是大多數網絡開發人員經常出ç¾çš„列表。還有其他列表å¯ç”¨æ–¼scsiã€video4linuxã€
-ideã€filesystemç­‰å­ç³»çµ±ã€‚查找郵件列表的最佳ä½ç½®æ˜¯èˆ‡å…§æ ¸åŽŸå§‹ç¢¼ä¸€èµ·æ‰“åŒ…çš„
+ideã€filesystemç­‰å­ç³»çµ±ã€‚查找郵件列表的最佳ä½ç½®æ˜¯èˆ‡å…§æ ¸æºä»£ç¢¼ä¸€èµ·æ‰“包的
MAINTAINERS文件。
開始內核開發
@@ -344,7 +344,7 @@ MAINTAINERS文件。
å…¬å¸é€šå¸¸å¸Œæœ›è˜è«‹çŸ¥å的開發人員來啓動開發團隊。實際上,這是一種有效的技術。
但它也往往是昂貴的,而且å°å¢žåŠ æœ‰ç¶“é©—çš„å…§æ ¸é–‹ç™¼äººå“¡çš„æ•¸é‡æ²’有多大幫助。考
慮到時間投入,å¯ä»¥è®“內部開發人員加快Linux內核的開發速度。利用這段時間å¯ä»¥
-è®“åƒ±ä¸»æ“æœ‰ä¸€æ‰¹æ—¢äº†è§£å…§æ ¸åˆäº†è§£å…¬å¸çš„開發人員,還å¯ä»¥å¹«åŠ©åŸ¹è¨“å…¶ä»–äººã€‚å¾žä¸­æœŸ
+è®“åƒ±ä¸»æ“æœ‰ä¸€æ‰¹æ—¢çž­è§£å…§æ ¸åˆçž­è§£å…¬å¸çš„開發人員,還å¯ä»¥å¹«åŠ©åŸ¹è¨“å…¶ä»–äººã€‚å¾žä¸­æœŸ
來看,這通常是更有利å¯åœ–的方法。
å¯ä»¥ç†è§£çš„æ˜¯ï¼Œå–®å€‹é–‹ç™¼äººå“¡å¾€å¾€å°èµ·æ­¥æ„Ÿåˆ°èŒ«ç„¶ã€‚從一個大型項目開始å¯èƒ½æœƒå¾ˆ
@@ -353,17 +353,17 @@ MAINTAINERS文件。
這會分散整個開發社å€çš„æ³¨æ„力,因此,它們越來越被人ä¸çœ‹é‡ã€‚希望å‘社å€ä»‹ç´¹
自己的新開發人員將無法通éŽé€™äº›æ–¹å¼ç²å¾—他們期待的å響。
-Andrew Morton 爲有抱負的內核開發人員æä¾›äº†å¦‚下建議
+Andrew Morton 爲有抱負的內核開發人員æä¾›çž­å¦‚下建議
::
- 所有內核開發者的第一個項目肯定應該是「確ä¿å…§æ ¸åœ¨æ‚¨å¯ä»¥æ“作的所有
- 機器上始終完美é‹è¡Œã€ã€‚通常的方法是和其他人一起解決å•題(這å¯èƒ½éœ€
+ 所有內核開發者的第一個項目肯定應該是“確ä¿å…§æ ¸åœ¨æ‚¨å¯ä»¥æ“作的所有
+ 機器上始終完美é‹è¡Œâ€ã€‚通常的方法是和其他人一起解決å•題(這å¯èƒ½éœ€
è¦å …æŒï¼ï¼‰ï¼Œä½†å°±æ˜¯å¦‚此——這是內核開發的一部分。
(http://lwn.net/Articles/283982/)
-在沒有明顯å•題需è¦è§£æ±ºçš„æƒ…æ³ä¸‹ï¼Œé€šå¸¸å»ºè­°é–‹ç™¼äººå“¡æŸ¥çœ‹ç•¶å‰çš„回歸和開放缺陷
+在沒有明顯å•題需è¦è§£æ±ºçš„æƒ…æ³ä¸‹ï¼Œé€šå¸¸å»ºè­°é–‹ç™¼äººå“¡æŸ¥çœ‹ç•¶å‰çš„迴歸和開放缺陷
列表。從來都ä¸ç¼ºå°‘需è¦è§£æ±ºçš„å•題;通éŽè§£æ±ºé€™äº›å•題,開發人員將從該éŽç¨‹ç²å¾—
ç¶“é©—ï¼ŒåŒæ™‚與開發社å€çš„å…¶ä»–æˆå“¡å»ºç«‹ç›¸äº’å°Šé‡ã€‚
diff --git a/Documentation/translations/zh_TW/process/3.Early-stage.rst b/Documentation/translations/zh_TW/process/3.Early-stage.rst
index 636e506fd196..a6959e6350f4 100644
--- a/Documentation/translations/zh_TW/process/3.Early-stage.rst
+++ b/Documentation/translations/zh_TW/process/3.Early-stage.rst
@@ -26,13 +26,13 @@
--------
與任何工程項目一樣,æˆåŠŸçš„å…§æ ¸æ”¹å–„å¾žæ¸…æ™°æè¿°è¦è§£æ±ºçš„å•題開始。在æŸäº›æƒ…æ³
-下,這個步驟很容易:例如當æŸå€‹ç‰¹å®šç¡¬é«”需è¦é©…å‹•ç¨‹åºæ™‚。ä¸éŽï¼Œåœ¨å…¶ä»–情æ³ä¸‹ï¼Œ
+下,這個步驟很容易:例如當æŸå€‹ç‰¹å®šç¡¬ä»¶éœ€è¦é©…å‹•ç¨‹åºæ™‚。ä¸éŽï¼Œåœ¨å…¶ä»–情æ³ä¸‹ï¼Œ
很容易將實際å•題與建議的解決方案混在一起,這å¯èƒ½æœƒå°Žè‡´éº»ç…©ã€‚
-舉個例å­ï¼šå¹¾å¹´å‰ï¼ŒLinux音頻的開發人員尋求一種方法來é‹è¡Œæ‡‰ç”¨ç¨‹å¼ï¼Œè€Œä¸æœƒå› 
+舉個例å­ï¼šå¹¾å¹´å‰ï¼ŒLinux音頻的開發人員尋求一種方法來é‹è¡Œæ‡‰ç”¨ç¨‹åºï¼Œè€Œä¸æœƒå› 
系統延é²éŽå¤§è€Œå°Žè‡´é€€å‡ºæˆ–å…¶ä»–å•題。他們得到的解決方案是一個連接到Linux安全
-模塊(LSM)框架中的內核模塊;這個模塊å¯ä»¥é…置爲å…許特定的應用程å¼è¨ªå•實時
-調度程åºã€‚這個模塊被實ç¾ä¸¦ç™¼åˆ°linux-kernel郵件列表,在那裡它立å³é‡åˆ°äº†éº»ç…©ã€‚
+模塊(LSM)框架中的內核模塊;這個模塊å¯ä»¥é…置爲å…許特定的應用程åºè¨ªå•實時
+調度程åºã€‚這個模塊被實ç¾ä½µç™¼åˆ°linux-kernel郵件列表,在那è£å®ƒç«‹å³é‡åˆ°äº†éº»ç…©ã€‚
å°æ–¼éŸ³é »é–‹ç™¼äººå“¡ä¾†èªªï¼Œé€™å€‹å®‰å…¨æ¨¡å¡Šè¶³ä»¥è§£æ±ºä»–們當å‰çš„å•é¡Œã€‚ä½†æ˜¯ï¼Œå°æ–¼æ›´å»£æ³›çš„
內核社å€ä¾†èªªï¼Œé€™è¢«è¦–爲å°LSM框架的濫用(LSMæ¡†æž¶ä¸¦ä¸æ‰“算授予他們原本ä¸å…·å‚™çš„
@@ -41,15 +41,15 @@
然而,音頻社å€ç„¡æ³•超越他們實施的特定解決方案來看å•題;他們ä¸é¡˜æ„æŽ¥å—æ›¿ä»£æ–¹æ¡ˆã€‚
ç”±æ­¤ç”¢ç”Ÿçš„åˆ†æ­§ä½¿é€™äº›é–‹ç™¼äººå“¡å°æ•´å€‹å…§æ ¸é–‹ç™¼éŽç¨‹æ„Ÿåˆ°å¤±æœ›ï¼›å…¶ä¸­ä¸€å€‹é–‹ç™¼äººå“¡è¿”回
-到audio列表並發布了以下內容:
+到audio列表併發布了以下內容:
有很多éžå¸¸å¥½çš„Linux內核開發人員,但他們往往會被一羣傲慢的傻瓜所壓倒。
- 試圖å‘這些人傳é”ç”¨æˆ¶éœ€æ±‚æ˜¯æµªè²»æ™‚é–“ã€‚ä»–å€‘å¤ªã€Œè°æ˜Žã€äº†ï¼Œæ ¹æœ¬è½ä¸åˆ°å°‘數
+ 試圖å‘這些人傳é”ç”¨æˆ¶éœ€æ±‚æ˜¯æµªè²»æ™‚é–“ã€‚ä»–å€‘å¤ªâ€œè°æ˜Žâ€äº†ï¼Œæ ¹æœ¬è½ä¸åˆ°å°‘數
人的話。
(http://lwn.net/Articles/131776/)
-實際情æ³å»æ˜¯ä¸åŒçš„;與特定模塊相比,內核開發人員更關心系統穩定性ã€é•·æœŸç¶­è­·
+實際情æ³å»æ˜¯ä¸åŒçš„;與特定模塊相比,內核開發人員更關心繫統穩定性ã€é•·æœŸç¶­è­·
ä»¥åŠæ‰¾åˆ°å•é¡Œçš„æ­£ç¢ºè§£æ±ºæ–¹æ¡ˆã€‚é€™å€‹æ•…äº‹çš„å¯“æ„æ˜¯æŠŠé‡é»žæ”¾åœ¨å•é¡Œä¸Šâ€”â€”è€Œä¸æ˜¯å…·é«”çš„
解決方案上——並在開始編寫代碼之å‰èˆ‡é–‹ç™¼ç¤¾å€è¨Žè«–這個å•題。
@@ -72,7 +72,7 @@
- 很å¯èƒ½å•題是由內核以您ä¸ç†è§£çš„æ–¹å¼è§£æ±ºçš„。Linuxå…§æ ¸å¾ˆå¤§ï¼Œå…·æœ‰è¨±å¤šä¸æ˜Žé¡¯
çš„ç‰¹æ€§å’ŒåŠŸèƒ½ã€‚ä¸¦ä¸æ˜¯æ‰€æœ‰çš„內核功能都åƒäººå€‘所希望的那樣有文檔記錄,而且很
- å®¹æ˜“éºæ¼ä¸€äº›æ±è¥¿ã€‚æŸä½œè€…發布了一個完整的驅動程åºï¼Œé‡è¤‡äº†ä¸€å€‹å…¶ä¸
+ å®¹æ˜“éºæ¼ä¸€äº›æ±è¥¿ã€‚æŸä½œè€…發佈了一個完整的驅動程åºï¼Œé‡è¤‡äº†ä¸€å€‹å…¶ä¸
知é“çš„ç¾æœ‰é©…動程åºã€‚釿–°ç™¼æ˜Žç¾æœ‰è¼ªå­çš„代碼ä¸åƒ…æµªè²»ï¼Œè€Œä¸”ä¸æœƒè¢«æŽ¥å—到主線
內核中。
@@ -83,7 +83,7 @@
å¯èƒ½é¡˜æ„幫助創建這個解決方案。
在內核開發社å€çš„多年經驗給了我們一個明確的教訓:閉門設計和開發的內核代碼總是
-有一些å•題,這些å•é¡Œåªæœ‰åœ¨ä»£ç¢¼ç™¼å¸ƒåˆ°ç¤¾å€ä¸­æ™‚æ‰æœƒè¢«ç™¼ç¾ã€‚有時這些å•題很嚴é‡ï¼Œ
+有一些å•題,這些å•é¡Œåªæœ‰åœ¨ä»£ç¢¼ç™¼ä½ˆåˆ°ç¤¾å€ä¸­æ™‚纔會被發ç¾ã€‚有時這些å•題很嚴é‡ï¼Œ
éœ€è¦æ•¸æœˆæˆ–數年的努力æ‰èƒ½ä½¿ä»£ç¢¼é”到內核社å€çš„æ¨™æº–。例如:
- 設計並實ç¾äº†å–®è™•ç†å™¨ç³»çµ±çš„DeviceScapeç¶²çµ¡æ£§ã€‚åªæœ‰ä½¿å…¶é©åˆæ–¼å¤šè™•ç†å™¨ç³»çµ±ï¼Œ
@@ -103,16 +103,16 @@
找誰交æµï¼Ÿ
----------
-當開發人員決定公開他們的計劃時,下一個å•題是:我們從哪裡開始?答案是找到正確
+當開發人員決定公開他們的計劃時,下一個å•題是:我們從哪è£é–‹å§‹ï¼Ÿç­”案是找到正確
çš„éƒµä»¶åˆ—è¡¨å’Œæ­£ç¢ºçš„ç¶­è­·è€…ã€‚å°æ–¼éƒµä»¶åˆ—表,最好的方法是在維護者(MAINTAINERS)文件
-中查找è¦ç™¼å¸ƒçš„相關ä½ç½®ã€‚如果有一個åˆé©çš„å­ç³»çµ±åˆ—表,那麼其上發布通常比在
-linux-kernel上發布更å¯å–;您更有å¯èƒ½æŽ¥è§¸åˆ°åœ¨ç›¸é—œå­ç³»çµ±ä¸­å…·æœ‰å°ˆæ¥­çŸ¥è­˜çš„開發
+中查找è¦ç™¼ä½ˆçš„相關ä½ç½®ã€‚如果有一個åˆé©çš„å­ç³»çµ±åˆ—表,那麼其上發佈通常比在
+linux-kernel上發佈更å¯å–;您更有å¯èƒ½æŽ¥è§¸åˆ°åœ¨ç›¸é—œå­ç³»çµ±ä¸­å…·æœ‰å°ˆæ¥­çŸ¥è­˜çš„開發
人員,並且環境å¯èƒ½å…·æ”¯æŒæ€§ã€‚
找到維護人員å¯èƒ½æœƒæœ‰é»žå›°é›£ã€‚åŒæ¨£ï¼Œç¶­è­·è€…文件是開始的地方。但是,該文件往往ä¸
-æ˜¯æœ€æ–°çš„ï¼Œä¸¦ä¸”ä¸¦éžæ‰€æœ‰å­ç³»çµ±éƒ½åœ¨é‚£è£¡é¡¯ç¤ºã€‚實際上,維護者文件中列出的人員å¯èƒ½
+æ˜¯æœ€æ–°çš„ï¼Œä¸¦ä¸”ä¸¦éžæ‰€æœ‰å­ç³»çµ±éƒ½åœ¨é‚£è£é¡¯ç¤ºã€‚實際上,維護者文件中列出的人員å¯èƒ½
䏿˜¯ç•¶å‰å¯¦é𛿓”任該角色的人員。因此,當å°è¯ç¹«èª°æœ‰ç–‘啿™‚,一個有用的技巧是使用
-git(尤其是「git-logã€ï¼‰æŸ¥çœ‹æ„Ÿèˆˆè¶£çš„å­ç³»çµ±ä¸­ç•¶å‰æ´»å‹•的用戶。看看誰在寫補ä¸ã€
+git(尤其是“git-logâ€ï¼‰æŸ¥çœ‹æ„Ÿèˆˆè¶£çš„å­ç³»çµ±ä¸­ç•¶å‰æ´»å‹•的用戶。看看誰在寫補ä¸ã€
誰會在這些補ä¸ä¸ŠåŠ ä¸ŠSigned-off-by行簽å(如有)。這些人將是幫助新開發項目的
最佳人é¸ã€‚
@@ -123,7 +123,7 @@ git(尤其是「git-logã€ï¼‰æŸ¥çœ‹æ„Ÿèˆˆè¶£çš„å­ç³»çµ±ä¸­ç•¶å‰æ´»å‹•的用æ
.../scripts/get_maintainer.pl
-當給定「-fã€é¸é …時,此腳本將返回指定文件或目錄的當å‰ç¶­è­·è€…。如果在命令行上
+當給定“-fâ€é¸é …時,此腳本將返回指定文件或目錄的當å‰ç¶­è­·è€…。如果在命令行上
給出了一個補ä¸ï¼Œå®ƒå°‡åˆ—出å¯èƒ½æŽ¥æ”¶è£œä¸å‰¯æœ¬çš„維護人員。有許多é¸é …å¯ä»¥èª¿ç¯€
get_maintainer.plæœç´¢ç¶­è­·è€…的嚴格程度;請å°å¿ƒä½¿ç”¨æ›´æ¿€é€²çš„é¸é …ï¼Œå› çˆ²æœ€çµ‚çµæžœ
å¯èƒ½æœƒåŒ…æ‹¬å°æ‚¨æ­£åœ¨ä¿®æ”¹çš„代碼沒有真正興趣的開發人員。
@@ -134,17 +134,17 @@ get_maintainer.plæœç´¢ç¶­è­·è€…的嚴格程度;請å°å¿ƒä½¿ç”¨æ›´æ¿€é€²çš„é¸
何時郵寄?
----------
-如果å¯èƒ½çš„è©±ï¼Œåœ¨æ—©æœŸéšŽæ®µç™¼å¸ƒä½ çš„è¨ˆåŠƒåªæœƒæ›´æœ‰å¹«åŠ©ã€‚æè¿°æ­£åœ¨è§£æ±ºçš„å•題以åŠå·²ç¶“
+如果å¯èƒ½çš„è©±ï¼Œåœ¨æ—©æœŸéšŽæ®µç™¼ä½ˆä½ çš„è¨ˆåŠƒåªæœƒæ›´æœ‰å¹«åŠ©ã€‚æè¿°æ­£åœ¨è§£æ±ºçš„å•題以åŠå·²ç¶“
制定的關於如何實施的任何計劃。您å¯ä»¥æä¾›çš„任何信æ¯éƒ½å¯ä»¥å¹«åŠ©é–‹ç™¼ç¤¾å€çˆ²é …ç›®
æä¾›æœ‰ç”¨çš„輸入。
在這個階段å¯èƒ½ç™¼ç”Ÿçš„ä¸€ä»¶ä»¤äººæ²®å–ªçš„äº‹æƒ…ä¸æ˜¯å¾—到åå°æ„見,而是很少或根本沒有
å饋。令人傷心的事實是:(1)內核開發人員往往很忙;(2)ä¸ç¼ºå°‘有å®å‰è¨ˆåŠƒä½†
代碼(甚至代碼設想)很少的人去支æŒä»–們;(3)沒有人有義務審查或評論別人發表
-的想法。除此之外,高層級的設計常常隱è—著一些å•題,這些å•é¡Œåªæœ‰åœ¨æœ‰äººçœŸæ­£å˜—試
-實ç¾é€™äº›è¨­è¨ˆæ™‚æ‰æœƒè¢«ç™¼ç¾ï¼›å› æ­¤ï¼Œå…§æ ¸é–‹ç™¼äººå“¡å¯§é¡˜çœ‹åˆ°ä»£ç¢¼ã€‚
+的想法。除此之外,高層級的設計常常隱è—ç€ä¸€äº›å•題,這些å•é¡Œåªæœ‰åœ¨æœ‰äººçœŸæ­£å˜—試
+實ç¾é€™äº›è¨­è¨ˆæ™‚纔會被發ç¾ï¼›å› æ­¤ï¼Œå…§æ ¸é–‹ç™¼äººå“¡å¯§é¡˜çœ‹åˆ°ä»£ç¢¼ã€‚
-如果發布請求評論(RFC)並沒得到什麼有用的評論,ä¸è¦ä»¥çˆ²é€™æ„å‘³è‘—ç„¡äººå°æ­¤é …ç›®
+如果發佈請求評論(RFC)並沒得到什麼有用的評論,ä¸è¦ä»¥çˆ²é€™æ„味ç€ç„¡äººå°æ­¤é …ç›®
æœ‰èˆˆè¶£ï¼ŒåŒæ™‚你也ä¸èƒ½å‡è¨­ä½ çš„æƒ³æ³•沒有å•題。在這種情æ³ä¸‹ï¼Œæœ€å¥½çš„åšæ³•是繼續進
行,把你的進展隨時通知社å€ã€‚
@@ -152,12 +152,12 @@ get_maintainer.plæœç´¢ç¶­è­·è€…的嚴格程度;請å°å¿ƒä½¿ç”¨æ›´æ¿€é€²çš„é¸
-----------------------
如果您的工作是在公å¸ç’°å¢ƒä¸­å®Œæˆçš„,就åƒå¤§å¤šæ•¸Linux內核工作一樣;顯然,在您將
-å…¬å¸çš„計劃或代碼發布到公共郵件列表之å‰ï¼Œå¿…é ˆç²å¾—有é©ç•¶æ¬Šåˆ©ç¶“ç†çš„許å¯ã€‚發布
-ä¸ç¢ºå®šæ˜¯å¦å…¼å®¹GPL的代碼尤其會帶來å•題;公å¸çš„管ç†å±¤å’Œæ³•律人員越早能夠就發布
+å…¬å¸çš„計劃或代碼發佈到公共郵件列表之å‰ï¼Œå¿…é ˆç²å¾—有é©ç•¶æ¬Šåˆ©ç¶“ç†çš„許å¯ã€‚發佈
+ä¸ç¢ºå®šæ˜¯å¦å…¼å®¹GPL的代碼尤其會帶來å•題;公å¸çš„管ç†å±¤å’Œæ³•律人員越早能夠就發佈
å…§æ ¸é–‹ç™¼é …ç›®é”æˆä¸€è‡´ï¼Œå°åƒèˆ‡çš„æ¯å€‹äººéƒ½è¶Šå¥½ã€‚
一些讀者å¯èƒ½æœƒèªçˆ²ä»–們的核心工作是爲了支æŒé‚„æ²’æœ‰æ­£å¼æ‰¿èªå­˜åœ¨çš„產å“。將僱主
-的計劃公布在公共郵件列表上å¯èƒ½ä¸æ˜¯ä¸€å€‹å¯è¡Œçš„鏿“‡ã€‚在這種情æ³ä¸‹ï¼Œæœ‰å¿…è¦è€ƒæ…®
+的計劃公佈在公共郵件列表上å¯èƒ½ä¸æ˜¯ä¸€å€‹å¯è¡Œçš„鏿“‡ã€‚在這種情æ³ä¸‹ï¼Œæœ‰å¿…è¦è€ƒæ…®
ä¿å¯†æ˜¯å¦çœŸçš„æ˜¯å¿…è¦çš„;通常ä¸éœ€è¦æŠŠé–‹ç™¼è¨ˆåŠƒé—œåœ¨é–€å…§ã€‚
的確,有些情æ³ä¸‹ä¸€å®¶å…¬å¸åœ¨é–‹ç™¼éŽç¨‹çš„æ—©æœŸç„¡æ³•åˆæ³•åœ°æŠ«éœ²å…¶è¨ˆåŠƒã€‚æ“æœ‰ç¶“é©—è±å¯Œ
diff --git a/Documentation/translations/zh_TW/process/4.Coding.rst b/Documentation/translations/zh_TW/process/4.Coding.rst
index adb5339aab6a..7a4e01eabd81 100644
--- a/Documentation/translations/zh_TW/process/4.Coding.rst
+++ b/Documentation/translations/zh_TW/process/4.Coding.rst
@@ -19,7 +19,7 @@
======================
雖然一個堅實的ã€é¢å‘社å€çš„設計éŽç¨‹æœ‰å¾ˆå¤šå€¼å¾—說é“的,但是任何內核開發項目工作
-çš„è­‰æ˜Žéƒ½åæ˜ åœ¨ä»£ç¢¼ä¸­ã€‚它是將由其他開發人員檢查併åˆä¸¦ï¼ˆæˆ–ä¸åˆä½µï¼‰åˆ°ä¸»ç·šæ¨¹ä¸­
+çš„è­‰æ˜Žéƒ½åæ˜ åœ¨ä»£ç¢¼ä¸­ã€‚它是將由其他開發人員檢查併åˆä¸¦ï¼ˆæˆ–ä¸åˆä¸¦ï¼‰åˆ°ä¸»ç·šæ¨¹ä¸­
çš„ä»£ç¢¼ã€‚æ‰€ä»¥é€™æ®µä»£ç¢¼çš„è³ªé‡æ±ºå®šäº†é …目的最終æˆåŠŸã€‚
本節將檢查編碼éŽç¨‹ã€‚我們將從內核開發人員常犯的幾種錯誤開始。然後é‡é»žå°‡è½‰ç§»
@@ -32,7 +32,7 @@
********
內核長期以來都有其標準的代碼風格,如
-:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+:ref:`Documentation/translations/zh_CN/process/coding-style.rst <tw_codingstyle>`
中所述。在多數時候,該文檔中æè¿°çš„æº–則至多被èªçˆ²æ˜¯å»ºè­°æ€§çš„。因此,內核中存在
大é‡ä¸ç¬¦åˆä»£ç¢¼é¢¨æ ¼æº–則的代碼。這種代碼的存在會給內核開發人員帶來兩方é¢çš„å±å®³ã€‚
@@ -42,7 +42,7 @@
開發人員能夠快速ç†è§£å…¶ä¸­çš„任何部分。所以å†ä¹Ÿç¶“ä¸èµ·å¥‡æ€ªæ ¼å¼çš„代碼的折騰了。
內核的代碼風格å¶çˆ¾æœƒèˆ‡åƒ±ä¸»çš„強制風格發生è¡çªã€‚在這種情æ³ä¸‹ï¼Œå¿…須在代碼åˆä½µ
-之å‰éµå¾žå…§æ ¸ä»£ç¢¼é¢¨æ ¼ã€‚將代碼放入內核æ„å‘³è‘—ä»¥å¤šç¨®æ–¹å¼æ”¾æ£„一定程度的控制權——
+之å‰éµå¾žå…§æ ¸ä»£ç¢¼é¢¨æ ¼ã€‚將代碼放入內核æ„味ç€ä»¥å¤šç¨®æ–¹å¼æ”¾æ£„一定程度的控制權——
包括控制代碼樣å¼ã€‚
å¦ä¸€å€‹å±å®³æ˜¯èªçˆ²å·²ç¶“在內核中的代碼迫切需è¦ä¿®å¾©ä»£ç¢¼æ¨£å¼ã€‚開發者å¯èƒ½æœƒé–‹å§‹ç·¨å¯«
@@ -70,21 +70,21 @@
ç°¡å–®é»žï¼Œå…ˆè€ƒæ…®ä¸€å€‹èª¿ç”¨æ™‚å§‹çµ‚åªæœ‰ä¸€å€‹åƒæ•¸ä¸”總爲零的函數。我們å¯ä»¥ä¿ç•™é€™å€‹åƒæ•¸ï¼Œ
以在需è¦ä½¿ç”¨å®ƒæ™‚æä¾›çš„é¡å¤–éˆæ´»æ€§ã€‚ä¸éŽï¼Œåœ¨é‚£æ™‚實ç¾äº†é€™å€‹é¡å¤–åƒæ•¸çš„代碼很有
å¯èƒ½ä»¥æŸç¨®å¾žæœªè¢«æ³¨æ„到的微妙方å¼è¢«ç ´å£žâ€”—因爲它從未被使用éŽã€‚或者當需è¦é¡å¤–
-çš„éˆæ´»æ€§æ™‚,它並未以符åˆç¨‹å¼è¨­è¨ˆå¸«ç•¶åˆæœŸæœ›çš„æ–¹å¼ä¾†å¯¦ç¾ã€‚內核開發人員通常會æäº¤
+çš„éˆæ´»æ€§æ™‚,它並未以符åˆç¨‹åºå“¡ç•¶åˆæœŸæœ›çš„æ–¹å¼ä¾†å¯¦ç¾ã€‚內核開發人員通常會æäº¤
補ä¸ä¾†åˆªé™¤æœªä½¿ç”¨çš„åƒæ•¸ï¼›ä¸€èˆ¬ä¾†èªªï¼Œä¸€é–‹å§‹å°±ä¸æ‡‰è©²æ·»åŠ é€™äº›åƒæ•¸ã€‚
-éš±è—硬體訪å•的抽象層——通常爲了å…許大é‡çš„驅動程åºå…¼å®¹å¤šå€‹ä½œæ¥­ç³»çµ±â€”—尤其ä¸å—
+éš±è—硬件訪å•的抽象層——通常爲了å…許大é‡çš„驅動程åºå…¼å®¹å¤šå€‹æ“作系統——尤其ä¸å—
歡迎。這樣的層使代碼變得模糊,å¯èƒ½æœƒé€ æˆæ€§èƒ½æå¤±ï¼›å®ƒå€‘ä¸å±¬æ–¼Linux內核。
å¦ä¸€æ–¹é¢ï¼Œå¦‚果您發ç¾è‡ªå·±å¾žå¦ä¸€å€‹å…§æ ¸å­ç³»çµ±è¤‡è£½äº†å¤§é‡çš„代碼,那麼是時候
-了解一下:是å¦éœ€è¦å°‡é€™äº›ä»£ç¢¼ä¸­çš„部分æå–到單ç¨çš„庫中,或者在更高的層次上
+瞭解一下:是å¦éœ€è¦å°‡é€™äº›ä»£ç¢¼ä¸­çš„部分æå–到單ç¨çš„庫中,或者在更高的層次上
實ç¾é€™äº›åŠŸèƒ½ã€‚åœ¨æ•´å€‹å…§æ ¸ä¸­è¤‡è£½ç›¸åŒçš„代碼沒有價值。
#ifdef å’Œé è™•ç†
***************
-Cé è™•ç†å™¨ä¼¼ä¹Žçµ¦ä¸€äº›C程å¼è¨­è¨ˆå¸«å¸¶ä¾†äº†å¼·å¤§çš„誘惑,他們èªçˆ²å®ƒæ˜¯ä¸€ç¨®å°‡å¤§é‡éˆæ´»æ€§åŠ å…¥
-原始碼中的方法。但是é è™•ç†å™¨ä¸æ˜¯C,大é‡ä½¿ç”¨å®ƒæœƒå°Žè‡´ä»£ç¢¼å°å…¶ä»–人來說更難閱讀,
+Cé è™•ç†å™¨ä¼¼ä¹Žçµ¦ä¸€äº›C程åºå“¡å¸¶ä¾†äº†å¼·å¤§çš„誘惑,他們èªçˆ²å®ƒæ˜¯ä¸€ç¨®å°‡å¤§é‡éˆæ´»æ€§åŠ å…¥
+æºä»£ç¢¼ä¸­çš„æ–¹æ³•。但是é è™•ç†å™¨ä¸æ˜¯C,大é‡ä½¿ç”¨å®ƒæœƒå°Žè‡´ä»£ç¢¼å°å…¶ä»–人來說更難閱讀,
å°ç·¨è­¯å™¨ä¾†èªªæ›´é›£æª¢æŸ¥æ­£ç¢ºæ€§ã€‚使用了大é‡é è™•ç†å™¨å¹¾ä¹Žç¸½æ˜¯ä»£ç¢¼éœ€è¦ä¸€äº›
清ç†å·¥ä½œçš„æ¨™èªŒã€‚
@@ -100,23 +100,23 @@ Cé è™•ç†å™¨å®å­˜åœ¨è¨±å¤šå±éšªæ€§ï¼ŒåŒ…括å¯èƒ½å°å…·æœ‰å‰¯ä½œç”¨ä¸”沒有é
å…§è¯å‡½æ•¸
********
-ä¸éŽï¼Œå…§è¯å‡½æ•¸æœ¬èº«ä¹Ÿå­˜åœ¨é¢¨éšªã€‚程å¼è¨­è¨ˆå¸«å¯ä»¥å‚¾å¿ƒæ–¼é¿å…函數調用和用內è¯å‡½æ•¸å¡«å……æº
+ä¸éŽï¼Œå…§è¯å‡½æ•¸æœ¬èº«ä¹Ÿå­˜åœ¨é¢¨éšªã€‚程åºå“¡å¯ä»¥å‚¾å¿ƒæ–¼é¿å…函數調用和用內è¯å‡½æ•¸å¡«å……æº
文件所固有的效率。然而,這些功能實際上會é™ä½Žæ€§èƒ½ã€‚因爲它們的代碼在æ¯å€‹èª¿ç”¨ç«™
-點都被複製一é,所以最終會增加編譯內核的大å°ã€‚此外,這也å°è™•ç†å™¨çš„內存緩存
+點都被複制一é,所以最終會增加編譯內核的大å°ã€‚此外,這也å°è™•ç†å™¨çš„內存緩存
造æˆå£“力,從而大大é™ä½ŽåŸ·è¡Œé€Ÿåº¦ã€‚通常內è¯å‡½æ•¸æ‡‰è©²éžå¸¸å°ï¼Œè€Œä¸”相å°è¼ƒå°‘。畢竟
å‡½æ•¸èª¿ç”¨çš„æˆæœ¬ä¸¦ä¸é«˜ï¼›å¤§é‡å‰µå»ºå…§è¯å‡½æ•¸æ˜¯éŽæ—©å„ªåŒ–的典型例å­ã€‚
-一般來說,內核程å¼è¨­è¨ˆå¸«æœƒè‡ªå†’é¢¨éšªå¿½ç•¥ç·©å­˜æ•ˆæžœã€‚åœ¨æ•¸æ“šçµæ§‹èª²ç¨‹é–‹é ­ä¸­çš„ç¶“å…¸
-時間/空間權衡通常ä¸é©ç”¨æ–¼ç•¶ä»£ç¡¬é«”。空間 *就是* æ™‚é–“ï¼Œå› çˆ²ä¸€å€‹å¤§çš„ç¨‹åºæ¯”一個
+一般來說,內核程åºå“¡æœƒè‡ªå†’é¢¨éšªå¿½ç•¥ç·©å­˜æ•ˆæžœã€‚åœ¨æ•¸æ“šçµæ§‹èª²ç¨‹é–‹é ­ä¸­çš„ç¶“å…¸
+時間/空間權衡通常ä¸é©ç”¨æ–¼ç•¶ä»£ç¡¬ä»¶ã€‚空間 *就是* æ™‚é–“ï¼Œå› çˆ²ä¸€å€‹å¤§çš„ç¨‹åºæ¯”一個
更緊湊的程åºé‹è¡Œå¾—慢。
è¼ƒæ–°çš„ç·¨è­¯å™¨è¶Šä¾†è¶Šæ¿€é€²åœ°æ±ºå®šä¸€å€‹çµ¦å®šå‡½æ•¸æ˜¯å¦æ‡‰è©²å…§è¯ã€‚å› æ­¤ï¼Œéš¨æ„æ”¾ç½®ä½¿ç”¨
-「inlineã€é—œéµå­—å¯èƒ½ä¸åƒ…僅是éŽåº¦çš„,也å¯èƒ½æ˜¯ç„¡ç”¨çš„。
+“inlineâ€é—œéµå­—å¯èƒ½ä¸åƒ…僅是éŽåº¦çš„,也å¯èƒ½æ˜¯ç„¡ç”¨çš„。
鎖
**
-2006å¹´5月,「deviceescapeã€ç¶²çµ¡å †æ£§åœ¨å‰å‘¼å¾Œæ“下以GPL發布,並被ç´å…¥ä¸»ç·šå…§æ ¸ã€‚
+2006å¹´5月,“deviceescapeâ€ç¶²çµ¡å †æ£§åœ¨å‰å‘¼å¾Œæ“下以GPL發佈,並被ç´å…¥ä¸»ç·šå…§æ ¸ã€‚
é€™æ˜¯ä¸€å€‹å—æ­¡è¿Žçš„æ¶ˆæ¯ï¼›Linux中å°ç„¡ç·šç¶²çµ¡çš„æ”¯æŒå……å…¶é‡è¢«èªçˆ²æ˜¯ä¸åˆæ ¼çš„,而
Deviceescape堆棧承諾修復這種情æ³ã€‚然而直到2007å¹´6月(2.6.22),這段代碼æ‰çœŸ
正進入主線。發生了什麼?
@@ -125,25 +125,25 @@ Deviceescape堆棧承諾修復這種情æ³ã€‚然而直到2007å¹´6月(2.6.22)
設計。在åˆä½µé€™å€‹ç¶²çµ¡å †æ£§ï¼ˆç¾åœ¨ç¨±çˆ²mac80211)之å‰ï¼Œéœ€è¦å°å…¶é€²è¡Œä¸€å€‹éŽ–æ–¹æ¡ˆçš„
改造。
-曾經,Linux內核代碼å¯ä»¥åœ¨ä¸è€ƒæ…®å¤šè™•ç†å™¨ç³»çµ±æ‰€å¸¶ä¾†çš„並發性å•題的情æ³ä¸‹é€²è¡Œ
+曾經,Linux內核代碼å¯ä»¥åœ¨ä¸è€ƒæ…®å¤šè™•ç†å™¨ç³»çµ±æ‰€å¸¶ä¾†çš„併發性å•題的情æ³ä¸‹é€²è¡Œ
開發。然而ç¾åœ¨ï¼Œé€™å€‹æ–‡æª”就是在雙核筆記本電腦上寫的。å³ä½¿åœ¨å–®è™•ç†å™¨ç³»çµ±ä¸Šï¼Œ
-爲æé«˜éŸ¿æ‡‰èƒ½åŠ›æ‰€åšçš„工作也會æé«˜å…§æ ¸å…§çš„並發性水平。編寫內核代碼而ä¸è€ƒæ…®éŽ–
+爲æé«˜éŸ¿æ‡‰èƒ½åŠ›æ‰€åšçš„工作也會æé«˜å…§æ ¸å…§çš„併發性水平。編寫內核代碼而ä¸è€ƒæ…®éŽ–
çš„æ—¥å­æ—©å·²é åŽ»ã€‚
-å¯ä»¥ç”±å¤šå€‹ç·šç¨‹ä¸¦ç™¼è¨ªå•的任何資æºï¼ˆæ•¸æ“šçµæ§‹ã€ç¡¬é«”寄存器等)必須由鎖ä¿è­·ã€‚æ–°
+å¯ä»¥ç”±å¤šå€‹ç·šç¨‹ä½µç™¼è¨ªå•的任何資æºï¼ˆæ•¸æ“šçµæ§‹ã€ç¡¬ä»¶å¯„存器等)必須由鎖ä¿è­·ã€‚æ–°
çš„ä»£ç¢¼æ‡‰è©²è¬¹è¨˜é€™ä¸€è¦æ±‚;事後修改鎖是一項相當困難的任務。內核開發人員應該花
-時間充分了解å¯ç”¨çš„éŽ–åŽŸèªžï¼Œä»¥ä¾¿çˆ²å·¥ä½œé¸æ“‡æ­£ç¢ºçš„工具。å°ä¸¦ç™¼æ€§ç¼ºä¹é—œæ³¨çš„代碼
+時間充分了解å¯ç”¨çš„éŽ–åŽŸèªžï¼Œä»¥ä¾¿çˆ²å·¥ä½œé¸æ“‡æ­£ç¢ºçš„工具。å°ä½µç™¼æ€§ç¼ºä¹é—œæ³¨çš„代碼
很難進入主線。
-回歸
+è¿´æ­¸
****
-最後一個值得一æçš„å±éšªæ˜¯å›žæ­¸ï¼šå®ƒå¯èƒ½æœƒå¼•èµ·å°Žè‡´ç¾æœ‰ç”¨æˆ¶çš„æŸäº›æ±è¥¿ä¸­æ–·çš„æ”¹è®Š
-(這也å¯èƒ½æœƒå¸¶ä¾†å¾ˆå¤§çš„æ”¹é€²ï¼‰ã€‚這種變化被稱爲「回歸ã€ï¼Œå›žæ­¸å·²ç¶“æˆçˆ²ä¸»ç·šå…§æ ¸
-最ä¸å—歡迎的å•題。除了少數例外情æ³ï¼Œå¦‚果回歸ä¸èƒ½åŠæ™‚修正,會導致回歸的修改
-å°‡è¢«å–æ¶ˆã€‚最好首先é¿å…回歸發生。
+最後一個值得一æçš„å±éšªæ˜¯è¿´æ­¸ï¼šå®ƒå¯èƒ½æœƒå¼•èµ·å°Žè‡´ç¾æœ‰ç”¨æˆ¶çš„æŸäº›æ±è¥¿ä¸­æ–·çš„æ”¹è®Š
+(這也å¯èƒ½æœƒå¸¶ä¾†å¾ˆå¤§çš„æ”¹é€²ï¼‰ã€‚這種變化被稱爲“迴歸â€ï¼Œè¿´æ­¸å·²ç¶“æˆçˆ²ä¸»ç·šå…§æ ¸
+最ä¸å—歡迎的å•題。除了少數例外情æ³ï¼Œå¦‚果迴歸ä¸èƒ½åŠæ™‚修正,會導致迴歸的修改
+å°‡è¢«å–æ¶ˆã€‚最好首先é¿å…迴歸發生。
-人們常常爭論,如果回歸帶來的功能é è¶…éŽç”¢ç”Ÿçš„å•題,那麼回歸是å¦çˆ²å¯æŽ¥å—的。
+人們常常爭論,如果迴歸帶來的功能é è¶…éŽç”¢ç”Ÿçš„å•題,那麼迴歸是å¦çˆ²å¯æŽ¥å—的。
如果它破壞了一個系統å»çˆ²åå€‹ç³»çµ±å¸¶ä¾†æ–°çš„åŠŸèƒ½ï¼Œçˆ²ä½•ä¸æ”¹æ”¹æ…‹åº¦å‘¢ï¼Ÿ2007å¹´7月,
Linuså°é€™å€‹å•題給出了最佳答案:
@@ -154,7 +154,7 @@ Linuså°é€™å€‹å•題給出了最佳答案:
(http://lwn.net/Articles/243460/)
-特別ä¸å—歡迎的一種回歸類型是用戶空間ABI的任何變化。一旦接å£è¢«å°Žå‡ºåˆ°ç”¨æˆ¶ç©ºé–“,
+特別ä¸å—歡迎的一種迴歸類型是用戶空間ABI的任何變化。一旦接å£è¢«å°Žå‡ºåˆ°ç”¨æˆ¶ç©ºé–“,
å°±å¿…é ˆç„¡é™æœŸåœ°æ”¯æŒå®ƒã€‚這一事實使得用戶空間接å£çš„創建特別具有挑戰性:因爲它們
ä¸èƒ½ä»¥ä¸å…¼å®¹çš„æ–¹å¼é€²è¡Œæ›´æ”¹ï¼Œæ‰€ä»¥å¿…須一次就å°ã€‚因此,用戶空間接å£ç¸½æ˜¯éœ€è¦å¤§é‡
çš„æ€è€ƒã€æ¸…晰的文檔和廣泛的審查。
@@ -171,19 +171,19 @@ Linuså°é€™å€‹å•題給出了最佳答案:
第一步是注æ„編譯器產生的警告。當å‰ç‰ˆæœ¬çš„GCCå¯ä»¥æª¢æ¸¬ï¼ˆä¸¦è­¦å‘Šï¼‰å¤§é‡æ½›åœ¨éŒ¯èª¤ã€‚
通常,這些警告都指å‘真正的å•題。æäº¤ä»¥ä¾›å¯©é–±çš„ä»£ç¢¼ä¸€èˆ¬ä¸æœƒç”¢ç”Ÿä»»ä½•編譯器警告。
-在消除警告時,注æ„了解真正的原因,並儘é‡é¿å…僅「修復ã€ä½¿è­¦å‘Šæ¶ˆå¤±è€Œä¸è§£æ±ºå…¶åŽŸå› ã€‚
+在消除警告時,注æ„瞭解真正的原因,並儘é‡é¿å…僅“修復â€ä½¿è­¦å‘Šæ¶ˆå¤±è€Œä¸è§£æ±ºå…¶åŽŸå› ã€‚
-請注æ„ï¼Œä¸¦éžæ‰€æœ‰ç·¨è­¯å™¨è­¦å‘Šéƒ½é»˜èªå•“用。使用「make KCFLAGS=-Wã€æ§‹å»ºå…§æ ¸ä»¥
+請注æ„ï¼Œä¸¦éžæ‰€æœ‰ç·¨è­¯å™¨è­¦å‘Šéƒ½é»˜èªå•“用。使用“make KCFLAGS=-Wâ€æ§‹å»ºå…§æ ¸ä»¥
ç²å¾—完整集åˆã€‚
-å…§æ ¸æä¾›äº†å¹¾å€‹é…ç½®é¸é …,å¯ä»¥æ‰“開調試功能;大多數é…ç½®é¸é …使–¼ã€Œkernel hackingã€
+å…§æ ¸æä¾›äº†å¹¾å€‹é…ç½®é¸é …,å¯ä»¥æ‰“開調試功能;大多數é…ç½®é¸é …使–¼â€œkernel hackingâ€
å­èœå–®ä¸­ã€‚å°æ–¼ä»»ä½•用於開發或測試目的的內核,都應該啓用其中幾個é¸é …。特別是,
您應該打開:
- FRAME_WARN ç²å–大於給定數é‡çš„堆棧幀的警告。
這些警告生æˆçš„輸出å¯èƒ½æ¯”較冗長,但您ä¸å¿…擔心來自內核其他部分的警告。
- - DEBUG_OBJECTS 將添加代碼以跟蹤內核創建的å„種å°è±¡çš„生命周期,並在出ç¾å•題
+ - DEBUG_OBJECTS 將添加代碼以跟蹤內核創建的å„種å°è±¡çš„生命週期,並在出ç¾å•題
æ™‚ç™¼å‡ºè­¦å‘Šã€‚å¦‚æžœä½ è¦æ·»åŠ å‰µå»ºï¼ˆå’Œå°Žå‡ºï¼‰é—œæ–¼å…¶è‡ªå·±çš„è¤‡é›œå°è±¡çš„å­ç³»çµ±ï¼Œè«‹
考慮打開å°è±¡èª¿è©¦åŸºç¤Žçµæ§‹çš„æ”¯æŒã€‚
@@ -195,34 +195,34 @@ Linuså°é€™å€‹å•題給出了最佳答案:
還有很多其他調試é¸é …,其中一些將在下é¢è¨Žè«–ã€‚å…¶ä¸­ä¸€äº›æœ‰é¡¯è‘—çš„æ€§èƒ½å½±éŸ¿ï¼Œä¸æ‡‰
一直使用。在學習å¯ç”¨é¸é …上花費一些時間,å¯èƒ½æœƒåœ¨çŸ­æœŸå…§å¾—到許多回報。
-其中一個較é‡çš„調試工具是鎖檢查器或「lockdepã€ã€‚該工具將跟蹤系統中æ¯å€‹éŽ–
+其中一個較é‡çš„調試工具是鎖檢查器或“lockdepâ€ã€‚該工具將跟蹤系統中æ¯å€‹éŽ–
(spinlock或mutex)的ç²å–和釋放ã€ç²å–鎖的相å°é †åºã€ç•¶å‰ä¸­æ–·ç’°å¢ƒç­‰ç­‰ã€‚然後,
它å¯ä»¥ç¢ºä¿ç¸½æ˜¯ä»¥ç›¸åŒçš„é †åºç²å–鎖,相åŒçš„中斷å‡è¨­é©ç”¨æ–¼æ‰€æœ‰æƒ…æ³ç­‰ç­‰ã€‚æ›å¥è©±
說,lockdepå¯ä»¥æ‰¾åˆ°è¨±å¤šå°Žè‡´ç³»çµ±æ­»éŽ–çš„å ´æ™¯ã€‚åœ¨éƒ¨ç½²çš„ç³»çµ±ä¸­ï¼Œé€™ç¨®å•題å¯èƒ½æœƒ
å¾ˆç—›è‹¦ï¼ˆå°æ–¼é–‹ç™¼äººå“¡å’Œç”¨æˆ¶è€Œè¨€ï¼‰ï¼›LockDepå…許æå‰ä»¥è‡ªå‹•æ–¹å¼ç™¼ç¾å•題。具有
-ä»»ä½•é¡žåž‹çš„éžæ™®é€šéŽ–çš„ä»£ç¢¼åœ¨æäº¤åˆä½µå‰æ‡‰åœ¨å•“用lockdep的情æ³ä¸‹é‹è¡Œæ¸¬è©¦ã€‚
+ä»»ä½•é¡žåž‹çš„éžæ™®é€šéŽ–çš„ä»£ç¢¼åœ¨æäº¤åˆä¸¦å‰æ‡‰åœ¨å•“用lockdep的情æ³ä¸‹é‹è¡Œæ¸¬è©¦ã€‚
-作爲一個勤奮的內核程å¼è¨­è¨ˆå¸«ï¼Œæ¯«ç„¡ç–‘å•,您將檢查任何å¯èƒ½å¤±æ•—çš„æ“作(如內存分é…)
+作爲一個勤奮的內核程åºå“¡ï¼Œæ¯«ç„¡ç–‘å•,您將檢查任何å¯èƒ½å¤±æ•—çš„æ“作(如內存分é…)
的返回狀態。然而,事實上,最終的故障復ç¾è·¯å¾‘å¯èƒ½å®Œå…¨æ²’æœ‰ç¶“éŽæ¸¬è©¦ã€‚未測試的
代碼往往會出å•題;如果所有這些錯誤處ç†è·¯å¾‘都被執行了幾次,那麼您å¯èƒ½å°ä»£ç¢¼
更有信心。
å…§æ ¸æä¾›äº†ä¸€å€‹å¯ä»¥åšåˆ°é€™ä¸€é»žçš„錯誤注入框架,特別是在涉åŠå…§å­˜åˆ†é…的情æ³ä¸‹ã€‚
啓用故障注入後,內存分é…çš„å¯é…置失敗的百分比;這些失敗å¯ä»¥é™å®šåœ¨ç‰¹å®šçš„代碼
-範åœå…§ã€‚在啓用了故障注入的情æ³ä¸‹é‹è¡Œï¼Œç¨‹å¼è¨­è¨ˆå¸«å¯ä»¥çœ‹åˆ°ç•¶æƒ…æ³æƒ¡åŒ–時代碼如何響
+範åœå…§ã€‚在啓用了故障注入的情æ³ä¸‹é‹è¡Œï¼Œç¨‹åºå“¡å¯ä»¥çœ‹åˆ°ç•¶æƒ…æ³æƒ¡åŒ–時代碼如何響
應。有關如何使用此工具的詳細信æ¯ï¼Œè«‹åƒé–±
Documentation/fault-injection/fault-injection.rst。
-「sparseã€éœæ…‹åˆ†æžå·¥å…·å¯ä»¥ç™¼ç¾å…¶ä»–類型的錯誤。sparseå¯ä»¥è­¦å‘Šç¨‹å¼è¨­è¨ˆå¸«ç”¨æˆ¶ç©ºé–“
+“sparseâ€éœæ…‹åˆ†æžå·¥å…·å¯ä»¥ç™¼ç¾å…¶ä»–類型的錯誤。sparseå¯ä»¥è­¦å‘Šç¨‹åºå“¡ç”¨æˆ¶ç©ºé–“
和內核空間地å€ä¹‹é–“的混淆ã€å¤§ç«¯åºèˆ‡å°ç«¯åºçš„æ··æ·†ã€åœ¨éœ€è¦ä¸€çµ„使¨™èªŒçš„地方傳éž
-整數值等等。sparse必須單ç¨å®‰è£(如果您的分發伺æœå™¨æ²’有將其打包,
+整數值等等。sparse必須單ç¨å®‰è£(如果您的分發æœå‹™å™¨æ²’有將其打包,
å¯ä»¥åœ¨ https://sparse.wiki.kernel.org/index.php/Main_page 找到),
-然後å¯ä»¥é€šéŽåœ¨make命令中添加「C=1ã€åœ¨ä»£ç¢¼ä¸Šé‹è¡Œå®ƒã€‚
+然後å¯ä»¥é€šéŽåœ¨make命令中添加“C=1â€åœ¨ä»£ç¢¼ä¸Šé‹è¡Œå®ƒã€‚
-「Coccinelleã€å·¥å…· :ref:`http://coccinelle.lip6.fr/ <devtools_coccinelle>`
-能夠發ç¾å„種潛在的編碼å•題;它還å¯ä»¥çˆ²é€™äº›å•題æå‡ºä¿®è¤‡æ–¹æ¡ˆã€‚在
-scripts/coccinelle目錄下已經打包了相當多的內核「語義補ä¸ã€ï¼›é‹è¡Œ
-「make coccicheckã€å°‡é‹è¡Œé€™äº›èªžç¾©è£œä¸ä¸¦å ±å‘Šç™¼ç¾çš„任何å•題。有關詳細信æ¯ï¼Œè«‹åƒé–±
+“Coccinelleâ€å·¥å…· :ref:`http://coccinelle.lip6.fr/ <devtools_coccinelle>`
+能夠發ç¾å„種潛在的編碼å•題;它還å¯ä»¥çˆ²é€™äº›å•題æå‡ºä¿®å¾©æ–¹æ¡ˆã€‚在
+scripts/coccinelle目錄下已經打包了相當多的內核“語義補ä¸â€ï¼›é‹è¡Œ
+“make coccicheckâ€å°‡é‹è¡Œé€™äº›èªžç¾©è£œä¸ä¸¦å ±å‘Šç™¼ç¾çš„任何å•題。有關詳細信æ¯ï¼Œè«‹åƒé–±
:ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>`
@@ -247,7 +247,7 @@ scripts/coccinelle目錄下已經打包了相當多的內核「語義補ä¸ã€ï¼
任何添加新用戶空間接å£çš„代碼——包括新的sysfs或/proc文件——都應該包å«è©²æŽ¥å£
的文檔,該文檔使用戶空間開發人員能夠知é“他們在使用什麼。請åƒé–±
-Documentation/ABI/README,了解如何此文檔格å¼ä»¥åŠéœ€è¦æä¾›å“ªäº›ä¿¡æ¯ã€‚
+Documentation/ABI/README,瞭解如何此文檔格å¼ä»¥åŠéœ€è¦æä¾›å“ªäº›ä¿¡æ¯ã€‚
文檔 :ref:`Documentation/admin-guide/kernel-parameters.rst <kernelparameters>`
æè¿°äº†å…§æ ¸çš„æ‰€æœ‰å¼•å°Žæ™‚é–“åƒæ•¸ã€‚ä»»ä½•æ·»åŠ æ–°åƒæ•¸çš„補ä¸éƒ½æ‡‰è©²å‘該文檔添加é©ç•¶çš„
@@ -256,27 +256,27 @@ Documentation/ABI/README,了解如何此文檔格å¼ä»¥åŠéœ€è¦æä¾›å“ªäº›ä¿
任何新的é…ç½®é¸é …都必須附有幫助文本,幫助文本需清楚地解釋這些é¸é …以åŠç”¨æˆ¶å¯èƒ½
希望何時使用它們。
-許多å­ç³»çµ±çš„內部APIä¿¡æ¯é€šéŽå°ˆé–€æ ¼å¼åŒ–的注釋進行記錄;這些注釋å¯ä»¥é€šéŽ
-「kernel-docã€è…³æœ¬ä»¥å¤šç¨®æ–¹å¼æå–和格å¼åŒ–。如果您在具有kerneldoc注釋的å­ç³»çµ±ä¸­
+許多å­ç³»çµ±çš„內部APIä¿¡æ¯é€šéŽå°ˆé–€æ ¼å¼åŒ–的註釋進行記錄;這些註釋å¯ä»¥é€šéŽ
+“kernel-docâ€è…³æœ¬ä»¥å¤šç¨®æ–¹å¼æå–和格å¼åŒ–。如果您在具有kerneldoc註釋的å­ç³»çµ±ä¸­
工作,則應該維護它們,並根據需è¦çˆ²å¤–部å¯ç”¨çš„功能添加它們。å³ä½¿åœ¨æ²’有如此記錄
-的領域中,爲將來添加kerneldocæ³¨é‡‹ä¹Ÿæ²’æœ‰å£žè™•ï¼›å¯¦éš›ä¸Šï¼Œé€™å°æ–¼å‰›é–‹å§‹é–‹ç™¼å…§æ ¸çš„人
-來說是一個有用的活動。這些注釋的格å¼ä»¥åŠå¦‚何創建kerneldoc模æ¿çš„一些信æ¯å¯ä»¥åœ¨
+的領域中,爲將來添加kerneldocè¨»é‡‹ä¹Ÿæ²’æœ‰å£žè™•ï¼›å¯¦éš›ä¸Šï¼Œé€™å°æ–¼å‰›é–‹å§‹é–‹ç™¼å…§æ ¸çš„人
+來說是一個有用的活動。這些註釋的格å¼ä»¥åŠå¦‚何創建kerneldoc模æ¿çš„一些信æ¯å¯ä»¥åœ¨
:ref:`Documentation/doc-guide/ <doc_guide>` 上找到。
-任何閱讀大é‡ç¾æœ‰å…§æ ¸ä»£ç¢¼çš„人都會注æ„到,注釋的缺失往往是最值得注æ„çš„ã€‚åŒæ™‚,
-å°æ–°ä»£ç¢¼çš„è¦æ±‚比éŽåŽ»æ›´é«˜ï¼›åˆä½µæœªæ³¨é‡‹çš„ä»£ç¢¼å°‡æ›´åŠ å›°é›£ã€‚é€™å°±æ˜¯èªªï¼Œäººå€‘ä¸¦ä¸æœŸæœ›
-詳細注釋的代碼。代碼本身應該是自解釋的,注釋闡釋了更微妙的方é¢ã€‚
+任何閱讀大é‡ç¾æœ‰å…§æ ¸ä»£ç¢¼çš„人都會注æ„到,註釋的缺失往往是最值得注æ„çš„ã€‚åŒæ™‚,
+å°æ–°ä»£ç¢¼çš„è¦æ±‚比éŽåŽ»æ›´é«˜ï¼›åˆä½µæœªè¨»é‡‹çš„ä»£ç¢¼å°‡æ›´åŠ å›°é›£ã€‚é€™å°±æ˜¯èªªï¼Œäººå€‘ä¸¦ä¸æœŸæœ›
+詳細註釋的代碼。代碼本身應該是自解釋的,註釋闡釋了更微妙的方é¢ã€‚
-æŸäº›äº‹æƒ…應該總是被注釋。使用內存å±éšœæ™‚,應附上一行文字,解釋爲什麼需è¦è¨­ç½®å…§å­˜
+æŸäº›äº‹æƒ…應該總是被註釋。使用內存å±éšœæ™‚,應附上一行文字,解釋爲什麼需è¦è¨­ç½®å…§å­˜
å±éšœã€‚æ•¸æ“šçµæ§‹çš„鎖è¦å‰‡é€šå¸¸éœ€è¦åœ¨æŸå€‹åœ°æ–¹è§£é‡‹ã€‚ä¸€èˆ¬ä¾†èªªï¼Œä¸»è¦æ•¸æ“šçµæ§‹éœ€è¦å…¨é¢
的文檔。應該指出代碼中分立的ä½ä¹‹é–“䏿˜Žé¡¯çš„ä¾è³´æ€§ã€‚任何å¯èƒ½èª˜ä½¿ä»£ç¢¼ç®¡ç†äººé€²è¡Œ
-錯誤的「清ç†ã€çš„事情都需è¦ä¸€å€‹æ³¨é‡‹ä¾†èªªæ˜Žçˆ²ä»€éº¼è¦é€™æ¨£åšã€‚等等。
+錯誤的“清ç†â€çš„事情都需è¦ä¸€å€‹è¨»é‡‹ä¾†èªªæ˜Žçˆ²ä»€éº¼è¦é€™æ¨£åšã€‚等等。
內部API更改
-----------
-å…§æ ¸æä¾›çµ¦ç”¨æˆ¶ç©ºé–“çš„äºŒé€²ä½æŽ¥å£ä¸èƒ½è¢«ç ´å£žï¼Œé™¤éžé€¼ä¸å¾—已。而內核的內部編程接å£
+å…§æ ¸æä¾›çµ¦ç”¨æˆ¶ç©ºé–“的二進制接å£ä¸èƒ½è¢«ç ´å£žï¼Œé™¤éžé€¼ä¸å¾—已。而內核的內部編程接å£
是高度æµå‹•çš„ï¼Œç•¶éœ€è¦æ™‚å¯ä»¥æ›´æ”¹ã€‚如果你發ç¾è‡ªå·±ä¸å¾—ä¸è™•ç†ä¸€å€‹å…§æ ¸API,或者僅
åƒ…å› çˆ²å®ƒä¸æ»¿è¶³ä½ çš„需求導致無法使用特定的功能,這å¯èƒ½æ˜¯APIéœ€è¦æ”¹è®Šçš„一個標誌。
作爲內核開發人員,您有權進行此類更改。
@@ -287,7 +287,7 @@ Documentation/ABI/README,了解如何此文檔格å¼ä»¥åŠéœ€è¦æä¾›å“ªäº›ä¿
å¦ä¸€å€‹è¦é»žæ˜¯ï¼Œæ›´æ”¹å…§éƒ¨API的開發人員通常è¦è² è²¬ä¿®å¾©å…§æ ¸æ¨¹ä¸­è¢«æ›´æ”¹ç ´å£žçš„任何代碼。
å°æ–¼ä¸€å€‹å»£æ³›ä½¿ç”¨çš„函數,這個責任å¯ä»¥å°Žè‡´æˆç™¾ä¸Šåƒçš„變化,其中許多變化å¯èƒ½èˆ‡å…¶ä»–
-開發人員正在åšçš„工作相è¡çªã€‚ä¸ç”¨èªªï¼Œé€™å¯èƒ½æ˜¯ä¸€é …大工程,所以最好確ä¿ç†ç”±æ˜¯
+開發人員正在åšçš„工作相沖çªã€‚ä¸ç”¨èªªï¼Œé€™å¯èƒ½æ˜¯ä¸€é …大工程,所以最好確ä¿ç†ç”±æ˜¯
å¯é çš„。請注æ„,coccinelle工具å¯ä»¥å¹«åŠ©é€²è¡Œå»£æ³›çš„API更改。
在進行ä¸å…¼å®¹çš„API更改時,應儘å¯èƒ½ç¢ºä¿ç·¨è­¯å™¨æ•ç²æœªæ›´æ–°çš„ä»£ç¢¼ã€‚é€™å°‡å¹«åŠ©æ‚¨ç¢ºä¿æ‰¾
diff --git a/Documentation/translations/zh_TW/process/5.Posting.rst b/Documentation/translations/zh_TW/process/5.Posting.rst
index 27015622ad63..d398dda427aa 100644
--- a/Documentation/translations/zh_TW/process/5.Posting.rst
+++ b/Documentation/translations/zh_TW/process/5.Posting.rst
@@ -15,27 +15,27 @@
.. _tw_development_posting:
-發布補ä¸
+發佈補ä¸
========
æ‚¨çš„å·¥ä½œé²æ—©æœƒæº–備好æäº¤çµ¦ç¤¾å€é€²è¡Œå¯©æŸ¥ï¼Œä¸¦æœ€çµ‚包å«åˆ°ä¸»ç·šå…§æ ¸ä¸­ã€‚毫ä¸ç¨€å¥‡ï¼Œ
-內核開發社å€å·²ç¶“發展出一套用於發布補ä¸çš„約定和éŽç¨‹ï¼›éµå¾ªé€™äº›ç´„定和éŽç¨‹å°‡ä½¿
+內核開發社å€å·²ç¶“發展出一套用於發佈補ä¸çš„約定和éŽç¨‹ï¼›éµå¾ªé€™äº›ç´„定和éŽç¨‹å°‡ä½¿
åƒèˆ‡å…¶ä¸­çš„æ¯å€‹äººçš„ç”Ÿæ´»æ›´åŠ è¼•é¬†ã€‚æœ¬æ–‡æª”è©¦åœ–æè¿°é€™äº›ç´„定的部分細節;更多信æ¯
也å¯åœ¨ä»¥ä¸‹æ–‡æª”中找到
-:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
-和 :ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`。
+:ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <tw_submittingpatches>`
+和 :ref:`Documentation/translations/zh_CN/process/submit-checklist.rst <tw_submitchecklist>`。
-何時郵寄
+何時寄é€
--------
-在補ä¸å®Œå…¨ã€Œæº–備好ã€ä¹‹å‰ï¼Œé¿å…ç™¼å¸ƒè£œä¸æ˜¯ä¸€ç¨®æŒçºŒçš„èª˜æƒ‘ã€‚å°æ–¼ç°¡å–®çš„補ä¸ï¼Œé€™
+在補ä¸å®Œå…¨â€œæº–備好â€ä¹‹å‰ï¼Œé¿å…ç™¼ä½ˆè£œä¸æ˜¯ä¸€ç¨®æŒçºŒçš„èª˜æƒ‘ã€‚å°æ–¼ç°¡å–®çš„補ä¸ï¼Œé€™
䏿˜¯å•題。但是如果正在完æˆçš„工作很複雜,那麼在工作完æˆä¹‹å‰å¾žç¤¾å€ç²å¾—å饋就
-å¯ä»¥ç²å¾—很多好處。因此,您應該考慮發布正在進行的工作,甚至維護一個å¯ç”¨çš„Git
+å¯ä»¥ç²å¾—很多好處。因此,您應該考慮發佈正在進行的工作,甚至維護一個å¯ç”¨çš„Git
樹,以便感興趣的開發人員å¯ä»¥éš¨æ™‚趕上您的工作。
-當發布中有尚未準備好被包å«çš„代碼,最好在發布中說明。還應æåŠä»»ä½•有待完æˆçš„
+當發佈中有尚未準備好被包å«çš„代碼,最好在發佈中說明。還應æåŠä»»ä½•有待完æˆçš„
主è¦å·¥ä½œå’Œä»»ä½•已知å•題。很少有人會願æ„看那些被èªçˆ²æ˜¯åŠç”Ÿä¸ç†Ÿçš„補ä¸ï¼Œä½†æ˜¯
-那些願æ„的人會帶著他們的點å­ä¾†ä¸€èµ·å¹«åŠ©ä½ æŠŠå·¥ä½œæŽ¨å‘æ­£ç¢ºçš„æ–¹å‘。
+那些願æ„的人會帶ç€ä»–們的點å­ä¾†ä¸€èµ·å¹«åŠ©ä½ æŠŠå·¥ä½œæŽ¨å‘æ­£ç¢ºçš„æ–¹å‘。
創建補ä¸ä¹‹å‰
------------
@@ -50,20 +50,20 @@
- 您的更改是å¦å…·æœ‰æ€§èƒ½å½±éŸ¿ï¼Ÿå¦‚果是這樣,您應該é‹è¡ŒåŸºæº–測試來顯示您的變更的
å½±éŸ¿ï¼ˆæˆ–å¥½è™•ï¼‰ï¼›çµæžœçš„æ‘˜è¦æ‡‰è©²åŒ…å«åœ¨è£œä¸ä¸­ã€‚
- - ç¢ºä¿æ‚¨æœ‰æ¬Šç™¼å¸ƒä»£ç¢¼ã€‚如果這項工作是爲僱主完æˆçš„,僱主å°é€™é …工作具有所有權,
- ä¸¦ä¸”å¿…é ˆåŒæ„根據GPLå°å…¶é€²è¡Œç™¼å¸ƒã€‚
+ - ç¢ºä¿æ‚¨æœ‰æ¬Šç™¼ä½ˆä»£ç¢¼ã€‚如果這項工作是爲僱主完æˆçš„,僱主å°é€™é …工作具有所有權,
+ ä¸¦ä¸”å¿…é ˆåŒæ„根據GPLå°å…¶é€²è¡Œç™¼ä½ˆã€‚
-一般來說,在發布代碼之å‰é€²è¡Œä¸€äº›é¡å¤–çš„æ€è€ƒï¼Œå¹¾ä¹Žç¸½æ˜¯èƒ½åœ¨çŸ­æ™‚間內得到回報。
+一般來說,在發佈代碼之å‰é€²è¡Œä¸€äº›é¡å¤–çš„æ€è€ƒï¼Œå¹¾ä¹Žç¸½æ˜¯èƒ½åœ¨çŸ­æ™‚間內得到回報。
è£œä¸æº–å‚™
--------
-準備補ä¸ç™¼å¸ƒçš„工作é‡å¯èƒ½å¾ˆé©šäººï¼Œä½†åœ¨æ­¤å˜—è©¦ç¯€çœæ™‚é–“é€šå¸¸æ˜¯ä¸æ˜Žæ™ºçš„,å³ä½¿åœ¨çŸ­æœŸ
+準備補ä¸ç™¼ä½ˆçš„工作é‡å¯èƒ½å¾ˆé©šäººï¼Œä½†åœ¨æ­¤å˜—è©¦ç¯€çœæ™‚é–“é€šå¸¸æ˜¯ä¸æ˜Žæ™ºçš„,å³ä½¿åœ¨çŸ­æœŸ
內亦然。
å¿…é ˆé‡å°å…§æ ¸çš„特定版本準備補ä¸ã€‚ä¸€èˆ¬ä¾†èªªï¼Œè£œä¸æ‡‰è©²åŸºæ–¼Linusçš„Git樹中的當å‰
-主線。當以主線爲基礎時,請從一個衆所周知的發布點開始——如穩定版本或 -rc
-ç‰ˆæœ¬ç™¼å¸ƒé»žâ€”â€”è€Œä¸æ˜¯åœ¨ä¸€å€‹ä»»æ„的主線分支點。
+主線。當以主線爲基礎時,請從一個衆所周知的發佈點開始——如穩定版本或 -rc
+ç‰ˆæœ¬ç™¼ä½ˆé»žâ€”â€”è€Œä¸æ˜¯åœ¨ä¸€å€‹ä»»æ„的主線分支點。
也å¯èƒ½éœ€è¦é‡å°-mmã€linux-next或å­ç³»çµ±æ¨¹ç”Ÿæˆç‰ˆæœ¬ï¼Œä»¥ä¾¿æ–¼æ›´å»£æ³›çš„æ¸¬è©¦å’Œå¯©æŸ¥ã€‚
根據補ä¸çš„å€åŸŸä»¥åŠå…¶ä»–地方的情æ³ï¼Œé‡å°å…¶ä»–樹建立的補ä¸å¯èƒ½éœ€è¦å¤§é‡çš„工作來
@@ -73,12 +73,12 @@
åˆ†å‰²è£œä¸æ˜¯ä¸€é–€è—è¡“ï¼›ä¸€äº›é–‹ç™¼äººå“¡èŠ±äº†å¾ˆé•·æ™‚é–“ä¾†å¼„æ¸…æ¥šå¦‚ä½•æŒ‰ç…§ç¤¾å€æœŸæœ›çš„æ–¹å¼ä¾†
分割。ä¸éŽï¼Œé€™äº›ç¶“驗法則也許有幫助:
- - 您發布的補ä¸ç³»åˆ—å¹¾ä¹Žè‚¯å®šä¸æœƒæ˜¯é–‹ç™¼éŽç¨‹ä¸­ç‰ˆæœ¬æŽ§åˆ¶ç³»çµ±ä¸­çš„一系列更改。相å,
+ - 您發佈的補ä¸ç³»åˆ—å¹¾ä¹Žè‚¯å®šä¸æœƒæ˜¯é–‹ç™¼éŽç¨‹ä¸­ç‰ˆæœ¬æŽ§åˆ¶ç³»çµ±ä¸­çš„一系列更改。相å,
需è¦å°æ‚¨æ‰€åšæ›´æ”¹çš„æœ€çµ‚å½¢å¼åŠ ä»¥è€ƒæ…®ï¼Œç„¶å¾Œä»¥æœ‰æ„義的方å¼é€²è¡Œæ‹†åˆ†ã€‚開發人員å°
離散的ã€è‡ªåŒ…å«çš„æ›´æ”¹æ„Ÿèˆˆè¶£ï¼Œè€Œä¸æ˜¯æ‚¨å‰µé€ é€™äº›æ›´æ”¹çš„原始路徑。
- - æ¯å€‹é‚輯上ç¨ç«‹çš„變更都應該格å¼åŒ–爲單ç¨çš„補ä¸ã€‚這些更改å¯ä»¥æ˜¯å°çš„(如「å‘
- æ­¤çµæ§‹é«”添加欄ä½ã€ï¼‰æˆ–大的(如添加一個é‡è¦çš„æ–°é©…動程åºï¼‰ï¼Œä½†å®ƒå€‘在概念上
+ - æ¯å€‹é‚輯上ç¨ç«‹çš„變更都應該格å¼åŒ–爲單ç¨çš„補ä¸ã€‚這些更改å¯ä»¥æ˜¯å°çš„(如“å‘
+ æ­¤çµæ§‹é«”添加字段â€ï¼‰æˆ–大的(如添加一個é‡è¦çš„æ–°é©…動程åºï¼‰ï¼Œä½†å®ƒå€‘在概念上
應該是å°çš„,並且å¯ä»¥åœ¨ä¸€è¡Œå…§ç°¡è¿°ã€‚æ¯å€‹è£œä¸éƒ½æ‡‰è©²åšä¸€å€‹ç‰¹å®šçš„ã€å¯ä»¥å–®ç¨
檢查並驗證它所åšçš„事情的更改。
@@ -88,34 +88,34 @@
- æ¯å€‹è£œä¸éƒ½æ‡‰è©²èƒ½å‰µå»ºä¸€å€‹å¯ä»¥æ­£ç¢ºåœ°æ§‹å»ºå’Œé‹è¡Œçš„內核;如果補ä¸ç³»åˆ—在中間被
æ–·é–‹ï¼Œé‚£éº¼çµæžœä»æ‡‰æ˜¯ä¸€å€‹æ­£å¸¸å·¥ä½œçš„å…§æ ¸ã€‚éƒ¨åˆ†æ‡‰ç”¨ä¸€ç³»åˆ—è£œä¸æ˜¯ä½¿ç”¨
- 「git bisctã€å·¥å…·æŸ¥æ‰¾å›žæ­¸çš„ä¸€å€‹å¸¸è¦‹å ´æ™¯ï¼›å¦‚æžœçµæžœæ˜¯ä¸€å€‹æå£žçš„內核,那麼將使
+ “git bisctâ€å·¥å…·æŸ¥æ‰¾å›žæ­¸çš„ä¸€å€‹å¸¸è¦‹å ´æ™¯ï¼›å¦‚æžœçµæžœæ˜¯ä¸€å€‹æå£žçš„內核,那麼將使
那些從事追蹤å•題的高尚工作的開發人員和用戶的生活更加艱難。
- ä¸è¦éŽåˆ†åˆ†å‰²ã€‚一ä½é–‹ç™¼äººå“¡æ›¾ç¶“將一組é‡å°å–®å€‹æ–‡ä»¶çš„編輯分æˆ500個單ç¨çš„補ä¸
- 發布,這並沒有使他æˆçˆ²å…§æ ¸éƒµä»¶åˆ—è¡¨ä¸­æœ€å—æ­¡è¿Žçš„人。一個補ä¸å¯ä»¥ç›¸ç•¶å¤§ï¼Œ
+ 發佈,這並沒有使他æˆçˆ²å…§æ ¸éƒµä»¶åˆ—è¡¨ä¸­æœ€å—æ­¡è¿Žçš„人。一個補ä¸å¯ä»¥ç›¸ç•¶å¤§ï¼Œ
åªè¦å®ƒä»ç„¶åŒ…å«ä¸€å€‹å–®ä¸€çš„ *é‚輯* 變更。
- ç”¨ä¸€ç³»åˆ—è£œä¸æ·»åŠ ä¸€å€‹å…¨æ–°çš„åŸºç¤Žè¨­æ–½ï¼Œä½†æ˜¯è©²è¨­æ–½åœ¨ç³»åˆ—ä¸­çš„æœ€å¾Œä¸€å€‹è£œä¸å•“用
整個變更之å‰ä¸èƒ½ä½¿ç”¨ï¼Œé€™çœ‹èµ·ä¾†å¾ˆèª˜äººã€‚如果å¯èƒ½çš„話,應該é¿å…這種誘惑;
- å¦‚æžœé€™å€‹ç³»åˆ—å¢žåŠ äº†å›žæ­¸ï¼Œé‚£éº¼äºŒåˆ†æ³•å°‡æŒ‡å‡ºæœ€å¾Œä¸€å€‹è£œä¸æ˜¯å°Žè‡´å•題的補ä¸ï¼Œ
+ å¦‚æžœé€™å€‹ç³»åˆ—å¢žåŠ äº†è¿´æ­¸ï¼Œé‚£éº¼äºŒåˆ†æ³•å°‡æŒ‡å‡ºæœ€å¾Œä¸€å€‹è£œä¸æ˜¯å°Žè‡´å•題的補ä¸ï¼Œ
å³ä½¿çœŸæ­£çš„bug在其他地方。åªè¦æœ‰å¯èƒ½ï¼Œæ·»åŠ æ–°ä»£ç¢¼çš„è£œä¸ç¨‹åºæ‡‰è©²ç«‹å³æ¿€æ´»è©²
代碼。
-創建完美補ä¸ç³»åˆ—的工作å¯èƒ½æ˜¯ä¸€å€‹ä»¤äººæ²®å–ªçš„éŽç¨‹ï¼Œåœ¨å®Œæˆã€ŒçœŸæ­£çš„工作ã€ä¹‹å¾Œéœ€è¦
+創建完美補ä¸ç³»åˆ—的工作å¯èƒ½æ˜¯ä¸€å€‹ä»¤äººæ²®å–ªçš„éŽç¨‹ï¼Œåœ¨å®Œæˆâ€œçœŸæ­£çš„工作â€ä¹‹å¾Œéœ€è¦
花費大é‡çš„æ™‚é–“å’Œæ€è€ƒã€‚但是如果åšå¾—好,花費的時間就是值得的。
è£œä¸æ ¼å¼å’Œæ›´æ”¹æ—¥èªŒ
------------------
-所以ç¾åœ¨ä½ æœ‰äº†ä¸€ç³»åˆ—完美的補ä¸å¯ä»¥ç™¼å¸ƒï¼Œä½†æ˜¯é€™é …工作還沒有完æˆã€‚æ¯å€‹è£œä¸éƒ½
+所以ç¾åœ¨ä½ æœ‰äº†ä¸€ç³»åˆ—完美的補ä¸å¯ä»¥ç™¼ä½ˆï¼Œä½†æ˜¯é€™é …工作還沒有完æˆã€‚æ¯å€‹è£œä¸éƒ½
需è¦è¢«æ ¼å¼åŒ–æˆä¸€æ¢æ¶ˆæ¯ï¼Œä»¥å¿«é€Ÿè€Œæ¸…晰地將其目的傳é”到世界其他地方。爲此,
æ¯å€‹è£œä¸å°‡ç”±ä»¥ä¸‹éƒ¨åˆ†çµ„æˆï¼š
- - å¯é¸çš„「Fromã€è¡Œï¼Œè¡¨æ˜Žè£œä¸ä½œè€…ã€‚åªæœ‰ç•¶ä½ é€šéŽé›»å­éƒµä»¶ç™¼é€åˆ¥äººçš„è£œä¸æ™‚,這一行
- æ‰æ˜¯å¿…須的,但是爲防止疑å•åŠ ä¸Šå®ƒä¹Ÿä¸æœƒæœ‰ä»€éº¼å£žè™•。
+ - å¯é¸çš„“Fromâ€è¡Œï¼Œè¡¨æ˜Žè£œä¸ä½œè€…ã€‚åªæœ‰ç•¶ä½ é€šéŽé›»å­éƒµä»¶ç™¼é€åˆ¥äººçš„è£œä¸æ™‚,這一行
+ 纔是必須的,但是爲防止疑å•åŠ ä¸Šå®ƒä¹Ÿä¸æœƒæœ‰ä»€éº¼å£žè™•。
- 一行æè¿°ï¼Œèªªæ˜Žè£œä¸çš„ä½œç”¨ã€‚å°æ–¼åœ¨æ²’有其他上下文的情æ³ä¸‹çœ‹åˆ°è©²æ¶ˆæ¯çš„讀者來說,
- è©²æ¶ˆæ¯æ‡‰è¶³ä»¥ç¢ºå®šä¿®è£œç¨‹åºçš„範åœï¼›æ­¤è¡Œå°‡é¡¯ç¤ºåœ¨ã€Œshort form(簡短格å¼ï¼‰ã€è®Šæ›´
+ è©²æ¶ˆæ¯æ‡‰è¶³ä»¥ç¢ºå®šä¿®è£œç¨‹åºçš„範åœï¼›æ­¤è¡Œå°‡é¡¯ç¤ºåœ¨â€œshort form(簡短格å¼ï¼‰â€è®Šæ›´
日誌中。此消æ¯é€šå¸¸éœ€è¦å…ˆåŠ ä¸Šå­ç³»çµ±å稱å‰ç¶´ï¼Œç„¶å¾Œæ˜¯è£œä¸çš„目的。例如:
::
@@ -144,17 +144,17 @@
一般來說,你越把自己放在æ¯å€‹é–±è®€ä½ è®Šæ›´æ—¥èªŒçš„人的ä½ç½®ä¸Šï¼Œè®Šæ›´æ—¥èªŒï¼ˆå’Œå…§æ ¸
作爲一個整體)就越好。
-䏿¶ˆèªªï¼Œè®Šæ›´æ—¥èªŒæ˜¯å°‡è®Šæ›´æäº¤åˆ°ç‰ˆæœ¬æŽ§åˆ¶ç³»çµ±æ™‚使用的文本。接下來將是:
+ä¸éœ€è¦èªªï¼Œè®Šæ›´æ—¥èªŒæ˜¯å°‡è®Šæ›´æäº¤åˆ°ç‰ˆæœ¬æŽ§åˆ¶ç³»çµ±æ™‚使用的文本。接下來將是:
- - è£œä¸æœ¬èº«ï¼ŒæŽ¡ç”¨çµ±ä¸€çš„(「-uã€ï¼‰è£œä¸æ ¼å¼ã€‚使用「-pã€é¸é …來diff將使函數å與
+ - è£œä¸æœ¬èº«ï¼ŒæŽ¡ç”¨çµ±ä¸€çš„(“-uâ€ï¼‰è£œä¸æ ¼å¼ã€‚使用“-pâ€é¸é …來diff將使函數å與
更改相關è¯ï¼Œå¾žè€Œä½¿çµæžœè£œä¸æ›´å®¹æ˜“被其他人讀å–。
您應該é¿å…在補ä¸ä¸­åŒ…括與更改ä¸ç›¸é—œæ–‡ä»¶ï¼ˆä¾‹å¦‚,構建éŽç¨‹ç”Ÿæˆçš„æ–‡ä»¶æˆ–編輯器
-備份文件)。文檔目錄中的「dontdiffã€æ–‡ä»¶åœ¨é€™æ–¹é¢æœ‰å¹«åŠ©ï¼›ä½¿ç”¨ã€Œ-Xã€é¸é …å°‡
+備份文件)。文檔目錄中的“dontdiffâ€æ–‡ä»¶åœ¨é€™æ–¹é¢æœ‰å¹«åŠ©ï¼›ä½¿ç”¨â€œ-Xâ€é¸é …å°‡
其傳éžçµ¦diff。
ä¸Šé¢æåˆ°çš„æ¨™ç±¤ï¼ˆtag)用於æè¿°å„種開發人員如何與這個補ä¸çš„開發相關è¯ã€‚
-:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+:ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <tw_submittingpatches>`
文檔中å°å®ƒå€‘進行了詳細æè¿°ï¼›ä¸‹é¢æ˜¯ä¸€å€‹ç°¡çŸ­çš„總çµã€‚æ¯ä¸€è¡Œçš„æ ¼å¼å¦‚下:
::
@@ -165,14 +165,14 @@
- Signed-off-by: 這是一個開發人員的證明,證明他或她有權æäº¤è£œä¸ä»¥åŒ…å«åˆ°å…§æ ¸
ä¸­ã€‚é€™è¡¨æ˜ŽåŒæ„開發者來æºèªè­‰å”議,其全文見
- :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+ :ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <tw_submittingpatches>`
如果沒有åˆé©çš„簽字,則ä¸èƒ½åˆä½µåˆ°ä¸»ç·šä¸­ã€‚
- Co-developed-by: è²æ˜Žè£œä¸æ˜¯ç”±å¤šå€‹é–‹ç™¼äººå“¡å…±åŒå‰µå»ºçš„;當幾個人在一個補ä¸ä¸Š
工作時,它用於給出共åŒä½œè€…(除了 From: 所給出的作者之外)。由於
Co-developed-by: 表示作者身份,所以æ¯å€‹å…±åŒé–‹ç™¼äººï¼Œå¿…須緊跟在相關åˆä½œä½œè€…
的Signed-off-by之後。具體內容和示例見以下文件
- :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+ :ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <tw_submittingpatches>`
- Acked-by: 表示å¦ä¸€å€‹é–‹ç™¼äººå“¡ï¼ˆé€šå¸¸æ˜¯ç›¸é—œä»£ç¢¼çš„ç¶­è­·äººå“¡ï¼‰åŒæ„補ä¸é©åˆåŒ…å«
在內核中。
@@ -180,7 +180,7 @@
- Tested-by: è²æ˜ŽæŸäººå·²ç¶“測試了補ä¸ä¸¦ç¢ºèªå®ƒå¯ä»¥å·¥ä½œã€‚
- Reviewed-by: 表示æŸé–‹ç™¼äººå“¡å·²ç¶“審查了補ä¸çš„æ­£ç¢ºæ€§ï¼›æœ‰é—œè©³ç´°ä¿¡æ¯ï¼Œè«‹åƒé–±
- :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+ :ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <tw_submittingpatches>`
- Reported-by: 指定報告此補ä¸ä¿®å¾©çš„å•題的用戶;此標記用於表示感è¬ã€‚
@@ -188,16 +188,16 @@
在補ä¸ä¸­æ·»åŠ æ¨™ç±¤æ™‚è¦å°å¿ƒï¼šåªæœ‰Cc:æ‰é©åˆåœ¨æ²’有指定人員明確許å¯çš„æƒ…æ³ä¸‹æ·»åŠ ã€‚
-發é€è£œä¸
+寄é€è£œä¸
--------
-在寄出補ä¸ä¹‹å‰ï¼Œæ‚¨é‚„éœ€è¦æ³¨æ„以下幾點:
+在寄é€è£œä¸ä¹‹å‰ï¼Œæ‚¨é‚„éœ€è¦æ³¨æ„以下幾點:
- 您確定您的郵件發é€ç¨‹åºä¸æœƒæå£žè£œä¸å—Žï¼Ÿè¢«éƒµä»¶å®¢æˆ¶ç«¯æ›´æ”¹ç©ºç™½æˆ–修飾了行的補ä¸
無法被å¦ä¸€ç«¯æŽ¥å—ï¼Œä¸¦ä¸”é€šå¸¸ä¸æœƒé€²è¡Œä»»ä½•詳細檢查。如果有任何疑å•,先把補ä¸å¯„
給你自己,讓你自己確定它是完好無æçš„。
- :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+ :ref:`Documentation/translations/zh_CN/process/email-clients.rst <tw_email_clients>`
æä¾›äº†ä¸€äº›æœ‰ç”¨çš„æç¤ºï¼Œå¯ä»¥è®“特定的郵件客戶端正常發é€è£œä¸ã€‚
- ä½ ç¢ºå®šä½ çš„è£œä¸æ²’有è’å”的錯誤嗎?您應該始終通éŽscripts/checkpatch.pl檢查
@@ -209,12 +209,12 @@
引用補ä¸çš„部分。相å,åªéœ€å°‡è£œä¸ç›´æŽ¥æ”¾åˆ°æ‚¨çš„æ¶ˆæ¯ä¸­ã€‚
å¯„å‡ºè£œä¸æ™‚,é‡è¦çš„æ˜¯å°‡å‰¯æœ¬ç™¼é€çµ¦ä»»ä½•å¯èƒ½æ„Ÿèˆˆè¶£çš„人。與其他一些項目ä¸åŒï¼Œå…§æ ¸
-鼓勵人們甚至錯誤地發é€éŽå¤šçš„副本;ä¸è¦å‡å®šç›¸é—œäººå“¡æœƒçœ‹åˆ°æ‚¨åœ¨éƒµä»¶åˆ—表中的發布。
+鼓勵人們甚至錯誤地發é€éŽå¤šçš„副本;ä¸è¦å‡å®šç›¸é—œäººå“¡æœƒçœ‹åˆ°æ‚¨åœ¨éƒµä»¶åˆ—表中的發佈。
尤其是,副本應發é€è‡³ï¼š
- å—影響å­ç³»çµ±çš„ç¶­è­·äººå“¡ã€‚å¦‚å‰æ‰€è¿°ï¼Œç¶­è­·äººå“¡æ–‡ä»¶æ˜¯æŸ¥æ‰¾é€™äº›äººå“¡çš„首é¸åœ°æ–¹ã€‚
- - 其他在åŒä¸€é ˜åŸŸå·¥ä½œçš„開發人員,尤其是那些ç¾åœ¨å¯èƒ½åœ¨é‚£è£¡å·¥ä½œçš„開發人員。使用
+ - 其他在åŒä¸€é ˜åŸŸå·¥ä½œçš„開發人員,尤其是那些ç¾åœ¨å¯èƒ½åœ¨é‚£è£å·¥ä½œçš„開發人員。使用
git查看還有誰修改了您正在處ç†çš„æ–‡ä»¶ï¼Œé€™å¾ˆæœ‰å¹«åŠ©ã€‚
- å¦‚æžœæ‚¨å°æŸéŒ¯èª¤å ±å‘Šæˆ–功能請求åšå‡ºéŸ¿æ‡‰ï¼Œä¹Ÿå¯ä»¥æŠ„é€åŽŸå§‹ç™¼é€äººã€‚
@@ -223,7 +223,7 @@
- å¦‚æžœæ‚¨æ­£åœ¨ä¿®å¾©ä¸€å€‹ç¼ºé™·ï¼Œè«‹è€ƒæ…®è©²ä¿®å¾©æ˜¯å¦æ‡‰é€²å…¥ä¸‹ä¸€å€‹ç©©å®šæ›´æ–°ã€‚如果是這樣,
補ä¸å‰¯æœ¬ä¹Ÿæ‡‰ç™¼åˆ°stable@vger.kernel.org 。å¦å¤–ï¼Œåœ¨è£œä¸æœ¬èº«çš„æ¨™ç±¤ä¸­æ·»åР䏀個
- 「Cc: stable@vger.kernel.orgã€ï¼›é€™å°‡ä½¿ç©©å®šç‰ˆåœ˜éšŠåœ¨ä¿®å¾©é€²å…¥ä¸»ç·šæ™‚收到通知。
+ “Cc: stable@vger.kernel.orgâ€ï¼›é€™å°‡ä½¿ç©©å®šç‰ˆåœ˜éšŠåœ¨ä¿®å¾©é€²å…¥ä¸»ç·šæ™‚收到通知。
當爲一個補ä¸é¸æ“‡æŽ¥æ”¶è€…時,最好清楚你èªçˆ²èª°æœ€çµ‚會接å—這個補ä¸ä¸¦å°‡å…¶åˆä½µã€‚é›–ç„¶
å¯ä»¥å°‡è£œä¸ç›´æŽ¥ç™¼çµ¦Linus Torvalds並讓他åˆä½µï¼Œä½†é€šå¸¸æƒ…æ³ä¸‹ä¸æœƒé€™æ¨£åšã€‚Linus很
@@ -236,7 +236,7 @@
[PATCH nn/mm] subsys: one-line description of the patch
-其中「nnã€æ˜¯è£œä¸çš„åºè™Ÿï¼Œã€Œmmã€æ˜¯ç³»åˆ—中補ä¸çš„總數,「subsysã€æ˜¯å—影響å­ç³»çµ±çš„
+其中“nnâ€æ˜¯è£œä¸çš„åºè™Ÿï¼Œâ€œmmâ€æ˜¯ç³»åˆ—中補ä¸çš„總數,“subsysâ€æ˜¯å—影響å­ç³»çµ±çš„
å稱。當然,一個單ç¨çš„補ä¸å¯ä»¥çœç•¥nn/mm。
如果您有一系列é‡è¦çš„補ä¸ï¼Œé‚£éº¼é€šå¸¸ç™¼é€ä¸€å€‹ç°¡ä»‹ä½œçˆ²ç¬¬ã€‡éƒ¨åˆ†ã€‚ä¸éŽï¼Œé€™å€‹ç´„定
diff --git a/Documentation/translations/zh_TW/process/6.Followthrough.rst b/Documentation/translations/zh_TW/process/6.Followthrough.rst
index 5073b6e77c1c..bcc885ae1b8e 100644
--- a/Documentation/translations/zh_TW/process/6.Followthrough.rst
+++ b/Documentation/translations/zh_TW/process/6.Followthrough.rst
@@ -18,13 +18,13 @@
跟進
====
-此時,您已經éµå¾ªäº†åˆ°ç›®å‰çˆ²æ­¢çµ¦å‡ºçš„æŒ‡å°Žæ–¹é‡ï¼Œä¸¦ä¸”,隨著您自己的工程技能的增加,
+此時,您已經éµå¾ªäº†åˆ°ç›®å‰çˆ²æ­¢çµ¦å‡ºçš„æŒ‡å°Žæ–¹é‡ï¼Œä¸¦ä¸”ï¼Œéš¨ç€æ‚¨è‡ªå·±çš„工程技能的增加,
已經發布了一系列完美的補ä¸ã€‚å³ä½¿æ˜¯ç¶“é©—è±å¯Œçš„內核開發人員也能犯的最大錯誤之一
-是,èªçˆ²ä»–們的工作ç¾åœ¨å·²ç¶“完æˆäº†ã€‚äº‹å¯¦ä¸Šï¼Œç™¼å¸ƒè£œä¸æ„味著進入æµç¨‹çš„下一個階段,
+是,èªçˆ²ä»–們的工作ç¾åœ¨å·²ç¶“完æˆäº†ã€‚äº‹å¯¦ä¸Šï¼Œç™¼ä½ˆè£œä¸æ„味ç€é€²å…¥æµç¨‹çš„下一個階段,
å¯èƒ½é‚„需è¦åšå¾ˆå¤šå·¥ä½œã€‚
-一個補ä¸åœ¨é¦–次發布時就éžå¸¸å‡ºè‰²ã€æ²’有改進的餘地,這是很罕見的。內核開發æµç¨‹å·²
-èªè­˜åˆ°é€™ä¸€äº‹å¯¦ï¼Œå› æ­¤å®ƒéžå¸¸æ³¨é‡å°å·²ç™¼å¸ƒä»£ç¢¼çš„æ”¹é€²ã€‚作爲代碼的作者,您應該與
+一個補ä¸åœ¨é¦–次發佈時就éžå¸¸å‡ºè‰²ã€æ²’有改進的餘地,這是很罕見的。內核開發æµç¨‹å·²
+èªè­˜åˆ°é€™ä¸€äº‹å¯¦ï¼Œå› æ­¤å®ƒéžå¸¸æ³¨é‡å°å·²ç™¼ä½ˆä»£ç¢¼çš„æ”¹é€²ã€‚作爲代碼的作者,您應該與
內核社å€åˆä½œï¼Œä»¥ç¢ºä¿æ‚¨çš„代碼符åˆå…§æ ¸çš„è³ªé‡æ¨™æº–。如果ä¸åƒèˆ‡é€™å€‹éŽç¨‹ï¼Œå¾ˆå¯èƒ½æœƒ
無法將補ä¸åˆä½µåˆ°ä¸»ç·šä¸­ã€‚
@@ -41,7 +41,7 @@
調整到大é‡çš„é‡å¯«â€”—都來自於å°Linuxçš„ç†è§£ï¼Œå³å¾žç¾åœ¨èµ·å年後,Linuxä»å°‡
在開發中。
- - 代碼審查是一項艱苦的工作,這是一項相å°åƒåŠ›ä¸è¨Žå¥½çš„工作;人們記得誰編寫了
+ - 代碼審查是一項艱苦的工作,這是一項相å°å–«åŠ›ä¸è¨Žå¥½çš„工作;人們記得誰編寫了
å…§æ ¸ä»£ç¢¼ï¼Œä½†å°æ–¼é‚£äº›å¯©æŸ¥å®ƒçš„人來說,幾乎沒有什麼長久的åè²ã€‚因此,審閱
人員å¯èƒ½æœƒè®Šå¾—æš´èºï¼Œå°¤å…¶æ˜¯ç•¶ä»–å€‘çœ‹åˆ°åŒæ¨£çš„錯誤被一éåˆä¸€é地犯下時。如果
你得到了一個看起來憤怒ã€ä¾®è¾±æˆ–å®Œå…¨å†’çŠ¯ä½ çš„è©•è«–ï¼Œè«‹æŠ‘åˆ¶ä»¥åŒæ¨£æ–¹å¼å›žæ‡‰çš„è¡å‹•。
@@ -54,7 +54,7 @@
所有這些歸根çµåº•å°±æ˜¯ï¼Œç•¶å¯©é–±è€…å‘æ‚¨ç™¼é€è©•è«–æ™‚ï¼Œæ‚¨éœ€è¦æ³¨æ„他們正在進行的技術
評論。ä¸è¦è®“ä»–å€‘çš„è¡¨é”æ–¹å¼æˆ–你自己的驕傲阻止此事。當你在一個補ä¸ä¸Šå¾—到評論
-時,花點時間去ç†è§£è©•論人想說什麼。如果å¯èƒ½çš„è©±ï¼Œè«‹ä¿®è¦†å¯©é–±è€…è¦æ±‚您修復的內
+時,花點時間去ç†è§£è©•論人想說什麼。如果å¯èƒ½çš„è©±ï¼Œè«‹ä¿®å¾©å¯©é–±è€…è¦æ±‚您修復的內
容。然後回覆審閱者:è¬è¬ä»–們,並æè¿°ä½ å°‡å¦‚何回答他們的å•題。
請注æ„,您ä¸å¿…åŒæ„審閱者建議的æ¯å€‹æ›´æ”¹ã€‚如果您èªçˆ²å¯©é–±è€…誤解了您的代碼,請
@@ -65,19 +65,19 @@
是錯誤的,或者你甚至沒有解決正確的å•題。
Andrew Morton建議,æ¯ä¸€å€‹ä¸æœƒå°Žè‡´ä»£ç¢¼æ›´æ”¹çš„審閱評論都應該產生一個é¡å¤–的代碼
-注釋;這å¯ä»¥å¹«åŠ©æœªä¾†çš„å¯©é–±äººå“¡é¿å…第一次出ç¾çš„å•題。
+註釋;這å¯ä»¥å¹«åŠ©æœªä¾†çš„å¯©é–±äººå“¡é¿å…第一次出ç¾çš„å•題。
ä¸€å€‹è‡´å‘½çš„éŒ¯èª¤æ˜¯å¿½è¦–è©•è«–ï¼Œå¸Œæœ›å®ƒå€‘æœƒæ¶ˆå¤±ã€‚å®ƒå€‘ä¸æœƒèµ°çš„。如果您在沒有å°ä¹‹å‰
收到的評論åšå‡ºéŸ¿æ‡‰çš„æƒ…æ³ä¸‹é‡æ–°ç™¼å¸ƒä»£ç¢¼ï¼Œé‚£éº¼å¾ˆå¯èƒ½æœƒç™¼ç¾è£œä¸æ¯«ç„¡ç”¨è™•。
-èªªåˆ°é‡æ–°ç™¼å¸ƒä»£ç¢¼ï¼šè«‹è¨˜ä½ï¼Œå¯©é–±è€…䏿œƒè¨˜ä½æ‚¨ä¸Šæ¬¡ç™¼å¸ƒçš„代碼的所有細節。因此,
+èªªåˆ°é‡æ–°ç™¼å¸ƒä»£ç¢¼ï¼šè«‹è¨˜ä½ï¼Œå¯©é–±è€…䏿œƒè¨˜ä½æ‚¨ä¸Šæ¬¡ç™¼ä½ˆçš„代碼的所有細節。因此,
æé†’å¯©é–±äººå“¡ä»¥å‰æå‡ºçš„å•é¡Œä»¥åŠæ‚¨å¦‚何處ç†é€™äº›å•題總是一個好主æ„;補ä¸è®Šæ›´
日誌是æä¾›æ­¤é¡žä¿¡æ¯çš„好地方。審閱者ä¸å¿…æœç´¢åˆ—表檔案來熟悉上次所說的內容;
å¦‚æžœæ‚¨å¹«åŠ©ä»–å€‘ç›´æŽ¥é–‹å§‹ï¼Œç•¶ä»–å€‘é‡æ–°æŸ¥çœ‹æ‚¨çš„代碼時,心情會更好。
-å¦‚æžœä½ å·²ç¶“è©¦è‘—åšæ­£ç¢ºçš„事情,但事情ä»ç„¶æ²’有進展呢?大多數技術上的分歧都å¯ä»¥
+如果你已經試ç€åšæ­£ç¢ºçš„äº‹æƒ…ï¼Œä½†äº‹æƒ…ä»ç„¶æ²’有進展呢?大多數技術上的分歧都å¯ä»¥
通éŽè¨Žè«–來解決,但有時人們ä»éœ€è¦åšå‡ºæ±ºå®šã€‚如果你真的èªçˆ²é€™å€‹æ±ºå®šå°ä½ ä¸åˆ©ï¼Œ
-ä½ å¯ä»¥è©¦è‘—呿œ‰æ›´é«˜æ¬ŠåŠ›çš„äººä¸Šè¨´ã€‚å°æ–¼æœ¬æ–‡ï¼Œæ›´é«˜æ¬ŠåŠ›çš„äººæ˜¯ Andrew Morton 。
+ä½ å¯ä»¥è©¦ç€å‘æœ‰æ›´é«˜æ¬ŠåŠ›çš„äººä¸Šè¨´ã€‚å°æ–¼æœ¬æ–‡ï¼Œæ›´é«˜æ¬ŠåŠ›çš„äººæ˜¯ Andrew Morton 。
Andrew 在內核開發社å€ä¸­éžå¸¸å—尊敬;他經常爲似乎被絕望阻塞的事情清障。儘管
å¦‚æ­¤ï¼Œä¸æ‡‰è¼•易就直接找 Andrew ï¼Œä¹Ÿä¸æ‡‰åœ¨æ‰€æœ‰å…¶ä»–æ›¿ä»£æ–¹æ¡ˆéƒ½è¢«å˜—è©¦ä¹‹å‰æ‰¾ä»–。
當然,記ä½ï¼Œä»–也å¯èƒ½ä¸åŒæ„ä½ çš„æ„見。
@@ -95,7 +95,7 @@ Andrew 在內核開發社å€ä¸­éžå¸¸å—尊敬;他經常爲似乎被絕望阻å
包å«åœ¨å­ç³»çµ±æ¨¹ä¸­å¯ä»¥æé«˜è£œä¸çš„å¯è¦‹æ€§ã€‚ç¾åœ¨ï¼Œä½¿ç”¨è©²æ¨¹çš„其他開發人員將默èªç²
得補ä¸ã€‚å­ç³»çµ±æ¨¹é€šå¸¸ä¹Ÿçˆ²Linuxæä¾›æ”¯æŒï¼Œä½¿å…¶å…§å®¹å°æ•´å€‹é–‹ç™¼ç¤¾å€å¯è¦‹ã€‚在這一點
-上,您很å¯èƒ½æœƒå¾žä¸€çµ„新的審閱者那裡得到更多的評論;這些評論需è¦åƒä¸Šä¸€è¼ªé‚£æ¨£
+上,您很å¯èƒ½æœƒå¾žä¸€çµ„新的審閱者那è£å¾—到更多的評論;這些評論需è¦åƒä¸Šä¸€è¼ªé‚£æ¨£
得到回應。
åœ¨é€™æ™‚ä¹Ÿæœƒç™¼ç”Ÿé»žä»€éº¼ï¼Œé€™å–æ±ºæ–¼ä½ çš„補ä¸çš„æ€§è³ªï¼Œæ˜¯å¦èˆ‡å…¶ä»–人正在åšçš„工作發生
@@ -114,23 +114,23 @@ Andrew 在內核開發社å€ä¸­éžå¸¸å—尊敬;他經常爲似乎被絕望阻å
這種誘惑,您ä»ç„¶éœ€è¦å°æœ‰å•題或建議的開發人員作出響應。
ä¸éŽï¼Œæ›´é‡è¦çš„æ˜¯ï¼šå°‡ä»£ç¢¼åŒ…å«åœ¨ä¸»ç·šä¸­æœƒå°‡ä»£ç¢¼äº¤çµ¦æ›´å¤šçš„一些測試人員。å³ä½¿æ‚¨
-爲尚未å¯ç”¨çš„硬體æä¾›äº†é©…動程åºï¼Œæ‚¨ä¹Ÿæœƒé©šè¨æ–¼æœ‰å¤šå°‘人會將您的代碼構建到內核
+爲尚未å¯ç”¨çš„硬件æä¾›äº†é©…動程åºï¼Œæ‚¨ä¹Ÿæœƒé©šè¨æ–¼æœ‰å¤šå°‘人會將您的代碼構建到內核
中。當然,如果有測試人員,也å¯èƒ½æœƒæœ‰éŒ¯èª¤å ±å‘Šã€‚
-最糟糕的錯誤報告是回歸。如果你的補ä¸å°Žè‡´å›žæ­¸ï¼Œä½ æœƒç™¼ç¾å¤šåˆ°è®“ä½ ä¸èˆ’æœçš„眼ç›ç›¯
-著你;回歸需è¦å„˜å¿«ä¿®å¾©ã€‚如果您ä¸é¡˜æ„æˆ–ç„¡æ³•ä¿®å¾©å›žæ­¸ï¼ˆå…¶ä»–äººéƒ½ä¸æœƒçˆ²æ‚¨ä¿®å¾©ï¼‰ï¼Œ
+最糟糕的錯誤報告是迴歸。如果你的補ä¸å°Žè‡´è¿´æ­¸ï¼Œä½ æœƒç™¼ç¾å¤šåˆ°è®“ä½ ä¸èˆ’æœçš„眼ç›ç›¯
+ç€ä½ ï¼›è¿´æ­¸éœ€è¦å„˜å¿«ä¿®å¾©ã€‚如果您ä¸é¡˜æ„æˆ–ç„¡æ³•ä¿®å¾©è¿´æ­¸ï¼ˆå…¶ä»–äººéƒ½ä¸æœƒçˆ²æ‚¨ä¿®å¾©ï¼‰ï¼Œ
那麼在穩定期內,您的補ä¸å¹¾ä¹Žè‚¯å®šæœƒè¢«ç§»é™¤ã€‚除了å¦å®šæ‚¨çˆ²ä½¿è£œä¸é€²å…¥ä¸»ç·šæ‰€åšçš„
-æ‰€æœ‰å·¥ä½œä¹‹å¤–ï¼Œå¦‚æžœç”±æ–¼æœªèƒ½ä¿®å¾©å›žæ­¸è€Œå–æ¶ˆè£œä¸ï¼Œå¾ˆå¯èƒ½æœƒä½¿å°‡ä¾†çš„工作更難被åˆä½µã€‚
+æ‰€æœ‰å·¥ä½œä¹‹å¤–ï¼Œå¦‚æžœç”±æ–¼æœªèƒ½ä¿®å¾©è¿´æ­¸è€Œå–æ¶ˆè£œä¸ï¼Œå¾ˆå¯èƒ½æœƒä½¿å°‡ä¾†çš„工作更難被åˆä½µã€‚
-在處ç†å®Œä»»ä½•回歸之後,å¯èƒ½é‚„有其他普通缺陷需è¦è™•ç†ã€‚穩定期是修復這些錯誤並
-確ä¿ä»£ç¢¼åœ¨ä¸»ç·šå…§æ ¸ç‰ˆæœ¬ä¸­çš„首次發布儘å¯èƒ½å¯é çš„æœ€å¥½æ©Ÿæœƒã€‚所以,請回應錯誤
+在處ç†å®Œä»»ä½•迴歸之後,å¯èƒ½é‚„有其他普通缺陷需è¦è™•ç†ã€‚穩定期是修復這些錯誤並
+確ä¿ä»£ç¢¼åœ¨ä¸»ç·šå…§æ ¸ç‰ˆæœ¬ä¸­çš„首次發佈儘å¯èƒ½å¯é çš„æœ€å¥½æ©Ÿæœƒã€‚所以,請回應錯誤
報告,並儘å¯èƒ½è§£æ±ºå•題。這就是穩定期的目的;一旦解決了舊補ä¸çš„任何å•題,就
å¯ä»¥é–‹å§‹ç›¡æƒ…創建新補ä¸ã€‚
別忘了,還有其他節點也å¯èƒ½æœƒå‰µå»ºç¼ºé™·å ±å‘Šï¼šä¸‹ä¸€å€‹ä¸»ç·šç©©å®šç‰ˆæœ¬ï¼Œç•¶è‘—å的發行
商鏿“‡åŒ…嫿‚¨è£œä¸çš„內核版本時等等。繼續響應這些報告是您工作的基本素養。但是
如果這ä¸èƒ½æä¾›è¶³å¤ çš„動機,那麼也需è¦è€ƒæ…®ï¼šé–‹ç™¼ç¤¾å€æœƒè¨˜ä½é‚£äº›åœ¨åˆä½µå¾Œå°ä»£ç¢¼
-å¤±åŽ»èˆˆè¶£çš„é–‹ç™¼äººå“¡ã€‚ä¸‹ä¸€æ¬¡ä½ ç™¼å¸ƒè£œä¸æ™‚ï¼Œä»–å€‘æœƒä»¥ä½ ä»¥å¾Œä¸æœƒæŒçºŒç¶­è­·å®ƒçˆ²å‰æ
+å¤±åŽ»èˆˆè¶£çš„é–‹ç™¼äººå“¡ã€‚ä¸‹ä¸€æ¬¡ä½ ç™¼ä½ˆè£œä¸æ™‚ï¼Œä»–å€‘æœƒä»¥ä½ ä»¥å¾Œä¸æœƒæŒçºŒç¶­è­·å®ƒçˆ²å‰æ
來評估它。
å…¶ä»–å¯èƒ½ç™¼ç”Ÿçš„事情
@@ -141,15 +141,15 @@ Andrew 在內核開發社å€ä¸­éžå¸¸å—尊敬;他經常爲似乎被絕望阻å
維護人員(確ä¿åŒ…å«ä¸€å€‹æ­£ç¢ºçš„From:行,這樣屬性是正確的,並添加一個您自己的
signoff ),或者回復一個 Acked-by: 讓原始發é€è€…å‘上發é€å®ƒã€‚
-如果您ä¸åŒæ„補ä¸ï¼Œè«‹ç¦®è²Œåœ°å›žå¾©ï¼Œè§£é‡‹åŽŸå› ã€‚å¦‚æžœå¯èƒ½çš„話,告訴作者需è¦åšå“ªäº›
-更改æ‰èƒ½è®“您接å—補ä¸ã€‚åˆä½µä»£ç¢¼çš„編寫者和維護者所åå°çš„補ä¸çš„確存在著一定的
+如果您ä¸åŒæ„補ä¸ï¼Œè«‹ç¦®è²Œåœ°å›žè¦†ï¼Œè§£é‡‹åŽŸå› ã€‚å¦‚æžœå¯èƒ½çš„話,告訴作者需è¦åšå“ªäº›
+更改æ‰èƒ½è®“您接å—補ä¸ã€‚åˆä½µä»£ç¢¼çš„編寫者和維護者所åå°çš„補ä¸çš„確存在ç€ä¸€å®šçš„
阻力,但僅此而已。如果你被èªçˆ²ä¸å¿…è¦çš„é˜»ç¤™äº†å¥½çš„å·¥ä½œï¼Œé‚£éº¼é€™äº›è£œä¸æœ€çµ‚會
繞éŽä½ ä¸¦é€²å…¥ä¸»ç·šã€‚在Linux內核中,沒有人å°ä»»ä½•ä»£ç¢¼æ“æœ‰çµ•å°çš„妿±ºæ¬Šã€‚å¯èƒ½é™¤
了Linus。
-在éžå¸¸ç½•見的情æ³ä¸‹ï¼Œæ‚¨å¯èƒ½æœƒçœ‹åˆ°å®Œå…¨ä¸åŒçš„æ±è¥¿ï¼šå¦ä¸€å€‹é–‹ç™¼äººå“¡ç™¼å¸ƒäº†é‡å°æ‚¨
-çš„å•題的ä¸åŒè§£æ±ºæ–¹æ¡ˆã€‚在這時,兩個補ä¸ä¹‹ä¸€å¯èƒ½ä¸æœƒè¢«åˆä½µï¼Œã€Œæˆ‘的補ä¸é¦–å…ˆ
-發布ã€ä¸è¢«èªçˆ²æ˜¯ä¸€å€‹ä»¤äººä¿¡æœçš„æŠ€è¡“論據。如果有別人的補ä¸å–代了你的補ä¸è€Œé€²
+在éžå¸¸ç½•見的情æ³ä¸‹ï¼Œæ‚¨å¯èƒ½æœƒçœ‹åˆ°å®Œå…¨ä¸åŒçš„æ±è¥¿ï¼šå¦ä¸€å€‹é–‹ç™¼äººå“¡ç™¼ä½ˆäº†é‡å°æ‚¨
+çš„å•題的ä¸åŒè§£æ±ºæ–¹æ¡ˆã€‚在這時,兩個補ä¸ä¹‹ä¸€å¯èƒ½ä¸æœƒè¢«åˆä½µï¼Œâ€œæˆ‘的補ä¸é¦–å…ˆ
+發佈â€ä¸è¢«èªçˆ²æ˜¯ä¸€å€‹ä»¤äººä¿¡æœçš„æŠ€è¡“論據。如果有別人的補ä¸å–代了你的補ä¸è€Œé€²
å…¥äº†ä¸»ç·šï¼Œé‚£éº¼åªæœ‰ä¸€ç¨®æ–¹æ³•å¯ä»¥å›žæ‡‰ä½ ï¼šå¾ˆé«˜èˆˆä½ çš„å•題解決了,請繼續工作å§ã€‚
ä»¥é€™ç¨®æ–¹å¼æŠŠæŸäººçš„工作推到一邊å¯èƒ½å°Žè‡´å‚·å¿ƒå’Œæ°£é¤’ï¼Œä½†æ˜¯ç¤¾å€æœƒè¨˜ä½ä½ çš„忇‰ï¼Œ
å³ä½¿å¾ˆä¹…以後他們已經忘記了誰的補ä¸çœŸæ­£è¢«åˆä½µã€‚
diff --git a/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
index 2cbd16bfed29..db74d8ca3f3b 100644
--- a/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
+++ b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
@@ -24,14 +24,14 @@
使用Git管ç†è£œä¸
---------------
-內核使用分布å¼ç‰ˆæœ¬æŽ§åˆ¶å§‹æ–¼2002å¹´åˆï¼Œç•¶æ™‚Linus首次開始使用專有的Bitkeeper應用
-程åºã€‚é›–ç„¶BitKeeper存在爭議,但它所體ç¾çš„è»Ÿé«”ç‰ˆæœ¬ç®¡ç†æ–¹æ³•å»è‚¯å®šä¸æ˜¯ã€‚分布å¼
+內核使用分佈å¼ç‰ˆæœ¬æŽ§åˆ¶å§‹æ–¼2002å¹´åˆï¼Œç•¶æ™‚Linus首次開始使用專有的Bitkeeper應用
+程åºã€‚é›–ç„¶BitKeeper存在爭議,但它所體ç¾çš„è»Ÿä»¶ç‰ˆæœ¬ç®¡ç†æ–¹æ³•å»è‚¯å®šä¸æ˜¯ã€‚分佈å¼
版本控制å¯ä»¥ç«‹å³åŠ é€Ÿå…§æ ¸é–‹ç™¼é …ç›®ã€‚ç¾åœ¨æœ‰å¥½å¹¾ç¨®å…費的BitKeeper替代å“。
ä½†ç„¡è«–å¥½å£žï¼Œå…§æ ¸é …ç›®éƒ½å·²ç¶“é¸æ“‡äº†Git作爲其工具。
-使用Git管ç†è£œä¸å¯ä»¥ä½¿é–‹ç™¼äººå“¡çš„ç”Ÿæ´»æ›´åŠ è¼•é¬†ï¼Œå°¤å…¶æ˜¯éš¨è‘—è£œä¸æ•¸é‡çš„增長。Git也
+使用Git管ç†è£œä¸å¯ä»¥ä½¿é–‹ç™¼äººå“¡çš„生活更加輕鬆,尤其是隨ç€è£œä¸æ•¸é‡çš„增長。Git也
有其粗糙的邊角和一定的å±éšªæ€§ï¼Œå®ƒæ˜¯ä¸€å€‹å¹´è¼•和強大的工具,ä»ç„¶åœ¨å…¶é–‹ç™¼äººå“¡å®Œå–„
-ä¸­ã€‚æœ¬æ–‡æª”ä¸æœƒè©¦åœ–教會讀者如何使用git;這會是個巨長的文檔。相å,這裡的é‡é»ž
+ä¸­ã€‚æœ¬æ–‡æª”ä¸æœƒè©¦åœ–教會讀者如何使用git;這會是個巨長的文檔。相å,這è£çš„é‡é»ž
將是Git如何特別é©åˆå…§æ ¸é–‹ç™¼éŽç¨‹ã€‚想è¦åŠ å¿«ç”¨Git速度的開發人員å¯ä»¥åœ¨ä»¥ä¸‹ç¶²ç«™ä¸Š
找到更多信æ¯ï¼š
@@ -42,22 +42,22 @@
åŒæ™‚網上也能找到å„ç¨®å„æ¨£çš„æ•™ç¨‹ã€‚
在嘗試使用它生æˆè£œä¸ä¾›ä»–人使用之å‰ï¼Œç¬¬ä¸€è¦å‹™æ˜¯é–±è®€ä¸Šè¿°ç¶²é ï¼Œå°Git的工作方å¼
-有一個紮實的了解。使用Git的開發人員應能進行拉å–主線存儲庫的副本,查詢修訂
-æ­·å²ï¼Œæäº¤å°æ¨¹çš„æ›´æ”¹ï¼Œä½¿ç”¨åˆ†æ”¯ç­‰æ“作。了解Git用於é‡å¯«æ­·å²çš„工具(如rebase)
-也很有用。Git有自己的術語和概念;Git的新用戶應該了解引用ã€é ç¨‹åˆ†æ”¯ã€ç´¢å¼•ã€
-快進åˆä½µã€æŽ¨æ‹‰ã€æ¸¸é›¢é ­ç­‰ã€‚一開始å¯èƒ½æœ‰é»žåš‡äººï¼Œä½†é€™äº›æ¦‚念ä¸é›£é€šéŽä¸€é»žå­¸ç¿’來
+有一個紮實的瞭解。使用Git的開發人員應能進行拉å–主線存儲庫的副本,查詢修訂
+æ­·å²ï¼Œæäº¤å°æ¨¹çš„æ›´æ”¹ï¼Œä½¿ç”¨åˆ†æ”¯ç­‰æ“作。瞭解Git用於é‡å¯«æ­·å²çš„工具(如rebase)
+也很有用。Git有自己的術語和概念;Git的新用戶應該瞭解引用ã€é ç¨‹åˆ†æ”¯ã€ç´¢å¼•ã€
+快進åˆä½µã€æŽ¨æ‹‰ã€éŠé›¢é ­ç­‰ã€‚一開始å¯èƒ½æœ‰é»žåš‡äººï¼Œä½†é€™äº›æ¦‚念ä¸é›£é€šéŽä¸€é»žå­¸ç¿’來
ç†è§£ã€‚
使用git生æˆé€šéŽé›»å­éƒµä»¶æäº¤çš„è£œä¸æ˜¯æé«˜é€Ÿåº¦çš„一個很好的練習。
-當您準備好開始建立Git樹供其他人查看時,無疑需è¦ä¸€å€‹å¯ä»¥å¾žä¸­æ‹‰å–的伺æœå™¨ã€‚
-如果您有一個å¯ä»¥è¨ªå•網際網路的系統,那麼使用git-daemon設置這樣的伺æœå™¨ç›¸å°
+當您準備好開始建立Git樹供其他人查看時,無疑需è¦ä¸€å€‹å¯ä»¥å¾žä¸­æ‹‰å–çš„æœå‹™å™¨ã€‚
+如果您有一個å¯ä»¥è¨ªå•因特網的系統,那麼使用git-daemon設置這樣的æœå‹™å™¨ç›¸å°
ç°¡å–®ã€‚åŒæ™‚,å…費的公共託管網站(例如github)也開始出ç¾åœ¨ç¶²çµ¡ä¸Šã€‚æˆç†Ÿçš„開發
人員å¯ä»¥åœ¨kernel.org上ç²å¾—一個帳戶,但這些帳戶並ä¸å®¹æ˜“得到;更多有關信æ¯ï¼Œ
è«‹åƒé–± https://kernel.org/faq/ 。
-正常的Git工作æµç¨‹æ¶‰åŠåˆ°è¨±å¤šåˆ†æ”¯çš„使用。æ¯ä¸€æ¢é–‹ç™¼ç·šéƒ½å¯ä»¥åˆ†çˆ²å–®ç¨çš„「主題
-分支ã€ï¼Œä¸¦ç¨ç«‹ç¶­è­·ã€‚Git的分支很容易使用,沒有ç†ç”±ä¸ä½¿ç”¨å®ƒå€‘。而且,在任何
+正常的Git工作æµç¨‹æ¶‰åŠåˆ°è¨±å¤šåˆ†æ”¯çš„使用。æ¯ä¸€æ¢é–‹ç™¼ç·šéƒ½å¯ä»¥åˆ†çˆ²å–®ç¨çš„“主題
+分支â€ï¼Œä¸¦ç¨ç«‹ç¶­è­·ã€‚Git的分支很容易使用,沒有ç†ç”±ä¸ä½¿ç”¨å®ƒå€‘。而且,在任何
情æ³ä¸‹ï¼Œæ‚¨éƒ½ä¸æ‡‰è©²åœ¨ä»»ä½•您打算讓其他人從中拉å–的分支中進行開發。應該å°å¿ƒåœ°
創建公開å¯ç”¨çš„分支;當開發分支處於完整狀態並已準備好時(è€Œä¸æ˜¯ä¹‹å‰ï¼‰æ‰åˆä½µ
開發分支的補ä¸ã€‚
@@ -72,10 +72,10 @@ Gitæä¾›äº†ä¸€äº›å¼·å¤§çš„工具,å¯ä»¥è®“您é‡å¯«é–‹ç™¼æ­·å²ã€‚䏀個䏿–
簡單癡迷。é‡å¯«æ­·å²å°‡é‡å¯«è©²æ­·å²ä¸­åŒ…å«çš„æ›´æ”¹ï¼Œå°‡ç¶“éŽæ¸¬è©¦ï¼ˆå¸Œæœ›å¦‚此)的內核樹
變爲未經測試的內核樹。除此之外,如果開發人員沒有共享項目歷å²ï¼Œä»–們就無法
輕鬆地å”作;如果您é‡å¯«äº†å…¶ä»–開發人員拉入他們存儲庫的歷å²ï¼Œæ‚¨å°‡ä½¿é€™äº›é–‹ç™¼
-人員的生活更加困難。因此,這裡有一個簡單的經驗法則:被導出到其他地方的歷å²
+äººå“¡çš„ç”Ÿæ´»æ›´åŠ å›°é›£ã€‚å› æ­¤ï¼Œé€™è£æœ‰ä¸€å€‹ç°¡å–®çš„經驗法則:被導出到其他地方的歷å²
在此後通常被èªçˆ²æ˜¯ä¸å¯è®Šçš„。
-因此,一旦將一組更改推é€åˆ°å…¬é–‹å¯ç”¨çš„伺æœå™¨ä¸Šï¼Œå°±ä¸æ‡‰è©²é‡å¯«é€™äº›æ›´æ”¹ã€‚如果您
+因此,一旦將一組更改推é€åˆ°å…¬é–‹å¯ç”¨çš„æœå‹™å™¨ä¸Šï¼Œå°±ä¸æ‡‰è©²é‡å¯«é€™äº›æ›´æ”¹ã€‚如果您
嘗試強制進行無法快進åˆä½µçš„æ›´æ”¹ï¼ˆå³ä¸å…±äº«åŒä¸€æ­·å²è¨˜éŒ„的更改),Git將嘗試強制
執行此è¦å‰‡ã€‚這å¯èƒ½è¦†è“‹æª¢æŸ¥ï¼Œæœ‰æ™‚甚至需è¦é‡å¯«å°Žå‡ºçš„æ¨¹ã€‚在樹之間移動變更集以
é¿å…linux-next中的è¡çªå°±æ˜¯ä¸€å€‹ä¾‹å­ã€‚但這種行爲應該是罕見的。這就是爲什麼
@@ -86,9 +86,9 @@ Gitæä¾›äº†ä¸€äº›å¼·å¤§çš„工具,å¯ä»¥è®“您é‡å¯«é–‹ç™¼æ­·å²ã€‚䏀個䏿–
å°æ–¼ä¸€å€‹ç§æœ‰çš„分支,rebasing å¯èƒ½æ˜¯ä¸€å€‹å¾ˆå®¹æ˜“跟上å¦ä¸€æ£µæ¨¹çš„æ–¹æ³•,但是一旦
一棵樹被導出到外界,rebasingå°±ä¸å¯å–了。一旦發生這種情æ³ï¼Œå°±å¿…須進行完全
åˆä½µï¼ˆmerge)。åˆä½µæœ‰æ™‚是很有æ„ç¾©çš„ï¼Œä½†æ˜¯éŽæ–¼é »ç¹çš„åˆä½µæœƒä¸å¿…è¦åœ°æ“¾äº‚æ­·å²ã€‚
-在這種情æ³ä¸‹å»ºè­°çš„åšæ³•是ä¸è¦é »ç¹åˆä½µï¼Œé€šå¸¸åªåœ¨ç‰¹å®šçš„發布點(如主線-rc發布)
+在這種情æ³ä¸‹å»ºè­°çš„åšæ³•是ä¸è¦é »ç¹åˆä½µï¼Œé€šå¸¸åªåœ¨ç‰¹å®šçš„發佈點(如主線-rc發佈)
åˆä½µã€‚如果您å°ç‰¹å®šçš„æ›´æ”¹æ„Ÿåˆ°ç·Šå¼µï¼Œå‰‡å¯ä»¥å§‹çµ‚åœ¨ç§æœ‰åˆ†æ”¯ä¸­åŸ·è¡Œæ¸¬è©¦åˆä½µã€‚在
-這種情æ³ä¸‹ï¼Œgit「rerereã€å·¥å…·å¾ˆæœ‰ç”¨ï¼›å®ƒèƒ½è¨˜ä½åˆä½µè¡çªæ˜¯å¦‚何解決的,這樣您
+這種情æ³ä¸‹ï¼Œgit“rerereâ€å·¥å…·å¾ˆæœ‰ç”¨ï¼›å®ƒèƒ½è¨˜ä½åˆä½µè¡çªæ˜¯å¦‚何解決的,這樣您
å°±ä¸å¿…é‡è¤‡ç›¸åŒçš„工作。
關於Git這樣的工具的一個最大的å覆抱怨是:補ä¸å¾žä¸€å€‹å­˜å„²åº«åˆ°å¦ä¸€å€‹å­˜å„²åº«çš„
@@ -98,36 +98,36 @@ Gitæä¾›äº†ä¸€äº›å¼·å¤§çš„工具,å¯ä»¥è®“您é‡å¯«é–‹ç™¼æ­·å²ã€‚䏀個䏿–
::
- ä½ å¯ä»¥çµ¦æˆ‘發補ä¸ï¼Œä½†ç•¶æˆ‘從你那裡拉å–一個Gitè£œä¸æ™‚,我需è¦çŸ¥é“你清楚
+ ä½ å¯ä»¥çµ¦æˆ‘發補ä¸ï¼Œä½†ç•¶æˆ‘å¾žä½ é‚£è£æ‹‰å–一個Gitè£œä¸æ™‚,我需è¦çŸ¥é“你清楚
自己在åšä»€éº¼ï¼Œæˆ‘需è¦èƒ½å¤ ç›¸ä¿¡äº‹æƒ…而 *無需* 手動檢查æ¯å€‹å–®ç¨çš„æ›´æ”¹ã€‚
(http://lwn.net/Articles/224135/)。
-爲了é¿å…這種情æ³ï¼Œè«‹ç¢ºä¿çµ¦å®šåˆ†æ”¯ä¸­çš„æ‰€æœ‰è£œä¸éƒ½èˆ‡ç›¸é—œä¸»é¡Œç·Šå¯†ç›¸é—œï¼›ã€Œé©…動程åº
-修復ã€åˆ†æ”¯ä¸æ‡‰æ›´æ”¹æ ¸å¿ƒå…§å­˜ç®¡ç†ä»£ç¢¼ã€‚而且,最é‡è¦çš„æ˜¯ï¼Œä¸è¦ä½¿ç”¨Git樹來繞éŽ
-審查éŽç¨‹ã€‚䏿™‚的將樹的摘è¦ç™¼å¸ƒåˆ°ç›¸é—œçš„列表中,在åˆé©æ™‚候請求linux-next中
+爲了é¿å…這種情æ³ï¼Œè«‹ç¢ºä¿çµ¦å®šåˆ†æ”¯ä¸­çš„æ‰€æœ‰è£œä¸éƒ½èˆ‡ç›¸é—œä¸»é¡Œç·Šå¯†ç›¸é—œï¼›â€œé©…動程åº
+修復â€åˆ†æ”¯ä¸æ‡‰æ›´æ”¹æ ¸å¿ƒå…§å­˜ç®¡ç†ä»£ç¢¼ã€‚而且,最é‡è¦çš„æ˜¯ï¼Œä¸è¦ä½¿ç”¨Git樹來繞éŽ
+審查éŽç¨‹ã€‚䏿™‚的將樹的摘è¦ç™¼ä½ˆåˆ°ç›¸é—œçš„列表中,在åˆé©æ™‚候請求linux-next中
包å«è©²æ¨¹ã€‚
如果其他人開始發é€è£œä¸ä»¥åŒ…å«åˆ°æ‚¨çš„æ¨¹ä¸­ï¼Œä¸è¦å¿˜è¨˜å¯©é–±å®ƒå€‘。還è¦ç¢ºä¿æ‚¨ç¶­è­·æ­£ç¢º
-的作者信æ¯ï¼› git 「amã€å·¥å…·åœ¨é€™æ–¹é¢åšå¾—最好,但是如果補ä¸é€šéŽç¬¬ä¸‰æ–¹è½‰ç™¼çµ¦æ‚¨ï¼Œ
-您å¯èƒ½éœ€è¦åœ¨è£œä¸ä¸­æ·»åŠ ã€ŒFrom:ã€è¡Œã€‚
+的作者信æ¯ï¼› git “amâ€å·¥å…·åœ¨é€™æ–¹é¢åšå¾—最好,但是如果補ä¸é€šéŽç¬¬ä¸‰æ–¹è½‰ç™¼çµ¦æ‚¨ï¼Œ
+您å¯èƒ½éœ€è¦åœ¨è£œä¸ä¸­æ·»åŠ â€œFrom:â€è¡Œã€‚
è«‹æ±‚æ‹‰å–æ™‚,請務必æä¾›æ‰€æœ‰ç›¸é—œä¿¡æ¯ï¼šæ¨¹çš„ä½ç½®ã€è¦æ‹‰å–çš„åˆ†æ”¯ä»¥åŠæ‹‰å–將導致的
æ›´æ”¹ã€‚åœ¨é€™æ–¹é¢ git request-pull 命令éžå¸¸æœ‰ç”¨ï¼›å®ƒå°‡æŒ‰ç…§å…¶ä»–開發人員所期望的
-æ ¼å¼åŒ–è«‹æ±‚ï¼Œä¸¦æª¢æŸ¥ä»¥ç¢ºä¿æ‚¨å·²è¨˜å¾—將這些更改推é€åˆ°å…¬å…±ä¼ºæœå™¨ã€‚
+æ ¼å¼åŒ–è«‹æ±‚ï¼Œä¸¦æª¢æŸ¥ä»¥ç¢ºä¿æ‚¨å·²è¨˜å¾—將這些更改推é€åˆ°å…¬å…±æœå‹™å™¨ã€‚
審閱補ä¸
--------
-一些讀者顯然會åå°å°‡æœ¬ç¯€èˆ‡ã€Œé«˜ç´šä¸»é¡Œã€æ”¾åœ¨ä¸€èµ·ï¼Œå› çˆ²å³ä½¿æ˜¯å‰›é–‹å§‹çš„內核開發人員
-也應該審閱補ä¸ã€‚當然,沒有比查看其他人發布的代碼更好的方法來學習如何在內核環境
+一些讀者顯然會åå°å°‡æœ¬ç¯€èˆ‡â€œé«˜ç´šä¸»é¡Œâ€æ”¾åœ¨ä¸€èµ·ï¼Œå› çˆ²å³ä½¿æ˜¯å‰›é–‹å§‹çš„內核開發人員
+也應該審閱補ä¸ã€‚當然,沒有比查看其他人發佈的代碼更好的方法來學習如何在內核環境
中編程了。此外,審閱者永é ä¾›ä¸æ‡‰æ±‚;通éŽå¯©é–±ä»£ç¢¼ï¼Œæ‚¨å¯ä»¥å°æ•´å€‹æµç¨‹åšå‡ºé‡å¤§è²¢ç»ã€‚
審查代碼å¯èƒ½æ˜¯ä¸€å‰¯ä»¤äººç”Ÿç•的圖景,特別是å°ä¸€å€‹æ–°çš„內核開發人員來說,他們
-å¯èƒ½æœƒå°å…¬é–‹è©¢å•代碼感到緊張,而這些代碼是由那些有更多經驗的人發布的。ä¸éŽï¼Œ
+å¯èƒ½æœƒå°å…¬é–‹è©¢å•代碼感到緊張,而這些代碼是由那些有更多經驗的人發佈的。ä¸éŽï¼Œ
å³ä½¿æ˜¯æœ€æœ‰ç¶“驗的開發人員編寫的代碼也å¯ä»¥å¾—到改進。也許å°ï¼ˆæ‰€æœ‰ï¼‰å¯©é–±è€…最好
-的建議是:把審閱評論當æˆå•é¡Œè€Œä¸æ˜¯æ‰¹è©•。詢å•「在這æ¢è·¯å¾‘中如何釋放鎖?ã€
-ç¸½æ˜¯æ¯”èªªã€Œé€™è£¡çš„éŽ–æ˜¯éŒ¯èª¤çš„ã€æ›´å¥½ã€‚
+的建議是:把審閱評論當æˆå•é¡Œè€Œä¸æ˜¯æ‰¹è©•。詢å•“在這æ¢è·¯å¾‘中如何釋放鎖?â€
+總是比說“這è£çš„éŽ–æ˜¯éŒ¯èª¤çš„â€æ›´å¥½ã€‚
ä¸åŒçš„開發人員將從ä¸åŒçš„角度審查代碼。部分人會主è¦é—œæ³¨ä»£ç¢¼é¢¨æ ¼ä»¥åŠä»£ç¢¼è¡Œæ˜¯
妿œ‰å°¾éš¨ç©ºæ ¼ã€‚其他人會主è¦é—œæ³¨è£œä¸ä½œçˆ²ä¸€å€‹æ•´é«”實ç¾çš„變更是å¦å°å…§æ ¸æœ‰å¥½è™•。
diff --git a/Documentation/translations/zh_TW/process/8.Conclusion.rst b/Documentation/translations/zh_TW/process/8.Conclusion.rst
index 1207991d1570..a0c00741f912 100644
--- a/Documentation/translations/zh_TW/process/8.Conclusion.rst
+++ b/Documentation/translations/zh_TW/process/8.Conclusion.rst
@@ -17,13 +17,13 @@
更多信æ¯
========
-關於Linux內核開發和相關主題的信æ¯ä¾†æºå¾ˆå¤šã€‚首先是在內核原始碼分發中找到的
+關於Linux內核開發和相關主題的信æ¯ä¾†æºå¾ˆå¤šã€‚首先是在內核æºä»£ç¢¼åˆ†ç™¼ä¸­æ‰¾åˆ°çš„
文檔目錄。頂級
-:ref:`Documentation/translations/zh_TW/process/howto.rst <tw_process_howto>`
+:ref:`Documentation/translations/zh_CN/process/howto.rst <tw_process_howto>`
文件是一個é‡è¦çš„起點;
-:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+:ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <tw_submittingpatches>`
也是所有內核開發人員都應該閱讀的內容。許多內部內核API都是使用kerneldoc機制
-記錄的;「make htmldocsã€æˆ–「make pdfdocsã€å¯ç”¨æ–¼ä»¥HTML或PDFæ ¼å¼ç”Ÿæˆé€™äº›æ–‡æª”
+記錄的;“make htmldocsâ€æˆ–“make pdfdocsâ€å¯ç”¨æ–¼ä»¥HTML或PDFæ ¼å¼ç”Ÿæˆé€™äº›æ–‡æª”
(儘管æŸäº›ç™¼è¡Œç‰ˆæä¾›çš„tex版本會é‡åˆ°å…§éƒ¨é™åˆ¶ï¼Œç„¡æ³•æ­£ç¢ºè™•ç†æ–‡æª”)。
ä¸åŒçš„網站在å„個細節層次上討論內核開發。本文作者想謙虛地建議用 https://lwn.net/
@@ -35,7 +35,7 @@
https://kernelnewbies.org/
-ç•¶ç„¶ï¼Œä¹Ÿä¸æ‡‰è©²å¿˜è¨˜ https://kernel.org/ ,這是內核發布信æ¯çš„æœ€çµ‚ä½ç½®ã€‚
+ç•¶ç„¶ï¼Œä¹Ÿä¸æ‡‰è©²å¿˜è¨˜ https://kernel.org/ ,這是內核發佈信æ¯çš„æœ€çµ‚ä½ç½®ã€‚
關於內核開發有很多書:
@@ -47,7 +47,7 @@
《深入ç†è§£Linux內核》(Daniel Bovetå’ŒMarco Cesati)
然而,所有這些書都有一個共åŒçš„ç¼ºé»žï¼šå®ƒå€‘ä¸Šæž¶æ™‚å°±å¾€å¾€æœ‰äº›éŽæ™‚,而且已經上架
-一段時間了。ä¸éŽï¼Œåœ¨é‚£è£¡é‚„是å¯ä»¥æ‰¾åˆ°ç›¸ç•¶å¤šçš„好信æ¯ã€‚
+一段時間了。ä¸éŽï¼Œåœ¨é‚£è£é‚„是å¯ä»¥æ‰¾åˆ°ç›¸ç•¶å¤šçš„好信æ¯ã€‚
有關git的文檔,請訪å•:
@@ -61,7 +61,7 @@
ç¥è³€æ‰€æœ‰é€šéŽé€™ç¯‡å†—長的文檔的人。希望它能夠幫助您ç†è§£Linux內核是如何開發的,
ä»¥åŠæ‚¨å¦‚何åƒèˆ‡é€™å€‹éŽç¨‹ã€‚
-最後,é‡è¦çš„æ˜¯åƒèˆ‡ã€‚任何開æºè»Ÿé«”é …ç›®éƒ½ä¸æœƒè¶…éŽå…¶è²¢ç»è€…投入其中的總和。Linux
+最後,é‡è¦çš„æ˜¯åƒèˆ‡ã€‚任何開æºè»Ÿä»¶é …ç›®éƒ½ä¸æœƒè¶…éŽå…¶è²¢ç»è€…投入其中的總和。Linux
內核的發展速度和以å‰ä¸€æ¨£å¿«ï¼Œå› çˆ²å®ƒå¾—到了大é‡é–‹ç™¼äººå“¡çš„幫助,他們都在努力使它
變得更好。內核是一個最æˆåŠŸçš„ä¾‹å­ï¼Œèªªæ˜Žäº†ç•¶æˆåƒä¸Šè¬çš„人爲了一個共åŒçš„目標一起
工作時,å¯ä»¥åšå‡ºä»€éº¼ã€‚
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
index 920bb0f36974..48df918000e9 100644
--- a/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
+++ b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
@@ -8,34 +8,34 @@
.. _tw_code_of_conduct_interpretation:
-Linux內核貢ç»è€…契約行為準則解釋
+Linux內核貢ç»è€…契約行爲準則解釋
===============================
:ref:`tw_code_of_conduct` 準則是一個通用文檔,旨在爲幾乎所有開æºç¤¾å€æä¾›ä¸€å¥—è¦å‰‡ã€‚
æ¯å€‹é–‹æºç¤¾å€éƒ½æ˜¯ç¨ä¸€ç„¡äºŒçš„,Linux內核也ä¸ä¾‹å¤–。因此,本文æè¿°äº†Linux內核社å€ä¸­
-如何解釋它。我們也ä¸å¸Œæœ›é€™ç¨®è§£é‡‹éš¨è‘—æ™‚é–“çš„æŽ¨ç§»æ˜¯éœæ…‹çš„,並將根據需è¦é€²è¡Œèª¿æ•´ã€‚
+如何解釋它。我們也ä¸å¸Œæœ›é€™ç¨®è§£é‡‹éš¨ç€æ™‚é–“çš„æŽ¨ç§»æ˜¯éœæ…‹çš„,並將根據需è¦é€²è¡Œèª¿æ•´ã€‚
-èˆ‡é–‹ç™¼è»Ÿé«”çš„ã€Œå‚³çµ±ã€æ–¹æ³•相比,Linux內核開發工作是一個éžå¸¸å€‹äººåŒ–çš„éŽç¨‹ã€‚你的貢ç»
+èˆ‡é–‹ç™¼è»Ÿä»¶çš„â€œå‚³çµ±â€æ–¹æ³•相比,Linux內核開發工作是一個éžå¸¸å€‹äººåŒ–çš„éŽç¨‹ã€‚你的貢ç»
å’ŒèƒŒå¾Œçš„æƒ³æ³•å°‡è¢«ä»”ç´°å¯©æŸ¥ï¼Œå¾€å¾€å°Žè‡´æ‰¹åˆ¤å’Œæ‰¹è©•ã€‚å¯©æŸ¥å°‡å¹¾ä¹Žç¸½æ˜¯éœ€è¦æ”¹é€²ï¼Œææ–™æ‰
能包括在內核中。è¦çŸ¥é“這是因爲所有相關人員都希望看到Linuxæ•´é«”æˆåŠŸçš„æœ€ä½³è§£æ±ºæ–¹
-案。這個開發éŽç¨‹å·²ç¶“被證明å¯ä»¥å‰µå»ºæœ‰å²ä»¥ä¾†æœ€å¥å£¯çš„ä½œæ¥­ç³»çµ±å…§æ ¸ï¼Œæˆ‘å€‘ä¸æƒ³åšä»»ä½•
+案。這個開發éŽç¨‹å·²ç¶“被證明å¯ä»¥å‰µå»ºæœ‰å²ä»¥ä¾†æœ€å¥å£¯çš„æ“ä½œç³»çµ±å…§æ ¸ï¼Œæˆ‘å€‘ä¸æƒ³åšä»»ä½•
事情來導致æäº¤è³ªé‡å’Œæœ€çµ‚çµæžœçš„下é™ã€‚
維護者
------
-行為準則多次使用「維護者ã€ä¸€è©žã€‚在內核社å€ä¸­ï¼Œã€Œç¶­è­·è€…ã€æ˜¯è² è²¬å­ç³»çµ±ã€é©…å‹•ç¨‹åºæˆ–
-文件的任何人,並在內核原始碼樹的維護者文件中列出。
+行爲準則多次使用“維護者â€ä¸€è©žã€‚在內核社å€ä¸­ï¼Œâ€œç¶­è­·è€…â€æ˜¯è² è²¬å­ç³»çµ±ã€é©…å‹•ç¨‹åºæˆ–
+文件的任何人,並在內核æºä»£ç¢¼æ¨¹çš„維護者文件中列出。
責任
----
-《行為準則》æåˆ°äº†ç¶­è­·äººå“¡çš„æ¬Šåˆ©å’Œè²¬ä»»ï¼Œé€™éœ€è¦é€²ä¸€æ­¥æ¾„清。
+《行爲準則》æåˆ°äº†ç¶­è­·äººå“¡çš„æ¬Šåˆ©å’Œè²¬ä»»ï¼Œé€™éœ€è¦é€²ä¸€æ­¥æ¾„清。
首先,最é‡è¦çš„æ˜¯ï¼Œæœ‰ä¸€å€‹åˆç†çš„æœŸæœ›æ˜¯ç”±ç¶­è­·äººå“¡é€šéŽå¯¦ä¾‹ä¾†é ˜å°Žã€‚
ä¹Ÿå°±æ˜¯èªªï¼Œæˆ‘å€‘çš„ç¤¾å€æ˜¯å»£é—Šçš„,å°ç¶­è­·è€…æ²’æœ‰æ–°çš„è¦æ±‚,他們單方é¢è™•ç†å…¶ä»–人在
-他們活èºçš„社å€çš„行爲。這一責任由我們所有人承擔,最終《行為準則》記錄了最終的
+他們活èºçš„社å€çš„行爲。這一責任由我們所有人承擔,最終《行爲準則》記錄了最終的
上訴路徑,以防有關行爲å•題的å•題懸而未決。
維護人員應該願æ„在出ç¾å•題時æä¾›å¹«åŠ©ï¼Œä¸¦åœ¨éœ€è¦æ™‚與社å€ä¸­çš„其他人åˆä½œã€‚如果您
@@ -43,10 +43,10 @@ Linux內核貢ç»è€…契約行為準則解釋
é™¤éžæ‚¨é¡˜æ„,å¦å‰‡ä¸æœƒå°‡å…¶è¦–爲é•è¦å ±å‘Šã€‚如果您ä¸ç¢ºå®šæ˜¯å¦è©²è¯ç¹«TAB 或任何其他維
護人員,請è¯ç¹«æˆ‘們的è¡çªèª¿è§£äºº Mishi Choudhary <mishi@linux.com>。
-æœ€å¾Œï¼Œã€Œå–„å¾…å°æ–¹ã€æ‰æ˜¯æ¯å€‹äººçš„æœ€çµ‚ç›®æ¨™ã€‚æˆ‘å€‘çŸ¥é“æ¯å€‹äººéƒ½æ˜¯äººï¼Œæœ‰æ™‚我們都會失敗,
-但我們所有人的首è¦ç›®æ¨™æ‡‰è©²æ˜¯åŠªåŠ›å‹å¥½åœ°è§£æ±ºå•é¡Œã€‚åŸ·è¡Œè¡Œç‚ºæº–å‰‡å°‡æ˜¯æœ€å¾Œçš„é¸æ“‡ã€‚
+æœ€å¾Œï¼Œâ€œå–„å¾…å°æ–¹â€çº”是æ¯å€‹äººçš„æœ€çµ‚ç›®æ¨™ã€‚æˆ‘å€‘çŸ¥é“æ¯å€‹äººéƒ½æ˜¯äººï¼Œæœ‰æ™‚我們都會失敗,
+但我們所有人的首è¦ç›®æ¨™æ‡‰è©²æ˜¯åŠªåŠ›å‹å¥½åœ°è§£æ±ºå•é¡Œã€‚åŸ·è¡Œè¡Œçˆ²æº–å‰‡å°‡æ˜¯æœ€å¾Œçš„é¸æ“‡ã€‚
-æˆ‘å€‘çš„ç›®æ¨™æ˜¯å‰µå»ºä¸€å€‹å¼·å¤§çš„ã€æŠ€è¡“å…ˆé€²çš„ä½œæ¥­ç³»çµ±ï¼Œä»¥åŠæ‰€æ¶‰åŠçš„æŠ€è¡“複雜性,這自
+æˆ‘å€‘çš„ç›®æ¨™æ˜¯å‰µå»ºä¸€å€‹å¼·å¤§çš„ã€æŠ€è¡“å…ˆé€²çš„æ“ä½œç³»çµ±ï¼Œä»¥åŠæ‰€æ¶‰åŠçš„æŠ€è¡“複雜性,這自
然需è¦å°ˆæ¥­çŸ¥è­˜å’Œæ±ºç­–。
所需的專業知識因貢ç»é ˜åŸŸè€Œç•°ã€‚它主è¦ç”±ä¸Šä¸‹æ–‡å’ŒæŠ€è¡“複雜性決定,其次由貢ç»è€…å’Œ
@@ -55,58 +55,58 @@ Linux內核貢ç»è€…契約行為準則解釋
專家的期望和決策都è¦ç¶“éŽè¨Žè«–,但在最後,爲了å–得進展,必須能夠åšå‡ºæ±ºç­–。這一
特權掌æ¡åœ¨ç¶­è­·äººå“¡å’Œé …目領導的手中,é è¨ˆå°‡å–„æ„使用。
-因此,設定專業知識期望ã€ä½œå‡ºæ±ºå®šå’Œæ‹’絕ä¸é©ç•¶çš„è²¢ç»ä¸è¢«è¦–爲é•å行為準則。
+因此,設定專業知識期望ã€ä½œå‡ºæ±ºå®šå’Œæ‹’絕ä¸é©ç•¶çš„è²¢ç»ä¸è¢«è¦–爲é•å行爲準則。
雖然維護人員一般都歡迎新來者,但他們幫助(新)貢ç»è€…å…‹æœéšœç¤™çš„能力有é™ï¼Œå› æ­¤
-ä»–å€‘å¿…é ˆç¢ºå®šå„ªå…ˆäº‹é …ã€‚é€™ä¹Ÿä¸æ‡‰è¢«è¦–爲é•åäº†è¡Œç‚ºæº–å‰‡ã€‚å…§æ ¸ç¤¾å€æ„識到這一點,並
+ä»–å€‘å¿…é ˆç¢ºå®šå„ªå…ˆäº‹é …ã€‚é€™ä¹Ÿä¸æ‡‰è¢«è¦–爲é•åäº†è¡Œçˆ²æº–å‰‡ã€‚å…§æ ¸ç¤¾å€æ„識到這一點,並
以å„ç¨®å½¢å¼æä¾›å…¥é–€ç´šç¯€ç›®ï¼Œå¦‚ kernelnewbies.org 。
範åœ
----
-Linux內核社å€ä¸»è¦åœ¨ä¸€çµ„公共電å­éƒµä»¶åˆ—表上進行交互,這些列表分布在由多個ä¸åŒ
-公叿ˆ–個人控制的多個ä¸åŒä¼ºæœå™¨ä¸Šã€‚所有這些列表都在內核原始碼樹中的
+Linux內核社å€ä¸»è¦åœ¨ä¸€çµ„公共電å­éƒµä»¶åˆ—表上進行交互,這些列表分佈在由多個ä¸åŒ
+公叿ˆ–個人控制的多個ä¸åŒæœå‹™å™¨ä¸Šã€‚所有這些列表都在內核æºä»£ç¢¼æ¨¹ä¸­çš„
MAINTAINERS 文件中定義。發é€åˆ°é€™äº›éƒµä»¶åˆ—表的任何電å­éƒµä»¶éƒ½è¢«è¦–爲包å«åœ¨è¡Œçˆ²
準則中。
使用 kernel.org bugzilla和其他å­ç³»çµ±bugzilla 或bug跟蹤工具的開發人員應該éµå¾ª
-行為準則的指導原則。Linuxå…§æ ¸ç¤¾å€æ²’有「官方ã€é …目電å­éƒµä»¶åœ°å€æˆ–「官方ã€ç¤¾äº¤åª’é«”
-地å€ã€‚使用kernel.orgé›»å­éƒµä»¶å¸³æˆ¶åŸ·è¡Œçš„任何活動必須éµå¾ªçˆ²kernel.org發布的行爲
+行爲準則的指導原則。Linuxå…§æ ¸ç¤¾å€æ²’有“官方â€é …目電å­éƒµä»¶åœ°å€æˆ–“官方â€ç¤¾äº¤åª’é«”
+地å€ã€‚使用kernel.orgé›»å­éƒµä»¶å¸³æˆ¶åŸ·è¡Œçš„任何活動必須éµå¾ªçˆ²kernel.org發佈的行爲
準則,就åƒä»»ä½•使用公å¸é›»å­éƒµä»¶å¸³æˆ¶çš„個人必須éµå¾ªè©²å…¬å¸çš„特定è¦å‰‡ä¸€æ¨£ã€‚
-行為準則並ä¸ç¦æ­¢åœ¨éƒµä»¶åˆ—表消æ¯ã€å…§æ ¸æ›´æ”¹æ—¥èªŒæ¶ˆæ¯æˆ–代碼注釋中繼續包å«å稱ã€
+行爲準則並ä¸ç¦æ­¢åœ¨éƒµä»¶åˆ—表消æ¯ã€å…§æ ¸æ›´æ”¹æ—¥èªŒæ¶ˆæ¯æˆ–代碼註釋中繼續包å«å稱ã€
é›»å­éƒµä»¶åœ°å€å’Œç›¸é—œæ³¨é‡‹ã€‚
-其他論壇中的互動包括在é©ç”¨æ–¼ä¸Šè¿°è«–壇的任何è¦å‰‡ä¸­ï¼Œé€šå¸¸ä¸åŒ…括在行為準則中。
+其他論壇中的互動包括在é©ç”¨æ–¼ä¸Šè¿°è«–壇的任何è¦å‰‡ä¸­ï¼Œé€šå¸¸ä¸åŒ…括在行爲準則中。
除了在極端情æ³ä¸‹å¯è€ƒæ…®çš„例外情æ³ã€‚
-æäº¤çµ¦å…§æ ¸çš„è²¢ç»æ‡‰è©²ä½¿ç”¨é©ç•¶çš„語言。在行為準則之å‰å·²ç¶“存在的內容ç¾åœ¨ä¸æœƒè¢«
+æäº¤çµ¦å…§æ ¸çš„è²¢ç»æ‡‰è©²ä½¿ç”¨é©ç•¶çš„語言。在行爲準則之å‰å·²ç¶“存在的內容ç¾åœ¨ä¸æœƒè¢«
視爲é•å。然而,ä¸é©ç•¶çš„語言å¯ä»¥è¢«è¦–爲一個bug;如果任何相關方æäº¤è£œä¸ï¼Œ
這樣的bug將被更快地修復。當å‰å±¬æ–¼ç”¨æˆ¶/å…§æ ¸API的一部分的表é”å¼ï¼Œæˆ–è€…åæ˜ å·²
-發布標準或è¦ç¯„中使用的術語的表é”å¼ï¼Œä¸è¢«è¦–爲bug。
+發佈標準或è¦ç¯„中使用的術語的表é”å¼ï¼Œä¸è¢«è¦–爲bug。
執行
----
-行為準則中列出的地å€å±¬æ–¼è¡Œç‚ºæº–則委員會。https://kernel.org/code-of-conduct.html
+行爲準則中列出的地å€å±¬æ–¼è¡Œçˆ²æº–則委員會。https://kernel.org/code-of-conduct.html
列出了在任何給定時間接收這些電å­éƒµä»¶çš„確切æˆå“¡ã€‚æˆå“¡ä¸èƒ½è¨ªå•在加入委員會之å‰
或離開委員會之後所åšçš„報告。
-最åˆçš„行為準則委員會由TAB的志願者以åŠä½œçˆ²ä¸­ç«‹ç¬¬ä¸‰æ–¹çš„專業調解人組æˆã€‚委員會
+最åˆçš„行爲準則委員會由TAB的志願者以åŠä½œçˆ²ä¸­ç«‹ç¬¬ä¸‰æ–¹çš„專業調解人組æˆã€‚委員會
的首è¦ä»»å‹™æ˜¯å»ºç«‹æ–‡ä»¶åŒ–çš„æµç¨‹ï¼Œä¸¦å°‡å…¶å…¬é–‹ã€‚
如果報告人ä¸å¸Œæœ›å°‡æ•´å€‹å§”員會ç´å…¥æŠ•訴或關切,å¯ç›´æŽ¥è¯ç¹«å§”員會的任何æˆå“¡ï¼ŒåŒ…括
調解人。
-行為準則委員會根據æµç¨‹å¯©æŸ¥æ¡ˆä¾‹ï¼ˆè¦‹ä¸Šæ–‡ï¼‰ï¼Œä¸¦æ ¹æ“šéœ€è¦å’Œé©ç•¶èˆ‡TABå”商,例如請求
+行爲準則委員會根據æµç¨‹å¯©æŸ¥æ¡ˆä¾‹ï¼ˆè¦‹ä¸Šæ–‡ï¼‰ï¼Œä¸¦æ ¹æ“šéœ€è¦å’Œé©ç•¶èˆ‡TABå”商,例如請求
和接收有關內核社å€çš„ä¿¡æ¯ã€‚
委員會åšå‡ºçš„任何決定都將æäº¤åˆ°è¡¨ä¸­ï¼Œä»¥ä¾¿åœ¨å¿…è¦æ™‚與相關維護人員一起執行。行爲
準則委員會的決定å¯ä»¥é€šéŽä¸‰åˆ†ä¹‹äºŒçš„æŠ•票推翻。
-æ¯å­£åº¦ï¼Œè¡Œç‚ºæº–則委員會和標籤將æä¾›ä¸€ä»½å ±å‘Šï¼Œæ¦‚述行為準則委員會收到的匿å報告
+æ¯å­£åº¦ï¼Œè¡Œçˆ²æº–則委員會和標籤將æä¾›ä¸€ä»½å ±å‘Šï¼Œæ¦‚述行爲準則委員會收到的匿å報告
åŠå…¶ç‹€æ…‹ï¼Œä»¥åŠä»»ä½•妿±ºæ±ºå®šçš„細節,包括完整和å¯è­˜åˆ¥çš„æŠ•票細節。
-我們希望在啓動期之後爲行為準則委員會人員é…備建立一個ä¸åŒçš„æµç¨‹ã€‚ç™¼ç”Ÿæ­¤æƒ…æ³æ™‚,
+我們希望在啓動期之後爲行爲準則委員會人員é…備建立一個ä¸åŒçš„æµç¨‹ã€‚ç™¼ç”Ÿæ­¤æƒ…æ³æ™‚,
å°‡ä½¿ç”¨è©²ä¿¡æ¯æ›´æ–°æ­¤æ–‡æª”。
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct.rst b/Documentation/translations/zh_TW/process/code-of-conduct.rst
index e3087112f0bc..a7a31de03526 100644
--- a/Documentation/translations/zh_TW/process/code-of-conduct.rst
+++ b/Documentation/translations/zh_TW/process/code-of-conduct.rst
@@ -8,7 +8,7 @@
.. _tw_code_of_conduct:
-è²¢ç»è€…契約行為準則
+è²¢ç»è€…契約行爲準則
++++++++++++++++++
我們的誓言
@@ -35,7 +35,7 @@
* 使用性æ„味的語言或æ„象以åŠä¸å—æ­¡è¿Žçš„æ€§æ³¨æ„æˆ–者更éŽåˆ†çš„行爲
* 煽動ã€ä¾®è¾±/è²¶æè©•論以åŠå€‹äººæˆ–政治攻擊
* 公開或ç§ä¸‹é¨·æ“¾
-* 未經明確許å¯ï¼Œç™¼å¸ƒä»–人的ç§äººä¿¡æ¯ï¼Œå¦‚ç‰©ç†æˆ–é›»å­åœ°å€ã€‚
+* 未經明確許å¯ï¼Œç™¼ä½ˆä»–人的ç§äººä¿¡æ¯ï¼Œå¦‚ç‰©ç†æˆ–é›»å­åœ°å€ã€‚
* 在專業場åˆè¢«åˆç†èªçˆ²ä¸é©ç•¶çš„其他行爲
我們的責任
@@ -44,29 +44,29 @@
ç¶­è­·äººå“¡è² è²¬æ¾„æ¸…å¯æŽ¥å—行爲的標準,並應é‡å°ä»»ä½•ä¸å¯æŽ¥å—行爲採å–é©ç•¶å’Œå…¬å¹³çš„
糾正措施。
-維護人員有權和責任刪除ã€ç·¨è¼¯æˆ–拒絕與本行為準則ä¸ä¸€è‡´çš„è©•è«–ã€æ‰¿è«¾ã€ä»£ç¢¼ã€
+維護人員有權和責任刪除ã€ç·¨è¼¯æˆ–拒絕與本行爲準則ä¸ä¸€è‡´çš„è©•è«–ã€æ‰¿è«¾ã€ä»£ç¢¼ã€
wiki編輯ã€å•題和其他貢ç»ï¼Œæˆ–æš«æ™‚æˆ–æ°¸ä¹…ç¦æ­¢ä»»ä½•è²¢ç»è€…從事他們èªçˆ²ä¸é©ç•¶ã€
å¨è„…ã€å†’犯或有害的其他行爲。
範åœ
====
-ç•¶å€‹äººä»£è¡¨é …ç›®æˆ–å…¶ç¤¾å€æ™‚,本行為準則既é©ç”¨æ–¼é …目空間,也é©ç”¨æ–¼å…¬å…±ç©ºé–“。
+ç•¶å€‹äººä»£è¡¨é …ç›®æˆ–å…¶ç¤¾å€æ™‚,本行爲準則既é©ç”¨æ–¼é …目空間,也é©ç”¨æ–¼å…¬å…±ç©ºé–“。
代表一個項目或社å€çš„例å­åŒ…括使用一個正å¼çš„項目電å­éƒµä»¶åœ°å€ï¼Œé€šéŽä¸€å€‹æ­£å¼
-的社交媒體帳戶發布,或者在在線或離線事件中擔任指定的代表。項目維護人員å¯ä»¥
+的社交媒體帳戶發佈,或者在在線或離線事件中擔任指定的代表。項目維護人員å¯ä»¥
進一步定義和澄清項目的表示。
執行
====
-如有濫用ã€é¨·æ“¾æˆ–å…¶ä»–ä¸å¯æŽ¥å—的行爲,å¯è¯ç¹«è¡Œç‚ºæº–則委員會<conduct@kernel.org>。
-所有投訴都將接å—審查和調查,並將得到必è¦å’Œé©ç•¶çš„答覆。行為準則委員會有義務
-å°äº‹ä»¶å ±å‘Šäººä¿å¯†ã€‚具體執行政策的進一步細節å¯å–®ç¨å…¬å¸ƒã€‚
+如有濫用ã€é¨·æ“¾æˆ–å…¶ä»–ä¸å¯æŽ¥å—的行爲,å¯è¯ç¹«è¡Œçˆ²æº–則委員會<conduct@kernel.org>。
+所有投訴都將接å—審查和調查,並將得到必è¦å’Œé©ç•¶çš„答覆。行爲準則委員會有義務
+å°äº‹ä»¶å ±å‘Šäººä¿å¯†ã€‚具體執行政策的進一步細節å¯å–®ç¨å…¬ä½ˆã€‚
歸屬
====
-本行為準則改編自《貢ç»è€…契約》,版本1.4,å¯å¾ž
+本行爲準則改編自《貢ç»è€…契約》,版本1.4,å¯å¾ž
https://www.contributor-covenant.org/version/1/4/code-of-conduct.html ç²å–。
解釋
diff --git a/Documentation/translations/zh_TW/process/coding-style.rst b/Documentation/translations/zh_TW/process/coding-style.rst
index 83862e4d3b64..5749363de421 100644
--- a/Documentation/translations/zh_TW/process/coding-style.rst
+++ b/Documentation/translations/zh_TW/process/coding-style.rst
@@ -2,42 +2,44 @@
.. include:: ../disclaimer-zh_TW.rst
-:Original: :ref:`Documentation/process/coding-style.rst <codingstyle>`
+:Original: Documentation/process/coding-style.rst
.. _tw_codingstyle:
-譯者::
+:譯者:
+ - 張樂 Zhang Le <r0bertz@gentoo.org>
+ - Andy Deng <theandy.deng@gmail.com>
+ - 峿ƒ³æˆ <bobwxc@email.cn>
- 中文版維護者: 張樂 Zhang Le <r0bertz@gentoo.org>
- 中文版翻譯者: 張樂 Zhang Le <r0bertz@gentoo.org>
- 中文版校譯者: çŽ‹è° Wang Cong <xiyou.wangcong@gmail.com>
- wheelz <kernel.zeng@gmail.com>
- ç®¡æ—­æ± Xudong Guan <xudong.guan@gmail.com>
- Li Zefan <lizf@cn.fujitsu.com>
- Wang Chen <wangchen@cn.fujitsu.com>
- Hu Haowen <src.res.211@gmail.com>
+:æ ¡è­¯:
+ - çŽ‹è° Wang Cong <xiyou.wangcong@gmail.com>
+ - wheelz <kernel.zeng@gmail.com>
+ - ç®¡æ—­æ± Xudong Guan <xudong.guan@gmail.com>
+ - Li Zefan <lizf@cn.fujitsu.com>
+ - Wang Chen <wangchen@cn.fujitsu.com>
+ - Hu Haowen <src.res.211@gmail.com>
Linux 內核代碼風格
-=========================
+==================
這是一個簡短的文檔,æè¿°äº† linux 內核的首é¸ä»£ç¢¼é¢¨æ ¼ã€‚代碼風格是因人而異的,
而且我ä¸é¡˜æ„æŠŠè‡ªå·±çš„è§€é»žå¼·åŠ çµ¦ä»»ä½•äººï¼Œä½†é€™å°±åƒæˆ‘去åšä»»ä½•事情都必須éµå¾ªçš„原則
-é‚£æ¨£ï¼Œæˆ‘ä¹Ÿå¸Œæœ›åœ¨çµ•å¤§å¤šæ•¸äº‹ä¸Šä¿æŒé€™ç¨®çš„æ…‹åº¦ã€‚è«‹ (在寫代碼時) 至少考慮一下這裡
+é‚£æ¨£ï¼Œæˆ‘ä¹Ÿå¸Œæœ›åœ¨çµ•å¤§å¤šæ•¸äº‹ä¸Šä¿æŒé€™ç¨®çš„æ…‹åº¦ã€‚è«‹ (在寫代碼時) 至少考慮一下這è£
的代碼風格。
-首先,我建議你列å°ä¸€ä»½ GNU 代碼è¦ç¯„,然後ä¸è¦è®€ã€‚燒了它,這是一個具有é‡å¤§è±¡å¾µ
+首先,我建議你打å°ä¸€ä»½ GNU 代碼è¦ç¯„,然後ä¸è¦è®€ã€‚燒了它,這是一個具有é‡å¤§è±¡å¾µ
性æ„義的動作。
ä¸ç®¡æ€Žæ¨£ï¼Œç¾åœ¨æˆ‘們開始:
1) 縮進
---------------
+-------
-制表符是 8 個字符,所以縮進也是 8 個字符。有些異端é‹å‹•試圖將縮進變爲 4 (甚至
+製表符是 8 個字符,所以縮進也是 8 個字符。有些異端é‹å‹•試圖將縮進變爲 4 (甚至
2ï¼) 字符深,這幾乎相當於嘗試將圓周率的值定義爲 3。
-ç†ç”±ï¼šç¸®é€²çš„全部æ„義就在於清楚的定義一個控制塊起止於何處。尤其是當你盯著你的
+ç†ç”±ï¼šç¸®é€²çš„全部æ„義就在於清楚的定義一個控制塊起止於何處。尤其是當你盯ç€ä½ çš„
å±å¹•連續看了 20 å°æ™‚之後,你將會發ç¾å¤§ä¸€é»žçš„縮進會使你更容易分辨縮進。
ç¾åœ¨ï¼Œæœ‰äº›äººæœƒæŠ±æ€¨ 8 個字符的縮進會使代碼å‘å³é‚Šç§»å‹•的太é ï¼Œåœ¨ 80 個字符的終端
@@ -69,39 +71,60 @@ Linux 內核代碼風格
break;
}
-ä¸è¦æŠŠå¤šå€‹èªžå¥æ”¾åœ¨ä¸€è¡Œé‡Œï¼Œé™¤éžä½ æœ‰ä»€éº¼æ±è¥¿è¦éš±è—:
+ä¸è¦æŠŠå¤šå€‹èªžå¥æ”¾åœ¨ä¸€è¡Œè£ï¼Œé™¤éžä½ æœ‰ä»€éº¼æ±è¥¿è¦éš±è—:
.. code-block:: c
if (condition) do_this;
do_something_everytime;
-也ä¸è¦åœ¨ä¸€è¡Œé‡Œæ”¾å¤šå€‹è³¦å€¼èªžå¥ã€‚內核代碼風格超級簡單。就是é¿å…å¯èƒ½å°Žè‡´åˆ¥äººèª¤è®€
+ä¸è¦ä½¿ç”¨é€—號來é¿å…使用大括號:
+
+.. code-block:: c
+
+ if (condition)
+ do_this(), do_that();
+
+使用大括號包裹多語å¥ï¼š
+
+.. code-block:: c
+
+ if (condition) {
+ do_this();
+ do_that();
+ }
+
+也ä¸è¦åœ¨ä¸€è¡Œè£æ”¾å¤šå€‹è³¦å€¼èªžå¥ã€‚內核代碼風格超級簡單。就是é¿å…å¯èƒ½å°Žè‡´åˆ¥äººèª¤è®€
的表é”å¼ã€‚
-é™¤äº†æ³¨é‡‹ã€æ–‡æª”å’Œ Kconfig 之外,ä¸è¦ä½¿ç”¨ç©ºæ ¼ä¾†ç¸®é€²ï¼Œå‰é¢çš„例孿˜¯ä¾‹å¤–,是有æ„爲
+é™¤äº†è¨»é‡‹ã€æ–‡æª”å’Œ Kconfig 之外,ä¸è¦ä½¿ç”¨ç©ºæ ¼ä¾†ç¸®é€²ï¼Œå‰é¢çš„例孿˜¯ä¾‹å¤–,是有æ„爲
之。
é¸ç”¨ä¸€å€‹å¥½çš„編輯器,ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºæ ¼ã€‚
2) 把長的行和字符串打散
-------------------------------
+-----------------------
代碼風格的æ„義就在於使用平常使用的工具來維æŒä»£ç¢¼çš„å¯è®€æ€§å’Œå¯ç¶­è­·æ€§ã€‚
æ¯ä¸€è¡Œçš„長度的é™åˆ¶æ˜¯ 80 列,我們強烈建議您éµå®ˆé€™å€‹æ…£ä¾‹ã€‚
é•·æ–¼ 80 列的語å¥è¦æ‰“æ•£æˆæœ‰æ„義的片段。除éžè¶…éŽ 80 列能顯著增加å¯è®€æ€§ï¼Œä¸¦ä¸”ä¸
-會隱è—ä¿¡æ¯ã€‚å­ç‰‡æ®µè¦æ˜Žé¡¯çŸ­æ–¼æ¯ç‰‡æ®µï¼Œä¸¦æ˜Žé¡¯é å³ã€‚é€™åŒæ¨£é©ç”¨æ–¼æœ‰è‘—å¾ˆé•·åƒæ•¸åˆ—表
-的函數頭。然而,絕å°ä¸è¦æ‰“æ•£å°ç”¨æˆ¶å¯è¦‹çš„字符串,例如 printk ä¿¡æ¯ï¼Œå› çˆ²é€™æ¨£å°±
+會隱è—ä¿¡æ¯ã€‚
+
+å­ç‰‡æ®µè¦æ˜Žé¡¯çŸ­æ–¼æ¯ç‰‡æ®µï¼Œä¸¦æ˜Žé¡¯é å³ã€‚一種éžå¸¸å¸¸ç”¨çš„æ¨£å¼æ˜¯å°‡å­é«”與函數左括號å°é½Šã€‚
+
+é€™åŒæ¨£é©ç”¨æ–¼æœ‰ç€å¾ˆé•·åƒæ•¸åˆ—表的函數頭。
+
+然而,絕å°ä¸è¦æ‰“æ•£å°ç”¨æˆ¶å¯è¦‹çš„字符串,例如 printk ä¿¡æ¯ï¼Œå› çˆ²é€™æ¨£å°±
很難å°å®ƒå€‘ grep。
3) 大括號和空格的放置
-------------------------------
+---------------------
-C 語言風格中å¦å¤–一個常見å•題是大括號的放置。和縮進大å°ä¸åŒï¼Œé¸æ“‡æˆ–棄用æŸç§æ”¾
+C 語言風格中å¦å¤–一個常見å•題是大括號的放置。和縮進大å°ä¸åŒï¼Œé¸æ“‡æˆ–棄用æŸç¨®æ”¾
置策略並沒有多少技術上的原因,ä¸éŽé¦–é¸çš„æ–¹å¼ï¼Œå°±åƒ Kernighan å’Œ Ritchie 展示
çµ¦æˆ‘å€‘çš„ï¼Œæ˜¯æŠŠèµ·å§‹å¤§æ‹¬è™Ÿæ”¾åœ¨è¡Œå°¾ï¼Œè€ŒæŠŠçµæŸå¤§æ‹¬è™Ÿæ”¾åœ¨è¡Œé¦–,所以:
@@ -135,12 +158,12 @@ C 語言風格中å¦å¤–一個常見å•題是大括號的放置。和縮進大å°
body of function
}
-全世界的異端å¯èƒ½æœƒæŠ±æ€¨é€™å€‹ä¸ä¸€è‡´æ€§æ˜¯... 呃... ä¸ä¸€è‡´çš„,ä¸éŽæ‰€æœ‰æ€ç¶­å¥å…¨çš„人
+全世界的異端å¯èƒ½æœƒæŠ±æ€¨é€™å€‹ä¸ä¸€è‡´æ€§æ˜¯â€¦â€¦å‘ƒâ€¦â€¦ä¸ä¸€è‡´ï¼Œä¸éŽæ‰€æœ‰æ€ç¶­å¥å…¨çš„人
éƒ½çŸ¥é“ (a) K&R 是 **正確的** 並且 (b) K&R 是正確的。此外,ä¸ç®¡æ€Žæ¨£å‡½æ•¸éƒ½æ˜¯ç‰¹
殊的 (C 函數是ä¸èƒ½åµŒå¥—çš„)。
-注æ„çµæŸå¤§æ‹¬è™Ÿç¨è‡ªå æ“šä¸€è¡Œï¼Œé™¤éžå®ƒå¾Œé¢è·Ÿè‘—åŒä¸€å€‹èªžå¥çš„剩餘部分,也就是 do 語
-å¥ä¸­çš„ "while" 或者 if 語å¥ä¸­çš„ "else",åƒé€™æ¨£ï¼š
+注æ„çµæŸå¤§æ‹¬è™Ÿç¨è‡ªä½”據一行,除éžå®ƒå¾Œé¢è·Ÿç€åŒä¸€å€‹èªžå¥çš„剩餘部分,也就是 do 語
+å¥ä¸­çš„ ``while`` 或者 if 語å¥ä¸­çš„ ``else`` ,åƒé€™æ¨£ï¼š
.. code-block:: c
@@ -164,7 +187,7 @@ C 語言風格中å¦å¤–一個常見å•題是大括號的放置。和縮進大å°
也請注æ„這種大括號的放置方å¼ä¹Ÿèƒ½ä½¿ç©º (或者差ä¸å¤šç©ºçš„) è¡Œçš„æ•¸é‡æœ€å°åŒ–ï¼ŒåŒæ™‚ä¸
失å¯è®€æ€§ã€‚因此,由於你的å±å¹•上的新行是ä¸å¯å†ç”Ÿè³‡æº (想想 25 行的終端å±å¹•),你
-將會有更多的空行來放置注釋。
+將會有更多的空行來放置註釋。
ç•¶åªæœ‰ä¸€å€‹å–®ç¨çš„語å¥çš„æ™‚候,ä¸ç”¨åŠ ä¸å¿…è¦çš„大括號。
@@ -194,12 +217,12 @@ C 語言風格中å¦å¤–一個常見å•題是大括號的放置。和縮進大å°
}
3.1) 空格
-********************
+*********
Linux å…§æ ¸çš„ç©ºæ ¼ä½¿ç”¨æ–¹å¼ (主è¦) å–æ±ºæ–¼å®ƒæ˜¯ç”¨æ–¼å‡½æ•¸é‚„是關éµå­—。(大多數) é—œéµå­—
後è¦åŠ ä¸€å€‹ç©ºæ ¼ã€‚å€¼å¾—æ³¨æ„的例外是 sizeof, typeof, alignof å’Œ __attribute__,這
-些關éµå­—æŸäº›ç¨‹åº¦ä¸Šçœ‹èµ·ä¾†æ›´åƒå‡½æ•¸ (它們在 Linux é‡Œä¹Ÿå¸¸å¸¸ä¼´éš¨å°æ‹¬è™Ÿè€Œä½¿ç”¨ï¼Œå„˜ç®¡
-在 C é‡Œé€™æ¨£çš„å°æ‹¬è™Ÿä¸æ˜¯å¿…éœ€çš„ï¼Œå°±åƒ ``struct fileinfo info;`` è²æ˜ŽéŽå¾Œçš„
+些關éµå­—æŸäº›ç¨‹åº¦ä¸Šçœ‹èµ·ä¾†æ›´åƒå‡½æ•¸ (它們在 Linux è£ä¹Ÿå¸¸å¸¸ä¼´éš¨å°æ‹¬è™Ÿè€Œä½¿ç”¨ï¼Œå„˜ç®¡
+在 C è£é€™æ¨£çš„å°æ‹¬è™Ÿä¸æ˜¯å¿…éœ€çš„ï¼Œå°±åƒ ``struct fileinfo info;`` è²æ˜ŽéŽå¾Œçš„
``sizeof info``)。
所以在這些關éµå­—之後放一個空格::
@@ -213,7 +236,7 @@ Linux å…§æ ¸çš„ç©ºæ ¼ä½¿ç”¨æ–¹å¼ (主è¦) å–æ±ºæ–¼å®ƒæ˜¯ç”¨æ–¼å‡½æ•¸é‚„是關é
s = sizeof(struct file);
-ä¸è¦åœ¨å°æ‹¬è™Ÿé‡Œçš„表é”å¼å…©å´åŠ ç©ºæ ¼ã€‚é€™æ˜¯ä¸€å€‹ **å例** :
+ä¸è¦åœ¨å°æ‹¬è™Ÿè£çš„表é”å¼å…©å´åŠ ç©ºæ ¼ã€‚é€™æ˜¯ä¸€å€‹ **å例** :
.. code-block:: c
@@ -257,10 +280,10 @@ Linux å…§æ ¸çš„ç©ºæ ¼ä½¿ç”¨æ–¹å¼ (主è¦) å–æ±ºæ–¼å®ƒæ˜¯ç”¨æ–¼å‡½æ•¸é‚„是關é
4) 命å
-------------------------------
+-------
-C 是一個簡樸的語言,你的命å也應該這樣。和 Modula-2 å’Œ Pascal 程å¼è¨­è¨ˆå¸«ä¸åŒï¼Œ
-C 程å¼è¨­è¨ˆå¸«ä¸ä½¿ç”¨é¡žä¼¼ ThisVariableIsATemporaryCounter 這樣è¯éº—çš„å字。C 程å¼è¨­è¨ˆå¸«æœƒ
+C 是一個簡樸的語言,你的命å也應該這樣。和 Modula-2 å’Œ Pascal 程åºå“¡ä¸åŒï¼Œ
+C 程åºå“¡ä¸ä½¿ç”¨é¡žä¼¼ ThisVariableIsATemporaryCounter 這樣è¯éº—çš„å字。C 程åºå“¡æœƒ
稱那個變é‡çˆ² ``tmp`` ï¼Œé€™æ¨£å¯«èµ·ä¾†æœƒæ›´å®¹æ˜“ï¼Œè€Œä¸”è‡³å°‘ä¸æœƒä»¤å…¶é›£æ–¼ç†è§£ã€‚
ä¸éŽï¼Œé›–然混用大å°å¯«çš„åå­—æ˜¯ä¸æå€¡ä½¿ç”¨çš„ï¼Œä½†æ˜¯å…¨å±€è®Šé‡é‚„是需è¦ä¸€å€‹å…·æè¿°æ€§çš„
@@ -271,23 +294,42 @@ C 程å¼è¨­è¨ˆå¸«ä¸ä½¿ç”¨é¡žä¼¼ ThisVariableIsATemporaryCounter 這樣è¯éº—çš„
``count_active_users()`` 或者類似的åå­—ï¼Œä½ ä¸æ‡‰è©²å«å®ƒ ``cntuser()`` 。
在函數å中包å«å‡½æ•¸é¡žåž‹ (æ‰€è¬‚çš„åŒˆç‰™åˆ©å‘½åæ³•) 是腦å­å‡ºäº†å•題——編譯器知é“那些類
-型而且能夠檢查那些類型,這樣åšåªèƒ½æŠŠç¨‹å¼è¨­è¨ˆå¸«å¼„糊塗了。難怪微軟總是製造出有å•題
-的程åºã€‚
+型而且能夠檢查那些類型,這樣åšåªèƒ½æŠŠç¨‹åºå“¡å¼„糊塗了。
本地變é‡å應該簡短,而且能夠表é”相關的å«ç¾©ã€‚如果你有一些隨機的整數型的循環計
數器,它應該被稱爲 ``i`` 。å«å®ƒ ``loop_counter`` 並無益處,如果它沒有被誤解的
å¯èƒ½çš„話。類似的, ``tmp`` å¯ä»¥ç”¨ä¾†ç¨±å‘¼ä»»æ„類型的臨時變é‡ã€‚
如果你怕混淆了你的本地變é‡å,你就é‡åˆ°å¦ä¸€å€‹å•題了,å«åšå‡½æ•¸å¢žé•·è·çˆ¾è’™å¤±è¡¡ç¶œ
-åˆç—‡ã€‚請看第六章 (函數)。
+åˆå¾µã€‚請看第六章 (函數)。
+å°æ–¼ç¬¦è™Ÿå稱和文檔,é¿å…引入新的“master/slaveâ€ï¼ˆæˆ–ç¨ç«‹æ–¼â€œmasterâ€çš„“slaveâ€ï¼‰
+和“blacklist/whitelistâ€ã€‚
+
+“master/slaveâ€æŽ¨è–¦æ›¿æ›çˆ²ï¼š
+ '{primary,main} / {secondary,replica,subordinate}'
+ '{initiator,requester} / {target,responder}'
+ '{controller,host} / {device,worker,proxy}'
+ 'leader/follower'
+ 'director/performer'
+
+“blacklist/whitelistâ€æŽ¨è–¦æ›¿æ›çˆ²ï¼š
+ 'denylist/allowlist'
+ 'blocklist/passlist'
+
+å¼•å…¥æ–°ç”¨æ³•çš„ä¾‹å¤–æƒ…æ³æ˜¯ï¼šç¶­è­·ç”¨æˆ¶ç©ºé–“ABI/APIï¼Œæˆ–æ›´æ–°ç¾æœ‰ï¼ˆæˆªè‡³2020年)硬件或
+å”è­°è¦ç¯„çš„ä»£ç¢¼æ™‚è¦æ±‚é€™äº›è¡“èªžã€‚å°æ–¼æ–°è¦ç¯„,儘å¯èƒ½å°‡è¡“語的è¦ç¯„用法轉æ›çˆ²å…§æ ¸
+編碼標準。
+
+.. warning::
+ 以上主從ã€é»‘白åå–®è¦å‰‡ä¸é©ç”¨æ–¼ä¸­æ–‡æ–‡æª”,請勿更改中文術語ï¼
5) Typedef
------------
+----------
ä¸è¦ä½¿ç”¨é¡žä¼¼ ``vps_t`` 之類的æ±è¥¿ã€‚
-å°çµæ§‹é«”和指é‡ä½¿ç”¨ typedef 是一個 **錯誤** 。當你在代碼里看到:
+å°çµæ§‹é«”和指é‡ä½¿ç”¨ typedef 是一個 **錯誤** 。當你在代碼è£çœ‹åˆ°ï¼š
.. code-block:: c
@@ -312,13 +354,13 @@ C 程å¼è¨­è¨ˆå¸«ä¸ä½¿ç”¨é¡žä¼¼ ThisVariableIsATemporaryCounter 這樣è¯éº—çš„
.. note::
- ä¸é€æ˜Žæ€§å’Œ "訪å•函數" 本身是ä¸å¥½çš„。我們使用 pte_t 等類型的原因在於真
+ ä¸é€æ˜Žæ€§å’Œâ€œè¨ªå•å‡½æ•¸â€æœ¬èº«æ˜¯ä¸å¥½çš„。我們使用 pte_t 等類型的原因在於真
的是完全沒有任何共用的å¯è¨ªå•ä¿¡æ¯ã€‚
(b) 清楚的整數類型,如此,這層抽象就å¯ä»¥ **幫助** 消除到底是 ``int`` 還是
``long`` 的混淆。
- u8/u16/u32 是完全沒有å•題的 typedef,ä¸éŽå®ƒå€‘更符åˆé¡žåˆ¥ (d) è€Œä¸æ˜¯é€™è£¡ã€‚
+ u8/u16/u32 是完全沒有å•題的 typedef,ä¸éŽå®ƒå€‘更符åˆé¡žåˆ¥ (d) è€Œä¸æ˜¯é€™è£ã€‚
.. note::
@@ -345,30 +387,30 @@ C 程å¼è¨­è¨ˆå¸«ä¸ä½¿ç”¨é¡žä¼¼ ThisVariableIsATemporaryCounter 這樣è¯éº—çš„
(e) å¯ä»¥åœ¨ç”¨æˆ¶ç©ºé–“安全使用的類型。
- 在æŸäº›ç”¨æˆ¶ç©ºé–“å¯è¦‹çš„çµæ§‹é«”裡,我們ä¸èƒ½è¦æ±‚ C99 類型而且ä¸èƒ½ç”¨ä¸Šé¢æåˆ°çš„
+ 在æŸäº›ç”¨æˆ¶ç©ºé–“å¯è¦‹çš„çµæ§‹é«”è£ï¼Œæˆ‘們ä¸èƒ½è¦æ±‚ C99 類型而且ä¸èƒ½ç”¨ä¸Šé¢æåˆ°çš„
``u32`` é¡žåž‹ã€‚å› æ­¤ï¼Œæˆ‘å€‘åœ¨èˆ‡ç”¨æˆ¶ç©ºé–“å…±äº«çš„æ‰€æœ‰çµæ§‹é«”中使用 __u32 和類似
的類型。
å¯èƒ½é‚„有其他的情æ³ï¼Œä¸éŽåŸºæœ¬çš„è¦å‰‡æ˜¯ **æ°¸é ä¸è¦** 使用 typedef,除éžä½ å¯ä»¥æ˜Ž
確的應用上述æŸå€‹è¦å‰‡ä¸­çš„一個。
-ç¸½çš„ä¾†èªªï¼Œå¦‚æžœä¸€å€‹æŒ‡é‡æˆ–è€…ä¸€å€‹çµæ§‹é«”裡的元素å¯ä»¥åˆç†çš„被直接訪å•到,那麼它們
+ç¸½çš„ä¾†èªªï¼Œå¦‚æžœä¸€å€‹æŒ‡é‡æˆ–è€…ä¸€å€‹çµæ§‹é«”è£çš„元素å¯ä»¥åˆç†çš„被直接訪å•到,那麼它們
就䏿‡‰è©²æ˜¯ä¸€å€‹ typedef。
6) 函數
-------------------------------
+-------
函數應該簡短而漂亮,並且åªå®Œæˆä¸€ä»¶äº‹æƒ…。函數應該å¯ä»¥ä¸€å±æˆ–者兩å±é¡¯ç¤ºå®Œ (我們
éƒ½çŸ¥é“ ISO/ANSI å±å¹•大尿˜¯ 80x24),åªåšä¸€ä»¶äº‹æƒ…,而且把它åšå¥½ã€‚
一個函數的最大長度是和該函數的複雜度和縮進級數æˆå比的。所以,如果你有一個ç†
è«–ä¸Šå¾ˆç°¡å–®çš„åªæœ‰ä¸€å€‹å¾ˆé•· (但是簡單) çš„ case 語å¥çš„函數,而且你需è¦åœ¨æ¯å€‹ case
-里åšå¾ˆå¤šå¾ˆå°çš„事情,這樣的函數儘管很長,但也是å¯ä»¥çš„。
+è£åšå¾ˆå¤šå¾ˆå°çš„事情,這樣的函數儘管很長,但也是å¯ä»¥çš„。
ä¸éŽï¼Œå¦‚æžœä½ æœ‰ä¸€å€‹è¤‡é›œçš„å‡½æ•¸ï¼Œè€Œä¸”ä½ æ‡·ç–‘ä¸€å€‹å¤©åˆ†ä¸æ˜¯å¾ˆé«˜çš„高中一年級學生å¯èƒ½
甚至æžä¸æ¸…楚這個函數的目的,你應該嚴格éµå®ˆå‰é¢æåˆ°çš„長度é™åˆ¶ã€‚使用輔助函數,
-並爲之å–個具æè¿°æ€§çš„åå­— (如果你覺得它們的性能很é‡è¦çš„話,å¯ä»¥è®“編譯器內è¯å®ƒ
+併爲之å–個具æè¿°æ€§çš„åå­— (如果你覺得它們的性能很é‡è¦çš„話,å¯ä»¥è®“編譯器內è¯å®ƒ
們,這樣的效果往往會比你寫一個複雜函數的效果è¦å¥½ã€‚)
函數的å¦å¤–ä¸€å€‹è¡¡é‡æ¨™æº–是本地變é‡çš„æ•¸é‡ã€‚此數é‡ä¸æ‡‰è¶…éŽ 5ï¼10 個,å¦å‰‡ä½ çš„函數
@@ -376,7 +418,7 @@ C 程å¼è¨­è¨ˆå¸«ä¸ä½¿ç”¨é¡žä¼¼ ThisVariableIsATemporaryCounter 這樣è¯éº—çš„
çš„åŒæ™‚跟蹤 7 個ä¸åŒçš„事物,如果å†å¢žå¤šçš„話,就會糊塗了。å³ä¾¿ä½ è°ç©ŽéŽäººï¼Œä½ ä¹Ÿå¯
èƒ½æœƒè¨˜ä¸æ¸…ä½  2 個星期å‰åšéŽçš„事情。
-åœ¨æºæ–‡ä»¶é‡Œï¼Œä½¿ç”¨ç©ºè¡Œéš”é–‹ä¸åŒçš„函數。如果該函數需è¦è¢«å°Žå‡ºï¼Œå®ƒçš„ **EXPORT** å®
+åœ¨æºæ–‡ä»¶è£ï¼Œä½¿ç”¨ç©ºè¡Œéš”é–‹ä¸åŒçš„函數。如果該函數需è¦è¢«å°Žå‡ºï¼Œå®ƒçš„ **EXPORT** å®
æ‡‰è©²ç·Šè²¼åœ¨å®ƒçš„çµæŸå¤§æ‹¬è™Ÿä¹‹ä¸‹ã€‚比如:
.. code-block:: c
@@ -387,12 +429,46 @@ C 程å¼è¨­è¨ˆå¸«ä¸ä½¿ç”¨é¡žä¼¼ ThisVariableIsATemporaryCounter 這樣è¯éº—çš„
}
EXPORT_SYMBOL(system_is_up);
-在函數原型中,包å«å‡½æ•¸å和它們的數據類型。雖然 C èªžè¨€è£¡æ²’æœ‰é€™æ¨£çš„è¦æ±‚,在
-Linux 里這是æå€¡çš„åšæ³•,因爲這樣å¯ä»¥å¾ˆç°¡å–®çš„給讀者æä¾›æ›´å¤šçš„æœ‰åƒ¹å€¼çš„ä¿¡æ¯ã€‚
+6.1) 函數原型
+*************
+
+在函數原型中包å«åƒæ•¸å和它們的數據類型。雖然 C èªžè¨€è£æ²’æœ‰é€™æ¨£çš„è¦æ±‚,但在
+Linux è£é€™æ˜¯æå€¡çš„åšæ³•,因爲這樣å¯ä»¥å¾ˆç°¡å–®çš„給讀者æä¾›æ›´å¤šçš„æœ‰åƒ¹å€¼çš„ä¿¡æ¯ã€‚
+ä¸è¦åœ¨å‡½æ•¸è²æ˜Žè£ä½¿ç”¨ ``extern`` é—œéµå­—ï¼Œå› çˆ²é€™æœƒå°Žè‡´ä»£ç¢¼è¡Œè®Šé•·ï¼Œä¸¦ä¸”ä¸æ˜¯åš´æ ¼
+必需的。
+
+å¯«å‡½æ•¸åŽŸåž‹æ™‚ï¼Œè«‹ä¿æŒ `元素順åºè¦å‰‡ <https://lore.kernel.org/mm-commits/CAHk-=wiOCLRny5aifWNhr621kYrJwhfURsa0vFPeUEm8mF0ufg@mail.gmail.com/>`_ 。
+ä¾‹å¦‚ä¸‹åˆ—å‡½æ•¸è²æ˜Ž::
+
+ __init void * __must_check action(enum magic value, size_t size, u8 count,
+ char *fmt, ...) __printf(4, 5) __malloc;
+
+æŽ¨è–¦çš„å‡½æ•¸åŽŸåž‹å…ƒç´ é †åºæ˜¯ï¼š
+
+- 儲存類型(下方的 ``static __always_inline`` ï¼Œæ³¨æ„ ``__always_inline``
+ æŠ€è¡“ä¸Šä¾†è¬›æ˜¯å€‹å±¬æ€§ä½†è¢«ç•¶åš ``inline`` )
+- 儲存類型屬性(上方的 ``__init`` ——å³ç¯€è²æ˜Žï¼Œä½†ä¹Ÿåƒ ``__cold`` )
+- 返回類型(上方的 ``void *`` )
+- 返回類型屬性(上方的 ``__must_check`` )
+- 函數å(上方的 ``action`` )
+- å‡½æ•¸åƒæ•¸ï¼ˆä¸Šæ–¹çš„ ``(enum magic value, size_t size, u8 count, char *fmt, ...)`` ,
+ 注æ„å¿…é ˆå¯«ä¸Šåƒæ•¸å)
+- å‡½æ•¸åƒæ•¸å±¬æ€§ï¼ˆä¸Šæ–¹çš„ ``__printf(4, 5)`` )
+- 函數行爲屬性(上方的 ``__malloc`` )
+
+請注æ„ï¼Œå°æ–¼å‡½æ•¸ **定義** (å³å¯¦éš›å‡½æ•¸é«”),編譯器ä¸å…è¨±åœ¨å‡½æ•¸åƒæ•¸ä¹‹å¾Œæ·»åР函
+æ•¸åƒæ•¸å±¬æ€§ã€‚在這種情æ³ä¸‹ï¼Œå®ƒå€‘應該跟隨存儲類型屬性(例如,與上é¢çš„ **è²æ˜Ž**
+示例相比,請注æ„下é¢çš„ ``__printf(4, 5)`` çš„ä½ç½®ç™¼ç”Ÿäº†è®ŠåŒ–)::
+
+ static __always_inline __init __printf(4, 5) void * __must_check action(enum magic value,
+ size_t size, u8 count, char *fmt, ...) __malloc
+ {
+ ...
+ }
7) 集中的函數退出途徑
-------------------------------
+---------------------
雖然被æŸäº›äººè²ç¨±å·²ç¶“éŽæ™‚,但是 goto 語å¥çš„等價物還是經常被編譯器所使用,具體
形弿˜¯ç„¡æ¢ä»¶è·³è½‰æŒ‡ä»¤ã€‚
@@ -436,7 +512,7 @@ Linux 里這是æå€¡çš„åšæ³•,因爲這樣å¯ä»¥å¾ˆç°¡å–®çš„給讀者æä¾›æ›
return result;
}
-ä¸€å€‹éœ€è¦æ³¨æ„的常見錯誤是 ``一個 err 錯誤`` ,就åƒé€™æ¨£ï¼š
+ä¸€å€‹éœ€è¦æ³¨æ„的常見錯誤是 ``å–® err 錯誤`` ,就åƒé€™æ¨£ï¼š
.. code-block:: c
@@ -459,22 +535,22 @@ Linux 里這是æå€¡çš„åšæ³•,因爲這樣å¯ä»¥å¾ˆç°¡å–®çš„給讀者æä¾›æ›
ç†æƒ³æƒ…æ³ä¸‹ï¼Œä½ æ‡‰è©²æ¨¡æ“¬éŒ¯èª¤ä¾†æ¸¬è©¦æ‰€æœ‰é€€å‡ºè·¯å¾‘。
-8) 注釋
-------------------------------
+8) 註釋
+-------
-注釋是好的,ä¸éŽæœ‰éŽåº¦æ³¨é‡‹çš„å±éšªã€‚æ°¸é ä¸è¦åœ¨æ³¨é‡‹é‡Œè§£é‡‹ä½ çš„代碼是如何é‹ä½œçš„:
+註釋是好的,ä¸éŽæœ‰éŽåº¦è¨»é‡‹çš„å±éšªã€‚æ°¸é ä¸è¦åœ¨è¨»é‡‹è£è§£é‡‹ä½ çš„代碼是如何é‹ä½œçš„:
æ›´å¥½çš„åšæ³•是讓別人一看你的代碼就å¯ä»¥æ˜Žç™½ï¼Œè§£é‡‹å¯«çš„很差的代碼是浪費時間。
-一般的,你想è¦ä½ çš„æ³¨é‡‹å‘Šè¨´åˆ¥äººä½ çš„代碼åšäº†ä»€éº¼ï¼Œè€Œä¸æ˜¯æ€Žéº¼åšçš„。也請你ä¸è¦æŠŠ
-注釋放在一個函數體內部:如果函數複雜到你需è¦ç¨ç«‹çš„æ³¨é‡‹å…¶ä¸­çš„一部分,你很å¯èƒ½
+一般來說你用註釋告訴別人你的代碼åšäº†ä»€éº¼ï¼Œè€Œä¸æ˜¯æ€Žéº¼åšçš„。也請你ä¸è¦æŠŠ
+註釋放在一個函數體內部:如果函數複雜到你需è¦ç¨ç«‹çš„註釋其中的一部分,你很å¯èƒ½
需è¦å›žåˆ°ç¬¬å…­ç« çœ‹ä¸€çœ‹ã€‚ä½ å¯ä»¥åšä¸€äº›å°æ³¨é‡‹ä¾†è¨»æ˜Žæˆ–警告æŸäº›å¾ˆè°æ˜Ž (或者槽糕) çš„
-åšæ³•,但ä¸è¦åŠ å¤ªå¤šã€‚ä½ æ‡‰è©²åšçš„,是把注釋放在函數的頭部,告訴人們它åšäº†ä»€éº¼ï¼Œ
+åšæ³•,但ä¸è¦åŠ å¤ªå¤šã€‚ä½ æ‡‰è©²åšçš„,是把註釋放在函數的頭部,告訴人們它åšäº†ä»€éº¼ï¼Œ
也å¯ä»¥åŠ ä¸Šå®ƒåšé€™äº›äº‹æƒ…的原因。
-當注釋內核 API 函數時,請使用 kernel-doc æ ¼å¼ã€‚請看
-Documentation/doc-guide/ å’Œ scripts/kernel-doc 以ç²å¾—詳細信æ¯ã€‚
+當註釋內核 API 函數時,請使用 kernel-doc æ ¼å¼ã€‚詳見
+Documentation/translations/zh_CN/doc-guide/index.rst 和 scripts/kernel-doc 。
-é•· (多行) 注釋的首é¸é¢¨æ ¼æ˜¯ï¼š
+é•· (多行) 註釋的首é¸é¢¨æ ¼æ˜¯ï¼š
.. code-block:: c
@@ -487,7 +563,7 @@ Documentation/doc-guide/ å’Œ scripts/kernel-doc 以ç²å¾—詳細信æ¯ã€‚
* with beginning and ending almost-blank lines.
*/
-å°æ–¼åœ¨ net/ å’Œ drivers/net/ 的文件,首é¸çš„é•· (多行) 注釋風格有些ä¸åŒã€‚
+å°æ–¼åœ¨ net/ å’Œ drivers/net/ 的文件,首é¸çš„é•· (多行) 註釋風格有些ä¸åŒã€‚
.. code-block:: c
@@ -498,23 +574,24 @@ Documentation/doc-guide/ å’Œ scripts/kernel-doc 以ç²å¾—詳細信æ¯ã€‚
* but there is no initial almost-blank line.
*/
-注釋數據也是很é‡è¦çš„,ä¸ç®¡æ˜¯åŸºæœ¬é¡žåž‹é‚„是è¡ç”Ÿé¡žåž‹ã€‚爲了方便實ç¾é€™ä¸€é»žï¼Œæ¯ä¸€è¡Œ
+註釋數據也是很é‡è¦çš„,ä¸ç®¡æ˜¯åŸºæœ¬é¡žåž‹é‚„是è¡ç”Ÿé¡žåž‹ã€‚爲了方便實ç¾é€™ä¸€é»žï¼Œæ¯ä¸€è¡Œ
應åªè²æ˜Žä¸€å€‹æ•¸æ“š (ä¸è¦ä½¿ç”¨é€—è™Ÿä¾†ä¸€æ¬¡è²æ˜Žå¤šå€‹æ•¸æ“š)。這樣你就有空間來爲æ¯å€‹æ•¸æ“š
å¯«ä¸€æ®µå°æ³¨é‡‹ä¾†è§£é‡‹å®ƒå€‘的用途了。
9) 你已經把事情弄糟了
-------------------------------
+---------------------
-這沒什麼,我們都是這樣。å¯èƒ½ä½ çš„使用了很長時間 Unix 的朋å‹å·²ç¶“告訴你
-``GNU emacs`` 能自動幫你格å¼åŒ– C 原始碼,而且你也注æ„到了,確實是這樣,ä¸éŽå®ƒ
+這沒什麼,我們都是這樣。å¯èƒ½ä½ é•·æœŸä½¿ç”¨ Unix 的朋å‹å·²ç¶“告訴你
+``GNU emacs`` 能自動幫你格å¼åŒ– C æºä»£ç¢¼ï¼Œè€Œä¸”你也注æ„到了,確實是這樣,ä¸éŽå®ƒ
所使用的默èªå€¼å’Œæˆ‘們想è¦çš„ç›¸åŽ»ç”šé  (實際上,甚至比隨機打的還è¦å·®â€”—無數個猴å­
-在 GNU emacs 里打字永é ä¸æœƒå‰µé€ å‡ºä¸€å€‹å¥½ç¨‹åº) (譯註:Infinite Monkey Theorem)
+在 GNU emacs è£æ‰“å­—æ°¸é ä¸æœƒå‰µé€ å‡ºä¸€å€‹å¥½ç¨‹åº)
+*(譯註:Infinite Monkey Theorem)*
所以你è¦éº¼æ”¾æ£„ GNU emacs,è¦éº¼æ”¹è®Šå®ƒè®“它使用更åˆç†çš„è¨­å®šã€‚è¦æŽ¡ç”¨å¾Œä¸€å€‹æ–¹æ¡ˆï¼Œ
-ä½ å¯ä»¥æŠŠä¸‹é¢é€™æ®µç²˜è²¼åˆ°ä½ çš„ .emacs 文件里。
+ä½ å¯ä»¥æŠŠä¸‹é¢é€™æ®µç²˜è²¼åˆ°ä½ çš„ .emacs 文件è£ã€‚
-.. code-block:: none
+.. code-block:: elisp
(defun c-lineup-arglist-tabs-only (ignored)
"Line up argument lists by tabs, not spaces"
@@ -533,7 +610,7 @@ Documentation/doc-guide/ å’Œ scripts/kernel-doc 以ç²å¾—詳細信æ¯ã€‚
(c-offsets-alist . (
(arglist-close . c-lineup-arglist-tabs-only)
(arglist-cont-nonempty .
- (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
+ (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
(arglist-intro . +)
(brace-list-intro . +)
(c . c-lineup-C-comments)
@@ -565,24 +642,29 @@ Documentation/doc-guide/ å’Œ scripts/kernel-doc 以ç²å¾—詳細信æ¯ã€‚
這會讓 emacs 在 ``~/src/linux-trees`` 下的 C æºæ–‡ä»¶ç²å¾—更好的內核代碼風格。
-ä¸éŽå°±ç®—你嘗試讓 emacs 正確的格å¼åŒ–ä»£ç¢¼å¤±æ•—äº†ï¼Œä¹Ÿä¸¦ä¸æ„味著你失去了一切:還å¯
+ä¸éŽå°±ç®—你嘗試讓 emacs 正確的格å¼åŒ–ä»£ç¢¼å¤±æ•—äº†ï¼Œä¹Ÿä¸¦ä¸æ„味ç€ä½ å¤±åŽ»äº†ä¸€åˆ‡ï¼šé‚„å¯
以用 ``indent`` 。
ä¸éŽï¼ŒGNU indent 也有和 GNU emacs 一樣有å•題的設定,所以你需è¦çµ¦å®ƒä¸€äº›å‘½ä»¤é¸
項。ä¸éŽï¼Œé€™é‚„ä¸ç®—太糟糕,因爲就算是 GNU indent 的作者也èªåŒ K&R çš„æ¬Šå¨æ€§
(GNU çš„äººä¸¦ä¸æ˜¯å£žäººï¼Œä»–å€‘åªæ˜¯åœ¨é€™å€‹å•題上被嚴é‡çš„誤導了),所以你åªè¦çµ¦ indent
指定é¸é … ``-kr -i8`` (代表 ``K&R,8 字符縮進``),或使用 ``scripts/Lindent``
-這樣就å¯ä»¥ä»¥æœ€æ™‚髦的方å¼ç¸®é€²åŽŸå§‹ç¢¼ã€‚
+這樣就å¯ä»¥ä»¥æœ€æ™‚髦的方å¼ç¸®é€²æºä»£ç¢¼ã€‚
-``indent`` 有很多é¸é …ï¼Œç‰¹åˆ¥æ˜¯é‡æ–°æ ¼å¼åŒ–注釋的時候,你å¯èƒ½éœ€è¦çœ‹ä¸€ä¸‹å®ƒçš„æ‰‹å†Šã€‚
+``indent`` 有很多é¸é …ï¼Œç‰¹åˆ¥æ˜¯é‡æ–°æ ¼å¼åŒ–註釋的時候,你å¯èƒ½éœ€è¦çœ‹ä¸€ä¸‹å®ƒçš„æ‰‹å†Šã€‚
ä¸éŽè¨˜ä½ï¼š ``indent`` ä¸èƒ½ä¿®æ­£å£žçš„編程習慣。
+請注æ„,您還å¯ä»¥ä½¿ç”¨ ``clang-format`` 工具幫助您處ç†é€™äº›è¦å‰‡ï¼Œå¿«é€Ÿè‡ªå‹•釿–°æ ¼
+å¼åŒ–部分代碼,並審閱整個文件以發ç¾ä»£ç¢¼é¢¨æ ¼éŒ¯èª¤ã€æ‰“字錯誤和å¯èƒ½çš„æ”¹é€²ã€‚它還å¯
+ä»¥æ–¹ä¾¿åœ°æŽ’åº ``#include`` ,å°é½Šè®Šé‡/å®ï¼Œé‡æŽ’文本和其他類似任務。
+詳見 Documentation/process/clang-format.rst 。
+
10) Kconfig é…置文件
-------------------------------
+--------------------
-å°æ–¼é布æºç¢¼æ¨¹çš„æ‰€æœ‰ Kconfig* é…ç½®æ–‡ä»¶ä¾†èªªï¼Œå®ƒå€‘ç¸®é€²æ–¹å¼æœ‰æ‰€ä¸åŒã€‚緊挨著
-``config`` 定義的行,用一個制表符縮進,然而 help ä¿¡æ¯çš„縮進則é¡å¤–增加 2 個空
+å°æ–¼é佈æºç¢¼æ¨¹çš„æ‰€æœ‰ Kconfig* é…ç½®æ–‡ä»¶ä¾†èªªï¼Œå®ƒå€‘ç¸®é€²æ–¹å¼æœ‰æ‰€ä¸åŒã€‚緊挨ç€
+``config`` 定義的行,用一個製表符縮進,然而 help ä¿¡æ¯çš„縮進則é¡å¤–增加 2 個空
格。舉個例å­::
config AUDIT
@@ -594,7 +676,7 @@ Documentation/doc-guide/ å’Œ scripts/kernel-doc 以ç²å¾—詳細信æ¯ã€‚
logging of avc messages output). Does not do system-call
auditing without CONFIG_AUDITSYSCALL.
-而那些å±éšªçš„功能 (比如æŸäº›æ–‡ä»¶ç³»çµ±çš„寫支æŒ) 應該在它們的æç¤ºå­—符串里顯著的è²
+而那些å±éšªçš„功能 (比如æŸäº›æ–‡ä»¶ç³»çµ±çš„寫支æŒ) 應該在它們的æç¤ºå­—符串è£é¡¯è‘—çš„è²
明這一點::
config ADFS_FS_RW
@@ -602,17 +684,17 @@ Documentation/doc-guide/ å’Œ scripts/kernel-doc 以ç²å¾—詳細信æ¯ã€‚
depends on ADFS_FS
...
-è¦æŸ¥çœ‹é…置文件的完整文檔,請看 Documentation/kbuild/kconfig-language.rst。
+è¦æŸ¥çœ‹é…置文件的完整文檔,請看 Documentation/kbuild/kconfig-language.rst 。
11) æ•¸æ“šçµæ§‹
-------------------------------
+------------
-å¦‚æžœä¸€å€‹æ•¸æ“šçµæ§‹ï¼Œåœ¨å‰µå»ºå’ŒéŠ·æ¯€å®ƒçš„å–®ç·šåŸ·è¡Œç’°å¢ƒä¹‹å¤–å¯è¦‹ï¼Œé‚£éº¼å®ƒå¿…é ˆè¦æœ‰ä¸€å€‹å¼•
-用計數器。內核里沒有垃圾收集 (並且內核之外的垃圾收集慢且效率低下),這æ„味著你
+å¦‚æžœä¸€å€‹æ•¸æ“šçµæ§‹ï¼Œåœ¨å‰µå»ºå’ŒéŠ·ç‡¬å®ƒçš„å–®ç·šåŸ·è¡Œç’°å¢ƒä¹‹å¤–å¯è¦‹ï¼Œé‚£éº¼å®ƒå¿…é ˆè¦æœ‰ä¸€å€‹å¼•
+ç”¨è¨ˆæ•¸å™¨ã€‚å…§æ ¸è£æ²’有垃圾收集 (並且內核之外的垃圾收集慢且效率低下),這æ„味ç€ä½ 
絕å°éœ€è¦è¨˜éŒ„ä½ å°é€™ç¨®æ•¸æ“šçµæ§‹çš„使用情æ³ã€‚
-引用計數æ„味著你能夠é¿å…上鎖,並且å…許多個用戶並行訪å•é€™å€‹æ•¸æ“šçµæ§‹â€”—而ä¸éœ€è¦
+引用計數æ„味ç€ä½ èƒ½å¤ é¿å…上鎖,並且å…許多個用戶並行訪å•é€™å€‹æ•¸æ“šçµæ§‹â€”—而ä¸éœ€è¦
æ“”å¿ƒé€™å€‹æ•¸æ“šçµæ§‹åƒ…僅因爲暫時ä¸è¢«ä½¿ç”¨å°±æ¶ˆå¤±äº†ï¼Œé‚£äº›ç”¨æˆ¶å¯èƒ½ä¸éŽæ˜¯æ²‰ç¡äº†ä¸€é™£æˆ–
者åšäº†ä¸€äº›å…¶ä»–事情而已。
@@ -626,13 +708,13 @@ Documentation/doc-guide/ å’Œ scripts/kernel-doc 以ç²å¾—詳細信æ¯ã€‚
mm_count),和文件系統 (``struct super_block``: s_count 和 s_active) 中找到。
記ä½ï¼šå¦‚æžœå¦ä¸€å€‹åŸ·è¡Œç·šç´¢å¯ä»¥æ‰¾åˆ°ä½ çš„æ•¸æ“šçµæ§‹ï¼Œä½†é€™å€‹æ•¸æ“šçµæ§‹æ²’有引用計數器,
-這裡幾乎肯定是一個 bug。
+這è£å¹¾ä¹Žè‚¯å®šæ˜¯ä¸€å€‹ bug。
12) å®ï¼Œæžšèˆ‰å’ŒRTL
-------------------------------
+-----------------
-用於定義常é‡çš„å®çš„åå­—åŠæžšèˆ‰é‡Œçš„æ¨™ç±¤éœ€è¦å¤§å¯«ã€‚
+用於定義常é‡çš„å®çš„åå­—åŠæžšèˆ‰è£çš„æ¨™ç±¤éœ€è¦å¤§å¯«ã€‚
.. code-block:: c
@@ -642,9 +724,9 @@ mm_count),和文件系統 (``struct super_block``: s_count å’Œ s_active) 中æ‰
å®çš„å字請用大寫字æ¯ï¼Œä¸éŽå½¢å¦‚函數的å®çš„åå­—å¯ä»¥ç”¨å°å¯«å­—æ¯ã€‚
-一般的,如果能寫æˆå…§è¯å‡½æ•¸å°±ä¸è¦å¯«æˆåƒå‡½æ•¸çš„å®ã€‚
+通常如果能寫æˆå…§è¯å‡½æ•¸å°±ä¸è¦å¯«æˆåƒå‡½æ•¸çš„å®ã€‚
-嫿œ‰å¤šå€‹èªžå¥çš„宿‡‰è©²è¢«åŒ…å«åœ¨ä¸€å€‹ do-while 代碼塊里:
+嫿œ‰å¤šå€‹èªžå¥çš„宿‡‰è©²è¢«åŒ…å«åœ¨ä¸€å€‹ do-while 代碼塊è£ï¼š
.. code-block:: c
@@ -667,7 +749,7 @@ mm_count),和文件系統 (``struct super_block``: s_count å’Œ s_active) 中æ‰
} while (0)
**éžå¸¸** ä¸å¥½ã€‚它看起來åƒä¸€å€‹å‡½æ•¸ï¼Œä¸éŽå»èƒ½å°Žè‡´ ``調用`` 它的函數退出;ä¸è¦æ‰“
-亂讀者大腦里的語法分æžå™¨ã€‚
+亂讀者大腦è£çš„語法分æžå™¨ã€‚
2) ä¾è³´æ–¼ä¸€å€‹å›ºå®šå字的本地變é‡çš„å®ï¼š
@@ -689,7 +771,7 @@ mm_count),和文件系統 (``struct super_block``: s_count å’Œ s_active) 中æ‰
#define CONSTANT 0x4000
#define CONSTEXP (CONSTANT | 3)
-5) 在å®é‡Œå®šç¾©é¡žä¼¼å‡½æ•¸çš„æœ¬åœ°è®Šé‡æ™‚命åè¡çªï¼š
+5) 在å®è£å®šç¾©é¡žä¼¼å‡½æ•¸çš„æœ¬åœ°è®Šé‡æ™‚命åè¡çªï¼š
.. code-block:: c
@@ -700,45 +782,46 @@ mm_count),和文件系統 (``struct super_block``: s_count å’Œ s_active) 中æ‰
(ret); \
})
-ret 是本地變é‡çš„通用åå­— - __foo_ret æ›´ä¸å®¹æ˜“與一個已存在的變é‡è¡çªã€‚
+ret 是本地變é‡çš„通用å字—— __foo_ret æ›´ä¸å®¹æ˜“與一個已存在的變é‡è¡çªã€‚
-cpp 手冊å°å®çš„講解很詳細。gcc internals 手冊也詳細講解了 RTL,內核里的彙編語
+cpp 手冊å°å®çš„講解很詳細。gcc internals 手冊也詳細講解了 RTL,內核è£çš„彙編語
言經常用到它。
-13) 列å°å…§æ ¸æ¶ˆæ¯
-------------------------------
+13) 打å°å…§æ ¸æ¶ˆæ¯
+----------------
-內核開發者應該是å—éŽè‰¯å¥½æ•™è‚²çš„。請一定注æ„內核信æ¯çš„æ‹¼å¯«ï¼Œä»¥çµ¦äººä»¥å¥½çš„å°è±¡ã€‚
+內核開發者應該看起來有文化。請一定注æ„內核信æ¯çš„æ‹¼å¯«ï¼Œä»¥çµ¦äººè‰¯å¥½çš„å°è±¡ã€‚
ä¸è¦ç”¨ä¸è¦ç¯„的單詞比如 ``dont``,而è¦ç”¨ ``do not`` 或者 ``don't`` 。ä¿è­‰é€™äº›ä¿¡
-æ¯ç°¡å–®æ˜Žäº†,無歧義。
+æ¯ç°¡å–®æ˜Žçž­ã€ç„¡æ­§ç¾©ã€‚
內核信æ¯ä¸å¿…以英文å¥è™ŸçµæŸã€‚
-åœ¨å°æ‹¬è™Ÿé‡Œåˆ—å°æ•¸å­— (%d) 沒有任何價值,應該é¿å…這樣åšã€‚
+åœ¨å°æ‹¬è™Ÿè£æ‰“å°æ•¸å­— (%d) 沒有任何價值,應該é¿å…這樣åšã€‚
-<linux/device.h> 里有一些驅動模型診斷å®ï¼Œä½ æ‡‰è©²ä½¿ç”¨å®ƒå€‘,以確ä¿ä¿¡æ¯å°æ‡‰æ–¼æ­£ç¢º
+<linux/device.h> è£æœ‰ä¸€äº›é©…動模型診斷å®ï¼Œä½ æ‡‰è©²ä½¿ç”¨å®ƒå€‘,以確ä¿ä¿¡æ¯å°æ‡‰æ–¼æ­£ç¢º
的設備和驅動,並且被標記了正確的消æ¯ç´šåˆ¥ã€‚é€™äº›å®æœ‰ï¼šdev_err(), dev_warn(),
dev_info() ç­‰ç­‰ã€‚å°æ–¼é‚£äº›ä¸å’ŒæŸå€‹ç‰¹å®šè¨­å‚™ç›¸é—œé€£çš„ä¿¡æ¯ï¼Œ<linux/printk.h> 定義
了 pr_notice(), pr_info(), pr_warn(), pr_err() 和其他。
寫出好的調試信æ¯å¯ä»¥æ˜¯ä¸€å€‹å¾ˆå¤§çš„æŒ‘戰;一旦你寫出後,這些信æ¯åœ¨é ç¨‹é™¤éŒ¯æ™‚能æ
-供極大的幫助。然而列å°èª¿è©¦ä¿¡æ¯çš„è™•ç†æ–¹å¼åŒåˆ—å°éžèª¿è©¦ä¿¡æ¯ä¸åŒã€‚å…¶ä»– pr_XXX()
-函數能無æ¢ä»¶åœ°åˆ—å°ï¼Œpr_debug() å»ä¸ï¼›é»˜èªæƒ…æ³ä¸‹å®ƒä¸æœƒè¢«ç·¨è­¯ï¼Œé™¤éžå®šç¾©äº† DEBUG
+供極大的幫助。然而打å°èª¿è©¦ä¿¡æ¯çš„è™•ç†æ–¹å¼åŒæ‰“å°éžèª¿è©¦ä¿¡æ¯ä¸åŒã€‚å…¶ä»– pr_XXX()
+函數能無æ¢ä»¶åœ°æ‰“å°ï¼Œpr_debug() å»ä¸ï¼›é»˜èªæƒ…æ³ä¸‹å®ƒä¸æœƒè¢«ç·¨è­¯ï¼Œé™¤éžå®šç¾©äº† DEBUG
或設定了 CONFIG_DYNAMIC_DEBUGã€‚å¯¦éš›é€™åŒæ¨£æ˜¯çˆ²äº† dev_dbg(),一個相關約定是在一
個已經開啓了 DEBUG 時,使用 VERBOSE_DEBUG 來添加 dev_vdbg()。
-許多å­ç³»çµ±æ“有 Kconfig 調試é¸é …來開啓 -DDEBUG åœ¨å°æ‡‰çš„ Makefile 裡é¢ï¼›åœ¨å…¶ä»–
-情æ³ä¸‹ï¼Œç‰¹æ®Šæ–‡ä»¶ä½¿ç”¨ #define DEBUG。當一æ¢èª¿è©¦ä¿¡æ¯éœ€è¦è¢«ç„¡æ¢ä»¶åˆ—å°æ™‚,例如,
+許多å­ç³»çµ±æ“有 Kconfig 調試é¸é …來開啓尿‡‰ Makefile è£é¢çš„ -DDEBUG;在其他
+情æ³ä¸‹ï¼Œç‰¹æ®Šæ–‡ä»¶ä½¿ç”¨ #define DEBUG。當一æ¢èª¿è©¦ä¿¡æ¯éœ€è¦è¢«ç„¡æ¢ä»¶æ‰“å°æ™‚,例如,
如果已經包å«ä¸€å€‹èª¿è©¦ç›¸é—œçš„ #ifdef æ¢ä»¶ï¼Œprintk(KERN_DEBUG ...) å°±å¯è¢«ä½¿ç”¨ã€‚
14) 分é…å…§å­˜
-------------------------------
+------------
å…§æ ¸æä¾›äº†ä¸‹é¢çš„一般用途的內存分é…函數:
kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。
-è«‹åƒè€ƒ API 文檔以ç²å–有關它們的詳細信æ¯ã€‚
+è«‹åƒè€ƒ API 文檔以ç²å–有關它們的詳細信æ¯ï¼š
+Documentation/translations/zh_CN/core-api/memory-allocation.rst 。
傳éžçµæ§‹é«”大å°çš„首é¸å½¢å¼æ˜¯é€™æ¨£çš„:
@@ -765,17 +848,19 @@ kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。
p = kcalloc(n, sizeof(...), ...);
-å…©ç¨®å½¢å¼æª¢æŸ¥åˆ†é…å¤§å° n * sizeof(...) 的溢出,如果溢出返回 NULL。
+兩種形å¼éƒ½æœƒæª¢æŸ¥åˆ†é… n * sizeof(...) 大尿™‚內存的溢出,如果溢出返回 NULL。
+在沒有 __GFP_NOWARN 的情æ³ä¸‹ä½¿ç”¨æ™‚,這些通用分é…函數都會在失敗時發起堆棧轉儲,
+因此當返回NULL時,沒有必è¦ç™¼å‡ºé¡å¤–的失敗消æ¯ã€‚
15) å…§è¯å¼Šç—…
-------------------------------
+------------
有一個常見的誤解是 ``å…§è¯`` 是 gcc æä¾›çš„å¯ä»¥è®“代碼é‹è¡Œæ›´å¿«çš„一個é¸é …。雖然使
用內è¯å‡½æ•¸æœ‰æ™‚候是æ°ç•¶çš„ (比如作爲一種替代å®çš„æ–¹å¼ï¼Œè«‹çœ‹ç¬¬å二章),ä¸éŽå¾ˆå¤šæƒ…
æ³ä¸‹ä¸æ˜¯é€™æ¨£ã€‚inline çš„éŽåº¦ä½¿ç”¨æœƒä½¿å…§æ ¸è®Šå¤§ï¼Œå¾žè€Œä½¿æ•´å€‹ç³»çµ±é‹è¡Œé€Ÿåº¦è®Šæ…¢ã€‚
-因爲體ç©å¤§å…§æ ¸æœƒå ç”¨æ›´å¤šçš„æŒ‡ä»¤é«˜é€Ÿç·©å­˜ï¼Œè€Œä¸”會導致 pagecache çš„å¯ç”¨å…§å­˜æ¸›å°‘。
-想åƒä¸€ä¸‹ï¼Œä¸€æ¬¡ pagecache 未命中就會導致一次ç£ç¢Ÿå°‹å€ï¼Œå°‡è€—時 5 毫秒。5 毫秒的
+因爲體ç©å¤§å…§æ ¸æœƒä½”用更多的指令高速緩存,而且會導致 pagecache çš„å¯ç”¨å…§å­˜æ¸›å°‘。
+想象一下,一次 pagecache 未命中就會導致一次ç£ç›¤å°‹å€ï¼Œå°‡è€—時 5 毫秒。5 毫秒的
時間內 CPU 能執行很多很多指令。
一個基本的原則是如果一個函數有 3 行以上,就ä¸è¦æŠŠå®ƒè®Šæˆå…§è¯å‡½æ•¸ã€‚這個原則的一
@@ -790,7 +875,7 @@ inline gcc 也å¯ä»¥è‡ªå‹•使其內è¯ã€‚而且其他用戶å¯èƒ½æœƒè¦æ±‚移除
16) 函數返回值åŠå‘½å
-------------------------------
+--------------------
函數å¯ä»¥è¿”回多種ä¸åŒé¡žåž‹çš„值,最常見的一種是表明函數執行æˆåŠŸæˆ–è€…å¤±æ•—çš„å€¼ã€‚é€™æ¨£
的一個值å¯ä»¥è¡¨ç¤ºçˆ²ä¸€å€‹éŒ¯èª¤ä»£ç¢¼æ•´æ•¸ (-Exxxï¼å¤±æ•—,0ï¼æˆåŠŸ) 或者一個 ``æˆåŠŸ``
@@ -801,7 +886,7 @@ inline gcc 也å¯ä»¥è‡ªå‹•使其內è¯ã€‚而且其他用戶å¯èƒ½æœƒè¦æ±‚移除
產生這種 bug,請éµå¾ªä¸‹é¢çš„æ…£ä¾‹::
如果函數的å字是一個動作或者強制性的命令,那麼這個函數應該返回錯誤代
- 碼整數。如果是一個判斷,那麼函數應該返回一個 "æˆåŠŸ" 布爾值。
+ 碼整數。如果是一個判斷,那麼函數應該返回一個“æˆåŠŸâ€å¸ƒçˆ¾å€¼ã€‚
比如, ``add work`` 是一個命令,所以 add_work() 在æˆåŠŸæ™‚è¿”å›ž 0,在失敗時返回
-EBUSY。類似的,因爲 ``PCI device present`` 是一個判斷,所以 pci_dev_present()
@@ -810,13 +895,35 @@ inline gcc 也å¯ä»¥è‡ªå‹•使其內è¯ã€‚而且其他用戶å¯èƒ½æœƒè¦æ±‚移除
所有 EXPORTed 函數都必須éµå®ˆé€™å€‹æ…£ä¾‹ï¼Œæ‰€æœ‰çš„å…¬å…±å‡½æ•¸ä¹Ÿéƒ½æ‡‰è©²å¦‚æ­¤ã€‚ç§æœ‰
(static) 函數ä¸éœ€è¦å¦‚此,但是我們也推薦這樣åšã€‚
-è¿”å›žå€¼æ˜¯å¯¦éš›è¨ˆç®—çµæžœè€Œä¸æ˜¯è¨ˆç®—æ˜¯å¦æˆåŠŸçš„æ¨™èªŒçš„å‡½æ•¸ä¸å—此慣例的é™åˆ¶ã€‚一般的,
+è¿”å›žå€¼æ˜¯å¯¦éš›è¨ˆç®—çµæžœè€Œä¸æ˜¯è¨ˆç®—æ˜¯å¦æˆåŠŸçš„æ¨™èªŒçš„å‡½æ•¸ä¸å—此慣例的é™åˆ¶ã€‚通常
他們通éŽè¿”回一些正常值範åœä¹‹å¤–çš„çµæžœä¾†è¡¨ç¤ºå‡ºéŒ¯ã€‚å…¸åž‹çš„ä¾‹å­æ˜¯è¿”回指é‡çš„函數,
他們使用 NULL 或者 ERR_PTR 機制來報告錯誤。
+17) 使用布爾類型
+----------------
+
+Linux內核布爾(bool)類型是C99 _Bool類型的別å。布爾值åªèƒ½çˆ²0或1,而å°å¸ƒçˆ¾çš„
+éš±å¼æˆ–顯å¼è½‰æ›å°‡è‡ªå‹•將值轉æ›çˆ²true或false。在使用布爾類型時 **ä¸éœ€è¦** 構造,
+它會消除一類錯誤。
+
+使用布爾值時,應使用trueå’Œfalseå®šç¾©ï¼Œè€Œä¸æ˜¯1å’Œ0。
-17) ä¸è¦é‡æ–°ç™¼æ˜Žå…§æ ¸å®
-------------------------------
+布爾函數返回類型和堆棧變é‡ç¸½æ˜¯å¯ä»¥åœ¨é©ç•¶çš„æ™‚候使用。鼓勵使用布爾來æé«˜å¯è®€æ€§ï¼Œ
+並且布爾值在存儲時通常比“intâ€æ›´å¥½ã€‚
+
+如果緩存行佈局或值的大å°å¾ˆé‡è¦ï¼Œè«‹ä¸è¦ä½¿ç”¨å¸ƒçˆ¾ï¼Œå› çˆ²å…¶å¤§å°å’Œå°é½Šæ–¹å¼æ ¹æ“šç·¨è­¯
+çš„é«”ç³»çµæ§‹è€Œä¸åŒã€‚é‡å°å°é½Šå’Œå¤§å°é€²è¡Œå„ªåŒ–çš„çµæ§‹é«”䏿‡‰ä½¿ç”¨å¸ƒçˆ¾ã€‚
+
+å¦‚æžœä¸€å€‹çµæ§‹é«”有多個true/false值,請考慮將它們åˆä½µçˆ²å…·æœ‰1比特æˆå“¡çš„ä½åŸŸï¼Œæˆ–使
+用é©ç•¶çš„固定寬度類型,如u8。
+
+é¡žä¼¼åœ°ï¼Œå°æ–¼å‡½æ•¸åƒæ•¸ï¼Œå¤šå€‹true/false值å¯ä»¥åˆä½µçˆ²å–®å€‹æŒ‰ä½çš„“標誌â€åƒæ•¸ï¼Œå¦‚果調
+用點具有裸true/false常é‡ï¼Œâ€œæ¨™èªŒâ€åƒæ•¸é€šå¸¸æ˜¯æ›´å…·å¯è®€æ€§çš„æ›¿ä»£æ–¹æ³•。
+
+ç¸½ä¹‹ï¼Œåœ¨çµæ§‹é«”å’Œåƒæ•¸ä¸­æœ‰é™åœ°ä½¿ç”¨å¸ƒçˆ¾å¯ä»¥æé«˜å¯è®€æ€§ã€‚
+
+18) ä¸è¦é‡æ–°ç™¼æ˜Žå…§æ ¸å®
+----------------------
頭文件 include/linux/kernel.h 包å«äº†ä¸€äº›å®ï¼Œä½ æ‡‰è©²ä½¿ç”¨å®ƒå€‘,而ä¸è¦è‡ªå·±å¯«ä¸€äº›
它們的變種。比如,如果你需è¦è¨ˆç®—一個數組的長度,使用這個å®
@@ -832,15 +939,15 @@ inline gcc 也å¯ä»¥è‡ªå‹•使其內è¯ã€‚而且其他用戶å¯èƒ½æœƒè¦æ±‚移除
#define sizeof_field(t, f) (sizeof(((t*)0)->f))
還有å¯ä»¥åšåš´æ ¼çš„類型檢查的 min() å’Œ max() å®ï¼Œå¦‚果你需è¦å¯ä»¥ä½¿ç”¨å®ƒå€‘。你å¯ä»¥
-自己看看那個頭文件里還定義了什麼你å¯ä»¥æ‹¿ä¾†ç”¨çš„æ±è¥¿ï¼Œå¦‚æžœæœ‰å®šç¾©çš„è©±ï¼Œä½ å°±ä¸æ‡‰
-åœ¨ä½ çš„ä»£ç¢¼é‡Œè‡ªå·±é‡æ–°å®šç¾©ã€‚
+自己看看那個頭文件è£é‚„定義了什麼你å¯ä»¥æ‹¿ä¾†ç”¨çš„æ±è¥¿ï¼Œå¦‚æžœæœ‰å®šç¾©çš„è©±ï¼Œä½ å°±ä¸æ‡‰
+在你的代碼è£è‡ªå·±é‡æ–°å®šç¾©ã€‚
-18) 編輯器模å¼è¡Œå’Œå…¶ä»–需è¦ç¾…嗦的事情
---------------------------------------------------
+19) 編輯器模å¼è¡Œå’Œå…¶ä»–需è¦ç¾…嗦的事情
+------------------------------------
-有一些編輯器å¯ä»¥è§£é‡‹åµŒå…¥åœ¨æºæ–‡ä»¶é‡Œçš„由一些特殊標記標明的é…置信æ¯ã€‚比如,emacs
-能夠解釋被標記æˆé€™æ¨£çš„行:
+有一些編輯器å¯ä»¥è§£é‡‹åµŒå…¥åœ¨æºæ–‡ä»¶è£çš„由一些特殊標記標明的é…置信æ¯ã€‚比如,emacs
+能夠解æžè¢«æ¨™è¨˜æˆé€™æ¨£çš„行:
.. code-block:: c
@@ -856,23 +963,23 @@ inline gcc 也å¯ä»¥è‡ªå‹•使其內è¯ã€‚而且其他用戶å¯èƒ½æœƒè¦æ±‚移除
End:
*/
-Vim 能夠解釋這樣的標記:
+Vim 能夠解æžé€™æ¨£çš„æ¨™è¨˜ï¼š
.. code-block:: c
/* vim:set sw=8 noet */
-ä¸è¦åœ¨åŽŸå§‹ç¢¼ä¸­åŒ…å«ä»»ä½•這樣的內容。æ¯å€‹äººéƒ½æœ‰ä»–自己的編輯器é…ç½®ï¼Œä½ çš„æºæ–‡ä»¶ä¸
+ä¸è¦åœ¨æºä»£ç¢¼ä¸­åŒ…å«ä»»ä½•這樣的內容。æ¯å€‹äººéƒ½æœ‰ä»–自己的編輯器é…ç½®ï¼Œä½ çš„æºæ–‡ä»¶ä¸
應該覆蓋別人的é…置。這包括有關縮進和模å¼é…置的標記。人們å¯ä»¥ä½¿ç”¨ä»–們自己定製
的模å¼ï¼Œæˆ–者使用其他å¯ä»¥ç”¢ç”Ÿæ­£ç¢ºçš„縮進的巧妙方法。
-19) å…§è¯å½™ç·¨
-------------------------------
+20) å…§è¯å½™ç·¨
+------------
-在特定架構的代碼中,你å¯èƒ½éœ€è¦å…§è¯å½™ç·¨èˆ‡ CPU 和平å°ç›¸é—œåŠŸèƒ½é€£æŽ¥ã€‚éœ€è¦é€™éº¼å𿙂
+在特定架構的代碼中,你å¯èƒ½éœ€è¦å…§è¯å½™ç·¨èˆ‡ CPU 和平臺相關功能連接。需è¦é€™éº¼å𿙂
å°±ä¸è¦çŒ¶è±«ã€‚然而,當 C å¯ä»¥å®Œæˆå·¥ä½œæ™‚,ä¸è¦å¹³ç™½ç„¡æ•…地使用內è¯å½™ç·¨ã€‚在å¯èƒ½çš„æƒ…
-æ³ä¸‹ï¼Œä½ å¯ä»¥ä¸¦ä¸”應該用 C 和硬體æºé€šã€‚
+æ³ä¸‹ï¼Œä½ å¯ä»¥ä¸¦ä¸”應該用 C 和硬件æºé€šã€‚
請考慮去寫æ†ç¶é€šç”¨ä½å…ƒ (wrap common bits) 的內è¯å½™ç·¨çš„簡單輔助函數,別去é‡è¤‡
åœ°å¯«ä¸‹åªæœ‰ç´°å¾®å·®ç•°å…§è¯å½™ç·¨ã€‚記ä½å…§è¯å½™ç·¨å¯ä»¥ä½¿ç”¨ C åƒæ•¸ã€‚
@@ -883,9 +990,9 @@ Vim 能夠解釋這樣的標記:
ä½ å¯èƒ½éœ€è¦æŠŠå½™ç·¨èªžå¥æ¨™è¨˜çˆ² volatile,用來阻止 GCC 在沒發ç¾ä»»ä½•副作用後就把它
移除了。你ä¸å¿…總是這樣åšï¼Œå„˜ç®¡ï¼Œé€™ä¸å¿…è¦çš„舉動會é™åˆ¶å„ªåŒ–。
-在寫一個包å«å¤šæ¢æŒ‡ä»¤çš„單個內è¯å½™ç·¨èªžå¥æ™‚ï¼ŒæŠŠæ¯æ¢æŒ‡ä»¤ç”¨å¼•號分割而且å„å ä¸€è¡Œï¼Œ
-é™¤äº†æœ€å¾Œä¸€æ¢æŒ‡ä»¤å¤–,在æ¯å€‹æŒ‡ä»¤çµå°¾åŠ ä¸Š \n\t,讓彙編輸出時å¯ä»¥æ­£ç¢ºåœ°ç¸®é€²ä¸‹ä¸€æ¢
-指令:
+在寫一個包å«å¤šæ¢æŒ‡ä»¤çš„單個內è¯å½™ç·¨èªžå¥æ™‚ï¼ŒæŠŠæ¯æ¢æŒ‡ä»¤ç”¨å¼•號分割而且å„佔一行,
+é™¤äº†æœ€å¾Œä¸€æ¢æŒ‡ä»¤å¤–,在æ¯å€‹æŒ‡ä»¤çµå°¾åŠ ä¸Š ``\n\t`` ,讓彙編輸出時å¯ä»¥æ­£ç¢ºåœ°ç¸®é€²
+ä¸‹ä¸€æ¢æŒ‡ä»¤ï¼š
.. code-block:: c
@@ -894,10 +1001,10 @@ Vim 能夠解釋這樣的標記:
: /* outputs */ : /* inputs */ : /* clobbers */);
-20) æ¢ä»¶ç·¨è­¯
-------------------------------
+21) æ¢ä»¶ç·¨è­¯
+------------
-åªè¦å¯èƒ½ï¼Œå°±ä¸è¦åœ¨ .c 文件裡é¢ä½¿ç”¨é è™•ç†æ¢ä»¶ (#if, #ifdef);這樣åšè®“代碼更難
+åªè¦å¯èƒ½ï¼Œå°±ä¸è¦åœ¨ .c 文件è£é¢ä½¿ç”¨é è™•ç†æ¢ä»¶ (#if, #ifdef)ï¼›é€™æ¨£åšæœƒè®“代碼更難
閱讀並且更難去跟蹤é‚輯。替代方案是,在頭文件中用é è™•ç†æ¢ä»¶æä¾›çµ¦é‚£äº› .c 文件
使用,å†çµ¦ #else æä¾›ä¸€å€‹ç©ºæ¨ (no-op stub) 版本,然後在 .c 文件內無æ¢ä»¶åœ°èª¿ç”¨
那些 (定義在頭文件內的) 函數。這樣åšï¼Œç·¨è­¯å™¨æœƒé¿å…爲æ¨å‡½æ•¸ (stub) 的調用生æˆ
@@ -908,8 +1015,8 @@ Vim 能夠解釋這樣的標記:
æ¢ä»¶åˆ°é€™å€‹è¼”助函數內。
如果你有一個在特定é…置中,å¯èƒ½è®Šæˆæœªä½¿ç”¨çš„函數或變é‡ï¼Œç·¨è­¯å™¨æœƒè­¦å‘Šå®ƒå®šç¾©äº†ä½†
-未使用,把它標記爲 __maybe_unused è€Œä¸æ˜¯å°‡å®ƒåŒ…å«åœ¨ä¸€å€‹é è™•ç†æ¢ä»¶ä¸­ã€‚(然而,如
-果一個函數或變é‡ç¸½æ˜¯æœªä½¿ç”¨ï¼Œå°±ç›´æŽ¥åˆªé™¤å®ƒã€‚)
+未使用,請把它標記爲 __maybe_unused è€Œä¸æ˜¯å°‡å®ƒåŒ…å«åœ¨ä¸€å€‹é è™•ç†æ¢ä»¶ä¸­ã€‚(然而,
+如果一個函數或變é‡ç¸½æ˜¯æœªä½¿ç”¨ï¼Œå°±ç›´æŽ¥åˆªé™¤å®ƒã€‚)
在代碼中,儘å¯èƒ½åœ°ä½¿ç”¨ IS_ENABLED å®ä¾†è½‰åŒ–æŸå€‹ Kconfig 標記爲 C 的布爾
表é”å¼ï¼Œä¸¦åœ¨ä¸€èˆ¬çš„ C æ¢ä»¶ä¸­ä½¿ç”¨å®ƒï¼š
@@ -926,7 +1033,7 @@ Vim 能夠解釋這樣的標記:
ä¸å­˜åœ¨æ™‚,你還是必須去用 #ifdef。
在任何有æ„義的 #if 或 #ifdef 塊的末尾 (è¶…éŽå¹¾è¡Œçš„),在 #endif åŒä¸€è¡Œçš„後é¢å¯«ä¸‹
-註解,注釋這個æ¢ä»¶è¡¨é”å¼ã€‚例如:
+註解,註釋這個æ¢ä»¶è¡¨é”å¼ã€‚例如:
.. code-block:: c
@@ -935,24 +1042,46 @@ Vim 能夠解釋這樣的標記:
#endif /* CONFIG_SOMETHING */
-附錄 I) åƒè€ƒ
--------------------
+附錄 I) åƒè€ƒè³‡æ–™
+----------------
-The C Programming Language, 第二版
+The C Programming Language, 2nd Edition
作者:Brian W. Kernighan 和 Denni M. Ritchie.
Prentice Hall, Inc., 1988.
-ISBN 0-13-110362-8 (軟皮), 0-13-110370-9 (硬皮).
+ISBN 0-13-110362-8 (å¹³è£), 0-13-110370-9 (ç²¾è£).
+
+.. note::
+
+ 《C程åºè¨­è¨ˆèªžè¨€ï¼ˆç¬¬2版)》
+ 作者:[美] Brian W. Kernighan / [美] Dennis M. Ritchie
+ 譯者:å¾å¯¶æ–‡ / æŽå¿— / 尤晉元(審校)
+ 出版社:機械工業出版社,2019
+ ISBN:9787111617945
The Practice of Programming
作者:Brian W. Kernighan 和 Rob Pike.
Addison-Wesley, Inc., 1999.
ISBN 0-201-61586-X.
+.. note::
+
+ 《程åºè¨­è¨ˆå¯¦è¸ã€‹
+ 作者:[美] Brian W. Kernighan / [美] Rob Pike
+ 出版社:機械工業出版社,2005
+ ISBN:9787111091578
+
+ 《程åºè¨­è¨ˆå¯¦è¸ã€‹
+ 作者:[美] Brian W. Kernighan / Rob Pike
+ 譯者:裘宗燕
+ 出版社:機械工業出版社,2000
+ ISBN:9787111075738
+
GNU 手冊 - éµå¾ª K&R 標準和此文本 - cpp, gcc, gcc internals and indent,
都å¯ä»¥å¾ž https://www.gnu.org/manual/ 找到
WG14 是 C 語言的國際標準化工作組,URL: http://www.open-std.org/JTC1/SC22/WG14/
-Kernel process/coding-style.rst,作者 greg@kroah.com 發表於 OLS 2002:
+內核文檔 Documentation/process/coding-style.rst,
+作者 greg@kroah.com 發表於 OLS 2002:
http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
diff --git a/Documentation/translations/zh_TW/process/development-process.rst b/Documentation/translations/zh_TW/process/development-process.rst
index f4cf5c2bbc82..7d803d3db89e 100644
--- a/Documentation/translations/zh_TW/process/development-process.rst
+++ b/Documentation/translations/zh_TW/process/development-process.rst
@@ -26,5 +26,5 @@
7.AdvancedTopics
8.Conclusion
-本文檔的目的是幫助開發人員(åŠå…¶ç¶“ç†ï¼‰ä»¥æœ€å°çš„æŒ«æŠ˜æ„Ÿèˆ‡é–‹ç™¼ç¤¾å€åˆä½œã€‚它試圖記錄這個社å€å¦‚何以一種ä¸ç†Ÿæ‚‰Linux內核開發(或者實際上是自由軟體開發)的人å¯ä»¥è¨ªå•的方å¼å·¥ä½œã€‚雖然這裡有一些技術資料,但這是一個é¢å‘éŽç¨‹çš„討論,ä¸éœ€è¦æ·±å…¥äº†è§£å…§æ ¸ç·¨ç¨‹å°±å¯ä»¥ç†è§£ã€‚
+本文檔的目的是幫助開發人員(åŠå…¶ç¶“ç†ï¼‰ä»¥æœ€å°çš„æŒ«æŠ˜æ„Ÿèˆ‡é–‹ç™¼ç¤¾å€åˆä½œã€‚它試圖記錄這個社å€å¦‚何以一種ä¸ç†Ÿæ‚‰Linux內核開發(或者實際上是自由軟件開發)的人å¯ä»¥è¨ªå•的方å¼å·¥ä½œã€‚é›–ç„¶é€™è£æœ‰ä¸€äº›æŠ€è¡“資料,但這是一個é¢å‘éŽç¨‹çš„討論,ä¸éœ€è¦æ·±å…¥çž­è§£å…§æ ¸ç·¨ç¨‹å°±å¯ä»¥ç†è§£ã€‚
diff --git a/Documentation/translations/zh_TW/process/email-clients.rst b/Documentation/translations/zh_TW/process/email-clients.rst
index ae63e41d9cee..55e10d3fc28a 100644
--- a/Documentation/translations/zh_TW/process/email-clients.rst
+++ b/Documentation/translations/zh_TW/process/email-clients.rst
@@ -1,20 +1,21 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. _tw_email_clients:
+.. SPDX-License-Identifier: GPL-2.0-or-later
.. include:: ../disclaimer-zh_TW.rst
-:Original: :ref:`Documentation/process/email-clients.rst <email_clients>`
+.. _tw_email_clients:
-譯者::
+:Original: Documentation/process/email-clients.rst
- 中文版維護者: 賈å¨å¨ Harry Wei <harryxiyou@gmail.com>
- 中文版翻譯者: 賈å¨å¨ Harry Wei <harryxiyou@gmail.com>
- 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
- 中文版校譯者: Yinglin Luan <synmyth@gmail.com>
- Xiaochen Wang <wangxiaochen0@gmail.com>
- yaxinsn <yaxinsn@163.com>
- Hu Haowen <src.res.211@gmail.com>
+:譯者:
+ - 賈å¨å¨ Harry Wei <harryxiyou@gmail.com>
+ - 時奎亮 Alex Shi <alexs@kernel.org>
+ - 峿ƒ³æˆ Wu XiangCheng <bobwxc@email.cn>
+
+:æ ¡è­¯:
+ - Yinglin Luan <synmyth@gmail.com>
+ - Xiaochen Wang <wangxiaochen0@gmail.com>
+ - yaxinsn <yaxinsn@163.com>
+ - Hu Haowen <src.res.211@gmail.com>
Linux郵件客戶端é…置信æ¯
=======================
@@ -30,30 +31,35 @@ Git
改日誌。如果工作正常,å†å°‡è£œä¸ç™¼é€åˆ°ç›¸æ‡‰çš„郵件列表。
-普通é…ç½®
+通用é…ç½®
--------
+
Linuxå…§æ ¸è£œä¸æ˜¯é€šéŽéƒµä»¶è¢«æäº¤çš„,最好把補ä¸ä½œçˆ²éƒµä»¶é«”的內嵌文本。有些維護者
æŽ¥æ”¶é™„ä»¶ï¼Œä½†æ˜¯é™„ä»¶çš„å…§å®¹æ ¼å¼æ‡‰è©²æ˜¯"text/plain"。然而,附件一般是ä¸è´Šæˆçš„,
因爲這會使補ä¸çš„引用部分在評論éŽç¨‹ä¸­è®Šçš„很困難。
+åŒæ™‚ä¹Ÿå¼·çƒˆå»ºè­°åœ¨è£œä¸æˆ–其他郵件的正文中使用純文本格å¼ã€‚https://useplaintext.email
+有助於瞭解如何é…置你喜歡的郵件客戶端,並在您還沒有首é¸çš„æƒ…æ³ä¸‹åˆ—出一些推薦的
+客戶端。
+
用來發é€Linux內核補ä¸çš„郵件客戶端在發é€è£œä¸æ™‚應該處於文本的原始狀態。例如,
-他們ä¸èƒ½æ”¹è®Šæˆ–者刪除制表符或者空格,甚至是在æ¯ä¸€è¡Œçš„開頭或者çµå°¾ã€‚
+他們ä¸èƒ½æ”¹è®Šæˆ–者刪除製表符或者空格,甚至是在æ¯ä¸€è¡Œçš„開頭或者çµå°¾ã€‚
ä¸è¦é€šéŽ"format=flowed"模å¼ç™¼é€è£œä¸ã€‚這樣會引起ä¸å¯é æœŸä»¥åŠæœ‰å®³çš„æ–·è¡Œã€‚
ä¸è¦è®“你的郵件客戶端進行自動æ›è¡Œã€‚這樣也會破壞你的補ä¸ã€‚
-郵件客戶端ä¸èƒ½æ”¹è®Šæ–‡æœ¬çš„字符集編碼方å¼ã€‚è¦ç™¼é€çš„補ä¸åªèƒ½æ˜¯ASCII或者UTF-8編碼方å¼ï¼Œ
-如果你使用UTF-8編碼方å¼ç™¼é€éƒµä»¶ï¼Œé‚£éº¼ä½ å°‡æœƒé¿å…一些å¯èƒ½ç™¼ç”Ÿçš„字符集å•題。
+郵件客戶端ä¸èƒ½æ”¹è®Šæ–‡æœ¬çš„字符集編碼方å¼ã€‚è¦ç™¼é€çš„補ä¸åªèƒ½æ˜¯ASCII或者UTF-8編碼
+æ–¹å¼ï¼Œå¦‚果你使用UTF-8編碼方å¼ç™¼é€éƒµä»¶ï¼Œé‚£éº¼ä½ å°‡æœƒé¿å…一些å¯èƒ½ç™¼ç”Ÿçš„字符集å•題。
-郵件客戶端應該形æˆä¸¦ä¸”ä¿æŒ References: 或者 In-Reply-To: 標題,那麼
-éƒµä»¶è©±é¡Œå°±ä¸æœƒä¸­æ–·ã€‚
+郵件客戶端應該生æˆä¸¦ä¸”ä¿æŒâ€œReferences:â€æˆ–者“In-Reply-To:â€éƒµä»¶é ­ï¼Œé€™æ¨£éƒµä»¶æœƒè©±
+就䏿œƒä¸­æ–·ã€‚
-複製粘帖(或者剪貼粘帖)通常ä¸èƒ½ç”¨æ–¼è£œä¸ï¼Œå› çˆ²åˆ¶è¡¨ç¬¦æœƒè½‰æ›çˆ²ç©ºæ ¼ã€‚使用xclipboard, xclip
-或者xcutsel也許å¯ä»¥ï¼Œä½†æ˜¯æœ€å¥½æ¸¬è©¦ä¸€ä¸‹æˆ–者é¿å…使用複製粘帖。
+複製粘帖(或者剪貼粘帖)通常ä¸èƒ½ç”¨æ–¼è£œä¸ï¼Œå› çˆ²è£½è¡¨ç¬¦æœƒè½‰æ›çˆ²ç©ºæ ¼ã€‚使用xclipboard,
+xclip或者xcutsel也許å¯ä»¥ï¼Œä½†æ˜¯æœ€å¥½æ¸¬è©¦ä¸€ä¸‹æˆ–者é¿å…使用複製粘帖。
-ä¸è¦åœ¨ä½¿ç”¨PGP/GPGç½²å的郵件中包å«è£œä¸ã€‚這樣會使得很多腳本ä¸èƒ½è®€å–å’Œé©ç”¨æ–¼ä½ çš„補ä¸ã€‚
-(這個å•題應該是å¯ä»¥ä¿®å¾©çš„)
+ä¸è¦åœ¨ä½¿ç”¨PGP/GPGç°½å的郵件中包å«è£œä¸ã€‚這樣會使得很多腳本ä¸èƒ½è®€å–å’Œé©ç”¨æ–¼ä½ çš„
+補ä¸ã€‚(這個å•題應該是å¯ä»¥ä¿®å¾©çš„)
在給內核郵件列表發é€è£œä¸ä¹‹å‰ï¼Œçµ¦è‡ªå·±ç™¼é€ä¸€å€‹è£œä¸æ˜¯å€‹ä¸éŒ¯çš„主æ„,ä¿å­˜æŽ¥æ”¶åˆ°çš„
郵件,將補ä¸ç”¨'patch'命令打上,如果æˆåŠŸäº†ï¼Œå†çµ¦å…§æ ¸éƒµä»¶åˆ—表發é€ã€‚
@@ -61,100 +67,135 @@ Linuxå…§æ ¸è£œä¸æ˜¯é€šéŽéƒµä»¶è¢«æäº¤çš„,最好把補ä¸ä½œçˆ²éƒµä»¶é«”çš„
一些郵件客戶端æç¤º
------------------
-這裡給出一些詳細的MUAé…ç½®æç¤ºï¼Œå¯ä»¥ç”¨æ–¼çµ¦Linux內核發é€è£œä¸ã€‚é€™äº›ä¸¦ä¸æ„味是
-所有的軟體包é…置總çµã€‚
+
+這è£çµ¦å‡ºä¸€äº›è©³ç´°çš„MUAé…ç½®æç¤ºï¼Œå¯ä»¥ç”¨æ–¼çµ¦Linux內核發é€è£œä¸ã€‚é€™äº›ä¸¦ä¸æ„味是
+所有的軟件包é…置總çµã€‚
說明:
-TUI = 以文本爲基礎的用戶接å£
-GUI = 圖形界é¢ç”¨æˆ¶æŽ¥å£
+
+- TUI = 以文本爲基礎的用戶接å£
+- GUI = 圖形界é¢ç”¨æˆ¶æŽ¥å£
Alpine (TUI)
-~~~~~~~~~~~~
+************
é…ç½®é¸é …:
-在"Sending Preferences"部分:
-- "Do Not Send Flowed Text"必須開啓
-- "Strip Whitespace Before Sending"必須關閉
+在 :menuselection:`Sending Preferences` èœå–®ï¼š
+
+- :menuselection:`Do Not Send Flowed Text` 必須開啓
+- :menuselection:`Strip Whitespace Before Sending` 必須關閉
+
+ç•¶å¯«éƒµä»¶æ™‚ï¼Œå…‰æ¨™æ‡‰è©²æ”¾åœ¨è£œä¸æœƒå‡ºç¾çš„地方,然後按下 :kbd:`CTRL-R` 組åˆéµï¼Œä½¿æŒ‡
+å®šçš„è£œä¸æ–‡ä»¶åµŒå…¥åˆ°éƒµä»¶ä¸­ã€‚
-ç•¶å¯«éƒµä»¶æ™‚ï¼Œå…‰æ¨™æ‡‰è©²æ”¾åœ¨è£œä¸æœƒå‡ºç¾çš„地方,然後按下CTRL-R組åˆéµï¼Œä½¿æŒ‡å®šçš„
-è£œä¸æ–‡ä»¶åµŒå…¥åˆ°éƒµä»¶ä¸­ã€‚
+Claws Mail (GUI)
+****************
+
+å¯ä»¥ç”¨ï¼Œæœ‰äººç”¨å®ƒæˆåŠŸåœ°ç™¼éŽè£œä¸ã€‚
+
+用 :menuselection:`Message-->Insert File` (:kbd:`CTRL-I`) 或外置編輯器æ’入補ä¸ã€‚
+
+è‹¥è¦åœ¨Claws編輯窗å£é‡ä¿®æ”¹æ’入的補ä¸ï¼Œéœ€é—œé–‰
+:menuselection:`Configuration-->Preferences-->Compose-->Wrapping`
+的 `Auto wrapping` 。
Evolution (GUI)
-~~~~~~~~~~~~~~~
+***************
-一些開發者æˆåŠŸçš„ä½¿ç”¨å®ƒç™¼é€è£œä¸
+一些開發者æˆåŠŸçš„ä½¿ç”¨å®ƒç™¼é€è£œä¸ã€‚
-ç•¶é¸æ“‡éƒµä»¶é¸é …:Preformat
- 從Format->Heading->Preformatted (Ctrl-7)或者工具欄
+撰寫郵件時:
+從 :menuselection:`æ ¼å¼-->æ®µè½æ¨£å¼-->é æ ¼å¼åŒ–` (:kbd:`CTRL-7`)
+æˆ–å·¥å…·æ¬„é¸æ“‡ :menuselection:`é æ ¼å¼åŒ–` ï¼›
然後使用:
- Insert->Text File... (Alt-n x)æ’å…¥è£œä¸æ–‡ä»¶ã€‚
+:menuselection:`æ’å…¥-->文本文件...` (:kbd:`ALT-N x`) æ’å…¥è£œä¸æ–‡ä»¶ã€‚
-ä½ é‚„å¯ä»¥"diff -Nru old.c new.c | xclip"ï¼Œé¸æ“‡Preformat,然後使用中間éµé€²è¡Œç²˜å¸–。
+ä½ é‚„å¯ä»¥ ``diff -Nru old.c new.c | xclip`` ï¼Œé¸æ“‡ :menuselection:`é æ ¼å¼åŒ–` ,
+然後使用鼠標中éµé€²è¡Œç²˜å¸–。
Kmail (GUI)
-~~~~~~~~~~~
+***********
一些開發者æˆåŠŸçš„ä½¿ç”¨å®ƒç™¼é€è£œä¸ã€‚
-默èªè¨­ç½®ä¸çˆ²HTMLæ ¼å¼æ˜¯åˆé©çš„ï¼›ä¸è¦å•“用它。
+é»˜èªæ’°å¯«è¨­ç½®ç¦ç”¨HTMLæ ¼å¼æ˜¯åˆé©çš„ï¼›ä¸è¦å•“用它。
+
+當書寫一å°éƒµä»¶çš„æ™‚候,在é¸é …下é¢ä¸è¦é¸æ“‡è‡ªå‹•æ›è¡Œã€‚唯一的缺點就是你在郵件中輸
+å…¥çš„ä»»ä½•æ–‡æœ¬éƒ½ä¸æœƒè¢«è‡ªå‹•æ›è¡Œï¼Œå› æ­¤ä½ å¿…須在發é€è£œä¸ä¹‹å‰æ‰‹å‹•æ›è¡Œã€‚最簡單的方法
+就是啓用自動æ›è¡Œä¾†æ›¸å¯«éƒµä»¶ï¼Œç„¶å¾ŒæŠŠå®ƒä¿å­˜çˆ²è‰ç¨¿ã€‚一旦你在è‰ç¨¿ä¸­å†æ¬¡æ‰“開它,它
+已經全部自動æ›è¡Œäº†ï¼Œé‚£éº¼ä½ çš„éƒµä»¶é›–ç„¶æ²’æœ‰é¸æ“‡è‡ªå‹•æ›è¡Œï¼Œä½†æ˜¯é‚„䏿œƒå¤±åŽ»å·²æœ‰çš„è‡ª
+å‹•æ›è¡Œã€‚
-當書寫一å°éƒµä»¶çš„æ™‚候,在é¸é …下é¢ä¸è¦é¸æ“‡è‡ªå‹•æ›è¡Œã€‚唯一的缺點就是你在郵件中輸入的任何文本
-éƒ½ä¸æœƒè¢«è‡ªå‹•æ›è¡Œï¼Œå› æ­¤ä½ å¿…須在發é€è£œä¸ä¹‹å‰æ‰‹å‹•æ›è¡Œã€‚最簡單的方法就是啓用自動æ›è¡Œä¾†æ›¸å¯«éƒµä»¶ï¼Œ
-然後把它ä¿å­˜çˆ²è‰ç¨¿ã€‚一旦你在è‰ç¨¿ä¸­å†æ¬¡æ‰“開它,它已經全部自動æ›è¡Œäº†ï¼Œé‚£éº¼ä½ çš„郵件雖然沒有
-鏿“‡è‡ªå‹•æ›è¡Œï¼Œä½†æ˜¯é‚„䏿œƒå¤±åŽ»å·²æœ‰çš„è‡ªå‹•æ›è¡Œã€‚
+在郵件的底部,æ’入補ä¸ä¹‹å‰ï¼Œæ”¾ä¸Šå¸¸ç”¨çš„補ä¸å®šç•Œç¬¦ï¼šä¸‰å€‹é€£å­—符(``---``)。
-在郵件的底部,æ’入補ä¸ä¹‹å‰ï¼Œæ”¾ä¸Šå¸¸ç”¨çš„補ä¸å®šç•Œç¬¦ï¼šä¸‰å€‹é€£å­—號(---)。
+然後在 :menuselection:`ä¿¡ä»¶` èœå–®ï¼Œé¸æ“‡ :menuselection:`æ’入文本文件` ,接
+ç€é¸å–ä½ çš„è£œä¸æ–‡ä»¶ã€‚還有一個é¡å¤–çš„é¸é …,你å¯ä»¥é€šéŽå®ƒé…置你的創建新郵件工具欄,
+加上 :menuselection:`æ’入文本文件` 圖標。
-然後在"Message"èœå–®æ¢ç›®ï¼Œé¸æ“‡æ’入文件,接著é¸å–ä½ çš„è£œä¸æ–‡ä»¶ã€‚還有一個é¡å¤–çš„é¸é …,你å¯ä»¥
-通éŽå®ƒé…置你的郵件建立工具欄èœå–®ï¼Œé‚„å¯ä»¥å¸¶ä¸Š"insert file"圖標。
+å°‡ç·¨è¼¯å™¨çª—å£æ‹‰åˆ°è¶³å¤ å¯¬é¿å…æŠ˜è¡Œã€‚å°æ–¼KMail 1.13.5 (KDE 4.5.4),它會在發é€éƒµä»¶
+時å°ç·¨è¼¯å™¨çª—å£ä¸­é¡¯ç¤ºæŠ˜è¡Œçš„地方自動æ›è¡Œã€‚在é¸é …èœå–®ä¸­å–消自動æ›è¡Œä»ä¸èƒ½è§£æ±ºã€‚
+因此,如果你的補ä¸ä¸­æœ‰éžå¸¸é•·çš„行,必須在發é€ä¹‹å‰æŠŠç·¨è¼¯å™¨çª—壿‹‰å¾—éžå¸¸å¯¬ã€‚
+åƒè¦‹ï¼šhttps://bugs.kde.org/show_bug.cgi?id=174034
-ä½ å¯ä»¥å®‰å…¨åœ°é€šéŽGPGæ¨™è¨˜é™„ä»¶ï¼Œä½†æ˜¯å…§åµŒè£œä¸æœ€å¥½ä¸è¦ä½¿ç”¨GPG標記它們。作爲內嵌文本的簽發補ä¸ï¼Œ
-當從GPG中æå–7ä½ç·¨ç¢¼æ™‚會使他們變的更加複雜。
+ä½ å¯ä»¥å®‰å…¨åœ°ç”¨GPGç°½åé™„ä»¶ï¼Œä½†æ˜¯å…§åµŒè£œä¸æœ€å¥½ä¸è¦ä½¿ç”¨GPGç°½å它們。作爲內嵌文本
+æ’入的簽å補ä¸å°‡ä½¿å…¶é›£ä»¥å¾ž7-bit編碼中æå–。
-如果你éžè¦ä»¥é™„件的形å¼ç™¼é€è£œä¸ï¼Œé‚£éº¼å°±å³éµé»žæ“Šé™„件,然後é¸ä¸­å±¬æ€§ï¼Œçªå‡º"Suggest automatic
-display",這樣內嵌附件更容易讓讀者看到。
+如果你éžè¦ä»¥é™„件的形å¼ç™¼é€è£œä¸ï¼Œé‚£éº¼å°±å³éµé»žæ“Šé™„ä»¶ï¼Œç„¶å¾Œé¸æ“‡
+:menuselection:`屬性` ,打開 :menuselection:`建議自動顯示` ï¼Œä½¿é™„ä»¶å…§è¯æ›´å®¹
+易讓讀者看到。
-ç•¶ä½ è¦ä¿å­˜å°‡è¦ç™¼é€çš„內嵌文本補ä¸ï¼Œä½ å¯ä»¥å¾žæ¶ˆæ¯åˆ—è¡¨çª—æ ¼é¸æ“‡åŒ…å«è£œä¸çš„éƒµä»¶ï¼Œç„¶å¾Œå³æ“Šé¸æ“‡
-"save as"。你å¯ä»¥ä½¿ç”¨ä¸€å€‹æ²’有更改的包å«è£œä¸çš„郵件,如果它是以正確的形å¼çµ„æˆã€‚當你正真在它
-自己的窗å£ä¹‹ä¸‹å¯Ÿçœ‹ï¼Œé‚£æ™‚沒有é¸é …å¯ä»¥ä¿å­˜éƒµä»¶--已經有一個這樣的bug被匯報到了kmailçš„bugzilla
-並且希望這將會被處ç†ã€‚郵件是以åªé‡å°æŸå€‹ç”¨æˆ¶å¯è®€å¯«çš„æ¬Šé™è¢«ä¿å­˜çš„,所以如果你想把郵件複製到其他地方,
-ä½ ä¸å¾—ä¸æŠŠä»–å€‘çš„æ¬Šé™æ”¹çˆ²çµ„或者整體å¯è®€ã€‚
+ç•¶ä½ è¦ä¿å­˜å°‡è¦ç™¼é€çš„內嵌文本補ä¸ï¼Œä½ å¯ä»¥å¾žæ¶ˆæ¯åˆ—è¡¨çª—æ ¼é¸æ“‡åŒ…å«è£œä¸çš„郵件,然
+後å³éµé¸æ“‡ :menuselection:`å¦å­˜çˆ²` 。如果整個電å­éƒµä»¶çš„çµ„æˆæ­£ç¢ºï¼Œæ‚¨å¯ç›´æŽ¥å°‡
+其作爲補ä¸ä½¿ç”¨ã€‚é›»å­éƒµä»¶ä»¥ç•¶å‰ç”¨æˆ¶å¯è®€å¯«æ¬Šé™ä¿å­˜ï¼Œå› æ­¤æ‚¨å¿…é ˆ ``chmod`` ,以
+使其在複製到別處時用戶組和其他人å¯è®€ã€‚
Lotus Notes (GUI)
-~~~~~~~~~~~~~~~~~
+*****************
ä¸è¦ä½¿ç”¨å®ƒã€‚
+IBM Verse (Web GUI)
+*******************
+
+åŒä¸Šæ¢ã€‚
+
Mutt (TUI)
-~~~~~~~~~~
+**********
-很多Linux開發人員使用mutt客戶端,所以證明它肯定工作的éžå¸¸æ¼‚亮。
+很多Linux開發人員使用mutt客戶端,這證明它肯定工作得éžå¸¸æ¼‚亮。
-Muttä¸è‡ªå¸¶ç·¨è¼¯å™¨ï¼Œæ‰€ä»¥ä¸ç®¡ä½ ä½¿ç”¨ä»€éº¼ç·¨è¼¯å™¨éƒ½ä¸æ‡‰è©²å¸¶æœ‰è‡ªå‹•斷行。大多數編輯器都帶有
-一個"insert file"é¸é …,它å¯ä»¥é€šéŽä¸æ”¹è®Šæ–‡ä»¶å…§å®¹çš„æ–¹å¼æ’入文件。
+Muttä¸è‡ªå¸¶ç·¨è¼¯å™¨ï¼Œæ‰€ä»¥ä¸ç®¡ä½ ä½¿ç”¨ä»€éº¼ç·¨è¼¯å™¨ï¼Œä¸è‡ªå‹•斷行就行。大多數編輯器都有
+:menuselection:`æ’入文件` é¸é …,它å¯ä»¥åœ¨ä¸æ”¹è®Šæ–‡ä»¶å…§å®¹çš„æƒ…æ³ä¸‹æ’入文件。
+
+用 ``vim`` 作爲mutt的編輯器::
-'vim'作爲mutt的編輯器:
set editor="vi"
- 如果使用xclip,敲入以下命令
+如果使用xclip,敲入以下命令::
+
:set paste
- 按中éµä¹‹å‰æˆ–者shift-insert或者使用
+
+ç„¶å¾Œå†æŒ‰ä¸­éµæˆ–者shift-insert或者使用::
+
:r filename
-å¦‚æžœæƒ³è¦æŠŠè£œä¸ä½œçˆ²å…§åµŒæ–‡æœ¬ã€‚
-(a)ttach工作的很好,ä¸å¸¶æœ‰"set paste"。
+æŠŠè£œä¸æ’入爲內嵌文本。
+在未設置 ``set paste`` 時(a)ttach工作的很好。
ä½ å¯ä»¥é€šéŽ ``git format-patch`` 生æˆè£œä¸ï¼Œç„¶å¾Œç”¨ Mutt發é€å®ƒå€‘::
- $ mutt -H 0001-some-bug-fix.patch
+ $ mutt -H 0001-some-bug-fix.patch
é…ç½®é¸é …:
+
它應該以默èªè¨­ç½®çš„å½¢å¼å·¥ä½œã€‚
-然而,把"send_charset"設置爲"us-ascii::utf-8"也是一個ä¸éŒ¯çš„主æ„。
+然而,把 ``send_charset`` 設置一下也是一個ä¸éŒ¯çš„主æ„::
-Mutt 是高度å¯é…置的。 這裡是個使用mutté€šéŽ Gmail 發é€çš„補ä¸çš„æœ€å°é…ç½®::
+ set send_charset="us-ascii:utf-8"
+
+Mutt 是高度å¯é…置的。 é€™è£æ˜¯å€‹ä½¿ç”¨mutté€šéŽ Gmail 發é€çš„補ä¸çš„æœ€å°é…ç½®::
# .muttrc
# ================ IMAP ====================
@@ -181,72 +222,108 @@ Mutt 是高度å¯é…置的。 這裡是個使用mutté€šéŽ Gmail 發é€çš„補ä¸
set from = "username@gmail.com"
set use_from = yes
-Muttæ–‡æª”å«æœ‰æ›´å¤šä¿¡æ¯:
+Muttæ–‡æª”å«æœ‰æ›´å¤šä¿¡æ¯ï¼š
- http://dev.mutt.org/trac/wiki/UseCases/Gmail
+ https://gitlab.com/muttmua/mutt/-/wikis/UseCases/Gmail
- http://dev.mutt.org/doc/manual.html
+ http://www.mutt.org/doc/manual/
Pine (TUI)
-~~~~~~~~~~
+**********
PineéŽåŽ»æœ‰ä¸€äº›ç©ºæ ¼åˆªæ¸›å•題,但是這些ç¾åœ¨æ‡‰è©²éƒ½è¢«ä¿®å¾©äº†ã€‚
-如果å¯ä»¥ï¼Œè«‹ä½¿ç”¨alpine(pine的繼承者)
+如果å¯ä»¥ï¼Œè«‹ä½¿ç”¨alpine(pine的繼承者)。
é…ç½®é¸é …:
-- æœ€è¿‘çš„ç‰ˆæœ¬éœ€è¦æ¶ˆé™¤æµç¨‹æ–‡æœ¬
-- "no-strip-whitespace-before-send"é¸é …也是需è¦çš„。
+
+- æœ€è¿‘çš„ç‰ˆæœ¬éœ€è¦ ``quell-flowed-text``
+- ``no-strip-whitespace-before-send`` é¸é …也是需è¦çš„。
Sylpheed (GUI)
-~~~~~~~~~~~~~~
+**************
- 內嵌文本å¯ä»¥å¾ˆå¥½çš„工作(或者使用附件)。
- å…許使用外部的編輯器。
-- å°æ–¼ç›®éŒ„較多時éžå¸¸æ…¢ã€‚
+- 收件箱較多時éžå¸¸æ…¢ã€‚
- 如果通éŽnon-SSL連接,無法使用TLS SMTP授權。
-- 在組æˆçª—å£ä¸­æœ‰ä¸€å€‹å¾ˆæœ‰ç”¨çš„ruler bar。
-- çµ¦åœ°å€æœ¬ä¸­æ·»åŠ åœ°å€å°±ä¸æœƒæ­£ç¢ºçš„了解顯示å。
+- 撰寫窗å£çš„æ¨™å°ºå¾ˆæœ‰ç”¨ã€‚
+- å°‡åœ°å€æ·»åŠ åˆ°é€šè¨Šç°¿æ™‚ç„¡æ³•æ­£ç¢ºç†è§£é¡¯ç¤ºçš„å稱。
Thunderbird (GUI)
-~~~~~~~~~~~~~~~~~
+*****************
+
+Thunderbird是Outlook的克隆版本,它很容易æå£žæ–‡æœ¬ï¼Œä½†ä¹Ÿæœ‰ä¸€äº›æ–¹æ³•強制修正。
+
+在完æˆä¿®æ”¹å¾Œï¼ˆåŒ…æ‹¬å®‰è£æ“´å±•),您需è¦é‡æ–°å•“å‹•Thunderbird。
+
+- å…許使用外部編輯器:
+
+ 使用Thunderbirdç™¼è£œä¸æœ€ç°¡å–®çš„æ–¹æ³•是使用擴展來打開您最喜歡的外部編輯器。
+
+ 䏋颿˜¯ä¸€äº›èƒ½å¤ åšåˆ°é€™ä¸€é»žçš„æ“´å±•樣例。
+
+ - “External Editor Revivedâ€
+
+ https://github.com/Frederick888/external-editor-revived
+
+ https://addons.thunderbird.net/en-GB/thunderbird/addon/external-editor-revived/
+
+ 它需è¦å®‰è£â€œæœ¬åœ°æ¶ˆæ¯ä¸»æ©Ÿï¼ˆnative messaging host)â€ã€‚
+ åƒè¦‹ä»¥ä¸‹æ–‡æª”:
+ https://github.com/Frederick888/external-editor-revived/wiki
+
+ - “External Editorâ€
+
+ https://github.com/exteditor/exteditor
+
+ ä¸‹è¼‰ä¸¦å®‰è£æ­¤æ“´å±•,然後打開 :menuselection:`新建消æ¯` 窗å£, 用
+ :menuselection:`查看-->工具欄-->自定義...` 給它增加一個按鈕,直接點擊此
+ 按鈕å³å¯ä½¿ç”¨å¤–置編輯器。
+
+ 請注æ„,“External Editorâ€è¦æ±‚你的編輯器ä¸èƒ½fork,æ›å¥è©±èªªï¼Œç·¨è¼¯å™¨å¿…須在
+ 關閉å‰ä¸è¿”回。你å¯èƒ½éœ€è¦å‚³éžé¡å¤–çš„åƒæ•¸æˆ–修改編輯器設置。最值得注æ„的是,
+ 如果您使用的是gvim,那麼您必須將 :menuselection:`external editor` 設置的
+ 編輯器字段設置爲 ``/usr/bin/gvim --nofork"`` (å‡è¨­å¯åŸ·è¡Œæ–‡ä»¶åœ¨
+ ``/usr/bin`` ï¼‰ï¼Œä»¥å‚³éž ``-f`` åƒæ•¸ã€‚如果您正在使用其他編輯器,請閱讀其
+ 手冊瞭解如何處ç†ã€‚
-é»˜èªæƒ…æ³ä¸‹ï¼Œthunderbird很容易æå£žæ–‡æœ¬ï¼Œä½†æ˜¯é‚„有一些方法å¯ä»¥å¼·åˆ¶å®ƒè®Šå¾—更好。
+è‹¥è¦ä¿®æ­£å…§éƒ¨ç·¨è¼¯å™¨ï¼Œè«‹åŸ·è¡Œä»¥ä¸‹æ“作:
-- 在用戶帳號設置里,組æˆå’Œå°‹å€ï¼Œä¸è¦é¸æ“‡"Compose messages in HTML format"。
+- 修改你的Thunderbird設置,ä¸è¦ä½¿ç”¨ ``format=flowed`` ï¼
+ 回到主窗å£ï¼ŒæŒ‰ç…§
+ :menuselection:`主èœå–®-->首é¸é …-->常è¦-->é…置編輯器...`
+ 打開Thunderbirdçš„é…置編輯器。
-- 編輯你的Thunderbirdé…置設置來使它ä¸è¦æ‹†è¡Œä½¿ç”¨ï¼šuser_pref("mailnews.wraplength", 0);
+ - 將 ``mailnews.send_plaintext_flowed`` 設爲 ``false``
-- 編輯你的Thunderbirdé…置設置,使它ä¸è¦ä½¿ç”¨"format=flowed"æ ¼å¼ï¼šuser_pref("mailnews.
- send_plaintext_flowed", false);
+ - 將 ``mailnews.wraplength`` 從 ``72`` 改爲 ``0``
-- 你需è¦ä½¿Thunderbird變爲é å…ˆæ ¼å¼æ–¹å¼ï¼š
- å¦‚æžœé»˜èªæƒ…æ³ä¸‹ä½ æ›¸å¯«çš„æ˜¯HTMLæ ¼å¼ï¼Œé‚£ä¸æ˜¯å¾ˆé›£ã€‚åƒ…åƒ…å¾žæ¨™é¡Œæ¬„çš„ä¸‹æ‹‰æ¡†ä¸­é¸æ“‡"Preformat"æ ¼å¼ã€‚
- å¦‚æžœé»˜èªæƒ…æ³ä¸‹ä½ æ›¸å¯«çš„æ˜¯æ–‡æœ¬æ ¼å¼ï¼Œä½ ä¸å¾—把它改爲HTMLæ ¼å¼ï¼ˆåƒ…僅作爲一次性的)來書寫新的消æ¯ï¼Œ
- 然後強制使它回到文本格å¼ï¼Œå¦å‰‡å®ƒå°±æœƒæ‹†è¡Œã€‚è¦å¯¦ç¾å®ƒï¼Œåœ¨å¯«ä¿¡çš„圖標上使用shiftéµä¾†ä½¿å®ƒè®Šçˆ²HTML
- æ ¼å¼ï¼Œç„¶å¾Œæ¨™é¡Œæ¬„çš„ä¸‹æ‹‰æ¡†ä¸­é¸æ“‡"Preformat"æ ¼å¼ã€‚
+- ä¸è¦å¯«HTML郵件ï¼
+ 回到主窗å£ï¼Œæ‰“é–‹
+ :menuselection:`主èœå–®-->賬戶設置-->ä½ çš„@郵件.地å€-->通訊錄/編寫&地å€ç°¿` ,
+ 關掉 ``以HTMLæ ¼å¼ç·¨å¯«æ¶ˆæ¯`` 。
-- å…許使用外部的編輯器:
- é‡å°Thunderbirdæ‰“è£œä¸æœ€ç°¡å–®çš„æ–¹æ³•就是使用一個"external editor"擴展,然後使用你最喜歡的
- $EDITORä¾†è®€å–æˆ–者åˆä½µè£œä¸åˆ°æ–‡æœ¬ä¸­ã€‚è¦å¯¦ç¾å®ƒï¼Œå¯ä»¥ä¸‹è¼‰ä¸¦ä¸”安è£é€™å€‹æ“´å±•,然後添加一個使用它的
- 按éµView->Toolbars->Customize...最後當你書寫信æ¯çš„æ™‚候僅僅點擊它就å¯ä»¥äº†ã€‚
+- åªç”¨ç´”æ–‡æœ¬æ ¼å¼æŸ¥çœ‹éƒµä»¶ï¼
+ 回到主窗å£ï¼Œ :menuselection:`主èœå–®-->查看-->消æ¯é«”爲-->純文本` ï¼
TkRat (GUI)
-~~~~~~~~~~~
+***********
å¯ä»¥ä½¿ç”¨å®ƒã€‚使用"Insert file..."或者外部的編輯器。
Gmail (Web GUI)
-~~~~~~~~~~~~~~~
+***************
ä¸è¦ä½¿ç”¨å®ƒç™¼é€è£œä¸ã€‚
-Gmailç¶²é å®¢æˆ¶ç«¯è‡ªå‹•地把制表符轉æ›çˆ²ç©ºæ ¼ã€‚
+Gmailç¶²é å®¢æˆ¶ç«¯è‡ªå‹•地把製表符轉æ›çˆ²ç©ºæ ¼ã€‚
-雖然制表符轉æ›çˆ²ç©ºæ ¼å•題å¯ä»¥è¢«å¤–éƒ¨ç·¨è¼¯å™¨è§£æ±ºï¼ŒåŒæ™‚它還會使用回車æ›è¡ŒæŠŠæ¯è¡Œæ‹†åˆ†çˆ²78個字符。
+雖然製表符轉æ›çˆ²ç©ºæ ¼å•題å¯ä»¥è¢«å¤–éƒ¨ç·¨è¼¯å™¨è§£æ±ºï¼Œä½†å®ƒåŒæ™‚還會使用回車æ›è¡ŒæŠŠæ¯è¡Œ
+拆分爲78個字符。
-å¦ä¸€å€‹å•題是Gmailé‚„æœƒæŠŠä»»ä½•ä¸æ˜¯ASCIIçš„å­—ç¬¦çš„ä¿¡æ¯æ”¹çˆ²base64編碼。它把æ±è¥¿è®Šçš„åƒæ­æ´²äººçš„å字。
+å¦ä¸€å€‹å•題是Gmailé‚„æœƒæŠŠä»»ä½•å«æœ‰éžASCIIçš„å­—ç¬¦çš„æ¶ˆæ¯æ”¹ç”¨base64ç·¨ç¢¼ï¼Œå¦‚æ­æ´²äººçš„
+å字。
- ###
diff --git a/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
index 8e4db8baa0d1..b9f6ab7b6666 100644
--- a/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
+++ b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
@@ -6,17 +6,17 @@
:Translator: Alex Shi <alex.shi@linux.alibaba.com>
Hu Haowen <src.res.211@gmail.com>
-被é™åˆ¶çš„硬體å•題
+被é™åˆ¶çš„硬件å•題
================
範åœ
----
-導致安全å•題的硬體å•題與åªå½±éŸ¿Linux內核的純軟體錯誤是ä¸åŒçš„安全錯誤類別。
+導致安全å•題的硬件å•題與隻影響Linux內核的純軟件錯誤是ä¸åŒçš„安全錯誤類別。
-å¿…é ˆå€åˆ¥å°å¾…諸如熔毀(Meltdown)ã€Spectreã€L1TF等硬體å•題,因爲它們通常會影響
-所有作業系統(「OSã€ï¼‰ï¼Œå› æ­¤éœ€è¦åœ¨ä¸åŒçš„OS供應商ã€ç™¼è¡Œç‰ˆã€ç¡¬é«”ä¾›æ‡‰å•†å’Œå…¶ä»–å„æ–¹
-之間進行å”èª¿ã€‚å°æ–¼æŸäº›å•題,軟體緩解å¯èƒ½ä¾è³´æ–¼å¾®ç¢¼æˆ–固件更新,這需è¦é€²ä¸€æ­¥çš„
+å¿…é ˆå€åˆ¥å°å¾…諸如熔燬(Meltdown)ã€Spectreã€L1TF等硬件å•題,因爲它們通常會影響
+所有æ“作系統(“OSâ€ï¼‰ï¼Œå› æ­¤éœ€è¦åœ¨ä¸åŒçš„OS供應商ã€ç™¼è¡Œç‰ˆã€ç¡¬ä»¶ä¾›æ‡‰å•†å’Œå…¶ä»–儿–¹
+之間進行å”èª¿ã€‚å°æ–¼æŸäº›å•題,軟件緩解å¯èƒ½ä¾è³´æ–¼å¾®ç¢¼æˆ–固件更新,這需è¦é€²ä¸€æ­¥çš„
å”調。
.. _tw_Contact:
@@ -24,9 +24,9 @@
接觸
----
-Linux內核硬體安全å°çµ„ç¨ç«‹æ–¼æ™®é€šçš„Linux內核安全å°çµ„。
+Linux內核硬件安全å°çµ„ç¨ç«‹æ–¼æ™®é€šçš„Linux內核安全å°çµ„。
-該å°çµ„åªè² è²¬å”調被é™åˆ¶çš„硬體安全å•題。Linuxå…§æ ¸ä¸­ç´”è»Ÿé«”å®‰å…¨æ¼æ´žçš„報告ä¸ç”±è©²
+該å°çµ„åªè² è²¬å”調被é™åˆ¶çš„硬件安全å•題。Linuxå…§æ ¸ä¸­ç´”è»Ÿä»¶å®‰å…¨æ¼æ´žçš„報告ä¸ç”±è©²
å°çµ„處ç†ï¼Œå ±å‘Šè€…將被引導至常è¦Linux內核安全å°çµ„(:ref:`Documentation/admin-guide/
<securitybugs>`)è¯ç¹«ã€‚
@@ -37,13 +37,13 @@ Linux內核硬體安全å°çµ„ç¨ç«‹æ–¼æ™®é€šçš„Linux內核安全å°çµ„。
者的PGP密鑰或S/MIME證書籤å。該列表的PGP密鑰和S/MIME證書å¯å¾ž
https://www.kernel.org/.... ç²å¾—。
-雖然硬體安全å•題通常由å—影響的硬體供應商處ç†ï¼Œä½†æˆ‘å€‘æ­¡è¿Žç™¼ç¾æ½›åœ¨ç¡¬é«”缺陷的研究
+雖然硬件安全å•題通常由å—影響的硬件供應商處ç†ï¼Œä½†æˆ‘å€‘æ­¡è¿Žç™¼ç¾æ½›åœ¨ç¡¬ä»¶ç¼ºé™·çš„研究
人員或個人與我們è¯ç¹«ã€‚
-硬體安全官
+硬件安全官
^^^^^^^^^^
-ç›®å‰çš„硬體安全官å°çµ„:
+ç›®å‰çš„硬件安全官å°çµ„:
- Linus Torvalds(Linux基金會院士)
- Greg Kroah Hartman(Linux基金會院士)
@@ -62,50 +62,50 @@ Linux基金會目å‰çš„IT基礎設施安全總監是 Konstantin Ryabitsev。
ä¿å¯†å”è­°
--------
-Linux內核硬體安全å°çµ„䏿˜¯æ­£å¼çš„æ©Ÿæ§‹ï¼Œå› æ­¤ç„¡æ³•簽訂任何ä¿å¯†å”è­°ã€‚æ ¸å¿ƒç¤¾å€æ„識到
+Linux內核硬件安全å°çµ„䏿˜¯æ­£å¼çš„æ©Ÿæ§‹ï¼Œå› æ­¤ç„¡æ³•簽訂任何ä¿å¯†å”è­°ã€‚æ ¸å¿ƒç¤¾å€æ„識到
這些å•é¡Œçš„æ•æ„Ÿæ€§ï¼Œä¸¦æä¾›äº†ä¸€ä»½è«’解備忘錄。
諒解備忘錄
----------
-Linuxå…§æ ¸ç¤¾å€æ·±åˆ»ç†è§£åœ¨ä¸åŒä½œæ¥­ç³»çµ±ä¾›æ‡‰å•†ã€ç™¼è¡Œå•†ã€ç¡¬é«”ä¾›æ‡‰å•†å’Œå…¶ä»–å„æ–¹ä¹‹é–“
-進行å”èª¿æ™‚ï¼Œä¿æŒç¡¬é«”安全å•題處於é™åˆ¶ç‹€æ…‹çš„è¦æ±‚。
+Linuxå…§æ ¸ç¤¾å€æ·±åˆ»ç†è§£åœ¨ä¸åŒæ“作系統供應商ã€ç™¼è¡Œå•†ã€ç¡¬ä»¶ä¾›æ‡‰å•†å’Œå…¶ä»–儿–¹ä¹‹é–“
+進行å”èª¿æ™‚ï¼Œä¿æŒç¡¬ä»¶å®‰å…¨å•題處於é™åˆ¶ç‹€æ…‹çš„è¦æ±‚。
-Linux內核社å€åœ¨éŽåŽ»å·²ç¶“æˆåŠŸåœ°è™•ç†äº†ç¡¬é«”安全å•題,並且有必è¦çš„æ©Ÿåˆ¶å…許在é™åˆ¶
+Linux內核社å€åœ¨éŽåŽ»å·²ç¶“æˆåŠŸåœ°è™•ç†äº†ç¡¬ä»¶å®‰å…¨å•題,並且有必è¦çš„æ©Ÿåˆ¶å…許在é™åˆ¶
é™åˆ¶ä¸‹é€²è¡Œç¬¦åˆç¤¾å€çš„開發。
-Linuxå…§æ ¸ç¤¾å€æœ‰ä¸€å€‹å°ˆé–€çš„硬體安全å°çµ„負責åˆå§‹è¯ç¹«ï¼Œä¸¦ç›£ç£åœ¨é™åˆ¶è¦å‰‡ä¸‹è™•ç†
+Linuxå…§æ ¸ç¤¾å€æœ‰ä¸€å€‹å°ˆé–€çš„硬件安全å°çµ„負責åˆå§‹è¯ç¹«ï¼Œä¸¦ç›£ç£åœ¨é™åˆ¶è¦å‰‡ä¸‹è™•ç†
此類å•題的éŽç¨‹ã€‚
-硬體安全å°çµ„確定開發人員(領域專家),他們將組æˆç‰¹å®šå•題的åˆå§‹éŸ¿æ‡‰å°çµ„。最åˆ
+硬件安全å°çµ„確定開發人員(領域專家),他們將組æˆç‰¹å®šå•題的åˆå§‹éŸ¿æ‡‰å°çµ„。最åˆ
的響應å°çµ„å¯ä»¥å¼•入更多的開發人員(領域專家)以最佳的技術方å¼è§£æ±ºé€™å€‹å•題。
所有相關開發商承諾éµå®ˆé™åˆ¶è¦å®šï¼Œä¸¦å°æ”¶åˆ°çš„ä¿¡æ¯ä¿å¯†ã€‚é•忉¿è«¾å°‡å°Žè‡´ç«‹å³å¾žç•¶å‰
-å•題中排除,並從所有相關郵件列表中刪除。此外,硬體安全å°çµ„還將把é•å者排除在
+å•題中排除,並從所有相關郵件列表中刪除。此外,硬件安全å°çµ„還將把é•å者排除在
未來的å•é¡Œä¹‹å¤–ã€‚é€™ä¸€å¾Œæžœçš„å½±éŸ¿åœ¨æˆ‘å€‘ç¤¾å€æ˜¯ä¸€ç¨®éžå¸¸æœ‰æ•ˆçš„卿‡¾ã€‚如果發生é•è¦
-情æ³ï¼Œç¡¬é«”安全å°çµ„將立å³é€šçŸ¥ç›¸é—œæ–¹ã€‚å¦‚æžœæ‚¨æˆ–ä»»ä½•äººç™¼ç¾æ½›åœ¨çš„é•è¦è¡Œçˆ²ï¼Œè«‹ç«‹å³
-å‘硬體安全人員報告。
+情æ³ï¼Œç¡¬ä»¶å®‰å…¨å°çµ„將立å³é€šçŸ¥ç›¸é—œæ–¹ã€‚å¦‚æžœæ‚¨æˆ–ä»»ä½•äººç™¼ç¾æ½›åœ¨çš„é•è¦è¡Œçˆ²ï¼Œè«‹ç«‹å³
+å‘硬件安全人員報告。
æµç¨‹
^^^^
-由於Linux內核開發的全çƒåˆ†å¸ƒå¼ç‰¹æ€§ï¼Œé¢å°é¢çš„æœƒè­°å¹¾ä¹Žä¸å¯èƒ½è§£æ±ºç¡¬é«”安全å•題。
+由於Linux內核開發的全çƒåˆ†ä½ˆå¼ç‰¹æ€§ï¼Œé¢å°é¢çš„æœƒè­°å¹¾ä¹Žä¸å¯èƒ½è§£æ±ºç¡¬ä»¶å®‰å…¨å•題。
由於時å€å’Œå…¶ä»–因素,電話會議很難å”調,åªèƒ½åœ¨çµ•å°å¿…è¦æ™‚使用。加密電å­éƒµä»¶å·²è¢«
證明是解決此類å•題的最有效和最安全的通信方法。
開始披露
""""""""
-披露內容首先通éŽé›»å­éƒµä»¶è¯ç¹«Linux內核硬體安全å°çµ„。此åˆå§‹è¯ç¹«äººæ‡‰åŒ…å«å•題的
-æè¿°å’Œä»»ä½•已知å—影響硬體的列表。如果您的組織製造或分發å—影響的硬體,我們建議
-您也考慮哪些其他硬體å¯èƒ½æœƒå—到影響。
+披露內容首先通éŽé›»å­éƒµä»¶è¯ç¹«Linux內核硬件安全å°çµ„。此åˆå§‹è¯ç¹«äººæ‡‰åŒ…å«å•題的
+æè¿°å’Œä»»ä½•已知å—影響硬件的列表。如果您的組織製造或分發å—影響的硬件,我們建議
+您也考慮哪些其他硬件å¯èƒ½æœƒå—到影響。
-硬體安全å°çµ„å°‡æä¾›ä¸€å€‹ç‰¹å®šæ–¼äº‹ä»¶çš„åŠ å¯†éƒµä»¶åˆ—è¡¨ï¼Œç”¨æ–¼èˆ‡å ±å‘Šè€…é€²è¡Œåˆæ­¥è¨Žè«–ã€
+硬件安全å°çµ„å°‡æä¾›ä¸€å€‹ç‰¹å®šæ–¼äº‹ä»¶çš„åŠ å¯†éƒµä»¶åˆ—è¡¨ï¼Œç”¨æ–¼èˆ‡å ±å‘Šè€…é€²è¡Œåˆæ­¥è¨Žè«–ã€
進一步披露和å”調。
-硬體安全å°çµ„å°‡å‘æŠ«éœ²æ–¹æä¾›ä¸€ä»½é–‹ç™¼äººå“¡ï¼ˆé ˜åŸŸå°ˆå®¶ï¼‰å單,在與開發人員確èªä»–們
+硬件安全å°çµ„å°‡å‘æŠ«éœ²æ–¹æä¾›ä¸€ä»½é–‹ç™¼äººå“¡ï¼ˆé ˜åŸŸå°ˆå®¶ï¼‰å單,在與開發人員確èªä»–們
å°‡éµå®ˆæœ¬è«’解備忘錄和文件化æµç¨‹å¾Œï¼Œæ‡‰é¦–先告知開發人員有關該å•題的信æ¯ã€‚這些開發
-人員組æˆåˆå§‹éŸ¿æ‡‰å°çµ„,並在åˆå§‹æŽ¥è§¸å¾Œè² è²¬è™•ç†å•題。硬體安全å°çµ„支æŒéŸ¿æ‡‰å°çµ„,
+人員組æˆåˆå§‹éŸ¿æ‡‰å°çµ„,並在åˆå§‹æŽ¥è§¸å¾Œè² è²¬è™•ç†å•題。硬件安全å°çµ„支æŒéŸ¿æ‡‰å°çµ„,
但ä¸ä¸€å®šåƒèˆ‡ç·©è§£é–‹ç™¼éŽç¨‹ã€‚
雖然個別開發人員å¯èƒ½é€šéŽå…¶åƒ±ä¸»å—到ä¿å¯†å”è­°çš„ä¿è­·ï¼Œä½†ä»–們ä¸èƒ½ä»¥Linux內核開發
@@ -113,7 +113,7 @@ Linuxå…§æ ¸ç¤¾å€æœ‰ä¸€å€‹å°ˆé–€çš„硬體安全å°çµ„負責åˆå§‹è¯ç¹«ï¼Œä¸¦ç›£
披露方應æä¾›å·²ç¶“或應該被告知該å•題的所有其他實體的è¯ç¹«äººå單。這有幾個目的:
- - 披露的實體列表å…許跨行業通信,例如其他作業系統供應商ã€ç¡¬é«”供應商等。
+ - 披露的實體列表å…許跨行業通信,例如其他æ“作系統供應商ã€ç¡¬ä»¶ä¾›æ‡‰å•†ç­‰ã€‚
- å¯è¯ç¹«å·²æŠ«éœ²çš„實體,指定應åƒèˆ‡ç·©è§£æŽªæ–½é–‹ç™¼çš„專家。
@@ -133,10 +133,10 @@ Linuxå…§æ ¸ç¤¾å€æœ‰ä¸€å€‹å°ˆé–€çš„硬體安全å°çµ„負責åˆå§‹è¯ç¹«ï¼Œä¸¦ç›£
åˆå§‹éŸ¿æ‡‰å°çµ„設置加密郵件列表,或在é©ç•¶çš„æƒ…æ³ä¸‹é‡æ–°ä¿®æ”¹ç¾æœ‰éƒµä»¶åˆ—表。
-使用郵件列表接近於正常的Linux開發éŽç¨‹ï¼Œä¸¦ä¸”在éŽåŽ»å·²ç¶“æˆåŠŸåœ°ç”¨æ–¼çˆ²å„種硬體安全
+使用郵件列表接近於正常的Linux開發éŽç¨‹ï¼Œä¸¦ä¸”在éŽåŽ»å·²ç¶“æˆåŠŸåœ°ç”¨æ–¼çˆ²å„種硬件安全
å•題開發緩解措施。
-郵件列表的æ“作方å¼èˆ‡æ­£å¸¸çš„Linux開發相åŒã€‚發布ã€è¨Žè«–和審查修補程åºï¼Œå¦‚æžœåŒæ„,
+郵件列表的æ“作方å¼èˆ‡æ­£å¸¸çš„Linux開發相åŒã€‚發佈ã€è¨Žè«–和審查修補程åºï¼Œå¦‚æžœåŒæ„,
則應用於éžå…¬å…±git存儲庫,åƒèˆ‡é–‹ç™¼äººå“¡åªèƒ½é€šéŽå®‰å…¨é€£æŽ¥è¨ªå•該存儲庫。存儲庫包å«
é‡å°ä¸»ç·šå…§æ ¸çš„主開發分支,並根據需è¦çˆ²ç©©å®šçš„內核版本æä¾›å‘後移æ¤åˆ†æ”¯ã€‚
@@ -155,9 +155,9 @@ Linuxå…§æ ¸ç¤¾å€æœ‰ä¸€å€‹å°ˆé–€çš„硬體安全å°çµ„負責åˆå§‹è¯ç¹«ï¼Œä¸¦ç›£
""""""""
æœ‰é—œå„æ–¹å°‡å”商é™åˆ¶çµæŸçš„æ—¥æœŸå’Œæ™‚間。此時,準備好的緩解措施集æˆåˆ°ç›¸é—œçš„內核樹中
-並發布。
+併發布。
-雖然我們ç†è§£ç¡¬é«”安全å•題需è¦å”調é™åˆ¶æ™‚間,但é™åˆ¶æ™‚間應é™åˆ¶åœ¨æ‰€æœ‰æœ‰é—œå„方制定ã€
+雖然我們ç†è§£ç¡¬ä»¶å®‰å…¨å•題需è¦å”調é™åˆ¶æ™‚間,但é™åˆ¶æ™‚間應é™åˆ¶åœ¨æ‰€æœ‰æœ‰é—œå„方制定ã€
測試和準備緩解措施所需的最短時間內。人爲地延長é™åˆ¶æ™‚間以滿足會議討論日期或其他
éžæŠ€è¡“åŽŸå› ï¼Œæœƒçµ¦ç›¸é—œçš„é–‹ç™¼äººå“¡å’ŒéŸ¿æ‡‰å°çµ„帶來了更多的工作和負擔,因爲補ä¸éœ€è¦
ä¿æŒæœ€æ–°ï¼Œä»¥ä¾¿è·Ÿè¹¤æ­£åœ¨é€²è¡Œçš„上游內核開發,這å¯èƒ½æœƒé€ æˆè¡çªçš„æ›´æ”¹ã€‚
@@ -165,7 +165,7 @@ Linuxå…§æ ¸ç¤¾å€æœ‰ä¸€å€‹å°ˆé–€çš„硬體安全å°çµ„負責åˆå§‹è¯ç¹«ï¼Œä¸¦ç›£
CVE分é…
"""""""
-硬體安全å°çµ„å’Œåˆå§‹éŸ¿æ‡‰å°çµ„都ä¸åˆ†é…CVE,開發éŽç¨‹ä¹Ÿä¸éœ€è¦CVE。如果CVE是由披露方
+硬件安全å°çµ„å’Œåˆå§‹éŸ¿æ‡‰å°çµ„都ä¸åˆ†é…CVE,開發éŽç¨‹ä¹Ÿä¸éœ€è¦CVE。如果CVE是由披露方
æä¾›çš„,則å¯ç”¨æ–¼æ–‡æª”中。
æµç¨‹å°ˆä½¿
@@ -196,22 +196,22 @@ CVE分é…
Google Kees Cook <keescook@chromium.org>
============= ========================================================
-如果è¦å°‡æ‚¨çš„組織添加到專使å單中,請與硬體安全å°çµ„è¯ç¹«ã€‚被æå的專使必須完全
+如果è¦å°‡æ‚¨çš„組織添加到專使å單中,請與硬件安全å°çµ„è¯ç¹«ã€‚被æå的專使必須完全
ç†è§£å’Œæ”¯æŒæˆ‘們的éŽç¨‹ï¼Œä¸¦ä¸”在Linux內核社å€ä¸­å¾ˆå®¹æ˜“è¯ç¹«ã€‚
加密郵件列表
------------
æˆ‘å€‘ä½¿ç”¨åŠ å¯†éƒµä»¶åˆ—è¡¨é€²è¡Œé€šä¿¡ã€‚é€™äº›åˆ—è¡¨çš„å·¥ä½œåŽŸç†æ˜¯ï¼Œç™¼é€åˆ°åˆ—表的電å­éƒµä»¶ä½¿ç”¨
-列表的PGP密鑰或列表的/MIME證書進行加密。郵件列表軟體å°é›»å­éƒµä»¶é€²è¡Œè§£å¯†ï¼Œä¸¦
+列表的PGP密鑰或列表的/MIME證書進行加密。郵件列表軟件å°é›»å­éƒµä»¶é€²è¡Œè§£å¯†ï¼Œä¸¦
使用訂閱者的PGP密鑰或S/MIME證書爲æ¯å€‹è¨‚閱者分別å°å…¶é€²è¡Œé‡æ–°åŠ å¯†ã€‚æœ‰é—œéƒµä»¶åˆ—è¡¨
-軟體和用於確ä¿åˆ—表安全和數據ä¿è­·çš„設置的詳細信æ¯ï¼Œè«‹è¨ªå•:
+軟件和用於確ä¿åˆ—表安全和數據ä¿è­·çš„設置的詳細信æ¯ï¼Œè«‹è¨ªå•:
https://www.kernel.org/....
é—œéµé»ž
^^^^^^
-åˆæ¬¡æŽ¥è§¸è¦‹ :ref:`tw_Contact`. å°æ–¼ç‰¹å®šæ–¼äº‹ä»¶çš„郵件列表,密鑰和S/MIME證書通éŽ
+åˆæ¬¡æŽ¥è§¸è¦‹ :ref:`zh_Contact`. å°æ–¼ç‰¹å®šæ–¼äº‹ä»¶çš„郵件列表,密鑰和S/MIME證書通éŽ
特定列表發é€çš„é›»å­éƒµä»¶å‚³éžçµ¦è¨‚閱者。
訂閱事件特定列表
@@ -220,8 +220,8 @@ https://www.kernel.org/....
訂閱由響應å°çµ„處ç†ã€‚希望åƒèˆ‡é€šä¿¡çš„æŠ«éœ²æ–¹å°‡æ½›åœ¨è¨‚戶的列表發é€çµ¦éŸ¿æ‡‰çµ„,以便
響應組å¯ä»¥é©—證訂閱請求。
-æ¯å€‹è¨‚戶都需è¦é€šéŽé›»å­éƒµä»¶å‘響應å°çµ„發é€è¨‚閱請求。電å­éƒµä»¶å¿…須使用訂閱伺æœå™¨
-çš„PGP密鑰或S/MIME證書籤å。如果使用PGP密鑰,則必須從公鑰伺æœå™¨ç²å¾—該密鑰,
+æ¯å€‹è¨‚戶都需è¦é€šéŽé›»å­éƒµä»¶å‘響應å°çµ„發é€è¨‚閱請求。電å­éƒµä»¶å¿…須使用訂閱æœå‹™å™¨
+çš„PGP密鑰或S/MIME證書籤å。如果使用PGP密鑰,則必須從公鑰æœå‹™å™¨ç²å¾—該密鑰,
ä¸¦ä¸”ç†æƒ³æƒ…æ³ä¸‹è©²å¯†é‘°é€£æŽ¥åˆ°Linux內核的PGP信任網。å¦è«‹åƒè¦‹:
https://www.kernel.org/signature.html.
diff --git a/Documentation/translations/zh_TW/process/index.rst b/Documentation/translations/zh_TW/process/index.rst
index d742642dab01..6a0d98b2f9ee 100644
--- a/Documentation/translations/zh_TW/process/index.rst
+++ b/Documentation/translations/zh_TW/process/index.rst
@@ -13,11 +13,12 @@
.. _tw_process_index:
+========================
與Linux 內核社å€ä¸€èµ·å·¥ä½œ
========================
你想æˆçˆ²Linux內核開發人員嗎?歡迎之至ï¼åœ¨å­¸ç¿’è¨±å¤šé—œæ–¼å…§æ ¸çš„æŠ€è¡“çŸ¥è­˜çš„åŒæ™‚,
-了解我們社å€çš„工作方å¼ä¹Ÿå¾ˆé‡è¦ã€‚閱讀這些文檔å¯ä»¥è®“您以更輕鬆的ã€éº»ç…©æ›´å°‘çš„
+瞭解我們社å€çš„工作方å¼ä¹Ÿå¾ˆé‡è¦ã€‚閱讀這些文檔å¯ä»¥è®“您以更輕鬆的ã€éº»ç…©æ›´å°‘çš„
æ–¹å¼å°‡æ›´æ”¹åˆä½µåˆ°å…§æ ¸ã€‚
以下是æ¯ä½é–‹ç™¼äººå“¡éƒ½æ‡‰é–±è®€çš„基本指å—:
@@ -49,7 +50,7 @@
management-style
embargoed-hardware-issues
-這些是一些總體性技術指å—,由於ä¸å¤§å¥½åˆ†é¡žè€Œæ”¾åœ¨é€™è£¡ï¼š
+這些是一些總體性技術指å—,由於ä¸å¤§å¥½åˆ†é¡žè€Œæ”¾åœ¨é€™è£ï¼š
.. toctree::
:maxdepth: 1
diff --git a/Documentation/translations/zh_TW/process/kernel-driver-statement.rst b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
index 963ecece3db1..e967089d2e1f 100644
--- a/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
+++ b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
@@ -1,6 +1,6 @@
.. SPDX-License-Identifier: GPL-2.0
-.. _zh_process_statement_driver:
+.. _tw_process_statement_driver:
.. include:: ../disclaimer-zh_TW.rst
diff --git a/Documentation/translations/zh_TW/process/license-rules.rst b/Documentation/translations/zh_TW/process/license-rules.rst
index 503b6701bde4..2c43bcf2ac79 100644
--- a/Documentation/translations/zh_TW/process/license-rules.rst
+++ b/Documentation/translations/zh_TW/process/license-rules.rst
@@ -1,7 +1,5 @@
.. SPDX-License-Identifier: GPL-2.0
-.. SPDX-License-Identifier: GPL-2.0
-
.. include:: ../disclaimer-zh_TW.rst
:Original: :ref:`Documentation/process/license-rules.rst <kernel_licensing>`
@@ -17,10 +15,10 @@ Linux內核根據LICENSES/preferred/GPL-2.0中æä¾›çš„GNU通用公共許å¯è­‰ç
(GPL-2.0ï¼‰çš„æ¢æ¬¾æä¾›ï¼Œä¸¦åœ¨LICENSES/exceptions/Linux-syscall-note中顯å¼
æè¿°äº†ä¾‹å¤–的系統調用,如COPYING文件中所述。
-此文檔文件æä¾›äº†å¦‚何尿¯å€‹æºæ–‡ä»¶é€²è¡Œæ³¨é‡‹ä»¥ä½¿å…¶è¨±å¯è­‰æ¸…晰明確的說明。
+此文檔文件æä¾›çž­å¦‚何尿¯å€‹æºæ–‡ä»¶é€²è¡Œè¨»é‡‹ä»¥ä½¿å…¶è¨±å¯è­‰æ¸…晰明確的說明。
å®ƒä¸æœƒå–代內核的許å¯è­‰ã€‚
-內核原始碼作爲一個整體é©ç”¨æ–¼COPYING文件中æè¿°çš„許å¯è­‰ï¼Œä½†æ˜¯å–®å€‹æºæ–‡ä»¶å¯ä»¥
+å…§æ ¸æºä»£ç¢¼ä½œçˆ²ä¸€å€‹æ•´é«”é©ç”¨æ–¼COPYING文件中æè¿°çš„許å¯è­‰ï¼Œä½†æ˜¯å–®å€‹æºæ–‡ä»¶å¯ä»¥
具有ä¸åŒçš„與GPL-20兼容的許å¯è­‰::
GPL-1.0+ : GNU通用公共許å¯è­‰v1.0或更高版本
@@ -34,18 +32,18 @@ Linux內核根據LICENSES/preferred/GPL-2.0中æä¾›çš„GNU通用公共許å¯è­‰ç
MIT等許å¯ã€‚
用戶空間API(UAPI)頭文件æè¿°äº†ç”¨æˆ¶ç©ºé–“程åºèˆ‡å…§æ ¸çš„æŽ¥å£ï¼Œé€™æ˜¯ä¸€ç¨®ç‰¹æ®Šæƒ…æ³ã€‚
-根據內核COPYING文件中的注釋,syscallæŽ¥å£æ˜¯ä¸€å€‹æ˜Žç¢ºçš„é‚Šç•Œï¼Œå®ƒä¸æœƒå°‡GPLè¦æ±‚
-擴展到任何使用它與內核通信的軟體。由於UAPI頭文件必須包å«åœ¨å‰µå»ºåœ¨Linuxå…§æ ¸
+根據內核COPYING文件中的註釋,syscallæŽ¥å£æ˜¯ä¸€å€‹æ˜Žç¢ºçš„é‚Šç•Œï¼Œå®ƒä¸æœƒå°‡GPLè¦æ±‚
+擴展到任何使用它與內核通信的軟件。由於UAPI頭文件必須包å«åœ¨å‰µå»ºåœ¨Linuxå…§æ ¸
上é‹è¡Œçš„å¯åŸ·è¡Œæ–‡ä»¶çš„ä»»ä½•æºæ–‡ä»¶ä¸­ï¼Œå› æ­¤æ­¤ä¾‹å¤–必須記錄在特別的許å¯è­‰è¡¨è¿°ä¸­ã€‚
-è¡¨é”æºæ–‡ä»¶è¨±å¯è­‰çš„常用方法是將匹é…çš„æ¨£æ¿æ–‡æœ¬æ·»åŠ åˆ°æ–‡ä»¶çš„é ‚éƒ¨æ³¨é‡‹ä¸­ã€‚ç”±æ–¼
-æ ¼å¼ï¼Œæ‹¼å¯«éŒ¯èª¤ç­‰ï¼Œé€™äº›ã€Œæ¨£æ¿ã€å¾ˆé›£é€šéŽé‚£äº›åœ¨ä¸Šä¸‹æ–‡ä¸­ä½¿ç”¨çš„驗證許å¯è­‰åˆè¦æ€§
+è¡¨é”æºæ–‡ä»¶è¨±å¯è­‰çš„常用方法是將匹é…çš„æ¨£æ¿æ–‡æœ¬æ·»åŠ åˆ°æ–‡ä»¶çš„é ‚éƒ¨è¨»é‡‹ä¸­ã€‚ç”±æ–¼
+æ ¼å¼ï¼Œæ‹¼å¯«éŒ¯èª¤ç­‰ï¼Œé€™äº›â€œæ¨£æ¿â€å¾ˆé›£é€šéŽé‚£äº›åœ¨ä¸Šä¸‹æ–‡ä¸­ä½¿ç”¨çš„驗證許å¯è­‰åˆè¦æ€§
的工具。
-æ¨£æ¿æ–‡æœ¬çš„æ›¿ä»£æ–¹æ³•是在æ¯å€‹æºæ–‡ä»¶ä¸­ä½¿ç”¨è»Ÿé«”包數據交æ›ï¼ˆSPDX)許å¯è­‰æ¨™è­˜ç¬¦ã€‚
+æ¨£æ¿æ–‡æœ¬çš„æ›¿ä»£æ–¹æ³•是在æ¯å€‹æºæ–‡ä»¶ä¸­ä½¿ç”¨è»Ÿä»¶åŒ…數據交æ›ï¼ˆSPDX)許å¯è­‰æ¨™è­˜ç¬¦ã€‚
SPDX許å¯è­‰æ¨™è­˜ç¬¦æ˜¯æ©Ÿå™¨å¯è§£æžçš„,並且是用於æä¾›æ–‡ä»¶å…§å®¹çš„許å¯è­‰çš„精確縮寫。
SPDX許å¯è­‰æ¨™è­˜ç¬¦ç”±Linux 基金會的SPDX 工作組管ç†ï¼Œä¸¦å¾—到了整個行業,工具
-供應商和法律團隊的åˆä½œå¤¥ä¼´çš„ä¸€è‡´åŒæ„。有關詳細信æ¯ï¼Œè«‹åƒé–±
+供應商和法律團隊的åˆä½œä¼™ä¼´çš„ä¸€è‡´åŒæ„。有關詳細信æ¯ï¼Œè«‹åƒé–±
https://spdx.org/
Linuxå…§æ ¸éœ€è¦æ‰€æœ‰æºæ–‡ä»¶ä¸­çš„精確SPDX標識符。內核中使用的有效標識符在
@@ -58,7 +56,7 @@ https://spdx.org/licenses/ 上的官方SPDX許å¯è­‰åˆ—表中檢索,並附帶è
1.安置:
-   內核文件中的SPDX許å¯è­‰æ¨™è­˜ç¬¦æ‡‰æ·»åŠ åˆ°å¯åŒ…嫿³¨é‡‹çš„æ–‡ä»¶ä¸­çš„ç¬¬ä¸€è¡Œã€‚å°æ–¼å¤§å¤š
+   內核文件中的SPDX許å¯è­‰æ¨™è­˜ç¬¦æ‡‰æ·»åŠ åˆ°å¯åŒ…å«è¨»é‡‹çš„æ–‡ä»¶ä¸­çš„ç¬¬ä¸€è¡Œã€‚å°æ–¼å¤§å¤š
數文件,這是第一行,除了那些在第一行中需è¦'#!PATH_TO_INTERPRETER'的腳本。
å°æ–¼é€™äº›è…³æœ¬ï¼ŒSPDX標識符進入第二行。
@@ -66,7 +64,7 @@ https://spdx.org/licenses/ 上的官方SPDX許å¯è­‰åˆ—表中檢索,並附帶è
2. 風格:
- SPDX許å¯è­‰æ¨™è­˜ç¬¦ä»¥æ³¨é‡‹çš„形弿·»åŠ ã€‚æ³¨é‡‹æ¨£å¼å–決於文件類型::
+ SPDX許å¯è­‰æ¨™è­˜ç¬¦ä»¥è¨»é‡‹çš„形弿·»åŠ ã€‚è¨»é‡‹æ¨£å¼å–決於文件類型::
C source: // SPDX-License-Identifier: <SPDX License Expression>
C header: /* SPDX-License-Identifier: <SPDX License Expression> */
@@ -75,20 +73,20 @@ https://spdx.org/licenses/ 上的官方SPDX許å¯è­‰åˆ—表中檢索,並附帶è
.rst: .. SPDX-License-Identifier: <SPDX License Expression>
.dts{i}: // SPDX-License-Identifier: <SPDX License Expression>
- å¦‚æžœç‰¹å®šå·¥å…·ç„¡æ³•è™•ç†æ¨™æº–注釋樣å¼ï¼Œå‰‡æ‡‰ä½¿ç”¨å·¥å…·æŽ¥å—的相應注釋機制。這是在
- C 頭文件中使用「/\*\*/ã€æ¨£å¼æ³¨é‡‹çš„原因。éŽåŽ»åœ¨ä½¿ç”¨ç”Ÿæˆçš„.lds文件中觀察到
- 構建被破壞,其中'ld'無法解æžC++注釋。ç¾åœ¨å·²ç¶“解決了這個å•題,但ä»ç„¶æœ‰è¼ƒ
- 舊的彙編程åºå·¥å…·ç„¡æ³•處ç†C++樣å¼çš„æ³¨é‡‹ã€‚
+ å¦‚æžœç‰¹å®šå·¥å…·ç„¡æ³•è™•ç†æ¨™æº–註釋樣å¼ï¼Œå‰‡æ‡‰ä½¿ç”¨å·¥å…·æŽ¥å—的相應註釋機制。這是在
+ C 頭文件中使用“/\*\*/â€æ¨£å¼è¨»é‡‹çš„原因。éŽåŽ»åœ¨ä½¿ç”¨ç”Ÿæˆçš„.lds文件中觀察到
+ 構建被破壞,其中'ld'無法解æžC++註釋。ç¾åœ¨å·²ç¶“解決了這個å•題,但ä»ç„¶æœ‰è¼ƒ
+ 舊的彙編程åºå·¥å…·ç„¡æ³•處ç†C++樣å¼çš„註釋。
|
3. 奿³•:
<SPDX許å¯è­‰è¡¨é”å¼>是SPDX許å¯è­‰åˆ—表中的SPDX短格å¼è¨±å¯è­‰æ¨™è­˜ç¬¦ï¼Œæˆ–者在許å¯
- 證例外é©ç”¨æ™‚由「WITHã€åˆ†éš”的兩個SPDX短格å¼è¨±å¯è­‰æ¨™è­˜ç¬¦çš„組åˆã€‚當應用多個許
- å¯è­‰æ™‚,表é”å¼ç”±åˆ†éš”å­è¡¨é”å¼çš„é—œéµå­—「ANDã€ï¼Œã€ŒORã€çµ„æˆï¼Œä¸¦ç”±ã€Œï¼ˆã€ï¼Œã€Œï¼‰ã€åŒ…åœã€‚
+ 證例外é©ç”¨æ™‚由“WITHâ€åˆ†éš”的兩個SPDX短格å¼è¨±å¯è­‰æ¨™è­˜ç¬¦çš„組åˆã€‚當應用多個許
+ å¯è­‰æ™‚,表é”å¼ç”±åˆ†éš”å­è¡¨é”å¼çš„é—œéµå­—“ANDâ€ï¼Œâ€œORâ€çµ„æˆï¼Œä¸¦ç”±â€œï¼ˆâ€ï¼Œâ€œï¼‰â€åŒ…åœã€‚
- 帶有「或更高ã€é¸é …çš„[L]GPL等許å¯è­‰çš„許å¯è­‰æ¨™è­˜ç¬¦é€šéŽä½¿ç”¨ã€Œ+ã€ä¾†è¡¨ç¤ºã€Œæˆ–更高ã€
+ 帶有“或更高â€é¸é …çš„[L]GPL等許å¯è­‰çš„許å¯è­‰æ¨™è­˜ç¬¦é€šéŽä½¿ç”¨â€œ+â€ä¾†è¡¨ç¤ºâ€œæˆ–更高â€
é¸é …來構建。::
// SPDX-License-Identifier: GPL-2.0+
@@ -230,7 +228,7 @@ https://spdx.org/licenses/ 上的官方SPDX許å¯è­‰åˆ—表中檢索,並附帶è
元標籤:
- 「其他ã€è¨±å¯è­‰çš„å…ƒæ¨™ç±¤è¦æ±‚與 `優先許å¯`_ çš„è¦æ±‚相åŒã€‚
+ “其他â€è¨±å¯è­‰çš„å…ƒæ¨™ç±¤è¦æ±‚與 `優先許å¯`_ çš„è¦æ±‚相åŒã€‚
文件格å¼ç¤ºä¾‹::
@@ -267,8 +265,8 @@ https://spdx.org/licenses/ 上的官方SPDX許å¯è­‰åˆ—表中檢索,並附帶è
LICENSES/exceptions/GCC-exception-2.0
- 包å«GCC'連çµä¾‹å¤–',它å…許ç¨ç«‹æ–¼å…¶è¨±å¯è­‰çš„ä»»ä½•äºŒé€²ä½æ–‡ä»¶èˆ‡æ¨™è¨˜æœ‰æ­¤ä¾‹å¤–çš„
- 文件的編譯版本連çµã€‚這是從GPLä¸å…¼å®¹åŽŸå§‹ç¢¼å‰µå»ºå¯é‹è¡Œçš„å¯åŸ·è¡Œæ–‡ä»¶æ‰€å¿…需的。
+ 包å«GCC'éˆæŽ¥ä¾‹å¤–',它å…許ç¨ç«‹æ–¼å…¶è¨±å¯è­‰çš„任何二進制文件與標記有此例外的
+ æ–‡ä»¶çš„ç·¨è­¯ç‰ˆæœ¬éˆæŽ¥ã€‚é€™æ˜¯å¾žGPLä¸å…¼å®¹æºä»£ç¢¼å‰µå»ºå¯é‹è¡Œçš„å¯åŸ·è¡Œæ–‡ä»¶æ‰€å¿…需的。
_`例外元標記`:
@@ -333,11 +331,11 @@ https://spdx.org/licenses/ 上的官方SPDX許å¯è­‰åˆ—表中檢索,並附帶è
_`模塊許å¯`
-----------------
- å¯åŠ è¼‰å…§æ ¸æ¨¡å¡Šé‚„éœ€è¦MODULE_LICENSEï¼ˆï¼‰æ¨™è¨˜ã€‚æ­¤æ¨™è¨˜æ—¢ä¸æ›¿ä»£æ­£ç¢ºçš„原始碼
+ å¯åŠ è¼‰å…§æ ¸æ¨¡å¡Šé‚„éœ€è¦MODULE_LICENSEï¼ˆï¼‰æ¨™è¨˜ã€‚æ­¤æ¨™è¨˜æ—¢ä¸æ›¿ä»£æ­£ç¢ºçš„æºä»£ç¢¼
許å¯è­‰ä¿¡æ¯ï¼ˆSPDX-License-Identifier),也ä¸ä»¥ä»»ä½•æ–¹å¼è¡¨ç¤ºæˆ–確定æä¾›æ¨¡å¡Š
- 原始碼的確切許å¯è­‰ã€‚
+ æºä»£ç¢¼çš„確切許å¯è­‰ã€‚
- 此標記的唯一目的是æä¾›è¶³å¤ çš„ä¿¡æ¯ï¼Œè©²æ¨¡å¡Šæ˜¯å¦æ˜¯è‡ªç”±è»Ÿé«”或者是內核模塊加
+ 此標記的唯一目的是æä¾›è¶³å¤ çš„ä¿¡æ¯ï¼Œè©²æ¨¡å¡Šæ˜¯å¦æ˜¯è‡ªç”±è»Ÿä»¶æˆ–者是內核模塊加
載器和用戶空間工具的專有模塊。
MODULE_LICENSE()的有效許å¯è­‰å­—符串是:
@@ -365,9 +363,9 @@ _`模塊許å¯`
åªèƒ½é€šéŽç›¸æ‡‰çš„æºæ–‡ä»¶ä¸­çš„è¨±å¯è­‰ä¿¡æ¯ä¾†ç¢ºå®šã€‚
"Proprietary" 該模塊屬於專有許å¯ã€‚此字符串僅用於專有的第三
- 方模塊,ä¸èƒ½ç”¨æ–¼åœ¨å…§æ ¸æ¨¹ä¸­å…·æœ‰åŽŸå§‹ç¢¼çš„æ¨¡å¡Šã€‚
- ä»¥é€™ç¨®æ–¹å¼æ¨™è¨˜çš„æ¨¡å¡Šåœ¨åŠ è¼‰æ™‚æœƒä½¿ç”¨'P'標記汙
- 染內核,並且內核模塊加載器拒絕將這些模塊連çµ
+ 方模塊,ä¸èƒ½ç”¨æ–¼åœ¨å…§æ ¸æ¨¹ä¸­å…·æœ‰æºä»£ç¢¼çš„æ¨¡å¡Šã€‚
+ ä»¥é€™ç¨®æ–¹å¼æ¨™è¨˜çš„æ¨¡å¡Šåœ¨åŠ è¼‰æ™‚æœƒä½¿ç”¨'P'標記污
+ æŸ“å…§æ ¸ï¼Œä¸¦ä¸”å…§æ ¸æ¨¡å¡ŠåŠ è¼‰å™¨æ‹’çµ•å°‡é€™äº›æ¨¡å¡ŠéˆæŽ¥
到使用EXPORT_SYMBOL_GPL()導出的符號。
============================= =============================================
diff --git a/Documentation/translations/zh_TW/process/management-style.rst b/Documentation/translations/zh_TW/process/management-style.rst
index e9d29024f4c9..f3913e3c159d 100644
--- a/Documentation/translations/zh_TW/process/management-style.rst
+++ b/Documentation/translations/zh_TW/process/management-style.rst
@@ -16,20 +16,20 @@ Linux內核管ç†é¢¨æ ¼
ä¸»è¦æ˜¯çˆ²äº†é¿å…å覆回答 [#cnf1]_ 相åŒï¼ˆæˆ–類似)的å•題。
管ç†é¢¨æ ¼æ˜¯éžå¸¸å€‹äººåŒ–的,比簡單的編碼風格è¦å‰‡æ›´é›£ä»¥é‡åŒ–,因此本文檔å¯èƒ½èˆ‡å¯¦
-éš›æƒ…æ³æœ‰é—œï¼Œä¹Ÿå¯èƒ½èˆ‡å¯¦éš›æƒ…æ³ç„¡é—œã€‚èµ·åˆå®ƒæ˜¯ä¸€å€‹çŽ©ç¬‘ï¼Œä½†é€™ä¸¦ä¸æ„味著它å¯èƒ½ä¸
+éš›æƒ…æ³æœ‰é—œï¼Œä¹Ÿå¯èƒ½èˆ‡å¯¦éš›æƒ…æ³ç„¡é—œã€‚èµ·åˆå®ƒæ˜¯ä¸€å€‹çŽ©ç¬‘ï¼Œä½†é€™ä¸¦ä¸æ„味ç€å®ƒå¯èƒ½ä¸
是真的。你得自己決定。
-順便說一å¥ï¼Œåœ¨è«‡åˆ°ã€Œæ ¸å¿ƒç®¡ç†è€…ã€æ™‚ï¼Œä¸»è¦æ˜¯æŠ€è¡“è² è²¬äººï¼Œè€Œä¸æ˜¯åœ¨å…¬å¸å…§éƒ¨é€²è¡Œå‚³
-統管ç†çš„人。如果你簽署了採購訂單或者å°ä½ çš„團隊的é ç®—有任何了解,你幾乎肯定
+順便說一å¥ï¼Œåœ¨è«‡åˆ°â€œæ ¸å¿ƒç®¡ç†è€…â€æ™‚ï¼Œä¸»è¦æ˜¯æŠ€è¡“è² è²¬äººï¼Œè€Œä¸æ˜¯åœ¨å…¬å¸å…§éƒ¨é€²è¡Œå‚³
+統管ç†çš„人。如果你簽署了採購訂單或者å°ä½ çš„團隊的é ç®—有任何瞭解,你幾乎肯定
䏿˜¯ä¸€å€‹æ ¸å¿ƒç®¡ç†è€…。這些建議å¯èƒ½é©ç”¨æ–¼æ‚¨ï¼Œä¹Ÿå¯èƒ½ä¸é©ç”¨æ–¼æ‚¨ã€‚
-首先,我建議你購買「高效人的七個習慣ã€ï¼Œè€Œä¸æ˜¯é–±è®€å®ƒã€‚燒了它,這是一個å‰å¤§çš„
+首先,我建議你購買“高效人的七個習慣â€ï¼Œè€Œä¸æ˜¯é–±è®€å®ƒã€‚燒了它,這是一個å‰å¤§çš„
象徵性姿態。
.. [#cnf1] æœ¬æ–‡ä»¶ä¸¦ä¸æ˜¯é€šéŽå›žç­”å•題,而是通éŽè®“æå•者痛苦地明白,我們ä¸çŸ¥é“
答案是什麼。
-ä¸ç®¡æ€Žæ¨£ï¼Œé€™è£¡æ˜¯ï¼š
+ä¸ç®¡æ€Žæ¨£ï¼Œé€™è£æ˜¯ï¼š
.. _tw_decisions:
@@ -39,14 +39,14 @@ Linux內核管ç†é¢¨æ ¼
æ¯å€‹äººéƒ½èªçˆ²ç®¡ç†è€…åšæ±ºå®šï¼Œè€Œä¸”決策很é‡è¦ã€‚決定越大越痛苦,管ç†è€…就必須越高級。
這很明顯,但事實並éžå¦‚此。
-éŠæˆ²çš„å字是 **é¿å…** åšå‡ºæ±ºå®šã€‚å°¤å…¶æ˜¯ï¼Œå¦‚æžœæœ‰äººå‘Šè¨´ä½ ã€Œé¸æ“‡ï¼ˆa)或(b),
-我們真的需è¦ä½ ä¾†åšæ±ºå®šã€ï¼Œä½ å°±æ˜¯é™·å…¥éº»ç…©çš„管ç†è€…。你管ç†çš„人比你更了解細節,
+最é‡è¦çš„æ˜¯ **é¿å…** åšå‡ºæ±ºå®šã€‚å°¤å…¶æ˜¯ï¼Œå¦‚æžœæœ‰äººå‘Šè¨´ä½ â€œé¸æ“‡ï¼ˆa)或(b),
+我們真的需è¦ä½ ä¾†åšæ±ºå®šâ€ï¼Œä½ å°±æ˜¯é™·å…¥éº»ç…©çš„管ç†è€…。你管ç†çš„人比你更瞭解細節,
æ‰€ä»¥å¦‚æžœä»–å€‘ä¾†æ‰¾ä½ åšæŠ€è¡“æ±ºç­–ï¼Œä½ å®Œè›‹äº†ã€‚ä½ é¡¯ç„¶æ²’æœ‰èƒ½åŠ›çˆ²ä»–å€‘åšé€™å€‹æ±ºå®šã€‚
-(推論:如果你管ç†çš„äººä¸æ¯”你更了解細節,你也會被æžç ¸ï¼Œå„˜ç®¡åŽŸå› å®Œå…¨ä¸åŒã€‚
+(推論:如果你管ç†çš„äººä¸æ¯”你更瞭解細節,你也會被æžç ¸ï¼Œå„˜ç®¡åŽŸå› å®Œå…¨ä¸åŒã€‚
也就是說,你的工作是錯的,他們應該管ç†ä½ çš„æ‰æ™ºï¼‰
-æ‰€ä»¥éŠæˆ²çš„å字是 **é¿å…** åšå‡ºæ±ºå®šï¼Œè‡³å°‘是那些大而痛苦的決定。åšä¸€äº›å°çš„
+所以最é‡è¦çš„æ˜¯ **é¿å…** åšå‡ºæ±ºå®šï¼Œè‡³å°‘是那些大而痛苦的決定。åšä¸€äº›å°çš„
å’Œéžçµæžœæ€§çš„æ±ºå®šæ˜¯å¾ˆå¥½çš„,並且使您看起來好åƒçŸ¥é“自己在åšä»€éº¼ï¼Œæ‰€ä»¥å…§æ ¸ç®¡ç†è€…
需è¦åšçš„æ˜¯å°‡é‚£äº›å¤§çš„和痛苦的決定變æˆé‚£äº›æ²’有人真正關心的å°äº‹æƒ…。
@@ -61,7 +61,7 @@ Linux內核管ç†é¢¨æ ¼
逃離的角è½ã€‚走投無路的è€é¼ å¯èƒ½å¾ˆå±éšªâ€”—走投無路的管ç†è€…çœŸå¯æ†ã€‚
事實證明,由於沒有人會愚蠢到讓內核管ç†è€…承擔巨大的財政責任,所以通常很容易
-回溯。既然你ä¸å¯èƒ½æµªè²»æŽ‰ä½ ç„¡æ³•償還的巨é¡è³‡é‡‘,你唯一å¯ä»¥å›žæº¯çš„就是技術決策,
+回溯。既然你ä¸å¯èƒ½æµªè²»æŽ‰ä½ ç„¡æ³•償還的鉅é¡è³‡é‡‘,你唯一å¯ä»¥å›žæº¯çš„就是技術決策,
而回溯很容易:åªè¦å‘Šè¨´å¤§å®¶ä½ æ˜¯å€‹ä¸ç¨±è·çš„傻瓜,說å°ä¸èµ·ï¼Œç„¶å¾Œæ’¤éŠ·ä½ åŽ»å¹´è®“åˆ¥
人所åšçš„æ¯«ç„¡åƒ¹å€¼çš„工作。çªç„¶é–“,你一年å‰åšçš„æ±ºå®šä¸åœ¨æ˜¯ä¸€å€‹é‡å¤§çš„æ±ºå®šï¼Œå› çˆ²
它很容易被推翻。
@@ -72,7 +72,7 @@ Linux內核管ç†é¢¨æ ¼
確實很難。
- 如果有人告訴你,你去年所åšçš„工作終究是ä¸å€¼å¾—的,那麼å°é‚£äº›å¯æ†çš„低級工
程師來說也是很困難的,雖然實際的 **工作** 很容易刪除,但你å¯èƒ½å·²ç¶“ä¸å¯
- 挽回地失去了工程師的信任。記ä½ï¼šã€Œä¸å¯æ’¤éŠ·ã€æ˜¯æˆ‘們一開始就試圖é¿å…的,
+ 挽回地失去了工程師的信任。記ä½ï¼šâ€œä¸å¯æ’¤éŠ·â€æ˜¯æˆ‘們一開始就試圖é¿å…的,
而你的決定終究是一個é‡å¤§çš„æ±ºå®šã€‚
令人欣慰的是,這兩個原因都å¯ä»¥é€šéŽé å…ˆæ‰¿èªä½ æ²’有任何線索,æå‰å‘Šè¨´äººå€‘ä½ çš„
@@ -80,19 +80,19 @@ Linux內核管ç†é¢¨æ ¼
的權利,並讓人們 **æ„è­˜** 到這一點。當你 **還沒有** åšéŽçœŸæ­£æ„šè ¢çš„事情的時
候,承èªè‡ªå·±æ˜¯æ„šè ¢çš„è¦å®¹æ˜“得多。
-然後,當它真的被證明是愚蠢的時候,人們就轉動他們的眼ç èªªã€Œå“Žå‘€ï¼Œä¸‹æ¬¡ä¸è¦äº†ã€ã€‚
+然後,當它真的被證明是愚蠢的時候,人們就轉動他們的眼ç èªªâ€œå“Žå‘€ï¼Œä¸‹æ¬¡ä¸è¦äº†â€ã€‚
這種å°ä¸ç¨±è·çš„先發制人的承èªï¼Œä¹Ÿå¯èƒ½ä½¿çœŸæ­£åšé€™é …å·¥ä½œçš„äººä¹Ÿæœƒä¸‰æ€æ˜¯å¦å€¼å¾—åšã€‚
畢竟,如果他們ä¸ç¢ºå®šé€™æ˜¯å¦æ˜¯ä¸€å€‹å¥½ä¸»æ„ï¼Œä½ è‚¯å®šä¸æ‡‰è©²é€šéŽå‘他們ä¿è­‰ä»–們所åš
的工作將會進入(內核)鼓勵他們。在他們開始一項巨大的努力之å‰ï¼Œè‡³å°‘讓他們三
æ€è€Œå¾Œè¡Œã€‚
-記ä½ï¼šä»–們最好比你更了解細節,而且他們通常èªçˆ²ä»–們尿¯ä»¶äº‹éƒ½æœ‰ç­”案。作爲一
+記ä½ï¼šä»–們最好比你更瞭解細節,而且他們通常èªçˆ²ä»–們尿¯ä»¶äº‹éƒ½æœ‰ç­”案。作爲一
個管ç†è€…,你能åšçš„æœ€å¥½çš„äº‹æƒ…ä¸æ˜¯çŒè¼¸è‡ªä¿¡ï¼Œè€Œæ˜¯å°ä»–們所åšçš„事情進行å¥åº·çš„æ‰¹
判性æ€è€ƒã€‚
-順便說一å¥ï¼Œå¦ä¸€ç¨®é¿å…åšå‡ºæ±ºå®šçš„æ–¹æ³•æ˜¯çœ‹èµ·ä¾†å¾ˆå¯æ†çš„æŠ±æ€¨ 「我們ä¸èƒ½å…©è€…å…¼
-å¾—å—Žï¼Ÿã€ ç›¸ä¿¡æˆ‘ï¼Œå®ƒæ˜¯æœ‰æ•ˆçš„ã€‚å¦‚æžœä¸æ¸…楚哪種方法更好,他們最終會弄清楚的。
+順便說一å¥ï¼Œå¦ä¸€ç¨®é¿å…åšå‡ºæ±ºå®šçš„æ–¹æ³•æ˜¯çœ‹èµ·ä¾†å¾ˆå¯æ†çš„æŠ±æ€¨ “我們ä¸èƒ½å…©è€…å…¼
+å¾—å—Žï¼Ÿâ€ ç›¸ä¿¡æˆ‘ï¼Œå®ƒæ˜¯æœ‰æ•ˆçš„ã€‚å¦‚æžœä¸æ¸…楚哪種方法更好,他們最終會弄清楚的。
最終的答案å¯èƒ½æ˜¯å…©å€‹åœ˜éšŠéƒ½æœƒå› çˆ²é€™ç¨®æƒ…æ³è€Œæ„Ÿåˆ°æ²®å–ªï¼Œä»¥è‡³æ–¼ä»–們放棄了。
這è½èµ·ä¾†åƒæ˜¯ä¸€å€‹å¤±æ•—,但這通常是一個跡象,表明兩個項目都有å•題,而åƒèˆ‡å…¶ä¸­
@@ -102,7 +102,7 @@ Linux內核管ç†é¢¨æ ¼
2)人
-----
-大多數人都是白癡,åšä¸€å管ç†è€…æ„味著你必須處ç†å¥½é€™ä»¶äº‹ï¼Œä¹Ÿè¨±æ›´é‡è¦çš„æ˜¯,
+大多數人都是白癡,åšä¸€å管ç†è€…æ„味ç€ä½ å¿…須處ç†å¥½é€™ä»¶äº‹ï¼Œä¹Ÿè¨±æ›´é‡è¦çš„æ˜¯,
**他們** 必須處ç†å¥½ä½ ã€‚
事實證明,雖然很容易糾正技術錯誤,但ä¸å®¹æ˜“糾正人格障礙。你åªèƒ½å’Œä»–們的和
@@ -110,16 +110,16 @@ Linux內核管ç†é¢¨æ ¼
但是,爲了åšå¥½ä½œçˆ²å…§æ ¸ç®¡ç†è€…的準備,最好記ä½ä¸è¦ç‡’掉任何橋樑,ä¸è¦è½Ÿç‚¸ä»»ä½•
ç„¡è¾œçš„æ‘æ°‘,也ä¸è¦ç–é å¤ªå¤šçš„內核開發人員。事實證明,ç–é äººæ˜¯ç›¸ç•¶å®¹æ˜“的,而
-親近一個ç–é çš„人是很難的。因此,「ç–é ã€ç«‹å³å±¬æ–¼ã€Œä¸å¯é€†ã€çš„範疇,並根據
+親近一個ç–é çš„人是很難的。因此,“ç–é â€ç«‹å³å±¬æ–¼â€œä¸å¯é€†â€çš„範疇,並根據
:ref:`tw_decisions` æˆçˆ²çµ•ä¸å¯ä»¥åšçš„事情。
-é€™è£¡åªæœ‰å¹¾å€‹ç°¡å–®çš„è¦å‰‡ï¼š
+這è£åªæœ‰å¹¾å€‹ç°¡å–®çš„è¦å‰‡ï¼š
(1) ä¸è¦å«äººç¬¨è›‹ï¼ˆè‡³å°‘ä¸è¦åœ¨å…¬å…±å ´åˆï¼‰
(2) 學習如何在忘記è¦å‰‡(1)æ™‚é“æ­‰
-å•題在於 #1 很容易去åšï¼Œå› çˆ²ä½ å¯ä»¥ç”¨æ•¸ç™¾è¬ç¨®ä¸åŒçš„æ–¹å¼èªªã€Œä½ æ˜¯ä¸€å€‹ç¬¨è›‹ã€ [#cnf2]_
-有時甚至沒有æ„識到,而且幾乎總是帶著一種白熱化的信念,èªçˆ²ä½ æ˜¯å°çš„。
+å•題在於 #1 很容易去åšï¼Œå› çˆ²ä½ å¯ä»¥ç”¨æ•¸ç™¾è¬ç¨®ä¸åŒçš„æ–¹å¼èªªâ€œä½ æ˜¯ä¸€å€‹ç¬¨è›‹â€ [#cnf2]_
+有時甚至沒有æ„識到,而且幾乎總是帶ç€ä¸€ç¨®ç™½ç†±åŒ–的信念,èªçˆ²ä½ æ˜¯å°çš„。
你越確信自己是å°çš„(讓我們é¢å°ç¾å¯¦å§ï¼Œä½ å¯ä»¥æŠŠå¹¾ä¹Žæ‰€æœ‰äººéƒ½ç¨±çˆ²å£žäººï¼Œè€Œä¸”ä½ 
經常是å°çš„ï¼‰ï¼Œäº‹å¾Œé“æ­‰å°±è¶Šé›£ã€‚
@@ -127,12 +127,12 @@ Linux內核管ç†é¢¨æ ¼
è¦è§£æ±ºæ­¤å•é¡Œï¼Œæ‚¨å¯¦éš›ä¸Šåªæœ‰å…©å€‹é¸é …:
- éžå¸¸æ“…長铿­‰
- - 把「愛ã€å‡å‹»åœ°æ•£é–‹ï¼Œæ²’有人會真正感覺到自己被ä¸å…¬å¹³åœ°çž„準了。讓它有足夠的
+ - 把“愛â€å‡å‹»åœ°æ•£é–‹ï¼Œæ²’有人會真正感覺到自己被ä¸å…¬å¹³åœ°çž„準了。讓它有足夠的
創造性,他們甚至å¯èƒ½æœƒè¦ºå¾—好笑。
鏿“‡æ°¸é ä¿æŒç¦®è²Œæ˜¯ä¸å­˜åœ¨çš„。沒有人會相信一個如此明顯地隱è—了他們真實性格的人。
-.. [#cnf2] ä¿ç¾…·西蒙演唱了「離開愛人的50種方法ã€ï¼Œå› çˆ²å¦çŽ‡åœ°èªªï¼Œã€Œå‘Šè¨´é–‹ç™¼è€…
+.. [#cnf2] ä¿ç¾…·西蒙演唱了“離開愛人的50種方法â€ï¼Œå› çˆ²å¦çŽ‡åœ°èªªï¼Œâ€œå‘Šè¨´é–‹ç™¼è€…
他們是D*CKHEAD" çš„100è¬ç¨®æ–¹æ³•都無法確èªã€‚但我確信他已經這麼想了。
3)人2 - 好人
@@ -148,8 +148,8 @@ Linux內核管ç†é¢¨æ ¼
ç‰¹åˆ¥æ˜¯ï¼Œä»–å€‘èƒ½å¤ çˆ²ä½ åšæ±ºå®šï¼Œé€™å°±æ˜¯éŠæˆ²çš„全部內容。
所以當你發ç¾ä¸€å€‹æ¯”ä½ è°æ˜Žçš„人時,就順其自然å§ã€‚你的管ç†è·è²¬åœ¨å¾ˆå¤§ç¨‹åº¦ä¸Šè®Šæˆ
-了「è½èµ·ä¾†åƒæ˜¯å€‹å¥½ä¸»æ„——去嘗試å§ã€ï¼Œæˆ–者「è½èµ·ä¾†ä¸éŒ¯ï¼Œä½†æ˜¯XXX呢?ã€ã€Œã€‚第二個版
-本尤其是一個很好的方法,è¦éº¼å­¸ç¿’一些關於「XXXã€çš„æ–°æ±è¥¿ï¼Œè¦éº¼é€šéŽæŒ‡å‡ºä¸€äº›è°æ˜Ž
+了“è½èµ·ä¾†åƒæ˜¯å€‹å¥½ä¸»æ„——去嘗試å§â€ï¼Œæˆ–者“è½èµ·ä¾†ä¸éŒ¯ï¼Œä½†æ˜¯XXX呢?â€â€œã€‚第二個版
+本尤其是一個很好的方法,è¦éº¼å­¸ç¿’一些關於“XXXâ€çš„æ–°æ±è¥¿ï¼Œè¦éº¼é€šéŽæŒ‡å‡ºä¸€äº›è°æ˜Ž
人沒有想到的æ±è¥¿ä¾†é¡¯å¾—æ›´å…·ç®¡ç†æ€§ã€‚無論哪種情æ³ï¼Œä½ éƒ½æœƒè´ã€‚
è¦æ³¨æ„的一件事是èªè­˜åˆ°ä¸€å€‹é ˜åŸŸçš„å‰å¤§ä¸ä¸€å®šæœƒè½‰åŒ–爲其他領域。所以你å¯èƒ½æœƒå‘
@@ -172,22 +172,22 @@ Linux內核管ç†é¢¨æ ¼
他們也å¯èƒ½æ˜¯èƒ½å¤ è§£æ±ºå•題的人。因爲,讓我們é¢å°ç¾å¯¦å§ï¼Œè‚¯å®šä¸æ˜¯ä½ ã€‚
承擔責任也是你首先æˆçˆ²ç®¡ç†è€…的原因。這是讓人們信任你,讓你ç²å¾—潛在的榮耀的
-一部分,因爲你就是那個會說「我æžç ¸äº†ã€çš„人。如果你已經éµå¾ªäº†ä»¥å‰çš„è¦å‰‡ï¼Œä½ ç¾
+一部分,因爲你就是那個會說“我æžç ¸äº†â€çš„人。如果你已經éµå¾ªäº†ä»¥å‰çš„è¦å‰‡ï¼Œä½ ç¾
在已經很擅長說了。
5)應é¿å…的事情
---------------
-æœ‰ä¸€ä»¶äº‹äººå€‘ç”šè‡³æ¯”è¢«ç¨±çˆ²ã€Œç¬¨è›‹ã€æ›´è¨ŽåŽ­ï¼Œé‚£å°±æ˜¯åœ¨ä¸€å€‹ç¥žè–çš„è²éŸ³ä¸­è¢«ç¨±çˆ²ã€Œç¬¨è›‹ã€ã€‚
+æœ‰ä¸€ä»¶äº‹äººå€‘ç”šè‡³æ¯”è¢«ç¨±çˆ²â€œç¬¨è›‹â€æ›´è¨ŽåŽ­ï¼Œé‚£å°±æ˜¯åœ¨ä¸€å€‹ç¥žè–çš„è²éŸ³ä¸­è¢«ç¨±çˆ²â€œç¬¨è›‹â€ã€‚
第一個你å¯ä»¥é“æ­‰ï¼Œç¬¬äºŒå€‹ä½ ä¸æœƒçœŸæ­£å¾—到機會。å³ä½¿ä½ åšå¾—很好,他們也å¯èƒ½ä¸å†
傾è½ã€‚
-我們都èªçˆ²è‡ªå·±æ¯”別人強,這æ„味著當別人è£è…”作勢時,這會讓我們很惱ç«ã€‚你也許
+我們都èªçˆ²è‡ªå·±æ¯”別人強,這æ„味ç€ç•¶åˆ¥äººè£è…”作勢時,這會讓我們很惱ç«ã€‚你也許
在é“德和智力上比你周åœçš„æ¯å€‹äººéƒ½å„ªè¶Šï¼Œä½†ä¸è¦è©¦åœ–太明顯,除éžä½ çœŸçš„æ‰“算激怒
æŸäºº [#cnf3]_
åŒæ¨£ï¼Œä¸è¦å°äº‹æƒ…太客氣或太微妙。禮貌很容易è½å¾—è½èŠ±æµæ°´ï¼ŒæŠŠå•題隱è—起來,
-正如他們所說,「在網際網路上,沒人能è½åˆ°ä½ çš„å«è“„。ã€ç”¨ä¸€å€‹éˆå™¨æŠŠé€™ä¸€é»žéŒ˜é€²åŽ»ï¼Œ
+正如他們所說,“在互è¯ç¶²ä¸Šï¼Œæ²’人能è½åˆ°ä½ çš„å«è“„。â€ç”¨ä¸€å€‹éˆå™¨æŠŠé€™ä¸€é»žéŒ˜é€²åŽ»ï¼Œ
因爲你ä¸èƒ½çœŸçš„ä¾é åˆ¥äººä¾†ç²å¾—你的觀點。
一些幽默å¯ä»¥å¹«åŠ©ç·©å’Œç›´çŽ‡å’Œé“德化。éŽåº¦åˆ°è’謬的地步,å¯ä»¥çŒè¼¸ä¸€å€‹è§€é»žï¼Œè€Œä¸
@@ -203,8 +203,8 @@ Linux內核管ç†é¢¨æ ¼
既然你的主è¦è²¬ä»»ä¼¼ä¹Žæ˜¯çˆ²åˆ¥äººçš„錯誤承擔責任,並且讓別人痛苦地明白你是ä¸ç¨±è·
的,那麼顯而易見的å•題之一就變æˆäº†çˆ²ä»€éº¼é¦–å…ˆè¦é€™æ¨£åšã€‚
-首先,雖然你å¯èƒ½æœƒæˆ–å¯èƒ½ä¸æœƒè½åˆ°å幾歲女孩(或男孩,讓我們ä¸è¦åœ¨é€™è£¡è©•判或
-性別歧視)敲你的更衣室門,你會得到一個巨大的個人æˆå°±æ„Ÿçˆ²ã€Œè² è²¬ã€ã€‚別介æ„你真
+首先,雖然你å¯èƒ½æœƒæˆ–å¯èƒ½ä¸æœƒè½åˆ°å幾歲女孩(或男孩,讓我們ä¸è¦åœ¨é€™è£è©•判或
+性別歧視)敲你的更衣室門,你會得到一個巨大的個人æˆå°±æ„Ÿçˆ²â€œè² è²¬â€ã€‚別介æ„你真
的在領導別人,你è¦è·Ÿä¸Šåˆ¥äººï¼Œå„˜å¯èƒ½å¿«åœ°è¿½è¶•他們。æ¯å€‹äººéƒ½æœƒèªçˆ²ä½ æ˜¯è² è²¬äººã€‚
如果你å¯ä»¥åšåˆ°é€™å€‹ï¼Œ 這是個å‰å¤§çš„工作ï¼
diff --git a/Documentation/translations/zh_TW/process/stable-api-nonsense.rst b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
index 33fc85c2cc51..6839d25bb22a 100644
--- a/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
+++ b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
@@ -17,45 +17,45 @@
Linux 內核驅動接å£
==================
-寫作本文檔的目的,是爲了解釋爲什麼Linux既沒有二進ä½å…§æ ¸æŽ¥å£ï¼Œä¹Ÿæ²’有穩定
-的內核接å£ã€‚這裡所說的內核接å£ï¼Œæ˜¯æŒ‡å…§æ ¸é‡Œçš„æŽ¥å£ï¼Œè€Œä¸æ˜¯å…§æ ¸å’Œç”¨æˆ¶ç©ºé–“
-的接å£ã€‚內核到用戶空間的接å£ï¼Œæ˜¯æä¾›çµ¦æ‡‰ç”¨ç¨‹å¼ä½¿ç”¨çš„系統調用,系統調用
-在歷å²ä¸Šå¹¾ä¹Žæ²’有éŽè®ŠåŒ–ï¼Œå°‡ä¾†ä¹Ÿä¸æœƒæœ‰è®ŠåŒ–ã€‚æˆ‘æœ‰ä¸€äº›è€æ‡‰ç”¨ç¨‹å¼æ˜¯åœ¨0.9版本
-或者更早版本的內核上編譯的,在使用2.6版本內核的Linux發布上ä¾ç„¶ç”¨å¾—很好
-。用戶和應用程å¼ä½œè€…å¯ä»¥å°‡é€™å€‹æŽ¥å£çœ‹æˆæ˜¯ç©©å®šçš„。
+寫作本文檔的目的,是爲了解釋爲什麼Linux既沒有二進制內核接å£ï¼Œä¹Ÿæ²’有穩定
+的內核接å£ã€‚é€™è£æ‰€èªªçš„內核接å£ï¼Œæ˜¯æŒ‡å…§æ ¸è£çš„æŽ¥å£ï¼Œè€Œä¸æ˜¯å…§æ ¸å’Œç”¨æˆ¶ç©ºé–“
+的接å£ã€‚內核到用戶空間的接å£ï¼Œæ˜¯æä¾›çµ¦æ‡‰ç”¨ç¨‹åºä½¿ç”¨çš„系統調用,系統調用
+在歷å²ä¸Šå¹¾ä¹Žæ²’有éŽè®ŠåŒ–ï¼Œå°‡ä¾†ä¹Ÿä¸æœƒæœ‰è®ŠåŒ–ã€‚æˆ‘æœ‰ä¸€äº›è€æ‡‰ç”¨ç¨‹åºæ˜¯åœ¨0.9版本
+或者更早版本的內核上編譯的,在使用2.6版本內核的Linux發佈上ä¾ç„¶ç”¨å¾—很好
+。用戶和應用程åºä½œè€…å¯ä»¥å°‡é€™å€‹æŽ¥å£çœ‹æˆæ˜¯ç©©å®šçš„。
執行綱è¦
--------
你也許以爲自己想è¦ç©©å®šçš„內核接å£ï¼Œä½†æ˜¯ä½ ä¸æ¸…楚你è¦çš„å¯¦éš›ä¸Šä¸æ˜¯å®ƒã€‚你需
-è¦çš„其實是穩定的驅動程åºï¼Œè€Œä½ åªæœ‰å°‡é©…å‹•ç¨‹åºæ”¾åˆ°å…¬ç‰ˆå…§æ ¸çš„原始碼樹里,
-æ‰æœ‰å¯èƒ½é”到這個目的。而且這樣åšé‚„有很多其它好處,正是因爲這些好處使得
-Linux能æˆçˆ²å¼·å£¯ï¼Œç©©å®šï¼Œæˆç†Ÿçš„ä½œæ¥­ç³»çµ±ï¼Œé€™ä¹Ÿæ˜¯ä½ æœ€é–‹å§‹é¸æ“‡Linux的原因。
+è¦çš„其實是穩定的驅動程åºï¼Œè€Œä½ åªæœ‰å°‡é©…å‹•ç¨‹åºæ”¾åˆ°å…¬ç‰ˆå…§æ ¸çš„æºä»£ç¢¼æ¨¹è£ï¼Œ
+纔有å¯èƒ½é”到這個目的。而且這樣åšé‚„有很多其它好處,正是因爲這些好處使得
+Linux能æˆçˆ²å¼·å£¯ï¼Œç©©å®šï¼Œæˆç†Ÿçš„æ“ä½œç³»çµ±ï¼Œé€™ä¹Ÿæ˜¯ä½ æœ€é–‹å§‹é¸æ“‡Linux的原因。
入門
-----
-åªæœ‰é‚£äº›å¯«é©…動程åºçš„ã€Œæ€ªäººã€æ‰æœƒæ“”心內核接å£çš„æ”¹è®Šï¼Œå°å»£å¤§ç”¨æˆ¶ä¾†èªªï¼Œæ—¢
+åªæœ‰é‚£äº›å¯«é©…動程åºçš„“怪人â€çº”會擔心內核接å£çš„æ”¹è®Šï¼Œå°å»£å¤§ç”¨æˆ¶ä¾†èªªï¼Œæ—¢
看ä¸åˆ°å…§æ ¸æŽ¥å£ï¼Œä¹Ÿä¸éœ€è¦åŽ»é—œå¿ƒå®ƒã€‚
é¦–å…ˆï¼Œæˆ‘ä¸æ‰“算討論關於任何éžGPL許å¯çš„內核驅動的法律å•題,這些éžGPL許å¯
-的驅動程åºåŒ…括ä¸å…¬é–‹åŽŸå§‹ç¢¼ï¼Œéš±è—åŽŸå§‹ç¢¼ï¼ŒäºŒé€²ä½æˆ–者是用原始碼包è£ï¼Œæˆ–者
-是其它任何形å¼çš„ä¸èƒ½ä»¥GPL許å¯å…¬é–‹åŽŸå§‹ç¢¼çš„é©…å‹•ç¨‹åºã€‚如果有法律å•題,請咨
-è©¢å¾‹å¸«ï¼Œæˆ‘åªæ˜¯ä¸€å€‹ç¨‹å¼è¨­è¨ˆå¸«ï¼Œæ‰€ä»¥æˆ‘åªæ‰“算探討技術å•é¡Œï¼ˆä¸æ˜¯å°çœ‹æ³•律å•題,
+的驅動程åºåŒ…括ä¸å…¬é–‹æºä»£ç¢¼ï¼Œéš±è—æºä»£ç¢¼ï¼ŒäºŒé€²åˆ¶æˆ–者是用æºä»£ç¢¼åŒ…è£ï¼Œæˆ–者
+是其它任何形å¼çš„ä¸èƒ½ä»¥GPL許å¯å…¬é–‹æºä»£ç¢¼çš„驅動程åºã€‚如果有法律å•題,請諮
+è©¢å¾‹å¸«ï¼Œæˆ‘åªæ˜¯ä¸€å€‹ç¨‹åºå“¡ï¼Œæ‰€ä»¥æˆ‘åªæ‰“算探討技術å•é¡Œï¼ˆä¸æ˜¯å°çœ‹æ³•律å•題,
法律å•題很實際,並且需è¦ä¸€ç›´é—œæ³¨ï¼‰ã€‚
-既然åªè«‡æŠ€è¡“å•題,我們就有了下é¢å…©å€‹ä¸»é¡Œï¼šäºŒé€²ä½å…§æ ¸æŽ¥å£å’Œç©©å®šçš„å…§æ ¸æº
-代碼接å£ã€‚這兩個å•題是互相關è¯çš„ï¼Œè®“æˆ‘å€‘å…ˆè§£æ±ºæŽ‰äºŒé€²ä½æŽ¥å£çš„å•題。
+既然åªè«‡æŠ€è¡“å•題,我們就有了下é¢å…©å€‹ä¸»é¡Œï¼šäºŒé€²åˆ¶å…§æ ¸æŽ¥å£å’Œç©©å®šçš„å…§æ ¸æº
+代碼接å£ã€‚這兩個å•題是互相關è¯çš„,讓我們先解決掉二進制接å£çš„å•題。
-二進ä½å…§æ ¸æŽ¥å£
+二進制內核接å£
--------------
-å‡å¦‚我們有一個穩定的內核原始碼接å£ï¼Œé‚£éº¼è‡ªç„¶è€Œç„¶çš„ï¼Œæˆ‘å€‘å°±æ“æœ‰äº†ç©©å®šçš„
-äºŒé€²ä½æŽ¥å£ï¼Œæ˜¯é€™æ¨£çš„嗎?錯。讓我們看看關於Linux內核的幾點事實:
+å‡å¦‚我們有一個穩定的內核æºä»£ç¢¼æŽ¥å£ï¼Œé‚£éº¼è‡ªç„¶è€Œç„¶çš„ï¼Œæˆ‘å€‘å°±æ“æœ‰äº†ç©©å®šçš„
+二進制接å£ï¼Œæ˜¯é€™æ¨£çš„嗎?錯。讓我們看看關於Linux內核的幾點事實:
- - å–æ±ºæ–¼æ‰€ç”¨çš„C編譯器的版本,ä¸åŒçš„å…§æ ¸æ•¸æ“šçµæ§‹é‡Œçš„çµæ§‹é«”çš„å°é½Šæ–¹
+ - å–æ±ºæ–¼æ‰€ç”¨çš„C編譯器的版本,ä¸åŒçš„å…§æ ¸æ•¸æ“šçµæ§‹è£çš„çµæ§‹é«”çš„å°é½Šæ–¹
弿œƒæœ‰å·®åˆ¥ï¼Œä»£ç¢¼ä¸­ä¸åŒå‡½æ•¸çš„表ç¾å½¢å¼ä¹Ÿä¸ä¸€æ¨£ï¼ˆå‡½æ•¸æ˜¯ä¸æ˜¯è¢«inline
ç·¨è­¯å–æ±ºæ–¼ç·¨è­¯å™¨è¡Œçˆ²ï¼‰ã€‚ä¸åŒçš„函數的表ç¾å½¢å¼ä¸¦ä¸é‡è¦ï¼Œä½†æ˜¯æ•¸æ“š
çµæ§‹å…§éƒ¨çš„å°é½Šæ–¹å¼å¾ˆé—œéµã€‚
@@ -69,33 +69,33 @@ Linux能æˆçˆ²å¼·å£¯ï¼Œç©©å®šï¼Œæˆç†Ÿçš„作業系統,這也是你最開始é¸
項。
- Linuxå¯ä»¥åœ¨å¾ˆå¤šçš„ä¸åŒé«”ç³»çµæ§‹çš„處ç†å™¨ä¸Šé‹è¡Œã€‚在æŸå€‹é«”ç³»çµæ§‹ä¸Šç·¨
- 譯好的二進ä½é©…動程åºï¼Œä¸å¯èƒ½åœ¨å¦å¤–ä¸€å€‹é«”ç³»çµæ§‹ä¸Šæ­£ç¢ºçš„é‹è¡Œã€‚
+ 譯好的二進制驅動程åºï¼Œä¸å¯èƒ½åœ¨å¦å¤–ä¸€å€‹é«”ç¹«çµæ§‹ä¸Šæ­£ç¢ºçš„é‹è¡Œã€‚
å°æ–¼ä¸€å€‹ç‰¹å®šçš„內核,滿足這些æ¢ä»¶ä¸¦ä¸é›£ï¼Œä½¿ç”¨åŒä¸€å€‹Cç·¨è­¯å™¨å’ŒåŒæ¨£çš„å…§æ ¸é…
-ç½®é¸é …ä¾†ç·¨è­¯é©…å‹•ç¨‹åºæ¨¡å¡Šå°±å¯ä»¥äº†ã€‚這尿–¼çµ¦ä¸€å€‹ç‰¹å®šLinux發布的特定版本æ
-供驅動程åºï¼Œæ˜¯å®Œå…¨å¯ä»¥æ»¿è¶³éœ€æ±‚的。但是如果你è¦çµ¦ä¸åŒç™¼å¸ƒçš„ä¸åŒç‰ˆæœ¬éƒ½ç™¼
-布一個驅動程åºï¼Œå°±éœ€è¦åœ¨æ¯å€‹ç™¼å¸ƒä¸Šç”¨ä¸åŒçš„å…§æ ¸è¨­ç½®åƒæ•¸éƒ½ç·¨è­¯ä¸€æ¬¡å…§æ ¸ï¼Œ
-é€™ç°¡ç›´è·Ÿå™©å¤¢ä¸€æ¨£ã€‚è€Œä¸”é‚„è¦æ³¨æ„到,æ¯å€‹Linux發布還æä¾›ä¸åŒçš„Linux內核,
-這些內核都é‡å°ä¸åŒçš„硬體類型進行了優化(有很多種ä¸åŒçš„處ç†å™¨ï¼Œé‚„有ä¸åŒ
-的內核設置é¸é …)。所以æ¯ç™¼å¸ƒä¸€æ¬¡é©…動程åºï¼Œéƒ½éœ€è¦æä¾›å¾ˆå¤šä¸åŒç‰ˆæœ¬çš„å…§æ ¸
+ç½®é¸é …ä¾†ç·¨è­¯é©…å‹•ç¨‹åºæ¨¡å¡Šå°±å¯ä»¥äº†ã€‚這尿–¼çµ¦ä¸€å€‹ç‰¹å®šLinux發佈的特定版本æ
+供驅動程åºï¼Œæ˜¯å®Œå…¨å¯ä»¥æ»¿è¶³éœ€æ±‚的。但是如果你è¦çµ¦ä¸åŒç™¼ä½ˆçš„ä¸åŒç‰ˆæœ¬éƒ½ç™¼
+佈一個驅動程åºï¼Œå°±éœ€è¦åœ¨æ¯å€‹ç™¼ä½ˆä¸Šç”¨ä¸åŒçš„å…§æ ¸è¨­ç½®åƒæ•¸éƒ½ç·¨è­¯ä¸€æ¬¡å…§æ ¸ï¼Œ
+é€™ç°¡ç›´è·Ÿå™©å¤¢ä¸€æ¨£ã€‚è€Œä¸”é‚„è¦æ³¨æ„到,æ¯å€‹Linux發佈還æä¾›ä¸åŒçš„Linux內核,
+這些內核都é‡å°ä¸åŒçš„硬件類型進行了優化(有很多種ä¸åŒçš„處ç†å™¨ï¼Œé‚„有ä¸åŒ
+的內核設置é¸é …)。所以æ¯ç™¼ä½ˆä¸€æ¬¡é©…動程åºï¼Œéƒ½éœ€è¦æä¾›å¾ˆå¤šä¸åŒç‰ˆæœ¬çš„å…§æ ¸
模塊。
-ç›¸ä¿¡æˆ‘ï¼Œå¦‚æžœä½ çœŸçš„è¦æŽ¡å–這種發布方å¼ï¼Œä¸€å®šæœƒæ…¢æ…¢ç˜‹æŽ‰ï¼Œæˆ‘很久以å‰å°±æœ‰éŽ
+ç›¸ä¿¡æˆ‘ï¼Œå¦‚æžœä½ çœŸçš„è¦æŽ¡å–這種發佈方å¼ï¼Œä¸€å®šæœƒæ…¢æ…¢ç˜‹æŽ‰ï¼Œæˆ‘很久以å‰å°±æœ‰éŽ
深刻的教訓...
-穩定的內核原始碼接å£
+穩定的內核æºä»£ç¢¼æŽ¥å£
--------------------
-如果有人ä¸å°‡ä»–的內核驅動程åºï¼Œæ”¾å…¥å…¬ç‰ˆå…§æ ¸çš„åŽŸå§‹ç¢¼æ¨¹ï¼Œè€Œåˆæƒ³è®“驅動程åº
+如果有人ä¸å°‡ä»–的內核驅動程åºï¼Œæ”¾å…¥å…¬ç‰ˆå…§æ ¸çš„æºä»£ç¢¼æ¨¹ï¼Œè€Œåˆæƒ³è®“驅動程åº
ä¸€ç›´ä¿æŒåœ¨æœ€æ–°çš„內核中å¯ç”¨ï¼Œé‚£éº¼é€™å€‹è©±é¡Œå°‡æœƒè®Šå¾—沒完沒了。
內核開發是æŒçºŒè€Œä¸”快節å¥çš„ï¼Œå¾žä¾†éƒ½ä¸æœƒæ…¢ä¸‹ä¾†ã€‚å…§æ ¸é–‹ç™¼äººå“¡åœ¨ç•¶å‰æŽ¥å£ä¸­
找到bugï¼Œæˆ–è€…æ‰¾åˆ°æ›´å¥½çš„å¯¦ç¾æ–¹å¼ã€‚一旦發ç¾é€™äº›ï¼Œä»–們就很快會去修改當å‰çš„
-接å£ã€‚ä¿®æ”¹æŽ¥å£æ„味著,函數åå¯èƒ½æœƒæ”¹è®Šï¼Œçµæ§‹é«”å¯èƒ½è¢«æ“´å……或者刪減,函數
+接å£ã€‚ä¿®æ”¹æŽ¥å£æ„味ç€ï¼Œå‡½æ•¸åå¯èƒ½æœƒæ”¹è®Šï¼Œçµæ§‹é«”å¯èƒ½è¢«æ“´å……或者刪減,函數
çš„åƒæ•¸ä¹Ÿå¯èƒ½ç™¼ç”Ÿæ”¹è®Šã€‚一旦接å£è¢«ä¿®æ”¹ï¼Œå…§æ ¸ä¸­ä½¿ç”¨é€™äº›æŽ¥å£çš„地方需è¦åŒæ™‚
修正,這樣æ‰èƒ½ä¿è­‰æ‰€æœ‰çš„æ±è¥¿ç¹¼çºŒå·¥ä½œã€‚
-舉一個例å­ï¼Œå…§æ ¸çš„USBé©…å‹•ç¨‹åºæŽ¥å£åœ¨USBå­ç³»çµ±çš„æ•´å€‹ç”Ÿå‘½å‘¨æœŸä¸­ï¼Œè‡³å°‘ç¶“æ­·
+舉一個例å­ï¼Œå…§æ ¸çš„USBé©…å‹•ç¨‹åºæŽ¥å£åœ¨USBå­ç³»çµ±çš„æ•´å€‹ç”Ÿå‘½é€±æœŸä¸­ï¼Œè‡³å°‘ç¶“æ­·
了三次é‡å¯«ã€‚這些é‡å¯«è§£æ±ºä»¥ä¸‹å•題:
- 把數據æµå¾žåŒæ­¥æ¨¡å¼æ”¹æˆéžåŒæ­¥æ¨¡å¼ï¼Œé€™å€‹æ”¹å‹•減少了一些驅動程åºçš„
@@ -104,11 +104,11 @@ Linux能æˆçˆ²å¼·å£¯ï¼Œç©©å®šï¼Œæˆç†Ÿçš„作業系統,這也是你最開始é¸
- 修改了USB核心代碼中爲USBé©…å‹•åˆ†é…æ•¸æ“šåŒ…內存的方å¼ï¼Œæ‰€æœ‰çš„驅動都
éœ€è¦æä¾›æ›´å¤šçš„åƒæ•¸çµ¦USB核心,以修正了很多已經被記錄在案的死鎖。
-這和一些å°é–‰åŽŸå§‹ç¢¼çš„ä½œæ¥­ç³»çµ±å½¢æˆé®®æ˜Žçš„å°æ¯”,在那些作業系統上,ä¸å¾—ä¸é¡
+這和一些å°é–‰æºä»£ç¢¼çš„æ“ä½œç³»çµ±å½¢æˆé®®æ˜Žçš„å°æ¯”,在那些æ“作系統上,ä¸å¾—ä¸é¡
外的維護舊的USB接å£ã€‚這導致了一個å¯èƒ½æ€§ï¼Œæ–°çš„開發者ä¾ç„¶æœƒä¸å°å¿ƒä½¿ç”¨èˆŠçš„
-接å£ï¼Œä»¥ä¸æ°ç•¶çš„æ–¹å¼ç·¨å¯«ä»£ç¢¼ï¼Œé€²è€Œå½±éŸ¿åˆ°ä½œæ¥­ç³»çµ±çš„穩定性。
+接å£ï¼Œä»¥ä¸æ°ç•¶çš„æ–¹å¼ç·¨å¯«ä»£ç¢¼ï¼Œé€²è€Œå½±éŸ¿åˆ°æ“作系統的穩定性。
在上é¢çš„例å­ä¸­ï¼Œæ‰€æœ‰çš„é–‹ç™¼è€…éƒ½åŒæ„這些é‡è¦çš„æ”¹å‹•,在這樣的情æ³ä¸‹ä¿®æ”¹ä»£
-價很低。如果Linuxä¿æŒä¸€å€‹ç©©å®šçš„內核原始碼接å£ï¼Œé‚£éº¼å°±å¾—創建一個新的接å£
+價很低。如果Linuxä¿æŒä¸€å€‹ç©©å®šçš„å…§æ ¸æºä»£ç¢¼æŽ¥å£ï¼Œé‚£éº¼å°±å¾—創建一個新的接å£
;舊的,有å•題的接å£å¿…須一直維護,給Linux USB開發者帶來é¡å¤–的工作。既然
所有的Linux USBé©…å‹•çš„ä½œè€…éƒ½æ˜¯åˆ©ç”¨è‡ªå·±çš„æ™‚é–“å·¥ä½œï¼Œé‚£éº¼è¦æ±‚ä»–å€‘åŽ»åšæ¯«ç„¡æ„
義的å…è²»é¡å¤–工作,是ä¸å¯èƒ½çš„。
@@ -126,28 +126,28 @@ Linux能æˆçˆ²å¼·å£¯ï¼Œç©©å®šï¼Œæˆç†Ÿçš„作業系統,這也是你最開始é¸
è¦åšä»€éº¼
--------
-如果你寫了一個Linux內核驅動,但是它還ä¸åœ¨Linux原始碼樹里,作爲一個開發
-者,你應該怎麼åšï¼Ÿçˆ²æ¯å€‹ç™¼å¸ƒçš„æ¯å€‹ç‰ˆæœ¬æä¾›ä¸€å€‹äºŒé€²ä½é©…動,那簡直是一個
+如果你寫了一個Linux內核驅動,但是它還ä¸åœ¨Linuxæºä»£ç¢¼æ¨¹è£ï¼Œä½œçˆ²ä¸€å€‹é–‹ç™¼
+者,你應該怎麼åšï¼Ÿçˆ²æ¯å€‹ç™¼ä½ˆçš„æ¯å€‹ç‰ˆæœ¬æä¾›ä¸€å€‹äºŒé€²åˆ¶é©…動,那簡直是一個
噩夢,è¦è·Ÿä¸Šæ°¸é è™•於變化之中的內核接å£ï¼Œä¹Ÿæ˜¯ä¸€ä»¶è¾›è‹¦æ´»ã€‚
-很簡單,讓你的驅動進入內核原始碼樹(è¦è¨˜å¾—我們在談論的是以GPL許å¯ç™¼è¡Œ
+很簡單,讓你的驅動進入內核æºä»£ç¢¼æ¨¹ï¼ˆè¦è¨˜å¾—我們在談論的是以GPL許å¯ç™¼è¡Œ
的驅動,如果你的代碼ä¸ç¬¦åˆGPL,那麼ç¥ä½ å¥½é‹ï¼Œä½ åªèƒ½è‡ªå·±è§£æ±ºé€™å€‹å•題了,
-你這個å¸è¡€é¬¼<把Andrewå’ŒLinuså°å¸è¡€é¬¼çš„定義連çµåˆ°é€™è£¡>)。當你的代碼加入
-å…¬ç‰ˆå…§æ ¸åŽŸå§‹ç¢¼æ¨¹ä¹‹å¾Œï¼Œå¦‚æžœä¸€å€‹å…§æ ¸æŽ¥å£æ”¹è®Šï¼Œä½ çš„驅動會直接被修改接å£çš„
+你這個å¸è¡€é¬¼<把Andrewå’ŒLinuså°å¸è¡€é¬¼çš„å®šç¾©éˆæŽ¥åˆ°é€™è£>)。當你的代碼加入
+公版內核æºä»£ç¢¼æ¨¹ä¹‹å¾Œï¼Œå¦‚æžœä¸€å€‹å…§æ ¸æŽ¥å£æ”¹è®Šï¼Œä½ çš„驅動會直接被修改接å£çš„
那個人修改。ä¿è­‰ä½ çš„é©…å‹•æ°¸é éƒ½å¯ä»¥ç·¨è­¯é€šéŽï¼Œä¸¦ä¸”一直工作,你幾乎ä¸éœ€è¦
åšä»€éº¼äº‹æƒ…。
-把驅動放到內核原始碼樹里會有很多的好處:
+把驅動放到內核æºä»£ç¢¼æ¨¹è£æœƒæœ‰å¾ˆå¤šçš„好處:
- é©…å‹•çš„è³ªé‡æœƒæå‡ï¼Œè€Œç¶­è­·æˆæœ¬ï¼ˆå°åŽŸå§‹ä½œè€…ä¾†èªªï¼‰æœƒä¸‹é™ã€‚
- 其他人會給驅動添加新特性。
- 其他人會找到驅動中的bug並修復。
- 其他人會在驅動中找到性能優化的機會。
- 當外部的接å£çš„æ”¹è®Šéœ€è¦ä¿®æ”¹é©…動程åºçš„æ™‚候,其他人會修改驅動程åº
- - ä¸éœ€è¦è¯ç¹«ä»»ä½•發行商,這個驅動會自動的隨著所有的Linux發布一起發
+ - ä¸éœ€è¦è¯ç¹«ä»»ä½•ç™¼è¡Œå•†ï¼Œé€™å€‹é©…å‹•æœƒè‡ªå‹•çš„éš¨ç€æ‰€æœ‰çš„Linux發佈一起發
布。
-和別的作業系統相比,Linux爲更多ä¸åŒçš„設備æä¾›ç¾æˆçš„驅動,而且能在更多ä¸
-åŒé«”ç³»çµæ§‹çš„處ç†å™¨ä¸Šæ”¯æŒé€™äº›è¨­å‚™ã€‚這個經éŽè€ƒé©—的開發模å¼ï¼Œå¿…然是錯ä¸äº†
+和別的æ“作系統相比,Linux爲更多ä¸åŒçš„設備æä¾›ç¾æˆçš„驅動,而且能在更多ä¸
+åŒé«”ç¹«çµæ§‹çš„處ç†å™¨ä¸Šæ”¯æŒé€™äº›è¨­å‚™ã€‚這個經éŽè€ƒé©—的開發模å¼ï¼Œå¿…然是錯ä¸äº†
çš„ :)
感è¬
diff --git a/Documentation/translations/zh_TW/process/stable-kernel-rules.rst b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
index 29d9a70a1868..bd82a8ff3969 100644
--- a/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
+++ b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
@@ -17,10 +17,10 @@
- Kangkai Yin <e12051@motorola.com>
- 胡皓文 Hu Haowen <src.res.211@gmail.com>
-所有你想知é“的事情 - 關於linux穩定版發布
+所有你想知é“的事情 - 關於linux穩定版發佈
========================================
-關於Linux 2.6穩定版發布,所有你想知é“的事情。
+關於Linux 2.6穩定版發佈,所有你想知é“的事情。
關於哪些類型的補ä¸å¯ä»¥è¢«æŽ¥æ”¶é€²å…¥ç©©å®šç‰ˆä»£ç¢¼æ¨¹ï¼Œå“ªäº›ä¸å¯ä»¥çš„è¦å‰‡ï¼š
----------------------------------------------------------------
@@ -28,39 +28,39 @@
- å¿…é ˆæ˜¯é¡¯è€Œæ˜“è¦‹çš„æ­£ç¢ºï¼Œä¸¦ä¸”ç¶“éŽæ¸¬è©¦çš„。
- 連åŒä¸Šä¸‹æ–‡ï¼Œä¸èƒ½å¤§æ–¼100行。
- å¿…é ˆåªä¿®æ­£ä¸€ä»¶äº‹æƒ…。
- - 必須修正了一個給大家帶來麻煩的真正的bugï¼ˆä¸æ˜¯ã€Œé€™ä¹Ÿè¨±æ˜¯ä¸€å€‹å•題...ã€
+ - 必須修正了一個給大家帶來麻煩的真正的bugï¼ˆä¸æ˜¯â€œé€™ä¹Ÿè¨±æ˜¯ä¸€å€‹å•題...â€
那樣的æ±è¥¿ï¼‰ã€‚
- 必須修正帶來如下後果的å•題:編譯錯誤(å°è¢«æ¨™è¨˜çˆ²CONFIG_BROKEN的例外),
- 內核崩潰,掛起,數據æå£žï¼ŒçœŸæ­£çš„安全å•題,或者一些類似「哦,這ä¸
- 好ã€çš„å•題。簡短的說,就是一些致命的å•題。
- - 沒有「ç†è«–上的競爭æ¢ä»¶ã€ï¼Œé™¤éžèƒ½çµ¦å‡ºç«¶çˆ­æ¢ä»¶å¦‚何被利用的解釋。
- - ä¸èƒ½å­˜åœ¨ä»»ä½•的「瑣碎的ã€ä¿®æ­£ï¼ˆæ‹¼å¯«ä¿®æ­£ï¼ŒåŽ»æŽ‰å¤šé¤˜ç©ºæ ¼ä¹‹é¡žçš„ï¼‰ã€‚
+ 內核崩潰,掛起,數據æå£žï¼ŒçœŸæ­£çš„安全å•題,或者一些類似“哦,這ä¸
+ 好â€çš„å•題。簡短的說,就是一些致命的å•題。
+ - 沒有“ç†è«–上的競爭æ¢ä»¶â€ï¼Œé™¤éžèƒ½çµ¦å‡ºç«¶çˆ­æ¢ä»¶å¦‚何被利用的解釋。
+ - ä¸èƒ½å­˜åœ¨ä»»ä½•的“瑣碎的â€ä¿®æ­£ï¼ˆæ‹¼å¯«ä¿®æ­£ï¼ŒåŽ»æŽ‰å¤šé¤˜ç©ºæ ¼ä¹‹é¡žçš„ï¼‰ã€‚
- 必須被相關å­ç³»çµ±çš„維護者接å—。
- - å¿…é ˆéµå¾ªDocumentation/translations/zh_TW/process/submitting-patches.rst里的è¦å‰‡ã€‚
+ - å¿…é ˆéµå¾ªDocumentation/translations/zh_CN/process/submitting-patches.rstè£çš„è¦å‰‡ã€‚
å‘穩定版代碼樹æäº¤è£œä¸çš„éŽç¨‹ï¼š
------------------------------
- 在確èªäº†è£œä¸ç¬¦åˆä»¥ä¸Šçš„è¦å‰‡å¾Œï¼Œå°‡è£œä¸ç™¼é€åˆ°stable@vger.kernel.org。
- - 如果補ä¸è¢«æŽ¥å—到隊列里,發é€è€…會收到一個ACK回復,如果沒有被接å—,收
- 到的是NAK回復。回復需è¦å¹¾å¤©çš„æ™‚é–“ï¼Œé€™å–æ±ºæ–¼é–‹ç™¼è€…的時間安排。
- - 被接å—çš„è£œä¸æœƒè¢«åŠ åˆ°ç©©å®šç‰ˆæœ¬éšŠåˆ—é‡Œï¼Œç­‰å¾…å…¶ä»–é–‹ç™¼è€…çš„å¯©æŸ¥ã€‚
+ - 如果補ä¸è¢«æŽ¥å—到隊列è£ï¼Œç™¼é€è€…會收到一個ACK回覆,如果沒有被接å—,收
+ 到的是NAK回覆。回覆需è¦å¹¾å¤©çš„æ™‚é–“ï¼Œé€™å–æ±ºæ–¼é–‹ç™¼è€…的時間安排。
+ - 被接å—çš„è£œä¸æœƒè¢«åŠ åˆ°ç©©å®šç‰ˆæœ¬éšŠåˆ—è£ï¼Œç­‰å¾…其他開發者的審查。
- 安全方é¢çš„補ä¸ä¸è¦ç™¼åˆ°é€™å€‹åˆ—表,應該發é€åˆ°security@kernel.org。
-審查周期:
+審查週期:
----------
- - 當穩定版的維護者決定開始一個審查周期,補ä¸å°‡è¢«ç™¼é€åˆ°å¯©æŸ¥å§”員會,以
+ - 當穩定版的維護者決定開始一個審查週期,補ä¸å°‡è¢«é«®é€åˆ°å¯©æŸ¥å§”員會,以
åŠè¢«è£œä¸å½±éŸ¿çš„é ˜åŸŸçš„ç¶­è­·è€…ï¼ˆé™¤éžæäº¤è€…å°±æ˜¯è©²é ˜åŸŸçš„ç¶­è­·è€…ï¼‰ä¸¦ä¸”æŠ„é€
到linux-kernel郵件列表。
- - 審查委員會有48å°æ™‚的時間,用來決定給該補ä¸å›žå¾©ACK還是NAK。
+ - 審查委員會有48å°æ™‚的時間,用來決定給該補ä¸å›žè¦†ACK還是NAK。
- 如果委員會中有æˆå“¡æ‹’絕這個補ä¸ï¼Œæˆ–者linux-kernel列表上有人åå°é€™å€‹
補ä¸ï¼Œä¸¦æå‡ºç¶­è­·è€…å’Œå¯©æŸ¥å§”å“¡æœƒä¹‹å‰æ²’有æ„識到的å•é¡Œï¼Œè£œä¸æœƒå¾žéšŠåˆ—中
丟棄。
- - åœ¨å¯©æŸ¥å‘¨æœŸçµæŸçš„æ™‚候,那些得到ACK回應的補ä¸å°‡æœƒè¢«åŠ å…¥åˆ°æœ€æ–°çš„ç©©å®šç‰ˆ
- 發布中,一個新的穩定版發布就此產生。
- - 安全性補ä¸å°‡å¾žå…§æ ¸å®‰å…¨å°çµ„é‚£è£¡ç›´æŽ¥æŽ¥æ”¶åˆ°ç©©å®šç‰ˆä»£ç¢¼æ¨¹ä¸­ï¼Œè€Œä¸æ˜¯é€šéŽ
- 通常的審查周期。請è¯ç¹«å…§æ ¸å®‰å…¨å°çµ„以ç²å¾—關於這個éŽç¨‹çš„æ›´å¤šç´°ç¯€ã€‚
+ - åœ¨å¯©æŸ¥é€±æœŸçµæŸçš„æ™‚候,那些得到ACK回應的補ä¸å°‡æœƒè¢«åŠ å…¥åˆ°æœ€æ–°çš„ç©©å®šç‰ˆ
+ 發佈中,一個新的穩定版發佈就此產生。
+ - 安全性補ä¸å°‡å¾žå…§æ ¸å®‰å…¨å°çµ„é‚£è£ç›´æŽ¥æŽ¥æ”¶åˆ°ç©©å®šç‰ˆä»£ç¢¼æ¨¹ä¸­ï¼Œè€Œä¸æ˜¯é€šéŽ
+ 通常的審查週期。請è¯ç¹«å…§æ ¸å®‰å…¨å°çµ„以ç²å¾—關於這個éŽç¨‹çš„æ›´å¤šç´°ç¯€ã€‚
審查委員會:
------------
diff --git a/Documentation/translations/zh_TW/process/submit-checklist.rst b/Documentation/translations/zh_TW/process/submit-checklist.rst
index 12bf6f5ca5c6..942962d1e2f4 100644
--- a/Documentation/translations/zh_TW/process/submit-checklist.rst
+++ b/Documentation/translations/zh_TW/process/submit-checklist.rst
@@ -2,108 +2,114 @@
.. include:: ../disclaimer-zh_TW.rst
-:Original: :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`
-:Translator: Alex Shi <alex.shi@linux.alibaba.com>
- Hu Haowen <src.res.211@gmail.com>
+:Original: Documentation/process/submit-checklist.rst
+:Translator:
+ - Alex Shi <alexs@kernel.org>
+ - Wu XiangCheng <bobwxc@email.cn>
+ - Hu Haowen <src.res.211@gmail.com>
.. _tw_submitchecklist:
-Linuxå…§æ ¸è£œä¸æäº¤æ¸…å–®
-~~~~~~~~~~~~~~~~~~~~~
+Linuxå…§æ ¸è£œä¸æäº¤æª¢æŸ¥å–®
+~~~~~~~~~~~~~~~~~~~~~~~
å¦‚æžœé–‹ç™¼äººå“¡å¸Œæœ›çœ‹åˆ°ä»–å€‘çš„å…§æ ¸è£œä¸æäº¤æ›´å¿«åœ°è¢«æŽ¥å—,那麼他們應該åšä¸€äº›åŸºæœ¬
的事情。
-這些都是在
-:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+這些都是在 Documentation/translations/zh_CN/process/submitting-patches.rst
和其他有關æäº¤Linux內核補ä¸çš„æ–‡æª”中æä¾›çš„。
-1) 如果使用工具,則包括定義/è²æ˜Žè©²å·¥å…·çš„æ–‡ä»¶ã€‚ä¸è¦ä¾è³´æ–¼å…¶ä»–頭文件拉入您使用
+1) 如果使用工具,則包括定義/è²æ˜Žè©²å·¥å…·çš„æ–‡ä»¶ã€‚ä¸è¦ä¾è³´å…¶ä»–頭文件來引入您使用
的頭文件。
2) 乾淨的編譯:
- a) 使用é©ç”¨æˆ–修改的 ``CONFIG`` é¸é … ``=y``ã€``=m`` å’Œ ``=n`` 。沒有GCC
- 警告/錯誤,沒有連çµå™¨è­¦å‘Š/錯誤。
+ a) 使用åˆé©çš„ ``CONFIG`` é¸é … ``=y``ã€``=m`` å’Œ ``=n`` 。沒有 ``gcc``
+ 警告/éŒ¯èª¤ï¼Œæ²’æœ‰éˆæŽ¥å™¨è­¦å‘Š/錯誤。
- b) 通éŽallnoconfigã€allmodconfig
+ b) é€šéŽ ``allnoconfig`` 〠``allmodconfig``
c) 使用 ``O=builddir`` 時å¯ä»¥æˆåŠŸç·¨è­¯
-3) 通éŽä½¿ç”¨æœ¬åœ°äº¤å‰ç·¨è­¯å·¥å…·æˆ–其他一些構建場在多個CPUé«”ç³»çµæ§‹ä¸Šæ§‹å»ºã€‚
+ d) 任何 Doucmentation/ 下的變更都能æˆåŠŸæ§‹å»ºä¸”ä¸å¼•入新警告/錯誤。
+ 用 ``make htmldocs`` 或 ``make pdfdocs`` 檢驗構建情æ³ä¸¦ä¿®å¾©å•題。
+
+3) 通éŽä½¿ç”¨æœ¬åœ°äº¤å‰ç·¨è­¯å·¥å…·æˆ–其他一些構建設施在多個CPUé«”ç³»çµæ§‹ä¸Šæ§‹å»ºã€‚
4) PPC64是一種很好的交å‰ç·¨è­¯æª¢æŸ¥é«”ç³»çµæ§‹ï¼Œå› çˆ²å®ƒå‚¾å‘æ–¼å°64ä½çš„æ•¸ä½¿ç”¨ç„¡ç¬¦è™Ÿ
長整型。
-5) 如下所述 :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`.
- æª¢æŸ¥æ‚¨çš„è£œä¸æ˜¯å¦çˆ²å¸¸è¦æ¨£å¼ã€‚在æäº¤ï¼ˆ ``scripts/check patch.pl`` )之å‰ï¼Œ
- ä½¿ç”¨è£œä¸æ¨£å¼æª¢æŸ¥å™¨æª¢æŸ¥æ˜¯å¦æœ‰è¼•微的è¡çªã€‚æ‚¨æ‡‰è©²èƒ½å¤ è™•ç†æ‚¨çš„補ä¸ä¸­å­˜åœ¨çš„æ‰€æœ‰
+5) 按 Documentation/translations/zh_CN/process/coding-style.rst 所述檢查您的
+ è£œä¸æ˜¯å¦çˆ²å¸¸è¦æ¨£å¼ã€‚在æäº¤ä¹‹å‰ä½¿ç”¨è£œä¸æ¨£å¼æª¢æŸ¥å™¨ ``scripts/checkpatch.pl``
+ æª¢æŸ¥æ˜¯å¦æœ‰è¼•微的è¡çªã€‚æ‚¨æ‡‰è©²èƒ½å¤ è™•ç†æ‚¨çš„補ä¸ä¸­å­˜åœ¨çš„æ‰€æœ‰
é•è¦è¡Œçˆ²ã€‚
-6) 任何新的或修改éŽçš„ ``CONFIG`` é¸é …éƒ½ä¸æœƒå¼„é«’é…ç½®èœå–®ï¼Œä¸¦é»˜èªçˆ²é—œé–‰ï¼Œé™¤éž
- å®ƒå€‘ç¬¦åˆ ``Documentation/kbuild/kconfig-language.rst`` 中記錄的異常æ¢ä»¶,
- èœå–®å±¬æ€§ï¼šé»˜èªå€¼.
+6) 任何新的或修改éŽçš„ ``CONFIG`` é¸é …éƒ½ä¸æ‡‰æžäº‚é…ç½®èœå–®ï¼Œä¸¦é»˜èªçˆ²é—œé–‰ï¼Œé™¤éž
+ å®ƒå€‘ç¬¦åˆ ``Documentation/kbuild/kconfig-language.rst`` èœå–®å±¬æ€§ï¼šé»˜èªå€¼ä¸­
+ 記錄的例外æ¢ä»¶ã€‚
7) 所有新的 ``kconfig`` é¸é …都有幫助文本。
-8) 已仔細審查了相關的 ``Kconfig`` 組åˆã€‚這很難用測試來糾正——腦力在這裡是有
+8) 已仔細審查了相關的 ``Kconfig`` 組åˆã€‚é€™å¾ˆé›£ç”¨æ¸¬è©¦ä¾†ç³¾æ­£â€”â€”è…¦åŠ›åœ¨é€™è£æ˜¯æœ‰
回報的。
-9) 用 sparse 檢查乾淨。
+9) é€šéŽ sparse 清查。
+ (åƒè¦‹ Documentation/translations/zh_CN/dev-tools/sparse.rst )
10) 使用 ``make checkstack`` å’Œ ``make namespacecheck`` 並修復他們發ç¾çš„任何
å•題。
.. note::
- ``checkstack`` 並沒有明確指出å•題,但是任何一個在堆棧上使用超éŽ512
+ ``checkstack`` 䏦䏿œƒæ˜Žç¢ºæŒ‡å‡ºå•題,但是任何一個在堆棧上使用超éŽ512
字節的函數都å¯ä»¥é€²è¡Œæ›´æ”¹ã€‚
-11) 包括 :ref:`kernel-doc <kernel_doc>` 內核文檔以記錄全局內核APIã€‚ï¼ˆéœæ…‹å‡½æ•¸
- ä¸éœ€è¦ï¼Œä½†ä¹Ÿå¯ä»¥ã€‚)使用 ``make htmldocs`` 或 ``make pdfdocs`` 檢查
- :ref:`kernel-doc <kernel_doc>` 並修復任何å•題。
+11) 包括 :ref:`kernel-doc <kernel_doc_zh>` 內核文檔以記錄全局內核APIã€‚ï¼ˆéœæ…‹
+ 函數ä¸éœ€è¦ï¼Œä½†ä¹Ÿå¯ä»¥ã€‚)使用 ``make htmldocs`` 或 ``make pdfdocs`` 檢查
+ :ref:`kernel-doc <kernel_doc_zh>` 並修復任何å•題。
-12) 通éŽä»¥ä¸‹é¸é …åŒæ™‚啓用的測試 ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
+12) 通éŽä»¥ä¸‹é¸é …åŒæ™‚啓用的測試: ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``,
``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``,
- ``CONFIG_PROVE_RCU`` and ``CONFIG_DEBUG_OBJECTS_RCU_HEAD``
-
-13) å·²ç¶“éŽæ§‹å»ºå’Œé‹è¡Œæ™‚測試,包括有或沒有 ``CONFIG_SMP``, ``CONFIG_PREEMPT``.
+ ``CONFIG_PROVE_RCU`` 和 ``CONFIG_DEBUG_OBJECTS_RCU_HEAD`` 。
-14) 如果補ä¸ç¨‹åºå½±éŸ¿IO/ç£ç¢Ÿç­‰ï¼šä½¿ç”¨æˆ–ä¸ä½¿ç”¨ ``CONFIG_LBDAF`` 進行測試。
+13) 在 ``CONFIG_SMP``, ``CONFIG_PREEMPT`` 開啓和關閉的情æ³ä¸‹éƒ½é€²è¡Œæ§‹å»ºå’Œé‹è¡Œ
+ 時測試。
-15) 所有代碼路徑都已在啓用所有lockdep功能的情æ³ä¸‹é‹è¡Œã€‚
+14) 所有代碼路徑都已在啓用所有死鎖檢測(lockdep)功能的情æ³ä¸‹é‹è¡Œã€‚
-16) 所有新的/procæ¢ç›®éƒ½è¨˜éŒ„在 ``Documentation/``
+15) 所有新的 ``/proc`` æ¢ç›®éƒ½è¨˜éŒ„在 ``Documentation/``
-17) æ‰€æœ‰æ–°çš„å…§æ ¸å¼•å°Žåƒæ•¸éƒ½è¨˜éŒ„在
+16) æ‰€æœ‰æ–°çš„å…§æ ¸å¼•å°Žåƒæ•¸éƒ½è¨˜éŒ„在
Documentation/admin-guide/kernel-parameters.rst 中。
-18) æ‰€æœ‰æ–°çš„æ¨¡å¡Šåƒæ•¸éƒ½è¨˜éŒ„在 ``MODULE_PARM_DESC()``
+17) æ‰€æœ‰æ–°çš„æ¨¡å¡Šåƒæ•¸éƒ½è¨˜éŒ„在 ``MODULE_PARM_DESC()``
-19) 所有新的用戶空間接å£éƒ½è¨˜éŒ„在 ``Documentation/ABI/`` 中。有關詳細信æ¯ï¼Œ
+18) 所有新的用戶空間接å£éƒ½è¨˜éŒ„在 ``Documentation/ABI/`` 中。有關詳細信æ¯ï¼Œ
è«‹åƒé–± ``Documentation/ABI/README`` 。更改用戶空間接å£çš„è£œä¸æ‡‰è©²æŠ„é€
linux-api@vger.kernel.org。
-20) 已通éŽè‡³å°‘注入slabå’Œpage分é…失敗進行檢查。請åƒé–± ``Documentation/fault-injection/``
+19) 已通éŽè‡³å°‘注入slabå’Œpage分é…失敗進行檢查。請åƒé–± ``Documentation/fault-injection/`` 。
如果新代碼是實質性的,那麼添加å­ç³»çµ±ç‰¹å®šçš„æ•…障注入å¯èƒ½æ˜¯åˆé©çš„。
-21) 新添加的代碼已經用 ``gcc -W`` 編譯(使用 ``make EXTRA-CFLAGS=-W`` )。這
- 將產生大é‡å™ªè²ï¼Œä½†å°æ–¼æŸ¥æ‰¾è«¸å¦‚「警告:有符號和無符號之間的比較ã€ä¹‹é¡žçš„錯誤
+20) 新添加的代碼已經用 ``gcc -W`` 編譯(使用 ``make EXTRA-CFLAGS=-W`` )。這
+ 將產生大é‡å™ªè²ï¼Œä½†å°æ–¼æŸ¥æ‰¾è«¸å¦‚“警告:有符號和無符號之間的比較â€ä¹‹é¡žçš„錯誤
很有用。
-22) 在它被åˆä½µåˆ°-mm補ä¸é›†ä¸­ä¹‹å¾Œé€²è¡Œæ¸¬è©¦ï¼Œä»¥ç¢ºä¿å®ƒä»ç„¶èˆ‡æ‰€æœ‰å…¶ä»–排隊的補ä¸ä»¥
+21) 在它被åˆä½µåˆ°-mm補ä¸é›†ä¸­ä¹‹å¾Œé€²è¡Œæ¸¬è©¦ï¼Œä»¥ç¢ºä¿å®ƒä»ç„¶èˆ‡æ‰€æœ‰å…¶ä»–排隊的補ä¸ä»¥
åŠVMã€VFS和其他å­ç³»çµ±ä¸­çš„å„種更改一起工作。
-23) 所有內存å±éšœä¾‹å¦‚ ``barrier()``, ``rmb()``, ``wmb()`` 都需è¦åŽŸå§‹ç¢¼ä¸­çš„æ³¨
+22) 所有內存å±éšœï¼ˆä¾‹å¦‚ ``barrier()``, ``rmb()``, ``wmb()`` ï¼‰éƒ½éœ€è¦æºä»£ç¢¼æ³¨
釋來解釋它們正在執行的æ“作åŠå…¶åŽŸå› çš„é‚輯。
-24) å¦‚æžœè£œä¸æ·»åŠ äº†ä»»ä½•ioctlï¼Œé‚£éº¼ä¹Ÿè¦æ›´æ–° ``Documentation/userspace-api/ioctl/ioctl-number.rst``
+23) å¦‚æžœè£œä¸æ·»åŠ äº†ä»»ä½•ioctlï¼Œé‚£éº¼ä¹Ÿè¦æ›´æ–°
+ ``Documentation/userspace-api/ioctl/ioctl-number.rst`` 。
-25) 如果修改後的原始碼ä¾è³´æˆ–使用與以下 ``Kconfig`` 符號相關的任何內核API或
+24) 如果修改後的æºä»£ç¢¼ä¾è³´æˆ–使用與以下 ``Kconfig`` 符號相關的任何內核API或
功能,則在ç¦ç”¨ç›¸é—œ ``Kconfig`` 符號和/或 ``=m`` (如果該é¸é …å¯ç”¨ï¼‰çš„æƒ…æ³
下測試以下多個構建[ä¸¦éžæ‰€æœ‰é€™äº›éƒ½åŒæ™‚å­˜åœ¨ï¼Œåªæ˜¯å®ƒå€‘çš„å„種/隨機組åˆ]:
- ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``, ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
- ``CONFIG_NET``, ``CONFIG_INET=n`` (但是後者伴隨 ``CONFIG_NET=y``).
+ ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``,
+ ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
+ ``CONFIG_NET``, ``CONFIG_INET=n`` ï¼ˆä½†æ˜¯æœ€å¾Œä¸€å€‹éœ€è¦ ``CONFIG_NET=y`` )。
diff --git a/Documentation/translations/zh_TW/process/submitting-patches.rst b/Documentation/translations/zh_TW/process/submitting-patches.rst
index 0746809c31a2..8272b3218b54 100644
--- a/Documentation/translations/zh_TW/process/submitting-patches.rst
+++ b/Documentation/translations/zh_TW/process/submitting-patches.rst
@@ -1,229 +1,199 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. _tw_submittingpatches:
+.. SPDX-License-Identifier: GPL-2.0-or-later
.. include:: ../disclaimer-zh_TW.rst
-:Original: :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+.. _tw_submittingpatches:
-譯者::
+:Original: Documentation/process/submitting-patches.rst
- 中文版維護者: é¾å®‡ TripleX Chung <xxx.phy@gmail.com>
- 中文版翻譯者: é¾å®‡ TripleX Chung <xxx.phy@gmail.com>
- 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
- 中文版校譯者: æŽé™½ Li Yang <leoyang.li@nxp.com>
- çŽ‹è° Wang Cong <xiyou.wangcong@gmail.com>
- 胡皓文 Hu Haowen <src.res.211@gmail.com>
+:譯者:
+ - é¾å®‡ TripleX Chung <xxx.phy@gmail.com>
+ - 時奎亮 Alex Shi <alexs@kernel.org>
+ - 峿ƒ³æˆ Wu XiangCheng <bobwxc@email.cn>
+:æ ¡è­¯:
+ - æŽé™½ Li Yang <leoyang.li@nxp.com>
+ - çŽ‹è° Wang Cong <xiyou.wangcong@gmail.com>
+ - 胡皓文 Hu Haowen <src.res.211@gmail.com>
-如何讓你的改動進入內核
-======================
-å°æ–¼æƒ³è¦å°‡æ”¹å‹•æäº¤åˆ° Linux 內核的個人或者公å¸ä¾†èªªï¼Œå¦‚æžœä¸ç†Ÿæ‚‰ã€Œè¦çŸ©ã€ï¼Œ
-æäº¤çš„æµç¨‹æœƒè®“äººç•æ‡¼ã€‚本文檔收集了一系列建議,這些建議å¯ä»¥å¤§å¤§çš„æé«˜ä½ 
+æäº¤è£œä¸ï¼šå¦‚何讓你的改動進入內核
+================================
+
+å°æ–¼æƒ³è¦å°‡æ”¹å‹•æäº¤åˆ° Linux 內核的個人或者公å¸ä¾†èªªï¼Œå¦‚æžœä¸ç†Ÿæ‚‰â€œè¦çŸ©â€ï¼Œ
+æäº¤çš„æµç¨‹æœƒè®“äººç•æ‡¼ã€‚本文檔包å«äº†ä¸€ç³»åˆ—建議,å¯ä»¥å¤§å¤§æé«˜ä½ 
的改動被接å—的機會.
-ä»¥ä¸‹æ–‡æª”å«æœ‰å¤§é‡ç°¡æ½”的建議, 具體請見:
-:ref:`Documentation/process <development_process_main>`
-åŒæ¨£ï¼Œ:ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`
-給出在æäº¤ä»£ç¢¼å‰éœ€è¦æª¢æŸ¥çš„項目的列表。
+本文檔以較爲簡潔的行文給出了大é‡å»ºè­°ã€‚關於內核開發æµç¨‹å¦‚何進行的詳細信æ¯ï¼Œ
+åƒè¦‹ï¼š Documentation/translations/zh_CN/process/development-process.rst 。
+Documentation/translations/zh_CN/process/submit-checklist.rst 給出了一系列
+æäº¤è£œä¸ä¹‹å‰è¦æª¢æŸ¥çš„事項。設備樹相關的補ä¸ï¼Œè«‹åƒé–±
+Documentation/devicetree/bindings/submitting-patches.rst 。
-其中許多步驟æè¿°äº†Git版本控制系統的默èªè¡Œçˆ²ï¼›å¦‚果您使用Git來準備補ä¸ï¼Œ
-您將發ç¾å®ƒçˆ²æ‚¨å®Œæˆçš„大部分機械工作,儘管您ä»ç„¶éœ€è¦æº–備和記錄一組åˆç†çš„
-補ä¸ã€‚一般來說,使用git將使您作爲內核開發人員的生活更輕鬆。
+本文檔å‡è¨­æ‚¨æ­£åœ¨ä½¿ç”¨ ``git`` 準備你的補ä¸ã€‚如果您ä¸ç†Ÿæ‚‰ ``git`` ,最好學習
+如何使用它,這將使您作爲內核開發人員的生活變得更加輕鬆。
+部分å­ç³»çµ±å’Œç¶­è­·äººå“¡çš„æ¨¹æœ‰ä¸€äº›é—œæ–¼å…¶å·¥ä½œæµç¨‹å’Œè¦æ±‚çš„é¡å¤–ä¿¡æ¯ï¼Œè«‹åƒé–±
+Documentation/process/maintainer-handbooks.rst 。
-0) ç²å–ç•¶å‰æºç¢¼æ¨¹
------------------
+ç²å–ç•¶å‰æºç¢¼æ¨¹
+--------------
-如果您沒有一個å¯ä»¥ä½¿ç”¨ç•¶å‰å…§æ ¸åŽŸå§‹ç¢¼çš„å­˜å„²åº«ï¼Œè«‹ä½¿ç”¨gitç²å–一個。您將è¦
-從主線存儲庫開始,它å¯ä»¥é€šéŽä»¥ä¸‹æ–¹å¼ç²å–::
+如果您手頭沒有當å‰å…§æ ¸æºä»£ç¢¼çš„存儲庫,請使用 ``git`` ç²å–一份。您需è¦å…ˆç²å–
+主線存儲庫,它å¯ä»¥é€šéŽä»¥ä¸‹å‘½ä»¤æ‹‰å–::
- git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
-但是,請注æ„,您å¯èƒ½ä¸å¸Œæœ›ç›´æŽ¥é‡å°ä¸»ç·šæ¨¹é€²è¡Œé–‹ç™¼ã€‚大多數å­ç³»çµ±ç¶­è­·äººå“¡é‹
+但是,請注æ„,您å¯èƒ½ä¸æƒ³ç›´æŽ¥é‡å°ä¸»ç·šæ¨¹é€²è¡Œé–‹ç™¼ã€‚大多數å­ç³»çµ±ç¶­è­·äººå“¡é‹
行自己的樹,並希望看到é‡å°é€™äº›æ¨¹æº–備的補ä¸ã€‚è«‹åƒè¦‹MAINTAINERS文件中å­ç³»
-統的 **T:** 項以查找該樹,或者簡單地詢å•ç¶­è­·è€…è©²æ¨¹æ˜¯å¦æœªåœ¨å…¶ä¸­åˆ—出。
-
-ä»ç„¶å¯ä»¥é€šéŽtarballs下載內核版本(如下一節所述),但這是進行內核開發的
-一種困難的方å¼ã€‚
-
-1) "diff -up"
--------------
-
-使用 "diff -up" 或者 "diff -uprN" 來創建補ä¸ã€‚
-
-所有內核的改動,都是以補ä¸çš„å½¢å¼å‘ˆç¾çš„,補ä¸ç”± diff(1) 生æˆã€‚創建補ä¸çš„
-時候,è¦ç¢ºèªå®ƒæ˜¯ä»¥ "unified diff" æ ¼å¼å‰µå»ºçš„,這種格å¼ç”± diff(1) çš„ '-u'
-åƒæ•¸ç”Ÿæˆã€‚而且,請使用 '-p' åƒæ•¸ï¼Œé‚£æ¨£æœƒé¡¯ç¤ºæ¯å€‹æ”¹å‹•所在的C函數,使得
-產生的補ä¸å®¹æ˜“è®€å¾—å¤šã€‚è£œä¸æ‡‰è©²åŸºæ–¼å…§æ ¸åŽŸå§‹ç¢¼æ¨¹çš„æ ¹ç›®éŒ„ï¼Œè€Œä¸æ˜¯è£¡é‚Šçš„ä»»
-何å­ç›®éŒ„。
-
-爲一個單ç¨çš„æ–‡ä»¶å‰µå»ºè£œä¸ï¼Œä¸€èˆ¬ä¾†èªªé€™æ¨£åšå°±å¤ äº†::
-
- SRCTREE=linux
- MYFILE=drivers/net/mydriver.c
-
- cd $SRCTREE
- cp $MYFILE $MYFILE.orig
- vi $MYFILE # make your change
- cd ..
- diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
-
-爲多個文件創建補ä¸ï¼Œä½ å¯ä»¥è§£é–‹ä¸€å€‹æ²’有修改éŽçš„內核原始碼樹,然後和你自
-å·±çš„ä»£ç¢¼æ¨¹ä¹‹é–“åš diff 。例如::
-
- MYSRC=/devel/linux
-
- tar xvfz linux-3.19.tar.gz
- mv linux-3.19 linux-3.19-vanilla
- diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \
- linux-3.19-vanilla $MYSRC > /tmp/patch
-
-"dontdiff" 是內核在編譯的時候產生的文件的列表,列表中的文件在 diff(1)
-產生的補ä¸é‡Œæœƒè¢«è·³éŽã€‚
-
-確定你的補ä¸é‡Œæ²’有包å«ä»»ä½•ä¸å±¬æ–¼é€™æ¬¡è£œä¸æäº¤çš„é¡å¤–文件。記得在用diff(1)
-生æˆè£œä¸ä¹‹å¾Œï¼Œå¯©é–±ä¸€æ¬¡è£œä¸ï¼Œä»¥ç¢ºä¿æº–確。
-
-如果你的改動很散亂,你應該研究一下如何將補ä¸åˆ†å‰²æˆç¨ç«‹çš„部分,將改動分
-割æˆä¸€ç³»åˆ—åˆä¹Žé‚輯的步驟。這樣更容易讓其他內核開發者審核,如果你想你的
-補ä¸è¢«æŽ¥å—,這是很é‡è¦çš„。請åƒé–±ï¼š
-:ref:`tw_split_changes`
-
-如果你用 ``git`` , ``git rebase -i`` å¯ä»¥å¹«åŠ©ä½ é€™ä¸€é»žã€‚å¦‚æžœä½ ä¸ç”¨ ``git``,
-``quilt`` <https://savannah.nongnu.org/projects/quilt> å¦å¤–一個æµè¡Œçš„鏿“‡ã€‚
+統的 **T:** 項以查找該樹,或者直接詢å•ç¶­è­·è€…è©²æ¨¹æ˜¯å¦æœªåœ¨å…¶ä¸­åˆ—出。
.. _tw_describe_changes:
-2) æè¿°ä½ çš„æ”¹å‹•
----------------
+æè¿°ä½ çš„æ”¹å‹•
+------------
æè¿°ä½ çš„å•é¡Œã€‚ç„¡è«–æ‚¨çš„è£œä¸æ˜¯ä¸€è¡ŒéŒ¯èª¤ä¿®å¾©é‚„是5000行新功能,都必須有一個潛在
-çš„å•題激勵您完æˆé€™é …工作。讓審稿人相信有一個å•題值得解決,讓他們讀完第一段
-是有æ„義的。
+çš„å•題激勵您完æˆé€™é …工作。說æœå¯©é–±è€…相信有一個å•題值得解決,讓他們讀完第一段
+後就能明白這一點。
æè¿°ç”¨æˆ¶å¯è¦‹çš„影響。直接崩潰和鎖定是相當有說æœåŠ›çš„ï¼Œä½†ä¸¦ä¸æ˜¯æ‰€æœ‰çš„錯誤都那麼
-明目張胆。å³ä½¿åœ¨ä»£ç¢¼å¯©æŸ¥æœŸé–“發ç¾äº†é€™å€‹å•é¡Œï¼Œä¹Ÿè¦æè¿°ä¸€ä¸‹æ‚¨èªçˆ²å®ƒå¯èƒ½å°ç”¨æˆ¶ç”¢
+明目張膽。å³ä½¿åœ¨ä»£ç¢¼å¯©é–±æœŸé–“發ç¾äº†é€™å€‹å•é¡Œï¼Œä¹Ÿè¦æè¿°ä¸€ä¸‹æ‚¨èªçˆ²å®ƒå¯èƒ½å°ç”¨æˆ¶ç”¢
生的影響。請記ä½ï¼Œå¤§å¤šæ•¸Linux安è£é‹è¡Œçš„內核來自二級穩定樹或特定於供應商/產å“
的樹,åªå¾žä¸Šæ¸¸ç²¾é¸ç‰¹å®šçš„補ä¸ï¼Œå› æ­¤è«‹åŒ…å«ä»»ä½•å¯ä»¥å¹«åŠ©æ‚¨å°‡æ›´æ”¹å®šä½åˆ°ä¸‹æ¸¸çš„內容:
-觸發的場景ã€DMESG的摘錄ã€å´©æ½°æè¿°ã€æ€§èƒ½å›žæ­¸ã€å»¶é²å°–峯ã€éŽ–å®šç­‰ã€‚
+觸發的場景ã€DMESG的摘錄ã€å´©æ½°æè¿°ã€æ€§èƒ½è¿´æ­¸ã€å»¶é²å°–峯ã€éŽ–å®šç­‰ã€‚
-é‡åŒ–優化和權衡。如果您è²ç¨±åœ¨æ€§èƒ½ã€å…§å­˜æ¶ˆè€—ã€å †æ£§å ç”¨ç©ºé–“或二進ä½å¤§å°æ–¹é¢æœ‰æ‰€
-改進,請包括支æŒå®ƒå€‘çš„æ•¸å­—ã€‚ä½†ä¹Ÿè¦æè¿°ä¸æ˜Žé¡¯çš„æˆæœ¬ã€‚å„ªåŒ–é€šå¸¸ä¸æ˜¯å…費的,而是
-在CPUã€å…§å­˜å’Œå¯è®€æ€§ä¹‹é–“進行權衡;或者,探索性的工作,在ä¸åŒçš„工作負載之間進
+質é‡å„ªåŒ–和權衡。如果您è²ç¨±åœ¨æ€§èƒ½ã€å…§å­˜æ¶ˆè€—ã€å †æ£§ä½”ç”¨ç©ºé–“æˆ–äºŒé€²åˆ¶å¤§å°æ–¹é¢æœ‰æ‰€
+改進,請包括支æŒå®ƒå€‘çš„æ•¸æ“šã€‚ä½†ä¹Ÿè¦æè¿°ä¸æ˜Žé¡¯çš„æˆæœ¬ã€‚å„ªåŒ–é€šå¸¸ä¸æ˜¯é›¶æˆæœ¬çš„,而是
+在CPUã€å…§å­˜å’Œå¯è®€æ€§ä¹‹é–“é€²è¡Œæ¬Šè¡¡ï¼›æˆ–è€…ï¼ŒåšæŽ¢ç´¢æ€§çš„å·¥ä½œï¼Œåœ¨ä¸åŒçš„工作負載之間進
行權衡。請æè¿°å„ªåŒ–çš„é æœŸç¼ºé»žï¼Œä»¥ä¾¿å¯©é–±è€…å¯ä»¥æ¬Šè¡¡æˆæœ¬å’Œæ”¶ç›Šã€‚
-一旦å•題建立起來,就è¦è©³ç´°åœ°æè¿°ä¸€ä¸‹æ‚¨å¯¦éš›åœ¨åšä»€éº¼ã€‚å°æ–¼å¯©é–±è€…來說,用簡單的
-英語æè¿°ä»£ç¢¼çš„變化是很é‡è¦çš„,以驗證代碼的行爲是å¦ç¬¦åˆæ‚¨çš„æ„é¡˜ã€‚
+æå‡ºå•題之後,就è¦è©³ç´°åœ°æè¿°ä¸€ä¸‹æ‚¨å¯¦éš›åœ¨åšçš„æŠ€è¡“ç´°ç¯€ã€‚å°æ–¼å¯©é–±è€…來說,用簡練的
+英語æè¿°ä»£ç¢¼çš„變化是很é‡è¦çš„,以驗證代碼的行爲是å¦ç¬¦åˆæ‚¨çš„æ„åœ–ã€‚
-å¦‚æžœæ‚¨å°‡è£œä¸æè¿°å¯«åœ¨ä¸€å€‹è¡¨å–®ä¸­ï¼Œé€™å€‹è¡¨å–®å¯ä»¥å¾ˆå®¹æ˜“地作爲「æäº¤æ—¥èªŒã€æ”¾å…¥Linux
-的原始碼管ç†ç³»çµ±git中,那麼維護人員將éžå¸¸æ„Ÿè¬æ‚¨ã€‚見 :ref:`tw_explicit_in_reply_to`.
+å¦‚æžœæ‚¨å°‡è£œä¸æè¿°å¯«æˆâ€œæ¨™æº–æ ¼å¼â€ï¼Œå¯ä»¥å¾ˆå®¹æ˜“地作爲“æäº¤æ—¥èªŒâ€æ”¾å…¥Linuxçš„æºä»£
+碼管ç†ç³»çµ± ``git`` 中,那麼維護人員將éžå¸¸æ„Ÿè¬æ‚¨ã€‚
+åƒè¦‹ :ref:`zh_the_canonical_patch_format` 。
æ¯å€‹è£œä¸åªè§£æ±ºä¸€å€‹å•題。如果你的æè¿°é–‹å§‹è®Šé•·ï¼Œé€™å°±è¡¨æ˜Žä½ å¯èƒ½éœ€è¦æ‹†åˆ†ä½ çš„補ä¸ã€‚
-請見 :ref:`tw_split_changes`
+請見 :ref:`zh_split_changes` 。
-æäº¤æˆ–釿–°æäº¤ä¿®è£œç¨‹åºæˆ–修補程åºç³»åˆ—時,請包括完整的修補程åºèªªæ˜Žå’Œç†ç”±ã€‚ä¸è¦
+æäº¤æˆ–釿–°æäº¤è£œä¸æˆ–補ä¸ç³»åˆ—時,請包括完整的補ä¸èªªæ˜Žå’Œç†ç”±ã€‚ä¸è¦
åªèªªé€™æ˜¯è£œä¸ï¼ˆç³»åˆ—)的第幾版。ä¸è¦æœŸæœ›å­ç³»çµ±ç¶­è­·äººå“¡å¼•用更早的補ä¸ç‰ˆæœ¬æˆ–引用
URLä¾†æŸ¥æ‰¾è£œä¸æè¿°ä¸¦å°‡å…¶æ”¾å…¥è£œä¸ä¸­ã€‚也就是說,補ä¸ï¼ˆç³»åˆ—)åŠå…¶æè¿°æ‡‰è©²æ˜¯ç¨ç«‹çš„。
-這å°ç¶­è­·äººå“¡å’Œå¯©æŸ¥äººå“¡éƒ½æœ‰å¥½è™•。一些評審者å¯èƒ½ç”šè‡³æ²’有收到補ä¸çš„æ—©æœŸç‰ˆæœ¬ã€‚
+這å°ç¶­è­·äººå“¡å’Œå¯©é–±è€…都有好處。一些審閱者å¯èƒ½ç”šè‡³æ²’有收到補ä¸çš„æ—©æœŸç‰ˆæœ¬ã€‚
-æè¿°ä½ åœ¨å‘½ä»¤èªžæ°£ä¸­çš„變化,例如「make xyzzy do frotzã€è€Œä¸æ˜¯ã€Œ[這個補ä¸]make
-xyzzy do frotzã€æˆ–「[我]changed xyzzy to do frotzã€ï¼Œå°±å¥½åƒä½ åœ¨å‘½ä»¤ä»£ç¢¼åº«æ”¹è®Š
+ç”¨ç¥ˆä½¿å¥æè¿°ä½ çš„è®Šæ›´ï¼Œä¾‹å¦‚â€œmake xyzzy do frotzâ€è€Œä¸æ˜¯â€œ[This patch]make
+xyzzy do frotzâ€æˆ–“[I]changed xyzzy to do frotzâ€ï¼Œå°±å¥½åƒä½ åœ¨å‘½ä»¤ä»£ç¢¼åº«æ”¹è®Š
它的行爲一樣。
-如果修補程åºä¿®å¾©äº†ä¸€å€‹è¨˜éŒ„çš„bugæ¢ç›®ï¼Œè«‹æŒ‰ç·¨è™Ÿå’ŒURL引用該bugæ¢ç›®ã€‚如果補ä¸ä¾†
-自郵件列表討論,請給出郵件列表存檔的URL;使用帶有 ``Message-ID`` 的
-https://lore.kernel.org/ é‡å®šå‘,以確ä¿é€£çµä¸æœƒéŽæ™‚。
-
-但是,在沒有外部資æºçš„æƒ…æ³ä¸‹ï¼Œå„˜é‡è®“你的解釋å¯ç†è§£ã€‚除了æä¾›éƒµä»¶åˆ—表存檔或
-bugçš„URL之外,還è¦ç¸½çµéœ€è¦æäº¤è£œä¸çš„相關討論è¦é»žã€‚
-
-如果您想è¦å¼•用一個特定的æäº¤ï¼Œä¸è¦åªå¼•用æäº¤çš„ SHA-1 ID。還請包括æäº¤çš„一行
-摘è¦ï¼Œä»¥ä¾¿æ–¼å¯©é–±è€…了解它是關於什麼的。例如::
+如果您想è¦å¼•用一個特定的æäº¤ï¼Œä¸è¦åªå¼•用æäº¤çš„SHA-1 ID。還請包括æäº¤çš„一行
+摘è¦ï¼Œä»¥ä¾¿æ–¼å¯©é–±è€…瞭解它是關於什麼的。例如::
Commit e21d2170f36602ae2708 ("video: remove unnecessary
platform_set_drvdata()") removed the unnecessary
platform_set_drvdata(), but left the variable "dev" unused,
delete it.
-您還應該確ä¿è‡³å°‘使用å‰12ä½ SHA-1 ID. 內核存儲庫包å«*許多*å°è±¡ï¼Œä½¿èˆ‡è¼ƒçŸ­çš„ID
+您還應該確ä¿è‡³å°‘使用å‰12ä½SHA-1 IDã€‚å…§æ ¸å­˜å„²åº«åŒ…å« *許多* å°è±¡ï¼Œä½¿è¼ƒçŸ­çš„ID
發生è¡çªçš„å¯èƒ½æ€§å¾ˆå¤§ã€‚記ä½ï¼Œå³ä½¿ç¾åœ¨ä¸æœƒèˆ‡æ‚¨çš„六個字符ID發生è¡çªï¼Œé€™ç¨®æƒ…æ³
-å¯èƒ½äº”年後改變。
+也å¯èƒ½åœ¨äº”年後改變。
+
+如果該變更的相關討論或背景信æ¯å¯ä»¥åœ¨ç¶²ä¸ŠæŸ¥é–±ï¼Œè«‹åŠ ä¸Šâ€œLink:â€æ¨™ç±¤æŒ‡å‘它。例如
+你的補ä¸ä¿®å¾©äº†ä¸€å€‹ç¼ºé™·ï¼Œéœ€è¦æ·»åŠ ä¸€å€‹å¸¶æœ‰URL的標籤指å‘郵件列表存檔或缺陷跟蹤器
+çš„ç›¸é—œå ±å‘Šï¼›å¦‚æžœè©²è£œä¸æ˜¯ç”±ä¸€äº›æ—©å…ˆéƒµä»¶åˆ—表討論或網絡上的記錄引起的,請指å‘它。
+
+ç•¶éˆæŽ¥åˆ°éƒµä»¶åˆ—è¡¨å­˜æª”æ™‚ï¼Œè«‹é¦–é¸lore.kernel.org郵件存檔æœå‹™ã€‚用郵件中的
+``Message-ID`` 頭(去掉尖括號)å¯ä»¥å‰µå»ºéˆæŽ¥URL。例如::
+
+ Link: https://lore.kernel.org/r/30th.anniversary.repost@klaava.Helsinki.FI/
+
+è«‹æª¢æŸ¥è©²éˆæŽ¥ä»¥ç¢ºä¿å¯ç”¨ä¸”æŒ‡å‘æ­£ç¢ºçš„郵件。
+
+ä¸éŽï¼Œåœ¨æ²’有外部資æºçš„æƒ…æ³ä¸‹ï¼Œä¹Ÿè¦å„˜é‡è®“你的解釋å¯ç†è§£ã€‚除了æä¾›éƒµä»¶åˆ—表存檔或
+缺陷的URL之外,還è¦éœ€è¦ç¸½çµè©²è£œä¸çš„相關討論è¦é»žã€‚
-如果修補程åºä¿®å¾©äº†ç‰¹å®šæäº¤ä¸­çš„錯誤,例如,使用 ``git bisct`` ,請使用帶有å‰
-12個字符SHA-1 ID çš„"Fixes:"標記和單行摘è¦ã€‚爲了簡化ä¸è¦å°‡æ¨™è¨˜æ‹†åˆ†çˆ²å¤šå€‹ï¼Œ
-è¡Œã€æ¨™è¨˜ä¸å—分æžè…³æœ¬ã€Œ75列æ›è¡Œã€è¦å‰‡çš„é™åˆ¶ã€‚例如::
+如果補ä¸ä¿®å¾©äº†ç‰¹å®šæäº¤ä¸­çš„錯誤,例如使用 ``git bisct`` 發ç¾äº†ä¸€å€‹å•題,請使用
+帶有å‰12個字符SHA-1 ID的“Fixes:â€æ¨™ç±¤å’Œå–®è¡Œæ‘˜è¦ã€‚爲了簡化解æžè…³æœ¬ï¼Œä¸è¦å°‡è©²
+標籤拆分爲多行,標籤ä¸å—“75列æ›è¡Œâ€è¦å‰‡çš„é™åˆ¶ã€‚例如::
- Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
+ Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
-下列 ``git config`` 設置å¯ä»¥æ·»åŠ è®“ ``git log``, ``git show`` 漂亮的顯示格å¼::
+下列 ``git config`` 設置å¯ä»¥è®“ ``git log``, ``git show`` 增加上述風格的顯示格å¼::
[core]
abbrev = 12
[pretty]
fixes = Fixes: %h (\"%s\")
+使用示例::
+
+ $ git log -1 --pretty=fixes 54a4f0239f2e
+ Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
+
.. _tw_split_changes:
-3) 拆分你的改動
----------------
+拆分你的改動
+------------
-å°‡æ¯å€‹é‚輯更改分隔æˆä¸€å€‹å–®ç¨çš„補ä¸ã€‚
+å°‡æ¯å€‹ **é‚輯更改** 拆分æˆä¸€å€‹å–®ç¨çš„補ä¸ã€‚
-ä¾‹å¦‚ï¼Œå¦‚æžœä½ çš„æ”¹å‹•é‡ŒåŒæ™‚有bug修正和性能優化,那麼把這些改動拆分到兩個或
-è€…æ›´å¤šçš„è£œä¸æ–‡ä»¶ä¸­ã€‚如果你的改動包å«å°API的修改,並且修改了驅動程åºä¾†é©
-應這些新的API,那麼把這些修改分æˆå…©å€‹è£œä¸ã€‚
+例如,如果你的改動è£åŒæ™‚有bug修正和性能優化,那麼把這些改動拆分到兩個或
+è€…æ›´å¤šçš„è£œä¸æ–‡ä»¶ä¸­ã€‚如果你的改動包å«å°API的修改,並且增加了一個使用該新API
+的驅動,那麼把這些修改分æˆå…©å€‹è£œä¸ã€‚
å¦ä¸€æ–¹é¢ï¼Œå¦‚果你將一個單ç¨çš„æ”¹å‹•åšæˆå¤šå€‹è£œä¸æ–‡ä»¶ï¼Œé‚£éº¼å°‡å®ƒå€‘åˆä½µæˆä¸€å€‹
-å–®ç¨çš„è£œä¸æ–‡ä»¶ã€‚這樣一個é‚輯上單ç¨çš„æ”¹å‹•åªè¢«åŒ…å«åœ¨ä¸€å€‹è£œä¸æ–‡ä»¶é‡Œã€‚
+å–®ç¨çš„è£œä¸æ–‡ä»¶ã€‚這樣一個é‚輯上單ç¨çš„æ”¹å‹•åªè¢«åŒ…å«åœ¨ä¸€å€‹è£œä¸æ–‡ä»¶è£ã€‚
-如果有一個補ä¸ä¾è³´å¦å¤–一個補ä¸ä¾†å®Œæˆå®ƒçš„æ”¹å‹•,那沒å•題。簡單的在你的補
-ä¸æè¿°é‡ŒæŒ‡å‡ºã€Œé€™å€‹è£œä¸ä¾è³´æŸè£œä¸ã€å°±å¥½äº†ã€‚
+需è¦è¨˜ä½çš„一點是,æ¯å€‹è£œä¸çš„æ›´æ”¹éƒ½æ‡‰æ˜“æ–¼ç†è§£ï¼Œä»¥ä¾¿å¯©é–±è€…驗證。æ¯å€‹è£œä¸éƒ½æ‡‰è©²
+å°å…¶åƒ¹å€¼é€²è¡Œé—¡è¿°ã€‚
-åœ¨å°‡æ‚¨çš„æ›´æ”¹åŠƒåˆ†çˆ²ä¸€ç³»åˆ—è£œä¸æ™‚,è¦ç‰¹åˆ¥æ³¨æ„確ä¿å…§æ ¸åœ¨ç³»åˆ—中的æ¯å€‹è£œä¸ä¹‹å¾Œ
-都能正常構建和é‹è¡Œã€‚使用 ``git bisect`` 來追蹤å•題的開發者å¯èƒ½æœƒåœ¨ä»»ä½•時
-候分割你的補ä¸ç³»åˆ—ï¼›å¦‚æžœä½ åœ¨ä¸­é–“å¼•å…¥éŒ¯èª¤ï¼Œä»–å€‘ä¸æœƒæ„Ÿè¬ä½ ã€‚
+如果有一個補ä¸ä¾è³´å¦å¤–一個補ä¸ä¾†å®Œæˆå®ƒçš„æ”¹å‹•,那沒å•題。直接在你的補
+ä¸æè¿°è£æŒ‡å‡º **“這個補ä¸ä¾è³´æŸè£œä¸â€** 就好了。
-如果你ä¸èƒ½å°‡è£œä¸æ¿ƒç¸®æˆæ›´å°‘çš„æ–‡ä»¶ï¼Œé‚£éº¼æ¯æ¬¡å¤§ç´„發é€å‡º15個,然後等待審查
+åœ¨å°‡æ‚¨çš„æ›´æ”¹åŠƒåˆ†çˆ²ä¸€ç³»åˆ—è£œä¸æ™‚,è¦ç‰¹åˆ¥æ³¨æ„確ä¿å…§æ ¸åœ¨æ‡‰ç”¨ç³»åˆ—中的æ¯å€‹è£œä¸ä¹‹å¾Œ
+都能正常構建和é‹è¡Œã€‚使用 ``git bisect`` 來追蹤å•題的開發者å¯èƒ½æœƒåœ¨ä»»ä½•地方分
+割你的補ä¸ç³»åˆ—ï¼›å¦‚æžœä½ åœ¨ä¸­é–“å¼•å…¥éŒ¯èª¤ï¼Œä»–å€‘ä¸æœƒæ„Ÿè¬ä½ ã€‚
+
+如果你ä¸èƒ½å°‡è£œä¸ç³»åˆ—濃縮得更å°ï¼Œé‚£éº¼æ¯æ¬¡å¤§ç´„發é€å‡º15個補ä¸ï¼Œç„¶å¾Œç­‰å¾…審閱
和集æˆã€‚
-4) 檢查你的更改風格
--------------------
+檢查你的更改風格
+----------------
-æª¢æŸ¥æ‚¨çš„è£œä¸æ˜¯å¦å­˜åœ¨åŸºæœ¬æ¨£å¼è¡çªï¼Œè©³ç´°ä¿¡æ¯å¯åœ¨
-:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
-中找到。如果ä¸é€™æ¨£åšï¼Œåªæœƒæµªè²»å¯©ç¨¿äººçš„æ™‚間,並且會導致你的補ä¸è¢«æ‹’絕,甚至
+æª¢æŸ¥æ‚¨çš„è£œä¸æ˜¯å¦é•å了基本樣å¼è¦å®šï¼Œè©³ç´°ä¿¡æ¯åƒè¦‹
+Documentation/translations/zh_CN/process/coding-style.rst
+中找到。如果ä¸é€™æ¨£åšï¼Œåªæœƒæµªè²»å¯©é–±è€…的時間,並且會導致你的補ä¸è¢«æ‹’絕,甚至
å¯èƒ½æ²’有被閱讀。
一個é‡è¦çš„例外是在將代碼從一個文件移動到å¦ä¸€å€‹æ–‡ä»¶æ™‚——在這種情æ³ä¸‹ï¼Œæ‚¨ä¸æ‡‰
該在移動代碼的åŒä¸€å€‹è£œä¸ä¸­ä¿®æ”¹ç§»å‹•的代碼。這清楚地æè¿°äº†ç§»å‹•代碼和您的更改
-的行爲。這大大有助於審查實際差異,並å…許工具更好地跟蹤代碼本身的歷å²ã€‚
+的行爲。這大大有助於審閱實際差異,並å…許工具更好地跟蹤代碼本身的歷å²ã€‚
在æäº¤ä¹‹å‰ï¼Œä½¿ç”¨è£œä¸æ¨£å¼æª¢æŸ¥ç¨‹åºæª¢æŸ¥è£œä¸ï¼ˆscripts/check patch.pl)。ä¸éŽï¼Œ
請注æ„ï¼Œæ¨£å¼æª¢æŸ¥ç¨‹åºæ‡‰è©²è¢«è¦–爲一個指å—ï¼Œè€Œä¸æ˜¯ä½œçˆ²äººé¡žåˆ¤æ–·çš„æ›¿ä»£å“。如果您
-的代碼看起來更好,但有é•è¦è¡Œçˆ²ï¼Œé‚£éº¼æœ€å¥½ä¸è¦ä½¿ç”¨å®ƒã€‚
+的代碼看起來更好,但有é•è¦è¡Œçˆ²ï¼Œé‚£éº¼æœ€å¥½åˆ¥ç®¡å®ƒã€‚
檢查者報告三個級別:
- ERROR:很å¯èƒ½å‡ºéŒ¯çš„事情
- - WARNING:需è¦ä»”細審查的事項
+ - WARNING:需è¦ä»”細審閱的事項
- CHECKï¼šéœ€è¦æ€è€ƒçš„事情
您應該能夠判斷您的補ä¸ä¸­å­˜åœ¨çš„æ‰€æœ‰é•è¦è¡Œçˆ²ã€‚
-5) 鏿“‡è£œä¸æ”¶ä»¶äºº
------------------
+鏿“‡è£œä¸æ”¶ä»¶äºº
+--------------
-您應該總是在任何補ä¸ä¸Šè¤‡è£½ç›¸æ‡‰çš„å­ç³»çµ±ç¶­è­·äººå“¡ï¼Œä»¥ç²å¾—他們維護的代碼;查看
-維護人員文件和原始碼修訂歷å²è¨˜éŒ„,以了解這些維護人員是誰。腳本
-scripts/get_Maintainer.pl在這個步驟中éžå¸¸æœ‰ç”¨ã€‚如果您找ä¸åˆ°æ­£åœ¨å·¥ä½œçš„å­ç³»çµ±
+您應該總是知會任何補ä¸ç›¸æ‡‰ä»£ç¢¼çš„å­ç³»çµ±ç¶­è­·äººå“¡ï¼›æŸ¥çœ‹
+維護人員文件和æºä»£ç¢¼ä¿®è¨‚æ­·å²è¨˜éŒ„,以瞭解這些維護人員是誰。腳本
+scripts/get_maintainer.pl在這個步驟中éžå¸¸æœ‰ç”¨ã€‚如果您找ä¸åˆ°æ­£åœ¨å·¥ä½œçš„å­ç³»çµ±
的維護人員,那麼Andrew Morton(akpm@linux-foundation.org)將充當最後的維護
人員。
-æ‚¨é€šå¸¸é‚„æ‡‰è©²é¸æ“‡è‡³å°‘一個郵件列表來接收補ä¸é›†çš„。linux-kernel@vger.kernel.org
-作爲最後一個解決辦法的列表,但是這個列表上的體ç©å·²ç¶“引起了許多開發人員的拒絕。
-在MAINTAINERS文件中查找å­ç³»çµ±ç‰¹å®šçš„列表;您的補ä¸å¯èƒ½æœƒåœ¨é‚£è£¡å¾—到更多的關注。
+æ‚¨é€šå¸¸é‚„æ‡‰è©²é¸æ“‡è‡³å°‘一個郵件列表來接收補ä¸é›†çš„副本。linux-kernel@vger.kernel.org
+是所有補ä¸çš„默èªåˆ—表,但是這個列表的æµé‡å·²ç¶“導致了許多開發人員ä¸å†çœ‹å®ƒã€‚
+在MAINTAINERS文件中查找å­ç³»çµ±ç‰¹å®šçš„列表;您的補ä¸å¯èƒ½æœƒåœ¨é‚£è£å¾—到更多的關注。
ä¸éŽï¼Œè«‹ä¸è¦ç™¼é€åžƒåœ¾éƒµä»¶åˆ°ç„¡é—œçš„列表。
許多與內核相關的列表託管在vger.kernel.org上;您å¯ä»¥åœ¨
@@ -232,188 +202,170 @@ http://vger.kernel.org/vger-lists.html 上找到它們的列表。ä¸éŽï¼Œä¹Ÿæœ
ä¸è¦ä¸€æ¬¡ç™¼é€è¶…éŽ15個補ä¸åˆ°vger郵件列表ï¼ï¼ï¼ï¼
-Linus Torvalds 是決定改動能å¦é€²å…¥ Linux å…§æ ¸çš„æœ€çµ‚è£æ±ºè€…。他的 e-mail
-åœ°å€æ˜¯ <torvalds@linux-foundation.org> 。他收到的 e-mail 很多,所以一般
-的說,最好別給他發 e-mail。
+Linus Torvalds是決定改動能å¦é€²å…¥ Linux å…§æ ¸çš„æœ€çµ‚è£æ±ºè€…ã€‚ä»–çš„éƒµä»¶åœ°å€æ˜¯
+torvalds@linux-foundation.org 。他收到的郵件很多,所以一般來說最好 **別**
+給他發郵件。
-如果您有修復å¯åˆ©ç”¨å®‰å…¨æ¼æ´žçš„補ä¸ï¼Œè«‹å°‡è©²è£œä¸ç™¼é€åˆ° security@kernel.orgã€‚å°æ–¼
-åš´é‡çš„bug,å¯ä»¥è€ƒæ…®çŸ­æœŸæš«åœä»¥å…許分銷商å‘用戶發布補ä¸ï¼›åœ¨é€™ç¨®æƒ…æ³ä¸‹ï¼Œé¡¯ç„¶ä¸æ‡‰
-將補ä¸ç™¼é€åˆ°ä»»ä½•公共列表。
+如果您有修復å¯åˆ©ç”¨å®‰å…¨æ¼æ´žçš„補ä¸ï¼Œè«‹å°‡è©²è£œä¸ç™¼é€åˆ° security@kernel.org ã€‚å°æ–¼
+åš´é‡çš„bug,å¯ä»¥è€ƒæ…®çŸ­æœŸç¦ä»¤ä»¥å…許分銷商(有時間)å‘用戶發佈補ä¸ï¼›åœ¨é€™ç¨®æƒ…æ³ä¸‹ï¼Œ
+é¡¯ç„¶ä¸æ‡‰å°‡è£œä¸ç™¼é€åˆ°ä»»ä½•公共列表。
+åƒè¦‹ Documentation/translations/zh_CN/admin-guide/security-bugs.rst 。
-修復已發布內核中嚴é‡éŒ¯èª¤çš„補ä¸ç¨‹åºæ‡‰è©²æŒ‡å‘穩定版維護人員,方法是放這樣的一行::
+修復已發佈內核中嚴é‡éŒ¯èª¤çš„補ä¸ç¨‹åºæ‡‰è©²æŠ„é€çµ¦ç©©å®šç‰ˆç¶­è­·äººå“¡ï¼Œæ–¹æ³•是把以下列行
+放進補ä¸çš„籤準å€ï¼ˆæ³¨æ„ï¼Œä¸æ˜¯é›»å­éƒµä»¶æ”¶ä»¶äººï¼‰::
- Cc: stable@vger.kernel.org
+ Cc: stable@vger.kernel.org
-進入補ä¸çš„簽准å€ï¼ˆæ³¨æ„ï¼Œä¸æ˜¯é›»å­éƒµä»¶æ”¶ä»¶äººï¼‰ã€‚除了這個文件之外,您還應該閱讀
-:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+除了本文件之外,您還應該閱讀
+Documentation/translations/zh_CN/process/stable-kernel-rules.rst 。
-但是,請注æ„,一些å­ç³»çµ±ç¶­è­·äººå“¡å¸Œæœ›å¾—出他們自己的çµè«–,å³å“ªäº›è£œä¸æ‡‰è©²è¢«æ”¾åˆ°
-穩定的樹上。尤其是網絡維護人員,ä¸å¸Œæœ›çœ‹åˆ°å–®å€‹é–‹ç™¼äººå“¡åœ¨è£œä¸ä¸­æ·»åŠ åƒä¸Šé¢é€™æ¨£
-的行。
-
-如果更改影響到用戶和內核接å£ï¼Œè«‹å‘手冊é ç¶­è­·äººå“¡ï¼ˆå¦‚維護人員文件中所列)發é€
+如果更改影響到用戶å´å…§æ ¸æŽ¥å£ï¼Œè«‹å‘手冊é ç¶­è­·äººå“¡ï¼ˆå¦‚維護人員文件中所列)發é€
手冊é è£œä¸ï¼Œæˆ–è‡³å°‘ç™¼é€æ›´æ”¹é€šçŸ¥ï¼Œä»¥ä¾¿ä¸€äº›ä¿¡æ¯é€²å…¥æ‰‹å†Šé ã€‚還應將用戶空間API
-更改複製到 linux-api@vger.kernel.org。
+更改抄é€åˆ° linux-api@vger.kernel.org 。
+
-6) 沒有 MIME 編碼,沒有連çµï¼Œæ²’æœ‰å£“ç¸®ï¼Œæ²’æœ‰é™„ä»¶ï¼Œåªæœ‰ç´”文本
------------------------------------------------------------
+ä¸è¦MIME編碼,ä¸è¦éˆæŽ¥ï¼Œä¸è¦å£“縮,ä¸è¦é™„件,åªè¦ç´”文本
+------------------------------------------------------
Linus 和其他的內核開發者需è¦é–±è®€å’Œè©•è«–ä½ æäº¤çš„æ”¹å‹•ã€‚å°æ–¼å…§æ ¸é–‹ç™¼è€…來說
-,å¯ä»¥ã€Œå¼•用ã€ä½ çš„æ”¹å‹•很é‡è¦ï¼Œä½¿ç”¨ä¸€èˆ¬çš„ e-mail 工具,他們就å¯ä»¥åœ¨ä½ çš„
+,å¯ä»¥â€œå¼•用â€ä½ çš„æ”¹å‹•很é‡è¦ï¼Œä½¿ç”¨ä¸€èˆ¬çš„郵件工具,他們就å¯ä»¥åœ¨ä½ çš„
代碼的任何ä½ç½®æ·»åŠ è©•è«–ã€‚
-因爲這個原因,所有的æäº¤çš„補ä¸éƒ½æ˜¯ e-mail 中「內嵌ã€çš„。
+因爲這個原因,所有的æäº¤çš„補ä¸éƒ½æ˜¯éƒµä»¶ä¸­â€œå…§åµŒâ€çš„。最簡單(和推薦)的方法就
+是使用 ``git send-email`` 。https://git-send-email.io 有 ``git send-email``
+çš„äº¤äº’å¼æ•™ç¨‹ã€‚
+
+å¦‚æžœä½ é¸æ“‡ä¸ç”¨ ``git send-email`` :
.. warning::
- 如果你使用剪切-粘貼你的補ä¸ï¼Œå°å¿ƒä½ çš„編輯器的自動æ›è¡ŒåŠŸèƒ½ç ´å£žä½ çš„è£œä¸
-ä¸è¦å°‡è£œä¸ä½œçˆ² MIME 編碼的附件,ä¸ç®¡æ˜¯å¦å£“縮。很多æµè¡Œçš„ e-mail 軟體ä¸
-是任何時候都將 MIME 編碼的附件當作純文本發é€çš„,這會使得別人無法在你的
-代碼中加評論。å¦å¤–,MIME 編碼的附件會讓 Linus 多花一點時間來處ç†ï¼Œé€™å°±
-é™ä½Žäº†ä½ çš„æ”¹å‹•被接å—çš„å¯èƒ½æ€§ã€‚
+ 如果你使用剪切-粘貼你的補ä¸ï¼Œå°å¿ƒä½ çš„編輯器的自動æ›è¡ŒåŠŸèƒ½ç ´å£žä½ çš„è£œä¸
-例外:如果你的郵éžå“¡å¼„壞了補ä¸ï¼Œé‚£éº¼æœ‰äººå¯èƒ½æœƒè¦æ±‚你使用mime釿–°ç™¼é€è£œä¸
+ä¸è¦å°‡è£œä¸ä½œçˆ²MIME編碼的附件,ä¸ç®¡æ˜¯å¦å£“縮。很多æµè¡Œçš„郵件軟件ä¸
+是任何時候都將MIME編碼的附件當作純文本發é€çš„,這會使得別人無法在你的
+代碼中加評論。å¦å¤–,MIME編碼的附件會讓Linus多花一點時間來處ç†ï¼Œé€™å°±
+é™ä½Žäº†ä½ çš„æ”¹å‹•被接å—çš„å¯èƒ½æ€§ã€‚
-è«‹åƒé–± :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
-以ç²å–有關é…置電å­éƒµä»¶å®¢æˆ¶ç«¯ä»¥ä½¿å…¶ä¸å—影響地發é€ä¿®è£œç¨‹åºçš„æç¤ºã€‚
+例外:如果你的郵路æå£žäº†è£œä¸ï¼Œé‚£éº¼æœ‰äººå¯èƒ½æœƒè¦æ±‚你使用MIME釿–°ç™¼é€è£œä¸ã€‚
-7) e-mail 的大å°
-----------------
+è«‹åƒé–± Documentation/translations/zh_CN/process/email-clients.rst
+以ç²å–有關é…置電å­éƒµä»¶å®¢æˆ¶ç«¯ä»¥ä½¿å…¶ä¸å—影響地發é€è£œä¸çš„æç¤ºã€‚
-大的改動å°éƒµä»¶åˆ—表ä¸åˆé©ï¼Œå°æŸäº›ç¶­è­·è€…也ä¸åˆé©ã€‚如果你的補ä¸ï¼Œåœ¨ä¸å£“縮
-的情æ³ä¸‹ï¼Œè¶…éŽäº†300kBï¼Œé‚£éº¼ä½ æœ€å¥½å°‡è£œä¸æ”¾åœ¨ä¸€å€‹èƒ½é€šéŽ internet 訪å•çš„æœ
-務器上,然後用指å‘你的補ä¸çš„ URL 替代。但是請注æ„,如果您的補ä¸è¶…éŽäº†
-300kb,那麼它幾乎肯定需è¦è¢«ç ´å£žã€‚
+回覆審閱æ„見
+------------
-8)回複評審æ„見
----------------
+你的補ä¸å¹¾ä¹Žè‚¯å®šæœƒå¾—到審閱者å°è£œä¸æ”¹é€²æ–¹æ³•的評論(以回覆郵件的形å¼ï¼‰ã€‚您必須
+å°é€™äº›è©•論作出回應;讓補ä¸è¢«å¿½ç•¥çš„一個好辦法就是忽略審閱者的æ„見。直接回復郵
+件來回應æ„見å³å¯ã€‚䏿œƒå°Žè‡´ä»£ç¢¼æ›´æ”¹çš„æ„è¦‹æˆ–å•題幾乎肯定會帶來註釋或變更日誌的
+改變,以便下一個審閱者更好地瞭解正在發生的事情。
-你的補ä¸å¹¾ä¹Žè‚¯å®šæœƒå¾—到評審者å°è£œä¸æ”¹é€²æ–¹æ³•的評論。您必須å°é€™äº›è©•論作出
-回應;讓補ä¸è¢«å¿½ç•¥çš„一個好辦法就是忽略審閱者的æ„è¦‹ã€‚ä¸æœƒå°Žè‡´ä»£ç¢¼æ›´æ”¹çš„
-æ„見或å•題幾乎肯定會帶來注釋或變更日誌的改變,以便下一個評審者更好地了解
-正在發生的事情。
+一定è¦å‘Šè¨´å¯©é–±è€…你在åšä»€éº¼æ”¹è®Šï¼Œä¸¦æ„Ÿè¬ä»–們的時間。代碼審閱是一個累人且耗時的
+éŽç¨‹ï¼Œå¯©é–±è€…有時會變得暴èºã€‚å³ä½¿åœ¨é€™ç¨®æƒ…æ³ä¸‹ï¼Œä¹Ÿè¦ç¦®è²Œåœ°å›žæ‡‰ä¸¦è§£æ±ºä»–們指出的
+å•題。當發é€ä¸‹ä¸€ç‰ˆæ™‚,在å°é¢éƒµä»¶æˆ–ç¨ç«‹è£œä¸é‡ŒåŠ ä¸Š ``patch changelog`` 說明與
+å‰ä¸€ç‰ˆæœ¬çš„ä¸åŒä¹‹è™•(åƒè¦‹ :ref:`zh_the_canonical_patch_format` )。
-一定è¦å‘Šè¨´å¯©ç¨¿äººä½ åœ¨åšä»€éº¼æ”¹è®Šï¼Œä¸¦æ„Ÿè¬ä»–們的時間。代碼審查是一個累人且
-耗時的éŽç¨‹ï¼Œå¯©æŸ¥äººå“¡æœ‰æ™‚會變得暴èºã€‚å³ä½¿åœ¨é€™ç¨®æƒ…æ³ä¸‹ï¼Œä¹Ÿè¦ç¦®è²Œåœ°å›žæ‡‰ä¸¦
-解決他們指出的å•題。
+.. _tw_resend_reminders:
-9)ä¸è¦æ´©æ°£æˆ–ä¸è€ç…©
--------------------
+ä¸è¦æ³„氣或ä¸è€ç…©
+----------------
-æäº¤æ›´æ”¹å¾Œï¼Œè«‹è€å¿ƒç­‰å¾…。審閱者是忙碌的人,å¯èƒ½ç„¡æ³•ç«‹å³è¨ªå•您的修補程åºã€‚
+æäº¤æ›´æ”¹å¾Œï¼Œè«‹è€å¿ƒç­‰å¾…。審閱者是大忙人,å¯èƒ½ç„¡æ³•ç«‹å³å¯©é–±æ‚¨çš„補ä¸ã€‚
-æ›¾å¹¾ä½•æ™‚ï¼Œè£œä¸æ›¾åœ¨æ²’有評論的情æ³ä¸‹æ¶ˆå¤±åœ¨ç©ºç™½ä¸­ï¼Œä½†é–‹ç™¼éŽç¨‹æ¯”ç¾åœ¨æ›´åŠ é †åˆ©ã€‚
-您應該在一周左å³çš„æ™‚é–“å…§æ”¶åˆ°è©•è«–ï¼›å¦‚æžœæ²’æœ‰æ”¶åˆ°è©•è«–ï¼Œè«‹ç¢ºä¿æ‚¨å·²å°‡è£œä¸ç™¼é€
-到正確的ä½ç½®ã€‚åœ¨é‡æ–°æäº¤æˆ–è¯ç¹«å¯©é–±è€…之å‰è‡³å°‘等待一周-在諸如åˆä½µçª—å£ä¹‹é¡žçš„
+æ›¾å¹¾ä½•æ™‚ï¼Œè£œä¸æ›¾åœ¨æ²’收到評論的情æ³ä¸‹æ¶ˆå¤±åœ¨è™›ç©ºä¸­ï¼Œä½†ç¾åœ¨é–‹ç™¼éŽç¨‹æ‡‰è©²æ›´åŠ é †åˆ©äº†ã€‚
+您應該在一週左å³çš„æ™‚é–“å…§æ”¶åˆ°è©•è«–ï¼›å¦‚æžœæ²’æœ‰æ”¶åˆ°è©•è«–ï¼Œè«‹ç¢ºä¿æ‚¨å·²å°‡è£œä¸ç™¼é€
+到正確的ä½ç½®ã€‚åœ¨é‡æ–°æäº¤æˆ–è¯ç¹«å¯©é–±è€…之å‰è‡³å°‘等待一週——在諸如åˆä½µçª—å£ä¹‹é¡žçš„
ç¹å¿™æ™‚é–“å¯èƒ½æ›´é•·ã€‚
-10ï¼‰ä¸»é¡Œä¸­åŒ…å« PATCH
---------------------
-
-由於到linuså’Œlinux內核的電å­éƒµä»¶æµé‡å¾ˆé«˜ï¼Œé€šå¸¸æœƒåœ¨ä¸»é¡Œè¡Œå‰é¢åŠ ä¸Š[PATCH]
-å‰ç¶´. 這使Linus和其他內核開發人員更容易將補ä¸èˆ‡å…¶ä»–é›»å­éƒµä»¶è¨Žè«–å€åˆ†é–‹ã€‚
+在等了幾個星期後,用帶RESEND的主題é‡ç™¼è£œä¸ä¹Ÿæ˜¯å¯ä»¥çš„::
-11)簽署你的作å“-開發者原始èªè­‰
--------------------------------
+ [PATCH Vx RESEND] sub/sys: Condensed patch summary
-爲了加強å°èª°åšäº†ä½•事的追蹤,尤其是å°é‚£äº›é€éŽå¥½å¹¾å±¤çš„維護者的補ä¸ï¼Œæˆ‘們
-建議在發é€å‡ºåŽ»çš„è£œä¸ä¸ŠåР䏀個 「sign-off〠的éŽç¨‹ã€‚
+當你發佈補ä¸ï¼ˆç³»åˆ—)修改版的時候,ä¸è¦åŠ ä¸Šâ€œRESENDâ€â€”—“RESENDâ€åªé©ç”¨æ–¼é‡
+æ–°æäº¤ä¹‹å‰æœªç¶“修改的補ä¸ï¼ˆç³»åˆ—)。
-"sign-off" 是在補ä¸çš„æ³¨é‡‹çš„æœ€å¾Œçš„簡單的一行文字,èªè­‰ä½ ç·¨å¯«äº†å®ƒæˆ–者其他
-人有權力將它作爲開放原始碼的補ä¸å‚³éžã€‚è¦å‰‡å¾ˆç°¡å–®ï¼šå¦‚果你能èªè­‰å¦‚下信æ¯:
-
-開發者來æºè­‰æ›¸ 1.1
-^^^^^^^^^^^^^^^^^^
-
-å°æ–¼æœ¬é …目的貢ç»ï¼Œæˆ‘èªè­‰å¦‚下信æ¯ï¼š
+ä¸»é¡Œä¸­åŒ…å« PATCH
+----------------
- (aï¼‰é€™äº›è²¢ç»æ˜¯å®Œå…¨æˆ–者部分的由我創建,我有權利以文件中指出
- 的開放原始碼許å¯è­‰æäº¤å®ƒï¼›æˆ–者
- (b)這些貢ç»åŸºæ–¼ä»¥å‰çš„工作,據我所知,這些以å‰çš„å·¥ä½œå—æ°ç•¶çš„開放
- 原始碼許å¯è­‰ä¿è­·ï¼Œè€Œä¸”,根據許å¯è­‰ï¼Œæˆ‘有權æäº¤ä¿®æ”¹å¾Œçš„è²¢ç»ï¼Œ
- 無論是完全還是部分由我創造,這些貢ç»éƒ½ä½¿ç”¨åŒä¸€å€‹é–‹æ”¾åŽŸå§‹ç¢¼è¨±å¯è­‰
- ï¼ˆé™¤éžæˆ‘被å…許用其它的許å¯è­‰ï¼‰ï¼Œæ­£å¦‚文件中指出的;或者
- (c)這些貢ç»ç”±èªè­‰ï¼ˆa),(b)或者(c)的人直接æä¾›çµ¦æˆ‘,而
- 且我沒有修改它。
- (d)我ç†è§£ä¸¦åŒæ„é€™å€‹é …ç›®å’Œè²¢ç»æ˜¯å…¬é–‹çš„,貢ç»çš„記錄(包括我
- 一起æäº¤çš„個人記錄,包括 sign-off )被永久維護並且å¯ä»¥å’Œé€™å€‹é …ç›®
- 或者開放原始碼的許å¯è­‰åŒæ­¥åœ°å†ç™¼è¡Œã€‚
+由於到Linuså’Œlinux-kernel的電å­éƒµä»¶æµé‡å¾ˆé«˜ï¼Œé€šå¸¸æœƒåœ¨ä¸»é¡Œè¡Œå‰é¢åŠ ä¸Š[PATCH]
+å‰ç¶´ã€‚這使Linus和其他內核開發人員更容易將補ä¸èˆ‡å…¶ä»–é›»å­éƒµä»¶è¨Žè«–å€åˆ†é–‹ã€‚
-那麼加入這樣一行::
+``git send-email`` 會自動爲你加上。
- Signed-off-by: Random J Developer <random@developer.example.org>
+簽署你的作å“——開發者來æºèªè­‰
+------------------------------
-使用你的真å(抱歉,ä¸èƒ½ä½¿ç”¨å‡å或者匿å。)
+爲了加強å°èª°åšäº†ä½•事的追蹤,尤其是å°é‚£äº›é€éŽå¥½å¹¾å±¤ç¶­è­·è€…æ‰æœ€çµ‚到é”的補ä¸ï¼Œæˆ‘
+們在通éŽéƒµä»¶ç™¼é€çš„補ä¸ä¸Šå¼•入了“簽署(sign-offï¼‰â€æµç¨‹ã€‚
-有人在最後加上標籤。ç¾åœ¨é€™äº›æ±è¥¿æœƒè¢«å¿½ç•¥ï¼Œä½†æ˜¯ä½ å¯ä»¥é€™æ¨£åšï¼Œä¾†æ¨™è¨˜å…¬å¸
-內部的éŽç¨‹ï¼Œæˆ–è€…åªæ˜¯æŒ‡å‡ºé—œæ–¼ sign-off 的一些特殊細節。
+â€œç°½ç½²â€æ˜¯åœ¨è£œä¸è¨»é‡‹æœ€å¾Œçš„一行簡單文字,èªè­‰ä½ ç·¨å¯«äº†å®ƒæˆ–者其他
+人有權力將它作爲開放æºä»£ç¢¼çš„補ä¸å‚³éžã€‚è¦å‰‡å¾ˆç°¡å–®ï¼šå¦‚果你能èªè­‰å¦‚下信æ¯:
-如果您是å­ç³»çµ±æˆ–分支維護人員,有時需è¦ç¨å¾®ä¿®æ”¹æ”¶åˆ°çš„補ä¸ï¼Œä»¥ä¾¿åˆä½µå®ƒå€‘,
-因爲樹和æäº¤è€…中的代碼ä¸å®Œå…¨ç›¸åŒã€‚如果你嚴格éµå®ˆè¦å‰‡ï¼ˆcï¼‰ï¼Œä½ æ‡‰è©²è¦æ±‚æäº¤è€…
-釿–°ç™¼å¸ƒï¼Œä½†é€™å®Œå…¨æ˜¯åœ¨æµªè²»æ™‚間和精力。è¦å‰‡ï¼ˆb)å…許您調整代碼,但是更改一個
-æäº¤è€…的代碼並讓他èªå¯æ‚¨çš„錯誤是éžå¸¸ä¸ç¦®è²Œçš„。è¦è§£æ±ºæ­¤å•題,建議在最後一個
-由簽åè¡Œå’Œæ‚¨çš„è¡Œä¹‹é–“æ·»åŠ ä¸€è¡Œï¼ŒæŒ‡ç¤ºæ›´æ”¹çš„æ€§è³ªã€‚é›–ç„¶é€™ä¸¦ä¸æ˜¯å¼·åˆ¶æ€§çš„,但似乎
-在æè¿°å‰åŠ ä¸Šæ‚¨çš„éƒµä»¶å’Œ/或姓å(全部用方括號括起來),這足以讓人注æ„åˆ°æ‚¨å°æœ€
-後一分é˜çš„æ›´æ”¹è² æœ‰è²¬ä»»ã€‚例如::
+開發者來æºèªè­‰ 1.1
+^^^^^^^^^^^^^^^^^^
- Signed-off-by: Random J Developer <random@developer.example.org>
- [lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
- Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
+å°æ–¼æœ¬é …目的貢ç»ï¼Œæˆ‘èªè­‰å¦‚下信æ¯ï¼š
-å¦‚æžœæ‚¨ç¶­è­·ä¸€å€‹ç©©å®šçš„åˆ†æ”¯æ©Ÿæ§‹ï¼ŒåŒæ™‚希望å°ä½œè€…進行致è¬ã€è·Ÿè¹¤æ›´æ”¹ã€åˆä½µä¿®å¾©ä¸¦
-ä¿è­·æäº¤è€…ä¸å—æŠ•è¨´ï¼Œé‚£éº¼é€™ç¨®åšæ³•尤其有用。請注æ„,在任何情æ³ä¸‹éƒ½ä¸èƒ½æ›´æ”¹ä½œè€…
-çš„ID(From 頭),因爲它是出ç¾åœ¨æ›´æ”¹æ—¥èªŒä¸­çš„æ¨™è­˜ã€‚
+ (a) é€™äº›è²¢ç»æ˜¯å®Œå…¨æˆ–者部分的由我創建,我有權利以文件中指出
+ 的開放æºä»£ç¢¼è¨±å¯è­‰æäº¤å®ƒï¼›æˆ–者
-å°å›žåˆï¼ˆback-porters)的特別說明:在æäº¤æ¶ˆæ¯çš„頂部(主題行之後)æ’入一個補ä¸
-çš„èµ·æºæŒ‡ç¤ºä¼¼ä¹Žæ˜¯ä¸€ç¨®å¸¸è¦‹ä¸”有用的實è¸ï¼Œä»¥ä¾¿æ–¼è·Ÿè¹¤ã€‚ä¾‹å¦‚ï¼Œä¸‹é¢æ˜¯æˆ‘們在3.x穩定
-版本中看到的內容::
+ (b) 這些貢ç»åŸºæ–¼ä»¥å‰çš„工作,據我所知,這些以å‰çš„å·¥ä½œå—æ°ç•¶çš„開放
+ æºä»£ç¢¼è¨±å¯è­‰ä¿è­·ï¼Œè€Œä¸”,根據文件中指出的許å¯è­‰ï¼Œæˆ‘有權æäº¤ä¿®æ”¹å¾Œçš„è²¢ç»ï¼Œ
+ 無論是完全還是部分由我創造,這些貢ç»éƒ½ä½¿ç”¨åŒä¸€å€‹é–‹æ”¾æºä»£ç¢¼è¨±å¯è­‰
+ ï¼ˆé™¤éžæˆ‘被å…許用其它的許å¯è­‰ï¼‰ï¼›æˆ–者
- Date: Tue Oct 7 07:26:38 2014 -0400
+ (c) 這些貢ç»ç”±èªè­‰ï¼ˆa),(b)或者(c)的人直接æä¾›çµ¦æˆ‘,而
+ 且我沒有修改它。
- libata: Un-break ATA blacklist
+ (d) 我ç†è§£ä¸¦åŒæ„é€™å€‹é …ç›®å’Œè²¢ç»æ˜¯å…¬é–‹çš„,貢ç»çš„記錄(包括我
+ 一起æäº¤çš„個人記錄,包括sign-off)被永久維護並且å¯ä»¥å’Œé€™å€‹é …ç›®
+ 或者開放æºä»£ç¢¼çš„許å¯è­‰åŒæ­¥åœ°å†ç™¼è¡Œã€‚
- commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream.
+那麼加入這樣一行::
-還有, 這裡是一個舊版內核中的一個回åˆè£œä¸::
+ Signed-off-by: Random J Developer <random@developer.example.org>
- Date: Tue May 13 22:12:27 2008 +0200
+使用你的真å(抱歉,ä¸èƒ½ä½¿ç”¨å‡å或者匿å。)如果使用 ``git commit -s`` 的話
+將會自動完æˆã€‚撤銷也應當包å«â€œSigned-off-byâ€ï¼Œ ``git revert -s`` 會幫你æžå®šã€‚
- wireless, airo: waitbusy() won't delay
+有些人會在最後加上é¡å¤–的標籤。ç¾åœ¨é€™äº›æ±è¥¿æœƒè¢«å¿½ç•¥ï¼Œä½†æ˜¯ä½ å¯ä»¥é€™æ¨£åšï¼Œä¾†æ¨™è¨˜
+å…¬å¸å…§éƒ¨çš„éŽç¨‹ï¼Œæˆ–è€…åªæ˜¯æŒ‡å‡ºé—œæ–¼ç°½ç½²çš„一些特殊細節。
- [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+作者簽署之後的任何其他簽署(Signed-off-by:'s)å‡ä¾†è‡ªè™•ç†å’Œå‚³éžè£œä¸çš„人員,但
+未åƒèˆ‡å…¶é–‹ç™¼ã€‚ç°½ç½²éˆæ‡‰ç•¶å映補ä¸å‚³æ’­åˆ°ç¶­è­·è€…並最終傳播到Linus所經éŽçš„ **真實**
+路徑,首個簽署指明單個作者的主è¦ä½œè€…身份。
-12)何時使用Acked-by:,CC:,和Co-Developed by:
-----------------------------------------------
+何時使用Acked-by:,CC:,和Co-Developed by:
+------------------------------------------
-Singed-off-by: 標記表示簽å者åƒèˆ‡äº†è£œä¸çš„開發,或者他/她在補ä¸çš„傳éžè·¯å¾‘中。
+Singed-off-by: 標籤表示簽å者åƒèˆ‡äº†è£œä¸çš„開發,或者他/她在補ä¸çš„傳éžè·¯å¾‘中。
-如果一個人沒有直接åƒèˆ‡è£œä¸çš„æº–備或處ç†ï¼Œä½†å¸Œæœ›è¡¨ç¤ºä¸¦è¨˜éŒ„他們å°è£œä¸çš„æ‰¹å‡†ï¼Œ
-那麼他們å¯ä»¥è¦æ±‚在補ä¸çš„變更日誌中添加一個 Acked-by:
+如果一個人沒有直接åƒèˆ‡è£œä¸çš„æº–備或處ç†ï¼Œä½†å¸Œæœ›è¡¨ç¤ºä¸¦è¨˜éŒ„他們å°è£œä¸çš„æ‰¹å‡†/è´Šæˆï¼Œ
+那麼他們å¯ä»¥è¦æ±‚在補ä¸çš„變更日誌中添加一個Acked-by:。
-Acked-by:通常由å—影響代碼的維護者使用,當該維護者既沒有貢ç»ä¹Ÿæ²’æœ‰è½‰ç™¼è£œä¸æ™‚。
+Acked-by: 通常由å—影響代碼的維護者使用,當該維護者既沒有貢ç»ä¹Ÿæ²’æœ‰è½‰ç™¼è£œä¸æ™‚。
-Acked-by: ä¸åƒç°½å­—人那樣正å¼ã€‚這是一個記錄,確èªäººè‡³å°‘審查了補ä¸ï¼Œä¸¦è¡¨ç¤ºæŽ¥å—。
-因此,補ä¸åˆä½µæœ‰æ™‚會手動將Acker的「Yep,looks good to meã€è½‰æ›çˆ² Acked-By:(但
+Acked-by: ä¸åƒç°½ç½²é‚£æ¨£æ­£å¼ã€‚這是一個記錄,確èªäººè‡³å°‘審閱了補ä¸ï¼Œä¸¦è¡¨ç¤ºæŽ¥å—。
+因此,補ä¸åˆä½µæœ‰æ™‚會手動將Acker的“Yep,looks good to meâ€è½‰æ›çˆ² Acked-By:(但
請注æ„ï¼Œé€šå¸¸æœ€å¥½è¦æ±‚一個明確的Ack)。
Acked-by:ä¸ä¸€å®šè¡¨ç¤ºå°æ•´å€‹è£œä¸çš„確èªã€‚例如,如果一個補ä¸å½±éŸ¿å¤šå€‹å­ç³»çµ±ï¼Œä¸¦ä¸”
-有一個:來自一個å­ç³»çµ±ç¶­è­·è€…,那麼這通常表示åªç¢ºèªå½±éŸ¿ç¶­è­·è€…代碼的部分。這裡
-應該仔細判斷。如有疑å•,應åƒè€ƒéƒµä»¶åˆ—表檔案中的原始討論。
+有一個來自æŸå€‹å­ç³»çµ±ç¶­è­·è€…çš„Acked-By:,那麼這通常表示åªç¢ºèªå½±éŸ¿ç¶­è­·è€…代碼的部
+åˆ†ã€‚é€™è£æ‡‰è©²ä»”細判斷。如有疑å•,應åƒè€ƒéƒµä»¶åˆ—表存檔中的原始討論。
-如果æŸäººæœ‰æ©Ÿæœƒå°è£œä¸é€²è¡Œè©•論,但沒有æä¾›æ­¤é¡žè©•論,您å¯ä»¥é¸æ“‡åœ¨è£œä¸ä¸­æ·»åŠ  ``Cc:``
-這是唯一一個標籤,它å¯ä»¥åœ¨æ²’有被它命åçš„äººé¡¯å¼æ“作的情æ³ä¸‹æ·»åŠ ï¼Œä½†å®ƒæ‡‰è©²è¡¨æ˜Ž
-這個人是在補ä¸ä¸ŠæŠ„é€çš„。討論中包å«äº†æ½›åœ¨åˆ©ç›Šç›¸é—œæ–¹ã€‚
+如果æŸäººæœ¬æ‡‰æœ‰æ©Ÿæœƒå°è£œä¸é€²è¡Œè©•論,但沒有æä¾›æ­¤é¡žè©•論,您å¯ä»¥é¸æ“‡åœ¨è£œä¸ä¸­æ·»åŠ 
+``Cc:`` 這是唯一å¯ä»¥åœ¨æ²’æœ‰è¢«è©²äººæ˜Žç¢ºåŒæ„的情æ³ä¸‹æ·»åŠ çš„æ¨™ç±¤â€”â€”ä½†å®ƒæ‡‰è©²è¡¨æ˜Ž
+這個人是在補ä¸ä¸ŠæŠ„é€çš„。此標籤記錄了討論中包å«çš„æ½›åœ¨åˆ©ç›Šç›¸é—œæ–¹ã€‚
Co-developed-by: è²æ˜Žè£œä¸æ˜¯ç”±å¤šå€‹é–‹ç™¼äººå“¡å…±åŒå‰µå»ºçš„;當幾個人在一個補ä¸ä¸Šå·¥
-作時,它用於將屬性賦予共åŒä½œè€…(除了 From: 所賦予的作者之外)。因爲
-Co-developed-by: 表示作者身份,所以æ¯å€‹å…±åŒé–‹ç™¼äººï¼šå¿…須緊跟在相關åˆä½œä½œè€…çš„
-ç°½å之後。標準的簽核程åºè¦æ±‚ï¼šæ¨™è¨˜çš„ç°½æ ¸é †åºæ‡‰å„˜å¯èƒ½å映補ä¸çš„æ™‚é–“æ­·å²ï¼Œè€Œä¸
-ç®¡ä½œè€…æ˜¯é€šéŽ From :還是由 Co-developed-by: å…±åŒé–‹ç™¼çš„。值得注æ„的是,最後一
-個簽字人:必須始終是æäº¤è£œä¸çš„開發人員。
+作時,它用於給出共åŒä½œè€…(除了From:所給出的作者之外)。因爲Co-developed-by:
+表示作者身份,所以æ¯å€‹Co-developed-by:必須緊跟在相關åˆä½œä½œè€…的簽署之後。標準
+簽署程åºè¦æ±‚Singed-off-by:æ¨™ç±¤çš„é †åºæ‡‰å„˜å¯èƒ½å映補ä¸çš„æ™‚é–“æ­·å²ï¼Œç„¡è«–作者是通
+éŽFrom:還是Co-developed-by:表明。值得注æ„的是,最後一個Singed-off-by:必須是
+æäº¤è£œä¸çš„開發人員。
-注æ„,當作者也是電å­éƒµä»¶æ¨™é¡Œã€Œç™¼ä»¶äººï¼šã€è¡Œä¸­åˆ—出的人時,「From: 〠標記是å¯é¸çš„。
+注æ„,如果From:作者也是電å­éƒµä»¶æ¨™é¡Œçš„From:行中列出的人,則From:標籤是å¯é¸çš„。
-作者æäº¤çš„補ä¸ç¨‹åºç¤ºä¾‹::
+被From:作者æäº¤çš„補ä¸ç¤ºä¾‹::
<changelog>
@@ -423,7 +375,7 @@ Co-developed-by: 表示作者身份,所以æ¯å€‹å…±åŒé–‹ç™¼äººï¼šå¿…須緊跟
Signed-off-by: Second Co-Author <second@coauthor.example.org>
Signed-off-by: From Author <from@author.example.org>
-åˆä½œé–‹ç™¼è€…æäº¤çš„補ä¸ç¤ºä¾‹::
+被åˆä½œé–‹ç™¼è€…æäº¤çš„補ä¸ç¤ºä¾‹::
From: From Author <from@author.example.org>
@@ -436,106 +388,115 @@ Co-developed-by: 表示作者身份,所以æ¯å€‹å…±åŒé–‹ç™¼äººï¼šå¿…須緊跟
Signed-off-by: Submitting Co-Author <sub@coauthor.example.org>
-13ï¼‰ä½¿ç”¨å ±å‘Šäººï¼šã€æ¸¬è©¦äººï¼šã€å¯©æ ¸äººï¼šã€å»ºè­°äººï¼šã€ä¿®å¾©äººï¼š
---------------------------------------------------------
+使用Reported-by:ã€Tested-by:ã€Reviewed-by:ã€Suggested-by:å’ŒFixes:
+-----------------------------------------------------------------
Reported-by: 給那些發ç¾éŒ¯èª¤ä¸¦å ±å‘ŠéŒ¯èª¤çš„人致è¬ï¼Œå®ƒå¸Œæœ›æ¿€å‹µä»–å€‘åœ¨å°‡ä¾†å†æ¬¡å¹«åŠ©
-我們。請注æ„,如果bugæ˜¯ä»¥ç§æœ‰æ–¹å¼å ±å‘Šçš„,那麼在使用Reported-by標記之å‰ï¼Œè«‹
-先請求權é™ã€‚
+我們。請注æ„,如果bugæ˜¯ä»¥ç§æœ‰æ–¹å¼å ±å‘Šçš„,那麼在使用Reported-by標籤之å‰ï¼Œè«‹
+先請求許å¯ã€‚此標籤是爲Bug設計的;請ä¸è¦å°‡å…¶ç”¨æ–¼æ„Ÿè¬åŠŸèƒ½è«‹æ±‚ã€‚
-Tested-by: 標記表示補ä¸å·²ç”±æŒ‡å®šçš„人(在æŸäº›ç’°å¢ƒä¸­ï¼‰æˆåŠŸæ¸¬è©¦ã€‚é€™å€‹æ¨™ç±¤é€šçŸ¥
-ç¶­è­·äººå“¡å·²ç¶“åŸ·è¡Œäº†ä¸€äº›æ¸¬è©¦ï¼Œçˆ²å°‡ä¾†çš„è£œä¸æä¾›äº†ä¸€ç¨®å®šä½æ¸¬è©¦äººå“¡çš„æ–¹æ³•,並確
-ä¿æ¸¬è©¦äººå“¡çš„信譽。
+Tested-by: 標籤表示補ä¸å·²ç”±æŒ‡å®šçš„人(在æŸäº›ç’°å¢ƒä¸­ï¼‰æˆåŠŸæ¸¬è©¦ã€‚é€™å€‹æ¨™ç±¤é€šçŸ¥
+ç¶­è­·äººå“¡å·²ç¶“åŸ·è¡Œäº†ä¸€äº›æ¸¬è©¦ï¼Œçˆ²å°‡ä¾†çš„è£œä¸æä¾›äº†ä¸€ç¨®å®šä½æ¸¬è©¦äººå“¡çš„æ–¹æ³•,並彰顯測試人員的功勞。
-Reviewed-by:相åï¼Œæ ¹æ“šå¯©æŸ¥äººçš„è²æ˜Žï¼Œè¡¨æ˜Žè©²è£œä¸å·²è¢«å¯©æŸ¥ä¸¦è¢«èªçˆ²æ˜¯å¯æŽ¥å—的:
+Reviewed-by:根據審閱者的監ç£è²æ˜Žï¼Œè¡¨æ˜Žè©²è£œä¸å·²è¢«å¯©é–±ä¸¦è¢«èªçˆ²æ˜¯å¯æŽ¥å—的:
-審查人的監ç£è²æ˜Ž
+審閱者的監ç£è²æ˜Ž
^^^^^^^^^^^^^^^^
-é€šéŽæä¾›æˆ‘çš„ Reviewed-byï¼Œæˆ‘è²æ˜Žï¼š
+é€šéŽæä¾›æˆ‘çš„Reviewed-by:æ¨™ç±¤ï¼Œæˆ‘è²æ˜Žï¼š
- (a) 我已經å°é€™å€‹è£œä¸é€²è¡Œäº†ä¸€æ¬¡æŠ€è¡“審查,以評估它是å¦é©åˆè¢«åŒ…å«åˆ°
+ (a) 我已經å°é€™å€‹è£œä¸é€²è¡Œäº†ä¸€æ¬¡æŠ€è¡“審閱,以評估它是å¦é©åˆè¢«åŒ…å«åˆ°
主線內核中。
(b) 與補ä¸ç›¸é—œçš„任何å•題ã€é¡§æ…®æˆ–å•題都已å饋給æäº¤è€…ã€‚æˆ‘å°æäº¤è€…å°
我的評論的回應感到滿æ„。
- (c) 雖然這一æäº¤å¯èƒ½æœƒæ”¹é€²ä¸€äº›æ±è¥¿ï¼Œä½†æˆ‘相信,此時,(1)å°å…§æ ¸
+ (c) 雖然這一æäº¤å¯èƒ½ä»å¯è¢«æ”¹é€²ï¼Œä½†æˆ‘相信,此時,(1)å°å…§æ ¸
進行了有價值的修改,(2)沒有包å«çˆ­è«–中涉åŠçš„已知å•題。
- (d) 雖然我已經審查了補ä¸ä¸¦èªçˆ²å®ƒæ˜¯å¥å…¨çš„ï¼Œä½†æˆ‘ä¸æœƒï¼ˆé™¤éžå¦æœ‰æ˜Žç¢º
- 說明)作出任何ä¿è­‰æˆ–ä¿è­‰å®ƒå°‡åœ¨ä»»ä½•給定情æ³ä¸‹å¯¦ç¾å…¶è¦å®šçš„目的
+ (d) 雖然我已經審閱了補ä¸ä¸¦èªçˆ²å®ƒæ˜¯å¥å…¨çš„ï¼Œä½†æˆ‘ä¸æœƒï¼ˆé™¤éžå¦æœ‰æ˜Žç¢º
+ 說明)作出任何ä¿è­‰æˆ–æ“”ä¿å®ƒæœƒåœ¨ä»»ä½•給定情æ³ä¸‹å¯¦ç¾å…¶è¦å®šçš„目的
或正常é‹è¡Œã€‚
-Reviewed-by æ˜¯ä¸€ç¨®è§€é»žè²æ˜Žï¼Œå³è£œä¸æ˜¯å°å…§æ ¸çš„é©ç•¶ä¿®æ”¹ï¼Œæ²’有任何éºç•™çš„åš´é‡æŠ€è¡“
-å•題。任何感興趣的審閱者(完æˆå·¥ä½œçš„人)都å¯ä»¥çˆ²ä¸€å€‹è£œä¸æä¾›ä¸€å€‹ Review-by
-標籤。此標籤用於å‘審閱者æä¾›è‡´è¬ï¼Œä¸¦é€šçŸ¥ç¶­è­·è€…已在修補程åºä¸Šå®Œæˆçš„審閱程度。
-Reviewed-by: 當由已知了解主題å€åŸŸä¸¦åŸ·è¡Œå¾¹åº•檢查的審閱者æä¾›æ™‚,通常會增加
+Reviewed-byæ˜¯ä¸€ç¨®è§€é»žè²æ˜Žï¼Œå³è£œä¸æ˜¯å°å…§æ ¸çš„é©ç•¶ä¿®æ”¹ï¼Œæ²’有任何éºç•™çš„åš´é‡æŠ€è¡“
+å•題。任何感興趣的審閱者(完æˆå·¥ä½œçš„人)都å¯ä»¥çˆ²ä¸€å€‹è£œä¸æä¾›ä¸€å€‹Reviewed-by
+標籤。此標籤用於å‘審閱者æä¾›è‡´è¬ï¼Œä¸¦é€šçŸ¥ç¶­è­·è€…補ä¸çš„審閱進度。
+ç•¶Reviewed-by:標籤由已知了解主題å€åŸŸä¸¦åŸ·è¡Œå¾¹åº•檢查的審閱者æä¾›æ™‚,通常會增加
補ä¸é€²å…¥å…§æ ¸çš„å¯èƒ½æ€§ã€‚
+一旦從測試人員或審閱者的“Tested-byâ€å’Œâ€œReviewed-byâ€æ¨™ç±¤å‡ºç¾åœ¨éƒµä»¶åˆ—表中,
+作者應在發é€ä¸‹ä¸€å€‹ç‰ˆæœ¬æ™‚將其添加到é©ç”¨çš„補ä¸ä¸­ã€‚但是,如果補ä¸åœ¨ä»¥ä¸‹ç‰ˆæœ¬ä¸­ç™¼
+生了實質性更改,這些標籤å¯èƒ½ä¸å†é©ç”¨ï¼Œå› æ­¤æ‡‰è©²åˆªé™¤ã€‚é€šå¸¸ï¼Œåœ¨è£œä¸æ›´æ”¹æ—¥èªŒä¸­
+(在 ``---`` 分隔符之後)應該æåˆ°åˆªé™¤æŸäººçš„æ¸¬è©¦è€…或審閱者標籤。
+
Suggested-by: 表示補ä¸çš„æƒ³æ³•是由指定的人æå‡ºçš„,並確ä¿å°‡æ­¤æƒ³æ³•歸功於指定的
-人。請注æ„,未經許å¯ï¼Œä¸å¾—添加此標籤,特別是如果該想法未在公共論壇上發布。
-é€™å°±æ˜¯èªªï¼Œå¦‚æžœæˆ‘å€‘å‹¤å¿«åœ°è‡´è¬æˆ‘們的創æ„è€…ï¼Œä»–å€‘å¾ˆæœ‰å¸Œæœ›åœ¨æœªä¾†å¾—åˆ°é¼“èˆžï¼Œå†æ¬¡
+人。請注æ„,未經許å¯ï¼Œä¸å¾—添加此標籤,特別是如果該想法未在公共論壇上發佈。
+也就是說,如果我們勤快地致è¬å‰µæ„æä¾›è€…,他們將å—åˆ°é¼“èˆžï¼Œå¾ˆæœ‰å¸Œæœ›åœ¨æœªä¾†å†æ¬¡
幫助我們。
-Fixes: 指示補ä¸åœ¨ä»¥å‰çš„æäº¤ä¸­ä¿®å¾©äº†ä¸€å€‹å•題。它å¯ä»¥å¾ˆå®¹æ˜“地確定錯誤的來æºï¼Œ
-這有助於檢查錯誤修復。這個標記還幫助穩定內核團隊確定應該接收修復的穩定內核
-版本。這是指示補ä¸ä¿®å¾©çš„éŒ¯èª¤çš„é¦–é¸æ–¹æ³•。請åƒé–± :ref:`tw_describe_changes`
-æè¿°æ‚¨çš„æ›´æ”¹ä»¥äº†è§£æ›´å¤šè©³ç´°ä¿¡æ¯ã€‚
+Fixes: 指示補ä¸ä¿®å¾©äº†ä¹‹å‰æäº¤çš„一個å•題。它å¯ä»¥ä¾¿æ–¼ç¢ºå®šéŒ¯èª¤çš„來æºï¼Œé€™æœ‰åŠ©æ–¼
+檢查錯誤修復。這個標籤還幫助穩定內核團隊確定應該接收修復的穩定內核版本。這是
+指示補ä¸ä¿®å¾©çš„éŒ¯èª¤çš„é¦–é¸æ–¹æ³•。請åƒé–± :ref:`zh_describe_changes` 瞭解更多信æ¯ã€‚
+
+.. note::
+
+ 附加Fixes:æ¨™ç±¤ä¸æœƒæ”¹è®Šç©©å®šå…§æ ¸è¦å‰‡æµç¨‹ï¼Œä¹Ÿä¸æ”¹è®Šæ‰€æœ‰ç©©å®šç‰ˆè£œä¸æŠ„é€
+ stable@vger.kernel.orgçš„è¦æ±‚。有關更多信æ¯ï¼Œè«‹é–±è®€
+ Documentation/translations/zh_CN/process/stable-kernel-rules.rst 。
.. _tw_the_canonical_patch_format:
-12ï¼‰æ¨™æº–è£œä¸æ ¼å¼
-----------------
+æ¨™æº–è£œä¸æ ¼å¼
+------------
本節æè¿°å¦‚何格å¼åŒ–è£œä¸æœ¬èº«ã€‚請注æ„,如果您的補ä¸å­˜å„²åœ¨ ``Git`` 存儲庫中,則
-å¯ä»¥ä½¿ç”¨ ``git format-patch`` é€²è¡Œæ­£ç¢ºçš„è£œä¸æ ¼å¼è¨­ç½®ã€‚但是,這些工具無法創建
+å¯ä»¥ä½¿ç”¨ ``git format-patch`` é€²è¡Œæ­£ç¢ºçš„è£œä¸æ ¼å¼åŒ–。但是,這些工具無法創建
å¿…è¦çš„æ–‡æœ¬ï¼Œå› æ­¤è«‹å‹™å¿…閱讀下é¢çš„說明。
-標準的補ä¸ï¼Œæ¨™é¡Œè¡Œæ˜¯::
+æ¨™æº–çš„è£œä¸æ¨™é¡Œè¡Œæ˜¯::
Subject: [PATCH 001/123] å­ç³»çµ±:一å¥è©±æ¦‚è¿°
-標準補ä¸çš„信體存在如下部分:
+標準補ä¸çš„信體包å«å¦‚下部分:
- - 一個 "from" 行指出補ä¸ä½œè€…。後跟空行(僅當發é€ä¿®è£œç¨‹åºçš„äººä¸æ˜¯ä½œè€…時æ‰éœ€è¦ï¼‰ã€‚
+ - 一個 ``from`` 行指出補ä¸ä½œè€…。後跟空行(僅當發é€è£œä¸çš„äººä¸æ˜¯ä½œè€…時æ‰éœ€è¦ï¼‰ã€‚
- - 解釋的正文,行以75列包è£ï¼Œé€™å°‡è¢«è¤‡è£½åˆ°æ°¸ä¹…變更日誌來æè¿°é€™å€‹è£œä¸ã€‚
+ - 說明文字,æ¯è¡Œæœ€é•·75列,這將被複制到永久變更日誌來æè¿°é€™å€‹è£œä¸ã€‚
- 一個空行
- - ä¸Šé¢æè¿°çš„ã€ŒSigned-off-by〠行,也將出ç¾åœ¨æ›´æ”¹æ—¥èªŒä¸­ã€‚
+ - 上述的 ``Signed-off-by:`` 行,也將出ç¾åœ¨æ›´æ”¹æ—¥èªŒä¸­ã€‚
- åªåŒ…å« ``---`` 的標記線。
- - 任何其他ä¸é©åˆæ”¾åœ¨è®Šæ›´æ—¥èªŒçš„æ³¨é‡‹ã€‚
+ - 任何其他ä¸é©åˆæ”¾åœ¨è®Šæ›´æ—¥èªŒçš„註釋。
- 實際補ä¸ï¼ˆ ``diff`` 輸出)。
-標題行的格å¼ï¼Œä½¿å¾—å°æ¨™é¡Œè¡ŒæŒ‰å­—æ¯åºæŽ’åºéžå¸¸çš„容易 - 很多 e-mail 客戶端都
-å¯ä»¥æ”¯æŒ - 因爲åºåˆ—號是用零填充的,所以按數字排åºå’ŒæŒ‰å­—æ¯æŽ’åºæ˜¯ä¸€æ¨£çš„。
+標題行的格å¼ï¼Œä½¿å¾—å°æ¨™é¡Œè¡ŒæŒ‰å­—æ¯åºæŽ’åºéžå¸¸çš„容易——很多郵件客戶端都
+å¯ä»¥æ”¯æŒâ€”—因爲åºåˆ—號是用零填充的,所以按數字排åºå’ŒæŒ‰å­—æ¯æŽ’åºæ˜¯ä¸€æ¨£çš„。
-e-mail 標題中的「å­ç³»çµ±ã€æ¨™è­˜å“ªå€‹å…§æ ¸å­ç³»çµ±å°‡è¢«æ‰“補ä¸ã€‚
+郵件標題中的“å­ç³»çµ±â€æ¨™è­˜å“ªå€‹å…§æ ¸å­ç³»çµ±å°‡è¢«æ‰“補ä¸ã€‚
-e-mail 標題中的「一å¥è©±æ¦‚è¿°ã€æ‰¼è¦çš„æè¿° e-mail 中的補ä¸ã€‚「一å¥è©±æ¦‚è¿°ã€
-䏿‡‰è©²æ˜¯ä¸€å€‹æ–‡ä»¶åã€‚å°æ–¼ä¸€å€‹è£œä¸ç³»åˆ—(「補ä¸ç³»åˆ—ã€æŒ‡ä¸€ç³»åˆ—的多個相關補
-ä¸ï¼‰ï¼Œä¸è¦å°æ¯å€‹è£œä¸éƒ½ä½¿ç”¨åŒæ¨£çš„「一å¥è©±æ¦‚è¿°ã€ã€‚
+郵件標題中的“一å¥è©±æ¦‚è¿°â€æ‰¼è¦çš„æè¿°éƒµä»¶ä¸­çš„補ä¸ã€‚“一å¥è©±æ¦‚è¿°â€
+䏿‡‰è©²æ˜¯ä¸€å€‹æ–‡ä»¶åã€‚å°æ–¼ä¸€å€‹è£œä¸ç³»åˆ—(“補ä¸ç³»åˆ—â€æŒ‡ä¸€ç³»åˆ—的多個相關補
+ä¸ï¼‰ï¼Œä¸è¦å°æ¯å€‹è£œä¸éƒ½ä½¿ç”¨åŒæ¨£çš„“一å¥è©±æ¦‚è¿°â€ã€‚
-è¨˜ä½ e-mail 的「一å¥è©±æ¦‚è¿°ã€æœƒæˆçˆ²è©²è£œä¸çš„全局唯一標識。它會蔓延到 git
-的改動記錄里。然後「一å¥è©±æ¦‚è¿°ã€æœƒè¢«ç”¨åœ¨é–‹ç™¼è€…的討論里,用來指代這個補
-ä¸ã€‚ç”¨æˆ¶å°‡å¸Œæœ›é€šéŽ google 來æœç´¢"一å¥è©±æ¦‚è¿°"來找到那些討論這個補ä¸çš„æ–‡
+記ä½éƒµä»¶çš„“一å¥è©±æ¦‚è¿°â€æœƒæˆçˆ²è©²è£œä¸çš„全局唯一標識。它會進入 ``git``
+的改動記錄è£ã€‚然後“一å¥è©±æ¦‚è¿°â€æœƒè¢«ç”¨åœ¨é–‹ç™¼è€…的討論è£ï¼Œç”¨ä¾†æŒ‡ä»£é€™å€‹è£œ
+ä¸ã€‚ç”¨æˆ¶å°‡å¸Œæœ›é€šéŽæœç´¢å¼•擎æœç´¢â€œä¸€å¥è©±æ¦‚è¿°â€ä¾†æ‰¾åˆ°é‚£äº›è¨Žè«–這個補ä¸çš„æ–‡
章。當人們在兩三個月後使用諸如 ``gitk`` 或 ``git log --oneline`` 之類
的工具查看數åƒå€‹è£œä¸æ™‚,也會很快看到它。
出於這些原因,概述必須ä¸è¶…éŽ70-75個字符,並且必須æè¿°è£œä¸çš„æ›´æ”¹ä»¥åŠçˆ²
-什麼需è¦è£œä¸ã€‚æ—¢è¦ç°¡æ½”åˆè¦æè¿°æ€§å¾ˆæœ‰æŒ‘戰性,但寫得好的概述應該這樣åšã€‚
+什麼需è¦è£œä¸ã€‚æ—¢è¦ç°¡æ½”åˆè¦æè¿°æ€§å¾ˆæœ‰æŒ‘戰性,但寫得好的概述應該這樣。
-概述的å‰ç¶´å¯ä»¥ç”¨æ–¹æ‹¬è™Ÿæ‹¬èµ·ä¾†ï¼šã€ŒSubject: [PATCH <tag>...] <概述>ã€ã€‚標記
+概述的å‰ç¶´å¯ä»¥ç”¨æ–¹æ‹¬è™Ÿæ‹¬èµ·ä¾†ï¼šâ€œSubject: [PATCH <tag>...] <概述>â€ã€‚標記
ä¸è¢«è¦–爲概述的一部分,而是æè¿°æ‡‰è©²å¦‚何處ç†è£œä¸ã€‚如果補ä¸çš„多個版本已發
-é€å‡ºä¾†ä»¥éŸ¿æ‡‰è©•審(å³ã€Œv1,v2,v3ã€ï¼‰æˆ–「rfcã€ï¼Œä»¥æŒ‡ç¤ºè©•審請求,那麼通用標記
-å¯èƒ½åŒ…括版本æè¿°ç¬¦ã€‚如果一個補ä¸ç³»åˆ—中有四個補ä¸ï¼Œé‚£éº¼å„個補ä¸å¯ä»¥é€™æ¨£
-編號:1/4ã€2/4ã€3/4ã€4/4。這å¯ä»¥ç¢ºä¿é–‹ç™¼äººå“¡äº†è§£è£œä¸æ‡‰ç”¨çš„é †åºï¼Œä¸¦ä¸”他們
+é€å‡ºä¾†ä»¥éŸ¿æ‡‰è©•審(å³â€œv1,v2,v3â€ï¼‰å‰‡å¿…須包å«ç‰ˆæœ¬è™Ÿï¼Œæˆ–包å«â€œRFCâ€ä»¥æŒ‡ç¤º
+評審請求。如果一個補ä¸ç³»åˆ—中有四個補ä¸ï¼Œé‚£éº¼å„個補ä¸å¯ä»¥é€™æ¨£ç·¨è™Ÿï¼š1/4ã€2/4ã€
+3/4ã€4/4。這å¯ä»¥ç¢ºä¿é–‹ç™¼äººå“¡çž­è§£è£œä¸æ‡‰ç”¨çš„é †åºï¼Œä¸”
已經查看或應用了補ä¸ç³»åˆ—中的所有補ä¸ã€‚
一些標題的例å­::
@@ -543,95 +504,134 @@ e-mail 標題中的「一å¥è©±æ¦‚è¿°ã€æ‰¼è¦çš„æè¿° e-mail 中的補ä¸ã€‚ã€
Subject: [patch 2/5] ext2: improve scalability of bitmap searching
Subject: [PATCHv2 001/207] x86: fix eflags tracking
-"From" 行是信體裡的最上é¢ä¸€è¡Œï¼Œå…·æœ‰å¦‚下格å¼ï¼š
+``From`` 行是信體è£çš„æœ€ä¸Šé¢ä¸€è¡Œï¼Œå…·æœ‰å¦‚下格å¼::
+
From: Patch Author <author@example.com>
-"From" 行指明在永久改動日誌里,誰會被確èªçˆ²ä½œè€…。如果沒有 "From" 行,那
-麼郵件頭裡的 "From: " 行會被用來決定改動日誌中的作者。
+``From`` 行指明在永久改動日誌è£ï¼Œèª°æœƒè¢«ç¢ºèªçˆ²ä½œè€…。如果沒有 ``From`` 行,那
+麼郵件頭è£çš„ ``From:`` 行會被用來決定改動日誌中的作者。
-說明的主題將會被æäº¤åˆ°æ°¸ä¹…的原始碼改動日誌里,因此å°é‚£äº›æ—©å·²ç¶“ä¸è¨˜å¾—å’Œ
-這個補ä¸ç›¸é—œçš„討論細節的有能力的讀者來說,是有æ„義的。包括補ä¸ç¨‹åºå®šä½
-錯誤的(內核日誌消æ¯ã€OOPS消æ¯ç­‰ï¼‰ç—‡ç‹€ï¼Œå°æ–¼æœç´¢æäº¤æ—¥èªŒä»¥å°‹æ‰¾é©ç”¨è£œä¸çš„人
-尤其有用。如果一個補ä¸ä¿®å¾©äº†ä¸€å€‹ç·¨è­¯å¤±æ•—,那麼å¯èƒ½ä¸éœ€è¦åŒ…嫿‰€æœ‰ç·¨è­¯å¤±æ•—ï¼›
+說明文字將會被æäº¤åˆ°æ°¸ä¹…çš„æºä»£ç¢¼æ”¹å‹•日誌è£ï¼Œå› æ­¤æ‡‰é‡å°é‚£äº›æ—©å·²ç¶“ä¸è¨˜å¾—和這
+個補ä¸ç›¸é—œçš„討論細節的讀者。包括補ä¸è™•ç†çš„æ•…障症狀(內核日誌消æ¯ã€oops消æ¯
+ç­‰ï¼‰ï¼Œé€™å°æ–¼å¯èƒ½æ­£åœ¨æœç´¢æäº¤æ—¥èªŒä»¥æŸ¥æ‰¾é©ç”¨è£œä¸çš„人特別有用。文本應該寫得如
+æ­¤è©³ç´°ï¼Œä»¥ä¾¿åœ¨æ•¸é€±ã€æ•¸æœˆç”šè‡³æ•¸å¹´å¾Œé–±è®€æ™‚,能夠爲讀者æä¾›æ‰€éœ€çš„細節信æ¯ï¼Œä»¥
+掌æ¡å‰µå»ºè£œä¸çš„ **原因** 。
+
+如果一個補ä¸ä¿®å¾©äº†ä¸€å€‹ç·¨è­¯å¤±æ•—,那麼å¯èƒ½ä¸éœ€è¦åŒ…å« *所有* 編譯失敗;
åªè¦è¶³å¤ è®“æœç´¢è£œä¸çš„人能夠找到它就行了。與概述一樣,既è¦ç°¡æ½”åˆè¦æè¿°æ€§ã€‚
-"---" æ¨™è¨˜è¡Œå°æ–¼è£œä¸è™•ç†å·¥å…·è¦æ‰¾åˆ°å“ªè£¡æ˜¯æ”¹å‹•日誌信æ¯çš„çµæŸï¼Œæ˜¯ä¸å¯ç¼ºå°‘
+``---`` æ¨™è¨˜è¡Œå°æ–¼è£œä¸è™•ç†å·¥å…·è¦æ‰¾åˆ°å“ªè£æ˜¯æ”¹å‹•日誌信æ¯çš„çµæŸï¼Œæ˜¯ä¸å¯ç¼ºå°‘
的。
-å°æ–¼ "---" 標記之後的é¡å¤–註解,一個好的用途就是用來寫 diffstat,用來顯
-示修改了什麼文件和æ¯å€‹æ–‡ä»¶éƒ½å¢žåŠ å’Œåˆªé™¤äº†å¤šå°‘è¡Œã€‚diffstat å°æ–¼æ¯”較大的補
-ä¸ç‰¹åˆ¥æœ‰ç”¨ã€‚å…¶é¤˜é‚£äº›åªæ˜¯å’Œæ™‚刻或者開發者相關的註解,ä¸åˆé©æ”¾åˆ°æ°¸ä¹…的改
-動日誌里的,也應該放這裡。
-使用 diffstatçš„é¸é … "-p 1 -w 70" 這樣文件å就會從內核原始碼樹的目錄開始
-ï¼Œä¸æœƒå ç”¨å¤ªå¯¬çš„空間(很容易é©åˆ80列的寬度,也許會有一些縮進。)
+å°æ–¼ ``---`` 標記之後的é¡å¤–註解,一個好的用途就是用來寫 ``diffstat`` ,用來顯
+示修改了什麼文件和æ¯å€‹æ–‡ä»¶éƒ½å¢žåŠ å’Œåˆªé™¤äº†å¤šå°‘è¡Œã€‚ ``diffstat`` å°æ–¼æ¯”較大的補
+ä¸ç‰¹åˆ¥æœ‰ç”¨ã€‚
+使用 ``diffstat`` çš„é¸é … ``-p 1 -w 70`` 這樣文件å就會從內核æºä»£ç¢¼æ¨¹çš„目錄開始
+ï¼Œä¸æœƒä½”用太寬的空間(很容易é©åˆ80列的寬度,也許會有一些縮進。)
+( ``git`` é»˜èªæœƒç”Ÿæˆåˆé©çš„diffstat。)
-在後é¢çš„åƒè€ƒè³‡æ–™ä¸­èƒ½çœ‹åˆ°é©ç•¶çš„è£œä¸æ ¼å¼çš„æ›´å¤šç´°ç¯€ã€‚
+其餘那些åªé©ç”¨æ–¼ç•¶æ™‚或者與維護者相關的註解,ä¸åˆé©æ”¾åˆ°æ°¸ä¹…的改動日誌è£çš„,也
+應該放這è£ã€‚較好的例å­å°±æ˜¯ ``è£œä¸æ›´æ”¹è¨˜éŒ„`` ,記錄了v1å’Œv2版本補ä¸ä¹‹é–“的差異。
-.. _tw_explicit_in_reply_to:
+è«‹å°‡æ­¤ä¿¡æ¯æ”¾åœ¨å°‡è®Šæ›´æ—¥èªŒèˆ‡è£œä¸çš„其餘部分分隔開的 ``---`` 行 **之後** 。版本
+ä¿¡æ¯ä¸æ˜¯æäº¤åˆ°gitæ¨¹çš„è®Šæ›´æ—¥èªŒçš„ä¸€éƒ¨åˆ†ã€‚åªæ˜¯ä¾›å¯©é–±äººå“¡ä½¿ç”¨çš„附加信æ¯ã€‚如果將
+其放置在æäº¤æ¨™è¨˜ä¸Šæ–¹ï¼Œå‰‡éœ€è¦æ‰‹å‹•交互æ‰èƒ½å°‡å…¶åˆªé™¤ã€‚å¦‚æžœå®ƒä½æ–¼åˆ†éš”線以下,則在
+æ‡‰ç”¨è£œä¸æ™‚會自動å‰é›¢::
-15) 明確回覆郵件頭(In-Reply-To)
--------------------------------
+ <commit message>
+ ...
+ Signed-off-by: Author <author@mail>
+ ---
+ V2 -> V3: Removed redundant helper function
+ V1 -> V2: Cleaned up coding style and addressed review comments
-手動添加回復補ä¸çš„的標題頭(In-Reply_To:) 是有幫助的(例如,使用 ``git send-email`` )
-將補ä¸èˆ‡ä»¥å‰çš„相關討論關è¯èµ·ä¾†ï¼Œä¾‹å¦‚,將bug修復程åºé€£çµåˆ°é›»å­éƒµä»¶å’Œbug報告。
-ä½†æ˜¯ï¼Œå°æ–¼å¤šè£œä¸ç³»åˆ—,最好é¿å…在回復時使用連çµåˆ°è©²ç³»åˆ—的舊版本。這樣,
-補ä¸çš„å¤šå€‹ç‰ˆæœ¬å°±ä¸æœƒæˆçˆ²é›»å­éƒµä»¶å®¢æˆ¶ç«¯ä¸­ç„¡æ³•管ç†çš„引用åºåˆ—ã€‚å¦‚æžœé€£çµæœ‰ç”¨ï¼Œ
-å¯ä»¥ä½¿ç”¨ https://lore.kernel.org/ é‡å®šå‘器(例如,在å°é¢é›»å­éƒµä»¶æ–‡æœ¬ä¸­ï¼‰
-連çµåˆ°è£œä¸ç³»åˆ—的早期版本。
+ path/to/file | 5+++--
+ ...
+
+在後é¢çš„åƒè€ƒè³‡æ–™ä¸­èƒ½çœ‹åˆ°æ­£ç¢ºè£œä¸æ ¼å¼çš„æ›´å¤šç´°ç¯€ã€‚
-16) 發é€git pull請求
---------------------
+.. _tw_backtraces:
-如果您有一系列補ä¸ï¼Œé‚£éº¼è®“維護人員通éŽgit pullæ“作將它們直接拉入å­ç³»çµ±å­˜å„²
-庫å¯èƒ½æ˜¯æœ€æ–¹ä¾¿çš„。但是,請注æ„,從開發人員那裡ç²å–è£œä¸æ¯”從郵件列表中ç²å–補
-ä¸éœ€è¦æ›´é«˜çš„信任度。因此,許多å­ç³»çµ±ç¶­è­·äººå“¡ä¸é¡˜æ„接å—請求,特別是來自新的
-未知開發人員的請求。如果有疑å•,您å¯ä»¥åœ¨å°é¢éƒµä»¶ä¸­ä½¿ç”¨pull 請求作爲補ä¸ç³»åˆ—
-正常發布的一個é¸é …,讓維護人員å¯ä»¥é¸æ“‡ä½¿ç”¨å…¶ä¸­ä¹‹ä¸€ã€‚
+æäº¤æ¶ˆæ¯ä¸­çš„回溯(Backtraces)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+回溯有助於記錄導致å•題的調用éˆã€‚ç„¶è€Œï¼Œä¸¦éžæ‰€æœ‰å›žæº¯éƒ½æœ‰å¹«åŠ©ã€‚ä¾‹å¦‚ï¼Œæ—©æœŸå¼•å°Žèª¿
+ç”¨éˆæ˜¯ç¨ç‰¹è€Œæ˜Žé¡¯çš„。而é€å­—複製完整的dmesgè¼¸å‡ºå‰‡æœƒå¢žåŠ æ™‚é–“æˆ³ã€æ¨¡å¡Šåˆ—表ã€å¯„å­˜
+器和堆棧轉儲等分散注æ„力的信æ¯ã€‚
+
+因此,最有用的回溯應該從轉儲中æå–相關信æ¯ï¼Œä»¥æ›´å®¹æ˜“集中在真實å•é¡Œä¸Šã€‚ä¸‹é¢æ˜¯
+一個剪è£è‰¯å¥½çš„回溯示例::
+
+ unchecked MSR access error: WRMSR to 0xd51 (tried to write 0x0000000000000064)
+ at rIP: 0xffffffffae059994 (native_write_msr+0x4/0x20)
+ Call Trace:
+ mba_wrmsr
+ update_domains
+ rdtgroup_mkdir
+
+.. _tw_explicit_in_reply_to:
+
+明確回覆郵件頭(In-Reply-To)
+-----------------------------
+
+手動添加回復補ä¸çš„的郵件頭(In-Reply_To:)是有用的(例如,使用 ``git send-email`` ),
+å¯ä»¥å°‡è£œä¸èˆ‡ä»¥å‰çš„相關討論關è¯èµ·ä¾†ï¼Œä¾‹å¦‚,將bug補ä¸éˆæŽ¥åˆ°é›»å­éƒµä»¶å’Œbug報告。
+ä½†æ˜¯ï¼Œå°æ–¼å¤šè£œä¸ç³»åˆ—,最好é¿å…åœ¨å›žè¦†æ™‚ä½¿ç”¨éˆæŽ¥åˆ°è©²ç³»åˆ—çš„èˆŠç‰ˆæœ¬ã€‚é€™æ¨£ï¼Œ
+補ä¸çš„å¤šå€‹ç‰ˆæœ¬å°±ä¸æœƒæˆçˆ²é›»å­éƒµä»¶å®¢æˆ¶ç«¯ä¸­ç„¡æ³•管ç†çš„å¼•ç”¨æ¨¹ã€‚å¦‚æžœéˆæŽ¥æœ‰ç”¨ï¼Œ
+å¯ä»¥ä½¿ç”¨ https://lore.kernel.org/ é‡å®šå‘器(例如,在å°é¢é›»å­éƒµä»¶æ–‡æœ¬ä¸­ï¼‰
+éˆæŽ¥åˆ°è£œä¸ç³»åˆ—的早期版本。
-pull 請求的主題行中應該有[Git Pull]。請求本身應該在一行中包å«å­˜å„²åº«å稱和
-感興趣的分支;它應該看起來åƒ::
+給出基礎樹信æ¯
+--------------
- Please pull from
+當其他開發人員收到您的補ä¸ä¸¦é–‹å§‹å¯©é–±æ™‚ï¼ŒçŸ¥é“æ‡‰è©²å°‡æ‚¨çš„工作放到代碼樹歷å²è¨˜éŒ„
+中的什麼ä½ç½®é€šå¸¸å¾ˆæœ‰ç”¨ã€‚這尿–¼è‡ªå‹•化æŒçºŒé›†æˆæµæ°´ï¼ˆCIï¼‰ç‰¹åˆ¥æœ‰ç”¨ï¼Œé€™äº›æµæ°´ç·šè©¦
+圖é‹è¡Œä¸€ç³»åˆ—測試,以便在維護人員開始審閱之å‰ç¢ºå®šæäº¤çš„質é‡ã€‚
- git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+如果您使用 ``git format-patch`` 生æˆè£œä¸ï¼Œå‰‡å¯ä»¥é€šéŽ ``--base`` 標誌在æäº¤ä¸­
+自動包å«åŸºç¤Žæ¨¹ä¿¡æ¯ã€‚使用此é¸é …æœ€ç°¡å–®ã€æœ€æ–¹ä¾¿çš„æ–¹æ³•是é…åˆä¸»é¡Œåˆ†æ”¯::
- to get these changes:
+ $ git checkout -t -b my-topical-branch master
+ Branch 'my-topical-branch' set up to track local branch 'master'.
+ Switched to a new branch 'my-topical-branch'
+ [perform your edits and commits]
-pull 請求還應該包å«ä¸€æ¢æ•´é«”消æ¯ï¼Œèªªæ˜Žè«‹æ±‚中將包å«ä»€éº¼ï¼Œä¸€å€‹è£œä¸æœ¬èº«çš„ ``Git shortlog``
-以åŠä¸€å€‹é¡¯ç¤ºè£œä¸ç³»åˆ—整體效果的 ``diffstat`` ã€‚ç•¶ç„¶ï¼Œå°‡æ‰€æœ‰é€™äº›ä¿¡æ¯æ”¶é›†åœ¨ä¸€èµ·
-的最簡單方法是讓 ``git`` 使用 ``git request-pull`` 命令爲您完æˆé€™äº›å·¥ä½œã€‚
+ $ git format-patch --base=auto --cover-letter -o outgoing/ master
+ outgoing/0000-cover-letter.patch
+ outgoing/0001-First-Commit.patch
+ outgoing/...
-一些維護人員(包括Linus)希望看到來自已簽åæäº¤çš„請求;這增加了他們å°ä½ çš„
-è«‹æ±‚ä¿¡å¿ƒã€‚ç‰¹åˆ¥æ˜¯ï¼Œåœ¨æ²’æœ‰ç°½åæ¨™ç±¤çš„æƒ…æ³ä¸‹ï¼ŒLinus 䏿œƒå¾žåƒ Github 這樣的公共
-託管站點拉請求。
+當你編輯 ``outgoing/0000-cover-letter.patch`` 時,您會注æ„到在它的最底部有一
+行 ``base-commit:`` 尾註,它爲審閱者和CI工具æä¾›äº†è¶³å¤ çš„ä¿¡æ¯ä»¥æ­£ç¢ºåŸ·è¡Œ
+``git am`` 而ä¸å¿…擔心è¡çª::
-創建此類簽å的第一步是生æˆä¸€å€‹ GNRPG 密鑰,並由一個或多個核心內核開發人員å°
-其進行簽åã€‚é€™ä¸€æ­¥å°æ–°é–‹ç™¼äººå“¡ä¾†èªªå¯èƒ½å¾ˆå›°é›£ï¼Œä½†æ²’有辦法繞éŽå®ƒã€‚åƒåŠ æœƒè­°æ˜¯
-找到å¯ä»¥ç°½ç½²æ‚¨çš„密鑰的開發人員的好方法。
+ $ git checkout -b patch-review [base-commit-id]
+ Switched to a new branch 'patch-review'
+ $ git am patches.mbox
+ Applying: First Commit
+ Applying: ...
-一旦您在Git 中準備了一個您希望有人拉的補ä¸ç³»åˆ—,就用 ``git tag -s`` 創建一
-å€‹ç°½åæ¨™è¨˜ã€‚這將創建一個新標記,標識該系列中的最後一次æäº¤ï¼Œä¸¦åŒ…å«ç”¨æ‚¨çš„ç§
-鑰創建的簽å。您還å¯ä»¥å°‡changelog樣å¼çš„æ¶ˆæ¯æ·»åŠ åˆ°æ¨™è¨˜ä¸­ï¼›é€™æ˜¯ä¸€å€‹æè¿°æ‹‰è«‹æ±‚
-æ•´é«”æ•ˆæžœçš„ç†æƒ³ä½ç½®ã€‚
+有關此é¸é …的更多信æ¯ï¼Œè«‹åƒé–± ``man git-format-patch`` 。
-如果維護人員將è¦å¾žä¸­æå–çš„æ¨¹ä¸æ˜¯æ‚¨æ­£åœ¨ä½¿ç”¨çš„存儲庫,請ä¸è¦å¿˜è¨˜å°‡å·²ç°½å的標記
-顝弿ލé€åˆ°å…¬å…±æ¨¹ã€‚
+.. note::
-ç”Ÿæˆæ‹‰è«‹æ±‚時,請使用已簽å的標記作爲目標。這樣的命令å¯ä»¥å¯¦ç¾::
+ ``--base`` 功能是在2.9.0版git中引入的。
- git request-pull master git://my.public.tree/linux.git my-signed-tag
+如果您ä¸ä½¿ç”¨gitæ ¼å¼åŒ–補ä¸ï¼Œä»ç„¶å¯ä»¥åŒ…å«ç›¸åŒçš„ ``base-commit`` 尾註,以指示您
+的工作所基於的樹的æäº¤å“ˆå¸Œã€‚你應該在å°é¢éƒµä»¶æˆ–系列的第一個補ä¸ä¸­æ·»åŠ å®ƒï¼Œå®ƒæ‡‰
+該放在 ``---`` è¡Œçš„ä¸‹é¢æˆ–所有其他內容之後,å³åªåœ¨ä½ çš„é›»å­éƒµä»¶ç°½å之å‰ã€‚
åƒè€ƒæ–‡ç»
--------
-Andrew Morton, "The perfect patch" (tpp).
+Andrew Morton,“完美的補ä¸â€ï¼ˆtpp)
<https://www.ozlabs.org/~akpm/stuff/tpp.txt>
-Jeff Garzik, "Linux kernel patch submission format".
+Jeff Garzik,“Linuxå…§æ ¸è£œä¸æäº¤æ ¼å¼â€
<https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html>
-Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+Greg Kroah-Hartman,“如何惹惱內核å­ç³»çµ±ç¶­è­·äººå“¡â€
<http://www.kroah.com/log/linux/maintainer.html>
<http://www.kroah.com/log/linux/maintainer-02.html>
@@ -644,17 +644,16 @@ Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
<http://www.kroah.com/log/linux/maintainer-06.html>
-NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+ä¸ï¼ï¼ï¼åˆ¥å†ç™¼å·¨åž‹è£œä¸ç‚¸å½ˆçµ¦linux-kernel@vger.kernel.org的人們了ï¼
<https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
-Kernel Documentation/process/coding-style.rst:
- :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+å…§æ ¸ Documentation/translations/zh_CN/process/coding-style.rst
-Linus Torvalds's mail on the canonical patch format:
+Linus Torvaldsé—œæ–¼æ¨™æº–è£œä¸æ ¼å¼çš„郵件
<https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>
-Andi Kleen, "On submitting kernel patches"
- Some strategies to get difficult or controversial changes in.
+Andi Kleen,“æäº¤è£œä¸ä¹‹è·¯â€
+ 一些幫助åˆå…¥å›°é›£æˆ–有爭議的變更的策略。
http://halobates.de/on-submitting-patches.pdf
diff --git a/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
index 469cb5b3a07c..a609620affb0 100644
--- a/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
+++ b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
@@ -19,20 +19,20 @@
時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
胡皓文 Hu Haowen <src.res.211@gmail.com>
-çˆ²ä»€éº¼ä¸æ‡‰è©²ä½¿ç”¨ã€Œvolatileã€é¡žåž‹
-================================
+çˆ²ä»€éº¼ä¸æ‡‰è©²ä½¿ç”¨â€œvolatileâ€é¡žåž‹
+==============================
-C程å¼è¨­è¨ˆå¸«é€šå¸¸èªçˆ²volatile表示æŸå€‹è®Šé‡å¯ä»¥åœ¨ç•¶å‰åŸ·è¡Œçš„線程之外被改變;因此,在內核
-ä¸­ç”¨åˆ°å…±äº«æ•¸æ“šçµæ§‹æ™‚,常常會有C程å¼è¨­è¨ˆå¸«å–œæ­¡ä½¿ç”¨volatile這類變é‡ã€‚æ›å¥è©±èªªï¼Œä»–們經
+C程åºå“¡é€šå¸¸èªçˆ²volatile表示æŸå€‹è®Šé‡å¯ä»¥åœ¨ç•¶å‰åŸ·è¡Œçš„線程之外被改變;因此,在內核
+ä¸­ç”¨åˆ°å…±äº«æ•¸æ“šçµæ§‹æ™‚,常常會有C程åºå“¡å–œæ­¡ä½¿ç”¨volatile這類變é‡ã€‚æ›å¥è©±èªªï¼Œä»–們經
常會把volatileé¡žåž‹çœ‹æˆæŸç¨®ç°¡æ˜“的原å­è®Šé‡ï¼Œç•¶ç„¶å®ƒå€‘䏿˜¯ã€‚在內核中使用volatileå¹¾
乎總是錯誤的;本文檔將解釋爲什麼這樣。
ç†è§£volatileçš„é—œéµæ˜¯çŸ¥é“它的目的是用來消除優化,實際上很少有人真正需è¦é€™æ¨£çš„æ‡‰
-用。在內核中,程å¼è¨­è¨ˆå¸«å¿…須防止æ„外的並發訪å•ç ´å£žå…±äº«çš„æ•¸æ“šçµæ§‹ï¼Œé€™å…¶å¯¦æ˜¯ä¸€å€‹å®Œå…¨
-ä¸åŒçš„任務。用來防止æ„外並發訪å•çš„ä¿è­·æŽªæ–½ï¼Œå¯ä»¥æ›´åŠ é«˜æ•ˆçš„é¿å…大多數優化相關的
+用。在內核中,程åºå“¡å¿…須防止æ„外的併發訪å•ç ´å£žå…±äº«çš„æ•¸æ“šçµæ§‹ï¼Œé€™å…¶å¯¦æ˜¯ä¸€å€‹å®Œå…¨
+ä¸åŒçš„任務。用來防止æ„外併發訪å•çš„ä¿è­·æŽªæ–½ï¼Œå¯ä»¥æ›´åŠ é«˜æ•ˆçš„é¿å…大多數優化相關的
å•題。
-åƒvolatile一樣,內核æä¾›äº†å¾ˆå¤šåŽŸèªžä¾†ä¿è­‰ä¸¦ç™¼è¨ªå•時的數據安全(自旋鎖, 互斥é‡,å…§
+åƒvolatile一樣,內核æä¾›äº†å¾ˆå¤šåŽŸèªžä¾†ä¿è­‰ä½µç™¼è¨ªå•時的數據安全(自旋鎖, 互斥é‡,å…§
å­˜å±éšœç­‰ç­‰ï¼‰ï¼ŒåŒæ¨£å¯ä»¥é˜²æ­¢æ„外的優化。如果å¯ä»¥æ­£ç¢ºä½¿ç”¨é€™äº›å…§æ ¸åŽŸèªžï¼Œé‚£éº¼å°±æ²’æœ‰
å¿…è¦å†ä½¿ç”¨volatile。如果ä»ç„¶å¿…須使用volatile,那麼幾乎å¯ä»¥è‚¯å®šåœ¨ä»£ç¢¼çš„æŸè™•æœ‰ä¸€
個bug。在正確設計的內核代碼中,volatile能帶來的僅僅是使事情變慢。
@@ -46,8 +46,8 @@ C程å¼è¨­è¨ˆå¸«é€šå¸¸èªçˆ²volatile表示æŸå€‹è®Šé‡å¯ä»¥åœ¨ç•¶å‰åŸ·è¡Œçš„ç·
如果所有的代碼都éµå¾ªåŠ éŽ–è¦å‰‡ï¼Œç•¶æŒæœ‰the_lock的時候,ä¸å¯èƒ½æ„外的改變shared_dataçš„
值。任何å¯èƒ½è¨ªå•該數據的其他代碼都會在這個鎖上等待。自旋鎖原語跟內存å±éšœä¸€æ¨£â€”— 它
-們顯å¼çš„用來書寫æˆé€™æ¨£ —— æ„味著數據訪å•䏿œƒè·¨è¶Šå®ƒå€‘而被優化。所以本來編譯器èªçˆ²
-它知é“在shared_data裡é¢å°‡æœ‰ä»€éº¼ï¼Œä½†æ˜¯å› çˆ²spin_lock()調用跟內存å±éšœä¸€æ¨£ï¼Œæœƒå¼·åˆ¶ç·¨
+們顯å¼çš„用來書寫æˆé€™æ¨£ —— æ„å‘³ç€æ•¸æ“šè¨ªå•䏿œƒè·¨è¶Šå®ƒå€‘而被優化。所以本來編譯器èªçˆ²
+它知é“在shared_dataè£é¢å°‡æœ‰ä»€éº¼ï¼Œä½†æ˜¯å› çˆ²spin_lock()調用跟內存å±éšœä¸€æ¨£ï¼Œæœƒå¼·åˆ¶ç·¨
譯器忘記它所知é“的一切。那麼在訪å•é€™äº›æ•¸æ“šæ™‚ä¸æœƒæœ‰å„ªåŒ–çš„å•題。
如果shared_data被è²å爲volatile,鎖æ“作將ä»ç„¶æ˜¯å¿…é ˆçš„ã€‚å°±ç®—æˆ‘å€‘çŸ¥é“æ²’有其他人正在
@@ -55,13 +55,13 @@ C程å¼è¨­è¨ˆå¸«é€šå¸¸èªçˆ²volatile表示æŸå€‹è®Šé‡å¯ä»¥åœ¨ç•¶å‰åŸ·è¡Œçš„ç·
shared_data䏿˜¯volatile的。在處ç†å…±äº«æ•¸æ“šçš„æ™‚候,é©ç•¶çš„鎖æ“作å¯ä»¥ä¸å†éœ€è¦
volatile —— 並且是有潛在å±å®³çš„。
-volatileçš„å­˜å„²é¡žåž‹æœ€åˆæ˜¯çˆ²é‚£äº›å…§å­˜æ˜ å°„çš„I/O寄存器而定義。在內核里,寄存器訪å•也應
-該被鎖ä¿è­·ï¼Œä½†æ˜¯äººå€‘也ä¸å¸Œæœ›ç·¨è­¯å™¨ã€Œå„ªåŒ–ã€è‡¨ç•Œå€å…§çš„寄存器訪å•。內核里I/O的內存訪å•
+volatileçš„å­˜å„²é¡žåž‹æœ€åˆæ˜¯çˆ²é‚£äº›å…§å­˜æ˜ å°„çš„I/O寄存器而定義。在內核è£ï¼Œå¯„存器訪å•也應
+該被鎖ä¿è­·ï¼Œä½†æ˜¯äººå€‘也ä¸å¸Œæœ›ç·¨è­¯å™¨â€œå„ªåŒ–â€è‡¨ç•Œå€å…§çš„寄存器訪å•。內核è£I/O的內存訪å•
是通éŽè¨ªå•函數完æˆçš„ï¼›ä¸è´Šæˆé€šéŽæŒ‡é‡å°I/O內存的直接訪å•ï¼Œä¸¦ä¸”ä¸æ˜¯åœ¨æ‰€æœ‰é«”系架構上
都能工作。那些訪å•函數正是爲了防止æ„外優化而寫的,因此,å†èªªä¸€æ¬¡ï¼Œvolatile類型ä¸
是必需的。
-å¦ä¸€ç¨®å¼•起用戶å¯èƒ½ä½¿ç”¨volatileçš„æƒ…æ³æ˜¯ç•¶è™•ç†å™¨æ­£å¿™è‘—等待一個變é‡çš„值。正確執行一
+å¦ä¸€ç¨®å¼•起用戶å¯èƒ½ä½¿ç”¨volatileçš„æƒ…æ³æ˜¯ç•¶è™•ç†å™¨æ­£å¿™ç€ç­‰å¾…一個變é‡çš„值。正確執行一
個忙等待的方法是::
while (my_variable != what_i_want)
@@ -74,14 +74,14 @@ cpu_relax()調用會é™ä½ŽCPUçš„èƒ½é‡æ¶ˆè€—æˆ–è€…è®“ä½æ–¼è¶…線程雙處ç†å™¨
- 在一些體系架構的系統上,å…許直接的I/0內存訪å•,那麼å‰é¢æåˆ°çš„訪å•函數å¯ä»¥ä½¿ç”¨
volatile。基本上,æ¯ä¸€å€‹è¨ªå•函數調用它自己都是一個å°çš„臨界å€åŸŸä¸¦ä¸”ä¿è­‰äº†æŒ‰ç…§
- 程å¼è¨­è¨ˆå¸«æœŸæœ›çš„é‚£æ¨£ç™¼ç”Ÿè¨ªå•æ“作。
+ 程åºå“¡æœŸæœ›çš„é‚£æ¨£ç™¼ç”Ÿè¨ªå•æ“作。
- æŸäº›æœƒæ”¹è®Šå…§å­˜çš„å…§è¯å½™ç·¨ä»£ç¢¼é›–然沒有什麼其他明顯的附作用,但是有被GCC刪除的å¯
èƒ½æ€§ã€‚åœ¨å½™ç·¨è²æ˜Žä¸­åŠ ä¸Švolatileé—œéµå­—å¯ä»¥é˜²æ­¢é€™ç¨®åˆªé™¤æ“作。
- Jiffiesè®Šé‡æ˜¯ä¸€ç¨®ç‰¹æ®Šæƒ…æ³ï¼Œé›–ç„¶æ¯æ¬¡å¼•用它的時候都å¯ä»¥æœ‰ä¸åŒçš„值,但讀jiffies
è®Šé‡æ™‚ä¸éœ€è¦ä»»ä½•特殊的加鎖ä¿è­·ã€‚所以jiffies變é‡å¯ä»¥ä½¿ç”¨volatile,但是ä¸è´Šæˆ
- å…¶ä»–è·Ÿjiffies相åŒé¡žåž‹è®Šé‡ä½¿ç”¨volatile。Jiffies被èªçˆ²æ˜¯ä¸€ç¨®ã€Œæ„šè ¢çš„éºç•™ç‰©"
+ å…¶ä»–è·Ÿjiffies相åŒé¡žåž‹è®Šé‡ä½¿ç”¨volatile。Jiffies被èªçˆ²æ˜¯ä¸€ç¨®â€œæ„šè ¢çš„éºç•™ç‰©"
(Linus的話)因爲解決這個å•é¡Œæ¯”ä¿æŒç¾ç‹€è¦éº»ç…©çš„多。
- 由於æŸäº›I/0設備å¯èƒ½æœƒä¿®æ”¹é€£çºŒä¸€è‡´çš„å…§å­˜,所以有時,指å‘é€£çºŒä¸€è‡´å…§å­˜çš„æ•¸æ“šçµæ§‹
@@ -92,9 +92,9 @@ cpu_relax()調用會é™ä½ŽCPUçš„èƒ½é‡æ¶ˆè€—æˆ–è€…è®“ä½æ–¼è¶…線程雙處ç†å™¨
bug並且需è¦å°é€™æ¨£çš„代碼é¡å¤–仔細檢查。那些試圖使用volatile的開發人員需è¦é€€ä¸€æ­¥æƒ³æƒ³
他們真正想實ç¾çš„æ˜¯ä»€éº¼ã€‚
-éžå¸¸æ­¡è¿Žåˆªé™¤volatile變é‡çš„è£œä¸ ï¼ åªè¦è­‰æ˜Žé€™äº›è£œä¸å®Œæ•´çš„考慮了並發å•題。
+éžå¸¸æ­¡è¿Žåˆªé™¤volatile變é‡çš„è£œä¸ ï¼ åªè¦è­‰æ˜Žé€™äº›è£œä¸å®Œæ•´çš„考慮了併發å•題。
-注釋
+註釋
----
[1] https://lwn.net/Articles/233481/
diff --git a/Documentation/usb/gadget-testing.rst b/Documentation/usb/gadget-testing.rst
index 394cd226bfae..29072c166d23 100644
--- a/Documentation/usb/gadget-testing.rst
+++ b/Documentation/usb/gadget-testing.rst
@@ -755,6 +755,8 @@ The uac2 function provides these attributes in its function directory:
req_number the number of pre-allocated request for both capture
and playback
function_name name of the interface
+ c_terminal_type code of the capture terminal type
+ p_terminal_type code of the playback terminal type
================ ====================================================
The attributes have sane default values.
diff --git a/Documentation/usb/gadget_uvc.rst b/Documentation/usb/gadget_uvc.rst
index 80a1f031b593..bf78fba3ce23 100644
--- a/Documentation/usb/gadget_uvc.rst
+++ b/Documentation/usb/gadget_uvc.rst
@@ -126,7 +126,7 @@ might do:
create_frame 1920 1080 uncompressed yuyv
The only uncompressed format currently supported is YUYV, which is detailed at
-Documentation/userspace-api/media/v4l/pixfmt-packed.yuv.rst.
+Documentation/userspace-api/media/v4l/pixfmt-packed-yuv.rst.
Color Matching Descriptors
~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/userspace-api/dma-buf-alloc-exchange.rst b/Documentation/userspace-api/dma-buf-alloc-exchange.rst
new file mode 100644
index 000000000000..fdff19fce13e
--- /dev/null
+++ b/Documentation/userspace-api/dma-buf-alloc-exchange.rst
@@ -0,0 +1,389 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. Copyright 2021-2023 Collabora Ltd.
+
+========================
+Exchanging pixel buffers
+========================
+
+As originally designed, the Linux graphics subsystem had extremely limited
+support for sharing pixel-buffer allocations between processes, devices, and
+subsystems. Modern systems require extensive integration between all three
+classes; this document details how applications and kernel subsystems should
+approach this sharing for two-dimensional image data.
+
+It is written with reference to the DRM subsystem for GPU and display devices,
+V4L2 for media devices, and also to Vulkan, EGL and Wayland, for userspace
+support, however any other subsystems should also follow this design and advice.
+
+
+Glossary of terms
+=================
+
+.. glossary::
+
+ image:
+ Conceptually a two-dimensional array of pixels. The pixels may be stored
+ in one or more memory buffers. Has width and height in pixels, pixel
+ format and modifier (implicit or explicit).
+
+ row:
+ A span along a single y-axis value, e.g. from co-ordinates (0,100) to
+ (200,100).
+
+ scanline:
+ Synonym for row.
+
+ column:
+ A span along a single x-axis value, e.g. from co-ordinates (100,0) to
+ (100,100).
+
+ memory buffer:
+ A piece of memory for storing (parts of) pixel data. Has stride and size
+ in bytes and at least one handle in some API. May contain one or more
+ planes.
+
+ plane:
+ A two-dimensional array of some or all of an image's color and alpha
+ channel values.
+
+ pixel:
+ A picture element. Has a single color value which is defined by one or
+ more color channels values, e.g. R, G and B, or Y, Cb and Cr. May also
+ have an alpha value as an additional channel.
+
+ pixel data:
+ Bytes or bits that represent some or all of the color/alpha channel values
+ of a pixel or an image. The data for one pixel may be spread over several
+ planes or memory buffers depending on format and modifier.
+
+ color value:
+ A tuple of numbers, representing a color. Each element in the tuple is a
+ color channel value.
+
+ color channel:
+ One of the dimensions in a color model. For example, RGB model has
+ channels R, G, and B. Alpha channel is sometimes counted as a color
+ channel as well.
+
+ pixel format:
+ A description of how pixel data represents the pixel's color and alpha
+ values.
+
+ modifier:
+ A description of how pixel data is laid out in memory buffers.
+
+ alpha:
+ A value that denotes the color coverage in a pixel. Sometimes used for
+ translucency instead.
+
+ stride:
+ A value that denotes the relationship between pixel-location co-ordinates
+ and byte-offset values. Typically used as the byte offset between two
+ pixels at the start of vertically-consecutive tiling blocks. For linear
+ layouts, the byte offset between two vertically-adjacent pixels. For
+ non-linear formats the stride must be computed in a consistent way, which
+ usually is done as-if the layout was linear.
+
+ pitch:
+ Synonym for stride.
+
+
+Formats and modifiers
+=====================
+
+Each buffer must have an underlying format. This format describes the color
+values provided for each pixel. Although each subsystem has its own format
+descriptions (e.g. V4L2 and fbdev), the ``DRM_FORMAT_*`` tokens should be reused
+wherever possible, as they are the standard descriptions used for interchange.
+These tokens are described in the ``drm_fourcc.h`` file, which is a part of
+DRM's uAPI.
+
+Each ``DRM_FORMAT_*`` token describes the translation between a pixel
+co-ordinate in an image, and the color values for that pixel contained within
+its memory buffers. The number and type of color channels are described:
+whether they are RGB or YUV, integer or floating-point, the size of each channel
+and their locations within the pixel memory, and the relationship between color
+planes.
+
+For example, ``DRM_FORMAT_ARGB8888`` describes a format in which each pixel has
+a single 32-bit value in memory. Alpha, red, green, and blue, color channels are
+available at 8-bit precision per channel, ordered respectively from most to
+least significant bits in little-endian storage. ``DRM_FORMAT_*`` is not
+affected by either CPU or device endianness; the byte pattern in memory is
+always as described in the format definition, which is usually little-endian.
+
+As a more complex example, ``DRM_FORMAT_NV12`` describes a format in which luma
+and chroma YUV samples are stored in separate planes, where the chroma plane is
+stored at half the resolution in both dimensions (i.e. one U/V chroma
+sample is stored for each 2x2 pixel grouping).
+
+Format modifiers describe a translation mechanism between these per-pixel memory
+samples, and the actual memory storage for the buffer. The most straightforward
+modifier is ``DRM_FORMAT_MOD_LINEAR``, describing a scheme in which each plane
+is laid out row-sequentially, from the top-left to the bottom-right corner.
+This is considered the baseline interchange format, and most convenient for CPU
+access.
+
+Modern hardware employs much more sophisticated access mechanisms, typically
+making use of tiled access and possibly also compression. For example, the
+``DRM_FORMAT_MOD_VIVANTE_TILED`` modifier describes memory storage where pixels
+are stored in 4x4 blocks arranged in row-major ordering, i.e. the first tile in
+a plane stores pixels (0,0) to (3,3) inclusive, and the second tile in a plane
+stores pixels (4,0) to (7,3) inclusive.
+
+Some modifiers may modify the number of planes required for an image; for
+example, the ``I915_FORMAT_MOD_Y_TILED_CCS`` modifier adds a second plane to RGB
+formats in which it stores data about the status of every tile, notably
+including whether the tile is fully populated with pixel data, or can be
+expanded from a single solid color.
+
+These extended layouts are highly vendor-specific, and even specific to
+particular generations or configurations of devices per-vendor. For this reason,
+support of modifiers must be explicitly enumerated and negotiated by all users
+in order to ensure a compatible and optimal pipeline, as discussed below.
+
+
+Dimensions and size
+===================
+
+Each pixel buffer must be accompanied by logical pixel dimensions. This refers
+to the number of unique samples which can be extracted from, or stored to, the
+underlying memory storage. For example, even though a 1920x1080
+``DRM_FORMAT_NV12`` buffer has a luma plane containing 1920x1080 samples for the Y
+component, and 960x540 samples for the U and V components, the overall buffer is
+still described as having dimensions of 1920x1080.
+
+The in-memory storage of a buffer is not guaranteed to begin immediately at the
+base address of the underlying memory, nor is it guaranteed that the memory
+storage is tightly clipped to either dimension.
+
+Each plane must therefore be described with an ``offset`` in bytes, which will be
+added to the base address of the memory storage before performing any per-pixel
+calculations. This may be used to combine multiple planes into a single memory
+buffer; for example, ``DRM_FORMAT_NV12`` may be stored in a single memory buffer
+where the luma plane's storage begins immediately at the start of the buffer
+with an offset of 0, and the chroma plane's storage follows within the same buffer
+beginning from the byte offset for that plane.
+
+Each plane must also have a ``stride`` in bytes, expressing the offset in memory
+between two contiguous row. For example, a ``DRM_FORMAT_MOD_LINEAR`` buffer
+with dimensions of 1000x1000 may have been allocated as if it were 1024x1000, in
+order to allow for aligned access patterns. In this case, the buffer will still
+be described with a width of 1000, however the stride will be ``1024 * bpp``,
+indicating that there are 24 pixels at the positive extreme of the x axis whose
+values are not significant.
+
+Buffers may also be padded further in the y dimension, simply by allocating a
+larger area than would ordinarily be required. For example, many media decoders
+are not able to natively output buffers of height 1080, but instead require an
+effective height of 1088 pixels. In this case, the buffer continues to be
+described as having a height of 1080, with the memory allocation for each buffer
+being increased to account for the extra padding.
+
+
+Enumeration
+===========
+
+Every user of pixel buffers must be able to enumerate a set of supported formats
+and modifiers, described together. Within KMS, this is achieved with the
+``IN_FORMATS`` property on each DRM plane, listing the supported DRM formats, and
+the modifiers supported for each format. In userspace, this is supported through
+the `EGL_EXT_image_dma_buf_import_modifiers`_ extension entrypoints for EGL, the
+`VK_EXT_image_drm_format_modifier`_ extension for Vulkan, and the
+`zwp_linux_dmabuf_v1`_ extension for Wayland.
+
+Each of these interfaces allows users to query a set of supported
+format+modifier combinations.
+
+
+Negotiation
+===========
+
+It is the responsibility of userspace to negotiate an acceptable format+modifier
+combination for its usage. This is performed through a simple intersection of
+lists. For example, if a user wants to use Vulkan to render an image to be
+displayed on a KMS plane, it must:
+
+ - query KMS for the ``IN_FORMATS`` property for the given plane
+ - query Vulkan for the supported formats for its physical device, making sure
+ to pass the ``VkImageUsageFlagBits`` and ``VkImageCreateFlagBits``
+ corresponding to the intended rendering use
+ - intersect these formats to determine the most appropriate one
+ - for this format, intersect the lists of supported modifiers for both KMS and
+ Vulkan, to obtain a final list of acceptable modifiers for that format
+
+This intersection must be performed for all usages. For example, if the user
+also wishes to encode the image to a video stream, it must query the media API
+it intends to use for encoding for the set of modifiers it supports, and
+additionally intersect against this list.
+
+If the intersection of all lists is an empty list, it is not possible to share
+buffers in this way, and an alternate strategy must be considered (e.g. using
+CPU access routines to copy data between the different uses, with the
+corresponding performance cost).
+
+The resulting modifier list is unsorted; the order is not significant.
+
+
+Allocation
+==========
+
+Once userspace has determined an appropriate format, and corresponding list of
+acceptable modifiers, it must allocate the buffer. As there is no universal
+buffer-allocation interface available at either kernel or userspace level, the
+client makes an arbitrary choice of allocation interface such as Vulkan, GBM, or
+a media API.
+
+Each allocation request must take, at a minimum: the pixel format, a list of
+acceptable modifiers, and the buffer's width and height. Each API may extend
+this set of properties in different ways, such as allowing allocation in more
+than two dimensions, intended usage patterns, etc.
+
+The component which allocates the buffer will make an arbitrary choice of what
+it considers the 'best' modifier within the acceptable list for the requested
+allocation, any padding required, and further properties of the underlying
+memory buffers such as whether they are stored in system or device-specific
+memory, whether or not they are physically contiguous, and their cache mode.
+These properties of the memory buffer are not visible to userspace, however the
+``dma-heaps`` API is an effort to address this.
+
+After allocation, the client must query the allocator to determine the actual
+modifier selected for the buffer, as well as the per-plane offset and stride.
+Allocators are not permitted to vary the format in use, to select a modifier not
+provided within the acceptable list, nor to vary the pixel dimensions other than
+the padding expressed through offset, stride, and size.
+
+Communicating additional constraints, such as alignment of stride or offset,
+placement within a particular memory area, etc, is out of scope of dma-buf,
+and is not solved by format and modifier tokens.
+
+
+Import
+======
+
+To use a buffer within a different context, device, or subsystem, the user
+passes these parameters (format, modifier, width, height, and per-plane offset
+and stride) to an importing API.
+
+Each memory buffer is referred to by a buffer handle, which may be unique or
+duplicated within an image. For example, a ``DRM_FORMAT_NV12`` buffer may have
+the luma and chroma buffers combined into a single memory buffer by use of the
+per-plane offset parameters, or they may be completely separate allocations in
+memory. For this reason, each import and allocation API must provide a separate
+handle for each plane.
+
+Each kernel subsystem has its own types and interfaces for buffer management.
+DRM uses GEM buffer objects (BOs), V4L2 has its own references, etc. These types
+are not portable between contexts, processes, devices, or subsystems.
+
+To address this, ``dma-buf`` handles are used as the universal interchange for
+buffers. Subsystem-specific operations are used to export native buffer handles
+to a ``dma-buf`` file descriptor, and to import those file descriptors into a
+native buffer handle. dma-buf file descriptors can be transferred between
+contexts, processes, devices, and subsystems.
+
+For example, a Wayland media player may use V4L2 to decode a video frame into a
+``DRM_FORMAT_NV12`` buffer. This will result in two memory planes (luma and
+chroma) being dequeued by the user from V4L2. These planes are then exported to
+one dma-buf file descriptor per plane, these descriptors are then sent along
+with the metadata (format, modifier, width, height, per-plane offset and stride)
+to the Wayland server. The Wayland server will then import these file
+descriptors as an EGLImage for use through EGL/OpenGL (ES), a VkImage for use
+through Vulkan, or a KMS framebuffer object; each of these import operations
+will take the same metadata and convert the dma-buf file descriptors into their
+native buffer handles.
+
+Having a non-empty intersection of supported modifiers does not guarantee that
+import will succeed into all consumers; they may have constraints beyond those
+implied by modifiers which must be satisfied.
+
+
+Implicit modifiers
+==================
+
+The concept of modifiers post-dates all of the subsystems mentioned above. As
+such, it has been retrofitted into all of these APIs, and in order to ensure
+backwards compatibility, support is needed for drivers and userspace which do
+not (yet) support modifiers.
+
+As an example, GBM is used to allocate buffers to be shared between EGL for
+rendering and KMS for display. It has two entrypoints for allocating buffers:
+``gbm_bo_create`` which only takes the format, width, height, and a usage token,
+and ``gbm_bo_create_with_modifiers`` which extends this with a list of modifiers.
+
+In the latter case, the allocation is as discussed above, being provided with a
+list of acceptable modifiers that the implementation can choose from (or fail if
+it is not possible to allocate within those constraints). In the former case
+where modifiers are not provided, the GBM implementation must make its own
+choice as to what is likely to be the 'best' layout. Such a choice is entirely
+implementation-specific: some will internally use tiled layouts which are not
+CPU-accessible if the implementation decides that is a good idea through
+whatever heuristic. It is the implementation's responsibility to ensure that
+this choice is appropriate.
+
+To support this case where the layout is not known because there is no awareness
+of modifiers, a special ``DRM_FORMAT_MOD_INVALID`` token has been defined. This
+pseudo-modifier declares that the layout is not known, and that the driver
+should use its own logic to determine what the underlying layout may be.
+
+.. note::
+
+ ``DRM_FORMAT_MOD_INVALID`` is a non-zero value. The modifier value zero is
+ ``DRM_FORMAT_MOD_LINEAR``, which is an explicit guarantee that the image
+ has the linear layout. Care and attention should be taken to ensure that
+ zero as a default value is not mixed up with either no modifier or the linear
+ modifier. Also note that in some APIs the invalid modifier value is specified
+ with an out-of-band flag, like in ``DRM_IOCTL_MODE_ADDFB2``.
+
+There are four cases where this token may be used:
+ - during enumeration, an interface may return ``DRM_FORMAT_MOD_INVALID``, either
+ as the sole member of a modifier list to declare that explicit modifiers are
+ not supported, or as part of a larger list to declare that implicit modifiers
+ may be used
+ - during allocation, a user may supply ``DRM_FORMAT_MOD_INVALID``, either as the
+ sole member of a modifier list (equivalent to not supplying a modifier list
+ at all) to declare that explicit modifiers are not supported and must not be
+ used, or as part of a larger list to declare that an allocation using implicit
+ modifiers is acceptable
+ - in a post-allocation query, an implementation may return
+ ``DRM_FORMAT_MOD_INVALID`` as the modifier of the allocated buffer to declare
+ that the underlying layout is implementation-defined and that an explicit
+ modifier description is not available; per the above rules, this may only be
+ returned when the user has included ``DRM_FORMAT_MOD_INVALID`` as part of the
+ list of acceptable modifiers, or not provided a list
+ - when importing a buffer, the user may supply ``DRM_FORMAT_MOD_INVALID`` as the
+ buffer modifier (or not supply a modifier) to indicate that the modifier is
+ unknown for whatever reason; this is only acceptable when the buffer has
+ not been allocated with an explicit modifier
+
+It follows from this that for any single buffer, the complete chain of operations
+formed by the producer and all the consumers must be either fully implicit or fully
+explicit. For example, if a user wishes to allocate a buffer for use between
+GPU, display, and media, but the media API does not support modifiers, then the
+user **must not** allocate the buffer with explicit modifiers and attempt to
+import the buffer into the media API with no modifier, but either perform the
+allocation using implicit modifiers, or allocate the buffer for media use
+separately and copy between the two buffers.
+
+As one exception to the above, allocations may be 'upgraded' from implicit
+to explicit modifiers. For example, if the buffer is allocated with
+``gbm_bo_create`` (taking no modifiers), the user may then query the modifier with
+``gbm_bo_get_modifier`` and then use this modifier as an explicit modifier token
+if a valid modifier is returned.
+
+When allocating buffers for exchange between different users and modifiers are
+not available, implementations are strongly encouraged to use
+``DRM_FORMAT_MOD_LINEAR`` for their allocation, as this is the universal baseline
+for exchange. However, it is not guaranteed that this will result in the correct
+interpretation of buffer content, as implicit modifier operation may still be
+subject to driver-specific heuristics.
+
+Any new users - userspace programs and protocols, kernel subsystems, etc -
+wishing to exchange buffers must offer interoperability through dma-buf file
+descriptors for memory planes, DRM format tokens to describe the format, DRM
+format modifiers to describe the layout in memory, at least width and height for
+dimensions, and at least offset and stride for each memory plane.
+
+.. _zwp_linux_dmabuf_v1: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml
+.. _VK_EXT_image_drm_format_modifier: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_image_drm_format_modifier.html
+.. _EGL_EXT_image_dma_buf_import_modifiers: https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import_modifiers.txt
diff --git a/Documentation/userspace-api/index.rst b/Documentation/userspace-api/index.rst
index 72a65db0c498..031df47a7c19 100644
--- a/Documentation/userspace-api/index.rst
+++ b/Documentation/userspace-api/index.rst
@@ -22,6 +22,7 @@ place where this information is gathered.
unshare
spec_ctrl
accelerators/ocxl
+ dma-buf-alloc-exchange
ebpf/index
ELF
ioctl/index
diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst
index d8cd8cd9ce25..2e3822677061 100644
--- a/Documentation/userspace-api/landlock.rst
+++ b/Documentation/userspace-api/landlock.rst
@@ -8,13 +8,13 @@ Landlock: unprivileged access control
=====================================
:Author: Mickaël Salaün
-:Date: October 2022
+:Date: October 2023
The goal of Landlock is to enable to restrict ambient rights (e.g. global
-filesystem access) for a set of processes. Because Landlock is a stackable
-LSM, it makes possible to create safe security sandboxes as new security layers
-in addition to the existing system-wide access-controls. This kind of sandbox
-is expected to help mitigate the security impact of bugs or
+filesystem or network access) for a set of processes. Because Landlock
+is a stackable LSM, it makes possible to create safe security sandboxes as new
+security layers in addition to the existing system-wide access-controls. This
+kind of sandbox is expected to help mitigate the security impact of bugs or
unexpected/malicious behaviors in user space applications. Landlock empowers
any process, including unprivileged ones, to securely restrict themselves.
@@ -28,20 +28,34 @@ appropriately <kernel_support>`.
Landlock rules
==============
-A Landlock rule describes an action on an object. An object is currently a
-file hierarchy, and the related filesystem actions are defined with `access
-rights`_. A set of rules is aggregated in a ruleset, which can then restrict
+A Landlock rule describes an action on an object which the process intends to
+perform. A set of rules is aggregated in a ruleset, which can then restrict
the thread enforcing it, and its future children.
+The two existing types of rules are:
+
+Filesystem rules
+ For these rules, the object is a file hierarchy,
+ and the related filesystem actions are defined with
+ `filesystem access rights`.
+
+Network rules (since ABI v4)
+ For these rules, the object is a TCP port,
+ and the related actions are defined with `network access rights`.
+
Defining and enforcing a security policy
----------------------------------------
-We first need to define the ruleset that will contain our rules. For this
-example, the ruleset will contain rules that only allow read actions, but write
-actions will be denied. The ruleset then needs to handle both of these kind of
-actions. This is required for backward and forward compatibility (i.e. the
-kernel and user space may not know each other's supported restrictions), hence
-the need to be explicit about the denied-by-default access rights.
+We first need to define the ruleset that will contain our rules.
+
+For this example, the ruleset will contain rules that only allow filesystem
+read actions and establish a specific TCP connection. Filesystem write
+actions and other TCP actions will be denied.
+
+The ruleset then needs to handle both these kinds of actions. This is
+required for backward and forward compatibility (i.e. the kernel and user
+space may not know each other's supported restrictions), hence the need
+to be explicit about the denied-by-default access rights.
.. code-block:: c
@@ -62,6 +76,9 @@ the need to be explicit about the denied-by-default access rights.
LANDLOCK_ACCESS_FS_MAKE_SYM |
LANDLOCK_ACCESS_FS_REFER |
LANDLOCK_ACCESS_FS_TRUNCATE,
+ .handled_access_net =
+ LANDLOCK_ACCESS_NET_BIND_TCP |
+ LANDLOCK_ACCESS_NET_CONNECT_TCP,
};
Because we may not know on which kernel version an application will be
@@ -70,9 +87,7 @@ should try to protect users as much as possible whatever the kernel they are
using. To avoid binary enforcement (i.e. either all security features or
none), we can leverage a dedicated Landlock command to get the current version
of the Landlock ABI and adapt the handled accesses. Let's check if we should
-remove the ``LANDLOCK_ACCESS_FS_REFER`` or ``LANDLOCK_ACCESS_FS_TRUNCATE``
-access rights, which are only supported starting with the second and third
-version of the ABI.
+remove access rights which are only supported in higher versions of the ABI.
.. code-block:: c
@@ -92,6 +107,12 @@ version of the ABI.
case 2:
/* Removes LANDLOCK_ACCESS_FS_TRUNCATE for ABI < 3 */
ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_TRUNCATE;
+ __attribute__((fallthrough));
+ case 3:
+ /* Removes network support for ABI < 4 */
+ ruleset_attr.handled_access_net &=
+ ~(LANDLOCK_ACCESS_NET_BIND_TCP |
+ LANDLOCK_ACCESS_NET_CONNECT_TCP);
}
This enables to create an inclusive ruleset that will contain our rules.
@@ -143,10 +164,23 @@ for the ruleset creation, by filtering access rights according to the Landlock
ABI version. In this example, this is not required because all of the requested
``allowed_access`` rights are already available in ABI 1.
-We now have a ruleset with one rule allowing read access to ``/usr`` while
-denying all other handled accesses for the filesystem. The next step is to
-restrict the current thread from gaining more privileges (e.g. thanks to a SUID
-binary).
+For network access-control, we can add a set of rules that allow to use a port
+number for a specific action: HTTPS connections.
+
+.. code-block:: c
+
+ struct landlock_net_port_attr net_port = {
+ .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP,
+ .port = 443,
+ };
+
+ err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
+ &net_port, 0);
+
+The next step is to restrict the current thread from gaining more privileges
+(e.g. through a SUID binary). We now have a ruleset with the first rule
+allowing read access to ``/usr`` while denying all other handled accesses for
+the filesystem, and a second rule allowing HTTPS connections.
.. code-block:: c
@@ -355,7 +389,7 @@ Access rights
-------------
.. kernel-doc:: include/uapi/linux/landlock.h
- :identifiers: fs_access
+ :identifiers: fs_access net_access
Creating a new ruleset
----------------------
@@ -374,6 +408,7 @@ Extending a ruleset
.. kernel-doc:: include/uapi/linux/landlock.h
:identifiers: landlock_rule_type landlock_path_beneath_attr
+ landlock_net_port_attr
Enforcing a ruleset
-------------------
@@ -387,9 +422,9 @@ Current limitations
Filesystem topology modification
--------------------------------
-As for file renaming and linking, a sandboxed thread cannot modify its
-filesystem topology, whether via :manpage:`mount(2)` or
-:manpage:`pivot_root(2)`. However, :manpage:`chroot(2)` calls are not denied.
+Threads sandboxed with filesystem restrictions cannot modify filesystem
+topology, whether via :manpage:`mount(2)` or :manpage:`pivot_root(2)`.
+However, :manpage:`chroot(2)` calls are not denied.
Special filesystems
-------------------
@@ -451,6 +486,14 @@ always allowed when using a kernel that only supports the first or second ABI.
Starting with the Landlock ABI version 3, it is now possible to securely control
truncation thanks to the new ``LANDLOCK_ACCESS_FS_TRUNCATE`` access right.
+Network support (ABI < 4)
+-------------------------
+
+Starting with the Landlock ABI version 4, it is now possible to restrict TCP
+bind and connect actions to only a set of allowed ports thanks to the new
+``LANDLOCK_ACCESS_NET_BIND_TCP`` and ``LANDLOCK_ACCESS_NET_CONNECT_TCP``
+access rights.
+
.. _kernel_support:
Kernel support
@@ -469,6 +512,12 @@ still enable it by adding ``lsm=landlock,[...]`` to
Documentation/admin-guide/kernel-parameters.rst thanks to the bootloader
configuration.
+To be able to explicitly allow TCP operations (e.g., adding a network rule with
+``LANDLOCK_ACCESS_NET_BIND_TCP``), the kernel must support TCP
+(``CONFIG_INET=y``). Otherwise, sys_landlock_add_rule() returns an
+``EAFNOSUPPORT`` error, which can safely be ignored because this kind of TCP
+operation is already not possible.
+
Questions and answers
=====================
diff --git a/Documentation/userspace-api/media/drivers/camera-sensor.rst b/Documentation/userspace-api/media/drivers/camera-sensor.rst
new file mode 100644
index 000000000000..919a50e8b9d9
--- /dev/null
+++ b/Documentation/userspace-api/media/drivers/camera-sensor.rst
@@ -0,0 +1,104 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _media_using_camera_sensor_drivers:
+
+Using camera sensor drivers
+===========================
+
+This section describes common practices for how the V4L2 sub-device interface is
+used to control the camera sensor drivers.
+
+You may also find :ref:`media_writing_camera_sensor_drivers` useful.
+
+Frame size
+----------
+
+There are two distinct ways to configure the frame size produced by camera
+sensors.
+
+Freely configurable camera sensor drivers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Freely configurable camera sensor drivers expose the device's internal
+processing pipeline as one or more sub-devices with different cropping and
+scaling configurations. The output size of the device is the result of a series
+of cropping and scaling operations from the device's pixel array's size.
+
+An example of such a driver is the CCS driver.
+
+Register list based drivers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Register list based drivers generally, instead of able to configure the device
+they control based on user requests, are limited to a number of preset
+configurations that combine a number of different parameters that on hardware
+level are independent. How a driver picks such configuration is based on the
+format set on a source pad at the end of the device's internal pipeline.
+
+Most sensor drivers are implemented this way.
+
+Frame interval configuration
+----------------------------
+
+There are two different methods for obtaining possibilities for different frame
+intervals as well as configuring the frame interval. Which one to implement
+depends on the type of the device.
+
+Raw camera sensors
+~~~~~~~~~~~~~~~~~~
+
+Instead of a high level parameter such as frame interval, the frame interval is
+a result of the configuration of a number of camera sensor implementation
+specific parameters. Luckily, these parameters tend to be the same for more or
+less all modern raw camera sensors.
+
+The frame interval is calculated using the following equation::
+
+ frame interval = (analogue crop width + horizontal blanking) *
+ (analogue crop height + vertical blanking) / pixel rate
+
+The formula is bus independent and is applicable for raw timing parameters on
+large variety of devices beyond camera sensors. Devices that have no analogue
+crop, use the full source image size, i.e. pixel array size.
+
+Horizontal and vertical blanking are specified by ``V4L2_CID_HBLANK`` and
+``V4L2_CID_VBLANK``, respectively. The unit of the ``V4L2_CID_HBLANK`` control
+is pixels and the unit of the ``V4L2_CID_VBLANK`` is lines. The pixel rate in
+the sensor's **pixel array** is specified by ``V4L2_CID_PIXEL_RATE`` in the same
+sub-device. The unit of that control is pixels per second.
+
+Register list based drivers need to implement read-only sub-device nodes for the
+purpose. Devices that are not register list based need these to configure the
+device's internal processing pipeline.
+
+The first entity in the linear pipeline is the pixel array. The pixel array may
+be followed by other entities that are there to allow configuring binning,
+skipping, scaling or digital crop, see :ref:`VIDIOC_SUBDEV_G_SELECTION
+<VIDIOC_SUBDEV_G_SELECTION>`.
+
+USB cameras etc. devices
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+USB video class hardware, as well as many cameras offering a similar higher
+level interface natively, generally use the concept of frame interval (or frame
+rate) on device level in firmware or hardware. This means lower level controls
+implemented by raw cameras may not be used on uAPI (or even kAPI) to control the
+frame interval on these devices.
+
+Rotation, orientation and flipping
+----------------------------------
+
+Some systems have the camera sensor mounted upside down compared to its natural
+mounting rotation. In such cases, drivers shall expose the information to
+userspace with the :ref:`V4L2_CID_CAMERA_SENSOR_ROTATION
+<v4l2-camera-sensor-rotation>` control.
+
+Sensor drivers shall also report the sensor's mounting orientation with the
+:ref:`V4L2_CID_CAMERA_SENSOR_ORIENTATION <v4l2-camera-sensor-orientation>`.
+
+Sensor drivers that have any vertical or horizontal flips embedded in the
+register programming sequences shall initialize the :ref:`V4L2_CID_HFLIP
+<v4l2-cid-hflip>` and :ref:`V4L2_CID_VFLIP <v4l2-cid-vflip>` controls with the
+values programmed by the register sequences. The default values of these
+controls shall be 0 (disabled). Especially these controls shall not be inverted,
+independently of the sensor's mounting rotation.
diff --git a/Documentation/userspace-api/media/drivers/index.rst b/Documentation/userspace-api/media/drivers/index.rst
index 6708d649afd7..1726f8ec86fa 100644
--- a/Documentation/userspace-api/media/drivers/index.rst
+++ b/Documentation/userspace-api/media/drivers/index.rst
@@ -32,11 +32,13 @@ For more details see the file COPYING in the source distribution of Linux.
:numbered:
aspeed-video
+ camera-sensor
ccs
cx2341x-uapi
dw100
imx-uapi
max2175
+ npcm-video
omap3isp-uapi
st-vgxy61
uvcvideo
diff --git a/Documentation/userspace-api/media/drivers/npcm-video.rst b/Documentation/userspace-api/media/drivers/npcm-video.rst
new file mode 100644
index 000000000000..b47771dd8b27
--- /dev/null
+++ b/Documentation/userspace-api/media/drivers/npcm-video.rst
@@ -0,0 +1,66 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: <isonum.txt>
+
+NPCM video driver
+=================
+
+This driver is used to control the Video Capture/Differentiation (VCD) engine
+and Encoding Compression Engine (ECE) present on Nuvoton NPCM SoCs. The VCD can
+capture a frame from digital video input and compare two frames in memory, and
+the ECE can compress the frame data into HEXTILE format.
+
+Driver-specific Controls
+------------------------
+
+V4L2_CID_NPCM_CAPTURE_MODE
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The VCD engine supports two modes:
+
+- COMPLETE mode:
+
+ Capture the next complete frame into memory.
+
+- DIFF mode:
+
+ Compare the incoming frame with the frame stored in memory, and updates the
+ differentiated frame in memory.
+
+Application can use ``V4L2_CID_NPCM_CAPTURE_MODE`` control to set the VCD mode
+with different control values (enum v4l2_npcm_capture_mode):
+
+- ``V4L2_NPCM_CAPTURE_MODE_COMPLETE``: will set VCD to COMPLETE mode.
+- ``V4L2_NPCM_CAPTURE_MODE_DIFF``: will set VCD to DIFF mode.
+
+V4L2_CID_NPCM_RECT_COUNT
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+If using V4L2_PIX_FMT_HEXTILE format, VCD will capture frame data and then ECE
+will compress the data into HEXTILE rectangles and store them in V4L2 video
+buffer with the layout defined in Remote Framebuffer Protocol:
+::
+
+ (RFC 6143, https://www.rfc-editor.org/rfc/rfc6143.html#section-7.6.1)
+
+ +--------------+--------------+-------------------+
+ | No. of bytes | Type [Value] | Description |
+ +--------------+--------------+-------------------+
+ | 2 | U16 | x-position |
+ | 2 | U16 | y-position |
+ | 2 | U16 | width |
+ | 2 | U16 | height |
+ | 4 | S32 | encoding-type (5) |
+ +--------------+--------------+-------------------+
+ | HEXTILE rectangle data |
+ +-------------------------------------------------+
+
+Application can get the video buffer through VIDIOC_DQBUF, and followed by
+calling ``V4L2_CID_NPCM_RECT_COUNT`` control to get the number of HEXTILE
+rectangles in this buffer.
+
+References
+----------
+include/uapi/linux/npcm-video.h
+
+**Copyright** |copy| 2022 Nuvoton Technologies
diff --git a/Documentation/userspace-api/media/gen-errors.rst b/Documentation/userspace-api/media/gen-errors.rst
index e595d0bea109..4e8defd3612b 100644
--- a/Documentation/userspace-api/media/gen-errors.rst
+++ b/Documentation/userspace-api/media/gen-errors.rst
@@ -59,9 +59,7 @@ Generic Error Codes
- - ``ENOTTY``
- - The ioctl is not supported by the driver, actually meaning that
- the required functionality is not available, or the file
- descriptor is not for a media device.
+ - The ioctl is not supported by the file descriptor.
- - ``ENOSPC``
diff --git a/Documentation/userspace-api/media/v4l/buffer.rst b/Documentation/userspace-api/media/v4l/buffer.rst
index 04dec3e570ed..52bbee81c080 100644
--- a/Documentation/userspace-api/media/v4l/buffer.rst
+++ b/Documentation/userspace-api/media/v4l/buffer.rst
@@ -549,9 +549,9 @@ Buffer Flags
- 0x00000400
- The buffer has been prepared for I/O and can be queued by the
application. Drivers set or clear this flag when the
- :ref:`VIDIOC_QUERYBUF`,
+ :ref:`VIDIOC_QUERYBUF <VIDIOC_QUERYBUF>`,
:ref:`VIDIOC_PREPARE_BUF <VIDIOC_QBUF>`,
- :ref:`VIDIOC_QBUF` or
+ :ref:`VIDIOC_QBUF <VIDIOC_QBUF>` or
:ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl is called.
* .. _`V4L2-BUF-FLAG-NO-CACHE-INVALIDATE`:
diff --git a/Documentation/userspace-api/media/v4l/control.rst b/Documentation/userspace-api/media/v4l/control.rst
index 4463fce694b0..57893814a1e5 100644
--- a/Documentation/userspace-api/media/v4l/control.rst
+++ b/Documentation/userspace-api/media/v4l/control.rst
@@ -143,9 +143,13 @@ Control IDs
recognise the difference between digital and analogue gain use
controls ``V4L2_CID_DIGITAL_GAIN`` and ``V4L2_CID_ANALOGUE_GAIN``.
+.. _v4l2-cid-hflip:
+
``V4L2_CID_HFLIP`` ``(boolean)``
Mirror the picture horizontally.
+.. _v4l2-cid-vflip:
+
``V4L2_CID_VFLIP`` ``(boolean)``
Mirror the picture vertically.
diff --git a/Documentation/userspace-api/media/v4l/dev-subdev.rst b/Documentation/userspace-api/media/v4l/dev-subdev.rst
index a4f1df7093e8..43988516acdd 100644
--- a/Documentation/userspace-api/media/v4l/dev-subdev.rst
+++ b/Documentation/userspace-api/media/v4l/dev-subdev.rst
@@ -579,20 +579,19 @@ is started.
There are three steps in configuring the streams:
-1) Set up links. Connect the pads between sub-devices using the :ref:`Media
-Controller API <media_controller>`
+1. Set up links. Connect the pads between sub-devices using the
+ :ref:`Media Controller API <media_controller>`
-2) Streams. Streams are declared and their routing is configured by
-setting the routing table for the sub-device using
-:ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl. Note that
-setting the routing table will reset formats and selections in the
-sub-device to default values.
+2. Streams. Streams are declared and their routing is configured by setting the
+ routing table for the sub-device using :ref:`VIDIOC_SUBDEV_S_ROUTING
+ <VIDIOC_SUBDEV_G_ROUTING>` ioctl. Note that setting the routing table will
+ reset formats and selections in the sub-device to default values.
-3) Configure formats and selections. Formats and selections of each stream
-are configured separately as documented for plain sub-devices in
-:ref:`format-propagation`. The stream ID is set to the same stream ID
-associated with either sink or source pads of routes configured using the
-:ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl.
+3. Configure formats and selections. Formats and selections of each stream are
+ configured separately as documented for plain sub-devices in
+ :ref:`format-propagation`. The stream ID is set to the same stream ID
+ associated with either sink or source pads of routes configured using the
+ :ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl.
Multiplexed streams setup example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -618,11 +617,11 @@ modeled as V4L2 devices, exposed to userspace via /dev/videoX nodes.
To configure this pipeline, the userspace must take the following steps:
-1) Set up media links between entities: connect the sensors to the bridge,
-bridge to the receiver, and the receiver to the DMA engines. This step does
-not differ from normal non-multiplexed media controller setup.
+1. Set up media links between entities: connect the sensors to the bridge,
+ bridge to the receiver, and the receiver to the DMA engines. This step does
+ not differ from normal non-multiplexed media controller setup.
-2) Configure routing
+2. Configure routing
.. flat-table:: Bridge routing table
:header-rows: 1
@@ -656,14 +655,14 @@ not differ from normal non-multiplexed media controller setup.
- V4L2_SUBDEV_ROUTE_FL_ACTIVE
- Pixel data stream from Sensor B
-3) Configure formats and selections
+3. Configure formats and selections
-After configuring routing, the next step is configuring the formats and
-selections for the streams. This is similar to performing this step without
-streams, with just one exception: the ``stream`` field needs to be assigned
-to the value of the stream ID.
+ After configuring routing, the next step is configuring the formats and
+ selections for the streams. This is similar to performing this step without
+ streams, with just one exception: the ``stream`` field needs to be assigned
+ to the value of the stream ID.
-A common way to accomplish this is to start from the sensors and propagate the
-configurations along the stream towards the receiver,
-using :ref:`VIDIOC_SUBDEV_S_FMT <VIDIOC_SUBDEV_G_FMT>` ioctls to configure each
-stream endpoint in each sub-device.
+ A common way to accomplish this is to start from the sensors and propagate
+ the configurations along the stream towards the receiver, using
+ :ref:`VIDIOC_SUBDEV_S_FMT <VIDIOC_SUBDEV_G_FMT>` ioctls to configure each
+ stream endpoint in each sub-device.
diff --git a/Documentation/userspace-api/media/v4l/dv-timings.rst b/Documentation/userspace-api/media/v4l/dv-timings.rst
index e17f056b129f..4b19bcb4bd80 100644
--- a/Documentation/userspace-api/media/v4l/dv-timings.rst
+++ b/Documentation/userspace-api/media/v4l/dv-timings.rst
@@ -33,6 +33,27 @@ current DV timings they use the
the DV timings as seen by the video receiver applications use the
:ref:`VIDIOC_QUERY_DV_TIMINGS` ioctl.
+When the hardware detects a video source change (e.g. the video
+signal appears or disappears, or the video resolution changes), then
+it will issue a `V4L2_EVENT_SOURCE_CHANGE` event. Use the
+:ref:`ioctl VIDIOC_SUBSCRIBE_EVENT <VIDIOC_SUBSCRIBE_EVENT>` and the
+:ref:`VIDIOC_DQEVENT` to check if this event was reported.
+
+If the video signal changed, then the application has to stop
+streaming, free all buffers, and call the :ref:`VIDIOC_QUERY_DV_TIMINGS`
+to obtain the new video timings, and if they are valid, it can set
+those by calling the :ref:`ioctl VIDIOC_S_DV_TIMINGS <VIDIOC_G_DV_TIMINGS>`.
+This will also update the format, so use the :ref:`ioctl VIDIOC_G_FMT <VIDIOC_G_FMT>`
+to obtain the new format. Now the application can allocate new buffers
+and start streaming again.
+
+The :ref:`VIDIOC_QUERY_DV_TIMINGS` will just report what the
+hardware detects, it will never change the configuration. If the
+currently set timings and the actually detected timings differ, then
+typically this will mean that you will not be able to capture any
+video. The correct approach is to rely on the `V4L2_EVENT_SOURCE_CHANGE`
+event so you know when something changed.
+
Applications can make use of the :ref:`input-capabilities` and
:ref:`output-capabilities` flags to determine whether the digital
video ioctls can be used with the given input or output.
diff --git a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
index 296ad2025e8d..886ba7b08d6b 100644
--- a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
+++ b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
@@ -288,6 +288,13 @@ please make a proposal on the linux-media mailing list.
- 'MT2110R'
- This format is two-planar 10-Bit raster mode and having similitude with
``V4L2_PIX_FMT_MM21`` in term of alignment and tiling. Used for AVC.
+ * .. _V4L2-PIX-FMT-HEXTILE:
+
+ - ``V4L2_PIX_FMT_HEXTILE``
+ - 'HXTL'
+ - Compressed format used by Nuvoton NPCM video driver. This format is
+ defined in Remote Framebuffer Protocol (RFC 6143, chapter 7.7.4 Hextile
+ Encoding).
.. raw:: latex
\normalsize
diff --git a/Documentation/userspace-api/media/v4l/pixfmt-srggb12p.rst b/Documentation/userspace-api/media/v4l/pixfmt-srggb12p.rst
index b6e79e2f8ce4..7c3810ff783c 100644
--- a/Documentation/userspace-api/media/v4l/pixfmt-srggb12p.rst
+++ b/Documentation/userspace-api/media/v4l/pixfmt-srggb12p.rst
@@ -60,7 +60,7 @@ Each cell is one byte.
G\ :sub:`10low`\ (bits 3--0)
- G\ :sub:`12high`
- R\ :sub:`13high`
- - R\ :sub:`13low`\ (bits 3--2)
+ - R\ :sub:`13low`\ (bits 7--4)
G\ :sub:`12low`\ (bits 3--0)
- - start + 12:
@@ -82,6 +82,6 @@ Each cell is one byte.
G\ :sub:`30low`\ (bits 3--0)
- G\ :sub:`32high`
- R\ :sub:`33high`
- - R\ :sub:`33low`\ (bits 3--2)
+ - R\ :sub:`33low`\ (bits 7--4)
G\ :sub:`32low`\ (bits 3--0)
diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst
index a3a35eeed708..eb3cd20b0cf2 100644
--- a/Documentation/userspace-api/media/v4l/subdev-formats.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst
@@ -949,6 +949,78 @@ The following tables list existing packed RGB formats.
- b\ :sub:`2`
- b\ :sub:`1`
- b\ :sub:`0`
+ * .. _MEDIA-BUS-FMT-RGB666-2X9-BE:
+
+ - MEDIA_BUS_FMT_RGB666_2X9_BE
+ - 0x1025
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ - r\ :sub:`5`
+ - r\ :sub:`4`
+ - r\ :sub:`3`
+ - r\ :sub:`2`
+ - r\ :sub:`1`
+ - r\ :sub:`0`
+ - g\ :sub:`5`
+ - g\ :sub:`4`
+ - g\ :sub:`3`
+ * -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ - g\ :sub:`2`
+ - g\ :sub:`1`
+ - g\ :sub:`0`
+ - b\ :sub:`5`
+ - b\ :sub:`4`
+ - b\ :sub:`3`
+ - b\ :sub:`2`
+ - b\ :sub:`1`
+ - b\ :sub:`0`
* .. _MEDIA-BUS-FMT-BGR666-1X18:
- MEDIA_BUS_FMT_BGR666_1X18
diff --git a/Documentation/userspace-api/netlink/genetlink-legacy.rst b/Documentation/userspace-api/netlink/genetlink-legacy.rst
index 40b82ad5d54a..70a77387f6c4 100644
--- a/Documentation/userspace-api/netlink/genetlink-legacy.rst
+++ b/Documentation/userspace-api/netlink/genetlink-legacy.rst
@@ -11,6 +11,20 @@ the ``genetlink-legacy`` protocol level.
Specification
=============
+Globals
+-------
+
+Attributes listed directly at the root level of the spec file.
+
+version
+~~~~~~~
+
+Generic Netlink family version, default is 1.
+
+``version`` has historically been used to introduce family changes
+which may break backwards compatibility. Since compatibility breaking changes
+are generally not allowed ``version`` is very rarely used.
+
Attribute type nests
--------------------
@@ -168,7 +182,7 @@ members
- ``name`` - The attribute name of the struct member
- ``type`` - One of the scalar types ``u8``, ``u16``, ``u32``, ``u64``, ``s8``,
- ``s16``, ``s32``, ``s64``, ``string`` or ``binary``.
+ ``s16``, ``s32``, ``s64``, ``string``, ``binary`` or ``bitfield32``.
- ``byte-order`` - ``big-endian`` or ``little-endian``
- ``doc``, ``enum``, ``enum-as-flags``, ``display-hint`` - Same as for
:ref:`attribute definitions <attribute_properties>`
diff --git a/Documentation/userspace-api/netlink/specs.rst b/Documentation/userspace-api/netlink/specs.rst
index cc4e2430997e..c1b951649113 100644
--- a/Documentation/userspace-api/netlink/specs.rst
+++ b/Documentation/userspace-api/netlink/specs.rst
@@ -86,11 +86,6 @@ name
Name of the family. Name identifies the family in a unique way, since
the Family IDs are allocated dynamically.
-version
-~~~~~~~
-
-Generic Netlink family version, default is 1.
-
protocol
~~~~~~~~
@@ -408,10 +403,21 @@ This section describes the attribute types supported by the ``genetlink``
compatibility level. Refer to documentation of different levels for additional
attribute types.
-Scalar integer types
+Common integer types
--------------------
-Fixed-width integer types:
+``sint`` and ``uint`` represent signed and unsigned 64 bit integers.
+If the value can fit on 32 bits only 32 bits are carried in netlink
+messages, otherwise full 64 bits are carried. Note that the payload
+is only aligned to 4B, so the full 64 bit value may be unaligned!
+
+Common integer types should be preferred over fix-width types in majority
+of cases.
+
+Fix-width integer types
+-----------------------
+
+Fixed-width integer types include:
``u8``, ``u16``, ``u32``, ``u64``, ``s8``, ``s16``, ``s32``, ``s64``.
Note that types smaller than 32 bit should be avoided as using them
@@ -421,6 +427,9 @@ See :ref:`pad_type` for padding of 64 bit attributes.
The payload of the attribute is the integer in host order unless ``byte-order``
specifies otherwise.
+64 bit values are usually aligned by the kernel but it is recommended
+that the user space is able to deal with unaligned values.
+
.. _pad_type:
pad
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 21a7578142a1..7025b3751027 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -416,6 +416,13 @@ Reads the general purpose registers from the vcpu.
__u64 pc;
};
+ /* LoongArch */
+ struct kvm_regs {
+ /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+ unsigned long gpr[32];
+ unsigned long pc;
+ };
+
4.12 KVM_SET_REGS
-----------------
@@ -506,7 +513,7 @@ translation mode.
------------------
:Capability: basic
-:Architectures: x86, ppc, mips, riscv
+:Architectures: x86, ppc, mips, riscv, loongarch
:Type: vcpu ioctl
:Parameters: struct kvm_interrupt (in)
:Returns: 0 on success, negative on failure.
@@ -540,7 +547,7 @@ ioctl is useful if the in-kernel PIC is not used.
PPC:
^^^^
-Queues an external interrupt to be injected. This ioctl is overleaded
+Queues an external interrupt to be injected. This ioctl is overloaded
with 3 different irq values:
a) KVM_INTERRUPT_SET
@@ -592,6 +599,14 @@ b) KVM_INTERRUPT_UNSET
This is an asynchronous vcpu ioctl and can be invoked from any thread.
+LOONGARCH:
+^^^^^^^^^^
+
+Queues an external interrupt to be injected into the virtual CPU. A negative
+interrupt number dequeues the interrupt.
+
+This is an asynchronous vcpu ioctl and can be invoked from any thread.
+
4.17 KVM_DEBUG_GUEST
--------------------
@@ -737,7 +752,7 @@ signal mask.
----------------
:Capability: basic
-:Architectures: x86
+:Architectures: x86, loongarch
:Type: vcpu ioctl
:Parameters: struct kvm_fpu (out)
:Returns: 0 on success, -1 on error
@@ -746,7 +761,7 @@ Reads the floating point state from the vcpu.
::
- /* for KVM_GET_FPU and KVM_SET_FPU */
+ /* x86: for KVM_GET_FPU and KVM_SET_FPU */
struct kvm_fpu {
__u8 fpr[8][16];
__u16 fcw;
@@ -761,12 +776,21 @@ Reads the floating point state from the vcpu.
__u32 pad2;
};
+ /* LoongArch: for KVM_GET_FPU and KVM_SET_FPU */
+ struct kvm_fpu {
+ __u32 fcsr;
+ __u64 fcc;
+ struct kvm_fpureg {
+ __u64 val64[4];
+ }fpr[32];
+ };
+
4.23 KVM_SET_FPU
----------------
:Capability: basic
-:Architectures: x86
+:Architectures: x86, loongarch
:Type: vcpu ioctl
:Parameters: struct kvm_fpu (in)
:Returns: 0 on success, -1 on error
@@ -775,7 +799,7 @@ Writes the floating point state to the vcpu.
::
- /* for KVM_GET_FPU and KVM_SET_FPU */
+ /* x86: for KVM_GET_FPU and KVM_SET_FPU */
struct kvm_fpu {
__u8 fpr[8][16];
__u16 fcw;
@@ -790,6 +814,15 @@ Writes the floating point state to the vcpu.
__u32 pad2;
};
+ /* LoongArch: for KVM_GET_FPU and KVM_SET_FPU */
+ struct kvm_fpu {
+ __u32 fcsr;
+ __u64 fcc;
+ struct kvm_fpureg {
+ __u64 val64[4];
+ }fpr[32];
+ };
+
4.24 KVM_CREATE_IRQCHIP
-----------------------
@@ -965,7 +998,7 @@ be set in the flags field of this ioctl:
The KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL flag requests KVM to generate
the contents of the hypercall page automatically; hypercalls will be
intercepted and passed to userspace through KVM_EXIT_XEN. In this
-ase, all of the blob size and address fields must be zero.
+case, all of the blob size and address fields must be zero.
The KVM_XEN_HVM_CONFIG_EVTCHN_SEND flag indicates to KVM that userspace
will always use the KVM_XEN_HVM_EVTCHN_SEND ioctl to deliver event
@@ -1070,7 +1103,7 @@ Other flags returned by ``KVM_GET_CLOCK`` are accepted but ignored.
:Extended by: KVM_CAP_INTR_SHADOW
:Architectures: x86, arm64
:Type: vcpu ioctl
-:Parameters: struct kvm_vcpu_event (out)
+:Parameters: struct kvm_vcpu_events (out)
:Returns: 0 on success, -1 on error
X86:
@@ -1193,7 +1226,7 @@ directly to the virtual CPU).
:Extended by: KVM_CAP_INTR_SHADOW
:Architectures: x86, arm64
:Type: vcpu ioctl
-:Parameters: struct kvm_vcpu_event (in)
+:Parameters: struct kvm_vcpu_events (in)
:Returns: 0 on success, -1 on error
X86:
@@ -1387,7 +1420,7 @@ documentation when it pops into existence).
-------------------
:Capability: KVM_CAP_ENABLE_CAP
-:Architectures: mips, ppc, s390, x86
+:Architectures: mips, ppc, s390, x86, loongarch
:Type: vcpu ioctl
:Parameters: struct kvm_enable_cap (in)
:Returns: 0 on success; -1 on error
@@ -1442,7 +1475,7 @@ for vm-wide capabilities.
---------------------
:Capability: KVM_CAP_MP_STATE
-:Architectures: x86, s390, arm64, riscv
+:Architectures: x86, s390, arm64, riscv, loongarch
:Type: vcpu ioctl
:Parameters: struct kvm_mp_state (out)
:Returns: 0 on success; -1 on error
@@ -1460,7 +1493,7 @@ Possible values are:
========================== ===============================================
KVM_MP_STATE_RUNNABLE the vcpu is currently running
- [x86,arm64,riscv]
+ [x86,arm64,riscv,loongarch]
KVM_MP_STATE_UNINITIALIZED the vcpu is an application processor (AP)
which has not yet received an INIT signal [x86]
KVM_MP_STATE_INIT_RECEIVED the vcpu has received an INIT signal, and is
@@ -1516,11 +1549,14 @@ For riscv:
The only states that are valid are KVM_MP_STATE_STOPPED and
KVM_MP_STATE_RUNNABLE which reflect if the vcpu is paused or not.
+On LoongArch, only the KVM_MP_STATE_RUNNABLE state is used to reflect
+whether the vcpu is runnable.
+
4.39 KVM_SET_MP_STATE
---------------------
:Capability: KVM_CAP_MP_STATE
-:Architectures: x86, s390, arm64, riscv
+:Architectures: x86, s390, arm64, riscv, loongarch
:Type: vcpu ioctl
:Parameters: struct kvm_mp_state (in)
:Returns: 0 on success; -1 on error
@@ -1538,6 +1574,9 @@ For arm64/riscv:
The only states that are valid are KVM_MP_STATE_STOPPED and
KVM_MP_STATE_RUNNABLE which reflect if the vcpu should be paused or not.
+On LoongArch, only the KVM_MP_STATE_RUNNABLE state is used to reflect
+whether the vcpu is runnable.
+
4.40 KVM_SET_IDENTITY_MAP_ADDR
------------------------------
@@ -2841,6 +2880,19 @@ Following are the RISC-V D-extension registers:
0x8020 0000 0600 0020 fcsr Floating point control and status register
======================= ========= =============================================
+LoongArch registers are mapped using the lower 32 bits. The upper 16 bits of
+that is the register group type.
+
+LoongArch csr registers are used to control guest cpu or get status of guest
+cpu, and they have the following id bit patterns::
+
+ 0x9030 0000 0001 00 <reg:5> <sel:3> (64-bit)
+
+LoongArch KVM control registers are used to implement some new defined functions
+such as set vcpu counter or reset vcpu, and they have the following id bit patterns::
+
+ 0x9030 0000 0002 <reg:16>
+
4.69 KVM_GET_ONE_REG
--------------------
@@ -3063,7 +3115,7 @@ as follow::
};
An entry with a "page_shift" of 0 is unused. Because the array is
-organized in increasing order, a lookup can stop when encoutering
+organized in increasing order, a lookup can stop when encountering
such an entry.
The "slb_enc" field provides the encoding to use in the SLB for the
@@ -3370,6 +3422,8 @@ return indicates the attribute is implemented. It does not necessarily
indicate that the attribute can be read or written in the device's
current state. "addr" is ignored.
+.. _KVM_ARM_VCPU_INIT:
+
4.82 KVM_ARM_VCPU_INIT
----------------------
@@ -3455,7 +3509,7 @@ Possible features:
- KVM_RUN and KVM_GET_REG_LIST are not available;
- KVM_GET_ONE_REG and KVM_SET_ONE_REG cannot be used to access
- the scalable archietctural SVE registers
+ the scalable architectural SVE registers
KVM_REG_ARM64_SVE_ZREG(), KVM_REG_ARM64_SVE_PREG() or
KVM_REG_ARM64_SVE_FFR;
@@ -4401,7 +4455,7 @@ This will have undefined effects on the guest if it has not already
placed itself in a quiescent state where no vcpu will make MMU enabled
memory accesses.
-On succsful completion, the pending HPT will become the guest's active
+On successful completion, the pending HPT will become the guest's active
HPT and the previous HPT will be discarded.
On failure, the guest will still be operating on its previous HPT.
@@ -5016,7 +5070,7 @@ before the vcpu is fully usable.
Between KVM_ARM_VCPU_INIT and KVM_ARM_VCPU_FINALIZE, the feature may be
configured by use of ioctls such as KVM_SET_ONE_REG. The exact configuration
-that should be performaned and how to do it are feature-dependent.
+that should be performed and how to do it are feature-dependent.
Other calls that depend on a particular feature being finalized, such as
KVM_RUN, KVM_GET_REG_LIST, KVM_GET_ONE_REG and KVM_SET_ONE_REG, will fail with
@@ -5124,6 +5178,24 @@ Valid values for 'action'::
#define KVM_PMU_EVENT_ALLOW 0
#define KVM_PMU_EVENT_DENY 1
+Via this API, KVM userspace can also control the behavior of the VM's fixed
+counters (if any) by configuring the "action" and "fixed_counter_bitmap" fields.
+
+Specifically, KVM follows the following pseudo-code when determining whether to
+allow the guest FixCtr[i] to count its pre-defined fixed event::
+
+ FixCtr[i]_is_allowed = (action == ALLOW) && (bitmap & BIT(i)) ||
+ (action == DENY) && !(bitmap & BIT(i));
+ FixCtr[i]_is_denied = !FixCtr[i]_is_allowed;
+
+KVM always consumes fixed_counter_bitmap, it's userspace's responsibility to
+ensure fixed_counter_bitmap is set correctly, e.g. if userspace wants to define
+a filter that only affects general purpose counters.
+
+Note, the "events" field also applies to fixed counters' hardcoded event_select
+and unit_mask values. "fixed_counter_bitmap" has higher priority than "events"
+if there is a contradiction between the two.
+
4.121 KVM_PPC_SVM_OFF
---------------------
@@ -5475,7 +5547,7 @@ KVM_XEN_ATTR_TYPE_EVTCHN
from the guest. A given sending port number may be directed back to
a specified vCPU (by APIC ID) / port / priority on the guest, or to
trigger events on an eventfd. The vCPU and priority can be changed
- by setting KVM_XEN_EVTCHN_UPDATE in a subsequent call, but but other
+ by setting KVM_XEN_EVTCHN_UPDATE in a subsequent call, but other
fields cannot change for a given sending port. A port mapping is
removed by using KVM_XEN_EVTCHN_DEASSIGN in the flags field. Passing
KVM_XEN_EVTCHN_RESET in the flags field removes all interception of
@@ -6070,6 +6142,56 @@ writes to the CNTVCT_EL0 and CNTPCT_EL0 registers using the SET_ONE_REG
interface. No error will be returned, but the resulting offset will not be
applied.
+.. _KVM_ARM_GET_REG_WRITABLE_MASKS:
+
+4.139 KVM_ARM_GET_REG_WRITABLE_MASKS
+-------------------------------------------
+
+:Capability: KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES
+:Architectures: arm64
+:Type: vm ioctl
+:Parameters: struct reg_mask_range (in/out)
+:Returns: 0 on success, < 0 on error
+
+
+::
+
+ #define KVM_ARM_FEATURE_ID_RANGE 0
+ #define KVM_ARM_FEATURE_ID_RANGE_SIZE (3 * 8 * 8)
+
+ struct reg_mask_range {
+ __u64 addr; /* Pointer to mask array */
+ __u32 range; /* Requested range */
+ __u32 reserved[13];
+ };
+
+This ioctl copies the writable masks for a selected range of registers to
+userspace.
+
+The ``addr`` field is a pointer to the destination array where KVM copies
+the writable masks.
+
+The ``range`` field indicates the requested range of registers.
+``KVM_CHECK_EXTENSION`` for the ``KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES``
+capability returns the supported ranges, expressed as a set of flags. Each
+flag's bit index represents a possible value for the ``range`` field.
+All other values are reserved for future use and KVM may return an error.
+
+The ``reserved[13]`` array is reserved for future use and should be 0, or
+KVM may return an error.
+
+KVM_ARM_FEATURE_ID_RANGE (0)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The Feature ID range is defined as the AArch64 System register space with
+op0==3, op1=={0, 1, 3}, CRn==0, CRm=={0-7}, op2=={0-7}.
+
+The mask returned array pointed to by ``addr`` is indexed by the macro
+``ARM64_FEATURE_ID_RANGE_IDX(op0, op1, crn, crm, op2)``, allowing userspace
+to know what fields can be changed for the system register described by
+``op0, op1, crn, crm, op2``. KVM rejects ID register values that describe a
+superset of the features supported by the system.
+
5. The kvm_run structure
========================
diff --git a/Documentation/virt/kvm/arm/index.rst b/Documentation/virt/kvm/arm/index.rst
index e84848432158..7f231c724e16 100644
--- a/Documentation/virt/kvm/arm/index.rst
+++ b/Documentation/virt/kvm/arm/index.rst
@@ -11,3 +11,4 @@ ARM
hypercalls
pvtime
ptp_kvm
+ vcpu-features
diff --git a/Documentation/virt/kvm/arm/vcpu-features.rst b/Documentation/virt/kvm/arm/vcpu-features.rst
new file mode 100644
index 000000000000..f7cc6d8d8b74
--- /dev/null
+++ b/Documentation/virt/kvm/arm/vcpu-features.rst
@@ -0,0 +1,48 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===============================
+vCPU feature selection on arm64
+===============================
+
+KVM/arm64 provides two mechanisms that allow userspace to configure
+the CPU features presented to the guest.
+
+KVM_ARM_VCPU_INIT
+=================
+
+The ``KVM_ARM_VCPU_INIT`` ioctl accepts a bitmap of feature flags
+(``struct kvm_vcpu_init::features``). Features enabled by this interface are
+*opt-in* and may change/extend UAPI. See :ref:`KVM_ARM_VCPU_INIT` for complete
+documentation of the features controlled by the ioctl.
+
+Otherwise, all CPU features supported by KVM are described by the architected
+ID registers.
+
+The ID Registers
+================
+
+The Arm architecture specifies a range of *ID Registers* that describe the set
+of architectural features supported by the CPU implementation. KVM initializes
+the guest's ID registers to the maximum set of CPU features supported by the
+system. The ID register values may be VM-scoped in KVM, meaning that the
+values could be shared for all vCPUs in a VM.
+
+KVM allows userspace to *opt-out* of certain CPU features described by the ID
+registers by writing values to them via the ``KVM_SET_ONE_REG`` ioctl. The ID
+registers are mutable until the VM has started, i.e. userspace has called
+``KVM_RUN`` on at least one vCPU in the VM. Userspace can discover what fields
+are mutable in the ID registers using the ``KVM_ARM_GET_REG_WRITABLE_MASKS``.
+See the :ref:`ioctl documentation <KVM_ARM_GET_REG_WRITABLE_MASKS>` for more
+details.
+
+Userspace is allowed to *limit* or *mask* CPU features according to the rules
+outlined by the architecture in DDI0487J.a D19.1.3 'Principles of the ID
+scheme for fields in ID register'. KVM does not allow ID register values that
+exceed the capabilities of the system.
+
+.. warning::
+ It is **strongly recommended** that userspace modify the ID register values
+ before accessing the rest of the vCPU's CPU register state. KVM may use the
+ ID register values to control feature emulation. Interleaving ID register
+ modification with other system register accesses may lead to unpredictable
+ behavior.
diff --git a/Documentation/virt/kvm/devices/arm-vgic-v3.rst b/Documentation/virt/kvm/devices/arm-vgic-v3.rst
index 51e5e5762571..5817edb4e046 100644
--- a/Documentation/virt/kvm/devices/arm-vgic-v3.rst
+++ b/Documentation/virt/kvm/devices/arm-vgic-v3.rst
@@ -59,6 +59,13 @@ Groups:
It is invalid to mix calls with KVM_VGIC_V3_ADDR_TYPE_REDIST and
KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION attributes.
+ Note that to obtain reproducible results (the same VCPU being associated
+ with the same redistributor across a save/restore operation), VCPU creation
+ order, redistributor region creation order as well as the respective
+ interleaves of VCPU and region creation MUST be preserved. Any change in
+ either ordering may result in a different vcpu_id/redistributor association,
+ resulting in a VM that will fail to run at restore time.
+
Errors:
======= =============================================================
diff --git a/Documentation/virt/kvm/x86/mmu.rst b/Documentation/virt/kvm/x86/mmu.rst
index d47595b33fcf..2b3b6d442302 100644
--- a/Documentation/virt/kvm/x86/mmu.rst
+++ b/Documentation/virt/kvm/x86/mmu.rst
@@ -202,10 +202,22 @@ Shadow pages contain the following information:
Is 1 if the MMU instance cannot use A/D bits. EPT did not have A/D
bits before Haswell; shadow EPT page tables also cannot use A/D bits
if the L1 hypervisor does not enable them.
+ role.guest_mode:
+ Indicates the shadow page is created for a nested guest.
role.passthrough:
The page is not backed by a guest page table, but its first entry
points to one. This is set if NPT uses 5-level page tables (host
CR4.LA57=1) and is shadowing L1's 4-level NPT (L1 CR4.LA57=0).
+ mmu_valid_gen:
+ The MMU generation of this page, used to fast zap of all MMU pages within a
+ VM without blocking vCPUs too long. Specifically, KVM updates the per-VM
+ valid MMU generation which causes the mismatch of mmu_valid_gen for each mmu
+ page. This makes all existing MMU pages obsolete. Obsolete pages can't be
+ used. Therefore, vCPUs must load a new, valid root before re-entering the
+ guest. The MMU generation is only ever '0' or '1'. Note, the TDP MMU doesn't
+ use this field as non-root TDP MMU pages are reachable only from their
+ owning root. Thus it suffices for TDP MMU to use role.invalid in root pages
+ to invalidate all MMU pages.
gfn:
Either the guest page table containing the translations shadowed by this
page, or the base page frame for linear translations. See role.direct.
@@ -219,21 +231,30 @@ Shadow pages contain the following information:
at __pa(sp2->spt). sp2 will point back at sp1 through parent_pte.
The spt array forms a DAG structure with the shadow page as a node, and
guest pages as leaves.
- gfns:
- An array of 512 guest frame numbers, one for each present pte. Used to
- perform a reverse map from a pte to a gfn. When role.direct is set, any
- element of this array can be calculated from the gfn field when used, in
- this case, the array of gfns is not allocated. See role.direct and gfn.
- root_count:
- A counter keeping track of how many hardware registers (guest cr3 or
- pdptrs) are now pointing at the page. While this counter is nonzero, the
- page cannot be destroyed. See role.invalid.
+ shadowed_translation:
+ An array of 512 shadow translation entries, one for each present pte. Used
+ to perform a reverse map from a pte to a gfn as well as its access
+ permission. When role.direct is set, the shadow_translation array is not
+ allocated. This is because the gfn contained in any element of this array
+ can be calculated from the gfn field when used. In addition, when
+ role.direct is set, KVM does not track access permission for each of the
+ gfn. See role.direct and gfn.
+ root_count / tdp_mmu_root_count:
+ root_count is a reference counter for root shadow pages in Shadow MMU.
+ vCPUs elevate the refcount when getting a shadow page that will be used as
+ a root page, i.e. page that will be loaded into hardware directly (CR3,
+ PDPTRs, nCR3 EPTP). Root pages cannot be destroyed while their refcount is
+ non-zero. See role.invalid. tdp_mmu_root_count is similar but exclusively
+ used in TDP MMU as an atomic refcount.
parent_ptes:
The reverse mapping for the pte/ptes pointing at this page's spt. If
parent_ptes bit 0 is zero, only one spte points at this page and
parent_ptes points at this single spte, otherwise, there exists multiple
sptes pointing at this page and (parent_ptes & ~0x1) points at a data
structure with a list of parent sptes.
+ ptep:
+ The kernel virtual address of the SPTE that points at this shadow page.
+ Used exclusively by the TDP MMU, this field is a union with parent_ptes.
unsync:
If true, then the translations in this page may not match the guest's
translation. This is equivalent to the state of the tlb when a pte is
@@ -261,6 +282,10 @@ Shadow pages contain the following information:
since the last time the page table was actually used; if emulation
is triggered too frequently on this page, KVM will unmap the page
to avoid emulation in the future.
+ tdp_mmu_page:
+ Is 1 if the shadow page is a TDP MMU page. This variable is used to
+ bifurcate the control flows for KVM when walking any data structure that
+ may contain pages from both TDP MMU and shadow MMU.
Reverse map
===========
diff --git a/MAINTAINERS b/MAINTAINERS
index 7608b714653f..9104430e148e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -171,13 +171,10 @@ S: Supported
F: drivers/soc/fujitsu/a64fx-diag.c
A8293 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/a8293*
AACRAID SCSI RAID DRIVER
@@ -294,6 +291,8 @@ F: drivers/pnp/pnpacpi/
F: include/acpi/
F: include/linux/acpi.h
F: include/linux/fwnode.h
+F: include/linux/fw_table.h
+F: lib/fw_table.c
F: tools/power/acpi/
ACPI APEI
@@ -309,7 +308,7 @@ ACPI COMPONENT ARCHITECTURE (ACPICA)
M: Robert Moore <robert.moore@intel.com>
M: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
L: linux-acpi@vger.kernel.org
-L: acpica-devel@lists.linuxfoundation.org
+L: acpica-devel@lists.linux.dev
S: Supported
W: https://acpica.org/
W: https://github.com/acpica/acpica/
@@ -378,8 +377,9 @@ F: drivers/acpi/viot.c
F: include/linux/acpi_viot.h
ACPI WMI DRIVER
+M: Armin Wolf <W_Armin@gmx.de>
L: platform-driver-x86@vger.kernel.org
-S: Orphan
+S: Maintained
F: Documentation/driver-api/wmi.rst
F: Documentation/wmi/
F: drivers/platform/x86/wmi.c
@@ -573,23 +573,17 @@ F: drivers/iio/accel/adxl372_i2c.c
F: drivers/iio/accel/adxl372_spi.c
AF9013 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/af9013*
AF9033 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/af9033*
AFFS FILE SYSTEM
@@ -647,13 +641,10 @@ F: fs/aio.c
F: include/linux/*aio*.h
AIRSPY MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/airspy/
ALACRITECH GIGABIT ETHERNET DRIVER
@@ -907,7 +898,7 @@ F: drivers/crypto/ccp/
F: include/linux/ccp.h
AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER - SEV SUPPORT
-M: Brijesh Singh <brijesh.singh@amd.com>
+M: Ashish Kalra <ashish.kalra@amd.com>
M: Tom Lendacky <thomas.lendacky@amd.com>
L: linux-crypto@vger.kernel.org
S: Supported
@@ -1118,7 +1109,7 @@ ANALOG DEVICES INC AD4130 DRIVER
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
-W: http://ez.analog.com/community/linux-device-drivers
+W: https://ez.analog.com/linux-software-drivers
F: Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130
F: Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
F: drivers/iio/adc/ad4130.c
@@ -1151,7 +1142,7 @@ ANALOG DEVICES INC AD74115 DRIVER
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
-W: http://ez.analog.com/community/linux-device-drivers
+W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/addac/adi,ad74115.yaml
F: drivers/iio/addac/ad74115.c
@@ -1459,7 +1450,6 @@ F: drivers/hwmon/applesmc.c
APPLETALK NETWORK LAYER
L: netdev@vger.kernel.org
S: Odd fixes
-F: drivers/net/appletalk/
F: include/linux/atalk.h
F: include/uapi/linux/atalk.h
F: net/appletalk/
@@ -1636,13 +1626,13 @@ F: drivers/gpu/drm/arm/display/include/
F: drivers/gpu/drm/arm/display/komeda/
ARM MALI PANFROST DRM DRIVER
+M: Boris Brezillon <boris.brezillon@collabora.com>
M: Rob Herring <robh@kernel.org>
-M: Tomeu Vizoso <tomeu.vizoso@collabora.com>
R: Steven Price <steven.price@arm.com>
-R: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
L: dri-devel@lists.freedesktop.org
S: Supported
T: git git://anongit.freedesktop.org/drm/drm-misc
+F: Documentation/gpu/panfrost.rst
F: drivers/gpu/drm/panfrost/
F: include/uapi/drm/panfrost_drm.h
@@ -1798,7 +1788,7 @@ F: drivers/irqchip/irq-owl-sirq.c
F: drivers/mmc/host/owl-mmc.c
F: drivers/net/ethernet/actions/
F: drivers/pinctrl/actions/*
-F: drivers/soc/actions/
+F: drivers/pmdomain/actions/
F: include/dt-bindings/power/owl-*
F: include/dt-bindings/reset/actions,*
F: include/linux/soc/actions/
@@ -1826,6 +1816,13 @@ N: allwinner
N: sun[x456789]i
N: sun[25]0i
+ARM/AMD PENSANDO ARM64 ARCHITECTURE
+M: Brad Larson <blarson@amd.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Supported
+F: Documentation/devicetree/bindings/*/amd,pensando*
+F: arch/arm64/boot/dts/amd/elba*
+
ARM/Amlogic Meson SoC CLOCK FRAMEWORK
M: Neil Armstrong <neil.armstrong@linaro.org>
M: Jerome Brunet <jbrunet@baylibre.com>
@@ -2068,12 +2065,16 @@ F: Documentation/trace/coresight/*
F: drivers/hwtracing/coresight/*
F: include/dt-bindings/arm/coresight-cti-dt.h
F: include/linux/coresight*
+F: include/uapi/linux/coresight*
F: samples/coresight/*
+F: tools/perf/Documentation/arm-coresight.txt
F: tools/perf/arch/arm/util/auxtrace.c
F: tools/perf/arch/arm/util/cs-etm.c
F: tools/perf/arch/arm/util/cs-etm.h
F: tools/perf/arch/arm/util/pmu.c
+F: tools/perf/tests/shell/*coresight*
F: tools/perf/tests/shell/coresight/*
+F: tools/perf/tests/shell/lib/*coresight*
F: tools/perf/util/cs-etm-decoder/*
F: tools/perf/util/cs-etm.*
@@ -2142,6 +2143,7 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
F: arch/arm/boot/dts/nxp/imx/
F: arch/arm/boot/dts/nxp/mxs/
+F: arch/arm64/boot/dts/freescale/
X: arch/arm64/boot/dts/freescale/fsl-*
X: arch/arm64/boot/dts/freescale/qoriq-*
X: drivers/media/i2c/
@@ -2221,21 +2223,28 @@ F: arch/arm/boot/dts/ti/omap/omap3-igep*
ARM/INTEL IXP4XX ARM ARCHITECTURE
M: Linus Walleij <linusw@kernel.org>
M: Imre Kaloz <kaloz@openwrt.org>
-M: Krzysztof Halasa <khalasa@piap.pl>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
-F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
+F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml
F: Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
F: Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion*
+F: Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml
F: Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
F: arch/arm/boot/dts/intel/ixp/
F: arch/arm/mach-ixp4xx/
F: drivers/bus/intel-ixp4xx-eb.c
+F: drivers/char/hw_random/ixp4xx-rng.c
F: drivers/clocksource/timer-ixp4xx.c
F: drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
F: drivers/gpio/gpio-ixp4xx.c
F: drivers/irqchip/irq-ixp4xx.c
+F: drivers/net/ethernet/xscale/ixp4xx_eth.c
+F: drivers/net/wan/ixp4xx_hss.c
+F: drivers/soc/ixp4xx/ixp4xx-npe.c
+F: drivers/soc/ixp4xx/ixp4xx-qmgr.c
+F: include/linux/soc/ixp4xx/npe.h
+F: include/linux/soc/ixp4xx/qmgr.h
ARM/INTEL KEEMBAY ARCHITECTURE
M: Paul J. Murphy <paul.j.murphy@intel.com>
@@ -2337,7 +2346,7 @@ F: drivers/rtc/rtc-mt7622.c
ARM/Mediatek SoC support
M: Matthias Brugger <matthias.bgg@gmail.com>
-R: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+M: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
L: linux-kernel@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
@@ -2490,6 +2499,18 @@ F: drivers/rtc/rtc-nct3018y.c
F: include/dt-bindings/clock/nuvoton,npcm7xx-clock.h
F: include/dt-bindings/clock/nuvoton,npcm845-clk.h
+ARM/NUVOTON NPCM VIDEO ENGINE DRIVER
+M: Joseph Liu <kwliu@nuvoton.com>
+M: Marvin Lin <kflin@nuvoton.com>
+L: linux-media@vger.kernel.org
+L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
+S: Maintained
+F: Documentation/devicetree/bindings/media/nuvoton,npcm-ece.yaml
+F: Documentation/devicetree/bindings/media/nuvoton,npcm-vcd.yaml
+F: Documentation/userspace-api/media/drivers/npcm-video.rst
+F: drivers/media/platform/nuvoton/
+F: include/uapi/linux/npcm-video.h
+
ARM/NUVOTON WPCM450 ARCHITECTURE
M: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
@@ -2503,7 +2524,7 @@ F: drivers/*/*/*wpcm*
F: drivers/*/*wpcm*
ARM/NXP S32G ARCHITECTURE
-M: Chester Lin <clin@suse.com>
+M: Chester Lin <chester62515@gmail.com>
R: Andreas Färber <afaerber@suse.de>
R: Matthias Brugger <mbrugger@suse.com>
R: NXP S32 Linux Team <s32@nxp.com>
@@ -3474,6 +3495,14 @@ W: http://bcache.evilpiepirate.org
C: irc://irc.oftc.net/bcache
F: drivers/md/bcache/
+BCACHEFS
+M: Kent Overstreet <kent.overstreet@linux.dev>
+R: Brian Foster <bfoster@redhat.com>
+L: linux-bcachefs@vger.kernel.org
+S: Supported
+C: irc://irc.oftc.net/bcache
+F: fs/bcachefs/
+
BDISP ST MEDIA DRIVER
M: Fabien Dessenne <fabien.dessenne@foss.st.com>
L: linux-media@vger.kernel.org
@@ -3517,12 +3546,14 @@ R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
R: Rasmus Villemoes <linux@rasmusvillemoes.dk>
S: Maintained
F: include/linux/bitfield.h
+F: include/linux/bitmap-str.h
F: include/linux/bitmap.h
F: include/linux/bits.h
F: include/linux/cpumask.h
F: include/linux/find.h
F: include/linux/nodemask.h
F: include/vdso/bits.h
+F: lib/bitmap-str.c
F: lib/bitmap.c
F: lib/cpumask.c
F: lib/cpumask_kunit.c
@@ -3606,9 +3637,10 @@ F: Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml
F: drivers/iio/accel/bma400*
BPF JIT for ARM
-M: Shubham Bansal <illusionist.neo@gmail.com>
+M: Russell King <linux@armlinux.org.uk>
+M: Puranjay Mohan <puranjay12@gmail.com>
L: bpf@vger.kernel.org
-S: Odd Fixes
+S: Maintained
F: arch/arm/net/
BPF JIT for ARM64
@@ -3752,7 +3784,7 @@ F: net/sched/act_bpf.c
F: net/sched/cls_bpf.c
F: samples/bpf/
F: scripts/bpf_doc.py
-F: scripts/pahole-flags.sh
+F: scripts/Makefile.btf
F: scripts/pahole-version.sh
F: tools/bpf/
F: tools/lib/bpf/
@@ -3788,6 +3820,15 @@ L: bpf@vger.kernel.org
S: Odd Fixes
K: (?:\b|_)bpf(?:\b|_)
+BPF [NETKIT] (BPF-programmable network device)
+M: Daniel Borkmann <daniel@iogearbox.net>
+M: Nikolay Aleksandrov <razor@blackwall.org>
+L: bpf@vger.kernel.org
+L: netdev@vger.kernel.org
+S: Supported
+F: drivers/net/netkit.c
+F: include/net/netkit.h
+
BPF [NETWORKING] (struct_ops, reuseport)
M: Martin KaFai Lau <martin.lau@linux.dev>
L: bpf@vger.kernel.org
@@ -4330,8 +4371,7 @@ F: drivers/net/ethernet/broadcom/bcmsysport.*
F: drivers/net/ethernet/broadcom/unimac.h
BROADCOM TG3 GIGABIT ETHERNET DRIVER
-M: Siva Reddy Kallam <siva.kallam@broadcom.com>
-M: Prashant Sreedharan <prashant@broadcom.com>
+M: Pavan Chebbi <pavan.chebbi@broadcom.com>
M: Michael Chan <mchan@broadcom.com>
L: netdev@vger.kernel.org
S: Supported
@@ -4804,6 +4844,13 @@ X: drivers/char/ipmi/
X: drivers/char/random.c
X: drivers/char/tpm/
+CHARGERLAB POWER-Z HARDWARE MONITOR DRIVER
+M: Thomas Weißschuh <linux@weissschuh.net>
+L: linux-hwmon@vger.kernel.org
+S: Maintained
+F: Documentation/hwmon/powerz.rst
+F: drivers/hwmon/powerz.c
+
CHECKPATCH
M: Andy Whitcroft <apw@canonical.com>
M: Joe Perches <joe@perches.com>
@@ -4921,6 +4968,7 @@ F: drivers/spi/spi-cs42l43*
F: include/dt-bindings/sound/cs*
F: include/linux/mfd/cs42l43*
F: include/sound/cs*
+F: sound/pci/hda/cirrus*
F: sound/pci/hda/cs*
F: sound/pci/hda/hda_cs_dsp_ctl.*
F: sound/soc/codecs/cs*
@@ -5017,7 +5065,6 @@ CLANG CONTROL FLOW INTEGRITY SUPPORT
M: Sami Tolvanen <samitolvanen@google.com>
M: Kees Cook <keescook@chromium.org>
R: Nathan Chancellor <nathan@kernel.org>
-R: Nick Desaulniers <ndesaulniers@google.com>
L: llvm@lists.linux.dev
S: Supported
B: https://github.com/ClangBuiltLinux/linux/issues
@@ -5032,8 +5079,9 @@ F: .clang-format
CLANG/LLVM BUILD SUPPORT
M: Nathan Chancellor <nathan@kernel.org>
-M: Nick Desaulniers <ndesaulniers@google.com>
-R: Tom Rix <trix@redhat.com>
+R: Nick Desaulniers <ndesaulniers@google.com>
+R: Bill Wendling <morbo@google.com>
+R: Justin Stitt <justinstitt@google.com>
L: llvm@lists.linux.dev
S: Supported
W: https://clangbuiltlinux.github.io/
@@ -5060,6 +5108,14 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
F: Documentation/devicetree/bindings/timer/
F: drivers/clocksource/
+CLOSURES
+M: Kent Overstreet <kent.overstreet@linux.dev>
+L: linux-bcachefs@vger.kernel.org
+S: Supported
+C: irc://irc.oftc.net/bcache
+F: include/linux/closure.h
+F: lib/closure.c
+
CMPC ACPI DRIVER
M: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
M: Daniel Oliveira Nascimento <don@syst.com.br>
@@ -5175,7 +5231,6 @@ F: drivers/platform/x86/compal-laptop.c
COMPILER ATTRIBUTES
M: Miguel Ojeda <ojeda@kernel.org>
-R: Nick Desaulniers <ndesaulniers@google.com>
S: Maintained
F: include/linux/compiler_attributes.h
@@ -5191,6 +5246,7 @@ L: linux-cxl@vger.kernel.org
S: Maintained
F: drivers/cxl/
F: include/uapi/linux/cxl_mem.h
+F: tools/testing/cxl/
COMPUTE EXPRESS LINK PMU (CPMU)
M: Jonathan Cameron <jonathan.cameron@huawei.com>
@@ -5205,6 +5261,12 @@ S: Orphan
W: http://accessrunner.sourceforge.net/
F: drivers/usb/atm/cxacru.c
+CONFIDENTIAL COMPUTING THREAT MODEL FOR X86 VIRTUALIZATION (SNP/TDX)
+M: Elena Reshetova <elena.reshetova@intel.com>
+M: Carlos Bilbao <carlos.bilbao@amd.com>
+S: Maintained
+F: Documentation/security/snp-tdx-threat-model.rst
+
CONFIGFS
M: Joel Becker <jlbec@evilplan.org>
M: Christoph Hellwig <hch@lst.de>
@@ -5279,6 +5341,7 @@ S: Maintained
F: mm/memcontrol.c
F: mm/swap_cgroup.c
F: tools/testing/selftests/cgroup/memcg_protection.m
+F: tools/testing/selftests/cgroup/test_hugetlb_memcg.c
F: tools/testing/selftests/cgroup/test_kmem.c
F: tools/testing/selftests/cgroup/test_memcontrol.c
@@ -5319,12 +5382,6 @@ M: Bence Csókás <bence98@sch.bme.hu>
S: Maintained
F: drivers/i2c/busses/i2c-cp2615.c
-CPMAC ETHERNET DRIVER
-M: Florian Fainelli <f.fainelli@gmail.com>
-L: netdev@vger.kernel.org
-S: Maintained
-F: drivers/net/ethernet/ti/cpmac.c
-
CPU FREQUENCY DRIVERS - VEXPRESS SPC ARM BIG LITTLE
M: Viresh Kumar <viresh.kumar@linaro.org>
M: Sudeep Holla <sudeep.holla@arm.com>
@@ -5536,13 +5593,10 @@ F: Documentation/driver-api/media/drivers/cx88*
F: drivers/media/pci/cx88/
CXD2820R MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/cxd2820r*
CXGB3 ETHERNET DRIVER (CXGB3)
@@ -5608,7 +5662,7 @@ M: Andrew Donnellan <ajd@linux.ibm.com>
L: linuxppc-dev@lists.ozlabs.org
S: Supported
F: Documentation/ABI/testing/sysfs-class-cxl
-F: Documentation/powerpc/cxl.rst
+F: Documentation/arch/powerpc/cxl.rst
F: arch/powerpc/platforms/powernv/pci-cxl.c
F: drivers/misc/cxl/
F: include/misc/cxl*
@@ -5620,7 +5674,7 @@ M: Matthew R. Ochs <mrochs@linux.ibm.com>
M: Uma Krishnan <ukrishn@linux.ibm.com>
L: linux-scsi@vger.kernel.org
S: Supported
-F: Documentation/powerpc/cxlflash.rst
+F: Documentation/arch/powerpc/cxlflash.rst
F: drivers/scsi/cxlflash/
F: include/uapi/scsi/cxlflash_ioctl.h
@@ -5655,13 +5709,10 @@ F: Documentation/devicetree/bindings/input/cypress-sf.yaml
F: drivers/input/keyboard/cypress-sf.c
CYPRESS_FIRMWARE MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/common/cypress_firmware*
CYTTSP TOUCHSCREEN DRIVER
@@ -5995,6 +6046,7 @@ F: include/linux/devm-helpers.h
DEVICE-MAPPER (LVM)
M: Alasdair Kergon <agk@redhat.com>
M: Mike Snitzer <snitzer@kernel.org>
+M: Mikulas Patocka <mpatocka@redhat.com>
M: dm-devel@lists.linux.dev
L: dm-devel@lists.linux.dev
S: Maintained
@@ -6085,6 +6137,13 @@ L: linux-gpio@vger.kernel.org
S: Maintained
F: drivers/gpio/gpio-gpio-mm.c
+DIGITEQ AUTOMOTIVE MGB4 V4L2 DRIVER
+M: Martin Tuma <martin.tuma@digiteqautomotive.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: Documentation/admin-guide/media/mgb4.rst
+F: drivers/media/pci/mgb4/
+
DIOLAN U2C-12 I2C DRIVER
M: Guenter Roeck <linux@roeck-us.net>
L: linux-i2c@vger.kernel.org
@@ -6125,11 +6184,11 @@ F: drivers/video/fbdev/udlfb.c
F: include/video/udlfb.h
DISTRIBUTED LOCK MANAGER (DLM)
-M: Christine Caulfield <ccaulfie@redhat.com>
+M: Alexander Aring <aahringo@redhat.com>
M: David Teigland <teigland@redhat.com>
L: gfs2@lists.linux.dev
S: Supported
-W: http://sources.redhat.com/cluster/
+W: https://pagure.io/dlm
T: git git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm.git
F: fs/dlm/
@@ -6142,6 +6201,7 @@ L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
F: Documentation/driver-api/dma-buf.rst
+F: Documentation/userspace-api/dma-buf-alloc-exchange.rst
F: drivers/dma-buf/
F: include/linux/*fence.h
F: include/linux/dma-buf.h
@@ -6344,6 +6404,17 @@ F: Documentation/networking/device_drivers/ethernet/freescale/dpaa2/switch-drive
F: drivers/net/ethernet/freescale/dpaa2/dpaa2-switch*
F: drivers/net/ethernet/freescale/dpaa2/dpsw*
+DPLL SUBSYSTEM
+M: Vadim Fedorenko <vadim.fedorenko@linux.dev>
+M: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
+M: Jiri Pirko <jiri@resnulli.us>
+L: netdev@vger.kernel.org
+S: Supported
+F: Documentation/driver-api/dpll.rst
+F: drivers/dpll/*
+F: include/linux/dpll.h
+F: include/uapi/linux/dpll.h
+
DRBD DRIVER
M: Philipp Reisner <philipp.reisner@linbit.com>
M: Lars Ellenberg <lars.ellenberg@linbit.com>
@@ -6445,7 +6516,7 @@ F: drivers/gpu/drm/ast/
DRM DRIVER FOR BOCHS VIRTUAL GPU
M: Gerd Hoffmann <kraxel@redhat.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
F: drivers/gpu/drm/tiny/bochs.c
@@ -6623,6 +6694,7 @@ S: Maintained
B: https://gitlab.freedesktop.org/drm/msm/-/issues
T: git https://gitlab.freedesktop.org/drm/msm.git
F: Documentation/devicetree/bindings/display/msm/
+F: drivers/gpu/drm/ci/xfails/msm*
F: drivers/gpu/drm/msm/
F: include/uapi/drm/msm_drm.h
@@ -6691,7 +6763,7 @@ F: drivers/gpu/drm/tiny/repaper.c
DRM DRIVER FOR QEMU'S CIRRUS DEVICE
M: Dave Airlie <airlied@redhat.com>
M: Gerd Hoffmann <kraxel@redhat.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Obsolete
W: https://www.kraxel.org/blog/2014/10/qemu-using-cirrus-considered-harmful/
T: git git://anongit.freedesktop.org/drm/drm-misc
@@ -6700,7 +6772,7 @@ F: drivers/gpu/drm/tiny/cirrus.c
DRM DRIVER FOR QXL VIRTUAL GPU
M: Dave Airlie <airlied@redhat.com>
M: Gerd Hoffmann <kraxel@redhat.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
L: spice-devel@lists.freedesktop.org
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
@@ -6758,7 +6830,7 @@ F: drivers/gpu/drm/panel/panel-sitronix-st7701.c
DRM DRIVER FOR SITRONIX ST7703 PANELS
M: Guido Günther <agx@sigxcpu.org>
R: Purism Kernel Team <kernel@puri.sm>
-R: Ondrej Jirman <megous@megous.com>
+R: Ondrej Jirman <megi@xff.cz>
S: Maintained
F: Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
F: drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -6774,7 +6846,8 @@ DRM DRIVER FOR SOLOMON SSD130X OLED DISPLAYS
M: Javier Martinez Canillas <javierm@redhat.com>
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
-F: Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
+F: Documentation/devicetree/bindings/display/solomon,ssd-common.yaml
+F: Documentation/devicetree/bindings/display/solomon,ssd13*.yaml
F: drivers/gpu/drm/solomon/ssd130x*
DRM DRIVER FOR ST-ERICSSON MCDE
@@ -6869,12 +6942,26 @@ M: Thomas Zimmermann <tzimmermann@suse.de>
S: Maintained
W: https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html
T: git git://anongit.freedesktop.org/drm/drm-misc
+F: Documentation/devicetree/bindings/display/
+F: Documentation/devicetree/bindings/gpu/
F: Documentation/gpu/
-F: drivers/gpu/drm/*
+F: drivers/gpu/drm/
F: drivers/gpu/vga/
-F: include/drm/drm*
+F: include/drm/drm
F: include/linux/vga*
-F: include/uapi/drm/drm*
+F: include/uapi/drm/
+X: drivers/gpu/drm/amd/
+X: drivers/gpu/drm/armada/
+X: drivers/gpu/drm/etnaviv/
+X: drivers/gpu/drm/exynos/
+X: drivers/gpu/drm/i915/
+X: drivers/gpu/drm/kmb/
+X: drivers/gpu/drm/mediatek/
+X: drivers/gpu/drm/msm/
+X: drivers/gpu/drm/nouveau/
+X: drivers/gpu/drm/radeon/
+X: drivers/gpu/drm/renesas/
+X: drivers/gpu/drm/tegra/
DRM DRIVERS FOR ALLWINNER A10
M: Maxime Ripard <mripard@kernel.org>
@@ -6895,6 +6982,7 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
F: Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml
F: Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
F: Documentation/gpu/meson.rst
+F: drivers/gpu/drm/ci/xfails/meson*
F: drivers/gpu/drm/meson/
DRM DRIVERS FOR ATMEL HLCDC
@@ -6918,7 +7006,9 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
F: Documentation/devicetree/bindings/display/bridge/
F: drivers/gpu/drm/bridge/
F: drivers/gpu/drm/drm_bridge.c
+F: drivers/gpu/drm/drm_bridge_connector.c
F: include/drm/drm_bridge.h
+F: include/drm/drm_bridge_connector.h
DRM DRIVERS FOR EXYNOS
M: Inki Dae <inki.dae@samsung.com>
@@ -6942,10 +7032,12 @@ F: Documentation/devicetree/bindings/display/fsl,dcu.txt
F: Documentation/devicetree/bindings/display/fsl,tcon.txt
F: drivers/gpu/drm/fsl-dcu/
-DRM DRIVERS FOR FREESCALE IMX
+DRM DRIVERS FOR FREESCALE IMX 5/6
M: Philipp Zabel <p.zabel@pengutronix.de>
L: dri-devel@lists.freedesktop.org
S: Maintained
+T: git git://anongit.freedesktop.org/drm/drm-misc
+T: git git://git.pengutronix.de/git/pza/linux
F: Documentation/devicetree/bindings/display/imx/
F: drivers/gpu/drm/imx/ipuv3/
F: drivers/gpu/ipu-v3/
@@ -6964,7 +7056,7 @@ DRM DRIVERS FOR GMA500 (Poulsbo, Moorestown and derivative chipsets)
M: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
-T: git git://github.com/patjak/drm-gma500
+T: git git://anongit.freedesktop.org/drm/drm-misc
F: drivers/gpu/drm/gma500/
DRM DRIVERS FOR HISILICON
@@ -7003,6 +7095,7 @@ L: dri-devel@lists.freedesktop.org
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Supported
F: Documentation/devicetree/bindings/display/mediatek/
+F: drivers/gpu/drm/ci/xfails/mediatek*
F: drivers/gpu/drm/mediatek/
F: drivers/phy/mediatek/phy-mtk-dp.c
F: drivers/phy/mediatek/phy-mtk-hdmi*
@@ -7022,7 +7115,7 @@ F: drivers/gpu/host1x/
F: include/linux/host1x.h
F: include/uapi/drm/tegra_drm.h
-DRM DRIVERS FOR RENESAS
+DRM DRIVERS FOR RENESAS R-CAR
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
L: dri-devel@lists.freedesktop.org
@@ -7033,7 +7126,16 @@ F: Documentation/devicetree/bindings/display/bridge/renesas,dsi-csi2-tx.yaml
F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml
F: Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml
F: Documentation/devicetree/bindings/display/renesas,du.yaml
-F: drivers/gpu/drm/renesas/
+F: drivers/gpu/drm/renesas/rcar-du/
+
+DRM DRIVERS FOR RENESAS SHMOBILE
+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+M: Geert Uytterhoeven <geert+renesas@glider.be>
+L: dri-devel@lists.freedesktop.org
+L: linux-renesas-soc@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/display/renesas,shmobile-lcdc.yaml
+F: drivers/gpu/drm/renesas/shmobile/
F: include/linux/platform_data/shmob_drm.h
DRM DRIVERS FOR ROCKCHIP
@@ -7043,6 +7145,7 @@ L: dri-devel@lists.freedesktop.org
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
F: Documentation/devicetree/bindings/display/rockchip/
+F: drivers/gpu/drm/ci/xfails/rockchip*
F: drivers/gpu/drm/rockchip/
DRM DRIVERS FOR STI
@@ -7139,7 +7242,7 @@ F: Documentation/devicetree/bindings/display/xlnx/
F: drivers/gpu/drm/xlnx/
DRM GPU SCHEDULER
-M: Luben Tuikov <luben.tuikov@amd.com>
+M: Luben Tuikov <ltuikov89@gmail.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
@@ -7148,6 +7251,7 @@ F: include/drm/gpu_scheduler.h
DRM PANEL DRIVERS
M: Neil Armstrong <neil.armstrong@linaro.org>
+R: Jessica Zhang <quic_jesszhan@quicinc.com>
R: Sam Ravnborg <sam@ravnborg.org>
L: dri-devel@lists.freedesktop.org
S: Maintained
@@ -7198,53 +7302,38 @@ T: git git://linuxtv.org/media_tree.git
F: drivers/media/pci/dt3155/
DVB_USB_AF9015 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/af9015*
DVB_USB_AF9035 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/af9035*
DVB_USB_ANYSEE MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/anysee*
DVB_USB_AU6610 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/au6610*
DVB_USB_CE6230 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/ce6230*
DVB_USB_CXUSB MEDIA DRIVER
@@ -7258,22 +7347,17 @@ T: git git://linuxtv.org/media_tree.git
F: drivers/media/usb/dvb-usb/cxusb*
DVB_USB_EC168 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/ec168*
DVB_USB_GL861 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/gl861*
DVB_USB_MXL111SF MEDIA DRIVER
@@ -7287,23 +7371,18 @@ T: git git://linuxtv.org/mkrufky/mxl111sf.git
F: drivers/media/usb/dvb-usb-v2/mxl111sf*
DVB_USB_RTL28XXU MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/rtl28xxu*
DVB_USB_V2 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/dvb_usb*
F: drivers/media/usb/dvb-usb-v2/usb_urb.c
@@ -7345,13 +7424,10 @@ F: Documentation/devicetree/bindings/input/e3x0-button.txt
F: drivers/input/misc/e3x0-button.c
E4000 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/e4000*
EARTH_PT1 MEDIA DRIVER
@@ -7367,13 +7443,10 @@ S: Odd Fixes
F: drivers/media/pci/pt3/
EC100 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/ec100*
ECRYPT FILE SYSTEM
@@ -7733,6 +7806,7 @@ R: Yue Hu <huyue2@coolpad.com>
R: Jeffle Xu <jefflexu@linux.alibaba.com>
L: linux-erofs@lists.ozlabs.org
S: Maintained
+W: https://erofs.docs.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
F: Documentation/ABI/testing/sysfs-fs-erofs
F: Documentation/filesystems/erofs.rst
@@ -7767,7 +7841,7 @@ F: drivers/net/can/usb/etas_es58x/
ETHERNET BRIDGE
M: Roopa Prabhu <roopa@nvidia.com>
M: Nikolay Aleksandrov <razor@blackwall.org>
-L: bridge@lists.linux-foundation.org (moderated for non-subscribers)
+L: bridge@lists.linux.dev
L: netdev@vger.kernel.org
S: Maintained
W: http://www.linuxfoundation.org/en/Net:Bridge
@@ -7990,13 +8064,10 @@ F: drivers/media/tuners/fc0011.c
F: drivers/media/tuners/fc0011.h
FC2580 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/fc2580*
FCOE SUBSYSTEM (libfc, libfcoe, fcoe)
@@ -8043,6 +8114,27 @@ F: include/linux/fs_types.h
F: include/uapi/linux/fs.h
F: include/uapi/linux/openat2.h
+FILESYSTEMS [EXPORTFS]
+M: Chuck Lever <chuck.lever@oracle.com>
+M: Jeff Layton <jlayton@kernel.org>
+R: Amir Goldstein <amir73il@gmail.com>
+L: linux-fsdevel@vger.kernel.org
+L: linux-nfs@vger.kernel.org
+S: Supported
+F: Documentation/filesystems/nfs/exporting.rst
+F: fs/exportfs/
+F: fs/fhandle.c
+F: include/linux/exportfs.h
+
+FILESYSTEMS [IOMAP]
+M: Christian Brauner <brauner@kernel.org>
+R: Darrick J. Wong <djwong@kernel.org>
+L: linux-xfs@vger.kernel.org
+L: linux-fsdevel@vger.kernel.org
+S: Supported
+F: fs/iomap/
+F: include/linux/iomap.h
+
FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
M: Riku Voipio <riku.voipio@iki.fi>
L: linux-hwmon@vger.kernel.org
@@ -8103,7 +8195,7 @@ F: include/linux/arm_ffa.h
FIRMWARE LOADER (request_firmware)
M: Luis Chamberlain <mcgrof@kernel.org>
-M: Russ Weight <russell.h.weight@intel.com>
+M: Russ Weight <russ.weight@linux.dev>
L: linux-kernel@vger.kernel.org
S: Maintained
F: Documentation/firmware_class/
@@ -8134,7 +8226,7 @@ M: Geoffrey D. Bennett <g@b4.vu>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
-F: sound/usb/mixer_scarlett_gen2.c
+F: sound/usb/mixer_scarlett2.c
FORCEDETH GIGABIT ETHERNET DRIVER
M: Rain River <rain.1986.08.12@gmail.com>
@@ -8247,6 +8339,14 @@ F: Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
F: drivers/spi/spi-fsl-dspi.c
F: include/linux/spi/spi-fsl-dspi.h
+FREESCALE eDMA DRIVER
+M: Frank Li <Frank.Li@nxp.com>
+L: imx@lists.linux.dev
+L: dmaengine@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/dma/fsl,edma.yaml
+F: drivers/dma/fsl-edma*.*
+
FREESCALE ENETC ETHERNET DRIVERS
M: Claudiu Manoil <claudiu.manoil@nxp.com>
M: Vladimir Oltean <vladimir.oltean@nxp.com>
@@ -8625,6 +8725,8 @@ L: linux-hardening@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
F: Documentation/kbuild/gcc-plugins.rst
+F: include/linux/stackleak.h
+F: kernel/stackleak.c
F: scripts/Makefile.gcc-plugins
F: scripts/gcc-plugins/
@@ -8721,6 +8823,7 @@ F: include/linux/phy/
GENERIC PINCTRL I2C DEMULTIPLEXER DRIVER
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
S: Supported
+F: Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml
F: drivers/i2c/muxes/i2c-demux-pinctrl.c
GENERIC PM DOMAINS
@@ -8740,6 +8843,13 @@ S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm.git
F: drivers/pmdomain/
+GENERIC RADIX TREE
+M: Kent Overstreet <kent.overstreet@linux.dev>
+S: Supported
+C: irc://irc.oftc.net/bcache
+F: include/linux/generic-radix-tree.h
+F: lib/generic-radix-tree.c
+
GENERIC RESISTIVE TOUCHSCREEN ADC DRIVER
M: Eugen Hristev <eugen.hristev@microchip.com>
L: linux-input@vger.kernel.org
@@ -8789,7 +8899,6 @@ S: Maintained
F: scripts/get_maintainer.pl
GFS2 FILE SYSTEM
-M: Bob Peterson <rpeterso@redhat.com>
M: Andreas Gruenbacher <agruenba@redhat.com>
L: gfs2@lists.linux.dev
S: Supported
@@ -8980,6 +9089,13 @@ F: drivers/staging/greybus/sdio.c
F: drivers/staging/greybus/spi.c
F: drivers/staging/greybus/spilib.c
+GREYBUS BEAGLEPLAY DRIVERS
+M: Ayush Singh <ayushdevel1325@gmail.com>
+L: greybus-dev@lists.linaro.org (moderated for non-subscribers)
+S: Maintained
+F: Documentation/devicetree/bindings/net/ti,cc1352p7.yaml
+F: drivers/greybus/gb-beagleplay.c
+
GREYBUS SUBSYSTEM
M: Johan Hovold <johan@kernel.org>
M: Alex Elder <elder@kernel.org>
@@ -9076,17 +9192,15 @@ T: git https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/linux.git
F: Documentation/ABI/testing/debugfs-driver-habanalabs
F: Documentation/ABI/testing/sysfs-driver-habanalabs
F: drivers/accel/habanalabs/
+F: include/linux/habanalabs/
F: include/trace/events/habanalabs.h
F: include/uapi/drm/habanalabs_accel.h
HACKRF MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/hackrf/
HANDSHAKE UPCALL FOR TRANSPORT LAYER SECURITY
@@ -9459,6 +9573,7 @@ F: drivers/crypto/hisilicon/sgl.c
F: include/linux/hisi_acc_qm.h
HISILICON ROCE DRIVER
+M: Chengchang Tang <tangchengchang@huawei.com>
M: Junxian Huang <huangjunxian6@hisilicon.com>
L: linux-rdma@vger.kernel.org
S: Maintained
@@ -9660,6 +9775,7 @@ F: include/linux/hugetlb.h
F: mm/hugetlb.c
F: mm/hugetlb_vmemmap.c
F: mm/hugetlb_vmemmap.h
+F: tools/testing/selftests/cgroup/test_hugetlb_memcg.c
HVA ST MEDIA DRIVER
M: Jean-Christophe Trotin <jean-christophe.trotin@foss.st.com>
@@ -9942,12 +10058,6 @@ F: Documentation/driver-api/i3c
F: drivers/i3c/
F: include/linux/i3c/
-IA64 (Itanium) PLATFORM
-L: linux-ia64@vger.kernel.org
-S: Orphan
-F: Documentation/arch/ia64/
-F: arch/ia64/
-
IBM Operation Panel Input Driver
M: Eddie James <eajames@linux.ibm.com>
L: linux-input@vger.kernel.org
@@ -10443,7 +10553,6 @@ F: drivers/platform/x86/intel/atomisp2/led.c
INTEL BIOS SAR INT1092 DRIVER
M: Shravan Sudhakar <s.shravan@intel.com>
-M: Intel Corporation <linuxwwan@intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/intel/int1092/
@@ -10483,6 +10592,7 @@ C: irc://irc.oftc.net/intel-gfx
T: git git://anongit.freedesktop.org/drm-intel
F: Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
F: Documentation/gpu/i915.rst
+F: drivers/gpu/drm/ci/xfails/i915*
F: drivers/gpu/drm/i915/
F: include/drm/i915*
F: include/uapi/drm/i915_drm.h
@@ -10630,22 +10740,6 @@ L: linux-crypto@vger.kernel.org
S: Maintained
F: drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
-INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT
-M: Krzysztof Halasa <khalasa@piap.pl>
-S: Maintained
-F: drivers/net/ethernet/xscale/ixp4xx_eth.c
-F: drivers/net/wan/ixp4xx_hss.c
-F: drivers/soc/ixp4xx/ixp4xx-npe.c
-F: drivers/soc/ixp4xx/ixp4xx-qmgr.c
-F: include/linux/soc/ixp4xx/npe.h
-F: include/linux/soc/ixp4xx/qmgr.h
-
-INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
-M: Deepak Saxena <dsaxena@plexity.net>
-S: Maintained
-F: Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml
-F: drivers/char/hw_random/ixp4xx-rng.c
-
INTEL KEEM BAY DRM DRIVER
M: Anitha Chrisanthus <anitha.chrisanthus@intel.com>
M: Edmund Dea <edmund.j.dea@intel.com>
@@ -10709,7 +10803,7 @@ F: drivers/mfd/intel-m10-bmc*
F: include/linux/mfd/intel-m10-bmc.h
INTEL MAX10 BMC SECURE UPDATES
-M: Russ Weight <russell.h.weight@intel.com>
+M: Peter Colberg <peter.colberg@intel.com>
L: linux-fpga@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
@@ -10877,7 +10971,6 @@ F: drivers/net/wireless/intel/iwlwifi/
INTEL WMI SLIM BOOTLOADER (SBL) FIRMWARE UPDATE DRIVER
M: Jithu Joseph <jithu.joseph@intel.com>
-R: Maurice Ma <maurice.ma@intel.com>
S: Maintained
W: https://slimbootloader.github.io/security/firmware-update.html
F: drivers/platform/x86/intel/wmi/sbl-fw-update.c
@@ -10889,7 +10982,6 @@ F: drivers/platform/x86/intel/wmi/thunderbolt.c
INTEL WWAN IOSM DRIVER
M: M Chetan Kumar <m.chetan.kumar@intel.com>
-M: Intel Corporation <linuxwwan@intel.com>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/wwan/iosm/
@@ -10959,15 +11051,6 @@ L: linux-mips@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/sgi/ioc3-eth.c
-IOMAP FILESYSTEM LIBRARY
-M: Darrick J. Wong <djwong@kernel.org>
-L: linux-xfs@vger.kernel.org
-L: linux-fsdevel@vger.kernel.org
-S: Supported
-T: git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
-F: fs/iomap/
-F: include/linux/iomap.h
-
IOMMU DMA-API LAYER
M: Robin Murphy <robin.murphy@arm.com>
L: iommu@lists.linux.dev
@@ -11150,7 +11233,6 @@ M: Sagi Grimberg <sagi@grimberg.me>
L: linux-rdma@vger.kernel.org
L: target-devel@vger.kernel.org
S: Supported
-W: http://www.linux-iscsi.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git master
F: drivers/infiniband/ulp/isert
@@ -11192,13 +11274,10 @@ F: Documentation/hwmon/it87.rst
F: drivers/hwmon/it87.c
IT913X MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/it913x*
ITE IT66121 HDMI BRIDGE DRIVER
@@ -11380,7 +11459,6 @@ F: fs/autofs/
KERNEL BUILD + files below scripts/ (unless maintained elsewhere)
M: Masahiro Yamada <masahiroy@kernel.org>
R: Nathan Chancellor <nathan@kernel.org>
-R: Nick Desaulniers <ndesaulniers@google.com>
R: Nicolas Schier <nicolas@fjasle.eu>
L: linux-kbuild@vger.kernel.org
S: Maintained
@@ -11400,16 +11478,20 @@ F: usr/
KERNEL HARDENING (not covered by other areas)
M: Kees Cook <keescook@chromium.org>
+R: Gustavo A. R. Silva <gustavoars@kernel.org>
L: linux-hardening@vger.kernel.org
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
F: Documentation/ABI/testing/sysfs-kernel-oops_count
F: Documentation/ABI/testing/sysfs-kernel-warn_count
+F: arch/*/configs/hardening.config
F: include/linux/overflow.h
F: include/linux/randomize_kstack.h
+F: kernel/configs/hardening.config
F: mm/usercopy.c
K: \b(add|choose)_random_kstack_offset\b
K: \b__check_(object_size|heap_object)\b
+K: \b__counted_by\b
KERNEL JANITORS
L: kernel-janitors@vger.kernel.org
@@ -11428,7 +11510,6 @@ S: Supported
W: http://nfs.sourceforge.net/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux.git
F: Documentation/filesystems/nfs/
-F: fs/exportfs/
F: fs/lockd/
F: fs/nfs_common/
F: fs/nfsd/
@@ -11530,6 +11611,18 @@ F: include/kvm/arm_*
F: tools/testing/selftests/kvm/*/aarch64/
F: tools/testing/selftests/kvm/aarch64/
+KERNEL VIRTUAL MACHINE FOR LOONGARCH (KVM/LoongArch)
+M: Tianrui Zhao <zhaotianrui@loongson.cn>
+M: Bibo Mao <maobibo@loongson.cn>
+M: Huacai Chen <chenhuacai@kernel.org>
+L: kvm@vger.kernel.org
+L: loongarch@lists.linux.dev
+S: Maintained
+T: git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
+F: arch/loongarch/include/asm/kvm*
+F: arch/loongarch/include/uapi/asm/kvm*
+F: arch/loongarch/kvm/
+
KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
M: Huacai Chen <chenhuacai@kernel.org>
L: linux-mips@vger.kernel.org
@@ -11566,6 +11659,7 @@ F: arch/riscv/include/asm/kvm*
F: arch/riscv/include/uapi/asm/kvm*
F: arch/riscv/kvm/
F: tools/testing/selftests/kvm/*/riscv/
+F: tools/testing/selftests/kvm/riscv/
KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
M: Christian Borntraeger <borntraeger@linux.ibm.com>
@@ -11902,12 +11996,6 @@ F: drivers/leds/
F: include/dt-bindings/leds/
F: include/linux/leds.h
-LEGACY EEPROM DRIVER
-M: Jean Delvare <jdelvare@suse.com>
-S: Maintained
-F: Documentation/misc-devices/eeprom.rst
-F: drivers/misc/eeprom/eeprom.c
-
LEGO MINDSTORMS EV3
R: David Lechner <david@lechnology.com>
S: Maintained
@@ -12062,6 +12150,13 @@ F: include/linux/nd.h
F: include/uapi/linux/ndctl.h
F: tools/testing/nvdimm/
+LIBRARY CODE
+M: Andrew Morton <akpm@linux-foundation.org>
+L: linux-kernel@vger.kernel.org
+S: Supported
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-nonmm-unstable
+F: lib/*
+
LICENSES and SPDX stuff
M: Thomas Gleixner <tglx@linutronix.de>
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -12094,6 +12189,8 @@ LINUX FOR POWERPC (32-BIT AND 64-BIT)
M: Michael Ellerman <mpe@ellerman.id.au>
R: Nicholas Piggin <npiggin@gmail.com>
R: Christophe Leroy <christophe.leroy@csgroup.eu>
+R: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
+R: Naveen N. Rao <naveen.n.rao@linux.ibm.com>
L: linuxppc-dev@lists.ozlabs.org
S: Supported
W: https://github.com/linuxppc/wiki/wiki
@@ -12103,7 +12200,7 @@ F: Documentation/ABI/stable/sysfs-firmware-opal-*
F: Documentation/devicetree/bindings/i2c/i2c-opal.txt
F: Documentation/devicetree/bindings/powerpc/
F: Documentation/devicetree/bindings/rtc/rtc-opal.txt
-F: Documentation/powerpc/
+F: Documentation/arch/powerpc/
F: arch/powerpc/
F: drivers/*/*/*pasemi*
F: drivers/*/*pasemi*
@@ -12459,6 +12556,14 @@ F: drivers/hwmon/ltc2947-i2c.c
F: drivers/hwmon/ltc2947-spi.c
F: drivers/hwmon/ltc2947.h
+LTC2991 HARDWARE MONITOR DRIVER
+M: Antoniu Miclaus <antoniu.miclaus@analog.com>
+L: linux-hwmon@vger.kernel.org
+S: Supported
+W: https://ez.analog.com/linux-software-drivers
+F: Documentation/devicetree/bindings/hwmon/adi,ltc2991.yaml
+F: drivers/hwmon/ltc2991.c
+
LTC2983 IIO TEMPERATURE DRIVER
M: Nuno Sá <nuno.sa@analog.com>
L: linux-iio@vger.kernel.org
@@ -12533,13 +12638,10 @@ W: http://www.tazenda.demon.co.uk/phil/linux-hp
F: arch/m68k/hp300/
M88DS3103 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/m88ds3103*
M88RS2000 MEDIA DRIVER
@@ -12826,7 +12928,7 @@ MAX31827 TEMPERATURE SWITCH DRIVER
M: Daniel Matyas <daniel.matyas@analog.com>
L: linux-hwmon@vger.kernel.org
S: Supported
-W: http://ez.analog.com/community/linux-device-drivers
+W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/hwmon/adi,max31827.yaml
F: Documentation/hwmon/max31827.rst
F: drivers/hwmon/max31827.c
@@ -13510,7 +13612,6 @@ F: net/dsa/tag_mtk.c
MEDIATEK T7XX 5G WWAN MODEM DRIVER
M: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
-M: Intel Corporation <linuxwwan@intel.com>
R: Chiranjeevi Rapolu <chiranjeevi.rapolu@linux.intel.com>
R: Liu Haijun <haijun.liu@mediatek.com>
R: M Chetan Kumar <m.chetan.kumar@linux.intel.com>
@@ -13531,7 +13632,7 @@ F: drivers/usb/mtu3/
MEGACHIPS STDPXXXX-GE-B850V3-FW LVDS/DP++ BRIDGES
M: Peter Senna Tschudin <peter.senna@gmail.com>
-M: Martin Donnelly <martin.donnelly@ge.com>
+M: Ian Ray <ian.ray@ge.com>
M: Martyn Welch <martyn.welch@collabora.co.uk>
S: Maintained
F: Documentation/devicetree/bindings/display/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt
@@ -13541,6 +13642,7 @@ MEGARAID SCSI/SAS DRIVERS
M: Kashyap Desai <kashyap.desai@broadcom.com>
M: Sumit Saxena <sumit.saxena@broadcom.com>
M: Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
+M: Chandrakanth patil <chandrakanth.patil@broadcom.com>
L: megaraidlinux.pdl@broadcom.com
L: linux-scsi@vger.kernel.org
S: Maintained
@@ -13624,7 +13726,6 @@ F: drivers/net/ethernet/mellanox/mlxfw/
MELLANOX HARDWARE PLATFORM SUPPORT
M: Hans de Goede <hdegoede@redhat.com>
M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
-M: Mark Gross <markgross@kernel.org>
M: Vadim Pasternak <vadimp@nvidia.com>
L: platform-driver-x86@vger.kernel.org
S: Supported
@@ -13674,6 +13775,12 @@ F: drivers/infiniband/hw/mlx5/
F: include/linux/mlx5/
F: include/uapi/rdma/mlx5-abi.h
+MELLANOX MLX5 VDPA DRIVER
+M: Dragos Tatulea <dtatulea@nvidia.com>
+L: virtualization@lists.linux-foundation.org
+S: Supported
+F: drivers/vdpa/mlx5/
+
MELLANOX MLXCPLD I2C AND MUX DRIVER
M: Vadim Pasternak <vadimp@nvidia.com>
M: Michael Shych <michaelsh@nvidia.com>
@@ -13854,9 +13961,10 @@ F: Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml
F: drivers/staging/media/meson/vdec/
METHODE UDPU SUPPORT
-M: Vladimir Vid <vladimir.vid@sartura.hr>
+M: Robert Marko <robert.marko@sartura.hr>
S: Maintained
-F: arch/arm64/boot/dts/marvell/armada-3720-uDPU.dts
+F: arch/arm64/boot/dts/marvell/armada-3720-eDPU.dts
+F: arch/arm64/boot/dts/marvell/armada-3720-uDPU.*
MHI BUS
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
@@ -14026,6 +14134,13 @@ S: Supported
F: Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt
F: drivers/regulator/mcp16502.c
+MICROCHIP MCP3564 ADC DRIVER
+M: Marius Cristea <marius.cristea@microchip.com>
+L: linux-iio@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml
+F: drivers/iio/adc/mcp3564.c
+
MICROCHIP MCP3911 ADC DRIVER
M: Marcus Folkesson <marcus.folkesson@gmail.com>
M: Kent Gustavsson <kent@minoris.se>
@@ -14035,7 +14150,7 @@ F: Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml
F: drivers/iio/adc/mcp3911.c
MICROCHIP MMC/SD/SDIO MCI DRIVER
-M: Ludovic Desroches <ludovic.desroches@microchip.com>
+M: Aubin Constans <aubin.constans@microchip.com>
S: Maintained
F: drivers/mmc/host/atmel-mci.c
@@ -14219,7 +14334,6 @@ F: drivers/platform/surface/surface_gpe.c
MICROSOFT SURFACE HARDWARE PLATFORM SUPPORT
M: Hans de Goede <hdegoede@redhat.com>
M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
-M: Mark Gross <markgross@kernel.org>
M: Maximilian Luz <luzmaximilian@gmail.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
@@ -14354,9 +14468,11 @@ MIPS/LOONGSON1 ARCHITECTURE
M: Keguang Zhang <keguang.zhang@gmail.com>
L: linux-mips@vger.kernel.org
S: Maintained
+F: Documentation/devicetree/bindings/*/loongson,ls1*.yaml
F: arch/mips/include/asm/mach-loongson32/
F: arch/mips/loongson32/
F: drivers/*/*loongson1*
+F: drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
MIPS/LOONGSON2EF ARCHITECTURE
M: Jiaxun Yang <jiaxun.yang@flygoat.com>
@@ -14384,6 +14500,11 @@ W: https://linuxtv.org
T: git git://linuxtv.org/media_tree.git
F: drivers/media/radio/radio-miropcm20*
+MITSUMI MM8013 FG DRIVER
+M: Konrad Dybcio <konradybcio@kernel.org>
+F: Documentation/devicetree/bindings/power/supply/mitsumi,mm8013.yaml
+F: drivers/power/supply/mm8013.c
+
MMP SUPPORT
R: Lubomir Rintel <lkundrak@v3.sk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -14414,20 +14535,16 @@ F: include/asm-generic/tlb.h
F: mm/mmu_gather.c
MN88472 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/dvb-frontends/mn88472*
MN88473 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/dvb-frontends/mn88473*
@@ -14438,7 +14555,7 @@ L: linux-kernel@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git modules-next
F: include/linux/kmod.h
-F: include/linux/module.h
+F: include/linux/module*.h
F: kernel/module/
F: lib/test_kmod.c
F: scripts/module*
@@ -14515,23 +14632,17 @@ S: Orphan
F: drivers/platform/x86/msi-wmi.c
MSI001 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/msi001*
MSI2500 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/msi2500/
MSTAR INTERRUPT CONTROLLER DRIVER
@@ -14547,6 +14658,14 @@ L: linux-mtd@lists.infradead.org
S: Maintained
F: drivers/mtd/devices/docg3*
+MT9M114 ONSEMI SENSOR DRIVER
+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+T: git git://linuxtv.org/media_tree.git
+F: Documentation/devicetree/bindings/media/i2c/onnn,mt9m114.yaml
+F: drivers/media/i2c/mt9m114.c
+
MT9P031 APTINA CAMERA SENSOR
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
@@ -14811,6 +14930,7 @@ M: Jakub Kicinski <kuba@kernel.org>
M: Paolo Abeni <pabeni@redhat.com>
L: netdev@vger.kernel.org
S: Maintained
+P: Documentation/process/maintainer-netdev.rst
Q: https://patchwork.kernel.org/project/netdevbpf/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
@@ -14862,6 +14982,7 @@ M: Jakub Kicinski <kuba@kernel.org>
M: Paolo Abeni <pabeni@redhat.com>
L: netdev@vger.kernel.org
S: Maintained
+P: Documentation/process/maintainer-netdev.rst
Q: https://patchwork.kernel.org/project/netdevbpf/list/
B: mailto:netdev@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
@@ -14872,6 +14993,7 @@ F: Documentation/networking/
F: Documentation/process/maintainer-netdev.rst
F: Documentation/userspace-api/netlink/
F: include/linux/in.h
+F: include/linux/indirect_call_wrapper.h
F: include/linux/net.h
F: include/linux/netdevice.h
F: include/net/
@@ -14884,6 +15006,7 @@ F: lib/random32.c
F: net/
F: tools/net/
F: tools/testing/selftests/net/
+X: net/9p/
X: net/bluetooth/
NETWORKING [IPSEC]
@@ -14963,10 +15086,11 @@ W: https://github.com/multipath-tcp/mptcp_net-next/wiki
B: https://github.com/multipath-tcp/mptcp_net-next/issues
T: git https://github.com/multipath-tcp/mptcp_net-next.git export-net
T: git https://github.com/multipath-tcp/mptcp_net-next.git export
+F: Documentation/netlink/specs/mptcp.yaml
F: Documentation/networking/mptcp-sysctl.rst
F: include/net/mptcp.h
F: include/trace/events/mptcp.h
-F: include/uapi/linux/mptcp.h
+F: include/uapi/linux/mptcp*.h
F: net/mptcp/
F: tools/testing/selftests/bpf/*/*mptcp*.c
F: tools/testing/selftests/net/mptcp/
@@ -15139,7 +15263,7 @@ NOLIBC HEADER FILE
M: Willy Tarreau <w@1wt.eu>
M: Thomas Weißschuh <linux@weissschuh.net>
S: Maintained
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc.git
F: tools/include/nolibc/
F: tools/testing/selftests/nolibc/
@@ -15359,6 +15483,7 @@ M: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
R: Lucas Stach <l.stach@pengutronix.de>
L: dri-devel@lists.freedesktop.org
S: Maintained
+T: git git://anongit.freedesktop.org/drm/drm-misc
F: Documentation/devicetree/bindings/display/imx/nxp,imx8mq-dcss.yaml
F: drivers/gpu/drm/imx/dcss/
@@ -15431,7 +15556,7 @@ NXP TFA9879 DRIVER
M: Peter Rosin <peda@axentia.se>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
-F: Documentation/devicetree/bindings/sound/tfa9879.txt
+F: Documentation/devicetree/bindings/sound/nxp,tfa9879.yaml
F: sound/soc/codecs/tfa9879*
NXP-NCI NFC DRIVER
@@ -15468,6 +15593,13 @@ F: include/linux/objagg.h
F: lib/objagg.c
F: lib/test_objagg.c
+OBJPOOL
+M: Matt Wu <wuqiang.matt@bytedance.com>
+S: Supported
+F: include/linux/objpool.h
+F: lib/objpool.c
+F: lib/test_objpool.c
+
OBJTOOL
M: Josh Poimboeuf <jpoimboe@kernel.org>
M: Peter Zijlstra <peterz@infradead.org>
@@ -15780,7 +15912,7 @@ L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml
-F: drivers/media/i2c/ov5647.c
+F: drivers/media/i2c/ov4689.c
OMNIVISION OV5640 SENSOR DRIVER
M: Steve Longerbeam <slongerbeam@gmail.com>
@@ -15870,8 +16002,7 @@ F: Documentation/devicetree/bindings/media/i2c/ovti,ov8858.yaml
F: drivers/media/i2c/ov8858.c
OMNIVISION OV9282 SENSOR DRIVER
-M: Paul J. Murphy <paul.j.murphy@intel.com>
-M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
+M: Dave Stevenson <dave.stevenson@raspberrypi.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
@@ -15979,6 +16110,7 @@ F: Documentation/ABI/testing/sysfs-firmware-ofw
F: drivers/of/
F: include/linux/of*.h
F: scripts/dtc/
+F: tools/testing/selftests/dt/
K: of_overlay_notifier_
K: of_overlay_fdt_apply
K: of_overlay_remove
@@ -16201,7 +16333,7 @@ M: Juergen Gross <jgross@suse.com>
R: Ajay Kaher <akaher@vmware.com>
R: Alexey Makhalov <amakhalov@vmware.com>
R: VMware PV-Drivers Reviewers <pv-drivers@vmware.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
L: x86@kernel.org
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
@@ -16277,11 +16409,6 @@ L: linux-i2c@vger.kernel.org
S: Maintained
F: drivers/i2c/muxes/i2c-mux-pca9541.c
-PCDP - PRIMARY CONSOLE AND DEBUG PORT
-M: Khalid Aziz <khalid@gonehiking.org>
-S: Maintained
-F: drivers/firmware/pcdp.*
-
PCI DRIVER FOR AARDVARK (Marvell Armada 3700)
M: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
M: Pali Rohár <pali@kernel.org>
@@ -16432,6 +16559,7 @@ L: linux-renesas-soc@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/*rcar*
F: drivers/pci/controller/*rcar*
+F: drivers/pci/controller/dwc/*rcar*
PCI DRIVER FOR SAMSUNG EXYNOS
M: Jingoo Han <jingoohan1@gmail.com>
@@ -16499,7 +16627,7 @@ R: Oliver O'Halloran <oohall@gmail.com>
L: linuxppc-dev@lists.ozlabs.org
S: Supported
F: Documentation/PCI/pci-error-recovery.rst
-F: Documentation/powerpc/eeh-pci-error-recovery.rst
+F: Documentation/arch/powerpc/eeh-pci-error-recovery.rst
F: arch/powerpc/include/*/eeh*.h
F: arch/powerpc/kernel/eeh*.c
F: arch/powerpc/platforms/*/eeh*.c
@@ -17548,15 +17676,6 @@ L: netdev@vger.kernel.org
S: Supported
F: drivers/net/ethernet/qlogic/qlcnic/
-QLOGIC QLGE 10Gb ETHERNET DRIVER
-M: Manish Chopra <manishc@marvell.com>
-M: GR-Linux-NIC-Dev@marvell.com
-M: Coiby Xu <coiby.xu@gmail.com>
-L: netdev@vger.kernel.org
-S: Supported
-F: Documentation/networking/device_drivers/qlogic/qlge.rst
-F: drivers/staging/qlge/
-
QM1D1B0004 MEDIA DRIVER
M: Akihiro Tsukada <tskd08@gmail.com>
L: linux-media@vger.kernel.org
@@ -17595,13 +17714,10 @@ F: drivers/bus/fsl-mc/
F: include/uapi/linux/fsl_mc.h
QT1010 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/qt1010*
QUALCOMM ATH12K WIRELESS DRIVER
@@ -17768,6 +17884,8 @@ L: iommu@lists.linux.dev
L: linux-arm-msm@vger.kernel.org
S: Maintained
F: drivers/iommu/arm/arm-smmu/qcom_iommu.c
+F: drivers/iommu/arm/arm-smmu/arm-smmu-qcom*
+F: drivers/iommu/msm_iommu*
QUALCOMM IPC ROUTER (QRTR) DRIVER
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
@@ -17809,6 +17927,18 @@ S: Maintained
F: Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
F: drivers/mtd/nand/raw/qcom_nandc.c
+QUALCOMM QSEECOM DRIVER
+M: Maximilian Luz <luzmaximilian@gmail.com>
+L: linux-arm-msm@vger.kernel.org
+S: Maintained
+F: drivers/firmware/qcom/qcom_qseecom.c
+
+QUALCOMM QSEECOM UEFISECAPP DRIVER
+M: Maximilian Luz <luzmaximilian@gmail.com>
+L: linux-arm-msm@vger.kernel.org
+S: Maintained
+F: drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
+
QUALCOMM RMNET DRIVER
M: Subash Abhinov Kasiviswanathan <quic_subashab@quicinc.com>
M: Sean Tranchetti <quic_stranche@quicinc.com>
@@ -17871,6 +18001,7 @@ C: irc://irc.oftc.net/radeon
T: git https://gitlab.freedesktop.org/agd5f/linux.git
F: Documentation/gpu/amdgpu/
F: drivers/gpu/drm/amd/
+F: drivers/gpu/drm/ci/xfails/amd*
F: drivers/gpu/drm/radeon/
F: include/uapi/drm/amdgpu_drm.h
F: include/uapi/drm/radeon_drm.h
@@ -17935,7 +18066,6 @@ F: arch/mips/boot/dts/ralink/mt7621*
RALINK RT2X00 WIRELESS LAN DRIVER
M: Stanislaw Gruszka <stf_xl@wp.pl>
-M: Helmut Schaa <helmut.schaa@googlemail.com>
L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/net/wireless/ralink/rt2x00/
@@ -18425,7 +18555,7 @@ L: linux-riscv@lists.infradead.org
S: Supported
Q: https://patchwork.kernel.org/project/linux-riscv/list/
C: irc://irc.libera.chat/riscv
-P: Documentation/riscv/patch-acceptance.rst
+P: Documentation/arch/riscv/patch-acceptance.rst
T: git git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git
F: arch/riscv/
N: riscv
@@ -18520,6 +18650,7 @@ F: sound/soc/rockchip/rockchip_i2s_tdm.*
ROCKCHIP ISP V1 DRIVER
M: Dafna Hirschfeld <dafna@fastmail.com>
+M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
L: linux-rockchip@lists.infradead.org
S: Maintained
@@ -18570,6 +18701,12 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/light/bh1750.yaml
F: drivers/iio/light/bh1750.c
+ROHM BM1390 PRESSURE SENSOR DRIVER
+M: Matti Vaittinen <mazziesaccount@gmail.com>
+L: linux-iio@vger.kernel.org
+S: Supported
+F: drivers/iio/pressure/rohm-bm1390.c
+
ROHM BU270xx LIGHT SENSOR DRIVERs
M: Matti Vaittinen <mazziesaccount@gmail.com>
L: linux-iio@vger.kernel.org
@@ -18635,33 +18772,24 @@ S: Maintained
F: drivers/tty/rpmsg_tty.c
RTL2830 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/rtl2830*
RTL2832 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/rtl2832*
RTL2832_SDR MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/rtl2832_sdr*
RTL8180 WIRELESS DRIVER
@@ -18712,9 +18840,10 @@ R: Andreas Hindborg <a.hindborg@samsung.com>
R: Alice Ryhl <aliceryhl@google.com>
L: rust-for-linux@vger.kernel.org
S: Supported
-W: https://github.com/Rust-for-Linux/linux
+W: https://rust-for-linux.com
B: https://github.com/Rust-for-Linux/linux/issues
C: zulip://rust-for-linux.zulipchat.com
+P: https://rust-for-linux.com/contributing
T: git https://github.com/Rust-for-Linux/linux.git rust-next
F: Documentation/rust/
F: rust/
@@ -19166,7 +19295,6 @@ M: "Martin K. Petersen" <martin.petersen@oracle.com>
L: linux-scsi@vger.kernel.org
L: target-devel@vger.kernel.org
S: Supported
-W: http://www.linux-iscsi.org
Q: https://patchwork.kernel.org/project/target-devel/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
F: Documentation/target/
@@ -19249,7 +19377,8 @@ F: Documentation/devicetree/bindings/mmc/sdhci-common.yaml
F: drivers/mmc/host/sdhci*
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) MICROCHIP DRIVER
-M: Eugen Hristev <eugen.hristev@microchip.com>
+M: Aubin Constans <aubin.constans@microchip.com>
+R: Eugen Hristev <eugen.hristev@collabora.com>
L: linux-mmc@vger.kernel.org
S: Supported
F: drivers/mmc/host/sdhci-of-at91.c
@@ -19406,6 +19535,7 @@ F: drivers/net/ethernet/sfc/
SFCTEMP HWMON DRIVER
M: Emil Renner Berthing <kernel@esmil.dk>
+M: Hal Feng <hal.feng@starfivetech.com>
L: linux-hwmon@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/hwmon/starfive,jh71x0-temp.yaml
@@ -19436,7 +19566,6 @@ S: Maintained
F: drivers/misc/sgi-xp/
SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS
-M: Karsten Graul <kgraul@linux.ibm.com>
M: Wenjia Zhang <wenjia@linux.ibm.com>
M: Jan Karcher <jaka@linux.ibm.com>
R: D. Wythe <alibuda@linux.alibaba.com>
@@ -19469,13 +19598,10 @@ F: drivers/media/platform/renesas/sh_vou.c
F: include/media/drv-intf/sh_vou.h
SI2157 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/si2157*
SI2165 MEDIA DRIVER
@@ -19487,13 +19613,10 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/dvb-frontends/si2165*
SI2168 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/si2168*
SI470X FM RADIO RECEIVER I2C DRIVER
@@ -20006,19 +20129,15 @@ T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/imx319.c
SONY IMX334 SENSOR DRIVER
-M: Paul J. Murphy <paul.j.murphy@intel.com>
-M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
F: drivers/media/i2c/imx334.c
SONY IMX335 SENSOR DRIVER
-M: Paul J. Murphy <paul.j.murphy@intel.com>
-M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
F: drivers/media/i2c/imx335.c
@@ -20031,10 +20150,8 @@ T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/imx355.c
SONY IMX412 SENSOR DRIVER
-M: Paul J. Murphy <paul.j.murphy@intel.com>
-M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
F: drivers/media/i2c/imx412.c
@@ -20067,10 +20184,17 @@ F: drivers/char/sonypi.c
F: drivers/platform/x86/sony-laptop.c
F: include/linux/sony-laptop.h
+SOPHGO DEVICETREES
+M: Chao Wei <chao.wei@sophgo.com>
+M: Chen Wang <unicorn_wang@outlook.com>
+S: Maintained
+F: arch/riscv/boot/dts/sophgo/
+F: Documentation/devicetree/bindings/riscv/sophgo.yaml
+
SOUND
M: Jaroslav Kysela <perex@perex.cz>
M: Takashi Iwai <tiwai@suse.com>
-L: alsa-devel@alsa-project.org (moderated for non-subscribers)
+L: linux-sound@vger.kernel.org
S: Maintained
W: http://www.alsa-project.org/
Q: http://patchwork.kernel.org/project/alsa-devel/list/
@@ -20083,7 +20207,7 @@ F: tools/testing/selftests/alsa
SOUND - ALSA SELFTESTS
M: Mark Brown <broonie@kernel.org>
-L: alsa-devel@alsa-project.org (moderated for non-subscribers)
+L: linux-sound@vger.kernel.org
L: linux-kselftest@vger.kernel.org
S: Supported
F: tools/testing/selftests/alsa
@@ -20109,7 +20233,7 @@ F: sound/soc/soc-generic-dmaengine-pcm.c
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
M: Liam Girdwood <lgirdwood@gmail.com>
M: Mark Brown <broonie@kernel.org>
-L: alsa-devel@alsa-project.org (moderated for non-subscribers)
+L: linux-sound@vger.kernel.org
S: Supported
W: http://alsa-project.org/main/index.php/ASoC
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
@@ -20117,6 +20241,10 @@ F: Documentation/devicetree/bindings/sound/
F: Documentation/sound/soc/
F: include/dt-bindings/sound/
F: include/sound/soc*
+F: include/sound/sof.h
+F: include/sound/sof/
+F: include/trace/events/sof*.h
+F: include/uapi/sound/asoc.h
F: sound/soc/
SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS
@@ -20470,6 +20598,13 @@ S: Supported
F: Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml
F: drivers/clk/starfive/clk-starfive-jh7110-pll.c
+STARFIVE JH7110 PWMDAC DRIVER
+M: Hal Feng <hal.feng@starfivetech.com>
+M: Xingyu Wu <xingyu.wu@starfivetech.com>
+S: Supported
+F: Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml
+F: sound/soc/starfive/jh7110_pwmdac.c
+
STARFIVE JH7110 SYSCON
M: William Qiu <william.qiu@starfivetech.com>
M: Xingyu Wu <xingyu.wu@starfivetech.com>
@@ -20493,6 +20628,7 @@ F: include/dt-bindings/clock/starfive?jh71*.h
STARFIVE JH71X0 PINCTRL DRIVERS
M: Emil Renner Berthing <kernel@esmil.dk>
M: Jianlong Huang <jianlong.huang@starfivetech.com>
+M: Hal Feng <hal.feng@starfivetech.com>
L: linux-gpio@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pinctrl/starfive,jh71*.yaml
@@ -20516,9 +20652,10 @@ F: drivers/usb/cdns3/cdns3-starfive.c
STARFIVE JH71XX PMU CONTROLLER DRIVER
M: Walker Chen <walker.chen@starfivetech.com>
+M: Changhuang Liang <changhuang.liang@starfivetech.com>
S: Supported
F: Documentation/devicetree/bindings/power/starfive*
-F: drivers/pmdomain/starfive/jh71xx-pmu.c
+F: drivers/pmdomain/starfive/
F: include/dt-bindings/power/starfive,jh7110-pmu.h
STARFIVE SOC DRIVERS
@@ -20526,7 +20663,6 @@ M: Conor Dooley <conor@kernel.org>
S: Maintained
T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
F: Documentation/devicetree/bindings/soc/starfive/
-F: drivers/soc/starfive/
STARFIVE TRNG DRIVER
M: Jia Jie Ho <jiajie.ho@starfivetech.com>
@@ -20907,6 +21043,7 @@ F: drivers/clk/clk-sc[mp]i.c
F: drivers/cpufreq/sc[mp]i-cpufreq.c
F: drivers/firmware/arm_scmi/
F: drivers/firmware/arm_scpi.c
+F: drivers/pmdomain/arm/
F: drivers/powercap/arm_scmi_powercap.c
F: drivers/regulator/scmi-regulator.c
F: drivers/reset/reset-scmi.c
@@ -20981,33 +21118,24 @@ W: http://tcp-lp-mod.sourceforge.net/
F: net/ipv4/tcp_lp.c
TDA10071 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/tda10071*
TDA18212 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/tda18212*
TDA18218 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/tda18218*
TDA18250 MEDIA DRIVER
@@ -21366,8 +21494,8 @@ F: drivers/media/radio/radio-raremono.c
THERMAL
M: Rafael J. Wysocki <rafael@kernel.org>
M: Daniel Lezcano <daniel.lezcano@linaro.org>
-R: Amit Kucheria <amitk@kernel.org>
R: Zhang Rui <rui.zhang@intel.com>
+R: Lukasz Luba <lukasz.luba@arm.com>
L: linux-pm@vger.kernel.org
S: Supported
Q: https://patchwork.kernel.org/project/linux-pm/list/
@@ -21554,7 +21682,9 @@ F: Documentation/devicetree/bindings/counter/ti-eqep.yaml
F: drivers/counter/ti-eqep.c
TI ETHERNET SWITCH DRIVER (CPSW)
-R: Grygorii Strashko <grygorii.strashko@ti.com>
+R: Siddharth Vadapalli <s-vadapalli@ti.com>
+R: Ravi Gunasekaran <r-gunasekaran@ti.com>
+R: Roger Quadros <rogerq@kernel.org>
L: linux-omap@vger.kernel.org
L: netdev@vger.kernel.org
S: Maintained
@@ -21578,6 +21708,22 @@ F: Documentation/devicetree/bindings/media/i2c/ti,ds90*
F: drivers/media/i2c/ds90*
F: include/media/i2c/ds90*
+TI ICSSG ETHERNET DRIVER (ICSSG)
+R: MD Danish Anwar <danishanwar@ti.com>
+R: Roger Quadros <rogerq@kernel.org>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L: netdev@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/net/ti,icss*.yaml
+F: drivers/net/ethernet/ti/icssg/*
+
+TI J721E CSI2RX DRIVER
+M: Jai Luthra <j-luthra@ti.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml
+F: drivers/media/platform/ti/j721e-csi2rx/
+
TI KEYSTONE MULTICORE NAVIGATOR DRIVERS
M: Nishanth Menon <nm@ti.com>
M: Santosh Shilimkar <ssantosh@kernel.org>
@@ -21834,9 +21980,11 @@ W: https://www.tq-group.com/en/products/tq-embedded/
F: arch/arm/boot/dts/imx*mba*.dts*
F: arch/arm/boot/dts/imx*tqma*.dts*
F: arch/arm/boot/dts/mba*.dtsi
+F: arch/arm64/boot/dts/freescale/fsl-*tqml*.dts*
F: arch/arm64/boot/dts/freescale/imx*mba*.dts*
F: arch/arm64/boot/dts/freescale/imx*tqma*.dts*
F: arch/arm64/boot/dts/freescale/mba*.dtsi
+F: arch/arm64/boot/dts/freescale/tqml*.dts*
F: drivers/gpio/gpio-tqmx86.c
F: drivers/mfd/tqmx86.c
F: drivers/watchdog/tqmx86_wdt.c
@@ -21844,6 +21992,7 @@ F: drivers/watchdog/tqmx86_wdt.c
TRACING
M: Steven Rostedt <rostedt@goodmis.org>
M: Masami Hiramatsu <mhiramat@kernel.org>
+R: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
L: linux-kernel@vger.kernel.org
L: linux-trace-kernel@vger.kernel.org
S: Maintained
@@ -21892,6 +22041,14 @@ W: https://github.com/srcres258/linux-doc
T: git git://github.com/srcres258/linux-doc.git doc-zh-tw
F: Documentation/translations/zh_TW/
+TRUSTED SECURITY MODULE (TSM) ATTESTATION REPORTS
+M: Dan Williams <dan.j.williams@intel.com>
+L: linux-coco@lists.linux.dev
+S: Maintained
+F: Documentation/ABI/testing/configfs-tsm
+F: drivers/virt/coco/tsm.c
+F: include/linux/tsm.h
+
TTY LAYER AND SERIAL DRIVERS
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
M: Jiri Slaby <jirislaby@kernel.org>
@@ -21914,13 +22071,10 @@ F: include/uapi/linux/serial_core.h
F: include/uapi/linux/tty.h
TUA9001 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org
-W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/tua9001*
TULIP NETWORK DRIVERS
@@ -22740,7 +22894,7 @@ VIRTIO AND VHOST VSOCK DRIVER
M: Stefan Hajnoczi <stefanha@redhat.com>
M: Stefano Garzarella <sgarzare@redhat.com>
L: kvm@vger.kernel.org
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
L: netdev@vger.kernel.org
S: Maintained
F: drivers/vhost/vsock.c
@@ -22752,7 +22906,7 @@ F: net/vmw_vsock/virtio_transport_common.c
VIRTIO BALLOON
M: "Michael S. Tsirkin" <mst@redhat.com>
M: David Hildenbrand <david@redhat.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Maintained
F: drivers/virtio/virtio_balloon.c
F: include/linux/balloon_compaction.h
@@ -22764,7 +22918,7 @@ M: "Michael S. Tsirkin" <mst@redhat.com>
M: Jason Wang <jasowang@redhat.com>
R: Paolo Bonzini <pbonzini@redhat.com>
R: Stefan Hajnoczi <stefanha@redhat.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Maintained
F: drivers/block/virtio_blk.c
F: drivers/scsi/virtio_scsi.c
@@ -22773,7 +22927,7 @@ F: include/uapi/linux/virtio_scsi.h
VIRTIO CONSOLE DRIVER
M: Amit Shah <amit@kernel.org>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Maintained
F: drivers/char/virtio_console.c
F: include/linux/virtio_console.h
@@ -22783,7 +22937,7 @@ VIRTIO CORE AND NET DRIVERS
M: "Michael S. Tsirkin" <mst@redhat.com>
M: Jason Wang <jasowang@redhat.com>
R: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Maintained
F: Documentation/ABI/testing/sysfs-bus-vdpa
F: Documentation/ABI/testing/sysfs-class-vduse
@@ -22802,7 +22956,7 @@ F: tools/virtio/
VIRTIO CRYPTO DRIVER
M: Gonglei <arei.gonglei@huawei.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
L: linux-crypto@vger.kernel.org
S: Maintained
F: drivers/crypto/virtio/
@@ -22813,7 +22967,7 @@ M: Cornelia Huck <cohuck@redhat.com>
M: Halil Pasic <pasic@linux.ibm.com>
M: Eric Farman <farman@linux.ibm.com>
L: linux-s390@vger.kernel.org
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
L: kvm@vger.kernel.org
S: Supported
F: arch/s390/include/uapi/asm/virtio-ccw.h
@@ -22823,7 +22977,7 @@ VIRTIO FILE SYSTEM
M: Vivek Goyal <vgoyal@redhat.com>
M: Stefan Hajnoczi <stefanha@redhat.com>
M: Miklos Szeredi <miklos@szeredi.hu>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
L: linux-fsdevel@vger.kernel.org
S: Supported
W: https://virtio-fs.gitlab.io/
@@ -22835,7 +22989,7 @@ VIRTIO GPIO DRIVER
M: Enrico Weigelt, metux IT consult <info@metux.net>
M: Viresh Kumar <vireshk@kernel.org>
L: linux-gpio@vger.kernel.org
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Maintained
F: drivers/gpio/gpio-virtio.c
F: include/uapi/linux/virtio_gpio.h
@@ -22846,9 +23000,10 @@ M: Gerd Hoffmann <kraxel@redhat.com>
R: Gurchetan Singh <gurchetansingh@chromium.org>
R: Chia-I Wu <olvaffe@gmail.com>
L: dri-devel@lists.freedesktop.org
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
+F: drivers/gpu/drm/ci/xfails/virtio*
F: drivers/gpu/drm/virtio/
F: include/uapi/linux/virtio_gpu.h
@@ -22856,7 +23011,7 @@ VIRTIO HOST (VHOST)
M: "Michael S. Tsirkin" <mst@redhat.com>
M: Jason Wang <jasowang@redhat.com>
L: kvm@vger.kernel.org
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
L: netdev@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git
@@ -22872,7 +23027,7 @@ M: Jason Wang <jasowang@redhat.com>
M: Mike Christie <michael.christie@oracle.com>
R: Paolo Bonzini <pbonzini@redhat.com>
R: Stefan Hajnoczi <stefanha@redhat.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Maintained
F: drivers/vhost/scsi.c
@@ -22880,7 +23035,7 @@ VIRTIO I2C DRIVER
M: Conghui Chen <conghui.chen@intel.com>
M: Viresh Kumar <viresh.kumar@linaro.org>
L: linux-i2c@vger.kernel.org
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Maintained
F: drivers/i2c/busses/i2c-virtio.c
F: include/uapi/linux/virtio_i2c.h
@@ -22893,14 +23048,14 @@ F: include/uapi/linux/virtio_input.h
VIRTIO IOMMU DRIVER
M: Jean-Philippe Brucker <jean-philippe@linaro.org>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Maintained
F: drivers/iommu/virtio-iommu.c
F: include/uapi/linux/virtio_iommu.h
VIRTIO MEM DRIVER
M: David Hildenbrand <david@redhat.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Maintained
W: https://virtio-mem.gitlab.io/
F: drivers/virtio/virtio_mem.c
@@ -22908,7 +23063,7 @@ F: include/uapi/linux/virtio_mem.h
VIRTIO PMEM DRIVER
M: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
S: Maintained
F: drivers/nvdimm/nd_virtio.c
F: drivers/nvdimm/virtio_pmem.c
@@ -22916,7 +23071,7 @@ F: drivers/nvdimm/virtio_pmem.c
VIRTIO SOUND DRIVER
M: Anton Yakovlev <anton.yakovlev@opensynergy.com>
M: "Michael S. Tsirkin" <mst@redhat.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: include/uapi/linux/virtio_snd.h
@@ -22939,7 +23094,7 @@ F: fs/vboxsf/*
VIRTUAL PCM TEST DRIVER
M: Ivan Orlov <ivan.orlov0322@gmail.com>
-L: alsa-devel@alsa-project.org
+L: linux-sound@vger.kernel.org
S: Maintained
F: Documentation/sound/cards/pcmtest.rst
F: sound/drivers/pcmtest.c
@@ -22965,16 +23120,9 @@ W: https://linuxtv.org
T: git git://linuxtv.org/media_tree.git
F: drivers/media/test-drivers/vivid/*
-VLYNQ BUS
-M: Florian Fainelli <f.fainelli@gmail.com>
-L: openwrt-devel@lists.openwrt.org (subscribers-only)
-S: Maintained
-F: drivers/vlynq/vlynq.c
-F: include/linux/vlynq.h
-
VM SOCKETS (AF_VSOCK)
M: Stefano Garzarella <sgarzare@redhat.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/vsockmon.c
@@ -23018,7 +23166,7 @@ VMWARE HYPERVISOR INTERFACE
M: Ajay Kaher <akaher@vmware.com>
M: Alexey Makhalov <amakhalov@vmware.com>
R: VMware PV-Drivers Reviewers <pv-drivers@vmware.com>
-L: virtualization@lists.linux-foundation.org
+L: virtualization@lists.linux.dev
L: x86@kernel.org
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/vmware
@@ -23042,7 +23190,7 @@ F: drivers/scsi/vmw_pvscsi.c
F: drivers/scsi/vmw_pvscsi.h
VMWARE VIRTUAL PTP CLOCK DRIVER
-M: Deep Shah <sdeep@vmware.com>
+M: Jeff Sipek <jsipek@vmware.com>
R: Ajay Kaher <akaher@vmware.com>
R: Alexey Makhalov <amakhalov@vmware.com>
R: VMware PV-Drivers Reviewers <pv-drivers@vmware.com>
@@ -23428,7 +23576,6 @@ F: drivers/platform/x86/x86-android-tablets/
X86 PLATFORM DRIVERS
M: Hans de Goede <hdegoede@redhat.com>
M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
-M: Mark Gross <markgross@kernel.org>
L: platform-driver-x86@vger.kernel.org
S: Maintained
Q: https://patchwork.kernel.org/project/platform-driver-x86/list/
@@ -23466,6 +23613,20 @@ F: arch/x86/kernel/dumpstack.c
F: arch/x86/kernel/stacktrace.c
F: arch/x86/kernel/unwind_*.c
+X86 TRUST DOMAIN EXTENSIONS (TDX)
+M: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+R: Dave Hansen <dave.hansen@linux.intel.com>
+L: x86@kernel.org
+L: linux-coco@lists.linux.dev
+S: Supported
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/tdx
+F: arch/x86/boot/compressed/tdx*
+F: arch/x86/coco/tdx/
+F: arch/x86/include/asm/shared/tdx.h
+F: arch/x86/include/asm/tdx.h
+F: arch/x86/virt/vmx/tdx/
+F: drivers/virt/coco/tdx-guest
+
X86 VDSO
M: Andy Lutomirski <luto@kernel.org>
L: linux-kernel@vger.kernel.org
@@ -23646,8 +23807,7 @@ T: git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
P: Documentation/filesystems/xfs-maintainer-entry-profile.rst
F: Documentation/ABI/testing/sysfs-fs-xfs
F: Documentation/admin-guide/xfs.rst
-F: Documentation/filesystems/xfs-delayed-logging-design.rst
-F: Documentation/filesystems/xfs-self-describing-metadata.rst
+F: Documentation/filesystems/xfs-*
F: fs/xfs/
F: include/uapi/linux/dqblk_xfs.h
F: include/uapi/linux/fsmap.h
@@ -23689,6 +23849,11 @@ F: Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
F: drivers/gpio/gpio-xilinx.c
F: drivers/gpio/gpio-zynq.c
+XILINX LL TEMAC ETHERNET DRIVER
+L: netdev@vger.kernel.org
+S: Orphan
+F: drivers/net/ethernet/xilinx/ll_temac*
+
XILINX PWM DRIVER
M: Sean Anderson <sean.anderson@seco.com>
S: Maintained
@@ -23721,6 +23886,13 @@ F: Documentation/devicetree/bindings/media/xilinx/
F: drivers/media/platform/xilinx/
F: include/uapi/linux/xilinx-v4l2-controls.h
+XILINX VERSAL EDAC DRIVER
+M: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>
+M: Sai Krishna Potthuri <sai.krishna.potthuri@amd.com>
+S: Maintained
+F: Documentation/devicetree/bindings/memory-controllers/xlnx,versal-ddrmc-edac.yaml
+F: drivers/edac/versal_edac.c
+
XILINX WATCHDOG DRIVER
M: Srinivas Neeli <srinivas.neeli@amd.com>
R: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>
@@ -23847,20 +24019,16 @@ S: Orphan
F: drivers/net/wireless/zydas/zd1211rw/
ZD1301 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org/
-W: http://palosaari.fi/linux/
Q: https://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/usb/dvb-usb-v2/zd1301*
ZD1301_DEMOD MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linuxtv.org/
-W: http://palosaari.fi/linux/
Q: https://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/dvb-frontends/zd1301_demod*
diff --git a/Makefile b/Makefile
index 88ebf6547964..70fc4c11dfc0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
-PATCHLEVEL = 6
+PATCHLEVEL = 7
SUBLEVEL = 0
EXTRAVERSION = -rc5
NAME = Hurr durr I'ma ninja sloth
@@ -277,10 +277,6 @@ no-dot-config-targets := $(clean-targets) \
$(version_h) headers headers_% archheaders archscripts \
%asm-generic kernelversion %src-pkg dt_binding_check \
outputmakefile rustavailable rustfmt rustfmtcheck
-# Installation targets should not require compiler. Unfortunately, vdso_install
-# is an exception where build artifacts may be updated. This must be fixed.
-no-compiler-targets := $(no-dot-config-targets) install dtbs_install \
- headers_install modules_install modules_sign kernelrelease image_name
no-sync-config-targets := $(no-dot-config-targets) %install modules_sign kernelrelease \
image_name
single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.rsi %.s %.symtypes %/
@@ -288,7 +284,6 @@ single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.rsi %.s %.symtypes %
config-build :=
mixed-build :=
need-config := 1
-need-compiler := 1
may-sync-config := 1
single-build :=
@@ -298,18 +293,14 @@ ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
endif
endif
-ifneq ($(filter $(no-compiler-targets), $(MAKECMDGOALS)),)
- ifeq ($(filter-out $(no-compiler-targets), $(MAKECMDGOALS)),)
- need-compiler :=
- endif
-endif
-
ifneq ($(filter $(no-sync-config-targets), $(MAKECMDGOALS)),)
ifeq ($(filter-out $(no-sync-config-targets), $(MAKECMDGOALS)),)
may-sync-config :=
endif
endif
+need-compiler := $(may-sync-config)
+
ifneq ($(KBUILD_EXTMOD),)
may-sync-config :=
endif
@@ -378,7 +369,7 @@ include $(srctree)/scripts/subarch.include
# When performing cross compilation for other architectures ARCH shall be set
# to the target architecture. (See arch/* for the possibilities).
# ARCH can be set during invocation of make:
-# make ARCH=ia64
+# make ARCH=arm64
# Another way is to have ARCH set in the environment.
# The default ARCH is the host where make is executed.
@@ -386,7 +377,7 @@ include $(srctree)/scripts/subarch.include
# during compilation. Only gcc and related bin-utils executables
# are prefixed with $(CROSS_COMPILE).
# CROSS_COMPILE can be set on the command line
-# make CROSS_COMPILE=ia64-linux-
+# make CROSS_COMPILE=aarch64-linux-gnu-
# Alternatively CROSS_COMPILE can be set in the environment.
# Default value for CROSS_COMPILE is not to prefix executables
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
@@ -522,8 +513,6 @@ LZ4 = lz4c
XZ = xz
ZSTD = zstd
-PAHOLE_FLAGS = $(shell PAHOLE=$(PAHOLE) $(srctree)/scripts/pahole-flags.sh)
-
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
-Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF)
NOSTDINC_FLAGS :=
@@ -614,7 +603,6 @@ export KBUILD_RUSTFLAGS RUSTFLAGS_KERNEL RUSTFLAGS_MODULE
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_RUSTFLAGS_MODULE KBUILD_LDFLAGS_MODULE
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL KBUILD_RUSTFLAGS_KERNEL
-export PAHOLE_FLAGS
# Files to ignore in find ... statements
@@ -684,7 +672,7 @@ ifdef config-build
# *config targets only - make sure prerequisites are updated, and descend
# in scripts/kconfig to make the *config target
-# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
+# Read arch-specific Makefile to set KBUILD_DEFCONFIG as needed.
# KBUILD_DEFCONFIG may point out an alternative default configuration
# used for 'make defconfig'
include $(srctree)/arch/$(SRCARCH)/Makefile
@@ -698,7 +686,7 @@ config: outputmakefile scripts_basic FORCE
else #!config-build
# ===========================================================================
-# Build targets only - this includes vmlinux, arch specific targets, clean
+# Build targets only - this includes vmlinux, arch-specific targets, clean
# targets and others. In general all targets except *config targets.
# If building an external module we do not care about the all: rule
@@ -1011,6 +999,7 @@ KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
# include additional Makefiles when needed
include-y := scripts/Makefile.extrawarn
include-$(CONFIG_DEBUG_INFO) += scripts/Makefile.debug
+include-$(CONFIG_DEBUG_INFO_BTF)+= scripts/Makefile.btf
include-$(CONFIG_KASAN) += scripts/Makefile.kasan
include-$(CONFIG_KCSAN) += scripts/Makefile.kcsan
include-$(CONFIG_KMSAN) += scripts/Makefile.kmsan
@@ -1318,6 +1307,14 @@ quiet_cmd_install = INSTALL $(INSTALL_PATH)
cmd_install = unset sub_make_done; $(srctree)/scripts/install.sh
# ---------------------------------------------------------------------------
+# vDSO install
+
+PHONY += vdso_install
+vdso_install: export INSTALL_FILES = $(vdso-install-y)
+vdso_install:
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.vdsoinst
+
+# ---------------------------------------------------------------------------
# Tools
ifdef CONFIG_OBJTOOL
@@ -1367,8 +1364,8 @@ kselftest-%: headers FORCE
PHONY += kselftest-merge
kselftest-merge:
$(if $(wildcard $(objtree)/.config),, $(error No .config exists, config your kernel first!))
- $(Q)find $(srctree)/tools/testing/selftests -name config | \
- xargs $(srctree)/scripts/kconfig/merge_config.sh -m $(objtree)/.config
+ $(Q)find $(srctree)/tools/testing/selftests -name config -o -name config.$(UTS_MACHINE) | \
+ xargs $(srctree)/scripts/kconfig/merge_config.sh -y -m $(objtree)/.config
$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
# ---------------------------------------------------------------------------
@@ -1474,7 +1471,7 @@ endif # CONFIG_MODULES
# Directories & files removed with 'make clean'
CLEAN_FILES += vmlinux.symvers modules-only.symvers \
modules.builtin modules.builtin.modinfo modules.nsdeps \
- compile_commands.json .thinlto-cache rust/test rust/doc \
+ compile_commands.json .thinlto-cache rust/test \
rust-project.json .vmlinux.objs .vmlinux.export.c
# Directories & files removed with 'make mrproper'
@@ -1486,7 +1483,7 @@ MRPROPER_FILES += include/config include/generated \
certs/signing_key.pem \
certs/x509.genkey \
vmlinux-gdb.py \
- kernel.spec rpmbuild \
+ rpmbuild \
rust/libmacros.so
# clean - Delete most, but leave enough to build external modules
@@ -1560,6 +1557,7 @@ help:
@echo '* vmlinux - Build the bare kernel'
@echo '* modules - Build all modules'
@echo ' modules_install - Install all modules to INSTALL_MOD_PATH (default: /)'
+ @echo ' vdso_install - Install unstripped vdso to INSTALL_MOD_PATH (default: /)'
@echo ' dir/ - Build all files in dir and below'
@echo ' dir/file.[ois] - Build specified target only'
@echo ' dir/file.ll - Build the LLVM assembly file'
@@ -1637,9 +1635,9 @@ help:
@echo 'Documentation targets:'
@$(MAKE) -f $(srctree)/Documentation/Makefile dochelp
@echo ''
- @echo 'Architecture specific targets ($(SRCARCH)):'
+ @echo 'Architecture-specific targets ($(SRCARCH)):'
@$(or $(archhelp),\
- echo ' No architecture specific help defined for $(SRCARCH)')
+ echo ' No architecture-specific help defined for $(SRCARCH)')
@echo ''
@$(if $(boards), \
$(foreach b, $(boards), \
@@ -1681,7 +1679,7 @@ help-boards: $(help-board-dirs)
boards-per-dir = $(sort $(notdir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/$*/*_defconfig)))
$(help-board-dirs): help-%:
- @echo 'Architecture specific targets ($(SRCARCH) $*):'
+ @echo 'Architecture-specific targets ($(SRCARCH) $*):'
@$(if $(boards-per-dir), \
$(foreach b, $(boards-per-dir), \
printf " %-24s - Build for %s\\n" $*/$(b) $(subst _defconfig,,$(b));) \
diff --git a/arch/Kconfig b/arch/Kconfig
index 12d51495caec..f4b210ab0612 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -1088,7 +1088,6 @@ config HAVE_ARCH_COMPAT_MMAP_BASES
config PAGE_SIZE_LESS_THAN_64KB
def_bool y
depends on !ARM64_64K_PAGES
- depends on !IA64_PAGE_SIZE_64KB
depends on !PAGE_SIZE_64KB
depends on !PARISC_PAGE_SIZE_64KB
depends on PAGE_SIZE_LESS_THAN_256KB
diff --git a/arch/alpha/include/asm/bitops.h b/arch/alpha/include/asm/bitops.h
index bafb1c1f0fdc..3e33621922c3 100644
--- a/arch/alpha/include/asm/bitops.h
+++ b/arch/alpha/include/asm/bitops.h
@@ -286,6 +286,26 @@ arch___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
#define arch_test_bit generic_test_bit
#define arch_test_bit_acquire generic_test_bit_acquire
+static inline bool xor_unlock_is_negative_byte(unsigned long mask,
+ volatile unsigned long *p)
+{
+ unsigned long temp, old;
+
+ __asm__ __volatile__(
+ "1: ldl_l %0,%4\n"
+ " mov %0,%2\n"
+ " xor %0,%3,%0\n"
+ " stl_c %0,%1\n"
+ " beq %0,2f\n"
+ ".subsection 2\n"
+ "2: br 1b\n"
+ ".previous"
+ :"=&r" (temp), "=m" (*p), "=&r" (old)
+ :"Ir" (mask), "m" (*p));
+
+ return (old & BIT(7)) != 0;
+}
+
/*
* ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check against ~0UL first..
diff --git a/arch/alpha/include/asm/local.h b/arch/alpha/include/asm/local.h
index 0fcaad642cc3..88eb398947a5 100644
--- a/arch/alpha/include/asm/local.h
+++ b/arch/alpha/include/asm/local.h
@@ -65,28 +65,27 @@ static __inline__ bool local_try_cmpxchg(local_t *l, long *old, long new)
#define local_xchg(l, n) (xchg_local(&((l)->a.counter), (n)))
/**
- * local_add_unless - add unless the number is a given value
+ * local_add_unless - add unless the number is already a given value
* @l: pointer of type local_t
* @a: the amount to add to l...
* @u: ...unless l is equal to u.
*
- * Atomically adds @a to @l, so long as it was not @u.
- * Returns non-zero if @l was not @u, and zero otherwise.
+ * Atomically adds @a to @l, if @v was not already @u.
+ * Returns true if the addition was done.
*/
-#define local_add_unless(l, a, u) \
-({ \
- long c, old; \
- c = local_read(l); \
- for (;;) { \
- if (unlikely(c == (u))) \
- break; \
- old = local_cmpxchg((l), c, c + (a)); \
- if (likely(old == c)) \
- break; \
- c = old; \
- } \
- c != (u); \
-})
+static __inline__ bool
+local_add_unless(local_t *l, long a, long u)
+{
+ long c = local_read(l);
+
+ do {
+ if (unlikely(c == u))
+ return false;
+ } while (!local_try_cmpxchg(l, &c, c + a));
+
+ return true;
+}
+
#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
#define local_add_negative(a, l) (local_add_return((a), (l)) < 0)
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index 5816a31c1b38..2c89c1c55712 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/interrupt.h>
+#include <linux/screen_info.h>
#include <linux/io.h>
/* Prototypes of functions used across modules here in this directory. */
@@ -113,6 +114,7 @@ extern int boot_cpuid;
#ifdef CONFIG_VERBOSE_MCHECK
extern unsigned long alpha_verbose_mcheck;
#endif
+extern struct screen_info vgacon_screen_info;
/* srmcons.c */
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index c80258ec332f..0738f9396f95 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -131,13 +131,14 @@ static void determine_cpu_caches (unsigned int);
static char __initdata command_line[COMMAND_LINE_SIZE];
+#ifdef CONFIG_VGA_CONSOLE
/*
* The format of "screen_info" is strange, and due to early
* i386-setup code. This is just enough to make the console
* code think we're on a VGA color display.
*/
-struct screen_info screen_info = {
+struct screen_info vgacon_screen_info = {
.orig_x = 0,
.orig_y = 25,
.orig_video_cols = 80,
@@ -145,8 +146,7 @@ struct screen_info screen_info = {
.orig_video_isVGA = 1,
.orig_video_points = 16
};
-
-EXPORT_SYMBOL(screen_info);
+#endif
/*
* The direct map I/O window, if any. This should be the same
@@ -652,7 +652,7 @@ setup_arch(char **cmdline_p)
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
- conswitchp = &vga_con;
+ vgacon_register_screen(&vgacon_screen_info);
#endif
#endif
diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
index e1bee8f84c58..33b2798de8fc 100644
--- a/arch/alpha/kernel/sys_miata.c
+++ b/arch/alpha/kernel/sys_miata.c
@@ -183,16 +183,17 @@ miata_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
the 2nd 8259 controller. So we have to check for it first. */
if((slot == 7) && (PCI_FUNC(dev->devfn) == 3)) {
- u8 irq=0;
struct pci_dev *pdev = pci_get_slot(dev->bus, dev->devfn & ~7);
- if(pdev == NULL || pci_read_config_byte(pdev, 0x40,&irq) != PCIBIOS_SUCCESSFUL) {
- pci_dev_put(pdev);
+ u8 irq = 0;
+ int ret;
+
+ if (!pdev)
return -1;
- }
- else {
- pci_dev_put(pdev);
- return irq;
- }
+
+ ret = pci_read_config_byte(pdev, 0x40, &irq);
+ pci_dev_put(pdev);
+
+ return ret == PCIBIOS_SUCCESSFUL ? irq : -1;
}
return COMMON_TABLE_LOOKUP;
diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
index 7c420d8dac53..086488ed83a7 100644
--- a/arch/alpha/kernel/sys_sio.c
+++ b/arch/alpha/kernel/sys_sio.c
@@ -57,11 +57,13 @@ sio_init_irq(void)
static inline void __init
alphabook1_init_arch(void)
{
+#ifdef CONFIG_VGA_CONSOLE
/* The AlphaBook1 has LCD video fixed at 800x600,
37 rows and 100 cols. */
- screen_info.orig_y = 37;
- screen_info.orig_video_cols = 100;
- screen_info.orig_video_lines = 37;
+ vgacon_screen_info.orig_y = 37;
+ vgacon_screen_info.orig_video_cols = 100;
+ vgacon_screen_info.orig_video_lines = 37;
+#endif
lca_init_arch();
}
diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl
index ad37569d0507..18c842ca6c32 100644
--- a/arch/alpha/kernel/syscalls/syscall.tbl
+++ b/arch/alpha/kernel/syscalls/syscall.tbl
@@ -334,7 +334,7 @@
401 common io_submit sys_io_submit
402 common io_cancel sys_io_cancel
405 common exit_group sys_exit_group
-406 common lookup_dcookie sys_lookup_dcookie
+406 common lookup_dcookie sys_ni_syscall
407 common epoll_create sys_epoll_create
408 common epoll_ctl sys_epoll_ctl
409 common epoll_wait sys_epoll_wait
@@ -492,3 +492,7 @@
560 common set_mempolicy_home_node sys_ni_syscall
561 common cachestat sys_cachestat
562 common fchmodat2 sys_fchmodat2
+563 common map_shadow_stack sys_map_shadow_stack
+564 common futex_wake sys_futex_wake
+565 common futex_wait sys_futex_wait
+566 common futex_requeue sys_futex_requeue
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index de1566e32cb8..68e8301c0df2 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -32,9 +32,6 @@ struct kprobe;
void arch_remove_kprobe(struct kprobe *p);
-int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
-
struct prev_kprobe {
struct kprobe *kp;
unsigned long status;
diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
index d5b3ed2c58f5..c380d8c30704 100644
--- a/arch/arc/kernel/troubleshoot.c
+++ b/arch/arc/kernel/troubleshoot.c
@@ -90,10 +90,12 @@ static void show_faulting_vma(unsigned long address)
*/
if (vma) {
char buf[ARC_PATH_MAX];
- char *nm = "?";
+ char *nm = "anon";
if (vma->vm_file) {
- nm = file_path(vma->vm_file, buf, ARC_PATH_MAX-1);
+ /* XXX: can we use %pD below and get rid of buf? */
+ nm = d_path(file_user_path(vma->vm_file), buf,
+ ARC_PATH_MAX-1);
if (IS_ERR(nm))
nm = "?";
}
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9557808e8937..f8567e95f98b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -8,6 +8,7 @@ config ARM
select ARCH_HAS_CPU_FINALIZE_INIT if MMU
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VIRTUAL if MMU
+ select ARCH_HAS_DMA_ALLOC if MMU
select ARCH_HAS_DMA_WRITE_COMBINE if !ARM_DMA_MEM_BUFFERABLE
select ARCH_HAS_ELF_RANDOMIZE
select ARCH_HAS_FORTIFY_SOURCE
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index b407b7b9b715..fc2b41d41447 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1593,10 +1593,8 @@ config DEBUG_UART_PHYS
default 0x48020000 if DEBUG_OMAP4UART3 || DEBUG_TI81XXUART1
default 0x48022000 if DEBUG_TI81XXUART2
default 0x48024000 if DEBUG_TI81XXUART3
- default 0x4806a000 if DEBUG_OMAP2UART1 || DEBUG_OMAP3UART1 || \
- DEBUG_OMAP4UART1 || DEBUG_OMAP5UART1
- default 0x4806c000 if DEBUG_OMAP2UART2 || DEBUG_OMAP3UART2 || \
- DEBUG_OMAP4UART2 || DEBUG_OMAP5UART2
+ default 0x4806a000 if DEBUG_OMAP2UART1
+ default 0x4806c000 if DEBUG_OMAP2UART2
default 0x4806e000 if DEBUG_OMAP2UART3 || DEBUG_OMAP4UART4
default 0x49020000 if DEBUG_OMAP3UART3
default 0x49042000 if DEBUG_OMAP3UART4
@@ -1719,10 +1717,8 @@ config DEBUG_UART_VIRT
default 0xfa020000 if DEBUG_OMAP4UART3 || DEBUG_TI81XXUART1
default 0xfa022000 if DEBUG_TI81XXUART2
default 0xfa024000 if DEBUG_TI81XXUART3
- default 0xfa06a000 if DEBUG_OMAP2UART1 || DEBUG_OMAP3UART1 || \
- DEBUG_OMAP4UART1 || DEBUG_OMAP5UART1
- default 0xfa06c000 if DEBUG_OMAP2UART2 || DEBUG_OMAP3UART2 || \
- DEBUG_OMAP4UART2 || DEBUG_OMAP5UART2
+ default 0xfa06a000 if DEBUG_OMAP2UART1
+ default 0xfa06c000 if DEBUG_OMAP2UART2
default 0xfa06e000 if DEBUG_OMAP2UART3 || DEBUG_OMAP4UART4
default 0xfa71e000 if DEBUG_QCOM_UARTDM
default 0xfb009000 if DEBUG_REALVIEW_STD_PORT
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 547e5856eaa0..5ba42f69f8ce 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -304,11 +304,7 @@ $(INSTALL_TARGETS): KBUILD_IMAGE = $(boot)/$(patsubst %install,%Image,$@)
$(INSTALL_TARGETS):
$(call cmd,install)
-PHONY += vdso_install
-vdso_install:
-ifeq ($(CONFIG_VDSO),y)
- $(Q)$(MAKE) $(build)=arch/arm/vdso $@
-endif
+vdso-install-$(CONFIG_VDSO) += arch/arm/vdso/vdso.so.dbg
# My testing targets (bypasses dependencies)
bp:; $(Q)$(MAKE) $(build)=$(boot) $(boot)/bootpImage
@@ -331,7 +327,6 @@ define archhelp
echo ' Install using (your) ~/bin/$(INSTALLKERNEL) or'
echo ' (distribution) /sbin/$(INSTALLKERNEL) or'
echo ' install to $$(INSTALL_PATH) and run lilo'
- echo ' vdso_install - Install unstripped vdso.so to $$(INSTALL_MOD_PATH)/vdso'
echo
echo ' multi_v7_lpae_defconfig - multi_v7_defconfig with CONFIG_ARM_LPAE enabled'
endef
diff --git a/arch/arm/boot/dts/allwinner/Makefile b/arch/arm/boot/dts/allwinner/Makefile
index eebb5a0c873a..2d26c3397f14 100644
--- a/arch/arm/boot/dts/allwinner/Makefile
+++ b/arch/arm/boot/dts/allwinner/Makefile
@@ -256,6 +256,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
sun8i-t113s-mangopi-mq-r-t113.dtb \
sun8i-t3-cqa3t-bv3.dtb \
sun8i-v3-sl631-imx179.dtb \
+ sun8i-v3s-anbernic-rg-nano.dtb \
sun8i-v3s-licheepi-zero.dtb \
sun8i-v3s-licheepi-zero-dock.dtb \
sun8i-v40-bananapi-m2-berry.dtb
diff --git a/arch/arm/boot/dts/allwinner/sun8i-r40.dtsi b/arch/arm/boot/dts/allwinner/sun8i-r40.dtsi
index 4ef26d8f5340..a5b1f1e3900d 100644
--- a/arch/arm/boot/dts/allwinner/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/allwinner/sun8i-r40.dtsi
@@ -338,6 +338,8 @@
resets = <&ccu RST_BUS_VE>;
interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
allwinner,sram = <&ve_sram 1>;
+ interconnects = <&mbus 4>;
+ interconnect-names = "dma-mem";
};
mmc0: mmc@1c0f000 {
diff --git a/arch/arm/boot/dts/allwinner/sun8i-v3s-anbernic-rg-nano.dts b/arch/arm/boot/dts/allwinner/sun8i-v3s-anbernic-rg-nano.dts
new file mode 100644
index 000000000000..f34dfdf1566d
--- /dev/null
+++ b/arch/arm/boot/dts/allwinner/sun8i-v3s-anbernic-rg-nano.dts
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+#include <dt-bindings/input/linux-event-codes.h>
+#include "sun8i-v3s.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+/ {
+ model = "Anbernic RG Nano";
+ compatible = "anbernic,rg-nano", "allwinner,sun8i-v3s";
+
+ aliases {
+ rtc0 = &pcf8563;
+ rtc1 = &rtc;
+ serial0 = &uart0;
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ brightness-levels = <0 1 2 3 8 14 21 32 46 60 80 100>;
+ default-brightness-level = <11>;
+ power-supply = <&reg_vcc5v0>;
+ pwms = <&pwm 0 40000 1>;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ gpio_keys: gpio-keys {
+ compatible = "gpio-keys";
+
+ button-a {
+ gpios = <&gpio_expander 12 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-A";
+ linux,code = <BTN_EAST>;
+ };
+
+ button-b {
+ gpios = <&gpio_expander 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-B";
+ linux,code = <BTN_SOUTH>;
+ };
+
+ button-down {
+ gpios = <&gpio_expander 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "DPAD-DOWN";
+ linux,code = <BTN_DPAD_DOWN>;
+ };
+
+ button-left {
+ gpios = <&gpio_expander 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "DPAD-LEFT";
+ linux,code = <BTN_DPAD_LEFT>;
+ };
+
+ button-right {
+ gpios = <&gpio_expander 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "DPAD-RIGHT";
+ linux,code = <BTN_DPAD_RIGHT>;
+ };
+
+ button-se {
+ gpios = <&gpio_expander 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-SELECT";
+ linux,code = <BTN_SELECT>;
+ };
+
+ button-st {
+ gpios = <&gpio_expander 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-START";
+ linux,code = <BTN_START>;
+ };
+
+ button-tl {
+ gpios = <&gpio_expander 2 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-L";
+ linux,code = <BTN_TL>;
+ };
+
+ button-tr {
+ gpios = <&gpio_expander 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-R";
+ linux,code = <BTN_TR>;
+ };
+
+ button-up {
+ gpios = <&gpio_expander 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "DPAD-UP";
+ linux,code = <BTN_DPAD_UP>;
+ };
+
+ button-x {
+ gpios = <&gpio_expander 11 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-X";
+ linux,code = <BTN_NORTH>;
+ };
+
+ button-y {
+ gpios = <&gpio_expander 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-Y";
+ linux,code = <BTN_WEST>;
+ };
+ };
+};
+
+&codec {
+ allwinner,audio-routing = "Speaker", "HP",
+ "MIC1", "Mic",
+ "Mic", "HBIAS";
+ allwinner,pa-gpios = <&pio 5 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PF6 */
+ status = "okay";
+};
+
+&ehci {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ gpio_expander: gpio@20 {
+ compatible = "nxp,pcal6416";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ interrupt-parent = <&pio>;
+ interrupts = <1 3 IRQ_TYPE_EDGE_BOTH>; /* PB3/EINT3 */
+ vcc-supply = <&reg_vcc3v3>;
+ };
+
+ axp209: pmic@34 {
+ reg = <0x34>;
+ interrupt-parent = <&pio>;
+ interrupts = <1 5 IRQ_TYPE_EDGE_FALLING>; /* PB5/EINT5 */
+ };
+
+ pcf8563: rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+};
+
+#include "axp209.dtsi"
+
+&battery_power_supply {
+ status = "okay";
+};
+
+&mmc0 {
+ broken-cd;
+ bus-width = <4>;
+ disable-wp;
+ vmmc-supply = <&reg_vcc3v3>;
+ vqmmc-supply = <&reg_vcc3v3>;
+ status = "okay";
+};
+
+&ohci {
+ status = "okay";
+};
+
+&pio {
+ vcc-pb-supply = <&reg_vcc3v3>;
+ vcc-pc-supply = <&reg_vcc3v3>;
+ vcc-pf-supply = <&reg_vcc3v3>;
+ vcc-pg-supply = <&reg_vcc3v3>;
+
+ spi0_no_miso_pins: spi0-no-miso-pins {
+ pins = "PC1", "PC2", "PC3";
+ function = "spi0";
+ };
+};
+
+&pwm {
+ pinctrl-0 = <&pwm0_pin>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+/* DCDC2 wired into vdd-cpu, vdd-sys, and vdd-ephy. */
+&reg_dcdc2 {
+ regulator-always-on;
+ regulator-max-microvolt = <1250000>;
+ regulator-min-microvolt = <1250000>;
+ regulator-name = "vdd-cpu";
+};
+
+/* DCDC3 wired into every 3.3v input that isn't the RTC. */
+&reg_dcdc3 {
+ regulator-always-on;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "vcc-io";
+};
+
+/* LDO1 wired into RTC, voltage is hard-wired at 3.3v. */
+&reg_ldo1 {
+ regulator-always-on;
+ regulator-name = "vcc-rtc";
+};
+
+/* LDO2 wired into VCC-PLL and audio codec. */
+&reg_ldo2 {
+ regulator-always-on;
+ regulator-max-microvolt = <3000000>;
+ regulator-min-microvolt = <3000000>;
+ regulator-name = "vcc-pll";
+};
+
+/* LDO3, LDO4, and LDO5 unused. */
+&reg_ldo3 {
+ status = "disabled";
+};
+
+&reg_ldo4 {
+ status = "disabled";
+};
+
+/* RTC uses internal oscillator */
+&rtc {
+ /delete-property/ clocks;
+};
+
+&spi0 {
+ pinctrl-0 = <&spi0_no_miso_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ display@0 {
+ compatible = "saef,sftc154b", "panel-mipi-dbi-spi";
+ reg = <0>;
+ backlight = <&backlight>;
+ dc-gpios = <&pio 2 0 GPIO_ACTIVE_HIGH>; /* PC0 */
+ reset-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2 */
+ spi-max-frequency = <100000000>;
+
+ height-mm = <39>;
+ width-mm = <39>;
+
+ /* Set hb-porch to compensate for non-visible area */
+ panel-timing {
+ hactive = <240>;
+ vactive = <240>;
+ hback-porch = <80>;
+ vback-porch = <0>;
+ clock-frequency = <0>;
+ hfront-porch = <0>;
+ hsync-len = <0>;
+ vfront-porch = <0>;
+ vsync-len = <0>;
+ };
+ };
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_pb_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usb_power_supply {
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 6 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PG5 */
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi b/arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi
index 3b9a282c2746..e8a04476b776 100644
--- a/arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi
@@ -319,6 +319,29 @@
#phy-cells = <1>;
};
+ ehci: usb@1c1a000 {
+ compatible = "allwinner,sun8i-v3s-ehci", "generic-ehci";
+ reg = <0x01c1a000 0x100>;
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_EHCI0>, <&ccu CLK_BUS_OHCI0>;
+ resets = <&ccu RST_BUS_EHCI0>, <&ccu RST_BUS_OHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci: usb@1c1a400 {
+ compatible = "allwinner,sun8i-v3s-ohci", "generic-ohci";
+ reg = <0x01c1a400 0x100>;
+ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_EHCI0>, <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_EHCI0>, <&ccu RST_BUS_OHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
ccu: clock@1c20000 {
compatible = "allwinner,sun8i-v3s-ccu";
reg = <0x01c20000 0x400>;
@@ -414,6 +437,18 @@
bias-pull-up;
};
+ /omit-if-no-ref/
+ pwm0_pin: pwm0-pin {
+ pins = "PB4";
+ function = "pwm0";
+ };
+
+ /omit-if-no-ref/
+ pwm1_pin: pwm1-pin {
+ pins = "PB5";
+ function = "pwm1";
+ };
+
spi0_pins: spi0-pins {
pins = "PC0", "PC1", "PC2", "PC3";
function = "spi0";
diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
index 23cbc7203a8e..d3ac20e316d0 100644
--- a/arch/arm/boot/dts/aspeed/Makefile
+++ b/arch/arm/boot/dts/aspeed/Makefile
@@ -19,6 +19,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
aspeed-bmc-facebook-fuji.dtb \
aspeed-bmc-facebook-galaxy100.dtb \
aspeed-bmc-facebook-greatlakes.dtb \
+ aspeed-bmc-facebook-minerva-cmc.dtb \
aspeed-bmc-facebook-minipack.dtb \
aspeed-bmc-facebook-tiogapass.dtb \
aspeed-bmc-facebook-wedge40.dtb \
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtjade.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtjade.dts
index 0a51d2e32fab..8ab5f301f926 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtjade.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtjade.dts
@@ -760,49 +760,63 @@
&gpio {
gpio-line-names =
- /*A0-A7*/ "","","","S0_BMC_SPECIAL_BOOT","","","","",
- /*B0-B7*/ "BMC_SELECT_EEPROM","","","",
- "POWER_BUTTON","","","",
+ /*A0-A7*/ "","","","host0-special-boot","","","","",
+ /*B0-B7*/ "i2c-backup-sel","","","",
+ "power-button","presence-cpu0","","",
/*C0-C7*/ "","","","","","","","",
/*D0-D7*/ "","","","","","","","",
/*E0-E7*/ "","","","","","","","",
- /*F0-F7*/ "","","BMC_SYS_PSON_L","S0_DDR_SAVE","PGOOD",
- "S1_DDR_SAVE","","",
- /*G0-G7*/ "host0-ready","SHD_REQ_L","","S0_OVERTEMP_L","","",
- "","",
- /*H0-H7*/ "","","","","PSU1_VIN_GOOD","PSU2_VIN_GOOD","","",
- /*I0-I7*/ "PSU1_PRESENT","PSU2_PRESENT","S1_BMC_SPECIAL_BOOT",
- "","","","","",
- /*J0-J7*/ "S0_HIGHTEMP_L","S0_FAULT_L","S0_SCP_AUTH_FAIL_L","",
- "","","","",
+ /*F0-F7*/ "ps0-pgood","ps1-pgood","power-chassis-control","s0-ddr-save",
+ "power-chassis-good", "s1-ddr-save","","",
+ /*G0-G7*/ "host0-ready","host0-shd-req-n","host0-shd-ack-n",
+ "s0-overtemp-n","","","","",
+ /*H0-H7*/ "uart1-mode1","uart2-mode1","uart3-mode1","uart4-mode1",
+ "ps0-vin-good","ps1-vin-good","","i2c6-reset-n",
+ /*I0-I7*/ "presence-ps0","presence-ps1","s1-special-boot","","","","","",
+ /*J0-J7*/ "s0-hightemp-n","s0-fault-alert","s0-sys-auth-failure-n",
+ "host0-reboot-ack-n","","","","",
/*K0-K7*/ "","","","","","","","",
- /*L0-L7*/ "","","","BMC_SYSRESET_L","SPI_AUTH_FAIL_L","","","",
- /*M0-M7*/ "","","","","","","","",
+ /*L0-L7*/ "","","","host0-sysreset-n","s0-spi-auth-fail-n","","","",
+ /*M0-M7*/ "","","","","s0-i2c9-alert-n","s1-i2c9-alert-n","","",
/*N0-N7*/ "","","","","","","","",
/*O0-O7*/ "","","","","","","","",
/*P0-P7*/ "","","","","","","","",
- /*Q0-Q7*/ "","","","","","UID_BUTTON","","",
- /*R0-R7*/ "","","BMC_EXT_HIGHTEMP_L","OCP_AUX_PWREN",
- "OCP_MAIN_PWREN","RESET_BUTTON","","",
- /*S0-S7*/ "","","","","rtc-battery-voltage-read-enable","","","",
+ /*Q0-Q7*/ "","","","","","identify-button","led-identify","",
+ /*R0-R7*/ "","","ext-hightemp-n","","ocp-main-pwren","reset-button","","",
+ /*S0-S7*/ "s0-vr-hot-n","s1-vr-hot-n","","",
+ "rtc-battery-voltage-read-enable","vr-pmbus-sel-n","","",
/*T0-T7*/ "","","","","","","","",
/*U0-U7*/ "","","","","","","","",
/*V0-V7*/ "","","","","","","","",
/*W0-W7*/ "","","","","","","","",
/*X0-X7*/ "","","","","","","","",
- /*Y0-Y7*/ "","","","","","","","",
- /*Z0-Z7*/ "S0_BMC_PLIMIT","S1_FAULT_L","S1_FW_BOOT_OK","","",
- "S1_SCP_AUTH_FAIL_L","S1_OVERTEMP_L","",
+ /*Y0-Y7*/ "","","","bmc-vga-en-n","","","","",
+ /*Z0-Z7*/ "s0-plimit","s1-fault-alert","s1-fw-boot-ok","s0-rtc-lock","",
+ "s1-sys-auth-failure-n","s1-overtemp-n","",
/*AA0-AA7*/ "","","","","","","","",
- /*AB0-AB7*/ "S1_HIGHTEMP_L","S1_BMC_PLIMIT","S0_BMC_DDR_ADDR",
- "S1_BMC_DDR_ADR","","","","",
- /*AC0-AC7*/ "SYS_PWR_GD","","","","","BMC_READY","SLAVE_PRESENT_L",
- "BMC_OCP_PG";
+ /*AB0-AB7*/ "s1-hightemp-n","s1-plimit","s0-ddr-addr","s1-ddr-addr","","",
+ "","",
+ /*AC0-AC7*/ "sys-pwr-gd","","spi0-program-sel","spi0-backup-sel","bmc-ok",
+ "","presence-cpu1","ocp-pgood";
i2c4-o-en-hog {
gpio-hog;
gpios = <ASPEED_GPIO(Y, 2) GPIO_ACTIVE_HIGH>;
output-high;
- line-name = "BMC_I2C4_O_EN";
+ line-name = "i2c4-o-en";
+ };
+
+ ocp-aux-pwren-hog {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(R, 3) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "ocp-aux-pwren";
+ };
+
+ bmc-ready {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(AC, 5) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "bmc-ready";
};
};
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtmitchell.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtmitchell.dts
index 0715cb9ab30c..7b540880cef9 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtmitchell.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtmitchell.dts
@@ -14,6 +14,42 @@
aliases {
serial7 = &uart8;
serial8 = &uart9;
+
+ /*
+ * I2C NVMe alias port
+ */
+ i2c100 = &backplane_0;
+ i2c48 = &nvmeslot_0;
+ i2c49 = &nvmeslot_1;
+ i2c50 = &nvmeslot_2;
+ i2c51 = &nvmeslot_3;
+ i2c52 = &nvmeslot_4;
+ i2c53 = &nvmeslot_5;
+ i2c54 = &nvmeslot_6;
+ i2c55 = &nvmeslot_7;
+
+ i2c101 = &backplane_1;
+ i2c56 = &nvmeslot_8;
+ i2c57 = &nvmeslot_9;
+ i2c58 = &nvmeslot_10;
+ i2c59 = &nvmeslot_11;
+ i2c60 = &nvmeslot_12;
+ i2c61 = &nvmeslot_13;
+ i2c62 = &nvmeslot_14;
+ i2c63 = &nvmeslot_15;
+
+ i2c102 = &backplane_2;
+ i2c64 = &nvmeslot_16;
+ i2c65 = &nvmeslot_17;
+ i2c66 = &nvmeslot_18;
+ i2c67 = &nvmeslot_19;
+ i2c68 = &nvmeslot_20;
+ i2c69 = &nvmeslot_21;
+ i2c70 = &nvmeslot_22;
+ i2c71 = &nvmeslot_23;
+
+ i2c80 = &nvme_m2_0;
+ i2c81 = &nvme_m2_1;
};
chosen {
@@ -497,6 +533,11 @@
&i2c8 {
status = "okay";
+ temperature-sensor@48 {
+ compatible = "ti,tmp112";
+ reg = <0x48>;
+ };
+
gpio@77 {
compatible = "nxp,pca9539";
reg = <0x77>;
@@ -516,6 +557,237 @@
&i2c9 {
status = "okay";
+ i2c-mux@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+ i2c-mux-idle-disconnect;
+
+ backplane_1: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0>;
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ pagesize = <32>;
+ };
+
+ i2c-mux@71 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x71>;
+ i2c-mux-idle-disconnect;
+
+ nvmeslot_8: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0>;
+ };
+ nvmeslot_9: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1>;
+ };
+ nvmeslot_10: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x2>;
+ };
+ nvmeslot_11: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x3>;
+ };
+ nvmeslot_12: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x4>;
+ };
+ nvmeslot_13: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x5>;
+ };
+ nvmeslot_14: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x6>;
+ };
+ nvmeslot_15: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x7>;
+ };
+ };
+
+ tmp432@4c {
+ compatible = "ti,tmp75";
+ reg = <0x4c>;
+ };
+ };
+
+ backplane_2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x2>;
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ pagesize = <32>;
+ };
+
+ i2c-mux@71 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x71>;
+ i2c-mux-idle-disconnect;
+
+ nvmeslot_16: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0>;
+ };
+ nvmeslot_17: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1>;
+ };
+ nvmeslot_18: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x2>;
+ };
+ nvmeslot_19: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x3>;
+ };
+ nvmeslot_20: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x4>;
+ };
+ nvmeslot_21: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x5>;
+ };
+ nvmeslot_22: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x6>;
+ };
+ nvmeslot_23: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x7>;
+ };
+ };
+
+ tmp432@4c {
+ compatible = "ti,tmp75";
+ reg = <0x4c>;
+ };
+ };
+
+ backplane_0: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x4>;
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ pagesize = <32>;
+ };
+
+ i2c-mux@71 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x71>;
+ i2c-mux-idle-disconnect;
+
+ nvmeslot_0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0>;
+ };
+ nvmeslot_1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1>;
+ };
+ nvmeslot_2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x2>;
+ };
+ nvmeslot_3: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x3>;
+ };
+ nvmeslot_4: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x4>;
+ };
+ nvmeslot_5: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x5>;
+ };
+ nvmeslot_6: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x6>;
+ };
+ nvmeslot_7: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x7>;
+ };
+ };
+
+ tmp432@4c {
+ compatible = "ti,tmp75";
+ reg = <0x4c>;
+ };
+ };
+
+ i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x7>;
+
+ i2c-mux@71 {
+ compatible = "nxp,pca9546";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x71>;
+ i2c-mux-idle-disconnect;
+
+ nvme_m2_0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0>;
+ };
+
+ nvme_m2_1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1>;
+ };
+ };
+ };
+ };
};
&i2c11 {
@@ -546,20 +818,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_adc0_default &pinctrl_adc1_default
- &pinctrl_adc2_default &pinctrl_adc3_default
- &pinctrl_adc4_default &pinctrl_adc5_default
- &pinctrl_adc6_default &pinctrl_adc7_default>;
-};
-
-&adc1 {
- ref_voltage = <2500>;
- status = "okay";
-
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_adc8_default &pinctrl_adc9_default
- &pinctrl_adc10_default &pinctrl_adc11_default
- &pinctrl_adc12_default &pinctrl_adc13_default
- &pinctrl_adc14_default &pinctrl_adc15_default>;
+ &pinctrl_adc2_default>;
};
&vhub {
@@ -575,16 +834,17 @@
gpio-line-names =
/*A0-A7*/ "","","","","","i2c2-reset-n","i2c6-reset-n","i2c4-reset-n",
/*B0-B7*/ "","","","","host0-sysreset-n","host0-pmin-n","","",
- /*C0-C7*/ "s0-vrd-fault-n","s1-vrd-fault-n","","",
+ /*C0-C7*/ "s0-vrd-fault-n","s1-vrd-fault-n","bmc-debug-mode","",
"irq-n","","vrd-sel","spd-sel",
/*D0-D7*/ "presence-ps0","presence-ps1","hsc-12vmain-alt2-n","ext-high-temp-n",
"","bmc-ncsi-txen","","",
- /*E0-E7*/ "","","clk50m-bmc-ncsi","","","","","",
+ /*E0-E7*/ "","eth-phy-int-n","clk50m-bmc-ncsi","","","","","",
/*F0-F7*/ "s0-pcp-oc-warn-n","s1-pcp-oc-warn-n","power-chassis-control",
"cpu-bios-recover","s0-heartbeat","hs-csout-prochot",
"s0-vr-hot-n","s1-vr-hot-n",
/*G0-G7*/ "","","hsc-12vmain-alt1-n","","","","","",
- /*H0-H7*/ "","","wd-disable-n","power-chassis-good","","","","",
+ /*H0-H7*/ "jtag-program-sel","fpga-program-b","wd-disable-n",
+ "power-chassis-good","","","","",
/*I0-I7*/ "","","","","","adc-sw","power-button","rtc-battery-voltage-read-enable",
/*J0-J7*/ "","","","","","","","",
/*K0-K7*/ "","","","","","","","",
@@ -599,17 +859,17 @@
/*Q0-Q7*/ "","","","","","","","",
/*R0-R7*/ "","","","","","","","",
/*S0-S7*/ "","","identify-button","led-identify",
- "s1-ddr-save","spi-nor-access","sys-pgood","presence-cpu1",
+ "s1-ddr-save","spi-nor-access","host0-ready","presence-cpu1",
/*T0-T7*/ "","","","","","","","",
/*U0-U7*/ "","","","","","","","",
/*V0-V7*/ "s0-hightemp-n","s0-fault-alert","s0-sys-auth-failure-n",
- "host0-reboot-ack-n","host0-ready","host0-shd-req-n",
+ "host0-reboot-ack-n","s0-fw-boot-ok","host0-shd-req-n",
"host0-shd-ack-n","s0-overtemp-n",
- /*W0-W7*/ "","ocp-main-pwren","ocp-pgood","",
+ /*W0-W7*/ "ocp-aux-pwren","ocp-main-pwren","ocp-pgood","s1-pcp-pgood",
"bmc-ok","bmc-ready","spi0-program-sel","spi0-backup-sel",
/*X0-X7*/ "i2c-backup-sel","s1-fault-alert","s1-fw-boot-ok",
"s1-hightemp-n","s0-spi-auth-fail-n","s1-sys-auth-failure-n",
- "s1-overtemp-n","s1-spi-auth-fail-n",
+ "s1-overtemp-n","cpld-s1-spi-auth-fail-n",
/*Y0-Y7*/ "","","","","","","","host0-special-boot",
/*Z0-Z7*/ "reset-button","ps0-pgood","ps1-pgood","","","","","";
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-minerva-cmc.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-minerva-cmc.dts
new file mode 100644
index 000000000000..f04ef9063520
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-minerva-cmc.dts
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2023 Facebook Inc.
+/dts-v1/;
+
+#include "aspeed-g6.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+#include <dt-bindings/i2c/i2c.h>
+
+/ {
+ model = "Facebook Minerva CMC";
+ compatible = "facebook,minerva-cmc", "aspeed,ast2600";
+
+ aliases {
+ serial5 = &uart5;
+ };
+
+ chosen {
+ stdout-path = "serial5:57600n8";
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x80000000>;
+ };
+
+ iio-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&adc0 0>, <&adc0 1>, <&adc0 2>, <&adc0 3>,
+ <&adc0 4>, <&adc0 5>, <&adc0 6>, <&adc0 7>,
+ <&adc1 2>;
+ };
+};
+
+&uart6 {
+ status = "okay";
+};
+
+&wdt1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdtrst1_default>;
+ aspeed,reset-type = "soc";
+ aspeed,external-signal;
+ aspeed,ext-push-pull;
+ aspeed,ext-active-high;
+ aspeed,ext-pulse-duration = <256>;
+};
+
+&mac3 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii4_default>;
+ use-ncsi;
+ mlx,multi-host;
+};
+
+&fmc {
+ status = "okay";
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "bmc";
+ spi-max-frequency = <50000000>;
+#include "openbmc-flash-layout-128.dtsi"
+ };
+ flash@1 {
+ status = "okay";
+ m25p,fast-read;
+ label = "alt-bmc";
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&rtc {
+ status = "okay";
+};
+
+&sgpiom1 {
+ status = "okay";
+ ngpios = <128>;
+ bus-frequency = <2000000>;
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+
+ temperature-sensor@4b {
+ compatible = "ti,tmp75";
+ reg = <0x4B>;
+ };
+
+ eeprom@51 {
+ compatible = "atmel,24c128";
+ reg = <0x51>;
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ i2c-mux@77 {
+ compatible = "nxp,pca9548";
+ reg = <0x77>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-mux-idle-disconnect;
+
+ i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ eeprom@50 {
+ compatible = "atmel,24c128";
+ reg = <0x50>;
+ };
+ };
+
+ i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ eeprom@50 {
+ compatible = "atmel,24c128";
+ reg = <0x50>;
+ };
+ };
+
+ i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+
+ eeprom@50 {
+ compatible = "atmel,24c128";
+ reg = <0x50>;
+ };
+ };
+
+ i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+
+ eeprom@50 {
+ compatible = "atmel,24c128";
+ reg = <0x50>;
+ };
+ };
+
+ i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+
+ eeprom@50 {
+ compatible = "atmel,24c128";
+ reg = <0x50>;
+ };
+ };
+
+ i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+
+ eeprom@50 {
+ compatible = "atmel,24c128";
+ reg = <0x50>;
+ };
+ };
+ };
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&i2c4 {
+ status = "okay";
+};
+
+&i2c5 {
+ status = "okay";
+};
+
+&i2c6 {
+ status = "okay";
+};
+
+&i2c7 {
+ status = "okay";
+};
+
+&i2c8 {
+ status = "okay";
+};
+
+&i2c9 {
+ status = "okay";
+};
+
+&i2c10 {
+ status = "okay";
+};
+
+&i2c11 {
+ status = "okay";
+};
+
+&i2c12 {
+ status = "okay";
+};
+
+&i2c13 {
+ status = "okay";
+};
+
+&i2c14 {
+ status = "okay";
+ multi-master;
+
+ ipmb@10 {
+ compatible = "ipmb-dev";
+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+ i2c-protocol;
+ };
+};
+
+&i2c15 {
+ status = "okay";
+
+ eeprom@50 {
+ compatible = "atmel,24c128";
+ reg = <0x50>;
+ };
+};
+
+&adc0 {
+ aspeed,int-vref-microvolt = <2500000>;
+ status = "okay";
+ pinctrl-0 = <&pinctrl_adc0_default &pinctrl_adc1_default
+ &pinctrl_adc2_default &pinctrl_adc3_default
+ &pinctrl_adc4_default &pinctrl_adc5_default
+ &pinctrl_adc6_default &pinctrl_adc7_default>;
+};
+
+&adc1 {
+ aspeed,int-vref-microvolt = <2500000>;
+ status = "okay";
+ pinctrl-0 = <&pinctrl_adc10_default>;
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&uhci {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-bonnell.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-bonnell.dts
index d47ce4edc67c..cad1b9aac97b 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-bonnell.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-bonnell.dts
@@ -34,6 +34,11 @@
#size-cells = <1>;
ranges;
+ event_log: tcg_event_log@b3d00000 {
+ no-map;
+ reg = <0xb3d00000 0x100000>;
+ };
+
ramoops@b3e00000 {
compatible = "ramoops";
reg = <0xb3e00000 0x200000>; /* 16 * (4 * 0x8000) */
@@ -454,8 +459,9 @@
status = "okay";
tpm@2e {
- compatible = "nuvoton,npct75x";
+ compatible = "nuvoton,npct75x", "tcg,tpm-tis-i2c";
reg = <0x2e>;
+ memory-region = <&event_log>;
};
eeprom@50 {
diff --git a/arch/arm/boot/dts/broadcom/bcm-ns.dtsi b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
index 88fda18af1f8..d0d5f7e52a91 100644
--- a/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
+++ b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi
@@ -14,6 +14,13 @@
#address-cells = <1>;
#size-cells = <1>;
+ pmu {
+ compatible = "arm,cortex-a9-pmu";
+ interrupts =
+ <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
chipcommon-a-bus@18000000 {
compatible = "simple-bus";
ranges = <0x00000000 0x18000000 0x00001000>;
@@ -320,6 +327,29 @@
#address-cells = <1>;
};
+ mdio-mux@18003000 {
+ compatible = "mdio-mux-mmioreg", "mdio-mux";
+ mdio-parent-bus = <&mdio>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x18003000 0x4>;
+ mux-mask = <0x200>;
+
+ mdio@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb3_phy: usb3-phy@10 {
+ compatible = "brcm,ns-ax-usb3-phy";
+ reg = <0x10>;
+ usb3-dmp-syscon = <&usb3_dmp>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+ };
+ };
+
rng: rng@18004000 {
compatible = "brcm,bcm5301x-rng";
reg = <0x18004000 0x14>;
@@ -460,6 +490,10 @@
brcm,nand-has-wp;
};
+ usb3_dmp: syscon@18105000 {
+ reg = <0x18105000 0x1000>;
+ };
+
thermal-zones {
cpu_thermal: cpu-thermal {
polling-delay-passive = <0>;
diff --git a/arch/arm/boot/dts/broadcom/bcm2711-rpi-400.dts b/arch/arm/boot/dts/broadcom/bcm2711-rpi-400.dts
index 1ab8184302db..5a2869a18bd5 100644
--- a/arch/arm/boot/dts/broadcom/bcm2711-rpi-400.dts
+++ b/arch/arm/boot/dts/broadcom/bcm2711-rpi-400.dts
@@ -36,9 +36,7 @@
gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
};
-&leds {
- /delete-node/ led_act;
-};
+/delete-node/ &led_act;
&pm {
/delete-property/ system-power-controller;
diff --git a/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp-common.dtsi b/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp-common.dtsi
index 42bcbf10957c..9f9084269ef5 100644
--- a/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp-common.dtsi
+++ b/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp-common.dtsi
@@ -181,5 +181,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm4708-luxul-xap-1510.dts b/arch/arm/boot/dts/broadcom/bcm4708-luxul-xap-1510.dts
index e04d2e5ea51a..72e960c888ac 100644
--- a/arch/arm/boot/dts/broadcom/bcm4708-luxul-xap-1510.dts
+++ b/arch/arm/boot/dts/broadcom/bcm4708-luxul-xap-1510.dts
@@ -85,5 +85,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm4708-luxul-xwc-1000.dts b/arch/arm/boot/dts/broadcom/bcm4708-luxul-xwc-1000.dts
index a399800139d9..750e17482371 100644
--- a/arch/arm/boot/dts/broadcom/bcm4708-luxul-xwc-1000.dts
+++ b/arch/arm/boot/dts/broadcom/bcm4708-luxul-xwc-1000.dts
@@ -88,5 +88,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm4708-netgear-r6250.dts b/arch/arm/boot/dts/broadcom/bcm4708-netgear-r6250.dts
index fad3473810a2..2bdbc7d18b0e 100644
--- a/arch/arm/boot/dts/broadcom/bcm4708-netgear-r6250.dts
+++ b/arch/arm/boot/dts/broadcom/bcm4708-netgear-r6250.dts
@@ -122,5 +122,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm4708-smartrg-sr400ac.dts b/arch/arm/boot/dts/broadcom/bcm4708-smartrg-sr400ac.dts
index 5b2b7b8b3b12..b226bef3369c 100644
--- a/arch/arm/boot/dts/broadcom/bcm4708-smartrg-sr400ac.dts
+++ b/arch/arm/boot/dts/broadcom/bcm4708-smartrg-sr400ac.dts
@@ -145,6 +145,14 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-600dhp2.dts b/arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-600dhp2.dts
index d0a26b643b82..192b8db5a89c 100644
--- a/arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-600dhp2.dts
+++ b/arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-600dhp2.dts
@@ -145,5 +145,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm47081-luxul-xap-1410.dts b/arch/arm/boot/dts/broadcom/bcm47081-luxul-xap-1410.dts
index 9f21d6d6d35b..0198b5f9e4a7 100644
--- a/arch/arm/boot/dts/broadcom/bcm47081-luxul-xap-1410.dts
+++ b/arch/arm/boot/dts/broadcom/bcm47081-luxul-xap-1410.dts
@@ -81,5 +81,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm47081-luxul-xwr-1200.dts b/arch/arm/boot/dts/broadcom/bcm47081-luxul-xwr-1200.dts
index 256107291702..73ff1694a4a0 100644
--- a/arch/arm/boot/dts/broadcom/bcm47081-luxul-xwr-1200.dts
+++ b/arch/arm/boot/dts/broadcom/bcm47081-luxul-xwr-1200.dts
@@ -148,5 +148,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts
index 4f44cb4df704..59400217f8c3 100644
--- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts
+++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts
@@ -25,6 +25,12 @@
<0x88000000 0x08000000>;
};
+ nvram@1c080000 {
+ et1macaddr: et1macaddr {
+ #nvmem-cell-cells = <1>;
+ };
+ };
+
leds {
compatible = "gpio-leds";
@@ -62,6 +68,11 @@
};
};
+&gmac0 {
+ nvmem-cells = <&et1macaddr 0>;
+ nvmem-cell-names = "mac-address";
+};
+
&usb3_phy {
status = "okay";
};
diff --git a/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts b/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts
index 99253fd7adb3..2ba5adf2b7e7 100644
--- a/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts
+++ b/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts
@@ -47,3 +47,41 @@
&usb3_phy {
status = "okay";
};
+
+&srab {
+ status = "okay";
+
+ ports {
+ port@0 {
+ label = "lan1";
+ };
+
+ port@1 {
+ label = "lan2";
+ };
+
+ port@2 {
+ label = "lan3";
+ };
+
+ port@3 {
+ label = "lan4";
+ };
+
+ port@4 {
+ label = "wan";
+ };
+
+ port@5 {
+ status = "disabled";
+ };
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ label = "cpu";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts b/arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts
index 707c561703ed..127ca8741220 100644
--- a/arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts
+++ b/arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts
@@ -227,6 +227,24 @@
label = "wan";
};
+ port@5 {
+ status = "disabled";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
+
+ port@7 {
+ status = "disabled";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
+
port@8 {
label = "cpu";
};
diff --git a/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts b/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts
index c914569ddd5e..c5099defe9f9 100644
--- a/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts
+++ b/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts
@@ -25,6 +25,15 @@
<0x88000000 0x08000000>;
};
+ nvram@1e3f0000 {
+ compatible = "brcm,nvram";
+ reg = <0x1e3f0000 0x10000>;
+
+ et2macaddr: et2macaddr {
+ #nvmem-cell-cells = <1>;
+ };
+ };
+
nand_controller: nand-controller@18028000 {
nand@0 {
partitions {
@@ -112,6 +121,11 @@
vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>;
};
+&gmac0 {
+ nvmem-cells = <&et2macaddr 0>;
+ nvmem-cell-names = "mac-address";
+};
+
&spi_nor {
status = "okay";
};
@@ -142,6 +156,16 @@
port@4 {
label = "wan";
+ nvmem-cells = <&et2macaddr 3>;
+ nvmem-cell-names = "mac-address";
+ };
+
+ port@5 {
+ status = "disabled";
+ };
+
+ port@7 {
+ status = "disabled";
};
port@8 {
diff --git a/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-890l.dts b/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-890l.dts
index f050acbea0b2..3124dfd01b94 100644
--- a/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-890l.dts
+++ b/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-890l.dts
@@ -192,6 +192,14 @@
label = "wan";
};
+ port@5 {
+ status = "disabled";
+ };
+
+ port@7 {
+ status = "disabled";
+ };
+
port@8 {
label = "cpu";
phy-mode = "rgmii";
diff --git a/arch/arm/boot/dts/broadcom/bcm47094-luxul-abr-4500.dts b/arch/arm/boot/dts/broadcom/bcm47094-luxul-abr-4500.dts
index e8991d4e248c..e374062eb5b7 100644
--- a/arch/arm/boot/dts/broadcom/bcm47094-luxul-abr-4500.dts
+++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-abr-4500.dts
@@ -107,5 +107,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xap-1610.dts b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xap-1610.dts
index afc635c8cdeb..badafa024d24 100644
--- a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xap-1610.dts
+++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xap-1610.dts
@@ -120,5 +120,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xbr-4500.dts b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xbr-4500.dts
index 7cfa4607ef31..cf95af9db1e6 100644
--- a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xbr-4500.dts
+++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xbr-4500.dts
@@ -107,5 +107,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwc-2000.dts b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwc-2000.dts
index d55e10095eae..992c19e1cfa1 100644
--- a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwc-2000.dts
+++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwc-2000.dts
@@ -75,5 +75,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3100.dts b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3100.dts
index ccf031c0e276..4d0ba315a204 100644
--- a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3100.dts
+++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3100.dts
@@ -147,5 +147,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3150-v1.dts b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3150-v1.dts
index e28f7a350117..83c429afc297 100644
--- a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3150-v1.dts
+++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3150-v1.dts
@@ -158,5 +158,13 @@
port@5 {
label = "cpu";
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts b/arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts
index 03ad614e6b72..0bf5106f7012 100644
--- a/arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts
+++ b/arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts
@@ -124,6 +124,14 @@
full-duplex;
};
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts b/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts
index 26c12bfb0bdd..25eeacf6a248 100644
--- a/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts
+++ b/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts
@@ -185,6 +185,14 @@
full-duplex;
};
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/broadcom/bcm5301x.dtsi b/arch/arm/boot/dts/broadcom/bcm5301x.dtsi
index 600a1b54f2ae..f06a178a9240 100644
--- a/arch/arm/boot/dts/broadcom/bcm5301x.dtsi
+++ b/arch/arm/boot/dts/broadcom/bcm5301x.dtsi
@@ -26,13 +26,6 @@
};
};
- pmu {
- compatible = "arm,cortex-a9-pmu";
- interrupts =
- <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
- };
-
clocks {
#address-cells = <1>;
#size-cells = <1>;
@@ -69,33 +62,6 @@
};
};
- mdio-mux@18003000 {
- compatible = "mdio-mux-mmioreg", "mdio-mux";
- mdio-parent-bus = <&mdio>;
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x18003000 0x4>;
- mux-mask = <0x200>;
-
- mdio@0 {
- reg = <0x0>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- usb3_phy: usb3-phy@10 {
- compatible = "brcm,ns-ax-usb3-phy";
- reg = <0x10>;
- usb3-dmp-syscon = <&usb3_dmp>;
- #phy-cells = <0>;
- status = "disabled";
- };
- };
- };
-
- usb3_dmp: syscon@18105000 {
- reg = <0x18105000 0x1000>;
- };
-
i2c0: i2c@18009000 {
compatible = "brcm,iproc-i2c";
reg = <0x18009000 0x50>;
diff --git a/arch/arm/boot/dts/broadcom/bcm953012er.dts b/arch/arm/boot/dts/broadcom/bcm953012er.dts
index 4fe3b3653376..d939ec9f4a9e 100644
--- a/arch/arm/boot/dts/broadcom/bcm953012er.dts
+++ b/arch/arm/boot/dts/broadcom/bcm953012er.dts
@@ -84,6 +84,14 @@
label = "cpu";
ethernet = <&gmac0>;
};
+
+ port@7 {
+ status = "disabled";
+ };
+
+ port@8 {
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/intel/ixp/Makefile b/arch/arm/boot/dts/intel/ixp/Makefile
index 1a25ce3cf84f..ab8525f1ea1d 100644
--- a/arch/arm/boot/dts/intel/ixp/Makefile
+++ b/arch/arm/boot/dts/intel/ixp/Makefile
@@ -16,4 +16,5 @@ dtb-$(CONFIG_ARCH_IXP4XX) += \
intel-ixp43x-gateworks-gw2358.dtb \
intel-ixp42x-netgear-wg302v1.dtb \
intel-ixp42x-arcom-vulcan.dtb \
- intel-ixp42x-gateway-7001.dtb
+ intel-ixp42x-gateway-7001.dtb \
+ intel-ixp42x-usrobotics-usr8200.dtb
diff --git a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-dlink-dsm-g600.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-dlink-dsm-g600.dts
index b9d46eb06507..fa133c913606 100644
--- a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-dlink-dsm-g600.dts
+++ b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-dlink-dsm-g600.dts
@@ -57,7 +57,7 @@
button-reset {
wakeup-source;
- linux,code = <KEY_ESC>;
+ linux,code = <KEY_RESTART>;
label = "reset";
gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-freecom-fsg-3.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-freecom-fsg-3.dts
index 5a5e16cc7335..73d3c11dd0d4 100644
--- a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-freecom-fsg-3.dts
+++ b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-freecom-fsg-3.dts
@@ -44,7 +44,7 @@
};
button-reset {
wakeup-source;
- linux,code = <KEY_ESC>;
+ linux,code = <KEY_RESTART>;
label = "reset";
gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-iomega-nas100d.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-iomega-nas100d.dts
index 8da6823e1dbe..26f02dad6a54 100644
--- a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-iomega-nas100d.dts
+++ b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-iomega-nas100d.dts
@@ -63,7 +63,7 @@
};
button-reset {
wakeup-source;
- linux,code = <KEY_ESC>;
+ linux,code = <KEY_RESTART>;
label = "reset";
gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-nslu2.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-nslu2.dts
index da1e93212b86..2eec5f63d399 100644
--- a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-nslu2.dts
+++ b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-nslu2.dts
@@ -65,7 +65,7 @@
};
button-reset {
wakeup-source;
- linux,code = <KEY_ESC>;
+ linux,code = <KEY_RESTART>;
label = "reset";
gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
};
@@ -101,6 +101,8 @@
flash@0,0 {
compatible = "intel,ixp4xx-flash", "cfi-flash";
bank-width = <2>;
+ /* Enable writes on the expansion bus */
+ intel,ixp4xx-eb-write-enable = <1>;
/*
* 8 MB of Flash in 0x20000 byte blocks
* mapped in at CS0.
diff --git a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-wrv54g.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-wrv54g.dts
index 4aba9e0214a0..98275a363c57 100644
--- a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-wrv54g.dts
+++ b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-wrv54g.dts
@@ -13,7 +13,7 @@
/ {
model = "Linksys WRV54G / Gemtek GTWX5715";
- compatible = "linksys,wrv54g", "gemtek,gtwx5715", "intel,ixp42x";
+ compatible = "linksys,wrv54g", "intel,ixp42x";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-usrobotics-usr8200.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-usrobotics-usr8200.dts
new file mode 100644
index 000000000000..90fd51b36e7d
--- /dev/null
+++ b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-usrobotics-usr8200.dts
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for the USRobotics USR8200 firewall
+ * VPN and NAS. Based on know-how from Peter Denison.
+ *
+ * This machine is based on IXP422, the USR internal codename
+ * is "Jeeves".
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "USRobotics USR8200";
+ compatible = "usr,usr8200", "intel,ixp42x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x4000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8";
+ stdout-path = "uart1:115200n8";
+ };
+
+ aliases {
+ /* These are switched around */
+ serial0 = &uart1;
+ serial1 = &uart0;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ ieee1394_led: led-1394 {
+ label = "usr8200:green:1394";
+ gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+ usb1_led: led-usb1 {
+ label = "usr8200:green:usb1";
+ gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+ usb2_led: led-usb2 {
+ label = "usr8200:green:usb2";
+ gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+ wireless_led: led-wireless {
+ /*
+ * This LED is mounted inside the case but cannot be
+ * seen from the outside: probably USR planned at one
+ * point for the device to have a wireless card, then
+ * changed their mind and didn't mount it, leaving the
+ * LED in place.
+ */
+ label = "usr8200:green:wireless";
+ gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+ pwr_led: led-pwr {
+ label = "usr8200:green:pwr";
+ gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+
+ button-reset {
+ wakeup-source;
+ linux,code = <KEY_RESTART>;
+ label = "reset";
+ gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ soc {
+ bus@c4000000 {
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /* Enable writes on the expansion bus */
+ intel,ixp4xx-eb-write-enable = <1>;
+ /* 16 MB of Flash mapped in at CS0 */
+ reg = <0 0x00000000 0x1000000>;
+
+ partitions {
+ compatible = "redboot-fis";
+ /* Eraseblock at 0x0fe0000 */
+ fis-index-block = <0x7f>;
+ };
+ };
+ rtc@2,0 {
+ /* EPSON RTC7301 DG DIL-capsule */
+ compatible = "epson,rtc7301dg";
+ /*
+ * These timing settings were found in the boardfile patch:
+ * IXP4XX_EXP_CS2 = 0x3fff000 | IXP4XX_EXP_BUS_SIZE(0) | IXP4XX_EXP_BUS_WR_EN |
+ * IXP4XX_EXP_BUS_CS_EN | IXP4XX_EXP_BUS_BYTE_EN;
+ */
+ intel,ixp4xx-eb-t1 = <0>; // no cycles extra address phase
+ intel,ixp4xx-eb-t2 = <0>; // no cycles extra setup phase
+ intel,ixp4xx-eb-t3 = <15>; // 15 cycles extra strobe phase
+ intel,ixp4xx-eb-t4 = <3>; // 3 cycles extra hold phase
+ intel,ixp4xx-eb-t5 = <15>; // 15 cycles extra recovery phase
+ intel,ixp4xx-eb-cycle-type = <0>; // Intel cycle
+ intel,ixp4xx-eb-byte-access-on-halfword = <0>;
+ intel,ixp4xx-eb-mux-address-and-data = <0>;
+ intel,ixp4xx-eb-ahb-split-transfers = <0>;
+ intel,ixp4xx-eb-write-enable = <1>;
+ intel,ixp4xx-eb-byte-access = <1>;
+ /* 512 bytes at CS2 */
+ reg = <2 0x00000000 0x0000200>;
+ reg-io-width = <1>;
+ native-endian;
+ /* FIXME: try to check if there is an IRQ for the RTC? */
+ };
+ };
+
+ pci@c0000000 {
+ status = "okay";
+
+ /*
+ * Taken from USR8200 boardfile from OpenWrt
+ *
+ * We have 3 slots (IDSEL) with partly swizzled IRQs on slot 16.
+ * We assume the same IRQ for all pins on the remaining slots, that
+ * is what the boardfile was doing.
+ */
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map =
+ /* IDSEL 14 used for "Wireless" in the board file */
+ <0x7000 0 0 1 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 14 is irq 7 */
+ /* IDSEL 15 used for VIA VT6307 IEEE 1394 Firewire */
+ <0x7800 0 0 1 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 15 is irq 8 */
+ /* IDSEL 16 used for VIA VT6202 USB 2.0 4+1 */
+ <0x8000 0 0 1 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 16 is irq 11 */
+ <0x8000 0 0 2 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 16 is irq 10 */
+ <0x8000 0 0 3 &gpio0 9 IRQ_TYPE_LEVEL_LOW>; /* INT C on slot 16 is irq 9 */
+ };
+
+ gpio@c8004000 {
+ /* Enable clock out on GPIO 15 */
+ intel,ixp4xx-gpio15-clkout;
+ };
+
+ /* EthB WAN */
+ ethernet@c8009000 {
+ status = "okay";
+ queue-rx = <&qmgr 3>;
+ queue-txready = <&qmgr 20>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy9>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy9: ethernet-phy@9 {
+ reg = <9>;
+ };
+
+ /* The switch uses MDIO addresses 16 thru 31 */
+ switch@16 {
+ compatible = "marvell,mv88e6060";
+ reg = <16>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ label = "lan1";
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "lan2";
+ };
+
+ port@2 {
+ reg = <2>;
+ label = "lan3";
+ };
+
+ port@3 {
+ reg = <3>;
+ label = "lan4";
+ };
+
+ port@5 {
+ /* Port 5 is the CPU port according to the MV88E6060 datasheet */
+ reg = <5>;
+ phy-mode = "rgmii-id";
+ ethernet = <&ethc>;
+ label = "cpu";
+ fixed-link {
+ speed = <100>;
+ full-duplex;
+ };
+ };
+ };
+ };
+ };
+ };
+
+ /* EthC LAN connected to the Marvell DSA Switch */
+ ethc: ethernet@c800a000 {
+ status = "okay";
+ queue-rx = <&qmgr 4>;
+ queue-txready = <&qmgr 21>;
+ phy-mode = "rgmii";
+ fixed-link {
+ speed = <100>;
+ full-duplex;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/mediatek/mt2701-evb.dts b/arch/arm/boot/dts/mediatek/mt2701-evb.dts
index d1535f385f36..9c7325f18933 100644
--- a/arch/arm/boot/dts/mediatek/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mediatek/mt2701-evb.dts
@@ -244,7 +244,7 @@
&usb2 {
status = "okay";
usb-role-switch;
- connector{
+ connector {
compatible = "gpio-usb-b-connector", "usb-b-connector";
type = "micro";
id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/mediatek/mt6323.dtsi b/arch/arm/boot/dts/mediatek/mt6323.dtsi
index 7fda40ab5fe8..c230c865116d 100644
--- a/arch/arm/boot/dts/mediatek/mt6323.dtsi
+++ b/arch/arm/boot/dts/mediatek/mt6323.dtsi
@@ -21,10 +21,10 @@
status = "disabled";
};
- mt6323regulator: mt6323regulator{
+ mt6323regulator: mt6323regulator {
compatible = "mediatek,mt6323-regulator";
- mt6323_vproc_reg: buck_vproc{
+ mt6323_vproc_reg: buck_vproc {
regulator-name = "vproc";
regulator-min-microvolt = < 700000>;
regulator-max-microvolt = <1350000>;
@@ -33,7 +33,7 @@
regulator-boot-on;
};
- mt6323_vsys_reg: buck_vsys{
+ mt6323_vsys_reg: buck_vsys {
regulator-name = "vsys";
regulator-min-microvolt = <1400000>;
regulator-max-microvolt = <2987500>;
@@ -42,13 +42,13 @@
regulator-boot-on;
};
- mt6323_vpa_reg: buck_vpa{
+ mt6323_vpa_reg: buck_vpa {
regulator-name = "vpa";
regulator-min-microvolt = < 500000>;
regulator-max-microvolt = <3650000>;
};
- mt6323_vtcxo_reg: ldo_vtcxo{
+ mt6323_vtcxo_reg: ldo_vtcxo {
regulator-name = "vtcxo";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
@@ -57,28 +57,28 @@
regulator-boot-on;
};
- mt6323_vcn28_reg: ldo_vcn28{
+ mt6323_vcn28_reg: ldo_vcn28 {
regulator-name = "vcn28";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-enable-ramp-delay = <185>;
};
- mt6323_vcn33_bt_reg: ldo_vcn33_bt{
+ mt6323_vcn33_bt_reg: ldo_vcn33_bt {
regulator-name = "vcn33_bt";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3600000>;
regulator-enable-ramp-delay = <185>;
};
- mt6323_vcn33_wifi_reg: ldo_vcn33_wifi{
+ mt6323_vcn33_wifi_reg: ldo_vcn33_wifi {
regulator-name = "vcn33_wifi";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3600000>;
regulator-enable-ramp-delay = <185>;
};
- mt6323_va_reg: ldo_va{
+ mt6323_va_reg: ldo_va {
regulator-name = "va";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
@@ -87,14 +87,14 @@
regulator-boot-on;
};
- mt6323_vcama_reg: ldo_vcama{
+ mt6323_vcama_reg: ldo_vcama {
regulator-name = "vcama";
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <2800000>;
regulator-enable-ramp-delay = <216>;
};
- mt6323_vio28_reg: ldo_vio28{
+ mt6323_vio28_reg: ldo_vio28 {
regulator-name = "vio28";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
@@ -103,7 +103,7 @@
regulator-boot-on;
};
- mt6323_vusb_reg: ldo_vusb{
+ mt6323_vusb_reg: ldo_vusb {
regulator-name = "vusb";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
@@ -111,7 +111,7 @@
regulator-boot-on;
};
- mt6323_vmc_reg: ldo_vmc{
+ mt6323_vmc_reg: ldo_vmc {
regulator-name = "vmc";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
@@ -119,7 +119,7 @@
regulator-boot-on;
};
- mt6323_vmch_reg: ldo_vmch{
+ mt6323_vmch_reg: ldo_vmch {
regulator-name = "vmch";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3300000>;
@@ -127,7 +127,7 @@
regulator-boot-on;
};
- mt6323_vemc3v3_reg: ldo_vemc3v3{
+ mt6323_vemc3v3_reg: ldo_vemc3v3 {
regulator-name = "vemc3v3";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3300000>;
@@ -135,49 +135,49 @@
regulator-boot-on;
};
- mt6323_vgp1_reg: ldo_vgp1{
+ mt6323_vgp1_reg: ldo_vgp1 {
regulator-name = "vgp1";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3300000>;
regulator-enable-ramp-delay = <216>;
};
- mt6323_vgp2_reg: ldo_vgp2{
+ mt6323_vgp2_reg: ldo_vgp2 {
regulator-name = "vgp2";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3000000>;
regulator-enable-ramp-delay = <216>;
};
- mt6323_vgp3_reg: ldo_vgp3{
+ mt6323_vgp3_reg: ldo_vgp3 {
regulator-name = "vgp3";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1800000>;
regulator-enable-ramp-delay = <216>;
};
- mt6323_vcn18_reg: ldo_vcn18{
+ mt6323_vcn18_reg: ldo_vcn18 {
regulator-name = "vcn18";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-enable-ramp-delay = <216>;
};
- mt6323_vsim1_reg: ldo_vsim1{
+ mt6323_vsim1_reg: ldo_vsim1 {
regulator-name = "vsim1";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3000000>;
regulator-enable-ramp-delay = <216>;
};
- mt6323_vsim2_reg: ldo_vsim2{
+ mt6323_vsim2_reg: ldo_vsim2 {
regulator-name = "vsim2";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3000000>;
regulator-enable-ramp-delay = <216>;
};
- mt6323_vrtc_reg: ldo_vrtc{
+ mt6323_vrtc_reg: ldo_vrtc {
regulator-name = "vrtc";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
@@ -185,28 +185,28 @@
regulator-boot-on;
};
- mt6323_vcamaf_reg: ldo_vcamaf{
+ mt6323_vcamaf_reg: ldo_vcamaf {
regulator-name = "vcamaf";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3300000>;
regulator-enable-ramp-delay = <216>;
};
- mt6323_vibr_reg: ldo_vibr{
+ mt6323_vibr_reg: ldo_vibr {
regulator-name = "vibr";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3300000>;
regulator-enable-ramp-delay = <36>;
};
- mt6323_vrf18_reg: ldo_vrf18{
+ mt6323_vrf18_reg: ldo_vrf18 {
regulator-name = "vrf18";
regulator-min-microvolt = <1825000>;
regulator-max-microvolt = <1825000>;
regulator-enable-ramp-delay = <187>;
};
- mt6323_vm_reg: ldo_vm{
+ mt6323_vm_reg: ldo_vm {
regulator-name = "vm";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1800000>;
@@ -215,7 +215,7 @@
regulator-boot-on;
};
- mt6323_vio18_reg: ldo_vio18{
+ mt6323_vio18_reg: ldo_vio18 {
regulator-name = "vio18";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
@@ -224,14 +224,14 @@
regulator-boot-on;
};
- mt6323_vcamd_reg: ldo_vcamd{
+ mt6323_vcamd_reg: ldo_vcamd {
regulator-name = "vcamd";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1800000>;
regulator-enable-ramp-delay = <216>;
};
- mt6323_vcamio_reg: ldo_vcamio{
+ mt6323_vcamio_reg: ldo_vcamio {
regulator-name = "vcamio";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
diff --git a/arch/arm/boot/dts/mediatek/mt7623n.dtsi b/arch/arm/boot/dts/mediatek/mt7623n.dtsi
index 3adab5cd1fef..3e5cabf19cde 100644
--- a/arch/arm/boot/dts/mediatek/mt7623n.dtsi
+++ b/arch/arm/boot/dts/mediatek/mt7623n.dtsi
@@ -116,8 +116,8 @@
"mediatek,mt2701-jpgdec";
reg = <0 0x15004000 0 0x1000>;
interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_LOW>;
- clocks = <&imgsys CLK_IMG_JPGDEC_SMI>,
- <&imgsys CLK_IMG_JPGDEC>;
+ clocks = <&imgsys CLK_IMG_JPGDEC_SMI>,
+ <&imgsys CLK_IMG_JPGDEC>;
clock-names = "jpgdec-smi",
"jpgdec";
power-domains = <&scpsys MT2701_POWER_DOMAIN_ISP>;
diff --git a/arch/arm/boot/dts/mediatek/mt7629-rfb.dts b/arch/arm/boot/dts/mediatek/mt7629-rfb.dts
index 84e14bee7235..f24ebc20732a 100644
--- a/arch/arm/boot/dts/mediatek/mt7629-rfb.dts
+++ b/arch/arm/boot/dts/mediatek/mt7629-rfb.dts
@@ -168,7 +168,7 @@
i2c_pins: i2c-pins {
mux {
function = "i2c";
- groups = "i2c_0";
+ groups = "i2c_0";
};
conf {
diff --git a/arch/arm/boot/dts/microchip/Makefile b/arch/arm/boot/dts/microchip/Makefile
index 31e03747cdf4..efde9546c8f4 100644
--- a/arch/arm/boot/dts/microchip/Makefile
+++ b/arch/arm/boot/dts/microchip/Makefile
@@ -4,6 +4,7 @@ DTC_FLAGS_at91-sam9x60_curiosity := -@
DTC_FLAGS_at91-sam9x60ek := -@
DTC_FLAGS_at91-sama5d27_som1_ek := -@
DTC_FLAGS_at91-sama5d27_wlsom1_ek := -@
+DTC_FLAGS_at91-sama5d29_curiosity := -@
DTC_FLAGS_at91-sama5d2_icp := -@
DTC_FLAGS_at91-sama5d2_ptc_ek := -@
DTC_FLAGS_at91-sama5d2_xplained := -@
@@ -64,6 +65,7 @@ dtb-$(CONFIG_SOC_SAM_V7) += \
at91-nattis-2-natte-2.dtb \
at91-sama5d27_som1_ek.dtb \
at91-sama5d27_wlsom1_ek.dtb \
+ at91-sama5d29_curiosity.dtb \
at91-sama5d2_icp.dtb \
at91-sama5d2_ptc_ek.dtb \
at91-sama5d2_xplained.dtb \
diff --git a/arch/arm/boot/dts/microchip/at91-sam9x60_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sam9x60_curiosity.dts
index cb86a3a170ce..83372c1f291b 100644
--- a/arch/arm/boot/dts/microchip/at91-sam9x60_curiosity.dts
+++ b/arch/arm/boot/dts/microchip/at91-sam9x60_curiosity.dts
@@ -439,6 +439,10 @@
status = "okay";
};
+&rtt {
+ atmel,rtt-rtc-time-reg = <&gpbr 0x0>;
+};
+
&sdmmc0 {
bus-width = <4>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts
new file mode 100644
index 000000000000..6b02b7bcfd49
--- /dev/null
+++ b/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts
@@ -0,0 +1,600 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * at91-sama5d29_curiosity.dts - Device Tree file for SAMA5D29 Curiosity board
+ *
+ * Copyright (C) 2023 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Mihai Sain <mihai.sain@microchip.com>
+ *
+ */
+/dts-v1/;
+#include "sama5d29.dtsi"
+#include "sama5d2-pinfunc.h"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/mfd/atmel-flexcom.h>
+
+/ {
+ model = "Microchip SAMA5D29 Curiosity";
+ compatible = "microchip,sama5d29-curiosity", "atmel,sama5d29", "atmel,sama5d2", "atmel,sama5";
+
+ aliases {
+ serial0 = &uart0; // debug
+ serial1 = &uart1; // RPi
+ serial2 = &uart3; // mikro BUS 2
+ serial3 = &uart4; // mikro BUS 1
+ serial4 = &uart6; // flx1 Bluetooth
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait";
+ stdout-path = "serial0:115200n8";
+ };
+
+ clocks {
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <24000000>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_key_gpio_default>;
+
+ button-1 {
+ label = "USER BUTTON";
+ gpios = <&pioA PIN_PA17 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_PROG1>;
+ wakeup-source;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_led_gpio_default>;
+ status = "okay";
+
+ led-red {
+ label = "red";
+ gpios = <&pioA PIN_PA7 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-green {
+ label = "green";
+ gpios = <&pioA PIN_PA8 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-blue {
+ label = "blue";
+ gpios = <&pioA PIN_PA9 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ memory@20000000 {
+ device_type = "memory";
+ reg = <0x20000000 0x20000000>;
+ };
+};
+
+&adc {
+ vddana-supply = <&vdd_3v3>;
+ vref-supply = <&vdd_3v3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
+ status = "okay";
+};
+
+&can0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can0_default>;
+ status = "okay";
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can1_default>;
+ status = "okay";
+};
+
+&flx1 {
+ atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_USART>;
+ status = "okay";
+
+ uart6: serial@200 {
+ pinctrl-0 = <&pinctrl_flx1_default>;
+ pinctrl-names = "default";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "okay";
+ };
+};
+
+&flx4 {
+ atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_SPI>;
+ status = "okay";
+
+ spi6: spi@400 {
+ dmas = <0>, <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rpi_spi>;
+ status = "okay";
+ };
+};
+
+&i2c0 {
+ dmas = <0>, <0>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c0_default>;
+ pinctrl-1 = <&pinctrl_i2c0_gpio>;
+ sda-gpios = <&pioA PIN_PB31 GPIO_ACTIVE_HIGH>;
+ scl-gpios = <&pioA PIN_PC0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ i2c-sda-hold-time-ns = <350>;
+ status = "okay";
+
+ mcp16502@5b {
+ compatible = "microchip,mcp16502";
+ reg = <0x5b>;
+ status = "okay";
+ lpm-gpios = <&pioBU 0 GPIO_ACTIVE_LOW>;
+
+ regulators {
+ vdd_3v3: VDD_IO {
+ regulator-name = "VDD_IO";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <2>;
+ regulator-allowed-modes = <2>, <4>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-mode = <4>;
+ };
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-mode = <4>;
+ };
+ };
+
+ vddio_ddr: VDD_DDR {
+ regulator-name = "VDD_DDR";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <2>;
+ regulator-allowed-modes = <2>, <4>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1200000>;
+ regulator-changeable-in-suspend;
+ regulator-mode = <4>;
+ };
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1200000>;
+ regulator-changeable-in-suspend;
+ regulator-mode = <4>;
+ };
+ };
+
+ vdd_core: VDD_CORE {
+ regulator-name = "VDD_CORE";
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-initial-mode = <2>;
+ regulator-allowed-modes = <2>, <4>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-mode = <4>;
+ };
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-mode = <4>;
+ };
+ };
+
+ vdd_ddr: VDD_OTHER {
+ regulator-name = "VDD_OTHER";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <2>;
+ regulator-allowed-modes = <2>, <4>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ regulator-changeable-in-suspend;
+ regulator-mode = <4>;
+ };
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ regulator-changeable-in-suspend;
+ regulator-mode = <4>;
+ };
+ };
+
+ LDO1 {
+ regulator-name = "LDO1";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ };
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ LDO2 {
+ regulator-name = "LDO2";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ };
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&i2c1 {
+ dmas = <0>, <0>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c1_default>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ i2c-analog-filter;
+ i2c-digital-filter;
+ i2c-digital-filter-width-ns = <35>;
+ sda-gpios = <&pioA PIN_PD4 GPIO_ACTIVE_HIGH>;
+ scl-gpios = <&pioA PIN_PD5 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+};
+
+&pioA {
+ pinctrl_adc_default: adc-default {
+ pinmux = <PIN_PD25__GPIO>,
+ <PIN_PD26__GPIO>;
+ bias-disable;
+ };
+
+ pinctrl_adtrg_default: adtrg-default {
+ pinmux = <PIN_PD31__ADTRG>;
+ bias-pull-up;
+ };
+
+ pinctrl_can0_default: can0-default {
+ pinmux = <PIN_PC10__CANTX0>,
+ <PIN_PC11__CANRX0>;
+ bias-disable;
+ };
+
+ pinctrl_can1_default: can1-default {
+ pinmux = <PIN_PC26__CANTX1>,
+ <PIN_PC27__CANRX1>;
+ bias-disable;
+ };
+
+ pinctrl_debug_uart: debug-uart {
+ pinmux = <PIN_PB26__URXD0>,
+ <PIN_PB27__UTXD0>;
+ bias-disable;
+ };
+
+ pinctrl_flx1_default: flx1-default {
+ pinmux = <PIN_PA24__FLEXCOM1_IO0>,
+ <PIN_PA23__FLEXCOM1_IO1>,
+ <PIN_PA25__FLEXCOM1_IO3>,
+ <PIN_PA26__FLEXCOM1_IO4>;
+ bias-disable;
+ };
+
+ pinctrl_i2c0_default: i2c0-default {
+ pinmux = <PIN_PB31__TWD0>,
+ <PIN_PC0__TWCK0>;
+ bias-disable;
+ };
+
+ pinctrl_i2c0_gpio: i2c0-gpio-default {
+ pinmux = <PIN_PB31__GPIO>,
+ <PIN_PC0__GPIO>;
+ bias-disable;
+ };
+
+ pinctrl_i2c1_default: i2c1-default {
+ pinmux = <PIN_PD4__TWD1>,
+ <PIN_PD5__TWCK1>;
+ bias-disable;
+ };
+
+ pinctrl_i2c1_gpio: i2c1-gpio-default {
+ pinmux = <PIN_PD4__GPIO>,
+ <PIN_PD5__GPIO>;
+ bias-disable;
+ };
+
+ pinctrl_key_gpio_default: key-gpio-default {
+ pinmux = <PIN_PA17__GPIO>;
+ bias-pull-up;
+ };
+
+ pinctrl_led_gpio_default: led-gpio-default {
+ pinmux = <PIN_PA7__GPIO>,
+ <PIN_PA8__GPIO>,
+ <PIN_PA9__GPIO>;
+ bias-pull-up;
+ };
+
+ pinctrl_mikrobus1_pwm: mikrobus1-pwm {
+ pinmux = <PIN_PA31__PWML0>;
+ bias-disable;
+ };
+
+ pinctrl_mikrobus2_pwm: mikrobus2-pwm {
+ pinmux = <PIN_PB0__PWMH1>;
+ bias-disable;
+ };
+
+ pinctrl_mikrobus1_uart: mikrobus1-uart {
+ pinmux = <PIN_PB3__URXD4>,
+ <PIN_PB4__UTXD4>;
+ bias-disable;
+ };
+
+ pinctrl_mikrobus2_uart: mikrobus2-uart {
+ pinmux = <PIN_PB11__URXD3>,
+ <PIN_PB12__UTXD3>;
+ bias-disable;
+ };
+
+ pinctrl_qspi1_default: qspi1-default {
+ pinmux = <PIN_PB5__QSPI1_SCK>,
+ <PIN_PB6__QSPI1_CS>,
+ <PIN_PB7__QSPI1_IO0>,
+ <PIN_PB8__QSPI1_IO1>,
+ <PIN_PB9__QSPI1_IO2>,
+ <PIN_PB10__QSPI1_IO3>;
+ bias-disable;
+ };
+
+ pinctrl_rpi_spi: rpi-spi {
+ pinmux = <PIN_PD12__FLEXCOM4_IO0>,
+ <PIN_PD13__FLEXCOM4_IO1>,
+ <PIN_PD14__FLEXCOM4_IO2>,
+ <PIN_PD15__FLEXCOM4_IO3>,
+ <PIN_PD16__FLEXCOM4_IO4>;
+ bias-disable;
+ };
+
+ pinctrl_rpi_uart: rpi-uart {
+ pinmux = <PIN_PD2__URXD1>,
+ <PIN_PD3__UTXD1>;
+ bias-disable;
+ };
+
+ pinctrl_sdmmc0_default: sdmmc0-default {
+ pinmux = <PIN_PA0__SDMMC0_CK>,
+ <PIN_PA1__SDMMC0_CMD>,
+ <PIN_PA2__SDMMC0_DAT0>,
+ <PIN_PA3__SDMMC0_DAT1>,
+ <PIN_PA4__SDMMC0_DAT2>,
+ <PIN_PA5__SDMMC0_DAT3>,
+ <PIN_PA11__SDMMC0_VDDSEL>,
+ <PIN_PA13__SDMMC0_CD>;
+ bias-disable;
+ };
+
+ pinctrl_sdmmc1_default: sdmmc1-default {
+ pinmux = <PIN_PA18__SDMMC1_DAT0>,
+ <PIN_PA19__SDMMC1_DAT1>,
+ <PIN_PA20__SDMMC1_DAT2>,
+ <PIN_PA21__SDMMC1_DAT3>,
+ <PIN_PA22__SDMMC1_CK>,
+ <PIN_PA28__SDMMC1_CMD>,
+ <PIN_PA30__SDMMC1_CD>;
+ bias-disable;
+ };
+
+ pinctrl_spi1_default: spi1-default {
+ pinmux = <PIN_PC1__SPI1_SPCK>,
+ <PIN_PC2__SPI1_MOSI>,
+ <PIN_PC3__SPI1_MISO>,
+ <PIN_PC4__SPI1_NPCS0>,
+ <PIN_PC5__SPI1_NPCS1>,
+ <PIN_PC6__SPI1_NPCS2>,
+ <PIN_PC7__SPI1_NPCS3>;
+ bias-disable;
+ };
+
+ pinctrl_usb_default: usb-default {
+ pinmux = <PIN_PA6__GPIO>;
+ bias-disable;
+ };
+
+ pinctrl_usba_vbus: usba-vbus {
+ pinmux = <PIN_PB13__GPIO>;
+ bias-disable;
+ };
+};
+
+&pwm0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mikrobus1_pwm &pinctrl_mikrobus2_pwm>;
+ status = "okay";
+};
+
+&qspi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi1_default>;
+ status = "okay";
+
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <80000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ m25p,fast-read;
+ label = "atmel_qspi1";
+ status = "okay";
+
+ at91bootstrap@0 {
+ label = "at91bootstrap";
+ reg = <0x0 0x40000>;
+ };
+
+ bootloader@40000 {
+ label = "bootloader";
+ reg = <0x40000 0xc0000>;
+ };
+
+ bootloaderenvred@100000 {
+ label = "bootloader env redundant";
+ reg = <0x100000 0x40000>;
+ };
+
+ bootloaderenv@140000 {
+ label = "bootloader env";
+ reg = <0x140000 0x40000>;
+ };
+
+ dtb@180000 {
+ label = "device tree";
+ reg = <0x180000 0x80000>;
+ };
+
+ kernel@200000 {
+ label = "kernel";
+ reg = <0x200000 0x600000>;
+ };
+ };
+};
+
+&sdmmc0 {
+ bus-width = <4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sdmmc0_default>;
+ disable-wp;
+ status = "okay";
+};
+
+&sdmmc1 {
+ bus-width = <4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sdmmc1_default>;
+ disable-wp;
+ status = "okay";
+};
+
+&shutdown_controller {
+ debounce-delay-us = <976>;
+ atmel,wakeup-rtc-timer;
+
+ input@0 {
+ reg = <0>;
+ };
+};
+
+&spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi1_default>;
+ status = "okay";
+};
+
+&tcb0 {
+ timer0: timer@0 {
+ compatible = "atmel,tcb-timer";
+ reg = <0>;
+ };
+
+ timer1: timer@1 {
+ compatible = "atmel,tcb-timer";
+ reg = <1>;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_debug_uart>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rpi_uart>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mikrobus2_uart>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mikrobus1_uart>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "okay";
+};
+
+&usb0 {
+ atmel,vbus-gpio = <&pioA PIN_PB13 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usba_vbus>;
+ status = "okay";
+};
+
+&usb1 {
+ num-ports = <3>;
+ atmel,vbus-gpio = <0
+ &pioA PIN_PA6 GPIO_ACTIVE_HIGH
+ 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_default>;
+ status = "okay";
+};
+
+&usb2 {
+ status = "okay";
+};
+
+&watchdog {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/microchip/sama5d4.dtsi b/arch/arm/boot/dts/microchip/sama5d4.dtsi
index 50650e2f4267..58ceed997889 100644
--- a/arch/arm/boot/dts/microchip/sama5d4.dtsi
+++ b/arch/arm/boot/dts/microchip/sama5d4.dtsi
@@ -694,7 +694,7 @@
clock-names = "aes_clk";
};
- tdes: crpyto@fc04c000 {
+ tdes: crypto@fc04c000 {
compatible = "atmel,at91sam9g46-tdes";
reg = <0xfc04c000 0x100>;
interrupts = <14 IRQ_TYPE_LEVEL_HIGH 0>;
diff --git a/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-gsj.dts b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-gsj.dts
index 9b1cc7f4adf0..cd7843339c24 100644
--- a/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-gsj.dts
+++ b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-gsj.dts
@@ -146,7 +146,7 @@
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
- bmc@0{
+ bmc@0 {
label = "bmc";
reg = <0x000000 0x2000000>;
};
@@ -155,7 +155,7 @@
reg = <0x0000000 0x80000>;
read-only;
};
- u-boot-env@100000{
+ u-boot-env@100000 {
label = "u-boot-env";
reg = <0x00100000 0x40000>;
};
diff --git a/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts
index 58329adbd918..5787ae95d3b4 100644
--- a/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts
+++ b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts
@@ -397,7 +397,7 @@
reg = <0x0000000 0xC0000>;
read-only;
};
- u-boot-env@100000{
+ u-boot-env@100000 {
label = "u-boot-env";
reg = <0x00100000 0x40000>;
};
diff --git a/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus.dts b/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus.dts
index 209fa3400317..baa39d0c1032 100644
--- a/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus.dts
+++ b/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus.dts
@@ -111,7 +111,7 @@
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
- bmc@0{
+ bmc@0 {
label = "bmc";
reg = <0x000000 0x2000000>;
};
@@ -120,7 +120,7 @@
reg = <0x0000000 0x80000>;
read-only;
};
- u-boot-env@100000{
+ u-boot-env@100000 {
label = "u-boot-env";
reg = <0x00100000 0x40000>;
};
diff --git a/arch/arm/boot/dts/nvidia/tegra20-acer-a500-picasso.dts b/arch/arm/boot/dts/nvidia/tegra20-acer-a500-picasso.dts
index 486fd244291e..a619ea83ed3b 100644
--- a/arch/arm/boot/dts/nvidia/tegra20-acer-a500-picasso.dts
+++ b/arch/arm/boot/dts/nvidia/tegra20-acer-a500-picasso.dts
@@ -65,7 +65,7 @@
rgb {
status = "okay";
- port@0 {
+ port {
lcd_output: endpoint {
remote-endpoint = <&lvds_encoder_input>;
bus-width = <18>;
diff --git a/arch/arm/boot/dts/nvidia/tegra20-asus-tf101.dts b/arch/arm/boot/dts/nvidia/tegra20-asus-tf101.dts
index a3757b7daeda..e118809dc6d9 100644
--- a/arch/arm/boot/dts/nvidia/tegra20-asus-tf101.dts
+++ b/arch/arm/boot/dts/nvidia/tegra20-asus-tf101.dts
@@ -66,7 +66,7 @@
rgb {
status = "okay";
- port@0 {
+ port {
lcd_output: endpoint {
remote-endpoint = <&lvds_encoder_input>;
bus-width = <18>;
diff --git a/arch/arm/boot/dts/nvidia/tegra30-asus-lvds-display.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-lvds-display.dtsi
index bae09d82594d..680edff0f26f 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-asus-lvds-display.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra30-asus-lvds-display.dtsi
@@ -10,7 +10,7 @@
rgb {
status = "okay";
- port@0 {
+ port {
dpi_output: endpoint {
remote-endpoint = <&bridge_input>;
bus-width = <24>;
diff --git a/arch/arm/boot/dts/nvidia/tegra30-asus-tf700t.dts b/arch/arm/boot/dts/nvidia/tegra30-asus-tf700t.dts
index efde7dad718a..9c480fde2e76 100644
--- a/arch/arm/boot/dts/nvidia/tegra30-asus-tf700t.dts
+++ b/arch/arm/boot/dts/nvidia/tegra30-asus-tf700t.dts
@@ -15,7 +15,7 @@
rgb {
status = "okay";
- port@0 {
+ port {
dpi_output: endpoint {
remote-endpoint = <&bridge_input>;
bus-width = <24>;
diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile
index 3629e343d322..a724d1a7a9a0 100644
--- a/arch/arm/boot/dts/nxp/imx/Makefile
+++ b/arch/arm/boot/dts/nxp/imx/Makefile
@@ -47,6 +47,8 @@ dtb-$(CONFIG_SOC_IMX53) += \
imx53-qsb.dtb \
imx53-qsrb.dtb \
imx53-sk-imx53.dtb \
+ imx53-sk-imx53-atm0700d4-lvds.dtb \
+ imx53-sk-imx53-atm0700d4-rgb.dtb \
imx53-smd.dtb \
imx53-tx53-x03x.dtb \
imx53-tx53-x13x.dtb \
@@ -244,6 +246,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6q-udoo.dtb \
imx6q-utilite-pro.dtb \
imx6q-var-dt6customboard.dtb \
+ imx6q-var-mx6customboard.dtb \
imx6q-vicut1.dtb \
imx6q-wandboard.dtb \
imx6q-wandboard-revb1.dtb \
diff --git a/arch/arm/boot/dts/nxp/imx/imx25.dtsi b/arch/arm/boot/dts/nxp/imx/imx25.dtsi
index 5f90d72b840b..534c70b8d79d 100644
--- a/arch/arm/boot/dts/nxp/imx/imx25.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx25.dtsi
@@ -529,7 +529,6 @@
compatible = "fsl,imx25-wdt", "fsl,imx21-wdt";
reg = <0x53fdc000 0x4000>;
clocks = <&clks 126>;
- clock-names = "";
interrupts = <55>;
};
@@ -583,10 +582,9 @@
};
dryice@53ffc000 {
- compatible = "fsl,imx25-dryice", "fsl,imx25-rtc";
+ compatible = "fsl,imx25-rtc";
reg = <0x53ffc000 0x4000>;
clocks = <&clks 81>;
- clock-names = "ipg";
interrupts = <25 56>;
};
};
@@ -594,6 +592,9 @@
iram: sram@78000000 {
compatible = "mmio-sram";
reg = <0x78000000 0x20000>;
+ ranges = <0 0x78000000 0x20000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
};
emi@80000000 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx27-phytec-phycard-s-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx27-phytec-phycard-s-som.dtsi
index 303f920201c5..abc9233c5a1b 100644
--- a/arch/arm/boot/dts/nxp/imx/imx27-phytec-phycard-s-som.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx27-phytec-phycard-s-som.dtsi
@@ -34,7 +34,7 @@
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
- at24@52 {
+ eeprom@52 {
compatible = "atmel,24c32";
pagesize = <32>;
reg = <0x52>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx27-phytec-phycore-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx27-phytec-phycore-som.dtsi
index 7191e10712b9..7b2ea4cdae58 100644
--- a/arch/arm/boot/dts/nxp/imx/imx27-phytec-phycore-som.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx27-phytec-phycore-som.dtsi
@@ -180,7 +180,7 @@
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
- at24@52 {
+ eeprom@52 {
compatible = "atmel,24c32";
pagesize = <32>;
reg = <0x52>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts b/arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts
index 5d4b29d76585..7cd17b43b4b2 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts
@@ -119,8 +119,8 @@
compatible = "i2c-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_swi2c>;
- gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>, /* sda */
- <&gpio3 4 GPIO_ACTIVE_HIGH>; /* scl */
+ sda-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+ scl-gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>;
i2c-gpio,delay-us = <50>;
status = "okay";
diff --git a/arch/arm/boot/dts/nxp/imx/imx51.dtsi b/arch/arm/boot/dts/nxp/imx/imx51.dtsi
index 2b3195f5e32c..c96d6311dfa7 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx51.dtsi
@@ -651,7 +651,7 @@
};
sahara: crypto@83ff8000 {
- compatible = "fsl,imx53-sahara", "fsl,imx51-sahara";
+ compatible = "fsl,imx53-sahara";
reg = <0x83ff8000 0x4000>;
interrupts = <19 20>;
clocks = <&clks IMX5_CLK_SAHARA_IPG_GATE>,
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4-lvds.dts b/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4-lvds.dts
new file mode 100644
index 000000000000..b1c1e7c759b3
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4-lvds.dts
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2023 Linaro Ltd.
+
+/dts-v1/;
+
+#include <dt-bindings/pwm/pwm.h>
+#include "imx53-sk-imx53-atm0700d4.dtsi"
+
+/ {
+ lvds-decoder {
+ compatible = "ti,sn65lvds94", "lvds-decoder";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ lvds_decoder_in: endpoint {
+ remote-endpoint = <&lvds0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ lvds_decoder_out: endpoint {
+ remote-endpoint = <&panel_rgb_in>;
+ };
+ };
+ };
+ };
+};
+
+&iomuxc {
+ pinctrl_lvds0: lvds0grp {
+ /* LVDS pins only have pin mux configuration */
+ fsl,pins = <
+ MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK 0x80000000
+ MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 0x80000000
+ MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 0x80000000
+ MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 0x80000000
+ MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 0x80000000
+ >;
+ };
+
+ pinctrl_spi_gpio: spigrp {
+ fsl,pins = <
+ MX53_PAD_EIM_A22__GPIO2_16 0x1f4
+ MX53_PAD_EIM_A21__GPIO2_17 0x1f4
+ MX53_PAD_EIM_A16__GPIO2_22 0x1f4
+ MX53_PAD_EIM_A18__GPIO2_20 0x1f4
+ >;
+ };
+};
+
+&ldb {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lvds0>;
+ status = "okay";
+
+ lvds0: lvds-channel@0 {
+ reg = <0>;
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <24>;
+ status = "okay";
+
+ port@2 {
+ reg = <2>;
+
+ lvds0_out: endpoint {
+ remote-endpoint = <&lvds_decoder_in>;
+ };
+ };
+ };
+};
+
+&panel_rgb_in {
+ remote-endpoint = <&lvds_decoder_out>;
+};
+
+&spi_ts {
+ pinctrl-0 = <&pinctrl_spi_gpio>;
+ pinctrl-names = "default";
+
+ sck-gpios = <&gpio2 16 GPIO_ACTIVE_HIGH>;
+ miso-gpios = <&gpio2 22 GPIO_ACTIVE_HIGH>;
+ mosi-gpios = <&gpio2 17 GPIO_ACTIVE_HIGH>;
+ cs-gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
+};
+
+&touchscreen {
+ interrupts-extended = <&gpio3 22 IRQ_TYPE_EDGE_BOTH>;
+ pendown-gpio = <&gpio3 22 GPIO_ACTIVE_LOW>;
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4-rgb.dts b/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4-rgb.dts
new file mode 100644
index 000000000000..2559ada7e401
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4-rgb.dts
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2023 Linaro Ltd.
+
+/dts-v1/;
+
+#include <dt-bindings/pwm/pwm.h>
+#include "imx53-sk-imx53-atm0700d4.dtsi"
+
+/ {
+ display: disp0 {
+ compatible = "fsl,imx-parallel-display";
+ interface-pix-fmt = "rgb24";
+ pinctrl-0 = <&pinctrl_rgb24>;
+ pinctrl-names = "default";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ display0_in: endpoint {
+ remote-endpoint = <&ipu_di0_disp0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ display_out: endpoint {
+ remote-endpoint = <&panel_rgb_in>;
+ };
+ };
+ };
+
+};
+
+&iomuxc {
+ pinctrl_rgb24: rgb24grp {
+ fsl,pins = <
+ MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK 0x5
+ MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 0x5
+ MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 0x5
+ MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 0x5
+ MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 0x5
+ MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 0x5
+ MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 0x5
+ MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 0x5
+ MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 0x5
+ MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 0x5
+ MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 0x5
+ MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 0x5
+ MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 0x5
+ MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 0x5
+ MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 0x5
+ MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 0x5
+ MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 0x5
+ MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 0x5
+ MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 0x5
+ MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 0x5
+ MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 0x5
+ MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 0x5
+ MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 0x5
+ MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 0x5
+ MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 0x5
+ MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 0x5
+ MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 0x5
+ MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 0x5
+ >;
+ };
+
+ pinctrl_spi_gpio: spigrp {
+ fsl,pins = <
+ MX53_PAD_SD1_DATA1__GPIO1_17 0x1f4
+ MX53_PAD_GPIO_7__GPIO1_7 0x1f4
+ MX53_PAD_PATA_DATA3__GPIO2_3 0x1f4
+ MX53_PAD_PATA_DATA8__GPIO2_8 0x1f4
+ >;
+ };
+};
+
+&ipu_di0_disp0 {
+ remote-endpoint = <&display0_in>;
+};
+
+&panel {
+ enable-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+};
+
+&panel_rgb_in {
+ remote-endpoint = <&display_out>;
+};
+
+&pwm1 {
+ status = "disabled";
+};
+
+&spi_ts {
+ pinctrl-0 = <&pinctrl_spi_gpio>;
+ pinctrl-names = "default";
+
+ sck-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+ mosi-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
+ miso-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
+ cs-gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>;
+};
+
+&touchscreen {
+ interrupts-extended = <&gpio2 6 IRQ_TYPE_EDGE_BOTH>;
+ pendown-gpio = <&gpio2 6 GPIO_ACTIVE_LOW>;
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4.dtsi
new file mode 100644
index 000000000000..e395004e80e6
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4.dtsi
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2023 Linaro Ltd.
+
+/dts-v1/;
+
+#include <dt-bindings/pwm/pwm.h>
+#include "imx53-sk-imx53.dts"
+
+/ {
+ panel: panel-rgb {
+ compatible = "powertip,ph800480t013-idf02";
+
+ port {
+ panel_rgb_in: endpoint {
+ };
+ };
+ };
+
+ spi_ts: spi {
+ compatible = "spi-gpio";
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+
+ num-chipselects = <1>;
+
+ touchscreen: touchscreen@0 {
+ reg = <0>;
+ compatible = "ti,ads7843";
+ spi-max-frequency = <300000>;
+
+ ti,vref-mv = /bits/ 16 <3300>;
+ ti,x-plate-ohms = /bits/ 16 <450>;
+ ti,y-plate-ohms = /bits/ 16 <250>;
+ ti,debounce-tol = /bits/ 16 <10>;
+ ti,debounce-rep = /bits/ 16 <0>;
+ touchscreen-size-x = <4096>;
+ touchscreen-size-y = <4096>;
+ touchscreen-swapped-x-y;
+ touchscreen-max-pressure = <100>;
+
+ wakeup-source;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53.dtsi b/arch/arm/boot/dts/nxp/imx/imx53.dtsi
index 0ebc35e6e985..07658e477095 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx53.dtsi
@@ -275,7 +275,7 @@
ecspi1: spi@50010000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx53-ecspi";
reg = <0x50010000 0x4000>;
interrupts = <36>;
clocks = <&clks IMX5_CLK_ECSPI1_IPG_GATE>,
@@ -701,7 +701,7 @@
ecspi2: spi@63fac000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx53-ecspi";
reg = <0x63fac000 0x4000>;
interrupts = <37>;
clocks = <&clks IMX5_CLK_ECSPI2_IPG_GATE>,
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-b650v3.dts b/arch/arm/boot/dts/nxp/imx/imx6q-b650v3.dts
index fa1a1df37cde..b0d345f5d071 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-b650v3.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-b650v3.dts
@@ -98,8 +98,8 @@
};
&usbphy1 {
- fsl,tx-cal-45-dn-ohms = <55>;
- fsl,tx-cal-45-dp-ohms = <55>;
+ fsl,tx-cal-45-dn-ohms = <54>;
+ fsl,tx-cal-45-dp-ohms = <54>;
fsl,tx-d-cal = <100>;
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-pistachio.dts b/arch/arm/boot/dts/nxp/imx/imx6q-pistachio.dts
index fb9f320103c6..46c6b96d8073 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-pistachio.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-pistachio.dts
@@ -637,11 +637,11 @@
};
&usbphy1 {
- fsl,tx-d-cal = <0x5>;
+ fsl,tx-d-cal = <79>;
};
&usbphy2 {
- fsl,tx-d-cal = <0x5>;
+ fsl,tx-d-cal = <79>;
};
&usdhc1 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-skov-reve-mi1010ait-1cp1.dts b/arch/arm/boot/dts/nxp/imx/imx6q-skov-reve-mi1010ait-1cp1.dts
index a3f247c722b4..0342a79ccd5d 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-skov-reve-mi1010ait-1cp1.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-skov-reve-mi1010ait-1cp1.dts
@@ -37,9 +37,9 @@
&clks {
assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
- <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+ <&clks IMX6QDL_CLK_LDB_DI1_SEL>, <&clks IMX6QDL_CLK_ENET_REF_SEL>;
assigned-clock-parents = <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>,
- <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>;
+ <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>, <&clk50m_phy>;
};
&hdmi {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-var-mx6customboard.dts b/arch/arm/boot/dts/nxp/imx/imx6q-var-mx6customboard.dts
new file mode 100644
index 000000000000..6f9d094dd6d0
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-var-mx6customboard.dts
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Support for Variscite MX6 Carrier-board
+ *
+ * Copyright 2016 Variscite, Ltd. All Rights Reserved
+ * Copyright 2022 Bootlin
+ */
+
+/dts-v1/;
+
+#include "imx6qdl-var-som.dtsi"
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+ model = "Variscite i.MX6 QUAD/DUAL VAR-SOM-MX6 Custom Board";
+ compatible = "variscite,mx6customboard", "variscite,var-som-imx6q", "fsl,imx6q";
+
+ panel0: lvds-panel0 {
+ compatible = "panel-lvds";
+ backlight = <&backlight_lvds>;
+ width-mm = <152>;
+ height-mm = <91>;
+ label = "etm070001adh6";
+ data-mapping = "jeida-18";
+
+ panel-timing {
+ clock-frequency = <32000000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <39>;
+ hfront-porch = <39>;
+ vback-porch = <29>;
+ vfront-porch = <13>;
+ hsync-len = <47>;
+ vsync-len = <2>;
+ };
+
+ port {
+ panel_in_lvds0: endpoint {
+ remote-endpoint = <&lvds0_out>;
+ };
+ };
+ };
+
+ panel1: lvds-panel1 {
+ compatible = "panel-lvds";
+ width-mm = <152>;
+ height-mm = <91>;
+ data-mapping = "jeida-18";
+
+ panel-timing {
+ clock-frequency = <38251000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <112>;
+ hfront-porch = <32>;
+ vback-porch = <3>;
+ vfront-porch = <17>;
+ hsync-len = <80>;
+ vsync-len = <4>;
+ };
+
+ port {
+ panel_in_lvds1: endpoint {
+ remote-endpoint = <&lvds1_out>;
+ };
+ };
+ };
+
+ backlight_lvds: backlight-lvds {
+ compatible = "pwm-backlight";
+ pwms = <&pwm2 0 50000 0>;
+ brightness-levels = <0 4 8 16 32 64 128 248>;
+ default-brightness-level = <7>;
+ power-supply = <&reg_3p3v>;
+ };
+};
+
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+
+ touchscreen@24 {
+ compatible = "cypress,tt21000";
+ reg = <0x24>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&reg_3p3v>;
+ touchscreen-size-x = <880>;
+ touchscreen-size-y = <1280>;
+ };
+
+ touchscreen@38 {
+ compatible = "edt,edt-ft5306";
+ reg = <0x38>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+ touchscreen-size-x = <1800>;
+ touchscreen-size-y = <1000>;
+ };
+};
+
+&iomuxc {
+ pinctrl_camera: cameragrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x1b0b0
+ MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN 0x1b0b0
+ MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x1b0b0
+ MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x1b0b0
+ MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x1b0b0
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x1b0b0
+ MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x1b0b0
+ >;
+ };
+
+ pinctrl_ipu1: ipu1grp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+ MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
+ MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
+ MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
+ MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04 0x10
+ MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
+ MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
+ MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
+ MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
+ MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
+ MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
+ MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
+ MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
+ MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
+ MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
+ MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
+ MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
+ MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
+ MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
+ MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
+ MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
+ MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
+ MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
+ MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
+ MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
+ MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
+ MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
+ MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
+ MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D23__UART3_CTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbotg_var: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x17059
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17071
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10071
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17071
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17071
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17071
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17071
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ >;
+ };
+};
+
+&ldb {
+ status = "okay";
+
+ lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <24>;
+ status = "okay";
+
+ port@4 {
+ reg = <4>;
+
+ lvds0_out: endpoint {
+ remote-endpoint = <&panel_in_lvds0>;
+ };
+ };
+ };
+
+ lvds-channel@1 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <24>;
+ status = "okay";
+
+ port@4 {
+ reg = <4>;
+
+ lvds1_out: endpoint {
+ remote-endpoint = <&panel_in_lvds1>;
+ };
+ };
+ };
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ cd-gpios = <&gpio4 14 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio4 15 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi
index 9594bc5745ed..1e723807ab4c 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi
@@ -52,6 +52,11 @@
/ {
/* these are used by bootloader for disabling nodes */
aliases {
+ ethernet0 = &fec;
+ ethernet1 = &lan1;
+ ethernet2 = &lan2;
+ ethernet3 = &lan3;
+ ethernet4 = &lan4;
led0 = &led0;
led1 = &led1;
led2 = &led2;
@@ -212,28 +217,61 @@
compatible = "marvell,mv88e6085";
reg = <0>;
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sw_phy0: ethernet-phy@0 {
+ reg = <0x0>;
+ };
+
+ sw_phy1: ethernet-phy@1 {
+ reg = <0x1>;
+ };
+
+ sw_phy2: ethernet-phy@2 {
+ reg = <0x2>;
+ };
+
+ sw_phy3: ethernet-phy@3 {
+ reg = <0x3>;
+ };
+ };
+
ports {
#address-cells = <1>;
#size-cells = <0>;
- port@0 {
+ lan4: port@0 {
reg = <0>;
label = "lan4";
+ phy-handle = <&sw_phy0>;
+ phy-mode = "internal";
+ local-mac-address = [00 00 00 00 00 00];
};
- port@1 {
+ lan3: port@1 {
reg = <1>;
label = "lan3";
+ phy-handle = <&sw_phy1>;
+ phy-mode = "internal";
+ local-mac-address = [00 00 00 00 00 00];
};
- port@2 {
+ lan2: port@2 {
reg = <2>;
label = "lan2";
+ phy-handle = <&sw_phy2>;
+ phy-mode = "internal";
+ local-mac-address = [00 00 00 00 00 00];
};
- port@3 {
+ lan1: port@3 {
reg = <3>;
label = "lan1";
+ phy-handle = <&sw_phy3>;
+ phy-mode = "internal";
+ local-mac-address = [00 00 00 00 00 00];
};
port@5 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5910.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5910.dtsi
index 218d6e667ed2..424dc7fcd533 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5910.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5910.dtsi
@@ -326,7 +326,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio7>;
interrupts = <13 0>;
- interrupt-names = "INT1";
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5912.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5912.dtsi
index de5983cf7810..49ea25c71967 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5912.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5912.dtsi
@@ -307,7 +307,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio7>;
interrupts = <13 0>;
- interrupt-names = "INT1";
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi
index 763831dc0e24..32a110a35b02 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi
@@ -15,7 +15,7 @@
reg = <0x10000000 0xF0000000>;
};
- reg_1p8v: regulator@0 {
+ reg_1p8v: regulator-1p8v {
compatible = "regulator-fixed";
regulator-name = "1P8V";
regulator-min-microvolt = <1800000>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi
new file mode 100644
index 000000000000..a1ea33c4eeb7
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi
@@ -0,0 +1,569 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Support for Variscite VAR-SOM-MX6 Module
+ *
+ * Copyright 2011 Linaro Ltd.
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-2016 Variscite, Ltd.
+ * Author: Donio Ron <ron.d@variscite.com>
+ * Copyright 2022 Bootlin
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include <dt-bindings/clock/imx6qdl-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/sound/fsl-imx-audmux.h>
+
+/ {
+ model = "Variscite VAR-SOM-MX6 module";
+ compatible = "variscite,var-som-imx6q", "fsl,imx6q";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ memory@10000000 {
+ device_type = "memory";
+ reg = <0x10000000 0x40000000>;
+ };
+
+ reg_usb_otg_vbus: regulator-usb-otg-vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_usb_h1_vbus: regulator-usb-h1-vbud {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_h1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_1p8v: regulator-1p8v {
+ compatible = "regulator-fixed";
+ regulator-name = "1P8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_wl18xx_vmmc: regulator-wl18xx {
+ compatible = "regulator-fixed";
+ regulator-name = "vwl1807";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&gpio7 8 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ startup-delay-us = <70000>;
+ };
+
+ sound: sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "var-som-audio";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&sound_codec>;
+ simple-audio-card,frame-master = <&sound_codec>;
+ simple-audio-card,widgets = "Headphone", "Headphone Jack",
+ "Line", "Line In", "Microphone", "Mic Jack";
+ simple-audio-card,routing = "Headphone Jack", "HPLOUT",
+ "Headphone Jack", "HPROUT",
+ "LINE1L", "Line In",
+ "LINE1R", "Line In";
+
+ sound_cpu: simple-audio-card,cpu {
+ sound-dai = <&ssi2>;
+ };
+
+ sound_codec: simple-audio-card,codec {
+ sound-dai = <&tlv320aic3106>;
+ clocks = <&clks IMX6QDL_CLK_CKO>;
+ };
+ };
+
+ rfkill {
+ compatible = "rfkill-gpio";
+ name = "rfkill";
+ radio-type = "bluetooth";
+ shutdown-gpios = <&gpio6 18 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux>;
+ status = "okay";
+
+ mux-ssi2 {
+ fsl,audmux-port = <1>;
+ fsl,port-config = <
+ (IMX_AUDMUX_V2_PTCR_SYN |
+ IMX_AUDMUX_V2_PTCR_TFSDIR |
+ IMX_AUDMUX_V2_PTCR_TFSEL(2) |
+ IMX_AUDMUX_V2_PTCR_TCLKDIR |
+ IMX_AUDMUX_V2_PTCR_TCSEL(2))
+ IMX_AUDMUX_V2_PDCR_RXDSEL(2)
+ >;
+ };
+
+ mux-aud3 {
+ fsl,audmux-port = <2>;
+ fsl,port-config = <
+ IMX_AUDMUX_V2_PTCR_SYN
+ IMX_AUDMUX_V2_PDCR_RXDSEL(1)
+ >;
+ };
+};
+
+&ecspi3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi3>;
+ cs-gpios = <&gpio4 24 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rgmii";
+ phy-handle = <&rgmii_phy>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rgmii_phy: ethernet-phy@7 {
+ reg = <7>;
+ reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <10000>;
+ };
+ };
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand>;
+ status = "okay";
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ pmic@8 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pmic>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3950000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3950000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3950000>;
+ };
+
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vgen1_reg: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+ };
+
+ tlv320aic3106: audio-codec@1b {
+ compatible = "ti,tlv320aic3106";
+ reg = <0x1b>;
+ #sound-dai-cells = <0>;
+ DRVDD-supply = <&reg_3p3v>;
+ AVDD-supply = <&reg_3p3v>;
+ IOVDD-supply = <&reg_3p3v>;
+ DVDD-supply = <&reg_1p8v>;
+ ai3x-ocmv = <0>;
+ reset-gpios = <&gpio4 5 GPIO_ACTIVE_LOW>;
+ ai3x-gpio-func = <
+ 0 /* AIC3X_GPIO1_FUNC_DISABLED */
+ 5 /* AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT */
+ >;
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ /* Audio Clock */
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
+ >;
+ };
+
+ pinctrl_bt: btgrp {
+ fsl,pins = <
+ /* Bluetooth/wifi enable */
+ MX6QDL_PAD_SD3_DAT6__GPIO6_IO18 0x1b0b1
+ /* Wifi Slow Clock */
+ MX6QDL_PAD_ENET_RXD0__OSC32K_32K_OUT 0x000b0
+ >;
+ };
+
+ pinctrl_ecspi3: ecspi3grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
+ MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
+ MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
+ >;
+ };
+
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+ >;
+ };
+
+ pinctrl_enet_irq: enetirqgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
+ >;
+ };
+
+ pinctrl_gpmi_nand: gpminandgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb0b1
+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
+ >;
+ };
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* CTW6120 IRQ */
+ MX6QDL_PAD_EIM_DA7__GPIO3_IO07 0xb0b1
+ /* SDMMC2 CD/WP */
+ MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x1b0b0
+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x1b0b0
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+ MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_pmic: pmicgrp {
+ fsl,pins = <
+ /* PMIC INT */
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0
+ >;
+ };
+
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT9__PWM2_OUT 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT4__UART2_RX_DATA 0x1b0b1
+ MX6QDL_PAD_SD3_DAT5__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D28__UART2_CTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_D29__UART2_RTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17069
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10069
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17069
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17069
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17069
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17069
+ /* WL_EN */
+ MX6QDL_PAD_SD3_DAT7__GPIO6_IO17 0x13059
+ /* WL_IRQ */
+ MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x13059
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3grp100mhzgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170B9
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100B9
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170B9
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170B9
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170B9
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170B9
+ /* WL_EN */
+ MX6QDL_PAD_SD3_DAT7__GPIO6_IO17 0x130B9
+ /* WL_IRQ */
+ MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x130B9
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3grp200mhzgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170F9
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100F9
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170F9
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170F9
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170F9
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170F9
+ /* WL_EN */
+ MX6QDL_PAD_SD3_DAT7__GPIO6_IO17 0x130F9
+ /* WL_IRQ */
+ MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x130F9
+ >;
+ };
+};
+
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm2>;
+ status = "okay";
+};
+
+&reg_arm {
+ vin-supply = <&sw1a_reg>;
+};
+
+&reg_pu {
+ vin-supply = <&sw1c_reg>;
+};
+
+&reg_soc {
+ vin-supply = <&sw1c_reg>;
+};
+
+&reg_vdd1p1 {
+ vin-supply = <&vgen5_reg>;
+};
+
+&reg_vdd2p5 {
+ vin-supply = <&vgen5_reg>;
+};
+
+&snvs_poweroff {
+ status = "okay";
+};
+
+&ssi2 {
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2 &pinctrl_bt>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&usbh1 {
+ vbus-supply = <&reg_usb_h1_vbus>;
+ status = "okay";
+};
+
+&usbotg {
+ vbus-supply = <&reg_usb_otg_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg_var>;
+ disable-over-current;
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usbphy1 {
+ fsl,tx-d-cal = <0x5>;
+};
+
+&usbphy2 {
+ fsl,tx-d-cal = <0x5>;
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ non-removable;
+ keep-power-in-suspend;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+ bus-width = <4>;
+ vmmc-supply = <&reg_wl18xx_vmmc>;
+ non-removable;
+ wakeup-source;
+ keep-power-in-suspend;
+ cap-power-off-card;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ wifi: wifi@2 {
+ compatible = "ti,wl1835";
+ reg = <2>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <17 IRQ_TYPE_EDGE_RISING>;
+ ref-clock-frequency = <38400000>;
+ };
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-pico.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-pico.dtsi
index 4ffe99ed55ca..07dcecbe485d 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ul-pico.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-pico.dtsi
@@ -121,6 +121,8 @@
max-speed = <100>;
interrupt-parent = <&gpio5>;
interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&clks IMX6UL_CLK_ENET_REF>;
+ clock-names = "rmii-ref";
};
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi
index 6bd90473050b..1db146ac1c17 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi
@@ -114,10 +114,8 @@
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c_gpio>;
- gpios = <
- &gpio5 1 GPIO_ACTIVE_HIGH /* SDA */
- &gpio5 0 GPIO_ACTIVE_HIGH /* SCL */
- >;
+ sda-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
+ scl-gpios = <&gpio5 0 GPIO_ACTIVE_HIGH>;
clock-frequency = <400000>;
status = "okay";
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-aster.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-aster.dts
index 919c0464d6cb..b2cdf4877718 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-aster.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-aster.dts
@@ -12,6 +12,5 @@
model = "Toradex Colibri iMX6ULL 1GB (eMMC) on Colibri Aster";
compatible = "toradex,colibri-imx6ull-emmc-aster",
"toradex,colibri-imx6ull-emmc",
- "toradex,colibri-imx6ull",
"fsl,imx6ull";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-eval-v3.dts
index 61b93cb040c7..2dc16c54fc78 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-eval-v3.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-eval-v3.dts
@@ -12,6 +12,5 @@
model = "Toradex Colibri iMX6ULL 1GB (eMMC) on Colibri Evaluation Board V3";
compatible = "toradex,colibri-imx6ull-emmc-eval",
"toradex,colibri-imx6ull-emmc",
- "toradex,colibri-imx6ull",
"fsl,imx6ull";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris-v2.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris-v2.dts
index b9060c2f7977..9bae08fb7f85 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris-v2.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris-v2.dts
@@ -10,8 +10,7 @@
/ {
model = "Toradex Colibri iMX6ULL 1G (eMMC) on Colibri Iris V2";
- compatible = "toradex,colibri-imx6ull-iris-v2",
+ compatible = "toradex,colibri-imx6ull-emmc-iris-v2",
"toradex,colibri-imx6ull-emmc",
- "toradex,colibri-imx6ull",
"fsl,imx6ull";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris.dts
index 0ab71f2f5daa..0b1603ff9420 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris.dts
@@ -12,6 +12,5 @@
model = "Toradex Colibri iMX6ULL 1GB (eMMC) on Colibri Iris";
compatible = "toradex,colibri-imx6ull-emmc-iris",
"toradex,colibri-imx6ull-emmc",
- "toradex,colibri-imx6ull",
"fsl,imx6ull";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-eval-v3.dts
index d6da984e518d..c5bc255b21e1 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-eval-v3.dts
@@ -10,7 +10,7 @@
/ {
model = "Toradex Colibri iMX6ULL 256/512MB on Colibri Evaluation Board V3";
- compatible = "toradex,colibri-imx6ull-eval", "fsl,imx6ull";
+ compatible = "toradex,colibri-imx6ull-eval", "toradex,colibri-imx6ull", "fsl,imx6ull";
};
&ad7879_ts {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-aster.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-aster.dts
index c7da5b41966f..d3bbd05da293 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-aster.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-aster.dts
@@ -11,7 +11,7 @@
/ {
model = "Toradex Colibri iMX6ULL 512MB on Colibri Aster";
compatible = "toradex,colibri-imx6ull-wifi-aster",
- "toradex,colibri-imx6ull",
+ "toradex,colibri-imx6ull-wifi",
"fsl,imx6ull";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-eval-v3.dts
index 917f5dbe64ba..0ac306c9cef2 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-eval-v3.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-eval-v3.dts
@@ -10,7 +10,7 @@
/ {
model = "Toradex Colibri iMX6ULL 512MB on Colibri Evaluation Board V3";
- compatible = "toradex,colibri-imx6ull-wifi-eval", "fsl,imx6ull";
+ compatible = "toradex,colibri-imx6ull-wifi-eval", "toradex,colibri-imx6ull-wifi", "fsl,imx6ull";
};
&ad7879_ts {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris-v2.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris-v2.dts
index 488da6df56fa..38cd52c45496 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris-v2.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris-v2.dts
@@ -11,7 +11,7 @@
/ {
model = "Toradex Colibri iMX6ULL 512MB on Colibri Iris V2";
compatible = "toradex,colibri-imx6ull-wifi-iris-v2",
- "toradex,colibri-imx6ull",
+ "toradex,colibri-imx6ull-wifi",
"fsl,imx6ull";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris.dts
index e63253254754..5f60df64f173 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris.dts
@@ -11,7 +11,7 @@
/ {
model = "Toradex Colibri iMX6ULL 512MB on Colibri Iris";
compatible = "toradex,colibri-imx6ull-wifi-iris",
- "toradex,colibri-imx6ull",
+ "toradex,colibri-imx6ull-wifi",
"fsl,imx6ull";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-emmc.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-emmc.dts
index 14adb87da911..1610f3892d9e 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-emmc.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-emmc.dts
@@ -9,8 +9,8 @@
/ {
model = "PHYTEC phyGate-Tauri i.MX6 UltraLite";
- compatible = "phytec,imx6ull-phygate-tauri",
- "phytec,imx6ull-phygate-tauri-emmc",
+ compatible = "phytec,imx6ull-phygate-tauri-emmc",
+ "phytec,imx6ull-phygate-tauri",
"phytec,imx6ull-pcl063", "fsl,imx6ull";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-nand.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-nand.dts
index ae396ac63443..92e7d38d5637 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-nand.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-nand.dts
@@ -9,8 +9,8 @@
/ {
model = "PHYTEC phyGate-Tauri i.MX6 UltraLite";
- compatible = "phytec,imx6ull-phygate-tauri",
- "phytec,imx6ull-phygate-tauri-nand",
+ compatible = "phytec,imx6ull-phygate-tauri-nand",
+ "phytec,imx6ull-phygate-tauri",
"phytec,imx6ull-pcl063", "fsl,imx6ull";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri.dtsi
index ea627638e40c..44cc4ff1d0df 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri.dtsi
@@ -9,11 +9,6 @@
#include "imx6ull-phytec-phycore-som.dtsi"
/ {
-
- model = "PHYTEC phyGate-Tauri i.MX6 UltraLite";
- compatible = "phytec,imx6ull-phygate-tauri",
- "phytec,imx6ull-pcl063", "fsl,imx6ull";
-
aliases {
rtc0 = &i2c_rtc;
rtc1 = &snvs_rtc;
diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-aster.dts b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-aster.dts
index d9c7045a55ba..212e0685585d 100644
--- a/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-aster.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-aster.dts
@@ -12,7 +12,6 @@
model = "Toradex Colibri iMX7D 1GB (eMMC) on Aster Carrier Board";
compatible = "toradex,colibri-imx7d-emmc-aster",
"toradex,colibri-imx7d-emmc",
- "toradex,colibri-imx7d",
"fsl,imx7d";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-eval-v3.dts
index 96b599439dde..1deece7e7129 100644
--- a/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-eval-v3.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-eval-v3.dts
@@ -11,7 +11,6 @@
model = "Toradex Colibri iMX7D 1GB (eMMC) on Colibri Evaluation Board V3";
compatible = "toradex,colibri-imx7d-emmc-eval-v3",
"toradex,colibri-imx7d-emmc",
- "toradex,colibri-imx7d",
"fsl,imx7d";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris-v2.dts b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris-v2.dts
index 5eccb837b158..22e7863c2e80 100644
--- a/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris-v2.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris-v2.dts
@@ -11,7 +11,6 @@
model = "Toradex Colibri iMX7D 1GB on Iris V2 Carrier Board";
compatible = "toradex,colibri-imx7d-emmc-iris-v2",
"toradex,colibri-imx7d-emmc",
- "toradex,colibri-imx7d",
"fsl,imx7d";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris.dts b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris.dts
index ae10e8a66ff1..a3cf8f50e3dc 100644
--- a/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris.dts
@@ -11,7 +11,6 @@
model = "Toradex Colibri iMX7D 1GB on Iris Carrier Board";
compatible = "toradex,colibri-imx7d-emmc-iris",
"toradex,colibri-imx7d-emmc",
- "toradex,colibri-imx7d",
"fsl,imx7d";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts b/arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts
index f263e391e24c..62221131336f 100644
--- a/arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts
@@ -61,6 +61,10 @@
};
};
+&usdhc1 {
+ status = "disabled";
+};
+
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx7s.dtsi b/arch/arm/boot/dts/nxp/imx/imx7s.dtsi
index e152d08f27d4..5387da8a2a0a 100644
--- a/arch/arm/boot/dts/nxp/imx/imx7s.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx7s.dtsi
@@ -454,7 +454,7 @@
};
gpt1: timer@302d0000 {
- compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
+ compatible = "fsl,imx7d-gpt", "fsl,imx6dl-gpt";
reg = <0x302d0000 0x10000>;
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_GPT1_ROOT_CLK>,
@@ -463,7 +463,7 @@
};
gpt2: timer@302e0000 {
- compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
+ compatible = "fsl,imx7d-gpt", "fsl,imx6dl-gpt";
reg = <0x302e0000 0x10000>;
interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_GPT2_ROOT_CLK>,
@@ -473,7 +473,7 @@
};
gpt3: timer@302f0000 {
- compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
+ compatible = "fsl,imx7d-gpt", "fsl,imx6dl-gpt";
reg = <0x302f0000 0x10000>;
interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_GPT3_ROOT_CLK>,
@@ -483,7 +483,7 @@
};
gpt4: timer@30300000 {
- compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
+ compatible = "fsl,imx7d-gpt", "fsl,imx6dl-gpt";
reg = <0x30300000 0x10000>;
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_GPT4_ROOT_CLK>,
@@ -658,7 +658,6 @@
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
#interrupt-cells = <3>;
interrupt-parent = <&intc>;
- #power-domain-cells = <1>;
pgc {
#address-cells = <1>;
@@ -800,10 +799,8 @@
compatible = "fsl,imx7-csi";
reg = <0x30710000 0x10000>;
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_CLK_DUMMY>,
- <&clks IMX7D_CSI_MCLK_ROOT_CLK>,
- <&clks IMX7D_CLK_DUMMY>;
- clock-names = "axi", "mclk", "dcic";
+ clocks = <&clks IMX7D_CSI_MCLK_ROOT_CLK>;
+ clock-names = "mclk";
status = "disabled";
port {
diff --git a/arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi b/arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi
index b01ddda7bd9e..ac338320ac1d 100644
--- a/arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi
@@ -209,7 +209,7 @@
};
usbphy1: usb-phy@40350000 {
- compatible = "fsl,imx7ulp-usbphy", "fsl,imx6ul-usbphy";
+ compatible = "fsl,imx7ulp-usbphy";
reg = <0x40350000 0x1000>;
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&pcc2 IMX7ULP_CLK_USB_PHY>;
diff --git a/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi b/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi
index ebf97fcdd8ea..5a8b867d7d79 100644
--- a/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi
@@ -35,22 +35,25 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_buttons>;
- button1 {
+ button-1 {
label = "s14";
linux,code = <KEY_1>;
gpios = <&expander_in0 0 GPIO_ACTIVE_LOW>;
+ wakeup-source;
};
- button2 {
+ button-2 {
label = "s6";
linux,code = <KEY_2>;
gpios = <&expander_in0 1 GPIO_ACTIVE_LOW>;
+ wakeup-source;
};
- button3 {
+ button-3 {
label = "s7";
linux,code = <KEY_3>;
gpios = <&expander_in0 2 GPIO_ACTIVE_LOW>;
+ wakeup-source;
};
power-button {
diff --git a/arch/arm/boot/dts/nxp/mxs/imx23-evk.dts b/arch/arm/boot/dts/nxp/mxs/imx23-evk.dts
index 3b609d987d88..7365fe4581a3 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx23-evk.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx23-evk.dts
@@ -137,7 +137,7 @@
backlight_display: backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 2 5000000>;
+ pwms = <&pwm 2 5000000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx23-sansa.dts b/arch/arm/boot/dts/nxp/mxs/imx23-sansa.dts
index 46057d9bf555..636cf09a2b37 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx23-sansa.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx23-sansa.dts
@@ -166,7 +166,7 @@
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 2 5000000>;
+ pwms = <&pwm 2 5000000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx23-xfi3.dts b/arch/arm/boot/dts/nxp/mxs/imx23-xfi3.dts
index b1d8210f3ecc..28341d8315c2 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx23-xfi3.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx23-xfi3.dts
@@ -153,7 +153,7 @@
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 2 5000000>;
+ pwms = <&pwm 2 5000000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx23.dtsi b/arch/arm/boot/dts/nxp/mxs/imx23.dtsi
index 5eca942a52fd..fdf18b7cb2f6 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx23.dtsi
+++ b/arch/arm/boot/dts/nxp/mxs/imx23.dtsi
@@ -561,7 +561,7 @@
compatible = "fsl,imx23-pwm";
reg = <0x80064000 0x2000>;
clocks = <&clks 30>;
- #pwm-cells = <2>;
+ #pwm-cells = <3>;
fsl,pwm-number = <5>;
status = "disabled";
};
@@ -598,7 +598,7 @@
reg = <0x80070000 0x2000>;
interrupts = <0>;
clocks = <&clks 32>, <&clks 16>;
- clock-names = "uart", "apb_pclk";
+ clock-names = "uartclk", "apb_pclk";
status = "disabled";
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-apf28dev.dts b/arch/arm/boot/dts/nxp/mxs/imx28-apf28dev.dts
index fd6fee63ad2f..6c87266eb135 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-apf28dev.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-apf28dev.dts
@@ -39,7 +39,7 @@
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 3 191000>;
+ pwms = <&pwm 3 191000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-cfa10049.dts b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10049.dts
index 953e3162d2d2..f0ce897b9d5c 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-cfa10049.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10049.dts
@@ -173,7 +173,7 @@
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 3 5000000>;
+ pwms = <&pwm 3 5000000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-cfa10055.dts b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10055.dts
index 70e225a99fbe..cb68edd6101b 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-cfa10055.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10055.dts
@@ -39,7 +39,7 @@
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 3 5000000>;
+ pwms = <&pwm 3 5000000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-cfa10057.dts b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10057.dts
index 0be7356941ee..5875c3d7ba97 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-cfa10057.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10057.dts
@@ -26,7 +26,7 @@
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 4 5000000>;
+ pwms = <&pwm 4 5000000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <7>;
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-cfa10058.dts b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10058.dts
index aae0f1801461..b414e67ef379 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-cfa10058.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10058.dts
@@ -26,7 +26,7 @@
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 3 5000000>;
+ pwms = <&pwm 3 5000000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-eukrea-mbmx28lc.dtsi b/arch/arm/boot/dts/nxp/mxs/imx28-eukrea-mbmx28lc.dtsi
index 6633cde305e5..652fc9e57a55 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-eukrea-mbmx28lc.dtsi
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-eukrea-mbmx28lc.dtsi
@@ -14,7 +14,7 @@
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 4 1000000>;
+ pwms = <&pwm 4 1000000 0>;
brightness-levels = <0 25 50 75 100 125 150 175 200 225 255>;
default-brightness-level = <10>;
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-evk.dts b/arch/arm/boot/dts/nxp/mxs/imx28-evk.dts
index 783abb82b2a8..9ebb7371e235 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-evk.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-evk.dts
@@ -117,7 +117,7 @@
backlight_display: backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 2 5000000>;
+ pwms = <&pwm 2 5000000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-m28cu3.dts b/arch/arm/boot/dts/nxp/mxs/imx28-m28cu3.dts
index 8241c2d159fa..34b4d3246db1 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-m28cu3.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-m28cu3.dts
@@ -17,7 +17,7 @@
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 3 5000000>;
+ pwms = <&pwm 3 5000000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-m28evk.dts b/arch/arm/boot/dts/nxp/mxs/imx28-m28evk.dts
index 6bf26f386a5e..13070ca08cff 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-m28evk.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-m28evk.dts
@@ -13,7 +13,7 @@
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 4 5000000>;
+ pwms = <&pwm 4 5000000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts b/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts
index 23ad7cd0a1de..153e4017951d 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts
@@ -131,7 +131,7 @@
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 0 500000>;
+ pwms = <&pwm 0 500000 0>;
/*
* a silly way to create a 1:1 relationship between the
* PWM value and the actual duty cycle
@@ -652,6 +652,7 @@
vbus-supply = <&reg_usb0_vbus>;
disable-over-current;
dr_mode = "peripheral";
+ phy_type = "utmi";
status = "okay";
};
@@ -659,19 +660,18 @@
vbus-supply = <&reg_usb1_vbus>;
disable-over-current;
dr_mode = "host";
+ phy_type = "utmi";
status = "okay";
};
&usbphy0 {
pinctrl-names = "default";
pinctrl-0 = <&tx28_usbphy0_pins>;
- phy_type = "utmi";
status = "okay";
};
&usbphy1 {
pinctrl-names = "default";
pinctrl-0 = <&tx28_usbphy1_pins>;
- phy_type = "utmi";
status = "okay";
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-xea.dts b/arch/arm/boot/dts/nxp/mxs/imx28-xea.dts
index a400c108f66a..6c5e6856648a 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-xea.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-xea.dts
@@ -8,6 +8,7 @@
#include "imx28-lwe.dtsi"
/ {
+ model = "Liebherr XEA board";
compatible = "lwn,imx28-xea", "fsl,imx28";
};
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28.dtsi b/arch/arm/boot/dts/nxp/mxs/imx28.dtsi
index 763adeb995ee..6932d23fb29d 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28.dtsi
+++ b/arch/arm/boot/dts/nxp/mxs/imx28.dtsi
@@ -1003,7 +1003,7 @@
};
dcp: crypto@80028000 {
- compatible = "fsl,imx28-dcp", "fsl,imx23-dcp";
+ compatible = "fsl,imx28-dcp";
reg = <0x80028000 0x2000>;
interrupts = <52>, <53>, <54>;
status = "okay";
@@ -1185,7 +1185,7 @@
compatible = "fsl,imx28-pwm", "fsl,imx23-pwm";
reg = <0x80064000 0x2000>;
clocks = <&clks 44>;
- #pwm-cells = <2>;
+ #pwm-cells = <3>;
fsl,pwm-number = <8>;
status = "disabled";
};
@@ -1252,7 +1252,7 @@
reg = <0x80074000 0x1000>;
interrupts = <47>;
clocks = <&clks 45>, <&clks 26>;
- clock-names = "uart", "apb_pclk";
+ clock-names = "uartclk", "apb_pclk";
status = "disabled";
};
diff --git a/arch/arm/boot/dts/nxp/vf/vfxxx.dtsi b/arch/arm/boot/dts/nxp/vf/vfxxx.dtsi
index d1095b700c56..acccf9a3c898 100644
--- a/arch/arm/boot/dts/nxp/vf/vfxxx.dtsi
+++ b/arch/arm/boot/dts/nxp/vf/vfxxx.dtsi
@@ -111,8 +111,7 @@
interrupts = <61 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks VF610_CLK_UART0>;
clock-names = "ipg";
- dmas = <&edma0 0 2>,
- <&edma0 0 3>;
+ dmas = <&edma0 0 2>, <&edma0 0 3>;
dma-names = "rx","tx";
status = "disabled";
};
@@ -123,8 +122,7 @@
interrupts = <62 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks VF610_CLK_UART1>;
clock-names = "ipg";
- dmas = <&edma0 0 4>,
- <&edma0 0 5>;
+ dmas = <&edma0 0 4>, <&edma0 0 5>;
dma-names = "rx","tx";
status = "disabled";
};
@@ -135,8 +133,7 @@
interrupts = <63 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks VF610_CLK_UART2>;
clock-names = "ipg";
- dmas = <&edma0 0 6>,
- <&edma0 0 7>;
+ dmas = <&edma0 0 6>, <&edma0 0 7>;
dma-names = "rx","tx";
status = "disabled";
};
@@ -147,8 +144,7 @@
interrupts = <64 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks VF610_CLK_UART3>;
clock-names = "ipg";
- dmas = <&edma0 0 8>,
- <&edma0 0 9>;
+ dmas = <&edma0 0 8>, <&edma0 0 9>;
dma-names = "rx","tx";
status = "disabled";
};
@@ -162,8 +158,7 @@
clocks = <&clks VF610_CLK_DSPI0>;
clock-names = "dspi";
spi-num-chipselects = <6>;
- dmas = <&edma1 1 12>,
- <&edma1 1 13>;
+ dmas = <&edma1 1 12>, <&edma1 1 13>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -177,8 +172,7 @@
clocks = <&clks VF610_CLK_DSPI1>;
clock-names = "dspi";
spi-num-chipselects = <4>;
- dmas = <&edma1 1 14>,
- <&edma1 1 15>;
+ dmas = <&edma1 1 14>, <&edma1 1 15>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -426,8 +420,7 @@
interrupts = <72 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks VF610_CLK_I2C1>;
clock-names = "ipg";
- dmas = <&edma0 0 52>,
- <&edma0 0 53>;
+ dmas = <&edma0 0 52>, <&edma0 0 53>;
dma-names = "rx","tx";
status = "disabled";
};
@@ -551,8 +544,7 @@
clocks = <&clks VF610_CLK_DSPI3>;
clock-names = "dspi";
spi-num-chipselects = <2>;
- dmas = <&edma1 0 12>,
- <&edma1 0 13>;
+ dmas = <&edma1 0 12>, <&edma1 0 13>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -719,8 +711,7 @@
interrupts = <74 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks VF610_CLK_I2C3>;
clock-names = "ipg";
- dmas = <&edma0 1 38>,
- <&edma0 1 39>;
+ dmas = <&edma0 1 38>, <&edma0 1 39>;
dma-names = "rx","tx";
status = "disabled";
};
diff --git a/arch/arm/boot/dts/qcom/qcom-apq8026-samsung-matisse-wifi.dts b/arch/arm/boot/dts/qcom/qcom-apq8026-samsung-matisse-wifi.dts
index 884d99297d4c..f516e0426bb9 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8026-samsung-matisse-wifi.dts
+++ b/arch/arm/boot/dts/qcom/qcom-apq8026-samsung-matisse-wifi.dts
@@ -45,11 +45,11 @@
event-hall-sensor {
label = "Hall Effect Sensor";
- gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>;
- interrupts = <&tlmm 110 IRQ_TYPE_EDGE_FALLING>;
+ gpios = <&tlmm 110 GPIO_ACTIVE_LOW>;
linux,input-type = <EV_SW>;
linux,code = <SW_LID>;
debounce-interval = <15>;
+ linux,can-disable;
wakeup-source;
};
};
diff --git a/arch/arm/boot/dts/qcom/qcom-apq8060-dragonboard.dts b/arch/arm/boot/dts/qcom/qcom-apq8060-dragonboard.dts
index db4c791b2e2f..569cbf0d8df8 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8060-dragonboard.dts
+++ b/arch/arm/boot/dts/qcom/qcom-apq8060-dragonboard.dts
@@ -24,7 +24,6 @@
regulator-min-microvolt = <3700000>;
regulator-max-microvolt = <3700000>;
regulator-name = "VPH";
- regulator-type = "voltage";
regulator-always-on;
regulator-boot-on;
};
diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064-asus-nexus7-flo.dts b/arch/arm/boot/dts/qcom/qcom-apq8064-asus-nexus7-flo.dts
index c57c27cd8a20..c0dd6399f597 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064-asus-nexus7-flo.dts
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064-asus-nexus7-flo.dts
@@ -36,7 +36,6 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-name = "ext_3p3v";
- regulator-type = "voltage";
startup-delay-us = <0>;
gpio = <&tlmm_pinmux 77 GPIO_ACTIVE_HIGH>;
enable-active-high;
diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064-ifc6410.dts b/arch/arm/boot/dts/qcom/qcom-apq8064-ifc6410.dts
index 96307550523a..b0c5e7bd5e74 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064-ifc6410.dts
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064-ifc6410.dts
@@ -58,7 +58,6 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-name = "ext_3p3v";
- regulator-type = "voltage";
startup-delay-us = <0>;
gpio = <&tlmm_pinmux 77 GPIO_ACTIVE_HIGH>;
enable-active-high;
diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index 516f0d2495e2..59fd86b9fb47 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -1270,7 +1270,6 @@
dsi0: dsi@4700000 {
compatible = "qcom,apq8064-dsi-ctrl",
"qcom,mdss-dsi-ctrl";
- label = "MDSS DSI CTRL->0";
#address-cells = <1>;
#size-cells = <0>;
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dts b/arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dts
index 1796ded31d17..12e806adcda8 100644
--- a/arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dts
+++ b/arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dts
@@ -20,6 +20,33 @@
stdout-path = "serial0:115200n8";
};
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&buttons_pins>;
+ pinctrl-names = "default";
+
+ button {
+ label = "reset";
+ linux,code = <KEY_RESTART>;
+ gpios = <&qcom_pinmux 66 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ debounce-interval = <60>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-0 = <&leds_pins>;
+ pinctrl-names = "default";
+
+ led-0 {
+ label = "rb3011:green:user";
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&qcom_pinmux 33 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+ };
+
memory@42000000 {
reg = <0x42000000 0x3e000000>;
device_type = "memory";
@@ -302,34 +329,6 @@
};
};
};
-
- gpio-keys {
- compatible = "gpio-keys";
- pinctrl-0 = <&buttons_pins>;
- pinctrl-names = "default";
-
- button {
- label = "reset";
- linux,code = <KEY_RESTART>;
- gpios = <&qcom_pinmux 66 GPIO_ACTIVE_LOW>;
- linux,input-type = <1>;
- debounce-interval = <60>;
- };
- };
-
- leds {
- compatible = "gpio-leds";
- pinctrl-0 = <&leds_pins>;
- pinctrl-names = "default";
-
- led-0 {
- label = "rb3011:green:user";
- color = <LED_COLOR_ID_GREEN>;
- gpios = <&qcom_pinmux 33 GPIO_ACTIVE_HIGH>;
- default-state = "off";
- };
- };
-
};
};
diff --git a/arch/arm/boot/dts/qcom/qcom-ipq8064-v1.0.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8064-v1.0.dtsi
index 17f65e140e02..49de9752632f 100644
--- a/arch/arm/boot/dts/qcom/qcom-ipq8064-v1.0.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-ipq8064-v1.0.dtsi
@@ -14,6 +14,67 @@
stdout-path = "serial0:115200n8";
};
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&buttons_pins>;
+ pinctrl-names = "default";
+
+ button-1 {
+ label = "reset";
+ linux,code = <KEY_RESTART>;
+ gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ debounce-interval = <60>;
+ };
+ button-2 {
+ label = "wps";
+ linux,code = <KEY_WPS_BUTTON>;
+ gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ debounce-interval = <60>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-0 = <&leds_pins>;
+ pinctrl-names = "default";
+
+ led-0 {
+ label = "led_usb1";
+ gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "usbdev";
+ default-state = "off";
+ };
+
+ led-1 {
+ label = "led_usb3";
+ gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "usbdev";
+ default-state = "off";
+ };
+
+ led-2 {
+ label = "status_led_fail";
+ function = LED_FUNCTION_STATUS;
+ gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ led-3 {
+ label = "sata_led";
+ gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ led-4 {
+ label = "status_led_pass";
+ function = LED_FUNCTION_STATUS;
+ gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+ };
+
soc {
gsbi@16300000 {
qcom,mode = <GSBI_PROT_I2C_UART>;
@@ -64,66 +125,5 @@
ports-implemented = <0x1>;
status = "okay";
};
-
- gpio-keys {
- compatible = "gpio-keys";
- pinctrl-0 = <&buttons_pins>;
- pinctrl-names = "default";
-
- button-1 {
- label = "reset";
- linux,code = <KEY_RESTART>;
- gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>;
- linux,input-type = <1>;
- debounce-interval = <60>;
- };
- button-2 {
- label = "wps";
- linux,code = <KEY_WPS_BUTTON>;
- gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>;
- linux,input-type = <1>;
- debounce-interval = <60>;
- };
- };
-
- leds {
- compatible = "gpio-leds";
- pinctrl-0 = <&leds_pins>;
- pinctrl-names = "default";
-
- led-0 {
- label = "led_usb1";
- gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>;
- linux,default-trigger = "usbdev";
- default-state = "off";
- };
-
- led-1 {
- label = "led_usb3";
- gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>;
- linux,default-trigger = "usbdev";
- default-state = "off";
- };
-
- led-2 {
- label = "status_led_fail";
- function = LED_FUNCTION_STATUS;
- gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>;
- default-state = "off";
- };
-
- led-3 {
- label = "sata_led";
- gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>;
- default-state = "off";
- };
-
- led-4 {
- label = "status_led_pass";
- function = LED_FUNCTION_STATUS;
- gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>;
- default-state = "off";
- };
- };
};
};
diff --git a/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi b/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi
index fc4f52f9e9f7..63e21aa23642 100644
--- a/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi
@@ -47,14 +47,12 @@
};
};
- regulators {
- vsdcc_fixed: vsdcc-regulator {
- compatible = "regulator-fixed";
- regulator-name = "SDCC Power";
- regulator-min-microvolt = <2700000>;
- regulator-max-microvolt = <2700000>;
- regulator-always-on;
- };
+ vsdcc_fixed: vsdcc-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "SDCC Power";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ regulator-always-on;
};
soc: soc {
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi
index 44f3f0127fd7..97a377b5a0ec 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi
@@ -56,6 +56,18 @@
rpm: remoteproc {
compatible = "qcom,msm8226-rpm-proc", "qcom,rpm-proc";
+ master-stats {
+ compatible = "qcom,rpm-master-stats";
+ qcom,rpm-msg-ram = <&apss_master_stats>,
+ <&mpss_master_stats>,
+ <&lpss_master_stats>,
+ <&pronto_master_stats>;
+ qcom,master-names = "APSS",
+ "MPSS",
+ "LPSS",
+ "PRONTO";
+ };
+
smd-edge {
interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
qcom,ipc = <&apcs 8 0>;
@@ -230,6 +242,17 @@
status = "disabled";
};
+ blsp1_uart2: serial@f991e000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0xf991e000 0x1000>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>,
+ <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core",
+ "iface";
+ status = "disabled";
+ };
+
blsp1_uart3: serial@f991f000 {
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
reg = <0xf991f000 0x1000>;
@@ -313,6 +336,21 @@
#size-cells = <0>;
};
+ blsp1_i2c6: i2c@f9928000 {
+ compatible = "qcom,i2c-qup-v2.1.1";
+ reg = <0xf9928000 0x1000>;
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_QUP6_I2C_APPS_CLK>,
+ <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core",
+ "iface";
+ pinctrl-0 = <&blsp1_i2c6_pins>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
cci: cci@fda0c000 {
compatible = "qcom,msm8226-cci";
#address-cells = <1>;
@@ -460,6 +498,13 @@
bias-disable;
};
+ blsp1_i2c6_pins: blsp1-i2c6-state {
+ pins = "gpio22", "gpio23";
+ function = "blsp_i2c6";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
cci_default: cci-default-state {
pins = "gpio29", "gpio30";
function = "cci_i2c0";
@@ -742,6 +787,26 @@
rpm_msg_ram: sram@fc428000 {
compatible = "qcom,rpm-msg-ram";
reg = <0xfc428000 0x4000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0xfc428000 0x4000>;
+
+ apss_master_stats: sram@150 {
+ reg = <0x150 0x14>;
+ };
+
+ mpss_master_stats: sram@b50 {
+ reg = <0xb50 0x14>;
+ };
+
+ lpss_master_stats: sram@1550 {
+ reg = <0x1550 0x14>;
+ };
+
+ pronto_master_stats: sram@1f50 {
+ reg = <0x1f50 0x14>;
+ };
};
tcsr_mutex: hwlock@fd484000 {
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
index 706fef53767e..0bc2e66d15b1 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
@@ -116,6 +116,18 @@
rpm: remoteproc {
compatible = "qcom,msm8974-rpm-proc", "qcom,rpm-proc";
+ master-stats {
+ compatible = "qcom,rpm-master-stats";
+ qcom,rpm-msg-ram = <&apss_master_stats>,
+ <&mpss_master_stats>,
+ <&lpss_master_stats>,
+ <&pronto_master_stats>;
+ qcom,master-names = "APSS",
+ "MPSS",
+ "LPSS",
+ "PRONTO";
+ };
+
smd-edge {
interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
qcom,ipc = <&apcs 8 0>;
@@ -1067,6 +1079,26 @@
rpm_msg_ram: sram@fc428000 {
compatible = "qcom,rpm-msg-ram";
reg = <0xfc428000 0x4000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0xfc428000 0x4000>;
+
+ apss_master_stats: sram@150 {
+ reg = <0x150 0x14>;
+ };
+
+ mpss_master_stats: sram@b50 {
+ reg = <0xb50 0x14>;
+ };
+
+ lpss_master_stats: sram@1550 {
+ reg = <0x1550 0x14>;
+ };
+
+ pronto_master_stats: sram@1f50 {
+ reg = <0x1f50 0x14>;
+ };
};
bimc: interconnect@fc380000 {
diff --git a/arch/arm/boot/dts/qcom/qcom-sdx55.dtsi b/arch/arm/boot/dts/qcom/qcom-sdx55.dtsi
index 55ce87b75253..2aa5089a8513 100644
--- a/arch/arm/boot/dts/qcom/qcom-sdx55.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-sdx55.dtsi
@@ -379,7 +379,7 @@
power-domains = <&gcc PCIE_GDSC>;
- phys = <&pcie_lane>;
+ phys = <&pcie_phy>;
phy-names = "pciephy";
status = "disabled";
@@ -428,7 +428,7 @@
resets = <&gcc GCC_PCIE_BCR>;
reset-names = "core";
power-domains = <&gcc PCIE_GDSC>;
- phys = <&pcie_lane>;
+ phys = <&pcie_phy>;
phy-names = "pciephy";
max-link-speed = <3>;
num-lanes = <2>;
@@ -438,18 +438,25 @@
pcie_phy: phy@1c07000 {
compatible = "qcom,sdx55-qmp-pcie-phy";
- reg = <0x01c07000 0x1c4>;
+ reg = <0x01c07000 0x2000>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
clocks = <&gcc GCC_PCIE_AUX_PHY_CLK_SRC>,
<&gcc GCC_PCIE_CFG_AHB_CLK>,
<&gcc GCC_PCIE_0_CLKREF_CLK>,
- <&gcc GCC_PCIE_RCHNG_PHY_CLK>;
+ <&gcc GCC_PCIE_RCHNG_PHY_CLK>,
+ <&gcc GCC_PCIE_PIPE_CLK>;
clock-names = "aux",
"cfg_ahb",
"ref",
- "refgen";
+ "refgen",
+ "pipe";
+
+ clock-output-names = "pcie_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_PHY_BCR>;
reset-names = "phy";
@@ -458,20 +465,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie_lane: lanes@1c06000 {
- reg = <0x01c06000 0x104>, /* tx0 */
- <0x01c06200 0x328>, /* rx0 */
- <0x01c07200 0x1e8>, /* pcs */
- <0x01c06800 0x104>, /* tx1 */
- <0x01c06a00 0x328>, /* rx1 */
- <0x01c07600 0x800>; /* pcs_misc */
- clocks = <&gcc GCC_PCIE_PIPE_CLK>;
- clock-names = "pipe0";
-
- #phy-cells = <0>;
- clock-output-names = "pcie_pipe_clk";
- };
};
ipa: ipa@1e40000 {
@@ -645,7 +638,6 @@
#size-cells = <0>;
interrupt-controller;
#interrupt-cells = <4>;
- cell-index = <0>;
};
tlmm: pinctrl@f100000 {
diff --git a/arch/arm/boot/dts/qcom/qcom-sdx65-mtp.dts b/arch/arm/boot/dts/qcom/qcom-sdx65-mtp.dts
index fcf1c51c5e7a..9649c859a2c3 100644
--- a/arch/arm/boot/dts/qcom/qcom-sdx65-mtp.dts
+++ b/arch/arm/boot/dts/qcom/qcom-sdx65-mtp.dts
@@ -4,6 +4,10 @@
*/
/dts-v1/;
+/* PM7250B is configured to use SID2/3 */
+#define PM7250B_SID 2
+#define PM7250B_SID1 3
+
#include "qcom-sdx65.dtsi"
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include <arm64/qcom/pmk8350.dtsi>
diff --git a/arch/arm/boot/dts/qcom/qcom-sdx65.dtsi b/arch/arm/boot/dts/qcom/qcom-sdx65.dtsi
index 1a3583029a64..e559adaaeee7 100644
--- a/arch/arm/boot/dts/qcom/qcom-sdx65.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-sdx65.dtsi
@@ -466,9 +466,9 @@
interrupts = <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "hc_irq", "pwr_irq";
- clocks = <&gcc GCC_SDCC1_APPS_CLK>,
- <&gcc GCC_SDCC1_AHB_CLK>;
- clock-names = "core", "iface";
+ clocks = <&gcc GCC_SDCC1_AHB_CLK>,
+ <&gcc GCC_SDCC1_APPS_CLK>;
+ clock-names = "iface", "core";
status = "disabled";
};
@@ -544,7 +544,6 @@
#interrupt-cells = <4>;
#address-cells = <2>;
#size-cells = <0>;
- cell-index = <0>;
qcom,channel = <0>;
qcom,ee = <0>;
};
diff --git a/arch/arm/boot/dts/renesas/r7s72100-genmai.dts b/arch/arm/boot/dts/renesas/r7s72100-genmai.dts
index 1e8447176b10..29ba098f5dd5 100644
--- a/arch/arm/boot/dts/renesas/r7s72100-genmai.dts
+++ b/arch/arm/boot/dts/renesas/r7s72100-genmai.dts
@@ -29,9 +29,33 @@
reg = <0x08000000 0x08000000>;
};
- lbsc {
+ flash@18000000 {
+ compatible = "mtd-rom";
+ reg = <0x18000000 0x08000000>;
+ bank-width = <4>;
+ device-width = <1>;
+
+ clocks = <&mstp9_clks R7S72100_CLK_SPIBSC0>;
+ power-domains = <&cpg_clocks>;
+
#address-cells = <1>;
#size-cells = <1>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "user";
+ reg = <0x00000000 0x04000000>;
+ };
+
+ partition@4000000 {
+ label = "user1";
+ reg = <0x04000000 0x40000000>;
+ };
+ };
};
leds {
@@ -87,6 +111,62 @@
clock-frequency = <13330000>;
};
+&bsc {
+ flash@0 {
+ compatible = "cfi-flash";
+ reg = <0x00000000 0x04000000>;
+ bank-width = <2>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "uboot";
+ reg = <0x00000000 0x00040000>;
+ };
+
+ partition@40000 {
+ label = "uboot-env";
+ reg = <0x00040000 0x00020000>;
+ };
+
+ partition@60000 {
+ label = "flash";
+ reg = <0x00060000 0x03fa0000>;
+ };
+ };
+ };
+
+ flash@4000000 {
+ compatible = "cfi-flash";
+ reg = <0x04000000 0x04000000>;
+ bank-width = <2>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "uboot1";
+ reg = <0x00000000 0x00040000>;
+ };
+
+ partition@40000 {
+ label = "uboot-env1";
+ reg = <0x00040000 0x00020000>;
+ };
+
+ partition@60000 {
+ label = "flash1";
+ reg = <0x00060000 0x03fa0000>;
+ };
+ };
+ };
+};
+
&usb_x1_clk {
clock-frequency = <48000000>;
};
diff --git a/arch/arm/boot/dts/renesas/r7s72100-gr-peach.dts b/arch/arm/boot/dts/renesas/r7s72100-gr-peach.dts
index 105f9c71f9fd..9d29861f23f1 100644
--- a/arch/arm/boot/dts/renesas/r7s72100-gr-peach.dts
+++ b/arch/arm/boot/dts/renesas/r7s72100-gr-peach.dts
@@ -29,14 +29,8 @@
reg = <0x20000000 0x00a00000>;
};
- lbsc {
- #address-cells = <1>;
- #size-cells = <1>;
- };
-
flash@18000000 {
compatible = "mtd-rom";
- probe-type = "map_rom";
reg = <0x18000000 0x00800000>;
bank-width = <4>;
device-width = <1>;
diff --git a/arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts b/arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts
index 1c5acf694407..b547216d4801 100644
--- a/arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts
+++ b/arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts
@@ -29,6 +29,48 @@
reg = <0x08000000 0x02000000>;
};
+ flash@18000000 {
+ compatible = "mtd-rom";
+ reg = <0x18000000 0x08000000>;
+ clocks = <&mstp9_clks R7S72100_CLK_SPIBSC0>;
+ power-domains = <&cpg_clocks>;
+ bank-width = <4>;
+ device-width = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "uboot";
+ reg = <0x00000000 0x00080000>;
+ };
+
+ partition@80000 {
+ label = "uboot-env";
+ reg = <0x00080000 0x00040000>;
+ };
+
+ partition@c0000 {
+ label = "dt";
+ reg = <0x000c0000 0x00040000>;
+ };
+
+ partition@100000 {
+ label = "kernel";
+ reg = <0x00100000 0x00280000>;
+ };
+
+ partition@400000 {
+ label = "rootfs";
+ reg = <0x00400000 0x01c00000>;
+ };
+ };
+ };
+
keyboard {
compatible = "gpio-keys";
@@ -60,11 +102,6 @@
};
};
- lbsc {
- #address-cells = <1>;
- #size-cells = <1>;
- };
-
leds {
compatible = "gpio-leds";
@@ -118,6 +155,30 @@
};
};
+&bsc {
+ flash@0 {
+ compatible = "cfi-flash";
+ reg = <0x00000000 0x4000000>;
+ bank-width = <2>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "apps";
+ reg = <0x00000000 0x01000000>;
+ };
+
+ partition@1000000 {
+ label = "data";
+ reg = <0x01000000 0x03000000>;
+ };
+ };
+ };
+};
+
&usb_x1_clk {
clock-frequency = <48000000>;
};
diff --git a/arch/arm/boot/dts/renesas/r7s72100.dtsi b/arch/arm/boot/dts/renesas/r7s72100.dtsi
index b07b71307f24..e6d8da6faffb 100644
--- a/arch/arm/boot/dts/renesas/r7s72100.dtsi
+++ b/arch/arm/boot/dts/renesas/r7s72100.dtsi
@@ -36,6 +36,13 @@
clock-div = <3>;
};
+ bsc: bsc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0x18000000>;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts b/arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts
index 69a5a44b8a2f..cd2324b8e8ff 100644
--- a/arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts
+++ b/arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts
@@ -63,11 +63,6 @@
};
};
- lbsc {
- #address-cells = <1>;
- #size-cells = <1>;
- };
-
leds {
compatible = "gpio-leds";
diff --git a/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts
index e81a7213d304..ed75c01dbee1 100644
--- a/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts
+++ b/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts
@@ -164,7 +164,7 @@
&bsc {
flash@0 {
- compatible = "cfi-flash", "mtd-rom";
+ compatible = "cfi-flash";
reg = <0x0 0x08000000>;
bank-width = <2>;
diff --git a/arch/arm/boot/dts/renesas/r8a7778-bockw.dts b/arch/arm/boot/dts/renesas/r8a7778-bockw.dts
index 9b65d246e583..a3f9d74e8877 100644
--- a/arch/arm/boot/dts/renesas/r8a7778-bockw.dts
+++ b/arch/arm/boot/dts/renesas/r8a7778-bockw.dts
@@ -62,6 +62,35 @@
};
&bsc {
+ flash@0 {
+ compatible = "cfi-flash";
+ reg = <0x0 0x04000000>;
+ pinctrl-0 = <&flash_pins>;
+ pinctrl-names = "default";
+ bank-width = <2>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "uboot";
+ reg = <0x00000000 0x00040000>;
+ read-only;
+ };
+ partition@40000 {
+ label = "uboot-env";
+ reg = <0x00040000 0x00040000>;
+ read-only;
+ };
+ partition@80000 {
+ label = "flash";
+ reg = <0x00080000 0x03f80000>;
+ };
+ };
+ };
+
ethernet@18300000 {
compatible = "smsc,lan89218", "smsc,lan9115";
reg = <0x18300000 0x1000>;
@@ -126,6 +155,11 @@
pinctrl-0 = <&scif_clk_pins>;
pinctrl-names = "default";
+ flash_pins: flash {
+ groups = "lbsc_cs0";
+ function = "lbsc";
+ };
+
scif0_pins: scif0 {
groups = "scif0_data_a", "scif0_ctrl";
function = "scif0";
diff --git a/arch/arm/boot/dts/renesas/r8a7779-marzen.dts b/arch/arm/boot/dts/renesas/r8a7779-marzen.dts
index fd40890bd77b..08ea149b1ee6 100644
--- a/arch/arm/boot/dts/renesas/r8a7779-marzen.dts
+++ b/arch/arm/boot/dts/renesas/r8a7779-marzen.dts
@@ -52,21 +52,6 @@
states = <3300000 1>, <1800000 0>;
};
- ethernet@18000000 {
- compatible = "smsc,lan89218", "smsc,lan9115";
- reg = <0x18000000 0x100>;
- pinctrl-0 = <&ethernet_pins>;
- pinctrl-names = "default";
-
- phy-mode = "mii";
- interrupt-parent = <&irqpin0>;
- interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
- smsc,irq-push-pull;
- reg-io-width = <4>;
- vddvario-supply = <&fixedregulator3v3>;
- vdd33a-supply = <&fixedregulator3v3>;
- };
-
keyboard-irq {
compatible = "gpio-keys";
@@ -229,6 +214,23 @@
clock-frequency = <31250000>;
};
+&lbsc {
+ ethernet@18000000 {
+ compatible = "smsc,lan89218", "smsc,lan9115";
+ reg = <0x18000000 0x100>;
+ pinctrl-0 = <&ethernet_pins>;
+ pinctrl-names = "default";
+
+ phy-mode = "mii";
+ interrupt-parent = <&irqpin0>;
+ interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+ smsc,irq-push-pull;
+ reg-io-width = <4>;
+ vddvario-supply = <&fixedregulator3v3>;
+ vdd33a-supply = <&fixedregulator3v3>;
+ };
+};
+
&tmu0 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/renesas/r8a7779.dtsi b/arch/arm/boot/dts/renesas/r8a7779.dtsi
index 97b767d81d92..7743af5e2a6f 100644
--- a/arch/arm/boot/dts/renesas/r8a7779.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7779.dtsi
@@ -699,6 +699,13 @@
};
};
+ lbsc: lbsc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0x1c000000>;
+ };
+
prr: chipid@ff000044 {
compatible = "renesas,prr";
reg = <0xff000044 4>;
diff --git a/arch/arm/boot/dts/renesas/r8a7790-lager.dts b/arch/arm/boot/dts/renesas/r8a7790-lager.dts
index 5ad5349a50dc..4d666ad8b114 100644
--- a/arch/arm/boot/dts/renesas/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/renesas/r8a7790-lager.dts
@@ -73,11 +73,6 @@
reg = <1 0x40000000 0 0xc0000000>;
};
- lbsc {
- #address-cells = <1>;
- #size-cells = <1>;
- };
-
keyboard {
compatible = "gpio-keys";
diff --git a/arch/arm/boot/dts/renesas/r8a7791-koelsch.dts b/arch/arm/boot/dts/renesas/r8a7791-koelsch.dts
index 26a40782cc89..545515b41ea3 100644
--- a/arch/arm/boot/dts/renesas/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/renesas/r8a7791-koelsch.dts
@@ -73,11 +73,6 @@
reg = <2 0x00000000 0 0x40000000>;
};
- lbsc {
- #address-cells = <1>;
- #size-cells = <1>;
- };
-
keyboard {
compatible = "gpio-keys";
diff --git a/arch/arm/boot/dts/renesas/r8a7792-blanche.dts b/arch/arm/boot/dts/renesas/r8a7792-blanche.dts
index c66de9dd12df..e793134f32a3 100644
--- a/arch/arm/boot/dts/renesas/r8a7792-blanche.dts
+++ b/arch/arm/boot/dts/renesas/r8a7792-blanche.dts
@@ -39,21 +39,6 @@
regulator-always-on;
};
- ethernet@18000000 {
- compatible = "smsc,lan89218", "smsc,lan9115";
- reg = <0 0x18000000 0 0x100>;
- phy-mode = "mii";
- interrupt-parent = <&irqc>;
- interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
- smsc,irq-push-pull;
- reg-io-width = <4>;
- vddvario-supply = <&d3_3v>;
- vdd33a-supply = <&d3_3v>;
-
- pinctrl-0 = <&lan89218_pins>;
- pinctrl-names = "default";
- };
-
vga-encoder {
compatible = "adi,adv7123";
@@ -196,6 +181,23 @@
clock-frequency = <48000000>;
};
+&lbsc {
+ ethernet@18000000 {
+ compatible = "smsc,lan89218", "smsc,lan9115";
+ reg = <0x18000000 0x100>;
+ phy-mode = "mii";
+ interrupt-parent = <&irqc>;
+ interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+ smsc,irq-push-pull;
+ reg-io-width = <4>;
+ vddvario-supply = <&d3_3v>;
+ vdd33a-supply = <&d3_3v>;
+
+ pinctrl-0 = <&lan89218_pins>;
+ pinctrl-names = "default";
+ };
+};
+
&pfc {
scif0_pins: scif0 {
groups = "scif0_data";
@@ -239,7 +241,7 @@
};
keyboard_pins: keyboard {
- pins = "GP_3_10", "GP_3_11", "GP_3_12", "GP_3_15", "GP_11_02";
+ pins = "GP_3_10", "GP_3_11", "GP_3_12", "GP_3_15", "GP_11_2";
bias-pull-up;
};
diff --git a/arch/arm/boot/dts/renesas/r8a7792-wheat.dts b/arch/arm/boot/dts/renesas/r8a7792-wheat.dts
index 434e4655be9d..f87e78fe3f6e 100644
--- a/arch/arm/boot/dts/renesas/r8a7792-wheat.dts
+++ b/arch/arm/boot/dts/renesas/r8a7792-wheat.dts
@@ -38,22 +38,6 @@
regulator-always-on;
};
- ethernet@18000000 {
- compatible = "smsc,lan89218", "smsc,lan9115";
- reg = <0 0x18000000 0 0x100>;
- phy-mode = "mii";
- interrupt-parent = <&irqc>;
- interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
- smsc,irq-push-pull;
- smsc,save-mac-address;
- reg-io-width = <4>;
- vddvario-supply = <&d3_3v>;
- vdd33a-supply = <&d3_3v>;
-
- pinctrl-0 = <&lan89218_pins>;
- pinctrl-names = "default";
- };
-
keyboard {
compatible = "gpio-keys";
@@ -117,6 +101,24 @@
clock-frequency = <20000000>;
};
+&lbsc {
+ ethernet@18000000 {
+ compatible = "smsc,lan89218", "smsc,lan9115";
+ reg = <0x18000000 0x100>;
+ phy-mode = "mii";
+ interrupt-parent = <&irqc>;
+ interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+ smsc,irq-push-pull;
+ smsc,save-mac-address;
+ reg-io-width = <4>;
+ vddvario-supply = <&d3_3v>;
+ vdd33a-supply = <&d3_3v>;
+
+ pinctrl-0 = <&lan89218_pins>;
+ pinctrl-names = "default";
+ };
+};
+
&pfc {
scif0_pins: scif0 {
groups = "scif0_data";
diff --git a/arch/arm/boot/dts/renesas/r8a7792.dtsi b/arch/arm/boot/dts/renesas/r8a7792.dtsi
index a6d9367f8fa0..ecfab3ff59e8 100644
--- a/arch/arm/boot/dts/renesas/r8a7792.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7792.dtsi
@@ -84,6 +84,13 @@
clock-frequency = <0>;
};
+ lbsc: lbsc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0x1c000000>;
+ };
+
pmu {
compatible = "arm,cortex-a15-pmu";
interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/arch/arm/boot/dts/renesas/r8a7794-alt.dts b/arch/arm/boot/dts/renesas/r8a7794-alt.dts
index 4d93319674c6..08df031bc27c 100644
--- a/arch/arm/boot/dts/renesas/r8a7794-alt.dts
+++ b/arch/arm/boot/dts/renesas/r8a7794-alt.dts
@@ -90,11 +90,6 @@
states = <3300000 1>, <1800000 0>;
};
- lbsc {
- #address-cells = <1>;
- #size-cells = <1>;
- };
-
keyboard {
compatible = "gpio-keys";
diff --git a/arch/arm/boot/dts/rockchip/rk3128.dtsi b/arch/arm/boot/dts/rockchip/rk3128.dtsi
index b63bd4ad3143..01edf244ddee 100644
--- a/arch/arm/boot/dts/rockchip/rk3128.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3128.dtsi
@@ -27,6 +27,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "rockchip,rk3036-smp";
cpu0: cpu@f00 {
device_type = "cpu";
@@ -34,10 +35,8 @@
reg = <0xf00>;
clock-latency = <40000>;
clocks = <&cru ARMCLK>;
- operating-points = <
- /* KHz uV */
- 816000 1000000
- >;
+ resets = <&cru SRST_CORE0>;
+ operating-points-v2 = <&cpu_opp_table>;
#cooling-cells = <2>; /* min followed by max */
};
@@ -45,18 +44,59 @@
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0xf01>;
+ resets = <&cru SRST_CORE1>;
+ operating-points-v2 = <&cpu_opp_table>;
};
cpu2: cpu@f02 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0xf02>;
+ resets = <&cru SRST_CORE2>;
+ operating-points-v2 = <&cpu_opp_table>;
};
cpu3: cpu@f03 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0xf03>;
+ resets = <&cru SRST_CORE3>;
+ operating-points-v2 = <&cpu_opp_table>;
+ };
+ };
+
+ cpu_opp_table: opp-table-0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-216000000 {
+ opp-hz = /bits/ 64 <216000000>;
+ opp-microvolt = <950000 950000 1325000>;
+ };
+ opp-408000000 {
+ opp-hz = /bits/ 64 <408000000>;
+ opp-microvolt = <950000 950000 1325000>;
+ };
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <950000 950000 1325000>;
+ };
+ opp-696000000 {
+ opp-hz = /bits/ 64 <696000000>;
+ opp-microvolt = <975000 975000 1325000>;
+ };
+ opp-816000000 {
+ opp-hz = /bits/ 64 <816000000>;
+ opp-microvolt = <1075000 1075000 1325000>;
+ opp-suspend;
+ };
+ opp-1008000000 {
+ opp-hz = /bits/ 64 <1008000000>;
+ opp-microvolt = <1200000 1200000 1325000>;
+ };
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <1325000 1325000 1325000>;
};
};
@@ -64,7 +104,8 @@
compatible = "arm,armv7-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
- <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
arm,cpu-registers-not-fw-configured;
clock-frequency = <24000000>;
};
@@ -76,6 +117,19 @@
#clock-cells = <0>;
};
+ imem: sram@10080000 {
+ compatible = "mmio-sram";
+ reg = <0x10080000 0x2000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x10080000 0x2000>;
+
+ smp-sram@0 {
+ compatible = "rockchip,rk3066-smp-sram";
+ reg = <0x00 0x10>;
+ };
+ };
+
pmu: syscon@100a0000 {
compatible = "rockchip,rk3128-pmu", "syscon", "simple-mfd";
reg = <0x100a0000 0x1000>;
@@ -233,7 +287,7 @@
compatible = "rockchip,rk3128-timer", "rockchip,rk3288-timer";
reg = <0x20044000 0x20>;
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cru PCLK_TIMER>, <&xin24m>;
+ clocks = <&cru PCLK_TIMER>, <&cru SCLK_TIMER0>;
clock-names = "pclk", "timer";
};
@@ -241,7 +295,7 @@
compatible = "rockchip,rk3128-timer", "rockchip,rk3288-timer";
reg = <0x20044020 0x20>;
interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cru PCLK_TIMER>, <&xin24m>;
+ clocks = <&cru PCLK_TIMER>, <&cru SCLK_TIMER1>;
clock-names = "pclk", "timer";
};
@@ -249,7 +303,7 @@
compatible = "rockchip,rk3128-timer", "rockchip,rk3288-timer";
reg = <0x20044040 0x20>;
interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cru PCLK_TIMER>, <&xin24m>;
+ clocks = <&cru PCLK_TIMER>, <&cru SCLK_TIMER2>;
clock-names = "pclk", "timer";
};
@@ -257,7 +311,7 @@
compatible = "rockchip,rk3128-timer", "rockchip,rk3288-timer";
reg = <0x20044060 0x20>;
interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cru PCLK_TIMER>, <&xin24m>;
+ clocks = <&cru PCLK_TIMER>, <&cru SCLK_TIMER3>;
clock-names = "pclk", "timer";
};
@@ -265,7 +319,7 @@
compatible = "rockchip,rk3128-timer", "rockchip,rk3288-timer";
reg = <0x20044080 0x20>;
interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cru PCLK_TIMER>, <&xin24m>;
+ clocks = <&cru PCLK_TIMER>, <&cru SCLK_TIMER4>;
clock-names = "pclk", "timer";
};
@@ -273,7 +327,7 @@
compatible = "rockchip,rk3128-timer", "rockchip,rk3288-timer";
reg = <0x200440a0 0x20>;
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cru PCLK_TIMER>, <&xin24m>;
+ clocks = <&cru PCLK_TIMER>, <&cru SCLK_TIMER5>;
clock-names = "pclk", "timer";
};
@@ -426,7 +480,7 @@
i2c0: i2c@20072000 {
compatible = "rockchip,rk3128-i2c", "rockchip,rk3288-i2c";
- reg = <20072000 0x1000>;
+ reg = <0x20072000 0x1000>;
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "i2c";
clocks = <&cru PCLK_I2C0>;
@@ -458,6 +512,7 @@
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
arm,pl330-broken-no-flushp;
+ arm,pl330-periph-burst;
clocks = <&cru ACLK_DMAC>;
clock-names = "apb_pclk";
#dma-cells = <1>;
@@ -793,7 +848,7 @@
};
sdmmc_pwren: sdmmc-pwren {
- rockchip,pins = <1 RK_PB6 1 &pcfg_pull_default>;
+ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_default>;
};
sdmmc_bus4: sdmmc-bus4 {
diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
index ffc16d6b97e1..a721744cbfd1 100644
--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
@@ -215,9 +215,9 @@
power-domain@RK3228_PD_VOP {
reg = <RK3228_PD_VOP>;
- clocks =<&cru ACLK_VOP>,
- <&cru DCLK_VOP>,
- <&cru HCLK_VOP>;
+ clocks = <&cru ACLK_VOP>,
+ <&cru DCLK_VOP>,
+ <&cru HCLK_VOP>;
pm_qos = <&qos_vop>;
#power-domain-cells = <0>;
};
diff --git a/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts b/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts
index 3d587602e13a..f09be8405964 100644
--- a/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts
+++ b/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts
@@ -88,6 +88,10 @@
};
};
+&pwm11 {
+ status = "okay";
+};
+
&sdmmc {
bus-width = <4>;
cap-mmc-highspeed;
diff --git a/arch/arm/boot/dts/rockchip/rv1126-pinctrl.dtsi b/arch/arm/boot/dts/rockchip/rv1126-pinctrl.dtsi
index 554353e0a758..bb34b0c9cb4a 100644
--- a/arch/arm/boot/dts/rockchip/rv1126-pinctrl.dtsi
+++ b/arch/arm/boot/dts/rockchip/rv1126-pinctrl.dtsi
@@ -87,6 +87,22 @@
<0 RK_PB5 1 &pcfg_pull_none_drv_level_0_smt>;
};
};
+ pwm2 {
+ /omit-if-no-ref/
+ pwm2m0_pins: pwm2m0-pins {
+ rockchip,pins =
+ /* pwm2_pin_m0 */
+ <0 RK_PC0 3 &pcfg_pull_none>;
+ };
+ };
+ pwm11 {
+ /omit-if-no-ref/
+ pwm11m0_pins: pwm11m0-pins {
+ rockchip,pins =
+ /* pwm11_pin_m0 */
+ <3 RK_PA7 6 &pcfg_pull_none>;
+ };
+ };
rgmii {
/omit-if-no-ref/
rgmiim1_pins: rgmiim1-pins {
diff --git a/arch/arm/boot/dts/rockchip/rv1126.dtsi b/arch/arm/boot/dts/rockchip/rv1126.dtsi
index 9c918420ecd5..9ccd1bad6229 100644
--- a/arch/arm/boot/dts/rockchip/rv1126.dtsi
+++ b/arch/arm/boot/dts/rockchip/rv1126.dtsi
@@ -247,6 +247,17 @@
status = "disabled";
};
+ pwm2: pwm@ff430020 {
+ compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm";
+ reg = <0xff430020 0x10>;
+ clock-names = "pwm", "pclk";
+ clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm2m0_pins>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
pmucru: clock-controller@ff480000 {
compatible = "rockchip,rv1126-pmucru";
reg = <0xff480000 0x1000>;
@@ -276,6 +287,17 @@
clock-names = "apb_pclk";
};
+ pwm11: pwm@ff550030 {
+ compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm";
+ reg = <0xff550030 0x10>;
+ clock-names = "pwm", "pclk";
+ clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>;
+ pinctrl-0 = <&pwm11m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
uart0: serial@ff560000 {
compatible = "rockchip,rv1126-uart", "snps,dw-apb-uart";
reg = <0xff560000 0x100>;
diff --git a/arch/arm/boot/dts/samsung/exynos4210.dtsi b/arch/arm/boot/dts/samsung/exynos4210.dtsi
index 0e27c3375e2e..510e8665d1a2 100644
--- a/arch/arm/boot/dts/samsung/exynos4210.dtsi
+++ b/arch/arm/boot/dts/samsung/exynos4210.dtsi
@@ -391,8 +391,16 @@
};
&cpu_thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
+ /*
+ * Exynos 4210 supports thermal interrupts, but only for the rising
+ * threshold. This means that polling is not needed for preventing
+ * overheating, but only for decreasing cooling when possible. Hence we
+ * poll with a high delay. Ideally, we would disable polling for the
+ * first trip point, but this isn't really possible without outrageous
+ * hacks.
+ */
+ polling-delay-passive = <5000>;
+ polling-delay = <5000>;
};
&gic {
diff --git a/arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi b/arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi
index ce81e42bf5eb..d7954ff466b4 100644
--- a/arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi
+++ b/arch/arm/boot/dts/samsung/exynos4212-tab3.dtsi
@@ -300,34 +300,33 @@
mic-bias-supply = <&mic_bias_reg>;
submic-bias-supply = <&submic_bias_reg>;
- samsung,audio-routing =
- "HP", "HPOUT1L",
- "HP", "HPOUT1R",
+ audio-routing = "HP", "HPOUT1L",
+ "HP", "HPOUT1R",
- "SPK", "SPKOUTLN",
- "SPK", "SPKOUTLP",
- "SPK", "SPKOUTRN",
- "SPK", "SPKOUTRP",
+ "SPK", "SPKOUTLN",
+ "SPK", "SPKOUTLP",
+ "SPK", "SPKOUTRN",
+ "SPK", "SPKOUTRP",
- "RCV", "HPOUT2N",
- "RCV", "HPOUT2P",
+ "RCV", "HPOUT2N",
+ "RCV", "HPOUT2P",
- "LINE", "LINEOUT2N",
- "LINE", "LINEOUT2P",
+ "LINE", "LINEOUT2N",
+ "LINE", "LINEOUT2P",
- "HDMI", "LINEOUT1N",
- "HDMI", "LINEOUT1P",
+ "HDMI", "LINEOUT1N",
+ "HDMI", "LINEOUT1P",
- "IN2LP:VXRN", "MICBIAS1",
- "IN2LN", "MICBIAS1",
- "Main Mic", "MICBIAS1",
+ "IN2LP:VXRN", "MICBIAS1",
+ "IN2LN", "MICBIAS1",
+ "Main Mic", "MICBIAS1",
- "IN1RP", "MICBIAS2",
- "IN1RN", "MICBIAS2",
- "Sub Mic", "MICBIAS2",
+ "IN1RP", "MICBIAS2",
+ "IN1RN", "MICBIAS2",
+ "Sub Mic", "MICBIAS2",
- "IN1LP", "Headset Mic",
- "IN1LN", "Headset Mic";
+ "IN1LP", "Headset Mic",
+ "IN1LN", "Headset Mic";
cpu {
sound-dai = <&i2s0 0>;
diff --git a/arch/arm/boot/dts/samsung/exynos4412-galaxy-s3.dtsi b/arch/arm/boot/dts/samsung/exynos4412-galaxy-s3.dtsi
index 94122e9c6625..54e1a57ae886 100644
--- a/arch/arm/boot/dts/samsung/exynos4412-galaxy-s3.dtsi
+++ b/arch/arm/boot/dts/samsung/exynos4412-galaxy-s3.dtsi
@@ -173,36 +173,35 @@
};
&sound {
- samsung,audio-routing =
- "HP", "HPOUT1L",
- "HP", "HPOUT1R",
+ audio-routing = "HP", "HPOUT1L",
+ "HP", "HPOUT1R",
- "SPK", "SPKOUTLN",
- "SPK", "SPKOUTLP",
- "SPK", "SPKOUTRN",
- "SPK", "SPKOUTRP",
+ "SPK", "SPKOUTLN",
+ "SPK", "SPKOUTLP",
+ "SPK", "SPKOUTRN",
+ "SPK", "SPKOUTRP",
- "RCV", "HPOUT2N",
- "RCV", "HPOUT2P",
+ "RCV", "HPOUT2N",
+ "RCV", "HPOUT2P",
- "HDMI", "LINEOUT1N",
- "HDMI", "LINEOUT1P",
+ "HDMI", "LINEOUT1N",
+ "HDMI", "LINEOUT1P",
- "LINE", "LINEOUT2N",
- "LINE", "LINEOUT2P",
+ "LINE", "LINEOUT2N",
+ "LINE", "LINEOUT2P",
- "IN1LP", "MICBIAS1",
- "IN1LN", "MICBIAS1",
- "Main Mic", "MICBIAS1",
+ "IN1LP", "MICBIAS1",
+ "IN1LN", "MICBIAS1",
+ "Main Mic", "MICBIAS1",
- "IN1RP", "Sub Mic",
- "IN1RN", "Sub Mic",
+ "IN1RP", "Sub Mic",
+ "IN1RN", "Sub Mic",
- "IN2LP:VXRN", "MICBIAS2",
- "Headset Mic", "MICBIAS2",
+ "IN2LP:VXRN", "MICBIAS2",
+ "Headset Mic", "MICBIAS2",
- "IN2RN", "FM In",
- "IN2RP:VXRP", "FM In";
+ "IN2RN", "FM In",
+ "IN2RP:VXRP", "FM In";
};
&submic_bias_reg {
diff --git a/arch/arm/boot/dts/samsung/exynos4412-midas.dtsi b/arch/arm/boot/dts/samsung/exynos4412-midas.dtsi
index 7daf25865551..3d5aace668dc 100644
--- a/arch/arm/boot/dts/samsung/exynos4412-midas.dtsi
+++ b/arch/arm/boot/dts/samsung/exynos4412-midas.dtsi
@@ -137,21 +137,21 @@
key-down {
gpios = <&gpx3 3 GPIO_ACTIVE_LOW>;
- linux,code = <114>;
+ linux,code = <KEY_VOLUMEDOWN>;
label = "volume down";
debounce-interval = <10>;
};
key-up {
gpios = <&gpx2 2 GPIO_ACTIVE_LOW>;
- linux,code = <115>;
+ linux,code = <KEY_VOLUMEUP>;
label = "volume up";
debounce-interval = <10>;
};
key-power {
gpios = <&gpx2 7 GPIO_ACTIVE_LOW>;
- linux,code = <116>;
+ linux,code = <KEY_POWER>;
label = "power";
debounce-interval = <10>;
wakeup-source;
@@ -159,7 +159,7 @@
key-ok {
gpios = <&gpx0 1 GPIO_ACTIVE_LOW>;
- linux,code = <139>;
+ linux,code = <KEY_OK>;
label = "ok";
debounce-interval = <10>;
wakeup-source;
diff --git a/arch/arm/boot/dts/samsung/exynos4412-n710x.dts b/arch/arm/boot/dts/samsung/exynos4412-n710x.dts
index 9ae05b0d684c..0a151437fc73 100644
--- a/arch/arm/boot/dts/samsung/exynos4412-n710x.dts
+++ b/arch/arm/boot/dts/samsung/exynos4412-n710x.dts
@@ -76,34 +76,33 @@
};
&sound {
- samsung,audio-routing =
- "HP", "HPOUT1L",
- "HP", "HPOUT1R",
+ audio-routing = "HP", "HPOUT1L",
+ "HP", "HPOUT1R",
- "SPK", "SPKOUTLN",
- "SPK", "SPKOUTLP",
+ "SPK", "SPKOUTLN",
+ "SPK", "SPKOUTLP",
- "RCV", "HPOUT2N",
- "RCV", "HPOUT2P",
+ "RCV", "HPOUT2N",
+ "RCV", "HPOUT2P",
- "HDMI", "LINEOUT1N",
- "HDMI", "LINEOUT1P",
+ "HDMI", "LINEOUT1N",
+ "HDMI", "LINEOUT1P",
- "LINE", "LINEOUT2N",
- "LINE", "LINEOUT2P",
+ "LINE", "LINEOUT2N",
+ "LINE", "LINEOUT2P",
- "IN1LP", "MICBIAS2",
- "IN1LN", "MICBIAS2",
- "Headset Mic", "MICBIAS2",
+ "IN1LP", "MICBIAS2",
+ "IN1LN", "MICBIAS2",
+ "Headset Mic", "MICBIAS2",
- "IN1RP", "Sub Mic",
- "IN1RN", "Sub Mic",
+ "IN1RP", "Sub Mic",
+ "IN1RN", "Sub Mic",
- "IN2LP:VXRN", "Main Mic",
- "IN2LN", "Main Mic",
+ "IN2LP:VXRN", "Main Mic",
+ "IN2LN", "Main Mic",
- "IN2RN", "FM In",
- "IN2RP:VXRP", "FM In";
+ "IN2RN", "FM In",
+ "IN2RP:VXRP", "FM In";
};
&submic_bias_reg {
diff --git a/arch/arm/boot/dts/samsung/exynos4412-odroidu3.dts b/arch/arm/boot/dts/samsung/exynos4412-odroidu3.dts
index 42812da1f882..b1b0916b1505 100644
--- a/arch/arm/boot/dts/samsung/exynos4412-odroidu3.dts
+++ b/arch/arm/boot/dts/samsung/exynos4412-odroidu3.dts
@@ -138,13 +138,12 @@
samsung,audio-widgets =
"Headphone", "Headphone Jack",
"Speakers", "Speakers";
- samsung,audio-routing =
- "Headphone Jack", "HPL",
- "Headphone Jack", "HPR",
- "Headphone Jack", "MICBIAS",
- "IN1", "Headphone Jack",
- "Speakers", "SPKL",
- "Speakers", "SPKR";
+ audio-routing = "Headphone Jack", "HPL",
+ "Headphone Jack", "HPR",
+ "Headphone Jack", "MICBIAS",
+ "IN1", "Headphone Jack",
+ "Speakers", "SPKL",
+ "Speakers", "SPKR";
};
&spi_1 {
diff --git a/arch/arm/boot/dts/samsung/exynos4412-odroidx.dts b/arch/arm/boot/dts/samsung/exynos4412-odroidx.dts
index d5316cf2fbb6..0eb8a2680a20 100644
--- a/arch/arm/boot/dts/samsung/exynos4412-odroidx.dts
+++ b/arch/arm/boot/dts/samsung/exynos4412-odroidx.dts
@@ -135,9 +135,8 @@
"Headphone", "Headphone Jack",
"Microphone", "Mic Jack",
"Microphone", "DMIC";
- samsung,audio-routing =
- "Headphone Jack", "HPL",
- "Headphone Jack", "HPR",
- "IN1", "Mic Jack",
- "Mic Jack", "MICBIAS";
+ audio-routing = "Headphone Jack", "HPL",
+ "Headphone Jack", "HPR",
+ "IN1", "Mic Jack",
+ "Mic Jack", "MICBIAS";
};
diff --git a/arch/arm/boot/dts/samsung/exynos5422-odroidxu3-audio.dtsi b/arch/arm/boot/dts/samsung/exynos5422-odroidxu3-audio.dtsi
index 86b96f9706db..52a1d8fd5452 100644
--- a/arch/arm/boot/dts/samsung/exynos5422-odroidxu3-audio.dtsi
+++ b/arch/arm/boot/dts/samsung/exynos5422-odroidxu3-audio.dtsi
@@ -18,16 +18,15 @@
samsung,audio-widgets =
"Headphone", "Headphone Jack",
"Speakers", "Speakers";
- samsung,audio-routing =
- "Headphone Jack", "HPL",
- "Headphone Jack", "HPR",
- "Headphone Jack", "MICBIAS",
- "IN12", "Headphone Jack",
- "Speakers", "SPKL",
- "Speakers", "SPKR",
- "I2S Playback", "Mixer DAI TX",
- "HiFi Playback", "Mixer DAI TX",
- "Mixer DAI RX", "HiFi Capture";
+ audio-routing = "Headphone Jack", "HPL",
+ "Headphone Jack", "HPR",
+ "Headphone Jack", "MICBIAS",
+ "IN12", "Headphone Jack",
+ "Speakers", "SPKL",
+ "Speakers", "SPKR",
+ "I2S Playback", "Mixer DAI TX",
+ "HiFi Playback", "Mixer DAI TX",
+ "Mixer DAI RX", "HiFi Capture";
cpu {
sound-dai = <&i2s0 0>, <&i2s0 1>;
diff --git a/arch/arm/boot/dts/samsung/exynos5422-odroidxu4.dts b/arch/arm/boot/dts/samsung/exynos5422-odroidxu4.dts
index f5fb617f46bd..363786f032cc 100644
--- a/arch/arm/boot/dts/samsung/exynos5422-odroidxu4.dts
+++ b/arch/arm/boot/dts/samsung/exynos5422-odroidxu4.dts
@@ -35,7 +35,7 @@
compatible = "samsung,odroid-xu3-audio";
model = "Odroid-XU4";
- samsung,audio-routing = "I2S Playback", "Mixer DAI TX";
+ audio-routing = "I2S Playback", "Mixer DAI TX";
cpu {
sound-dai = <&i2s0 0>, <&i2s0 1>;
diff --git a/arch/arm/boot/dts/samsung/s5pv210-fascinate4g.dts b/arch/arm/boot/dts/samsung/s5pv210-fascinate4g.dts
index eaa7c4f0e257..149e488f8e74 100644
--- a/arch/arm/boot/dts/samsung/s5pv210-fascinate4g.dts
+++ b/arch/arm/boot/dts/samsung/s5pv210-fascinate4g.dts
@@ -74,30 +74,29 @@
headset-detect-gpios = <&gph0 6 GPIO_ACTIVE_HIGH>;
headset-key-gpios = <&gph3 6 GPIO_ACTIVE_HIGH>;
- samsung,audio-routing =
- "HP", "HPOUT1L",
- "HP", "HPOUT1R",
+ audio-routing = "HP", "HPOUT1L",
+ "HP", "HPOUT1R",
- "SPK", "SPKOUTLN",
- "SPK", "SPKOUTLP",
+ "SPK", "SPKOUTLN",
+ "SPK", "SPKOUTLP",
- "RCV", "HPOUT2N",
- "RCV", "HPOUT2P",
+ "RCV", "HPOUT2N",
+ "RCV", "HPOUT2P",
- "LINE", "LINEOUT2N",
- "LINE", "LINEOUT2P",
+ "LINE", "LINEOUT2N",
+ "LINE", "LINEOUT2P",
- "IN1LP", "Main Mic",
- "IN1LN", "Main Mic",
+ "IN1LP", "Main Mic",
+ "IN1LN", "Main Mic",
- "IN1RP", "Headset Mic",
- "IN1RN", "Headset Mic",
+ "IN1RP", "Headset Mic",
+ "IN1RN", "Headset Mic",
- "Modem Out", "Modem TX",
- "Modem RX", "Modem In",
+ "Modem Out", "Modem TX",
+ "Modem RX", "Modem In",
- "Bluetooth SPK", "TX",
- "RX", "Bluetooth Mic";
+ "Bluetooth SPK", "TX",
+ "RX", "Bluetooth Mic";
pinctrl-names = "default";
pinctrl-0 = <&headset_det &earpath_sel>;
diff --git a/arch/arm/boot/dts/samsung/s5pv210-galaxys.dts b/arch/arm/boot/dts/samsung/s5pv210-galaxys.dts
index 532d3f5bceb1..879294412381 100644
--- a/arch/arm/boot/dts/samsung/s5pv210-galaxys.dts
+++ b/arch/arm/boot/dts/samsung/s5pv210-galaxys.dts
@@ -101,33 +101,32 @@
headset-detect-gpios = <&gph0 6 GPIO_ACTIVE_LOW>;
headset-key-gpios = <&gph3 6 GPIO_ACTIVE_HIGH>;
- samsung,audio-routing =
- "HP", "HPOUT1L",
- "HP", "HPOUT1R",
+ audio-routing = "HP", "HPOUT1L",
+ "HP", "HPOUT1R",
- "SPK", "SPKOUTLN",
- "SPK", "SPKOUTLP",
+ "SPK", "SPKOUTLN",
+ "SPK", "SPKOUTLP",
- "RCV", "HPOUT2N",
- "RCV", "HPOUT2P",
+ "RCV", "HPOUT2N",
+ "RCV", "HPOUT2P",
- "LINE", "LINEOUT2N",
- "LINE", "LINEOUT2P",
+ "LINE", "LINEOUT2N",
+ "LINE", "LINEOUT2P",
- "IN1LP", "Main Mic",
- "IN1LN", "Main Mic",
+ "IN1LP", "Main Mic",
+ "IN1LN", "Main Mic",
- "IN1RP", "Headset Mic",
- "IN1RN", "Headset Mic",
+ "IN1RP", "Headset Mic",
+ "IN1RN", "Headset Mic",
- "IN2LN", "FM In",
- "IN2RN", "FM In",
+ "IN2LN", "FM In",
+ "IN2RN", "FM In",
- "Modem Out", "Modem TX",
- "Modem RX", "Modem In",
+ "Modem Out", "Modem TX",
+ "Modem RX", "Modem In",
- "Bluetooth SPK", "TX",
- "RX", "Bluetooth Mic";
+ "Bluetooth SPK", "TX",
+ "RX", "Bluetooth Mic";
pinctrl-names = "default";
pinctrl-0 = <&headset_det &earpath_sel>;
diff --git a/arch/arm/boot/dts/st/Makefile b/arch/arm/boot/dts/st/Makefile
index 44b264c399ec..7892ad69b441 100644
--- a/arch/arm/boot/dts/st/Makefile
+++ b/arch/arm/boot/dts/st/Makefile
@@ -59,6 +59,7 @@ dtb-$(CONFIG_ARCH_STM32) += \
stm32mp157c-lxa-tac-gen1.dtb \
stm32mp157c-lxa-tac-gen2.dtb \
stm32mp157c-odyssey.dtb \
+ stm32mp157c-osd32mp1-red.dtb \
stm32mp157c-phycore-stm32mp1-3.dtb
dtb-$(CONFIG_ARCH_U8500) += \
ste-snowball.dtb \
diff --git a/arch/arm/boot/dts/st/spear1310-evb.dts b/arch/arm/boot/dts/st/spear1310-evb.dts
index 05408df38203..18191a87f07c 100644
--- a/arch/arm/boot/dts/st/spear1310-evb.dts
+++ b/arch/arm/boot/dts/st/spear1310-evb.dts
@@ -352,7 +352,6 @@
#size-cells = <0>;
spi-max-frequency = <1000000>;
spi-cpha;
- pl022,hierarchy = <0>;
pl022,interface = <0>;
pl022,slave-tx-disable;
pl022,com-mode = <0>;
@@ -385,7 +384,6 @@
spi-max-frequency = <12000000>;
spi-cpol;
spi-cpha;
- pl022,hierarchy = <0>;
pl022,interface = <0>;
pl022,slave-tx-disable;
pl022,com-mode = <0x2>;
diff --git a/arch/arm/boot/dts/st/spear1340-evb.dts b/arch/arm/boot/dts/st/spear1340-evb.dts
index 7700f2afc128..cea624fc745c 100644
--- a/arch/arm/boot/dts/st/spear1340-evb.dts
+++ b/arch/arm/boot/dts/st/spear1340-evb.dts
@@ -445,7 +445,6 @@
spi-max-frequency = <12000000>;
spi-cpol;
spi-cpha;
- pl022,hierarchy = <0>;
pl022,interface = <0>;
pl022,slave-tx-disable;
pl022,com-mode = <0x2>;
@@ -461,7 +460,6 @@
spi-max-frequency = <1000000>;
spi-cpha;
reg = <1>;
- pl022,hierarchy = <0>;
pl022,interface = <0>;
pl022,slave-tx-disable;
pl022,com-mode = <0>;
diff --git a/arch/arm/boot/dts/st/ste-href-tvk1281618-r2.dtsi b/arch/arm/boot/dts/st/ste-href-tvk1281618-r2.dtsi
index 37e59403c01f..7448135e25f6 100644
--- a/arch/arm/boot/dts/st/ste-href-tvk1281618-r2.dtsi
+++ b/arch/arm/boot/dts/st/ste-href-tvk1281618-r2.dtsi
@@ -192,7 +192,7 @@
#size-cells = <0>;
reg = <0x4b>;
vdd-supply = <&ab8500_ldo_aux1_reg>;
- vddio-supply = <&db8500_vsmps2_reg>;
+ vio-supply = <&db8500_vsmps2_reg>;
pinctrl-names = "default";
pinctrl-0 = <&synaptics_tvk_mode>;
interrupt-parent = <&gpio2>;
@@ -200,7 +200,7 @@
rmi4-f01@1 {
reg = <0x1>;
- syna,nosleep = <1>;
+ syna,nosleep-mode = <1>;
};
rmi4-f11@11 {
reg = <0x11>;
diff --git a/arch/arm/boot/dts/st/stih407-family.dtsi b/arch/arm/boot/dts/st/stih407-family.dtsi
index 3f58383a7b59..29302e74aa1d 100644
--- a/arch/arm/boot/dts/st/stih407-family.dtsi
+++ b/arch/arm/boot/dts/st/stih407-family.dtsi
@@ -111,7 +111,6 @@
regulator-min-microvolt = <784000>;
regulator-max-microvolt = <1299000>;
regulator-always-on;
- max-duty-cycle = <255>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/st/stih418-b2264.dts b/arch/arm/boot/dts/st/stih418-b2264.dts
index fc32a03073b6..fdc16e9f5822 100644
--- a/arch/arm/boot/dts/st/stih418-b2264.dts
+++ b/arch/arm/boot/dts/st/stih418-b2264.dts
@@ -69,19 +69,19 @@
};
aliases {
- ttyAS0 = &sbc_serial0;
+ serial0 = &sbc_serial0;
ethernet0 = &ethernet0;
};
- soc {
- leds {
- compatible = "gpio-leds";
- led-green {
- gpios = <&pio1 3 GPIO_ACTIVE_HIGH>;
- default-state = "off";
- };
+ leds {
+ compatible = "gpio-leds";
+ led-green {
+ gpios = <&pio1 3 GPIO_ACTIVE_LOW>;
+ default-state = "off";
};
+ };
+ soc {
pin-controller-sbc@961f080 {
gmac1 {
rgmii1-0 {
diff --git a/arch/arm/boot/dts/st/stm32746g-eval.dts b/arch/arm/boot/dts/st/stm32746g-eval.dts
index a293e65141c6..e9ac37b6eca0 100644
--- a/arch/arm/boot/dts/st/stm32746g-eval.dts
+++ b/arch/arm/boot/dts/st/stm32746g-eval.dts
@@ -188,9 +188,10 @@
status = "okay";
vmmc-supply = <&mmc_vcard>;
broken-cd;
- pinctrl-names = "default", "opendrain";
+ pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdio_pins_a>;
pinctrl-1 = <&sdio_pins_od_a>;
+ pinctrl-2 = <&sdio_pins_sleep_a>;
bus-width = <4>;
};
diff --git a/arch/arm/boot/dts/st/stm32f7-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32f7-pinctrl.dtsi
index 65480a9f5cc4..97fc3fb5a9ca 100644
--- a/arch/arm/boot/dts/st/stm32f7-pinctrl.dtsi
+++ b/arch/arm/boot/dts/st/stm32f7-pinctrl.dtsi
@@ -263,6 +263,17 @@
};
};
+ sdio_pins_sleep_a: sdio-pins-sleep-a-0 {
+ pins {
+ pinmux = <STM32_PINMUX('C', 8, ANALOG)>, /* SDMMC1 D0 */
+ <STM32_PINMUX('C', 9, ANALOG)>, /* SDMMC1 D1 */
+ <STM32_PINMUX('C', 10, ANALOG)>, /* SDMMC1 D2 */
+ <STM32_PINMUX('C', 11, ANALOG)>, /* SDMMC1 D3 */
+ <STM32_PINMUX('C', 12, ANALOG)>, /* SDMMC1 CLK */
+ <STM32_PINMUX('D', 2, ANALOG)>; /* SDMMC1 CMD */
+ };
+ };
+
sdio_pins_b: sdio-pins-b-0 {
pins {
pinmux = <STM32_PINMUX('G', 9, AF11)>, /* SDMMC2 D0 */
@@ -294,6 +305,17 @@
};
};
+ sdio_pins_sleep_b: sdio-pins-sleep-b-0 {
+ pins {
+ pinmux = <STM32_PINMUX('G', 9, ANALOG)>, /* SDMMC2 D0 */
+ <STM32_PINMUX('G', 10, ANALOG)>, /* SDMMC2 D1 */
+ <STM32_PINMUX('B', 3, ANALOG)>, /* SDMMC2 D2 */
+ <STM32_PINMUX('B', 4, ANALOG)>, /* SDMMC2 D3 */
+ <STM32_PINMUX('D', 6, ANALOG)>, /* SDMMC2 CLK */
+ <STM32_PINMUX('D', 7, ANALOG)>; /* SDMMC2 CMD */
+ };
+ };
+
can1_pins_a: can1-0 {
pins1 {
pinmux = <STM32_PINMUX('A', 12, AF9)>; /* CAN1_TX */
@@ -376,7 +398,6 @@
};
};
-
ltdc_pins_a: ltdc-0 {
pins {
pinmux = <STM32_PINMUX('E', 4, AF14)>, /* LCD_B0 */
diff --git a/arch/arm/boot/dts/st/stm32f746-disco.dts b/arch/arm/boot/dts/st/stm32f746-disco.dts
index 37e3a905fc3c..087de6f09629 100644
--- a/arch/arm/boot/dts/st/stm32f746-disco.dts
+++ b/arch/arm/boot/dts/st/stm32f746-disco.dts
@@ -164,9 +164,10 @@
status = "okay";
vmmc-supply = <&vcc_3v3>;
cd-gpios = <&gpioc 13 GPIO_ACTIVE_LOW>;
- pinctrl-names = "default", "opendrain";
+ pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdio_pins_a>;
pinctrl-1 = <&sdio_pins_od_a>;
+ pinctrl-2 = <&sdio_pins_sleep_a>;
bus-width = <4>;
};
diff --git a/arch/arm/boot/dts/st/stm32f769-disco.dts b/arch/arm/boot/dts/st/stm32f769-disco.dts
index b038d0ed39e8..5d12ae25b327 100644
--- a/arch/arm/boot/dts/st/stm32f769-disco.dts
+++ b/arch/arm/boot/dts/st/stm32f769-disco.dts
@@ -131,9 +131,10 @@
vmmc-supply = <&mmc_vcard>;
cd-gpios = <&gpioi 15 GPIO_ACTIVE_LOW>;
broken-cd;
- pinctrl-names = "default", "opendrain";
+ pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdio_pins_b>;
pinctrl-1 = <&sdio_pins_od_b>;
+ pinctrl-2 = <&sdio_pins_sleep_b>;
bus-width = <4>;
};
diff --git a/arch/arm/boot/dts/st/stm32mp131.dtsi b/arch/arm/boot/dts/st/stm32mp131.dtsi
index ac90fcbf0c09..b04d24c939c3 100644
--- a/arch/arm/boot/dts/st/stm32mp131.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp131.dtsi
@@ -1210,6 +1210,25 @@
};
};
+ hash: hash@54003000 {
+ compatible = "st,stm32mp13-hash";
+ reg = <0x54003000 0x400>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc HASH1>;
+ resets = <&rcc HASH1_R>;
+ dmas = <&mdma 30 0x2 0x1000a02 0x0 0x0>;
+ dma-names = "in";
+ status = "disabled";
+ };
+
+ rng: rng@54004000 {
+ compatible = "st,stm32mp13-rng";
+ reg = <0x54004000 0x400>;
+ clocks = <&rcc RNG1_K>;
+ resets = <&rcc RNG1_R>;
+ status = "disabled";
+ };
+
mdma: dma-controller@58000000 {
compatible = "st,stm32h7-mdma";
reg = <0x58000000 0x1000>;
diff --git a/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi
index 098153ee99a3..ae83e7b10232 100644
--- a/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi
@@ -6,6 +6,7 @@
#include <dt-bindings/pinctrl/stm32-pinfunc.h>
&pinctrl {
+ /omit-if-no-ref/
adc1_ain_pins_a: adc1-ain-0 {
pins {
pinmux = <STM32_PINMUX('F', 11, ANALOG)>, /* ADC1_INP2 */
@@ -17,12 +18,14 @@
};
};
+ /omit-if-no-ref/
adc1_in6_pins_a: adc1-in6-0 {
pins {
pinmux = <STM32_PINMUX('F', 12, ANALOG)>;
};
};
+ /omit-if-no-ref/
adc12_ain_pins_a: adc12-ain-0 {
pins {
pinmux = <STM32_PINMUX('C', 3, ANALOG)>, /* ADC1 in13 */
@@ -32,6 +35,7 @@
};
};
+ /omit-if-no-ref/
adc12_ain_pins_b: adc12-ain-1 {
pins {
pinmux = <STM32_PINMUX('F', 12, ANALOG)>, /* ADC1 in6 */
@@ -39,6 +43,7 @@
};
};
+ /omit-if-no-ref/
adc12_usb_cc_pins_a: adc12-usb-cc-pins-0 {
pins {
pinmux = <STM32_PINMUX('A', 4, ANALOG)>, /* ADC12 in18 */
@@ -46,6 +51,7 @@
};
};
+ /omit-if-no-ref/
cec_pins_a: cec-0 {
pins {
pinmux = <STM32_PINMUX('A', 15, AF4)>;
@@ -55,12 +61,14 @@
};
};
+ /omit-if-no-ref/
cec_sleep_pins_a: cec-sleep-0 {
pins {
pinmux = <STM32_PINMUX('A', 15, ANALOG)>; /* HDMI_CEC */
};
};
+ /omit-if-no-ref/
cec_pins_b: cec-1 {
pins {
pinmux = <STM32_PINMUX('B', 6, AF5)>;
@@ -70,24 +78,28 @@
};
};
+ /omit-if-no-ref/
cec_sleep_pins_b: cec-sleep-1 {
pins {
pinmux = <STM32_PINMUX('B', 6, ANALOG)>; /* HDMI_CEC */
};
};
+ /omit-if-no-ref/
dac_ch1_pins_a: dac-ch1-0 {
pins {
pinmux = <STM32_PINMUX('A', 4, ANALOG)>;
};
};
+ /omit-if-no-ref/
dac_ch2_pins_a: dac-ch2-0 {
pins {
pinmux = <STM32_PINMUX('A', 5, ANALOG)>;
};
};
+ /omit-if-no-ref/
dcmi_pins_a: dcmi-0 {
pins {
pinmux = <STM32_PINMUX('H', 8, AF13)>,/* DCMI_HSYNC */
@@ -109,6 +121,7 @@
};
};
+ /omit-if-no-ref/
dcmi_sleep_pins_a: dcmi-sleep-0 {
pins {
pinmux = <STM32_PINMUX('H', 8, ANALOG)>,/* DCMI_HSYNC */
@@ -129,6 +142,7 @@
};
};
+ /omit-if-no-ref/
dcmi_pins_b: dcmi-1 {
pins {
pinmux = <STM32_PINMUX('A', 4, AF13)>,/* DCMI_HSYNC */
@@ -146,6 +160,7 @@
};
};
+ /omit-if-no-ref/
dcmi_sleep_pins_b: dcmi-sleep-1 {
pins {
pinmux = <STM32_PINMUX('A', 4, ANALOG)>,/* DCMI_HSYNC */
@@ -162,6 +177,7 @@
};
};
+ /omit-if-no-ref/
dcmi_pins_c: dcmi-2 {
pins {
pinmux = <STM32_PINMUX('A', 4, AF13)>,/* DCMI_HSYNC */
@@ -181,6 +197,7 @@
};
};
+ /omit-if-no-ref/
dcmi_sleep_pins_c: dcmi-sleep-2 {
pins {
pinmux = <STM32_PINMUX('A', 4, ANALOG)>,/* DCMI_HSYNC */
@@ -199,6 +216,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rgmii_pins_a: rgmii-0 {
pins1 {
pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
@@ -230,6 +248,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rgmii_sleep_pins_a: rgmii-sleep-0 {
pins1 {
pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */
@@ -250,6 +269,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rgmii_pins_b: rgmii-1 {
pins1 {
pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
@@ -281,6 +301,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rgmii_sleep_pins_b: rgmii-sleep-1 {
pins1 {
pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */
@@ -301,6 +322,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rgmii_pins_c: rgmii-2 {
pins1 {
pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
@@ -332,6 +354,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rgmii_sleep_pins_c: rgmii-sleep-2 {
pins1 {
pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */
@@ -352,6 +375,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rgmii_pins_d: rgmii-3 {
pins1 {
pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
@@ -382,6 +406,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rgmii_sleep_pins_d: rgmii-sleep-3 {
pins1 {
pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */
@@ -402,6 +427,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rgmii_pins_e: rgmii-4 {
pins1 {
pinmux = <STM32_PINMUX('G', 4, AF11)>, /* ETH_RGMII_GTX_CLK */
@@ -425,6 +451,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rgmii_sleep_pins_e: rgmii-sleep-4 {
pins1 {
pinmux = <STM32_PINMUX('G', 4, ANALOG)>, /* ETH_RGMII_GTX_CLK */
@@ -442,6 +469,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rmii_pins_a: rmii-0 {
pins1 {
pinmux = <STM32_PINMUX('G', 13, AF11)>, /* ETH1_RMII_TXD0 */
@@ -462,6 +490,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rmii_sleep_pins_a: rmii-sleep-0 {
pins1 {
pinmux = <STM32_PINMUX('G', 13, ANALOG)>, /* ETH1_RMII_TXD0 */
@@ -476,6 +505,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rmii_pins_b: rmii-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 5, AF0)>, /* ETH1_CLK */
@@ -503,6 +533,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rmii_sleep_pins_b: rmii-sleep-1 {
pins1 {
pinmux = <STM32_PINMUX('A', 2, ANALOG)>, /* ETH1_MDIO */
@@ -517,6 +548,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rmii_pins_c: rmii-2 {
pins1 {
pinmux = <STM32_PINMUX('G', 13, AF11)>, /* ETH1_RMII_TXD0 */
@@ -537,6 +569,7 @@
};
};
+ /omit-if-no-ref/
ethernet0_rmii_sleep_pins_c: rmii-sleep-2 {
pins1 {
pinmux = <STM32_PINMUX('G', 13, ANALOG)>, /* ETH1_RMII_TXD0 */
@@ -551,6 +584,7 @@
};
};
+ /omit-if-no-ref/
fmc_pins_a: fmc-0 {
pins1 {
pinmux = <STM32_PINMUX('D', 4, AF12)>, /* FMC_NOE */
@@ -576,6 +610,7 @@
};
};
+ /omit-if-no-ref/
fmc_sleep_pins_a: fmc-sleep-0 {
pins {
pinmux = <STM32_PINMUX('D', 4, ANALOG)>, /* FMC_NOE */
@@ -595,6 +630,7 @@
};
};
+ /omit-if-no-ref/
fmc_pins_b: fmc-1 {
pins {
pinmux = <STM32_PINMUX('D', 4, AF12)>, /* FMC_NOE */
@@ -624,6 +660,7 @@
};
};
+ /omit-if-no-ref/
fmc_sleep_pins_b: fmc-sleep-1 {
pins {
pinmux = <STM32_PINMUX('D', 4, ANALOG)>, /* FMC_NOE */
@@ -650,6 +687,7 @@
};
};
+ /omit-if-no-ref/
i2c1_pins_a: i2c1-0 {
pins {
pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */
@@ -660,6 +698,7 @@
};
};
+ /omit-if-no-ref/
i2c1_sleep_pins_a: i2c1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('D', 12, ANALOG)>, /* I2C1_SCL */
@@ -667,6 +706,7 @@
};
};
+ /omit-if-no-ref/
i2c1_pins_b: i2c1-1 {
pins {
pinmux = <STM32_PINMUX('F', 14, AF5)>, /* I2C1_SCL */
@@ -677,6 +717,7 @@
};
};
+ /omit-if-no-ref/
i2c1_sleep_pins_b: i2c1-sleep-1 {
pins {
pinmux = <STM32_PINMUX('F', 14, ANALOG)>, /* I2C1_SCL */
@@ -684,6 +725,7 @@
};
};
+ /omit-if-no-ref/
i2c2_pins_a: i2c2-0 {
pins {
pinmux = <STM32_PINMUX('H', 4, AF4)>, /* I2C2_SCL */
@@ -694,6 +736,7 @@
};
};
+ /omit-if-no-ref/
i2c2_sleep_pins_a: i2c2-sleep-0 {
pins {
pinmux = <STM32_PINMUX('H', 4, ANALOG)>, /* I2C2_SCL */
@@ -701,6 +744,7 @@
};
};
+ /omit-if-no-ref/
i2c2_pins_b1: i2c2-1 {
pins {
pinmux = <STM32_PINMUX('H', 5, AF4)>; /* I2C2_SDA */
@@ -710,12 +754,14 @@
};
};
+ /omit-if-no-ref/
i2c2_sleep_pins_b1: i2c2-sleep-1 {
pins {
pinmux = <STM32_PINMUX('H', 5, ANALOG)>; /* I2C2_SDA */
};
};
+ /omit-if-no-ref/
i2c2_pins_c: i2c2-2 {
pins {
pinmux = <STM32_PINMUX('F', 1, AF4)>, /* I2C2_SCL */
@@ -726,6 +772,7 @@
};
};
+ /omit-if-no-ref/
i2c2_pins_sleep_c: i2c2-sleep-2 {
pins {
pinmux = <STM32_PINMUX('F', 1, ANALOG)>, /* I2C2_SCL */
@@ -733,6 +780,7 @@
};
};
+ /omit-if-no-ref/
i2c5_pins_a: i2c5-0 {
pins {
pinmux = <STM32_PINMUX('A', 11, AF4)>, /* I2C5_SCL */
@@ -743,6 +791,7 @@
};
};
+ /omit-if-no-ref/
i2c5_sleep_pins_a: i2c5-sleep-0 {
pins {
pinmux = <STM32_PINMUX('A', 11, ANALOG)>, /* I2C5_SCL */
@@ -751,6 +800,7 @@
};
};
+ /omit-if-no-ref/
i2c5_pins_b: i2c5-1 {
pins {
pinmux = <STM32_PINMUX('D', 0, AF4)>, /* I2C5_SCL */
@@ -761,6 +811,7 @@
};
};
+ /omit-if-no-ref/
i2c5_sleep_pins_b: i2c5-sleep-1 {
pins {
pinmux = <STM32_PINMUX('D', 0, ANALOG)>, /* I2C5_SCL */
@@ -768,6 +819,7 @@
};
};
+ /omit-if-no-ref/
i2s2_pins_a: i2s2-0 {
pins {
pinmux = <STM32_PINMUX('I', 3, AF5)>, /* I2S2_SDO */
@@ -779,6 +831,7 @@
};
};
+ /omit-if-no-ref/
i2s2_sleep_pins_a: i2s2-sleep-0 {
pins {
pinmux = <STM32_PINMUX('I', 3, ANALOG)>, /* I2S2_SDO */
@@ -787,6 +840,28 @@
};
};
+ /omit-if-no-ref/
+ i2s2_pins_b: i2s2-1 {
+ pins {
+ pinmux = <STM32_PINMUX('C', 3, AF5)>, /* I2S2_SDO */
+ <STM32_PINMUX('B', 12, AF5)>, /* I2S2_WS */
+ <STM32_PINMUX('B', 13, AF5)>; /* I2S2_CK */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <1>;
+ };
+ };
+
+ /omit-if-no-ref/
+ i2s2_sleep_pins_b: i2s2-sleep-1 {
+ pins {
+ pinmux = <STM32_PINMUX('C', 3, ANALOG)>, /* I2S2_SDO */
+ <STM32_PINMUX('B', 12, ANALOG)>, /* I2S2_WS */
+ <STM32_PINMUX('B', 13, ANALOG)>; /* I2S2_CK */
+ };
+ };
+
+ /omit-if-no-ref/
ltdc_pins_a: ltdc-0 {
pins {
pinmux = <STM32_PINMUX('G', 7, AF14)>, /* LCD_CLK */
@@ -823,6 +898,7 @@
};
};
+ /omit-if-no-ref/
ltdc_sleep_pins_a: ltdc-sleep-0 {
pins {
pinmux = <STM32_PINMUX('G', 7, ANALOG)>, /* LCD_CLK */
@@ -856,6 +932,7 @@
};
};
+ /omit-if-no-ref/
ltdc_pins_b: ltdc-1 {
pins {
pinmux = <STM32_PINMUX('I', 14, AF14)>, /* LCD_CLK */
@@ -892,6 +969,7 @@
};
};
+ /omit-if-no-ref/
ltdc_sleep_pins_b: ltdc-sleep-1 {
pins {
pinmux = <STM32_PINMUX('I', 14, ANALOG)>, /* LCD_CLK */
@@ -925,6 +1003,7 @@
};
};
+ /omit-if-no-ref/
ltdc_pins_c: ltdc-2 {
pins1 {
pinmux = <STM32_PINMUX('B', 1, AF9)>, /* LTDC_R6 */
@@ -960,6 +1039,7 @@
};
};
+ /omit-if-no-ref/
ltdc_sleep_pins_c: ltdc-sleep-2 {
pins1 {
pinmux = <STM32_PINMUX('B', 1, ANALOG)>, /* LTDC_R6 */
@@ -987,6 +1067,7 @@
};
};
+ /omit-if-no-ref/
ltdc_pins_d: ltdc-3 {
pins1 {
pinmux = <STM32_PINMUX('G', 7, AF14)>; /* LCD_CLK */
@@ -1028,6 +1109,7 @@
};
};
+ /omit-if-no-ref/
ltdc_sleep_pins_d: ltdc-sleep-3 {
pins {
pinmux = <STM32_PINMUX('G', 7, ANALOG)>, /* LCD_CLK */
@@ -1061,6 +1143,84 @@
};
};
+ /omit-if-no-ref/
+ ltdc_pins_e: ltdc-4 {
+ pins1 {
+ pinmux = <STM32_PINMUX('H', 2, AF14)>, /* LTDC_R0 */
+ <STM32_PINMUX('H', 3, AF14)>, /* LTDC_R1 */
+ <STM32_PINMUX('H', 8, AF14)>, /* LTDC_R2 */
+ <STM32_PINMUX('H', 9, AF14)>, /* LTDC_R3 */
+ <STM32_PINMUX('H', 10, AF14)>, /* LTDC_R4 */
+ <STM32_PINMUX('C', 0, AF14)>, /* LTDC_R5 */
+ <STM32_PINMUX('H', 12, AF14)>, /* LTDC_R6 */
+ <STM32_PINMUX('E', 15, AF14)>, /* LTDC_R7 */
+ <STM32_PINMUX('E', 14, AF13)>, /* LTDC_G0 */
+ <STM32_PINMUX('E', 6, AF14)>, /* LTDC_G1 */
+ <STM32_PINMUX('H', 13, AF14)>, /* LTDC_G2 */
+ <STM32_PINMUX('H', 14, AF14)>, /* LTDC_G3 */
+ <STM32_PINMUX('H', 4, AF14)>, /* LTDC_G4 */
+ <STM32_PINMUX('I', 0, AF14)>, /* LTDC_G5 */
+ <STM32_PINMUX('I', 1, AF14)>, /* LTDC_G6 */
+ <STM32_PINMUX('I', 2, AF14)>, /* LTDC_G7 */
+ <STM32_PINMUX('D', 9, AF14)>, /* LTDC_B0 */
+ <STM32_PINMUX('G', 12, AF14)>, /* LTDC_B1 */
+ <STM32_PINMUX('G', 10, AF14)>, /* LTDC_B2 */
+ <STM32_PINMUX('D', 10, AF14)>, /* LTDC_B3 */
+ <STM32_PINMUX('E', 12, AF14)>, /* LTDC_B4 */
+ <STM32_PINMUX('A', 3, AF14)>, /* LTDC_B5 */
+ <STM32_PINMUX('B', 8, AF14)>, /* LTDC_B6 */
+ <STM32_PINMUX('D', 8, AF14)>, /* LTDC_B7 */
+ <STM32_PINMUX('F', 10, AF14)>, /* LTDC_DE */
+ <STM32_PINMUX('I', 9, AF14)>, /* LTDC_VSYNC */
+ <STM32_PINMUX('I', 10, AF14)>; /* LTDC_HSYNC */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+
+ pins2 {
+ pinmux = <STM32_PINMUX('G', 7, AF14)>; /* LTDC_CLK */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <1>;
+ };
+ };
+
+ /omit-if-no-ref/
+ ltdc_sleep_pins_e: ltdc-sleep-4 {
+ pins {
+ pinmux = <STM32_PINMUX('H', 2, ANALOG)>, /* LTDC_R0 */
+ <STM32_PINMUX('H', 3, ANALOG)>, /* LTDC_R1 */
+ <STM32_PINMUX('H', 8, ANALOG)>, /* LTDC_R2 */
+ <STM32_PINMUX('H', 9, ANALOG)>, /* LTDC_R3 */
+ <STM32_PINMUX('H', 10, ANALOG)>, /* LTDC_R4 */
+ <STM32_PINMUX('C', 0, ANALOG)>, /* LTDC_R5 */
+ <STM32_PINMUX('H', 12, ANALOG)>, /* LTDC_R6 */
+ <STM32_PINMUX('E', 15, ANALOG)>, /* LTDC_R7 */
+ <STM32_PINMUX('D', 9, ANALOG)>, /* LTDC_B0 */
+ <STM32_PINMUX('G', 12, ANALOG)>, /* LTDC_B1 */
+ <STM32_PINMUX('G', 10, ANALOG)>, /* LTDC_B2 */
+ <STM32_PINMUX('D', 10, ANALOG)>, /* LTDC_B3 */
+ <STM32_PINMUX('E', 12, ANALOG)>, /* LTDC_B4 */
+ <STM32_PINMUX('A', 3, ANALOG)>, /* LTDC_B5 */
+ <STM32_PINMUX('B', 8, ANALOG)>, /* LTDC_B6 */
+ <STM32_PINMUX('D', 8, ANALOG)>, /* LTDC_B7 */
+ <STM32_PINMUX('E', 14, ANALOG)>, /* LTDC_G0 */
+ <STM32_PINMUX('E', 6, ANALOG)>, /* LTDC_G1 */
+ <STM32_PINMUX('H', 13, ANALOG)>, /* LTDC_G2 */
+ <STM32_PINMUX('H', 14, ANALOG)>, /* LTDC_G3 */
+ <STM32_PINMUX('H', 4, ANALOG)>, /* LTDC_G4 */
+ <STM32_PINMUX('I', 0, ANALOG)>, /* LTDC_G5 */
+ <STM32_PINMUX('I', 1, ANALOG)>, /* LTDC_G6 */
+ <STM32_PINMUX('I', 2, ANALOG)>, /* LTDC_G7 */
+ <STM32_PINMUX('F', 10, ANALOG)>, /* LTDC_DE */
+ <STM32_PINMUX('I', 9, ANALOG)>, /* LTDC_VSYNC */
+ <STM32_PINMUX('I', 10, ANALOG)>, /* LTDC_HSYNC */
+ <STM32_PINMUX('G', 7, ANALOG)>; /* LTDC_CLK */
+ };
+ };
+
+ /omit-if-no-ref/
mco1_pins_a: mco1-0 {
pins {
pinmux = <STM32_PINMUX('A', 13, AF2)>; /* MCO1 */
@@ -1070,12 +1230,14 @@
};
};
+ /omit-if-no-ref/
mco1_sleep_pins_a: mco1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('A', 13, ANALOG)>; /* MCO1 */
};
};
+ /omit-if-no-ref/
mco2_pins_a: mco2-0 {
pins {
pinmux = <STM32_PINMUX('G', 2, AF1)>; /* MCO2 */
@@ -1085,12 +1247,14 @@
};
};
+ /omit-if-no-ref/
mco2_sleep_pins_a: mco2-sleep-0 {
pins {
pinmux = <STM32_PINMUX('G', 2, ANALOG)>; /* MCO2 */
};
};
+ /omit-if-no-ref/
m_can1_pins_a: m-can1-0 {
pins1 {
pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
@@ -1104,6 +1268,7 @@
};
};
+ /omit-if-no-ref/
m_can1_sleep_pins_a: m_can1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('H', 13, ANALOG)>, /* CAN1_TX */
@@ -1111,6 +1276,7 @@
};
};
+ /omit-if-no-ref/
m_can1_pins_b: m-can1-1 {
pins1 {
pinmux = <STM32_PINMUX('A', 12, AF9)>; /* CAN1_TX */
@@ -1124,6 +1290,7 @@
};
};
+ /omit-if-no-ref/
m_can1_sleep_pins_b: m_can1-sleep-1 {
pins {
pinmux = <STM32_PINMUX('A', 12, ANALOG)>, /* CAN1_TX */
@@ -1131,6 +1298,7 @@
};
};
+ /omit-if-no-ref/
m_can1_pins_c: m-can1-2 {
pins1 {
pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
@@ -1144,6 +1312,7 @@
};
};
+ /omit-if-no-ref/
m_can1_sleep_pins_c: m_can1-sleep-2 {
pins {
pinmux = <STM32_PINMUX('H', 13, ANALOG)>, /* CAN1_TX */
@@ -1151,6 +1320,29 @@
};
};
+ /omit-if-no-ref/
+ m_can1_pins_d: m-can1-3 {
+ pins1 {
+ pinmux = <STM32_PINMUX('D', 1, AF9)>; /* CAN1_TX */
+ slew-rate = <1>;
+ drive-push-pull;
+ bias-disable;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('D', 0, AF9)>; /* CAN1_RX */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ m_can1_sleep_pins_d: m_can1-sleep-3 {
+ pins {
+ pinmux = <STM32_PINMUX('D', 1, ANALOG)>, /* CAN1_TX */
+ <STM32_PINMUX('D', 0, ANALOG)>; /* CAN1_RX */
+ };
+ };
+
+ /omit-if-no-ref/
m_can2_pins_a: m-can2-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 13, AF9)>; /* CAN2_TX */
@@ -1164,6 +1356,7 @@
};
};
+ /omit-if-no-ref/
m_can2_sleep_pins_a: m_can2-sleep-0 {
pins {
pinmux = <STM32_PINMUX('B', 13, ANALOG)>, /* CAN2_TX */
@@ -1171,6 +1364,7 @@
};
};
+ /omit-if-no-ref/
pwm1_pins_a: pwm1-0 {
pins {
pinmux = <STM32_PINMUX('E', 9, AF1)>, /* TIM1_CH1 */
@@ -1182,6 +1376,7 @@
};
};
+ /omit-if-no-ref/
pwm1_sleep_pins_a: pwm1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('E', 9, ANALOG)>, /* TIM1_CH1 */
@@ -1190,6 +1385,7 @@
};
};
+ /omit-if-no-ref/
pwm1_pins_b: pwm1-1 {
pins {
pinmux = <STM32_PINMUX('E', 9, AF1)>; /* TIM1_CH1 */
@@ -1199,12 +1395,14 @@
};
};
+ /omit-if-no-ref/
pwm1_sleep_pins_b: pwm1-sleep-1 {
pins {
pinmux = <STM32_PINMUX('E', 9, ANALOG)>; /* TIM1_CH1 */
};
};
+ /omit-if-no-ref/
pwm1_pins_c: pwm1-2 {
pins {
pinmux = <STM32_PINMUX('E', 11, AF1)>; /* TIM1_CH2 */
@@ -1213,12 +1411,14 @@
};
};
+ /omit-if-no-ref/
pwm1_sleep_pins_c: pwm1-sleep-2 {
pins {
pinmux = <STM32_PINMUX('E', 11, ANALOG)>; /* TIM1_CH2 */
};
};
+ /omit-if-no-ref/
pwm2_pins_a: pwm2-0 {
pins {
pinmux = <STM32_PINMUX('A', 3, AF1)>; /* TIM2_CH4 */
@@ -1228,12 +1428,14 @@
};
};
+ /omit-if-no-ref/
pwm2_sleep_pins_a: pwm2-sleep-0 {
pins {
pinmux = <STM32_PINMUX('A', 3, ANALOG)>; /* TIM2_CH4 */
};
};
+ /omit-if-no-ref/
pwm3_pins_a: pwm3-0 {
pins {
pinmux = <STM32_PINMUX('C', 7, AF2)>; /* TIM3_CH2 */
@@ -1243,12 +1445,14 @@
};
};
+ /omit-if-no-ref/
pwm3_sleep_pins_a: pwm3-sleep-0 {
pins {
pinmux = <STM32_PINMUX('C', 7, ANALOG)>; /* TIM3_CH2 */
};
};
+ /omit-if-no-ref/
pwm3_pins_b: pwm3-1 {
pins {
pinmux = <STM32_PINMUX('B', 5, AF2)>; /* TIM3_CH2 */
@@ -1258,12 +1462,14 @@
};
};
+ /omit-if-no-ref/
pwm3_sleep_pins_b: pwm3-sleep-1 {
pins {
pinmux = <STM32_PINMUX('B', 5, ANALOG)>; /* TIM3_CH2 */
};
};
+ /omit-if-no-ref/
pwm4_pins_a: pwm4-0 {
pins {
pinmux = <STM32_PINMUX('D', 14, AF2)>, /* TIM4_CH3 */
@@ -1274,6 +1480,7 @@
};
};
+ /omit-if-no-ref/
pwm4_sleep_pins_a: pwm4-sleep-0 {
pins {
pinmux = <STM32_PINMUX('D', 14, ANALOG)>, /* TIM4_CH3 */
@@ -1281,6 +1488,7 @@
};
};
+ /omit-if-no-ref/
pwm4_pins_b: pwm4-1 {
pins {
pinmux = <STM32_PINMUX('D', 13, AF2)>; /* TIM4_CH2 */
@@ -1290,12 +1498,14 @@
};
};
+ /omit-if-no-ref/
pwm4_sleep_pins_b: pwm4-sleep-1 {
pins {
pinmux = <STM32_PINMUX('D', 13, ANALOG)>; /* TIM4_CH2 */
};
};
+ /omit-if-no-ref/
pwm5_pins_a: pwm5-0 {
pins {
pinmux = <STM32_PINMUX('H', 11, AF2)>; /* TIM5_CH2 */
@@ -1305,12 +1515,14 @@
};
};
+ /omit-if-no-ref/
pwm5_sleep_pins_a: pwm5-sleep-0 {
pins {
pinmux = <STM32_PINMUX('H', 11, ANALOG)>; /* TIM5_CH2 */
};
};
+ /omit-if-no-ref/
pwm5_pins_b: pwm5-1 {
pins {
pinmux = <STM32_PINMUX('H', 11, AF2)>, /* TIM5_CH2 */
@@ -1322,6 +1534,7 @@
};
};
+ /omit-if-no-ref/
pwm5_sleep_pins_b: pwm5-sleep-1 {
pins {
pinmux = <STM32_PINMUX('H', 11, ANALOG)>, /* TIM5_CH2 */
@@ -1330,6 +1543,7 @@
};
};
+ /omit-if-no-ref/
pwm8_pins_a: pwm8-0 {
pins {
pinmux = <STM32_PINMUX('I', 2, AF3)>; /* TIM8_CH4 */
@@ -1339,12 +1553,14 @@
};
};
+ /omit-if-no-ref/
pwm8_sleep_pins_a: pwm8-sleep-0 {
pins {
pinmux = <STM32_PINMUX('I', 2, ANALOG)>; /* TIM8_CH4 */
};
};
+ /omit-if-no-ref/
pwm8_pins_b: pwm8-1 {
pins {
pinmux = <STM32_PINMUX('I', 5, AF3)>, /* TIM8_CH1 */
@@ -1356,6 +1572,7 @@
};
};
+ /omit-if-no-ref/
pwm8_sleep_pins_b: pwm8-sleep-1 {
pins {
pinmux = <STM32_PINMUX('I', 5, ANALOG)>, /* TIM8_CH1 */
@@ -1365,6 +1582,7 @@
};
};
+ /omit-if-no-ref/
pwm12_pins_a: pwm12-0 {
pins {
pinmux = <STM32_PINMUX('H', 6, AF2)>; /* TIM12_CH1 */
@@ -1374,12 +1592,14 @@
};
};
+ /omit-if-no-ref/
pwm12_sleep_pins_a: pwm12-sleep-0 {
pins {
pinmux = <STM32_PINMUX('H', 6, ANALOG)>; /* TIM12_CH1 */
};
};
+ /omit-if-no-ref/
qspi_clk_pins_a: qspi-clk-0 {
pins {
pinmux = <STM32_PINMUX('F', 10, AF9)>; /* QSPI_CLK */
@@ -1389,12 +1609,14 @@
};
};
+ /omit-if-no-ref/
qspi_clk_sleep_pins_a: qspi-clk-sleep-0 {
pins {
pinmux = <STM32_PINMUX('F', 10, ANALOG)>; /* QSPI_CLK */
};
};
+ /omit-if-no-ref/
qspi_bk1_pins_a: qspi-bk1-0 {
pins {
pinmux = <STM32_PINMUX('F', 8, AF10)>, /* QSPI_BK1_IO0 */
@@ -1407,6 +1629,7 @@
};
};
+ /omit-if-no-ref/
qspi_bk1_sleep_pins_a: qspi-bk1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('F', 8, ANALOG)>, /* QSPI_BK1_IO0 */
@@ -1416,6 +1639,7 @@
};
};
+ /omit-if-no-ref/
qspi_bk2_pins_a: qspi-bk2-0 {
pins {
pinmux = <STM32_PINMUX('H', 2, AF9)>, /* QSPI_BK2_IO0 */
@@ -1428,6 +1652,7 @@
};
};
+ /omit-if-no-ref/
qspi_bk2_sleep_pins_a: qspi-bk2-sleep-0 {
pins {
pinmux = <STM32_PINMUX('H', 2, ANALOG)>, /* QSPI_BK2_IO0 */
@@ -1437,6 +1662,7 @@
};
};
+ /omit-if-no-ref/
qspi_cs1_pins_a: qspi-cs1-0 {
pins {
pinmux = <STM32_PINMUX('B', 6, AF10)>; /* QSPI_BK1_NCS */
@@ -1446,12 +1672,14 @@
};
};
+ /omit-if-no-ref/
qspi_cs1_sleep_pins_a: qspi-cs1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('B', 6, ANALOG)>; /* QSPI_BK1_NCS */
};
};
+ /omit-if-no-ref/
qspi_cs2_pins_a: qspi-cs2-0 {
pins {
pinmux = <STM32_PINMUX('C', 0, AF10)>; /* QSPI_BK2_NCS */
@@ -1461,12 +1689,14 @@
};
};
+ /omit-if-no-ref/
qspi_cs2_sleep_pins_a: qspi-cs2-sleep-0 {
pins {
pinmux = <STM32_PINMUX('C', 0, ANALOG)>; /* QSPI_BK2_NCS */
};
};
+ /omit-if-no-ref/
sai2a_pins_a: sai2a-0 {
pins {
pinmux = <STM32_PINMUX('I', 5, AF10)>, /* SAI2_SCK_A */
@@ -1479,6 +1709,7 @@
};
};
+ /omit-if-no-ref/
sai2a_sleep_pins_a: sai2a-sleep-0 {
pins {
pinmux = <STM32_PINMUX('I', 5, ANALOG)>, /* SAI2_SCK_A */
@@ -1488,6 +1719,7 @@
};
};
+ /omit-if-no-ref/
sai2a_pins_b: sai2a-1 {
pins1 {
pinmux = <STM32_PINMUX('I', 6, AF10)>, /* SAI2_SD_A */
@@ -1499,6 +1731,7 @@
};
};
+ /omit-if-no-ref/
sai2a_sleep_pins_b: sai2a-sleep-1 {
pins {
pinmux = <STM32_PINMUX('I', 6, ANALOG)>, /* SAI2_SD_A */
@@ -1507,6 +1740,7 @@
};
};
+ /omit-if-no-ref/
sai2a_pins_c: sai2a-2 {
pins {
pinmux = <STM32_PINMUX('D', 13, AF10)>, /* SAI2_SCK_A */
@@ -1518,6 +1752,7 @@
};
};
+ /omit-if-no-ref/
sai2a_sleep_pins_c: sai2a-sleep-2 {
pins {
pinmux = <STM32_PINMUX('D', 13, ANALOG)>, /* SAI2_SCK_A */
@@ -1526,6 +1761,7 @@
};
};
+ /omit-if-no-ref/
sai2b_pins_a: sai2b-0 {
pins1 {
pinmux = <STM32_PINMUX('E', 12, AF10)>, /* SAI2_SCK_B */
@@ -1541,6 +1777,7 @@
};
};
+ /omit-if-no-ref/
sai2b_sleep_pins_a: sai2b-sleep-0 {
pins {
pinmux = <STM32_PINMUX('F', 11, ANALOG)>, /* SAI2_SD_B */
@@ -1550,6 +1787,7 @@
};
};
+ /omit-if-no-ref/
sai2b_pins_b: sai2b-1 {
pins {
pinmux = <STM32_PINMUX('F', 11, AF10)>; /* SAI2_SD_B */
@@ -1557,12 +1795,14 @@
};
};
+ /omit-if-no-ref/
sai2b_sleep_pins_b: sai2b-sleep-1 {
pins {
pinmux = <STM32_PINMUX('F', 11, ANALOG)>; /* SAI2_SD_B */
};
};
+ /omit-if-no-ref/
sai2b_pins_c: sai2b-2 {
pins1 {
pinmux = <STM32_PINMUX('F', 11, AF10)>; /* SAI2_SD_B */
@@ -1570,12 +1810,14 @@
};
};
+ /omit-if-no-ref/
sai2b_sleep_pins_c: sai2b-sleep-2 {
pins {
pinmux = <STM32_PINMUX('F', 11, ANALOG)>; /* SAI2_SD_B */
};
};
+ /omit-if-no-ref/
sai2b_pins_d: sai2b-3 {
pins1 {
pinmux = <STM32_PINMUX('H', 2, AF10)>, /* SAI2_SCK_B */
@@ -1591,6 +1833,7 @@
};
};
+ /omit-if-no-ref/
sai2b_sleep_pins_d: sai2b-sleep-3 {
pins1 {
pinmux = <STM32_PINMUX('H', 2, ANALOG)>, /* SAI2_SCK_B */
@@ -1600,6 +1843,7 @@
};
};
+ /omit-if-no-ref/
sai4a_pins_a: sai4a-0 {
pins {
pinmux = <STM32_PINMUX('B', 5, AF10)>; /* SAI4_SD_A */
@@ -1609,12 +1853,14 @@
};
};
+ /omit-if-no-ref/
sai4a_sleep_pins_a: sai4a-sleep-0 {
pins {
pinmux = <STM32_PINMUX('B', 5, ANALOG)>; /* SAI4_SD_A */
};
};
+ /omit-if-no-ref/
sdmmc1_b4_pins_a: sdmmc1-b4-0 {
pins1 {
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
@@ -1634,6 +1880,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {
pins1 {
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
@@ -1658,6 +1905,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_b4_init_pins_a: sdmmc1-b4-init-0 {
pins1 {
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
@@ -1670,6 +1918,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 {
pins {
pinmux = <STM32_PINMUX('C', 8, ANALOG)>, /* SDMMC1_D0 */
@@ -1681,6 +1930,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_b4_pins_b: sdmmc1-b4-1 {
pins1 {
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
@@ -1700,6 +1950,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_b4_od_pins_b: sdmmc1-b4-od-1 {
pins1 {
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
@@ -1724,6 +1975,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_b4_sleep_pins_b: sdmmc1-b4-sleep-1 {
pins {
pinmux = <STM32_PINMUX('C', 8, ANALOG)>, /* SDMMC1_D0 */
@@ -1735,6 +1987,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_dir_pins_a: sdmmc1-dir-0 {
pins1 {
pinmux = <STM32_PINMUX('F', 2, AF11)>, /* SDMMC1_D0DIR */
@@ -1750,6 +2003,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_dir_init_pins_a: sdmmc1-dir-init-0 {
pins1 {
pinmux = <STM32_PINMUX('F', 2, AF11)>, /* SDMMC1_D0DIR */
@@ -1761,6 +2015,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_dir_sleep_pins_a: sdmmc1-dir-sleep-0 {
pins {
pinmux = <STM32_PINMUX('F', 2, ANALOG)>, /* SDMMC1_D0DIR */
@@ -1770,6 +2025,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_dir_pins_b: sdmmc1-dir-1 {
pins1 {
pinmux = <STM32_PINMUX('F', 2, AF11)>, /* SDMMC1_D0DIR */
@@ -1785,6 +2041,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_dir_sleep_pins_b: sdmmc1-dir-sleep-1 {
pins {
pinmux = <STM32_PINMUX('F', 2, ANALOG)>, /* SDMMC1_D0DIR */
@@ -1794,6 +2051,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_b4_pins_a: sdmmc2-b4-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
@@ -1813,6 +2071,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_b4_od_pins_a: sdmmc2-b4-od-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
@@ -1837,6 +2096,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_b4_sleep_pins_a: sdmmc2-b4-sleep-0 {
pins {
pinmux = <STM32_PINMUX('B', 14, ANALOG)>, /* SDMMC2_D0 */
@@ -1848,6 +2108,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_b4_pins_b: sdmmc2-b4-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
@@ -1867,6 +2128,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_b4_od_pins_b: sdmmc2-b4-od-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
@@ -1891,6 +2153,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_d47_pins_a: sdmmc2-d47-0 {
pins {
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
@@ -1903,6 +2166,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_d47_sleep_pins_a: sdmmc2-d47-sleep-0 {
pins {
pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */
@@ -1912,6 +2176,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_d47_pins_b: sdmmc2-d47-1 {
pins {
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
@@ -1924,6 +2189,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_d47_sleep_pins_b: sdmmc2-d47-sleep-1 {
pins {
pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */
@@ -1933,6 +2199,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_d47_pins_c: sdmmc2-d47-2 {
pins {
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
@@ -1945,6 +2212,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_d47_sleep_pins_c: sdmmc2-d47-sleep-2 {
pins {
pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */
@@ -1954,6 +2222,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_d47_pins_d: sdmmc2-d47-3 {
pins {
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
@@ -1963,6 +2232,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_d47_sleep_pins_d: sdmmc2-d47-sleep-3 {
pins {
pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */
@@ -1972,6 +2242,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_d47_pins_e: sdmmc2-d47-4 {
pins {
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
@@ -1984,6 +2255,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_d47_sleep_pins_e: sdmmc2-d47-sleep-4 {
pins {
pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */
@@ -1993,6 +2265,7 @@
};
};
+ /omit-if-no-ref/
sdmmc3_b4_pins_a: sdmmc3-b4-0 {
pins1 {
pinmux = <STM32_PINMUX('F', 0, AF9)>, /* SDMMC3_D0 */
@@ -2012,6 +2285,7 @@
};
};
+ /omit-if-no-ref/
sdmmc3_b4_od_pins_a: sdmmc3-b4-od-0 {
pins1 {
pinmux = <STM32_PINMUX('F', 0, AF9)>, /* SDMMC3_D0 */
@@ -2036,6 +2310,7 @@
};
};
+ /omit-if-no-ref/
sdmmc3_b4_sleep_pins_a: sdmmc3-b4-sleep-0 {
pins {
pinmux = <STM32_PINMUX('F', 0, ANALOG)>, /* SDMMC3_D0 */
@@ -2047,6 +2322,7 @@
};
};
+ /omit-if-no-ref/
sdmmc3_b4_pins_b: sdmmc3-b4-1 {
pins1 {
pinmux = <STM32_PINMUX('F', 0, AF9)>, /* SDMMC3_D0 */
@@ -2066,6 +2342,7 @@
};
};
+ /omit-if-no-ref/
sdmmc3_b4_od_pins_b: sdmmc3-b4-od-1 {
pins1 {
pinmux = <STM32_PINMUX('F', 0, AF9)>, /* SDMMC3_D0 */
@@ -2090,6 +2367,7 @@
};
};
+ /omit-if-no-ref/
sdmmc3_b4_sleep_pins_b: sdmmc3-b4-sleep-1 {
pins {
pinmux = <STM32_PINMUX('F', 0, ANALOG)>, /* SDMMC3_D0 */
@@ -2101,6 +2379,7 @@
};
};
+ /omit-if-no-ref/
spdifrx_pins_a: spdifrx-0 {
pins {
pinmux = <STM32_PINMUX('G', 12, AF8)>; /* SPDIF_IN1 */
@@ -2108,12 +2387,14 @@
};
};
+ /omit-if-no-ref/
spdifrx_sleep_pins_a: spdifrx-sleep-0 {
pins {
pinmux = <STM32_PINMUX('G', 12, ANALOG)>; /* SPDIF_IN1 */
};
};
+ /omit-if-no-ref/
spi1_pins_b: spi1-1 {
pins1 {
pinmux = <STM32_PINMUX('A', 5, AF5)>, /* SPI1_SCK */
@@ -2129,6 +2410,7 @@
};
};
+ /omit-if-no-ref/
spi2_pins_a: spi2-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, AF5)>, /* SPI2_SCK */
@@ -2144,6 +2426,7 @@
};
};
+ /omit-if-no-ref/
spi2_pins_b: spi2-1 {
pins1 {
pinmux = <STM32_PINMUX('I', 1, AF5)>, /* SPI2_SCK */
@@ -2159,6 +2442,7 @@
};
};
+ /omit-if-no-ref/
spi2_pins_c: spi2-2 {
pins1 {
pinmux = <STM32_PINMUX('I', 1, AF5)>, /* SPI2_SCK */
@@ -2173,6 +2457,7 @@
};
};
+ /omit-if-no-ref/
spi4_pins_a: spi4-0 {
pins {
pinmux = <STM32_PINMUX('E', 12, AF5)>, /* SPI4_SCK */
@@ -2187,6 +2472,7 @@
};
};
+ /omit-if-no-ref/
spi5_pins_a: spi5-0 {
pins1 {
pinmux = <STM32_PINMUX('F', 7, AF5)>, /* SPI5_SCK */
@@ -2202,6 +2488,7 @@
};
};
+ /omit-if-no-ref/
stusb1600_pins_a: stusb1600-0 {
pins {
pinmux = <STM32_PINMUX('I', 11, GPIO)>;
@@ -2209,6 +2496,7 @@
};
};
+ /omit-if-no-ref/
uart4_pins_a: uart4-0 {
pins1 {
pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
@@ -2222,6 +2510,7 @@
};
};
+ /omit-if-no-ref/
uart4_idle_pins_a: uart4-idle-0 {
pins1 {
pinmux = <STM32_PINMUX('G', 11, ANALOG)>; /* UART4_TX */
@@ -2232,6 +2521,7 @@
};
};
+ /omit-if-no-ref/
uart4_sleep_pins_a: uart4-sleep-0 {
pins {
pinmux = <STM32_PINMUX('G', 11, ANALOG)>, /* UART4_TX */
@@ -2239,6 +2529,7 @@
};
};
+ /omit-if-no-ref/
uart4_pins_b: uart4-1 {
pins1 {
pinmux = <STM32_PINMUX('D', 1, AF8)>; /* UART4_TX */
@@ -2252,6 +2543,7 @@
};
};
+ /omit-if-no-ref/
uart4_pins_c: uart4-2 {
pins1 {
pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
@@ -2265,6 +2557,7 @@
};
};
+ /omit-if-no-ref/
uart4_pins_d: uart4-3 {
pins1 {
pinmux = <STM32_PINMUX('A', 13, AF8)>; /* UART4_TX */
@@ -2278,6 +2571,7 @@
};
};
+ /omit-if-no-ref/
uart4_idle_pins_d: uart4-idle-3 {
pins1 {
pinmux = <STM32_PINMUX('A', 13, ANALOG)>; /* UART4_TX */
@@ -2288,6 +2582,7 @@
};
};
+ /omit-if-no-ref/
uart4_sleep_pins_d: uart4-sleep-3 {
pins {
pinmux = <STM32_PINMUX('A', 13, ANALOG)>, /* UART4_TX */
@@ -2295,6 +2590,7 @@
};
};
+ /omit-if-no-ref/
uart5_pins_a: uart5-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 13, AF14)>; /* UART5_TX */
@@ -2308,6 +2604,7 @@
};
};
+ /omit-if-no-ref/
uart7_pins_a: uart7-0 {
pins1 {
pinmux = <STM32_PINMUX('E', 8, AF7)>; /* UART7_TX */
@@ -2323,6 +2620,7 @@
};
};
+ /omit-if-no-ref/
uart7_pins_b: uart7-1 {
pins1 {
pinmux = <STM32_PINMUX('F', 7, AF7)>; /* UART7_TX */
@@ -2336,6 +2634,7 @@
};
};
+ /omit-if-no-ref/
uart7_pins_c: uart7-2 {
pins1 {
pinmux = <STM32_PINMUX('E', 8, AF7)>; /* UART7_TX */
@@ -2349,6 +2648,7 @@
};
};
+ /omit-if-no-ref/
uart7_idle_pins_c: uart7-idle-2 {
pins1 {
pinmux = <STM32_PINMUX('E', 8, ANALOG)>; /* UART7_TX */
@@ -2359,6 +2659,7 @@
};
};
+ /omit-if-no-ref/
uart7_sleep_pins_c: uart7-sleep-2 {
pins {
pinmux = <STM32_PINMUX('E', 8, ANALOG)>, /* UART7_TX */
@@ -2366,6 +2667,7 @@
};
};
+ /omit-if-no-ref/
uart8_pins_a: uart8-0 {
pins1 {
pinmux = <STM32_PINMUX('E', 1, AF8)>; /* UART8_TX */
@@ -2379,6 +2681,7 @@
};
};
+ /omit-if-no-ref/
uart8_rtscts_pins_a: uart8rtscts-0 {
pins {
pinmux = <STM32_PINMUX('G', 7, AF8)>, /* UART8_RTS */
@@ -2387,6 +2690,7 @@
};
};
+ /omit-if-no-ref/
usart1_pins_a: usart1-0 {
pins1 {
pinmux = <STM32_PINMUX('A', 12, AF7)>; /* USART1_RTS */
@@ -2400,6 +2704,7 @@
};
};
+ /omit-if-no-ref/
usart1_idle_pins_a: usart1-idle-0 {
pins1 {
pinmux = <STM32_PINMUX('A', 12, ANALOG)>, /* USART1_RTS */
@@ -2407,6 +2712,7 @@
};
};
+ /omit-if-no-ref/
usart1_sleep_pins_a: usart1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('A', 12, ANALOG)>, /* USART1_RTS */
@@ -2414,6 +2720,7 @@
};
};
+ /omit-if-no-ref/
usart2_pins_a: usart2-0 {
pins1 {
pinmux = <STM32_PINMUX('F', 5, AF7)>, /* USART2_TX */
@@ -2429,6 +2736,7 @@
};
};
+ /omit-if-no-ref/
usart2_sleep_pins_a: usart2-sleep-0 {
pins {
pinmux = <STM32_PINMUX('F', 5, ANALOG)>, /* USART2_TX */
@@ -2438,6 +2746,7 @@
};
};
+ /omit-if-no-ref/
usart2_pins_b: usart2-1 {
pins1 {
pinmux = <STM32_PINMUX('F', 5, AF7)>, /* USART2_TX */
@@ -2453,6 +2762,7 @@
};
};
+ /omit-if-no-ref/
usart2_sleep_pins_b: usart2-sleep-1 {
pins {
pinmux = <STM32_PINMUX('F', 5, ANALOG)>, /* USART2_TX */
@@ -2462,6 +2772,7 @@
};
};
+ /omit-if-no-ref/
usart2_pins_c: usart2-2 {
pins1 {
pinmux = <STM32_PINMUX('D', 5, AF7)>, /* USART2_TX */
@@ -2477,6 +2788,7 @@
};
};
+ /omit-if-no-ref/
usart2_idle_pins_c: usart2-idle-2 {
pins1 {
pinmux = <STM32_PINMUX('D', 5, ANALOG)>, /* USART2_TX */
@@ -2494,6 +2806,7 @@
};
};
+ /omit-if-no-ref/
usart2_sleep_pins_c: usart2-sleep-2 {
pins {
pinmux = <STM32_PINMUX('D', 5, ANALOG)>, /* USART2_TX */
@@ -2503,6 +2816,7 @@
};
};
+ /omit-if-no-ref/
usart3_pins_a: usart3-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, AF7)>; /* USART3_TX */
@@ -2516,6 +2830,7 @@
};
};
+ /omit-if-no-ref/
usart3_idle_pins_a: usart3-idle-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, ANALOG)>; /* USART3_TX */
@@ -2526,6 +2841,7 @@
};
};
+ /omit-if-no-ref/
usart3_sleep_pins_a: usart3-sleep-0 {
pins {
pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
@@ -2533,6 +2849,7 @@
};
};
+ /omit-if-no-ref/
usart3_pins_b: usart3-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
@@ -2548,6 +2865,7 @@
};
};
+ /omit-if-no-ref/
usart3_idle_pins_b: usart3-idle-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
@@ -2565,6 +2883,7 @@
};
};
+ /omit-if-no-ref/
usart3_sleep_pins_b: usart3-sleep-1 {
pins {
pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
@@ -2574,6 +2893,7 @@
};
};
+ /omit-if-no-ref/
usart3_pins_c: usart3-2 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
@@ -2589,6 +2909,7 @@
};
};
+ /omit-if-no-ref/
usart3_idle_pins_c: usart3-idle-2 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
@@ -2606,6 +2927,7 @@
};
};
+ /omit-if-no-ref/
usart3_sleep_pins_c: usart3-sleep-2 {
pins {
pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
@@ -2615,6 +2937,7 @@
};
};
+ /omit-if-no-ref/
usart3_pins_d: usart3-3 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
@@ -2630,6 +2953,7 @@
};
};
+ /omit-if-no-ref/
usart3_idle_pins_d: usart3-idle-3 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
@@ -2642,6 +2966,7 @@
};
};
+ /omit-if-no-ref/
usart3_sleep_pins_d: usart3-sleep-3 {
pins {
pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
@@ -2651,6 +2976,7 @@
};
};
+ /omit-if-no-ref/
usart3_pins_e: usart3-4 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
@@ -2666,6 +2992,7 @@
};
};
+ /omit-if-no-ref/
usart3_idle_pins_e: usart3-idle-4 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
@@ -2683,6 +3010,7 @@
};
};
+ /omit-if-no-ref/
usart3_sleep_pins_e: usart3-sleep-4 {
pins {
pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
@@ -2692,6 +3020,7 @@
};
};
+ /omit-if-no-ref/
usart3_pins_f: usart3-5 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
@@ -2707,12 +3036,14 @@
};
};
+ /omit-if-no-ref/
usbotg_hs_pins_a: usbotg-hs-0 {
pins {
pinmux = <STM32_PINMUX('A', 10, ANALOG)>; /* OTG_ID */
};
};
+ /omit-if-no-ref/
usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 {
pins {
pinmux = <STM32_PINMUX('A', 11, ANALOG)>, /* OTG_FS_DM */
@@ -2722,6 +3053,7 @@
};
&pinctrl_z {
+ /omit-if-no-ref/
i2c2_pins_b2: i2c2-0 {
pins {
pinmux = <STM32_PINMUX('Z', 0, AF3)>; /* I2C2_SCL */
@@ -2731,12 +3063,14 @@
};
};
+ /omit-if-no-ref/
i2c2_sleep_pins_b2: i2c2-sleep-0 {
pins {
pinmux = <STM32_PINMUX('Z', 0, ANALOG)>; /* I2C2_SCL */
};
};
+ /omit-if-no-ref/
i2c4_pins_a: i2c4-0 {
pins {
pinmux = <STM32_PINMUX('Z', 4, AF6)>, /* I2C4_SCL */
@@ -2747,6 +3081,7 @@
};
};
+ /omit-if-no-ref/
i2c4_sleep_pins_a: i2c4-sleep-0 {
pins {
pinmux = <STM32_PINMUX('Z', 4, ANALOG)>, /* I2C4_SCL */
@@ -2754,6 +3089,7 @@
};
};
+ /omit-if-no-ref/
i2c6_pins_a: i2c6-0 {
pins {
pinmux = <STM32_PINMUX('Z', 6, AF2)>, /* I2C6_SCL */
@@ -2764,6 +3100,7 @@
};
};
+ /omit-if-no-ref/
i2c6_sleep_pins_a: i2c6-sleep-0 {
pins {
pinmux = <STM32_PINMUX('Z', 6, ANALOG)>, /* I2C6_SCL */
@@ -2771,6 +3108,7 @@
};
};
+ /omit-if-no-ref/
spi1_pins_a: spi1-0 {
pins1 {
pinmux = <STM32_PINMUX('Z', 0, AF5)>, /* SPI1_SCK */
@@ -2786,6 +3124,7 @@
};
};
+ /omit-if-no-ref/
spi1_sleep_pins_a: spi1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('Z', 0, ANALOG)>, /* SPI1_SCK */
@@ -2794,6 +3133,7 @@
};
};
+ /omit-if-no-ref/
usart1_pins_b: usart1-1 {
pins1 {
pinmux = <STM32_PINMUX('Z', 7, AF7)>; /* USART1_TX */
@@ -2807,6 +3147,7 @@
};
};
+ /omit-if-no-ref/
usart1_idle_pins_b: usart1-idle-1 {
pins1 {
pinmux = <STM32_PINMUX('Z', 7, ANALOG)>; /* USART1_TX */
@@ -2817,6 +3158,7 @@
};
};
+ /omit-if-no-ref/
usart1_sleep_pins_b: usart1-sleep-1 {
pins {
pinmux = <STM32_PINMUX('Z', 7, ANALOG)>, /* USART1_TX */
diff --git a/arch/arm/boot/dts/st/stm32mp157c-osd32mp1-red.dts b/arch/arm/boot/dts/st/stm32mp157c-osd32mp1-red.dts
new file mode 100644
index 000000000000..bd67a1db9122
--- /dev/null
+++ b/arch/arm/boot/dts/st/stm32mp157c-osd32mp1-red.dts
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) Geanix ApS 2023 - All Rights Reserved
+ * Author: Sean Nyekjaer <sean@geanix.com>
+ */
+
+/dts-v1/;
+
+#include "stm32mp157.dtsi"
+#include "stm32mp15xc.dtsi"
+#include "stm32mp15xx-osd32.dtsi"
+#include "stm32mp15xxac-pinctrl.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/stm32-pinfunc.h>
+
+/ {
+ model = "Octavo OSD32MP1 RED board";
+ compatible = "oct,stm32mp157c-osd32-red", "oct,stm32mp15xx-osd32", "st,stm32mp157";
+
+ aliases {
+ serial0 = &uart4;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ led-controller-0 {
+ compatible = "gpio-leds";
+
+ led-0 {
+ label = "heartbeat";
+ gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
+
+&crc1 {
+ status = "okay";
+};
+
+&dts {
+ status = "okay";
+};
+
+&ethernet0 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&ethernet0_rgmii_pins_a>;
+ pinctrl-1 = <&ethernet0_rgmii_sleep_pins_a>;
+ phy-mode = "rgmii-id";
+ max-speed = <1000>;
+ phy-handle = <&phy0>;
+ st,eth-clk-sel;
+ status = "okay";
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy0: ethernet-phy@3 {
+ reg = <3>;
+ };
+ };
+};
+
+&iwdg2 {
+ timeout-sec = <32>;
+ status = "okay";
+};
+
+&i2c1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2c1_pins_a>;
+ pinctrl-1 = <&i2c1_sleep_pins_a>;
+ status = "okay";
+ i2c-scl-rising-time-ns = <100>;
+ i2c-scl-falling-time-ns = <7>;
+ /* spare dmas for other usage */
+ /delete-property/dmas;
+ /delete-property/dma-names;
+
+ hdmi-transmitter@39 {
+ compatible = "sil,sii9022";
+ reg = <0x39>;
+ reset-gpios = <&gpiog 0 GPIO_ACTIVE_LOW>;
+ interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-parent = <&gpiog>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&ltdc_pins_e>;
+ pinctrl-1 = <&ltdc_sleep_pins_e>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ sii9022_in: endpoint {
+ remote-endpoint = <&ltdc_ep0_out>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ sii9022_tx_endpoint: endpoint {
+ remote-endpoint = <&i2s2_endpoint>;
+ };
+ };
+ };
+ };
+};
+
+&i2s2 {
+ clocks = <&rcc SPI2>, <&rcc SPI2_K>, <&rcc CK_PER>, <&rcc PLL3_R>;
+ clock-names = "pclk", "i2sclk", "x8k", "x11k";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2s2_pins_b>;
+ pinctrl-1 = <&i2s2_sleep_pins_b>;
+ status = "okay";
+
+ i2s2_port: port {
+ i2s2_endpoint: endpoint {
+ remote-endpoint = <&sii9022_tx_endpoint>;
+ dai-format = "i2s";
+ mclk-fs = <256>;
+ };
+ };
+};
+
+&ltdc {
+ status = "okay";
+
+ port {
+ ltdc_ep0_out: endpoint {
+ remote-endpoint = <&sii9022_in>;
+ };
+ };
+};
+
+&m_can1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&m_can1_pins_d>;
+ pinctrl-1 = <&m_can1_sleep_pins_d>;
+ status = "okay";
+};
+
+&pwr_regulators {
+ vdd-supply = <&vdd>;
+ vdd_3v3_usbfs-supply = <&vdd_usb>;
+};
+
+&rtc {
+ status = "okay";
+};
+
+&sdmmc1 {
+ pinctrl-names = "default", "opendrain", "sleep";
+ pinctrl-0 = <&sdmmc1_b4_pins_a>;
+ pinctrl-1 = <&sdmmc1_b4_od_pins_a>;
+ pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
+ cd-gpios = <&gpioe 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ disable-wp;
+ st,neg-edge;
+ bus-width = <4>;
+ vmmc-supply = <&v3v3>;
+ status = "okay";
+};
+
+&sdmmc2 {
+ pinctrl-names = "default", "opendrain", "sleep";
+ pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_d>;
+ pinctrl-1 = <&sdmmc2_b4_od_pins_a>;
+ pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_d>;
+ non-removable;
+ no-sd;
+ no-sdio;
+ st,neg-edge;
+ bus-width = <8>;
+ vmmc-supply = <&v3v3>;
+ vqmmc-supply = <&vdd>;
+ mmc-ddr-3_3v;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default", "sleep", "idle";
+ pinctrl-0 = <&uart4_pins_a>;
+ pinctrl-1 = <&uart4_sleep_pins_a>;
+ pinctrl-2 = <&uart4_idle_pins_a>;
+ /* spare dmas for other usage */
+ /delete-property/dmas;
+ /delete-property/dma-names;
+ status = "okay";
+};
+
+&usbh_ehci {
+ phys = <&usbphyc_port0>;
+ phy-names = "usb";
+ status = "okay";
+};
+
+&usbh_ohci {
+ phys = <&usbphyc_port0>;
+ phy-names = "usb";
+ status = "okay";
+};
+
+&usbotg_hs {
+ vbus-supply = <&vbus_otg>;
+};
+
+&usbphyc {
+ status = "okay";
+};
+
+&usbphyc_port0 {
+ phy-supply = <&vdd_usb>;
+};
+
+&usbphyc_port1 {
+ phy-supply = <&vdd_usb>;
+};
diff --git a/arch/arm/boot/dts/st/stm32mp15xc-lxa-tac.dtsi b/arch/arm/boot/dts/st/stm32mp15xc-lxa-tac.dtsi
index 184b8bb4ebbf..f09b7c384bd9 100644
--- a/arch/arm/boot/dts/st/stm32mp15xc-lxa-tac.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp15xc-lxa-tac.dtsi
@@ -597,10 +597,6 @@ baseboard_eeprom: &sip_eeprom {
phy-supply = <&vdd_usb>;
};
-&v3v3_hdmi {
- /delete-property/regulator-always-on;
-};
-
&vrefbuf {
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
diff --git a/arch/arm/boot/dts/st/stm32mp15xx-osd32.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-osd32.dtsi
index a43965c86fe8..aeb71c41a734 100644
--- a/arch/arm/boot/dts/st/stm32mp15xx-osd32.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp15xx-osd32.dtsi
@@ -117,18 +117,14 @@
regulator-name = "v1v8_audio";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
- regulator-always-on;
interrupts = <IT_CURLIM_LDO1 0>;
-
};
v3v3_hdmi: ldo2 {
regulator-name = "v3v3_hdmi";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
- regulator-always-on;
interrupts = <IT_CURLIM_LDO2 0>;
-
};
vtt_ddr: ldo3 {
@@ -156,9 +152,7 @@
regulator-name = "v1v2_hdmi";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
- regulator-always-on;
interrupts = <IT_CURLIM_LDO6 0>;
-
};
vref_ddr: vref_ddr {
diff --git a/arch/arm/boot/dts/ti/omap/am335x-pocketbeagle.dts b/arch/arm/boot/dts/ti/omap/am335x-pocketbeagle.dts
index 5dfe4d4bab93..78ce860e59b3 100644
--- a/arch/arm/boot/dts/ti/omap/am335x-pocketbeagle.dts
+++ b/arch/arm/boot/dts/ti/omap/am335x-pocketbeagle.dts
@@ -8,6 +8,7 @@
#include "am33xx.dtsi"
#include "am335x-osd335x-common.dtsi"
+#include <dt-bindings/leds/common.h>
/ {
model = "TI AM335x PocketBeagle";
@@ -25,6 +26,8 @@
led-usr0 {
label = "beaglebone:green:usr0";
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_HEARTBEAT;
gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
default-state = "off";
@@ -32,6 +35,8 @@
led-usr1 {
label = "beaglebone:green:usr1";
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_DISK_ACTIVITY;
gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "mmc0";
default-state = "off";
@@ -39,6 +44,8 @@
led-usr2 {
label = "beaglebone:green:usr2";
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_CPU;
gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "cpu0";
default-state = "off";
@@ -46,6 +53,8 @@
led-usr3 {
label = "beaglebone:green:usr3";
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_INDICATOR;
gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
@@ -112,7 +121,7 @@
"P2.24",
"P2.33",
"P2.22",
- "P2.18",
+ "P2.18 [PRU0.15i]",
"NC",
"NC",
"P2.01 [PWM1A]",
@@ -208,11 +217,6 @@
compatible = "pinconf-single";
pinctrl-names = "default";
- pinctrl-0 = < &P2_03_gpio &P1_34_gpio &P2_19_gpio &P2_24_gpio
- &P2_33_gpio &P2_22_gpio &P2_18_gpio &P2_10_gpio
- &P2_06_gpio &P2_04_gpio &P2_02_gpio &P2_08_gpio
- &P2_17_gpio >;
-
/* P2_03 (ZCZ ball T10) gpio0_23 0x824 PIN 9 */
P2_03_gpio: P2-03-gpio-pins {
pinctrl-single,pins = <
@@ -267,10 +271,10 @@
pinctrl-single,bias-pulldown = < 0x10 0x00 0x10 0x18>;
};
- /* P2_18 (ZCZ ball U13) gpio1_15 0x83c PIN 15 */
- P2_18_gpio: P2-18-gpio-pins {
+ /* P2_20 (ZCZ ball T13) gpio2_00 0x888 */
+ P2_20_gpio: P2-20-gpio-pins {
pinctrl-single,pins = <
- AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLUP, MUX_MODE7)
+ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_INPUT_PULLUP, MUX_MODE7)
>;
pinctrl-single,bias-pullup = < 0x10 0x10 0x00 0x18>;
pinctrl-single,bias-pulldown = < 0x10 0x00 0x10 0x18>;
@@ -401,6 +405,27 @@
AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT_PULLDOWN, MUX_MODE6) /* (U17) gpmc_wpn.uart4_txd */
>;
};
+
+ pru0_pins: pinmux-pru0-pins {
+ pinctrl-single,pins = <
+ AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_INPUT_PULLUP, MUX_MODE5)/* (D14) xdma_event_intr1.pr1_pru0_pru_r31_16 */
+ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE5)/* (A14) mcasp0_ahclkx.pr1_pru0_pru_r30_7 */
+ AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE5) /* (B12) mcasp0_acklr.pr1_pru0_pru_r30_4 */
+ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT_PULLDOWN, MUX_MODE5) /* (B13) mcasp0_fsx.pr1_pru0_pru_r30_1 */
+ AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLUP, MUX_MODE6) /* (U13) gpmc_ad15.pr1_pru0_pru_r31_15 */
+ AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR1, PIN_OUTPUT_PULLDOWN, MUX_MODE5) /* (D13) mcasp0_axr1.pr1_pru0_pru_r30_6 */
+ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE5)/* (C12) mcasp0_ahclkr.pr1_pru0_pru_r30_3 */
+ AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_OUTPUT_PULLDOWN, MUX_MODE5) /* (D12) mcasp0_axr0.pr1_pru0_pru_r30_2 */
+ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_OUTPUT_PULLDOWN, MUX_MODE5) /* (C13) mcasp0_fsr.pr1_pru0_pru_r30_5 */
+ >;
+ };
+
+ pru1_pins: pinmux-pru1-pins {
+ pinctrl-single,pins = <
+ AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE5)/*(R6) lcd_ac_bias_en.pr1_pru1_pru_r30_11 */
+ AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE5) /* (V5) lcd_pclk.pr1_pru1_pru_r30_10 */
+ >;
+ };
};
&epwmss0 {
@@ -482,3 +507,17 @@
&usb1 {
dr_mode = "host";
};
+
+&pruss_tm {
+ status = "okay";
+};
+
+&pru0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pru0_pins>;
+};
+
+&pru1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pru1_pins>;
+};
diff --git a/arch/arm/boot/dts/ti/omap/am3517-evm.dts b/arch/arm/boot/dts/ti/omap/am3517-evm.dts
index af9df15274be..40f15da81043 100644
--- a/arch/arm/boot/dts/ti/omap/am3517-evm.dts
+++ b/arch/arm/boot/dts/ti/omap/am3517-evm.dts
@@ -172,11 +172,24 @@
&davinci_emac {
pinctrl-names = "default";
pinctrl-0 = <&ethernet_pins>;
+ phy-mode = "rmii";
+ phy-handle = <&ethphy0>;
status = "okay";
};
&davinci_mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "okay";
+
+ ethphy0: ethernet-phy@0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&enet_phy_pins>;
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <26 IRQ_TYPE_LEVEL_LOW>; /* gpio_58 */
+ };
};
&dss {
@@ -257,6 +270,12 @@
>;
};
+ enet_phy_pins: ethernet-phy-pins {
+ pinctrl-single,pins = <
+ OMAP3_CORE1_IOPAD(0x20bc, PIN_INPUT | MUX_MODE4) /* gpmc_ncs7.gpio_57 */
+ >;
+ };
+
i2c2_pins: i2c2-pins {
pinctrl-single,pins = <
OMAP3_CORE1_IOPAD(0x21be, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_scl */
@@ -271,13 +290,6 @@
>;
};
- leds_pins: leds-pins {
- pinctrl-single,pins = <
- OMAP3_WKUP_IOPAD(0x2a24, PIN_OUTPUT_PULLUP | MUX_MODE4) /* jtag_emu0.gpio_11 */
- OMAP3_WKUP_IOPAD(0x2a26, PIN_OUTPUT_PULLUP | MUX_MODE4) /* jtag_emu1.gpio_31 */
- >;
- };
-
mmc1_pins: mmc1-pins {
pinctrl-single,pins = <
OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */
@@ -355,3 +367,12 @@
>;
};
};
+
+&omap3_pmx_wkup {
+ leds_pins: leds-pins {
+ pinctrl-single,pins = <
+ OMAP3_WKUP_IOPAD(0x2a24, PIN_OUTPUT_PULLUP | MUX_MODE4) /* jtag_emu0.gpio_11 */
+ OMAP3_WKUP_IOPAD(0x2a26, PIN_OUTPUT_PULLUP | MUX_MODE4) /* jtag_emu1.gpio_31 */
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/ti/omap/am3517.dtsi b/arch/arm/boot/dts/ti/omap/am3517.dtsi
index fbfc956f4e4d..77e58e686fb1 100644
--- a/arch/arm/boot/dts/ti/omap/am3517.dtsi
+++ b/arch/arm/boot/dts/ti/omap/am3517.dtsi
@@ -15,6 +15,7 @@
aliases {
serial3 = &uart4;
can = &hecc;
+ ethernet = &davinci_emac;
};
cpus {
diff --git a/arch/arm/boot/dts/ti/omap/motorola-mapphone-common.dtsi b/arch/arm/boot/dts/ti/omap/motorola-mapphone-common.dtsi
index d2d516d113ba..a2bb3609c94f 100644
--- a/arch/arm/boot/dts/ti/omap/motorola-mapphone-common.dtsi
+++ b/arch/arm/boot/dts/ti/omap/motorola-mapphone-common.dtsi
@@ -67,7 +67,8 @@
fsusb1_phy: usb-phy@1 {
compatible = "motorola,mapphone-mdm6600";
pinctrl-0 = <&usb_mdm6600_pins>;
- pinctrl-names = "default";
+ pinctrl-1 = <&usb_mdm6600_sleep_pins>;
+ pinctrl-names = "default", "sleep";
enable-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>; /* gpio_95 */
power-gpios = <&gpio2 22 GPIO_ACTIVE_HIGH>; /* gpio_54 */
reset-gpios = <&gpio2 17 GPIO_ACTIVE_HIGH>; /* gpio_49 */
@@ -476,6 +477,23 @@
>;
};
+ /* Modem sleep pins to keep gpio_49 high with internal pull */
+ usb_mdm6600_sleep_pins: usb-mdm6600-sleep-pins {
+ pinctrl-single,pins = <
+ OMAP4_IOPAD(0x0d8, PIN_INPUT | MUX_MODE3)
+ OMAP4_IOPAD(0x07c, PIN_OUTPUT | MUX_MODE3)
+ OMAP4_IOPAD(0x072, PIN_INPUT_PULLUP | MUX_MODE7) /* Keep gpio_49 reset high */
+ OMAP4_IOPAD(0x14e, PIN_OUTPUT | MUX_MODE3)
+ OMAP4_IOPAD(0x150, PIN_OFF_OUTPUT_LOW | PIN_INPUT | MUX_MODE3)
+ OMAP4_IOPAD(0x07e, PIN_INPUT | MUX_MODE3)
+ OMAP4_IOPAD(0x07a, PIN_INPUT | MUX_MODE3)
+ OMAP4_IOPAD(0x078, PIN_INPUT | MUX_MODE3)
+ OMAP4_IOPAD(0x094, PIN_OUTPUT | MUX_MODE3)
+ OMAP4_IOPAD(0x096, PIN_OUTPUT | MUX_MODE3)
+ OMAP4_IOPAD(0x142, PIN_OUTPUT | MUX_MODE3)
+ >;
+ };
+
usb_ulpi_pins: usb-ulpi-pins {
pinctrl-single,pins = <
OMAP4_IOPAD(0x196, MUX_MODE7)
diff --git a/arch/arm/boot/dts/ti/omap/omap3-devkit8000-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-devkit8000-common.dtsi
index 3b9838f1bb6b..07d5894ebb74 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-devkit8000-common.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap3-devkit8000-common.dtsi
@@ -275,8 +275,8 @@
ethernet@6,0 {
compatible = "davicom,dm9000";
- reg = <6 0x000 2
- 6 0x400 2>; /* CS6, offset 0 and 0x400, IO size 2 */
+ reg = <6 0x000 2>,
+ <6 0x400 2>; /* CS6, offset 0 and 0x400, IO size 2 */
bank-width = <2>;
interrupt-parent = <&gpio1>;
interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
diff --git a/arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi b/arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi
index b6b27e93857f..3661340009e7 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi
@@ -11,7 +11,7 @@
/ {
model = "OMAP3 GTA04";
- compatible = "goldelico,gta04", "ti,omap3630", "ti,omap36xx", "ti,omap3";
+ compatible = "goldelico,gta04", "ti,omap3630", "ti,omap3";
cpus {
cpu@0 {
cpu0-supply = <&vcc>;
diff --git a/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts b/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts
index e119e2cccc4e..01d783826d5f 100644
--- a/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts
+++ b/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts
@@ -4,6 +4,7 @@
*/
/dts-v1/;
+#include <dt-bindings/leds/common.h>
#include <dt-bindings/input/input.h>
#include "omap4460.dtsi"
@@ -188,15 +189,6 @@
pinctrl-0 = <&mpu9150h_pins>;
interrupt-parent = <&gpio2>;
interrupt = <19 IRQ_TYPE_LEVEL_HIGH>;
-
- i2c-gate {
- #address-cells = <1>;
- #size-cells = <0>;
- magnetometer@c {
- compatible = "asahi-kasei,ak8975";
- reg = <0x0c>;
- };
- };
};
};
@@ -206,7 +198,31 @@
clock-frequency = <100000>;
- /* TODO: BD2606MVV at 0x66 */
+ led-controller@66 {
+ compatible = "rohm,bd2606mvv";
+ reg = <0x66>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_STATUS;
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_STATUS;
+ };
+
+ led@4 {
+ reg = <4>;
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_STATUS;
+ };
+ };
};
&i2c4 {
@@ -227,7 +243,16 @@
reset-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>;
};
- /* TODO: mpu9150 at control unit, seems to require quirks */
+ mpu9150: imu@68 {
+ compatible = "invensense,mpu9150";
+ reg = <0x68>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&mpu9150_pins>;
+ interrupt-parent = <&gpio2>;
+ interrupt = <7 IRQ_TYPE_LEVEL_HIGH>;
+ invensense,level-shifter;
+ };
};
&keypad {
@@ -362,6 +387,12 @@
>;
};
+ mpu9150_pins: pinmux-mpu9150-pins {
+ pinctrl-single,pins = <
+ OMAP4_IOPAD(0x5e, PIN_INPUT_PULLUP | MUX_MODE3)
+ >;
+ };
+
mpu9150h_pins: pinmux-mpu9150h-pins {
pinctrl-single,pins = <
OMAP4_IOPAD(0x76, PIN_INPUT_PULLUP | MUX_MODE3)
@@ -410,7 +441,7 @@
>;
};
- wl12xx_gpio: pinmux-wl12xx-gpio {
+ wl12xx_gpio: pinmux-wl12xx-gpio-pins {
pinctrl-single,pins = <
OMAP4_IOPAD(0x1c8, PIN_OUTPUT | MUX_MODE3) /* gpio_24 / WLAN_EN */
>;
diff --git a/arch/arm/boot/dts/ti/omap/omap4-l4-abe.dtsi b/arch/arm/boot/dts/ti/omap/omap4-l4-abe.dtsi
index 7ae8b620515c..59f546a278f8 100644
--- a/arch/arm/boot/dts/ti/omap/omap4-l4-abe.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap4-l4-abe.dtsi
@@ -109,6 +109,8 @@
reg = <0x0 0xff>, /* MPU private access */
<0x49022000 0xff>; /* L3 Interconnect */
reg-names = "mpu", "dma";
+ clocks = <&abe_clkctrl OMAP4_MCBSP1_CLKCTRL 24>;
+ clock-names = "fck";
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "common";
ti,buffer-size = <128>;
@@ -142,6 +144,8 @@
reg = <0x0 0xff>, /* MPU private access */
<0x49024000 0xff>; /* L3 Interconnect */
reg-names = "mpu", "dma";
+ clocks = <&abe_clkctrl OMAP4_MCBSP2_CLKCTRL 24>;
+ clock-names = "fck";
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "common";
ti,buffer-size = <128>;
@@ -175,6 +179,8 @@
reg = <0x0 0xff>, /* MPU private access */
<0x49026000 0xff>; /* L3 Interconnect */
reg-names = "mpu", "dma";
+ clocks = <&abe_clkctrl OMAP4_MCBSP3_CLKCTRL 24>;
+ clock-names = "fck";
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "common";
ti,buffer-size = <128>;
diff --git a/arch/arm/boot/dts/ti/omap/omap4-l4.dtsi b/arch/arm/boot/dts/ti/omap/omap4-l4.dtsi
index 46b8f9efd413..3fcef3080eae 100644
--- a/arch/arm/boot/dts/ti/omap/omap4-l4.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap4-l4.dtsi
@@ -2043,6 +2043,8 @@
compatible = "ti,omap4-mcbsp";
reg = <0x0 0xff>; /* L4 Interconnect */
reg-names = "mpu";
+ clocks = <&l4_per_clkctrl OMAP4_MCBSP4_CLKCTRL 24>;
+ clock-names = "fck";
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "common";
ti,buffer-size = <128>;
diff --git a/arch/arm/boot/dts/ti/omap/omap5-l4-abe.dtsi b/arch/arm/boot/dts/ti/omap/omap5-l4-abe.dtsi
index a03bca5a3584..97b0c3b5f573 100644
--- a/arch/arm/boot/dts/ti/omap/omap5-l4-abe.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap5-l4-abe.dtsi
@@ -109,6 +109,8 @@
reg = <0x0 0xff>, /* MPU private access */
<0x49022000 0xff>; /* L3 Interconnect */
reg-names = "mpu", "dma";
+ clocks = <&abe_clkctrl OMAP5_MCBSP1_CLKCTRL 24>;
+ clock-names = "fck";
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "common";
ti,buffer-size = <128>;
@@ -142,6 +144,8 @@
reg = <0x0 0xff>, /* MPU private access */
<0x49024000 0xff>; /* L3 Interconnect */
reg-names = "mpu", "dma";
+ clocks = <&abe_clkctrl OMAP5_MCBSP2_CLKCTRL 24>;
+ clock-names = "fck";
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "common";
ti,buffer-size = <128>;
@@ -175,6 +179,8 @@
reg = <0x0 0xff>, /* MPU private access */
<0x49026000 0xff>; /* L3 Interconnect */
reg-names = "mpu", "dma";
+ clocks = <&abe_clkctrl OMAP5_MCBSP3_CLKCTRL 24>;
+ clock-names = "fck";
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "common";
ti,buffer-size = <128>;
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 77c83ba81715..1fbd7363cf11 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -785,19 +785,6 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
return ret;
}
-/**
- * sa1111_probe - probe for a single SA1111 chip.
- * @phys_addr: physical address of device.
- *
- * Probe for a SA1111 chip. This must be called
- * before any other SA1111-specific code.
- *
- * Returns:
- * %-ENODEV device not found.
- * %-EBUSY physical address already marked in-use.
- * %-EINVAL no platform data passed
- * %0 successful.
- */
static int __sa1111_probe(struct device *me, struct resource *mem, int irq)
{
struct sa1111_platform_data *pd = me->platform_data;
@@ -1108,6 +1095,20 @@ static int sa1111_resume_noirq(struct device *dev)
#define sa1111_resume_noirq NULL
#endif
+/**
+ * sa1111_probe - probe for a single SA1111 chip.
+ * @pdev: platform device.
+ *
+ * Probe for a SA1111 chip. This must be called
+ * before any other SA1111-specific code.
+ *
+ * Returns:
+ * * %-ENODEV - device not found.
+ * * %-ENOMEM - memory allocation failure.
+ * * %-EBUSY - physical address already marked in-use.
+ * * %-EINVAL - no platform data passed
+ * * %0 - successful.
+ */
static int sa1111_probe(struct platform_device *pdev)
{
struct resource *mem;
diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig
index ed66a2958912..9d1b297c432e 100644
--- a/arch/arm/configs/aspeed_g4_defconfig
+++ b/arch/arm/configs/aspeed_g4_defconfig
@@ -58,7 +58,6 @@ CONFIG_NET_NCSI=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_FIRMWARE_MEMMAP=y
CONFIG_MTD=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_PARTITIONED_MASTER=y
diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig
index b6487a4b45c0..b55f8f539c5f 100644
--- a/arch/arm/configs/aspeed_g5_defconfig
+++ b/arch/arm/configs/aspeed_g5_defconfig
@@ -70,7 +70,6 @@ CONFIG_MCTP=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_FIRMWARE_MEMMAP=y
CONFIG_MTD=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_PARTITIONED_MASTER=y
@@ -81,6 +80,8 @@ CONFIG_MTD_UBI_FASTMAP=y
CONFIG_MTD_UBI_BLOCK=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=y
+CONFIG_SMPRO_ERRMON=y
+CONFIG_SMPRO_MISC=y
CONFIG_EEPROM_AT24=y
CONFIG_EEPROM_AT25=y
CONFIG_SCSI=y
@@ -150,6 +151,7 @@ CONFIG_ASPEED_KCS_IPMI_BMC=y
CONFIG_IPMI_KCS_BMC_CDEV_IPMI=y
CONFIG_IPMI_KCS_BMC_SERIO=y
CONFIG_ASPEED_BT_IPMI_BMC=y
+CONFIG_SSIF_IPMI_BMC=y
CONFIG_HW_RANDOM_TIMERIOMEM=y
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS_I2C=y
@@ -173,6 +175,7 @@ CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_W1=y
CONFIG_W1_MASTER_GPIO=y
CONFIG_W1_SLAVE_THERM=y
+CONFIG_SENSORS_SMPRO=y
CONFIG_SENSORS_ADT7475=y
CONFIG_SENSORS_ASPEED=y
CONFIG_SENSORS_IIO_HWMON=y
@@ -194,6 +197,7 @@ CONFIG_SENSORS_SBTSI=y
CONFIG_SENSORS_TMP421=y
CONFIG_SENSORS_W83773G=y
CONFIG_WATCHDOG_SYSFS=y
+CONFIG_MFD_SMPRO=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_SUPPORT_FILTER=y
CONFIG_MEDIA_PLATFORM_SUPPORT=y
@@ -251,9 +255,11 @@ CONFIG_FSI_MASTER_GPIO=y
CONFIG_FSI_MASTER_HUB=y
CONFIG_FSI_MASTER_AST_CF=y
CONFIG_FSI_MASTER_ASPEED=y
+CONFIG_FSI_MASTER_I2CR=y
CONFIG_FSI_SCOM=y
CONFIG_FSI_SBEFIFO=y
CONFIG_FSI_OCC=y
+CONFIG_I2CR_SCOM=y
CONFIG_PECI=y
CONFIG_PECI_CPU=y
CONFIG_PECI_ASPEED=y
diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
index 53b1d41b4a8b..c98d5ff8a1ed 100644
--- a/arch/arm/configs/exynos_defconfig
+++ b/arch/arm/configs/exynos_defconfig
@@ -93,7 +93,7 @@ CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_ATA=y
# CONFIG_SATA_PMP is not set
-CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_DWC=y
# CONFIG_ATA_SFF is not set
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
@@ -322,6 +322,7 @@ CONFIG_EXYNOS_ADC=y
CONFIG_STMPE_ADC=y
CONFIG_CM36651=y
CONFIG_AK8975=y
+CONFIG_SENSORS_ISL29018=y
CONFIG_PWM=y
CONFIG_PWM_SAMSUNG=y
CONFIG_PHY_EXYNOS5250_SATA=y
diff --git a/arch/arm/configs/hardening.config b/arch/arm/configs/hardening.config
new file mode 100644
index 000000000000..327349ce6377
--- /dev/null
+++ b/arch/arm/configs/hardening.config
@@ -0,0 +1,7 @@
+# Basic kernel hardening options (specific to arm)
+
+# Make sure PXN/PAN emulation is enabled.
+CONFIG_CPU_SW_DOMAIN_PAN=y
+
+# Dangerous; old interfaces and needless additional attack surface.
+# CONFIG_OABI_COMPAT is not set
diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig
index d95686d19401..59c4835ffc97 100644
--- a/arch/arm/configs/keystone_defconfig
+++ b/arch/arm/configs/keystone_defconfig
@@ -98,7 +98,6 @@ CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_MANGLE=y
-CONFIG_IP_NF_TARGET_CLUSTERIP=y
CONFIG_IP_NF_TARGET_ECN=y
CONFIG_IP_NF_TARGET_TTL=y
CONFIG_IP_NF_RAW=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 23fc49f23d25..10fd74bf85f9 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -237,6 +237,7 @@ CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_AHCI_BRCM=y
CONFIG_AHCI_DM816=y
+CONFIG_AHCI_DWC=m
CONFIG_AHCI_ST=y
CONFIG_AHCI_IMX=y
CONFIG_AHCI_SUNXI=y
@@ -314,6 +315,7 @@ CONFIG_KEYBOARD_PXA27x=m
CONFIG_KEYBOARD_SAMSUNG=m
CONFIG_KEYBOARD_ST_KEYSCAN=y
CONFIG_KEYBOARD_SPEAR=y
+CONFIG_KEYBOARD_TM2_TOUCHKEY=m
CONFIG_KEYBOARD_CROS_EC=m
CONFIG_MOUSE_PS2_ELANTECH=y
CONFIG_MOUSE_CYAPA=m
@@ -691,6 +693,8 @@ CONFIG_VIDEO_STI_HVA=m
CONFIG_VIDEO_STM32_DCMI=m
CONFIG_V4L_TEST_DRIVERS=y
CONFIG_VIDEO_VIVID=m
+CONFIG_VIDEO_S5C73M3=m
+CONFIG_VIDEO_S5K6A3=m
CONFIG_VIDEO_ADV7180=m
CONFIG_VIDEO_ADV7604=m
CONFIG_VIDEO_ADV7604_CEC=y
@@ -857,7 +861,6 @@ CONFIG_USB_MUSB_HDRC=m
CONFIG_USB_MUSB_SUNXI=m
CONFIG_USB_MUSB_TUSB6010=m
CONFIG_USB_MUSB_OMAP2PLUS=m
-CONFIG_USB_MUSB_AM35X=m
CONFIG_USB_MUSB_DSPS=m
CONFIG_USB_MUSB_UX500=m
CONFIG_USB_UX500_DMA=y
@@ -1073,7 +1076,6 @@ CONFIG_QCOM_IPCC=y
CONFIG_OMAP_IOMMU=y
CONFIG_OMAP_IOMMU_DEBUG=y
CONFIG_ROCKCHIP_IOMMU=y
-CONFIG_TEGRA_IOMMU_GART=y
CONFIG_TEGRA_IOMMU_SMMU=y
CONFIG_EXYNOS_IOMMU=y
CONFIG_QCOM_IOMMU=y
@@ -1203,6 +1205,8 @@ CONFIG_PHY_QCOM_USB_HS=y
CONFIG_PHY_RCAR_GEN2=m
CONFIG_PHY_ROCKCHIP_DP=m
CONFIG_PHY_ROCKCHIP_USB=y
+CONFIG_PHY_EXYNOS_DP_VIDEO=m
+CONFIG_PHY_EXYNOS_MIPI_VIDEO=m
CONFIG_PHY_SAMSUNG_USB2=m
CONFIG_PHY_EXYNOS5250_SATA=m
CONFIG_PHY_UNIPHIER_USB2=y
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index b685018dcf54..7b1b41b4b160 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -78,7 +78,6 @@ CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=m
-CONFIG_NF_LOG_NETDEV=m
CONFIG_NF_CONNTRACK_ZONES=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_TIMEOUT=y
@@ -92,7 +91,6 @@ CONFIG_NF_TABLES_INET=y
CONFIG_NF_TABLES_NETDEV=y
CONFIG_NFT_NUMGEN=m
CONFIG_NFT_CT=m
-CONFIG_NFT_COUNTER=m
CONFIG_NFT_CONNLIMIT=m
CONFIG_NFT_LOG=m
CONFIG_NFT_LIMIT=m
@@ -100,7 +98,6 @@ CONFIG_NFT_MASQ=m
CONFIG_NFT_REDIR=m
CONFIG_NFT_NAT=m
CONFIG_NFT_TUNNEL=m
-CONFIG_NFT_OBJREF=m
CONFIG_NFT_QUEUE=m
CONFIG_NFT_QUOTA=m
CONFIG_NFT_REJECT=m
@@ -179,7 +176,6 @@ CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
CONFIG_NFT_DUP_IPV4=m
CONFIG_NFT_FIB_IPV4=m
-CONFIG_NF_FLOW_TABLE_IPV4=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_ECN=m
@@ -193,14 +189,12 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_NETMAP=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_SECURITY=m
CONFIG_NFT_DUP_IPV6=m
CONFIG_NFT_FIB_IPV6=m
-CONFIG_NF_FLOW_TABLE_IPV6=m
CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
@@ -225,7 +219,6 @@ CONFIG_IP6_NF_TARGET_NPT=m
CONFIG_NF_TABLES_BRIDGE=m
CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
-CONFIG_NF_LOG_BRIDGE=m
CONFIG_BRIDGE=m
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_VLAN_8021Q=m
@@ -484,7 +477,6 @@ CONFIG_LIRC=y
CONFIG_RC_DEVICES=y
CONFIG_IR_GPIO_TX=m
CONFIG_IR_PWM_TX=m
-CONFIG_IR_RX51=m
CONFIG_IR_SPI=m
CONFIG_MEDIA_SUPPORT=m
CONFIG_V4L_PLATFORM_DRIVERS=y
@@ -560,7 +552,6 @@ CONFIG_USB_STORAGE=m
CONFIG_USB_MUSB_HDRC=m
CONFIG_USB_MUSB_TUSB6010=m
CONFIG_USB_MUSB_OMAP2PLUS=m
-CONFIG_USB_MUSB_AM35X=m
CONFIG_USB_MUSB_DSPS=m
CONFIG_USB_INVENTRA_DMA=y
CONFIG_USB_TI_CPPI41_DMA=y
diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig
index 23c131b0854b..9e81b1849e4c 100644
--- a/arch/arm/configs/pxa_defconfig
+++ b/arch/arm/configs/pxa_defconfig
@@ -100,7 +100,6 @@ CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_CONNECTOR=y
CONFIG_MTD=y
-CONFIG_MTD_AR7_PARTS=m
CONFIG_MTD_CMDLINE_PARTS=m
CONFIG_MTD_OF_PARTS=m
CONFIG_MTD_AFS_PARTS=m
diff --git a/arch/arm/configs/s5pv210_defconfig b/arch/arm/configs/s5pv210_defconfig
index 72df854878f8..d280169081bd 100644
--- a/arch/arm/configs/s5pv210_defconfig
+++ b/arch/arm/configs/s5pv210_defconfig
@@ -97,6 +97,7 @@ CONFIG_MMC_SDHCI_S3C_DMA=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_MAX8998=m
CONFIG_DMADEVICES=y
+CONFIG_IIO=y
CONFIG_PWM=y
CONFIG_PWM_SAMSUNG=y
CONFIG_PHY_SAMSUNG_USB2=m
diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig
index 22205ef0f376..dfdea295c4af 100644
--- a/arch/arm/configs/shmobile_defconfig
+++ b/arch/arm/configs/shmobile_defconfig
@@ -6,6 +6,7 @@ CONFIG_CGROUPS=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_PERF_EVENTS=y
+CONFIG_KEXEC=y
CONFIG_ARCH_RENESAS=y
CONFIG_PL310_ERRATA_588369=y
CONFIG_SMP=y
@@ -13,7 +14,6 @@ CONFIG_SCHED_MC=y
CONFIG_NR_CPUS=8
CONFIG_HIGHMEM=y
CONFIG_ARM_APPENDED_DTB=y
-CONFIG_KEXEC=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index 613f07b8ce15..8635b7216bfc 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -292,7 +292,6 @@ CONFIG_CHROME_PLATFORMS=y
CONFIG_CROS_EC=y
CONFIG_CROS_EC_I2C=m
CONFIG_CROS_EC_SPI=m
-CONFIG_TEGRA_IOMMU_GART=y
CONFIG_TEGRA_IOMMU_SMMU=y
CONFIG_ARCH_TEGRA_2x_SOC=y
CONFIG_ARCH_TEGRA_3x_SOC=y
diff --git a/arch/arm/crypto/nhpoly1305-neon-glue.c b/arch/arm/crypto/nhpoly1305-neon-glue.c
index e93e41ff2656..62cf7ccdde73 100644
--- a/arch/arm/crypto/nhpoly1305-neon-glue.c
+++ b/arch/arm/crypto/nhpoly1305-neon-glue.c
@@ -34,6 +34,14 @@ static int nhpoly1305_neon_update(struct shash_desc *desc,
return 0;
}
+static int nhpoly1305_neon_digest(struct shash_desc *desc,
+ const u8 *src, unsigned int srclen, u8 *out)
+{
+ return crypto_nhpoly1305_init(desc) ?:
+ nhpoly1305_neon_update(desc, src, srclen) ?:
+ crypto_nhpoly1305_final(desc, out);
+}
+
static struct shash_alg nhpoly1305_alg = {
.base.cra_name = "nhpoly1305",
.base.cra_driver_name = "nhpoly1305-neon",
@@ -44,6 +52,7 @@ static struct shash_alg nhpoly1305_alg = {
.init = crypto_nhpoly1305_init,
.update = nhpoly1305_neon_update,
.final = crypto_nhpoly1305_final,
+ .digest = nhpoly1305_neon_digest,
.setkey = crypto_nhpoly1305_setkey,
.descsize = sizeof(struct nhpoly1305_state),
};
diff --git a/arch/arm/include/asm/arm_pmuv3.h b/arch/arm/include/asm/arm_pmuv3.h
index 72529f5e2bed..a41b503b7dcd 100644
--- a/arch/arm/include/asm/arm_pmuv3.h
+++ b/arch/arm/include/asm/arm_pmuv3.h
@@ -23,6 +23,8 @@
#define PMUSERENR __ACCESS_CP15(c9, 0, c14, 0)
#define PMINTENSET __ACCESS_CP15(c9, 0, c14, 1)
#define PMINTENCLR __ACCESS_CP15(c9, 0, c14, 2)
+#define PMCEID2 __ACCESS_CP15(c9, 0, c14, 4)
+#define PMCEID3 __ACCESS_CP15(c9, 0, c14, 5)
#define PMMIR __ACCESS_CP15(c9, 0, c14, 6)
#define PMCCFILTR __ACCESS_CP15(c14, 0, c15, 7)
@@ -150,21 +152,6 @@ static inline u64 read_pmccntr(void)
return read_sysreg(PMCCNTR);
}
-static inline void write_pmxevcntr(u32 val)
-{
- write_sysreg(val, PMXEVCNTR);
-}
-
-static inline u32 read_pmxevcntr(void)
-{
- return read_sysreg(PMXEVCNTR);
-}
-
-static inline void write_pmxevtyper(u32 val)
-{
- write_sysreg(val, PMXEVTYPER);
-}
-
static inline void write_pmcntenset(u32 val)
{
write_sysreg(val, PMCNTENSET);
@@ -205,16 +192,6 @@ static inline void write_pmuserenr(u32 val)
write_sysreg(val, PMUSERENR);
}
-static inline u32 read_pmceid0(void)
-{
- return read_sysreg(PMCEID0);
-}
-
-static inline u32 read_pmceid1(void)
-{
- return read_sysreg(PMCEID1);
-}
-
static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {}
static inline void kvm_clr_pmu_events(u32 clr) {}
static inline bool kvm_pmu_counter_deferred(struct perf_event_attr *attr)
@@ -231,6 +208,7 @@ static inline void kvm_vcpu_pmu_resync_el0(void) {}
/* PMU Version in DFR Register */
#define ARMV8_PMU_DFR_VER_NI 0
+#define ARMV8_PMU_DFR_VER_V3P1 0x4
#define ARMV8_PMU_DFR_VER_V3P4 0x5
#define ARMV8_PMU_DFR_VER_V3P5 0x6
#define ARMV8_PMU_DFR_VER_IMP_DEF 0xF
@@ -251,4 +229,24 @@ static inline bool is_pmuv3p5(int pmuver)
return pmuver >= ARMV8_PMU_DFR_VER_V3P5;
}
+static inline u64 read_pmceid0(void)
+{
+ u64 val = read_sysreg(PMCEID0);
+
+ if (read_pmuver() >= ARMV8_PMU_DFR_VER_V3P1)
+ val |= (u64)read_sysreg(PMCEID2) << 32;
+
+ return val;
+}
+
+static inline u64 read_pmceid1(void)
+{
+ u64 val = read_sysreg(PMCEID1);
+
+ if (read_pmuver() >= ARMV8_PMU_DFR_VER_V3P1)
+ val |= (u64)read_sysreg(PMCEID3) << 32;
+
+ return val;
+}
+
#endif
diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h
index c6aded1b069c..e2a1916013e7 100644
--- a/arch/arm/include/asm/dma.h
+++ b/arch/arm/include/asm/dma.h
@@ -12,6 +12,9 @@
extern phys_addr_t arm_dma_zone_size; \
arm_dma_zone_size && arm_dma_zone_size < (0x100000000ULL - PAGE_OFFSET) ? \
(PAGE_OFFSET + arm_dma_zone_size) : 0xffffffffUL; })
+
+extern phys_addr_t arm_dma_limit;
+#define ARCH_LOW_ADDRESS_LIMIT arm_dma_limit
#endif
#ifdef CONFIG_ISA_DMA_API
diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h
index 41536feb4392..d48859fdf32c 100644
--- a/arch/arm/include/asm/domain.h
+++ b/arch/arm/include/asm/domain.h
@@ -8,8 +8,8 @@
#define __ASM_PROC_DOMAIN_H
#ifndef __ASSEMBLY__
+#include <linux/thread_info.h>
#include <asm/barrier.h>
-#include <asm/thread_info.h>
#endif
/*
diff --git a/arch/arm/include/asm/exception.h b/arch/arm/include/asm/exception.h
index 58e039a851af..3c82975d46db 100644
--- a/arch/arm/include/asm/exception.h
+++ b/arch/arm/include/asm/exception.h
@@ -10,10 +10,6 @@
#include <linux/interrupt.h>
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
#define __exception_irq_entry __irq_entry
-#else
-#define __exception_irq_entry
-#endif
#endif /* __ASM_ARM_EXCEPTION_H */
diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h
index e62832dcba76..a8287e7ab9d4 100644
--- a/arch/arm/include/asm/kexec.h
+++ b/arch/arm/include/asm/kexec.h
@@ -2,8 +2,6 @@
#ifndef _ARM_KEXEC_H
#define _ARM_KEXEC_H
-#ifdef CONFIG_KEXEC
-
/* Maximum physical address we can use pages from */
#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
/* Maximum address we can reach in physical address mode */
@@ -82,6 +80,4 @@ static inline struct page *boot_pfn_to_page(unsigned long boot_pfn)
#endif /* __ASSEMBLY__ */
-#endif /* CONFIG_KEXEC */
-
#endif /* _ARM_KEXEC_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index e26a278d301a..5b8dbf1b0be4 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -40,8 +40,6 @@ struct kprobe_ctlblk {
void arch_remove_kprobe(struct kprobe *);
int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
-int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
/* optinsn template addresses */
extern __visible kprobe_opcode_t optprobe_template_entry[];
diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h
index 546af8b1e3f6..cc106f946c69 100644
--- a/arch/arm/include/asm/setup.h
+++ b/arch/arm/include/asm/setup.h
@@ -11,6 +11,7 @@
#ifndef __ASMARM_SETUP_H
#define __ASMARM_SETUP_H
+#include <linux/screen_info.h>
#include <uapi/asm/setup.h>
@@ -35,4 +36,8 @@ void early_mm_init(const struct machine_desc *);
void adjust_lowmem_bounds(void);
void setup_dma_zone(const struct machine_desc *desc);
+#ifdef CONFIG_VGA_CONSOLE
+extern struct screen_info vgacon_screen_info;
+#endif
+
#endif
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h
index 0aaefe3e1700..2621b9fb9b19 100644
--- a/arch/arm/include/asm/traps.h
+++ b/arch/arm/include/asm/traps.h
@@ -2,6 +2,7 @@
#ifndef _ASMARM_TRAP_H
#define _ASMARM_TRAP_H
+#include <linux/linkage.h>
#include <linux/list.h>
struct pt_regs;
@@ -28,7 +29,7 @@ static inline int __in_irqentry_text(unsigned long ptr)
ptr < (unsigned long)&__irqentry_text_end;
}
-extern void __init early_trap_init(void *);
+extern void early_trap_init(void *);
extern void dump_backtrace_entry(unsigned long where, unsigned long from,
unsigned long frame, const char *loglvl);
extern void ptrace_break(struct pt_regs *regs);
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index bb5c81823117..9556d04387f7 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -8,6 +8,7 @@
/*
* User space memory access functions
*/
+#include <linux/kernel.h>
#include <linux/string.h>
#include <asm/page.h>
#include <asm/domain.h>
@@ -109,16 +110,6 @@ extern int __get_user_64t_1(void *);
extern int __get_user_64t_2(void *);
extern int __get_user_64t_4(void *);
-#define __GUP_CLOBBER_1 "lr", "cc"
-#ifdef CONFIG_CPU_USE_DOMAINS
-#define __GUP_CLOBBER_2 "ip", "lr", "cc"
-#else
-#define __GUP_CLOBBER_2 "lr", "cc"
-#endif
-#define __GUP_CLOBBER_4 "lr", "cc"
-#define __GUP_CLOBBER_32t_8 "lr", "cc"
-#define __GUP_CLOBBER_8 "lr", "cc"
-
#define __get_user_x(__r2, __p, __e, __l, __s) \
__asm__ __volatile__ ( \
__asmeq("%0", "r0") __asmeq("%1", "r2") \
@@ -126,7 +117,7 @@ extern int __get_user_64t_4(void *);
"bl __get_user_" #__s \
: "=&r" (__e), "=r" (__r2) \
: "0" (__p), "r" (__l) \
- : __GUP_CLOBBER_##__s)
+ : "ip", "lr", "cc")
/* narrowing a double-word get into a single 32bit word register: */
#ifdef __ARMEB__
@@ -148,7 +139,7 @@ extern int __get_user_64t_4(void *);
"bl __get_user_64t_" #__s \
: "=&r" (__e), "=r" (__r2) \
: "0" (__p), "r" (__l) \
- : __GUP_CLOBBER_##__s)
+ : "ip", "lr", "cc")
#else
#define __get_user_x_64t __get_user_x
#endif
diff --git a/arch/arm/include/asm/vga.h b/arch/arm/include/asm/vga.h
index 7c0bee57855a..6c430ec371df 100644
--- a/arch/arm/include/asm/vga.h
+++ b/arch/arm/include/asm/vga.h
@@ -5,6 +5,7 @@
#include <linux/io.h>
extern unsigned long vga_base;
+extern struct screen_info vgacon_screen_info;
#define VGA_MAP_MEM(x,s) (vga_base + (x))
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index d53f56d6f840..771264d4726a 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -59,7 +59,7 @@ obj-$(CONFIG_FUNCTION_TRACER) += entry-ftrace.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o patch.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o patch.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o
# Main staffs in KPROBES are in arch/arm/probes/ .
obj-$(CONFIG_KPROBES) += patch.o insn.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
diff --git a/arch/arm/kernel/atags_parse.c b/arch/arm/kernel/atags_parse.c
index 33f6eb5213a5..4ec591bde3df 100644
--- a/arch/arm/kernel/atags_parse.c
+++ b/arch/arm/kernel/atags_parse.c
@@ -69,18 +69,18 @@ static int __init parse_tag_mem32(const struct tag *tag)
__tagtable(ATAG_MEM, parse_tag_mem32);
-#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
+#if defined(CONFIG_ARCH_FOOTBRIDGE) && defined(CONFIG_VGA_CONSOLE)
static int __init parse_tag_videotext(const struct tag *tag)
{
- screen_info.orig_x = tag->u.videotext.x;
- screen_info.orig_y = tag->u.videotext.y;
- screen_info.orig_video_page = tag->u.videotext.video_page;
- screen_info.orig_video_mode = tag->u.videotext.video_mode;
- screen_info.orig_video_cols = tag->u.videotext.video_cols;
- screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
- screen_info.orig_video_lines = tag->u.videotext.video_lines;
- screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
- screen_info.orig_video_points = tag->u.videotext.video_points;
+ vgacon_screen_info.orig_x = tag->u.videotext.x;
+ vgacon_screen_info.orig_y = tag->u.videotext.y;
+ vgacon_screen_info.orig_video_page = tag->u.videotext.video_page;
+ vgacon_screen_info.orig_video_mode = tag->u.videotext.video_mode;
+ vgacon_screen_info.orig_video_cols = tag->u.videotext.video_cols;
+ vgacon_screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
+ vgacon_screen_info.orig_video_lines = tag->u.videotext.video_lines;
+ vgacon_screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
+ vgacon_screen_info.orig_video_points = tag->u.videotext.video_points;
return 0;
}
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index 264827281113..fdb74e64206a 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -13,7 +13,6 @@
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/of_irq.h>
-#include <linux/of_platform.h>
#include <linux/smp.h>
#include <asm/cputype.h>
diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c
index e94655ef16bb..6f9ec7d28a71 100644
--- a/arch/arm/kernel/efi.c
+++ b/arch/arm/kernel/efi.c
@@ -123,12 +123,6 @@ void __init arm_efi_init(void)
{
efi_init();
- if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI) {
- /* dummycon on ARM needs non-zero values for columns/lines */
- screen_info.orig_video_cols = 80;
- screen_info.orig_video_lines = 25;
- }
-
/* ARM does not permit early mappings to persist across paging_init() */
efi_memmap_unmap();
diff --git a/arch/arm/kernel/isa.c b/arch/arm/kernel/isa.c
index 20218876bef2..905b1b191546 100644
--- a/arch/arm/kernel/isa.c
+++ b/arch/arm/kernel/isa.c
@@ -16,7 +16,7 @@
static unsigned int isa_membase, isa_portbase, isa_portshift;
-static struct ctl_table ctl_isa_vars[4] = {
+static struct ctl_table ctl_isa_vars[] = {
{
.procname = "membase",
.data = &isa_membase,
@@ -35,7 +35,7 @@ static struct ctl_table ctl_isa_vars[4] = {
.maxlen = sizeof(isa_portshift),
.mode = 0444,
.proc_handler = proc_dointvec,
- }, {}
+ },
};
static struct ctl_table_header *isa_sysctl_header;
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index c66b560562b3..ff2299ce1ad7 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -15,10 +15,10 @@
#include <linux/console.h>
#include <linux/seq_file.h>
#include <linux/screen_info.h>
-#include <linux/of_platform.h>
#include <linux/init.h>
#include <linux/kexec.h>
#include <linux/libfdt.h>
+#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/cpu.h>
#include <linux/interrupt.h>
@@ -928,9 +928,8 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)
request_resource(&ioport_resource, &lp2);
}
-#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) || \
- defined(CONFIG_EFI)
-struct screen_info screen_info = {
+#if defined(CONFIG_VGA_CONSOLE)
+struct screen_info vgacon_screen_info = {
.orig_video_lines = 30,
.orig_video_cols = 80,
.orig_video_mode = 0,
@@ -1010,7 +1009,8 @@ static void __init reserve_crashkernel(void)
total_mem = get_total_mem();
ret = parse_crashkernel(boot_command_line, total_mem,
- &crash_size, &crash_base);
+ &crash_size, &crash_base,
+ NULL, NULL);
/* invalid value specified or crashkernel=0 */
if (ret || !crash_size)
return;
@@ -1193,7 +1193,7 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
- conswitchp = &vga_con;
+ vgacon_register_screen(&vgacon_screen_info);
#endif
#endif
diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S
index d71ab61430b2..de75ae4d5ab4 100644
--- a/arch/arm/lib/memset.S
+++ b/arch/arm/lib/memset.S
@@ -17,6 +17,7 @@ ENTRY(__memset)
ENTRY(mmioset)
WEAK(memset)
UNWIND( .fnstart )
+ and r1, r1, #255 @ cast to unsigned char
ands r3, r0, #3 @ 1 unaligned?
mov ip, r0 @ preserve r0 as return value
bne 6f @ 1
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
index 2157493b78a9..df69af932375 100644
--- a/arch/arm/mach-imx/mmdc.c
+++ b/arch/arm/mach-imx/mmdc.c
@@ -501,6 +501,10 @@ static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_b
name = devm_kasprintf(&pdev->dev,
GFP_KERNEL, "mmdc%d", ret);
+ if (!name) {
+ ret = -ENOMEM;
+ goto pmu_release_id;
+ }
pmu_mmdc->mmdc_ipg_clk = mmdc_ipg_clk;
pmu_mmdc->devtype_data = (struct fsl_mmdc_devtype_data *)of_id->data;
@@ -523,9 +527,10 @@ static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_b
pmu_register_err:
pr_warn("MMDC Perf PMU failed (%d), disabled\n", ret);
- ida_simple_remove(&mmdc_ida, pmu_mmdc->id);
cpuhp_state_remove_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node);
hrtimer_cancel(&pmu_mmdc->hrtimer);
+pmu_release_id:
+ ida_simple_remove(&mmdc_ida, pmu_mmdc->id);
pmu_free:
kfree(pmu_mmdc);
return ret;
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 9808cd27e2cf..0daf6c5b5c1c 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -550,6 +550,7 @@ static struct platform_device *ams_delta_devices[] __initdata = {
&ams_delta_nand_device,
&ams_delta_lcd_device,
&cx20442_codec_device,
+ &modem_nreset_device,
};
static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = {
@@ -560,22 +561,6 @@ static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = {
&ams_delta_nand_gpio_table,
};
-/*
- * Some drivers may not use GPIO lookup tables but need to be provided
- * with GPIO numbers. The same applies to GPIO based IRQ lines - some
- * drivers may even not use GPIO layer but expect just IRQ numbers.
- * We could either define GPIO lookup tables then use them on behalf
- * of those devices, or we can use GPIO driver level methods for
- * identification of GPIO and IRQ numbers. For the purpose of the latter,
- * defina a helper function which identifies GPIO chips by their labels.
- */
-static int gpiochip_match_by_label(struct gpio_chip *chip, void *data)
-{
- char *label = data;
-
- return !strcmp(label, chip->label);
-}
-
static struct gpiod_hog ams_delta_gpio_hogs[] = {
GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT, "keybrd_dataout",
GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW),
@@ -615,14 +600,28 @@ static void __init modem_assign_irq(struct gpio_chip *chip)
*/
static void __init omap_gpio_deps_init(void)
{
+ struct gpio_device *gdev;
struct gpio_chip *chip;
- chip = gpiochip_find(OMAP_GPIO_LABEL, gpiochip_match_by_label);
- if (!chip) {
- pr_err("%s: OMAP GPIO chip not found\n", __func__);
+ /*
+ * Some drivers may not use GPIO lookup tables but need to be provided
+ * with GPIO numbers. The same applies to GPIO based IRQ lines - some
+ * drivers may even not use GPIO layer but expect just IRQ numbers.
+ * We could either define GPIO lookup tables then use them on behalf
+ * of those devices, or we can use GPIO driver level methods for
+ * identification of GPIO and IRQ numbers.
+ *
+ * This reference will be leaked but that's alright as this device
+ * never goes down.
+ */
+ gdev = gpio_device_find_by_label(OMAP_GPIO_LABEL);
+ if (!gdev) {
+ pr_err("%s: OMAP GPIO device not found\n", __func__);
return;
}
+ chip = gpio_device_get_chip(gdev);
+
/*
* Start with FIQ initialization as it may have to request
* and release successfully each OMAP GPIO pin in turn.
@@ -782,26 +781,28 @@ static struct plat_serial8250_port ams_delta_modem_ports[] = {
{ },
};
+static int ams_delta_modem_pm_activate(struct device *dev)
+{
+ modem_priv.regulator = regulator_get(dev, "RESET#");
+ if (IS_ERR(modem_priv.regulator))
+ return -EPROBE_DEFER;
+
+ return 0;
+}
+
+static struct dev_pm_domain ams_delta_modem_pm_domain = {
+ .activate = ams_delta_modem_pm_activate,
+};
+
static struct platform_device ams_delta_modem_device = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM1,
.dev = {
.platform_data = ams_delta_modem_ports,
+ .pm_domain = &ams_delta_modem_pm_domain,
},
};
-static int __init modem_nreset_init(void)
-{
- int err;
-
- err = platform_device_register(&modem_nreset_device);
- if (err)
- pr_err("Couldn't register the modem regulator device\n");
-
- return err;
-}
-
-
/*
* This function expects MODEM IRQ number already assigned to the port.
* The MODEM device requires its RESET# pin kept high during probe.
@@ -833,37 +834,6 @@ static int __init ams_delta_modem_init(void)
}
arch_initcall_sync(ams_delta_modem_init);
-static int __init late_init(void)
-{
- int err;
-
- err = modem_nreset_init();
- if (err)
- return err;
-
- /*
- * Once the modem device is registered, the modem_nreset
- * regulator can be requested on behalf of that device.
- */
- modem_priv.regulator = regulator_get(&ams_delta_modem_device.dev,
- "RESET#");
- if (IS_ERR(modem_priv.regulator)) {
- err = PTR_ERR(modem_priv.regulator);
- goto unregister;
- }
- return 0;
-
-unregister:
- platform_device_unregister(&ams_delta_modem_device);
- return err;
-}
-
-static void __init ams_delta_init_late(void)
-{
- omap1_init_late();
- late_init();
-}
-
static void __init ams_delta_map_io(void)
{
omap1_map_io();
@@ -877,7 +847,7 @@ MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
.init_early = omap1_init_early,
.init_irq = omap1_init_irq,
.init_machine = ams_delta_init,
- .init_late = ams_delta_init_late,
+ .init_late = omap1_init_late,
.init_time = omap1_timer_init,
.restart = omap1_restart,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 7e061d671fde..c917cb2c6e17 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -51,11 +51,6 @@
#define PALMTE_HDQ_GPIO 11
#define PALMTE_HEADPHONES_GPIO 14
#define PALMTE_SPEAKER_GPIO 15
-#define PALMTE_DC_GPIO OMAP_MPUIO(2)
-#define PALMTE_MMC_SWITCH_GPIO OMAP_MPUIO(4)
-#define PALMTE_MMC1_GPIO OMAP_MPUIO(6)
-#define PALMTE_MMC2_GPIO OMAP_MPUIO(7)
-#define PALMTE_MMC3_GPIO OMAP_MPUIO(11)
static const unsigned int palmte_keymap[] = {
KEY(0, 0, KEY_F1), /* Calendar */
diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index 410d17d1d443..f618a6df2938 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -176,17 +176,18 @@ static u64 notrace omap_32k_read_sched_clock(void)
return sync32k_cnt_reg ? readl_relaxed(sync32k_cnt_reg) : 0;
}
+static struct timespec64 persistent_ts;
+static cycles_t cycles;
+static unsigned int persistent_mult, persistent_shift;
+
/**
* omap_read_persistent_clock64 - Return time from a persistent clock.
+ * @ts: &struct timespec64 for the returned time
*
* Reads the time from a source which isn't disabled during PM, the
* 32k sync timer. Convert the cycles elapsed since last read into
* nsecs and adds to a monotonically increasing timespec64.
*/
-static struct timespec64 persistent_ts;
-static cycles_t cycles;
-static unsigned int persistent_mult, persistent_shift;
-
static void omap_read_persistent_clock64(struct timespec64 *ts)
{
unsigned long long nsecs;
@@ -206,10 +207,9 @@ static void omap_read_persistent_clock64(struct timespec64 *ts)
/**
* omap_init_clocksource_32k - setup and register counter 32k as a
* kernel clocksource
- * @pbase: base addr of counter_32k module
- * @size: size of counter_32k to map
+ * @vbase: base addr of counter_32k module
*
- * Returns 0 upon success or negative error code upon failure.
+ * Returns: %0 upon success or negative error code upon failure.
*
*/
static int __init omap_init_clocksource_32k(void __iomem *vbase)
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 8e3b5068d4ab..31755a378c73 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -498,6 +498,15 @@ struct menelaus_platform_data n8x0_menelaus_platform_data = {
.late_init = n8x0_menelaus_late_init,
};
+static struct gpiod_lookup_table nokia810_asoc_gpio_table = {
+ .dev_id = "soc-audio",
+ .table = {
+ GPIO_LOOKUP("gpio-0-15", 10, "headset", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("gpio-80-111", 21, "speaker", GPIO_ACTIVE_HIGH),
+ { }
+ },
+};
+
static int __init n8x0_late_initcall(void)
{
if (!board_caps)
@@ -505,6 +514,7 @@ static int __init n8x0_late_initcall(void)
n8x0_mmc_init();
n8x0_usb_init();
+ gpiod_add_lookup_table(&nokia810_asoc_gpio_table);
return 0;
}
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 1e17b5f77588..ba71928c0fcb 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2209,7 +2209,7 @@ int omap_hwmod_parse_module_range(struct omap_hwmod *oh,
return err;
pr_debug("omap_hwmod: %s %pOFn at %pR\n",
- oh->name, np, &res);
+ oh->name, np, res);
if (oh && oh->mpu_rt_idx) {
omap_hwmod_fix_mpu_rt_idx(oh, np, res);
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index c1c0121f478d..b947bacf23a3 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -275,9 +275,19 @@ static struct platform_device pandora_backlight = {
.id = -1,
};
+static struct gpiod_lookup_table pandora_soc_audio_gpios = {
+ .dev_id = "soc-audio",
+ .table = {
+ GPIO_LOOKUP("gpio-112-127", 6, "dac", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("gpio-0-15", 14, "amp", GPIO_ACTIVE_HIGH),
+ { }
+ },
+};
+
static void __init omap3_pandora_legacy_init(void)
{
platform_device_register(&pandora_backlight);
+ gpiod_add_lookup_table(&pandora_soc_audio_gpios);
}
#endif /* CONFIG_ARCH_OMAP3 */
diff --git a/arch/arm/mach-shmobile/pm-rcar-gen2.c b/arch/arm/mach-shmobile/pm-rcar-gen2.c
index 672081405a7e..907a4f8c5aed 100644
--- a/arch/arm/mach-shmobile/pm-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/pm-rcar-gen2.c
@@ -46,15 +46,16 @@ void __init rcar_gen2_pm_init(void)
{
void __iomem *p;
u32 bar;
- static int once;
struct device_node *np;
bool has_a7 = false;
bool has_a15 = false;
struct resource res;
int error;
- if (once++)
+ if (!request_mem_region(0, SZ_256K, "Boot Area")) {
+ pr_err("Failed to request boot area\n");
return;
+ }
for_each_of_cpu_node(np) {
if (of_device_is_compatible(np, "arm,cortex-a15"))
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index 1bc609986c16..474c325323a3 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -38,7 +38,14 @@ static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
{
- void __iomem *base = ioremap(HPBREG_BASE, 0x1000);
+ void __iomem *base;
+
+ if (!request_mem_region(0, SZ_4K, "Boot Area")) {
+ pr_err("Failed to request boot area\n");
+ return;
+ }
+
+ base = ioremap(HPBREG_BASE, 0x1000);
/* Map the reset vector (in headsmp-scu.S, headsmp.S) */
writel(__pa(shmobile_boot_vector), base + AVECR);
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index 453d48865029..9196b37ea292 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -44,10 +44,16 @@ static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
{
- void __iomem *ap = ioremap(AP_BASE, PAGE_SIZE);
- void __iomem *sysc = ioremap(SYSC_BASE, PAGE_SIZE);
+ void __iomem *ap, *sysc;
+
+ if (!request_mem_region(0, SZ_4K, "Boot Area")) {
+ pr_err("Failed to request boot area\n");
+ return;
+ }
/* Map the reset vector (in headsmp.S) */
+ ap = ioremap(AP_BASE, PAGE_SIZE);
+ sysc = ioremap(SYSC_BASE, PAGE_SIZE);
writel(0, ap + APARMBAREA); /* 4k */
writel(__pa(shmobile_boot_vector), sysc + SBAR);
iounmap(sysc);
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 6a1c9fca5260..1d672457d02f 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -2,6 +2,7 @@
/*
* Just-In-Time compiler for eBPF filters on 32bit ARM
*
+ * Copyright (c) 2023 Puranjay Mohan <puranjay12@gmail.com>
* Copyright (c) 2017 Shubham Bansal <illusionist.neo@gmail.com>
* Copyright (c) 2011 Mircea Gherzan <mgherzan@gmail.com>
*/
@@ -15,6 +16,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/if_vlan.h>
+#include <linux/math64.h>
#include <asm/cacheflush.h>
#include <asm/hwcap.h>
@@ -228,6 +230,44 @@ static u32 jit_mod32(u32 dividend, u32 divisor)
return dividend % divisor;
}
+static s32 jit_sdiv32(s32 dividend, s32 divisor)
+{
+ return dividend / divisor;
+}
+
+static s32 jit_smod32(s32 dividend, s32 divisor)
+{
+ return dividend % divisor;
+}
+
+/* Wrappers for 64-bit div/mod */
+static u64 jit_udiv64(u64 dividend, u64 divisor)
+{
+ return div64_u64(dividend, divisor);
+}
+
+static u64 jit_mod64(u64 dividend, u64 divisor)
+{
+ u64 rem;
+
+ div64_u64_rem(dividend, divisor, &rem);
+ return rem;
+}
+
+static s64 jit_sdiv64(s64 dividend, s64 divisor)
+{
+ return div64_s64(dividend, divisor);
+}
+
+static s64 jit_smod64(s64 dividend, s64 divisor)
+{
+ u64 q;
+
+ q = div64_s64(dividend, divisor);
+
+ return dividend - q * divisor;
+}
+
static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx)
{
inst |= (cond << 28);
@@ -333,6 +373,9 @@ static u32 arm_bpf_ldst_imm8(u32 op, u8 rt, u8 rn, s16 imm8)
#define ARM_LDRD_I(rt, rn, off) arm_bpf_ldst_imm8(ARM_INST_LDRD_I, rt, rn, off)
#define ARM_LDRH_I(rt, rn, off) arm_bpf_ldst_imm8(ARM_INST_LDRH_I, rt, rn, off)
+#define ARM_LDRSH_I(rt, rn, off) arm_bpf_ldst_imm8(ARM_INST_LDRSH_I, rt, rn, off)
+#define ARM_LDRSB_I(rt, rn, off) arm_bpf_ldst_imm8(ARM_INST_LDRSB_I, rt, rn, off)
+
#define ARM_STR_I(rt, rn, off) arm_bpf_ldst_imm12(ARM_INST_STR_I, rt, rn, off)
#define ARM_STRB_I(rt, rn, off) arm_bpf_ldst_imm12(ARM_INST_STRB_I, rt, rn, off)
#define ARM_STRD_I(rt, rn, off) arm_bpf_ldst_imm8(ARM_INST_STRD_I, rt, rn, off)
@@ -474,17 +517,18 @@ static inline int epilogue_offset(const struct jit_ctx *ctx)
return to - from - 2;
}
-static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op)
+static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op, u8 sign)
{
const int exclude_mask = BIT(ARM_R0) | BIT(ARM_R1);
const s8 *tmp = bpf2a32[TMP_REG_1];
+ u32 dst;
#if __LINUX_ARM_ARCH__ == 7
if (elf_hwcap & HWCAP_IDIVA) {
- if (op == BPF_DIV)
- emit(ARM_UDIV(rd, rm, rn), ctx);
- else {
- emit(ARM_UDIV(ARM_IP, rm, rn), ctx);
+ if (op == BPF_DIV) {
+ emit(sign ? ARM_SDIV(rd, rm, rn) : ARM_UDIV(rd, rm, rn), ctx);
+ } else {
+ emit(sign ? ARM_SDIV(ARM_IP, rm, rn) : ARM_UDIV(ARM_IP, rm, rn), ctx);
emit(ARM_MLS(rd, rn, ARM_IP, rm), ctx);
}
return;
@@ -512,8 +556,19 @@ static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op)
emit(ARM_PUSH(CALLER_MASK & ~exclude_mask), ctx);
/* Call appropriate function */
- emit_mov_i(ARM_IP, op == BPF_DIV ?
- (u32)jit_udiv32 : (u32)jit_mod32, ctx);
+ if (sign) {
+ if (op == BPF_DIV)
+ dst = (u32)jit_sdiv32;
+ else
+ dst = (u32)jit_smod32;
+ } else {
+ if (op == BPF_DIV)
+ dst = (u32)jit_udiv32;
+ else
+ dst = (u32)jit_mod32;
+ }
+
+ emit_mov_i(ARM_IP, dst, ctx);
emit_blx_r(ARM_IP, ctx);
/* Restore caller-saved registers from stack */
@@ -530,6 +585,78 @@ static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op)
emit(ARM_MOV_R(ARM_R0, tmp[1]), ctx);
}
+static inline void emit_udivmod64(const s8 *rd, const s8 *rm, const s8 *rn, struct jit_ctx *ctx,
+ u8 op, u8 sign)
+{
+ u32 dst;
+
+ /* Push caller-saved registers on stack */
+ emit(ARM_PUSH(CALLER_MASK), ctx);
+
+ /*
+ * As we are implementing 64-bit div/mod as function calls, We need to put the dividend in
+ * R0-R1 and the divisor in R2-R3. As we have already pushed these registers on the stack,
+ * we can recover them later after returning from the function call.
+ */
+ if (rm[1] != ARM_R0 || rn[1] != ARM_R2) {
+ /*
+ * Move Rm to {R1, R0} if it is not already there.
+ */
+ if (rm[1] != ARM_R0) {
+ if (rn[1] == ARM_R0)
+ emit(ARM_PUSH(BIT(ARM_R0) | BIT(ARM_R1)), ctx);
+ emit(ARM_MOV_R(ARM_R1, rm[0]), ctx);
+ emit(ARM_MOV_R(ARM_R0, rm[1]), ctx);
+ if (rn[1] == ARM_R0) {
+ emit(ARM_POP(BIT(ARM_R2) | BIT(ARM_R3)), ctx);
+ goto cont;
+ }
+ }
+ /*
+ * Move Rn to {R3, R2} if it is not already there.
+ */
+ if (rn[1] != ARM_R2) {
+ emit(ARM_MOV_R(ARM_R3, rn[0]), ctx);
+ emit(ARM_MOV_R(ARM_R2, rn[1]), ctx);
+ }
+ }
+
+cont:
+
+ /* Call appropriate function */
+ if (sign) {
+ if (op == BPF_DIV)
+ dst = (u32)jit_sdiv64;
+ else
+ dst = (u32)jit_smod64;
+ } else {
+ if (op == BPF_DIV)
+ dst = (u32)jit_udiv64;
+ else
+ dst = (u32)jit_mod64;
+ }
+
+ emit_mov_i(ARM_IP, dst, ctx);
+ emit_blx_r(ARM_IP, ctx);
+
+ /* Save return value */
+ if (rd[1] != ARM_R0) {
+ emit(ARM_MOV_R(rd[0], ARM_R1), ctx);
+ emit(ARM_MOV_R(rd[1], ARM_R0), ctx);
+ }
+
+ /* Recover {R3, R2} and {R1, R0} from stack if they are not Rd */
+ if (rd[1] != ARM_R0 && rd[1] != ARM_R2) {
+ emit(ARM_POP(CALLER_MASK), ctx);
+ } else if (rd[1] != ARM_R0) {
+ emit(ARM_POP(BIT(ARM_R0) | BIT(ARM_R1)), ctx);
+ emit(ARM_ADD_I(ARM_SP, ARM_SP, 8), ctx);
+ } else {
+ emit(ARM_ADD_I(ARM_SP, ARM_SP, 8), ctx);
+ emit(ARM_POP(BIT(ARM_R2) | BIT(ARM_R3)), ctx);
+ }
+}
+
/* Is the translated BPF register on stack? */
static bool is_stacked(s8 reg)
{
@@ -744,12 +871,16 @@ 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,
+static inline void emit_a32_mov_r(const s8 dst, const s8 src, const u8 off,
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);
}
@@ -758,15 +889,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, ctx);
+ emit_a32_mov_r(dst_lo, src_lo, 0, 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, ctx);
- emit_a32_mov_r(dst_hi, src_hi, ctx);
+ emit_a32_mov_r(dst_lo, src_lo, 0, ctx);
+ emit_a32_mov_r(dst_hi, src_hi, 0, ctx);
} else if (is_stacked(src_lo) && is_stacked(dst_lo)) {
const u8 *tmp = bpf2a32[TMP_REG_1];
@@ -782,6 +913,24 @@ static inline void emit_a32_mov_r64(const bool is64, const s8 dst[],
}
}
+/* dst = (signed)src */
+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;
+
+ rt = arm_bpf_get_reg64(dst, tmp, 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);
+ }
+}
+
/* Shift operations */
static inline void emit_a32_alu_i(const s8 dst, const u32 val,
struct jit_ctx *ctx, const u8 op) {
@@ -1026,6 +1175,24 @@ static bool is_ldst_imm(s16 off, const u8 size)
return -off_max <= off && off <= off_max;
}
+static bool is_ldst_imm8(s16 off, const u8 size)
+{
+ s16 off_max = 0;
+
+ switch (size) {
+ case BPF_B:
+ off_max = 0xff;
+ break;
+ case BPF_W:
+ off_max = 0xfff;
+ break;
+ case BPF_H:
+ off_max = 0xff;
+ break;
+ }
+ return -off_max <= off && off <= off_max;
+}
+
/* *(size *)(dst + off) = src */
static inline void emit_str_r(const s8 dst, const s8 src[],
s16 off, struct jit_ctx *ctx, const u8 sz){
@@ -1105,6 +1272,50 @@ static inline void emit_ldx_r(const s8 dst[], const s8 src,
arm_bpf_put_reg64(dst, rd, ctx);
}
+/* dst = *(signed size*)(src + off) */
+static inline void emit_ldsx_r(const s8 dst[], const s8 src,
+ s16 off, struct jit_ctx *ctx, const u8 sz){
+ const s8 *tmp = bpf2a32[TMP_REG_1];
+ const s8 *rd = is_stacked(dst_lo) ? tmp : dst;
+ s8 rm = src;
+ int add_off;
+
+ if (!is_ldst_imm8(off, sz)) {
+ /*
+ * offset does not fit in the load/store immediate,
+ * construct an ADD instruction to apply the offset.
+ */
+ add_off = imm8m(off);
+ if (add_off > 0) {
+ emit(ARM_ADD_I(tmp[0], src, add_off), ctx);
+ rm = tmp[0];
+ } else {
+ emit_a32_mov_i(tmp[0], off, ctx);
+ emit(ARM_ADD_R(tmp[0], tmp[0], src), ctx);
+ rm = tmp[0];
+ }
+ off = 0;
+ }
+
+ switch (sz) {
+ case BPF_B:
+ /* Load a Byte with sign extension*/
+ emit(ARM_LDRSB_I(rd[1], rm, off), ctx);
+ break;
+ case BPF_H:
+ /* Load a HalfWord with sign extension*/
+ emit(ARM_LDRSH_I(rd[1], rm, off), ctx);
+ break;
+ case BPF_W:
+ /* Load a Word*/
+ emit(ARM_LDR_I(rd[1], rm, off), ctx);
+ break;
+ }
+ /* Carry the sign extension to upper 32 bits */
+ emit(ARM_ASR_I(rd[0], rd[1], 31), ctx);
+ arm_bpf_put_reg64(dst, rd, ctx);
+}
+
/* Arithmatic Operation */
static inline void emit_ar_r(const u8 rd, const u8 rt, const u8 rm,
const u8 rn, struct jit_ctx *ctx, u8 op,
@@ -1385,7 +1596,10 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
emit_a32_mov_i(dst_hi, 0, ctx);
break;
}
- emit_a32_mov_r64(is64, dst, src, ctx);
+ if (insn->off)
+ emit_a32_movsx_r64(is64, insn->off, dst, src, ctx);
+ else
+ emit_a32_mov_r64(is64, dst, src, ctx);
break;
case BPF_K:
/* Sign-extend immediate value to destination reg */
@@ -1461,7 +1675,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
rt = src_lo;
break;
}
- emit_udivmod(rd_lo, rd_lo, rt, ctx, BPF_OP(code));
+ emit_udivmod(rd_lo, rd_lo, rt, ctx, BPF_OP(code), off);
arm_bpf_put_reg32(dst_lo, rd_lo, ctx);
if (!ctx->prog->aux->verifier_zext)
emit_a32_mov_i(dst_hi, 0, ctx);
@@ -1470,7 +1684,19 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
case BPF_ALU64 | BPF_DIV | BPF_X:
case BPF_ALU64 | BPF_MOD | BPF_K:
case BPF_ALU64 | BPF_MOD | BPF_X:
- goto notyet;
+ rd = arm_bpf_get_reg64(dst, tmp2, ctx);
+ switch (BPF_SRC(code)) {
+ case BPF_X:
+ rs = arm_bpf_get_reg64(src, tmp, ctx);
+ break;
+ case BPF_K:
+ rs = tmp;
+ emit_a32_mov_se_i64(is64, rs, imm, ctx);
+ break;
+ }
+ emit_udivmod64(rd, rd, rs, ctx, BPF_OP(code), off);
+ arm_bpf_put_reg64(dst, rd, ctx);
+ break;
/* dst = dst << imm */
/* dst = dst >> imm */
/* dst = dst >> imm (signed) */
@@ -1545,10 +1771,12 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
break;
/* dst = htole(dst) */
/* dst = htobe(dst) */
- case BPF_ALU | BPF_END | BPF_FROM_LE:
- case BPF_ALU | BPF_END | BPF_FROM_BE:
+ case BPF_ALU | BPF_END | BPF_FROM_LE: /* also BPF_TO_LE */
+ case BPF_ALU | BPF_END | BPF_FROM_BE: /* also BPF_TO_BE */
+ /* dst = bswap(dst) */
+ case BPF_ALU64 | BPF_END | BPF_FROM_LE: /* also BPF_TO_LE */
rd = arm_bpf_get_reg64(dst, tmp, ctx);
- if (BPF_SRC(code) == BPF_FROM_LE)
+ if (BPF_SRC(code) == BPF_FROM_LE && BPF_CLASS(code) != BPF_ALU64)
goto emit_bswap_uxt;
switch (imm) {
case 16:
@@ -1603,8 +1831,15 @@ exit:
case BPF_LDX | BPF_MEM | BPF_H:
case BPF_LDX | BPF_MEM | BPF_B:
case BPF_LDX | BPF_MEM | BPF_DW:
+ /* LDSX: dst = *(signed size *)(src + off) */
+ case BPF_LDX | BPF_MEMSX | BPF_B:
+ case BPF_LDX | BPF_MEMSX | BPF_H:
+ case BPF_LDX | BPF_MEMSX | BPF_W:
rn = arm_bpf_get_reg32(src_lo, tmp2[1], ctx);
- emit_ldx_r(dst, rn, off, ctx, BPF_SIZE(code));
+ if (BPF_MODE(insn->code) == BPF_MEMSX)
+ emit_ldsx_r(dst, rn, off, ctx, BPF_SIZE(code));
+ else
+ emit_ldx_r(dst, rn, off, ctx, BPF_SIZE(code));
break;
/* speculation barrier */
case BPF_ST | BPF_NOSPEC:
@@ -1761,10 +1996,15 @@ go_jmp:
break;
/* JMP OFF */
case BPF_JMP | BPF_JA:
+ case BPF_JMP32 | BPF_JA:
{
- if (off == 0)
+ if (BPF_CLASS(code) == BPF_JMP32 && imm != 0)
+ jmp_offset = bpf2a32_offset(i + imm, i, ctx);
+ else if (BPF_CLASS(code) == BPF_JMP && off != 0)
+ jmp_offset = bpf2a32_offset(i + off, i, ctx);
+ else
break;
- jmp_offset = bpf2a32_offset(i+off, i, ctx);
+
check_imm24(jmp_offset);
emit(ARM_B(jmp_offset), ctx);
break;
diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h
index e0b593a1498d..438f0e1f91a0 100644
--- a/arch/arm/net/bpf_jit_32.h
+++ b/arch/arm/net/bpf_jit_32.h
@@ -79,9 +79,11 @@
#define ARM_INST_LDST__IMM12 0x00000fff
#define ARM_INST_LDRB_I 0x05500000
#define ARM_INST_LDRB_R 0x07d00000
+#define ARM_INST_LDRSB_I 0x015000d0
#define ARM_INST_LDRD_I 0x014000d0
#define ARM_INST_LDRH_I 0x015000b0
#define ARM_INST_LDRH_R 0x019000b0
+#define ARM_INST_LDRSH_I 0x015000f0
#define ARM_INST_LDR_I 0x05100000
#define ARM_INST_LDR_R 0x07900000
@@ -137,6 +139,7 @@
#define ARM_INST_TST_I 0x03100000
#define ARM_INST_UDIV 0x0730f010
+#define ARM_INST_SDIV 0x0710f010
#define ARM_INST_UMULL 0x00800090
@@ -265,6 +268,7 @@
#define ARM_TST_I(rn, imm) _AL3_I(ARM_INST_TST, 0, rn, imm)
#define ARM_UDIV(rd, rn, rm) (ARM_INST_UDIV | (rd) << 16 | (rn) | (rm) << 8)
+#define ARM_SDIV(rd, rn, rm) (ARM_INST_SDIV | (rd) << 16 | (rn) | (rm) << 8)
#define ARM_UMULL(rd_lo, rd_hi, rn, rm) (ARM_INST_UMULL | (rd_hi) << 16 \
| (rd_lo) << 12 | (rm) << 8 | rn)
diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
index c572d6c3dee0..584f9528c996 100644
--- a/arch/arm/tools/syscall.tbl
+++ b/arch/arm/tools/syscall.tbl
@@ -263,7 +263,7 @@
246 common io_submit sys_io_submit
247 common io_cancel sys_io_cancel
248 common exit_group sys_exit_group
-249 common lookup_dcookie sys_lookup_dcookie
+249 common lookup_dcookie sys_ni_syscall
250 common epoll_create sys_epoll_create
251 common epoll_ctl sys_epoll_ctl sys_oabi_epoll_ctl
252 common epoll_wait sys_epoll_wait
@@ -466,3 +466,7 @@
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
451 common cachestat sys_cachestat
452 common fchmodat2 sys_fchmodat2
+453 common map_shadow_stack sys_map_shadow_stack
+454 common futex_wake sys_futex_wake
+455 common futex_wait sys_futex_wait
+456 common futex_requeue sys_futex_requeue
diff --git a/arch/arm/vdso/Makefile b/arch/arm/vdso/Makefile
index 515ca33b854c..d761bd2e2f40 100644
--- a/arch/arm/vdso/Makefile
+++ b/arch/arm/vdso/Makefile
@@ -63,28 +63,3 @@ quiet_cmd_vdsold_and_vdso_check = LD $@
quiet_cmd_vdsomunge = MUNGE $@
cmd_vdsomunge = $(objtree)/$(obj)/vdsomunge $< $@
-
-#
-# Install the unstripped copy of vdso.so.dbg. If our toolchain
-# supports build-id, install .build-id links as well.
-#
-# Cribbed from arch/x86/vdso/Makefile.
-#
-quiet_cmd_vdso_install = INSTALL $<
-define cmd_vdso_install
- cp $< "$(MODLIB)/vdso/vdso.so"; \
- if readelf -n $< | grep -q 'Build ID'; then \
- buildid=`readelf -n $< |grep 'Build ID' |sed -e 's/^.*Build ID: \(.*\)$$/\1/'`; \
- first=`echo $$buildid | cut -b-2`; \
- last=`echo $$buildid | cut -b3-`; \
- mkdir -p "$(MODLIB)/vdso/.build-id/$$first"; \
- ln -sf "../../vdso.so" "$(MODLIB)/vdso/.build-id/$$first/$$last.debug"; \
- fi
-endef
-
-$(MODLIB)/vdso: FORCE
- @mkdir -p $(MODLIB)/vdso
-
-PHONY += vdso_install
-vdso_install: $(obj)/vdso.so.dbg $(MODLIB)/vdso
- $(call cmd,vdso_install)
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index c392e18f1e43..a395b6c0aae2 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -164,9 +164,6 @@ static int xen_starting_cpu(unsigned int cpu)
BUG_ON(err);
per_cpu(xen_vcpu, cpu) = vcpup;
- if (!xen_kernel_unmapped_at_usr())
- xen_setup_runstate_info(cpu);
-
after_register_vcpu_info:
enable_percpu_irq(xen_events_irq, 0);
return 0;
@@ -487,7 +484,8 @@ static int __init xen_guest_init(void)
* for secondary CPUs as they are brought up.
* For uniformity we use VCPUOP_register_vcpu_info even on cpu0.
*/
- xen_vcpu_info = alloc_percpu(struct vcpu_info);
+ xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info),
+ 1 << fls(sizeof(struct vcpu_info) - 1));
if (xen_vcpu_info == NULL)
return -ENOMEM;
@@ -523,9 +521,6 @@ static int __init xen_guest_init(void)
return -EINVAL;
}
- if (!xen_kernel_unmapped_at_usr())
- xen_time_setup_guest();
-
if (xen_initial_domain())
pvclock_gtod_register_notifier(&xen_pvclock_gtod_notifier);
@@ -535,7 +530,13 @@ static int __init xen_guest_init(void)
}
early_initcall(xen_guest_init);
-static int __init xen_pm_init(void)
+static int xen_starting_runstate_cpu(unsigned int cpu)
+{
+ xen_setup_runstate_info(cpu);
+ return 0;
+}
+
+static int __init xen_late_init(void)
{
if (!xen_domain())
return -ENODEV;
@@ -548,9 +549,16 @@ static int __init xen_pm_init(void)
do_settimeofday64(&ts);
}
- return 0;
+ if (xen_kernel_unmapped_at_usr())
+ return 0;
+
+ xen_time_setup_guest();
+
+ return cpuhp_setup_state(CPUHP_AP_ARM_XEN_RUNSTATE_STARTING,
+ "arm/xen_runstate:starting",
+ xen_starting_runstate_cpu, NULL);
}
-late_initcall(xen_pm_init);
+late_initcall(xen_late_init);
/* empty stubs */
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 78f20e632712..7b071a00425d 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1368,6 +1368,8 @@ choice
config CPU_BIG_ENDIAN
bool "Build big-endian kernel"
depends on !LD_IS_LLD || LLD_VERSION >= 130000
+ # https://github.com/llvm/llvm-project/commit/1379b150991f70a5782e9a143c2ba5308da1161c
+ depends on AS_IS_GNU || AS_VERSION >= 150000
help
Say Y if you plan on running a kernel with a big-endian userspace.
@@ -1496,6 +1498,9 @@ config ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG
config ARCH_SUPPORTS_CRASH_DUMP
def_bool y
+config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
+ def_bool CRASH_CORE
+
config TRANS_TABLE
def_bool y
depends on HIBERNATION || KEXEC_CORE
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 6069120199bb..24335565bad5 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -244,6 +244,18 @@ config ARCH_NPCM
General support for NPCM8xx BMC (Arbel).
Nuvoton NPCM8xx BMC based on the Cortex A35.
+config ARCH_PENSANDO
+ bool "AMD Pensando Platforms"
+ help
+ This enables support for the ARMv8 based AMD Pensando SoC
+ family to include the Elba SoC.
+
+ AMD Pensando SoCs support a range of Distributed Services
+ Cards in PCIe format installed into servers. The Elba
+ SoC includes 16 Cortex A-72 CPU cores, 144 P4-programmable
+ cores for a minimal latency/jitter datapath, and network
+ interfaces up to 200 Gb/s.
+
config ARCH_QCOM
bool "Qualcomm Platforms"
select GPIOLIB
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 2d49aea0ff67..9a2d3723cd0f 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -158,7 +158,7 @@ endif
all: $(notdir $(KBUILD_IMAGE))
-
+vmlinuz.efi: Image
Image vmlinuz.efi: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
@@ -169,12 +169,6 @@ install: KBUILD_IMAGE := $(boot)/Image
install zinstall:
$(call cmd,install)
-PHONY += vdso_install
-vdso_install:
- $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso $@
- $(if $(CONFIG_COMPAT_VDSO), \
- $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 $@)
-
archprepare:
$(Q)$(MAKE) $(build)=arch/arm64/tools kapi
ifeq ($(CONFIG_ARM64_ERRATUM_843419),y)
@@ -205,6 +199,9 @@ ifdef CONFIG_COMPAT_VDSO
endif
endif
+vdso-install-y += arch/arm64/kernel/vdso/vdso.so.dbg
+vdso-install-$(CONFIG_COMPAT_VDSO) += arch/arm64/kernel/vdso32/vdso.so.dbg:vdso32.so
+
include $(srctree)/scripts/Makefile.defconf
PHONY += virtconfig
diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 3b0ad5406238..3aca6787a167 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -38,6 +38,8 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64-model-b.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-tanix-tx6.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-tanix-tx6-mini.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-bigtreetech-cb1-manta.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-bigtreetech-pi.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-orangepi-zero2.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-x96-mate.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-orangepi-zero3.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1-manta.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1-manta.dts
new file mode 100644
index 000000000000..dbce61b355d6
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1-manta.dts
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2023 Martin Botka <martin.botka@somainline.org>.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616-bigtreetech-cb1.dtsi"
+
+/ {
+ model = "BigTreeTech CB1";
+ compatible = "bigtreetech,cb1-manta", "bigtreetech,cb1", "allwinner,sun50i-h616";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1.dtsi
new file mode 100644
index 000000000000..1fed2b46cfe8
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1.dtsi
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2023 Martin Botka <martin.botka@somainline.org>.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ aliases {
+ ethernet0 = &rtl8189ftv;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+ };
+ };
+
+ reg_vcc5v: regulator-vcc5v {
+ /* board wide 5V supply from carrier boards */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ reg_vcc33_wifi: vcc33-wifi {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc33-wifi";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ vin-supply = <&reg_vcc5v>;
+ };
+
+ reg_vcc_wifi_io: vcc-wifi-io {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-wifi-io";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ vin-supply = <&reg_vcc33_wifi>;
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&rtc 1>;
+ clock-names = "ext_clock";
+ reset-gpios = <&pio 6 18 GPIO_ACTIVE_LOW>; /* PG18 */
+ post-power-on-delay-ms = <200>;
+ };
+};
+
+&mmc0 {
+ vmmc-supply = <&reg_dldo1>;
+ /* Card detection pin is not connected */
+ broken-cd;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&mmc1 {
+ vmmc-supply = <&reg_vcc33_wifi>;
+ vqmmc-supply = <&reg_vcc_wifi_io>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ bus-width = <4>;
+ non-removable;
+ mmc-ddr-1_8v;
+ status = "okay";
+
+ rtl8189ftv: wifi@1 {
+ reg = <1>;
+ };
+};
+
+&r_i2c {
+ status = "okay";
+
+ axp313a: pmic@36 {
+ compatible = "x-powers,axp313a";
+ reg = <0x36>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ regulators{
+ reg_dcdc1: dcdc1 {
+ regulator-name = "vdd-gpu-sys";
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <990000>;
+ regulator-always-on;
+ };
+
+ reg_dcdc2: dcdc2 {
+ regulator-name = "vdd-cpu";
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-ramp-delay = <200>;
+ regulator-always-on;
+ };
+
+ reg_dcdc3: dcdc3 {
+ regulator-name = "vcc-dram";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ };
+
+ reg_aldo1: aldo1 {
+ regulator-name = "vcc-1v8-pll";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ reg_dldo1: dldo1 {
+ regulator-name = "vcc-3v3-io";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&usbphy {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-pi.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-pi.dts
new file mode 100644
index 000000000000..832f08b2b260
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-pi.dts
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2023 Martin Botka <martin@biqu3d.com>.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616-bigtreetech-cb1.dtsi"
+
+/ {
+ model = "BigTreeTech Pi";
+ compatible = "bigtreetech,pi", "allwinner,sun50i-h616";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&ehci2 {
+ status = "okay";
+};
+
+&ehci3 {
+ status = "okay";
+};
+
+&ir {
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&ohci2 {
+ status = "okay";
+};
+
+&ohci3 {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
index 74aed0d232a9..d549d277d972 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
@@ -133,6 +133,13 @@
#reset-cells = <1>;
};
+ sid: efuse@3006000 {
+ compatible = "allwinner,sun50i-h616-sid", "allwinner,sun50i-a64-sid";
+ reg = <0x03006000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
watchdog: watchdog@30090a0 {
compatible = "allwinner,sun50i-h616-wdt",
"allwinner,sun6i-a31-wdt";
diff --git a/arch/arm64/boot/dts/amd/Makefile b/arch/arm64/boot/dts/amd/Makefile
index 68103a8b0ef5..8502cc2afbc5 100644
--- a/arch/arm64/boot/dts/amd/Makefile
+++ b/arch/arm64/boot/dts/amd/Makefile
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_PENSANDO) += elba-asic.dtb
dtb-$(CONFIG_ARCH_SEATTLE) += amd-overdrive-rev-b0.dtb amd-overdrive-rev-b1.dtb
diff --git a/arch/arm64/boot/dts/amd/amd-overdrive-rev-b0.dts b/arch/arm64/boot/dts/amd/amd-overdrive-rev-b0.dts
index 21149acb6b31..1a65f1ec183d 100644
--- a/arch/arm64/boot/dts/amd/amd-overdrive-rev-b0.dts
+++ b/arch/arm64/boot/dts/amd/amd-overdrive-rev-b0.dts
@@ -64,7 +64,6 @@
reg = <0>;
spi-max-frequency = <20000000>;
voltage-ranges = <3200 3400>;
- pl022,hierarchy = <0>;
pl022,interface = <0>;
pl022,com-mode = <0x0>;
pl022,rx-level-trig = <0>;
diff --git a/arch/arm64/boot/dts/amd/amd-overdrive-rev-b1.dts b/arch/arm64/boot/dts/amd/amd-overdrive-rev-b1.dts
index 99205ae1b46b..52f8d36295a8 100644
--- a/arch/arm64/boot/dts/amd/amd-overdrive-rev-b1.dts
+++ b/arch/arm64/boot/dts/amd/amd-overdrive-rev-b1.dts
@@ -76,7 +76,6 @@
reg = <0>;
spi-max-frequency = <20000000>;
voltage-ranges = <3200 3400>;
- pl022,hierarchy = <0>;
pl022,interface = <0>;
pl022,com-mode = <0x0>;
pl022,rx-level-trig = <0>;
diff --git a/arch/arm64/boot/dts/amd/elba-16core.dtsi b/arch/arm64/boot/dts/amd/elba-16core.dtsi
new file mode 100644
index 000000000000..568bcc39ce9f
--- /dev/null
+++ b/arch/arm64/boot/dts/amd/elba-16core.dtsi
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
+/*
+ * Copyright 2020-2023 Advanced Micro Devices, Inc.
+ */
+
+/ {
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu-map {
+ cluster0 {
+ core0 { cpu = <&cpu0>; };
+ core1 { cpu = <&cpu1>; };
+ core2 { cpu = <&cpu2>; };
+ core3 { cpu = <&cpu3>; };
+ };
+
+ cluster1 {
+ core0 { cpu = <&cpu4>; };
+ core1 { cpu = <&cpu5>; };
+ core2 { cpu = <&cpu6>; };
+ core3 { cpu = <&cpu7>; };
+ };
+
+ cluster2 {
+ core0 { cpu = <&cpu8>; };
+ core1 { cpu = <&cpu9>; };
+ core2 { cpu = <&cpu10>; };
+ core3 { cpu = <&cpu11>; };
+ };
+
+ cluster3 {
+ core0 { cpu = <&cpu12>; };
+ core1 { cpu = <&cpu13>; };
+ core2 { cpu = <&cpu14>; };
+ core3 { cpu = <&cpu15>; };
+ };
+ };
+
+ /* CLUSTER 0 */
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x0>;
+ next-level-cache = <&l2_0>;
+ enable-method = "psci";
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x1>;
+ next-level-cache = <&l2_0>;
+ enable-method = "psci";
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x2>;
+ next-level-cache = <&l2_0>;
+ enable-method = "psci";
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x3>;
+ next-level-cache = <&l2_0>;
+ enable-method = "psci";
+ };
+
+ l2_0: l2-cache0 {
+ compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ /* CLUSTER 1 */
+ cpu4: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x100>;
+ next-level-cache = <&l2_1>;
+ enable-method = "psci";
+ };
+
+ cpu5: cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x101>;
+ next-level-cache = <&l2_1>;
+ enable-method = "psci";
+ };
+
+ cpu6: cpu@102 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x102>;
+ next-level-cache = <&l2_1>;
+ enable-method = "psci";
+ };
+
+ cpu7: cpu@103 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x103>;
+ next-level-cache = <&l2_1>;
+ enable-method = "psci";
+ };
+
+ l2_1: l2-cache1 {
+ compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ /* CLUSTER 2 */
+ cpu8: cpu@200 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x200>;
+ next-level-cache = <&l2_2>;
+ enable-method = "psci";
+ };
+
+ cpu9: cpu@201 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x201>;
+ next-level-cache = <&l2_2>;
+ enable-method = "psci";
+ };
+
+ cpu10: cpu@202 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x202>;
+ next-level-cache = <&l2_2>;
+ enable-method = "psci";
+ };
+
+ cpu11: cpu@203 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x203>;
+ next-level-cache = <&l2_2>;
+ enable-method = "psci";
+ };
+
+ l2_2: l2-cache2 {
+ compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ /* CLUSTER 3 */
+ cpu12: cpu@300 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x300>;
+ next-level-cache = <&l2_3>;
+ enable-method = "psci";
+ };
+
+ cpu13: cpu@301 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x301>;
+ next-level-cache = <&l2_3>;
+ enable-method = "psci";
+ };
+
+ cpu14: cpu@302 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x302>;
+ next-level-cache = <&l2_3>;
+ enable-method = "psci";
+ };
+
+ cpu15: cpu@303 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x303>;
+ next-level-cache = <&l2_3>;
+ enable-method = "psci";
+ };
+
+ l2_3: l2-cache3 {
+ compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/amd/elba-asic-common.dtsi b/arch/arm64/boot/dts/amd/elba-asic-common.dtsi
new file mode 100644
index 000000000000..46b6c6783f58
--- /dev/null
+++ b/arch/arm64/boot/dts/amd/elba-asic-common.dtsi
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
+/*
+ * Copyright 2020-2022 Advanced Micro Devices, Inc.
+ */
+
+&ahb_clk {
+ clock-frequency = <400000000>;
+};
+
+&emmc_clk {
+ clock-frequency = <200000000>;
+};
+
+&flash_clk {
+ clock-frequency = <400000000>;
+};
+
+&ref_clk {
+ clock-frequency = <156250000>;
+};
+
+&qspi {
+ status = "okay";
+
+ flash0: flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <40000000>;
+ spi-rx-bus-width = <2>;
+ m25p,fast-read;
+ cdns,read-delay = <0>;
+ cdns,tshsl-ns = <0>;
+ cdns,tsd2d-ns = <0>;
+ cdns,tchsh-ns = <0>;
+ cdns,tslch-ns = <0>;
+ };
+};
+
+&gpio0 {
+ status = "okay";
+};
+
+&emmc {
+ bus-width = <8>;
+ cap-mmc-hw-reset;
+ status = "okay";
+};
+
+&wdt0 {
+ status = "okay";
+};
+
+&i2c0 {
+ clock-frequency = <100000>;
+ status = "okay";
+
+ rtc@51 {
+ compatible = "nxp,pcf85263";
+ reg = <0x51>;
+ };
+};
+
+&spi0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ num-cs = <4>;
+ cs-gpios = <0>, <0>, <&porta 1 GPIO_ACTIVE_LOW>,
+ <&porta 7 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amd/elba-asic.dts b/arch/arm64/boot/dts/amd/elba-asic.dts
new file mode 100644
index 000000000000..c3f4da2f7449
--- /dev/null
+++ b/arch/arm64/boot/dts/amd/elba-asic.dts
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
+/*
+ * Device Tree file for AMD Pensando Elba Board.
+ *
+ * Copyright 2020-2022 Advanced Micro Devices, Inc.
+ */
+
+/dts-v1/;
+
+#include "elba.dtsi"
+#include "elba-16core.dtsi"
+#include "elba-asic-common.dtsi"
+#include "elba-flash-parts.dtsi"
+
+/ {
+ model = "AMD Pensando Elba Board";
+ compatible = "amd,pensando-elba-ortano", "amd,pensando-elba";
+
+ aliases {
+ serial0 = &uart0;
+ spi0 = &spi0;
+ spi1 = &qspi;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
diff --git a/arch/arm64/boot/dts/amd/elba-flash-parts.dtsi b/arch/arm64/boot/dts/amd/elba-flash-parts.dtsi
new file mode 100644
index 000000000000..cf761a05a81f
--- /dev/null
+++ b/arch/arm64/boot/dts/amd/elba-flash-parts.dtsi
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
+/*
+ * Copyright 2020-2023 Advanced Micro Devices, Inc.
+ */
+
+&flash0 {
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ partition@0 {
+ label = "rsvd";
+ reg = <0x0 0x10000>;
+ read-only;
+ };
+
+ partition@10000 {
+ label = "flash";
+ reg = <0x10000 0xfff0000>;
+ };
+
+ partition@f0000 {
+ label = "golduenv";
+ reg = <0xf0000 0x10000>;
+ };
+
+ partition@100000 {
+ label = "boot0";
+ reg = <0x100000 0x80000>;
+ };
+
+ partition@180000 {
+ label = "golduboot";
+ reg = <0x180000 0x200000>;
+ };
+
+ partition@380000 {
+ label = "brdcfg0";
+ reg = <0x380000 0x10000>;
+ };
+
+ partition@390000 {
+ label = "brdcfg1";
+ reg = <0x390000 0x10000>;
+ };
+
+ partition@400000 {
+ label = "goldfw";
+ reg = <0x400000 0x3c00000>;
+ };
+
+ partition@4010000 {
+ label = "fwmap";
+ reg = <0x4010000 0x20000>;
+ };
+
+ partition@4030000 {
+ label = "fwsel";
+ reg = <0x4030000 0x20000>;
+ };
+
+ partition@4090000 {
+ label = "bootlog";
+ reg = <0x4090000 0x20000>;
+ };
+
+ partition@40b0000 {
+ label = "panicbuf";
+ reg = <0x40b0000 0x20000>;
+ };
+
+ partition@40d0000 {
+ label = "uservars";
+ reg = <0x40d0000 0x20000>;
+ };
+
+ partition@4200000 {
+ label = "uboota";
+ reg = <0x4200000 0x400000>;
+ };
+
+ partition@4600000 {
+ label = "ubootb";
+ reg = <0x4600000 0x400000>;
+ };
+
+ partition@4a00000 {
+ label = "mainfwa";
+ reg = <0x4a00000 0x1000000>;
+ };
+
+ partition@5a00000 {
+ label = "mainfwb";
+ reg = <0x5a00000 0x1000000>;
+ };
+
+ partition@6a00000 {
+ label = "diaguboot";
+ reg = <0x6a00000 0x400000>;
+ };
+
+ partition@6e00000 {
+ label = "spare";
+ reg = <0x6e00000 0x1200000>;
+ };
+
+ partition@8000000 {
+ label = "diagfw";
+ reg = <0x8000000 0x7fe0000>;
+ };
+
+ partition@ffe0000 {
+ label = "ubootenv";
+ reg = <0xffe0000 0x10000>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/amd/elba.dtsi b/arch/arm64/boot/dts/amd/elba.dtsi
new file mode 100644
index 000000000000..674890cf2a34
--- /dev/null
+++ b/arch/arm64/boot/dts/amd/elba.dtsi
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
+/*
+ * Copyright 2020-2022 Advanced Micro Devices, Inc.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include "dt-bindings/interrupt-controller/arm-gic.h"
+
+/ {
+ model = "Elba ASIC Board";
+ compatible = "amd,pensando-elba";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ dma-coherent;
+
+ ahb_clk: oscillator0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ emmc_clk: oscillator2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ flash_clk: oscillator3 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ ref_clk: oscillator4 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a72-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ soc: soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ i2c0: i2c@400 {
+ compatible = "snps,designware-i2c";
+ reg = <0x0 0x400 0x0 0x100>;
+ clocks = <&ahb_clk>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-sda-hold-time-ns = <480>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ wdt0: watchdog@1400 {
+ compatible = "snps,dw-wdt";
+ reg = <0x0 0x1400 0x0 0x100>;
+ clocks = <&ahb_clk>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ qspi: spi@2400 {
+ compatible = "amd,pensando-elba-qspi", "cdns,qspi-nor";
+ reg = <0x0 0x2400 0x0 0x400>,
+ <0x0 0x7fff0000 0x0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&flash_clk>;
+ cdns,fifo-depth = <1024>;
+ cdns,fifo-width = <4>;
+ cdns,trigger-address = <0x7fff0000>;
+ status = "disabled";
+ };
+
+ spi0: spi@2800 {
+ compatible = "amd,pensando-elba-spi";
+ reg = <0x0 0x2800 0x0 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ amd,pensando-elba-syscon = <&syscon>;
+ clocks = <&ahb_clk>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ num-cs = <2>;
+ status = "disabled";
+ };
+
+ gpio0: gpio@4000 {
+ compatible = "snps,dw-apb-gpio";
+ reg = <0x0 0x4000 0x0 0x78>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ porta: gpio-port@0 {
+ compatible = "snps,dw-apb-gpio-port";
+ reg = <0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ interrupt-parent = <&gic>;
+ #interrupt-cells = <2>;
+ };
+
+ portb: gpio-port@1 {
+ compatible = "snps,dw-apb-gpio-port";
+ reg = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ };
+ };
+
+ uart0: serial@4800 {
+ compatible = "ns16550a";
+ reg = <0x0 0x4800 0x0 0x100>;
+ clocks = <&ref_clk>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
+
+ gic: interrupt-controller@800000 {
+ compatible = "arm,gic-v3";
+ reg = <0x0 0x800000 0x0 0x200000>, /* GICD */
+ <0x0 0xa00000 0x0 0x200000>, /* GICR */
+ <0x0 0x60000000 0x0 0x2000>, /* GICC */
+ <0x0 0x60010000 0x0 0x1000>, /* GICH */
+ <0x0 0x60020000 0x0 0x2000>; /* GICV */
+ #address-cells = <2>;
+ #size-cells = <2>;
+ #interrupt-cells = <3>;
+ ranges;
+ interrupt-controller;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+ /*
+ * Elba specific pre-ITS is enabled using the
+ * existing property socionext,synquacer-pre-its
+ */
+ gic_its: msi-controller@820000 {
+ compatible = "arm,gic-v3-its";
+ reg = <0x0 0x820000 0x0 0x10000>;
+ msi-controller;
+ #msi-cells = <1>;
+ socionext,synquacer-pre-its =
+ <0xc00000 0x1000000>;
+ };
+ };
+
+ emmc: mmc@30440000 {
+ compatible = "amd,pensando-elba-sd4hc", "cdns,sd4hc";
+ reg = <0x0 0x30440000 0x0 0x10000>,
+ <0x0 0x30480044 0x0 0x4>; /* byte-lane ctrl */
+ clocks = <&emmc_clk>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ cdns,phy-input-delay-sd-highspeed = <0x4>;
+ cdns,phy-input-delay-legacy = <0x4>;
+ cdns,phy-input-delay-sd-uhs-sdr50 = <0x6>;
+ cdns,phy-input-delay-sd-uhs-ddr50 = <0x16>;
+ mmc-ddr-1_8v;
+ status = "disabled";
+ };
+
+ syscon: syscon@307c0000 {
+ compatible = "amd,pensando-elba-syscon", "syscon";
+ reg = <0x0 0x307c0000 0x0 0x3000>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index 8b6f57a94863..cc8b34bd583d 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_MESON) += amlogic-c3-c302x-aw409.dtb
dtb-$(CONFIG_ARCH_MESON) += amlogic-t7-a311d2-an400.dtb
dtb-$(CONFIG_ARCH_MESON) += amlogic-t7-a311d2-khadas-vim4.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-a1-ad401.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-a1-ad402.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-axg-jethome-jethub-j100.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-axg-jethome-jethub-j110-rev-2.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-axg-jethome-jethub-j110-rev-3.dtb
@@ -17,6 +18,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-bananapi-cm4-cm4io.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gsking-x.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking-pro.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-g12b-a311d-libretech-cc.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-odroid-go-ultra.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-odroid-n2-plus.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-odroid-n2.dtb
@@ -72,6 +74,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-sm1-bananapi-m2-pro.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-sm1-bananapi-m5.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-sm1-h96-max.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-sm1-khadas-vim3l.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-sm1-s905d3-libretech-cc.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-sm1-odroid-c4.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-sm1-odroid-hc4.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-sm1-sei610.dtb
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
index 1423d4a79156..a03c7667d2b6 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/amlogic,t7-pwrc.h>
/ {
interrupt-parent = <&gic>;
@@ -118,6 +119,11 @@
sm: secure-monitor {
compatible = "amlogic,meson-gxbb-sm";
+
+ pwrc: power-controller {
+ compatible = "amlogic,t7-pwrc";
+ #power-domain-cells = <1>;
+ };
};
soc {
@@ -143,6 +149,28 @@
#size-cells = <2>;
ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>;
+ watchdog@2100 {
+ compatible = "amlogic,t7-wdt";
+ reg = <0x0 0x2100 0x0 0x10>;
+ clocks = <&xtal>;
+ };
+
+ periphs_pinctrl: pinctrl@4000 {
+ compatible = "amlogic,t7-periphs-pinctrl";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ gpio: bank@4000 {
+ reg = <0x0 0x4000 0x0 0x0064>,
+ <0x0 0x40c0 0x0 0x0220>;
+ reg-names = "mux", "gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&periphs_pinctrl 0 0 157>;
+ };
+ };
+
uart_a: serial@78000 {
compatible = "amlogic,t7-uart", "amlogic,meson-s4-uart";
reg = <0x0 0x78000 0x0 0x18>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts b/arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts
new file mode 100644
index 000000000000..1c20516fa653
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023 SberDevices
+ * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
+ */
+
+/dts-v1/;
+
+#include "meson-a1.dtsi"
+
+/ {
+ compatible = "amlogic,ad402", "amlogic,a1";
+ model = "Amlogic Meson A1 AD402 Development Board";
+
+ aliases {
+ serial0 = &uart_AO_B;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x8000000>;
+ };
+
+ reserved-memory {
+ /* 3 MiB reserved for Amlogic Trust OS (BL32) */
+ secos_reserved: secos@3d00000 {
+ reg = <0x0 0x03d00000 0x0 0x300000>;
+ no-map;
+ };
+ };
+
+ firmware {
+ optee {
+ compatible = "linaro,optee-tz";
+ method = "smc";
+ };
+ };
+
+ battery_4v2: regulator-battery-4v2 {
+ compatible = "regulator-fixed";
+ regulator-name = "4V2";
+ regulator-min-microvolt = <4200000>;
+ regulator-max-microvolt = <4200000>;
+ regulator-always-on;
+ };
+
+ vddq_1v35: regulator-vddq-1v35 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDDQ_1V35";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ vin-supply = <&battery_4v2>;
+ regulator-always-on;
+ };
+
+ vddao_3v3: regulator-vddao-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDDAO_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&battery_4v2>;
+ regulator-always-on;
+ };
+
+ vcc_3v3: regulator-vcc-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vddao_3v3>;
+ regulator-always-on;
+ };
+
+ vddio_1v8: regulator-vddio-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDDIO_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vddao_3v3>;
+ regulator-always-on;
+ };
+};
+
+/* Bluetooth HCI H4 */
+&uart_AO {
+ status = "okay";
+ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
+ pinctrl-names = "default";
+};
+
+&uart_AO_B {
+ status = "okay";
+};
+
+&saradc {
+ status = "okay";
+ vref-supply = <&vddio_1v8>;
+};
+
+&spifc {
+ status = "okay";
+ pinctrl-0 = <&spifc_pins>;
+ pinctrl-names = "default";
+
+ spi_nand@0 {
+ compatible = "spi-nand";
+ status = "okay";
+ reg = <0>;
+ spi-max-frequency = <96000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ };
+};
+
+&usb2_phy1 {
+ phy-supply = <&vcc_3v3>;
+};
+
+&usb {
+ status = "okay";
+ dr_mode = "peripheral";
+};
+
+&sd_emmc {
+ status = "okay";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pinctrl-0 = <&sdio_pins>;
+ pinctrl-1 = <&sdio_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
+
+ bus-width = <4>;
+ cap-sd-highspeed;
+ sd-uhs-sdr104;
+ max-frequency = <200000000>;
+ non-removable;
+ disable-wp;
+
+ vmmc-supply = <&vddao_3v3>;
+ vqmmc-supply = <&vddio_1v8>;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
index 96225c421194..648e7f49424f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
@@ -3,9 +3,13 @@
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
-#include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/amlogic,a1-pll-clkc.h>
+#include <dt-bindings/clock/amlogic,a1-peripherals-clkc.h>
#include <dt-bindings/gpio/meson-a1-gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/power/meson-a1-power.h>
+#include <dt-bindings/reset/amlogic,meson-a1-reset.h>
/ {
compatible = "amlogic,a1";
@@ -41,6 +45,15 @@
};
};
+ efuse: efuse {
+ compatible = "amlogic,meson-gxbb-efuse";
+ clocks = <&clkc_periphs CLKID_OTP>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ secure-monitor = <&sm>;
+ power-domains = <&pwrc PWRC_OTP_ID>;
+ };
+
psci {
compatible = "arm,psci-1.0";
method = "smc";
@@ -66,7 +79,6 @@
pwrc: power-controller {
compatible = "amlogic,meson-a1-pwrc";
#power-domain-cells = <1>;
- status = "okay";
};
};
@@ -76,6 +88,16 @@
#size-cells = <2>;
ranges;
+ spifc: spi@fd000400 {
+ compatible = "amlogic,a1-spifc";
+ reg = <0x0 0xfd000400 0x0 0x290>;
+ clocks = <&clkc_periphs CLKID_SPIFC>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&pwrc PWRC_SPIFC_ID>;
+ status = "disabled";
+ };
+
apb: bus@fe000000 {
compatible = "simple-bus";
reg = <0x0 0xfe000000 0x0 0x1000000>;
@@ -83,7 +105,6 @@
#size-cells = <2>;
ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x1000000>;
-
reset: reset-controller@0 {
compatible = "amlogic,meson-a1-reset";
reg = <0x0 0x0 0x0 0x8c>;
@@ -105,6 +126,196 @@
gpio-ranges = <&periphs_pinctrl 0 0 62>;
};
+ i2c0_f11_pins: i2c0-f11 {
+ mux {
+ groups = "i2c0_sck_f11",
+ "i2c0_sda_f12";
+ function = "i2c0";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c0_f9_pins: i2c0-f9 {
+ mux {
+ groups = "i2c0_sck_f9",
+ "i2c0_sda_f10";
+ function = "i2c0";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c1_x_pins: i2c1-x {
+ mux {
+ groups = "i2c1_sck_x",
+ "i2c1_sda_x";
+ function = "i2c1";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c1_a_pins: i2c1-a {
+ mux {
+ groups = "i2c1_sck_a",
+ "i2c1_sda_a";
+ function = "i2c1";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c2_x0_pins: i2c2-x0 {
+ mux {
+ groups = "i2c2_sck_x0",
+ "i2c2_sda_x1";
+ function = "i2c2";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c2_x15_pins: i2c2-x15 {
+ mux {
+ groups = "i2c2_sck_x15",
+ "i2c2_sda_x16";
+ function = "i2c2";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c2_a4_pins: i2c2-a4 {
+ mux {
+ groups = "i2c2_sck_a4",
+ "i2c2_sda_a5";
+ function = "i2c2";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c2_a8_pins: i2c2-a8 {
+ mux {
+ groups = "i2c2_sck_a8",
+ "i2c2_sda_a9";
+ function = "i2c2";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c3_x_pins: i2c3-x {
+ mux {
+ groups = "i2c3_sck_x",
+ "i2c3_sda_x";
+ function = "i2c3";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c3_f_pins: i2c3-f {
+ mux {
+ groups = "i2c3_sck_f",
+ "i2c3_sda_f";
+ function = "i2c3";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ uart_a_pins: uart-a {
+ mux {
+ groups = "uart_a_tx",
+ "uart_a_rx";
+ function = "uart_a";
+ };
+ };
+
+ uart_a_cts_rts_pins: uart-a-cts-rts {
+ mux {
+ groups = "uart_a_cts",
+ "uart_a_rts";
+ function = "uart_a";
+ bias-pull-down;
+ };
+ };
+
+ sdio_pins: sdio {
+ mux0 {
+ groups = "sdcard_d0_x",
+ "sdcard_d1_x",
+ "sdcard_d2_x",
+ "sdcard_d3_x",
+ "sdcard_cmd_x";
+ function = "sdcard";
+ bias-pull-up;
+ };
+
+ mux1 {
+ groups = "sdcard_clk_x";
+ function = "sdcard";
+ bias-disable;
+ };
+ };
+
+ sdio_clk_gate_pins: sdio-clk-gate {
+ mux {
+ groups = "sdcard_clk_x";
+ function = "sdcard";
+ bias-pull-down;
+ };
+ };
+
+ spifc_pins: spifc {
+ mux {
+ groups = "spif_mo",
+ "spif_mi",
+ "spif_clk",
+ "spif_cs",
+ "spif_hold_n",
+ "spif_wp_n";
+ function = "spif";
+ };
+ };
+ };
+
+ gpio_intc: interrupt-controller@440 {
+ compatible = "amlogic,meson-a1-gpio-intc",
+ "amlogic,meson-gpio-intc";
+ reg = <0x0 0x0440 0x0 0x14>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ amlogic,channel-interrupts =
+ <49 50 51 52 53 54 55 56>;
+ };
+
+ clkc_periphs: clock-controller@800 {
+ compatible = "amlogic,a1-peripherals-clkc";
+ reg = <0 0x800 0 0x104>;
+ #clock-cells = <1>;
+ clocks = <&clkc_pll CLKID_FCLK_DIV2>,
+ <&clkc_pll CLKID_FCLK_DIV3>,
+ <&clkc_pll CLKID_FCLK_DIV5>,
+ <&clkc_pll CLKID_FCLK_DIV7>,
+ <&clkc_pll CLKID_HIFI_PLL>,
+ <&xtal>;
+ clock-names = "fclk_div2", "fclk_div3",
+ "fclk_div5", "fclk_div7",
+ "hifi_pll", "xtal";
+ };
+
+ i2c0: i2c@1400 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x1400 0x0 0x20>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc_periphs CLKID_I2C_M_A>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
};
uart_AO: serial@1c00 {
@@ -127,14 +338,148 @@
status = "disabled";
};
- gpio_intc: interrupt-controller@0440 {
- compatible = "amlogic,meson-a1-gpio-intc",
- "amlogic,meson-gpio-intc";
- reg = <0x0 0x0440 0x0 0x14>;
- interrupt-controller;
- #interrupt-cells = <2>;
- amlogic,channel-interrupts =
- <49 50 51 52 53 54 55 56>;
+ saradc: adc@2c00 {
+ compatible = "amlogic,meson-g12a-saradc",
+ "amlogic,meson-saradc";
+ reg = <0x0 0x2c00 0x0 0x48>;
+ #io-channel-cells = <1>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&xtal>,
+ <&clkc_periphs CLKID_SARADC_EN>,
+ <&clkc_periphs CLKID_SARADC>,
+ <&clkc_periphs CLKID_SARADC_SEL>;
+ clock-names = "clkin", "core",
+ "adc_clk", "adc_sel";
+ status = "disabled";
+ };
+
+ i2c1: i2c@5c00 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x5c00 0x0 0x20>;
+ interrupts = <GIC_SPI 68 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc_periphs CLKID_I2C_M_B>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
+ };
+
+ i2c2: i2c@6800 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x6800 0x0 0x20>;
+ interrupts = <GIC_SPI 76 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc_periphs CLKID_I2C_M_C>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
+ };
+
+ i2c3: i2c@6c00 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x6c00 0x0 0x20>;
+ interrupts = <GIC_SPI 78 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc_periphs CLKID_I2C_M_D>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
+ };
+
+ usb2_phy1: phy@4000 {
+ compatible = "amlogic,a1-usb2-phy";
+ clocks = <&clkc_periphs CLKID_USB_PHY_IN>;
+ clock-names = "xtal";
+ reg = <0x0 0x4000 0x0 0x60>;
+ resets = <&reset RESET_USBPHY>;
+ reset-names = "phy";
+ #phy-cells = <0>;
+ power-domains = <&pwrc PWRC_USB_ID>;
+ };
+
+ hwrng: rng@5118 {
+ compatible = "amlogic,meson-rng";
+ reg = <0x0 0x5118 0x0 0x4>;
+ power-domains = <&pwrc PWRC_OTP_ID>;
+ };
+
+ sec_AO: ao-secure@5a20 {
+ compatible = "amlogic,meson-gx-ao-secure", "syscon";
+ reg = <0x0 0x5a20 0x0 0x140>;
+ amlogic,has-chip-id;
+ };
+
+ clkc_pll: pll-clock-controller@7c80 {
+ compatible = "amlogic,a1-pll-clkc";
+ reg = <0 0x7c80 0 0x18c>;
+ #clock-cells = <1>;
+ clocks = <&clkc_periphs CLKID_FIXPLL_IN>,
+ <&clkc_periphs CLKID_HIFIPLL_IN>;
+ clock-names = "fixpll_in", "hifipll_in";
+ };
+
+ sd_emmc: sd@10000 {
+ compatible = "amlogic,meson-axg-mmc";
+ reg = <0x0 0x10000 0x0 0x800>;
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc_periphs CLKID_SD_EMMC_A>,
+ <&clkc_periphs CLKID_SD_EMMC>,
+ <&clkc_pll CLKID_FCLK_DIV2>;
+ clock-names = "core",
+ "clkin0",
+ "clkin1";
+ assigned-clocks = <&clkc_periphs CLKID_SD_EMMC_SEL2>;
+ assigned-clock-parents = <&xtal>;
+ resets = <&reset RESET_SD_EMMC_A>;
+ power-domains = <&pwrc PWRC_SD_EMMC_ID>;
+ status = "disabled";
+ };
+ };
+
+ usb: usb@fe004400 {
+ status = "disabled";
+ compatible = "amlogic,meson-a1-usb-ctrl";
+ reg = <0x0 0xfe004400 0x0 0xa0>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ clocks = <&clkc_periphs CLKID_USB_CTRL>,
+ <&clkc_periphs CLKID_USB_BUS>,
+ <&clkc_periphs CLKID_USB_CTRL_IN>;
+ clock-names = "usb_ctrl", "usb_bus", "xtal_usb_ctrl";
+ resets = <&reset RESET_USBCTRL>;
+ reset-name = "usb_ctrl";
+
+ dr_mode = "otg";
+
+ phys = <&usb2_phy1>;
+ phy-names = "usb2-phy1";
+
+ dwc3: usb@ff400000 {
+ compatible = "snps,dwc3";
+ reg = <0x0 0xff400000 0x0 0x100000>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ dr_mode = "host";
+ snps,dis_u2_susphy_quirk;
+ snps,quirk-frame-length-adjustment = <0x20>;
+ snps,parkmode-disable-ss-quirk;
+ };
+
+ dwc2: usb@ff500000 {
+ compatible = "amlogic,meson-a1-usb", "snps,dwc2";
+ reg = <0x0 0xff500000 0x0 0x40000>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&usb2_phy1>;
+ phy-names = "usb2-phy";
+ clocks = <&clkc_periphs CLKID_USB_PHY>;
+ clock-names = "otg";
+ dr_mode = "peripheral";
+ g-rx-fifo-size = <192>;
+ g-np-tx-fifo-size = <128>;
+ g-tx-fifo-size = <128 128 16 16 16>;
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index 768d0ed78dbe..a49aa62e3f9f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -1908,6 +1908,19 @@
resets = <&reset RESET_SD_EMMC_C>;
};
+ nfc: nand-controller@7800 {
+ compatible = "amlogic,meson-axg-nfc";
+ reg = <0x0 0x7800 0x0 0x100>,
+ <0x0 0x7000 0x0 0x800>;
+ reg-names = "nfc", "emmc";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc CLKID_SD_EMMC_C>,
+ <&clkc CLKID_FCLK_DIV2>;
+ clock-names = "core", "device";
+ };
+
usb2_phy1: phy@9020 {
compatible = "amlogic,meson-gxl-usb2-phy";
#phy-cells = <0>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12.dtsi
index 6a1f4dcf6488..e732df3f3114 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12.dtsi
@@ -15,10 +15,10 @@
compatible = "amlogic,axg-tdm-iface";
#sound-dai-cells = <0>;
sound-name-prefix = "TDM_A";
- clocks = <&clkc_audio AUD_CLKID_MST_A_MCLK>,
- <&clkc_audio AUD_CLKID_MST_A_SCLK>,
- <&clkc_audio AUD_CLKID_MST_A_LRCLK>;
- clock-names = "mclk", "sclk", "lrclk";
+ clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
+ <&clkc_audio AUD_CLKID_MST_A_LRCLK>,
+ <&clkc_audio AUD_CLKID_MST_A_MCLK>;
+ clock-names = "sclk", "lrclk", "mclk";
status = "disabled";
};
@@ -26,10 +26,10 @@
compatible = "amlogic,axg-tdm-iface";
#sound-dai-cells = <0>;
sound-name-prefix = "TDM_B";
- clocks = <&clkc_audio AUD_CLKID_MST_B_MCLK>,
- <&clkc_audio AUD_CLKID_MST_B_SCLK>,
- <&clkc_audio AUD_CLKID_MST_B_LRCLK>;
- clock-names = "mclk", "sclk", "lrclk";
+ clocks = <&clkc_audio AUD_CLKID_MST_B_SCLK>,
+ <&clkc_audio AUD_CLKID_MST_B_LRCLK>,
+ <&clkc_audio AUD_CLKID_MST_B_MCLK>;
+ clock-names = "sclk", "lrclk", "mclk";
status = "disabled";
};
@@ -37,10 +37,10 @@
compatible = "amlogic,axg-tdm-iface";
#sound-dai-cells = <0>;
sound-name-prefix = "TDM_C";
- clocks = <&clkc_audio AUD_CLKID_MST_C_MCLK>,
- <&clkc_audio AUD_CLKID_MST_C_SCLK>,
- <&clkc_audio AUD_CLKID_MST_C_LRCLK>;
- clock-names = "mclk", "sclk", "lrclk";
+ clocks = <&clkc_audio AUD_CLKID_MST_C_SCLK>,
+ <&clkc_audio AUD_CLKID_MST_C_LRCLK>,
+ <&clkc_audio AUD_CLKID_MST_C_MCLK>;
+ clock-names = "sclk", "lrclk", "mclk";
status = "disabled";
};
};
@@ -195,8 +195,7 @@
};
tdmin_a: audio-controller@300 {
- compatible = "amlogic,g12a-tdmin",
- "amlogic,axg-tdmin";
+ compatible = "amlogic,g12a-tdmin";
reg = <0x0 0x300 0x0 0x40>;
sound-name-prefix = "TDMIN_A";
resets = <&clkc_audio AUD_RESET_TDMIN_A>;
@@ -211,8 +210,7 @@
};
tdmin_b: audio-controller@340 {
- compatible = "amlogic,g12a-tdmin",
- "amlogic,axg-tdmin";
+ compatible = "amlogic,g12a-tdmin";
reg = <0x0 0x340 0x0 0x40>;
sound-name-prefix = "TDMIN_B";
resets = <&clkc_audio AUD_RESET_TDMIN_B>;
@@ -227,8 +225,7 @@
};
tdmin_c: audio-controller@380 {
- compatible = "amlogic,g12a-tdmin",
- "amlogic,axg-tdmin";
+ compatible = "amlogic,g12a-tdmin";
reg = <0x0 0x380 0x0 0x40>;
sound-name-prefix = "TDMIN_C";
resets = <&clkc_audio AUD_RESET_TDMIN_C>;
@@ -243,8 +240,7 @@
};
tdmin_lb: audio-controller@3c0 {
- compatible = "amlogic,g12a-tdmin",
- "amlogic,axg-tdmin";
+ compatible = "amlogic,g12a-tdmin";
reg = <0x0 0x3c0 0x0 0x40>;
sound-name-prefix = "TDMIN_LB";
resets = <&clkc_audio AUD_RESET_TDMIN_LB>;
@@ -272,12 +268,12 @@
status = "disabled";
};
- spdifout: audio-controller@480 {
+ spdifout_a: audio-controller@480 {
compatible = "amlogic,g12a-spdifout",
"amlogic,axg-spdifout";
reg = <0x0 0x480 0x0 0x50>;
#sound-dai-cells = <0>;
- sound-name-prefix = "SPDIFOUT";
+ sound-name-prefix = "SPDIFOUT_A";
clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>,
<&clkc_audio AUD_CLKID_SPDIFOUT_CLK>;
clock-names = "pclk", "mclk";
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
index 4b5d11e56364..8355ddd7e9ae 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
@@ -8,6 +8,8 @@
#include "meson-g12a.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/meson-g12a-gpio.h>
+#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
+#include <dt-bindings/sound/meson-g12a-toacodec.h>
/ {
compatible = "amlogic,u200", "amlogic,g12a";
@@ -18,6 +20,26 @@
ethernet0 = &ethmac;
};
+ dioo2133: audio-amplifier-0 {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
+ VCC-supply = <&vcc_5v>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "10U2";
+ };
+
+ spdif_dir: audio-codec-0 {
+ compatible = "linux,spdif-dir";
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "DIR";
+ };
+
+ spdif_dit: audio-codec-1 {
+ compatible = "linux,spdif-dit";
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "DIT";
+ };
+
chosen {
stdout-path = "serial0:115200n8";
};
@@ -147,6 +169,216 @@
regulator-boot-on;
regulator-always-on;
};
+
+ sound {
+ compatible = "amlogic,axg-sound-card";
+ model = "U200";
+ audio-widgets = "Line", "Lineout";
+ audio-aux-devs = <&tdmout_a>, <&tdmout_b>, <&tdmout_c>,
+ <&tdmin_a>, <&tdmin_b>, <&tdmin_c>,
+ <&tdmin_lb>, <&dioo2133>;
+ audio-routing = "TDMOUT_A IN 0", "FRDDR_A OUT 0",
+ "TDMOUT_A IN 1", "FRDDR_B OUT 0",
+ "TDMOUT_A IN 2", "FRDDR_C OUT 0",
+ "TDM_A Playback", "TDMOUT_A OUT",
+ "TDMOUT_B IN 0", "FRDDR_A OUT 1",
+ "TDMOUT_B IN 1", "FRDDR_B OUT 1",
+ "TDMOUT_B IN 2", "FRDDR_C OUT 1",
+ "TDM_B Playback", "TDMOUT_B OUT",
+ "TDMOUT_C IN 0", "FRDDR_A OUT 2",
+ "TDMOUT_C IN 1", "FRDDR_B OUT 2",
+ "TDMOUT_C IN 2", "FRDDR_C OUT 2",
+ "TDM_C Playback", "TDMOUT_C OUT",
+ "SPDIFOUT_A IN 0", "FRDDR_A OUT 3",
+ "SPDIFOUT_A IN 1", "FRDDR_B OUT 3",
+ "SPDIFOUT_A IN 2", "FRDDR_C OUT 3",
+ "SPDIFOUT_B IN 0", "FRDDR_A OUT 4",
+ "SPDIFOUT_B IN 1", "FRDDR_B OUT 4",
+ "SPDIFOUT_B IN 2", "FRDDR_C OUT 4",
+ "TDMIN_A IN 0", "TDM_A Capture",
+ "TDMIN_A IN 1", "TDM_B Capture",
+ "TDMIN_A IN 2", "TDM_C Capture",
+ "TDMIN_A IN 3", "TDM_A Loopback",
+ "TDMIN_A IN 4", "TDM_B Loopback",
+ "TDMIN_A IN 5", "TDM_C Loopback",
+ "TDMIN_B IN 0", "TDM_A Capture",
+ "TDMIN_B IN 1", "TDM_B Capture",
+ "TDMIN_B IN 2", "TDM_C Capture",
+ "TDMIN_B IN 3", "TDM_A Loopback",
+ "TDMIN_B IN 4", "TDM_B Loopback",
+ "TDMIN_B IN 5", "TDM_C Loopback",
+ "TDMIN_C IN 0", "TDM_A Capture",
+ "TDMIN_C IN 1", "TDM_B Capture",
+ "TDMIN_C IN 2", "TDM_C Capture",
+ "TDMIN_C IN 3", "TDM_A Loopback",
+ "TDMIN_C IN 4", "TDM_B Loopback",
+ "TDMIN_C IN 5", "TDM_C Loopback",
+ "TDMIN_LB IN 3", "TDM_A Capture",
+ "TDMIN_LB IN 4", "TDM_B Capture",
+ "TDMIN_LB IN 5", "TDM_C Capture",
+ "TDMIN_LB IN 0", "TDM_A Loopback",
+ "TDMIN_LB IN 1", "TDM_B Loopback",
+ "TDMIN_LB IN 2", "TDM_C Loopback",
+ "TODDR_A IN 0", "TDMIN_A OUT",
+ "TODDR_B IN 0", "TDMIN_A OUT",
+ "TODDR_C IN 0", "TDMIN_A OUT",
+ "TODDR_A IN 1", "TDMIN_B OUT",
+ "TODDR_B IN 1", "TDMIN_B OUT",
+ "TODDR_C IN 1", "TDMIN_B OUT",
+ "TODDR_A IN 2", "TDMIN_C OUT",
+ "TODDR_B IN 2", "TDMIN_C OUT",
+ "TODDR_C IN 2", "TDMIN_C OUT",
+ "TODDR_A IN 3", "SPDIFIN Capture",
+ "TODDR_B IN 3", "SPDIFIN Capture",
+ "TODDR_C IN 3", "SPDIFIN Capture",
+ "TODDR_A IN 6", "TDMIN_LB OUT",
+ "TODDR_B IN 6", "TDMIN_LB OUT",
+ "TODDR_C IN 6", "TDMIN_LB OUT",
+ "10U2 INL", "ACODEC LOLP",
+ "10U2 INR", "ACODEC LORP",
+ "Lineout", "10U2 OUTL",
+ "Lineout", "10U2 OUTR";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ dai-link-0 {
+ sound-dai = <&frddr_a>;
+ };
+
+ dai-link-1 {
+ sound-dai = <&frddr_b>;
+ };
+
+ dai-link-2 {
+ sound-dai = <&frddr_c>;
+ };
+
+ dai-link-3 {
+ sound-dai = <&toddr_a>;
+ };
+
+ dai-link-4 {
+ sound-dai = <&toddr_b>;
+ };
+
+ dai-link-5 {
+ sound-dai = <&toddr_c>;
+ };
+
+ /* Connected to the WIFI/BT chip */
+ dai-link-6 {
+ sound-dai = <&tdmif_a>;
+ dai-format = "dsp_a";
+ dai-tdm-slot-tx-mask-0 = <1 1>;
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&toacodec TOACODEC_IN_A>;
+ };
+
+ codec-1 {
+ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_A>;
+ };
+ };
+
+ /* Connected to the onboard AD82584F DAC */
+ dai-link-7 {
+ sound-dai = <&tdmif_b>;
+ dai-format = "i2s";
+ dai-tdm-slot-tx-mask-0 = <1 1>;
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&toacodec TOACODEC_IN_B>;
+ };
+
+ codec-1 {
+ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>;
+ };
+ };
+
+ /* 8ch HDMI interface */
+ dai-link-8 {
+ sound-dai = <&tdmif_c>;
+ dai-format = "i2s";
+ dai-tdm-slot-tx-mask-0 = <1 1>;
+ dai-tdm-slot-tx-mask-1 = <1 1>;
+ dai-tdm-slot-tx-mask-2 = <1 1>;
+ dai-tdm-slot-tx-mask-3 = <1 1>;
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&toacodec TOACODEC_IN_C>;
+ };
+
+ codec-1 {
+ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_C>;
+ };
+ };
+
+ /* spdif hdmi and coax output */
+ dai-link-9 {
+ sound-dai = <&spdifout_a>;
+
+ codec-0 {
+ sound-dai = <&spdif_dit>;
+ };
+
+ codec-1 {
+ sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_A>;
+ };
+ };
+
+ /* spdif hdmi interface */
+ dai-link-10 {
+ sound-dai = <&spdifout_b>;
+
+ codec {
+ sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_B>;
+ };
+ };
+
+ /* hdmi glue */
+ dai-link-11 {
+ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+
+ /* internal codec glue */
+ dai-link-12 {
+ sound-dai = <&toacodec TOACODEC_OUT>;
+
+ codec {
+ sound-dai = <&acodec>;
+ };
+ };
+
+ /* spdif coax input */
+ dai-link-13 {
+ sound-dai = <&spdifin>;
+
+ codec {
+ sound-dai = <&spdif_dir>;
+ };
+ };
+ };
+};
+
+&acodec {
+ status = "okay";
+};
+
+&arb {
+ status = "okay";
};
&cec_AO {
@@ -163,6 +395,10 @@
hdmi-phandle = <&hdmi_tx>;
};
+&clkc_audio {
+ status = "okay";
+};
+
&cpu0 {
cpu-supply = <&vddcpu>;
operating-points-v2 = <&cpu_opp_table>;
@@ -191,6 +427,10 @@
clock-latency = <50000>;
};
+&clkc_audio {
+ status = "okay";
+};
+
&cvbs_vdac_port {
cvbs_vdac_out: endpoint {
remote-endpoint = <&cvbs_connector_in>;
@@ -203,6 +443,18 @@
phy-mode = "rmii";
};
+&frddr_a {
+ status = "okay";
+};
+
+&frddr_b {
+ status = "okay";
+};
+
+&frddr_c {
+ status = "okay";
+};
+
&hdmi_tx {
status = "okay";
pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>;
@@ -288,6 +540,95 @@
vqmmc-supply = <&flash_1v8>;
};
+&spdifin {
+ pinctrl-0 = <&spdif_in_h_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&spdifout_a {
+ pinctrl-0 = <&spdif_ao_out_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&spdifout_b {
+ status = "okay";
+};
+
+&tdmif_a {
+ pinctrl-0 = <&tdm_a_fs_pins>, <&tdm_a_sclk_pins>, <&tdm_a_dout0_pins> ;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&tdmif_b {
+ pinctrl-0 = <&mclk0_a_pins>, <&tdm_b_fs_pins>, <&tdm_b_sclk_pins>,
+ <&tdm_b_dout0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ assigned-clocks = <&clkc_audio AUD_CLKID_TDM_MCLK_PAD0>,
+ <&clkc_audio AUD_CLKID_TDM_SCLK_PAD1>,
+ <&clkc_audio AUD_CLKID_TDM_LRCLK_PAD1>;
+ assigned-clock-parents = <&clkc_audio AUD_CLKID_MST_B_MCLK>,
+ <&clkc_audio AUD_CLKID_MST_B_SCLK>,
+ <&clkc_audio AUD_CLKID_MST_B_LRCLK>;
+ assigned-clock-rates = <0>, <0>, <0>;
+};
+
+&tdmif_c {
+ status = "okay";
+};
+
+&tdmin_a {
+ status = "okay";
+};
+
+&tdmin_b {
+ status = "okay";
+};
+
+&tdmin_c {
+ status = "okay";
+};
+
+&tdmin_lb {
+ status = "okay";
+};
+
+&tdmout_a {
+ status = "okay";
+};
+
+&tdmout_b {
+ status = "okay";
+};
+
+&tdmout_c {
+ status = "okay";
+};
+
+&toacodec {
+ status = "okay";
+};
+
+&toddr_a {
+ status = "okay";
+};
+
+&toddr_b {
+ status = "okay";
+};
+
+&toddr_c {
+ status = "okay";
+};
+
+&tohdmitx {
+ status = "okay";
+};
+
&uart_AO {
status = "okay";
pinctrl-0 = <&uart_ao_a_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts
index 7ca904f5acbb..4969a76460fa 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts
@@ -155,9 +155,9 @@
"TDMOUT_B IN 1", "FRDDR_B OUT 1",
"TDMOUT_B IN 2", "FRDDR_C OUT 1",
"TDM_B Playback", "TDMOUT_B OUT",
- "SPDIFOUT IN 0", "FRDDR_A OUT 3",
- "SPDIFOUT IN 1", "FRDDR_B OUT 3",
- "SPDIFOUT IN 2", "FRDDR_C OUT 3";
+ "SPDIFOUT_A IN 0", "FRDDR_A OUT 3",
+ "SPDIFOUT_A IN 1", "FRDDR_B OUT 3",
+ "SPDIFOUT_A IN 2", "FRDDR_C OUT 3";
assigned-clocks = <&clkc CLKID_MPLL2>,
<&clkc CLKID_MPLL0>,
@@ -196,7 +196,7 @@
/* spdif hdmi or toslink interface */
dai-link-4 {
- sound-dai = <&spdifout>;
+ sound-dai = <&spdifout_a>;
codec-0 {
sound-dai = <&spdif_dit>;
@@ -456,7 +456,7 @@
vqmmc-supply = <&flash_1v8>;
};
-&spdifout {
+&spdifout_a {
pinctrl-0 = <&spdif_out_h_pins>;
pinctrl-names = "default";
status = "okay";
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-libretech-cc.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-libretech-cc.dts
new file mode 100644
index 000000000000..65b963d794cd
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-libretech-cc.dts
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/clock/g12a-clkc.h>
+#include "meson-g12b-a311d.dtsi"
+#include "meson-libretech-cottonwood.dtsi"
+
+/ {
+ compatible = "libretech,aml-a311d-cc", "amlogic,a311d", "amlogic,g12b";
+ model = "Libre Computer AML-A311D-CC Alta";
+
+ vddcpu_a: regulator-vddcpu-a {
+ compatible = "pwm-regulator";
+ regulator-name = "VDDCPU_A";
+ regulator-min-microvolt = <730000>;
+ regulator-max-microvolt = <1011000>;
+ regulator-boot-on;
+ regulator-always-on;
+ pwm-supply = <&dc_in>;
+ pwms = <&pwm_ab 0 1250 0>;
+ pwm-dutycycle-range = <100 0>;
+ };
+
+ sound {
+ model = "LC-ALTA";
+ audio-routing = "TDMOUT_A IN 0", "FRDDR_A OUT 0",
+ "TDMOUT_A IN 1", "FRDDR_B OUT 0",
+ "TDMOUT_A IN 2", "FRDDR_C OUT 0",
+ "TDM_A Playback", "TDMOUT_A OUT",
+ "TDMOUT_B IN 0", "FRDDR_A OUT 1",
+ "TDMOUT_B IN 1", "FRDDR_B OUT 1",
+ "TDMOUT_B IN 2", "FRDDR_C OUT 1",
+ "TDM_B Playback", "TDMOUT_B OUT",
+ "TDMOUT_C IN 0", "FRDDR_A OUT 2",
+ "TDMOUT_C IN 1", "FRDDR_B OUT 2",
+ "TDMOUT_C IN 2", "FRDDR_C OUT 2",
+ "TDM_C Playback", "TDMOUT_C OUT",
+ "TDMIN_A IN 0", "TDM_A Capture",
+ "TDMIN_B IN 0", "TDM_A Capture",
+ "TDMIN_C IN 0", "TDM_A Capture",
+ "TDMIN_A IN 3", "TDM_A Loopback",
+ "TDMIN_B IN 3", "TDM_A Loopback",
+ "TDMIN_C IN 3", "TDM_A Loopback",
+ "TDMIN_A IN 1", "TDM_B Capture",
+ "TDMIN_B IN 1", "TDM_B Capture",
+ "TDMIN_C IN 1", "TDM_B Capture",
+ "TDMIN_A IN 4", "TDM_B Loopback",
+ "TDMIN_B IN 4", "TDM_B Loopback",
+ "TDMIN_C IN 4", "TDM_B Loopback",
+ "TDMIN_A IN 2", "TDM_C Capture",
+ "TDMIN_B IN 2", "TDM_C Capture",
+ "TDMIN_C IN 2", "TDM_C Capture",
+ "TDMIN_A IN 5", "TDM_C Loopback",
+ "TDMIN_B IN 5", "TDM_C Loopback",
+ "TDMIN_C IN 5", "TDM_C Loopback",
+ "TODDR_A IN 0", "TDMIN_A OUT",
+ "TODDR_B IN 0", "TDMIN_A OUT",
+ "TODDR_C IN 0", "TDMIN_A OUT",
+ "TODDR_A IN 1", "TDMIN_B OUT",
+ "TODDR_B IN 1", "TDMIN_B OUT",
+ "TODDR_C IN 1", "TDMIN_B OUT",
+ "TODDR_A IN 2", "TDMIN_C OUT",
+ "TODDR_B IN 2", "TDMIN_C OUT",
+ "TODDR_C IN 2", "TDMIN_C OUT",
+ "Lineout", "ACODEC LOLP",
+ "Lineout", "ACODEC LORP";
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vddcpu_b>;
+ operating-points-v2 = <&cpu_opp_table_0>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu1 {
+ cpu-supply = <&vddcpu_b>;
+ operating-points-v2 = <&cpu_opp_table_0>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu100 {
+ cpu-supply = <&vddcpu_a>;
+ operating-points-v2 = <&cpub_opp_table_1>;
+ clocks = <&clkc CLKID_CPUB_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu101 {
+ cpu-supply = <&vddcpu_a>;
+ operating-points-v2 = <&cpub_opp_table_1>;
+ clocks = <&clkc CLKID_CPUB_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu102 {
+ cpu-supply = <&vddcpu_a>;
+ operating-points-v2 = <&cpub_opp_table_1>;
+ clocks = <&clkc CLKID_CPUB_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu103 {
+ cpu-supply = <&vddcpu_a>;
+ operating-points-v2 = <&cpub_opp_table_1>;
+ clocks = <&clkc CLKID_CPUB_CLK>;
+ clock-latency = <50000>;
+};
+
+&pwm_ab {
+ pinctrl-0 = <&pwm_a_e_pins>, <&pwm_b_x7_pins>;
+ clocks = <&xtal>, <&xtal>;
+ clock-names = "clkin0", "clkin1";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts
index 3e826095e792..8fc2e143cb54 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts
@@ -34,9 +34,9 @@
"TDMOUT_B IN 1", "FRDDR_B OUT 1",
"TDMOUT_B IN 2", "FRDDR_C OUT 1",
"TDM_B Playback", "TDMOUT_B OUT",
- "SPDIFOUT IN 0", "FRDDR_A OUT 3",
- "SPDIFOUT IN 1", "FRDDR_B OUT 3",
- "SPDIFOUT IN 2", "FRDDR_C OUT 3";
+ "SPDIFOUT_A IN 0", "FRDDR_A OUT 3",
+ "SPDIFOUT_A IN 1", "FRDDR_B OUT 3",
+ "SPDIFOUT_A IN 2", "FRDDR_C OUT 3";
assigned-clocks = <&clkc CLKID_MPLL2>,
<&clkc CLKID_MPLL0>,
@@ -75,7 +75,7 @@
/* spdif hdmi or toslink interface */
dai-link-4 {
- sound-dai = <&spdifout>;
+ sound-dai = <&spdifout_a>;
codec-0 {
sound-dai = <&spdif_dit>;
@@ -139,7 +139,7 @@
};
};
-&spdifout {
+&spdifout_a {
pinctrl-0 = <&spdif_out_h_pins>;
pinctrl-names = "default";
status = "okay";
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6.dts
index 098a3af6d381..ce548b373296 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6.dts
@@ -29,9 +29,9 @@
"TDMOUT_B IN 1", "FRDDR_B OUT 1",
"TDMOUT_B IN 2", "FRDDR_C OUT 1",
"TDM_B Playback", "TDMOUT_B OUT",
- "SPDIFOUT IN 0", "FRDDR_A OUT 3",
- "SPDIFOUT IN 1", "FRDDR_B OUT 3",
- "SPDIFOUT IN 2", "FRDDR_C OUT 3";
+ "SPDIFOUT_A IN 0", "FRDDR_A OUT 3",
+ "SPDIFOUT_A IN 1", "FRDDR_B OUT 3",
+ "SPDIFOUT_A IN 2", "FRDDR_C OUT 3";
assigned-clocks = <&clkc CLKID_MPLL2>,
<&clkc CLKID_MPLL0>,
@@ -70,7 +70,7 @@
/* spdif hdmi or toslink interface */
dai-link-4 {
- sound-dai = <&spdifout>;
+ sound-dai = <&spdifout_a>;
codec-0 {
sound-dai = <&spdif_dit>;
@@ -125,7 +125,7 @@
linux,rc-map-name = "rc-khadas";
};
-&spdifout {
+&spdifout_a {
pinctrl-0 = <&spdif_out_h_pins>;
pinctrl-names = "default";
status = "okay";
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
index 3c93d1898b40..292c718ee19c 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
@@ -9,11 +9,19 @@
#include "meson-gxbb-p20x.dtsi"
#include <dt-bindings/input/input.h>
+#include <dt-bindings/sound/meson-aiu.h>
/ {
compatible = "amlogic,p200", "amlogic,meson-gxbb";
model = "Amlogic Meson GXBB P200 Development Board";
+ spdif_dit: audio-codec-0 {
+ #sound-dai-cells = <0>;
+ compatible = "linux,spdif-dit";
+ status = "okay";
+ sound-name-prefix = "DIT";
+ };
+
avdd18_usb_adc: regulator-avdd18_usb_adc {
compatible = "regulator-fixed";
regulator-name = "AVDD18_USB_ADC";
@@ -57,6 +65,58 @@
press-threshold-microvolt = <0>; /* 0% */
};
};
+
+ sound {
+ compatible = "amlogic,gx-sound-card";
+ model = "P200";
+ assigned-clocks = <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>,
+ <&clkc CLKID_MPLL2>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ dai-link-0 {
+ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
+ };
+
+ dai-link-1 {
+ sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>;
+ };
+
+ dai-link-2 {
+ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
+ dai-format = "i2s";
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
+ };
+ };
+
+ dai-link-3 {
+ sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>;
+
+ codec-0 {
+ sound-dai = <&spdif_dit>;
+ };
+ };
+
+ dai-link-4 {
+ sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
+
+ codec-0 {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
+};
+
+&aiu {
+ status = "okay";
+ pinctrl-0 = <&spdif_out_y_pins>;
+ pinctrl-names = "default";
};
&ethmac {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
index 150a82f3b2d7..6f81eed83bec 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
@@ -8,10 +8,49 @@
/dts-v1/;
#include "meson-gxbb-p20x.dtsi"
+#include <dt-bindings/sound/meson-aiu.h>
/ {
compatible = "amlogic,p201", "amlogic,meson-gxbb";
model = "Amlogic Meson GXBB P201 Development Board";
+
+ sound {
+ compatible = "amlogic,gx-sound-card";
+ model = "P201";
+ assigned-clocks = <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>,
+ <&clkc CLKID_MPLL2>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ dai-link-0 {
+ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
+ };
+
+ dai-link-1 {
+ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
+ dai-format = "i2s";
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
+ };
+ };
+
+ dai-link-2 {
+ sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
+
+ codec-0 {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
+};
+
+&aiu {
+ status = "okay";
};
&ethmac {
diff --git a/arch/arm64/boot/dts/amlogic/meson-libretech-cottonwood.dtsi b/arch/arm64/boot/dts/amlogic/meson-libretech-cottonwood.dtsi
new file mode 100644
index 000000000000..35e8f5bae990
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-libretech-cottonwood.dtsi
@@ -0,0 +1,614 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#include <dt-bindings/clock/g12a-clkc.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/gpio/meson-g12a-gpio.h>
+#include <dt-bindings/sound/meson-g12a-toacodec.h>
+#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
+
+/ {
+ aliases {
+ serial0 = &uart_AO;
+ ethernet0 = &ethmac;
+ spi0 = &spifc;
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x80000000>;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ dioo2133: audio-amplifier-0 {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&gpio GPIOX_0 GPIO_ACTIVE_HIGH>;
+ VCC-supply = <&vcc_5v>;
+ sound-name-prefix = "10U2";
+ };
+
+ /* TOFIX: handle CVBS_DET on SARADC channel 0 */
+ cvbs-connector {
+ compatible = "composite-video-connector";
+
+ port {
+ cvbs_connector_in: endpoint {
+ remote-endpoint = <&cvbs_vdac_out>;
+ };
+ };
+ };
+
+ emmc_pwrseq: emmc-pwrseq {
+ compatible = "mmc-pwrseq-emmc";
+ reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>;
+ };
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_tmds_out>;
+ };
+ };
+ };
+
+ led-blue {
+ compatible = "pwm-leds";
+
+ led {
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_ACTIVITY;
+ linux,default-trigger = "heartbeat";
+ max-brightness = <255>;
+ pwms = <&pwm_ab 1 1250 0>;
+ active-low;
+ };
+ };
+
+ led-green {
+ compatible = "pwm-leds";
+
+ led {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_STATUS;
+ linux,default-trigger = "default-on";
+ max-brightness = <255>;
+ pwms = <&pwm_cd 1 1250 0>;
+ active-low;
+ };
+ };
+
+ led-orange {
+ compatible = "gpio-leds";
+
+ led {
+ color = <LED_COLOR_ID_AMBER>;
+ function = LED_FUNCTION_STANDBY;
+ gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+ panic-indicator;
+ };
+ };
+
+ dc_in: regulator-dc-in {
+ compatible = "regulator-fixed";
+ regulator-name = "5V_IN";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ flash_1v8: regulator-flash-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "FLASH_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ vin-supply = <&vcc_3v3>;
+ };
+
+ vcc_card: regulator-vcc-card {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_CARD";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vddao_3v3>;
+ gpio = <&gpio GPIOX_2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ enable-active-high;
+ gpio-open-drain;
+ };
+
+ vcc_3v3: regulator-vcc-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ vin-supply = <&vddao_3v3>;
+
+ /* FIXME: controlled by TEST_N */
+ };
+
+ vcc_5v: regulator-vcc-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ vin-supply = <&dc_in>;
+ gpio = <&gpio GPIOH_8 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ enable-active-high;
+ gpio-open-drain;
+ };
+
+ vddao_3v3: regulator-vddao_3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDDAO_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ vin-supply = <&dc_in>;
+ };
+
+ vddcpu_b: regulator-vddcpu-b {
+ compatible = "pwm-regulator";
+ regulator-name = "VDDCPU_B";
+ regulator-min-microvolt = <730000>;
+ regulator-max-microvolt = <1011000>;
+ regulator-boot-on;
+ regulator-always-on;
+ pwm-supply = <&dc_in>;
+ pwms = <&pwm_AO_cd 1 1250 0>;
+ pwm-dutycycle-range = <100 0>;
+ };
+
+ vddio_ao18: regulator-vddio_ao18 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDDIO_AO18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ vin-supply = <&vddao_3v3>;
+ };
+
+ vddio_c: regulator-vddio_c {
+ compatible = "regulator-gpio";
+ regulator-name = "VDDIO_C";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-settling-time-up-us = <200>;
+ regulator-settling-time-down-us = <50000>;
+ vin-supply = <&vddao_3v3>;
+ gpios = <&gpio GPIOX_4 GPIO_ACTIVE_HIGH>;
+ states = <3300000 0>,
+ <1800000 1>;
+ };
+
+ sound {
+ compatible = "amlogic,axg-sound-card";
+ audio-widgets = "Line", "Lineout";
+ audio-aux-devs = <&tdmout_a>, <&tdmout_b>, <&tdmout_c>,
+ <&tdmin_a>, <&tdmin_b>, <&tdmin_c>,
+ <&dioo2133>;
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ dai-link-0 {
+ sound-dai = <&frddr_a>;
+ };
+
+ dai-link-1 {
+ sound-dai = <&frddr_b>;
+ };
+
+ dai-link-2 {
+ sound-dai = <&frddr_c>;
+ };
+
+ dai-link-3 {
+ sound-dai = <&toddr_a>;
+ };
+
+ dai-link-4 {
+ sound-dai = <&toddr_b>;
+ };
+
+ dai-link-5 {
+ sound-dai = <&toddr_c>;
+ };
+
+ /*
+ * Audio setup: The 40 pins header provides access to 2 TDMs,
+ * SPDIF In/Out and PDM inputs.
+ * - TDM A: 2 lanes
+ * D0: 40/X9
+ * D1: 38/X8
+ * BCLK: 12/X11
+ * FS: 35/X10
+ * - TDM B: 4 lanes
+ * D0: 37/A3
+ * D1: 16/A4
+ * D2: 18/A5 or 7/AO6
+ * D3: 22/A6 or 21/H5
+ * BCLK: 29/A1 or 8/AO8
+ * FS: 31/A2 or 11/AO7
+ * - 2 Master Clocks:
+ * MCLK0: 15/A0 or 10/AO9
+ * MCLK1: 33/X15
+ * - SPDIF:
+ * OUT: 32/A11
+ * IN: 21/H5
+ * - PDM Input:
+ * DO: 13/A8
+ * D1: 26/A9
+ * D2: 22/A6
+ * D3: 18/A5
+ * DCLK: 36/A7
+ *
+ * TDM C is not usable on the 40 pins connector so it is
+ * setup for the HDMI 4 lanes i2s.
+ *
+ * No pinctrl is enabled by default to preserve the
+ * genericity of the 40 pins header. Many configurations are
+ * possible based on the desired use case. Please adjust TDM
+ * masks, clock setups and pinctrl accordingly.
+ */
+
+ dai-link-6 {
+ sound-dai = <&tdmif_a>;
+ dai-format = "dsp_a";
+ dai-tdm-slot-tx-mask-0 = <1 1>;
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_A>;
+ };
+
+ codec-1 {
+ sound-dai = <&toacodec TOACODEC_IN_A>;
+ };
+ };
+
+ dai-link-7 {
+ sound-dai = <&tdmif_b>;
+ dai-format = "i2s";
+ dai-tdm-slot-tx-mask-0 = <1 1>;
+ dai-tdm-slot-rx-mask-1 = <1 1>;
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>;
+ };
+
+ codec-1 {
+ sound-dai = <&toacodec TOACODEC_IN_B>;
+ };
+ };
+
+ dai-link-8 {
+ sound-dai = <&tdmif_c>;
+ dai-format = "i2s";
+ dai-tdm-slot-tx-mask-0 = <1 1>;
+ dai-tdm-slot-tx-mask-1 = <1 1>;
+ dai-tdm-slot-tx-mask-2 = <1 1>;
+ dai-tdm-slot-tx-mask-3 = <1 1>;
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_C>;
+ };
+
+ codec-1 {
+ sound-dai = <&toacodec TOACODEC_IN_C>;
+ };
+ };
+
+ dai-link-9 {
+ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+
+ dai-link-10 {
+ sound-dai = <&toacodec TOACODEC_OUT>;
+
+ codec {
+ sound-dai = <&acodec>;
+ };
+ };
+ };
+};
+
+&acodec {
+ status = "okay";
+ AVDD-supply = <&vddio_ao18>;
+};
+
+&arb {
+ status = "okay";
+};
+
+&cecb_AO {
+ status = "okay";
+ pinctrl-0 = <&cec_ao_b_h_pins>;
+ pinctrl-names = "default";
+ hdmi-phandle = <&hdmi_tx>;
+};
+
+&clkc_audio {
+ status = "okay";
+};
+
+&cvbs_vdac_port {
+ cvbs_vdac_out: endpoint {
+ remote-endpoint = <&cvbs_connector_in>;
+ };
+};
+
+&dwc3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hub: hub@1 {
+ compatible = "usb5e3,626";
+ reg = <1>;
+ reset-gpios = <&gpio GPIOC_7 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
+ vdd-supply = <&vcc_5v>;
+ };
+};
+
+&ethmac {
+ pinctrl-0 = <&eth_pins>, <&eth_rgmii_pins>, <&eth_phy_irq_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+ phy-mode = "rgmii";
+ phy-handle = <&external_phy>;
+ amlogic,tx-delay-ns = <2>;
+};
+
+&ext_mdio {
+ external_phy: ethernet-phy@0 {
+ /* Realtek RTL8211F (0x001cc916) */
+ reg = <0>;
+ max-speed = <1000>;
+
+ reset-assert-us = <100000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
+
+ interrupt-parent = <&gpio_intc>;
+ /* MAC_INTR on GPIOZ_14 */
+ interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&frddr_a {
+ status = "okay";
+};
+
+&frddr_b {
+ status = "okay";
+};
+
+&frddr_c {
+ status = "okay";
+};
+
+&hdmi_tx {
+ status = "okay";
+ pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>;
+ pinctrl-names = "default";
+ hdmi-supply = <&vcc_5v>;
+};
+
+&hdmi_tx_tmds_port {
+ hdmi_tx_tmds_out: endpoint {
+ remote-endpoint = <&hdmi_connector_in>;
+ };
+};
+
+&ir {
+ status = "okay";
+ pinctrl-0 = <&remote_input_ao_pins>;
+ pinctrl-names = "default";
+};
+
+&periphs_pinctrl {
+ spi_cs_disable_pins: spi-cs-disable {
+ mux {
+ groups = "BOOT_14";
+ function = "gpio_periphs";
+ bias-disable;
+ output-high;
+ };
+ };
+
+ eth_phy_irq_pins: eth-phy-irq {
+ mux {
+ groups = "GPIOZ_14";
+ function = "gpio_periphs";
+ bias-pull-up;
+ output-disable;
+ };
+ };
+};
+
+&pwm_AO_cd {
+ status = "okay";
+ pinctrl-0 = <&pwm_ao_d_e_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin1";
+};
+
+&pwm_ab {
+ status = "okay";
+ pinctrl-0 = <&pwm_b_x7_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin1";
+};
+
+&pwm_cd {
+ status = "okay";
+ pinctrl-0 = <&pwm_d_x3_pins>;
+ pinctrl-names = "default";
+ clocks = <&xtal>;
+ clock-names = "clkin1";
+};
+
+&saradc {
+ status = "okay";
+ vref-supply = <&vddio_ao18>;
+};
+
+/* SD card */
+&sd_emmc_b {
+ status = "okay";
+ pinctrl-0 = <&sdcard_c_pins>;
+ pinctrl-1 = <&sdcard_clk_gate_c_pins>;
+ pinctrl-names = "default", "clk-gate";
+
+ bus-width = <4>;
+ cap-sd-highspeed;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ max-frequency = <200000000>;
+ disable-wp;
+
+ cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&vcc_card>;
+ vqmmc-supply = <&vddio_c>;
+};
+
+/*
+ * EMMC_D4, EMMC_D5, EMMC_D6 and EMMC_D7 pins are shared between SPI NOR CS
+ * and eMMC Data 4 to 7 pins.
+ * Replace emmc_data_8b_pins to emmc_data_4b_pins from sd_emmc_c pinctrl-0,
+ * and change bus-width to 4 then spifc can be enabled.
+ */
+&sd_emmc_c {
+ status = "okay";
+ pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_8b_pins>, <&emmc_ds_pins>,
+ <&spi_cs_disable_pins>;
+ pinctrl-1 = <&emmc_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
+
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ max-frequency = <200000000>;
+ disable-wp;
+
+ mmc-pwrseq = <&emmc_pwrseq>;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&flash_1v8>;
+};
+
+&spifc {
+ status = "disabled";
+ pinctrl-0 = <&nor_pins>;
+ pinctrl-names = "default";
+ cs-gpios = <&gpio BOOT_14 GPIO_ACTIVE_LOW>;
+
+ w25lq128d: flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <80000000>;
+ };
+};
+
+&tdmif_a {
+ status = "okay";
+};
+
+&tdmif_b {
+ status = "okay";
+};
+
+&tdmif_c {
+ status = "okay";
+};
+
+&tdmin_a {
+ status = "okay";
+};
+
+&tdmin_b {
+ status = "okay";
+};
+
+&tdmin_c {
+ status = "okay";
+};
+
+&tdmout_a {
+ status = "okay";
+};
+
+&tdmout_b {
+ status = "okay";
+};
+
+&tdmout_c {
+ status = "okay";
+};
+
+&toacodec {
+ status = "okay";
+};
+
+&toddr_a {
+ status = "okay";
+};
+
+&toddr_b {
+ status = "okay";
+};
+
+&toddr_c {
+ status = "okay";
+};
+
+&tohdmitx {
+ status = "okay";
+};
+
+&uart_AO {
+ status = "okay";
+ pinctrl-0 = <&uart_ao_a_pins>;
+ pinctrl-names = "default";
+};
+
+&usb2_phy1 {
+ phy-supply = <&dc_in>;
+};
+
+&usb3_pcie_phy {
+ phy-supply = <&vcc_5v>;
+};
+
+&usb {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts b/arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts
index 8ffbcb2b1ac5..c1f322c73982 100644
--- a/arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts
@@ -28,3 +28,9 @@
&uart_B {
status = "okay";
};
+
+&ir {
+ status = "okay";
+ pinctrl-0 = <&remote_pins>;
+ pinctrl-names = "default";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
index f24460186d3d..e0cfc54ebccb 100644
--- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
@@ -106,6 +106,14 @@
#gpio-cells = <2>;
gpio-ranges = <&periphs_pinctrl 0 0 82>;
};
+
+ remote_pins: remote-pin {
+ mux {
+ groups = "remote_in";
+ function = "remote_in";
+ bias-disable;
+ };
+ };
};
gpio_intc: interrupt-controller@4080 {
@@ -133,6 +141,18 @@
reg = <0x0 0x2000 0x0 0x98>;
#reset-cells = <1>;
};
+
+ ir: ir@84040 {
+ compatible = "amlogic,meson-s4-ir";
+ reg = <0x0 0x84040 0x0 0x30>;
+ interrupts = <GIC_SPI 22 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ hwrng: rng@440788 {
+ compatible = "amlogic,meson-s4-rng";
+ reg = <0x0 0x440788 0x0 0x0c>;
+ };
};
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-s905d3-libretech-cc.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-s905d3-libretech-cc.dts
new file mode 100644
index 000000000000..537370db360f
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-sm1-s905d3-libretech-cc.dts
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/clock/g12a-clkc.h>
+#include "meson-sm1.dtsi"
+#include "meson-libretech-cottonwood.dtsi"
+
+/ {
+ compatible = "libretech,aml-s905d3-cc", "amlogic,sm1";
+ model = "Libre Computer AML-S905D3-CC Solitude";
+
+ sound {
+ model = "LC-SOLITUDE";
+ audio-routing = "TDMOUT_A IN 0", "FRDDR_A OUT 0",
+ "TDMOUT_A IN 1", "FRDDR_B OUT 0",
+ "TDMOUT_A IN 2", "FRDDR_C OUT 0",
+ "TDM_A Playback", "TDMOUT_A OUT",
+ "TDMOUT_B IN 0", "FRDDR_A OUT 1",
+ "TDMOUT_B IN 1", "FRDDR_B OUT 1",
+ "TDMOUT_B IN 2", "FRDDR_C OUT 1",
+ "TDM_B Playback", "TDMOUT_B OUT",
+ "TDMOUT_C IN 0", "FRDDR_A OUT 2",
+ "TDMOUT_C IN 1", "FRDDR_B OUT 2",
+ "TDMOUT_C IN 2", "FRDDR_C OUT 2",
+ "TDM_C Playback", "TDMOUT_C OUT",
+ "TDMIN_A IN 0", "TDM_A Capture",
+ "TDMIN_B IN 0", "TDM_A Capture",
+ "TDMIN_C IN 0", "TDM_A Capture",
+ "TDMIN_A IN 13", "TDM_A Loopback",
+ "TDMIN_B IN 13", "TDM_A Loopback",
+ "TDMIN_C IN 13", "TDM_A Loopback",
+ "TDMIN_A IN 1", "TDM_B Capture",
+ "TDMIN_B IN 1", "TDM_B Capture",
+ "TDMIN_C IN 1", "TDM_B Capture",
+ "TDMIN_A IN 14", "TDM_B Loopback",
+ "TDMIN_B IN 14", "TDM_B Loopback",
+ "TDMIN_C IN 14", "TDM_B Loopback",
+ "TDMIN_A IN 2", "TDM_C Capture",
+ "TDMIN_B IN 2", "TDM_C Capture",
+ "TDMIN_C IN 2", "TDM_C Capture",
+ "TDMIN_A IN 15", "TDM_C Loopback",
+ "TDMIN_B IN 15", "TDM_C Loopback",
+ "TDMIN_C IN 15", "TDM_C Loopback",
+ "TODDR_A IN 0", "TDMIN_A OUT",
+ "TODDR_B IN 0", "TDMIN_A OUT",
+ "TODDR_C IN 0", "TDMIN_A OUT",
+ "TODDR_A IN 1", "TDMIN_B OUT",
+ "TODDR_B IN 1", "TDMIN_B OUT",
+ "TODDR_C IN 1", "TDMIN_B OUT",
+ "TODDR_A IN 2", "TDMIN_C OUT",
+ "TODDR_B IN 2", "TDMIN_C OUT",
+ "TODDR_C IN 2", "TDMIN_C OUT",
+ "Lineout", "ACODEC LOLP",
+ "Lineout", "ACODEC LORP";
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vddcpu_b>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu1 {
+ cpu-supply = <&vddcpu_b>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU1_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu2 {
+ cpu-supply = <&vddcpu_b>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU2_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu3 {
+ cpu-supply = <&vddcpu_b>;
+ operating-points-v2 = <&cpu_opp_table>;
+ clocks = <&clkc CLKID_CPU3_CLK>;
+ clock-latency = <50000>;
+};
diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
index 377660d705d1..65ebac3082e2 100644
--- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
@@ -728,7 +728,7 @@
};
};
- sbgpio: gpio@17001000{
+ sbgpio: gpio@17001000 {
compatible = "apm,xgene-gpio-sb";
reg = <0x0 0x17001000 0x0 0x400>;
#gpio-cells = <2>;
diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi
index efa79209f4b2..988928c60f15 100644
--- a/arch/arm64/boot/dts/apm/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi
@@ -946,7 +946,7 @@
dr_mode = "host";
};
- sbgpio: gpio@17001000{
+ sbgpio: gpio@17001000 {
compatible = "apm,xgene-gpio-sb";
reg = <0x0 0x17001000 0x0 0x400>;
#gpio-cells = <2>;
diff --git a/arch/arm64/boot/dts/bitmain/bm1880.dtsi b/arch/arm64/boot/dts/bitmain/bm1880.dtsi
index 53a9b76057aa..22a200fb07d2 100644
--- a/arch/arm64/boot/dts/bitmain/bm1880.dtsi
+++ b/arch/arm64/boot/dts/bitmain/bm1880.dtsi
@@ -184,7 +184,7 @@
status = "disabled";
};
- uart1: serial@5801A000 {
+ uart1: serial@5801a000 {
compatible = "snps,dw-apb-uart";
reg = <0x0 0x5801a000 0x0 0x2000>;
clocks = <&clk BM1880_CLK_UART_500M>,
@@ -197,7 +197,7 @@
status = "disabled";
};
- uart2: serial@5801C000 {
+ uart2: serial@5801c000 {
compatible = "snps,dw-apb-uart";
reg = <0x0 0x5801c000 0x0 0x2000>;
clocks = <&clk BM1880_CLK_UART_500M>,
@@ -210,7 +210,7 @@
status = "disabled";
};
- uart3: serial@5801E000 {
+ uart3: serial@5801e000 {
compatible = "snps,dw-apb-uart";
reg = <0x0 0x5801e000 0x0 0x2000>;
clocks = <&clk BM1880_CLK_UART_500M>,
diff --git a/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts
index fbf0392b8371..dec5a110f1e8 100644
--- a/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts
+++ b/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts
@@ -113,7 +113,6 @@
spi-max-frequency = <5000000>;
spi-cpha;
spi-cpol;
- pl022,hierarchy = <0>;
pl022,interface = <0>;
pl022,slave-tx-disable = <0>;
pl022,com-mode = <0>;
@@ -137,7 +136,6 @@
at25,page-size = <64>;
spi-cpha;
spi-cpol;
- pl022,hierarchy = <0>;
pl022,interface = <0>;
pl022,slave-tx-disable = <0>;
pl022,com-mode = <0>;
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi
index d163891cd399..8f02de8480b6 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi
@@ -124,19 +124,18 @@
audio-amplifier = <&max98504>;
mic-bias-gpios = <&gpr3 2 GPIO_ACTIVE_HIGH>;
model = "wm5110";
- samsung,audio-routing =
- /* Headphone */
- "HP", "HPOUT1L",
- "HP", "HPOUT1R",
-
- /* Speaker */
- "SPK", "SPKOUT",
- "SPKOUT", "HPOUT2L",
- "SPKOUT", "HPOUT2R",
-
- /* Receiver */
- "RCV", "HPOUT3L",
- "RCV", "HPOUT3R";
+ audio-routing = /* Headphone */
+ "HP", "HPOUT1L",
+ "HP", "HPOUT1R",
+
+ /* Speaker */
+ "SPK", "SPKOUT",
+ "SPKOUT", "HPOUT2L",
+ "SPKOUT", "HPOUT2R",
+
+ /* Receiver */
+ "RCV", "HPOUT3L",
+ "RCV", "HPOUT3R";
};
};
@@ -1103,7 +1102,7 @@
te_irq: te-irq-pins {
samsung,pins = "gpf1-3";
- samsung,pin-function = <0xf>;
+ samsung,pin-function = <EXYNOS_PIN_FUNC_EINT>;
};
};
diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi
index 54ed5167d0f6..6ed80ddf3369 100644
--- a/arch/arm64/boot/dts/exynos/exynos7.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi
@@ -25,7 +25,6 @@
pinctrl6 = &pinctrl_fsys0;
pinctrl7 = &pinctrl_fsys1;
pinctrl8 = &pinctrl_bus1;
- tmuctrl0 = &tmuctrl_0;
};
arm-pmu {
diff --git a/arch/arm64/boot/dts/exynos/exynos850-e850-96.dts b/arch/arm64/boot/dts/exynos/exynos850-e850-96.dts
index 6ed38912507f..f074df8982b3 100644
--- a/arch/arm64/boot/dts/exynos/exynos850-e850-96.dts
+++ b/arch/arm64/boot/dts/exynos/exynos850-e850-96.dts
@@ -29,6 +29,22 @@
stdout-path = &serial_0;
};
+ connector {
+ compatible = "gpio-usb-b-connector", "usb-b-connector";
+ label = "micro-USB";
+ type = "micro";
+ vbus-supply = <&reg_usb_host_vbus>;
+ id-gpios = <&gpa0 0 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&micro_usb_det_pins>;
+
+ port {
+ usb_dr_connector: endpoint {
+ remote-endpoint = <&usb1_drd_sw>;
+ };
+ };
+ };
+
/*
* RAM: 4 GiB (eMCP):
* - 2 GiB at 0x80000000
@@ -111,6 +127,35 @@
};
};
+ /* TODO: Remove this once PMIC is implemented */
+ reg_dummy: regulator-0 {
+ compatible = "regulator-fixed";
+ regulator-name = "dummy_reg";
+ };
+
+ reg_usb_host_vbus: regulator-1 {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_host_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpa3 5 GPIO_ACTIVE_LOW>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges;
+
+ ramoops@f0000000 {
+ compatible = "ramoops";
+ reg = <0x0 0xf0000000 0x200000>;
+ record-size = <0x20000>;
+ console-size = <0x20000>;
+ ftrace-size = <0x100000>;
+ pmsg-size = <0x20000>;
+ };
+ };
+
/*
* RTC clock (XrtcXTI); external, must be 32.768 kHz.
*
@@ -172,6 +217,12 @@
samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
};
+
+ micro_usb_det_pins: micro-usb-det-pins {
+ samsung,pins = "gpa0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
};
&rtc {
@@ -186,6 +237,28 @@
pinctrl-0 = <&uart1_pins>;
};
+&usbdrd {
+ status = "okay";
+ vdd10-supply = <&reg_dummy>;
+ vdd33-supply = <&reg_dummy>;
+};
+
+&usbdrd_dwc3 {
+ dr_mode = "otg";
+ usb-role-switch;
+ role-switch-default-mode = "host";
+
+ port {
+ usb1_drd_sw: endpoint {
+ remote-endpoint = <&usb_dr_connector>;
+ };
+ };
+};
+
+&usbdrd_phy {
+ status = "okay";
+};
+
&usi_uart {
samsung,clkreq-on; /* needed for UART mode */
status = "okay";
diff --git a/arch/arm64/boot/dts/exynos/exynos850.dtsi b/arch/arm64/boot/dts/exynos/exynos850.dtsi
index aa077008b3be..53104e65b9c6 100644
--- a/arch/arm64/boot/dts/exynos/exynos850.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos850.dtsi
@@ -570,6 +570,36 @@
clocks = <&cmu_cmgp CLK_GOUT_SYSREG_CMGP_PCLK>;
};
+ usbdrd: usb@13600000 {
+ compatible = "samsung,exynos850-dwusb3";
+ ranges = <0x0 0x13600000 0x10000>;
+ clocks = <&cmu_hsi CLK_GOUT_USB_BUS_EARLY_CLK>,
+ <&cmu_hsi CLK_GOUT_USB_REF_CLK>;
+ clock-names = "bus_early", "ref";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "disabled";
+
+ usbdrd_dwc3: usb@0 {
+ compatible = "snps,dwc3";
+ reg = <0x0 0x10000>;
+ interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&usbdrd_phy 0>;
+ phy-names = "usb2-phy";
+ };
+ };
+
+ usbdrd_phy: phy@135d0000 {
+ compatible = "samsung,exynos850-usbdrd-phy";
+ reg = <0x135d0000 0x100>;
+ clocks = <&cmu_hsi CLK_GOUT_USB_PHY_ACLK>,
+ <&cmu_hsi CLK_GOUT_USB_PHY_REF_CLK>;
+ clock-names = "phy", "ref";
+ samsung,pmu-syscon = <&pmu_system_controller>;
+ #phy-cells = <1>;
+ status = "disabled";
+ };
+
usi_uart: usi@138200c0 {
compatible = "samsung,exynos850-usi";
reg = <0x138200c0 0x20>;
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 89aee6c92576..300049037eb0 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -15,12 +15,15 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-rdb.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-tqmls1043a-mbls10xxa.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-frwy.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-tqmls1046a-mbls10xxa.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1088a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1088a-rdb.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1088a-ten64.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1088a-tqmls1088a-mbls10xxa.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-rdb.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2081a-rdb.dtb
@@ -33,6 +36,7 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-clearfog-cx.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-honeycomb.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2162a-clearfog.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2162a-qds.dtb
fsl-ls1028a-qds-13bb-dtbs := fsl-ls1028a-qds.dtb fsl-ls1028a-qds-13bb.dtbo
@@ -66,6 +70,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-mx8menlo.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-nitrogen-r2.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-phg.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-phyboard-polis-rdk.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-phygate-tauri-l.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-prt8mm.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-tqma8mqml-mba8mx.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-var-som-symphony.dtb
@@ -83,6 +88,10 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-nonwifi-yavia.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-wifi-dahlia.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-wifi-dev.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-wifi-yavia.dtb
+
+imx8mm-tqma8mqml-mba8mx-lvds-tm070jvhg33-dtbs += imx8mm-tqma8mqml-mba8mx.dtb imx8mm-tqma8mqml-mba8mx-lvds-tm070jvhg33.dtbo
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-tqma8mqml-mba8mx-lvds-tm070jvhg33.dtb
+
dtb-$(CONFIG_ARCH_MXC) += imx8mn-beacon-kit.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mn-bsh-smm-s2.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mn-bsh-smm-s2pro.dtb
@@ -92,6 +101,10 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mn-ddr4-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mn-tqma8mqnl-mba8mx.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mn-var-som-symphony.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mn-venice-gw7902.dtb
+
+imx8mn-tqma8mqnl-mba8mx-lvds-tm070jvhg33-dtbs += imx8mn-tqma8mqnl-mba8mx.dtb imx8mn-tqma8mqnl-mba8mx-lvds-tm070jvhg33.dtbo
+dtb-$(CONFIG_ARCH_MXC) += imx8mn-tqma8mqnl-mba8mx-lvds-tm070jvhg33.dtb
+
dtb-$(CONFIG_ARCH_MXC) += imx8mp-beacon-kit.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-data-modul-edm-sbc.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-debix-model-a.dtb
@@ -133,6 +146,10 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mq-pico-pi.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-thor96.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-rmb3.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-zest.dtb
+
+imx8mq-tqma8mq-mba8mx-lvds-tm070jvhg33-dtbs += imx8mq-tqma8mq-mba8mx.dtb imx8mq-tqma8mq-mba8mx-lvds-tm070jvhg33.dtbo
+dtb-$(CONFIG_ARCH_MXC) += imx8mq-tqma8mq-mba8mx-lvds-tm070jvhg33.dtb
+
dtb-$(CONFIG_ARCH_MXC) += imx8qm-apalis-eval.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8qm-apalis-ixora-v1.1.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8qm-apalis-v1.1-eval.dtb
@@ -159,6 +176,7 @@ imx8mm-venice-gw73xx-0x-rpidsi-dtbs := imx8mm-venice-gw73xx-0x.dtb imx8mm-venice
imx8mm-venice-gw73xx-0x-rs232-rts-dtbs := imx8mm-venice-gw73xx-0x.dtb imx8mm-venice-gw73xx-0x-rs232-rts.dtbo
imx8mm-venice-gw73xx-0x-rs422-dtbs := imx8mm-venice-gw73xx-0x.dtb imx8mm-venice-gw73xx-0x-rs422.dtbo
imx8mm-venice-gw73xx-0x-rs485-dtbs := imx8mm-venice-gw73xx-0x.dtb imx8mm-venice-gw73xx-0x-rs485.dtbo
+imx8mp-venice-gw74xx-imx219-dtbs := imx8mp-venice-gw74xx.dtb imx8mp-venice-gw74xx-imx219.dtbo
imx8mp-venice-gw74xx-rpidsi-dtbs := imx8mp-venice-gw74xx.dtb imx8mp-venice-gw74xx-rpidsi.dtbo
dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw72xx-0x-imx219.dtb
@@ -171,6 +189,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw73xx-0x-rpidsi.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw73xx-0x-rs232-rts.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw73xx-0x-rs422.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw73xx-0x-rs485.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw74xx-imx219.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw74xx-rpidsi.dtb
dtb-$(CONFIG_ARCH_S32) += s32g274a-evb.dtb
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-tqmls1043a-mbls10xxa.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-tqmls1043a-mbls10xxa.dts
new file mode 100644
index 000000000000..03748a7f657b
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-tqmls1043a-mbls10xxa.dts
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2018-2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Gregor Herburger, Timo Herbrecher
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "fsl-ls1043a-tqmls1043a.dtsi"
+#include "tqmls10xxa-mbls10xxa.dtsi"
+
+/ {
+ model = "TQ-Systems GmbH LS1043A TQMLS1043A SoM on MBLS10xxA board";
+ compatible = "tq,ls1043a-tqmls1043a-mbls10xxa", "tq,ls1043a-tqmls1043a",
+ "fsl,ls1043a";
+
+ aliases {
+ qsgmii-s1-p1 = &qsgmii1_phy1;
+ qsgmii-s1-p2 = &qsgmii1_phy2;
+ qsgmii-s1-p3 = &qsgmii1_phy3;
+ qsgmii-s1-p4 = &qsgmii1_phy4;
+ qsgmii-s2-p1 = &qsgmii2_phy1;
+ qsgmii-s2-p2 = &qsgmii2_phy2;
+ qsgmii-s2-p3 = &qsgmii2_phy3;
+ qsgmii-s2-p4 = &qsgmii2_phy4;
+ serial0 = &duart0;
+ serial1 = &duart1;
+ };
+
+ chosen {
+ stdout-path = &duart1;
+ };
+};
+
+&esdhc {
+ cd-gpios = <&gpio3 2 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio3 3 GPIO_ACTIVE_HIGH>;
+};
+
+&usb2 {
+ status = "okay";
+};
+
+#include "fsl-ls1043-post.dtsi"
+#include "tqmls104xa-mbls10xxa-fman.dtsi"
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-tqmls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a-tqmls1043a.dtsi
new file mode 100644
index 000000000000..12d5f3938e5d
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-tqmls1043a.dtsi
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2018-2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Gregor Herburger, Timo Herbrecher
+ *
+ * Device Tree Include file for LS1043A based SoM of TQ
+ */
+
+#include "fsl-ls1043a.dtsi"
+#include "tqmls10xxa.dtsi"
+
+&qspi {
+ num-cs = <2>;
+ status = "okay";
+
+ qflash0: flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <62500000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index f8acbefc805b..229bb4bebe42 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -526,20 +526,6 @@
status = "disabled";
};
- dspi1: spi@2110000 {
- compatible = "fsl,ls1043a-dspi", "fsl,ls1021a-v1.0-dspi";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x2110000 0x0 0x10000>;
- interrupts = <0 65 0x4>;
- clock-names = "dspi";
- clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
- QORIQ_CLK_PLL_DIV(1)>;
- spi-num-chipselects = <5>;
- big-endian;
- status = "disabled";
- };
-
i2c0: i2c@2180000 {
compatible = "fsl,ls1043a-i2c", "fsl,vf610-i2c";
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-tqmls1046a-mbls10xxa.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-tqmls1046a-mbls10xxa.dts
new file mode 100644
index 000000000000..37834ae3deac
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-tqmls1046a-mbls10xxa.dts
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2018-2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Gregor Herburger, Timo Herbrecher
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "fsl-ls1046a-tqmls1046a.dtsi"
+#include "tqmls10xxa-mbls10xxa.dtsi"
+
+/ {
+ model = "TQ-Systems GmbH LS1046A TQMLS1046A SoM on MBLS10xxA board";
+ compatible = "tq,ls1046a-tqmls1046a-mbls10xxa", "tq,ls1046a-tqmls1046a",
+ "fsl,ls1046a";
+
+ aliases {
+ qsgmii-s1-p1 = &qsgmii1_phy1;
+ qsgmii-s1-p2 = &qsgmii1_phy2;
+ qsgmii-s1-p3 = &qsgmii1_phy3;
+ qsgmii-s1-p4 = &qsgmii1_phy4;
+ qsgmii-s2-p1 = &qsgmii2_phy1;
+ qsgmii-s2-p2 = &qsgmii2_phy2;
+ qsgmii-s2-p3 = &qsgmii2_phy3;
+ qsgmii-s2-p4 = &qsgmii2_phy4;
+ serial0 = &duart0;
+ serial1 = &duart1;
+ };
+
+ chosen {
+ stdout-path = &duart1;
+ };
+};
+
+&dspi {
+ status = "okay";
+};
+
+&esdhc {
+ cd-gpios = <&gpio3 2 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio3 3 GPIO_ACTIVE_HIGH>;
+};
+
+&usb2 {
+ status = "okay";
+};
+
+#include "fsl-ls1046-post.dtsi"
+#include "tqmls104xa-mbls10xxa-fman.dtsi"
+
+&enet7 {
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-tqmls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a-tqmls1046a.dtsi
new file mode 100644
index 000000000000..4a8f8bc688f5
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-tqmls1046a.dtsi
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2018-2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Gregor Herburger, Timo Herbrecher
+ *
+ * Device Tree Include file for LS1046A based SoM of TQ
+ */
+
+#include "fsl-ls1046a.dtsi"
+#include "tqmls10xxa.dtsi"
+
+&qspi {
+ num-cs = <2>;
+ status = "okay";
+
+ qflash0: flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <62500000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+ };
+
+ qflash1: flash@1 {
+ compatible = "jedec,spi-nor";
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <62500000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-tqmls1088a-mbls10xxa.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-tqmls1088a-mbls10xxa.dts
new file mode 100644
index 000000000000..e567918f6afc
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-tqmls1088a-mbls10xxa.dts
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2018-2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Gregor Herburger, Timo Herbrecher
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "fsl-ls1088a-tqmls1088a.dtsi"
+#include "tqmls10xxa-mbls10xxa.dtsi"
+
+/ {
+ model = "TQ-Systems GmbH LS1088A TQMLS1088A SoM on MBLS10xxA board";
+ compatible = "tq,ls1088a-tqmls1088a-mbls10xxa", "tq,ls1088a-tqmls1088a",
+ "fsl,ls1088a";
+
+ aliases {
+ dpmac1 = &dpmac1;
+ dpmac2 = &dpmac2;
+ dpmac3 = &dpmac3;
+ dpmac4 = &dpmac4;
+ dpmac5 = &dpmac5;
+ dpmac6 = &dpmac6;
+ dpmac7 = &dpmac7;
+ dpmac8 = &dpmac8;
+ dpmac9 = &dpmac9;
+ dpmac10 = &dpmac10;
+ qsgmii-s1-p1 = &qsgmii1_phy1;
+ qsgmii-s1-p2 = &qsgmii1_phy2;
+ qsgmii-s1-p3 = &qsgmii1_phy3;
+ qsgmii-s1-p4 = &qsgmii1_phy4;
+ qsgmii-s2-p1 = &qsgmii2_phy1;
+ qsgmii-s2-p2 = &qsgmii2_phy2;
+ qsgmii-s2-p3 = &qsgmii2_phy3;
+ qsgmii-s2-p4 = &qsgmii2_phy4;
+ rgmii-s1 = &rgmii_phy1;
+ rgmii-s2 = &rgmii_phy2;
+ serial0 = &duart0;
+ serial1 = &duart1;
+ };
+
+ chosen {
+ stdout-path = &duart1;
+ };
+};
+
+&esdhc {
+ cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
+};
+
+&sfp1_i2c {
+ status = "okay";
+};
+
+&sfp2_i2c {
+ status = "okay";
+};
+
+#include "tqmls1088a-mbls10xxa-mc.dtsi"
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-tqmls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a-tqmls1088a.dtsi
new file mode 100644
index 000000000000..9a0f21484be9
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-tqmls1088a.dtsi
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2018-2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Gregor Herburger, Timo Herbrecher
+ *
+ * Device Tree Include file for LS1088A based SoM of TQ
+ */
+
+#include "fsl-ls1088a.dtsi"
+#include "tqmls10xxa.dtsi"
+
+&qspi {
+ num-cs = <2>;
+ status = "okay";
+
+ qflash0: flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <62500000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+ };
+
+ qflash1: flash@1 {
+ compatible = "jedec,spi-nor";
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <62500000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
index d2f5345d0560..717288bbdb8b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
@@ -1186,26 +1186,34 @@
dma-coherent;
};
- usb0: usb@3100000 {
- status = "disabled";
- compatible = "snps,dwc3";
- reg = <0x0 0x3100000 0x0 0x10000>;
- interrupts = <0 80 0x4>; /* Level high type */
- dr_mode = "host";
- snps,quirk-frame-length-adjustment = <0x20>;
- snps,dis_rxdet_inp3_quirk;
- snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
- };
+ bus: bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "simple-bus";
+ ranges;
+ dma-ranges = <0x0 0x0 0x0 0x0 0x100 0x00000000>;
+
+ usb0: usb@3100000 {
+ compatible = "snps,dwc3";
+ reg = <0x0 0x3100000 0x0 0x10000>;
+ interrupts = <0 80 0x4>; /* Level high type */
+ dr_mode = "host";
+ snps,quirk-frame-length-adjustment = <0x20>;
+ snps,dis_rxdet_inp3_quirk;
+ snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
+ status = "disabled";
+ };
- usb1: usb@3110000 {
- status = "disabled";
- compatible = "snps,dwc3";
- reg = <0x0 0x3110000 0x0 0x10000>;
- interrupts = <0 81 0x4>; /* Level high type */
- dr_mode = "host";
- snps,quirk-frame-length-adjustment = <0x20>;
- snps,dis_rxdet_inp3_quirk;
- snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
+ usb1: usb@3110000 {
+ compatible = "snps,dwc3";
+ reg = <0x0 0x3110000 0x0 0x10000>;
+ interrupts = <0 81 0x4>; /* Level high type */
+ dr_mode = "host";
+ snps,quirk-frame-length-adjustment = <0x20>;
+ snps,dis_rxdet_inp3_quirk;
+ snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
+ status = "disabled";
+ };
};
ccn@4000000 {
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
index ea6a94b57aeb..f176ca2e244e 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
@@ -626,6 +626,13 @@
#phy-cells = <1>;
};
+ serdes_2: phy@1eb0000 {
+ compatible = "fsl,lynx-28g";
+ reg = <0x0 0x1eb0000 0x0 0x1e30>;
+ #phy-cells = <1>;
+ status = "disabled";
+ };
+
crypto: crypto@8000000 {
compatible = "fsl,sec-v5.0", "fsl,sec-v4.0";
fsl,sec-era = <10>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts b/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts
new file mode 100644
index 000000000000..9f88583aa25e
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts
@@ -0,0 +1,376 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+//
+// Device Tree file for LX2162A Clearfog
+//
+// Copyright 2023 Josua Mayer <josua@solid-run.com>
+
+/dts-v1/;
+
+#include "fsl-lx2160a.dtsi"
+#include "fsl-lx2162a-sr-som.dtsi"
+
+/ {
+ model = "SolidRun LX2162A Clearfog";
+ compatible = "solidrun,lx2162a-clearfog", "solidrun,lx2162a-som", "fsl,lx2160a";
+
+ aliases {
+ crypto = &crypto;
+ i2c0 = &i2c0;
+ i2c1 = &i2c2;
+ i2c2 = &i2c4;
+ i2c3 = &sfp_i2c0;
+ i2c4 = &sfp_i2c1;
+ i2c5 = &sfp_i2c2;
+ i2c6 = &sfp_i2c3;
+ i2c7 = &mpcie1_i2c;
+ i2c8 = &mpcie0_i2c;
+ i2c9 = &pcieclk_i2c;
+ mmc0 = &esdhc0;
+ mmc1 = &esdhc1;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led_sfp_at: led-sfp-at {
+ gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; /* PROC_IRQ5 */
+ default-state = "off";
+ };
+
+ led_sfp_ab: led-sfp-ab {
+ gpios = <&gpio2 11 GPIO_ACTIVE_HIGH>; /* PROC_IRQ11 */
+ default-state = "off";
+ };
+
+ led_sfp_bt: led-sfp-bt {
+ gpios = <&gpio2 13 GPIO_ACTIVE_HIGH>; /* EVT1_B */
+ default-state = "off";
+ };
+
+ led_sfp_bb: led-sfp-bb {
+ gpios = <&gpio2 14 GPIO_ACTIVE_HIGH>; /* EVT2_B */
+ default-state = "off";
+ };
+ };
+
+ sfp_at: sfp-at {
+ compatible = "sff,sfp";
+ i2c-bus = <&sfp_i2c0>;
+ mod-def0-gpios = <&gpio2 16 GPIO_ACTIVE_LOW>; /* EVT4_B */
+ maximum-power-milliwatt = <2000>;
+ };
+
+ sfp_ab: sfp-ab {
+ compatible = "sff,sfp";
+ i2c-bus = <&sfp_i2c1>;
+ mod-def0-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>; /* PROC_IRQ1 */
+ maximum-power-milliwatt = <2000>;
+ };
+
+ sfp_bt: sfp-bt {
+ compatible = "sff,sfp";
+ i2c-bus = <&sfp_i2c2>;
+ mod-def0-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>; /* PROC_IRQ10 */
+ maximum-power-milliwatt = <2000>;
+ };
+
+ sfp_bb: sfp-bb {
+ compatible = "sff,sfp";
+ i2c-bus = <&sfp_i2c3>;
+ mod-def0-gpios = <&gpio2 15 GPIO_ACTIVE_LOW>; /* EVT3_B */
+ maximum-power-milliwatt = <2000>;
+ };
+};
+
+&dpmac3 {
+ sfp = <&sfp_at>;
+ managed = "in-band-status";
+ phys = <&serdes_1 7>;
+};
+
+&dpmac4 {
+ sfp = <&sfp_ab>;
+ managed = "in-band-status";
+ phys = <&serdes_1 6>;
+};
+
+&dpmac5 {
+ sfp = <&sfp_bt>;
+ managed = "in-band-status";
+ phys = <&serdes_1 5>;
+};
+
+&dpmac6 {
+ sfp = <&sfp_bb>;
+ managed = "in-band-status";
+ phys = <&serdes_1 4>;
+};
+
+&dpmac11 {
+ phys = <&serdes_2 0>;
+ phy-handle = <&ethernet_phy3>;
+ phy-connection-type = "sgmii";
+ status = "okay";
+};
+
+&dpmac12 {
+ phys = <&serdes_2 1>;
+ phy-handle = <&ethernet_phy1>;
+ phy-connection-type = "sgmii";
+ status = "okay";
+};
+
+&dpmac13 {
+ phys = <&serdes_2 6>;
+ phy-handle = <&ethernet_phy6>;
+ phy-connection-type = "sgmii";
+ status = "okay";
+};
+
+&dpmac14 {
+ phys = <&serdes_2 7>;
+ phy-handle = <&ethernet_phy8>;
+ phy-connection-type = "sgmii";
+ status = "okay";
+};
+
+&dpmac15 {
+ phys = <&serdes_2 4>;
+ phy-handle = <&ethernet_phy4>;
+ phy-connection-type = "sgmii";
+ status = "okay";
+};
+
+&dpmac16 {
+ phys = <&serdes_2 5>;
+ phy-handle = <&ethernet_phy2>;
+ phy-connection-type = "sgmii";
+ status = "okay";
+};
+
+&dpmac17 {
+ /* override connection to on-SoM phy */
+ /delete-property/ phy-handle;
+ /delete-property/ phy-connection-type;
+
+ phys = <&serdes_2 2>;
+ phy-handle = <&ethernet_phy5>;
+ phy-connection-type = "sgmii";
+ status = "okay";
+};
+
+&dpmac18 {
+ phys = <&serdes_2 3>;
+ phy-handle = <&ethernet_phy7>;
+ phy-connection-type = "sgmii";
+ status = "okay";
+};
+
+&emdio1 {
+ ethernet_phy1: ethernet-phy@8 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <8>;
+ max-speed = <1000>;
+ };
+
+ ethernet_phy2: ethernet-phy@9 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <9>;
+ max-speed = <1000>;
+ };
+
+ ethernet_phy3: ethernet-phy@10 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <10>;
+ max-speed = <1000>;
+ };
+
+ ethernet_phy4: ethernet-phy@11 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <11>;
+ max-speed = <1000>;
+ };
+
+ ethernet_phy5: ethernet-phy@12 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <12>;
+ max-speed = <1000>;
+ };
+
+ ethernet_phy6: ethernet-phy@13 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <13>;
+ max-speed = <1000>;
+ };
+
+ ethernet_phy7: ethernet-phy@14 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <14>;
+ max-speed = <1000>;
+ };
+
+ ethernet_phy8: ethernet-phy@15 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <15>;
+ max-speed = <1000>;
+ };
+};
+
+&esdhc0 {
+ sd-uhs-sdr104;
+ sd-uhs-sdr50;
+ sd-uhs-sdr25;
+ sd-uhs-sdr12;
+ status = "okay";
+};
+
+&ethernet_phy0 {
+ /*
+ * SoM has a phy at address 1 connected to SoC Ethernet Controller 1.
+ * It competes for WRIOP MAC17, and no connector has been wired.
+ */
+ status = "disabled";
+};
+
+&i2c2 {
+ status = "okay";
+
+ /* retimer@18 */
+
+ i2c-mux@70 {
+ compatible = "nxp,pca9546";
+ reg = <0x70>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-mux-idle-disconnect;
+
+ sfp_i2c0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ sfp_i2c1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ sfp_i2c2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ sfp_i2c3: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+ };
+
+ i2c-mux@71 {
+ compatible = "nxp,pca9546";
+ reg = <0x71>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-mux-idle-disconnect;
+
+ mpcie1_i2c: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ mpcie0_i2c: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ pcieclk_i2c: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+
+ /* clock-controller@6b */
+ };
+ };
+};
+
+&pcie3 {
+ status = "disabled";
+};
+
+&pcie4 {
+ status = "disabled";
+};
+
+&pcs_mdio3 {
+ status = "okay";
+};
+
+&pcs_mdio4 {
+ status = "okay";
+};
+
+&pcs_mdio5 {
+ status = "okay";
+};
+
+&pcs_mdio6 {
+ status = "okay";
+};
+
+&pcs_mdio11 {
+ status = "okay";
+};
+
+&pcs_mdio12 {
+ status = "okay";
+};
+
+&pcs_mdio13 {
+ status = "okay";
+};
+
+&pcs_mdio14 {
+ status = "okay";
+};
+
+&pcs_mdio15 {
+ status = "okay";
+};
+
+&pcs_mdio16 {
+ status = "okay";
+};
+
+&pcs_mdio17 {
+ status = "okay";
+};
+
+&pcs_mdio18 {
+ status = "okay";
+};
+
+&serdes_1 {
+ status = "okay";
+};
+
+&serdes_2 {
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2162a-sr-som.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2162a-sr-som.dtsi
new file mode 100644
index 000000000000..0580ea30cfbc
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2162a-sr-som.dtsi
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+//
+// Device Tree file for LX2162A-SOM
+//
+// Copyright 2021 Rabeeh Khoury <rabeeh@solid-run.com>
+// Copyright 2023 Josua Mayer <josua@solid-run.com>
+
+&crypto {
+ status = "okay";
+};
+
+&dpmac17 {
+ phy-handle = <&ethernet_phy0>;
+ phy-connection-type = "rgmii-id";
+};
+
+&emdio1 {
+ status = "okay";
+
+ ethernet_phy0: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
+&esdhc1 {
+ bus-width = <8>;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ status = "okay";
+};
+
+&fspi {
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ m25p,fast-read;
+ spi-max-frequency = <50000000>;
+ /* The following setting enables 1-1-8 (CMD-ADDR-DATA) mode */
+ spi-rx-bus-width = <8>;
+ spi-tx-bus-width = <1>;
+ };
+};
+
+&i2c0 {
+ status = "okay";
+
+ fan-controller@18 {
+ compatible = "ti,amc6821";
+ reg = <0x18>;
+ };
+
+ ddr_spd: eeprom@51 {
+ compatible = "st,24c02", "atmel,24c02";
+ reg = <0x51>;
+ read-only;
+ };
+
+ config_eeprom: eeprom@57 {
+ compatible = "st,24c02", "atmel,24c02";
+ reg = <0x57>;
+ };
+};
+
+&i2c4 {
+ status = "okay";
+
+ variable_eeprom: eeprom@54 {
+ compatible = "st,24c2048", "atmel,24c2048";
+ reg = <0x54>;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi
index c6d51f116298..5438923a905c 100644
--- a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi
@@ -165,7 +165,6 @@
"gpio5-24", "UART24-FORCEOFF", "gpio5-26",
"LED-4-GREEN", "gpio5-28", "LED-4-RED", "gpio5-30",
"gpio5-31";
- ngpios = <32>;
};
/* Apalis PWM3, MXM3 pin 6 */
diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi
index 40067ab8aa74..72136c436a70 100644
--- a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi
@@ -212,7 +212,6 @@
"gpio5-24", "UART24-FORCEOFF", "gpio5-26",
"LED-4-GREEN", "gpio5-28", "LED-4-RED", "gpio5-30",
"gpio5-31";
- ngpios = <32>;
};
/* Apalis PWM3, MXM3 pin 6 */
diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
index 9b1b522517f8..f69b0c17560a 100644
--- a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
@@ -82,12 +82,9 @@
pinctrl-0 = <&pinctrl_wifi_pdn>;
gpio = <&lsio_gpio1 28 GPIO_ACTIVE_HIGH>;
enable-active-high;
+ regulator-always-on;
regulator-name = "wifi_pwrdn_fake_regulator";
regulator-settling-time-us = <100>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
};
reg_pcie_switch: regulator-pcie-switch {
@@ -264,7 +261,7 @@
reset-assert-us = <2>;
reset-deassert-us = <2>;
reset-gpios = <&lsio_gpio1 11 GPIO_ACTIVE_LOW>;
- reset-names = "phy-reset";
+ reset-names = "phy";
};
};
};
@@ -503,15 +500,6 @@
"MXM3_185",
"MXM3_187";
- /*
- * Add GPIO2_20 as a wakeup source:
- * Pin: 101 SC_P_SPI3_CS0 (MXM3_37/WAKE1_MICO)
- * Type: 5 SC_PAD_WAKEUP_FALL_EDGE
- * Line: 20
- */
- pad-wakeup = <IMX8QM_SPI3_CS0 5 20>;
- pad-wakeup-num = <1>;
-
pcie-wifi-hog {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pcie_wifi_refclk>;
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi
index 6c8d75ef9250..9d75ce467569 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi
@@ -7,17 +7,74 @@
#include <dt-bindings/clock/imx8-lpcg.h>
#include <dt-bindings/firmware/imx/rsrc.h>
+audio_ipg_clk: clock-audio-ipg {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <120000000>;
+ clock-output-names = "audio_ipg_clk";
+};
+
audio_subsys: bus@59000000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x59000000 0x0 0x59000000 0x1000000>;
- audio_ipg_clk: clock-audio-ipg {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <120000000>;
- clock-output-names = "audio_ipg_clk";
+ edma0: dma-controller@591f0000 {
+ compatible = "fsl,imx8qm-edma";
+ reg = <0x591f0000 0x190000>;
+ #dma-cells = <3>;
+ shared-interrupt;
+ dma-channels = <24>;
+ dma-channel-mask = <0x5c0c00>;
+ interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>, /* 0 asrc 0 */
+ <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>, /* 1 */
+ <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>, /* 2 */
+ <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>, /* 3 */
+ <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>, /* 4 */
+ <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>, /* 5 */
+ <GIC_SPI 410 IRQ_TYPE_LEVEL_HIGH>, /* 6 esai0 */
+ <GIC_SPI 410 IRQ_TYPE_LEVEL_HIGH>, /* 7 */
+ <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>, /* 8 spdif0 */
+ <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>, /* 9 */
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* 10 unused */
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* 11 unused */
+ <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>, /* 12 sai0 */
+ <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>, /* 13 */
+ <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>, /* 14 sai1 */
+ <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>, /* 15 */
+ <GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>, /* 16 sai2 */
+ <GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH>, /* 17 sai3 */
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* 18 unused */
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* 19 unused */
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* 20 unused */
+ <GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH>, /* 21 */
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* 22 unused */
+ <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH>; /* 23 unused */
+ power-domains = <&pd IMX_SC_R_DMA_0_CH0>,
+ <&pd IMX_SC_R_DMA_0_CH1>,
+ <&pd IMX_SC_R_DMA_0_CH2>,
+ <&pd IMX_SC_R_DMA_0_CH3>,
+ <&pd IMX_SC_R_DMA_0_CH4>,
+ <&pd IMX_SC_R_DMA_0_CH5>,
+ <&pd IMX_SC_R_DMA_0_CH6>,
+ <&pd IMX_SC_R_DMA_0_CH7>,
+ <&pd IMX_SC_R_DMA_0_CH8>,
+ <&pd IMX_SC_R_DMA_0_CH9>,
+ <&pd IMX_SC_R_DMA_0_CH10>,
+ <&pd IMX_SC_R_DMA_0_CH11>,
+ <&pd IMX_SC_R_DMA_0_CH12>,
+ <&pd IMX_SC_R_DMA_0_CH13>,
+ <&pd IMX_SC_R_DMA_0_CH14>,
+ <&pd IMX_SC_R_DMA_0_CH15>,
+ <&pd IMX_SC_R_DMA_0_CH16>,
+ <&pd IMX_SC_R_DMA_0_CH17>,
+ <&pd IMX_SC_R_DMA_0_CH18>,
+ <&pd IMX_SC_R_DMA_0_CH19>,
+ <&pd IMX_SC_R_DMA_0_CH20>,
+ <&pd IMX_SC_R_DMA_0_CH21>,
+ <&pd IMX_SC_R_DMA_0_CH22>,
+ <&pd IMX_SC_R_DMA_0_CH23>;
};
dsp_lpcg: clock-controller@59580000 {
@@ -65,4 +122,35 @@ audio_subsys: bus@59000000 {
memory-region = <&dsp_reserved>;
status = "disabled";
};
+
+ edma1: dma-controller@599f0000 {
+ compatible = "fsl,imx8qm-edma";
+ reg = <0x599f0000 0xc0000>;
+ #dma-cells = <3>;
+ shared-interrupt;
+ dma-channels = <11>;
+ dma-channel-mask = <0xc0>;
+ interrupts = <GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH>, /* 0 asrc 1 */
+ <GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>, /* 1 */
+ <GIC_SPI 384 IRQ_TYPE_LEVEL_HIGH>, /* 2 */
+ <GIC_SPI 385 IRQ_TYPE_LEVEL_HIGH>, /* 3 */
+ <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH>, /* 4 */
+ <GIC_SPI 387 IRQ_TYPE_LEVEL_HIGH>, /* 5 */
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* 6 unused */
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* 7 unused */
+ <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>, /* sai4 */
+ <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>; /* sai5 */
+ power-domains = <&pd IMX_SC_R_DMA_1_CH0>,
+ <&pd IMX_SC_R_DMA_1_CH1>,
+ <&pd IMX_SC_R_DMA_1_CH2>,
+ <&pd IMX_SC_R_DMA_1_CH3>,
+ <&pd IMX_SC_R_DMA_1_CH4>,
+ <&pd IMX_SC_R_DMA_1_CH5>,
+ <&pd IMX_SC_R_DMA_1_CH6>,
+ <&pd IMX_SC_R_DMA_1_CH7>,
+ <&pd IMX_SC_R_DMA_1_CH8>,
+ <&pd IMX_SC_R_DMA_1_CH9>,
+ <&pd IMX_SC_R_DMA_1_CH10>;
+ };
};
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
index fc1a5d34382b..3c42240e78e2 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
@@ -7,33 +7,33 @@
#include <dt-bindings/clock/imx8-lpcg.h>
#include <dt-bindings/firmware/imx/rsrc.h>
+conn_axi_clk: clock-conn-axi {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <333333333>;
+ clock-output-names = "conn_axi_clk";
+};
+
+conn_ahb_clk: clock-conn-ahb {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <166666666>;
+ clock-output-names = "conn_ahb_clk";
+};
+
+conn_ipg_clk: clock-conn-ipg {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <83333333>;
+ clock-output-names = "conn_ipg_clk";
+};
+
conn_subsys: bus@5b000000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x5b000000 0x0 0x5b000000 0x1000000>;
- conn_axi_clk: clock-conn-axi {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <333333333>;
- clock-output-names = "conn_axi_clk";
- };
-
- conn_ahb_clk: clock-conn-ahb {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <166666666>;
- clock-output-names = "conn_ahb_clk";
- };
-
- conn_ipg_clk: clock-conn-ipg {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <83333333>;
- clock-output-names = "conn_ipg_clk";
- };
-
usbotg1: usb@5b0d0000 {
compatible = "fsl,imx7ulp-usb", "fsl,imx6ul-usb", "fsl,imx27-usb";
reg = <0x5b0d0000 0x200>;
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
index adb98a72bdfd..b0bb77150adc 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
@@ -7,19 +7,19 @@
#include <dt-bindings/clock/imx8-lpcg.h>
#include <dt-bindings/firmware/imx/rsrc.h>
+dma_ipg_clk: clock-dma-ipg {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <120000000>;
+ clock-output-names = "dma_ipg_clk";
+};
+
dma_subsys: bus@5a000000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x5a000000 0x0 0x5a000000 0x1000000>;
- dma_ipg_clk: clock-dma-ipg {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <120000000>;
- clock-output-names = "dma_ipg_clk";
- };
-
lpspi0: spi@5a000000 {
compatible = "fsl,imx7ulp-spi";
reg = <0x5a000000 0x10000>;
@@ -86,52 +86,135 @@ dma_subsys: bus@5a000000 {
lpuart0: serial@5a060000 {
reg = <0x5a060000 0x1000>;
- interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&uart0_lpcg IMX_LPCG_CLK_4>,
<&uart0_lpcg IMX_LPCG_CLK_0>;
clock-names = "ipg", "baud";
assigned-clocks = <&clk IMX_SC_R_UART_0 IMX_SC_PM_CLK_PER>;
assigned-clock-rates = <80000000>;
power-domains = <&pd IMX_SC_R_UART_0>;
+ dma-names = "tx","rx";
+ dmas = <&edma2 9 0 0>, <&edma2 8 0 1>;
status = "disabled";
};
lpuart1: serial@5a070000 {
reg = <0x5a070000 0x1000>;
- interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&uart1_lpcg IMX_LPCG_CLK_4>,
<&uart1_lpcg IMX_LPCG_CLK_0>;
clock-names = "ipg", "baud";
assigned-clocks = <&clk IMX_SC_R_UART_1 IMX_SC_PM_CLK_PER>;
assigned-clock-rates = <80000000>;
power-domains = <&pd IMX_SC_R_UART_1>;
+ dma-names = "tx","rx";
+ dmas = <&edma2 11 0 0>, <&edma2 10 0 1>;
status = "disabled";
};
lpuart2: serial@5a080000 {
reg = <0x5a080000 0x1000>;
- interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&uart2_lpcg IMX_LPCG_CLK_4>,
<&uart2_lpcg IMX_LPCG_CLK_0>;
clock-names = "ipg", "baud";
assigned-clocks = <&clk IMX_SC_R_UART_2 IMX_SC_PM_CLK_PER>;
assigned-clock-rates = <80000000>;
power-domains = <&pd IMX_SC_R_UART_2>;
+ dma-names = "tx","rx";
+ dmas = <&edma2 13 0 0>, <&edma2 12 0 1>;
status = "disabled";
};
lpuart3: serial@5a090000 {
reg = <0x5a090000 0x1000>;
- interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&uart3_lpcg IMX_LPCG_CLK_4>,
<&uart3_lpcg IMX_LPCG_CLK_0>;
clock-names = "ipg", "baud";
assigned-clocks = <&clk IMX_SC_R_UART_3 IMX_SC_PM_CLK_PER>;
assigned-clock-rates = <80000000>;
power-domains = <&pd IMX_SC_R_UART_3>;
+ dma-names = "tx","rx";
+ dmas = <&edma2 15 0 0>, <&edma2 14 0 1>;
status = "disabled";
};
+ adma_pwm: pwm@5a190000 {
+ compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm";
+ reg = <0x5a190000 0x1000>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&adma_pwm_lpcg 1>,
+ <&adma_pwm_lpcg 0>;
+ clock-names = "ipg", "per";
+ assigned-clocks = <&clk IMX_SC_R_LCD_0_PWM_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <3>;
+ power-domains = <&pd IMX_SC_R_LCD_0_PWM_0>;
+ };
+
+ edma2: dma-controller@5a1f0000 {
+ compatible = "fsl,imx8qm-edma";
+ reg = <0x5a1f0000 0x170000>;
+ #dma-cells = <3>;
+ dma-channels = <16>;
+ interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 435 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 436 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 437 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 439 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 441 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&pd IMX_SC_R_DMA_2_CH0>,
+ <&pd IMX_SC_R_DMA_2_CH1>,
+ <&pd IMX_SC_R_DMA_2_CH2>,
+ <&pd IMX_SC_R_DMA_2_CH3>,
+ <&pd IMX_SC_R_DMA_2_CH4>,
+ <&pd IMX_SC_R_DMA_2_CH5>,
+ <&pd IMX_SC_R_DMA_2_CH6>,
+ <&pd IMX_SC_R_DMA_2_CH7>,
+ <&pd IMX_SC_R_DMA_2_CH8>,
+ <&pd IMX_SC_R_DMA_2_CH9>,
+ <&pd IMX_SC_R_DMA_2_CH10>,
+ <&pd IMX_SC_R_DMA_2_CH11>,
+ <&pd IMX_SC_R_DMA_2_CH12>,
+ <&pd IMX_SC_R_DMA_2_CH13>,
+ <&pd IMX_SC_R_DMA_2_CH14>,
+ <&pd IMX_SC_R_DMA_2_CH15>;
+ };
+
+ edma3: dma-controller@5a9f0000 {
+ compatible = "fsl,imx8qm-edma";
+ reg = <0x5a9f0000 0x90000>;
+ #dma-cells = <3>;
+ dma-channels = <8>;
+ interrupts = <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&pd IMX_SC_R_DMA_3_CH0>,
+ <&pd IMX_SC_R_DMA_3_CH1>,
+ <&pd IMX_SC_R_DMA_3_CH2>,
+ <&pd IMX_SC_R_DMA_3_CH3>,
+ <&pd IMX_SC_R_DMA_3_CH4>,
+ <&pd IMX_SC_R_DMA_3_CH5>,
+ <&pd IMX_SC_R_DMA_3_CH6>,
+ <&pd IMX_SC_R_DMA_3_CH7>;
+ };
+
spi0_lpcg: clock-controller@5a400000 {
compatible = "fsl,imx8qxp-lpcg";
reg = <0x5a400000 0x10000>;
@@ -228,6 +311,18 @@ dma_subsys: bus@5a000000 {
power-domains = <&pd IMX_SC_R_UART_3>;
};
+ adma_pwm_lpcg: clock-controller@5a590000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5a590000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&clk IMX_SC_R_LCD_0_PWM_0 IMX_SC_PM_CLK_PER>,
+ <&dma_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>;
+ clock-output-names = "adma_pwm_lpcg_clk",
+ "adma_pwm_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_LCD_0_PWM_0>;
+ };
+
i2c0: i2c@5a800000 {
reg = <0x5a800000 0x4000>;
interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi
index a90654155a88..e7783cc2d830 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi
@@ -3,25 +3,22 @@
* Copyright 2019-2021 NXP
* Zhou Guoniu <guoniu.zhou@nxp.com>
*/
+img_ipg_clk: clock-img-ipg {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <200000000>;
+ clock-output-names = "img_ipg_clk";
+};
+
img_subsys: bus@58000000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x58000000 0x0 0x58000000 0x1000000>;
- img_ipg_clk: clock-img-ipg {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <200000000>;
- clock-output-names = "img_ipg_clk";
- };
-
jpegdec: jpegdec@58400000 {
reg = <0x58400000 0x00050000>;
- interrupts = <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&img_jpeg_dec_lpcg IMX_LPCG_CLK_0>,
<&img_jpeg_dec_lpcg IMX_LPCG_CLK_4>;
clock-names = "per", "ipg";
@@ -29,18 +26,13 @@ img_subsys: bus@58000000 {
<&img_jpeg_dec_lpcg IMX_LPCG_CLK_4>;
assigned-clock-rates = <200000000>, <200000000>;
power-domains = <&pd IMX_SC_R_MJPEG_DEC_MP>,
- <&pd IMX_SC_R_MJPEG_DEC_S0>,
- <&pd IMX_SC_R_MJPEG_DEC_S1>,
- <&pd IMX_SC_R_MJPEG_DEC_S2>,
- <&pd IMX_SC_R_MJPEG_DEC_S3>;
+ <&pd IMX_SC_R_MJPEG_DEC_S0>;
+ slot = <0>;
};
jpegenc: jpegenc@58450000 {
reg = <0x58450000 0x00050000>;
- interrupts = <GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&img_jpeg_enc_lpcg IMX_LPCG_CLK_0>,
<&img_jpeg_enc_lpcg IMX_LPCG_CLK_4>;
clock-names = "per", "ipg";
@@ -48,10 +40,8 @@ img_subsys: bus@58000000 {
<&img_jpeg_enc_lpcg IMX_LPCG_CLK_4>;
assigned-clock-rates = <200000000>, <200000000>;
power-domains = <&pd IMX_SC_R_MJPEG_ENC_MP>,
- <&pd IMX_SC_R_MJPEG_ENC_S0>,
- <&pd IMX_SC_R_MJPEG_ENC_S1>,
- <&pd IMX_SC_R_MJPEG_ENC_S2>,
- <&pd IMX_SC_R_MJPEG_ENC_S3>;
+ <&pd IMX_SC_R_MJPEG_ENC_S0>;
+ slot = <0>;
};
img_jpeg_dec_lpcg: clock-controller@585d0000 {
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
index ea8c93757521..7e510b21bbac 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
@@ -7,6 +7,13 @@
#include <dt-bindings/clock/imx8-lpcg.h>
#include <dt-bindings/firmware/imx/rsrc.h>
+lsio_bus_clk: clock-lsio-bus {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ clock-output-names = "lsio_bus_clk";
+};
+
lsio_subsys: bus@5d000000 {
compatible = "simple-bus";
#address-cells = <1>;
@@ -14,20 +21,6 @@ lsio_subsys: bus@5d000000 {
ranges = <0x5d000000 0x0 0x5d000000 0x1000000>,
<0x08000000 0x0 0x08000000 0x10000000>;
- lsio_mem_clk: clock-lsio-mem {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <200000000>;
- clock-output-names = "lsio_mem_clk";
- };
-
- lsio_bus_clk: clock-lsio-bus {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <100000000>;
- clock-output-names = "lsio_bus_clk";
- };
-
lsio_pwm0: pwm@5d000000 {
compatible = "fsl,imx27-pwm";
reg = <0x5d000000 0x10000>;
@@ -36,7 +29,8 @@ lsio_subsys: bus@5d000000 {
<&pwm0_lpcg 1>;
assigned-clocks = <&clk IMX_SC_R_PWM_0 IMX_SC_PM_CLK_PER>;
assigned-clock-rates = <24000000>;
- #pwm-cells = <2>;
+ #pwm-cells = <3>;
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
@@ -48,7 +42,8 @@ lsio_subsys: bus@5d000000 {
<&pwm1_lpcg 1>;
assigned-clocks = <&clk IMX_SC_R_PWM_1 IMX_SC_PM_CLK_PER>;
assigned-clock-rates = <24000000>;
- #pwm-cells = <2>;
+ #pwm-cells = <3>;
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
@@ -60,7 +55,8 @@ lsio_subsys: bus@5d000000 {
<&pwm2_lpcg 1>;
assigned-clocks = <&clk IMX_SC_R_PWM_2 IMX_SC_PM_CLK_PER>;
assigned-clock-rates = <24000000>;
- #pwm-cells = <2>;
+ #pwm-cells = <3>;
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
@@ -72,7 +68,8 @@ lsio_subsys: bus@5d000000 {
<&pwm3_lpcg 1>;
assigned-clocks = <&clk IMX_SC_R_PWM_3 IMX_SC_PM_CLK_PER>;
assigned-clock-rates = <24000000>;
- #pwm-cells = <2>;
+ #pwm-cells = <3>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
index b9157ca08b03..b972658efb17 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
@@ -186,7 +186,6 @@
&flexspi0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexspi0>;
- nxp,fspi-dll-slvdly = <4>;
status = "okay";
mt35xu512aba0: flash@0 {
@@ -365,7 +364,6 @@
fsl,spi-only-use-cs1-sel;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lpspi3>;
- pinctrl-assert-gpios = <&pca6416_1 7 GPIO_ACTIVE_HIGH>;
status = "okay";
spidev0: spi@0 {
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
index e2eeddf38aa3..0a477f6318f1 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
@@ -15,23 +15,53 @@
interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
};
+&edma2 {
+ interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 291 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 292 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 293 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 294 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 295 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&edma3 {
+ interrupts = <GIC_SPI 296 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 297 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 298 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 301 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 303 IRQ_TYPE_LEVEL_HIGH>;
+};
+
&i2c0 {
- compatible = "fsl,imx8dxl-lpi2c", "fsl,imx8qxp-lpi2c", "fsl,imx7ulp-lpi2c";
+ compatible = "fsl,imx8dxl-lpi2c", "fsl,imx7ulp-lpi2c";
interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>;
};
&i2c1 {
- compatible = "fsl,imx8dxl-lpi2c", "fsl,imx8qxp-lpi2c", "fsl,imx7ulp-lpi2c";
+ compatible = "fsl,imx8dxl-lpi2c", "fsl,imx7ulp-lpi2c";
interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
};
&i2c2 {
- compatible = "fsl,imx8qxp-lpi2c", "fsl,imx7ulp-lpi2c";
+ compatible = "fsl,imx8dxl-lpi2c", "fsl,imx7ulp-lpi2c";
interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>;
};
&i2c3 {
- compatible = "fsl,imx8qxp-lpi2c", "fsl,imx7ulp-lpi2c";
+ compatible = "fsl,imx8dxl-lpi2c", "fsl,imx7ulp-lpi2c";
interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
index 652493ae4bb5..a414df645351 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
@@ -6,14 +6,16 @@
/delete-node/ &enet1_lpcg;
/delete-node/ &fec2;
-&conn_subsys {
+/ {
conn_enet0_root_clk: clock-conn-enet0-root {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <250000000>;
clock-output-names = "conn_enet0_root_clk";
};
+};
+&conn_subsys {
eqos: ethernet@5b050000 {
compatible = "nxp,imx8dxl-dwmac-eqos", "snps,dwmac-5.10a";
reg = <0x5b050000 0x10000>;
@@ -116,7 +118,7 @@
};
&fec1 {
- compatible = "fsl,imx8qm-fec";
+ compatible = "fsl,imx8dxl-fec", "fsl,imx8qm-fec", "fsl,imx6sx-fec";
interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl.dtsi
index 792b7224ca5b..f580eb6db9a6 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl.dtsi
@@ -122,10 +122,8 @@
&lsio_mu1 3 3>;
pd: power-controller {
- compatible = "fsl,scu-pd";
+ compatible = "fsl,imx8dl-scu-pd", "fsl,scu-pd";
#power-domain-cells = <1>;
- wakeup-irq = <160 163 235 236 237 228 229 230 231 238
- 239 240 166 169>;
};
clk: clock-controller {
@@ -168,12 +166,12 @@
};
watchdog {
- compatible = "fsl,imx-sc-wdt";
+ compatible = "fsl,imx8dxl-sc-wdt", "fsl,imx-sc-wdt";
timeout-sec = <60>;
};
tsens: thermal-sensor {
- compatible = "fsl,imx-sc-thermal";
+ compatible = "fsl,imx8dxl-sc-thermal", "fsl,imx-sc-thermal";
#thermal-sensor-cells = <1>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi
index b10e2a703a44..6086dae2e5fb 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi
@@ -6,6 +6,13 @@
#include <dt-bindings/phy/phy-imx8-pcie.h>
/ {
+
+ dmic_codec: dmic-codec {
+ compatible = "dmic-codec";
+ num-channels = <1>;
+ #sound-dai-cells = <0>;
+ };
+
leds {
compatible = "gpio-leds";
@@ -98,18 +105,46 @@
enable-active-high;
};
- sound {
- compatible = "fsl,imx-audio-wm8962";
- model = "wm8962-audio";
- audio-cpu = <&sai3>;
- audio-codec = <&wm8962>;
- audio-routing =
- "Headphone Jack", "HPOUTL",
- "Headphone Jack", "HPOUTR",
- "Ext Spk", "SPKOUTL",
- "Ext Spk", "SPKOUTR",
- "AMIC", "MICBIAS",
- "IN3R", "AMIC";
+ sound-dmic {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "dmic";
+ simple-audio-card,format = "pdm";
+ simple-audio-card,bitclock-master = <&dailink_master>;
+ simple-audio-card,frame-master = <&dailink_master>;
+
+ dailink_master: simple-audio-card,cpu {
+ sound-dai = <&micfil>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&dmic_codec>;
+ };
+ };
+
+ sound-wm8962 {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "wm8962";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,widgets = "Headphone", "Headphones",
+ "Microphone", "Headset Mic",
+ "Speaker", "Speaker";
+ simple-audio-card,routing = "Headphones", "HPOUTL",
+ "Headphones", "HPOUTR",
+ "Speaker", "SPKOUTL",
+ "Speaker", "SPKOUTR",
+ "Headset Mic", "MICBIAS",
+ "IN3R", "Headset Mic";
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai3>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&wm8962>;
+ clocks = <&clk IMX8MM_CLK_SAI3_ROOT>;
+ frame-master;
+ bitclock-master;
+ };
};
};
@@ -192,6 +227,7 @@
0x0000 /* 4:FN_DMICCDAT */
0x0000 /* 5:Default */
>;
+ #sound-dai-cells = <0>;
};
pca6416_0: gpio@20 {
@@ -215,6 +251,15 @@
};
};
+&micfil {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pdm>;
+ assigned-clocks = <&clk IMX8MM_CLK_PDM>;
+ assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <49152000>;
+ status = "okay";
+};
+
&mipi_csi {
status = "okay";
ports {
@@ -352,6 +397,13 @@
>;
};
+ pinctrl_pdm: pdmgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_RXC_PDM_CLK 0xd6
+ MX8MM_IOMUXC_SAI5_RXD0_PDM_DATA0 0xd6
+ >;
+ };
+
pinctrl_reg_usb_otg1: usbotg1grp {
fsl,pins = <
MX8MM_IOMUXC_SAI3_RXC_GPIO4_IO29 0x19
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-ddr4-evk.dts b/arch/arm64/boot/dts/freescale/imx8mm-ddr4-evk.dts
index 010e836ebe5c..27848cee1670 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-ddr4-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-ddr4-evk.dts
@@ -23,7 +23,6 @@
&gpmi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
- nand-on-flash-bbt;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phg.dts b/arch/arm64/boot/dts/freescale/imx8mm-phg.dts
index 606a4f4d5f15..75bbedc6164c 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-phg.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-phg.dts
@@ -111,6 +111,11 @@
};
};
+/* QSPI is not populated on the SoM */
+&flexspi {
+ status = "disabled";
+};
+
&ecspi1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi1>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts
new file mode 100644
index 000000000000..968f475b9a96
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts
@@ -0,0 +1,489 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2023 PHYTEC Messtechnik GmbH
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/leds/common.h>
+#include "imx8mm-phycore-som.dtsi"
+
+/ {
+ model = "PHYTEC phyGATE-Tauri-L-iMX8MM";
+ compatible = "phytec,imx8mm-phygate-tauri-l",
+ "phytec,imx8mm-phycore-som", "fsl,imx8mm";
+
+ chosen {
+ stdout-path = &uart3;
+ };
+
+ can_osc_40m: clock-can {
+ compatible = "fixed-clock";
+ clock-frequency = <40000000>;
+ clock-output-names = "can_osc_40m";
+ #clock-cells = <0>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiokeys>;
+
+ key {
+ gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+ label = "KEY-A";
+ linux,code = <KEY_A>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_leds>;
+
+ led-1 {
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&gpio5 5 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "none";
+ };
+
+ led-2 {
+ color = <LED_COLOR_ID_YELLOW>;
+ gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "none";
+ };
+ };
+
+ usdhc1_pwrseq: pwr-seq {
+ compatible = "mmc-pwrseq-simple";
+ post-power-on-delay-ms = <100>;
+ power-off-delay-us = <60>;
+ reset-gpios = <&gpio2 7 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_usb_hub_vbus: regulator-hub-otg1 {
+ compatible = "regulator-fixed";
+ gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbhubpwr>;
+ regulator-name = "usb_hub_vbus";
+ regulator-max-microvolt = <5000000>;
+ regulator-min-microvolt = <5000000>;
+ };
+
+ reg_usb_otg1_vbus: regulator-usb-otg1 {
+ compatible = "regulator-fixed";
+ gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1pwr>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-max-microvolt = <5000000>;
+ regulator-min-microvolt = <5000000>;
+ };
+
+ reg_usdhc2_vmmc: regulator-usdhc2 {
+ compatible = "regulator-fixed";
+ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ off-on-delay-us = <20000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "VSD_3V3";
+ };
+};
+
+&ecspi1 {
+ cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>,
+ <&gpio5 13 GPIO_ACTIVE_LOW>,
+ <&gpio5 2 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1 &pinctrl_ecspi1_cs>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ /* CAN MCP251XFD */
+ can0: can@0 {
+ compatible = "microchip,mcp251xfd";
+ reg = <0>;
+ clocks = <&can_osc_40m>;
+ interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can_int>;
+ spi-max-frequency = <10000000>;
+ };
+
+ tpm: tpm@1 {
+ compatible = "tcg,tpm_tis-spi";
+ interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_tpm>;
+ reg = <1>;
+ spi-max-frequency = <38000000>;
+ };
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+
+ temp_sense0: temperature-sensor@49 {
+ compatible = "ti,tmp102";
+ reg = <0x49>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <31 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_tempsense>;
+ #thermal-sensor-cells = <1>;
+ };
+};
+
+&i2c3 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+};
+
+&i2c4 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ pinctrl-1 = <&pinctrl_i2c4_gpio>;
+ scl-gpios = <&gpio5 20 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+};
+
+/* PCIe */
+&pcie0 {
+ assigned-clocks = <&clk IMX8MM_CLK_PCIE1_AUX>,
+ <&clk IMX8MM_CLK_PCIE1_PHY>,
+ <&clk IMX8MM_CLK_PCIE1_CTRL>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>,
+ <&clk IMX8MM_SYS_PLL2_100M>,
+ <&clk IMX8MM_SYS_PLL2_250M>;
+ assigned-clock-rates = <10000000>, <100000000>, <250000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie>;
+ reset-gpio = <&gpio3 22 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm3>;
+ status = "okay";
+};
+
+&pwm4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm4>;
+ status = "okay";
+};
+
+/* RTC */
+&rv3028 {
+ trickle-resistor-ohms = <3000>;
+};
+
+&uart1 {
+ assigned-clocks = <&clk IMX8MM_CLK_UART1>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+/* UART2 - RS232 */
+&uart2 {
+ assigned-clocks = <&clk IMX8MM_CLK_UART2>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+/* UART - console */
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ status = "okay";
+};
+
+/* USB */
+&usbotg1 {
+ adp-disable;
+ dr_mode = "otg";
+ over-current-active-low;
+ samsung,picophy-pre-emp-curr-control = <3>;
+ samsung,picophy-dc-vol-level-adjust = <7>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1>;
+ srp-disable;
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ status = "okay";
+};
+
+&usbotg2 {
+ disable-over-current;
+ dr_mode = "host";
+ samsung,picophy-pre-emp-curr-control = <3>;
+ samsung,picophy-dc-vol-level-adjust = <7>;
+ vbus-supply = <&reg_usb_hub_vbus>;
+ status = "okay";
+};
+
+/* SD-Card */
+&usdhc2 {
+ assigned-clocks = <&clk IMX8MM_CLK_USDHC2>;
+ assigned-clock-rates = <200000000>;
+ bus-width = <4>;
+ cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+ vqmmc-supply = <&reg_nvcc_sd2>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_can_int: can-intgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x00
+ >;
+ };
+
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI1_MISO_ECSPI1_MISO 0x82
+ MX8MM_IOMUXC_ECSPI1_MOSI_ECSPI1_MOSI 0x82
+ MX8MM_IOMUXC_ECSPI1_SCLK_ECSPI1_SCLK 0x82
+ >;
+ };
+
+ pinctrl_ecspi1_cs: ecspi1csgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI1_SS0_GPIO5_IO9 0x00
+ MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0x00
+ MX8MM_IOMUXC_SAI3_MCLK_GPIO5_IO2 0x00
+ >;
+ };
+
+ pinctrl_gpiokeys: keygrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x00
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c2
+ MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA 0x400001c2
+ >;
+ };
+
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SDA_GPIO5_IO17 0x1e0
+ MX8MM_IOMUXC_I2C2_SCL_GPIO5_IO16 0x1e0
+ >;
+ };
+
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c2
+ MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA 0x400001c2
+ >;
+ };
+
+ pinctrl_i2c3_gpio: i2c3gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SDA_GPIO5_IO19 0x1e0
+ MX8MM_IOMUXC_I2C3_SCL_GPIO5_IO18 0x1e0
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c2
+ MX8MM_IOMUXC_I2C4_SDA_I2C4_SDA 0x400001c2
+ >;
+ };
+
+ pinctrl_i2c4_gpio: i2c4gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C4_SDA_GPIO5_IO21 0x1e0
+ MX8MM_IOMUXC_I2C4_SCL_GPIO5_IO20 0x1e0
+ >;
+ };
+
+ pinctrl_leds: leds1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI3_RXD_GPIO4_IO30 0x00
+ MX8MM_IOMUXC_SPDIF_EXT_CLK_GPIO5_IO5 0x00
+ >;
+ };
+
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <
+ /* COEX2 */
+ MX8MM_IOMUXC_SAI5_RXD1_GPIO3_IO22 0x00
+ /* COEX1 */
+ MX8MM_IOMUXC_SAI1_TXD0_GPIO4_IO12 0x12
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO01_PWM1_OUT 0x40
+ >;
+ };
+
+ pinctrl_pwm3: pwm3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SPDIF_TX_PWM3_OUT 0x40
+ >;
+ };
+
+ pinctrl_pwm4: pwm4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO15_PWM4_OUT 0x40
+ >;
+ };
+
+ pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_RESET_B_GPIO2_IO19 0x40
+ >;
+ };
+
+ pinctrl_tempsense: tempsensegrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI3_TXFS_GPIO4_IO31 0x00
+ >;
+ };
+
+ pinctrl_tpm: tpmgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_STROBE_GPIO2_IO11 0x140
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART1_TXD_UART1_DCE_TX 0x00
+ MX8MM_IOMUXC_UART1_RXD_UART1_DCE_RX 0x00
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x00
+ MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x00
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART3_RXD_UART3_DCE_RX 0x140
+ MX8MM_IOMUXC_UART3_TXD_UART3_DCE_TX 0x140
+ >;
+ };
+
+ pinctrl_usbhubpwr: usbhubpwrgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO14_GPIO1_IO14 0x00
+ >;
+ };
+
+ pinctrl_usbotg1pwr: usbotg1pwrgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x00
+ >;
+ };
+
+ pinctrl_usbotg1: usbotg1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO13_USB1_OTG_OC 0x80
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x182
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0xc6
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc6
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc6
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc6
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc6
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x40
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x192
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d2
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d2
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d2
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d2
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d2
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2100mhzgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x194
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d4
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d4
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d4
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d4
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d4
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2200mhzgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x196
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d6
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d6
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d6
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d6
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d6
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx-lvds-tm070jvhg33.dtso b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx-lvds-tm070jvhg33.dtso
new file mode 100644
index 000000000000..e44249c6d8a0
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx-lvds-tm070jvhg33.dtso
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2022-2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Alexander Stein
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+ compatible = "tq,imx8mm-tqma8mqml-mba8mx", "tq,imx8mm-tqma8mqml", "fsl,imx8mm";
+};
+
+&backlight_lvds {
+ status = "okay";
+};
+
+&dsi_lvds_bridge {
+ status = "okay";
+};
+
+&expander0 {
+ dsi-mux-oe-hog {
+ gpio-hog;
+ gpios = <10 GPIO_ACTIVE_LOW>;
+ output-high;
+ line-name = "DSI_MUX_OE#";
+ };
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&mipi_dsi {
+ status = "okay";
+};
+
+&panel {
+ compatible = "tianma,tm070jvhg33";
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi
index b4466a26d838..8c0c6e715924 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi
@@ -230,6 +230,11 @@
};
};
+&mipi_dsi {
+ vddcore-supply = <&ldo4_reg>;
+ vddio-supply = <&ldo3_reg>;
+};
+
&pcie_phy {
fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
fsl,clkreq-unsupported;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
index 0ce60ad9c7d5..6425773f68e0 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
@@ -96,7 +96,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio4>;
interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "INT1";
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi
index 570992a52b75..3a0a10e835a2 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi
@@ -118,7 +118,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio4>;
interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "INT1";
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi
index 1800c6a4b1fc..d79fe9f62b95 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi
@@ -104,8 +104,15 @@
&ecspi2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi2>;
- cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+ cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>,
+ <&gpio1 10 GPIO_ACTIVE_LOW>;
status = "okay";
+
+ tpm@1 {
+ compatible = "tcg,tpm_tis-spi";
+ reg = <0x1>;
+ spi-max-frequency = <36000000>;
+ };
};
&gpio1 {
@@ -138,7 +145,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio4>;
interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "INT1";
};
};
@@ -362,6 +368,7 @@
MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0xd6
MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0xd6
MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0xd6
+ MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0xd6
>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
index ed46d4f3e66f..87b80e2412cb 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
@@ -357,6 +357,8 @@
interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
adc {
compatible = "gw,gsc-adc";
@@ -642,7 +644,6 @@
pinctrl-0 = <&pinctrl_ksz>;
interrupt-parent = <&gpio4>;
interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
- phy-mode = "rgmii-id";
ports {
#address-cells = <1>;
@@ -678,7 +679,6 @@
port@5 {
reg = <5>;
- label = "cpu";
ethernet = <&fec1>;
phy-mode = "rgmii-id";
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
index b318c2d08038..06a394a41d7c 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
@@ -314,6 +314,8 @@
interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
adc {
compatible = "gw,gsc-adc";
@@ -585,7 +587,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio1>;
interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "INT1";
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
index 0e102a12bca4..db1737bf637d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
@@ -280,6 +280,8 @@
interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
adc {
compatible = "gw,gsc-adc";
@@ -541,7 +543,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio1>;
interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "INT1";
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
index 6afbabc89c02..05489a31e7fd 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
@@ -330,6 +330,8 @@
interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
adc {
compatible = "gw,gsc-adc";
@@ -585,7 +587,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio1>;
interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "INT1";
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
index 236fe44f779d..738024baaa57 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
@@ -399,6 +399,7 @@
"pll8k", "pll11k", "clkext3";
dmas = <&sdma2 24 25 0x80000000>;
dma-names = "rx";
+ #sound-dai-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi
index 16761975f56e..20018ee2c803 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi
@@ -4,6 +4,12 @@
*/
/ {
+ dmic_codec: dmic-codec {
+ compatible = "dmic-codec";
+ num-channels = <1>;
+ #sound-dai-cells = <0>;
+ };
+
leds {
compatible = "gpio-leds";
@@ -74,6 +80,22 @@
enable-active-high;
};
+ sound-dmic {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "dmic";
+ simple-audio-card,format = "pdm";
+ simple-audio-card,bitclock-master = <&dailink_master>;
+ simple-audio-card,frame-master = <&dailink_master>;
+
+ dailink_master: simple-audio-card,cpu {
+ sound-dai = <&micfil>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&dmic_codec>;
+ };
+ };
+
sound-wm8962 {
compatible = "simple-audio-card";
simple-audio-card,name = "wm8962";
@@ -221,6 +243,15 @@
};
};
+&micfil {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pdm>;
+ assigned-clocks = <&clk IMX8MN_CLK_PDM>;
+ assigned-clock-parents = <&clk IMX8MN_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <49152000>;
+ status = "okay";
+};
+
&sai3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai3>;
@@ -311,6 +342,13 @@
>;
};
+ pinctrl_pdm: pdmgrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_SAI5_RXC_PDM_CLK 0xd6
+ MX8MN_IOMUXC_SAI5_RXD0_PDM_BIT_STREAM0 0xd6
+ >;
+ };
+
pinctrl_reg_usb_otg: reg-otggrp {
fsl,pins = <
MX8MN_IOMUXC_SAI3_RXC_GPIO4_IO29 0x19
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-bsh-smm-s2.dts b/arch/arm64/boot/dts/freescale/imx8mn-bsh-smm-s2.dts
index 7acc5a960dd9..11a1ba5bfdb7 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-bsh-smm-s2.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mn-bsh-smm-s2.dts
@@ -21,7 +21,6 @@
&gpmi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
- nand-on-flash-bbt;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi
index 0e60995a5727..3f6a19839c9e 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi
@@ -71,8 +71,6 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_wlf>;
wlf,mute-gpios = <&gpio5 21 GPIO_ACTIVE_LOW>;
- clocks = <&clk IMX8MN_CLK_SAI3_ROOT>;
- clock-names = "mclk";
};
sound-bt-sco {
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-lvds-tm070jvhg33.dtso b/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-lvds-tm070jvhg33.dtso
new file mode 100644
index 000000000000..29235e390a5d
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-lvds-tm070jvhg33.dtso
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2022-2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Alexander Stein
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+ compatible = "tq,imx8mn-tqma8mqnl-mba8mx", "tq,imx8mn-tqma8mqnl", "fsl,imx8mn";
+};
+
+&backlight_lvds {
+ status = "okay";
+};
+
+&dsi_lvds_bridge {
+ status = "okay";
+};
+
+&expander0 {
+ dsi-mux-oe-hog {
+ gpio-hog;
+ gpios = <10 GPIO_ACTIVE_LOW>;
+ output-high;
+ line-name = "DSI_MUX_OE#";
+ };
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&mipi_dsi {
+ status = "okay";
+};
+
+&panel {
+ compatible = "tianma,tm070jvhg33";
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl.dtsi
index 391ca5516e4c..fb24b9aa1b93 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl.dtsi
@@ -219,6 +219,11 @@
};
};
+&mipi_dsi {
+ vddcore-supply = <&ldo4_reg>;
+ vddio-supply = <&ldo3_reg>;
+};
+
&usdhc3 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc3>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
index 08746fb82561..0b1fa04f1d67 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
@@ -312,6 +312,8 @@
interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
adc {
compatible = "gw,gsc-adc";
@@ -583,7 +585,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio1>;
interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "INT1";
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
index aa38dd6dc9ba..1bb1d0c1bae4 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
@@ -371,6 +371,7 @@
"pll8k", "pll11k", "clkext3";
dmas = <&sdma2 24 25 0x80000000>;
dma-names = "rx";
+ #sound-dai-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts b/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts
index acd265d8b58e..0bea0798d2db 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts
@@ -23,6 +23,12 @@
stdout-path = &uart2;
};
+ clk_xtal25: clock-xtal25 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <25000000>;
+ };
+
connector {
compatible = "usb-c-connector";
label = "USB-C";
@@ -49,6 +55,12 @@
};
};
+ dmic_codec: dmic-codec {
+ compatible = "dmic-codec";
+ num-channels = <1>;
+ #sound-dai-cells = <0>;
+ };
+
gpio-keys {
compatible = "gpio-keys";
autorepeat;
@@ -112,12 +124,6 @@
};
};
- pcie0_refclk: clock-pcie {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <100000000>;
- };
-
reg_audio: regulator-wm8962 {
compatible = "regulator-fixed";
regulator-name = "3v3_aud";
@@ -147,6 +153,22 @@
enable-active-high;
};
+ sound-dmic {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "sound-pdm";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&dailink_master>;
+ simple-audio-card,frame-master = <&dailink_master>;
+
+ dailink_master: simple-audio-card,cpu {
+ sound-dai = <&micfil>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&dmic_codec>;
+ };
+ };
+
sound-wm8962 {
compatible = "simple-audio-card";
simple-audio-card,name = "wm8962";
@@ -174,6 +196,11 @@
};
};
+&audio_blk_ctrl {
+ assigned-clocks = <&clk IMX8MP_AUDIO_PLL1>, <&clk IMX8MP_AUDIO_PLL2>;
+ assigned-clock-rates = <393216000>, <135475200>;
+};
+
&ecspi2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi2>;
@@ -246,6 +273,13 @@
interrupt-controller;
#interrupt-cells = <2>;
};
+
+ pcieclk: clock-generator@68 {
+ compatible = "renesas,9fgv0241";
+ reg = <0x68>;
+ clocks = <&clk_xtal25>;
+ #clock-cells = <1>;
+ };
};
&i2c3 {
@@ -364,6 +398,15 @@
};
};
+&micfil {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pdm>;
+ assigned-clocks = <&clk IMX8MP_CLK_PDM>;
+ assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <49152000>;
+ status = "okay";
+};
+
&pcie {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pcie>;
@@ -372,8 +415,9 @@
};
&pcie_phy {
+ fsl,clkreq-unsupported;
fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
- clocks = <&pcie0_refclk>;
+ clocks = <&pcieclk 1>;
clock-names = "ref";
status = "okay";
};
@@ -545,6 +589,13 @@
>;
};
+ pinctrl_pdm: pdmgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_RXC__AUDIOMIX_PDM_CLK 0xd6
+ MX8MP_IOMUXC_SAI5_RXD0__AUDIOMIX_PDM_BIT_STREAM00 0xd6
+ >;
+ };
+
pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp {
fsl,pins = <
MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19 0x40
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts
index 13674dc64be9..d98a040860a4 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts
@@ -362,6 +362,8 @@
};
buck2: BUCK2 { /* VDD_ARM */
+ nxp,dvs-run-voltage = <950000>;
+ nxp,dvs-standby-voltage = <850000>;
regulator-min-microvolt = <850000>;
regulator-max-microvolt = <1000000>;
regulator-ramp-delay = <3125>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-debix-model-a.dts b/arch/arm64/boot/dts/freescale/imx8mp-debix-model-a.dts
index 28db9349ed62..267ceffc02d8 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-debix-model-a.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-debix-model-a.dts
@@ -284,7 +284,6 @@
usb_hub_2_x: hub@1 {
compatible = "usbbda,5411";
reg = <1>;
- reset-gpios = <&gpio4 25 GPIO_ACTIVE_LOW>;
vdd-supply = <&reg_usb_hub>;
peer-hub = <&usb_hub_3_x>;
};
@@ -293,7 +292,6 @@
usb_hub_3_x: hub@2 {
compatible = "usbbda,411";
reg = <2>;
- reset-gpios = <&gpio4 25 GPIO_ACTIVE_LOW>;
vdd-supply = <&reg_usb_hub>;
peer-hub = <&usb_hub_2_x>;
};
@@ -443,7 +441,6 @@
pinctrl_usb1: usb1grp {
fsl,pins = <
MX8MP_IOMUXC_GPIO1_IO14__USB2_OTG_PWR 0x10
- MX8MP_IOMUXC_SAI2_TXC__GPIO4_IO25 0x19
>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-debix-som-a-bmb-08.dts b/arch/arm64/boot/dts/freescale/imx8mp-debix-som-a-bmb-08.dts
index 0b0c95432bdc..0afd90224a59 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-debix-som-a-bmb-08.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-debix-som-a-bmb-08.dts
@@ -220,7 +220,7 @@
reg = <0x52>;
pagesize = <16>;
#address-cells = <1>;
- #size-cells = <0>;
+ #size-cells = <1>;
/* MACs stored in ASCII */
ethmac1: mac-address@0 {
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts
index e9fb5f7f39b5..3b1c940860e0 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts
@@ -186,9 +186,9 @@
&pcie_phy {
clock-names = "ref";
- clocks = <&clk IMX8MP_SYS_PLL2_100M>;
+ clocks = <&hsio_blk_ctrl>;
fsl,clkreq-unsupported;
- fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_UNUSED>;
+ fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_OUTPUT>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts
index 31d85d5871c9..b749e28e5ede 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts
@@ -35,33 +35,6 @@
clock-frequency = <25000000>;
};
- connector {
- compatible = "usb-c-connector";
- label = "USB-C";
- data-role = "dual";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
-
- usb_c_0_hs_ep: endpoint {
- remote-endpoint = <&dwc3_0_hs_ep>;
- };
- };
-
- port@1 {
- reg = <1>;
-
- usb_c_0_ss_ep: endpoint {
- remote-endpoint = <&ptn5150_in_ep>;
- };
- };
- };
- };
-
gpio-keys {
compatible = "gpio-keys";
@@ -202,33 +175,19 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ptn5150>;
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
+ port {
- port@0 {
- reg = <0>;
-
- ptn5150_in_ep: endpoint {
- remote-endpoint = <&usb_c_0_ss_ep>;
- };
- };
-
- port@1 {
- reg = <1>;
-
- ptn5150_out_ep: endpoint {
- remote-endpoint = <&dwc3_0_ss_ep>;
- };
+ ptn5150_out_ep: endpoint {
+ remote-endpoint = <&dwc3_0_ep>;
};
};
};
power-sensor@40 {
- compatible = "ti,ina238";
- reg = <0x40>;
- shunt-resistor = <20000>; /* 0.02 R */
- ti,shunt-gain = <1>; /* Drop cca. 40mV */
+ compatible = "ti,ina238";
+ reg = <0x40>;
+ shunt-resistor = <20000>; /* 0.02 R */
+ ti,shunt-gain = <1>; /* Drop cca. 40mV */
};
eeprom_board: eeprom@54 {
@@ -253,10 +212,6 @@
};
};
-&ethphy0g {
- reg = <7>;
-};
-
&fec { /* Second ethernet */
pinctrl-0 = <&pinctrl_fec_rgmii>;
phy-handle = <&ethphypdk>;
@@ -310,16 +265,7 @@
usb-role-switch;
port {
- #address-cells = <1>;
- #size-cells = <0>;
-
- dwc3_0_hs_ep: endpoint@0 {
- reg = <0>;
- remote-endpoint = <&usb_c_0_hs_ep>;
- };
-
- dwc3_0_ss_ep: endpoint@1 {
- reg = <1>;
+ dwc3_0_ep: endpoint {
remote-endpoint = <&ptn5150_out_ep>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi
index cb1953d14aa9..d8963f32ec84 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi
@@ -25,9 +25,7 @@
reg_eth_vio: regulator-eth-vio {
compatible = "regulator-fixed";
- gpio = <&gpio2 10 GPIO_ACTIVE_LOW>;
- pinctrl-0 = <&pinctrl_enet_vio>;
- pinctrl-names = "default";
+ gpio = <&ioexp 2 GPIO_ACTIVE_LOW>;
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <3300000>;
@@ -57,6 +55,11 @@
regulator-max-microvolt = <3300000>;
regulator-name = "VDD_3P3V_AWO";
};
+
+ wlan_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&ioexp 1 GPIO_ACTIVE_LOW>;
+ };
};
&A53_0 {
@@ -112,7 +115,7 @@
reg = <0>;
reset-assert-us = <1000>;
reset-deassert-us = <1000>;
- reset-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&ioexp 4 GPIO_ACTIVE_LOW>;
/* Non-default PHY population option. */
status = "disabled";
};
@@ -128,7 +131,7 @@
reg = <5>;
reset-assert-us = <1000>;
reset-deassert-us = <1000>;
- reset-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&ioexp 4 GPIO_ACTIVE_LOW>;
/* Default PHY population option. */
status = "okay";
};
@@ -293,6 +296,8 @@
};
buck2: BUCK2 { /* VDD_ARM */
+ nxp,dvs-run-voltage = <950000>;
+ nxp,dvs-standby-voltage = <850000>;
regulator-min-microvolt = <850000>;
regulator-max-microvolt = <1000000>;
regulator-ramp-delay = <3125>;
@@ -348,8 +353,9 @@
};
adc@48 {
- compatible = "ti,tla2024";
+ compatible = "ti,ads1015";
reg = <0x48>;
+ interrupts-extended = <&ioexp 7 IRQ_TYPE_EDGE_FALLING>;
#address-cells = <1>;
#size-cells = <0>;
@@ -396,24 +402,42 @@
};
eeprom0: eeprom@50 { /* EEPROM with EQoS MAC address */
- compatible = "atmel,24c02";
- pagesize = <16>;
+ compatible = "atmel,24c32"; /* M24C32-D */
+ pagesize = <32>;
reg = <0x50>;
};
rv3032: rtc@51 {
compatible = "microcrystal,rv3032";
reg = <0x51>;
- interrupts-extended = <&gpio5 5 IRQ_TYPE_LEVEL_LOW>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_rtc>;
+ interrupts-extended = <&ioexp 3 IRQ_TYPE_EDGE_FALLING>;
+ wakeup-source;
};
eeprom1: eeprom@53 { /* EEPROM with FEC MAC address */
- compatible = "atmel,24c02";
- pagesize = <16>;
+ compatible = "atmel,24c32"; /* M24C32-D */
+ pagesize = <32>;
reg = <0x53>;
};
+
+ ioexp: gpio@74 {
+ compatible = "nxp,pca9539";
+ reg = <0x74>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts-extended = <&gpio3 20 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ioexp>;
+ wakeup-source;
+
+ gpio-line-names =
+ "BT_REG_EN", "WL_REG_EN", "VIO_SWITCHED_#EN", "RTC_#INT",
+ "ENET_QOS_#RST", "RGB_OSZ_ENABLE", "USB1_ID", "ADC_ALTER_RDY",
+ "DHCOM-W", "DHCOM-V", "DHCOM-U", "DHCOM-T",
+ "BT_HOST_WAKE", "BT_DEV_WAKE", "", "";
+ };
};
&i2c4 {
@@ -463,6 +487,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
status = "okay";
+ wakeup-source;
};
&uart2 {
@@ -484,10 +509,8 @@
assigned-clock-rates = <80000000>;
bluetooth {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart2_bt>;
compatible = "cypress,cyw4373a0-bt";
- shutdown-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&ioexp 0 GPIO_ACTIVE_HIGH>;
max-speed = <4000000>;
};
};
@@ -514,8 +537,6 @@
};
&usb_dwc3_0 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usb0_vbus>;
dr_mode = "otg";
status = "okay";
};
@@ -541,6 +562,7 @@
pinctrl-0 = <&pinctrl_usdhc1>;
pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ mmc-pwrseq = <&wlan_pwrseq>;
vmmc-supply = <&buck4>;
bus-width = <4>;
non-removable;
@@ -559,7 +581,6 @@
* connected to the SoC, but can be connected on to
* SoC pin on the carrier board.
*/
- reset-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
};
};
@@ -601,8 +622,9 @@
&pinctrl_dhcom_d &pinctrl_dhcom_e &pinctrl_dhcom_f
&pinctrl_dhcom_g &pinctrl_dhcom_h &pinctrl_dhcom_i
&pinctrl_dhcom_j &pinctrl_dhcom_k &pinctrl_dhcom_l
- /* GPIO_M is connected to CLKOUT1 */
- &pinctrl_dhcom_int>;
+ &pinctrl_dhcom_m &pinctrl_dhcom_n &pinctrl_dhcom_o
+ &pinctrl_dhcom_p &pinctrl_dhcom_q &pinctrl_dhcom_r
+ &pinctrl_dhcom_s &pinctrl_dhcom_int>;
pinctrl-names = "default";
pinctrl_dhcom_a: dhcom-a-grp {
@@ -689,6 +711,55 @@
>;
};
+ pinctrl_dhcom_m: dhcom-m-grp {
+ fsl,pins = <
+ /* CSIx_MCLK */
+ MX8MP_IOMUXC_SPDIF_EXT_CLK__GPIO5_IO05 0x2
+ >;
+ };
+
+ pinctrl_dhcom_n: dhcom-n-grp {
+ fsl,pins = <
+ /* CSI2_D3- */
+ MX8MP_IOMUXC_SD1_DATA7__GPIO2_IO09 0x2
+ >;
+ };
+
+ pinctrl_dhcom_o: dhcom-o-grp {
+ fsl,pins = <
+ /* CSI2_D3+ */
+ MX8MP_IOMUXC_SD1_DATA6__GPIO2_IO08 0x2
+ >;
+ };
+
+ pinctrl_dhcom_p: dhcom-p-grp {
+ fsl,pins = <
+ /* CSI2_D2- */
+ MX8MP_IOMUXC_SD1_RESET_B__GPIO2_IO10 0x2
+ >;
+ };
+
+ pinctrl_dhcom_q: dhcom-q-grp {
+ fsl,pins = <
+ /* CSI2_D2+ */
+ MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x2
+ >;
+ };
+
+ pinctrl_dhcom_r: dhcom-r-grp {
+ fsl,pins = <
+ /* CSI2_D1- */
+ MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12 0x2
+ >;
+ };
+
+ pinctrl_dhcom_s: dhcom-s-grp {
+ fsl,pins = <
+ /* CSI2_D1+ */
+ MX8MP_IOMUXC_GPIO1_IO10__GPIO1_IO10 0x2
+ >;
+ };
+
pinctrl_dhcom_int: dhcom-int-grp {
fsl,pins = <
/* INT_HIGHEST_PRIO */
@@ -762,16 +833,8 @@
>;
};
- pinctrl_enet_vio: dhcom-enet-vio-grp {
- fsl,pins = <
- MX8MP_IOMUXC_SD1_RESET_B__GPIO2_IO10 0x22
- >;
- };
-
pinctrl_ethphy0: dhcom-ethphy0-grp {
fsl,pins = <
- /* ENET_QOS_#RST Reset */
- MX8MP_IOMUXC_SAI5_RXC__GPIO3_IO20 0x22
/* ENET_QOS_#INT Interrupt */
MX8MP_IOMUXC_SAI5_RXFS__GPIO3_IO19 0x22
>;
@@ -897,6 +960,13 @@
>;
};
+ pinctrl_ioexp: dhcom-ioexp-grp {
+ fsl,pins = <
+ /* #GPIO_EXP_INT */
+ MX8MP_IOMUXC_SAI5_RXC__GPIO3_IO20 0x22
+ >;
+ };
+
pinctrl_pmic: dhcom-pmic-grp {
fsl,pins = <
/* PMIC_nINT */
@@ -910,13 +980,6 @@
>;
};
- pinctrl_rtc: dhcom-rtc-grp {
- fsl,pins = <
- /* RTC_#INT Interrupt */
- MX8MP_IOMUXC_SPDIF_EXT_CLK__GPIO5_IO05 0x40000080
- >;
- };
-
pinctrl_tc9595: dhcom-tc9595-grp {
fsl,pins = <
/* RESET_DSIBRIDGE */
@@ -962,13 +1025,6 @@
>;
};
- pinctrl_uart2_bt: dhcom-uart2-bt-grp {
- fsl,pins = <
- /* BT_REG_EN */
- MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12 0x144
- >;
- };
-
pinctrl_uart3: dhcom-uart3-grp {
fsl,pins = <
MX8MP_IOMUXC_ECSPI1_SCLK__UART3_DCE_RX 0x49
@@ -985,12 +1041,6 @@
>;
};
- pinctrl_usb0_vbus: dhcom-usb0-grp {
- fsl,pins = <
- MX8MP_IOMUXC_GPIO1_IO10__USB1_OTG_ID 0x0
- >;
- };
-
pinctrl_usb1_vbus: dhcom-usb1-grp {
fsl,pins = <
MX8MP_IOMUXC_GPIO1_IO14__USB2_OTG_PWR 0x6
@@ -1006,8 +1056,6 @@
MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d0
MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d0
MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d0
- /* WL_REG_EN */
- MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x144
>;
};
@@ -1019,8 +1067,6 @@
MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d4
MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d4
MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d4
- /* WL_REG_EN */
- MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x144
>;
};
@@ -1032,8 +1078,6 @@
MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d6
MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d6
MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d6
- /* WL_REG_EN */
- MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x144
>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts b/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts
index 1e14c4cd3128..c8640cac3edc 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts
@@ -19,6 +19,36 @@
stdout-path = &uart1;
};
+ reg_can1_stby: regulator-can1-stby {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1_reg>;
+ gpio = <&gpio3 20 GPIO_ACTIVE_LOW>;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "can1-stby";
+ };
+
+ reg_can2_stby: regulator-can2-stby {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2_reg>;
+ gpio = <&gpio3 21 GPIO_ACTIVE_LOW>;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "can2-stby";
+ };
+
+ reg_usb1_vbus: regulator-usb1-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb1_vbus>;
+ gpio = <&gpio1 12 GPIO_ACTIVE_LOW>;
+ regulator-max-microvolt = <5000000>;
+ regulator-min-microvolt = <5000000>;
+ regulator-name = "usb1_host_vbus";
+ };
+
reg_usdhc2_vmmc: regulator-usdhc2 {
compatible = "regulator-fixed";
pinctrl-names = "default";
@@ -57,6 +87,21 @@
};
};
+/* CAN FD */
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can1_stby>;
+ status = "okay";
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can2_stby>;
+ status = "okay";
+};
+
&i2c2 {
clock-frequency = <400000>;
pinctrl-names = "default", "gpio";
@@ -101,6 +146,47 @@
status = "okay";
};
+/* USB1 Host mode Type-A */
+&usb3_phy0 {
+ vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+};
+
+&usb3_0 {
+ status = "okay";
+};
+
+&usb_dwc3_0 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+/* USB2 4-port USB3.0 HUB */
+&usb3_phy1 {
+ status = "okay";
+};
+
+&usb3_1 {
+ fsl,permanently-attached;
+ fsl,disable-port-power-control;
+ status = "okay";
+};
+
+&usb_dwc3_1 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+/* RS232/RS485 */
+&uart2 {
+ assigned-clocks = <&clk IMX8MP_CLK_UART2>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_80M>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
/* SD-Card */
&usdhc2 {
assigned-clocks = <&clk IMX8MP_CLK_USDHC2>;
@@ -115,6 +201,33 @@
status = "okay";
};
+&gpio1 {
+ gpio-line-names = "", "", "X_PMIC_WDOG_B", "",
+ "PMIC_SD_VSEL", "", "", "", "", "",
+ "", "", "USB1_OTG_PWR", "", "", "X_nETHPHY_INT";
+};
+
+&gpio2 {
+ gpio-line-names = "", "", "", "",
+ "", "", "", "", "", "",
+ "", "", "X_SD2_CD_B", "", "", "",
+ "", "", "", "SD2_RESET_B";
+};
+
+&gpio3 {
+ gpio-line-names = "", "", "", "",
+ "", "", "", "", "", "",
+ "", "", "", "", "", "",
+ "", "", "", "", "nCAN1_EN", "nCAN2_EN";
+};
+
+&gpio4 {
+ gpio-line-names = "", "", "", "",
+ "", "", "", "", "", "",
+ "", "", "", "", "", "",
+ "", "", "X_PMIC_IRQ_B", "", "nENET0_INT_PWDN";
+};
+
&iomuxc {
pinctrl_eqos: eqosgrp {
fsl,pins = <
@@ -136,6 +249,32 @@
>;
};
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_RXD2__CAN1_RX 0x154
+ MX8MP_IOMUXC_SAI5_RXD1__CAN1_TX 0x154
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_MCLK__CAN2_RX 0x154
+ MX8MP_IOMUXC_SAI5_RXD3__CAN2_TX 0x154
+ >;
+ };
+
+ pinctrl_flexcan1_reg: flexcan1reggrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_RXC__GPIO3_IO20 0x154
+ >;
+ };
+
+ pinctrl_flexcan2_reg: flexcan2reggrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_RXD0__GPIO3_IO21 0x154
+ >;
+ };
+
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001c2
@@ -163,6 +302,21 @@
>;
};
+ pinctrl_usb1_vbus: usb1vbusgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12 0x10
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX 0x140
+ MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x140
+ MX8MP_IOMUXC_SAI3_RXC__UART2_DCE_CTS 0x140
+ MX8MP_IOMUXC_SAI3_RXD__UART2_DCE_RTS 0x140
+ >;
+ };
+
pinctrl_usdhc2_pins: usdhc2-gpiogrp {
fsl,pins = <
MX8MP_IOMUXC_SD2_CD_B__GPIO2_IO12 0x1c4
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi
index d8df97060e8f..c976c3b6cbc6 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi
@@ -199,6 +199,19 @@
status = "okay";
};
+&gpio1 {
+ gpio-line-names = "", "", "X_PMIC_WDOG_B", "",
+ "", "", "", "", "", "",
+ "", "", "", "", "", "X_nETHPHY_INT";
+};
+
+&gpio4 {
+ gpio-line-names = "", "", "", "",
+ "", "", "", "", "", "",
+ "", "", "", "", "", "",
+ "", "", "X_PMIC_IRQ_B";
+};
+
&iomuxc {
pinctrl_fec: fecgrp {
fsl,pins = <
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw71xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw71xx.dtsi
index c531564c7ebb..bf47b5e9dd8c 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw71xx.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw71xx.dtsi
@@ -78,7 +78,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio4>;
interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "INT1";
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi
index f3bab22d5e68..f942e949084b 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi
@@ -113,7 +113,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio4>;
interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "INT1";
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi
index 68c62def4c06..b0d42b18c5ce 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi
@@ -95,8 +95,15 @@
&ecspi2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi2>;
- cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+ cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>,
+ <&gpio1 10 GPIO_ACTIVE_LOW>;
status = "okay";
+
+ tpm@1 {
+ compatible = "tcg,tpm_tis-spi";
+ reg = <0x1>;
+ spi-max-frequency = <36000000>;
+ };
};
&gpio4 {
@@ -125,7 +132,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio4>;
interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "INT1";
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx-imx219.dtso b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx-imx219.dtso
new file mode 100644
index 000000000000..270a9114da97
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx-imx219.dtso
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2023 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "imx8mp-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+ compatible = "gw,imx8mp-gw74xx", "fsl,imx8mp";
+
+ reg_cam: regulator-cam {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_cam>;
+ compatible = "regulator-fixed";
+ regulator-name = "reg_cam";
+ gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ cam24m: cam24m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "cam24m";
+ };
+};
+
+&i2c4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ imx219: sensor@10 {
+ compatible = "sony,imx219";
+ reg = <0x10>;
+ clocks = <&cam24m>;
+ VDIG-supply = <&reg_cam>;
+
+ port {
+ /* MIPI CSI-2 bus endpoint */
+ imx219_to_mipi_csi2: endpoint {
+ remote-endpoint = <&mipi_csi_0_in>;
+ clock-lanes = <0>;
+ data-lanes = <1 2>;
+ link-frequencies = /bits/ 64 <456000000>;
+ };
+ };
+ };
+};
+
+&isi_0 {
+ status = "okay";
+};
+
+&mipi_csi_0 {
+ status = "okay";
+
+ ports {
+ port@0 {
+ mipi_csi_0_in: endpoint {
+ remote-endpoint = <&imx219_to_mipi_csi2>;
+ data-lanes = <1 2>;
+ };
+ };
+ };
+};
+
+&iomuxc {
+ pinctrl_reg_cam: regcamgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO04__GPIO1_IO04 0x41
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
index faa370a5885f..2ab9f4cc12cc 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
@@ -461,7 +461,6 @@
st,drdy-int-pin = <1>;
interrupt-parent = <&gpio1>;
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "INT1";
};
switch: switch@5f {
@@ -512,7 +511,6 @@
port@5 {
reg = <5>;
- label = "cpu";
ethernet = <&fec>;
phy-mode = "rgmii-id";
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
index e9e4fcb562f1..04f2083c4ab2 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
@@ -184,7 +184,6 @@
&eqos {
phy-handle = <&ethphy0>;
phy-mode = "rgmii-id";
- phy-supply = <&reg_module_eth1phy>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_eqos>;
snps,force_thresh_dma_mode;
diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index 83d907294fbc..1264da6012f9 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -202,6 +202,60 @@
clock-output-names = "clk_ext4";
};
+ funnel {
+ /*
+ * non-configurable funnel don't show up on the AMBA
+ * bus. As such no need to add "arm,primecell".
+ */
+ compatible = "arm,coresight-static-funnel";
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ ca_funnel_in_port0: endpoint {
+ remote-endpoint = <&etm0_out_port>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ ca_funnel_in_port1: endpoint {
+ remote-endpoint = <&etm1_out_port>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ ca_funnel_in_port2: endpoint {
+ remote-endpoint = <&etm2_out_port>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+
+ ca_funnel_in_port3: endpoint {
+ remote-endpoint = <&etm3_out_port>;
+ };
+ };
+ };
+
+ out-ports {
+ port {
+
+ ca_funnel_out_port0: endpoint {
+ remote-endpoint = <&hugo_funnel_in_port0>;
+ };
+ };
+ };
+ };
+
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
@@ -368,59 +422,6 @@
};
};
- funnel {
- /*
- * non-configurable funnel don't show up on the AMBA
- * bus. As such no need to add "arm,primecell".
- */
- compatible = "arm,coresight-static-funnel";
-
- in-ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
-
- ca_funnel_in_port0: endpoint {
- remote-endpoint = <&etm0_out_port>;
- };
- };
-
- port@1 {
- reg = <1>;
-
- ca_funnel_in_port1: endpoint {
- remote-endpoint = <&etm1_out_port>;
- };
- };
-
- port@2 {
- reg = <2>;
-
- ca_funnel_in_port2: endpoint {
- remote-endpoint = <&etm2_out_port>;
- };
- };
-
- port@3 {
- reg = <3>;
-
- ca_funnel_in_port3: endpoint {
- remote-endpoint = <&etm3_out_port>;
- };
- };
- };
-
- out-ports {
- port {
- ca_funnel_out_port0: endpoint {
- remote-endpoint = <&hugo_funnel_in_port0>;
- };
- };
- };
- };
-
funnel@28c03000 {
compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
reg = <0x28c03000 0x1000>;
@@ -1459,6 +1460,47 @@
interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
+
+ easrc: easrc@30c90000 {
+ compatible = "fsl,imx8mp-easrc", "fsl,imx8mn-easrc";
+ reg = <0x30c90000 0x10000>;
+ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_ASRC_IPG>;
+ clock-names = "mem";
+ dmas = <&sdma2 16 23 0> , <&sdma2 17 23 0>,
+ <&sdma2 18 23 0> , <&sdma2 19 23 0>,
+ <&sdma2 20 23 0> , <&sdma2 21 23 0>,
+ <&sdma2 22 23 0> , <&sdma2 23 23 0>;
+ dma-names = "ctx0_rx", "ctx0_tx",
+ "ctx1_rx", "ctx1_tx",
+ "ctx2_rx", "ctx2_tx",
+ "ctx3_rx", "ctx3_tx";
+ firmware-name = "imx/easrc/easrc-imx8mn.bin";
+ fsl,asrc-rate = <8000>;
+ fsl,asrc-format = <2>;
+ status = "disabled";
+ };
+
+ micfil: audio-controller@30ca0000 {
+ compatible = "fsl,imx8mp-micfil";
+ reg = <0x30ca0000 0x10000>;
+ #sound-dai-cells = <0>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_PDM_IPG>,
+ <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_PDM_SEL>,
+ <&clk IMX8MP_AUDIO_PLL1_OUT>,
+ <&clk IMX8MP_AUDIO_PLL2_OUT>,
+ <&clk IMX8MP_CLK_EXT3>;
+ clock-names = "ipg_clk", "ipg_clk_app",
+ "pll8k", "pll11k", "clkext3";
+ dmas = <&sdma2 24 25 0x80000000>;
+ dma-names = "rx";
+ status = "disabled";
+ };
+
};
sdma3: dma-controller@30e00000 {
@@ -2030,6 +2072,7 @@
phys = <&usb3_phy0>, <&usb3_phy0>;
phy-names = "usb2-phy", "usb3-phy";
snps,gfladj-refclk-lpm-sel-quirk;
+ snps,parkmode-disable-ss-quirk;
};
};
@@ -2072,6 +2115,7 @@
phys = <&usb3_phy1>, <&usb3_phy1>;
phy-names = "usb2-phy", "usb3-phy";
snps,gfladj-refclk-lpm-sel-quirk;
+ snps,parkmode-disable-ss-quirk;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
index 138a4d36a7ef..ffb5fe61630d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
@@ -381,7 +381,7 @@
gpio-hog;
gpios = <1 GPIO_ACTIVE_HIGH>;
input;
- lane-mapping = "pmic-5v";
+ line-name = "pmic-5v";
};
};
@@ -1001,7 +1001,7 @@
};
regulator@3e {
- compatible = "tps65132";
+ compatible = "ti,tps65132";
reg = <0x3e>;
reg_lcd_avdd: outp {
@@ -1154,15 +1154,12 @@
pinctrl-0 = <&pinctrl_charger_in>;
interrupt-parent = <&gpio3>;
interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
- phys = <&usb3_phy0>;
ti,battery-regulation-voltage = <4208000>; /* uV */
ti,termination-current = <128000>; /* uA */
ti,precharge-current = <128000>; /* uA */
ti,minimum-sys-voltage = <3700000>; /* uV */
ti,boost-voltage = <5000000>; /* uV */
ti,boost-max-current = <1500000>; /* uA */
- ti,use-vinmin-threshold = <1>; /* enable VINDPM */
- ti,vinmin-threshold = <3900000>; /* uV */
monitored-battery = <&bat>;
power-supplies = <&typec_pd>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts b/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts
index 8614c18b5998..767819cce886 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts
@@ -142,7 +142,7 @@
#address-cells = <1>;
#size-cells = <0>;
- i2c1a: i2c1@0 {
+ i2c1a: i2c@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
@@ -159,7 +159,7 @@
};
};
- i2c1b: i2c1@1 {
+ i2c1b: i2c@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
@@ -176,7 +176,7 @@
};
};
- i2c1c: i2c1@2 {
+ i2c1c: i2c@2 {
reg = <2>;
#address-cells = <1>;
#size-cells = <0>;
@@ -193,7 +193,7 @@
};
};
- i2c1d: i2c1@3 {
+ i2c1d: i2c@3 {
reg = <3>;
#address-cells = <1>;
#size-cells = <0>;
@@ -222,7 +222,7 @@
#address-cells = <1>;
#size-cells = <0>;
- i2c4@0 {
+ i2c@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
@@ -257,14 +257,14 @@
};
};
- ddc_i2c_bus: i2c4@1 {
+ ddc_i2c_bus: i2c@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
clock-frequency = <100000>;
};
- i2c4@3 {
+ i2c@3 {
reg = <3>;
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts b/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts
index 89cbec5c41b2..ec89b5adeb93 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts
@@ -67,12 +67,12 @@
compatible = "rohm,bd71837";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pmic>;
+ #clock-cells = <0>;
clocks = <&pmic_osc>;
clock-names = "osc";
clock-output-names = "pmic_clk";
interrupt-parent = <&gpio1>;
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "irq";
regulators {
buck1: BUCK1 {
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-thor96.dts b/arch/arm64/boot/dts/freescale/imx8mq-thor96.dts
index 6e6182709d22..eaa9d0c0fcc1 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-thor96.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-thor96.dts
@@ -107,7 +107,7 @@
compatible = "mmc-pwrseq-simple";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_wifi_reg_on>;
- gpio = <&gpio3 3 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio3 3 GPIO_ACTIVE_HIGH>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx-lvds-tm070jvhg33.dtso b/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx-lvds-tm070jvhg33.dtso
new file mode 100644
index 000000000000..306977d6ba0c
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx-lvds-tm070jvhg33.dtso
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2019-2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Alexander Stein
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+ compatible = "tq,imx8mq-tqma8mq-mba8mx", "tq,imx8mq-tqma8mq", "fsl,imx8mq";
+};
+
+&backlight_lvds {
+ status = "okay";
+};
+
+&dphy {
+ status = "okay";
+};
+
+&dsi_lvds_bridge {
+ status = "okay";
+};
+
+&expander0 {
+ dsi-mux-oe-hog {
+ gpio-hog;
+ gpios = <10 GPIO_ACTIVE_LOW>;
+ output-high;
+ line-name = "DSI_MUX_OE#";
+ };
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&mipi_dsi {
+ status = "okay";
+};
+
+&panel {
+ compatible = "tianma,tm070jvhg33";
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi
index cb777b47baf9..0c960efd9b3d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi
@@ -15,7 +15,7 @@
stdout-path = &uart1;
};
- mdio0: bitbang-mdio {
+ mdio0: mdio {
compatible = "virtual,mdio-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mdio_bitbang>, <&pinctrl_fec1_phy_reset>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index 35f07dfb4ca8..c6dc3ba0d43b 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -225,6 +225,59 @@
};
};
+ funnel {
+ /*
+ * non-configurable funnel don't show up on the AMBA
+ * bus. As such no need to add "arm,primecell".
+ */
+ compatible = "arm,coresight-static-funnel";
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ ca_funnel_in_port0: endpoint {
+ remote-endpoint = <&etm0_out_port>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ ca_funnel_in_port1: endpoint {
+ remote-endpoint = <&etm1_out_port>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ ca_funnel_in_port2: endpoint {
+ remote-endpoint = <&etm2_out_port>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+
+ ca_funnel_in_port3: endpoint {
+ remote-endpoint = <&etm3_out_port>;
+ };
+ };
+ };
+
+ out-ports {
+ port {
+ ca_funnel_out_port0: endpoint {
+ remote-endpoint = <&hugo_funnel_in_port0>;
+ };
+ };
+ };
+ };
+
pmu {
compatible = "arm,cortex-a53-pmu";
interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
@@ -394,59 +447,6 @@
};
};
- funnel {
- /*
- * non-configurable funnel don't show up on the AMBA
- * bus. As such no need to add "arm,primecell".
- */
- compatible = "arm,coresight-static-funnel";
-
- in-ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
-
- ca_funnel_in_port0: endpoint {
- remote-endpoint = <&etm0_out_port>;
- };
- };
-
- port@1 {
- reg = <1>;
-
- ca_funnel_in_port1: endpoint {
- remote-endpoint = <&etm1_out_port>;
- };
- };
-
- port@2 {
- reg = <2>;
-
- ca_funnel_in_port2: endpoint {
- remote-endpoint = <&etm2_out_port>;
- };
- };
-
- port@3 {
- reg = <3>;
-
- ca_funnel_in_port3: endpoint {
- remote-endpoint = <&etm3_out_port>;
- };
- };
- };
-
- out-ports {
- port {
- ca_funnel_out_port0: endpoint {
- remote-endpoint = <&hugo_funnel_in_port0>;
- };
- };
- };
- };
-
funnel@28c03000 {
compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
reg = <0x28c03000 0x1000>;
@@ -1649,6 +1649,7 @@
phys = <&usb3_phy0>, <&usb3_phy0>;
phy-names = "usb2-phy", "usb3-phy";
power-domains = <&pgc_otg1>;
+ snps,parkmode-disable-ss-quirk;
status = "disabled";
};
@@ -1680,6 +1681,7 @@
phys = <&usb3_phy1>, <&usb3_phy1>;
phy-names = "usb2-phy", "usb3-phy";
power-domains = <&pgc_otg2>;
+ snps,parkmode-disable-ss-quirk;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-apalis.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-apalis.dtsi
index 1c6af9f549a8..4d6427fbe875 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm-apalis.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qm-apalis.dtsi
@@ -21,7 +21,6 @@
* this PHY model. Use delay on MAC side instead.
*/
&fec1 {
- fsl,rgmii_txc_dly;
phy-mode = "rgmii-rxid";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts
index 0b34cc2250e1..6d50838ad17d 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts
+++ b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts
@@ -47,6 +47,18 @@
status = "okay";
};
+&lpuart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart2>;
+ status = "okay";
+};
+
+&lpuart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart3>;
+ status = "okay";
+};
+
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_fec1>;
@@ -118,6 +130,20 @@
>;
};
+ pinctrl_lpuart2: lpuart2grp {
+ fsl,pins = <
+ IMX8QM_UART0_RTS_B_DMA_UART2_RX 0x06000020
+ IMX8QM_UART0_CTS_B_DMA_UART2_TX 0x06000020
+ >;
+ };
+
+ pinctrl_lpuart3: lpuart3grp {
+ fsl,pins = <
+ IMX8QM_M41_GPIO0_00_DMA_UART3_RX 0x06000020
+ IMX8QM_M41_GPIO0_01_DMA_UART3_TX 0x06000020
+ >;
+ };
+
pinctrl_usdhc1: usdhc1grp {
fsl,pins = <
IMX8QM_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
index e9b198c13b2f..8439dd6b3935 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
@@ -44,6 +44,69 @@
};
};
+&edma2 {
+ reg = <0x5a1f0000 0x170000>;
+ #dma-cells = <3>;
+ dma-channels = <22>;
+ dma-channel-mask = <0xf00>;
+ interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* unused */
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* unused */
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* unused */
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* unused */
+ <GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 435 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 436 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 437 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 439 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 441 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 442 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 443 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&pd IMX_SC_R_DMA_0_CH0>,
+ <&pd IMX_SC_R_DMA_0_CH1>,
+ <&pd IMX_SC_R_DMA_0_CH2>,
+ <&pd IMX_SC_R_DMA_0_CH3>,
+ <&pd IMX_SC_R_DMA_0_CH4>,
+ <&pd IMX_SC_R_DMA_0_CH5>,
+ <&pd IMX_SC_R_DMA_0_CH6>,
+ <&pd IMX_SC_R_DMA_0_CH7>,
+ <&pd IMX_SC_R_DMA_0_CH8>,
+ <&pd IMX_SC_R_DMA_0_CH9>,
+ <&pd IMX_SC_R_DMA_0_CH10>,
+ <&pd IMX_SC_R_DMA_0_CH11>,
+ <&pd IMX_SC_R_DMA_0_CH12>,
+ <&pd IMX_SC_R_DMA_0_CH13>,
+ <&pd IMX_SC_R_DMA_0_CH14>,
+ <&pd IMX_SC_R_DMA_0_CH15>,
+ <&pd IMX_SC_R_DMA_0_CH16>,
+ <&pd IMX_SC_R_DMA_0_CH17>,
+ <&pd IMX_SC_R_DMA_0_CH18>,
+ <&pd IMX_SC_R_DMA_0_CH19>,
+ <&pd IMX_SC_R_DMA_0_CH20>,
+ <&pd IMX_SC_R_DMA_0_CH21>;
+ status = "okay";
+};
+
+&edma3 {
+ power-domains = <&pd IMX_SC_R_DMA_1_CH0>,
+ <&pd IMX_SC_R_DMA_1_CH1>,
+ <&pd IMX_SC_R_DMA_1_CH2>,
+ <&pd IMX_SC_R_DMA_1_CH3>,
+ <&pd IMX_SC_R_DMA_1_CH4>,
+ <&pd IMX_SC_R_DMA_1_CH5>,
+ <&pd IMX_SC_R_DMA_1_CH6>,
+ <&pd IMX_SC_R_DMA_1_CH7>;
+};
+
&flexcan1 {
fsl,clk-source = /bits/ 8 <1>;
};
@@ -64,18 +127,22 @@
&lpuart0 {
compatible = "fsl,imx8qm-lpuart", "fsl,imx8qxp-lpuart";
+ dmas = <&edma2 13 0 0>, <&edma2 12 0 1>;
};
&lpuart1 {
compatible = "fsl,imx8qm-lpuart", "fsl,imx8qxp-lpuart";
+ dmas = <&edma2 15 0 0>, <&edma2 14 0 1>;
};
&lpuart2 {
compatible = "fsl,imx8qm-lpuart", "fsl,imx8qxp-lpuart";
+ dmas = <&edma2 17 0 0>, <&edma2 16 0 1>;
};
&lpuart3 {
compatible = "fsl,imx8qm-lpuart", "fsl,imx8qxp-lpuart";
+ dmas = <&edma2 19 0 0>, <&edma2 18 0 1>;
};
&i2c0 {
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi
index 7764b4146e0a..2bbdacb1313f 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi
@@ -8,5 +8,5 @@
};
&jpegenc {
- compatible = "nxp,imx8qm-jpgdec", "nxp,imx8qxp-jpgenc";
+ compatible = "nxp,imx8qm-jpgenc", "nxp,imx8qxp-jpgenc";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
index 7924b0969ad8..99611729943c 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
@@ -187,6 +187,18 @@
status = "okay";
};
+&lpuart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart2>;
+ status = "okay";
+};
+
+&lpuart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart3>;
+ status = "okay";
+};
+
&mu_m0 {
status = "okay";
};
@@ -340,6 +352,20 @@
>;
};
+ pinctrl_lpuart2: lpuart2grp {
+ fsl,pins = <
+ IMX8QXP_UART2_TX_ADMA_UART2_TX 0x06000020
+ IMX8QXP_UART2_RX_ADMA_UART2_RX 0x06000020
+ >;
+ };
+
+ pinctrl_lpuart3: lpuart3grp {
+ fsl,pins = <
+ IMX8QXP_FLEXCAN2_TX_ADMA_UART3_TX 0x06000020
+ IMX8QXP_FLEXCAN2_RX_ADMA_UART3_RX 0x06000020
+ >;
+ };
+
pinctrl_typec: typecgrp {
fsl,pins = <
IMX8QXP_SPI2_SCK_LSIO_GPIO1_IO03 0x06000021
diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
index 8a6596d5a581..c4a0082f30d3 100644
--- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
@@ -360,7 +360,7 @@
interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&pcc4 IMX8ULP_CLK_FLEXSPI2>,
<&pcc4 IMX8ULP_CLK_FLEXSPI2>;
- clock-names = "fspi", "fspi_en";
+ clock-names = "fspi_en", "fspi";
assigned-clocks = <&pcc4 IMX8ULP_CLK_FLEXSPI2>;
assigned-clock-parents = <&cgc1 IMX8ULP_CLK_SPLL3_PFD3_DIV2>;
status = "disabled";
@@ -483,12 +483,13 @@
};
};
- gpioe: gpio@2d000080 {
- compatible = "fsl,imx8ulp-gpio", "fsl,imx7ulp-gpio";
- reg = <0x2d000080 0x1000>, <0x2d000040 0x40>;
+ gpioe: gpio@2d000000 {
+ compatible = "fsl,imx8ulp-gpio";
+ reg = <0x2d000000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
- interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&pcc4 IMX8ULP_CLK_RGPIOE>,
@@ -497,12 +498,13 @@
gpio-ranges = <&iomuxc1 0 32 24>;
};
- gpiof: gpio@2d010080 {
- compatible = "fsl,imx8ulp-gpio", "fsl,imx7ulp-gpio";
- reg = <0x2d010080 0x1000>, <0x2d010040 0x40>;
+ gpiof: gpio@2d010000 {
+ compatible = "fsl,imx8ulp-gpio";
+ reg = <0x2d010000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
- interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&pcc4 IMX8ULP_CLK_RGPIOF>,
@@ -532,12 +534,13 @@
};
};
- gpiod: gpio@2e200080 {
- compatible = "fsl,imx8ulp-gpio", "fsl,imx7ulp-gpio";
- reg = <0x2e200080 0x1000>, <0x2e200040 0x40>;
+ gpiod: gpio@2e200000 {
+ compatible = "fsl,imx8ulp-gpio";
+ reg = <0x2e200000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
- interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&pcc5 IMX8ULP_CLK_RGPIOD>,
diff --git a/arch/arm64/boot/dts/freescale/imx8x-colibri-iris-v2.dtsi b/arch/arm64/boot/dts/freescale/imx8x-colibri-iris-v2.dtsi
index 98202a437040..58ec0b399c4f 100644
--- a/arch/arm64/boot/dts/freescale/imx8x-colibri-iris-v2.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8x-colibri-iris-v2.dtsi
@@ -23,11 +23,11 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lvds_converter &pinctrl_gpio_iris>;
- pinctrl_enable_3v3_vmmc: enable_3v3_vmmc {
+ pinctrl_enable_3v3_vmmc: enable-3v3-vmmc-grp {
fsl,pins = <IMX8QXP_SAI1_RXFS_LSIO_GPIO0_IO31 0x20>; /* SODIMM 100 */
};
- pinctrl_lvds_converter: lcd-lvds {
+ pinctrl_lvds_converter: lvds-converter-grp {
fsl,pins = <IMX8QXP_FLEXCAN1_TX_LSIO_GPIO1_IO18 0x20>, /* SODIMM 55 */
/* 6B/8B mode. Select LOW - 8B mode (24bit) */
<IMX8QXP_FLEXCAN1_RX_LSIO_GPIO1_IO17 0x20>, /* SODIMM 63 */
diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
index cafd39130eb8..2b9d47716f75 100644
--- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
@@ -149,6 +149,12 @@
status = "okay";
};
+&lpuart5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5>;
+ status = "okay";
+};
+
&usdhc1 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc1>;
@@ -222,6 +228,15 @@
>;
};
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX93_PAD_DAP_TDO_TRACESWO__LPUART5_TX 0x31e
+ MX93_PAD_DAP_TDI__LPUART5_RX 0x31e
+ MX93_PAD_DAP_TMS_SWDIO__LPUART5_RTS_B 0x31e
+ MX93_PAD_DAP_TCLK_SWCLK__LPUART5_CTS_B 0x31e
+ >;
+ };
+
pinctrl_usdhc1: usdhc1grp {
fsl,pins = <
MX93_PAD_SD1_CLK__USDHC1_CLK 0x15fe
diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts
index f06139bdff97..3c5c67ebee5d 100644
--- a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts
@@ -577,7 +577,7 @@
fsl,pins = <
MX93_PAD_UART2_TXD__LPUART2_TX 0x31e
MX93_PAD_UART2_RXD__LPUART2_RX 0x31e
- MX93_PAD_SAI1_TXD0__LPUART2_RTS_B 0x31e
+ MX93_PAD_SAI1_TXD0__LPUART2_RTS_B 0x51e
>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx93.dtsi b/arch/arm64/boot/dts/freescale/imx93.dtsi
index 6f85a05ee7e1..34c0540276d1 100644
--- a/arch/arm64/boot/dts/freescale/imx93.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93.dtsi
@@ -185,7 +185,47 @@
#size-cells = <1>;
ranges;
- anomix_ns_gpr: syscon@44210000 {
+ edma1: dma-controller@44000000 {
+ compatible = "fsl,imx93-edma3";
+ reg = <0x44000000 0x200000>;
+ #dma-cells = <3>;
+ dma-channels = <31>;
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, // 0: Reserved
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, // 1: CANFD1
+ <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>, // 2: Reserved
+ <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, // 3: GPIO1 CH0
+ <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>, // 4: GPIO1 CH1
+ <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>, // 5: I3C1 TO Bus
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, // 6: I3C1 From Bus
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, // 7: LPI2C1 M TX
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, // 8: LPI2C1 S TX
+ <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>, // 9: LPI2C2 M RX
+ <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>, // 10: LPI2C2 S RX
+ <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, // 11: LPSPI1 TX
+ <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>, // 12: LPSPI1 RX
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, // 13: LPSPI2 TX
+ <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, // 14: LPSPI2 RX
+ <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, // 15: LPTMR1
+ <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>, // 16: LPUART1 TX
+ <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>, // 17: LPUART1 RX
+ <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>, // 18: LPUART2 TX
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, // 19: LPUART2 RX
+ <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, // 20: S400
+ <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>, // 21: SAI TX
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>, // 22: SAI RX
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, // 23: TPM1 CH0/CH2
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>, // 24: TPM1 CH1/CH3
+ <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>, // 25: TPM1 Overflow
+ <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, // 26: TMP2 CH0/CH2
+ <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>, // 27: TMP2 CH1/CH3
+ <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, // 28: TMP2 Overflow
+ <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, // 29: PDM
+ <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>; // 30: ADC1
+ clocks = <&clk IMX93_CLK_EDMA1_GATE>;
+ clock-names = "dma";
+ };
+
+ aonmix_ns_gpr: syscon@44210000 {
compatible = "fsl,imx93-aonmix-ns-syscfg", "syscon";
reg = <0x44210000 0x1000>;
};
@@ -296,6 +336,8 @@
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX93_CLK_LPUART1_GATE>;
clock-names = "ipg";
+ dmas = <&edma1 17 0 1>, <&edma1 16 0 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -305,6 +347,8 @@
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX93_CLK_LPUART2_GATE>;
clock-names = "ipg";
+ dmas = <&edma1 19 0 1>, <&edma1 18 0 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -319,6 +363,7 @@
assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>;
assigned-clock-rates = <40000000>;
fsl,clk-source = /bits/ 8 <0>;
+ fsl,stop-mode = <&aonmix_ns_gpr 0x14 0>;
status = "disabled";
};
@@ -372,7 +417,7 @@
compatible = "fsl,imx93-src-slice";
reg = <0x44462400 0x400>, <0x44465800 0x400>;
#power-domain-cells = <0>;
- clocks = <&clk IMX93_CLK_MEDIA_AXI>,
+ clocks = <&clk IMX93_CLK_NIC_MEDIA_GATE>,
<&clk IMX93_CLK_MEDIA_APB>;
};
};
@@ -385,6 +430,7 @@
tmu: tmu@44482000 {
compatible = "fsl,qoriq-tmu";
reg = <0x44482000 0x1000>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX93_CLK_TMC_GATE>;
little-endian;
fsl,tmu-range = <0x800000da 0x800000e9
@@ -423,6 +469,80 @@
#size-cells = <1>;
ranges;
+ edma2: dma-controller@42000000 {
+ compatible = "fsl,imx93-edma4";
+ reg = <0x42000000 0x210000>;
+ #dma-cells = <3>;
+ shared-interrupt;
+ dma-channels = <64>;
+ interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX93_CLK_EDMA2_GATE>;
+ clock-names = "dma";
+ };
+
wakeupmix_gpr: syscon@42420000 {
compatible = "fsl,imx93-wakeupmix-syscfg", "syscon";
reg = <0x42420000 0x1000>;
@@ -550,6 +670,8 @@
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX93_CLK_LPUART3_GATE>;
clock-names = "ipg";
+ dmas = <&edma2 18 0 1>, <&edma2 17 0 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -559,6 +681,8 @@
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX93_CLK_LPUART4_GATE>;
clock-names = "ipg";
+ dmas = <&edma2 20 0 1>, <&edma2 19 0 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -568,6 +692,8 @@
interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX93_CLK_LPUART5_GATE>;
clock-names = "ipg";
+ dmas = <&edma2 22 0 1>, <&edma2 21 0 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -577,6 +703,8 @@
interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX93_CLK_LPUART6_GATE>;
clock-names = "ipg";
+ dmas = <&edma2 24 0 1>, <&edma2 23 0 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -591,6 +719,7 @@
assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>;
assigned-clock-rates = <40000000>;
fsl,clk-source = /bits/ 8 <0>;
+ fsl,stop-mode = <&wakeupmix_gpr 0x0c 2>;
status = "disabled";
};
@@ -615,6 +744,8 @@
interrupts = <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX93_CLK_LPUART7_GATE>;
clock-names = "ipg";
+ dmas = <&edma2 88 0 1>, <&edma2 87 0 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -624,6 +755,8 @@
interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX93_CLK_LPUART8_GATE>;
clock-names = "ipg";
+ dmas = <&edma2 90 0 1>, <&edma2 89 0 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -824,12 +957,13 @@
};
};
- gpio2: gpio@43810080 {
- compatible = "fsl,imx93-gpio", "fsl,imx7ulp-gpio";
- reg = <0x43810080 0x1000>, <0x43810040 0x40>;
+ gpio2: gpio@43810000 {
+ compatible = "fsl,imx93-gpio", "fsl,imx8ulp-gpio";
+ reg = <0x43810000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
- interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&clk IMX93_CLK_GPIO2_GATE>,
@@ -838,12 +972,13 @@
gpio-ranges = <&iomuxc 0 4 30>;
};
- gpio3: gpio@43820080 {
- compatible = "fsl,imx93-gpio", "fsl,imx7ulp-gpio";
- reg = <0x43820080 0x1000>, <0x43820040 0x40>;
+ gpio3: gpio@43820000 {
+ compatible = "fsl,imx93-gpio", "fsl,imx8ulp-gpio";
+ reg = <0x43820000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
- interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&clk IMX93_CLK_GPIO3_GATE>,
@@ -853,12 +988,13 @@
<&iomuxc 26 34 2>, <&iomuxc 28 0 4>;
};
- gpio4: gpio@43830080 {
- compatible = "fsl,imx93-gpio", "fsl,imx7ulp-gpio";
- reg = <0x43830080 0x1000>, <0x43830040 0x40>;
+ gpio4: gpio@43830000 {
+ compatible = "fsl,imx93-gpio", "fsl,imx8ulp-gpio";
+ reg = <0x43830000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
- interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&clk IMX93_CLK_GPIO4_GATE>,
@@ -867,12 +1003,13 @@
gpio-ranges = <&iomuxc 0 38 28>, <&iomuxc 28 36 2>;
};
- gpio1: gpio@47400080 {
- compatible = "fsl,imx93-gpio", "fsl,imx7ulp-gpio";
- reg = <0x47400080 0x1000>, <0x47400040 0x40>;
+ gpio1: gpio@47400000 {
+ compatible = "fsl,imx93-gpio", "fsl,imx8ulp-gpio";
+ reg = <0x47400000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
- interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&clk IMX93_CLK_GPIO1_GATE>,
diff --git a/arch/arm64/boot/dts/freescale/mba8mx.dtsi b/arch/arm64/boot/dts/freescale/mba8mx.dtsi
index 8a9fe5cdcc98..e2bc53b8d39a 100644
--- a/arch/arm64/boot/dts/freescale/mba8mx.dtsi
+++ b/arch/arm64/boot/dts/freescale/mba8mx.dtsi
@@ -8,6 +8,16 @@
/* TQ-Systems GmbH MBa8Mx baseboard */
/ {
+ backlight_lvds: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm3 0 5000000 0>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <7>;
+ power-supply = <&reg_12v>;
+ enable-gpios = <&expander2 2 GPIO_ACTIVE_HIGH>;
+ status = "disabled";
+ };
+
beeper {
compatible = "pwm-beeper";
pwms = <&pwm4 0 250000 0>;
@@ -65,12 +75,45 @@
};
};
+ gpio_delays: gpio-delays {
+ compatible = "gpio-delay";
+ #gpio-cells = <3>;
+ gpio-controller;
+ gpios = <&expander0 6 GPIO_ACTIVE_HIGH>;
+ gpio-line-names = "LVDS_BRIDGE_EN_1V8";
+ };
+
+ panel: panel-lvds {
+ /*
+ * Display is not fixed, so compatible has to be added from
+ * DT overlay
+ */
+ backlight = <&backlight_lvds>;
+ power-supply = <&reg_vcc_3v3>;
+ status = "disabled";
+
+ port {
+ panel_in_lvds: endpoint {
+ data-lanes = <1 2 3 4>;
+ remote-endpoint = <&lvds_bridge_out>;
+ };
+ };
+ };
+
pcie0_refclk: pcie0-refclk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <100000000>;
};
+ reg_12v: regulator-12v {
+ compatible = "regulator-fixed";
+ regulator-name = "MBA8MX_12V";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ regulator-always-on;
+ };
+
reg_hub_vbus: regulator-hub-vbus {
compatible = "regulator-fixed";
regulator-name = "MBA8MX_HUB_VBUS";
@@ -157,6 +200,10 @@
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-line-names = "", "", "", "",
+ "", "", "LVDS_BRIDGE_EN", "",
+ "", "", "", "",
+ "", "", "", "";
sd-mux-oe-hog {
gpio-hog;
@@ -227,6 +274,52 @@
scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
+
+ dsi_lvds_bridge: bridge@2d {
+ compatible = "ti,sn65dsi84";
+ reg = <0x2d>;
+ enable-gpios = <&gpio_delays 0 130000 0>;
+ vcc-supply = <&reg_sn65dsi83_1v8>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ lvds_bridge_in: endpoint {
+ data-lanes = <1 2 3 4>;
+ remote-endpoint = <&mipi_dsi_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ lvds_bridge_out: endpoint {
+ remote-endpoint = <&panel_in_lvds>;
+ };
+ };
+ };
+ };
+};
+
+&mipi_dsi {
+ samsung,burst-clock-frequency = <891000000>;
+ samsung,esc-clock-frequency = <20000000>;
+
+ ports {
+ port@1 {
+ reg = <1>;
+
+ mipi_dsi_out: endpoint {
+ data-lanes = <1 2 3 4>;
+ remote-endpoint = <&lvds_bridge_in>;
+ };
+ };
+ };
};
&pwm3 {
diff --git a/arch/arm64/boot/dts/freescale/tqmls104xa-mbls10xxa-fman.dtsi b/arch/arm64/boot/dts/freescale/tqmls104xa-mbls10xxa-fman.dtsi
new file mode 100644
index 000000000000..4c38dd541143
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/tqmls104xa-mbls10xxa-fman.dtsi
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2019,2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Gregor Herburger, Timo Herbrecher
+ *
+ * Device Tree Include file for MBLS10xxA from TQ (FMAN related sections)
+ */
+
+#include <dt-bindings/net/ti-dp83867.h>
+
+&enet0 {
+ status = "disabled";
+};
+
+&enet1 {
+ status = "disabled";
+};
+
+&enet2 {
+ phy-handle = <&rgmii_phy1>;
+ phy-connection-type = "rgmii";
+ phy-mode = "rgmii-id";
+ status = "okay";
+};
+
+&enet3 {
+ phy-handle = <&rgmii_phy2>;
+ phy-connection-type = "rgmii";
+ phy-mode = "rgmii-id";
+ status = "okay";
+};
+
+&enet4 {
+ status = "disabled";
+};
+
+&enet5 {
+ status = "disabled";
+};
+
+&enet6 {
+ status = "disabled";
+};
+
+&mdio0 {
+ status = "okay";
+
+ qsgmii2_phy1: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x00>;
+ };
+
+ qsgmii2_phy2: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x01>;
+ };
+
+ qsgmii2_phy3: ethernet-phy@2 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x02>;
+ };
+
+ qsgmii2_phy4: ethernet-phy@3 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x03>;
+ };
+
+ rgmii_phy2: ethernet-phy@c {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x0c>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_1_50_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_50_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+ };
+
+ rgmii_phy1: ethernet-phy@e {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x0e>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_1_50_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_50_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+ };
+
+ qsgmii1_phy1: ethernet-phy@1c {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1c>;
+ };
+
+ qsgmii1_phy2: ethernet-phy@1d {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1d>;
+ };
+
+ qsgmii1_phy3: ethernet-phy@1e {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1e>;
+ };
+
+ qsgmii1_phy4: ethernet-phy@1f {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1f>;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/tqmls1088a-mbls10xxa-mc.dtsi b/arch/arm64/boot/dts/freescale/tqmls1088a-mbls10xxa-mc.dtsi
new file mode 100644
index 000000000000..2471bb109e8e
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/tqmls1088a-mbls10xxa-mc.dtsi
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2018-2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Gregor Herburger, Timo Herbrecher
+ *
+ * Device Tree Include file for MBLS10xxA from TQ (MC related sections)
+ */
+
+#include <dt-bindings/net/ti-dp83867.h>
+
+/ {
+ sfp1: sfp1 {
+ compatible = "sff,sfp";
+ i2c-bus = <&sfp1_i2c>;
+ mod-def0-gpios = <&gpioexp2 2 GPIO_ACTIVE_LOW>;
+ los-gpios = <&gpioexp2 3 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpios = <&gpioexp2 0 GPIO_ACTIVE_HIGH>;
+ tx-disable-gpios = <&gpioexp2 1 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp2: sfp2 {
+ compatible = "sff,sfp";
+ i2c-bus = <&sfp2_i2c>;
+ mod-def0-gpios = <&gpioexp2 10 GPIO_ACTIVE_LOW>;
+ los-gpios = <&gpioexp2 11 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpios = <&gpioexp2 8 GPIO_ACTIVE_HIGH>;
+ tx-disable-gpios = <&gpioexp2 9 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&dpmac1 {
+ pcs-handle = <&pcs1>;
+};
+
+&dpmac2 {
+ pcs-handle = <&pcs2>;
+};
+
+&dpmac3 {
+ pcs-handle = <&pcs3_0>;
+};
+
+&dpmac4 {
+ pcs-handle = <&pcs3_1>;
+};
+
+&dpmac5 {
+ pcs-handle = <&pcs3_2>;
+};
+
+&dpmac6 {
+ pcs-handle = <&pcs3_3>;
+};
+
+&dpmac7 {
+ pcs-handle = <&pcs7_0>;
+};
+
+&dpmac8 {
+ pcs-handle = <&pcs7_1>;
+};
+
+&dpmac9 {
+ pcs-handle = <&pcs7_2>;
+};
+
+&dpmac10 {
+ pcs-handle = <&pcs7_3>;
+};
+
+&emdio1 {
+ status = "okay";
+
+ qsgmii2_phy1: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x00>;
+ };
+
+ qsgmii2_phy2: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x01>;
+ };
+
+ qsgmii2_phy3: ethernet-phy@2 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x02>;
+ };
+
+ qsgmii2_phy4: ethernet-phy@3 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x03>;
+ };
+
+ rgmii_phy2: ethernet-phy@c {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x0c>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_1_50_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_50_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+ };
+
+ rgmii_phy1: ethernet-phy@e {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x0e>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_1_50_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_50_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+ };
+
+ qsgmii1_phy1: ethernet-phy@1c {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1c>;
+ };
+
+ qsgmii1_phy2: ethernet-phy@1d {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1d>;
+ };
+
+ qsgmii1_phy3: ethernet-phy@1e {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1e>;
+ };
+
+ qsgmii1_phy4: ethernet-phy@1f {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1f>;
+ };
+};
+
+&pcs_mdio1 {
+ status = "okay";
+};
+
+&pcs_mdio2 {
+ status = "okay";
+};
+
+&pcs_mdio3 {
+ status = "okay";
+};
+
+&pcs_mdio7 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/tqmls10xxa-mbls10xxa.dtsi b/arch/arm64/boot/dts/freescale/tqmls10xxa-mbls10xxa.dtsi
new file mode 100644
index 000000000000..65b4ed28a3d4
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/tqmls10xxa-mbls10xxa.dtsi
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2018-2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Gregor Herburger, Timo Herbrecher
+ *
+ * Device Tree Include file for MBLS10xxA from TQ
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ gpio-keys-polled {
+ compatible = "gpio-keys-polled";
+ poll-interval = <100>;
+ autorepeat;
+
+ button-0 {
+ label = "button0";
+ gpios = <&gpioexp3 5 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_F1>;
+ };
+
+ button-1 {
+ label = "button1";
+ gpios = <&gpioexp3 6 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_F2>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-user {
+ gpios = <&gpioexp3 13 GPIO_ACTIVE_LOW>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_HEARTBEAT;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "V_3V3_MB";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&duart0 {
+ status = "okay";
+};
+
+&duart1 {
+ status = "okay";
+};
+
+&esdhc {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+
+ i2c-mux@70 {
+ compatible = "nxp,pca9544";
+ reg = <0x70>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpioexp1: gpio@20 {
+ compatible = "nxp,pca9555";
+ reg = <0x20>;
+ vcc-supply = <&reg_3v3>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpioexp2: gpio@21 {
+ compatible = "nxp,pca9555";
+ reg = <0x21>;
+ vcc-supply = <&reg_3v3>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpioexp3: gpio@22 {
+ compatible = "nxp,pca9555";
+ reg = <0x22>;
+ vcc-supply = <&reg_3v3>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+ };
+
+ sfp1_i2c: i2c@1 {
+ reg = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ sfp2_i2c: i2c@2 {
+ reg = <0x2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c@3 {
+ reg = <0x3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
+
+&sata {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&usb1 {
+ dr_mode = "otg";
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/tqmls10xxa.dtsi b/arch/arm64/boot/dts/freescale/tqmls10xxa.dtsi
new file mode 100644
index 000000000000..138f8778afde
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/tqmls10xxa.dtsi
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright (c) 2018-2023 TQ-Systems GmbH <linux@ew.tq-group.com>,
+ * D-82229 Seefeld, Germany.
+ * Author: Gregor Herburger, Timo Herbrecher
+ *
+ * Device Tree Include file for TQMLs10xxA SoM of TQ
+ */
+
+/ {
+ reg_vcc3v3: regulator-vcc3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+};
+
+&i2c0 {
+ status = "okay";
+
+ temperature-sensor@18 {
+ compatible = "nxp,se97b", "jedec,jc-42.4-temp";
+ reg = <0x18>;
+ };
+
+ eeprom@50 {
+ compatible = "nxp,se97b", "atmel,24c02";
+ reg = <0x50>;
+ pagesize = <16>;
+ vcc-supply = <&reg_vcc3v3>;
+ read-only;
+ };
+
+ rtc@51 {
+ compatible = "nxp,pcf85063a";
+ reg = <0x51>;
+ };
+
+ eeprom@57 {
+ compatible = "atmel,24c64";
+ reg = <0x57>;
+ pagesize = <32>;
+ vcc-supply = <&reg_vcc3v3>;
+ };
+};
+
+&esdhc {
+ /* eSDHC or eMMC: set by bootloader */
+ non-removable;
+ disable-wp;
+ mmc-hs200-1_8v;
+ sd-uhs-sdr104;
+ sd-uhs-sdr50;
+ sd-uhs-sdr25;
+ sd-uhs-sdr12;
+};
diff --git a/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi b/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi
index 62d03ffa9485..b5e042b8e929 100644
--- a/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi
@@ -144,7 +144,7 @@
clocks = <&cnm_clock>;
clock-names = "core";
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
- clock-frequency=<100000>;
+ clock-frequency = <100000>;
pinctrl-names = "default", "gpio";
pinctrl-0 = <&i2c0_pins>;
@@ -163,7 +163,7 @@
clocks = <&cnm_clock>;
clock-names = "core";
interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
- clock-frequency=<100000>;
+ clock-frequency = <100000>;
pinctrl-names = "default", "gpio";
pinctrl-0 = <&i2c1_pins>;
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-eDPU.dts b/arch/arm64/boot/dts/marvell/armada-3720-eDPU.dts
index 57fc698e55d0..d6d37a1f6f38 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-eDPU.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-eDPU.dts
@@ -12,3 +12,50 @@
&eth0 {
phy-mode = "2500base-x";
};
+
+/*
+ * External MV88E6361 switch is only available on v2 of the board.
+ * U-Boot will enable the MDIO bus and switch nodes.
+ */
+&mdio {
+ status = "disabled";
+ pinctrl-names = "default";
+ pinctrl-0 = <&smi_pins>;
+
+ /* Actual device is MV88E6361 */
+ switch: switch@0 {
+ compatible = "marvell,mv88e6190";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ label = "cpu";
+ phy-mode = "2500base-x";
+ managed = "in-band-status";
+ ethernet = <&eth0>;
+ };
+
+ port@9 {
+ reg = <9>;
+ label = "downlink";
+ phy-mode = "2500base-x";
+ managed = "in-band-status";
+ };
+
+ port@a {
+ reg = <10>;
+ label = "uplink";
+ phy-mode = "2500base-x";
+ managed = "in-band-status";
+ sfp = <&sfp_eth1>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dtsi b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dtsi
index 5fc613d24151..49cbdb55b4b3 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dtsi
@@ -13,7 +13,7 @@
/ {
aliases {
ethernet0 = &eth0;
- /* for dsa slave device */
+ /* for DSA user port device */
ethernet1 = &switch0port1;
ethernet2 = &switch0port2;
ethernet3 = &switch0port3;
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-uDPU.dtsi b/arch/arm64/boot/dts/marvell/armada-3720-uDPU.dtsi
index 3f79923376fb..3a9b6907185d 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-uDPU.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-3720-uDPU.dtsi
@@ -61,10 +61,10 @@
sfp_eth1: sfp-eth1 {
compatible = "sff,sfp";
i2c-bus = <&i2c1>;
- los-gpio = <&gpiosb 7 GPIO_ACTIVE_HIGH>;
- mod-def0-gpio = <&gpiosb 8 GPIO_ACTIVE_LOW>;
- tx-disable-gpio = <&gpiosb 9 GPIO_ACTIVE_HIGH>;
- tx-fault-gpio = <&gpiosb 10 GPIO_ACTIVE_HIGH>;
+ los-gpios = <&gpiosb 7 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&gpiosb 8 GPIO_ACTIVE_LOW>;
+ tx-disable-gpios = <&gpiosb 9 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpios = <&gpiosb 10 GPIO_ACTIVE_HIGH>;
maximum-power-milliwatt = <3000>;
};
};
diff --git a/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi b/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi
index 32cfb3e2efc3..47d45ff3d6f5 100644
--- a/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi
+++ b/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi
@@ -120,7 +120,7 @@
"mpp59", "mpp60", "mpp61";
marvell,function = "sdio";
};
- cp0_spi0_pins: cp0-spi-pins-0 {
+ cp0_spi1_pins: cp0-spi-pins-1 {
marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
marvell,function = "spi1";
};
@@ -170,7 +170,7 @@
&cp0_spi1 {
pinctrl-names = "default";
- pinctrl-0 = <&cp0_spi0_pins>;
+ pinctrl-0 = <&cp0_spi1_pins>;
reg = <0x700680 0x50>, /* control */
<0x2000000 0x1000000>; /* CS0 */
status = "okay";
diff --git a/arch/arm64/boot/dts/marvell/cn9130-db.dtsi b/arch/arm64/boot/dts/marvell/cn9130-db.dtsi
index c7de1ea0d470..6eb6a175de38 100644
--- a/arch/arm64/boot/dts/marvell/cn9130-db.dtsi
+++ b/arch/arm64/boot/dts/marvell/cn9130-db.dtsi
@@ -307,7 +307,7 @@
&cp0_spi1 {
status = "disabled";
pinctrl-names = "default";
- pinctrl-0 = <&cp0_spi0_pins>;
+ pinctrl-0 = <&cp0_spi1_pins>;
reg = <0x700680 0x50>;
flash@0 {
@@ -371,7 +371,7 @@
"mpp59", "mpp60", "mpp61";
marvell,function = "sdio";
};
- cp0_spi0_pins: cp0-spi-pins-0 {
+ cp0_spi1_pins: cp0-spi-pins-1 {
marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
marvell,function = "spi1";
};
diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index c99c3372a4b5..e6e7592a3645 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -45,7 +45,9 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku176.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-pumpkin.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-asurada-hayato-r1.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-asurada-hayato-r5-sku2.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-asurada-spherion-r0.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-asurada-spherion-r4.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-tomato-r1.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-tomato-r2.dtb
@@ -53,4 +55,5 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-tomato-r3.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-demo.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8365-evk.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-genio-1200-evk.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8516-pumpkin.dtb
diff --git a/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts b/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts
index b5746e6d0b15..7364c7278276 100644
--- a/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts
+++ b/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts
@@ -22,6 +22,23 @@
serial1 = &uart1;
};
+ backlight_lcd0: backlight {
+ compatible = "led-backlight";
+ leds = <&disp_led_pwm>, <&pmic_bl_led>;
+
+ default-brightness-level = <300>;
+ };
+
+ led-controller-display {
+ compatible = "pwm-leds";
+
+ disp_led_pwm: led-0 {
+ label = "backlight-pwm";
+ pwms = <&pwm0 0 500000>;
+ max-brightness = <1024>;
+ };
+ };
+
memory@40000000 {
device_type = "memory";
reg = <0 0x40000000 0 0x1e800000>;
@@ -49,6 +66,65 @@
no-map;
};
};
+
+ vreg_disp_avdd: regulator-disp-avdd {
+ compatible = "regulator-fixed";
+ regulator-name = "disp_avdd";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&pio 138 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ vreg_disp_avee: regulator-disp-avee {
+ compatible = "regulator-fixed";
+ regulator-name = "disp_avee";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&pio 139 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ vreg_disp_vddh: regulator-disp-vddh {
+ compatible = "regulator-fixed";
+ regulator-name = "disp_vddh";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&dsi0 {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel: panel@0 {
+ compatible = "sharp,ls060t1sx01";
+ reg = <0>;
+ avdd-supply = <&vreg_disp_avdd>;
+ avee-supply = <&vreg_disp_avee>;
+ vddi-supply = <&mt6331_vgp3_reg>;
+ vddh-supply = <&vreg_disp_vddh>;
+ reset-gpios = <&pio 106 GPIO_ACTIVE_LOW>;
+ backlight = <&backlight_lcd0>;
+
+ pinctrl-0 = <&disp_rst_pins>;
+ pinctrl-names = "default";
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&dsi0_out>;
+ };
+ };
+ };
+
+ port {
+ dsi0_out: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
+ };
};
&fhctl {
@@ -163,7 +239,17 @@
status = "okay";
};
+&mt6331_vgp3_reg {
+ regulator-min-microvolt = <1800000>;
+};
+
&pio {
+ disp_rst_pins: lcm-pins {
+ pins-rst {
+ pinmux = <PINMUX_GPIO106__FUNC_GPIO106>;
+ };
+ };
+
mmc0_pins_default: emmc-sdr-pins {
pins-cmd-dat {
pinmux = <PINMUX_GPIO154__FUNC_MSDC0_DAT0>,
@@ -338,6 +424,21 @@
* an interrupt on the companion, so we use the MT6332 IRQ GPIO.
*/
interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>;
+
+ mt6332-led {
+ compatible = "mediatek,mt6332-led";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic_bl_led: led@0 {
+ reg = <0>;
+ label = "backlight-pmic";
+ };
+ };
+};
+
+&pwm0 {
+ status = "okay";
};
&uart0 {
diff --git a/arch/arm64/boot/dts/mediatek/mt6795.dtsi b/arch/arm64/boot/dts/mediatek/mt6795.dtsi
index 597bce2fed72..e5e269a660b1 100644
--- a/arch/arm64/boot/dts/mediatek/mt6795.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt6795.dtsi
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015 MediaTek Inc.
- * Author: Mars.C <mars.cheng@mediatek.com>
+ * Copyright (C) 2023 Collabora Ltd.
+ * Authors: Mars.C <mars.cheng@mediatek.com>
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
*/
#include <dt-bindings/interrupt-controller/irq.h>
@@ -19,6 +21,23 @@
#address-cells = <2>;
#size-cells = <2>;
+ aliases {
+ ovl0 = &ovl0;
+ ovl1 = &ovl1;
+ rdma0 = &rdma0;
+ rdma1 = &rdma1;
+ rdma2 = &rdma2;
+ wdma0 = &wdma0;
+ wdma1 = &wdma1;
+ color0 = &color0;
+ color1 = &color1;
+ split0 = &split0;
+ split1 = &split1;
+ dpi0 = &dpi0;
+ dsi0 = &dsi0;
+ dsi1 = &dsi1;
+ };
+
psci {
compatible = "arm,psci-0.2";
method = "smc";
@@ -434,6 +453,26 @@
#mbox-cells = <2>;
};
+ mipi_tx0: dsi-phy@10215000 {
+ compatible = "mediatek,mt8173-mipi-tx";
+ reg = <0 0x10215000 0 0x1000>;
+ clocks = <&clk26m>;
+ clock-output-names = "mipi_tx0_pll";
+ #clock-cells = <0>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+
+ mipi_tx1: dsi-phy@10216000 {
+ compatible = "mediatek,mt8173-mipi-tx";
+ reg = <0 0x10216000 0 0x1000>;
+ clocks = <&clk26m>;
+ clock-output-names = "mipi_tx1_pll";
+ #clock-cells = <0>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+
gic: interrupt-controller@10221000 {
compatible = "arm,gic-400";
#interrupt-cells = <3>;
@@ -690,6 +729,211 @@
mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0 0x1000>;
};
+ ovl0: ovl@1400c000 {
+ compatible = "mediatek,mt6795-disp-ovl", "mediatek,mt8173-disp-ovl";
+ reg = <0 0x1400c000 0 0x1000>;
+ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_OVL0>;
+ iommus = <&iommu M4U_PORT_DISP_OVL0>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0xc000 0x1000>;
+ };
+
+ ovl1: ovl@1400d000 {
+ compatible = "mediatek,mt6795-disp-ovl", "mediatek,mt8173-disp-ovl";
+ reg = <0 0x1400d000 0 0x1000>;
+ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_OVL1>;
+ iommus = <&iommu M4U_PORT_DISP_OVL1>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0xd000 0x1000>;
+ };
+
+ rdma0: rdma@1400e000 {
+ compatible = "mediatek,mt6795-disp-rdma", "mediatek,mt8173-disp-rdma";
+ reg = <0 0x1400e000 0 0x1000>;
+ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_RDMA0>;
+ iommus = <&iommu M4U_PORT_DISP_RDMA0>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0xe000 0x1000>;
+ };
+
+ rdma1: rdma@1400f000 {
+ compatible = "mediatek,mt6795-disp-rdma", "mediatek,mt8173-disp-rdma";
+ reg = <0 0x1400f000 0 0x1000>;
+ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_RDMA1>;
+ iommus = <&iommu M4U_PORT_DISP_RDMA1>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0xf000 0x1000>;
+ };
+
+ rdma2: rdma@14010000 {
+ compatible = "mediatek,mt6795-disp-rdma", "mediatek,mt8173-disp-rdma";
+ reg = <0 0x14010000 0 0x1000>;
+ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_RDMA2>;
+ iommus = <&iommu M4U_PORT_DISP_RDMA2>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0 0x1000>;
+ };
+
+ wdma0: wdma@14011000 {
+ compatible = "mediatek,mt6795-disp-wdma", "mediatek,mt8173-disp-wdma";
+ reg = <0 0x14011000 0 0x1000>;
+ interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_WDMA0>;
+ iommus = <&iommu M4U_PORT_DISP_WDMA0>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0x1000 0x1000>;
+ };
+
+ wdma1: wdma@14012000 {
+ compatible = "mediatek,mt6795-disp-wdma", "mediatek,mt8173-disp-wdma";
+ reg = <0 0x14012000 0 0x1000>;
+ interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_WDMA1>;
+ iommus = <&iommu M4U_PORT_DISP_WDMA1>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0x2000 0x1000>;
+ };
+
+ color0: color@14013000 {
+ compatible = "mediatek,mt6795-disp-color", "mediatek,mt8173-disp-color";
+ reg = <0 0x14013000 0 0x1000>;
+ interrupts = <GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_COLOR0>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0x3000 0x1000>;
+ };
+
+ color1: color@14014000 {
+ compatible = "mediatek,mt6795-disp-color", "mediatek,mt8173-disp-color";
+ reg = <0 0x14014000 0 0x1000>;
+ interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_COLOR1>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0x4000 0x1000>;
+ };
+
+ aal@14015000 {
+ compatible = "mediatek,mt6795-disp-aal", "mediatek,mt8173-disp-aal";
+ reg = <0 0x14015000 0 0x1000>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_AAL>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0x5000 0x1000>;
+ };
+
+ gamma@14016000 {
+ compatible = "mediatek,mt6795-disp-gamma", "mediatek,mt8173-disp-gamma";
+ reg = <0 0x14016000 0 0x1000>;
+ interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_GAMMA>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0x6000 0x1000>;
+ };
+
+ merge@14017000 {
+ compatible = "mediatek,mt6795-disp-merge", "mediatek,mt8173-disp-merge";
+ reg = <0 0x14017000 0 0x1000>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_MERGE>;
+ };
+
+ split0: split@14018000 {
+ compatible = "mediatek,mt6795-disp-split", "mediatek,mt8173-disp-split";
+ reg = <0 0x14018000 0 0x1000>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_SPLIT0>;
+ };
+
+ split1: split@14019000 {
+ compatible = "mediatek,mt6795-disp-split", "mediatek,mt8173-disp-split";
+ reg = <0 0x14019000 0 0x1000>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_SPLIT1>;
+ };
+
+ ufoe@1401a000 {
+ compatible = "mediatek,mt6795-disp-ufoe", "mediatek,mt8173-disp-ufoe";
+ reg = <0 0x1401a000 0 0x1000>;
+ interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DISP_UFOE>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0xa000 0x1000>;
+ };
+
+ dsi0: dsi@1401b000 {
+ compatible = "mediatek,mt6795-dsi", "mediatek,mt8173-dsi";
+ reg = <0 0x1401b000 0 0x1000>;
+ interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DSI0_ENGINE>,
+ <&mmsys CLK_MM_DSI0_DIGITAL>,
+ <&mipi_tx0>;
+ clock-names = "engine", "digital", "hs";
+ phys = <&mipi_tx0>;
+ phy-names = "dphy";
+ status = "disabled";
+ };
+
+ dsi1: dsi@1401c000 {
+ compatible = "mediatek,mt6795-dsi", "mediatek,mt8173-dsi";
+ reg = <0 0x1401c000 0 0x1000>;
+ interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DSI1_ENGINE>,
+ <&mmsys CLK_MM_DSI1_DIGITAL>,
+ <&mipi_tx1>;
+ clock-names = "engine", "digital", "hs";
+ phys = <&mipi_tx1>;
+ phy-names = "dphy";
+ status = "disabled";
+ };
+
+ dpi0: dpi@1401d000 {
+ compatible = "mediatek,mt6795-dpi", "mediatek,mt8183-dpi";
+ reg = <0 0x1401d000 0 0x1000>;
+ interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_DPI_PIXEL>,
+ <&mmsys CLK_MM_DPI_ENGINE>,
+ <&apmixedsys CLK_APMIXED_TVDPLL>;
+ clock-names = "pixel", "engine", "pll";
+ status = "disabled";
+ };
+
+ pwm0: pwm@1401e000 {
+ compatible = "mediatek,mt6795-disp-pwm", "mediatek,mt8173-disp-pwm";
+ reg = <0 0x1401e000 0 0x1000>;
+ #pwm-cells = <2>;
+ clocks = <&mmsys CLK_MM_DISP_PWM026M>, <&mmsys CLK_MM_DISP_PWM0MM>;
+ clock-names = "main", "mm";
+ status = "disabled";
+ };
+
+ pwm1: pwm@1401f000 {
+ compatible = "mediatek,mt6795-disp-pwm", "mediatek,mt8173-disp-pwm";
+ reg = <0 0x1401f000 0 0x1000>;
+ #pwm-cells = <2>;
+ clocks = <&mmsys CLK_MM_DISP_PWM126M>, <&mmsys CLK_MM_DISP_PWM1MM>;
+ clock-names = "main", "mm";
+ status = "disabled";
+ };
+
+ mutex: mutex@14020000 {
+ compatible = "mediatek,mt8173-disp-mutex";
+ reg = <0 0x14020000 0 0x1000>;
+ interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&spm MT6795_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_MUTEX_32K>;
+ mediatek,gce-events = <CMDQ_EVENT_MUTEX0_STREAM_EOF>,
+ <CMDQ_EVENT_MUTEX1_STREAM_EOF>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1402XXXX 0 0x1000>;
+ };
+
larb0: larb@14021000 {
compatible = "mediatek,mt6795-smi-larb";
reg = <0 0x14021000 0 0x1000>;
@@ -708,6 +952,13 @@
clock-names = "apb", "smi";
};
+ od@14023000 {
+ compatible = "mediatek,mt6795-disp-od", "mediatek,mt8173-disp-od";
+ reg = <0 0x14023000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_DISP_OD>;
+ mediatek,gce-client-reg = <&gce SUBSYS_1402XXXX 0x3000 0x1000>;
+ };
+
larb2: larb@15001000 {
compatible = "mediatek,mt6795-smi-larb";
reg = <0 0x15001000 0 0x1000>;
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
index 86cedb0bf1a9..c46682150e50 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
@@ -73,7 +73,7 @@
};
};
- memory {
+ memory@40000000 {
reg = <0 0x40000000 0 0x40000000>;
};
@@ -385,9 +385,9 @@
i2s1_pins: i2s1-pins {
mux {
function = "i2s";
- groups = "i2s_out_mclk_bclk_ws",
- "i2s1_in_data",
- "i2s1_out_data";
+ groups = "i2s_out_mclk_bclk_ws",
+ "i2s1_in_data",
+ "i2s1_out_data";
};
conf {
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
index dad8e683aac5..2dc1bdc74e21 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
@@ -55,7 +55,7 @@
};
};
- memory {
+ memory@40000000 {
reg = <0 0x40000000 0 0x20000000>;
};
@@ -311,9 +311,9 @@
i2s1_pins: i2s1-pins {
mux {
function = "i2s";
- groups = "i2s_out_mclk_bclk_ws",
- "i2s1_in_data",
- "i2s1_out_data";
+ groups = "i2s_out_mclk_bclk_ws",
+ "i2s1_in_data",
+ "i2s1_out_data";
};
conf {
diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
index 36ef2dbe8add..3ee9266fa8e9 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -905,7 +905,7 @@
status = "disabled";
};
- sata_phy: t-phy@1a243000 {
+ sata_phy: t-phy {
compatible = "mediatek,mt7622-tphy",
"mediatek,generic-tphy-v1";
#address-cells = <2>;
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
index af4a4309bda4..b876e501216b 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
@@ -126,6 +126,7 @@
compatible = "sff,sfp";
i2c-bus = <&i2c_sfp1>;
los-gpios = <&pio 46 GPIO_ACTIVE_HIGH>;
+ maximum-power-milliwatt = <3000>;
mod-def0-gpios = <&pio 49 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&pio 20 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
@@ -137,6 +138,7 @@
i2c-bus = <&i2c_sfp2>;
los-gpios = <&pio 31 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&pio 47 GPIO_ACTIVE_LOW>;
+ maximum-power-milliwatt = <3000>;
tx-disable-gpios = <&pio 15 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&pio 48 GPIO_ACTIVE_HIGH>;
};
@@ -150,16 +152,16 @@
trip = <&cpu_trip_active_high>;
};
- cpu-active-low {
+ cpu-active-med {
/* active: set fan to cooling level 1 */
cooling-device = <&fan 1 1>;
- trip = <&cpu_trip_active_low>;
+ trip = <&cpu_trip_active_med>;
};
- cpu-passive {
- /* passive: set fan to cooling level 0 */
+ cpu-active-low {
+ /* active: set fan to cooling level 0 */
cooling-device = <&fan 0 0>;
- trip = <&cpu_trip_passive>;
+ trip = <&cpu_trip_active_low>;
};
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
index 68539ea788df..fc751e049953 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
@@ -374,6 +374,10 @@
reg = <0 0x11230000 0 0x1000>,
<0 0x11c20000 0 0x1000>;
interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+ assigned-clocks = <&topckgen CLK_TOP_EMMC_416M_SEL>,
+ <&topckgen CLK_TOP_EMMC_250M_SEL>;
+ assigned-clock-parents = <&apmixedsys CLK_APMIXED_MPLL>,
+ <&topckgen CLK_TOP_NET1PLL_D5_D2>;
clocks = <&topckgen CLK_TOP_EMMC_416M_SEL>,
<&infracfg CLK_INFRA_MSDC_HCK_CK>,
<&infracfg CLK_INFRA_MSDC_CK>,
@@ -434,7 +438,7 @@
};
};
- pcie_phy: t-phy@11c00000 {
+ pcie_phy: t-phy {
compatible = "mediatek,mt7986-tphy",
"mediatek,generic-tphy-v2";
#address-cells = <2>;
@@ -610,22 +614,34 @@
thermal-sensors = <&thermal 0>;
trips {
+ cpu_trip_crit: crit {
+ temperature = <125000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+
+ cpu_trip_hot: hot {
+ temperature = <120000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
cpu_trip_active_high: active-high {
temperature = <115000>;
hysteresis = <2000>;
type = "active";
};
- cpu_trip_active_low: active-low {
+ cpu_trip_active_med: active-med {
temperature = <85000>;
hysteresis = <2000>;
type = "active";
};
- cpu_trip_passive: passive {
- temperature = <40000>;
+ cpu_trip_active_low: active-low {
+ temperature = <60000>;
hysteresis = <2000>;
- type = "passive";
+ type = "active";
};
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
index 5122963d8743..d258c80213b2 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
@@ -44,7 +44,7 @@
id-gpio = <&pio 16 GPIO_ACTIVE_HIGH>;
};
- usb_p1_vbus: regulator@0 {
+ usb_p1_vbus: regulator-usb-p1 {
compatible = "regulator-fixed";
regulator-name = "usb_vbus";
regulator-min-microvolt = <5000000>;
@@ -53,7 +53,7 @@
enable-active-high;
};
- usb_p0_vbus: regulator@1 {
+ usb_p0_vbus: regulator-usb-p0 {
compatible = "regulator-fixed";
regulator-name = "vbus";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
index d8bd51807683..77f9ab94c00b 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
@@ -31,14 +31,14 @@
#address-cells = <2>;
#size-cells = <2>;
ranges;
- scp_mem_reserved: scp_mem_region {
+ scp_mem_reserved: memory@50000000 {
compatible = "shared-dma-pool";
reg = <0 0x50000000 0 0x2900000>;
no-map;
};
};
- ntc@0 {
+ thermal-sensor {
compatible = "murata,ncp03wf104";
pullup-uv = <1800000>;
pullup-ohm = <390000>;
@@ -155,8 +155,8 @@
};
&pio {
- i2c_pins_0: i2c0{
- pins_i2c{
+ i2c_pins_0: i2c0 {
+ pins_i2c {
pinmux = <PINMUX_GPIO82__FUNC_SDA0>,
<PINMUX_GPIO83__FUNC_SCL0>;
mediatek,pull-up-adv = <3>;
@@ -164,8 +164,8 @@
};
};
- i2c_pins_1: i2c1{
- pins_i2c{
+ i2c_pins_1: i2c1 {
+ pins_i2c {
pinmux = <PINMUX_GPIO81__FUNC_SDA1>,
<PINMUX_GPIO84__FUNC_SCL1>;
mediatek,pull-up-adv = <3>;
@@ -173,8 +173,8 @@
};
};
- i2c_pins_2: i2c2{
- pins_i2c{
+ i2c_pins_2: i2c2 {
+ pins_i2c {
pinmux = <PINMUX_GPIO103__FUNC_SCL2>,
<PINMUX_GPIO104__FUNC_SDA2>;
mediatek,pull-up-adv = <3>;
@@ -182,8 +182,8 @@
};
};
- i2c_pins_3: i2c3{
- pins_i2c{
+ i2c_pins_3: i2c3 {
+ pins_i2c {
pinmux = <PINMUX_GPIO50__FUNC_SCL3>,
<PINMUX_GPIO51__FUNC_SDA3>;
mediatek,pull-up-adv = <3>;
@@ -191,8 +191,8 @@
};
};
- i2c_pins_4: i2c4{
- pins_i2c{
+ i2c_pins_4: i2c4 {
+ pins_i2c {
pinmux = <PINMUX_GPIO105__FUNC_SCL4>,
<PINMUX_GPIO106__FUNC_SDA4>;
mediatek,pull-up-adv = <3>;
@@ -200,8 +200,8 @@
};
};
- i2c_pins_5: i2c5{
- pins_i2c{
+ i2c_pins_5: i2c5 {
+ pins_i2c {
pinmux = <PINMUX_GPIO48__FUNC_SCL5>,
<PINMUX_GPIO49__FUNC_SDA5>;
mediatek,pull-up-adv = <3>;
@@ -209,8 +209,8 @@
};
};
- spi_pins_0: spi0{
- pins_spi{
+ spi_pins_0: spi0 {
+ pins_spi {
pinmux = <PINMUX_GPIO85__FUNC_SPI0_MI>,
<PINMUX_GPIO86__FUNC_SPI0_CSB>,
<PINMUX_GPIO87__FUNC_SPI0_MO>,
@@ -324,8 +324,8 @@
};
};
- spi_pins_1: spi1{
- pins_spi{
+ spi_pins_1: spi1 {
+ pins_spi {
pinmux = <PINMUX_GPIO161__FUNC_SPI1_A_MI>,
<PINMUX_GPIO162__FUNC_SPI1_A_CSB>,
<PINMUX_GPIO163__FUNC_SPI1_A_MO>,
@@ -334,8 +334,8 @@
};
};
- spi_pins_2: spi2{
- pins_spi{
+ spi_pins_2: spi2 {
+ pins_spi {
pinmux = <PINMUX_GPIO0__FUNC_SPI2_CSB>,
<PINMUX_GPIO1__FUNC_SPI2_MO>,
<PINMUX_GPIO2__FUNC_SPI2_CLK>,
@@ -344,8 +344,8 @@
};
};
- spi_pins_3: spi3{
- pins_spi{
+ spi_pins_3: spi3 {
+ pins_spi {
pinmux = <PINMUX_GPIO21__FUNC_SPI3_MI>,
<PINMUX_GPIO22__FUNC_SPI3_CSB>,
<PINMUX_GPIO23__FUNC_SPI3_MO>,
@@ -354,8 +354,8 @@
};
};
- spi_pins_4: spi4{
- pins_spi{
+ spi_pins_4: spi4 {
+ pins_spi {
pinmux = <PINMUX_GPIO17__FUNC_SPI4_MI>,
<PINMUX_GPIO18__FUNC_SPI4_CSB>,
<PINMUX_GPIO19__FUNC_SPI4_MO>,
@@ -364,8 +364,8 @@
};
};
- spi_pins_5: spi5{
- pins_spi{
+ spi_pins_5: spi5 {
+ pins_spi {
pinmux = <PINMUX_GPIO13__FUNC_SPI5_MI>,
<PINMUX_GPIO14__FUNC_SPI5_CSB>,
<PINMUX_GPIO15__FUNC_SPI5_MO>,
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
index bf97b60ae4d1..820260348de9 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
@@ -91,6 +91,8 @@
&dsi0 {
status = "okay";
+ /delete-property/#size-cells;
+ /delete-property/#address-cells;
/delete-node/panel@0;
ports {
port {
@@ -441,20 +443,20 @@
};
touchscreen_pins: touchscreen-pins {
- touch_int_odl {
+ touch-int-odl {
pinmux = <PINMUX_GPIO155__FUNC_GPIO155>;
input-enable;
bias-pull-up;
};
- touch_rst_l {
+ touch-rst-l {
pinmux = <PINMUX_GPIO156__FUNC_GPIO156>;
output-high;
};
};
trackpad_pins: trackpad-pins {
- trackpad_int {
+ trackpad-int {
pinmux = <PINMUX_GPIO7__FUNC_GPIO7>;
input-enable;
bias-disable; /* pulled externally */
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
index 6ce16a265e05..7881a27be029 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
@@ -103,12 +103,20 @@
regulator-max-microvolt = <3300000>;
};
+ /* system wide semi-regulated power rail from charger */
+ reg_vsys: regulator-vsys {
+ compatible = "regulator-fixed";
+ regulator-name = "vsys";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
reserved_memory: reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
- scp_mem_reserved: scp_mem_region {
+ scp_mem_reserved: memory@50000000 {
compatible = "shared-dma-pool";
reg = <0 0x50000000 0 0x2900000>;
no-map;
@@ -404,6 +412,26 @@
Avdd-supply = <&mt6358_vaud28_reg>;
};
+&mt6358regulator {
+ vsys-ldo1-supply = <&reg_vsys>;
+ vsys-ldo2-supply = <&reg_vsys>;
+ vsys-ldo3-supply = <&reg_vsys>;
+ vsys-vcore-supply = <&reg_vsys>;
+ vsys-vdram1-supply = <&reg_vsys>;
+ vsys-vgpu-supply = <&reg_vsys>;
+ vsys-vmodem-supply = <&reg_vsys>;
+ vsys-vpa-supply = <&reg_vsys>;
+ vsys-vproc11-supply = <&reg_vsys>;
+ vsys-vproc12-supply = <&reg_vsys>;
+ vsys-vs1-supply = <&reg_vsys>;
+ vsys-vs2-supply = <&reg_vsys>;
+ vs1-ldo1-supply = <&mt6358_vs1_reg>;
+ vs2-ldo1-supply = <&mt6358_vdram1_reg>;
+ vs2-ldo2-supply = <&mt6358_vs2_reg>;
+ vs2-ldo3-supply = <&mt6358_vs2_reg>;
+ vs2-ldo4-supply = <&mt6358_vs2_reg>;
+};
+
&mt6358_vgpu_reg {
regulator-min-microvolt = <625000>;
regulator-max-microvolt = <900000>;
@@ -432,7 +460,7 @@
&pio {
aud_pins_default: audiopins {
- pins_bus {
+ pins-bus {
pinmux = <PINMUX_GPIO97__FUNC_I2S2_MCK>,
<PINMUX_GPIO98__FUNC_I2S2_BCK>,
<PINMUX_GPIO101__FUNC_I2S2_LRCK>,
@@ -454,7 +482,7 @@
};
aud_pins_tdm_out_on: audiotdmouton {
- pins_bus {
+ pins-bus {
pinmux = <PINMUX_GPIO169__FUNC_TDM_BCK_2ND>,
<PINMUX_GPIO170__FUNC_TDM_LRCK_2ND>,
<PINMUX_GPIO171__FUNC_TDM_DATA0_2ND>,
@@ -466,7 +494,7 @@
};
aud_pins_tdm_out_off: audiotdmoutoff {
- pins_bus {
+ pins-bus {
pinmux = <PINMUX_GPIO169__FUNC_GPIO169>,
<PINMUX_GPIO170__FUNC_GPIO170>,
<PINMUX_GPIO171__FUNC_GPIO171>,
@@ -480,13 +508,13 @@
};
bt_pins: bt-pins {
- pins_bt_en {
+ pins-bt-en {
pinmux = <PINMUX_GPIO120__FUNC_GPIO120>;
output-low;
};
};
- ec_ap_int_odl: ec_ap_int_odl {
+ ec_ap_int_odl: ec-ap-int-odl {
pins1 {
pinmux = <PINMUX_GPIO151__FUNC_GPIO151>;
input-enable;
@@ -494,7 +522,7 @@
};
};
- h1_int_od_l: h1_int_od_l {
+ h1_int_od_l: h1-int-od-l {
pins1 {
pinmux = <PINMUX_GPIO153__FUNC_GPIO153>;
input-enable;
@@ -502,7 +530,7 @@
};
i2c0_pins: i2c0 {
- pins_bus {
+ pins-bus {
pinmux = <PINMUX_GPIO82__FUNC_SDA0>,
<PINMUX_GPIO83__FUNC_SCL0>;
mediatek,pull-up-adv = <3>;
@@ -511,7 +539,7 @@
};
i2c1_pins: i2c1 {
- pins_bus {
+ pins-bus {
pinmux = <PINMUX_GPIO81__FUNC_SDA1>,
<PINMUX_GPIO84__FUNC_SCL1>;
mediatek,pull-up-adv = <3>;
@@ -520,7 +548,7 @@
};
i2c2_pins: i2c2 {
- pins_bus {
+ pins-bus {
pinmux = <PINMUX_GPIO103__FUNC_SCL2>,
<PINMUX_GPIO104__FUNC_SDA2>;
bias-disable;
@@ -529,7 +557,7 @@
};
i2c3_pins: i2c3 {
- pins_bus {
+ pins-bus {
pinmux = <PINMUX_GPIO50__FUNC_SCL3>,
<PINMUX_GPIO51__FUNC_SDA3>;
mediatek,pull-up-adv = <3>;
@@ -538,7 +566,7 @@
};
i2c4_pins: i2c4 {
- pins_bus {
+ pins-bus {
pinmux = <PINMUX_GPIO105__FUNC_SCL4>,
<PINMUX_GPIO106__FUNC_SDA4>;
bias-disable;
@@ -547,7 +575,7 @@
};
i2c5_pins: i2c5 {
- pins_bus {
+ pins-bus {
pinmux = <PINMUX_GPIO48__FUNC_SCL5>,
<PINMUX_GPIO49__FUNC_SDA5>;
mediatek,pull-up-adv = <3>;
@@ -556,7 +584,7 @@
};
i2c6_pins: i2c6 {
- pins_bus {
+ pins-bus {
pinmux = <PINMUX_GPIO11__FUNC_SCL6>,
<PINMUX_GPIO12__FUNC_SDA6>;
bias-disable;
@@ -564,7 +592,7 @@
};
mmc0_pins_default: mmc0-pins-default {
- pins_cmd_dat {
+ pins-cmd-dat {
pinmux = <PINMUX_GPIO123__FUNC_MSDC0_DAT0>,
<PINMUX_GPIO128__FUNC_MSDC0_DAT1>,
<PINMUX_GPIO125__FUNC_MSDC0_DAT2>,
@@ -579,13 +607,13 @@
mediatek,pull-up-adv = <01>;
};
- pins_clk {
+ pins-clk {
pinmux = <PINMUX_GPIO124__FUNC_MSDC0_CLK>;
drive-strength = <MTK_DRIVE_14mA>;
mediatek,pull-down-adv = <10>;
};
- pins_rst {
+ pins-rst {
pinmux = <PINMUX_GPIO133__FUNC_MSDC0_RSTB>;
drive-strength = <MTK_DRIVE_14mA>;
mediatek,pull-down-adv = <01>;
@@ -593,7 +621,7 @@
};
mmc0_pins_uhs: mmc0-pins-uhs {
- pins_cmd_dat {
+ pins-cmd-dat {
pinmux = <PINMUX_GPIO123__FUNC_MSDC0_DAT0>,
<PINMUX_GPIO128__FUNC_MSDC0_DAT1>,
<PINMUX_GPIO125__FUNC_MSDC0_DAT2>,
@@ -608,19 +636,19 @@
mediatek,pull-up-adv = <01>;
};
- pins_clk {
+ pins-clk {
pinmux = <PINMUX_GPIO124__FUNC_MSDC0_CLK>;
drive-strength = <MTK_DRIVE_14mA>;
mediatek,pull-down-adv = <10>;
};
- pins_ds {
+ pins-ds {
pinmux = <PINMUX_GPIO131__FUNC_MSDC0_DSL>;
drive-strength = <MTK_DRIVE_14mA>;
mediatek,pull-down-adv = <10>;
};
- pins_rst {
+ pins-rst {
pinmux = <PINMUX_GPIO133__FUNC_MSDC0_RSTB>;
drive-strength = <MTK_DRIVE_14mA>;
mediatek,pull-up-adv = <01>;
@@ -628,7 +656,7 @@
};
mmc1_pins_default: mmc1-pins-default {
- pins_cmd_dat {
+ pins-cmd-dat {
pinmux = <PINMUX_GPIO31__FUNC_MSDC1_CMD>,
<PINMUX_GPIO32__FUNC_MSDC1_DAT0>,
<PINMUX_GPIO34__FUNC_MSDC1_DAT1>,
@@ -638,7 +666,7 @@
mediatek,pull-up-adv = <10>;
};
- pins_clk {
+ pins-clk {
pinmux = <PINMUX_GPIO29__FUNC_MSDC1_CLK>;
input-enable;
mediatek,pull-down-adv = <10>;
@@ -646,7 +674,7 @@
};
mmc1_pins_uhs: mmc1-pins-uhs {
- pins_cmd_dat {
+ pins-cmd-dat {
pinmux = <PINMUX_GPIO31__FUNC_MSDC1_CMD>,
<PINMUX_GPIO32__FUNC_MSDC1_DAT0>,
<PINMUX_GPIO34__FUNC_MSDC1_DAT1>,
@@ -657,7 +685,7 @@
mediatek,pull-up-adv = <10>;
};
- pins_clk {
+ pins-clk {
pinmux = <PINMUX_GPIO29__FUNC_MSDC1_CLK>;
drive-strength = <MTK_DRIVE_8mA>;
mediatek,pull-down-adv = <10>;
@@ -665,15 +693,15 @@
};
};
- panel_pins_default: panel_pins_default {
- panel_reset {
+ panel_pins_default: panel-pins-default {
+ panel-reset {
pinmux = <PINMUX_GPIO45__FUNC_GPIO45>;
output-low;
bias-pull-up;
};
};
- pwm0_pin_default: pwm0_pin_default {
+ pwm0_pin_default: pwm0-pin-default {
pins1 {
pinmux = <PINMUX_GPIO176__FUNC_GPIO176>;
output-high;
@@ -685,14 +713,14 @@
};
scp_pins: scp {
- pins_scp_uart {
+ pins-scp-uart {
pinmux = <PINMUX_GPIO110__FUNC_TP_URXD1_AO>,
<PINMUX_GPIO112__FUNC_TP_UTXD1_AO>;
};
};
spi0_pins: spi0 {
- pins_spi{
+ pins-spi {
pinmux = <PINMUX_GPIO85__FUNC_SPI0_MI>,
<PINMUX_GPIO86__FUNC_GPIO86>,
<PINMUX_GPIO87__FUNC_SPI0_MO>,
@@ -702,7 +730,7 @@
};
spi1_pins: spi1 {
- pins_spi{
+ pins-spi {
pinmux = <PINMUX_GPIO161__FUNC_SPI1_A_MI>,
<PINMUX_GPIO162__FUNC_SPI1_A_CSB>,
<PINMUX_GPIO163__FUNC_SPI1_A_MO>,
@@ -712,20 +740,20 @@
};
spi2_pins: spi2 {
- pins_spi{
+ pins-spi {
pinmux = <PINMUX_GPIO0__FUNC_SPI2_CSB>,
<PINMUX_GPIO1__FUNC_SPI2_MO>,
<PINMUX_GPIO2__FUNC_SPI2_CLK>;
bias-disable;
};
- pins_spi_mi {
+ pins-spi-mi {
pinmux = <PINMUX_GPIO94__FUNC_SPI2_MI>;
mediatek,pull-down-adv = <00>;
};
};
spi3_pins: spi3 {
- pins_spi{
+ pins-spi {
pinmux = <PINMUX_GPIO21__FUNC_SPI3_MI>,
<PINMUX_GPIO22__FUNC_SPI3_CSB>,
<PINMUX_GPIO23__FUNC_SPI3_MO>,
@@ -735,7 +763,7 @@
};
spi4_pins: spi4 {
- pins_spi{
+ pins-spi {
pinmux = <PINMUX_GPIO17__FUNC_SPI4_MI>,
<PINMUX_GPIO18__FUNC_SPI4_CSB>,
<PINMUX_GPIO19__FUNC_SPI4_MO>,
@@ -745,7 +773,7 @@
};
spi5_pins: spi5 {
- pins_spi{
+ pins-spi {
pinmux = <PINMUX_GPIO13__FUNC_SPI5_MI>,
<PINMUX_GPIO14__FUNC_SPI5_CSB>,
<PINMUX_GPIO15__FUNC_SPI5_MO>,
@@ -755,63 +783,63 @@
};
uart0_pins_default: uart0-pins-default {
- pins_rx {
+ pins-rx {
pinmux = <PINMUX_GPIO95__FUNC_URXD0>;
input-enable;
bias-pull-up;
};
- pins_tx {
+ pins-tx {
pinmux = <PINMUX_GPIO96__FUNC_UTXD0>;
};
};
uart1_pins_default: uart1-pins-default {
- pins_rx {
+ pins-rx {
pinmux = <PINMUX_GPIO121__FUNC_URXD1>;
input-enable;
bias-pull-up;
};
- pins_tx {
+ pins-tx {
pinmux = <PINMUX_GPIO115__FUNC_UTXD1>;
};
- pins_rts {
+ pins-rts {
pinmux = <PINMUX_GPIO47__FUNC_URTS1>;
output-enable;
};
- pins_cts {
+ pins-cts {
pinmux = <PINMUX_GPIO46__FUNC_UCTS1>;
input-enable;
};
};
uart1_pins_sleep: uart1-pins-sleep {
- pins_rx {
+ pins-rx {
pinmux = <PINMUX_GPIO121__FUNC_GPIO121>;
input-enable;
bias-pull-up;
};
- pins_tx {
+ pins-tx {
pinmux = <PINMUX_GPIO115__FUNC_UTXD1>;
};
- pins_rts {
+ pins-rts {
pinmux = <PINMUX_GPIO47__FUNC_URTS1>;
output-enable;
};
- pins_cts {
+ pins-cts {
pinmux = <PINMUX_GPIO46__FUNC_UCTS1>;
input-enable;
};
};
wifi_pins_pwrseq: wifi-pins-pwrseq {
- pins_wifi_enable {
+ pins-wifi-enable {
pinmux = <PINMUX_GPIO119__FUNC_GPIO119>;
output-low;
};
};
wifi_pins_wakeup: wifi-pins-wakeup {
- pins_wifi_wakeup {
+ pins-wifi-wakeup {
pinmux = <PINMUX_GPIO113__FUNC_GPIO113>;
input-enable;
};
@@ -831,7 +859,7 @@
pinctrl-names = "default";
pinctrl-0 = <&scp_pins>;
- cros_ec {
+ cros-ec-rpmsg {
compatible = "google,cros-ec-rpmsg";
mediatek,rpmsg-name = "cros-ec-rpmsg";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts b/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts
index 526bcae7a3f8..b5784a60c315 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts
@@ -193,7 +193,7 @@
&pio {
i2c_pins_0: i2c0 {
- pins_i2c{
+ pins_i2c {
pinmux = <PINMUX_GPIO82__FUNC_SDA0>,
<PINMUX_GPIO83__FUNC_SCL0>;
mediatek,pull-up-adv = <3>;
@@ -202,7 +202,7 @@
};
i2c_pins_1: i2c1 {
- pins_i2c{
+ pins_i2c {
pinmux = <PINMUX_GPIO81__FUNC_SDA1>,
<PINMUX_GPIO84__FUNC_SCL1>;
mediatek,pull-up-adv = <3>;
@@ -211,7 +211,7 @@
};
i2c_pins_2: i2c2 {
- pins_i2c{
+ pins_i2c {
pinmux = <PINMUX_GPIO103__FUNC_SCL2>,
<PINMUX_GPIO104__FUNC_SDA2>;
mediatek,pull-up-adv = <3>;
@@ -220,7 +220,7 @@
};
i2c_pins_3: i2c3 {
- pins_i2c{
+ pins_i2c {
pinmux = <PINMUX_GPIO50__FUNC_SCL3>,
<PINMUX_GPIO51__FUNC_SDA3>;
mediatek,pull-up-adv = <3>;
@@ -229,7 +229,7 @@
};
i2c_pins_4: i2c4 {
- pins_i2c{
+ pins_i2c {
pinmux = <PINMUX_GPIO105__FUNC_SCL4>,
<PINMUX_GPIO106__FUNC_SDA4>;
mediatek,pull-up-adv = <3>;
@@ -238,7 +238,7 @@
};
i2c_pins_5: i2c5 {
- pins_i2c{
+ pins_i2c {
pinmux = <PINMUX_GPIO48__FUNC_SCL5>,
<PINMUX_GPIO49__FUNC_SDA5>;
mediatek,pull-up-adv = <3>;
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index 5169779d01df..976dc968b3ca 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -1210,127 +1210,6 @@
nvmem-cell-names = "calibration-data";
};
- thermal_zones: thermal-zones {
- cpu_thermal: cpu-thermal {
- polling-delay-passive = <100>;
- polling-delay = <500>;
- thermal-sensors = <&thermal 0>;
- sustainable-power = <5000>;
-
- trips {
- threshold: trip-point0 {
- temperature = <68000>;
- hysteresis = <2000>;
- type = "passive";
- };
-
- target: trip-point1 {
- temperature = <80000>;
- hysteresis = <2000>;
- type = "passive";
- };
-
- cpu_crit: cpu-crit {
- temperature = <115000>;
- hysteresis = <2000>;
- type = "critical";
- };
- };
-
- cooling-maps {
- map0 {
- trip = <&target>;
- cooling-device = <&cpu0
- THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>,
- <&cpu1
- THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>,
- <&cpu2
- THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>,
- <&cpu3
- THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>;
- contribution = <3072>;
- };
- map1 {
- trip = <&target>;
- cooling-device = <&cpu4
- THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>,
- <&cpu5
- THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>,
- <&cpu6
- THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>,
- <&cpu7
- THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>;
- contribution = <1024>;
- };
- };
- };
-
- /* The tzts1 ~ tzts6 don't need to polling */
- /* The tzts1 ~ tzts6 don't need to thermal throttle */
-
- tzts1: tzts1 {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&thermal 1>;
- sustainable-power = <5000>;
- trips {};
- cooling-maps {};
- };
-
- tzts2: tzts2 {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&thermal 2>;
- sustainable-power = <5000>;
- trips {};
- cooling-maps {};
- };
-
- tzts3: tzts3 {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&thermal 3>;
- sustainable-power = <5000>;
- trips {};
- cooling-maps {};
- };
-
- tzts4: tzts4 {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&thermal 4>;
- sustainable-power = <5000>;
- trips {};
- cooling-maps {};
- };
-
- tzts5: tzts5 {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&thermal 5>;
- sustainable-power = <5000>;
- trips {};
- cooling-maps {};
- };
-
- tztsABB: tztsABB {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&thermal 6>;
- sustainable-power = <5000>;
- trips {};
- cooling-maps {};
- };
- };
-
pwm0: pwm@1100e000 {
compatible = "mediatek,mt8183-disp-pwm";
reg = <0 0x1100e000 0 0x1000>;
@@ -2105,4 +1984,125 @@
power-domains = <&spm MT8183_POWER_DOMAIN_CAM>;
};
};
+
+ thermal_zones: thermal-zones {
+ cpu_thermal: cpu-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <500>;
+ thermal-sensors = <&thermal 0>;
+ sustainable-power = <5000>;
+
+ trips {
+ threshold: trip-point0 {
+ temperature = <68000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ target: trip-point1 {
+ temperature = <80000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_crit: cpu-crit {
+ temperature = <115000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&target>;
+ cooling-device = <&cpu0
+ THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>,
+ <&cpu1
+ THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>,
+ <&cpu2
+ THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>,
+ <&cpu3
+ THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>;
+ contribution = <3072>;
+ };
+ map1 {
+ trip = <&target>;
+ cooling-device = <&cpu4
+ THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>,
+ <&cpu5
+ THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>,
+ <&cpu6
+ THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>,
+ <&cpu7
+ THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>;
+ contribution = <1024>;
+ };
+ };
+ };
+
+ /* The tzts1 ~ tzts6 don't need to polling */
+ /* The tzts1 ~ tzts6 don't need to thermal throttle */
+
+ tzts1: tzts1 {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&thermal 1>;
+ sustainable-power = <5000>;
+ trips {};
+ cooling-maps {};
+ };
+
+ tzts2: tzts2 {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&thermal 2>;
+ sustainable-power = <5000>;
+ trips {};
+ cooling-maps {};
+ };
+
+ tzts3: tzts3 {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&thermal 3>;
+ sustainable-power = <5000>;
+ trips {};
+ cooling-maps {};
+ };
+
+ tzts4: tzts4 {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&thermal 4>;
+ sustainable-power = <5000>;
+ trips {};
+ cooling-maps {};
+ };
+
+ tzts5: tzts5 {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&thermal 5>;
+ sustainable-power = <5000>;
+ trips {};
+ cooling-maps {};
+ };
+
+ tztsABB: tztsABB {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&thermal 6>;
+ sustainable-power = <5000>;
+ trips {};
+ cooling-maps {};
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8186.dtsi b/arch/arm64/boot/dts/mediatek/mt8186.dtsi
index f04ae70c470a..df0c04f2ba1d 100644
--- a/arch/arm64/boot/dts/mediatek/mt8186.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8186.dtsi
@@ -924,7 +924,8 @@
reg = <MT8186_POWER_DOMAIN_CSIRX_TOP>;
clocks = <&topckgen CLK_TOP_SENINF>,
<&topckgen CLK_TOP_SENINF1>;
- clock-names = "csirx_top0", "csirx_top1";
+ clock-names = "subsys-csirx-top0",
+ "subsys-csirx-top1";
#power-domain-cells = <0>;
};
@@ -942,7 +943,8 @@
reg = <MT8186_POWER_DOMAIN_ADSP_AO>;
clocks = <&topckgen CLK_TOP_AUDIODSP>,
<&topckgen CLK_TOP_ADSP_BUS>;
- clock-names = "audioadsp", "adsp_bus";
+ clock-names = "audioadsp",
+ "subsys-adsp-bus";
#address-cells = <1>;
#size-cells = <0>;
#power-domain-cells = <1>;
@@ -975,8 +977,11 @@
<&mmsys CLK_MM_SMI_COMMON>,
<&mmsys CLK_MM_SMI_GALS>,
<&mmsys CLK_MM_SMI_IOMMU>;
- clock-names = "disp", "mdp", "smi_infra", "smi_common",
- "smi_gals", "smi_iommu";
+ clock-names = "disp", "mdp",
+ "subsys-smi-infra",
+ "subsys-smi-common",
+ "subsys-smi-gals",
+ "subsys-smi-iommu";
mediatek,infracfg = <&infracfg_ao>;
#address-cells = <1>;
#size-cells = <0>;
@@ -993,15 +998,17 @@
power-domain@MT8186_POWER_DOMAIN_CAM {
reg = <MT8186_POWER_DOMAIN_CAM>;
- clocks = <&topckgen CLK_TOP_CAM>,
- <&topckgen CLK_TOP_SENINF>,
+ clocks = <&topckgen CLK_TOP_SENINF>,
<&topckgen CLK_TOP_SENINF1>,
<&topckgen CLK_TOP_SENINF2>,
<&topckgen CLK_TOP_SENINF3>,
+ <&camsys CLK_CAM2MM_GALS>,
<&topckgen CLK_TOP_CAMTM>,
- <&camsys CLK_CAM2MM_GALS>;
- clock-names = "cam-top", "cam0", "cam1", "cam2",
- "cam3", "cam-tm", "gals";
+ <&topckgen CLK_TOP_CAM>;
+ clock-names = "cam0", "cam1", "cam2",
+ "cam3", "gals",
+ "subsys-cam-tm",
+ "subsys-cam-top";
mediatek,infracfg = <&infracfg_ao>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1020,9 +1027,9 @@
power-domain@MT8186_POWER_DOMAIN_IMG {
reg = <MT8186_POWER_DOMAIN_IMG>;
- clocks = <&topckgen CLK_TOP_IMG1>,
- <&imgsys1 CLK_IMG1_GALS_IMG1>;
- clock-names = "img-top", "gals";
+ clocks = <&imgsys1 CLK_IMG1_GALS_IMG1>,
+ <&topckgen CLK_TOP_IMG1>;
+ clock-names = "gals", "subsys-img-top";
mediatek,infracfg = <&infracfg_ao>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1041,8 +1048,11 @@
<&ipesys CLK_IPE_LARB20>,
<&ipesys CLK_IPE_SMI_SUBCOM>,
<&ipesys CLK_IPE_GALS_IPE>;
- clock-names = "ipe-top", "ipe-larb0", "ipe-larb1",
- "ipe-smi", "ipe-gals";
+ clock-names = "subsys-ipe-top",
+ "subsys-ipe-larb0",
+ "subsys-ipe-larb1",
+ "subsys-ipe-smi",
+ "subsys-ipe-gals";
mediatek,infracfg = <&infracfg_ao>;
#power-domain-cells = <0>;
};
@@ -1061,7 +1071,9 @@
clocks = <&topckgen CLK_TOP_WPE>,
<&wpesys CLK_WPE_SMI_LARB8_CK_EN>,
<&wpesys CLK_WPE_SMI_LARB8_PCLK_EN>;
- clock-names = "wpe0", "larb-ck", "larb-pclk";
+ clock-names = "wpe0",
+ "subsys-larb-ck",
+ "subsys-larb-pclk";
mediatek,infracfg = <&infracfg_ao>;
#power-domain-cells = <0>;
};
@@ -1656,7 +1668,7 @@
#address-cells = <1>;
#size-cells = <1>;
- gpu_speedbin: gpu-speed-bin@59c {
+ gpu_speedbin: gpu-speedbin@59c {
reg = <0x59c 0x4>;
bits = <0 3>;
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-audio-rt1015p-rt5682.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada-audio-rt1015p-rt5682.dtsi
deleted file mode 100644
index f521f50d448f..000000000000
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-audio-rt1015p-rt5682.dtsi
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 OR MIT)
-/*
- * Copyright 2020 Google LLC
- */
-
-#include "mt8192-asurada-audio-rt5682.dtsi"
-#include "mt8192-asurada-audio-rt1015p.dtsi"
-
-&sound {
- compatible = "mediatek,mt8192_mt6359_rt1015p_rt5682";
-
- speaker-codecs {
- sound-dai = <&rt1015p>;
- };
-
- headset-codec {
- sound-dai = <&rt5682 0>;
- };
-};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-audio-rt1015p.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada-audio-rt1015p.dtsi
deleted file mode 100644
index e5743789934e..000000000000
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-audio-rt1015p.dtsi
+++ /dev/null
@@ -1,26 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 OR MIT)
-/*
- * Copyright (C) 2022 MediaTek Inc.
- */
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/mt8192-pinfunc.h>
-
-/ {
- rt1015p: audio-codec {
- compatible = "realtek,rt1015p";
- pinctrl-names = "default";
- pinctrl-0 = <&rt1015p_pins>;
- sdb-gpios = <&pio 147 GPIO_ACTIVE_HIGH>;
- #sound-dai-cells = <0>;
- };
-};
-
-&pio {
- rt1015p_pins: rt1015p-default-pins {
- pins {
- pinmux = <PINMUX_GPIO147__FUNC_GPIO147>;
- output-low;
- };
- };
-};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-audio-rt5682.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada-audio-rt5682.dtsi
deleted file mode 100644
index 05e48b870a92..000000000000
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-audio-rt5682.dtsi
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 OR MIT)
-/*
- * Copyright (C) 2022 MediaTek Inc.
- */
-
-&i2c1 {
- rt5682: audio-codec@1a {
- compatible = "realtek,rt5682i";
- reg = <0x1a>;
- interrupts-extended = <&pio 18 IRQ_TYPE_LEVEL_LOW>;
- realtek,jd-src = <1>;
- realtek,btndet-delay = <16>;
- #sound-dai-cells = <1>;
-
- AVDD-supply = <&mt6359_vio18_ldo_reg>;
- DBVDD-supply = <&mt6359_vio18_ldo_reg>;
- LDO1-IN-supply = <&mt6359_vio18_ldo_reg>;
- MICVDD-supply = <&pp3300_g>;
- VBAT-supply = <&pp3300_ldo_z>;
- };
-};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts b/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts
index 6e23428a3ed2..fd2cb8765a15 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts
@@ -4,7 +4,6 @@
*/
/dts-v1/;
#include "mt8192-asurada.dtsi"
-#include "mt8192-asurada-audio-rt1015p-rt5682.dtsi"
/ {
model = "Google Hayato rev1";
@@ -101,6 +100,24 @@
};
};
+&rt5682 {
+ compatible = "realtek,rt5682i";
+ realtek,btndet-delay = <16>;
+ VBAT-supply = <&pp3300_ldo_z>;
+};
+
+&sound {
+ compatible = "mediatek,mt8192_mt6359_rt1015p_rt5682";
+
+ speaker-codecs {
+ sound-dai = <&rt1015p>;
+ };
+
+ headset-codec {
+ sound-dai = <&rt5682 0>;
+ };
+};
+
&touchscreen {
compatible = "hid-over-i2c";
post-power-on-delay-ms = <10>;
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r5-sku2.dts b/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r5-sku2.dts
new file mode 100644
index 000000000000..3127ee5f6172
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r5-sku2.dts
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2022 Google LLC
+ */
+/dts-v1/;
+#include "mt8192-asurada.dtsi"
+
+/ {
+ model = "Google Hayato rev5";
+ compatible = "google,hayato-rev5-sku2", "google,hayato-sku2",
+ "google,hayato", "mediatek,mt8192";
+};
+
+&keyboard_controller {
+ function-row-physmap = <
+ MATRIX_KEY(0x00, 0x02, 0) /* T1 */
+ MATRIX_KEY(0x03, 0x02, 0) /* T2 */
+ MATRIX_KEY(0x02, 0x02, 0) /* T3 */
+ MATRIX_KEY(0x01, 0x02, 0) /* T4 */
+ MATRIX_KEY(0x03, 0x04, 0) /* T5 */
+ MATRIX_KEY(0x02, 0x04, 0) /* T6 */
+ MATRIX_KEY(0x01, 0x04, 0) /* T7 */
+ MATRIX_KEY(0x02, 0x09, 0) /* T8 */
+ MATRIX_KEY(0x01, 0x09, 0) /* T9 */
+ MATRIX_KEY(0x00, 0x04, 0) /* T10 */
+ >;
+ linux,keymap = <
+ MATRIX_KEY(0x00, 0x02, KEY_BACK)
+ MATRIX_KEY(0x03, 0x02, KEY_FORWARD)
+ MATRIX_KEY(0x02, 0x02, KEY_REFRESH)
+ MATRIX_KEY(0x01, 0x02, KEY_FULL_SCREEN)
+ MATRIX_KEY(0x03, 0x04, KEY_SCALE)
+ MATRIX_KEY(0x02, 0x04, KEY_BRIGHTNESSDOWN)
+ MATRIX_KEY(0x01, 0x04, KEY_BRIGHTNESSUP)
+ MATRIX_KEY(0x02, 0x09, KEY_MUTE)
+ MATRIX_KEY(0x01, 0x09, KEY_VOLUMEDOWN)
+ MATRIX_KEY(0x00, 0x04, KEY_VOLUMEUP)
+
+ CROS_STD_MAIN_KEYMAP
+ >;
+};
+
+&rt5682 {
+ compatible = "realtek,rt5682s";
+};
+
+&sound {
+ compatible = "mediatek,mt8192_mt6359_rt1015p_rt5682s";
+
+ speaker-codecs {
+ sound-dai = <&rt1015p>;
+ };
+
+ headset-codec {
+ sound-dai = <&rt5682 0>;
+ };
+};
+
+&touchscreen {
+ compatible = "hid-over-i2c";
+ post-power-on-delay-ms = <10>;
+ hid-descr-addr = <0x0001>;
+ vdd-supply = <&pp3300_u>;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
index c6ad10cec95e..bc88866ab2f5 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
@@ -4,7 +4,6 @@
*/
/dts-v1/;
#include "mt8192-asurada.dtsi"
-#include "mt8192-asurada-audio-rt1015p-rt5682.dtsi"
#include <dt-bindings/leds/common.h>
/ {
@@ -58,6 +57,24 @@
>;
};
+&rt5682 {
+ compatible = "realtek,rt5682i";
+ realtek,btndet-delay = <16>;
+ VBAT-supply = <&pp3300_ldo_z>;
+};
+
+&sound {
+ compatible = "mediatek,mt8192_mt6359_rt1015p_rt5682";
+
+ speaker-codecs {
+ sound-dai = <&rt1015p>;
+ };
+
+ headset-codec {
+ sound-dai = <&rt5682 0>;
+ };
+};
+
&touchscreen {
compatible = "elan,ekth3500";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r4.dts b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r4.dts
new file mode 100644
index 000000000000..0039158c9e60
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r4.dts
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2022 Google LLC
+ */
+/dts-v1/;
+#include "mt8192-asurada.dtsi"
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "Google Spherion (rev4)";
+ compatible = "google,spherion-rev4", "google,spherion",
+ "mediatek,mt8192";
+
+ pwmleds {
+ compatible = "pwm-leds";
+
+ led {
+ function = LED_FUNCTION_KBD_BACKLIGHT;
+ color = <LED_COLOR_ID_WHITE>;
+ pwms = <&cros_ec_pwm 0>;
+ max-brightness = <1023>;
+ };
+ };
+};
+
+&cros_ec_pwm {
+ status = "okay";
+};
+
+&keyboard_controller {
+ function-row-physmap = <
+ MATRIX_KEY(0x00, 0x02, 0) /* T1 */
+ MATRIX_KEY(0x03, 0x02, 0) /* T2 */
+ MATRIX_KEY(0x02, 0x02, 0) /* T3 */
+ MATRIX_KEY(0x01, 0x02, 0) /* T4 */
+ MATRIX_KEY(0x03, 0x04, 0) /* T5 */
+ MATRIX_KEY(0x02, 0x04, 0) /* T6 */
+ MATRIX_KEY(0x01, 0x04, 0) /* T7 */
+ MATRIX_KEY(0x02, 0x09, 0) /* T8 */
+ MATRIX_KEY(0x01, 0x09, 0) /* T9 */
+ MATRIX_KEY(0x00, 0x04, 0) /* T10 */
+ >;
+ linux,keymap = <
+ MATRIX_KEY(0x00, 0x02, KEY_BACK)
+ MATRIX_KEY(0x03, 0x02, KEY_REFRESH)
+ MATRIX_KEY(0x02, 0x02, KEY_FULL_SCREEN)
+ MATRIX_KEY(0x01, 0x02, KEY_SCALE)
+ MATRIX_KEY(0x03, 0x04, KEY_SYSRQ)
+ MATRIX_KEY(0x02, 0x04, KEY_BRIGHTNESSDOWN)
+ MATRIX_KEY(0x01, 0x04, KEY_BRIGHTNESSUP)
+ MATRIX_KEY(0x02, 0x09, KEY_MUTE)
+ MATRIX_KEY(0x01, 0x09, KEY_VOLUMEDOWN)
+ MATRIX_KEY(0x00, 0x04, KEY_VOLUMEUP)
+
+ CROS_STD_MAIN_KEYMAP
+ >;
+};
+
+&rt5682 {
+ compatible = "realtek,rt5682s";
+};
+
+&sound {
+ compatible = "mediatek,mt8192_mt6359_rt1015p_rt5682s";
+
+ speaker-codecs {
+ sound-dai = <&rt1015p>;
+ };
+
+ headset-codec {
+ sound-dai = <&rt5682 0>;
+ };
+};
+
+&touchscreen {
+ compatible = "elan,ekth3500";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
index 0e8b34117090..f2281250ac35 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
@@ -210,6 +210,14 @@
};
};
+ rt1015p: audio-codec {
+ compatible = "realtek,rt1015p";
+ pinctrl-names = "default";
+ pinctrl-0 = <&rt1015p_pins>;
+ sdb-gpios = <&pio 147 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ };
+
sound: sound {
mediatek,platform = <&afe>;
pinctrl-names = "aud_clk_mosi_off",
@@ -305,6 +313,19 @@
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
+
+ rt5682: audio-codec@1a {
+ /* Realtek RT5682i or RT5682s, sharing the same configuration */
+ reg = <0x1a>;
+ interrupts-extended = <&pio 18 IRQ_TYPE_LEVEL_LOW>;
+ realtek,jd-src = <1>;
+ #sound-dai-cells = <1>;
+
+ AVDD-supply = <&mt6359_vio18_ldo_reg>;
+ DBVDD-supply = <&mt6359_vio18_ldo_reg>;
+ LDO1-IN-supply = <&mt6359_vio18_ldo_reg>;
+ MICVDD-supply = <&pp3300_g>;
+ };
};
&i2c2 {
@@ -1184,6 +1205,13 @@
};
};
+ rt1015p_pins: rt1015p-default-pins {
+ pins {
+ pinmux = <PINMUX_GPIO147__FUNC_GPIO147>;
+ output-low;
+ };
+ };
+
scp_pins: scp-pins {
pins-vreq-vao {
pinmux = <PINMUX_GPIO195__FUNC_SCP_VREQ_VAO>;
@@ -1284,7 +1312,7 @@
pinctrl-names = "default";
pinctrl-0 = <&scp_pins>;
- cros-ec {
+ cros-ec-rpmsg {
compatible = "google,cros-ec-rpmsg";
mediatek,rpmsg-name = "cros-ec-rpmsg";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
index 37a3e9de90ff..5a7cab489ff3 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
@@ -47,6 +47,19 @@
reg = <0 0x40000000 0 0x80000000>;
};
+ pp3300_disp_x: regulator-pp3300-disp-x {
+ compatible = "regulator-fixed";
+ regulator-name = "pp3300_disp_x";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <2500>;
+ enable-active-high;
+ gpio = <&pio 55 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&panel_fixed_pins>;
+ vin-supply = <&pp3300_z2>;
+ };
+
/* system wide LDO 3.3V power rail */
pp3300_z5: regulator-pp3300-ldo-z5 {
compatible = "regulator-fixed";
@@ -217,6 +230,20 @@
reg = <1>;
edp_out: endpoint {
data-lanes = <0 1 2 3>;
+ remote-endpoint = <&panel_in>;
+ };
+ };
+ };
+
+ aux-bus {
+ panel {
+ compatible = "edp-panel";
+ power-supply = <&pp3300_disp_x>;
+ backlight = <&backlight_lcd0>;
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&edp_out>;
+ };
};
};
};
@@ -362,7 +389,7 @@
pinctrl-0 = <&i2c7_pins>;
pmic@34 {
- #interrupt-cells = <1>;
+ #interrupt-cells = <2>;
compatible = "mediatek,mt6360";
reg = <0x34>;
interrupt-controller;
@@ -881,6 +908,12 @@
};
};
+ panel_fixed_pins: panel-pwr-default-pins {
+ pins-vreg-en {
+ pinmux = <PINMUX_GPIO55__FUNC_GPIO55>;
+ };
+ };
+
pio_default: pio-default-pins {
pins-wifi-enable {
pinmux = <PINMUX_GPIO58__FUNC_GPIO58>;
diff --git a/arch/arm64/boot/dts/mediatek/mt8195-demo.dts b/arch/arm64/boot/dts/mediatek/mt8195-demo.dts
index b2485ddfd33b..69c7f3954ae5 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195-demo.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8195-demo.dts
@@ -48,7 +48,7 @@
memory@40000000 {
device_type = "memory";
- reg = <0 0x40000000 0 0x80000000>;
+ reg = <0 0x40000000 0x2 0x00000000>;
};
reserved-memory {
@@ -56,13 +56,8 @@
#size-cells = <2>;
ranges;
- /* 2 MiB reserved for ARM Trusted Firmware (BL31) */
- bl31_secmon_reserved: secmon@54600000 {
- no-map;
- reg = <0 0x54600000 0x0 0x200000>;
- };
-
- /* 12 MiB reserved for OP-TEE (BL32)
+ /*
+ * 12 MiB reserved for OP-TEE (BL32)
* +-----------------------+ 0x43e0_0000
* | SHMEM 2MiB |
* +-----------------------+ 0x43c0_0000
@@ -75,11 +70,39 @@
no-map;
reg = <0 0x43200000 0 0x00c00000>;
};
+
+ scp_mem: memory@50000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x50000000 0 0x2900000>;
+ no-map;
+ };
+
+ vpu_mem: memory@53000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x53000000 0 0x1400000>; /* 20 MB */
+ };
+
+ /* 2 MiB reserved for ARM Trusted Firmware (BL31) */
+ bl31_secmon_mem: memory@54600000 {
+ no-map;
+ reg = <0 0x54600000 0x0 0x200000>;
+ };
+
+ snd_dma_mem: memory@60000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x60000000 0 0x1100000>;
+ no-map;
+ };
+
+ apu_mem: memory@62000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x62000000 0 0x1400000>; /* 20 MB */
+ };
};
};
&eth {
- phy-mode ="rgmii-id";
+ phy-mode = "rgmii-id";
phy-handle = <&ethernet_phy0>;
snps,reset-gpio = <&pio 93 GPIO_ACTIVE_HIGH>;
snps,reset-delays-us = <0 10000 80000>;
diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
index a9e52b50c8c4..e0ac2e9f5b72 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
@@ -313,6 +313,7 @@
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH 0>;
cpus = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>,
<&cpu4>, <&cpu5>, <&cpu6>, <&cpu7>;
+ status = "fail";
};
dmic_codec: dmic-codec {
@@ -626,6 +627,8 @@
power-domain@MT8195_POWER_DOMAIN_VENC_CORE1 {
reg = <MT8195_POWER_DOMAIN_VENC_CORE1>;
+ clocks = <&vencsys_core1 CLK_VENC_CORE1_LARB>;
+ clock-names = "venc1-larb";
mediatek,infracfg = <&infracfg_ao>;
#power-domain-cells = <0>;
};
@@ -688,6 +691,8 @@
power-domain@MT8195_POWER_DOMAIN_VENC {
reg = <MT8195_POWER_DOMAIN_VENC>;
+ clocks = <&vencsys CLK_VENC_LARB>;
+ clock-names = "venc0-larb";
mediatek,infracfg = <&infracfg_ao>;
#power-domain-cells = <0>;
};
@@ -2664,7 +2669,7 @@
reg = <0 0x1b010000 0 0x1000>;
mediatek,larb-id = <20>;
mediatek,smi = <&smi_common_vpp>;
- clocks = <&vencsys_core1 CLK_VENC_CORE1_LARB>,
+ clocks = <&vencsys_core1 CLK_VENC_CORE1_VENC>,
<&vencsys_core1 CLK_VENC_CORE1_GALS>,
<&vppsys0 CLK_VPP0_GALS_VDO0_VDO1_VENCSYS_CORE1>;
clock-names = "apb", "smi", "gals";
diff --git a/arch/arm64/boot/dts/mediatek/mt8365.dtsi b/arch/arm64/boot/dts/mediatek/mt8365.dtsi
index 413496c92069..24581f7410aa 100644
--- a/arch/arm64/boot/dts/mediatek/mt8365.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8365.dtsi
@@ -9,6 +9,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/power/mediatek,mt8365-power.h>
/ {
compatible = "mediatek,mt8365";
@@ -298,6 +299,119 @@
reg = <0 0x10005000 0 0x1000>;
};
+ scpsys: syscon@10006000 {
+ compatible = "mediatek,mt8365-syscfg", "syscon", "simple-mfd";
+ reg = <0 0x10006000 0 0x1000>;
+ #power-domain-cells = <1>;
+
+ /* System Power Manager */
+ spm: power-controller {
+ compatible = "mediatek,mt8365-power-controller";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ /* power domains of the SoC */
+ power-domain@MT8365_POWER_DOMAIN_MM {
+ reg = <MT8365_POWER_DOMAIN_MM>;
+ clocks = <&topckgen CLK_TOP_MM_SEL>,
+ <&mmsys CLK_MM_MM_SMI_COMMON>,
+ <&mmsys CLK_MM_MM_SMI_COMM0>,
+ <&mmsys CLK_MM_MM_SMI_COMM1>,
+ <&mmsys CLK_MM_MM_SMI_LARB0>;
+ clock-names = "mm", "mm-0", "mm-1",
+ "mm-2", "mm-3";
+ #power-domain-cells = <0>;
+ mediatek,infracfg = <&infracfg>;
+ mediatek,infracfg-nao = <&infracfg_nao>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-domain@MT8365_POWER_DOMAIN_CAM {
+ reg = <MT8365_POWER_DOMAIN_CAM>;
+ clocks = <&camsys CLK_CAM_LARB2>,
+ <&camsys CLK_CAM_SENIF>,
+ <&camsys CLK_CAMSV0>,
+ <&camsys CLK_CAMSV1>,
+ <&camsys CLK_CAM_FDVT>,
+ <&camsys CLK_CAM_WPE>;
+ clock-names = "cam-0", "cam-1",
+ "cam-2", "cam-3",
+ "cam-4", "cam-5";
+ #power-domain-cells = <0>;
+ mediatek,infracfg = <&infracfg>;
+ mediatek,smi = <&smi_common>;
+ };
+
+ power-domain@MT8365_POWER_DOMAIN_VDEC {
+ reg = <MT8365_POWER_DOMAIN_VDEC>;
+ #power-domain-cells = <0>;
+ mediatek,smi = <&smi_common>;
+ };
+
+ power-domain@MT8365_POWER_DOMAIN_VENC {
+ reg = <MT8365_POWER_DOMAIN_VENC>;
+ #power-domain-cells = <0>;
+ mediatek,smi = <&smi_common>;
+ };
+
+ power-domain@MT8365_POWER_DOMAIN_APU {
+ reg = <MT8365_POWER_DOMAIN_APU>;
+ clocks = <&infracfg CLK_IFR_APU_AXI>,
+ <&apu CLK_APU_IPU_CK>,
+ <&apu CLK_APU_AXI>,
+ <&apu CLK_APU_JTAG>,
+ <&apu CLK_APU_IF_CK>,
+ <&apu CLK_APU_EDMA>,
+ <&apu CLK_APU_AHB>;
+ clock-names = "apu", "apu-0",
+ "apu-1", "apu-2",
+ "apu-3", "apu-4",
+ "apu-5";
+ #power-domain-cells = <0>;
+ mediatek,infracfg = <&infracfg>;
+ mediatek,smi = <&smi_common>;
+ };
+ };
+
+ power-domain@MT8365_POWER_DOMAIN_CONN {
+ reg = <MT8365_POWER_DOMAIN_CONN>;
+ clocks = <&topckgen CLK_TOP_CONN_32K>,
+ <&topckgen CLK_TOP_CONN_26M>;
+ clock-names = "conn", "conn1";
+ #power-domain-cells = <0>;
+ mediatek,infracfg = <&infracfg>;
+ };
+
+ power-domain@MT8365_POWER_DOMAIN_MFG {
+ reg = <MT8365_POWER_DOMAIN_MFG>;
+ clocks = <&topckgen CLK_TOP_MFG_SEL>;
+ clock-names = "mfg";
+ #power-domain-cells = <0>;
+ mediatek,infracfg = <&infracfg>;
+ };
+
+ power-domain@MT8365_POWER_DOMAIN_AUDIO {
+ reg = <MT8365_POWER_DOMAIN_AUDIO>;
+ clocks = <&topckgen CLK_TOP_AUD_INTBUS_SEL>,
+ <&infracfg CLK_IFR_AUDIO>,
+ <&infracfg CLK_IFR_AUD_26M_BK>;
+ clock-names = "audio", "audio1", "audio2";
+ #power-domain-cells = <0>;
+ mediatek,infracfg = <&infracfg>;
+ };
+
+ power-domain@MT8365_POWER_DOMAIN_DSP {
+ reg = <MT8365_POWER_DOMAIN_DSP>;
+ clocks = <&topckgen CLK_TOP_DSP_SEL>,
+ <&topckgen CLK_TOP_DSP_26M>;
+ clock-names = "dsp", "dsp1";
+ #power-domain-cells = <0>;
+ mediatek,infracfg = <&infracfg>;
+ };
+ };
+ };
+
watchdog: watchdog@10007000 {
compatible = "mediatek,mt8365-wdt", "mediatek,mt6589-wdt";
reg = <0 0x10007000 0 0x100>;
@@ -357,6 +471,14 @@
reg = <0 0x10200a80 0 0x20>;
};
+ iommu: iommu@10205000 {
+ compatible = "mediatek,mt8365-m4u";
+ reg = <0 0x10205000 0 0x1000>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_LOW>;
+ mediatek,larbs = <&larb0>, <&larb1>, <&larb2>, <&larb3>;
+ #iommu-cells = <1>;
+ };
+
infracfg_nao: infracfg@1020e000 {
compatible = "mediatek,mt8365-infracfg", "syscon";
reg = <0 0x1020e000 0 0x1000>;
@@ -603,6 +725,94 @@
#phy-cells = <1>;
};
};
+
+ mmsys: syscon@14000000 {
+ compatible = "mediatek,mt8365-mmsys", "syscon";
+ reg = <0 0x14000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ smi_common: smi@14002000 {
+ compatible = "mediatek,mt8365-smi-common";
+ reg = <0 0x14002000 0 0x1000>;
+ clocks = <&mmsys CLK_MM_MM_SMI_COMMON>,
+ <&mmsys CLK_MM_MM_SMI_COMMON>,
+ <&mmsys CLK_MM_MM_SMI_COMM0>,
+ <&mmsys CLK_MM_MM_SMI_COMM1>;
+ clock-names = "apb", "smi", "gals0", "gals1";
+ power-domains = <&spm MT8365_POWER_DOMAIN_MM>;
+ };
+
+ larb0: larb@14003000 {
+ compatible = "mediatek,mt8365-smi-larb",
+ "mediatek,mt8186-smi-larb";
+ reg = <0 0x14003000 0 0x1000>;
+ mediatek,smi = <&smi_common>;
+ clocks = <&mmsys CLK_MM_MM_SMI_LARB0>,
+ <&mmsys CLK_MM_MM_SMI_LARB0>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8365_POWER_DOMAIN_MM>;
+ mediatek,larb-id = <0>;
+ };
+
+ camsys: syscon@15000000 {
+ compatible = "mediatek,mt8365-imgsys", "syscon";
+ reg = <0 0x15000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ larb2: larb@15001000 {
+ compatible = "mediatek,mt8365-smi-larb",
+ "mediatek,mt8186-smi-larb";
+ reg = <0 0x15001000 0 0x1000>;
+ mediatek,smi = <&smi_common>;
+ clocks = <&mmsys CLK_MM_MM_SMI_IMG>,
+ <&camsys CLK_CAM_LARB2>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8365_POWER_DOMAIN_CAM>;
+ mediatek,larb-id = <2>;
+ };
+
+ vdecsys: syscon@16000000 {
+ compatible = "mediatek,mt8365-vdecsys", "syscon";
+ reg = <0 0x16000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ larb3: larb@16010000 {
+ compatible = "mediatek,mt8365-smi-larb",
+ "mediatek,mt8186-smi-larb";
+ reg = <0 0x16010000 0 0x1000>;
+ mediatek,smi = <&smi_common>;
+ clocks = <&vdecsys CLK_VDEC_LARB1>,
+ <&vdecsys CLK_VDEC_LARB1>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8365_POWER_DOMAIN_VDEC>;
+ mediatek,larb-id = <3>;
+ };
+
+ vencsys: syscon@17000000 {
+ compatible = "mediatek,mt8365-vencsys", "syscon";
+ reg = <0 0x17000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ larb1: larb@17010000 {
+ compatible = "mediatek,mt8365-smi-larb",
+ "mediatek,mt8186-smi-larb";
+ reg = <0 0x17010000 0 0x1000>;
+ mediatek,smi = <&smi_common>;
+ clocks = <&vencsys CLK_VENC>, <&vencsys CLK_VENC>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8365_POWER_DOMAIN_VENC>;
+ mediatek,larb-id = <1>;
+ };
+
+ apu: syscon@19020000 {
+ compatible = "mediatek,mt8365-apu", "syscon";
+ reg = <0 0x19020000 0 0x1000>;
+ #clock-cells = <1>;
+ };
};
timer {
diff --git a/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts b/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts
new file mode 100644
index 000000000000..70b465f7c6a7
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts
@@ -0,0 +1,901 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2023 MediaTek Inc.
+ * Author: Ben Lok <ben.lok@mediatek.com>
+ * Macpaul Lin <macpaul.lin@mediatek.com>
+ */
+/dts-v1/;
+
+#include "mt8195.dtsi"
+#include "mt6359.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/mt8195-pinfunc.h>
+#include <dt-bindings/regulator/mediatek,mt6360-regulator.h>
+#include <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/usb/pd.h>
+
+/ {
+ model = "MediaTek Genio 1200 EVK-P1V2-EMMC";
+ compatible = "mediatek,mt8395-evk", "mediatek,mt8395",
+ "mediatek,mt8195";
+
+ aliases {
+ serial0 = &uart0;
+ ethernet0 = &eth;
+ };
+
+ chosen {
+ stdout-path = "serial0:921600n8";
+ };
+
+ firmware {
+ optee {
+ compatible = "linaro,optee-tz";
+ method = "smc";
+ };
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0 0x40000000 0x2 0x00000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /*
+ * 12 MiB reserved for OP-TEE (BL32)
+ * +-----------------------+ 0x43e0_0000
+ * | SHMEM 2MiB |
+ * +-----------------------+ 0x43c0_0000
+ * | | TA_RAM 8MiB |
+ * + TZDRAM +--------------+ 0x4340_0000
+ * | | TEE_RAM 2MiB |
+ * +-----------------------+ 0x4320_0000
+ */
+ optee_reserved: optee@43200000 {
+ no-map;
+ reg = <0 0x43200000 0 0x00c00000>;
+ };
+
+ scp_mem: memory@50000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x50000000 0 0x2900000>;
+ no-map;
+ };
+
+ vpu_mem: memory@53000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x53000000 0 0x1400000>; /* 20 MB */
+ };
+
+ /* 2 MiB reserved for ARM Trusted Firmware (BL31) */
+ bl31_secmon_mem: memory@54600000 {
+ no-map;
+ reg = <0 0x54600000 0x0 0x200000>;
+ };
+
+ snd_dma_mem: memory@60000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x60000000 0 0x1100000>;
+ no-map;
+ };
+
+ apu_mem: memory@62000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x62000000 0 0x1400000>; /* 20 MB */
+ };
+ };
+
+ backlight_lcd0: backlight-lcd0 {
+ compatible = "pwm-backlight";
+ pwms = <&disp_pwm0 0 500000>;
+ enable-gpios = <&pio 47 GPIO_ACTIVE_HIGH>;
+ brightness-levels = <0 1023>;
+ num-interpolated-steps = <1023>;
+ default-brightness-level = <576>;
+ };
+
+ backlight_lcd1: backlight-lcd1 {
+ compatible = "pwm-backlight";
+ pwms = <&disp_pwm1 0 500000>;
+ enable-gpios = <&pio 46 GPIO_ACTIVE_HIGH>;
+ brightness-levels = <0 1023>;
+ num-interpolated-steps = <1023>;
+ default-brightness-level = <576>;
+ };
+
+ can_clk: can-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <20000000>;
+ clock-output-names = "can-clk";
+ };
+
+ edp_panel_fixed_3v3: regulator-0 {
+ compatible = "regulator-fixed";
+ regulator-name = "edp_panel_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpio = <&pio 6 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&edp_panel_3v3_en_pins>;
+ };
+
+ edp_panel_fixed_12v: regulator-1 {
+ compatible = "regulator-fixed";
+ regulator-name = "edp_backlight_12v";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ enable-active-high;
+ gpio = <&pio 96 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&edp_panel_12v_en_pins>;
+ };
+
+ keys: gpio-keys {
+ compatible = "gpio-keys";
+
+ button-volume-up {
+ wakeup-source;
+ debounce-interval = <100>;
+ gpios = <&pio 106 GPIO_ACTIVE_LOW>;
+ label = "volume_up";
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+
+ wifi_fixed_3v3: regulator-2 {
+ compatible = "regulator-fixed";
+ regulator-name = "wifi_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pio 135 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+};
+
+&disp_pwm0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_default_pins>;
+ status = "okay";
+};
+
+&dmic_codec {
+ wakeup-delay-ms = <200>;
+};
+
+&eth {
+ phy-mode ="rgmii-rxid";
+ phy-handle = <&eth_phy0>;
+ snps,reset-gpio = <&pio 93 GPIO_ACTIVE_HIGH>;
+ snps,reset-delays-us = <0 10000 10000>;
+ mediatek,tx-delay-ps = <2030>;
+ mediatek,mac-wol;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&eth_default_pins>;
+ pinctrl-1 = <&eth_sleep_pins>;
+ status = "okay";
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ eth_phy0: eth-phy0@1 {
+ compatible = "ethernet-phy-id001c.c916";
+ reg = <0x1>;
+ };
+ };
+};
+
+&i2c0 {
+ clock-frequency = <400000>;
+ pinctrl-0 = <&i2c0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+ pinctrl-0 = <&i2c1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ touchscreen@5d {
+ compatible = "goodix,gt9271";
+ reg = <0x5d>;
+ interrupt-parent = <&pio>;
+ interrupts = <132 IRQ_TYPE_EDGE_RISING>;
+ irq-gpios = <&pio 132 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&pio 133 GPIO_ACTIVE_HIGH>;
+ AVDD28-supply = <&mt6360_ldo1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&touch_pins>;
+ };
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+ pinctrl-0 = <&i2c2_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&i2c6 {
+ clock-frequency = <400000>;
+ pinctrl-0 = <&i2c6_pins>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ mt6360: pmic@34 {
+ compatible = "mediatek,mt6360";
+ reg = <0x34>;
+ interrupts = <128 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-names = "IRQB";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ pinctrl-0 = <&mt6360_pins>;
+
+ charger {
+ compatible = "mediatek,mt6360-chg";
+ richtek,vinovp-microvolt = <14500000>;
+
+ otg_vbus_regulator: usb-otg-vbus-regulator {
+ regulator-name = "usb-otg-vbus";
+ regulator-min-microvolt = <4425000>;
+ regulator-max-microvolt = <5825000>;
+ };
+ };
+
+ regulator {
+ compatible = "mediatek,mt6360-regulator";
+ LDO_VIN3-supply = <&mt6360_buck2>;
+
+ mt6360_buck1: buck1 {
+ regulator-name = "emi_vdd2";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP
+ MT6360_OPMODE_ULP>;
+ regulator-always-on;
+ };
+
+ mt6360_buck2: buck2 {
+ regulator-name = "emi_vddq";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP
+ MT6360_OPMODE_ULP>;
+ regulator-always-on;
+ };
+
+ mt6360_ldo1: ldo1 {
+ regulator-name = "tp1_p3v0";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ regulator-always-on;
+ };
+
+ mt6360_ldo2: ldo2 {
+ regulator-name = "panel1_p1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+
+ mt6360_ldo3: ldo3 {
+ regulator-name = "vmc_pmu";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3600000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+
+ mt6360_ldo5: ldo5 {
+ regulator-name = "vmch_pmu";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3600000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+
+ /* This is a measure point, which name is mt6360_ldo1 on schematic */
+ mt6360_ldo6: ldo6 {
+ regulator-name = "mt6360_ldo1";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <2100000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+
+ mt6360_ldo7: ldo7 {
+ regulator-name = "emi_vmddr_en";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <2100000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&mfg0 {
+ domain-supply = <&mt6315_7_vbuck1>;
+};
+
+&mmc0 {
+ status = "okay";
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc0_default_pins>;
+ pinctrl-1 = <&mmc0_uhs_pins>;
+ bus-width = <8>;
+ max-frequency = <200000000>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ cap-mmc-hw-reset;
+ no-sdio;
+ no-sd;
+ hs400-ds-delay = <0x14c11>;
+ vmmc-supply = <&mt6359_vemc_1_ldo_reg>;
+ vqmmc-supply = <&mt6359_vufs_ldo_reg>;
+ non-removable;
+};
+
+&mmc1 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc1_default_pins>;
+ pinctrl-1 = <&mmc1_uhs_pins>;
+ bus-width = <4>;
+ max-frequency = <200000000>;
+ cap-sd-highspeed;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ no-mmc;
+ no-sdio;
+ vmmc-supply = <&mt6360_ldo5>;
+ vqmmc-supply = <&mt6360_ldo3>;
+ status = "okay";
+ non-removable;
+};
+
+&mt6359_vaud18_ldo_reg {
+ regulator-always-on;
+};
+
+&mt6359_vbbck_ldo_reg {
+ regulator-always-on;
+};
+
+/* For USB Hub */
+&mt6359_vcamio_ldo_reg {
+ regulator-always-on;
+};
+
+&mt6359_vcn33_2_bt_ldo_reg {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+};
+
+&mt6359_vcore_buck_reg {
+ regulator-always-on;
+};
+
+&mt6359_vgpu11_buck_reg {
+ regulator-always-on;
+};
+
+&mt6359_vpu_buck_reg {
+ regulator-always-on;
+};
+
+&mt6359_vrf12_ldo_reg {
+ regulator-always-on;
+};
+
+&mt6359codec {
+ mediatek,mic-type-0 = <1>; /* ACC */
+ mediatek,mic-type-1 = <3>; /* DCC */
+ mediatek,mic-type-2 = <1>; /* ACC */
+};
+
+&pcie0 {
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&pcie0_default_pins>;
+ pinctrl-1 = <&pcie0_idle_pins>;
+ status = "okay";
+};
+
+&pcie1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_default_pins>;
+ status = "disabled";
+};
+
+&pciephy {
+ status = "okay";
+};
+
+&pio {
+ audio_default_pins: audio-default-pins {
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO61__FUNC_DMIC1_CLK>,
+ <PINMUX_GPIO62__FUNC_DMIC1_DAT>,
+ <PINMUX_GPIO65__FUNC_PCM_DO>,
+ <PINMUX_GPIO66__FUNC_PCM_CLK>,
+ <PINMUX_GPIO67__FUNC_PCM_DI>,
+ <PINMUX_GPIO68__FUNC_PCM_SYNC>,
+ <PINMUX_GPIO69__FUNC_AUD_CLK_MOSI>,
+ <PINMUX_GPIO70__FUNC_AUD_SYNC_MOSI>,
+ <PINMUX_GPIO71__FUNC_AUD_DAT_MOSI0>,
+ <PINMUX_GPIO72__FUNC_AUD_DAT_MOSI1>,
+ <PINMUX_GPIO73__FUNC_AUD_DAT_MISO0>,
+ <PINMUX_GPIO74__FUNC_AUD_DAT_MISO1>,
+ <PINMUX_GPIO75__FUNC_AUD_DAT_MISO2>;
+ };
+ };
+
+ disp_pwm1_default_pins: disp-pwm1-default-pins {
+ pins1 {
+ pinmux = <PINMUX_GPIO104__FUNC_DISP_PWM1>;
+ };
+ };
+
+ edp_panel_12v_en_pins: edp-panel-12v-en-pins {
+ pins1 {
+ pinmux = <PINMUX_GPIO96__FUNC_GPIO96>;
+ output-high;
+ };
+ };
+
+ edp_panel_3v3_en_pins: edp-panel-3v3-en-pins {
+ pins1 {
+ pinmux = <PINMUX_GPIO6__FUNC_GPIO6>;
+ output-high;
+ };
+ };
+
+ eth_default_pins: eth-default-pins {
+ pins-cc {
+ pinmux = <PINMUX_GPIO85__FUNC_GBE_TXC>,
+ <PINMUX_GPIO86__FUNC_GBE_RXC>,
+ <PINMUX_GPIO87__FUNC_GBE_RXDV>,
+ <PINMUX_GPIO88__FUNC_GBE_TXEN>;
+ drive-strength = <MTK_DRIVE_8mA>;
+ };
+
+ pins-mdio {
+ pinmux = <PINMUX_GPIO89__FUNC_GBE_MDC>,
+ <PINMUX_GPIO90__FUNC_GBE_MDIO>;
+ input-enable;
+ };
+
+ pins-power {
+ pinmux = <PINMUX_GPIO91__FUNC_GPIO91>,
+ <PINMUX_GPIO92__FUNC_GPIO92>;
+ output-high;
+ };
+
+ pins-rxd {
+ pinmux = <PINMUX_GPIO81__FUNC_GBE_RXD3>,
+ <PINMUX_GPIO82__FUNC_GBE_RXD2>,
+ <PINMUX_GPIO83__FUNC_GBE_RXD1>,
+ <PINMUX_GPIO84__FUNC_GBE_RXD0>;
+ };
+
+ pins-txd {
+ pinmux = <PINMUX_GPIO77__FUNC_GBE_TXD3>,
+ <PINMUX_GPIO78__FUNC_GBE_TXD2>,
+ <PINMUX_GPIO79__FUNC_GBE_TXD1>,
+ <PINMUX_GPIO80__FUNC_GBE_TXD0>;
+ drive-strength = <MTK_DRIVE_8mA>;
+ };
+ };
+
+ eth_sleep_pins: eth-sleep-pins {
+ pins-cc {
+ pinmux = <PINMUX_GPIO85__FUNC_GPIO85>,
+ <PINMUX_GPIO86__FUNC_GPIO86>,
+ <PINMUX_GPIO87__FUNC_GPIO87>,
+ <PINMUX_GPIO88__FUNC_GPIO88>;
+ };
+
+ pins-mdio {
+ pinmux = <PINMUX_GPIO89__FUNC_GPIO89>,
+ <PINMUX_GPIO90__FUNC_GPIO90>;
+ input-disable;
+ bias-disable;
+ };
+
+ pins-rxd {
+ pinmux = <PINMUX_GPIO81__FUNC_GPIO81>,
+ <PINMUX_GPIO82__FUNC_GPIO82>,
+ <PINMUX_GPIO83__FUNC_GPIO83>,
+ <PINMUX_GPIO84__FUNC_GPIO84>;
+ };
+
+ pins-txd {
+ pinmux = <PINMUX_GPIO77__FUNC_GPIO77>,
+ <PINMUX_GPIO78__FUNC_GPIO78>,
+ <PINMUX_GPIO79__FUNC_GPIO79>,
+ <PINMUX_GPIO80__FUNC_GPIO80>;
+ };
+ };
+
+ gpio_key_pins: gpio-keys-pins {
+ pins {
+ pinmux = <PINMUX_GPIO106__FUNC_GPIO106>;
+ bias-pull-up;
+ input-enable;
+ };
+ };
+
+ i2c0_pins: i2c0-pins {
+ pins {
+ pinmux = <PINMUX_GPIO8__FUNC_SDA0>,
+ <PINMUX_GPIO9__FUNC_SCL0>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_111>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c1_pins: i2c1-pins {
+ pins {
+ pinmux = <PINMUX_GPIO10__FUNC_SDA1>,
+ <PINMUX_GPIO11__FUNC_SCL1>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_111>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c2_pins: i2c2-pins {
+ pins {
+ pinmux = <PINMUX_GPIO12__FUNC_SDA2>,
+ <PINMUX_GPIO13__FUNC_SCL2>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_111>;
+ drive-strength = <MTK_DRIVE_6mA>;
+ };
+ };
+
+ i2c6_pins: i2c6-pins {
+ pins {
+ pinmux = <PINMUX_GPIO25__FUNC_SDA6>,
+ <PINMUX_GPIO26__FUNC_SCL6>;
+ bias-pull-up;
+ };
+ };
+
+ mmc0_default_pins: mmc0-default-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO122__FUNC_MSDC0_CLK>;
+ drive-strength = <MTK_DRIVE_6mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO126__FUNC_MSDC0_DAT0>,
+ <PINMUX_GPIO125__FUNC_MSDC0_DAT1>,
+ <PINMUX_GPIO124__FUNC_MSDC0_DAT2>,
+ <PINMUX_GPIO123__FUNC_MSDC0_DAT3>,
+ <PINMUX_GPIO119__FUNC_MSDC0_DAT4>,
+ <PINMUX_GPIO118__FUNC_MSDC0_DAT5>,
+ <PINMUX_GPIO117__FUNC_MSDC0_DAT6>,
+ <PINMUX_GPIO116__FUNC_MSDC0_DAT7>,
+ <PINMUX_GPIO121__FUNC_MSDC0_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_6mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins-rst {
+ pinmux = <PINMUX_GPIO120__FUNC_MSDC0_RSTB>;
+ drive-strength = <MTK_DRIVE_6mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ mmc0_uhs_pins: mmc0-uhs-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO122__FUNC_MSDC0_CLK>;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO126__FUNC_MSDC0_DAT0>,
+ <PINMUX_GPIO125__FUNC_MSDC0_DAT1>,
+ <PINMUX_GPIO124__FUNC_MSDC0_DAT2>,
+ <PINMUX_GPIO123__FUNC_MSDC0_DAT3>,
+ <PINMUX_GPIO119__FUNC_MSDC0_DAT4>,
+ <PINMUX_GPIO118__FUNC_MSDC0_DAT5>,
+ <PINMUX_GPIO117__FUNC_MSDC0_DAT6>,
+ <PINMUX_GPIO116__FUNC_MSDC0_DAT7>,
+ <PINMUX_GPIO121__FUNC_MSDC0_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins-ds {
+ pinmux = <PINMUX_GPIO127__FUNC_MSDC0_DSL>;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-rst {
+ pinmux = <PINMUX_GPIO120__FUNC_MSDC0_RSTB>;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ mmc1_default_pins: mmc1-default-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO111__FUNC_MSDC1_CLK>;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO110__FUNC_MSDC1_CMD>,
+ <PINMUX_GPIO112__FUNC_MSDC1_DAT0>,
+ <PINMUX_GPIO113__FUNC_MSDC1_DAT1>,
+ <PINMUX_GPIO114__FUNC_MSDC1_DAT2>,
+ <PINMUX_GPIO115__FUNC_MSDC1_DAT3>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ mmc1_uhs_pins: mmc1-uhs-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO111__FUNC_MSDC1_CLK>;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO110__FUNC_MSDC1_CMD>,
+ <PINMUX_GPIO112__FUNC_MSDC1_DAT0>,
+ <PINMUX_GPIO113__FUNC_MSDC1_DAT1>,
+ <PINMUX_GPIO114__FUNC_MSDC1_DAT2>,
+ <PINMUX_GPIO115__FUNC_MSDC1_DAT3>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ mt6360_pins: mt6360-pins {
+ pins {
+ pinmux = <PINMUX_GPIO17__FUNC_GPIO17>,
+ <PINMUX_GPIO128__FUNC_GPIO128>;
+ input-enable;
+ bias-pull-up;
+ };
+ };
+
+ pcie0_default_pins: pcie0-default-pins {
+ pins {
+ pinmux = <PINMUX_GPIO19__FUNC_WAKEN>,
+ <PINMUX_GPIO20__FUNC_PERSTN>,
+ <PINMUX_GPIO21__FUNC_CLKREQN>;
+ bias-pull-up;
+ };
+ };
+
+ pcie0_idle_pins: pcie0-idle-pins {
+ pins {
+ pinmux = <PINMUX_GPIO20__FUNC_GPIO20>;
+ bias-disable;
+ output-low;
+ };
+ };
+
+ pcie1_default_pins: pcie1-default-pins {
+ pins {
+ pinmux = <PINMUX_GPIO22__FUNC_PERSTN_1>,
+ <PINMUX_GPIO23__FUNC_CLKREQN_1>,
+ <PINMUX_GPIO24__FUNC_WAKEN_1>;
+ bias-pull-up;
+ };
+ };
+
+ pwm0_default_pins: pwm0-default-pins {
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO97__FUNC_DISP_PWM0>;
+ };
+ };
+
+ spi1_pins: spi1-pins {
+ pins {
+ pinmux = <PINMUX_GPIO136__FUNC_SPIM1_CSB>,
+ <PINMUX_GPIO137__FUNC_SPIM1_CLK>,
+ <PINMUX_GPIO138__FUNC_SPIM1_MO>,
+ <PINMUX_GPIO139__FUNC_SPIM1_MI>;
+ bias-disable;
+ };
+ };
+
+ spi2_pins: spi-pins {
+ pins {
+ pinmux = <PINMUX_GPIO140__FUNC_SPIM2_CSB>,
+ <PINMUX_GPIO141__FUNC_SPIM2_CLK>,
+ <PINMUX_GPIO142__FUNC_SPIM2_MO>,
+ <PINMUX_GPIO143__FUNC_SPIM2_MI>;
+ bias-disable;
+ };
+ };
+
+ touch_pins: touch-pins {
+ pins-irq {
+ pinmux = <PINMUX_GPIO132__FUNC_GPIO132>;
+ input-enable;
+ bias-disable;
+ };
+
+ pins-reset {
+ pinmux = <PINMUX_GPIO133__FUNC_GPIO133>;
+ output-high;
+ };
+ };
+
+ uart0_pins: uart0-pins {
+ pins {
+ pinmux = <PINMUX_GPIO98__FUNC_UTXD0>,
+ <PINMUX_GPIO99__FUNC_URXD0>;
+ };
+ };
+
+ uart1_pins: uart1-pins {
+ pins {
+ pinmux = <PINMUX_GPIO100__FUNC_URTS1>,
+ <PINMUX_GPIO101__FUNC_UCTS1>,
+ <PINMUX_GPIO102__FUNC_UTXD1>,
+ <PINMUX_GPIO103__FUNC_URXD1>;
+ };
+ };
+};
+
+&pmic {
+ interrupt-parent = <&pio>;
+ interrupts = <222 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&scp {
+ memory-region = <&scp_mem>;
+ status = "okay";
+};
+
+&spi1 {
+ pinctrl-0 = <&spi1_pins>;
+ pinctrl-names = "default";
+ mediatek,pad-select = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+ cs-gpios = <&pio 64 GPIO_ACTIVE_LOW>;
+
+ can0: can@0 {
+ compatible = "microchip,mcp2518fd";
+ reg = <0>;
+ clocks = <&can_clk>;
+ spi-max-frequency = <20000000>;
+ interrupts-extended = <&pio 16 IRQ_TYPE_LEVEL_LOW>;
+ vdd-supply = <&mt6359_vcn33_2_bt_ldo_reg>;
+ xceiver-supply = <&mt6359_vcn33_2_bt_ldo_reg>;
+ };
+};
+
+&spi2 {
+ pinctrl-0 = <&spi2_pins>;
+ pinctrl-names = "default";
+ mediatek,pad-select = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+};
+
+&spmi {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ mt6315_6: pmic@6 {
+ compatible = "mediatek,mt6315-regulator";
+ reg = <0x6 SPMI_USID>;
+
+ regulators {
+ mt6315_6_vbuck1: vbuck1 {
+ regulator-compatible = "vbuck1";
+ regulator-name = "Vbcpu";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1193750>;
+ regulator-enable-ramp-delay = <256>;
+ regulator-allowed-modes = <0 1 2>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ mt6315_7: pmic@7 {
+ compatible = "mediatek,mt6315-regulator";
+ reg = <0x7 SPMI_USID>;
+
+ regulators {
+ mt6315_7_vbuck1: vbuck1 {
+ regulator-compatible = "vbuck1";
+ regulator-name = "Vgpu";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1193750>;
+ regulator-enable-ramp-delay = <256>;
+ regulator-allowed-modes = <0 1 2>;
+ };
+ };
+ };
+};
+
+&u3phy0 {
+ status = "okay";
+};
+
+&u3phy1 {
+ status = "okay";
+};
+
+&u3phy2 {
+ status = "okay";
+};
+
+&u3phy3 {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-0 = <&uart1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&ufsphy {
+ status = "disabled";
+};
+
+&xhci0 {
+ status = "okay";
+};
+
+&xhci1 {
+ vusb33-supply = <&mt6359_vusb_ldo_reg>;
+ status = "okay";
+};
+
+&xhci2 {
+ vusb33-supply = <&mt6359_vusb_ldo_reg>;
+ status = "okay";
+};
+
+&xhci3 {
+ vusb33-supply = <&mt6359_vusb_ldo_reg>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
index 8b78be8f4f9d..7e24a212c7e4 100644
--- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
@@ -93,6 +93,8 @@
resets = <&tegra_car 28>;
reset-names = "host1x";
+ iommus = <&mc TEGRA_SWGROUP_HC>;
+
#address-cells = <2>;
#size-cells = <2>;
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
index 53805555dd2d..9ebb7369256e 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
@@ -31,6 +31,33 @@
};
host1x@50000000 {
+ dsia: dsi@54300000 {
+ avdd-dsi-csi-supply = <&vdd_dsi_csi>;
+ status = "okay";
+
+ link2: panel@0 {
+ compatible = "jdi,lpm102a188a";
+ reg = <0>;
+ };
+ };
+
+ dsib: dsi@54400000 {
+ avdd-dsi-csi-supply = <&vdd_dsi_csi>;
+ nvidia,ganged-mode = <&dsia>;
+ status = "okay";
+
+ link1: panel@0 {
+ compatible = "jdi,lpm102a188a";
+ reg = <0>;
+ power-supply = <&pplcd_vdd>;
+ ddi-supply = <&pp1800_lcdio>;
+ enable-gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
+ link2 = <&link2>;
+ backlight = <&backlight>;
+ };
+ };
+
dpaux: dpaux@545c0000 {
status = "okay";
};
@@ -1651,6 +1678,37 @@
status = "okay";
};
+ backlight: backlight@2c {
+ compatible = "ti,lp8557";
+ reg = <0x2c>;
+ power-supply = <&pplcd_vdd>;
+ enable-supply = <&pp1800_lcdio>;
+ bl-name = "lp8557-backlight";
+ dev-ctrl = /bits/ 8 <0x01>;
+ init-brt = /bits/ 8 <0x80>;
+
+ /* Full scale current, 20mA */
+ rom-11h {
+ rom-addr = /bits/ 8 <0x11>;
+ rom-val = /bits/ 8 <0x05>;
+ };
+ /* Frequency = 4.9kHz, magic undocumented val */
+ rom-12h {
+ rom-addr = /bits/ 8 <0x12>;
+ rom-val = /bits/ 8 <0x29>;
+ };
+ /* Boost freq = 1MHz, BComp option = 1 */
+ rom-13h {
+ rom-addr = /bits/ 8 <0x13>;
+ rom-val = /bits/ 8 <0x03>;
+ };
+ /* 4V OV, 6 output LED string enabled */
+ rom-14h {
+ rom-addr = /bits/ 8 <0x14>;
+ rom-val = /bits/ 8 <0xbf>;
+ };
+ };
+
audio-codec@2d {
compatible = "realtek,rt5677";
reg = <0x2d>;
@@ -1932,4 +1990,12 @@
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
};
+
+ vdd_dsi_csi: regulator-vdd-dsi-csi {
+ compatible = "regulator-fixed";
+ regulator-name = "AVDD_DSI_CSI_1V2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ vin-supply = <&pp1200_avdd>;
+ };
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi
index 62c4fdad0b60..553fa4ba1cd4 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi
@@ -44,6 +44,39 @@
status = "okay";
};
+ i2c@c250000 {
+ power-sensor@41 {
+ compatible = "ti,ina3221";
+ reg = <0x41>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ input@0 {
+ reg = <0x0>;
+ label = "CVB_ATX_12V";
+ shunt-resistor-micro-ohms = <2000>;
+ };
+
+ input@1 {
+ reg = <0x1>;
+ label = "CVB_ATX_3V3";
+ shunt-resistor-micro-ohms = <2000>;
+ };
+
+ input@2 {
+ reg = <0x2>;
+ label = "CVB_ATX_5V";
+ shunt-resistor-micro-ohms = <2000>;
+ };
+ };
+
+ power-sensor@44 {
+ compatible = "ti,ina219";
+ reg = <0x44>;
+ shunt-resistor = <2000>;
+ };
+ };
+
rtc@c2a0000 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi
index 5e7797df50c2..db6ef711674a 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi
@@ -1987,5 +1987,58 @@
status = "okay";
};
};
+
+ i2c@c240000 {
+ status = "okay";
+
+ power-sensor@40 {
+ compatible = "ti,ina3221";
+ reg = <0x40>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ input@0 {
+ reg = <0x0>;
+ label = "VDD_GPU_SOC";
+ shunt-resistor-micro-ohms = <2000>;
+ };
+
+ input@1 {
+ reg = <0x1>;
+ label = "VDD_CPU_CV";
+ shunt-resistor-micro-ohms = <2000>;
+ };
+
+ input@2 {
+ reg = <0x2>;
+ label = "VIN_SYS_5V0";
+ shunt-resistor-micro-ohms = <2000>;
+ ti,summation-disable;
+ };
+ };
+
+ power-sensor@41 {
+ compatible = "ti,ina3221";
+ reg = <0x41>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ input@0 {
+ reg = <0x0>;
+ status = "disabled";
+ };
+
+ input@1 {
+ reg = <0x1>;
+ label = "VDDQ_VDD2_1V8AO";
+ shunt-resistor-micro-ohms = <2000>;
+ };
+
+ input@2 {
+ reg = <0x2>;
+ status = "disabled";
+ };
+ };
+ };
};
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts
index 4413a9b6da87..ea13c4a7027c 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts
@@ -30,6 +30,7 @@
};
serial@31d0000 {
+ current-speed = <115200>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi
index 5f592f1d81e2..59c14ded5e9f 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi
@@ -28,7 +28,7 @@
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
- spi-max-frequency = <136000000>;
+ spi-max-frequency = <102000000>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
};
@@ -42,7 +42,7 @@
mmc@3400000 {
status = "okay";
bus-width = <4>;
- cd-gpios = <&gpio TEGRA234_MAIN_GPIO(G, 7) GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio TEGRA234_MAIN_GPIO(G, 7) GPIO_ACTIVE_LOW>;
disable-wp;
};
@@ -55,6 +55,35 @@
avdd-usb-supply = <&vdd_3v3_ao>;
};
+ i2c@c240000 {
+ status = "okay";
+
+ power-sensor@40 {
+ compatible = "ti,ina3221";
+ reg = <0x40>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ input@0 {
+ reg = <0x0>;
+ label = "VDD_IN";
+ shunt-resistor-micro-ohms = <5000>;
+ };
+
+ input@1 {
+ reg = <0x1>;
+ label = "VDD_CPU_GPU_CV";
+ shunt-resistor-micro-ohms = <5000>;
+ };
+
+ input@2 {
+ reg = <0x2>;
+ label = "VDD_SOC";
+ shunt-resistor-micro-ohms = <5000>;
+ };
+ };
+ };
+
rtc@c2a0000 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts
index e9460aedd47c..61b0e69d3d20 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts
@@ -12,15 +12,10 @@
model = "NVIDIA Jetson Orin NX Engineering Reference Developer Kit";
aliases {
- serial0 = &tcu;
serial1 = &uarta;
serial2 = &uarte;
};
- chosen {
- stdout-path = "serial0:115200n8";
- };
-
bus@0 {
serial@3100000 {
compatible = "nvidia,tegra194-hsuart";
@@ -34,10 +29,6 @@
status = "okay";
};
- serial@31d0000 {
- status = "okay";
- };
-
pwm@32a0000 {
assigned-clocks = <&bpmp TEGRA234_CLK_PWM3>;
assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
@@ -94,10 +85,6 @@
enable-active-high;
};
- serial {
- status = "okay";
- };
-
thermal-zones {
tj-thermal {
cooling-maps {
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi
index 39110c1232e0..5d0298b6c30d 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi
@@ -29,6 +29,7 @@
};
serial@31d0000 {
+ current-speed = <115200>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234.dtsi b/arch/arm64/boot/dts/nvidia/tegra234.dtsi
index 95524e5bce82..3f16595d099c 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra234.dtsi
@@ -43,12 +43,12 @@
<GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>;
status = "okay";
};
@@ -694,6 +694,8 @@
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&bpmp TEGRA234_CLK_UARTE>;
resets = <&bpmp TEGRA234_RESET_UARTE>;
+ dmas = <&gpcdma 20>, <&gpcdma 20>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -705,8 +707,8 @@
#address-cells = <1>;
#size-cells = <0>;
clock-frequency = <400000>;
- clocks = <&bpmp TEGRA234_CLK_I2C1
- &bpmp TEGRA234_CLK_PLLP_OUT0>;
+ clocks = <&bpmp TEGRA234_CLK_I2C1>,
+ <&bpmp TEGRA234_CLK_PLLP_OUT0>;
assigned-clocks = <&bpmp TEGRA234_CLK_I2C1>;
assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
clock-names = "div-clk", "parent";
@@ -724,8 +726,8 @@
#size-cells = <0>;
status = "disabled";
clock-frequency = <400000>;
- clocks = <&bpmp TEGRA234_CLK_I2C3
- &bpmp TEGRA234_CLK_PLLP_OUT0>;
+ clocks = <&bpmp TEGRA234_CLK_I2C3>,
+ <&bpmp TEGRA234_CLK_PLLP_OUT0>;
assigned-clocks = <&bpmp TEGRA234_CLK_I2C3>;
assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
clock-names = "div-clk", "parent";
@@ -743,8 +745,8 @@
#size-cells = <0>;
status = "disabled";
clock-frequency = <100000>;
- clocks = <&bpmp TEGRA234_CLK_I2C4
- &bpmp TEGRA234_CLK_PLLP_OUT0>;
+ clocks = <&bpmp TEGRA234_CLK_I2C4>,
+ <&bpmp TEGRA234_CLK_PLLP_OUT0>;
assigned-clocks = <&bpmp TEGRA234_CLK_I2C4>;
assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
clock-names = "div-clk", "parent";
@@ -762,8 +764,8 @@
#size-cells = <0>;
status = "disabled";
clock-frequency = <100000>;
- clocks = <&bpmp TEGRA234_CLK_I2C6
- &bpmp TEGRA234_CLK_PLLP_OUT0>;
+ clocks = <&bpmp TEGRA234_CLK_I2C6>,
+ <&bpmp TEGRA234_CLK_PLLP_OUT0>;
assigned-clocks = <&bpmp TEGRA234_CLK_I2C6>;
assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
clock-names = "div-clk", "parent";
@@ -781,8 +783,8 @@
#size-cells = <0>;
status = "disabled";
clock-frequency = <100000>;
- clocks = <&bpmp TEGRA234_CLK_I2C7
- &bpmp TEGRA234_CLK_PLLP_OUT0>;
+ clocks = <&bpmp TEGRA234_CLK_I2C7>,
+ <&bpmp TEGRA234_CLK_PLLP_OUT0>;
assigned-clocks = <&bpmp TEGRA234_CLK_I2C7>;
assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
clock-names = "div-clk", "parent";
@@ -807,8 +809,8 @@
#size-cells = <0>;
status = "disabled";
clock-frequency = <100000>;
- clocks = <&bpmp TEGRA234_CLK_I2C9
- &bpmp TEGRA234_CLK_PLLP_OUT0>;
+ clocks = <&bpmp TEGRA234_CLK_I2C9>,
+ <&bpmp TEGRA234_CLK_PLLP_OUT0>;
assigned-clocks = <&bpmp TEGRA234_CLK_I2C9>;
assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
clock-names = "div-clk", "parent";
@@ -819,7 +821,7 @@
};
spi@3210000 {
- compatible = "nvidia,tegra210-spi";
+ compatible = "nvidia,tegra210-spi", "nvidia,tegra114-spi";
reg = <0x0 0x03210000 0x0 0x1000>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
@@ -838,7 +840,7 @@
};
spi@3230000 {
- compatible = "nvidia,tegra210-spi";
+ compatible = "nvidia,tegra210-spi", "nvidia,tegra114-spi";
reg = <0x0 0x03230000 0x0 0x1000>;
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
@@ -1751,8 +1753,8 @@
#size-cells = <0>;
status = "disabled";
clock-frequency = <100000>;
- clocks = <&bpmp TEGRA234_CLK_I2C2
- &bpmp TEGRA234_CLK_PLLP_OUT0>;
+ clocks = <&bpmp TEGRA234_CLK_I2C2>,
+ <&bpmp TEGRA234_CLK_PLLP_OUT0>;
clock-names = "div-clk", "parent";
assigned-clocks = <&bpmp TEGRA234_CLK_I2C2>;
assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
@@ -1770,8 +1772,8 @@
#size-cells = <0>;
status = "disabled";
clock-frequency = <400000>;
- clocks = <&bpmp TEGRA234_CLK_I2C8
- &bpmp TEGRA234_CLK_PLLP_OUT0>;
+ clocks = <&bpmp TEGRA234_CLK_I2C8>,
+ <&bpmp TEGRA234_CLK_PLLP_OUT0>;
clock-names = "div-clk", "parent";
assigned-clocks = <&bpmp TEGRA234_CLK_I2C8>;
assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
@@ -1782,7 +1784,7 @@
};
spi@c260000 {
- compatible = "nvidia,tegra210-spi";
+ compatible = "nvidia,tegra210-spi", "nvidia,tegra114-spi";
reg = <0x0 0x0c260000 0x0 0x1000>;
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 2cca20563a1d..d6cb840b7050 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -1,5 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc.dtb
+
+apq8016-sbc-usb-host-dtbs := apq8016-sbc.dtb apq8016-sbc-usb-host.dtbo
+
+dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-usb-host.dtb
dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-d3-camera-mezzanine.dtb
dtb-$(CONFIG_ARCH_QCOM) += apq8039-t2.dtb
dtb-$(CONFIG_ARCH_QCOM) += apq8094-sony-xperia-kitakami-karin_windy.dtb
@@ -41,6 +45,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-thwc-uf896.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-thwc-ufi001c.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-wingtech-wt88047.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-yiming-uz801v3.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8939-longcheer-l9100.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8939-samsung-a7.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8939-sony-xperia-kanuti-tulip.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8953-motorola-potter.dtb
@@ -81,6 +86,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-lilac.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-maple.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-poplar.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-xiaomi-sagit.dtb
+dtb-$(CONFIG_ARCH_QCOM) += qcm6490-fairphone-fp5.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qdu1000-idp.dtb
@@ -112,11 +118,16 @@ dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-r3-lte.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-r9.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-r9-kb.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-r9-lte.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-r10.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-r10-kb.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-r10-lte.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-limozeen-r4.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-limozeen-r9.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-limozeen-r10.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-limozeen-nots-r4.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-limozeen-nots-r5.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-limozeen-nots-r9.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-lazor-limozeen-nots-r10.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pazquel-lte-parade.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pazquel-lte-ti.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pazquel-parade.dtb
@@ -196,6 +207,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sm6125-sony-xperia-seine-pdx201.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm6125-xiaomi-laurel-sprout.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm6350-sony-xperia-lena-pdx213.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm6375-sony-xperia-murray-pdx225.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sm7125-xiaomi-joyeuse.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm7225-fairphone-fp4.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-hdk.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-microsoft-surface-duo.dtb
diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc-usb-host.dtso b/arch/arm64/boot/dts/qcom/apq8016-sbc-usb-host.dtso
new file mode 100644
index 000000000000..a82c26b7eae8
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8016-sbc-usb-host.dtso
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+/plugin/;
+
+&usb {
+ dr_mode = "host";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dts b/arch/arm64/boot/dts/qcom/apq8016-sbc.dts
index 4f5541e9be0e..9ffad7d1f2b6 100644
--- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dts
+++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dts
@@ -172,6 +172,9 @@
pd-gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>;
avdd-supply = <&pm8916_l6>;
+ a2vdd-supply = <&pm8916_l6>;
+ dvdd-supply = <&pm8916_l6>;
+ pvdd-supply = <&pm8916_l6>;
v1p2-supply = <&pm8916_l6>;
v3p3-supply = <&pm8916_l17>;
@@ -230,6 +233,10 @@
status = "okay";
};
+&gpu {
+ status = "okay";
+};
+
&lpass {
status = "okay";
};
@@ -238,6 +245,10 @@
status = "okay";
};
+&mba_mem {
+ status = "okay";
+};
+
&mdss {
status = "okay";
};
@@ -253,10 +264,13 @@
firmware-name = "qcom/apq8016/mba.mbn", "qcom/apq8016/modem.mbn";
};
+&mpss_mem {
+ status = "okay";
+ reg = <0x0 0x86800000 0x0 0x2b00000>;
+};
+
&pm8916_codec {
status = "okay";
- clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>;
- clock-names = "mclk";
qcom,mbhc-vthreshold-low = <75 150 237 450 500>;
qcom,mbhc-vthreshold-high = <75 150 237 450 500>;
};
@@ -364,6 +378,14 @@
extcon = <&usb_id>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
firmware-name = "qcom/apq8016/wcnss.mbn";
@@ -377,6 +399,10 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
/* Enable CoreSight */
&cti0 { status = "okay"; };
&cti1 { status = "okay"; };
diff --git a/arch/arm64/boot/dts/qcom/apq8039-t2.dts b/arch/arm64/boot/dts/qcom/apq8039-t2.dts
index 027d1da7e81d..4f82bb668616 100644
--- a/arch/arm64/boot/dts/qcom/apq8039-t2.dts
+++ b/arch/arm64/boot/dts/qcom/apq8039-t2.dts
@@ -131,6 +131,10 @@
status = "okay";
};
+&gpu {
+ status = "okay";
+};
+
&lpass {
status = "okay";
};
@@ -391,3 +395,7 @@
&wcnss_iris {
compatible = "qcom,wcn3680";
};
+
+&wcnss_mem {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
index 385b178314db..e8148b3d6c50 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
@@ -62,25 +62,23 @@
stdout-path = "serial0:115200n8";
};
- clocks {
- divclk4: divclk4 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32768>;
- clock-output-names = "divclk4";
+ div1_mclk: divclk1 {
+ compatible = "gpio-gate-clock";
+ pinctrl-0 = <&audio_mclk>;
+ pinctrl-names = "default";
+ clocks = <&rpmcc RPM_SMD_DIV_CLK1>;
+ #clock-cells = <0>;
+ enable-gpios = <&pm8994_gpios 15 0>;
+ };
- pinctrl-names = "default";
- pinctrl-0 = <&divclk4_pin_a>;
- };
+ divclk4: divclk4 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "divclk4";
- div1_mclk: divclk1 {
- compatible = "gpio-gate-clock";
- pinctrl-0 = <&audio_mclk>;
- pinctrl-names = "default";
- clocks = <&rpmcc RPM_SMD_DIV_CLK1>;
- #clock-cells = <0>;
- enable-gpios = <&pm8994_gpios 15 0>;
- };
+ pinctrl-names = "default";
+ pinctrl-0 = <&divclk4_pin_a>;
};
gpio-keys {
@@ -1091,7 +1089,6 @@
vdda-phy-supply = <&vreg_l28a_0p925>;
vdda-pll-supply = <&vreg_l12a_1p8>;
- vddp-ref-clk-supply = <&vreg_l25a_1p2>;
};
&ufshc {
@@ -1100,6 +1097,7 @@
vcc-supply = <&vreg_l20a_2p95>;
vccq-supply = <&vreg_l25a_1p2>;
vccq2-supply = <&vreg_s4a_1p8>;
+ vdd-hba-supply = <&vreg_l25a_1p2>;
vcc-max-microamp = <600000>;
vccq-max-microamp = <450000>;
diff --git a/arch/arm64/boot/dts/qcom/ipq5018.dtsi b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
index 9f13d2dcdfd5..38ffdc3cbdcd 100644
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -57,6 +57,7 @@
firmware {
scm {
compatible = "qcom,scm-ipq5018", "qcom,scm";
+ qcom,sdi-enabled;
};
};
@@ -181,6 +182,13 @@
};
};
+ watchdog: watchdog@b017000 {
+ compatible = "qcom,apss-wdt-ipq5018", "qcom,kpss-wdt";
+ reg = <0x0b017000 0x40>;
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&sleep_clk>;
+ };
+
timer@b120000 {
compatible = "arm,armv7-timer-mem";
reg = <0x0b120000 0x1000>;
diff --git a/arch/arm64/boot/dts/qcom/ipq5332-rdp468.dts b/arch/arm64/boot/dts/qcom/ipq5332-rdp468.dts
index f96b0c8c908b..c224ffc65b08 100644
--- a/arch/arm64/boot/dts/qcom/ipq5332-rdp468.dts
+++ b/arch/arm64/boot/dts/qcom/ipq5332-rdp468.dts
@@ -12,6 +12,15 @@
/ {
model = "Qualcomm Technologies, Inc. IPQ5332 MI01.6";
compatible = "qcom,ipq5332-ap-mi01.6", "qcom,ipq5332";
+
+ regulator_fixed_5p0: regulator-s0500 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <500000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-name = "fixed_5p0";
+ };
};
&blsp1_spi0 {
@@ -79,3 +88,17 @@
bias-pull-up;
};
};
+
+&usb {
+ status = "okay";
+};
+
+&usb_dwc {
+ dr_mode = "host";
+};
+
+&usbphy0 {
+ vdd-supply = <&regulator_fixed_5p0>;
+
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/ipq5332.dtsi b/arch/arm64/boot/dts/qcom/ipq5332.dtsi
index 8bfc2db44624..d3fef2f80a81 100644
--- a/arch/arm64/boot/dts/qcom/ipq5332.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5332.dtsi
@@ -135,7 +135,7 @@
reg = <0x0 0x4a800000 0x0 0x100000>;
no-map;
- hwlocks = <&tcsr_mutex 0>;
+ hwlocks = <&tcsr_mutex 3>;
};
};
@@ -145,6 +145,19 @@
#size-cells = <1>;
ranges = <0 0 0 0xffffffff>;
+ usbphy0: phy@7b000 {
+ compatible = "qcom,ipq5332-usb-hsphy";
+ reg = <0x0007b000 0x12c>;
+
+ clocks = <&gcc GCC_USB0_PHY_CFG_AHB_CLK>;
+
+ resets = <&gcc GCC_QUSB2_0_PHY_BCR>;
+
+ #phy-cells = <0>;
+
+ status = "disabled";
+ };
+
qfprom: efuse@a4000 {
compatible = "qcom,ipq5332-qfprom", "qcom,qfprom";
reg = <0x000a4000 0x721>;
@@ -290,6 +303,48 @@
status = "disabled";
};
+ usb: usb@8af8800 {
+ compatible = "qcom,ipq5332-dwc3", "qcom,dwc3";
+ reg = <0x08af8800 0x400>;
+
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hs_phy_irq";
+
+ clocks = <&gcc GCC_USB0_MASTER_CLK>,
+ <&gcc GCC_SNOC_USB_CLK>,
+ <&gcc GCC_USB0_SLEEP_CLK>,
+ <&gcc GCC_USB0_MOCK_UTMI_CLK>;
+ clock-names = "core",
+ "iface",
+ "sleep",
+ "mock_utmi";
+
+ resets = <&gcc GCC_USB_BCR>;
+
+ qcom,select-utmi-as-pipe-clk;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ status = "disabled";
+
+ usb_dwc: usb@8a00000 {
+ compatible = "snps,dwc3";
+ reg = <0x08a00000 0xe000>;
+ clocks = <&gcc GCC_USB0_MOCK_UTMI_CLK>;
+ clock-names = "ref";
+ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+ phy-names = "usb2-phy";
+ phys = <&usbphy0>;
+ tx-fifo-resize;
+ snps,is-utmi-l1-suspend;
+ snps,hird-threshold = /bits/ 8 <0x0>;
+ snps,dis_u2_susphy_quirk;
+ snps,dis_u3_susphy_quirk;
+ };
+ };
+
intc: interrupt-controller@b000000 {
compatible = "qcom,msm-qgic2";
reg = <0x0b000000 0x1000>, /* GICD */
diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
index 47b8b1d6730a..e59b9df96c7e 100644
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
@@ -211,7 +211,7 @@
smem {
compatible = "qcom,smem";
memory-region = <&smem_region>;
- hwlocks = <&tcsr_mutex 0>;
+ hwlocks = <&tcsr_mutex 3>;
};
soc: soc@0 {
@@ -278,33 +278,25 @@
pcie_phy: phy@84000 {
compatible = "qcom,ipq6018-qmp-pcie-phy";
- reg = <0x0 0x00084000 0x0 0x1bc>; /* Serdes PLL */
+ reg = <0x0 0x00084000 0x0 0x1000>;
status = "disabled";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
clocks = <&gcc GCC_PCIE0_AUX_CLK>,
- <&gcc GCC_PCIE0_AHB_CLK>;
- clock-names = "aux", "cfg_ahb";
+ <&gcc GCC_PCIE0_AHB_CLK>,
+ <&gcc GCC_PCIE0_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "pipe";
+
+ clock-output-names = "gcc_pcie0_pipe_clk_src";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE0_PHY_BCR>,
<&gcc GCC_PCIE0PHY_PHY_BCR>;
reset-names = "phy",
"common";
-
- pcie_phy0: phy@84200 {
- reg = <0x0 0x00084200 0x0 0x16c>, /* Serdes Tx */
- <0x0 0x00084400 0x0 0x200>, /* Serdes Rx */
- <0x0 0x00084800 0x0 0x1f0>, /* PCS: Lane0, COM, PCIE */
- <0x0 0x00084c00 0x0 0xf4>; /* pcs_misc */
- #phy-cells = <0>;
-
- clocks = <&gcc GCC_PCIE0_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "gcc_pcie0_pipe_clk_src";
- #clock-cells = <0>;
- };
};
mdio: mdio@90000 {
@@ -393,7 +385,7 @@
tcsr_mutex: hwlock@1905000 {
compatible = "qcom,ipq6018-tcsr-mutex", "qcom,tcsr-mutex";
- reg = <0x0 0x01905000 0x0 0x1000>;
+ reg = <0x0 0x01905000 0x0 0x20000>;
#hwlock-cells = <1>;
};
@@ -756,7 +748,7 @@
#address-cells = <3>;
#size-cells = <2>;
- phys = <&pcie_phy0>;
+ phys = <&pcie_phy>;
phy-names = "pciephy";
ranges = <0x81000000 0x0 0x00000000 0x0 0x20200000 0x0 0x10000>,
diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
index 00ed71936b47..2f275c84e566 100644
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -101,7 +101,7 @@
reg = <0x0 0x4ab00000 0x0 0x100000>;
no-map;
- hwlocks = <&tcsr_mutex 0>;
+ hwlocks = <&tcsr_mutex 3>;
};
memory@4ac00000 {
@@ -211,59 +211,48 @@
pcie_qmp0: phy@84000 {
compatible = "qcom,ipq8074-qmp-gen3-pcie-phy";
- reg = <0x00084000 0x1bc>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
+ reg = <0x00084000 0x1000>;
clocks = <&gcc GCC_PCIE0_AUX_CLK>,
- <&gcc GCC_PCIE0_AHB_CLK>;
- clock-names = "aux", "cfg_ahb";
+ <&gcc GCC_PCIE0_AHB_CLK>,
+ <&gcc GCC_PCIE0_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "pipe";
+
+ clock-output-names = "pcie20_phy0_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
+
resets = <&gcc GCC_PCIE0_PHY_BCR>,
- <&gcc GCC_PCIE0PHY_PHY_BCR>;
+ <&gcc GCC_PCIE0PHY_PHY_BCR>;
reset-names = "phy",
"common";
status = "disabled";
-
- pcie_phy0: phy@84200 {
- reg = <0x84200 0x16c>,
- <0x84400 0x200>,
- <0x84800 0x1f0>,
- <0x84c00 0xf4>;
- #phy-cells = <0>;
- #clock-cells = <0>;
- clocks = <&gcc GCC_PCIE0_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "pcie20_phy0_pipe_clk";
- };
};
pcie_qmp1: phy@8e000 {
compatible = "qcom,ipq8074-qmp-pcie-phy";
- reg = <0x0008e000 0x1c4>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
+ reg = <0x0008e000 0x1000>;
clocks = <&gcc GCC_PCIE1_AUX_CLK>,
- <&gcc GCC_PCIE1_AHB_CLK>;
- clock-names = "aux", "cfg_ahb";
+ <&gcc GCC_PCIE1_AHB_CLK>,
+ <&gcc GCC_PCIE1_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "pipe";
+
+ clock-output-names = "pcie20_phy1_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
+
resets = <&gcc GCC_PCIE1_PHY_BCR>,
- <&gcc GCC_PCIE1PHY_PHY_BCR>;
+ <&gcc GCC_PCIE1PHY_PHY_BCR>;
reset-names = "phy",
"common";
status = "disabled";
-
- pcie_phy1: phy@8e200 {
- reg = <0x8e200 0x130>,
- <0x8e400 0x200>,
- <0x8e800 0x1f8>;
- #phy-cells = <0>;
- #clock-cells = <0>;
- clocks = <&gcc GCC_PCIE1_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "pcie20_phy1_pipe_clk";
- };
};
mdio: mdio@90000 {
@@ -807,7 +796,7 @@
#address-cells = <3>;
#size-cells = <2>;
- phys = <&pcie_phy1>;
+ phys = <&pcie_qmp1>;
phy-names = "pciephy";
ranges = <0x81000000 0x0 0x00000000 0x10200000 0x0 0x10000>, /* I/O */
@@ -869,7 +858,7 @@
#address-cells = <3>;
#size-cells = <2>;
- phys = <&pcie_phy0>;
+ phys = <&pcie_qmp0>;
phy-names = "pciephy";
ranges = <0x81000000 0x0 0x00000000 0x20200000 0x0 0x10000>, /* I/O */
diff --git a/arch/arm64/boot/dts/qcom/ipq9574.dtsi b/arch/arm64/boot/dts/qcom/ipq9574.dtsi
index 51aba071c1eb..8a72ad4afd03 100644
--- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi
@@ -195,7 +195,7 @@
smem@4aa00000 {
compatible = "qcom,smem";
reg = <0x0 0x4aa00000 0x0 0x100000>;
- hwlocks = <&tcsr_mutex 0>;
+ hwlocks = <&tcsr_mutex 3>;
no-map;
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts b/arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts
index 84723c9b73b4..57a74eea1005 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts
@@ -155,6 +155,14 @@
extcon = <&usb_id>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
};
@@ -163,6 +171,10 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
accel_int_default: accel-int-default-state {
pins = "gpio115";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts b/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts
index 47da738661bf..aa4c1ab1e673 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts
@@ -192,6 +192,14 @@
extcon = <&usb_id>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
};
@@ -200,6 +208,10 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
accel_int_default: accel-int-default-state {
pins = "gpio31";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts b/arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts
index 92f695481769..a8be6ff66893 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts
@@ -160,6 +160,14 @@
extcon = <&usb_id>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
};
@@ -168,6 +176,10 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
gpio_keys_default: gpio-keys-default-state {
pins = "gpio107", "gpio117";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts b/arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts
index 4aeeee24cedc..b748d140b52e 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts
@@ -150,6 +150,14 @@
extcon = <&usb_id>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
};
@@ -158,6 +166,10 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
camera_flash_default: camera-flash-default-state {
pins = "gpio31", "gpio32";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts b/arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts
index 484e488a5eca..bf7fc89dd106 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts
@@ -328,6 +328,14 @@
extcon = <&usb_id>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
};
@@ -336,6 +344,10 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
accel_irq_default: accel-irq-default-state {
pins = "gpio115";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts
index 3892ad4f639a..47d1c5cb13f4 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts
@@ -23,9 +23,14 @@
stdout-path = "serial0";
};
+ /*
+ * For some reason, the signed wcnss firmware is not relocatable.
+ * It must be loaded at 0x8b600000. All other firmware is relocatable,
+ * so place wcnss at the fixed address and then all other firmware
+ * regions will be automatically allocated at a fitting place.
+ */
reserved-memory {
- /* wcnss.mdt is not relocatable, so it must be loaded at 0x8b600000 */
- /delete-node/ wcnss@89300000;
+ /delete-node/ wcnss;
wcnss_mem: wcnss@8b600000 {
reg = <0x0 0x8b600000 0x0 0x600000>;
@@ -259,6 +264,14 @@
extcon = <&pm8916_usbin>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
};
@@ -267,6 +280,10 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
accel_int_default: accel-int-default-state {
pins = "gpio116";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts
index d73294af1a06..41cadb906b98 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts
@@ -146,6 +146,14 @@
extcon = <&usb_id>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
};
@@ -154,6 +162,10 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
button_backlight_default: button-backlight-default-state {
pins = "gpio17";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi
index 019bf73178fa..0b29132b74e1 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi
@@ -239,6 +239,10 @@
status = "okay";
};
+&gpu {
+ status = "okay";
+};
+
&mdss {
status = "okay";
};
@@ -284,6 +288,14 @@
extcon = <&muic>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&tlmm {
accel_int_default: accel-int-default-state {
pins = "gpio115";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts
index e5a569698c4f..f5a808369518 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts
@@ -120,6 +120,10 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
panel_vdd3_default: panel-vdd3-default-state {
pins = "gpio9";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts
index 388482a1e3d9..391befa22bb4 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts
@@ -71,6 +71,10 @@
compatible = "qcom,wcn3660b";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
tkey_en_default: tkey-en-default-state {
pins = "gpio97";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi
index 6f65fd4b3ed3..0824ab041d80 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi
@@ -83,6 +83,10 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
tkey_en_default: tkey-en-default-state {
pins = "gpio97";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt5-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt5-common.dtsi
index 54d648972d35..c19cf20d7427 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt5-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt5-common.dtsi
@@ -158,6 +158,14 @@
extcon = <&pm8916_usbin>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
};
@@ -166,6 +174,10 @@
compatible = "qcom,wcn3660b";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
accel_int_default: accel-int-default-state {
pins = "gpio115";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt510.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt510.dts
index 48111c6a2c78..75c4854ecd64 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt510.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt510.dts
@@ -19,6 +19,19 @@
pinctrl-names = "default";
};
+ reg_lcd_vmipi: regulator-lcd-vmipi {
+ compatible = "regulator-fixed";
+ regulator-name = "lcd_vmipi";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ gpio = <&tlmm 8 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&lcd_en_default>;
+ pinctrl-names = "default";
+ };
+
reg_motor_vdd: regulator-motor-vdd {
compatible = "regulator-fixed";
regulator-name = "motor_vdd";
@@ -55,6 +68,19 @@
enable-active-high;
};
+ reg_vlcd_5p4v: regulator-vlcd-5p4v {
+ compatible = "regulator-fixed";
+ regulator-name = "vlcd_5p4v";
+ regulator-min-microvolt = <5400000>;
+ regulator-max-microvolt = <5400000>;
+
+ gpio = <&tlmm 51 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&buckbooster_en_default>;
+ pinctrl-names = "default";
+ };
+
vibrator {
compatible = "pwm-vibrator";
@@ -81,10 +107,49 @@
pinctrl-0 = <&tsp_int_rst_default>;
pinctrl-names = "default";
+
+ linux,keycodes = <KEY_APPSELECT KEY_BACK>;
+ };
+};
+
+&mdss {
+ status = "okay";
+};
+
+&mdss_dsi0 {
+ pinctrl-0 = <&mdss_default>;
+ pinctrl-1 = <&mdss_sleep>;
+ pinctrl-names = "default", "sleep";
+
+ panel@0 {
+ compatible = "samsung,ltl101at01", "samsung,s6d7aa0";
+ reg = <0>;
+
+ power-supply = <&reg_vlcd_5p4v>;
+ vmipi-supply = <&reg_lcd_vmipi>;
+ reset-gpios = <&tlmm 97 GPIO_ACTIVE_LOW>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
};
};
+&mdss_dsi0_out {
+ data-lanes = <0 1 2 3>;
+ remote-endpoint = <&panel_in>;
+};
+
&tlmm {
+ buckbooster_en_default: buckbooster-en-default-state {
+ pins = "gpio51";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
motor_en_default: motor-en-default-state {
pins = "gpio76";
function = "gpio";
@@ -97,6 +162,27 @@
function = "gcc_gp2_clk_a";
};
+ lcd_en_default: lcd-en-default-state {
+ pins = "gpio8";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ mdss_default: mdss-default-state {
+ pins = "gpio97";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ mdss_sleep: mdss-sleep-state {
+ pins = "gpio97";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
tsp_en_default: tsp-en-default-state {
pins = "gpio73";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts
index 98ceaad7fcea..11359bcc27b3 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts
@@ -9,6 +9,19 @@
compatible = "samsung,gt58", "qcom,msm8916";
chassis-type = "tablet";
+ reg_5p4v: regulator-5p4v {
+ compatible = "regulator-fixed";
+ regulator-name = "vlcd_5p4v";
+ regulator-min-microvolt = <5400000>;
+ regulator-max-microvolt = <5400000>;
+
+ gpio = <&tlmm 8 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&buckbooster_en_default>;
+ pinctrl-names = "default";
+ };
+
reg_vdd_tsp: regulator-vdd-tsp {
compatible = "regulator-fixed";
regulator-name = "vdd_tsp";
@@ -51,7 +64,58 @@
};
};
+&mdss {
+ status = "okay";
+};
+
+&mdss_dsi0 {
+ pinctrl-0 = <&mdss_default>;
+ pinctrl-1 = <&mdss_sleep>;
+ pinctrl-names = "default", "sleep";
+
+ panel@0 {
+ compatible = "samsung,lsl080al03", "samsung,s6d7aa0";
+ reg = <0>;
+
+ power-supply = <&reg_5p4v>;
+ vmipi-supply = <&pm8916_l5>;
+ reset-gpios = <&tlmm 97 GPIO_ACTIVE_LOW>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+ };
+};
+
+&mdss_dsi0_out {
+ data-lanes = <0 1 2 3>;
+ remote-endpoint = <&panel_in>;
+};
+
&tlmm {
+ buckbooster_en_default: buckbooster-en-default-state {
+ pins = "gpio8";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ mdss_default: mdss-default-state {
+ pins = "gpio97";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ mdss_sleep: mdss-sleep-state {
+ pins = "gpio97";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
reg_tsp_en_default: reg-tsp-en-default-state {
pins = "gpio73";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-j5-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-j5-common.dtsi
index cb0e4a7faf91..fe59be3505fe 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-j5-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-j5-common.dtsi
@@ -84,6 +84,31 @@
pinctrl-0 = <&muic_int_default>;
};
};
+
+ i2c_sensors: i2c-sensors {
+ compatible = "i2c-gpio";
+
+ sda-gpios = <&tlmm 31 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&tlmm 32 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+
+ pinctrl-0 = <&sensors_i2c_default>;
+ pinctrl-names = "default";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ accelerometer: accelerometer@1d {
+ compatible = "st,lis2hh12";
+ reg = <0x1d>;
+
+ interrupts-extended = <&tlmm 115 IRQ_TYPE_LEVEL_HIGH>;
+
+ pinctrl-0 = <&accel_int_default>;
+ pinctrl-names = "default";
+
+ st,drdy-int-pin = <1>;
+ };
+ };
};
&blsp_i2c5 {
@@ -138,6 +163,14 @@
extcon = <&muic>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
};
@@ -146,7 +179,18 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
+ accel_int_default: accel-int-default-state {
+ pins = "gpio115";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
gpio_hall_sensor_default: gpio-hall-sensor-default-state {
pins = "gpio52";
function = "gpio";
@@ -187,6 +231,13 @@
bias-disable;
};
+ sensors_i2c_default: sensors-i2c-default-state {
+ pins = "gpio31", "gpio32";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
tsp_int_default: tsp-int-default-state {
pins = "gpio13";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-j5.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-j5.dts
index 3e1ff5b4d2d7..58c2f5a70e78 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-j5.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-j5.dts
@@ -10,6 +10,11 @@
chassis-type = "handset";
};
+&accelerometer {
+ vdd-supply = <&pm8916_l5>;
+ vddio-supply = <&pm8916_l5>;
+};
+
&blsp_i2c5 {
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-j5x.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-j5x.dts
index b2fe109723d8..8b404a9cd62d 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-j5x.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-j5x.dts
@@ -23,6 +23,17 @@
};
};
+&accelerometer {
+ interrupts-extended = <&tlmm 49 IRQ_TYPE_LEVEL_HIGH>;
+
+ vdd-supply = <&pm8916_l6>;
+ vddio-supply = <&pm8916_l6>;
+
+ mount-matrix = "0", "-1", "0",
+ "1", "0", "0",
+ "0", "0", "-1";
+};
+
&muic {
interrupts = <121 IRQ_TYPE_EDGE_FALLING>;
};
@@ -40,6 +51,10 @@
};
};
+&accel_int_default {
+ pins = "gpio49";
+};
+
&muic_int_default {
pins = "gpio121";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts
index eaf877378937..68da2a2d3077 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts
@@ -359,6 +359,14 @@
extcon = <&muic>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
};
@@ -367,6 +375,10 @@
compatible = "qcom,wcn3660b";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
fg_alert_default: fg-alert-default-state {
pins = "gpio121";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-ufi.dtsi b/arch/arm64/boot/dts/qcom/msm8916-ufi.dtsi
index 004a129a2ee2..c77ed04bb6c3 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-ufi.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-ufi.dtsi
@@ -17,18 +17,6 @@
stdout-path = "serial0";
};
- reserved-memory {
- mpss_mem: mpss@86800000 {
- reg = <0x0 0x86800000 0x0 0x5500000>;
- no-map;
- };
-
- gps_mem: gps@8bd00000 {
- reg = <0x0 0x8bd00000 0x0 0x200000>;
- no-map;
- };
- };
-
gpio-keys {
compatible = "gpio-keys";
@@ -92,10 +80,19 @@
clocks = <&xo_board>, <&sleep_clk>, <0>, <0>, <0>, <0>, <0>;
};
+&mba_mem {
+ status = "okay";
+};
+
&mpss {
status = "okay";
};
+&mpss_mem {
+ reg = <0x0 0x86800000 0x0 0x5500000>;
+ status = "okay";
+};
+
&pm8916_usbin {
status = "okay";
};
@@ -115,6 +112,14 @@
extcon = <&pm8916_usbin>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
};
@@ -123,6 +128,10 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
/* pins are board-specific */
button_default: button-default-state {
diff --git a/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts
index 8e238976ab1c..419f35c1fc92 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts
@@ -189,6 +189,14 @@
extcon = <&usb_id>;
};
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
&wcnss {
status = "okay";
};
@@ -197,6 +205,10 @@
compatible = "qcom,wcn3620";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
camera_flash_default: camera-flash-default-state {
pins = "gpio31", "gpio32";
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 33fb65d73104..4f799b536a92 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -74,23 +74,43 @@
};
mpss_mem: mpss@86800000 {
- reg = <0x0 0x86800000 0x0 0x2b00000>;
+ /*
+ * The memory region for the mpss firmware is generally
+ * relocatable and could be allocated dynamically.
+ * However, many firmware versions tend to fail when
+ * loaded to some special addresses, so it is hard to
+ * define reliable alloc-ranges.
+ *
+ * alignment = <0x0 0x400000>;
+ * alloc-ranges = <0x0 0x86800000 0x0 0x8000000>;
+ */
+ reg = <0x0 0x86800000 0x0 0>; /* size is device-specific */
no-map;
+ status = "disabled";
};
- wcnss_mem: wcnss@89300000 {
- reg = <0x0 0x89300000 0x0 0x600000>;
+ wcnss_mem: wcnss {
+ size = <0x0 0x600000>;
+ alignment = <0x0 0x100000>;
+ alloc-ranges = <0x0 0x86800000 0x0 0x8000000>;
no-map;
+ status = "disabled";
};
- venus_mem: venus@89900000 {
- reg = <0x0 0x89900000 0x0 0x600000>;
+ venus_mem: venus {
+ size = <0x0 0x500000>;
+ alignment = <0x0 0x100000>;
+ alloc-ranges = <0x0 0x86800000 0x0 0x8000000>;
no-map;
+ status = "disabled";
};
- mba_mem: mba@8ea00000 {
+ mba_mem: mba {
+ size = <0x0 0x100000>;
+ alignment = <0x0 0x100000>;
+ alloc-ranges = <0x0 0x86800000 0x0 0x8000000>;
no-map;
- reg = <0 0x8ea00000 0 0x100000>;
+ status = "disabled";
};
};
@@ -1750,7 +1770,7 @@
};
};
- gpu@1c00000 {
+ gpu: gpu@1c00000 {
compatible = "qcom,adreno-306.0", "qcom,adreno";
reg = <0x01c00000 0x20000>;
reg-names = "kgsl_3d0_reg_memory";
@@ -1773,6 +1793,7 @@
power-domains = <&gcc OXILI_GDSC>;
operating-points-v2 = <&gpu_opp_table>;
iommus = <&gpu_iommu 1>, <&gpu_iommu 2>;
+ status = "disabled";
gpu_opp_table: opp-table {
compatible = "operating-points-v2";
@@ -1797,7 +1818,7 @@
clock-names = "core", "iface", "bus";
iommus = <&apps_iommu 5>;
memory-region = <&venus_mem>;
- status = "okay";
+ status = "disabled";
video-decoder {
compatible = "venus-decoder";
@@ -1813,7 +1834,7 @@
#size-cells = <1>;
#iommu-cells = <1>;
compatible = "qcom,msm8916-iommu", "qcom,msm-iommu-v1";
- ranges = <0 0x01e20000 0x40000>;
+ ranges = <0 0x01e20000 0x20000>;
reg = <0x01ef0000 0x3000>;
clocks = <&gcc GCC_SMMU_CFG_CLK>,
<&gcc GCC_APSS_TCU_CLK>;
diff --git a/arch/arm64/boot/dts/qcom/msm8939-longcheer-l9100.dts b/arch/arm64/boot/dts/qcom/msm8939-longcheer-l9100.dts
new file mode 100644
index 000000000000..6802714fda3f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8939-longcheer-l9100.dts
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+#include "msm8939-pm8916.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
+
+/ {
+ model = "BQ Aquaris M5 (Longcheer L9100)";
+ compatible = "longcheer,l9100", "qcom,msm8939";
+ chassis-type = "handset";
+
+ aliases {
+ mmc0 = &sdhc_1; /* eMMC */
+ mmc1 = &sdhc_2; /* SD card */
+ serial0 = &blsp_uart2;
+ };
+
+ chosen {
+ stdout-path = "serial0";
+ };
+
+ gpio-hall-sensor {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&gpio_hall_sensor_default>;
+ pinctrl-names = "default";
+
+ label = "GPIO Hall Effect Sensor";
+
+ event-hall-sensor {
+ label = "Hall Effect Sensor";
+ gpios = <&tlmm 20 GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_SW>;
+ linux,code = <SW_LID>;
+ linux,can-disable;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&gpio_keys_default>;
+ pinctrl-names = "default";
+
+ label = "GPIO Buttons";
+
+ button-volume-up {
+ label = "Volume Up";
+ gpios = <&tlmm 107 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ gpios = <&tlmm 17 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_WHITE>;
+ default-state = "off";
+ function = LED_FUNCTION_KBD_BACKLIGHT;
+
+ pinctrl-0 = <&button_backlight_default>;
+ pinctrl-names = "default";
+ };
+ };
+
+ reg_ts_vdd: regulator-vdd-ts {
+ compatible = "regulator-fixed";
+ regulator-name = "regulator-vdd-ts";
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+
+ gpio = <&tlmm 78 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&ts_vdd_default>;
+ pinctrl-names = "default";
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pm8916_pwm 0 100000>;
+ brightness-levels = <0 255>;
+ num-interpolated-steps = <255>;
+ default-brightness-level = <128>;
+ enable-gpios = <&tlmm 98 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&lcd_bl_en_default>;
+ pinctrl-names = "default";
+ };
+
+ flash-led-controller {
+ compatible = "ocs,ocp8110";
+ flash-gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>;
+ enable-gpios = <&tlmm 49 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&camera_front_flash_default>;
+ pinctrl-names = "default";
+
+ led {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ flash-max-timeout-us = <250000>;
+ };
+ };
+
+ usb_id: usb-id {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&usb_id_default &usb_id_switch_default>;
+ pinctrl-names = "default";
+ };
+
+};
+
+&blsp_i2c3 {
+ status = "okay";
+
+ magnetometer@d {
+ compatible = "asahi-kasei,ak09911";
+ reg = <0x0d>;
+
+ vdd-supply = <&pm8916_l17>;
+ vid-supply = <&pm8916_l6>;
+
+ reset-gpios = <&tlmm 68 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&mag_reset_default>;
+ pinctrl-names = "default";
+ };
+
+ light-sensor@23 {
+ compatible = "liteon,ltr559";
+ reg = <0x23>;
+
+ vdd-supply = <&pm8916_l17>;
+ vddio-supply = <&pm8916_l5>;
+
+ interrupts-extended = <&tlmm 113 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-0 = <&light_int_default>;
+ pinctrl-names = "default";
+ };
+
+ imu@68 {
+ compatible = "bosch,bmi160";
+ reg = <0x68>;
+
+ vdd-supply = <&pm8916_l17>;
+ vddio-supply = <&pm8916_l6>;
+ };
+};
+
+&blsp_i2c5 {
+ status = "okay";
+
+ touchscreen@4a {
+ compatible = "atmel,maxtouch";
+ reg = <0x4a>;
+
+ interrupts-extended = <&tlmm 13 IRQ_TYPE_LEVEL_LOW>;
+
+ reset-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>;
+
+ vdda-supply = <&pm8916_l6>;
+ vdd-supply = <&reg_ts_vdd>;
+
+ pinctrl-0 = <&ts_int_reset_default>;
+ pinctrl-names = "default";
+
+ /* Keys listed from right to left */
+ linux,keycodes = <KEY_APPSELECT KEY_HOMEPAGE KEY_BACK>;
+ };
+};
+
+&blsp_uart2 {
+ status = "okay";
+};
+
+&pm8916_mpps {
+ pwm_out: mpp4-state {
+ pins = "mpp4";
+ function = "digital";
+ power-source = <PM8916_MPP_VPH>;
+ output-low;
+ qcom,dtest = <1>;
+ };
+};
+
+&pm8916_pwm {
+ pinctrl-0 = <&pwm_out>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pm8916_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&pm8916_rpm_regulators {
+ pm8916_l17: l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+};
+
+&pm8916_vib {
+ status = "okay";
+};
+
+&sdhc_1 {
+ status = "okay";
+};
+
+&sdhc_2 {
+ pinctrl-0 = <&sdc2_default &sdc2_cd_default>;
+ pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>;
+ pinctrl-names = "default", "sleep";
+
+ cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>;
+
+ status = "okay";
+};
+
+&usb {
+ extcon = <&usb_id>, <&usb_id>;
+ status = "okay";
+};
+
+&usb_hs_phy {
+ extcon = <&usb_id>;
+};
+
+&wcnss {
+ status = "okay";
+};
+
+&wcnss_iris {
+ compatible = "qcom,wcn3620";
+};
+
+&tlmm {
+ button_backlight_default: button-backlight-default-state {
+ pins = "gpio17";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ camera_front_flash_default: camera-front-flash-default-state {
+ pins = "gpio8", "gpio49";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ gpio_hall_sensor_default: gpio-hall-sensor-default-state {
+ pins = "gpio20";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ gpio_keys_default: gpio-keys-default-state {
+ pins = "gpio107";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ lcd_bl_en_default: lcd-bl-en-default-state {
+ pins = "gpio98";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ light_int_default: light-int-default-state {
+ pins = "gpio113";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ mag_reset_default: mag-reset-default-state {
+ pins = "gpio68";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ sdc2_cd_default: sdc2-cd-default-state {
+ pins = "gpio38";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ ts_int_reset_default: ts-int-reset-default-state {
+ pins = "gpio12", "gpio13";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ ts_vdd_default: ts-vdd-default-state {
+ pins = "gpio78";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ usb_id_default: usb-id-default-state {
+ pins = "gpio110";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+
+ usb_id_switch_default: usb-id-switch-default-state {
+ pins = "gpio121";
+ function = "gpio";
+ drive-strength = <2>;
+ output-high;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts b/arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts
index ba652909d162..fccd8fec8b8f 100644
--- a/arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts
+++ b/arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts
@@ -352,6 +352,10 @@
compatible = "qcom,wcn3660b";
};
+&wcnss_mem {
+ status = "okay";
+};
+
&tlmm {
accel_int_default: accel-int-default-state {
pins = "gpio115";
diff --git a/arch/arm64/boot/dts/qcom/msm8939-sony-xperia-kanuti-tulip.dts b/arch/arm64/boot/dts/qcom/msm8939-sony-xperia-kanuti-tulip.dts
index 89b6aebba404..eeb4d578c6fa 100644
--- a/arch/arm64/boot/dts/qcom/msm8939-sony-xperia-kanuti-tulip.dts
+++ b/arch/arm64/boot/dts/qcom/msm8939-sony-xperia-kanuti-tulip.dts
@@ -39,6 +39,10 @@
};
};
+&gpu {
+ status = "okay";
+};
+
&mdss {
status = "okay";
};
@@ -87,3 +91,7 @@
&wcnss_iris {
compatible = "qcom,wcn3660";
};
+
+&wcnss_mem {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8939.dtsi b/arch/arm64/boot/dts/qcom/msm8939.dtsi
index 6e24f0f2374f..324b5d26db40 100644
--- a/arch/arm64/boot/dts/qcom/msm8939.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8939.dtsi
@@ -346,23 +346,43 @@
};
mpss_mem: mpss@86800000 {
- reg = <0x0 0x86800000 0x0 0x5500000>;
+ /*
+ * The memory region for the mpss firmware is generally
+ * relocatable and could be allocated dynamically.
+ * However, many firmware versions tend to fail when
+ * loaded to some special addresses, so it is hard to
+ * define reliable alloc-ranges.
+ *
+ * alignment = <0x0 0x400000>;
+ * alloc-ranges = <0x0 0x86800000 0x0 0x8000000>;
+ */
+ reg = <0x0 0x86800000 0x0 0>; /* size is device-specific */
no-map;
+ status = "disabled";
};
- wcnss_mem: wcnss@8bd00000 {
- reg = <0x0 0x8bd00000 0x0 0x600000>;
+ wcnss_mem: wcnss {
+ size = <0x0 0x600000>;
+ alignment = <0x0 0x100000>;
+ alloc-ranges = <0x0 0x86800000 0x0 0x8000000>;
no-map;
+ status = "disabled";
};
- venus_mem: venus@8c300000 {
- reg = <0x0 0x8c300000 0x0 0x800000>;
+ venus_mem: venus {
+ size = <0x0 0x500000>;
+ alignment = <0x0 0x100000>;
+ alloc-ranges = <0x0 0x86800000 0x0 0x8000000>;
no-map;
+ status = "disabled";
};
- mba_mem: mba@8cb00000 {
- reg = <0x0 0x8cb00000 0x0 0x100000>;
+ mba_mem: mba {
+ size = <0x0 0x100000>;
+ alignment = <0x0 0x100000>;
+ alloc-ranges = <0x0 0x86800000 0x0 0x8000000>;
no-map;
+ status = "disabled";
};
};
@@ -1395,7 +1415,7 @@
};
};
- gpu@1c00000 {
+ gpu: gpu@1c00000 {
compatible = "qcom,adreno-405.0", "qcom,adreno";
reg = <0x01c00000 0x10000>;
reg-names = "kgsl_3d0_reg_memory";
@@ -1418,6 +1438,7 @@
power-domains = <&gcc OXILI_GDSC>;
operating-points-v2 = <&opp_table>;
iommus = <&gpu_iommu 1>, <&gpu_iommu 2>;
+ status = "disabled";
opp_table: opp-table {
compatible = "operating-points-v2";
@@ -1447,7 +1468,7 @@
apps_iommu: iommu@1ef0000 {
compatible = "qcom,msm8916-iommu", "qcom,msm-iommu-v1";
reg = <0x01ef0000 0x3000>;
- ranges = <0 0x01e20000 0x40000>;
+ ranges = <0 0x01e20000 0x20000>;
clocks = <&gcc GCC_SMMU_CFG_CLK>,
<&gcc GCC_APSS_TCU_CLK>;
clock-names = "iface", "bus";
diff --git a/arch/arm64/boot/dts/qcom/msm8976.dtsi b/arch/arm64/boot/dts/qcom/msm8976.dtsi
index f9f5afbcc52b..d2bb1ada361a 100644
--- a/arch/arm64/boot/dts/qcom/msm8976.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8976.dtsi
@@ -338,7 +338,12 @@
};
lpass_mem: lpass@8c200000 {
- reg = <0x0 0x8c200000 0x0 0x1800000>;
+ reg = <0x0 0x8c200000 0x0 0x1000000>;
+ no-map;
+ };
+
+ wcnss_fw_mem: wcnss@8d200000 {
+ reg = <0x0 0x8d200000 0x0 0x800000>;
no-map;
};
@@ -379,7 +384,7 @@
smp2p-modem {
compatible = "qcom,smp2p";
interrupts = <GIC_SPI 27 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 13>;
+ qcom,ipc = <&apcs 8 14>;
qcom,local-pid = <0>;
qcom,remote-pid = <1>;
@@ -402,7 +407,7 @@
smp2p-wcnss {
compatible = "qcom,smp2p";
interrupts = <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 17>;
+ qcom,ipc = <&apcs 8 18>;
qcom,local-pid = <0>;
qcom,remote-pid = <4>;
@@ -428,9 +433,9 @@
#address-cells = <1>;
#size-cells = <0>;
- qcom,ipc-1 = <&apcs 8 12>;
+ qcom,ipc-1 = <&apcs 8 13>;
qcom,ipc-2 = <&apcs 8 9>;
- qcom,ipc-3 = <&apcs 8 18>;
+ qcom,ipc-3 = <&apcs 8 19>;
apps_smsm: apps@0 {
reg = <0>;
diff --git a/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts b/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
index fcca1ba94da6..133f9c2540bc 100644
--- a/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
+++ b/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
@@ -15,6 +15,7 @@
/delete-node/ &audio_mem;
/delete-node/ &mpss_mem;
/delete-node/ &peripheral_region;
+/delete-node/ &res_hyp_mem;
/delete-node/ &rmtfs_mem;
/ {
@@ -109,11 +110,6 @@
qcom,client-id = <1>;
};
- audio_mem: audio@cb400000 {
- reg = <0 0xcb000000 0 0x400000>;
- no-mem;
- };
-
qseecom_mem: qseecom@cb400000 {
reg = <0 0xcb400000 0 0x1c00000>;
no-mem;
diff --git a/arch/arm64/boot/dts/qcom/msm8994-msft-lumia-octagon.dtsi b/arch/arm64/boot/dts/qcom/msm8994-msft-lumia-octagon.dtsi
index 2861bcdf87b7..cbc84459a5ae 100644
--- a/arch/arm64/boot/dts/qcom/msm8994-msft-lumia-octagon.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8994-msft-lumia-octagon.dtsi
@@ -23,6 +23,7 @@
/delete-node/ &mba_mem;
/delete-node/ &mpss_mem;
/delete-node/ &peripheral_region;
+/delete-node/ &res_hyp_mem;
/delete-node/ &rmtfs_mem;
/delete-node/ &smem_mem;
diff --git a/arch/arm64/boot/dts/qcom/msm8994.dtsi b/arch/arm64/boot/dts/qcom/msm8994.dtsi
index c3262571520d..8295bf1b219d 100644
--- a/arch/arm64/boot/dts/qcom/msm8994.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8994.dtsi
@@ -281,7 +281,7 @@
no-map;
};
- reserved@6c00000 {
+ res_hyp_mem: reserved@6c00000 {
reg = <0 0x06c00000 0 0x400000>;
no-map;
};
diff --git a/arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi
index ec5457508fe6..38035e0db80b 100644
--- a/arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi
@@ -772,7 +772,6 @@
&ufsphy {
vdda-phy-supply = <&vreg_l28a_0p925>;
vdda-pll-supply = <&vreg_l12a_1p8>;
- vddp-ref-clk-supply = <&vreg_l25a_1p2>;
status = "okay";
};
@@ -781,6 +780,7 @@
vcc-supply = <&vreg_l20a_2p95>;
vccq-supply = <&vreg_l25a_1p2>;
vccq2-supply = <&vreg_s4a_1p8>;
+ vdd-hba-supply = <&vreg_l25a_1p2>;
vcc-max-microamp = <600000>;
vccq-max-microamp = <450000>;
diff --git a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi
index bcd2397eb373..5ab583be9e0a 100644
--- a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi
@@ -11,26 +11,24 @@
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
/ {
- clocks {
- divclk1_cdc: divclk1 {
- compatible = "gpio-gate-clock";
- clocks = <&rpmcc RPM_SMD_DIV_CLK1>;
- #clock-cells = <0>;
- enable-gpios = <&pm8994_gpios 15 GPIO_ACTIVE_HIGH>;
+ divclk1_cdc: divclk1 {
+ compatible = "gpio-gate-clock";
+ clocks = <&rpmcc RPM_SMD_DIV_CLK1>;
+ #clock-cells = <0>;
+ enable-gpios = <&pm8994_gpios 15 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&divclk1_default>;
- };
+ pinctrl-names = "default";
+ pinctrl-0 = <&divclk1_default>;
+ };
- divclk4: divclk4 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32768>;
- clock-output-names = "divclk4";
+ divclk4: divclk4 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "divclk4";
- pinctrl-names = "default";
- pinctrl-0 = <&divclk4_pin_a>;
- };
+ pinctrl-names = "default";
+ pinctrl-0 = <&divclk4_pin_a>;
};
gpio-keys {
@@ -117,7 +115,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
/delete-node/ mba@91500000;
@@ -419,6 +417,7 @@
vcc-supply = <&vreg_l20a_2p95>;
vccq-supply = <&vreg_l25a_1p2>;
vccq2-supply = <&vreg_s4a_1p8>;
+ vdd-hba-supply = <&vreg_l25a_1p2>;
vcc-max-microamp = <600000>;
vccq-max-microamp = <450000>;
@@ -430,7 +429,6 @@
vdda-phy-supply = <&vreg_l28a_0p925>;
vdda-pll-supply = <&vreg_l12a_1p8>;
- vddp-ref-clk-supply = <&vreg_l25a_1p2>;
};
&venus {
diff --git a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts
index d1066edaea47..f8e9d90afab0 100644
--- a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts
+++ b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts
@@ -20,16 +20,14 @@
qcom,pmic-id = <0x20009 0x2000a 0x00 0x00>;
qcom,board-id = <31 0>;
- clocks {
- divclk2_haptics: divclk2 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32768>;
- clock-output-names = "divclk2";
-
- pinctrl-names = "default";
- pinctrl-0 = <&divclk2_pin_a>;
- };
+ divclk2_haptics: divclk2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "divclk2";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&divclk2_pin_a>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index c8e0986425ab..6ba9da9e6a8b 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -9,6 +9,7 @@
#include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/interconnect/qcom,msm8996.h>
#include <dt-bindings/interconnect/qcom,msm8996-cbf.h>
+#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/soc/qcom,apr.h>
@@ -538,7 +539,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
mpss_mem: mpss@88800000 {
diff --git a/arch/arm64/boot/dts/qcom/msm8998-fxtec-pro1.dts b/arch/arm64/boot/dts/qcom/msm8998-fxtec-pro1.dts
index b6a214bea70f..f1ceaedd9520 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-fxtec-pro1.dts
+++ b/arch/arm64/boot/dts/qcom/msm8998-fxtec-pro1.dts
@@ -671,6 +671,7 @@
vcc-supply = <&vreg_l20a_2p95>;
vccq-supply = <&vreg_l26a_1p2>;
vccq2-supply = <&vreg_s4a_1p8>;
+ vdd-hba-supply = <&vreg_l26a_1p2>;
vcc-max-microamp = <750000>;
vccq-max-microamp = <560000>;
vccq2-max-microamp = <750000>;
@@ -680,7 +681,6 @@
status = "okay";
vdda-phy-supply = <&vreg_l1a_0p875>;
vdda-pll-supply = <&vreg_l2a_1p2>;
- vddp-ref-clk-supply = <&vreg_l26a_1p2>;
};
&usb3 {
diff --git a/arch/arm64/boot/dts/qcom/msm8998-mtp.dts b/arch/arm64/boot/dts/qcom/msm8998-mtp.dts
index 4319f4da8996..7c77612fb990 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8998-mtp.dts
@@ -412,6 +412,7 @@
vcc-supply = <&vreg_l20a_2p95>;
vccq-supply = <&vreg_l26a_1p2>;
vccq2-supply = <&vreg_s4a_1p8>;
+ vdd-hba-supply = <&vreg_l26a_1p2>;
vcc-max-microamp = <750000>;
vccq-max-microamp = <560000>;
vccq2-max-microamp = <750000>;
@@ -421,7 +422,6 @@
status = "okay";
vdda-phy-supply = <&vreg_l1a_0p875>;
vdda-pll-supply = <&vreg_l2a_1p2>;
- vddp-ref-clk-supply = <&vreg_l26a_1p2>;
};
&usb3 {
diff --git a/arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi
index 68e634f8212c..e6a69d942a4a 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi
@@ -534,6 +534,7 @@
vcc-supply = <&vreg_l20a_2p95>;
vccq-supply = <&vreg_l26a_1p2>;
vccq2-supply = <&vreg_s4a_1p8>;
+ vdd-hba-supply = <&vreg_l26a_1p2>;
vcc-max-microamp = <750000>;
vccq-max-microamp = <560000>;
vccq2-max-microamp = <750000>;
@@ -544,7 +545,6 @@
vdda-phy-supply = <&vreg_l1a_0p875>;
vdda-pll-supply = <&vreg_l2a_1p2>;
- vddp-ref-clk-supply = <&vreg_l26a_1p2>;
};
&usb3 {
diff --git a/arch/arm64/boot/dts/qcom/msm8998-xiaomi-sagit.dts b/arch/arm64/boot/dts/qcom/msm8998-xiaomi-sagit.dts
index 437b30cc8bdc..0cac06f25a77 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-xiaomi-sagit.dts
+++ b/arch/arm64/boot/dts/qcom/msm8998-xiaomi-sagit.dts
@@ -667,6 +667,7 @@
vcc-supply = <&vreg_l20a_2p95>;
vccq-supply = <&vreg_l26a_1p2>;
vccq2-supply = <&vreg_s4a_1p8>;
+ vdd-hba-supply = <&vreg_l26a_1p2>;
vcc-max-microamp = <750000>;
vccq-max-microamp = <560000>;
vccq2-max-microamp = <750000>;
@@ -676,7 +677,6 @@
&ufsphy {
vdda-phy-supply = <&vreg_l1a_0p875>;
vdda-pll-supply = <&vreg_l2a_1p2>;
- vddp-ref-clk-supply = <&vreg_l26a_1p2>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi
index f180047cacb0..b485bf925ce6 100644
--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi
@@ -6,6 +6,7 @@
#include <dt-bindings/clock/qcom,gpucc-msm8998.h>
#include <dt-bindings/clock/qcom,mmcc-msm8998.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/gpio/gpio.h>
@@ -56,7 +57,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
spss_mem: memory@8ab00000 {
@@ -945,7 +946,7 @@
#address-cells = <3>;
#size-cells = <2>;
num-lanes = <1>;
- phys = <&pciephy>;
+ phys = <&pcie_phy>;
phy-names = "pciephy";
status = "disabled";
@@ -975,32 +976,28 @@
pcie_phy: phy@1c06000 {
compatible = "qcom,msm8998-qmp-pcie-phy";
- reg = <0x01c06000 0x18c>;
- #address-cells = <1>;
- #size-cells = <1>;
+ reg = <0x01c06000 0x1000>;
status = "disabled";
- ranges;
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
<&gcc GCC_PCIE_0_CFG_AHB_CLK>,
- <&gcc GCC_PCIE_CLKREF_CLK>;
- clock-names = "aux", "cfg_ahb", "ref";
+ <&gcc GCC_PCIE_CLKREF_CLK>,
+ <&gcc GCC_PCIE_0_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "pipe";
+
+ clock-output-names = "pcie_0_pipe_clk_src";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_0_PHY_BCR>, <&gcc GCC_PCIE_PHY_BCR>;
reset-names = "phy", "common";
vdda-phy-supply = <&vreg_l1a_0p875>;
vdda-pll-supply = <&vreg_l2a_1p2>;
-
- pciephy: phy@1c06800 {
- reg = <0x01c06200 0x128>, <0x01c06400 0x1fc>, <0x01c06800 0x20c>;
- #phy-cells = <0>;
-
- clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "pcie_0_pipe_clk_src";
- #clock-cells = <0>;
- };
};
ufshc: ufshc@1da4000 {
diff --git a/arch/arm64/boot/dts/qcom/pm6150.dtsi b/arch/arm64/boot/dts/qcom/pm6150.dtsi
index 7d4d1f2767ed..ddbaf7280b03 100644
--- a/arch/arm64/boot/dts/qcom/pm6150.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm6150.dtsi
@@ -53,6 +53,14 @@
bias-pull-up;
linux,code = <KEY_POWER>;
};
+
+ pm6150_resin: resin {
+ compatible = "qcom,pm8941-resin";
+ interrupts = <0x0 0x8 1 IRQ_TYPE_EDGE_BOTH>;
+ debounce = <15625>;
+ bias-pull-up;
+ status = "disabled";
+ };
};
pm6150_temp: temp-alarm@2400 {
@@ -88,6 +96,14 @@
status = "disabled";
};
+ pm6150_rtc: rtc@6000 {
+ compatible = "qcom,pm8941-rtc";
+ reg = <0x6000>, <0x6100>;
+ reg-names = "rtc", "alarm";
+ interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
pm6150_gpios: gpio@c000 {
compatible = "qcom,pm6150-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
diff --git a/arch/arm64/boot/dts/qcom/pm7250b.dtsi b/arch/arm64/boot/dts/qcom/pm7250b.dtsi
index e8540c36bd99..df0afe82f250 100644
--- a/arch/arm64/boot/dts/qcom/pm7250b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm7250b.dtsi
@@ -39,16 +39,16 @@
};
&spmi_bus {
- pmic@2 {
+ pmic@PM7250B_SID {
compatible = "qcom,pm7250b", "qcom,spmi-pmic";
- reg = <0x2 SPMI_USID>;
+ reg = <PM7250B_SID SPMI_USID>;
#address-cells = <1>;
#size-cells = <0>;
pm7250b_temp: temp-alarm@2400 {
compatible = "qcom,spmi-temp-alarm";
reg = <0x2400>;
- interrupts = <0x2 0x24 0x0 IRQ_TYPE_EDGE_BOTH>;
+ interrupts = <PM7250B_SID 0x24 0x0 IRQ_TYPE_EDGE_BOTH>;
io-channels = <&pm7250b_adc ADC5_DIE_TEMP>;
io-channel-names = "thermal";
#thermal-sensor-cells = <0>;
@@ -60,7 +60,7 @@
#address-cells = <1>;
#size-cells = <0>;
#io-channel-cells = <1>;
- interrupts = <0x2 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <PM7250B_SID 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
channel@0 {
reg = <ADC5_REF_GND>;
@@ -141,7 +141,7 @@
pm7250b_adc_tm: adc-tm@3500 {
compatible = "qcom,spmi-adc-tm5";
reg = <0x3500>;
- interrupts = <0x2 0x35 0x0 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <PM7250B_SID 0x35 0x0 IRQ_TYPE_EDGE_RISING>;
#thermal-sensor-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
@@ -159,9 +159,9 @@
};
};
- pmic@3 {
+ pmic@PM7250B_SID1 {
compatible = "qcom,pm7250b", "qcom,spmi-pmic";
- reg = <0x3 SPMI_USID>;
+ reg = <PM7250B_SID1 SPMI_USID>;
#address-cells = <1>;
#size-cells = <0>;
};
diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
index 2b9123df5847..1aee3270ce7b 100644
--- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
@@ -59,6 +59,46 @@
reg = <0x1100>;
};
+ pm8150b_typec: typec@1500 {
+ compatible = "qcom,pm8150b-typec";
+ status = "disabled";
+ reg = <0x1500>,
+ <0x1700>;
+ interrupts = <0x2 0x15 0x00 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x01 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x15 0x02 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x03 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x15 0x04 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x05 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x06 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x15 0x07 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x00 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x01 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x02 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x03 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x04 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x05 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x06 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x07 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "or-rid-detect-change",
+ "vpd-detect",
+ "cc-state-change",
+ "vconn-oc",
+ "vbus-change",
+ "attach-detach",
+ "legacy-cable-detect",
+ "try-snk-src-detect",
+ "sig-tx",
+ "sig-rx",
+ "msg-tx",
+ "msg-rx",
+ "msg-tx-failed",
+ "msg-tx-discarded",
+ "msg-rx-discarded",
+ "fr-swap";
+ vdd-vbus-supply = <&pm8150b_vbus>;
+ };
+
pm8150b_temp: temp-alarm@2400 {
compatible = "qcom,spmi-temp-alarm";
reg = <0x2400>;
diff --git a/arch/arm64/boot/dts/qcom/pm8150l.dtsi b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
index b1686e5777b8..ac08a09c64c2 100644
--- a/arch/arm64/boot/dts/qcom/pm8150l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
@@ -132,5 +132,15 @@
status = "disabled";
};
+ pm8150l_wled: leds@d800 {
+ compatible = "qcom,pm8150l-wled";
+ reg = <0xd800>, <0xd900>;
+ interrupts = <0x5 0xd8 0x1 IRQ_TYPE_EDGE_RISING>,
+ <0x5 0xd8 0x2 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "ovp", "short";
+ label = "backlight";
+
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm64/boot/dts/qcom/pm8350c.dtsi b/arch/arm64/boot/dts/qcom/pm8350c.dtsi
index f28e71487d5c..aa74e21fe0dc 100644
--- a/arch/arm64/boot/dts/qcom/pm8350c.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8350c.dtsi
@@ -30,6 +30,12 @@
#interrupt-cells = <2>;
};
+ pm8350c_flash: led-controller@ee00 {
+ compatible = "qcom,pm8350c-flash-led", "qcom,spmi-flash-led";
+ reg = <0xee00>;
+ status = "disabled";
+ };
+
pm8350c_pwm: pwm {
compatible = "qcom,pm8350c-pwm";
#pwm-cells = <2>;
diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi
index 223442f909f1..f4de86787743 100644
--- a/arch/arm64/boot/dts/qcom/pm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi
@@ -142,9 +142,6 @@
pm8916_codec: audio-codec@f000 {
compatible = "qcom,pm8916-wcd-analog-codec";
reg = <0xf000>;
- reg-names = "pmic-codec-core";
- clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>;
- clock-names = "mclk";
interrupt-parent = <&spmi_bus>;
interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
<0x1 0xf0 0x1 IRQ_TYPE_NONE>,
diff --git a/arch/arm64/boot/dts/qcom/pmr735d.dtsi b/arch/arm64/boot/dts/qcom/pmr735d_a.dtsi
index 41fb664a10b3..37daaefe3431 100644
--- a/arch/arm64/boot/dts/qcom/pmr735d.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmr735d_a.dtsi
@@ -28,27 +28,6 @@
};
};
};
-
- pmr735d-l-thermal {
- polling-delay-passive = <100>;
- polling-delay = <0>;
-
- thermal-sensors = <&pmr735d_l_temp_alarm>;
-
- trips {
- trip0 {
- temperature = <95000>;
- hysteresis = <0>;
- type = "passive";
- };
-
- trip1 {
- temperature = <115000>;
- hysteresis = <0>;
- type = "hot";
- };
- };
- };
};
};
@@ -77,28 +56,4 @@
#interrupt-cells = <2>;
};
};
-
- pmr735d_l: pmic@b {
- compatible = "qcom,pmr735d", "qcom,spmi-pmic";
- reg = <0xb SPMI_USID>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- pmr735d_l_temp_alarm: temp-alarm@a00 {
- compatible = "qcom,spmi-temp-alarm";
- reg = <0xa00>;
- interrupts = <0xb 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
- #thermal-sensor-cells = <0>;
- };
-
- pmr735d_l_gpios: gpio@8800 {
- compatible = "qcom,pmr735d-gpio", "qcom,spmi-gpio";
- reg = <0x8800>;
- gpio-controller;
- gpio-ranges = <&pmr735d_l_gpios 0 0 2>;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
- };
};
diff --git a/arch/arm64/boot/dts/qcom/pmr735d_b.dtsi b/arch/arm64/boot/dts/qcom/pmr735d_b.dtsi
new file mode 100644
index 000000000000..3b470f6ac46f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pmr735d_b.dtsi
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/spmi/spmi.h>
+
+/ {
+ thermal-zones {
+ pmr735d-l-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+
+ thermal-sensors = <&pmr735d_l_temp_alarm>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+ };
+ };
+ };
+};
+
+
+&spmi_bus {
+ pmr735d_l: pmic@b {
+ compatible = "qcom,pmr735d", "qcom,spmi-pmic";
+ reg = <0xb SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmr735d_l_temp_alarm: temp-alarm@a00 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0xa00>;
+ interrupts = <0xb 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ pmr735d_l_gpios: gpio@8800 {
+ compatible = "qcom,pmr735d-gpio", "qcom,spmi-gpio";
+ reg = <0x8800>;
+ gpio-controller;
+ gpio-ranges = <&pmr735d_l_gpios 0 0 2>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
new file mode 100644
index 000000000000..2de0b8c26c35
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
@@ -0,0 +1,667 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2023, Luca Weiss <luca.weiss@fairphone.com>
+ */
+
+/dts-v1/;
+
+/* PM7250B is configured to use SID8/9 */
+#define PM7250B_SID 8
+#define PM7250B_SID1 9
+
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include "sc7280.dtsi"
+#include "pm7250b.dtsi"
+#include "pm7325.dtsi"
+#include "pm8350c.dtsi" /* PM7350C */
+#include "pmk8350.dtsi" /* PMK7325 */
+
+/delete-node/ &rmtfs_mem;
+
+/ {
+ model = "Fairphone 5";
+ compatible = "fairphone,fp5", "qcom,qcm6490";
+ chassis-type = "handset";
+
+ aliases {
+ serial0 = &uart5;
+ serial1 = &uart7;
+ };
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ framebuffer0: framebuffer@a000000 {
+ compatible = "simple-framebuffer";
+ reg = <0x0 0xe1000000 0x0 (2700 * 1224 * 4)>;
+ width = <1224>;
+ height = <2700>;
+ stride = <(1224 * 4)>;
+ format = "a8r8g8b8";
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&volume_down_default>, <&hall_sensor_default>;
+ pinctrl-names = "default";
+
+ key-volume-up {
+ label = "Volume up";
+ gpios = <&pm7325_gpios 6 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ /* Powered by the always-on vreg_l8c */
+ event-hall-sensor {
+ label = "Hall Effect Sensor";
+ gpios = <&tlmm 155 GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_SW>;
+ linux,code = <SW_LID>;
+ linux,can-disable;
+ wakeup-source;
+ };
+ };
+
+ reserved-memory {
+ cont_splash_mem: cont-splash@e1000000 {
+ reg = <0x0 0xe1000000 0x0 0x2300000>;
+ no-map;
+ };
+
+ adsp_mem: adsp@86700000 {
+ reg = <0x0 0x86700000 0x0 0x2800000>;
+ no-map;
+ };
+
+ cdsp_mem: cdsp@88f00000 {
+ reg = <0x0 0x88f00000 0x0 0x1e00000>;
+ no-map;
+ };
+
+ mpss_mem: mpss@8b800000 {
+ reg = <0x0 0x8b800000 0x0 0xf600000>;
+ no-map;
+ };
+
+ wpss_mem: wpss@9ae00000 {
+ reg = <0x0 0x9ae00000 0x0 0x1900000>;
+ no-map;
+ };
+
+ rmtfs_mem: memory@f8500000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0x0 0xf8500000 0x0 0x600000>;
+ no-map;
+
+ qcom,client-id = <1>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>, <QCOM_SCM_VMID_NAV>;
+ };
+ };
+
+ ois_avdd0_1p8: regulator-ois-avdd0-1p8 {
+ compatible = "regulator-fixed";
+ regulator-name = "OIS_AVDD0_1P8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&tlmm 157 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&vreg_bob>;
+ };
+
+ ois_dvdd_1p1: regulator-ois-dvdd-1p1 {
+ compatible = "regulator-fixed";
+ regulator-name = "OIS_DVDD_1P1";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ gpio = <&tlmm 97 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&vreg_s8b>;
+ };
+
+ afvdd_2p8: regulator-afvdd-2p8 {
+ compatible = "regulator-fixed";
+ regulator-name = "AFVDD_2P8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ gpio = <&tlmm 68 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&vreg_bob>;
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm7325-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vreg_s1b: smps1 {
+ regulator-min-microvolt = <1840000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ vreg_s7b: smps7 {
+ regulator-min-microvolt = <535000>;
+ regulator-max-microvolt = <1120000>;
+ };
+
+ vreg_s8b: smps8 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_RET>;
+ };
+
+ vreg_l1b: ldo1 {
+ regulator-min-microvolt = <825000>;
+ regulator-max-microvolt = <925000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2b: ldo2 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3b: ldo3 {
+ regulator-min-microvolt = <312000>;
+ regulator-max-microvolt = <910000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6b: ldo6 {
+ regulator-min-microvolt = <1140000>;
+ regulator-max-microvolt = <1260000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7b: ldo7 {
+ regulator-min-microvolt = <2400000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8b: ldo8 {
+ regulator-min-microvolt = <870000>;
+ regulator-max-microvolt = <970000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9b: ldo9 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11b: ldo11 {
+ regulator-min-microvolt = <1504000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l12b: ldo12 {
+ regulator-min-microvolt = <751000>;
+ regulator-max-microvolt = <824000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13b: ldo13 {
+ regulator-min-microvolt = <530000>;
+ regulator-max-microvolt = <824000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14b: ldo14 {
+ regulator-min-microvolt = <1080000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l15b: ldo15 {
+ regulator-min-microvolt = <765000>;
+ regulator-max-microvolt = <1020000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l16b: ldo16 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l17b: ldo17 {
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1900000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l18b: ldo18 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l19b: ldo19 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm8350c-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vreg_s1c: smps1 {
+ regulator-min-microvolt = <2190000>;
+ regulator-max-microvolt = <2210000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s9c: smps9 {
+ regulator-min-microvolt = <1010000>;
+ regulator-max-microvolt = <1170000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1c: ldo1 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1980000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2c: ldo2 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1950000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3c: ldo3 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4c: ldo4 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5c: ldo5 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6c: ldo6 {
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7c: ldo7 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8c: ldo8 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ /* Hall sensor VDD */
+ regulator-always-on;
+ };
+
+ vreg_l9c: ldo9 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l10c: ldo10 {
+ regulator-min-microvolt = <720000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11c: ldo11 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l12c: ldo12 {
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13c: ldo13 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_bob: bob {
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+ };
+ };
+};
+
+&dispcc {
+ /* Disable for now so simple-framebuffer continues working */
+ status = "disabled";
+};
+
+&gcc {
+ protected-clocks = <GCC_CFG_NOC_LPASS_CLK>,
+ <GCC_EDP_CLKREF_EN>,
+ <GCC_MSS_CFG_AHB_CLK>,
+ <GCC_MSS_GPLL0_MAIN_DIV_CLK_SRC>,
+ <GCC_MSS_OFFLINE_AXI_CLK>,
+ <GCC_MSS_Q6SS_BOOT_CLK_SRC>,
+ <GCC_MSS_Q6_MEMNOC_AXI_CLK>,
+ <GCC_MSS_SNOC_AXI_CLK>,
+ <GCC_QSPI_CNOC_PERIPH_AHB_CLK>,
+ <GCC_QSPI_CORE_CLK>,
+ <GCC_QSPI_CORE_CLK_SRC>,
+ <GCC_SEC_CTRL_CLK_SRC>,
+ <GCC_WPSS_AHB_BDG_MST_CLK>,
+ <GCC_WPSS_AHB_CLK>,
+ <GCC_WPSS_RSCP_CLK>;
+};
+
+&gpi_dma0 {
+ status = "okay";
+};
+
+&gpi_dma1 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+
+ /* PM8008 PMIC @ 8 and 9 */
+ /* Pixelworks @ 26 */
+ /* FSA4480 USB audio switch @ 42 */
+ /* AW86927FCR haptics @ 5a */
+};
+
+&i2c2 {
+ status = "okay";
+
+ /* AW88261FCR amplifier @ 34 */
+ /* AW88261FCR amplifier @ 35 */
+};
+
+&i2c4 {
+ status = "okay";
+
+ /* PTN36502 USB redriver @ 1a */
+};
+
+&i2c9 {
+ status = "okay";
+
+ /* ST21NFC NFC @ 28 */
+ /* VL53L3 ToF @ 29 */
+};
+
+&ipa {
+ qcom,gsi-loader = "self";
+ memory-region = <&ipa_fw_mem>;
+ firmware-name = "qcom/qcm6490/fairphone5/ipa_fws.mdt";
+ status = "okay";
+};
+
+&pm7325_gpios {
+ volume_down_default: volume-down-default-state {
+ pins = "gpio6";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ power-source = <1>;
+ bias-pull-up;
+ input-enable;
+ };
+};
+
+&pm8350c_flash {
+ status = "okay";
+
+ led-0 {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ led-sources = <1>, <4>;
+ led-max-microamp = <500000>;
+ flash-max-microamp = <1500000>;
+ flash-max-timeout-us = <1280000>;
+ };
+};
+
+&pmk8350_rtc {
+ status = "okay";
+};
+
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&qup_spi13_cs {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&qup_spi13_data_clk {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&qup_uart5_rx {
+ drive-strength = <2>;
+ bias-disable;
+};
+
+&qup_uart5_tx {
+ drive-strength = <2>;
+ bias-disable;
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&sdc2_clk {
+ drive-strength = <16>;
+ bias-disable;
+};
+
+&sdc2_cmd {
+ drive-strength = <10>;
+ bias-pull-up;
+};
+
+&sdc2_data {
+ drive-strength = <10>;
+ bias-pull-up;
+};
+
+&sdhc_2 {
+ vmmc-supply = <&vreg_l9c>;
+ vqmmc-supply = <&vreg_l6c>;
+
+ pinctrl-0 = <&sdc2_clk>, <&sdc2_cmd>, <&sdc2_data>;
+ pinctrl-1 = <&sdc2_clk_sleep>, <&sdc2_cmd_sleep>, <&sdc2_data_sleep>;
+
+ status = "okay";
+};
+
+&spi13 {
+ status = "okay";
+
+ /* Goodix touchscreen @ 0 */
+};
+
+&tlmm {
+ /*
+ * 32-33: SMB1394 (SPMI)
+ * 56-59: fingerprint reader (SPI)
+ */
+ gpio-reserved-ranges = <32 2>, <56 4>;
+
+ bluetooth_enable_default: bluetooth-enable-default-state {
+ pins = "gpio85";
+ function = "gpio";
+ output-low;
+ bias-disable;
+ };
+
+ hall_sensor_default: hall-sensor-default-state {
+ pins = "gpio155";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_uart7_sleep_cts: qup-uart7-sleep-cts-state {
+ pins = "gpio28";
+ function = "gpio";
+ /*
+ * Configure a bias-bus-hold on CTS to lower power
+ * usage when Bluetooth is turned off. Bus hold will
+ * maintain a low power state regardless of whether
+ * the Bluetooth module drives the pin in either
+ * direction or leaves the pin fully unpowered.
+ */
+ bias-bus-hold;
+ };
+
+ qup_uart7_sleep_rts: qup-uart7-sleep-rts-state {
+ pins = "gpio29";
+ function = "gpio";
+ /*
+ * Configure pull-down on RTS. As RTS is active low
+ * signal, pull it low to indicate the BT SoC that it
+ * can wakeup the system anytime from suspend state by
+ * pulling RX low (by sending wakeup bytes).
+ */
+ bias-pull-down;
+ };
+
+ qup_uart7_sleep_tx: qup-uart7-sleep-tx-state {
+ pins = "gpio30";
+ function = "gpio";
+ /*
+ * Configure pull-up on TX when it isn't actively driven
+ * to prevent BT SoC from receiving garbage during sleep.
+ */
+ bias-pull-up;
+ };
+
+ qup_uart7_sleep_rx: qup-uart7-sleep-rx-state {
+ pins = "gpio31";
+ function = "gpio";
+ /*
+ * Configure a pull-up on RX. This is needed to avoid
+ * garbage data when the TX pin of the Bluetooth module
+ * is floating which may cause spurious wakeups.
+ */
+ bias-pull-up;
+ };
+
+ sw_ctrl_default: sw-ctrl-default-state {
+ pins = "gpio86";
+ function = "gpio";
+ bias-pull-down;
+ };
+};
+
+&uart5 {
+ compatible = "qcom,geni-debug-uart";
+ status = "okay";
+};
+
+&uart7 {
+ /delete-property/interrupts;
+ interrupts-extended = <&intc GIC_SPI 608 IRQ_TYPE_LEVEL_HIGH>,
+ <&tlmm 31 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-1 = <&qup_uart7_sleep_cts>, <&qup_uart7_sleep_rts>, <&qup_uart7_sleep_tx>, <&qup_uart7_sleep_rx>;
+ pinctrl-names = "default", "sleep";
+
+ status = "okay";
+
+ bluetooth: bluetooth {
+ compatible = "qcom,wcn6750-bt";
+
+ pinctrl-0 = <&bluetooth_enable_default>, <&sw_ctrl_default>;
+ pinctrl-names = "default";
+
+ enable-gpios = <&tlmm 85 GPIO_ACTIVE_HIGH>;
+ swctrl-gpios = <&tlmm 86 GPIO_ACTIVE_HIGH>;
+
+ vddio-supply = <&vreg_l19b>;
+ vddaon-supply = <&vreg_s7b>;
+ vddbtcxmx-supply = <&vreg_s7b>;
+ vddrfacmn-supply = <&vreg_s7b>;
+ vddrfa0p8-supply = <&vreg_s7b>;
+ vddrfa1p7-supply = <&vreg_s1b>;
+ vddrfa1p2-supply = <&vreg_s8b>;
+ vddrfa2p2-supply = <&vreg_s1c>;
+ vddasd-supply = <&vreg_l11c>;
+
+ max-speed = <3200000>;
+ };
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "peripheral";
+};
+
+&usb_1_hsphy {
+ vdda-pll-supply = <&vreg_l10c>;
+ vdda18-supply = <&vreg_l1c>;
+ vdda33-supply = <&vreg_l2b>;
+
+ qcom,hs-crossover-voltage-microvolt = <28000>;
+ qcom,hs-output-impedance-micro-ohms = <2600000>;
+ qcom,hs-rise-fall-time-bp = <5430>;
+ qcom,hs-disconnect-bp = <1743>;
+ qcom,hs-amplitude-bp = <2430>;
+
+ qcom,pre-emphasis-amplitude-bp = <20000>;
+ qcom,pre-emphasis-duration-bp = <20000>;
+
+ qcom,squelch-detector-bp = <(-2090)>;
+
+ status = "okay";
+};
+
+&usb_1_qmpphy {
+ vdda-phy-supply = <&vreg_l6b>;
+ vdda-pll-supply = <&vreg_l1b>;
+
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
index eadba066972e..94885b9c21c8 100644
--- a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
+++ b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
@@ -5,6 +5,7 @@
/dts-v1/;
+#include <dt-bindings/leds/common.h>
#include "qcm2290.dtsi"
#include "pm2250.dtsi"
@@ -13,7 +14,7 @@
compatible = "qcom,qrb2210-rb1", "qcom,qrb2210", "qcom,qcm2290";
aliases {
- serial0 = &uart0;
+ serial0 = &uart4;
sdhc1 = &sdhc_1;
sdhc2 = &sdhc_2;
};
@@ -39,6 +40,38 @@
};
};
+ leds {
+ compatible = "gpio-leds";
+
+ led-bt {
+ label = "blue:bt";
+ function = LED_FUNCTION_BLUETOOTH;
+ color = <LED_COLOR_ID_BLUE>;
+ gpios = <&tlmm 45 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "bluetooth-power";
+ default-state = "off";
+ };
+
+ led-user0 {
+ label = "green:user0";
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&tlmm 52 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "none";
+ default-state = "off";
+ panic-indicator;
+ };
+
+ led-wlan {
+ label = "yellow:wlan";
+ function = LED_FUNCTION_WLAN;
+ color = <LED_COLOR_ID_YELLOW>;
+ gpios = <&tlmm 47 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "phy0tx";
+ default-state = "off";
+ };
+ };
+
vreg_hdmi_out_1p2: regulator-hdmi-out-1p2 {
compatible = "regulator-fixed";
regulator-name = "VREG_HDMI_OUT_1P2";
@@ -134,6 +167,16 @@
status = "okay";
};
+&remoteproc_adsp {
+ firmware-name = "qcom/qcm2290/adsp.mbn";
+ status = "okay";
+};
+
+&remoteproc_mpss {
+ firmware-name = "qcom/qcm2290/modem.mbn";
+ status = "okay";
+};
+
&rpm_requests {
regulators {
compatible = "qcom,rpm-pm2250-regulators";
@@ -150,15 +193,15 @@
pm2250_s3: s3 {
/* 0.4V-1.6625V -> 1.3V (Power tree requirements) */
- regulator-min-microvolts = <1350000>;
- regulator-max-microvolts = <1350000>;
+ regulator-min-microvolt = <1352000>;
+ regulator-max-microvolt = <1352000>;
regulator-boot-on;
};
pm2250_s4: s4 {
/* 1.2V-2.35V -> 2.05V (Power tree requirements) */
- regulator-min-microvolts = <2072000>;
- regulator-max-microvolts = <2072000>;
+ regulator-min-microvolt = <2072000>;
+ regulator-max-microvolt = <2072000>;
regulator-boot-on;
};
@@ -166,47 +209,47 @@
pm2250_l2: l2 {
/* LPDDR4X VDD2 */
- regulator-min-microvolts = <1136000>;
- regulator-max-microvolts = <1136000>;
+ regulator-min-microvolt = <1136000>;
+ regulator-max-microvolt = <1136000>;
regulator-always-on;
regulator-boot-on;
};
pm2250_l3: l3 {
/* LPDDR4X VDDQ */
- regulator-min-microvolts = <616000>;
- regulator-max-microvolts = <616000>;
+ regulator-min-microvolt = <616000>;
+ regulator-max-microvolt = <616000>;
regulator-always-on;
regulator-boot-on;
};
pm2250_l4: l4 {
- /* max = 3.05V -> max = just below 3V (SDHCI2) */
- regulator-min-microvolts = <1648000>;
- regulator-max-microvolts = <2992000>;
+ /* max = 3.05V -> max = 2.7 to disable 3V signaling (SDHCI2) */
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2700000>;
regulator-allow-set-load;
};
pm2250_l5: l5 {
/* CSI/DSI */
- regulator-min-microvolts = <1232000>;
- regulator-max-microvolts = <1232000>;
+ regulator-min-microvolt = <1232000>;
+ regulator-max-microvolt = <1232000>;
regulator-allow-set-load;
regulator-boot-on;
};
pm2250_l6: l6 {
/* DRAM PLL */
- regulator-min-microvolts = <928000>;
- regulator-max-microvolts = <928000>;
+ regulator-min-microvolt = <928000>;
+ regulator-max-microvolt = <928000>;
regulator-always-on;
regulator-boot-on;
};
pm2250_l7: l7 {
/* Wi-Fi CX/MX */
- regulator-min-microvolts = <664000>;
- regulator-max-microvolts = <664000>;
+ regulator-min-microvolt = <664000>;
+ regulator-max-microvolt = <664000>;
};
/*
@@ -216,37 +259,37 @@
pm2250_l10: l10 {
/* Wi-Fi RFA */
- regulator-min-microvolts = <1300000>;
- regulator-max-microvolts = <1300000>;
+ regulator-min-microvolt = <1304000>;
+ regulator-max-microvolt = <1304000>;
};
pm2250_l11: l11 {
/* GPS RF1 */
- regulator-min-microvolts = <1000000>;
- regulator-max-microvolts = <1000000>;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
regulator-boot-on;
};
pm2250_l12: l12 {
/* USB PHYs */
- regulator-min-microvolts = <928000>;
- regulator-max-microvolts = <928000>;
+ regulator-min-microvolt = <928000>;
+ regulator-max-microvolt = <928000>;
regulator-allow-set-load;
regulator-boot-on;
};
pm2250_l13: l13 {
/* USB/QFPROM/PLLs */
- regulator-min-microvolts = <1800000>;
- regulator-max-microvolts = <1800000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
regulator-allow-set-load;
regulator-boot-on;
};
pm2250_l14: l14 {
/* SDHCI1 VQMMC */
- regulator-min-microvolts = <1800000>;
- regulator-max-microvolts = <1800000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
regulator-allow-set-load;
/* Broken hardware, never turn it off! */
regulator-always-on;
@@ -254,8 +297,8 @@
pm2250_l15: l15 {
/* WCD/DSI/BT VDDIO */
- regulator-min-microvolts = <1800000>;
- regulator-max-microvolts = <1800000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
regulator-allow-set-load;
regulator-always-on;
regulator-boot-on;
@@ -263,47 +306,47 @@
pm2250_l16: l16 {
/* GPS RF2 */
- regulator-min-microvolts = <1800000>;
- regulator-max-microvolts = <1800000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
regulator-boot-on;
};
pm2250_l17: l17 {
- regulator-min-microvolts = <3000000>;
- regulator-max-microvolts = <3000000>;
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
};
pm2250_l18: l18 {
/* VDD_PXn */
- regulator-min-microvolts = <1800000>;
- regulator-max-microvolts = <1800000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
};
pm2250_l19: l19 {
/* VDD_PXn */
- regulator-min-microvolts = <1800000>;
- regulator-max-microvolts = <1800000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
};
pm2250_l20: l20 {
/* SDHCI1 VMMC */
- regulator-min-microvolts = <2856000>;
- regulator-max-microvolts = <2856000>;
+ regulator-min-microvolt = <2400000>;
+ regulator-max-microvolt = <3600000>;
regulator-allow-set-load;
};
pm2250_l21: l21 {
/* SDHCI2 VMMC */
- regulator-min-microvolts = <2960000>;
- regulator-max-microvolts = <3300000>;
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <3300000>;
regulator-allow-set-load;
regulator-boot-on;
};
pm2250_l22: l22 {
/* Wi-Fi */
- regulator-min-microvolts = <3312000>;
- regulator-max-microvolts = <3312000>;
+ regulator-min-microvolt = <3312000>;
+ regulator-max-microvolt = <3312000>;
};
};
};
@@ -357,7 +400,7 @@
};
/* UART connected to the Micro-USB port via a FTDI chip */
-&uart0 {
+&uart4 {
compatible = "qcom,geni-debug-uart";
status = "okay";
};
@@ -366,6 +409,12 @@
status = "okay";
};
+&usb_qmpphy {
+ vdda-phy-supply = <&pm2250_l12>;
+ vdda-pll-supply = <&pm2250_l13>;
+ status = "okay";
+};
+
&usb_hsphy {
vdd-supply = <&pm2250_l12>;
vdda-pll-supply = <&pm2250_l13>;
@@ -373,6 +422,14 @@
status = "okay";
};
+&wifi {
+ vdd-0.8-cx-mx-supply = <&pm2250_l7>;
+ vdd-1.8-xo-supply = <&pm2250_l13>;
+ vdd-1.3-rfa-supply = <&pm2250_l10>;
+ vdd-3.3-ch0-supply = <&pm2250_l22>;
+ status = "okay";
+};
+
&xo_board {
clock-frequency = <38400000>;
};
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
index dfa8ee5c75af..c8cd40a462a3 100644
--- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
+++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
@@ -9,6 +9,7 @@
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/usb/pd.h>
#include "sm8250.dtsi"
#include "pm8150.dtsi"
#include "pm8150b.dtsi"
@@ -609,12 +610,61 @@
/* LS-I2C1 */
&i2c15 {
status = "okay";
+
+ typec-mux@1c {
+ compatible = "onnn,nb7vpq904m";
+ reg = <0x1c>;
+
+ vcc-supply = <&vreg_s4a_1p8>;
+
+ retimer-switch;
+ orientation-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ redriver_usb_con_ss: endpoint {
+ remote-endpoint = <&pm8150b_typec_mux_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ redriver_phy_con_ss: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_out>;
+ data-lanes = <0 1 2 3>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ redriver_usb_con_sbu: endpoint {
+ remote-endpoint = <&pm8150b_typec_sbu_out>;
+ };
+ };
+ };
+ };
};
&mdss {
status = "okay";
};
+&mdss_dp {
+ status = "okay";
+};
+
+&mdss_dp_out {
+ data-lanes = <0 1>;
+ remote-endpoint = <&usb_1_qmpphy_dp_in>;
+};
+
&mdss_dsi0 {
status = "okay";
vdda-supply = <&vreg_l9a_1p2>;
@@ -1273,7 +1323,12 @@
};
&usb_1_dwc3 {
- dr_mode = "peripheral";
+ dr_mode = "otg";
+ usb-role-switch;
+};
+
+&usb_1_role_switch_out {
+ remote-endpoint = <&pm8150b_role_switch_in>;
};
&usb_1_hsphy {
@@ -1289,6 +1344,11 @@
vdda-phy-supply = <&vreg_l9a_1p2>;
vdda-pll-supply = <&vreg_l18a_0p92>;
+ orientation-switch;
+};
+
+&usb_1_qmpphy_out {
+ remote-endpoint = <&redriver_phy_con_ss>;
};
&usb_2 {
@@ -1339,3 +1399,66 @@
drive-strength = <6>;
bias-disable;
};
+
+&pm8150b_vbus {
+ regulator-min-microamp = <500000>;
+ regulator-max-microamp = <3000000>;
+ status = "okay";
+};
+
+&pm8150b_typec {
+ status = "okay";
+
+ vdd-pdphy-supply = <&vreg_l2a_3p1>;
+
+ connector {
+ compatible = "usb-c-connector";
+
+ power-role = "source";
+ data-role = "dual";
+ self-powered;
+
+ source-pdos = <PDO_FIXED(5000, 3000,
+ PDO_FIXED_DUAL_ROLE |
+ PDO_FIXED_USB_COMM |
+ PDO_FIXED_DATA_SWAP)>;
+
+ altmodes {
+ displayport {
+ svid = <0xff01>;
+ vdo = <0x00001c46>;
+ };
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ pm8150b_role_switch_in: endpoint {
+ remote-endpoint = <&usb_1_role_switch_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ pm8150b_typec_mux_in: endpoint {
+ remote-endpoint = <&redriver_usb_con_ss>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ pm8150b_typec_sbu_out: endpoint {
+ remote-endpoint = <&redriver_usb_con_sbu>;
+ };
+ };
+ };
+ };
+};
+
+&usb_1_qmpphy_dp_in {
+ remote-endpoint = <&mdss_dp_out>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi b/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi
index 3c3b6287cd27..eaa43f022a65 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi
@@ -173,7 +173,7 @@
compatible = "qcom,pmm8654au-gpio", "qcom,spmi-gpio";
reg = <0x8800>;
gpio-controller;
- gpio-ranges = <&pmm8654au_2_gpios 0 0 12>;
+ gpio-ranges = <&pmm8654au_1_gpios 0 0 12>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride.dts b/arch/arm64/boot/dts/qcom/sa8775p-ride.dts
index 81a7eeb9cfcd..9760bb4b468c 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p-ride.dts
+++ b/arch/arm64/boot/dts/qcom/sa8775p-ride.dts
@@ -285,6 +285,7 @@
compatible = "ethernet-phy-id0141.0dd4";
reg = <0x8>;
device_type = "ethernet-phy";
+ interrupts-extended = <&tlmm 7 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&pmm8654au_2_gpios 8 GPIO_ACTIVE_LOW>;
reset-assert-us = <11000>;
reset-deassert-us = <70000>;
@@ -294,6 +295,7 @@
compatible = "ethernet-phy-id0141.0dd4";
reg = <0xa>;
device_type = "ethernet-phy";
+ interrupts-extended = <&tlmm 26 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&pmm8654au_2_gpios 9 GPIO_ACTIVE_LOW>;
reset-assert-us = <11000>;
reset-deassert-us = <70000>;
diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
index 9f4f58e831a4..b6a93b11cbbd 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
@@ -1525,6 +1525,7 @@
<0 0>,
<0 0>,
<0 0>;
+ qcom,ice = <&ice>;
status = "disabled";
};
@@ -1546,6 +1547,13 @@
status = "disabled";
};
+ ice: crypto@1d88000 {
+ compatible = "qcom,sa8775p-inline-crypto-engine",
+ "qcom,inline-crypto-engine";
+ reg = <0x0 0x01d88000 0x0 0x8000>;
+ clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
+ };
+
usb_0_hsphy: phy@88e4000 {
compatible = "qcom,sa8775p-usb-hs-phy",
"qcom,usb-snps-hs-5nm-phy";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
index a532cc4aac47..7765c8f64905 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
@@ -10,7 +10,6 @@
/* Deleted nodes from sc7180-trogdor.dtsi */
-/delete-node/ &alc5682;
/delete-node/ &pp3300_codec;
/ {
@@ -104,6 +103,7 @@ ap_ts_pen_1v8: &i2c4 {
interrupt-parent = <&tlmm>;
interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ panel = <&panel>;
reset-gpios = <&tlmm 8 GPIO_ACTIVE_LOW>;
vdd-supply = <&pp3300_ts>;
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
index b27dcd2ec856..2ba3bbf3b9ad 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
@@ -7,6 +7,8 @@
/* This file must be included after sc7180-trogdor.dtsi */
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
+
/ {
/* BOARD-SPECIFIC TOP LEVEL NODES */
@@ -116,6 +118,7 @@ ap_ts_pen_1v8: &i2c4 {
interrupt-parent = <&tlmm>;
interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ panel = <&panel>;
reset-gpios = <&tlmm 8 GPIO_ACTIVE_LOW>;
vdd-supply = <&pp3300_touch>;
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dts
index 36326ef972dc..d6db7d83adcf 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dts
@@ -11,19 +11,13 @@
#include "sc7180-trogdor-parade-ps8640.dtsi"
#include <arm/cros-ec-keyboard.dtsi>
#include "sc7180-trogdor-lte-sku.dtsi"
+#include "sc7180-trogdor-rt5682s-sku.dtsi"
/ {
model = "Google Kingoftown";
compatible = "google,kingoftown", "qcom,sc7180";
};
-&alc5682 {
- compatible = "realtek,rt5682s";
- /delete-property/ VBAT-supply;
- realtek,dmic1-clk-pin = <2>;
- realtek,dmic-clk-rate-hz = <2048000>;
-};
-
&ap_tp_i2c {
status = "okay";
};
@@ -84,11 +78,6 @@ ap_ts_pen_1v8: &i2c4 {
gpio = <&tlmm 67 GPIO_ACTIVE_HIGH>;
};
-&sound {
- compatible = "google,sc7180-trogdor";
- model = "sc7180-rt5682s-max98357a-1mic";
-};
-
&wifi {
qcom,ath10k-calibration-variant = "GO_KINGOFTOWN";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r10.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r10.dts
new file mode 100644
index 000000000000..eba15535e1c7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r10.dts
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Lazor Limozeen board device tree source
+ *
+ * Copyright 2023 Google LLC.
+ */
+
+/dts-v1/;
+
+#include "sc7180-trogdor.dtsi"
+#include "sc7180-trogdor-parade-ps8640.dtsi"
+#include "sc7180-trogdor-lazor.dtsi"
+#include "sc7180-trogdor-lte-sku.dtsi"
+#include "sc7180-trogdor-rt5682s-sku.dtsi"
+
+/ {
+ model = "Google Lazor Limozeen without Touchscreen (rev10+)";
+ compatible = "google,lazor-sku6", "google,lazor-sku18", "qcom,sc7180";
+};
+
+/delete-node/ &ap_ts;
+
+&panel {
+ compatible = "edp-panel";
+};
+
+&sdhc_2 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r5.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r5.dts
index 7f01573b5543..e7da0d6e8ef5 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r5.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r5.dts
@@ -11,6 +11,7 @@
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
#include "sc7180-trogdor-lazor.dtsi"
#include "sc7180-trogdor-lte-sku.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/ {
model = "Google Lazor Limozeen without Touchscreen (rev5 - rev8)";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r9.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r9.dts
index 913b5fc3ba76..a609a2651549 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r9.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r9.dts
@@ -11,13 +11,14 @@
#include "sc7180-trogdor-parade-ps8640.dtsi"
#include "sc7180-trogdor-lazor.dtsi"
#include "sc7180-trogdor-lte-sku.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/ {
- model = "Google Lazor Limozeen without Touchscreen (rev9+)";
- compatible = "google,lazor-sku6", "qcom,sc7180";
+ model = "Google Lazor Limozeen without Touchscreen (rev9)";
+ compatible = "google,lazor-rev9-sku6", "google,lazor-rev9-sku18", "qcom,sc7180";
};
-/delete-node/&ap_ts;
+/delete-node/ &ap_ts;
&panel {
compatible = "edp-panel";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r10.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r10.dts
new file mode 100644
index 000000000000..5cc7c0d8e70b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r10.dts
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Lazor Limozeen board device tree source
+ *
+ * Copyright 2023 Google LLC.
+ */
+
+/dts-v1/;
+
+#include "sc7180-trogdor.dtsi"
+#include "sc7180-trogdor-parade-ps8640.dtsi"
+#include "sc7180-trogdor-lazor.dtsi"
+#include "sc7180-trogdor-lte-sku.dtsi"
+#include "sc7180-trogdor-rt5682s-sku.dtsi"
+
+/ {
+ model = "Google Lazor Limozeen (rev10+)";
+ compatible = "google,lazor-sku4", "google,lazor-sku15", "qcom,sc7180";
+};
+
+/delete-node/ &ap_ts;
+
+&ap_ts_pen_1v8 {
+ ap_ts: touchscreen@10 {
+ compatible = "elan,ekth3500";
+ reg = <0x10>;
+ pinctrl-0 = <&ts_int_l>, <&ts_reset_l>;
+ pinctrl-names = "default";
+
+ interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&tlmm>;
+
+ vcc33-supply = <&pp3300_ts>;
+
+ reset-gpios = <&tlmm 8 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&panel {
+ compatible = "auo,b116xa01";
+};
+
+&sdhc_2 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r4.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r4.dts
index d42dcd421146..8a24812b9a00 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r4.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r4.dts
@@ -11,6 +11,8 @@
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
#include "sc7180-trogdor-lazor.dtsi"
#include "sc7180-trogdor-lte-sku.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
+
/ {
model = "Google Lazor Limozeen (rev4 - rev8)";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r9.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r9.dts
index 15d77dc5f956..dd377209dec3 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r9.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-r9.dts
@@ -11,23 +11,24 @@
#include "sc7180-trogdor-parade-ps8640.dtsi"
#include "sc7180-trogdor-lazor.dtsi"
#include "sc7180-trogdor-lte-sku.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/ {
- model = "Google Lazor Limozeen (rev9+)";
- compatible = "google,lazor-sku4", "qcom,sc7180";
+ model = "Google Lazor Limozeen (rev9)";
+ compatible = "google,lazor-rev9-sku4", "google,lazor-rev9-sku15", "qcom,sc7180";
};
-/delete-node/&ap_ts;
+/delete-node/ &ap_ts;
&ap_ts_pen_1v8 {
ap_ts: touchscreen@10 {
compatible = "elan,ekth3500";
reg = <0x10>;
- pinctrl-names = "default";
pinctrl-0 = <&ts_int_l>, <&ts_reset_l>;
+ pinctrl-names = "default";
- interrupt-parent = <&tlmm>;
interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&tlmm>;
vcc33-supply = <&pp3300_ts>;
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1.dts
index 80c7108bc51b..b60060a38426 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1.dts
@@ -10,6 +10,7 @@
#include "sc7180-trogdor.dtsi"
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
#include "sc7180-trogdor-lazor.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/ {
model = "Google Lazor (rev1 - 2)";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-kb.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-kb.dts
new file mode 100644
index 000000000000..45d34718a1bc
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-kb.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Lazor board device tree source
+ *
+ * Copyright 2023 Google LLC.
+ */
+
+/dts-v1/;
+
+#include "sc7180-trogdor.dtsi"
+#include "sc7180-trogdor-parade-ps8640.dtsi"
+#include "sc7180-trogdor-lazor.dtsi"
+#include "sc7180-lite.dtsi"
+#include "sc7180-trogdor-rt5682s-sku.dtsi"
+
+/ {
+ model = "Google Lazor (rev10+) with KB Backlight";
+ compatible = "google,lazor-sku2", "qcom,sc7180";
+};
+
+&keyboard_backlight {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-lte.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-lte.dts
new file mode 100644
index 000000000000..79028d0dd1b0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-lte.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Lazor board device tree source
+ *
+ * Copyright 2023 Google LLC.
+ */
+
+/dts-v1/;
+
+#include "sc7180-trogdor.dtsi"
+#include "sc7180-trogdor-parade-ps8640.dtsi"
+#include "sc7180-trogdor-lazor.dtsi"
+#include "sc7180-trogdor-lte-sku.dtsi"
+#include "sc7180-trogdor-rt5682s-sku.dtsi"
+
+/ {
+ model = "Google Lazor (rev10+) with LTE";
+ compatible = "google,lazor-sku0", "google,lazor-sku10", "qcom,sc7180";
+};
+
+&ap_sar_sensor_i2c {
+ status = "okay";
+};
+
+&keyboard_backlight {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10.dts
new file mode 100644
index 000000000000..045827341ea0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Lazor board device tree source
+ *
+ * Copyright 2023 Google LLC.
+ */
+
+/dts-v1/;
+
+#include "sc7180-trogdor.dtsi"
+#include "sc7180-trogdor-parade-ps8640.dtsi"
+#include "sc7180-trogdor-lazor.dtsi"
+#include "sc7180-lite.dtsi"
+#include "sc7180-trogdor-rt5682s-sku.dtsi"
+
+/ {
+ model = "Google Lazor (rev10+)";
+ compatible = "google,lazor", "qcom,sc7180";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-kb.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-kb.dts
index 6ff81c1f7c44..3459b81c5628 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-kb.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-kb.dts
@@ -10,6 +10,7 @@
#include "sc7180-trogdor.dtsi"
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
#include "sc7180-trogdor-lazor.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
#include "sc7180-lite.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-lte.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-lte.dts
index e58e36e35950..ff8f47da109d 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-lte.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-lte.dts
@@ -11,6 +11,7 @@
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
#include "sc7180-trogdor-lazor.dtsi"
#include "sc7180-trogdor-lte-sku.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/ {
model = "Google Lazor (rev3 - 8) with LTE";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3.dts
index 76c83f88cb41..dd8f6d95655e 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3.dts
@@ -10,6 +10,7 @@
#include "sc7180-trogdor.dtsi"
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
#include "sc7180-trogdor-lazor.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
#include "sc7180-lite.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-kb.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-kb.dts
index 960f7b7ce094..faf527972977 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-kb.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-kb.dts
@@ -10,11 +10,12 @@
#include "sc7180-trogdor.dtsi"
#include "sc7180-trogdor-parade-ps8640.dtsi"
#include "sc7180-trogdor-lazor.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
#include "sc7180-lite.dtsi"
/ {
- model = "Google Lazor (rev9+) with KB Backlight";
- compatible = "google,lazor-sku2", "qcom,sc7180";
+ model = "Google Lazor (rev9) with KB Backlight";
+ compatible = "google,lazor-rev9-sku2", "qcom,sc7180";
};
&keyboard_backlight {
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-lte.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-lte.dts
index 38027f13b9d0..d737fd0637fb 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-lte.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-lte.dts
@@ -11,10 +11,11 @@
#include "sc7180-trogdor-parade-ps8640.dtsi"
#include "sc7180-trogdor-lazor.dtsi"
#include "sc7180-trogdor-lte-sku.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/ {
- model = "Google Lazor (rev9+) with LTE";
- compatible = "google,lazor-sku0", "qcom,sc7180";
+ model = "Google Lazor (rev9) with LTE";
+ compatible = "google,lazor-rev9-sku0", "google,lazor-rev9-sku10", "qcom,sc7180";
};
&ap_sar_sensor_i2c {
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9.dts
index 56dd222650d3..8daad32ff53b 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9.dts
@@ -10,9 +10,10 @@
#include "sc7180-trogdor.dtsi"
#include "sc7180-trogdor-parade-ps8640.dtsi"
#include "sc7180-trogdor-lazor.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
#include "sc7180-lite.dtsi"
/ {
- model = "Google Lazor (rev9+)";
- compatible = "google,lazor", "qcom,sc7180";
+ model = "Google Lazor (rev9)";
+ compatible = "google,lazor-rev9", "qcom,sc7180";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi
index 13339b723a93..e9f213d27711 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi
@@ -43,6 +43,7 @@ ap_ts_pen_1v8: &i2c4 {
interrupt-parent = <&tlmm>;
interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ panel = <&panel>;
post-power-on-delay-ms = <20>;
hid-descr-addr = <0x0001>;
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-lte-parade.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-lte-parade.dts
index 767cb7450c0d..1c3d9f1381ca 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-lte-parade.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-lte-parade.dts
@@ -11,6 +11,7 @@
#include "sc7180-trogdor-parade-ps8640.dtsi"
#include "sc7180-trogdor-pazquel.dtsi"
#include "sc7180-trogdor-lte-sku.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/ {
model = "Google Pazquel (Parade,LTE)";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-lte-ti.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-lte-ti.dts
index 9145b74e9009..bf170471b00c 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-lte-ti.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-lte-ti.dts
@@ -11,6 +11,7 @@
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
#include "sc7180-trogdor-pazquel.dtsi"
#include "sc7180-trogdor-lte-sku.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/ {
model = "Google Pazquel (TI,LTE)";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-parade.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-parade.dts
index 9a0e6632a786..60ae129b83c9 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-parade.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-parade.dts
@@ -10,6 +10,7 @@
#include "sc7180-trogdor.dtsi"
#include "sc7180-trogdor-parade-ps8640.dtsi"
#include "sc7180-trogdor-pazquel.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/ {
model = "Google Pazquel (Parade)";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-ti.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-ti.dts
index 47c5970d8c22..31678a98ce2c 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-ti.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel-ti.dts
@@ -10,6 +10,7 @@
#include "sc7180-trogdor.dtsi"
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
#include "sc7180-trogdor-pazquel.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/ {
model = "Google Pazquel (TI)";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360.dtsi
index 273e2249f018..89034b6702f4 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360.dtsi
@@ -7,13 +7,7 @@
/* This file must be included after sc7180-trogdor.dtsi */
#include "sc7180-trogdor-pazquel.dtsi"
-
-&alc5682 {
- compatible = "realtek,rt5682s";
- realtek,dmic1-clk-pin = <2>;
- realtek,dmic-clk-rate-hz = <2048000>;
- /delete-property/ VBAT-supply;
-};
+#include "sc7180-trogdor-rt5682s-sku.dtsi"
ap_ts_pen_1v8: &i2c4 {
clock-frequency = <400000>;
@@ -64,11 +58,6 @@ ap_ts_pen_1v8: &i2c4 {
>;
};
-&sound {
- compatible = "google,sc7180-trogdor";
- model = "sc7180-rt5682s-max98357a-1mic";
-};
-
&wifi {
qcom,ath10k-calibration-variant = "GO_PAZQUEL360";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi
index fd944842dd6c..0be62331f982 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi
@@ -8,6 +8,7 @@
#include "sc7180-trogdor.dtsi"
/* Must come after sc7180-trogdor.dtsi to modify cros_ec */
#include <arm/cros-ec-keyboard.dtsi>
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
/ {
@@ -102,6 +103,7 @@ ap_ts_pen_1v8: &i2c4 {
interrupt-parent = <&tlmm>;
interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ panel = <&panel>;
post-power-on-delay-ms = <20>;
hid-descr-addr = <0x0001>;
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi
index 62ab6427dd65..5f06842c683b 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi
@@ -8,6 +8,7 @@
/dts-v1/;
#include "sc7180-trogdor.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/* This board only has 1 USB Type-C port. */
/delete-node/ &usb_c1;
@@ -69,6 +70,7 @@
interrupt-parent = <&tlmm>;
interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ panel = <&panel>;
post-power-on-delay-ms = <20>;
hid-descr-addr = <0x0001>;
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts
index 671b3691f1bb..c9667751a990 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts
@@ -10,6 +10,7 @@
#include "sc7180-trogdor.dtsi"
/* Must come after sc7180-trogdor.dtsi to modify cros_ec */
#include <arm/cros-ec-keyboard.dtsi>
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-rt5682i-sku.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-rt5682i-sku.dtsi
new file mode 100644
index 000000000000..26f2f5de489c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-rt5682i-sku.dtsi
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Trogdor dts fragment for SKUs with rt5682i
+ *
+ * Copyright 2023 Google LLC.
+ */
+
+&hp_i2c {
+ alc5682: codec@1a {
+ compatible = "realtek,rt5682i";
+ reg = <0x1a>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_irq>;
+
+ #sound-dai-cells = <1>;
+
+ interrupt-parent = <&tlmm>;
+ /*
+ * This will get ignored because the interrupt type
+ * is set in rt5682.c.
+ */
+ interrupts = <28 IRQ_TYPE_EDGE_BOTH>;
+
+ AVDD-supply = <&pp1800_alc5682>;
+ DBVDD-supply = <&pp1800_alc5682>;
+ LDO1-IN-supply = <&pp1800_alc5682>;
+ MICVDD-supply = <&pp3300_codec>;
+ VBAT-supply = <&pp3300_audio>;
+
+ realtek,dmic1-data-pin = <1>;
+ realtek,dmic1-clk-pin = <1>;
+ realtek,jd-src = <1>;
+ };
+};
+
+&sound {
+ model = "sc7180-rt5682-max98357a-1mic";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-rt5682s-sku.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-rt5682s-sku.dtsi
new file mode 100644
index 000000000000..ea036a73f875
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-rt5682s-sku.dtsi
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Trogdor dts fragment for SKUs with rt5682s
+ *
+ * Copyright 2023 Google LLC.
+ */
+
+&hp_i2c {
+ alc5682: codec@1a {
+ compatible = "realtek,rt5682s";
+ reg = <0x1a>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_irq>;
+
+ #sound-dai-cells = <1>;
+
+ interrupt-parent = <&tlmm>;
+ /*
+ * This will get ignored because the interrupt type
+ * is set in rt5682.c.
+ */
+ interrupts = <28 IRQ_TYPE_EDGE_BOTH>;
+
+ AVDD-supply = <&pp1800_alc5682>;
+ DBVDD-supply = <&pp1800_alc5682>;
+ LDO1-IN-supply = <&pp1800_alc5682>;
+ MICVDD-supply = <&pp3300_codec>;
+
+ realtek,dmic1-data-pin = <1>;
+ realtek,dmic1-clk-pin = <2>;
+ realtek,dmic-clk-rate-hz = <2048000>;
+ realtek,jd-src = <1>;
+ };
+};
+
+&sound {
+ model = "sc7180-rt5682s-max98357a-1mic";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe-rt5682s.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe-rt5682s.dts
index 6225ab8329c3..116f79c25a5d 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe-rt5682s.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe-rt5682s.dts
@@ -10,21 +10,20 @@
/dts-v1/;
-#include "sc7180-trogdor-wormdingler-rev1-boe.dts"
+#include "sc7180-trogdor-wormdingler.dtsi"
+#include "sc7180-trogdor-rt5682s-sku.dtsi"
/ {
model = "Google Wormdingler rev1+ (BOE, rt5682s)";
compatible = "google,wormdingler-sku1025", "qcom,sc7180";
};
-&alc5682 {
- compatible = "realtek,rt5682s";
- /delete-property/ VBAT-supply;
- realtek,dmic1-clk-pin = <2>;
- realtek,dmic-clk-rate-hz = <2048000>;
+&mdss_dsi0_phy {
+ qcom,phy-rescode-offset-top = /bits/ 8 <31 31 31 31 (-32)>;
+ qcom,phy-rescode-offset-bot = /bits/ 8 <31 31 31 31 (-32)>;
+ qcom,phy-drive-ldo-level = <450>;
};
-&sound {
- compatible = "google,sc7180-trogdor";
- model = "sc7180-rt5682s-max98357a-1mic";
+&panel {
+ compatible = "boe,tv110c9m-ll3";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe.dts
index 6eeead70d3eb..72627760e2a4 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe.dts
@@ -11,6 +11,7 @@
/dts-v1/;
#include "sc7180-trogdor-wormdingler.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/ {
model = "Google Wormdingler rev1+ BOE panel board";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx-rt5682s.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx-rt5682s.dts
index b40b068dad6a..0bf355e08f78 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx-rt5682s.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx-rt5682s.dts
@@ -10,21 +10,14 @@
/dts-v1/;
-#include "sc7180-trogdor-wormdingler-rev1-inx.dts"
+#include "sc7180-trogdor-wormdingler.dtsi"
+#include "sc7180-trogdor-rt5682s-sku.dtsi"
/ {
model = "Google Wormdingler rev1+ (INX, rt5682s)";
compatible = "google,wormdingler-sku1", "qcom,sc7180";
};
-&alc5682 {
- compatible = "realtek,rt5682s";
- /delete-property/ VBAT-supply;
- realtek,dmic1-clk-pin = <2>;
- realtek,dmic-clk-rate-hz = <2048000>;
-};
-
-&sound {
- compatible = "google,sc7180-trogdor";
- model = "sc7180-rt5682s-max98357a-1mic";
+&panel {
+ compatible = "innolux,hj110iz-01a";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx.dts
index dd34a2297ea0..4b165b826ab3 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx.dts
@@ -11,6 +11,7 @@
/dts-v1/;
#include "sc7180-trogdor-wormdingler.dtsi"
+#include "sc7180-trogdor-rt5682i-sku.dtsi"
/ {
model = "Google Wormdingler rev1+ INX panel board";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi
index 2f6a340ddd2a..305ad127246e 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi
@@ -123,6 +123,7 @@
interrupt-parent = <&tlmm>;
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+ panel = <&panel>;
post-power-on-delay-ms = <70>;
hid-descr-addr = <0x0001>;
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
index 5a33e16a8b67..46aaeba28604 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
@@ -372,7 +372,6 @@
sound: sound {
compatible = "google,sc7180-trogdor";
- model = "sc7180-rt5682-max98357a-1mic";
audio-routing =
"Headphone Jack", "HPOL",
@@ -747,32 +746,6 @@ ap_tp_i2c: &i2c7 {
hp_i2c: &i2c9 {
status = "okay";
clock-frequency = <400000>;
-
- alc5682: codec@1a {
- compatible = "realtek,rt5682i";
- reg = <0x1a>;
- pinctrl-names = "default";
- pinctrl-0 = <&hp_irq>;
-
- #sound-dai-cells = <1>;
-
- interrupt-parent = <&tlmm>;
- /*
- * This will get ignored because the interrupt type
- * is set in rt5682.c.
- */
- interrupts = <28 IRQ_TYPE_EDGE_BOTH>;
-
- AVDD-supply = <&pp1800_alc5682>;
- DBVDD-supply = <&pp1800_alc5682>;
- LDO1-IN-supply = <&pp1800_alc5682>;
- MICVDD-supply = <&pp3300_codec>;
- VBAT-supply = <&pp3300_audio>;
-
- realtek,dmic1-data-pin = <1>;
- realtek,dmic1-clk-pin = <1>;
- realtek,jd-src = <1>;
- };
};
&lpasscc {
diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
index a79c0f2e1879..11f353d416b4 100644
--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
@@ -11,15 +11,19 @@
#include <dt-bindings/clock/qcom,lpasscorecc-sc7180.h>
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/clock/qcom,videocc-sc7180.h>
+#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/interconnect/qcom,icc.h>
#include <dt-bindings/interconnect/qcom,osm-l3.h>
#include <dt-bindings/interconnect/qcom,sc7180.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy-qcom-qmp.h>
#include <dt-bindings/phy/phy-qcom-qusb2.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/reset/qcom,sdm845-aoss.h>
#include <dt-bindings/reset/qcom,sdm845-pdc.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
+#include <dt-bindings/soc/qcom,apr.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/thermal/thermal.h>
/ {
@@ -687,7 +691,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
};
@@ -2042,6 +2046,11 @@
pins = "gpio57";
function = "lpass_ext";
};
+
+ ter_mi2s_active: ter-mi2s-active-state {
+ pins = "gpio63", "gpio64", "gpio65", "gpio66";
+ function = "mi2s_2";
+ };
};
remoteproc_mpss: remoteproc@4080000 {
@@ -2795,49 +2804,28 @@
nvmem-cells = <&qusb2p_hstx_trim>;
};
- usb_1_qmpphy: phy-wrapper@88e9000 {
+ usb_1_qmpphy: phy@88e8000 {
compatible = "qcom,sc7180-qmp-usb3-dp-phy";
- reg = <0 0x088e9000 0 0x18c>,
- <0 0x088e8000 0 0x3c>,
- <0 0x088ea000 0 0x18c>;
+ reg = <0 0x088e8000 0 0x3000>;
status = "disabled";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
- <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
<&gcc GCC_USB3_PRIM_CLKREF_CLK>,
- <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "com_aux";
+ <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+ <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>,
+ <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>;
+ clock-names = "aux",
+ "ref",
+ "com_aux",
+ "usb3_pipe",
+ "cfg_ahb";
resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
<&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
reset-names = "phy", "common";
- usb_1_ssphy: usb3-phy@88e9200 {
- reg = <0 0x088e9200 0 0x128>,
- <0 0x088e9400 0 0x200>,
- <0 0x088e9c00 0 0x218>,
- <0 0x088e9600 0 0x128>,
- <0 0x088e9800 0 0x200>,
- <0 0x088e9a00 0 0x18>;
- #clock-cells = <0>;
- #phy-cells = <0>;
- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "usb3_phy_pipe_clk_src";
- };
-
- dp_phy: dp-phy@88ea200 {
- reg = <0 0x088ea200 0 0x200>,
- <0 0x088ea400 0 0x200>,
- <0 0x088eaa00 0 0x200>,
- <0 0x088ea600 0 0x200>,
- <0 0x088ea800 0 0x200>;
- #clock-cells = <1>;
- #phy-cells = <0>;
- };
+ #clock-cells = <1>;
+ #phy-cells = <1>;
};
pmu@90b6300 {
@@ -3001,7 +2989,7 @@
iommus = <&apps_smmu 0x540 0>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
- phys = <&usb_1_hsphy>, <&usb_1_ssphy>;
+ phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
maximum-speed = "super-speed";
};
@@ -3307,8 +3295,9 @@
"ctrl_link_iface", "stream_pixel";
assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
<&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
- assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>;
- phys = <&dp_phy>;
+ assigned-clock-parents = <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
+ phys = <&usb_1_qmpphy QMP_USB43DP_DP_PHY>;
phy-names = "dp";
operating-points-v2 = <&dp_opp_table>;
@@ -3365,8 +3354,8 @@
<&gcc GCC_DISP_GPLL0_CLK_SRC>,
<&mdss_dsi0_phy 0>,
<&mdss_dsi0_phy 1>,
- <&dp_phy 0>,
- <&dp_phy 1>;
+ <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
clock-names = "bi_tcxo",
"gcc_disp_gpll0_clk_src",
"dsi0_phy_pll_out_byteclk",
@@ -3776,6 +3765,126 @@
status = "disabled";
};
+ remoteproc_adsp: remoteproc@62400000 {
+ compatible = "qcom,sc7180-adsp-pas";
+ reg = <0 0x62400000 0 0x100>;
+
+ interrupts-extended = <&intc GIC_SPI 162 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>,
+ <&adsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog",
+ "fatal",
+ "ready",
+ "handover",
+ "stop-ack";
+
+ clocks = <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "xo";
+
+ power-domains = <&rpmhpd SC7180_LCX>,
+ <&rpmhpd SC7180_LMX>;
+ power-domain-names = "lcx", "lmx";
+
+ qcom,qmp = <&aoss_qmp>;
+ qcom,smem-states = <&adsp_smp2p_out 0>;
+ qcom,smem-state-names = "stop";
+
+ status = "disabled";
+
+ glink-edge {
+ interrupts = <GIC_SPI 156 IRQ_TYPE_EDGE_RISING>;
+ label = "lpass";
+ qcom,remote-pid = <2>;
+ mboxes = <&apss_shared 8>;
+
+ apr {
+ compatible = "qcom,apr-v2";
+ qcom,glink-channels = "apr_audio_svc";
+ qcom,domain = <APR_DOMAIN_ADSP>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ service@3 {
+ compatible = "qcom,q6core";
+ reg = <APR_SVC_ADSP_CORE>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ };
+
+ q6afe: service@4 {
+ compatible = "qcom,q6afe";
+ reg = <APR_SVC_AFE>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ q6afedai: dais {
+ compatible = "qcom,q6afe-dais";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ };
+
+ q6afecc: clock-controller {
+ compatible = "qcom,q6afe-clocks";
+ #clock-cells = <2>;
+ };
+ };
+
+ q6asm: service@7 {
+ compatible = "qcom,q6asm";
+ reg = <APR_SVC_ASM>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ q6asmdai: dais {
+ compatible = "qcom,q6asm-dais";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ iommus = <&apps_smmu 0x1001 0x0>;
+ };
+ };
+
+ q6adm: service@8 {
+ compatible = "qcom,q6adm";
+ reg = <APR_SVC_ADM>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ q6routing: routing {
+ compatible = "qcom,q6adm-routing";
+ #sound-dai-cells = <0>;
+ };
+ };
+ };
+
+ fastrpc {
+ compatible = "qcom,fastrpc";
+ qcom,glink-channels = "fastrpcglink-apps-dsp";
+ label = "adsp";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compute-cb@3 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <3>;
+ iommus = <&apps_smmu 0x1003 0x0>;
+ };
+
+ compute-cb@4 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <4>;
+ iommus = <&apps_smmu 0x1004 0x0>;
+ };
+
+ compute-cb@5 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <5>;
+ iommus = <&apps_smmu 0x1005 0x0>;
+ qcom,nsessions = <5>;
+ };
+ };
+ };
+ };
+
lpasscc: clock-controller@62d00000 {
compatible = "qcom,sc7180-lpasscorecc";
reg = <0 0x62d00000 0 0x50000>,
diff --git a/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi b/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi
index 2e1cd219fc18..5d462ae14ba1 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi
@@ -46,6 +46,26 @@
};
};
+&lpass_aon {
+ status = "okay";
+};
+
+&lpass_core {
+ status = "okay";
+};
+
+&lpass_hm {
+ status = "okay";
+};
+
+&lpasscc {
+ status = "okay";
+};
+
+&pdc_reset {
+ status = "okay";
+};
+
/* The PMIC PON code isn't compatible w/ how Chrome EC/BIOS handle things. */
&pmk8350_pon {
status = "disabled";
@@ -84,6 +104,10 @@
dma-coherent;
};
+&watchdog {
+ status = "okay";
+};
+
&wifi {
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/sc7280-crd-r3.dts b/arch/arm64/boot/dts/qcom/sc7280-crd-r3.dts
index afae7f46b050..c2cba9d7179b 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-crd-r3.dts
+++ b/arch/arm64/boot/dts/qcom/sc7280-crd-r3.dts
@@ -38,6 +38,10 @@
};
};
+&bluetooth {
+ vddio-supply = <&vreg_l18b_1p8>;
+};
+
ap_tp_i2c: &i2c0 {
status = "okay";
clock-frequency = <400000>;
diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
index 925428a5f6ae..66f1eb83cca7 100644
--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
@@ -13,11 +13,13 @@
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/clock/qcom,videocc-sc7280.h>
#include <dt-bindings/dma/qcom-gpi.h>
+#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interconnect/qcom,osm-l3.h>
#include <dt-bindings/interconnect/qcom,sc7280.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/mailbox/qcom-ipcc.h>
+#include <dt-bindings/phy/phy-qcom-qmp.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/reset/qcom,sdm845-aoss.h>
#include <dt-bindings/reset/qcom,sdm845-pdc.h>
@@ -156,7 +158,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
};
@@ -170,9 +172,8 @@
reg = <0x0 0x0>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ power-domains = <&CPU_PD0>;
+ power-domain-names = "psci";
next-level-cache = <&L2_0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
@@ -198,9 +199,8 @@
reg = <0x0 0x100>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ power-domains = <&CPU_PD1>;
+ power-domain-names = "psci";
next-level-cache = <&L2_100>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
@@ -221,9 +221,8 @@
reg = <0x0 0x200>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ power-domains = <&CPU_PD2>;
+ power-domain-names = "psci";
next-level-cache = <&L2_200>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
@@ -244,9 +243,8 @@
reg = <0x0 0x300>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ power-domains = <&CPU_PD3>;
+ power-domain-names = "psci";
next-level-cache = <&L2_300>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
@@ -267,9 +265,8 @@
reg = <0x0 0x400>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- cpu-idle-states = <&BIG_CPU_SLEEP_0
- &BIG_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ power-domains = <&CPU_PD4>;
+ power-domain-names = "psci";
next-level-cache = <&L2_400>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
@@ -290,9 +287,8 @@
reg = <0x0 0x500>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- cpu-idle-states = <&BIG_CPU_SLEEP_0
- &BIG_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ power-domains = <&CPU_PD5>;
+ power-domain-names = "psci";
next-level-cache = <&L2_500>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
@@ -313,9 +309,8 @@
reg = <0x0 0x600>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- cpu-idle-states = <&BIG_CPU_SLEEP_0
- &BIG_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ power-domains = <&CPU_PD6>;
+ power-domain-names = "psci";
next-level-cache = <&L2_600>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
@@ -336,9 +331,8 @@
reg = <0x0 0x700>;
clocks = <&cpufreq_hw 2>;
enable-method = "psci";
- cpu-idle-states = <&BIG_CPU_SLEEP_0
- &BIG_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ power-domains = <&CPU_PD7>;
+ power-domain-names = "psci";
next-level-cache = <&L2_700>;
operating-points-v2 = <&cpu7_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
@@ -431,9 +425,11 @@
min-residency-us = <5555>;
local-timer-stop;
};
+ };
+ domain-idle-states {
CLUSTER_SLEEP_0: cluster-sleep-0 {
- compatible = "arm,idle-state";
+ compatible = "domain-idle-state";
idle-state-name = "cluster-power-down";
arm,psci-suspend-param = <0x40003444>;
entry-latency-us = <3263>;
@@ -649,18 +645,6 @@
};
};
- eud_typec: connector {
- compatible = "usb-c-connector";
-
- ports {
- port@0 {
- con_eud: endpoint {
- remote-endpoint = <&eud_con>;
- };
- };
- };
- };
-
memory@80000000 {
device_type = "memory";
/* We expect the bootloader to fill in the size */
@@ -811,6 +795,59 @@
psci {
compatible = "arm,psci-1.0";
method = "smc";
+
+ CPU_PD0: power-domain-cpu0 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ };
+
+ CPU_PD1: power-domain-cpu1 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ };
+
+ CPU_PD2: power-domain-cpu2 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ };
+
+ CPU_PD3: power-domain-cpu3 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ };
+
+ CPU_PD4: power-domain-cpu4 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ };
+
+ CPU_PD5: power-domain-cpu5 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ };
+
+ CPU_PD6: power-domain-cpu6 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ };
+
+ CPU_PD7: power-domain-cpu7 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ };
+
+ CLUSTER_PD: power-domain-cluster {
+ #power-domain-cells = <0>;
+ domain-idle-states = <&CLUSTER_SLEEP_0>;
+ };
};
qspi_opp_table: opp-table-qspi {
@@ -868,8 +905,9 @@
reg = <0 0x00100000 0 0x1f0000>;
clocks = <&rpmhcc RPMH_CXO_CLK>,
<&rpmhcc RPMH_CXO_CLK_A>, <&sleep_clk>,
- <0>, <&pcie1_lane>,
- <0>, <0>, <0>, <0>;
+ <0>, <&pcie1_phy>,
+ <0>, <0>, <0>,
+ <&usb_1_qmpphy QMP_USB43DP_USB3_PIPE_CLK>;
clock-names = "bi_tcxo", "bi_tcxo_ao", "sleep_clk",
"pcie_0_pipe_clk", "pcie_1_pipe_clk",
"ufs_phy_rx_symbol_0_clk", "ufs_phy_rx_symbol_1_clk",
@@ -2119,7 +2157,7 @@
clocks = <&gcc GCC_PCIE_1_PIPE_CLK>,
<&gcc GCC_PCIE_1_PIPE_CLK_SRC>,
- <&pcie1_lane>,
+ <&pcie1_phy>,
<&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_PCIE_1_AUX_CLK>,
<&gcc GCC_PCIE_1_CFG_AHB_CLK>,
@@ -2153,7 +2191,7 @@
power-domains = <&gcc GCC_PCIE_1_GDSC>;
- phys = <&pcie1_lane>;
+ phys = <&pcie1_phy>;
phy-names = "pciephy";
pinctrl-names = "default";
@@ -2169,15 +2207,22 @@
pcie1_phy: phy@1c0e000 {
compatible = "qcom,sm8250-qmp-gen3x2-pcie-phy";
- reg = <0 0x01c0e000 0 0x1c0>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c0e000 0 0x1000>;
clocks = <&gcc GCC_PCIE_1_AUX_CLK>,
<&gcc GCC_PCIE_1_CFG_AHB_CLK>,
<&gcc GCC_PCIE_CLKREF_EN>,
- <&gcc GCC_PCIE1_PHY_RCHNG_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "refgen";
+ <&gcc GCC_PCIE1_PHY_RCHNG_CLK>,
+ <&gcc GCC_PCIE_1_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "refgen",
+ "pipe";
+
+ clock-output-names = "pcie_1_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_1_PHY_BCR>;
reset-names = "phy";
@@ -2186,21 +2231,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie1_lane: phy@1c0e200 {
- reg = <0 0x01c0e200 0 0x170>,
- <0 0x01c0e400 0 0x200>,
- <0 0x01c0ea00 0 0x1f0>,
- <0 0x01c0e600 0 0x170>,
- <0 0x01c0e800 0 0x200>,
- <0 0x01c0ee00 0 0xf4>;
- clocks = <&gcc GCC_PCIE_1_PIPE_CLK>;
- clock-names = "pipe0";
-
- #phy-cells = <0>;
- #clock-cells = <0>;
- clock-output-names = "pcie_1_pipe_clk";
- };
};
ipa: ipa@1e40000 {
@@ -2266,6 +2296,7 @@
clocks = <&gcc GCC_CFG_NOC_LPASS_CLK>;
clock-names = "iface";
#clock-cells = <1>;
+ status = "reserved"; /* Owned by ADSP firmware */
};
lpass_rx_macro: codec@3200000 {
@@ -2417,6 +2448,7 @@
clock-names = "bi_tcxo", "bi_tcxo_ao", "iface";
#clock-cells = <1>;
#power-domain-cells = <1>;
+ status = "reserved"; /* Owned by ADSP firmware */
};
lpass_core: clock-controller@3900000 {
@@ -2427,6 +2459,7 @@
power-domains = <&lpass_hm LPASS_CORE_CC_LPASS_CORE_HM_GDSC>;
#clock-cells = <1>;
#power-domain-cells = <1>;
+ status = "reserved"; /* Owned by ADSP firmware */
};
lpass_cpu: audio@3987000 {
@@ -2497,6 +2530,7 @@
clock-names = "bi_tcxo";
#clock-cells = <1>;
#power-domain-cells = <1>;
+ status = "reserved"; /* Owned by ADSP firmware */
};
lpass_ag_noc: interconnect@3c40000 {
@@ -2510,7 +2544,6 @@
compatible = "qcom,sc7280-lpass-lpi-pinctrl";
reg = <0 0x033c0000 0x0 0x20000>,
<0 0x03550000 0x0 0x10000>;
- qcom,adsp-bypass-mode;
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&lpass_tlmm 0 0 15>;
@@ -3346,49 +3379,26 @@
resets = <&gcc GCC_QUSB2PHY_SEC_BCR>;
};
- usb_1_qmpphy: phy-wrapper@88e9000 {
- compatible = "qcom,sc7280-qmp-usb3-dp-phy",
- "qcom,sm8250-qmp-usb3-dp-phy";
- reg = <0 0x088e9000 0 0x200>,
- <0 0x088e8000 0 0x40>,
- <0 0x088ea000 0 0x200>;
+ usb_1_qmpphy: phy@88e8000 {
+ compatible = "qcom,sc7280-qmp-usb3-dp-phy";
+ reg = <0 0x088e8000 0 0x3000>;
status = "disabled";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
<&rpmhcc RPMH_CXO_CLK>,
- <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
- clock-names = "aux", "ref_clk_src", "com_aux";
+ <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+ <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+ clock-names = "aux",
+ "ref",
+ "com_aux",
+ "usb3_pipe";
resets = <&gcc GCC_USB3_DP_PHY_PRIM_BCR>,
<&gcc GCC_USB3_PHY_PRIM_BCR>;
reset-names = "phy", "common";
- usb_1_ssphy: usb3-phy@88e9200 {
- reg = <0 0x088e9200 0 0x200>,
- <0 0x088e9400 0 0x200>,
- <0 0x088e9c00 0 0x400>,
- <0 0x088e9600 0 0x200>,
- <0 0x088e9800 0 0x200>,
- <0 0x088e9a00 0 0x100>;
- #clock-cells = <0>;
- #phy-cells = <0>;
- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "usb3_phy_pipe_clk_src";
- };
-
- dp_phy: dp-phy@88ea200 {
- reg = <0 0x088ea200 0 0x200>,
- <0 0x088ea400 0 0x200>,
- <0 0x088eaa00 0 0x200>,
- <0 0x088ea600 0 0x200>,
- <0 0x088ea800 0 0x200>;
- #phy-cells = <0>;
- #clock-cells = <1>;
- };
+ #clock-cells = <1>;
+ #phy-cells = <1>;
};
usb_2: usb@8cf8800 {
@@ -3624,6 +3634,8 @@
<0 0x88e2000 0 0x1000>;
interrupts-extended = <&pdc 11 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -3634,13 +3646,6 @@
remote-endpoint = <&usb2_role_switch>;
};
};
-
- port@1 {
- reg = <1>;
- eud_con: endpoint {
- remote-endpoint = <&con_eud>;
- };
- };
};
};
@@ -3702,7 +3707,7 @@
iommus = <&apps_smmu 0xe0 0x0>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
- phys = <&usb_1_hsphy>, <&usb_1_ssphy>;
+ phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
maximum-speed = "super-speed";
};
@@ -3807,8 +3812,8 @@
<&gcc GCC_DISP_GPLL0_CLK_SRC>,
<&mdss_dsi_phy 0>,
<&mdss_dsi_phy 1>,
- <&dp_phy 0>,
- <&dp_phy 1>,
+ <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>,
<&mdss_edp_phy 0>,
<&mdss_edp_phy 1>;
clock-names = "bi_tcxo",
@@ -4144,8 +4149,9 @@
"stream_pixel";
assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
<&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
- assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>;
- phys = <&dp_phy>;
+ assigned-clock-parents = <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
+ phys = <&usb_1_qmpphy QMP_USB43DP_DP_PHY>;
phy-names = "dp";
operating-points-v2 = <&dp_opp_table>;
@@ -4215,6 +4221,7 @@
compatible = "qcom,sc7280-pdc-global";
reg = <0 0x0b5e0000 0 0x20000>;
#reset-cells = <1>;
+ status = "reserved"; /* Owned by firmware */
};
tsens0: thermal-sensor@c263000 {
@@ -5211,11 +5218,12 @@
};
};
- watchdog@17c10000 {
+ watchdog: watchdog@17c10000 {
compatible = "qcom,apss-wdt-sc7280", "qcom,kpss-wdt";
reg = <0 0x17c10000 0 0x1000>;
clocks = <&sleep_clk>;
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+ status = "reserved"; /* Owned by Gunyah hyp */
};
timer@17c20000 {
@@ -5291,6 +5299,7 @@
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 1>;
+ power-domains = <&CLUSTER_PD>;
apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter";
@@ -5363,6 +5372,14 @@
reg = <0 0x18591000 0 0x1000>,
<0 0x18592000 0 0x1000>,
<0 0x18593000 0 0x1000>;
+
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "dcvsh-irq-0",
+ "dcvsh-irq-1",
+ "dcvsh-irq-2";
+
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GCC_GPLL0>;
clock-names = "xo", "alternate";
#freq-domain-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts b/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts
index abc66613ccaa..3ea07d094b60 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts
+++ b/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts
@@ -6,6 +6,7 @@
/dts-v1/;
+#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/gpio-keys.h>
#include <dt-bindings/input/input.h>
@@ -130,7 +131,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
wlan_mem: wlan-region@8bc00000 {
diff --git a/arch/arm64/boot/dts/qcom/sc8180x-primus.dts b/arch/arm64/boot/dts/qcom/sc8180x-primus.dts
index 834e6f9fb7c8..fd2fab4895b3 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x-primus.dts
+++ b/arch/arm64/boot/dts/qcom/sc8180x-primus.dts
@@ -6,6 +6,7 @@
/dts-v1/;
+#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/gpio-keys.h>
#include <dt-bindings/input/input.h>
@@ -135,7 +136,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
wlan_mem: wlan-region@8bc00000 {
diff --git a/arch/arm64/boot/dts/qcom/sc8180x.dtsi b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
index 486f7ffef43b..a34f438ef2d9 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
@@ -1749,23 +1749,28 @@
<&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_0 0>;
interconnect-names = "pcie-mem", "cpu-pcie";
- phys = <&pcie0_lane>;
+ phys = <&pcie0_phy>;
phy-names = "pciephy";
status = "disabled";
};
- pcie0_phy: phy-wrapper@1c06000 {
+ pcie0_phy: phy@1c06000 {
compatible = "qcom,sc8180x-qmp-pcie-phy";
- reg = <0 0x1c06000 0 0x1c0>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c06000 0 0x1000>;
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
<&gcc GCC_PCIE_0_CFG_AHB_CLK>,
<&gcc GCC_PCIE_0_CLKREF_CLK>,
- <&gcc GCC_PCIE1_PHY_REFGEN_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "refgen";
+ <&gcc GCC_PCIE1_PHY_REFGEN_CLK>,
+ <&gcc GCC_PCIE_0_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "refgen",
+ "pipe";
+ #clock-cells = <0>;
+ clock-output-names = "pcie_0_pipe_clk";
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_0_PHY_BCR>;
reset-names = "phy";
@@ -1774,21 +1779,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie0_lane: phy@1c06200 {
- reg = <0 0x1c06200 0 0x170>, /* tx0 */
- <0 0x1c06400 0 0x200>, /* rx0 */
- <0 0x1c06a00 0 0x1f0>, /* pcs */
- <0 0x1c06600 0 0x170>, /* tx1 */
- <0 0x1c06800 0 0x200>, /* rx1 */
- <0 0x1c06e00 0 0xf4>; /* pcs_com */
- clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
- clock-names = "pipe0";
-
- #clock-cells = <0>;
- clock-output-names = "pcie_0_pipe_clk";
- #phy-cells = <0>;
- };
};
pcie3: pci@1c08000 {
@@ -1856,23 +1846,29 @@
<&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_0 0>;
interconnect-names = "pcie-mem", "cpu-pcie";
- phys = <&pcie3_lane>;
+ phys = <&pcie3_phy>;
phy-names = "pciephy";
status = "disabled";
};
- pcie3_phy: phy-wrapper@1c0c000 {
+ pcie3_phy: phy@1c0c000 {
compatible = "qcom,sc8180x-qmp-pcie-phy";
- reg = <0 0x1c0c000 0 0x1c0>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c0c000 0 0x1000>;
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
<&gcc GCC_PCIE_3_CFG_AHB_CLK>,
<&gcc GCC_PCIE_3_CLKREF_CLK>,
- <&gcc GCC_PCIE2_PHY_REFGEN_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "refgen";
+ <&gcc GCC_PCIE2_PHY_REFGEN_CLK>,
+ <&gcc GCC_PCIE_3_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "refgen",
+ "pipe";
+ #clock-cells = <0>;
+ clock-output-names = "pcie_3_pipe_clk";
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_3_PHY_BCR>;
reset-names = "phy";
@@ -1881,21 +1877,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie3_lane: phy@1c0c200 {
- reg = <0 0x1c0c200 0 0x170>, /* tx0 */
- <0 0x1c0c400 0 0x200>, /* rx0 */
- <0 0x1c0ca00 0 0x1f0>, /* pcs */
- <0 0x1c0c600 0 0x170>, /* tx1 */
- <0 0x1c0c800 0 0x200>, /* rx1 */
- <0 0x1c0ce00 0 0xf4>; /* pcs_com */
- clocks = <&gcc GCC_PCIE_3_PIPE_CLK>;
- clock-names = "pipe0";
-
- #clock-cells = <0>;
- clock-output-names = "pcie_3_pipe_clk";
- #phy-cells = <0>;
- };
};
pcie1: pci@1c10000 {
@@ -1963,23 +1944,29 @@
<&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_0 0>;
interconnect-names = "pcie-mem", "cpu-pcie";
- phys = <&pcie1_lane>;
+ phys = <&pcie1_phy>;
phy-names = "pciephy";
status = "disabled";
};
- pcie1_phy: phy-wrapper@1c16000 {
+ pcie1_phy: phy@1c16000 {
compatible = "qcom,sc8180x-qmp-pcie-phy";
- reg = <0 0x1c16000 0 0x1c0>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c16000 0 0x1000>;
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
<&gcc GCC_PCIE_1_CFG_AHB_CLK>,
<&gcc GCC_PCIE_1_CLKREF_CLK>,
- <&gcc GCC_PCIE1_PHY_REFGEN_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "refgen";
+ <&gcc GCC_PCIE1_PHY_REFGEN_CLK>,
+ <&gcc GCC_PCIE_1_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "refgen",
+ "pipe";
+ #clock-cells = <0>;
+ clock-output-names = "pcie_1_pipe_clk";
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_1_PHY_BCR>;
reset-names = "phy";
@@ -1988,21 +1975,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie1_lane: phy@1c0e200 {
- reg = <0 0x1c16200 0 0x170>, /* tx0 */
- <0 0x1c16400 0 0x200>, /* rx0 */
- <0 0x1c16a00 0 0x1f0>, /* pcs */
- <0 0x1c16600 0 0x170>, /* tx1 */
- <0 0x1c16800 0 0x200>, /* rx1 */
- <0 0x1c16e00 0 0xf4>; /* pcs_com */
- clocks = <&gcc GCC_PCIE_1_PIPE_CLK>;
- clock-names = "pipe0";
- #clock-cells = <0>;
- clock-output-names = "pcie_1_pipe_clk";
-
- #phy-cells = <0>;
- };
};
pcie2: pci@1c18000 {
@@ -2070,23 +2042,29 @@
<&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_0 0>;
interconnect-names = "pcie-mem", "cpu-pcie";
- phys = <&pcie2_lane>;
+ phys = <&pcie2_phy>;
phy-names = "pciephy";
status = "disabled";
};
- pcie2_phy: phy-wrapper@1c1c000 {
+ pcie2_phy: phy@1c1c000 {
compatible = "qcom,sc8180x-qmp-pcie-phy";
- reg = <0 0x1c1c000 0 0x1c0>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c1c000 0 0x1000>;
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
<&gcc GCC_PCIE_2_CFG_AHB_CLK>,
<&gcc GCC_PCIE_2_CLKREF_CLK>,
- <&gcc GCC_PCIE2_PHY_REFGEN_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "refgen";
+ <&gcc GCC_PCIE2_PHY_REFGEN_CLK>,
+ <&gcc GCC_PCIE_2_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "refgen",
+ "pipe";
+ #clock-cells = <0>;
+ clock-output-names = "pcie_3_pipe_clk";
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_2_PHY_BCR>;
reset-names = "phy";
@@ -2095,22 +2073,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie2_lane: phy@1c0e200 {
- reg = <0 0x1c1c200 0 0x170>, /* tx0 */
- <0 0x1c1c400 0 0x200>, /* rx0 */
- <0 0x1c1ca00 0 0x1f0>, /* pcs */
- <0 0x1c1c600 0 0x170>, /* tx1 */
- <0 0x1c1c800 0 0x200>, /* rx1 */
- <0 0x1c1ce00 0 0xf4>; /* pcs_com */
- clocks = <&gcc GCC_PCIE_2_PIPE_CLK>;
- clock-names = "pipe0";
-
- #clock-cells = <0>;
- clock-output-names = "pcie_2_pipe_clk";
-
- #phy-cells = <0>;
- };
};
ufs_mem_hc: ufshc@1d84000 {
@@ -2118,7 +2080,7 @@
"jedec,ufs-2.0";
reg = <0 0x01d84000 0 0x2500>;
interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>;
- phys = <&ufs_mem_phy_lanes>;
+ phys = <&ufs_mem_phy>;
phy-names = "ufsphy";
lanes-per-direction = <2>;
#reset-cells = <1>;
@@ -2157,10 +2119,8 @@
ufs_mem_phy: phy-wrapper@1d87000 {
compatible = "qcom,sc8180x-qmp-ufs-phy";
- reg = <0 0x01d87000 0 0x1c0>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01d87000 0 0x1000>;
+
clocks = <&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_UFS_PHY_PHY_AUX_CLK>;
clock-names = "ref",
@@ -2168,16 +2128,10 @@
resets = <&ufs_mem_hc 0>;
reset-names = "ufsphy";
- status = "disabled";
- ufs_mem_phy_lanes: phy@1d87400 {
- reg = <0 0x01d87400 0 0x108>,
- <0 0x01d87600 0 0x1e0>,
- <0 0x01d87c00 0 0x1dc>,
- <0 0x01d87800 0 0x108>,
- <0 0x01d87a00 0 0x1e0>;
- #phy-cells = <0>;
- };
+ #phy-cells = <0>;
+
+ status = "disabled";
};
ipa_virt: interconnect@1e00000 {
@@ -2606,14 +2560,14 @@
clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
<&gcc GCC_USB30_PRIM_MASTER_CLK>,
<&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
- <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
<&gcc GCC_USB30_PRIM_SLEEP_CLK>,
+ <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
<&gcc GCC_USB3_SEC_CLKREF_CLK>;
clock-names = "cfg_noc",
"core",
"iface",
- "mock_utmi",
"sleep",
+ "mock_utmi",
"xo";
resets = <&gcc GCC_USB30_PRIM_BCR>;
power-domains = <&gcc USB30_PRIM_GDSC>;
@@ -2657,14 +2611,14 @@
clocks = <&gcc GCC_CFG_NOC_USB3_SEC_AXI_CLK>,
<&gcc GCC_USB30_SEC_MASTER_CLK>,
<&gcc GCC_AGGRE_USB3_SEC_AXI_CLK>,
- <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
<&gcc GCC_USB30_SEC_SLEEP_CLK>,
+ <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
<&gcc GCC_USB3_SEC_CLKREF_CLK>;
clock-names = "cfg_noc",
"core",
"iface",
- "mock_utmi",
"sleep",
+ "mock_utmi",
"xo";
resets = <&gcc GCC_USB30_SEC_BCR>;
power-domains = <&gcc USB30_SEC_GDSC>;
@@ -3307,7 +3261,6 @@
#size-cells = <0>;
interrupt-controller;
#interrupt-cells = <4>;
- cell-index = <0>;
};
apps_smmu: iommu@15000000 {
diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi
index ec6003212c4d..775700f78e0f 100644
--- a/arch/arm64/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi
@@ -8,6 +8,7 @@
#include <dt-bindings/clock/qcom,gpucc-sdm660.h>
#include <dt-bindings/clock/qcom,mmcc-sdm660.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/interconnect/qcom,sdm660.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/gpio/gpio.h>
@@ -453,7 +454,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
smem_region: smem-mem@86000000 {
@@ -1028,6 +1029,65 @@
};
};
+ remoteproc_mss: remoteproc@4080000 {
+ compatible = "qcom,sdm660-mss-pil";
+ reg = <0x04080000 0x100>, <0x04180000 0x40>;
+ reg-names = "qdsp6", "rmb";
+
+ interrupts-extended = <&intc GIC_SPI 448 IRQ_TYPE_EDGE_RISING>,
+ <&modem_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&modem_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&modem_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
+ <&modem_smp2p_in 3 IRQ_TYPE_EDGE_RISING>,
+ <&modem_smp2p_in 7 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog",
+ "fatal",
+ "ready",
+ "handover",
+ "stop-ack",
+ "shutdown-ack";
+
+ clocks = <&gcc GCC_MSS_CFG_AHB_CLK>,
+ <&gcc GCC_BIMC_MSS_Q6_AXI_CLK>,
+ <&gcc GCC_BOOT_ROM_AHB_CLK>,
+ <&gcc GPLL0_OUT_MSSCC>,
+ <&gcc GCC_MSS_SNOC_AXI_CLK>,
+ <&gcc GCC_MSS_MNOC_BIMC_AXI_CLK>,
+ <&rpmcc RPM_SMD_QDSS_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface",
+ "bus",
+ "mem",
+ "gpll0_mss",
+ "snoc_axi",
+ "mnoc_axi",
+ "qdss",
+ "xo";
+
+ qcom,smem-states = <&modem_smp2p_out 0>;
+ qcom,smem-state-names = "stop";
+
+ resets = <&gcc GCC_MSS_RESTART>;
+ reset-names = "mss_restart";
+
+ qcom,halt-regs = <&tcsr_regs_1 0x3000 0x5000 0x4000>;
+
+ power-domains = <&rpmpd SDM660_VDDCX>,
+ <&rpmpd SDM660_VDDMX>;
+ power-domain-names = "cx", "mx";
+
+ memory-region = <&mba_region>, <&mpss_region>;
+
+ status = "disabled";
+
+ glink-edge {
+ interrupts = <GIC_SPI 452 IRQ_TYPE_EDGE_RISING>;
+ label = "modem";
+ qcom,remote-pid = <1>;
+ mboxes = <&apcs_glb 15>;
+ };
+ };
+
adreno_gpu: gpu@5000000 {
compatible = "qcom,adreno-508.0", "qcom,adreno";
@@ -1416,10 +1476,10 @@
clocks = <&gcc GCC_CFG_NOC_USB2_AXI_CLK>,
<&gcc GCC_USB20_MASTER_CLK>,
- <&gcc GCC_USB20_MOCK_UTMI_CLK>,
- <&gcc GCC_USB20_SLEEP_CLK>;
+ <&gcc GCC_USB20_SLEEP_CLK>,
+ <&gcc GCC_USB20_MOCK_UTMI_CLK>;
clock-names = "cfg_noc", "core",
- "mock_utmi", "sleep";
+ "sleep", "mock_utmi";
assigned-clocks = <&gcc GCC_USB20_MOCK_UTMI_CLK>,
<&gcc GCC_USB20_MASTER_CLK>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 84cd2e39266f..ba2043d67370 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -1328,7 +1328,8 @@
compatible = "qcom,sdm670-pdc", "qcom,pdc";
reg = <0 0x0b220000 0 0x30000>;
qcom,pdc-ranges = <0 480 40>, <41 521 7>, <49 529 4>,
- <54 534 24>, <79 559 30>, <115 630 7>;
+ <54 534 24>, <79 559 15>, <94 609 15>,
+ <115 630 7>;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupt-controller;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
index f86e7acdfd99..0ab5e8f53ac9 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
@@ -143,16 +143,20 @@
};
};
+&cpufreq_hw {
+ /delete-property/ interrupts-extended; /* reference to lmh_cluster[01] */
+};
+
&psci {
- /delete-node/ cpu0;
- /delete-node/ cpu1;
- /delete-node/ cpu2;
- /delete-node/ cpu3;
- /delete-node/ cpu4;
- /delete-node/ cpu5;
- /delete-node/ cpu6;
- /delete-node/ cpu7;
- /delete-node/ cpu-cluster0;
+ /delete-node/ power-domain-cpu0;
+ /delete-node/ power-domain-cpu1;
+ /delete-node/ power-domain-cpu2;
+ /delete-node/ power-domain-cpu3;
+ /delete-node/ power-domain-cpu4;
+ /delete-node/ power-domain-cpu5;
+ /delete-node/ power-domain-cpu6;
+ /delete-node/ power-domain-cpu7;
+ /delete-node/ power-domain-cluster;
};
&cpus {
@@ -275,6 +279,14 @@
&CLUSTER_SLEEP_0>;
};
+&lmh_cluster0 {
+ status = "disabled";
+};
+
+&lmh_cluster1 {
+ status = "disabled";
+};
+
/*
* Reserved memory changes
*
@@ -338,6 +350,8 @@
&apps_rsc {
+ /delete-property/ power-domains;
+
regulators-0 {
compatible = "qcom,pm8998-rpmh-regulators";
qcom,pmic-id = "a";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi
index f942c5afea9b..99dafc6716e7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi
@@ -111,7 +111,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
/* rmtfs upper guard */
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
index b3c27a524742..76bfa786612c 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
@@ -114,7 +114,7 @@
&adsp_pas {
status = "okay";
- firmware-name = "qcom/sdm845/adsp.mdt";
+ firmware-name = "qcom/sdm845/adsp.mbn";
};
&apps_rsc {
@@ -415,7 +415,7 @@
&cdsp_pas {
status = "okay";
- firmware-name = "qcom/sdm845/cdsp.mdt";
+ firmware-name = "qcom/sdm845/cdsp.mbn";
};
&gcc {
@@ -533,6 +533,38 @@
firmware-name = "qcom/sdm845/mba.mbn", "qcom/sdm845/modem.mbn";
};
+&pcie0 {
+ perst-gpios = <&tlmm 35 GPIO_ACTIVE_LOW>;
+
+ pinctrl-0 = <&pcie0_default_state>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&pcie0_phy {
+ vdda-phy-supply = <&vreg_l1a_0p875>;
+ vdda-pll-supply = <&vreg_l26a_1p2>;
+
+ status = "okay";
+};
+
+&pcie1 {
+ perst-gpios = <&tlmm 102 GPIO_ACTIVE_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_default_state>;
+
+ status = "okay";
+};
+
+&pcie1_phy {
+ status = "okay";
+
+ vdda-phy-supply = <&vreg_l1a_0p875>;
+ vdda-pll-supply = <&vreg_l26a_1p2>;
+};
+
&pm8998_adc {
channel@4c {
reg = <ADC5_XO_THERM_100K_PU>;
@@ -609,6 +641,11 @@
};
};
+&pm8998_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
&qupv3_id_1 {
status = "okay";
};
@@ -625,6 +662,52 @@
cd-gpios = <&tlmm 126 GPIO_ACTIVE_LOW>;
};
+&tlmm {
+ pcie0_default_state: pcie0-default-state {
+ clkreq-pins {
+ pins = "gpio36";
+ function = "pci_e0";
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio35";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio37";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie1_default_state: pcie1-default-state {
+ clkreq-pins {
+ pins = "gpio103";
+ function = "pci_e1";
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio102";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio104";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+};
+
&uart9 {
status = "okay";
};
@@ -716,6 +799,9 @@
vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
+
+ qcom,snoc-host-cap-8bit-quirk;
+ qcom,ath10k-calibration-variant = "Qualcomm_sdm845mtp";
};
/* PINCTRL - additions to nodes defined in sdm845.dtsi */
diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
index 122c7128dea9..b523b5fff702 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
@@ -90,7 +90,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
rmtfs_upper_guard: rmtfs-upper-guard@f5d01000 {
no-map;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-akari.dts b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-akari.dts
index d97b7f1e7140..6e65909ab582 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-akari.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-akari.dts
@@ -15,3 +15,173 @@
&panel {
compatible = "sony,td4353-jdi-tama";
};
+
+&pmi8998_gpios {
+ gpio-line-names = "NC", /* GPIO_1 */
+ "NC",
+ "NC",
+ "",
+ "NC",
+ "NC",
+ "",
+ "WLC_EN_N",
+ "NC",
+ "NC", /* GPIO_10 */
+ "RSVD(WLC_EN_N)",
+ "CAM_IO_EN",
+ "",
+ "NC";
+};
+
+&tlmm {
+ gpio-line-names = "NC", /* GPIO_0 */
+ "NC",
+ "NC",
+ "NC",
+ "DEBUG_UART_TX",
+ "DEBUG_UART_RX",
+ "DISP_RESET_N",
+ "NC",
+ "CHAT_CAM_PWR_EN",
+ "CAM2_RSTN",
+ "MDP_VSYNC_P", /* GPIO_10 */
+ "RGBC_IR_INT",
+ "NFC_VEN",
+ "CAM_MCLK0",
+ "CAM_MCLK1",
+ "NC",
+ "NC",
+ "CCI_I2C_SDA0",
+ "CCI_I2C_SCL0",
+ "CCI_I2C_SDA1",
+ "CCI_I2C_SCL1", /* GPIO_20 */
+ "CAM_SOF",
+ "TOF_INT",
+ "TOF_RESET_N",
+ "NC",
+ "NC",
+ "NC",
+ "MAIN_CAM_PWR_EN",
+ "DVDT_ENABLE",
+ "DVDT_WRT_DET_AND",
+ "DVDT_WRT_DET_OR", /* GPIO_30 */
+ "WLC_INT_N",
+ "NC",
+ "CAMSENSOR_I2C_SDA",
+ "CAMSENSOR_I2C_SCL",
+ "NC",
+ "NC",
+ "NC",
+ "CC_DIR",
+ "NC",
+ "FP_RESET_N", /* GPIO_40 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "BT_HCI_UART_CTS_N",
+ "BT_HCI_UART_RFR_N",
+ "BT_HCI_UART_TXD",
+ "BT_HCI_UART_TRXD",
+ "USB_AUDIO_EN1",
+ "SW_SERVICE", /* GPIO_50 */
+ "US_EURO_SEL",
+ "NC",
+ "CODEC_INT2_N",
+ "CODEC_INT1_N",
+ "APPS_I2C_SDA",
+ "APPS_I2C_SCL",
+ "FORCED_USB_BOOT",
+ "NC",
+ "NC",
+ "NC", /* GPIO_60 */
+ "USB_PD_EN",
+ "NFC_DWLD_EN",
+ "NFC_IRQ",
+ "CODEC_RST_N",
+ "CODEC_SPI_MISO",
+ "CODEC_SPI_MOSI",
+ "CODEC_SPI_CLK",
+ "CODEC_SPI_CS_N",
+ "NC",
+ "CODEC_SLIMBUS_CLK", /* GPIO_70 */
+ "CODEC_SLIMBUS_DATA0",
+ "CODEC_SLIMBUS_DATA1",
+ "BT_FM_SLIMBUS_DATA",
+ "BT_FM_SLIMBUS_CLK",
+ "HW_ID_0",
+ "HW_ID_1",
+ "TX_GTR_THRES_IN",
+ "NC",
+ "NC",
+ "CAM1_RSTN", /* GPIO_80 */
+ "",
+ "",
+ "",
+ "",
+ "TS_I2C_SDA",
+ "TS_I2C_SCL",
+ "NC",
+ "NC",
+ "NC",
+ "NC", /* GPIO_90 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "RFFE6_CLK",
+ "RFFE6_DATA",
+ "TS_RESET_N",
+ "", /* GPIO_100 */
+ "GRFC4",
+ "DEBUG_GPIO0",
+ "DEBUG_GPIO1",
+ "RF_LCD_ID_EN",
+ "UIM2_DATA",
+ "UIM2_CLK",
+ "UIM2_RESET",
+ "UIM2_PRESENT",
+ "UIM1_DATA",
+ "UIM1_CLK", /* GPIO_110 */
+ "UIM1_RESET",
+ "UIM1_PRESENT",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "ACCEL_INT",
+ "GYRO_INT",
+ "COMPASS_INT",
+ "ALS_PROX_INT_N", /* GPIO_120 */
+ "FP_INT",
+ "RF_ID_EXTENTION",
+ "BAROMETER_INT",
+ "ACC_COVER_OPEN",
+ "TS_INT_N",
+ "TRAY_DET",
+ "GRFC3",
+ "NC",
+ "UIM2_DETECT_EN",
+ "QLINK_REQUEST", /* GPIO_130 */
+ "QLINK_ENABLE",
+ "GRFC2",
+ "NC",
+ "WMSS_RESET_N",
+ "PA_INDICATOR_OR",
+ "GRFC1",
+ "RFFE3_DATA",
+ "RFFE3_CLK",
+ "RFFE4_DATA",
+ "RFFE4_CLK", /* GPIO_140 */
+ "RFFE5_DATA",
+ "RFFE5_CLK",
+ "GNSS_EN",
+ "MSS_LTE_COXM_TXD",
+ "MSS_LTE_COXM_RXD",
+ "RFFE2_DATA",
+ "RFFE2_CLK",
+ "RFFE1_DATA",
+ "RFFE1_CLK";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-akatsuki.dts b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-akatsuki.dts
index 5d2052a0ff69..82e59e453354 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-akatsuki.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-akatsuki.dts
@@ -44,11 +44,179 @@
/delete-property/ touch-reset-gpios;
};
+&pmi8998_gpios {
+ gpio-line-names = "NC", /* GPIO_1 */
+ "NC",
+ "NC",
+ "",
+ "NC",
+ "NC",
+ "",
+ "WLC_EN_N",
+ "NC",
+ "NC", /* GPIO_10 */
+ "NC",
+ "CAM_IO_EN",
+ "",
+ "NC";
+};
+
&pmi8998_wled {
status = "disabled";
};
&tlmm {
+ gpio-line-names = "NC", /* GPIO_0 */
+ "NC",
+ "NC",
+ "NC",
+ "DEBUG_UART_TX",
+ "DEBUG_UART_RX",
+ "DISP_RESET_N",
+ "SAMD_RSTEN_N",
+ "CHAT_CAM_PWR_EN",
+ "CAM2_RSTN",
+ "MDP_VSYNC_P", /* GPIO_10 */
+ "RGBC_IR_INT",
+ "NFC_VEN",
+ "CAM_MCLK0",
+ "CAM_MCLK1",
+ "NC",
+ "MASTER_RST_N",
+ "CCI_I2C_SDA0",
+ "CCI_I2C_SCL0",
+ "CCI_I2C_SDA1",
+ "CCI_I2C_SCL1", /* GPIO_20 */
+ "CAM_SOF",
+ "TOF_INT",
+ "TOF_RESET_N",
+ "NC",
+ "NC",
+ "NC",
+ "MAIN_CAM_PWR_EN",
+ "DVDT_ENABLE",
+ "DVDT_WRT_DET_AND",
+ "DVDT_WRT_DET_OR", /* GPIO_30 */
+ "WLC_INT_N",
+ "NC",
+ "CAMSENSOR_I2C_SDA",
+ "CAMSENSOR_I2C_SCL",
+ "NC",
+ "NC",
+ "NC",
+ "CC_DIR",
+ "NC",
+ "FP_RESET_N", /* GPIO_40 */
+ "NC",
+ "NC",
+ "NC",
+ "DISP_ERR_FG",
+ "BT_HCI_UART_CTS_N",
+ "BT_HCI_UART_RFR_N",
+ "BT_HCI_UART_TXD",
+ "BT_HCI_UART_TRXD",
+ "USB_AUDIO_EN1",
+ "SW_SERVICE", /* GPIO_50 */
+ "US_EURO_SEL",
+ "SAMD_BOOTL_PIN",
+ "CODEC_INT2_N",
+ "CODEC_INT1_N",
+ "APPS_I2C_SDA",
+ "APPS_I2C_SCL",
+ "FORCED_USB_BOOT",
+ "SDM_SWD_CLK",
+ "SDM_SWD_DAT",
+ "SAMD_RST", /* GPIO_60 */
+ "USB_PD_EN",
+ "NFC_DWLD_EN",
+ "NFC_IRQ",
+ "CODEC_RST_N",
+ "CODEC_SPI_MISO",
+ "CODEC_SPI_MOSI",
+ "CODEC_SPI_CLK",
+ "CODEC_SPI_CS_N",
+ "NC",
+ "CODEC_SLIMBUS_CLK", /* GPIO_70 */
+ "CODEC_SLIMBUS_DATA0",
+ "CODEC_SLIMBUS_DATA1",
+ "BT_FM_SLIMBUS_DATA",
+ "BT_FM_SLIMBUS_CLK",
+ "HW_ID_0",
+ "HW_ID_1",
+ "TX_GTR_THRES_IN",
+ "MODE_SEL2",
+ "NC",
+ "CAM1_RSTN", /* GPIO_80 */
+ "",
+ "",
+ "",
+ "",
+ "TS_I2C_SDA",
+ "TS_I2C_SCL",
+ "NC",
+ "NC",
+ "NC",
+ "NC", /* GPIO_90 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "RFFE6_CLK",
+ "RFFE6_DATA",
+ "TS_RESET_N",
+ "", /* GPIO_100 */
+ "GRFC4",
+ "DEBUG_GPIO0",
+ "DEBUG_GPIO1",
+ "RF_LCD_ID_EN",
+ "UIM2_DATA",
+ "UIM2_CLK",
+ "UIM2_RESET",
+ "UIM2_PRESENT",
+ "UIM1_DATA",
+ "UIM1_CLK", /* GPIO_110 */
+ "UIM1_RESET",
+ "UIM1_PRESENT",
+ "NC",
+ "NC",
+ "NC",
+ "NFC_ESE_PWR_REQ",
+ "ACCEL_INT",
+ "GYRO_INT",
+ "COMPASS_INT",
+ "ALS_PROX_INT_N", /* GPIO_120 */
+ "FP_INT",
+ "RF_ID_EXTENTION",
+ "BAROMETER_INT",
+ "ACC_COVER_OPEN",
+ "TS_INT_N",
+ "TRAY_DET",
+ "GRFC3",
+ "NC",
+ "UIM2_DETECT_EN",
+ "QLINK_REQUEST", /* GPIO_130 */
+ "QLINK_ENABLE",
+ "GRFC2",
+ "TS_VDDIO_EN",
+ "WMSS_RESET_N",
+ "PA_INDICATOR_OR",
+ "GRFC1",
+ "RFFE3_DATA",
+ "RFFE3_CLK",
+ "RFFE4_DATA",
+ "RFFE4_CLK", /* GPIO_140 */
+ "RFFE5_DATA",
+ "RFFE5_CLK",
+ "GNSS_EN",
+ "MSS_LTE_COXM_TXD",
+ "MSS_LTE_COXM_RXD",
+ "RFFE2_DATA",
+ "RFFE2_CLK",
+ "RFFE1_DATA",
+ "RFFE1_CLK";
+
ts_vddio_en: ts-vddio-en-state {
pins = "gpio133";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-apollo.dts b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-apollo.dts
index cd056f78070f..dc15ab1a2716 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-apollo.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama-apollo.dts
@@ -17,3 +17,173 @@
height-mm = <112>;
width-mm = <56>;
};
+
+&pmi8998_gpios {
+ gpio-line-names = "NC", /* GPIO_1 */
+ "NC",
+ "NC",
+ "",
+ "VIB_LDO_EN",
+ "NC",
+ "",
+ "NC",
+ "NC",
+ "NC", /* GPIO_10 */
+ "NC",
+ "CAM_IO_EN",
+ "",
+ "NC";
+};
+
+&tlmm {
+ gpio-line-names = "NC", /* GPIO_0 */
+ "NC",
+ "NC",
+ "NC",
+ "DEBUG_UART_TX",
+ "DEBUG_UART_RX",
+ "DISP_RESET_N",
+ "NC",
+ "CHAT_CAM_PWR_EN",
+ "CAM2_RSTN",
+ "MDP_VSYNC_P", /* GPIO_10 */
+ "RGBC_IR_INT",
+ "NFC_VEN",
+ "CAM_MCLK0",
+ "CAM_MCLK1",
+ "NC",
+ "NC",
+ "CCI_I2C_SDA0",
+ "CCI_I2C_SCL0",
+ "CCI_I2C_SDA1",
+ "CCI_I2C_SCL1", /* GPIO_20 */
+ "CAM_SOF",
+ "TOF_INT",
+ "TOF_RESET_N",
+ "NC",
+ "NC",
+ "NC",
+ "MAIN_CAM_PWR_EN",
+ "DVDT_ENABLE",
+ "DVDT_WRT_DET_AND",
+ "DVDT_WRT_DET_OR", /* GPIO_30 */
+ "NC",
+ "NC",
+ "CAMSENSOR_I2C_SDA",
+ "CAMSENSOR_I2C_SCL",
+ "NC",
+ "NC",
+ "NC",
+ "CC_DIR",
+ "NC",
+ "FP_RESET_N", /* GPIO_40 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "BT_HCI_UART_CTS_N",
+ "BT_HCI_UART_RFR_N",
+ "BT_HCI_UART_TXD",
+ "BT_HCI_UART_TRXD",
+ "USB_AUDIO_EN1",
+ "SW_SERVICE", /* GPIO_50 */
+ "US_EURO_SEL",
+ "NC",
+ "CODEC_INT2_N",
+ "CODEC_INT1_N",
+ "APPS_I2C_SDA",
+ "APPS_I2C_SCL",
+ "FORCED_USB_BOOT",
+ "NC",
+ "NC",
+ "NC", /* GPIO_60 */
+ "USB_PD_EN",
+ "NFC_DWLD_EN",
+ "NFC_IRQ",
+ "CODEC_RST_N",
+ "CODEC_SPI_MISO",
+ "CODEC_SPI_MOSI",
+ "CODEC_SPI_CLK",
+ "CODEC_SPI_CS_N",
+ "NC",
+ "CODEC_SLIMBUS_CLK", /* GPIO_70 */
+ "CODEC_SLIMBUS_DATA0",
+ "CODEC_SLIMBUS_DATA1",
+ "BT_FM_SLIMBUS_DATA",
+ "BT_FM_SLIMBUS_CLK",
+ "HW_ID_0",
+ "HW_ID_1",
+ "TX_GTR_THRES_IN",
+ "NC",
+ "NC",
+ "CAM1_RSTN", /* GPIO_80 */
+ "",
+ "",
+ "",
+ "",
+ "TS_I2C_SDA",
+ "TS_I2C_SCL",
+ "NC",
+ "NC",
+ "NC",
+ "NC", /* GPIO_90 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "RFFE6_CLK",
+ "RFFE6_DATA",
+ "TS_RESET_N",
+ "", /* GPIO_100 */
+ "GRFC4",
+ "DEBUG_GPIO0",
+ "DEBUG_GPIO1",
+ "RF_LCD_ID_EN",
+ "UIM2_DATA",
+ "UIM2_CLK",
+ "UIM2_RESET",
+ "UIM2_PRESENT",
+ "UIM1_DATA",
+ "UIM1_CLK", /* GPIO_110 */
+ "UIM1_RESET",
+ "UIM1_PRESENT",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "ACCEL_INT",
+ "GYRO_INT",
+ "COMPASS_INT",
+ "ALS_PROX_INT_N", /* GPIO_120 */
+ "FP_INT",
+ "RF_ID_EXTENTION",
+ "BAROMETER_INT",
+ "ACC_COVER_OPEN",
+ "TS_INT_N",
+ "TRAY_DET",
+ "GRFC3",
+ "NC",
+ "UIM2_DETECT_EN",
+ "QLINK_REQUEST", /* GPIO_130 */
+ "QLINK_ENABLE",
+ "GRFC2",
+ "NC",
+ "WMSS_RESET_N",
+ "PA_INDICATOR_OR",
+ "GRFC1",
+ "RFFE3_DATA",
+ "RFFE3_CLK",
+ "RFFE4_DATA",
+ "RFFE4_CLK", /* GPIO_140 */
+ "RFFE5_DATA",
+ "RFFE5_CLK",
+ "GNSS_EN",
+ "MSS_LTE_COXM_TXD",
+ "MSS_LTE_COXM_RXD",
+ "RFFE2_DATA",
+ "RFFE2_CLK",
+ "RFFE1_DATA",
+ "RFFE1_CLK";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
index 7ee61b20452e..b02a1dc5fecd 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
@@ -67,6 +67,36 @@
};
};
+ cam_vana_front_vreg: cam-vana-front-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "cam_vana_front_vreg";
+ gpio = <&tlmm 8 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&chat_cam_pwr_en>;
+ pinctrl-names = "default";
+ };
+
+ cam_vana_rear_vreg: cam-vana-rear-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "cam_vana_rear_vreg";
+ gpio = <&tlmm 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&main_cam_pwr_en>;
+ pinctrl-names = "default";
+ };
+
+ cam_vio_vreg: cam-vio-reagulator {
+ compatible = "regulator-fixed";
+ regulator-name = "cam_vio_vreg";
+ gpio = <&pmi8998_gpios 12 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&cam_io_en>;
+ pinctrl-names = "default";
+ };
+
vph_pwr: vph-pwr-regulator {
compatible = "regulator-fixed";
regulator-name = "vph_pwr";
@@ -524,7 +554,41 @@
status = "okay";
};
+&pm8005_gpios {
+ gpio-line-names = "NC", /* GPIO_1 */
+ "NC",
+ "",
+ "";
+};
+
&pm8998_gpios {
+ gpio-line-names = "NC", /* GPIO_1 */
+ "FOCUS_N",
+ "",
+ "NC",
+ "VOL_DOWN_N",
+ "VOL_UP_N",
+ "SNAPSHOT_N",
+ "NC",
+ "FLASH_THERM",
+ "NC", /* GPIO_10 */
+ "LCD_ID",
+ "RF_ID",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "", /* GPIO_20 */
+ "NFC_CLK_REQ",
+ "",
+ "",
+ "",
+ "",
+ "";
+
focus_n: focus-n-state {
pins = "gpio2";
function = PMIC_GPIO_FUNC_NORMAL;
@@ -558,6 +622,17 @@
};
};
+&pmi8998_gpios {
+ cam_io_en: cam-io-en-state {
+ pins = "gpio12";
+ function = "normal";
+ qcom,drive-strength = <3>;
+ power-source = <0>;
+ drive-push-pull;
+ output-low;
+ };
+};
+
&pmi8998_wled {
default-brightness = <800>;
qcom,switching-freq = <800>;
@@ -626,6 +701,14 @@
bias-pull-down;
};
+ chat_cam_pwr_en: chat-cam-pwr-en-state {
+ pins = "gpio8";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+
sde_te_active_sleep: sde-te-active-sleep-state {
pins = "gpio10";
function = "mdp_vsync";
@@ -633,6 +716,14 @@
bias-pull-down;
};
+ main_cam_pwr_en: main-cam-pwr-en-state {
+ pins = "gpio27";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+
ts_default: ts-default-state {
reset-pins {
pins = "gpio99";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
index 9d6faeb65624..93b1582e807d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
@@ -111,7 +111,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts
index 6db12abaa88d..e386b504e978 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts
@@ -108,7 +108,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 055ca80c0075..bf5e6eb9d313 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -18,6 +18,7 @@
#include <dt-bindings/interconnect/qcom,osm-l3.h>
#include <dt-bindings/interconnect/qcom,sdm845.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy-qcom-qmp.h>
#include <dt-bindings/phy/phy-qcom-qusb2.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/reset/qcom,sdm845-aoss.h>
@@ -813,7 +814,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
qseecom_mem: qseecom@8ab00000 {
@@ -1197,8 +1198,8 @@
clocks = <&rpmhcc RPMH_CXO_CLK>,
<&rpmhcc RPMH_CXO_CLK_A>,
<&sleep_clk>,
- <&pcie0_lane>,
- <&pcie1_lane>;
+ <&pcie0_phy>,
+ <&pcie1_phy>;
clock-names = "bi_tcxo",
"bi_tcxo_ao",
"sleep_clk",
@@ -2370,7 +2371,7 @@
power-domains = <&gcc PCIE_0_GDSC>;
- phys = <&pcie0_lane>;
+ phys = <&pcie0_phy>;
phy-names = "pciephy";
status = "disabled";
@@ -2378,15 +2379,22 @@
pcie0_phy: phy@1c06000 {
compatible = "qcom,sdm845-qmp-pcie-phy";
- reg = <0 0x01c06000 0 0x18c>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c06000 0 0x1000>;
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
<&gcc GCC_PCIE_0_CFG_AHB_CLK>,
<&gcc GCC_PCIE_0_CLKREF_CLK>,
- <&gcc GCC_PCIE_PHY_REFGEN_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "refgen";
+ <&gcc GCC_PCIE_PHY_REFGEN_CLK>,
+ <&gcc GCC_PCIE_0_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "refgen",
+ "pipe";
+
+ clock-output-names = "pcie_0_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_0_PHY_BCR>;
reset-names = "phy";
@@ -2395,19 +2403,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie0_lane: phy@1c06200 {
- reg = <0 0x01c06200 0 0x128>,
- <0 0x01c06400 0 0x1fc>,
- <0 0x01c06800 0 0x218>,
- <0 0x01c06600 0 0x70>;
- clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
- clock-names = "pipe0";
-
- #clock-cells = <0>;
- #phy-cells = <0>;
- clock-output-names = "pcie_0_pipe_clk";
- };
};
pcie1: pci@1c08000 {
@@ -2480,7 +2475,7 @@
power-domains = <&gcc PCIE_1_GDSC>;
- phys = <&pcie1_lane>;
+ phys = <&pcie1_phy>;
phy-names = "pciephy";
status = "disabled";
@@ -2488,15 +2483,22 @@
pcie1_phy: phy@1c0a000 {
compatible = "qcom,sdm845-qhp-pcie-phy";
- reg = <0 0x01c0a000 0 0x800>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c0a000 0 0x2000>;
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
<&gcc GCC_PCIE_1_CFG_AHB_CLK>,
<&gcc GCC_PCIE_1_CLKREF_CLK>,
- <&gcc GCC_PCIE_PHY_REFGEN_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "refgen";
+ <&gcc GCC_PCIE_PHY_REFGEN_CLK>,
+ <&gcc GCC_PCIE_1_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "refgen",
+ "pipe";
+
+ clock-output-names = "pcie_1_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_1_PHY_BCR>;
reset-names = "phy";
@@ -2505,18 +2507,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie1_lane: phy@1c06200 {
- reg = <0 0x01c0a800 0 0x800>,
- <0 0x01c0a800 0 0x800>,
- <0 0x01c0b800 0 0x400>;
- clocks = <&gcc GCC_PCIE_1_PIPE_CLK>;
- clock-names = "pipe0";
-
- #clock-cells = <0>;
- #phy-cells = <0>;
- clock-output-names = "pcie_1_pipe_clk";
- };
};
mem_noc: interconnect@1380000 {
@@ -3984,49 +3974,28 @@
nvmem-cells = <&qusb2s_hstx_trim>;
};
- usb_1_qmpphy: phy@88e9000 {
+ usb_1_qmpphy: phy@88e8000 {
compatible = "qcom,sdm845-qmp-usb3-dp-phy";
- reg = <0 0x088e9000 0 0x18c>,
- <0 0x088e8000 0 0x38>,
- <0 0x088ea000 0 0x40>;
+ reg = <0 0x088e8000 0 0x3000>;
status = "disabled";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
- <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
<&gcc GCC_USB3_PRIM_CLKREF_CLK>,
- <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "com_aux";
+ <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+ <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>,
+ <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>;
+ clock-names = "aux",
+ "ref",
+ "com_aux",
+ "usb3_pipe",
+ "cfg_ahb";
resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
<&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
reset-names = "phy", "common";
- usb_1_ssphy: usb3-phy@88e9200 {
- reg = <0 0x088e9200 0 0x128>,
- <0 0x088e9400 0 0x200>,
- <0 0x088e9c00 0 0x218>,
- <0 0x088e9600 0 0x128>,
- <0 0x088e9800 0 0x200>,
- <0 0x088e9a00 0 0x100>;
- #clock-cells = <0>;
- #phy-cells = <0>;
- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "usb3_phy_pipe_clk_src";
- };
-
- dp_phy: dp-phy@88ea200 {
- reg = <0 0x088ea200 0 0x200>,
- <0 0x088ea400 0 0x200>,
- <0 0x088eaa00 0 0x200>,
- <0 0x088ea600 0 0x200>,
- <0 0x088ea800 0 0x200>;
- #clock-cells = <1>;
- #phy-cells = <0>;
- };
+ #clock-cells = <1>;
+ #phy-cells = <1>;
};
usb_2_qmpphy: phy@88eb000 {
@@ -4106,7 +4075,7 @@
iommus = <&apps_smmu 0x740 0>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
- phys = <&usb_1_hsphy>, <&usb_1_ssphy>;
+ phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
};
};
@@ -4574,8 +4543,9 @@
"ctrl_link_iface", "stream_pixel";
assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
<&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
- assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>;
- phys = <&dp_phy>;
+ assigned-clock-parents = <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
+ phys = <&usb_1_qmpphy QMP_USB43DP_DP_PHY>;
phy-names = "dp";
operating-points-v2 = <&dp_opp_table>;
@@ -4913,8 +4883,8 @@
<&mdss_dsi0_phy 1>,
<&mdss_dsi1_phy 0>,
<&mdss_dsi1_phy 1>,
- <&dp_phy 0>,
- <&dp_phy 1>;
+ <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
clock-names = "bi_tcxo",
"gcc_disp_gpll0_clk_src",
"gcc_disp_gpll0_div_clk_src",
diff --git a/arch/arm64/boot/dts/qcom/sdx75-idp.dts b/arch/arm64/boot/dts/qcom/sdx75-idp.dts
index 10d15871f2c4..a14e0650c4a8 100644
--- a/arch/arm64/boot/dts/qcom/sdx75-idp.dts
+++ b/arch/arm64/boot/dts/qcom/sdx75-idp.dts
@@ -44,7 +44,7 @@
};
&apps_rsc {
- pmx75-rpmh-regulators {
+ regulators-0 {
compatible = "qcom,pmx75-rpmh-regulators";
qcom,pmic-id = "b";
diff --git a/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts b/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts
index 75951fd439df..2c7a12983dae 100644
--- a/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts
+++ b/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts
@@ -225,13 +225,13 @@
vcc-max-microamp = <600000>;
vccq2-supply = <&vreg_l11a>;
vccq2-max-microamp = <600000>;
+ vdd-hba-supply = <&vreg_l18a>;
status = "okay";
};
&ufs_mem_phy {
vdda-phy-supply = <&vreg_l4a>;
vdda-pll-supply = <&vreg_l12a>;
- vddp-ref-clk-supply = <&vreg_l18a>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts b/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts
index 9b70a87906dc..98eb072fa912 100644
--- a/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts
+++ b/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts
@@ -219,13 +219,13 @@
vcc-max-microamp = <600000>;
vccq2-supply = <&pm6125_l11a>;
vccq2-max-microamp = <600000>;
+ vdd-hba-supply = <&pm6125_l18a>;
status = "okay";
};
&ufs_mem_phy {
vdda-phy-supply = <&pm6125_l4a>;
vdda-pll-supply = <&pm6125_l12a>;
- vddp-ref-clk-supply = <&pm6125_l18a>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts b/arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts
index c2d15fc6c96b..54da053a8042 100644
--- a/arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts
+++ b/arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts
@@ -344,13 +344,13 @@
vcc-max-microamp = <600000>;
vccq2-supply = <&pm6125_l11>;
vccq2-max-microamp = <600000>;
+ vdd-hba-supply = <&pm6125_l18>;
status = "okay";
};
&ufs_mem_phy {
vdda-phy-supply = <&pm6125_l4>;
vdda-pll-supply = <&pm6125_l12>;
- vddp-ref-clk-supply = <&pm6125_l18>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
index fb4cba004367..08046f866f60 100644
--- a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
+++ b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
@@ -179,6 +179,43 @@
/* Cirrus Logic CS35L41 boosted audio amplifier @ 40 */
};
+&mdss {
+ status = "okay";
+};
+
+&mdss_dsi0 {
+ vdda-supply = <&pm6125_l18>;
+ status = "okay";
+
+ panel@0 {
+ compatible = "samsung,sofef01-m-ams597ut01";
+ reg = <0>;
+
+ reset-gpios = <&tlmm 90 GPIO_ACTIVE_LOW>;
+
+ vddio-supply = <&pm6125_l12>;
+
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active_sleep>;
+ pinctrl-1 = <&mdss_dsi_sleep &mdss_te_active_sleep>;
+ pinctrl-names = "default", "sleep";
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+ };
+};
+
+&mdss_dsi0_out {
+ remote-endpoint = <&panel_in>;
+ data-lanes = <0 1 2 3>;
+};
+
+&mdss_dsi0_phy {
+ status = "okay";
+};
+
&pm6125_adc {
pinctrl-names = "default";
pinctrl-0 = <&camera_flash_therm &emmc_ufs_therm &rf_pa1_therm>;
@@ -474,6 +511,28 @@
drive-strength = <2>;
bias-disable;
};
+
+ mdss_te_active_sleep: mdss-te-active-sleep-state {
+ pins = "gpio89";
+ function = "mdp_vsync";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ mdss_dsi_active: mdss-dsi-active-state {
+ pins = "gpio90";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ mdss_dsi_sleep: mdss-dsi-sleep-state {
+ pins = "gpio90";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
};
&usb3 {
diff --git a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts
index 272bc85f1719..a49d3ebb1931 100644
--- a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts
+++ b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts
@@ -400,15 +400,13 @@
vccq2-supply = <&vreg_l11a>;
vcc-max-microamp = <600000>;
vccq2-max-microamp = <600000>;
+ vdd-hba-supply = <&vreg_l18a>;
status = "okay";
};
&ufs_mem_phy {
vdda-phy-supply = <&vreg_l4a>;
vdda-pll-supply = <&vreg_l10a>;
- vdda-phy-max-microamp = <51400>;
- vdda-pll-max-microamp = <14200>;
- vddp-ref-clk-supply = <&vreg_l18a>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi
index d7c1a40617c6..eb07eca3a48d 100644
--- a/arch/arm64/boot/dts/qcom/sm6125.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi
@@ -3,6 +3,7 @@
* Copyright (c) 2021, Martin Botka <martin.botka@somainline.org>
*/
+#include <dt-bindings/clock/qcom,dispcc-sm6125.h>
#include <dt-bindings/clock/qcom,gcc-sm6125.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/dma/qcom-gpi.h>
@@ -22,7 +23,6 @@
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <19200000>;
- clock-output-names = "xo_board";
};
sleep_clk: sleep-clk {
@@ -198,6 +198,8 @@
rpmcc: clock-controller {
compatible = "qcom,rpmcc-sm6125", "qcom,rpmcc";
#clock-cells = <1>;
+ clocks = <&xo_board>;
+ clock-names = "xo";
};
rpmpd: power-controller {
@@ -683,6 +685,24 @@
status = "disabled";
};
+ spmi_bus: spmi@1c40000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x01c40000 0x1100>,
+ <0x01e00000 0x2000000>,
+ <0x03e00000 0x100000>,
+ <0x03f00000 0xa0000>,
+ <0x01c0a000 0x26000>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupt-names = "periph_irq";
+ interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ };
+
rpm_msg_ram: sram@45f0000 {
compatible = "qcom,rpm-msg-ram";
reg = <0x045f0000 0x7000>;
@@ -699,7 +719,7 @@
clocks = <&gcc GCC_SDCC1_AHB_CLK>,
<&gcc GCC_SDCC1_APPS_CLK>,
- <&xo_board>;
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
clock-names = "iface", "core", "xo";
iommus = <&apps_smmu 0x160 0x0>;
@@ -726,7 +746,7 @@
clocks = <&gcc GCC_SDCC2_AHB_CLK>,
<&gcc GCC_SDCC2_APPS_CLK>,
- <&xo_board>;
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
clock-names = "iface", "core", "xo";
iommus = <&apps_smmu 0x180 0x0>;
@@ -1188,27 +1208,226 @@
reg = <0x04690000 0x10000>;
};
- spmi_bus: spmi@1c40000 {
- compatible = "qcom,spmi-pmic-arb";
- reg = <0x01c40000 0x1100>,
- <0x01e00000 0x2000000>,
- <0x03e00000 0x100000>,
- <0x03f00000 0xa0000>,
- <0x01c0a000 0x26000>;
- reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
- interrupt-names = "periph_irq";
- interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
- qcom,ee = <0>;
- qcom,channel = <0>;
- #address-cells = <2>;
- #size-cells = <0>;
+ mdss: display-subsystem@5e00000 {
+ compatible = "qcom,sm6125-mdss";
+ reg = <0x05e00000 0x1000>;
+ reg-names = "mdss";
+
+ interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
- #interrupt-cells = <4>;
+ #interrupt-cells = <1>;
+
+ clocks = <&gcc GCC_DISP_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>;
+ clock-names = "iface",
+ "ahb",
+ "core";
+
+ power-domains = <&dispcc MDSS_GDSC>;
+
+ iommus = <&apps_smmu 0x400 0x0>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ status = "disabled";
+
+ mdss_mdp: display-controller@5e01000 {
+ compatible = "qcom,sm6125-dpu";
+ reg = <0x05e01000 0x83208>,
+ <0x05eb0000 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_ROT_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>,
+ <&gcc GCC_DISP_THROTTLE_CORE_CLK>;
+ clock-names = "bus",
+ "iface",
+ "rot",
+ "lut",
+ "core",
+ "vsync",
+ "throttle";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ assigned-clock-rates = <19200000>;
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmpd SM6125_VDDCX>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&mdss_dsi0_in>;
+ };
+ };
+ };
+
+ mdp_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-192000000 {
+ opp-hz = /bits/ 64 <192000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ };
+
+ opp-256000000 {
+ opp-hz = /bits/ 64 <256000000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+
+ opp-307200000 {
+ opp-hz = /bits/ 64 <307200000>;
+ required-opps = <&rpmpd_opp_svs_plus>;
+ };
+
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ required-opps = <&rpmpd_opp_nom>;
+ };
+
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ required-opps = <&rpmpd_opp_turbo>;
+ };
+ };
+ };
+
+ mdss_dsi0: dsi@5e94000 {
+ compatible = "qcom,sm6125-dsi-ctrl", "qcom,mdss-dsi-ctrl";
+ reg = <0x05e94000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC0_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmpd SM6125_VDDCX>;
+
+ phys = <&mdss_dsi0_phy>;
+ phy-names = "dsi";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ mdss_dsi0_in: endpoint {
+ remote-endpoint = <&dpu_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ mdss_dsi0_out: endpoint {
+ };
+ };
+ };
+
+ dsi_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-164000000 {
+ opp-hz = /bits/ 64 <164000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ };
+
+ opp-187500000 {
+ opp-hz = /bits/ 64 <187500000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+ };
+ };
+
+ mdss_dsi0_phy: phy@5e94400 {
+ compatible = "qcom,sm6125-dsi-phy-14nm";
+ reg = <0x05e94400 0x100>,
+ <0x05e94500 0x300>,
+ <0x05e94800 0x188>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface",
+ "ref";
+
+ required-opps = <&rpmpd_opp_nom>;
+ power-domains = <&rpmpd SM6125_VDDMX>;
+
+ status = "disabled";
+ };
+ };
+
+ dispcc: clock-controller@5f00000 {
+ compatible = "qcom,sm6125-dispcc";
+ reg = <0x05f00000 0x20000>;
+
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&mdss_dsi0_phy 0>,
+ <&mdss_dsi0_phy 1>,
+ <0>,
+ <0>,
+ <0>,
+ <&gcc GCC_DISP_AHB_CLK>,
+ <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>;
+ clock-names = "bi_tcxo",
+ "dsi0_phy_pll_out_byteclk",
+ "dsi0_phy_pll_out_dsiclk",
+ "dsi1_phy_pll_out_dsiclk",
+ "dp_phy_pll_link_clk",
+ "dp_phy_pll_vco_div_clk",
+ "cfg_ahb_clk",
+ "gcc_disp_gpll0_div_clk_src";
+
+ required-opps = <&rpmpd_opp_ret>;
+ power-domains = <&rpmpd SM6125_VDDCX>;
+
+ #clock-cells = <1>;
+ #power-domain-cells = <1>;
};
apps_smmu: iommu@c600000 {
compatible = "qcom,sm6125-smmu-500", "qcom,smmu-500", "arm,mmu-500";
- reg = <0xc600000 0x80000>;
+ reg = <0x0c600000 0x80000>;
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/arch/arm64/boot/dts/qcom/sm7125-xiaomi-common.dtsi b/arch/arm64/boot/dts/qcom/sm7125-xiaomi-common.dtsi
new file mode 100644
index 000000000000..e55cd83c19b8
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm7125-xiaomi-common.dtsi
@@ -0,0 +1,423 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/arm/qcom,ids.h>
+#include <dt-bindings/firmware/qcom,scm.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include "sm7125.dtsi"
+#include "pm6150.dtsi"
+#include "pm6150l.dtsi"
+
+/delete-node/ &ipa_fw_mem;
+/delete-node/ &rmtfs_mem;
+
+/ {
+ chassis-type = "handset";
+
+ qcom,msm-id = <QCOM_ID_SM7125 0>;
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ framebuffer@9c000000 {
+ compatible = "simple-framebuffer";
+ reg = <0x0 0x9c000000 0x0 (1080 * 2400 * 4)>;
+ width = <1080>;
+ height = <2400>;
+ stride = <(1080 * 4)>;
+ format = "a8r8g8b8";
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>;
+ };
+ };
+
+ gpio_keys: gpio-keys {
+ compatible = "gpio-keys";
+
+ key-vol-up {
+ label = "Volume Up";
+ linux,code = <KEY_VOLUMEUP>;
+ gpios = <&pm6150l_gpios 2 GPIO_ACTIVE_LOW>;
+ debounce-interval = <15>;
+ linux,can-disable;
+ wakeup-source;
+ };
+ };
+
+ reserved-memory {
+ mpss_mem: memory@86000000 {
+ reg = <0x0 0x86000000 0x0 0x8400000>;
+ no-map;
+ };
+
+ venus_mem: memory@8ee00000 {
+ reg = <0x0 0x8ee00000 0x0 0x500000>;
+ no-map;
+ };
+
+ cdsp_mem: memory@8f300000 {
+ reg = <0x0 0x8f300000 0x0 0x1e00000>;
+ no-map;
+ };
+
+ adsp_mem: memory@91100000 {
+ reg = <0x0 0x91100000 0x0 0x2800000>;
+ no-map;
+ };
+
+ wlan_mem: memory@93900000 {
+ reg = <0x0 0x93900000 0x0 0x200000>;
+ no-map;
+ };
+
+ ipa_fw_mem: memory@93b00000 {
+ reg = <0x0 0x93b00000 0x0 0x10000>;
+ no-map;
+ };
+
+ gpu_mem: memory@93b15000 {
+ reg = <0x0 0x93b15000 0x0 0x2000>;
+ no-map;
+ };
+
+ cont_splash_mem: memory@9c000000 {
+ reg = <0x0 0x9c000000 0x0 (1080 * 2400 * 4)>;
+ no-map;
+ };
+
+ pstore_mem: ramoops@9d800000 {
+ compatible = "ramoops";
+ reg = <0x0 0x9d800000 0x0 0x400000>;
+ record-size = <0x80000>;
+ pmsg-size = <0x200000>;
+ console-size = <0x100000>;
+ };
+
+ rmtfs_mem: memory@fa601000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0x0 0xfa601000 0x0 0x200000>;
+ no-map;
+
+ qcom,client-id = <1>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
+ };
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm6150-rpmh-regulators";
+ qcom,pmic-id = "a";
+
+ vreg_s1a_1p1: smps1 {
+ regulator-min-microvolt = <1128000>;
+ regulator-max-microvolt = <1128000>;
+ };
+
+ vreg_s4a_1p0: smps4 {
+ regulator-min-microvolt = <824000>;
+ regulator-max-microvolt = <1120000>;
+ };
+
+ vreg_s5a_2p0: smps5 {
+ regulator-min-microvolt = <1744000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ vreg_l1a_1p2: ldo1 {
+ regulator-min-microvolt = <1178000>;
+ regulator-max-microvolt = <1256000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2a_1p0: ldo2 {
+ regulator-min-microvolt = <944000>;
+ regulator-max-microvolt = <1056000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3a_1p0: ldo3 {
+ regulator-min-microvolt = <968000>;
+ regulator-max-microvolt = <1064000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4a_0p88: ldo4 {
+ regulator-min-microvolt = <824000>;
+ regulator-max-microvolt = <928000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5a_2p7: ldo5 {
+ regulator-min-microvolt = <2496000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6a_0p6: ldo6 {
+ regulator-min-microvolt = <568000>;
+ regulator-max-microvolt = <648000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9a_0p664: ldo9 {
+ regulator-min-microvolt = <488000>;
+ regulator-max-microvolt = <800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l10a_1p8: ldo10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1832000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11a_1p8: ldo11 {
+ regulator-min-microvolt = <1696000>;
+ regulator-max-microvolt = <1904000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l12a_1p8: ldo12 {
+ regulator-min-microvolt = <1696000>;
+ regulator-max-microvolt = <1952000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13a_1p8: ldo13 {
+ regulator-min-microvolt = <1696000>;
+ regulator-max-microvolt = <1904000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14a_1p8: ldo14 {
+ regulator-min-microvolt = <1728000>;
+ regulator-max-microvolt = <1832000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l15a_1p8: ldo15 {
+ regulator-min-microvolt = <1696000>;
+ regulator-max-microvolt = <1904000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l16a_2p7: ldo16 {
+ regulator-min-microvolt = <2496000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l17a_3p1: ldo17 {
+ regulator-min-microvolt = <2920000>;
+ regulator-max-microvolt = <3232000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l18a_3p0: ldo18 {
+ regulator-min-microvolt = <1696000>;
+ regulator-max-microvolt = <1904000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l19a_3p0: ldo19 {
+ regulator-min-microvolt = <2696000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm6150l-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vreg_s8c_1p3: smps8 {
+ regulator-min-microvolt = <1120000>;
+ regulator-max-microvolt = <1408000>;
+ };
+
+ vreg_l1c_1p8: ldo1 {
+ regulator-min-microvolt = <1616000>;
+ regulator-max-microvolt = <1984000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2c_1p3: ldo2 {
+ regulator-min-microvolt = <1168000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3c_1p23: ldo3 {
+ regulator-min-microvolt = <1144000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4c_1p8: ldo4 {
+ regulator-min-microvolt = <1648000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5c_1p8: ldo5 {
+ regulator-min-microvolt = <1648000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6c_3p0: ldo6 {
+ regulator-min-microvolt = <1648000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7c_3p0: ldo7 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3312000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8c_1p8: ldo8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1904000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9c_2p9: ldo9 {
+ regulator-min-microvolt = <2952000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l10c_3p3: ldo10 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11c_3p3: ldo11 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_bob: bob {
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+ };
+ };
+};
+
+&dispcc {
+ /* HACK: disable until a panel driver is ready to retain simplefb */
+ status = "disabled";
+};
+
+&pm6150_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&pm6150_rtc {
+ status = "okay";
+};
+
+&sdhc_2 {
+ cd-gpios = <&tlmm 69 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default","sleep";
+ pinctrl-0 = <&sdc2_on>;
+ pinctrl-1 = <&sdc2_off>;
+ vmmc-supply = <&vreg_l9c_2p9>;
+ vqmmc-supply = <&vreg_l6c_3p0>;
+ status = "okay";
+};
+
+&tlmm {
+ gpio-reserved-ranges = <0 4>, <34 4>, <59 4>;
+
+ sdc2_on: sdc2-on-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ bias-disable;
+ drive-strength = <16>;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ sd-cd-pins {
+ pins = "gpio69";
+ function = "gpio";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+ };
+
+ sdc2_off: sdc2-off-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ sd-cd-pins {
+ pins = "gpio69";
+ function = "gpio";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+ };
+};
+
+&usb_1 {
+ qcom,select-utmi-as-pipe-clk;
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "peripheral";
+ maximum-speed = "high-speed";
+ status = "okay";
+};
+
+&usb_1_hsphy {
+ vdd-supply = <&vreg_l4a_0p88>;
+ vdda-phy-dpdm-supply = <&vreg_l17a_3p1>;
+ vdda-pll-supply = <&vreg_l11a_1p8>;
+ status = "okay";
+};
+
+&usb_1_qmpphy {
+ vdda-phy-supply = <&vreg_l4a_0p88>;
+ vdda-pll-supply = <&vreg_l3c_1p23>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sm7125-xiaomi-joyeuse.dts b/arch/arm64/boot/dts/qcom/sm7125-xiaomi-joyeuse.dts
new file mode 100644
index 000000000000..e010d1957509
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm7125-xiaomi-joyeuse.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include "sm7125-xiaomi-common.dtsi"
+
+/ {
+ model = "Xiaomi Redmi Note 9 Pro (Global)";
+ compatible = "xiaomi,joyeuse", "qcom,sm7125";
+
+ /* required for bootloader to select correct board */
+ qcom,board-id = <0x50022 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sm7125.dtsi b/arch/arm64/boot/dts/qcom/sm7125.dtsi
new file mode 100644
index 000000000000..12dd72859a43
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm7125.dtsi
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+#include "sc7180.dtsi"
+
+/* SM7125 uses Kryo 465 instead of Kryo 468 */
+&CPU0 { compatible = "qcom,kryo465"; };
+&CPU1 { compatible = "qcom,kryo465"; };
+&CPU2 { compatible = "qcom,kryo465"; };
+&CPU3 { compatible = "qcom,kryo465"; };
+&CPU4 { compatible = "qcom,kryo465"; };
+&CPU5 { compatible = "qcom,kryo465"; };
+&CPU6 { compatible = "qcom,kryo465"; };
+&CPU7 { compatible = "qcom,kryo465"; };
diff --git a/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts b/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts
index 18171c5d8a38..ade619805519 100644
--- a/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts
+++ b/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts
@@ -5,9 +5,14 @@
/dts-v1/;
+/* PM7250B is configured to use SID2/3 */
+#define PM7250B_SID 2
+#define PM7250B_SID1 3
+
/* PMK8350 (in reality a PMK8003) is configured to use SID6 instead of 0 */
#define PMK8350_SID 6
+#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/iio/qcom,spmi-adc7-pmk8350.h>
#include <dt-bindings/input/input.h>
@@ -75,7 +80,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
};
@@ -386,36 +391,10 @@
};
&i2c10 {
- clock-frequency = <400000>;
- status = "okay";
-
/* PM8008 PMIC @ 8 and 9 */
/* PX8618 @ 26 */
/* SMB1395 PMIC @ 34 */
-
- haptics@5a {
- compatible = "awinic,aw8695";
- reg = <0x5a>;
- interrupts-extended = <&tlmm 85 IRQ_TYPE_EDGE_FALLING>;
- reset-gpios = <&tlmm 90 GPIO_ACTIVE_HIGH>;
-
- awinic,f0-preset = <2350>;
- awinic,f0-coefficient = <260>;
- awinic,f0-calibration-percent = <7>;
- awinic,drive-level = <125>;
-
- awinic,f0-detection-play-time = <5>;
- awinic,f0-detection-wait-time = <3>;
- awinic,f0-detection-repeat = <2>;
- awinic,f0-detection-trace = <15>;
-
- awinic,boost-debug = /bits/ 8 <0x30 0xeb 0xd4>;
- awinic,tset = /bits/ 8 <0x12>;
- awinic,r-spare = /bits/ 8 <0x68>;
-
- awinic,bemf-upper-threshold = <4104>;
- awinic,bemf-lower-threshold = <1016>;
- };
+ /* awinic,aw8695 @ 5a */
};
&ipa {
diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
index 06c53000bb74..97623af13464 100644
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -5,7 +5,9 @@
*/
#include <dt-bindings/dma/qcom-gpi.h>
+#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy-qcom-qmp.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
#include <dt-bindings/clock/qcom,rpmh.h>
@@ -720,7 +722,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
camera_mem: memory@8b700000 {
@@ -1873,7 +1875,7 @@
power-domains = <&gcc PCIE_0_GDSC>;
- phys = <&pcie0_lane>;
+ phys = <&pcie0_phy>;
phy-names = "pciephy";
perst-gpio = <&tlmm 35 GPIO_ACTIVE_HIGH>;
@@ -1887,14 +1889,22 @@
pcie0_phy: phy@1c06000 {
compatible = "qcom,sm8150-qmp-gen3x1-pcie-phy";
- reg = <0 0x01c06000 0 0x1c0>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c06000 0 0x1000>;
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
<&gcc GCC_PCIE_0_CFG_AHB_CLK>,
- <&gcc GCC_PCIE0_PHY_REFGEN_CLK>;
- clock-names = "aux", "cfg_ahb", "refgen";
+ <&gcc GCC_PCIE_0_CLKREF_CLK>,
+ <&gcc GCC_PCIE0_PHY_REFGEN_CLK>,
+ <&gcc GCC_PCIE_0_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "refgen",
+ "pipe";
+
+ clock-output-names = "pcie_0_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_0_PHY_BCR>;
reset-names = "phy";
@@ -1903,18 +1913,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie0_lane: phy@1c06200 {
- reg = <0 0x01c06200 0 0x170>, /* tx */
- <0 0x01c06400 0 0x200>, /* rx */
- <0 0x01c06800 0 0x1f0>, /* pcs */
- <0 0x01c06c00 0 0xf4>; /* "pcs_lane" same as pcs_misc? */
- clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
- clock-names = "pipe0";
-
- #phy-cells = <0>;
- clock-output-names = "pcie_0_pipe_clk";
- };
};
pcie1: pci@1c08000 {
@@ -1971,7 +1969,7 @@
power-domains = <&gcc PCIE_1_GDSC>;
- phys = <&pcie1_lane>;
+ phys = <&pcie1_phy>;
phy-names = "pciephy";
perst-gpio = <&tlmm 102 GPIO_ACTIVE_HIGH>;
@@ -1985,14 +1983,22 @@
pcie1_phy: phy@1c0e000 {
compatible = "qcom,sm8150-qmp-gen3x2-pcie-phy";
- reg = <0 0x01c0e000 0 0x1c0>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c0e000 0 0x1000>;
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
<&gcc GCC_PCIE_1_CFG_AHB_CLK>,
- <&gcc GCC_PCIE1_PHY_REFGEN_CLK>;
- clock-names = "aux", "cfg_ahb", "refgen";
+ <&gcc GCC_PCIE_1_CLKREF_CLK>,
+ <&gcc GCC_PCIE1_PHY_REFGEN_CLK>,
+ <&gcc GCC_PCIE_1_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "refgen",
+ "pipe";
+
+ clock-output-names = "pcie_1_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_1_PHY_BCR>;
reset-names = "phy";
@@ -2001,20 +2007,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie1_lane: phy@1c0e200 {
- reg = <0 0x01c0e200 0 0x170>, /* tx0 */
- <0 0x01c0e400 0 0x200>, /* rx0 */
- <0 0x01c0ea00 0 0x1f0>, /* pcs */
- <0 0x01c0e600 0 0x170>, /* tx1 */
- <0 0x01c0e800 0 0x200>, /* rx1 */
- <0 0x01c0ee00 0 0xf4>; /* "pcs_com" same as pcs_misc? */
- clocks = <&gcc GCC_PCIE_1_PIPE_CLK>;
- clock-names = "pipe0";
-
- #phy-cells = <0>;
- clock-output-names = "pcie_1_pipe_clk";
- };
};
ufs_mem_hc: ufshc@1d84000 {
@@ -3434,38 +3426,27 @@
resets = <&gcc GCC_QUSB2PHY_SEC_BCR>;
};
- usb_1_qmpphy: phy@88e9000 {
- compatible = "qcom,sm8150-qmp-usb3-phy";
- reg = <0 0x088e9000 0 0x18c>,
- <0 0x088e8000 0 0x10>;
- status = "disabled";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ usb_1_qmpphy: phy@88e8000 {
+ compatible = "qcom,sm8150-qmp-usb3-dp-phy";
+ reg = <0 0x088e8000 0 0x3000>;
clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
- <&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_USB3_PRIM_CLKREF_CLK>,
- <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
- clock-names = "aux", "ref_clk_src", "ref", "com_aux";
+ <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+ <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+ clock-names = "aux",
+ "ref",
+ "com_aux",
+ "usb3_pipe";
resets = <&gcc GCC_USB3_DP_PHY_PRIM_BCR>,
<&gcc GCC_USB3_PHY_PRIM_BCR>;
reset-names = "phy", "common";
- usb_1_ssphy: phy@88e9200 {
- reg = <0 0x088e9200 0 0x200>,
- <0 0x088e9400 0 0x200>,
- <0 0x088e9c00 0 0x218>,
- <0 0x088e9600 0 0x200>,
- <0 0x088e9800 0 0x200>,
- <0 0x088e9a00 0 0x100>;
- #clock-cells = <0>;
- #phy-cells = <0>;
- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "usb3_phy_pipe_clk_src";
- };
+ #clock-cells = <1>;
+ #phy-cells = <1>;
+
+ status = "disabled";
};
usb_2_qmpphy: phy@88eb000 {
@@ -3606,7 +3587,7 @@
iommus = <&apps_smmu 0x140 0>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
- phys = <&usb_1_hsphy>, <&usb_1_ssphy>;
+ phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
};
};
@@ -3941,8 +3922,8 @@
<&mdss_dsi0_phy 1>,
<&mdss_dsi1_phy 0>,
<&mdss_dsi1_phy 1>,
- <0>,
- <0>;
+ <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
clock-names = "bi_tcxo",
"dsi0_phy_pll_out_byteclk",
"dsi0_phy_pll_out_dsiclk",
diff --git a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
index ecdc20bc10f5..e07d0311ecb5 100644
--- a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
@@ -18,7 +18,12 @@
qcom,msm-id = <356 0x20001>; /* SM8250 v2.1 */
qcom,board-id = <0x10008 0>;
+ aliases {
+ serial0 = &uart12;
+ };
+
chosen {
+ stdout-path = "serial0:115200n8";
#address-cells = <2>;
#size-cells = <2>;
ranges;
diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
index a4e58ad731c3..be970472f6c4 100644
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -15,6 +15,7 @@
#include <dt-bindings/interconnect/qcom,osm-l3.h>
#include <dt-bindings/interconnect/qcom,sm8250.h>
#include <dt-bindings/mailbox/qcom-ipcc.h>
+#include <dt-bindings/phy/phy-qcom-qmp.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/power/qcom,rpmhpd.h>
#include <dt-bindings/soc/qcom,apr.h>
@@ -371,6 +372,12 @@
};
};
+ qup_virt: interconnect-qup-virt {
+ compatible = "qcom,sm8250-qup-virt";
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
+
cpu0_opp_table: opp-table-cpu0 {
compatible = "operating-points-v2";
opp-shared;
@@ -1023,6 +1030,13 @@
dmas = <&gpi_dma2 0 0 QCOM_GPI_I2C>,
<&gpi_dma2 1 0 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>,
+ <&aggre1_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1039,6 +1053,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>,
+ <&aggre1_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1055,6 +1075,13 @@
dmas = <&gpi_dma2 0 1 QCOM_GPI_I2C>,
<&gpi_dma2 1 1 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>,
+ <&aggre1_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1071,6 +1098,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>,
+ <&aggre1_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1087,6 +1120,13 @@
dmas = <&gpi_dma2 0 2 QCOM_GPI_I2C>,
<&gpi_dma2 1 2 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>,
+ <&aggre1_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1103,6 +1143,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>,
+ <&aggre1_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1119,6 +1165,13 @@
dmas = <&gpi_dma2 0 3 QCOM_GPI_I2C>,
<&gpi_dma2 1 3 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>,
+ <&aggre1_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1135,6 +1188,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>,
+ <&aggre1_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1150,6 +1209,10 @@
interrupts = <GIC_SPI 585 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
status = "disabled";
};
@@ -1164,6 +1227,13 @@
dmas = <&gpi_dma2 0 4 QCOM_GPI_I2C>,
<&gpi_dma2 1 4 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>,
+ <&aggre1_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1180,6 +1250,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>,
+ <&aggre1_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1195,6 +1271,10 @@
interrupts = <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
status = "disabled";
};
@@ -1209,6 +1289,13 @@
dmas = <&gpi_dma2 0 5 QCOM_GPI_I2C>,
<&gpi_dma2 1 5 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>,
+ <&aggre1_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1225,6 +1312,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>,
+ <&aggre1_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1277,6 +1370,13 @@
dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>,
<&gpi_dma0 1 0 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1293,6 +1393,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1309,6 +1415,13 @@
dmas = <&gpi_dma0 0 1 QCOM_GPI_I2C>,
<&gpi_dma0 1 1 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1325,6 +1438,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1341,6 +1460,13 @@
dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>,
<&gpi_dma0 1 2 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1357,6 +1483,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1372,6 +1504,10 @@
interrupts = <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
status = "disabled";
};
@@ -1386,6 +1522,13 @@
dmas = <&gpi_dma0 0 3 QCOM_GPI_I2C>,
<&gpi_dma0 1 3 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1402,6 +1545,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1418,6 +1567,13 @@
dmas = <&gpi_dma0 0 4 QCOM_GPI_I2C>,
<&gpi_dma0 1 4 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1434,6 +1590,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1450,6 +1612,13 @@
dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>,
<&gpi_dma0 1 5 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1466,6 +1635,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1482,6 +1657,13 @@
dmas = <&gpi_dma0 0 6 QCOM_GPI_I2C>,
<&gpi_dma0 1 6 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1498,6 +1680,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1513,6 +1701,10 @@
interrupts = <GIC_SPI 607 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
status = "disabled";
};
@@ -1527,6 +1719,13 @@
dmas = <&gpi_dma0 0 7 QCOM_GPI_I2C>,
<&gpi_dma0 1 7 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1543,6 +1742,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1592,6 +1797,13 @@
dmas = <&gpi_dma1 0 0 QCOM_GPI_I2C>,
<&gpi_dma1 1 0 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>,
+ <&aggre1_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1608,6 +1820,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>,
+ <&aggre1_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1624,6 +1842,13 @@
dmas = <&gpi_dma1 0 1 QCOM_GPI_I2C>,
<&gpi_dma1 1 1 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>,
+ <&aggre1_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1640,6 +1865,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>,
+ <&aggre1_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1656,6 +1887,13 @@
dmas = <&gpi_dma1 0 2 QCOM_GPI_I2C>,
<&gpi_dma1 1 2 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>,
+ <&aggre1_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1672,6 +1910,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>,
+ <&aggre1_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1688,6 +1932,13 @@
dmas = <&gpi_dma1 0 3 QCOM_GPI_I2C>,
<&gpi_dma1 1 3 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>,
+ <&aggre1_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1704,6 +1955,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>,
+ <&aggre1_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1720,6 +1977,13 @@
dmas = <&gpi_dma1 0 4 QCOM_GPI_I2C>,
<&gpi_dma1 1 4 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>,
+ <&aggre1_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1736,6 +2000,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>,
+ <&aggre1_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1751,6 +2021,10 @@
interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
status = "disabled";
};
@@ -1765,6 +2039,13 @@
dmas = <&gpi_dma1 0 5 QCOM_GPI_I2C>,
<&gpi_dma1 1 5 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ power-domains = <&rpmhpd SM8250_CX>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>,
+ <&aggre1_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1781,6 +2062,12 @@
dma-names = "tx", "rx";
power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qup_opp_table>;
+ interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>,
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>,
+ <&aggre1_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1898,7 +2185,7 @@
power-domains = <&gcc PCIE_0_GDSC>;
- phys = <&pcie0_lane>;
+ phys = <&pcie0_phy>;
phy-names = "pciephy";
perst-gpios = <&tlmm 79 GPIO_ACTIVE_LOW>;
@@ -1913,15 +2200,23 @@
pcie0_phy: phy@1c06000 {
compatible = "qcom,sm8250-qmp-gen3x1-pcie-phy";
- reg = <0 0x01c06000 0 0x1c0>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c06000 0 0x1000>;
+
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
<&gcc GCC_PCIE_0_CFG_AHB_CLK>,
<&gcc GCC_PCIE_WIFI_CLKREF_EN>,
- <&gcc GCC_PCIE0_PHY_REFGEN_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "refgen";
+ <&gcc GCC_PCIE0_PHY_REFGEN_CLK>,
+ <&gcc GCC_PCIE_0_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "refgen",
+ "pipe";
+
+ clock-output-names = "pcie_0_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_0_PHY_BCR>;
reset-names = "phy";
@@ -1930,20 +2225,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie0_lane: phy@1c06200 {
- reg = <0 0x01c06200 0 0x170>, /* tx */
- <0 0x01c06400 0 0x200>, /* rx */
- <0 0x01c06800 0 0x1f0>, /* pcs */
- <0 0x01c06c00 0 0xf4>; /* "pcs_lane" same as pcs_misc? */
- clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
- clock-names = "pipe0";
-
- #phy-cells = <0>;
-
- #clock-cells = <0>;
- clock-output-names = "pcie_0_pipe_clk";
- };
};
pcie1: pci@1c08000 {
@@ -2005,7 +2286,7 @@
power-domains = <&gcc PCIE_1_GDSC>;
- phys = <&pcie1_lane>;
+ phys = <&pcie1_phy>;
phy-names = "pciephy";
perst-gpios = <&tlmm 82 GPIO_ACTIVE_LOW>;
@@ -2020,15 +2301,23 @@
pcie1_phy: phy@1c0e000 {
compatible = "qcom,sm8250-qmp-gen3x2-pcie-phy";
- reg = <0 0x01c0e000 0 0x1c0>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c0e000 0 0x1000>;
+
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
<&gcc GCC_PCIE_1_CFG_AHB_CLK>,
<&gcc GCC_PCIE_WIGIG_CLKREF_EN>,
- <&gcc GCC_PCIE1_PHY_REFGEN_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "refgen";
+ <&gcc GCC_PCIE1_PHY_REFGEN_CLK>,
+ <&gcc GCC_PCIE_1_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "refgen",
+ "pipe";
+
+ clock-output-names = "pcie_1_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_1_PHY_BCR>;
reset-names = "phy";
@@ -2037,22 +2326,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie1_lane: phy@1c0e200 {
- reg = <0 0x01c0e200 0 0x170>, /* tx0 */
- <0 0x01c0e400 0 0x200>, /* rx0 */
- <0 0x01c0ea00 0 0x1f0>, /* pcs */
- <0 0x01c0e600 0 0x170>, /* tx1 */
- <0 0x01c0e800 0 0x200>, /* rx1 */
- <0 0x01c0ee00 0 0xf4>; /* "pcs_com" same as pcs_misc? */
- clocks = <&gcc GCC_PCIE_1_PIPE_CLK>;
- clock-names = "pipe0";
-
- #phy-cells = <0>;
-
- #clock-cells = <0>;
- clock-output-names = "pcie_1_pipe_clk";
- };
};
pcie2: pci@1c10000 {
@@ -2114,7 +2387,7 @@
power-domains = <&gcc PCIE_2_GDSC>;
- phys = <&pcie2_lane>;
+ phys = <&pcie2_phy>;
phy-names = "pciephy";
perst-gpios = <&tlmm 85 GPIO_ACTIVE_LOW>;
@@ -2129,15 +2402,23 @@
pcie2_phy: phy@1c16000 {
compatible = "qcom,sm8250-qmp-modem-pcie-phy";
- reg = <0 0x01c16000 0 0x1c0>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c16000 0 0x1000>;
+
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
<&gcc GCC_PCIE_2_CFG_AHB_CLK>,
<&gcc GCC_PCIE_MDM_CLKREF_EN>,
- <&gcc GCC_PCIE2_PHY_REFGEN_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "refgen";
+ <&gcc GCC_PCIE2_PHY_REFGEN_CLK>,
+ <&gcc GCC_PCIE_2_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "refgen",
+ "pipe";
+
+ clock-output-names = "pcie_2_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_2_PHY_BCR>;
reset-names = "phy";
@@ -2146,22 +2427,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie2_lane: phy@1c16200 {
- reg = <0 0x01c16200 0 0x170>, /* tx0 */
- <0 0x01c16400 0 0x200>, /* rx0 */
- <0 0x01c16a00 0 0x1f0>, /* pcs */
- <0 0x01c16600 0 0x170>, /* tx1 */
- <0 0x01c16800 0 0x200>, /* rx1 */
- <0 0x01c16e00 0 0xf4>; /* "pcs_com" same as pcs_misc? */
- clocks = <&gcc GCC_PCIE_2_PIPE_CLK>;
- clock-names = "pipe0";
-
- #phy-cells = <0>;
-
- #clock-cells = <0>;
- clock-output-names = "pcie_2_pipe_clk";
- };
};
ufs_mem_hc: ufshc@1d84000 {
@@ -3580,47 +3845,45 @@
resets = <&gcc GCC_QUSB2PHY_SEC_BCR>;
};
- usb_1_qmpphy: phy@88e9000 {
+ usb_1_qmpphy: phy@88e8000 {
compatible = "qcom,sm8250-qmp-usb3-dp-phy";
- reg = <0 0x088e9000 0 0x200>,
- <0 0x088e8000 0 0x40>,
- <0 0x088ea000 0 0x200>;
+ reg = <0 0x088e8000 0 0x3000>;
status = "disabled";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
<&rpmhcc RPMH_CXO_CLK>,
- <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
- clock-names = "aux", "ref_clk_src", "com_aux";
+ <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+ <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+ clock-names = "aux",
+ "ref",
+ "com_aux",
+ "usb3_pipe";
resets = <&gcc GCC_USB3_DP_PHY_PRIM_BCR>,
<&gcc GCC_USB3_PHY_PRIM_BCR>;
reset-names = "phy", "common";
- usb_1_ssphy: usb3-phy@88e9200 {
- reg = <0 0x088e9200 0 0x200>,
- <0 0x088e9400 0 0x200>,
- <0 0x088e9c00 0 0x400>,
- <0 0x088e9600 0 0x200>,
- <0 0x088e9800 0 0x200>,
- <0 0x088e9a00 0 0x100>;
- #clock-cells = <0>;
- #phy-cells = <0>;
- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "usb3_phy_pipe_clk_src";
- };
+ #clock-cells = <1>;
+ #phy-cells = <1>;
- dp_phy: dp-phy@88ea200 {
- reg = <0 0x088ea200 0 0x200>,
- <0 0x088ea400 0 0x200>,
- <0 0x088eaa00 0 0x200>,
- <0 0x088ea600 0 0x200>,
- <0 0x088ea800 0 0x200>;
- #phy-cells = <0>;
- #clock-cells = <1>;
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ usb_1_qmpphy_out: endpoint {};
+ };
+
+ port@1 {
+ reg = <1>;
+ };
+
+ port@2 {
+ reg = <2>;
+
+ usb_1_qmpphy_dp_in: endpoint {};
+ };
};
};
@@ -3892,8 +4155,12 @@
iommus = <&apps_smmu 0x0 0x0>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
- phys = <&usb_1_hsphy>, <&usb_1_ssphy>;
+ phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
+
+ port {
+ usb_1_role_switch_out: endpoint {};
+ };
};
};
@@ -4383,6 +4650,14 @@
remote-endpoint = <&mdss_dsi1_in>;
};
};
+
+ port@2 {
+ reg = <2>;
+
+ dpu_intf0_out: endpoint {
+ remote-endpoint = <&mdss_dp_in>;
+ };
+ };
};
mdp_opp_table: opp-table {
@@ -4410,6 +4685,85 @@
};
};
+ mdss_dp: displayport-controller@ae90000 {
+ compatible = "qcom,sm8250-dp", "qcom,sm8350-dp";
+ reg = <0 0xae90000 0 0x200>,
+ <0 0xae90200 0 0x200>,
+ <0 0xae90400 0 0x600>,
+ <0 0xae91000 0 0x400>,
+ <0 0xae91400 0 0x400>;
+ interrupt-parent = <&mdss>;
+ interrupts = <12>;
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_AUX_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_LINK_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK>;
+ clock-names = "core_iface",
+ "core_aux",
+ "ctrl_link",
+ "ctrl_link_iface",
+ "stream_pixel";
+
+ assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
+ assigned-clock-parents = <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
+
+ phys = <&usb_1_qmpphy QMP_USB43DP_DP_PHY>;
+ phy-names = "dp";
+
+ #sound-dai-cells = <0>;
+
+ operating-points-v2 = <&dp_opp_table>;
+ power-domains = <&rpmhpd SM8250_MMCX>;
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ mdss_dp_in: endpoint {
+ remote-endpoint = <&dpu_intf0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ mdss_dp_out: endpoint {
+ };
+ };
+ };
+
+ dp_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-160000000 {
+ opp-hz = /bits/ 64 <160000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-270000000 {
+ opp-hz = /bits/ 64 <270000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-540000000 {
+ opp-hz = /bits/ 64 <540000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+
+ opp-810000000 {
+ opp-hz = /bits/ 64 <810000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+ };
+ };
+
mdss_dsi0: dsi@ae94000 {
compatible = "qcom,sm8250-dsi-ctrl",
"qcom,mdss-dsi-ctrl";
@@ -4586,8 +4940,8 @@
<&mdss_dsi0_phy 1>,
<&mdss_dsi1_phy 0>,
<&mdss_dsi1_phy 1>,
- <&dp_phy 0>,
- <&dp_phy 1>;
+ <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
clock-names = "bi_tcxo",
"dsi0_phy_pll_out_byteclk",
"dsi0_phy_pll_out_dsiclk",
diff --git a/arch/arm64/boot/dts/qcom/sm8350-hdk.dts b/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
index 4013d25a7df3..b43d264ed42b 100644
--- a/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
@@ -7,7 +7,12 @@
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include "sm8350.dtsi"
+#include "pm8350.dtsi"
+#include "pm8350b.dtsi"
+#include "pm8350c.dtsi"
#include "pmk8350.dtsi"
+#include "pmr735a.dtsi"
+#include "pmr735b.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SM8350 HDK";
@@ -294,6 +299,81 @@
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
};
+
+ regulators-2 {
+ compatible = "qcom,pmr735a-rpmh-regulators";
+ qcom,pmic-id = "e";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+
+ vdd-l1-l2-supply = <&vreg_s2e_0p85>;
+ vdd-l3-supply = <&vreg_s1e_1p25>;
+ vdd-l4-supply = <&vreg_s1c_1p86>;
+ vdd-l5-l6-supply = <&vreg_s1c_1p86>;
+ vdd-l7-bob-supply = <&vreg_bob>;
+
+ vreg_s1e_1p25: smps1 {
+ regulator-name = "vreg_s1e_1p25";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1280000>;
+ };
+
+ vreg_s2e_0p85: smps2 {
+ regulator-name = "vreg_s2e_0p85";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <976000>;
+ };
+
+ vreg_s3e_2p20: smps3 {
+ regulator-name = "vreg_s3e_2p20";
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2352000>;
+ };
+
+ vreg_l1e_0p9: ldo1 {
+ regulator-name = "vreg_l1e_0p9";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <912000>;
+ };
+
+ vreg_l2e_1p2: ldo2 {
+ regulator-name = "vreg_l2e_0p8";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vreg_l3e_1p2: ldo3 {
+ regulator-name = "vreg_l3e_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vreg_l4e_1p7: ldo4 {
+ regulator-name = "vreg_l4e_1p7";
+ regulator-min-microvolt = <1776000>;
+ regulator-max-microvolt = <1872000>;
+ };
+
+ vreg_l5e_0p8: ldo5 {
+ regulator-name = "vreg_l5e_0p8";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ };
+
+ vreg_l6e_0p8: ldo6 {
+ regulator-name = "vreg_l6e_0p8";
+ regulator-min-microvolt = <480000>;
+ regulator-max-microvolt = <904000>;
+ };
+
+ vreg_l7e_2p8: ldo7 {
+ regulator-name = "vreg_l7e_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+ };
};
&cdsp {
@@ -760,6 +840,7 @@
vcc-max-microamp = <800000>;
vccq-supply = <&vreg_l9b_1p2>;
vccq-max-microamp = <900000>;
+ vdd-hba-supply = <&vreg_l9b_1p2>;
};
&ufs_mem_phy {
diff --git a/arch/arm64/boot/dts/qcom/sm8350-mtp.dts b/arch/arm64/boot/dts/qcom/sm8350-mtp.dts
index c5a6c8745606..8bee57f3b25a 100644
--- a/arch/arm64/boot/dts/qcom/sm8350-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8350-mtp.dts
@@ -325,6 +325,7 @@
vcc-max-microamp = <800000>;
vccq-supply = <&vreg_l9b_1p2>;
vccq-max-microamp = <900000>;
+ vdd-hba-supply = <&vreg_l9b_1p2>;
};
&ufs_mem_phy {
diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi
index 00604bf7724f..b46236235b7f 100644
--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi
@@ -10,6 +10,7 @@
#include <dt-bindings/clock/qcom,gpucc-sm8350.h>
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/dma/qcom-gpi.h>
+#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interconnect/qcom,sm8350.h>
#include <dt-bindings/mailbox/qcom-ipcc.h>
@@ -503,7 +504,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
hyp_reserved_mem: memory@d0000000 {
@@ -2964,7 +2965,7 @@
};
qup_uart18_default: qup-uart18-default-state {
- pins = "gpio58", "gpio59";
+ pins = "gpio68", "gpio69";
function = "qup18";
drive-strength = <2>;
bias-disable;
diff --git a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
index bd5e8181f2aa..20153d08edde 100644
--- a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
@@ -915,14 +915,23 @@
"SpkrRight IN", "WSA_SPK2 OUT",
"IN1_HPHL", "HPHL_OUT",
"IN2_HPHR", "HPHR_OUT",
+ "AMIC1", "MIC BIAS1",
"AMIC2", "MIC BIAS2",
- "VA DMIC0", "MIC BIAS1",
- "VA DMIC1", "MIC BIAS1",
- "VA DMIC2", "MIC BIAS3",
- "TX DMIC0", "MIC BIAS1",
- "TX DMIC1", "MIC BIAS2",
- "TX DMIC2", "MIC BIAS3",
- "TX SWR_ADC1", "ADC2_OUTPUT";
+ "AMIC3", "MIC BIAS3",
+ "AMIC4", "MIC BIAS3",
+ "AMIC5", "MIC BIAS4",
+ "VA DMIC0", "MIC BIAS3",
+ "VA DMIC1", "MIC BIAS3",
+ "VA DMIC2", "MIC BIAS1",
+ "VA DMIC3", "MIC BIAS1",
+ "TX DMIC0", "MIC BIAS3",
+ "TX DMIC1", "MIC BIAS3",
+ "TX DMIC2", "MIC BIAS1",
+ "TX DMIC3", "MIC BIAS1",
+ "TX SWR_INPUT0", "ADC1_OUTPUT",
+ "TX SWR_INPUT1", "ADC2_OUTPUT",
+ "TX SWR_INPUT2", "ADC3_OUTPUT",
+ "TX SWR_INPUT3", "ADC4_OUTPUT";
wcd-playback-dai-link {
link-name = "WCD Playback";
@@ -1073,6 +1082,7 @@
vcc-max-microamp = <1100000>;
vccq-supply = <&vreg_l9b_1p2>;
vccq-max-microamp = <1200000>;
+ vdd-hba-supply = <&vreg_l9b_1p2>;
};
&ufs_mem_phy {
diff --git a/arch/arm64/boot/dts/qcom/sm8450-qrd.dts b/arch/arm64/boot/dts/qcom/sm8450-qrd.dts
index 37479327707f..c7d05945aa51 100644
--- a/arch/arm64/boot/dts/qcom/sm8450-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sm8450-qrd.dts
@@ -443,6 +443,7 @@
vcc-max-microamp = <1100000>;
vccq-supply = <&vreg_l9b_1p2>;
vccq-max-microamp = <1200000>;
+ vdd-hba-supply = <&vreg_l9b_1p2>;
};
&ufs_mem_phy {
diff --git a/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi
index 001fb2723fbb..8b29fcf483a3 100644
--- a/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi
@@ -80,7 +80,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
ramoops@ffc00000 {
diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
index 2a60cf8bd891..1783fa78bdbc 100644
--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
@@ -10,6 +10,7 @@
#include <dt-bindings/clock/qcom,sm8450-dispcc.h>
#include <dt-bindings/clock/qcom,sm8450-videocc.h>
#include <dt-bindings/dma/qcom-gpi.h>
+#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/mailbox/qcom-ipcc.h>
#include <dt-bindings/phy/phy-qcom-qmp.h>
@@ -540,7 +541,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
xbl_sc_mem2: memory@a6e00000 {
@@ -750,8 +751,8 @@
#power-domain-cells = <1>;
clocks = <&rpmhcc RPMH_CXO_CLK>,
<&sleep_clk>,
- <&pcie0_lane>,
- <&pcie1_lane>,
+ <&pcie0_phy>,
+ <&pcie1_phy>,
<0>,
<&ufs_mem_phy_lanes 0>,
<&ufs_mem_phy_lanes 1>,
@@ -1738,11 +1739,6 @@
};
};
- rng: rng@10c3000 {
- compatible = "qcom,sm8450-prng-ee", "qcom,prng-ee";
- reg = <0 0x010c3000 0 0x1000>;
- };
-
pcie0: pci@1c00000 {
compatible = "qcom,pcie-sm8450-pcie0";
reg = <0 0x01c00000 0 0x3000>,
@@ -1780,7 +1776,7 @@
clocks = <&gcc GCC_PCIE_0_PIPE_CLK>,
<&gcc GCC_PCIE_0_PIPE_CLK_SRC>,
- <&pcie0_lane>,
+ <&pcie0_phy>,
<&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_PCIE_0_AUX_CLK>,
<&gcc GCC_PCIE_0_CFG_AHB_CLK>,
@@ -1811,7 +1807,7 @@
power-domains = <&gcc PCIE_0_GDSC>;
- phys = <&pcie0_lane>;
+ phys = <&pcie0_phy>;
phy-names = "pciephy";
perst-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
@@ -1825,15 +1821,23 @@
pcie0_phy: phy@1c06000 {
compatible = "qcom,sm8450-qmp-gen3x1-pcie-phy";
- reg = <0 0x01c06000 0 0x200>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c06000 0 0x2000>;
+
clocks = <&gcc GCC_PCIE_0_AUX_CLK>,
<&gcc GCC_PCIE_0_CFG_AHB_CLK>,
<&gcc GCC_PCIE_0_CLKREF_EN>,
- <&gcc GCC_PCIE_0_PHY_RCHNG_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "refgen";
+ <&gcc GCC_PCIE_0_PHY_RCHNG_CLK>,
+ <&gcc GCC_PCIE_0_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "rchng",
+ "pipe";
+
+ clock-output-names = "pcie_0_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_0_PHY_BCR>;
reset-names = "phy";
@@ -1842,19 +1846,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie0_lane: phy@1c06200 {
- reg = <0 0x01c06e00 0 0x200>, /* tx */
- <0 0x01c07000 0 0x200>, /* rx */
- <0 0x01c06200 0 0x200>, /* pcs */
- <0 0x01c06600 0 0x200>; /* pcs_pcie */
- clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
- clock-names = "pipe0";
-
- #clock-cells = <0>;
- #phy-cells = <0>;
- clock-output-names = "pcie_0_pipe_clk";
- };
};
pcie1: pci@1c08000 {
@@ -1894,7 +1885,7 @@
clocks = <&gcc GCC_PCIE_1_PIPE_CLK>,
<&gcc GCC_PCIE_1_PIPE_CLK_SRC>,
- <&pcie1_lane>,
+ <&pcie1_phy>,
<&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_PCIE_1_AUX_CLK>,
<&gcc GCC_PCIE_1_CFG_AHB_CLK>,
@@ -1923,7 +1914,7 @@
power-domains = <&gcc PCIE_1_GDSC>;
- phys = <&pcie1_lane>;
+ phys = <&pcie1_phy>;
phy-names = "pciephy";
perst-gpios = <&tlmm 97 GPIO_ACTIVE_LOW>;
@@ -1935,17 +1926,25 @@
status = "disabled";
};
- pcie1_phy: phy@1c0f000 {
+ pcie1_phy: phy@1c0e000 {
compatible = "qcom,sm8450-qmp-gen4x2-pcie-phy";
- reg = <0 0x01c0f000 0 0x200>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x01c0e000 0 0x2000>;
+
clocks = <&gcc GCC_PCIE_1_PHY_AUX_CLK>,
<&gcc GCC_PCIE_1_CFG_AHB_CLK>,
<&gcc GCC_PCIE_1_CLKREF_EN>,
- <&gcc GCC_PCIE_1_PHY_RCHNG_CLK>;
- clock-names = "aux", "cfg_ahb", "ref", "refgen";
+ <&gcc GCC_PCIE_1_PHY_RCHNG_CLK>,
+ <&gcc GCC_PCIE_1_PIPE_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "rchng",
+ "pipe";
+
+ clock-output-names = "pcie_1_pipe_clk";
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
resets = <&gcc GCC_PCIE_1_PHY_BCR>;
reset-names = "phy";
@@ -1954,21 +1953,6 @@
assigned-clock-rates = <100000000>;
status = "disabled";
-
- pcie1_lane: phy@1c0e000 {
- reg = <0 0x01c0e000 0 0x200>, /* tx */
- <0 0x01c0e200 0 0x300>, /* rx */
- <0 0x01c0f200 0 0x200>, /* pcs */
- <0 0x01c0e800 0 0x200>, /* tx */
- <0 0x01c0ea00 0 0x300>, /* rx */
- <0 0x01c0f400 0 0xc00>; /* pcs_pcie */
- clocks = <&gcc GCC_PCIE_1_PIPE_CLK>;
- clock-names = "pipe0";
-
- #clock-cells = <0>;
- #phy-cells = <0>;
- clock-output-names = "pcie_1_pipe_clk";
- };
};
config_noc: interconnect@1500000 {
diff --git a/arch/arm64/boot/dts/qcom/sm8550-mtp.dts b/arch/arm64/boot/dts/qcom/sm8550-mtp.dts
index f29cce5186ac..9a70875028b7 100644
--- a/arch/arm64/boot/dts/qcom/sm8550-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8550-mtp.dts
@@ -13,7 +13,8 @@
#include "pm8550ve.dtsi"
#include "pm8550vs.dtsi"
#include "pmk8550.dtsi"
-#include "pmr735d.dtsi"
+#include "pmr735d_a.dtsi"
+#include "pmr735d_b.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SM8550 MTP";
@@ -58,6 +59,7 @@
compatible = "qcom,sm8550-pmic-glink", "qcom,pmic-glink";
#address-cells = <1>;
#size-cells = <0>;
+ orientation-gpios = <&tlmm 11 GPIO_ACTIVE_HIGH>;
connector@0 {
compatible = "usb-c-connector";
@@ -797,8 +799,7 @@
vcc-max-microamp = <1300000>;
vccq-supply = <&vreg_l1g_1p2>;
vccq-max-microamp = <1200000>;
- vccq2-supply = <&vreg_l3g_1p2>;
- vccq2-max-microamp = <100>;
+ vdd-hba-supply = <&vreg_l3g_1p2>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm8550-qrd.dts b/arch/arm64/boot/dts/qcom/sm8550-qrd.dts
index 2c09ce8aeafd..eef811def39b 100644
--- a/arch/arm64/boot/dts/qcom/sm8550-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sm8550-qrd.dts
@@ -14,7 +14,8 @@
#include "pm8550ve.dtsi"
#include "pm8550vs.dtsi"
#include "pmk8550.dtsi"
-#include "pmr735d.dtsi"
+#include "pmr735d_a.dtsi"
+#include "pmr735d_b.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SM8550 QRD";
@@ -23,6 +24,7 @@
aliases {
serial0 = &uart7;
+ serial1 = &uart14;
};
wcd938x: audio-codec {
@@ -75,6 +77,7 @@
compatible = "qcom,sm8550-pmic-glink", "qcom,pmic-glink";
#address-cells = <1>;
#size-cells = <0>;
+ orientation-gpios = <&tlmm 11 GPIO_ACTIVE_HIGH>;
connector@0 {
compatible = "usb-c-connector";
@@ -765,6 +768,10 @@
status = "okay";
};
+&qupv3_id_1 {
+ status = "okay";
+};
+
&remoteproc_adsp {
firmware-name = "qcom/sm8550/adsp.mbn",
"qcom/sm8550/adsp_dtb.mbn";
@@ -842,6 +849,21 @@
&tlmm {
gpio-reserved-ranges = <32 8>;
+ bt_default: bt-default-state {
+ bt-en-pins {
+ pins = "gpio81";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ sw-ctrl-pins {
+ pins = "gpio82";
+ function = "gpio";
+ bias-pull-down;
+ };
+ };
+
sde_dsi_active: sde-dsi-active-state {
pins = "gpio133";
function = "gpio";
@@ -883,14 +905,36 @@
status = "okay";
};
+&uart14 {
+ status = "okay";
+
+ bluetooth {
+ compatible = "qcom,wcn7850-bt";
+
+ vddio-supply = <&vreg_l15b_1p8>;
+ vddaon-supply = <&vreg_s4e_0p95>;
+ vdddig-supply = <&vreg_s4e_0p95>;
+ vddrfa0p8-supply = <&vreg_s4e_0p95>;
+ vddrfa1p2-supply = <&vreg_s4g_1p25>;
+ vddrfa1p9-supply = <&vreg_s6g_1p86>;
+
+ max-speed = <3200000>;
+
+ enable-gpios = <&tlmm 81 GPIO_ACTIVE_HIGH>;
+ swctrl-gpios = <&tlmm 82 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&bt_default>;
+ pinctrl-names = "default";
+ };
+};
+
&ufs_mem_hc {
reset-gpios = <&tlmm 210 GPIO_ACTIVE_LOW>;
vcc-supply = <&vreg_l17b_2p5>;
vcc-max-microamp = <1300000>;
vccq-supply = <&vreg_l1g_1p2>;
vccq-max-microamp = <1200000>;
- vccq2-supply = <&vreg_l3g_1p2>;
- vccq2-max-microamp = <100>;
+ vdd-hba-supply = <&vreg_l3g_1p2>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi
index d115960bdeec..7b9ddde0b2c9 100644
--- a/arch/arm64/boot/dts/qcom/sm8550.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi
@@ -5,11 +5,13 @@
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/clock/qcom,sm8450-videocc.h>
+#include <dt-bindings/clock/qcom,sm8550-camcc.h>
#include <dt-bindings/clock/qcom,sm8550-gcc.h>
#include <dt-bindings/clock/qcom,sm8550-gpucc.h>
#include <dt-bindings/clock/qcom,sm8550-tcsr.h>
#include <dt-bindings/clock/qcom,sm8550-dispcc.h>
#include <dt-bindings/dma/qcom-gpi.h>
+#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interconnect/qcom,sm8550-rpmh.h>
@@ -570,7 +572,7 @@
no-map;
qcom,client-id = <1>;
- qcom,vmid = <15>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>;
};
mpss_dsm_mem: mpss-dsm-region@d4d00000 {
@@ -1054,6 +1056,20 @@
status = "disabled";
};
+ uart14: serial@898000 {
+ compatible = "qcom,geni-uart";
+ reg = <0 0x898000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP2_S6_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_uart14_default>, <&qup_uart14_cts_rts>;
+ interrupts = <GIC_SPI 461 IRQ_TYPE_LEVEL_HIGH>;
+ interconnects = <&clk_virt MASTER_QUP_CORE_2 0 &clk_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_2 0>;
+ interconnect-names = "qup-core", "qup-config";
+ status = "disabled";
+ };
+
i2c15: i2c@89c000 {
compatible = "qcom,geni-i2c";
reg = <0 0x0089c000 0 0x4000>;
@@ -2420,6 +2436,20 @@
#power-domain-cells = <1>;
};
+ camcc: clock-controller@ade0000 {
+ compatible = "qcom,sm8550-camcc";
+ reg = <0 0x0ade0000 0 0x20000>;
+ clocks = <&gcc GCC_CAMERA_AHB_CLK>,
+ <&bi_tcxo_div2>,
+ <&bi_tcxo_ao_div2>,
+ <&sleep_clk>;
+ power-domains = <&rpmhpd SM8550_MMCX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
mdss: display-subsystem@ae00000 {
compatible = "qcom,sm8550-mdss";
reg = <0 0x0ae00000 0 0x1000>;
@@ -3498,6 +3528,22 @@
bias-disable;
};
+ qup_uart14_default: qup-uart14-default-state {
+ /* TX, RX */
+ pins = "gpio78", "gpio79";
+ function = "qup2_se6";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_uart14_cts_rts: qup-uart14-cts-rts-state {
+ /* CTS, RTS */
+ pins = "gpio76", "gpio77";
+ function = "qup2_se6";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
sdc2_sleep: sdc2-sleep-state {
clk-pins {
pins = "sdc2_clk";
diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
index 7114cbbd8713..8ea68d582710 100644
--- a/arch/arm64/boot/dts/renesas/Makefile
+++ b/arch/arm64/boot/dts/renesas/Makefile
@@ -29,21 +29,35 @@ dtb-$(CONFIG_ARCH_R8A774E1) += r8a774e1-hihope-rzg2h-ex-idk-1110wr.dtb
dtb-$(CONFIG_ARCH_R8A774E1) += r8a774e1-hihope-rzg2h-ex-mipi-2.1.dtb
dtb-$(CONFIG_ARCH_R8A77951) += r8a77951-salvator-x.dtb
+r8a77951-salvator-x-panel-aa104xd12-dtbs := r8a77951-salvator-x.dtb salvator-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77951) += r8a77951-salvator-x-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A77951) += r8a77951-salvator-xs.dtb
+r8a77951-salvator-xs-panel-aa104xd12-dtbs := r8a77951-salvator-xs.dtb salvator-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77951) += r8a77951-salvator-xs-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A77951) += r8a77951-ulcb.dtb
dtb-$(CONFIG_ARCH_R8A77951) += r8a77951-ulcb-kf.dtb
dtb-$(CONFIG_ARCH_R8A77960) += r8a77960-salvator-x.dtb
+r8a77960-salvator-x-panel-aa104xd12-dtbs := r8a77960-salvator-x.dtb salvator-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77960) += r8a77960-salvator-x-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A77960) += r8a77960-salvator-xs.dtb
+r8a77960-salvator-xs-panel-aa104xd12-dtbs := r8a77960-salvator-xs.dtb salvator-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77960) += r8a77960-salvator-xs-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A77960) += r8a77960-ulcb.dtb
dtb-$(CONFIG_ARCH_R8A77960) += r8a77960-ulcb-kf.dtb
dtb-$(CONFIG_ARCH_R8A77961) += r8a77961-salvator-xs.dtb
+r8a77961-salvator-xs-panel-aa104xd12-dtbs := r8a77961-salvator-xs.dtb salvator-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77961) += r8a77961-salvator-xs-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A77961) += r8a77961-ulcb.dtb
dtb-$(CONFIG_ARCH_R8A77961) += r8a77961-ulcb-kf.dtb
dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-x.dtb
+r8a77965-salvator-x-panel-aa104xd12-dtbs := r8a77965-salvator-x.dtb salvator-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-x-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-xs.dtb
+r8a77965-salvator-xs-panel-aa104xd12-dtbs := r8a77965-salvator-xs.dtb salvator-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-xs-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-ulcb.dtb
dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-ulcb-kf.dtb
@@ -55,36 +69,60 @@ dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk.dtb
dtb-$(CONFIG_ARCH_R8A77980) += r8a77980a-condor-i.dtb
dtb-$(CONFIG_ARCH_R8A77990) += r8a77990-ebisu.dtb
+r8a77990-ebisu-panel-aa104xd12-dtbs := r8a77990-ebisu.dtb draak-ebisu-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77990) += r8a77990-ebisu-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A77995) += r8a77995-draak.dtb
+r8a77995-draak-panel-aa104xd12-dtbs := r8a77995-draak.dtb draak-ebisu-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77995) += r8a77995-draak-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A779A0) += r8a779a0-falcon.dtb
dtb-$(CONFIG_ARCH_R8A779F0) += r8a779f0-spider.dtb
+dtb-$(CONFIG_ARCH_R8A779F0) += r8a779f4-s4sk.dtb
dtb-$(CONFIG_ARCH_R8A779G0) += r8a779g0-white-hawk.dtb
dtb-$(CONFIG_ARCH_R8A779G0) += r8a779g0-white-hawk-ard-audio-da7212.dtbo
+r8a779g0-white-hawk-ard-audio-da7212-dtbs := r8a779g0-white-hawk.dtb r8a779g0-white-hawk-ard-audio-da7212.dtbo
+dtb-$(CONFIG_ARCH_R8A779G0) += r8a779g0-white-hawk-ard-audio-da7212.dtb
dtb-$(CONFIG_ARCH_R8A77951) += r8a779m1-salvator-xs.dtb
+r8a779m1-salvator-xs-panel-aa104xd12-dtbs := r8a779m1-salvator-xs.dtb salvator-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77951) += r8a779m1-salvator-xs-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A77951) += r8a779m1-ulcb.dtb
dtb-$(CONFIG_ARCH_R8A77951) += r8a779m1-ulcb-kf.dtb
dtb-$(CONFIG_ARCH_R8A77961) += r8a779m3-salvator-xs.dtb
+r8a779m3-salvator-xs-panel-aa104xd12-dtbs := r8a779m3-salvator-xs.dtb salvator-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77961) += r8a779m3-salvator-xs-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R8A77961) += r8a779m3-ulcb.dtb
dtb-$(CONFIG_ARCH_R8A77961) += r8a779m3-ulcb-kf.dtb
dtb-$(CONFIG_ARCH_R8A77965) += r8a779m5-salvator-xs.dtb
+r8a779m5-salvator-xs-panel-aa104xd12-dtbs := r8a779m5-salvator-xs.dtb salvator-panel-aa104xd12.dtbo
+dtb-$(CONFIG_ARCH_R8A77965) += r8a779m5-salvator-xs-panel-aa104xd12.dtb
dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043u11-smarc.dtb
dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043-smarc-pmod.dtbo
+r9a07g043u11-smarc-pmod-dtbs := r9a07g043u11-smarc.dtb r9a07g043-smarc-pmod.dtbo
+dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043u11-smarc-pmod.dtb
dtb-$(CONFIG_ARCH_R9A07G044) += r9a07g044c2-smarc.dtb
dtb-$(CONFIG_ARCH_R9A07G044) += r9a07g044c2-smarc-cru-csi-ov5645.dtbo
+r9a07g044c2-smarc-cru-csi-ov5645-dtbs := r9a07g044c2-smarc.dtb r9a07g044c2-smarc-cru-csi-ov5645.dtbo
+dtb-$(CONFIG_ARCH_R9A07G044) += r9a07g044c2-smarc-cru-csi-ov5645.dtb
+
dtb-$(CONFIG_ARCH_R9A07G044) += r9a07g044l2-smarc.dtb
dtb-$(CONFIG_ARCH_R9A07G044) += r9a07g044l2-smarc-cru-csi-ov5645.dtbo
+r9a07g044l2-smarc-cru-csi-ov5645-dtbs := r9a07g044l2-smarc.dtb r9a07g044l2-smarc-cru-csi-ov5645.dtbo
+dtb-$(CONFIG_ARCH_R9A07G044) += r9a07g044l2-smarc-cru-csi-ov5645.dtb
dtb-$(CONFIG_ARCH_R9A07G054) += r9a07g054l2-smarc.dtb
dtb-$(CONFIG_ARCH_R9A07G054) += r9a07g054l2-smarc-cru-csi-ov5645.dtbo
+r9a07g054l2-smarc-cru-csi-ov5645-dtbs := r9a07g054l2-smarc.dtb r9a07g054l2-smarc-cru-csi-ov5645.dtbo
+dtb-$(CONFIG_ARCH_R9A07G054) += r9a07g054l2-smarc-cru-csi-ov5645.dtb
+
+dtb-$(CONFIG_ARCH_R9A08G045) += r9a08g045s33-smarc.dtb
dtb-$(CONFIG_ARCH_R9A09G011) += r9a09g011-v2mevk2.dtb
diff --git a/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi b/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi
index 2e9927b97732..5a14f116f7a1 100644
--- a/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi
+++ b/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi
@@ -651,7 +651,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&versaclock6_bb 4>, <&audio_clk_b>,
<&audio_clk_c>,
- <&cpg CPG_CORE CPG_AUDIO_CLK_I>;
+ <&cpg CPG_MOD 922>;
status = "okay";
diff --git a/arch/arm64/boot/dts/renesas/ebisu.dtsi b/arch/arm64/boot/dts/renesas/ebisu.dtsi
index bbc29452d1be..f1a5778ef115 100644
--- a/arch/arm64/boot/dts/renesas/ebisu.dtsi
+++ b/arch/arm64/boot/dts/renesas/ebisu.dtsi
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the Ebisu board
+ * Device Tree Source for the Ebisu/Ebisu-4D board
*
* Copyright (C) 2018 Renesas Electronics Corp.
*/
diff --git a/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi b/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi
index 7fc0339a3ac9..66f3affe0469 100644
--- a/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi
+++ b/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi
@@ -112,7 +112,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&cs2000>,
<&audio_clk_c>,
- <&cpg CPG_CORE CPG_AUDIO_CLK_I>;
+ <&cpg CPG_MOD 922>;
rsnd_port: port {
rsnd_endpoint: endpoint {
diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
index 9065dc243428..95b0a1f6debf 100644
--- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
@@ -10,8 +10,6 @@
#include <dt-bindings/clock/r8a774a1-cpg-mssr.h>
#include <dt-bindings/power/r8a774a1-sysc.h>
-#define CPG_AUDIO_CLK_I R8A774A1_CLK_S0D4
-
/ {
compatible = "renesas,r8a774a1";
#address-cells = <2>;
@@ -1713,7 +1711,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&audio_clk_b>,
<&audio_clk_c>,
- <&cpg CPG_CORE R8A774A1_CLK_S0D4>;
+ <&cpg CPG_MOD 922>;
clock-names = "ssi-all",
"ssi.9", "ssi.8", "ssi.7", "ssi.6",
"ssi.5", "ssi.4", "ssi.3", "ssi.2",
diff --git a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi
index 75776decd218..786660fcdea4 100644
--- a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi
@@ -10,8 +10,6 @@
#include <dt-bindings/clock/r8a774b1-cpg-mssr.h>
#include <dt-bindings/power/r8a774b1-sysc.h>
-#define CPG_AUDIO_CLK_I R8A774B1_CLK_S0D4
-
/ {
compatible = "renesas,r8a774b1";
#address-cells = <2>;
@@ -1597,7 +1595,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&audio_clk_b>,
<&audio_clk_c>,
- <&cpg CPG_CORE R8A774B1_CLK_S0D4>;
+ <&cpg CPG_MOD 922>;
clock-names = "ssi-all",
"ssi.9", "ssi.8", "ssi.7", "ssi.6",
"ssi.5", "ssi.4", "ssi.3", "ssi.2",
diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
index ad2e87b039ac..eed94ffed7c1 100644
--- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
@@ -1350,7 +1350,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&audio_clk_b>,
<&audio_clk_c>,
- <&cpg CPG_CORE R8A774C0_CLK_ZA2>;
+ <&cpg CPG_MOD 922>;
clock-names = "ssi-all",
"ssi.9", "ssi.8", "ssi.7", "ssi.6",
"ssi.5", "ssi.4", "ssi.3", "ssi.2",
diff --git a/arch/arm64/boot/dts/renesas/r8a774e1.dtsi b/arch/arm64/boot/dts/renesas/r8a774e1.dtsi
index 2acf4067ab2f..175e5d296da6 100644
--- a/arch/arm64/boot/dts/renesas/r8a774e1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774e1.dtsi
@@ -10,8 +10,6 @@
#include <dt-bindings/clock/r8a774e1-cpg-mssr.h>
#include <dt-bindings/power/r8a774e1-sysc.h>
-#define CPG_AUDIO_CLK_I R8A774E1_CLK_S0D4
-
/ {
compatible = "renesas,r8a774e1";
#address-cells = <2>;
@@ -1809,7 +1807,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&audio_clk_b>,
<&audio_clk_c>,
- <&cpg CPG_CORE R8A774E1_CLK_S0D4>;
+ <&cpg CPG_MOD 922>;
clock-names = "ssi-all",
"ssi.9", "ssi.8", "ssi.7", "ssi.6",
"ssi.5", "ssi.4", "ssi.3", "ssi.2",
diff --git a/arch/arm64/boot/dts/renesas/r8a77951.dtsi b/arch/arm64/boot/dts/renesas/r8a77951.dtsi
index 6d15229d25ab..a4260d9291ba 100644
--- a/arch/arm64/boot/dts/renesas/r8a77951.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77951.dtsi
@@ -9,8 +9,6 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/r8a7795-sysc.h>
-#define CPG_AUDIO_CLK_I R8A7795_CLK_S0D4
-
#define SOC_HAS_HDMI1
#define SOC_HAS_SATA
#define SOC_HAS_USB2_CH2
@@ -2032,7 +2030,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&audio_clk_b>,
<&audio_clk_c>,
- <&cpg CPG_CORE R8A7795_CLK_S0D4>;
+ <&cpg CPG_MOD 922>;
clock-names = "ssi-all",
"ssi.9", "ssi.8", "ssi.7", "ssi.6",
"ssi.5", "ssi.4", "ssi.3", "ssi.2",
diff --git a/arch/arm64/boot/dts/renesas/r8a77960.dtsi b/arch/arm64/boot/dts/renesas/r8a77960.dtsi
index 17062ec506be..a631ead171b2 100644
--- a/arch/arm64/boot/dts/renesas/r8a77960.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77960.dtsi
@@ -9,8 +9,6 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/r8a7796-sysc.h>
-#define CPG_AUDIO_CLK_I R8A7796_CLK_S0D4
-
/ {
compatible = "renesas,r8a7796";
#address-cells = <2>;
@@ -1903,7 +1901,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&audio_clk_b>,
<&audio_clk_c>,
- <&cpg CPG_CORE R8A7796_CLK_S0D4>;
+ <&cpg CPG_MOD 922>;
clock-names = "ssi-all",
"ssi.9", "ssi.8", "ssi.7", "ssi.6",
"ssi.5", "ssi.4", "ssi.3", "ssi.2",
diff --git a/arch/arm64/boot/dts/renesas/r8a77961.dtsi b/arch/arm64/boot/dts/renesas/r8a77961.dtsi
index d3f47da1b626..7254912a241f 100644
--- a/arch/arm64/boot/dts/renesas/r8a77961.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77961.dtsi
@@ -9,8 +9,6 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/r8a77961-sysc.h>
-#define CPG_AUDIO_CLK_I R8A77961_CLK_S0D4
-
/ {
compatible = "renesas,r8a77961";
#address-cells = <2>;
@@ -1783,7 +1781,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&audio_clk_b>,
<&audio_clk_c>,
- <&cpg CPG_CORE R8A77961_CLK_S0D4>;
+ <&cpg CPG_MOD 922>;
clock-names = "ssi-all",
"ssi.9", "ssi.8", "ssi.7", "ssi.6",
"ssi.5", "ssi.4", "ssi.3", "ssi.2",
diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
index c75820038491..e57b9027066e 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
@@ -12,8 +12,6 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/r8a77965-sysc.h>
-#define CPG_AUDIO_CLK_I R8A77965_CLK_S0D4
-
#define SOC_HAS_SATA
/ {
@@ -1766,7 +1764,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&audio_clk_b>,
<&audio_clk_c>,
- <&cpg CPG_CORE R8A77965_CLK_S0D4>;
+ <&cpg CPG_MOD 922>;
clock-names = "ssi-all",
"ssi.9", "ssi.8", "ssi.7", "ssi.6",
"ssi.5", "ssi.4", "ssi.3", "ssi.2",
diff --git a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
index 9da0fd08f8c4..d5ac34a966f6 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the Ebisu board with R-Car E3
+ * Device Tree Source for the Ebisu/Ebisu-4D board with R-Car E3
*
* Copyright (C) 2018 Renesas Electronics Corp.
*/
diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
index 4c545eff9b42..8c2b28342387 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
@@ -1501,7 +1501,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&audio_clk_b>,
<&audio_clk_c>,
- <&cpg CPG_CORE R8A77990_CLK_ZA2>;
+ <&cpg CPG_MOD 922>;
clock-names = "ssi-all",
"ssi.9", "ssi.8", "ssi.7", "ssi.6",
"ssi.5", "ssi.4", "ssi.3", "ssi.2",
diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
index e25024a7b66c..8cf6473c63d3 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
@@ -1063,7 +1063,7 @@
<&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&audio_clk_b>,
- <&cpg CPG_CORE R8A77995_CLK_ZA2>;
+ <&cpg CPG_MOD 922>;
clock-names = "ssi-all",
"ssi.4", "ssi.3",
"src.6", "src.5",
diff --git a/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi
index 5cbde8e8fcd5..477f3114d2fd 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi
@@ -53,6 +53,12 @@
reg = <0x4 0x80000000 0x0 0x80000000>;
};
+ rc21012_pci: clk-rc21012-pci {
+ compatible = "fixed-clock";
+ clock-frequency = <100000000>;
+ #clock-cells = <0>;
+ };
+
rc21012_ufs: clk-rc21012-ufs {
compatible = "fixed-clock";
clock-frequency = <38400000>;
@@ -106,6 +112,12 @@
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
+
+ rc21012-gpio2-hog {
+ gpio-hog;
+ gpios = <5 GPIO_ACTIVE_LOW>;
+ output-high;
+ };
};
};
@@ -145,6 +157,18 @@
status = "okay";
};
+&pcie0_clkref {
+ compatible = "gpio-gate-clock";
+ clocks = <&rc21012_pci>;
+ enable-gpios = <&gpio2 15 GPIO_ACTIVE_LOW>;
+ /delete-property/ clock-frequency;
+};
+
+&pciec0 {
+ reset-gpio = <&gpio_exp_20 0 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
&pfc {
pinctrl-0 = <&scif_clk_pins>;
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
index ecdd5a523fa3..7fb4989cce8a 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
@@ -262,6 +262,20 @@
clock-frequency = <0>;
};
+ pcie0_clkref: pcie0-clkref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
+ pcie1_clkref: pcie1-clkref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
pmu_a55 {
compatible = "arm,cortex-a55-pmu";
interrupts-extended = <&gic GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
@@ -726,6 +740,126 @@
status = "disabled";
};
+ pciec0: pcie@e65d0000 {
+ compatible = "renesas,r8a779f0-pcie",
+ "renesas,rcar-gen4-pcie";
+ reg = <0 0xe65d0000 0 0x1000>, <0 0xe65d2000 0 0x0800>,
+ <0 0xe65d3000 0 0x2000>, <0 0xe65d5000 0 0x1200>,
+ <0 0xe65d6200 0 0x0e00>, <0 0xe65d7000 0 0x0400>,
+ <0 0xfe000000 0 0x400000>;
+ reg-names = "dbi", "dbi2", "atu", "dma", "app", "phy", "config";
+ interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi", "dma", "sft_ce", "app";
+ clocks = <&cpg CPG_MOD 624>, <&pcie0_clkref>;
+ clock-names = "core", "ref";
+ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
+ resets = <&cpg 624>;
+ reset-names = "pwr";
+ max-link-speed = <4>;
+ num-lanes = <2>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ bus-range = <0x00 0xff>;
+ device_type = "pci";
+ ranges = <0x01000000 0 0x00000000 0 0xfe000000 0 0x00400000>,
+ <0x02000000 0 0x30000000 0 0x30000000 0 0x10000000>;
+ dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &gic GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gic GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gic GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gic GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>;
+ snps,enable-cdm-check;
+ status = "disabled";
+ };
+
+ pciec1: pcie@e65d8000 {
+ compatible = "renesas,r8a779f0-pcie",
+ "renesas,rcar-gen4-pcie";
+ reg = <0 0xe65d8000 0 0x1000>, <0 0xe65da000 0 0x0800>,
+ <0 0xe65db000 0 0x2000>, <0 0xe65dd000 0 0x1200>,
+ <0 0xe65de200 0 0x0e00>, <0 0xe65df000 0 0x0400>,
+ <0 0xee900000 0 0x400000>;
+ reg-names = "dbi", "dbi2", "atu", "dma", "app", "phy", "config";
+ interrupts = <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi", "dma", "sft_ce", "app";
+ clocks = <&cpg CPG_MOD 625>, <&pcie1_clkref>;
+ clock-names = "core", "ref";
+ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
+ resets = <&cpg 625>;
+ reset-names = "pwr";
+ max-link-speed = <4>;
+ num-lanes = <2>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ bus-range = <0x00 0xff>;
+ device_type = "pci";
+ ranges = <0x01000000 0 0x00000000 0 0xee900000 0 0x00400000>,
+ <0x02000000 0 0xc0000000 0 0xc0000000 0 0x10000000>;
+ dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &gic GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gic GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gic GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gic GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>;
+ snps,enable-cdm-check;
+ status = "disabled";
+ };
+
+ pciec0_ep: pcie-ep@e65d0000 {
+ compatible = "renesas,r8a779f0-pcie-ep",
+ "renesas,rcar-gen4-pcie-ep";
+ reg = <0 0xe65d0000 0 0x2000>, <0 0xe65d2000 0 0x1000>,
+ <0 0xe65d3000 0 0x2000>, <0 0xe65d5000 0 0x1200>,
+ <0 0xe65d6200 0 0x0e00>, <0 0xe65d7000 0 0x0400>,
+ <0 0xfe000000 0 0x400000>;
+ reg-names = "dbi", "dbi2", "atu", "dma", "app", "phy", "addr_space";
+ interrupts = <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "dma", "sft_ce", "app";
+ clocks = <&cpg CPG_MOD 624>, <&pcie0_clkref>;
+ clock-names = "core", "ref";
+ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
+ resets = <&cpg 624>;
+ reset-names = "pwr";
+ max-link-speed = <4>;
+ num-lanes = <2>;
+ max-functions = /bits/ 8 <2>;
+ status = "disabled";
+ };
+
+ pciec1_ep: pcie-ep@e65d8000 {
+ compatible = "renesas,r8a779f0-pcie-ep",
+ "renesas,rcar-gen4-pcie-ep";
+ reg = <0 0xe65d8000 0 0x2000>, <0 0xe65da000 0 0x1000>,
+ <0 0xe65db000 0 0x2000>, <0 0xe65dd000 0 0x1200>,
+ <0 0xe65de200 0 0x0e00>, <0 0xe65df000 0 0x0400>,
+ <0 0xee900000 0 0x400000>;
+ reg-names = "dbi", "dbi2", "atu", "dma", "app", "phy", "addr_space";
+ interrupts = <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "dma", "sft_ce", "app";
+ clocks = <&cpg CPG_MOD 625>, <&pcie1_clkref>;
+ clock-names = "core", "ref";
+ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
+ resets = <&cpg 625>;
+ reset-names = "pwr";
+ max-link-speed = <4>;
+ num-lanes = <2>;
+ max-functions = /bits/ 8 <2>;
+ status = "disabled";
+ };
+
ufs: ufs@e6860000 {
compatible = "renesas,r8a779f0-ufs";
reg = <0 0xe6860000 0 0x100>;
diff --git a/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts b/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts
new file mode 100644
index 000000000000..abfda5c6ca16
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts
@@ -0,0 +1,240 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Device Tree Source for the R-Car S4 Starter Kit board
+ *
+ * Copyright (C) 2023 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include "r8a779f4.dtsi"
+
+/ {
+ model = "R-Car S4 Starter Kit board";
+ compatible = "renesas,s4sk", "renesas,r8a779f4", "renesas,r8a779f0";
+
+ aliases {
+ serial0 = &hscif0;
+ serial1 = &hscif1;
+ eth0 = &rswitch;
+ };
+
+ chosen {
+ bootargs = "ignore_loglevel rw root=/dev/nfs ip=on";
+ stdout-path = "serial0:921600n8";
+ };
+
+ memory@48000000 {
+ device_type = "memory";
+ /* first 128MB is reserved for secure area. */
+ /* The last 512MB is reserved for CR. */
+ reg = <0x0 0x48000000 0x0 0x58000000>;
+ };
+
+ memory@480000000 {
+ device_type = "memory";
+ reg = <0x4 0x80000000 0x0 0x80000000>;
+ };
+
+ vcc_sdhi: regulator-vcc-sdhi {
+ compatible = "regulator-fixed";
+ regulator-name = "SDHI Vcc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+};
+
+&eth_serdes {
+ status = "okay";
+};
+
+&extal_clk {
+ clock-frequency = <20000000>;
+};
+
+&extalr_clk {
+ clock-frequency = <32768>;
+};
+
+&hscif0 {
+ pinctrl-0 = <&hscif0_pins>;
+ pinctrl-names = "default";
+
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&hscif1 {
+ pinctrl-0 = <&hscif1_pins>;
+ pinctrl-names = "default";
+
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&i2c2 {
+ pinctrl-0 = <&i2c2_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+ clock-frequency = <400000>;
+};
+
+&i2c4 {
+ pinctrl-0 = <&i2c4_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+ clock-frequency = <400000>;
+};
+
+&i2c5 {
+ pinctrl-0 = <&i2c5_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+ clock-frequency = <400000>;
+
+ eeprom@50 {
+ compatible = "st,24c16", "atmel,24c16";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
+};
+
+&mmc0 {
+ pinctrl-0 = <&sd_pins>;
+ pinctrl-names = "default";
+
+ vmmc-supply = <&vcc_sdhi>;
+ cd-gpios = <&gpio1 23 GPIO_ACTIVE_LOW>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&pfc {
+ pinctrl-0 = <&scif_clk_pins>;
+ pinctrl-names = "default";
+
+ hscif0_pins: hscif0 {
+ groups = "hscif0_data", "hscif0_ctrl";
+ function = "hscif0";
+ };
+
+ hscif1_pins: hscif1 {
+ groups = "hscif1_data", "hscif1_ctrl";
+ function = "hscif1";
+ };
+
+ i2c2_pins: i2c2 {
+ groups = "i2c2";
+ function = "i2c2";
+ };
+
+ i2c4_pins: i2c4 {
+ groups = "i2c4";
+ function = "i2c4";
+ };
+
+ i2c5_pins: i2c5 {
+ groups = "i2c5";
+ function = "i2c5";
+ };
+
+ scif_clk_pins: scif_clk {
+ groups = "scif_clk";
+ function = "scif_clk";
+ };
+
+ sd_pins: sd {
+ groups = "mmc_data4", "mmc_ctrl";
+ function = "mmc";
+ power-source = <3300>;
+ };
+
+ tsn0_pins: tsn0 {
+ groups = "tsn0_mdio_b", "tsn0_link_b";
+ function = "tsn0";
+ drive-strength = <18>;
+ power-source = <3300>;
+ };
+
+ tsn1_pins: tsn1 {
+ groups = "tsn1_mdio_b", "tsn1_link_b";
+ function = "tsn1";
+ drive-strength = <18>;
+ power-source = <3300>;
+ };
+};
+
+&rswitch {
+ pinctrl-0 = <&tsn0_pins>, <&tsn1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ phy-handle = <&ic99>;
+ phy-mode = "sgmii";
+ phys = <&eth_serdes 0>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ic99: ethernet-phy@1 {
+ reg = <1>;
+ compatible = "ethernet-phy-ieee802.3-c45";
+ interrupt-parent = <&gpio3>;
+ interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ phy-handle = <&ic102>;
+ phy-mode = "sgmii";
+ phys = <&eth_serdes 1>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ic102: ethernet-phy@2 {
+ reg = <2>;
+ compatible = "ethernet-phy-ieee802.3-c45";
+ interrupt-parent = <&gpio3>;
+ interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
+ };
+
+ port@2 {
+ status = "disabled";
+ };
+ };
+};
+
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
+&scif_clk {
+ clock-frequency = <24000000>;
+};
+
+&ufs {
+ status = "okay";
+};
+
+&ufs30_clk {
+ clock-frequency = <38400000>;
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a779f4.dtsi b/arch/arm64/boot/dts/renesas/r8a779f4.dtsi
new file mode 100644
index 000000000000..ebed41892df3
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a779f4.dtsi
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Device Tree Source for the R-Car S4-8 (R8A779F4) SoC
+ *
+ * Copyright (C) 2023 Renesas Electronics Corp.
+ */
+
+#include "r8a779f0.dtsi"
+
+/ {
+ compatible = "renesas,r8a779f4", "renesas,r8a779f0";
+};
diff --git a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
new file mode 100644
index 000000000000..6c7b29b69d0e
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Device Tree Source for the RZ/G3S SoC
+ *
+ * Copyright (C) 2023 Renesas Electronics Corp.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/r9a08g045-cpg.h>
+
+/ {
+ compatible = "renesas,r9a08g045";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a55";
+ reg = <0>;
+ device_type = "cpu";
+ #cooling-cells = <2>;
+ next-level-cache = <&L3_CA55>;
+ enable-method = "psci";
+ clocks = <&cpg CPG_CORE R9A08G045_CLK_I>;
+ };
+
+ L3_CA55: cache-controller-0 {
+ compatible = "cache";
+ cache-level = <3>;
+ cache-unified;
+ cache-size = <0x40000>;
+ };
+ };
+
+ extal_clk: extal-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board. */
+ clock-frequency = <0>;
+ };
+
+ soc: soc {
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ scif0: serial@1004b800 {
+ compatible = "renesas,scif-r9a08g045", "renesas,scif-r9a07g044";
+ reg = <0 0x1004b800 0 0x400>;
+ interrupts = <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "eri", "rxi", "txi",
+ "bri", "dri", "tei";
+ clocks = <&cpg CPG_MOD R9A08G045_SCIF0_CLK_PCK>;
+ clock-names = "fck";
+ power-domains = <&cpg>;
+ resets = <&cpg R9A08G045_SCIF0_RST_SYSTEM_N>;
+ status = "disabled";
+ };
+
+ cpg: clock-controller@11010000 {
+ compatible = "renesas,r9a08g045-cpg";
+ reg = <0 0x11010000 0 0x10000>;
+ clocks = <&extal_clk>;
+ clock-names = "extal";
+ #clock-cells = <2>;
+ #reset-cells = <1>;
+ #power-domain-cells = <0>;
+ };
+
+ sysc: system-controller@11020000 {
+ compatible = "renesas,r9a08g045-sysc";
+ reg = <0 0x11020000 0 0x10000>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "lpm_int", "ca55stbydone_int",
+ "cm33stbyr_int", "ca55_deny";
+ status = "disabled";
+ };
+
+ pinctrl: pinctrl@11030000 {
+ compatible = "renesas,r9a08g045-pinctrl";
+ reg = <0 0x11030000 0 0x10000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&pinctrl 0 0 152>;
+ clocks = <&cpg CPG_MOD R9A08G045_GPIO_HCLK>;
+ power-domains = <&cpg>;
+ resets = <&cpg R9A08G045_GPIO_RSTN>,
+ <&cpg R9A08G045_GPIO_PORT_RESETN>,
+ <&cpg R9A08G045_GPIO_SPARE_RESETN>;
+ };
+
+ sdhi0: mmc@11c00000 {
+ compatible = "renesas,sdhi-r9a08g045", "renesas,rcar-gen3-sdhi";
+ reg = <0x0 0x11c00000 0 0x10000>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD R9A08G045_SDHI0_IMCLK>,
+ <&cpg CPG_MOD R9A08G045_SDHI0_CLK_HS>,
+ <&cpg CPG_MOD R9A08G045_SDHI0_IMCLK2>,
+ <&cpg CPG_MOD R9A08G045_SDHI0_ACLK>;
+ clock-names = "core", "clkh", "cd", "aclk";
+ resets = <&cpg R9A08G045_SDHI0_IXRST>;
+ power-domains = <&cpg>;
+ status = "disabled";
+ };
+
+ sdhi1: mmc@11c10000 {
+ compatible = "renesas,sdhi-r9a08g045", "renesas,rcar-gen3-sdhi";
+ reg = <0x0 0x11c10000 0 0x10000>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD R9A08G045_SDHI1_IMCLK>,
+ <&cpg CPG_MOD R9A08G045_SDHI1_CLK_HS>,
+ <&cpg CPG_MOD R9A08G045_SDHI1_IMCLK2>,
+ <&cpg CPG_MOD R9A08G045_SDHI1_ACLK>;
+ clock-names = "core", "clkh", "cd", "aclk";
+ resets = <&cpg R9A08G045_SDHI1_IXRST>;
+ power-domains = <&cpg>;
+ status = "disabled";
+ };
+
+ sdhi2: mmc@11c20000 {
+ compatible = "renesas,sdhi-r9a08g045", "renesas,rcar-gen3-sdhi";
+ reg = <0x0 0x11c20000 0 0x10000>;
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD R9A08G045_SDHI2_IMCLK>,
+ <&cpg CPG_MOD R9A08G045_SDHI2_CLK_HS>,
+ <&cpg CPG_MOD R9A08G045_SDHI2_IMCLK2>,
+ <&cpg CPG_MOD R9A08G045_SDHI2_ACLK>;
+ clock-names = "core", "clkh", "cd", "aclk";
+ resets = <&cpg R9A08G045_SDHI2_IXRST>;
+ power-domains = <&cpg>;
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@12400000 {
+ compatible = "arm,gic-v3";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0x0 0x12400000 0 0x40000>,
+ <0x0 0x12440000 0 0x60000>;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts-extended = <&gic GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+ <&gic GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+ <&gic GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+ <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
diff --git a/arch/arm64/boot/dts/renesas/r9a08g045s33-smarc.dts b/arch/arm64/boot/dts/renesas/r9a08g045s33-smarc.dts
new file mode 100644
index 000000000000..6b57e0e02dbe
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r9a08g045s33-smarc.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Device Tree Source for the RZ/G3S SMARC EVK board
+ *
+ * Copyright (C) 2023 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+
+#include "r9a08g045s33.dtsi"
+#include "rzg3s-smarc-som.dtsi"
+#include "rzg3s-smarc.dtsi"
+
+/ {
+ model = "Renesas SMARC EVK version 2 based on r9a08g045s33";
+ compatible = "renesas,smarc2-evk", "renesas,rzg3s-smarcm",
+ "renesas,r9a08g045s33", "renesas,r9a08g045";
+};
diff --git a/arch/arm64/boot/dts/renesas/r9a08g045s33.dtsi b/arch/arm64/boot/dts/renesas/r9a08g045s33.dtsi
new file mode 100644
index 000000000000..3351f26c7a2a
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r9a08g045s33.dtsi
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Device Tree Source for the RZ/G3S R9A08G045S33 SoC specific part
+ *
+ * Copyright (C) 2023 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+
+#include "r9a08g045.dtsi"
+
+/ {
+ compatible = "renesas,r9a08g045s33", "renesas,r9a08g045";
+};
diff --git a/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi b/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi
index a7594ba3a998..b7a3e6caa386 100644
--- a/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi
@@ -32,12 +32,6 @@
stdout-path = "serial0:115200n8";
};
- audio_mclock: audio_mclock {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <11289600>;
- };
-
snd_rzg2l: sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
@@ -55,7 +49,7 @@
};
codec_dai: simple-audio-card,codec {
- clocks = <&audio_mclock>;
+ clocks = <&versa3 2>;
sound-dai = <&wm8978>;
};
};
@@ -76,6 +70,12 @@
gpios-states = <1>;
states = <3300000 1>, <1800000 0>;
};
+
+ x1: x1-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ };
};
&audio_clk1 {
diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
index 68eab8e26bf2..37807f1bda4d 100644
--- a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
@@ -110,6 +110,26 @@
#sound-dai-cells = <0>;
reg = <0x1a>;
};
+
+ versa3: clock-generator@68 {
+ compatible = "renesas,5p35023";
+ reg = <0x68>;
+ #clock-cells = <1>;
+ clocks = <&x1>;
+
+ renesas,settings = [
+ 80 00 11 19 4c 02 23 7f 83 19 08 a9 5f 25 24 bf
+ 00 14 7a e1 00 00 00 00 01 55 59 bb 3f 30 90 b6
+ 80 b0 45 c4 95
+ ];
+
+ assigned-clocks = <&versa3 0>, <&versa3 1>,
+ <&versa3 2>, <&versa3 3>,
+ <&versa3 4>, <&versa3 5>;
+ assigned-clock-rates = <24000000>, <11289600>,
+ <11289600>, <12000000>,
+ <25000000>, <12288000>;
+ };
};
#if PMOD_MTU3
diff --git a/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi
index 83fce96a2575..859bc8745e66 100644
--- a/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi
@@ -126,6 +126,26 @@
#sound-dai-cells = <0>;
reg = <0x1a>;
};
+
+ versa3: clock-generator@68 {
+ compatible = "renesas,5p35023";
+ reg = <0x68>;
+ #clock-cells = <1>;
+ clocks = <&x1>;
+
+ renesas,settings = [
+ 80 00 11 19 4c 02 23 7f 83 19 08 a9 5f 25 24 bf
+ 00 14 7a e1 00 00 00 00 01 55 59 bb 3f 30 90 b6
+ 80 b0 45 c4 95
+ ];
+
+ assigned-clocks = <&versa3 0>, <&versa3 1>,
+ <&versa3 2>, <&versa3 3>,
+ <&versa3 4>, <&versa3 5>;
+ assigned-clock-rates = <24000000>, <11289600>,
+ <11289600>, <12000000>,
+ <25000000>, <12288000>;
+ };
};
#if PMOD_MTU3
diff --git a/arch/arm64/boot/dts/renesas/rzg2ul-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2ul-smarc.dtsi
index 8eb411aac80d..de590996e10a 100644
--- a/arch/arm64/boot/dts/renesas/rzg2ul-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2ul-smarc.dtsi
@@ -20,6 +20,30 @@
sound-dai = <&ssi1>;
};
+&i2c0 {
+ clock-frequency = <400000>;
+
+ versa3: clock-generator@68 {
+ compatible = "renesas,5p35023";
+ reg = <0x68>;
+ #clock-cells = <1>;
+ clocks = <&x1>;
+
+ renesas,settings = [
+ 80 00 11 19 4c 02 23 7f 83 19 08 a9 5f 25 24 bf
+ 00 14 7a e1 00 00 00 00 01 55 59 bb 3f 30 90 b6
+ 80 b0 45 c4 95
+ ];
+
+ assigned-clocks = <&versa3 0>, <&versa3 1>,
+ <&versa3 2>, <&versa3 3>,
+ <&versa3 4>, <&versa3 5>;
+ assigned-clock-rates = <24000000>, <11289600>,
+ <11289600>, <12000000>,
+ <25000000>, <12288000>;
+ };
+};
+
&i2c1 {
wm8978: codec@1a {
compatible = "wlf,wm8978";
diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi
new file mode 100644
index 000000000000..a199de8f8b02
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Device Tree Source for the R9A08G045S33 SMARC Carrier-II's SoM board.
+ *
+ * Copyright (C) 2023 Renesas Electronics Corp.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/rzg2l-pinctrl.h>
+
+/*
+ * Signals of SW_CONFIG switches:
+ * @SW_SD0_DEV_SEL:
+ * 0 - SD0 is connected to eMMC
+ * 1 - SD0 is connected to uSD0 card
+ */
+#define SW_SD0_DEV_SEL 1
+
+/ {
+ compatible = "renesas,rzg3s-smarcm", "renesas,r9a08g045s33", "renesas,r9a08g045";
+
+ aliases {
+ mmc0 = &sdhi0;
+ };
+
+ chosen {
+ bootargs = "ignore_loglevel";
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@48000000 {
+ device_type = "memory";
+ /* First 128MB is reserved for secure area. */
+ reg = <0x0 0x48000000 0x0 0x38000000>;
+ };
+
+ vcc_sdhi0: regulator0 {
+ compatible = "regulator-fixed";
+ regulator-name = "SDHI0 Vcc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&pinctrl RZG2L_GPIO(2, 1) GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+#if SW_SD0_DEV_SEL
+ vccq_sdhi0: regulator1 {
+ compatible = "regulator-gpio";
+ regulator-name = "SDHI0 VccQ";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&pinctrl RZG2L_GPIO(2, 2) GPIO_ACTIVE_HIGH>;
+ gpios-states = <1>;
+ states = <3300000 1>, <1800000 0>;
+ };
+#else
+ reg_1p8v: regulator1 {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+#endif
+};
+
+&extal_clk {
+ clock-frequency = <24000000>;
+};
+
+#if SW_SD0_DEV_SEL
+/* SD0 slot */
+&sdhi0 {
+ pinctrl-0 = <&sdhi0_pins>;
+ pinctrl-1 = <&sdhi0_uhs_pins>;
+ pinctrl-names = "default", "state_uhs";
+ vmmc-supply = <&vcc_sdhi0>;
+ vqmmc-supply = <&vccq_sdhi0>;
+ bus-width = <4>;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ max-frequency = <125000000>;
+ status = "okay";
+};
+#else
+/* eMMC */
+&sdhi0 {
+ pinctrl-0 = <&sdhi0_emmc_pins>;
+ pinctrl-1 = <&sdhi0_emmc_pins>;
+ pinctrl-names = "default", "state_uhs";
+ vmmc-supply = <&vcc_sdhi0>;
+ vqmmc-supply = <&reg_1p8v>;
+ bus-width = <8>;
+ mmc-hs200-1_8v;
+ non-removable;
+ fixed-emmc-driver-type = <1>;
+ max-frequency = <125000000>;
+ status = "okay";
+};
+#endif
+
+&pinctrl {
+ sdhi0_pins: sd0 {
+ data {
+ pins = "SD0_DATA0", "SD0_DATA1", "SD0_DATA2", "SD0_DATA3";
+ power-source = <3300>;
+ };
+
+ ctrl {
+ pins = "SD0_CLK", "SD0_CMD";
+ power-source = <3300>;
+ };
+
+ cd {
+ pinmux = <RZG2L_PORT_PINMUX(0, 0, 1)>; /* SD0_CD */
+ };
+ };
+
+ sdhi0_uhs_pins: sd0-uhs {
+ data {
+ pins = "SD0_DATA0", "SD0_DATA1", "SD0_DATA2", "SD0_DATA3";
+ power-source = <1800>;
+ };
+
+ ctrl {
+ pins = "SD0_CLK", "SD0_CMD";
+ power-source = <1800>;
+ };
+
+ cd {
+ pinmux = <RZG2L_PORT_PINMUX(0, 0, 1)>; /* SD0_CD */
+ };
+ };
+
+ sdhi0_emmc_pins: sd0-emmc {
+ pins = "SD0_DATA0", "SD0_DATA1", "SD0_DATA2", "SD0_DATA3",
+ "SD0_DATA4", "SD0_DATA5", "SD0_DATA6", "SD0_DATA7",
+ "SD0_CLK", "SD0_CMD", "SD0_RST#";
+ power-source = <1800>;
+ };
+};
diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi
new file mode 100644
index 000000000000..e7073a09ed2e
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Device Tree Source for the RZ SMARC Carrier-II Board.
+ *
+ * Copyright (C) 2023 Renesas Electronics Corp.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/rzg2l-pinctrl.h>
+
+/ {
+ aliases {
+ serial0 = &scif0;
+ };
+};
+
+&pinctrl {
+ scif0_pins: scif0 {
+ pinmux = <RZG2L_PORT_PINMUX(6, 3, 1)>, /* RXD */
+ <RZG2L_PORT_PINMUX(6, 4, 1)>; /* TXD */
+ };
+};
+
+&scif0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&scif0_pins>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/renesas/salvator-common.dtsi b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
index 4a3d5037821f..1eb4883b3219 100644
--- a/arch/arm64/boot/dts/renesas/salvator-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
@@ -822,7 +822,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&cs2000>,
<&audio_clk_c>,
- <&cpg CPG_CORE CPG_AUDIO_CLK_I>;
+ <&cpg CPG_MOD 922>;
ports {
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card-mix+split.dtsi b/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card-mix+split.dtsi
index 672b0a224ef9..be6d7a035739 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card-mix+split.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card-mix+split.dtsi
@@ -21,14 +21,14 @@
/ {
sound_card: sound {
compatible = "audio-graph-scu-card";
- label = "rcar-sound";
+ label = "snd-ulcb-mix";
routing = "ak4613 Playback", "DAI0 Playback",
"ak4613 Playback", "DAI1 Playback",
"DAI0 Capture", "ak4613 Capture";
- dais = <&rsnd_port0 /* (A) CPU0 */
- &rsnd_port1 /* (B) CPU1 */
+ dais = <&snd_ulcb1 /* (A) CPU0 */
+ &snd_ulcb2 /* (B) CPU1 */
>;
};
};
@@ -58,14 +58,18 @@
};
&rcar_sound {
- ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports@0 {
#address-cells = <1>;
#size-cells = <0>;
+ reg = <0>;
/*
* (A) CPU0
*/
- rsnd_port0: port@0 {
+ snd_ulcb1: port@0 {
reg = <0>;
rsnd_for_ak4613_1: endpoint {
remote-endpoint = <&ak4613_ep1>;
@@ -78,7 +82,7 @@
/*
* (B) CPU1
*/
- rsnd_port1: port@1 {
+ snd_ulcb2: port@1 {
reg = <1>;
rsnd_for_ak4613_2: endpoint {
remote-endpoint = <&ak4613_ep2>;
diff --git a/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card.dtsi b/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card.dtsi
index 3be54df645e6..3f1df6ee17ea 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card.dtsi
@@ -18,10 +18,10 @@
/ {
sound_card: sound {
compatible = "audio-graph-card";
- label = "rcar-sound";
+ label = "snd-ulcb";
- dais = <&rsnd_port0 /* (A) CPU0 <-> ak4613 */
- &rsnd_port1 /* (B) CPU1 -> HDMI */
+ dais = <&snd_ulcb1 /* (A) CPU0 <-> ak4613 */
+ &snd_ulcb2 /* (B) CPU1 -> HDMI */
>;
};
};
@@ -53,10 +53,15 @@
};
&rcar_sound {
- ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports@0 {
#address-cells = <1>;
#size-cells = <0>;
- rsnd_port0: port@0 {
+ reg = <0>;
+
+ snd_ulcb1: port@0 {
/*
* (A) CPU0 <-> ak4613
*/
@@ -69,7 +74,7 @@
capture = <&ssi1>, <&src1>, <&dvc1>;
};
};
- rsnd_port1: port@1 {
+ snd_ulcb2: port@1 {
/*
* (B) CPU1 -> HDMI
*/
diff --git a/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card2-mix+split.dtsi b/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card2-mix+split.dtsi
index 75b024e3fef1..8966e6a7d28b 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card2-mix+split.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card2-mix+split.dtsi
@@ -20,13 +20,12 @@
/ {
sound_card: sound {
compatible = "audio-graph-card2";
- label = "rcar-sound";
+ label = "snd-ulcb-mix";
routing = "ak4613 Playback", "DAI0 Playback",
"ak4613 Playback", "DAI1 Playback",
"DAI0 Capture", "ak4613 Capture";
- /delete-property/ dais;
links = <&fe_a /* (A) CPU0 */
&fe_b /* (B) CPU1 */
&be_x /* (X) ak4613 */
@@ -50,14 +49,12 @@
};
ports@1 {
- #address-cells = <1>;
- #size-cells = <0>;
reg = <1>;
/*
* BE
* (X) ak4613
*/
- be_x: port@0 { reg = <0>; be_x_ep: endpoint { remote-endpoint = <&ak4613_x_ep>; }; };
+ be_x: port { be_x_ep: endpoint { remote-endpoint = <&ak4613_x_ep>; }; };
};
};
};
@@ -78,9 +75,13 @@
};
&rcar_sound {
- ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports@0 {
#address-cells = <1>;
#size-cells = <0>;
+ reg = <0>;
/*
* (A) CPU0
diff --git a/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card2.dtsi
index 5ebec1235843..19fa6e102995 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card2.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-audio-graph-card2.dtsi
@@ -20,7 +20,7 @@
compatible = "audio-graph-card2";
/delete-property/ dais;
- links = <&rsnd_port0 /* (A) CPU0 <-> ak4613 */
- &rsnd_port1 /* (B) CPU1 -> HDMI */
+ links = <&snd_ulcb1 /* (A) CPU0 <-> ak4613 */
+ &snd_ulcb2 /* (B) CPU1 -> HDMI */
>;
};
diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card-mix+split.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card-mix+split.dtsi
index 9b01354940fd..8ae6af1af094 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card-mix+split.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card-mix+split.dtsi
@@ -19,32 +19,31 @@
*
* (A) aplay -D plughw:0,0 xxx.wav (MIX-0)
* (B) aplay -D plughw:0,1 xxx.wav (MIX-1)
- * (C) aplay -D plughw:0,2 xxx.wav (TDM-0)
- * (D) aplay -D plughw:0,3 xxx.wav (TDM-1)
- * (E) aplay -D plughw:0,4 xxx.wav (TDM-2)
- * (F) aplay -D plughw:0,5 xxx.wav (TDM-3)
+ * (C) aplay -D plughw:1,0 xxx.wav (TDM-0)
+ * (D) aplay -D plughw:1,1 xxx.wav (TDM-1)
+ * (E) aplay -D plughw:1,2 xxx.wav (TDM-2)
+ * (F) aplay -D plughw:1,3 xxx.wav (TDM-3)
*
* (A) arecord -D plughw:0,0 xxx.wav
- * (G) arecord -D plughw:0,6 xxx.wav
+ * (G) arecord -D plughw:1,4 xxx.wav
*/
+/ {
+ sound_card_kf: expand-sound {
+ compatible = "audio-graph-scu-card";
+ label = "snd-kf-split";
-&sound_card {
- routing = "ak4613 Playback", "DAI0 Playback",
- "ak4613 Playback", "DAI1 Playback",
- "DAI0 Capture", "ak4613 Capture",
- "pcm3168a Playback", "DAI2 Playback",
- "pcm3168a Playback", "DAI3 Playback",
- "pcm3168a Playback", "DAI4 Playback",
- "pcm3168a Playback", "DAI5 Playback";
+ routing = "pcm3168a Playback", "DAI2 Playback",
+ "pcm3168a Playback", "DAI3 Playback",
+ "pcm3168a Playback", "DAI4 Playback",
+ "pcm3168a Playback", "DAI5 Playback";
- dais = <&rsnd_port0 /* (A) CPU0 */
- &rsnd_port1 /* (B) CPU1 */
- &rsnd_port2 /* (C) CPU2 */
- &rsnd_port3 /* (D) CPU3 */
- &rsnd_port4 /* (E) CPU4 */
- &rsnd_port5 /* (F) CPU5 */
- &rsnd_port6 /* (G) GPU6 */
- >;
+ dais = <&snd_kf1 /* (C) CPU2 */
+ &snd_kf2 /* (D) CPU3 */
+ &snd_kf3 /* (E) CPU4 */
+ &snd_kf4 /* (F) CPU5 */
+ &snd_kf5 /* (G) GPU6 */
+ >;
+ };
};
&pcm3168a {
@@ -103,13 +102,15 @@
};
&rcar_sound {
- ports {
- /* rsnd_port0-1 are defined in ulcb.dtsi */
+ ports@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
/*
* (C) CPU2
*/
- rsnd_port2: port@2 {
+ snd_kf1: port@2 {
reg = <2>;
rsnd_for_pcm3168a_play1: endpoint {
remote-endpoint = <&pcm3168a_endpoint_p1>;
@@ -121,7 +122,7 @@
/*
* (D) CPU3
*/
- rsnd_port3: port@3 {
+ snd_kf2: port@3 {
reg = <3>;
rsnd_for_pcm3168a_play2: endpoint {
remote-endpoint = <&pcm3168a_endpoint_p2>;
@@ -133,7 +134,7 @@
/*
* (E) CPU4
*/
- rsnd_port4: port@4 {
+ snd_kf3: port@4 {
reg = <4>;
rsnd_for_pcm3168a_play3: endpoint {
remote-endpoint = <&pcm3168a_endpoint_p3>;
@@ -145,7 +146,7 @@
/*
* (F) CPU5
*/
- rsnd_port5: port@5 {
+ snd_kf4: port@5 {
reg = <5>;
rsnd_for_pcm3168a_play4: endpoint {
remote-endpoint = <&pcm3168a_endpoint_p4>;
@@ -157,7 +158,7 @@
/*
* (G) CPU6
*/
- rsnd_port6: port@6 {
+ snd_kf5: port@6 {
reg = <6>;
rsnd_for_pcm3168a_capture: endpoint {
remote-endpoint = <&pcm3168a_endpoint_c>;
diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card.dtsi
index 1db99b7608f0..5fbd4ca83e20 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card.dtsi
@@ -13,18 +13,20 @@
*
* (A) aplay -D plughw:0,0 xxx.wav
* (B) aplay -D plughw:0,1 xxx.wav
- * (C) aplay -D plughw:0,2 xxx.wav
+ * (C) aplay -D plughw:1,0 xxx.wav
*
* (A) arecord -D plughw:0,0 xxx.wav
- * (D) arecord -D plughw:0,3 xxx.wav
+ * (D) arecord -D plughw:1,1 xxx.wav
*/
+/ {
+ sound_card_kf: expand-sound {
+ compatible = "audio-graph-card";
+ label = "snd-kf";
-&sound_card {
- dais = <&rsnd_port0 /* (A) CPU0 <-> ak4613 */
- &rsnd_port1 /* (B) CPU1 -> HDMI */
- &rsnd_port2 /* (C) CPU2 -> PCM3168A-p */
- &rsnd_port3 /* (D) CPU3 <- PCM3168A-c */
+ dais = <&snd_kf1 /* (C) CPU2 -> PCM3168A-p */
+ &snd_kf2 /* (D) CPU3 <- PCM3168A-c */
>;
+ };
};
&pcm3168a {
@@ -56,12 +58,15 @@
};
&rcar_sound {
- ports {
- /* rsnd_port0/1 are defined in ulcb.dtsi */
+ ports@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
/*
* (C) CPU2 -> PCM3168A-p
*/
- rsnd_port2: port@2 {
+ snd_kf1: port@2 {
reg = <2>;
rsnd_for_pcm3168a_play: endpoint {
remote-endpoint = <&pcm3168a_endpoint_p>;
@@ -74,7 +79,7 @@
/*
* (D) CPU3 <- PCM3168A-c
*/
- rsnd_port3: port@3 {
+ snd_kf2: port@3 {
reg = <3>;
rsnd_for_pcm3168a_capture: endpoint {
remote-endpoint = <&pcm3168a_endpoint_c>;
diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card2-mix+split.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card2-mix+split.dtsi
index da644128a9ae..4cf632bc4621 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card2-mix+split.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card2-mix+split.dtsi
@@ -19,61 +19,65 @@
*
* (A) aplay -D plughw:0,0 xxx.wav (MIX-0)
* (B) aplay -D plughw:0,1 xxx.wav (MIX-1)
- * (C) aplay -D plughw:0,2 xxx.wav (TDM-0)
- * (D) aplay -D plughw:0,3 xxx.wav (TDM-1)
- * (E) aplay -D plughw:0,4 xxx.wav (TDM-2)
- * (F) aplay -D plughw:0,5 xxx.wav (TDM-3)
+ * (C) aplay -D plughw:1,0 xxx.wav (TDM-0)
+ * (D) aplay -D plughw:1,1 xxx.wav (TDM-1)
+ * (E) aplay -D plughw:1,2 xxx.wav (TDM-2)
+ * (F) aplay -D plughw:1,3 xxx.wav (TDM-3)
*
* (A) arecord -D plughw:0,0 xxx.wav
- * (G) arecord -D plughw:0,6 xxx.wav
+ * (G) arecord -D plughw:1,4 xxx.wav
*/
-&sound_card {
- routing = "ak4613 Playback", "DAI0 Playback",
- "ak4613 Playback", "DAI1 Playback",
- "DAI0 Capture", "ak4613 Capture",
- "pcm3168a Playback", "DAI2 Playback",
- "pcm3168a Playback", "DAI3 Playback",
- "pcm3168a Playback", "DAI4 Playback",
- "pcm3168a Playback", "DAI5 Playback",
- "DAI6 Capture", "pcm3168a Capture";
+/ {
+ sound_card_kf: expand-sound {
+ compatible = "audio-graph-card2";
+ label = "snd-kf-split";
- /delete-property/ dais;
- links = <&fe_a /* (A) CPU0 */
- &fe_b /* (B) CPU1 */
- &fe_c /* (C) CPU2 */
- &fe_d /* (D) CPU3 */
- &fe_e /* (E) CPU4 */
- &fe_f /* (F) CPU5 */
- &rsnd_g /* (G) CPU6 */
- &be_x /* (X) ak4613 */
- &be_y /* (Y) PCM3168A-p */
- >;
+ routing = "pcm3168a Playback", "DAI2 Playback",
+ "pcm3168a Playback", "DAI3 Playback",
+ "pcm3168a Playback", "DAI4 Playback",
+ "pcm3168a Playback", "DAI5 Playback",
+ "DAI6 Capture", "pcm3168a Capture";
- dpcm {
- ports@0 {
- /*
- * FE
- *
- * (A)/(B) are defined on ulcb
- * (C) CPU2
- * (D) CPU3
- * (E) CPU4
- * (F) CPU5
- */
- fe_c: port@2 { reg = <2>; fe_c_ep: endpoint { remote-endpoint = <&rsnd_c_ep>; }; };
- fe_d: port@3 { reg = <3>; fe_d_ep: endpoint { remote-endpoint = <&rsnd_d_ep>; }; };
- fe_e: port@4 { reg = <4>; fe_e_ep: endpoint { remote-endpoint = <&rsnd_e_ep>; }; };
- fe_f: port@5 { reg = <5>; fe_f_ep: endpoint { remote-endpoint = <&rsnd_f_ep>; }; };
- };
+ links = <&fe_c /* (C) CPU2 */
+ &fe_d /* (D) CPU3 */
+ &fe_e /* (E) CPU4 */
+ &fe_f /* (F) CPU5 */
+ &rsnd_g /* (G) CPU6 */
+ &be_y /* (Y) PCM3168A-p */
+ >;
- ports@1 {
- /*
- * BE
- *
- * (X) is defined on ulcb
- * (Y) PCM3168A-p
- */
- be_y: port@1 { reg = <1>; be_y_ep: endpoint { remote-endpoint = <&pcm3168a_y_ep>; }; };
+ dpcm {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ /*
+ * FE
+ *
+ * (C) CPU2
+ * (D) CPU3
+ * (E) CPU4
+ * (F) CPU5
+ */
+ fe_c: port@2 { reg = <2>; fe_c_ep: endpoint { remote-endpoint = <&rsnd_c_ep>; }; };
+ fe_d: port@3 { reg = <3>; fe_d_ep: endpoint { remote-endpoint = <&rsnd_d_ep>; }; };
+ fe_e: port@4 { reg = <4>; fe_e_ep: endpoint { remote-endpoint = <&rsnd_e_ep>; }; };
+ fe_f: port@5 { reg = <5>; fe_f_ep: endpoint { remote-endpoint = <&rsnd_f_ep>; }; };
+ };
+
+ ports@1 {
+ reg = <1>;
+ /*
+ * BE
+ *
+ * (Y) PCM3168A-p
+ */
+ be_y: port { be_y_ep: endpoint { remote-endpoint = <&pcm3168a_y_ep>; }; };
+ };
};
};
};
@@ -111,8 +115,10 @@
};
&rcar_sound {
- ports {
- /* (A)/(B) are defined in ulcb.dtsi */
+ ports@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
/*
* (C) CPU2
diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card2.dtsi
index c30e056538e4..4fc229418dd7 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card2.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-kf-audio-graph-card2.dtsi
@@ -13,18 +13,18 @@
*
* (A) aplay -D plughw:0,0 xxx.wav
* (B) aplay -D plughw:0,1 xxx.wav
- * (C) aplay -D plughw:0,2 xxx.wav
+ * (C) aplay -D plughw:1,0 xxx.wav
*
* (A) arecord -D plughw:0,0 xxx.wav
- * (D) arecord -D plughw:0,3 xxx.wav
+ * (D) arecord -D plughw:1,1 xxx.wav
*/
#include "ulcb-kf-audio-graph-card.dtsi"
-&sound_card {
+&sound_card_kf {
+ compatible = "audio-graph-card2";
+
/delete-property/ dais;
- links = <&rsnd_port0 /* (A) CPU0 <-> ak4613 */
- &rsnd_port1 /* (B) CPU1 -> HDMI */
- &rsnd_port2 /* (C) CPU2 -> PCM3168A-p */
- &rsnd_port3 /* (D) CPU3 <- PCM3168A-c */
+ links = <&snd_kf1 /* (C) CPU2 -> PCM3168A-p */
+ &snd_kf2 /* (D) CPU3 <- PCM3168A-c */
>;
};
diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-simple-audio-card-mix+split.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-simple-audio-card-mix+split.dtsi
index bc221f994473..f01d91aaadf3 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-kf-simple-audio-card-mix+split.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-kf-simple-audio-card-mix+split.dtsi
@@ -19,89 +19,92 @@
*
* (A) aplay -D plughw:0,0 xxx.wav (MIX-0)
* (B) aplay -D plughw:0,1 xxx.wav (MIX-1)
- * (C) aplay -D plughw:0,2 xxx.wav (TDM-0)
- * (D) aplay -D plughw:0,3 xxx.wav (TDM-1)
- * (E) aplay -D plughw:0,4 xxx.wav (TDM-2)
- * (F) aplay -D plughw:0,5 xxx.wav (TDM-3)
+ * (C) aplay -D plughw:1,0 xxx.wav (TDM-0)
+ * (D) aplay -D plughw:1,1 xxx.wav (TDM-1)
+ * (E) aplay -D plughw:1,2 xxx.wav (TDM-2)
+ * (F) aplay -D plughw:1,3 xxx.wav (TDM-3)
*
* (A) arecord -D plughw:0,0 xxx.wav
- * (G) arecord -D plughw:0,6 xxx.wav
+ * (G) arecord -D plughw:1,4 xxx.wav
*/
-&sound_card {
-
- simple-audio-card,routing = "ak4613 Playback", "DAI0 Playback",
- "ak4613 Playback", "DAI1 Playback",
- "DAI0 Capture", "ak4613 Capture",
- "pcm3168a Playback", "DAI2 Playback",
- "pcm3168a Playback", "DAI3 Playback",
- "pcm3168a Playback", "DAI4 Playback",
- "pcm3168a Playback", "DAI5 Playback";
-
- /* dai-link@0 is defined in ulcb.dtsi */
-
- simple-audio-card,dai-link@1 {
+/ {
+ sound_card_kf: expand-sound {
#address-cells = <1>;
#size-cells = <0>;
- reg = <1>;
- convert-channels = <8>; /* to 8ch TDM */
- /*
- * (C) CPU2
- */
- cpu@0 {
+ compatible = "simple-scu-audio-card";
+ label = "snd-kf-split";
+
+ simple-audio-card,routing = "pcm3168a Playback", "DAI2 Playback",
+ "pcm3168a Playback", "DAI3 Playback",
+ "pcm3168a Playback", "DAI4 Playback",
+ "pcm3168a Playback", "DAI5 Playback";
+
+ simple-audio-card,dai-link@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
reg = <0>;
- bitclock-master;
- frame-master;
- sound-dai = <&rcar_sound 2>;
+ convert-channels = <8>; /* to 8ch TDM */
+
+ /*
+ * (C) CPU2
+ */
+ cpu@0 {
+ reg = <0>;
+ bitclock-master;
+ frame-master;
+ sound-dai = <&rcar_sound 2>;
+ };
+ /*
+ * (D) CPU3
+ */
+ cpu@1 {
+ reg = <1>;
+ sound-dai = <&rcar_sound 3>;
+ };
+ /*
+ * (E) CPU4
+ */
+ cpu@2 {
+ reg = <2>;
+ sound-dai = <&rcar_sound 4>;
+ };
+ /*
+ * (F) CPU5
+ */
+ cpu@3 {
+ reg = <3>;
+ sound-dai = <&rcar_sound 5>;
+ };
+ /*
+ * (Y) PCM3168A-p
+ */
+ codec {
+ prefix = "pcm3168a";
+ mclk-fs = <512>;
+ sound-dai = <&pcm3168a 0>;
+ };
};
- /*
- * (D) CPU3
- */
- cpu@1 {
+
+ simple-audio-card,dai-link@1 {
reg = <1>;
- sound-dai = <&rcar_sound 3>;
- };
- /*
- * (E) CPU4
- */
- cpu@2 {
- reg = <2>;
- sound-dai = <&rcar_sound 4>;
- };
- /*
- * (F) CPU5
- */
- cpu@3 {
- reg = <3>;
- sound-dai = <&rcar_sound 5>;
- };
- /*
- * (Y) PCM3168A-p
- */
- codec {
- prefix = "pcm3168a";
- mclk-fs = <512>;
- sound-dai = <&pcm3168a 0>;
- };
- };
- simple-audio-card,dai-link@2 {
- reg = <2>;
- /*
- * (G) CPU6
- */
- cpu {
- bitclock-master;
- frame-master;
- sound-dai = <&rcar_sound 6>;
- };
- /*
- * (Z) PCM3168A-c
- */
- codec {
- prefix = "pcm3168a";
- mclk-fs = <512>;
- sound-dai = <&pcm3168a 1>;
+ /*
+ * (G) CPU6
+ */
+ cpu {
+ bitclock-master;
+ frame-master;
+ sound-dai = <&rcar_sound 6>;
+ };
+ /*
+ * (Z) PCM3168A-c
+ */
+ codec {
+ prefix = "pcm3168a";
+ mclk-fs = <512>;
+ sound-dai = <&pcm3168a 1>;
+ };
};
};
};
@@ -115,7 +118,8 @@
};
&rcar_sound {
- rcar_sound,dai {
+ rcar_sound,dai@1 {
+ reg = <1>;
/* dai0-1 are defined in ulcb.dtsi */
diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-simple-audio-card.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-simple-audio-card.dtsi
index 2010e8ac7fdc..28d29ecfb395 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-kf-simple-audio-card.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-kf-simple-audio-card.dtsi
@@ -13,45 +13,51 @@
*
* (A) aplay -D plughw:0,0 xxx.wav
* (B) aplay -D plughw:0,1 xxx.wav
- * (C) aplay -D plughw:0,2 xxx.wav
+ * (C) aplay -D plughw:1,0 xxx.wav
*
* (A) arecord -D plughw:0,0 xxx.wav
- * (D) arecord -D plughw:0,3 xxx.wav
+ * (D) arecord -D plughw:1,1 xxx.wav
*/
-&sound_card {
- /* dai-link@0/1 are defined in ulcb.dtsi */
+/ {
+ sound_card_kf: expand-sound {
+ compatible = "simple-audio-card";
+ label = "snd-kf";
- /*
- * (C) CPU2 -> PCM3168A-p
- */
- simple-audio-card,dai-link@2 {
- reg = <2>;
- cpu {
- bitclock-master;
- frame-master;
- dai-tdm-slot-num = <8>;
- sound-dai = <&rcar_sound 2>;
- };
- codec {
- mclk-fs = <512>;
- sound-dai = <&pcm3168a 0>;
- };
- };
- /*
- * (D) CPU3 <- PCM3168A-c
- */
- simple-audio-card,dai-link@3 {
- reg = <3>;
- cpu {
- bitclock-master;
- frame-master;
- dai-tdm-slot-num = <6>;
- sound-dai = <&rcar_sound 3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /*
+ * (C) CPU2 -> PCM3168A-p
+ */
+ simple-audio-card,dai-link@0 {
+ reg = <0>;
+ cpu {
+ bitclock-master;
+ frame-master;
+ dai-tdm-slot-num = <8>;
+ sound-dai = <&rcar_sound 2>;
+ };
+ codec {
+ mclk-fs = <512>;
+ sound-dai = <&pcm3168a 0>;
+ };
};
- codec {
- mclk-fs = <512>;
- sound-dai = <&pcm3168a 1>;
+ /*
+ * (D) CPU3 <- PCM3168A-c
+ */
+ simple-audio-card,dai-link@1 {
+ reg = <1>;
+ cpu {
+ bitclock-master;
+ frame-master;
+ dai-tdm-slot-num = <6>;
+ sound-dai = <&rcar_sound 3>;
+ };
+ codec {
+ mclk-fs = <512>;
+ sound-dai = <&pcm3168a 1>;
+ };
};
};
};
@@ -65,9 +71,8 @@
};
&rcar_sound {
-
- rcar_sound,dai {
- /* dai0-1 are defined in ulcb.dtsi */
+ rcar_sound,dai@1 {
+ reg = <1>;
/*
* (C) CPU2 -> PCM3168A-p
diff --git a/arch/arm64/boot/dts/renesas/ulcb-simple-audio-card-mix+split.dtsi b/arch/arm64/boot/dts/renesas/ulcb-simple-audio-card-mix+split.dtsi
index 217d89019845..9b955510e38e 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-simple-audio-card-mix+split.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-simple-audio-card-mix+split.dtsi
@@ -24,7 +24,7 @@
#size-cells = <0>;
compatible = "simple-scu-audio-card";
- label = "rcar-sound";
+ label = "snd-ulcb-mix";
simple-audio-card,prefix = "ak4613";
simple-audio-card,routing = "ak4613 Playback", "DAI0 Playback",
@@ -72,9 +72,13 @@
};
&rcar_sound {
+ #address-cells = <1>;
+ #size-cells = <0>;
#sound-dai-cells = <1>;
- rcar_sound,dai {
+ rcar_sound,dai@0 {
+ reg = <0>;
+
/*
* (A) CPU0
*/
diff --git a/arch/arm64/boot/dts/renesas/ulcb-simple-audio-card.dtsi b/arch/arm64/boot/dts/renesas/ulcb-simple-audio-card.dtsi
index 751cfd8c5257..ba0e188e7b21 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-simple-audio-card.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-simple-audio-card.dtsi
@@ -18,7 +18,7 @@
/ {
sound_card: sound {
compatible = "simple-audio-card";
- label = "rcar-sound";
+ label = "snd-ulcb";
#address-cells = <1>;
#size-cells = <0>;
@@ -69,9 +69,13 @@
};
&rcar_sound {
+ #address-cells = <1>;
+ #size-cells = <0>;
#sound-dai-cells = <1>;
- rcar_sound,dai {
+ rcar_sound,dai@0 {
+ reg = <0>;
+
/*
* (A) CPU0 <-> ak4613
*/
diff --git a/arch/arm64/boot/dts/renesas/ulcb.dtsi b/arch/arm64/boot/dts/renesas/ulcb.dtsi
index 0be2716659e9..a2f66f916048 100644
--- a/arch/arm64/boot/dts/renesas/ulcb.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb.dtsi
@@ -383,7 +383,7 @@
<&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
<&audio_clk_a>, <&cs2000>,
<&audio_clk_c>,
- <&cpg CPG_CORE CPG_AUDIO_CLK_I>;
+ <&cpg CPG_MOD 922>;
};
&rpc {
diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
index e7728007fd1b..a18f33bf0c0e 100644
--- a/arch/arm64/boot/dts/rockchip/Makefile
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -77,6 +77,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353vs.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg503.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.1.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.2.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-powkiddy-rgb30.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-a.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-b.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-radxa-cm3-io.dtb
@@ -101,7 +102,11 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6a-io.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6b-io.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-v10.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nanopc-t6.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-orangepi-5-plus.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-quartzpro64.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-rock-5b.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-turing-rk1.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-indiedroid-nova.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-khadas-edge2.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-rock-5a.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5.dtb
diff --git a/arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts b/arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts
index 08a3ad3e7ae9..7d4c5324c61b 100644
--- a/arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts
+++ b/arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts
@@ -68,15 +68,17 @@
simple-audio-card,format = "i2s";
simple-audio-card,name = "Haikou,I2S-codec";
simple-audio-card,mclk-fs = <512>;
+ simple-audio-card,frame-master = <&sgtl5000_codec>;
+ simple-audio-card,bitclock-master = <&sgtl5000_codec>;
- simple-audio-card,codec {
- clocks = <&sgtl5000_clk>;
+ sgtl5000_codec: simple-audio-card,codec {
sound-dai = <&sgtl5000>;
+ // Prevent the dai subsystem from overwriting the clock
+ // frequency. We are using a fixed-frequency oscillator.
+ system-clock-fixed;
};
simple-audio-card,cpu {
- bitclock-master;
- frame-master;
sound-dai = <&i2s0_8ch>;
};
};
@@ -84,7 +86,7 @@
sgtl5000_clk: sgtl5000-oscillator {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <24576000>;
+ clock-frequency = <24576000>;
};
dc_12v: dc-12v-regulator {
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index e729e7a22b23..cc8209795c3e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -668,7 +668,7 @@
vdec: video-codec@ff360000 {
compatible = "rockchip,rk3328-vdec", "rockchip,rk3399-vdec";
- reg = <0x0 0xff360000 0x0 0x400>;
+ reg = <0x0 0xff360000 0x0 0x480>;
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>,
<&cru SCLK_VDEC_CABAC>, <&cru SCLK_VDEC_CORE>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi
index 5c1929d41cc0..cacbad35cfc8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi
@@ -509,8 +509,7 @@ ap_i2c_tp: &i2c5 {
&pci_rootport {
mvl_wifi: wifi@0,0 {
compatible = "pci1b4b,2b42";
- reg = <0x83010000 0x0 0x00000000 0x0 0x00100000
- 0x83010000 0x0 0x00100000 0x0 0x00100000>;
+ reg = <0x0000 0x0 0x0 0x0 0x0>;
interrupt-parent = <&gpio0>;
interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet-dumo.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet-dumo.dts
index 853e88455e75..9e4b12ed62cb 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet-dumo.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet-dumo.dts
@@ -34,8 +34,8 @@
&pci_rootport {
wifi@0,0 {
compatible = "qcom,ath10k";
- reg = <0x00010000 0x0 0x00000000 0x0 0x00000000>,
- <0x03010010 0x0 0x00000000 0x0 0x00200000>;
+ reg = <0x00000000 0x0 0x00000000 0x0 0x00000000>,
+ <0x03000010 0x0 0x00000000 0x0 0x00200000>;
qcom,ath10k-calibration-variant = "GO_DUMO";
};
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
index c9bf1d5c3a42..789fd0dcc88b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
@@ -489,6 +489,7 @@ ap_i2c_audio: &i2c8 {
#address-cells = <3>;
#size-cells = <2>;
ranges;
+ device_type = "pci";
};
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi
index 7dccbe8a9393..f2279aa6ca9e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi
@@ -492,6 +492,7 @@
&i2s0 {
pinctrl-0 = <&i2s0_2ch_bus>;
+ pinctrl-1 = <&i2s0_2ch_bus_bclk_off>;
rockchip,capture-channels = <2>;
rockchip,playback-channels = <2>;
status = "okay";
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 9da0b6d77c8d..da0dfb237f85 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1109,7 +1109,9 @@
power-domain@RK3399_PD_VDU {
reg = <RK3399_PD_VDU>;
clocks = <&cru ACLK_VDU>,
- <&cru HCLK_VDU>;
+ <&cru HCLK_VDU>,
+ <&cru SCLK_VDU_CA>,
+ <&cru SCLK_VDU_CORE>;
pm_qos = <&qos_video_m1_r>,
<&qos_video_m1_w>;
#power-domain-cells = <0>;
@@ -1358,7 +1360,6 @@
interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&cru PCLK_DDR_MON>;
clock-names = "pclk_ddr_mon";
- status = "disabled";
};
vpu: video-codec@ff650000 {
@@ -1385,7 +1386,7 @@
vdec: video-codec@ff660000 {
compatible = "rockchip,rk3399-vdec";
- reg = <0x0 0xff660000 0x0 0x400>;
+ reg = <0x0 0xff660000 0x0 0x480>;
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&cru ACLK_VDU>, <&cru HCLK_VDU>,
<&cru SCLK_VDU_CA>, <&cru SCLK_VDU_CORE>;
@@ -2457,6 +2458,16 @@
<4 RK_PA0 1 &pcfg_pull_none>;
};
+ i2s0_2ch_bus_bclk_off: i2s0-2ch-bus-bclk-off {
+ rockchip,pins =
+ <3 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>,
+ <3 RK_PD1 1 &pcfg_pull_none>,
+ <3 RK_PD2 1 &pcfg_pull_none>,
+ <3 RK_PD3 1 &pcfg_pull_none>,
+ <3 RK_PD7 1 &pcfg_pull_none>,
+ <4 RK_PA0 1 &pcfg_pull_none>;
+ };
+
i2s0_8ch_bus: i2s0-8ch-bus {
rockchip,pins =
<3 RK_PD0 1 &pcfg_pull_none>,
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-powkiddy-rgb30.dts b/arch/arm64/boot/dts/rockchip/rk3566-powkiddy-rgb30.dts
new file mode 100644
index 000000000000..1ead3c5c24b3
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-powkiddy-rgb30.dts
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rk3566-anbernic-rg353x.dtsi"
+
+/ {
+ model = "RGB30";
+ compatible = "powkiddy,rgb30", "rockchip,rk3566";
+
+ aliases {
+ mmc1 = &sdmmc0;
+ mmc2 = &sdmmc1;
+ mmc3 = &sdmmc2;
+ };
+
+ battery: battery {
+ compatible = "simple-battery";
+ charge-full-design-microamp-hours = <3151000>;
+ charge-term-current-microamp = <300000>;
+ constant-charge-current-max-microamp = <2000000>;
+ constant-charge-voltage-max-microvolt = <4250000>;
+ factory-internal-resistance-micro-ohms = <117000>;
+ voltage-max-design-microvolt = <4172000>;
+ voltage-min-design-microvolt = <3400000>;
+
+ ocv-capacity-celsius = <20>;
+ ocv-capacity-table-0 = <4172000 100>, <4092000 95>, <4035000 90>, <3990000 85>,
+ <3939000 80>, <3895000 75>, <3852000 70>, <3807000 65>,
+ <3762000 60>, <3713000 55>, <3672000 50>, <3647000 45>,
+ <3629000 40>, <3613000 35>, <3598000 30>, <3578000 25>,
+ <3550000 20>, <3519000 15>, <3479000 10>, <3438000 5>,
+ <3400000 0>;
+ };
+
+ /*
+ * Channels reversed for speakers. Headphones automatically switch via hardware when
+ * detected with no ability to control output in software. Headphones appear to be mono
+ * (each output channel receives all audio). No microphone support on 3.5mm jack.
+ */
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "rk817_ext";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,widgets =
+ "Headphone", "Headphones";
+ simple-audio-card,routing =
+ "Headphones", "HPOL",
+ "Headphones", "HPOR";
+
+ simple-audio-card,codec {
+ sound-dai = <&rk817>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1_8ch>;
+ };
+ };
+};
+
+/delete-node/ &adc_keys;
+
+&chosen {
+ /delete-property/ stdout-path;
+};
+
+&cru {
+ assigned-clocks = <&pmucru CLK_RTC_32K>, <&cru PLL_GPLL>,
+ <&pmucru PLL_PPLL>, <&cru PLL_VPLL>;
+ assigned-clock-rates = <32768>, <1200000000>,
+ <200000000>, <292500000>;
+};
+
+&gpio_keys_control {
+ button-r1 {
+ gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>;
+ label = "TR";
+ linux,code = <BTN_TR>;
+ };
+
+ button-r2 {
+ gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>;
+ label = "TR2";
+ linux,code = <BTN_TR2>;
+ };
+};
+
+/delete-node/ &{/i2c@fdd40000/regulator@40};
+
+&i2c0 {
+ vdd_cpu: regulator@1c {
+ compatible = "tcs,tcs4525";
+ reg = <0x1c>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <712500>;
+ regulator-max-microvolt = <1390000>;
+ regulator-name = "vdd_cpu";
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc_sys>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+/*
+ * Device has 2 red LEDs instead of an amber and a red. Relabel LEDs as
+ * red_led0 and red_led1.
+ */
+/delete-node/ &{/pwm-leds/led-1};
+/delete-node/ &{/pwm-leds/led-2};
+
+&leds {
+ red_led0: led-1 {
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_CHARGING;
+ max-brightness = <255>;
+ pwms = <&pwm7 0 25000 0>;
+ };
+
+ red_led1: led-2 {
+ color = <LED_COLOR_ID_RED>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ max-brightness = <255>;
+ pwms = <&pwm0 0 25000 0>;
+ };
+};
+
+&panel {
+ compatible = "powkiddy,rgb30-panel";
+ vcc-supply = <&vcc3v3_lcd0_n>;
+ iovcc-supply = <&vcc3v3_lcd0_n>;
+ /delete-property/ vdd-supply;
+};
+
+&pwm5 {
+ status = "disabled";
+};
+
+&rk817 {
+ rk817_charger: charger {
+ monitored-battery = <&battery>;
+ rockchip,resistor-sense-micro-ohms = <10000>;
+ rockchip,sleep-enter-current-microamp = <300000>;
+ rockchip,sleep-filter-current-microamp = <100000>;
+ };
+};
+
+/* There is no UART header visible on the board for this device. */
+&uart2 {
+ status = "disabled";
+};
+
+/delete-node/ &vibrator;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
index e05ab11981f5..a5e974ea659e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
@@ -15,6 +15,7 @@
ethernet0 = &gmac1;
mmc0 = &sdhci;
mmc1 = &sdmmc0;
+ mmc2 = &sdmmc2;
};
chosen: chosen {
@@ -747,6 +748,9 @@
non-removable;
pinctrl-names = "default";
pinctrl-0 = <&sdmmc2m0_bus4 &sdmmc2m0_cmd &sdmmc2m0_clk>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
sd-uhs-sdr104;
vmmc-supply = <&vcc3v3_sys>;
vqmmc-supply = <&vcc_1v8>;
diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index abee88911982..c19c0f1b3778 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -959,6 +959,13 @@
reg = <0x0 0xfe1a8100 0x0 0x20>;
};
+ dfi: dfi@fe230000 {
+ compatible = "rockchip,rk3568-dfi";
+ reg = <0x00 0xfe230000 0x00 0x400>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ rockchip,pmu = <&pmugrf>;
+ };
+
pcie2x1: pcie@fe260000 {
compatible = "rockchip,rk3568-pcie";
reg = <0x3 0xc0000000 0x0 0x00400000>,
@@ -970,7 +977,7 @@
<GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "sys", "pmc", "msi", "legacy", "err";
+ interrupt-names = "sys", "pmc", "msg", "legacy", "err";
bus-range = <0x0 0xf>;
clocks = <&cru ACLK_PCIE20_MST>, <&cru ACLK_PCIE20_SLV>,
<&cru ACLK_PCIE20_DBI>, <&cru PCLK_PCIE20>,
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
index 229a9111f5eb..b9d789d57862 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
@@ -7,6 +7,7 @@
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/rockchip.h>
#include "rk3588.dtsi"
@@ -23,12 +24,84 @@
stdout-path = "serial2:1500000n8";
};
+ adc-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 1>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-vol-up {
+ label = "Volume Up";
+ linux,code = <KEY_VOLUMEUP>;
+ press-threshold-microvolt = <17000>;
+ };
+
+ button-vol-down {
+ label = "Volume Down";
+ linux,code = <KEY_VOLUMEDOWN>;
+ press-threshold-microvolt = <417000>;
+ };
+
+ button-menu {
+ label = "Menu";
+ linux,code = <KEY_MENU>;
+ press-threshold-microvolt = <890000>;
+ };
+
+ button-escape {
+ label = "Escape";
+ linux,code = <KEY_ESC>;
+ press-threshold-microvolt = <1235000>;
+ };
+ };
+
backlight: backlight {
compatible = "pwm-backlight";
power-supply = <&vcc12v_dcin>;
pwms = <&pwm2 0 25000 0>;
};
+ pcie20_avdd0v85: pcie20-avdd0v85-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "pcie20_avdd0v85";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ vin-supply = <&avdd_0v85_s0>;
+ };
+
+ pcie20_avdd1v8: pcie20-avdd1v8-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "pcie20_avdd1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&avcc_1v8_s0>;
+ };
+
+ pcie30_avdd0v75: pcie30-avdd0v75-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "pcie30_avdd0v75";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ vin-supply = <&avdd_0v75_s0>;
+ };
+
+ pcie30_avdd1v8: pcie30-avdd1v8-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "pcie30_avdd1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&avcc_1v8_s0>;
+ };
+
vcc12v_dcin: vcc12v-dcin-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
@@ -38,6 +111,19 @@
regulator-max-microvolt = <12000000>;
};
+ vcc3v3_pcie30: vcc3v3-pcie30-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_pcie30";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpios = <&gpio3 RK_PC3 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc12v_dcin>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc3v3_pcie30_en>;
+ };
+
vcc5v0_host: vcc5v0-host-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host";
@@ -87,6 +173,10 @@
status = "okay";
};
+&combphy2_psu {
+ status = "okay";
+};
+
&cpu_b0 {
cpu-supply = <&vdd_cpu_big0_s0>;
};
@@ -163,7 +253,32 @@
};
};
+&pcie2x1l1 {
+ reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_1_rst>, <&rtl8111_isolate>;
+ status = "okay";
+};
+
+&pcie30phy {
+ status = "okay";
+};
+
+&pcie3x4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3_reset>;
+ reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie30>;
+ status = "okay";
+};
+
&pinctrl {
+ rtl8111 {
+ rtl8111_isolate: rtl8111-isolate {
+ rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
rtl8211f {
rtl8211f_rst: rtl8211f-rst {
rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
@@ -177,6 +292,22 @@
};
};
+ pcie2 {
+ pcie2_1_rst: pcie2-1-rst {
+ rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie3 {
+ pcie3_reset: pcie3-reset {
+ rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ vcc3v3_pcie30_en: vcc3v3-pcie30-en {
+ rockchip,pins = <3 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
usb {
vcc5v0_host_en: vcc5v0-host-en {
rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
@@ -188,6 +319,11 @@
status = "okay";
};
+&saradc {
+ vref-supply = <&vcc_1v8_s0>;
+ status = "okay";
+};
+
&sdhci {
bus-width = <8>;
no-sdio;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts
index 0bd80e515754..97af4f912828 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts
@@ -137,6 +137,18 @@
vin-supply = <&vcc5v0_sys>;
};
+ vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_m2_1_pwren>;
+ regulator-name = "vcc3v3_pcie2x1l0";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
vcc3v3_pcie30: vcc3v3-pcie30-regulator {
compatible = "regulator-fixed";
enable-active-high;
@@ -421,6 +433,14 @@
status = "okay";
};
+&pcie2x1l1 {
+ reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie2x1l0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_1_rst>;
+ status = "okay";
+};
+
&pcie2x1l2 {
reset-gpios = <&gpio4 RK_PA4 GPIO_ACTIVE_HIGH>;
vpcie3v3-supply = <&vcc_3v3_pcie20>;
@@ -467,6 +487,10 @@
rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
};
+ pcie2_1_rst: pcie2-1-rst {
+ rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
pcie2_2_rst: pcie2-2-rst {
rockchip,pins = <4 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
};
@@ -474,6 +498,10 @@
pcie_m2_0_pwren: pcie-m20-pwren {
rockchip,pins = <2 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
};
+
+ pcie_m2_1_pwren: pcie-m21-pwren {
+ rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
};
usb {
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
new file mode 100644
index 000000000000..298c183d6f4f
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
@@ -0,0 +1,848 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023 Ondřej Jirman <megi@xff.cz>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/usb/pd.h>
+#include "rk3588.dtsi"
+
+/ {
+ model = "Xunlong Orange Pi 5 Plus";
+ compatible = "xunlong,orangepi-5-plus", "rockchip,rk3588";
+
+ aliases {
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc;
+ serial2 = &uart2;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ adc-keys-0 {
+ compatible = "adc-keys";
+ io-channels = <&saradc 0>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-maskrom {
+ label = "Mask Rom";
+ linux,code = <KEY_SETUP>;
+ press-threshold-microvolt = <2000>;
+ };
+ };
+
+ adc-keys-1 {
+ compatible = "adc-keys";
+ io-channels = <&saradc 1>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-recovery {
+ label = "Recovery";
+ linux,code = <KEY_VENDOR>;
+ press-threshold-microvolt = <2000>;
+ };
+ };
+
+ speaker_amp: speaker-audio-amplifier {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>;
+ sound-name-prefix = "Speaker Amp";
+ };
+
+ headphone_amp: headphones-audio-amplifier {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&gpio3 RK_PA7 GPIO_ACTIVE_HIGH>;
+ sound-name-prefix = "Headphones Amp";
+ };
+
+ ir-receiver {
+ compatible = "gpio-ir-receiver";
+ gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir_receiver_pin>;
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&blue_led_pin>;
+
+ led {
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_INDICATOR;
+ function-enumerator = <1>;
+ gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ fan: pwm-fan {
+ compatible = "pwm-fan";
+ cooling-levels = <0 70 75 80 100>;
+ fan-supply = <&vcc5v0_sys>;
+ pwms = <&pwm3 0 50000 0>;
+ #cooling-cells = <2>;
+ };
+
+ pwm-leds {
+ compatible = "pwm-leds";
+
+ led {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_INDICATOR;
+ function-enumerator = <2>;
+ max-brightness = <255>;
+ pwms = <&pwm2 0 25000 0>;
+ };
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_detect>;
+ simple-audio-card,name = "Analog";
+ simple-audio-card,aux-devs = <&speaker_amp>, <&headphone_amp>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,hp-det-gpio = <&gpio1 RK_PD3 GPIO_ACTIVE_LOW>;
+ simple-audio-card,bitclock-master = <&daicpu>;
+ simple-audio-card,frame-master = <&daicpu>;
+ /*TODO: SARADC_IN3 is used as MIC detection / key input */
+
+ simple-audio-card,widgets =
+ "Microphone", "Onboard Microphone",
+ "Microphone", "Microphone Jack",
+ "Speaker", "Speaker",
+ "Headphone", "Headphones";
+
+ simple-audio-card,routing =
+ "Headphones", "LOUT1",
+ "Headphones", "ROUT1",
+ "Speaker", "LOUT2",
+ "Speaker", "ROUT2",
+
+ "Headphones", "Headphones Amp OUTL",
+ "Headphones", "Headphones Amp OUTR",
+ "Headphones Amp INL", "LOUT1",
+ "Headphones Amp INR", "ROUT1",
+
+ "Speaker", "Speaker Amp OUTL",
+ "Speaker", "Speaker Amp OUTR",
+ "Speaker Amp INL", "LOUT2",
+ "Speaker Amp INR", "ROUT2",
+
+ /* single ended signal to LINPUT1 */
+ "LINPUT1", "Microphone Jack",
+ "RINPUT1", "Microphone Jack",
+ /* differential signal */
+ "LINPUT2", "Onboard Microphone",
+ "RINPUT2", "Onboard Microphone";
+
+ daicpu: simple-audio-card,cpu {
+ sound-dai = <&i2s0_8ch>;
+ system-clock-frequency = <12288000>;
+ };
+
+ daicodec: simple-audio-card,codec {
+ sound-dai = <&es8388>;
+ system-clock-frequency = <12288000>;
+ };
+ };
+
+ vcc3v3_pcie30: vcc3v3-pcie30-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio2 RK_PB6 GPIO_ACTIVE_HIGH>;
+ regulator-name = "vcc3v3_pcie30";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc3v3_pcie_eth: vcc3v3-pcie-eth-regulator {
+ compatible = "regulator-fixed";
+ gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>;
+ regulator-name = "vcc3v3_pcie_eth";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <50000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc3v3_wf: vcc3v3-wf-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>;
+ regulator-name = "vcc3v3_wf";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <50000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_sys: vcc5v0-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vcc5v0_usb20: vcc5v0-usb20-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc5v0_usb20_en>;
+ regulator-name = "vcc5v0_usb20";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+};
+
+&combphy0_ps {
+ status = "okay";
+};
+
+&combphy1_ps {
+ status = "okay";
+};
+
+&combphy2_psu {
+ status = "okay";
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b1 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b2 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_b3 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l1 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l2 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l3 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0m2_xfer>;
+ status = "okay";
+
+ vdd_cpu_big0_s0: regulator@42 {
+ compatible = "rockchip,rk8602";
+ reg = <0x42>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big0_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_big1_s0: regulator@43 {
+ compatible = "rockchip,rk8603", "rockchip,rk8602";
+ reg = <0x43>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big1_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c6 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <0>;
+ clock-output-names = "hym8563";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hym8563_int>;
+ wakeup-source;
+ };
+};
+
+&i2c7 {
+ status = "okay";
+
+ /* PLDO2 vcca 1.8V, BUCK8 gated by PLDO2 being enabled */
+ es8388: audio-codec@11 {
+ compatible = "everest,es8388";
+ reg = <0x11>;
+ clocks = <&cru I2S0_8CH_MCLKOUT>;
+ clock-names = "mclk";
+ AVDD-supply = <&vcc_1v8_s0>;
+ DVDD-supply = <&vcc_1v8_s0>;
+ HPVDD-supply = <&vcc_3v3_s0>;
+ PVDD-supply = <&vcc_3v3_s0>;
+ assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
+ assigned-clock-rates = <12288000>;
+ #sound-dai-cells = <0>;
+ };
+};
+
+&i2s0_8ch {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0_lrck
+ &i2s0_mclk
+ &i2s0_sclk
+ &i2s0_sdi0
+ &i2s0_sdo0>;
+ status = "okay";
+};
+
+&i2s2_2ch {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s2m0_lrck
+ &i2s2m0_sclk
+ &i2s2m0_sdi
+ &i2s2m0_sdo>;
+ status = "okay";
+};
+
+/* phy1 - M.KEY socket */
+&pcie2x1l0 {
+ reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_wf>;
+ status = "okay";
+};
+
+/* phy2 - right ethernet port */
+&pcie2x1l1 {
+ reset-gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie_eth>;
+ status = "okay";
+};
+
+/* phy0 - left ethernet port */
+&pcie2x1l2 {
+ reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie_eth>;
+ status = "okay";
+};
+
+&pcie30phy {
+ status = "okay";
+};
+
+&pcie3x4 {
+ reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie30>;
+ status = "okay";
+};
+
+&pinctrl {
+ hym8563 {
+ hym8563_int: hym8563-int {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ leds {
+ blue_led_pin: blue-led {
+ rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ ir-receiver {
+ ir_receiver_pin: ir-receiver-pin {
+ rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ sound {
+ hp_detect: hp-detect {
+ rockchip,pins = <1 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb {
+ vcc5v0_usb20_en: vcc5v0-usb20-en {
+ rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pwm2 {
+ pinctrl-0 = <&pwm2m1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pwm3 {
+ pinctrl-0 = <&pwm3m1_pins>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcc_1v8_s0>;
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ no-sdio;
+ no-sd;
+ non-removable;
+ max-frequency = <200000000>;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ max-frequency = <150000000>;
+ no-sdio;
+ no-mmc;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_3v3_s3>;
+ vqmmc-supply = <&vccio_sd_s0>;
+ status = "okay";
+};
+
+&sfc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&fspim1_pins>;
+ status = "okay";
+
+ spi_flash: flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-max-frequency = <100000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <1>;
+ };
+};
+
+&spi2 {
+ assigned-clocks = <&cru CLK_SPI2>;
+ assigned-clock-rates = <200000000>;
+ num-cs = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
+ status = "okay";
+
+ pmic@0 {
+ compatible = "rockchip,rk806";
+ reg = <0x0>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+ <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+ spi-max-frequency = <1000000>;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc5v0_sys>;
+ vcc6-supply = <&vcc5v0_sys>;
+ vcc7-supply = <&vcc5v0_sys>;
+ vcc8-supply = <&vcc5v0_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+ vcc10-supply = <&vcc5v0_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc5v0_sys>;
+ vcc13-supply = <&vdd2_ddr_s3>;
+ vcc14-supply = <&vdd2_ddr_s3>;
+ vcca-supply = <&vcc5v0_sys>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ rk806_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ regulators {
+ vdd_gpu_s0: dcdc-reg1 {
+ regulator-name = "vdd_gpu_s0";
+ regulator-boot-on;
+ regulator-enable-ramp-delay = <400>;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_s0: dcdc-reg2 {
+ regulator-name = "vdd_cpu_lit_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_log_s0: dcdc-reg3 {
+ regulator-name = "vdd_log_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <825000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_vdenc_s0: dcdc-reg4 {
+ regulator-name = "vdd_vdenc_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <825000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_ddr_s0: dcdc-reg5 {
+ regulator-name = "vdd_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <900000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ vdd2_ddr_s3: dcdc-reg6 {
+ regulator-name = "vdd2_ddr_s3";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_2v0_pldo_s3: dcdc-reg7 {
+ regulator-name = "vdd_2v0_pldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2000000>;
+ };
+ };
+
+ vcc_3v3_s3: dcdc-reg8 {
+ regulator-name = "vcc_3v3_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vddq_ddr_s0: dcdc-reg9 {
+ regulator-name = "vddq_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s3: dcdc-reg10 {
+ regulator-name = "vcc_1v8_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ avcc_1v8_s0: pldo-reg1 {
+ regulator-name = "avcc_1v8_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ /* shorted to avcc_1v8_s0 on the board */
+ vcc_1v8_s0: pldo-reg2 {
+ regulator-name = "vcc_1v8_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ avdd_1v2_s0: pldo-reg3 {
+ regulator-name = "avdd_1v2_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_3v3_s0: pldo-reg4 {
+ regulator-name = "vcc_3v3_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd_s0: pldo-reg5 {
+ regulator-name = "vccio_sd_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ pldo6_s3: pldo-reg6 {
+ regulator-name = "pldo6_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd_0v75_s3: nldo-reg1 {
+ regulator-name = "vdd_0v75_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_ddr_pll_s0: nldo-reg2 {
+ regulator-name = "vdd_ddr_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ avdd_0v75_s0: nldo-reg3 {
+ regulator-name = "avdd_0v75_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ /*
+ * The schematic mentions that actual setting
+ * should be 0.8375V. RK3588 datasheet specifies
+ * maximum as 0.825V. So we set datasheet max
+ * here.
+ */
+ regulator-min-microvolt = <825000>;
+ regulator-max-microvolt = <825000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v85_s0: nldo-reg4 {
+ regulator-name = "vdd_0v85_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v75_s0: nldo-reg5 {
+ regulator-name = "vdd_0v75_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&u2phy2 {
+ status = "okay";
+};
+
+&u2phy3 {
+ status = "okay";
+};
+
+&u2phy2_host {
+ phy-supply = <&vcc5v0_usb20>;
+ status = "okay";
+};
+
+&u2phy3_host {
+ phy-supply = <&vcc5v0_usb20>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-0 = <&uart2m0_xfer>;
+ status = "okay";
+};
+
+&uart9 {
+ pinctrl-0 = <&uart9m0_xfer>;
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
new file mode 100644
index 000000000000..5c59f9571dce
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
@@ -0,0 +1,1137 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023 Ondřej Jirman <megi@xff.cz>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/usb/pd.h>
+#include "rk3588.dtsi"
+
+/ {
+ model = "PINE64 QuartzPro64";
+ compatible = "pine64,quartzpro64", "rockchip,rk3588";
+
+ aliases {
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc;
+ serial2 = &uart2;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ adc-keys-0 {
+ compatible = "adc-keys";
+ io-channels = <&saradc 0>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-maskrom {
+ label = "Mask Rom";
+ linux,code = <KEY_SETUP>;
+ press-threshold-microvolt = <393>;
+ };
+ };
+
+ adc-keys-1 {
+ compatible = "adc-keys";
+ io-channels = <&saradc 1>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-volume-up {
+ label = "V+/REC";
+ linux,code = <KEY_VOLUMEUP>;
+ press-threshold-microvolt = <17821>;
+ };
+
+ button-volume-down {
+ label = "V-";
+ linux,code = <KEY_VOLUMEDOWN>;
+ press-threshold-microvolt = <415384>;
+ };
+
+ button-menu {
+ label = "MENU";
+ linux,code = <KEY_MENU>;
+ press-threshold-microvolt = <890909>;
+ };
+
+ button-esc {
+ label = "ESC";
+ linux,code = <KEY_ESC>;
+ press-threshold-microvolt = <1233962>;
+ };
+ };
+
+ headphone_amp: audio-amplifier-headphone {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
+ sound-name-prefix = "Headphones Amp";
+ };
+
+ speaker_amp: audio-amplifier-speaker {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&gpio1 RK_PD3 GPIO_ACTIVE_HIGH>;
+ sound-name-prefix = "Speaker Amp";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pins>;
+
+ led-1 {
+ color = <LED_COLOR_ID_ORANGE>;
+ function = LED_FUNCTION_INDICATOR;
+ gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_detect>;
+ simple-audio-card,name = "Analog";
+ simple-audio-card,aux-devs = <&speaker_amp>, <&headphone_amp>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>;
+ simple-audio-card,bitclock-master = <&daicpu>;
+ simple-audio-card,frame-master = <&daicpu>;
+ /* SARADC_IN3 is used as MIC detection / key input */
+
+ simple-audio-card,widgets =
+ "Microphone", "Onboard Microphone",
+ "Microphone", "Microphone Jack",
+ "Speaker", "Speaker",
+ "Headphone", "Headphones";
+
+ simple-audio-card,routing =
+ "Headphones", "LOUT1",
+ "Headphones", "ROUT1",
+ "Speaker", "LOUT2",
+ "Speaker", "ROUT2",
+
+ "Headphones", "Headphones Amp OUTL",
+ "Headphones", "Headphones Amp OUTR",
+ "Headphones Amp INL", "LOUT1",
+ "Headphones Amp INR", "ROUT1",
+
+ "Speaker", "Speaker Amp OUTL",
+ "Speaker", "Speaker Amp OUTR",
+ "Speaker Amp INL", "LOUT2",
+ "Speaker Amp INR", "ROUT2",
+
+ /* single ended signal to LINPUT1 */
+ "LINPUT1", "Microphone Jack",
+ "RINPUT1", "Microphone Jack",
+ /* differential signal */
+ "LINPUT2", "Onboard Microphone",
+ "RINPUT2", "Onboard Microphone";
+
+ daicpu: simple-audio-card,cpu {
+ sound-dai = <&i2s0_8ch>;
+ system-clock-frequency = <12288000>;
+ };
+
+ daicodec: simple-audio-card,codec {
+ sound-dai = <&es8388>;
+ system-clock-frequency = <12288000>;
+ };
+ };
+
+ vcc12v_dcin: vcc12v-dcin-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc12v_dcin";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ vcc3v3_bt: vcc3v3-bt-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
+ regulator-name = "vcc3v3_bt";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <50000>;
+ vin-supply = <&vcc_3v3_s0>;
+ };
+
+ vcc3v3_pcie30: vcc3v3-pcie30-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio3 RK_PC3 GPIO_ACTIVE_HIGH>;
+ regulator-name = "vcc3v3_pcie30";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+
+ vcc3v3_wf: vcc3v3-wf-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_HIGH>;
+ regulator-name = "vcc3v3_wf";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <50000>;
+ vin-supply = <&vcc_3v3_s0>;
+ };
+
+ vcc4v0_sys: vcc4v0-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc4v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <4000000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+
+ vcc5v0_host: vcc5v0-host-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc5v0_host_en>;
+ regulator-name = "vcc5v0_host";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_usb>;
+ };
+
+ vcc5v0_usb: vcc5v0-usb-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_usb";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+};
+
+&combphy0_ps {
+ status = "okay";
+};
+
+&combphy1_ps {
+ status = "okay";
+};
+
+&combphy2_psu {
+ status = "okay";
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b1 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b2 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_b3 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l1 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l2 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l3 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&gmac0 {
+ clock_in_out = "output";
+ phy-handle = <&rgmii_phy>;
+ phy-mode = "rgmii-rxid";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac0_miim
+ &gmac0_tx_bus2
+ &gmac0_rx_bus2
+ &gmac0_rgmii_clk
+ &gmac0_rgmii_bus>;
+ rx_delay = <0x00>;
+ tx_delay = <0x43>;
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ clock-output-names = "hym8563";
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PD4 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hym8563_int>;
+ wakeup-source;
+ };
+};
+
+&i2c7 {
+ status = "okay";
+
+ es8388: audio-codec@11 {
+ compatible = "everest,es8388";
+ reg = <0x11>;
+ assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
+ assigned-clock-rates = <12288000>;
+ clocks = <&cru I2S0_8CH_MCLKOUT>;
+ clock-names = "mclk";
+ AVDD-supply = <&avcc_1v8_codec_s0>;
+ DVDD-supply = <&avcc_1v8_codec_s0>;
+ HPVDD-supply = <&vcc_3v3_s0>;
+ PVDD-supply = <&vcc_3v3_s0>;
+ #sound-dai-cells = <0>;
+ };
+};
+
+&i2s0_8ch {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0_lrck
+ &i2s0_mclk
+ &i2s0_sclk
+ &i2s0_sdi0
+ &i2s0_sdo0>;
+ status = "okay";
+};
+
+&mdio0 {
+ rgmii_phy: ethernet-phy@1 {
+ /* RTL8211F */
+ compatible = "ethernet-phy-id001c.c916";
+ reg = <0x1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtl8211f_rst>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pinctrl {
+ hym8563 {
+ hym8563_int: hym8563-int {
+ rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ leds {
+ led_pins: led-pins {
+ rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ rtl8111 {
+ rtl8111_isolate: rtl8111-isolate {
+ rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ rtl8211f {
+ rtl8211f_rst: rtl8211f-rst {
+ rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ };
+
+ sound {
+ hp_detect: hp-detect {
+ rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb {
+ vcc5v0_host_en: vcc5v0-host-en {
+ rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+/* WIFI */
+&pcie2x1l0 {
+ reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_wf>;
+ status = "okay";
+};
+
+/* GMAC1 */
+&pcie2x1l1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtl8111_isolate>;
+ reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&pcie30phy {
+ status = "okay";
+};
+
+&pcie3x4 {
+ reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie30>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcc_1v8_s0>;
+ status = "okay";
+};
+
+&sata0 {
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ no-sdio;
+ no-sd;
+ non-removable;
+ max-frequency = <150000000>;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ max-frequency = <150000000>;
+ no-sdio;
+ no-mmc;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_3v3_s3>;
+ vqmmc-supply = <&vccio_sd_s0>;
+ status = "okay";
+};
+
+&spi2 {
+ assigned-clocks = <&cru CLK_SPI2>;
+ assigned-clock-rates = <200000000>;
+ num-cs = <2>;
+ status = "okay";
+
+ pmic@0 {
+ compatible = "rockchip,rk806";
+ reg = <0x0>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-parent = <&gpio0>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+ <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+ pinctrl-names = "default";
+ spi-max-frequency = <1000000>;
+
+ vcc1-supply = <&vcc4v0_sys>;
+ vcc2-supply = <&vcc4v0_sys>;
+ vcc3-supply = <&vcc4v0_sys>;
+ vcc4-supply = <&vcc4v0_sys>;
+ vcc5-supply = <&vcc4v0_sys>;
+ vcc6-supply = <&vcc4v0_sys>;
+ vcc7-supply = <&vcc4v0_sys>;
+ vcc8-supply = <&vcc4v0_sys>;
+ vcc9-supply = <&vcc4v0_sys>;
+ vcc10-supply = <&vcc4v0_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc4v0_sys>;
+ vcc13-supply = <&vcc_1v1_nldo_s3>;
+ vcc14-supply = <&vcc_1v1_nldo_s3>;
+ vcca-supply = <&vcc4v0_sys>;
+
+ rk806_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ regulators {
+ vdd_gpu_s0: dcdc-reg1 {
+ regulator-name = "vdd_gpu_s0";
+ regulator-boot-on;
+ regulator-enable-ramp-delay = <400>;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_npu_s0: dcdc-reg2 {
+ regulator-name = "vdd_npu_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_log_s0: dcdc-reg3 {
+ regulator-name = "vdd_log_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <750000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_vdenc_s0: dcdc-reg4 {
+ regulator-name = "vdd_vdenc_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+
+ };
+
+ vdd_gpu_mem_s0: dcdc-reg5 {
+ regulator-name = "vdd_gpu_mem_s0";
+ regulator-boot-on;
+ regulator-enable-ramp-delay = <400>;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+
+ };
+
+ vdd_npu_mem_s0: dcdc-reg6 {
+ regulator-name = "vdd_npu_mem_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+
+ };
+
+ vcc_2v0_pldo_s3: dcdc-reg7 {
+ regulator-name = "vdd_2v0_pldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2000000>;
+ };
+ };
+
+ vdd_vdenc_mem_s0: dcdc-reg8 {
+ regulator-name = "vdd_vdenc_mem_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd2_ddr_s3: dcdc-reg9 {
+ regulator-name = "vdd2_ddr_s3";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_1v1_nldo_s3: dcdc-reg10 {
+ regulator-name = "vcc_1v1_nldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1100000>;
+ };
+ };
+
+ avcc_1v8_s0: pldo-reg1 {
+ regulator-name = "avcc_1v8_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd1_1v8_ddr_s3: pldo-reg2 {
+ regulator-name = "vdd1_1v8_ddr_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ avcc_1v8_codec_s0: pldo-reg3 {
+ regulator-name = "avcc_1v8_codec_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_3v3_s3: pldo-reg4 {
+ regulator-name = "vcc_3v3_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vccio_sd_s0: pldo-reg5 {
+ regulator-name = "vccio_sd_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s3: pldo-reg6 {
+ regulator-name = "vcc_1v8_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd_0v75_s3: nldo-reg1 {
+ regulator-name = "vdd_0v75_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ /* reserved for LPDDR5, unused? */
+ vdd2l_0v9_ddr_s3: nldo-reg2 {
+ regulator-name = "vdd2l_0v9_ddr_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <900000>;
+ };
+ };
+
+ vdd_0v75_hdmi_edp_s0: nldo-reg3 {
+ regulator-name = "vdd_0v75_hdmi_edp_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ avdd_0v75_s0: nldo-reg4 {
+ regulator-name = "avdd_0v75_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v85_s0: nldo-reg5 {
+ regulator-name = "vdd_0v85_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+
+ pmic@1 {
+ compatible = "rockchip,rk806";
+ reg = <0x01>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-parent = <&gpio0>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-0 = <&rk806_slave_dvs1_null>, <&rk806_slave_dvs2_null>,
+ <&rk806_slave_dvs3_null>;
+ pinctrl-names = "default";
+ spi-max-frequency = <1000000>;
+
+ vcc1-supply = <&vcc4v0_sys>;
+ vcc2-supply = <&vcc4v0_sys>;
+ vcc3-supply = <&vcc4v0_sys>;
+ vcc4-supply = <&vcc4v0_sys>;
+ vcc5-supply = <&vcc4v0_sys>;
+ vcc6-supply = <&vcc4v0_sys>;
+ vcc7-supply = <&vcc4v0_sys>;
+ vcc8-supply = <&vcc4v0_sys>;
+ vcc9-supply = <&vcc4v0_sys>;
+ vcc10-supply = <&vcc4v0_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc4v0_sys>;
+ vcc13-supply = <&vcc_1v1_nldo_s3>;
+ vcc14-supply = <&vcc_2v0_pldo_s3>;
+ vcca-supply = <&vcc4v0_sys>;
+
+ rk806_slave_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun0";
+ };
+
+ rk806_slave_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_slave_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ regulators {
+ vdd_cpu_big1_s0: dcdc-reg1 {
+ regulator-name = "vdd_cpu_big1_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_big0_s0: dcdc-reg2 {
+ regulator-name = "vdd_cpu_big0_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_s0: dcdc-reg3 {
+ regulator-name = "vdd_cpu_lit_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_3v3_s0: dcdc-reg4 {
+ regulator-name = "vcc_3v3_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_big1_mem_s0: dcdc-reg5 {
+ regulator-name = "vdd_cpu_big1_mem_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+
+ vdd_cpu_big0_mem_s0: dcdc-reg6 {
+ regulator-name = "vdd_cpu_big0_mem_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s0: dcdc-reg7 {
+ regulator-name = "vcc_1v8_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_mem_s0: dcdc-reg8 {
+ regulator-name = "vdd_cpu_lit_mem_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vddq_ddr_s0: dcdc-reg9 {
+ regulator-name = "vddq_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_ddr_s0: dcdc-reg10 {
+ regulator-name = "vdd_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <900000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ /* reserved, unused? */
+ vcc_1v8_cam_s0: pldo-reg1 {
+ regulator-name = "vcc_1v8_cam_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ avdd1v8_ddr_pll_s0: pldo-reg2 {
+ regulator-name = "avdd1v8_ddr_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_1v8_pll_s0: pldo-reg3 {
+ regulator-name = "vdd_1v8_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ /* reserved, unused? */
+ vcc_3v3_sd_s0: pldo-reg4 {
+ regulator-name = "vcc_3v3_sd_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ /* reserved, unused? */
+ vcc_2v8_cam_s0: pldo-reg5 {
+ regulator-name = "vcc_2v8_cam_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ /* unused */
+ pldo6_s3: pldo-reg6 {
+ regulator-name = "pldo6_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd_0v75_pll_s0: nldo-reg1 {
+ regulator-name = "vdd_0v75_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_ddr_pll_s0: nldo-reg2 {
+ regulator-name = "vdd_ddr_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ avdd_0v85_s0: nldo-reg3 {
+ regulator-name = "avdd_0v85_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ /* reserved, unused */
+ avdd_1v2_cam_s0: nldo-reg4 {
+ regulator-name = "avdd_1v2_cam_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ avdd_1v2_s0: nldo-reg5 {
+ regulator-name = "avdd_1v2_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&u2phy2 {
+ status = "okay";
+};
+
+&u2phy2_host {
+ phy-supply = <&vcc5v0_host>;
+ status = "okay";
+};
+
+&u2phy3 {
+ status = "okay";
+};
+
+&u2phy3_host {
+ phy-supply = <&vcc5v0_host>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2m0_xfer>;
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
index 8ab60968f275..741f631db345 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
@@ -3,6 +3,7 @@
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
#include "rk3588.dtsi"
/ {
@@ -12,6 +13,7 @@
aliases {
mmc0 = &sdhci;
mmc1 = &sdmmc;
+ mmc2 = &sdio;
serial2 = &uart2;
};
@@ -36,6 +38,19 @@
pinctrl-0 = <&hp_detect>;
};
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_rgb_b>;
+
+ led_rgb_b {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_BLUE>;
+ gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
fan: pwm-fan {
compatible = "pwm-fan";
cooling-levels = <0 95 145 195 255>;
@@ -44,6 +59,43 @@
#cooling-cells = <2>;
};
+ vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_0_vcc3v3_en>;
+ regulator-name = "vcc3v3_pcie2x1l0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <50000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc3v3_pcie2x1l2: vcc3v3-pcie2x1l2-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_pcie2x1l2";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc_3v3_s3>;
+ };
+
+ vcc3v3_pcie30: vcc3v3-pcie30-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3_vcc3v3_en>;
+ regulator-name = "vcc3v3_pcie30";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
vcc5v0_host: vcc5v0-host-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host";
@@ -78,6 +130,14 @@
};
};
+&combphy0_ps {
+ status = "okay";
+};
+
+&combphy1_ps {
+ status = "okay";
+};
+
&cpu_b0 {
cpu-supply = <&vdd_cpu_big0_s0>;
};
@@ -204,6 +264,34 @@
};
};
+&pcie2x1l0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_0_rst>;
+ reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie2x1l0>;
+ status = "okay";
+};
+
+&pcie2x1l2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_2_rst>;
+ reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie2x1l2>;
+ status = "okay";
+};
+
+&pcie30phy {
+ status = "okay";
+};
+
+&pcie3x4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3_rst>;
+ reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie30>;
+ status = "okay";
+};
+
&pinctrl {
hym8563 {
hym8563_int: hym8563-int {
@@ -211,12 +299,42 @@
};
};
+ leds {
+ led_rgb_b: led-rgb-b {
+ rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
sound {
hp_detect: hp-detect {
rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
+ pcie2 {
+ pcie2_0_rst: pcie2-0-rst {
+ rockchip,pins = <4 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie2_0_vcc3v3_en: pcie2-0-vcc-en {
+ rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie2_2_rst: pcie2-2-rst {
+ rockchip,pins = <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie3 {
+ pcie3_rst: pcie3-rst {
+ rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie3_vcc3v3_en: pcie3-vcc3v3-en {
+ rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
usb {
vcc5v0_host_en: vcc5v0-host-en {
rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
@@ -258,6 +376,33 @@
status = "okay";
};
+&sdio {
+ max-frequency = <200000000>;
+ no-sd;
+ no-mmc;
+ non-removable;
+ bus-width = <4>;
+ cap-sdio-irq;
+ disable-wp;
+ keep-power-in-suspend;
+ wakeup-source;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc3v3_pcie2x1l0>;
+ vqmmc-supply = <&vcc_1v8_s3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdiom0_pins>;
+ status = "okay";
+};
+
+&uart6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart6m1_xfer &uart6m1_ctsn &uart6m1_rtsn>;
+ status = "okay";
+};
+
&spi2 {
status = "okay";
assigned-clocks = <&cru CLK_SPI2>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dts b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dts
new file mode 100644
index 000000000000..7bcad28d73b8
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * This device tree covers the common case where the RK1 is used as a
+ * "compute node" system, where the carrier board is functioning more like a
+ * generic backplane (with no non-autoenumerable peripherals of its own) than
+ * like a device that the SoM is meant to enable.
+ *
+ * Copyright (c) 2023 Sam Edwards <CFSworks@gmail.com>
+ */
+
+/dts-v1/;
+#include "rk3588-turing-rk1.dtsi"
+
+/ {
+ model = "Turing Machines RK1";
+ compatible = "turing,rk1", "rockchip,rk3588";
+
+ chosen {
+ stdout-path = "serial9:115200n8";
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
new file mode 100644
index 000000000000..d88c0e852356
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
@@ -0,0 +1,614 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device tree definitions for the Turing RK1 SoM.
+ *
+ * Copyright (c) 2023 Sam Edwards <CFSworks@gmail.com>
+ *
+ * Based on RK3588-EVB1 devicetree
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rk3588.dtsi"
+
+/ {
+ compatible = "turing,rk1", "rockchip,rk3588";
+
+ aliases {
+ ethernet0 = &gmac1;
+ mmc0 = &sdhci;
+ serial2 = &uart2;
+ serial9 = &uart9;
+ };
+
+ fan: pwm-fan {
+ compatible = "pwm-fan";
+ cooling-levels = <0 25 95 145 195 255>;
+ fan-supply = <&vcc5v0_sys>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0m2_pins &fan_int>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA4 IRQ_TYPE_EDGE_FALLING>;
+ pwms = <&pwm0 0 50000 0>;
+ #cooling-cells = <2>;
+ };
+
+ vcc3v3_pcie30: vcc3v3-pcie30-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_pcie30";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc3v3_pcie30_en>;
+ startup-delay-us = <5000>;
+ };
+
+ vcc5v0_sys: vcc5v0-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v1_nldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+};
+
+&combphy2_psu {
+ status = "okay";
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b1 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b2 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_b3 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l1 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l2 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l3 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&gmac1 {
+ clock_in_out = "output";
+ phy-handle = <&rgmii_phy>;
+ phy-mode = "rgmii-rxid";
+ pinctrl-0 = <&gmac1_miim
+ &gmac1_tx_bus2
+ &gmac1_rx_bus2
+ &gmac1_rgmii_clk
+ &gmac1_rgmii_bus>;
+ pinctrl-names = "default";
+ rx_delay = <0x00>;
+ tx_delay = <0x43>;
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0m2_xfer>;
+ status = "okay";
+
+ vdd_cpu_big0_s0: regulator@42 {
+ compatible = "rockchip,rk8602";
+ reg = <0x42>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big0_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_big1_s0: regulator@43 {
+ compatible = "rockchip,rk8603", "rockchip,rk8602";
+ reg = <0x43>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big1_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1m2_xfer>;
+ status = "okay";
+
+ vdd_npu_s0: regulator@42 {
+ compatible = "rockchip,rk8602";
+ reg = <0x42>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_npu_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c6 {
+ status = "okay";
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ clock-output-names = "hym8563";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hym8563_int>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-source;
+ };
+};
+
+&mdio1 {
+ rgmii_phy: ethernet-phy@1 {
+ /* RTL8211F */
+ compatible = "ethernet-phy-id001c.c916",
+ "ethernet-phy-ieee802.3-c22";
+ reg = <0x1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtl8211f_rst>;
+ reset-assert-us = <15000>;
+ reset-deassert-us = <50000>;
+ reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pcie2x1l1 {
+ linux,pci-domain = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_reset>;
+ reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&pcie30phy {
+ status = "okay";
+};
+
+&pcie3x4 {
+ linux,pci-domain = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3_reset>;
+ reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie30>;
+ status = "okay";
+};
+
+&pinctrl {
+ fan {
+ fan_int: fan-int {
+ rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ hym8563 {
+ hym8563_int: hym8563-int {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ pcie2 {
+ pcie2_reset: pcie2-reset {
+ rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie3 {
+ pcie3_reset: pcie3-reset {
+ rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ vcc3v3_pcie30_en: pcie3-reg {
+ rockchip,pins = <2 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ rtl8211f {
+ rtl8211f_rst: rtl8211f-rst {
+ rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pwm0 {
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ no-sdio;
+ no-sd;
+ non-removable;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ status = "okay";
+};
+
+&spi2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
+ num-cs = <1>;
+
+ pmic@0 {
+ compatible = "rockchip,rk806";
+ spi-max-frequency = <1000000>;
+ reg = <0x0>;
+
+ interrupt-parent = <&gpio0>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+ <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc5v0_sys>;
+ vcc6-supply = <&vcc5v0_sys>;
+ vcc7-supply = <&vcc5v0_sys>;
+ vcc8-supply = <&vcc5v0_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+ vcc10-supply = <&vcc5v0_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc5v0_sys>;
+ vcc13-supply = <&vcc_1v1_nldo_s3>;
+ vcc14-supply = <&vcc_1v1_nldo_s3>;
+ vcca-supply = <&vcc5v0_sys>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ rk806_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ regulators {
+ vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 {
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_gpu_s0";
+ regulator-enable-ramp-delay = <400>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_cpu_lit_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_log_s0: dcdc-reg3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <750000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_log_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_vdenc_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_ddr_s0: dcdc-reg5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <900000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_ddr_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ vdd2_ddr_s3: dcdc-reg6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vdd2_ddr_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_2v0_pldo_s3: dcdc-reg7 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_2v0_pldo_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2000000>;
+ };
+ };
+
+ vcc_3v3_s3: dcdc-reg8 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc_3v3_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vddq_ddr_s0: dcdc-reg9 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vddq_ddr_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s3: dcdc-reg10 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc_1v8_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ avcc_1v8_s0: pldo-reg1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "avcc_1v8_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s0: pldo-reg2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc_1v8_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ avdd_1v2_s0: pldo-reg3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-name = "avdd_1v2_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_3v3_s0: pldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vcc_3v3_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd_s0: pldo-reg5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vccio_sd_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ pldo6_s3: pldo-reg6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "pldo6_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd_0v75_s3: nldo-reg1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-name = "vdd_0v75_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_ddr_pll_s0: nldo-reg2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-name = "vdd_ddr_pll_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ avdd_0v75_s0: nldo-reg3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-name = "avdd_0v75_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v85_s0: nldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-name = "vdd_0v85_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v75_s0: nldo-reg5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-name = "vdd_0v75_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&uart2 {
+ pinctrl-0 = <&uart2m0_xfer>;
+ status = "okay";
+};
+
+&uart9 {
+ pinctrl-0 = <&uart9m0_xfer>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
index d1503a4b233a..60f00ceb630e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
@@ -3,6 +3,7 @@
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/pinctrl/rockchip.h>
#include <dt-bindings/usb/pd.h>
#include "rk3588s.dtsi"
@@ -11,6 +12,34 @@
model = "Indiedroid Nova";
compatible = "indiedroid,nova", "rockchip,rk3588s";
+ adc-keys-0 {
+ compatible = "adc-keys";
+ io-channel-names = "buttons";
+ io-channels = <&saradc 0>;
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-boot {
+ label = "boot";
+ linux,code = <KEY_PROG1>;
+ press-threshold-microvolt = <18000>;
+ };
+ };
+
+ adc-keys-1 {
+ compatible = "adc-keys";
+ io-channel-names = "buttons";
+ io-channels = <&saradc 1>;
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-recovery {
+ label = "recovery";
+ linux,code = <KEY_PROG2>;
+ press-threshold-microvolt = <18000>;
+ };
+ };
+
aliases {
mmc0 = &sdhci;
mmc1 = &sdmmc;
@@ -109,6 +138,10 @@
};
};
+&combphy0_ps {
+ status = "okay";
+};
+
&cpu_l0 {
cpu-supply = <&vdd_cpu_lit_s0>;
};
@@ -348,6 +381,12 @@
};
};
+&pcie2x1l2 {
+ pinctrl-0 = <&rtl8111_perstb>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&pinctrl {
bluetooth-pins {
bt_reset: bt-reset {
@@ -366,6 +405,12 @@
};
};
+ ethernet-pins {
+ rtl8111_perstb: rtl8111-perstb {
+ rockchip,pins = <3 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
hym8563 {
hym8563_int: hym8563-int {
@@ -394,6 +439,11 @@
};
};
+&saradc {
+ vref-supply = <&vcca_1v8_s0>;
+ status = "okay";
+};
+
/* HS400 modes seemed to cause io errors. */
&sdhci {
bus-width = <8>;
@@ -735,6 +785,24 @@
status = "okay";
};
+&u2phy2 {
+ status = "okay";
+};
+
+&u2phy2_host {
+ phy-supply = <&vcc5v0_usb>;
+ status = "okay";
+};
+
+&u2phy3 {
+ status = "okay";
+};
+
+&u2phy3_host {
+ phy-supply = <&vcc5v0_usb>;
+ status = "okay";
+};
+
&uart2 {
pinctrl-0 = <&uart2m0_xfer>;
status = "okay";
@@ -759,3 +827,19 @@
pinctrl-names = "default";
};
};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts
new file mode 100644
index 000000000000..e3a839a12dc6
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts
@@ -0,0 +1,662 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rk3588s.dtsi"
+
+/ {
+ model = "Xunlong Orange Pi 5";
+ compatible = "xunlong,orangepi-5", "rockchip,rk3588s";
+
+ aliases {
+ mmc0 = &sdmmc;
+ serial2 = &uart2;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ adc-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 1>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-recovery {
+ label = "Recovery";
+ linux,code = <KEY_VENDOR>;
+ press-threshold-microvolt = <1800>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&leds_gpio>;
+
+ led-1 {
+ gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>;
+ label = "status_led";
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ vbus_typec: vbus-typec-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&typec5v_pwren>;
+ regulator-name = "vbus_typec";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_sys: vcc5v0-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator {
+ compatible = "regulator-fixed";
+ enable-active-low;
+ gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_LOW>;
+ regulator-name = "vcc_3v3_sd_s0";
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_3v3_s3>;
+ };
+
+ vcc3v3_pcie20: vcc3v3-pcie20-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>;
+ regulator-name = "vcc3v3_pcie20";
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ startup-delay-us = <50000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+};
+
+&combphy0_ps {
+ status = "okay";
+};
+
+&combphy2_psu {
+ status = "okay";
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b1 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b2 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_b3 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l1 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l2 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l3 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&gmac1 {
+ clock_in_out = "output";
+ phy-handle = <&rgmii_phy1>;
+ phy-mode = "rgmii-rxid";
+ pinctrl-0 = <&gmac1_miim
+ &gmac1_tx_bus2
+ &gmac1_rx_bus2
+ &gmac1_rgmii_clk
+ &gmac1_rgmii_bus>;
+ pinctrl-names = "default";
+ tx_delay = <0x42>;
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0m2_xfer>;
+ status = "okay";
+
+ vdd_cpu_big0_s0: regulator@42 {
+ compatible = "rockchip,rk8602";
+ reg = <0x42>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big0_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_big1_s0: regulator@43 {
+ compatible = "rockchip,rk8603", "rockchip,rk8602";
+ reg = <0x43>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big1_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ vdd_npu_s0: regulator@42 {
+ compatible = "rockchip,rk8602";
+ reg = <0x42>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_npu_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c6m3_xfer>;
+ status = "okay";
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ clock-output-names = "hym8563";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hym8563_int>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-source;
+ };
+};
+
+&mdio1 {
+ rgmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pcie2x1l2 {
+ reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie20>;
+ status = "okay";
+};
+
+&pinctrl {
+ gpio-func {
+ leds_gpio: leds-gpio {
+ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ hym8563 {
+ hym8563_int: hym8563-int {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb-typec {
+ usbc0_int: usbc0-int {
+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ typec5v_pwren: typec5v-pwren {
+ rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&saradc {
+ vref-supply = <&avcc_1v8_s0>;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ disable-wp;
+ max-frequency = <150000000>;
+ no-mmc;
+ no-sdio;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_3v3_sd_s0>;
+ vqmmc-supply = <&vccio_sd_s0>;
+ status = "okay";
+};
+
+&sfc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&fspim0_pins>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-max-frequency = <100000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <1>;
+ };
+};
+
+&spi2 {
+ status = "okay";
+ assigned-clocks = <&cru CLK_SPI2>;
+ assigned-clock-rates = <200000000>;
+ num-cs = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
+
+ pmic@0 {
+ compatible = "rockchip,rk806";
+ reg = <0x0>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+ <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+ spi-max-frequency = <1000000>;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc5v0_sys>;
+ vcc6-supply = <&vcc5v0_sys>;
+ vcc7-supply = <&vcc5v0_sys>;
+ vcc8-supply = <&vcc5v0_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+ vcc10-supply = <&vcc5v0_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc5v0_sys>;
+ vcc13-supply = <&vcc_1v1_nldo_s3>;
+ vcc14-supply = <&vcc_1v1_nldo_s3>;
+ vcca-supply = <&vcc5v0_sys>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ rk806_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ regulators {
+ vdd_gpu_s0: dcdc-reg1 {
+ regulator-name = "vdd_gpu_s0";
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <400>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_s0: dcdc-reg2 {
+ regulator-name = "vdd_cpu_lit_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_log_s0: dcdc-reg3 {
+ regulator-name = "vdd_log_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <750000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_vdenc_s0: dcdc-reg4 {
+ regulator-name = "vdd_vdenc_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_ddr_s0: dcdc-reg5 {
+ regulator-name = "vdd_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <900000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ vcc_1v1_nldo_s3: vdd2_ddr_s3: dcdc-reg6 {
+ regulator-name = "vdd2_ddr_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1100000>;
+ regulator-min-microvolt = <1100000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_2v0_pldo_s3: dcdc-reg7 {
+ regulator-name = "vdd_2v0_pldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2000000>;
+ };
+ };
+
+ vcc_3v3_s3: dcdc-reg8 {
+ regulator-name = "vcc_3v3_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vddq_ddr_s0: dcdc-reg9 {
+ regulator-name = "vddq_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s3: dcdc-reg10 {
+ regulator-name = "vcc_1v8_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ avcc_1v8_s0: pldo-reg1 {
+ regulator-name = "avcc_1v8_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s0: pldo-reg2 {
+ regulator-name = "vcc_1v8_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ avdd_1v2_s0: pldo-reg3 {
+ regulator-name = "avdd_1v2_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_3v3_s0: pldo-reg4 {
+ regulator-name = "vcc_3v3_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd_s0: pldo-reg5 {
+ regulator-name = "vccio_sd_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ pldo6_s3: pldo-reg6 {
+ regulator-name = "pldo6_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd_0v75_s3: nldo-reg1 {
+ regulator-name = "vdd_0v75_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_ddr_pll_s0: nldo-reg2 {
+ regulator-name = "vdd_ddr_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ avdd_0v75_s0: nldo-reg3 {
+ regulator-name = "avdd_0v75_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v85_s0: nldo-reg4 {
+ regulator-name = "vdd_0v85_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v75_s0: nldo-reg5 {
+ regulator-name = "vdd_0v75_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&u2phy2 {
+ status = "okay";
+};
+
+&u2phy2_host {
+ status = "okay";
+};
+
+&u2phy3 {
+ status = "okay";
+};
+
+&u2phy3_host {
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-0 = <&uart2m0_xfer>;
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi
index 48181671eacb..30db12c4fc82 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi
@@ -369,7 +369,7 @@
emmc_data_strobe: emmc-data-strobe {
rockchip,pins =
/* emmc_data_strobe */
- <2 RK_PA2 1 &pcfg_pull_none>;
+ <2 RK_PA2 1 &pcfg_pull_down>;
};
};
@@ -1350,6 +1350,41 @@
i2s2 {
/omit-if-no-ref/
+ i2s2m0_lrck: i2s2m0-lrck {
+ rockchip,pins =
+ /* i2s2m0_lrck */
+ <2 RK_PC0 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ i2s2m0_mclk: i2s2m0-mclk {
+ rockchip,pins =
+ /* i2s2m0_mclk */
+ <2 RK_PB6 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ i2s2m0_sclk: i2s2m0-sclk {
+ rockchip,pins =
+ /* i2s2m0_sclk */
+ <2 RK_PB7 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ i2s2m0_sdi: i2s2m0-sdi {
+ rockchip,pins =
+ /* i2s2m0_sdi */
+ <2 RK_PC3 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ i2s2m0_sdo: i2s2m0-sdo {
+ rockchip,pins =
+ /* i2s2m0_sdo */
+ <4 RK_PC3 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
i2s2m1_lrck: i2s2m1-lrck {
rockchip,pins =
/* i2s2m1_lrck */
@@ -3308,6 +3343,15 @@
uart9 {
/omit-if-no-ref/
+ uart9m0_xfer: uart9m0-xfer {
+ rockchip,pins =
+ /* uart9_rx_m0 */
+ <2 RK_PC4 10 &pcfg_pull_up>,
+ /* uart9_tx_m0 */
+ <2 RK_PC2 10 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
uart9m1_xfer: uart9m1-xfer {
rockchip,pins =
/* uart9_rx_m1 */
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 5544f66c6ff4..8aa0499f9b03 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -443,6 +443,32 @@
status = "disabled";
};
+ usb_host2_xhci: usb@fcd00000 {
+ compatible = "rockchip,rk3588-dwc3", "snps,dwc3";
+ reg = <0x0 0xfcd00000 0x0 0x400000>;
+ interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru REF_CLK_USB3OTG2>, <&cru SUSPEND_CLK_USB3OTG2>,
+ <&cru ACLK_USB3OTG2>, <&cru CLK_UTMI_OTG2>,
+ <&cru CLK_PIPEPHY2_PIPE_U3_G>;
+ clock-names = "ref_clk", "suspend_clk", "bus_clk", "utmi", "pipe";
+ dr_mode = "host";
+ phys = <&combphy2_psu PHY_TYPE_USB3>;
+ phy-names = "usb3-phy";
+ phy_type = "utmi_wide";
+ resets = <&cru SRST_A_USB3OTG2>;
+ snps,dis_enblslpm_quirk;
+ snps,dis-u2-freeclk-exists-quirk;
+ snps,dis-del-phy-power-chg-quirk;
+ snps,dis-tx-ipgap-linecheck-quirk;
+ snps,dis_rxdet_inp3_quirk;
+ status = "disabled";
+ };
+
+ pmu1grf: syscon@fd58a000 {
+ compatible = "rockchip,rk3588-pmugrf", "syscon", "simple-mfd";
+ reg = <0x0 0xfd58a000 0x0 0x10000>;
+ };
+
sys_grf: syscon@fd58c000 {
compatible = "rockchip,rk3588-sys-grf", "syscon";
reg = <0x0 0xfd58c000 0x0 0x1000>;
@@ -1329,6 +1355,16 @@
};
};
+ dfi: dfi@fe060000 {
+ reg = <0x00 0xfe060000 0x00 0x10000>;
+ compatible = "rockchip,rk3588-dfi";
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH 0>;
+ rockchip,pmu = <&pmu1grf>;
+ };
+
gmac1: ethernet@fe1c0000 {
compatible = "rockchip,rk3588-gmac", "snps,dwmac-4.20a";
reg = <0x0 0xfe1c0000 0x0 0x10000>;
@@ -1424,6 +1460,17 @@
};
};
+ sfc: spi@fe2b0000 {
+ compatible = "rockchip,sfc";
+ reg = <0x0 0xfe2b0000 0x0 0x4000>;
+ interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>;
+ clock-names = "clk_sfc", "hclk_sfc";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
sdmmc: mmc@fe2c0000 {
compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc";
reg = <0x0 0xfe2c0000 0x0 0x4000>;
@@ -2304,6 +2351,19 @@
#interrupt-cells = <2>;
};
};
+
+ av1d: video-codec@fdc70000 {
+ compatible = "rockchip,rk3588-av1-vpu";
+ reg = <0x0 0xfdc70000 0x0 0x800>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "vdpu";
+ assigned-clocks = <&cru ACLK_AV1>, <&cru PCLK_AV1>;
+ assigned-clock-rates = <400000000>, <400000000>;
+ clocks = <&cru ACLK_AV1>, <&cru PCLK_AV1>;
+ clock-names = "aclk", "hclk";
+ power-domains = <&power RK3588_PD_AV1>;
+ resets = <&cru SRST_A_AV1>, <&cru SRST_P_AV1>, <&cru SRST_A_AV1_BIU>, <&cru SRST_P_AV1_BIU>;
+ };
};
#include "rk3588s-pinctrl.dtsi"
diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
index 7bb36b071475..4680571c264d 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
@@ -52,6 +52,8 @@
l2: l2-cache {
compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
};
};
diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
index 4e2171630272..335093da6573 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
@@ -86,10 +86,14 @@
a72_l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
};
a53_l2: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
};
};
diff --git a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi
index 38ccfb46ea42..d6e3cc6fdb25 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi
@@ -83,6 +83,8 @@
l2: l2-cache {
compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
};
};
diff --git a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
index d34a1d5e79c0..66791a974f8f 100644
--- a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
@@ -6,6 +6,60 @@
#include <dt-bindings/pinctrl/stm32-pinfunc.h>
&pinctrl {
+ sdmmc1_b4_pins_a: sdmmc1-b4-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('E', 4, AF10)>, /* SDMMC1_D0 */
+ <STM32_PINMUX('E', 5, AF10)>, /* SDMMC1_D1 */
+ <STM32_PINMUX('E', 0, AF10)>, /* SDMMC1_D2 */
+ <STM32_PINMUX('E', 1, AF10)>, /* SDMMC1_D3 */
+ <STM32_PINMUX('E', 2, AF10)>; /* SDMMC1_CMD */
+ slew-rate = <2>;
+ drive-push-pull;
+ bias-disable;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 3, AF10)>; /* SDMMC1_CK */
+ slew-rate = <3>;
+ drive-push-pull;
+ bias-disable;
+ };
+ };
+
+ sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('E', 4, AF10)>, /* SDMMC1_D0 */
+ <STM32_PINMUX('E', 5, AF10)>, /* SDMMC1_D1 */
+ <STM32_PINMUX('E', 0, AF10)>, /* SDMMC1_D2 */
+ <STM32_PINMUX('E', 1, AF10)>; /* SDMMC1_D3 */
+ slew-rate = <2>;
+ drive-push-pull;
+ bias-disable;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 3, AF10)>; /* SDMMC1_CK */
+ slew-rate = <3>;
+ drive-push-pull;
+ bias-disable;
+ };
+ pins3 {
+ pinmux = <STM32_PINMUX('E', 2, AF10)>; /* SDMMC1_CMD */
+ slew-rate = <2>;
+ drive-open-drain;
+ bias-disable;
+ };
+ };
+
+ sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('E', 4, ANALOG)>, /* SDMMC1_D0 */
+ <STM32_PINMUX('E', 5, ANALOG)>, /* SDMMC1_D1 */
+ <STM32_PINMUX('E', 0, ANALOG)>, /* SDMMC1_D2 */
+ <STM32_PINMUX('E', 1, ANALOG)>, /* SDMMC1_D3 */
+ <STM32_PINMUX('E', 3, ANALOG)>, /* SDMMC1_CK */
+ <STM32_PINMUX('E', 2, ANALOG)>; /* SDMMC1_CMD */
+ };
+ };
+
usart2_pins_a: usart2-0 {
pins1 {
pinmux = <STM32_PINMUX('A', 4, AF6)>; /* USART2_TX */
diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index 5268a4321841..124403f5f1f4 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -28,6 +28,12 @@
interrupt-parent = <&intc>;
};
+ arm_wdt: watchdog {
+ compatible = "arm,smc-wdt";
+ arm,smc-id = <0xb200005a>;
+ status = "disabled";
+ };
+
clocks {
ck_flexgen_08: ck-flexgen-08 {
#clock-cells = <0>;
@@ -119,6 +125,19 @@
clocks = <&ck_flexgen_08>;
status = "disabled";
};
+
+ sdmmc1: mmc@48220000 {
+ compatible = "st,stm32mp25-sdmmc2", "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00353180>;
+ reg = <0x48220000 0x400>, <0x44230400 0x8>;
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ck_flexgen_51>;
+ clock-names = "apb_pclk";
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ max-frequency = <120000000>;
+ status = "disabled";
+ };
};
syscfg: syscon@44230000 {
diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
index 39b4726cc098..b2d3afb15758 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
@@ -6,6 +6,7 @@
/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
#include "stm32mp257.dtsi"
#include "stm32mp25xf.dtsi"
#include "stm32mp25-pinctrl.dtsi"
@@ -39,6 +40,32 @@
no-map;
};
};
+
+ vdd_sdcard: vdd-sdcard {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd_sdcard";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+};
+
+&arm_wdt {
+ timeout-sec = <32>;
+ status = "okay";
+};
+
+&sdmmc1 {
+ pinctrl-names = "default", "opendrain", "sleep";
+ pinctrl-0 = <&sdmmc1_b4_pins_a>;
+ pinctrl-1 = <&sdmmc1_b4_od_pins_a>;
+ pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
+ cd-gpios = <&gpiod 9 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ disable-wp;
+ st,neg-edge;
+ bus-width = <4>;
+ vmmc-supply = <&vdd_sdcard>;
+ status = "okay";
};
&usart2 {
diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile
index e7b8e2e7f083..77a347f9f47d 100644
--- a/arch/arm64/boot/dts/ti/Makefile
+++ b/arch/arm64/boot/dts/ti/Makefile
@@ -9,6 +9,8 @@
# alphabetically.
# Boards with AM62x SoC
+k3-am625-sk-hdmi-audio-dtbs := k3-am625-sk.dtb k3-am62x-sk-hdmi-audio.dtbo
+k3-am62-lp-sk-hdmi-audio-dtbs := k3-am62-lp-sk.dtb k3-am62x-sk-hdmi-audio.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-am625-beagleplay.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-phyboard-lyra-rdk.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-sk.dtb
@@ -19,7 +21,8 @@ dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-dahlia.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-dev.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-yavia.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am62-lp-sk.dtb
-dtb-$(CONFIG_ARCH_K3) += k3-am62x-sk-hdmi-audio.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am625-sk-hdmi-audio.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am62-lp-sk-hdmi-audio.dtb
# Boards with AM62Ax SoC
dtb-$(CONFIG_ARCH_K3) += k3-am62a7-sk.dtb
@@ -43,6 +46,8 @@ dtb-$(CONFIG_ARCH_K3) += k3-am642-tqma64xxl-mbax4xxl-wlan.dtb
# Boards with AM65x SoC
k3-am654-gp-evm-dtbs := k3-am654-base-board.dtb k3-am654-base-board-rocktech-rk101-panel.dtbo
+k3-am654-evm-dtbs := k3-am654-base-board.dtb k3-am654-icssg2.dtbo
+k3-am654-idk-dtbs := k3-am654-evm.dtb k3-am654-idk.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-am6528-iot2050-basic.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am6528-iot2050-basic-pg2.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced.dtb
@@ -50,6 +55,8 @@ dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced-m2.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced-pg2.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am654-base-board.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am654-gp-evm.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am654-evm.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am654-idk.dtb
# Boards with J7200 SoC
k3-j7200-evm-dtbs := k3-j7200-common-proc-board.dtb k3-j7200-evm-quad-port-eth-exp.dtbo
@@ -66,6 +73,8 @@ dtb-$(CONFIG_ARCH_K3) += k3-j721e-sk.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am68-sk-base-board.dtb
dtb-$(CONFIG_ARCH_K3) += k3-j721s2-common-proc-board.dtb
dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-gesi-exp-board.dtbo
+k3-j721s2-evm-dtbs := k3-j721s2-common-proc-board.dtb k3-j721s2-evm-gesi-exp-board.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm.dtb
# Boards with J784s4 SoC
dtb-$(CONFIG_ARCH_K3) += k3-am69-sk.dtb
diff --git a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
index 284b90c94da8..e5c64c86d1d5 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
@@ -81,7 +81,8 @@
};
dmss: bus@48000000 {
- compatible = "simple-mfd";
+ bootph-all;
+ compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
dma-ranges;
@@ -90,6 +91,7 @@
ti,sci-dev-id = <25>;
secure_proxy_main: mailbox@4d000000 {
+ bootph-all;
compatible = "ti,am654-secure-proxy";
#mbox-cells = <1>;
reg-names = "target_data", "rt", "scfg";
@@ -165,6 +167,7 @@
};
dmsc: system-controller@44043000 {
+ bootph-all;
compatible = "ti,k2g-sci";
ti,host-id = <12>;
mbox-names = "rx", "tx";
@@ -174,16 +177,19 @@
reg = <0x00 0x44043000 0x00 0xfe0>;
k3_pds: power-controller {
+ bootph-all;
compatible = "ti,sci-pm-domain";
#power-domain-cells = <2>;
};
k3_clks: clock-controller {
+ bootph-all;
compatible = "ti,k2g-sci-clk";
#clock-cells = <2>;
};
k3_reset: reset-controller {
+ bootph-all;
compatible = "ti,sci-reset";
#reset-cells = <2>;
};
@@ -202,6 +208,7 @@
};
secure_proxy_sa3: mailbox@43600000 {
+ bootph-pre-ram;
compatible = "ti,am654-secure-proxy";
#mbox-cells = <1>;
reg-names = "target_data", "rt", "scfg";
@@ -217,6 +224,7 @@
};
main_pmx0: pinctrl@f4000 {
+ bootph-all;
compatible = "pinctrl-single";
reg = <0x00 0xf4000 0x00 0x2ac>;
#pinctrl-cells = <1>;
@@ -225,12 +233,14 @@
};
main_esm: esm@420000 {
+ bootph-pre-ram;
compatible = "ti,j721e-esm";
reg = <0x00 0x420000 0x00 0x1000>;
ti,esm-pins = <160>, <161>, <162>, <163>, <177>, <178>;
};
main_timer0: timer@2400000 {
+ bootph-all;
compatible = "ti,am654-timer";
reg = <0x00 0x2400000 0x00 0x400>;
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi
index 80a3e1db26a9..0e0b234581c6 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi
@@ -7,6 +7,7 @@
&cbass_mcu {
mcu_pmx0: pinctrl@4084000 {
+ bootph-all;
compatible = "pinctrl-single";
reg = <0x00 0x04084000 0x00 0x88>;
#pinctrl-cells = <1>;
@@ -15,6 +16,7 @@
};
mcu_esm: esm@4100000 {
+ bootph-pre-ram;
compatible = "ti,j721e-esm";
reg = <0x00 0x4100000 0x00 0x1000>;
ti,esm-pins = <0>, <1>, <2>, <85>;
diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin-wifi.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-wifi.dtsi
index 90ddc71bcd30..a6808b10c7b2 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-verdin-wifi.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-wifi.dtsi
@@ -35,5 +35,11 @@
&main_uart5 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart5>;
+ uart-has-rtscts;
status = "okay";
+
+ bluetooth {
+ compatible = "nxp,88w8987-bt";
+ fw-init-baudrate = <3000000>;
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
index 40992e7e4c30..5db52f237253 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
@@ -1061,6 +1061,7 @@
vddc-supply = <&reg_1v2_dsi>;
vddmipi-supply = <&reg_1v2_dsi>;
vddio-supply = <&reg_1v8_dsi>;
+ status = "disabled";
dsi_bridge_ports: ports {
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
index eae052887186..fef76f52a52e 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
@@ -7,6 +7,7 @@
&cbass_wakeup {
wkup_conf: syscon@43000000 {
+ bootph-all;
compatible = "syscon", "simple-mfd";
reg = <0x00 0x43000000 0x00 0x20000>;
#address-cells = <1>;
@@ -14,6 +15,7 @@
ranges = <0x0 0x00 0x43000000 0x20000>;
chipid: chipid@14 {
+ bootph-all;
compatible = "ti,am654-chipid";
reg = <0x14 0x4>;
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62.dtsi b/arch/arm64/boot/dts/ti/k3-am62.dtsi
index 11f14eef2d44..f1e15206e1ce 100644
--- a/arch/arm64/boot/dts/ti/k3-am62.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62.dtsi
@@ -47,6 +47,7 @@
};
cbass_main: bus@f0000 {
+ bootph-all;
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
@@ -86,6 +87,7 @@
<0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>;
cbass_mcu: bus@4000000 {
+ bootph-all;
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
@@ -93,6 +95,7 @@
};
cbass_wakeup: bus@b00000 {
+ bootph-all;
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
diff --git a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
index 7cfdf562b53b..9a6bd0a3c94f 100644
--- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
+++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
@@ -46,6 +46,7 @@
};
memory@80000000 {
+ bootph-pre-ram;
device_type = "memory";
/* 2G RAM */
reg = <0x00000000 0x80000000 0x00000000 0x80000000>;
@@ -58,7 +59,7 @@
ramoops: ramoops@9ca00000 {
compatible = "ramoops";
- reg = <0x00 0x9c700000 0x00 0x00100000>;
+ reg = <0x00 0x9ca00000 0x00 0x00100000>;
record-size = <0x8000>;
console-size = <0x8000>;
ftrace-size = <0x00>;
@@ -83,6 +84,7 @@
};
vsys_5v0: regulator-1 {
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "vsys_5v0";
regulator-min-microvolt = <5000000>;
@@ -93,6 +95,7 @@
vdd_3v3: regulator-2 {
/* output of TLV62595DMQR-U12 */
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "vdd_3v3";
regulator-min-microvolt = <3300000>;
@@ -118,6 +121,7 @@
vdd_3v3_sd: regulator-4 {
/* output of TPS22918DBVR-U21 */
+ bootph-all;
pinctrl-names = "default";
pinctrl-0 = <&vdd_3v3_sd_pins_default>;
@@ -132,6 +136,7 @@
};
vdd_sd_dv: regulator-5 {
+ bootph-all;
compatible = "regulator-gpio";
regulator-name = "sd_hs200_switch";
pinctrl-names = "default";
@@ -146,9 +151,11 @@
};
leds {
+ bootph-all;
compatible = "gpio-leds";
led-0 {
+ bootph-all;
gpios = <&main_gpio0 3 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
function = LED_FUNCTION_HEARTBEAT;
@@ -156,6 +163,7 @@
};
led-1 {
+ bootph-all;
gpios = <&main_gpio0 4 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "disk-activity";
function = LED_FUNCTION_DISK_ACTIVITY;
@@ -163,16 +171,19 @@
};
led-2 {
+ bootph-all;
gpios = <&main_gpio0 5 GPIO_ACTIVE_HIGH>;
function = LED_FUNCTION_CPU;
};
led-3 {
+ bootph-all;
gpios = <&main_gpio0 6 GPIO_ACTIVE_HIGH>;
function = LED_FUNCTION_LAN;
};
led-4 {
+ bootph-all;
gpios = <&main_gpio0 9 GPIO_ACTIVE_HIGH>;
function = LED_FUNCTION_WLAN;
};
@@ -245,6 +256,7 @@
&main_pmx0 {
gpio0_pins_default: gpio0-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x0004, PIN_INPUT, 7) /* (G25) OSPI0_LBCLKO.GPIO0_1 */
AM62X_IOPAD(0x0008, PIN_INPUT, 7) /* (J24) OSPI0_DQS.GPIO0_2 */
@@ -264,6 +276,7 @@
};
vdd_sd_dv_pins_default: vdd-sd-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x0244, PIN_OUTPUT, 7) /* (C17) MMC1_SDWP.GPIO1_49 */
>;
@@ -283,6 +296,7 @@
};
local_i2c_pins_default: local-i2c-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x01e0, PIN_INPUT_PULLUP, 0) /* (B16) I2C0_SCL */
AM62X_IOPAD(0x01e4, PIN_INPUT_PULLUP, 0) /* (A16) I2C0_SDA */
@@ -321,6 +335,7 @@
};
emmc_pins_default: emmc-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x0220, PIN_INPUT, 0) /* (Y3) MMC0_CMD */
AM62X_IOPAD(0x0218, PIN_INPUT, 0) /* (AB1) MMC0_CLK */
@@ -336,12 +351,14 @@
};
vdd_3v3_sd_pins_default: vdd-3v3-sd-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x01c4, PIN_INPUT, 7) /* (B14) SPI0_D1_GPIO1_19 */
>;
};
sd_pins_default: sd-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x023c, PIN_INPUT, 0) /* (A21) MMC1_CMD */
AM62X_IOPAD(0x0234, PIN_INPUT, 0) /* (B22) MMC1_CLK */
@@ -418,6 +435,7 @@
};
mikrobus_gpio_pins_default: mikrobus-gpio-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x019c, PIN_INPUT, 7) /* (B18) MCASP0_AXR1.GPIO1_9 */
AM62X_IOPAD(0x01a0, PIN_INPUT, 7) /* (E18) MCASP0_AXR0.GPIO1_10 */
@@ -426,6 +444,7 @@
};
console_pins_default: console-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x01c8, PIN_INPUT, 0) /* (D14) UART0_RXD */
AM62X_IOPAD(0x01cc, PIN_OUTPUT, 0) /* (E14) UART0_TXD */
@@ -597,6 +616,7 @@
};
&main_gpio0 {
+ bootph-all;
pinctrl-names = "default";
pinctrl-0 = <&gpio0_pins_default>;
gpio-line-names = "BL_EN_3V3", "SPE_PO_EN", "RTC_INT", /* 0-2 */
@@ -616,6 +636,7 @@
};
&main_gpio1 {
+ bootph-all;
pinctrl-names = "default";
pinctrl-0 = <&mikrobus_gpio_pins_default>;
gpio-line-names = "", "", "", "", "", /* 0-4 */
@@ -633,6 +654,7 @@
};
&main_i2c0 {
+ bootph-all;
pinctrl-names = "default";
pinctrl-0 = <&local_i2c_pins_default>;
clock-frequency = <400000>;
@@ -651,6 +673,7 @@
};
tps65219: pmic@30 {
+ bootph-all;
compatible = "ti,tps65219";
reg = <0x30>;
buck1-supply = <&vsys_5v0>;
@@ -801,6 +824,7 @@
};
&sdhci0 {
+ bootph-all;
pinctrl-names = "default";
pinctrl-0 = <&emmc_pins_default>;
ti,driver-strength-ohm = <50>;
@@ -810,6 +834,7 @@
&sdhci1 {
/* SD/MMC */
+ bootph-all;
pinctrl-names = "default";
pinctrl-0 = <&sd_pins_default>;
@@ -850,6 +875,7 @@
};
&main_uart0 {
+ bootph-all;
pinctrl-names = "default";
pinctrl-0 = <&console_pins_default>;
status = "okay";
@@ -870,6 +896,12 @@
pinctrl-names = "default";
pinctrl-0 = <&wifi_debug_uart_pins_default>;
status = "okay";
+
+ mcu {
+ compatible = "ti,cc1352p7";
+ reset-gpios = <&main_gpio0 72 GPIO_ACTIVE_LOW>;
+ vdds-supply = <&vdd_3v3>;
+ };
};
&dss {
diff --git a/arch/arm64/boot/dts/ti/k3-am625-sk.dts b/arch/arm64/boot/dts/ti/k3-am625-sk.dts
index 7c98c1b855d1..b18092497c9a 100644
--- a/arch/arm64/boot/dts/ti/k3-am625-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am625-sk.dts
@@ -31,6 +31,7 @@
vmain_pd: regulator-0 {
/* TPS65988 PD CONTROLLER OUTPUT */
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "vmain_pd";
regulator-min-microvolt = <5000000>;
@@ -41,6 +42,7 @@
vcc_5v0: regulator-1 {
/* Output of LM34936 */
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "vcc_5v0";
regulator-min-microvolt = <5000000>;
@@ -52,6 +54,7 @@
vcc_3v3_sys: regulator-2 {
/* output of LM61460-Q1 */
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "vcc_3v3_sys";
regulator-min-microvolt = <3300000>;
@@ -63,6 +66,7 @@
vdd_mmc1: regulator-3 {
/* TPS22918DBVR */
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "vdd_mmc1";
regulator-min-microvolt = <3300000>;
@@ -75,6 +79,7 @@
vdd_sd_dv: regulator-4 {
/* Output of TLV71033 */
+ bootph-all;
compatible = "regulator-gpio";
regulator-name = "tlv71033";
pinctrl-names = "default";
@@ -102,6 +107,7 @@
&main_pmx0 {
main_rgmii2_pins_default: main-rgmii2-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x184, PIN_INPUT, 0) /* (AE23) RGMII2_RD0 */
AM62X_IOPAD(0x188, PIN_INPUT, 0) /* (AB20) RGMII2_RD1 */
@@ -119,6 +125,7 @@
};
ospi0_pins_default: ospi0-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x000, PIN_OUTPUT, 0) /* (H24) OSPI0_CLK */
AM62X_IOPAD(0x02c, PIN_OUTPUT, 0) /* (F23) OSPI0_CSn0 */
@@ -135,20 +142,32 @@
};
vdd_sd_dv_pins_default: vdd-sd-dv-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x07c, PIN_OUTPUT, 7) /* (P25) GPMC0_CLK.GPIO0_31 */
>;
};
main_gpio1_ioexp_intr_pins_default: main-gpio1-ioexp-intr-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x01d4, PIN_INPUT, 7) /* (B15) UART0_RTSn.GPIO1_23 */
>;
};
};
+&main_gpio0 {
+ bootph-all;
+};
+
+&main_gpio1 {
+ bootph-all;
+};
+
&main_i2c1 {
+ bootph-all;
exp1: gpio@22 {
+ bootph-all;
compatible = "ti,tca6424";
reg = <0x22>;
gpio-controller;
@@ -207,12 +226,18 @@
};
};
+&fss {
+ bootph-all;
+};
+
&ospi0 {
+ bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&ospi0_pins_default>;
flash@0 {
+ bootph-all;
compatible = "jedec,spi-nor";
reg = <0x0>;
spi-tx-bus-width = <8>;
@@ -225,6 +250,7 @@
cdns,read-delay = <4>;
partitions {
+ bootph-all;
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
@@ -260,6 +286,7 @@
};
partition@3fc0000 {
+ bootph-pre-ram;
label = "ospi.phypattern";
reg = <0x3fc0000 0x40000>;
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
index 3198af08fb9f..4ae7fdc5221b 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
@@ -816,4 +816,64 @@
clock-names = "fck";
status = "disabled";
};
+
+ mcasp0: audio-controller@2b00000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b00000 0x00 0x2000>,
+ <0x00 0x02b08000 0x00 0x400>;
+ reg-names = "mpu", "dat";
+ interrupts = <GIC_SPI 236 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+
+ dmas = <&main_bcdma 0 0xc500 0>, <&main_bcdma 0 0x4500 0>;
+ dma-names = "tx", "rx";
+
+ clocks = <&k3_clks 190 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 190 0>;
+ assigned-clock-parents = <&k3_clks 190 2>;
+ power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ mcasp1: audio-controller@2b10000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b10000 0x00 0x2000>,
+ <0x00 0x02b18000 0x00 0x400>;
+ reg-names = "mpu", "dat";
+ interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+
+ dmas = <&main_bcdma 0 0xc501 0>, <&main_bcdma 0 0x4501 0>;
+ dma-names = "tx", "rx";
+
+ clocks = <&k3_clks 191 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 191 0>;
+ assigned-clock-parents = <&k3_clks 191 2>;
+ power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ mcasp2: audio-controller@2b20000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b20000 0x00 0x2000>,
+ <0x00 0x02b28000 0x00 0x400>;
+ reg-names = "mpu", "dat";
+ interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+
+ dmas = <&main_bcdma 0 0xc502 0>, <&main_bcdma 0 0x4502 0>;
+ dma-names = "tx", "rx";
+
+ clocks = <&k3_clks 192 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 192 0>;
+ assigned-clock-parents = <&k3_clks 192 2>;
+ power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
index cff283c75f8e..8f64ac2c7568 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
@@ -79,10 +79,10 @@
regulator-boot-on;
};
- vcc_3v3_sys: regulator-2 {
+ vcc_3v3_main: regulator-2 {
/* output of LM5141-Q1 */
compatible = "regulator-fixed";
- regulator-name = "vcc_3v3_sys";
+ regulator-name = "vcc_3v3_main";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
vin-supply = <&vmain_pd>;
@@ -101,6 +101,17 @@
gpio = <&exp1 3 GPIO_ACTIVE_HIGH>;
};
+ vcc_3v3_sys: regulator-4 {
+ /* output of TPS222965DSGT */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_sys";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_3v3_main>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -114,6 +125,41 @@
default-state = "off";
};
};
+
+ tlv320_mclk: clk-0 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <12288000>;
+ };
+
+ codec_audio: sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "AM62Ax-SKEVM";
+ simple-audio-card,widgets =
+ "Headphone", "Headphone Jack",
+ "Line", "Line In",
+ "Microphone", "Microphone Jack";
+ simple-audio-card,routing =
+ "Headphone Jack", "HPLOUT",
+ "Headphone Jack", "HPROUT",
+ "LINE1L", "Line In",
+ "LINE1R", "Line In",
+ "MIC3R", "Microphone Jack",
+ "Microphone Jack", "Mic Bias";
+ simple-audio-card,format = "dsp_b";
+ simple-audio-card,bitclock-master = <&sound_master>;
+ simple-audio-card,frame-master = <&sound_master>;
+ simple-audio-card,bitclock-inversion;
+
+ simple-audio-card,cpu {
+ sound-dai = <&mcasp1>;
+ };
+
+ sound_master: simple-audio-card,codec {
+ sound-dai = <&tlv320aic3106>;
+ clocks = <&tlv320_mclk>;
+ };
+ };
};
&mcu_pmx0 {
@@ -219,6 +265,29 @@
AM62AX_IOPAD(0x12c, PIN_INPUT, 0) /* (W16) RGMII1_TX_CTL */
>;
};
+
+ main_mcasp1_pins_default: main-mcasp1-default-pins {
+ pinctrl-single,pins = <
+ AM62AX_IOPAD(0x090, PIN_INPUT, 2) /* (L19) GPMC0_BE0n_CLE.MCASP1_ACLKX */
+ AM62AX_IOPAD(0x098, PIN_INPUT, 2) /* (R18) GPMC0_WAIT0.MCASP1_AFSX */
+ AM62AX_IOPAD(0x08c, PIN_OUTPUT, 2) /* (K19) GPMC0_WEn.MCASP1_AXR0 */
+ AM62AX_IOPAD(0x084, PIN_INPUT, 2) /* (L18) GPMC0_ADVn_ALE.MCASP1_AXR2 */
+ >;
+ };
+};
+
+&mcu_pmx0 {
+ status = "okay";
+
+ pmic_irq_pins_default: pmic-irq-default-pins {
+ pinctrl-single,pins = <
+ AM62AX_MCU_IOPAD(0x000, PIN_INPUT, 7) /* (E11) MCU_GPIO0_0 */
+ >;
+ };
+};
+
+&mcu_gpio0 {
+ status = "okay";
};
&main_i2c0 {
@@ -244,13 +313,94 @@
};
};
};
+
+ tps659312: pmic@48 {
+ compatible = "ti,tps6593-q1";
+ reg = <0x48>;
+ ti,primary-pmic;
+ system-power-controller;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_irq_pins_default>;
+ interrupt-parent = <&mcu_gpio0>;
+ interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+
+ buck123-supply = <&vcc_3v3_sys>;
+ buck4-supply = <&vcc_3v3_sys>;
+ buck5-supply = <&vcc_3v3_sys>;
+ ldo1-supply = <&vcc_3v3_sys>;
+ ldo2-supply = <&vcc_3v3_sys>;
+ ldo3-supply = <&buck5>;
+ ldo4-supply = <&vcc_3v3_sys>;
+
+ regulators {
+ buck123: buck123 {
+ regulator-name = "vcc_core";
+ regulator-min-microvolt = <715000>;
+ regulator-max-microvolt = <895000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck4: buck4 {
+ regulator-name = "vcc_1v1";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck5: buck5 {
+ regulator-name = "vcc_1v8_sys";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1: ldo1 {
+ regulator-name = "vddshv5_sdio";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo2: ldo2 {
+ regulator-name = "vpp_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo3: ldo3 {
+ regulator-name = "vcc_0v85";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo4: ldo4 {
+ regulator-name = "vdda_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
};
&main_i2c1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c1_pins_default>;
- clock-frequency = <400000>;
+ clock-frequency = <100000>;
exp1: gpio@22 {
compatible = "ti,tca6424";
@@ -271,6 +421,19 @@
"MCASP1_FET_SEL", "UART1_FET_SEL",
"PD_I2C_IRQ", "IO_EXP_TEST_LED";
};
+
+ tlv320aic3106: audio-codec@1b {
+ #sound-dai-cells = <0>;
+ compatible = "ti,tlv320aic3106";
+ reg = <0x1b>;
+ ai3x-micbias-vg = <1>; /* 2.0V */
+
+ /* Regulators */
+ AVDD-supply = <&vcc_3v3_sys>;
+ IOVDD-supply = <&vcc_3v3_sys>;
+ DRVDD-supply = <&vcc_3v3_sys>;
+ DVDD-supply = <&buck5>;
+ };
};
&sdhci1 {
@@ -361,3 +524,23 @@
ti,min-output-impedance;
};
};
+
+&mcasp1 {
+ status = "okay";
+ #sound-dai-cells = <0>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcasp1_pins_default>;
+
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+
+ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+ 1 0 2 0
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ >;
+ tx-num-evt = <32>;
+ rx-num-evt = <32>;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi
index c24ff905437f..963758c7d377 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi
@@ -40,18 +40,37 @@
};
};
+ main_conf: bus@100000 {
+ compatible = "simple-bus";
+ reg = <0x00 0x00100000 0x00 0x20000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x00 0x00 0x00100000 0x20000>;
+
+ phy_gmii_sel: phy@4044 {
+ compatible = "ti,am654-phy-gmii-sel";
+ reg = <0x4044 0x8>;
+ #phy-cells = <1>;
+ };
+
+ epwm_tbclk: clock-controller@4130 {
+ compatible = "ti,am62-epwm-tbclk";
+ reg = <0x4130 0x4>;
+ #clock-cells = <1>;
+ };
+ };
+
dmss: bus@48000000 {
- bootph-all;
- compatible = "simple-mfd";
+ compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
dma-ranges;
ranges = <0x00 0x48000000 0x00 0x48000000 0x00 0x06400000>;
+ bootph-all;
ti,sci-dev-id = <25>;
secure_proxy_main: mailbox@4d000000 {
- bootph-all;
compatible = "ti,am654-secure-proxy";
#mbox-cells = <1>;
reg-names = "target_data", "rt", "scfg";
@@ -60,11 +79,76 @@
<0x00 0x4a400000 0x00 0x80000>;
interrupt-names = "rx_012";
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ bootph-all;
+ };
+
+ inta_main_dmss: interrupt-controller@48000000 {
+ compatible = "ti,sci-inta";
+ reg = <0x00 0x48000000 0x00 0x100000>;
+ #interrupt-cells = <0>;
+ interrupt-controller;
+ interrupt-parent = <&gic500>;
+ msi-controller;
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <28>;
+ ti,interrupt-ranges = <5 69 35>;
+ ti,unmapped-event-sources = <&main_bcdma>, <&main_pktdma>;
+ };
+
+ main_bcdma: dma-controller@485c0100 {
+ compatible = "ti,am64-dmss-bcdma";
+ reg = <0x00 0x485c0100 0x00 0x100>,
+ <0x00 0x4c000000 0x00 0x20000>,
+ <0x00 0x4a820000 0x00 0x20000>,
+ <0x00 0x4aa40000 0x00 0x20000>,
+ <0x00 0x4bc00000 0x00 0x100000>;
+ reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt";
+ msi-parent = <&inta_main_dmss>;
+ #dma-cells = <3>;
+
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <26>;
+ ti,sci-rm-range-bchan = <0x20>; /* BLOCK_COPY_CHAN */
+ ti,sci-rm-range-rchan = <0x21>; /* SPLIT_TR_RX_CHAN */
+ ti,sci-rm-range-tchan = <0x22>; /* SPLIT_TR_TX_CHAN */
+ bootph-all;
+ };
+
+ main_pktdma: dma-controller@485c0000 {
+ compatible = "ti,am64-dmss-pktdma";
+ reg = <0x00 0x485c0000 0x00 0x100>,
+ <0x00 0x4a800000 0x00 0x20000>,
+ <0x00 0x4aa00000 0x00 0x40000>,
+ <0x00 0x4b800000 0x00 0x400000>;
+ reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt";
+ msi-parent = <&inta_main_dmss>;
+ #dma-cells = <2>;
+ bootph-all;
+
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <30>;
+ ti,sci-rm-range-tchan = <0x23>, /* UNMAPPED_TX_CHAN */
+ <0x24>, /* CPSW_TX_CHAN */
+ <0x25>, /* SAUL_TX_0_CHAN */
+ <0x26>; /* SAUL_TX_1_CHAN */
+ ti,sci-rm-range-tflow = <0x10>, /* RING_UNMAPPED_TX_CHAN */
+ <0x11>, /* RING_CPSW_TX_CHAN */
+ <0x12>, /* RING_SAUL_TX_0_CHAN */
+ <0x13>; /* RING_SAUL_TX_1_CHAN */
+ ti,sci-rm-range-rchan = <0x29>, /* UNMAPPED_RX_CHAN */
+ <0x2b>, /* CPSW_RX_CHAN */
+ <0x2d>, /* SAUL_RX_0_CHAN */
+ <0x2f>, /* SAUL_RX_1_CHAN */
+ <0x31>, /* SAUL_RX_2_CHAN */
+ <0x33>; /* SAUL_RX_3_CHAN */
+ ti,sci-rm-range-rflow = <0x2a>, /* FLOW_UNMAPPED_RX_CHAN */
+ <0x2c>, /* FLOW_CPSW_RX_CHAN */
+ <0x2e>, /* FLOW_SAUL_RX_0/1_CHAN */
+ <0x32>; /* FLOW_SAUL_RX_2/3_CHAN */
};
};
dmsc: system-controller@44043000 {
- bootph-all;
compatible = "ti,k2g-sci";
ti,host-id = <12>;
mbox-names = "rx", "tx";
@@ -72,37 +156,72 @@
<&secure_proxy_main 13>;
reg-names = "debug_messages";
reg = <0x00 0x44043000 0x00 0xfe0>;
+ bootph-all;
k3_pds: power-controller {
- bootph-all;
compatible = "ti,sci-pm-domain";
#power-domain-cells = <2>;
+ bootph-all;
};
k3_clks: clock-controller {
- bootph-all;
compatible = "ti,k2g-sci-clk";
#clock-cells = <2>;
+ bootph-all;
};
k3_reset: reset-controller {
- bootph-all;
compatible = "ti,sci-reset";
#reset-cells = <2>;
+ bootph-all;
};
};
- main_pmx0: pinctrl@f4000 {
+ crypto: crypto@40900000 {
+ compatible = "ti,am62-sa3ul";
+ reg = <0x00 0x40900000 0x00 0x1200>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x00 0x40900000 0x00 0x40900000 0x00 0x30000>;
+
+ dmas = <&main_pktdma 0xf501 0>, <&main_pktdma 0x7506 0>,
+ <&main_pktdma 0x7507 0>;
+ dma-names = "tx", "rx1", "rx2";
+ };
+
+ secure_proxy_sa3: mailbox@43600000 {
+ compatible = "ti,am654-secure-proxy";
+ #mbox-cells = <1>;
+ reg-names = "target_data", "rt", "scfg";
+ reg = <0x00 0x43600000 0x00 0x10000>,
+ <0x00 0x44880000 0x00 0x20000>,
+ <0x00 0x44860000 0x00 0x20000>;
+ /*
+ * Marked Disabled:
+ * Node is incomplete as it is meant for bootloaders and
+ * firmware on non-MPU processors
+ */
+ status = "disabled";
bootph-all;
+ };
+
+ main_pmx0: pinctrl@f4000 {
compatible = "pinctrl-single";
reg = <0x00 0xf4000 0x00 0x2ac>;
#pinctrl-cells = <1>;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0xffffffff>;
+ bootph-all;
+ };
+
+ main_esm: esm@420000 {
+ compatible = "ti,j721e-esm";
+ reg = <0x00 0x420000 0x00 0x1000>;
+ ti,esm-pins = <160>, <161>, <162>, <163>, <177>, <178>;
+ bootph-pre-ram;
};
main_timer0: timer@2400000 {
- bootph-all;
compatible = "ti,am654-timer";
reg = <0x00 0x2400000 0x00 0x400>;
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
@@ -112,6 +231,91 @@
assigned-clock-parents = <&k3_clks 36 3>;
power-domains = <&k3_pds 36 TI_SCI_PD_EXCLUSIVE>;
ti,timer-pwm;
+ bootph-all;
+ };
+
+ main_timer1: timer@2410000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2410000 0x00 0x400>;
+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 37 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 37 2>;
+ assigned-clock-parents = <&k3_clks 37 3>;
+ power-domains = <&k3_pds 37 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer2: timer@2420000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2420000 0x00 0x400>;
+ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 38 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 38 2>;
+ assigned-clock-parents = <&k3_clks 38 3>;
+ power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer3: timer@2430000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2430000 0x00 0x400>;
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 39 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 39 2>;
+ assigned-clock-parents = <&k3_clks 39 3>;
+ power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer4: timer@2440000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2440000 0x00 0x400>;
+ interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 40 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 40 2>;
+ assigned-clock-parents = <&k3_clks 40 3>;
+ power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer5: timer@2450000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2450000 0x00 0x400>;
+ interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 41 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 41 2>;
+ assigned-clock-parents = <&k3_clks 41 3>;
+ power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer6: timer@2460000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2460000 0x00 0x400>;
+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 42 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 42 2>;
+ assigned-clock-parents = <&k3_clks 42 3>;
+ power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer7: timer@2470000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2470000 0x00 0x400>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 43 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 43 2>;
+ assigned-clock-parents = <&k3_clks 43 3>;
+ power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
};
main_uart0: serial@2800000 {
@@ -133,4 +337,548 @@
clock-names = "fclk";
status = "disabled";
};
+
+ main_uart2: serial@2820000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x02820000 0x00 0x100>;
+ interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 153 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ main_uart3: serial@2830000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x02830000 0x00 0x100>;
+ interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 154 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ main_uart4: serial@2840000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x02840000 0x00 0x100>;
+ interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 155 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 155 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ main_uart5: serial@2850000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x02850000 0x00 0x100>;
+ interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 156 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 156 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ main_uart6: serial@2860000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x02860000 0x00 0x100>;
+ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 158 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 158 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ main_i2c0: i2c@20000000 {
+ compatible = "ti,am64-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x20000000 0x00 0x100>;
+ interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 102 2>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ main_i2c1: i2c@20010000 {
+ compatible = "ti,am64-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x20010000 0x00 0x100>;
+ interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 103 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 103 2>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ main_i2c2: i2c@20020000 {
+ compatible = "ti,am64-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x20020000 0x00 0x100>;
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 104 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 104 2>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ main_i2c3: i2c@20030000 {
+ compatible = "ti,am64-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x20030000 0x00 0x100>;
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 105 2>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ main_spi0: spi@20100000 {
+ compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+ reg = <0x00 0x20100000 0x00 0x400>;
+ interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 141 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 141 0>;
+ status = "disabled";
+ };
+
+ main_spi1: spi@20110000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x20110000 0x00 0x400>;
+ interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 142 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 142 0>;
+ status = "disabled";
+ };
+
+ main_spi2: spi@20120000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x20120000 0x00 0x400>;
+ interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 143 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 143 0>;
+ status = "disabled";
+ };
+
+ main_gpio_intr: interrupt-controller@a00000 {
+ compatible = "ti,sci-intr";
+ reg = <0x00 0x00a00000 0x00 0x800>;
+ ti,intr-trigger-type = <1>;
+ interrupt-controller;
+ interrupt-parent = <&gic500>;
+ #interrupt-cells = <1>;
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <3>;
+ ti,interrupt-ranges = <0 32 16>;
+ };
+
+ main_gpio0: gpio@600000 {
+ compatible = "ti,am64-gpio", "ti,keystone-gpio";
+ reg = <0x00 0x00600000 0x00 0x100>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&main_gpio_intr>;
+ interrupts = <190>, <191>, <192>,
+ <193>, <194>, <195>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ ti,ngpio = <92>;
+ ti,davinci-gpio-unbanked = <0>;
+ power-domains = <&k3_pds 77 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 77 0>;
+ clock-names = "gpio";
+ };
+
+ main_gpio1: gpio@601000 {
+ compatible = "ti,am64-gpio", "ti,keystone-gpio";
+ reg = <0x00 0x00601000 0x00 0x100>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&main_gpio_intr>;
+ interrupts = <180>, <181>, <182>,
+ <183>, <184>, <185>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ ti,ngpio = <52>;
+ ti,davinci-gpio-unbanked = <0>;
+ power-domains = <&k3_pds 78 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 78 0>;
+ clock-names = "gpio";
+ };
+
+ sdhci0: mmc@fa10000 {
+ compatible = "ti,am64-sdhci-8bit";
+ reg = <0x00 0x0fa10000 0x00 0x1000>, <0x00 0x0fa18000 0x00 0x400>;
+ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 57 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 57 1>, <&k3_clks 57 2>;
+ clock-names = "clk_ahb", "clk_xin";
+ assigned-clocks = <&k3_clks 57 2>;
+ assigned-clock-parents = <&k3_clks 57 4>;
+ ti,otap-del-sel-legacy = <0x0>;
+ status = "disabled";
+ };
+
+ sdhci1: mmc@fa00000 {
+ compatible = "ti,am62-sdhci";
+ reg = <0x00 0x0fa00000 0x00 0x1000>, <0x00 0x0fa08000 0x00 0x400>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 58 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 58 5>, <&k3_clks 58 6>;
+ clock-names = "clk_ahb", "clk_xin";
+ ti,otap-del-sel-legacy = <0x8>;
+ status = "disabled";
+ };
+
+ sdhci2: mmc@fa20000 {
+ compatible = "ti,am62-sdhci";
+ reg = <0x00 0x0fa20000 0x00 0x1000>, <0x00 0x0fa28000 0x00 0x400>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 184 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 184 5>, <&k3_clks 184 6>;
+ clock-names = "clk_ahb", "clk_xin";
+ ti,otap-del-sel-legacy = <0x8>;
+ status = "disabled";
+ };
+
+ fss: bus@fc00000 {
+ compatible = "simple-bus";
+ reg = <0x00 0x0fc00000 0x00 0x70000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ospi0: spi@fc40000 {
+ compatible = "ti,am654-ospi", "cdns,qspi-nor";
+ reg = <0x00 0x0fc40000 0x00 0x100>,
+ <0x05 0x00000000 0x01 0x00000000>;
+ interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
+ cdns,fifo-depth = <256>;
+ cdns,fifo-width = <4>;
+ cdns,trigger-address = <0x0>;
+ clocks = <&k3_clks 75 7>;
+ assigned-clocks = <&k3_clks 75 7>;
+ assigned-clock-parents = <&k3_clks 75 8>;
+ assigned-clock-rates = <166666666>;
+ power-domains = <&k3_pds 75 TI_SCI_PD_EXCLUSIVE>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ };
+
+ cpsw3g: ethernet@8000000 {
+ compatible = "ti,am642-cpsw-nuss";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ reg = <0x00 0x08000000 0x00 0x200000>;
+ reg-names = "cpsw_nuss";
+ ranges = <0x00 0x00 0x00 0x08000000 0x00 0x200000>;
+ clocks = <&k3_clks 13 0>;
+ assigned-clocks = <&k3_clks 13 3>;
+ assigned-clock-parents = <&k3_clks 13 11>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 13 TI_SCI_PD_EXCLUSIVE>;
+
+ dmas = <&main_pktdma 0xc600 15>,
+ <&main_pktdma 0xc601 15>,
+ <&main_pktdma 0xc602 15>,
+ <&main_pktdma 0xc603 15>,
+ <&main_pktdma 0xc604 15>,
+ <&main_pktdma 0xc605 15>,
+ <&main_pktdma 0xc606 15>,
+ <&main_pktdma 0xc607 15>,
+ <&main_pktdma 0x4600 15>;
+ dma-names = "tx0", "tx1", "tx2", "tx3", "tx4", "tx5", "tx6",
+ "tx7", "rx";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpsw_port1: port@1 {
+ reg = <1>;
+ ti,mac-only;
+ label = "port1";
+ phys = <&phy_gmii_sel 1>;
+ mac-address = [00 00 00 00 00 00];
+ };
+
+ cpsw_port2: port@2 {
+ reg = <2>;
+ ti,mac-only;
+ label = "port2";
+ phys = <&phy_gmii_sel 2>;
+ mac-address = [00 00 00 00 00 00];
+ };
+ };
+
+ cpsw3g_mdio: mdio@f00 {
+ compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+ reg = <0x00 0xf00 0x00 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 13 0>;
+ clock-names = "fck";
+ bus_freq = <1000000>;
+ status = "disabled";
+ };
+
+ cpts@3d000 {
+ compatible = "ti,j721e-cpts";
+ reg = <0x00 0x3d000 0x00 0x400>;
+ clocks = <&k3_clks 13 3>;
+ clock-names = "cpts";
+ interrupts-extended = <&gic500 GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "cpts";
+ ti,cpts-ext-ts-inputs = <4>;
+ ti,cpts-periodic-outputs = <2>;
+ };
+ };
+
+ hwspinlock: spinlock@2a000000 {
+ compatible = "ti,am64-hwspinlock";
+ reg = <0x00 0x2a000000 0x00 0x1000>;
+ #hwlock-cells = <1>;
+ };
+
+ mailbox0_cluster0: mailbox@29000000 {
+ compatible = "ti,am64-mailbox";
+ reg = <0x00 0x29000000 0x00 0x200>;
+ interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ };
+
+ mailbox0_cluster1: mailbox@29010000 {
+ compatible = "ti,am64-mailbox";
+ reg = <0x00 0x29010000 0x00 0x200>;
+ interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ };
+
+ mailbox0_cluster2: mailbox@29020000 {
+ compatible = "ti,am64-mailbox";
+ reg = <0x00 0x29020000 0x00 0x200>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ };
+
+ mailbox0_cluster3: mailbox@29030000 {
+ compatible = "ti,am64-mailbox";
+ reg = <0x00 0x29030000 0x00 0x200>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ };
+
+ ecap0: pwm@23100000 {
+ compatible = "ti,am3352-ecap";
+ #pwm-cells = <3>;
+ reg = <0x00 0x23100000 0x00 0x100>;
+ power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 51 0>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ ecap1: pwm@23110000 {
+ compatible = "ti,am3352-ecap";
+ #pwm-cells = <3>;
+ reg = <0x00 0x23110000 0x00 0x100>;
+ power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 52 0>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ ecap2: pwm@23120000 {
+ compatible = "ti,am3352-ecap";
+ #pwm-cells = <3>;
+ reg = <0x00 0x23120000 0x00 0x100>;
+ power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 53 0>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ main_mcan0: can@20701000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x20701000 0x00 0x200>,
+ <0x00 0x20708000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 98 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 98 6>, <&k3_clks 98 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan1: can@20711000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x20711000 0x00 0x200>,
+ <0x00 0x20718000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 99 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 99 6>, <&k3_clks 99 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_rti0: watchdog@e000000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x0e000000 0x00 0x100>;
+ clocks = <&k3_clks 125 0>;
+ power-domains = <&k3_pds 125 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 125 0>;
+ assigned-clock-parents = <&k3_clks 125 2>;
+ };
+
+ main_rti1: watchdog@e010000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x0e010000 0x00 0x100>;
+ clocks = <&k3_clks 126 0>;
+ power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 126 0>;
+ assigned-clock-parents = <&k3_clks 126 2>;
+ };
+
+ main_rti2: watchdog@e020000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x0e020000 0x00 0x100>;
+ clocks = <&k3_clks 127 0>;
+ power-domains = <&k3_pds 127 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 127 0>;
+ assigned-clock-parents = <&k3_clks 127 2>;
+ };
+
+ main_rti3: watchdog@e030000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x0e030000 0x00 0x100>;
+ clocks = <&k3_clks 128 0>;
+ power-domains = <&k3_pds 128 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 128 0>;
+ assigned-clock-parents = <&k3_clks 128 2>;
+ };
+
+ main_rti15: watchdog@e0f0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x0e0f0000 0x00 0x100>;
+ clocks = <&k3_clks 130 0>;
+ power-domains = <&k3_pds 130 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 130 0>;
+ assigned-clock-parents = <&k3_clks 130 2>;
+ };
+
+ epwm0: pwm@23000000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x00 0x23000000 0x00 0x100>;
+ power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 0>, <&k3_clks 86 0>;
+ clock-names = "tbclk", "fck";
+ status = "disabled";
+ };
+
+ epwm1: pwm@23010000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x00 0x23010000 0x00 0x100>;
+ power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 1>, <&k3_clks 87 0>;
+ clock-names = "tbclk", "fck";
+ status = "disabled";
+ };
+
+ epwm2: pwm@23020000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x00 0x23020000 0x00 0x100>;
+ power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 2>, <&k3_clks 88 0>;
+ clock-names = "tbclk", "fck";
+ status = "disabled";
+ };
+
+ mcasp0: audio-controller@2b00000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b00000 0x00 0x2000>,
+ <0x00 0x02b08000 0x00 0x400>;
+ reg-names = "mpu", "dat";
+ interrupts = <GIC_SPI 236 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+
+ dmas = <&main_bcdma 0 0xc500 0>, <&main_bcdma 0 0x4500 0>;
+ dma-names = "tx", "rx";
+
+ clocks = <&k3_clks 190 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 190 0>;
+ assigned-clock-parents = <&k3_clks 190 2>;
+ power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ mcasp1: audio-controller@2b10000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b10000 0x00 0x2000>,
+ <0x00 0x02b18000 0x00 0x400>;
+ reg-names = "mpu", "dat";
+ interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+
+ dmas = <&main_bcdma 0 0xc501 0>, <&main_bcdma 0 0x4501 0>;
+ dma-names = "tx", "rx";
+
+ clocks = <&k3_clks 191 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 191 0>;
+ assigned-clock-parents = <&k3_clks 191 2>;
+ power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ mcasp2: audio-controller@2b20000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b20000 0x00 0x2000>,
+ <0x00 0x02b28000 0x00 0x400>;
+ reg-names = "mpu", "dat";
+ interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+
+ dmas = <&main_bcdma 0 0xc502 0>, <&main_bcdma 0 0x4502 0>;
+ dma-names = "tx", "rx";
+
+ clocks = <&k3_clks 192 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 192 0>;
+ assigned-clock-parents = <&k3_clks 192 2>;
+ power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi
index 27ca1c9c6d13..c4b0b91d70cf 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi
@@ -11,5 +11,195 @@
#pinctrl-cells = <1>;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0xffffffff>;
+ bootph-all;
+ };
+
+ mcu_esm: esm@4100000 {
+ compatible = "ti,j721e-esm";
+ reg = <0x00 0x4100000 0x00 0x1000>;
+ ti,esm-pins = <0>, <1>, <2>, <85>;
+ status = "reserved";
+ bootph-pre-ram;
+ };
+
+ /*
+ * The MCU domain timer interrupts are routed only to the ESM module,
+ * and not currently available for Linux. The MCU domain timers are
+ * of limited use without interrupts, and likely reserved by the ESM.
+ */
+ mcu_timer0: timer@4800000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x4800000 0x00 0x400>;
+ clocks = <&k3_clks 35 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ status = "reserved";
+ };
+
+ mcu_timer1: timer@4810000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x4810000 0x00 0x400>;
+ clocks = <&k3_clks 48 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 48 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ status = "reserved";
+ };
+
+ mcu_timer2: timer@4820000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x4820000 0x00 0x400>;
+ clocks = <&k3_clks 49 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 49 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ status = "reserved";
+ };
+
+ mcu_timer3: timer@4830000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x4830000 0x00 0x400>;
+ clocks = <&k3_clks 50 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 50 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ status = "reserved";
+ };
+
+ mcu_uart0: serial@4a00000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x04a00000 0x00 0x100>;
+ interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 149 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ mcu_i2c0: i2c@4900000 {
+ compatible = "ti,am64-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x04900000 0x00 0x100>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 106 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 106 2>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ mcu_spi0: spi@4b00000 {
+ compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+ reg = <0x00 0x04b00000 0x00 0x400>;
+ interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 147 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 147 0>;
+ status = "disabled";
+ };
+
+ mcu_spi1: spi@4b10000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x04b10000 0x00 0x400>;
+ interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 148 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 148 0>;
+ status = "disabled";
+ };
+
+ mcu_gpio_intr: interrupt-controller@4210000 {
+ compatible = "ti,sci-intr";
+ reg = <0x00 0x04210000 0x00 0x200>;
+ ti,intr-trigger-type = <1>;
+ interrupt-controller;
+ interrupt-parent = <&gic500>;
+ #interrupt-cells = <1>;
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <5>;
+ ti,interrupt-ranges = <0 104 4>;
+ };
+
+ mcu_gpio0: gpio@4201000 {
+ compatible = "ti,am64-gpio", "ti,keystone-gpio";
+ reg = <0x00 0x4201000 0x00 0x100>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&mcu_gpio_intr>;
+ interrupts = <30>, <31>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ ti,ngpio = <24>;
+ ti,davinci-gpio-unbanked = <0>;
+ power-domains = <&k3_pds 79 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 79 0>;
+ clock-names = "gpio";
+ };
+
+ mcu_rti0: watchdog@4880000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x04880000 0x00 0x100>;
+ clocks = <&k3_clks 131 0>;
+ power-domains = <&k3_pds 131 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 131 0>;
+ assigned-clock-parents = <&k3_clks 131 2>;
+ /* Tightly coupled to M4F */
+ status = "reserved";
+ };
+
+ mcu_mcan0: can@4e08000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x4e08000 0x00 0x200>,
+ <0x00 0x4e00000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 188 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 188 6>, <&k3_clks 188 1>;
+ clock-names = "hclk", "cclk";
+ bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ status = "disabled";
+ };
+
+ mcu_mcan1: can@4e18000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x4e18000 0x00 0x200>,
+ <0x00 0x4e10000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 189 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 189 6>, <&k3_clks 189 1>;
+ clock-names = "hclk", "cclk";
+ bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ status = "disabled";
+ };
+
+ mcu_r5fss0: r5fss@79000000 {
+ compatible = "ti,am62-r5fss";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x79000000 0x00 0x79000000 0x8000>,
+ <0x79020000 0x00 0x79020000 0x8000>;
+ power-domains = <&k3_pds 7 TI_SCI_PD_EXCLUSIVE>;
+ mcu_r5fss0_core0: r5f@79000000 {
+ compatible = "ti,am62-r5f";
+ reg = <0x79000000 0x00008000>,
+ <0x79020000 0x00008000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <9>;
+ ti,sci-proc-ids = <0x03 0xff>;
+ resets = <&k3_reset 9 1>;
+ firmware-name = "am62p-mcu-r5f0_0-fw";
+ ti,atcm-enable = <0>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <0>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi
new file mode 100644
index 000000000000..85ce545633ea
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/thermal/thermal.h>
+
+thermal_zones: thermal-zones {
+ main0_thermal: main0-thermal {
+ polling-delay-passive = <250>; /* milliSeconds */
+ polling-delay = <500>; /* milliSeconds */
+ thermal-sensors = <&wkup_vtm0 0>;
+
+ trips {
+ main0_crit: main0-crit {
+ temperature = <125000>; /* milliCelsius */
+ hysteresis = <2000>; /* milliCelsius */
+ type = "critical";
+ };
+ };
+ };
+
+ main1_thermal: main1-thermal {
+ polling-delay-passive = <250>; /* milliSeconds */
+ polling-delay = <500>; /* milliSeconds */
+ thermal-sensors = <&wkup_vtm0 1>;
+
+ trips {
+ main1_crit: main1-crit {
+ temperature = <125000>; /* milliCelsius */
+ hysteresis = <2000>; /* milliCelsius */
+ type = "critical";
+ };
+ };
+ };
+
+ main2_thermal: main2-thermal {
+ polling-delay-passive = <250>; /* milliSeconds */
+ polling-delay = <500>; /* milliSeconds */
+ thermal-sensors = <&wkup_vtm0 2>;
+
+ trips {
+ main2_crit: main2-crit {
+ temperature = <125000>; /* milliCelsius */
+ hysteresis = <2000>; /* milliCelsius */
+ type = "critical";
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi
index aaf4b793b58e..19f42b39394e 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi
@@ -6,17 +6,17 @@
&cbass_wakeup {
wkup_conf: bus@43000000 {
- bootph-all;
compatible = "simple-bus";
reg = <0x00 0x43000000 0x00 0x20000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00 0x00 0x43000000 0x20000>;
+ bootph-all;
chipid: chipid@14 {
- bootph-all;
compatible = "ti,am654-chipid";
reg = <0x14 0x4>;
+ bootph-all;
};
};
@@ -29,4 +29,69 @@
clock-names = "fclk";
status = "disabled";
};
+
+ wkup_i2c0: i2c@2b200000 {
+ compatible = "ti,am64-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x2b200000 0x00 0x100>;
+ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 107 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 107 4>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ wkup_rtc0: rtc@2b1f0000 {
+ compatible = "ti,am62-rtc";
+ reg = <0x00 0x2b1f0000 0x00 0x100>;
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 117 6> , <&k3_clks 117 0>;
+ clock-names = "vbus", "osc32k";
+ power-domains = <&k3_pds 117 TI_SCI_PD_EXCLUSIVE>;
+ wakeup-source;
+ };
+
+ wkup_rti0: watchdog@2b000000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2b000000 0x00 0x100>;
+ clocks = <&k3_clks 132 0>;
+ power-domains = <&k3_pds 132 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 132 0>;
+ assigned-clock-parents = <&k3_clks 132 2>;
+ /* Used by DM firmware */
+ status = "reserved";
+ };
+
+ wkup_vtm0: temperature-sensor@b00000 {
+ compatible = "ti,j7200-vtm";
+ reg = <0x00 0xb00000 0x00 0x400>,
+ <0x00 0xb01000 0x00 0x400>;
+ power-domains = <&k3_pds 95 TI_SCI_PD_EXCLUSIVE>;
+ #thermal-sensor-cells = <1>;
+ };
+
+ wkup_r5fss0: r5fss@78000000 {
+ compatible = "ti,am62-r5fss";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x78000000 0x00 0x78000000 0x8000>,
+ <0x78100000 0x00 0x78100000 0x8000>;
+ power-domains = <&k3_pds 119 TI_SCI_PD_EXCLUSIVE>;
+
+ wkup_r5fss0_core0: r5f@78000000 {
+ compatible = "ti,am62-r5f";
+ reg = <0x78000000 0x00008000>,
+ <0x78100000 0x00008000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <121>;
+ ti,sci-proc-ids = <0x01 0xff>;
+ resets = <&k3_reset 121 1>;
+ firmware-name = "am62-wkup-r5f0_0-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62p.dtsi b/arch/arm64/boot/dts/ti/k3-am62p.dtsi
index 294ab73ec98b..84ffe7b9dcaf 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p.dtsi
@@ -45,10 +45,10 @@
};
cbass_main: bus@f0000 {
- bootph-all;
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
+ bootph-all;
ranges = <0x00 0x000f0000 0x00 0x000f0000 0x00 0x00030000>, /* Main MMRs */
<0x00 0x00420000 0x00 0x00420000 0x00 0x00001000>, /* ESM0 */
@@ -100,10 +100,10 @@
<0x00 0x79020000 0x00 0x79020000 0x00 0x00008000>, /* MCU R5 BTCM */
<0x00 0x79100000 0x00 0x79100000 0x00 0x00040000>, /* MCU IRAM0 */
<0x00 0x79140000 0x00 0x79140000 0x00 0x00040000>; /* MCU IRAM1 */
+ bootph-all;
};
cbass_wakeup: bus@b00000 {
- bootph-all;
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
@@ -112,8 +112,11 @@
<0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>, /* WKUP CTRL MMR */
<0x00 0x78000000 0x00 0x78000000 0x00 0x00008000>, /* DM R5 ATCM*/
<0x00 0x78100000 0x00 0x78100000 0x00 0x00008000>; /* DM R5 BTCM*/
+ bootph-all;
};
};
+
+ #include "k3-am62p-thermal.dtsi"
};
/* Now include peripherals for each bus segment */
diff --git a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
index 6fb17b17c95e..f377eadef0c1 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
@@ -8,6 +8,9 @@
/dts-v1/;
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
#include "k3-am62p5.dtsi"
/ {
@@ -18,6 +21,12 @@
serial0 = &wkup_uart0;
serial2 = &main_uart0;
serial3 = &main_uart1;
+ mmc0 = &sdhci0;
+ mmc1 = &sdhci1;
+ mmc2 = &sdhci2;
+ spi0 = &ospi0;
+ ethernet0 = &cpsw_port1;
+ ethernet1 = &cpsw_port2;
};
chosen {
@@ -29,6 +38,7 @@
reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
<0x00000008 0x80000000 0x00000001 0x80000000>;
device_type = "memory";
+ bootph-pre-ram;
};
reserved-memory {
@@ -52,35 +62,511 @@
no-map;
};
};
+
+ vmain_pd: regulator-0 {
+ /* TPS65988 PD CONTROLLER OUTPUT */
+ compatible = "regulator-fixed";
+ regulator-name = "vmain_pd";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ bootph-all;
+ };
+
+ vcc_5v0: regulator-1 {
+ /* Output of TPS630702RNMR */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vmain_pd>;
+ regulator-always-on;
+ regulator-boot-on;
+ bootph-all;
+ };
+
+ vdd_mmc1: regulator-2 {
+ /* TPS22918DBVR */
+ compatible = "regulator-fixed";
+ regulator-name = "vdd_mmc1";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ enable-active-high;
+ gpio = <&exp1 3 GPIO_ACTIVE_HIGH>;
+ bootph-all;
+ };
+
+ vddshv_sdio: regulator-3 {
+ compatible = "regulator-gpio";
+ regulator-name = "vddshv_sdio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&vddshv_sdio_pins_default>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ gpios = <&main_gpio0 31 GPIO_ACTIVE_HIGH>;
+ states = <1800000 0x0>,
+ <3300000 0x1>;
+ bootph-all;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usr_led_pins_default>;
+
+ led-0 {
+ label = "am62-sk:green:heartbeat";
+ gpios = <&main_gpio1 49 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ function = LED_FUNCTION_HEARTBEAT;
+ default-state = "off";
+ };
+ };
+
+ tlv320_mclk: clk-0 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <12288000>;
+ };
+
+ codec_audio: sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "AM62x-SKEVM";
+ simple-audio-card,widgets =
+ "Headphone", "Headphone Jack",
+ "Line", "Line In",
+ "Microphone", "Microphone Jack";
+ simple-audio-card,routing =
+ "Headphone Jack", "HPLOUT",
+ "Headphone Jack", "HPROUT",
+ "LINE1L", "Line In",
+ "LINE1R", "Line In",
+ "MIC3R", "Microphone Jack",
+ "Microphone Jack", "Mic Bias";
+ simple-audio-card,format = "dsp_b";
+ simple-audio-card,bitclock-master = <&sound_master>;
+ simple-audio-card,frame-master = <&sound_master>;
+ simple-audio-card,bitclock-inversion;
+
+ simple-audio-card,cpu {
+ sound-dai = <&mcasp1>;
+ };
+
+ sound_master: simple-audio-card,codec {
+ sound-dai = <&tlv320aic3106>;
+ clocks = <&tlv320_mclk>;
+ };
+ };
+};
+
+&main_gpio0 {
+ bootph-all;
+};
+
+&main_gpio1 {
+ bootph-all;
};
&main_pmx0 {
- main_uart0_pins_default: main-uart0-default-pins {
+ bootph-all;
+
+ main_i2c0_pins_default: main-i2c0-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x01e0, PIN_INPUT_PULLUP, 0) /* (B25) I2C0_SCL */
+ AM62PX_IOPAD(0x01e4, PIN_INPUT_PULLUP, 0) /* (A24) I2C0_SDA */
+ >;
+ };
+
+ main_i2c1_pins_default: main-i2c1-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x01e8, PIN_INPUT_PULLUP, 0) /* (C24) I2C1_SCL */
+ AM62PX_IOPAD(0x01ec, PIN_INPUT_PULLUP, 0) /* (B24) I2C1_SDA */
+ >;
bootph-all;
+ };
+
+ main_i2c2_pins_default: main-i2c2-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x00b0, PIN_INPUT_PULLUP, 1) /* (T22) GPMC0_CSn2.I2C2_SCL */
+ AM62PX_IOPAD(0x00b4, PIN_INPUT_PULLUP, 1) /* (U25) GPMC0_CSn3.I2C2_SDA */
+ >;
+ };
+
+ main_gpio1_ioexp_intr_pins_default: main-gpio1-ioexp-intr-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x01d4, PIN_INPUT, 7) /* (C22) UART0_RTSn.GPIO1_23 */
+ >;
+ };
+
+ main_mcasp1_pins_default: main-mcasp1-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x0090, PIN_INPUT, 2) /* (U24) GPMC0_BE0n_CLE.MCASP1_ACLKX */
+ AM62PX_IOPAD(0x0098, PIN_INPUT, 2) /* (AA24) GPMC0_WAIT0.MCASP1_AFSX */
+ AM62PX_IOPAD(0x008c, PIN_INPUT, 2) /* (T25) GPMC0_WEn.MCASP1_AXR0 */
+ AM62PX_IOPAD(0x0084, PIN_INPUT, 2) /* (R25) GPMC0_ADVn_ALE.MCASP1_AXR2 */
+ >;
+ };
+
+ main_mdio1_pins_default: main-mdio1-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x0160, PIN_OUTPUT, 0) /* (F17) MDIO0_MDC */
+ AM62PX_IOPAD(0x015c, PIN_INPUT, 0) /* (F16) MDIO0_MDIO */
+ >;
+ };
+
+ main_mmc1_pins_default: main-mmc1-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x023c, PIN_INPUT, 0) /* (H20) MMC1_CMD */
+ AM62PX_IOPAD(0x0234, PIN_OUTPUT, 0) /* (J24) MMC1_CLK */
+ AM62PX_IOPAD(0x0230, PIN_INPUT, 0) /* (H21) MMC1_DAT0 */
+ AM62PX_IOPAD(0x022c, PIN_INPUT_PULLUP, 0) /* (H23) MMC1_DAT1 */
+ AM62PX_IOPAD(0x0228, PIN_INPUT_PULLUP, 0) /* (H22) MMC1_DAT2 */
+ AM62PX_IOPAD(0x0224, PIN_INPUT_PULLUP, 0) /* (H25) MMC1_DAT3 */
+ AM62PX_IOPAD(0x0240, PIN_INPUT, 0) /* (D23) MMC1_SDCD */
+ >;
+ bootph-all;
+ };
+
+ main_mmc2_pins_default: main-mmc2-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x0120, PIN_INPUT, 0) /* (K24) MMC2_CMD */
+ AM62PX_IOPAD(0x0118, PIN_OUTPUT, 0) /* (K21) MMC2_CLK */
+ AM62PX_IOPAD(0x011C, PIN_INPUT, 0) /* () MMC2_CLKLB */
+ AM62PX_IOPAD(0x0114, PIN_INPUT, 0) /* (K23) MMC2_DAT0 */
+ AM62PX_IOPAD(0x0110, PIN_INPUT_PULLUP, 0) /* (K22) MMC2_DAT1 */
+ AM62PX_IOPAD(0x010c, PIN_INPUT_PULLUP, 0) /* (L20) MMC2_DAT2 */
+ AM62PX_IOPAD(0x0108, PIN_INPUT_PULLUP, 0) /* (L21) MMC2_DAT3 */
+ >;
+ bootph-all;
+ };
+
+ main_rgmii1_pins_default: main-rgmii1-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x014c, PIN_INPUT, 0) /* (B15) RGMII1_RD0 */
+ AM62PX_IOPAD(0x0150, PIN_INPUT, 0) /* (B16) RGMII1_RD1 */
+ AM62PX_IOPAD(0x0154, PIN_INPUT, 0) /* (A14) RGMII1_RD2 */
+ AM62PX_IOPAD(0x0158, PIN_INPUT, 0) /* (B14) RGMII1_RD3 */
+ AM62PX_IOPAD(0x0148, PIN_INPUT, 0) /* (A16) RGMII1_RXC */
+ AM62PX_IOPAD(0x0144, PIN_INPUT, 0) /* (A15) RGMII1_RX_CTL */
+ AM62PX_IOPAD(0x0134, PIN_INPUT, 0) /* (A18) RGMII1_TD0 */
+ AM62PX_IOPAD(0x0138, PIN_INPUT, 0) /* (C17) RGMII1_TD1 */
+ AM62PX_IOPAD(0x013c, PIN_INPUT, 0) /* (A17) RGMII1_TD2 */
+ AM62PX_IOPAD(0x0140, PIN_INPUT, 0) /* (C16) RGMII1_TD3 */
+ AM62PX_IOPAD(0x0130, PIN_INPUT, 0) /* (B17) RGMII1_TXC */
+ AM62PX_IOPAD(0x012c, PIN_INPUT, 0) /* (B18) RGMII1_TX_CTL */
+ >;
+ bootph-all;
+ };
+
+ main_rgmii2_pins_default: main-rgmii2-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x0184, PIN_INPUT, 0) /* (E19) RGMII2_RD0 */
+ AM62PX_IOPAD(0x0188, PIN_INPUT, 0) /* (E16) RGMII2_RD1 */
+ AM62PX_IOPAD(0x018c, PIN_INPUT, 0) /* (E17) RGMII2_RD2 */
+ AM62PX_IOPAD(0x0190, PIN_INPUT, 0) /* (C19) RGMII2_RD3 */
+ AM62PX_IOPAD(0x0180, PIN_INPUT, 0) /* (D19) RGMII2_RXC */
+ AM62PX_IOPAD(0x017c, PIN_INPUT, 0) /* (F19) RGMII2_RX_CTL */
+ AM62PX_IOPAD(0x016c, PIN_INPUT, 0) /* (B19) RGMII2_TD0 */
+ AM62PX_IOPAD(0x0170, PIN_INPUT, 0) /* (A21) RGMII2_TD1 */
+ AM62PX_IOPAD(0x0174, PIN_INPUT, 0) /* (D17) RGMII2_TD2 */
+ AM62PX_IOPAD(0x0178, PIN_INPUT, 0) /* (A19) RGMII2_TD3 */
+ AM62PX_IOPAD(0x0168, PIN_INPUT, 0) /* (D16) RGMII2_TXC */
+ AM62PX_IOPAD(0x0164, PIN_INPUT, 0) /* (A20) RGMII2_TX_CTL */
+ >;
+ bootph-all;
+ };
+
+ main_uart0_pins_default: main-uart0-default-pins {
pinctrl-single,pins = <
AM62PX_IOPAD(0x1c8, PIN_INPUT, 0) /* (A22) UART0_RXD */
AM62PX_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (B22) UART0_TXD */
- AM62PX_IOPAD(0x1d0, PIN_INPUT, 0) /* (A23) UART0_CTSn */
- AM62PX_IOPAD(0x1d4, PIN_OUTPUT, 0) /* (C22) UART0_RTSn */
>;
+ bootph-all;
};
main_uart1_pins_default: main-uart1-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x0194, PIN_INPUT, 2) /* (D25) MCASP0_AXR3.UART1_CTSn */
+ AM62PX_IOPAD(0x0198, PIN_OUTPUT, 2) /* (E25) MCASP0_AXR2.UART1_RTSn */
+ AM62PX_IOPAD(0x01ac, PIN_INPUT, 2) /* (G23) MCASP0_AFSR.UART1_RXD */
+ AM62PX_IOPAD(0x01b0, PIN_OUTPUT, 2) /* (G20) MCASP0_ACLKR.UART1_TXD */
+ >;
bootph-all;
+ };
+
+ main_wlirq_pins_default: main-wlirq-default-pins {
pinctrl-single,pins = <
- AM62PX_IOPAD(0x194, PIN_INPUT, 2) /* (D25) MCASP0_AXR3 */
- AM62PX_IOPAD(0x198, PIN_OUTPUT, 2) /* (E25) MCASP0_AXR2 */
- AM62PX_IOPAD(0x1ac, PIN_INPUT, 2) /* (G23) MCASP0_AFSR */
- AM62PX_IOPAD(0x1b0, PIN_OUTPUT, 2) /* (G20) MCASP0_ACLKR */
+ AM62PX_IOPAD(0x0128, PIN_INPUT, 7) /* (K25) MMC2_SDWP.GPIO0_72 */
+ >;
+ };
+
+ ospi0_pins_default: ospi0-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x0000, PIN_OUTPUT, 0) /* (P23) OSPI0_CLK */
+ AM62PX_IOPAD(0x002c, PIN_OUTPUT, 0) /* (M25) OSPI0_CSn0 */
+ AM62PX_IOPAD(0x000c, PIN_INPUT, 0) /* (L25) OSPI0_D0 */
+ AM62PX_IOPAD(0x0010, PIN_INPUT, 0) /* (N24) OSPI0_D1 */
+ AM62PX_IOPAD(0x0014, PIN_INPUT, 0) /* (N25) OSPI0_D2 */
+ AM62PX_IOPAD(0x0018, PIN_INPUT, 0) /* (M24) OSPI0_D3 */
+ AM62PX_IOPAD(0x001c, PIN_INPUT, 0) /* (N21) OSPI0_D4 */
+ AM62PX_IOPAD(0x0020, PIN_INPUT, 0) /* (N22) OSPI0_D5 */
+ AM62PX_IOPAD(0x0024, PIN_INPUT, 0) /* (P21) OSPI0_D6 */
+ AM62PX_IOPAD(0x0028, PIN_INPUT, 0) /* (N20) OSPI0_D7 */
+ AM62PX_IOPAD(0x0008, PIN_INPUT, 0) /* (P22) OSPI0_DQS */
+ >;
+ bootph-all;
+ };
+
+ usr_led_pins_default: usr-led-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x0244, PIN_INPUT, 7) /* (D24) MMC1_SDWP.GPIO1_49 */
+ >;
+ };
+
+ vddshv_sdio_pins_default: vddshvr-sdio-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x007c, PIN_INPUT, 7) /* (Y25) GPMC0_CLK.GPIO0_31 */
+ >;
+ bootph-all;
+ };
+
+ wlan_en_pins_default: wlan-en-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_IOPAD(0x0124, PIN_INPUT, 7) /* (J25) MMC2_SDCD.GPIO0_71 */
>;
};
};
-&main_uart0 {
+&main_i2c1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c1_pins_default>;
+ clock-frequency = <100000>;
+ bootph-all;
+
+ tlv320aic3106: audio-codec@1b {
+ #sound-dai-cells = <0>;
+ compatible = "ti,tlv320aic3106";
+ reg = <0x1b>;
+ ai3x-micbias-vg = <1>; /* 2.0V */
+ };
+
+ exp1: gpio@22 {
+ compatible = "ti,tca6424";
+ reg = <0x22>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "OLDI_INT#", "x8_NAND_DETECT",
+ "UART1_FET_SEL", "MMC1_SD_EN",
+ "VPP_EN", "EXP_PS_3V3_EN",
+ "UART1_FET_BUF_EN", "EXP_HAT_DETECT",
+ "DSI_GPIO0", "DSI_GPIO1",
+ "OLDI_EDID", "BT_UART_WAKE_SOC_3V3",
+ "USB_TYPEA_OC_INDICATION", "CSI_GPIO0",
+ "CSI_GPIO1", "WLAN_ALERTn",
+ "HDMI_INTn", "TEST_GPIO2",
+ "MCASP1_FET_EN", "MCASP1_BUF_BT_EN",
+ "MCASP1_FET_SEL", "DSI_EDID",
+ "PD_I2C_IRQ", "IO_EXP_TEST_LED";
+
+ interrupt-parent = <&main_gpio1>;
+ interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_gpio1_ioexp_intr_pins_default>;
+ bootph-all;
+ };
+
+ exp2: gpio@23 {
+ compatible = "ti,tca6424";
+ reg = <0x23>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "BT_EN_SOC", "EXP_PS_5V0_EN",
+ "", "",
+ "", "",
+ "", "",
+ "WL_LT_EN", "",
+ "TP3", "TP6",
+ "TP4", "TP7",
+ "TP5", "TP8",
+ "SoC_I2C2_MCAN_SEL", "GPIO_HDMI_RSTn",
+ "GPIO_CPSW2_RST", "GPIO_CPSW1_RST",
+ "GPIO_OLDI_RSTn", "GPIO_AUD_RSTn",
+ "GPIO_eMMC_RSTn", "SoC_WLAN_SDIO_RST";
+ };
+};
+
+&main_i2c2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c2_pins_default>;
+ clock-frequency = <400000>;
+};
+
+&sdhci0 {
+ status = "okay";
+ ti,driver-strength-ohm = <50>;
+ disable-wp;
+};
+
+&sdhci1 {
+ /* SD/MMC */
+ status = "okay";
+ vmmc-supply = <&vdd_mmc1>;
+ vqmmc-supply = <&vddshv_sdio>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mmc1_pins_default>;
+ ti,driver-strength-ohm = <50>;
+ disable-wp;
+ no-1-8-v;
+ bootph-all;
+};
+
+&cpsw3g {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_rgmii1_pins_default>,
+ <&main_rgmii2_pins_default>;
+};
+
+&cpsw_port1 {
+ phy-mode = "rgmii-rxid";
+ phy-handle = <&cpsw3g_phy0>;
+};
+
+&cpsw_port2 {
+ phy-mode = "rgmii-rxid";
+ phy-handle = <&cpsw3g_phy1>;
+};
+
+&cpsw3g_mdio {
+ cpsw3g_phy0: ethernet-phy@0 {
+ reg = <0>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ ti,min-output-impedance;
+ };
+
+ cpsw3g_phy1: ethernet-phy@1 {
+ reg = <1>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ ti,min-output-impedance;
+ };
+};
+
+&mcasp1 {
+ status = "okay";
+ #sound-dai-cells = <0>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcasp1_pins_default>;
+
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+
+ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+ 1 0 2 0
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ >;
+ tx-num-evt = <32>;
+ rx-num-evt = <32>;
+};
+
+&fss {
bootph-all;
+};
+
+&ospi0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&ospi0_pins_default>;
+ bootph-all;
+
+ flash@0{
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-tx-bus-width = <8>;
+ spi-rx-bus-width = <8>;
+ spi-max-frequency = <25000000>;
+ cdns,tshsl-ns = <60>;
+ cdns,tsd2d-ns = <60>;
+ cdns,tchsh-ns = <60>;
+ cdns,tslch-ns = <60>;
+ cdns,read-delay = <4>;
+ bootph-all;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ bootph-all;
+
+ partition@0 {
+ label = "ospi.tiboot3";
+ reg = <0x00 0x80000>;
+ };
+
+ partition@80000 {
+ label = "ospi.tispl";
+ reg = <0x80000 0x200000>;
+ };
+
+ partition@280000 {
+ label = "ospi.u-boot";
+ reg = <0x280000 0x400000>;
+ };
+
+ partition@680000 {
+ label = "ospi.env";
+ reg = <0x680000 0x40000>;
+ };
+
+ partition@6c0000 {
+ label = "ospi.env.backup";
+ reg = <0x6c0000 0x40000>;
+ };
+
+ partition@800000 {
+ label = "ospi.rootfs";
+ reg = <0x800000 0x37c0000>;
+ };
+
+ partition@3fc0000 {
+ label = "ospi.phypattern";
+ reg = <0x3fc0000 0x40000>;
+ bootph-all;
+ };
+ };
+ };
+};
+
+&mailbox0_cluster0 {
+ mbox_r5_0: mbox-r5-0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+};
+
+&mailbox0_cluster1 {
+ mbox_mcu_r5_0: mbox-mcu-r5-0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+};
+
+&main_uart0 {
pinctrl-names = "default";
pinctrl-0 = <&main_uart0_pins_default>;
status = "okay";
+ bootph-all;
};
&main_uart1 {
@@ -88,29 +574,27 @@
pinctrl-0 = <&main_uart1_pins_default>;
/* Main UART1 is used by TIFS firmware */
status = "reserved";
-};
-
-&cbass_mcu {
bootph-all;
};
&mcu_pmx0 {
bootph-all;
+
wkup_uart0_pins_default: wkup-uart0-default-pins {
- bootph-all;
pinctrl-single,pins = <
AM62PX_MCU_IOPAD(0x02c, PIN_INPUT, 0) /* (C7) WKUP_UART0_CTSn */
AM62PX_MCU_IOPAD(0x030, PIN_OUTPUT, 0) /* (C6) WKUP_UART0_RTSn */
AM62PX_MCU_IOPAD(0x024, PIN_INPUT, 0) /* (D8) WKUP_UART0_RXD */
AM62PX_MCU_IOPAD(0x028, PIN_OUTPUT, 0) /* (D7) WKUP_UART0_TXD */
>;
+ bootph-all;
};
};
&wkup_uart0 {
/* WKUP UART0 is used by DM firmware */
- bootph-all;
pinctrl-names = "default";
pinctrl-0 = <&wkup_uart0_pins_default>;
status = "reserved";
+ bootph-all;
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi
index 677ff8de4b6e..19f57ead4ebd 100644
--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi
@@ -28,6 +28,7 @@
};
memory@80000000 {
+ bootph-pre-ram;
device_type = "memory";
/* 2G RAM */
reg = <0x00000000 0x80000000 0x00000000 0x80000000>;
@@ -130,6 +131,7 @@
&main_pmx0 {
/* First pad number is ALW package and second is AMC package */
main_uart0_pins_default: main-uart0-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x1c8, PIN_INPUT, 0) /* (D14/A13) UART0_RXD */
AM62X_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14/E11) UART0_TXD */
@@ -137,6 +139,7 @@
};
main_uart1_pins_default: main-uart1-default-pins {
+ bootph-pre-ram;
pinctrl-single,pins = <
AM62X_IOPAD(0x194, PIN_INPUT, 2) /* (B19/B18) MCASP0_AXR3.UART1_CTSn */
AM62X_IOPAD(0x198, PIN_OUTPUT, 2) /* (A19/B17) MCASP0_AXR2.UART1_RTSn */
@@ -167,6 +170,7 @@
};
main_mmc0_pins_default: main-mmc0-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (Y3/V3) MMC0_CMD */
AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (AB1/Y1) MMC0_CLK */
@@ -182,6 +186,7 @@
};
main_mmc1_pins_default: main-mmc1-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x23c, PIN_INPUT, 0) /* (A21/C18) MMC1_CMD */
AM62X_IOPAD(0x234, PIN_INPUT, 0) /* (B22/A20) MMC1_CLK */
@@ -207,6 +212,7 @@
};
main_rgmii1_pins_default: main-rgmii1-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x14c, PIN_INPUT, 0) /* (AB17/W15) RGMII1_RD0 */
AM62X_IOPAD(0x150, PIN_INPUT, 0) /* (AC17/Y16) RGMII1_RD1 */
@@ -274,6 +280,7 @@
&mcu_pmx0 {
wkup_uart0_pins_default: wkup-uart0-default-pins {
+ bootph-pre-ram;
pinctrl-single,pins = <
AM62X_MCU_IOPAD(0x02c, PIN_INPUT, 0) /* (C6/A7) WKUP_UART0_CTSn */
AM62X_MCU_IOPAD(0x030, PIN_OUTPUT, 0) /* (A4/B4) WKUP_UART0_RTSn */
@@ -285,12 +292,14 @@
&wkup_uart0 {
/* WKUP UART0 is used by DM firmware */
+ bootph-pre-ram;
status = "reserved";
pinctrl-names = "default";
pinctrl-0 = <&wkup_uart0_pins_default>;
};
&main_uart0 {
+ bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart0_pins_default>;
@@ -298,6 +307,7 @@
&main_uart1 {
/* Main UART1 is used by TIFS firmware */
+ bootph-pre-ram;
status = "reserved";
pinctrl-names = "default";
pinctrl-0 = <&main_uart1_pins_default>;
@@ -390,6 +400,7 @@
};
&sdhci0 {
+ bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_mmc0_pins_default>;
@@ -399,6 +410,7 @@
&sdhci1 {
/* SD/MMC */
+ bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_mmc1_pins_default>;
@@ -407,21 +419,25 @@
};
&cpsw3g {
+ bootph-all;
pinctrl-names = "default";
pinctrl-0 = <&main_rgmii1_pins_default>;
};
&cpsw_port1 {
+ bootph-all;
phy-mode = "rgmii-rxid";
phy-handle = <&cpsw3g_phy0>;
};
&cpsw3g_mdio {
+ bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_mdio1_pins_default>;
cpsw3g_phy0: ethernet-phy@0 {
+ bootph-all;
reg = <0>;
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
diff --git a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
index 0df54a741824..0be642bc1b86 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
@@ -38,6 +38,7 @@
};
main_conf: syscon@43000000 {
+ bootph-all;
compatible = "ti,j721e-system-controller", "syscon", "simple-mfd";
reg = <0x0 0x43000000 0x0 0x20000>;
#address-cells = <1>;
@@ -45,6 +46,7 @@
ranges = <0x0 0x0 0x43000000 0x20000>;
chipid@14 {
+ bootph-all;
compatible = "ti,am654-chipid";
reg = <0x00000014 0x4>;
};
@@ -96,7 +98,8 @@
};
dmss: bus@48000000 {
- compatible = "simple-mfd";
+ bootph-all;
+ compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
dma-ranges;
@@ -105,6 +108,7 @@
ti,sci-dev-id = <25>;
secure_proxy_main: mailbox@4d000000 {
+ bootph-all;
compatible = "ti,am654-secure-proxy";
#mbox-cells = <1>;
reg-names = "target_data", "rt", "scfg";
@@ -188,6 +192,7 @@
};
dmsc: system-controller@44043000 {
+ bootph-all;
compatible = "ti,k2g-sci";
ti,host-id = <12>;
mbox-names = "rx", "tx";
@@ -197,22 +202,26 @@
reg = <0x00 0x44043000 0x00 0xfe0>;
k3_pds: power-controller {
+ bootph-all;
compatible = "ti,sci-pm-domain";
#power-domain-cells = <2>;
};
k3_clks: clock-controller {
+ bootph-all;
compatible = "ti,k2g-sci-clk";
#clock-cells = <2>;
};
k3_reset: reset-controller {
+ bootph-all;
compatible = "ti,sci-reset";
#reset-cells = <2>;
};
};
main_pmx0: pinctrl@f4000 {
+ bootph-all;
compatible = "pinctrl-single";
reg = <0x00 0xf4000 0x00 0x2d0>;
#pinctrl-cells = <1>;
@@ -221,6 +230,7 @@
};
main_timer0: timer@2400000 {
+ bootph-all;
compatible = "ti,am654-timer";
reg = <0x00 0x2400000 0x00 0x400>;
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
@@ -365,6 +375,7 @@
};
main_esm: esm@420000 {
+ bootph-pre-ram;
compatible = "ti,j721e-esm";
reg = <0x00 0x420000 0x00 0x1000>;
ti,esm-pins = <160>, <161>;
@@ -1158,21 +1169,21 @@
};
main_rti0: watchdog@e000000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0xe000000 0x00 0x100>;
- clocks = <&k3_clks 125 0>;
- power-domains = <&k3_pds 125 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 125 0>;
- assigned-clock-parents = <&k3_clks 125 2>;
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0xe000000 0x00 0x100>;
+ clocks = <&k3_clks 125 0>;
+ power-domains = <&k3_pds 125 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 125 0>;
+ assigned-clock-parents = <&k3_clks 125 2>;
};
main_rti1: watchdog@e010000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0xe010000 0x00 0x100>;
- clocks = <&k3_clks 126 0>;
- power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 126 0>;
- assigned-clock-parents = <&k3_clks 126 2>;
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0xe010000 0x00 0x100>;
+ clocks = <&k3_clks 126 0>;
+ power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 126 0>;
+ assigned-clock-parents = <&k3_clks 126 2>;
};
icssg0: icssg@30000000 {
diff --git a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi
index 686d49790721..b9508072bebb 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi
@@ -146,6 +146,7 @@
};
mcu_pmx0: pinctrl@4084000 {
+ bootph-all;
compatible = "pinctrl-single";
reg = <0x00 0x4084000 0x00 0x84>;
#pinctrl-cells = <1>;
@@ -154,6 +155,7 @@
};
mcu_esm: esm@4100000 {
+ bootph-pre-ram;
compatible = "ti,j721e-esm";
reg = <0x00 0x4100000 0x00 0x1000>;
ti,esm-pins = <0>, <1>;
diff --git a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
index 1c2c8f0daca9..f87f09d83c95 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
@@ -126,6 +126,12 @@
AM64X_IOPAD(0x002c, PIN_OUTPUT, 0) /* (L19) OSPI0_CSn0 */
>;
};
+
+ rtc_pins_default: rtc-defaults-pins {
+ pinctrl-single,pins = <
+ AM64X_IOPAD(0x0278, PIN_INPUT, 7) /* (C19) EXTINTn.GPIO1_70 */
+ >;
+ };
};
&cpsw3g {
@@ -177,6 +183,11 @@
i2c_som_rtc: rtc@52 {
compatible = "microcrystal,rv3028";
reg = <0x52>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtc_pins_default>;
+ interrupt-parent = <&main_gpio1>;
+ interrupts = <70 IRQ_TYPE_EDGE_FALLING>;
+ wakeup-source;
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-am64.dtsi b/arch/arm64/boot/dts/ti/k3-am64.dtsi
index 8e9c2bc70f4d..0187c42aed4f 100644
--- a/arch/arm64/boot/dts/ti/k3-am64.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64.dtsi
@@ -47,6 +47,7 @@
};
cbass_main: bus@f4000 {
+ bootph-all;
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
@@ -85,6 +86,7 @@
<0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>;
cbass_mcu: bus@4000000 {
+ bootph-all;
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
diff --git a/arch/arm64/boot/dts/ti/k3-am642-evm.dts b/arch/arm64/boot/dts/ti/k3-am642-evm.dts
index b4a1f73d4fb1..4dba18941015 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-evm.dts
@@ -35,6 +35,7 @@
};
memory@80000000 {
+ bootph-all;
device_type = "memory";
/* 2G RAM */
reg = <0x00000000 0x80000000 0x00000000 0x80000000>;
@@ -108,6 +109,7 @@
evm_12v0: regulator-0 {
/* main DC jack */
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "evm_12v0";
regulator-min-microvolt = <12000000>;
@@ -129,6 +131,7 @@
vsys_3v3: regulator-2 {
/* output of LM5140 */
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "vsys_3v3";
regulator-min-microvolt = <3300000>;
@@ -140,6 +143,7 @@
vdd_mmc1: regulator-3 {
/* TPS2051BD */
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "vdd_mmc1";
regulator-min-microvolt = <3300000>;
@@ -161,6 +165,7 @@
};
vtt_supply: regulator-5 {
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "vtt";
pinctrl-names = "default";
@@ -251,6 +256,7 @@
};
main_uart0_pins_default: main-uart0-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x0238, PIN_INPUT, 0) /* (B16) UART0_CTSn */
AM64X_IOPAD(0x023c, PIN_OUTPUT, 0) /* (A16) UART0_RTSn */
@@ -269,6 +275,7 @@
};
main_i2c0_pins_default: main-i2c0-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x0260, PIN_INPUT_PULLUP, 0) /* (A18) I2C0_SCL */
AM64X_IOPAD(0x0264, PIN_INPUT_PULLUP, 0) /* (B18) I2C0_SDA */
@@ -276,6 +283,7 @@
};
main_i2c1_pins_default: main-i2c1-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x0268, PIN_INPUT_PULLUP, 0) /* (C18) I2C1_SCL */
AM64X_IOPAD(0x026c, PIN_INPUT_PULLUP, 0) /* (B19) I2C1_SDA */
@@ -283,6 +291,7 @@
};
mdio1_pins_default: mdio1-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x01fc, PIN_OUTPUT, 4) /* (R2) PRG0_PRU1_GPO19.MDIO0_MDC */
AM64X_IOPAD(0x01f8, PIN_INPUT, 4) /* (P5) PRG0_PRU1_GPO18.MDIO0_MDIO */
@@ -290,6 +299,7 @@
};
rgmii1_pins_default: rgmii1-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x01cc, PIN_INPUT, 4) /* (W5) PRG0_PRU1_GPO7.RGMII1_RD0 */
AM64X_IOPAD(0x01d4, PIN_INPUT, 4) /* (Y5) PRG0_PRU1_GPO9.RGMII1_RD1 */
@@ -307,6 +317,7 @@
};
rgmii2_pins_default: rgmii2-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x0108, PIN_INPUT, 4) /* (W11) PRG1_PRU1_GPO0.RGMII2_RD0 */
AM64X_IOPAD(0x010c, PIN_INPUT, 4) /* (V11) PRG1_PRU1_GPO1.RGMII2_RD1 */
@@ -324,6 +335,7 @@
};
main_usb0_pins_default: main-usb0-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x02a8, PIN_OUTPUT, 0) /* (E19) USB0_DRVVBUS */
>;
@@ -366,6 +378,7 @@
};
ddr_vtt_pins_default: ddr-vtt-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x0030, PIN_OUTPUT_PULLUP, 7) /* (L18) OSPI0_CSN1.GPIO0_12 */
>;
@@ -373,6 +386,7 @@
};
&main_uart0 {
+ bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart0_pins_default>;
@@ -387,11 +401,21 @@
};
&main_i2c0 {
+ bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c0_pins_default>;
clock-frequency = <400000>;
+ gpio@38 {
+ /* TCA9554 */
+ compatible = "nxp,pca9554";
+ reg = <0x38>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "HSE_DETECT";
+ };
+
eeprom@50 {
/* AT24CM01 */
compatible = "atmel,24c1024";
@@ -400,12 +424,14 @@
};
&main_i2c1 {
+ bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c1_pins_default>;
clock-frequency = <400000>;
exp1: gpio@22 {
+ bootph-all;
compatible = "ti,tca6424";
reg = <0x22>;
gpio-controller;
@@ -438,6 +464,10 @@
};
};
+&main_gpio0 {
+ bootph-all;
+};
+
/* mcu_gpio0 is reserved for mcu firmware usage */
&mcu_gpio0 {
status = "reserved";
@@ -467,6 +497,7 @@
&sdhci1 {
/* SD/MMC */
+ bootph-all;
vmmc-supply = <&vdd_mmc1>;
pinctrl-names = "default";
bus-width = <4>;
@@ -476,11 +507,13 @@
};
&usbss0 {
+ bootph-all;
ti,vbus-divider;
ti,usb2-only;
};
&usb0 {
+ bootph-all;
dr_mode = "otg";
maximum-speed = "high-speed";
pinctrl-names = "default";
@@ -488,11 +521,13 @@
};
&cpsw3g {
+ bootph-all;
pinctrl-names = "default";
pinctrl-0 = <&rgmii1_pins_default>, <&rgmii2_pins_default>;
};
&cpsw_port1 {
+ bootph-all;
phy-mode = "rgmii-rxid";
phy-handle = <&cpsw3g_phy0>;
};
@@ -503,11 +538,13 @@
};
&cpsw3g_mdio {
+ bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mdio1_pins_default>;
cpsw3g_phy0: ethernet-phy@0 {
+ bootph-all;
reg = <0>;
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
diff --git a/arch/arm64/boot/dts/ti/k3-am642-sk.dts b/arch/arm64/boot/dts/ti/k3-am642-sk.dts
index 722fd285a34e..f29c8a9b59ba 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-sk.dts
@@ -34,6 +34,7 @@
};
memory@80000000 {
+ bootph-pre-ram;
device_type = "memory";
/* 2G RAM */
reg = <0x00000000 0x80000000 0x00000000 0x80000000>;
@@ -107,6 +108,7 @@
vusb_main: regulator-0 {
/* USB MAIN INPUT 5V DC */
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "vusb_main5v0";
regulator-min-microvolt = <5000000>;
@@ -117,6 +119,7 @@
vcc_3v3_sys: regulator-1 {
/* output of LP8733xx */
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "vcc_3v3_sys";
regulator-min-microvolt = <3300000>;
@@ -128,6 +131,7 @@
vdd_mmc1: regulator-2 {
/* TPS2051BD */
+ bootph-all;
compatible = "regulator-fixed";
regulator-name = "vdd_mmc1";
regulator-min-microvolt = <3300000>;
@@ -234,6 +238,7 @@
&main_pmx0 {
main_mmc1_pins_default: main-mmc1-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x029c, PIN_INPUT_PULLUP, 0) /* (C20) MMC1_SDWP */
AM64X_IOPAD(0x0298, PIN_INPUT_PULLUP, 0) /* (D19) MMC1_SDCD */
@@ -248,6 +253,7 @@
};
main_uart0_pins_default: main-uart0-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x0238, PIN_INPUT, 0) /* (B16) UART0_CTSn */
AM64X_IOPAD(0x023c, PIN_OUTPUT, 0) /* (A16) UART0_RTSn */
@@ -257,6 +263,7 @@
};
main_uart1_pins_default: main-uart1-default-pins {
+ bootph-pre-ram;
pinctrl-single,pins = <
AM64X_IOPAD(0x0248, PIN_INPUT, 0) /* (D16) UART1_CTSn */
AM64X_IOPAD(0x024c, PIN_OUTPUT, 0) /* (E16) UART1_RTSn */
@@ -266,12 +273,14 @@
};
main_usb0_pins_default: main-usb0-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x02a8, PIN_OUTPUT, 0) /* (E19) USB0_DRVVBUS */
>;
};
main_i2c0_pins_default: main-i2c0-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x0260, PIN_INPUT_PULLUP, 0) /* (A18) I2C0_SCL */
AM64X_IOPAD(0x0264, PIN_INPUT_PULLUP, 0) /* (B18) I2C0_SDA */
@@ -279,6 +288,7 @@
};
main_i2c1_pins_default: main-i2c1-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM64X_IOPAD(0x0268, PIN_INPUT_PULLUP, 0) /* (C18) I2C1_SCL */
AM64X_IOPAD(0x026c, PIN_INPUT_PULLUP, 0) /* (B19) I2C1_SDA */
@@ -367,6 +377,7 @@
};
&main_uart0 {
+ bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart0_pins_default>;
@@ -375,12 +386,14 @@
&main_uart1 {
/* main_uart1 is reserved for firmware usage */
+ bootph-pre-ram;
status = "reserved";
pinctrl-names = "default";
pinctrl-0 = <&main_uart1_pins_default>;
};
&main_i2c0 {
+ bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c0_pins_default>;
@@ -393,12 +406,14 @@
};
&main_i2c1 {
+ bootph-all;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c1_pins_default>;
clock-frequency = <400000>;
exp1: gpio@70 {
+ bootph-all;
compatible = "nxp,pca9538";
reg = <0x70>;
gpio-controller;
@@ -445,6 +460,7 @@
&sdhci1 {
/* SD/MMC */
+ bootph-all;
vmmc-supply = <&vdd_mmc1>;
pinctrl-names = "default";
bus-width = <4>;
@@ -454,11 +470,22 @@
};
&serdes_ln_ctrl {
+ bootph-all;
idle-states = <AM64_SERDES0_LANE0_USB>;
};
+&serdes_refclk {
+ bootph-all;
+};
+
+&serdes_wiz0 {
+ bootph-all;
+};
+
&serdes0 {
+ bootph-all;
serdes0_usb_link: phy@0 {
+ bootph-all;
reg = <0>;
cdns,num-lanes = <1>;
#phy-cells = <0>;
@@ -468,10 +495,12 @@
};
&usbss0 {
+ bootph-all;
ti,vbus-divider;
};
&usb0 {
+ bootph-all;
dr_mode = "host";
maximum-speed = "super-speed";
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts
index 04c15b64f0b7..d95d80076a42 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts
@@ -8,6 +8,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
#include <dt-bindings/net/ti-dp83867.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/pwm/pwm.h>
@@ -19,6 +20,7 @@
compatible = "tq,am642-tqma6442l-mbax4xxl", "tq,am642-tqma6442l",
"ti,am642";
model = "TQ-Systems TQMa64xxL SoM on MBax4xxL carrier board";
+ chassis-type = "embedded";
aliases {
ethernet0 = &cpsw_port1;
@@ -58,12 +60,14 @@
pinctrl-0 = <&mcu_gpio_leds_pins>;
led-0 {
- label = "led0";
gpios = <&mcu_gpio0 8 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_INDICATOR;
};
led-1 {
- label = "led1";
gpios = <&mcu_gpio0 9 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_INDICATOR;
};
};
@@ -170,7 +174,8 @@
&main_gpio1 {
pinctrl-names = "default";
- pinctrl-0 = <&main_gpio1_hog_pins>;
+ pinctrl-0 = <&main_gpio1_hog_pins>,
+ <&main_gpio1_pru_pins>;
gpio-line-names =
"", "", "", "", /* 0-3 */
"", "", "", "", /* 4-7 */
@@ -545,6 +550,79 @@
>;
};
+ main_gpio1_pru_pins: main-gpio1-pru-pins {
+ pinctrl-single,pins = <
+ /* (Y1) PRG0_PRU0_GPO0.GPIO1_0 */
+ AM64X_IOPAD(0x0160, PIN_INPUT, 7)
+ /* (R4) PRG0_PRU0_GPO1.GPIO1_1 */
+ AM64X_IOPAD(0x0164, PIN_INPUT, 7)
+ /* (U2) PRG0_PRU0_GPO2.GPIO1_2 */
+ AM64X_IOPAD(0x0168, PIN_INPUT, 7)
+ /* (V2) PRG0_PRU0_GPO3.GPIO1_3 */
+ AM64X_IOPAD(0x016c, PIN_INPUT, 7)
+ /* (AA2) PRG0_PRU0_GPO4.GPIO1_4 */
+ AM64X_IOPAD(0x0170, PIN_INPUT, 7)
+ /* (R3) PRG0_PRU0_GPO5.GPIO1_5 */
+ AM64X_IOPAD(0x0174, PIN_INPUT, 7)
+ /* (T3) PRG0_PRU0_GPO6.GPIO1_6 */
+ AM64X_IOPAD(0x0178, PIN_INPUT, 7)
+ /* (T1) PRG0_PRU0_GPO7.GPIO1_7 */
+ AM64X_IOPAD(0x017c, PIN_INPUT, 7)
+ /* (T2) PRG0_PRU0_GPO8.GPIO1_8 */
+ AM64X_IOPAD(0x0180, PIN_INPUT, 7)
+ /* (Y3) PRG0_PRU0_GPO11.GPIO1_11 */
+ AM64X_IOPAD(0x018c, PIN_INPUT, 7)
+ /* (AA3) PRG0_PRU0_GPO12.GPIO1_12 */
+ AM64X_IOPAD(0x0190, PIN_INPUT, 7)
+ /* (R6) PRG0_PRU0_GPO13.GPIO1_13 */
+ AM64X_IOPAD(0x0194, PIN_INPUT, 7)
+ /* (V4) PRG0_PRU0_GPO14.GPIO1_14 */
+ AM64X_IOPAD(0x0198, PIN_INPUT, 7)
+ /* (T5) PRG0_PRU0_GPO15.GPIO1_15 */
+ AM64X_IOPAD(0x019c, PIN_INPUT, 7)
+ /* (U4) PRG0_PRU0_GPO16.GPIO1_16 */
+ AM64X_IOPAD(0x01a0, PIN_INPUT, 7)
+ /* (U1) PRG0_PRU0_GPO17.GPIO1_17 */
+ AM64X_IOPAD(0x01a4, PIN_INPUT, 7)
+ /* (V1) PRG0_PRU0_GPO18.GPIO1_18 */
+ AM64X_IOPAD(0x01a8, PIN_INPUT, 7)
+ /* (W1) PRG0_PRU0_GPO19.GPIO1_19 */
+ AM64X_IOPAD(0x01ac, PIN_INPUT, 7)
+ /* (Y2) PRG0_PRU1_GPO0.GPIO1_20 */
+ AM64X_IOPAD(0x01b0, PIN_INPUT, 7)
+ /* (W2) PRG0_PRU1_GPO1.GPIO1_21 */
+ AM64X_IOPAD(0x01b4, PIN_INPUT, 7)
+ /* (V3) PRG0_PRU1_GPO2.GPIO1_22 */
+ AM64X_IOPAD(0x01b8, PIN_INPUT, 7)
+ /* (T4) PRG0_PRU1_GPO3.GPIO1_23 */
+ AM64X_IOPAD(0x01bc, PIN_INPUT, 7)
+ /* (W3) PRG0_PRU1_GPO4.GPIO1_24 */
+ AM64X_IOPAD(0x01c0, PIN_INPUT, 7)
+ /* (P4) PRG0_PRU1_GPO5.GPIO1_25 */
+ AM64X_IOPAD(0x01c4, PIN_INPUT, 7)
+ /* (R5) PRG0_PRU1_GPO6.GPIO1_26 */
+ AM64X_IOPAD(0x01c8, PIN_INPUT, 7)
+ /* (R1) PRG0_PRU1_GPO8.GPIO1_28 */
+ AM64X_IOPAD(0x01d0, PIN_INPUT, 7)
+ /* (W4) PRG0_PRU1_GPO11.GPIO1_31 */
+ AM64X_IOPAD(0x01dc, PIN_INPUT, 7)
+ /* (Y4) PRG0_PRU1_GPO12.GPIO1_32 */
+ AM64X_IOPAD(0x01e0, PIN_INPUT, 7)
+ /* (T6) PRG0_PRU1_GPO13.GPIO1_33 */
+ AM64X_IOPAD(0x01e4, PIN_INPUT, 7)
+ /* (U6) PRG0_PRU1_GPO14.GPIO1_34 */
+ AM64X_IOPAD(0x01e8, PIN_INPUT, 7)
+ /* (U5) PRG0_PRU1_GPO15.GPIO1_35 */
+ AM64X_IOPAD(0x01ec, PIN_INPUT, 7)
+ /* (AA4) PRG0_PRU1_GPO16.GPIO1_36 */
+ AM64X_IOPAD(0x01f0, PIN_INPUT, 7)
+ /* (P2) PRG0_MDIO0_MDIO.GPIO1_40 */
+ AM64X_IOPAD(0x0200, PIN_INPUT, 7)
+ /* (P3) PRG0_MDIO0_MDC.GPIO1_41 */
+ AM64X_IOPAD(0x0204, PIN_INPUT, 7)
+ >;
+ };
+
main_mcan0_pins: main-mcan0-pins {
pinctrl-single,pins = <
/* (B17) MCAN0_RX */
diff --git a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi
index 6229849b5d96..d82d4a98306a 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi
@@ -85,6 +85,15 @@
no-map;
};
};
+
+ reg_1v8: regulator-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "V_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
};
&main_i2c0 {
@@ -96,11 +105,13 @@
tmp1075: temperature-sensor@4a {
compatible = "ti,tmp1075";
reg = <0x4a>;
+ vs-supply = <&reg_1v8>;
};
eeprom0: eeprom@50 {
compatible = "st,24c02", "atmel,24c02";
reg = <0x50>;
+ vcc-supply = <&reg_1v8>;
pagesize = <16>;
read-only;
};
@@ -114,6 +125,7 @@
eeprom1: eeprom@54 {
compatible = "st,24c64", "atmel,24c64";
reg = <0x54>;
+ vcc-supply = <&reg_1v8>;
pagesize = <32>;
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
index bc460033a37a..5ebb87f467de 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
@@ -600,7 +600,7 @@
};
main_navss: bus@30800000 {
- compatible = "simple-mfd";
+ compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges = <0x0 0x30800000 0x0 0x30800000 0x0 0xbc00000>;
@@ -1151,6 +1151,18 @@
};
};
+ icssg0_iep0: iep@2e000 {
+ compatible = "ti,am654-icss-iep";
+ reg = <0x2e000 0x1000>;
+ clocks = <&icssg0_iepclk_mux>;
+ };
+
+ icssg0_iep1: iep@2f000 {
+ compatible = "ti,am654-icss-iep";
+ reg = <0x2f000 0x1000>;
+ clocks = <&icssg0_iepclk_mux>;
+ };
+
icssg0_mii_rt: mii-rt@32000 {
compatible = "ti,pruss-mii", "syscon";
reg = <0x32000 0x100>;
@@ -1293,6 +1305,18 @@
};
};
+ icssg1_iep0: iep@2e000 {
+ compatible = "ti,am654-icss-iep";
+ reg = <0x2e000 0x1000>;
+ clocks = <&icssg1_iepclk_mux>;
+ };
+
+ icssg1_iep1: iep@2f000 {
+ compatible = "ti,am654-icss-iep";
+ reg = <0x2f000 0x1000>;
+ clocks = <&icssg1_iepclk_mux>;
+ };
+
icssg1_mii_rt: mii-rt@32000 {
compatible = "ti,pruss-mii", "syscon";
reg = <0x32000 0x100>;
@@ -1435,6 +1459,18 @@
};
};
+ icssg2_iep0: iep@2e000 {
+ compatible = "ti,am654-icss-iep";
+ reg = <0x2e000 0x1000>;
+ clocks = <&icssg2_iepclk_mux>;
+ };
+
+ icssg2_iep1: iep@2f000 {
+ compatible = "ti,am654-icss-iep";
+ reg = <0x2f000 0x1000>;
+ clocks = <&icssg2_iepclk_mux>;
+ };
+
icssg2_mii_rt: mii-rt@32000 {
compatible = "ti,pruss-mii", "syscon";
reg = <0x32000 0x100>;
diff --git a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi
index 1e536dc41f61..edd5cfbec40e 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi
@@ -185,7 +185,7 @@
};
mcu_navss: bus@28380000 {
- compatible = "simple-mfd";
+ compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>;
diff --git a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts
index f5c26e9fba98..1637ec5ab5ed 100644
--- a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts
+++ b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts
@@ -369,6 +369,13 @@
ti,enable-vout-discharge;
};
+ gpio@38 {
+ compatible = "nxp,pca9554";
+ reg = <0x38>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
pca9554: gpio@39 {
compatible = "nxp,pca9554";
reg = <0x39>;
diff --git a/arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso b/arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso
new file mode 100644
index 000000000000..ec8cf20ca3ac
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT overlay for IDK application board on AM654 EVM
+ *
+ * Copyright (C) 2018-2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/net/ti-dp83867.h>
+#include "k3-pinctrl.h"
+
+&{/} {
+ aliases {
+ ethernet1 = "/icssg2-eth/ethernet-ports/port@0";
+ ethernet2 = "/icssg2-eth/ethernet-ports/port@1";
+ };
+
+ /* Ethernet node on PRU-ICSSG2 */
+ icssg2_eth: icssg2-eth {
+ compatible = "ti,am654-icssg-prueth";
+ pinctrl-names = "default";
+ pinctrl-0 = <&icssg2_rgmii_pins_default>;
+ sram = <&msmc_ram>;
+ ti,prus = <&pru2_0>, <&rtu2_0>, <&tx_pru2_0>,
+ <&pru2_1>, <&rtu2_1>, <&tx_pru2_1>;
+ firmware-name = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-pru1-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf";
+
+ ti,pruss-gp-mux-sel = <2>, /* MII mode */
+ <2>,
+ <2>,
+ <2>, /* MII mode */
+ <2>,
+ <2>;
+
+ ti,mii-g-rt = <&icssg2_mii_g_rt>;
+ ti,mii-rt = <&icssg2_mii_rt>;
+ ti,iep = <&icssg2_iep0>, <&icssg2_iep1>;
+
+ interrupt-parent = <&icssg2_intc>;
+ interrupts = <24 0 2>, <25 1 3>;
+ interrupt-names = "tx_ts0", "tx_ts1";
+
+ dmas = <&main_udmap 0xc300>, /* egress slice 0 */
+ <&main_udmap 0xc301>, /* egress slice 0 */
+ <&main_udmap 0xc302>, /* egress slice 0 */
+ <&main_udmap 0xc303>, /* egress slice 0 */
+ <&main_udmap 0xc304>, /* egress slice 1 */
+ <&main_udmap 0xc305>, /* egress slice 1 */
+ <&main_udmap 0xc306>, /* egress slice 1 */
+ <&main_udmap 0xc307>, /* egress slice 1 */
+ <&main_udmap 0x4300>, /* ingress slice 0 */
+ <&main_udmap 0x4301>; /* ingress slice 1 */
+
+ dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3",
+ "tx1-0", "tx1-1", "tx1-2", "tx1-3",
+ "rx0", "rx1";
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ icssg2_emac0: port@0 {
+ reg = <0>;
+ phy-handle = <&icssg2_phy0>;
+ phy-mode = "rgmii-id";
+ ti,syscon-rgmii-delay = <&scm_conf 0x4120>;
+ /* Filled in by bootloader */
+ local-mac-address = [00 00 00 00 00 00];
+ };
+ icssg2_emac1: port@1 {
+ reg = <1>;
+ phy-handle = <&icssg2_phy1>;
+ phy-mode = "rgmii-id";
+ ti,syscon-rgmii-delay = <&scm_conf 0x4124>;
+ /* Filled in by bootloader */
+ local-mac-address = [00 00 00 00 00 00];
+ };
+ };
+ };
+};
+
+&main_pmx0 {
+
+ icssg2_mdio_pins_default: icssg2-mdio-default-pins {
+ pinctrl-single,pins = <
+ AM65X_IOPAD(0x0094, PIN_INPUT, 2) /* (AC19) PRG2_PRU0_GPO7.PRG2_MDIO0_MDIO */
+ AM65X_IOPAD(0x00c8, PIN_OUTPUT, 2) /* (AE15) PRG2_PRU1_GPO7.PRG2_MDIO0_MDC */
+ >;
+ };
+
+ icssg2_rgmii_pins_default: icssg2-rgmii-default-pins {
+ pinctrl-single,pins = <
+ AM65X_IOPAD(0x00ac, PIN_INPUT, 2) /* (AH15) PRG2_PRU1_GPO0.PRG2_RGMII2_RD0 */
+ AM65X_IOPAD(0x00b0, PIN_INPUT, 2) /* (AC16) PRG2_PRU1_GPO1.PRG2_RGMII2_RD1 */
+ AM65X_IOPAD(0x00b4, PIN_INPUT, 2) /* (AD17) PRG2_PRU1_GPO2.PRG2_RGMII2_RD2 */
+ AM65X_IOPAD(0x00b8, PIN_INPUT, 2) /* (AH14) PRG2_PRU1_GPO3.PRG2_RGMII2_RD3 */
+ AM65X_IOPAD(0x00cc, PIN_OUTPUT, 2) /* (AD15) PRG2_PRU1_GPO8.PRG2_RGMII2_TD0 */
+ AM65X_IOPAD(0x00d0, PIN_OUTPUT, 2) /* (AF14) PRG2_PRU1_GPO9.PRG2_RGMII2_TD1 */
+ AM65X_IOPAD(0x00d4, PIN_OUTPUT, 2) /* (AC15) PRG2_PRU1_GPO10.PRG2_RGMII2_TD2 */
+ AM65X_IOPAD(0x00d8, PIN_OUTPUT, 2) /* (AD14) PRG2_PRU1_GPO11.PRG2_RGMII2_TD3 */
+ AM65X_IOPAD(0x00dc, PIN_INPUT, 2) /* (AE14) PRG2_PRU1_GPO16.PRG2_RGMII2_TXC */
+ AM65X_IOPAD(0x00c4, PIN_OUTPUT, 2) /* (AC17) PRG2_PRU1_GPO6.PRG2_RGMII2_TX_CTL */
+ AM65X_IOPAD(0x00c0, PIN_INPUT, 2) /* (AG15) PRG2_PRU1_GPO5.PRG2_RGMII2_RXC */
+ AM65X_IOPAD(0x00bc, PIN_INPUT, 2) /* (AG14) PRG2_PRU1_GPO4.PRG2_RGMII2_RX_CTL */
+
+ AM65X_IOPAD(0x0078, PIN_INPUT, 2) /* (AF18) PRG2_PRU0_GPO0.PRG2_RGMII1_RD0 */
+ AM65X_IOPAD(0x007c, PIN_INPUT, 2) /* (AE18) PRG2_PRU0_GPO1.PRG2_RGMII1_RD1 */
+ AM65X_IOPAD(0x0080, PIN_INPUT, 2) /* (AH17) PRG2_PRU0_GPO2.PRG2_RGMII1_RD2 */
+ AM65X_IOPAD(0x0084, PIN_INPUT, 2) /* (AG18) PRG2_PRU0_GPO3.PRG2_RGMII1_RD3 */
+ AM65X_IOPAD(0x0098, PIN_OUTPUT, 2) /* (AH16) PRG2_PRU0_GPO8.PRG2_RGMII1_TD0 */
+ AM65X_IOPAD(0x009c, PIN_OUTPUT, 2) /* (AG16) PRG2_PRU0_GPO9.PRG2_RGMII1_TD1 */
+ AM65X_IOPAD(0x00a0, PIN_OUTPUT, 2) /* (AF16) PRG2_PRU0_GPO10.PRG2_RGMII1_TD2 */
+ AM65X_IOPAD(0x00a4, PIN_OUTPUT, 2) /* (AE16) PRG2_PRU0_GPO11.PRG2_RGMII1_TD3 */
+ AM65X_IOPAD(0x00a8, PIN_INPUT, 2) /* (AD16) PRG2_PRU0_GPO16.PRG2_RGMII1_TXC */
+ AM65X_IOPAD(0x0090, PIN_OUTPUT, 2) /* (AE17) PRG2_PRU0_GPO6.PRG2_RGMII1_TX_CTL */
+ AM65X_IOPAD(0x008c, PIN_INPUT, 2) /* (AF17) PRG2_PRU0_GPO5.PRG2_RGMII1_RXC */
+ AM65X_IOPAD(0x0088, PIN_INPUT, 2) /* (AG17) PRG2_PRU0_GPO4.PRG2_RGMII1_RX_CTL */
+ >;
+ };
+};
+
+&icssg2_mdio {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&icssg2_mdio_pins_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ icssg2_phy0: ethernet-phy@0 {
+ reg = <0>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ };
+
+ icssg2_phy1: ethernet-phy@3 {
+ reg = <3>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso
new file mode 100644
index 000000000000..150428dfce6f
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT overlay for IDK application board on AM654 EVM
+ *
+ * Copyright (C) 2018-2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/net/ti-dp83867.h>
+#include "k3-pinctrl.h"
+
+&{/} {
+ aliases {
+ ethernet3 = "/icssg0-eth/ethernet-ports/port@0";
+ ethernet4 = "/icssg0-eth/ethernet-ports/port@1";
+ ethernet5 = "/icssg1-eth/ethernet-ports/port@0";
+ ethernet6 = "/icssg1-eth/ethernet-ports/port@1";
+ };
+
+ /* Ethernet node on PRU-ICSSG0 */
+ icssg0_eth: icssg0-eth {
+ compatible = "ti,am654-icssg-prueth";
+ pinctrl-names = "default";
+ pinctrl-0 = <&icssg0_rgmii_pins_default>;
+ sram = <&msmc_ram>;
+ ti,prus = <&pru0_0>, <&rtu0_0>, <&tx_pru0_0>, <&pru0_1>, <&rtu0_1>, <&tx_pru0_1>;
+ firmware-name = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-pru1-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf";
+
+ ti,pruss-gp-mux-sel = <2>, /* MII mode */
+ <2>,
+ <2>,
+ <2>, /* MII mode */
+ <2>,
+ <2>;
+
+ ti,mii-g-rt = <&icssg0_mii_g_rt>;
+ ti,mii-rt = <&icssg0_mii_rt>;
+ ti,iep = <&icssg0_iep0>, <&icssg0_iep1>;
+
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <24 0 2>, <25 1 3>;
+ interrupt-names = "tx_ts0", "tx_ts1";
+
+ dmas = <&main_udmap 0xc100>, /* egress slice 0 */
+ <&main_udmap 0xc101>, /* egress slice 0 */
+ <&main_udmap 0xc102>, /* egress slice 0 */
+ <&main_udmap 0xc103>, /* egress slice 0 */
+ <&main_udmap 0xc104>, /* egress slice 1 */
+ <&main_udmap 0xc105>, /* egress slice 1 */
+ <&main_udmap 0xc106>, /* egress slice 1 */
+ <&main_udmap 0xc107>, /* egress slice 1 */
+
+ <&main_udmap 0x4100>, /* ingress slice 0 */
+ <&main_udmap 0x4101>, /* ingress slice 1 */
+ <&main_udmap 0x4102>, /* mgmnt rsp slice 0 */
+ <&main_udmap 0x4103>; /* mgmnt rsp slice 1 */
+ dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3",
+ "tx1-0", "tx1-1", "tx1-2", "tx1-3",
+ "rx0", "rx1";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ icssg0_emac0: port@0 {
+ reg = <0>;
+ phy-handle = <&icssg0_phy0>;
+ phy-mode = "rgmii-id";
+ ti,syscon-rgmii-delay = <&scm_conf 0x4100>;
+ /* Filled in by bootloader */
+ local-mac-address = [00 00 00 00 00 00];
+ };
+ icssg0_emac1: port@1 {
+ reg = <1>;
+ phy-handle = <&icssg0_phy1>;
+ phy-mode = "rgmii-id";
+ ti,syscon-rgmii-delay = <&scm_conf 0x4104>;
+ /* Filled in by bootloader */
+ local-mac-address = [00 00 00 00 00 00];
+ };
+ };
+ };
+
+ /* Ethernet node on PRU-ICSSG1 */
+ icssg1_eth: icssg1-eth {
+ compatible = "ti,am654-icssg-prueth";
+ pinctrl-names = "default";
+ pinctrl-0 = <&icssg1_rgmii_pins_default>;
+ sram = <&msmc_ram>;
+ ti,prus = <&pru1_0>, <&rtu1_0>, <&tx_pru1_0>, <&pru1_1>, <&rtu1_1>, <&tx_pru1_1>;
+ firmware-name = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-pru1-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf",
+ "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf";
+
+ ti,pruss-gp-mux-sel = <2>, /* MII mode */
+ <2>,
+ <2>,
+ <2>, /* MII mode */
+ <2>,
+ <2>;
+
+ ti,mii-g-rt = <&icssg1_mii_g_rt>;
+ ti,mii-rt = <&icssg1_mii_rt>;
+ ti,iep = <&icssg1_iep0>, <&icssg1_iep1>;
+
+ interrupt-parent = <&icssg1_intc>;
+ interrupts = <24 0 2>, <25 1 3>;
+ interrupt-names = "tx_ts0", "tx_ts1";
+
+ dmas = <&main_udmap 0xc200>, /* egress slice 0 */
+ <&main_udmap 0xc201>, /* egress slice 0 */
+ <&main_udmap 0xc202>, /* egress slice 0 */
+ <&main_udmap 0xc203>, /* egress slice 0 */
+ <&main_udmap 0xc204>, /* egress slice 1 */
+ <&main_udmap 0xc205>, /* egress slice 1 */
+ <&main_udmap 0xc206>, /* egress slice 1 */
+ <&main_udmap 0xc207>, /* egress slice 1 */
+
+ <&main_udmap 0x4200>, /* ingress slice 0 */
+ <&main_udmap 0x4201>, /* ingress slice 1 */
+ <&main_udmap 0x4202>, /* mgmnt rsp slice 0 */
+ <&main_udmap 0x4203>; /* mgmnt rsp slice 1 */
+ dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3",
+ "tx1-0", "tx1-1", "tx1-2", "tx1-3",
+ "rx0", "rx1";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ icssg1_emac0: port@0 {
+ reg = <0>;
+ phy-handle = <&icssg1_phy0>;
+ phy-mode = "rgmii-id";
+ ti,syscon-rgmii-delay = <&scm_conf 0x4110>;
+ /* Filled in by bootloader */
+ local-mac-address = [00 00 00 00 00 00];
+ };
+ icssg1_emac1: port@1 {
+ reg = <1>;
+ phy-handle = <&icssg1_phy1>;
+ phy-mode = "rgmii-id";
+ ti,syscon-rgmii-delay = <&scm_conf 0x4114>;
+ /* Filled in by bootloader */
+ local-mac-address = [00 00 00 00 00 00];
+ };
+ };
+ };
+};
+
+&main_pmx0 {
+
+ icssg0_mdio_pins_default: icssg0-mdio-default-pins {
+ pinctrl-single,pins = <
+ AM65X_IOPAD(0x0294, PIN_INPUT, 0) /* (AE26) PRG0_MDIO0_MDIO */
+ AM65X_IOPAD(0x0298, PIN_OUTPUT, 0) /* (AE28) PRG0_MDIO0_MDC */
+ >;
+ };
+
+ icssg0_rgmii_pins_default: icssg0-rgmii-default-pins {
+ pinctrl-single,pins = <
+ AM65X_IOPAD(0x0244, PIN_INPUT, 2) /* (AB28) PRG0_PRU1_GPO0.PRG0_RGMII2_RD0 */
+ AM65X_IOPAD(0x0248, PIN_INPUT, 2) /* (AC28) PRG0_PRU1_GPO1.PRG0_RGMII2_RD1 */
+ AM65X_IOPAD(0x024c, PIN_INPUT, 2) /* (AC27) PRG0_PRU1_GPO2.PRG0_RGMII2_RD2 */
+ AM65X_IOPAD(0x0250, PIN_INPUT, 2) /* (AB26) PRG0_PRU1_GPO3.PRG0_RGMII2_RD3 */
+ AM65X_IOPAD(0x0274, PIN_OUTPUT, 2) /* (AC25) PRG0_PRU1_GPO12.PRG0_RGMII2_TD0 */
+ AM65X_IOPAD(0x0278, PIN_OUTPUT, 2) /* (AD25) PRG0_PRU1_GPO13.PRG0_RGMII2_TD1 */
+ AM65X_IOPAD(0x027c, PIN_OUTPUT, 2) /* (AD24) PRG0_PRU1_GPO14.PRG0_RGMII2_TD2 */
+ AM65X_IOPAD(0x0280, PIN_OUTPUT, 2) /* (AE27) PRG0_PRU1_GPO15.PRG0_RGMII2_TD3 */
+ AM65X_IOPAD(0x0284, PIN_INPUT, 2) /* (AC24) PRG0_PRU1_GPO16.PRG0_RGMII2_TXC */
+ AM65X_IOPAD(0x0270, PIN_OUTPUT, 2) /* (AB24) PRG0_PRU1_GPO11.PRG0_RGMII2_TX_CTL */
+ AM65X_IOPAD(0x025c, PIN_INPUT, 2) /* (AB27) PRG0_PRU1_GPO6.PRG0_RGMII2_RXC */
+ AM65X_IOPAD(0x0254, PIN_INPUT, 2) /* (AA25) PRG0_PRU1_GPO4.PRG0_RGMII2_RX_CTL */
+
+ AM65X_IOPAD(0x01f4, PIN_INPUT, 2) /* (V24) PRG0_PRU0_GPO0.PRG0_RGMII1_RD0 */
+ AM65X_IOPAD(0x01f8, PIN_INPUT, 2) /* (W25) PRG0_PRU0_GPO1.PRG0_RGMII1_RD1 */
+ AM65X_IOPAD(0x01fc, PIN_INPUT, 2) /* (W24) PRG0_PRU0_GPO2.PRG0_RGMII1_RD2 */
+ AM65X_IOPAD(0x0200, PIN_INPUT, 2) /* (AA27) PRG0_PRU0_GPO3.PRG0_RGMII1_RD3 */
+ AM65X_IOPAD(0x0224, PIN_OUTPUT, 2) /* (AD27) PRG0_PRU0_GPO12.PRG0_RGMII1_TD0 */
+ AM65X_IOPAD(0x0228, PIN_OUTPUT, 2) /* (AC26) PRG0_PRU0_GPO13.PRG0_RGMII1_TD1 */
+ AM65X_IOPAD(0x022c, PIN_OUTPUT, 2) /* (AD26) PRG0_PRU0_GPO14.PRG0_RGMII1_TD2 */
+ AM65X_IOPAD(0x0230, PIN_OUTPUT, 2) /* (AA24) PRG0_PRU0_GPO15.PRG0_RGMII1_TD3 */
+ AM65X_IOPAD(0x0234, PIN_INPUT, 2) /* (AD28) PRG0_PRU0_GPO16.PRG0_RGMII1_TXC */
+ AM65X_IOPAD(0x0220, PIN_OUTPUT, 2) /* (AB25) PRG0_PRU0_GPO11.PRG0_RGMII1_TX_CTL */
+ AM65X_IOPAD(0x020c, PIN_INPUT, 2) /* (Y25) PRG0_PRU0_GPO6.PRG0_RGMII1_RXC */
+ AM65X_IOPAD(0x0204, PIN_INPUT, 2) /* (Y24) PRG0_PRU0_GPO4.PRG0_RGMII1_RX_CTL */
+ >;
+ };
+
+ icssg0_iep0_pins_default: icssg0-iep0-default-pins {
+ pinctrl-single,pins = <
+ AM65X_IOPAD(0x0240, PIN_INPUT, 2) /* (U24) PRG0_PRU0_GPO19.PRG0_IEP0_EDC_SYNC_OUT0 */
+ >;
+ };
+
+ icssg1_mdio_pins_default: icssg1-mdio-default-pins {
+ pinctrl-single,pins = <
+ AM65X_IOPAD(0x0180, PIN_INPUT, 0) /* (AD18) PRG1_MDIO0_MDIO */
+ AM65X_IOPAD(0x0184, PIN_OUTPUT, 0) /* (AH18) PRG1_MDIO0_MDC */
+ >;
+ };
+
+ icssg1_rgmii_pins_default: icssg1-rgmii-default-pins {
+ pinctrl-single,pins = <
+ AM65X_IOPAD(0x0130, PIN_INPUT, 2) /* (AH24) PRG1_PRU1_GPO0.PRG1_RGMII2_RD0 */
+ AM65X_IOPAD(0x0134, PIN_INPUT, 2) /* (AH23) PRG1_PRU1_GPO1.PRG1_RGMII2_RD1 */
+ AM65X_IOPAD(0x0138, PIN_INPUT, 2) /* (AG21) PRG1_PRU1_GPO2.PRG1_RGMII2_RD2 */
+ AM65X_IOPAD(0x013c, PIN_INPUT, 2) /* (AH22) PRG1_PRU1_GPO3.PRG1_RGMII2_RD3 */
+ AM65X_IOPAD(0x0160, PIN_OUTPUT, 2) /* (AE20) PRG1_PRU1_GPO12.PRG1_RGMII2_TD0 */
+ AM65X_IOPAD(0x0164, PIN_OUTPUT, 2) /* (AF19) PRG1_PRU1_GPO13.PRG1_RGMII2_TD1 */
+ AM65X_IOPAD(0x0168, PIN_OUTPUT, 2) /* (AH19) PRG1_PRU1_GPO14.PRG1_RGMII2_TD2 */
+ AM65X_IOPAD(0x016c, PIN_OUTPUT, 2) /* (AG19) PRG1_PRU1_GPO15.PRG1_RGMII2_TD3 */
+ AM65X_IOPAD(0x0170, PIN_INPUT, 2) /* (AE19) PRG1_PRU1_GPO16.PRG1_RGMII2_TXC */
+ AM65X_IOPAD(0x015c, PIN_OUTPUT, 2) /* (AC20) PRG1_PRU1_GPO11.PRG1_RGMII2_TX_CTL */
+ AM65X_IOPAD(0x0148, PIN_INPUT, 2) /* (AG22) PRG1_PRU1_GPO6.PRG1_RGMII2_RXC */
+ AM65X_IOPAD(0x0140, PIN_INPUT, 2) /* (AE21) PRG1_PRU1_GPO4.PRG1_RGMII2_RX_CTL */
+
+ AM65X_IOPAD(0x00e0, PIN_INPUT, 2) /* (AE22) PRG1_PRU0_GPO0.PRG1_RGMII1_RD0 */
+ AM65X_IOPAD(0x00e4, PIN_INPUT, 2) /* (AG24) PRG1_PRU0_GPO1.PRG1_RGMII1_RD1 */
+ AM65X_IOPAD(0x00e8, PIN_INPUT, 2) /* (AF23) PRG1_PRU0_GPO2.PRG1_RGMII1_RD2 */
+ AM65X_IOPAD(0x00ec, PIN_INPUT, 2) /* (AD21) PRG1_PRU0_GPO3.PRG1_RGMII1_RD3 */
+ AM65X_IOPAD(0x0110, PIN_OUTPUT, 2) /* (AH20) PRG1_PRU0_GPO12.PRG1_RGMII1_TD0 */
+ AM65X_IOPAD(0x0114, PIN_OUTPUT, 2) /* (AH21) PRG1_PRU0_GPO13.PRG1_RGMII1_TD1 */
+ AM65X_IOPAD(0x0118, PIN_OUTPUT, 2) /* (AG20) PRG1_PRU0_GPO14.PRG1_RGMII1_TD2 */
+ AM65X_IOPAD(0x011c, PIN_OUTPUT, 2) /* (AD19) PRG1_PRU0_GPO15.PRG1_RGMII1_TD3 */
+ AM65X_IOPAD(0x0120, PIN_INPUT, 2) /* (AD20) PRG1_PRU0_GPO16.PRG1_RGMII1_TXC */
+ AM65X_IOPAD(0x010c, PIN_OUTPUT, 2) /* (AF21) PRG1_PRU0_GPO11.PRG1_RGMII1_TX_CTL */
+ AM65X_IOPAD(0x00f8, PIN_INPUT, 2) /* (AF22) PRG1_PRU0_GPO6.PRG1_RGMII1_RXC */
+ AM65X_IOPAD(0x00f0, PIN_INPUT, 2) /* (AG23) PRG1_PRU0_GPO4.PRG1_RGMII1_RX_CTL */
+ >;
+ };
+
+ icssg1_iep0_pins_default: icssg1-iep0-default-pins {
+ pinctrl-single,pins = <
+ AM65X_IOPAD(0x012c, PIN_INPUT, 2) /* (AG26) PRG1_PRU0_GPO19.PRG1_IEP0_EDC_SYNC_OUT0 */
+ >;
+ };
+};
+
+&icssg0_mdio {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&icssg0_mdio_pins_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ icssg0_phy0: ethernet-phy@0 {
+ reg = <0>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ };
+
+ icssg0_phy1: ethernet-phy@3 {
+ reg = <3>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ };
+};
+
+&icssg0_iep0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&icssg0_iep0_pins_default>;
+};
+
+&icssg1_mdio {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&icssg1_mdio_pins_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ icssg1_phy0: ethernet-phy@0 {
+ reg = <0>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ };
+
+ icssg1_phy1: ethernet-phy@3 {
+ reg = <3>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ };
+};
+
+&icssg1_iep0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&icssg1_iep0_pins_default>;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
index 5df5946687b3..1e1a82f9d2b8 100644
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
@@ -553,3 +553,59 @@
};
};
};
+
+&serdes_ln_ctrl {
+ idle-states = <J721S2_SERDES0_LANE0_PCIE1_LANE0>, <J721S2_SERDES0_LANE1_PCIE1_LANE1>,
+ <J721S2_SERDES0_LANE2_USB_SWAP>, <J721S2_SERDES0_LANE3_USB>;
+};
+
+&serdes_refclk {
+ clock-frequency = <100000000>;
+};
+
+&serdes0 {
+ status = "okay";
+
+ serdes0_pcie_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <2>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_PCIE>;
+ resets = <&serdes_wiz0 1>, <&serdes_wiz0 2>;
+ };
+
+ serdes0_usb_link: phy@2 {
+ status = "okay";
+ reg = <2>;
+ cdns,num-lanes = <1>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_USB3>;
+ resets = <&serdes_wiz0 3>;
+ };
+};
+
+&pcie1_rc {
+ status = "okay";
+ reset-gpios = <&exp1 10 GPIO_ACTIVE_HIGH>;
+ phys = <&serdes0_pcie_link>;
+ phy-names = "pcie-phy";
+ num-lanes = <2>;
+};
+
+&usb_serdes_mux {
+ idle-states = <0>; /* USB0 to SERDES lane 2 */
+};
+
+&usbss0 {
+ status = "okay";
+ pinctrl-0 = <&main_usbss0_pins_default>;
+ pinctrl-names = "default";
+ ti,vbus-divider;
+};
+
+&usb0 {
+ dr_mode = "host";
+ maximum-speed = "super-speed";
+ phys = <&serdes0_usb_link>;
+ phy-names = "cdns3,usb3-phy";
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi
index 6c9139f73201..20861a0a46b0 100644
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi
@@ -25,6 +25,108 @@
reg = <0x00 0x9e800000 0x00 0x01800000>;
no-map;
};
+
+ mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa0000000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa0100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa1000000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa1100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa2000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss0_core0_memory_region: r5f-memory@a2100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa2100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa3000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss0_core1_memory_region: r5f-memory@a3100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa3100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss1_core0_memory_region: r5f-memory@a4100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa5000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss1_core1_memory_region: r5f-memory@a5100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa5100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ c71_0_dma_memory_region: c71-dma-memory@a6000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa6000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c71_0_memory_region: c71-memory@a6100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa6100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ c71_1_dma_memory_region: c71-dma-memory@a7000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa7000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c71_1_memory_region: c71-memory@a7100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa7100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ rtos_ipc_memory_region: ipc-memories@a8000000 {
+ reg = <0x00 0xa8000000 0x00 0x01c00000>;
+ alignment = <0x1000>;
+ no-map;
+ };
};
};
@@ -49,3 +151,109 @@
reg = <0x51>;
};
};
+
+&mailbox0_cluster0 {
+ status = "okay";
+ interrupts = <436>;
+ mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster1 {
+ status = "okay";
+ interrupts = <432>;
+ mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster2 {
+ status = "okay";
+ interrupts = <428>;
+ mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster4 {
+ status = "okay";
+ interrupts = <420>;
+ mbox_c71_0: mbox-c71-0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_c71_1: mbox-c71-1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mcu_r5fss0_core0 {
+ mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>;
+ memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
+ <&mcu_r5fss0_core0_memory_region>;
+};
+
+&mcu_r5fss0_core1 {
+ mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>;
+ memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
+ <&mcu_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss0_core0 {
+ mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>;
+ memory-region = <&main_r5fss0_core0_dma_memory_region>,
+ <&main_r5fss0_core0_memory_region>;
+};
+
+&main_r5fss0_core1 {
+ mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>;
+ memory-region = <&main_r5fss0_core1_dma_memory_region>,
+ <&main_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss1_core0 {
+ mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core0>;
+ memory-region = <&main_r5fss1_core0_dma_memory_region>,
+ <&main_r5fss1_core0_memory_region>;
+};
+
+&main_r5fss1_core1 {
+ mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core1>;
+ memory-region = <&main_r5fss1_core1_dma_memory_region>,
+ <&main_r5fss1_core1_memory_region>;
+};
+
+&c71_0 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster4>, <&mbox_c71_0>;
+ memory-region = <&c71_0_dma_memory_region>,
+ <&c71_0_memory_region>;
+};
+
+&c71_1 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster4>, <&mbox_c71_1>;
+ memory-region = <&c71_1_dma_memory_region>,
+ <&c71_1_memory_region>;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am69-sk.dts b/arch/arm64/boot/dts/ti/k3-am69-sk.dts
index 06993709111e..9868c7049bfb 100644
--- a/arch/arm64/boot/dts/ti/k3-am69-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am69-sk.dts
@@ -47,6 +47,150 @@
reg = <0x00 0x9e800000 0x00 0x01800000>;
no-map;
};
+
+ mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa0000000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa0100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa1000000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa1100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa2000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss0_core0_memory_region: r5f-memory@a2100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa2100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa3000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss0_core1_memory_region: r5f-memory@a3100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa3100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss1_core0_memory_region: r5f-memory@a4100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa5000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss1_core1_memory_region: r5f-memory@a5100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa5100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss2_core0_dma_memory_region: r5f-dma-memory@a6000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa6000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss2_core0_memory_region: r5f-memory@a6100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa6100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss2_core1_dma_memory_region: r5f-dma-memory@a7000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa7000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss2_core1_memory_region: r5f-memory@a7100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa7100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ c71_0_dma_memory_region: c71-dma-memory@a8000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa8000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c71_0_memory_region: c71-memory@a8100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa8100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ c71_1_dma_memory_region: c71-dma-memory@a9000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa9000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c71_1_memory_region: c71-memory@a9100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa9100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ c71_2_dma_memory_region: c71-dma-memory@aa000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xaa000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c71_2_memory_region: c71-memory@aa100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xaa100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ c71_3_dma_memory_region: c71-dma-memory@ab000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xab000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c71_3_memory_region: c71-memory@ab100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xab100000 0x00 0xf00000>;
+ no-map;
+ };
};
vusb_main: regulator-vusb-main5v0 {
@@ -107,6 +251,76 @@
states = <1800000 0x0>,
<3300000 0x1>;
};
+
+ dp0_pwr_3v3: regulator-dp0-pwr {
+ compatible = "regulator-fixed";
+ regulator-name = "dp0-pwr";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&dp_pwr_en_pins_default>;
+ gpio = <&main_gpio0 4 0>; /* DP0_3V3 _EN */
+ enable-active-high;
+ };
+
+ dp0: connector-dp0 {
+ compatible = "dp-connector";
+ label = "DP0";
+ type = "full-size";
+ dp-pwr-supply = <&dp0_pwr_3v3>;
+
+ port {
+ dp0_connector_in: endpoint {
+ remote-endpoint = <&dp0_out>;
+ };
+ };
+ };
+
+ connector-hdmi {
+ compatible = "hdmi-connector";
+ label = "hdmi";
+ type = "a";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_hpd_pins_default>;
+ ddc-i2c-bus = <&mcu_i2c1>;
+ hpd-gpios = <&main_gpio0 0 GPIO_ACTIVE_HIGH>; /* HDMI_HPD */
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&tfp410_out>;
+ };
+ };
+ };
+
+ bridge-dvi {
+ compatible = "ti,tfp410";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_pdn_pins_default>;
+ powerdown-gpios = <&wkup_gpio0 14 GPIO_ACTIVE_LOW>; /* HDMI_PDn */
+ ti,deskew = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ tfp410_in: endpoint {
+ remote-endpoint = <&dpi1_out0>;
+ pclk-sample = <1>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ tfp410_out: endpoint {
+ remote-endpoint = <&hdmi_connector_in>;
+ };
+ };
+ };
+ };
};
&main_pmx0 {
@@ -164,6 +378,57 @@
J784S4_IOPAD(0x004, PIN_INPUT, 7) /* (AG36) MCAN12_TX.GPIO0_1 */
>;
};
+
+ dp0_pins_default: dp0-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x014, PIN_INPUT, 13) /* (AG33) MCAN14_TX.DP0_HPD */
+ >;
+ };
+
+ dp_pwr_en_pins_default: dp-pwr-en-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x010, PIN_INPUT, 7) /* (AH33) MCAN13_RX.GPIO0_4 */
+ >;
+ };
+
+ dss_vout0_pins_default: dss-vout0-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x074, PIN_OUTPUT, 2) /* (AC33) MCAN2_TX.VOUT0_DATA0 */
+ J784S4_IOPAD(0x070, PIN_OUTPUT, 2) /* (AH38) MCAN1_RX.VOUT0_DATA1 */
+ J784S4_IOPAD(0x07c, PIN_OUTPUT, 2) /* (AJ38) MCASP0_AXR3.VOUT0_DATA2 */
+ J784S4_IOPAD(0x068, PIN_OUTPUT, 2) /* (AE38) MCAN0_RX.VOUT0_DATA3 */
+ J784S4_IOPAD(0x064, PIN_OUTPUT, 2) /* (AF38) MCAN0_TX.VOUT0_DATA4 */
+ J784S4_IOPAD(0x060, PIN_OUTPUT, 2) /* (AE36) MCASP2_AXR1.VOUT0_DATA5 */
+ J784S4_IOPAD(0x05c, PIN_OUTPUT, 2) /* (AC36) MCASP2_AXR0.VOUT0_DATA6 */
+ J784S4_IOPAD(0x058, PIN_OUTPUT, 2) /* (AE37) MCASP2_AFSX.VOUT0_DATA7 */
+ J784S4_IOPAD(0x054, PIN_OUTPUT, 2) /* (AD37) MCASP2_ACLKX.VOUT0_DATA8 */
+ J784S4_IOPAD(0x050, PIN_OUTPUT, 2) /* (AC37) MCASP1_AXR2.VOUT0_DATA9 */
+ J784S4_IOPAD(0x04c, PIN_OUTPUT, 2) /* (AC32) MCASP1_AXR1.VOUT0_DATA10 */
+ J784S4_IOPAD(0x048, PIN_OUTPUT, 2) /* (AK33) MCASP0_AXR2.VOUT0_DATA11 */
+ J784S4_IOPAD(0x044, PIN_OUTPUT, 2) /* (AG37) MCASP0_AXR1.VOUT0_DATA12 */
+ J784S4_IOPAD(0x040, PIN_OUTPUT, 2) /* (AF37) MCASP0_AXR0.VOUT0_DATA13 */
+ J784S4_IOPAD(0x03c, PIN_OUTPUT, 2) /* (AK38) MCASP0_AFSX.VOUT0_DATA14 */
+ J784S4_IOPAD(0x038, PIN_OUTPUT, 2) /* (AK35) MCASP0_ACLKX.VOUT0_DATA15 */
+ J784S4_IOPAD(0x0c8, PIN_OUTPUT, 2) /* (AJ32) EXT_REFCLK1.VOUT0_DATA16 */
+ J784S4_IOPAD(0x030, PIN_OUTPUT, 2) /* (AK37) GPIO0_12.VOUT0_DATA17 */
+ J784S4_IOPAD(0x02c, PIN_OUTPUT, 2) /* (AL32) GPIO0_11.VOUT0_DATA18 */
+ J784S4_IOPAD(0x028, PIN_OUTPUT, 2) /* (AE33) MCAN16_RX.VOUT0_DATA19 */
+ J784S4_IOPAD(0x024, PIN_OUTPUT, 2) /* (AH34) MCAN16_TX.VOUT0_DATA20 */
+ J784S4_IOPAD(0x020, PIN_OUTPUT, 2) /* (AJ35) MCAN15_RX.VOUT0_DATA21 */
+ J784S4_IOPAD(0x01c, PIN_OUTPUT, 2) /* (AG34) MCAN15_TX.VOUT0_DATA22 */
+ J784S4_IOPAD(0x018, PIN_OUTPUT, 2) /* (AK36) MCAN14_RX.VOUT0_DATA23 */
+ J784S4_IOPAD(0x084, PIN_OUTPUT, 2) /* (AG38) MCASP0_AXR5.VOUT0_DE */
+ J784S4_IOPAD(0x080, PIN_OUTPUT, 2) /* (AK34) MCASP0_AXR4.VOUT0_HSYNC */
+ J784S4_IOPAD(0x078, PIN_OUTPUT, 2) /* (AH37) MCAN2_RX.VOUT0_PCLK */
+ J784S4_IOPAD(0x088, PIN_OUTPUT, 2) /* (AF36) MCASP0_AXR6.VOUT0_VSYNC */
+ >;
+ };
+
+ hdmi_hpd_pins_default: hdmi-hpd-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x000, PIN_INPUT, 7) /* (AN35) EXTINTN.GPIO0_0 */
+ >;
+ };
};
&wkup_pmx2 {
@@ -238,6 +503,21 @@
J784S4_WKUP_IOPAD(0x11c, PIN_INPUT, 7) /* (M34) WKUP_GPIO0_67 */
>;
};
+
+ mcu_i2c1_pins_default: mcu-i2c1-default-pins {
+ pinctrl-single,pins = <
+ /* (L35) WKUP_GPIO0_8.MCU_I2C1_SCL */
+ J784S4_WKUP_IOPAD(0x078, PIN_INPUT_PULLUP, 0)
+ /* (L34) WKUP_GPIO0_9.MCU_I2C1_SDA */
+ J784S4_WKUP_IOPAD(0x07c, PIN_INPUT_PULLUP, 0)
+ >;
+ };
+
+ hdmi_pdn_pins_default: hdmi-pdn-default-pins {
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x090, PIN_INPUT, 7) /* (H37) WKUP_GPIO0_14 */
+ >;
+ };
};
&wkup_pmx3 {
@@ -248,6 +528,90 @@
};
};
+&mailbox0_cluster0 {
+ status = "okay";
+ interrupts = <436>;
+ mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster1 {
+ status = "okay";
+ interrupts = <432>;
+ mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster2 {
+ status = "okay";
+ interrupts = <428>;
+ mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster3 {
+ status = "okay";
+ interrupts = <424>;
+ mbox_main_r5fss2_core0: mbox-main-r5fss2-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_main_r5fss2_core1: mbox-main-r5fss2-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster4 {
+ status = "okay";
+ interrupts = <420>;
+ mbox_c71_0: mbox-c71-0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_c71_1: mbox-c71-1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster5 {
+ status = "okay";
+ interrupts = <416>;
+ mbox_c71_2: mbox-c71-2 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_c71_3: mbox-c71-3 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
&wkup_uart0 {
/* Firmware usage */
status = "reserved";
@@ -362,3 +726,175 @@
phy-mode = "rgmii-rxid";
phy-handle = <&mcu_phy0>;
};
+
+&mcu_r5fss0_core0 {
+ mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>;
+ memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
+ <&mcu_r5fss0_core0_memory_region>;
+};
+
+&mcu_r5fss0_core1 {
+ mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>;
+ memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
+ <&mcu_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss0_core0 {
+ mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>;
+ memory-region = <&main_r5fss0_core0_dma_memory_region>,
+ <&main_r5fss0_core0_memory_region>;
+};
+
+&main_r5fss0_core1 {
+ mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>;
+ memory-region = <&main_r5fss0_core1_dma_memory_region>,
+ <&main_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss1_core0 {
+ mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core0>;
+ memory-region = <&main_r5fss1_core0_dma_memory_region>,
+ <&main_r5fss1_core0_memory_region>;
+};
+
+&main_r5fss1_core1 {
+ mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core1>;
+ memory-region = <&main_r5fss1_core1_dma_memory_region>,
+ <&main_r5fss1_core1_memory_region>;
+};
+
+&main_r5fss2_core0 {
+ mboxes = <&mailbox0_cluster3>, <&mbox_main_r5fss2_core0>;
+ memory-region = <&main_r5fss2_core0_dma_memory_region>,
+ <&main_r5fss2_core0_memory_region>;
+};
+
+&main_r5fss2_core1 {
+ mboxes = <&mailbox0_cluster3>, <&mbox_main_r5fss2_core1>;
+ memory-region = <&main_r5fss2_core1_dma_memory_region>,
+ <&main_r5fss2_core1_memory_region>;
+};
+
+&c71_0 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster4>, <&mbox_c71_0>;
+ memory-region = <&c71_0_dma_memory_region>,
+ <&c71_0_memory_region>;
+};
+
+&c71_1 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster4>, <&mbox_c71_1>;
+ memory-region = <&c71_1_dma_memory_region>,
+ <&c71_1_memory_region>;
+};
+
+&c71_2 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster5>, <&mbox_c71_2>;
+ memory-region = <&c71_2_dma_memory_region>,
+ <&c71_2_memory_region>;
+};
+
+&c71_3 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster5>, <&mbox_c71_3>;
+ memory-region = <&c71_3_dma_memory_region>,
+ <&c71_3_memory_region>;
+};
+
+&wkup_gpio_intr {
+ status = "okay";
+};
+
+&mcu_i2c1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_i2c1_pins_default>;
+ clock-frequency = <100000>;
+};
+
+&serdes_refclk {
+ status = "okay";
+ clock-frequency = <100000000>;
+};
+
+&dss {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dss_vout0_pins_default>;
+ assigned-clocks = <&k3_clks 218 2>,
+ <&k3_clks 218 5>,
+ <&k3_clks 218 14>,
+ <&k3_clks 218 18>;
+ assigned-clock-parents = <&k3_clks 218 3>,
+ <&k3_clks 218 7>,
+ <&k3_clks 218 16>,
+ <&k3_clks 218 22>;
+};
+
+&serdes_wiz4 {
+ status = "okay";
+};
+
+&serdes4 {
+ status = "okay";
+ serdes4_dp_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <4>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_DP>;
+ resets = <&serdes_wiz4 1>, <&serdes_wiz4 2>,
+ <&serdes_wiz4 3>, <&serdes_wiz4 4>;
+ };
+};
+
+&mhdp {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dp0_pins_default>;
+ phys = <&serdes4_dp_link>;
+ phy-names = "dpphy";
+};
+
+&dss_ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* DP */
+ port@0 {
+ reg = <0>;
+
+ dpi0_out: endpoint {
+ remote-endpoint = <&dp0_in>;
+ };
+ };
+
+ /* HDMI */
+ port@1 {
+ reg = <1>;
+
+ dpi1_out0: endpoint {
+ remote-endpoint = <&tfp410_in>;
+ };
+ };
+};
+
+&dp0_ports {
+
+ port@0 {
+ reg = <0>;
+
+ dp0_in: endpoint {
+ remote-endpoint = <&dpi0_out>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+
+ dp0_out: endpoint {
+ remote-endpoint = <&dp0_connector_in>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
index cdb1d6b2a982..264913f83287 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
@@ -91,7 +91,7 @@
};
main_navss: bus@30000000 {
- compatible = "simple-mfd";
+ compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>;
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
index 6ffaf85fa63f..3fc588b848c6 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
@@ -318,7 +318,7 @@
};
mcu_navss: bus@28380000 {
- compatible = "simple-mfd";
+ compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>;
@@ -637,4 +637,11 @@
power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
#thermal-sensor-cells = <1>;
};
+
+ mcu_esm: esm@40800000 {
+ compatible = "ti,j721e-esm";
+ reg = <0x00 0x40800000 0x00 0x1000>;
+ ti,esm-pins = <95>;
+ bootph-pre-ram;
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
index f6c7e1614521..746b9f8b1c64 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
@@ -181,7 +181,7 @@
};
main_navss: bus@30000000 {
- compatible = "simple-mfd";
+ compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>;
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
index 05d6ef127ba7..f7ab7719fc07 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
@@ -440,7 +440,7 @@
};
mcu_navss: bus@28380000 {
- compatible = "simple-mfd";
+ compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>;
@@ -671,4 +671,11 @@
power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
#thermal-sensor-cells = <1>;
};
+
+ mcu_esm: esm@40800000 {
+ compatible = "ti,j721e-esm";
+ reg = <0x00 0x40800000 0x00 0x1000>;
+ ti,esm-pins = <95>;
+ bootph-pre-ram;
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
index 084f8f5b6699..b03731b53a26 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
@@ -775,7 +775,7 @@
};
main_navss: bus@30000000 {
- compatible = "simple-mfd";
+ compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>;
@@ -807,6 +807,7 @@
ti,sci = <&sms>;
ti,sci-dev-id = <265>;
ti,interrupt-ranges = <0 0 256>;
+ ti,unmapped-event-sources = <&main_bcdma_csi>;
};
secure_proxy_main: mailbox@32c00000 {
@@ -1103,6 +1104,22 @@
ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */
};
+ main_bcdma_csi: dma-controller@311a0000 {
+ compatible = "ti,j721s2-dmss-bcdma-csi";
+ reg = <0x00 0x311a0000 0x00 0x100>,
+ <0x00 0x35d00000 0x00 0x20000>,
+ <0x00 0x35c00000 0x00 0x10000>,
+ <0x00 0x35e00000 0x00 0x80000>;
+ reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt";
+ msi-parent = <&main_udmass_inta>;
+ #dma-cells = <3>;
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <225>;
+ ti,sci-rm-range-rchan = <0x21>;
+ ti,sci-rm-range-tchan = <0x22>;
+ status = "disabled";
+ };
+
cpts@310d0000 {
compatible = "ti,j721e-cpts";
reg = <0x0 0x310d0000 0x0 0x400>;
@@ -1695,4 +1712,217 @@
dss_ports: ports {
};
};
+
+ main_r5fss0: r5fss@5c00000 {
+ compatible = "ti,j721s2-r5fss";
+ ti,cluster-mode = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x5c00000 0x00 0x5c00000 0x20000>,
+ <0x5d00000 0x00 0x5d00000 0x20000>;
+ power-domains = <&k3_pds 277 TI_SCI_PD_EXCLUSIVE>;
+
+ main_r5fss0_core0: r5f@5c00000 {
+ compatible = "ti,j721s2-r5f";
+ reg = <0x5c00000 0x00010000>,
+ <0x5c10000 0x00010000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <279>;
+ ti,sci-proc-ids = <0x06 0xff>;
+ resets = <&k3_reset 279 1>;
+ firmware-name = "j721s2-main-r5f0_0-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+
+ main_r5fss0_core1: r5f@5d00000 {
+ compatible = "ti,j721s2-r5f";
+ reg = <0x5d00000 0x00010000>,
+ <0x5d10000 0x00010000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <280>;
+ ti,sci-proc-ids = <0x07 0xff>;
+ resets = <&k3_reset 280 1>;
+ firmware-name = "j721s2-main-r5f0_1-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+ };
+
+ main_r5fss1: r5fss@5e00000 {
+ compatible = "ti,j721s2-r5fss";
+ ti,cluster-mode = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x5e00000 0x00 0x5e00000 0x20000>,
+ <0x5f00000 0x00 0x5f00000 0x20000>;
+ power-domains = <&k3_pds 278 TI_SCI_PD_EXCLUSIVE>;
+
+ main_r5fss1_core0: r5f@5e00000 {
+ compatible = "ti,j721s2-r5f";
+ reg = <0x5e00000 0x00010000>,
+ <0x5e10000 0x00010000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <281>;
+ ti,sci-proc-ids = <0x08 0xff>;
+ resets = <&k3_reset 281 1>;
+ firmware-name = "j721s2-main-r5f1_0-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+
+ main_r5fss1_core1: r5f@5f00000 {
+ compatible = "ti,j721s2-r5f";
+ reg = <0x5f00000 0x00010000>,
+ <0x5f10000 0x00010000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <282>;
+ ti,sci-proc-ids = <0x09 0xff>;
+ resets = <&k3_reset 282 1>;
+ firmware-name = "j721s2-main-r5f1_1-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+ };
+
+ c71_0: dsp@64800000 {
+ compatible = "ti,j721s2-c71-dsp";
+ reg = <0x00 0x64800000 0x00 0x00080000>,
+ <0x00 0x64e00000 0x00 0x0000c000>;
+ reg-names = "l2sram", "l1dram";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <8>;
+ ti,sci-proc-ids = <0x30 0xff>;
+ resets = <&k3_reset 8 1>;
+ firmware-name = "j721s2-c71_0-fw";
+ status = "disabled";
+ };
+
+ c71_1: dsp@65800000 {
+ compatible = "ti,j721s2-c71-dsp";
+ reg = <0x00 0x65800000 0x00 0x00080000>,
+ <0x00 0x65e00000 0x00 0x0000c000>;
+ reg-names = "l2sram", "l1dram";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <11>;
+ ti,sci-proc-ids = <0x31 0xff>;
+ resets = <&k3_reset 11 1>;
+ firmware-name = "j721s2-c71_1-fw";
+ status = "disabled";
+ };
+
+ main_esm: esm@700000 {
+ compatible = "ti,j721e-esm";
+ reg = <0x00 0x700000 0x00 0x1000>;
+ ti,esm-pins = <688>, <689>;
+ bootph-pre-ram;
+ };
+
+ watchdog0: watchdog@2200000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2200000 0x00 0x100>;
+ clocks = <&k3_clks 286 1>;
+ power-domains = <&k3_pds 286 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 286 1>;
+ assigned-clock-parents = <&k3_clks 286 5>;
+ };
+
+ watchdog1: watchdog@2210000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2210000 0x00 0x100>;
+ clocks = <&k3_clks 287 1>;
+ power-domains = <&k3_pds 287 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 287 1>;
+ assigned-clock-parents = <&k3_clks 287 5>;
+ };
+
+ /*
+ * The following RTI instances are coupled with MCU R5Fs, c7x and
+ * GPU so keeping them reserved as these will be used by their
+ * respective firmware
+ */
+ watchdog2: watchdog@22f0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x22f0000 0x00 0x100>;
+ clocks = <&k3_clks 290 1>;
+ power-domains = <&k3_pds 290 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 290 1>;
+ assigned-clock-parents = <&k3_clks 290 5>;
+ /* reserved for GPU */
+ status = "reserved";
+ };
+
+ watchdog3: watchdog@2300000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2300000 0x00 0x100>;
+ clocks = <&k3_clks 288 1>;
+ power-domains = <&k3_pds 288 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 288 1>;
+ assigned-clock-parents = <&k3_clks 288 5>;
+ /* reserved for C7X_0 */
+ status = "reserved";
+ };
+
+ watchdog4: watchdog@2310000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2310000 0x00 0x100>;
+ clocks = <&k3_clks 289 1>;
+ power-domains = <&k3_pds 289 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 289 1>;
+ assigned-clock-parents = <&k3_clks 289 5>;
+ /* reserved for C7X_1 */
+ status = "reserved";
+ };
+
+ watchdog5: watchdog@23c0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x23c0000 0x00 0x100>;
+ clocks = <&k3_clks 291 1>;
+ power-domains = <&k3_pds 291 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 291 1>;
+ assigned-clock-parents = <&k3_clks 291 5>;
+ /* reserved for MAIN_R5F0_0 */
+ status = "reserved";
+ };
+
+ watchdog6: watchdog@23d0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x23d0000 0x00 0x100>;
+ clocks = <&k3_clks 292 1>;
+ power-domains = <&k3_pds 292 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 292 1>;
+ assigned-clock-parents = <&k3_clks 292 5>;
+ /* reserved for MAIN_R5F0_1 */
+ status = "reserved";
+ };
+
+ watchdog7: watchdog@23e0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x23e0000 0x00 0x100>;
+ clocks = <&k3_clks 293 1>;
+ power-domains = <&k3_pds 293 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 293 1>;
+ assigned-clock-parents = <&k3_clks 293 5>;
+ /* reserved for MAIN_R5F1_0 */
+ status = "reserved";
+ };
+
+ watchdog8: watchdog@23f0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x23f0000 0x00 0x100>;
+ clocks = <&k3_clks 294 1>;
+ power-domains = <&k3_pds 294 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 294 1>;
+ assigned-clock-parents = <&k3_clks 294 5>;
+ /* reserved for MAIN_R5F1_1 */
+ status = "reserved";
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
index 2ddad9318554..7254f3bd3634 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
@@ -443,7 +443,7 @@
};
mcu_navss: bus@28380000 {
- compatible = "simple-mfd";
+ compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>;
@@ -655,4 +655,84 @@
power-domains = <&k3_pds 154 TI_SCI_PD_SHARED>;
#thermal-sensor-cells = <1>;
};
+
+ mcu_r5fss0: r5fss@41000000 {
+ compatible = "ti,j721s2-r5fss";
+ ti,cluster-mode = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x41000000 0x00 0x41000000 0x20000>,
+ <0x41400000 0x00 0x41400000 0x20000>;
+ power-domains = <&k3_pds 283 TI_SCI_PD_EXCLUSIVE>;
+
+ mcu_r5fss0_core0: r5f@41000000 {
+ compatible = "ti,j721s2-r5f";
+ reg = <0x41000000 0x00010000>,
+ <0x41010000 0x00010000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <284>;
+ ti,sci-proc-ids = <0x01 0xff>;
+ resets = <&k3_reset 284 1>;
+ firmware-name = "j721s2-mcu-r5f0_0-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+
+ mcu_r5fss0_core1: r5f@41400000 {
+ compatible = "ti,j721s2-r5f";
+ reg = <0x41400000 0x00010000>,
+ <0x41410000 0x00010000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <285>;
+ ti,sci-proc-ids = <0x02 0xff>;
+ resets = <&k3_reset 285 1>;
+ firmware-name = "j721s2-mcu-r5f0_1-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+ };
+
+ mcu_esm: esm@40800000 {
+ compatible = "ti,j721e-esm";
+ reg = <0x00 0x40800000 0x00 0x1000>;
+ ti,esm-pins = <95>;
+ bootph-pre-ram;
+ };
+
+ wkup_esm: esm@42080000 {
+ compatible = "ti,j721e-esm";
+ reg = <0x00 0x42080000 0x00 0x1000>;
+ ti,esm-pins = <63>;
+ bootph-pre-ram;
+ };
+
+ /*
+ * The 2 RTI instances are couple with MCU R5Fs so keeping them
+ * reserved as these will be used by their respective firmware
+ */
+ mcu_watchdog0: watchdog@40600000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x40600000 0x00 0x100>;
+ clocks = <&k3_clks 295 1>;
+ power-domains = <&k3_pds 295 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 295 1>;
+ assigned-clock-parents = <&k3_clks 295 5>;
+ /* reserved for MCU_R5F0_0 */
+ status = "reserved";
+ };
+
+ mcu_watchdog1: watchdog@40610000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x40610000 0x00 0x100>;
+ clocks = <&k3_clks 296 1>;
+ power-domains = <&k3_pds 296 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 296 1>;
+ assigned-clock-parents = <&k3_clks 296 5>;
+ /* reserved for MCU_R5F0_1 */
+ status = "reserved";
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
index a4006f328027..dcad372620b1 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
@@ -29,6 +29,108 @@
alignment = <0x1000>;
no-map;
};
+
+ mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa0000000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa0100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa1000000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa1100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa2000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss0_core0_memory_region: r5f-memory@a2100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa2100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa3000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss0_core1_memory_region: r5f-memory@a3100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa3100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss1_core0_memory_region: r5f-memory@a4100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa5000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss1_core1_memory_region: r5f-memory@a5100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa5100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ c71_0_dma_memory_region: c71-dma-memory@a6000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa6000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c71_0_memory_region: c71-memory@a6100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa6100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ c71_1_dma_memory_region: c71-dma-memory@a7000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa7000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c71_1_memory_region: c71-memory@a7100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa7100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ rtos_ipc_memory_region: ipc-memories@a8000000 {
+ reg = <0x00 0xa8000000 0x00 0x01c00000>;
+ alignment = <0x1000>;
+ no-map;
+ };
};
mux0: mux-controller {
@@ -151,3 +253,109 @@
cdns,read-delay = <4>;
};
};
+
+&mailbox0_cluster0 {
+ status = "okay";
+ interrupts = <436>;
+ mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster1 {
+ status = "okay";
+ interrupts = <432>;
+ mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster2 {
+ status = "okay";
+ interrupts = <428>;
+ mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster4 {
+ status = "okay";
+ interrupts = <420>;
+ mbox_c71_0: mbox-c71-0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_c71_1: mbox-c71-1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mcu_r5fss0_core0 {
+ mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>;
+ memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
+ <&mcu_r5fss0_core0_memory_region>;
+};
+
+&mcu_r5fss0_core1 {
+ mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>;
+ memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
+ <&mcu_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss0_core0 {
+ mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>;
+ memory-region = <&main_r5fss0_core0_dma_memory_region>,
+ <&main_r5fss0_core0_memory_region>;
+};
+
+&main_r5fss0_core1 {
+ mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>;
+ memory-region = <&main_r5fss0_core1_dma_memory_region>,
+ <&main_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss1_core0 {
+ mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core0>;
+ memory-region = <&main_r5fss1_core0_dma_memory_region>,
+ <&main_r5fss1_core0_memory_region>;
+};
+
+&main_r5fss1_core1 {
+ mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core1>;
+ memory-region = <&main_r5fss1_core1_dma_memory_region>,
+ <&main_r5fss1_core1_memory_region>;
+};
+
+&c71_0 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster4>, <&mbox_c71_0>;
+ memory-region = <&c71_0_dma_memory_region>,
+ <&c71_0_memory_region>;
+};
+
+&c71_1 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster4>, <&mbox_c71_1>;
+ memory-region = <&c71_1_dma_memory_region>,
+ <&c71_1_memory_region>;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
index 5991c2e1d994..f1f4c8634ab6 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
@@ -249,6 +249,28 @@
states = <1800000 0x0>,
<3300000 0x1>;
};
+
+ dp0_pwr_3v3: regulator-dp0-prw {
+ compatible = "regulator-fixed";
+ regulator-name = "dp0-pwr";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&exp4 0 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ dp0: connector-dp0 {
+ compatible = "dp-connector";
+ label = "DP0";
+ type = "full-size";
+ dp-pwr-supply = <&dp0_pwr_3v3>;
+
+ port {
+ dp0_connector_in: endpoint {
+ remote-endpoint = <&dp0_out>;
+ };
+ };
+ };
};
&main_pmx0 {
@@ -289,6 +311,19 @@
J784S4_IOPAD(0x020, PIN_INPUT, 7) /* (AJ35) MCAN15_RX.GPIO0_8 */
>;
};
+
+ dp0_pins_default: dp0-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x0cc, PIN_INPUT, 12) /* (AM37) SPI0_CS0.DP0_HPD */
+ >;
+ };
+
+ main_i2c4_pins_default: main-i2c4-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x014, PIN_INPUT_PULLUP, 8) /* (AG33) MCAN14_TX.I2C4_SCL */
+ J784S4_IOPAD(0x010, PIN_INPUT_PULLUP, 8) /* (AH33) MCAN13_RX.I2C4_SDA */
+ >;
+ };
};
&wkup_pmx2 {
@@ -862,3 +897,85 @@
ti,adc-channels = <0 1 2 3 4 5 6 7>;
};
};
+
+&serdes_refclk {
+ status = "okay";
+ clock-frequency = <100000000>;
+};
+
+&dss {
+ status = "okay";
+ assigned-clocks = <&k3_clks 218 2>,
+ <&k3_clks 218 5>,
+ <&k3_clks 218 14>,
+ <&k3_clks 218 18>;
+ assigned-clock-parents = <&k3_clks 218 3>,
+ <&k3_clks 218 7>,
+ <&k3_clks 218 16>,
+ <&k3_clks 218 22>;
+};
+
+&serdes_wiz4 {
+ status = "okay";
+};
+
+&serdes4 {
+ status = "okay";
+ serdes4_dp_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <4>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_DP>;
+ resets = <&serdes_wiz4 1>, <&serdes_wiz4 2>,
+ <&serdes_wiz4 3>, <&serdes_wiz4 4>;
+ };
+};
+
+&mhdp {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dp0_pins_default>;
+ phys = <&serdes4_dp_link>;
+ phy-names = "dpphy";
+};
+
+&dss_ports {
+ /* DP */
+ port {
+ dpi0_out: endpoint {
+ remote-endpoint = <&dp0_in>;
+ };
+ };
+};
+
+&main_i2c4 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c4_pins_default>;
+ clock-frequency = <400000>;
+
+ exp4: gpio@20 {
+ compatible = "ti,tca6408";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+};
+
+&dp0_ports {
+ port@0 {
+ reg = <0>;
+
+ dp0_in: endpoint {
+ remote-endpoint = <&dpi0_out>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+
+ dp0_out: endpoint {
+ remote-endpoint = <&dp0_connector_in>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
index efed2d683f63..d89bcddcfe3d 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
@@ -5,6 +5,21 @@
* Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
*/
+#include <dt-bindings/mux/mux.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/phy/phy-ti.h>
+
+#include "k3-serdes.h"
+
+/ {
+ serdes_refclk: clock-serdes {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ /* To be enabled when serdes_wiz* is functional */
+ status = "disabled";
+ };
+};
+
&cbass_main {
msmc_ram: sram@70000000 {
compatible = "mmio-sram";
@@ -26,6 +41,42 @@
};
};
+ scm_conf: bus@100000 {
+ compatible = "simple-bus";
+ reg = <0x00 0x00100000 0x00 0x1c000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x00 0x00 0x00100000 0x1c000>;
+
+ serdes_ln_ctrl: mux-controller@4080 {
+ compatible = "reg-mux";
+ reg = <0x00004080 0x30>;
+ #mux-control-cells = <1>;
+ mux-reg-masks = <0x4080 0x3>, <0x4084 0x3>, /* SERDES0 lane0/1 select */
+ <0x4088 0x3>, <0x408c 0x3>, /* SERDES0 lane2/3 select */
+ <0x4090 0x3>, <0x4094 0x3>, /* SERDES1 lane0/1 select */
+ <0x4098 0x3>, <0x409c 0x3>, /* SERDES1 lane2/3 select */
+ <0x40a0 0x3>, <0x40a4 0x3>, /* SERDES2 lane0/1 select */
+ <0x40a8 0x3>, <0x40ac 0x3>; /* SERDES2 lane2/3 select */
+ idle-states = <J784S4_SERDES0_LANE0_PCIE1_LANE0>,
+ <J784S4_SERDES0_LANE1_PCIE1_LANE1>,
+ <J784S4_SERDES0_LANE2_IP3_UNUSED>,
+ <J784S4_SERDES0_LANE3_USB>,
+ <J784S4_SERDES1_LANE0_PCIE0_LANE0>,
+ <J784S4_SERDES1_LANE1_PCIE0_LANE1>,
+ <J784S4_SERDES1_LANE2_PCIE0_LANE2>,
+ <J784S4_SERDES1_LANE3_PCIE0_LANE3>,
+ <J784S4_SERDES2_LANE0_IP2_UNUSED>,
+ <J784S4_SERDES2_LANE1_IP2_UNUSED>,
+ <J784S4_SERDES2_LANE2_QSGMII_LANE1>,
+ <J784S4_SERDES2_LANE3_QSGMII_LANE2>,
+ <J784S4_SERDES4_LANE0_EDP_LANE0>,
+ <J784S4_SERDES4_LANE1_EDP_LANE1>,
+ <J784S4_SERDES4_LANE2_EDP_LANE2>,
+ <J784S4_SERDES4_LANE3_EDP_LANE3>;
+ };
+ };
+
gic500: interrupt-controller@1800000 {
compatible = "arm,gic-v3";
#address-cells = <2>;
@@ -669,6 +720,160 @@
status = "disabled";
};
+ serdes_wiz0: wiz@5060000 {
+ compatible = "ti,j784s4-wiz-10g";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ power-domains = <&k3_pds 404 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 404 2>, <&k3_clks 404 6>, <&serdes_refclk>, <&k3_clks 404 5>;
+ clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
+ assigned-clocks = <&k3_clks 404 6>;
+ assigned-clock-parents = <&k3_clks 404 10>;
+ num-lanes = <4>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ ranges = <0x5060000 0x00 0x5060000 0x10000>;
+ status = "disabled";
+
+ serdes0: serdes@5060000 {
+ compatible = "ti,j721e-serdes-10g";
+ reg = <0x05060000 0x010000>;
+ reg-names = "torrent_phy";
+ resets = <&serdes_wiz0 0>;
+ reset-names = "torrent_reset";
+ clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz0 TI_WIZ_PHY_EN_REFCLK>;
+ clock-names = "refclk", "phy_en_refclk";
+ assigned-clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz0 TI_WIZ_PLL1_REFCLK>,
+ <&serdes_wiz0 TI_WIZ_REFCLK_DIG>;
+ assigned-clock-parents = <&k3_clks 404 6>,
+ <&k3_clks 404 6>,
+ <&k3_clks 404 6>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <1>;
+ status = "disabled";
+ };
+ };
+
+ serdes_wiz1: wiz@5070000 {
+ compatible = "ti,j784s4-wiz-10g";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ power-domains = <&k3_pds 405 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 405 2>, <&k3_clks 405 6>, <&serdes_refclk>, <&k3_clks 405 5>;
+ clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
+ assigned-clocks = <&k3_clks 405 6>;
+ assigned-clock-parents = <&k3_clks 405 10>;
+ num-lanes = <4>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ ranges = <0x05070000 0x00 0x05070000 0x10000>;
+ status = "disabled";
+
+ serdes1: serdes@5070000 {
+ compatible = "ti,j721e-serdes-10g";
+ reg = <0x05070000 0x010000>;
+ reg-names = "torrent_phy";
+ resets = <&serdes_wiz1 0>;
+ reset-names = "torrent_reset";
+ clocks = <&serdes_wiz1 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz1 TI_WIZ_PHY_EN_REFCLK>;
+ clock-names = "refclk", "phy_en_refclk";
+ assigned-clocks = <&serdes_wiz1 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz1 TI_WIZ_PLL1_REFCLK>,
+ <&serdes_wiz1 TI_WIZ_REFCLK_DIG>;
+ assigned-clock-parents = <&k3_clks 405 6>,
+ <&k3_clks 405 6>,
+ <&k3_clks 405 6>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <1>;
+ status = "disabled";
+ };
+ };
+
+ serdes_wiz2: wiz@5020000 {
+ compatible = "ti,j784s4-wiz-10g";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ power-domains = <&k3_pds 406 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 406 2>, <&k3_clks 406 6>, <&serdes_refclk>, <&k3_clks 406 5>;
+ clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
+ assigned-clocks = <&k3_clks 406 6>;
+ assigned-clock-parents = <&k3_clks 406 10>;
+ num-lanes = <4>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ ranges = <0x05020000 0x00 0x05020000 0x10000>;
+ status = "disabled";
+
+ serdes2: serdes@5020000 {
+ compatible = "ti,j721e-serdes-10g";
+ reg = <0x05020000 0x010000>;
+ reg-names = "torrent_phy";
+ resets = <&serdes_wiz2 0>;
+ reset-names = "torrent_reset";
+ clocks = <&serdes_wiz2 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz2 TI_WIZ_PHY_EN_REFCLK>;
+ clock-names = "refclk", "phy_en_refclk";
+ assigned-clocks = <&serdes_wiz2 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz2 TI_WIZ_PLL1_REFCLK>,
+ <&serdes_wiz2 TI_WIZ_REFCLK_DIG>;
+ assigned-clock-parents = <&k3_clks 406 6>,
+ <&k3_clks 406 6>,
+ <&k3_clks 406 6>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <1>;
+ status = "disabled";
+ };
+ };
+
+ serdes_wiz4: wiz@5050000 {
+ compatible = "ti,j784s4-wiz-10g";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ power-domains = <&k3_pds 407 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 407 2>, <&k3_clks 407 6>, <&serdes_refclk>, <&k3_clks 407 5>;
+ clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
+ assigned-clocks = <&k3_clks 407 6>;
+ assigned-clock-parents = <&k3_clks 407 10>;
+ num-lanes = <4>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ ranges = <0x05050000 0x00 0x05050000 0x10000>,
+ <0xa030a00 0x00 0xa030a00 0x40>; /* DPTX PHY */
+ status = "disabled";
+
+ serdes4: serdes@5050000 {
+ /*
+ * Note: we also map DPTX PHY registers as the Torrent
+ * needs to manage those.
+ */
+ compatible = "ti,j721e-serdes-10g";
+ reg = <0x05050000 0x010000>,
+ <0x0a030a00 0x40>; /* DPTX PHY */
+ reg-names = "torrent_phy";
+ resets = <&serdes_wiz4 0>;
+ reset-names = "torrent_reset";
+ clocks = <&serdes_wiz4 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz4 TI_WIZ_PHY_EN_REFCLK>;
+ clock-names = "refclk", "phy_en_refclk";
+ assigned-clocks = <&serdes_wiz4 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz4 TI_WIZ_PLL1_REFCLK>,
+ <&serdes_wiz4 TI_WIZ_REFCLK_DIG>;
+ assigned-clock-parents = <&k3_clks 407 6>,
+ <&k3_clks 407 6>,
+ <&k3_clks 407 6>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <1>;
+ status = "disabled";
+ };
+ };
+
main_navss: bus@30000000 {
bootph-all;
compatible = "simple-bus";
@@ -703,6 +908,7 @@
ti,sci = <&sms>;
ti,sci-dev-id = <321>;
ti,interrupt-ranges = <0 0 256>;
+ ti,unmapped-event-sources = <&main_bcdma_csi>;
};
secure_proxy_main: mailbox@32c00000 {
@@ -1000,6 +1206,22 @@
ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */
};
+ main_bcdma_csi: dma-controller@311a0000 {
+ compatible = "ti,j721s2-dmss-bcdma-csi";
+ reg = <0x00 0x311a0000 0x00 0x100>,
+ <0x00 0x35d00000 0x00 0x20000>,
+ <0x00 0x35c00000 0x00 0x10000>,
+ <0x00 0x35e00000 0x00 0x80000>;
+ reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt";
+ msi-parent = <&main_udmass_inta>;
+ #dma-cells = <3>;
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <281>;
+ ti,sci-rm-range-rchan = <0x21>;
+ ti,sci-rm-range-tchan = <0x22>;
+ status = "disabled";
+ };
+
cpts@310d0000 {
compatible = "ti,j721e-cpts";
reg = <0x00 0x310d0000 0x00 0x400>;
@@ -1568,4 +1790,279 @@
firmware-name = "j784s4-c71_3-fw";
status = "disabled";
};
+
+ main_esm: esm@700000 {
+ compatible = "ti,j721e-esm";
+ reg = <0x00 0x700000 0x00 0x1000>;
+ ti,esm-pins = <688>, <689>, <690>, <691>, <692>, <693>, <694>,
+ <695>;
+ bootph-pre-ram;
+ };
+
+ watchdog0: watchdog@2200000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2200000 0x00 0x100>;
+ clocks = <&k3_clks 348 1>;
+ power-domains = <&k3_pds 348 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 348 0>;
+ assigned-clock-parents = <&k3_clks 348 4>;
+ };
+
+ watchdog1: watchdog@2210000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2210000 0x00 0x100>;
+ clocks = <&k3_clks 349 1>;
+ power-domains = <&k3_pds 349 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 349 0>;
+ assigned-clock-parents = <&k3_clks 349 4>;
+ };
+
+ watchdog2: watchdog@2220000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2220000 0x00 0x100>;
+ clocks = <&k3_clks 350 1>;
+ power-domains = <&k3_pds 350 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 350 0>;
+ assigned-clock-parents = <&k3_clks 350 4>;
+ };
+
+ watchdog3: watchdog@2230000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2230000 0x00 0x100>;
+ clocks = <&k3_clks 351 1>;
+ power-domains = <&k3_pds 351 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 351 0>;
+ assigned-clock-parents = <&k3_clks 351 4>;
+ };
+
+ watchdog4: watchdog@2240000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2240000 0x00 0x100>;
+ clocks = <&k3_clks 352 1>;
+ power-domains = <&k3_pds 352 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 352 0>;
+ assigned-clock-parents = <&k3_clks 352 4>;
+ };
+
+ watchdog5: watchdog@2250000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2250000 0x00 0x100>;
+ clocks = <&k3_clks 353 1>;
+ power-domains = <&k3_pds 353 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 353 0>;
+ assigned-clock-parents = <&k3_clks 353 4>;
+ };
+
+ watchdog6: watchdog@2260000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2260000 0x00 0x100>;
+ clocks = <&k3_clks 354 1>;
+ power-domains = <&k3_pds 354 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 354 0>;
+ assigned-clock-parents = <&k3_clks 354 4>;
+ };
+
+ watchdog7: watchdog@2270000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2270000 0x00 0x100>;
+ clocks = <&k3_clks 355 1>;
+ power-domains = <&k3_pds 355 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 355 0>;
+ assigned-clock-parents = <&k3_clks 355 4>;
+ };
+
+ /*
+ * The following RTI instances are coupled with MCU R5Fs, c7x and
+ * GPU so keeping them reserved as these will be used by their
+ * respective firmware
+ */
+ watchdog8: watchdog@22f0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x22f0000 0x00 0x100>;
+ clocks = <&k3_clks 360 1>;
+ power-domains = <&k3_pds 360 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 360 0>;
+ assigned-clock-parents = <&k3_clks 360 4>;
+ /* reserved for GPU */
+ status = "reserved";
+ };
+
+ watchdog9: watchdog@2300000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2300000 0x00 0x100>;
+ clocks = <&k3_clks 356 1>;
+ power-domains = <&k3_pds 356 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 356 0>;
+ assigned-clock-parents = <&k3_clks 356 4>;
+ /* reserved for C7X_0 DSP */
+ status = "reserved";
+ };
+
+ watchdog10: watchdog@2310000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2310000 0x00 0x100>;
+ clocks = <&k3_clks 357 1>;
+ power-domains = <&k3_pds 357 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 357 0>;
+ assigned-clock-parents = <&k3_clks 357 4>;
+ /* reserved for C7X_1 DSP */
+ status = "reserved";
+ };
+
+ watchdog11: watchdog@2320000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2320000 0x00 0x100>;
+ clocks = <&k3_clks 358 1>;
+ power-domains = <&k3_pds 358 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 358 0>;
+ assigned-clock-parents = <&k3_clks 358 4>;
+ /* reserved for C7X_2 DSP */
+ status = "reserved";
+ };
+
+ watchdog12: watchdog@2330000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2330000 0x00 0x100>;
+ clocks = <&k3_clks 359 1>;
+ power-domains = <&k3_pds 359 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 359 0>;
+ assigned-clock-parents = <&k3_clks 359 4>;
+ /* reserved for C7X_3 DSP */
+ status = "reserved";
+ };
+
+ watchdog13: watchdog@23c0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x23c0000 0x00 0x100>;
+ clocks = <&k3_clks 361 1>;
+ power-domains = <&k3_pds 361 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 361 0>;
+ assigned-clock-parents = <&k3_clks 361 4>;
+ /* reserved for MAIN_R5F0_0 */
+ status = "reserved";
+ };
+
+ watchdog14: watchdog@23d0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x23d0000 0x00 0x100>;
+ clocks = <&k3_clks 362 1>;
+ power-domains = <&k3_pds 362 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 362 0>;
+ assigned-clock-parents = <&k3_clks 362 4>;
+ /* reserved for MAIN_R5F0_1 */
+ status = "reserved";
+ };
+
+ watchdog15: watchdog@23e0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x23e0000 0x00 0x100>;
+ clocks = <&k3_clks 363 1>;
+ power-domains = <&k3_pds 363 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 363 0>;
+ assigned-clock-parents = <&k3_clks 363 4>;
+ /* reserved for MAIN_R5F1_0 */
+ status = "reserved";
+ };
+
+ watchdog16: watchdog@23f0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x23f0000 0x00 0x100>;
+ clocks = <&k3_clks 364 1>;
+ power-domains = <&k3_pds 364 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 364 0>;
+ assigned-clock-parents = <&k3_clks 364 4>;
+ /* reserved for MAIN_R5F1_1 */
+ status = "reserved";
+ };
+
+ watchdog17: watchdog@2540000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2540000 0x00 0x100>;
+ clocks = <&k3_clks 365 1>;
+ power-domains = <&k3_pds 365 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 365 0>;
+ assigned-clock-parents = <&k3_clks 366 4>;
+ /* reserved for MAIN_R5F2_0 */
+ status = "reserved";
+ };
+
+ watchdog18: watchdog@2550000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2550000 0x00 0x100>;
+ clocks = <&k3_clks 366 1>;
+ power-domains = <&k3_pds 366 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 366 0>;
+ assigned-clock-parents = <&k3_clks 366 4>;
+ /* reserved for MAIN_R5F2_1 */
+ status = "reserved";
+ };
+
+ mhdp: bridge@a000000 {
+ compatible = "ti,j721e-mhdp8546";
+ reg = <0x0 0xa000000 0x0 0x30a00>,
+ <0x0 0x4f40000 0x0 0x20>;
+ reg-names = "mhdptx", "j721e-intg";
+ clocks = <&k3_clks 217 11>;
+ interrupt-parent = <&gic500>;
+ interrupts = <GIC_SPI 614 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 217 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+
+ dp0_ports: ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /* Remote-endpoints are on the boards so
+ * ports are defined in the platform dt file.
+ */
+ };
+ };
+
+ dss: dss@4a00000 {
+ compatible = "ti,j721e-dss";
+ reg = <0x00 0x04a00000 0x00 0x10000>, /* common_m */
+ <0x00 0x04a10000 0x00 0x10000>, /* common_s0*/
+ <0x00 0x04b00000 0x00 0x10000>, /* common_s1*/
+ <0x00 0x04b10000 0x00 0x10000>, /* common_s2*/
+ <0x00 0x04a20000 0x00 0x10000>, /* vidl1 */
+ <0x00 0x04a30000 0x00 0x10000>, /* vidl2 */
+ <0x00 0x04a50000 0x00 0x10000>, /* vid1 */
+ <0x00 0x04a60000 0x00 0x10000>, /* vid2 */
+ <0x00 0x04a70000 0x00 0x10000>, /* ovr1 */
+ <0x00 0x04a90000 0x00 0x10000>, /* ovr2 */
+ <0x00 0x04ab0000 0x00 0x10000>, /* ovr3 */
+ <0x00 0x04ad0000 0x00 0x10000>, /* ovr4 */
+ <0x00 0x04a80000 0x00 0x10000>, /* vp1 */
+ <0x00 0x04aa0000 0x00 0x10000>, /* vp1 */
+ <0x00 0x04ac0000 0x00 0x10000>, /* vp1 */
+ <0x00 0x04ae0000 0x00 0x10000>, /* vp4 */
+ <0x00 0x04af0000 0x00 0x10000>; /* wb */
+ reg-names = "common_m", "common_s0",
+ "common_s1", "common_s2",
+ "vidl1", "vidl2","vid1","vid2",
+ "ovr1", "ovr2", "ovr3", "ovr4",
+ "vp1", "vp2", "vp3", "vp4",
+ "wb";
+ clocks = <&k3_clks 218 0>,
+ <&k3_clks 218 2>,
+ <&k3_clks 218 5>,
+ <&k3_clks 218 14>,
+ <&k3_clks 218 18>;
+ clock-names = "fck", "vp1", "vp2", "vp3", "vp4";
+ power-domains = <&k3_pds 218 TI_SCI_PD_EXCLUSIVE>;
+ interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "common_m",
+ "common_s0",
+ "common_s1",
+ "common_s2";
+ status = "disabled";
+
+ dss_ports: ports {
+ /* Ports that DSS drives are platform specific
+ * so they are defined in platform dt file.
+ */
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi
index 4ab4018d3695..adb5ea6b9732 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi
@@ -700,4 +700,44 @@
status = "disabled";
};
};
+
+ mcu_esm: esm@40800000 {
+ compatible = "ti,j721e-esm";
+ reg = <0x00 0x40800000 0x00 0x1000>;
+ ti,esm-pins = <95>;
+ bootph-pre-ram;
+ };
+
+ wkup_esm: esm@42080000 {
+ compatible = "ti,j721e-esm";
+ reg = <0x00 0x42080000 0x00 0x1000>;
+ ti,esm-pins = <63>;
+ bootph-pre-ram;
+ };
+
+ /*
+ * The 2 RTI instances are couple with MCU R5Fs so keeping them
+ * reserved as these will be used by their respective firmware
+ */
+ mcu_watchdog0: watchdog@40600000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x40600000 0x00 0x100>;
+ clocks = <&k3_clks 367 1>;
+ power-domains = <&k3_pds 367 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 367 0>;
+ assigned-clock-parents = <&k3_clks 367 4>;
+ /* reserved for MCU_R5F0_0 */
+ status = "reserved";
+ };
+
+ mcu_watchdog1: watchdog@40610000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x40610000 0x00 0x100>;
+ clocks = <&k3_clks 368 1>;
+ power-domains = <&k3_pds 368 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 368 0>;
+ assigned-clock-parents = <&k3_clks 368 4>;
+ /* reserved for MCU_R5F0_1 */
+ status = "reserved";
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-serdes.h b/arch/arm64/boot/dts/ti/k3-serdes.h
index 29167f85c1f6..21b4886c47ba 100644
--- a/arch/arm64/boot/dts/ti/k3-serdes.h
+++ b/arch/arm64/boot/dts/ti/k3-serdes.h
@@ -111,7 +111,7 @@
#define J721S2_SERDES0_LANE2_EDP_LANE2 0x0
#define J721S2_SERDES0_LANE2_PCIE1_LANE2 0x1
-#define J721S2_SERDES0_LANE2_IP3_UNUSED 0x2
+#define J721S2_SERDES0_LANE2_USB_SWAP 0x2
#define J721S2_SERDES0_LANE2_IP4_UNUSED 0x3
#define J721S2_SERDES0_LANE3_EDP_LANE3 0x0
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index a789119e6483..b60aa1f89343 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -423,6 +423,7 @@ CONFIG_MHI_WWAN_MBIM=m
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_ADC=m
CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=m
CONFIG_KEYBOARD_SNVS_PWRKEY=m
CONFIG_KEYBOARD_IMX_SC_KEY=m
CONFIG_KEYBOARD_CROS_EC=y
@@ -599,6 +600,7 @@ CONFIG_PINCTRL_SDM660=y
CONFIG_PINCTRL_SDM670=y
CONFIG_PINCTRL_SDM845=y
CONFIG_PINCTRL_SM6115=y
+CONFIG_PINCTRL_SM6115_LPASS_LPI=m
CONFIG_PINCTRL_SM6125=y
CONFIG_PINCTRL_SM6350=y
CONFIG_PINCTRL_SM6375=y
@@ -606,12 +608,14 @@ CONFIG_PINCTRL_SM8150=y
CONFIG_PINCTRL_SM8250=y
CONFIG_PINCTRL_SM8250_LPASS_LPI=m
CONFIG_PINCTRL_SM8350=y
+CONFIG_PINCTRL_SM8350_LPASS_LPI=m
CONFIG_PINCTRL_SM8450=y
CONFIG_PINCTRL_SM8450_LPASS_LPI=m
CONFIG_PINCTRL_SC8280XP_LPASS_LPI=m
CONFIG_PINCTRL_SM8550=y
CONFIG_PINCTRL_SM8550_LPASS_LPI=m
CONFIG_PINCTRL_LPASS_LPI=m
+CONFIG_GPIO_AGGREGATOR=m
CONFIG_GPIO_ALTERA=m
CONFIG_GPIO_DAVINCI=y
CONFIG_GPIO_DWAPB=y
@@ -683,6 +687,7 @@ CONFIG_QCOM_SPMI_ADC_TM5=m
CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
CONFIG_UNIPHIER_THERMAL=y
+CONFIG_KHADAS_MCU_FAN_THERMAL=m
CONFIG_WATCHDOG=y
CONFIG_SL28CPLD_WATCHDOG=m
CONFIG_ARM_SP805_WATCHDOG=y
@@ -722,9 +727,11 @@ CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_SL28CPLD=y
CONFIG_RZ_MTU3=y
CONFIG_MFD_TPS65219=y
+CONFIG_MFD_TPS6594_I2C=m
CONFIG_MFD_TI_AM335X_TSCADC=m
CONFIG_MFD_ROHM_BD718XX=y
CONFIG_MFD_WCD934X=m
+CONFIG_MFD_KHADAS_MCU=m
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_AXP20X=y
CONFIG_REGULATOR_BD718XX=y
@@ -762,6 +769,8 @@ CONFIG_RC_DEVICES=y
CONFIG_IR_GPIO_CIR=m
CONFIG_IR_MESON=m
CONFIG_IR_SUNXI=m
+CONFIG_MEDIA_CEC_SUPPORT=y
+CONFIG_CEC_MESON_G12A_AO=m
CONFIG_MEDIA_SUPPORT=m
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
@@ -835,6 +844,7 @@ CONFIG_DRM_PANEL_BOE_TV101WUM_NL6=m
CONFIG_DRM_PANEL_LVDS=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_PANEL_EDP=m
+CONFIG_DRM_PANEL_ILITEK_ILI9882T=m
CONFIG_DRM_PANEL_MANTIX_MLAF057WE51=m
CONFIG_DRM_PANEL_RAYDIUM_RM67191=m
CONFIG_DRM_PANEL_SITRONIX_ST7703=m
@@ -846,6 +856,7 @@ CONFIG_DRM_LONTIUM_LT9611UXC=m
CONFIG_DRM_ITE_IT66121=m
CONFIG_DRM_NWL_MIPI_DSI=m
CONFIG_DRM_PARADE_PS8640=m
+CONFIG_DRM_SAMSUNG_DSIM=m
CONFIG_DRM_SII902X=m
CONFIG_DRM_SIMPLE_BRIDGE=m
CONFIG_DRM_THINE_THC63LVD1024=m
@@ -1031,16 +1042,20 @@ CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_MASS_STORAGE=m
CONFIG_TYPEC=m
CONFIG_TYPEC_TCPM=m
CONFIG_TYPEC_TCPCI=m
CONFIG_TYPEC_FUSB302=m
CONFIG_TYPEC_TPS6598X=m
CONFIG_TYPEC_HD3SS3220=m
+CONFIG_TYPEC_QCOM_PMIC=m
CONFIG_TYPEC_UCSI=m
CONFIG_TYPEC_MUX_FSA4480=m
+CONFIG_TYPEC_MUX_NB7VPQ904M=m
CONFIG_UCSI_CCG=m
CONFIG_TYPEC_MUX_GPIO_SBU=m
+CONFIG_TYPEC_DP_ALTMODE=m
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_ARMMMCI=y
@@ -1106,6 +1121,7 @@ CONFIG_RTC_DRV_RK808=m
CONFIG_RTC_DRV_ISL1208=m
CONFIG_RTC_DRV_PCF85063=m
CONFIG_RTC_DRV_PCF85363=m
+CONFIG_RTC_DRV_PCF8563=m
CONFIG_RTC_DRV_M41T80=m
CONFIG_RTC_DRV_BQ32K=m
CONFIG_RTC_DRV_RX8581=m
@@ -1161,6 +1177,7 @@ CONFIG_XEN_GRANT_DEV_ALLOC=y
CONFIG_STAGING=y
CONFIG_STAGING_MEDIA=y
CONFIG_VIDEO_MAX96712=m
+CONFIG_VIDEO_MESON_VDEC=m
CONFIG_CHROME_PLATFORMS=y
CONFIG_CROS_EC=y
CONFIG_CROS_EC_I2C=y
@@ -1335,6 +1352,7 @@ CONFIG_ARCH_R8A774B1=y
CONFIG_ARCH_R9A07G043=y
CONFIG_ARCH_R9A07G044=y
CONFIG_ARCH_R9A07G054=y
+CONFIG_ARCH_R9A08G045=y
CONFIG_ARCH_R9A09G011=y
CONFIG_ROCKCHIP_IODOMAIN=y
CONFIG_ROCKCHIP_PM_DOMAINS=y
@@ -1422,6 +1440,7 @@ CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=m
CONFIG_PHY_QCOM_USB_HS_28NM=m
CONFIG_PHY_QCOM_USB_SS=m
CONFIG_PHY_QCOM_SGMII_ETH=m
+CONFIG_PHY_QCOM_M31_USB=m
CONFIG_PHY_R8A779F0_ETHERNET_SERDES=y
CONFIG_PHY_RCAR_GEN3_PCIE=y
CONFIG_PHY_RCAR_GEN3_USB2=y
@@ -1452,6 +1471,7 @@ CONFIG_QCOM_L3_PMU=y
CONFIG_ARM_SPE_PMU=m
CONFIG_ARM_DMC620_PMU=m
CONFIG_HISI_PMU=y
+CONFIG_MESON_DDR_PMU=m
CONFIG_NVMEM_LAYOUT_SL28_VPD=m
CONFIG_NVMEM_IMX_OCOTP=y
CONFIG_NVMEM_IMX_OCOTP_ELE=m
diff --git a/arch/arm64/configs/hardening.config b/arch/arm64/configs/hardening.config
new file mode 100644
index 000000000000..b0e795208998
--- /dev/null
+++ b/arch/arm64/configs/hardening.config
@@ -0,0 +1,22 @@
+# Basic kernel hardening options (specific to arm64)
+
+# Make sure PAN emulation is enabled.
+CONFIG_ARM64_SW_TTBR0_PAN=y
+
+# Software Shadow Stack or PAC
+CONFIG_SHADOW_CALL_STACK=y
+
+# Pointer authentication (ARMv8.3 and later). If hardware actually supports
+# it, one can turn off CONFIG_STACKPROTECTOR_STRONG with this enabled.
+CONFIG_ARM64_PTR_AUTH=y
+CONFIG_ARM64_PTR_AUTH_KERNEL=y
+
+# Available in ARMv8.5 and later.
+CONFIG_ARM64_BTI=y
+CONFIG_ARM64_BTI_KERNEL=y
+CONFIG_ARM64_MTE=y
+CONFIG_KASAN_HW_TAGS=y
+CONFIG_ARM64_E0PD=y
+
+# Available in ARMv8.7 and later.
+CONFIG_ARM64_EPAN=y
diff --git a/arch/arm64/crypto/nhpoly1305-neon-glue.c b/arch/arm64/crypto/nhpoly1305-neon-glue.c
index cd882c35d925..e4a0b463f080 100644
--- a/arch/arm64/crypto/nhpoly1305-neon-glue.c
+++ b/arch/arm64/crypto/nhpoly1305-neon-glue.c
@@ -34,6 +34,14 @@ static int nhpoly1305_neon_update(struct shash_desc *desc,
return 0;
}
+static int nhpoly1305_neon_digest(struct shash_desc *desc,
+ const u8 *src, unsigned int srclen, u8 *out)
+{
+ return crypto_nhpoly1305_init(desc) ?:
+ nhpoly1305_neon_update(desc, src, srclen) ?:
+ crypto_nhpoly1305_final(desc, out);
+}
+
static struct shash_alg nhpoly1305_alg = {
.base.cra_name = "nhpoly1305",
.base.cra_driver_name = "nhpoly1305-neon",
@@ -44,6 +52,7 @@ static struct shash_alg nhpoly1305_alg = {
.init = crypto_nhpoly1305_init,
.update = nhpoly1305_neon_update,
.final = crypto_nhpoly1305_final,
+ .digest = nhpoly1305_neon_digest,
.setkey = crypto_nhpoly1305_setkey,
.descsize = sizeof(struct nhpoly1305_state),
};
diff --git a/arch/arm64/crypto/sha1-ce-core.S b/arch/arm64/crypto/sha1-ce-core.S
index 889ca0f8972b..9b1f2d82a6fe 100644
--- a/arch/arm64/crypto/sha1-ce-core.S
+++ b/arch/arm64/crypto/sha1-ce-core.S
@@ -62,10 +62,10 @@
.endm
/*
- * int sha1_ce_transform(struct sha1_ce_state *sst, u8 const *src,
- * int blocks)
+ * int __sha1_ce_transform(struct sha1_ce_state *sst, u8 const *src,
+ * int blocks)
*/
-SYM_FUNC_START(sha1_ce_transform)
+SYM_FUNC_START(__sha1_ce_transform)
/* load round constants */
loadrc k0.4s, 0x5a827999, w6
loadrc k1.4s, 0x6ed9eba1, w6
@@ -147,4 +147,4 @@ CPU_LE( rev32 v11.16b, v11.16b )
str dgb, [x0, #16]
mov w0, w2
ret
-SYM_FUNC_END(sha1_ce_transform)
+SYM_FUNC_END(__sha1_ce_transform)
diff --git a/arch/arm64/crypto/sha1-ce-glue.c b/arch/arm64/crypto/sha1-ce-glue.c
index 71fa4f1122d7..1dd93e1fcb39 100644
--- a/arch/arm64/crypto/sha1-ce-glue.c
+++ b/arch/arm64/crypto/sha1-ce-glue.c
@@ -29,18 +29,19 @@ struct sha1_ce_state {
extern const u32 sha1_ce_offsetof_count;
extern const u32 sha1_ce_offsetof_finalize;
-asmlinkage int sha1_ce_transform(struct sha1_ce_state *sst, u8 const *src,
- int blocks);
+asmlinkage int __sha1_ce_transform(struct sha1_ce_state *sst, u8 const *src,
+ int blocks);
-static void __sha1_ce_transform(struct sha1_state *sst, u8 const *src,
- int blocks)
+static void sha1_ce_transform(struct sha1_state *sst, u8 const *src,
+ int blocks)
{
while (blocks) {
int rem;
kernel_neon_begin();
- rem = sha1_ce_transform(container_of(sst, struct sha1_ce_state,
- sst), src, blocks);
+ rem = __sha1_ce_transform(container_of(sst,
+ struct sha1_ce_state,
+ sst), src, blocks);
kernel_neon_end();
src += (blocks - rem) * SHA1_BLOCK_SIZE;
blocks = rem;
@@ -59,7 +60,7 @@ static int sha1_ce_update(struct shash_desc *desc, const u8 *data,
return crypto_sha1_update(desc, data, len);
sctx->finalize = 0;
- sha1_base_do_update(desc, data, len, __sha1_ce_transform);
+ sha1_base_do_update(desc, data, len, sha1_ce_transform);
return 0;
}
@@ -79,9 +80,9 @@ static int sha1_ce_finup(struct shash_desc *desc, const u8 *data,
*/
sctx->finalize = finalize;
- sha1_base_do_update(desc, data, len, __sha1_ce_transform);
+ sha1_base_do_update(desc, data, len, sha1_ce_transform);
if (!finalize)
- sha1_base_do_finalize(desc, __sha1_ce_transform);
+ sha1_base_do_finalize(desc, sha1_ce_transform);
return sha1_base_finish(desc, out);
}
@@ -93,7 +94,7 @@ static int sha1_ce_final(struct shash_desc *desc, u8 *out)
return crypto_sha1_finup(desc, NULL, 0, out);
sctx->finalize = 0;
- sha1_base_do_finalize(desc, __sha1_ce_transform);
+ sha1_base_do_finalize(desc, sha1_ce_transform);
return sha1_base_finish(desc, out);
}
diff --git a/arch/arm64/crypto/sha2-ce-core.S b/arch/arm64/crypto/sha2-ce-core.S
index 491179922f49..fce84d88ddb2 100644
--- a/arch/arm64/crypto/sha2-ce-core.S
+++ b/arch/arm64/crypto/sha2-ce-core.S
@@ -71,11 +71,11 @@
.word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
/*
- * void sha2_ce_transform(struct sha256_ce_state *sst, u8 const *src,
- * int blocks)
+ * int __sha256_ce_transform(struct sha256_ce_state *sst, u8 const *src,
+ * int blocks)
*/
.text
-SYM_FUNC_START(sha2_ce_transform)
+SYM_FUNC_START(__sha256_ce_transform)
/* load round constants */
adr_l x8, .Lsha2_rcon
ld1 { v0.4s- v3.4s}, [x8], #64
@@ -154,4 +154,4 @@ CPU_LE( rev32 v19.16b, v19.16b )
3: st1 {dgav.4s, dgbv.4s}, [x0]
mov w0, w2
ret
-SYM_FUNC_END(sha2_ce_transform)
+SYM_FUNC_END(__sha256_ce_transform)
diff --git a/arch/arm64/crypto/sha2-ce-glue.c b/arch/arm64/crypto/sha2-ce-glue.c
index c57a6119fefc..0a44d2e7ee1f 100644
--- a/arch/arm64/crypto/sha2-ce-glue.c
+++ b/arch/arm64/crypto/sha2-ce-glue.c
@@ -30,18 +30,19 @@ struct sha256_ce_state {
extern const u32 sha256_ce_offsetof_count;
extern const u32 sha256_ce_offsetof_finalize;
-asmlinkage int sha2_ce_transform(struct sha256_ce_state *sst, u8 const *src,
- int blocks);
+asmlinkage int __sha256_ce_transform(struct sha256_ce_state *sst, u8 const *src,
+ int blocks);
-static void __sha2_ce_transform(struct sha256_state *sst, u8 const *src,
+static void sha256_ce_transform(struct sha256_state *sst, u8 const *src,
int blocks)
{
while (blocks) {
int rem;
kernel_neon_begin();
- rem = sha2_ce_transform(container_of(sst, struct sha256_ce_state,
- sst), src, blocks);
+ rem = __sha256_ce_transform(container_of(sst,
+ struct sha256_ce_state,
+ sst), src, blocks);
kernel_neon_end();
src += (blocks - rem) * SHA256_BLOCK_SIZE;
blocks = rem;
@@ -55,8 +56,8 @@ const u32 sha256_ce_offsetof_finalize = offsetof(struct sha256_ce_state,
asmlinkage void sha256_block_data_order(u32 *digest, u8 const *src, int blocks);
-static void __sha256_block_data_order(struct sha256_state *sst, u8 const *src,
- int blocks)
+static void sha256_arm64_transform(struct sha256_state *sst, u8 const *src,
+ int blocks)
{
sha256_block_data_order(sst->state, src, blocks);
}
@@ -68,10 +69,10 @@ static int sha256_ce_update(struct shash_desc *desc, const u8 *data,
if (!crypto_simd_usable())
return sha256_base_do_update(desc, data, len,
- __sha256_block_data_order);
+ sha256_arm64_transform);
sctx->finalize = 0;
- sha256_base_do_update(desc, data, len, __sha2_ce_transform);
+ sha256_base_do_update(desc, data, len, sha256_ce_transform);
return 0;
}
@@ -85,8 +86,8 @@ static int sha256_ce_finup(struct shash_desc *desc, const u8 *data,
if (!crypto_simd_usable()) {
if (len)
sha256_base_do_update(desc, data, len,
- __sha256_block_data_order);
- sha256_base_do_finalize(desc, __sha256_block_data_order);
+ sha256_arm64_transform);
+ sha256_base_do_finalize(desc, sha256_arm64_transform);
return sha256_base_finish(desc, out);
}
@@ -96,9 +97,9 @@ static int sha256_ce_finup(struct shash_desc *desc, const u8 *data,
*/
sctx->finalize = finalize;
- sha256_base_do_update(desc, data, len, __sha2_ce_transform);
+ sha256_base_do_update(desc, data, len, sha256_ce_transform);
if (!finalize)
- sha256_base_do_finalize(desc, __sha2_ce_transform);
+ sha256_base_do_finalize(desc, sha256_ce_transform);
return sha256_base_finish(desc, out);
}
@@ -107,15 +108,22 @@ static int sha256_ce_final(struct shash_desc *desc, u8 *out)
struct sha256_ce_state *sctx = shash_desc_ctx(desc);
if (!crypto_simd_usable()) {
- sha256_base_do_finalize(desc, __sha256_block_data_order);
+ sha256_base_do_finalize(desc, sha256_arm64_transform);
return sha256_base_finish(desc, out);
}
sctx->finalize = 0;
- sha256_base_do_finalize(desc, __sha2_ce_transform);
+ sha256_base_do_finalize(desc, sha256_ce_transform);
return sha256_base_finish(desc, out);
}
+static int sha256_ce_digest(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ sha256_base_init(desc);
+ return sha256_ce_finup(desc, data, len, out);
+}
+
static int sha256_ce_export(struct shash_desc *desc, void *out)
{
struct sha256_ce_state *sctx = shash_desc_ctx(desc);
@@ -155,6 +163,7 @@ static struct shash_alg algs[] = { {
.update = sha256_ce_update,
.final = sha256_ce_final,
.finup = sha256_ce_finup,
+ .digest = sha256_ce_digest,
.export = sha256_ce_export,
.import = sha256_ce_import,
.descsize = sizeof(struct sha256_ce_state),
diff --git a/arch/arm64/crypto/sha256-glue.c b/arch/arm64/crypto/sha256-glue.c
index 9b5c86e07a9a..35356987cc1e 100644
--- a/arch/arm64/crypto/sha256-glue.c
+++ b/arch/arm64/crypto/sha256-glue.c
@@ -27,8 +27,8 @@ asmlinkage void sha256_block_data_order(u32 *digest, const void *data,
unsigned int num_blks);
EXPORT_SYMBOL(sha256_block_data_order);
-static void __sha256_block_data_order(struct sha256_state *sst, u8 const *src,
- int blocks)
+static void sha256_arm64_transform(struct sha256_state *sst, u8 const *src,
+ int blocks)
{
sha256_block_data_order(sst->state, src, blocks);
}
@@ -36,8 +36,8 @@ static void __sha256_block_data_order(struct sha256_state *sst, u8 const *src,
asmlinkage void sha256_block_neon(u32 *digest, const void *data,
unsigned int num_blks);
-static void __sha256_block_neon(struct sha256_state *sst, u8 const *src,
- int blocks)
+static void sha256_neon_transform(struct sha256_state *sst, u8 const *src,
+ int blocks)
{
sha256_block_neon(sst->state, src, blocks);
}
@@ -45,17 +45,15 @@ static void __sha256_block_neon(struct sha256_state *sst, u8 const *src,
static int crypto_sha256_arm64_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
- return sha256_base_do_update(desc, data, len,
- __sha256_block_data_order);
+ return sha256_base_do_update(desc, data, len, sha256_arm64_transform);
}
static int crypto_sha256_arm64_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
if (len)
- sha256_base_do_update(desc, data, len,
- __sha256_block_data_order);
- sha256_base_do_finalize(desc, __sha256_block_data_order);
+ sha256_base_do_update(desc, data, len, sha256_arm64_transform);
+ sha256_base_do_finalize(desc, sha256_arm64_transform);
return sha256_base_finish(desc, out);
}
@@ -98,7 +96,7 @@ static int sha256_update_neon(struct shash_desc *desc, const u8 *data,
if (!crypto_simd_usable())
return sha256_base_do_update(desc, data, len,
- __sha256_block_data_order);
+ sha256_arm64_transform);
while (len > 0) {
unsigned int chunk = len;
@@ -114,7 +112,7 @@ static int sha256_update_neon(struct shash_desc *desc, const u8 *data,
sctx->count % SHA256_BLOCK_SIZE;
kernel_neon_begin();
- sha256_base_do_update(desc, data, chunk, __sha256_block_neon);
+ sha256_base_do_update(desc, data, chunk, sha256_neon_transform);
kernel_neon_end();
data += chunk;
len -= chunk;
@@ -128,13 +126,13 @@ static int sha256_finup_neon(struct shash_desc *desc, const u8 *data,
if (!crypto_simd_usable()) {
if (len)
sha256_base_do_update(desc, data, len,
- __sha256_block_data_order);
- sha256_base_do_finalize(desc, __sha256_block_data_order);
+ sha256_arm64_transform);
+ sha256_base_do_finalize(desc, sha256_arm64_transform);
} else {
if (len)
sha256_update_neon(desc, data, len);
kernel_neon_begin();
- sha256_base_do_finalize(desc, __sha256_block_neon);
+ sha256_base_do_finalize(desc, sha256_neon_transform);
kernel_neon_end();
}
return sha256_base_finish(desc, out);
diff --git a/arch/arm64/crypto/sha512-ce-core.S b/arch/arm64/crypto/sha512-ce-core.S
index b6a3a36e15f5..91ef68b15fcc 100644
--- a/arch/arm64/crypto/sha512-ce-core.S
+++ b/arch/arm64/crypto/sha512-ce-core.S
@@ -102,11 +102,11 @@
.endm
/*
- * void sha512_ce_transform(struct sha512_state *sst, u8 const *src,
- * int blocks)
+ * int __sha512_ce_transform(struct sha512_state *sst, u8 const *src,
+ * int blocks)
*/
.text
-SYM_FUNC_START(sha512_ce_transform)
+SYM_FUNC_START(__sha512_ce_transform)
/* load state */
ld1 {v8.2d-v11.2d}, [x0]
@@ -203,4 +203,4 @@ CPU_LE( rev64 v19.16b, v19.16b )
3: st1 {v8.2d-v11.2d}, [x0]
mov w0, w2
ret
-SYM_FUNC_END(sha512_ce_transform)
+SYM_FUNC_END(__sha512_ce_transform)
diff --git a/arch/arm64/crypto/sha512-ce-glue.c b/arch/arm64/crypto/sha512-ce-glue.c
index 94cb7580deb7..f3431fc62315 100644
--- a/arch/arm64/crypto/sha512-ce-glue.c
+++ b/arch/arm64/crypto/sha512-ce-glue.c
@@ -26,27 +26,27 @@ MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("sha384");
MODULE_ALIAS_CRYPTO("sha512");
-asmlinkage int sha512_ce_transform(struct sha512_state *sst, u8 const *src,
- int blocks);
+asmlinkage int __sha512_ce_transform(struct sha512_state *sst, u8 const *src,
+ int blocks);
asmlinkage void sha512_block_data_order(u64 *digest, u8 const *src, int blocks);
-static void __sha512_ce_transform(struct sha512_state *sst, u8 const *src,
- int blocks)
+static void sha512_ce_transform(struct sha512_state *sst, u8 const *src,
+ int blocks)
{
while (blocks) {
int rem;
kernel_neon_begin();
- rem = sha512_ce_transform(sst, src, blocks);
+ rem = __sha512_ce_transform(sst, src, blocks);
kernel_neon_end();
src += (blocks - rem) * SHA512_BLOCK_SIZE;
blocks = rem;
}
}
-static void __sha512_block_data_order(struct sha512_state *sst, u8 const *src,
- int blocks)
+static void sha512_arm64_transform(struct sha512_state *sst, u8 const *src,
+ int blocks)
{
sha512_block_data_order(sst->state, src, blocks);
}
@@ -54,8 +54,8 @@ static void __sha512_block_data_order(struct sha512_state *sst, u8 const *src,
static int sha512_ce_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
- sha512_block_fn *fn = crypto_simd_usable() ? __sha512_ce_transform
- : __sha512_block_data_order;
+ sha512_block_fn *fn = crypto_simd_usable() ? sha512_ce_transform
+ : sha512_arm64_transform;
sha512_base_do_update(desc, data, len, fn);
return 0;
@@ -64,8 +64,8 @@ static int sha512_ce_update(struct shash_desc *desc, const u8 *data,
static int sha512_ce_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
- sha512_block_fn *fn = crypto_simd_usable() ? __sha512_ce_transform
- : __sha512_block_data_order;
+ sha512_block_fn *fn = crypto_simd_usable() ? sha512_ce_transform
+ : sha512_arm64_transform;
sha512_base_do_update(desc, data, len, fn);
sha512_base_do_finalize(desc, fn);
@@ -74,8 +74,8 @@ static int sha512_ce_finup(struct shash_desc *desc, const u8 *data,
static int sha512_ce_final(struct shash_desc *desc, u8 *out)
{
- sha512_block_fn *fn = crypto_simd_usable() ? __sha512_ce_transform
- : __sha512_block_data_order;
+ sha512_block_fn *fn = crypto_simd_usable() ? sha512_ce_transform
+ : sha512_arm64_transform;
sha512_base_do_finalize(desc, fn);
return sha512_base_finish(desc, out);
diff --git a/arch/arm64/crypto/sha512-glue.c b/arch/arm64/crypto/sha512-glue.c
index 2acff1c7df5d..62f129dea83d 100644
--- a/arch/arm64/crypto/sha512-glue.c
+++ b/arch/arm64/crypto/sha512-glue.c
@@ -23,8 +23,8 @@ asmlinkage void sha512_block_data_order(u64 *digest, const void *data,
unsigned int num_blks);
EXPORT_SYMBOL(sha512_block_data_order);
-static void __sha512_block_data_order(struct sha512_state *sst, u8 const *src,
- int blocks)
+static void sha512_arm64_transform(struct sha512_state *sst, u8 const *src,
+ int blocks)
{
sha512_block_data_order(sst->state, src, blocks);
}
@@ -32,17 +32,15 @@ static void __sha512_block_data_order(struct sha512_state *sst, u8 const *src,
static int sha512_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
- return sha512_base_do_update(desc, data, len,
- __sha512_block_data_order);
+ return sha512_base_do_update(desc, data, len, sha512_arm64_transform);
}
static int sha512_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
if (len)
- sha512_base_do_update(desc, data, len,
- __sha512_block_data_order);
- sha512_base_do_finalize(desc, __sha512_block_data_order);
+ sha512_base_do_update(desc, data, len, sha512_arm64_transform);
+ sha512_base_do_finalize(desc, sha512_arm64_transform);
return sha512_base_finish(desc, out);
}
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 5c8ee5a541d2..4b6d2d52053e 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -6,5 +6,5 @@ generic-y += qspinlock.h
generic-y += parport.h
generic-y += user.h
-generated-y += cpucaps.h
+generated-y += cpucap-defs.h
generated-y += sysreg-defs.h
diff --git a/arch/arm64/include/asm/alternative-macros.h b/arch/arm64/include/asm/alternative-macros.h
index 94b486192e1f..210bb43cff2c 100644
--- a/arch/arm64/include/asm/alternative-macros.h
+++ b/arch/arm64/include/asm/alternative-macros.h
@@ -226,8 +226,8 @@ alternative_endif
static __always_inline bool
alternative_has_cap_likely(const unsigned long cpucap)
{
- compiletime_assert(cpucap < ARM64_NCAPS,
- "cpucap must be < ARM64_NCAPS");
+ if (!cpucap_is_possible(cpucap))
+ return false;
asm_volatile_goto(
ALTERNATIVE_CB("b %l[l_no]", %[cpucap], alt_cb_patch_nops)
@@ -244,8 +244,8 @@ l_no:
static __always_inline bool
alternative_has_cap_unlikely(const unsigned long cpucap)
{
- compiletime_assert(cpucap < ARM64_NCAPS,
- "cpucap must be < ARM64_NCAPS");
+ if (!cpucap_is_possible(cpucap))
+ return false;
asm_volatile_goto(
ALTERNATIVE("nop", "b %l[l_yes]", %[cpucap])
diff --git a/arch/arm64/include/asm/arch_gicv3.h b/arch/arm64/include/asm/arch_gicv3.h
index 01281a5336cf..5f172611654b 100644
--- a/arch/arm64/include/asm/arch_gicv3.h
+++ b/arch/arm64/include/asm/arch_gicv3.h
@@ -79,6 +79,14 @@ static inline u64 gic_read_iar_cavium_thunderx(void)
return 0x3ff;
}
+static u64 __maybe_unused gic_read_iar(void)
+{
+ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_CAVIUM_23154))
+ return gic_read_iar_cavium_thunderx();
+ else
+ return gic_read_iar_common();
+}
+
static inline void gic_write_ctlr(u32 val)
{
write_sysreg_s(val, SYS_ICC_CTLR_EL1);
diff --git a/arch/arm64/include/asm/archrandom.h b/arch/arm64/include/asm/archrandom.h
index b0abc64f86b0..ecdb3cfcd0f8 100644
--- a/arch/arm64/include/asm/archrandom.h
+++ b/arch/arm64/include/asm/archrandom.h
@@ -63,7 +63,7 @@ static __always_inline bool __cpu_has_rng(void)
{
if (unlikely(!system_capabilities_finalized() && !preemptible()))
return this_cpu_has_cap(ARM64_HAS_RNG);
- return cpus_have_const_cap(ARM64_HAS_RNG);
+ return alternative_has_cap_unlikely(ARM64_HAS_RNG);
}
static inline size_t __must_check arch_get_random_longs(unsigned long *v, size_t max_longs)
diff --git a/arch/arm64/include/asm/arm_pmuv3.h b/arch/arm64/include/asm/arm_pmuv3.h
index 18dc2fb3d7b7..c27404fa4418 100644
--- a/arch/arm64/include/asm/arm_pmuv3.h
+++ b/arch/arm64/include/asm/arm_pmuv3.h
@@ -46,12 +46,12 @@ static inline u32 read_pmuver(void)
ID_AA64DFR0_EL1_PMUVer_SHIFT);
}
-static inline void write_pmcr(u32 val)
+static inline void write_pmcr(u64 val)
{
write_sysreg(val, pmcr_el0);
}
-static inline u32 read_pmcr(void)
+static inline u64 read_pmcr(void)
{
return read_sysreg(pmcr_el0);
}
@@ -71,21 +71,6 @@ static inline u64 read_pmccntr(void)
return read_sysreg(pmccntr_el0);
}
-static inline void write_pmxevcntr(u32 val)
-{
- write_sysreg(val, pmxevcntr_el0);
-}
-
-static inline u32 read_pmxevcntr(void)
-{
- return read_sysreg(pmxevcntr_el0);
-}
-
-static inline void write_pmxevtyper(u32 val)
-{
- write_sysreg(val, pmxevtyper_el0);
-}
-
static inline void write_pmcntenset(u32 val)
{
write_sysreg(val, pmcntenset_el0);
@@ -106,7 +91,7 @@ static inline void write_pmintenclr(u32 val)
write_sysreg(val, pmintenclr_el1);
}
-static inline void write_pmccfiltr(u32 val)
+static inline void write_pmccfiltr(u64 val)
{
write_sysreg(val, pmccfiltr_el0);
}
@@ -126,12 +111,12 @@ static inline void write_pmuserenr(u32 val)
write_sysreg(val, pmuserenr_el0);
}
-static inline u32 read_pmceid0(void)
+static inline u64 read_pmceid0(void)
{
return read_sysreg(pmceid0_el0);
}
-static inline u32 read_pmceid1(void)
+static inline u64 read_pmceid1(void)
{
return read_sysreg(pmceid1_el0);
}
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
index d115451ed263..fefac75fa009 100644
--- a/arch/arm64/include/asm/cacheflush.h
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -132,7 +132,7 @@ void flush_dcache_folio(struct folio *);
static __always_inline void icache_inval_all_pou(void)
{
- if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
+ if (alternative_has_cap_unlikely(ARM64_HAS_CACHE_DIC))
return;
asm("ic ialluis");
diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h
index e749838b9c5d..f3034099fd95 100644
--- a/arch/arm64/include/asm/cpu.h
+++ b/arch/arm64/include/asm/cpu.h
@@ -63,12 +63,6 @@ struct cpuinfo_arm64 {
u64 reg_id_aa64smfr0;
struct cpuinfo_32bit aarch32;
-
- /* pseudo-ZCR for recording maximum ZCR_EL1 LEN value: */
- u64 reg_zcr;
-
- /* pseudo-SMCR for recording maximum SMCR_EL1 LEN value: */
- u64 reg_smcr;
};
DECLARE_PER_CPU(struct cpuinfo_arm64, cpu_data);
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
new file mode 100644
index 000000000000..270680e2b5c4
--- /dev/null
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_CPUCAPS_H
+#define __ASM_CPUCAPS_H
+
+#include <asm/cpucap-defs.h>
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+/*
+ * Check whether a cpucap is possible at compiletime.
+ */
+static __always_inline bool
+cpucap_is_possible(const unsigned int cap)
+{
+ compiletime_assert(__builtin_constant_p(cap),
+ "cap must be a constant");
+ compiletime_assert(cap < ARM64_NCAPS,
+ "cap must be < ARM64_NCAPS");
+
+ switch (cap) {
+ case ARM64_HAS_PAN:
+ return IS_ENABLED(CONFIG_ARM64_PAN);
+ case ARM64_HAS_EPAN:
+ return IS_ENABLED(CONFIG_ARM64_EPAN);
+ case ARM64_SVE:
+ return IS_ENABLED(CONFIG_ARM64_SVE);
+ case ARM64_SME:
+ case ARM64_SME2:
+ case ARM64_SME_FA64:
+ return IS_ENABLED(CONFIG_ARM64_SME);
+ case ARM64_HAS_CNP:
+ return IS_ENABLED(CONFIG_ARM64_CNP);
+ case ARM64_HAS_ADDRESS_AUTH:
+ case ARM64_HAS_GENERIC_AUTH:
+ return IS_ENABLED(CONFIG_ARM64_PTR_AUTH);
+ case ARM64_HAS_GIC_PRIO_MASKING:
+ return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI);
+ case ARM64_MTE:
+ return IS_ENABLED(CONFIG_ARM64_MTE);
+ case ARM64_BTI:
+ return IS_ENABLED(CONFIG_ARM64_BTI);
+ case ARM64_HAS_TLB_RANGE:
+ return IS_ENABLED(CONFIG_ARM64_TLB_RANGE);
+ case ARM64_UNMAP_KERNEL_AT_EL0:
+ return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0);
+ case ARM64_WORKAROUND_843419:
+ return IS_ENABLED(CONFIG_ARM64_ERRATUM_843419);
+ case ARM64_WORKAROUND_1742098:
+ return IS_ENABLED(CONFIG_ARM64_ERRATUM_1742098);
+ case ARM64_WORKAROUND_2645198:
+ return IS_ENABLED(CONFIG_ARM64_ERRATUM_2645198);
+ case ARM64_WORKAROUND_2658417:
+ return IS_ENABLED(CONFIG_ARM64_ERRATUM_2658417);
+ case ARM64_WORKAROUND_CAVIUM_23154:
+ return IS_ENABLED(CONFIG_CAVIUM_ERRATUM_23154);
+ case ARM64_WORKAROUND_NVIDIA_CARMEL_CNP:
+ return IS_ENABLED(CONFIG_NVIDIA_CARMEL_CNP_ERRATUM);
+ case ARM64_WORKAROUND_REPEAT_TLBI:
+ return IS_ENABLED(CONFIG_ARM64_WORKAROUND_REPEAT_TLBI);
+ }
+
+ return true;
+}
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 5bba39376055..f6d416fe49b0 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -23,6 +23,7 @@
#include <linux/bug.h>
#include <linux/jump_label.h>
#include <linux/kernel.h>
+#include <linux/cpumask.h>
/*
* CPU feature register tracking
@@ -380,6 +381,7 @@ struct arm64_cpu_capabilities {
* method is robust against being called multiple times.
*/
const struct arm64_cpu_capabilities *match_list;
+ const struct cpumask *cpus;
};
static inline int cpucap_default_scope(const struct arm64_cpu_capabilities *cap)
@@ -438,6 +440,11 @@ unsigned long cpu_get_elf_hwcap2(void);
#define cpu_set_named_feature(name) cpu_set_feature(cpu_feature(name))
#define cpu_have_named_feature(name) cpu_have_feature(cpu_feature(name))
+static __always_inline bool boot_capabilities_finalized(void)
+{
+ return alternative_has_cap_likely(ARM64_ALWAYS_BOOT);
+}
+
static __always_inline bool system_capabilities_finalized(void)
{
return alternative_has_cap_likely(ARM64_ALWAYS_SYSTEM);
@@ -450,6 +457,8 @@ static __always_inline bool system_capabilities_finalized(void)
*/
static __always_inline bool cpus_have_cap(unsigned int num)
{
+ if (__builtin_constant_p(num) && !cpucap_is_possible(num))
+ return false;
if (num >= ARM64_NCAPS)
return false;
return arch_test_bit(num, system_cpucaps);
@@ -458,55 +467,37 @@ static __always_inline bool cpus_have_cap(unsigned int num)
/*
* Test for a capability without a runtime check.
*
- * Before capabilities are finalized, this returns false.
- * After capabilities are finalized, this is patched to avoid a runtime check.
+ * Before boot capabilities are finalized, this will BUG().
+ * After boot capabilities are finalized, this is patched to avoid a runtime
+ * check.
*
* @num must be a compile-time constant.
*/
-static __always_inline bool __cpus_have_const_cap(int num)
+static __always_inline bool cpus_have_final_boot_cap(int num)
{
- if (num >= ARM64_NCAPS)
- return false;
- return alternative_has_cap_unlikely(num);
+ if (boot_capabilities_finalized())
+ return alternative_has_cap_unlikely(num);
+ else
+ BUG();
}
/*
* Test for a capability without a runtime check.
*
- * Before capabilities are finalized, this will BUG().
- * After capabilities are finalized, this is patched to avoid a runtime check.
+ * Before system capabilities are finalized, this will BUG().
+ * After system capabilities are finalized, this is patched to avoid a runtime
+ * check.
*
* @num must be a compile-time constant.
*/
static __always_inline bool cpus_have_final_cap(int num)
{
if (system_capabilities_finalized())
- return __cpus_have_const_cap(num);
+ return alternative_has_cap_unlikely(num);
else
BUG();
}
-/*
- * Test for a capability, possibly with a runtime check for non-hyp code.
- *
- * For hyp code, this behaves the same as cpus_have_final_cap().
- *
- * For non-hyp code:
- * Before capabilities are finalized, this behaves as cpus_have_cap().
- * After capabilities are finalized, this is patched to avoid a runtime check.
- *
- * @num must be a compile-time constant.
- */
-static __always_inline bool cpus_have_const_cap(int num)
-{
- if (is_hyp_code())
- return cpus_have_final_cap(num);
- else if (system_capabilities_finalized())
- return __cpus_have_const_cap(num);
- else
- return cpus_have_cap(num);
-}
-
static inline int __attribute_const__
cpuid_feature_extract_signed_field_width(u64 features, int field, int width)
{
@@ -626,7 +617,9 @@ static inline bool id_aa64pfr1_mte(u64 pfr1)
return val >= ID_AA64PFR1_EL1_MTE_MTE2;
}
-void __init setup_cpu_features(void);
+void __init setup_system_features(void);
+void __init setup_user_features(void);
+
void check_local_cpu_capabilities(void);
u64 read_sanitised_ftr_reg(u32 id);
@@ -735,13 +728,12 @@ static inline bool system_supports_mixed_endian(void)
static __always_inline bool system_supports_fpsimd(void)
{
- return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
+ return alternative_has_cap_likely(ARM64_HAS_FPSIMD);
}
static inline bool system_uses_hw_pan(void)
{
- return IS_ENABLED(CONFIG_ARM64_PAN) &&
- cpus_have_const_cap(ARM64_HAS_PAN);
+ return alternative_has_cap_unlikely(ARM64_HAS_PAN);
}
static inline bool system_uses_ttbr0_pan(void)
@@ -752,26 +744,22 @@ static inline bool system_uses_ttbr0_pan(void)
static __always_inline bool system_supports_sve(void)
{
- return IS_ENABLED(CONFIG_ARM64_SVE) &&
- cpus_have_const_cap(ARM64_SVE);
+ return alternative_has_cap_unlikely(ARM64_SVE);
}
static __always_inline bool system_supports_sme(void)
{
- return IS_ENABLED(CONFIG_ARM64_SME) &&
- cpus_have_const_cap(ARM64_SME);
+ return alternative_has_cap_unlikely(ARM64_SME);
}
static __always_inline bool system_supports_sme2(void)
{
- return IS_ENABLED(CONFIG_ARM64_SME) &&
- cpus_have_const_cap(ARM64_SME2);
+ return alternative_has_cap_unlikely(ARM64_SME2);
}
static __always_inline bool system_supports_fa64(void)
{
- return IS_ENABLED(CONFIG_ARM64_SME) &&
- cpus_have_const_cap(ARM64_SME_FA64);
+ return alternative_has_cap_unlikely(ARM64_SME_FA64);
}
static __always_inline bool system_supports_tpidr2(void)
@@ -781,20 +769,17 @@ static __always_inline bool system_supports_tpidr2(void)
static __always_inline bool system_supports_cnp(void)
{
- return IS_ENABLED(CONFIG_ARM64_CNP) &&
- cpus_have_const_cap(ARM64_HAS_CNP);
+ return alternative_has_cap_unlikely(ARM64_HAS_CNP);
}
static inline bool system_supports_address_auth(void)
{
- return IS_ENABLED(CONFIG_ARM64_PTR_AUTH) &&
- cpus_have_const_cap(ARM64_HAS_ADDRESS_AUTH);
+ return cpus_have_final_boot_cap(ARM64_HAS_ADDRESS_AUTH);
}
static inline bool system_supports_generic_auth(void)
{
- return IS_ENABLED(CONFIG_ARM64_PTR_AUTH) &&
- cpus_have_const_cap(ARM64_HAS_GENERIC_AUTH);
+ return alternative_has_cap_unlikely(ARM64_HAS_GENERIC_AUTH);
}
static inline bool system_has_full_ptr_auth(void)
@@ -804,14 +789,12 @@ static inline bool system_has_full_ptr_auth(void)
static __always_inline bool system_uses_irq_prio_masking(void)
{
- return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) &&
- cpus_have_const_cap(ARM64_HAS_GIC_PRIO_MASKING);
+ return alternative_has_cap_unlikely(ARM64_HAS_GIC_PRIO_MASKING);
}
static inline bool system_supports_mte(void)
{
- return IS_ENABLED(CONFIG_ARM64_MTE) &&
- cpus_have_const_cap(ARM64_MTE);
+ return alternative_has_cap_unlikely(ARM64_MTE);
}
static inline bool system_has_prio_mask_debugging(void)
@@ -822,13 +805,18 @@ static inline bool system_has_prio_mask_debugging(void)
static inline bool system_supports_bti(void)
{
- return IS_ENABLED(CONFIG_ARM64_BTI) && cpus_have_const_cap(ARM64_BTI);
+ return cpus_have_final_cap(ARM64_BTI);
+}
+
+static inline bool system_supports_bti_kernel(void)
+{
+ return IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) &&
+ cpus_have_final_boot_cap(ARM64_BTI);
}
static inline bool system_supports_tlb_range(void)
{
- return IS_ENABLED(CONFIG_ARM64_TLB_RANGE) &&
- cpus_have_const_cap(ARM64_HAS_TLB_RANGE);
+ return alternative_has_cap_unlikely(ARM64_HAS_TLB_RANGE);
}
int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 74d00feb62f0..7c7493cb571f 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -86,7 +86,8 @@
#define ARM_CPU_PART_NEOVERSE_N2 0xD49
#define ARM_CPU_PART_CORTEX_A78C 0xD4B
-#define APM_CPU_PART_POTENZA 0x000
+#define APM_CPU_PART_XGENE 0x000
+#define APM_CPU_VAR_POTENZA 0x00
#define CAVIUM_CPU_PART_THUNDERX 0x0A1
#define CAVIUM_CPU_PART_THUNDERX_81XX 0x0A2
diff --git a/arch/arm64/include/asm/crash_core.h b/arch/arm64/include/asm/crash_core.h
new file mode 100644
index 000000000000..9f5c8d339f44
--- /dev/null
+++ b/arch/arm64/include/asm/crash_core.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _ARM64_CRASH_CORE_H
+#define _ARM64_CRASH_CORE_H
+
+/* Current arm64 boot protocol requires 2MB alignment */
+#define CRASH_ALIGN SZ_2M
+
+#define CRASH_ADDR_LOW_MAX arm64_dma_phys_limit
+#define CRASH_ADDR_HIGH_MAX (PHYS_MASK + 1)
+#endif
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 8df46f186c64..50e5f25d3024 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -32,6 +32,32 @@
#define VFP_STATE_SIZE ((32 * 8) + 4)
#endif
+static inline unsigned long cpacr_save_enable_kernel_sve(void)
+{
+ unsigned long old = read_sysreg(cpacr_el1);
+ unsigned long set = CPACR_EL1_FPEN_EL1EN | CPACR_EL1_ZEN_EL1EN;
+
+ write_sysreg(old | set, cpacr_el1);
+ isb();
+ return old;
+}
+
+static inline unsigned long cpacr_save_enable_kernel_sme(void)
+{
+ unsigned long old = read_sysreg(cpacr_el1);
+ unsigned long set = CPACR_EL1_FPEN_EL1EN | CPACR_EL1_SMEN_EL1EN;
+
+ write_sysreg(old | set, cpacr_el1);
+ isb();
+ return old;
+}
+
+static inline void cpacr_restore(unsigned long cpacr)
+{
+ write_sysreg(cpacr, cpacr_el1);
+ isb();
+}
+
/*
* When we defined the maximum SVE vector length we defined the ABI so
* that the maximum vector length included all the reserved for future
@@ -123,12 +149,12 @@ extern void sme_save_state(void *state, int zt);
extern void sme_load_state(void const *state, int zt);
struct arm64_cpu_capabilities;
-extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
-extern void sme_kernel_enable(const struct arm64_cpu_capabilities *__unused);
-extern void sme2_kernel_enable(const struct arm64_cpu_capabilities *__unused);
-extern void fa64_kernel_enable(const struct arm64_cpu_capabilities *__unused);
+extern void cpu_enable_fpsimd(const struct arm64_cpu_capabilities *__unused);
+extern void cpu_enable_sve(const struct arm64_cpu_capabilities *__unused);
+extern void cpu_enable_sme(const struct arm64_cpu_capabilities *__unused);
+extern void cpu_enable_sme2(const struct arm64_cpu_capabilities *__unused);
+extern void cpu_enable_fa64(const struct arm64_cpu_capabilities *__unused);
-extern u64 read_zcr_features(void);
extern u64 read_smcr_features(void);
/*
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index 521267478d18..cd71e09ea14d 100644
--- a/arch/arm64/include/asm/hwcap.h
+++ b/arch/arm64/include/asm/hwcap.h
@@ -139,6 +139,9 @@
#define KERNEL_HWCAP_SME_F16F16 __khwcap2_feature(SME_F16F16)
#define KERNEL_HWCAP_MOPS __khwcap2_feature(MOPS)
#define KERNEL_HWCAP_HBC __khwcap2_feature(HBC)
+#define KERNEL_HWCAP_SVE_B16B16 __khwcap2_feature(SVE_B16B16)
+#define KERNEL_HWCAP_LRCPC3 __khwcap2_feature(LRCPC3)
+#define KERNEL_HWCAP_LSE128 __khwcap2_feature(LSE128)
/*
* This yields a mask that user programs can use to figure out what
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h
index fac08e18bcd5..50ce8b697ff3 100644
--- a/arch/arm64/include/asm/irq.h
+++ b/arch/arm64/include/asm/irq.h
@@ -6,6 +6,9 @@
#include <asm-generic/irq.h>
+void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu);
+#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace
+
struct pt_regs;
int set_handle_irq(void (*handle_irq)(struct pt_regs *));
diff --git a/arch/arm64/include/asm/irqflags.h b/arch/arm64/include/asm/irqflags.h
index 1f31ec146d16..0a7186a93882 100644
--- a/arch/arm64/include/asm/irqflags.h
+++ b/arch/arm64/include/asm/irqflags.h
@@ -21,12 +21,6 @@
* exceptions should be unmasked.
*/
-static __always_inline bool __irqflags_uses_pmr(void)
-{
- return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) &&
- alternative_has_cap_unlikely(ARM64_HAS_GIC_PRIO_MASKING);
-}
-
static __always_inline void __daif_local_irq_enable(void)
{
barrier();
@@ -49,7 +43,7 @@ static __always_inline void __pmr_local_irq_enable(void)
static inline void arch_local_irq_enable(void)
{
- if (__irqflags_uses_pmr()) {
+ if (system_uses_irq_prio_masking()) {
__pmr_local_irq_enable();
} else {
__daif_local_irq_enable();
@@ -77,7 +71,7 @@ static __always_inline void __pmr_local_irq_disable(void)
static inline void arch_local_irq_disable(void)
{
- if (__irqflags_uses_pmr()) {
+ if (system_uses_irq_prio_masking()) {
__pmr_local_irq_disable();
} else {
__daif_local_irq_disable();
@@ -99,7 +93,7 @@ static __always_inline unsigned long __pmr_local_save_flags(void)
*/
static inline unsigned long arch_local_save_flags(void)
{
- if (__irqflags_uses_pmr()) {
+ if (system_uses_irq_prio_masking()) {
return __pmr_local_save_flags();
} else {
return __daif_local_save_flags();
@@ -118,7 +112,7 @@ static __always_inline bool __pmr_irqs_disabled_flags(unsigned long flags)
static inline bool arch_irqs_disabled_flags(unsigned long flags)
{
- if (__irqflags_uses_pmr()) {
+ if (system_uses_irq_prio_masking()) {
return __pmr_irqs_disabled_flags(flags);
} else {
return __daif_irqs_disabled_flags(flags);
@@ -137,7 +131,7 @@ static __always_inline bool __pmr_irqs_disabled(void)
static inline bool arch_irqs_disabled(void)
{
- if (__irqflags_uses_pmr()) {
+ if (system_uses_irq_prio_masking()) {
return __pmr_irqs_disabled();
} else {
return __daif_irqs_disabled();
@@ -169,7 +163,7 @@ static __always_inline unsigned long __pmr_local_irq_save(void)
static inline unsigned long arch_local_irq_save(void)
{
- if (__irqflags_uses_pmr()) {
+ if (system_uses_irq_prio_masking()) {
return __pmr_local_irq_save();
} else {
return __daif_local_irq_save();
@@ -196,7 +190,7 @@ static __always_inline void __pmr_local_irq_restore(unsigned long flags)
*/
static inline void arch_local_irq_restore(unsigned long flags)
{
- if (__irqflags_uses_pmr()) {
+ if (system_uses_irq_prio_masking()) {
__pmr_local_irq_restore(flags);
} else {
__daif_local_irq_restore(flags);
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 05cd82eeca13..be7a3680dadf 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -37,8 +37,6 @@ struct kprobe_ctlblk {
void arch_remove_kprobe(struct kprobe *);
int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
-int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
void __kretprobe_trampoline(void);
void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 5882b2415596..b85f46a73e21 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -102,7 +102,9 @@
#define HCR_HOST_NVHE_PROTECTED_FLAGS (HCR_HOST_NVHE_FLAGS | HCR_TSC)
#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
-#define HCRX_GUEST_FLAGS (HCRX_EL2_SMPME | HCRX_EL2_TCR2En)
+#define HCRX_GUEST_FLAGS \
+ (HCRX_EL2_SMPME | HCRX_EL2_TCR2En | \
+ (cpus_have_final_cap(ARM64_HAS_MOPS) ? (HCRX_EL2_MSCEn | HCRX_EL2_MCE2) : 0))
#define HCRX_HOST_FLAGS (HCRX_EL2_MSCEn | HCRX_EL2_TCR2En)
/* TCR_EL2 Registers bits */
@@ -344,14 +346,14 @@
*/
#define __HFGRTR_EL2_RES0 (GENMASK(63, 56) | GENMASK(53, 51))
#define __HFGRTR_EL2_MASK GENMASK(49, 0)
-#define __HFGRTR_EL2_nMASK (GENMASK(55, 54) | BIT(50))
+#define __HFGRTR_EL2_nMASK (GENMASK(58, 57) | GENMASK(55, 54) | BIT(50))
#define __HFGWTR_EL2_RES0 (GENMASK(63, 56) | GENMASK(53, 51) | \
BIT(46) | BIT(42) | BIT(40) | BIT(28) | \
GENMASK(26, 25) | BIT(21) | BIT(18) | \
GENMASK(15, 14) | GENMASK(10, 9) | BIT(2))
#define __HFGWTR_EL2_MASK GENMASK(49, 0)
-#define __HFGWTR_EL2_nMASK (GENMASK(55, 54) | BIT(50))
+#define __HFGWTR_EL2_nMASK (GENMASK(58, 57) | GENMASK(55, 54) | BIT(50))
#define __HFGITR_EL2_RES0 GENMASK(63, 57)
#define __HFGITR_EL2_MASK GENMASK(54, 0)
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index 3d6725ff0bf6..78a550537b67 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -54,6 +54,11 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu);
int kvm_inject_nested_sync(struct kvm_vcpu *vcpu, u64 esr_el2);
int kvm_inject_nested_irq(struct kvm_vcpu *vcpu);
+static inline bool vcpu_has_feature(const struct kvm_vcpu *vcpu, int feature)
+{
+ return test_bit(feature, vcpu->kvm->arch.vcpu_features);
+}
+
#if defined(__KVM_VHE_HYPERVISOR__) || defined(__KVM_NVHE_HYPERVISOR__)
static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
{
@@ -62,7 +67,7 @@ static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
#else
static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
{
- return test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features);
+ return vcpu_has_feature(vcpu, KVM_ARM_VCPU_EL1_32BIT);
}
#endif
@@ -71,14 +76,14 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS;
if (has_vhe() || has_hvhe())
vcpu->arch.hcr_el2 |= HCR_E2H;
- if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) {
+ if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN)) {
/* route synchronous external abort exceptions to EL2 */
vcpu->arch.hcr_el2 |= HCR_TEA;
/* trap error record accesses */
vcpu->arch.hcr_el2 |= HCR_TERR;
}
- if (cpus_have_const_cap(ARM64_HAS_STAGE2_FWB)) {
+ if (cpus_have_final_cap(ARM64_HAS_STAGE2_FWB)) {
vcpu->arch.hcr_el2 |= HCR_FWB;
} else {
/*
@@ -465,7 +470,7 @@ static inline bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
{
- return vcpu_read_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
+ return __vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
}
static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
@@ -565,12 +570,6 @@ static __always_inline void kvm_incr_pc(struct kvm_vcpu *vcpu)
vcpu_set_flag((v), e); \
} while (0)
-
-static inline bool vcpu_has_feature(struct kvm_vcpu *vcpu, int feature)
-{
- return test_bit(feature, vcpu->arch.features);
-}
-
static __always_inline void kvm_write_cptr_el2(u64 val)
{
if (has_vhe() || has_hvhe())
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index af06ccb7ee34..824f29f04916 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -78,7 +78,7 @@ extern unsigned int __ro_after_init kvm_sve_max_vl;
int __init kvm_arm_init_sve(void);
u32 __attribute_const__ kvm_target_cpu(void);
-int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
+void kvm_reset_vcpu(struct kvm_vcpu *vcpu);
void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu);
struct kvm_hyp_memcache {
@@ -158,6 +158,16 @@ struct kvm_s2_mmu {
phys_addr_t pgd_phys;
struct kvm_pgtable *pgt;
+ /*
+ * VTCR value used on the host. For a non-NV guest (or a NV
+ * guest that runs in a context where its own S2 doesn't
+ * apply), its T0SZ value reflects that of the IPA size.
+ *
+ * For a shadow S2 MMU, T0SZ reflects the PARange exposed to
+ * the guest.
+ */
+ u64 vtcr;
+
/* The last vcpu id that ran on each physical CPU */
int __percpu *last_vcpu_ran;
@@ -202,12 +212,34 @@ struct kvm_protected_vm {
struct kvm_hyp_memcache teardown_mc;
};
+struct kvm_mpidr_data {
+ u64 mpidr_mask;
+ DECLARE_FLEX_ARRAY(u16, cmpidr_to_idx);
+};
+
+static inline u16 kvm_mpidr_index(struct kvm_mpidr_data *data, u64 mpidr)
+{
+ unsigned long mask = data->mpidr_mask;
+ u64 aff = mpidr & MPIDR_HWID_BITMASK;
+ int nbits, bit, bit_idx = 0;
+ u16 index = 0;
+
+ /*
+ * If this looks like RISC-V's BEXT or x86's PEXT
+ * instructions, it isn't by accident.
+ */
+ nbits = fls(mask);
+ for_each_set_bit(bit, &mask, nbits) {
+ index |= (aff & BIT(bit)) >> (bit - bit_idx);
+ bit_idx++;
+ }
+
+ return index;
+}
+
struct kvm_arch {
struct kvm_s2_mmu mmu;
- /* VTCR_EL2 value for this VM */
- u64 vtcr;
-
/* Interrupt controller */
struct vgic_dist vgic;
@@ -239,15 +271,16 @@ struct kvm_arch {
#define KVM_ARCH_FLAG_VM_COUNTER_OFFSET 5
/* Timer PPIs made immutable */
#define KVM_ARCH_FLAG_TIMER_PPIS_IMMUTABLE 6
- /* SMCCC filter initialized for the VM */
-#define KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED 7
/* Initial ID reg values loaded */
-#define KVM_ARCH_FLAG_ID_REGS_INITIALIZED 8
+#define KVM_ARCH_FLAG_ID_REGS_INITIALIZED 7
unsigned long flags;
/* VM-wide vCPU feature set */
DECLARE_BITMAP(vcpu_features, KVM_VCPU_MAX_FEATURES);
+ /* MPIDR to vcpu index mapping, optional */
+ struct kvm_mpidr_data *mpidr_data;
+
/*
* VM-wide PMU filter, implemented as a bitmap and big enough for
* up to 2^10 events (ARMv8.0) or 2^16 events (ARMv8.1+).
@@ -257,6 +290,9 @@ struct kvm_arch {
cpumask_var_t supported_cpus;
+ /* PMCR_EL0.N value for the guest */
+ u8 pmcr_n;
+
/* Hypercall features firmware registers' descriptor */
struct kvm_smccc_features smccc_feat;
struct maple_tree smccc_filter;
@@ -574,9 +610,6 @@ struct kvm_vcpu_arch {
/* Cache some mmu pages needed inside spinlock regions */
struct kvm_mmu_memory_cache mmu_page_cache;
- /* feature flags */
- DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES);
-
/* Virtual SError ESR to restore when HCR_EL2.VSE is set */
u64 vsesr_el2;
@@ -1025,7 +1058,7 @@ int kvm_arm_pvtime_has_attr(struct kvm_vcpu *vcpu,
extern unsigned int __ro_after_init kvm_arm_vmid_bits;
int __init kvm_arm_vmid_alloc_init(void);
void __init kvm_arm_vmid_alloc_free(void);
-void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid);
+bool kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid);
void kvm_arm_vmid_clear_active(void);
static inline void kvm_arm_pvtime_vcpu_init(struct kvm_vcpu_arch *vcpu_arch)
@@ -1052,7 +1085,7 @@ static inline void kvm_init_host_cpu_context(struct kvm_cpu_context *cpu_ctxt)
static inline bool kvm_system_needs_idmapped_vectors(void)
{
- return cpus_have_const_cap(ARM64_SPECTRE_V3A);
+ return cpus_have_final_cap(ARM64_SPECTRE_V3A);
}
static inline void kvm_arch_sync_events(struct kvm *kvm) {}
@@ -1078,6 +1111,8 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
struct kvm_arm_copy_mte_tags *copy_tags);
int kvm_vm_ioctl_set_counter_offset(struct kvm *kvm,
struct kvm_arm_counter_offset *offset);
+int kvm_vm_ioctl_get_reg_writable_masks(struct kvm *kvm,
+ struct reg_mask_range *range);
/* Guest/host FPSIMD coordination helpers */
int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);
@@ -1109,8 +1144,8 @@ static inline bool kvm_set_pmuserenr(u64 val)
}
#endif
-void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu);
-void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu);
+void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu);
+void kvm_vcpu_put_vhe(struct kvm_vcpu *vcpu);
int __init kvm_set_ipa_limit(void);
diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index 66efd67ea7e8..145ce73fc16c 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -93,6 +93,8 @@ void __timer_disable_traps(struct kvm_vcpu *vcpu);
void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt);
void __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt);
#else
+void __vcpu_load_switch_sysregs(struct kvm_vcpu *vcpu);
+void __vcpu_put_switch_sysregs(struct kvm_vcpu *vcpu);
void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt);
void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt);
void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt);
@@ -111,11 +113,6 @@ void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
void __sve_restore_state(void *sve_pffr, u32 *fpsr);
-#ifndef __KVM_NVHE_HYPERVISOR__
-void activate_traps_vhe_load(struct kvm_vcpu *vcpu);
-void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu);
-#endif
-
u64 __guest_enter(struct kvm_vcpu *vcpu);
bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt, u32 func_id);
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 96a80e8f6226..49e0d4b36bd0 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -150,9 +150,9 @@ static __always_inline unsigned long __kern_hyp_va(unsigned long v)
*/
#define KVM_PHYS_SHIFT (40)
-#define kvm_phys_shift(kvm) VTCR_EL2_IPA(kvm->arch.vtcr)
-#define kvm_phys_size(kvm) (_AC(1, ULL) << kvm_phys_shift(kvm))
-#define kvm_phys_mask(kvm) (kvm_phys_size(kvm) - _AC(1, ULL))
+#define kvm_phys_shift(mmu) VTCR_EL2_IPA((mmu)->vtcr)
+#define kvm_phys_size(mmu) (_AC(1, ULL) << kvm_phys_shift(mmu))
+#define kvm_phys_mask(mmu) (kvm_phys_size(mmu) - _AC(1, ULL))
#include <asm/kvm_pgtable.h>
#include <asm/stage2_pgtable.h>
@@ -218,22 +218,47 @@ static inline void __clean_dcache_guest_page(void *va, size_t size)
* faulting in pages. Furthermore, FWB implies IDC, so cleaning to
* PoU is not required either in this case.
*/
- if (cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
+ if (cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
return;
kvm_flush_dcache_to_poc(va, size);
}
+static inline size_t __invalidate_icache_max_range(void)
+{
+ u8 iminline;
+ u64 ctr;
+
+ asm volatile(ALTERNATIVE_CB("movz %0, #0\n"
+ "movk %0, #0, lsl #16\n"
+ "movk %0, #0, lsl #32\n"
+ "movk %0, #0, lsl #48\n",
+ ARM64_ALWAYS_SYSTEM,
+ kvm_compute_final_ctr_el0)
+ : "=r" (ctr));
+
+ iminline = SYS_FIELD_GET(CTR_EL0, IminLine, ctr) + 2;
+ return MAX_DVM_OPS << iminline;
+}
+
static inline void __invalidate_icache_guest_page(void *va, size_t size)
{
- if (icache_is_aliasing()) {
- /* any kind of VIPT cache */
+ /*
+ * VPIPT I-cache maintenance must be done from EL2. See comment in the
+ * nVHE flavor of __kvm_tlb_flush_vmid_ipa().
+ */
+ if (icache_is_vpipt() && read_sysreg(CurrentEL) != CurrentEL_EL2)
+ return;
+
+ /*
+ * Blow the whole I-cache if it is aliasing (i.e. VIPT) or the
+ * invalidation range exceeds our arbitrary limit on invadations by
+ * cache line.
+ */
+ if (icache_is_aliasing() || size > __invalidate_icache_max_range())
icache_inval_all_pou();
- } else if (read_sysreg(CurrentEL) != CurrentEL_EL1 ||
- !icache_is_vpipt()) {
- /* PIPT or VPIPT at EL2 (see comment in __kvm_tlb_flush_vmid_ipa) */
+ else
icache_inval_pou((unsigned long)va, (unsigned long)va + size);
- }
}
void kvm_set_way_flush(struct kvm_vcpu *vcpu);
@@ -299,7 +324,7 @@ static __always_inline u64 kvm_get_vttbr(struct kvm_s2_mmu *mmu)
static __always_inline void __load_stage2(struct kvm_s2_mmu *mmu,
struct kvm_arch *arch)
{
- write_sysreg(arch->vtcr, vtcr_el2);
+ write_sysreg(mmu->vtcr, vtcr_el2);
write_sysreg(kvm_get_vttbr(mmu), vttbr_el2);
/*
diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm/kvm_nested.h
index fa23cc9c2adc..6cec8e9c6c91 100644
--- a/arch/arm64/include/asm/kvm_nested.h
+++ b/arch/arm64/include/asm/kvm_nested.h
@@ -2,13 +2,14 @@
#ifndef __ARM64_KVM_NESTED_H
#define __ARM64_KVM_NESTED_H
+#include <asm/kvm_emulate.h>
#include <linux/kvm_host.h>
static inline bool vcpu_has_nv(const struct kvm_vcpu *vcpu)
{
return (!__is_defined(__KVM_NVHE_HYPERVISOR__) &&
cpus_have_final_cap(ARM64_HAS_NESTED_VIRT) &&
- test_bit(KVM_ARM_VCPU_HAS_EL2, vcpu->arch.features));
+ vcpu_has_feature(vcpu, KVM_ARM_VCPU_HAS_EL2));
}
extern bool __check_nv_sr_forward(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/include/asm/lse.h b/arch/arm64/include/asm/lse.h
index cbbcdc35c4cd..3129a5819d0e 100644
--- a/arch/arm64/include/asm/lse.h
+++ b/arch/arm64/include/asm/lse.h
@@ -16,14 +16,9 @@
#include <asm/atomic_lse.h>
#include <asm/cpucaps.h>
-static __always_inline bool system_uses_lse_atomics(void)
-{
- return alternative_has_cap_likely(ARM64_HAS_LSE_ATOMICS);
-}
-
#define __lse_ll_sc_body(op, ...) \
({ \
- system_uses_lse_atomics() ? \
+ alternative_has_cap_likely(ARM64_HAS_LSE_ATOMICS) ? \
__lse_##op(__VA_ARGS__) : \
__ll_sc_##op(__VA_ARGS__); \
})
@@ -34,8 +29,6 @@ static __always_inline bool system_uses_lse_atomics(void)
#else /* CONFIG_ARM64_LSE_ATOMICS */
-static inline bool system_uses_lse_atomics(void) { return false; }
-
#define __lse_ll_sc_body(op, ...) __ll_sc_##op(__VA_ARGS__)
#define ARM64_LSE_ATOMIC_INSN(llsc, lse) llsc
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 94b68850cb9f..2fcf51231d6e 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -57,7 +57,7 @@ typedef struct {
static inline bool arm64_kernel_unmapped_at_el0(void)
{
- return cpus_have_const_cap(ARM64_UNMAP_KERNEL_AT_EL0);
+ return alternative_has_cap_unlikely(ARM64_UNMAP_KERNEL_AT_EL0);
}
extern void arm64_memblock_init(void);
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index a6fb325424e7..9ce4200508b1 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -152,7 +152,7 @@ static inline void cpu_install_ttbr0(phys_addr_t ttbr0, unsigned long t0sz)
* Atomically replaces the active TTBR1_EL1 PGD with a new VA-compatible PGD,
* avoiding the possibility of conflicting TLB entries being allocated.
*/
-static inline void cpu_replace_ttbr1(pgd_t *pgdp, pgd_t *idmap)
+static inline void __cpu_replace_ttbr1(pgd_t *pgdp, pgd_t *idmap, bool cnp)
{
typedef void (ttbr_replace_func)(phys_addr_t);
extern ttbr_replace_func idmap_cpu_replace_ttbr1;
@@ -162,17 +162,8 @@ static inline void cpu_replace_ttbr1(pgd_t *pgdp, pgd_t *idmap)
/* phys_to_ttbr() zeros lower 2 bits of ttbr with 52-bit PA */
phys_addr_t ttbr1 = phys_to_ttbr(virt_to_phys(pgdp));
- if (system_supports_cnp() && !WARN_ON(pgdp != lm_alias(swapper_pg_dir))) {
- /*
- * cpu_replace_ttbr1() is used when there's a boot CPU
- * up (i.e. cpufeature framework is not up yet) and
- * latter only when we enable CNP via cpufeature's
- * enable() callback.
- * Also we rely on the system_cpucaps bit being set before
- * calling the enable() function.
- */
+ if (cnp)
ttbr1 |= TTBR_CNP_BIT;
- }
replace_phys = (void *)__pa_symbol(idmap_cpu_replace_ttbr1);
@@ -189,6 +180,21 @@ static inline void cpu_replace_ttbr1(pgd_t *pgdp, pgd_t *idmap)
cpu_uninstall_idmap();
}
+static inline void cpu_enable_swapper_cnp(void)
+{
+ __cpu_replace_ttbr1(lm_alias(swapper_pg_dir), idmap_pg_dir, true);
+}
+
+static inline void cpu_replace_ttbr1(pgd_t *pgdp, pgd_t *idmap)
+{
+ /*
+ * Only for early TTBR1 replacement before cpucaps are finalized and
+ * before we've decided whether to use CNP.
+ */
+ WARN_ON(system_capabilities_finalized());
+ __cpu_replace_ttbr1(pgdp, idmap, false);
+}
+
/*
* It would be nice to return ASIDs back to the allocator, but unfortunately
* that introduces a race with a generation rollover where we could erroneously
diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h
index bfa6638b4c93..79550b22ba19 100644
--- a/arch/arm64/include/asm/module.h
+++ b/arch/arm64/include/asm/module.h
@@ -44,8 +44,7 @@ struct plt_entry {
static inline bool is_forbidden_offset_for_adrp(void *place)
{
- return IS_ENABLED(CONFIG_ARM64_ERRATUM_843419) &&
- cpus_have_const_cap(ARM64_WORKAROUND_843419) &&
+ return cpus_have_final_cap(ARM64_WORKAROUND_843419) &&
((u64)place & 0xfff) >= 0xff8;
}
diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h
index 4cedbaa16f41..91fbd5c8a391 100644
--- a/arch/arm64/include/asm/mte.h
+++ b/arch/arm64/include/asm/mte.h
@@ -90,7 +90,7 @@ static inline bool try_page_mte_tagging(struct page *page)
}
void mte_zero_clear_page_tags(void *addr);
-void mte_sync_tags(pte_t pte);
+void mte_sync_tags(pte_t pte, unsigned int nr_pages);
void mte_copy_page_tags(void *kto, const void *kfrom);
void mte_thread_init_user(void);
void mte_thread_switch(struct task_struct *next);
@@ -122,7 +122,7 @@ static inline bool try_page_mte_tagging(struct page *page)
static inline void mte_zero_clear_page_tags(void *addr)
{
}
-static inline void mte_sync_tags(pte_t pte)
+static inline void mte_sync_tags(pte_t pte, unsigned int nr_pages)
{
}
static inline void mte_copy_page_tags(void *kto, const void *kfrom)
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index eed814b00a38..e9624f6326dd 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -75,11 +75,7 @@ extern bool arm64_use_ng_mappings;
* If we have userspace only BTI we don't want to mark kernel pages
* guarded even if the system does support BTI.
*/
-#ifdef CONFIG_ARM64_BTI_KERNEL
-#define PTE_MAYBE_GP (system_supports_bti() ? PTE_GP : 0)
-#else
-#define PTE_MAYBE_GP 0
-#endif
+#define PTE_MAYBE_GP (system_supports_bti_kernel() ? PTE_GP : 0)
#define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
#define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL_RO)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 7f7d9b1df4e5..79ce70fbb751 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -325,8 +325,7 @@ static inline void __check_safe_pte_update(struct mm_struct *mm, pte_t *ptep,
__func__, pte_val(old_pte), pte_val(pte));
}
-static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep, pte_t pte)
+static inline void __sync_cache_and_tags(pte_t pte, unsigned int nr_pages)
{
if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte))
__sync_icache_dcache(pte);
@@ -339,24 +338,22 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
*/
if (system_supports_mte() && pte_access_permitted(pte, false) &&
!pte_special(pte) && pte_tagged(pte))
- mte_sync_tags(pte);
-
- __check_safe_pte_update(mm, ptep, pte);
-
- set_pte(ptep, pte);
+ mte_sync_tags(pte, nr_pages);
}
-static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep, pte_t pte, unsigned int nr)
+static inline void set_ptes(struct mm_struct *mm,
+ unsigned long __always_unused addr,
+ pte_t *ptep, pte_t pte, unsigned int nr)
{
page_table_check_ptes_set(mm, ptep, pte, nr);
+ __sync_cache_and_tags(pte, nr);
for (;;) {
- __set_pte_at(mm, addr, ptep, pte);
+ __check_safe_pte_update(mm, ptep, pte);
+ set_pte(ptep, pte);
if (--nr == 0)
break;
ptep++;
- addr += PAGE_SIZE;
pte_val(pte) += PAGE_SIZE;
}
}
@@ -531,18 +528,29 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd)
#define pud_pfn(pud) ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT)
#define pfn_pud(pfn,prot) __pud(__phys_to_pud_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))
+static inline void __set_pte_at(struct mm_struct *mm,
+ unsigned long __always_unused addr,
+ pte_t *ptep, pte_t pte, unsigned int nr)
+{
+ __sync_cache_and_tags(pte, nr);
+ __check_safe_pte_update(mm, ptep, pte);
+ set_pte(ptep, pte);
+}
+
static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
pmd_t *pmdp, pmd_t pmd)
{
page_table_check_pmd_set(mm, pmdp, pmd);
- return __set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd));
+ return __set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd),
+ PMD_SIZE >> PAGE_SHIFT);
}
static inline void set_pud_at(struct mm_struct *mm, unsigned long addr,
pud_t *pudp, pud_t pud)
{
page_table_check_pud_set(mm, pudp, pud);
- return __set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud));
+ return __set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud),
+ PUD_SIZE >> PAGE_SHIFT);
}
#define __p4d_to_phys(p4d) __pte_to_phys(p4d_pte(p4d))
@@ -826,6 +834,12 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
pte = set_pte_bit(pte, __pgprot(PTE_DIRTY));
pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
+ /*
+ * If we end up clearing hw dirtiness for a sw-dirty PTE, set hardware
+ * dirtiness again.
+ */
+ if (pte_sw_dirty(pte))
+ pte = pte_mkdirty(pte);
return pte;
}
diff --git a/arch/arm64/include/asm/setup.h b/arch/arm64/include/asm/setup.h
index f4af547ef54c..2e4d7da74fb8 100644
--- a/arch/arm64/include/asm/setup.h
+++ b/arch/arm64/include/asm/setup.h
@@ -21,9 +21,22 @@ static inline bool arch_parse_debug_rodata(char *arg)
extern bool rodata_enabled;
extern bool rodata_full;
- if (arg && !strcmp(arg, "full")) {
+ if (!arg)
+ return false;
+
+ if (!strcmp(arg, "full")) {
+ rodata_enabled = rodata_full = true;
+ return true;
+ }
+
+ if (!strcmp(arg, "off")) {
+ rodata_enabled = rodata_full = false;
+ return true;
+ }
+
+ if (!strcmp(arg, "on")) {
rodata_enabled = true;
- rodata_full = true;
+ rodata_full = false;
return true;
}
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 9b31e6d0da17..efb13112b408 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -89,9 +89,9 @@ extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
-extern void arch_send_wakeup_ipi_mask(const struct cpumask *mask);
+extern void arch_send_wakeup_ipi(unsigned int cpu);
#else
-static inline void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
+static inline void arch_send_wakeup_ipi(unsigned int cpu)
{
BUILD_BUG();
}
diff --git a/arch/arm64/include/asm/spectre.h b/arch/arm64/include/asm/spectre.h
index 9cc501450486..06c357d83b13 100644
--- a/arch/arm64/include/asm/spectre.h
+++ b/arch/arm64/include/asm/spectre.h
@@ -73,7 +73,7 @@ static __always_inline void arm64_apply_bp_hardening(void)
{
struct bp_hardening_data *d;
- if (!cpus_have_const_cap(ARM64_SPECTRE_V2))
+ if (!alternative_has_cap_unlikely(ARM64_SPECTRE_V2))
return;
d = this_cpu_ptr(&bp_hardening_data);
diff --git a/arch/arm64/include/asm/stage2_pgtable.h b/arch/arm64/include/asm/stage2_pgtable.h
index c8dca8ae359c..23d27623e478 100644
--- a/arch/arm64/include/asm/stage2_pgtable.h
+++ b/arch/arm64/include/asm/stage2_pgtable.h
@@ -21,13 +21,13 @@
* (IPA_SHIFT - 4).
*/
#define stage2_pgtable_levels(ipa) ARM64_HW_PGTABLE_LEVELS((ipa) - 4)
-#define kvm_stage2_levels(kvm) VTCR_EL2_LVLS(kvm->arch.vtcr)
+#define kvm_stage2_levels(mmu) VTCR_EL2_LVLS((mmu)->vtcr)
/*
* kvm_mmmu_cache_min_pages() is the number of pages required to install
* a stage-2 translation. We pre-allocate the entry level page table at
* the VM creation.
*/
-#define kvm_mmu_cache_min_pages(kvm) (kvm_stage2_levels(kvm) - 1)
+#define kvm_mmu_cache_min_pages(mmu) (kvm_stage2_levels(mmu) - 1)
#endif /* __ARM64_S2_PGTABLE_H_ */
diff --git a/arch/arm64/include/asm/syscall_wrapper.h b/arch/arm64/include/asm/syscall_wrapper.h
index 17f687510c48..d977713ec0ba 100644
--- a/arch/arm64/include/asm/syscall_wrapper.h
+++ b/arch/arm64/include/asm/syscall_wrapper.h
@@ -54,7 +54,6 @@
ALLOW_ERROR_INJECTION(__arm64_sys##name, ERRNO); \
static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
- asmlinkage long __arm64_sys##name(const struct pt_regs *regs); \
asmlinkage long __arm64_sys##name(const struct pt_regs *regs) \
{ \
return __se_sys##name(SC_ARM64_REGS_TO_ARGS(x,__VA_ARGS__)); \
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 38296579a4fd..5e65f51c10d2 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -270,6 +270,8 @@
/* ETM */
#define SYS_TRCOSLAR sys_reg(2, 1, 1, 0, 4)
+#define SYS_BRBCR_EL2 sys_reg(2, 4, 9, 0, 0)
+
#define SYS_MIDR_EL1 sys_reg(3, 0, 0, 0, 0)
#define SYS_MPIDR_EL1 sys_reg(3, 0, 0, 0, 5)
#define SYS_REVIDR_EL1 sys_reg(3, 0, 0, 0, 6)
@@ -484,6 +486,7 @@
#define SYS_SCTLR_EL2 sys_reg(3, 4, 1, 0, 0)
#define SYS_ACTLR_EL2 sys_reg(3, 4, 1, 0, 1)
+#define SYS_SCTLR2_EL2 sys_reg(3, 4, 1, 0, 3)
#define SYS_HCR_EL2 sys_reg(3, 4, 1, 1, 0)
#define SYS_MDCR_EL2 sys_reg(3, 4, 1, 1, 1)
#define SYS_CPTR_EL2 sys_reg(3, 4, 1, 1, 2)
@@ -497,10 +500,15 @@
#define SYS_VTCR_EL2 sys_reg(3, 4, 2, 1, 2)
#define SYS_TRFCR_EL2 sys_reg(3, 4, 1, 2, 1)
+#define SYS_VNCR_EL2 sys_reg(3, 4, 2, 2, 0)
#define SYS_HAFGRTR_EL2 sys_reg(3, 4, 3, 1, 6)
#define SYS_SPSR_EL2 sys_reg(3, 4, 4, 0, 0)
#define SYS_ELR_EL2 sys_reg(3, 4, 4, 0, 1)
#define SYS_SP_EL1 sys_reg(3, 4, 4, 1, 0)
+#define SYS_SPSR_irq sys_reg(3, 4, 4, 3, 0)
+#define SYS_SPSR_abt sys_reg(3, 4, 4, 3, 1)
+#define SYS_SPSR_und sys_reg(3, 4, 4, 3, 2)
+#define SYS_SPSR_fiq sys_reg(3, 4, 4, 3, 3)
#define SYS_IFSR32_EL2 sys_reg(3, 4, 5, 0, 1)
#define SYS_AFSR0_EL2 sys_reg(3, 4, 5, 1, 0)
#define SYS_AFSR1_EL2 sys_reg(3, 4, 5, 1, 1)
@@ -514,6 +522,18 @@
#define SYS_MAIR_EL2 sys_reg(3, 4, 10, 2, 0)
#define SYS_AMAIR_EL2 sys_reg(3, 4, 10, 3, 0)
+#define SYS_MPAMHCR_EL2 sys_reg(3, 4, 10, 4, 0)
+#define SYS_MPAMVPMV_EL2 sys_reg(3, 4, 10, 4, 1)
+#define SYS_MPAM2_EL2 sys_reg(3, 4, 10, 5, 0)
+#define __SYS__MPAMVPMx_EL2(x) sys_reg(3, 4, 10, 6, x)
+#define SYS_MPAMVPM0_EL2 __SYS__MPAMVPMx_EL2(0)
+#define SYS_MPAMVPM1_EL2 __SYS__MPAMVPMx_EL2(1)
+#define SYS_MPAMVPM2_EL2 __SYS__MPAMVPMx_EL2(2)
+#define SYS_MPAMVPM3_EL2 __SYS__MPAMVPMx_EL2(3)
+#define SYS_MPAMVPM4_EL2 __SYS__MPAMVPMx_EL2(4)
+#define SYS_MPAMVPM5_EL2 __SYS__MPAMVPMx_EL2(5)
+#define SYS_MPAMVPM6_EL2 __SYS__MPAMVPMx_EL2(6)
+#define SYS_MPAMVPM7_EL2 __SYS__MPAMVPMx_EL2(7)
#define SYS_VBAR_EL2 sys_reg(3, 4, 12, 0, 0)
#define SYS_RVBAR_EL2 sys_reg(3, 4, 12, 0, 1)
@@ -562,24 +582,49 @@
#define SYS_CONTEXTIDR_EL2 sys_reg(3, 4, 13, 0, 1)
#define SYS_TPIDR_EL2 sys_reg(3, 4, 13, 0, 2)
+#define SYS_SCXTNUM_EL2 sys_reg(3, 4, 13, 0, 7)
+
+#define __AMEV_op2(m) (m & 0x7)
+#define __AMEV_CRm(n, m) (n | ((m & 0x8) >> 3))
+#define __SYS__AMEVCNTVOFF0n_EL2(m) sys_reg(3, 4, 13, __AMEV_CRm(0x8, m), __AMEV_op2(m))
+#define SYS_AMEVCNTVOFF0n_EL2(m) __SYS__AMEVCNTVOFF0n_EL2(m)
+#define __SYS__AMEVCNTVOFF1n_EL2(m) sys_reg(3, 4, 13, __AMEV_CRm(0xA, m), __AMEV_op2(m))
+#define SYS_AMEVCNTVOFF1n_EL2(m) __SYS__AMEVCNTVOFF1n_EL2(m)
#define SYS_CNTVOFF_EL2 sys_reg(3, 4, 14, 0, 3)
#define SYS_CNTHCTL_EL2 sys_reg(3, 4, 14, 1, 0)
+#define SYS_CNTHP_TVAL_EL2 sys_reg(3, 4, 14, 2, 0)
+#define SYS_CNTHP_CTL_EL2 sys_reg(3, 4, 14, 2, 1)
+#define SYS_CNTHP_CVAL_EL2 sys_reg(3, 4, 14, 2, 2)
+#define SYS_CNTHV_TVAL_EL2 sys_reg(3, 4, 14, 3, 0)
+#define SYS_CNTHV_CTL_EL2 sys_reg(3, 4, 14, 3, 1)
+#define SYS_CNTHV_CVAL_EL2 sys_reg(3, 4, 14, 3, 2)
/* VHE encodings for architectural EL0/1 system registers */
+#define SYS_BRBCR_EL12 sys_reg(2, 5, 9, 0, 0)
#define SYS_SCTLR_EL12 sys_reg(3, 5, 1, 0, 0)
+#define SYS_CPACR_EL12 sys_reg(3, 5, 1, 0, 2)
+#define SYS_SCTLR2_EL12 sys_reg(3, 5, 1, 0, 3)
+#define SYS_ZCR_EL12 sys_reg(3, 5, 1, 2, 0)
+#define SYS_TRFCR_EL12 sys_reg(3, 5, 1, 2, 1)
+#define SYS_SMCR_EL12 sys_reg(3, 5, 1, 2, 6)
#define SYS_TTBR0_EL12 sys_reg(3, 5, 2, 0, 0)
#define SYS_TTBR1_EL12 sys_reg(3, 5, 2, 0, 1)
#define SYS_TCR_EL12 sys_reg(3, 5, 2, 0, 2)
+#define SYS_TCR2_EL12 sys_reg(3, 5, 2, 0, 3)
#define SYS_SPSR_EL12 sys_reg(3, 5, 4, 0, 0)
#define SYS_ELR_EL12 sys_reg(3, 5, 4, 0, 1)
#define SYS_AFSR0_EL12 sys_reg(3, 5, 5, 1, 0)
#define SYS_AFSR1_EL12 sys_reg(3, 5, 5, 1, 1)
#define SYS_ESR_EL12 sys_reg(3, 5, 5, 2, 0)
#define SYS_TFSR_EL12 sys_reg(3, 5, 5, 6, 0)
+#define SYS_FAR_EL12 sys_reg(3, 5, 6, 0, 0)
+#define SYS_PMSCR_EL12 sys_reg(3, 5, 9, 9, 0)
#define SYS_MAIR_EL12 sys_reg(3, 5, 10, 2, 0)
#define SYS_AMAIR_EL12 sys_reg(3, 5, 10, 3, 0)
#define SYS_VBAR_EL12 sys_reg(3, 5, 12, 0, 0)
+#define SYS_CONTEXTIDR_EL12 sys_reg(3, 5, 13, 0, 1)
+#define SYS_SCXTNUM_EL12 sys_reg(3, 5, 13, 0, 7)
#define SYS_CNTKCTL_EL12 sys_reg(3, 5, 14, 1, 0)
#define SYS_CNTP_TVAL_EL02 sys_reg(3, 5, 14, 2, 0)
#define SYS_CNTP_CTL_EL02 sys_reg(3, 5, 14, 2, 1)
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h
index 2c29239d05c3..846c563689a8 100644
--- a/arch/arm64/include/asm/tlb.h
+++ b/arch/arm64/include/asm/tlb.h
@@ -96,7 +96,10 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pudp,
unsigned long addr)
{
- tlb_remove_ptdesc(tlb, virt_to_ptdesc(pudp));
+ struct ptdesc *ptdesc = virt_to_ptdesc(pudp);
+
+ pagetable_pud_dtor(ptdesc);
+ tlb_remove_ptdesc(tlb, ptdesc);
}
#endif
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index b149cf9f91bc..bb2c2833a987 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -105,7 +105,7 @@ static inline unsigned long get_trans_granule(void)
#define __tlbi_level(op, addr, level) do { \
u64 arg = addr; \
\
- if (cpus_have_const_cap(ARM64_HAS_ARMv8_4_TTL) && \
+ if (alternative_has_cap_unlikely(ARM64_HAS_ARMv8_4_TTL) && \
level) { \
u64 ttl = level & 3; \
ttl |= get_trans_granule() << 2; \
@@ -284,16 +284,15 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
{
-#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
/*
* TLB flush deferral is not required on systems which are affected by
* ARM64_WORKAROUND_REPEAT_TLBI, as __tlbi()/__tlbi_user() implementation
* will have two consecutive TLBI instructions with a dsb(ish) in between
* defeating the purpose (i.e save overall 'dsb ish' cost).
*/
- if (unlikely(cpus_have_const_cap(ARM64_WORKAROUND_REPEAT_TLBI)))
+ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_REPEAT_TLBI))
return false;
-#endif
+
return true;
}
@@ -333,7 +332,7 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
* This is meant to avoid soft lock-ups on large TLB flushing ranges and not
* necessarily a performance improvement.
*/
-#define MAX_TLBI_OPS PTRS_PER_PTE
+#define MAX_DVM_OPS PTRS_PER_PTE
/*
* __flush_tlb_range_op - Perform TLBI operation upon a range
@@ -413,12 +412,12 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
/*
* When not uses TLB range ops, we can handle up to
- * (MAX_TLBI_OPS - 1) pages;
+ * (MAX_DVM_OPS - 1) pages;
* When uses TLB range ops, we can handle up to
* (MAX_TLBI_RANGE_PAGES - 1) pages.
*/
if ((!system_supports_tlb_range() &&
- (end - start) >= (MAX_TLBI_OPS * stride)) ||
+ (end - start) >= (MAX_DVM_OPS * stride)) ||
pages >= MAX_TLBI_RANGE_PAGES) {
flush_tlb_mm(vma->vm_mm);
return;
@@ -451,7 +450,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
{
unsigned long addr;
- if ((end - start) > (MAX_TLBI_OPS * PAGE_SIZE)) {
+ if ((end - start) > (MAX_DVM_OPS * PAGE_SIZE)) {
flush_tlb_all();
return;
}
diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
index d66dfb3a72dd..eefe766d6161 100644
--- a/arch/arm64/include/asm/traps.h
+++ b/arch/arm64/include/asm/traps.h
@@ -9,10 +9,9 @@
#include <linux/list.h>
#include <asm/esr.h>
+#include <asm/ptrace.h>
#include <asm/sections.h>
-struct pt_regs;
-
#ifdef CONFIG_ARMV8_DEPRECATED
bool try_emulate_armv8_deprecated(struct pt_regs *regs, u32 insn);
#else
@@ -101,4 +100,55 @@ static inline unsigned long arm64_ras_serror_get_severity(unsigned long esr)
bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned long esr);
void __noreturn arm64_serror_panic(struct pt_regs *regs, unsigned long esr);
+
+static inline void arm64_mops_reset_regs(struct user_pt_regs *regs, unsigned long esr)
+{
+ bool wrong_option = esr & ESR_ELx_MOPS_ISS_WRONG_OPTION;
+ bool option_a = esr & ESR_ELx_MOPS_ISS_OPTION_A;
+ int dstreg = ESR_ELx_MOPS_ISS_DESTREG(esr);
+ int srcreg = ESR_ELx_MOPS_ISS_SRCREG(esr);
+ int sizereg = ESR_ELx_MOPS_ISS_SIZEREG(esr);
+ unsigned long dst, src, size;
+
+ dst = regs->regs[dstreg];
+ src = regs->regs[srcreg];
+ size = regs->regs[sizereg];
+
+ /*
+ * Put the registers back in the original format suitable for a
+ * prologue instruction, using the generic return routine from the
+ * Arm ARM (DDI 0487I.a) rules CNTMJ and MWFQH.
+ */
+ if (esr & ESR_ELx_MOPS_ISS_MEM_INST) {
+ /* SET* instruction */
+ if (option_a ^ wrong_option) {
+ /* Format is from Option A; forward set */
+ regs->regs[dstreg] = dst + size;
+ regs->regs[sizereg] = -size;
+ }
+ } else {
+ /* CPY* instruction */
+ if (!(option_a ^ wrong_option)) {
+ /* Format is from Option B */
+ if (regs->pstate & PSR_N_BIT) {
+ /* Backward copy */
+ regs->regs[dstreg] = dst - size;
+ regs->regs[srcreg] = src - size;
+ }
+ } else {
+ /* Format is from Option A */
+ if (size & BIT(63)) {
+ /* Forward copy */
+ regs->regs[dstreg] = dst + size;
+ regs->regs[srcreg] = src + size;
+ regs->regs[sizereg] = -size;
+ }
+ }
+ }
+
+ if (esr & ESR_ELx_MOPS_ISS_FROM_EPILOGUE)
+ regs->pc -= 8;
+ else
+ regs->pc -= 4;
+}
#endif
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index bd77253b62e0..531effca5f1f 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -39,7 +39,7 @@
#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5)
#define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800)
-#define __NR_compat_syscalls 453
+#define __NR_compat_syscalls 457
#endif
#define __ARCH_WANT_SYS_CLONE
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index 78b68311ec81..9f7c1bf99526 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -508,8 +508,8 @@ __SYSCALL(__NR_io_submit, compat_sys_io_submit)
__SYSCALL(__NR_io_cancel, sys_io_cancel)
#define __NR_exit_group 248
__SYSCALL(__NR_exit_group, sys_exit_group)
-#define __NR_lookup_dcookie 249
-__SYSCALL(__NR_lookup_dcookie, compat_sys_lookup_dcookie)
+ /* 249 was lookup_dcookie */
+__SYSCALL(249, sys_ni_syscall)
#define __NR_epoll_create 250
__SYSCALL(__NR_epoll_create, sys_epoll_create)
#define __NR_epoll_ctl 251
@@ -911,6 +911,14 @@ __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node)
__SYSCALL(__NR_cachestat, sys_cachestat)
#define __NR_fchmodat2 452
__SYSCALL(__NR_fchmodat2, sys_fchmodat2)
+#define __NR_map_shadow_stack 453
+__SYSCALL(__NR_map_shadow_stack, sys_map_shadow_stack)
+#define __NR_futex_wake 454
+__SYSCALL(__NR_futex_wake, sys_futex_wake)
+#define __NR_futex_wait 455
+__SYSCALL(__NR_futex_wait, sys_futex_wait)
+#define __NR_futex_requeue 456
+__SYSCALL(__NR_futex_requeue, sys_futex_requeue)
/*
* Please add new compat syscalls above this comment and update
diff --git a/arch/arm64/include/asm/vectors.h b/arch/arm64/include/asm/vectors.h
index bc9a2145f419..b815d8f2c0dc 100644
--- a/arch/arm64/include/asm/vectors.h
+++ b/arch/arm64/include/asm/vectors.h
@@ -62,7 +62,7 @@ DECLARE_PER_CPU_READ_MOSTLY(const char *, this_cpu_vector);
static inline const char *
arm64_get_bp_hardening_vector(enum arm64_bp_harden_el1_vectors slot)
{
- if (arm64_kernel_unmapped_at_el0())
+ if (cpus_have_cap(ARM64_UNMAP_KERNEL_AT_EL0))
return (char *)(TRAMP_VALIAS + SZ_2K * slot);
WARN_ON_ONCE(slot == EL1_VECTOR_KPTI);
diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h
index 53026f45a509..5023599fa278 100644
--- a/arch/arm64/include/uapi/asm/hwcap.h
+++ b/arch/arm64/include/uapi/asm/hwcap.h
@@ -104,5 +104,8 @@
#define HWCAP2_SME_F16F16 (1UL << 42)
#define HWCAP2_MOPS (1UL << 43)
#define HWCAP2_HBC (1UL << 44)
+#define HWCAP2_SVE_B16B16 (1UL << 45)
+#define HWCAP2_LRCPC3 (1UL << 46)
+#define HWCAP2_LSE128 (1UL << 47)
#endif /* _UAPI__ASM_HWCAP_H */
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index f7ddd73a8c0f..89d2fc872d9f 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -505,6 +505,38 @@ struct kvm_smccc_filter {
#define KVM_HYPERCALL_EXIT_SMC (1U << 0)
#define KVM_HYPERCALL_EXIT_16BIT (1U << 1)
+/*
+ * Get feature ID registers userspace writable mask.
+ *
+ * From DDI0487J.a, D19.2.66 ("ID_AA64MMFR2_EL1, AArch64 Memory Model
+ * Feature Register 2"):
+ *
+ * "The Feature ID space is defined as the System register space in
+ * AArch64 with op0==3, op1=={0, 1, 3}, CRn==0, CRm=={0-7},
+ * op2=={0-7}."
+ *
+ * This covers all currently known R/O registers that indicate
+ * anything useful feature wise, including the ID registers.
+ *
+ * If we ever need to introduce a new range, it will be described as
+ * such in the range field.
+ */
+#define KVM_ARM_FEATURE_ID_RANGE_IDX(op0, op1, crn, crm, op2) \
+ ({ \
+ __u64 __op1 = (op1) & 3; \
+ __op1 -= (__op1 == 3); \
+ (__op1 << 6 | ((crm) & 7) << 3 | (op2)); \
+ })
+
+#define KVM_ARM_FEATURE_ID_RANGE 0
+#define KVM_ARM_FEATURE_ID_RANGE_SIZE (3 * 8 * 8)
+
+struct reg_mask_range {
+ __u64 addr; /* Pointer to mask array */
+ __u32 range; /* Requested range */
+ __u32 reserved[13];
+};
+
#endif
#endif /* __ARM_KVM_H__ */
diff --git a/arch/arm64/kernel/acpi_parking_protocol.c b/arch/arm64/kernel/acpi_parking_protocol.c
index b1990e38aed0..e1be29e608b7 100644
--- a/arch/arm64/kernel/acpi_parking_protocol.c
+++ b/arch/arm64/kernel/acpi_parking_protocol.c
@@ -103,7 +103,7 @@ static int acpi_parking_protocol_cpu_boot(unsigned int cpu)
&mailbox->entry_point);
writel_relaxed(cpu_entry->gic_cpu_id, &mailbox->cpu_id);
- arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+ arch_send_wakeup_ipi(cpu);
return 0;
}
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index e459cfd33711..dd6ce86d4332 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -52,10 +52,8 @@ struct insn_emulation {
int min;
int max;
- /*
- * sysctl for this emulation + a sentinal entry.
- */
- struct ctl_table sysctl[2];
+ /* sysctl for this emulation */
+ struct ctl_table sysctl;
};
#define ARM_OPCODE_CONDTEST_FAIL 0
@@ -558,7 +556,7 @@ static void __init register_insn_emulation(struct insn_emulation *insn)
update_insn_emulation_mode(insn, INSN_UNDEF);
if (insn->status != INSN_UNAVAILABLE) {
- sysctl = &insn->sysctl[0];
+ sysctl = &insn->sysctl;
sysctl->mode = 0644;
sysctl->maxlen = sizeof(int);
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 5706e74c5578..e29e0fea63fb 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -121,22 +121,6 @@ cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCI, 0);
}
-static DEFINE_RAW_SPINLOCK(reg_user_mask_modification);
-static void __maybe_unused
-cpu_clear_bf16_from_user_emulation(const struct arm64_cpu_capabilities *__unused)
-{
- struct arm64_ftr_reg *regp;
-
- regp = get_arm64_ftr_reg(SYS_ID_AA64ISAR1_EL1);
- if (!regp)
- return;
-
- raw_spin_lock(&reg_user_mask_modification);
- if (regp->user_mask & ID_AA64ISAR1_EL1_BF16_MASK)
- regp->user_mask &= ~ID_AA64ISAR1_EL1_BF16_MASK;
- raw_spin_unlock(&reg_user_mask_modification);
-}
-
#define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \
.matches = is_affected_midr_range, \
.midr_range = MIDR_RANGE(model, v_min, r_min, v_max, r_max)
@@ -727,7 +711,6 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
/* Cortex-A510 r0p0 - r1p1 */
ERRATA_MIDR_RANGE(MIDR_CORTEX_A510, 0, 0, 1, 1),
MIDR_FIXED(MIDR_CPU_VAR_REV(1,1), BIT(25)),
- .cpu_enable = cpu_clear_bf16_from_user_emulation,
},
#endif
#ifdef CONFIG_ARM64_ERRATUM_2966298
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 444a73c2e638..91d2d6714969 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -279,6 +279,8 @@ static const struct arm64_ftr_bits ftr_id_aa64zfr0[] = {
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE),
FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_EL1_SHA3_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE),
+ FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_EL1_B16B16_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE),
FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_EL1_BF16_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE),
FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_EL1_BitPerm_SHIFT, 4, 0),
@@ -611,18 +613,6 @@ static const struct arm64_ftr_bits ftr_id_dfr1[] = {
ARM64_FTR_END,
};
-static const struct arm64_ftr_bits ftr_zcr[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE,
- ZCR_ELx_LEN_SHIFT, ZCR_ELx_LEN_WIDTH, 0), /* LEN */
- ARM64_FTR_END,
-};
-
-static const struct arm64_ftr_bits ftr_smcr[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE,
- SMCR_ELx_LEN_SHIFT, SMCR_ELx_LEN_WIDTH, 0), /* LEN */
- ARM64_FTR_END,
-};
-
/*
* Common ftr bits for a 32bit register with all hidden, strict
* attributes, with 4bit feature fields and a default safe value of
@@ -735,10 +725,6 @@ static const struct __ftr_reg_entry {
ARM64_FTR_REG(SYS_ID_AA64MMFR2_EL1, ftr_id_aa64mmfr2),
ARM64_FTR_REG(SYS_ID_AA64MMFR3_EL1, ftr_id_aa64mmfr3),
- /* Op1 = 0, CRn = 1, CRm = 2 */
- ARM64_FTR_REG(SYS_ZCR_EL1, ftr_zcr),
- ARM64_FTR_REG(SYS_SMCR_EL1, ftr_smcr),
-
/* Op1 = 1, CRn = 0, CRm = 0 */
ARM64_FTR_REG(SYS_GMID_EL1, ftr_gmid),
@@ -1013,6 +999,37 @@ static void init_32bit_cpu_features(struct cpuinfo_32bit *info)
init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
}
+#ifdef CONFIG_ARM64_PSEUDO_NMI
+static bool enable_pseudo_nmi;
+
+static int __init early_enable_pseudo_nmi(char *p)
+{
+ return kstrtobool(p, &enable_pseudo_nmi);
+}
+early_param("irqchip.gicv3_pseudo_nmi", early_enable_pseudo_nmi);
+
+static __init void detect_system_supports_pseudo_nmi(void)
+{
+ struct device_node *np;
+
+ if (!enable_pseudo_nmi)
+ return;
+
+ /*
+ * Detect broken MediaTek firmware that doesn't properly save and
+ * restore GIC priorities.
+ */
+ np = of_find_compatible_node(NULL, NULL, "arm,gic-v3");
+ if (np && of_property_read_bool(np, "mediatek,broken-save-restore-fw")) {
+ pr_info("Pseudo-NMI disabled due to MediaTek Chromebook GICR save problem\n");
+ enable_pseudo_nmi = false;
+ }
+ of_node_put(np);
+}
+#else /* CONFIG_ARM64_PSEUDO_NMI */
+static inline void detect_system_supports_pseudo_nmi(void) { }
+#endif
+
void __init init_cpu_features(struct cpuinfo_arm64 *info)
{
/* Before we start using the tables, make sure it is sorted */
@@ -1040,22 +1057,26 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
if (IS_ENABLED(CONFIG_ARM64_SVE) &&
id_aa64pfr0_sve(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
- info->reg_zcr = read_zcr_features();
- init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
+ unsigned long cpacr = cpacr_save_enable_kernel_sve();
+
vec_init_vq_map(ARM64_VEC_SVE);
+
+ cpacr_restore(cpacr);
}
if (IS_ENABLED(CONFIG_ARM64_SME) &&
id_aa64pfr1_sme(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1))) {
- info->reg_smcr = read_smcr_features();
+ unsigned long cpacr = cpacr_save_enable_kernel_sme();
+
/*
* We mask out SMPS since even if the hardware
* supports priorities the kernel does not at present
* and we block access to them.
*/
info->reg_smidr = read_cpuid(SMIDR_EL1) & ~SMIDR_EL1_SMPS;
- init_cpu_ftr_reg(SYS_SMCR_EL1, info->reg_smcr);
vec_init_vq_map(ARM64_VEC_SME);
+
+ cpacr_restore(cpacr);
}
if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
@@ -1068,6 +1089,13 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
init_cpucap_indirect_list();
/*
+ * Detect broken pseudo-NMI. Must be called _before_ the call to
+ * setup_boot_cpu_capabilities() since it interacts with
+ * can_use_gic_priorities().
+ */
+ detect_system_supports_pseudo_nmi();
+
+ /*
* Detect and enable early CPU capabilities based on the boot CPU,
* after we have initialised the CPU feature infrastructure.
*/
@@ -1289,32 +1317,34 @@ void update_cpu_features(int cpu,
taint |= check_update_ftr_reg(SYS_ID_AA64SMFR0_EL1, cpu,
info->reg_id_aa64smfr0, boot->reg_id_aa64smfr0);
+ /* Probe vector lengths */
if (IS_ENABLED(CONFIG_ARM64_SVE) &&
id_aa64pfr0_sve(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
- info->reg_zcr = read_zcr_features();
- taint |= check_update_ftr_reg(SYS_ZCR_EL1, cpu,
- info->reg_zcr, boot->reg_zcr);
+ if (!system_capabilities_finalized()) {
+ unsigned long cpacr = cpacr_save_enable_kernel_sve();
- /* Probe vector lengths */
- if (!system_capabilities_finalized())
vec_update_vq_map(ARM64_VEC_SVE);
+
+ cpacr_restore(cpacr);
+ }
}
if (IS_ENABLED(CONFIG_ARM64_SME) &&
id_aa64pfr1_sme(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1))) {
- info->reg_smcr = read_smcr_features();
+ unsigned long cpacr = cpacr_save_enable_kernel_sme();
+
/*
* We mask out SMPS since even if the hardware
* supports priorities the kernel does not at present
* and we block access to them.
*/
info->reg_smidr = read_cpuid(SMIDR_EL1) & ~SMIDR_EL1_SMPS;
- taint |= check_update_ftr_reg(SYS_SMCR_EL1, cpu,
- info->reg_smcr, boot->reg_smcr);
/* Probe vector lengths */
if (!system_capabilities_finalized())
vec_update_vq_map(ARM64_VEC_SME);
+
+ cpacr_restore(cpacr);
}
/*
@@ -1564,14 +1594,6 @@ static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry, int _
MIDR_CPU_VAR_REV(1, MIDR_REVISION_MASK));
}
-static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unused)
-{
- u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
-
- return cpuid_feature_extract_signed_field(pfr0,
- ID_AA64PFR0_EL1_FP_SHIFT) < 0;
-}
-
static bool has_cache_idc(const struct arm64_cpu_capabilities *entry,
int scope)
{
@@ -1621,7 +1643,7 @@ has_useable_cnp(const struct arm64_cpu_capabilities *entry, int scope)
if (is_kdump_kernel())
return false;
- if (cpus_have_const_cap(ARM64_WORKAROUND_NVIDIA_CARMEL_CNP))
+ if (cpus_have_cap(ARM64_WORKAROUND_NVIDIA_CARMEL_CNP))
return false;
return has_cpuid_feature(entry, scope);
@@ -1754,16 +1776,15 @@ void create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt,
phys_addr_t size, pgprot_t prot,
phys_addr_t (*pgtable_alloc)(int), int flags);
-static phys_addr_t kpti_ng_temp_alloc;
+static phys_addr_t __initdata kpti_ng_temp_alloc;
-static phys_addr_t kpti_ng_pgd_alloc(int shift)
+static phys_addr_t __init kpti_ng_pgd_alloc(int shift)
{
kpti_ng_temp_alloc -= PAGE_SIZE;
return kpti_ng_temp_alloc;
}
-static void
-kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
+static int __init __kpti_install_ng_mappings(void *__unused)
{
typedef void (kpti_remap_fn)(int, int, phys_addr_t, unsigned long);
extern kpti_remap_fn idmap_kpti_install_ng_mappings;
@@ -1776,20 +1797,6 @@ kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
pgd_t *kpti_ng_temp_pgd;
u64 alloc = 0;
- if (__this_cpu_read(this_cpu_vector) == vectors) {
- const char *v = arm64_get_bp_hardening_vector(EL1_VECTOR_KPTI);
-
- __this_cpu_write(this_cpu_vector, v);
- }
-
- /*
- * We don't need to rewrite the page-tables if either we've done
- * it already or we have KASLR enabled and therefore have not
- * created any global mappings at all.
- */
- if (arm64_use_ng_mappings)
- return;
-
remap_fn = (void *)__pa_symbol(idmap_kpti_install_ng_mappings);
if (!cpu) {
@@ -1826,14 +1833,43 @@ kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
free_pages(alloc, order);
arm64_use_ng_mappings = true;
}
+
+ return 0;
+}
+
+static void __init kpti_install_ng_mappings(void)
+{
+ /* Check whether KPTI is going to be used */
+ if (!cpus_have_cap(ARM64_UNMAP_KERNEL_AT_EL0))
+ return;
+
+ /*
+ * We don't need to rewrite the page-tables if either we've done
+ * it already or we have KASLR enabled and therefore have not
+ * created any global mappings at all.
+ */
+ if (arm64_use_ng_mappings)
+ return;
+
+ stop_machine(__kpti_install_ng_mappings, NULL, cpu_online_mask);
}
+
#else
-static void
-kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
+static inline void kpti_install_ng_mappings(void)
{
}
#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
+static void cpu_enable_kpti(struct arm64_cpu_capabilities const *cap)
+{
+ if (__this_cpu_read(this_cpu_vector) == vectors) {
+ const char *v = arm64_get_bp_hardening_vector(EL1_VECTOR_KPTI);
+
+ __this_cpu_write(this_cpu_vector, v);
+ }
+
+}
+
static int __init parse_kpti(char *str)
{
bool enabled;
@@ -1848,6 +1884,8 @@ static int __init parse_kpti(char *str)
early_param("kpti", parse_kpti);
#ifdef CONFIG_ARM64_HW_AFDBM
+static struct cpumask dbm_cpus __read_mostly;
+
static inline void __cpu_enable_hw_dbm(void)
{
u64 tcr = read_sysreg(tcr_el1) | TCR_HD;
@@ -1883,35 +1921,22 @@ static bool cpu_can_use_dbm(const struct arm64_cpu_capabilities *cap)
static void cpu_enable_hw_dbm(struct arm64_cpu_capabilities const *cap)
{
- if (cpu_can_use_dbm(cap))
+ if (cpu_can_use_dbm(cap)) {
__cpu_enable_hw_dbm();
+ cpumask_set_cpu(smp_processor_id(), &dbm_cpus);
+ }
}
static bool has_hw_dbm(const struct arm64_cpu_capabilities *cap,
int __unused)
{
- static bool detected = false;
/*
* DBM is a non-conflicting feature. i.e, the kernel can safely
* run a mix of CPUs with and without the feature. So, we
* unconditionally enable the capability to allow any late CPU
* to use the feature. We only enable the control bits on the
- * CPU, if it actually supports.
- *
- * We have to make sure we print the "feature" detection only
- * when at least one CPU actually uses it. So check if this CPU
- * can actually use it and print the message exactly once.
- *
- * This is safe as all CPUs (including secondary CPUs - due to the
- * LOCAL_CPU scope - and the hotplugged CPUs - via verification)
- * goes through the "matches" check exactly once. Also if a CPU
- * matches the criteria, it is guaranteed that the CPU will turn
- * the DBM on, as the capability is unconditionally enabled.
+ * CPU, if it is supported.
*/
- if (!detected && cpu_can_use_dbm(cap)) {
- detected = true;
- pr_info("detected: Hardware dirty bit management\n");
- }
return true;
}
@@ -1944,8 +1969,6 @@ int get_cpu_with_amu_feat(void)
static void cpu_amu_enable(struct arm64_cpu_capabilities const *cap)
{
if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU)) {
- pr_info("detected CPU%d: Activity Monitors Unit (AMU)\n",
- smp_processor_id());
cpumask_set_cpu(smp_processor_id(), &amu_cpus);
/* 0 reference values signal broken/disabled counters */
@@ -2104,14 +2127,6 @@ static void cpu_enable_e0pd(struct arm64_cpu_capabilities const *cap)
#endif /* CONFIG_ARM64_E0PD */
#ifdef CONFIG_ARM64_PSEUDO_NMI
-static bool enable_pseudo_nmi;
-
-static int __init early_enable_pseudo_nmi(char *p)
-{
- return kstrtobool(p, &enable_pseudo_nmi);
-}
-early_param("irqchip.gicv3_pseudo_nmi", early_enable_pseudo_nmi);
-
static bool can_use_gic_priorities(const struct arm64_cpu_capabilities *entry,
int scope)
{
@@ -2190,12 +2205,23 @@ static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap)
}
#endif /* CONFIG_ARM64_MTE */
+static void user_feature_fixup(void)
+{
+ if (cpus_have_cap(ARM64_WORKAROUND_2658417)) {
+ struct arm64_ftr_reg *regp;
+
+ regp = get_arm64_ftr_reg(SYS_ID_AA64ISAR1_EL1);
+ if (regp)
+ regp->user_mask &= ~ID_AA64ISAR1_EL1_BF16_MASK;
+ }
+}
+
static void elf_hwcap_fixup(void)
{
-#ifdef CONFIG_ARM64_ERRATUM_1742098
- if (cpus_have_const_cap(ARM64_WORKAROUND_1742098))
+#ifdef CONFIG_COMPAT
+ if (cpus_have_cap(ARM64_WORKAROUND_1742098))
compat_elf_hwcap2 &= ~COMPAT_HWCAP2_AES;
-#endif /* ARM64_ERRATUM_1742098 */
+#endif /* CONFIG_COMPAT */
}
#ifdef CONFIG_KVM
@@ -2351,7 +2377,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.desc = "Kernel page table isolation (KPTI)",
.capability = ARM64_UNMAP_KERNEL_AT_EL0,
.type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE,
- .cpu_enable = kpti_install_ng_mappings,
+ .cpu_enable = cpu_enable_kpti,
.matches = unmap_kernel_at_el0,
/*
* The ID feature fields below are used to indicate that
@@ -2361,11 +2387,11 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
ARM64_CPUID_FIELDS(ID_AA64PFR0_EL1, CSV3, IMP)
},
{
- /* FP/SIMD is not implemented */
- .capability = ARM64_HAS_NO_FPSIMD,
- .type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE,
- .min_field_value = 0,
- .matches = has_no_fpsimd,
+ .capability = ARM64_HAS_FPSIMD,
+ .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+ .matches = has_cpuid_feature,
+ .cpu_enable = cpu_enable_fpsimd,
+ ARM64_CPUID_FIELDS(ID_AA64PFR0_EL1, FP, IMP)
},
#ifdef CONFIG_ARM64_PMEM
{
@@ -2388,7 +2414,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.desc = "Scalable Vector Extension",
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
.capability = ARM64_SVE,
- .cpu_enable = sve_kernel_enable,
+ .cpu_enable = cpu_enable_sve,
.matches = has_cpuid_feature,
ARM64_CPUID_FIELDS(ID_AA64PFR0_EL1, SVE, IMP)
},
@@ -2405,16 +2431,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
#endif /* CONFIG_ARM64_RAS_EXTN */
#ifdef CONFIG_ARM64_AMU_EXTN
{
- /*
- * The feature is enabled by default if CONFIG_ARM64_AMU_EXTN=y.
- * Therefore, don't provide .desc as we don't want the detection
- * message to be shown until at least one CPU is detected to
- * support the feature.
- */
+ .desc = "Activity Monitors Unit (AMU)",
.capability = ARM64_HAS_AMU_EXTN,
.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
.matches = has_amu,
.cpu_enable = cpu_amu_enable,
+ .cpus = &amu_cpus,
ARM64_CPUID_FIELDS(ID_AA64PFR0_EL1, AMU, IMP)
},
#endif /* CONFIG_ARM64_AMU_EXTN */
@@ -2454,18 +2476,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
},
#ifdef CONFIG_ARM64_HW_AFDBM
{
- /*
- * Since we turn this on always, we don't want the user to
- * think that the feature is available when it may not be.
- * So hide the description.
- *
- * .desc = "Hardware pagetable Dirty Bit Management",
- *
- */
+ .desc = "Hardware dirty bit management",
.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
.capability = ARM64_HW_DBM,
.matches = has_hw_dbm,
.cpu_enable = cpu_enable_hw_dbm,
+ .cpus = &dbm_cpus,
ARM64_CPUID_FIELDS(ID_AA64MMFR1_EL1, HAFDBS, DBM)
},
#endif
@@ -2641,7 +2657,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
.capability = ARM64_SME,
.matches = has_cpuid_feature,
- .cpu_enable = sme_kernel_enable,
+ .cpu_enable = cpu_enable_sme,
ARM64_CPUID_FIELDS(ID_AA64PFR1_EL1, SME, IMP)
},
/* FA64 should be sorted after the base SME capability */
@@ -2650,7 +2666,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
.capability = ARM64_SME_FA64,
.matches = has_cpuid_feature,
- .cpu_enable = fa64_kernel_enable,
+ .cpu_enable = cpu_enable_fa64,
ARM64_CPUID_FIELDS(ID_AA64SMFR0_EL1, FA64, IMP)
},
{
@@ -2658,7 +2674,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
.capability = ARM64_SME2,
.matches = has_cpuid_feature,
- .cpu_enable = sme2_kernel_enable,
+ .cpu_enable = cpu_enable_sme2,
ARM64_CPUID_FIELDS(ID_AA64PFR1_EL1, SME, SME2)
},
#endif /* CONFIG_ARM64_SME */
@@ -2787,6 +2803,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
HWCAP_CAP(ID_AA64ISAR0_EL1, SHA2, SHA512, CAP_HWCAP, KERNEL_HWCAP_SHA512),
HWCAP_CAP(ID_AA64ISAR0_EL1, CRC32, IMP, CAP_HWCAP, KERNEL_HWCAP_CRC32),
HWCAP_CAP(ID_AA64ISAR0_EL1, ATOMIC, IMP, CAP_HWCAP, KERNEL_HWCAP_ATOMICS),
+ HWCAP_CAP(ID_AA64ISAR0_EL1, ATOMIC, FEAT_LSE128, CAP_HWCAP, KERNEL_HWCAP_LSE128),
HWCAP_CAP(ID_AA64ISAR0_EL1, RDM, IMP, CAP_HWCAP, KERNEL_HWCAP_ASIMDRDM),
HWCAP_CAP(ID_AA64ISAR0_EL1, SHA3, IMP, CAP_HWCAP, KERNEL_HWCAP_SHA3),
HWCAP_CAP(ID_AA64ISAR0_EL1, SM3, IMP, CAP_HWCAP, KERNEL_HWCAP_SM3),
@@ -2807,6 +2824,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
HWCAP_CAP(ID_AA64ISAR1_EL1, FCMA, IMP, CAP_HWCAP, KERNEL_HWCAP_FCMA),
HWCAP_CAP(ID_AA64ISAR1_EL1, LRCPC, IMP, CAP_HWCAP, KERNEL_HWCAP_LRCPC),
HWCAP_CAP(ID_AA64ISAR1_EL1, LRCPC, LRCPC2, CAP_HWCAP, KERNEL_HWCAP_ILRCPC),
+ HWCAP_CAP(ID_AA64ISAR1_EL1, LRCPC, LRCPC3, CAP_HWCAP, KERNEL_HWCAP_LRCPC3),
HWCAP_CAP(ID_AA64ISAR1_EL1, FRINTTS, IMP, CAP_HWCAP, KERNEL_HWCAP_FRINT),
HWCAP_CAP(ID_AA64ISAR1_EL1, SB, IMP, CAP_HWCAP, KERNEL_HWCAP_SB),
HWCAP_CAP(ID_AA64ISAR1_EL1, BF16, IMP, CAP_HWCAP, KERNEL_HWCAP_BF16),
@@ -2821,6 +2839,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
HWCAP_CAP(ID_AA64ZFR0_EL1, AES, IMP, CAP_HWCAP, KERNEL_HWCAP_SVEAES),
HWCAP_CAP(ID_AA64ZFR0_EL1, AES, PMULL128, CAP_HWCAP, KERNEL_HWCAP_SVEPMULL),
HWCAP_CAP(ID_AA64ZFR0_EL1, BitPerm, IMP, CAP_HWCAP, KERNEL_HWCAP_SVEBITPERM),
+ HWCAP_CAP(ID_AA64ZFR0_EL1, B16B16, IMP, CAP_HWCAP, KERNEL_HWCAP_SVE_B16B16),
HWCAP_CAP(ID_AA64ZFR0_EL1, BF16, IMP, CAP_HWCAP, KERNEL_HWCAP_SVEBF16),
HWCAP_CAP(ID_AA64ZFR0_EL1, BF16, EBF16, CAP_HWCAP, KERNEL_HWCAP_SVE_EBF16),
HWCAP_CAP(ID_AA64ZFR0_EL1, SHA3, IMP, CAP_HWCAP, KERNEL_HWCAP_SVESHA3),
@@ -2981,7 +3000,7 @@ static void update_cpu_capabilities(u16 scope_mask)
!caps->matches(caps, cpucap_default_scope(caps)))
continue;
- if (caps->desc)
+ if (caps->desc && !caps->cpus)
pr_info("detected: %s\n", caps->desc);
__set_bit(caps->capability, system_cpucaps);
@@ -3153,36 +3172,28 @@ static void verify_local_elf_hwcaps(void)
static void verify_sve_features(void)
{
- u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
- u64 zcr = read_zcr_features();
+ unsigned long cpacr = cpacr_save_enable_kernel_sve();
- unsigned int safe_len = safe_zcr & ZCR_ELx_LEN_MASK;
- unsigned int len = zcr & ZCR_ELx_LEN_MASK;
-
- if (len < safe_len || vec_verify_vq_map(ARM64_VEC_SVE)) {
+ if (vec_verify_vq_map(ARM64_VEC_SVE)) {
pr_crit("CPU%d: SVE: vector length support mismatch\n",
smp_processor_id());
cpu_die_early();
}
- /* Add checks on other ZCR bits here if necessary */
+ cpacr_restore(cpacr);
}
static void verify_sme_features(void)
{
- u64 safe_smcr = read_sanitised_ftr_reg(SYS_SMCR_EL1);
- u64 smcr = read_smcr_features();
-
- unsigned int safe_len = safe_smcr & SMCR_ELx_LEN_MASK;
- unsigned int len = smcr & SMCR_ELx_LEN_MASK;
+ unsigned long cpacr = cpacr_save_enable_kernel_sme();
- if (len < safe_len || vec_verify_vq_map(ARM64_VEC_SME)) {
+ if (vec_verify_vq_map(ARM64_VEC_SME)) {
pr_crit("CPU%d: SME: vector length support mismatch\n",
smp_processor_id());
cpu_die_early();
}
- /* Add checks on other SMCR bits here if necessary */
+ cpacr_restore(cpacr);
}
static void verify_hyp_capabilities(void)
@@ -3289,7 +3300,6 @@ EXPORT_SYMBOL_GPL(this_cpu_has_cap);
* This helper function is used in a narrow window when,
* - The system wide safe registers are set with all the SMP CPUs and,
* - The SYSTEM_FEATURE system_cpucaps may not have been set.
- * In all other cases cpus_have_{const_}cap() should be used.
*/
static bool __maybe_unused __system_matches_cap(unsigned int n)
{
@@ -3328,23 +3338,50 @@ unsigned long cpu_get_elf_hwcap2(void)
return elf_hwcap[1];
}
-static void __init setup_system_capabilities(void)
+void __init setup_system_features(void)
{
+ int i;
/*
- * We have finalised the system-wide safe feature
- * registers, finalise the capabilities that depend
- * on it. Also enable all the available capabilities,
- * that are not enabled already.
+ * The system-wide safe feature feature register values have been
+ * finalized. Finalize and log the available system capabilities.
*/
update_cpu_capabilities(SCOPE_SYSTEM);
+ if (IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN) &&
+ !cpus_have_cap(ARM64_HAS_PAN))
+ pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n");
+
+ /*
+ * Enable all the available capabilities which have not been enabled
+ * already.
+ */
enable_cpu_capabilities(SCOPE_ALL & ~SCOPE_BOOT_CPU);
+
+ kpti_install_ng_mappings();
+
+ sve_setup();
+ sme_setup();
+
+ /*
+ * Check for sane CTR_EL0.CWG value.
+ */
+ if (!cache_type_cwg())
+ pr_warn("No Cache Writeback Granule information, assuming %d\n",
+ ARCH_DMA_MINALIGN);
+
+ for (i = 0; i < ARM64_NCAPS; i++) {
+ const struct arm64_cpu_capabilities *caps = cpucap_ptrs[i];
+
+ if (caps && caps->cpus && caps->desc &&
+ cpumask_any(caps->cpus) < nr_cpu_ids)
+ pr_info("detected: %s on CPU%*pbl\n",
+ caps->desc, cpumask_pr_args(caps->cpus));
+ }
}
-void __init setup_cpu_features(void)
+void __init setup_user_features(void)
{
- u32 cwg;
+ user_feature_fixup();
- setup_system_capabilities();
setup_elf_hwcaps(arm64_elf_hwcaps);
if (system_supports_32bit_el0()) {
@@ -3352,20 +3389,7 @@ void __init setup_cpu_features(void)
elf_hwcap_fixup();
}
- if (system_uses_ttbr0_pan())
- pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n");
-
- sve_setup();
- sme_setup();
minsigstksz_setup();
-
- /*
- * Check for sane CTR_EL0.CWG value.
- */
- cwg = cache_type_cwg();
- if (!cwg)
- pr_warn("No Cache Writeback Granule information, assuming %d\n",
- ARCH_DMA_MINALIGN);
}
static int enable_mismatched_32bit_el0(unsigned int cpu)
@@ -3422,7 +3446,7 @@ subsys_initcall_sync(init_32bit_el0_mask);
static void __maybe_unused cpu_enable_cnp(struct arm64_cpu_capabilities const *cap)
{
- cpu_replace_ttbr1(lm_alias(swapper_pg_dir), idmap_pg_dir);
+ cpu_enable_swapper_cnp();
}
/*
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 98fda8500535..a257da7b56fe 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -127,6 +127,9 @@ static const char *const hwcap_str[] = {
[KERNEL_HWCAP_SME_F16F16] = "smef16f16",
[KERNEL_HWCAP_MOPS] = "mops",
[KERNEL_HWCAP_HBC] = "hbc",
+ [KERNEL_HWCAP_SVE_B16B16] = "sveb16b16",
+ [KERNEL_HWCAP_LRCPC3] = "lrcpc3",
+ [KERNEL_HWCAP_LSE128] = "lse128",
};
#ifdef CONFIG_COMPAT
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 2b478ca356b0..0228001347be 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -71,10 +71,6 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
return pgprot_val(PAGE_KERNEL_EXEC);
}
-/* we will fill this structure from the stub, so don't put it in .bss */
-struct screen_info screen_info __section(".data");
-EXPORT_SYMBOL(screen_info);
-
int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
{
pteval_t prot_val = create_mapping_protection(md);
@@ -113,8 +109,7 @@ static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data)
pte = set_pte_bit(pte, __pgprot(PTE_RDONLY));
if (md->attribute & EFI_MEMORY_XP)
pte = set_pte_bit(pte, __pgprot(PTE_PXN));
- else if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) &&
- system_supports_bti() && spd->has_bti)
+ else if (system_supports_bti_kernel() && spd->has_bti)
pte = set_pte_bit(pte, __pgprot(PTE_GP));
set_pte(ptep, pte);
return 0;
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 91e44ac7150f..1559c706d32d 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -589,7 +589,6 @@ static struct ctl_table sve_default_vl_table[] = {
.proc_handler = vec_proc_do_default_vl,
.extra1 = &vl_info[ARM64_VEC_SVE],
},
- { }
};
static int __init sve_sysctl_init(void)
@@ -613,7 +612,6 @@ static struct ctl_table sme_default_vl_table[] = {
.proc_handler = vec_proc_do_default_vl,
.extra1 = &vl_info[ARM64_VEC_SME],
},
- { }
};
static int __init sme_sysctl_init(void)
@@ -1160,44 +1158,20 @@ fail:
panic("Cannot allocate percpu memory for EFI SVE save/restore");
}
-/*
- * Enable SVE for EL1.
- * Intended for use by the cpufeatures code during CPU boot.
- */
-void sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
+void cpu_enable_sve(const struct arm64_cpu_capabilities *__always_unused p)
{
write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);
isb();
}
-/*
- * Read the pseudo-ZCR used by cpufeatures to identify the supported SVE
- * vector length.
- *
- * Use only if SVE is present.
- * This function clobbers the SVE vector length.
- */
-u64 read_zcr_features(void)
-{
- /*
- * Set the maximum possible VL, and write zeroes to all other
- * bits to see if they stick.
- */
- sve_kernel_enable(NULL);
- write_sysreg_s(ZCR_ELx_LEN_MASK, SYS_ZCR_EL1);
-
- /* Return LEN value that would be written to get the maximum VL */
- return sve_vq_from_vl(sve_get_vl()) - 1;
-}
-
void __init sve_setup(void)
{
struct vl_info *info = &vl_info[ARM64_VEC_SVE];
- u64 zcr;
DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
unsigned long b;
+ int max_bit;
- if (!system_supports_sve())
+ if (!cpus_have_cap(ARM64_SVE))
return;
/*
@@ -1208,17 +1182,8 @@ void __init sve_setup(void)
if (WARN_ON(!test_bit(__vq_to_bit(SVE_VQ_MIN), info->vq_map)))
set_bit(__vq_to_bit(SVE_VQ_MIN), info->vq_map);
- zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
- info->max_vl = sve_vl_from_vq((zcr & ZCR_ELx_LEN_MASK) + 1);
-
- /*
- * Sanity-check that the max VL we determined through CPU features
- * corresponds properly to sve_vq_map. If not, do our best:
- */
- if (WARN_ON(info->max_vl != find_supported_vector_length(ARM64_VEC_SVE,
- info->max_vl)))
- info->max_vl = find_supported_vector_length(ARM64_VEC_SVE,
- info->max_vl);
+ max_bit = find_first_bit(info->vq_map, SVE_VQ_MAX);
+ info->max_vl = sve_vl_from_vq(__bit_to_vq(max_bit));
/*
* For the default VL, pick the maximum supported value <= 64.
@@ -1296,7 +1261,7 @@ static void sme_free(struct task_struct *task)
task->thread.sme_state = NULL;
}
-void sme_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
+void cpu_enable_sme(const struct arm64_cpu_capabilities *__always_unused p)
{
/* Set priority for all PEs to architecturally defined minimum */
write_sysreg_s(read_sysreg_s(SYS_SMPRI_EL1) & ~SMPRI_EL1_PRIORITY_MASK,
@@ -1311,80 +1276,48 @@ void sme_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
isb();
}
-/*
- * This must be called after sme_kernel_enable(), we rely on the
- * feature table being sorted to ensure this.
- */
-void sme2_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
+void cpu_enable_sme2(const struct arm64_cpu_capabilities *__always_unused p)
{
+ /* This must be enabled after SME */
+ BUILD_BUG_ON(ARM64_SME2 <= ARM64_SME);
+
/* Allow use of ZT0 */
write_sysreg_s(read_sysreg_s(SYS_SMCR_EL1) | SMCR_ELx_EZT0_MASK,
SYS_SMCR_EL1);
}
-/*
- * This must be called after sme_kernel_enable(), we rely on the
- * feature table being sorted to ensure this.
- */
-void fa64_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
+void cpu_enable_fa64(const struct arm64_cpu_capabilities *__always_unused p)
{
+ /* This must be enabled after SME */
+ BUILD_BUG_ON(ARM64_SME_FA64 <= ARM64_SME);
+
/* Allow use of FA64 */
write_sysreg_s(read_sysreg_s(SYS_SMCR_EL1) | SMCR_ELx_FA64_MASK,
SYS_SMCR_EL1);
}
-/*
- * Read the pseudo-SMCR used by cpufeatures to identify the supported
- * vector length.
- *
- * Use only if SME is present.
- * This function clobbers the SME vector length.
- */
-u64 read_smcr_features(void)
-{
- sme_kernel_enable(NULL);
-
- /*
- * Set the maximum possible VL.
- */
- write_sysreg_s(read_sysreg_s(SYS_SMCR_EL1) | SMCR_ELx_LEN_MASK,
- SYS_SMCR_EL1);
-
- /* Return LEN value that would be written to get the maximum VL */
- return sve_vq_from_vl(sme_get_vl()) - 1;
-}
-
void __init sme_setup(void)
{
struct vl_info *info = &vl_info[ARM64_VEC_SME];
- u64 smcr;
- int min_bit;
+ int min_bit, max_bit;
- if (!system_supports_sme())
+ if (!cpus_have_cap(ARM64_SME))
return;
/*
* SME doesn't require any particular vector length be
* supported but it does require at least one. We should have
* disabled the feature entirely while bringing up CPUs but
- * let's double check here.
+ * let's double check here. The bitmap is SVE_VQ_MAP sized for
+ * sharing with SVE.
*/
WARN_ON(bitmap_empty(info->vq_map, SVE_VQ_MAX));
min_bit = find_last_bit(info->vq_map, SVE_VQ_MAX);
info->min_vl = sve_vl_from_vq(__bit_to_vq(min_bit));
- smcr = read_sanitised_ftr_reg(SYS_SMCR_EL1);
- info->max_vl = sve_vl_from_vq((smcr & SMCR_ELx_LEN_MASK) + 1);
-
- /*
- * Sanity-check that the max VL we determined through CPU features
- * corresponds properly to sme_vq_map. If not, do our best:
- */
- if (WARN_ON(info->max_vl != find_supported_vector_length(ARM64_VEC_SME,
- info->max_vl)))
- info->max_vl = find_supported_vector_length(ARM64_VEC_SME,
- info->max_vl);
+ max_bit = find_first_bit(info->vq_map, SVE_VQ_MAX);
+ info->max_vl = sve_vl_from_vq(__bit_to_vq(max_bit));
WARN_ON(info->min_vl > info->max_vl);
@@ -1529,8 +1462,17 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)
*/
void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs)
{
- /* TODO: implement lazy context saving/restoring */
- WARN_ON(1);
+ /* Even if we chose not to use FPSIMD, the hardware could still trap: */
+ if (!system_supports_fpsimd()) {
+ force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc, 0);
+ return;
+ }
+
+ /*
+ * When FPSIMD is enabled, we should never take a trap unless something
+ * has gone very wrong.
+ */
+ BUG();
}
/*
@@ -1771,13 +1713,23 @@ void fpsimd_bind_state_to_cpu(struct cpu_fp_state *state)
void fpsimd_restore_current_state(void)
{
/*
- * For the tasks that were created before we detected the absence of
- * FP/SIMD, the TIF_FOREIGN_FPSTATE could be set via fpsimd_thread_switch(),
- * e.g, init. This could be then inherited by the children processes.
- * If we later detect that the system doesn't support FP/SIMD,
- * we must clear the flag for all the tasks to indicate that the
- * FPSTATE is clean (as we can't have one) to avoid looping for ever in
- * do_notify_resume().
+ * TIF_FOREIGN_FPSTATE is set on the init task and copied by
+ * arch_dup_task_struct() regardless of whether FP/SIMD is detected.
+ * Thus user threads can have this set even when FP/SIMD hasn't been
+ * detected.
+ *
+ * When FP/SIMD is detected, begin_new_exec() will set
+ * TIF_FOREIGN_FPSTATE via flush_thread() -> fpsimd_flush_thread(),
+ * and fpsimd_thread_switch() will set TIF_FOREIGN_FPSTATE when
+ * switching tasks. We detect FP/SIMD before we exec the first user
+ * process, ensuring this has TIF_FOREIGN_FPSTATE set and
+ * do_notify_resume() will call fpsimd_restore_current_state() to
+ * install the user FP/SIMD context.
+ *
+ * When FP/SIMD is not detected, nothing else will clear or set
+ * TIF_FOREIGN_FPSTATE prior to the first return to userspace, and
+ * we must clear TIF_FOREIGN_FPSTATE to avoid do_notify_resume()
+ * looping forever calling fpsimd_restore_current_state().
*/
if (!system_supports_fpsimd()) {
clear_thread_flag(TIF_FOREIGN_FPSTATE);
@@ -2110,6 +2062,13 @@ static inline void fpsimd_hotplug_init(void)
static inline void fpsimd_hotplug_init(void) { }
#endif
+void cpu_enable_fpsimd(const struct arm64_cpu_capabilities *__always_unused p)
+{
+ unsigned long enable = CPACR_EL1_FPEN_EL1EN | CPACR_EL1_FPEN_EL0EN;
+ write_sysreg(read_sysreg(CPACR_EL1) | enable, CPACR_EL1);
+ isb();
+}
+
/*
* FP/SIMD support code initialisation.
*/
diff --git a/arch/arm64/kernel/idle.c b/arch/arm64/kernel/idle.c
index c1125753fe9b..05cfb347ec26 100644
--- a/arch/arm64/kernel/idle.c
+++ b/arch/arm64/kernel/idle.c
@@ -20,7 +20,7 @@
* ensure that interrupts are not masked at the PMR (because the core will
* not wake up if we block the wake up signal in the interrupt controller).
*/
-void noinstr cpu_do_idle(void)
+void __cpuidle cpu_do_idle(void)
{
struct arm_cpuidle_irq_context context;
@@ -35,7 +35,7 @@ void noinstr cpu_do_idle(void)
/*
* This is our default idle handler.
*/
-void noinstr arch_cpu_idle(void)
+void __cpuidle arch_cpu_idle(void)
{
/*
* This should do all the clock switching and wait for interrupt
diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
index 35f3c7959513..5e4dc72ab1bd 100644
--- a/arch/arm64/kernel/image-vars.h
+++ b/arch/arm64/kernel/image-vars.h
@@ -27,7 +27,9 @@ PROVIDE(__efistub__text = _text);
PROVIDE(__efistub__end = _end);
PROVIDE(__efistub___inittext_end = __inittext_end);
PROVIDE(__efistub__edata = _edata);
+#if defined(CONFIG_EFI_EARLYCON) || defined(CONFIG_SYSFB)
PROVIDE(__efistub_screen_info = screen_info);
+#endif
PROVIDE(__efistub__ctype = _ctype);
PROVIDE(__pi___memcpy = __pi_memcpy);
diff --git a/arch/arm64/kernel/module-plts.c b/arch/arm64/kernel/module-plts.c
index bd69a4e7cd60..bde32979c06a 100644
--- a/arch/arm64/kernel/module-plts.c
+++ b/arch/arm64/kernel/module-plts.c
@@ -167,9 +167,6 @@ static unsigned int count_plts(Elf64_Sym *syms, Elf64_Rela *rela, int num,
switch (ELF64_R_TYPE(rela[i].r_info)) {
case R_AARCH64_JUMP26:
case R_AARCH64_CALL26:
- if (!IS_ENABLED(CONFIG_RANDOMIZE_BASE))
- break;
-
/*
* We only have to consider branch targets that resolve
* to symbols that are defined in a different section.
@@ -203,8 +200,7 @@ static unsigned int count_plts(Elf64_Sym *syms, Elf64_Rela *rela, int num,
break;
case R_AARCH64_ADR_PREL_PG_HI21_NC:
case R_AARCH64_ADR_PREL_PG_HI21:
- if (!IS_ENABLED(CONFIG_ARM64_ERRATUM_843419) ||
- !cpus_have_const_cap(ARM64_WORKAROUND_843419))
+ if (!cpus_have_final_cap(ARM64_WORKAROUND_843419))
break;
/*
@@ -239,13 +235,13 @@ static unsigned int count_plts(Elf64_Sym *syms, Elf64_Rela *rela, int num,
}
}
- if (IS_ENABLED(CONFIG_ARM64_ERRATUM_843419) &&
- cpus_have_const_cap(ARM64_WORKAROUND_843419))
+ if (cpus_have_final_cap(ARM64_WORKAROUND_843419)) {
/*
* Add some slack so we can skip PLT slots that may trigger
* the erratum due to the placement of the ADRP instruction.
*/
ret += DIV_ROUND_UP(ret, (SZ_4K / sizeof(struct plt_entry)));
+ }
return ret;
}
@@ -269,9 +265,6 @@ static int partition_branch_plt_relas(Elf64_Sym *syms, Elf64_Rela *rela,
{
int i = 0, j = numrels - 1;
- if (!IS_ENABLED(CONFIG_RANDOMIZE_BASE))
- return 0;
-
while (i < j) {
if (branch_rela_needs_plt(syms, &rela[i], dstidx))
i++;
diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index 4edecaac8f91..a41ef3213e1e 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -35,10 +35,10 @@ DEFINE_STATIC_KEY_FALSE(mte_async_or_asymm_mode);
EXPORT_SYMBOL_GPL(mte_async_or_asymm_mode);
#endif
-void mte_sync_tags(pte_t pte)
+void mte_sync_tags(pte_t pte, unsigned int nr_pages)
{
struct page *page = pte_page(pte);
- long i, nr_pages = compound_nr(page);
+ unsigned int i;
/* if PG_mte_tagged is set, tags have already been initialised */
for (i = 0; i < nr_pages; i++, page++) {
@@ -411,8 +411,8 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
struct page *page = get_user_page_vma_remote(mm, addr,
gup_flags, &vma);
- if (IS_ERR_OR_NULL(page)) {
- err = page == NULL ? -EIO : PTR_ERR(page);
+ if (IS_ERR(page)) {
+ err = PTR_ERR(page);
break;
}
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 0fcc4eb1a7ab..7387b68c745b 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -454,7 +454,7 @@ static void ssbs_thread_switch(struct task_struct *next)
* If all CPUs implement the SSBS extension, then we just need to
* context-switch the PSTATE field.
*/
- if (cpus_have_const_cap(ARM64_SSBS))
+ if (alternative_has_cap_unlikely(ARM64_SSBS))
return;
spectre_v4_enable_task_mitigation(next);
@@ -724,7 +724,6 @@ static struct ctl_table tagged_addr_sysctl_table[] = {
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
- { }
};
static int __init tagged_addr_init(void)
diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c
index 05f40c4e18fd..6268a13a1d58 100644
--- a/arch/arm64/kernel/proton-pack.c
+++ b/arch/arm64/kernel/proton-pack.c
@@ -972,7 +972,7 @@ static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot)
* When KPTI is in use, the vectors are switched when exiting to
* user-space.
*/
- if (arm64_kernel_unmapped_at_el0())
+ if (cpus_have_cap(ARM64_UNMAP_KERNEL_AT_EL0))
return;
write_sysreg(v, vbar_el1);
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 960b98b43506..defbab84e9e5 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -32,7 +32,9 @@
#include <linux/irq_work.h>
#include <linux/kernel_stat.h>
#include <linux/kexec.h>
+#include <linux/kgdb.h>
#include <linux/kvm_host.h>
+#include <linux/nmi.h>
#include <asm/alternative.h>
#include <asm/atomic.h>
@@ -72,13 +74,19 @@ enum ipi_msg_type {
IPI_CPU_CRASH_STOP,
IPI_TIMER,
IPI_IRQ_WORK,
- IPI_WAKEUP,
- NR_IPI
+ NR_IPI,
+ /*
+ * Any enum >= NR_IPI and < MAX_IPI is special and not tracable
+ * with trace_ipi_*
+ */
+ IPI_CPU_BACKTRACE = NR_IPI,
+ IPI_KGDB_ROUNDUP,
+ MAX_IPI
};
-static int ipi_irq_base __read_mostly;
-static int nr_ipi __read_mostly = NR_IPI;
-static struct irq_desc *ipi_desc[NR_IPI] __read_mostly;
+static int ipi_irq_base __ro_after_init;
+static int nr_ipi __ro_after_init = NR_IPI;
+static struct irq_desc *ipi_desc[MAX_IPI] __ro_after_init;
static void ipi_setup(int cpu);
@@ -215,7 +223,7 @@ asmlinkage notrace void secondary_start_kernel(void)
if (system_uses_irq_prio_masking())
init_gic_priority_masking();
- rcu_cpu_starting(cpu);
+ rcutree_report_cpu_starting(cpu);
trace_hardirqs_off();
/*
@@ -401,7 +409,7 @@ void __noreturn cpu_die_early(void)
/* Mark this CPU absent */
set_cpu_present(cpu, 0);
- rcu_report_dead(cpu);
+ rcutree_report_cpu_dead();
if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) {
update_cpu_boot_status(CPU_KILL_ME);
@@ -431,9 +439,10 @@ static void __init hyp_mode_check(void)
void __init smp_cpus_done(unsigned int max_cpus)
{
pr_info("SMP: Total of %d processors activated.\n", num_online_cpus());
- setup_cpu_features();
+ setup_system_features();
hyp_mode_check();
apply_alternatives_all();
+ setup_user_features();
mark_linear_text_alias_ro();
}
@@ -520,7 +529,7 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
{
u64 hwid = processor->arm_mpidr;
- if (!(processor->flags & ACPI_MADT_ENABLED)) {
+ if (!acpi_gicc_is_usable(processor)) {
pr_debug("skipping disabled CPU entry with 0x%llx MPIDR\n", hwid);
return;
}
@@ -764,7 +773,6 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = {
[IPI_CPU_CRASH_STOP] = "CPU stop (for crash dump) interrupts",
[IPI_TIMER] = "Timer broadcast interrupts",
[IPI_IRQ_WORK] = "IRQ work interrupts",
- [IPI_WAKEUP] = "CPU wake-up interrupts",
};
static void smp_cross_call(const struct cpumask *target, unsigned int ipinr);
@@ -797,13 +805,6 @@ void arch_send_call_function_single_ipi(int cpu)
smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC);
}
-#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
-void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
-{
- smp_cross_call(mask, IPI_WAKEUP);
-}
-#endif
-
#ifdef CONFIG_IRQ_WORK
void arch_irq_work_raise(void)
{
@@ -854,6 +855,38 @@ static void __noreturn ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs
#endif
}
+static void arm64_backtrace_ipi(cpumask_t *mask)
+{
+ __ipi_send_mask(ipi_desc[IPI_CPU_BACKTRACE], mask);
+}
+
+void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu)
+{
+ /*
+ * NOTE: though nmi_trigger_cpumask_backtrace() has "nmi_" in the name,
+ * nothing about it truly needs to be implemented using an NMI, it's
+ * just that it's _allowed_ to work with NMIs. If ipi_should_be_nmi()
+ * returned false our backtrace attempt will just use a regular IPI.
+ */
+ nmi_trigger_cpumask_backtrace(mask, exclude_cpu, arm64_backtrace_ipi);
+}
+
+#ifdef CONFIG_KGDB
+void kgdb_roundup_cpus(void)
+{
+ int this_cpu = raw_smp_processor_id();
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ /* No need to roundup ourselves */
+ if (cpu == this_cpu)
+ continue;
+
+ __ipi_send_single(ipi_desc[IPI_KGDB_ROUNDUP], cpu);
+ }
+}
+#endif
+
/*
* Main handler for inter-processor interrupts
*/
@@ -897,13 +930,17 @@ static void do_handle_IPI(int ipinr)
break;
#endif
-#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
- case IPI_WAKEUP:
- WARN_ONCE(!acpi_parking_protocol_valid(cpu),
- "CPU%u: Wake-up IPI outside the ACPI parking protocol\n",
- cpu);
+ case IPI_CPU_BACKTRACE:
+ /*
+ * NOTE: in some cases this _won't_ be NMI context. See the
+ * comment in arch_trigger_cpumask_backtrace().
+ */
+ nmi_cpu_backtrace(get_irq_regs());
+ break;
+
+ case IPI_KGDB_ROUNDUP:
+ kgdb_nmicallback(cpu, get_irq_regs());
break;
-#endif
default:
pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr);
@@ -926,6 +963,22 @@ static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
__ipi_send_mask(ipi_desc[ipinr], target);
}
+static bool ipi_should_be_nmi(enum ipi_msg_type ipi)
+{
+ if (!system_uses_irq_prio_masking())
+ return false;
+
+ switch (ipi) {
+ case IPI_CPU_STOP:
+ case IPI_CPU_CRASH_STOP:
+ case IPI_CPU_BACKTRACE:
+ case IPI_KGDB_ROUNDUP:
+ return true;
+ default:
+ return false;
+ }
+}
+
static void ipi_setup(int cpu)
{
int i;
@@ -933,8 +986,14 @@ static void ipi_setup(int cpu)
if (WARN_ON_ONCE(!ipi_irq_base))
return;
- for (i = 0; i < nr_ipi; i++)
- enable_percpu_irq(ipi_irq_base + i, 0);
+ for (i = 0; i < nr_ipi; i++) {
+ if (ipi_should_be_nmi(i)) {
+ prepare_percpu_nmi(ipi_irq_base + i);
+ enable_percpu_nmi(ipi_irq_base + i, 0);
+ } else {
+ enable_percpu_irq(ipi_irq_base + i, 0);
+ }
+ }
}
#ifdef CONFIG_HOTPLUG_CPU
@@ -945,8 +1004,14 @@ static void ipi_teardown(int cpu)
if (WARN_ON_ONCE(!ipi_irq_base))
return;
- for (i = 0; i < nr_ipi; i++)
- disable_percpu_irq(ipi_irq_base + i);
+ for (i = 0; i < nr_ipi; i++) {
+ if (ipi_should_be_nmi(i)) {
+ disable_percpu_nmi(ipi_irq_base + i);
+ teardown_percpu_nmi(ipi_irq_base + i);
+ } else {
+ disable_percpu_irq(ipi_irq_base + i);
+ }
+ }
}
#endif
@@ -954,15 +1019,23 @@ void __init set_smp_ipi_range(int ipi_base, int n)
{
int i;
- WARN_ON(n < NR_IPI);
- nr_ipi = min(n, NR_IPI);
+ WARN_ON(n < MAX_IPI);
+ nr_ipi = min(n, MAX_IPI);
for (i = 0; i < nr_ipi; i++) {
int err;
- err = request_percpu_irq(ipi_base + i, ipi_handler,
- "IPI", &cpu_number);
- WARN_ON(err);
+ if (ipi_should_be_nmi(i)) {
+ err = request_percpu_nmi(ipi_base + i, ipi_handler,
+ "IPI", &cpu_number);
+ WARN(err, "Could not request IPI %d as NMI, err=%d\n",
+ i, err);
+ } else {
+ err = request_percpu_irq(ipi_base + i, ipi_handler,
+ "IPI", &cpu_number);
+ WARN(err, "Could not request IPI %d as IRQ, err=%d\n",
+ i, err);
+ }
ipi_desc[i] = irq_to_desc(ipi_base + i);
irq_set_status_flags(ipi_base + i, IRQ_HIDDEN);
@@ -979,6 +1052,17 @@ void arch_smp_send_reschedule(int cpu)
smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
}
+#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
+void arch_send_wakeup_ipi(unsigned int cpu)
+{
+ /*
+ * We use a scheduler IPI to wake the CPU as this avoids the need for a
+ * dedicated IPI and we can safely handle spurious scheduler IPIs.
+ */
+ smp_send_reschedule(cpu);
+}
+#endif
+
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
void tick_broadcast(const struct cpumask *mask)
{
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index 0fbdf5fe64d8..eca4d0435211 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -55,13 +55,13 @@ void notrace __cpu_suspend_exit(void)
/* Restore CnP bit in TTBR1_EL1 */
if (system_supports_cnp())
- cpu_replace_ttbr1(lm_alias(swapper_pg_dir), idmap_pg_dir);
+ cpu_enable_swapper_cnp();
/*
* PSTATE was not saved over suspend/resume, re-enable any detected
* features that might not have been set correctly.
*/
- if (cpus_have_const_cap(ARM64_HAS_DIT))
+ if (alternative_has_cap_unlikely(ARM64_HAS_DIT))
set_pstate_dit(1);
__uaccess_enable_hw_pan();
@@ -98,6 +98,15 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
struct sleep_stack_data state;
struct arm_cpuidle_irq_context context;
+ /*
+ * Some portions of CPU state (e.g. PSTATE.{PAN,DIT}) are initialized
+ * before alternatives are patched, but are only restored by
+ * __cpu_suspend_exit() after alternatives are patched. To avoid
+ * accidentally losing these bits we must not attempt to suspend until
+ * after alternatives have been patched.
+ */
+ WARN_ON(!system_capabilities_finalized());
+
/* Report any MTE async fault before going to suspend */
mte_suspend_enter();
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index df14336c3a29..4a609e9b65de 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -31,7 +31,7 @@ __do_compat_cache_op(unsigned long start, unsigned long end)
if (fatal_signal_pending(current))
return 0;
- if (cpus_have_const_cap(ARM64_WORKAROUND_1542419)) {
+ if (cpus_have_final_cap(ARM64_WORKAROUND_1542419)) {
/*
* The workaround requires an inner-shareable tlbi.
* We pick the reserved-ASID to minimise the impact.
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 8b70759cdbb9..215e6d7f2df8 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -516,53 +516,7 @@ void do_el1_fpac(struct pt_regs *regs, unsigned long esr)
void do_el0_mops(struct pt_regs *regs, unsigned long esr)
{
- bool wrong_option = esr & ESR_ELx_MOPS_ISS_WRONG_OPTION;
- bool option_a = esr & ESR_ELx_MOPS_ISS_OPTION_A;
- int dstreg = ESR_ELx_MOPS_ISS_DESTREG(esr);
- int srcreg = ESR_ELx_MOPS_ISS_SRCREG(esr);
- int sizereg = ESR_ELx_MOPS_ISS_SIZEREG(esr);
- unsigned long dst, src, size;
-
- dst = pt_regs_read_reg(regs, dstreg);
- src = pt_regs_read_reg(regs, srcreg);
- size = pt_regs_read_reg(regs, sizereg);
-
- /*
- * Put the registers back in the original format suitable for a
- * prologue instruction, using the generic return routine from the
- * Arm ARM (DDI 0487I.a) rules CNTMJ and MWFQH.
- */
- if (esr & ESR_ELx_MOPS_ISS_MEM_INST) {
- /* SET* instruction */
- if (option_a ^ wrong_option) {
- /* Format is from Option A; forward set */
- pt_regs_write_reg(regs, dstreg, dst + size);
- pt_regs_write_reg(regs, sizereg, -size);
- }
- } else {
- /* CPY* instruction */
- if (!(option_a ^ wrong_option)) {
- /* Format is from Option B */
- if (regs->pstate & PSR_N_BIT) {
- /* Backward copy */
- pt_regs_write_reg(regs, dstreg, dst - size);
- pt_regs_write_reg(regs, srcreg, src - size);
- }
- } else {
- /* Format is from Option A */
- if (size & BIT(63)) {
- /* Forward copy */
- pt_regs_write_reg(regs, dstreg, dst + size);
- pt_regs_write_reg(regs, srcreg, src + size);
- pt_regs_write_reg(regs, sizereg, -size);
- }
- }
- }
-
- if (esr & ESR_ELx_MOPS_ISS_FROM_EPILOGUE)
- regs->pc -= 8;
- else
- regs->pc -= 4;
+ arm64_mops_reset_regs(&regs->user_regs, esr);
/*
* If single stepping then finish the step before executing the
@@ -631,7 +585,7 @@ static void ctr_read_handler(unsigned long esr, struct pt_regs *regs)
int rt = ESR_ELx_SYS64_ISS_RT(esr);
unsigned long val = arm64_ftr_reg_user_value(&arm64_ftr_reg_ctrel0);
- if (cpus_have_const_cap(ARM64_WORKAROUND_1542419)) {
+ if (cpus_have_final_cap(ARM64_WORKAROUND_1542419)) {
/* Hide DIC so that we can trap the unnecessary maintenance...*/
val &= ~BIT(CTR_EL0_DIC_SHIFT);
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index d9e1355730ef..5562daf38a22 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -212,7 +212,7 @@ static int __setup_additional_pages(enum vdso_abi abi,
if (IS_ERR(ret))
goto up_fail;
- if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) && system_supports_bti())
+ if (system_supports_bti_kernel())
gp_flags = VM_ARM64_BTI;
vdso_base += VVAR_NR_PAGES * PAGE_SIZE;
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index fe7a53c6781f..8818287f1095 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -78,13 +78,3 @@ include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
# Actual build commands
quiet_cmd_vdsold_and_vdso_check = LD $@
cmd_vdsold_and_vdso_check = $(cmd_ld); $(cmd_vdso_check)
-
-# Install commands for the unstripped file
-quiet_cmd_vdso_install = INSTALL $@
- cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
-
-vdso.so: $(obj)/vdso.so.dbg
- @mkdir -p $(MODLIB)/vdso
- $(call cmd,vdso_install)
-
-vdso_install: vdso.so
diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile
index 2f73e5bca213..1f911a76c5af 100644
--- a/arch/arm64/kernel/vdso32/Makefile
+++ b/arch/arm64/kernel/vdso32/Makefile
@@ -172,13 +172,3 @@ gen-vdsosym := $(srctree)/$(src)/../vdso/gen_vdso_offsets.sh
quiet_cmd_vdsosym = VDSOSYM $@
# The AArch64 nm should be able to read an AArch32 binary
cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
-
-# Install commands for the unstripped file
-quiet_cmd_vdso_install = INSTALL32 $@
- cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/vdso32.so
-
-vdso.so: $(obj)/vdso.so.dbg
- @mkdir -p $(MODLIB)/vdso
- $(call cmd,vdso_install)
-
-vdso_install: vdso.so
diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index 6dcdae4d38cb..13ba691b848f 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -55,11 +55,6 @@ static struct irq_ops arch_timer_irq_ops = {
.get_input_level = kvm_arch_timer_get_input_level,
};
-static bool has_cntpoff(void)
-{
- return (has_vhe() && cpus_have_final_cap(ARM64_HAS_ECV_CNTPOFF));
-}
-
static int nr_timers(struct kvm_vcpu *vcpu)
{
if (!vcpu_has_nv(vcpu))
@@ -180,7 +175,7 @@ u64 kvm_phys_timer_read(void)
return timecounter->cc->read(timecounter->cc);
}
-static void get_timer_map(struct kvm_vcpu *vcpu, struct timer_map *map)
+void get_timer_map(struct kvm_vcpu *vcpu, struct timer_map *map)
{
if (vcpu_has_nv(vcpu)) {
if (is_hyp_ctxt(vcpu)) {
@@ -458,7 +453,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
timer_ctx->irq.level);
if (!userspace_irqchip(vcpu->kvm)) {
- ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
+ ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu,
timer_irq(timer_ctx),
timer_ctx->irq.level,
timer_ctx);
@@ -548,8 +543,7 @@ static void timer_save_state(struct arch_timer_context *ctx)
timer_set_ctl(ctx, read_sysreg_el0(SYS_CNTP_CTL));
cval = read_sysreg_el0(SYS_CNTP_CVAL);
- if (!has_cntpoff())
- cval -= timer_get_offset(ctx);
+ cval -= timer_get_offset(ctx);
timer_set_cval(ctx, cval);
@@ -636,8 +630,7 @@ static void timer_restore_state(struct arch_timer_context *ctx)
cval = timer_get_cval(ctx);
offset = timer_get_offset(ctx);
set_cntpoff(offset);
- if (!has_cntpoff())
- cval += offset;
+ cval += offset;
write_sysreg_el0(cval, SYS_CNTP_CVAL);
isb();
write_sysreg_el0(timer_get_ctl(ctx), SYS_CNTP_CTL);
@@ -943,7 +936,7 @@ void kvm_timer_sync_user(struct kvm_vcpu *vcpu)
unmask_vtimer_irq_user(vcpu);
}
-int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
+void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
{
struct arch_timer_cpu *timer = vcpu_timer(vcpu);
struct timer_map map;
@@ -987,8 +980,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
soft_timer_cancel(&map.emul_vtimer->hrtimer);
if (map.emul_ptimer)
soft_timer_cancel(&map.emul_ptimer->hrtimer);
-
- return 0;
}
static void timer_context_init(struct kvm_vcpu *vcpu, int timerid)
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 4866b3f7b4ea..e5f75f1f1085 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -205,6 +205,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
if (is_protected_kvm_enabled())
pkvm_destroy_hyp_vm(kvm);
+ kfree(kvm->arch.mpidr_data);
kvm_destroy_vcpus(kvm);
kvm_unshare_hyp(kvm, kvm + 1);
@@ -284,7 +285,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
r = kvm_arm_pvtime_supported();
break;
case KVM_CAP_ARM_EL1_32BIT:
- r = cpus_have_const_cap(ARM64_HAS_32BIT_EL1);
+ r = cpus_have_final_cap(ARM64_HAS_32BIT_EL1);
break;
case KVM_CAP_GUEST_DEBUG_HW_BPS:
r = get_num_brps();
@@ -296,7 +297,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
r = kvm_arm_support_pmu_v3();
break;
case KVM_CAP_ARM_INJECT_SERROR_ESR:
- r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN);
+ r = cpus_have_final_cap(ARM64_HAS_RAS_EXTN);
break;
case KVM_CAP_ARM_VM_IPA_SIZE:
r = get_kvm_ipa_limit();
@@ -317,6 +318,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES:
r = kvm_supported_block_sizes();
break;
+ case KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES:
+ r = BIT(0);
+ break;
default:
r = 0;
}
@@ -367,7 +371,6 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
/* Force users to call KVM_ARM_VCPU_INIT */
vcpu_clear_flag(vcpu, VCPU_INITIALIZED);
- bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES);
vcpu->arch.mmu_page_cache.gfp_zero = __GFP_ZERO;
@@ -438,9 +441,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
* We might get preempted before the vCPU actually runs, but
* over-invalidation doesn't affect correctness.
*/
- if (*last_ran != vcpu->vcpu_id) {
+ if (*last_ran != vcpu->vcpu_idx) {
kvm_call_hyp(__kvm_flush_cpu_context, mmu);
- *last_ran = vcpu->vcpu_id;
+ *last_ran = vcpu->vcpu_idx;
}
vcpu->cpu = cpu;
@@ -448,7 +451,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
kvm_vgic_load(vcpu);
kvm_timer_vcpu_load(vcpu);
if (has_vhe())
- kvm_vcpu_load_sysregs_vhe(vcpu);
+ kvm_vcpu_load_vhe(vcpu);
kvm_arch_vcpu_load_fp(vcpu);
kvm_vcpu_pmu_restore_guest(vcpu);
if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
@@ -472,7 +475,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
kvm_arch_vcpu_put_debug_state_flags(vcpu);
kvm_arch_vcpu_put_fp(vcpu);
if (has_vhe())
- kvm_vcpu_put_sysregs_vhe(vcpu);
+ kvm_vcpu_put_vhe(vcpu);
kvm_timer_vcpu_put(vcpu);
kvm_vgic_put(vcpu);
kvm_vcpu_pmu_restore_host(vcpu);
@@ -578,6 +581,57 @@ static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu)
return vcpu_get_flag(vcpu, VCPU_INITIALIZED);
}
+static void kvm_init_mpidr_data(struct kvm *kvm)
+{
+ struct kvm_mpidr_data *data = NULL;
+ unsigned long c, mask, nr_entries;
+ u64 aff_set = 0, aff_clr = ~0UL;
+ struct kvm_vcpu *vcpu;
+
+ mutex_lock(&kvm->arch.config_lock);
+
+ if (kvm->arch.mpidr_data || atomic_read(&kvm->online_vcpus) == 1)
+ goto out;
+
+ kvm_for_each_vcpu(c, vcpu, kvm) {
+ u64 aff = kvm_vcpu_get_mpidr_aff(vcpu);
+ aff_set |= aff;
+ aff_clr &= aff;
+ }
+
+ /*
+ * A significant bit can be either 0 or 1, and will only appear in
+ * aff_set. Use aff_clr to weed out the useless stuff.
+ */
+ mask = aff_set ^ aff_clr;
+ nr_entries = BIT_ULL(hweight_long(mask));
+
+ /*
+ * Don't let userspace fool us. If we need more than a single page
+ * to describe the compressed MPIDR array, just fall back to the
+ * iterative method. Single vcpu VMs do not need this either.
+ */
+ if (struct_size(data, cmpidr_to_idx, nr_entries) <= PAGE_SIZE)
+ data = kzalloc(struct_size(data, cmpidr_to_idx, nr_entries),
+ GFP_KERNEL_ACCOUNT);
+
+ if (!data)
+ goto out;
+
+ data->mpidr_mask = mask;
+
+ kvm_for_each_vcpu(c, vcpu, kvm) {
+ u64 aff = kvm_vcpu_get_mpidr_aff(vcpu);
+ u16 index = kvm_mpidr_index(data, aff);
+
+ data->cmpidr_to_idx[index] = c;
+ }
+
+ kvm->arch.mpidr_data = data;
+out:
+ mutex_unlock(&kvm->arch.config_lock);
+}
+
/*
* Handle both the initialisation that is being done when the vcpu is
* run for the first time, as well as the updates that must be
@@ -601,6 +655,8 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
if (likely(vcpu_has_run_once(vcpu)))
return 0;
+ kvm_init_mpidr_data(kvm);
+
kvm_arm_vcpu_init_debug(vcpu);
if (likely(irqchip_in_kernel(kvm))) {
@@ -801,8 +857,7 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
}
if (kvm_check_request(KVM_REQ_RELOAD_PMU, vcpu))
- kvm_pmu_handle_pmcr(vcpu,
- __vcpu_sys_reg(vcpu, PMCR_EL0));
+ kvm_vcpu_reload_pmu(vcpu);
if (kvm_check_request(KVM_REQ_RESYNC_PMU_EL0, vcpu))
kvm_vcpu_pmu_restore_guest(vcpu);
@@ -950,7 +1005,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
* making a thread's VMID inactive. So we need to call
* kvm_arm_vmid_update() in non-premptible context.
*/
- kvm_arm_vmid_update(&vcpu->arch.hw_mmu->vmid);
+ if (kvm_arm_vmid_update(&vcpu->arch.hw_mmu->vmid) &&
+ has_vhe())
+ __load_stage2(vcpu->arch.hw_mmu,
+ vcpu->arch.hw_mmu->arch);
kvm_pmu_flush_hwstate(vcpu);
@@ -1134,27 +1192,23 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
bool line_status)
{
u32 irq = irq_level->irq;
- unsigned int irq_type, vcpu_idx, irq_num;
- int nrcpus = atomic_read(&kvm->online_vcpus);
+ unsigned int irq_type, vcpu_id, irq_num;
struct kvm_vcpu *vcpu = NULL;
bool level = irq_level->level;
irq_type = (irq >> KVM_ARM_IRQ_TYPE_SHIFT) & KVM_ARM_IRQ_TYPE_MASK;
- vcpu_idx = (irq >> KVM_ARM_IRQ_VCPU_SHIFT) & KVM_ARM_IRQ_VCPU_MASK;
- vcpu_idx += ((irq >> KVM_ARM_IRQ_VCPU2_SHIFT) & KVM_ARM_IRQ_VCPU2_MASK) * (KVM_ARM_IRQ_VCPU_MASK + 1);
+ vcpu_id = (irq >> KVM_ARM_IRQ_VCPU_SHIFT) & KVM_ARM_IRQ_VCPU_MASK;
+ vcpu_id += ((irq >> KVM_ARM_IRQ_VCPU2_SHIFT) & KVM_ARM_IRQ_VCPU2_MASK) * (KVM_ARM_IRQ_VCPU_MASK + 1);
irq_num = (irq >> KVM_ARM_IRQ_NUM_SHIFT) & KVM_ARM_IRQ_NUM_MASK;
- trace_kvm_irq_line(irq_type, vcpu_idx, irq_num, irq_level->level);
+ trace_kvm_irq_line(irq_type, vcpu_id, irq_num, irq_level->level);
switch (irq_type) {
case KVM_ARM_IRQ_TYPE_CPU:
if (irqchip_in_kernel(kvm))
return -ENXIO;
- if (vcpu_idx >= nrcpus)
- return -EINVAL;
-
- vcpu = kvm_get_vcpu(kvm, vcpu_idx);
+ vcpu = kvm_get_vcpu_by_id(kvm, vcpu_id);
if (!vcpu)
return -EINVAL;
@@ -1166,17 +1220,14 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
if (!irqchip_in_kernel(kvm))
return -ENXIO;
- if (vcpu_idx >= nrcpus)
- return -EINVAL;
-
- vcpu = kvm_get_vcpu(kvm, vcpu_idx);
+ vcpu = kvm_get_vcpu_by_id(kvm, vcpu_id);
if (!vcpu)
return -EINVAL;
if (irq_num < VGIC_NR_SGIS || irq_num >= VGIC_NR_PRIVATE_IRQS)
return -EINVAL;
- return kvm_vgic_inject_irq(kvm, vcpu->vcpu_id, irq_num, level, NULL);
+ return kvm_vgic_inject_irq(kvm, vcpu, irq_num, level, NULL);
case KVM_ARM_IRQ_TYPE_SPI:
if (!irqchip_in_kernel(kvm))
return -ENXIO;
@@ -1184,12 +1235,36 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
if (irq_num < VGIC_NR_PRIVATE_IRQS)
return -EINVAL;
- return kvm_vgic_inject_irq(kvm, 0, irq_num, level, NULL);
+ return kvm_vgic_inject_irq(kvm, NULL, irq_num, level, NULL);
}
return -EINVAL;
}
+static unsigned long system_supported_vcpu_features(void)
+{
+ unsigned long features = KVM_VCPU_VALID_FEATURES;
+
+ if (!cpus_have_final_cap(ARM64_HAS_32BIT_EL1))
+ clear_bit(KVM_ARM_VCPU_EL1_32BIT, &features);
+
+ if (!kvm_arm_support_pmu_v3())
+ clear_bit(KVM_ARM_VCPU_PMU_V3, &features);
+
+ if (!system_supports_sve())
+ clear_bit(KVM_ARM_VCPU_SVE, &features);
+
+ if (!system_has_full_ptr_auth()) {
+ clear_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, &features);
+ clear_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, &features);
+ }
+
+ if (!cpus_have_final_cap(ARM64_HAS_NESTED_VIRT))
+ clear_bit(KVM_ARM_VCPU_HAS_EL2, &features);
+
+ return features;
+}
+
static int kvm_vcpu_init_check_features(struct kvm_vcpu *vcpu,
const struct kvm_vcpu_init *init)
{
@@ -1204,12 +1279,25 @@ static int kvm_vcpu_init_check_features(struct kvm_vcpu *vcpu,
return -ENOENT;
}
- if (!test_bit(KVM_ARM_VCPU_EL1_32BIT, &features))
- return 0;
+ if (features & ~system_supported_vcpu_features())
+ return -EINVAL;
- if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1))
+ /*
+ * For now make sure that both address/generic pointer authentication
+ * features are requested by the userspace together.
+ */
+ if (test_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, &features) !=
+ test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, &features))
return -EINVAL;
+ /* Disallow NV+SVE for the time being */
+ if (test_bit(KVM_ARM_VCPU_HAS_EL2, &features) &&
+ test_bit(KVM_ARM_VCPU_SVE, &features))
+ return -EINVAL;
+
+ if (!test_bit(KVM_ARM_VCPU_EL1_32BIT, &features))
+ return 0;
+
/* MTE is incompatible with AArch32 */
if (kvm_has_mte(vcpu->kvm))
return -EINVAL;
@@ -1226,7 +1314,23 @@ static bool kvm_vcpu_init_changed(struct kvm_vcpu *vcpu,
{
unsigned long features = init->features[0];
- return !bitmap_equal(vcpu->arch.features, &features, KVM_VCPU_MAX_FEATURES);
+ return !bitmap_equal(vcpu->kvm->arch.vcpu_features, &features,
+ KVM_VCPU_MAX_FEATURES);
+}
+
+static int kvm_setup_vcpu(struct kvm_vcpu *vcpu)
+{
+ struct kvm *kvm = vcpu->kvm;
+ int ret = 0;
+
+ /*
+ * When the vCPU has a PMU, but no PMU is set for the guest
+ * yet, set the default one.
+ */
+ if (kvm_vcpu_has_pmu(vcpu) && !kvm->arch.arm_pmu)
+ ret = kvm_arm_set_default_pmu(kvm);
+
+ return ret;
}
static int __kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
@@ -1239,21 +1343,21 @@ static int __kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
mutex_lock(&kvm->arch.config_lock);
if (test_bit(KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED, &kvm->arch.flags) &&
- !bitmap_equal(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES))
+ kvm_vcpu_init_changed(vcpu, init))
goto out_unlock;
- bitmap_copy(vcpu->arch.features, &features, KVM_VCPU_MAX_FEATURES);
+ bitmap_copy(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES);
- /* Now we know what it is, we can reset it. */
- ret = kvm_reset_vcpu(vcpu);
- if (ret) {
- bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES);
+ ret = kvm_setup_vcpu(vcpu);
+ if (ret)
goto out_unlock;
- }
- bitmap_copy(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES);
+ /* Now we know what it is, we can reset it. */
+ kvm_reset_vcpu(vcpu);
+
set_bit(KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED, &kvm->arch.flags);
vcpu_set_flag(vcpu, VCPU_INITIALIZED);
+ ret = 0;
out_unlock:
mutex_unlock(&kvm->arch.config_lock);
return ret;
@@ -1278,7 +1382,8 @@ static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
if (kvm_vcpu_init_changed(vcpu, init))
return -EINVAL;
- return kvm_reset_vcpu(vcpu);
+ kvm_reset_vcpu(vcpu);
+ return 0;
}
static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
@@ -1629,6 +1734,13 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
return kvm_vm_set_attr(kvm, &attr);
}
+ case KVM_ARM_GET_REG_WRITABLE_MASKS: {
+ struct reg_mask_range range;
+
+ if (copy_from_user(&range, argp, sizeof(range)))
+ return -EFAULT;
+ return kvm_vm_ioctl_get_reg_writable_masks(kvm, &range);
+ }
default:
return -EINVAL;
}
@@ -1777,7 +1889,7 @@ static void hyp_install_host_vector(void)
* Call initialization code, and switch to the full blown HYP code.
* If the cpucaps haven't been finalized yet, something has gone very
* wrong, and hyp will crash and burn when it uses any
- * cpus_have_const_cap() wrapper.
+ * cpus_have_*_cap() wrapper.
*/
BUG_ON(!system_capabilities_finalized());
params = this_cpu_ptr_nvhe_sym(kvm_init_params);
@@ -2310,7 +2422,7 @@ static int __init init_hyp_mode(void)
if (is_protected_kvm_enabled()) {
if (IS_ENABLED(CONFIG_ARM64_PTR_AUTH_KERNEL) &&
- cpus_have_const_cap(ARM64_HAS_ADDRESS_AUTH))
+ cpus_have_final_cap(ARM64_HAS_ADDRESS_AUTH))
pkvm_hyp_init_ptrauth();
init_cpu_logical_map();
@@ -2341,6 +2453,18 @@ struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr)
unsigned long i;
mpidr &= MPIDR_HWID_BITMASK;
+
+ if (kvm->arch.mpidr_data) {
+ u16 idx = kvm_mpidr_index(kvm->arch.mpidr_data, mpidr);
+
+ vcpu = kvm_get_vcpu(kvm,
+ kvm->arch.mpidr_data->cmpidr_to_idx[idx]);
+ if (mpidr != kvm_vcpu_get_mpidr_aff(vcpu))
+ vcpu = NULL;
+
+ return vcpu;
+ }
+
kvm_for_each_vcpu(i, vcpu, kvm) {
if (mpidr == kvm_vcpu_get_mpidr_aff(vcpu))
return vcpu;
diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index 9ced1bf0c2b7..06185216a297 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -648,15 +648,80 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
SR_TRAP(SYS_APGAKEYLO_EL1, CGT_HCR_APK),
SR_TRAP(SYS_APGAKEYHI_EL1, CGT_HCR_APK),
/* All _EL2 registers */
- SR_RANGE_TRAP(sys_reg(3, 4, 0, 0, 0),
- sys_reg(3, 4, 3, 15, 7), CGT_HCR_NV),
+ SR_TRAP(SYS_BRBCR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_VPIDR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_VMPIDR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_SCTLR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_ACTLR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_SCTLR2_EL2, CGT_HCR_NV),
+ SR_RANGE_TRAP(SYS_HCR_EL2,
+ SYS_HCRX_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_SMPRIMAP_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_SMCR_EL2, CGT_HCR_NV),
+ SR_RANGE_TRAP(SYS_TTBR0_EL2,
+ SYS_TCR2_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_VTTBR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_VTCR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_VNCR_EL2, CGT_HCR_NV),
+ SR_RANGE_TRAP(SYS_HDFGRTR_EL2,
+ SYS_HAFGRTR_EL2, CGT_HCR_NV),
/* Skip the SP_EL1 encoding... */
SR_TRAP(SYS_SPSR_EL2, CGT_HCR_NV),
SR_TRAP(SYS_ELR_EL2, CGT_HCR_NV),
- SR_RANGE_TRAP(sys_reg(3, 4, 4, 1, 1),
- sys_reg(3, 4, 10, 15, 7), CGT_HCR_NV),
- SR_RANGE_TRAP(sys_reg(3, 4, 12, 0, 0),
- sys_reg(3, 4, 14, 15, 7), CGT_HCR_NV),
+ /* Skip SPSR_irq, SPSR_abt, SPSR_und, SPSR_fiq */
+ SR_TRAP(SYS_AFSR0_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_AFSR1_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_ESR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_VSESR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_TFSR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_FAR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_HPFAR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_PMSCR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_MAIR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_AMAIR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_MPAMHCR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_MPAMVPMV_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_MPAM2_EL2, CGT_HCR_NV),
+ SR_RANGE_TRAP(SYS_MPAMVPM0_EL2,
+ SYS_MPAMVPM7_EL2, CGT_HCR_NV),
+ /*
+ * Note that the spec. describes a group of MEC registers
+ * whose access should not trap, therefore skip the following:
+ * MECID_A0_EL2, MECID_A1_EL2, MECID_P0_EL2,
+ * MECID_P1_EL2, MECIDR_EL2, VMECID_A_EL2,
+ * VMECID_P_EL2.
+ */
+ SR_RANGE_TRAP(SYS_VBAR_EL2,
+ SYS_RMR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_VDISR_EL2, CGT_HCR_NV),
+ /* ICH_AP0R<m>_EL2 */
+ SR_RANGE_TRAP(SYS_ICH_AP0R0_EL2,
+ SYS_ICH_AP0R3_EL2, CGT_HCR_NV),
+ /* ICH_AP1R<m>_EL2 */
+ SR_RANGE_TRAP(SYS_ICH_AP1R0_EL2,
+ SYS_ICH_AP1R3_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_ICC_SRE_EL2, CGT_HCR_NV),
+ SR_RANGE_TRAP(SYS_ICH_HCR_EL2,
+ SYS_ICH_EISR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_ICH_ELRSR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_ICH_VMCR_EL2, CGT_HCR_NV),
+ /* ICH_LR<m>_EL2 */
+ SR_RANGE_TRAP(SYS_ICH_LR0_EL2,
+ SYS_ICH_LR15_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_CONTEXTIDR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_TPIDR_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_SCXTNUM_EL2, CGT_HCR_NV),
+ /* AMEVCNTVOFF0<n>_EL2, AMEVCNTVOFF1<n>_EL2 */
+ SR_RANGE_TRAP(SYS_AMEVCNTVOFF0n_EL2(0),
+ SYS_AMEVCNTVOFF1n_EL2(15), CGT_HCR_NV),
+ /* CNT*_EL2 */
+ SR_TRAP(SYS_CNTVOFF_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_CNTPOFF_EL2, CGT_HCR_NV),
+ SR_TRAP(SYS_CNTHCTL_EL2, CGT_HCR_NV),
+ SR_RANGE_TRAP(SYS_CNTHP_TVAL_EL2,
+ SYS_CNTHP_CVAL_EL2, CGT_HCR_NV),
+ SR_RANGE_TRAP(SYS_CNTHV_TVAL_EL2,
+ SYS_CNTHV_CVAL_EL2, CGT_HCR_NV),
/* All _EL02, _EL12 registers */
SR_RANGE_TRAP(sys_reg(3, 5, 0, 0, 0),
sys_reg(3, 5, 10, 15, 7), CGT_HCR_NV),
@@ -977,6 +1042,8 @@ enum fg_filter_id {
static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
/* HFGRTR_EL2, HFGWTR_EL2 */
+ SR_FGT(SYS_PIR_EL1, HFGxTR, nPIR_EL1, 0),
+ SR_FGT(SYS_PIRE0_EL1, HFGxTR, nPIRE0_EL1, 0),
SR_FGT(SYS_TPIDR2_EL0, HFGxTR, nTPIDR2_EL0, 0),
SR_FGT(SYS_SMPRI_EL1, HFGxTR, nSMPRI_EL1, 0),
SR_FGT(SYS_ACCDATA_EL1, HFGxTR, nACCDATA_EL1, 0),
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 95f6945c4432..aaf1d4939739 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -815,7 +815,7 @@ int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
struct kvm_vcpu_events *events)
{
events->exception.serror_pending = !!(vcpu->arch.hcr_el2 & HCR_VSE);
- events->exception.serror_has_esr = cpus_have_const_cap(ARM64_HAS_RAS_EXTN);
+ events->exception.serror_has_esr = cpus_have_final_cap(ARM64_HAS_RAS_EXTN);
if (events->exception.serror_pending && events->exception.serror_has_esr)
events->exception.serror_esr = vcpu_get_vsesr(vcpu);
@@ -837,7 +837,7 @@ int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
bool ext_dabt_pending = events->exception.ext_dabt_pending;
if (serror_pending && has_esr) {
- if (!cpus_have_const_cap(ARM64_HAS_RAS_EXTN))
+ if (!cpus_have_final_cap(ARM64_HAS_RAS_EXTN))
return -EINVAL;
if (!((events->exception.serror_esr) & ~ESR_ELx_ISS_MASK))
@@ -874,7 +874,7 @@ u32 __attribute_const__ kvm_target_cpu(void)
break;
case ARM_CPU_IMP_APM:
switch (part_number) {
- case APM_CPU_PART_POTENZA:
+ case APM_CPU_PART_XGENE:
return KVM_ARM_TARGET_XGENE_POTENZA;
}
break;
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 9cfe6bd1dbe4..f99d8af0b9af 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -30,6 +30,7 @@
#include <asm/fpsimd.h>
#include <asm/debug-monitors.h>
#include <asm/processor.h>
+#include <asm/traps.h>
struct kvm_exception_table_entry {
int insn, fixup;
@@ -265,6 +266,22 @@ static inline bool __populate_fault_info(struct kvm_vcpu *vcpu)
return __get_fault_info(vcpu->arch.fault.esr_el2, &vcpu->arch.fault);
}
+static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
+{
+ *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
+ arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2);
+ write_sysreg_el2(*vcpu_pc(vcpu), SYS_ELR);
+
+ /*
+ * Finish potential single step before executing the prologue
+ * instruction.
+ */
+ *vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
+ write_sysreg_el2(*vcpu_cpsr(vcpu), SYS_SPSR);
+
+ return true;
+}
+
static inline void __hyp_sve_restore_guest(struct kvm_vcpu *vcpu)
{
sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1, SYS_ZCR_EL2);
diff --git a/arch/arm64/kvm/hyp/include/nvhe/fixed_config.h b/arch/arm64/kvm/hyp/include/nvhe/fixed_config.h
index 37440e1dda93..e91922daa8ca 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/fixed_config.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/fixed_config.h
@@ -197,7 +197,8 @@
#define PVM_ID_AA64ISAR2_ALLOW (\
ARM64_FEATURE_MASK(ID_AA64ISAR2_EL1_GPA3) | \
- ARM64_FEATURE_MASK(ID_AA64ISAR2_EL1_APA3) \
+ ARM64_FEATURE_MASK(ID_AA64ISAR2_EL1_APA3) | \
+ ARM64_FEATURE_MASK(ID_AA64ISAR2_EL1_MOPS) \
)
u64 pvm_read_id_reg(const struct kvm_vcpu *vcpu, u32 id);
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 6e4dba9eadef..320f2eaa14a9 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -423,6 +423,7 @@ static __always_inline void do_ffa_mem_xfer(const u64 func_id,
DECLARE_REG(u32, fraglen, ctxt, 2);
DECLARE_REG(u64, addr_mbz, ctxt, 3);
DECLARE_REG(u32, npages_mbz, ctxt, 4);
+ struct ffa_mem_region_attributes *ep_mem_access;
struct ffa_composite_mem_region *reg;
struct ffa_mem_region *buf;
u32 offset, nr_ranges;
@@ -452,7 +453,9 @@ static __always_inline void do_ffa_mem_xfer(const u64 func_id,
buf = hyp_buffers.tx;
memcpy(buf, host_buffers.tx, fraglen);
- offset = buf->ep_mem_access[0].composite_off;
+ ep_mem_access = (void *)buf +
+ ffa_mem_desc_offset(buf, 0, FFA_VERSION_1_0);
+ offset = ep_mem_access->composite_off;
if (!offset || buf->ep_count != 1 || buf->sender_id != HOST_FFA_ID) {
ret = FFA_RET_INVALID_PARAMETERS;
goto out_unlock;
@@ -504,6 +507,7 @@ static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
DECLARE_REG(u32, handle_lo, ctxt, 1);
DECLARE_REG(u32, handle_hi, ctxt, 2);
DECLARE_REG(u32, flags, ctxt, 3);
+ struct ffa_mem_region_attributes *ep_mem_access;
struct ffa_composite_mem_region *reg;
u32 offset, len, fraglen, fragoff;
struct ffa_mem_region *buf;
@@ -528,7 +532,9 @@ static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
len = res->a1;
fraglen = res->a2;
- offset = buf->ep_mem_access[0].composite_off;
+ ep_mem_access = (void *)buf +
+ ffa_mem_desc_offset(buf, 0, FFA_VERSION_1_0);
+ offset = ep_mem_access->composite_off;
/*
* We can trust the SPMD to get this right, but let's at least
* check that we end up with something that doesn't look _completely_
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 9d703441278b..8d0a5834e883 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -129,8 +129,8 @@ static void prepare_host_vtcr(void)
parange = kvm_get_parange(id_aa64mmfr0_el1_sys_val);
phys_shift = id_aa64mmfr0_parange_to_phys_shift(parange);
- host_mmu.arch.vtcr = kvm_get_vtcr(id_aa64mmfr0_el1_sys_val,
- id_aa64mmfr1_el1_sys_val, phys_shift);
+ host_mmu.arch.mmu.vtcr = kvm_get_vtcr(id_aa64mmfr0_el1_sys_val,
+ id_aa64mmfr1_el1_sys_val, phys_shift);
}
static bool host_stage2_force_pte_cb(u64 addr, u64 end, enum kvm_pgtable_prot prot);
@@ -235,7 +235,7 @@ int kvm_guest_prepare_stage2(struct pkvm_hyp_vm *vm, void *pgd)
unsigned long nr_pages;
int ret;
- nr_pages = kvm_pgtable_stage2_pgd_size(vm->kvm.arch.vtcr) >> PAGE_SHIFT;
+ nr_pages = kvm_pgtable_stage2_pgd_size(mmu->vtcr) >> PAGE_SHIFT;
ret = hyp_pool_init(&vm->pool, hyp_virt_to_pfn(pgd), nr_pages, 0);
if (ret)
return ret;
@@ -295,7 +295,7 @@ int __pkvm_prot_finalize(void)
return -EPERM;
params->vttbr = kvm_get_vttbr(mmu);
- params->vtcr = host_mmu.arch.vtcr;
+ params->vtcr = mmu->vtcr;
params->hcr_el2 |= HCR_VM;
/*
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 8033ef353a5d..9d23a51d7f75 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -303,7 +303,7 @@ static void init_pkvm_hyp_vm(struct kvm *host_kvm, struct pkvm_hyp_vm *hyp_vm,
{
hyp_vm->host_kvm = host_kvm;
hyp_vm->kvm.created_vcpus = nr_vcpus;
- hyp_vm->kvm.arch.vtcr = host_mmu.arch.vtcr;
+ hyp_vm->kvm.arch.mmu.vtcr = host_mmu.arch.mmu.vtcr;
}
static int init_pkvm_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu,
@@ -483,7 +483,7 @@ int __pkvm_init_vm(struct kvm *host_kvm, unsigned long vm_hva,
}
vm_size = pkvm_get_hyp_vm_size(nr_vcpus);
- pgd_size = kvm_pgtable_stage2_pgd_size(host_mmu.arch.vtcr);
+ pgd_size = kvm_pgtable_stage2_pgd_size(host_mmu.arch.mmu.vtcr);
ret = -ENOMEM;
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index c353a06ee7e6..c50f8459e4fc 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -192,6 +192,7 @@ static const exit_handler_fn hyp_exit_handlers[] = {
[ESR_ELx_EC_DABT_LOW] = kvm_hyp_handle_dabt_low,
[ESR_ELx_EC_WATCHPT_LOW] = kvm_hyp_handle_watchpt_low,
[ESR_ELx_EC_PAC] = kvm_hyp_handle_ptrauth,
+ [ESR_ELx_EC_MOPS] = kvm_hyp_handle_mops,
};
static const exit_handler_fn pvm_exit_handlers[] = {
@@ -203,6 +204,7 @@ static const exit_handler_fn pvm_exit_handlers[] = {
[ESR_ELx_EC_DABT_LOW] = kvm_hyp_handle_dabt_low,
[ESR_ELx_EC_WATCHPT_LOW] = kvm_hyp_handle_watchpt_low,
[ESR_ELx_EC_PAC] = kvm_hyp_handle_ptrauth,
+ [ESR_ELx_EC_MOPS] = kvm_hyp_handle_mops,
};
static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index f155b8c9e98c..1966fdee740e 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -401,7 +401,7 @@ static int hyp_set_prot_attr(enum kvm_pgtable_prot prot, kvm_pte_t *ptep)
if (device)
return -EINVAL;
- if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) && system_supports_bti())
+ if (system_supports_bti_kernel())
attr |= KVM_PTE_LEAF_ATTR_HI_S1_GP;
} else {
attr |= KVM_PTE_LEAF_ATTR_HI_S1_XN;
@@ -664,7 +664,7 @@ u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift)
static bool stage2_has_fwb(struct kvm_pgtable *pgt)
{
- if (!cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
+ if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
return false;
return !(pgt->flags & KVM_PGTABLE_S2_NOFWB);
@@ -1314,7 +1314,7 @@ int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
ret = stage2_update_leaf_attrs(pgt, addr, 1, set, clr, NULL, &level,
KVM_PGTABLE_WALK_HANDLE_FAULT |
KVM_PGTABLE_WALK_SHARED);
- if (!ret)
+ if (!ret || ret == -EAGAIN)
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa_nsh, pgt->mmu, addr, level);
return ret;
}
@@ -1511,7 +1511,7 @@ int __kvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2_mmu *mmu,
kvm_pgtable_force_pte_cb_t force_pte_cb)
{
size_t pgd_sz;
- u64 vtcr = mmu->arch->vtcr;
+ u64 vtcr = mmu->vtcr;
u32 ia_bits = VTCR_EL2_IPA(vtcr);
u32 sl0 = FIELD_GET(VTCR_EL2_SL0_MASK, vtcr);
u32 start_level = VTCR_EL2_TGRAN_SL0_BASE - sl0;
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 6537f58b1a8c..1581df6aec87 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -39,6 +39,26 @@ static void __activate_traps(struct kvm_vcpu *vcpu)
___activate_traps(vcpu);
+ if (has_cntpoff()) {
+ struct timer_map map;
+
+ get_timer_map(vcpu, &map);
+
+ /*
+ * We're entrering the guest. Reload the correct
+ * values from memory now that TGE is clear.
+ */
+ if (map.direct_ptimer == vcpu_ptimer(vcpu))
+ val = __vcpu_sys_reg(vcpu, CNTP_CVAL_EL0);
+ if (map.direct_ptimer == vcpu_hptimer(vcpu))
+ val = __vcpu_sys_reg(vcpu, CNTHP_CVAL_EL2);
+
+ if (map.direct_ptimer) {
+ write_sysreg_el0(val, SYS_CNTP_CVAL);
+ isb();
+ }
+ }
+
val = read_sysreg(cpacr_el1);
val |= CPACR_ELx_TTA;
val &= ~(CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN |
@@ -77,6 +97,30 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2);
+ if (has_cntpoff()) {
+ struct timer_map map;
+ u64 val, offset;
+
+ get_timer_map(vcpu, &map);
+
+ /*
+ * We're exiting the guest. Save the latest CVAL value
+ * to memory and apply the offset now that TGE is set.
+ */
+ val = read_sysreg_el0(SYS_CNTP_CVAL);
+ if (map.direct_ptimer == vcpu_ptimer(vcpu))
+ __vcpu_sys_reg(vcpu, CNTP_CVAL_EL0) = val;
+ if (map.direct_ptimer == vcpu_hptimer(vcpu))
+ __vcpu_sys_reg(vcpu, CNTHP_CVAL_EL2) = val;
+
+ offset = read_sysreg_s(SYS_CNTPOFF_EL2);
+
+ if (map.direct_ptimer && offset) {
+ write_sysreg_el0(val + offset, SYS_CNTP_CVAL);
+ isb();
+ }
+ }
+
/*
* ARM errata 1165522 and 1530923 require the actual execution of the
* above before we can switch to the EL2/EL0 translation regime used by
@@ -93,12 +137,12 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
NOKPROBE_SYMBOL(__deactivate_traps);
/*
- * Disable IRQs in {activate,deactivate}_traps_vhe_{load,put}() to
+ * Disable IRQs in __vcpu_{load,put}_{activate,deactivate}_traps() to
* prevent a race condition between context switching of PMUSERENR_EL0
* in __{activate,deactivate}_traps_common() and IPIs that attempts to
* update PMUSERENR_EL0. See also kvm_set_pmuserenr().
*/
-void activate_traps_vhe_load(struct kvm_vcpu *vcpu)
+static void __vcpu_load_activate_traps(struct kvm_vcpu *vcpu)
{
unsigned long flags;
@@ -107,7 +151,7 @@ void activate_traps_vhe_load(struct kvm_vcpu *vcpu)
local_irq_restore(flags);
}
-void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu)
+static void __vcpu_put_deactivate_traps(struct kvm_vcpu *vcpu)
{
unsigned long flags;
@@ -116,6 +160,19 @@ void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu)
local_irq_restore(flags);
}
+void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu)
+{
+ __vcpu_load_switch_sysregs(vcpu);
+ __vcpu_load_activate_traps(vcpu);
+ __load_stage2(vcpu->arch.hw_mmu, vcpu->arch.hw_mmu->arch);
+}
+
+void kvm_vcpu_put_vhe(struct kvm_vcpu *vcpu)
+{
+ __vcpu_put_deactivate_traps(vcpu);
+ __vcpu_put_switch_sysregs(vcpu);
+}
+
static const exit_handler_fn hyp_exit_handlers[] = {
[0 ... ESR_ELx_EC_MAX] = NULL,
[ESR_ELx_EC_CP15_32] = kvm_hyp_handle_cp15_32,
@@ -126,6 +183,7 @@ static const exit_handler_fn hyp_exit_handlers[] = {
[ESR_ELx_EC_DABT_LOW] = kvm_hyp_handle_dabt_low,
[ESR_ELx_EC_WATCHPT_LOW] = kvm_hyp_handle_watchpt_low,
[ESR_ELx_EC_PAC] = kvm_hyp_handle_ptrauth,
+ [ESR_ELx_EC_MOPS] = kvm_hyp_handle_mops,
};
static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
@@ -170,17 +228,11 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
sysreg_save_host_state_vhe(host_ctxt);
/*
- * ARM erratum 1165522 requires us to configure both stage 1 and
- * stage 2 translation for the guest context before we clear
- * HCR_EL2.TGE.
- *
- * We have already configured the guest's stage 1 translation in
- * kvm_vcpu_load_sysregs_vhe above. We must now call
- * __load_stage2 before __activate_traps, because
- * __load_stage2 configures stage 2 translation, and
- * __activate_traps clear HCR_EL2.TGE (among other things).
+ * Note that ARM erratum 1165522 requires us to configure both stage 1
+ * and stage 2 translation for the guest context before we clear
+ * HCR_EL2.TGE. The stage 1 and stage 2 guest context has already been
+ * loaded on the CPU in kvm_vcpu_load_vhe().
*/
- __load_stage2(vcpu->arch.hw_mmu, vcpu->arch.hw_mmu->arch);
__activate_traps(vcpu);
__kvm_adjust_pc(vcpu);
diff --git a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c
index b35a178e7e0d..8e1e0d5033b6 100644
--- a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c
+++ b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c
@@ -52,7 +52,7 @@ void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt)
NOKPROBE_SYMBOL(sysreg_restore_guest_state_vhe);
/**
- * kvm_vcpu_load_sysregs_vhe - Load guest system registers to the physical CPU
+ * __vcpu_load_switch_sysregs - Load guest system registers to the physical CPU
*
* @vcpu: The VCPU pointer
*
@@ -62,7 +62,7 @@ NOKPROBE_SYMBOL(sysreg_restore_guest_state_vhe);
* and loading system register state early avoids having to load them on
* every entry to the VM.
*/
-void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu)
+void __vcpu_load_switch_sysregs(struct kvm_vcpu *vcpu)
{
struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt;
struct kvm_cpu_context *host_ctxt;
@@ -92,12 +92,10 @@ void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu)
__sysreg_restore_el1_state(guest_ctxt);
vcpu_set_flag(vcpu, SYSREGS_ON_CPU);
-
- activate_traps_vhe_load(vcpu);
}
/**
- * kvm_vcpu_put_sysregs_vhe - Restore host system registers to the physical CPU
+ * __vcpu_put_switch_syregs - Restore host system registers to the physical CPU
*
* @vcpu: The VCPU pointer
*
@@ -107,13 +105,12 @@ void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu)
* and deferring saving system register state until we're no longer running the
* VCPU avoids having to save them on every exit from the VM.
*/
-void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu)
+void __vcpu_put_switch_sysregs(struct kvm_vcpu *vcpu)
{
struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt;
struct kvm_cpu_context *host_ctxt;
host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
- deactivate_traps_vhe_put(vcpu);
__sysreg_save_el1_state(guest_ctxt);
__sysreg_save_user_state(guest_ctxt);
diff --git a/arch/arm64/kvm/hyp/vhe/tlb.c b/arch/arm64/kvm/hyp/vhe/tlb.c
index 46bd43f61d76..b636b4111dbf 100644
--- a/arch/arm64/kvm/hyp/vhe/tlb.c
+++ b/arch/arm64/kvm/hyp/vhe/tlb.c
@@ -11,18 +11,25 @@
#include <asm/tlbflush.h>
struct tlb_inv_context {
- unsigned long flags;
- u64 tcr;
- u64 sctlr;
+ struct kvm_s2_mmu *mmu;
+ unsigned long flags;
+ u64 tcr;
+ u64 sctlr;
};
static void __tlb_switch_to_guest(struct kvm_s2_mmu *mmu,
struct tlb_inv_context *cxt)
{
+ struct kvm_vcpu *vcpu = kvm_get_running_vcpu();
u64 val;
local_irq_save(cxt->flags);
+ if (vcpu && mmu != vcpu->arch.hw_mmu)
+ cxt->mmu = vcpu->arch.hw_mmu;
+ else
+ cxt->mmu = NULL;
+
if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
/*
* For CPUs that are affected by ARM errata 1165522 or 1530923,
@@ -66,10 +73,13 @@ static void __tlb_switch_to_host(struct tlb_inv_context *cxt)
* We're done with the TLB operation, let's restore the host's
* view of HCR_EL2.
*/
- write_sysreg(0, vttbr_el2);
write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2);
isb();
+ /* ... and the stage-2 MMU context that we switched away from */
+ if (cxt->mmu)
+ __load_stage2(cxt->mmu, cxt->mmu->arch);
+
if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
/* Restore the registers to what they were */
write_sysreg_el1(cxt->tcr, SYS_TCR);
diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
index 7fb4df0456de..5763d979d8ca 100644
--- a/arch/arm64/kvm/hypercalls.c
+++ b/arch/arm64/kvm/hypercalls.c
@@ -133,12 +133,10 @@ static bool kvm_smccc_test_fw_bmap(struct kvm_vcpu *vcpu, u32 func_id)
ARM_SMCCC_SMC_64, \
0, ARM_SMCCC_FUNC_MASK)
-static void init_smccc_filter(struct kvm *kvm)
+static int kvm_smccc_filter_insert_reserved(struct kvm *kvm)
{
int r;
- mt_init(&kvm->arch.smccc_filter);
-
/*
* Prevent userspace from handling any SMCCC calls in the architecture
* range, avoiding the risk of misrepresenting Spectre mitigation status
@@ -148,14 +146,25 @@ static void init_smccc_filter(struct kvm *kvm)
SMC32_ARCH_RANGE_BEGIN, SMC32_ARCH_RANGE_END,
xa_mk_value(KVM_SMCCC_FILTER_HANDLE),
GFP_KERNEL_ACCOUNT);
- WARN_ON_ONCE(r);
+ if (r)
+ goto out_destroy;
r = mtree_insert_range(&kvm->arch.smccc_filter,
SMC64_ARCH_RANGE_BEGIN, SMC64_ARCH_RANGE_END,
xa_mk_value(KVM_SMCCC_FILTER_HANDLE),
GFP_KERNEL_ACCOUNT);
- WARN_ON_ONCE(r);
+ if (r)
+ goto out_destroy;
+ return 0;
+out_destroy:
+ mtree_destroy(&kvm->arch.smccc_filter);
+ return r;
+}
+
+static bool kvm_smccc_filter_configured(struct kvm *kvm)
+{
+ return !mtree_empty(&kvm->arch.smccc_filter);
}
static int kvm_smccc_set_filter(struct kvm *kvm, struct kvm_smccc_filter __user *uaddr)
@@ -184,13 +193,14 @@ static int kvm_smccc_set_filter(struct kvm *kvm, struct kvm_smccc_filter __user
goto out_unlock;
}
+ if (!kvm_smccc_filter_configured(kvm)) {
+ r = kvm_smccc_filter_insert_reserved(kvm);
+ if (WARN_ON_ONCE(r))
+ goto out_unlock;
+ }
+
r = mtree_insert_range(&kvm->arch.smccc_filter, start, end,
xa_mk_value(filter.action), GFP_KERNEL_ACCOUNT);
- if (r)
- goto out_unlock;
-
- set_bit(KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED, &kvm->arch.flags);
-
out_unlock:
mutex_unlock(&kvm->arch.config_lock);
return r;
@@ -201,7 +211,7 @@ static u8 kvm_smccc_filter_get_action(struct kvm *kvm, u32 func_id)
unsigned long idx = func_id;
void *val;
- if (!test_bit(KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED, &kvm->arch.flags))
+ if (!kvm_smccc_filter_configured(kvm))
return KVM_SMCCC_FILTER_HANDLE;
/*
@@ -387,7 +397,7 @@ void kvm_arm_init_hypercalls(struct kvm *kvm)
smccc_feat->std_hyp_bmap = KVM_ARM_SMCCC_STD_HYP_FEATURES;
smccc_feat->vendor_hyp_bmap = KVM_ARM_SMCCC_VENDOR_HYP_FEATURES;
- init_smccc_filter(kvm);
+ mt_init(&kvm->arch.smccc_filter);
}
void kvm_arm_teardown_hypercalls(struct kvm *kvm)
@@ -554,7 +564,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
{
bool wants_02;
- wants_02 = test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features);
+ wants_02 = vcpu_has_feature(vcpu, KVM_ARM_VCPU_PSCI_0_2);
switch (val) {
case KVM_ARM_PSCI_0_1:
diff --git a/arch/arm64/kvm/mmio.c b/arch/arm64/kvm/mmio.c
index 3dd38a151d2a..200c8019a82a 100644
--- a/arch/arm64/kvm/mmio.c
+++ b/arch/arm64/kvm/mmio.c
@@ -135,6 +135,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
* volunteered to do so, and bail out otherwise.
*/
if (!kvm_vcpu_dabt_isvalid(vcpu)) {
+ trace_kvm_mmio_nisv(*vcpu_pc(vcpu), kvm_vcpu_get_esr(vcpu),
+ kvm_vcpu_get_hfar(vcpu), fault_ipa);
+
if (test_bit(KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER,
&vcpu->kvm->arch.flags)) {
run->exit_reason = KVM_EXIT_ARM_NISV;
@@ -143,7 +146,6 @@ int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
return 0;
}
- kvm_pr_unimpl("Data abort outside memslots with no valid syndrome info\n");
return -ENOSYS;
}
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 482280fe22d7..d87c8fcc4c24 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -892,7 +892,7 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long t
mmfr0 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
mmfr1 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
- kvm->arch.vtcr = kvm_get_vtcr(mmfr0, mmfr1, phys_shift);
+ mmu->vtcr = kvm_get_vtcr(mmfr0, mmfr1, phys_shift);
if (mmu->pgt != NULL) {
kvm_err("kvm_arch already initialized?\n");
@@ -1067,7 +1067,8 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
phys_addr_t addr;
int ret = 0;
struct kvm_mmu_memory_cache cache = { .gfp_zero = __GFP_ZERO };
- struct kvm_pgtable *pgt = kvm->arch.mmu.pgt;
+ struct kvm_s2_mmu *mmu = &kvm->arch.mmu;
+ struct kvm_pgtable *pgt = mmu->pgt;
enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_DEVICE |
KVM_PGTABLE_PROT_R |
(writable ? KVM_PGTABLE_PROT_W : 0);
@@ -1080,7 +1081,7 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
for (addr = guest_ipa; addr < guest_ipa + size; addr += PAGE_SIZE) {
ret = kvm_mmu_topup_memory_cache(&cache,
- kvm_mmu_cache_min_pages(kvm));
+ kvm_mmu_cache_min_pages(mmu));
if (ret)
break;
@@ -1298,28 +1299,8 @@ transparent_hugepage_adjust(struct kvm *kvm, struct kvm_memory_slot *memslot,
if (sz < PMD_SIZE)
return PAGE_SIZE;
- /*
- * The address we faulted on is backed by a transparent huge
- * page. However, because we map the compound huge page and
- * not the individual tail page, we need to transfer the
- * refcount to the head page. We have to be careful that the
- * THP doesn't start to split while we are adjusting the
- * refcounts.
- *
- * We are sure this doesn't happen, because mmu_invalidate_retry
- * was successful and we are holding the mmu_lock, so if this
- * THP is trying to split, it will be blocked in the mmu
- * notifier before touching any of the pages, specifically
- * before being able to call __split_huge_page_refcount().
- *
- * We can therefore safely transfer the refcount from PG_tail
- * to PG_head and switch the pfn from a tail page to the head
- * page accordingly.
- */
*ipap &= PMD_MASK;
- kvm_release_pfn_clean(pfn);
pfn &= ~(PTRS_PER_PMD - 1);
- get_page(pfn_to_page(pfn));
*pfnp = pfn;
return PMD_SIZE;
@@ -1431,7 +1412,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
if (fault_status != ESR_ELx_FSC_PERM ||
(logging_active && write_fault)) {
ret = kvm_mmu_topup_memory_cache(memcache,
- kvm_mmu_cache_min_pages(kvm));
+ kvm_mmu_cache_min_pages(vcpu->arch.hw_mmu));
if (ret)
return ret;
}
@@ -1578,7 +1559,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
if (device)
prot |= KVM_PGTABLE_PROT_DEVICE;
- else if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
+ else if (cpus_have_final_cap(ARM64_HAS_CACHE_DIC))
prot |= KVM_PGTABLE_PROT_X;
/*
@@ -1747,7 +1728,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
}
/* Userspace should not be able to register out-of-bounds IPAs */
- VM_BUG_ON(fault_ipa >= kvm_phys_size(vcpu->kvm));
+ VM_BUG_ON(fault_ipa >= kvm_phys_size(vcpu->arch.hw_mmu));
if (fault_status == ESR_ELx_FSC_ACCESS) {
handle_access_fault(vcpu, fault_ipa);
@@ -2021,7 +2002,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
* Prevent userspace from creating a memory region outside of the IPA
* space addressable by the KVM guest IPA space.
*/
- if ((new->base_gfn + new->npages) > (kvm_phys_size(kvm) >> PAGE_SHIFT))
+ if ((new->base_gfn + new->npages) > (kvm_phys_size(&kvm->arch.mmu) >> PAGE_SHIFT))
return -EFAULT;
hva = new->userspace_addr;
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 6ff3ec18c925..8350fb8fee0b 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -123,7 +123,7 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
if (host_kvm->created_vcpus < 1)
return -EINVAL;
- pgd_sz = kvm_pgtable_stage2_pgd_size(host_kvm->arch.vtcr);
+ pgd_sz = kvm_pgtable_stage2_pgd_size(host_kvm->arch.mmu.vtcr);
/*
* The PGD pages will be reclaimed using a hyp_memcache which implies
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 6b066e04dc5d..fe99b3dab6ce 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -60,6 +60,23 @@ static u32 kvm_pmu_event_mask(struct kvm *kvm)
return __kvm_pmu_event_mask(pmuver);
}
+u64 kvm_pmu_evtyper_mask(struct kvm *kvm)
+{
+ u64 mask = ARMV8_PMU_EXCLUDE_EL1 | ARMV8_PMU_EXCLUDE_EL0 |
+ kvm_pmu_event_mask(kvm);
+ u64 pfr0 = IDREG(kvm, SYS_ID_AA64PFR0_EL1);
+
+ if (SYS_FIELD_GET(ID_AA64PFR0_EL1, EL2, pfr0))
+ mask |= ARMV8_PMU_INCLUDE_EL2;
+
+ if (SYS_FIELD_GET(ID_AA64PFR0_EL1, EL3, pfr0))
+ mask |= ARMV8_PMU_EXCLUDE_NS_EL0 |
+ ARMV8_PMU_EXCLUDE_NS_EL1 |
+ ARMV8_PMU_EXCLUDE_EL3;
+
+ return mask;
+}
+
/**
* kvm_pmc_is_64bit - determine if counter is 64bit
* @pmc: counter context
@@ -72,7 +89,7 @@ static bool kvm_pmc_is_64bit(struct kvm_pmc *pmc)
static bool kvm_pmc_has_64bit_overflow(struct kvm_pmc *pmc)
{
- u64 val = __vcpu_sys_reg(kvm_pmc_to_vcpu(pmc), PMCR_EL0);
+ u64 val = kvm_vcpu_read_pmcr(kvm_pmc_to_vcpu(pmc));
return (pmc->idx < ARMV8_PMU_CYCLE_IDX && (val & ARMV8_PMU_PMCR_LP)) ||
(pmc->idx == ARMV8_PMU_CYCLE_IDX && (val & ARMV8_PMU_PMCR_LC));
@@ -250,7 +267,7 @@ void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu)
u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
{
- u64 val = __vcpu_sys_reg(vcpu, PMCR_EL0) >> ARMV8_PMU_PMCR_N_SHIFT;
+ u64 val = kvm_vcpu_read_pmcr(vcpu) >> ARMV8_PMU_PMCR_N_SHIFT;
val &= ARMV8_PMU_PMCR_N_MASK;
if (val == 0)
@@ -272,7 +289,7 @@ void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val)
if (!kvm_vcpu_has_pmu(vcpu))
return;
- if (!(__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) || !val)
+ if (!(kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E) || !val)
return;
for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) {
@@ -324,7 +341,7 @@ static u64 kvm_pmu_overflow_status(struct kvm_vcpu *vcpu)
{
u64 reg = 0;
- if ((__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E)) {
+ if ((kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E)) {
reg = __vcpu_sys_reg(vcpu, PMOVSSET_EL0);
reg &= __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
reg &= __vcpu_sys_reg(vcpu, PMINTENSET_EL1);
@@ -348,7 +365,7 @@ static void kvm_pmu_update_state(struct kvm_vcpu *vcpu)
pmu->irq_level = overflow;
if (likely(irqchip_in_kernel(vcpu->kvm))) {
- int ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
+ int ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu,
pmu->irq_num, overflow, pmu);
WARN_ON(ret);
}
@@ -426,7 +443,7 @@ static void kvm_pmu_counter_increment(struct kvm_vcpu *vcpu,
{
int i;
- if (!(__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E))
+ if (!(kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E))
return;
/* Weed out disabled counters */
@@ -569,7 +586,7 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
static bool kvm_pmu_counter_is_enabled(struct kvm_pmc *pmc)
{
struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
- return (__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) &&
+ return (kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E) &&
(__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & BIT(pmc->idx));
}
@@ -584,6 +601,7 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
struct perf_event *event;
struct perf_event_attr attr;
u64 eventsel, reg, data;
+ bool p, u, nsk, nsu;
reg = counter_index_to_evtreg(pmc->idx);
data = __vcpu_sys_reg(vcpu, reg);
@@ -610,13 +628,18 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
!test_bit(eventsel, vcpu->kvm->arch.pmu_filter))
return;
+ p = data & ARMV8_PMU_EXCLUDE_EL1;
+ u = data & ARMV8_PMU_EXCLUDE_EL0;
+ nsk = data & ARMV8_PMU_EXCLUDE_NS_EL1;
+ nsu = data & ARMV8_PMU_EXCLUDE_NS_EL0;
+
memset(&attr, 0, sizeof(struct perf_event_attr));
attr.type = arm_pmu->pmu.type;
attr.size = sizeof(attr);
attr.pinned = 1;
attr.disabled = !kvm_pmu_counter_is_enabled(pmc);
- attr.exclude_user = data & ARMV8_PMU_EXCLUDE_EL0 ? 1 : 0;
- attr.exclude_kernel = data & ARMV8_PMU_EXCLUDE_EL1 ? 1 : 0;
+ attr.exclude_user = (u != nsu);
+ attr.exclude_kernel = (p != nsk);
attr.exclude_hv = 1; /* Don't count EL2 events */
attr.exclude_host = 1; /* Don't count host events */
attr.config = eventsel;
@@ -657,18 +680,13 @@ void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
u64 select_idx)
{
struct kvm_pmc *pmc = kvm_vcpu_idx_to_pmc(vcpu, select_idx);
- u64 reg, mask;
+ u64 reg;
if (!kvm_vcpu_has_pmu(vcpu))
return;
- mask = ARMV8_PMU_EVTYPE_MASK;
- mask &= ~ARMV8_PMU_EVTYPE_EVENT;
- mask |= kvm_pmu_event_mask(vcpu->kvm);
-
reg = counter_index_to_evtreg(pmc->idx);
-
- __vcpu_sys_reg(vcpu, reg) = data & mask;
+ __vcpu_sys_reg(vcpu, reg) = data & kvm_pmu_evtyper_mask(vcpu->kvm);
kvm_pmu_create_perf_event(pmc);
}
@@ -717,10 +735,9 @@ static struct arm_pmu *kvm_pmu_probe_armpmu(void)
* It is still necessary to get a valid cpu, though, to probe for the
* default PMU instance as userspace is not required to specify a PMU
* type. In order to uphold the preexisting behavior KVM selects the
- * PMU instance for the core where the first call to the
- * KVM_ARM_VCPU_PMU_V3_CTRL attribute group occurs. A dependent use case
- * would be a user with disdain of all things big.LITTLE that affines
- * the VMM to a particular cluster of cores.
+ * PMU instance for the core during vcpu init. A dependent use
+ * case would be a user with disdain of all things big.LITTLE that
+ * affines the VMM to a particular cluster of cores.
*
* In any case, userspace should just do the sane thing and use the UAPI
* to select a PMU type directly. But, be wary of the baggage being
@@ -786,6 +803,17 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
return val & mask;
}
+void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu)
+{
+ u64 mask = kvm_pmu_valid_counter_mask(vcpu);
+
+ kvm_pmu_handle_pmcr(vcpu, kvm_vcpu_read_pmcr(vcpu));
+
+ __vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= mask;
+ __vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= mask;
+ __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= mask;
+}
+
int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
{
if (!kvm_vcpu_has_pmu(vcpu))
@@ -874,6 +902,52 @@ static bool pmu_irq_is_valid(struct kvm *kvm, int irq)
return true;
}
+/**
+ * kvm_arm_pmu_get_max_counters - Return the max number of PMU counters.
+ * @kvm: The kvm pointer
+ */
+u8 kvm_arm_pmu_get_max_counters(struct kvm *kvm)
+{
+ struct arm_pmu *arm_pmu = kvm->arch.arm_pmu;
+
+ /*
+ * The arm_pmu->num_events considers the cycle counter as well.
+ * Ignore that and return only the general-purpose counters.
+ */
+ return arm_pmu->num_events - 1;
+}
+
+static void kvm_arm_set_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu)
+{
+ lockdep_assert_held(&kvm->arch.config_lock);
+
+ kvm->arch.arm_pmu = arm_pmu;
+ kvm->arch.pmcr_n = kvm_arm_pmu_get_max_counters(kvm);
+}
+
+/**
+ * kvm_arm_set_default_pmu - No PMU set, get the default one.
+ * @kvm: The kvm pointer
+ *
+ * The observant among you will notice that the supported_cpus
+ * mask does not get updated for the default PMU even though it
+ * is quite possible the selected instance supports only a
+ * subset of cores in the system. This is intentional, and
+ * upholds the preexisting behavior on heterogeneous systems
+ * where vCPUs can be scheduled on any core but the guest
+ * counters could stop working.
+ */
+int kvm_arm_set_default_pmu(struct kvm *kvm)
+{
+ struct arm_pmu *arm_pmu = kvm_pmu_probe_armpmu();
+
+ if (!arm_pmu)
+ return -ENODEV;
+
+ kvm_arm_set_pmu(kvm, arm_pmu);
+ return 0;
+}
+
static int kvm_arm_pmu_v3_set_pmu(struct kvm_vcpu *vcpu, int pmu_id)
{
struct kvm *kvm = vcpu->kvm;
@@ -893,7 +967,7 @@ static int kvm_arm_pmu_v3_set_pmu(struct kvm_vcpu *vcpu, int pmu_id)
break;
}
- kvm->arch.arm_pmu = arm_pmu;
+ kvm_arm_set_pmu(kvm, arm_pmu);
cpumask_copy(kvm->arch.supported_cpus, &arm_pmu->supported_cpus);
ret = 0;
break;
@@ -916,23 +990,6 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
if (vcpu->arch.pmu.created)
return -EBUSY;
- if (!kvm->arch.arm_pmu) {
- /*
- * No PMU set, get the default one.
- *
- * The observant among you will notice that the supported_cpus
- * mask does not get updated for the default PMU even though it
- * is quite possible the selected instance supports only a
- * subset of cores in the system. This is intentional, and
- * upholds the preexisting behavior on heterogeneous systems
- * where vCPUs can be scheduled on any core but the guest
- * counters could stop working.
- */
- kvm->arch.arm_pmu = kvm_pmu_probe_armpmu();
- if (!kvm->arch.arm_pmu)
- return -ENODEV;
- }
-
switch (attr->attr) {
case KVM_ARM_VCPU_PMU_V3_IRQ: {
int __user *uaddr = (int __user *)(long)attr->addr;
@@ -1072,3 +1129,15 @@ u8 kvm_arm_pmu_get_pmuver_limit(void)
ID_AA64DFR0_EL1_PMUVer_V3P5);
return FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), tmp);
}
+
+/**
+ * kvm_vcpu_read_pmcr - Read PMCR_EL0 register for the vCPU
+ * @vcpu: The vcpu pointer
+ */
+u64 kvm_vcpu_read_pmcr(struct kvm_vcpu *vcpu)
+{
+ u64 pmcr = __vcpu_sys_reg(vcpu, PMCR_EL0) &
+ ~(ARMV8_PMU_PMCR_N_MASK << ARMV8_PMU_PMCR_N_SHIFT);
+
+ return pmcr | ((u64)vcpu->kvm->arch.pmcr_n << ARMV8_PMU_PMCR_N_SHIFT);
+}
diff --git a/arch/arm64/kvm/pmu.c b/arch/arm64/kvm/pmu.c
index 0eea225fd09a..a243934c5568 100644
--- a/arch/arm64/kvm/pmu.c
+++ b/arch/arm64/kvm/pmu.c
@@ -39,7 +39,7 @@ void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr)
{
struct kvm_pmu_events *pmu = kvm_get_pmu_events();
- if (!kvm_arm_support_pmu_v3() || !pmu || !kvm_pmu_switch_needed(attr))
+ if (!kvm_arm_support_pmu_v3() || !kvm_pmu_switch_needed(attr))
return;
if (!attr->exclude_host)
@@ -55,7 +55,7 @@ void kvm_clr_pmu_events(u32 clr)
{
struct kvm_pmu_events *pmu = kvm_get_pmu_events();
- if (!kvm_arm_support_pmu_v3() || !pmu)
+ if (!kvm_arm_support_pmu_v3())
return;
pmu->events_host &= ~clr;
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index 7a65a35ee4ac..5bb4de162cab 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -73,11 +73,8 @@ int __init kvm_arm_init_sve(void)
return 0;
}
-static int kvm_vcpu_enable_sve(struct kvm_vcpu *vcpu)
+static void kvm_vcpu_enable_sve(struct kvm_vcpu *vcpu)
{
- if (!system_supports_sve())
- return -EINVAL;
-
vcpu->arch.sve_max_vl = kvm_sve_max_vl;
/*
@@ -86,8 +83,6 @@ static int kvm_vcpu_enable_sve(struct kvm_vcpu *vcpu)
* kvm_arm_vcpu_finalize(), which freezes the configuration.
*/
vcpu_set_flag(vcpu, GUEST_HAS_SVE);
-
- return 0;
}
/*
@@ -170,20 +165,9 @@ static void kvm_vcpu_reset_sve(struct kvm_vcpu *vcpu)
memset(vcpu->arch.sve_state, 0, vcpu_sve_state_size(vcpu));
}
-static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
+static void kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
{
- /*
- * For now make sure that both address/generic pointer authentication
- * features are requested by the userspace together and the system
- * supports these capabilities.
- */
- if (!test_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, vcpu->arch.features) ||
- !test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features) ||
- !system_has_full_ptr_auth())
- return -EINVAL;
-
vcpu_set_flag(vcpu, GUEST_HAS_PTRAUTH);
- return 0;
}
/**
@@ -204,10 +188,9 @@ static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
* disable preemption around the vcpu reset as we would otherwise race with
* preempt notifiers which also call put/load.
*/
-int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
+void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
{
struct vcpu_reset_state reset_state;
- int ret;
bool loaded;
u32 pstate;
@@ -224,29 +207,16 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
if (loaded)
kvm_arch_vcpu_put(vcpu);
- /* Disallow NV+SVE for the time being */
- if (vcpu_has_nv(vcpu) && vcpu_has_feature(vcpu, KVM_ARM_VCPU_SVE)) {
- ret = -EINVAL;
- goto out;
- }
-
if (!kvm_arm_vcpu_sve_finalized(vcpu)) {
- if (test_bit(KVM_ARM_VCPU_SVE, vcpu->arch.features)) {
- ret = kvm_vcpu_enable_sve(vcpu);
- if (ret)
- goto out;
- }
+ if (vcpu_has_feature(vcpu, KVM_ARM_VCPU_SVE))
+ kvm_vcpu_enable_sve(vcpu);
} else {
kvm_vcpu_reset_sve(vcpu);
}
- if (test_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, vcpu->arch.features) ||
- test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features)) {
- if (kvm_vcpu_enable_ptrauth(vcpu)) {
- ret = -EINVAL;
- goto out;
- }
- }
+ if (vcpu_has_feature(vcpu, KVM_ARM_VCPU_PTRAUTH_ADDRESS) ||
+ vcpu_has_feature(vcpu, KVM_ARM_VCPU_PTRAUTH_GENERIC))
+ kvm_vcpu_enable_ptrauth(vcpu);
if (vcpu_el1_is_32bit(vcpu))
pstate = VCPU_RESET_PSTATE_SVC;
@@ -255,11 +225,6 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
else
pstate = VCPU_RESET_PSTATE_EL1;
- if (kvm_vcpu_has_pmu(vcpu) && !kvm_arm_support_pmu_v3()) {
- ret = -EINVAL;
- goto out;
- }
-
/* Reset core registers */
memset(vcpu_gp_regs(vcpu), 0, sizeof(*vcpu_gp_regs(vcpu)));
memset(&vcpu->arch.ctxt.fp_regs, 0, sizeof(vcpu->arch.ctxt.fp_regs));
@@ -294,12 +259,11 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
}
/* Reset timer */
- ret = kvm_timer_vcpu_reset(vcpu);
-out:
+ kvm_timer_vcpu_reset(vcpu);
+
if (loaded)
kvm_arch_vcpu_load(vcpu, smp_processor_id());
preempt_enable();
- return ret;
}
u32 get_kvm_ipa_limit(void)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index e92ec810d449..4735e1b37fb3 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -207,7 +207,7 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
* CPU left in the system, and certainly not from non-secure
* software).
*/
- if (!cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
+ if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
kvm_set_way_flush(vcpu);
return true;
@@ -379,7 +379,7 @@ static bool trap_loregion(struct kvm_vcpu *vcpu,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
- u64 val = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
+ u64 val = IDREG(vcpu->kvm, SYS_ID_AA64MMFR1_EL1);
u32 sr = reg_to_encoding(r);
if (!(val & (0xfUL << ID_AA64MMFR1_EL1_LO_SHIFT))) {
@@ -719,14 +719,9 @@ static unsigned int pmu_visibility(const struct kvm_vcpu *vcpu,
static u64 reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
{
- u64 n, mask = BIT(ARMV8_PMU_CYCLE_IDX);
+ u64 mask = BIT(ARMV8_PMU_CYCLE_IDX);
+ u8 n = vcpu->kvm->arch.pmcr_n;
- /* No PMU available, any PMU reg may UNDEF... */
- if (!kvm_arm_support_pmu_v3())
- return 0;
-
- n = read_sysreg(pmcr_el0) >> ARMV8_PMU_PMCR_N_SHIFT;
- n &= ARMV8_PMU_PMCR_N_MASK;
if (n)
mask |= GENMASK(n - 1, 0);
@@ -746,8 +741,12 @@ static u64 reset_pmevcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
static u64 reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
{
+ /* This thing will UNDEF, who cares about the reset value? */
+ if (!kvm_vcpu_has_pmu(vcpu))
+ return 0;
+
reset_unknown(vcpu, r);
- __vcpu_sys_reg(vcpu, r->reg) &= ARMV8_PMU_EVTYPE_MASK;
+ __vcpu_sys_reg(vcpu, r->reg) &= kvm_pmu_evtyper_mask(vcpu->kvm);
return __vcpu_sys_reg(vcpu, r->reg);
}
@@ -762,17 +761,15 @@ static u64 reset_pmselr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
static u64 reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
{
- u64 pmcr;
+ u64 pmcr = 0;
- /* No PMU available, PMCR_EL0 may UNDEF... */
- if (!kvm_arm_support_pmu_v3())
- return 0;
-
- /* Only preserve PMCR_EL0.N, and reset the rest to 0 */
- pmcr = read_sysreg(pmcr_el0) & (ARMV8_PMU_PMCR_N_MASK << ARMV8_PMU_PMCR_N_SHIFT);
if (!kvm_supports_32bit_el0())
pmcr |= ARMV8_PMU_PMCR_LC;
+ /*
+ * The value of PMCR.N field is included when the
+ * vCPU register is read via kvm_vcpu_read_pmcr().
+ */
__vcpu_sys_reg(vcpu, r->reg) = pmcr;
return __vcpu_sys_reg(vcpu, r->reg);
@@ -822,7 +819,7 @@ static bool access_pmcr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
* Only update writeable bits of PMCR (continuing into
* kvm_pmu_handle_pmcr() as well)
*/
- val = __vcpu_sys_reg(vcpu, PMCR_EL0);
+ val = kvm_vcpu_read_pmcr(vcpu);
val &= ~ARMV8_PMU_PMCR_MASK;
val |= p->regval & ARMV8_PMU_PMCR_MASK;
if (!kvm_supports_32bit_el0())
@@ -830,7 +827,7 @@ static bool access_pmcr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
kvm_pmu_handle_pmcr(vcpu, val);
} else {
/* PMCR.P & PMCR.C are RAZ */
- val = __vcpu_sys_reg(vcpu, PMCR_EL0)
+ val = kvm_vcpu_read_pmcr(vcpu)
& ~(ARMV8_PMU_PMCR_P | ARMV8_PMU_PMCR_C);
p->regval = val;
}
@@ -879,7 +876,7 @@ static bool pmu_counter_idx_valid(struct kvm_vcpu *vcpu, u64 idx)
{
u64 pmcr, val;
- pmcr = __vcpu_sys_reg(vcpu, PMCR_EL0);
+ pmcr = kvm_vcpu_read_pmcr(vcpu);
val = (pmcr >> ARMV8_PMU_PMCR_N_SHIFT) & ARMV8_PMU_PMCR_N_MASK;
if (idx >= val && idx != ARMV8_PMU_CYCLE_IDX) {
kvm_inject_undefined(vcpu);
@@ -988,12 +985,45 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
kvm_pmu_set_counter_event_type(vcpu, p->regval, idx);
kvm_vcpu_pmu_restore_guest(vcpu);
} else {
- p->regval = __vcpu_sys_reg(vcpu, reg) & ARMV8_PMU_EVTYPE_MASK;
+ p->regval = __vcpu_sys_reg(vcpu, reg);
}
return true;
}
+static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 val)
+{
+ bool set;
+
+ val &= kvm_pmu_valid_counter_mask(vcpu);
+
+ switch (r->reg) {
+ case PMOVSSET_EL0:
+ /* CRm[1] being set indicates a SET register, and CLR otherwise */
+ set = r->CRm & 2;
+ break;
+ default:
+ /* Op2[0] being set indicates a SET register, and CLR otherwise */
+ set = r->Op2 & 1;
+ break;
+ }
+
+ if (set)
+ __vcpu_sys_reg(vcpu, r->reg) |= val;
+ else
+ __vcpu_sys_reg(vcpu, r->reg) &= ~val;
+
+ return 0;
+}
+
+static int get_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 *val)
+{
+ u64 mask = kvm_pmu_valid_counter_mask(vcpu);
+
+ *val = __vcpu_sys_reg(vcpu, r->reg) & mask;
+ return 0;
+}
+
static bool access_pmcnten(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
@@ -1103,6 +1133,51 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
return true;
}
+static int get_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
+ u64 *val)
+{
+ *val = kvm_vcpu_read_pmcr(vcpu);
+ return 0;
+}
+
+static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
+ u64 val)
+{
+ u8 new_n = (val >> ARMV8_PMU_PMCR_N_SHIFT) & ARMV8_PMU_PMCR_N_MASK;
+ struct kvm *kvm = vcpu->kvm;
+
+ mutex_lock(&kvm->arch.config_lock);
+
+ /*
+ * The vCPU can't have more counters than the PMU hardware
+ * implements. Ignore this error to maintain compatibility
+ * with the existing KVM behavior.
+ */
+ if (!kvm_vm_has_ran_once(kvm) &&
+ new_n <= kvm_arm_pmu_get_max_counters(kvm))
+ kvm->arch.pmcr_n = new_n;
+
+ mutex_unlock(&kvm->arch.config_lock);
+
+ /*
+ * Ignore writes to RES0 bits, read only bits that are cleared on
+ * vCPU reset, and writable bits that KVM doesn't support yet.
+ * (i.e. only PMCR.N and bits [7:0] are mutable from userspace)
+ * The LP bit is RES0 when FEAT_PMUv3p5 is not supported on the vCPU.
+ * But, we leave the bit as it is here, as the vCPU's PMUver might
+ * be changed later (NOTE: the bit will be cleared on first vCPU run
+ * if necessary).
+ */
+ val &= ARMV8_PMU_PMCR_MASK;
+
+ /* The LC bit is RES1 when AArch32 is not supported */
+ if (!kvm_supports_32bit_el0())
+ val |= ARMV8_PMU_PMCR_LC;
+
+ __vcpu_sys_reg(vcpu, r->reg) = val;
+ return 0;
+}
+
/* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
#define DBG_BCR_BVR_WCR_WVR_EL1(n) \
{ SYS_DESC(SYS_DBGBVRn_EL1(n)), \
@@ -1216,8 +1291,14 @@ static s64 kvm_arm64_ftr_safe_value(u32 id, const struct arm64_ftr_bits *ftrp,
/* Some features have different safe value type in KVM than host features */
switch (id) {
case SYS_ID_AA64DFR0_EL1:
- if (kvm_ftr.shift == ID_AA64DFR0_EL1_PMUVer_SHIFT)
+ switch (kvm_ftr.shift) {
+ case ID_AA64DFR0_EL1_PMUVer_SHIFT:
+ kvm_ftr.type = FTR_LOWER_SAFE;
+ break;
+ case ID_AA64DFR0_EL1_DebugVer_SHIFT:
kvm_ftr.type = FTR_LOWER_SAFE;
+ break;
+ }
break;
case SYS_ID_DFR0_EL1:
if (kvm_ftr.shift == ID_DFR0_EL1_PerfMon_SHIFT)
@@ -1228,7 +1309,7 @@ static s64 kvm_arm64_ftr_safe_value(u32 id, const struct arm64_ftr_bits *ftrp,
return arm64_ftr_safe_value(&kvm_ftr, new, cur);
}
-/**
+/*
* arm64_check_features() - Check if a feature register value constitutes
* a subset of features indicated by the idreg's KVM sanitised limit.
*
@@ -1338,7 +1419,6 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
ARM64_FEATURE_MASK(ID_AA64ISAR2_EL1_GPA3));
if (!cpus_have_final_cap(ARM64_HAS_WFXT))
val &= ~ARM64_FEATURE_MASK(ID_AA64ISAR2_EL1_WFxT);
- val &= ~ARM64_FEATURE_MASK(ID_AA64ISAR2_EL1_MOPS);
break;
case SYS_ID_AA64MMFR2_EL1:
val &= ~ID_AA64MMFR2_EL1_CCIDX_MASK;
@@ -1373,6 +1453,13 @@ static inline bool is_id_reg(u32 id)
sys_reg_CRm(id) < 8);
}
+static inline bool is_aa32_id_reg(u32 id)
+{
+ return (sys_reg_Op0(id) == 3 && sys_reg_Op1(id) == 0 &&
+ sys_reg_CRn(id) == 0 && sys_reg_CRm(id) >= 1 &&
+ sys_reg_CRm(id) <= 3);
+}
+
static unsigned int id_visibility(const struct kvm_vcpu *vcpu,
const struct sys_reg_desc *r)
{
@@ -1469,14 +1556,21 @@ static u64 read_sanitised_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
return val;
}
+#define ID_REG_LIMIT_FIELD_ENUM(val, reg, field, limit) \
+({ \
+ u64 __f_val = FIELD_GET(reg##_##field##_MASK, val); \
+ (val) &= ~reg##_##field##_MASK; \
+ (val) |= FIELD_PREP(reg##_##field##_MASK, \
+ min(__f_val, (u64)reg##_##field##_##limit)); \
+ (val); \
+})
+
static u64 read_sanitised_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
const struct sys_reg_desc *rd)
{
u64 val = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
- /* Limit debug to ARMv8.0 */
- val &= ~ID_AA64DFR0_EL1_DebugVer_MASK;
- val |= SYS_FIELD_PREP_ENUM(ID_AA64DFR0_EL1, DebugVer, IMP);
+ val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64DFR0_EL1, DebugVer, V8P8);
/*
* Only initialize the PMU version if the vCPU was configured with one.
@@ -1496,6 +1590,7 @@ static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
const struct sys_reg_desc *rd,
u64 val)
{
+ u8 debugver = SYS_FIELD_GET(ID_AA64DFR0_EL1, DebugVer, val);
u8 pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer, val);
/*
@@ -1515,6 +1610,13 @@ static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
if (pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
val &= ~ID_AA64DFR0_EL1_PMUVer_MASK;
+ /*
+ * ID_AA64DFR0_EL1.DebugVer is one of those awkward fields with a
+ * nonzero minimum safe value.
+ */
+ if (debugver < ID_AA64DFR0_EL1_DebugVer_IMP)
+ return -EINVAL;
+
return set_id_reg(vcpu, rd, val);
}
@@ -1528,6 +1630,8 @@ static u64 read_sanitised_id_dfr0_el1(struct kvm_vcpu *vcpu,
if (kvm_vcpu_has_pmu(vcpu))
val |= SYS_FIELD_PREP(ID_DFR0_EL1, PerfMon, perfmon);
+ val = ID_REG_LIMIT_FIELD_ENUM(val, ID_DFR0_EL1, CopDbg, Debugv8p8);
+
return val;
}
@@ -1536,6 +1640,7 @@ static int set_id_dfr0_el1(struct kvm_vcpu *vcpu,
u64 val)
{
u8 perfmon = SYS_FIELD_GET(ID_DFR0_EL1, PerfMon, val);
+ u8 copdbg = SYS_FIELD_GET(ID_DFR0_EL1, CopDbg, val);
if (perfmon == ID_DFR0_EL1_PerfMon_IMPDEF) {
val &= ~ID_DFR0_EL1_PerfMon_MASK;
@@ -1551,6 +1656,9 @@ static int set_id_dfr0_el1(struct kvm_vcpu *vcpu,
if (perfmon != 0 && perfmon < ID_DFR0_EL1_PerfMon_PMUv3)
return -EINVAL;
+ if (copdbg < ID_DFR0_EL1_CopDbg_Armv8)
+ return -EINVAL;
+
return set_id_reg(vcpu, rd, val);
}
@@ -1791,8 +1899,8 @@ static unsigned int el2_visibility(const struct kvm_vcpu *vcpu,
* HCR_EL2.E2H==1, and only in the sysreg table for convenience of
* handling traps. Given that, they are always hidden from userspace.
*/
-static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu,
- const struct sys_reg_desc *rd)
+static unsigned int hidden_user_visibility(const struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *rd)
{
return REG_HIDDEN_USER;
}
@@ -1803,7 +1911,7 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu,
.reset = rst, \
.reg = name##_EL1, \
.val = v, \
- .visibility = elx2_visibility, \
+ .visibility = hidden_user_visibility, \
}
/*
@@ -1817,11 +1925,14 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu,
* from userspace.
*/
-/* sys_reg_desc initialiser for known cpufeature ID registers */
-#define ID_SANITISED(name) { \
+#define ID_DESC(name) \
SYS_DESC(SYS_##name), \
.access = access_id_reg, \
- .get_user = get_id_reg, \
+ .get_user = get_id_reg \
+
+/* sys_reg_desc initialiser for known cpufeature ID registers */
+#define ID_SANITISED(name) { \
+ ID_DESC(name), \
.set_user = set_id_reg, \
.visibility = id_visibility, \
.reset = kvm_read_sanitised_id_reg, \
@@ -1830,15 +1941,22 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu,
/* sys_reg_desc initialiser for known cpufeature ID registers */
#define AA32_ID_SANITISED(name) { \
- SYS_DESC(SYS_##name), \
- .access = access_id_reg, \
- .get_user = get_id_reg, \
+ ID_DESC(name), \
.set_user = set_id_reg, \
.visibility = aa32_id_visibility, \
.reset = kvm_read_sanitised_id_reg, \
.val = 0, \
}
+/* sys_reg_desc initialiser for writable ID registers */
+#define ID_WRITABLE(name, mask) { \
+ ID_DESC(name), \
+ .set_user = set_id_reg, \
+ .visibility = id_visibility, \
+ .reset = kvm_read_sanitised_id_reg, \
+ .val = mask, \
+}
+
/*
* sys_reg_desc initialiser for architecturally unallocated cpufeature ID
* register with encoding Op0=3, Op1=0, CRn=0, CRm=crm, Op2=op2
@@ -1860,9 +1978,7 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu,
* RAZ for the guest.
*/
#define ID_HIDDEN(name) { \
- SYS_DESC(SYS_##name), \
- .access = access_id_reg, \
- .get_user = get_id_reg, \
+ ID_DESC(name), \
.set_user = set_id_reg, \
.visibility = raz_visibility, \
.reset = kvm_read_sanitised_id_reg, \
@@ -1961,7 +2077,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
// DBGDTR[TR]X_EL0 share the same encoding
{ SYS_DESC(SYS_DBGDTRTX_EL0), trap_raz_wi },
- { SYS_DESC(SYS_DBGVCR32_EL2), NULL, reset_val, DBGVCR32_EL2, 0 },
+ { SYS_DESC(SYS_DBGVCR32_EL2), trap_undef, reset_val, DBGVCR32_EL2, 0 },
{ SYS_DESC(SYS_MPIDR_EL1), NULL, reset_mpidr, MPIDR_EL1 },
@@ -1980,7 +2096,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
.set_user = set_id_dfr0_el1,
.visibility = aa32_id_visibility,
.reset = read_sanitised_id_dfr0_el1,
- .val = ID_DFR0_EL1_PerfMon_MASK, },
+ .val = ID_DFR0_EL1_PerfMon_MASK |
+ ID_DFR0_EL1_CopDbg_MASK, },
ID_HIDDEN(ID_AFR0_EL1),
AA32_ID_SANITISED(ID_MMFR0_EL1),
AA32_ID_SANITISED(ID_MMFR1_EL1),
@@ -2014,11 +2131,17 @@ static const struct sys_reg_desc sys_reg_descs[] = {
.get_user = get_id_reg,
.set_user = set_id_reg,
.reset = read_sanitised_id_aa64pfr0_el1,
- .val = ID_AA64PFR0_EL1_CSV2_MASK | ID_AA64PFR0_EL1_CSV3_MASK, },
+ .val = ~(ID_AA64PFR0_EL1_AMU |
+ ID_AA64PFR0_EL1_MPAM |
+ ID_AA64PFR0_EL1_SVE |
+ ID_AA64PFR0_EL1_RAS |
+ ID_AA64PFR0_EL1_GIC |
+ ID_AA64PFR0_EL1_AdvSIMD |
+ ID_AA64PFR0_EL1_FP), },
ID_SANITISED(ID_AA64PFR1_EL1),
ID_UNALLOCATED(4,2),
ID_UNALLOCATED(4,3),
- ID_SANITISED(ID_AA64ZFR0_EL1),
+ ID_WRITABLE(ID_AA64ZFR0_EL1, ~ID_AA64ZFR0_EL1_RES0),
ID_HIDDEN(ID_AA64SMFR0_EL1),
ID_UNALLOCATED(4,6),
ID_UNALLOCATED(4,7),
@@ -2029,7 +2152,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
.get_user = get_id_reg,
.set_user = set_id_aa64dfr0_el1,
.reset = read_sanitised_id_aa64dfr0_el1,
- .val = ID_AA64DFR0_EL1_PMUVer_MASK, },
+ .val = ID_AA64DFR0_EL1_PMUVer_MASK |
+ ID_AA64DFR0_EL1_DebugVer_MASK, },
ID_SANITISED(ID_AA64DFR1_EL1),
ID_UNALLOCATED(5,2),
ID_UNALLOCATED(5,3),
@@ -2039,9 +2163,14 @@ static const struct sys_reg_desc sys_reg_descs[] = {
ID_UNALLOCATED(5,7),
/* CRm=6 */
- ID_SANITISED(ID_AA64ISAR0_EL1),
- ID_SANITISED(ID_AA64ISAR1_EL1),
- ID_SANITISED(ID_AA64ISAR2_EL1),
+ ID_WRITABLE(ID_AA64ISAR0_EL1, ~ID_AA64ISAR0_EL1_RES0),
+ ID_WRITABLE(ID_AA64ISAR1_EL1, ~(ID_AA64ISAR1_EL1_GPI |
+ ID_AA64ISAR1_EL1_GPA |
+ ID_AA64ISAR1_EL1_API |
+ ID_AA64ISAR1_EL1_APA)),
+ ID_WRITABLE(ID_AA64ISAR2_EL1, ~(ID_AA64ISAR2_EL1_RES0 |
+ ID_AA64ISAR2_EL1_APA3 |
+ ID_AA64ISAR2_EL1_GPA3)),
ID_UNALLOCATED(6,3),
ID_UNALLOCATED(6,4),
ID_UNALLOCATED(6,5),
@@ -2049,9 +2178,23 @@ static const struct sys_reg_desc sys_reg_descs[] = {
ID_UNALLOCATED(6,7),
/* CRm=7 */
- ID_SANITISED(ID_AA64MMFR0_EL1),
- ID_SANITISED(ID_AA64MMFR1_EL1),
- ID_SANITISED(ID_AA64MMFR2_EL1),
+ ID_WRITABLE(ID_AA64MMFR0_EL1, ~(ID_AA64MMFR0_EL1_RES0 |
+ ID_AA64MMFR0_EL1_TGRAN4_2 |
+ ID_AA64MMFR0_EL1_TGRAN64_2 |
+ ID_AA64MMFR0_EL1_TGRAN16_2)),
+ ID_WRITABLE(ID_AA64MMFR1_EL1, ~(ID_AA64MMFR1_EL1_RES0 |
+ ID_AA64MMFR1_EL1_HCX |
+ ID_AA64MMFR1_EL1_XNX |
+ ID_AA64MMFR1_EL1_TWED |
+ ID_AA64MMFR1_EL1_XNX |
+ ID_AA64MMFR1_EL1_VH |
+ ID_AA64MMFR1_EL1_VMIDBits)),
+ ID_WRITABLE(ID_AA64MMFR2_EL1, ~(ID_AA64MMFR2_EL1_RES0 |
+ ID_AA64MMFR2_EL1_EVT |
+ ID_AA64MMFR2_EL1_FWB |
+ ID_AA64MMFR2_EL1_IDS |
+ ID_AA64MMFR2_EL1_NV |
+ ID_AA64MMFR2_EL1_CCIDX)),
ID_SANITISED(ID_AA64MMFR3_EL1),
ID_UNALLOCATED(7,4),
ID_UNALLOCATED(7,5),
@@ -2116,14 +2259,16 @@ static const struct sys_reg_desc sys_reg_descs[] = {
/* PMBIDR_EL1 is not trapped */
{ PMU_SYS_REG(PMINTENSET_EL1),
- .access = access_pminten, .reg = PMINTENSET_EL1 },
+ .access = access_pminten, .reg = PMINTENSET_EL1,
+ .get_user = get_pmreg, .set_user = set_pmreg },
{ PMU_SYS_REG(PMINTENCLR_EL1),
- .access = access_pminten, .reg = PMINTENSET_EL1 },
+ .access = access_pminten, .reg = PMINTENSET_EL1,
+ .get_user = get_pmreg, .set_user = set_pmreg },
{ SYS_DESC(SYS_PMMIR_EL1), trap_raz_wi },
{ SYS_DESC(SYS_MAIR_EL1), access_vm_reg, reset_unknown, MAIR_EL1 },
- { SYS_DESC(SYS_PIRE0_EL1), access_vm_reg, reset_unknown, PIRE0_EL1 },
- { SYS_DESC(SYS_PIR_EL1), access_vm_reg, reset_unknown, PIR_EL1 },
+ { SYS_DESC(SYS_PIRE0_EL1), NULL, reset_unknown, PIRE0_EL1 },
+ { SYS_DESC(SYS_PIR_EL1), NULL, reset_unknown, PIR_EL1 },
{ SYS_DESC(SYS_AMAIR_EL1), access_vm_reg, reset_amair_el1, AMAIR_EL1 },
{ SYS_DESC(SYS_LORSA_EL1), trap_loregion },
@@ -2166,14 +2311,17 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ SYS_DESC(SYS_CTR_EL0), access_ctr },
{ SYS_DESC(SYS_SVCR), undef_access },
- { PMU_SYS_REG(PMCR_EL0), .access = access_pmcr,
- .reset = reset_pmcr, .reg = PMCR_EL0 },
+ { PMU_SYS_REG(PMCR_EL0), .access = access_pmcr, .reset = reset_pmcr,
+ .reg = PMCR_EL0, .get_user = get_pmcr, .set_user = set_pmcr },
{ PMU_SYS_REG(PMCNTENSET_EL0),
- .access = access_pmcnten, .reg = PMCNTENSET_EL0 },
+ .access = access_pmcnten, .reg = PMCNTENSET_EL0,
+ .get_user = get_pmreg, .set_user = set_pmreg },
{ PMU_SYS_REG(PMCNTENCLR_EL0),
- .access = access_pmcnten, .reg = PMCNTENSET_EL0 },
+ .access = access_pmcnten, .reg = PMCNTENSET_EL0,
+ .get_user = get_pmreg, .set_user = set_pmreg },
{ PMU_SYS_REG(PMOVSCLR_EL0),
- .access = access_pmovs, .reg = PMOVSSET_EL0 },
+ .access = access_pmovs, .reg = PMOVSSET_EL0,
+ .get_user = get_pmreg, .set_user = set_pmreg },
/*
* PM_SWINC_EL0 is exposed to userspace as RAZ/WI, as it was
* previously (and pointlessly) advertised in the past...
@@ -2201,7 +2349,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ PMU_SYS_REG(PMUSERENR_EL0), .access = access_pmuserenr,
.reset = reset_val, .reg = PMUSERENR_EL0, .val = 0 },
{ PMU_SYS_REG(PMOVSSET_EL0),
- .access = access_pmovs, .reg = PMOVSSET_EL0 },
+ .access = access_pmovs, .reg = PMOVSSET_EL0,
+ .get_user = get_pmreg, .set_user = set_pmreg },
{ SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 },
{ SYS_DESC(SYS_TPIDRRO_EL0), NULL, reset_unknown, TPIDRRO_EL0 },
@@ -2380,18 +2529,28 @@ static const struct sys_reg_desc sys_reg_descs[] = {
EL2_REG(VTTBR_EL2, access_rw, reset_val, 0),
EL2_REG(VTCR_EL2, access_rw, reset_val, 0),
- { SYS_DESC(SYS_DACR32_EL2), NULL, reset_unknown, DACR32_EL2 },
+ { SYS_DESC(SYS_DACR32_EL2), trap_undef, reset_unknown, DACR32_EL2 },
EL2_REG(HDFGRTR_EL2, access_rw, reset_val, 0),
EL2_REG(HDFGWTR_EL2, access_rw, reset_val, 0),
EL2_REG(SPSR_EL2, access_rw, reset_val, 0),
EL2_REG(ELR_EL2, access_rw, reset_val, 0),
{ SYS_DESC(SYS_SP_EL1), access_sp_el1},
- { SYS_DESC(SYS_IFSR32_EL2), NULL, reset_unknown, IFSR32_EL2 },
+ /* AArch32 SPSR_* are RES0 if trapped from a NV guest */
+ { SYS_DESC(SYS_SPSR_irq), .access = trap_raz_wi,
+ .visibility = hidden_user_visibility },
+ { SYS_DESC(SYS_SPSR_abt), .access = trap_raz_wi,
+ .visibility = hidden_user_visibility },
+ { SYS_DESC(SYS_SPSR_und), .access = trap_raz_wi,
+ .visibility = hidden_user_visibility },
+ { SYS_DESC(SYS_SPSR_fiq), .access = trap_raz_wi,
+ .visibility = hidden_user_visibility },
+
+ { SYS_DESC(SYS_IFSR32_EL2), trap_undef, reset_unknown, IFSR32_EL2 },
EL2_REG(AFSR0_EL2, access_rw, reset_val, 0),
EL2_REG(AFSR1_EL2, access_rw, reset_val, 0),
EL2_REG(ESR_EL2, access_rw, reset_val, 0),
- { SYS_DESC(SYS_FPEXC32_EL2), NULL, reset_val, FPEXC32_EL2, 0x700 },
+ { SYS_DESC(SYS_FPEXC32_EL2), trap_undef, reset_val, FPEXC32_EL2, 0x700 },
EL2_REG(FAR_EL2, access_rw, reset_val, 0),
EL2_REG(HPFAR_EL2, access_rw, reset_val, 0),
@@ -2438,14 +2597,15 @@ static bool trap_dbgdidr(struct kvm_vcpu *vcpu,
if (p->is_write) {
return ignore_write(vcpu, p);
} else {
- u64 dfr = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
- u64 pfr = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
- u32 el3 = !!cpuid_feature_extract_unsigned_field(pfr, ID_AA64PFR0_EL1_EL3_SHIFT);
-
- p->regval = ((((dfr >> ID_AA64DFR0_EL1_WRPs_SHIFT) & 0xf) << 28) |
- (((dfr >> ID_AA64DFR0_EL1_BRPs_SHIFT) & 0xf) << 24) |
- (((dfr >> ID_AA64DFR0_EL1_CTX_CMPs_SHIFT) & 0xf) << 20)
- | (6 << 16) | (1 << 15) | (el3 << 14) | (el3 << 12));
+ u64 dfr = IDREG(vcpu->kvm, SYS_ID_AA64DFR0_EL1);
+ u64 pfr = IDREG(vcpu->kvm, SYS_ID_AA64PFR0_EL1);
+ u32 el3 = !!SYS_FIELD_GET(ID_AA64PFR0_EL1, EL3, pfr);
+
+ p->regval = ((SYS_FIELD_GET(ID_AA64DFR0_EL1, WRPs, dfr) << 28) |
+ (SYS_FIELD_GET(ID_AA64DFR0_EL1, BRPs, dfr) << 24) |
+ (SYS_FIELD_GET(ID_AA64DFR0_EL1, CTX_CMPs, dfr) << 20) |
+ (SYS_FIELD_GET(ID_AA64DFR0_EL1, DebugVer, dfr) << 16) |
+ (1 << 15) | (el3 << 14) | (el3 << 12));
return true;
}
}
@@ -3572,6 +3732,65 @@ int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
return write_demux_regids(uindices);
}
+#define KVM_ARM_FEATURE_ID_RANGE_INDEX(r) \
+ KVM_ARM_FEATURE_ID_RANGE_IDX(sys_reg_Op0(r), \
+ sys_reg_Op1(r), \
+ sys_reg_CRn(r), \
+ sys_reg_CRm(r), \
+ sys_reg_Op2(r))
+
+static bool is_feature_id_reg(u32 encoding)
+{
+ return (sys_reg_Op0(encoding) == 3 &&
+ (sys_reg_Op1(encoding) < 2 || sys_reg_Op1(encoding) == 3) &&
+ sys_reg_CRn(encoding) == 0 &&
+ sys_reg_CRm(encoding) <= 7);
+}
+
+int kvm_vm_ioctl_get_reg_writable_masks(struct kvm *kvm, struct reg_mask_range *range)
+{
+ const void *zero_page = page_to_virt(ZERO_PAGE(0));
+ u64 __user *masks = (u64 __user *)range->addr;
+
+ /* Only feature id range is supported, reserved[13] must be zero. */
+ if (range->range ||
+ memcmp(range->reserved, zero_page, sizeof(range->reserved)))
+ return -EINVAL;
+
+ /* Wipe the whole thing first */
+ if (clear_user(masks, KVM_ARM_FEATURE_ID_RANGE_SIZE * sizeof(__u64)))
+ return -EFAULT;
+
+ for (int i = 0; i < ARRAY_SIZE(sys_reg_descs); i++) {
+ const struct sys_reg_desc *reg = &sys_reg_descs[i];
+ u32 encoding = reg_to_encoding(reg);
+ u64 val;
+
+ if (!is_feature_id_reg(encoding) || !reg->set_user)
+ continue;
+
+ /*
+ * For ID registers, we return the writable mask. Other feature
+ * registers return a full 64bit mask. That's not necessary
+ * compliant with a given revision of the architecture, but the
+ * RES0/RES1 definitions allow us to do that.
+ */
+ if (is_id_reg(encoding)) {
+ if (!reg->val ||
+ (is_aa32_id_reg(encoding) && !kvm_supports_32bit_el0()))
+ continue;
+ val = reg->val;
+ } else {
+ val = ~0UL;
+ }
+
+ if (put_user(val, (masks + KVM_ARM_FEATURE_ID_RANGE_INDEX(encoding))))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
int __init kvm_sys_reg_table_init(void)
{
struct sys_reg_params params;
diff --git a/arch/arm64/kvm/trace_arm.h b/arch/arm64/kvm/trace_arm.h
index 8ad53104934d..c18c1a95831e 100644
--- a/arch/arm64/kvm/trace_arm.h
+++ b/arch/arm64/kvm/trace_arm.h
@@ -136,6 +136,31 @@ TRACE_EVENT(kvm_mmio_emulate,
__entry->vcpu_pc, __entry->instr, __entry->cpsr)
);
+TRACE_EVENT(kvm_mmio_nisv,
+ TP_PROTO(unsigned long vcpu_pc, unsigned long esr,
+ unsigned long far, unsigned long ipa),
+ TP_ARGS(vcpu_pc, esr, far, ipa),
+
+ TP_STRUCT__entry(
+ __field( unsigned long, vcpu_pc )
+ __field( unsigned long, esr )
+ __field( unsigned long, far )
+ __field( unsigned long, ipa )
+ ),
+
+ TP_fast_assign(
+ __entry->vcpu_pc = vcpu_pc;
+ __entry->esr = esr;
+ __entry->far = far;
+ __entry->ipa = ipa;
+ ),
+
+ TP_printk("ipa %#016lx, esr %#016lx, far %#016lx, pc %#016lx",
+ __entry->ipa, __entry->esr,
+ __entry->far, __entry->vcpu_pc)
+);
+
+
TRACE_EVENT(kvm_set_way_flush,
TP_PROTO(unsigned long vcpu_pc, bool cache),
TP_ARGS(vcpu_pc, cache),
diff --git a/arch/arm64/kvm/vgic/vgic-debug.c b/arch/arm64/kvm/vgic/vgic-debug.c
index 07aa0437125a..85606a531dc3 100644
--- a/arch/arm64/kvm/vgic/vgic-debug.c
+++ b/arch/arm64/kvm/vgic/vgic-debug.c
@@ -166,7 +166,7 @@ static void print_header(struct seq_file *s, struct vgic_irq *irq,
if (vcpu) {
hdr = "VCPU";
- id = vcpu->vcpu_id;
+ id = vcpu->vcpu_idx;
}
seq_printf(s, "\n");
@@ -212,7 +212,7 @@ static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
" %2d "
"\n",
type, irq->intid,
- (irq->target_vcpu) ? irq->target_vcpu->vcpu_id : -1,
+ (irq->target_vcpu) ? irq->target_vcpu->vcpu_idx : -1,
pending,
irq->line_level,
irq->active,
@@ -224,7 +224,7 @@ static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
irq->mpidr,
irq->source,
irq->priority,
- (irq->vcpu) ? irq->vcpu->vcpu_id : -1);
+ (irq->vcpu) ? irq->vcpu->vcpu_idx : -1);
}
static int vgic_debug_show(struct seq_file *s, void *v)
diff --git a/arch/arm64/kvm/vgic/vgic-irqfd.c b/arch/arm64/kvm/vgic/vgic-irqfd.c
index 475059bacedf..8c711deb25aa 100644
--- a/arch/arm64/kvm/vgic/vgic-irqfd.c
+++ b/arch/arm64/kvm/vgic/vgic-irqfd.c
@@ -23,7 +23,7 @@ static int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
if (!vgic_valid_spi(kvm, spi_id))
return -EINVAL;
- return kvm_vgic_inject_irq(kvm, 0, spi_id, level, NULL);
+ return kvm_vgic_inject_irq(kvm, NULL, spi_id, level, NULL);
}
/**
diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
index 5fe2365a629f..2dad2d095160 100644
--- a/arch/arm64/kvm/vgic/vgic-its.c
+++ b/arch/arm64/kvm/vgic/vgic-its.c
@@ -378,6 +378,12 @@ static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
return ret;
}
+static struct kvm_vcpu *collection_to_vcpu(struct kvm *kvm,
+ struct its_collection *col)
+{
+ return kvm_get_vcpu_by_id(kvm, col->target_addr);
+}
+
/*
* Promotes the ITS view of affinity of an ITTE (which redistributor this LPI
* is targeting) to the VGIC's view, which deals with target VCPUs.
@@ -391,7 +397,7 @@ static void update_affinity_ite(struct kvm *kvm, struct its_ite *ite)
if (!its_is_collection_mapped(ite->collection))
return;
- vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
+ vcpu = collection_to_vcpu(kvm, ite->collection);
update_affinity(ite->irq, vcpu);
}
@@ -679,7 +685,7 @@ int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
if (!ite || !its_is_collection_mapped(ite->collection))
return E_ITS_INT_UNMAPPED_INTERRUPT;
- vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
+ vcpu = collection_to_vcpu(kvm, ite->collection);
if (!vcpu)
return E_ITS_INT_UNMAPPED_INTERRUPT;
@@ -887,7 +893,7 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
return E_ITS_MOVI_UNMAPPED_COLLECTION;
ite->collection = collection;
- vcpu = kvm_get_vcpu(kvm, collection->target_addr);
+ vcpu = collection_to_vcpu(kvm, collection);
vgic_its_invalidate_cache(kvm);
@@ -1121,7 +1127,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
}
if (its_is_collection_mapped(collection))
- vcpu = kvm_get_vcpu(kvm, collection->target_addr);
+ vcpu = collection_to_vcpu(kvm, collection);
irq = vgic_add_lpi(kvm, lpi_nr, vcpu);
if (IS_ERR(irq)) {
@@ -1242,21 +1248,22 @@ static int vgic_its_cmd_handle_mapc(struct kvm *kvm, struct vgic_its *its,
u64 *its_cmd)
{
u16 coll_id;
- u32 target_addr;
struct its_collection *collection;
bool valid;
valid = its_cmd_get_validbit(its_cmd);
coll_id = its_cmd_get_collection(its_cmd);
- target_addr = its_cmd_get_target_addr(its_cmd);
-
- if (target_addr >= atomic_read(&kvm->online_vcpus))
- return E_ITS_MAPC_PROCNUM_OOR;
if (!valid) {
vgic_its_free_collection(its, coll_id);
vgic_its_invalidate_cache(kvm);
} else {
+ struct kvm_vcpu *vcpu;
+
+ vcpu = kvm_get_vcpu_by_id(kvm, its_cmd_get_target_addr(its_cmd));
+ if (!vcpu)
+ return E_ITS_MAPC_PROCNUM_OOR;
+
collection = find_collection(its, coll_id);
if (!collection) {
@@ -1270,9 +1277,9 @@ static int vgic_its_cmd_handle_mapc(struct kvm *kvm, struct vgic_its *its,
coll_id);
if (ret)
return ret;
- collection->target_addr = target_addr;
+ collection->target_addr = vcpu->vcpu_id;
} else {
- collection->target_addr = target_addr;
+ collection->target_addr = vcpu->vcpu_id;
update_affinity_collection(kvm, its, collection);
}
}
@@ -1382,7 +1389,7 @@ static int vgic_its_cmd_handle_invall(struct kvm *kvm, struct vgic_its *its,
if (!its_is_collection_mapped(collection))
return E_ITS_INVALL_UNMAPPED_COLLECTION;
- vcpu = kvm_get_vcpu(kvm, collection->target_addr);
+ vcpu = collection_to_vcpu(kvm, collection);
vgic_its_invall(vcpu);
return 0;
@@ -1399,23 +1406,21 @@ static int vgic_its_cmd_handle_invall(struct kvm *kvm, struct vgic_its *its,
static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
u64 *its_cmd)
{
- u32 target1_addr = its_cmd_get_target_addr(its_cmd);
- u32 target2_addr = its_cmd_mask_field(its_cmd, 3, 16, 32);
struct kvm_vcpu *vcpu1, *vcpu2;
struct vgic_irq *irq;
u32 *intids;
int irq_count, i;
- if (target1_addr >= atomic_read(&kvm->online_vcpus) ||
- target2_addr >= atomic_read(&kvm->online_vcpus))
+ /* We advertise GITS_TYPER.PTA==0, making the address the vcpu ID */
+ vcpu1 = kvm_get_vcpu_by_id(kvm, its_cmd_get_target_addr(its_cmd));
+ vcpu2 = kvm_get_vcpu_by_id(kvm, its_cmd_mask_field(its_cmd, 3, 16, 32));
+
+ if (!vcpu1 || !vcpu2)
return E_ITS_MOVALL_PROCNUM_OOR;
- if (target1_addr == target2_addr)
+ if (vcpu1 == vcpu2)
return 0;
- vcpu1 = kvm_get_vcpu(kvm, target1_addr);
- vcpu2 = kvm_get_vcpu(kvm, target2_addr);
-
irq_count = vgic_copy_lpi_list(kvm, vcpu1, &intids);
if (irq_count < 0)
return irq_count;
@@ -2258,7 +2263,7 @@ static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
return PTR_ERR(ite);
if (its_is_collection_mapped(collection))
- vcpu = kvm_get_vcpu(kvm, collection->target_addr);
+ vcpu = kvm_get_vcpu_by_id(kvm, collection->target_addr);
irq = vgic_add_lpi(kvm, lpi_id, vcpu);
if (IS_ERR(irq)) {
@@ -2573,7 +2578,7 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
coll_id = val & KVM_ITS_CTE_ICID_MASK;
if (target_addr != COLLECTION_NOT_MAPPED &&
- target_addr >= atomic_read(&kvm->online_vcpus))
+ !kvm_get_vcpu_by_id(kvm, target_addr))
return -EINVAL;
collection = find_collection(its, coll_id);
diff --git a/arch/arm64/kvm/vgic/vgic-kvm-device.c b/arch/arm64/kvm/vgic/vgic-kvm-device.c
index 212b73a715c1..f48b8dab8b3d 100644
--- a/arch/arm64/kvm/vgic/vgic-kvm-device.c
+++ b/arch/arm64/kvm/vgic/vgic-kvm-device.c
@@ -27,7 +27,8 @@ int vgic_check_iorange(struct kvm *kvm, phys_addr_t ioaddr,
if (addr + size < addr)
return -EINVAL;
- if (addr & ~kvm_phys_mask(kvm) || addr + size > kvm_phys_size(kvm))
+ if (addr & ~kvm_phys_mask(&kvm->arch.mmu) ||
+ (addr + size) > kvm_phys_size(&kvm->arch.mmu))
return -E2BIG;
return 0;
@@ -339,13 +340,9 @@ int vgic_v2_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr,
{
int cpuid;
- cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
- KVM_DEV_ARM_VGIC_CPUID_SHIFT;
+ cpuid = FIELD_GET(KVM_DEV_ARM_VGIC_CPUID_MASK, attr->attr);
- if (cpuid >= atomic_read(&dev->kvm->online_vcpus))
- return -EINVAL;
-
- reg_attr->vcpu = kvm_get_vcpu(dev->kvm, cpuid);
+ reg_attr->vcpu = kvm_get_vcpu_by_id(dev->kvm, cpuid);
reg_attr->addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
return 0;
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
index 188d2187eede..89117ba2528a 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
@@ -1013,35 +1013,6 @@ int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
return 0;
}
-/*
- * Compare a given affinity (level 1-3 and a level 0 mask, from the SGI
- * generation register ICC_SGI1R_EL1) with a given VCPU.
- * If the VCPU's MPIDR matches, return the level0 affinity, otherwise
- * return -1.
- */
-static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct kvm_vcpu *vcpu)
-{
- unsigned long affinity;
- int level0;
-
- /*
- * Split the current VCPU's MPIDR into affinity level 0 and the
- * rest as this is what we have to compare against.
- */
- affinity = kvm_vcpu_get_mpidr_aff(vcpu);
- level0 = MPIDR_AFFINITY_LEVEL(affinity, 0);
- affinity &= ~MPIDR_LEVEL_MASK;
-
- /* bail out if the upper three levels don't match */
- if (sgi_aff != affinity)
- return -1;
-
- /* Is this VCPU's bit set in the mask ? */
- if (!(sgi_cpu_mask & BIT(level0)))
- return -1;
-
- return level0;
-}
/*
* The ICC_SGI* registers encode the affinity differently from the MPIDR,
@@ -1052,6 +1023,38 @@ static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct kvm_vcpu *vcpu)
((((reg) & ICC_SGI1R_AFFINITY_## level ##_MASK) \
>> ICC_SGI1R_AFFINITY_## level ##_SHIFT) << MPIDR_LEVEL_SHIFT(level))
+static void vgic_v3_queue_sgi(struct kvm_vcpu *vcpu, u32 sgi, bool allow_group1)
+{
+ struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, sgi);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&irq->irq_lock, flags);
+
+ /*
+ * An access targeting Group0 SGIs can only generate
+ * those, while an access targeting Group1 SGIs can
+ * generate interrupts of either group.
+ */
+ if (!irq->group || allow_group1) {
+ if (!irq->hw) {
+ irq->pending_latch = true;
+ vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+ } else {
+ /* HW SGI? Ask the GIC to inject it */
+ int err;
+ err = irq_set_irqchip_state(irq->host_irq,
+ IRQCHIP_STATE_PENDING,
+ true);
+ WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
+ raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+ }
+ } else {
+ raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+ }
+
+ vgic_put_irq(vcpu->kvm, irq);
+}
+
/**
* vgic_v3_dispatch_sgi - handle SGI requests from VCPUs
* @vcpu: The VCPU requesting a SGI
@@ -1062,83 +1065,46 @@ static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct kvm_vcpu *vcpu)
* This will trap in sys_regs.c and call this function.
* This ICC_SGI1R_EL1 register contains the upper three affinity levels of the
* target processors as well as a bitmask of 16 Aff0 CPUs.
- * If the interrupt routing mode bit is not set, we iterate over all VCPUs to
- * check for matching ones. If this bit is set, we signal all, but not the
- * calling VCPU.
+ *
+ * If the interrupt routing mode bit is not set, we iterate over the Aff0
+ * bits and signal the VCPUs matching the provided Aff{3,2,1}.
+ *
+ * If this bit is set, we signal all, but not the calling VCPU.
*/
void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1)
{
struct kvm *kvm = vcpu->kvm;
struct kvm_vcpu *c_vcpu;
- u16 target_cpus;
+ unsigned long target_cpus;
u64 mpidr;
- int sgi;
- int vcpu_id = vcpu->vcpu_id;
- bool broadcast;
- unsigned long c, flags;
-
- sgi = (reg & ICC_SGI1R_SGI_ID_MASK) >> ICC_SGI1R_SGI_ID_SHIFT;
- broadcast = reg & BIT_ULL(ICC_SGI1R_IRQ_ROUTING_MODE_BIT);
- target_cpus = (reg & ICC_SGI1R_TARGET_LIST_MASK) >> ICC_SGI1R_TARGET_LIST_SHIFT;
- mpidr = SGI_AFFINITY_LEVEL(reg, 3);
- mpidr |= SGI_AFFINITY_LEVEL(reg, 2);
- mpidr |= SGI_AFFINITY_LEVEL(reg, 1);
-
- /*
- * We iterate over all VCPUs to find the MPIDRs matching the request.
- * If we have handled one CPU, we clear its bit to detect early
- * if we are already finished. This avoids iterating through all
- * VCPUs when most of the times we just signal a single VCPU.
- */
- kvm_for_each_vcpu(c, c_vcpu, kvm) {
- struct vgic_irq *irq;
-
- /* Exit early if we have dealt with all requested CPUs */
- if (!broadcast && target_cpus == 0)
- break;
-
- /* Don't signal the calling VCPU */
- if (broadcast && c == vcpu_id)
- continue;
+ u32 sgi, aff0;
+ unsigned long c;
- if (!broadcast) {
- int level0;
+ sgi = FIELD_GET(ICC_SGI1R_SGI_ID_MASK, reg);
- level0 = match_mpidr(mpidr, target_cpus, c_vcpu);
- if (level0 == -1)
+ /* Broadcast */
+ if (unlikely(reg & BIT_ULL(ICC_SGI1R_IRQ_ROUTING_MODE_BIT))) {
+ kvm_for_each_vcpu(c, c_vcpu, kvm) {
+ /* Don't signal the calling VCPU */
+ if (c_vcpu == vcpu)
continue;
- /* remove this matching VCPU from the mask */
- target_cpus &= ~BIT(level0);
+ vgic_v3_queue_sgi(c_vcpu, sgi, allow_group1);
}
- irq = vgic_get_irq(vcpu->kvm, c_vcpu, sgi);
-
- raw_spin_lock_irqsave(&irq->irq_lock, flags);
+ return;
+ }
- /*
- * An access targeting Group0 SGIs can only generate
- * those, while an access targeting Group1 SGIs can
- * generate interrupts of either group.
- */
- if (!irq->group || allow_group1) {
- if (!irq->hw) {
- irq->pending_latch = true;
- vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
- } else {
- /* HW SGI? Ask the GIC to inject it */
- int err;
- err = irq_set_irqchip_state(irq->host_irq,
- IRQCHIP_STATE_PENDING,
- true);
- WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
- raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
- }
- } else {
- raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
- }
+ /* We iterate over affinities to find the corresponding vcpus */
+ mpidr = SGI_AFFINITY_LEVEL(reg, 3);
+ mpidr |= SGI_AFFINITY_LEVEL(reg, 2);
+ mpidr |= SGI_AFFINITY_LEVEL(reg, 1);
+ target_cpus = FIELD_GET(ICC_SGI1R_TARGET_LIST_MASK, reg);
- vgic_put_irq(vcpu->kvm, irq);
+ for_each_set_bit(aff0, &target_cpus, hweight_long(ICC_SGI1R_TARGET_LIST_MASK)) {
+ c_vcpu = kvm_mpidr_to_vcpu(kvm, mpidr | aff0);
+ if (c_vcpu)
+ vgic_v3_queue_sgi(c_vcpu, sgi, allow_group1);
}
}
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
index 3dfc8b84e03e..9465d3706ab9 100644
--- a/arch/arm64/kvm/vgic/vgic-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-v3.c
@@ -684,7 +684,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
if (kvm_vgic_global_state.vcpu_base == 0)
kvm_info("disabling GICv2 emulation\n");
- if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_30115)) {
+ if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_30115)) {
group0_trap = true;
group1_trap = true;
}
diff --git a/arch/arm64/kvm/vgic/vgic-v4.c b/arch/arm64/kvm/vgic/vgic-v4.c
index 339a55194b2c..74a67ad87f29 100644
--- a/arch/arm64/kvm/vgic/vgic-v4.c
+++ b/arch/arm64/kvm/vgic/vgic-v4.c
@@ -436,6 +436,10 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
if (ret)
goto out;
+ /* Silently exit if the vLPI is already mapped */
+ if (irq->hw)
+ goto out;
+
/*
* Emit the mapping request. If it fails, the ITS probably
* isn't v4 compatible, so let's silently bail out. Holding
diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index 8be4c1ebdec2..db2a95762b1b 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -422,7 +422,7 @@ retry:
/**
* kvm_vgic_inject_irq - Inject an IRQ from a device to the vgic
* @kvm: The VM structure pointer
- * @cpuid: The CPU for PPIs
+ * @vcpu: The CPU for PPIs or NULL for global interrupts
* @intid: The INTID to inject a new state to.
* @level: Edge-triggered: true: to trigger the interrupt
* false: to ignore the call
@@ -436,24 +436,22 @@ retry:
* level-sensitive interrupts. You can think of the level parameter as 1
* being HIGH and 0 being LOW and all devices being active-HIGH.
*/
-int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
- bool level, void *owner)
+int kvm_vgic_inject_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
+ unsigned int intid, bool level, void *owner)
{
- struct kvm_vcpu *vcpu;
struct vgic_irq *irq;
unsigned long flags;
int ret;
- trace_vgic_update_irq_pending(cpuid, intid, level);
-
ret = vgic_lazy_init(kvm);
if (ret)
return ret;
- vcpu = kvm_get_vcpu(kvm, cpuid);
if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
return -EINVAL;
+ trace_vgic_update_irq_pending(vcpu ? vcpu->vcpu_idx : 0, intid, level);
+
irq = vgic_get_irq(kvm, vcpu, intid);
if (!irq)
return -EINVAL;
diff --git a/arch/arm64/kvm/vmid.c b/arch/arm64/kvm/vmid.c
index 7fe8ba1a2851..806223b7022a 100644
--- a/arch/arm64/kvm/vmid.c
+++ b/arch/arm64/kvm/vmid.c
@@ -135,10 +135,11 @@ void kvm_arm_vmid_clear_active(void)
atomic64_set(this_cpu_ptr(&active_vmids), VMID_ACTIVE_INVALID);
}
-void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid)
+bool kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid)
{
unsigned long flags;
u64 vmid, old_active_vmid;
+ bool updated = false;
vmid = atomic64_read(&kvm_vmid->id);
@@ -156,17 +157,21 @@ void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid)
if (old_active_vmid != 0 && vmid_gen_match(vmid) &&
0 != atomic64_cmpxchg_relaxed(this_cpu_ptr(&active_vmids),
old_active_vmid, vmid))
- return;
+ return false;
raw_spin_lock_irqsave(&cpu_vmid_lock, flags);
/* Check that our VMID belongs to the current generation. */
vmid = atomic64_read(&kvm_vmid->id);
- if (!vmid_gen_match(vmid))
+ if (!vmid_gen_match(vmid)) {
vmid = new_vmid(kvm_vmid);
+ updated = true;
+ }
atomic64_set(this_cpu_ptr(&active_vmids), vmid);
raw_spin_unlock_irqrestore(&cpu_vmid_lock, flags);
+
+ return updated;
}
/*
diff --git a/arch/arm64/lib/delay.c b/arch/arm64/lib/delay.c
index 5b7890139bc2..cb2062e7e234 100644
--- a/arch/arm64/lib/delay.c
+++ b/arch/arm64/lib/delay.c
@@ -27,7 +27,7 @@ void __delay(unsigned long cycles)
{
cycles_t start = get_cycles();
- if (cpus_have_const_cap(ARM64_HAS_WFXT)) {
+ if (alternative_has_cap_unlikely(ARM64_HAS_WFXT)) {
u64 end = start + cycles;
/*
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 2e5d1e238af9..460d799e1296 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -571,7 +571,7 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
/* Write implies read */
vm_flags |= VM_WRITE;
/* If EPAN is absent then exec implies read */
- if (!cpus_have_const_cap(ARM64_HAS_EPAN))
+ if (!alternative_has_cap_unlikely(ARM64_HAS_EPAN))
vm_flags |= VM_EXEC;
}
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 13fd592228b1..f5aae342632c 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -544,8 +544,7 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
- if (IS_ENABLED(CONFIG_ARM64_ERRATUM_2645198) &&
- cpus_have_const_cap(ARM64_WORKAROUND_2645198)) {
+ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_2645198)) {
/*
* Break-before-make (BBM) is required for all user space mappings
* when the permission changes from executable to non-executable
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 8a0f8604348b..74c1db8ce271 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -16,6 +16,7 @@
#include <linux/nodemask.h>
#include <linux/initrd.h>
#include <linux/gfp.h>
+#include <linux/math.h>
#include <linux/memblock.h>
#include <linux/sort.h>
#include <linux/of.h>
@@ -64,15 +65,6 @@ EXPORT_SYMBOL(memstart_addr);
*/
phys_addr_t __ro_after_init arm64_dma_phys_limit;
-/* Current arm64 boot protocol requires 2MB alignment */
-#define CRASH_ALIGN SZ_2M
-
-#define CRASH_ADDR_LOW_MAX arm64_dma_phys_limit
-#define CRASH_ADDR_HIGH_MAX (PHYS_MASK + 1)
-#define CRASH_HIGH_SEARCH_BASE SZ_4G
-
-#define DEFAULT_CRASH_KERNEL_LOW_SIZE (128UL << 20)
-
/*
* To make optimal use of block mappings when laying out the linear
* mapping, round down the base of physical memory to a size that can
@@ -100,140 +92,25 @@ phys_addr_t __ro_after_init arm64_dma_phys_limit;
#define ARM64_MEMSTART_ALIGN (1UL << ARM64_MEMSTART_SHIFT)
#endif
-static int __init reserve_crashkernel_low(unsigned long long low_size)
+static void __init arch_reserve_crashkernel(void)
{
- unsigned long long low_base;
-
- low_base = memblock_phys_alloc_range(low_size, CRASH_ALIGN, 0, CRASH_ADDR_LOW_MAX);
- if (!low_base) {
- pr_err("cannot allocate crashkernel low memory (size:0x%llx).\n", low_size);
- return -ENOMEM;
- }
-
- pr_info("crashkernel low memory reserved: 0x%08llx - 0x%08llx (%lld MB)\n",
- low_base, low_base + low_size, low_size >> 20);
-
- crashk_low_res.start = low_base;
- crashk_low_res.end = low_base + low_size - 1;
- insert_resource(&iomem_resource, &crashk_low_res);
-
- return 0;
-}
-
-/*
- * reserve_crashkernel() - reserves memory for crash kernel
- *
- * This function reserves memory area given in "crashkernel=" kernel command
- * line parameter. The memory reserved is used by dump capture kernel when
- * primary kernel is crashing.
- */
-static void __init reserve_crashkernel(void)
-{
- unsigned long long crash_low_size = 0, search_base = 0;
- unsigned long long crash_max = CRASH_ADDR_LOW_MAX;
+ unsigned long long low_size = 0;
unsigned long long crash_base, crash_size;
char *cmdline = boot_command_line;
- bool fixed_base = false;
bool high = false;
int ret;
if (!IS_ENABLED(CONFIG_KEXEC_CORE))
return;
- /* crashkernel=X[@offset] */
ret = parse_crashkernel(cmdline, memblock_phys_mem_size(),
- &crash_size, &crash_base);
- if (ret == -ENOENT) {
- ret = parse_crashkernel_high(cmdline, 0, &crash_size, &crash_base);
- if (ret || !crash_size)
- return;
-
- /*
- * crashkernel=Y,low can be specified or not, but invalid value
- * is not allowed.
- */
- ret = parse_crashkernel_low(cmdline, 0, &crash_low_size, &crash_base);
- if (ret == -ENOENT)
- crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
- else if (ret)
- return;
-
- search_base = CRASH_HIGH_SEARCH_BASE;
- crash_max = CRASH_ADDR_HIGH_MAX;
- high = true;
- } else if (ret || !crash_size) {
- /* The specified value is invalid */
- return;
- }
-
- crash_size = PAGE_ALIGN(crash_size);
-
- /* User specifies base address explicitly. */
- if (crash_base) {
- fixed_base = true;
- search_base = crash_base;
- crash_max = crash_base + crash_size;
- }
-
-retry:
- crash_base = memblock_phys_alloc_range(crash_size, CRASH_ALIGN,
- search_base, crash_max);
- if (!crash_base) {
- /*
- * For crashkernel=size[KMG]@offset[KMG], print out failure
- * message if can't reserve the specified region.
- */
- if (fixed_base) {
- pr_warn("crashkernel reservation failed - memory is in use.\n");
- return;
- }
-
- /*
- * For crashkernel=size[KMG], if the first attempt was for
- * low memory, fall back to high memory, the minimum required
- * low memory will be reserved later.
- */
- if (!high && crash_max == CRASH_ADDR_LOW_MAX) {
- crash_max = CRASH_ADDR_HIGH_MAX;
- search_base = CRASH_ADDR_LOW_MAX;
- crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
- goto retry;
- }
-
- /*
- * For crashkernel=size[KMG],high, if the first attempt was
- * for high memory, fall back to low memory.
- */
- if (high && crash_max == CRASH_ADDR_HIGH_MAX) {
- crash_max = CRASH_ADDR_LOW_MAX;
- search_base = 0;
- goto retry;
- }
- pr_warn("cannot allocate crashkernel (size:0x%llx)\n",
- crash_size);
+ &crash_size, &crash_base,
+ &low_size, &high);
+ if (ret)
return;
- }
-
- if ((crash_base >= CRASH_ADDR_LOW_MAX) && crash_low_size &&
- reserve_crashkernel_low(crash_low_size)) {
- memblock_phys_free(crash_base, crash_size);
- return;
- }
-
- pr_info("crashkernel reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
- crash_base, crash_base + crash_size, crash_size >> 20);
- /*
- * The crashkernel memory will be removed from the kernel linear
- * map. Inform kmemleak so that it won't try to access it.
- */
- kmemleak_ignore_phys(crash_base);
- if (crashk_low_res.end)
- kmemleak_ignore_phys(crashk_low_res.start);
-
- crashk_res.start = crash_base;
- crashk_res.end = crash_base + crash_size - 1;
- insert_resource(&iomem_resource, &crashk_res);
+ reserve_crashkernel_generic(cmdline, crash_size, crash_base,
+ low_size, high);
}
/*
@@ -479,7 +356,7 @@ void __init bootmem_init(void)
* request_standard_resources() depends on crashkernel's memory being
* reserved, so do it here.
*/
- reserve_crashkernel();
+ arch_reserve_crashkernel();
memblock_dump_all();
}
@@ -493,8 +370,16 @@ void __init mem_init(void)
{
bool swiotlb = max_pfn > PFN_DOWN(arm64_dma_phys_limit);
- if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC))
+ if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb) {
+ /*
+ * If no bouncing needed for ZONE_DMA, reduce the swiotlb
+ * buffer for kmalloc() bouncing to 1MB per 1GB of RAM.
+ */
+ unsigned long size =
+ DIV_ROUND_UP(memblock_phys_mem_size(), 1024);
+ swiotlb_adjust_size(min(swiotlb_size_or_default(), size));
swiotlb = true;
+ }
swiotlb_init(swiotlb, SWIOTLB_VERBOSE);
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index f17d066e85eb..555285ebd5af 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -300,7 +300,11 @@ void __init kasan_init(void)
kasan_init_shadow();
kasan_init_depth();
#if defined(CONFIG_KASAN_GENERIC)
- /* CONFIG_KASAN_SW_TAGS also requires kasan_init_sw_tags(). */
+ /*
+ * Generic KASAN is now fully initialized.
+ * Software and Hardware Tag-Based modes still require
+ * kasan_init_sw_tags() and kasan_init_hw_tags() correspondingly.
+ */
pr_info("KernelAddressSanitizer initialized (generic)\n");
#endif
}
diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
index 8f5b7ce857ed..645fe60d000f 100644
--- a/arch/arm64/mm/mmap.c
+++ b/arch/arm64/mm/mmap.c
@@ -68,7 +68,7 @@ static int __init adjust_protection_map(void)
* With Enhanced PAN we can honour the execute-only permissions as
* there is no PAN override with such mappings.
*/
- if (cpus_have_const_cap(ARM64_HAS_EPAN)) {
+ if (cpus_have_cap(ARM64_HAS_EPAN)) {
protection_map[VM_EXEC] = PAGE_EXECONLY;
protection_map[VM_EXEC | VM_SHARED] = PAGE_EXECONLY;
}
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 47781bec6171..15f6347d23b6 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1469,8 +1469,7 @@ early_initcall(prevent_bootmem_remove_init);
pte_t ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
- if (IS_ENABLED(CONFIG_ARM64_ERRATUM_2645198) &&
- cpus_have_const_cap(ARM64_WORKAROUND_2645198)) {
+ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_2645198)) {
/*
* Break-before-make (BBM) is required for all user space mappings
* when the permission changes from executable to non-executable
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index 8e2017ba5f1b..924843f1f661 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -29,8 +29,8 @@ bool can_set_direct_map(void)
*
* KFENCE pool requires page-granular mapping if initialized late.
*/
- return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() ||
- arm64_kfence_can_set_direct_map();
+ return rodata_full || debug_pagealloc_enabled() ||
+ arm64_kfence_can_set_direct_map();
}
static int change_page_range(pte_t *ptep, unsigned long addr, void *data)
@@ -105,8 +105,7 @@ static int change_memory_common(unsigned long addr, int numpages,
* If we are manipulating read-only permissions, apply the same
* change to the linear mapping of the pages that back this VM area.
*/
- if (rodata_enabled &&
- rodata_full && (pgprot_val(set_mask) == PTE_RDONLY ||
+ if (rodata_full && (pgprot_val(set_mask) == PTE_RDONLY ||
pgprot_val(clear_mask) == PTE_RDONLY)) {
for (i = 0; i < area->nr_pages; i++) {
__change_memory_common((u64)page_address(area->pages[i]),
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 14fdf645edc8..f66c37a1610e 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -405,8 +405,7 @@ SYM_FUNC_START(__cpu_setup)
tlbi vmalle1 // Invalidate local TLB
dsb nsh
- mov x1, #3 << 20
- msr cpacr_el1, x1 // Enable FP/ASIMD
+ msr cpacr_el1, xzr // Reset cpacr_el1
mov x1, #1 << 12 // Reset mdscr_el1 and disable
msr mdscr_el1, x1 // access to the DCC from EL0
isb // Unmask debug exceptions now,
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 150d1c6543f7..7d4af64e3982 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -288,7 +288,7 @@ static bool is_lsi_offset(int offset, int scale)
static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
{
const struct bpf_prog *prog = ctx->prog;
- const bool is_main_prog = prog->aux->func_idx == 0;
+ const bool is_main_prog = !bpf_is_subprog(prog);
const u8 r6 = bpf2a64[BPF_REG_6];
const u8 r7 = bpf2a64[BPF_REG_7];
const u8 r8 = bpf2a64[BPF_REG_8];
diff --git a/arch/arm64/tools/Makefile b/arch/arm64/tools/Makefile
index 07a93ab21a62..fa2251d9762d 100644
--- a/arch/arm64/tools/Makefile
+++ b/arch/arm64/tools/Makefile
@@ -3,7 +3,7 @@
gen := arch/$(ARCH)/include/generated
kapi := $(gen)/asm
-kapi-hdrs-y := $(kapi)/cpucaps.h $(kapi)/sysreg-defs.h
+kapi-hdrs-y := $(kapi)/cpucap-defs.h $(kapi)/sysreg-defs.h
targets += $(addprefix ../../../, $(kapi-hdrs-y))
@@ -17,7 +17,7 @@ quiet_cmd_gen_cpucaps = GEN $@
quiet_cmd_gen_sysreg = GEN $@
cmd_gen_sysreg = mkdir -p $(dir $@); $(AWK) -f $(real-prereqs) > $@
-$(kapi)/cpucaps.h: $(src)/gen-cpucaps.awk $(src)/cpucaps FORCE
+$(kapi)/cpucap-defs.h: $(src)/gen-cpucaps.awk $(src)/cpucaps FORCE
$(call if_changed,gen_cpucaps)
$(kapi)/sysreg-defs.h: $(src)/gen-sysreg.awk $(src)/sysreg FORCE
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index dea3dc89234b..b98c38288a9d 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -27,6 +27,7 @@ HAS_ECV_CNTPOFF
HAS_EPAN
HAS_EVT
HAS_FGT
+HAS_FPSIMD
HAS_GENERIC_AUTH
HAS_GENERIC_AUTH_ARCH_QARMA3
HAS_GENERIC_AUTH_ARCH_QARMA5
@@ -39,7 +40,6 @@ HAS_LDAPR
HAS_LSE_ATOMICS
HAS_MOPS
HAS_NESTED_VIRT
-HAS_NO_FPSIMD
HAS_NO_HW_PREFETCH
HAS_PAN
HAS_S1PIE
diff --git a/arch/arm64/tools/gen-cpucaps.awk b/arch/arm64/tools/gen-cpucaps.awk
index 8525980379d7..2f4f61a0af17 100755
--- a/arch/arm64/tools/gen-cpucaps.awk
+++ b/arch/arm64/tools/gen-cpucaps.awk
@@ -15,8 +15,8 @@ function fatal(msg) {
/^#/ { next }
BEGIN {
- print "#ifndef __ASM_CPUCAPS_H"
- print "#define __ASM_CPUCAPS_H"
+ print "#ifndef __ASM_CPUCAP_DEFS_H"
+ print "#define __ASM_CPUCAP_DEFS_H"
print ""
print "/* Generated file - do not edit */"
cap_num = 0
@@ -31,7 +31,7 @@ BEGIN {
END {
printf("#define ARM64_NCAPS\t\t\t\t\t%d\n", cap_num)
print ""
- print "#endif /* __ASM_CPUCAPS_H */"
+ print "#endif /* __ASM_CPUCAP_DEFS_H */"
}
# Any lines not handled by previous rules are unexpected
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index 76ce150e7347..96cbeeab4eec 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -1026,7 +1026,11 @@ UnsignedEnum 35:32 SHA3
0b0000 NI
0b0001 IMP
EndEnum
-Res0 31:24
+Res0 31:28
+UnsignedEnum 27:24 B16B16
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
UnsignedEnum 23:20 BF16
0b0000 NI
0b0001 IMP
@@ -1235,6 +1239,7 @@ EndEnum
UnsignedEnum 23:20 ATOMIC
0b0000 NI
0b0010 IMP
+ 0b0011 FEAT_LSE128
EndEnum
UnsignedEnum 19:16 CRC32
0b0000 NI
@@ -1305,6 +1310,7 @@ UnsignedEnum 23:20 LRCPC
0b0000 NI
0b0001 IMP
0b0010 LRCPC2
+ 0b0011 LRCPC3
EndEnum
UnsignedEnum 19:16 FCMA
0b0000 NI
diff --git a/arch/csky/abiv1/alignment.c b/arch/csky/abiv1/alignment.c
index b60259daed1b..e5b8b4b2109a 100644
--- a/arch/csky/abiv1/alignment.c
+++ b/arch/csky/abiv1/alignment.c
@@ -329,7 +329,6 @@ static struct ctl_table alignment_tbl[5] = {
.mode = 0666,
.proc_handler = &proc_dointvec
},
- {}
};
static int __init csky_alignment_init(void)
diff --git a/arch/csky/kernel/setup.c b/arch/csky/kernel/setup.c
index 106fbf0b6f3b..51012e90780d 100644
--- a/arch/csky/kernel/setup.c
+++ b/arch/csky/kernel/setup.c
@@ -8,22 +8,10 @@
#include <linux/of_fdt.h>
#include <linux/start_kernel.h>
#include <linux/dma-map-ops.h>
-#include <linux/screen_info.h>
#include <asm/sections.h>
#include <asm/mmu_context.h>
#include <asm/pgalloc.h>
-#ifdef CONFIG_DUMMY_CONSOLE
-struct screen_info screen_info = {
- .orig_video_lines = 30,
- .orig_video_cols = 80,
- .orig_video_mode = 0,
- .orig_video_ega_bx = 0,
- .orig_video_isVGA = 1,
- .orig_video_points = 8
-};
-#endif
-
static void __init csky_memblock_init(void)
{
unsigned long lowmem_size = PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
diff --git a/arch/csky/kernel/vdso/Makefile b/arch/csky/kernel/vdso/Makefile
index 299e4e41ebc5..ddf784a62c11 100644
--- a/arch/csky/kernel/vdso/Makefile
+++ b/arch/csky/kernel/vdso/Makefile
@@ -58,13 +58,3 @@ quiet_cmd_vdsold = VDSOLD $@
# that contains the same symbols at the same offsets.
quiet_cmd_so2s = SO2S $@
cmd_so2s = $(NM) -D $< | $(srctree)/$(src)/so2s.sh > $@
-
-# install commands for the unstripped file
-quiet_cmd_vdso_install = INSTALL $@
- cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
-
-vdso.so: $(obj)/vdso.so.dbg
- @mkdir -p $(MODLIB)/vdso
- $(call cmd,vdso_install)
-
-vdso_install: vdso.so
diff --git a/arch/hexagon/include/asm/ptrace.h b/arch/hexagon/include/asm/ptrace.h
new file mode 100644
index 000000000000..ed35da1ee685
--- /dev/null
+++ b/arch/hexagon/include/asm/ptrace.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Ptrace definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _ASM_HEXAGON_PTRACE_H
+#define _ASM_HEXAGON_PTRACE_H
+
+#include <uapi/asm/ptrace.h>
+
+/* kprobe-based event tracer support */
+extern int regs_query_register_offset(const char *name);
+extern const char *regs_query_register_name(unsigned int offset);
+
+#define current_pt_regs() \
+ ((struct pt_regs *) \
+ ((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
+
+#if CONFIG_HEXAGON_ARCH_VERSION >= 4
+#define arch_has_single_step() (1)
+#endif
+
+#endif
diff --git a/arch/hexagon/include/uapi/asm/ptrace.h b/arch/hexagon/include/uapi/asm/ptrace.h
index f79de05b8689..2a3ea14ad9b9 100644
--- a/arch/hexagon/include/uapi/asm/ptrace.h
+++ b/arch/hexagon/include/uapi/asm/ptrace.h
@@ -29,17 +29,4 @@
#define profile_pc(regs) instruction_pointer(regs)
-/* kprobe-based event tracer support */
-extern int regs_query_register_offset(const char *name);
-extern const char *regs_query_register_name(unsigned int offset);
-
-#define current_pt_regs() \
- ((struct pt_regs *) \
- ((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
-
-#if CONFIG_HEXAGON_ARCH_VERSION >= 4
-#define arch_has_single_step() (1)
-#endif
-
-
#endif
diff --git a/arch/hexagon/kernel/Makefile b/arch/hexagon/kernel/Makefile
index e73cb321630e..3fdf937eb572 100644
--- a/arch/hexagon/kernel/Makefile
+++ b/arch/hexagon/kernel/Makefile
@@ -17,5 +17,3 @@ obj-y += vm_vectors.o
obj-$(CONFIG_HAS_DMA) += dma.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
-
-obj-$(CONFIG_VGA_CONSOLE) += screen_info.o
diff --git a/arch/hexagon/kernel/screen_info.c b/arch/hexagon/kernel/screen_info.c
deleted file mode 100644
index 1e1ceb18bafe..000000000000
--- a/arch/hexagon/kernel/screen_info.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#include <linux/screen_info.h>
-
-struct screen_info screen_info;
diff --git a/arch/ia64/Kbuild b/arch/ia64/Kbuild
deleted file mode 100644
index e77cc76d228c..000000000000
--- a/arch/ia64/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-y += kernel/ mm/
-obj-$(CONFIG_IA64_SGI_UV) += uv/
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
deleted file mode 100644
index 53faa122b0f4..000000000000
--- a/arch/ia64/Kconfig
+++ /dev/null
@@ -1,394 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config PGTABLE_LEVELS
- int "Page Table Levels" if !IA64_PAGE_SIZE_64KB
- range 3 4 if !IA64_PAGE_SIZE_64KB
- default 3
-
-menu "Processor type and features"
-
-config IA64
- bool
- select ARCH_BINFMT_ELF_EXTRA_PHDRS
- select ARCH_HAS_CPU_FINALIZE_INIT
- select ARCH_HAS_DMA_MARK_CLEAN
- select ARCH_HAS_STRNCPY_FROM_USER
- select ARCH_HAS_STRNLEN_USER
- select ARCH_MIGHT_HAVE_PC_PARPORT
- select ARCH_MIGHT_HAVE_PC_SERIO
- select ACPI
- select ACPI_NUMA if NUMA
- select ARCH_ENABLE_MEMORY_HOTPLUG
- select ARCH_ENABLE_MEMORY_HOTREMOVE
- select ARCH_SUPPORTS_ACPI
- select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
- select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
- select FORCE_PCI
- select PCI_DOMAINS if PCI
- select PCI_MSI
- select PCI_SYSCALL if PCI
- select HAS_IOPORT
- select HAVE_ASM_MODVERSIONS
- select HAVE_UNSTABLE_SCHED_CLOCK
- select HAVE_EXIT_THREAD
- select HAVE_KPROBES
- select HAVE_KRETPROBES
- select HAVE_FTRACE_MCOUNT_RECORD
- select HAVE_DYNAMIC_FTRACE if (!ITANIUM)
- select HAVE_FUNCTION_TRACER
- select HAVE_SETUP_PER_CPU_AREA
- select TTY
- select HAVE_ARCH_TRACEHOOK
- select HAVE_FUNCTION_DESCRIPTORS
- select HAVE_VIRT_CPU_ACCOUNTING
- select HUGETLB_PAGE_SIZE_VARIABLE if HUGETLB_PAGE
- select GENERIC_IRQ_PROBE
- select GENERIC_PENDING_IRQ if SMP
- select GENERIC_IRQ_SHOW
- select GENERIC_IRQ_LEGACY
- select ARCH_HAVE_NMI_SAFE_CMPXCHG
- select GENERIC_IOMAP
- select GENERIC_IOREMAP
- select GENERIC_SMP_IDLE_THREAD
- select ARCH_TASK_STRUCT_ON_STACK
- select ARCH_TASK_STRUCT_ALLOCATOR
- select ARCH_THREAD_STACK_ALLOCATOR
- select ARCH_CLOCKSOURCE_DATA
- select GENERIC_TIME_VSYSCALL
- select LEGACY_TIMER_TICK
- select SWIOTLB
- select SYSCTL_ARCH_UNALIGN_NO_WARN
- select HAVE_MOD_ARCH_SPECIFIC
- select MODULES_USE_ELF_RELA
- select ARCH_USE_CMPXCHG_LOCKREF
- select HAVE_ARCH_AUDITSYSCALL
- select NEED_DMA_MAP_STATE
- select NEED_SG_DMA_LENGTH
- select NUMA if !FLATMEM
- select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
- select ZONE_DMA32
- select FUNCTION_ALIGNMENT_32B
- default y
- help
- The Itanium Processor Family is Intel's 64-bit successor to
- the 32-bit X86 line. The IA-64 Linux project has a home
- page at <http://www.linuxia64.org/> and a mailing list at
- <linux-ia64@vger.kernel.org>.
-
-config 64BIT
- bool
- select ATA_NONSTANDARD if ATA
- default y
-
-config MMU
- bool
- default y
-
-config STACKTRACE_SUPPORT
- def_bool y
-
-config GENERIC_LOCKBREAK
- def_bool n
-
-config GENERIC_CALIBRATE_DELAY
- bool
- default y
-
-config DMI
- bool
- default y
- select DMI_SCAN_MACHINE_NON_EFI_FALLBACK
-
-config EFI
- bool
- select UCS2_STRING
- default y
-
-config SCHED_OMIT_FRAME_POINTER
- bool
- default y
-
-config IA64_UNCACHED_ALLOCATOR
- bool
- select GENERIC_ALLOCATOR
-
-config ARCH_USES_PG_UNCACHED
- def_bool y
- depends on IA64_UNCACHED_ALLOCATOR
-
-config AUDIT_ARCH
- bool
- default y
-
-choice
- prompt "Processor type"
- default ITANIUM
-
-config ITANIUM
- bool "Itanium"
- help
- Select your IA-64 processor type. The default is Itanium.
- This choice is safe for all IA-64 systems, but may not perform
- optimally on systems with, say, Itanium 2 or newer processors.
-
-config MCKINLEY
- bool "Itanium 2"
- help
- Select this to configure for an Itanium 2 (McKinley) processor.
-
-endchoice
-
-choice
- prompt "Kernel page size"
- default IA64_PAGE_SIZE_16KB
-
-config IA64_PAGE_SIZE_4KB
- bool "4KB"
- help
- This lets you select the page size of the kernel. For best IA-64
- performance, a page size of 8KB or 16KB is recommended. For best
- IA-32 compatibility, a page size of 4KB should be selected (the vast
- majority of IA-32 binaries work perfectly fine with a larger page
- size). For Itanium 2 or newer systems, a page size of 64KB can also
- be selected.
-
- 4KB For best IA-32 compatibility
- 8KB For best IA-64 performance
- 16KB For best IA-64 performance
- 64KB Requires Itanium 2 or newer processor.
-
- If you don't know what to do, choose 16KB.
-
-config IA64_PAGE_SIZE_8KB
- bool "8KB"
-
-config IA64_PAGE_SIZE_16KB
- bool "16KB"
-
-config IA64_PAGE_SIZE_64KB
- depends on !ITANIUM
- bool "64KB"
-
-endchoice
-
-source "kernel/Kconfig.hz"
-
-config IA64_BRL_EMU
- bool
- depends on ITANIUM
- default y
-
-# align cache-sensitive data to 128 bytes
-config IA64_L1_CACHE_SHIFT
- int
- default "7" if MCKINLEY
- default "6" if ITANIUM
-
-config IA64_SGI_UV
- bool "SGI-UV support"
- help
- Selecting this option will add specific support for running on SGI
- UV based systems. If you have an SGI UV system or are building a
- distro kernel, select this option.
-
-config IA64_HP_SBA_IOMMU
- bool "HP SBA IOMMU support"
- select DMA_OPS
- default y
- help
- Say Y here to add support for the SBA IOMMU found on HP zx1 and
- sx1000 systems. If you're unsure, answer Y.
-
-config IA64_CYCLONE
- bool "Cyclone (EXA) Time Source support"
- help
- Say Y here to enable support for IBM EXA Cyclone time source.
- If you're unsure, answer N.
-
-config ARCH_FORCE_MAX_ORDER
- int
- default "16" if HUGETLB_PAGE
- default "10"
-
-config SMP
- bool "Symmetric multi-processing support"
- help
- This enables support for systems with more than one CPU. If you have
- a system with only one CPU, say N. If you have a system with more
- than one CPU, say Y.
-
- If you say N here, the kernel will run on single and multiprocessor
- systems, but will use only one CPU of a multiprocessor system. If
- you say Y here, the kernel will run on many, but not all,
- single processor systems. On a single processor system, the kernel
- will run faster if you say N here.
-
- See also the SMP-HOWTO available at
- <http://www.tldp.org/docs.html#howto>.
-
- If you don't know what to do here, say N.
-
-config NR_CPUS
- int "Maximum number of CPUs (2-4096)"
- range 2 4096
- depends on SMP
- default "4096"
- help
- You should set this to the number of CPUs in your system, but
- keep in mind that a kernel compiled for, e.g., 2 CPUs will boot but
- only use 2 CPUs on a >2 CPU system. Setting this to a value larger
- than 64 will cause the use of a CPU mask array, causing a small
- performance hit.
-
-config HOTPLUG_CPU
- bool "Support for hot-pluggable CPUs"
- depends on SMP
- default n
- help
- Say Y here to experiment with turning CPUs off and on. CPUs
- can be controlled through /sys/devices/system/cpu/cpu#.
- Say N if you want to disable CPU hotplug.
-
-config SCHED_SMT
- bool "SMT scheduler support"
- depends on SMP
- help
- Improves the CPU scheduler's decision making when dealing with
- Intel IA64 chips with MultiThreading at a cost of slightly increased
- overhead in some places. If unsure say N here.
-
-config PERMIT_BSP_REMOVE
- bool "Support removal of Bootstrap Processor"
- depends on HOTPLUG_CPU
- default n
- help
- Say Y here if your platform SAL will support removal of BSP with HOTPLUG_CPU
- support.
-
-config FORCE_CPEI_RETARGET
- bool "Force assumption that CPEI can be re-targeted"
- depends on PERMIT_BSP_REMOVE
- default n
- help
- Say Y if you need to force the assumption that CPEI can be re-targeted to
- any cpu in the system. This hint is available via ACPI 3.0 specifications.
- Tiger4 systems are capable of re-directing CPEI to any CPU other than BSP.
- This option it useful to enable this feature on older BIOS's as well.
- You can also enable this by using boot command line option force_cpei=1.
-
-config ARCH_SELECT_MEMORY_MODEL
- def_bool y
-
-config ARCH_FLATMEM_ENABLE
- def_bool y
-
-config ARCH_SPARSEMEM_ENABLE
- def_bool y
- select SPARSEMEM_VMEMMAP_ENABLE
-
-config ARCH_SPARSEMEM_DEFAULT
- def_bool y
- depends on ARCH_SPARSEMEM_ENABLE
-
-config NUMA
- bool "NUMA support"
- depends on !FLATMEM
- select SMP
- select USE_PERCPU_NUMA_NODE_ID
- help
- Say Y to compile the kernel to support NUMA (Non-Uniform Memory
- Access). This option is for configuring high-end multiprocessor
- server systems. If in doubt, say N.
-
-config NODES_SHIFT
- int "Max num nodes shift(3-10)"
- range 3 10
- default "10"
- depends on NUMA
- help
- This option specifies the maximum number of nodes in your SSI system.
- MAX_NUMNODES will be 2^(This value).
- If in doubt, use the default.
-
-config HAVE_ARCH_NODEDATA_EXTENSION
- def_bool y
- depends on NUMA
-
-config HAVE_MEMORYLESS_NODES
- def_bool NUMA
-
-config ARCH_PROC_KCORE_TEXT
- def_bool y
- depends on PROC_KCORE
-
-config IA64_MCA_RECOVERY
- bool "MCA recovery from errors other than TLB."
-
-config IA64_PALINFO
- tristate "/proc/pal support"
- help
- If you say Y here, you are able to get PAL (Processor Abstraction
- Layer) information in /proc/pal. This contains useful information
- about the processors in your systems, such as cache and TLB sizes
- and the PAL firmware version in use.
-
- To use this option, you have to ensure that the "/proc file system
- support" (CONFIG_PROC_FS) is enabled, too.
-
-config IA64_MC_ERR_INJECT
- tristate "MC error injection support"
- help
- Adds support for MC error injection. If enabled, the kernel
- will provide a sysfs interface for user applications to
- call MC error injection PAL procedures to inject various errors.
- This is a useful tool for MCA testing.
-
- If you're unsure, do not select this option.
-
-config IA64_ESI
- bool "ESI (Extensible SAL Interface) support"
- help
- If you say Y here, support is built into the kernel to
- make ESI calls. ESI calls are used to support vendor-specific
- firmware extensions, such as the ability to inject memory-errors
- for test-purposes. If you're unsure, say N.
-
-config IA64_HP_AML_NFW
- bool "Support ACPI AML calls to native firmware"
- help
- This driver installs a global ACPI Operation Region handler for
- region 0xA1. AML methods can use this OpRegion to call arbitrary
- native firmware functions. The driver installs the OpRegion
- handler if there is an HPQ5001 device or if the user supplies
- the "force" module parameter, e.g., with the "aml_nfw.force"
- kernel command line option.
-
-endmenu
-
-config ARCH_SUPPORTS_KEXEC
- def_bool !SMP || HOTPLUG_CPU
-
-config ARCH_SUPPORTS_CRASH_DUMP
- def_bool IA64_MCA_RECOVERY && (!SMP || HOTPLUG_CPU)
-
-menu "Power management and ACPI options"
-
-source "kernel/power/Kconfig"
-
-source "drivers/acpi/Kconfig"
-
-if PM
-menu "CPU Frequency scaling"
-source "drivers/cpufreq/Kconfig"
-endmenu
-endif
-
-endmenu
-
-config MSPEC
- tristate "Memory special operations driver"
- depends on IA64
- select IA64_UNCACHED_ALLOCATOR
- help
- If you have an ia64 and you want to enable memory special
- operations support (formerly known as fetchop), say Y here,
- otherwise say N.
diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
deleted file mode 100644
index 2ce008e2d164..000000000000
--- a/arch/ia64/Kconfig.debug
+++ /dev/null
@@ -1,55 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-choice
- prompt "Physical memory granularity"
- default IA64_GRANULE_64MB
-
-config IA64_GRANULE_16MB
- bool "16MB"
- help
- IA-64 identity-mapped regions use a large page size called "granules".
-
- Select "16MB" for a small granule size.
- Select "64MB" for a large granule size. This is the current default.
-
-config IA64_GRANULE_64MB
- bool "64MB"
- depends on BROKEN
-
-endchoice
-
-config IA64_PRINT_HAZARDS
- bool "Print possible IA-64 dependency violations to console"
- depends on DEBUG_KERNEL
- help
- Selecting this option prints more information for Illegal Dependency
- Faults, that is, for Read-after-Write (RAW), Write-after-Write (WAW),
- or Write-after-Read (WAR) violations. This option is ignored if you
- are compiling for an Itanium A step processor
- (CONFIG_ITANIUM_ASTEP_SPECIFIC). If you're unsure, select Y.
-
-config DISABLE_VHPT
- bool "Disable VHPT"
- depends on DEBUG_KERNEL
- help
- The Virtual Hash Page Table (VHPT) enhances virtual address
- translation performance. Normally you want the VHPT active but you
- can select this option to disable the VHPT for debugging. If you're
- unsure, answer N.
-
-config IA64_DEBUG_CMPXCHG
- bool "Turn on compare-and-exchange bug checking (slow!)"
- depends on DEBUG_KERNEL && PRINTK
- help
- Selecting this option turns on bug checking for the IA-64
- compare-and-exchange instructions. This is slow! Itaniums
- from step B3 or later don't have this problem. If you're unsure,
- select N.
-
-config IA64_DEBUG_IRQ
- bool "Turn on irq debug checks (slow!)"
- depends on DEBUG_KERNEL
- help
- Selecting this option turns on bug checking for the IA-64 irq_save
- and restore instructions. It's useful for tracking down spinlock
- problems, but slow! If you're unsure, select N.
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
deleted file mode 100644
index d553ab7022fe..000000000000
--- a/arch/ia64/Makefile
+++ /dev/null
@@ -1,82 +0,0 @@
-#
-# ia64/Makefile
-#
-# This file is included by the global makefile so that you can add your own
-# architecture-specific flags and dependencies.
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License. See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1998-2004 by David Mosberger-Tang <davidm@hpl.hp.com>
-#
-
-KBUILD_DEFCONFIG := generic_defconfig
-
-NM := $(CROSS_COMPILE)nm -B
-
-CHECKFLAGS += -D__ia64=1 -D__ia64__=1 -D_LP64 -D__LP64__
-
-OBJCOPYFLAGS := --strip-all
-LDFLAGS_vmlinux := -static
-KBUILD_AFLAGS_KERNEL := -mconstant-gp
-EXTRA :=
-
-cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \
- -frename-registers -fno-optimize-sibling-calls
-KBUILD_CFLAGS_KERNEL := -mconstant-gp
-
-GAS_STATUS = $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)")
-KBUILD_CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)")
-
-ifeq ($(GAS_STATUS),buggy)
-$(error Sorry, you need a newer version of the assember, one that is built from \
- a source-tree that post-dates 18-Dec-2002. You can find a pre-compiled \
- static binary of such an assembler at: \
- \
- ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
-endif
-
-quiet_cmd_gzip = GZIP $@
-cmd_gzip = cat $(real-prereqs) | $(KGZIP) -n -f -9 > $@
-
-quiet_cmd_objcopy = OBJCOPY $@
-cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
-
-KBUILD_CFLAGS += $(cflags-y)
-
-libs-y += arch/ia64/lib/
-
-drivers-y += arch/ia64/pci/ arch/ia64/hp/common/
-
-PHONY += compressed check
-
-all: compressed unwcheck
-
-compressed: vmlinux.gz
-
-vmlinuz: vmlinux.gz
-
-vmlinux.gz: vmlinux.bin FORCE
- $(call if_changed,gzip)
-
-vmlinux.bin: vmlinux FORCE
- $(call if_changed,objcopy)
-
-unwcheck: vmlinux
- -$(Q)READELF=$(READELF) $(PYTHON3) $(srctree)/arch/ia64/scripts/unwcheck.py $<
-
-archheaders:
- $(Q)$(MAKE) $(build)=arch/ia64/kernel/syscalls all
-
-CLEAN_FILES += vmlinux.gz
-
-install: KBUILD_IMAGE := vmlinux.gz
-install:
- $(call cmd,install)
-
-define archhelp
- echo '* compressed - Build compressed kernel image'
- echo ' install - Install compressed kernel image'
- echo '* unwcheck - Check vmlinux for invalid unwind info'
-endef
diff --git a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig
deleted file mode 100644
index 7cb96db9a25d..000000000000
--- a/arch/ia64/configs/bigsur_defconfig
+++ /dev/null
@@ -1,102 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_PROFILING=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_SGI_PARTITION=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_PREEMPT=y
-CONFIG_IA64_PALINFO=y
-CONFIG_BINFMT_MISC=m
-CONFIG_ACPI_BUTTON=m
-CONFIG_ACPI_FAN=m
-CONFIG_ACPI_PROCESSOR=m
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_IPV6 is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=m
-CONFIG_ATA=m
-CONFIG_ATA_GENERIC=m
-CONFIG_ATA_PIIX=m
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SPI_ATTRS=m
-CONFIG_SCSI_QLOGIC_1280=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID10=m
-CONFIG_MD_MULTIPATH=m
-CONFIG_BLK_DEV_DM=m
-CONFIG_DM_CRYPT=m
-CONFIG_DM_SNAPSHOT=m
-CONFIG_DM_MIRROR=m
-CONFIG_DM_ZERO=m
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_EFI=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_AGP=m
-CONFIG_AGP_I460=m
-CONFIG_DRM=m
-CONFIG_DRM_R128=m
-CONFIG_SOUND=m
-CONFIG_SND=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_CS4281=m
-CONFIG_USB_HIDDEV=y
-CONFIG_USB=m
-CONFIG_USB_MON=m
-CONFIG_USB_UHCI_HCD=m
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-CONFIG_USB_STORAGE=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_XFS_FS=y
-CONFIG_XFS_QUOTA=y
-CONFIG_XFS_POSIX_ACL=y
-CONFIG_AUTOFS_FS=m
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_UDF_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_HUGETLBFS=y
-CONFIG_NFS_FS=m
-CONFIG_NFS_V4=m
-CONFIG_NFSD=m
-CONFIG_NFSD_V4=y
-CONFIG_CIFS=m
-CONFIG_CIFS_XATTR=y
-CONFIG_CIFS_POSIX=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_UTF8=m
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_DES=y
diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
deleted file mode 100644
index 4581240013dd..000000000000
--- a/arch/ia64/configs/generic_defconfig
+++ /dev/null
@@ -1,206 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=20
-CONFIG_CGROUPS=y
-CONFIG_CPUSETS=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_SGI_PARTITION=y
-CONFIG_MCKINLEY=y
-CONFIG_IA64_PAGE_SIZE_64KB=y
-CONFIG_IA64_CYCLONE=y
-CONFIG_SMP=y
-CONFIG_HOTPLUG_CPU=y
-CONFIG_IA64_MCA_RECOVERY=y
-CONFIG_IA64_PALINFO=y
-CONFIG_KEXEC=y
-CONFIG_CRASH_DUMP=y
-CONFIG_BINFMT_MISC=m
-CONFIG_ACPI_BUTTON=m
-CONFIG_ACPI_FAN=m
-CONFIG_ACPI_DOCK=y
-CONFIG_ACPI_PROCESSOR=m
-CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_CONNECTOR=y
-# CONFIG_PNP_DEBUG_MESSAGES is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_SGI_XP=m
-CONFIG_ATA=y
-CONFIG_ATA_GENERIC=y
-CONFIG_PATA_CMD64X=y
-CONFIG_ATA_PIIX=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_CHR_DEV_SG=m
-CONFIG_SCSI_FC_ATTRS=y
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_QLOGIC_1280=y
-CONFIG_SATA_VITESSE=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_MULTIPATH=m
-CONFIG_BLK_DEV_DM=m
-CONFIG_DM_CRYPT=m
-CONFIG_DM_SNAPSHOT=m
-CONFIG_DM_MIRROR=m
-CONFIG_DM_ZERO=m
-CONFIG_DM_MULTIPATH=m
-CONFIG_FUSION=y
-CONFIG_FUSION_SPI=y
-CONFIG_FUSION_FC=m
-CONFIG_FUSION_SAS=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
-CONFIG_NETCONSOLE=y
-CONFIG_TIGON3=y
-CONFIG_NET_TULIP=y
-CONFIG_TULIP=m
-CONFIG_E100=m
-CONFIG_E1000=y
-CONFIG_IGB=y
-# CONFIG_SERIO_SERPORT is not set
-CONFIG_GAMEPORT=m
-CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=6
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_EFI=y
-CONFIG_HPET=y
-CONFIG_AGP=m
-CONFIG_AGP_I460=m
-CONFIG_AGP_HP_ZX1=m
-CONFIG_DRM=m
-CONFIG_DRM_TDFX=m
-CONFIG_DRM_R128=m
-CONFIG_DRM_RADEON=m
-CONFIG_DRM_MGA=m
-CONFIG_DRM_SIS=m
-CONFIG_SOUND=m
-CONFIG_SND=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
-CONFIG_SND_VERBOSE_PRINTK=y
-CONFIG_SND_DUMMY=m
-CONFIG_SND_VIRMIDI=m
-CONFIG_SND_MTPAV=m
-CONFIG_SND_SERIAL_U16550=m
-CONFIG_SND_MPU401=m
-CONFIG_SND_CS4281=m
-CONFIG_SND_CS46XX=m
-CONFIG_SND_EMU10K1=m
-CONFIG_SND_FM801=m
-CONFIG_HID_GYRATION=m
-CONFIG_HID_PANTHERLORD=m
-CONFIG_HID_PETALYNX=m
-CONFIG_HID_SAMSUNG=m
-CONFIG_HID_SONY=m
-CONFIG_HID_SUNPLUS=m
-CONFIG_USB=m
-CONFIG_USB_MON=m
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_OHCI_HCD=m
-CONFIG_USB_UHCI_HCD=m
-CONFIG_USB_STORAGE=m
-CONFIG_INFINIBAND=m
-CONFIG_INFINIBAND_MTHCA=m
-CONFIG_INFINIBAND_IPOIB=m
-CONFIG_INTEL_IOMMU=y
-CONFIG_MSPEC=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_REISERFS_FS=y
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
-CONFIG_XFS_FS=y
-CONFIG_AUTOFS_FS=m
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_UDF_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_NTFS_FS=m
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_HUGETLBFS=y
-CONFIG_NFS_FS=m
-CONFIG_NFS_V4=m
-CONFIG_NFSD=m
-CONFIG_NFSD_V4=y
-CONFIG_CIFS=m
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRC_T10DIF=y
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
deleted file mode 100644
index c9e806616544..000000000000
--- a/arch/ia64/configs/gensparse_defconfig
+++ /dev/null
@@ -1,184 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=20
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_SGI_PARTITION=y
-CONFIG_MCKINLEY=y
-CONFIG_IA64_CYCLONE=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=512
-CONFIG_HOTPLUG_CPU=y
-CONFIG_SPARSEMEM_MANUAL=y
-CONFIG_IA64_MCA_RECOVERY=y
-CONFIG_IA64_PALINFO=y
-CONFIG_BINFMT_MISC=m
-CONFIG_ACPI_BUTTON=m
-CONFIG_ACPI_FAN=m
-CONFIG_ACPI_PROCESSOR=m
-CONFIG_HOTPLUG_PCI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_IPV6 is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_ATA=y
-CONFIG_ATA_GENERIC=y
-CONFIG_PATA_CMD64X=y
-CONFIG_ATA_PIIX=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_CHR_DEV_SG=m
-CONFIG_SCSI_FC_ATTRS=y
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_QLOGIC_1280=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_MULTIPATH=m
-CONFIG_BLK_DEV_DM=m
-CONFIG_DM_CRYPT=m
-CONFIG_DM_SNAPSHOT=m
-CONFIG_DM_MIRROR=m
-CONFIG_DM_ZERO=m
-CONFIG_DM_MULTIPATH=m
-CONFIG_FUSION=y
-CONFIG_FUSION_SPI=y
-CONFIG_FUSION_FC=m
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
-CONFIG_NETCONSOLE=y
-CONFIG_TIGON3=y
-CONFIG_NET_TULIP=y
-CONFIG_TULIP=m
-CONFIG_E100=m
-CONFIG_E1000=y
-# CONFIG_SERIO_SERPORT is not set
-CONFIG_GAMEPORT=m
-CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=6
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_EFI=y
-CONFIG_HPET=y
-CONFIG_AGP=m
-CONFIG_AGP_I460=m
-CONFIG_AGP_HP_ZX1=m
-CONFIG_DRM=m
-CONFIG_DRM_TDFX=m
-CONFIG_DRM_R128=m
-CONFIG_DRM_RADEON=m
-CONFIG_DRM_MGA=m
-CONFIG_DRM_SIS=m
-CONFIG_SOUND=m
-CONFIG_SND=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
-CONFIG_SND_VERBOSE_PRINTK=y
-CONFIG_SND_DUMMY=m
-CONFIG_SND_VIRMIDI=m
-CONFIG_SND_MTPAV=m
-CONFIG_SND_SERIAL_U16550=m
-CONFIG_SND_MPU401=m
-CONFIG_SND_CS4281=m
-CONFIG_SND_CS46XX=m
-CONFIG_SND_EMU10K1=m
-CONFIG_SND_FM801=m
-CONFIG_USB=m
-CONFIG_USB_MON=m
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_OHCI_HCD=m
-CONFIG_USB_UHCI_HCD=m
-CONFIG_USB_STORAGE=m
-CONFIG_INFINIBAND=m
-CONFIG_INFINIBAND_MTHCA=m
-CONFIG_INFINIBAND_IPOIB=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_REISERFS_FS=y
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
-CONFIG_XFS_FS=y
-CONFIG_AUTOFS_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_UDF_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_NTFS_FS=m
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_HUGETLBFS=y
-CONFIG_NFS_FS=m
-CONFIG_NFS_V4=m
-CONFIG_NFSD=m
-CONFIG_NFSD_V4=y
-CONFIG_CIFS=m
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_CRYPTO_MD5=y
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
deleted file mode 100644
index d7d8fb5c7b71..000000000000
--- a/arch/ia64/configs/tiger_defconfig
+++ /dev/null
@@ -1,169 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=20
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_SGI_PARTITION=y
-CONFIG_MCKINLEY=y
-CONFIG_IA64_PAGE_SIZE_64KB=y
-CONFIG_IA64_CYCLONE=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=16
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PERMIT_BSP_REMOVE=y
-CONFIG_FORCE_CPEI_RETARGET=y
-CONFIG_IA64_MCA_RECOVERY=y
-CONFIG_IA64_PALINFO=y
-CONFIG_KEXEC=y
-CONFIG_BINFMT_MISC=m
-CONFIG_ACPI_BUTTON=m
-CONFIG_ACPI_FAN=m
-CONFIG_ACPI_PROCESSOR=m
-CONFIG_HOTPLUG_PCI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_IPV6 is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_ATA=y
-CONFIG_ATA_GENERIC=y
-CONFIG_PATA_CMD64X=y
-CONFIG_ATA_PIIX=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_CHR_DEV_SG=m
-CONFIG_SCSI_FC_ATTRS=y
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_QLOGIC_1280=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_MULTIPATH=m
-CONFIG_BLK_DEV_DM=m
-CONFIG_DM_CRYPT=m
-CONFIG_DM_SNAPSHOT=m
-CONFIG_DM_MIRROR=m
-CONFIG_DM_ZERO=m
-CONFIG_FUSION=y
-CONFIG_FUSION_SPI=y
-CONFIG_FUSION_FC=y
-CONFIG_FUSION_CTL=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
-CONFIG_NETCONSOLE=y
-CONFIG_TIGON3=y
-CONFIG_NET_TULIP=y
-CONFIG_TULIP=m
-CONFIG_E100=m
-CONFIG_E1000=y
-# CONFIG_SERIO_SERPORT is not set
-CONFIG_GAMEPORT=m
-CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=6
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_EFI=y
-CONFIG_HPET=y
-CONFIG_AGP=m
-CONFIG_AGP_I460=m
-CONFIG_DRM=m
-CONFIG_DRM_TDFX=m
-CONFIG_DRM_R128=m
-CONFIG_DRM_RADEON=m
-CONFIG_DRM_MGA=m
-CONFIG_DRM_SIS=m
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_OHCI_HCD=m
-CONFIG_USB_UHCI_HCD=y
-CONFIG_USB_STORAGE=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_REISERFS_FS=y
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
-CONFIG_XFS_FS=y
-CONFIG_AUTOFS_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_UDF_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_NTFS_FS=m
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_HUGETLBFS=y
-CONFIG_NFS_FS=m
-CONFIG_NFS_V4=m
-CONFIG_NFSD=m
-CONFIG_NFSD_V4=y
-CONFIG_CIFS=m
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_IA64_GRANULE_16MB=y
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_MD5=y
diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
deleted file mode 100644
index ed104550d0d5..000000000000
--- a/arch/ia64/configs/zx1_defconfig
+++ /dev/null
@@ -1,148 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KPROBES=y
-CONFIG_MODULES=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MCKINLEY=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=16
-CONFIG_HOTPLUG_CPU=y
-CONFIG_FLATMEM_MANUAL=y
-CONFIG_IA64_MCA_RECOVERY=y
-CONFIG_IA64_PALINFO=y
-CONFIG_CRASH_DUMP=y
-CONFIG_BINFMT_MISC=y
-CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_ATA=y
-CONFIG_ATA_GENERIC=y
-CONFIG_PATA_CMD64X=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_FC_ATTRS=y
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_QLOGIC_1280=y
-CONFIG_FUSION=y
-CONFIG_FUSION_SPI=y
-CONFIG_FUSION_FC=y
-CONFIG_FUSION_CTL=m
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-CONFIG_TIGON3=y
-CONFIG_NET_TULIP=y
-CONFIG_TULIP=y
-CONFIG_TULIP_MWI=y
-CONFIG_TULIP_MMIO=y
-CONFIG_TULIP_NAPI=y
-CONFIG_TULIP_NAPI_HW_MITIGATION=y
-CONFIG_E100=y
-CONFIG_E1000=y
-CONFIG_INPUT_JOYDEV=y
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=8
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_EFI=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_AGP=y
-CONFIG_AGP_HP_ZX1=y
-CONFIG_DRM=y
-CONFIG_DRM_RADEON=y
-CONFIG_FB_RADEON=y
-CONFIG_FB_RADEON_DEBUG=y
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_SEQUENCER_OSS=y
-CONFIG_SND_FM801=y
-CONFIG_USB_HIDDEV=y
-CONFIG_USB=y
-CONFIG_USB_MON=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_UHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_UDF_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_HUGETLBFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
-CONFIG_NFSD=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=y
-CONFIG_NLS_CODEPAGE_775=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_CODEPAGE_852=y
-CONFIG_NLS_CODEPAGE_855=y
-CONFIG_NLS_CODEPAGE_857=y
-CONFIG_NLS_CODEPAGE_860=y
-CONFIG_NLS_CODEPAGE_861=y
-CONFIG_NLS_CODEPAGE_862=y
-CONFIG_NLS_CODEPAGE_863=y
-CONFIG_NLS_CODEPAGE_864=y
-CONFIG_NLS_CODEPAGE_865=y
-CONFIG_NLS_CODEPAGE_866=y
-CONFIG_NLS_CODEPAGE_869=y
-CONFIG_NLS_CODEPAGE_936=y
-CONFIG_NLS_CODEPAGE_950=y
-CONFIG_NLS_CODEPAGE_932=y
-CONFIG_NLS_CODEPAGE_949=y
-CONFIG_NLS_CODEPAGE_874=y
-CONFIG_NLS_ISO8859_8=y
-CONFIG_NLS_CODEPAGE_1251=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=y
-CONFIG_NLS_ISO8859_3=y
-CONFIG_NLS_ISO8859_4=y
-CONFIG_NLS_ISO8859_5=y
-CONFIG_NLS_ISO8859_6=y
-CONFIG_NLS_ISO8859_7=y
-CONFIG_NLS_ISO8859_9=y
-CONFIG_NLS_ISO8859_13=y
-CONFIG_NLS_ISO8859_14=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_KOI8_R=y
-CONFIG_NLS_KOI8_U=y
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_IA64_PRINT_HAZARDS=y
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_PCBC=m
diff --git a/arch/ia64/hp/common/Makefile b/arch/ia64/hp/common/Makefile
deleted file mode 100644
index 11a56ed38229..000000000000
--- a/arch/ia64/hp/common/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# ia64/platform/hp/common/Makefile
-#
-# Copyright (C) 2002 Hewlett Packard
-# Copyright (C) Alex Williamson (alex_williamson@hp.com)
-#
-
-obj-$(CONFIG_IA64_HP_SBA_IOMMU) += sba_iommu.o
-obj-$(CONFIG_IA64_HP_AML_NFW) += aml_nfw.o
diff --git a/arch/ia64/hp/common/aml_nfw.c b/arch/ia64/hp/common/aml_nfw.c
deleted file mode 100644
index 901df49461a0..000000000000
--- a/arch/ia64/hp/common/aml_nfw.c
+++ /dev/null
@@ -1,232 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * OpRegion handler to allow AML to call native firmware
- *
- * (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- *
- * This driver implements HP Open Source Review Board proposal 1842,
- * which was approved on 9/20/2006.
- *
- * For technical documentation, see the HP SPPA Firmware EAS, Appendix F.
- *
- * ACPI does not define a mechanism for AML methods to call native firmware
- * interfaces such as PAL or SAL. This OpRegion handler adds such a mechanism.
- * After the handler is installed, an AML method can call native firmware by
- * storing the arguments and firmware entry point to specific offsets in the
- * OpRegion. When AML reads the "return value" offset from the OpRegion, this
- * handler loads up the arguments, makes the firmware call, and returns the
- * result.
- */
-
-#include <linux/module.h>
-#include <linux/acpi.h>
-#include <asm/sal.h>
-
-MODULE_AUTHOR("Bjorn Helgaas <bjorn.helgaas@hp.com>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("ACPI opregion handler for native firmware calls");
-
-static bool force_register;
-module_param_named(force, force_register, bool, 0);
-MODULE_PARM_DESC(force, "Install opregion handler even without HPQ5001 device");
-
-#define AML_NFW_SPACE 0xA1
-
-struct ia64_pdesc {
- void *ip;
- void *gp;
-};
-
-/*
- * N.B. The layout of this structure is defined in the HP SPPA FW EAS, and
- * the member offsets are embedded in AML methods.
- */
-struct ia64_nfw_context {
- u64 arg[8];
- struct ia64_sal_retval ret;
- u64 ip;
- u64 gp;
- u64 pad[2];
-};
-
-static void *virt_map(u64 address)
-{
- if (address & (1UL << 63))
- return (void *) (__IA64_UNCACHED_OFFSET | address);
-
- return __va(address);
-}
-
-static void aml_nfw_execute(struct ia64_nfw_context *c)
-{
- struct ia64_pdesc virt_entry;
- ia64_sal_handler entry;
-
- virt_entry.ip = virt_map(c->ip);
- virt_entry.gp = virt_map(c->gp);
-
- entry = (ia64_sal_handler) &virt_entry;
-
- IA64_FW_CALL(entry, c->ret,
- c->arg[0], c->arg[1], c->arg[2], c->arg[3],
- c->arg[4], c->arg[5], c->arg[6], c->arg[7]);
-}
-
-static void aml_nfw_read_arg(u8 *offset, u32 bit_width, u64 *value)
-{
- switch (bit_width) {
- case 8:
- *value = *(u8 *)offset;
- break;
- case 16:
- *value = *(u16 *)offset;
- break;
- case 32:
- *value = *(u32 *)offset;
- break;
- case 64:
- *value = *(u64 *)offset;
- break;
- }
-}
-
-static void aml_nfw_write_arg(u8 *offset, u32 bit_width, u64 *value)
-{
- switch (bit_width) {
- case 8:
- *(u8 *) offset = *value;
- break;
- case 16:
- *(u16 *) offset = *value;
- break;
- case 32:
- *(u32 *) offset = *value;
- break;
- case 64:
- *(u64 *) offset = *value;
- break;
- }
-}
-
-static acpi_status aml_nfw_handler(u32 function, acpi_physical_address address,
- u32 bit_width, u64 *value, void *handler_context,
- void *region_context)
-{
- struct ia64_nfw_context *context = handler_context;
- u8 *offset = (u8 *) context + address;
-
- if (bit_width != 8 && bit_width != 16 &&
- bit_width != 32 && bit_width != 64)
- return AE_BAD_PARAMETER;
-
- if (address + (bit_width >> 3) > sizeof(struct ia64_nfw_context))
- return AE_BAD_PARAMETER;
-
- switch (function) {
- case ACPI_READ:
- if (address == offsetof(struct ia64_nfw_context, ret))
- aml_nfw_execute(context);
- aml_nfw_read_arg(offset, bit_width, value);
- break;
- case ACPI_WRITE:
- aml_nfw_write_arg(offset, bit_width, value);
- break;
- }
-
- return AE_OK;
-}
-
-static struct ia64_nfw_context global_context;
-static int global_handler_registered;
-
-static int aml_nfw_add_global_handler(void)
-{
- acpi_status status;
-
- if (global_handler_registered)
- return 0;
-
- status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
- AML_NFW_SPACE, aml_nfw_handler, NULL, &global_context);
- if (ACPI_FAILURE(status))
- return -ENODEV;
-
- global_handler_registered = 1;
- printk(KERN_INFO "Global 0x%02X opregion handler registered\n",
- AML_NFW_SPACE);
- return 0;
-}
-
-static int aml_nfw_remove_global_handler(void)
-{
- acpi_status status;
-
- if (!global_handler_registered)
- return 0;
-
- status = acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
- AML_NFW_SPACE, aml_nfw_handler);
- if (ACPI_FAILURE(status))
- return -ENODEV;
-
- global_handler_registered = 0;
- printk(KERN_INFO "Global 0x%02X opregion handler removed\n",
- AML_NFW_SPACE);
- return 0;
-}
-
-static int aml_nfw_add(struct acpi_device *device)
-{
- /*
- * We would normally allocate a new context structure and install
- * the address space handler for the specific device we found.
- * But the HP-UX implementation shares a single global context
- * and always puts the handler at the root, so we'll do the same.
- */
- return aml_nfw_add_global_handler();
-}
-
-static void aml_nfw_remove(struct acpi_device *device)
-{
- aml_nfw_remove_global_handler();
-}
-
-static const struct acpi_device_id aml_nfw_ids[] = {
- {"HPQ5001", 0},
- {"", 0}
-};
-
-static struct acpi_driver acpi_aml_nfw_driver = {
- .name = "native firmware",
- .ids = aml_nfw_ids,
- .ops = {
- .add = aml_nfw_add,
- .remove = aml_nfw_remove,
- },
-};
-
-static int __init aml_nfw_init(void)
-{
- int result;
-
- if (force_register)
- aml_nfw_add_global_handler();
-
- result = acpi_bus_register_driver(&acpi_aml_nfw_driver);
- if (result < 0) {
- aml_nfw_remove_global_handler();
- return result;
- }
-
- return 0;
-}
-
-static void __exit aml_nfw_exit(void)
-{
- acpi_bus_unregister_driver(&acpi_aml_nfw_driver);
- aml_nfw_remove_global_handler();
-}
-
-module_init(aml_nfw_init);
-module_exit(aml_nfw_exit);
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
deleted file mode 100644
index c4d477e8bcd4..000000000000
--- a/arch/ia64/hp/common/sba_iommu.c
+++ /dev/null
@@ -1,2155 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
-** IA64 System Bus Adapter (SBA) I/O MMU manager
-**
-** (c) Copyright 2002-2005 Alex Williamson
-** (c) Copyright 2002-2003 Grant Grundler
-** (c) Copyright 2002-2005 Hewlett-Packard Company
-**
-** Portions (c) 2000 Grant Grundler (from parisc I/O MMU code)
-** Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code)
-**
-**
-**
-** This module initializes the IOC (I/O Controller) found on HP
-** McKinley machines and their successors.
-**
-*/
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/acpi.h>
-#include <linux/efi.h>
-#include <linux/nodemask.h>
-#include <linux/bitops.h> /* hweight64() */
-#include <linux/crash_dump.h>
-#include <linux/iommu-helper.h>
-#include <linux/dma-map-ops.h>
-#include <linux/prefetch.h>
-#include <linux/swiotlb.h>
-
-#include <asm/delay.h> /* ia64_get_itc() */
-#include <asm/io.h>
-#include <asm/page.h> /* PAGE_OFFSET */
-#include <asm/dma.h>
-
-#include <asm/acpi-ext.h>
-
-#define PFX "IOC: "
-
-/*
-** Enabling timing search of the pdir resource map. Output in /proc.
-** Disabled by default to optimize performance.
-*/
-#undef PDIR_SEARCH_TIMING
-
-/*
-** This option allows cards capable of 64bit DMA to bypass the IOMMU. If
-** not defined, all DMA will be 32bit and go through the TLB.
-** There's potentially a conflict in the bio merge code with us
-** advertising an iommu, but then bypassing it. Since I/O MMU bypassing
-** appears to give more performance than bio-level virtual merging, we'll
-** do the former for now. NOTE: BYPASS_SG also needs to be undef'd to
-** completely restrict DMA to the IOMMU.
-*/
-#define ALLOW_IOV_BYPASS
-
-/*
-** This option specifically allows/disallows bypassing scatterlists with
-** multiple entries. Coalescing these entries can allow better DMA streaming
-** and in some cases shows better performance than entirely bypassing the
-** IOMMU. Performance increase on the order of 1-2% sequential output/input
-** using bonnie++ on a RAID0 MD device (sym2 & mpt).
-*/
-#undef ALLOW_IOV_BYPASS_SG
-
-/*
-** If a device prefetches beyond the end of a valid pdir entry, it will cause
-** a hard failure, ie. MCA. Version 3.0 and later of the zx1 LBA should
-** disconnect on 4k boundaries and prevent such issues. If the device is
-** particularly aggressive, this option will keep the entire pdir valid such
-** that prefetching will hit a valid address. This could severely impact
-** error containment, and is therefore off by default. The page that is
-** used for spill-over is poisoned, so that should help debugging somewhat.
-*/
-#undef FULL_VALID_PDIR
-
-#define ENABLE_MARK_CLEAN
-
-/*
-** The number of debug flags is a clue - this code is fragile. NOTE: since
-** tightening the use of res_lock the resource bitmap and actual pdir are no
-** longer guaranteed to stay in sync. The sanity checking code isn't going to
-** like that.
-*/
-#undef DEBUG_SBA_INIT
-#undef DEBUG_SBA_RUN
-#undef DEBUG_SBA_RUN_SG
-#undef DEBUG_SBA_RESOURCE
-#undef ASSERT_PDIR_SANITY
-#undef DEBUG_LARGE_SG_ENTRIES
-#undef DEBUG_BYPASS
-
-#if defined(FULL_VALID_PDIR) && defined(ASSERT_PDIR_SANITY)
-#error FULL_VALID_PDIR and ASSERT_PDIR_SANITY are mutually exclusive
-#endif
-
-#define SBA_INLINE __inline__
-/* #define SBA_INLINE */
-
-#ifdef DEBUG_SBA_INIT
-#define DBG_INIT(x...) printk(x)
-#else
-#define DBG_INIT(x...)
-#endif
-
-#ifdef DEBUG_SBA_RUN
-#define DBG_RUN(x...) printk(x)
-#else
-#define DBG_RUN(x...)
-#endif
-
-#ifdef DEBUG_SBA_RUN_SG
-#define DBG_RUN_SG(x...) printk(x)
-#else
-#define DBG_RUN_SG(x...)
-#endif
-
-
-#ifdef DEBUG_SBA_RESOURCE
-#define DBG_RES(x...) printk(x)
-#else
-#define DBG_RES(x...)
-#endif
-
-#ifdef DEBUG_BYPASS
-#define DBG_BYPASS(x...) printk(x)
-#else
-#define DBG_BYPASS(x...)
-#endif
-
-#ifdef ASSERT_PDIR_SANITY
-#define ASSERT(expr) \
- if(!(expr)) { \
- printk( "\n" __FILE__ ":%d: Assertion " #expr " failed!\n",__LINE__); \
- panic(#expr); \
- }
-#else
-#define ASSERT(expr)
-#endif
-
-/*
-** The number of pdir entries to "free" before issuing
-** a read to PCOM register to flush out PCOM writes.
-** Interacts with allocation granularity (ie 4 or 8 entries
-** allocated and free'd/purged at a time might make this
-** less interesting).
-*/
-#define DELAYED_RESOURCE_CNT 64
-
-#define PCI_DEVICE_ID_HP_SX2000_IOC 0x12ec
-
-#define ZX1_IOC_ID ((PCI_DEVICE_ID_HP_ZX1_IOC << 16) | PCI_VENDOR_ID_HP)
-#define ZX2_IOC_ID ((PCI_DEVICE_ID_HP_ZX2_IOC << 16) | PCI_VENDOR_ID_HP)
-#define REO_IOC_ID ((PCI_DEVICE_ID_HP_REO_IOC << 16) | PCI_VENDOR_ID_HP)
-#define SX1000_IOC_ID ((PCI_DEVICE_ID_HP_SX1000_IOC << 16) | PCI_VENDOR_ID_HP)
-#define SX2000_IOC_ID ((PCI_DEVICE_ID_HP_SX2000_IOC << 16) | PCI_VENDOR_ID_HP)
-
-#define ZX1_IOC_OFFSET 0x1000 /* ACPI reports SBA, we want IOC */
-
-#define IOC_FUNC_ID 0x000
-#define IOC_FCLASS 0x008 /* function class, bist, header, rev... */
-#define IOC_IBASE 0x300 /* IO TLB */
-#define IOC_IMASK 0x308
-#define IOC_PCOM 0x310
-#define IOC_TCNFG 0x318
-#define IOC_PDIR_BASE 0x320
-
-#define IOC_ROPE0_CFG 0x500
-#define IOC_ROPE_AO 0x10 /* Allow "Relaxed Ordering" */
-
-
-/* AGP GART driver looks for this */
-#define ZX1_SBA_IOMMU_COOKIE 0x0000badbadc0ffeeUL
-
-/*
-** The zx1 IOC supports 4/8/16/64KB page sizes (see TCNFG register)
-**
-** Some IOCs (sx1000) can run at the above pages sizes, but are
-** really only supported using the IOC at a 4k page size.
-**
-** iovp_size could only be greater than PAGE_SIZE if we are
-** confident the drivers really only touch the next physical
-** page iff that driver instance owns it.
-*/
-static unsigned long iovp_size;
-static unsigned long iovp_shift;
-static unsigned long iovp_mask;
-
-struct ioc {
- void __iomem *ioc_hpa; /* I/O MMU base address */
- char *res_map; /* resource map, bit == pdir entry */
- u64 *pdir_base; /* physical base address */
- unsigned long ibase; /* pdir IOV Space base */
- unsigned long imask; /* pdir IOV Space mask */
-
- unsigned long *res_hint; /* next avail IOVP - circular search */
- unsigned long dma_mask;
- spinlock_t res_lock; /* protects the resource bitmap, but must be held when */
- /* clearing pdir to prevent races with allocations. */
- unsigned int res_bitshift; /* from the RIGHT! */
- unsigned int res_size; /* size of resource map in bytes */
-#ifdef CONFIG_NUMA
- unsigned int node; /* node where this IOC lives */
-#endif
-#if DELAYED_RESOURCE_CNT > 0
- spinlock_t saved_lock; /* may want to try to get this on a separate cacheline */
- /* than res_lock for bigger systems. */
- int saved_cnt;
- struct sba_dma_pair {
- dma_addr_t iova;
- size_t size;
- } saved[DELAYED_RESOURCE_CNT];
-#endif
-
-#ifdef PDIR_SEARCH_TIMING
-#define SBA_SEARCH_SAMPLE 0x100
- unsigned long avg_search[SBA_SEARCH_SAMPLE];
- unsigned long avg_idx; /* current index into avg_search */
-#endif
-
- /* Stuff we don't need in performance path */
- struct ioc *next; /* list of IOC's in system */
- acpi_handle handle; /* for multiple IOC's */
- const char *name;
- unsigned int func_id;
- unsigned int rev; /* HW revision of chip */
- u32 iov_size;
- unsigned int pdir_size; /* in bytes, determined by IOV Space size */
- struct pci_dev *sac_only_dev;
-};
-
-static struct ioc *ioc_list, *ioc_found;
-static int reserve_sba_gart = 1;
-
-static SBA_INLINE void sba_mark_invalid(struct ioc *, dma_addr_t, size_t);
-static SBA_INLINE void sba_free_range(struct ioc *, dma_addr_t, size_t);
-
-#define sba_sg_address(sg) sg_virt((sg))
-
-#ifdef FULL_VALID_PDIR
-static u64 prefetch_spill_page;
-#endif
-
-#define GET_IOC(dev) ((dev_is_pci(dev)) \
- ? ((struct ioc *) PCI_CONTROLLER(to_pci_dev(dev))->iommu) : NULL)
-
-/*
-** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up
-** (or rather not merge) DMAs into manageable chunks.
-** On parisc, this is more of the software/tuning constraint
-** rather than the HW. I/O MMU allocation algorithms can be
-** faster with smaller sizes (to some degree).
-*/
-#define DMA_CHUNK_SIZE (BITS_PER_LONG*iovp_size)
-
-#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1))
-
-/************************************
-** SBA register read and write support
-**
-** BE WARNED: register writes are posted.
-** (ie follow writes which must reach HW with a read)
-**
-*/
-#define READ_REG(addr) __raw_readq(addr)
-#define WRITE_REG(val, addr) __raw_writeq(val, addr)
-
-#ifdef DEBUG_SBA_INIT
-
-/**
- * sba_dump_tlb - debugging only - print IOMMU operating parameters
- * @hpa: base address of the IOMMU
- *
- * Print the size/location of the IO MMU PDIR.
- */
-static void
-sba_dump_tlb(char *hpa)
-{
- DBG_INIT("IO TLB at 0x%p\n", (void *)hpa);
- DBG_INIT("IOC_IBASE : %016lx\n", READ_REG(hpa+IOC_IBASE));
- DBG_INIT("IOC_IMASK : %016lx\n", READ_REG(hpa+IOC_IMASK));
- DBG_INIT("IOC_TCNFG : %016lx\n", READ_REG(hpa+IOC_TCNFG));
- DBG_INIT("IOC_PDIR_BASE: %016lx\n", READ_REG(hpa+IOC_PDIR_BASE));
- DBG_INIT("\n");
-}
-#endif
-
-
-#ifdef ASSERT_PDIR_SANITY
-
-/**
- * sba_dump_pdir_entry - debugging only - print one IOMMU PDIR entry
- * @ioc: IO MMU structure which owns the pdir we are interested in.
- * @msg: text to print ont the output line.
- * @pide: pdir index.
- *
- * Print one entry of the IO MMU PDIR in human readable form.
- */
-static void
-sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide)
-{
- /* start printing from lowest pde in rval */
- u64 *ptr = &ioc->pdir_base[pide & ~(BITS_PER_LONG - 1)];
- unsigned long *rptr = (unsigned long *) &ioc->res_map[(pide >>3) & -sizeof(unsigned long)];
- uint rcnt;
-
- printk(KERN_DEBUG "SBA: %s rp %p bit %d rval 0x%lx\n",
- msg, rptr, pide & (BITS_PER_LONG - 1), *rptr);
-
- rcnt = 0;
- while (rcnt < BITS_PER_LONG) {
- printk(KERN_DEBUG "%s %2d %p %016Lx\n",
- (rcnt == (pide & (BITS_PER_LONG - 1)))
- ? " -->" : " ",
- rcnt, ptr, (unsigned long long) *ptr );
- rcnt++;
- ptr++;
- }
- printk(KERN_DEBUG "%s", msg);
-}
-
-
-/**
- * sba_check_pdir - debugging only - consistency checker
- * @ioc: IO MMU structure which owns the pdir we are interested in.
- * @msg: text to print ont the output line.
- *
- * Verify the resource map and pdir state is consistent
- */
-static int
-sba_check_pdir(struct ioc *ioc, char *msg)
-{
- u64 *rptr_end = (u64 *) &(ioc->res_map[ioc->res_size]);
- u64 *rptr = (u64 *) ioc->res_map; /* resource map ptr */
- u64 *pptr = ioc->pdir_base; /* pdir ptr */
- uint pide = 0;
-
- while (rptr < rptr_end) {
- u64 rval;
- int rcnt; /* number of bits we might check */
-
- rval = *rptr;
- rcnt = 64;
-
- while (rcnt) {
- /* Get last byte and highest bit from that */
- u32 pde = ((u32)((*pptr >> (63)) & 0x1));
- if ((rval & 0x1) ^ pde)
- {
- /*
- ** BUMMER! -- res_map != pdir --
- ** Dump rval and matching pdir entries
- */
- sba_dump_pdir_entry(ioc, msg, pide);
- return(1);
- }
- rcnt--;
- rval >>= 1; /* try the next bit */
- pptr++;
- pide++;
- }
- rptr++; /* look at next word of res_map */
- }
- /* It'd be nice if we always got here :^) */
- return 0;
-}
-
-
-/**
- * sba_dump_sg - debugging only - print Scatter-Gather list
- * @ioc: IO MMU structure which owns the pdir we are interested in.
- * @startsg: head of the SG list
- * @nents: number of entries in SG list
- *
- * print the SG list so we can verify it's correct by hand.
- */
-static void
-sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
-{
- while (nents-- > 0) {
- printk(KERN_DEBUG " %d : DMA %08lx/%05x CPU %p\n", nents,
- startsg->dma_address, startsg->dma_length,
- sba_sg_address(startsg));
- startsg = sg_next(startsg);
- }
-}
-
-static void
-sba_check_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
-{
- struct scatterlist *the_sg = startsg;
- int the_nents = nents;
-
- while (the_nents-- > 0) {
- if (sba_sg_address(the_sg) == 0x0UL)
- sba_dump_sg(NULL, startsg, nents);
- the_sg = sg_next(the_sg);
- }
-}
-
-#endif /* ASSERT_PDIR_SANITY */
-
-
-
-
-/**************************************************************
-*
-* I/O Pdir Resource Management
-*
-* Bits set in the resource map are in use.
-* Each bit can represent a number of pages.
-* LSbs represent lower addresses (IOVA's).
-*
-***************************************************************/
-#define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */
-
-/* Convert from IOVP to IOVA and vice versa. */
-#define SBA_IOVA(ioc,iovp,offset) ((ioc->ibase) | (iovp) | (offset))
-#define SBA_IOVP(ioc,iova) ((iova) & ~(ioc->ibase))
-
-#define PDIR_ENTRY_SIZE sizeof(u64)
-
-#define PDIR_INDEX(iovp) ((iovp)>>iovp_shift)
-
-#define RESMAP_MASK(n) ~(~0UL << (n))
-#define RESMAP_IDX_MASK (sizeof(unsigned long) - 1)
-
-
-/**
- * For most cases the normal get_order is sufficient, however it limits us
- * to PAGE_SIZE being the minimum mapping alignment and TC flush granularity.
- * It only incurs about 1 clock cycle to use this one with the static variable
- * and makes the code more intuitive.
- */
-static SBA_INLINE int
-get_iovp_order (unsigned long size)
-{
- long double d = size - 1;
- long order;
-
- order = ia64_getf_exp(d);
- order = order - iovp_shift - 0xffff + 1;
- if (order < 0)
- order = 0;
- return order;
-}
-
-static unsigned long ptr_to_pide(struct ioc *ioc, unsigned long *res_ptr,
- unsigned int bitshiftcnt)
-{
- return (((unsigned long)res_ptr - (unsigned long)ioc->res_map) << 3)
- + bitshiftcnt;
-}
-
-/**
- * sba_search_bitmap - find free space in IO PDIR resource bitmap
- * @ioc: IO MMU structure which owns the pdir we are interested in.
- * @bits_wanted: number of entries we need.
- * @use_hint: use res_hint to indicate where to start looking
- *
- * Find consecutive free bits in resource bitmap.
- * Each bit represents one entry in the IO Pdir.
- * Cool perf optimization: search for log2(size) bits at a time.
- */
-static SBA_INLINE unsigned long
-sba_search_bitmap(struct ioc *ioc, struct device *dev,
- unsigned long bits_wanted, int use_hint)
-{
- unsigned long *res_ptr;
- unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
- unsigned long flags, pide = ~0UL, tpide;
- unsigned long boundary_size;
- unsigned long shift;
- int ret;
-
- ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0);
- ASSERT(res_ptr < res_end);
-
- boundary_size = dma_get_seg_boundary_nr_pages(dev, iovp_shift);
-
- BUG_ON(ioc->ibase & ~iovp_mask);
- shift = ioc->ibase >> iovp_shift;
-
- spin_lock_irqsave(&ioc->res_lock, flags);
-
- /* Allow caller to force a search through the entire resource space */
- if (likely(use_hint)) {
- res_ptr = ioc->res_hint;
- } else {
- res_ptr = (ulong *)ioc->res_map;
- ioc->res_bitshift = 0;
- }
-
- /*
- * N.B. REO/Grande defect AR2305 can cause TLB fetch timeouts
- * if a TLB entry is purged while in use. sba_mark_invalid()
- * purges IOTLB entries in power-of-two sizes, so we also
- * allocate IOVA space in power-of-two sizes.
- */
- bits_wanted = 1UL << get_iovp_order(bits_wanted << iovp_shift);
-
- if (likely(bits_wanted == 1)) {
- unsigned int bitshiftcnt;
- for(; res_ptr < res_end ; res_ptr++) {
- if (likely(*res_ptr != ~0UL)) {
- bitshiftcnt = ffz(*res_ptr);
- *res_ptr |= (1UL << bitshiftcnt);
- pide = ptr_to_pide(ioc, res_ptr, bitshiftcnt);
- ioc->res_bitshift = bitshiftcnt + bits_wanted;
- goto found_it;
- }
- }
- goto not_found;
-
- }
-
- if (likely(bits_wanted <= BITS_PER_LONG/2)) {
- /*
- ** Search the resource bit map on well-aligned values.
- ** "o" is the alignment.
- ** We need the alignment to invalidate I/O TLB using
- ** SBA HW features in the unmap path.
- */
- unsigned long o = 1 << get_iovp_order(bits_wanted << iovp_shift);
- uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o);
- unsigned long mask, base_mask;
-
- base_mask = RESMAP_MASK(bits_wanted);
- mask = base_mask << bitshiftcnt;
-
- DBG_RES("%s() o %ld %p", __func__, o, res_ptr);
- for(; res_ptr < res_end ; res_ptr++)
- {
- DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr);
- ASSERT(0 != mask);
- for (; mask ; mask <<= o, bitshiftcnt += o) {
- tpide = ptr_to_pide(ioc, res_ptr, bitshiftcnt);
- ret = iommu_is_span_boundary(tpide, bits_wanted,
- shift,
- boundary_size);
- if ((0 == ((*res_ptr) & mask)) && !ret) {
- *res_ptr |= mask; /* mark resources busy! */
- pide = tpide;
- ioc->res_bitshift = bitshiftcnt + bits_wanted;
- goto found_it;
- }
- }
-
- bitshiftcnt = 0;
- mask = base_mask;
-
- }
-
- } else {
- int qwords, bits, i;
- unsigned long *end;
-
- qwords = bits_wanted >> 6; /* /64 */
- bits = bits_wanted - (qwords * BITS_PER_LONG);
-
- end = res_end - qwords;
-
- for (; res_ptr < end; res_ptr++) {
- tpide = ptr_to_pide(ioc, res_ptr, 0);
- ret = iommu_is_span_boundary(tpide, bits_wanted,
- shift, boundary_size);
- if (ret)
- goto next_ptr;
- for (i = 0 ; i < qwords ; i++) {
- if (res_ptr[i] != 0)
- goto next_ptr;
- }
- if (bits && res_ptr[i] && (__ffs(res_ptr[i]) < bits))
- continue;
-
- /* Found it, mark it */
- for (i = 0 ; i < qwords ; i++)
- res_ptr[i] = ~0UL;
- res_ptr[i] |= RESMAP_MASK(bits);
-
- pide = tpide;
- res_ptr += qwords;
- ioc->res_bitshift = bits;
- goto found_it;
-next_ptr:
- ;
- }
- }
-
-not_found:
- prefetch(ioc->res_map);
- ioc->res_hint = (unsigned long *) ioc->res_map;
- ioc->res_bitshift = 0;
- spin_unlock_irqrestore(&ioc->res_lock, flags);
- return (pide);
-
-found_it:
- ioc->res_hint = res_ptr;
- spin_unlock_irqrestore(&ioc->res_lock, flags);
- return (pide);
-}
-
-
-/**
- * sba_alloc_range - find free bits and mark them in IO PDIR resource bitmap
- * @ioc: IO MMU structure which owns the pdir we are interested in.
- * @size: number of bytes to create a mapping for
- *
- * Given a size, find consecutive unmarked and then mark those bits in the
- * resource bit map.
- */
-static int
-sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
-{
- unsigned int pages_needed = size >> iovp_shift;
-#ifdef PDIR_SEARCH_TIMING
- unsigned long itc_start;
-#endif
- unsigned long pide;
-
- ASSERT(pages_needed);
- ASSERT(0 == (size & ~iovp_mask));
-
-#ifdef PDIR_SEARCH_TIMING
- itc_start = ia64_get_itc();
-#endif
- /*
- ** "seek and ye shall find"...praying never hurts either...
- */
- pide = sba_search_bitmap(ioc, dev, pages_needed, 1);
- if (unlikely(pide >= (ioc->res_size << 3))) {
- pide = sba_search_bitmap(ioc, dev, pages_needed, 0);
- if (unlikely(pide >= (ioc->res_size << 3))) {
-#if DELAYED_RESOURCE_CNT > 0
- unsigned long flags;
-
- /*
- ** With delayed resource freeing, we can give this one more shot. We're
- ** getting close to being in trouble here, so do what we can to make this
- ** one count.
- */
- spin_lock_irqsave(&ioc->saved_lock, flags);
- if (ioc->saved_cnt > 0) {
- struct sba_dma_pair *d;
- int cnt = ioc->saved_cnt;
-
- d = &(ioc->saved[ioc->saved_cnt - 1]);
-
- spin_lock(&ioc->res_lock);
- while (cnt--) {
- sba_mark_invalid(ioc, d->iova, d->size);
- sba_free_range(ioc, d->iova, d->size);
- d--;
- }
- ioc->saved_cnt = 0;
- READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */
- spin_unlock(&ioc->res_lock);
- }
- spin_unlock_irqrestore(&ioc->saved_lock, flags);
-
- pide = sba_search_bitmap(ioc, dev, pages_needed, 0);
- if (unlikely(pide >= (ioc->res_size << 3))) {
- printk(KERN_WARNING "%s: I/O MMU @ %p is"
- "out of mapping resources, %u %u %lx\n",
- __func__, ioc->ioc_hpa, ioc->res_size,
- pages_needed, dma_get_seg_boundary(dev));
- return -1;
- }
-#else
- printk(KERN_WARNING "%s: I/O MMU @ %p is"
- "out of mapping resources, %u %u %lx\n",
- __func__, ioc->ioc_hpa, ioc->res_size,
- pages_needed, dma_get_seg_boundary(dev));
- return -1;
-#endif
- }
- }
-
-#ifdef PDIR_SEARCH_TIMING
- ioc->avg_search[ioc->avg_idx++] = (ia64_get_itc() - itc_start) / pages_needed;
- ioc->avg_idx &= SBA_SEARCH_SAMPLE - 1;
-#endif
-
- prefetchw(&(ioc->pdir_base[pide]));
-
-#ifdef ASSERT_PDIR_SANITY
- /* verify the first enable bit is clear */
- if(0x00 != ((u8 *) ioc->pdir_base)[pide*PDIR_ENTRY_SIZE + 7]) {
- sba_dump_pdir_entry(ioc, "sba_search_bitmap() botched it?", pide);
- }
-#endif
-
- DBG_RES("%s(%x) %d -> %lx hint %x/%x\n",
- __func__, size, pages_needed, pide,
- (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map),
- ioc->res_bitshift );
-
- return (pide);
-}
-
-
-/**
- * sba_free_range - unmark bits in IO PDIR resource bitmap
- * @ioc: IO MMU structure which owns the pdir we are interested in.
- * @iova: IO virtual address which was previously allocated.
- * @size: number of bytes to create a mapping for
- *
- * clear bits in the ioc's resource map
- */
-static SBA_INLINE void
-sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size)
-{
- unsigned long iovp = SBA_IOVP(ioc, iova);
- unsigned int pide = PDIR_INDEX(iovp);
- unsigned int ridx = pide >> 3; /* convert bit to byte address */
- unsigned long *res_ptr = (unsigned long *) &((ioc)->res_map[ridx & ~RESMAP_IDX_MASK]);
- int bits_not_wanted = size >> iovp_shift;
- unsigned long m;
-
- /* Round up to power-of-two size: see AR2305 note above */
- bits_not_wanted = 1UL << get_iovp_order(bits_not_wanted << iovp_shift);
- for (; bits_not_wanted > 0 ; res_ptr++) {
-
- if (unlikely(bits_not_wanted > BITS_PER_LONG)) {
-
- /* these mappings start 64bit aligned */
- *res_ptr = 0UL;
- bits_not_wanted -= BITS_PER_LONG;
- pide += BITS_PER_LONG;
-
- } else {
-
- /* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */
- m = RESMAP_MASK(bits_not_wanted) << (pide & (BITS_PER_LONG - 1));
- bits_not_wanted = 0;
-
- DBG_RES("%s( ,%x,%x) %x/%lx %x %p %lx\n", __func__, (uint) iova, size,
- bits_not_wanted, m, pide, res_ptr, *res_ptr);
-
- ASSERT(m != 0);
- ASSERT(bits_not_wanted);
- ASSERT((*res_ptr & m) == m); /* verify same bits are set */
- *res_ptr &= ~m;
- }
- }
-}
-
-
-/**************************************************************
-*
-* "Dynamic DMA Mapping" support (aka "Coherent I/O")
-*
-***************************************************************/
-
-/**
- * sba_io_pdir_entry - fill in one IO PDIR entry
- * @pdir_ptr: pointer to IO PDIR entry
- * @vba: Virtual CPU address of buffer to map
- *
- * SBA Mapping Routine
- *
- * Given a virtual address (vba, arg1) sba_io_pdir_entry()
- * loads the I/O PDIR entry pointed to by pdir_ptr (arg0).
- * Each IO Pdir entry consists of 8 bytes as shown below
- * (LSB == bit 0):
- *
- * 63 40 11 7 0
- * +-+---------------------+----------------------------------+----+--------+
- * |V| U | PPN[39:12] | U | FF |
- * +-+---------------------+----------------------------------+----+--------+
- *
- * V == Valid Bit
- * U == Unused
- * PPN == Physical Page Number
- *
- * The physical address fields are filled with the results of virt_to_phys()
- * on the vba.
- */
-
-#if 1
-#define sba_io_pdir_entry(pdir_ptr, vba) *pdir_ptr = ((vba & ~0xE000000000000FFFULL) \
- | 0x8000000000000000ULL)
-#else
-void SBA_INLINE
-sba_io_pdir_entry(u64 *pdir_ptr, unsigned long vba)
-{
- *pdir_ptr = ((vba & ~0xE000000000000FFFULL) | 0x80000000000000FFULL);
-}
-#endif
-
-#ifdef ENABLE_MARK_CLEAN
-/*
- * Since DMA is i-cache coherent, any (complete) pages that were written via
- * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to
- * flush them when they get mapped into an executable vm-area.
- */
-static void mark_clean(void *addr, size_t size)
-{
- struct folio *folio = virt_to_folio(addr);
- ssize_t left = size;
- size_t offset = offset_in_folio(folio, addr);
-
- if (offset) {
- left -= folio_size(folio) - offset;
- if (left <= 0)
- return;
- folio = folio_next(folio);
- }
-
- while (left >= folio_size(folio)) {
- left -= folio_size(folio);
- set_bit(PG_arch_1, &folio->flags);
- if (!left)
- break;
- folio = folio_next(folio);
- }
-}
-#endif
-
-/**
- * sba_mark_invalid - invalidate one or more IO PDIR entries
- * @ioc: IO MMU structure which owns the pdir we are interested in.
- * @iova: IO Virtual Address mapped earlier
- * @byte_cnt: number of bytes this mapping covers.
- *
- * Marking the IO PDIR entry(ies) as Invalid and invalidate
- * corresponding IO TLB entry. The PCOM (Purge Command Register)
- * is to purge stale entries in the IO TLB when unmapping entries.
- *
- * The PCOM register supports purging of multiple pages, with a minium
- * of 1 page and a maximum of 2GB. Hardware requires the address be
- * aligned to the size of the range being purged. The size of the range
- * must be a power of 2. The "Cool perf optimization" in the
- * allocation routine helps keep that true.
- */
-static SBA_INLINE void
-sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
-{
- u32 iovp = (u32) SBA_IOVP(ioc,iova);
-
- int off = PDIR_INDEX(iovp);
-
- /* Must be non-zero and rounded up */
- ASSERT(byte_cnt > 0);
- ASSERT(0 == (byte_cnt & ~iovp_mask));
-
-#ifdef ASSERT_PDIR_SANITY
- /* Assert first pdir entry is set */
- if (!(ioc->pdir_base[off] >> 60)) {
- sba_dump_pdir_entry(ioc,"sba_mark_invalid()", PDIR_INDEX(iovp));
- }
-#endif
-
- if (byte_cnt <= iovp_size)
- {
- ASSERT(off < ioc->pdir_size);
-
- iovp |= iovp_shift; /* set "size" field for PCOM */
-
-#ifndef FULL_VALID_PDIR
- /*
- ** clear I/O PDIR entry "valid" bit
- ** Do NOT clear the rest - save it for debugging.
- ** We should only clear bits that have previously
- ** been enabled.
- */
- ioc->pdir_base[off] &= ~(0x80000000000000FFULL);
-#else
- /*
- ** If we want to maintain the PDIR as valid, put in
- ** the spill page so devices prefetching won't
- ** cause a hard fail.
- */
- ioc->pdir_base[off] = (0x80000000000000FFULL | prefetch_spill_page);
-#endif
- } else {
- u32 t = get_iovp_order(byte_cnt) + iovp_shift;
-
- iovp |= t;
- ASSERT(t <= 31); /* 2GB! Max value of "size" field */
-
- do {
- /* verify this pdir entry is enabled */
- ASSERT(ioc->pdir_base[off] >> 63);
-#ifndef FULL_VALID_PDIR
- /* clear I/O Pdir entry "valid" bit first */
- ioc->pdir_base[off] &= ~(0x80000000000000FFULL);
-#else
- ioc->pdir_base[off] = (0x80000000000000FFULL | prefetch_spill_page);
-#endif
- off++;
- byte_cnt -= iovp_size;
- } while (byte_cnt > 0);
- }
-
- WRITE_REG(iovp | ioc->ibase, ioc->ioc_hpa+IOC_PCOM);
-}
-
-/**
- * sba_map_page - map one buffer and return IOVA for DMA
- * @dev: instance of PCI owned by the driver that's asking.
- * @page: page to map
- * @poff: offset into page
- * @size: number of bytes to map
- * @dir: dma direction
- * @attrs: optional dma attributes
- *
- * See Documentation/core-api/dma-api-howto.rst
- */
-static dma_addr_t sba_map_page(struct device *dev, struct page *page,
- unsigned long poff, size_t size,
- enum dma_data_direction dir,
- unsigned long attrs)
-{
- struct ioc *ioc;
- void *addr = page_address(page) + poff;
- dma_addr_t iovp;
- dma_addr_t offset;
- u64 *pdir_start;
- int pide;
-#ifdef ASSERT_PDIR_SANITY
- unsigned long flags;
-#endif
-#ifdef ALLOW_IOV_BYPASS
- unsigned long pci_addr = virt_to_phys(addr);
-#endif
-
-#ifdef ALLOW_IOV_BYPASS
- ASSERT(to_pci_dev(dev)->dma_mask);
- /*
- ** Check if the PCI device can DMA to ptr... if so, just return ptr
- */
- if (likely((pci_addr & ~to_pci_dev(dev)->dma_mask) == 0)) {
- /*
- ** Device is bit capable of DMA'ing to the buffer...
- ** just return the PCI address of ptr
- */
- DBG_BYPASS("sba_map_page() bypass mask/addr: "
- "0x%lx/0x%lx\n",
- to_pci_dev(dev)->dma_mask, pci_addr);
- return pci_addr;
- }
-#endif
- ioc = GET_IOC(dev);
- ASSERT(ioc);
-
- prefetch(ioc->res_hint);
-
- ASSERT(size > 0);
- ASSERT(size <= DMA_CHUNK_SIZE);
-
- /* save offset bits */
- offset = ((dma_addr_t) (long) addr) & ~iovp_mask;
-
- /* round up to nearest iovp_size */
- size = (size + offset + ~iovp_mask) & iovp_mask;
-
-#ifdef ASSERT_PDIR_SANITY
- spin_lock_irqsave(&ioc->res_lock, flags);
- if (sba_check_pdir(ioc,"Check before sba_map_page()"))
- panic("Sanity check failed");
- spin_unlock_irqrestore(&ioc->res_lock, flags);
-#endif
-
- pide = sba_alloc_range(ioc, dev, size);
- if (pide < 0)
- return DMA_MAPPING_ERROR;
-
- iovp = (dma_addr_t) pide << iovp_shift;
-
- DBG_RUN("%s() 0x%p -> 0x%lx\n", __func__, addr, (long) iovp | offset);
-
- pdir_start = &(ioc->pdir_base[pide]);
-
- while (size > 0) {
- ASSERT(((u8 *)pdir_start)[7] == 0); /* verify availability */
- sba_io_pdir_entry(pdir_start, (unsigned long) addr);
-
- DBG_RUN(" pdir 0x%p %lx\n", pdir_start, *pdir_start);
-
- addr += iovp_size;
- size -= iovp_size;
- pdir_start++;
- }
- /* force pdir update */
- wmb();
-
- /* form complete address */
-#ifdef ASSERT_PDIR_SANITY
- spin_lock_irqsave(&ioc->res_lock, flags);
- sba_check_pdir(ioc,"Check after sba_map_page()");
- spin_unlock_irqrestore(&ioc->res_lock, flags);
-#endif
- return SBA_IOVA(ioc, iovp, offset);
-}
-
-#ifdef ENABLE_MARK_CLEAN
-static SBA_INLINE void
-sba_mark_clean(struct ioc *ioc, dma_addr_t iova, size_t size)
-{
- u32 iovp = (u32) SBA_IOVP(ioc,iova);
- int off = PDIR_INDEX(iovp);
- void *addr;
-
- if (size <= iovp_size) {
- addr = phys_to_virt(ioc->pdir_base[off] &
- ~0xE000000000000FFFULL);
- mark_clean(addr, size);
- } else {
- do {
- addr = phys_to_virt(ioc->pdir_base[off] &
- ~0xE000000000000FFFULL);
- mark_clean(addr, min(size, iovp_size));
- off++;
- size -= iovp_size;
- } while (size > 0);
- }
-}
-#endif
-
-/**
- * sba_unmap_page - unmap one IOVA and free resources
- * @dev: instance of PCI owned by the driver that's asking.
- * @iova: IOVA of driver buffer previously mapped.
- * @size: number of bytes mapped in driver buffer.
- * @dir: R/W or both.
- * @attrs: optional dma attributes
- *
- * See Documentation/core-api/dma-api-howto.rst
- */
-static void sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
- enum dma_data_direction dir, unsigned long attrs)
-{
- struct ioc *ioc;
-#if DELAYED_RESOURCE_CNT > 0
- struct sba_dma_pair *d;
-#endif
- unsigned long flags;
- dma_addr_t offset;
-
- ioc = GET_IOC(dev);
- ASSERT(ioc);
-
-#ifdef ALLOW_IOV_BYPASS
- if (likely((iova & ioc->imask) != ioc->ibase)) {
- /*
- ** Address does not fall w/in IOVA, must be bypassing
- */
- DBG_BYPASS("sba_unmap_page() bypass addr: 0x%lx\n",
- iova);
-
-#ifdef ENABLE_MARK_CLEAN
- if (dir == DMA_FROM_DEVICE) {
- mark_clean(phys_to_virt(iova), size);
- }
-#endif
- return;
- }
-#endif
- offset = iova & ~iovp_mask;
-
- DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long) iova, size);
-
- iova ^= offset; /* clear offset bits */
- size += offset;
- size = ROUNDUP(size, iovp_size);
-
-#ifdef ENABLE_MARK_CLEAN
- if (dir == DMA_FROM_DEVICE)
- sba_mark_clean(ioc, iova, size);
-#endif
-
-#if DELAYED_RESOURCE_CNT > 0
- spin_lock_irqsave(&ioc->saved_lock, flags);
- d = &(ioc->saved[ioc->saved_cnt]);
- d->iova = iova;
- d->size = size;
- if (unlikely(++(ioc->saved_cnt) >= DELAYED_RESOURCE_CNT)) {
- int cnt = ioc->saved_cnt;
- spin_lock(&ioc->res_lock);
- while (cnt--) {
- sba_mark_invalid(ioc, d->iova, d->size);
- sba_free_range(ioc, d->iova, d->size);
- d--;
- }
- ioc->saved_cnt = 0;
- READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */
- spin_unlock(&ioc->res_lock);
- }
- spin_unlock_irqrestore(&ioc->saved_lock, flags);
-#else /* DELAYED_RESOURCE_CNT == 0 */
- spin_lock_irqsave(&ioc->res_lock, flags);
- sba_mark_invalid(ioc, iova, size);
- sba_free_range(ioc, iova, size);
- READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */
- spin_unlock_irqrestore(&ioc->res_lock, flags);
-#endif /* DELAYED_RESOURCE_CNT == 0 */
-}
-
-/**
- * sba_alloc_coherent - allocate/map shared mem for DMA
- * @dev: instance of PCI owned by the driver that's asking.
- * @size: number of bytes mapped in driver buffer.
- * @dma_handle: IOVA of new buffer.
- *
- * See Documentation/core-api/dma-api-howto.rst
- */
-static void *
-sba_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
- gfp_t flags, unsigned long attrs)
-{
- struct page *page;
- struct ioc *ioc;
- int node = -1;
- void *addr;
-
- ioc = GET_IOC(dev);
- ASSERT(ioc);
-#ifdef CONFIG_NUMA
- node = ioc->node;
-#endif
-
- page = alloc_pages_node(node, flags, get_order(size));
- if (unlikely(!page))
- return NULL;
-
- addr = page_address(page);
- memset(addr, 0, size);
- *dma_handle = page_to_phys(page);
-
-#ifdef ALLOW_IOV_BYPASS
- ASSERT(dev->coherent_dma_mask);
- /*
- ** Check if the PCI device can DMA to ptr... if so, just return ptr
- */
- if (likely((*dma_handle & ~dev->coherent_dma_mask) == 0)) {
- DBG_BYPASS("sba_alloc_coherent() bypass mask/addr: 0x%lx/0x%lx\n",
- dev->coherent_dma_mask, *dma_handle);
-
- return addr;
- }
-#endif
-
- /*
- * If device can't bypass or bypass is disabled, pass the 32bit fake
- * device to map single to get an iova mapping.
- */
- *dma_handle = sba_map_page(&ioc->sac_only_dev->dev, page, 0, size,
- DMA_BIDIRECTIONAL, 0);
- if (dma_mapping_error(dev, *dma_handle))
- return NULL;
- return addr;
-}
-
-
-/**
- * sba_free_coherent - free/unmap shared mem for DMA
- * @dev: instance of PCI owned by the driver that's asking.
- * @size: number of bytes mapped in driver buffer.
- * @vaddr: virtual address IOVA of "consistent" buffer.
- * @dma_handler: IO virtual address of "consistent" buffer.
- *
- * See Documentation/core-api/dma-api-howto.rst
- */
-static void sba_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, unsigned long attrs)
-{
- sba_unmap_page(dev, dma_handle, size, 0, 0);
- free_pages((unsigned long) vaddr, get_order(size));
-}
-
-
-/*
-** Since 0 is a valid pdir_base index value, can't use that
-** to determine if a value is valid or not. Use a flag to indicate
-** the SG list entry contains a valid pdir index.
-*/
-#define PIDE_FLAG 0x1UL
-
-#ifdef DEBUG_LARGE_SG_ENTRIES
-int dump_run_sg = 0;
-#endif
-
-
-/**
- * sba_fill_pdir - write allocated SG entries into IO PDIR
- * @ioc: IO MMU structure which owns the pdir we are interested in.
- * @startsg: list of IOVA/size pairs
- * @nents: number of entries in startsg list
- *
- * Take preprocessed SG list and write corresponding entries
- * in the IO PDIR.
- */
-
-static SBA_INLINE int
-sba_fill_pdir(
- struct ioc *ioc,
- struct scatterlist *startsg,
- int nents)
-{
- struct scatterlist *dma_sg = startsg; /* pointer to current DMA */
- int n_mappings = 0;
- u64 *pdirp = NULL;
- unsigned long dma_offset = 0;
-
- while (nents-- > 0) {
- int cnt = startsg->dma_length;
- startsg->dma_length = 0;
-
-#ifdef DEBUG_LARGE_SG_ENTRIES
- if (dump_run_sg)
- printk(" %2d : %08lx/%05x %p\n",
- nents, startsg->dma_address, cnt,
- sba_sg_address(startsg));
-#else
- DBG_RUN_SG(" %d : %08lx/%05x %p\n",
- nents, startsg->dma_address, cnt,
- sba_sg_address(startsg));
-#endif
- /*
- ** Look for the start of a new DMA stream
- */
- if (startsg->dma_address & PIDE_FLAG) {
- u32 pide = startsg->dma_address & ~PIDE_FLAG;
- dma_offset = (unsigned long) pide & ~iovp_mask;
- startsg->dma_address = 0;
- if (n_mappings)
- dma_sg = sg_next(dma_sg);
- dma_sg->dma_address = pide | ioc->ibase;
- pdirp = &(ioc->pdir_base[pide >> iovp_shift]);
- n_mappings++;
- }
-
- /*
- ** Look for a VCONTIG chunk
- */
- if (cnt) {
- unsigned long vaddr = (unsigned long) sba_sg_address(startsg);
- ASSERT(pdirp);
-
- /* Since multiple Vcontig blocks could make up
- ** one DMA stream, *add* cnt to dma_len.
- */
- dma_sg->dma_length += cnt;
- cnt += dma_offset;
- dma_offset=0; /* only want offset on first chunk */
- cnt = ROUNDUP(cnt, iovp_size);
- do {
- sba_io_pdir_entry(pdirp, vaddr);
- vaddr += iovp_size;
- cnt -= iovp_size;
- pdirp++;
- } while (cnt > 0);
- }
- startsg = sg_next(startsg);
- }
- /* force pdir update */
- wmb();
-
-#ifdef DEBUG_LARGE_SG_ENTRIES
- dump_run_sg = 0;
-#endif
- return(n_mappings);
-}
-
-
-/*
-** Two address ranges are DMA contiguous *iff* "end of prev" and
-** "start of next" are both on an IOV page boundary.
-**
-** (shift left is a quick trick to mask off upper bits)
-*/
-#define DMA_CONTIG(__X, __Y) \
- (((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - iovp_shift)) == 0UL)
-
-
-/**
- * sba_coalesce_chunks - preprocess the SG list
- * @ioc: IO MMU structure which owns the pdir we are interested in.
- * @startsg: list of IOVA/size pairs
- * @nents: number of entries in startsg list
- *
- * First pass is to walk the SG list and determine where the breaks are
- * in the DMA stream. Allocates PDIR entries but does not fill them.
- * Returns the number of DMA chunks.
- *
- * Doing the fill separate from the coalescing/allocation keeps the
- * code simpler. Future enhancement could make one pass through
- * the sglist do both.
- */
-static SBA_INLINE int
-sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
- struct scatterlist *startsg,
- int nents)
-{
- struct scatterlist *vcontig_sg; /* VCONTIG chunk head */
- unsigned long vcontig_len; /* len of VCONTIG chunk */
- unsigned long vcontig_end;
- struct scatterlist *dma_sg; /* next DMA stream head */
- unsigned long dma_offset, dma_len; /* start/len of DMA stream */
- int n_mappings = 0;
- unsigned int max_seg_size = dma_get_max_seg_size(dev);
- int idx;
-
- while (nents > 0) {
- unsigned long vaddr = (unsigned long) sba_sg_address(startsg);
-
- /*
- ** Prepare for first/next DMA stream
- */
- dma_sg = vcontig_sg = startsg;
- dma_len = vcontig_len = vcontig_end = startsg->length;
- vcontig_end += vaddr;
- dma_offset = vaddr & ~iovp_mask;
-
- /* PARANOID: clear entries */
- startsg->dma_address = startsg->dma_length = 0;
-
- /*
- ** This loop terminates one iteration "early" since
- ** it's always looking one "ahead".
- */
- while (--nents > 0) {
- unsigned long vaddr; /* tmp */
-
- startsg = sg_next(startsg);
-
- /* PARANOID */
- startsg->dma_address = startsg->dma_length = 0;
-
- /* catch brokenness in SCSI layer */
- ASSERT(startsg->length <= DMA_CHUNK_SIZE);
-
- /*
- ** First make sure current dma stream won't
- ** exceed DMA_CHUNK_SIZE if we coalesce the
- ** next entry.
- */
- if (((dma_len + dma_offset + startsg->length + ~iovp_mask) & iovp_mask)
- > DMA_CHUNK_SIZE)
- break;
-
- if (dma_len + startsg->length > max_seg_size)
- break;
-
- /*
- ** Then look for virtually contiguous blocks.
- **
- ** append the next transaction?
- */
- vaddr = (unsigned long) sba_sg_address(startsg);
- if (vcontig_end == vaddr)
- {
- vcontig_len += startsg->length;
- vcontig_end += startsg->length;
- dma_len += startsg->length;
- continue;
- }
-
-#ifdef DEBUG_LARGE_SG_ENTRIES
- dump_run_sg = (vcontig_len > iovp_size);
-#endif
-
- /*
- ** Not virtually contiguous.
- ** Terminate prev chunk.
- ** Start a new chunk.
- **
- ** Once we start a new VCONTIG chunk, dma_offset
- ** can't change. And we need the offset from the first
- ** chunk - not the last one. Ergo Successive chunks
- ** must start on page boundaries and dove tail
- ** with it's predecessor.
- */
- vcontig_sg->dma_length = vcontig_len;
-
- vcontig_sg = startsg;
- vcontig_len = startsg->length;
-
- /*
- ** 3) do the entries end/start on page boundaries?
- ** Don't update vcontig_end until we've checked.
- */
- if (DMA_CONTIG(vcontig_end, vaddr))
- {
- vcontig_end = vcontig_len + vaddr;
- dma_len += vcontig_len;
- continue;
- } else {
- break;
- }
- }
-
- /*
- ** End of DMA Stream
- ** Terminate last VCONTIG block.
- ** Allocate space for DMA stream.
- */
- vcontig_sg->dma_length = vcontig_len;
- dma_len = (dma_len + dma_offset + ~iovp_mask) & iovp_mask;
- ASSERT(dma_len <= DMA_CHUNK_SIZE);
- idx = sba_alloc_range(ioc, dev, dma_len);
- if (idx < 0) {
- dma_sg->dma_length = 0;
- return -1;
- }
- dma_sg->dma_address = (dma_addr_t)(PIDE_FLAG | (idx << iovp_shift)
- | dma_offset);
- n_mappings++;
- }
-
- return n_mappings;
-}
-
-static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
- int nents, enum dma_data_direction dir,
- unsigned long attrs);
-/**
- * sba_map_sg - map Scatter/Gather list
- * @dev: instance of PCI owned by the driver that's asking.
- * @sglist: array of buffer/length pairs
- * @nents: number of entries in list
- * @dir: R/W or both.
- * @attrs: optional dma attributes
- *
- * See Documentation/core-api/dma-api-howto.rst
- */
-static int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist,
- int nents, enum dma_data_direction dir,
- unsigned long attrs)
-{
- struct ioc *ioc;
- int coalesced, filled = 0;
-#ifdef ASSERT_PDIR_SANITY
- unsigned long flags;
-#endif
-#ifdef ALLOW_IOV_BYPASS_SG
- struct scatterlist *sg;
-#endif
-
- DBG_RUN_SG("%s() START %d entries\n", __func__, nents);
- ioc = GET_IOC(dev);
- ASSERT(ioc);
-
-#ifdef ALLOW_IOV_BYPASS_SG
- ASSERT(to_pci_dev(dev)->dma_mask);
- if (likely((ioc->dma_mask & ~to_pci_dev(dev)->dma_mask) == 0)) {
- for_each_sg(sglist, sg, nents, filled) {
- sg->dma_length = sg->length;
- sg->dma_address = virt_to_phys(sba_sg_address(sg));
- }
- return filled;
- }
-#endif
- /* Fast path single entry scatterlists. */
- if (nents == 1) {
- sglist->dma_length = sglist->length;
- sglist->dma_address = sba_map_page(dev, sg_page(sglist),
- sglist->offset, sglist->length, dir, attrs);
- if (dma_mapping_error(dev, sglist->dma_address))
- return -EIO;
- return 1;
- }
-
-#ifdef ASSERT_PDIR_SANITY
- spin_lock_irqsave(&ioc->res_lock, flags);
- if (sba_check_pdir(ioc,"Check before sba_map_sg_attrs()"))
- {
- sba_dump_sg(ioc, sglist, nents);
- panic("Check before sba_map_sg_attrs()");
- }
- spin_unlock_irqrestore(&ioc->res_lock, flags);
-#endif
-
- prefetch(ioc->res_hint);
-
- /*
- ** First coalesce the chunks and allocate I/O pdir space
- **
- ** If this is one DMA stream, we can properly map using the
- ** correct virtual address associated with each DMA page.
- ** w/o this association, we wouldn't have coherent DMA!
- ** Access to the virtual address is what forces a two pass algorithm.
- */
- coalesced = sba_coalesce_chunks(ioc, dev, sglist, nents);
- if (coalesced < 0) {
- sba_unmap_sg_attrs(dev, sglist, nents, dir, attrs);
- return -ENOMEM;
- }
-
- /*
- ** Program the I/O Pdir
- **
- ** map the virtual addresses to the I/O Pdir
- ** o dma_address will contain the pdir index
- ** o dma_len will contain the number of bytes to map
- ** o address contains the virtual address.
- */
- filled = sba_fill_pdir(ioc, sglist, nents);
-
-#ifdef ASSERT_PDIR_SANITY
- spin_lock_irqsave(&ioc->res_lock, flags);
- if (sba_check_pdir(ioc,"Check after sba_map_sg_attrs()"))
- {
- sba_dump_sg(ioc, sglist, nents);
- panic("Check after sba_map_sg_attrs()\n");
- }
- spin_unlock_irqrestore(&ioc->res_lock, flags);
-#endif
-
- ASSERT(coalesced == filled);
- DBG_RUN_SG("%s() DONE %d mappings\n", __func__, filled);
-
- return filled;
-}
-
-/**
- * sba_unmap_sg_attrs - unmap Scatter/Gather list
- * @dev: instance of PCI owned by the driver that's asking.
- * @sglist: array of buffer/length pairs
- * @nents: number of entries in list
- * @dir: R/W or both.
- * @attrs: optional dma attributes
- *
- * See Documentation/core-api/dma-api-howto.rst
- */
-static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
- int nents, enum dma_data_direction dir,
- unsigned long attrs)
-{
-#ifdef ASSERT_PDIR_SANITY
- struct ioc *ioc;
- unsigned long flags;
-#endif
-
- DBG_RUN_SG("%s() START %d entries, %p,%x\n",
- __func__, nents, sba_sg_address(sglist), sglist->length);
-
-#ifdef ASSERT_PDIR_SANITY
- ioc = GET_IOC(dev);
- ASSERT(ioc);
-
- spin_lock_irqsave(&ioc->res_lock, flags);
- sba_check_pdir(ioc,"Check before sba_unmap_sg_attrs()");
- spin_unlock_irqrestore(&ioc->res_lock, flags);
-#endif
-
- while (nents && sglist->dma_length) {
-
- sba_unmap_page(dev, sglist->dma_address, sglist->dma_length,
- dir, attrs);
- sglist = sg_next(sglist);
- nents--;
- }
-
- DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents);
-
-#ifdef ASSERT_PDIR_SANITY
- spin_lock_irqsave(&ioc->res_lock, flags);
- sba_check_pdir(ioc,"Check after sba_unmap_sg_attrs()");
- spin_unlock_irqrestore(&ioc->res_lock, flags);
-#endif
-
-}
-
-/**************************************************************
-*
-* Initialization and claim
-*
-***************************************************************/
-
-static void
-ioc_iova_init(struct ioc *ioc)
-{
- int tcnfg;
- int agp_found = 0;
- struct pci_dev *device = NULL;
-#ifdef FULL_VALID_PDIR
- unsigned long index;
-#endif
-
- /*
- ** Firmware programs the base and size of a "safe IOVA space"
- ** (one that doesn't overlap memory or LMMIO space) in the
- ** IBASE and IMASK registers.
- */
- ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & ~0x1UL;
- ioc->imask = READ_REG(ioc->ioc_hpa + IOC_IMASK) | 0xFFFFFFFF00000000UL;
-
- ioc->iov_size = ~ioc->imask + 1;
-
- DBG_INIT("%s() hpa %p IOV base 0x%lx mask 0x%lx (%dMB)\n",
- __func__, ioc->ioc_hpa, ioc->ibase, ioc->imask,
- ioc->iov_size >> 20);
-
- switch (iovp_size) {
- case 4*1024: tcnfg = 0; break;
- case 8*1024: tcnfg = 1; break;
- case 16*1024: tcnfg = 2; break;
- case 64*1024: tcnfg = 3; break;
- default:
- panic(PFX "Unsupported IOTLB page size %ldK",
- iovp_size >> 10);
- break;
- }
- WRITE_REG(tcnfg, ioc->ioc_hpa + IOC_TCNFG);
-
- ioc->pdir_size = (ioc->iov_size / iovp_size) * PDIR_ENTRY_SIZE;
- ioc->pdir_base = (void *) __get_free_pages(GFP_KERNEL,
- get_order(ioc->pdir_size));
- if (!ioc->pdir_base)
- panic(PFX "Couldn't allocate I/O Page Table\n");
-
- memset(ioc->pdir_base, 0, ioc->pdir_size);
-
- DBG_INIT("%s() IOV page size %ldK pdir %p size %x\n", __func__,
- iovp_size >> 10, ioc->pdir_base, ioc->pdir_size);
-
- ASSERT(ALIGN((unsigned long) ioc->pdir_base, 4*1024) == (unsigned long) ioc->pdir_base);
- WRITE_REG(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE);
-
- /*
- ** If an AGP device is present, only use half of the IOV space
- ** for PCI DMA. Unfortunately we can't know ahead of time
- ** whether GART support will actually be used, for now we
- ** can just key on an AGP device found in the system.
- ** We program the next pdir index after we stop w/ a key for
- ** the GART code to handshake on.
- */
- for_each_pci_dev(device)
- agp_found |= pci_find_capability(device, PCI_CAP_ID_AGP);
-
- if (agp_found && reserve_sba_gart) {
- printk(KERN_INFO PFX "reserving %dMb of IOVA space at 0x%lx for agpgart\n",
- ioc->iov_size/2 >> 20, ioc->ibase + ioc->iov_size/2);
- ioc->pdir_size /= 2;
- ((u64 *)ioc->pdir_base)[PDIR_INDEX(ioc->iov_size/2)] = ZX1_SBA_IOMMU_COOKIE;
- }
-#ifdef FULL_VALID_PDIR
- /*
- ** Check to see if the spill page has been allocated, we don't need more than
- ** one across multiple SBAs.
- */
- if (!prefetch_spill_page) {
- char *spill_poison = "SBAIOMMU POISON";
- int poison_size = 16;
- void *poison_addr, *addr;
-
- addr = (void *)__get_free_pages(GFP_KERNEL, get_order(iovp_size));
- if (!addr)
- panic(PFX "Couldn't allocate PDIR spill page\n");
-
- poison_addr = addr;
- for ( ; (u64) poison_addr < addr + iovp_size; poison_addr += poison_size)
- memcpy(poison_addr, spill_poison, poison_size);
-
- prefetch_spill_page = virt_to_phys(addr);
-
- DBG_INIT("%s() prefetch spill addr: 0x%lx\n", __func__, prefetch_spill_page);
- }
- /*
- ** Set all the PDIR entries valid w/ the spill page as the target
- */
- for (index = 0 ; index < (ioc->pdir_size / PDIR_ENTRY_SIZE) ; index++)
- ((u64 *)ioc->pdir_base)[index] = (0x80000000000000FF | prefetch_spill_page);
-#endif
-
- /* Clear I/O TLB of any possible entries */
- WRITE_REG(ioc->ibase | (get_iovp_order(ioc->iov_size) + iovp_shift), ioc->ioc_hpa + IOC_PCOM);
- READ_REG(ioc->ioc_hpa + IOC_PCOM);
-
- /* Enable IOVA translation */
- WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa + IOC_IBASE);
- READ_REG(ioc->ioc_hpa + IOC_IBASE);
-}
-
-static void __init
-ioc_resource_init(struct ioc *ioc)
-{
- spin_lock_init(&ioc->res_lock);
-#if DELAYED_RESOURCE_CNT > 0
- spin_lock_init(&ioc->saved_lock);
-#endif
-
- /* resource map size dictated by pdir_size */
- ioc->res_size = ioc->pdir_size / PDIR_ENTRY_SIZE; /* entries */
- ioc->res_size >>= 3; /* convert bit count to byte count */
- DBG_INIT("%s() res_size 0x%x\n", __func__, ioc->res_size);
-
- ioc->res_map = (char *) __get_free_pages(GFP_KERNEL,
- get_order(ioc->res_size));
- if (!ioc->res_map)
- panic(PFX "Couldn't allocate resource map\n");
-
- memset(ioc->res_map, 0, ioc->res_size);
- /* next available IOVP - circular search */
- ioc->res_hint = (unsigned long *) ioc->res_map;
-
-#ifdef ASSERT_PDIR_SANITY
- /* Mark first bit busy - ie no IOVA 0 */
- ioc->res_map[0] = 0x1;
- ioc->pdir_base[0] = 0x8000000000000000ULL | ZX1_SBA_IOMMU_COOKIE;
-#endif
-#ifdef FULL_VALID_PDIR
- /* Mark the last resource used so we don't prefetch beyond IOVA space */
- ioc->res_map[ioc->res_size - 1] |= 0x80UL; /* res_map is chars */
- ioc->pdir_base[(ioc->pdir_size / PDIR_ENTRY_SIZE) - 1] = (0x80000000000000FF
- | prefetch_spill_page);
-#endif
-
- DBG_INIT("%s() res_map %x %p\n", __func__,
- ioc->res_size, (void *) ioc->res_map);
-}
-
-static void __init
-ioc_sac_init(struct ioc *ioc)
-{
- struct pci_dev *sac = NULL;
- struct pci_controller *controller = NULL;
-
- /*
- * pci_alloc_coherent() must return a DMA address which is
- * SAC (single address cycle) addressable, so allocate a
- * pseudo-device to enforce that.
- */
- sac = kzalloc(sizeof(*sac), GFP_KERNEL);
- if (!sac)
- panic(PFX "Couldn't allocate struct pci_dev");
-
- controller = kzalloc(sizeof(*controller), GFP_KERNEL);
- if (!controller)
- panic(PFX "Couldn't allocate struct pci_controller");
-
- controller->iommu = ioc;
- sac->sysdata = controller;
- sac->dma_mask = 0xFFFFFFFFUL;
- sac->dev.bus = &pci_bus_type;
- ioc->sac_only_dev = sac;
-}
-
-static void __init
-ioc_zx1_init(struct ioc *ioc)
-{
- unsigned long rope_config;
- unsigned int i;
-
- if (ioc->rev < 0x20)
- panic(PFX "IOC 2.0 or later required for IOMMU support\n");
-
- /* 38 bit memory controller + extra bit for range displaced by MMIO */
- ioc->dma_mask = (0x1UL << 39) - 1;
-
- /*
- ** Clear ROPE(N)_CONFIG AO bit.
- ** Disables "NT Ordering" (~= !"Relaxed Ordering")
- ** Overrides bit 1 in DMA Hint Sets.
- ** Improves netperf UDP_STREAM by ~10% for tg3 on bcm5701.
- */
- for (i=0; i<(8*8); i+=8) {
- rope_config = READ_REG(ioc->ioc_hpa + IOC_ROPE0_CFG + i);
- rope_config &= ~IOC_ROPE_AO;
- WRITE_REG(rope_config, ioc->ioc_hpa + IOC_ROPE0_CFG + i);
- }
-}
-
-typedef void (initfunc)(struct ioc *);
-
-struct ioc_iommu {
- u32 func_id;
- char *name;
- initfunc *init;
-};
-
-static struct ioc_iommu ioc_iommu_info[] __initdata = {
- { ZX1_IOC_ID, "zx1", ioc_zx1_init },
- { ZX2_IOC_ID, "zx2", NULL },
- { SX1000_IOC_ID, "sx1000", NULL },
- { SX2000_IOC_ID, "sx2000", NULL },
-};
-
-static void __init ioc_init(unsigned long hpa, struct ioc *ioc)
-{
- struct ioc_iommu *info;
-
- ioc->next = ioc_list;
- ioc_list = ioc;
-
- ioc->ioc_hpa = ioremap(hpa, 0x1000);
-
- ioc->func_id = READ_REG(ioc->ioc_hpa + IOC_FUNC_ID);
- ioc->rev = READ_REG(ioc->ioc_hpa + IOC_FCLASS) & 0xFFUL;
- ioc->dma_mask = 0xFFFFFFFFFFFFFFFFUL; /* conservative */
-
- for (info = ioc_iommu_info; info < ioc_iommu_info + ARRAY_SIZE(ioc_iommu_info); info++) {
- if (ioc->func_id == info->func_id) {
- ioc->name = info->name;
- if (info->init)
- (info->init)(ioc);
- }
- }
-
- iovp_size = (1 << iovp_shift);
- iovp_mask = ~(iovp_size - 1);
-
- DBG_INIT("%s: PAGE_SIZE %ldK, iovp_size %ldK\n", __func__,
- PAGE_SIZE >> 10, iovp_size >> 10);
-
- if (!ioc->name) {
- ioc->name = kmalloc(24, GFP_KERNEL);
- if (ioc->name)
- sprintf((char *) ioc->name, "Unknown (%04x:%04x)",
- ioc->func_id & 0xFFFF, (ioc->func_id >> 16) & 0xFFFF);
- else
- ioc->name = "Unknown";
- }
-
- ioc_iova_init(ioc);
- ioc_resource_init(ioc);
- ioc_sac_init(ioc);
-
- printk(KERN_INFO PFX
- "%s %d.%d HPA 0x%lx IOVA space %dMb at 0x%lx\n",
- ioc->name, (ioc->rev >> 4) & 0xF, ioc->rev & 0xF,
- hpa, ioc->iov_size >> 20, ioc->ibase);
-}
-
-
-
-/**************************************************************************
-**
-** SBA initialization code (HW and SW)
-**
-** o identify SBA chip itself
-** o FIXME: initialize DMA hints for reasonable defaults
-**
-**************************************************************************/
-
-#ifdef CONFIG_PROC_FS
-static void *
-ioc_start(struct seq_file *s, loff_t *pos)
-{
- struct ioc *ioc;
- loff_t n = *pos;
-
- for (ioc = ioc_list; ioc; ioc = ioc->next)
- if (!n--)
- return ioc;
-
- return NULL;
-}
-
-static void *
-ioc_next(struct seq_file *s, void *v, loff_t *pos)
-{
- struct ioc *ioc = v;
-
- ++*pos;
- return ioc->next;
-}
-
-static void
-ioc_stop(struct seq_file *s, void *v)
-{
-}
-
-static int
-ioc_show(struct seq_file *s, void *v)
-{
- struct ioc *ioc = v;
- unsigned long *res_ptr = (unsigned long *)ioc->res_map;
- int i, used = 0;
-
- seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n",
- ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF));
-#ifdef CONFIG_NUMA
- if (ioc->node != NUMA_NO_NODE)
- seq_printf(s, "NUMA node : %d\n", ioc->node);
-#endif
- seq_printf(s, "IOVA size : %ld MB\n", ((ioc->pdir_size >> 3) * iovp_size)/(1024*1024));
- seq_printf(s, "IOVA page size : %ld kb\n", iovp_size/1024);
-
- for (i = 0; i < (ioc->res_size / sizeof(unsigned long)); ++i, ++res_ptr)
- used += hweight64(*res_ptr);
-
- seq_printf(s, "PDIR size : %d entries\n", ioc->pdir_size >> 3);
- seq_printf(s, "PDIR used : %d entries\n", used);
-
-#ifdef PDIR_SEARCH_TIMING
- {
- unsigned long i = 0, avg = 0, min, max;
- min = max = ioc->avg_search[0];
- for (i = 0; i < SBA_SEARCH_SAMPLE; i++) {
- avg += ioc->avg_search[i];
- if (ioc->avg_search[i] > max) max = ioc->avg_search[i];
- if (ioc->avg_search[i] < min) min = ioc->avg_search[i];
- }
- avg /= SBA_SEARCH_SAMPLE;
- seq_printf(s, "Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles/IOVA page)\n",
- min, avg, max);
- }
-#endif
-#ifndef ALLOW_IOV_BYPASS
- seq_printf(s, "IOVA bypass disabled\n");
-#endif
- return 0;
-}
-
-static const struct seq_operations ioc_seq_ops = {
- .start = ioc_start,
- .next = ioc_next,
- .stop = ioc_stop,
- .show = ioc_show
-};
-
-static void __init
-ioc_proc_init(void)
-{
- struct proc_dir_entry *dir;
-
- dir = proc_mkdir("bus/mckinley", NULL);
- if (!dir)
- return;
-
- proc_create_seq(ioc_list->name, 0, dir, &ioc_seq_ops);
-}
-#endif
-
-static void
-sba_connect_bus(struct pci_bus *bus)
-{
- acpi_handle handle, parent;
- acpi_status status;
- struct ioc *ioc;
-
- if (!PCI_CONTROLLER(bus))
- panic(PFX "no sysdata on bus %d!\n", bus->number);
-
- if (PCI_CONTROLLER(bus)->iommu)
- return;
-
- handle = acpi_device_handle(PCI_CONTROLLER(bus)->companion);
- if (!handle)
- return;
-
- /*
- * The IOC scope encloses PCI root bridges in the ACPI
- * namespace, so work our way out until we find an IOC we
- * claimed previously.
- */
- do {
- for (ioc = ioc_list; ioc; ioc = ioc->next)
- if (ioc->handle == handle) {
- PCI_CONTROLLER(bus)->iommu = ioc;
- return;
- }
-
- status = acpi_get_parent(handle, &parent);
- handle = parent;
- } while (ACPI_SUCCESS(status));
-
- printk(KERN_WARNING "No IOC for PCI Bus %04x:%02x in ACPI\n", pci_domain_nr(bus), bus->number);
-}
-
-static void __init
-sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
-{
-#ifdef CONFIG_NUMA
- unsigned int node;
-
- node = acpi_get_node(handle);
- if (node != NUMA_NO_NODE && !node_online(node))
- node = NUMA_NO_NODE;
-
- ioc->node = node;
-#endif
-}
-
-static void __init acpi_sba_ioc_add(struct ioc *ioc)
-{
- acpi_handle handle = ioc->handle;
- acpi_status status;
- u64 hpa, length;
- struct acpi_device_info *adi;
-
- ioc_found = ioc->next;
- status = hp_acpi_csr_space(handle, &hpa, &length);
- if (ACPI_FAILURE(status))
- goto err;
-
- status = acpi_get_object_info(handle, &adi);
- if (ACPI_FAILURE(status))
- goto err;
-
- /*
- * For HWP0001, only SBA appears in ACPI namespace. It encloses the PCI
- * root bridges, and its CSR space includes the IOC function.
- */
- if (strncmp("HWP0001", adi->hardware_id.string, 7) == 0) {
- hpa += ZX1_IOC_OFFSET;
- /* zx1 based systems default to kernel page size iommu pages */
- if (!iovp_shift)
- iovp_shift = min(PAGE_SHIFT, 16);
- }
- kfree(adi);
-
- /*
- * default anything not caught above or specified on cmdline to 4k
- * iommu page size
- */
- if (!iovp_shift)
- iovp_shift = 12;
-
- ioc_init(hpa, ioc);
- /* setup NUMA node association */
- sba_map_ioc_to_node(ioc, handle);
- return;
-
- err:
- kfree(ioc);
-}
-
-static const struct acpi_device_id hp_ioc_iommu_device_ids[] = {
- {"HWP0001", 0},
- {"HWP0004", 0},
- {"", 0},
-};
-
-static int acpi_sba_ioc_attach(struct acpi_device *device,
- const struct acpi_device_id *not_used)
-{
- struct ioc *ioc;
-
- ioc = kzalloc(sizeof(*ioc), GFP_KERNEL);
- if (!ioc)
- return -ENOMEM;
-
- ioc->next = ioc_found;
- ioc_found = ioc;
- ioc->handle = device->handle;
- return 1;
-}
-
-
-static struct acpi_scan_handler acpi_sba_ioc_handler = {
- .ids = hp_ioc_iommu_device_ids,
- .attach = acpi_sba_ioc_attach,
-};
-
-static int __init acpi_sba_ioc_init_acpi(void)
-{
- return acpi_scan_add_handler(&acpi_sba_ioc_handler);
-}
-/* This has to run before acpi_scan_init(). */
-arch_initcall(acpi_sba_ioc_init_acpi);
-
-static int sba_dma_supported (struct device *dev, u64 mask)
-{
- /* make sure it's at least 32bit capable */
- return ((mask & 0xFFFFFFFFUL) == 0xFFFFFFFFUL);
-}
-
-static const struct dma_map_ops sba_dma_ops = {
- .alloc = sba_alloc_coherent,
- .free = sba_free_coherent,
- .map_page = sba_map_page,
- .unmap_page = sba_unmap_page,
- .map_sg = sba_map_sg_attrs,
- .unmap_sg = sba_unmap_sg_attrs,
- .dma_supported = sba_dma_supported,
- .mmap = dma_common_mmap,
- .get_sgtable = dma_common_get_sgtable,
- .alloc_pages = dma_common_alloc_pages,
- .free_pages = dma_common_free_pages,
-};
-
-static int __init
-sba_init(void)
-{
- /*
- * If we are booting a kdump kernel, the sba_iommu will cause devices
- * that were not shutdown properly to MCA as soon as they are turned
- * back on. Our only option for a successful kdump kernel boot is to
- * use swiotlb.
- */
- if (is_kdump_kernel())
- return 0;
-
- /*
- * ioc_found should be populated by the acpi_sba_ioc_handler's .attach()
- * routine, but that only happens if acpi_scan_init() has already run.
- */
- while (ioc_found)
- acpi_sba_ioc_add(ioc_found);
-
- if (!ioc_list)
- return 0;
-
- {
- struct pci_bus *b = NULL;
- while ((b = pci_find_next_bus(b)) != NULL)
- sba_connect_bus(b);
- }
-
- /* no need for swiotlb with the iommu */
- swiotlb_exit();
- dma_ops = &sba_dma_ops;
-
-#ifdef CONFIG_PROC_FS
- ioc_proc_init();
-#endif
- return 0;
-}
-
-subsys_initcall(sba_init); /* must be initialized after ACPI etc., but before any drivers... */
-
-static int __init
-nosbagart(char *str)
-{
- reserve_sba_gart = 0;
- return 1;
-}
-
-__setup("nosbagart", nosbagart);
-
-static int __init
-sba_page_override(char *str)
-{
- unsigned long page_size;
-
- page_size = memparse(str, &str);
- switch (page_size) {
- case 4096:
- case 8192:
- case 16384:
- case 65536:
- iovp_shift = ffs(page_size) - 1;
- break;
- default:
- printk("%s: unknown/unsupported iommu page size %ld\n",
- __func__, page_size);
- }
-
- return 1;
-}
-
-__setup("sbapagesize=",sba_page_override);
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
deleted file mode 100644
index aefae2efde9f..000000000000
--- a/arch/ia64/include/asm/Kbuild
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-generated-y += syscall_table.h
-generic-y += agp.h
-generic-y += kvm_para.h
-generic-y += mcs_spinlock.h
-generic-y += vtime.h
diff --git a/arch/ia64/include/asm/acenv.h b/arch/ia64/include/asm/acenv.h
deleted file mode 100644
index 9d673cd4c2ad..000000000000
--- a/arch/ia64/include/asm/acenv.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * IA64 specific ACPICA environments and implementation
- *
- * Copyright (C) 2014, Intel Corporation
- * Author: Lv Zheng <lv.zheng@intel.com>
- */
-
-#ifndef _ASM_IA64_ACENV_H
-#define _ASM_IA64_ACENV_H
-
-#include <asm/intrinsics.h>
-
-#define COMPILER_DEPENDENT_INT64 long
-#define COMPILER_DEPENDENT_UINT64 unsigned long
-
-/* Asm macros */
-
-static inline int
-ia64_acpi_acquire_global_lock(unsigned int *lock)
-{
- unsigned int old, new, val;
- do {
- old = *lock;
- new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
- val = ia64_cmpxchg4_acq(lock, new, old);
- } while (unlikely (val != old));
- return (new < 3) ? -1 : 0;
-}
-
-static inline int
-ia64_acpi_release_global_lock(unsigned int *lock)
-{
- unsigned int old, new, val;
- do {
- old = *lock;
- new = old & ~0x3;
- val = ia64_cmpxchg4_acq(lock, new, old);
- } while (unlikely (val != old));
- return old & 0x1;
-}
-
-#define ACPI_ACQUIRE_GLOBAL_LOCK(facs, Acq) \
- ((Acq) = ia64_acpi_acquire_global_lock(&facs->global_lock))
-
-#define ACPI_RELEASE_GLOBAL_LOCK(facs, Acq) \
- ((Acq) = ia64_acpi_release_global_lock(&facs->global_lock))
-
-#endif /* _ASM_IA64_ACENV_H */
diff --git a/arch/ia64/include/asm/acpi-ext.h b/arch/ia64/include/asm/acpi-ext.h
deleted file mode 100644
index eaa57583d151..000000000000
--- a/arch/ia64/include/asm/acpi-ext.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P.
- * Alex Williamson <alex.williamson@hp.com>
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- *
- * Vendor specific extensions to ACPI.
- */
-
-#ifndef _ASM_IA64_ACPI_EXT_H
-#define _ASM_IA64_ACPI_EXT_H
-
-#include <linux/types.h>
-
-extern acpi_status hp_acpi_csr_space (acpi_handle, u64 *base, u64 *length);
-
-#endif /* _ASM_IA64_ACPI_EXT_H */
diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h
deleted file mode 100644
index 58500a964238..000000000000
--- a/arch/ia64/include/asm/acpi.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 2000,2001 J.I. Lee <jung-ik.lee@intel.com>
- * Copyright (C) 2001,2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
- */
-
-#ifndef _ASM_ACPI_H
-#define _ASM_ACPI_H
-
-#ifdef __KERNEL__
-
-#include <acpi/proc_cap_intel.h>
-
-#include <linux/init.h>
-#include <linux/numa.h>
-#include <asm/numa.h>
-
-
-extern int acpi_lapic;
-#define acpi_disabled 0 /* ACPI always enabled on IA64 */
-#define acpi_noirq 0 /* ACPI always enabled on IA64 */
-#define acpi_pci_disabled 0 /* ACPI PCI always enabled on IA64 */
-#define acpi_strict 1 /* no ACPI spec workarounds on IA64 */
-
-static inline bool acpi_has_cpu_in_madt(void)
-{
- return !!acpi_lapic;
-}
-
-#define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */
-static inline void disable_acpi(void) { }
-
-int acpi_request_vector (u32 int_type);
-int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
-
-/* Low-level suspend routine. */
-extern int acpi_suspend_lowlevel(void);
-
-static inline unsigned long acpi_get_wakeup_address(void)
-{
- return 0;
-}
-
-/*
- * Record the cpei override flag and current logical cpu. This is
- * useful for CPU removal.
- */
-extern unsigned int can_cpei_retarget(void);
-extern unsigned int is_cpu_cpei_target(unsigned int cpu);
-extern void set_cpei_target_cpu(unsigned int cpu);
-extern unsigned int get_cpei_target_cpu(void);
-extern void prefill_possible_map(void);
-#ifdef CONFIG_ACPI_HOTPLUG_CPU
-extern int additional_cpus;
-#else
-#define additional_cpus 0
-#endif
-
-#ifdef CONFIG_ACPI_NUMA
-#if MAX_NUMNODES > 256
-#define MAX_PXM_DOMAINS MAX_NUMNODES
-#else
-#define MAX_PXM_DOMAINS (256)
-#endif
-extern int pxm_to_nid_map[MAX_PXM_DOMAINS];
-extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
-#endif
-
-static inline bool arch_has_acpi_pdc(void) { return true; }
-static inline void arch_acpi_set_proc_cap_bits(u32 *cap)
-{
- *cap |= ACPI_PROC_CAP_EST_CAPABILITY_SMP;
-}
-
-#ifdef CONFIG_ACPI_NUMA
-extern cpumask_t early_cpu_possible_map;
-#define for_each_possible_early_cpu(cpu) \
- for_each_cpu((cpu), &early_cpu_possible_map)
-
-static inline void per_cpu_scan_finalize(int min_cpus, int reserve_cpus)
-{
- int low_cpu, high_cpu;
- int cpu;
- int next_nid = 0;
-
- low_cpu = cpumask_weight(&early_cpu_possible_map);
-
- high_cpu = max(low_cpu, min_cpus);
- high_cpu = min(high_cpu + reserve_cpus, NR_CPUS);
-
- for (cpu = low_cpu; cpu < high_cpu; cpu++) {
- cpumask_set_cpu(cpu, &early_cpu_possible_map);
- if (node_cpuid[cpu].nid == NUMA_NO_NODE) {
- node_cpuid[cpu].nid = next_nid;
- next_nid++;
- if (next_nid >= num_online_nodes())
- next_nid = 0;
- }
- }
-}
-
-extern void acpi_numa_fixup(void);
-
-#endif /* CONFIG_ACPI_NUMA */
-
-#endif /*__KERNEL__*/
-
-#endif /*_ASM_ACPI_H*/
diff --git a/arch/ia64/include/asm/asm-offsets.h b/arch/ia64/include/asm/asm-offsets.h
deleted file mode 100644
index d370ee36a182..000000000000
--- a/arch/ia64/include/asm/asm-offsets.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <generated/asm-offsets.h>
diff --git a/arch/ia64/include/asm/asm-prototypes.h b/arch/ia64/include/asm/asm-prototypes.h
deleted file mode 100644
index a96689447a74..000000000000
--- a/arch/ia64/include/asm/asm-prototypes.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_ASM_PROTOTYPES_H
-#define _ASM_IA64_ASM_PROTOTYPES_H
-
-#include <asm/cacheflush.h>
-#include <asm/checksum.h>
-#include <asm/esi.h>
-#include <asm/ftrace.h>
-#include <asm/page.h>
-#include <asm/pal.h>
-#include <asm/string.h>
-#include <linux/uaccess.h>
-#include <asm/unwind.h>
-#include <asm/xor.h>
-
-extern const char ia64_ivt[];
-
-signed int __divsi3(signed int, unsigned int);
-signed int __modsi3(signed int, unsigned int);
-
-signed long long __divdi3(signed long long, unsigned long long);
-signed long long __moddi3(signed long long, unsigned long long);
-
-unsigned int __udivsi3(unsigned int, unsigned int);
-unsigned int __umodsi3(unsigned int, unsigned int);
-
-unsigned long long __udivdi3(unsigned long long, unsigned long long);
-unsigned long long __umoddi3(unsigned long long, unsigned long long);
-
-#endif /* _ASM_IA64_ASM_PROTOTYPES_H */
diff --git a/arch/ia64/include/asm/asmmacro.h b/arch/ia64/include/asm/asmmacro.h
deleted file mode 100644
index 52619c517f09..000000000000
--- a/arch/ia64/include/asm/asmmacro.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_ASMMACRO_H
-#define _ASM_IA64_ASMMACRO_H
-
-/*
- * Copyright (C) 2000-2001, 2003-2004 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-
-#define ENTRY(name) \
- .align 32; \
- .proc name; \
-name:
-
-#define ENTRY_MIN_ALIGN(name) \
- .align 16; \
- .proc name; \
-name:
-
-#define GLOBAL_ENTRY(name) \
- .global name; \
- ENTRY(name)
-
-#define END(name) \
- .endp name
-
-/*
- * Helper macros to make unwind directives more readable:
- */
-
-/* prologue_gr: */
-#define ASM_UNW_PRLG_RP 0x8
-#define ASM_UNW_PRLG_PFS 0x4
-#define ASM_UNW_PRLG_PSP 0x2
-#define ASM_UNW_PRLG_PR 0x1
-#define ASM_UNW_PRLG_GRSAVE(ninputs) (32+(ninputs))
-
-/*
- * Helper macros for accessing user memory.
- *
- * When adding any new .section/.previous entries here, make sure to
- * also add it to the DISCARD section in arch/ia64/kernel/gate.lds.S or
- * unpleasant things will happen.
- */
-
- .section "__ex_table", "a" // declare section & section attributes
- .previous
-
-# define EX(y,x...) \
- .xdata4 "__ex_table", 99f-., y-.; \
- [99:] x
-# define EXCLR(y,x...) \
- .xdata4 "__ex_table", 99f-., y-.+4; \
- [99:] x
-
-/*
- * Tag MCA recoverable instruction ranges.
- */
-
- .section "__mca_table", "a" // declare section & section attributes
- .previous
-
-# define MCA_RECOVER_RANGE(y) \
- .xdata4 "__mca_table", y-., 99f-.; \
- [99:]
-
-/*
- * Mark instructions that need a load of a virtual address patched to be
- * a load of a physical address. We use this either in critical performance
- * path (ivt.S - TLB miss processing) or in places where it might not be
- * safe to use a "tpa" instruction (mca_asm.S - error recovery).
- */
- .section ".data..patch.vtop", "a" // declare section & section attributes
- .previous
-
-#define LOAD_PHYSICAL(pr, reg, obj) \
-[1:](pr)movl reg = obj; \
- .xdata4 ".data..patch.vtop", 1b-.
-
-/*
- * For now, we always put in the McKinley E9 workaround. On CPUs that don't need it,
- * we'll patch out the work-around bundles with NOPs, so their impact is minimal.
- */
-#define DO_MCKINLEY_E9_WORKAROUND
-
-#ifdef DO_MCKINLEY_E9_WORKAROUND
- .section ".data..patch.mckinley_e9", "a"
- .previous
-/* workaround for Itanium 2 Errata 9: */
-# define FSYS_RETURN \
- .xdata4 ".data..patch.mckinley_e9", 1f-.; \
-1:{ .mib; \
- nop.m 0; \
- mov r16=ar.pfs; \
- br.call.sptk.many b7=2f;; \
- }; \
-2:{ .mib; \
- nop.m 0; \
- mov ar.pfs=r16; \
- br.ret.sptk.many b6;; \
- }
-#else
-# define FSYS_RETURN br.ret.sptk.many b6
-#endif
-
-/*
- * If physical stack register size is different from DEF_NUM_STACK_REG,
- * dynamically patch the kernel for correct size.
- */
- .section ".data..patch.phys_stack_reg", "a"
- .previous
-#define LOAD_PHYS_STACK_REG_SIZE(reg) \
-[1:] adds reg=IA64_NUM_PHYS_STACK_REG*8+8,r0; \
- .xdata4 ".data..patch.phys_stack_reg", 1b-.
-
-/*
- * Up until early 2004, use of .align within a function caused bad unwind info.
- * TEXT_ALIGN(n) expands into ".align n" if a fixed GAS is available or into nothing
- * otherwise.
- */
-#ifdef HAVE_WORKING_TEXT_ALIGN
-# define TEXT_ALIGN(n) .align n
-#else
-# define TEXT_ALIGN(n)
-#endif
-
-#ifdef HAVE_SERIALIZE_DIRECTIVE
-# define dv_serialize_data .serialize.data
-# define dv_serialize_instruction .serialize.instruction
-#else
-# define dv_serialize_data
-# define dv_serialize_instruction
-#endif
-
-#endif /* _ASM_IA64_ASMMACRO_H */
diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h
deleted file mode 100644
index 6540a628d257..000000000000
--- a/arch/ia64/include/asm/atomic.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_ATOMIC_H
-#define _ASM_IA64_ATOMIC_H
-
-/*
- * Atomic operations that C can't guarantee us. Useful for
- * resource counting etc..
- *
- * NOTE: don't mess with the types below! The "unsigned long" and
- * "int" types were carefully placed so as to ensure proper operation
- * of the macros.
- *
- * Copyright (C) 1998, 1999, 2002-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#include <linux/types.h>
-
-#include <asm/intrinsics.h>
-#include <asm/barrier.h>
-
-
-#define ATOMIC64_INIT(i) { (i) }
-
-#define arch_atomic_read(v) READ_ONCE((v)->counter)
-#define arch_atomic64_read(v) READ_ONCE((v)->counter)
-
-#define arch_atomic_set(v,i) WRITE_ONCE(((v)->counter), (i))
-#define arch_atomic64_set(v,i) WRITE_ONCE(((v)->counter), (i))
-
-#define ATOMIC_OP(op, c_op) \
-static __inline__ int \
-ia64_atomic_##op (int i, atomic_t *v) \
-{ \
- __s32 old, new; \
- CMPXCHG_BUGCHECK_DECL \
- \
- do { \
- CMPXCHG_BUGCHECK(v); \
- old = arch_atomic_read(v); \
- new = old c_op i; \
- } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic_t)) != old); \
- return new; \
-}
-
-#define ATOMIC_FETCH_OP(op, c_op) \
-static __inline__ int \
-ia64_atomic_fetch_##op (int i, atomic_t *v) \
-{ \
- __s32 old, new; \
- CMPXCHG_BUGCHECK_DECL \
- \
- do { \
- CMPXCHG_BUGCHECK(v); \
- old = arch_atomic_read(v); \
- new = old c_op i; \
- } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic_t)) != old); \
- return old; \
-}
-
-#define ATOMIC_OPS(op, c_op) \
- ATOMIC_OP(op, c_op) \
- ATOMIC_FETCH_OP(op, c_op)
-
-ATOMIC_OPS(add, +)
-ATOMIC_OPS(sub, -)
-
-#ifdef __OPTIMIZE__
-#define __ia64_atomic_const(i) \
- static const int __ia64_atomic_p = __builtin_constant_p(i) ? \
- ((i) == 1 || (i) == 4 || (i) == 8 || (i) == 16 || \
- (i) == -1 || (i) == -4 || (i) == -8 || (i) == -16) : 0;\
- __ia64_atomic_p
-#else
-#define __ia64_atomic_const(i) 0
-#endif
-
-#define arch_atomic_add_return(i,v) \
-({ \
- int __ia64_aar_i = (i); \
- __ia64_atomic_const(i) \
- ? ia64_fetch_and_add(__ia64_aar_i, &(v)->counter) \
- : ia64_atomic_add(__ia64_aar_i, v); \
-})
-
-#define arch_atomic_sub_return(i,v) \
-({ \
- int __ia64_asr_i = (i); \
- __ia64_atomic_const(i) \
- ? ia64_fetch_and_add(-__ia64_asr_i, &(v)->counter) \
- : ia64_atomic_sub(__ia64_asr_i, v); \
-})
-
-#define arch_atomic_fetch_add(i,v) \
-({ \
- int __ia64_aar_i = (i); \
- __ia64_atomic_const(i) \
- ? ia64_fetchadd(__ia64_aar_i, &(v)->counter, acq) \
- : ia64_atomic_fetch_add(__ia64_aar_i, v); \
-})
-
-#define arch_atomic_fetch_sub(i,v) \
-({ \
- int __ia64_asr_i = (i); \
- __ia64_atomic_const(i) \
- ? ia64_fetchadd(-__ia64_asr_i, &(v)->counter, acq) \
- : ia64_atomic_fetch_sub(__ia64_asr_i, v); \
-})
-
-ATOMIC_FETCH_OP(and, &)
-ATOMIC_FETCH_OP(or, |)
-ATOMIC_FETCH_OP(xor, ^)
-
-#define arch_atomic_and(i,v) (void)ia64_atomic_fetch_and(i,v)
-#define arch_atomic_or(i,v) (void)ia64_atomic_fetch_or(i,v)
-#define arch_atomic_xor(i,v) (void)ia64_atomic_fetch_xor(i,v)
-
-#define arch_atomic_fetch_and(i,v) ia64_atomic_fetch_and(i,v)
-#define arch_atomic_fetch_or(i,v) ia64_atomic_fetch_or(i,v)
-#define arch_atomic_fetch_xor(i,v) ia64_atomic_fetch_xor(i,v)
-
-#undef ATOMIC_OPS
-#undef ATOMIC_FETCH_OP
-#undef ATOMIC_OP
-
-#define ATOMIC64_OP(op, c_op) \
-static __inline__ s64 \
-ia64_atomic64_##op (s64 i, atomic64_t *v) \
-{ \
- s64 old, new; \
- CMPXCHG_BUGCHECK_DECL \
- \
- do { \
- CMPXCHG_BUGCHECK(v); \
- old = arch_atomic64_read(v); \
- new = old c_op i; \
- } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic64_t)) != old); \
- return new; \
-}
-
-#define ATOMIC64_FETCH_OP(op, c_op) \
-static __inline__ s64 \
-ia64_atomic64_fetch_##op (s64 i, atomic64_t *v) \
-{ \
- s64 old, new; \
- CMPXCHG_BUGCHECK_DECL \
- \
- do { \
- CMPXCHG_BUGCHECK(v); \
- old = arch_atomic64_read(v); \
- new = old c_op i; \
- } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic64_t)) != old); \
- return old; \
-}
-
-#define ATOMIC64_OPS(op, c_op) \
- ATOMIC64_OP(op, c_op) \
- ATOMIC64_FETCH_OP(op, c_op)
-
-ATOMIC64_OPS(add, +)
-ATOMIC64_OPS(sub, -)
-
-#define arch_atomic64_add_return(i,v) \
-({ \
- s64 __ia64_aar_i = (i); \
- __ia64_atomic_const(i) \
- ? ia64_fetch_and_add(__ia64_aar_i, &(v)->counter) \
- : ia64_atomic64_add(__ia64_aar_i, v); \
-})
-
-#define arch_atomic64_sub_return(i,v) \
-({ \
- s64 __ia64_asr_i = (i); \
- __ia64_atomic_const(i) \
- ? ia64_fetch_and_add(-__ia64_asr_i, &(v)->counter) \
- : ia64_atomic64_sub(__ia64_asr_i, v); \
-})
-
-#define arch_atomic64_fetch_add(i,v) \
-({ \
- s64 __ia64_aar_i = (i); \
- __ia64_atomic_const(i) \
- ? ia64_fetchadd(__ia64_aar_i, &(v)->counter, acq) \
- : ia64_atomic64_fetch_add(__ia64_aar_i, v); \
-})
-
-#define arch_atomic64_fetch_sub(i,v) \
-({ \
- s64 __ia64_asr_i = (i); \
- __ia64_atomic_const(i) \
- ? ia64_fetchadd(-__ia64_asr_i, &(v)->counter, acq) \
- : ia64_atomic64_fetch_sub(__ia64_asr_i, v); \
-})
-
-ATOMIC64_FETCH_OP(and, &)
-ATOMIC64_FETCH_OP(or, |)
-ATOMIC64_FETCH_OP(xor, ^)
-
-#define arch_atomic64_and(i,v) (void)ia64_atomic64_fetch_and(i,v)
-#define arch_atomic64_or(i,v) (void)ia64_atomic64_fetch_or(i,v)
-#define arch_atomic64_xor(i,v) (void)ia64_atomic64_fetch_xor(i,v)
-
-#define arch_atomic64_fetch_and(i,v) ia64_atomic64_fetch_and(i,v)
-#define arch_atomic64_fetch_or(i,v) ia64_atomic64_fetch_or(i,v)
-#define arch_atomic64_fetch_xor(i,v) ia64_atomic64_fetch_xor(i,v)
-
-#undef ATOMIC64_OPS
-#undef ATOMIC64_FETCH_OP
-#undef ATOMIC64_OP
-
-#define arch_atomic_add(i,v) (void)arch_atomic_add_return((i), (v))
-#define arch_atomic_sub(i,v) (void)arch_atomic_sub_return((i), (v))
-
-#define arch_atomic64_add(i,v) (void)arch_atomic64_add_return((i), (v))
-#define arch_atomic64_sub(i,v) (void)arch_atomic64_sub_return((i), (v))
-
-#endif /* _ASM_IA64_ATOMIC_H */
diff --git a/arch/ia64/include/asm/barrier.h b/arch/ia64/include/asm/barrier.h
deleted file mode 100644
index 751cdd353446..000000000000
--- a/arch/ia64/include/asm/barrier.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Memory barrier definitions. This is based on information published
- * in the Processor Abstraction Layer and the System Abstraction Layer
- * manual.
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
- */
-#ifndef _ASM_IA64_BARRIER_H
-#define _ASM_IA64_BARRIER_H
-
-#include <linux/compiler.h>
-
-/*
- * Macros to force memory ordering. In these descriptions, "previous"
- * and "subsequent" refer to program order; "visible" means that all
- * architecturally visible effects of a memory access have occurred
- * (at a minimum, this means the memory has been read or written).
- *
- * wmb(): Guarantees that all preceding stores to memory-
- * like regions are visible before any subsequent
- * stores and that all following stores will be
- * visible only after all previous stores.
- * rmb(): Like wmb(), but for reads.
- * mb(): wmb()/rmb() combo, i.e., all previous memory
- * accesses are visible before all subsequent
- * accesses and vice versa. This is also known as
- * a "fence."
- *
- * Note: "mb()" and its variants cannot be used as a fence to order
- * accesses to memory mapped I/O registers. For that, mf.a needs to
- * be used. However, we don't want to always use mf.a because (a)
- * it's (presumably) much slower than mf and (b) mf.a is supported for
- * sequential memory pages only.
- */
-#define mb() ia64_mf()
-#define rmb() mb()
-#define wmb() mb()
-
-#define dma_rmb() mb()
-#define dma_wmb() mb()
-
-# define __smp_mb() mb()
-
-#define __smp_mb__before_atomic() barrier()
-#define __smp_mb__after_atomic() barrier()
-
-/*
- * IA64 GCC turns volatile stores into st.rel and volatile loads into ld.acq no
- * need for asm trickery!
- */
-
-#define __smp_store_release(p, v) \
-do { \
- compiletime_assert_atomic_type(*p); \
- barrier(); \
- WRITE_ONCE(*p, v); \
-} while (0)
-
-#define __smp_load_acquire(p) \
-({ \
- typeof(*p) ___p1 = READ_ONCE(*p); \
- compiletime_assert_atomic_type(*p); \
- barrier(); \
- ___p1; \
-})
-
-/*
- * The group barrier in front of the rsm & ssm are necessary to ensure
- * that none of the previous instructions in the same group are
- * affected by the rsm/ssm.
- */
-
-#include <asm-generic/barrier.h>
-
-#endif /* _ASM_IA64_BARRIER_H */
diff --git a/arch/ia64/include/asm/bitops.h b/arch/ia64/include/asm/bitops.h
deleted file mode 100644
index 1accb7842f58..000000000000
--- a/arch/ia64/include/asm/bitops.h
+++ /dev/null
@@ -1,453 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_BITOPS_H
-#define _ASM_IA64_BITOPS_H
-
-/*
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * 02/06/02 find_next_bit() and find_first_bit() added from Erich Focht's ia64
- * O(1) scheduler patch
- */
-
-#ifndef _LINUX_BITOPS_H
-#error only <linux/bitops.h> can be included directly
-#endif
-
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <asm/intrinsics.h>
-#include <asm/barrier.h>
-
-/**
- * set_bit - Atomically set a bit in memory
- * @nr: the bit to set
- * @addr: the address to start counting from
- *
- * This function is atomic and may not be reordered. See __set_bit()
- * if you do not require the atomic guarantees.
- * Note that @nr may be almost arbitrarily large; this function is not
- * restricted to acting on a single-word quantity.
- *
- * The address must be (at least) "long" aligned.
- * Note that there are driver (e.g., eepro100) which use these operations to
- * operate on hw-defined data-structures, so we can't easily change these
- * operations to force a bigger alignment.
- *
- * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
- */
-static __inline__ void
-set_bit (int nr, volatile void *addr)
-{
- __u32 bit, old, new;
- volatile __u32 *m;
- CMPXCHG_BUGCHECK_DECL
-
- m = (volatile __u32 *) addr + (nr >> 5);
- bit = 1 << (nr & 31);
- do {
- CMPXCHG_BUGCHECK(m);
- old = *m;
- new = old | bit;
- } while (cmpxchg_acq(m, old, new) != old);
-}
-
-/**
- * arch___set_bit - Set a bit in memory
- * @nr: the bit to set
- * @addr: the address to start counting from
- *
- * Unlike set_bit(), this function is non-atomic and may be reordered.
- * If it's called on the same region of memory simultaneously, the effect
- * may be that only one operation succeeds.
- */
-static __always_inline void
-arch___set_bit(unsigned long nr, volatile unsigned long *addr)
-{
- *((__u32 *) addr + (nr >> 5)) |= (1 << (nr & 31));
-}
-
-/**
- * clear_bit - Clears a bit in memory
- * @nr: Bit to clear
- * @addr: Address to start counting from
- *
- * clear_bit() is atomic and may not be reordered. However, it does
- * not contain a memory barrier, so if it is used for locking purposes,
- * you should call smp_mb__before_atomic() and/or smp_mb__after_atomic()
- * in order to ensure changes are visible on other processors.
- */
-static __inline__ void
-clear_bit (int nr, volatile void *addr)
-{
- __u32 mask, old, new;
- volatile __u32 *m;
- CMPXCHG_BUGCHECK_DECL
-
- m = (volatile __u32 *) addr + (nr >> 5);
- mask = ~(1 << (nr & 31));
- do {
- CMPXCHG_BUGCHECK(m);
- old = *m;
- new = old & mask;
- } while (cmpxchg_acq(m, old, new) != old);
-}
-
-/**
- * clear_bit_unlock - Clears a bit in memory with release
- * @nr: Bit to clear
- * @addr: Address to start counting from
- *
- * clear_bit_unlock() is atomic and may not be reordered. It does
- * contain a memory barrier suitable for unlock type operations.
- */
-static __inline__ void
-clear_bit_unlock (int nr, volatile void *addr)
-{
- __u32 mask, old, new;
- volatile __u32 *m;
- CMPXCHG_BUGCHECK_DECL
-
- m = (volatile __u32 *) addr + (nr >> 5);
- mask = ~(1 << (nr & 31));
- do {
- CMPXCHG_BUGCHECK(m);
- old = *m;
- new = old & mask;
- } while (cmpxchg_rel(m, old, new) != old);
-}
-
-/**
- * __clear_bit_unlock - Non-atomically clears a bit in memory with release
- * @nr: Bit to clear
- * @addr: Address to start counting from
- *
- * Similarly to clear_bit_unlock, the implementation uses a store
- * with release semantics. See also arch_spin_unlock().
- */
-static __inline__ void
-__clear_bit_unlock(int nr, void *addr)
-{
- __u32 * const m = (__u32 *) addr + (nr >> 5);
- __u32 const new = *m & ~(1 << (nr & 31));
-
- ia64_st4_rel_nta(m, new);
-}
-
-/**
- * arch___clear_bit - Clears a bit in memory (non-atomic version)
- * @nr: the bit to clear
- * @addr: the address to start counting from
- *
- * Unlike clear_bit(), this function is non-atomic and may be reordered.
- * If it's called on the same region of memory simultaneously, the effect
- * may be that only one operation succeeds.
- */
-static __always_inline void
-arch___clear_bit(unsigned long nr, volatile unsigned long *addr)
-{
- *((__u32 *) addr + (nr >> 5)) &= ~(1 << (nr & 31));
-}
-
-/**
- * change_bit - Toggle a bit in memory
- * @nr: Bit to toggle
- * @addr: Address to start counting from
- *
- * change_bit() is atomic and may not be reordered.
- * Note that @nr may be almost arbitrarily large; this function is not
- * restricted to acting on a single-word quantity.
- */
-static __inline__ void
-change_bit (int nr, volatile void *addr)
-{
- __u32 bit, old, new;
- volatile __u32 *m;
- CMPXCHG_BUGCHECK_DECL
-
- m = (volatile __u32 *) addr + (nr >> 5);
- bit = (1 << (nr & 31));
- do {
- CMPXCHG_BUGCHECK(m);
- old = *m;
- new = old ^ bit;
- } while (cmpxchg_acq(m, old, new) != old);
-}
-
-/**
- * arch___change_bit - Toggle a bit in memory
- * @nr: the bit to toggle
- * @addr: the address to start counting from
- *
- * Unlike change_bit(), this function is non-atomic and may be reordered.
- * If it's called on the same region of memory simultaneously, the effect
- * may be that only one operation succeeds.
- */
-static __always_inline void
-arch___change_bit(unsigned long nr, volatile unsigned long *addr)
-{
- *((__u32 *) addr + (nr >> 5)) ^= (1 << (nr & 31));
-}
-
-/**
- * test_and_set_bit - Set a bit and return its old value
- * @nr: Bit to set
- * @addr: Address to count from
- *
- * This operation is atomic and cannot be reordered.
- * It also implies the acquisition side of the memory barrier.
- */
-static __inline__ int
-test_and_set_bit (int nr, volatile void *addr)
-{
- __u32 bit, old, new;
- volatile __u32 *m;
- CMPXCHG_BUGCHECK_DECL
-
- m = (volatile __u32 *) addr + (nr >> 5);
- bit = 1 << (nr & 31);
- do {
- CMPXCHG_BUGCHECK(m);
- old = *m;
- new = old | bit;
- } while (cmpxchg_acq(m, old, new) != old);
- return (old & bit) != 0;
-}
-
-/**
- * test_and_set_bit_lock - Set a bit and return its old value for lock
- * @nr: Bit to set
- * @addr: Address to count from
- *
- * This is the same as test_and_set_bit on ia64
- */
-#define test_and_set_bit_lock test_and_set_bit
-
-/**
- * arch___test_and_set_bit - Set a bit and return its old value
- * @nr: Bit to set
- * @addr: Address to count from
- *
- * This operation is non-atomic and can be reordered.
- * If two examples of this operation race, one can appear to succeed
- * but actually fail. You must protect multiple accesses with a lock.
- */
-static __always_inline bool
-arch___test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
-{
- __u32 *p = (__u32 *) addr + (nr >> 5);
- __u32 m = 1 << (nr & 31);
- int oldbitset = (*p & m) != 0;
-
- *p |= m;
- return oldbitset;
-}
-
-/**
- * test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to clear
- * @addr: Address to count from
- *
- * This operation is atomic and cannot be reordered.
- * It also implies the acquisition side of the memory barrier.
- */
-static __inline__ int
-test_and_clear_bit (int nr, volatile void *addr)
-{
- __u32 mask, old, new;
- volatile __u32 *m;
- CMPXCHG_BUGCHECK_DECL
-
- m = (volatile __u32 *) addr + (nr >> 5);
- mask = ~(1 << (nr & 31));
- do {
- CMPXCHG_BUGCHECK(m);
- old = *m;
- new = old & mask;
- } while (cmpxchg_acq(m, old, new) != old);
- return (old & ~mask) != 0;
-}
-
-/**
- * arch___test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to clear
- * @addr: Address to count from
- *
- * This operation is non-atomic and can be reordered.
- * If two examples of this operation race, one can appear to succeed
- * but actually fail. You must protect multiple accesses with a lock.
- */
-static __always_inline bool
-arch___test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
-{
- __u32 *p = (__u32 *) addr + (nr >> 5);
- __u32 m = 1 << (nr & 31);
- int oldbitset = (*p & m) != 0;
-
- *p &= ~m;
- return oldbitset;
-}
-
-/**
- * test_and_change_bit - Change a bit and return its old value
- * @nr: Bit to change
- * @addr: Address to count from
- *
- * This operation is atomic and cannot be reordered.
- * It also implies the acquisition side of the memory barrier.
- */
-static __inline__ int
-test_and_change_bit (int nr, volatile void *addr)
-{
- __u32 bit, old, new;
- volatile __u32 *m;
- CMPXCHG_BUGCHECK_DECL
-
- m = (volatile __u32 *) addr + (nr >> 5);
- bit = (1 << (nr & 31));
- do {
- CMPXCHG_BUGCHECK(m);
- old = *m;
- new = old ^ bit;
- } while (cmpxchg_acq(m, old, new) != old);
- return (old & bit) != 0;
-}
-
-/**
- * arch___test_and_change_bit - Change a bit and return its old value
- * @nr: Bit to change
- * @addr: Address to count from
- *
- * This operation is non-atomic and can be reordered.
- */
-static __always_inline bool
-arch___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
-{
- __u32 old, bit = (1 << (nr & 31));
- __u32 *m = (__u32 *) addr + (nr >> 5);
-
- old = *m;
- *m = old ^ bit;
- return (old & bit) != 0;
-}
-
-#define arch_test_bit generic_test_bit
-#define arch_test_bit_acquire generic_test_bit_acquire
-
-/**
- * ffz - find the first zero bit in a long word
- * @x: The long word to find the bit in
- *
- * Returns the bit-number (0..63) of the first (least significant) zero bit.
- * Undefined if no zero exists, so code should check against ~0UL first...
- */
-static inline unsigned long
-ffz (unsigned long x)
-{
- unsigned long result;
-
- result = ia64_popcnt(x & (~x - 1));
- return result;
-}
-
-/**
- * __ffs - find first bit in word.
- * @x: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static __inline__ unsigned long
-__ffs (unsigned long x)
-{
- unsigned long result;
-
- result = ia64_popcnt((x-1) & ~x);
- return result;
-}
-
-#ifdef __KERNEL__
-
-/*
- * Return bit number of last (most-significant) bit set. Undefined
- * for x==0. Bits are numbered from 0..63 (e.g., ia64_fls(9) == 3).
- */
-static inline unsigned long
-ia64_fls (unsigned long x)
-{
- long double d = x;
- long exp;
-
- exp = ia64_getf_exp(d);
- return exp - 0xffff;
-}
-
-/*
- * Find the last (most significant) bit set. Returns 0 for x==0 and
- * bits are numbered from 1..32 (e.g., fls(9) == 4).
- */
-static inline int fls(unsigned int t)
-{
- unsigned long x = t & 0xffffffffu;
-
- if (!x)
- return 0;
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
- return ia64_popcnt(x);
-}
-
-/*
- * Find the last (most significant) bit set. Undefined for x==0.
- * Bits are numbered from 0..63 (e.g., __fls(9) == 3).
- */
-static inline unsigned long
-__fls (unsigned long x)
-{
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
- x |= x >> 32;
- return ia64_popcnt(x) - 1;
-}
-
-#include <asm-generic/bitops/fls64.h>
-
-#include <asm-generic/bitops/builtin-ffs.h>
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-static __inline__ unsigned long __arch_hweight64(unsigned long x)
-{
- unsigned long result;
- result = ia64_popcnt(x);
- return result;
-}
-
-#define __arch_hweight32(x) ((unsigned int) __arch_hweight64((x) & 0xfffffffful))
-#define __arch_hweight16(x) ((unsigned int) __arch_hweight64((x) & 0xfffful))
-#define __arch_hweight8(x) ((unsigned int) __arch_hweight64((x) & 0xfful))
-
-#include <asm-generic/bitops/const_hweight.h>
-
-#endif /* __KERNEL__ */
-
-#ifdef __KERNEL__
-
-#include <asm-generic/bitops/non-instrumented-non-atomic.h>
-
-#include <asm-generic/bitops/le.h>
-
-#include <asm-generic/bitops/ext2-atomic-setbit.h>
-
-#include <asm-generic/bitops/sched.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_IA64_BITOPS_H */
diff --git a/arch/ia64/include/asm/bug.h b/arch/ia64/include/asm/bug.h
deleted file mode 100644
index 66b37a532765..000000000000
--- a/arch/ia64/include/asm/bug.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_BUG_H
-#define _ASM_IA64_BUG_H
-
-#ifdef CONFIG_BUG
-#define ia64_abort() __builtin_trap()
-#define BUG() do { \
- printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
- barrier_before_unreachable(); \
- ia64_abort(); \
-} while (0)
-
-/* should this BUG be made generic? */
-#define HAVE_ARCH_BUG
-#endif
-
-#include <asm-generic/bug.h>
-
-#endif
diff --git a/arch/ia64/include/asm/cache.h b/arch/ia64/include/asm/cache.h
deleted file mode 100644
index 2f1c70647068..000000000000
--- a/arch/ia64/include/asm/cache.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_CACHE_H
-#define _ASM_IA64_CACHE_H
-
-
-/*
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-/* Bytes per L1 (data) cache line. */
-#define L1_CACHE_SHIFT CONFIG_IA64_L1_CACHE_SHIFT
-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-
-#ifdef CONFIG_SMP
-# define SMP_CACHE_SHIFT L1_CACHE_SHIFT
-# define SMP_CACHE_BYTES L1_CACHE_BYTES
-#else
- /*
- * The "aligned" directive can only _increase_ alignment, so this is
- * safe and provides an easy way to avoid wasting space on a
- * uni-processor:
- */
-# define SMP_CACHE_SHIFT 3
-# define SMP_CACHE_BYTES (1 << 3)
-#endif
-
-#define __read_mostly __section(".data..read_mostly")
-
-#endif /* _ASM_IA64_CACHE_H */
diff --git a/arch/ia64/include/asm/cacheflush.h b/arch/ia64/include/asm/cacheflush.h
deleted file mode 100644
index eac493fa9e0d..000000000000
--- a/arch/ia64/include/asm/cacheflush.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_CACHEFLUSH_H
-#define _ASM_IA64_CACHEFLUSH_H
-
-/*
- * Copyright (C) 2002 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/page-flags.h>
-#include <linux/bitops.h>
-
-#include <asm/page.h>
-
-#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
-static inline void flush_dcache_folio(struct folio *folio)
-{
- clear_bit(PG_arch_1, &folio->flags);
-}
-#define flush_dcache_folio flush_dcache_folio
-
-static inline void flush_dcache_page(struct page *page)
-{
- flush_dcache_folio(page_folio(page));
-}
-
-extern void flush_icache_range(unsigned long start, unsigned long end);
-#define flush_icache_range flush_icache_range
-extern void clflush_cache_range(void *addr, int size);
-
-#define flush_icache_user_page(vma, page, user_addr, len) \
-do { \
- unsigned long _addr = (unsigned long) page_address(page) + ((user_addr) & ~PAGE_MASK); \
- flush_icache_range(_addr, _addr + (len)); \
-} while (0)
-
-#include <asm-generic/cacheflush.h>
-
-#endif /* _ASM_IA64_CACHEFLUSH_H */
diff --git a/arch/ia64/include/asm/checksum.h b/arch/ia64/include/asm/checksum.h
deleted file mode 100644
index f3026213aa32..000000000000
--- a/arch/ia64/include/asm/checksum.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_CHECKSUM_H
-#define _ASM_IA64_CHECKSUM_H
-
-/*
- * Modified 1998, 1999
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-/*
- * This is a version of ip_compute_csum() optimized for IP headers,
- * which always checksum on 4 octet boundaries.
- */
-extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-
-/*
- * Computes the checksum of the TCP/UDP pseudo-header returns a 16-bit
- * checksum, already complemented
- */
-extern __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
- __u32 len, __u8 proto, __wsum sum);
-
-extern __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
- __u32 len, __u8 proto, __wsum sum);
-
-/*
- * Computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-extern __wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- * This routine is used for miscellaneous IP-like checksums, mainly in
- * icmp.c
- */
-extern __sum16 ip_compute_csum(const void *buff, int len);
-
-/*
- * Fold a partial checksum without adding pseudo headers.
- */
-static inline __sum16 csum_fold(__wsum csum)
-{
- u32 sum = (__force u32)csum;
- sum = (sum & 0xffff) + (sum >> 16);
- sum = (sum & 0xffff) + (sum >> 16);
- return (__force __sum16)~sum;
-}
-
-#define _HAVE_ARCH_IPV6_CSUM 1
-struct in6_addr;
-extern __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
- const struct in6_addr *daddr,
- __u32 len, __u8 proto, __wsum csum);
-
-#endif /* _ASM_IA64_CHECKSUM_H */
diff --git a/arch/ia64/include/asm/clocksource.h b/arch/ia64/include/asm/clocksource.h
deleted file mode 100644
index 71a517751afa..000000000000
--- a/arch/ia64/include/asm/clocksource.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* IA64-specific clocksource additions */
-
-#ifndef _ASM_IA64_CLOCKSOURCE_H
-#define _ASM_IA64_CLOCKSOURCE_H
-
-struct arch_clocksource_data {
- void *fsys_mmio; /* used by fsyscall asm code */
-};
-
-#endif /* _ASM_IA64_CLOCKSOURCE_H */
diff --git a/arch/ia64/include/asm/cmpxchg.h b/arch/ia64/include/asm/cmpxchg.h
deleted file mode 100644
index d85ee1a0a227..000000000000
--- a/arch/ia64/include/asm/cmpxchg.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_CMPXCHG_H
-#define _ASM_IA64_CMPXCHG_H
-
-#include <uapi/asm/cmpxchg.h>
-
-#define arch_xchg(ptr, x) \
-({(__typeof__(*(ptr))) __arch_xchg((unsigned long) (x), (ptr), sizeof(*(ptr)));})
-
-#define arch_cmpxchg(ptr, o, n) cmpxchg_acq((ptr), (o), (n))
-#define arch_cmpxchg64(ptr, o, n) cmpxchg_acq((ptr), (o), (n))
-
-#define arch_cmpxchg_local arch_cmpxchg
-#define arch_cmpxchg64_local arch_cmpxchg64
-
-#ifdef CONFIG_IA64_DEBUG_CMPXCHG
-# define CMPXCHG_BUGCHECK_DECL int _cmpxchg_bugcheck_count = 128;
-# define CMPXCHG_BUGCHECK(v) \
-do { \
- if (_cmpxchg_bugcheck_count-- <= 0) { \
- void *ip; \
- extern int _printk(const char *fmt, ...); \
- ip = (void *) ia64_getreg(_IA64_REG_IP); \
- _printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));\
- break; \
- } \
-} while (0)
-#else /* !CONFIG_IA64_DEBUG_CMPXCHG */
-# define CMPXCHG_BUGCHECK_DECL
-# define CMPXCHG_BUGCHECK(v)
-#endif /* !CONFIG_IA64_DEBUG_CMPXCHG */
-
-#endif /* _ASM_IA64_CMPXCHG_H */
diff --git a/arch/ia64/include/asm/cpu.h b/arch/ia64/include/asm/cpu.h
deleted file mode 100644
index db125df9e088..000000000000
--- a/arch/ia64/include/asm/cpu.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_CPU_H_
-#define _ASM_IA64_CPU_H_
-
-#include <linux/device.h>
-#include <linux/cpu.h>
-#include <linux/topology.h>
-#include <linux/percpu.h>
-
-struct ia64_cpu {
- struct cpu cpu;
-};
-
-DECLARE_PER_CPU(struct ia64_cpu, cpu_devices);
-
-DECLARE_PER_CPU(int, cpu_state);
-
-#ifdef CONFIG_HOTPLUG_CPU
-extern int arch_register_cpu(int num);
-extern void arch_unregister_cpu(int);
-#endif
-
-#endif /* _ASM_IA64_CPU_H_ */
diff --git a/arch/ia64/include/asm/cputime.h b/arch/ia64/include/asm/cputime.h
deleted file mode 100644
index 7f28c3564d5d..000000000000
--- a/arch/ia64/include/asm/cputime.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Definitions for measuring cputime on ia64 machines.
- *
- * Based on <asm-powerpc/cputime.h>.
- *
- * Copyright (C) 2007 FUJITSU LIMITED
- * Copyright (C) 2007 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
- *
- * If we have CONFIG_VIRT_CPU_ACCOUNTING_NATIVE, we measure cpu time in nsec.
- * Otherwise we measure cpu time in jiffies using the generic definitions.
- */
-
-#ifndef __IA64_CPUTIME_H
-#define __IA64_CPUTIME_H
-
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
-extern void arch_vtime_task_switch(struct task_struct *tsk);
-#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
-
-#endif /* __IA64_CPUTIME_H */
diff --git a/arch/ia64/include/asm/current.h b/arch/ia64/include/asm/current.h
deleted file mode 100644
index 86fbcc88dff2..000000000000
--- a/arch/ia64/include/asm/current.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_CURRENT_H
-#define _ASM_IA64_CURRENT_H
-
-/*
- * Modified 1998-2000
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-#include <asm/intrinsics.h>
-
-/*
- * In kernel mode, thread pointer (r13) is used to point to the current task
- * structure.
- */
-#define current ((struct task_struct *) ia64_getreg(_IA64_REG_TP))
-
-#endif /* _ASM_IA64_CURRENT_H */
diff --git a/arch/ia64/include/asm/cyclone.h b/arch/ia64/include/asm/cyclone.h
deleted file mode 100644
index a481393647e9..000000000000
--- a/arch/ia64/include/asm/cyclone.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ASM_IA64_CYCLONE_H
-#define ASM_IA64_CYCLONE_H
-
-#ifdef CONFIG_IA64_CYCLONE
-extern int use_cyclone;
-extern void __init cyclone_setup(void);
-#else /* CONFIG_IA64_CYCLONE */
-#define use_cyclone 0
-static inline void cyclone_setup(void)
-{
- printk(KERN_ERR "Cyclone Counter: System not configured"
- " w/ CONFIG_IA64_CYCLONE.\n");
-}
-#endif /* CONFIG_IA64_CYCLONE */
-#endif /* !ASM_IA64_CYCLONE_H */
diff --git a/arch/ia64/include/asm/delay.h b/arch/ia64/include/asm/delay.h
deleted file mode 100644
index 0227ac586107..000000000000
--- a/arch/ia64/include/asm/delay.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_DELAY_H
-#define _ASM_IA64_DELAY_H
-
-/*
- * Delay routines using a pre-computed "cycles/usec" value.
- *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/compiler.h>
-
-#include <asm/intrinsics.h>
-#include <asm/processor.h>
-
-static __inline__ void
-ia64_set_itm (unsigned long val)
-{
- ia64_setreg(_IA64_REG_CR_ITM, val);
- ia64_srlz_d();
-}
-
-static __inline__ unsigned long
-ia64_get_itm (void)
-{
- unsigned long result;
-
- result = ia64_getreg(_IA64_REG_CR_ITM);
- ia64_srlz_d();
- return result;
-}
-
-static __inline__ void
-ia64_set_itv (unsigned long val)
-{
- ia64_setreg(_IA64_REG_CR_ITV, val);
- ia64_srlz_d();
-}
-
-static __inline__ unsigned long
-ia64_get_itv (void)
-{
- return ia64_getreg(_IA64_REG_CR_ITV);
-}
-
-static __inline__ void
-ia64_set_itc (unsigned long val)
-{
- ia64_setreg(_IA64_REG_AR_ITC, val);
- ia64_srlz_d();
-}
-
-static __inline__ unsigned long
-ia64_get_itc (void)
-{
- unsigned long result;
-
- result = ia64_getreg(_IA64_REG_AR_ITC);
- ia64_barrier();
-#ifdef CONFIG_ITANIUM
- while (unlikely((__s32) result == -1)) {
- result = ia64_getreg(_IA64_REG_AR_ITC);
- ia64_barrier();
- }
-#endif
- return result;
-}
-
-extern void ia64_delay_loop (unsigned long loops);
-
-static __inline__ void
-__delay (unsigned long loops)
-{
- if (unlikely(loops < 1))
- return;
-
- ia64_delay_loop (loops - 1);
-}
-
-extern void udelay (unsigned long usecs);
-
-#endif /* _ASM_IA64_DELAY_H */
diff --git a/arch/ia64/include/asm/device.h b/arch/ia64/include/asm/device.h
deleted file mode 100644
index 918b198cd5bb..000000000000
--- a/arch/ia64/include/asm/device.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Arch specific extensions to struct device
- */
-#ifndef _ASM_IA64_DEVICE_H
-#define _ASM_IA64_DEVICE_H
-
-struct dev_archdata {
-};
-
-struct pdev_archdata {
-};
-
-#endif /* _ASM_IA64_DEVICE_H */
diff --git a/arch/ia64/include/asm/div64.h b/arch/ia64/include/asm/div64.h
deleted file mode 100644
index 6cd978cefb28..000000000000
--- a/arch/ia64/include/asm/div64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
deleted file mode 100644
index af6fa8e1597c..000000000000
--- a/arch/ia64/include/asm/dma-mapping.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_DMA_MAPPING_H
-#define _ASM_IA64_DMA_MAPPING_H
-
-/*
- * Copyright (C) 2003-2004 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-extern const struct dma_map_ops *dma_ops;
-
-static inline const struct dma_map_ops *get_arch_dma_ops(void)
-{
- return dma_ops;
-}
-
-#endif /* _ASM_IA64_DMA_MAPPING_H */
diff --git a/arch/ia64/include/asm/dma.h b/arch/ia64/include/asm/dma.h
deleted file mode 100644
index eaed2626ffda..000000000000
--- a/arch/ia64/include/asm/dma.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_DMA_H
-#define _ASM_IA64_DMA_H
-
-/*
- * Copyright (C) 1998-2002 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-
-#include <asm/io.h> /* need byte IO */
-
-extern unsigned long MAX_DMA_ADDRESS;
-
-#define free_dma(x)
-
-#endif /* _ASM_IA64_DMA_H */
diff --git a/arch/ia64/include/asm/dmi.h b/arch/ia64/include/asm/dmi.h
deleted file mode 100644
index ecd9e0a0f5f9..000000000000
--- a/arch/ia64/include/asm/dmi.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_DMI_H
-#define _ASM_DMI_H 1
-
-#include <linux/slab.h>
-#include <asm/io.h>
-
-/* Use normal IO mappings for DMI */
-#define dmi_early_remap ioremap
-#define dmi_early_unmap(x, l) iounmap(x)
-#define dmi_remap ioremap
-#define dmi_unmap iounmap
-#define dmi_alloc(l) kzalloc(l, GFP_ATOMIC)
-
-#endif
diff --git a/arch/ia64/include/asm/early_ioremap.h b/arch/ia64/include/asm/early_ioremap.h
deleted file mode 100644
index 934191b1e2e3..000000000000
--- a/arch/ia64/include/asm/early_ioremap.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_EARLY_IOREMAP_H
-#define _ASM_IA64_EARLY_IOREMAP_H
-
-extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
-#define early_memremap(phys_addr, size) early_ioremap(phys_addr, size)
-
-extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
-#define early_memunmap(addr, size) early_iounmap(addr, size)
-
-#endif
diff --git a/arch/ia64/include/asm/efi.h b/arch/ia64/include/asm/efi.h
deleted file mode 100644
index 6a4a50d8f19a..000000000000
--- a/arch/ia64/include/asm/efi.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_EFI_H
-#define _ASM_EFI_H
-
-typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg);
-
-void *efi_get_pal_addr(void);
-void efi_map_pal_code(void);
-void efi_memmap_walk(efi_freemem_callback_t, void *);
-void efi_memmap_walk_uc(efi_freemem_callback_t, void *);
-void efi_gettimeofday(struct timespec64 *ts);
-
-#endif
diff --git a/arch/ia64/include/asm/elf.h b/arch/ia64/include/asm/elf.h
deleted file mode 100644
index 2ef5f9966ad1..000000000000
--- a/arch/ia64/include/asm/elf.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_ELF_H
-#define _ASM_IA64_ELF_H
-
-/*
- * ELF-specific definitions.
- *
- * Copyright (C) 1998-1999, 2002-2004 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-
-#include <asm/fpu.h>
-#include <asm/page.h>
-#include <asm/auxvec.h>
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) ((x)->e_machine == EM_IA_64)
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS ELFCLASS64
-#define ELF_DATA ELFDATA2LSB
-#define ELF_ARCH EM_IA_64
-
-#define CORE_DUMP_USE_REGSET
-
-/* Least-significant four bits of ELF header's e_flags are OS-specific. The bits are
- interpreted as follows by Linux: */
-#define EF_IA_64_LINUX_EXECUTABLE_STACK 0x1 /* is stack (& heap) executable by default? */
-
-#define ELF_EXEC_PAGESIZE PAGE_SIZE
-
-/*
- * This is the location that an ET_DYN program is loaded if exec'ed.
- * Typical use of this is to invoke "./ld.so someprog" to test out a
- * new version of the loader. We need to make sure that it is out of
- * the way of the program that it will "exec", and that there is
- * sufficient room for the brk.
- */
-#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x800000000UL)
-
-#define PT_IA_64_UNWIND 0x70000001
-
-/* IA-64 relocations: */
-#define R_IA64_NONE 0x00 /* none */
-#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */
-#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */
-#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */
-#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */
-#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */
-#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */
-#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */
-#define R_IA64_GPREL22 0x2a /* @gprel(sym+add), add imm22 */
-#define R_IA64_GPREL64I 0x2b /* @gprel(sym+add), mov imm64 */
-#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym+add), data4 MSB */
-#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym+add), data4 LSB */
-#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym+add), data8 MSB */
-#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym+add), data8 LSB */
-#define R_IA64_LTOFF22 0x32 /* @ltoff(sym+add), add imm22 */
-#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym+add), mov imm64 */
-#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym+add), add imm22 */
-#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym+add), mov imm64 */
-#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym+add), data8 MSB */
-#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym+add), data8 LSB */
-#define R_IA64_FPTR64I 0x43 /* @fptr(sym+add), mov imm64 */
-#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym+add), data4 MSB */
-#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym+add), data4 LSB */
-#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym+add), data8 MSB */
-#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym+add), data8 LSB */
-#define R_IA64_PCREL60B 0x48 /* @pcrel(sym+add), brl */
-#define R_IA64_PCREL21B 0x49 /* @pcrel(sym+add), ptb, call */
-#define R_IA64_PCREL21M 0x4a /* @pcrel(sym+add), chk.s */
-#define R_IA64_PCREL21F 0x4b /* @pcrel(sym+add), fchkf */
-#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym+add), data4 MSB */
-#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym+add), data4 LSB */
-#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym+add), data8 MSB */
-#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym+add), data8 LSB */
-#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */
-#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */
-#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), 4 MSB */
-#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), 4 LSB */
-#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), 8 MSB */
-#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), 8 LSB */
-#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym+add), data4 MSB */
-#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym+add), data4 LSB */
-#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym+add), data8 MSB */
-#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym+add), data8 LSB */
-#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym+add), data4 MSB */
-#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym+add), data4 LSB */
-#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym+add), data8 MSB */
-#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym+add), data8 LSB */
-#define R_IA64_REL32MSB 0x6c /* data 4 + REL */
-#define R_IA64_REL32LSB 0x6d /* data 4 + REL */
-#define R_IA64_REL64MSB 0x6e /* data 8 + REL */
-#define R_IA64_REL64LSB 0x6f /* data 8 + REL */
-#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */
-#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */
-#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */
-#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */
-#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym+add), ptb, call */
-#define R_IA64_PCREL22 0x7a /* @pcrel(sym+add), imm22 */
-#define R_IA64_PCREL64I 0x7b /* @pcrel(sym+add), imm64 */
-#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */
-#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */
-#define R_IA64_COPY 0x84 /* dynamic reloc, data copy */
-#define R_IA64_SUB 0x85 /* -symbol + addend, add imm22 */
-#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */
-#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */
-#define R_IA64_TPREL14 0x91 /* @tprel(sym+add), add imm14 */
-#define R_IA64_TPREL22 0x92 /* @tprel(sym+add), add imm22 */
-#define R_IA64_TPREL64I 0x93 /* @tprel(sym+add), add imm64 */
-#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym+add), data8 MSB */
-#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym+add), data8 LSB */
-#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), add imm22 */
-#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym+add), data8 MSB */
-#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym+add), data8 LSB */
-#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(s+a)), imm22 */
-#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym+add), imm14 */
-#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym+add), imm22 */
-#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym+add), imm64 */
-#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym+add), data4 MSB */
-#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym+add), data4 LSB */
-#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym+add), data8 MSB */
-#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym+add), data8 LSB */
-#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */
-
-/* IA-64 specific section flags: */
-#define SHF_IA_64_SHORT 0x10000000 /* section near gp */
-
-/*
- * We use (abuse?) this macro to insert the (empty) vm_area that is
- * used to map the register backing store. I don't see any better
- * place to do this, but we should discuss this with Linus once we can
- * talk to him...
- */
-extern void ia64_init_addr_space (void);
-#define ELF_PLAT_INIT(_r, load_addr) ia64_init_addr_space()
-
-/* ELF register definitions. This is needed for core dump support. */
-
-/*
- * elf_gregset_t contains the application-level state in the following order:
- * r0-r31
- * NaT bits (for r0-r31; bit N == 1 iff rN is a NaT)
- * predicate registers (p0-p63)
- * b0-b7
- * ip cfm psr
- * ar.rsc ar.bsp ar.bspstore ar.rnat
- * ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec ar.csd ar.ssd
- */
-#define ELF_NGREG 128 /* we really need just 72 but let's leave some headroom... */
-#define ELF_NFPREG 128 /* f0 and f1 could be omitted, but so what... */
-
-/* elf_gregset_t register offsets */
-#define ELF_GR_0_OFFSET 0
-#define ELF_NAT_OFFSET (32 * sizeof(elf_greg_t))
-#define ELF_PR_OFFSET (33 * sizeof(elf_greg_t))
-#define ELF_BR_0_OFFSET (34 * sizeof(elf_greg_t))
-#define ELF_CR_IIP_OFFSET (42 * sizeof(elf_greg_t))
-#define ELF_CFM_OFFSET (43 * sizeof(elf_greg_t))
-#define ELF_CR_IPSR_OFFSET (44 * sizeof(elf_greg_t))
-#define ELF_GR_OFFSET(i) (ELF_GR_0_OFFSET + i * sizeof(elf_greg_t))
-#define ELF_BR_OFFSET(i) (ELF_BR_0_OFFSET + i * sizeof(elf_greg_t))
-#define ELF_AR_RSC_OFFSET (45 * sizeof(elf_greg_t))
-#define ELF_AR_BSP_OFFSET (46 * sizeof(elf_greg_t))
-#define ELF_AR_BSPSTORE_OFFSET (47 * sizeof(elf_greg_t))
-#define ELF_AR_RNAT_OFFSET (48 * sizeof(elf_greg_t))
-#define ELF_AR_CCV_OFFSET (49 * sizeof(elf_greg_t))
-#define ELF_AR_UNAT_OFFSET (50 * sizeof(elf_greg_t))
-#define ELF_AR_FPSR_OFFSET (51 * sizeof(elf_greg_t))
-#define ELF_AR_PFS_OFFSET (52 * sizeof(elf_greg_t))
-#define ELF_AR_LC_OFFSET (53 * sizeof(elf_greg_t))
-#define ELF_AR_EC_OFFSET (54 * sizeof(elf_greg_t))
-#define ELF_AR_CSD_OFFSET (55 * sizeof(elf_greg_t))
-#define ELF_AR_SSD_OFFSET (56 * sizeof(elf_greg_t))
-#define ELF_AR_END_OFFSET (57 * sizeof(elf_greg_t))
-
-typedef unsigned long elf_greg_t;
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct ia64_fpreg elf_fpreg_t;
-typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
-
-
-
-struct pt_regs; /* forward declaration... */
-extern void ia64_elf_core_copy_regs (struct pt_regs *src, elf_gregset_t dst);
-#define ELF_CORE_COPY_REGS(_dest,_regs) ia64_elf_core_copy_regs(_regs, _dest);
-
-/* This macro yields a bitmask that programs can use to figure out
- what instruction set this CPU supports. */
-#define ELF_HWCAP 0
-
-/* This macro yields a string that ld.so will use to load
- implementation specific libraries for optimization. Not terribly
- relevant until we have real hardware to play with... */
-#define ELF_PLATFORM NULL
-
-#define elf_read_implies_exec(ex, executable_stack) \
- ((executable_stack!=EXSTACK_DISABLE_X) && ((ex).e_flags & EF_IA_64_LINUX_EXECUTABLE_STACK) != 0)
-
-struct task_struct;
-
-#define GATE_EHDR ((const struct elfhdr *) GATE_ADDR)
-
-/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
-#define ARCH_DLINFO \
-do { \
- extern char __kernel_syscall_via_epc[]; \
- NEW_AUX_ENT(AT_SYSINFO, (unsigned long) __kernel_syscall_via_epc); \
- NEW_AUX_ENT(AT_SYSINFO_EHDR, (unsigned long) GATE_EHDR); \
-} while (0)
-
-/*
- * format for entries in the Global Offset Table
- */
-struct got_entry {
- uint64_t val;
-};
-
-/*
- * Layout of the Function Descriptor
- */
-struct fdesc {
- uint64_t addr;
- uint64_t gp;
-};
-
-#endif /* _ASM_IA64_ELF_H */
diff --git a/arch/ia64/include/asm/emergency-restart.h b/arch/ia64/include/asm/emergency-restart.h
deleted file mode 100644
index 108d8c48e42e..000000000000
--- a/arch/ia64/include/asm/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/ia64/include/asm/esi.h b/arch/ia64/include/asm/esi.h
deleted file mode 100644
index 56d1310af06e..000000000000
--- a/arch/ia64/include/asm/esi.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * ESI service calls.
- *
- * Copyright (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P.
- * Alex Williamson <alex.williamson@hp.com>
- */
-#ifndef esi_h
-#define esi_h
-
-#include <linux/efi.h>
-
-#define ESI_QUERY 0x00000001
-#define ESI_OPEN_HANDLE 0x02000000
-#define ESI_CLOSE_HANDLE 0x02000001
-
-enum esi_proc_type {
- ESI_PROC_SERIALIZED, /* calls need to be serialized */
- ESI_PROC_MP_SAFE, /* MP-safe, but not reentrant */
- ESI_PROC_REENTRANT /* MP-safe and reentrant */
-};
-
-extern struct ia64_sal_retval esi_call_phys (void *, u64 *);
-extern int ia64_esi_call(efi_guid_t, struct ia64_sal_retval *,
- enum esi_proc_type,
- u64, u64, u64, u64, u64, u64, u64, u64);
-extern int ia64_esi_call_phys(efi_guid_t, struct ia64_sal_retval *, u64, u64,
- u64, u64, u64, u64, u64, u64);
-
-#endif /* esi_h */
diff --git a/arch/ia64/include/asm/exception.h b/arch/ia64/include/asm/exception.h
deleted file mode 100644
index 1d5df8116a31..000000000000
--- a/arch/ia64/include/asm/exception.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-#ifndef __ASM_EXCEPTION_H
-#define __ASM_EXCEPTION_H
-
-struct pt_regs;
-struct exception_table_entry;
-
-extern void ia64_handle_exception(struct pt_regs *regs,
- const struct exception_table_entry *e);
-
-#define ia64_done_with_exception(regs) \
-({ \
- int __ex_ret = 0; \
- const struct exception_table_entry *e; \
- e = search_exception_tables((regs)->cr_iip + ia64_psr(regs)->ri); \
- if (e) { \
- ia64_handle_exception(regs, e); \
- __ex_ret = 1; \
- } \
- __ex_ret; \
-})
-
-#endif /* __ASM_EXCEPTION_H */
diff --git a/arch/ia64/include/asm/extable.h b/arch/ia64/include/asm/extable.h
deleted file mode 100644
index 83eac6aa0639..000000000000
--- a/arch/ia64/include/asm/extable.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_EXTABLE_H
-#define _ASM_IA64_EXTABLE_H
-
-#define ARCH_HAS_RELATIVE_EXTABLE
-
-struct exception_table_entry {
- int insn; /* location-relative address of insn this fixup is for */
- int fixup; /* location-relative continuation addr.; if bit 2 is set, r9 is set to 0 */
-};
-
-#endif
diff --git a/arch/ia64/include/asm/fb.h b/arch/ia64/include/asm/fb.h
deleted file mode 100644
index 1717b26fd423..000000000000
--- a/arch/ia64/include/asm/fb.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_FB_H_
-#define _ASM_FB_H_
-
-#include <linux/compiler.h>
-#include <linux/efi.h>
-#include <linux/string.h>
-
-#include <asm/page.h>
-
-struct file;
-
-static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
- unsigned long off)
-{
- if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- else
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-}
-#define fb_pgprotect fb_pgprotect
-
-static inline void fb_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
-{
- memcpy(to, (void __force *)from, n);
-}
-#define fb_memcpy_fromio fb_memcpy_fromio
-
-static inline void fb_memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
-{
- memcpy((void __force *)to, from, n);
-}
-#define fb_memcpy_toio fb_memcpy_toio
-
-static inline void fb_memset_io(volatile void __iomem *addr, int c, size_t n)
-{
- memset((void __force *)addr, c, n);
-}
-#define fb_memset fb_memset_io
-
-#include <asm-generic/fb.h>
-
-#endif /* _ASM_FB_H_ */
diff --git a/arch/ia64/include/asm/fpswa.h b/arch/ia64/include/asm/fpswa.h
deleted file mode 100644
index 2a0c23728b26..000000000000
--- a/arch/ia64/include/asm/fpswa.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_FPSWA_H
-#define _ASM_IA64_FPSWA_H
-
-/*
- * Floating-point Software Assist
- *
- * Copyright (C) 1999 Intel Corporation.
- * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * Copyright (C) 1999 Goutham Rao <goutham.rao@intel.com>
- */
-
-typedef struct {
- /* 4 * 128 bits */
- unsigned long fp_lp[4*2];
-} fp_state_low_preserved_t;
-
-typedef struct {
- /* 10 * 128 bits */
- unsigned long fp_lv[10 * 2];
-} fp_state_low_volatile_t;
-
-typedef struct {
- /* 16 * 128 bits */
- unsigned long fp_hp[16 * 2];
-} fp_state_high_preserved_t;
-
-typedef struct {
- /* 96 * 128 bits */
- unsigned long fp_hv[96 * 2];
-} fp_state_high_volatile_t;
-
-/**
- * floating point state to be passed to the FP emulation library by
- * the trap/fault handler
- */
-typedef struct {
- unsigned long bitmask_low64;
- unsigned long bitmask_high64;
- fp_state_low_preserved_t *fp_state_low_preserved;
- fp_state_low_volatile_t *fp_state_low_volatile;
- fp_state_high_preserved_t *fp_state_high_preserved;
- fp_state_high_volatile_t *fp_state_high_volatile;
-} fp_state_t;
-
-typedef struct {
- unsigned long status;
- unsigned long err0;
- unsigned long err1;
- unsigned long err2;
-} fpswa_ret_t;
-
-/**
- * function header for the Floating Point software assist
- * library. This function is invoked by the Floating point software
- * assist trap/fault handler.
- */
-typedef fpswa_ret_t (*efi_fpswa_t) (unsigned long trap_type, void *bundle, unsigned long *ipsr,
- unsigned long *fsr, unsigned long *isr, unsigned long *preds,
- unsigned long *ifs, fp_state_t *fp_state);
-
-/**
- * This is the FPSWA library interface as defined by EFI. We need to pass a
- * pointer to the interface itself on a call to the assist library
- */
-typedef struct {
- unsigned int revision;
- unsigned int reserved;
- efi_fpswa_t fpswa;
-} fpswa_interface_t;
-
-extern fpswa_interface_t *fpswa_interface;
-
-#endif /* _ASM_IA64_FPSWA_H */
diff --git a/arch/ia64/include/asm/ftrace.h b/arch/ia64/include/asm/ftrace.h
deleted file mode 100644
index a07a8e575453..000000000000
--- a/arch/ia64/include/asm/ftrace.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_FTRACE_H
-#define _ASM_IA64_FTRACE_H
-
-#ifdef CONFIG_FUNCTION_TRACER
-#define MCOUNT_INSN_SIZE 32 /* sizeof mcount call */
-
-#ifndef __ASSEMBLY__
-extern void _mcount(unsigned long pfs, unsigned long r1, unsigned long b0, unsigned long r0);
-#define mcount _mcount
-
-/* In IA64, MCOUNT_ADDR is set in link time, so it's not a constant at compile time */
-#define MCOUNT_ADDR (((struct fnptr *)mcount)->ip)
-#define FTRACE_ADDR (((struct fnptr *)ftrace_caller)->ip)
-
-static inline unsigned long ftrace_call_adjust(unsigned long addr)
-{
- /* second bundle, insn 2 */
- return addr - 0x12;
-}
-
-struct dyn_arch_ftrace {
-};
-#endif
-
-#endif /* CONFIG_FUNCTION_TRACER */
-
-#endif /* _ASM_IA64_FTRACE_H */
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
deleted file mode 100644
index 1db26b432d8c..000000000000
--- a/arch/ia64/include/asm/futex.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
-#include <linux/futex.h>
-#include <linux/uaccess.h>
-#include <asm/errno.h>
-
-#define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
-do { \
- register unsigned long r8 __asm ("r8") = 0; \
- __asm__ __volatile__( \
- " mf;; \n" \
- "[1:] " insn ";; \n" \
- " .xdata4 \"__ex_table\", 1b-., 2f-. \n" \
- "[2:]" \
- : "+r" (r8), "=r" (oldval) \
- : "r" (uaddr), "r" (oparg) \
- : "memory"); \
- ret = r8; \
-} while (0)
-
-#define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \
-do { \
- register unsigned long r8 __asm ("r8") = 0; \
- int val, newval; \
- do { \
- __asm__ __volatile__( \
- " mf;; \n" \
- "[1:] ld4 %3=[%4];; \n" \
- " mov %2=%3 \n" \
- insn ";; \n" \
- " mov ar.ccv=%2;; \n" \
- "[2:] cmpxchg4.acq %1=[%4],%3,ar.ccv;; \n" \
- " .xdata4 \"__ex_table\", 1b-., 3f-.\n" \
- " .xdata4 \"__ex_table\", 2b-., 3f-.\n" \
- "[3:]" \
- : "+r" (r8), "=r" (val), "=&r" (oldval), \
- "=&r" (newval) \
- : "r" (uaddr), "r" (oparg) \
- : "memory"); \
- if (unlikely (r8)) \
- break; \
- } while (unlikely (val != oldval)); \
- ret = r8; \
-} while (0)
-
-static inline int
-arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
-{
- int oldval = 0, ret;
-
- if (!access_ok(uaddr, sizeof(u32)))
- return -EFAULT;
-
- switch (op) {
- case FUTEX_OP_SET:
- __futex_atomic_op1("xchg4 %1=[%2],%3", ret, oldval, uaddr,
- oparg);
- break;
- case FUTEX_OP_ADD:
- __futex_atomic_op2("add %3=%3,%5", ret, oldval, uaddr, oparg);
- break;
- case FUTEX_OP_OR:
- __futex_atomic_op2("or %3=%3,%5", ret, oldval, uaddr, oparg);
- break;
- case FUTEX_OP_ANDN:
- __futex_atomic_op2("and %3=%3,%5", ret, oldval, uaddr,
- ~oparg);
- break;
- case FUTEX_OP_XOR:
- __futex_atomic_op2("xor %3=%3,%5", ret, oldval, uaddr, oparg);
- break;
- default:
- ret = -ENOSYS;
- }
-
- if (!ret)
- *oval = oldval;
-
- return ret;
-}
-
-static inline int
-futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
- u32 oldval, u32 newval)
-{
- if (!access_ok(uaddr, sizeof(u32)))
- return -EFAULT;
-
- {
- register unsigned long r8 __asm ("r8") = 0;
- unsigned long prev;
- __asm__ __volatile__(
- " mf;; \n"
- " mov ar.ccv=%4;; \n"
- "[1:] cmpxchg4.acq %1=[%2],%3,ar.ccv \n"
- " .xdata4 \"__ex_table\", 1b-., 2f-. \n"
- "[2:]"
- : "+r" (r8), "=&r" (prev)
- : "r" (uaddr), "r" (newval),
- "rO" ((long) (unsigned) oldval)
- : "memory");
- *uval = prev;
- return r8;
- }
-}
-
-#endif /* _ASM_FUTEX_H */
diff --git a/arch/ia64/include/asm/gcc_intrin.h b/arch/ia64/include/asm/gcc_intrin.h
deleted file mode 100644
index 83f230b23867..000000000000
--- a/arch/ia64/include/asm/gcc_intrin.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *
- * Copyright (C) 2002,2003 Jun Nakajima <jun.nakajima@intel.com>
- * Copyright (C) 2002,2003 Suresh Siddha <suresh.b.siddha@intel.com>
- */
-#ifndef _ASM_IA64_GCC_INTRIN_H
-#define _ASM_IA64_GCC_INTRIN_H
-
-#include <uapi/asm/gcc_intrin.h>
-
-register unsigned long ia64_r13 asm ("r13") __used;
-#endif /* _ASM_IA64_GCC_INTRIN_H */
diff --git a/arch/ia64/include/asm/hardirq.h b/arch/ia64/include/asm/hardirq.h
deleted file mode 100644
index ccde7c2ba00f..000000000000
--- a/arch/ia64/include/asm/hardirq.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_HARDIRQ_H
-#define _ASM_IA64_HARDIRQ_H
-
-/*
- * Modified 1998-2002, 2004 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-/*
- * No irq_cpustat_t for IA-64. The data is held in the per-CPU data structure.
- */
-
-#define __ARCH_IRQ_STAT 1
-
-#define local_softirq_pending_ref ia64_cpu_info.softirq_pending
-
-#include <linux/threads.h>
-#include <linux/irq.h>
-
-#include <asm/processor.h>
-
-extern void __iomem *ipi_base_addr;
-
-void ack_bad_irq(unsigned int irq);
-
-#endif /* _ASM_IA64_HARDIRQ_H */
diff --git a/arch/ia64/include/asm/hugetlb.h b/arch/ia64/include/asm/hugetlb.h
deleted file mode 100644
index 026ead47cd53..000000000000
--- a/arch/ia64/include/asm/hugetlb.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_HUGETLB_H
-#define _ASM_IA64_HUGETLB_H
-
-#include <asm/page.h>
-
-#define __HAVE_ARCH_HUGETLB_FREE_PGD_RANGE
-void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
- unsigned long end, unsigned long floor,
- unsigned long ceiling);
-
-#define __HAVE_ARCH_PREPARE_HUGEPAGE_RANGE
-int prepare_hugepage_range(struct file *file,
- unsigned long addr, unsigned long len);
-
-static inline int is_hugepage_only_range(struct mm_struct *mm,
- unsigned long addr,
- unsigned long len)
-{
- return (REGION_NUMBER(addr) == RGN_HPAGE ||
- REGION_NUMBER((addr)+(len)-1) == RGN_HPAGE);
-}
-#define is_hugepage_only_range is_hugepage_only_range
-
-#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
-static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
- unsigned long addr, pte_t *ptep)
-{
- return *ptep;
-}
-
-#include <asm-generic/hugetlb.h>
-
-#endif /* _ASM_IA64_HUGETLB_H */
diff --git a/arch/ia64/include/asm/hw_irq.h b/arch/ia64/include/asm/hw_irq.h
deleted file mode 100644
index 5d267132f8cb..000000000000
--- a/arch/ia64/include/asm/hw_irq.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_HW_IRQ_H
-#define _ASM_IA64_HW_IRQ_H
-
-/*
- * Copyright (C) 2001-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/profile.h>
-
-#include <asm/ptrace.h>
-#include <asm/smp.h>
-
-typedef u8 ia64_vector;
-
-/*
- * 0 special
- *
- * 1,3-14 are reserved from firmware
- *
- * 16-255 (vectored external interrupts) are available
- *
- * 15 spurious interrupt (see IVR)
- *
- * 16 lowest priority, 255 highest priority
- *
- * 15 classes of 16 interrupts each.
- */
-#define IA64_MIN_VECTORED_IRQ 16
-#define IA64_MAX_VECTORED_IRQ 255
-#define IA64_NUM_VECTORS 256
-
-#define AUTO_ASSIGN -1
-
-#define IA64_SPURIOUS_INT_VECTOR 0x0f
-
-/*
- * Vectors 0x10-0x1f are used for low priority interrupts, e.g. CMCI.
- */
-#define IA64_CPEP_VECTOR 0x1c /* corrected platform error polling vector */
-#define IA64_CMCP_VECTOR 0x1d /* corrected machine-check polling vector */
-#define IA64_CPE_VECTOR 0x1e /* corrected platform error interrupt vector */
-#define IA64_CMC_VECTOR 0x1f /* corrected machine-check interrupt vector */
-/*
- * Vectors 0x20-0x2f are reserved for legacy ISA IRQs.
- * Use vectors 0x30-0xe7 as the default device vector range for ia64.
- * Platforms may choose to reduce this range in platform_irq_setup, but the
- * platform range must fall within
- * [IA64_DEF_FIRST_DEVICE_VECTOR..IA64_DEF_LAST_DEVICE_VECTOR]
- */
-extern int ia64_first_device_vector;
-extern int ia64_last_device_vector;
-
-#ifdef CONFIG_SMP
-/* Reserve the lower priority vector than device vectors for "move IRQ" IPI */
-#define IA64_IRQ_MOVE_VECTOR 0x30 /* "move IRQ" IPI */
-#define IA64_DEF_FIRST_DEVICE_VECTOR 0x31
-#else
-#define IA64_DEF_FIRST_DEVICE_VECTOR 0x30
-#endif
-#define IA64_DEF_LAST_DEVICE_VECTOR 0xe7
-#define IA64_FIRST_DEVICE_VECTOR ia64_first_device_vector
-#define IA64_LAST_DEVICE_VECTOR ia64_last_device_vector
-#define IA64_MAX_DEVICE_VECTORS (IA64_DEF_LAST_DEVICE_VECTOR - IA64_DEF_FIRST_DEVICE_VECTOR + 1)
-#define IA64_NUM_DEVICE_VECTORS (IA64_LAST_DEVICE_VECTOR - IA64_FIRST_DEVICE_VECTOR + 1)
-
-#define IA64_MCA_RENDEZ_VECTOR 0xe8 /* MCA rendez interrupt */
-#define IA64_TIMER_VECTOR 0xef /* use highest-prio group 15 interrupt for timer */
-#define IA64_MCA_WAKEUP_VECTOR 0xf0 /* MCA wakeup (must be >MCA_RENDEZ_VECTOR) */
-#define IA64_IPI_LOCAL_TLB_FLUSH 0xfc /* SMP flush local TLB */
-#define IA64_IPI_RESCHEDULE 0xfd /* SMP reschedule */
-#define IA64_IPI_VECTOR 0xfe /* inter-processor interrupt vector */
-
-/* Used for encoding redirected irqs */
-
-#define IA64_IRQ_REDIRECTED (1 << 31)
-
-/* IA64 inter-cpu interrupt related definitions */
-
-#define IA64_IPI_DEFAULT_BASE_ADDR 0xfee00000
-
-/* Delivery modes for inter-cpu interrupts */
-enum {
- IA64_IPI_DM_INT = 0x0, /* pend an external interrupt */
- IA64_IPI_DM_PMI = 0x2, /* pend a PMI */
- IA64_IPI_DM_NMI = 0x4, /* pend an NMI (vector 2) */
- IA64_IPI_DM_INIT = 0x5, /* pend an INIT interrupt */
- IA64_IPI_DM_EXTINT = 0x7, /* pend an 8259-compatible interrupt. */
-};
-
-extern __u8 isa_irq_to_vector_map[16];
-#define isa_irq_to_vector(x) isa_irq_to_vector_map[(x)]
-
-struct irq_cfg {
- ia64_vector vector;
- cpumask_t domain;
- cpumask_t old_domain;
- unsigned move_cleanup_count;
- u8 move_in_progress : 1;
-};
-extern spinlock_t vector_lock;
-extern struct irq_cfg irq_cfg[NR_IRQS];
-#define irq_to_domain(x) irq_cfg[(x)].domain
-DECLARE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq);
-
-extern struct irq_chip irq_type_ia64_lsapic; /* CPU-internal interrupt controller */
-
-#define ia64_register_ipi ia64_native_register_ipi
-#define assign_irq_vector ia64_native_assign_irq_vector
-#define free_irq_vector ia64_native_free_irq_vector
-#define ia64_resend_irq ia64_native_resend_irq
-
-extern void ia64_native_register_ipi(void);
-extern int bind_irq_vector(int irq, int vector, cpumask_t domain);
-extern int ia64_native_assign_irq_vector (int irq); /* allocate a free vector */
-extern void ia64_native_free_irq_vector (int vector);
-extern int reserve_irq_vector (int vector);
-extern void __setup_vector_irq(int cpu);
-extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect);
-extern void destroy_and_reserve_irq (unsigned int irq);
-
-#ifdef CONFIG_SMP
-extern int irq_prepare_move(int irq, int cpu);
-extern void irq_complete_move(unsigned int irq);
-#else
-static inline int irq_prepare_move(int irq, int cpu) { return 0; }
-static inline void irq_complete_move(unsigned int irq) {}
-#endif
-
-static inline void ia64_native_resend_irq(unsigned int vector)
-{
- ia64_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0);
-}
-
-/*
- * Next follows the irq descriptor interface. On IA-64, each CPU supports 256 interrupt
- * vectors. On smaller systems, there is a one-to-one correspondence between interrupt
- * vectors and the Linux irq numbers. However, larger systems may have multiple interrupt
- * domains meaning that the translation from vector number to irq number depends on the
- * interrupt domain that a CPU belongs to. This API abstracts such platform-dependent
- * differences and provides a uniform means to translate between vector and irq numbers
- * and to obtain the irq descriptor for a given irq number.
- */
-
-/* Extract the IA-64 vector that corresponds to IRQ. */
-static inline ia64_vector
-irq_to_vector (int irq)
-{
- return irq_cfg[irq].vector;
-}
-
-/*
- * Convert the local IA-64 vector to the corresponding irq number. This translation is
- * done in the context of the interrupt domain that the currently executing CPU belongs
- * to.
- */
-static inline unsigned int
-local_vector_to_irq (ia64_vector vec)
-{
- return __this_cpu_read(vector_irq[vec]);
-}
-
-#endif /* _ASM_IA64_HW_IRQ_H */
diff --git a/arch/ia64/include/asm/idle.h b/arch/ia64/include/asm/idle.h
deleted file mode 100644
index 97c55b97e0ba..000000000000
--- a/arch/ia64/include/asm/idle.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_IDLE_H
-#define _ASM_IA64_IDLE_H
-
-static inline void enter_idle(void) { }
-static inline void exit_idle(void) { }
-
-#endif /* _ASM_IA64_IDLE_H */
diff --git a/arch/ia64/include/asm/intrinsics.h b/arch/ia64/include/asm/intrinsics.h
deleted file mode 100644
index 035b17fe12ef..000000000000
--- a/arch/ia64/include/asm/intrinsics.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Compiler-dependent intrinsics.
- *
- * Copyright (C) 2002-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#ifndef _ASM_IA64_INTRINSICS_H
-#define _ASM_IA64_INTRINSICS_H
-
-#include <uapi/asm/intrinsics.h>
-
-#endif /* _ASM_IA64_INTRINSICS_H */
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h
deleted file mode 100644
index eedc0afa8cad..000000000000
--- a/arch/ia64/include/asm/io.h
+++ /dev/null
@@ -1,271 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_IO_H
-#define _ASM_IA64_IO_H
-
-/*
- * This file contains the definitions for the emulated IO instructions
- * inb/inw/inl/outb/outw/outl and the "string versions" of the same
- * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
- * versions of the single-IO instructions (inb_p/inw_p/..).
- *
- * This file is not meant to be obfuscating: it's just complicated to
- * (a) handle it all in a way that makes gcc able to optimize it as
- * well as possible and (b) trying to avoid writing the same thing
- * over and over again with slight variations and possibly making a
- * mistake somewhere.
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
- */
-
-#include <asm/unaligned.h>
-#include <asm/early_ioremap.h>
-
-#define __IA64_UNCACHED_OFFSET RGN_BASE(RGN_UNCACHED)
-
-/*
- * The legacy I/O space defined by the ia64 architecture supports only 65536 ports, but
- * large machines may have multiple other I/O spaces so we can't place any a priori limit
- * on IO_SPACE_LIMIT. These additional spaces are described in ACPI.
- */
-#define IO_SPACE_LIMIT 0xffffffffffffffffUL
-
-#define MAX_IO_SPACES_BITS 8
-#define MAX_IO_SPACES (1UL << MAX_IO_SPACES_BITS)
-#define IO_SPACE_BITS 24
-#define IO_SPACE_SIZE (1UL << IO_SPACE_BITS)
-
-#define IO_SPACE_NR(port) ((port) >> IO_SPACE_BITS)
-#define IO_SPACE_BASE(space) ((space) << IO_SPACE_BITS)
-#define IO_SPACE_PORT(port) ((port) & (IO_SPACE_SIZE - 1))
-
-#define IO_SPACE_SPARSE_ENCODING(p) ((((p) >> 2) << 12) | ((p) & 0xfff))
-
-struct io_space {
- unsigned long mmio_base; /* base in MMIO space */
- int sparse;
-};
-
-extern struct io_space io_space[];
-extern unsigned int num_io_spaces;
-
-# ifdef __KERNEL__
-
-/*
- * All MMIO iomem cookies are in region 6; anything less is a PIO cookie:
- * 0xCxxxxxxxxxxxxxxx MMIO cookie (return from ioremap)
- * 0x000000001SPPPPPP PIO cookie (S=space number, P..P=port)
- *
- * ioread/writeX() uses the leading 1 in PIO cookies (PIO_OFFSET) to catch
- * code that uses bare port numbers without the prerequisite pci_iomap().
- */
-#define PIO_OFFSET (1UL << (MAX_IO_SPACES_BITS + IO_SPACE_BITS))
-#define PIO_MASK (PIO_OFFSET - 1)
-#define PIO_RESERVED __IA64_UNCACHED_OFFSET
-#define HAVE_ARCH_PIO_SIZE
-
-#include <asm/intrinsics.h>
-#include <asm/page.h>
-#include <asm-generic/iomap.h>
-
-/*
- * Change virtual addresses to physical addresses and vv.
- */
-static inline unsigned long
-virt_to_phys (volatile void *address)
-{
- return (unsigned long) address - PAGE_OFFSET;
-}
-#define virt_to_phys virt_to_phys
-
-static inline void*
-phys_to_virt (unsigned long address)
-{
- return (void *) (address + PAGE_OFFSET);
-}
-#define phys_to_virt phys_to_virt
-
-#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-extern u64 kern_mem_attribute (unsigned long phys_addr, unsigned long size);
-extern int valid_phys_addr_range (phys_addr_t addr, size_t count); /* efi.c */
-extern int valid_mmap_phys_addr_range (unsigned long pfn, size_t count);
-
-# endif /* KERNEL */
-
-/*
- * Memory fence w/accept. This should never be used in code that is
- * not IA-64 specific.
- */
-#define __ia64_mf_a() ia64_mfa()
-
-static inline void*
-__ia64_mk_io_addr (unsigned long port)
-{
- struct io_space *space;
- unsigned long offset;
-
- space = &io_space[IO_SPACE_NR(port)];
- port = IO_SPACE_PORT(port);
- if (space->sparse)
- offset = IO_SPACE_SPARSE_ENCODING(port);
- else
- offset = port;
-
- return (void *) (space->mmio_base | offset);
-}
-
-/*
- * For the in/out routines, we need to do "mf.a" _after_ doing the I/O access to ensure
- * that the access has completed before executing other I/O accesses. Since we're doing
- * the accesses through an uncachable (UC) translation, the CPU will execute them in
- * program order. However, we still need to tell the compiler not to shuffle them around
- * during optimization, which is why we use "volatile" pointers.
- */
-
-#define inb inb
-static inline unsigned int inb(unsigned long port)
-{
- volatile unsigned char *addr = __ia64_mk_io_addr(port);
- unsigned char ret;
-
- ret = *addr;
- __ia64_mf_a();
- return ret;
-}
-
-#define inw inw
-static inline unsigned int inw(unsigned long port)
-{
- volatile unsigned short *addr = __ia64_mk_io_addr(port);
- unsigned short ret;
-
- ret = *addr;
- __ia64_mf_a();
- return ret;
-}
-
-#define inl inl
-static inline unsigned int inl(unsigned long port)
-{
- volatile unsigned int *addr = __ia64_mk_io_addr(port);
- unsigned int ret;
-
- ret = *addr;
- __ia64_mf_a();
- return ret;
-}
-
-#define outb outb
-static inline void outb(unsigned char val, unsigned long port)
-{
- volatile unsigned char *addr = __ia64_mk_io_addr(port);
-
- *addr = val;
- __ia64_mf_a();
-}
-
-#define outw outw
-static inline void outw(unsigned short val, unsigned long port)
-{
- volatile unsigned short *addr = __ia64_mk_io_addr(port);
-
- *addr = val;
- __ia64_mf_a();
-}
-
-#define outl outl
-static inline void outl(unsigned int val, unsigned long port)
-{
- volatile unsigned int *addr = __ia64_mk_io_addr(port);
-
- *addr = val;
- __ia64_mf_a();
-}
-
-#define insb insb
-static inline void insb(unsigned long port, void *dst, unsigned long count)
-{
- unsigned char *dp = dst;
-
- while (count--)
- *dp++ = inb(port);
-}
-
-#define insw insw
-static inline void insw(unsigned long port, void *dst, unsigned long count)
-{
- unsigned short *dp = dst;
-
- while (count--)
- put_unaligned(inw(port), dp++);
-}
-
-#define insl insl
-static inline void insl(unsigned long port, void *dst, unsigned long count)
-{
- unsigned int *dp = dst;
-
- while (count--)
- put_unaligned(inl(port), dp++);
-}
-
-#define outsb outsb
-static inline void outsb(unsigned long port, const void *src,
- unsigned long count)
-{
- const unsigned char *sp = src;
-
- while (count--)
- outb(*sp++, port);
-}
-
-#define outsw outsw
-static inline void outsw(unsigned long port, const void *src,
- unsigned long count)
-{
- const unsigned short *sp = src;
-
- while (count--)
- outw(get_unaligned(sp++), port);
-}
-
-#define outsl outsl
-static inline void outsl(unsigned long port, const void *src,
- unsigned long count)
-{
- const unsigned int *sp = src;
-
- while (count--)
- outl(get_unaligned(sp++), port);
-}
-
-# ifdef __KERNEL__
-
-#define _PAGE_IOREMAP pgprot_val(PAGE_KERNEL)
-
-extern void __iomem * ioremap_uc(unsigned long offset, unsigned long size);
-
-#define ioremap_prot ioremap_prot
-#define ioremap_cache ioremap
-#define ioremap_uc ioremap_uc
-#define iounmap iounmap
-
-/*
- * String version of IO memory access ops:
- */
-extern void memcpy_fromio(void *dst, const volatile void __iomem *src, long n);
-extern void memcpy_toio(volatile void __iomem *dst, const void *src, long n);
-extern void memset_io(volatile void __iomem *s, int c, long n);
-
-#define memcpy_fromio memcpy_fromio
-#define memcpy_toio memcpy_toio
-#define memset_io memset_io
-#define xlate_dev_mem_ptr xlate_dev_mem_ptr
-#include <asm-generic/io.h>
-#undef PCI_IOBASE
-
-# endif /* __KERNEL__ */
-
-#endif /* _ASM_IA64_IO_H */
diff --git a/arch/ia64/include/asm/iommu.h b/arch/ia64/include/asm/iommu.h
deleted file mode 100644
index eb0db20c9d4c..000000000000
--- a/arch/ia64/include/asm/iommu.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_IOMMU_H
-#define _ASM_IA64_IOMMU_H 1
-
-#include <linux/acpi.h>
-
-/* 10 seconds */
-#define DMAR_OPERATION_TIMEOUT (((cycles_t) local_cpu_data->itc_freq)*10)
-
-extern void no_iommu_init(void);
-#ifdef CONFIG_INTEL_IOMMU
-extern int force_iommu, no_iommu;
-extern int iommu_detected;
-
-static inline int __init
-arch_rmrr_sanity_check(struct acpi_dmar_reserved_memory *rmrr) { return 0; }
-#else
-#define no_iommu (1)
-#define iommu_detected (0)
-#endif
-
-#endif
diff --git a/arch/ia64/include/asm/iosapic.h b/arch/ia64/include/asm/iosapic.h
deleted file mode 100644
index a91aeb413e17..000000000000
--- a/arch/ia64/include/asm/iosapic.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_IA64_IOSAPIC_H
-#define __ASM_IA64_IOSAPIC_H
-
-#define IOSAPIC_REG_SELECT 0x0
-#define IOSAPIC_WINDOW 0x10
-#define IOSAPIC_EOI 0x40
-
-#define IOSAPIC_VERSION 0x1
-
-/*
- * Redirection table entry
- */
-#define IOSAPIC_RTE_LOW(i) (0x10+i*2)
-#define IOSAPIC_RTE_HIGH(i) (0x11+i*2)
-
-#define IOSAPIC_DEST_SHIFT 16
-
-/*
- * Delivery mode
- */
-#define IOSAPIC_DELIVERY_SHIFT 8
-#define IOSAPIC_FIXED 0x0
-#define IOSAPIC_LOWEST_PRIORITY 0x1
-#define IOSAPIC_PMI 0x2
-#define IOSAPIC_NMI 0x4
-#define IOSAPIC_INIT 0x5
-#define IOSAPIC_EXTINT 0x7
-
-/*
- * Interrupt polarity
- */
-#define IOSAPIC_POLARITY_SHIFT 13
-#define IOSAPIC_POL_HIGH 0
-#define IOSAPIC_POL_LOW 1
-
-/*
- * Trigger mode
- */
-#define IOSAPIC_TRIGGER_SHIFT 15
-#define IOSAPIC_EDGE 0
-#define IOSAPIC_LEVEL 1
-
-/*
- * Mask bit
- */
-
-#define IOSAPIC_MASK_SHIFT 16
-#define IOSAPIC_MASK (1<<IOSAPIC_MASK_SHIFT)
-
-#define IOSAPIC_VECTOR_MASK 0xffffff00
-
-#ifndef __ASSEMBLY__
-
-#define NR_IOSAPICS 256
-
-#define iosapic_pcat_compat_init ia64_native_iosapic_pcat_compat_init
-#define __iosapic_read __ia64_native_iosapic_read
-#define __iosapic_write __ia64_native_iosapic_write
-#define iosapic_get_irq_chip ia64_native_iosapic_get_irq_chip
-
-extern void __init ia64_native_iosapic_pcat_compat_init(void);
-extern struct irq_chip *ia64_native_iosapic_get_irq_chip(unsigned long trigger);
-
-static inline unsigned int
-__ia64_native_iosapic_read(char __iomem *iosapic, unsigned int reg)
-{
- writel(reg, iosapic + IOSAPIC_REG_SELECT);
- return readl(iosapic + IOSAPIC_WINDOW);
-}
-
-static inline void
-__ia64_native_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
-{
- writel(reg, iosapic + IOSAPIC_REG_SELECT);
- writel(val, iosapic + IOSAPIC_WINDOW);
-}
-
-static inline void iosapic_eoi(char __iomem *iosapic, u32 vector)
-{
- writel(vector, iosapic + IOSAPIC_EOI);
-}
-
-extern void __init iosapic_system_init (int pcat_compat);
-extern int iosapic_init (unsigned long address, unsigned int gsi_base);
-extern int iosapic_remove (unsigned int gsi_base);
-extern int gsi_to_irq (unsigned int gsi);
-extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
- unsigned long trigger);
-extern void iosapic_unregister_intr (unsigned int irq);
-extern void iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
- unsigned long polarity,
- unsigned long trigger);
-extern int __init iosapic_register_platform_intr (u32 int_type,
- unsigned int gsi,
- int pmi_vector,
- u16 eid, u16 id,
- unsigned long polarity,
- unsigned long trigger);
-
-#ifdef CONFIG_NUMA
-extern void map_iosapic_to_node (unsigned int, int);
-#endif
-
-# endif /* !__ASSEMBLY__ */
-#endif /* __ASM_IA64_IOSAPIC_H */
diff --git a/arch/ia64/include/asm/irq.h b/arch/ia64/include/asm/irq.h
deleted file mode 100644
index 0eccf33dfe8b..000000000000
--- a/arch/ia64/include/asm/irq.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_IRQ_H
-#define _ASM_IA64_IRQ_H
-
-/*
- * Copyright (C) 1999-2000, 2002 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- *
- * 11/24/98 S.Eranian updated TIMER_IRQ and irq_canonicalize
- * 01/20/99 S.Eranian added keyboard interrupt
- * 02/29/00 D.Mosberger moved most things into hw_irq.h
- */
-
-#include <linux/types.h>
-#include <linux/cpumask.h>
-#include <asm/native/irq.h>
-
-#define NR_IRQS IA64_NATIVE_NR_IRQS
-
-static __inline__ int
-irq_canonicalize (int irq)
-{
- /*
- * We do the legacy thing here of pretending that irqs < 16
- * are 8259 irqs. This really shouldn't be necessary at all,
- * but we keep it here as serial.c still uses it...
- */
- return ((irq == 2) ? 9 : irq);
-}
-
-extern void set_irq_affinity_info (unsigned int irq, int dest, int redir);
-
-int create_irq(void);
-void destroy_irq(unsigned int irq);
-
-#endif /* _ASM_IA64_IRQ_H */
diff --git a/arch/ia64/include/asm/irq_regs.h b/arch/ia64/include/asm/irq_regs.h
deleted file mode 100644
index 3dd9c0b70270..000000000000
--- a/arch/ia64/include/asm/irq_regs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/ia64/include/asm/irq_remapping.h b/arch/ia64/include/asm/irq_remapping.h
deleted file mode 100644
index 547a6e87018c..000000000000
--- a/arch/ia64/include/asm/irq_remapping.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __IA64_INTR_REMAPPING_H
-#define __IA64_INTR_REMAPPING_H
-#define irq_remapping_enabled 0
-#endif
diff --git a/arch/ia64/include/asm/irqflags.h b/arch/ia64/include/asm/irqflags.h
deleted file mode 100644
index 1dc30f12e545..000000000000
--- a/arch/ia64/include/asm/irqflags.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * IRQ flags defines.
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
- */
-
-#ifndef _ASM_IA64_IRQFLAGS_H
-#define _ASM_IA64_IRQFLAGS_H
-
-#include <asm/pal.h>
-#include <asm/kregs.h>
-
-#ifdef CONFIG_IA64_DEBUG_IRQ
-extern unsigned long last_cli_ip;
-static inline void arch_maybe_save_ip(unsigned long flags)
-{
- if (flags & IA64_PSR_I)
- last_cli_ip = ia64_getreg(_IA64_REG_IP);
-}
-#else
-#define arch_maybe_save_ip(flags) do {} while (0)
-#endif
-
-/*
- * - clearing psr.i is implicitly serialized (visible by next insn)
- * - setting psr.i requires data serialization
- * - we need a stop-bit before reading PSR because we sometimes
- * write a floating-point register right before reading the PSR
- * and that writes to PSR.mfl
- */
-
-static inline unsigned long arch_local_save_flags(void)
-{
- ia64_stop();
- return ia64_getreg(_IA64_REG_PSR);
-}
-
-static inline unsigned long arch_local_irq_save(void)
-{
- unsigned long flags = arch_local_save_flags();
-
- ia64_stop();
- ia64_rsm(IA64_PSR_I);
- arch_maybe_save_ip(flags);
- return flags;
-}
-
-static inline void arch_local_irq_disable(void)
-{
-#ifdef CONFIG_IA64_DEBUG_IRQ
- arch_local_irq_save();
-#else
- ia64_stop();
- ia64_rsm(IA64_PSR_I);
-#endif
-}
-
-static inline void arch_local_irq_enable(void)
-{
- ia64_stop();
- ia64_ssm(IA64_PSR_I);
- ia64_srlz_d();
-}
-
-static inline void arch_local_irq_restore(unsigned long flags)
-{
-#ifdef CONFIG_IA64_DEBUG_IRQ
- unsigned long old_psr = arch_local_save_flags();
-#endif
- ia64_intrin_local_irq_restore(flags & IA64_PSR_I);
- arch_maybe_save_ip(old_psr & ~flags);
-}
-
-static inline bool arch_irqs_disabled_flags(unsigned long flags)
-{
- return (flags & IA64_PSR_I) == 0;
-}
-
-static inline bool arch_irqs_disabled(void)
-{
- return arch_irqs_disabled_flags(arch_local_save_flags());
-}
-
-static inline void arch_safe_halt(void)
-{
- arch_local_irq_enable();
- ia64_pal_halt_light(); /* PAL_HALT_LIGHT */
-}
-
-
-#endif /* _ASM_IA64_IRQFLAGS_H */
diff --git a/arch/ia64/include/asm/kdebug.h b/arch/ia64/include/asm/kdebug.h
deleted file mode 100644
index 4f7e6dc974bc..000000000000
--- a/arch/ia64/include/asm/kdebug.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef _IA64_KDEBUG_H
-#define _IA64_KDEBUG_H 1
-/*
- *
- * Copyright (C) Intel Corporation, 2005
- *
- * 2005-Apr Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
- * <anil.s.keshavamurthy@intel.com> adopted from
- * include/asm-x86_64/kdebug.h
- *
- * 2005-Oct Keith Owens <kaos@sgi.com>. Expand notify_die to cover more
- * events.
- */
-
-enum die_val {
- DIE_BREAK = 1,
- DIE_FAULT,
- DIE_OOPS,
- DIE_MACHINE_HALT,
- DIE_MACHINE_RESTART,
- DIE_MCA_MONARCH_ENTER,
- DIE_MCA_MONARCH_PROCESS,
- DIE_MCA_MONARCH_LEAVE,
- DIE_MCA_SLAVE_ENTER,
- DIE_MCA_SLAVE_PROCESS,
- DIE_MCA_SLAVE_LEAVE,
- DIE_MCA_RENDZVOUS_ENTER,
- DIE_MCA_RENDZVOUS_PROCESS,
- DIE_MCA_RENDZVOUS_LEAVE,
- DIE_MCA_NEW_TIMEOUT,
- DIE_INIT_ENTER,
- DIE_INIT_MONARCH_ENTER,
- DIE_INIT_MONARCH_PROCESS,
- DIE_INIT_MONARCH_LEAVE,
- DIE_INIT_SLAVE_ENTER,
- DIE_INIT_SLAVE_PROCESS,
- DIE_INIT_SLAVE_LEAVE,
- DIE_KDEBUG_ENTER,
- DIE_KDEBUG_LEAVE,
- DIE_KDUMP_ENTER,
- DIE_KDUMP_LEAVE,
-};
-
-#endif
diff --git a/arch/ia64/include/asm/kexec.h b/arch/ia64/include/asm/kexec.h
deleted file mode 100644
index 294b1e1ebd2d..000000000000
--- a/arch/ia64/include/asm/kexec.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_KEXEC_H
-#define _ASM_IA64_KEXEC_H
-
-#include <asm/setup.h>
-
-/* Maximum physical address we can use pages from */
-#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
-/* Maximum address we can reach in physical address mode */
-#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
-/* Maximum address we can use for the control code buffer */
-#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
-
-#define KEXEC_CONTROL_PAGE_SIZE (8192 + 8192 + 4096)
-
-/* The native architecture */
-#define KEXEC_ARCH KEXEC_ARCH_IA_64
-
-#define kexec_flush_icache_page(page) do { \
- unsigned long page_addr = (unsigned long)page_address(page); \
- flush_icache_range(page_addr, page_addr + PAGE_SIZE); \
- } while(0)
-
-extern struct kimage *ia64_kimage;
-extern const unsigned int relocate_new_kernel_size;
-extern void relocate_new_kernel(unsigned long, unsigned long,
- struct ia64_boot_param *, unsigned long);
-static inline void
-crash_setup_regs(struct pt_regs *newregs, struct pt_regs *oldregs)
-{
-}
-extern struct resource efi_memmap_res;
-extern struct resource boot_param_res;
-extern void kdump_smp_send_stop(void);
-extern void kdump_smp_send_init(void);
-extern void kexec_disable_iosapic(void);
-extern void crash_save_this_cpu(void);
-struct rsvd_region;
-extern unsigned long kdump_find_rsvd_region(unsigned long size,
- struct rsvd_region *rsvd_regions, int n);
-extern void kdump_cpu_freeze(struct unw_frame_info *info, void *arg);
-extern int kdump_status[];
-extern atomic_t kdump_cpu_freezed;
-extern atomic_t kdump_in_progress;
-
-#endif /* _ASM_IA64_KEXEC_H */
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
deleted file mode 100644
index 9e956768946c..000000000000
--- a/arch/ia64/include/asm/kprobes.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef _ASM_KPROBES_H
-#define _ASM_KPROBES_H
-/*
- * Kernel Probes (KProbes)
- *
- * Copyright (C) IBM Corporation, 2002, 2004
- * Copyright (C) Intel Corporation, 2005
- *
- * 2005-Apr Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
- * <anil.s.keshavamurthy@intel.com> adapted from i386
- */
-#include <asm-generic/kprobes.h>
-#include <asm/break.h>
-
-#define BREAK_INST (long)(__IA64_BREAK_KPROBE << 6)
-
-#ifdef CONFIG_KPROBES
-
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/percpu.h>
-
-#define __ARCH_WANT_KPROBES_INSN_SLOT
-#define MAX_INSN_SIZE 2 /* last half is for kprobe-booster */
-#define NOP_M_INST (long)(1<<27)
-#define BRL_INST(i1, i2) ((long)((0xcL << 37) | /* brl */ \
- (0x1L << 12) | /* many */ \
- (((i1) & 1) << 36) | ((i2) << 13))) /* imm */
-
-typedef union cmp_inst {
- struct {
- unsigned long long qp : 6;
- unsigned long long p1 : 6;
- unsigned long long c : 1;
- unsigned long long r2 : 7;
- unsigned long long r3 : 7;
- unsigned long long p2 : 6;
- unsigned long long ta : 1;
- unsigned long long x2 : 2;
- unsigned long long tb : 1;
- unsigned long long opcode : 4;
- unsigned long long reserved : 23;
- }f;
- unsigned long long l;
-} cmp_inst_t;
-
-struct kprobe;
-
-typedef struct _bundle {
- struct {
- unsigned long long template : 5;
- unsigned long long slot0 : 41;
- unsigned long long slot1_p0 : 64-46;
- } quad0;
- struct {
- unsigned long long slot1_p1 : 41 - (64-46);
- unsigned long long slot2 : 41;
- } quad1;
-} __attribute__((__aligned__(16))) bundle_t;
-
-struct prev_kprobe {
- struct kprobe *kp;
- unsigned long status;
-};
-
-#define MAX_PARAM_RSE_SIZE (0x60+0x60/0x3f)
-/* per-cpu kprobe control block */
-#define ARCH_PREV_KPROBE_SZ 2
-struct kprobe_ctlblk {
- unsigned long kprobe_status;
- unsigned long *bsp;
- unsigned long cfm;
- atomic_t prev_kprobe_index;
- struct prev_kprobe prev_kprobe[ARCH_PREV_KPROBE_SZ];
-};
-
-#define kretprobe_blacklist_size 0
-
-#define SLOT0_OPCODE_SHIFT (37)
-#define SLOT1_p1_OPCODE_SHIFT (37 - (64-46))
-#define SLOT2_OPCODE_SHIFT (37)
-
-#define INDIRECT_CALL_OPCODE (1)
-#define IP_RELATIVE_CALL_OPCODE (5)
-#define IP_RELATIVE_BRANCH_OPCODE (4)
-#define IP_RELATIVE_PREDICT_OPCODE (7)
-#define LONG_BRANCH_OPCODE (0xC)
-#define LONG_CALL_OPCODE (0xD)
-#define flush_insn_slot(p) do { } while (0)
-
-typedef struct kprobe_opcode {
- bundle_t bundle;
-} kprobe_opcode_t;
-
-/* Architecture specific copy of original instruction*/
-struct arch_specific_insn {
- /* copy of the instruction to be emulated */
- kprobe_opcode_t *insn;
- #define INST_FLAG_FIX_RELATIVE_IP_ADDR 1
- #define INST_FLAG_FIX_BRANCH_REG 2
- #define INST_FLAG_BREAK_INST 4
- #define INST_FLAG_BOOSTABLE 8
- unsigned long inst_flag;
- unsigned short target_br_reg;
- unsigned short slot;
-};
-
-extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
-extern int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
-
-extern void arch_remove_kprobe(struct kprobe *p);
-
-#endif /* CONFIG_KPROBES */
-#endif /* _ASM_KPROBES_H */
diff --git a/arch/ia64/include/asm/kregs.h b/arch/ia64/include/asm/kregs.h
deleted file mode 100644
index 44113b75e4eb..000000000000
--- a/arch/ia64/include/asm/kregs.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_KREGS_H
-#define _ASM_IA64_KREGS_H
-
-/*
- * Copyright (C) 2001-2002 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-/*
- * This file defines the kernel register usage convention used by Linux/ia64.
- */
-
-/*
- * Kernel registers:
- */
-#define IA64_KR_IO_BASE 0 /* ar.k0: legacy I/O base address */
-#define IA64_KR_TSSD 1 /* ar.k1: IVE uses this as the TSSD */
-#define IA64_KR_PER_CPU_DATA 3 /* ar.k3: physical per-CPU base */
-#define IA64_KR_CURRENT_STACK 4 /* ar.k4: what's mapped in IA64_TR_CURRENT_STACK */
-#define IA64_KR_FPU_OWNER 5 /* ar.k5: fpu-owner (UP only, at the moment) */
-#define IA64_KR_CURRENT 6 /* ar.k6: "current" task pointer */
-#define IA64_KR_PT_BASE 7 /* ar.k7: page table base address (physical) */
-
-#define _IA64_KR_PASTE(x,y) x##y
-#define _IA64_KR_PREFIX(n) _IA64_KR_PASTE(ar.k, n)
-#define IA64_KR(n) _IA64_KR_PREFIX(IA64_KR_##n)
-
-/*
- * Translation registers:
- */
-#define IA64_TR_KERNEL 0 /* itr0, dtr0: maps kernel image (code & data) */
-#define IA64_TR_PALCODE 1 /* itr1: maps PALcode as required by EFI */
-#define IA64_TR_CURRENT_STACK 1 /* dtr1: maps kernel's memory- & register-stacks */
-
-#define IA64_TR_ALLOC_BASE 2 /* itr&dtr: Base of dynamic TR resource*/
-#define IA64_TR_ALLOC_MAX 64 /* Max number for dynamic use*/
-
-/* Processor status register bits: */
-#define IA64_PSR_BE_BIT 1
-#define IA64_PSR_UP_BIT 2
-#define IA64_PSR_AC_BIT 3
-#define IA64_PSR_MFL_BIT 4
-#define IA64_PSR_MFH_BIT 5
-#define IA64_PSR_IC_BIT 13
-#define IA64_PSR_I_BIT 14
-#define IA64_PSR_PK_BIT 15
-#define IA64_PSR_DT_BIT 17
-#define IA64_PSR_DFL_BIT 18
-#define IA64_PSR_DFH_BIT 19
-#define IA64_PSR_SP_BIT 20
-#define IA64_PSR_PP_BIT 21
-#define IA64_PSR_DI_BIT 22
-#define IA64_PSR_SI_BIT 23
-#define IA64_PSR_DB_BIT 24
-#define IA64_PSR_LP_BIT 25
-#define IA64_PSR_TB_BIT 26
-#define IA64_PSR_RT_BIT 27
-/* The following are not affected by save_flags()/restore_flags(): */
-#define IA64_PSR_CPL0_BIT 32
-#define IA64_PSR_CPL1_BIT 33
-#define IA64_PSR_IS_BIT 34
-#define IA64_PSR_MC_BIT 35
-#define IA64_PSR_IT_BIT 36
-#define IA64_PSR_ID_BIT 37
-#define IA64_PSR_DA_BIT 38
-#define IA64_PSR_DD_BIT 39
-#define IA64_PSR_SS_BIT 40
-#define IA64_PSR_RI_BIT 41
-#define IA64_PSR_ED_BIT 43
-#define IA64_PSR_BN_BIT 44
-#define IA64_PSR_IA_BIT 45
-
-/* A mask of PSR bits that we generally don't want to inherit across a clone2() or an
- execve(). Only list flags here that need to be cleared/set for BOTH clone2() and
- execve(). */
-#define IA64_PSR_BITS_TO_CLEAR (IA64_PSR_MFL | IA64_PSR_MFH | IA64_PSR_DB | IA64_PSR_LP | \
- IA64_PSR_TB | IA64_PSR_ID | IA64_PSR_DA | IA64_PSR_DD | \
- IA64_PSR_SS | IA64_PSR_ED | IA64_PSR_IA)
-#define IA64_PSR_BITS_TO_SET (IA64_PSR_DFH | IA64_PSR_SP)
-
-#define IA64_PSR_BE (__IA64_UL(1) << IA64_PSR_BE_BIT)
-#define IA64_PSR_UP (__IA64_UL(1) << IA64_PSR_UP_BIT)
-#define IA64_PSR_AC (__IA64_UL(1) << IA64_PSR_AC_BIT)
-#define IA64_PSR_MFL (__IA64_UL(1) << IA64_PSR_MFL_BIT)
-#define IA64_PSR_MFH (__IA64_UL(1) << IA64_PSR_MFH_BIT)
-#define IA64_PSR_IC (__IA64_UL(1) << IA64_PSR_IC_BIT)
-#define IA64_PSR_I (__IA64_UL(1) << IA64_PSR_I_BIT)
-#define IA64_PSR_PK (__IA64_UL(1) << IA64_PSR_PK_BIT)
-#define IA64_PSR_DT (__IA64_UL(1) << IA64_PSR_DT_BIT)
-#define IA64_PSR_DFL (__IA64_UL(1) << IA64_PSR_DFL_BIT)
-#define IA64_PSR_DFH (__IA64_UL(1) << IA64_PSR_DFH_BIT)
-#define IA64_PSR_SP (__IA64_UL(1) << IA64_PSR_SP_BIT)
-#define IA64_PSR_PP (__IA64_UL(1) << IA64_PSR_PP_BIT)
-#define IA64_PSR_DI (__IA64_UL(1) << IA64_PSR_DI_BIT)
-#define IA64_PSR_SI (__IA64_UL(1) << IA64_PSR_SI_BIT)
-#define IA64_PSR_DB (__IA64_UL(1) << IA64_PSR_DB_BIT)
-#define IA64_PSR_LP (__IA64_UL(1) << IA64_PSR_LP_BIT)
-#define IA64_PSR_TB (__IA64_UL(1) << IA64_PSR_TB_BIT)
-#define IA64_PSR_RT (__IA64_UL(1) << IA64_PSR_RT_BIT)
-/* The following are not affected by save_flags()/restore_flags(): */
-#define IA64_PSR_CPL (__IA64_UL(3) << IA64_PSR_CPL0_BIT)
-#define IA64_PSR_IS (__IA64_UL(1) << IA64_PSR_IS_BIT)
-#define IA64_PSR_MC (__IA64_UL(1) << IA64_PSR_MC_BIT)
-#define IA64_PSR_IT (__IA64_UL(1) << IA64_PSR_IT_BIT)
-#define IA64_PSR_ID (__IA64_UL(1) << IA64_PSR_ID_BIT)
-#define IA64_PSR_DA (__IA64_UL(1) << IA64_PSR_DA_BIT)
-#define IA64_PSR_DD (__IA64_UL(1) << IA64_PSR_DD_BIT)
-#define IA64_PSR_SS (__IA64_UL(1) << IA64_PSR_SS_BIT)
-#define IA64_PSR_RI (__IA64_UL(3) << IA64_PSR_RI_BIT)
-#define IA64_PSR_ED (__IA64_UL(1) << IA64_PSR_ED_BIT)
-#define IA64_PSR_BN (__IA64_UL(1) << IA64_PSR_BN_BIT)
-#define IA64_PSR_IA (__IA64_UL(1) << IA64_PSR_IA_BIT)
-
-/* User mask bits: */
-#define IA64_PSR_UM (IA64_PSR_BE | IA64_PSR_UP | IA64_PSR_AC | IA64_PSR_MFL | IA64_PSR_MFH)
-
-/* Default Control Register */
-#define IA64_DCR_PP_BIT 0 /* privileged performance monitor default */
-#define IA64_DCR_BE_BIT 1 /* big-endian default */
-#define IA64_DCR_LC_BIT 2 /* ia32 lock-check enable */
-#define IA64_DCR_DM_BIT 8 /* defer TLB miss faults */
-#define IA64_DCR_DP_BIT 9 /* defer page-not-present faults */
-#define IA64_DCR_DK_BIT 10 /* defer key miss faults */
-#define IA64_DCR_DX_BIT 11 /* defer key permission faults */
-#define IA64_DCR_DR_BIT 12 /* defer access right faults */
-#define IA64_DCR_DA_BIT 13 /* defer access bit faults */
-#define IA64_DCR_DD_BIT 14 /* defer debug faults */
-
-#define IA64_DCR_PP (__IA64_UL(1) << IA64_DCR_PP_BIT)
-#define IA64_DCR_BE (__IA64_UL(1) << IA64_DCR_BE_BIT)
-#define IA64_DCR_LC (__IA64_UL(1) << IA64_DCR_LC_BIT)
-#define IA64_DCR_DM (__IA64_UL(1) << IA64_DCR_DM_BIT)
-#define IA64_DCR_DP (__IA64_UL(1) << IA64_DCR_DP_BIT)
-#define IA64_DCR_DK (__IA64_UL(1) << IA64_DCR_DK_BIT)
-#define IA64_DCR_DX (__IA64_UL(1) << IA64_DCR_DX_BIT)
-#define IA64_DCR_DR (__IA64_UL(1) << IA64_DCR_DR_BIT)
-#define IA64_DCR_DA (__IA64_UL(1) << IA64_DCR_DA_BIT)
-#define IA64_DCR_DD (__IA64_UL(1) << IA64_DCR_DD_BIT)
-
-/* Interrupt Status Register */
-#define IA64_ISR_X_BIT 32 /* execute access */
-#define IA64_ISR_W_BIT 33 /* write access */
-#define IA64_ISR_R_BIT 34 /* read access */
-#define IA64_ISR_NA_BIT 35 /* non-access */
-#define IA64_ISR_SP_BIT 36 /* speculative load exception */
-#define IA64_ISR_RS_BIT 37 /* mandatory register-stack exception */
-#define IA64_ISR_IR_BIT 38 /* invalid register frame exception */
-#define IA64_ISR_CODE_MASK 0xf
-
-#define IA64_ISR_X (__IA64_UL(1) << IA64_ISR_X_BIT)
-#define IA64_ISR_W (__IA64_UL(1) << IA64_ISR_W_BIT)
-#define IA64_ISR_R (__IA64_UL(1) << IA64_ISR_R_BIT)
-#define IA64_ISR_NA (__IA64_UL(1) << IA64_ISR_NA_BIT)
-#define IA64_ISR_SP (__IA64_UL(1) << IA64_ISR_SP_BIT)
-#define IA64_ISR_RS (__IA64_UL(1) << IA64_ISR_RS_BIT)
-#define IA64_ISR_IR (__IA64_UL(1) << IA64_ISR_IR_BIT)
-
-/* ISR code field for non-access instructions */
-#define IA64_ISR_CODE_TPA 0
-#define IA64_ISR_CODE_FC 1
-#define IA64_ISR_CODE_PROBE 2
-#define IA64_ISR_CODE_TAK 3
-#define IA64_ISR_CODE_LFETCH 4
-#define IA64_ISR_CODE_PROBEF 5
-
-#endif /* _ASM_IA64_kREGS_H */
diff --git a/arch/ia64/include/asm/libata-portmap.h b/arch/ia64/include/asm/libata-portmap.h
deleted file mode 100644
index 757f84e5dc6e..000000000000
--- a/arch/ia64/include/asm/libata-portmap.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_IA64_LIBATA_PORTMAP_H
-#define __ASM_IA64_LIBATA_PORTMAP_H
-
-#define ATA_PRIMARY_IRQ(dev) isa_irq_to_vector(14)
-
-#define ATA_SECONDARY_IRQ(dev) isa_irq_to_vector(15)
-
-#endif
diff --git a/arch/ia64/include/asm/linkage.h b/arch/ia64/include/asm/linkage.h
deleted file mode 100644
index 5178af560925..000000000000
--- a/arch/ia64/include/asm/linkage.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_LINKAGE_H
-#define __ASM_LINKAGE_H
-
-#ifndef __ASSEMBLY__
-
-#define asmlinkage CPP_ASMLINKAGE __attribute__((syscall_linkage))
-
-#else
-
-#include <asm/asmmacro.h>
-
-#endif
-
-#define cond_syscall(x) asm(".weak\t" #x "#\n" #x "#\t=\tsys_ni_syscall#")
-#define SYSCALL_ALIAS(alias, name) \
- asm ( #alias "# = " #name "#\n\t.globl " #alias "#")
-
-#endif
diff --git a/arch/ia64/include/asm/local.h b/arch/ia64/include/asm/local.h
deleted file mode 100644
index c11c530f74d0..000000000000
--- a/arch/ia64/include/asm/local.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local.h>
diff --git a/arch/ia64/include/asm/mca.h b/arch/ia64/include/asm/mca.h
deleted file mode 100644
index 05805249296c..000000000000
--- a/arch/ia64/include/asm/mca.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * File: mca.h
- * Purpose: Machine check handling specific defines
- *
- * Copyright (C) 1999, 2004 Silicon Graphics, Inc.
- * Copyright (C) Vijay Chander <vijay@engr.sgi.com>
- * Copyright (C) Srinivasa Thirumalachar <sprasad@engr.sgi.com>
- * Copyright (C) Russ Anderson <rja@sgi.com>
- */
-
-#ifndef _ASM_IA64_MCA_H
-#define _ASM_IA64_MCA_H
-
-#if !defined(__ASSEMBLY__)
-
-#include <linux/percpu.h>
-#include <linux/threads.h>
-#include <linux/types.h>
-#include <asm/ptrace.h>
-
-#define IA64_MCA_RENDEZ_TIMEOUT (20 * 1000) /* value in milliseconds - 20 seconds */
-
-typedef struct ia64_fptr {
- unsigned long fp;
- unsigned long gp;
-} ia64_fptr_t;
-
-typedef union cmcv_reg_u {
- u64 cmcv_regval;
- struct {
- u64 cmcr_vector : 8;
- u64 cmcr_reserved1 : 4;
- u64 cmcr_ignored1 : 1;
- u64 cmcr_reserved2 : 3;
- u64 cmcr_mask : 1;
- u64 cmcr_ignored2 : 47;
- } cmcv_reg_s;
-
-} cmcv_reg_t;
-
-#define cmcv_mask cmcv_reg_s.cmcr_mask
-#define cmcv_vector cmcv_reg_s.cmcr_vector
-
-enum {
- IA64_MCA_RENDEZ_CHECKIN_NOTDONE = 0x0,
- IA64_MCA_RENDEZ_CHECKIN_DONE = 0x1,
- IA64_MCA_RENDEZ_CHECKIN_INIT = 0x2,
- IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA = 0x3,
-};
-
-/* Information maintained by the MC infrastructure */
-typedef struct ia64_mc_info_s {
- u64 imi_mca_handler;
- size_t imi_mca_handler_size;
- u64 imi_monarch_init_handler;
- size_t imi_monarch_init_handler_size;
- u64 imi_slave_init_handler;
- size_t imi_slave_init_handler_size;
- u8 imi_rendez_checkin[NR_CPUS];
-
-} ia64_mc_info_t;
-
-/* Handover state from SAL to OS and vice versa, for both MCA and INIT events.
- * Besides the handover state, it also contains some saved registers from the
- * time of the event.
- * Note: mca_asm.S depends on the precise layout of this structure.
- */
-
-struct ia64_sal_os_state {
-
- /* SAL to OS */
- unsigned long os_gp; /* GP of the os registered with the SAL, physical */
- unsigned long pal_proc; /* PAL_PROC entry point, physical */
- unsigned long sal_proc; /* SAL_PROC entry point, physical */
- unsigned long rv_rc; /* MCA - Rendezvous state, INIT - reason code */
- unsigned long proc_state_param; /* from R18 */
- unsigned long monarch; /* 1 for a monarch event, 0 for a slave */
-
- /* common */
- unsigned long sal_ra; /* Return address in SAL, physical */
- unsigned long sal_gp; /* GP of the SAL - physical */
- struct pal_min_state_area *pal_min_state; /* from R17. physical in asm, virtual in C */
- /* Previous values of IA64_KR(CURRENT) and IA64_KR(CURRENT_STACK).
- * Note: if the MCA/INIT recovery code wants to resume to a new context
- * then it must change these values to reflect the new kernel stack.
- */
- unsigned long prev_IA64_KR_CURRENT; /* previous value of IA64_KR(CURRENT) */
- unsigned long prev_IA64_KR_CURRENT_STACK;
- struct task_struct *prev_task; /* previous task, NULL if it is not useful */
- /* Some interrupt registers are not saved in minstate, pt_regs or
- * switch_stack. Because MCA/INIT can occur when interrupts are
- * disabled, we need to save the additional interrupt registers over
- * MCA/INIT and resume.
- */
- unsigned long isr;
- unsigned long ifa;
- unsigned long itir;
- unsigned long iipa;
- unsigned long iim;
- unsigned long iha;
-
- /* OS to SAL */
- unsigned long os_status; /* OS status to SAL, enum below */
- unsigned long context; /* 0 if return to same context
- 1 if return to new context */
-
- /* I-resources */
- unsigned long iip;
- unsigned long ipsr;
- unsigned long ifs;
-};
-
-enum {
- IA64_MCA_CORRECTED = 0x0, /* Error has been corrected by OS_MCA */
- IA64_MCA_WARM_BOOT = -1, /* Warm boot of the system need from SAL */
- IA64_MCA_COLD_BOOT = -2, /* Cold boot of the system need from SAL */
- IA64_MCA_HALT = -3 /* System to be halted by SAL */
-};
-
-enum {
- IA64_INIT_RESUME = 0x0, /* Resume after return from INIT */
- IA64_INIT_WARM_BOOT = -1, /* Warm boot of the system need from SAL */
-};
-
-enum {
- IA64_MCA_SAME_CONTEXT = 0x0, /* SAL to return to same context */
- IA64_MCA_NEW_CONTEXT = -1 /* SAL to return to new context */
-};
-
-/* Per-CPU MCA state that is too big for normal per-CPU variables. */
-
-struct ia64_mca_cpu {
- u64 mca_stack[KERNEL_STACK_SIZE/8];
- u64 init_stack[KERNEL_STACK_SIZE/8];
-};
-
-/* Array of physical addresses of each CPU's MCA area. */
-extern unsigned long __per_cpu_mca[NR_CPUS];
-
-extern int cpe_vector;
-extern int ia64_cpe_irq;
-extern void ia64_mca_init(void);
-extern void ia64_mca_irq_init(void);
-extern void ia64_mca_cpu_init(void *);
-extern void ia64_os_mca_dispatch(void);
-extern void ia64_os_mca_dispatch_end(void);
-extern void ia64_mca_ucmc_handler(struct pt_regs *, struct ia64_sal_os_state *);
-extern void ia64_init_handler(struct pt_regs *,
- struct switch_stack *,
- struct ia64_sal_os_state *);
-extern void ia64_os_init_on_kdump(void);
-extern void ia64_monarch_init_handler(void);
-extern void ia64_slave_init_handler(void);
-extern void ia64_mca_cmc_vector_setup(void);
-extern int ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *));
-extern void ia64_unreg_MCA_extension(void);
-extern unsigned long ia64_get_rnat(unsigned long *);
-extern void ia64_set_psr_mc(void);
-extern void ia64_mca_printk(const char * fmt, ...)
- __attribute__ ((format (printf, 1, 2)));
-
-struct ia64_mca_notify_die {
- struct ia64_sal_os_state *sos;
- int *monarch_cpu;
- int *data;
-};
-
-DECLARE_PER_CPU(u64, ia64_mca_pal_base);
-
-#else /* __ASSEMBLY__ */
-
-#define IA64_MCA_CORRECTED 0x0 /* Error has been corrected by OS_MCA */
-#define IA64_MCA_WARM_BOOT -1 /* Warm boot of the system need from SAL */
-#define IA64_MCA_COLD_BOOT -2 /* Cold boot of the system need from SAL */
-#define IA64_MCA_HALT -3 /* System to be halted by SAL */
-
-#define IA64_INIT_RESUME 0x0 /* Resume after return from INIT */
-#define IA64_INIT_WARM_BOOT -1 /* Warm boot of the system need from SAL */
-
-#define IA64_MCA_SAME_CONTEXT 0x0 /* SAL to return to same context */
-#define IA64_MCA_NEW_CONTEXT -1 /* SAL to return to new context */
-
-#endif /* !__ASSEMBLY__ */
-#endif /* _ASM_IA64_MCA_H */
diff --git a/arch/ia64/include/asm/mca_asm.h b/arch/ia64/include/asm/mca_asm.h
deleted file mode 100644
index e3ab1f41f1c3..000000000000
--- a/arch/ia64/include/asm/mca_asm.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * File: mca_asm.h
- * Purpose: Machine check handling specific defines
- *
- * Copyright (C) 1999 Silicon Graphics, Inc.
- * Copyright (C) Vijay Chander <vijay@engr.sgi.com>
- * Copyright (C) Srinivasa Thirumalachar <sprasad@engr.sgi.com>
- * Copyright (C) 2000 Hewlett-Packard Co.
- * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2002 Intel Corp.
- * Copyright (C) 2002 Jenna Hall <jenna.s.hall@intel.com>
- * Copyright (C) 2005 Silicon Graphics, Inc
- * Copyright (C) 2005 Keith Owens <kaos@sgi.com>
- */
-#ifndef _ASM_IA64_MCA_ASM_H
-#define _ASM_IA64_MCA_ASM_H
-
-#include <asm/percpu.h>
-
-#define PSR_IC 13
-#define PSR_I 14
-#define PSR_DT 17
-#define PSR_RT 27
-#define PSR_MC 35
-#define PSR_IT 36
-#define PSR_BN 44
-
-/*
- * This macro converts a instruction virtual address to a physical address
- * Right now for simulation purposes the virtual addresses are
- * direct mapped to physical addresses.
- * 1. Lop off bits 61 thru 63 in the virtual address
- */
-#define INST_VA_TO_PA(addr) \
- dep addr = 0, addr, 61, 3
-/*
- * This macro converts a data virtual address to a physical address
- * Right now for simulation purposes the virtual addresses are
- * direct mapped to physical addresses.
- * 1. Lop off bits 61 thru 63 in the virtual address
- */
-#define DATA_VA_TO_PA(addr) \
- tpa addr = addr
-/*
- * This macro converts a data physical address to a virtual address
- * Right now for simulation purposes the virtual addresses are
- * direct mapped to physical addresses.
- * 1. Put 0x7 in bits 61 thru 63.
- */
-#define DATA_PA_TO_VA(addr,temp) \
- mov temp = 0x7 ;; \
- dep addr = temp, addr, 61, 3
-
-#define GET_THIS_PADDR(reg, var) \
- mov reg = IA64_KR(PER_CPU_DATA);; \
- addl reg = THIS_CPU(var), reg
-
-/*
- * This macro jumps to the instruction at the given virtual address
- * and starts execution in physical mode with all the address
- * translations turned off.
- * 1. Save the current psr
- * 2. Make sure that all the upper 32 bits are off
- *
- * 3. Clear the interrupt enable and interrupt state collection bits
- * in the psr before updating the ipsr and iip.
- *
- * 4. Turn off the instruction, data and rse translation bits of the psr
- * and store the new value into ipsr
- * Also make sure that the interrupts are disabled.
- * Ensure that we are in little endian mode.
- * [psr.{rt, it, dt, i, be} = 0]
- *
- * 5. Get the physical address corresponding to the virtual address
- * of the next instruction bundle and put it in iip.
- * (Using magic numbers 24 and 40 in the deposint instruction since
- * the IA64_SDK code directly maps to lower 24bits as physical address
- * from a virtual address).
- *
- * 6. Do an rfi to move the values from ipsr to psr and iip to ip.
- */
-#define PHYSICAL_MODE_ENTER(temp1, temp2, start_addr, old_psr) \
- mov old_psr = psr; \
- ;; \
- dep old_psr = 0, old_psr, 32, 32; \
- \
- mov ar.rsc = 0 ; \
- ;; \
- srlz.d; \
- mov temp2 = ar.bspstore; \
- ;; \
- DATA_VA_TO_PA(temp2); \
- ;; \
- mov temp1 = ar.rnat; \
- ;; \
- mov ar.bspstore = temp2; \
- ;; \
- mov ar.rnat = temp1; \
- mov temp1 = psr; \
- mov temp2 = psr; \
- ;; \
- \
- dep temp2 = 0, temp2, PSR_IC, 2; \
- ;; \
- mov psr.l = temp2; \
- ;; \
- srlz.d; \
- dep temp1 = 0, temp1, 32, 32; \
- ;; \
- dep temp1 = 0, temp1, PSR_IT, 1; \
- ;; \
- dep temp1 = 0, temp1, PSR_DT, 1; \
- ;; \
- dep temp1 = 0, temp1, PSR_RT, 1; \
- ;; \
- dep temp1 = 0, temp1, PSR_I, 1; \
- ;; \
- dep temp1 = 0, temp1, PSR_IC, 1; \
- ;; \
- dep temp1 = -1, temp1, PSR_MC, 1; \
- ;; \
- mov cr.ipsr = temp1; \
- ;; \
- LOAD_PHYSICAL(p0, temp2, start_addr); \
- ;; \
- mov cr.iip = temp2; \
- mov cr.ifs = r0; \
- DATA_VA_TO_PA(sp); \
- DATA_VA_TO_PA(gp); \
- ;; \
- srlz.i; \
- ;; \
- nop 1; \
- nop 2; \
- nop 1; \
- nop 2; \
- rfi; \
- ;;
-
-/*
- * This macro jumps to the instruction at the given virtual address
- * and starts execution in virtual mode with all the address
- * translations turned on.
- * 1. Get the old saved psr
- *
- * 2. Clear the interrupt state collection bit in the current psr.
- *
- * 3. Set the instruction translation bit back in the old psr
- * Note we have to do this since we are right now saving only the
- * lower 32-bits of old psr.(Also the old psr has the data and
- * rse translation bits on)
- *
- * 4. Set ipsr to this old_psr with "it" bit set and "bn" = 1.
- *
- * 5. Reset the current thread pointer (r13).
- *
- * 6. Set iip to the virtual address of the next instruction bundle.
- *
- * 7. Do an rfi to move ipsr to psr and iip to ip.
- */
-
-#define VIRTUAL_MODE_ENTER(temp1, temp2, start_addr, old_psr) \
- mov temp2 = psr; \
- ;; \
- mov old_psr = temp2; \
- ;; \
- dep temp2 = 0, temp2, PSR_IC, 2; \
- ;; \
- mov psr.l = temp2; \
- mov ar.rsc = 0; \
- ;; \
- srlz.d; \
- mov r13 = ar.k6; \
- mov temp2 = ar.bspstore; \
- ;; \
- DATA_PA_TO_VA(temp2,temp1); \
- ;; \
- mov temp1 = ar.rnat; \
- ;; \
- mov ar.bspstore = temp2; \
- ;; \
- mov ar.rnat = temp1; \
- ;; \
- mov temp1 = old_psr; \
- ;; \
- mov temp2 = 1; \
- ;; \
- dep temp1 = temp2, temp1, PSR_IC, 1; \
- ;; \
- dep temp1 = temp2, temp1, PSR_IT, 1; \
- ;; \
- dep temp1 = temp2, temp1, PSR_DT, 1; \
- ;; \
- dep temp1 = temp2, temp1, PSR_RT, 1; \
- ;; \
- dep temp1 = temp2, temp1, PSR_BN, 1; \
- ;; \
- \
- mov cr.ipsr = temp1; \
- movl temp2 = start_addr; \
- ;; \
- mov cr.iip = temp2; \
- movl gp = __gp \
- ;; \
- DATA_PA_TO_VA(sp, temp1); \
- srlz.i; \
- ;; \
- nop 1; \
- nop 2; \
- nop 1; \
- rfi \
- ;;
-
-/*
- * The MCA and INIT stacks in struct ia64_mca_cpu look like normal kernel
- * stacks, except that the SAL/OS state and a switch_stack are stored near the
- * top of the MCA/INIT stack. To support concurrent entry to MCA or INIT, as
- * well as MCA over INIT, each event needs its own SAL/OS state. All entries
- * are 16 byte aligned.
- *
- * +---------------------------+
- * | pt_regs |
- * +---------------------------+
- * | switch_stack |
- * +---------------------------+
- * | SAL/OS state |
- * +---------------------------+
- * | 16 byte scratch area |
- * +---------------------------+ <-------- SP at start of C MCA handler
- * | ..... |
- * +---------------------------+
- * | RBS for MCA/INIT handler |
- * +---------------------------+
- * | struct task for MCA/INIT |
- * +---------------------------+ <-------- Bottom of MCA/INIT stack
- */
-
-#define ALIGN16(x) ((x)&~15)
-#define MCA_PT_REGS_OFFSET ALIGN16(KERNEL_STACK_SIZE-IA64_PT_REGS_SIZE)
-#define MCA_SWITCH_STACK_OFFSET ALIGN16(MCA_PT_REGS_OFFSET-IA64_SWITCH_STACK_SIZE)
-#define MCA_SOS_OFFSET ALIGN16(MCA_SWITCH_STACK_OFFSET-IA64_SAL_OS_STATE_SIZE)
-#define MCA_SP_OFFSET ALIGN16(MCA_SOS_OFFSET-16)
-
-#endif /* _ASM_IA64_MCA_ASM_H */
diff --git a/arch/ia64/include/asm/meminit.h b/arch/ia64/include/asm/meminit.h
deleted file mode 100644
index f1d5bf2ba847..000000000000
--- a/arch/ia64/include/asm/meminit.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef meminit_h
-#define meminit_h
-
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-
-/*
- * Entries defined so far:
- * - boot param structure itself
- * - memory map
- * - initrd (optional)
- * - command line string
- * - kernel code & data
- * - crash dumping code reserved region
- * - Kernel memory map built from EFI memory map
- * - ELF core header
- *
- * More could be added if necessary
- */
-#define IA64_MAX_RSVD_REGIONS 9
-
-struct rsvd_region {
- u64 start; /* virtual address of beginning of element */
- u64 end; /* virtual address of end of element + 1 */
-};
-
-extern struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1];
-
-extern void find_memory (void);
-extern void reserve_memory (void);
-extern void find_initrd (void);
-extern int filter_rsvd_memory (u64 start, u64 end, void *arg);
-extern int filter_memory (u64 start, u64 end, void *arg);
-extern unsigned long efi_memmap_init(u64 *s, u64 *e);
-extern int find_max_min_low_pfn (u64, u64, void *);
-
-extern unsigned long vmcore_find_descriptor_size(unsigned long address);
-
-/*
- * For rounding an address to the next IA64_GRANULE_SIZE or order
- */
-#define GRANULEROUNDDOWN(n) ((n) & ~(IA64_GRANULE_SIZE-1))
-#define GRANULEROUNDUP(n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1))
-
-#ifdef CONFIG_NUMA
- extern void call_pernode_memory (unsigned long start, unsigned long len, void *func);
-#else
-# define call_pernode_memory(start, len, func) (*func)(start, len, 0)
-#endif
-
-#define IGNORE_PFN0 1 /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */
-
-extern int register_active_ranges(u64 start, u64 len, int nid);
-
-#endif /* meminit_h */
diff --git a/arch/ia64/include/asm/mman.h b/arch/ia64/include/asm/mman.h
deleted file mode 100644
index 15cf100add0e..000000000000
--- a/arch/ia64/include/asm/mman.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Based on <asm-i386/mman.h>.
- *
- * Modified 1998-2000, 2002
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-#ifndef _ASM_IA64_MMAN_H
-#define _ASM_IA64_MMAN_H
-
-#include <uapi/asm/mman.h>
-
-#ifndef __ASSEMBLY__
-#define arch_mmap_check ia64_mmap_check
-int ia64_mmap_check(unsigned long addr, unsigned long len,
- unsigned long flags);
-#endif
-#endif /* _ASM_IA64_MMAN_H */
diff --git a/arch/ia64/include/asm/mmiowb.h b/arch/ia64/include/asm/mmiowb.h
deleted file mode 100644
index d67aab4ea3b4..000000000000
--- a/arch/ia64/include/asm/mmiowb.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#ifndef _ASM_IA64_MMIOWB_H
-#define _ASM_IA64_MMIOWB_H
-
-/**
- * mmiowb - I/O write barrier
- *
- * Ensure ordering of I/O space writes. This will make sure that writes
- * following the barrier will arrive after all previous writes. For most
- * ia64 platforms, this is a simple 'mf.a' instruction.
- */
-#define mmiowb() ia64_mfa()
-
-#include <asm-generic/mmiowb.h>
-
-#endif /* _ASM_IA64_MMIOWB_H */
diff --git a/arch/ia64/include/asm/mmu.h b/arch/ia64/include/asm/mmu.h
deleted file mode 100644
index f75f44f531c2..000000000000
--- a/arch/ia64/include/asm/mmu.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __MMU_H
-#define __MMU_H
-
-/*
- * Type for a context number. We declare it volatile to ensure proper
- * ordering when it's accessed outside of spinlock'd critical sections
- * (e.g., as done in activate_mm() and init_new_context()).
- */
-typedef volatile unsigned long mm_context_t;
-
-typedef unsigned long nv_mm_context_t;
-
-#endif
diff --git a/arch/ia64/include/asm/mmu_context.h b/arch/ia64/include/asm/mmu_context.h
deleted file mode 100644
index 06257e355d00..000000000000
--- a/arch/ia64/include/asm/mmu_context.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_MMU_CONTEXT_H
-#define _ASM_IA64_MMU_CONTEXT_H
-
-/*
- * Copyright (C) 1998-2002 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-/*
- * Routines to manage the allocation of task context numbers. Task context
- * numbers are used to reduce or eliminate the need to perform TLB flushes
- * due to context switches. Context numbers are implemented using ia-64
- * region ids. Since the IA-64 TLB does not consider the region number when
- * performing a TLB lookup, we need to assign a unique region id to each
- * region in a process. We use the least significant three bits in aregion
- * id for this purpose.
- */
-
-#define IA64_REGION_ID_KERNEL 0 /* the kernel's region id (tlb.c depends on this being 0) */
-
-#define ia64_rid(ctx,addr) (((ctx) << 3) | (addr >> 61))
-
-# include <asm/page.h>
-# ifndef __ASSEMBLY__
-
-#include <linux/compiler.h>
-#include <linux/percpu.h>
-#include <linux/sched.h>
-#include <linux/mm_types.h>
-#include <linux/spinlock.h>
-
-#include <asm/processor.h>
-#include <asm-generic/mm_hooks.h>
-
-struct ia64_ctx {
- spinlock_t lock;
- unsigned int next; /* next context number to use */
- unsigned int limit; /* available free range */
- unsigned int max_ctx; /* max. context value supported by all CPUs */
- /* call wrap_mmu_context when next >= max */
- unsigned long *bitmap; /* bitmap size is max_ctx+1 */
- unsigned long *flushmap;/* pending rid to be flushed */
-};
-
-extern struct ia64_ctx ia64_ctx;
-DECLARE_PER_CPU(u8, ia64_need_tlb_flush);
-
-extern void mmu_context_init (void);
-extern void wrap_mmu_context (struct mm_struct *mm);
-
-/*
- * When the context counter wraps around all TLBs need to be flushed because
- * an old context number might have been reused. This is signalled by the
- * ia64_need_tlb_flush per-CPU variable, which is checked in the routine
- * below. Called by activate_mm(). <efocht@ess.nec.de>
- */
-static inline void
-delayed_tlb_flush (void)
-{
- extern void local_flush_tlb_all (void);
- unsigned long flags;
-
- if (unlikely(__ia64_per_cpu_var(ia64_need_tlb_flush))) {
- spin_lock_irqsave(&ia64_ctx.lock, flags);
- if (__ia64_per_cpu_var(ia64_need_tlb_flush)) {
- local_flush_tlb_all();
- __ia64_per_cpu_var(ia64_need_tlb_flush) = 0;
- }
- spin_unlock_irqrestore(&ia64_ctx.lock, flags);
- }
-}
-
-static inline nv_mm_context_t
-get_mmu_context (struct mm_struct *mm)
-{
- unsigned long flags;
- nv_mm_context_t context = mm->context;
-
- if (likely(context))
- goto out;
-
- spin_lock_irqsave(&ia64_ctx.lock, flags);
- /* re-check, now that we've got the lock: */
- context = mm->context;
- if (context == 0) {
- cpumask_clear(mm_cpumask(mm));
- if (ia64_ctx.next >= ia64_ctx.limit) {
- ia64_ctx.next = find_next_zero_bit(ia64_ctx.bitmap,
- ia64_ctx.max_ctx, ia64_ctx.next);
- ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap,
- ia64_ctx.max_ctx, ia64_ctx.next);
- if (ia64_ctx.next >= ia64_ctx.max_ctx)
- wrap_mmu_context(mm);
- }
- mm->context = context = ia64_ctx.next++;
- __set_bit(context, ia64_ctx.bitmap);
- }
- spin_unlock_irqrestore(&ia64_ctx.lock, flags);
-out:
- /*
- * Ensure we're not starting to use "context" before any old
- * uses of it are gone from our TLB.
- */
- delayed_tlb_flush();
-
- return context;
-}
-
-/*
- * Initialize context number to some sane value. MM is guaranteed to be a
- * brand-new address-space, so no TLB flushing is needed, ever.
- */
-#define init_new_context init_new_context
-static inline int
-init_new_context (struct task_struct *p, struct mm_struct *mm)
-{
- mm->context = 0;
- return 0;
-}
-
-static inline void
-reload_context (nv_mm_context_t context)
-{
- unsigned long rid;
- unsigned long rid_incr = 0;
- unsigned long rr0, rr1, rr2, rr3, rr4;
-
-#ifdef CONFIG_HUGETLB_PAGE
- unsigned long old_rr4;
- old_rr4 = ia64_get_rr(RGN_BASE(RGN_HPAGE));
-#endif
- rid = context << 3; /* make space for encoding the region number */
- rid_incr = 1 << 8;
-
- /* encode the region id, preferred page size, and VHPT enable bit: */
- rr0 = (rid << 8) | (PAGE_SHIFT << 2) | 1;
- rr1 = rr0 + 1*rid_incr;
- rr2 = rr0 + 2*rid_incr;
- rr3 = rr0 + 3*rid_incr;
- rr4 = rr0 + 4*rid_incr;
-#ifdef CONFIG_HUGETLB_PAGE
- rr4 = (rr4 & (~(0xfcUL))) | (old_rr4 & 0xfc);
-
-# if RGN_HPAGE != 4
-# error "reload_context assumes RGN_HPAGE is 4"
-# endif
-#endif
-
- ia64_set_rr0_to_rr4(rr0, rr1, rr2, rr3, rr4);
- ia64_srlz_i(); /* srlz.i implies srlz.d */
-}
-
-/*
- * Must be called with preemption off
- */
-static inline void
-activate_context (struct mm_struct *mm)
-{
- nv_mm_context_t context;
-
- do {
- context = get_mmu_context(mm);
- if (!cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm)))
- cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
- reload_context(context);
- /*
- * in the unlikely event of a TLB-flush by another thread,
- * redo the load.
- */
- } while (unlikely(context != mm->context));
-}
-
-/*
- * Switch from address space PREV to address space NEXT.
- */
-#define activate_mm activate_mm
-static inline void
-activate_mm (struct mm_struct *prev, struct mm_struct *next)
-{
- /*
- * We may get interrupts here, but that's OK because interrupt
- * handlers cannot touch user-space.
- */
- ia64_set_kr(IA64_KR_PT_BASE, __pa(next->pgd));
- activate_context(next);
-}
-
-#define switch_mm(prev_mm,next_mm,next_task) activate_mm(prev_mm, next_mm)
-
-#include <asm-generic/mmu_context.h>
-
-# endif /* ! __ASSEMBLY__ */
-#endif /* _ASM_IA64_MMU_CONTEXT_H */
diff --git a/arch/ia64/include/asm/mmzone.h b/arch/ia64/include/asm/mmzone.h
deleted file mode 100644
index 767201f66c93..000000000000
--- a/arch/ia64/include/asm/mmzone.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 2000,2003 Silicon Graphics, Inc. All rights reserved.
- * Copyright (c) 2002 NEC Corp.
- * Copyright (c) 2002 Erich Focht <efocht@ess.nec.de>
- * Copyright (c) 2002 Kimio Suganuma <k-suganuma@da.jp.nec.com>
- */
-#ifndef _ASM_IA64_MMZONE_H
-#define _ASM_IA64_MMZONE_H
-
-#include <linux/numa.h>
-#include <asm/page.h>
-#include <asm/meminit.h>
-
-#ifdef CONFIG_NUMA
-
-static inline int pfn_to_nid(unsigned long pfn)
-{
- extern int paddr_to_nid(unsigned long);
- int nid = paddr_to_nid(pfn << PAGE_SHIFT);
- if (nid < 0)
- return 0;
- else
- return nid;
-}
-
-#define MAX_PHYSNODE_ID 2048
-#endif /* CONFIG_NUMA */
-
-#define NR_NODE_MEMBLKS (MAX_NUMNODES * 4)
-
-#endif /* _ASM_IA64_MMZONE_H */
diff --git a/arch/ia64/include/asm/module.h b/arch/ia64/include/asm/module.h
deleted file mode 100644
index 7271b9c5fc76..000000000000
--- a/arch/ia64/include/asm/module.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_MODULE_H
-#define _ASM_IA64_MODULE_H
-
-#include <asm-generic/module.h>
-
-/*
- * IA-64-specific support for kernel module loader.
- *
- * Copyright (C) 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-struct elf64_shdr; /* forward declration */
-
-struct mod_arch_specific {
- /* Used only at module load time. */
- struct elf64_shdr *core_plt; /* core PLT section */
- struct elf64_shdr *init_plt; /* init PLT section */
- struct elf64_shdr *got; /* global offset table */
- struct elf64_shdr *opd; /* official procedure descriptors */
- struct elf64_shdr *unwind; /* unwind-table section */
- unsigned long gp; /* global-pointer for module */
- unsigned int next_got_entry; /* index of next available got entry */
-
- /* Used at module run and cleanup time. */
- void *core_unw_table; /* core unwind-table cookie returned by unwinder */
- void *init_unw_table; /* init unwind-table cookie returned by unwinder */
- void *opd_addr; /* symbolize uses .opd to get to actual function */
- unsigned long opd_size;
-};
-
-#define ARCH_SHF_SMALL SHF_IA_64_SHORT
-
-#endif /* _ASM_IA64_MODULE_H */
diff --git a/arch/ia64/include/asm/module.lds.h b/arch/ia64/include/asm/module.lds.h
deleted file mode 100644
index eff68f362793..000000000000
--- a/arch/ia64/include/asm/module.lds.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-SECTIONS {
- /* Group unwind sections into a single section: */
- .IA_64.unwind_info : { *(.IA_64.unwind_info*) }
- .IA_64.unwind : { *(.IA_64.unwind*) }
- /*
- * Create place-holder sections to hold the PLTs, GOT, and
- * official procedure-descriptors (.opd).
- */
- .core.plt : { BYTE(0) }
- .init.plt : { BYTE(0) }
- .got : { BYTE(0) }
- .opd : { BYTE(0) }
-}
diff --git a/arch/ia64/include/asm/msidef.h b/arch/ia64/include/asm/msidef.h
deleted file mode 100644
index 18d0e4226748..000000000000
--- a/arch/ia64/include/asm/msidef.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _IA64_MSI_DEF_H
-#define _IA64_MSI_DEF_H
-
-/*
- * Shifts for APIC-based data
- */
-
-#define MSI_DATA_VECTOR_SHIFT 0
-#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT)
-#define MSI_DATA_VECTOR_MASK 0xffffff00
-
-#define MSI_DATA_DELIVERY_MODE_SHIFT 8
-#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_MODE_SHIFT)
-#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_MODE_SHIFT)
-
-#define MSI_DATA_LEVEL_SHIFT 14
-#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT)
-#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT)
-
-#define MSI_DATA_TRIGGER_SHIFT 15
-#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT)
-#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT)
-
-/*
- * Shift/mask fields for APIC-based bus address
- */
-
-#define MSI_ADDR_DEST_ID_SHIFT 4
-#define MSI_ADDR_HEADER 0xfee00000
-
-#define MSI_ADDR_DEST_ID_MASK 0xfff0000f
-#define MSI_ADDR_DEST_ID_CPU(cpu) ((cpu) << MSI_ADDR_DEST_ID_SHIFT)
-
-#define MSI_ADDR_DEST_MODE_SHIFT 2
-#define MSI_ADDR_DEST_MODE_PHYS (0 << MSI_ADDR_DEST_MODE_SHIFT)
-#define MSI_ADDR_DEST_MODE_LOGIC (1 << MSI_ADDR_DEST_MODE_SHIFT)
-
-#define MSI_ADDR_REDIRECTION_SHIFT 3
-#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT)
-#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
-
-#endif/* _IA64_MSI_DEF_H */
diff --git a/arch/ia64/include/asm/native/inst.h b/arch/ia64/include/asm/native/inst.h
deleted file mode 100644
index e08662396029..000000000000
--- a/arch/ia64/include/asm/native/inst.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/******************************************************************************
- * arch/ia64/include/asm/native/inst.h
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- * VA Linux Systems Japan K.K.
- */
-
-#define DO_SAVE_MIN IA64_NATIVE_DO_SAVE_MIN
-
-#define MOV_FROM_IFA(reg) \
- mov reg = cr.ifa
-
-#define MOV_FROM_ITIR(reg) \
- mov reg = cr.itir
-
-#define MOV_FROM_ISR(reg) \
- mov reg = cr.isr
-
-#define MOV_FROM_IHA(reg) \
- mov reg = cr.iha
-
-#define MOV_FROM_IPSR(pred, reg) \
-(pred) mov reg = cr.ipsr
-
-#define MOV_FROM_IIM(reg) \
- mov reg = cr.iim
-
-#define MOV_FROM_IIP(reg) \
- mov reg = cr.iip
-
-#define MOV_FROM_IVR(reg, clob) \
- mov reg = cr.ivr
-
-#define MOV_FROM_PSR(pred, reg, clob) \
-(pred) mov reg = psr
-
-#define MOV_FROM_ITC(pred, pred_clob, reg, clob) \
-(pred) mov reg = ar.itc
-
-#define MOV_TO_IFA(reg, clob) \
- mov cr.ifa = reg
-
-#define MOV_TO_ITIR(pred, reg, clob) \
-(pred) mov cr.itir = reg
-
-#define MOV_TO_IHA(pred, reg, clob) \
-(pred) mov cr.iha = reg
-
-#define MOV_TO_IPSR(pred, reg, clob) \
-(pred) mov cr.ipsr = reg
-
-#define MOV_TO_IFS(pred, reg, clob) \
-(pred) mov cr.ifs = reg
-
-#define MOV_TO_IIP(reg, clob) \
- mov cr.iip = reg
-
-#define MOV_TO_KR(kr, reg, clob0, clob1) \
- mov IA64_KR(kr) = reg
-
-#define ITC_I(pred, reg, clob) \
-(pred) itc.i reg
-
-#define ITC_D(pred, reg, clob) \
-(pred) itc.d reg
-
-#define ITC_I_AND_D(pred_i, pred_d, reg, clob) \
-(pred_i) itc.i reg; \
-(pred_d) itc.d reg
-
-#define THASH(pred, reg0, reg1, clob) \
-(pred) thash reg0 = reg1
-
-#define SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(clob0, clob1) \
- ssm psr.ic | PSR_DEFAULT_BITS \
- ;; \
- srlz.i /* guarantee that interruption collectin is on */ \
- ;;
-
-#define SSM_PSR_IC_AND_SRLZ_D(clob0, clob1) \
- ssm psr.ic \
- ;; \
- srlz.d
-
-#define RSM_PSR_IC(clob) \
- rsm psr.ic
-
-#define SSM_PSR_I(pred, pred_clob, clob) \
-(pred) ssm psr.i
-
-#define RSM_PSR_I(pred, clob0, clob1) \
-(pred) rsm psr.i
-
-#define RSM_PSR_I_IC(clob0, clob1, clob2) \
- rsm psr.i | psr.ic
-
-#define RSM_PSR_DT \
- rsm psr.dt
-
-#define RSM_PSR_BE_I(clob0, clob1) \
- rsm psr.be | psr.i
-
-#define SSM_PSR_DT_AND_SRLZ_I \
- ssm psr.dt \
- ;; \
- srlz.i
-
-#define BSW_0(clob0, clob1, clob2) \
- bsw.0
-
-#define BSW_1(clob0, clob1) \
- bsw.1
-
-#define COVER \
- cover
-
-#define RFI \
- rfi
diff --git a/arch/ia64/include/asm/native/irq.h b/arch/ia64/include/asm/native/irq.h
deleted file mode 100644
index aa74915f8aa2..000000000000
--- a/arch/ia64/include/asm/native/irq.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/******************************************************************************
- * arch/ia64/include/asm/native/irq.h
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- * VA Linux Systems Japan K.K.
- */
-
-#ifndef _ASM_IA64_NATIVE_IRQ_H
-#define _ASM_IA64_NATIVE_IRQ_H
-
-#define NR_VECTORS 256
-
-#if (NR_VECTORS + 32 * NR_CPUS) < 1024
-#define IA64_NATIVE_NR_IRQS (NR_VECTORS + 32 * NR_CPUS)
-#else
-#define IA64_NATIVE_NR_IRQS 1024
-#endif
-
-#endif /* _ASM_IA64_NATIVE_IRQ_H */
diff --git a/arch/ia64/include/asm/native/patchlist.h b/arch/ia64/include/asm/native/patchlist.h
deleted file mode 100644
index f13e7675758c..000000000000
--- a/arch/ia64/include/asm/native/patchlist.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/******************************************************************************
- * arch/ia64/include/asm/native/inst.h
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- * VA Linux Systems Japan K.K.
- */
-
-#define __paravirt_start_gate_fsyscall_patchlist \
- __ia64_native_start_gate_fsyscall_patchlist
-#define __paravirt_end_gate_fsyscall_patchlist \
- __ia64_native_end_gate_fsyscall_patchlist
-#define __paravirt_start_gate_brl_fsys_bubble_down_patchlist \
- __ia64_native_start_gate_brl_fsys_bubble_down_patchlist
-#define __paravirt_end_gate_brl_fsys_bubble_down_patchlist \
- __ia64_native_end_gate_brl_fsys_bubble_down_patchlist
-#define __paravirt_start_gate_vtop_patchlist \
- __ia64_native_start_gate_vtop_patchlist
-#define __paravirt_end_gate_vtop_patchlist \
- __ia64_native_end_gate_vtop_patchlist
-#define __paravirt_start_gate_mckinley_e9_patchlist \
- __ia64_native_start_gate_mckinley_e9_patchlist
-#define __paravirt_end_gate_mckinley_e9_patchlist \
- __ia64_native_end_gate_mckinley_e9_patchlist
diff --git a/arch/ia64/include/asm/nodedata.h b/arch/ia64/include/asm/nodedata.h
deleted file mode 100644
index 2fb337b0e9b7..000000000000
--- a/arch/ia64/include/asm/nodedata.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 2000 Silicon Graphics, Inc. All rights reserved.
- * Copyright (c) 2002 NEC Corp.
- * Copyright (c) 2002 Erich Focht <efocht@ess.nec.de>
- * Copyright (c) 2002 Kimio Suganuma <k-suganuma@da.jp.nec.com>
- */
-#ifndef _ASM_IA64_NODEDATA_H
-#define _ASM_IA64_NODEDATA_H
-
-#include <linux/numa.h>
-
-#include <asm/percpu.h>
-#include <asm/mmzone.h>
-
-#ifdef CONFIG_NUMA
-
-/*
- * Node Data. One of these structures is located on each node of a NUMA system.
- */
-
-struct pglist_data;
-struct ia64_node_data {
- short active_cpu_count;
- short node;
- struct pglist_data *pg_data_ptrs[MAX_NUMNODES];
-};
-
-
-/*
- * Return a pointer to the node_data structure for the executing cpu.
- */
-#define local_node_data (local_cpu_data->node_data)
-
-/*
- * Given a node id, return a pointer to the pg_data_t for the node.
- *
- * NODE_DATA - should be used in all code not related to system
- * initialization. It uses pernode data structures to minimize
- * offnode memory references. However, these structure are not
- * present during boot. This macro can be used once cpu_init
- * completes.
- */
-#define NODE_DATA(nid) (local_node_data->pg_data_ptrs[nid])
-
-/*
- * LOCAL_DATA_ADDR - This is to calculate the address of other node's
- * "local_node_data" at hot-plug phase. The local_node_data
- * is pointed by per_cpu_page. Kernel usually use it for
- * just executing cpu. However, when new node is hot-added,
- * the addresses of local data for other nodes are necessary
- * to update all of them.
- */
-#define LOCAL_DATA_ADDR(pgdat) \
- ((struct ia64_node_data *)((u64)(pgdat) + \
- L1_CACHE_ALIGN(sizeof(struct pglist_data))))
-
-#endif /* CONFIG_NUMA */
-
-#endif /* _ASM_IA64_NODEDATA_H */
diff --git a/arch/ia64/include/asm/numa.h b/arch/ia64/include/asm/numa.h
deleted file mode 100644
index c5c253cb9bd6..000000000000
--- a/arch/ia64/include/asm/numa.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * This file contains NUMA specific prototypes and definitions.
- *
- * 2002/08/05 Erich Focht <efocht@ess.nec.de>
- *
- */
-#ifndef _ASM_IA64_NUMA_H
-#define _ASM_IA64_NUMA_H
-
-
-#ifdef CONFIG_NUMA
-
-#include <linux/cache.h>
-#include <linux/cpumask.h>
-#include <linux/numa.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-
-#include <asm/mmzone.h>
-
-extern u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
-extern cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
-extern pg_data_t *pgdat_list[MAX_NUMNODES];
-
-/* Stuff below this line could be architecture independent */
-
-extern int num_node_memblks; /* total number of memory chunks */
-
-/*
- * List of node memory chunks. Filled when parsing SRAT table to
- * obtain information about memory nodes.
-*/
-
-struct node_memblk_s {
- unsigned long start_paddr;
- unsigned long size;
- int nid; /* which logical node contains this chunk? */
- int bank; /* which mem bank on this node */
-};
-
-struct node_cpuid_s {
- u16 phys_id; /* id << 8 | eid */
- int nid; /* logical node containing this CPU */
-};
-
-extern struct node_memblk_s node_memblk[NR_NODE_MEMBLKS];
-extern struct node_cpuid_s node_cpuid[NR_CPUS];
-
-/*
- * ACPI 2.0 SLIT (System Locality Information Table)
- * http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf
- *
- * This is a matrix with "distances" between nodes, they should be
- * proportional to the memory access latency ratios.
- */
-
-extern u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
-#define slit_distance(from,to) (numa_slit[(from) * MAX_NUMNODES + (to)])
-extern int __node_distance(int from, int to);
-#define node_distance(from,to) __node_distance(from, to)
-
-extern int paddr_to_nid(unsigned long paddr);
-
-#define local_nodeid (cpu_to_node_map[smp_processor_id()])
-
-#define numa_off 0
-
-extern void map_cpu_to_node(int cpu, int nid);
-extern void unmap_cpu_from_node(int cpu, int nid);
-extern void numa_clear_node(int cpu);
-
-#else /* !CONFIG_NUMA */
-#define map_cpu_to_node(cpu, nid) do{}while(0)
-#define unmap_cpu_from_node(cpu, nid) do{}while(0)
-#define paddr_to_nid(addr) 0
-#define numa_clear_node(cpu) do { } while (0)
-#endif /* CONFIG_NUMA */
-
-#endif /* _ASM_IA64_NUMA_H */
diff --git a/arch/ia64/include/asm/page.h b/arch/ia64/include/asm/page.h
deleted file mode 100644
index 310b09c3342d..000000000000
--- a/arch/ia64/include/asm/page.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_PAGE_H
-#define _ASM_IA64_PAGE_H
-/*
- * Pagetable related stuff.
- *
- * Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <asm/intrinsics.h>
-#include <asm/types.h>
-
-/*
- * The top three bits of an IA64 address are its Region Number.
- * Different regions are assigned to different purposes.
- */
-#define RGN_SHIFT (61)
-#define RGN_BASE(r) (__IA64_UL_CONST(r)<<RGN_SHIFT)
-#define RGN_BITS (RGN_BASE(-1))
-
-#define RGN_KERNEL 7 /* Identity mapped region */
-#define RGN_UNCACHED 6 /* Identity mapped I/O region */
-#define RGN_GATE 5 /* Gate page, Kernel text, etc */
-#define RGN_HPAGE 4 /* For Huge TLB pages */
-
-/*
- * PAGE_SHIFT determines the actual kernel page size.
- */
-#if defined(CONFIG_IA64_PAGE_SIZE_4KB)
-# define PAGE_SHIFT 12
-#elif defined(CONFIG_IA64_PAGE_SIZE_8KB)
-# define PAGE_SHIFT 13
-#elif defined(CONFIG_IA64_PAGE_SIZE_16KB)
-# define PAGE_SHIFT 14
-#elif defined(CONFIG_IA64_PAGE_SIZE_64KB)
-# define PAGE_SHIFT 16
-#else
-# error Unsupported page size!
-#endif
-
-#define PAGE_SIZE (__IA64_UL_CONST(1) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE - 1))
-
-#define PERCPU_PAGE_SHIFT 18 /* log2() of max. size of per-CPU area */
-#define PERCPU_PAGE_SIZE (__IA64_UL_CONST(1) << PERCPU_PAGE_SHIFT)
-
-
-#ifdef CONFIG_HUGETLB_PAGE
-# define HPAGE_REGION_BASE RGN_BASE(RGN_HPAGE)
-# define HPAGE_SHIFT hpage_shift
-# define HPAGE_SHIFT_DEFAULT 28 /* check ia64 SDM for architecture supported size */
-# define HPAGE_SIZE (__IA64_UL_CONST(1) << HPAGE_SHIFT)
-# define HPAGE_MASK (~(HPAGE_SIZE - 1))
-
-# define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
-#endif /* CONFIG_HUGETLB_PAGE */
-
-#ifdef __ASSEMBLY__
-# define __pa(x) ((x) - PAGE_OFFSET)
-# define __va(x) ((x) + PAGE_OFFSET)
-#else /* !__ASSEMBLY */
-# define STRICT_MM_TYPECHECKS
-
-extern void clear_page (void *page);
-extern void copy_page (void *to, void *from);
-
-/*
- * clear_user_page() and copy_user_page() can't be inline functions because
- * flush_dcache_page() can't be defined until later...
- */
-#define clear_user_page(addr, vaddr, page) \
-do { \
- clear_page(addr); \
- flush_dcache_page(page); \
-} while (0)
-
-#define copy_user_page(to, from, vaddr, page) \
-do { \
- copy_page((to), (from)); \
- flush_dcache_page(page); \
-} while (0)
-
-
-#define vma_alloc_zeroed_movable_folio(vma, vaddr) \
-({ \
- struct folio *folio = vma_alloc_folio( \
- GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr, false); \
- if (folio) \
- flush_dcache_folio(folio); \
- folio; \
-})
-
-#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
-
-#include <asm-generic/memory_model.h>
-
-#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
-#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
-
-typedef union ia64_va {
- struct {
- unsigned long off : 61; /* intra-region offset */
- unsigned long reg : 3; /* region number */
- } f;
- unsigned long l;
- void *p;
-} ia64_va;
-
-/*
- * Note: These macros depend on the fact that PAGE_OFFSET has all
- * region bits set to 1 and all other bits set to zero. They are
- * expressed in this way to ensure they result in a single "dep"
- * instruction.
- */
-#define __pa(x) ({ia64_va _v; _v.l = (long) (x); _v.f.reg = 0; _v.l;})
-#define __va(x) ({ia64_va _v; _v.l = (long) (x); _v.f.reg = -1; _v.p;})
-
-#define REGION_NUMBER(x) ({ia64_va _v; _v.l = (long) (x); _v.f.reg;})
-#define REGION_OFFSET(x) ({ia64_va _v; _v.l = (long) (x); _v.f.off;})
-
-#ifdef CONFIG_HUGETLB_PAGE
-# define htlbpage_to_page(x) (((unsigned long) REGION_NUMBER(x) << 61) \
- | (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT)))
-# define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
-extern unsigned int hpage_shift;
-#endif
-
-static __inline__ int
-get_order (unsigned long size)
-{
- long double d = size - 1;
- long order;
-
- order = ia64_getf_exp(d);
- order = order - PAGE_SHIFT - 0xffff + 1;
- if (order < 0)
- order = 0;
- return order;
-}
-
-#endif /* !__ASSEMBLY__ */
-
-#ifdef STRICT_MM_TYPECHECKS
- /*
- * These are used to make use of C type-checking..
- */
- typedef struct { unsigned long pte; } pte_t;
- typedef struct { unsigned long pmd; } pmd_t;
-#if CONFIG_PGTABLE_LEVELS == 4
- typedef struct { unsigned long pud; } pud_t;
-#endif
- typedef struct { unsigned long pgd; } pgd_t;
- typedef struct { unsigned long pgprot; } pgprot_t;
- typedef struct page *pgtable_t;
-
-# define pte_val(x) ((x).pte)
-# define pmd_val(x) ((x).pmd)
-#if CONFIG_PGTABLE_LEVELS == 4
-# define pud_val(x) ((x).pud)
-#endif
-# define pgd_val(x) ((x).pgd)
-# define pgprot_val(x) ((x).pgprot)
-
-# define __pte(x) ((pte_t) { (x) } )
-# define __pmd(x) ((pmd_t) { (x) } )
-# define __pgprot(x) ((pgprot_t) { (x) } )
-
-#else /* !STRICT_MM_TYPECHECKS */
- /*
- * .. while these make it easier on the compiler
- */
-# ifndef __ASSEMBLY__
- typedef unsigned long pte_t;
- typedef unsigned long pmd_t;
- typedef unsigned long pgd_t;
- typedef unsigned long pgprot_t;
- typedef struct page *pgtable_t;
-# endif
-
-# define pte_val(x) (x)
-# define pmd_val(x) (x)
-# define pgd_val(x) (x)
-# define pgprot_val(x) (x)
-
-# define __pte(x) (x)
-# define __pgd(x) (x)
-# define __pgprot(x) (x)
-#endif /* !STRICT_MM_TYPECHECKS */
-
-#define PAGE_OFFSET RGN_BASE(RGN_KERNEL)
-
-#define VM_DATA_DEFAULT_FLAGS VM_DATA_FLAGS_TSK_EXEC
-
-#define GATE_ADDR RGN_BASE(RGN_GATE)
-
-/*
- * 0xa000000000000000+2*PERCPU_PAGE_SIZE
- * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page)
- */
-#define KERNEL_START (GATE_ADDR+__IA64_UL_CONST(0x100000000))
-#define PERCPU_ADDR (-PERCPU_PAGE_SIZE)
-#define LOAD_OFFSET (KERNEL_START - KERNEL_TR_PAGE_SIZE)
-
-#define __HAVE_ARCH_GATE_AREA 1
-
-#endif /* _ASM_IA64_PAGE_H */
diff --git a/arch/ia64/include/asm/pal.h b/arch/ia64/include/asm/pal.h
deleted file mode 100644
index e6b652f9e45e..000000000000
--- a/arch/ia64/include/asm/pal.h
+++ /dev/null
@@ -1,1827 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_PAL_H
-#define _ASM_IA64_PAL_H
-
-/*
- * Processor Abstraction Layer definitions.
- *
- * This is based on Intel IA-64 Architecture Software Developer's Manual rev 1.0
- * chapter 11 IA-64 Processor Abstraction Layer
- *
- * Copyright (C) 1998-2001 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999 Srinivasa Prasad Thirumalachar <sprasad@sprasad.engr.sgi.com>
- * Copyright (C) 2008 Silicon Graphics, Inc. (SGI)
- *
- * 99/10/01 davidm Make sure we pass zero for reserved parameters.
- * 00/03/07 davidm Updated pal_cache_flush() to be in sync with PAL v2.6.
- * 00/03/23 cfleck Modified processor min-state save area to match updated PAL & SAL info
- * 00/05/24 eranian Updated to latest PAL spec, fix structures bugs, added
- * 00/05/25 eranian Support for stack calls, and static physical calls
- * 00/06/18 eranian Support for stacked physical calls
- * 06/10/26 rja Support for Intel Itanium Architecture Software Developer's
- * Manual Rev 2.2 (Jan 2006)
- */
-
-/*
- * Note that some of these calls use a static-register only calling
- * convention which has nothing to do with the regular calling
- * convention.
- */
-#define PAL_CACHE_FLUSH 1 /* flush i/d cache */
-#define PAL_CACHE_INFO 2 /* get detailed i/d cache info */
-#define PAL_CACHE_INIT 3 /* initialize i/d cache */
-#define PAL_CACHE_SUMMARY 4 /* get summary of cache hierarchy */
-#define PAL_MEM_ATTRIB 5 /* list supported memory attributes */
-#define PAL_PTCE_INFO 6 /* purge TLB info */
-#define PAL_VM_INFO 7 /* return supported virtual memory features */
-#define PAL_VM_SUMMARY 8 /* return summary on supported vm features */
-#define PAL_BUS_GET_FEATURES 9 /* return processor bus interface features settings */
-#define PAL_BUS_SET_FEATURES 10 /* set processor bus features */
-#define PAL_DEBUG_INFO 11 /* get number of debug registers */
-#define PAL_FIXED_ADDR 12 /* get fixed component of processors's directed address */
-#define PAL_FREQ_BASE 13 /* base frequency of the platform */
-#define PAL_FREQ_RATIOS 14 /* ratio of processor, bus and ITC frequency */
-#define PAL_PERF_MON_INFO 15 /* return performance monitor info */
-#define PAL_PLATFORM_ADDR 16 /* set processor interrupt block and IO port space addr */
-#define PAL_PROC_GET_FEATURES 17 /* get configurable processor features & settings */
-#define PAL_PROC_SET_FEATURES 18 /* enable/disable configurable processor features */
-#define PAL_RSE_INFO 19 /* return rse information */
-#define PAL_VERSION 20 /* return version of PAL code */
-#define PAL_MC_CLEAR_LOG 21 /* clear all processor log info */
-#define PAL_MC_DRAIN 22 /* drain operations which could result in an MCA */
-#define PAL_MC_EXPECTED 23 /* set/reset expected MCA indicator */
-#define PAL_MC_DYNAMIC_STATE 24 /* get processor dynamic state */
-#define PAL_MC_ERROR_INFO 25 /* get processor MCA info and static state */
-#define PAL_MC_RESUME 26 /* Return to interrupted process */
-#define PAL_MC_REGISTER_MEM 27 /* Register memory for PAL to use during MCAs and inits */
-#define PAL_HALT 28 /* enter the low power HALT state */
-#define PAL_HALT_LIGHT 29 /* enter the low power light halt state*/
-#define PAL_COPY_INFO 30 /* returns info needed to relocate PAL */
-#define PAL_CACHE_LINE_INIT 31 /* init tags & data of cache line */
-#define PAL_PMI_ENTRYPOINT 32 /* register PMI memory entry points with the processor */
-#define PAL_ENTER_IA_32_ENV 33 /* enter IA-32 system environment */
-#define PAL_VM_PAGE_SIZE 34 /* return vm TC and page walker page sizes */
-
-#define PAL_MEM_FOR_TEST 37 /* get amount of memory needed for late processor test */
-#define PAL_CACHE_PROT_INFO 38 /* get i/d cache protection info */
-#define PAL_REGISTER_INFO 39 /* return AR and CR register information*/
-#define PAL_SHUTDOWN 40 /* enter processor shutdown state */
-#define PAL_PREFETCH_VISIBILITY 41 /* Make Processor Prefetches Visible */
-#define PAL_LOGICAL_TO_PHYSICAL 42 /* returns information on logical to physical processor mapping */
-#define PAL_CACHE_SHARED_INFO 43 /* returns information on caches shared by logical processor */
-#define PAL_GET_HW_POLICY 48 /* Get current hardware resource sharing policy */
-#define PAL_SET_HW_POLICY 49 /* Set current hardware resource sharing policy */
-#define PAL_VP_INFO 50 /* Information about virtual processor features */
-#define PAL_MC_HW_TRACKING 51 /* Hardware tracking status */
-
-#define PAL_COPY_PAL 256 /* relocate PAL procedures and PAL PMI */
-#define PAL_HALT_INFO 257 /* return the low power capabilities of processor */
-#define PAL_TEST_PROC 258 /* perform late processor self-test */
-#define PAL_CACHE_READ 259 /* read tag & data of cacheline for diagnostic testing */
-#define PAL_CACHE_WRITE 260 /* write tag & data of cacheline for diagnostic testing */
-#define PAL_VM_TR_READ 261 /* read contents of translation register */
-#define PAL_GET_PSTATE 262 /* get the current P-state */
-#define PAL_SET_PSTATE 263 /* set the P-state */
-#define PAL_BRAND_INFO 274 /* Processor branding information */
-
-#define PAL_GET_PSTATE_TYPE_LASTSET 0
-#define PAL_GET_PSTATE_TYPE_AVGANDRESET 1
-#define PAL_GET_PSTATE_TYPE_AVGNORESET 2
-#define PAL_GET_PSTATE_TYPE_INSTANT 3
-
-#define PAL_MC_ERROR_INJECT 276 /* Injects processor error or returns injection capabilities */
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-#include <asm/fpu.h>
-#include <asm/intrinsics.h>
-
-/*
- * Data types needed to pass information into PAL procedures and
- * interpret information returned by them.
- */
-
-/* Return status from the PAL procedure */
-typedef s64 pal_status_t;
-
-#define PAL_STATUS_SUCCESS 0 /* No error */
-#define PAL_STATUS_UNIMPLEMENTED (-1) /* Unimplemented procedure */
-#define PAL_STATUS_EINVAL (-2) /* Invalid argument */
-#define PAL_STATUS_ERROR (-3) /* Error */
-#define PAL_STATUS_CACHE_INIT_FAIL (-4) /* Could not initialize the
- * specified level and type of
- * cache without sideeffects
- * and "restrict" was 1
- */
-#define PAL_STATUS_REQUIRES_MEMORY (-9) /* Call requires PAL memory buffer */
-
-/* Processor cache level in the hierarchy */
-typedef u64 pal_cache_level_t;
-#define PAL_CACHE_LEVEL_L0 0 /* L0 */
-#define PAL_CACHE_LEVEL_L1 1 /* L1 */
-#define PAL_CACHE_LEVEL_L2 2 /* L2 */
-
-
-/* Processor cache type at a particular level in the hierarchy */
-
-typedef u64 pal_cache_type_t;
-#define PAL_CACHE_TYPE_INSTRUCTION 1 /* Instruction cache */
-#define PAL_CACHE_TYPE_DATA 2 /* Data or unified cache */
-#define PAL_CACHE_TYPE_INSTRUCTION_DATA 3 /* Both Data & Instruction */
-
-
-#define PAL_CACHE_FLUSH_INVALIDATE 1 /* Invalidate clean lines */
-#define PAL_CACHE_FLUSH_CHK_INTRS 2 /* check for interrupts/mc while flushing */
-
-/* Processor cache line size in bytes */
-typedef int pal_cache_line_size_t;
-
-/* Processor cache line state */
-typedef u64 pal_cache_line_state_t;
-#define PAL_CACHE_LINE_STATE_INVALID 0 /* Invalid */
-#define PAL_CACHE_LINE_STATE_SHARED 1 /* Shared */
-#define PAL_CACHE_LINE_STATE_EXCLUSIVE 2 /* Exclusive */
-#define PAL_CACHE_LINE_STATE_MODIFIED 3 /* Modified */
-
-typedef struct pal_freq_ratio {
- u32 den, num; /* numerator & denominator */
-} itc_ratio, proc_ratio;
-
-typedef union pal_cache_config_info_1_s {
- struct {
- u64 u : 1, /* 0 Unified cache ? */
- at : 2, /* 2-1 Cache mem attr*/
- reserved : 5, /* 7-3 Reserved */
- associativity : 8, /* 16-8 Associativity*/
- line_size : 8, /* 23-17 Line size */
- stride : 8, /* 31-24 Stride */
- store_latency : 8, /*39-32 Store latency*/
- load_latency : 8, /* 47-40 Load latency*/
- store_hints : 8, /* 55-48 Store hints*/
- load_hints : 8; /* 63-56 Load hints */
- } pcci1_bits;
- u64 pcci1_data;
-} pal_cache_config_info_1_t;
-
-typedef union pal_cache_config_info_2_s {
- struct {
- u32 cache_size; /*cache size in bytes*/
-
-
- u32 alias_boundary : 8, /* 39-32 aliased addr
- * separation for max
- * performance.
- */
- tag_ls_bit : 8, /* 47-40 LSb of addr*/
- tag_ms_bit : 8, /* 55-48 MSb of addr*/
- reserved : 8; /* 63-56 Reserved */
- } pcci2_bits;
- u64 pcci2_data;
-} pal_cache_config_info_2_t;
-
-
-typedef struct pal_cache_config_info_s {
- pal_status_t pcci_status;
- pal_cache_config_info_1_t pcci_info_1;
- pal_cache_config_info_2_t pcci_info_2;
- u64 pcci_reserved;
-} pal_cache_config_info_t;
-
-#define pcci_ld_hints pcci_info_1.pcci1_bits.load_hints
-#define pcci_st_hints pcci_info_1.pcci1_bits.store_hints
-#define pcci_ld_latency pcci_info_1.pcci1_bits.load_latency
-#define pcci_st_latency pcci_info_1.pcci1_bits.store_latency
-#define pcci_stride pcci_info_1.pcci1_bits.stride
-#define pcci_line_size pcci_info_1.pcci1_bits.line_size
-#define pcci_assoc pcci_info_1.pcci1_bits.associativity
-#define pcci_cache_attr pcci_info_1.pcci1_bits.at
-#define pcci_unified pcci_info_1.pcci1_bits.u
-#define pcci_tag_msb pcci_info_2.pcci2_bits.tag_ms_bit
-#define pcci_tag_lsb pcci_info_2.pcci2_bits.tag_ls_bit
-#define pcci_alias_boundary pcci_info_2.pcci2_bits.alias_boundary
-#define pcci_cache_size pcci_info_2.pcci2_bits.cache_size
-
-
-
-/* Possible values for cache attributes */
-
-#define PAL_CACHE_ATTR_WT 0 /* Write through cache */
-#define PAL_CACHE_ATTR_WB 1 /* Write back cache */
-#define PAL_CACHE_ATTR_WT_OR_WB 2 /* Either write thru or write
- * back depending on TLB
- * memory attributes
- */
-
-
-/* Possible values for cache hints */
-
-#define PAL_CACHE_HINT_TEMP_1 0 /* Temporal level 1 */
-#define PAL_CACHE_HINT_NTEMP_1 1 /* Non-temporal level 1 */
-#define PAL_CACHE_HINT_NTEMP_ALL 3 /* Non-temporal all levels */
-
-/* Processor cache protection information */
-typedef union pal_cache_protection_element_u {
- u32 pcpi_data;
- struct {
- u32 data_bits : 8, /* # data bits covered by
- * each unit of protection
- */
-
- tagprot_lsb : 6, /* Least -do- */
- tagprot_msb : 6, /* Most Sig. tag address
- * bit that this
- * protection covers.
- */
- prot_bits : 6, /* # of protection bits */
- method : 4, /* Protection method */
- t_d : 2; /* Indicates which part
- * of the cache this
- * protection encoding
- * applies.
- */
- } pcp_info;
-} pal_cache_protection_element_t;
-
-#define pcpi_cache_prot_part pcp_info.t_d
-#define pcpi_prot_method pcp_info.method
-#define pcpi_prot_bits pcp_info.prot_bits
-#define pcpi_tagprot_msb pcp_info.tagprot_msb
-#define pcpi_tagprot_lsb pcp_info.tagprot_lsb
-#define pcpi_data_bits pcp_info.data_bits
-
-/* Processor cache part encodings */
-#define PAL_CACHE_PROT_PART_DATA 0 /* Data protection */
-#define PAL_CACHE_PROT_PART_TAG 1 /* Tag protection */
-#define PAL_CACHE_PROT_PART_TAG_DATA 2 /* Tag+data protection (tag is
- * more significant )
- */
-#define PAL_CACHE_PROT_PART_DATA_TAG 3 /* Data+tag protection (data is
- * more significant )
- */
-#define PAL_CACHE_PROT_PART_MAX 6
-
-
-typedef struct pal_cache_protection_info_s {
- pal_status_t pcpi_status;
- pal_cache_protection_element_t pcp_info[PAL_CACHE_PROT_PART_MAX];
-} pal_cache_protection_info_t;
-
-
-/* Processor cache protection method encodings */
-#define PAL_CACHE_PROT_METHOD_NONE 0 /* No protection */
-#define PAL_CACHE_PROT_METHOD_ODD_PARITY 1 /* Odd parity */
-#define PAL_CACHE_PROT_METHOD_EVEN_PARITY 2 /* Even parity */
-#define PAL_CACHE_PROT_METHOD_ECC 3 /* ECC protection */
-
-
-/* Processor cache line identification in the hierarchy */
-typedef union pal_cache_line_id_u {
- u64 pclid_data;
- struct {
- u64 cache_type : 8, /* 7-0 cache type */
- level : 8, /* 15-8 level of the
- * cache in the
- * hierarchy.
- */
- way : 8, /* 23-16 way in the set
- */
- part : 8, /* 31-24 part of the
- * cache
- */
- reserved : 32; /* 63-32 is reserved*/
- } pclid_info_read;
- struct {
- u64 cache_type : 8, /* 7-0 cache type */
- level : 8, /* 15-8 level of the
- * cache in the
- * hierarchy.
- */
- way : 8, /* 23-16 way in the set
- */
- part : 8, /* 31-24 part of the
- * cache
- */
- mesi : 8, /* 39-32 cache line
- * state
- */
- start : 8, /* 47-40 lsb of data to
- * invert
- */
- length : 8, /* 55-48 #bits to
- * invert
- */
- trigger : 8; /* 63-56 Trigger error
- * by doing a load
- * after the write
- */
-
- } pclid_info_write;
-} pal_cache_line_id_u_t;
-
-#define pclid_read_part pclid_info_read.part
-#define pclid_read_way pclid_info_read.way
-#define pclid_read_level pclid_info_read.level
-#define pclid_read_cache_type pclid_info_read.cache_type
-
-#define pclid_write_trigger pclid_info_write.trigger
-#define pclid_write_length pclid_info_write.length
-#define pclid_write_start pclid_info_write.start
-#define pclid_write_mesi pclid_info_write.mesi
-#define pclid_write_part pclid_info_write.part
-#define pclid_write_way pclid_info_write.way
-#define pclid_write_level pclid_info_write.level
-#define pclid_write_cache_type pclid_info_write.cache_type
-
-/* Processor cache line part encodings */
-#define PAL_CACHE_LINE_ID_PART_DATA 0 /* Data */
-#define PAL_CACHE_LINE_ID_PART_TAG 1 /* Tag */
-#define PAL_CACHE_LINE_ID_PART_DATA_PROT 2 /* Data protection */
-#define PAL_CACHE_LINE_ID_PART_TAG_PROT 3 /* Tag protection */
-#define PAL_CACHE_LINE_ID_PART_DATA_TAG_PROT 4 /* Data+tag
- * protection
- */
-typedef struct pal_cache_line_info_s {
- pal_status_t pcli_status; /* Return status of the read cache line
- * info call.
- */
- u64 pcli_data; /* 64-bit data, tag, protection bits .. */
- u64 pcli_data_len; /* data length in bits */
- pal_cache_line_state_t pcli_cache_line_state; /* mesi state */
-
-} pal_cache_line_info_t;
-
-
-/* Machine Check related crap */
-
-/* Pending event status bits */
-typedef u64 pal_mc_pending_events_t;
-
-#define PAL_MC_PENDING_MCA (1 << 0)
-#define PAL_MC_PENDING_INIT (1 << 1)
-
-/* Error information type */
-typedef u64 pal_mc_info_index_t;
-
-#define PAL_MC_INFO_PROCESSOR 0 /* Processor */
-#define PAL_MC_INFO_CACHE_CHECK 1 /* Cache check */
-#define PAL_MC_INFO_TLB_CHECK 2 /* Tlb check */
-#define PAL_MC_INFO_BUS_CHECK 3 /* Bus check */
-#define PAL_MC_INFO_REQ_ADDR 4 /* Requestor address */
-#define PAL_MC_INFO_RESP_ADDR 5 /* Responder address */
-#define PAL_MC_INFO_TARGET_ADDR 6 /* Target address */
-#define PAL_MC_INFO_IMPL_DEP 7 /* Implementation
- * dependent
- */
-
-#define PAL_TLB_CHECK_OP_PURGE 8
-
-typedef struct pal_process_state_info_s {
- u64 reserved1 : 2,
- rz : 1, /* PAL_CHECK processor
- * rendezvous
- * successful.
- */
-
- ra : 1, /* PAL_CHECK attempted
- * a rendezvous.
- */
- me : 1, /* Distinct multiple
- * errors occurred
- */
-
- mn : 1, /* Min. state save
- * area has been
- * registered with PAL
- */
-
- sy : 1, /* Storage integrity
- * synched
- */
-
-
- co : 1, /* Continuable */
- ci : 1, /* MC isolated */
- us : 1, /* Uncontained storage
- * damage.
- */
-
-
- hd : 1, /* Non-essential hw
- * lost (no loss of
- * functionality)
- * causing the
- * processor to run in
- * degraded mode.
- */
-
- tl : 1, /* 1 => MC occurred
- * after an instr was
- * executed but before
- * the trap that
- * resulted from instr
- * execution was
- * generated.
- * (Trap Lost )
- */
- mi : 1, /* More information available
- * call PAL_MC_ERROR_INFO
- */
- pi : 1, /* Precise instruction pointer */
- pm : 1, /* Precise min-state save area */
-
- dy : 1, /* Processor dynamic
- * state valid
- */
-
-
- in : 1, /* 0 = MC, 1 = INIT */
- rs : 1, /* RSE valid */
- cm : 1, /* MC corrected */
- ex : 1, /* MC is expected */
- cr : 1, /* Control regs valid*/
- pc : 1, /* Perf cntrs valid */
- dr : 1, /* Debug regs valid */
- tr : 1, /* Translation regs
- * valid
- */
- rr : 1, /* Region regs valid */
- ar : 1, /* App regs valid */
- br : 1, /* Branch regs valid */
- pr : 1, /* Predicate registers
- * valid
- */
-
- fp : 1, /* fp registers valid*/
- b1 : 1, /* Preserved bank one
- * general registers
- * are valid
- */
- b0 : 1, /* Preserved bank zero
- * general registers
- * are valid
- */
- gr : 1, /* General registers
- * are valid
- * (excl. banked regs)
- */
- dsize : 16, /* size of dynamic
- * state returned
- * by the processor
- */
-
- se : 1, /* Shared error. MCA in a
- shared structure */
- reserved2 : 10,
- cc : 1, /* Cache check */
- tc : 1, /* TLB check */
- bc : 1, /* Bus check */
- rc : 1, /* Register file check */
- uc : 1; /* Uarch check */
-
-} pal_processor_state_info_t;
-
-typedef struct pal_cache_check_info_s {
- u64 op : 4, /* Type of cache
- * operation that
- * caused the machine
- * check.
- */
- level : 2, /* Cache level */
- reserved1 : 2,
- dl : 1, /* Failure in data part
- * of cache line
- */
- tl : 1, /* Failure in tag part
- * of cache line
- */
- dc : 1, /* Failure in dcache */
- ic : 1, /* Failure in icache */
- mesi : 3, /* Cache line state */
- mv : 1, /* mesi valid */
- way : 5, /* Way in which the
- * error occurred
- */
- wiv : 1, /* Way field valid */
- reserved2 : 1,
- dp : 1, /* Data poisoned on MBE */
- reserved3 : 6,
- hlth : 2, /* Health indicator */
-
- index : 20, /* Cache line index */
- reserved4 : 2,
-
- is : 1, /* instruction set (1 == ia32) */
- iv : 1, /* instruction set field valid */
- pl : 2, /* privilege level */
- pv : 1, /* privilege level field valid */
- mcc : 1, /* Machine check corrected */
- tv : 1, /* Target address
- * structure is valid
- */
- rq : 1, /* Requester identifier
- * structure is valid
- */
- rp : 1, /* Responder identifier
- * structure is valid
- */
- pi : 1; /* Precise instruction pointer
- * structure is valid
- */
-} pal_cache_check_info_t;
-
-typedef struct pal_tlb_check_info_s {
-
- u64 tr_slot : 8, /* Slot# of TR where
- * error occurred
- */
- trv : 1, /* tr_slot field is valid */
- reserved1 : 1,
- level : 2, /* TLB level where failure occurred */
- reserved2 : 4,
- dtr : 1, /* Fail in data TR */
- itr : 1, /* Fail in inst TR */
- dtc : 1, /* Fail in data TC */
- itc : 1, /* Fail in inst. TC */
- op : 4, /* Cache operation */
- reserved3 : 6,
- hlth : 2, /* Health indicator */
- reserved4 : 22,
-
- is : 1, /* instruction set (1 == ia32) */
- iv : 1, /* instruction set field valid */
- pl : 2, /* privilege level */
- pv : 1, /* privilege level field valid */
- mcc : 1, /* Machine check corrected */
- tv : 1, /* Target address
- * structure is valid
- */
- rq : 1, /* Requester identifier
- * structure is valid
- */
- rp : 1, /* Responder identifier
- * structure is valid
- */
- pi : 1; /* Precise instruction pointer
- * structure is valid
- */
-} pal_tlb_check_info_t;
-
-typedef struct pal_bus_check_info_s {
- u64 size : 5, /* Xaction size */
- ib : 1, /* Internal bus error */
- eb : 1, /* External bus error */
- cc : 1, /* Error occurred
- * during cache-cache
- * transfer.
- */
- type : 8, /* Bus xaction type*/
- sev : 5, /* Bus error severity*/
- hier : 2, /* Bus hierarchy level */
- dp : 1, /* Data poisoned on MBE */
- bsi : 8, /* Bus error status
- * info
- */
- reserved2 : 22,
-
- is : 1, /* instruction set (1 == ia32) */
- iv : 1, /* instruction set field valid */
- pl : 2, /* privilege level */
- pv : 1, /* privilege level field valid */
- mcc : 1, /* Machine check corrected */
- tv : 1, /* Target address
- * structure is valid
- */
- rq : 1, /* Requester identifier
- * structure is valid
- */
- rp : 1, /* Responder identifier
- * structure is valid
- */
- pi : 1; /* Precise instruction pointer
- * structure is valid
- */
-} pal_bus_check_info_t;
-
-typedef struct pal_reg_file_check_info_s {
- u64 id : 4, /* Register file identifier */
- op : 4, /* Type of register
- * operation that
- * caused the machine
- * check.
- */
- reg_num : 7, /* Register number */
- rnv : 1, /* reg_num valid */
- reserved2 : 38,
-
- is : 1, /* instruction set (1 == ia32) */
- iv : 1, /* instruction set field valid */
- pl : 2, /* privilege level */
- pv : 1, /* privilege level field valid */
- mcc : 1, /* Machine check corrected */
- reserved3 : 3,
- pi : 1; /* Precise instruction pointer
- * structure is valid
- */
-} pal_reg_file_check_info_t;
-
-typedef struct pal_uarch_check_info_s {
- u64 sid : 5, /* Structure identification */
- level : 3, /* Level of failure */
- array_id : 4, /* Array identification */
- op : 4, /* Type of
- * operation that
- * caused the machine
- * check.
- */
- way : 6, /* Way of structure */
- wv : 1, /* way valid */
- xv : 1, /* index valid */
- reserved1 : 6,
- hlth : 2, /* Health indicator */
- index : 8, /* Index or set of the uarch
- * structure that failed.
- */
- reserved2 : 24,
-
- is : 1, /* instruction set (1 == ia32) */
- iv : 1, /* instruction set field valid */
- pl : 2, /* privilege level */
- pv : 1, /* privilege level field valid */
- mcc : 1, /* Machine check corrected */
- tv : 1, /* Target address
- * structure is valid
- */
- rq : 1, /* Requester identifier
- * structure is valid
- */
- rp : 1, /* Responder identifier
- * structure is valid
- */
- pi : 1; /* Precise instruction pointer
- * structure is valid
- */
-} pal_uarch_check_info_t;
-
-typedef union pal_mc_error_info_u {
- u64 pmei_data;
- pal_processor_state_info_t pme_processor;
- pal_cache_check_info_t pme_cache;
- pal_tlb_check_info_t pme_tlb;
- pal_bus_check_info_t pme_bus;
- pal_reg_file_check_info_t pme_reg_file;
- pal_uarch_check_info_t pme_uarch;
-} pal_mc_error_info_t;
-
-#define pmci_proc_unknown_check pme_processor.uc
-#define pmci_proc_bus_check pme_processor.bc
-#define pmci_proc_tlb_check pme_processor.tc
-#define pmci_proc_cache_check pme_processor.cc
-#define pmci_proc_dynamic_state_size pme_processor.dsize
-#define pmci_proc_gpr_valid pme_processor.gr
-#define pmci_proc_preserved_bank0_gpr_valid pme_processor.b0
-#define pmci_proc_preserved_bank1_gpr_valid pme_processor.b1
-#define pmci_proc_fp_valid pme_processor.fp
-#define pmci_proc_predicate_regs_valid pme_processor.pr
-#define pmci_proc_branch_regs_valid pme_processor.br
-#define pmci_proc_app_regs_valid pme_processor.ar
-#define pmci_proc_region_regs_valid pme_processor.rr
-#define pmci_proc_translation_regs_valid pme_processor.tr
-#define pmci_proc_debug_regs_valid pme_processor.dr
-#define pmci_proc_perf_counters_valid pme_processor.pc
-#define pmci_proc_control_regs_valid pme_processor.cr
-#define pmci_proc_machine_check_expected pme_processor.ex
-#define pmci_proc_machine_check_corrected pme_processor.cm
-#define pmci_proc_rse_valid pme_processor.rs
-#define pmci_proc_machine_check_or_init pme_processor.in
-#define pmci_proc_dynamic_state_valid pme_processor.dy
-#define pmci_proc_operation pme_processor.op
-#define pmci_proc_trap_lost pme_processor.tl
-#define pmci_proc_hardware_damage pme_processor.hd
-#define pmci_proc_uncontained_storage_damage pme_processor.us
-#define pmci_proc_machine_check_isolated pme_processor.ci
-#define pmci_proc_continuable pme_processor.co
-#define pmci_proc_storage_intergrity_synced pme_processor.sy
-#define pmci_proc_min_state_save_area_regd pme_processor.mn
-#define pmci_proc_distinct_multiple_errors pme_processor.me
-#define pmci_proc_pal_attempted_rendezvous pme_processor.ra
-#define pmci_proc_pal_rendezvous_complete pme_processor.rz
-
-
-#define pmci_cache_level pme_cache.level
-#define pmci_cache_line_state pme_cache.mesi
-#define pmci_cache_line_state_valid pme_cache.mv
-#define pmci_cache_line_index pme_cache.index
-#define pmci_cache_instr_cache_fail pme_cache.ic
-#define pmci_cache_data_cache_fail pme_cache.dc
-#define pmci_cache_line_tag_fail pme_cache.tl
-#define pmci_cache_line_data_fail pme_cache.dl
-#define pmci_cache_operation pme_cache.op
-#define pmci_cache_way_valid pme_cache.wv
-#define pmci_cache_target_address_valid pme_cache.tv
-#define pmci_cache_way pme_cache.way
-#define pmci_cache_mc pme_cache.mc
-
-#define pmci_tlb_instr_translation_cache_fail pme_tlb.itc
-#define pmci_tlb_data_translation_cache_fail pme_tlb.dtc
-#define pmci_tlb_instr_translation_reg_fail pme_tlb.itr
-#define pmci_tlb_data_translation_reg_fail pme_tlb.dtr
-#define pmci_tlb_translation_reg_slot pme_tlb.tr_slot
-#define pmci_tlb_mc pme_tlb.mc
-
-#define pmci_bus_status_info pme_bus.bsi
-#define pmci_bus_req_address_valid pme_bus.rq
-#define pmci_bus_resp_address_valid pme_bus.rp
-#define pmci_bus_target_address_valid pme_bus.tv
-#define pmci_bus_error_severity pme_bus.sev
-#define pmci_bus_transaction_type pme_bus.type
-#define pmci_bus_cache_cache_transfer pme_bus.cc
-#define pmci_bus_transaction_size pme_bus.size
-#define pmci_bus_internal_error pme_bus.ib
-#define pmci_bus_external_error pme_bus.eb
-#define pmci_bus_mc pme_bus.mc
-
-/*
- * NOTE: this min_state_save area struct only includes the 1KB
- * architectural state save area. The other 3 KB is scratch space
- * for PAL.
- */
-
-struct pal_min_state_area {
- u64 pmsa_nat_bits; /* nat bits for saved GRs */
- u64 pmsa_gr[15]; /* GR1 - GR15 */
- u64 pmsa_bank0_gr[16]; /* GR16 - GR31 */
- u64 pmsa_bank1_gr[16]; /* GR16 - GR31 */
- u64 pmsa_pr; /* predicate registers */
- u64 pmsa_br0; /* branch register 0 */
- u64 pmsa_rsc; /* ar.rsc */
- u64 pmsa_iip; /* cr.iip */
- u64 pmsa_ipsr; /* cr.ipsr */
- u64 pmsa_ifs; /* cr.ifs */
- u64 pmsa_xip; /* previous iip */
- u64 pmsa_xpsr; /* previous psr */
- u64 pmsa_xfs; /* previous ifs */
- u64 pmsa_br1; /* branch register 1 */
- u64 pmsa_reserved[70]; /* pal_min_state_area should total to 1KB */
-};
-
-
-struct ia64_pal_retval {
- /*
- * A zero status value indicates call completed without error.
- * A negative status value indicates reason of call failure.
- * A positive status value indicates success but an
- * informational value should be printed (e.g., "reboot for
- * change to take effect").
- */
- s64 status;
- u64 v0;
- u64 v1;
- u64 v2;
-};
-
-/*
- * Note: Currently unused PAL arguments are generally labeled
- * "reserved" so the value specified in the PAL documentation
- * (generally 0) MUST be passed. Reserved parameters are not optional
- * parameters.
- */
-extern struct ia64_pal_retval ia64_pal_call_static (u64, u64, u64, u64);
-extern struct ia64_pal_retval ia64_pal_call_stacked (u64, u64, u64, u64);
-extern struct ia64_pal_retval ia64_pal_call_phys_static (u64, u64, u64, u64);
-extern struct ia64_pal_retval ia64_pal_call_phys_stacked (u64, u64, u64, u64);
-extern void ia64_save_scratch_fpregs (struct ia64_fpreg *);
-extern void ia64_load_scratch_fpregs (struct ia64_fpreg *);
-
-#define PAL_CALL(iprv,a0,a1,a2,a3) do { \
- struct ia64_fpreg fr[6]; \
- ia64_save_scratch_fpregs(fr); \
- iprv = ia64_pal_call_static(a0, a1, a2, a3); \
- ia64_load_scratch_fpregs(fr); \
-} while (0)
-
-#define PAL_CALL_STK(iprv,a0,a1,a2,a3) do { \
- struct ia64_fpreg fr[6]; \
- ia64_save_scratch_fpregs(fr); \
- iprv = ia64_pal_call_stacked(a0, a1, a2, a3); \
- ia64_load_scratch_fpregs(fr); \
-} while (0)
-
-#define PAL_CALL_PHYS(iprv,a0,a1,a2,a3) do { \
- struct ia64_fpreg fr[6]; \
- ia64_save_scratch_fpregs(fr); \
- iprv = ia64_pal_call_phys_static(a0, a1, a2, a3); \
- ia64_load_scratch_fpregs(fr); \
-} while (0)
-
-#define PAL_CALL_PHYS_STK(iprv,a0,a1,a2,a3) do { \
- struct ia64_fpreg fr[6]; \
- ia64_save_scratch_fpregs(fr); \
- iprv = ia64_pal_call_phys_stacked(a0, a1, a2, a3); \
- ia64_load_scratch_fpregs(fr); \
-} while (0)
-
-typedef int (*ia64_pal_handler) (u64, ...);
-extern ia64_pal_handler ia64_pal;
-extern void ia64_pal_handler_init (void *);
-
-extern ia64_pal_handler ia64_pal;
-
-extern pal_cache_config_info_t l0d_cache_config_info;
-extern pal_cache_config_info_t l0i_cache_config_info;
-extern pal_cache_config_info_t l1_cache_config_info;
-extern pal_cache_config_info_t l2_cache_config_info;
-
-extern pal_cache_protection_info_t l0d_cache_protection_info;
-extern pal_cache_protection_info_t l0i_cache_protection_info;
-extern pal_cache_protection_info_t l1_cache_protection_info;
-extern pal_cache_protection_info_t l2_cache_protection_info;
-
-extern pal_cache_config_info_t pal_cache_config_info_get(pal_cache_level_t,
- pal_cache_type_t);
-
-extern pal_cache_protection_info_t pal_cache_protection_info_get(pal_cache_level_t,
- pal_cache_type_t);
-
-
-extern void pal_error(int);
-
-
-/* Useful wrappers for the current list of pal procedures */
-
-typedef union pal_bus_features_u {
- u64 pal_bus_features_val;
- struct {
- u64 pbf_reserved1 : 29;
- u64 pbf_req_bus_parking : 1;
- u64 pbf_bus_lock_mask : 1;
- u64 pbf_enable_half_xfer_rate : 1;
- u64 pbf_reserved2 : 20;
- u64 pbf_enable_shared_line_replace : 1;
- u64 pbf_enable_exclusive_line_replace : 1;
- u64 pbf_disable_xaction_queueing : 1;
- u64 pbf_disable_resp_err_check : 1;
- u64 pbf_disable_berr_check : 1;
- u64 pbf_disable_bus_req_internal_err_signal : 1;
- u64 pbf_disable_bus_req_berr_signal : 1;
- u64 pbf_disable_bus_init_event_check : 1;
- u64 pbf_disable_bus_init_event_signal : 1;
- u64 pbf_disable_bus_addr_err_check : 1;
- u64 pbf_disable_bus_addr_err_signal : 1;
- u64 pbf_disable_bus_data_err_check : 1;
- } pal_bus_features_s;
-} pal_bus_features_u_t;
-
-extern void pal_bus_features_print (u64);
-
-/* Provide information about configurable processor bus features */
-static inline s64
-ia64_pal_bus_get_features (pal_bus_features_u_t *features_avail,
- pal_bus_features_u_t *features_status,
- pal_bus_features_u_t *features_control)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_PHYS(iprv, PAL_BUS_GET_FEATURES, 0, 0, 0);
- if (features_avail)
- features_avail->pal_bus_features_val = iprv.v0;
- if (features_status)
- features_status->pal_bus_features_val = iprv.v1;
- if (features_control)
- features_control->pal_bus_features_val = iprv.v2;
- return iprv.status;
-}
-
-/* Enables/disables specific processor bus features */
-static inline s64
-ia64_pal_bus_set_features (pal_bus_features_u_t feature_select)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_PHYS(iprv, PAL_BUS_SET_FEATURES, feature_select.pal_bus_features_val, 0, 0);
- return iprv.status;
-}
-
-/* Get detailed cache information */
-static inline s64
-ia64_pal_cache_config_info (u64 cache_level, u64 cache_type, pal_cache_config_info_t *conf)
-{
- struct ia64_pal_retval iprv;
-
- PAL_CALL(iprv, PAL_CACHE_INFO, cache_level, cache_type, 0);
-
- if (iprv.status == 0) {
- conf->pcci_status = iprv.status;
- conf->pcci_info_1.pcci1_data = iprv.v0;
- conf->pcci_info_2.pcci2_data = iprv.v1;
- conf->pcci_reserved = iprv.v2;
- }
- return iprv.status;
-
-}
-
-/* Get detailed cche protection information */
-static inline s64
-ia64_pal_cache_prot_info (u64 cache_level, u64 cache_type, pal_cache_protection_info_t *prot)
-{
- struct ia64_pal_retval iprv;
-
- PAL_CALL(iprv, PAL_CACHE_PROT_INFO, cache_level, cache_type, 0);
-
- if (iprv.status == 0) {
- prot->pcpi_status = iprv.status;
- prot->pcp_info[0].pcpi_data = iprv.v0 & 0xffffffff;
- prot->pcp_info[1].pcpi_data = iprv.v0 >> 32;
- prot->pcp_info[2].pcpi_data = iprv.v1 & 0xffffffff;
- prot->pcp_info[3].pcpi_data = iprv.v1 >> 32;
- prot->pcp_info[4].pcpi_data = iprv.v2 & 0xffffffff;
- prot->pcp_info[5].pcpi_data = iprv.v2 >> 32;
- }
- return iprv.status;
-}
-
-/*
- * Flush the processor instruction or data caches. *PROGRESS must be
- * initialized to zero before calling this for the first time..
- */
-static inline s64
-ia64_pal_cache_flush (u64 cache_type, u64 invalidate, u64 *progress, u64 *vector)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_CACHE_FLUSH, cache_type, invalidate, *progress);
- if (vector)
- *vector = iprv.v0;
- *progress = iprv.v1;
- return iprv.status;
-}
-
-
-/* Initialize the processor controlled caches */
-static inline s64
-ia64_pal_cache_init (u64 level, u64 cache_type, u64 rest)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_CACHE_INIT, level, cache_type, rest);
- return iprv.status;
-}
-
-/* Initialize the tags and data of a data or unified cache line of
- * processor controlled cache to known values without the availability
- * of backing memory.
- */
-static inline s64
-ia64_pal_cache_line_init (u64 physical_addr, u64 data_value)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_CACHE_LINE_INIT, physical_addr, data_value, 0);
- return iprv.status;
-}
-
-
-/* Read the data and tag of a processor controlled cache line for diags */
-static inline s64
-ia64_pal_cache_read (pal_cache_line_id_u_t line_id, u64 physical_addr)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_PHYS_STK(iprv, PAL_CACHE_READ, line_id.pclid_data,
- physical_addr, 0);
- return iprv.status;
-}
-
-/* Return summary information about the hierarchy of caches controlled by the processor */
-static inline long ia64_pal_cache_summary(unsigned long *cache_levels,
- unsigned long *unique_caches)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_CACHE_SUMMARY, 0, 0, 0);
- if (cache_levels)
- *cache_levels = iprv.v0;
- if (unique_caches)
- *unique_caches = iprv.v1;
- return iprv.status;
-}
-
-/* Write the data and tag of a processor-controlled cache line for diags */
-static inline s64
-ia64_pal_cache_write (pal_cache_line_id_u_t line_id, u64 physical_addr, u64 data)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_PHYS_STK(iprv, PAL_CACHE_WRITE, line_id.pclid_data,
- physical_addr, data);
- return iprv.status;
-}
-
-
-/* Return the parameters needed to copy relocatable PAL procedures from ROM to memory */
-static inline s64
-ia64_pal_copy_info (u64 copy_type, u64 num_procs, u64 num_iopics,
- u64 *buffer_size, u64 *buffer_align)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_COPY_INFO, copy_type, num_procs, num_iopics);
- if (buffer_size)
- *buffer_size = iprv.v0;
- if (buffer_align)
- *buffer_align = iprv.v1;
- return iprv.status;
-}
-
-/* Copy relocatable PAL procedures from ROM to memory */
-static inline s64
-ia64_pal_copy_pal (u64 target_addr, u64 alloc_size, u64 processor, u64 *pal_proc_offset)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_COPY_PAL, target_addr, alloc_size, processor);
- if (pal_proc_offset)
- *pal_proc_offset = iprv.v0;
- return iprv.status;
-}
-
-/* Return the number of instruction and data debug register pairs */
-static inline long ia64_pal_debug_info(unsigned long *inst_regs,
- unsigned long *data_regs)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_DEBUG_INFO, 0, 0, 0);
- if (inst_regs)
- *inst_regs = iprv.v0;
- if (data_regs)
- *data_regs = iprv.v1;
-
- return iprv.status;
-}
-
-#ifdef TBD
-/* Switch from IA64-system environment to IA-32 system environment */
-static inline s64
-ia64_pal_enter_ia32_env (ia32_env1, ia32_env2, ia32_env3)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_ENTER_IA_32_ENV, ia32_env1, ia32_env2, ia32_env3);
- return iprv.status;
-}
-#endif
-
-/* Get unique geographical address of this processor on its bus */
-static inline s64
-ia64_pal_fixed_addr (u64 *global_unique_addr)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_FIXED_ADDR, 0, 0, 0);
- if (global_unique_addr)
- *global_unique_addr = iprv.v0;
- return iprv.status;
-}
-
-/* Get base frequency of the platform if generated by the processor */
-static inline long ia64_pal_freq_base(unsigned long *platform_base_freq)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_FREQ_BASE, 0, 0, 0);
- if (platform_base_freq)
- *platform_base_freq = iprv.v0;
- return iprv.status;
-}
-
-/*
- * Get the ratios for processor frequency, bus frequency and interval timer to
- * the base frequency of the platform
- */
-static inline s64
-ia64_pal_freq_ratios (struct pal_freq_ratio *proc_ratio, struct pal_freq_ratio *bus_ratio,
- struct pal_freq_ratio *itc_ratio)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_FREQ_RATIOS, 0, 0, 0);
- if (proc_ratio)
- *(u64 *)proc_ratio = iprv.v0;
- if (bus_ratio)
- *(u64 *)bus_ratio = iprv.v1;
- if (itc_ratio)
- *(u64 *)itc_ratio = iprv.v2;
- return iprv.status;
-}
-
-/*
- * Get the current hardware resource sharing policy of the processor
- */
-static inline s64
-ia64_pal_get_hw_policy (u64 proc_num, u64 *cur_policy, u64 *num_impacted,
- u64 *la)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_GET_HW_POLICY, proc_num, 0, 0);
- if (cur_policy)
- *cur_policy = iprv.v0;
- if (num_impacted)
- *num_impacted = iprv.v1;
- if (la)
- *la = iprv.v2;
- return iprv.status;
-}
-
-/* Make the processor enter HALT or one of the implementation dependent low
- * power states where prefetching and execution are suspended and cache and
- * TLB coherency is not maintained.
- */
-static inline s64
-ia64_pal_halt (u64 halt_state)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_HALT, halt_state, 0, 0);
- return iprv.status;
-}
-
-typedef union pal_power_mgmt_info_u {
- u64 ppmi_data;
- struct {
- u64 exit_latency : 16,
- entry_latency : 16,
- power_consumption : 28,
- im : 1,
- co : 1,
- reserved : 2;
- } pal_power_mgmt_info_s;
-} pal_power_mgmt_info_u_t;
-
-/* Return information about processor's optional power management capabilities. */
-static inline s64
-ia64_pal_halt_info (pal_power_mgmt_info_u_t *power_buf)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_STK(iprv, PAL_HALT_INFO, (unsigned long) power_buf, 0, 0);
- return iprv.status;
-}
-
-/* Get the current P-state information */
-static inline s64
-ia64_pal_get_pstate (u64 *pstate_index, unsigned long type)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_STK(iprv, PAL_GET_PSTATE, type, 0, 0);
- *pstate_index = iprv.v0;
- return iprv.status;
-}
-
-/* Set the P-state */
-static inline s64
-ia64_pal_set_pstate (u64 pstate_index)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_STK(iprv, PAL_SET_PSTATE, pstate_index, 0, 0);
- return iprv.status;
-}
-
-/* Processor branding information*/
-static inline s64
-ia64_pal_get_brand_info (char *brand_info)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_STK(iprv, PAL_BRAND_INFO, 0, (u64)brand_info, 0);
- return iprv.status;
-}
-
-/* Cause the processor to enter LIGHT HALT state, where prefetching and execution are
- * suspended, but cache and TLB coherency is maintained.
- */
-static inline s64
-ia64_pal_halt_light (void)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_HALT_LIGHT, 0, 0, 0);
- return iprv.status;
-}
-
-/* Clear all the processor error logging registers and reset the indicator that allows
- * the error logging registers to be written. This procedure also checks the pending
- * machine check bit and pending INIT bit and reports their states.
- */
-static inline s64
-ia64_pal_mc_clear_log (u64 *pending_vector)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_MC_CLEAR_LOG, 0, 0, 0);
- if (pending_vector)
- *pending_vector = iprv.v0;
- return iprv.status;
-}
-
-/* Ensure that all outstanding transactions in a processor are completed or that any
- * MCA due to thes outstanding transaction is taken.
- */
-static inline s64
-ia64_pal_mc_drain (void)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_MC_DRAIN, 0, 0, 0);
- return iprv.status;
-}
-
-/* Return the machine check dynamic processor state */
-static inline s64
-ia64_pal_mc_dynamic_state (u64 info_type, u64 dy_buffer, u64 *size)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_MC_DYNAMIC_STATE, info_type, dy_buffer, 0);
- if (size)
- *size = iprv.v0;
- return iprv.status;
-}
-
-/* Return processor machine check information */
-static inline s64
-ia64_pal_mc_error_info (u64 info_index, u64 type_index, u64 *size, u64 *error_info)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_MC_ERROR_INFO, info_index, type_index, 0);
- if (size)
- *size = iprv.v0;
- if (error_info)
- *error_info = iprv.v1;
- return iprv.status;
-}
-
-/* Injects the requested processor error or returns info on
- * supported injection capabilities for current processor implementation
- */
-static inline s64
-ia64_pal_mc_error_inject_phys (u64 err_type_info, u64 err_struct_info,
- u64 err_data_buffer, u64 *capabilities, u64 *resources)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_PHYS_STK(iprv, PAL_MC_ERROR_INJECT, err_type_info,
- err_struct_info, err_data_buffer);
- if (capabilities)
- *capabilities= iprv.v0;
- if (resources)
- *resources= iprv.v1;
- return iprv.status;
-}
-
-static inline s64
-ia64_pal_mc_error_inject_virt (u64 err_type_info, u64 err_struct_info,
- u64 err_data_buffer, u64 *capabilities, u64 *resources)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_STK(iprv, PAL_MC_ERROR_INJECT, err_type_info,
- err_struct_info, err_data_buffer);
- if (capabilities)
- *capabilities= iprv.v0;
- if (resources)
- *resources= iprv.v1;
- return iprv.status;
-}
-
-/* Inform PALE_CHECK whether a machine check is expected so that PALE_CHECK willnot
- * attempt to correct any expected machine checks.
- */
-static inline s64
-ia64_pal_mc_expected (u64 expected, u64 *previous)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_MC_EXPECTED, expected, 0, 0);
- if (previous)
- *previous = iprv.v0;
- return iprv.status;
-}
-
-typedef union pal_hw_tracking_u {
- u64 pht_data;
- struct {
- u64 itc :4, /* Instruction cache tracking */
- dct :4, /* Date cache tracking */
- itt :4, /* Instruction TLB tracking */
- ddt :4, /* Data TLB tracking */
- reserved:48;
- } pal_hw_tracking_s;
-} pal_hw_tracking_u_t;
-
-/*
- * Hardware tracking status.
- */
-static inline s64
-ia64_pal_mc_hw_tracking (u64 *status)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_MC_HW_TRACKING, 0, 0, 0);
- if (status)
- *status = iprv.v0;
- return iprv.status;
-}
-
-/* Register a platform dependent location with PAL to which it can save
- * minimal processor state in the event of a machine check or initialization
- * event.
- */
-static inline s64
-ia64_pal_mc_register_mem (u64 physical_addr, u64 size, u64 *req_size)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_MC_REGISTER_MEM, physical_addr, size, 0);
- if (req_size)
- *req_size = iprv.v0;
- return iprv.status;
-}
-
-/* Restore minimal architectural processor state, set CMC interrupt if necessary
- * and resume execution
- */
-static inline s64
-ia64_pal_mc_resume (u64 set_cmci, u64 save_ptr)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_MC_RESUME, set_cmci, save_ptr, 0);
- return iprv.status;
-}
-
-/* Return the memory attributes implemented by the processor */
-static inline s64
-ia64_pal_mem_attrib (u64 *mem_attrib)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_MEM_ATTRIB, 0, 0, 0);
- if (mem_attrib)
- *mem_attrib = iprv.v0 & 0xff;
- return iprv.status;
-}
-
-/* Return the amount of memory needed for second phase of processor
- * self-test and the required alignment of memory.
- */
-static inline s64
-ia64_pal_mem_for_test (u64 *bytes_needed, u64 *alignment)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_MEM_FOR_TEST, 0, 0, 0);
- if (bytes_needed)
- *bytes_needed = iprv.v0;
- if (alignment)
- *alignment = iprv.v1;
- return iprv.status;
-}
-
-typedef union pal_perf_mon_info_u {
- u64 ppmi_data;
- struct {
- u64 generic : 8,
- width : 8,
- cycles : 8,
- retired : 8,
- reserved : 32;
- } pal_perf_mon_info_s;
-} pal_perf_mon_info_u_t;
-
-/* Return the performance monitor information about what can be counted
- * and how to configure the monitors to count the desired events.
- */
-static inline s64
-ia64_pal_perf_mon_info (u64 *pm_buffer, pal_perf_mon_info_u_t *pm_info)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_PERF_MON_INFO, (unsigned long) pm_buffer, 0, 0);
- if (pm_info)
- pm_info->ppmi_data = iprv.v0;
- return iprv.status;
-}
-
-/* Specifies the physical address of the processor interrupt block
- * and I/O port space.
- */
-static inline s64
-ia64_pal_platform_addr (u64 type, u64 physical_addr)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_PLATFORM_ADDR, type, physical_addr, 0);
- return iprv.status;
-}
-
-/* Set the SAL PMI entrypoint in memory */
-static inline s64
-ia64_pal_pmi_entrypoint (u64 sal_pmi_entry_addr)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_PMI_ENTRYPOINT, sal_pmi_entry_addr, 0, 0);
- return iprv.status;
-}
-
-struct pal_features_s;
-/* Provide information about configurable processor features */
-static inline s64
-ia64_pal_proc_get_features (u64 *features_avail,
- u64 *features_status,
- u64 *features_control,
- u64 features_set)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_PHYS(iprv, PAL_PROC_GET_FEATURES, 0, features_set, 0);
- if (iprv.status == 0) {
- *features_avail = iprv.v0;
- *features_status = iprv.v1;
- *features_control = iprv.v2;
- }
- return iprv.status;
-}
-
-/* Enable/disable processor dependent features */
-static inline s64
-ia64_pal_proc_set_features (u64 feature_select)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_PHYS(iprv, PAL_PROC_SET_FEATURES, feature_select, 0, 0);
- return iprv.status;
-}
-
-/*
- * Put everything in a struct so we avoid the global offset table whenever
- * possible.
- */
-typedef struct ia64_ptce_info_s {
- unsigned long base;
- u32 count[2];
- u32 stride[2];
-} ia64_ptce_info_t;
-
-/* Return the information required for the architected loop used to purge
- * (initialize) the entire TC
- */
-static inline s64
-ia64_get_ptce (ia64_ptce_info_t *ptce)
-{
- struct ia64_pal_retval iprv;
-
- if (!ptce)
- return -1;
-
- PAL_CALL(iprv, PAL_PTCE_INFO, 0, 0, 0);
- if (iprv.status == 0) {
- ptce->base = iprv.v0;
- ptce->count[0] = iprv.v1 >> 32;
- ptce->count[1] = iprv.v1 & 0xffffffff;
- ptce->stride[0] = iprv.v2 >> 32;
- ptce->stride[1] = iprv.v2 & 0xffffffff;
- }
- return iprv.status;
-}
-
-/* Return info about implemented application and control registers. */
-static inline s64
-ia64_pal_register_info (u64 info_request, u64 *reg_info_1, u64 *reg_info_2)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_REGISTER_INFO, info_request, 0, 0);
- if (reg_info_1)
- *reg_info_1 = iprv.v0;
- if (reg_info_2)
- *reg_info_2 = iprv.v1;
- return iprv.status;
-}
-
-typedef union pal_hints_u {
- unsigned long ph_data;
- struct {
- unsigned long si : 1,
- li : 1,
- reserved : 62;
- } pal_hints_s;
-} pal_hints_u_t;
-
-/* Return information about the register stack and RSE for this processor
- * implementation.
- */
-static inline long ia64_pal_rse_info(unsigned long *num_phys_stacked,
- pal_hints_u_t *hints)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_RSE_INFO, 0, 0, 0);
- if (num_phys_stacked)
- *num_phys_stacked = iprv.v0;
- if (hints)
- hints->ph_data = iprv.v1;
- return iprv.status;
-}
-
-/*
- * Set the current hardware resource sharing policy of the processor
- */
-static inline s64
-ia64_pal_set_hw_policy (u64 policy)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_SET_HW_POLICY, policy, 0, 0);
- return iprv.status;
-}
-
-/* Cause the processor to enter SHUTDOWN state, where prefetching and execution are
- * suspended, but cause cache and TLB coherency to be maintained.
- * This is usually called in IA-32 mode.
- */
-static inline s64
-ia64_pal_shutdown (void)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_SHUTDOWN, 0, 0, 0);
- return iprv.status;
-}
-
-/* Perform the second phase of processor self-test. */
-static inline s64
-ia64_pal_test_proc (u64 test_addr, u64 test_size, u64 attributes, u64 *self_test_state)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_TEST_PROC, test_addr, test_size, attributes);
- if (self_test_state)
- *self_test_state = iprv.v0;
- return iprv.status;
-}
-
-typedef union pal_version_u {
- u64 pal_version_val;
- struct {
- u64 pv_pal_b_rev : 8;
- u64 pv_pal_b_model : 8;
- u64 pv_reserved1 : 8;
- u64 pv_pal_vendor : 8;
- u64 pv_pal_a_rev : 8;
- u64 pv_pal_a_model : 8;
- u64 pv_reserved2 : 16;
- } pal_version_s;
-} pal_version_u_t;
-
-
-/*
- * Return PAL version information. While the documentation states that
- * PAL_VERSION can be called in either physical or virtual mode, some
- * implementations only allow physical calls. We don't call it very often,
- * so the overhead isn't worth eliminating.
- */
-static inline s64
-ia64_pal_version (pal_version_u_t *pal_min_version, pal_version_u_t *pal_cur_version)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_PHYS(iprv, PAL_VERSION, 0, 0, 0);
- if (pal_min_version)
- pal_min_version->pal_version_val = iprv.v0;
-
- if (pal_cur_version)
- pal_cur_version->pal_version_val = iprv.v1;
-
- return iprv.status;
-}
-
-typedef union pal_tc_info_u {
- u64 pti_val;
- struct {
- u64 num_sets : 8,
- associativity : 8,
- num_entries : 16,
- pf : 1,
- unified : 1,
- reduce_tr : 1,
- reserved : 29;
- } pal_tc_info_s;
-} pal_tc_info_u_t;
-
-#define tc_reduce_tr pal_tc_info_s.reduce_tr
-#define tc_unified pal_tc_info_s.unified
-#define tc_pf pal_tc_info_s.pf
-#define tc_num_entries pal_tc_info_s.num_entries
-#define tc_associativity pal_tc_info_s.associativity
-#define tc_num_sets pal_tc_info_s.num_sets
-
-
-/* Return information about the virtual memory characteristics of the processor
- * implementation.
- */
-static inline s64
-ia64_pal_vm_info (u64 tc_level, u64 tc_type, pal_tc_info_u_t *tc_info, u64 *tc_pages)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_VM_INFO, tc_level, tc_type, 0);
- if (tc_info)
- tc_info->pti_val = iprv.v0;
- if (tc_pages)
- *tc_pages = iprv.v1;
- return iprv.status;
-}
-
-/* Get page size information about the virtual memory characteristics of the processor
- * implementation.
- */
-static inline s64 ia64_pal_vm_page_size(u64 *tr_pages, u64 *vw_pages)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_VM_PAGE_SIZE, 0, 0, 0);
- if (tr_pages)
- *tr_pages = iprv.v0;
- if (vw_pages)
- *vw_pages = iprv.v1;
- return iprv.status;
-}
-
-typedef union pal_vm_info_1_u {
- u64 pvi1_val;
- struct {
- u64 vw : 1,
- phys_add_size : 7,
- key_size : 8,
- max_pkr : 8,
- hash_tag_id : 8,
- max_dtr_entry : 8,
- max_itr_entry : 8,
- max_unique_tcs : 8,
- num_tc_levels : 8;
- } pal_vm_info_1_s;
-} pal_vm_info_1_u_t;
-
-#define PAL_MAX_PURGES 0xFFFF /* all ones is means unlimited */
-
-typedef union pal_vm_info_2_u {
- u64 pvi2_val;
- struct {
- u64 impl_va_msb : 8,
- rid_size : 8,
- max_purges : 16,
- reserved : 32;
- } pal_vm_info_2_s;
-} pal_vm_info_2_u_t;
-
-/* Get summary information about the virtual memory characteristics of the processor
- * implementation.
- */
-static inline s64
-ia64_pal_vm_summary (pal_vm_info_1_u_t *vm_info_1, pal_vm_info_2_u_t *vm_info_2)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_VM_SUMMARY, 0, 0, 0);
- if (vm_info_1)
- vm_info_1->pvi1_val = iprv.v0;
- if (vm_info_2)
- vm_info_2->pvi2_val = iprv.v1;
- return iprv.status;
-}
-
-typedef union pal_vp_info_u {
- u64 pvi_val;
- struct {
- u64 index: 48, /* virtual feature set info */
- vmm_id: 16; /* feature set id */
- } pal_vp_info_s;
-} pal_vp_info_u_t;
-
-/*
- * Returns information about virtual processor features
- */
-static inline s64
-ia64_pal_vp_info (u64 feature_set, u64 vp_buffer, u64 *vp_info, u64 *vmm_id)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_VP_INFO, feature_set, vp_buffer, 0);
- if (vp_info)
- *vp_info = iprv.v0;
- if (vmm_id)
- *vmm_id = iprv.v1;
- return iprv.status;
-}
-
-typedef union pal_itr_valid_u {
- u64 piv_val;
- struct {
- u64 access_rights_valid : 1,
- priv_level_valid : 1,
- dirty_bit_valid : 1,
- mem_attr_valid : 1,
- reserved : 60;
- } pal_tr_valid_s;
-} pal_tr_valid_u_t;
-
-/* Read a translation register */
-static inline s64
-ia64_pal_tr_read (u64 reg_num, u64 tr_type, u64 *tr_buffer, pal_tr_valid_u_t *tr_valid)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL_PHYS_STK(iprv, PAL_VM_TR_READ, reg_num, tr_type,(u64)ia64_tpa(tr_buffer));
- if (tr_valid)
- tr_valid->piv_val = iprv.v0;
- return iprv.status;
-}
-
-/*
- * PAL_PREFETCH_VISIBILITY transaction types
- */
-#define PAL_VISIBILITY_VIRTUAL 0
-#define PAL_VISIBILITY_PHYSICAL 1
-
-/*
- * PAL_PREFETCH_VISIBILITY return codes
- */
-#define PAL_VISIBILITY_OK 1
-#define PAL_VISIBILITY_OK_REMOTE_NEEDED 0
-#define PAL_VISIBILITY_INVAL_ARG -2
-#define PAL_VISIBILITY_ERROR -3
-
-static inline s64
-ia64_pal_prefetch_visibility (s64 trans_type)
-{
- struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_PREFETCH_VISIBILITY, trans_type, 0, 0);
- return iprv.status;
-}
-
-/* data structure for getting information on logical to physical mappings */
-typedef union pal_log_overview_u {
- struct {
- u64 num_log :16, /* Total number of logical
- * processors on this die
- */
- tpc :8, /* Threads per core */
- reserved3 :8, /* Reserved */
- cpp :8, /* Cores per processor */
- reserved2 :8, /* Reserved */
- ppid :8, /* Physical processor ID */
- reserved1 :8; /* Reserved */
- } overview_bits;
- u64 overview_data;
-} pal_log_overview_t;
-
-typedef union pal_proc_n_log_info1_u{
- struct {
- u64 tid :16, /* Thread id */
- reserved2 :16, /* Reserved */
- cid :16, /* Core id */
- reserved1 :16; /* Reserved */
- } ppli1_bits;
- u64 ppli1_data;
-} pal_proc_n_log_info1_t;
-
-typedef union pal_proc_n_log_info2_u {
- struct {
- u64 la :16, /* Logical address */
- reserved :48; /* Reserved */
- } ppli2_bits;
- u64 ppli2_data;
-} pal_proc_n_log_info2_t;
-
-typedef struct pal_logical_to_physical_s
-{
- pal_log_overview_t overview;
- pal_proc_n_log_info1_t ppli1;
- pal_proc_n_log_info2_t ppli2;
-} pal_logical_to_physical_t;
-
-#define overview_num_log overview.overview_bits.num_log
-#define overview_tpc overview.overview_bits.tpc
-#define overview_cpp overview.overview_bits.cpp
-#define overview_ppid overview.overview_bits.ppid
-#define log1_tid ppli1.ppli1_bits.tid
-#define log1_cid ppli1.ppli1_bits.cid
-#define log2_la ppli2.ppli2_bits.la
-
-/* Get information on logical to physical processor mappings. */
-static inline s64
-ia64_pal_logical_to_phys(u64 proc_number, pal_logical_to_physical_t *mapping)
-{
- struct ia64_pal_retval iprv;
-
- PAL_CALL(iprv, PAL_LOGICAL_TO_PHYSICAL, proc_number, 0, 0);
-
- if (iprv.status == PAL_STATUS_SUCCESS)
- {
- mapping->overview.overview_data = iprv.v0;
- mapping->ppli1.ppli1_data = iprv.v1;
- mapping->ppli2.ppli2_data = iprv.v2;
- }
-
- return iprv.status;
-}
-
-typedef struct pal_cache_shared_info_s
-{
- u64 num_shared;
- pal_proc_n_log_info1_t ppli1;
- pal_proc_n_log_info2_t ppli2;
-} pal_cache_shared_info_t;
-
-/* Get information on logical to physical processor mappings. */
-static inline s64
-ia64_pal_cache_shared_info(u64 level,
- u64 type,
- u64 proc_number,
- pal_cache_shared_info_t *info)
-{
- struct ia64_pal_retval iprv;
-
- PAL_CALL(iprv, PAL_CACHE_SHARED_INFO, level, type, proc_number);
-
- if (iprv.status == PAL_STATUS_SUCCESS) {
- info->num_shared = iprv.v0;
- info->ppli1.ppli1_data = iprv.v1;
- info->ppli2.ppli2_data = iprv.v2;
- }
-
- return iprv.status;
-}
-#endif /* __ASSEMBLY__ */
-
-#endif /* _ASM_IA64_PAL_H */
diff --git a/arch/ia64/include/asm/param.h b/arch/ia64/include/asm/param.h
deleted file mode 100644
index f0b786227c40..000000000000
--- a/arch/ia64/include/asm/param.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Fundamental kernel parameters.
- *
- * Based on <asm-i386/param.h>.
- *
- * Modified 1998, 1999, 2002-2003
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-#ifndef _ASM_IA64_PARAM_H
-#define _ASM_IA64_PARAM_H
-
-#include <uapi/asm/param.h>
-
-# define HZ CONFIG_HZ
-# define USER_HZ HZ
-# define CLOCKS_PER_SEC HZ /* frequency at which times() counts */
-#endif /* _ASM_IA64_PARAM_H */
diff --git a/arch/ia64/include/asm/parport.h b/arch/ia64/include/asm/parport.h
deleted file mode 100644
index 360ca9bf2f6f..000000000000
--- a/arch/ia64/include/asm/parport.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * parport.h: platform-specific PC-style parport initialisation
- *
- * Copyright (C) 1999, 2000 Tim Waugh <tim@cyberelk.demon.co.uk>
- *
- * This file should only be included by drivers/parport/parport_pc.c.
- */
-
-#ifndef _ASM_IA64_PARPORT_H
-#define _ASM_IA64_PARPORT_H 1
-
-static int parport_pc_find_isa_ports(int autoirq, int autodma);
-
-static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
-{
- return parport_pc_find_isa_ports(autoirq, autodma);
-}
-
-#endif /* _ASM_IA64_PARPORT_H */
diff --git a/arch/ia64/include/asm/patch.h b/arch/ia64/include/asm/patch.h
deleted file mode 100644
index bd487ed22bf5..000000000000
--- a/arch/ia64/include/asm/patch.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_PATCH_H
-#define _ASM_IA64_PATCH_H
-
-/*
- * Copyright (C) 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * There are a number of reasons for patching instructions. Rather than duplicating code
- * all over the place, we put the common stuff here. Reasons for patching: in-kernel
- * module-loader, virtual-to-physical patch-list, McKinley Errata 9 workaround, and gate
- * shared library. Undoubtedly, some of these reasons will disappear and others will
- * be added over time.
- */
-#include <linux/elf.h>
-#include <linux/types.h>
-
-extern void ia64_patch (u64 insn_addr, u64 mask, u64 val); /* patch any insn slot */
-extern void ia64_patch_imm64 (u64 insn_addr, u64 val); /* patch "movl" w/abs. value*/
-extern void ia64_patch_imm60 (u64 insn_addr, u64 val); /* patch "brl" w/ip-rel value */
-
-extern void ia64_patch_mckinley_e9 (unsigned long start, unsigned long end);
-extern void ia64_patch_vtop (unsigned long start, unsigned long end);
-extern void ia64_patch_phys_stack_reg(unsigned long val);
-extern void ia64_patch_rse (unsigned long start, unsigned long end);
-extern void ia64_patch_gate (void);
-
-#endif /* _ASM_IA64_PATCH_H */
diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
deleted file mode 100644
index fa8f545c24c9..000000000000
--- a/arch/ia64/include/asm/pci.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_PCI_H
-#define _ASM_IA64_PCI_H
-
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/scatterlist.h>
-
-#include <asm/io.h>
-#include <asm/hw_irq.h>
-
-struct pci_vector_struct {
- __u16 segment; /* PCI Segment number */
- __u16 bus; /* PCI Bus number */
- __u32 pci_id; /* ACPI split 16 bits device, 16 bits function (see section 6.1.1) */
- __u8 pin; /* PCI PIN (0 = A, 1 = B, 2 = C, 3 = D) */
- __u32 irq; /* IRQ assigned */
-};
-
-/*
- * Can be used to override the logic in pci_scan_bus for skipping already-configured bus
- * numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the
- * loader.
- */
-#define pcibios_assign_all_busses() 0
-
-#define PCIBIOS_MIN_IO 0x1000
-#define PCIBIOS_MIN_MEM 0x10000000
-
-#define HAVE_PCI_MMAP
-#define ARCH_GENERIC_PCI_MMAP_RESOURCE
-#define arch_can_pci_mmap_wc() 1
-
-#define HAVE_PCI_LEGACY
-extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
- struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state);
-
-char *pci_get_legacy_mem(struct pci_bus *bus);
-int pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size);
-int pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size);
-
-struct pci_controller {
- struct acpi_device *companion;
- void *iommu;
- int segment;
- int node; /* nearest node with memory or NUMA_NO_NODE for global allocation */
-
- void *platform_data;
-};
-
-
-#define PCI_CONTROLLER(busdev) ((struct pci_controller *) busdev->sysdata)
-#define pci_domain_nr(busdev) (PCI_CONTROLLER(busdev)->segment)
-
-extern struct pci_ops pci_root_ops;
-
-static inline int pci_proc_domain(struct pci_bus *bus)
-{
- return (pci_domain_nr(bus) != 0);
-}
-
-#endif /* _ASM_IA64_PCI_H */
diff --git a/arch/ia64/include/asm/percpu.h b/arch/ia64/include/asm/percpu.h
deleted file mode 100644
index f357b9bb3576..000000000000
--- a/arch/ia64/include/asm/percpu.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_PERCPU_H
-#define _ASM_IA64_PERCPU_H
-
-/*
- * Copyright (C) 2002-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#ifdef __ASSEMBLY__
-# define THIS_CPU(var) (var) /* use this to mark accesses to per-CPU variables... */
-#else /* !__ASSEMBLY__ */
-
-
-#include <linux/threads.h>
-
-#ifdef CONFIG_SMP
-
-#ifdef HAVE_MODEL_SMALL_ATTRIBUTE
-# define PER_CPU_ATTRIBUTES __attribute__((__model__ (__small__)))
-#endif
-
-#define __my_cpu_offset __ia64_per_cpu_var(local_per_cpu_offset)
-
-extern void *per_cpu_init(void);
-
-#else /* ! SMP */
-
-#define per_cpu_init() (__phys_per_cpu_start)
-
-#endif /* SMP */
-
-#define PER_CPU_BASE_SECTION ".data..percpu"
-
-/*
- * Be extremely careful when taking the address of this variable! Due to virtual
- * remapping, it is different from the canonical address returned by this_cpu_ptr(&var)!
- * On the positive side, using __ia64_per_cpu_var() instead of this_cpu_ptr() is slightly
- * more efficient.
- */
-#define __ia64_per_cpu_var(var) (*({ \
- __verify_pcpu_ptr(&(var)); \
- ((typeof(var) __kernel __force *)&(var)); \
-}))
-
-#include <asm-generic/percpu.h>
-
-/* Equal to __per_cpu_offset[smp_processor_id()], but faster to access: */
-DECLARE_PER_CPU(unsigned long, local_per_cpu_offset);
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _ASM_IA64_PERCPU_H */
diff --git a/arch/ia64/include/asm/pgalloc.h b/arch/ia64/include/asm/pgalloc.h
deleted file mode 100644
index 0fb2b6291d58..000000000000
--- a/arch/ia64/include/asm/pgalloc.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_PGALLOC_H
-#define _ASM_IA64_PGALLOC_H
-
-/*
- * This file contains the functions and defines necessary to allocate
- * page tables.
- *
- * This hopefully works with any (fixed) ia-64 page-size, as defined
- * in <asm/page.h> (currently 8192).
- *
- * Copyright (C) 1998-2001 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2000, Goutham Rao <goutham.rao@intel.com>
- */
-
-
-#include <linux/compiler.h>
-#include <linux/mm.h>
-#include <linux/page-flags.h>
-#include <linux/threads.h>
-
-#include <asm-generic/pgalloc.h>
-
-#include <asm/mmu_context.h>
-
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
- return (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-}
-
-#if CONFIG_PGTABLE_LEVELS == 4
-static inline void
-p4d_populate(struct mm_struct *mm, p4d_t * p4d_entry, pud_t * pud)
-{
- p4d_val(*p4d_entry) = __pa(pud);
-}
-
-#define __pud_free_tlb(tlb, pud, address) pud_free((tlb)->mm, pud)
-#endif /* CONFIG_PGTABLE_LEVELS == 4 */
-
-static inline void
-pud_populate(struct mm_struct *mm, pud_t * pud_entry, pmd_t * pmd)
-{
- pud_val(*pud_entry) = __pa(pmd);
-}
-
-#define __pmd_free_tlb(tlb, pmd, address) pmd_free((tlb)->mm, pmd)
-
-static inline void
-pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, pgtable_t pte)
-{
- pmd_val(*pmd_entry) = page_to_phys(pte);
-}
-
-static inline void
-pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte)
-{
- pmd_val(*pmd_entry) = __pa(pte);
-}
-
-#define __pte_free_tlb(tlb, pte, address) pte_free((tlb)->mm, pte)
-
-#endif /* _ASM_IA64_PGALLOC_H */
diff --git a/arch/ia64/include/asm/pgtable.h b/arch/ia64/include/asm/pgtable.h
deleted file mode 100644
index 9be2d2ba6016..000000000000
--- a/arch/ia64/include/asm/pgtable.h
+++ /dev/null
@@ -1,545 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_PGTABLE_H
-#define _ASM_IA64_PGTABLE_H
-
-/*
- * This file contains the functions and defines necessary to modify and use
- * the IA-64 page table tree.
- *
- * This hopefully works with any (fixed) IA-64 page-size, as defined
- * in <asm/page.h>.
- *
- * Copyright (C) 1998-2005 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-
-#include <asm/mman.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/types.h>
-
-#define IA64_MAX_PHYS_BITS 50 /* max. number of physical address bits (architected) */
-
-/*
- * First, define the various bits in a PTE. Note that the PTE format
- * matches the VHPT short format, the firt doubleword of the VHPD long
- * format, and the first doubleword of the TLB insertion format.
- */
-#define _PAGE_P_BIT 0
-#define _PAGE_A_BIT 5
-#define _PAGE_D_BIT 6
-
-#define _PAGE_P (1 << _PAGE_P_BIT) /* page present bit */
-#define _PAGE_MA_WB (0x0 << 2) /* write back memory attribute */
-#define _PAGE_MA_UC (0x4 << 2) /* uncacheable memory attribute */
-#define _PAGE_MA_UCE (0x5 << 2) /* UC exported attribute */
-#define _PAGE_MA_WC (0x6 << 2) /* write coalescing memory attribute */
-#define _PAGE_MA_NAT (0x7 << 2) /* not-a-thing attribute */
-#define _PAGE_MA_MASK (0x7 << 2)
-#define _PAGE_PL_0 (0 << 7) /* privilege level 0 (kernel) */
-#define _PAGE_PL_1 (1 << 7) /* privilege level 1 (unused) */
-#define _PAGE_PL_2 (2 << 7) /* privilege level 2 (unused) */
-#define _PAGE_PL_3 (3 << 7) /* privilege level 3 (user) */
-#define _PAGE_PL_MASK (3 << 7)
-#define _PAGE_AR_R (0 << 9) /* read only */
-#define _PAGE_AR_RX (1 << 9) /* read & execute */
-#define _PAGE_AR_RW (2 << 9) /* read & write */
-#define _PAGE_AR_RWX (3 << 9) /* read, write & execute */
-#define _PAGE_AR_R_RW (4 << 9) /* read / read & write */
-#define _PAGE_AR_RX_RWX (5 << 9) /* read & exec / read, write & exec */
-#define _PAGE_AR_RWX_RW (6 << 9) /* read, write & exec / read & write */
-#define _PAGE_AR_X_RX (7 << 9) /* exec & promote / read & exec */
-#define _PAGE_AR_MASK (7 << 9)
-#define _PAGE_AR_SHIFT 9
-#define _PAGE_A (1 << _PAGE_A_BIT) /* page accessed bit */
-#define _PAGE_D (1 << _PAGE_D_BIT) /* page dirty bit */
-#define _PAGE_PPN_MASK (((__IA64_UL(1) << IA64_MAX_PHYS_BITS) - 1) & ~0xfffUL)
-#define _PAGE_ED (__IA64_UL(1) << 52) /* exception deferral */
-#define _PAGE_PROTNONE (__IA64_UL(1) << 63)
-
-/* We borrow bit 7 to store the exclusive marker in swap PTEs. */
-#define _PAGE_SWP_EXCLUSIVE (1 << 7)
-
-#define _PFN_MASK _PAGE_PPN_MASK
-/* Mask of bits which may be changed by pte_modify(); the odd bits are there for _PAGE_PROTNONE */
-#define _PAGE_CHG_MASK (_PAGE_P | _PAGE_PROTNONE | _PAGE_PL_MASK | _PAGE_AR_MASK | _PAGE_ED)
-
-#define _PAGE_SIZE_4K 12
-#define _PAGE_SIZE_8K 13
-#define _PAGE_SIZE_16K 14
-#define _PAGE_SIZE_64K 16
-#define _PAGE_SIZE_256K 18
-#define _PAGE_SIZE_1M 20
-#define _PAGE_SIZE_4M 22
-#define _PAGE_SIZE_16M 24
-#define _PAGE_SIZE_64M 26
-#define _PAGE_SIZE_256M 28
-#define _PAGE_SIZE_1G 30
-#define _PAGE_SIZE_4G 32
-
-#define __ACCESS_BITS _PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_MA_WB
-#define __DIRTY_BITS_NO_ED _PAGE_A | _PAGE_P | _PAGE_D | _PAGE_MA_WB
-#define __DIRTY_BITS _PAGE_ED | __DIRTY_BITS_NO_ED
-
-/*
- * How many pointers will a page table level hold expressed in shift
- */
-#define PTRS_PER_PTD_SHIFT (PAGE_SHIFT-3)
-
-/*
- * Definitions for fourth level:
- */
-#define PTRS_PER_PTE (__IA64_UL(1) << (PTRS_PER_PTD_SHIFT))
-
-/*
- * Definitions for third level:
- *
- * PMD_SHIFT determines the size of the area a third-level page table
- * can map.
- */
-#define PMD_SHIFT (PAGE_SHIFT + (PTRS_PER_PTD_SHIFT))
-#define PMD_SIZE (1UL << PMD_SHIFT)
-#define PMD_MASK (~(PMD_SIZE-1))
-#define PTRS_PER_PMD (1UL << (PTRS_PER_PTD_SHIFT))
-
-#if CONFIG_PGTABLE_LEVELS == 4
-/*
- * Definitions for second level:
- *
- * PUD_SHIFT determines the size of the area a second-level page table
- * can map.
- */
-#define PUD_SHIFT (PMD_SHIFT + (PTRS_PER_PTD_SHIFT))
-#define PUD_SIZE (1UL << PUD_SHIFT)
-#define PUD_MASK (~(PUD_SIZE-1))
-#define PTRS_PER_PUD (1UL << (PTRS_PER_PTD_SHIFT))
-#endif
-
-/*
- * Definitions for first level:
- *
- * PGDIR_SHIFT determines what a first-level page table entry can map.
- */
-#if CONFIG_PGTABLE_LEVELS == 4
-#define PGDIR_SHIFT (PUD_SHIFT + (PTRS_PER_PTD_SHIFT))
-#else
-#define PGDIR_SHIFT (PMD_SHIFT + (PTRS_PER_PTD_SHIFT))
-#endif
-#define PGDIR_SIZE (__IA64_UL(1) << PGDIR_SHIFT)
-#define PGDIR_MASK (~(PGDIR_SIZE-1))
-#define PTRS_PER_PGD_SHIFT PTRS_PER_PTD_SHIFT
-#define PTRS_PER_PGD (1UL << PTRS_PER_PGD_SHIFT)
-#define USER_PTRS_PER_PGD (5*PTRS_PER_PGD/8) /* regions 0-4 are user regions */
-
-/*
- * All the normal masks have the "page accessed" bits on, as any time
- * they are used, the page is accessed. They are cleared only by the
- * page-out routines.
- */
-#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_A)
-#define PAGE_SHARED __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW)
-#define PAGE_READONLY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
-#define PAGE_COPY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
-#define PAGE_COPY_EXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX)
-#define PAGE_GATE __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX)
-#define PAGE_KERNEL __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX)
-#define PAGE_KERNELRX __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX)
-#define PAGE_KERNEL_UC __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX | \
- _PAGE_MA_UC)
-
-# ifndef __ASSEMBLY__
-
-#include <linux/sched/mm.h> /* for mm_struct */
-#include <linux/bitops.h>
-#include <asm/cacheflush.h>
-#include <asm/mmu_context.h>
-
-/*
- * Next come the mappings that determine how mmap() protection bits
- * (PROT_EXEC, PROT_READ, PROT_WRITE, PROT_NONE) get implemented. The
- * _P version gets used for a private shared memory segment, the _S
- * version gets used for a shared memory segment with MAP_SHARED on.
- * In a private shared memory segment, we do a copy-on-write if a task
- * attempts to write to the page.
- */
- /* xwr */
-#define pgd_ERROR(e) printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
-#if CONFIG_PGTABLE_LEVELS == 4
-#define pud_ERROR(e) printk("%s:%d: bad pud %016lx.\n", __FILE__, __LINE__, pud_val(e))
-#endif
-#define pmd_ERROR(e) printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
-#define pte_ERROR(e) printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
-
-
-/*
- * Some definitions to translate between mem_map, PTEs, and page addresses:
- */
-
-
-/* Quick test to see if ADDR is a (potentially) valid physical address. */
-static inline long
-ia64_phys_addr_valid (unsigned long addr)
-{
- return (addr & (local_cpu_data->unimpl_pa_mask)) == 0;
-}
-
-/*
- * Now come the defines and routines to manage and access the three-level
- * page table.
- */
-
-
-#define VMALLOC_START (RGN_BASE(RGN_GATE) + 0x200000000UL)
-#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_SPARSEMEM_VMEMMAP)
-/* SPARSEMEM_VMEMMAP uses half of vmalloc... */
-# define VMALLOC_END (RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 10)))
-# define vmemmap ((struct page *)VMALLOC_END)
-#else
-# define VMALLOC_END (RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 9)))
-#endif
-
-/* fs/proc/kcore.c */
-#define kc_vaddr_to_offset(v) ((v) - RGN_BASE(RGN_GATE))
-#define kc_offset_to_vaddr(o) ((o) + RGN_BASE(RGN_GATE))
-
-#define RGN_MAP_SHIFT (PGDIR_SHIFT + PTRS_PER_PGD_SHIFT - 3)
-#define RGN_MAP_LIMIT ((1UL << RGN_MAP_SHIFT) - PAGE_SIZE) /* per region addr limit */
-
-#define PFN_PTE_SHIFT PAGE_SHIFT
-/*
- * Conversion functions: convert page frame number (pfn) and a protection value to a page
- * table entry (pte).
- */
-#define pfn_pte(pfn, pgprot) \
-({ pte_t __pte; pte_val(__pte) = ((pfn) << PAGE_SHIFT) | pgprot_val(pgprot); __pte; })
-
-/* Extract pfn from pte. */
-#define pte_pfn(_pte) ((pte_val(_pte) & _PFN_MASK) >> PAGE_SHIFT)
-
-#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
-
-/* This takes a physical page address that is used by the remapping functions */
-#define mk_pte_phys(physpage, pgprot) \
-({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; })
-
-#define pte_modify(_pte, newprot) \
- (__pte((pte_val(_pte) & ~_PAGE_CHG_MASK) | (pgprot_val(newprot) & _PAGE_CHG_MASK)))
-
-#define pte_none(pte) (!pte_val(pte))
-#define pte_present(pte) (pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE))
-#define pte_clear(mm,addr,pte) (pte_val(*(pte)) = 0UL)
-/* pte_page() returns the "struct page *" corresponding to the PTE: */
-#define pte_page(pte) virt_to_page(((pte_val(pte) & _PFN_MASK) + PAGE_OFFSET))
-
-#define pmd_none(pmd) (!pmd_val(pmd))
-#define pmd_bad(pmd) (!ia64_phys_addr_valid(pmd_val(pmd)))
-#define pmd_present(pmd) (pmd_val(pmd) != 0UL)
-#define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0UL)
-#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val(pmd) & _PFN_MASK))
-#define pmd_pfn(pmd) ((pmd_val(pmd) & _PFN_MASK) >> PAGE_SHIFT)
-#define pmd_page(pmd) virt_to_page((pmd_val(pmd) + PAGE_OFFSET))
-
-#define pud_none(pud) (!pud_val(pud))
-#define pud_bad(pud) (!ia64_phys_addr_valid(pud_val(pud)))
-#define pud_present(pud) (pud_val(pud) != 0UL)
-#define pud_clear(pudp) (pud_val(*(pudp)) = 0UL)
-#define pud_pgtable(pud) ((pmd_t *) __va(pud_val(pud) & _PFN_MASK))
-#define pud_page(pud) virt_to_page((pud_val(pud) + PAGE_OFFSET))
-
-#if CONFIG_PGTABLE_LEVELS == 4
-#define p4d_none(p4d) (!p4d_val(p4d))
-#define p4d_bad(p4d) (!ia64_phys_addr_valid(p4d_val(p4d)))
-#define p4d_present(p4d) (p4d_val(p4d) != 0UL)
-#define p4d_clear(p4dp) (p4d_val(*(p4dp)) = 0UL)
-#define p4d_pgtable(p4d) ((pud_t *) __va(p4d_val(p4d) & _PFN_MASK))
-#define p4d_page(p4d) virt_to_page((p4d_val(p4d) + PAGE_OFFSET))
-#endif
-
-/*
- * The following have defined behavior only work if pte_present() is true.
- */
-#define pte_write(pte) ((unsigned) (((pte_val(pte) & _PAGE_AR_MASK) >> _PAGE_AR_SHIFT) - 2) <= 4)
-#define pte_exec(pte) ((pte_val(pte) & _PAGE_AR_RX) != 0)
-#define pte_dirty(pte) ((pte_val(pte) & _PAGE_D) != 0)
-#define pte_young(pte) ((pte_val(pte) & _PAGE_A) != 0)
-
-/*
- * Note: we convert AR_RWX to AR_RX and AR_RW to AR_R by clearing the 2nd bit in the
- * access rights:
- */
-#define pte_wrprotect(pte) (__pte(pte_val(pte) & ~_PAGE_AR_RW))
-#define pte_mkwrite_novma(pte) (__pte(pte_val(pte) | _PAGE_AR_RW))
-#define pte_mkold(pte) (__pte(pte_val(pte) & ~_PAGE_A))
-#define pte_mkyoung(pte) (__pte(pte_val(pte) | _PAGE_A))
-#define pte_mkclean(pte) (__pte(pte_val(pte) & ~_PAGE_D))
-#define pte_mkdirty(pte) (__pte(pte_val(pte) | _PAGE_D))
-#define pte_mkhuge(pte) (__pte(pte_val(pte)))
-
-/*
- * Because ia64's Icache and Dcache is not coherent (on a cpu), we need to
- * sync icache and dcache when we insert *new* executable page.
- * __ia64_sync_icache_dcache() check Pg_arch_1 bit and flush icache
- * if necessary.
- *
- * set_pte() is also called by the kernel, but we can expect that the kernel
- * flushes icache explicitly if necessary.
- */
-#define pte_present_exec_user(pte)\
- ((pte_val(pte) & (_PAGE_P | _PAGE_PL_MASK | _PAGE_AR_RX)) == \
- (_PAGE_P | _PAGE_PL_3 | _PAGE_AR_RX))
-
-extern void __ia64_sync_icache_dcache(pte_t pteval);
-static inline void set_pte(pte_t *ptep, pte_t pteval)
-{
- /* page is present && page is user && page is executable
- * && (page swapin or new page or page migration
- * || copy_on_write with page copying.)
- */
- if (pte_present_exec_user(pteval) &&
- (!pte_present(*ptep) ||
- pte_pfn(*ptep) != pte_pfn(pteval)))
- /* load_module() calles flush_icache_range() explicitly*/
- __ia64_sync_icache_dcache(pteval);
- *ptep = pteval;
-}
-
-/*
- * Make page protection values cacheable, uncacheable, or write-
- * combining. Note that "protection" is really a misnomer here as the
- * protection value contains the memory attribute bits, dirty bits, and
- * various other bits as well.
- */
-#define pgprot_cacheable(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WB)
-#define pgprot_noncached(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_UC)
-#define pgprot_writecombine(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WC)
-
-struct file;
-extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
- unsigned long size, pgprot_t vma_prot);
-#define __HAVE_PHYS_MEM_ACCESS_PROT
-
-static inline unsigned long
-pgd_index (unsigned long address)
-{
- unsigned long region = address >> 61;
- unsigned long l1index = (address >> PGDIR_SHIFT) & ((PTRS_PER_PGD >> 3) - 1);
-
- return (region << (PAGE_SHIFT - 6)) | l1index;
-}
-#define pgd_index pgd_index
-
-/*
- * In the kernel's mapped region we know everything is in region number 5, so
- * as an optimisation its PGD already points to the area for that region.
- * However, this also means that we cannot use pgd_index() and we must
- * never add the region here.
- */
-#define pgd_offset_k(addr) \
- (init_mm.pgd + (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)))
-
-/* Look up a pgd entry in the gate area. On IA-64, the gate-area
- resides in the kernel-mapped segment, hence we use pgd_offset_k()
- here. */
-#define pgd_offset_gate(mm, addr) pgd_offset_k(addr)
-
-/* atomic versions of the some PTE manipulations: */
-
-static inline int
-ptep_test_and_clear_young (struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-#ifdef CONFIG_SMP
- if (!pte_young(*ptep))
- return 0;
- return test_and_clear_bit(_PAGE_A_BIT, ptep);
-#else
- pte_t pte = *ptep;
- if (!pte_young(pte))
- return 0;
- set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte));
- return 1;
-#endif
-}
-
-static inline pte_t
-ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-#ifdef CONFIG_SMP
- return __pte(xchg((long *) ptep, 0));
-#else
- pte_t pte = *ptep;
- pte_clear(mm, addr, ptep);
- return pte;
-#endif
-}
-
-static inline void
-ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-#ifdef CONFIG_SMP
- unsigned long new, old;
-
- do {
- old = pte_val(*ptep);
- new = pte_val(pte_wrprotect(__pte (old)));
- } while (cmpxchg((unsigned long *) ptep, old, new) != old);
-#else
- pte_t old_pte = *ptep;
- set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
-#endif
-}
-
-static inline int
-pte_same (pte_t a, pte_t b)
-{
- return pte_val(a) == pte_val(b);
-}
-
-#define update_mmu_cache_range(vmf, vma, address, ptep, nr) do { } while (0)
-#define update_mmu_cache(vma, address, ptep) do { } while (0)
-
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-extern void paging_init (void);
-
-/*
- * Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that
- * are !pte_none() && !pte_present().
- *
- * Note: The macros below rely on the fact that MAX_SWAPFILES_SHIFT <= number of
- * bits in the swap-type field of the swap pte. It would be nice to
- * enforce that, but we can't easily include <linux/swap.h> here.
- * (Of course, better still would be to define MAX_SWAPFILES_SHIFT here...).
- *
- * Format of swap pte:
- * bit 0 : present bit (must be zero)
- * bits 1- 6: swap type
- * bit 7 : exclusive marker
- * bits 8-62: swap offset
- * bit 63 : _PAGE_PROTNONE bit
- */
-#define __swp_type(entry) (((entry).val >> 1) & 0x3f)
-#define __swp_offset(entry) (((entry).val << 1) >> 9)
-#define __swp_entry(type, offset) ((swp_entry_t) { ((type & 0x3f) << 1) | \
- ((long) (offset) << 8) })
-#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
-#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
-
-static inline int pte_swp_exclusive(pte_t pte)
-{
- return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
-}
-
-static inline pte_t pte_swp_mkexclusive(pte_t pte)
-{
- pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;
- return pte;
-}
-
-static inline pte_t pte_swp_clear_exclusive(pte_t pte)
-{
- pte_val(pte) &= ~_PAGE_SWP_EXCLUSIVE;
- return pte;
-}
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
-extern struct page *zero_page_memmap_ptr;
-#define ZERO_PAGE(vaddr) (zero_page_memmap_ptr)
-
-/* We provide our own get_unmapped_area to cope with VA holes for userland */
-#define HAVE_ARCH_UNMAPPED_AREA
-
-#ifdef CONFIG_HUGETLB_PAGE
-#define HUGETLB_PGDIR_SHIFT (HPAGE_SHIFT + 2*(PAGE_SHIFT-3))
-#define HUGETLB_PGDIR_SIZE (__IA64_UL(1) << HUGETLB_PGDIR_SHIFT)
-#define HUGETLB_PGDIR_MASK (~(HUGETLB_PGDIR_SIZE-1))
-#endif
-
-
-#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-/*
- * Update PTEP with ENTRY, which is guaranteed to be a less
- * restrictive PTE. That is, ENTRY may have the ACCESSED, DIRTY, and
- * WRITABLE bits turned on, when the value at PTEP did not. The
- * WRITABLE bit may only be turned if SAFELY_WRITABLE is TRUE.
- *
- * SAFELY_WRITABLE is TRUE if we can update the value at PTEP without
- * having to worry about races. On SMP machines, there are only two
- * cases where this is true:
- *
- * (1) *PTEP has the PRESENT bit turned OFF
- * (2) ENTRY has the DIRTY bit turned ON
- *
- * On ia64, we could implement this routine with a cmpxchg()-loop
- * which ORs in the _PAGE_A/_PAGE_D bit if they're set in ENTRY.
- * However, like on x86, we can get a more streamlined version by
- * observing that it is OK to drop ACCESSED bit updates when
- * SAFELY_WRITABLE is FALSE. Besides being rare, all that would do is
- * result in an extra Access-bit fault, which would then turn on the
- * ACCESSED bit in the low-level fault handler (iaccess_bit or
- * daccess_bit in ivt.S).
- */
-#ifdef CONFIG_SMP
-# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable) \
-({ \
- int __changed = !pte_same(*(__ptep), __entry); \
- if (__changed && __safely_writable) { \
- set_pte(__ptep, __entry); \
- flush_tlb_page(__vma, __addr); \
- } \
- __changed; \
-})
-#else
-# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable) \
-({ \
- int __changed = !pte_same(*(__ptep), __entry); \
- if (__changed) { \
- set_pte_at((__vma)->vm_mm, (__addr), __ptep, __entry); \
- flush_tlb_page(__vma, __addr); \
- } \
- __changed; \
-})
-#endif
-# endif /* !__ASSEMBLY__ */
-
-/*
- * Identity-mapped regions use a large page size. We'll call such large pages
- * "granules". If you can think of a better name that's unambiguous, let me
- * know...
- */
-#if defined(CONFIG_IA64_GRANULE_64MB)
-# define IA64_GRANULE_SHIFT _PAGE_SIZE_64M
-#elif defined(CONFIG_IA64_GRANULE_16MB)
-# define IA64_GRANULE_SHIFT _PAGE_SIZE_16M
-#endif
-#define IA64_GRANULE_SIZE (1 << IA64_GRANULE_SHIFT)
-/*
- * log2() of the page size we use to map the kernel image (IA64_TR_KERNEL):
- */
-#define KERNEL_TR_PAGE_SHIFT _PAGE_SIZE_64M
-#define KERNEL_TR_PAGE_SIZE (1 << KERNEL_TR_PAGE_SHIFT)
-
-/* These tell get_user_pages() that the first gate page is accessible from user-level. */
-#define FIXADDR_USER_START GATE_ADDR
-#ifdef HAVE_BUGGY_SEGREL
-# define FIXADDR_USER_END (GATE_ADDR + 2*PAGE_SIZE)
-#else
-# define FIXADDR_USER_END (GATE_ADDR + 2*PERCPU_PAGE_SIZE)
-#endif
-
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTE_SAME
-#define __HAVE_ARCH_PGD_OFFSET_GATE
-
-
-#if CONFIG_PGTABLE_LEVELS == 3
-#include <asm-generic/pgtable-nopud.h>
-#endif
-#include <asm-generic/pgtable-nop4d.h>
-
-#endif /* _ASM_IA64_PGTABLE_H */
diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h
deleted file mode 100644
index 47e3801b526a..000000000000
--- a/arch/ia64/include/asm/processor.h
+++ /dev/null
@@ -1,660 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_PROCESSOR_H
-#define _ASM_IA64_PROCESSOR_H
-
-/*
- * Copyright (C) 1998-2004 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
- *
- * 11/24/98 S.Eranian added ia64_set_iva()
- * 12/03/99 D. Mosberger implement thread_saved_pc() via kernel unwind API
- * 06/16/00 A. Mallick added csd/ssd/tssd for ia32 support
- */
-
-
-#include <asm/intrinsics.h>
-#include <asm/kregs.h>
-#include <asm/ptrace.h>
-#include <asm/ustack.h>
-
-#define IA64_NUM_PHYS_STACK_REG 96
-#define IA64_NUM_DBG_REGS 8
-
-#define DEFAULT_MAP_BASE __IA64_UL_CONST(0x2000000000000000)
-#define DEFAULT_TASK_SIZE __IA64_UL_CONST(0xa000000000000000)
-
-/*
- * TASK_SIZE really is a mis-named. It really is the maximum user
- * space address (plus one). On IA-64, there are five regions of 2TB
- * each (assuming 8KB page size), for a total of 8TB of user virtual
- * address space.
- */
-#define TASK_SIZE DEFAULT_TASK_SIZE
-
-/*
- * This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (current->thread.map_base)
-
-#define IA64_THREAD_FPH_VALID (__IA64_UL(1) << 0) /* floating-point high state valid? */
-#define IA64_THREAD_DBG_VALID (__IA64_UL(1) << 1) /* debug registers valid? */
-#define IA64_THREAD_PM_VALID (__IA64_UL(1) << 2) /* performance registers valid? */
-#define IA64_THREAD_UAC_NOPRINT (__IA64_UL(1) << 3) /* don't log unaligned accesses */
-#define IA64_THREAD_UAC_SIGBUS (__IA64_UL(1) << 4) /* generate SIGBUS on unaligned acc. */
-#define IA64_THREAD_MIGRATION (__IA64_UL(1) << 5) /* require migration
- sync at ctx sw */
-#define IA64_THREAD_FPEMU_NOPRINT (__IA64_UL(1) << 6) /* don't log any fpswa faults */
-#define IA64_THREAD_FPEMU_SIGFPE (__IA64_UL(1) << 7) /* send a SIGFPE for fpswa faults */
-
-#define IA64_THREAD_UAC_SHIFT 3
-#define IA64_THREAD_UAC_MASK (IA64_THREAD_UAC_NOPRINT | IA64_THREAD_UAC_SIGBUS)
-#define IA64_THREAD_FPEMU_SHIFT 6
-#define IA64_THREAD_FPEMU_MASK (IA64_THREAD_FPEMU_NOPRINT | IA64_THREAD_FPEMU_SIGFPE)
-
-
-/*
- * This shift should be large enough to be able to represent 1000000000/itc_freq with good
- * accuracy while being small enough to fit 10*1000000000<<IA64_NSEC_PER_CYC_SHIFT in 64 bits
- * (this will give enough slack to represent 10 seconds worth of time as a scaled number).
- */
-#define IA64_NSEC_PER_CYC_SHIFT 30
-
-#ifndef __ASSEMBLY__
-
-#include <linux/cache.h>
-#include <linux/compiler.h>
-#include <linux/threads.h>
-#include <linux/types.h>
-#include <linux/bitops.h>
-
-#include <asm/fpu.h>
-#include <asm/page.h>
-#include <asm/percpu.h>
-#include <asm/rse.h>
-#include <asm/unwind.h>
-#include <linux/atomic.h>
-#ifdef CONFIG_NUMA
-#include <asm/nodedata.h>
-#endif
-
-/* like above but expressed as bitfields for more efficient access: */
-struct ia64_psr {
- __u64 reserved0 : 1;
- __u64 be : 1;
- __u64 up : 1;
- __u64 ac : 1;
- __u64 mfl : 1;
- __u64 mfh : 1;
- __u64 reserved1 : 7;
- __u64 ic : 1;
- __u64 i : 1;
- __u64 pk : 1;
- __u64 reserved2 : 1;
- __u64 dt : 1;
- __u64 dfl : 1;
- __u64 dfh : 1;
- __u64 sp : 1;
- __u64 pp : 1;
- __u64 di : 1;
- __u64 si : 1;
- __u64 db : 1;
- __u64 lp : 1;
- __u64 tb : 1;
- __u64 rt : 1;
- __u64 reserved3 : 4;
- __u64 cpl : 2;
- __u64 is : 1;
- __u64 mc : 1;
- __u64 it : 1;
- __u64 id : 1;
- __u64 da : 1;
- __u64 dd : 1;
- __u64 ss : 1;
- __u64 ri : 2;
- __u64 ed : 1;
- __u64 bn : 1;
- __u64 reserved4 : 19;
-};
-
-union ia64_isr {
- __u64 val;
- struct {
- __u64 code : 16;
- __u64 vector : 8;
- __u64 reserved1 : 8;
- __u64 x : 1;
- __u64 w : 1;
- __u64 r : 1;
- __u64 na : 1;
- __u64 sp : 1;
- __u64 rs : 1;
- __u64 ir : 1;
- __u64 ni : 1;
- __u64 so : 1;
- __u64 ei : 2;
- __u64 ed : 1;
- __u64 reserved2 : 20;
- };
-};
-
-union ia64_lid {
- __u64 val;
- struct {
- __u64 rv : 16;
- __u64 eid : 8;
- __u64 id : 8;
- __u64 ig : 32;
- };
-};
-
-union ia64_tpr {
- __u64 val;
- struct {
- __u64 ig0 : 4;
- __u64 mic : 4;
- __u64 rsv : 8;
- __u64 mmi : 1;
- __u64 ig1 : 47;
- };
-};
-
-union ia64_itir {
- __u64 val;
- struct {
- __u64 rv3 : 2; /* 0-1 */
- __u64 ps : 6; /* 2-7 */
- __u64 key : 24; /* 8-31 */
- __u64 rv4 : 32; /* 32-63 */
- };
-};
-
-union ia64_rr {
- __u64 val;
- struct {
- __u64 ve : 1; /* enable hw walker */
- __u64 reserved0: 1; /* reserved */
- __u64 ps : 6; /* log page size */
- __u64 rid : 24; /* region id */
- __u64 reserved1: 32; /* reserved */
- };
-};
-
-/*
- * CPU type, hardware bug flags, and per-CPU state. Frequently used
- * state comes earlier:
- */
-struct cpuinfo_ia64 {
- unsigned int softirq_pending;
- unsigned long itm_delta; /* # of clock cycles between clock ticks */
- unsigned long itm_next; /* interval timer mask value to use for next clock tick */
- unsigned long nsec_per_cyc; /* (1000000000<<IA64_NSEC_PER_CYC_SHIFT)/itc_freq */
- unsigned long unimpl_va_mask; /* mask of unimplemented virtual address bits (from PAL) */
- unsigned long unimpl_pa_mask; /* mask of unimplemented physical address bits (from PAL) */
- unsigned long itc_freq; /* frequency of ITC counter */
- unsigned long proc_freq; /* frequency of processor */
- unsigned long cyc_per_usec; /* itc_freq/1000000 */
- unsigned long ptce_base;
- unsigned int ptce_count[2];
- unsigned int ptce_stride[2];
- struct task_struct *ksoftirqd; /* kernel softirq daemon for this CPU */
-
-#ifdef CONFIG_SMP
- unsigned long loops_per_jiffy;
- int cpu;
- unsigned int socket_id; /* physical processor socket id */
- unsigned short core_id; /* core id */
- unsigned short thread_id; /* thread id */
- unsigned short num_log; /* Total number of logical processors on
- * this socket that were successfully booted */
- unsigned char cores_per_socket; /* Cores per processor socket */
- unsigned char threads_per_core; /* Threads per core */
-#endif
-
- /* CPUID-derived information: */
- unsigned long ppn;
- unsigned long features;
- unsigned char number;
- unsigned char revision;
- unsigned char model;
- unsigned char family;
- unsigned char archrev;
- char vendor[16];
- char *model_name;
-
-#ifdef CONFIG_NUMA
- struct ia64_node_data *node_data;
-#endif
-};
-
-DECLARE_PER_CPU(struct cpuinfo_ia64, ia64_cpu_info);
-
-/*
- * The "local" data variable. It refers to the per-CPU data of the currently executing
- * CPU, much like "current" points to the per-task data of the currently executing task.
- * Do not use the address of local_cpu_data, since it will be different from
- * cpu_data(smp_processor_id())!
- */
-#define local_cpu_data (&__ia64_per_cpu_var(ia64_cpu_info))
-#define cpu_data(cpu) (&per_cpu(ia64_cpu_info, cpu))
-
-extern void print_cpu_info (struct cpuinfo_ia64 *);
-
-#define SET_UNALIGN_CTL(task,value) \
-({ \
- (task)->thread.flags = (((task)->thread.flags & ~IA64_THREAD_UAC_MASK) \
- | (((value) << IA64_THREAD_UAC_SHIFT) & IA64_THREAD_UAC_MASK)); \
- 0; \
-})
-#define GET_UNALIGN_CTL(task,addr) \
-({ \
- put_user(((task)->thread.flags & IA64_THREAD_UAC_MASK) >> IA64_THREAD_UAC_SHIFT, \
- (int __user *) (addr)); \
-})
-
-#define SET_FPEMU_CTL(task,value) \
-({ \
- (task)->thread.flags = (((task)->thread.flags & ~IA64_THREAD_FPEMU_MASK) \
- | (((value) << IA64_THREAD_FPEMU_SHIFT) & IA64_THREAD_FPEMU_MASK)); \
- 0; \
-})
-#define GET_FPEMU_CTL(task,addr) \
-({ \
- put_user(((task)->thread.flags & IA64_THREAD_FPEMU_MASK) >> IA64_THREAD_FPEMU_SHIFT, \
- (int __user *) (addr)); \
-})
-
-struct thread_struct {
- __u32 flags; /* various thread flags (see IA64_THREAD_*) */
- /* writing on_ustack is performance-critical, so it's worth spending 8 bits on it... */
- __u8 on_ustack; /* executing on user-stacks? */
- __u8 pad[3];
- __u64 ksp; /* kernel stack pointer */
- __u64 map_base; /* base address for get_unmapped_area() */
- __u64 rbs_bot; /* the base address for the RBS */
- int last_fph_cpu; /* CPU that may hold the contents of f32-f127 */
- unsigned long dbr[IA64_NUM_DBG_REGS];
- unsigned long ibr[IA64_NUM_DBG_REGS];
- struct ia64_fpreg fph[96]; /* saved/loaded on demand */
-};
-
-#define INIT_THREAD { \
- .flags = 0, \
- .on_ustack = 0, \
- .ksp = 0, \
- .map_base = DEFAULT_MAP_BASE, \
- .rbs_bot = STACK_TOP - DEFAULT_USER_STACK_SIZE, \
- .last_fph_cpu = -1, \
- .dbr = {0, }, \
- .ibr = {0, }, \
- .fph = {{{{0}}}, } \
-}
-
-#define start_thread(regs,new_ip,new_sp) do { \
- regs->cr_ipsr = ((regs->cr_ipsr | (IA64_PSR_BITS_TO_SET | IA64_PSR_CPL)) \
- & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_RI | IA64_PSR_IS)); \
- regs->cr_iip = new_ip; \
- regs->ar_rsc = 0xf; /* eager mode, privilege level 3 */ \
- regs->ar_rnat = 0; \
- regs->ar_bspstore = current->thread.rbs_bot; \
- regs->ar_fpsr = FPSR_DEFAULT; \
- regs->loadrs = 0; \
- regs->r8 = get_dumpable(current->mm); /* set "don't zap registers" flag */ \
- regs->r12 = new_sp - 16; /* allocate 16 byte scratch area */ \
- if (unlikely(get_dumpable(current->mm) != SUID_DUMP_USER)) { \
- /* \
- * Zap scratch regs to avoid leaking bits between processes with different \
- * uid/privileges. \
- */ \
- regs->ar_pfs = 0; regs->b0 = 0; regs->pr = 0; \
- regs->r1 = 0; regs->r9 = 0; regs->r11 = 0; regs->r13 = 0; regs->r15 = 0; \
- } \
-} while (0)
-
-/* Forward declarations, a strange C thing... */
-struct mm_struct;
-struct task_struct;
-
-/* Get wait channel for task P. */
-extern unsigned long __get_wchan (struct task_struct *p);
-
-/* Return instruction pointer of blocked task TSK. */
-#define KSTK_EIP(tsk) \
- ({ \
- struct pt_regs *_regs = task_pt_regs(tsk); \
- _regs->cr_iip + ia64_psr(_regs)->ri; \
- })
-
-/* Return stack pointer of blocked task TSK. */
-#define KSTK_ESP(tsk) ((tsk)->thread.ksp)
-
-extern void ia64_getreg_unknown_kr (void);
-extern void ia64_setreg_unknown_kr (void);
-
-#define ia64_get_kr(regnum) \
-({ \
- unsigned long r = 0; \
- \
- switch (regnum) { \
- case 0: r = ia64_getreg(_IA64_REG_AR_KR0); break; \
- case 1: r = ia64_getreg(_IA64_REG_AR_KR1); break; \
- case 2: r = ia64_getreg(_IA64_REG_AR_KR2); break; \
- case 3: r = ia64_getreg(_IA64_REG_AR_KR3); break; \
- case 4: r = ia64_getreg(_IA64_REG_AR_KR4); break; \
- case 5: r = ia64_getreg(_IA64_REG_AR_KR5); break; \
- case 6: r = ia64_getreg(_IA64_REG_AR_KR6); break; \
- case 7: r = ia64_getreg(_IA64_REG_AR_KR7); break; \
- default: ia64_getreg_unknown_kr(); break; \
- } \
- r; \
-})
-
-#define ia64_set_kr(regnum, r) \
-({ \
- switch (regnum) { \
- case 0: ia64_setreg(_IA64_REG_AR_KR0, r); break; \
- case 1: ia64_setreg(_IA64_REG_AR_KR1, r); break; \
- case 2: ia64_setreg(_IA64_REG_AR_KR2, r); break; \
- case 3: ia64_setreg(_IA64_REG_AR_KR3, r); break; \
- case 4: ia64_setreg(_IA64_REG_AR_KR4, r); break; \
- case 5: ia64_setreg(_IA64_REG_AR_KR5, r); break; \
- case 6: ia64_setreg(_IA64_REG_AR_KR6, r); break; \
- case 7: ia64_setreg(_IA64_REG_AR_KR7, r); break; \
- default: ia64_setreg_unknown_kr(); break; \
- } \
-})
-
-/*
- * The following three macros can't be inline functions because we don't have struct
- * task_struct at this point.
- */
-
-/*
- * Return TRUE if task T owns the fph partition of the CPU we're running on.
- * Must be called from code that has preemption disabled.
- */
-#define ia64_is_local_fpu_owner(t) \
-({ \
- struct task_struct *__ia64_islfo_task = (t); \
- (__ia64_islfo_task->thread.last_fph_cpu == smp_processor_id() \
- && __ia64_islfo_task == (struct task_struct *) ia64_get_kr(IA64_KR_FPU_OWNER)); \
-})
-
-/*
- * Mark task T as owning the fph partition of the CPU we're running on.
- * Must be called from code that has preemption disabled.
- */
-#define ia64_set_local_fpu_owner(t) do { \
- struct task_struct *__ia64_slfo_task = (t); \
- __ia64_slfo_task->thread.last_fph_cpu = smp_processor_id(); \
- ia64_set_kr(IA64_KR_FPU_OWNER, (unsigned long) __ia64_slfo_task); \
-} while (0)
-
-/* Mark the fph partition of task T as being invalid on all CPUs. */
-#define ia64_drop_fpu(t) ((t)->thread.last_fph_cpu = -1)
-
-extern void __ia64_init_fpu (void);
-extern void __ia64_save_fpu (struct ia64_fpreg *fph);
-extern void __ia64_load_fpu (struct ia64_fpreg *fph);
-extern void ia64_save_debug_regs (unsigned long *save_area);
-extern void ia64_load_debug_regs (unsigned long *save_area);
-
-#define ia64_fph_enable() do { ia64_rsm(IA64_PSR_DFH); ia64_srlz_d(); } while (0)
-#define ia64_fph_disable() do { ia64_ssm(IA64_PSR_DFH); ia64_srlz_d(); } while (0)
-
-/* load fp 0.0 into fph */
-static inline void
-ia64_init_fpu (void) {
- ia64_fph_enable();
- __ia64_init_fpu();
- ia64_fph_disable();
-}
-
-/* save f32-f127 at FPH */
-static inline void
-ia64_save_fpu (struct ia64_fpreg *fph) {
- ia64_fph_enable();
- __ia64_save_fpu(fph);
- ia64_fph_disable();
-}
-
-/* load f32-f127 from FPH */
-static inline void
-ia64_load_fpu (struct ia64_fpreg *fph) {
- ia64_fph_enable();
- __ia64_load_fpu(fph);
- ia64_fph_disable();
-}
-
-static inline __u64
-ia64_clear_ic (void)
-{
- __u64 psr;
- psr = ia64_getreg(_IA64_REG_PSR);
- ia64_stop();
- ia64_rsm(IA64_PSR_I | IA64_PSR_IC);
- ia64_srlz_i();
- return psr;
-}
-
-/*
- * Restore the psr.
- */
-static inline void
-ia64_set_psr (__u64 psr)
-{
- ia64_stop();
- ia64_setreg(_IA64_REG_PSR_L, psr);
- ia64_srlz_i();
-}
-
-/*
- * Insert a translation into an instruction and/or data translation
- * register.
- */
-static inline void
-ia64_itr (__u64 target_mask, __u64 tr_num,
- __u64 vmaddr, __u64 pte,
- __u64 log_page_size)
-{
- ia64_setreg(_IA64_REG_CR_ITIR, (log_page_size << 2));
- ia64_setreg(_IA64_REG_CR_IFA, vmaddr);
- ia64_stop();
- if (target_mask & 0x1)
- ia64_itri(tr_num, pte);
- if (target_mask & 0x2)
- ia64_itrd(tr_num, pte);
-}
-
-/*
- * Insert a translation into the instruction and/or data translation
- * cache.
- */
-static inline void
-ia64_itc (__u64 target_mask, __u64 vmaddr, __u64 pte,
- __u64 log_page_size)
-{
- ia64_setreg(_IA64_REG_CR_ITIR, (log_page_size << 2));
- ia64_setreg(_IA64_REG_CR_IFA, vmaddr);
- ia64_stop();
- /* as per EAS2.6, itc must be the last instruction in an instruction group */
- if (target_mask & 0x1)
- ia64_itci(pte);
- if (target_mask & 0x2)
- ia64_itcd(pte);
-}
-
-/*
- * Purge a range of addresses from instruction and/or data translation
- * register(s).
- */
-static inline void
-ia64_ptr (__u64 target_mask, __u64 vmaddr, __u64 log_size)
-{
- if (target_mask & 0x1)
- ia64_ptri(vmaddr, (log_size << 2));
- if (target_mask & 0x2)
- ia64_ptrd(vmaddr, (log_size << 2));
-}
-
-/* Set the interrupt vector address. The address must be suitably aligned (32KB). */
-static inline void
-ia64_set_iva (void *ivt_addr)
-{
- ia64_setreg(_IA64_REG_CR_IVA, (__u64) ivt_addr);
- ia64_srlz_i();
-}
-
-/* Set the page table address and control bits. */
-static inline void
-ia64_set_pta (__u64 pta)
-{
- /* Note: srlz.i implies srlz.d */
- ia64_setreg(_IA64_REG_CR_PTA, pta);
- ia64_srlz_i();
-}
-
-static inline void
-ia64_eoi (void)
-{
- ia64_setreg(_IA64_REG_CR_EOI, 0);
- ia64_srlz_d();
-}
-
-#define cpu_relax() ia64_hint(ia64_hint_pause)
-
-static inline int
-ia64_get_irr(unsigned int vector)
-{
- unsigned int reg = vector / 64;
- unsigned int bit = vector % 64;
- unsigned long irr;
-
- switch (reg) {
- case 0: irr = ia64_getreg(_IA64_REG_CR_IRR0); break;
- case 1: irr = ia64_getreg(_IA64_REG_CR_IRR1); break;
- case 2: irr = ia64_getreg(_IA64_REG_CR_IRR2); break;
- case 3: irr = ia64_getreg(_IA64_REG_CR_IRR3); break;
- }
-
- return test_bit(bit, &irr);
-}
-
-static inline void
-ia64_set_lrr0 (unsigned long val)
-{
- ia64_setreg(_IA64_REG_CR_LRR0, val);
- ia64_srlz_d();
-}
-
-static inline void
-ia64_set_lrr1 (unsigned long val)
-{
- ia64_setreg(_IA64_REG_CR_LRR1, val);
- ia64_srlz_d();
-}
-
-
-/*
- * Given the address to which a spill occurred, return the unat bit
- * number that corresponds to this address.
- */
-static inline __u64
-ia64_unat_pos (void *spill_addr)
-{
- return ((__u64) spill_addr >> 3) & 0x3f;
-}
-
-/*
- * Set the NaT bit of an integer register which was spilled at address
- * SPILL_ADDR. UNAT is the mask to be updated.
- */
-static inline void
-ia64_set_unat (__u64 *unat, void *spill_addr, unsigned long nat)
-{
- __u64 bit = ia64_unat_pos(spill_addr);
- __u64 mask = 1UL << bit;
-
- *unat = (*unat & ~mask) | (nat << bit);
-}
-
-static inline __u64
-ia64_get_ivr (void)
-{
- __u64 r;
- ia64_srlz_d();
- r = ia64_getreg(_IA64_REG_CR_IVR);
- ia64_srlz_d();
- return r;
-}
-
-static inline void
-ia64_set_dbr (__u64 regnum, __u64 value)
-{
- __ia64_set_dbr(regnum, value);
-#ifdef CONFIG_ITANIUM
- ia64_srlz_d();
-#endif
-}
-
-static inline __u64
-ia64_get_dbr (__u64 regnum)
-{
- __u64 retval;
-
- retval = __ia64_get_dbr(regnum);
-#ifdef CONFIG_ITANIUM
- ia64_srlz_d();
-#endif
- return retval;
-}
-
-static inline __u64
-ia64_rotr (__u64 w, __u64 n)
-{
- return (w >> n) | (w << (64 - n));
-}
-
-#define ia64_rotl(w,n) ia64_rotr((w), (64) - (n))
-
-/*
- * Take a mapped kernel address and return the equivalent address
- * in the region 7 identity mapped virtual area.
- */
-static inline void *
-ia64_imva (void *addr)
-{
- void *result;
- result = (void *) ia64_tpa(addr);
- return __va(result);
-}
-
-#define ARCH_HAS_PREFETCH
-#define ARCH_HAS_PREFETCHW
-#define PREFETCH_STRIDE L1_CACHE_BYTES
-
-static inline void
-prefetch (const void *x)
-{
- ia64_lfetch(ia64_lfhint_none, x);
-}
-
-static inline void
-prefetchw (const void *x)
-{
- ia64_lfetch_excl(ia64_lfhint_none, x);
-}
-
-extern unsigned long boot_option_idle_override;
-
-enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_FORCE_MWAIT,
- IDLE_NOMWAIT, IDLE_POLL};
-
-void default_idle(void);
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _ASM_IA64_PROCESSOR_H */
diff --git a/arch/ia64/include/asm/ptrace.h b/arch/ia64/include/asm/ptrace.h
deleted file mode 100644
index 402874489890..000000000000
--- a/arch/ia64/include/asm/ptrace.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 1998-2004 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 2003 Intel Co
- * Suresh Siddha <suresh.b.siddha@intel.com>
- * Fenghua Yu <fenghua.yu@intel.com>
- * Arun Sharma <arun.sharma@intel.com>
- *
- * 12/07/98 S. Eranian added pt_regs & switch_stack
- * 12/21/98 D. Mosberger updated to match latest code
- * 6/17/99 D. Mosberger added second unat member to "struct switch_stack"
- *
- */
-#ifndef _ASM_IA64_PTRACE_H
-#define _ASM_IA64_PTRACE_H
-
-#ifndef ASM_OFFSETS_C
-#include <asm/asm-offsets.h>
-#endif
-#include <uapi/asm/ptrace.h>
-
-/*
- * Base-2 logarithm of number of pages to allocate per task structure
- * (including register backing store and memory stack):
- */
-#if defined(CONFIG_IA64_PAGE_SIZE_4KB)
-# define KERNEL_STACK_SIZE_ORDER 3
-#elif defined(CONFIG_IA64_PAGE_SIZE_8KB)
-# define KERNEL_STACK_SIZE_ORDER 2
-#elif defined(CONFIG_IA64_PAGE_SIZE_16KB)
-# define KERNEL_STACK_SIZE_ORDER 1
-#else
-# define KERNEL_STACK_SIZE_ORDER 0
-#endif
-
-#define IA64_RBS_OFFSET ((IA64_TASK_SIZE + IA64_THREAD_INFO_SIZE + 31) & ~31)
-#define IA64_STK_OFFSET ((1 << KERNEL_STACK_SIZE_ORDER)*PAGE_SIZE)
-
-#define KERNEL_STACK_SIZE IA64_STK_OFFSET
-
-#ifndef __ASSEMBLY__
-
-#include <asm/current.h>
-#include <asm/page.h>
-
-/*
- * We use the ia64_psr(regs)->ri to determine which of the three
- * instructions in bundle (16 bytes) took the sample. Generate
- * the canonical representation by adding to instruction pointer.
- */
-# define instruction_pointer(regs) ((regs)->cr_iip + ia64_psr(regs)->ri)
-# define instruction_pointer_set(regs, val) \
-({ \
- ia64_psr(regs)->ri = (val & 0xf); \
- regs->cr_iip = (val & ~0xfULL); \
-})
-
-static inline unsigned long user_stack_pointer(struct pt_regs *regs)
-{
- return regs->r12;
-}
-
-static inline int is_syscall_success(struct pt_regs *regs)
-{
- return regs->r10 != -1;
-}
-
-static inline long regs_return_value(struct pt_regs *regs)
-{
- if (is_syscall_success(regs))
- return regs->r8;
- else
- return -regs->r8;
-}
-
-/* Conserve space in histogram by encoding slot bits in address
- * bits 2 and 3 rather than bits 0 and 1.
- */
-#define profile_pc(regs) \
-({ \
- unsigned long __ip = instruction_pointer(regs); \
- (__ip & ~3UL) + ((__ip & 3UL) << 2); \
-})
-
- /* given a pointer to a task_struct, return the user's pt_regs */
-# define task_pt_regs(t) (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)
-# define ia64_psr(regs) ((struct ia64_psr *) &(regs)->cr_ipsr)
-# define user_mode(regs) (((struct ia64_psr *) &(regs)->cr_ipsr)->cpl != 0)
-# define user_stack(task,regs) ((long) regs - (long) task == IA64_STK_OFFSET - sizeof(*regs))
-# define fsys_mode(task,regs) \
- ({ \
- struct task_struct *_task = (task); \
- struct pt_regs *_regs = (regs); \
- !user_mode(_regs) && user_stack(_task, _regs); \
- })
-
- /*
- * System call handlers that, upon successful completion, need to return a negative value
- * should call force_successful_syscall_return() right before returning. On architectures
- * where the syscall convention provides for a separate error flag (e.g., alpha, ia64,
- * ppc{,64}, sparc{,64}, possibly others), this macro can be used to ensure that the error
- * flag will not get set. On architectures which do not support a separate error flag,
- * the macro is a no-op and the spurious error condition needs to be filtered out by some
- * other means (e.g., in user-level, by passing an extra argument to the syscall handler,
- * or something along those lines).
- *
- * On ia64, we can clear the user's pt_regs->r8 to force a successful syscall.
- */
-# define force_successful_syscall_return() (task_pt_regs(current)->r8 = 0)
-
- struct task_struct; /* forward decl */
- struct unw_frame_info; /* forward decl */
-
- extern unsigned long ia64_get_user_rbs_end (struct task_struct *, struct pt_regs *,
- unsigned long *);
- extern long ia64_peek (struct task_struct *, struct switch_stack *, unsigned long,
- unsigned long, long *);
- extern long ia64_poke (struct task_struct *, struct switch_stack *, unsigned long,
- unsigned long, long);
- extern void ia64_flush_fph (struct task_struct *);
- extern void ia64_sync_fph (struct task_struct *);
- extern void ia64_sync_krbs(void);
- extern long ia64_sync_user_rbs (struct task_struct *, struct switch_stack *,
- unsigned long, unsigned long);
-
- /* get nat bits for scratch registers such that bit N==1 iff scratch register rN is a NaT */
- extern unsigned long ia64_get_scratch_nat_bits (struct pt_regs *pt, unsigned long scratch_unat);
- /* put nat bits for scratch registers such that scratch register rN is a NaT iff bit N==1 */
- extern unsigned long ia64_put_scratch_nat_bits (struct pt_regs *pt, unsigned long nat);
-
- extern void ia64_increment_ip (struct pt_regs *pt);
- extern void ia64_decrement_ip (struct pt_regs *pt);
-
- extern void ia64_ptrace_stop(void);
- #define arch_ptrace_stop() \
- ia64_ptrace_stop()
- #define arch_ptrace_stop_needed() \
- (!test_thread_flag(TIF_RESTORE_RSE))
-
- #define arch_has_single_step() (1)
- #define arch_has_block_step() (1)
-
-#endif /* !__ASSEMBLY__ */
-#endif /* _ASM_IA64_PTRACE_H */
diff --git a/arch/ia64/include/asm/sal.h b/arch/ia64/include/asm/sal.h
deleted file mode 100644
index 22749a201e92..000000000000
--- a/arch/ia64/include/asm/sal.h
+++ /dev/null
@@ -1,919 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_SAL_H
-#define _ASM_IA64_SAL_H
-
-/*
- * System Abstraction Layer definitions.
- *
- * This is based on version 2.5 of the manual "IA-64 System
- * Abstraction Layer".
- *
- * Copyright (C) 2001 Intel
- * Copyright (C) 2002 Jenna Hall <jenna.s.hall@intel.com>
- * Copyright (C) 2001 Fred Lewis <frederick.v.lewis@intel.com>
- * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Srinivasa Prasad Thirumalachar <sprasad@sprasad.engr.sgi.com>
- *
- * 02/01/04 J. Hall Updated Error Record Structures to conform to July 2001
- * revision of the SAL spec.
- * 01/01/03 fvlewis Updated Error Record Structures to conform with Nov. 2000
- * revision of the SAL spec.
- * 99/09/29 davidm Updated for SAL 2.6.
- * 00/03/29 cfleck Updated SAL Error Logging info for processor (SAL 2.6)
- * (plus examples of platform error info structures from smariset @ Intel)
- */
-
-#define IA64_SAL_PLATFORM_FEATURE_BUS_LOCK_BIT 0
-#define IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT_BIT 1
-#define IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT_BIT 2
-#define IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT_BIT 3
-
-#define IA64_SAL_PLATFORM_FEATURE_BUS_LOCK (1<<IA64_SAL_PLATFORM_FEATURE_BUS_LOCK_BIT)
-#define IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT (1<<IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT_BIT)
-#define IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT (1<<IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT_BIT)
-#define IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT (1<<IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT_BIT)
-
-#ifndef __ASSEMBLY__
-
-#include <linux/bcd.h>
-#include <linux/spinlock.h>
-#include <linux/efi.h>
-
-#include <asm/pal.h>
-#include <asm/fpu.h>
-
-extern unsigned long sal_systab_phys;
-extern spinlock_t sal_lock;
-
-/* SAL spec _requires_ eight args for each call. */
-#define __IA64_FW_CALL(entry,result,a0,a1,a2,a3,a4,a5,a6,a7) \
- result = (*entry)(a0,a1,a2,a3,a4,a5,a6,a7)
-
-# define IA64_FW_CALL(entry,result,args...) do { \
- unsigned long __ia64_sc_flags; \
- struct ia64_fpreg __ia64_sc_fr[6]; \
- ia64_save_scratch_fpregs(__ia64_sc_fr); \
- spin_lock_irqsave(&sal_lock, __ia64_sc_flags); \
- __IA64_FW_CALL(entry, result, args); \
- spin_unlock_irqrestore(&sal_lock, __ia64_sc_flags); \
- ia64_load_scratch_fpregs(__ia64_sc_fr); \
-} while (0)
-
-# define SAL_CALL(result,args...) \
- IA64_FW_CALL(ia64_sal, result, args);
-
-# define SAL_CALL_NOLOCK(result,args...) do { \
- unsigned long __ia64_scn_flags; \
- struct ia64_fpreg __ia64_scn_fr[6]; \
- ia64_save_scratch_fpregs(__ia64_scn_fr); \
- local_irq_save(__ia64_scn_flags); \
- __IA64_FW_CALL(ia64_sal, result, args); \
- local_irq_restore(__ia64_scn_flags); \
- ia64_load_scratch_fpregs(__ia64_scn_fr); \
-} while (0)
-
-# define SAL_CALL_REENTRANT(result,args...) do { \
- struct ia64_fpreg __ia64_scs_fr[6]; \
- ia64_save_scratch_fpregs(__ia64_scs_fr); \
- preempt_disable(); \
- __IA64_FW_CALL(ia64_sal, result, args); \
- preempt_enable(); \
- ia64_load_scratch_fpregs(__ia64_scs_fr); \
-} while (0)
-
-#define SAL_SET_VECTORS 0x01000000
-#define SAL_GET_STATE_INFO 0x01000001
-#define SAL_GET_STATE_INFO_SIZE 0x01000002
-#define SAL_CLEAR_STATE_INFO 0x01000003
-#define SAL_MC_RENDEZ 0x01000004
-#define SAL_MC_SET_PARAMS 0x01000005
-#define SAL_REGISTER_PHYSICAL_ADDR 0x01000006
-
-#define SAL_CACHE_FLUSH 0x01000008
-#define SAL_CACHE_INIT 0x01000009
-#define SAL_PCI_CONFIG_READ 0x01000010
-#define SAL_PCI_CONFIG_WRITE 0x01000011
-#define SAL_FREQ_BASE 0x01000012
-#define SAL_PHYSICAL_ID_INFO 0x01000013
-
-#define SAL_UPDATE_PAL 0x01000020
-
-struct ia64_sal_retval {
- /*
- * A zero status value indicates call completed without error.
- * A negative status value indicates reason of call failure.
- * A positive status value indicates success but an
- * informational value should be printed (e.g., "reboot for
- * change to take effect").
- */
- long status;
- unsigned long v0;
- unsigned long v1;
- unsigned long v2;
-};
-
-typedef struct ia64_sal_retval (*ia64_sal_handler) (u64, ...);
-
-enum {
- SAL_FREQ_BASE_PLATFORM = 0,
- SAL_FREQ_BASE_INTERVAL_TIMER = 1,
- SAL_FREQ_BASE_REALTIME_CLOCK = 2
-};
-
-/*
- * The SAL system table is followed by a variable number of variable
- * length descriptors. The structure of these descriptors follows
- * below.
- * The defininition follows SAL specs from July 2000
- */
-struct ia64_sal_systab {
- u8 signature[4]; /* should be "SST_" */
- u32 size; /* size of this table in bytes */
- u8 sal_rev_minor;
- u8 sal_rev_major;
- u16 entry_count; /* # of entries in variable portion */
- u8 checksum;
- u8 reserved1[7];
- u8 sal_a_rev_minor;
- u8 sal_a_rev_major;
- u8 sal_b_rev_minor;
- u8 sal_b_rev_major;
- /* oem_id & product_id: terminating NUL is missing if string is exactly 32 bytes long. */
- u8 oem_id[32];
- u8 product_id[32]; /* ASCII product id */
- u8 reserved2[8];
-};
-
-enum sal_systab_entry_type {
- SAL_DESC_ENTRY_POINT = 0,
- SAL_DESC_MEMORY = 1,
- SAL_DESC_PLATFORM_FEATURE = 2,
- SAL_DESC_TR = 3,
- SAL_DESC_PTC = 4,
- SAL_DESC_AP_WAKEUP = 5
-};
-
-/*
- * Entry type: Size:
- * 0 48
- * 1 32
- * 2 16
- * 3 32
- * 4 16
- * 5 16
- */
-#define SAL_DESC_SIZE(type) "\060\040\020\040\020\020"[(unsigned) type]
-
-typedef struct ia64_sal_desc_entry_point {
- u8 type;
- u8 reserved1[7];
- u64 pal_proc;
- u64 sal_proc;
- u64 gp;
- u8 reserved2[16];
-}ia64_sal_desc_entry_point_t;
-
-typedef struct ia64_sal_desc_memory {
- u8 type;
- u8 used_by_sal; /* needs to be mapped for SAL? */
- u8 mem_attr; /* current memory attribute setting */
- u8 access_rights; /* access rights set up by SAL */
- u8 mem_attr_mask; /* mask of supported memory attributes */
- u8 reserved1;
- u8 mem_type; /* memory type */
- u8 mem_usage; /* memory usage */
- u64 addr; /* physical address of memory */
- u32 length; /* length (multiple of 4KB pages) */
- u32 reserved2;
- u8 oem_reserved[8];
-} ia64_sal_desc_memory_t;
-
-typedef struct ia64_sal_desc_platform_feature {
- u8 type;
- u8 feature_mask;
- u8 reserved1[14];
-} ia64_sal_desc_platform_feature_t;
-
-typedef struct ia64_sal_desc_tr {
- u8 type;
- u8 tr_type; /* 0 == instruction, 1 == data */
- u8 regnum; /* translation register number */
- u8 reserved1[5];
- u64 addr; /* virtual address of area covered */
- u64 page_size; /* encoded page size */
- u8 reserved2[8];
-} ia64_sal_desc_tr_t;
-
-typedef struct ia64_sal_desc_ptc {
- u8 type;
- u8 reserved1[3];
- u32 num_domains; /* # of coherence domains */
- u64 domain_info; /* physical address of domain info table */
-} ia64_sal_desc_ptc_t;
-
-typedef struct ia64_sal_ptc_domain_info {
- u64 proc_count; /* number of processors in domain */
- u64 proc_list; /* physical address of LID array */
-} ia64_sal_ptc_domain_info_t;
-
-typedef struct ia64_sal_ptc_domain_proc_entry {
- u64 id : 8; /* id of processor */
- u64 eid : 8; /* eid of processor */
-} ia64_sal_ptc_domain_proc_entry_t;
-
-
-#define IA64_SAL_AP_EXTERNAL_INT 0
-
-typedef struct ia64_sal_desc_ap_wakeup {
- u8 type;
- u8 mechanism; /* 0 == external interrupt */
- u8 reserved1[6];
- u64 vector; /* interrupt vector in range 0x10-0xff */
-} ia64_sal_desc_ap_wakeup_t ;
-
-extern ia64_sal_handler ia64_sal;
-extern struct ia64_sal_desc_ptc *ia64_ptc_domain_info;
-
-extern unsigned short sal_revision; /* supported SAL spec revision */
-extern unsigned short sal_version; /* SAL version; OEM dependent */
-#define SAL_VERSION_CODE(major, minor) ((bin2bcd(major) << 8) | bin2bcd(minor))
-
-extern const char *ia64_sal_strerror (long status);
-extern void ia64_sal_init (struct ia64_sal_systab *sal_systab);
-
-/* SAL information type encodings */
-enum {
- SAL_INFO_TYPE_MCA = 0, /* Machine check abort information */
- SAL_INFO_TYPE_INIT = 1, /* Init information */
- SAL_INFO_TYPE_CMC = 2, /* Corrected machine check information */
- SAL_INFO_TYPE_CPE = 3 /* Corrected platform error information */
-};
-
-/* Encodings for machine check parameter types */
-enum {
- SAL_MC_PARAM_RENDEZ_INT = 1, /* Rendezvous interrupt */
- SAL_MC_PARAM_RENDEZ_WAKEUP = 2, /* Wakeup */
- SAL_MC_PARAM_CPE_INT = 3 /* Corrected Platform Error Int */
-};
-
-/* Encodings for rendezvous mechanisms */
-enum {
- SAL_MC_PARAM_MECHANISM_INT = 1, /* Use interrupt */
- SAL_MC_PARAM_MECHANISM_MEM = 2 /* Use memory synchronization variable*/
-};
-
-/* Encodings for vectors which can be registered by the OS with SAL */
-enum {
- SAL_VECTOR_OS_MCA = 0,
- SAL_VECTOR_OS_INIT = 1,
- SAL_VECTOR_OS_BOOT_RENDEZ = 2
-};
-
-/* Encodings for mca_opt parameter sent to SAL_MC_SET_PARAMS */
-#define SAL_MC_PARAM_RZ_ALWAYS 0x1
-#define SAL_MC_PARAM_BINIT_ESCALATE 0x10
-
-/*
- * Definition of the SAL Error Log from the SAL spec
- */
-
-/* SAL Error Record Section GUID Definitions */
-#define SAL_PROC_DEV_ERR_SECT_GUID \
- EFI_GUID(0xe429faf1, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
-#define SAL_PLAT_MEM_DEV_ERR_SECT_GUID \
- EFI_GUID(0xe429faf2, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
-#define SAL_PLAT_SEL_DEV_ERR_SECT_GUID \
- EFI_GUID(0xe429faf3, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
-#define SAL_PLAT_PCI_BUS_ERR_SECT_GUID \
- EFI_GUID(0xe429faf4, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
-#define SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID \
- EFI_GUID(0xe429faf5, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
-#define SAL_PLAT_PCI_COMP_ERR_SECT_GUID \
- EFI_GUID(0xe429faf6, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
-#define SAL_PLAT_SPECIFIC_ERR_SECT_GUID \
- EFI_GUID(0xe429faf7, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
-#define SAL_PLAT_HOST_CTLR_ERR_SECT_GUID \
- EFI_GUID(0xe429faf8, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
-#define SAL_PLAT_BUS_ERR_SECT_GUID \
- EFI_GUID(0xe429faf9, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
-#define PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID \
- EFI_GUID(0x6cb0a200, 0x893a, 0x11da, 0x96, 0xd2, 0x0, 0x10, 0x83, 0xff, \
- 0xca, 0x4d)
-
-#define MAX_CACHE_ERRORS 6
-#define MAX_TLB_ERRORS 6
-#define MAX_BUS_ERRORS 1
-
-/* Definition of version according to SAL spec for logging purposes */
-typedef struct sal_log_revision {
- u8 minor; /* BCD (0..99) */
- u8 major; /* BCD (0..99) */
-} sal_log_revision_t;
-
-/* Definition of timestamp according to SAL spec for logging purposes */
-typedef struct sal_log_timestamp {
- u8 slh_second; /* Second (0..59) */
- u8 slh_minute; /* Minute (0..59) */
- u8 slh_hour; /* Hour (0..23) */
- u8 slh_reserved;
- u8 slh_day; /* Day (1..31) */
- u8 slh_month; /* Month (1..12) */
- u8 slh_year; /* Year (00..99) */
- u8 slh_century; /* Century (19, 20, 21, ...) */
-} sal_log_timestamp_t;
-
-/* Definition of log record header structures */
-typedef struct sal_log_record_header {
- u64 id; /* Unique monotonically increasing ID */
- sal_log_revision_t revision; /* Major and Minor revision of header */
- u8 severity; /* Error Severity */
- u8 validation_bits; /* 0: platform_guid, 1: !timestamp */
- u32 len; /* Length of this error log in bytes */
- sal_log_timestamp_t timestamp; /* Timestamp */
- efi_guid_t platform_guid; /* Unique OEM Platform ID */
-} sal_log_record_header_t;
-
-#define sal_log_severity_recoverable 0
-#define sal_log_severity_fatal 1
-#define sal_log_severity_corrected 2
-
-/*
- * Error Recovery Info (ERI) bit decode. From SAL Spec section B.2.2 Table B-3
- * Error Section Error_Recovery_Info Field Definition.
- */
-#define ERI_NOT_VALID 0x0 /* Error Recovery Field is not valid */
-#define ERI_NOT_ACCESSIBLE 0x30 /* Resource not accessible */
-#define ERI_CONTAINMENT_WARN 0x22 /* Corrupt data propagated */
-#define ERI_UNCORRECTED_ERROR 0x20 /* Uncorrected error */
-#define ERI_COMPONENT_RESET 0x24 /* Component must be reset */
-#define ERI_CORR_ERROR_LOG 0x21 /* Corrected error, needs logging */
-#define ERI_CORR_ERROR_THRESH 0x29 /* Corrected error threshold exceeded */
-
-/* Definition of log section header structures */
-typedef struct sal_log_sec_header {
- efi_guid_t guid; /* Unique Section ID */
- sal_log_revision_t revision; /* Major and Minor revision of Section */
- u8 error_recovery_info; /* Platform error recovery status */
- u8 reserved;
- u32 len; /* Section length */
-} sal_log_section_hdr_t;
-
-typedef struct sal_log_mod_error_info {
- struct {
- u64 check_info : 1,
- requestor_identifier : 1,
- responder_identifier : 1,
- target_identifier : 1,
- precise_ip : 1,
- reserved : 59;
- } valid;
- u64 check_info;
- u64 requestor_identifier;
- u64 responder_identifier;
- u64 target_identifier;
- u64 precise_ip;
-} sal_log_mod_error_info_t;
-
-typedef struct sal_processor_static_info {
- struct {
- u64 minstate : 1,
- br : 1,
- cr : 1,
- ar : 1,
- rr : 1,
- fr : 1,
- reserved : 58;
- } valid;
- struct pal_min_state_area min_state_area;
- u64 br[8];
- u64 cr[128];
- u64 ar[128];
- u64 rr[8];
- struct ia64_fpreg __attribute__ ((packed)) fr[128];
-} sal_processor_static_info_t;
-
-struct sal_cpuid_info {
- u64 regs[5];
- u64 reserved;
-};
-
-typedef struct sal_log_processor_info {
- sal_log_section_hdr_t header;
- struct {
- u64 proc_error_map : 1,
- proc_state_param : 1,
- proc_cr_lid : 1,
- psi_static_struct : 1,
- num_cache_check : 4,
- num_tlb_check : 4,
- num_bus_check : 4,
- num_reg_file_check : 4,
- num_ms_check : 4,
- cpuid_info : 1,
- reserved1 : 39;
- } valid;
- u64 proc_error_map;
- u64 proc_state_parameter;
- u64 proc_cr_lid;
- /*
- * The rest of this structure consists of variable-length arrays, which can't be
- * expressed in C.
- */
- sal_log_mod_error_info_t info[];
- /*
- * This is what the rest looked like if C supported variable-length arrays:
- *
- * sal_log_mod_error_info_t cache_check_info[.valid.num_cache_check];
- * sal_log_mod_error_info_t tlb_check_info[.valid.num_tlb_check];
- * sal_log_mod_error_info_t bus_check_info[.valid.num_bus_check];
- * sal_log_mod_error_info_t reg_file_check_info[.valid.num_reg_file_check];
- * sal_log_mod_error_info_t ms_check_info[.valid.num_ms_check];
- * struct sal_cpuid_info cpuid_info;
- * sal_processor_static_info_t processor_static_info;
- */
-} sal_log_processor_info_t;
-
-/* Given a sal_log_processor_info_t pointer, return a pointer to the processor_static_info: */
-#define SAL_LPI_PSI_INFO(l) \
-({ sal_log_processor_info_t *_l = (l); \
- ((sal_processor_static_info_t *) \
- ((char *) _l->info + ((_l->valid.num_cache_check + _l->valid.num_tlb_check \
- + _l->valid.num_bus_check + _l->valid.num_reg_file_check \
- + _l->valid.num_ms_check) * sizeof(sal_log_mod_error_info_t) \
- + sizeof(struct sal_cpuid_info)))); \
-})
-
-/* platform error log structures */
-
-typedef struct sal_log_mem_dev_err_info {
- sal_log_section_hdr_t header;
- struct {
- u64 error_status : 1,
- physical_addr : 1,
- addr_mask : 1,
- node : 1,
- card : 1,
- module : 1,
- bank : 1,
- device : 1,
- row : 1,
- column : 1,
- bit_position : 1,
- requestor_id : 1,
- responder_id : 1,
- target_id : 1,
- bus_spec_data : 1,
- oem_id : 1,
- oem_data : 1,
- reserved : 47;
- } valid;
- u64 error_status;
- u64 physical_addr;
- u64 addr_mask;
- u16 node;
- u16 card;
- u16 module;
- u16 bank;
- u16 device;
- u16 row;
- u16 column;
- u16 bit_position;
- u64 requestor_id;
- u64 responder_id;
- u64 target_id;
- u64 bus_spec_data;
- u8 oem_id[16];
- u8 oem_data[1]; /* Variable length data */
-} sal_log_mem_dev_err_info_t;
-
-typedef struct sal_log_sel_dev_err_info {
- sal_log_section_hdr_t header;
- struct {
- u64 record_id : 1,
- record_type : 1,
- generator_id : 1,
- evm_rev : 1,
- sensor_type : 1,
- sensor_num : 1,
- event_dir : 1,
- event_data1 : 1,
- event_data2 : 1,
- event_data3 : 1,
- reserved : 54;
- } valid;
- u16 record_id;
- u8 record_type;
- u8 timestamp[4];
- u16 generator_id;
- u8 evm_rev;
- u8 sensor_type;
- u8 sensor_num;
- u8 event_dir;
- u8 event_data1;
- u8 event_data2;
- u8 event_data3;
-} sal_log_sel_dev_err_info_t;
-
-typedef struct sal_log_pci_bus_err_info {
- sal_log_section_hdr_t header;
- struct {
- u64 err_status : 1,
- err_type : 1,
- bus_id : 1,
- bus_address : 1,
- bus_data : 1,
- bus_cmd : 1,
- requestor_id : 1,
- responder_id : 1,
- target_id : 1,
- oem_data : 1,
- reserved : 54;
- } valid;
- u64 err_status;
- u16 err_type;
- u16 bus_id;
- u32 reserved;
- u64 bus_address;
- u64 bus_data;
- u64 bus_cmd;
- u64 requestor_id;
- u64 responder_id;
- u64 target_id;
- u8 oem_data[1]; /* Variable length data */
-} sal_log_pci_bus_err_info_t;
-
-typedef struct sal_log_smbios_dev_err_info {
- sal_log_section_hdr_t header;
- struct {
- u64 event_type : 1,
- length : 1,
- time_stamp : 1,
- data : 1,
- reserved1 : 60;
- } valid;
- u8 event_type;
- u8 length;
- u8 time_stamp[6];
- u8 data[1]; /* data of variable length, length == slsmb_length */
-} sal_log_smbios_dev_err_info_t;
-
-typedef struct sal_log_pci_comp_err_info {
- sal_log_section_hdr_t header;
- struct {
- u64 err_status : 1,
- comp_info : 1,
- num_mem_regs : 1,
- num_io_regs : 1,
- reg_data_pairs : 1,
- oem_data : 1,
- reserved : 58;
- } valid;
- u64 err_status;
- struct {
- u16 vendor_id;
- u16 device_id;
- u8 class_code[3];
- u8 func_num;
- u8 dev_num;
- u8 bus_num;
- u8 seg_num;
- u8 reserved[5];
- } comp_info;
- u32 num_mem_regs;
- u32 num_io_regs;
- u64 reg_data_pairs[1];
- /*
- * array of address/data register pairs is num_mem_regs + num_io_regs elements
- * long. Each array element consists of a u64 address followed by a u64 data
- * value. The oem_data array immediately follows the reg_data_pairs array
- */
- u8 oem_data[1]; /* Variable length data */
-} sal_log_pci_comp_err_info_t;
-
-typedef struct sal_log_plat_specific_err_info {
- sal_log_section_hdr_t header;
- struct {
- u64 err_status : 1,
- guid : 1,
- oem_data : 1,
- reserved : 61;
- } valid;
- u64 err_status;
- efi_guid_t guid;
- u8 oem_data[1]; /* platform specific variable length data */
-} sal_log_plat_specific_err_info_t;
-
-typedef struct sal_log_host_ctlr_err_info {
- sal_log_section_hdr_t header;
- struct {
- u64 err_status : 1,
- requestor_id : 1,
- responder_id : 1,
- target_id : 1,
- bus_spec_data : 1,
- oem_data : 1,
- reserved : 58;
- } valid;
- u64 err_status;
- u64 requestor_id;
- u64 responder_id;
- u64 target_id;
- u64 bus_spec_data;
- u8 oem_data[1]; /* Variable length OEM data */
-} sal_log_host_ctlr_err_info_t;
-
-typedef struct sal_log_plat_bus_err_info {
- sal_log_section_hdr_t header;
- struct {
- u64 err_status : 1,
- requestor_id : 1,
- responder_id : 1,
- target_id : 1,
- bus_spec_data : 1,
- oem_data : 1,
- reserved : 58;
- } valid;
- u64 err_status;
- u64 requestor_id;
- u64 responder_id;
- u64 target_id;
- u64 bus_spec_data;
- u8 oem_data[1]; /* Variable length OEM data */
-} sal_log_plat_bus_err_info_t;
-
-/* Overall platform error section structure */
-typedef union sal_log_platform_err_info {
- sal_log_mem_dev_err_info_t mem_dev_err;
- sal_log_sel_dev_err_info_t sel_dev_err;
- sal_log_pci_bus_err_info_t pci_bus_err;
- sal_log_smbios_dev_err_info_t smbios_dev_err;
- sal_log_pci_comp_err_info_t pci_comp_err;
- sal_log_plat_specific_err_info_t plat_specific_err;
- sal_log_host_ctlr_err_info_t host_ctlr_err;
- sal_log_plat_bus_err_info_t plat_bus_err;
-} sal_log_platform_err_info_t;
-
-/* SAL log over-all, multi-section error record structure (processor+platform) */
-typedef struct err_rec {
- sal_log_record_header_t sal_elog_header;
- sal_log_processor_info_t proc_err;
- sal_log_platform_err_info_t plat_err;
- u8 oem_data_pad[1024];
-} ia64_err_rec_t;
-
-/*
- * Now define a couple of inline functions for improved type checking
- * and convenience.
- */
-
-extern s64 ia64_sal_cache_flush (u64 cache_type);
-extern void __init check_sal_cache_flush (void);
-
-/* Initialize all the processor and platform level instruction and data caches */
-static inline s64
-ia64_sal_cache_init (void)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL(isrv, SAL_CACHE_INIT, 0, 0, 0, 0, 0, 0, 0);
- return isrv.status;
-}
-
-/*
- * Clear the processor and platform information logged by SAL with respect to the machine
- * state at the time of MCA's, INITs, CMCs, or CPEs.
- */
-static inline s64
-ia64_sal_clear_state_info (u64 sal_info_type)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL_REENTRANT(isrv, SAL_CLEAR_STATE_INFO, sal_info_type, 0,
- 0, 0, 0, 0, 0);
- return isrv.status;
-}
-
-
-/* Get the processor and platform information logged by SAL with respect to the machine
- * state at the time of the MCAs, INITs, CMCs, or CPEs.
- */
-static inline u64
-ia64_sal_get_state_info (u64 sal_info_type, u64 *sal_info)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL_REENTRANT(isrv, SAL_GET_STATE_INFO, sal_info_type, 0,
- sal_info, 0, 0, 0, 0);
- if (isrv.status)
- return 0;
-
- return isrv.v0;
-}
-
-/*
- * Get the maximum size of the information logged by SAL with respect to the machine state
- * at the time of MCAs, INITs, CMCs, or CPEs.
- */
-static inline u64
-ia64_sal_get_state_info_size (u64 sal_info_type)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL_REENTRANT(isrv, SAL_GET_STATE_INFO_SIZE, sal_info_type, 0,
- 0, 0, 0, 0, 0);
- if (isrv.status)
- return 0;
- return isrv.v0;
-}
-
-/*
- * Causes the processor to go into a spin loop within SAL where SAL awaits a wakeup from
- * the monarch processor. Must not lock, because it will not return on any cpu until the
- * monarch processor sends a wake up.
- */
-static inline s64
-ia64_sal_mc_rendez (void)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL_NOLOCK(isrv, SAL_MC_RENDEZ, 0, 0, 0, 0, 0, 0, 0);
- return isrv.status;
-}
-
-/*
- * Allow the OS to specify the interrupt number to be used by SAL to interrupt OS during
- * the machine check rendezvous sequence as well as the mechanism to wake up the
- * non-monarch processor at the end of machine check processing.
- * Returns the complete ia64_sal_retval because some calls return more than just a status
- * value.
- */
-static inline struct ia64_sal_retval
-ia64_sal_mc_set_params (u64 param_type, u64 i_or_m, u64 i_or_m_val, u64 timeout, u64 rz_always)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val,
- timeout, rz_always, 0, 0);
- return isrv;
-}
-
-/* Read from PCI configuration space */
-static inline s64
-ia64_sal_pci_config_read (u64 pci_config_addr, int type, u64 size, u64 *value)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL(isrv, SAL_PCI_CONFIG_READ, pci_config_addr, size, type, 0, 0, 0, 0);
- if (value)
- *value = isrv.v0;
- return isrv.status;
-}
-
-/* Write to PCI configuration space */
-static inline s64
-ia64_sal_pci_config_write (u64 pci_config_addr, int type, u64 size, u64 value)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL(isrv, SAL_PCI_CONFIG_WRITE, pci_config_addr, size, value,
- type, 0, 0, 0);
- return isrv.status;
-}
-
-/*
- * Register physical addresses of locations needed by SAL when SAL procedures are invoked
- * in virtual mode.
- */
-static inline s64
-ia64_sal_register_physical_addr (u64 phys_entry, u64 phys_addr)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL(isrv, SAL_REGISTER_PHYSICAL_ADDR, phys_entry, phys_addr,
- 0, 0, 0, 0, 0);
- return isrv.status;
-}
-
-/*
- * Register software dependent code locations within SAL. These locations are handlers or
- * entry points where SAL will pass control for the specified event. These event handlers
- * are for the bott rendezvous, MCAs and INIT scenarios.
- */
-static inline s64
-ia64_sal_set_vectors (u64 vector_type,
- u64 handler_addr1, u64 gp1, u64 handler_len1,
- u64 handler_addr2, u64 gp2, u64 handler_len2)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL(isrv, SAL_SET_VECTORS, vector_type,
- handler_addr1, gp1, handler_len1,
- handler_addr2, gp2, handler_len2);
-
- return isrv.status;
-}
-
-/* Update the contents of PAL block in the non-volatile storage device */
-static inline s64
-ia64_sal_update_pal (u64 param_buf, u64 scratch_buf, u64 scratch_buf_size,
- u64 *error_code, u64 *scratch_buf_size_needed)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL(isrv, SAL_UPDATE_PAL, param_buf, scratch_buf, scratch_buf_size,
- 0, 0, 0, 0);
- if (error_code)
- *error_code = isrv.v0;
- if (scratch_buf_size_needed)
- *scratch_buf_size_needed = isrv.v1;
- return isrv.status;
-}
-
-/* Get physical processor die mapping in the platform. */
-static inline s64
-ia64_sal_physical_id_info(u16 *splid)
-{
- struct ia64_sal_retval isrv;
-
- if (sal_revision < SAL_VERSION_CODE(3,2))
- return -1;
-
- SAL_CALL(isrv, SAL_PHYSICAL_ID_INFO, 0, 0, 0, 0, 0, 0, 0);
- if (splid)
- *splid = isrv.v0;
- return isrv.status;
-}
-
-extern unsigned long sal_platform_features;
-
-extern int (*salinfo_platform_oemdata)(const u8 *, u8 **, u64 *);
-
-struct sal_ret_values {
- long r8; long r9; long r10; long r11;
-};
-
-#define IA64_SAL_OEMFUNC_MIN 0x02000000
-#define IA64_SAL_OEMFUNC_MAX 0x03ffffff
-
-extern int ia64_sal_oemcall(struct ia64_sal_retval *, u64, u64, u64, u64, u64,
- u64, u64, u64);
-extern int ia64_sal_oemcall_nolock(struct ia64_sal_retval *, u64, u64, u64,
- u64, u64, u64, u64, u64);
-extern int ia64_sal_oemcall_reentrant(struct ia64_sal_retval *, u64, u64, u64,
- u64, u64, u64, u64, u64);
-extern long
-ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second,
- unsigned long *drift_info);
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * System Abstraction Layer Specification
- * Section 3.2.5.1: OS_BOOT_RENDEZ to SAL return State.
- * Note: region regs are stored first in head.S _start. Hence they must
- * stay up front.
- */
-struct sal_to_os_boot {
- u64 rr[8]; /* Region Registers */
- u64 br[6]; /* br0:
- * return addr into SAL boot rendez routine */
- u64 gr1; /* SAL:GP */
- u64 gr12; /* SAL:SP */
- u64 gr13; /* SAL: Task Pointer */
- u64 fpsr;
- u64 pfs;
- u64 rnat;
- u64 unat;
- u64 bspstore;
- u64 dcr; /* Default Control Register */
- u64 iva;
- u64 pta;
- u64 itv;
- u64 pmv;
- u64 cmcv;
- u64 lrr[2];
- u64 gr[4];
- u64 pr; /* Predicate registers */
- u64 lc; /* Loop Count */
- struct ia64_fpreg fp[20];
-};
-
-/*
- * Global array allocated for NR_CPUS at boot time
- */
-extern struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS];
-
-extern void ia64_jump_to_sal(struct sal_to_os_boot *);
-#endif
-
-extern void ia64_sal_handler_init(void *entry_point, void *gpval);
-
-#define PALO_MAX_TLB_PURGES 0xFFFF
-#define PALO_SIG "PALO"
-
-struct palo_table {
- u8 signature[4]; /* Should be "PALO" */
- u32 length;
- u8 minor_revision;
- u8 major_revision;
- u8 checksum;
- u8 reserved1[5];
- u16 max_tlb_purges;
- u8 reserved2[6];
-};
-
-#define NPTCG_FROM_PAL 0
-#define NPTCG_FROM_PALO 1
-#define NPTCG_FROM_KERNEL_PARAMETER 2
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _ASM_IA64_SAL_H */
diff --git a/arch/ia64/include/asm/sections.h b/arch/ia64/include/asm/sections.h
deleted file mode 100644
index 8e0875cf6071..000000000000
--- a/arch/ia64/include/asm/sections.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_SECTIONS_H
-#define _ASM_IA64_SECTIONS_H
-
-/*
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/elf.h>
-#include <linux/uaccess.h>
-
-typedef struct fdesc func_desc_t;
-
-#include <asm-generic/sections.h>
-
-extern char __phys_per_cpu_start[];
-#ifdef CONFIG_SMP
-extern char __cpu0_per_cpu[];
-#endif
-extern char __start___vtop_patchlist[], __end___vtop_patchlist[];
-extern char __start___rse_patchlist[], __end___rse_patchlist[];
-extern char __start___mckinley_e9_bundles[], __end___mckinley_e9_bundles[];
-extern char __start___phys_stack_reg_patchlist[], __end___phys_stack_reg_patchlist[];
-extern char __start_gate_section[];
-extern char __start_gate_mckinley_e9_patchlist[], __end_gate_mckinley_e9_patchlist[];
-extern char __start_gate_vtop_patchlist[], __end_gate_vtop_patchlist[];
-extern char __start_gate_fsyscall_patchlist[], __end_gate_fsyscall_patchlist[];
-extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_bubble_down_patchlist[];
-extern char __start_unwind[], __end_unwind[];
-extern char __start_ivt_text[], __end_ivt_text[];
-
-#endif /* _ASM_IA64_SECTIONS_H */
diff --git a/arch/ia64/include/asm/serial.h b/arch/ia64/include/asm/serial.h
deleted file mode 100644
index 068be11583df..000000000000
--- a/arch/ia64/include/asm/serial.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Derived from the i386 version.
- */
-
-/*
- * This assumes you have a 1.8432 MHz clock for your UART.
- *
- * It'd be nice if someone built a serial card with a 24.576 MHz
- * clock, since the 16550A is capable of handling a top speed of 1.5
- * megabits/second; but this requires the faster clock.
- */
-#define BASE_BAUD ( 1843200 / 16 )
-
-/*
- * All legacy serial ports should be enumerated via ACPI namespace, so
- * we need not list them here.
- */
diff --git a/arch/ia64/include/asm/shmparam.h b/arch/ia64/include/asm/shmparam.h
deleted file mode 100644
index 43bd8324ab71..000000000000
--- a/arch/ia64/include/asm/shmparam.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_SHMPARAM_H
-#define _ASM_IA64_SHMPARAM_H
-
-/*
- * SHMLBA controls minimum alignment at which shared memory segments
- * get attached. The IA-64 architecture says that there may be a
- * performance degradation when there are virtual aliases within 1MB.
- * To reduce the chance of this, we set SHMLBA to 1MB. --davidm 00/12/20
- */
-#define SHMLBA (1024*1024)
-
-#endif /* _ASM_IA64_SHMPARAM_H */
diff --git a/arch/ia64/include/asm/signal.h b/arch/ia64/include/asm/signal.h
deleted file mode 100644
index 80f067f9b3ce..000000000000
--- a/arch/ia64/include/asm/signal.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Modified 1998-2001, 2003
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- *
- * Unfortunately, this file is being included by bits/signal.h in
- * glibc-2.x. Hence the #ifdef __KERNEL__ ugliness.
- */
-#ifndef _ASM_IA64_SIGNAL_H
-#define _ASM_IA64_SIGNAL_H
-
-#include <uapi/asm/signal.h>
-
-
-#define _NSIG 64
-#define _NSIG_BPW 64
-#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
-
-# ifndef __ASSEMBLY__
-
-/* Most things should be clean enough to redefine this at will, if care
- is taken to make libc match. */
-
-typedef unsigned long old_sigset_t;
-
-typedef struct {
- unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-# include <asm/sigcontext.h>
-
-# endif /* !__ASSEMBLY__ */
-#endif /* _ASM_IA64_SIGNAL_H */
diff --git a/arch/ia64/include/asm/smp.h b/arch/ia64/include/asm/smp.h
deleted file mode 100644
index aa92234c0142..000000000000
--- a/arch/ia64/include/asm/smp.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * SMP Support
- *
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * (c) Copyright 2001-2003, 2005 Hewlett-Packard Development Company, L.P.
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- */
-#ifndef _ASM_IA64_SMP_H
-#define _ASM_IA64_SMP_H
-
-#include <linux/init.h>
-#include <linux/threads.h>
-#include <linux/kernel.h>
-#include <linux/cpumask.h>
-#include <linux/bitops.h>
-#include <linux/irqreturn.h>
-
-#include <asm/param.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-
-static inline unsigned int
-ia64_get_lid (void)
-{
- union {
- struct {
- unsigned long reserved : 16;
- unsigned long eid : 8;
- unsigned long id : 8;
- unsigned long ignored : 32;
- } f;
- unsigned long bits;
- } lid;
-
- lid.bits = ia64_getreg(_IA64_REG_CR_LID);
- return lid.f.id << 8 | lid.f.eid;
-}
-
-#define hard_smp_processor_id() ia64_get_lid()
-
-#ifdef CONFIG_SMP
-
-#define raw_smp_processor_id() (current_thread_info()->cpu)
-
-extern struct smp_boot_data {
- int cpu_count;
- int cpu_phys_id[NR_CPUS];
-} smp_boot_data __initdata;
-
-extern char no_int_routing;
-
-extern cpumask_t cpu_core_map[NR_CPUS];
-DECLARE_PER_CPU_SHARED_ALIGNED(cpumask_t, cpu_sibling_map);
-extern int smp_num_siblings;
-extern void __iomem *ipi_base_addr;
-
-extern volatile int ia64_cpu_to_sapicid[];
-#define cpu_physical_id(i) ia64_cpu_to_sapicid[i]
-
-extern unsigned long ap_wakeup_vector;
-
-/*
- * Function to map hard smp processor id to logical id. Slow, so don't use this in
- * performance-critical code.
- */
-static inline int
-cpu_logical_id (int cpuid)
-{
- int i;
-
- for (i = 0; i < NR_CPUS; ++i)
- if (cpu_physical_id(i) == cpuid)
- break;
- return i;
-}
-
-/* Upping and downing of CPUs */
-extern int __cpu_disable (void);
-extern void __cpu_die (unsigned int cpu);
-extern void cpu_die (void) __attribute__ ((noreturn));
-extern void __init smp_build_cpu_map(void);
-
-extern void __init init_smp_config (void);
-extern void smp_do_timer (struct pt_regs *regs);
-
-extern irqreturn_t handle_IPI(int irq, void *dev_id);
-extern void smp_send_reschedule (int cpu);
-extern void identify_siblings (struct cpuinfo_ia64 *);
-extern int is_multithreading_enabled(void);
-
-extern void arch_send_call_function_single_ipi(int cpu);
-extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
-
-#else /* CONFIG_SMP */
-
-#define cpu_logical_id(i) 0
-#define cpu_physical_id(i) ia64_get_lid()
-
-#endif /* CONFIG_SMP */
-#endif /* _ASM_IA64_SMP_H */
diff --git a/arch/ia64/include/asm/sn/intr.h b/arch/ia64/include/asm/sn/intr.h
deleted file mode 100644
index 3885a77b21df..000000000000
--- a/arch/ia64/include/asm/sn/intr.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1992 - 1997, 2000-2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_INTR_H
-#define _ASM_IA64_SN_INTR_H
-
-#define SGI_XPC_ACTIVATE 0x30
-#define SGI_XPC_NOTIFY 0xe7
-
-#endif /* _ASM_IA64_SN_INTR_H */
diff --git a/arch/ia64/include/asm/sn/sn_sal.h b/arch/ia64/include/asm/sn/sn_sal.h
deleted file mode 100644
index d437aa43343b..000000000000
--- a/arch/ia64/include/asm/sn/sn_sal.h
+++ /dev/null
@@ -1,124 +0,0 @@
-#ifndef _ASM_IA64_SN_SN_SAL_H
-#define _ASM_IA64_SN_SN_SAL_H
-
-/*
- * System Abstraction Layer definitions for IA64
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 2000-2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/types.h>
-#include <asm/sal.h>
-
-// SGI Specific Calls
-#define SN_SAL_GET_PARTITION_ADDR 0x02000009
-#define SN_SAL_MEMPROTECT 0x0200003e
-
-#define SN_SAL_WATCHLIST_ALLOC 0x02000070
-#define SN_SAL_WATCHLIST_FREE 0x02000071
-
-/*
- * SAL Error Codes
- */
-#define SALRET_MORE_PASSES 1
-#define SALRET_OK 0
-#define SALRET_NOT_IMPLEMENTED (-1)
-#define SALRET_INVALID_ARG (-2)
-#define SALRET_ERROR (-3)
-
-/*
- * Returns the physical address of the partition's reserved page through
- * an iterative number of calls.
- *
- * On first call, 'cookie' and 'len' should be set to 0, and 'addr'
- * set to the nasid of the partition whose reserved page's address is
- * being sought.
- * On subsequent calls, pass the values, that were passed back on the
- * previous call.
- *
- * While the return status equals SALRET_MORE_PASSES, keep calling
- * this function after first copying 'len' bytes starting at 'addr'
- * into 'buf'. Once the return status equals SALRET_OK, 'addr' will
- * be the physical address of the partition's reserved page. If the
- * return status equals neither of these, an error as occurred.
- */
-static inline s64
-sn_partition_reserved_page_pa(u64 buf, u64 *cookie, u64 *addr, u64 *len)
-{
- struct ia64_sal_retval rv;
- ia64_sal_oemcall_reentrant(&rv, SN_SAL_GET_PARTITION_ADDR, *cookie,
- *addr, buf, *len, 0, 0, 0);
- *cookie = rv.v0;
- *addr = rv.v1;
- *len = rv.v2;
- return rv.status;
-}
-
-/*
- * Change memory access protections for a physical address range.
- * nasid_array is not used on Altix, but may be in future architectures.
- * Available memory protection access classes are defined after the function.
- */
-static inline int
-sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array)
-{
- struct ia64_sal_retval ret_stuff;
-
- ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_MEMPROTECT, paddr, len,
- (u64)nasid_array, perms, 0, 0, 0);
- return ret_stuff.status;
-}
-#define SN_MEMPROT_ACCESS_CLASS_0 0x14a080
-#define SN_MEMPROT_ACCESS_CLASS_1 0x2520c2
-#define SN_MEMPROT_ACCESS_CLASS_2 0x14a1ca
-#define SN_MEMPROT_ACCESS_CLASS_3 0x14a290
-#define SN_MEMPROT_ACCESS_CLASS_6 0x084080
-#define SN_MEMPROT_ACCESS_CLASS_7 0x021080
-
-union sn_watchlist_u {
- u64 val;
- struct {
- u64 blade : 16,
- size : 32,
- filler : 16;
- };
-};
-
-static inline int
-sn_mq_watchlist_alloc(int blade, void *mq, unsigned int mq_size,
- unsigned long *intr_mmr_offset)
-{
- struct ia64_sal_retval rv;
- unsigned long addr;
- union sn_watchlist_u size_blade;
- int watchlist;
-
- addr = (unsigned long)mq;
- size_blade.size = mq_size;
- size_blade.blade = blade;
-
- /*
- * bios returns watchlist number or negative error number.
- */
- ia64_sal_oemcall_nolock(&rv, SN_SAL_WATCHLIST_ALLOC, addr,
- size_blade.val, (u64)intr_mmr_offset,
- (u64)&watchlist, 0, 0, 0);
- if (rv.status < 0)
- return rv.status;
-
- return watchlist;
-}
-
-static inline int
-sn_mq_watchlist_free(int blade, int watchlist_num)
-{
- struct ia64_sal_retval rv;
- ia64_sal_oemcall_nolock(&rv, SN_SAL_WATCHLIST_FREE, blade,
- watchlist_num, 0, 0, 0, 0, 0);
- return rv.status;
-}
-#endif /* _ASM_IA64_SN_SN_SAL_H */
diff --git a/arch/ia64/include/asm/sparsemem.h b/arch/ia64/include/asm/sparsemem.h
deleted file mode 100644
index a58f8b466d96..000000000000
--- a/arch/ia64/include/asm/sparsemem.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_SPARSEMEM_H
-#define _ASM_IA64_SPARSEMEM_H
-
-#ifdef CONFIG_SPARSEMEM
-#include <asm/page.h>
-/*
- * SECTION_SIZE_BITS 2^N: how big each section will be
- * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space
- */
-
-#define SECTION_SIZE_BITS (30)
-#define MAX_PHYSMEM_BITS (50)
-#ifdef CONFIG_ARCH_FORCE_MAX_ORDER
-#if (CONFIG_ARCH_FORCE_MAX_ORDER + PAGE_SHIFT > SECTION_SIZE_BITS)
-#undef SECTION_SIZE_BITS
-#define SECTION_SIZE_BITS (CONFIG_ARCH_FORCE_MAX_ORDER + PAGE_SHIFT)
-#endif
-#endif
-
-#endif /* CONFIG_SPARSEMEM */
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-int memory_add_physaddr_to_nid(u64 addr);
-#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid
-#endif
-
-#endif /* _ASM_IA64_SPARSEMEM_H */
diff --git a/arch/ia64/include/asm/spinlock.h b/arch/ia64/include/asm/spinlock.h
deleted file mode 100644
index 0e5c1ad3239c..000000000000
--- a/arch/ia64/include/asm/spinlock.h
+++ /dev/null
@@ -1,265 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_SPINLOCK_H
-#define _ASM_IA64_SPINLOCK_H
-
-/*
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- *
- * This file is used for SMP configurations only.
- */
-
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/bitops.h>
-
-#include <linux/atomic.h>
-#include <asm/intrinsics.h>
-#include <asm/barrier.h>
-#include <asm/processor.h>
-
-#define arch_spin_lock_init(x) ((x)->lock = 0)
-
-/*
- * Ticket locks are conceptually two parts, one indicating the current head of
- * the queue, and the other indicating the current tail. The lock is acquired
- * by atomically noting the tail and incrementing it by one (thus adding
- * ourself to the queue and noting our position), then waiting until the head
- * becomes equal to the initial value of the tail.
- * The pad bits in the middle are used to prevent the next_ticket number
- * overflowing into the now_serving number.
- *
- * 31 17 16 15 14 0
- * +----------------------------------------------------+
- * | now_serving | padding | next_ticket |
- * +----------------------------------------------------+
- */
-
-#define TICKET_SHIFT 17
-#define TICKET_BITS 15
-#define TICKET_MASK ((1 << TICKET_BITS) - 1)
-
-static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
-{
- int *p = (int *)&lock->lock, ticket, serve;
-
- ticket = ia64_fetchadd(1, p, acq);
-
- if (!(((ticket >> TICKET_SHIFT) ^ ticket) & TICKET_MASK))
- return;
-
- ia64_invala();
-
- for (;;) {
- asm volatile ("ld4.c.nc %0=[%1]" : "=r"(serve) : "r"(p) : "memory");
-
- if (!(((serve >> TICKET_SHIFT) ^ ticket) & TICKET_MASK))
- return;
- cpu_relax();
- }
-}
-
-static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
-{
- int tmp = READ_ONCE(lock->lock);
-
- if (!(((tmp >> TICKET_SHIFT) ^ tmp) & TICKET_MASK))
- return ia64_cmpxchg(acq, &lock->lock, tmp, tmp + 1, sizeof (tmp)) == tmp;
- return 0;
-}
-
-static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
-{
- unsigned short *p = (unsigned short *)&lock->lock + 1, tmp;
-
- /* This could be optimised with ARCH_HAS_MMIOWB */
- mmiowb();
- asm volatile ("ld2.bias %0=[%1]" : "=r"(tmp) : "r"(p));
- WRITE_ONCE(*p, (tmp + 2) & ~1);
-}
-
-static inline int __ticket_spin_is_locked(arch_spinlock_t *lock)
-{
- long tmp = READ_ONCE(lock->lock);
-
- return !!(((tmp >> TICKET_SHIFT) ^ tmp) & TICKET_MASK);
-}
-
-static inline int __ticket_spin_is_contended(arch_spinlock_t *lock)
-{
- long tmp = READ_ONCE(lock->lock);
-
- return ((tmp - (tmp >> TICKET_SHIFT)) & TICKET_MASK) > 1;
-}
-
-static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
-{
- return !(((lock.lock >> TICKET_SHIFT) ^ lock.lock) & TICKET_MASK);
-}
-
-static inline int arch_spin_is_locked(arch_spinlock_t *lock)
-{
- return __ticket_spin_is_locked(lock);
-}
-
-static inline int arch_spin_is_contended(arch_spinlock_t *lock)
-{
- return __ticket_spin_is_contended(lock);
-}
-#define arch_spin_is_contended arch_spin_is_contended
-
-static __always_inline void arch_spin_lock(arch_spinlock_t *lock)
-{
- __ticket_spin_lock(lock);
-}
-
-static __always_inline int arch_spin_trylock(arch_spinlock_t *lock)
-{
- return __ticket_spin_trylock(lock);
-}
-
-static __always_inline void arch_spin_unlock(arch_spinlock_t *lock)
-{
- __ticket_spin_unlock(lock);
-}
-
-#ifdef ASM_SUPPORTED
-
-static __always_inline void
-arch_read_lock(arch_rwlock_t *lock)
-{
- unsigned long flags = 0;
-
- __asm__ __volatile__ (
- "tbit.nz p6, p0 = %1,%2\n"
- "br.few 3f\n"
- "1:\n"
- "fetchadd4.rel r2 = [%0], -1;;\n"
- "(p6) ssm psr.i\n"
- "2:\n"
- "hint @pause\n"
- "ld4 r2 = [%0];;\n"
- "cmp4.lt p7,p0 = r2, r0\n"
- "(p7) br.cond.spnt.few 2b\n"
- "(p6) rsm psr.i\n"
- ";;\n"
- "3:\n"
- "fetchadd4.acq r2 = [%0], 1;;\n"
- "cmp4.lt p7,p0 = r2, r0\n"
- "(p7) br.cond.spnt.few 1b\n"
- : : "r"(lock), "r"(flags), "i"(IA64_PSR_I_BIT)
- : "p6", "p7", "r2", "memory");
-}
-
-#else /* !ASM_SUPPORTED */
-
-#define arch_read_lock(rw) \
-do { \
- arch_rwlock_t *__read_lock_ptr = (rw); \
- \
- while (unlikely(ia64_fetchadd(1, (int *) __read_lock_ptr, acq) < 0)) { \
- ia64_fetchadd(-1, (int *) __read_lock_ptr, rel); \
- while (*(volatile int *)__read_lock_ptr < 0) \
- cpu_relax(); \
- } \
-} while (0)
-
-#endif /* !ASM_SUPPORTED */
-
-#define arch_read_unlock(rw) \
-do { \
- arch_rwlock_t *__read_lock_ptr = (rw); \
- ia64_fetchadd(-1, (int *) __read_lock_ptr, rel); \
-} while (0)
-
-#ifdef ASM_SUPPORTED
-
-static __always_inline void
-arch_write_lock(arch_rwlock_t *lock)
-{
- unsigned long flags = 0;
-
- __asm__ __volatile__ (
- "tbit.nz p6, p0 = %1, %2\n"
- "mov ar.ccv = r0\n"
- "dep r29 = -1, r0, 31, 1\n"
- "br.few 3f;;\n"
- "1:\n"
- "(p6) ssm psr.i\n"
- "2:\n"
- "hint @pause\n"
- "ld4 r2 = [%0];;\n"
- "cmp4.eq p0,p7 = r0, r2\n"
- "(p7) br.cond.spnt.few 2b\n"
- "(p6) rsm psr.i\n"
- ";;\n"
- "3:\n"
- "cmpxchg4.acq r2 = [%0], r29, ar.ccv;;\n"
- "cmp4.eq p0,p7 = r0, r2\n"
- "(p7) br.cond.spnt.few 1b;;\n"
- : : "r"(lock), "r"(flags), "i"(IA64_PSR_I_BIT)
- : "ar.ccv", "p6", "p7", "r2", "r29", "memory");
-}
-
-#define arch_write_trylock(rw) \
-({ \
- register long result; \
- \
- __asm__ __volatile__ ( \
- "mov ar.ccv = r0\n" \
- "dep r29 = -1, r0, 31, 1;;\n" \
- "cmpxchg4.acq %0 = [%1], r29, ar.ccv\n" \
- : "=r"(result) : "r"(rw) : "ar.ccv", "r29", "memory"); \
- (result == 0); \
-})
-
-static inline void arch_write_unlock(arch_rwlock_t *x)
-{
- u8 *y = (u8 *)x;
- barrier();
- asm volatile ("st1.rel.nta [%0] = r0\n\t" :: "r"(y+3) : "memory" );
-}
-
-#else /* !ASM_SUPPORTED */
-
-#define arch_write_lock(l) \
-({ \
- __u64 ia64_val, ia64_set_val = ia64_dep_mi(-1, 0, 31, 1); \
- __u32 *ia64_write_lock_ptr = (__u32 *) (l); \
- do { \
- while (*ia64_write_lock_ptr) \
- ia64_barrier(); \
- ia64_val = ia64_cmpxchg4_acq(ia64_write_lock_ptr, ia64_set_val, 0); \
- } while (ia64_val); \
-})
-
-#define arch_write_trylock(rw) \
-({ \
- __u64 ia64_val; \
- __u64 ia64_set_val = ia64_dep_mi(-1, 0, 31,1); \
- ia64_val = ia64_cmpxchg4_acq((__u32 *)(rw), ia64_set_val, 0); \
- (ia64_val == 0); \
-})
-
-static inline void arch_write_unlock(arch_rwlock_t *x)
-{
- barrier();
- x->write_lock = 0;
-}
-
-#endif /* !ASM_SUPPORTED */
-
-static inline int arch_read_trylock(arch_rwlock_t *x)
-{
- union {
- arch_rwlock_t lock;
- __u32 word;
- } old, new;
- old.lock = new.lock = *x;
- old.lock.write_lock = new.lock.write_lock = 0;
- ++new.lock.read_counter;
- return (u32)ia64_cmpxchg4_acq((__u32 *)(x), new.word, old.word) == old.word;
-}
-
-#endif /* _ASM_IA64_SPINLOCK_H */
diff --git a/arch/ia64/include/asm/spinlock_types.h b/arch/ia64/include/asm/spinlock_types.h
deleted file mode 100644
index 14b8a161c165..000000000000
--- a/arch/ia64/include/asm/spinlock_types.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_SPINLOCK_TYPES_H
-#define _ASM_IA64_SPINLOCK_TYPES_H
-
-#ifndef __LINUX_SPINLOCK_TYPES_RAW_H
-# error "please don't include this file directly"
-#endif
-
-typedef struct {
- volatile unsigned int lock;
-} arch_spinlock_t;
-
-#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
-
-typedef struct {
- volatile unsigned int read_counter : 31;
- volatile unsigned int write_lock : 1;
-} arch_rwlock_t;
-
-#define __ARCH_RW_LOCK_UNLOCKED { 0, 0 }
-
-#endif
diff --git a/arch/ia64/include/asm/string.h b/arch/ia64/include/asm/string.h
deleted file mode 100644
index 8b84df0dbfad..000000000000
--- a/arch/ia64/include/asm/string.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_STRING_H
-#define _ASM_IA64_STRING_H
-
-/*
- * Here is where we want to put optimized versions of the string
- * routines.
- *
- * Copyright (C) 1998-2000, 2002 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-
-#define __HAVE_ARCH_STRLEN 1 /* see arch/ia64/lib/strlen.S */
-#define __HAVE_ARCH_MEMSET 1 /* see arch/ia64/lib/memset.S */
-#define __HAVE_ARCH_MEMCPY 1 /* see arch/ia64/lib/memcpy.S */
-
-extern __kernel_size_t strlen (const char *);
-extern void *memcpy (void *, const void *, __kernel_size_t);
-extern void *memset (void *, int, __kernel_size_t);
-
-#endif /* _ASM_IA64_STRING_H */
diff --git a/arch/ia64/include/asm/switch_to.h b/arch/ia64/include/asm/switch_to.h
deleted file mode 100644
index a5a4e09468fa..000000000000
--- a/arch/ia64/include/asm/switch_to.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Low-level task switching. This is based on information published in
- * the Processor Abstraction Layer and the System Abstraction Layer
- * manual.
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
- */
-#ifndef _ASM_IA64_SWITCH_TO_H
-#define _ASM_IA64_SWITCH_TO_H
-
-#include <linux/percpu.h>
-
-struct task_struct;
-
-/*
- * Context switch from one thread to another. If the two threads have
- * different address spaces, schedule() has already taken care of
- * switching to the new address space by calling switch_mm().
- *
- * Disabling access to the fph partition and the debug-register
- * context switch MUST be done before calling ia64_switch_to() since a
- * newly created thread returns directly to
- * ia64_ret_from_syscall_clear_r8.
- */
-extern struct task_struct *ia64_switch_to (void *next_task);
-
-extern void ia64_save_extra (struct task_struct *task);
-extern void ia64_load_extra (struct task_struct *task);
-
-#define IA64_HAS_EXTRA_STATE(t) \
- ((t)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID))
-
-#define __switch_to(prev,next,last) do { \
- if (IA64_HAS_EXTRA_STATE(prev)) \
- ia64_save_extra(prev); \
- if (IA64_HAS_EXTRA_STATE(next)) \
- ia64_load_extra(next); \
- ia64_psr(task_pt_regs(next))->dfh = !ia64_is_local_fpu_owner(next); \
- (last) = ia64_switch_to((next)); \
-} while (0)
-
-#ifdef CONFIG_SMP
-/*
- * In the SMP case, we save the fph state when context-switching away from a thread that
- * modified fph. This way, when the thread gets scheduled on another CPU, the CPU can
- * pick up the state from task->thread.fph, avoiding the complication of having to fetch
- * the latest fph state from another CPU. In other words: eager save, lazy restore.
- */
-# define switch_to(prev,next,last) do { \
- if (ia64_psr(task_pt_regs(prev))->mfh && ia64_is_local_fpu_owner(prev)) { \
- ia64_psr(task_pt_regs(prev))->mfh = 0; \
- (prev)->thread.flags |= IA64_THREAD_FPH_VALID; \
- __ia64_save_fpu((prev)->thread.fph); \
- } \
- __switch_to(prev, next, last); \
- /* "next" in old context is "current" in new context */ \
- if (unlikely((current->thread.flags & IA64_THREAD_MIGRATION) && \
- (task_cpu(current) != \
- task_thread_info(current)->last_cpu))) { \
- task_thread_info(current)->last_cpu = task_cpu(current); \
- } \
-} while (0)
-#else
-# define switch_to(prev,next,last) __switch_to(prev, next, last)
-#endif
-
-#endif /* _ASM_IA64_SWITCH_TO_H */
diff --git a/arch/ia64/include/asm/syscall.h b/arch/ia64/include/asm/syscall.h
deleted file mode 100644
index 2b02a3fb862a..000000000000
--- a/arch/ia64/include/asm/syscall.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Access to user system call parameters and results
- *
- * Copyright (C) 2008 Intel Corp. Shaohua Li <shaohua.li@intel.com>
- *
- * See asm-generic/syscall.h for descriptions of what we must do here.
- */
-
-#ifndef _ASM_SYSCALL_H
-#define _ASM_SYSCALL_H 1
-
-#include <uapi/linux/audit.h>
-#include <linux/sched.h>
-#include <linux/err.h>
-
-static inline long syscall_get_nr(struct task_struct *task,
- struct pt_regs *regs)
-{
- if ((long)regs->cr_ifs < 0) /* Not a syscall */
- return -1;
-
- return regs->r15;
-}
-
-static inline void syscall_rollback(struct task_struct *task,
- struct pt_regs *regs)
-{
- /* do nothing */
-}
-
-static inline long syscall_get_error(struct task_struct *task,
- struct pt_regs *regs)
-{
- return regs->r10 == -1 ? -regs->r8:0;
-}
-
-static inline long syscall_get_return_value(struct task_struct *task,
- struct pt_regs *regs)
-{
- return regs->r8;
-}
-
-static inline void syscall_set_return_value(struct task_struct *task,
- struct pt_regs *regs,
- int error, long val)
-{
- if (error) {
- /* error < 0, but ia64 uses > 0 return value */
- regs->r8 = -error;
- regs->r10 = -1;
- } else {
- regs->r8 = val;
- regs->r10 = 0;
- }
-}
-
-extern void syscall_get_arguments(struct task_struct *task,
- struct pt_regs *regs, unsigned long *args);
-
-static inline int syscall_get_arch(struct task_struct *task)
-{
- return AUDIT_ARCH_IA64;
-}
-#endif /* _ASM_SYSCALL_H */
diff --git a/arch/ia64/include/asm/thread_info.h b/arch/ia64/include/asm/thread_info.h
deleted file mode 100644
index 21b257117e0a..000000000000
--- a/arch/ia64/include/asm/thread_info.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2002-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#ifndef _ASM_IA64_THREAD_INFO_H
-#define _ASM_IA64_THREAD_INFO_H
-
-#ifndef ASM_OFFSETS_C
-#include <asm/asm-offsets.h>
-#endif
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-
-#define THREAD_SIZE KERNEL_STACK_SIZE
-
-#ifndef __ASSEMBLY__
-
-/*
- * On IA-64, we want to keep the task structure and kernel stack together, so they can be
- * mapped by a single TLB entry and so they can be addressed by the "current" pointer
- * without having to do pointer masking.
- */
-struct thread_info {
- struct task_struct *task; /* XXX not really needed, except for dup_task_struct() */
- __u32 flags; /* thread_info flags (see TIF_*) */
- __u32 cpu; /* current CPU */
- __u32 last_cpu; /* Last CPU thread ran on */
- __u32 status; /* Thread synchronous flags */
- int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
- __u64 utime;
- __u64 stime;
- __u64 gtime;
- __u64 hardirq_time;
- __u64 softirq_time;
- __u64 idle_time;
- __u64 ac_stamp;
- __u64 ac_leave;
- __u64 ac_stime;
- __u64 ac_utime;
-#endif
-};
-
-#define INIT_THREAD_INFO(tsk) \
-{ \
- .task = &tsk, \
- .flags = 0, \
- .cpu = 0, \
- .preempt_count = INIT_PREEMPT_COUNT, \
-}
-
-#ifndef ASM_OFFSETS_C
-/* how to get the thread information struct from C */
-#define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
-#define arch_alloc_thread_stack_node(tsk, node) \
- ((unsigned long *) ((char *) (tsk) + IA64_TASK_SIZE))
-#define task_thread_info(tsk) ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
-#else
-#define current_thread_info() ((struct thread_info *) 0)
-#define arch_alloc_thread_stack_node(tsk, node) ((unsigned long *) 0)
-#define task_thread_info(tsk) ((struct thread_info *) 0)
-#endif
-#define arch_free_thread_stack(tsk) /* nothing */
-#define task_stack_page(tsk) ((void *)(tsk))
-
-#define __HAVE_THREAD_FUNCTIONS
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
-#define setup_thread_stack(p, org) \
- *task_thread_info(p) = *task_thread_info(org); \
- task_thread_info(p)->ac_stime = 0; \
- task_thread_info(p)->ac_utime = 0; \
- task_thread_info(p)->task = (p);
-#else
-#define setup_thread_stack(p, org) \
- *task_thread_info(p) = *task_thread_info(org); \
- task_thread_info(p)->task = (p);
-#endif
-#define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET)
-
-#define alloc_task_struct_node(node) \
-({ \
- struct page *page = alloc_pages_node(node, GFP_KERNEL | __GFP_COMP, \
- KERNEL_STACK_SIZE_ORDER); \
- struct task_struct *ret = page ? page_address(page) : NULL; \
- \
- ret; \
-})
-#define free_task_struct(tsk) free_pages((unsigned long) (tsk), KERNEL_STACK_SIZE_ORDER)
-
-#endif /* !__ASSEMBLY */
-
-/*
- * thread information flags
- * - these are process state flags that various assembly files may need to access
- * - pending work-to-be-done flags are in least-significant 16 bits, other flags
- * in top 16 bits
- */
-#define TIF_SIGPENDING 0 /* signal pending */
-#define TIF_NEED_RESCHED 1 /* rescheduling necessary */
-#define TIF_SYSCALL_TRACE 2 /* syscall trace active */
-#define TIF_SYSCALL_AUDIT 3 /* syscall auditing active */
-#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
-#define TIF_NOTIFY_SIGNAL 5 /* signal notification exist */
-#define TIF_NOTIFY_RESUME 6 /* resumption notification requested */
-#define TIF_MEMDIE 17 /* is terminating due to OOM killer */
-#define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */
-#define TIF_DB_DISABLED 19 /* debug trap disabled for fsyscall */
-#define TIF_RESTORE_RSE 21 /* user RBS is newer than kernel RBS */
-#define TIF_POLLING_NRFLAG 22 /* idle is polling for TIF_NEED_RESCHED */
-
-#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
-#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
-#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
-#define _TIF_SYSCALL_TRACEAUDIT (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP)
-#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
-#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
-#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
-#define _TIF_MCA_INIT (1 << TIF_MCA_INIT)
-#define _TIF_DB_DISABLED (1 << TIF_DB_DISABLED)
-#define _TIF_RESTORE_RSE (1 << TIF_RESTORE_RSE)
-#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
-
-/* "work to do on user-return" bits */
-#define TIF_ALLWORK_MASK (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SYSCALL_AUDIT|\
- _TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_NOTIFY_SIGNAL)
-/* like TIF_ALLWORK_BITS but sans TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT */
-#define TIF_WORK_MASK (TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT))
-
-#endif /* _ASM_IA64_THREAD_INFO_H */
diff --git a/arch/ia64/include/asm/timex.h b/arch/ia64/include/asm/timex.h
deleted file mode 100644
index 7ccc077a60be..000000000000
--- a/arch/ia64/include/asm/timex.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_TIMEX_H
-#define _ASM_IA64_TIMEX_H
-
-/*
- * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-/*
- * 2001/01/18 davidm Removed CLOCK_TICK_RATE. It makes no sense on IA-64.
- * Also removed cacheflush_time as it's entirely unused.
- */
-
-#include <asm/intrinsics.h>
-#include <asm/processor.h>
-
-typedef unsigned long cycles_t;
-
-extern void (*ia64_udelay)(unsigned long usecs);
-
-/*
- * For performance reasons, we don't want to define CLOCK_TICK_TRATE as
- * local_cpu_data->itc_rate. Fortunately, we don't have to, either: according to George
- * Anzinger, 1/CLOCK_TICK_RATE is taken as the resolution of the timer clock. The time
- * calculation assumes that you will use enough of these so that your tick size <= 1/HZ.
- * If the calculation shows that your CLOCK_TICK_RATE can not supply exactly 1/HZ ticks,
- * the actual value is calculated and used to update the wall clock each jiffie. Setting
- * the CLOCK_TICK_RATE to x*HZ insures that the calculation will find no errors. Hence we
- * pick a multiple of HZ which gives us a (totally virtual) CLOCK_TICK_RATE of about
- * 100MHz.
- */
-#define CLOCK_TICK_RATE (HZ * 100000UL)
-
-static inline cycles_t
-get_cycles (void)
-{
- cycles_t ret;
-
- ret = ia64_getreg(_IA64_REG_AR_ITC);
- return ret;
-}
-#define get_cycles get_cycles
-
-extern void ia64_cpu_local_tick (void);
-extern unsigned long long ia64_native_sched_clock (void);
-
-#endif /* _ASM_IA64_TIMEX_H */
diff --git a/arch/ia64/include/asm/tlb.h b/arch/ia64/include/asm/tlb.h
deleted file mode 100644
index a15fe0809aae..000000000000
--- a/arch/ia64/include/asm/tlb.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_TLB_H
-#define _ASM_IA64_TLB_H
-/*
- * Based on <asm-generic/tlb.h>.
- *
- * Copyright (C) 2002-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-/*
- * Removing a translation from a page table (including TLB-shootdown) is a four-step
- * procedure:
- *
- * (1) Flush (virtual) caches --- ensures virtual memory is coherent with kernel memory
- * (this is a no-op on ia64).
- * (2) Clear the relevant portions of the page-table
- * (3) Flush the TLBs --- ensures that stale content is gone from CPU TLBs
- * (4) Release the pages that were freed up in step (2).
- *
- * Note that the ordering of these steps is crucial to avoid races on MP machines.
- *
- * The Linux kernel defines several platform-specific hooks for TLB-shootdown. When
- * unmapping a portion of the virtual address space, these hooks are called according to
- * the following template:
- *
- * tlb <- tlb_gather_mmu(mm); // start unmap for address space MM
- * {
- * for each vma that needs a shootdown do {
- * tlb_start_vma(tlb, vma);
- * for each page-table-entry PTE that needs to be removed do {
- * tlb_remove_tlb_entry(tlb, pte, address);
- * if (pte refers to a normal page) {
- * tlb_remove_page(tlb, page);
- * }
- * }
- * tlb_end_vma(tlb, vma);
- * }
- * }
- * tlb_finish_mmu(tlb); // finish unmap for address space MM
- */
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/swap.h>
-
-#include <asm/processor.h>
-#include <asm/tlbflush.h>
-
-#include <asm-generic/tlb.h>
-
-#endif /* _ASM_IA64_TLB_H */
diff --git a/arch/ia64/include/asm/tlbflush.h b/arch/ia64/include/asm/tlbflush.h
deleted file mode 100644
index ceac10c4d6e2..000000000000
--- a/arch/ia64/include/asm/tlbflush.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_TLBFLUSH_H
-#define _ASM_IA64_TLBFLUSH_H
-
-/*
- * Copyright (C) 2002 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-
-#include <linux/mm.h>
-
-#include <asm/intrinsics.h>
-#include <asm/mmu_context.h>
-#include <asm/page.h>
-
-struct ia64_tr_entry {
- u64 ifa;
- u64 itir;
- u64 pte;
- u64 rr;
-}; /*Record for tr entry!*/
-
-extern int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size);
-extern void ia64_ptr_entry(u64 target_mask, int slot);
-extern struct ia64_tr_entry *ia64_idtrs[NR_CPUS];
-
-/*
- region register macros
-*/
-#define RR_TO_VE(val) (((val) >> 0) & 0x0000000000000001)
-#define RR_VE(val) (((val) & 0x0000000000000001) << 0)
-#define RR_VE_MASK 0x0000000000000001L
-#define RR_VE_SHIFT 0
-#define RR_TO_PS(val) (((val) >> 2) & 0x000000000000003f)
-#define RR_PS(val) (((val) & 0x000000000000003f) << 2)
-#define RR_PS_MASK 0x00000000000000fcL
-#define RR_PS_SHIFT 2
-#define RR_RID_MASK 0x00000000ffffff00L
-#define RR_TO_RID(val) ((val >> 8) & 0xffffff)
-
-/*
- * Now for some TLB flushing routines. This is the kind of stuff that
- * can be very expensive, so try to avoid them whenever possible.
- */
-extern void setup_ptcg_sem(int max_purges, int from_palo);
-
-/*
- * Flush everything (kernel mapping may also have changed due to
- * vmalloc/vfree).
- */
-extern void local_flush_tlb_all (void);
-
-#ifdef CONFIG_SMP
- extern void smp_flush_tlb_all (void);
- extern void smp_flush_tlb_mm (struct mm_struct *mm);
- extern void smp_flush_tlb_cpumask (cpumask_t xcpumask);
-# define flush_tlb_all() smp_flush_tlb_all()
-#else
-# define flush_tlb_all() local_flush_tlb_all()
-# define smp_flush_tlb_cpumask(m) local_flush_tlb_all()
-#endif
-
-static inline void
-local_finish_flush_tlb_mm (struct mm_struct *mm)
-{
- if (mm == current->active_mm)
- activate_context(mm);
-}
-
-/*
- * Flush a specified user mapping. This is called, e.g., as a result of fork() and
- * exit(). fork() ends up here because the copy-on-write mechanism needs to write-protect
- * the PTEs of the parent task.
- */
-static inline void
-flush_tlb_mm (struct mm_struct *mm)
-{
- if (!mm)
- return;
-
- set_bit(mm->context, ia64_ctx.flushmap);
- mm->context = 0;
-
- if (atomic_read(&mm->mm_users) == 0)
- return; /* happens as a result of exit_mmap() */
-
-#ifdef CONFIG_SMP
- smp_flush_tlb_mm(mm);
-#else
- local_finish_flush_tlb_mm(mm);
-#endif
-}
-
-extern void flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long end);
-
-/*
- * Page-granular tlb flush.
- */
-static inline void
-flush_tlb_page (struct vm_area_struct *vma, unsigned long addr)
-{
-#ifdef CONFIG_SMP
- flush_tlb_range(vma, (addr & PAGE_MASK), (addr & PAGE_MASK) + PAGE_SIZE);
-#else
- if (vma->vm_mm == current->active_mm)
- ia64_ptcl(addr, (PAGE_SHIFT << 2));
- else
- vma->vm_mm->context = 0;
-#endif
-}
-
-/*
- * Flush the local TLB. Invoked from another cpu using an IPI.
- */
-#ifdef CONFIG_SMP
-void smp_local_flush_tlb(void);
-#else
-#define smp_local_flush_tlb()
-#endif
-
-static inline void flush_tlb_kernel_range(unsigned long start,
- unsigned long end)
-{
- flush_tlb_all(); /* XXX fix me */
-}
-
-#endif /* _ASM_IA64_TLBFLUSH_H */
diff --git a/arch/ia64/include/asm/topology.h b/arch/ia64/include/asm/topology.h
deleted file mode 100644
index 43567240b0d6..000000000000
--- a/arch/ia64/include/asm/topology.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2002, Erich Focht, NEC
- *
- * All rights reserved.
- */
-#ifndef _ASM_IA64_TOPOLOGY_H
-#define _ASM_IA64_TOPOLOGY_H
-
-#include <asm/acpi.h>
-#include <asm/numa.h>
-#include <asm/smp.h>
-
-#ifdef CONFIG_NUMA
-
-/* Nodes w/o CPUs are preferred for memory allocations, see build_zonelists */
-#define PENALTY_FOR_NODE_WITH_CPUS 255
-
-/*
- * Nodes within this distance are eligible for reclaim by zone_reclaim() when
- * zone_reclaim_mode is enabled.
- */
-#define RECLAIM_DISTANCE 15
-
-/*
- * Returns a bitmask of CPUs on Node 'node'.
- */
-#define cpumask_of_node(node) ((node) == -1 ? \
- cpu_all_mask : \
- &node_to_cpu_mask[node])
-
-/*
- * Determines the node for a given pci bus
- */
-#define pcibus_to_node(bus) PCI_CONTROLLER(bus)->node
-
-void build_cpu_to_node_map(void);
-
-#endif /* CONFIG_NUMA */
-
-#ifdef CONFIG_SMP
-#define topology_physical_package_id(cpu) (cpu_data(cpu)->socket_id)
-#define topology_core_id(cpu) (cpu_data(cpu)->core_id)
-#define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
-#define topology_sibling_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
-#endif
-
-extern void arch_fix_phys_package_id(int num, u32 slot);
-
-#define cpumask_of_pcibus(bus) (pcibus_to_node(bus) == -1 ? \
- cpu_all_mask : \
- cpumask_of_node(pcibus_to_node(bus)))
-
-#include <asm-generic/topology.h>
-
-#endif /* _ASM_IA64_TOPOLOGY_H */
diff --git a/arch/ia64/include/asm/types.h b/arch/ia64/include/asm/types.h
deleted file mode 100644
index 5ddc7703de99..000000000000
--- a/arch/ia64/include/asm/types.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * This file is never included by application software unless explicitly
- * requested (e.g., via linux/types.h) in which case the application is
- * Linux specific so (user-) name space pollution is not a major issue.
- * However, for interoperability, libraries still need to be careful to
- * avoid naming clashes.
- *
- * Based on <asm-alpha/types.h>.
- *
- * Modified 1998-2000, 2002
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-#ifndef _ASM_IA64_TYPES_H
-#define _ASM_IA64_TYPES_H
-
-#include <asm-generic/int-ll64.h>
-#include <uapi/asm/types.h>
-
-#ifdef __ASSEMBLY__
-#else
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-
-struct fnptr {
- unsigned long ip;
- unsigned long gp;
-};
-
-#endif /* !__ASSEMBLY__ */
-#endif /* _ASM_IA64_TYPES_H */
diff --git a/arch/ia64/include/asm/uaccess.h b/arch/ia64/include/asm/uaccess.h
deleted file mode 100644
index 60adadeb3e9e..000000000000
--- a/arch/ia64/include/asm/uaccess.h
+++ /dev/null
@@ -1,265 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_UACCESS_H
-#define _ASM_IA64_UACCESS_H
-
-/*
- * This file defines various macros to transfer memory areas across
- * the user/kernel boundary. This needs to be done carefully because
- * this code is executed in kernel mode and uses user-specified
- * addresses. Thus, we need to be careful not to let the user to
- * trick us into accessing kernel memory that would normally be
- * inaccessible. This code is also fairly performance sensitive,
- * so we want to spend as little time doing safety checks as
- * possible.
- *
- * To make matters a bit more interesting, these macros sometimes also
- * called from within the kernel itself, in which case the address
- * validity check must be skipped. The get_fs() macro tells us what
- * to do: if get_fs()==USER_DS, checking is performed, if
- * get_fs()==KERNEL_DS, checking is bypassed.
- *
- * Note that even if the memory area specified by the user is in a
- * valid address range, it is still possible that we'll get a page
- * fault while accessing it. This is handled by filling out an
- * exception handler fixup entry for each instruction that has the
- * potential to fault. When such a fault occurs, the page fault
- * handler checks to see whether the faulting instruction has a fixup
- * associated and, if so, sets r8 to -EFAULT and clears r9 to 0 and
- * then resumes execution at the continuation point.
- *
- * Based on <asm-alpha/uaccess.h>.
- *
- * Copyright (C) 1998, 1999, 2001-2004 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/compiler.h>
-#include <linux/page-flags.h>
-
-#include <asm/intrinsics.h>
-#include <linux/pgtable.h>
-#include <asm/io.h>
-#include <asm/extable.h>
-
-/*
- * When accessing user memory, we need to make sure the entire area really is
- * in user-level space. We also need to make sure that the address doesn't
- * point inside the virtually mapped linear page table.
- */
-static inline int __access_ok(const void __user *p, unsigned long size)
-{
- unsigned long limit = TASK_SIZE;
- unsigned long addr = (unsigned long)p;
-
- return likely((size <= limit) && (addr <= (limit - size)) &&
- likely(REGION_OFFSET(addr) < RGN_MAP_LIMIT));
-}
-#define __access_ok __access_ok
-#include <asm-generic/access_ok.h>
-
-/*
- * These are the main single-value transfer routines. They automatically
- * use the right size if we just have the right pointer type.
- *
- * Careful to not
- * (a) re-use the arguments for side effects (sizeof/typeof is ok)
- * (b) require any knowledge of processes at this stage
- */
-#define put_user(x, ptr) __put_user_check((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)))
-#define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr)))
-
-/*
- * The "__xxx" versions do not do address space checking, useful when
- * doing multiple accesses to the same area (the programmer has to do the
- * checks by hand with "access_ok()")
- */
-#define __put_user(x, ptr) __put_user_nocheck((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)))
-#define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
-
-#ifdef ASM_SUPPORTED
- struct __large_struct { unsigned long buf[100]; };
-# define __m(x) (*(struct __large_struct __user *)(x))
-
-/* We need to declare the __ex_table section before we can use it in .xdata. */
-asm (".section \"__ex_table\", \"a\"\n\t.previous");
-
-# define __get_user_size(val, addr, n, err) \
-do { \
- register long __gu_r8 asm ("r8") = 0; \
- register long __gu_r9 asm ("r9"); \
- asm ("\n[1:]\tld"#n" %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \
- "\t.xdata4 \"__ex_table\", 1b-., 1f-.+4\n" \
- "[1:]" \
- : "=r"(__gu_r9), "=r"(__gu_r8) : "m"(__m(addr)), "1"(__gu_r8)); \
- (err) = __gu_r8; \
- (val) = __gu_r9; \
-} while (0)
-
-/*
- * The "__put_user_size()" macro tells gcc it reads from memory instead of writing it. This
- * is because they do not write to any memory gcc knows about, so there are no aliasing
- * issues.
- */
-# define __put_user_size(val, addr, n, err) \
-do { \
- register long __pu_r8 asm ("r8") = 0; \
- asm volatile ("\n[1:]\tst"#n" %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \
- "\t.xdata4 \"__ex_table\", 1b-., 1f-.\n" \
- "[1:]" \
- : "=r"(__pu_r8) : "m"(__m(addr)), "rO"(val), "0"(__pu_r8)); \
- (err) = __pu_r8; \
-} while (0)
-
-#else /* !ASM_SUPPORTED */
-# define RELOC_TYPE 2 /* ip-rel */
-# define __get_user_size(val, addr, n, err) \
-do { \
- __ld_user("__ex_table", (unsigned long) addr, n, RELOC_TYPE); \
- (err) = ia64_getreg(_IA64_REG_R8); \
- (val) = ia64_getreg(_IA64_REG_R9); \
-} while (0)
-# define __put_user_size(val, addr, n, err) \
-do { \
- __st_user("__ex_table", (unsigned long) addr, n, RELOC_TYPE, \
- (__force unsigned long) (val)); \
- (err) = ia64_getreg(_IA64_REG_R8); \
-} while (0)
-#endif /* !ASM_SUPPORTED */
-
-extern void __get_user_unknown (void);
-
-/*
- * Evaluating arguments X, PTR, SIZE, and SEGMENT may involve subroutine-calls, which
- * could clobber r8 and r9 (among others). Thus, be careful not to evaluate it while
- * using r8/r9.
- */
-#define __do_get_user(check, x, ptr, size) \
-({ \
- const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \
- __typeof__ (size) __gu_size = (size); \
- long __gu_err = -EFAULT; \
- unsigned long __gu_val = 0; \
- if (!check || __access_ok(__gu_ptr, size)) \
- switch (__gu_size) { \
- case 1: __get_user_size(__gu_val, __gu_ptr, 1, __gu_err); break; \
- case 2: __get_user_size(__gu_val, __gu_ptr, 2, __gu_err); break; \
- case 4: __get_user_size(__gu_val, __gu_ptr, 4, __gu_err); break; \
- case 8: __get_user_size(__gu_val, __gu_ptr, 8, __gu_err); break; \
- default: __get_user_unknown(); break; \
- } \
- (x) = (__force __typeof__(*(__gu_ptr))) __gu_val; \
- __gu_err; \
-})
-
-#define __get_user_nocheck(x, ptr, size) __do_get_user(0, x, ptr, size)
-#define __get_user_check(x, ptr, size) __do_get_user(1, x, ptr, size)
-
-extern void __put_user_unknown (void);
-
-/*
- * Evaluating arguments X, PTR, SIZE, and SEGMENT may involve subroutine-calls, which
- * could clobber r8 (among others). Thus, be careful not to evaluate them while using r8.
- */
-#define __do_put_user(check, x, ptr, size) \
-({ \
- __typeof__ (x) __pu_x = (x); \
- __typeof__ (*(ptr)) __user *__pu_ptr = (ptr); \
- __typeof__ (size) __pu_size = (size); \
- long __pu_err = -EFAULT; \
- \
- if (!check || __access_ok(__pu_ptr, __pu_size)) \
- switch (__pu_size) { \
- case 1: __put_user_size(__pu_x, __pu_ptr, 1, __pu_err); break; \
- case 2: __put_user_size(__pu_x, __pu_ptr, 2, __pu_err); break; \
- case 4: __put_user_size(__pu_x, __pu_ptr, 4, __pu_err); break; \
- case 8: __put_user_size(__pu_x, __pu_ptr, 8, __pu_err); break; \
- default: __put_user_unknown(); break; \
- } \
- __pu_err; \
-})
-
-#define __put_user_nocheck(x, ptr, size) __do_put_user(0, x, ptr, size)
-#define __put_user_check(x, ptr, size) __do_put_user(1, x, ptr, size)
-
-/*
- * Complex access routines
- */
-extern unsigned long __must_check __copy_user (void __user *to, const void __user *from,
- unsigned long count);
-
-static inline unsigned long
-raw_copy_to_user(void __user *to, const void *from, unsigned long count)
-{
- return __copy_user(to, (__force void __user *) from, count);
-}
-
-static inline unsigned long
-raw_copy_from_user(void *to, const void __user *from, unsigned long count)
-{
- return __copy_user((__force void __user *) to, from, count);
-}
-
-#define INLINE_COPY_FROM_USER
-#define INLINE_COPY_TO_USER
-
-extern unsigned long __do_clear_user (void __user *, unsigned long);
-
-#define __clear_user(to, n) __do_clear_user(to, n)
-
-#define clear_user(to, n) \
-({ \
- unsigned long __cu_len = (n); \
- if (__access_ok(to, __cu_len)) \
- __cu_len = __do_clear_user(to, __cu_len); \
- __cu_len; \
-})
-
-
-/*
- * Returns: -EFAULT if exception before terminator, N if the entire buffer filled, else
- * strlen.
- */
-extern long __must_check __strncpy_from_user (char *to, const char __user *from, long to_len);
-
-#define strncpy_from_user(to, from, n) \
-({ \
- const char __user * __sfu_from = (from); \
- long __sfu_ret = -EFAULT; \
- if (__access_ok(__sfu_from, 0)) \
- __sfu_ret = __strncpy_from_user((to), __sfu_from, (n)); \
- __sfu_ret; \
-})
-
-/*
- * Returns: 0 if exception before NUL or reaching the supplied limit
- * (N), a value greater than N if the limit would be exceeded, else
- * strlen.
- */
-extern unsigned long __strnlen_user (const char __user *, long);
-
-#define strnlen_user(str, len) \
-({ \
- const char __user *__su_str = (str); \
- unsigned long __su_ret = 0; \
- if (__access_ok(__su_str, 0)) \
- __su_ret = __strnlen_user(__su_str, len); \
- __su_ret; \
-})
-
-#define ARCH_HAS_TRANSLATE_MEM_PTR 1
-static __inline__ void *
-xlate_dev_mem_ptr(phys_addr_t p)
-{
- struct page *page;
- void *ptr;
-
- page = pfn_to_page(p >> PAGE_SHIFT);
- if (PageUncached(page))
- ptr = (void *)p + __IA64_UNCACHED_OFFSET;
- else
- ptr = __va(p);
-
- return ptr;
-}
-
-#endif /* _ASM_IA64_UACCESS_H */
diff --git a/arch/ia64/include/asm/uncached.h b/arch/ia64/include/asm/uncached.h
deleted file mode 100644
index 98f447fc77b7..000000000000
--- a/arch/ia64/include/asm/uncached.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2001-2008 Silicon Graphics, Inc. All rights reserved.
- *
- * Prototypes for the uncached page allocator
- */
-
-extern unsigned long uncached_alloc_page(int starting_nid, int n_pages);
-extern void uncached_free_page(unsigned long uc_addr, int n_pages);
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h
deleted file mode 100644
index 9ba6110b10b9..000000000000
--- a/arch/ia64/include/asm/unistd.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * IA-64 Linux syscall numbers and inline-functions.
- *
- * Copyright (C) 1998-2005 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#ifndef _ASM_IA64_UNISTD_H
-#define _ASM_IA64_UNISTD_H
-
-#include <uapi/asm/unistd.h>
-
-#define NR_syscalls __NR_syscalls /* length of syscall table */
-
-#define __ARCH_WANT_NEW_STAT
-#define __ARCH_WANT_SYS_UTIME
-
-#if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
-
-#include <linux/types.h>
-#include <linux/linkage.h>
-#include <linux/compiler.h>
-
-extern long __ia64_syscall (long a0, long a1, long a2, long a3, long a4, long nr);
-
-asmlinkage unsigned long sys_mmap(
- unsigned long addr, unsigned long len,
- int prot, int flags,
- int fd, long off);
-asmlinkage unsigned long sys_mmap2(
- unsigned long addr, unsigned long len,
- int prot, int flags,
- int fd, long pgoff);
-struct pt_regs;
-asmlinkage long sys_ia64_pipe(void);
-
-#endif /* !__ASSEMBLY__ */
-#endif /* _ASM_IA64_UNISTD_H */
diff --git a/arch/ia64/include/asm/unwind.h b/arch/ia64/include/asm/unwind.h
deleted file mode 100644
index c5bd4b3e3a36..000000000000
--- a/arch/ia64/include/asm/unwind.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_UNWIND_H
-#define _ASM_IA64_UNWIND_H
-
-/*
- * Copyright (C) 1999-2000, 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * A simple API for unwinding kernel stacks. This is used for
- * debugging and error reporting purposes. The kernel doesn't need
- * full-blown stack unwinding with all the bells and whitles, so there
- * is not much point in implementing the full IA-64 unwind API (though
- * it would of course be possible to implement the kernel API on top
- * of it).
- */
-
-struct task_struct; /* forward declaration */
-struct switch_stack; /* forward declaration */
-
-enum unw_application_register {
- UNW_AR_BSP,
- UNW_AR_BSPSTORE,
- UNW_AR_PFS,
- UNW_AR_RNAT,
- UNW_AR_UNAT,
- UNW_AR_LC,
- UNW_AR_EC,
- UNW_AR_FPSR,
- UNW_AR_RSC,
- UNW_AR_CCV,
- UNW_AR_CSD,
- UNW_AR_SSD
-};
-
-/*
- * The following declarations are private to the unwind
- * implementation:
- */
-
-struct unw_stack {
- unsigned long limit;
- unsigned long top;
-};
-
-#define UNW_FLAG_INTERRUPT_FRAME (1UL << 0)
-
-/*
- * No user of this module should every access this structure directly
- * as it is subject to change. It is declared here solely so we can
- * use automatic variables.
- */
-struct unw_frame_info {
- struct unw_stack regstk;
- struct unw_stack memstk;
- unsigned int flags;
- short hint;
- short prev_script;
-
- /* current frame info: */
- unsigned long bsp; /* backing store pointer value */
- unsigned long sp; /* stack pointer value */
- unsigned long psp; /* previous sp value */
- unsigned long ip; /* instruction pointer value */
- unsigned long pr; /* current predicate values */
- unsigned long *cfm_loc; /* cfm save location (or NULL) */
- unsigned long pt; /* struct pt_regs location */
-
- struct task_struct *task;
- struct switch_stack *sw;
-
- /* preserved state: */
- unsigned long *bsp_loc; /* previous bsp save location */
- unsigned long *bspstore_loc;
- unsigned long *pfs_loc;
- unsigned long *rnat_loc;
- unsigned long *rp_loc;
- unsigned long *pri_unat_loc;
- unsigned long *unat_loc;
- unsigned long *pr_loc;
- unsigned long *lc_loc;
- unsigned long *fpsr_loc;
- struct unw_ireg {
- unsigned long *loc;
- struct unw_ireg_nat {
- unsigned long type : 3; /* enum unw_nat_type */
- signed long off : 61; /* NaT word is at loc+nat.off */
- } nat;
- } r4, r5, r6, r7;
- unsigned long *b1_loc, *b2_loc, *b3_loc, *b4_loc, *b5_loc;
- struct ia64_fpreg *f2_loc, *f3_loc, *f4_loc, *f5_loc, *fr_loc[16];
-};
-
-/*
- * The official API follows below:
- */
-
-struct unw_table_entry {
- u64 start_offset;
- u64 end_offset;
- u64 info_offset;
-};
-
-/*
- * Initialize unwind support.
- */
-extern void unw_init (void);
-
-extern void *unw_add_unwind_table (const char *name, unsigned long segment_base, unsigned long gp,
- const void *table_start, const void *table_end);
-
-extern void unw_remove_unwind_table (void *handle);
-
-/*
- * Prepare to unwind blocked task t.
- */
-extern void unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t);
-
-extern void unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t,
- struct switch_stack *sw);
-
-/*
- * Prepare to unwind the currently running thread.
- */
-extern void unw_init_running (void (*callback)(struct unw_frame_info *info, void *arg), void *arg);
-
-/*
- * Unwind to previous to frame. Returns 0 if successful, negative
- * number in case of an error.
- */
-extern int unw_unwind (struct unw_frame_info *info);
-
-/*
- * Unwind until the return pointer is in user-land (or until an error
- * occurs). Returns 0 if successful, negative number in case of
- * error.
- */
-extern int unw_unwind_to_user (struct unw_frame_info *info);
-
-#define unw_is_intr_frame(info) (((info)->flags & UNW_FLAG_INTERRUPT_FRAME) != 0)
-
-static inline int
-unw_get_ip (struct unw_frame_info *info, unsigned long *valp)
-{
- *valp = (info)->ip;
- return 0;
-}
-
-static inline int
-unw_get_sp (struct unw_frame_info *info, unsigned long *valp)
-{
- *valp = (info)->sp;
- return 0;
-}
-
-static inline int
-unw_get_psp (struct unw_frame_info *info, unsigned long *valp)
-{
- *valp = (info)->psp;
- return 0;
-}
-
-static inline int
-unw_get_bsp (struct unw_frame_info *info, unsigned long *valp)
-{
- *valp = (info)->bsp;
- return 0;
-}
-
-static inline int
-unw_get_cfm (struct unw_frame_info *info, unsigned long *valp)
-{
- *valp = *(info)->cfm_loc;
- return 0;
-}
-
-static inline int
-unw_set_cfm (struct unw_frame_info *info, unsigned long val)
-{
- *(info)->cfm_loc = val;
- return 0;
-}
-
-static inline int
-unw_get_rp (struct unw_frame_info *info, unsigned long *val)
-{
- if (!info->rp_loc)
- return -1;
- *val = *info->rp_loc;
- return 0;
-}
-
-extern int unw_access_gr (struct unw_frame_info *, int, unsigned long *, char *, int);
-extern int unw_access_br (struct unw_frame_info *, int, unsigned long *, int);
-extern int unw_access_fr (struct unw_frame_info *, int, struct ia64_fpreg *, int);
-extern int unw_access_ar (struct unw_frame_info *, int, unsigned long *, int);
-extern int unw_access_pr (struct unw_frame_info *, unsigned long *, int);
-
-static inline int
-unw_set_gr (struct unw_frame_info *i, int n, unsigned long v, char nat)
-{
- return unw_access_gr(i, n, &v, &nat, 1);
-}
-
-static inline int
-unw_set_br (struct unw_frame_info *i, int n, unsigned long v)
-{
- return unw_access_br(i, n, &v, 1);
-}
-
-static inline int
-unw_set_fr (struct unw_frame_info *i, int n, struct ia64_fpreg v)
-{
- return unw_access_fr(i, n, &v, 1);
-}
-
-static inline int
-unw_set_ar (struct unw_frame_info *i, int n, unsigned long v)
-{
- return unw_access_ar(i, n, &v, 1);
-}
-
-static inline int
-unw_set_pr (struct unw_frame_info *i, unsigned long v)
-{
- return unw_access_pr(i, &v, 1);
-}
-
-#define unw_get_gr(i,n,v,nat) unw_access_gr(i,n,v,nat,0)
-#define unw_get_br(i,n,v) unw_access_br(i,n,v,0)
-#define unw_get_fr(i,n,v) unw_access_fr(i,n,v,0)
-#define unw_get_ar(i,n,v) unw_access_ar(i,n,v,0)
-#define unw_get_pr(i,v) unw_access_pr(i,v,0)
-
-#endif /* _ASM_UNWIND_H */
diff --git a/arch/ia64/include/asm/user.h b/arch/ia64/include/asm/user.h
deleted file mode 100644
index ec03d3ab8715..000000000000
--- a/arch/ia64/include/asm/user.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_USER_H
-#define _ASM_IA64_USER_H
-
-/*
- * Core file format: The core file is written in such a way that gdb
- * can understand it and provide useful information to the user (under
- * linux we use the `trad-core' bfd). The file contents are as
- * follows:
- *
- * upage: 1 page consisting of a user struct that tells gdb
- * what is present in the file. Directly after this is a
- * copy of the task_struct, which is currently not used by gdb,
- * but it may come in handy at some point. All of the registers
- * are stored as part of the upage. The upage should always be
- * only one page long.
- * data: The data segment follows next. We use current->end_text to
- * current->brk to pick up all of the user variables, plus any memory
- * that may have been sbrk'ed. No attempt is made to determine if a
- * page is demand-zero or if a page is totally unused, we just cover
- * the entire range. All of the addresses are rounded in such a way
- * that an integral number of pages is written.
- * stack: We need the stack information in order to get a meaningful
- * backtrace. We need to write the data from usp to
- * current->start_stack, so we round each of these in order to be able
- * to write an integer number of pages.
- *
- * Modified 1998, 1999, 2001
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-#include <linux/ptrace.h>
-#include <linux/types.h>
-
-#include <asm/page.h>
-
-#define EF_SIZE 3072 /* XXX fix me */
-
-struct user {
- unsigned long regs[EF_SIZE/8+32]; /* integer and fp regs */
- size_t u_tsize; /* text size (pages) */
- size_t u_dsize; /* data size (pages) */
- size_t u_ssize; /* stack size (pages) */
- unsigned long start_code; /* text starting address */
- unsigned long start_data; /* data starting address */
- unsigned long start_stack; /* stack starting address */
- long int signal; /* signal causing core dump */
- unsigned long u_ar0; /* help gdb find registers */
- unsigned long magic; /* identifies a core file */
- char u_comm[32]; /* user command name */
-};
-
-#endif /* _ASM_IA64_USER_H */
diff --git a/arch/ia64/include/asm/ustack.h b/arch/ia64/include/asm/ustack.h
deleted file mode 100644
index 112d40a0fec2..000000000000
--- a/arch/ia64/include/asm/ustack.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_USTACK_H
-#define _ASM_IA64_USTACK_H
-
-#include <asm/page.h>
-#include <uapi/asm/ustack.h>
-
-/* The absolute hard limit for stack size is 1/2 of the mappable space in the region */
-#define MAX_USER_STACK_SIZE (RGN_MAP_LIMIT/2)
-#define STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT)
-#define STACK_TOP_MAX STACK_TOP
-#endif /* _ASM_IA64_USTACK_H */
diff --git a/arch/ia64/include/asm/uv/uv.h b/arch/ia64/include/asm/uv/uv.h
deleted file mode 100644
index 48d4526bf4cd..000000000000
--- a/arch/ia64/include/asm/uv/uv.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_UV_UV_H
-#define _ASM_IA64_UV_UV_H
-
-#ifdef CONFIG_IA64_SGI_UV
-extern bool ia64_is_uv;
-
-static inline int is_uv_system(void)
-{
- return ia64_is_uv;
-}
-
-void __init uv_probe_system_type(void);
-void __init uv_setup(char **cmdline_p);
-#else /* CONFIG_IA64_SGI_UV */
-static inline int is_uv_system(void)
-{
- return false;
-}
-
-static inline void __init uv_probe_system_type(void)
-{
-}
-
-static inline void __init uv_setup(char **cmdline_p)
-{
-}
-#endif /* CONFIG_IA64_SGI_UV */
-
-#endif /* _ASM_IA64_UV_UV_H */
diff --git a/arch/ia64/include/asm/uv/uv_hub.h b/arch/ia64/include/asm/uv/uv_hub.h
deleted file mode 100644
index 809ddb6896db..000000000000
--- a/arch/ia64/include/asm/uv/uv_hub.h
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * SGI UV architectural definitions
- *
- * Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef __ASM_IA64_UV_HUB_H__
-#define __ASM_IA64_UV_HUB_H__
-
-#include <linux/numa.h>
-#include <linux/percpu.h>
-#include <asm/types.h>
-#include <asm/percpu.h>
-
-
-/*
- * Addressing Terminology
- *
- * M - The low M bits of a physical address represent the offset
- * into the blade local memory. RAM memory on a blade is physically
- * contiguous (although various IO spaces may punch holes in
- * it)..
- *
- * N - Number of bits in the node portion of a socket physical
- * address.
- *
- * NASID - network ID of a router, Mbrick or Cbrick. Nasid values of
- * routers always have low bit of 1, C/MBricks have low bit
- * equal to 0. Most addressing macros that target UV hub chips
- * right shift the NASID by 1 to exclude the always-zero bit.
- * NASIDs contain up to 15 bits.
- *
- * GNODE - NASID right shifted by 1 bit. Most mmrs contain gnodes instead
- * of nasids.
- *
- * PNODE - the low N bits of the GNODE. The PNODE is the most useful variant
- * of the nasid for socket usage.
- *
- *
- * NumaLink Global Physical Address Format:
- * +--------------------------------+---------------------+
- * |00..000| GNODE | NodeOffset |
- * +--------------------------------+---------------------+
- * |<-------53 - M bits --->|<--------M bits ----->
- *
- * M - number of node offset bits (35 .. 40)
- *
- *
- * Memory/UV-HUB Processor Socket Address Format:
- * +----------------+---------------+---------------------+
- * |00..000000000000| PNODE | NodeOffset |
- * +----------------+---------------+---------------------+
- * <--- N bits --->|<--------M bits ----->
- *
- * M - number of node offset bits (35 .. 40)
- * N - number of PNODE bits (0 .. 10)
- *
- * Note: M + N cannot currently exceed 44 (x86_64) or 46 (IA64).
- * The actual values are configuration dependent and are set at
- * boot time. M & N values are set by the hardware/BIOS at boot.
- */
-
-
-/*
- * Maximum number of bricks in all partitions and in all coherency domains.
- * This is the total number of bricks accessible in the numalink fabric. It
- * includes all C & M bricks. Routers are NOT included.
- *
- * This value is also the value of the maximum number of non-router NASIDs
- * in the numalink fabric.
- *
- * NOTE: a brick may contain 1 or 2 OS nodes. Don't get these confused.
- */
-#define UV_MAX_NUMALINK_BLADES 16384
-
-/*
- * Maximum number of C/Mbricks within a software SSI (hardware may support
- * more).
- */
-#define UV_MAX_SSI_BLADES 1
-
-/*
- * The largest possible NASID of a C or M brick (+ 2)
- */
-#define UV_MAX_NASID_VALUE (UV_MAX_NUMALINK_NODES * 2)
-
-/*
- * The following defines attributes of the HUB chip. These attributes are
- * frequently referenced and are kept in the per-cpu data areas of each cpu.
- * They are kept together in a struct to minimize cache misses.
- */
-struct uv_hub_info_s {
- unsigned long global_mmr_base;
- unsigned long gpa_mask;
- unsigned long gnode_upper;
- unsigned long lowmem_remap_top;
- unsigned long lowmem_remap_base;
- unsigned short pnode;
- unsigned short pnode_mask;
- unsigned short coherency_domain_number;
- unsigned short numa_blade_id;
- unsigned char blade_processor_id;
- unsigned char m_val;
- unsigned char n_val;
-};
-DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
-#define uv_hub_info this_cpu_ptr(&__uv_hub_info)
-#define uv_cpu_hub_info(cpu) (&per_cpu(__uv_hub_info, cpu))
-
-/*
- * Local & Global MMR space macros.
- * Note: macros are intended to be used ONLY by inline functions
- * in this file - not by other kernel code.
- * n - NASID (full 15-bit global nasid)
- * g - GNODE (full 15-bit global nasid, right shifted 1)
- * p - PNODE (local part of nsids, right shifted 1)
- */
-#define UV_NASID_TO_PNODE(n) (((n) >> 1) & uv_hub_info->pnode_mask)
-#define UV_PNODE_TO_NASID(p) (((p) << 1) | uv_hub_info->gnode_upper)
-
-#define UV_LOCAL_MMR_BASE 0xf4000000UL
-#define UV_GLOBAL_MMR32_BASE 0xf8000000UL
-#define UV_GLOBAL_MMR64_BASE (uv_hub_info->global_mmr_base)
-
-#define UV_GLOBAL_MMR32_PNODE_SHIFT 15
-#define UV_GLOBAL_MMR64_PNODE_SHIFT 26
-
-#define UV_GLOBAL_MMR32_PNODE_BITS(p) ((p) << (UV_GLOBAL_MMR32_PNODE_SHIFT))
-
-#define UV_GLOBAL_MMR64_PNODE_BITS(p) \
- ((unsigned long)(p) << UV_GLOBAL_MMR64_PNODE_SHIFT)
-
-/*
- * Macros for converting between kernel virtual addresses, socket local physical
- * addresses, and UV global physical addresses.
- * Note: use the standard __pa() & __va() macros for converting
- * between socket virtual and socket physical addresses.
- */
-
-/* socket phys RAM --> UV global physical address */
-static inline unsigned long uv_soc_phys_ram_to_gpa(unsigned long paddr)
-{
- if (paddr < uv_hub_info->lowmem_remap_top)
- paddr += uv_hub_info->lowmem_remap_base;
- return paddr | uv_hub_info->gnode_upper;
-}
-
-
-/* socket virtual --> UV global physical address */
-static inline unsigned long uv_gpa(void *v)
-{
- return __pa(v) | uv_hub_info->gnode_upper;
-}
-
-/* socket virtual --> UV global physical address */
-static inline void *uv_vgpa(void *v)
-{
- return (void *)uv_gpa(v);
-}
-
-/* UV global physical address --> socket virtual */
-static inline void *uv_va(unsigned long gpa)
-{
- return __va(gpa & uv_hub_info->gpa_mask);
-}
-
-/* pnode, offset --> socket virtual */
-static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset)
-{
- return __va(((unsigned long)pnode << uv_hub_info->m_val) | offset);
-}
-
-
-/*
- * Access global MMRs using the low memory MMR32 space. This region supports
- * faster MMR access but not all MMRs are accessible in this space.
- */
-static inline unsigned long *uv_global_mmr32_address(int pnode,
- unsigned long offset)
-{
- return __va(UV_GLOBAL_MMR32_BASE |
- UV_GLOBAL_MMR32_PNODE_BITS(pnode) | offset);
-}
-
-static inline void uv_write_global_mmr32(int pnode, unsigned long offset,
- unsigned long val)
-{
- *uv_global_mmr32_address(pnode, offset) = val;
-}
-
-static inline unsigned long uv_read_global_mmr32(int pnode,
- unsigned long offset)
-{
- return *uv_global_mmr32_address(pnode, offset);
-}
-
-/*
- * Access Global MMR space using the MMR space located at the top of physical
- * memory.
- */
-static inline unsigned long *uv_global_mmr64_address(int pnode,
- unsigned long offset)
-{
- return __va(UV_GLOBAL_MMR64_BASE |
- UV_GLOBAL_MMR64_PNODE_BITS(pnode) | offset);
-}
-
-static inline void uv_write_global_mmr64(int pnode, unsigned long offset,
- unsigned long val)
-{
- *uv_global_mmr64_address(pnode, offset) = val;
-}
-
-static inline unsigned long uv_read_global_mmr64(int pnode,
- unsigned long offset)
-{
- return *uv_global_mmr64_address(pnode, offset);
-}
-
-/*
- * Access hub local MMRs. Faster than using global space but only local MMRs
- * are accessible.
- */
-static inline unsigned long *uv_local_mmr_address(unsigned long offset)
-{
- return __va(UV_LOCAL_MMR_BASE | offset);
-}
-
-static inline unsigned long uv_read_local_mmr(unsigned long offset)
-{
- return *uv_local_mmr_address(offset);
-}
-
-static inline void uv_write_local_mmr(unsigned long offset, unsigned long val)
-{
- *uv_local_mmr_address(offset) = val;
-}
-
-/*
- * Structures and definitions for converting between cpu, node, pnode, and blade
- * numbers.
- */
-
-/* Blade-local cpu number of current cpu. Numbered 0 .. <# cpus on the blade> */
-static inline int uv_blade_processor_id(void)
-{
- return smp_processor_id();
-}
-
-/* Blade number of current cpu. Numnbered 0 .. <#blades -1> */
-static inline int uv_numa_blade_id(void)
-{
- return 0;
-}
-
-/* Convert a cpu number to the UV blade number */
-static inline int uv_cpu_to_blade_id(int cpu)
-{
- return 0;
-}
-
-/* Convert linux node number to the UV blade number */
-static inline int uv_node_to_blade_id(int nid)
-{
- return 0;
-}
-
-/* Convert a blade id to the PNODE of the blade */
-static inline int uv_blade_to_pnode(int bid)
-{
- return 0;
-}
-
-/* Determine the number of possible cpus on a blade */
-static inline int uv_blade_nr_possible_cpus(int bid)
-{
- return num_possible_cpus();
-}
-
-/* Determine the number of online cpus on a blade */
-static inline int uv_blade_nr_online_cpus(int bid)
-{
- return num_online_cpus();
-}
-
-/* Convert a cpu id to the PNODE of the blade containing the cpu */
-static inline int uv_cpu_to_pnode(int cpu)
-{
- return 0;
-}
-
-/* Convert a linux node number to the PNODE of the blade */
-static inline int uv_node_to_pnode(int nid)
-{
- return 0;
-}
-
-/* Maximum possible number of blades */
-static inline int uv_num_possible_blades(void)
-{
- return 1;
-}
-
-static inline void uv_hub_send_ipi(int pnode, int apicid, int vector)
-{
- /* not currently needed on ia64 */
-}
-
-
-#endif /* __ASM_IA64_UV_HUB__ */
-
diff --git a/arch/ia64/include/asm/uv/uv_mmrs.h b/arch/ia64/include/asm/uv/uv_mmrs.h
deleted file mode 100644
index fe0b8f05e1a8..000000000000
--- a/arch/ia64/include/asm/uv/uv_mmrs.h
+++ /dev/null
@@ -1,825 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * SGI UV MMR definitions
- *
- * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved.
- */
-
-#ifndef _ASM_IA64_UV_UV_MMRS_H
-#define _ASM_IA64_UV_UV_MMRS_H
-
-#define UV_MMR_ENABLE (1UL << 63)
-
-/* ========================================================================= */
-/* UVH_BAU_DATA_CONFIG */
-/* ========================================================================= */
-#define UVH_BAU_DATA_CONFIG 0x61680UL
-#define UVH_BAU_DATA_CONFIG_32 0x0438
-
-#define UVH_BAU_DATA_CONFIG_VECTOR_SHFT 0
-#define UVH_BAU_DATA_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_BAU_DATA_CONFIG_DM_SHFT 8
-#define UVH_BAU_DATA_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_BAU_DATA_CONFIG_DESTMODE_SHFT 11
-#define UVH_BAU_DATA_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_BAU_DATA_CONFIG_STATUS_SHFT 12
-#define UVH_BAU_DATA_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_BAU_DATA_CONFIG_P_SHFT 13
-#define UVH_BAU_DATA_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_BAU_DATA_CONFIG_T_SHFT 15
-#define UVH_BAU_DATA_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_BAU_DATA_CONFIG_M_SHFT 16
-#define UVH_BAU_DATA_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_BAU_DATA_CONFIG_APIC_ID_SHFT 32
-#define UVH_BAU_DATA_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
-
-union uvh_bau_data_config_u {
- unsigned long v;
- struct uvh_bau_data_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_EVENT_OCCURRED0 */
-/* ========================================================================= */
-#define UVH_EVENT_OCCURRED0 0x70000UL
-#define UVH_EVENT_OCCURRED0_32 0x005e8
-
-#define UVH_EVENT_OCCURRED0_LB_HCERR_SHFT 0
-#define UVH_EVENT_OCCURRED0_LB_HCERR_MASK 0x0000000000000001UL
-#define UVH_EVENT_OCCURRED0_GR0_HCERR_SHFT 1
-#define UVH_EVENT_OCCURRED0_GR0_HCERR_MASK 0x0000000000000002UL
-#define UVH_EVENT_OCCURRED0_GR1_HCERR_SHFT 2
-#define UVH_EVENT_OCCURRED0_GR1_HCERR_MASK 0x0000000000000004UL
-#define UVH_EVENT_OCCURRED0_LH_HCERR_SHFT 3
-#define UVH_EVENT_OCCURRED0_LH_HCERR_MASK 0x0000000000000008UL
-#define UVH_EVENT_OCCURRED0_RH_HCERR_SHFT 4
-#define UVH_EVENT_OCCURRED0_RH_HCERR_MASK 0x0000000000000010UL
-#define UVH_EVENT_OCCURRED0_XN_HCERR_SHFT 5
-#define UVH_EVENT_OCCURRED0_XN_HCERR_MASK 0x0000000000000020UL
-#define UVH_EVENT_OCCURRED0_SI_HCERR_SHFT 6
-#define UVH_EVENT_OCCURRED0_SI_HCERR_MASK 0x0000000000000040UL
-#define UVH_EVENT_OCCURRED0_LB_AOERR0_SHFT 7
-#define UVH_EVENT_OCCURRED0_LB_AOERR0_MASK 0x0000000000000080UL
-#define UVH_EVENT_OCCURRED0_GR0_AOERR0_SHFT 8
-#define UVH_EVENT_OCCURRED0_GR0_AOERR0_MASK 0x0000000000000100UL
-#define UVH_EVENT_OCCURRED0_GR1_AOERR0_SHFT 9
-#define UVH_EVENT_OCCURRED0_GR1_AOERR0_MASK 0x0000000000000200UL
-#define UVH_EVENT_OCCURRED0_LH_AOERR0_SHFT 10
-#define UVH_EVENT_OCCURRED0_LH_AOERR0_MASK 0x0000000000000400UL
-#define UVH_EVENT_OCCURRED0_RH_AOERR0_SHFT 11
-#define UVH_EVENT_OCCURRED0_RH_AOERR0_MASK 0x0000000000000800UL
-#define UVH_EVENT_OCCURRED0_XN_AOERR0_SHFT 12
-#define UVH_EVENT_OCCURRED0_XN_AOERR0_MASK 0x0000000000001000UL
-#define UVH_EVENT_OCCURRED0_SI_AOERR0_SHFT 13
-#define UVH_EVENT_OCCURRED0_SI_AOERR0_MASK 0x0000000000002000UL
-#define UVH_EVENT_OCCURRED0_LB_AOERR1_SHFT 14
-#define UVH_EVENT_OCCURRED0_LB_AOERR1_MASK 0x0000000000004000UL
-#define UVH_EVENT_OCCURRED0_GR0_AOERR1_SHFT 15
-#define UVH_EVENT_OCCURRED0_GR0_AOERR1_MASK 0x0000000000008000UL
-#define UVH_EVENT_OCCURRED0_GR1_AOERR1_SHFT 16
-#define UVH_EVENT_OCCURRED0_GR1_AOERR1_MASK 0x0000000000010000UL
-#define UVH_EVENT_OCCURRED0_LH_AOERR1_SHFT 17
-#define UVH_EVENT_OCCURRED0_LH_AOERR1_MASK 0x0000000000020000UL
-#define UVH_EVENT_OCCURRED0_RH_AOERR1_SHFT 18
-#define UVH_EVENT_OCCURRED0_RH_AOERR1_MASK 0x0000000000040000UL
-#define UVH_EVENT_OCCURRED0_XN_AOERR1_SHFT 19
-#define UVH_EVENT_OCCURRED0_XN_AOERR1_MASK 0x0000000000080000UL
-#define UVH_EVENT_OCCURRED0_SI_AOERR1_SHFT 20
-#define UVH_EVENT_OCCURRED0_SI_AOERR1_MASK 0x0000000000100000UL
-#define UVH_EVENT_OCCURRED0_RH_VPI_INT_SHFT 21
-#define UVH_EVENT_OCCURRED0_RH_VPI_INT_MASK 0x0000000000200000UL
-#define UVH_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT 22
-#define UVH_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK 0x0000000000400000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT 23
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK 0x0000000000800000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT 24
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK 0x0000000001000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT 25
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK 0x0000000002000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT 26
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK 0x0000000004000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT 27
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK 0x0000000008000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT 28
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK 0x0000000010000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT 29
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK 0x0000000020000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT 30
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK 0x0000000040000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT 31
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK 0x0000000080000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT 32
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK 0x0000000100000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT 33
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK 0x0000000200000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT 34
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK 0x0000000400000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT 35
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK 0x0000000800000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT 36
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK 0x0000001000000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT 37
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK 0x0000002000000000UL
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT 38
-#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK 0x0000004000000000UL
-#define UVH_EVENT_OCCURRED0_L1_NMI_INT_SHFT 39
-#define UVH_EVENT_OCCURRED0_L1_NMI_INT_MASK 0x0000008000000000UL
-#define UVH_EVENT_OCCURRED0_STOP_CLOCK_SHFT 40
-#define UVH_EVENT_OCCURRED0_STOP_CLOCK_MASK 0x0000010000000000UL
-#define UVH_EVENT_OCCURRED0_ASIC_TO_L1_SHFT 41
-#define UVH_EVENT_OCCURRED0_ASIC_TO_L1_MASK 0x0000020000000000UL
-#define UVH_EVENT_OCCURRED0_L1_TO_ASIC_SHFT 42
-#define UVH_EVENT_OCCURRED0_L1_TO_ASIC_MASK 0x0000040000000000UL
-#define UVH_EVENT_OCCURRED0_LTC_INT_SHFT 43
-#define UVH_EVENT_OCCURRED0_LTC_INT_MASK 0x0000080000000000UL
-#define UVH_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT 44
-#define UVH_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK 0x0000100000000000UL
-#define UVH_EVENT_OCCURRED0_IPI_INT_SHFT 45
-#define UVH_EVENT_OCCURRED0_IPI_INT_MASK 0x0000200000000000UL
-#define UVH_EVENT_OCCURRED0_EXTIO_INT0_SHFT 46
-#define UVH_EVENT_OCCURRED0_EXTIO_INT0_MASK 0x0000400000000000UL
-#define UVH_EVENT_OCCURRED0_EXTIO_INT1_SHFT 47
-#define UVH_EVENT_OCCURRED0_EXTIO_INT1_MASK 0x0000800000000000UL
-#define UVH_EVENT_OCCURRED0_EXTIO_INT2_SHFT 48
-#define UVH_EVENT_OCCURRED0_EXTIO_INT2_MASK 0x0001000000000000UL
-#define UVH_EVENT_OCCURRED0_EXTIO_INT3_SHFT 49
-#define UVH_EVENT_OCCURRED0_EXTIO_INT3_MASK 0x0002000000000000UL
-#define UVH_EVENT_OCCURRED0_PROFILE_INT_SHFT 50
-#define UVH_EVENT_OCCURRED0_PROFILE_INT_MASK 0x0004000000000000UL
-#define UVH_EVENT_OCCURRED0_RTC0_SHFT 51
-#define UVH_EVENT_OCCURRED0_RTC0_MASK 0x0008000000000000UL
-#define UVH_EVENT_OCCURRED0_RTC1_SHFT 52
-#define UVH_EVENT_OCCURRED0_RTC1_MASK 0x0010000000000000UL
-#define UVH_EVENT_OCCURRED0_RTC2_SHFT 53
-#define UVH_EVENT_OCCURRED0_RTC2_MASK 0x0020000000000000UL
-#define UVH_EVENT_OCCURRED0_RTC3_SHFT 54
-#define UVH_EVENT_OCCURRED0_RTC3_MASK 0x0040000000000000UL
-#define UVH_EVENT_OCCURRED0_BAU_DATA_SHFT 55
-#define UVH_EVENT_OCCURRED0_BAU_DATA_MASK 0x0080000000000000UL
-#define UVH_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_SHFT 56
-#define UVH_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_MASK 0x0100000000000000UL
-union uvh_event_occurred0_u {
- unsigned long v;
- struct uvh_event_occurred0_s {
- unsigned long lb_hcerr : 1; /* RW, W1C */
- unsigned long gr0_hcerr : 1; /* RW, W1C */
- unsigned long gr1_hcerr : 1; /* RW, W1C */
- unsigned long lh_hcerr : 1; /* RW, W1C */
- unsigned long rh_hcerr : 1; /* RW, W1C */
- unsigned long xn_hcerr : 1; /* RW, W1C */
- unsigned long si_hcerr : 1; /* RW, W1C */
- unsigned long lb_aoerr0 : 1; /* RW, W1C */
- unsigned long gr0_aoerr0 : 1; /* RW, W1C */
- unsigned long gr1_aoerr0 : 1; /* RW, W1C */
- unsigned long lh_aoerr0 : 1; /* RW, W1C */
- unsigned long rh_aoerr0 : 1; /* RW, W1C */
- unsigned long xn_aoerr0 : 1; /* RW, W1C */
- unsigned long si_aoerr0 : 1; /* RW, W1C */
- unsigned long lb_aoerr1 : 1; /* RW, W1C */
- unsigned long gr0_aoerr1 : 1; /* RW, W1C */
- unsigned long gr1_aoerr1 : 1; /* RW, W1C */
- unsigned long lh_aoerr1 : 1; /* RW, W1C */
- unsigned long rh_aoerr1 : 1; /* RW, W1C */
- unsigned long xn_aoerr1 : 1; /* RW, W1C */
- unsigned long si_aoerr1 : 1; /* RW, W1C */
- unsigned long rh_vpi_int : 1; /* RW, W1C */
- unsigned long system_shutdown_int : 1; /* RW, W1C */
- unsigned long lb_irq_int_0 : 1; /* RW, W1C */
- unsigned long lb_irq_int_1 : 1; /* RW, W1C */
- unsigned long lb_irq_int_2 : 1; /* RW, W1C */
- unsigned long lb_irq_int_3 : 1; /* RW, W1C */
- unsigned long lb_irq_int_4 : 1; /* RW, W1C */
- unsigned long lb_irq_int_5 : 1; /* RW, W1C */
- unsigned long lb_irq_int_6 : 1; /* RW, W1C */
- unsigned long lb_irq_int_7 : 1; /* RW, W1C */
- unsigned long lb_irq_int_8 : 1; /* RW, W1C */
- unsigned long lb_irq_int_9 : 1; /* RW, W1C */
- unsigned long lb_irq_int_10 : 1; /* RW, W1C */
- unsigned long lb_irq_int_11 : 1; /* RW, W1C */
- unsigned long lb_irq_int_12 : 1; /* RW, W1C */
- unsigned long lb_irq_int_13 : 1; /* RW, W1C */
- unsigned long lb_irq_int_14 : 1; /* RW, W1C */
- unsigned long lb_irq_int_15 : 1; /* RW, W1C */
- unsigned long l1_nmi_int : 1; /* RW, W1C */
- unsigned long stop_clock : 1; /* RW, W1C */
- unsigned long asic_to_l1 : 1; /* RW, W1C */
- unsigned long l1_to_asic : 1; /* RW, W1C */
- unsigned long ltc_int : 1; /* RW, W1C */
- unsigned long la_seq_trigger : 1; /* RW, W1C */
- unsigned long ipi_int : 1; /* RW, W1C */
- unsigned long extio_int0 : 1; /* RW, W1C */
- unsigned long extio_int1 : 1; /* RW, W1C */
- unsigned long extio_int2 : 1; /* RW, W1C */
- unsigned long extio_int3 : 1; /* RW, W1C */
- unsigned long profile_int : 1; /* RW, W1C */
- unsigned long rtc0 : 1; /* RW, W1C */
- unsigned long rtc1 : 1; /* RW, W1C */
- unsigned long rtc2 : 1; /* RW, W1C */
- unsigned long rtc3 : 1; /* RW, W1C */
- unsigned long bau_data : 1; /* RW, W1C */
- unsigned long power_management_req : 1; /* RW, W1C */
- unsigned long rsvd_57_63 : 7; /* */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_EVENT_OCCURRED0_ALIAS */
-/* ========================================================================= */
-#define UVH_EVENT_OCCURRED0_ALIAS 0x0000000000070008UL
-#define UVH_EVENT_OCCURRED0_ALIAS_32 0x005f0
-
-/* ========================================================================= */
-/* UVH_GR0_TLB_INT0_CONFIG */
-/* ========================================================================= */
-#define UVH_GR0_TLB_INT0_CONFIG 0x61b00UL
-
-#define UVH_GR0_TLB_INT0_CONFIG_VECTOR_SHFT 0
-#define UVH_GR0_TLB_INT0_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_GR0_TLB_INT0_CONFIG_DM_SHFT 8
-#define UVH_GR0_TLB_INT0_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_GR0_TLB_INT0_CONFIG_DESTMODE_SHFT 11
-#define UVH_GR0_TLB_INT0_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_GR0_TLB_INT0_CONFIG_STATUS_SHFT 12
-#define UVH_GR0_TLB_INT0_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_GR0_TLB_INT0_CONFIG_P_SHFT 13
-#define UVH_GR0_TLB_INT0_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_GR0_TLB_INT0_CONFIG_T_SHFT 15
-#define UVH_GR0_TLB_INT0_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_GR0_TLB_INT0_CONFIG_M_SHFT 16
-#define UVH_GR0_TLB_INT0_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_GR0_TLB_INT0_CONFIG_APIC_ID_SHFT 32
-#define UVH_GR0_TLB_INT0_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
-
-union uvh_gr0_tlb_int0_config_u {
- unsigned long v;
- struct uvh_gr0_tlb_int0_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_GR0_TLB_INT1_CONFIG */
-/* ========================================================================= */
-#define UVH_GR0_TLB_INT1_CONFIG 0x61b40UL
-
-#define UVH_GR0_TLB_INT1_CONFIG_VECTOR_SHFT 0
-#define UVH_GR0_TLB_INT1_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_GR0_TLB_INT1_CONFIG_DM_SHFT 8
-#define UVH_GR0_TLB_INT1_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_GR0_TLB_INT1_CONFIG_DESTMODE_SHFT 11
-#define UVH_GR0_TLB_INT1_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_GR0_TLB_INT1_CONFIG_STATUS_SHFT 12
-#define UVH_GR0_TLB_INT1_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_GR0_TLB_INT1_CONFIG_P_SHFT 13
-#define UVH_GR0_TLB_INT1_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_GR0_TLB_INT1_CONFIG_T_SHFT 15
-#define UVH_GR0_TLB_INT1_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_GR0_TLB_INT1_CONFIG_M_SHFT 16
-#define UVH_GR0_TLB_INT1_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_GR0_TLB_INT1_CONFIG_APIC_ID_SHFT 32
-#define UVH_GR0_TLB_INT1_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
-
-union uvh_gr0_tlb_int1_config_u {
- unsigned long v;
- struct uvh_gr0_tlb_int1_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_GR1_TLB_INT0_CONFIG */
-/* ========================================================================= */
-#define UVH_GR1_TLB_INT0_CONFIG 0x61f00UL
-
-#define UVH_GR1_TLB_INT0_CONFIG_VECTOR_SHFT 0
-#define UVH_GR1_TLB_INT0_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_GR1_TLB_INT0_CONFIG_DM_SHFT 8
-#define UVH_GR1_TLB_INT0_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_GR1_TLB_INT0_CONFIG_DESTMODE_SHFT 11
-#define UVH_GR1_TLB_INT0_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_GR1_TLB_INT0_CONFIG_STATUS_SHFT 12
-#define UVH_GR1_TLB_INT0_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_GR1_TLB_INT0_CONFIG_P_SHFT 13
-#define UVH_GR1_TLB_INT0_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_GR1_TLB_INT0_CONFIG_T_SHFT 15
-#define UVH_GR1_TLB_INT0_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_GR1_TLB_INT0_CONFIG_M_SHFT 16
-#define UVH_GR1_TLB_INT0_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_GR1_TLB_INT0_CONFIG_APIC_ID_SHFT 32
-#define UVH_GR1_TLB_INT0_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
-
-union uvh_gr1_tlb_int0_config_u {
- unsigned long v;
- struct uvh_gr1_tlb_int0_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_GR1_TLB_INT1_CONFIG */
-/* ========================================================================= */
-#define UVH_GR1_TLB_INT1_CONFIG 0x61f40UL
-
-#define UVH_GR1_TLB_INT1_CONFIG_VECTOR_SHFT 0
-#define UVH_GR1_TLB_INT1_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_GR1_TLB_INT1_CONFIG_DM_SHFT 8
-#define UVH_GR1_TLB_INT1_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_GR1_TLB_INT1_CONFIG_DESTMODE_SHFT 11
-#define UVH_GR1_TLB_INT1_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_GR1_TLB_INT1_CONFIG_STATUS_SHFT 12
-#define UVH_GR1_TLB_INT1_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_GR1_TLB_INT1_CONFIG_P_SHFT 13
-#define UVH_GR1_TLB_INT1_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_GR1_TLB_INT1_CONFIG_T_SHFT 15
-#define UVH_GR1_TLB_INT1_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_GR1_TLB_INT1_CONFIG_M_SHFT 16
-#define UVH_GR1_TLB_INT1_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_GR1_TLB_INT1_CONFIG_APIC_ID_SHFT 32
-#define UVH_GR1_TLB_INT1_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
-
-union uvh_gr1_tlb_int1_config_u {
- unsigned long v;
- struct uvh_gr1_tlb_int1_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_INT_CMPB */
-/* ========================================================================= */
-#define UVH_INT_CMPB 0x22080UL
-
-#define UVH_INT_CMPB_REAL_TIME_CMPB_SHFT 0
-#define UVH_INT_CMPB_REAL_TIME_CMPB_MASK 0x00ffffffffffffffUL
-
-union uvh_int_cmpb_u {
- unsigned long v;
- struct uvh_int_cmpb_s {
- unsigned long real_time_cmpb : 56; /* RW */
- unsigned long rsvd_56_63 : 8; /* */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_INT_CMPC */
-/* ========================================================================= */
-#define UVH_INT_CMPC 0x22100UL
-
-#define UVH_INT_CMPC_REAL_TIME_CMPC_SHFT 0
-#define UVH_INT_CMPC_REAL_TIME_CMPC_MASK 0x00ffffffffffffffUL
-
-union uvh_int_cmpc_u {
- unsigned long v;
- struct uvh_int_cmpc_s {
- unsigned long real_time_cmpc : 56; /* RW */
- unsigned long rsvd_56_63 : 8; /* */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_INT_CMPD */
-/* ========================================================================= */
-#define UVH_INT_CMPD 0x22180UL
-
-#define UVH_INT_CMPD_REAL_TIME_CMPD_SHFT 0
-#define UVH_INT_CMPD_REAL_TIME_CMPD_MASK 0x00ffffffffffffffUL
-
-union uvh_int_cmpd_u {
- unsigned long v;
- struct uvh_int_cmpd_s {
- unsigned long real_time_cmpd : 56; /* RW */
- unsigned long rsvd_56_63 : 8; /* */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_NODE_ID */
-/* ========================================================================= */
-#define UVH_NODE_ID 0x0UL
-
-#define UVH_NODE_ID_FORCE1_SHFT 0
-#define UVH_NODE_ID_FORCE1_MASK 0x0000000000000001UL
-#define UVH_NODE_ID_MANUFACTURER_SHFT 1
-#define UVH_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL
-#define UVH_NODE_ID_PART_NUMBER_SHFT 12
-#define UVH_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL
-#define UVH_NODE_ID_REVISION_SHFT 28
-#define UVH_NODE_ID_REVISION_MASK 0x00000000f0000000UL
-#define UVH_NODE_ID_NODE_ID_SHFT 32
-#define UVH_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL
-#define UVH_NODE_ID_NODES_PER_BIT_SHFT 48
-#define UVH_NODE_ID_NODES_PER_BIT_MASK 0x007f000000000000UL
-#define UVH_NODE_ID_NI_PORT_SHFT 56
-#define UVH_NODE_ID_NI_PORT_MASK 0x0f00000000000000UL
-
-union uvh_node_id_u {
- unsigned long v;
- struct uvh_node_id_s {
- unsigned long force1 : 1; /* RO */
- unsigned long manufacturer : 11; /* RO */
- unsigned long part_number : 16; /* RO */
- unsigned long revision : 4; /* RO */
- unsigned long node_id : 15; /* RW */
- unsigned long rsvd_47 : 1; /* */
- unsigned long nodes_per_bit : 7; /* RW */
- unsigned long rsvd_55 : 1; /* */
- unsigned long ni_port : 4; /* RO */
- unsigned long rsvd_60_63 : 4; /* */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR */
-/* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR 0x16000d0UL
-
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT 24
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_MASK 0x00003fffff000000UL
-
-union uvh_rh_gam_alias210_redirect_config_0_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_alias210_redirect_config_0_mmr_s {
- unsigned long rsvd_0_23 : 24; /* */
- unsigned long dest_base : 22; /* RW */
- unsigned long rsvd_46_63: 18; /* */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR */
-/* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR 0x16000e0UL
-
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR_DEST_BASE_SHFT 24
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR_DEST_BASE_MASK 0x00003fffff000000UL
-
-union uvh_rh_gam_alias210_redirect_config_1_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_alias210_redirect_config_1_mmr_s {
- unsigned long rsvd_0_23 : 24; /* */
- unsigned long dest_base : 22; /* RW */
- unsigned long rsvd_46_63: 18; /* */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR */
-/* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR 0x16000f0UL
-
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR_DEST_BASE_SHFT 24
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR_DEST_BASE_MASK 0x00003fffff000000UL
-
-union uvh_rh_gam_alias210_redirect_config_2_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_alias210_redirect_config_2_mmr_s {
- unsigned long rsvd_0_23 : 24; /* */
- unsigned long dest_base : 22; /* RW */
- unsigned long rsvd_46_63: 18; /* */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR */
-/* ========================================================================= */
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL
-
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_SHFT 48
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_MASK 0x0001000000000000UL
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT 52
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK 0x00f0000000000000UL
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
-
-union uvh_rh_gam_gru_overlay_config_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_gru_overlay_config_mmr_s {
- unsigned long rsvd_0_27: 28; /* */
- unsigned long base : 18; /* RW */
- unsigned long rsvd_46_47: 2; /* */
- unsigned long gr4 : 1; /* RW */
- unsigned long rsvd_49_51: 3; /* */
- unsigned long n_gru : 4; /* RW */
- unsigned long rsvd_56_62: 7; /* */
- unsigned long enable : 1; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR */
-/* ========================================================================= */
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR 0x1600028UL
-
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_DUAL_HUB_SHFT 46
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_DUAL_HUB_MASK 0x0000400000000000UL
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
-
-union uvh_rh_gam_mmr_overlay_config_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_mmr_overlay_config_mmr_s {
- unsigned long rsvd_0_25: 26; /* */
- unsigned long base : 20; /* RW */
- unsigned long dual_hub : 1; /* RW */
- unsigned long rsvd_47_62: 16; /* */
- unsigned long enable : 1; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_RTC */
-/* ========================================================================= */
-#define UVH_RTC 0x340000UL
-
-#define UVH_RTC_REAL_TIME_CLOCK_SHFT 0
-#define UVH_RTC_REAL_TIME_CLOCK_MASK 0x00ffffffffffffffUL
-
-union uvh_rtc_u {
- unsigned long v;
- struct uvh_rtc_s {
- unsigned long real_time_clock : 56; /* RW */
- unsigned long rsvd_56_63 : 8; /* */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_RTC1_INT_CONFIG */
-/* ========================================================================= */
-#define UVH_RTC1_INT_CONFIG 0x615c0UL
-
-#define UVH_RTC1_INT_CONFIG_VECTOR_SHFT 0
-#define UVH_RTC1_INT_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_RTC1_INT_CONFIG_DM_SHFT 8
-#define UVH_RTC1_INT_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_RTC1_INT_CONFIG_DESTMODE_SHFT 11
-#define UVH_RTC1_INT_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_RTC1_INT_CONFIG_STATUS_SHFT 12
-#define UVH_RTC1_INT_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_RTC1_INT_CONFIG_P_SHFT 13
-#define UVH_RTC1_INT_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_RTC1_INT_CONFIG_T_SHFT 15
-#define UVH_RTC1_INT_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_RTC1_INT_CONFIG_M_SHFT 16
-#define UVH_RTC1_INT_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_RTC1_INT_CONFIG_APIC_ID_SHFT 32
-#define UVH_RTC1_INT_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
-
-union uvh_rtc1_int_config_u {
- unsigned long v;
- struct uvh_rtc1_int_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_RTC2_INT_CONFIG */
-/* ========================================================================= */
-#define UVH_RTC2_INT_CONFIG 0x61600UL
-
-#define UVH_RTC2_INT_CONFIG_VECTOR_SHFT 0
-#define UVH_RTC2_INT_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_RTC2_INT_CONFIG_DM_SHFT 8
-#define UVH_RTC2_INT_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_RTC2_INT_CONFIG_DESTMODE_SHFT 11
-#define UVH_RTC2_INT_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_RTC2_INT_CONFIG_STATUS_SHFT 12
-#define UVH_RTC2_INT_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_RTC2_INT_CONFIG_P_SHFT 13
-#define UVH_RTC2_INT_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_RTC2_INT_CONFIG_T_SHFT 15
-#define UVH_RTC2_INT_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_RTC2_INT_CONFIG_M_SHFT 16
-#define UVH_RTC2_INT_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_RTC2_INT_CONFIG_APIC_ID_SHFT 32
-#define UVH_RTC2_INT_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
-
-union uvh_rtc2_int_config_u {
- unsigned long v;
- struct uvh_rtc2_int_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_RTC3_INT_CONFIG */
-/* ========================================================================= */
-#define UVH_RTC3_INT_CONFIG 0x61640UL
-
-#define UVH_RTC3_INT_CONFIG_VECTOR_SHFT 0
-#define UVH_RTC3_INT_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_RTC3_INT_CONFIG_DM_SHFT 8
-#define UVH_RTC3_INT_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_RTC3_INT_CONFIG_DESTMODE_SHFT 11
-#define UVH_RTC3_INT_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_RTC3_INT_CONFIG_STATUS_SHFT 12
-#define UVH_RTC3_INT_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_RTC3_INT_CONFIG_P_SHFT 13
-#define UVH_RTC3_INT_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_RTC3_INT_CONFIG_T_SHFT 15
-#define UVH_RTC3_INT_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_RTC3_INT_CONFIG_M_SHFT 16
-#define UVH_RTC3_INT_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_RTC3_INT_CONFIG_APIC_ID_SHFT 32
-#define UVH_RTC3_INT_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
-
-union uvh_rtc3_int_config_u {
- unsigned long v;
- struct uvh_rtc3_int_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_RTC_INC_RATIO */
-/* ========================================================================= */
-#define UVH_RTC_INC_RATIO 0x350000UL
-
-#define UVH_RTC_INC_RATIO_FRACTION_SHFT 0
-#define UVH_RTC_INC_RATIO_FRACTION_MASK 0x00000000000fffffUL
-#define UVH_RTC_INC_RATIO_RATIO_SHFT 20
-#define UVH_RTC_INC_RATIO_RATIO_MASK 0x0000000000700000UL
-
-union uvh_rtc_inc_ratio_u {
- unsigned long v;
- struct uvh_rtc_inc_ratio_s {
- unsigned long fraction : 20; /* RW */
- unsigned long ratio : 3; /* RW */
- unsigned long rsvd_23_63: 41; /* */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_SI_ADDR_MAP_CONFIG */
-/* ========================================================================= */
-#define UVH_SI_ADDR_MAP_CONFIG 0xc80000UL
-
-#define UVH_SI_ADDR_MAP_CONFIG_M_SKT_SHFT 0
-#define UVH_SI_ADDR_MAP_CONFIG_M_SKT_MASK 0x000000000000003fUL
-#define UVH_SI_ADDR_MAP_CONFIG_N_SKT_SHFT 8
-#define UVH_SI_ADDR_MAP_CONFIG_N_SKT_MASK 0x0000000000000f00UL
-
-union uvh_si_addr_map_config_u {
- unsigned long v;
- struct uvh_si_addr_map_config_s {
- unsigned long m_skt : 6; /* RW */
- unsigned long rsvd_6_7: 2; /* */
- unsigned long n_skt : 4; /* RW */
- unsigned long rsvd_12_63: 52; /* */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_SI_ALIAS0_OVERLAY_CONFIG */
-/* ========================================================================= */
-#define UVH_SI_ALIAS0_OVERLAY_CONFIG 0xc80008UL
-
-#define UVH_SI_ALIAS0_OVERLAY_CONFIG_BASE_SHFT 24
-#define UVH_SI_ALIAS0_OVERLAY_CONFIG_BASE_MASK 0x00000000ff000000UL
-#define UVH_SI_ALIAS0_OVERLAY_CONFIG_M_ALIAS_SHFT 48
-#define UVH_SI_ALIAS0_OVERLAY_CONFIG_M_ALIAS_MASK 0x001f000000000000UL
-#define UVH_SI_ALIAS0_OVERLAY_CONFIG_ENABLE_SHFT 63
-#define UVH_SI_ALIAS0_OVERLAY_CONFIG_ENABLE_MASK 0x8000000000000000UL
-
-union uvh_si_alias0_overlay_config_u {
- unsigned long v;
- struct uvh_si_alias0_overlay_config_s {
- unsigned long rsvd_0_23: 24; /* */
- unsigned long base : 8; /* RW */
- unsigned long rsvd_32_47: 16; /* */
- unsigned long m_alias : 5; /* RW */
- unsigned long rsvd_53_62: 10; /* */
- unsigned long enable : 1; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_SI_ALIAS1_OVERLAY_CONFIG */
-/* ========================================================================= */
-#define UVH_SI_ALIAS1_OVERLAY_CONFIG 0xc80010UL
-
-#define UVH_SI_ALIAS1_OVERLAY_CONFIG_BASE_SHFT 24
-#define UVH_SI_ALIAS1_OVERLAY_CONFIG_BASE_MASK 0x00000000ff000000UL
-#define UVH_SI_ALIAS1_OVERLAY_CONFIG_M_ALIAS_SHFT 48
-#define UVH_SI_ALIAS1_OVERLAY_CONFIG_M_ALIAS_MASK 0x001f000000000000UL
-#define UVH_SI_ALIAS1_OVERLAY_CONFIG_ENABLE_SHFT 63
-#define UVH_SI_ALIAS1_OVERLAY_CONFIG_ENABLE_MASK 0x8000000000000000UL
-
-union uvh_si_alias1_overlay_config_u {
- unsigned long v;
- struct uvh_si_alias1_overlay_config_s {
- unsigned long rsvd_0_23: 24; /* */
- unsigned long base : 8; /* RW */
- unsigned long rsvd_32_47: 16; /* */
- unsigned long m_alias : 5; /* RW */
- unsigned long rsvd_53_62: 10; /* */
- unsigned long enable : 1; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_SI_ALIAS2_OVERLAY_CONFIG */
-/* ========================================================================= */
-#define UVH_SI_ALIAS2_OVERLAY_CONFIG 0xc80018UL
-
-#define UVH_SI_ALIAS2_OVERLAY_CONFIG_BASE_SHFT 24
-#define UVH_SI_ALIAS2_OVERLAY_CONFIG_BASE_MASK 0x00000000ff000000UL
-#define UVH_SI_ALIAS2_OVERLAY_CONFIG_M_ALIAS_SHFT 48
-#define UVH_SI_ALIAS2_OVERLAY_CONFIG_M_ALIAS_MASK 0x001f000000000000UL
-#define UVH_SI_ALIAS2_OVERLAY_CONFIG_ENABLE_SHFT 63
-#define UVH_SI_ALIAS2_OVERLAY_CONFIG_ENABLE_MASK 0x8000000000000000UL
-
-union uvh_si_alias2_overlay_config_u {
- unsigned long v;
- struct uvh_si_alias2_overlay_config_s {
- unsigned long rsvd_0_23: 24; /* */
- unsigned long base : 8; /* RW */
- unsigned long rsvd_32_47: 16; /* */
- unsigned long m_alias : 5; /* RW */
- unsigned long rsvd_53_62: 10; /* */
- unsigned long enable : 1; /* RW */
- } s;
-};
-
-
-#endif /* _ASM_IA64_UV_UV_MMRS_H */
diff --git a/arch/ia64/include/asm/vermagic.h b/arch/ia64/include/asm/vermagic.h
deleted file mode 100644
index 29c7424f4c25..000000000000
--- a/arch/ia64/include/asm/vermagic.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#ifndef _ASM_VERMAGIC_H
-#define _ASM_VERMAGIC_H
-
-#include <linux/stringify.h>
-
-#define MODULE_ARCH_VERMAGIC "ia64" \
- "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__)
-
-#endif /* _ASM_VERMAGIC_H */
diff --git a/arch/ia64/include/asm/vga.h b/arch/ia64/include/asm/vga.h
deleted file mode 100644
index 64ce0b971a0a..000000000000
--- a/arch/ia64/include/asm/vga.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Access to VGA videoram
- *
- * (c) 1998 Martin Mares <mj@ucw.cz>
- * (c) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * (c) 1999 Don Dugger <don.dugger@intel.com>
- */
-
-#ifndef __ASM_IA64_VGA_H_
-#define __ASM_IA64_VGA_H_
-
-/*
- * On the PC, we can just recalculate addresses and then access the
- * videoram directly without any black magic.
- */
-
-extern unsigned long vga_console_iobase;
-extern unsigned long vga_console_membase;
-
-#define VGA_MAP_MEM(x,s) ((unsigned long) ioremap(vga_console_membase + (x), s))
-
-#define vga_readb(x) (*(x))
-#define vga_writeb(x,y) (*(y) = (x))
-
-#endif /* __ASM_IA64_VGA_H_ */
diff --git a/arch/ia64/include/asm/vmalloc.h b/arch/ia64/include/asm/vmalloc.h
deleted file mode 100644
index a2b51141ad28..000000000000
--- a/arch/ia64/include/asm/vmalloc.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef _ASM_IA64_VMALLOC_H
-#define _ASM_IA64_VMALLOC_H
-
-#endif /* _ASM_IA64_VMALLOC_H */
diff --git a/arch/ia64/include/asm/xor.h b/arch/ia64/include/asm/xor.h
deleted file mode 100644
index 6785f70d3208..000000000000
--- a/arch/ia64/include/asm/xor.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Optimized RAID-5 checksumming functions for IA-64.
- */
-
-
-extern void xor_ia64_2(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2);
-extern void xor_ia64_3(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3);
-extern void xor_ia64_4(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3,
- const unsigned long * __restrict p4);
-extern void xor_ia64_5(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3,
- const unsigned long * __restrict p4,
- const unsigned long * __restrict p5);
-
-static struct xor_block_template xor_block_ia64 = {
- .name = "ia64",
- .do_2 = xor_ia64_2,
- .do_3 = xor_ia64_3,
- .do_4 = xor_ia64_4,
- .do_5 = xor_ia64_5,
-};
-
-#define XOR_TRY_TEMPLATES xor_speed(&xor_block_ia64)
diff --git a/arch/ia64/include/asm/xtp.h b/arch/ia64/include/asm/xtp.h
deleted file mode 100644
index 5bf1d70ad860..000000000000
--- a/arch/ia64/include/asm/xtp.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_IA64_XTP_H
-#define _ASM_IA64_XTP_H
-
-#include <asm/io.h>
-
-#ifdef CONFIG_SMP
-
-#define XTP_OFFSET 0x1e0008
-
-#define SMP_IRQ_REDIRECTION (1 << 0)
-#define SMP_IPI_REDIRECTION (1 << 1)
-
-extern unsigned char smp_int_redirect;
-
-/*
- * XTP control functions:
- * min_xtp : route all interrupts to this CPU
- * normal_xtp: nominal XTP value
- * max_xtp : never deliver interrupts to this CPU.
- */
-
-static inline void
-min_xtp (void)
-{
- if (smp_int_redirect & SMP_IRQ_REDIRECTION)
- writeb(0x00, ipi_base_addr + XTP_OFFSET); /* XTP to min */
-}
-
-static inline void
-normal_xtp (void)
-{
- if (smp_int_redirect & SMP_IRQ_REDIRECTION)
- writeb(0x08, ipi_base_addr + XTP_OFFSET); /* XTP normal */
-}
-
-static inline void
-max_xtp (void)
-{
- if (smp_int_redirect & SMP_IRQ_REDIRECTION)
- writeb(0x0f, ipi_base_addr + XTP_OFFSET); /* Set XTP to max */
-}
-
-#endif /* CONFIG_SMP */
-
-#endif /* _ASM_IA64_XTP_Hy */
diff --git a/arch/ia64/include/uapi/asm/Kbuild b/arch/ia64/include/uapi/asm/Kbuild
deleted file mode 100644
index 3a1341e3535a..000000000000
--- a/arch/ia64/include/uapi/asm/Kbuild
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-generated-y += unistd_64.h
diff --git a/arch/ia64/include/uapi/asm/auxvec.h b/arch/ia64/include/uapi/asm/auxvec.h
deleted file mode 100644
index 09969a5d2e0a..000000000000
--- a/arch/ia64/include/uapi/asm/auxvec.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_AUXVEC_H
-#define _ASM_IA64_AUXVEC_H
-
-/*
- * Architecture-neutral AT_ values are in the range 0-17. Leave some room for more of
- * them, start the architecture-specific ones at 32.
- */
-#define AT_SYSINFO 32
-#define AT_SYSINFO_EHDR 33
-
-#define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */
-
-#endif /* _ASM_IA64_AUXVEC_H */
diff --git a/arch/ia64/include/uapi/asm/bitsperlong.h b/arch/ia64/include/uapi/asm/bitsperlong.h
deleted file mode 100644
index 1146d55563db..000000000000
--- a/arch/ia64/include/uapi/asm/bitsperlong.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef __ASM_IA64_BITSPERLONG_H
-#define __ASM_IA64_BITSPERLONG_H
-
-#define __BITS_PER_LONG 64
-
-#include <asm-generic/bitsperlong.h>
-
-#endif /* __ASM_IA64_BITSPERLONG_H */
diff --git a/arch/ia64/include/uapi/asm/break.h b/arch/ia64/include/uapi/asm/break.h
deleted file mode 100644
index 4ca110f0a94b..000000000000
--- a/arch/ia64/include/uapi/asm/break.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_BREAK_H
-#define _ASM_IA64_BREAK_H
-
-/*
- * IA-64 Linux break numbers.
- *
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-/*
- * OS-specific debug break numbers:
- */
-#define __IA64_BREAK_KDB 0x80100
-#define __IA64_BREAK_KPROBE 0x81000 /* .. 0x81fff */
-
-/*
- * OS-specific break numbers:
- */
-#define __IA64_BREAK_SYSCALL 0x100000
-
-#endif /* _ASM_IA64_BREAK_H */
diff --git a/arch/ia64/include/uapi/asm/byteorder.h b/arch/ia64/include/uapi/asm/byteorder.h
deleted file mode 100644
index f85d0faaaf34..000000000000
--- a/arch/ia64/include/uapi/asm/byteorder.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_BYTEORDER_H
-#define _ASM_IA64_BYTEORDER_H
-
-#include <linux/byteorder/little_endian.h>
-
-#endif /* _ASM_IA64_BYTEORDER_H */
diff --git a/arch/ia64/include/uapi/asm/cmpxchg.h b/arch/ia64/include/uapi/asm/cmpxchg.h
deleted file mode 100644
index a59b5de6eec6..000000000000
--- a/arch/ia64/include/uapi/asm/cmpxchg.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _UAPI_ASM_IA64_CMPXCHG_H
-#define _UAPI_ASM_IA64_CMPXCHG_H
-
-/*
- * Compare/Exchange, forked from asm/intrinsics.h
- * which was:
- *
- * Copyright (C) 2002-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-/* include compiler specific intrinsics */
-#include <asm/ia64regs.h>
-#include <asm/gcc_intrin.h>
-
-/*
- * This function doesn't exist, so you'll get a linker error if
- * something tries to do an invalid xchg().
- */
-extern void ia64_xchg_called_with_bad_pointer(void);
-
-#define __arch_xchg(x, ptr, size) \
-({ \
- unsigned long __xchg_result; \
- \
- switch (size) { \
- case 1: \
- __xchg_result = ia64_xchg1((__u8 __force *)ptr, x); \
- break; \
- \
- case 2: \
- __xchg_result = ia64_xchg2((__u16 __force *)ptr, x); \
- break; \
- \
- case 4: \
- __xchg_result = ia64_xchg4((__u32 __force *)ptr, x); \
- break; \
- \
- case 8: \
- __xchg_result = ia64_xchg8((__u64 __force *)ptr, x); \
- break; \
- default: \
- ia64_xchg_called_with_bad_pointer(); \
- } \
- (__typeof__ (*(ptr)) __force) __xchg_result; \
-})
-
-#ifndef __KERNEL__
-#define xchg(ptr, x) \
-({(__typeof__(*(ptr))) __arch_xchg((unsigned long) (x), (ptr), sizeof(*(ptr)));})
-#endif
-
-/*
- * Atomic compare and exchange. Compare OLD with MEM, if identical,
- * store NEW in MEM. Return the initial value in MEM. Success is
- * indicated by comparing RETURN with OLD.
- */
-
-/*
- * This function doesn't exist, so you'll get a linker error
- * if something tries to do an invalid cmpxchg().
- */
-extern long ia64_cmpxchg_called_with_bad_pointer(void);
-
-#define ia64_cmpxchg(sem, ptr, old, new, size) \
-({ \
- __u64 _o_, _r_; \
- \
- switch (size) { \
- case 1: \
- _o_ = (__u8) (long __force) (old); \
- break; \
- case 2: \
- _o_ = (__u16) (long __force) (old); \
- break; \
- case 4: \
- _o_ = (__u32) (long __force) (old); \
- break; \
- case 8: \
- _o_ = (__u64) (long __force) (old); \
- break; \
- default: \
- break; \
- } \
- switch (size) { \
- case 1: \
- _r_ = ia64_cmpxchg1_##sem((__u8 __force *) ptr, new, _o_); \
- break; \
- \
- case 2: \
- _r_ = ia64_cmpxchg2_##sem((__u16 __force *) ptr, new, _o_); \
- break; \
- \
- case 4: \
- _r_ = ia64_cmpxchg4_##sem((__u32 __force *) ptr, new, _o_); \
- break; \
- \
- case 8: \
- _r_ = ia64_cmpxchg8_##sem((__u64 __force *) ptr, new, _o_); \
- break; \
- \
- default: \
- _r_ = ia64_cmpxchg_called_with_bad_pointer(); \
- break; \
- } \
- (__typeof__(old) __force) _r_; \
-})
-
-#define cmpxchg_acq(ptr, o, n) \
- ia64_cmpxchg(acq, (ptr), (o), (n), sizeof(*(ptr)))
-#define cmpxchg_rel(ptr, o, n) \
- ia64_cmpxchg(rel, (ptr), (o), (n), sizeof(*(ptr)))
-
-/*
- * Worse still - early processor implementations actually just ignored
- * the acquire/release and did a full fence all the time. Unfortunately
- * this meant a lot of badly written code that used .acq when they really
- * wanted .rel became legacy out in the wild - so when we made a cpu
- * that strictly did the .acq or .rel ... all that code started breaking - so
- * we had to back-pedal and keep the "legacy" behavior of a full fence :-(
- */
-
-#ifndef __KERNEL__
-/* for compatibility with other platforms: */
-#define cmpxchg(ptr, o, n) cmpxchg_acq((ptr), (o), (n))
-#define cmpxchg64(ptr, o, n) cmpxchg_acq((ptr), (o), (n))
-
-#define cmpxchg_local cmpxchg
-#define cmpxchg64_local cmpxchg64
-#endif
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _UAPI_ASM_IA64_CMPXCHG_H */
diff --git a/arch/ia64/include/uapi/asm/fcntl.h b/arch/ia64/include/uapi/asm/fcntl.h
deleted file mode 100644
index 7b95523efe5a..000000000000
--- a/arch/ia64/include/uapi/asm/fcntl.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_FCNTL_H
-#define _ASM_IA64_FCNTL_H
-/*
- * Modified 1998-2000
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
- */
-
-#define force_o_largefile() \
- (personality(current->personality) != PER_LINUX32)
-
-#include <linux/personality.h>
-#include <asm-generic/fcntl.h>
-
-#endif /* _ASM_IA64_FCNTL_H */
diff --git a/arch/ia64/include/uapi/asm/fpu.h b/arch/ia64/include/uapi/asm/fpu.h
deleted file mode 100644
index 0df392982ce8..000000000000
--- a/arch/ia64/include/uapi/asm/fpu.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_FPU_H
-#define _ASM_IA64_FPU_H
-
-/*
- * Copyright (C) 1998, 1999, 2002, 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/types.h>
-
-/* floating point status register: */
-#define FPSR_TRAP_VD (1 << 0) /* invalid op trap disabled */
-#define FPSR_TRAP_DD (1 << 1) /* denormal trap disabled */
-#define FPSR_TRAP_ZD (1 << 2) /* zero-divide trap disabled */
-#define FPSR_TRAP_OD (1 << 3) /* overflow trap disabled */
-#define FPSR_TRAP_UD (1 << 4) /* underflow trap disabled */
-#define FPSR_TRAP_ID (1 << 5) /* inexact trap disabled */
-#define FPSR_S0(x) ((x) << 6)
-#define FPSR_S1(x) ((x) << 19)
-#define FPSR_S2(x) (__IA64_UL(x) << 32)
-#define FPSR_S3(x) (__IA64_UL(x) << 45)
-
-/* floating-point status field controls: */
-#define FPSF_FTZ (1 << 0) /* flush-to-zero */
-#define FPSF_WRE (1 << 1) /* widest-range exponent */
-#define FPSF_PC(x) (((x) & 0x3) << 2) /* precision control */
-#define FPSF_RC(x) (((x) & 0x3) << 4) /* rounding control */
-#define FPSF_TD (1 << 6) /* trap disabled */
-
-/* floating-point status field flags: */
-#define FPSF_V (1 << 7) /* invalid operation flag */
-#define FPSF_D (1 << 8) /* denormal/unnormal operand flag */
-#define FPSF_Z (1 << 9) /* zero divide (IEEE) flag */
-#define FPSF_O (1 << 10) /* overflow (IEEE) flag */
-#define FPSF_U (1 << 11) /* underflow (IEEE) flag */
-#define FPSF_I (1 << 12) /* inexact (IEEE) flag) */
-
-/* floating-point rounding control: */
-#define FPRC_NEAREST 0x0
-#define FPRC_NEGINF 0x1
-#define FPRC_POSINF 0x2
-#define FPRC_TRUNC 0x3
-
-#define FPSF_DEFAULT (FPSF_PC (0x3) | FPSF_RC (FPRC_NEAREST))
-
-/* This default value is the same as HP-UX uses. Don't change it
- without a very good reason. */
-#define FPSR_DEFAULT (FPSR_TRAP_VD | FPSR_TRAP_DD | FPSR_TRAP_ZD \
- | FPSR_TRAP_OD | FPSR_TRAP_UD | FPSR_TRAP_ID \
- | FPSR_S0 (FPSF_DEFAULT) \
- | FPSR_S1 (FPSF_DEFAULT | FPSF_TD | FPSF_WRE) \
- | FPSR_S2 (FPSF_DEFAULT | FPSF_TD) \
- | FPSR_S3 (FPSF_DEFAULT | FPSF_TD))
-
-# ifndef __ASSEMBLY__
-
-struct ia64_fpreg {
- union {
- unsigned long bits[2];
- long double __dummy; /* force 16-byte alignment */
- } u;
-};
-
-# endif /* __ASSEMBLY__ */
-
-#endif /* _ASM_IA64_FPU_H */
diff --git a/arch/ia64/include/uapi/asm/gcc_intrin.h b/arch/ia64/include/uapi/asm/gcc_intrin.h
deleted file mode 100644
index ecfa3eadb217..000000000000
--- a/arch/ia64/include/uapi/asm/gcc_intrin.h
+++ /dev/null
@@ -1,619 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- *
- * Copyright (C) 2002,2003 Jun Nakajima <jun.nakajima@intel.com>
- * Copyright (C) 2002,2003 Suresh Siddha <suresh.b.siddha@intel.com>
- */
-#ifndef _UAPI_ASM_IA64_GCC_INTRIN_H
-#define _UAPI_ASM_IA64_GCC_INTRIN_H
-
-#include <linux/types.h>
-#include <linux/compiler.h>
-
-/* define this macro to get some asm stmts included in 'c' files */
-#define ASM_SUPPORTED
-
-/* Optimization barrier */
-/* The "volatile" is due to gcc bugs */
-#define ia64_barrier() asm volatile ("":::"memory")
-
-#define ia64_stop() asm volatile (";;"::)
-
-#define ia64_invala_gr(regnum) asm volatile ("invala.e r%0" :: "i"(regnum))
-
-#define ia64_invala_fr(regnum) asm volatile ("invala.e f%0" :: "i"(regnum))
-
-#define ia64_flushrs() asm volatile ("flushrs;;":::"memory")
-
-#define ia64_loadrs() asm volatile ("loadrs;;":::"memory")
-
-extern void ia64_bad_param_for_setreg (void);
-extern void ia64_bad_param_for_getreg (void);
-
-
-#define ia64_setreg(regnum, val) \
-({ \
- switch (regnum) { \
- case _IA64_REG_PSR_L: \
- asm volatile ("mov psr.l=%0" :: "r"(val) : "memory"); \
- break; \
- case _IA64_REG_AR_KR0 ... _IA64_REG_AR_EC: \
- asm volatile ("mov ar%0=%1" :: \
- "i" (regnum - _IA64_REG_AR_KR0), \
- "r"(val): "memory"); \
- break; \
- case _IA64_REG_CR_DCR ... _IA64_REG_CR_LRR1: \
- asm volatile ("mov cr%0=%1" :: \
- "i" (regnum - _IA64_REG_CR_DCR), \
- "r"(val): "memory" ); \
- break; \
- case _IA64_REG_SP: \
- asm volatile ("mov r12=%0" :: \
- "r"(val): "memory"); \
- break; \
- case _IA64_REG_GP: \
- asm volatile ("mov gp=%0" :: "r"(val) : "memory"); \
- break; \
- default: \
- ia64_bad_param_for_setreg(); \
- break; \
- } \
-})
-
-#define ia64_getreg(regnum) \
-({ \
- __u64 ia64_intri_res; \
- \
- switch (regnum) { \
- case _IA64_REG_GP: \
- asm volatile ("mov %0=gp" : "=r"(ia64_intri_res)); \
- break; \
- case _IA64_REG_IP: \
- asm volatile ("mov %0=ip" : "=r"(ia64_intri_res)); \
- break; \
- case _IA64_REG_PSR: \
- asm volatile ("mov %0=psr" : "=r"(ia64_intri_res)); \
- break; \
- case _IA64_REG_TP: /* for current() */ \
- ia64_intri_res = ia64_r13; \
- break; \
- case _IA64_REG_AR_KR0 ... _IA64_REG_AR_EC: \
- asm volatile ("mov %0=ar%1" : "=r" (ia64_intri_res) \
- : "i"(regnum - _IA64_REG_AR_KR0)); \
- break; \
- case _IA64_REG_CR_DCR ... _IA64_REG_CR_LRR1: \
- asm volatile ("mov %0=cr%1" : "=r" (ia64_intri_res) \
- : "i" (regnum - _IA64_REG_CR_DCR)); \
- break; \
- case _IA64_REG_SP: \
- asm volatile ("mov %0=sp" : "=r" (ia64_intri_res)); \
- break; \
- default: \
- ia64_bad_param_for_getreg(); \
- break; \
- } \
- ia64_intri_res; \
-})
-
-#define ia64_hint_pause 0
-
-#define ia64_hint(mode) \
-({ \
- switch (mode) { \
- case ia64_hint_pause: \
- asm volatile ("hint @pause" ::: "memory"); \
- break; \
- } \
-})
-
-
-/* Integer values for mux1 instruction */
-#define ia64_mux1_brcst 0
-#define ia64_mux1_mix 8
-#define ia64_mux1_shuf 9
-#define ia64_mux1_alt 10
-#define ia64_mux1_rev 11
-
-#define ia64_mux1(x, mode) \
-({ \
- __u64 ia64_intri_res; \
- \
- switch (mode) { \
- case ia64_mux1_brcst: \
- asm ("mux1 %0=%1,@brcst" : "=r" (ia64_intri_res) : "r" (x)); \
- break; \
- case ia64_mux1_mix: \
- asm ("mux1 %0=%1,@mix" : "=r" (ia64_intri_res) : "r" (x)); \
- break; \
- case ia64_mux1_shuf: \
- asm ("mux1 %0=%1,@shuf" : "=r" (ia64_intri_res) : "r" (x)); \
- break; \
- case ia64_mux1_alt: \
- asm ("mux1 %0=%1,@alt" : "=r" (ia64_intri_res) : "r" (x)); \
- break; \
- case ia64_mux1_rev: \
- asm ("mux1 %0=%1,@rev" : "=r" (ia64_intri_res) : "r" (x)); \
- break; \
- } \
- ia64_intri_res; \
-})
-
-#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-# define ia64_popcnt(x) __builtin_popcountl(x)
-#else
-# define ia64_popcnt(x) \
- ({ \
- __u64 ia64_intri_res; \
- asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x)); \
- \
- ia64_intri_res; \
- })
-#endif
-
-#define ia64_getf_exp(x) \
-({ \
- long ia64_intri_res; \
- \
- asm ("getf.exp %0=%1" : "=r"(ia64_intri_res) : "f"(x)); \
- \
- ia64_intri_res; \
-})
-
-#define ia64_shrp(a, b, count) \
-({ \
- __u64 ia64_intri_res; \
- asm ("shrp %0=%1,%2,%3" : "=r"(ia64_intri_res) : "r"(a), "r"(b), "i"(count)); \
- ia64_intri_res; \
-})
-
-#define ia64_ldfs(regnum, x) \
-({ \
- register double __f__ asm ("f"#regnum); \
- asm volatile ("ldfs %0=[%1]" :"=f"(__f__): "r"(x)); \
-})
-
-#define ia64_ldfd(regnum, x) \
-({ \
- register double __f__ asm ("f"#regnum); \
- asm volatile ("ldfd %0=[%1]" :"=f"(__f__): "r"(x)); \
-})
-
-#define ia64_ldfe(regnum, x) \
-({ \
- register double __f__ asm ("f"#regnum); \
- asm volatile ("ldfe %0=[%1]" :"=f"(__f__): "r"(x)); \
-})
-
-#define ia64_ldf8(regnum, x) \
-({ \
- register double __f__ asm ("f"#regnum); \
- asm volatile ("ldf8 %0=[%1]" :"=f"(__f__): "r"(x)); \
-})
-
-#define ia64_ldf_fill(regnum, x) \
-({ \
- register double __f__ asm ("f"#regnum); \
- asm volatile ("ldf.fill %0=[%1]" :"=f"(__f__): "r"(x)); \
-})
-
-#define ia64_st4_rel_nta(m, val) \
-({ \
- asm volatile ("st4.rel.nta [%0] = %1\n\t" :: "r"(m), "r"(val)); \
-})
-
-#define ia64_stfs(x, regnum) \
-({ \
- register double __f__ asm ("f"#regnum); \
- asm volatile ("stfs [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
-})
-
-#define ia64_stfd(x, regnum) \
-({ \
- register double __f__ asm ("f"#regnum); \
- asm volatile ("stfd [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
-})
-
-#define ia64_stfe(x, regnum) \
-({ \
- register double __f__ asm ("f"#regnum); \
- asm volatile ("stfe [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
-})
-
-#define ia64_stf8(x, regnum) \
-({ \
- register double __f__ asm ("f"#regnum); \
- asm volatile ("stf8 [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
-})
-
-#define ia64_stf_spill(x, regnum) \
-({ \
- register double __f__ asm ("f"#regnum); \
- asm volatile ("stf.spill [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
-})
-
-#define ia64_fetchadd4_acq(p, inc) \
-({ \
- \
- __u64 ia64_intri_res; \
- asm volatile ("fetchadd4.acq %0=[%1],%2" \
- : "=r"(ia64_intri_res) : "r"(p), "i" (inc) \
- : "memory"); \
- \
- ia64_intri_res; \
-})
-
-#define ia64_fetchadd4_rel(p, inc) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("fetchadd4.rel %0=[%1],%2" \
- : "=r"(ia64_intri_res) : "r"(p), "i" (inc) \
- : "memory"); \
- \
- ia64_intri_res; \
-})
-
-#define ia64_fetchadd8_acq(p, inc) \
-({ \
- \
- __u64 ia64_intri_res; \
- asm volatile ("fetchadd8.acq %0=[%1],%2" \
- : "=r"(ia64_intri_res) : "r"(p), "i" (inc) \
- : "memory"); \
- \
- ia64_intri_res; \
-})
-
-#define ia64_fetchadd8_rel(p, inc) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("fetchadd8.rel %0=[%1],%2" \
- : "=r"(ia64_intri_res) : "r"(p), "i" (inc) \
- : "memory"); \
- \
- ia64_intri_res; \
-})
-
-#define ia64_xchg1(ptr,x) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("xchg1 %0=[%1],%2" \
- : "=r" (ia64_intri_res) : "r" (ptr), "r" (x) : "memory"); \
- ia64_intri_res; \
-})
-
-#define ia64_xchg2(ptr,x) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("xchg2 %0=[%1],%2" : "=r" (ia64_intri_res) \
- : "r" (ptr), "r" (x) : "memory"); \
- ia64_intri_res; \
-})
-
-#define ia64_xchg4(ptr,x) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("xchg4 %0=[%1],%2" : "=r" (ia64_intri_res) \
- : "r" (ptr), "r" (x) : "memory"); \
- ia64_intri_res; \
-})
-
-#define ia64_xchg8(ptr,x) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("xchg8 %0=[%1],%2" : "=r" (ia64_intri_res) \
- : "r" (ptr), "r" (x) : "memory"); \
- ia64_intri_res; \
-})
-
-#define ia64_cmpxchg1_acq(ptr, new, old) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("mov ar.ccv=%0;;" :: "rO"(old)); \
- asm volatile ("cmpxchg1.acq %0=[%1],%2,ar.ccv": \
- "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory"); \
- ia64_intri_res; \
-})
-
-#define ia64_cmpxchg1_rel(ptr, new, old) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("mov ar.ccv=%0;;" :: "rO"(old)); \
- asm volatile ("cmpxchg1.rel %0=[%1],%2,ar.ccv": \
- "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory"); \
- ia64_intri_res; \
-})
-
-#define ia64_cmpxchg2_acq(ptr, new, old) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("mov ar.ccv=%0;;" :: "rO"(old)); \
- asm volatile ("cmpxchg2.acq %0=[%1],%2,ar.ccv": \
- "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory"); \
- ia64_intri_res; \
-})
-
-#define ia64_cmpxchg2_rel(ptr, new, old) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("mov ar.ccv=%0;;" :: "rO"(old)); \
- \
- asm volatile ("cmpxchg2.rel %0=[%1],%2,ar.ccv": \
- "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory"); \
- ia64_intri_res; \
-})
-
-#define ia64_cmpxchg4_acq(ptr, new, old) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("mov ar.ccv=%0;;" :: "rO"(old)); \
- asm volatile ("cmpxchg4.acq %0=[%1],%2,ar.ccv": \
- "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory"); \
- ia64_intri_res; \
-})
-
-#define ia64_cmpxchg4_rel(ptr, new, old) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("mov ar.ccv=%0;;" :: "rO"(old)); \
- asm volatile ("cmpxchg4.rel %0=[%1],%2,ar.ccv": \
- "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory"); \
- ia64_intri_res; \
-})
-
-#define ia64_cmpxchg8_acq(ptr, new, old) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("mov ar.ccv=%0;;" :: "rO"(old)); \
- asm volatile ("cmpxchg8.acq %0=[%1],%2,ar.ccv": \
- "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory"); \
- ia64_intri_res; \
-})
-
-#define ia64_cmpxchg8_rel(ptr, new, old) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("mov ar.ccv=%0;;" :: "rO"(old)); \
- \
- asm volatile ("cmpxchg8.rel %0=[%1],%2,ar.ccv": \
- "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory"); \
- ia64_intri_res; \
-})
-
-#define ia64_mf() asm volatile ("mf" ::: "memory")
-#define ia64_mfa() asm volatile ("mf.a" ::: "memory")
-
-#define ia64_invala() asm volatile ("invala" ::: "memory")
-
-#define ia64_thash(addr) \
-({ \
- unsigned long ia64_intri_res; \
- asm volatile ("thash %0=%1" : "=r"(ia64_intri_res) : "r" (addr)); \
- ia64_intri_res; \
-})
-
-#define ia64_srlz_i() asm volatile (";; srlz.i ;;" ::: "memory")
-#define ia64_srlz_d() asm volatile (";; srlz.d" ::: "memory");
-
-#ifdef HAVE_SERIALIZE_DIRECTIVE
-# define ia64_dv_serialize_data() asm volatile (".serialize.data");
-# define ia64_dv_serialize_instruction() asm volatile (".serialize.instruction");
-#else
-# define ia64_dv_serialize_data()
-# define ia64_dv_serialize_instruction()
-#endif
-
-#define ia64_nop(x) asm volatile ("nop %0"::"i"(x));
-
-#define ia64_itci(addr) asm volatile ("itc.i %0;;" :: "r"(addr) : "memory")
-
-#define ia64_itcd(addr) asm volatile ("itc.d %0;;" :: "r"(addr) : "memory")
-
-
-#define ia64_itri(trnum, addr) asm volatile ("itr.i itr[%0]=%1" \
- :: "r"(trnum), "r"(addr) : "memory")
-
-#define ia64_itrd(trnum, addr) asm volatile ("itr.d dtr[%0]=%1" \
- :: "r"(trnum), "r"(addr) : "memory")
-
-#define ia64_tpa(addr) \
-({ \
- unsigned long ia64_pa; \
- asm volatile ("tpa %0 = %1" : "=r"(ia64_pa) : "r"(addr) : "memory"); \
- ia64_pa; \
-})
-
-#define __ia64_set_dbr(index, val) \
- asm volatile ("mov dbr[%0]=%1" :: "r"(index), "r"(val) : "memory")
-
-#define ia64_set_ibr(index, val) \
- asm volatile ("mov ibr[%0]=%1" :: "r"(index), "r"(val) : "memory")
-
-#define ia64_set_pkr(index, val) \
- asm volatile ("mov pkr[%0]=%1" :: "r"(index), "r"(val) : "memory")
-
-#define ia64_set_pmc(index, val) \
- asm volatile ("mov pmc[%0]=%1" :: "r"(index), "r"(val) : "memory")
-
-#define ia64_set_pmd(index, val) \
- asm volatile ("mov pmd[%0]=%1" :: "r"(index), "r"(val) : "memory")
-
-#define ia64_set_rr(index, val) \
- asm volatile ("mov rr[%0]=%1" :: "r"(index), "r"(val) : "memory");
-
-#define ia64_get_cpuid(index) \
-({ \
- unsigned long ia64_intri_res; \
- asm volatile ("mov %0=cpuid[%r1]" : "=r"(ia64_intri_res) : "rO"(index)); \
- ia64_intri_res; \
-})
-
-#define __ia64_get_dbr(index) \
-({ \
- unsigned long ia64_intri_res; \
- asm volatile ("mov %0=dbr[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
- ia64_intri_res; \
-})
-
-#define ia64_get_ibr(index) \
-({ \
- unsigned long ia64_intri_res; \
- asm volatile ("mov %0=ibr[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
- ia64_intri_res; \
-})
-
-#define ia64_get_pkr(index) \
-({ \
- unsigned long ia64_intri_res; \
- asm volatile ("mov %0=pkr[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
- ia64_intri_res; \
-})
-
-#define ia64_get_pmc(index) \
-({ \
- unsigned long ia64_intri_res; \
- asm volatile ("mov %0=pmc[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
- ia64_intri_res; \
-})
-
-
-#define ia64_get_pmd(index) \
-({ \
- unsigned long ia64_intri_res; \
- asm volatile ("mov %0=pmd[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
- ia64_intri_res; \
-})
-
-#define ia64_get_rr(index) \
-({ \
- unsigned long ia64_intri_res; \
- asm volatile ("mov %0=rr[%1]" : "=r"(ia64_intri_res) : "r" (index)); \
- ia64_intri_res; \
-})
-
-#define ia64_fc(addr) asm volatile ("fc %0" :: "r"(addr) : "memory")
-
-
-#define ia64_sync_i() asm volatile (";; sync.i" ::: "memory")
-
-#define ia64_ssm(mask) asm volatile ("ssm %0":: "i"((mask)) : "memory")
-#define ia64_rsm(mask) asm volatile ("rsm %0":: "i"((mask)) : "memory")
-#define ia64_sum(mask) asm volatile ("sum %0":: "i"((mask)) : "memory")
-#define ia64_rum(mask) asm volatile ("rum %0":: "i"((mask)) : "memory")
-
-#define ia64_ptce(addr) asm volatile ("ptc.e %0" :: "r"(addr))
-
-#define ia64_ptcga(addr, size) \
-do { \
- asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory"); \
- ia64_dv_serialize_data(); \
-} while (0)
-
-#define ia64_ptcl(addr, size) \
-do { \
- asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(size) : "memory"); \
- ia64_dv_serialize_data(); \
-} while (0)
-
-#define ia64_ptri(addr, size) \
- asm volatile ("ptr.i %0,%1" :: "r"(addr), "r"(size) : "memory")
-
-#define ia64_ptrd(addr, size) \
- asm volatile ("ptr.d %0,%1" :: "r"(addr), "r"(size) : "memory")
-
-#define ia64_ttag(addr) \
-({ \
- __u64 ia64_intri_res; \
- asm volatile ("ttag %0=%1" : "=r"(ia64_intri_res) : "r" (addr)); \
- ia64_intri_res; \
-})
-
-
-/* Values for lfhint in ia64_lfetch and ia64_lfetch_fault */
-
-#define ia64_lfhint_none 0
-#define ia64_lfhint_nt1 1
-#define ia64_lfhint_nt2 2
-#define ia64_lfhint_nta 3
-
-#define ia64_lfetch(lfhint, y) \
-({ \
- switch (lfhint) { \
- case ia64_lfhint_none: \
- asm volatile ("lfetch [%0]" : : "r"(y)); \
- break; \
- case ia64_lfhint_nt1: \
- asm volatile ("lfetch.nt1 [%0]" : : "r"(y)); \
- break; \
- case ia64_lfhint_nt2: \
- asm volatile ("lfetch.nt2 [%0]" : : "r"(y)); \
- break; \
- case ia64_lfhint_nta: \
- asm volatile ("lfetch.nta [%0]" : : "r"(y)); \
- break; \
- } \
-})
-
-#define ia64_lfetch_excl(lfhint, y) \
-({ \
- switch (lfhint) { \
- case ia64_lfhint_none: \
- asm volatile ("lfetch.excl [%0]" :: "r"(y)); \
- break; \
- case ia64_lfhint_nt1: \
- asm volatile ("lfetch.excl.nt1 [%0]" :: "r"(y)); \
- break; \
- case ia64_lfhint_nt2: \
- asm volatile ("lfetch.excl.nt2 [%0]" :: "r"(y)); \
- break; \
- case ia64_lfhint_nta: \
- asm volatile ("lfetch.excl.nta [%0]" :: "r"(y)); \
- break; \
- } \
-})
-
-#define ia64_lfetch_fault(lfhint, y) \
-({ \
- switch (lfhint) { \
- case ia64_lfhint_none: \
- asm volatile ("lfetch.fault [%0]" : : "r"(y)); \
- break; \
- case ia64_lfhint_nt1: \
- asm volatile ("lfetch.fault.nt1 [%0]" : : "r"(y)); \
- break; \
- case ia64_lfhint_nt2: \
- asm volatile ("lfetch.fault.nt2 [%0]" : : "r"(y)); \
- break; \
- case ia64_lfhint_nta: \
- asm volatile ("lfetch.fault.nta [%0]" : : "r"(y)); \
- break; \
- } \
-})
-
-#define ia64_lfetch_fault_excl(lfhint, y) \
-({ \
- switch (lfhint) { \
- case ia64_lfhint_none: \
- asm volatile ("lfetch.fault.excl [%0]" :: "r"(y)); \
- break; \
- case ia64_lfhint_nt1: \
- asm volatile ("lfetch.fault.excl.nt1 [%0]" :: "r"(y)); \
- break; \
- case ia64_lfhint_nt2: \
- asm volatile ("lfetch.fault.excl.nt2 [%0]" :: "r"(y)); \
- break; \
- case ia64_lfhint_nta: \
- asm volatile ("lfetch.fault.excl.nta [%0]" :: "r"(y)); \
- break; \
- } \
-})
-
-#define ia64_intrin_local_irq_restore(x) \
-do { \
- asm volatile (";; cmp.ne p6,p7=%0,r0;;" \
- "(p6) ssm psr.i;" \
- "(p7) rsm psr.i;;" \
- "(p6) srlz.d" \
- :: "r"((x)) : "p6", "p7", "memory"); \
-} while (0)
-
-#endif /* _UAPI_ASM_IA64_GCC_INTRIN_H */
diff --git a/arch/ia64/include/uapi/asm/ia64regs.h b/arch/ia64/include/uapi/asm/ia64regs.h
deleted file mode 100644
index d7d10cec8b9f..000000000000
--- a/arch/ia64/include/uapi/asm/ia64regs.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Copyright (C) 2002,2003 Intel Corp.
- * Jun Nakajima <jun.nakajima@intel.com>
- * Suresh Siddha <suresh.b.siddha@intel.com>
- */
-
-#ifndef _ASM_IA64_IA64REGS_H
-#define _ASM_IA64_IA64REGS_H
-
-/*
- * Register Names for getreg() and setreg().
- *
- * The "magic" numbers happen to match the values used by the Intel compiler's
- * getreg()/setreg() intrinsics.
- */
-
-/* Special Registers */
-
-#define _IA64_REG_IP 1016 /* getreg only */
-#define _IA64_REG_PSR 1019
-#define _IA64_REG_PSR_L 1019
-
-/* General Integer Registers */
-
-#define _IA64_REG_GP 1025 /* R1 */
-#define _IA64_REG_R8 1032 /* R8 */
-#define _IA64_REG_R9 1033 /* R9 */
-#define _IA64_REG_SP 1036 /* R12 */
-#define _IA64_REG_TP 1037 /* R13 */
-
-/* Application Registers */
-
-#define _IA64_REG_AR_KR0 3072
-#define _IA64_REG_AR_KR1 3073
-#define _IA64_REG_AR_KR2 3074
-#define _IA64_REG_AR_KR3 3075
-#define _IA64_REG_AR_KR4 3076
-#define _IA64_REG_AR_KR5 3077
-#define _IA64_REG_AR_KR6 3078
-#define _IA64_REG_AR_KR7 3079
-#define _IA64_REG_AR_RSC 3088
-#define _IA64_REG_AR_BSP 3089
-#define _IA64_REG_AR_BSPSTORE 3090
-#define _IA64_REG_AR_RNAT 3091
-#define _IA64_REG_AR_FCR 3093
-#define _IA64_REG_AR_EFLAG 3096
-#define _IA64_REG_AR_CSD 3097
-#define _IA64_REG_AR_SSD 3098
-#define _IA64_REG_AR_CFLAG 3099
-#define _IA64_REG_AR_FSR 3100
-#define _IA64_REG_AR_FIR 3101
-#define _IA64_REG_AR_FDR 3102
-#define _IA64_REG_AR_CCV 3104
-#define _IA64_REG_AR_UNAT 3108
-#define _IA64_REG_AR_FPSR 3112
-#define _IA64_REG_AR_ITC 3116
-#define _IA64_REG_AR_PFS 3136
-#define _IA64_REG_AR_LC 3137
-#define _IA64_REG_AR_EC 3138
-
-/* Control Registers */
-
-#define _IA64_REG_CR_DCR 4096
-#define _IA64_REG_CR_ITM 4097
-#define _IA64_REG_CR_IVA 4098
-#define _IA64_REG_CR_PTA 4104
-#define _IA64_REG_CR_IPSR 4112
-#define _IA64_REG_CR_ISR 4113
-#define _IA64_REG_CR_IIP 4115
-#define _IA64_REG_CR_IFA 4116
-#define _IA64_REG_CR_ITIR 4117
-#define _IA64_REG_CR_IIPA 4118
-#define _IA64_REG_CR_IFS 4119
-#define _IA64_REG_CR_IIM 4120
-#define _IA64_REG_CR_IHA 4121
-#define _IA64_REG_CR_LID 4160
-#define _IA64_REG_CR_IVR 4161 /* getreg only */
-#define _IA64_REG_CR_TPR 4162
-#define _IA64_REG_CR_EOI 4163
-#define _IA64_REG_CR_IRR0 4164 /* getreg only */
-#define _IA64_REG_CR_IRR1 4165 /* getreg only */
-#define _IA64_REG_CR_IRR2 4166 /* getreg only */
-#define _IA64_REG_CR_IRR3 4167 /* getreg only */
-#define _IA64_REG_CR_ITV 4168
-#define _IA64_REG_CR_PMV 4169
-#define _IA64_REG_CR_CMCV 4170
-#define _IA64_REG_CR_LRR0 4176
-#define _IA64_REG_CR_LRR1 4177
-
-/* Indirect Registers for getindreg() and setindreg() */
-
-#define _IA64_REG_INDR_CPUID 9000 /* getindreg only */
-#define _IA64_REG_INDR_DBR 9001
-#define _IA64_REG_INDR_IBR 9002
-#define _IA64_REG_INDR_PKR 9003
-#define _IA64_REG_INDR_PMC 9004
-#define _IA64_REG_INDR_PMD 9005
-#define _IA64_REG_INDR_RR 9006
-
-#endif /* _ASM_IA64_IA64REGS_H */
diff --git a/arch/ia64/include/uapi/asm/intrinsics.h b/arch/ia64/include/uapi/asm/intrinsics.h
deleted file mode 100644
index 63f27c4ec739..000000000000
--- a/arch/ia64/include/uapi/asm/intrinsics.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Compiler-dependent intrinsics.
- *
- * Copyright (C) 2002-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#ifndef _UAPI_ASM_IA64_INTRINSICS_H
-#define _UAPI_ASM_IA64_INTRINSICS_H
-
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-/* include compiler specific intrinsics */
-#include <asm/ia64regs.h>
-#include <asm/gcc_intrin.h>
-#include <asm/cmpxchg.h>
-
-#define ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4) \
-do { \
- ia64_set_rr(0x0000000000000000UL, (val0)); \
- ia64_set_rr(0x2000000000000000UL, (val1)); \
- ia64_set_rr(0x4000000000000000UL, (val2)); \
- ia64_set_rr(0x6000000000000000UL, (val3)); \
- ia64_set_rr(0x8000000000000000UL, (val4)); \
-} while (0)
-
-/*
- * Force an unresolved reference if someone tries to use
- * ia64_fetch_and_add() with a bad value.
- */
-extern unsigned long __bad_size_for_ia64_fetch_and_add (void);
-extern unsigned long __bad_increment_for_ia64_fetch_and_add (void);
-
-#define IA64_FETCHADD(tmp,v,n,sz,sem) \
-({ \
- switch (sz) { \
- case 4: \
- tmp = ia64_fetchadd4_##sem((unsigned int *) v, n); \
- break; \
- \
- case 8: \
- tmp = ia64_fetchadd8_##sem((unsigned long *) v, n); \
- break; \
- \
- default: \
- __bad_size_for_ia64_fetch_and_add(); \
- } \
-})
-
-#define ia64_fetchadd(i,v,sem) \
-({ \
- __u64 _tmp; \
- volatile __typeof__(*(v)) *_v = (v); \
- /* Can't use a switch () here: gcc isn't always smart enough for that... */ \
- if ((i) == -16) \
- IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v)), sem); \
- else if ((i) == -8) \
- IA64_FETCHADD(_tmp, _v, -8, sizeof(*(v)), sem); \
- else if ((i) == -4) \
- IA64_FETCHADD(_tmp, _v, -4, sizeof(*(v)), sem); \
- else if ((i) == -1) \
- IA64_FETCHADD(_tmp, _v, -1, sizeof(*(v)), sem); \
- else if ((i) == 1) \
- IA64_FETCHADD(_tmp, _v, 1, sizeof(*(v)), sem); \
- else if ((i) == 4) \
- IA64_FETCHADD(_tmp, _v, 4, sizeof(*(v)), sem); \
- else if ((i) == 8) \
- IA64_FETCHADD(_tmp, _v, 8, sizeof(*(v)), sem); \
- else if ((i) == 16) \
- IA64_FETCHADD(_tmp, _v, 16, sizeof(*(v)), sem); \
- else \
- _tmp = __bad_increment_for_ia64_fetch_and_add(); \
- (__typeof__(*(v))) (_tmp); /* return old value */ \
-})
-
-#define ia64_fetch_and_add(i,v) (ia64_fetchadd(i, v, rel) + (i)) /* return new value */
-
-#endif
-
-#endif /* _UAPI_ASM_IA64_INTRINSICS_H */
diff --git a/arch/ia64/include/uapi/asm/mman.h b/arch/ia64/include/uapi/asm/mman.h
deleted file mode 100644
index ce0cc3d7509e..000000000000
--- a/arch/ia64/include/uapi/asm/mman.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Based on <asm-i386/mman.h>.
- *
- * Modified 1998-2000, 2002
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-#ifndef _UAPI_ASM_IA64_MMAN_H
-#define _UAPI_ASM_IA64_MMAN_H
-
-
-#include <asm-generic/mman.h>
-
-#define MAP_GROWSUP 0x0200 /* register stack-like segment */
-
-
-#endif /* _UAPI_ASM_IA64_MMAN_H */
diff --git a/arch/ia64/include/uapi/asm/param.h b/arch/ia64/include/uapi/asm/param.h
deleted file mode 100644
index 123ab45940b4..000000000000
--- a/arch/ia64/include/uapi/asm/param.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Fundamental kernel parameters.
- *
- * Based on <asm-i386/param.h>.
- *
- * Modified 1998, 1999, 2002-2003
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-#ifndef _UAPI_ASM_IA64_PARAM_H
-#define _UAPI_ASM_IA64_PARAM_H
-
-
-#define EXEC_PAGESIZE 65536
-
-#ifndef NOGROUP
-# define NOGROUP (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64 /* max length of hostname */
-
-#ifndef __KERNEL__
- /*
- * Technically, this is wrong, but some old apps still refer to it. The proper way to
- * get the HZ value is via sysconf(_SC_CLK_TCK).
- */
-# define HZ 1024
-#endif
-
-#endif /* _UAPI_ASM_IA64_PARAM_H */
diff --git a/arch/ia64/include/uapi/asm/posix_types.h b/arch/ia64/include/uapi/asm/posix_types.h
deleted file mode 100644
index bded40f7defe..000000000000
--- a/arch/ia64/include/uapi/asm/posix_types.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_POSIX_TYPES_H
-#define _ASM_IA64_POSIX_TYPES_H
-
-typedef unsigned long __kernel_sigset_t; /* at least 32 bits */
-
-#include <asm-generic/posix_types.h>
-
-#endif /* _ASM_IA64_POSIX_TYPES_H */
diff --git a/arch/ia64/include/uapi/asm/ptrace.h b/arch/ia64/include/uapi/asm/ptrace.h
deleted file mode 100644
index f52655b44414..000000000000
--- a/arch/ia64/include/uapi/asm/ptrace.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Copyright (C) 1998-2004 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 2003 Intel Co
- * Suresh Siddha <suresh.b.siddha@intel.com>
- * Fenghua Yu <fenghua.yu@intel.com>
- * Arun Sharma <arun.sharma@intel.com>
- *
- * 12/07/98 S. Eranian added pt_regs & switch_stack
- * 12/21/98 D. Mosberger updated to match latest code
- * 6/17/99 D. Mosberger added second unat member to "struct switch_stack"
- *
- */
-#ifndef _UAPI_ASM_IA64_PTRACE_H
-#define _UAPI_ASM_IA64_PTRACE_H
-
-/*
- * When a user process is blocked, its state looks as follows:
- *
- * +----------------------+ ------- IA64_STK_OFFSET
- * | | ^
- * | struct pt_regs | |
- * | | |
- * +----------------------+ |
- * | | |
- * | memory stack | |
- * | (growing downwards) | |
- * //.....................// |
- * |
- * //.....................// |
- * | | |
- * +----------------------+ |
- * | struct switch_stack | |
- * | | |
- * +----------------------+ |
- * | | |
- * //.....................// |
- * |
- * //.....................// |
- * | | |
- * | register stack | |
- * | (growing upwards) | |
- * | | |
- * +----------------------+ | --- IA64_RBS_OFFSET
- * | struct thread_info | | ^
- * +----------------------+ | |
- * | | | |
- * | struct task_struct | | |
- * current -> | | | |
- * +----------------------+ -------
- *
- * Note that ar.ec is not saved explicitly in pt_reg or switch_stack.
- * This is because ar.ec is saved as part of ar.pfs.
- */
-
-
-#include <asm/fpu.h>
-
-
-#ifndef __ASSEMBLY__
-
-/*
- * This struct defines the way the registers are saved on system
- * calls.
- *
- * We don't save all floating point register because the kernel
- * is compiled to use only a very small subset, so the other are
- * untouched.
- *
- * THIS STRUCTURE MUST BE A MULTIPLE 16-BYTE IN SIZE
- * (because the memory stack pointer MUST ALWAYS be aligned this way)
- *
- */
-struct pt_regs {
- /* The following registers are saved by SAVE_MIN: */
- unsigned long b6; /* scratch */
- unsigned long b7; /* scratch */
-
- unsigned long ar_csd; /* used by cmp8xchg16 (scratch) */
- unsigned long ar_ssd; /* reserved for future use (scratch) */
-
- unsigned long r8; /* scratch (return value register 0) */
- unsigned long r9; /* scratch (return value register 1) */
- unsigned long r10; /* scratch (return value register 2) */
- unsigned long r11; /* scratch (return value register 3) */
-
- unsigned long cr_ipsr; /* interrupted task's psr */
- unsigned long cr_iip; /* interrupted task's instruction pointer */
- /*
- * interrupted task's function state; if bit 63 is cleared, it
- * contains syscall's ar.pfs.pfm:
- */
- unsigned long cr_ifs;
-
- unsigned long ar_unat; /* interrupted task's NaT register (preserved) */
- unsigned long ar_pfs; /* prev function state */
- unsigned long ar_rsc; /* RSE configuration */
- /* The following two are valid only if cr_ipsr.cpl > 0 || ti->flags & _TIF_MCA_INIT */
- unsigned long ar_rnat; /* RSE NaT */
- unsigned long ar_bspstore; /* RSE bspstore */
-
- unsigned long pr; /* 64 predicate registers (1 bit each) */
- unsigned long b0; /* return pointer (bp) */
- unsigned long loadrs; /* size of dirty partition << 16 */
-
- unsigned long r1; /* the gp pointer */
- unsigned long r12; /* interrupted task's memory stack pointer */
- unsigned long r13; /* thread pointer */
-
- unsigned long ar_fpsr; /* floating point status (preserved) */
- unsigned long r15; /* scratch */
-
- /* The remaining registers are NOT saved for system calls. */
-
- unsigned long r14; /* scratch */
- unsigned long r2; /* scratch */
- unsigned long r3; /* scratch */
-
- /* The following registers are saved by SAVE_REST: */
- unsigned long r16; /* scratch */
- unsigned long r17; /* scratch */
- unsigned long r18; /* scratch */
- unsigned long r19; /* scratch */
- unsigned long r20; /* scratch */
- unsigned long r21; /* scratch */
- unsigned long r22; /* scratch */
- unsigned long r23; /* scratch */
- unsigned long r24; /* scratch */
- unsigned long r25; /* scratch */
- unsigned long r26; /* scratch */
- unsigned long r27; /* scratch */
- unsigned long r28; /* scratch */
- unsigned long r29; /* scratch */
- unsigned long r30; /* scratch */
- unsigned long r31; /* scratch */
-
- unsigned long ar_ccv; /* compare/exchange value (scratch) */
-
- /*
- * Floating point registers that the kernel considers scratch:
- */
- struct ia64_fpreg f6; /* scratch */
- struct ia64_fpreg f7; /* scratch */
- struct ia64_fpreg f8; /* scratch */
- struct ia64_fpreg f9; /* scratch */
- struct ia64_fpreg f10; /* scratch */
- struct ia64_fpreg f11; /* scratch */
-};
-
-/*
- * This structure contains the addition registers that need to
- * preserved across a context switch. This generally consists of
- * "preserved" registers.
- */
-struct switch_stack {
- unsigned long caller_unat; /* user NaT collection register (preserved) */
- unsigned long ar_fpsr; /* floating-point status register */
-
- struct ia64_fpreg f2; /* preserved */
- struct ia64_fpreg f3; /* preserved */
- struct ia64_fpreg f4; /* preserved */
- struct ia64_fpreg f5; /* preserved */
-
- struct ia64_fpreg f12; /* scratch, but untouched by kernel */
- struct ia64_fpreg f13; /* scratch, but untouched by kernel */
- struct ia64_fpreg f14; /* scratch, but untouched by kernel */
- struct ia64_fpreg f15; /* scratch, but untouched by kernel */
- struct ia64_fpreg f16; /* preserved */
- struct ia64_fpreg f17; /* preserved */
- struct ia64_fpreg f18; /* preserved */
- struct ia64_fpreg f19; /* preserved */
- struct ia64_fpreg f20; /* preserved */
- struct ia64_fpreg f21; /* preserved */
- struct ia64_fpreg f22; /* preserved */
- struct ia64_fpreg f23; /* preserved */
- struct ia64_fpreg f24; /* preserved */
- struct ia64_fpreg f25; /* preserved */
- struct ia64_fpreg f26; /* preserved */
- struct ia64_fpreg f27; /* preserved */
- struct ia64_fpreg f28; /* preserved */
- struct ia64_fpreg f29; /* preserved */
- struct ia64_fpreg f30; /* preserved */
- struct ia64_fpreg f31; /* preserved */
-
- unsigned long r4; /* preserved */
- unsigned long r5; /* preserved */
- unsigned long r6; /* preserved */
- unsigned long r7; /* preserved */
-
- unsigned long b0; /* so we can force a direct return in copy_thread */
- unsigned long b1;
- unsigned long b2;
- unsigned long b3;
- unsigned long b4;
- unsigned long b5;
-
- unsigned long ar_pfs; /* previous function state */
- unsigned long ar_lc; /* loop counter (preserved) */
- unsigned long ar_unat; /* NaT bits for r4-r7 */
- unsigned long ar_rnat; /* RSE NaT collection register */
- unsigned long ar_bspstore; /* RSE dirty base (preserved) */
- unsigned long pr; /* 64 predicate registers (1 bit each) */
-};
-
-
-/* pt_all_user_regs is used for PTRACE_GETREGS PTRACE_SETREGS */
-struct pt_all_user_regs {
- unsigned long nat;
- unsigned long cr_iip;
- unsigned long cfm;
- unsigned long cr_ipsr;
- unsigned long pr;
-
- unsigned long gr[32];
- unsigned long br[8];
- unsigned long ar[128];
- struct ia64_fpreg fr[128];
-};
-
-#endif /* !__ASSEMBLY__ */
-
-/* indices to application-registers array in pt_all_user_regs */
-#define PT_AUR_RSC 16
-#define PT_AUR_BSP 17
-#define PT_AUR_BSPSTORE 18
-#define PT_AUR_RNAT 19
-#define PT_AUR_CCV 32
-#define PT_AUR_UNAT 36
-#define PT_AUR_FPSR 40
-#define PT_AUR_PFS 64
-#define PT_AUR_LC 65
-#define PT_AUR_EC 66
-
-/*
- * The numbers chosen here are somewhat arbitrary but absolutely MUST
- * not overlap with any of the number assigned in <linux/ptrace.h>.
- */
-#define PTRACE_SINGLEBLOCK 12 /* resume execution until next branch */
-#define PTRACE_OLD_GETSIGINFO 13 /* (replaced by PTRACE_GETSIGINFO in <linux/ptrace.h>) */
-#define PTRACE_OLD_SETSIGINFO 14 /* (replaced by PTRACE_SETSIGINFO in <linux/ptrace.h>) */
-#define PTRACE_GETREGS 18 /* get all registers (pt_all_user_regs) in one shot */
-#define PTRACE_SETREGS 19 /* set all registers (pt_all_user_regs) in one shot */
-
-#define PTRACE_OLDSETOPTIONS 21
-
-#endif /* _UAPI_ASM_IA64_PTRACE_H */
diff --git a/arch/ia64/include/uapi/asm/ptrace_offsets.h b/arch/ia64/include/uapi/asm/ptrace_offsets.h
deleted file mode 100644
index 2847c18139ef..000000000000
--- a/arch/ia64/include/uapi/asm/ptrace_offsets.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_PTRACE_OFFSETS_H
-#define _ASM_IA64_PTRACE_OFFSETS_H
-
-/*
- * Copyright (C) 1999, 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-/*
- * The "uarea" that can be accessed via PEEKUSER and POKEUSER is a
- * virtual structure that would have the following definition:
- *
- * struct uarea {
- * struct ia64_fpreg fph[96]; // f32-f127
- * unsigned long nat_bits;
- * unsigned long empty1;
- * struct ia64_fpreg f2; // f2-f5
- * :
- * struct ia64_fpreg f5;
- * struct ia64_fpreg f10; // f10-f31
- * :
- * struct ia64_fpreg f31;
- * unsigned long r4; // r4-r7
- * :
- * unsigned long r7;
- * unsigned long b1; // b1-b5
- * :
- * unsigned long b5;
- * unsigned long ar_ec;
- * unsigned long ar_lc;
- * unsigned long empty2[5];
- * unsigned long cr_ipsr;
- * unsigned long cr_iip;
- * unsigned long cfm;
- * unsigned long ar_unat;
- * unsigned long ar_pfs;
- * unsigned long ar_rsc;
- * unsigned long ar_rnat;
- * unsigned long ar_bspstore;
- * unsigned long pr;
- * unsigned long b6;
- * unsigned long ar_bsp;
- * unsigned long r1;
- * unsigned long r2;
- * unsigned long r3;
- * unsigned long r12;
- * unsigned long r13;
- * unsigned long r14;
- * unsigned long r15;
- * unsigned long r8;
- * unsigned long r9;
- * unsigned long r10;
- * unsigned long r11;
- * unsigned long r16;
- * :
- * unsigned long r31;
- * unsigned long ar_ccv;
- * unsigned long ar_fpsr;
- * unsigned long b0;
- * unsigned long b7;
- * unsigned long f6;
- * unsigned long f7;
- * unsigned long f8;
- * unsigned long f9;
- * unsigned long ar_csd;
- * unsigned long ar_ssd;
- * unsigned long rsvd1[710];
- * unsigned long dbr[8];
- * unsigned long rsvd2[504];
- * unsigned long ibr[8];
- * unsigned long rsvd3[504];
- * unsigned long pmd[4];
- * }
- */
-
-/* fph: */
-#define PT_F32 0x0000
-#define PT_F33 0x0010
-#define PT_F34 0x0020
-#define PT_F35 0x0030
-#define PT_F36 0x0040
-#define PT_F37 0x0050
-#define PT_F38 0x0060
-#define PT_F39 0x0070
-#define PT_F40 0x0080
-#define PT_F41 0x0090
-#define PT_F42 0x00a0
-#define PT_F43 0x00b0
-#define PT_F44 0x00c0
-#define PT_F45 0x00d0
-#define PT_F46 0x00e0
-#define PT_F47 0x00f0
-#define PT_F48 0x0100
-#define PT_F49 0x0110
-#define PT_F50 0x0120
-#define PT_F51 0x0130
-#define PT_F52 0x0140
-#define PT_F53 0x0150
-#define PT_F54 0x0160
-#define PT_F55 0x0170
-#define PT_F56 0x0180
-#define PT_F57 0x0190
-#define PT_F58 0x01a0
-#define PT_F59 0x01b0
-#define PT_F60 0x01c0
-#define PT_F61 0x01d0
-#define PT_F62 0x01e0
-#define PT_F63 0x01f0
-#define PT_F64 0x0200
-#define PT_F65 0x0210
-#define PT_F66 0x0220
-#define PT_F67 0x0230
-#define PT_F68 0x0240
-#define PT_F69 0x0250
-#define PT_F70 0x0260
-#define PT_F71 0x0270
-#define PT_F72 0x0280
-#define PT_F73 0x0290
-#define PT_F74 0x02a0
-#define PT_F75 0x02b0
-#define PT_F76 0x02c0
-#define PT_F77 0x02d0
-#define PT_F78 0x02e0
-#define PT_F79 0x02f0
-#define PT_F80 0x0300
-#define PT_F81 0x0310
-#define PT_F82 0x0320
-#define PT_F83 0x0330
-#define PT_F84 0x0340
-#define PT_F85 0x0350
-#define PT_F86 0x0360
-#define PT_F87 0x0370
-#define PT_F88 0x0380
-#define PT_F89 0x0390
-#define PT_F90 0x03a0
-#define PT_F91 0x03b0
-#define PT_F92 0x03c0
-#define PT_F93 0x03d0
-#define PT_F94 0x03e0
-#define PT_F95 0x03f0
-#define PT_F96 0x0400
-#define PT_F97 0x0410
-#define PT_F98 0x0420
-#define PT_F99 0x0430
-#define PT_F100 0x0440
-#define PT_F101 0x0450
-#define PT_F102 0x0460
-#define PT_F103 0x0470
-#define PT_F104 0x0480
-#define PT_F105 0x0490
-#define PT_F106 0x04a0
-#define PT_F107 0x04b0
-#define PT_F108 0x04c0
-#define PT_F109 0x04d0
-#define PT_F110 0x04e0
-#define PT_F111 0x04f0
-#define PT_F112 0x0500
-#define PT_F113 0x0510
-#define PT_F114 0x0520
-#define PT_F115 0x0530
-#define PT_F116 0x0540
-#define PT_F117 0x0550
-#define PT_F118 0x0560
-#define PT_F119 0x0570
-#define PT_F120 0x0580
-#define PT_F121 0x0590
-#define PT_F122 0x05a0
-#define PT_F123 0x05b0
-#define PT_F124 0x05c0
-#define PT_F125 0x05d0
-#define PT_F126 0x05e0
-#define PT_F127 0x05f0
-
-#define PT_NAT_BITS 0x0600
-
-#define PT_F2 0x0610
-#define PT_F3 0x0620
-#define PT_F4 0x0630
-#define PT_F5 0x0640
-#define PT_F10 0x0650
-#define PT_F11 0x0660
-#define PT_F12 0x0670
-#define PT_F13 0x0680
-#define PT_F14 0x0690
-#define PT_F15 0x06a0
-#define PT_F16 0x06b0
-#define PT_F17 0x06c0
-#define PT_F18 0x06d0
-#define PT_F19 0x06e0
-#define PT_F20 0x06f0
-#define PT_F21 0x0700
-#define PT_F22 0x0710
-#define PT_F23 0x0720
-#define PT_F24 0x0730
-#define PT_F25 0x0740
-#define PT_F26 0x0750
-#define PT_F27 0x0760
-#define PT_F28 0x0770
-#define PT_F29 0x0780
-#define PT_F30 0x0790
-#define PT_F31 0x07a0
-#define PT_R4 0x07b0
-#define PT_R5 0x07b8
-#define PT_R6 0x07c0
-#define PT_R7 0x07c8
-
-#define PT_B1 0x07d8
-#define PT_B2 0x07e0
-#define PT_B3 0x07e8
-#define PT_B4 0x07f0
-#define PT_B5 0x07f8
-
-#define PT_AR_EC 0x0800
-#define PT_AR_LC 0x0808
-
-#define PT_CR_IPSR 0x0830
-#define PT_CR_IIP 0x0838
-#define PT_CFM 0x0840
-#define PT_AR_UNAT 0x0848
-#define PT_AR_PFS 0x0850
-#define PT_AR_RSC 0x0858
-#define PT_AR_RNAT 0x0860
-#define PT_AR_BSPSTORE 0x0868
-#define PT_PR 0x0870
-#define PT_B6 0x0878
-#define PT_AR_BSP 0x0880 /* note: this points to the *end* of the backing store! */
-#define PT_R1 0x0888
-#define PT_R2 0x0890
-#define PT_R3 0x0898
-#define PT_R12 0x08a0
-#define PT_R13 0x08a8
-#define PT_R14 0x08b0
-#define PT_R15 0x08b8
-#define PT_R8 0x08c0
-#define PT_R9 0x08c8
-#define PT_R10 0x08d0
-#define PT_R11 0x08d8
-#define PT_R16 0x08e0
-#define PT_R17 0x08e8
-#define PT_R18 0x08f0
-#define PT_R19 0x08f8
-#define PT_R20 0x0900
-#define PT_R21 0x0908
-#define PT_R22 0x0910
-#define PT_R23 0x0918
-#define PT_R24 0x0920
-#define PT_R25 0x0928
-#define PT_R26 0x0930
-#define PT_R27 0x0938
-#define PT_R28 0x0940
-#define PT_R29 0x0948
-#define PT_R30 0x0950
-#define PT_R31 0x0958
-#define PT_AR_CCV 0x0960
-#define PT_AR_FPSR 0x0968
-#define PT_B0 0x0970
-#define PT_B7 0x0978
-#define PT_F6 0x0980
-#define PT_F7 0x0990
-#define PT_F8 0x09a0
-#define PT_F9 0x09b0
-#define PT_AR_CSD 0x09c0
-#define PT_AR_SSD 0x09c8
-
-#define PT_DBR 0x2000 /* data breakpoint registers */
-#define PT_IBR 0x3000 /* instruction breakpoint registers */
-#define PT_PMD 0x4000 /* performance monitoring counters */
-
-#endif /* _ASM_IA64_PTRACE_OFFSETS_H */
diff --git a/arch/ia64/include/uapi/asm/resource.h b/arch/ia64/include/uapi/asm/resource.h
deleted file mode 100644
index d488d2b22ac4..000000000000
--- a/arch/ia64/include/uapi/asm/resource.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_RESOURCE_H
-#define _ASM_IA64_RESOURCE_H
-
-#include <asm/ustack.h>
-#include <asm-generic/resource.h>
-
-#endif /* _ASM_IA64_RESOURCE_H */
diff --git a/arch/ia64/include/uapi/asm/rse.h b/arch/ia64/include/uapi/asm/rse.h
deleted file mode 100644
index 6d260af571c5..000000000000
--- a/arch/ia64/include/uapi/asm/rse.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_RSE_H
-#define _ASM_IA64_RSE_H
-
-/*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * Register stack engine related helper functions. This file may be
- * used in applications, so be careful about the name-space and give
- * some consideration to non-GNU C compilers (though __inline__ is
- * fine).
- */
-
-static __inline__ unsigned long
-ia64_rse_slot_num (unsigned long *addr)
-{
- return (((unsigned long) addr) >> 3) & 0x3f;
-}
-
-/*
- * Return TRUE if ADDR is the address of an RNAT slot.
- */
-static __inline__ unsigned long
-ia64_rse_is_rnat_slot (unsigned long *addr)
-{
- return ia64_rse_slot_num(addr) == 0x3f;
-}
-
-/*
- * Returns the address of the RNAT slot that covers the slot at
- * address SLOT_ADDR.
- */
-static __inline__ unsigned long *
-ia64_rse_rnat_addr (unsigned long *slot_addr)
-{
- return (unsigned long *) ((unsigned long) slot_addr | (0x3f << 3));
-}
-
-/*
- * Calculate the number of registers in the dirty partition starting at BSPSTORE and
- * ending at BSP. This isn't simply (BSP-BSPSTORE)/8 because every 64th slot stores
- * ar.rnat.
- */
-static __inline__ unsigned long
-ia64_rse_num_regs (unsigned long *bspstore, unsigned long *bsp)
-{
- unsigned long slots = (bsp - bspstore);
-
- return slots - (ia64_rse_slot_num(bspstore) + slots)/0x40;
-}
-
-/*
- * The inverse of the above: given bspstore and the number of
- * registers, calculate ar.bsp.
- */
-static __inline__ unsigned long *
-ia64_rse_skip_regs (unsigned long *addr, long num_regs)
-{
- long delta = ia64_rse_slot_num(addr) + num_regs;
-
- if (num_regs < 0)
- delta -= 0x3e;
- return addr + num_regs + delta/0x3f;
-}
-
-#endif /* _ASM_IA64_RSE_H */
diff --git a/arch/ia64/include/uapi/asm/setup.h b/arch/ia64/include/uapi/asm/setup.h
deleted file mode 100644
index 8d13ce8fb03a..000000000000
--- a/arch/ia64/include/uapi/asm/setup.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef __IA64_SETUP_H
-#define __IA64_SETUP_H
-
-#define COMMAND_LINE_SIZE 2048
-
-extern struct ia64_boot_param {
- __u64 command_line; /* physical address of command line arguments */
- __u64 efi_systab; /* physical address of EFI system table */
- __u64 efi_memmap; /* physical address of EFI memory map */
- __u64 efi_memmap_size; /* size of EFI memory map */
- __u64 efi_memdesc_size; /* size of an EFI memory map descriptor */
- __u32 efi_memdesc_version; /* memory descriptor version */
- struct {
- __u16 num_cols; /* number of columns on console output device */
- __u16 num_rows; /* number of rows on console output device */
- __u16 orig_x; /* cursor's x position */
- __u16 orig_y; /* cursor's y position */
- } console_info;
- __u64 fpswa; /* physical address of the fpswa interface */
- __u64 initrd_start;
- __u64 initrd_size;
-} *ia64_boot_param;
-
-#endif
diff --git a/arch/ia64/include/uapi/asm/sigcontext.h b/arch/ia64/include/uapi/asm/sigcontext.h
deleted file mode 100644
index 1bb6f0f2bd73..000000000000
--- a/arch/ia64/include/uapi/asm/sigcontext.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_SIGCONTEXT_H
-#define _ASM_IA64_SIGCONTEXT_H
-
-/*
- * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <asm/fpu.h>
-
-#define IA64_SC_FLAG_ONSTACK_BIT 0 /* is handler running on signal stack? */
-#define IA64_SC_FLAG_IN_SYSCALL_BIT 1 /* did signal interrupt a syscall? */
-#define IA64_SC_FLAG_FPH_VALID_BIT 2 /* is state in f[32]-f[127] valid? */
-
-#define IA64_SC_FLAG_ONSTACK (1 << IA64_SC_FLAG_ONSTACK_BIT)
-#define IA64_SC_FLAG_IN_SYSCALL (1 << IA64_SC_FLAG_IN_SYSCALL_BIT)
-#define IA64_SC_FLAG_FPH_VALID (1 << IA64_SC_FLAG_FPH_VALID_BIT)
-
-# ifndef __ASSEMBLY__
-
-/*
- * Note on handling of register backing store: sc_ar_bsp contains the address that would
- * be found in ar.bsp after executing a "cover" instruction the context in which the
- * signal was raised. If signal delivery required switching to an alternate signal stack
- * (sc_rbs_base is not NULL), the "dirty" partition (as it would exist after executing the
- * imaginary "cover" instruction) is backed by the *alternate* signal stack, not the
- * original one. In this case, sc_rbs_base contains the base address of the new register
- * backing store. The number of registers in the dirty partition can be calculated as:
- *
- * ndirty = ia64_rse_num_regs(sc_rbs_base, sc_rbs_base + (sc_loadrs >> 16))
- *
- */
-
-struct sigcontext {
- unsigned long sc_flags; /* see manifest constants above */
- unsigned long sc_nat; /* bit i == 1 iff scratch reg gr[i] is a NaT */
- stack_t sc_stack; /* previously active stack */
-
- unsigned long sc_ip; /* instruction pointer */
- unsigned long sc_cfm; /* current frame marker */
- unsigned long sc_um; /* user mask bits */
- unsigned long sc_ar_rsc; /* register stack configuration register */
- unsigned long sc_ar_bsp; /* backing store pointer */
- unsigned long sc_ar_rnat; /* RSE NaT collection register */
- unsigned long sc_ar_ccv; /* compare and exchange compare value register */
- unsigned long sc_ar_unat; /* ar.unat of interrupted context */
- unsigned long sc_ar_fpsr; /* floating-point status register */
- unsigned long sc_ar_pfs; /* previous function state */
- unsigned long sc_ar_lc; /* loop count register */
- unsigned long sc_pr; /* predicate registers */
- unsigned long sc_br[8]; /* branch registers */
- /* Note: sc_gr[0] is used as the "uc_link" member of ucontext_t */
- unsigned long sc_gr[32]; /* general registers (static partition) */
- struct ia64_fpreg sc_fr[128]; /* floating-point registers */
-
- unsigned long sc_rbs_base; /* NULL or new base of sighandler's rbs */
- unsigned long sc_loadrs; /* see description above */
-
- unsigned long sc_ar25; /* cmp8xchg16 uses this */
- unsigned long sc_ar26; /* rsvd for scratch use */
- unsigned long sc_rsvd[12]; /* reserved for future use */
- /*
- * The mask must come last so we can increase _NSIG_WORDS
- * without breaking binary compatibility.
- */
- sigset_t sc_mask; /* signal mask to restore after handler returns */
-};
-
-# endif /* __ASSEMBLY__ */
-#endif /* _ASM_IA64_SIGCONTEXT_H */
diff --git a/arch/ia64/include/uapi/asm/siginfo.h b/arch/ia64/include/uapi/asm/siginfo.h
deleted file mode 100644
index 796af1ccaa7e..000000000000
--- a/arch/ia64/include/uapi/asm/siginfo.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Based on <asm-i386/siginfo.h>.
- *
- * Modified 1998-2002
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-#ifndef _UAPI_ASM_IA64_SIGINFO_H
-#define _UAPI_ASM_IA64_SIGINFO_H
-
-
-#include <asm-generic/siginfo.h>
-
-#define si_imm _sifields._sigfault._imm /* as per UNIX SysV ABI spec */
-#define si_flags _sifields._sigfault._flags
-/*
- * si_isr is valid for SIGILL, SIGFPE, SIGSEGV, SIGBUS, and SIGTRAP provided that
- * si_code is non-zero and __ISR_VALID is set in si_flags.
- */
-#define si_isr _sifields._sigfault._isr
-
-/*
- * Flag values for si_flags:
- */
-#define __ISR_VALID_BIT 0
-#define __ISR_VALID (1 << __ISR_VALID_BIT)
-
-#endif /* _UAPI_ASM_IA64_SIGINFO_H */
diff --git a/arch/ia64/include/uapi/asm/signal.h b/arch/ia64/include/uapi/asm/signal.h
deleted file mode 100644
index 63d574e802a2..000000000000
--- a/arch/ia64/include/uapi/asm/signal.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Modified 1998-2001, 2003
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- *
- * Unfortunately, this file is being included by bits/signal.h in
- * glibc-2.x. Hence the #ifdef __KERNEL__ ugliness.
- */
-#ifndef _UAPI_ASM_IA64_SIGNAL_H
-#define _UAPI_ASM_IA64_SIGNAL_H
-
-
-#define SIGHUP 1
-#define SIGINT 2
-#define SIGQUIT 3
-#define SIGILL 4
-#define SIGTRAP 5
-#define SIGABRT 6
-#define SIGIOT 6
-#define SIGBUS 7
-#define SIGFPE 8
-#define SIGKILL 9
-#define SIGUSR1 10
-#define SIGSEGV 11
-#define SIGUSR2 12
-#define SIGPIPE 13
-#define SIGALRM 14
-#define SIGTERM 15
-#define SIGSTKFLT 16
-#define SIGCHLD 17
-#define SIGCONT 18
-#define SIGSTOP 19
-#define SIGTSTP 20
-#define SIGTTIN 21
-#define SIGTTOU 22
-#define SIGURG 23
-#define SIGXCPU 24
-#define SIGXFSZ 25
-#define SIGVTALRM 26
-#define SIGPROF 27
-#define SIGWINCH 28
-#define SIGIO 29
-#define SIGPOLL SIGIO
-/*
-#define SIGLOST 29
-*/
-#define SIGPWR 30
-#define SIGSYS 31
-/* signal 31 is no longer "unused", but the SIGUNUSED macro remains for backwards compatibility */
-#define SIGUNUSED 31
-
-/* These should not be considered constants from userland. */
-#define SIGRTMIN 32
-#define SIGRTMAX _NSIG
-
-#define SA_RESTORER 0x04000000
-
-/*
- * The minimum stack size needs to be fairly large because we want to
- * be sure that an app compiled for today's CPUs will continue to run
- * on all future CPU models. The CPU model matters because the signal
- * frame needs to have space for the complete machine state, including
- * all physical stacked registers. The number of physical stacked
- * registers is CPU model dependent, but given that the width of
- * ar.rsc.loadrs is 14 bits, we can assume that they'll never take up
- * more than 16KB of space.
- */
-#if 1
- /*
- * This is a stupid typo: the value was _meant_ to be 131072 (0x20000), but I typed it
- * in wrong. ;-( To preserve backwards compatibility, we leave the kernel at the
- * incorrect value and fix libc only.
- */
-# define MINSIGSTKSZ 131027 /* min. stack size for sigaltstack() */
-#else
-# define MINSIGSTKSZ 131072 /* min. stack size for sigaltstack() */
-#endif
-#define SIGSTKSZ 262144 /* default stack size for sigaltstack() */
-
-
-#include <asm-generic/signal-defs.h>
-
-# ifndef __ASSEMBLY__
-
-# include <linux/types.h>
-
-/* Avoid too many header ordering problems. */
-struct siginfo;
-
-typedef struct sigaltstack {
- void __user *ss_sp;
- int ss_flags;
- __kernel_size_t ss_size;
-} stack_t;
-
-
-# endif /* !__ASSEMBLY__ */
-#endif /* _UAPI_ASM_IA64_SIGNAL_H */
diff --git a/arch/ia64/include/uapi/asm/stat.h b/arch/ia64/include/uapi/asm/stat.h
deleted file mode 100644
index 3265ed5aac0f..000000000000
--- a/arch/ia64/include/uapi/asm/stat.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_STAT_H
-#define _ASM_IA64_STAT_H
-
-/*
- * Modified 1998, 1999
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-struct stat {
- unsigned long st_dev;
- unsigned long st_ino;
- unsigned long st_nlink;
- unsigned int st_mode;
- unsigned int st_uid;
- unsigned int st_gid;
- unsigned int __pad0;
- unsigned long st_rdev;
- unsigned long st_size;
- unsigned long st_atime;
- unsigned long st_atime_nsec;
- unsigned long st_mtime;
- unsigned long st_mtime_nsec;
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
- unsigned long st_blksize;
- long st_blocks;
- unsigned long __unused[3];
-};
-
-#define STAT_HAVE_NSEC 1
-
-struct ia64_oldstat {
- unsigned int st_dev;
- unsigned int st_ino;
- unsigned int st_mode;
- unsigned int st_nlink;
- unsigned int st_uid;
- unsigned int st_gid;
- unsigned int st_rdev;
- unsigned int __pad1;
- unsigned long st_size;
- unsigned long st_atime;
- unsigned long st_mtime;
- unsigned long st_ctime;
- unsigned int st_blksize;
- int st_blocks;
- unsigned int __unused1;
- unsigned int __unused2;
-};
-
-#endif /* _ASM_IA64_STAT_H */
diff --git a/arch/ia64/include/uapi/asm/statfs.h b/arch/ia64/include/uapi/asm/statfs.h
deleted file mode 100644
index de3bae4f137d..000000000000
--- a/arch/ia64/include/uapi/asm/statfs.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_STATFS_H
-#define _ASM_IA64_STATFS_H
-
-/*
- * Based on <asm-i386/statfs.h>.
- *
- * Modified 1998, 1999, 2003
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-/*
- * We need compat_statfs64 to be packed, because the i386 ABI won't
- * add padding at the end to bring it to a multiple of 8 bytes, but
- * the IA64 ABI will.
- */
-#define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4)))
-
-#include <asm-generic/statfs.h>
-
-#endif /* _ASM_IA64_STATFS_H */
diff --git a/arch/ia64/include/uapi/asm/swab.h b/arch/ia64/include/uapi/asm/swab.h
deleted file mode 100644
index 79f3fef1a05e..000000000000
--- a/arch/ia64/include/uapi/asm/swab.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_SWAB_H
-#define _ASM_IA64_SWAB_H
-
-/*
- * Modified 1998, 1999
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
- */
-
-#include <linux/types.h>
-#include <asm/intrinsics.h>
-#include <linux/compiler.h>
-
-static __inline__ __attribute_const__ __u64 __arch_swab64(__u64 x)
-{
- __u64 result;
-
- result = ia64_mux1(x, ia64_mux1_rev);
- return result;
-}
-#define __arch_swab64 __arch_swab64
-
-static __inline__ __attribute_const__ __u32 __arch_swab32(__u32 x)
-{
- return __arch_swab64(x) >> 32;
-}
-#define __arch_swab32 __arch_swab32
-
-static __inline__ __attribute_const__ __u16 __arch_swab16(__u16 x)
-{
- return __arch_swab64(x) >> 48;
-}
-#define __arch_swab16 __arch_swab16
-
-#endif /* _ASM_IA64_SWAB_H */
diff --git a/arch/ia64/include/uapi/asm/types.h b/arch/ia64/include/uapi/asm/types.h
deleted file mode 100644
index 2000de474be6..000000000000
--- a/arch/ia64/include/uapi/asm/types.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * This file is never included by application software unless explicitly
- * requested (e.g., via linux/types.h) in which case the application is
- * Linux specific so (user-) name space pollution is not a major issue.
- * However, for interoperability, libraries still need to be careful to
- * avoid naming clashes.
- *
- * Based on <asm-alpha/types.h>.
- *
- * Modified 1998-2000, 2002
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-#ifndef _UAPI_ASM_IA64_TYPES_H
-#define _UAPI_ASM_IA64_TYPES_H
-
-
-#ifndef __KERNEL__
-#include <asm-generic/int-l64.h>
-#endif
-
-#ifdef __ASSEMBLY__
-# define __IA64_UL(x) (x)
-# define __IA64_UL_CONST(x) x
-
-#else
-# define __IA64_UL(x) ((unsigned long)(x))
-# define __IA64_UL_CONST(x) x##UL
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _UAPI_ASM_IA64_TYPES_H */
diff --git a/arch/ia64/include/uapi/asm/ucontext.h b/arch/ia64/include/uapi/asm/ucontext.h
deleted file mode 100644
index 46f51e535e04..000000000000
--- a/arch/ia64/include/uapi/asm/ucontext.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ASM_IA64_UCONTEXT_H
-#define _ASM_IA64_UCONTEXT_H
-
-struct ucontext {
- struct sigcontext uc_mcontext;
-};
-
-#define uc_link uc_mcontext.sc_gr[0] /* wrong type; nobody cares */
-#define uc_sigmask uc_mcontext.sc_sigmask
-#define uc_stack uc_mcontext.sc_stack
-
-#endif /* _ASM_IA64_UCONTEXT_H */
diff --git a/arch/ia64/include/uapi/asm/unistd.h b/arch/ia64/include/uapi/asm/unistd.h
deleted file mode 100644
index 013e0bcacc39..000000000000
--- a/arch/ia64/include/uapi/asm/unistd.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * IA-64 Linux syscall numbers and inline-functions.
- *
- * Copyright (C) 1998-2005 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#ifndef _UAPI_ASM_IA64_UNISTD_H
-#define _UAPI_ASM_IA64_UNISTD_H
-
-
-#include <asm/break.h>
-
-#define __BREAK_SYSCALL __IA64_BREAK_SYSCALL
-
-#define __NR_Linux 1024
-
-#define __NR_umount __NR_umount2
-
-#include <asm/unistd_64.h>
-
-#endif /* _UAPI_ASM_IA64_UNISTD_H */
diff --git a/arch/ia64/include/uapi/asm/ustack.h b/arch/ia64/include/uapi/asm/ustack.h
deleted file mode 100644
index 703cc5f546ff..000000000000
--- a/arch/ia64/include/uapi/asm/ustack.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _UAPI_ASM_IA64_USTACK_H
-#define _UAPI_ASM_IA64_USTACK_H
-
-/*
- * Constants for the user stack size
- */
-
-
-/* Make a default stack size of 2GiB */
-#define DEFAULT_USER_STACK_SIZE (1UL << 31)
-
-#endif /* _UAPI_ASM_IA64_USTACK_H */
diff --git a/arch/ia64/install.sh b/arch/ia64/install.sh
deleted file mode 100755
index 2d4b66a9f362..000000000000
--- a/arch/ia64/install.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License. See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1995 by Linus Torvalds
-#
-# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
-#
-# "make install" script for ia64 architecture
-#
-# Arguments:
-# $1 - kernel version
-# $2 - kernel image file
-# $3 - kernel map file
-# $4 - default install path (blank if root directory)
-
-if [ -f $4/vmlinuz ]; then
- mv $4/vmlinuz $4/vmlinuz.old
-fi
-
-if [ -f $4/System.map ]; then
- mv $4/System.map $4/System.old
-fi
-
-cat $2 > $4/vmlinuz
-cp $3 $4/System.map
-
-test -x /usr/sbin/elilo && /usr/sbin/elilo
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
deleted file mode 100644
index d7e1cabee2ec..000000000000
--- a/arch/ia64/kernel/Makefile
+++ /dev/null
@@ -1,46 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the linux kernel.
-#
-
-ifdef CONFIG_DYNAMIC_FTRACE
-CFLAGS_REMOVE_ftrace.o = -pg
-endif
-
-extra-y := vmlinux.lds
-
-obj-y := head.o entry.o efi.o efi_stub.o gate-data.o fsys.o irq.o irq_ia64.o \
- irq_lsapic.o ivt.o pal.o patch.o process.o ptrace.o sal.o \
- salinfo.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
- unwind.o mca.o mca_asm.o topology.o dma-mapping.o iosapic.o acpi.o \
- acpi-ext.o
-
-obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
-
-obj-$(CONFIG_IA64_PALINFO) += palinfo.o
-obj-$(CONFIG_MODULES) += module.o
-obj-$(CONFIG_SMP) += smp.o smpboot.o
-obj-$(CONFIG_NUMA) += numa.o
-obj-$(CONFIG_IA64_CYCLONE) += cyclone.o
-obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
-obj-$(CONFIG_KPROBES) += kprobes.o
-obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
-obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
-obj-$(CONFIG_AUDIT) += audit.o
-obj-y += msi_ia64.o
-mca_recovery-y += mca_drv.o mca_drv_asm.o
-obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o
-obj-$(CONFIG_STACKTRACE) += stacktrace.o
-
-obj-$(CONFIG_IA64_ESI) += esi.o esi_stub.o # must be in kernel proper
-obj-$(CONFIG_INTEL_IOMMU) += pci-dma.o
-
-obj-$(CONFIG_ELF_CORE) += elfcore.o
-
-# fp_emulate() expects f2-f5,f16-f31 to contain the user-level state.
-CFLAGS_traps.o += -mfixed-range=f2-f5,f16-f31
-
-# The gate DSO image is built using a special linker script.
-include $(srctree)/$(src)/Makefile.gate
diff --git a/arch/ia64/kernel/Makefile.gate b/arch/ia64/kernel/Makefile.gate
deleted file mode 100644
index 846867bff6d6..000000000000
--- a/arch/ia64/kernel/Makefile.gate
+++ /dev/null
@@ -1,29 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# The gate DSO image is built using a special linker script.
-
-targets += gate.so gate.lds gate.o gate-dummy.o
-
-obj-y += gate-syms.o
-
-CPPFLAGS_gate.lds := -P -C -U$(ARCH)
-
-quiet_cmd_gate = GATE $@
- cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@
-
-GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1 \
- -Wl,--hash-style=sysv
-$(obj)/gate.so: $(obj)/gate.lds $(obj)/gate.o FORCE
- $(call if_changed,gate)
-
-GATECFLAGS_gate-dummy.o = -r
-$(obj)/gate-dummy.o: $(obj)/gate.lds $(obj)/gate.o FORCE
- $(call if_changed,gate)
-
-LDFLAGS_gate-syms.o := -r -R
-$(obj)/gate-syms.o: $(obj)/gate-dummy.o FORCE
- $(call if_changed,ld)
-
-# gate-data.o contains the gate DSO image as data in section .data..gate.
-# We must build gate.so before we can assemble it.
-# Note: kbuild does not track this dependency due to usage of .incbin
-$(obj)/gate-data.o: $(obj)/gate.so
diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c
deleted file mode 100644
index 42cd21480833..000000000000
--- a/arch/ia64/kernel/acpi-ext.c
+++ /dev/null
@@ -1,101 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P.
- * Alex Williamson <alex.williamson@hp.com>
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/acpi.h>
-
-#include <asm/acpi-ext.h>
-
-/*
- * Device CSRs that do not appear in PCI config space should be described
- * via ACPI. This would normally be done with Address Space Descriptors
- * marked as "consumer-only," but old versions of Windows and Linux ignore
- * the producer/consumer flag, so HP invented a vendor-defined resource to
- * describe the location and size of CSR space.
- */
-
-struct acpi_vendor_uuid hp_ccsr_uuid = {
- .subtype = 2,
- .data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
- 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
-};
-
-static acpi_status hp_ccsr_locate(acpi_handle obj, u64 *base, u64 *length)
-{
- acpi_status status;
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_resource *resource;
- struct acpi_resource_vendor_typed *vendor;
-
- status = acpi_get_vendor_resource(obj, METHOD_NAME__CRS, &hp_ccsr_uuid,
- &buffer);
-
- resource = buffer.pointer;
- vendor = &resource->data.vendor_typed;
-
- if (ACPI_FAILURE(status) || vendor->byte_length < 16) {
- status = AE_NOT_FOUND;
- goto exit;
- }
-
- memcpy(base, vendor->byte_data, sizeof(*base));
- memcpy(length, vendor->byte_data + 8, sizeof(*length));
-
- exit:
- kfree(buffer.pointer);
- return status;
-}
-
-struct csr_space {
- u64 base;
- u64 length;
-};
-
-static acpi_status find_csr_space(struct acpi_resource *resource, void *data)
-{
- struct csr_space *space = data;
- struct acpi_resource_address64 addr;
- acpi_status status;
-
- status = acpi_resource_to_address64(resource, &addr);
- if (ACPI_SUCCESS(status) &&
- addr.resource_type == ACPI_MEMORY_RANGE &&
- addr.address.address_length &&
- addr.producer_consumer == ACPI_CONSUMER) {
- space->base = addr.address.minimum;
- space->length = addr.address.address_length;
- return AE_CTRL_TERMINATE;
- }
- return AE_OK; /* keep looking */
-}
-
-static acpi_status hp_crs_locate(acpi_handle obj, u64 *base, u64 *length)
-{
- struct csr_space space = { 0, 0 };
-
- acpi_walk_resources(obj, METHOD_NAME__CRS, find_csr_space, &space);
- if (!space.length)
- return AE_NOT_FOUND;
-
- *base = space.base;
- *length = space.length;
- return AE_OK;
-}
-
-acpi_status hp_acpi_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
-{
- acpi_status status;
-
- status = hp_ccsr_locate(obj, csr_base, csr_length);
- if (ACPI_SUCCESS(status))
- return status;
-
- return hp_crs_locate(obj, csr_base, csr_length);
-}
-EXPORT_SYMBOL(hp_acpi_csr_space);
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
deleted file mode 100644
index 41e8fe55cd98..000000000000
--- a/arch/ia64/kernel/acpi.c
+++ /dev/null
@@ -1,913 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * acpi.c - Architecture-Specific Low-Level ACPI Support
- *
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 2000, 2002-2003 Hewlett-Packard Co.
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2000 Intel Corp.
- * Copyright (C) 2000,2001 J.I. Lee <jung-ik.lee@intel.com>
- * Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
- * Copyright (C) 2001 Jenna Hall <jenna.s.hall@intel.com>
- * Copyright (C) 2001 Takayoshi Kochi <t-kochi@bq.jp.nec.com>
- * Copyright (C) 2002 Erich Focht <efocht@ess.nec.de>
- * Copyright (C) 2004 Ashok Raj <ashok.raj@intel.com>
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/irq.h>
-#include <linux/acpi.h>
-#include <linux/efi.h>
-#include <linux/mmzone.h>
-#include <linux/nodemask.h>
-#include <linux/slab.h>
-#include <acpi/processor.h>
-#include <asm/io.h>
-#include <asm/iosapic.h>
-#include <asm/page.h>
-#include <asm/numa.h>
-#include <asm/sal.h>
-#include <asm/cyclone.h>
-
-#define PREFIX "ACPI: "
-
-int acpi_lapic;
-unsigned int acpi_cpei_override;
-unsigned int acpi_cpei_phys_cpuid;
-
-#define ACPI_MAX_PLATFORM_INTERRUPTS 256
-
-/* Array to record platform interrupt vectors for generic interrupt routing. */
-int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = {
- [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1
-};
-
-enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC;
-
-/*
- * Interrupt routing API for device drivers. Provides interrupt vector for
- * a generic platform event. Currently only CPEI is implemented.
- */
-int acpi_request_vector(u32 int_type)
-{
- int vector = -1;
-
- if (int_type < ACPI_MAX_PLATFORM_INTERRUPTS) {
- /* corrected platform error interrupt */
- vector = platform_intr_list[int_type];
- } else
- printk(KERN_ERR
- "acpi_request_vector(): invalid interrupt type\n");
- return vector;
-}
-
-void __init __iomem *__acpi_map_table(unsigned long phys, unsigned long size)
-{
- return __va(phys);
-}
-
-void __init __acpi_unmap_table(void __iomem *map, unsigned long size)
-{
-}
-
-/* --------------------------------------------------------------------------
- Boot-time Table Parsing
- -------------------------------------------------------------------------- */
-
-static int available_cpus __initdata;
-struct acpi_table_madt *acpi_madt __initdata;
-static u8 has_8259;
-
-static int __init
-acpi_parse_lapic_addr_ovr(union acpi_subtable_headers * header,
- const unsigned long end)
-{
- struct acpi_madt_local_apic_override *lapic;
-
- lapic = (struct acpi_madt_local_apic_override *)header;
-
- if (BAD_MADT_ENTRY(lapic, end))
- return -EINVAL;
-
- if (lapic->address) {
- iounmap(ipi_base_addr);
- ipi_base_addr = ioremap(lapic->address, 0);
- }
- return 0;
-}
-
-static int __init
-acpi_parse_lsapic(union acpi_subtable_headers *header, const unsigned long end)
-{
- struct acpi_madt_local_sapic *lsapic;
-
- lsapic = (struct acpi_madt_local_sapic *)header;
-
- /*Skip BAD_MADT_ENTRY check, as lsapic size could vary */
-
- if (lsapic->lapic_flags & ACPI_MADT_ENABLED) {
-#ifdef CONFIG_SMP
- smp_boot_data.cpu_phys_id[available_cpus] =
- (lsapic->id << 8) | lsapic->eid;
-#endif
- ++available_cpus;
- }
-
- total_cpus++;
- return 0;
-}
-
-static int __init
-acpi_parse_lapic_nmi(union acpi_subtable_headers * header, const unsigned long end)
-{
- struct acpi_madt_local_apic_nmi *lacpi_nmi;
-
- lacpi_nmi = (struct acpi_madt_local_apic_nmi *)header;
-
- if (BAD_MADT_ENTRY(lacpi_nmi, end))
- return -EINVAL;
-
- /* TBD: Support lapic_nmi entries */
- return 0;
-}
-
-static int __init
-acpi_parse_iosapic(union acpi_subtable_headers * header, const unsigned long end)
-{
- struct acpi_madt_io_sapic *iosapic;
-
- iosapic = (struct acpi_madt_io_sapic *)header;
-
- if (BAD_MADT_ENTRY(iosapic, end))
- return -EINVAL;
-
- return iosapic_init(iosapic->address, iosapic->global_irq_base);
-}
-
-static unsigned int __initdata acpi_madt_rev;
-
-static int __init
-acpi_parse_plat_int_src(union acpi_subtable_headers * header,
- const unsigned long end)
-{
- struct acpi_madt_interrupt_source *plintsrc;
- int vector;
-
- plintsrc = (struct acpi_madt_interrupt_source *)header;
-
- if (BAD_MADT_ENTRY(plintsrc, end))
- return -EINVAL;
-
- /*
- * Get vector assignment for this interrupt, set attributes,
- * and program the IOSAPIC routing table.
- */
- vector = iosapic_register_platform_intr(plintsrc->type,
- plintsrc->global_irq,
- plintsrc->io_sapic_vector,
- plintsrc->eid,
- plintsrc->id,
- ((plintsrc->inti_flags & ACPI_MADT_POLARITY_MASK) ==
- ACPI_MADT_POLARITY_ACTIVE_HIGH) ?
- IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
- ((plintsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) ==
- ACPI_MADT_TRIGGER_EDGE) ?
- IOSAPIC_EDGE : IOSAPIC_LEVEL);
-
- platform_intr_list[plintsrc->type] = vector;
- if (acpi_madt_rev > 1) {
- acpi_cpei_override = plintsrc->flags & ACPI_MADT_CPEI_OVERRIDE;
- }
-
- /*
- * Save the physical id, so we can check when its being removed
- */
- acpi_cpei_phys_cpuid = ((plintsrc->id << 8) | (plintsrc->eid)) & 0xffff;
-
- return 0;
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-unsigned int can_cpei_retarget(void)
-{
- extern int cpe_vector;
- extern unsigned int force_cpei_retarget;
-
- /*
- * Only if CPEI is supported and the override flag
- * is present, otherwise return that its re-targettable
- * if we are in polling mode.
- */
- if (cpe_vector > 0) {
- if (acpi_cpei_override || force_cpei_retarget)
- return 1;
- else
- return 0;
- }
- return 1;
-}
-
-unsigned int is_cpu_cpei_target(unsigned int cpu)
-{
- unsigned int logical_id;
-
- logical_id = cpu_logical_id(acpi_cpei_phys_cpuid);
-
- if (logical_id == cpu)
- return 1;
- else
- return 0;
-}
-
-void set_cpei_target_cpu(unsigned int cpu)
-{
- acpi_cpei_phys_cpuid = cpu_physical_id(cpu);
-}
-#endif
-
-unsigned int get_cpei_target_cpu(void)
-{
- return acpi_cpei_phys_cpuid;
-}
-
-static int __init
-acpi_parse_int_src_ovr(union acpi_subtable_headers * header,
- const unsigned long end)
-{
- struct acpi_madt_interrupt_override *p;
-
- p = (struct acpi_madt_interrupt_override *)header;
-
- if (BAD_MADT_ENTRY(p, end))
- return -EINVAL;
-
- iosapic_override_isa_irq(p->source_irq, p->global_irq,
- ((p->inti_flags & ACPI_MADT_POLARITY_MASK) ==
- ACPI_MADT_POLARITY_ACTIVE_LOW) ?
- IOSAPIC_POL_LOW : IOSAPIC_POL_HIGH,
- ((p->inti_flags & ACPI_MADT_TRIGGER_MASK) ==
- ACPI_MADT_TRIGGER_LEVEL) ?
- IOSAPIC_LEVEL : IOSAPIC_EDGE);
- return 0;
-}
-
-static int __init
-acpi_parse_nmi_src(union acpi_subtable_headers * header, const unsigned long end)
-{
- struct acpi_madt_nmi_source *nmi_src;
-
- nmi_src = (struct acpi_madt_nmi_source *)header;
-
- if (BAD_MADT_ENTRY(nmi_src, end))
- return -EINVAL;
-
- /* TBD: Support nimsrc entries */
- return 0;
-}
-
-static void __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
-{
- if (!strncmp(oem_id, "IBM", 3) && (!strncmp(oem_table_id, "SERMOW", 6))) {
-
- /*
- * Unfortunately ITC_DRIFT is not yet part of the
- * official SAL spec, so the ITC_DRIFT bit is not
- * set by the BIOS on this hardware.
- */
- sal_platform_features |= IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT;
-
- cyclone_setup();
- }
-}
-
-static int __init acpi_parse_madt(struct acpi_table_header *table)
-{
- acpi_madt = (struct acpi_table_madt *)table;
-
- acpi_madt_rev = acpi_madt->header.revision;
-
- /* remember the value for reference after free_initmem() */
-#ifdef CONFIG_ITANIUM
- has_8259 = 1; /* Firmware on old Itanium systems is broken */
-#else
- has_8259 = acpi_madt->flags & ACPI_MADT_PCAT_COMPAT;
-#endif
- iosapic_system_init(has_8259);
-
- /* Get base address of IPI Message Block */
-
- if (acpi_madt->address)
- ipi_base_addr = ioremap(acpi_madt->address, 0);
-
- printk(KERN_INFO PREFIX "Local APIC address %p\n", ipi_base_addr);
-
- acpi_madt_oem_check(acpi_madt->header.oem_id,
- acpi_madt->header.oem_table_id);
-
- return 0;
-}
-
-#ifdef CONFIG_ACPI_NUMA
-
-#undef SLIT_DEBUG
-
-#define PXM_FLAG_LEN ((MAX_PXM_DOMAINS + 1)/32)
-
-static int __initdata srat_num_cpus; /* number of cpus */
-static u32 pxm_flag[PXM_FLAG_LEN];
-#define pxm_bit_set(bit) (set_bit(bit,(void *)pxm_flag))
-#define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag))
-static struct acpi_table_slit __initdata *slit_table;
-cpumask_t early_cpu_possible_map = CPU_MASK_NONE;
-
-static int __init
-get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
-{
- int pxm;
-
- pxm = pa->proximity_domain_lo;
- if (acpi_srat_revision >= 2)
- pxm += pa->proximity_domain_hi[0] << 8;
- return pxm;
-}
-
-static int __init
-get_memory_proximity_domain(struct acpi_srat_mem_affinity *ma)
-{
- int pxm;
-
- pxm = ma->proximity_domain;
- if (acpi_srat_revision <= 1)
- pxm &= 0xff;
-
- return pxm;
-}
-
-/*
- * ACPI 2.0 SLIT (System Locality Information Table)
- * http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf
- */
-void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
-{
- u32 len;
-
- len = sizeof(struct acpi_table_header) + 8
- + slit->locality_count * slit->locality_count;
- if (slit->header.length != len) {
- printk(KERN_ERR
- "ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
- len, slit->header.length);
- return;
- }
- slit_table = slit;
-}
-
-void __init
-acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
-{
- int pxm;
-
- if (!(pa->flags & ACPI_SRAT_CPU_ENABLED))
- return;
-
- if (srat_num_cpus >= ARRAY_SIZE(node_cpuid)) {
- printk_once(KERN_WARNING
- "node_cpuid[%ld] is too small, may not be able to use all cpus\n",
- ARRAY_SIZE(node_cpuid));
- return;
- }
- pxm = get_processor_proximity_domain(pa);
-
- /* record this node in proximity bitmap */
- pxm_bit_set(pxm);
-
- node_cpuid[srat_num_cpus].phys_id =
- (pa->apic_id << 8) | (pa->local_sapic_eid);
- /* nid should be overridden as logical node id later */
- node_cpuid[srat_num_cpus].nid = pxm;
- cpumask_set_cpu(srat_num_cpus, &early_cpu_possible_map);
- srat_num_cpus++;
-}
-
-int __init
-acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
-{
- unsigned long paddr, size;
- int pxm;
- struct node_memblk_s *p, *q, *pend;
-
- pxm = get_memory_proximity_domain(ma);
-
- /* fill node memory chunk structure */
- paddr = ma->base_address;
- size = ma->length;
-
- /* Ignore disabled entries */
- if (!(ma->flags & ACPI_SRAT_MEM_ENABLED))
- return -1;
-
- if (num_node_memblks >= NR_NODE_MEMBLKS) {
- pr_err("NUMA: too many memblk ranges\n");
- return -EINVAL;
- }
-
- /* record this node in proximity bitmap */
- pxm_bit_set(pxm);
-
- /* Insertion sort based on base address */
- pend = &node_memblk[num_node_memblks];
- for (p = &node_memblk[0]; p < pend; p++) {
- if (paddr < p->start_paddr)
- break;
- }
- if (p < pend) {
- for (q = pend - 1; q >= p; q--)
- *(q + 1) = *q;
- }
- p->start_paddr = paddr;
- p->size = size;
- p->nid = pxm;
- num_node_memblks++;
- return 0;
-}
-
-void __init acpi_numa_fixup(void)
-{
- int i, j, node_from, node_to;
-
- /* If there's no SRAT, fix the phys_id and mark node 0 online */
- if (srat_num_cpus == 0) {
- node_set_online(0);
- node_cpuid[0].phys_id = hard_smp_processor_id();
- slit_distance(0, 0) = LOCAL_DISTANCE;
- goto out;
- }
-
- /*
- * MCD - This can probably be dropped now. No need for pxm ID to node ID
- * mapping with sparse node numbering iff MAX_PXM_DOMAINS <= MAX_NUMNODES.
- */
- nodes_clear(node_online_map);
- for (i = 0; i < MAX_PXM_DOMAINS; i++) {
- if (pxm_bit_test(i)) {
- int nid = acpi_map_pxm_to_node(i);
- node_set_online(nid);
- }
- }
-
- /* set logical node id in memory chunk structure */
- for (i = 0; i < num_node_memblks; i++)
- node_memblk[i].nid = pxm_to_node(node_memblk[i].nid);
-
- /* assign memory bank numbers for each chunk on each node */
- for_each_online_node(i) {
- int bank;
-
- bank = 0;
- for (j = 0; j < num_node_memblks; j++)
- if (node_memblk[j].nid == i)
- node_memblk[j].bank = bank++;
- }
-
- /* set logical node id in cpu structure */
- for_each_possible_early_cpu(i)
- node_cpuid[i].nid = pxm_to_node(node_cpuid[i].nid);
-
- printk(KERN_INFO "Number of logical nodes in system = %d\n",
- num_online_nodes());
- printk(KERN_INFO "Number of memory chunks in system = %d\n",
- num_node_memblks);
-
- if (!slit_table) {
- for (i = 0; i < MAX_NUMNODES; i++)
- for (j = 0; j < MAX_NUMNODES; j++)
- slit_distance(i, j) = i == j ?
- LOCAL_DISTANCE : REMOTE_DISTANCE;
- goto out;
- }
-
- memset(numa_slit, -1, sizeof(numa_slit));
- for (i = 0; i < slit_table->locality_count; i++) {
- if (!pxm_bit_test(i))
- continue;
- node_from = pxm_to_node(i);
- for (j = 0; j < slit_table->locality_count; j++) {
- if (!pxm_bit_test(j))
- continue;
- node_to = pxm_to_node(j);
- slit_distance(node_from, node_to) =
- slit_table->entry[i * slit_table->locality_count + j];
- }
- }
-
-#ifdef SLIT_DEBUG
- printk("ACPI 2.0 SLIT locality table:\n");
- for_each_online_node(i) {
- for_each_online_node(j)
- printk("%03d ", node_distance(i, j));
- printk("\n");
- }
-#endif
-out:
- node_possible_map = node_online_map;
-}
-#endif /* CONFIG_ACPI_NUMA */
-
-/*
- * success: return IRQ number (>=0)
- * failure: return < 0
- */
-int acpi_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity)
-{
- if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
- return gsi;
-
- if (has_8259 && gsi < 16)
- return isa_irq_to_vector(gsi);
-
- return iosapic_register_intr(gsi,
- (polarity ==
- ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH :
- IOSAPIC_POL_LOW,
- (triggering ==
- ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE :
- IOSAPIC_LEVEL);
-}
-EXPORT_SYMBOL_GPL(acpi_register_gsi);
-
-void acpi_unregister_gsi(u32 gsi)
-{
- if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
- return;
-
- if (has_8259 && gsi < 16)
- return;
-
- iosapic_unregister_intr(gsi);
-}
-EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
-
-static int __init acpi_parse_fadt(struct acpi_table_header *table)
-{
- struct acpi_table_header *fadt_header;
- struct acpi_table_fadt *fadt;
-
- fadt_header = (struct acpi_table_header *)table;
- if (fadt_header->revision != 3)
- return -ENODEV; /* Only deal with ACPI 2.0 FADT */
-
- fadt = (struct acpi_table_fadt *)fadt_header;
-
- acpi_register_gsi(NULL, fadt->sci_interrupt, ACPI_LEVEL_SENSITIVE,
- ACPI_ACTIVE_LOW);
- return 0;
-}
-
-int __init early_acpi_boot_init(void)
-{
- int ret;
-
- /*
- * do a partial walk of MADT to determine how many CPUs
- * we have including offline CPUs
- */
- if (acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
- printk(KERN_ERR PREFIX "Can't find MADT\n");
- return 0;
- }
-
- ret = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC,
- acpi_parse_lsapic, NR_CPUS);
- if (ret < 1)
- printk(KERN_ERR PREFIX
- "Error parsing MADT - no LAPIC entries\n");
- else
- acpi_lapic = 1;
-
-#ifdef CONFIG_SMP
- if (available_cpus == 0) {
- printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n");
- printk(KERN_INFO "CPU 0 (0x%04x)", hard_smp_processor_id());
- smp_boot_data.cpu_phys_id[available_cpus] =
- hard_smp_processor_id();
- available_cpus = 1; /* We've got at least one of these, no? */
- }
- smp_boot_data.cpu_count = available_cpus;
-#endif
- /* Make boot-up look pretty */
- printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus,
- total_cpus);
-
- return 0;
-}
-
-int __init acpi_boot_init(void)
-{
-
- /*
- * MADT
- * ----
- * Parse the Multiple APIC Description Table (MADT), if exists.
- * Note that this table provides platform SMP configuration
- * information -- the successor to MPS tables.
- */
-
- if (acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
- printk(KERN_ERR PREFIX "Can't find MADT\n");
- goto skip_madt;
- }
-
- /* Local APIC */
-
- if (acpi_table_parse_madt
- (ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE, acpi_parse_lapic_addr_ovr, 0) < 0)
- printk(KERN_ERR PREFIX
- "Error parsing LAPIC address override entry\n");
-
- if (acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0)
- < 0)
- printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
-
- /* I/O APIC */
-
- if (acpi_table_parse_madt
- (ACPI_MADT_TYPE_IO_SAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1) {
- printk(KERN_ERR PREFIX
- "Error parsing MADT - no IOSAPIC entries\n");
- }
-
- /* System-Level Interrupt Routing */
-
- if (acpi_table_parse_madt
- (ACPI_MADT_TYPE_INTERRUPT_SOURCE, acpi_parse_plat_int_src,
- ACPI_MAX_PLATFORM_INTERRUPTS) < 0)
- printk(KERN_ERR PREFIX
- "Error parsing platform interrupt source entry\n");
-
- if (acpi_table_parse_madt
- (ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr, 0) < 0)
- printk(KERN_ERR PREFIX
- "Error parsing interrupt source overrides entry\n");
-
- if (acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src, 0) < 0)
- printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
- skip_madt:
-
- /*
- * FADT says whether a legacy keyboard controller is present.
- * The FADT also contains an SCI_INT line, by which the system
- * gets interrupts such as power and sleep buttons. If it's not
- * on a Legacy interrupt, it needs to be setup.
- */
- if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt))
- printk(KERN_ERR PREFIX "Can't find FADT\n");
-
-#ifdef CONFIG_ACPI_NUMA
-#ifdef CONFIG_SMP
- if (srat_num_cpus == 0) {
- int cpu, i = 1;
- for (cpu = 0; cpu < smp_boot_data.cpu_count; cpu++)
- if (smp_boot_data.cpu_phys_id[cpu] !=
- hard_smp_processor_id())
- node_cpuid[i++].phys_id =
- smp_boot_data.cpu_phys_id[cpu];
- }
-#endif
- build_cpu_to_node_map();
-#endif
- return 0;
-}
-
-int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
-{
- int tmp;
-
- if (has_8259 && gsi < 16)
- *irq = isa_irq_to_vector(gsi);
- else {
- tmp = gsi_to_irq(gsi);
- if (tmp == -1)
- return -1;
- *irq = tmp;
- }
- return 0;
-}
-
-int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
-{
- if (isa_irq >= 16)
- return -1;
- *gsi = isa_irq;
- return 0;
-}
-
-/*
- * ACPI based hotplug CPU support
- */
-#ifdef CONFIG_ACPI_HOTPLUG_CPU
-int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
-{
-#ifdef CONFIG_ACPI_NUMA
- /*
- * We don't have cpu-only-node hotadd. But if the system equips
- * SRAT table, pxm is already found and node is ready.
- * So, just pxm_to_nid(pxm) is OK.
- * This code here is for the system which doesn't have full SRAT
- * table for possible cpus.
- */
- node_cpuid[cpu].phys_id = physid;
- node_cpuid[cpu].nid = acpi_get_node(handle);
-#endif
- return 0;
-}
-
-int additional_cpus __initdata = -1;
-
-static __init int setup_additional_cpus(char *s)
-{
- if (s)
- additional_cpus = simple_strtol(s, NULL, 0);
-
- return 0;
-}
-
-early_param("additional_cpus", setup_additional_cpus);
-
-/*
- * cpu_possible_mask should be static, it cannot change as CPUs
- * are onlined, or offlined. The reason is per-cpu data-structures
- * are allocated by some modules at init time, and dont expect to
- * do this dynamically on cpu arrival/departure.
- * cpu_present_mask on the other hand can change dynamically.
- * In case when cpu_hotplug is not compiled, then we resort to current
- * behaviour, which is cpu_possible == cpu_present.
- * - Ashok Raj
- *
- * Three ways to find out the number of additional hotplug CPUs:
- * - If the BIOS specified disabled CPUs in ACPI/mptables use that.
- * - The user can overwrite it with additional_cpus=NUM
- * - Otherwise don't reserve additional CPUs.
- */
-__init void prefill_possible_map(void)
-{
- int i;
- int possible, disabled_cpus;
-
- disabled_cpus = total_cpus - available_cpus;
-
- if (additional_cpus == -1) {
- if (disabled_cpus > 0)
- additional_cpus = disabled_cpus;
- else
- additional_cpus = 0;
- }
-
- possible = available_cpus + additional_cpus;
-
- if (possible > nr_cpu_ids)
- possible = nr_cpu_ids;
-
- printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
- possible, max((possible - available_cpus), 0));
-
- for (i = 0; i < possible; i++)
- set_cpu_possible(i, true);
-}
-
-static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
-{
- int cpu;
-
- cpu = cpumask_first_zero(cpu_present_mask);
- if (cpu >= nr_cpu_ids)
- return -EINVAL;
-
- acpi_map_cpu2node(handle, cpu, physid);
-
- set_cpu_present(cpu, true);
- ia64_cpu_to_sapicid[cpu] = physid;
-
- acpi_processor_set_pdc(handle);
-
- *pcpu = cpu;
- return (0);
-}
-
-/* wrapper to silence section mismatch warning */
-int __ref acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 acpi_id,
- int *pcpu)
-{
- return _acpi_map_lsapic(handle, physid, pcpu);
-}
-EXPORT_SYMBOL(acpi_map_cpu);
-
-int acpi_unmap_cpu(int cpu)
-{
- ia64_cpu_to_sapicid[cpu] = -1;
- set_cpu_present(cpu, false);
-
-#ifdef CONFIG_ACPI_NUMA
- /* NUMA specific cleanup's */
-#endif
-
- return (0);
-}
-EXPORT_SYMBOL(acpi_unmap_cpu);
-#endif /* CONFIG_ACPI_HOTPLUG_CPU */
-
-#ifdef CONFIG_ACPI_NUMA
-static acpi_status acpi_map_iosapic(acpi_handle handle, u32 depth,
- void *context, void **ret)
-{
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- union acpi_object *obj;
- struct acpi_madt_io_sapic *iosapic;
- unsigned int gsi_base;
- int node;
-
- /* Only care about objects w/ a method that returns the MADT */
- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
- return AE_OK;
-
- if (!buffer.length || !buffer.pointer)
- return AE_OK;
-
- obj = buffer.pointer;
- if (obj->type != ACPI_TYPE_BUFFER ||
- obj->buffer.length < sizeof(*iosapic)) {
- kfree(buffer.pointer);
- return AE_OK;
- }
-
- iosapic = (struct acpi_madt_io_sapic *)obj->buffer.pointer;
-
- if (iosapic->header.type != ACPI_MADT_TYPE_IO_SAPIC) {
- kfree(buffer.pointer);
- return AE_OK;
- }
-
- gsi_base = iosapic->global_irq_base;
-
- kfree(buffer.pointer);
-
- /* OK, it's an IOSAPIC MADT entry; associate it with a node */
- node = acpi_get_node(handle);
- if (node == NUMA_NO_NODE || !node_online(node) ||
- cpumask_empty(cpumask_of_node(node)))
- return AE_OK;
-
- /* We know a gsi to node mapping! */
- map_iosapic_to_node(gsi_base, node);
- return AE_OK;
-}
-
-static int __init
-acpi_map_iosapics (void)
-{
- acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
- return 0;
-}
-
-fs_initcall(acpi_map_iosapics);
-#endif /* CONFIG_ACPI_NUMA */
-
-int __ref acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
-{
- int err;
-
- if ((err = iosapic_init(phys_addr, gsi_base)))
- return err;
-
-#ifdef CONFIG_ACPI_NUMA
- acpi_map_iosapic(handle, 0, NULL, NULL);
-#endif /* CONFIG_ACPI_NUMA */
-
- return 0;
-}
-
-EXPORT_SYMBOL(acpi_register_ioapic);
-
-int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
-{
- return iosapic_remove(gsi_base);
-}
-
-EXPORT_SYMBOL(acpi_unregister_ioapic);
-
-/*
- * acpi_suspend_lowlevel() - save kernel state and suspend.
- *
- * TBD when IA64 starts to support suspend...
- */
-int acpi_suspend_lowlevel(void) { return 0; }
-
-void acpi_proc_quirk_mwait_check(void)
-{
-}
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
deleted file mode 100644
index be3b90fef2e9..000000000000
--- a/arch/ia64/kernel/asm-offsets.c
+++ /dev/null
@@ -1,289 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Generate definitions needed by assembly language modules.
- * This code generates raw asm output which is post-processed
- * to extract and format the required data.
- */
-
-#define ASM_OFFSETS_C 1
-
-#include <linux/sched/signal.h>
-#include <linux/pid.h>
-#include <linux/clocksource.h>
-#include <linux/kbuild.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/siginfo.h>
-#include <asm/sigcontext.h>
-#include <asm/mca.h>
-
-#include "../kernel/sigframe.h"
-#include "../kernel/fsyscall_gtod_data.h"
-
-void foo(void)
-{
- DEFINE(IA64_TASK_SIZE, sizeof (struct task_struct));
- DEFINE(IA64_THREAD_INFO_SIZE, sizeof (struct thread_info));
- DEFINE(IA64_PT_REGS_SIZE, sizeof (struct pt_regs));
- DEFINE(IA64_SWITCH_STACK_SIZE, sizeof (struct switch_stack));
- DEFINE(IA64_SIGINFO_SIZE, sizeof (struct siginfo));
- DEFINE(IA64_CPU_SIZE, sizeof (struct cpuinfo_ia64));
- DEFINE(SIGFRAME_SIZE, sizeof (struct sigframe));
- DEFINE(UNW_FRAME_INFO_SIZE, sizeof (struct unw_frame_info));
-
- BUILD_BUG_ON(sizeof(struct upid) != 16);
- DEFINE(IA64_UPID_SHIFT, 4);
-
- BLANK();
-
- DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
- DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
- DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
- DEFINE(TI_AC_STAMP, offsetof(struct thread_info, ac_stamp));
- DEFINE(TI_AC_LEAVE, offsetof(struct thread_info, ac_leave));
- DEFINE(TI_AC_STIME, offsetof(struct thread_info, ac_stime));
- DEFINE(TI_AC_UTIME, offsetof(struct thread_info, ac_utime));
-#endif
-
- BLANK();
-
- DEFINE(IA64_TASK_BLOCKED_OFFSET,offsetof (struct task_struct, blocked));
- DEFINE(IA64_TASK_CLEAR_CHILD_TID_OFFSET,offsetof (struct task_struct, clear_child_tid));
- DEFINE(IA64_TASK_THREAD_PID_OFFSET,offsetof (struct task_struct, thread_pid));
- DEFINE(IA64_PID_LEVEL_OFFSET, offsetof (struct pid, level));
- DEFINE(IA64_PID_UPID_OFFSET, offsetof (struct pid, numbers[0]));
- DEFINE(IA64_TASK_PENDING_OFFSET,offsetof (struct task_struct, pending));
- DEFINE(IA64_TASK_PID_OFFSET, offsetof (struct task_struct, pid));
- DEFINE(IA64_TASK_REAL_PARENT_OFFSET, offsetof (struct task_struct, real_parent));
- DEFINE(IA64_TASK_SIGNAL_OFFSET,offsetof (struct task_struct, signal));
- DEFINE(IA64_TASK_TGID_OFFSET, offsetof (struct task_struct, tgid));
- DEFINE(IA64_TASK_THREAD_KSP_OFFSET, offsetof (struct task_struct, thread.ksp));
- DEFINE(IA64_TASK_THREAD_ON_USTACK_OFFSET, offsetof (struct task_struct, thread.on_ustack));
-
- BLANK();
-
-
- DEFINE(IA64_SIGNAL_GROUP_STOP_COUNT_OFFSET,offsetof (struct signal_struct,
- group_stop_count));
- DEFINE(IA64_SIGNAL_SHARED_PENDING_OFFSET,offsetof (struct signal_struct, shared_pending));
- DEFINE(IA64_SIGNAL_PIDS_TGID_OFFSET, offsetof (struct signal_struct, pids[PIDTYPE_TGID]));
-
- BLANK();
-
- DEFINE(IA64_PT_REGS_B6_OFFSET, offsetof (struct pt_regs, b6));
- DEFINE(IA64_PT_REGS_B7_OFFSET, offsetof (struct pt_regs, b7));
- DEFINE(IA64_PT_REGS_AR_CSD_OFFSET, offsetof (struct pt_regs, ar_csd));
- DEFINE(IA64_PT_REGS_AR_SSD_OFFSET, offsetof (struct pt_regs, ar_ssd));
- DEFINE(IA64_PT_REGS_R8_OFFSET, offsetof (struct pt_regs, r8));
- DEFINE(IA64_PT_REGS_R9_OFFSET, offsetof (struct pt_regs, r9));
- DEFINE(IA64_PT_REGS_R10_OFFSET, offsetof (struct pt_regs, r10));
- DEFINE(IA64_PT_REGS_R11_OFFSET, offsetof (struct pt_regs, r11));
- DEFINE(IA64_PT_REGS_CR_IPSR_OFFSET, offsetof (struct pt_regs, cr_ipsr));
- DEFINE(IA64_PT_REGS_CR_IIP_OFFSET, offsetof (struct pt_regs, cr_iip));
- DEFINE(IA64_PT_REGS_CR_IFS_OFFSET, offsetof (struct pt_regs, cr_ifs));
- DEFINE(IA64_PT_REGS_AR_UNAT_OFFSET, offsetof (struct pt_regs, ar_unat));
- DEFINE(IA64_PT_REGS_AR_PFS_OFFSET, offsetof (struct pt_regs, ar_pfs));
- DEFINE(IA64_PT_REGS_AR_RSC_OFFSET, offsetof (struct pt_regs, ar_rsc));
- DEFINE(IA64_PT_REGS_AR_RNAT_OFFSET, offsetof (struct pt_regs, ar_rnat));
-
- DEFINE(IA64_PT_REGS_AR_BSPSTORE_OFFSET, offsetof (struct pt_regs, ar_bspstore));
- DEFINE(IA64_PT_REGS_PR_OFFSET, offsetof (struct pt_regs, pr));
- DEFINE(IA64_PT_REGS_B0_OFFSET, offsetof (struct pt_regs, b0));
- DEFINE(IA64_PT_REGS_LOADRS_OFFSET, offsetof (struct pt_regs, loadrs));
- DEFINE(IA64_PT_REGS_R1_OFFSET, offsetof (struct pt_regs, r1));
- DEFINE(IA64_PT_REGS_R12_OFFSET, offsetof (struct pt_regs, r12));
- DEFINE(IA64_PT_REGS_R13_OFFSET, offsetof (struct pt_regs, r13));
- DEFINE(IA64_PT_REGS_AR_FPSR_OFFSET, offsetof (struct pt_regs, ar_fpsr));
- DEFINE(IA64_PT_REGS_R15_OFFSET, offsetof (struct pt_regs, r15));
- DEFINE(IA64_PT_REGS_R14_OFFSET, offsetof (struct pt_regs, r14));
- DEFINE(IA64_PT_REGS_R2_OFFSET, offsetof (struct pt_regs, r2));
- DEFINE(IA64_PT_REGS_R3_OFFSET, offsetof (struct pt_regs, r3));
- DEFINE(IA64_PT_REGS_R16_OFFSET, offsetof (struct pt_regs, r16));
- DEFINE(IA64_PT_REGS_R17_OFFSET, offsetof (struct pt_regs, r17));
- DEFINE(IA64_PT_REGS_R18_OFFSET, offsetof (struct pt_regs, r18));
- DEFINE(IA64_PT_REGS_R19_OFFSET, offsetof (struct pt_regs, r19));
- DEFINE(IA64_PT_REGS_R20_OFFSET, offsetof (struct pt_regs, r20));
- DEFINE(IA64_PT_REGS_R21_OFFSET, offsetof (struct pt_regs, r21));
- DEFINE(IA64_PT_REGS_R22_OFFSET, offsetof (struct pt_regs, r22));
- DEFINE(IA64_PT_REGS_R23_OFFSET, offsetof (struct pt_regs, r23));
- DEFINE(IA64_PT_REGS_R24_OFFSET, offsetof (struct pt_regs, r24));
- DEFINE(IA64_PT_REGS_R25_OFFSET, offsetof (struct pt_regs, r25));
- DEFINE(IA64_PT_REGS_R26_OFFSET, offsetof (struct pt_regs, r26));
- DEFINE(IA64_PT_REGS_R27_OFFSET, offsetof (struct pt_regs, r27));
- DEFINE(IA64_PT_REGS_R28_OFFSET, offsetof (struct pt_regs, r28));
- DEFINE(IA64_PT_REGS_R29_OFFSET, offsetof (struct pt_regs, r29));
- DEFINE(IA64_PT_REGS_R30_OFFSET, offsetof (struct pt_regs, r30));
- DEFINE(IA64_PT_REGS_R31_OFFSET, offsetof (struct pt_regs, r31));
- DEFINE(IA64_PT_REGS_AR_CCV_OFFSET, offsetof (struct pt_regs, ar_ccv));
- DEFINE(IA64_PT_REGS_F6_OFFSET, offsetof (struct pt_regs, f6));
- DEFINE(IA64_PT_REGS_F7_OFFSET, offsetof (struct pt_regs, f7));
- DEFINE(IA64_PT_REGS_F8_OFFSET, offsetof (struct pt_regs, f8));
- DEFINE(IA64_PT_REGS_F9_OFFSET, offsetof (struct pt_regs, f9));
- DEFINE(IA64_PT_REGS_F10_OFFSET, offsetof (struct pt_regs, f10));
- DEFINE(IA64_PT_REGS_F11_OFFSET, offsetof (struct pt_regs, f11));
-
- BLANK();
-
- DEFINE(IA64_SWITCH_STACK_CALLER_UNAT_OFFSET, offsetof (struct switch_stack, caller_unat));
- DEFINE(IA64_SWITCH_STACK_AR_FPSR_OFFSET, offsetof (struct switch_stack, ar_fpsr));
- DEFINE(IA64_SWITCH_STACK_F2_OFFSET, offsetof (struct switch_stack, f2));
- DEFINE(IA64_SWITCH_STACK_F3_OFFSET, offsetof (struct switch_stack, f3));
- DEFINE(IA64_SWITCH_STACK_F4_OFFSET, offsetof (struct switch_stack, f4));
- DEFINE(IA64_SWITCH_STACK_F5_OFFSET, offsetof (struct switch_stack, f5));
- DEFINE(IA64_SWITCH_STACK_F12_OFFSET, offsetof (struct switch_stack, f12));
- DEFINE(IA64_SWITCH_STACK_F13_OFFSET, offsetof (struct switch_stack, f13));
- DEFINE(IA64_SWITCH_STACK_F14_OFFSET, offsetof (struct switch_stack, f14));
- DEFINE(IA64_SWITCH_STACK_F15_OFFSET, offsetof (struct switch_stack, f15));
- DEFINE(IA64_SWITCH_STACK_F16_OFFSET, offsetof (struct switch_stack, f16));
- DEFINE(IA64_SWITCH_STACK_F17_OFFSET, offsetof (struct switch_stack, f17));
- DEFINE(IA64_SWITCH_STACK_F18_OFFSET, offsetof (struct switch_stack, f18));
- DEFINE(IA64_SWITCH_STACK_F19_OFFSET, offsetof (struct switch_stack, f19));
- DEFINE(IA64_SWITCH_STACK_F20_OFFSET, offsetof (struct switch_stack, f20));
- DEFINE(IA64_SWITCH_STACK_F21_OFFSET, offsetof (struct switch_stack, f21));
- DEFINE(IA64_SWITCH_STACK_F22_OFFSET, offsetof (struct switch_stack, f22));
- DEFINE(IA64_SWITCH_STACK_F23_OFFSET, offsetof (struct switch_stack, f23));
- DEFINE(IA64_SWITCH_STACK_F24_OFFSET, offsetof (struct switch_stack, f24));
- DEFINE(IA64_SWITCH_STACK_F25_OFFSET, offsetof (struct switch_stack, f25));
- DEFINE(IA64_SWITCH_STACK_F26_OFFSET, offsetof (struct switch_stack, f26));
- DEFINE(IA64_SWITCH_STACK_F27_OFFSET, offsetof (struct switch_stack, f27));
- DEFINE(IA64_SWITCH_STACK_F28_OFFSET, offsetof (struct switch_stack, f28));
- DEFINE(IA64_SWITCH_STACK_F29_OFFSET, offsetof (struct switch_stack, f29));
- DEFINE(IA64_SWITCH_STACK_F30_OFFSET, offsetof (struct switch_stack, f30));
- DEFINE(IA64_SWITCH_STACK_F31_OFFSET, offsetof (struct switch_stack, f31));
- DEFINE(IA64_SWITCH_STACK_R4_OFFSET, offsetof (struct switch_stack, r4));
- DEFINE(IA64_SWITCH_STACK_R5_OFFSET, offsetof (struct switch_stack, r5));
- DEFINE(IA64_SWITCH_STACK_R6_OFFSET, offsetof (struct switch_stack, r6));
- DEFINE(IA64_SWITCH_STACK_R7_OFFSET, offsetof (struct switch_stack, r7));
- DEFINE(IA64_SWITCH_STACK_B0_OFFSET, offsetof (struct switch_stack, b0));
- DEFINE(IA64_SWITCH_STACK_B1_OFFSET, offsetof (struct switch_stack, b1));
- DEFINE(IA64_SWITCH_STACK_B2_OFFSET, offsetof (struct switch_stack, b2));
- DEFINE(IA64_SWITCH_STACK_B3_OFFSET, offsetof (struct switch_stack, b3));
- DEFINE(IA64_SWITCH_STACK_B4_OFFSET, offsetof (struct switch_stack, b4));
- DEFINE(IA64_SWITCH_STACK_B5_OFFSET, offsetof (struct switch_stack, b5));
- DEFINE(IA64_SWITCH_STACK_AR_PFS_OFFSET, offsetof (struct switch_stack, ar_pfs));
- DEFINE(IA64_SWITCH_STACK_AR_LC_OFFSET, offsetof (struct switch_stack, ar_lc));
- DEFINE(IA64_SWITCH_STACK_AR_UNAT_OFFSET, offsetof (struct switch_stack, ar_unat));
- DEFINE(IA64_SWITCH_STACK_AR_RNAT_OFFSET, offsetof (struct switch_stack, ar_rnat));
- DEFINE(IA64_SWITCH_STACK_AR_BSPSTORE_OFFSET, offsetof (struct switch_stack, ar_bspstore));
- DEFINE(IA64_SWITCH_STACK_PR_OFFSET, offsetof (struct switch_stack, pr));
-
- BLANK();
-
- DEFINE(IA64_SIGCONTEXT_IP_OFFSET, offsetof (struct sigcontext, sc_ip));
- DEFINE(IA64_SIGCONTEXT_AR_BSP_OFFSET, offsetof (struct sigcontext, sc_ar_bsp));
- DEFINE(IA64_SIGCONTEXT_AR_FPSR_OFFSET, offsetof (struct sigcontext, sc_ar_fpsr));
- DEFINE(IA64_SIGCONTEXT_AR_RNAT_OFFSET, offsetof (struct sigcontext, sc_ar_rnat));
- DEFINE(IA64_SIGCONTEXT_AR_UNAT_OFFSET, offsetof (struct sigcontext, sc_ar_unat));
- DEFINE(IA64_SIGCONTEXT_B0_OFFSET, offsetof (struct sigcontext, sc_br[0]));
- DEFINE(IA64_SIGCONTEXT_CFM_OFFSET, offsetof (struct sigcontext, sc_cfm));
- DEFINE(IA64_SIGCONTEXT_FLAGS_OFFSET, offsetof (struct sigcontext, sc_flags));
- DEFINE(IA64_SIGCONTEXT_FR6_OFFSET, offsetof (struct sigcontext, sc_fr[6]));
- DEFINE(IA64_SIGCONTEXT_PR_OFFSET, offsetof (struct sigcontext, sc_pr));
- DEFINE(IA64_SIGCONTEXT_R12_OFFSET, offsetof (struct sigcontext, sc_gr[12]));
- DEFINE(IA64_SIGCONTEXT_RBS_BASE_OFFSET,offsetof (struct sigcontext, sc_rbs_base));
- DEFINE(IA64_SIGCONTEXT_LOADRS_OFFSET, offsetof (struct sigcontext, sc_loadrs));
-
- BLANK();
-
- DEFINE(IA64_SIGPENDING_SIGNAL_OFFSET, offsetof (struct sigpending, signal));
-
- BLANK();
-
- DEFINE(IA64_SIGFRAME_ARG0_OFFSET, offsetof (struct sigframe, arg0));
- DEFINE(IA64_SIGFRAME_ARG1_OFFSET, offsetof (struct sigframe, arg1));
- DEFINE(IA64_SIGFRAME_ARG2_OFFSET, offsetof (struct sigframe, arg2));
- DEFINE(IA64_SIGFRAME_HANDLER_OFFSET, offsetof (struct sigframe, handler));
- DEFINE(IA64_SIGFRAME_SIGCONTEXT_OFFSET, offsetof (struct sigframe, sc));
- BLANK();
- /* for assembly files which can't include sched.h: */
- DEFINE(IA64_CLONE_VFORK, CLONE_VFORK);
- DEFINE(IA64_CLONE_VM, CLONE_VM);
-
- BLANK();
- DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET,
- offsetof (struct cpuinfo_ia64, nsec_per_cyc));
- DEFINE(IA64_CPUINFO_PTCE_BASE_OFFSET,
- offsetof (struct cpuinfo_ia64, ptce_base));
- DEFINE(IA64_CPUINFO_PTCE_COUNT_OFFSET,
- offsetof (struct cpuinfo_ia64, ptce_count));
- DEFINE(IA64_CPUINFO_PTCE_STRIDE_OFFSET,
- offsetof (struct cpuinfo_ia64, ptce_stride));
- BLANK();
- DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET,
- offsetof (struct __kernel_old_timespec, tv_nsec));
- DEFINE(IA64_TIME_SN_SPEC_SNSEC_OFFSET,
- offsetof (struct time_sn_spec, snsec));
-
- DEFINE(CLONE_SETTLS_BIT, 19);
-#if CLONE_SETTLS != (1<<19)
-# error "CLONE_SETTLS_BIT incorrect, please fix"
-#endif
-
- BLANK();
- DEFINE(IA64_MCA_CPU_MCA_STACK_OFFSET,
- offsetof (struct ia64_mca_cpu, mca_stack));
- DEFINE(IA64_MCA_CPU_INIT_STACK_OFFSET,
- offsetof (struct ia64_mca_cpu, init_stack));
- BLANK();
- DEFINE(IA64_SAL_OS_STATE_OS_GP_OFFSET,
- offsetof (struct ia64_sal_os_state, os_gp));
- DEFINE(IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET,
- offsetof (struct ia64_sal_os_state, proc_state_param));
- DEFINE(IA64_SAL_OS_STATE_SAL_RA_OFFSET,
- offsetof (struct ia64_sal_os_state, sal_ra));
- DEFINE(IA64_SAL_OS_STATE_SAL_GP_OFFSET,
- offsetof (struct ia64_sal_os_state, sal_gp));
- DEFINE(IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET,
- offsetof (struct ia64_sal_os_state, pal_min_state));
- DEFINE(IA64_SAL_OS_STATE_OS_STATUS_OFFSET,
- offsetof (struct ia64_sal_os_state, os_status));
- DEFINE(IA64_SAL_OS_STATE_CONTEXT_OFFSET,
- offsetof (struct ia64_sal_os_state, context));
- DEFINE(IA64_SAL_OS_STATE_SIZE,
- sizeof (struct ia64_sal_os_state));
- BLANK();
-
- DEFINE(IA64_PMSA_GR_OFFSET,
- offsetof(struct pal_min_state_area, pmsa_gr));
- DEFINE(IA64_PMSA_BANK1_GR_OFFSET,
- offsetof(struct pal_min_state_area, pmsa_bank1_gr));
- DEFINE(IA64_PMSA_PR_OFFSET,
- offsetof(struct pal_min_state_area, pmsa_pr));
- DEFINE(IA64_PMSA_BR0_OFFSET,
- offsetof(struct pal_min_state_area, pmsa_br0));
- DEFINE(IA64_PMSA_RSC_OFFSET,
- offsetof(struct pal_min_state_area, pmsa_rsc));
- DEFINE(IA64_PMSA_IIP_OFFSET,
- offsetof(struct pal_min_state_area, pmsa_iip));
- DEFINE(IA64_PMSA_IPSR_OFFSET,
- offsetof(struct pal_min_state_area, pmsa_ipsr));
- DEFINE(IA64_PMSA_IFS_OFFSET,
- offsetof(struct pal_min_state_area, pmsa_ifs));
- DEFINE(IA64_PMSA_XIP_OFFSET,
- offsetof(struct pal_min_state_area, pmsa_xip));
- BLANK();
-
- /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
- DEFINE(IA64_GTOD_SEQ_OFFSET,
- offsetof (struct fsyscall_gtod_data_t, seq));
- DEFINE(IA64_GTOD_WALL_TIME_OFFSET,
- offsetof (struct fsyscall_gtod_data_t, wall_time));
- DEFINE(IA64_GTOD_MONO_TIME_OFFSET,
- offsetof (struct fsyscall_gtod_data_t, monotonic_time));
- DEFINE(IA64_CLKSRC_MASK_OFFSET,
- offsetof (struct fsyscall_gtod_data_t, clk_mask));
- DEFINE(IA64_CLKSRC_MULT_OFFSET,
- offsetof (struct fsyscall_gtod_data_t, clk_mult));
- DEFINE(IA64_CLKSRC_SHIFT_OFFSET,
- offsetof (struct fsyscall_gtod_data_t, clk_shift));
- DEFINE(IA64_CLKSRC_MMIO_OFFSET,
- offsetof (struct fsyscall_gtod_data_t, clk_fsys_mmio));
- DEFINE(IA64_CLKSRC_CYCLE_LAST_OFFSET,
- offsetof (struct fsyscall_gtod_data_t, clk_cycle_last));
- DEFINE(IA64_ITC_JITTER_OFFSET,
- offsetof (struct itc_jitter_data_t, itc_jitter));
- DEFINE(IA64_ITC_LASTCYCLE_OFFSET,
- offsetof (struct itc_jitter_data_t, itc_lastcycle));
-
-}
diff --git a/arch/ia64/kernel/audit.c b/arch/ia64/kernel/audit.c
deleted file mode 100644
index ec61f20ca61f..000000000000
--- a/arch/ia64/kernel/audit.c
+++ /dev/null
@@ -1,63 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/audit.h>
-#include <asm/unistd.h>
-
-static unsigned dir_class[] = {
-#include <asm-generic/audit_dir_write.h>
-~0U
-};
-
-static unsigned read_class[] = {
-#include <asm-generic/audit_read.h>
-~0U
-};
-
-static unsigned write_class[] = {
-#include <asm-generic/audit_write.h>
-~0U
-};
-
-static unsigned chattr_class[] = {
-#include <asm-generic/audit_change_attr.h>
-~0U
-};
-
-static unsigned signal_class[] = {
-#include <asm-generic/audit_signal.h>
-~0U
-};
-
-int audit_classify_arch(int arch)
-{
- return 0;
-}
-
-int audit_classify_syscall(int abi, unsigned syscall)
-{
- switch(syscall) {
- case __NR_open:
- return AUDITSC_OPEN;
- case __NR_openat:
- return AUDITSC_OPENAT;
- case __NR_execve:
- return AUDITSC_EXECVE;
- case __NR_openat2:
- return AUDITSC_OPENAT2;
- default:
- return AUDITSC_NATIVE;
- }
-}
-
-static int __init audit_classes_init(void)
-{
- audit_register_class(AUDIT_CLASS_WRITE, write_class);
- audit_register_class(AUDIT_CLASS_READ, read_class);
- audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
- audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
- audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
- return 0;
-}
-
-__initcall(audit_classes_init);
diff --git a/arch/ia64/kernel/brl_emu.c b/arch/ia64/kernel/brl_emu.c
deleted file mode 100644
index 782c481d7052..000000000000
--- a/arch/ia64/kernel/brl_emu.c
+++ /dev/null
@@ -1,217 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Emulation of the "brl" instruction for IA64 processors that
- * don't support it in hardware.
- * Author: Stephan Zeisset, Intel Corp. <Stephan.Zeisset@intel.com>
- *
- * 02/22/02 D. Mosberger Clear si_flgs, si_isr, and si_imm to avoid
- * leaking kernel bits.
- */
-
-#include <linux/kernel.h>
-#include <linux/sched/signal.h>
-#include <linux/uaccess.h>
-#include <asm/processor.h>
-
-extern char ia64_set_b1, ia64_set_b2, ia64_set_b3, ia64_set_b4, ia64_set_b5;
-
-struct illegal_op_return {
- unsigned long fkt, arg1, arg2, arg3;
-};
-
-/*
- * The unimplemented bits of a virtual address must be set
- * to the value of the most significant implemented bit.
- * unimpl_va_mask includes all unimplemented bits and
- * the most significant implemented bit, so the result
- * of an and operation with the mask must be all 0's
- * or all 1's for the address to be valid.
- */
-#define unimplemented_virtual_address(va) ( \
- ((va) & local_cpu_data->unimpl_va_mask) != 0 && \
- ((va) & local_cpu_data->unimpl_va_mask) != local_cpu_data->unimpl_va_mask \
-)
-
-/*
- * The unimplemented bits of a physical address must be 0.
- * unimpl_pa_mask includes all unimplemented bits, so the result
- * of an and operation with the mask must be all 0's for the
- * address to be valid.
- */
-#define unimplemented_physical_address(pa) ( \
- ((pa) & local_cpu_data->unimpl_pa_mask) != 0 \
-)
-
-/*
- * Handle an illegal operation fault that was caused by an
- * unimplemented "brl" instruction.
- * If we are not successful (e.g because the illegal operation
- * wasn't caused by a "brl" after all), we return -1.
- * If we are successful, we return either 0 or the address
- * of a "fixup" function for manipulating preserved register
- * state.
- */
-
-struct illegal_op_return
-ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec)
-{
- unsigned long bundle[2];
- unsigned long opcode, btype, qp, offset, cpl;
- unsigned long next_ip;
- struct illegal_op_return rv;
- long tmp_taken, unimplemented_address;
-
- rv.fkt = (unsigned long) -1;
-
- /*
- * Decode the instruction bundle.
- */
-
- if (copy_from_user(bundle, (void *) (regs->cr_iip), sizeof(bundle)))
- return rv;
-
- next_ip = (unsigned long) regs->cr_iip + 16;
-
- /* "brl" must be in slot 2. */
- if (ia64_psr(regs)->ri != 1) return rv;
-
- /* Must be "mlx" template */
- if ((bundle[0] & 0x1e) != 0x4) return rv;
-
- opcode = (bundle[1] >> 60);
- btype = ((bundle[1] >> 29) & 0x7);
- qp = ((bundle[1] >> 23) & 0x3f);
- offset = ((bundle[1] & 0x0800000000000000L) << 4)
- | ((bundle[1] & 0x00fffff000000000L) >> 32)
- | ((bundle[1] & 0x00000000007fffffL) << 40)
- | ((bundle[0] & 0xffff000000000000L) >> 24);
-
- tmp_taken = regs->pr & (1L << qp);
-
- switch(opcode) {
-
- case 0xC:
- /*
- * Long Branch.
- */
- if (btype != 0) return rv;
- rv.fkt = 0;
- if (!(tmp_taken)) {
- /*
- * Qualifying predicate is 0.
- * Skip instruction.
- */
- regs->cr_iip = next_ip;
- ia64_psr(regs)->ri = 0;
- return rv;
- }
- break;
-
- case 0xD:
- /*
- * Long Call.
- */
- rv.fkt = 0;
- if (!(tmp_taken)) {
- /*
- * Qualifying predicate is 0.
- * Skip instruction.
- */
- regs->cr_iip = next_ip;
- ia64_psr(regs)->ri = 0;
- return rv;
- }
-
- /*
- * BR[btype] = IP+16
- */
- switch(btype) {
- case 0:
- regs->b0 = next_ip;
- break;
- case 1:
- rv.fkt = (unsigned long) &ia64_set_b1;
- break;
- case 2:
- rv.fkt = (unsigned long) &ia64_set_b2;
- break;
- case 3:
- rv.fkt = (unsigned long) &ia64_set_b3;
- break;
- case 4:
- rv.fkt = (unsigned long) &ia64_set_b4;
- break;
- case 5:
- rv.fkt = (unsigned long) &ia64_set_b5;
- break;
- case 6:
- regs->b6 = next_ip;
- break;
- case 7:
- regs->b7 = next_ip;
- break;
- }
- rv.arg1 = next_ip;
-
- /*
- * AR[PFS].pfm = CFM
- * AR[PFS].pec = AR[EC]
- * AR[PFS].ppl = PSR.cpl
- */
- cpl = ia64_psr(regs)->cpl;
- regs->ar_pfs = ((regs->cr_ifs & 0x3fffffffff)
- | (ar_ec << 52) | (cpl << 62));
-
- /*
- * CFM.sof -= CFM.sol
- * CFM.sol = 0
- * CFM.sor = 0
- * CFM.rrb.gr = 0
- * CFM.rrb.fr = 0
- * CFM.rrb.pr = 0
- */
- regs->cr_ifs = ((regs->cr_ifs & 0xffffffc00000007f)
- - ((regs->cr_ifs >> 7) & 0x7f));
-
- break;
-
- default:
- /*
- * Unknown opcode.
- */
- return rv;
-
- }
-
- regs->cr_iip += offset;
- ia64_psr(regs)->ri = 0;
-
- if (ia64_psr(regs)->it == 0)
- unimplemented_address = unimplemented_physical_address(regs->cr_iip);
- else
- unimplemented_address = unimplemented_virtual_address(regs->cr_iip);
-
- if (unimplemented_address) {
- /*
- * The target address contains unimplemented bits.
- */
- printk(KERN_DEBUG "Woah! Unimplemented Instruction Address Trap!\n");
- force_sig_fault(SIGILL, ILL_BADIADDR, (void __user *)NULL,
- 0, 0, 0);
- } else if (ia64_psr(regs)->tb) {
- /*
- * Branch Tracing is enabled.
- * Force a taken branch signal.
- */
- force_sig_fault(SIGTRAP, TRAP_BRANCH, (void __user *)NULL,
- 0, 0, 0);
- } else if (ia64_psr(regs)->ss) {
- /*
- * Single Step is enabled.
- * Force a trace signal.
- */
- force_sig_fault(SIGTRAP, TRAP_TRACE, (void __user *)NULL,
- 0, 0, 0);
- }
- return rv;
-}
diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c
deleted file mode 100644
index 88b3ce3e66cd..000000000000
--- a/arch/ia64/kernel/crash.c
+++ /dev/null
@@ -1,257 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/ia64/kernel/crash.c
- *
- * Architecture specific (ia64) functions for kexec based crash dumps.
- *
- * Created by: Khalid Aziz <khalid.aziz@hp.com>
- * Copyright (C) 2005 Hewlett-Packard Development Company, L.P.
- * Copyright (C) 2005 Intel Corp Zou Nan hai <nanhai.zou@intel.com>
- *
- */
-#include <linux/smp.h>
-#include <linux/delay.h>
-#include <linux/crash_dump.h>
-#include <linux/memblock.h>
-#include <linux/kexec.h>
-#include <linux/elfcore.h>
-#include <linux/reboot.h>
-#include <linux/sysctl.h>
-#include <linux/init.h>
-#include <linux/kdebug.h>
-
-#include <asm/mca.h>
-
-int kdump_status[NR_CPUS];
-static atomic_t kdump_cpu_frozen;
-atomic_t kdump_in_progress;
-static int kdump_freeze_monarch;
-static int kdump_on_init = 1;
-static int kdump_on_fatal_mca = 1;
-
-extern void ia64_dump_cpu_regs(void *);
-
-static DEFINE_PER_CPU(struct elf_prstatus, elf_prstatus);
-
-void
-crash_save_this_cpu(void)
-{
- void *buf;
- unsigned long cfm, sof, sol;
-
- int cpu = smp_processor_id();
- struct elf_prstatus *prstatus = &per_cpu(elf_prstatus, cpu);
-
- elf_greg_t *dst = (elf_greg_t *)&(prstatus->pr_reg);
- memset(prstatus, 0, sizeof(*prstatus));
- prstatus->common.pr_pid = current->pid;
-
- ia64_dump_cpu_regs(dst);
- cfm = dst[43];
- sol = (cfm >> 7) & 0x7f;
- sof = cfm & 0x7f;
- dst[46] = (unsigned long)ia64_rse_skip_regs((unsigned long *)dst[46],
- sof - sol);
-
- buf = (u64 *) per_cpu_ptr(crash_notes, cpu);
- if (!buf)
- return;
- buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS, prstatus,
- sizeof(*prstatus));
- final_note(buf);
-}
-
-#ifdef CONFIG_SMP
-static int
-kdump_wait_cpu_freeze(void)
-{
- int cpu_num = num_online_cpus() - 1;
- int timeout = 1000;
- while(timeout-- > 0) {
- if (atomic_read(&kdump_cpu_frozen) == cpu_num)
- return 0;
- udelay(1000);
- }
- return 1;
-}
-#endif
-
-void
-machine_crash_shutdown(struct pt_regs *pt)
-{
- /* This function is only called after the system
- * has paniced or is otherwise in a critical state.
- * The minimum amount of code to allow a kexec'd kernel
- * to run successfully needs to happen here.
- *
- * In practice this means shooting down the other cpus in
- * an SMP system.
- */
- kexec_disable_iosapic();
-#ifdef CONFIG_SMP
- /*
- * If kdump_on_init is set and an INIT is asserted here, kdump will
- * be started again via INIT monarch.
- */
- local_irq_disable();
- ia64_set_psr_mc(); /* mask MCA/INIT */
- if (atomic_inc_return(&kdump_in_progress) != 1)
- unw_init_running(kdump_cpu_freeze, NULL);
-
- /*
- * Now this cpu is ready for kdump.
- * Stop all others by IPI or INIT. They could receive INIT from
- * outside and might be INIT monarch, but only thing they have to
- * do is falling into kdump_cpu_freeze().
- *
- * If an INIT is asserted here:
- * - All receivers might be slaves, since some of cpus could already
- * be frozen and INIT might be masked on monarch. In this case,
- * all slaves will be frozen soon since kdump_in_progress will let
- * them into DIE_INIT_SLAVE_LEAVE.
- * - One might be a monarch, but INIT rendezvous will fail since
- * at least this cpu already have INIT masked so it never join
- * to the rendezvous. In this case, all slaves and monarch will
- * be frozen soon with no wait since the INIT rendezvous is skipped
- * by kdump_in_progress.
- */
- kdump_smp_send_stop();
- /* not all cpu response to IPI, send INIT to freeze them */
- if (kdump_wait_cpu_freeze()) {
- kdump_smp_send_init();
- /* wait again, don't go ahead if possible */
- kdump_wait_cpu_freeze();
- }
-#endif
-}
-
-static void
-machine_kdump_on_init(void)
-{
- crash_save_vmcoreinfo();
- local_irq_disable();
- kexec_disable_iosapic();
- machine_kexec(ia64_kimage);
-}
-
-void
-kdump_cpu_freeze(struct unw_frame_info *info, void *arg)
-{
- int cpuid;
-
- local_irq_disable();
- cpuid = smp_processor_id();
- crash_save_this_cpu();
- current->thread.ksp = (__u64)info->sw - 16;
-
- ia64_set_psr_mc(); /* mask MCA/INIT and stop reentrance */
-
- atomic_inc(&kdump_cpu_frozen);
- kdump_status[cpuid] = 1;
- mb();
- for (;;)
- cpu_relax();
-}
-
-static int
-kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
-{
- struct ia64_mca_notify_die *nd;
- struct die_args *args = data;
-
- if (atomic_read(&kdump_in_progress)) {
- switch (val) {
- case DIE_INIT_MONARCH_LEAVE:
- if (!kdump_freeze_monarch)
- break;
- fallthrough;
- case DIE_INIT_SLAVE_LEAVE:
- case DIE_INIT_MONARCH_ENTER:
- case DIE_MCA_RENDZVOUS_LEAVE:
- unw_init_running(kdump_cpu_freeze, NULL);
- break;
- }
- }
-
- if (!kdump_on_init && !kdump_on_fatal_mca)
- return NOTIFY_DONE;
-
- if (!ia64_kimage) {
- if (val == DIE_INIT_MONARCH_LEAVE)
- ia64_mca_printk(KERN_NOTICE
- "%s: kdump not configured\n",
- __func__);
- return NOTIFY_DONE;
- }
-
- if (val != DIE_INIT_MONARCH_LEAVE &&
- val != DIE_INIT_MONARCH_PROCESS &&
- val != DIE_MCA_MONARCH_LEAVE)
- return NOTIFY_DONE;
-
- nd = (struct ia64_mca_notify_die *)args->err;
-
- switch (val) {
- case DIE_INIT_MONARCH_PROCESS:
- /* Reason code 1 means machine check rendezvous*/
- if (kdump_on_init && (nd->sos->rv_rc != 1)) {
- if (atomic_inc_return(&kdump_in_progress) != 1)
- kdump_freeze_monarch = 1;
- }
- break;
- case DIE_INIT_MONARCH_LEAVE:
- /* Reason code 1 means machine check rendezvous*/
- if (kdump_on_init && (nd->sos->rv_rc != 1))
- machine_kdump_on_init();
- break;
- case DIE_MCA_MONARCH_LEAVE:
- /* *(nd->data) indicate if MCA is recoverable */
- if (kdump_on_fatal_mca && !(*(nd->data))) {
- if (atomic_inc_return(&kdump_in_progress) == 1)
- machine_kdump_on_init();
- /* We got fatal MCA while kdump!? No way!! */
- }
- break;
- }
- return NOTIFY_DONE;
-}
-
-#ifdef CONFIG_SYSCTL
-static struct ctl_table kdump_ctl_table[] = {
- {
- .procname = "kdump_on_init",
- .data = &kdump_on_init,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- {
- .procname = "kdump_on_fatal_mca",
- .data = &kdump_on_fatal_mca,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- { }
-};
-#endif
-
-static int
-machine_crash_setup(void)
-{
- /* be notified before default_monarch_init_process */
- static struct notifier_block kdump_init_notifier_nb = {
- .notifier_call = kdump_init_notifier,
- .priority = 1,
- };
- int ret;
- if((ret = register_die_notifier(&kdump_init_notifier_nb)) != 0)
- return ret;
-#ifdef CONFIG_SYSCTL
- register_sysctl("kernel", kdump_ctl_table);
-#endif
- return 0;
-}
-
-__initcall(machine_crash_setup);
-
diff --git a/arch/ia64/kernel/crash_dump.c b/arch/ia64/kernel/crash_dump.c
deleted file mode 100644
index 4ef68e2aa757..000000000000
--- a/arch/ia64/kernel/crash_dump.c
+++ /dev/null
@@ -1,27 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * kernel/crash_dump.c - Memory preserving reboot related code.
- *
- * Created by: Simon Horman <horms@verge.net.au>
- * Original code moved from kernel/crash.c
- * Original code comment copied from the i386 version of this file
- */
-
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/crash_dump.h>
-#include <linux/uio.h>
-#include <asm/page.h>
-
-ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn,
- size_t csize, unsigned long offset)
-{
- void *vaddr;
-
- if (!csize)
- return 0;
- vaddr = __va(pfn<<PAGE_SHIFT);
- csize = copy_to_iter(vaddr + offset, csize, iter);
- return csize;
-}
-
diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c
deleted file mode 100644
index 258d7b70c0f3..000000000000
--- a/arch/ia64/kernel/cyclone.c
+++ /dev/null
@@ -1,125 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/module.h>
-#include <linux/smp.h>
-#include <linux/time.h>
-#include <linux/errno.h>
-#include <linux/timex.h>
-#include <linux/clocksource.h>
-#include <linux/io.h>
-
-/* IBM Summit (EXA) Cyclone counter code*/
-#define CYCLONE_CBAR_ADDR 0xFEB00CD0
-#define CYCLONE_PMCC_OFFSET 0x51A0
-#define CYCLONE_MPMC_OFFSET 0x51D0
-#define CYCLONE_MPCS_OFFSET 0x51A8
-#define CYCLONE_TIMER_FREQ 100000000
-
-int use_cyclone;
-void __init cyclone_setup(void)
-{
- use_cyclone = 1;
-}
-
-static void __iomem *cyclone_mc;
-
-static u64 read_cyclone(struct clocksource *cs)
-{
- return (u64)readq((void __iomem *)cyclone_mc);
-}
-
-static struct clocksource clocksource_cyclone = {
- .name = "cyclone",
- .rating = 300,
- .read = read_cyclone,
- .mask = (1LL << 40) - 1,
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-int __init init_cyclone_clock(void)
-{
- u64 __iomem *reg;
- u64 base; /* saved cyclone base address */
- u64 offset; /* offset from pageaddr to cyclone_timer register */
- int i;
- u32 __iomem *cyclone_timer; /* Cyclone MPMC0 register */
-
- if (!use_cyclone)
- return 0;
-
- printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
-
- /* find base address */
- offset = (CYCLONE_CBAR_ADDR);
- reg = ioremap(offset, sizeof(u64));
- if(!reg){
- printk(KERN_ERR "Summit chipset: Could not find valid CBAR"
- " register.\n");
- use_cyclone = 0;
- return -ENODEV;
- }
- base = readq(reg);
- iounmap(reg);
- if(!base){
- printk(KERN_ERR "Summit chipset: Could not find valid CBAR"
- " value.\n");
- use_cyclone = 0;
- return -ENODEV;
- }
-
- /* setup PMCC */
- offset = (base + CYCLONE_PMCC_OFFSET);
- reg = ioremap(offset, sizeof(u64));
- if(!reg){
- printk(KERN_ERR "Summit chipset: Could not find valid PMCC"
- " register.\n");
- use_cyclone = 0;
- return -ENODEV;
- }
- writel(0x00000001,reg);
- iounmap(reg);
-
- /* setup MPCS */
- offset = (base + CYCLONE_MPCS_OFFSET);
- reg = ioremap(offset, sizeof(u64));
- if(!reg){
- printk(KERN_ERR "Summit chipset: Could not find valid MPCS"
- " register.\n");
- use_cyclone = 0;
- return -ENODEV;
- }
- writel(0x00000001,reg);
- iounmap(reg);
-
- /* map in cyclone_timer */
- offset = (base + CYCLONE_MPMC_OFFSET);
- cyclone_timer = ioremap(offset, sizeof(u32));
- if(!cyclone_timer){
- printk(KERN_ERR "Summit chipset: Could not find valid MPMC"
- " register.\n");
- use_cyclone = 0;
- return -ENODEV;
- }
-
- /*quick test to make sure its ticking*/
- for(i=0; i<3; i++){
- u32 old = readl(cyclone_timer);
- int stall = 100;
- while(stall--) barrier();
- if(readl(cyclone_timer) == old){
- printk(KERN_ERR "Summit chipset: Counter not counting!"
- " DISABLED\n");
- iounmap(cyclone_timer);
- cyclone_timer = NULL;
- use_cyclone = 0;
- return -ENODEV;
- }
- }
- /* initialize last tick */
- cyclone_mc = cyclone_timer;
- clocksource_cyclone.archdata.fsys_mmio = cyclone_timer;
- clocksource_register_hz(&clocksource_cyclone, CYCLONE_TIMER_FREQ);
-
- return 0;
-}
-
-__initcall(init_cyclone_clock);
diff --git a/arch/ia64/kernel/dma-mapping.c b/arch/ia64/kernel/dma-mapping.c
deleted file mode 100644
index cd0c166bfbc2..000000000000
--- a/arch/ia64/kernel/dma-mapping.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/dma-map-ops.h>
-#include <linux/export.h>
-
-/* Set this to 1 if there is a HW IOMMU in the system */
-int iommu_detected __read_mostly;
-
-const struct dma_map_ops *dma_ops;
-EXPORT_SYMBOL(dma_ops);
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
deleted file mode 100644
index 033f5aead88a..000000000000
--- a/arch/ia64/kernel/efi.c
+++ /dev/null
@@ -1,1360 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Extensible Firmware Interface
- *
- * Based on Extensible Firmware Interface Specification version 0.9
- * April 30, 1999
- *
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999-2003 Hewlett-Packard Co.
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- * (c) Copyright 2006 Hewlett-Packard Development Company, L.P.
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- *
- * All EFI Runtime Services are not implemented yet as EFI only
- * supports physical mode addressing on SoftSDV. This is to be fixed
- * in a future version. --drummond 1999-07-20
- *
- * Implemented EFI runtime services and virtual mode calls. --davidm
- *
- * Goutham Rao: <goutham.rao@intel.com>
- * Skip non-WB memory and ignore empty memory ranges.
- */
-#include <linux/module.h>
-#include <linux/memblock.h>
-#include <linux/crash_dump.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/efi.h>
-#include <linux/kexec.h>
-#include <linux/mm.h>
-
-#include <asm/efi.h>
-#include <asm/io.h>
-#include <asm/kregs.h>
-#include <asm/meminit.h>
-#include <asm/processor.h>
-#include <asm/mca.h>
-#include <asm/sal.h>
-#include <asm/setup.h>
-#include <asm/tlbflush.h>
-
-#define EFI_DEBUG 0
-
-#define ESI_TABLE_GUID \
- EFI_GUID(0x43EA58DC, 0xCF28, 0x4b06, 0xB3, \
- 0x91, 0xB7, 0x50, 0x59, 0x34, 0x2B, 0xD4)
-
-static unsigned long mps_phys = EFI_INVALID_TABLE_ADDR;
-static __initdata unsigned long palo_phys;
-
-unsigned long __initdata esi_phys = EFI_INVALID_TABLE_ADDR;
-unsigned long hcdp_phys = EFI_INVALID_TABLE_ADDR;
-unsigned long sal_systab_phys = EFI_INVALID_TABLE_ADDR;
-
-static const efi_config_table_type_t arch_tables[] __initconst = {
- {ESI_TABLE_GUID, &esi_phys, "ESI" },
- {HCDP_TABLE_GUID, &hcdp_phys, "HCDP" },
- {MPS_TABLE_GUID, &mps_phys, "MPS" },
- {PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, &palo_phys, "PALO" },
- {SAL_SYSTEM_TABLE_GUID, &sal_systab_phys, "SALsystab" },
- {},
-};
-
-extern efi_status_t efi_call_phys (void *, ...);
-
-static efi_runtime_services_t *runtime;
-static u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL;
-
-#define efi_call_virt(f, args...) (*(f))(args)
-
-#define STUB_GET_TIME(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_time_cap_t *atc = NULL; \
- efi_status_t ret; \
- \
- if (tc) \
- atc = adjust_arg(tc); \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), \
- adjust_arg(tm), atc); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
-}
-
-#define STUB_SET_TIME(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_set_time (efi_time_t *tm) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), \
- adjust_arg(tm)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
-}
-
-#define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, \
- efi_time_t *tm) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix( \
- (efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \
- adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
-}
-
-#define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_time_t *atm = NULL; \
- efi_status_t ret; \
- \
- if (tm) \
- atm = adjust_arg(tm); \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix( \
- (efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \
- enabled, atm); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
-}
-
-#define STUB_GET_VARIABLE(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \
- unsigned long *data_size, void *data) \
-{ \
- struct ia64_fpreg fr[6]; \
- u32 *aattr = NULL; \
- efi_status_t ret; \
- \
- if (attr) \
- aattr = adjust_arg(attr); \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix( \
- (efi_get_variable_t *) __va(runtime->get_variable), \
- adjust_arg(name), adjust_arg(vendor), aattr, \
- adjust_arg(data_size), adjust_arg(data)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
-}
-
-#define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, \
- efi_guid_t *vendor) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix( \
- (efi_get_next_variable_t *) __va(runtime->get_next_variable), \
- adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
-}
-
-#define STUB_SET_VARIABLE(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, \
- u32 attr, unsigned long data_size, \
- void *data) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix( \
- (efi_set_variable_t *) __va(runtime->set_variable), \
- adjust_arg(name), adjust_arg(vendor), attr, data_size, \
- adjust_arg(data)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
-}
-
-#define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_next_high_mono_count (u32 *count) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \
- __va(runtime->get_next_high_mono_count), \
- adjust_arg(count)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
-}
-
-#define STUB_RESET_SYSTEM(prefix, adjust_arg) \
-static void \
-prefix##_reset_system (int reset_type, efi_status_t status, \
- unsigned long data_size, efi_char16_t *data) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_char16_t *adata = NULL; \
- \
- if (data) \
- adata = adjust_arg(data); \
- \
- ia64_save_scratch_fpregs(fr); \
- efi_call_##prefix( \
- (efi_reset_system_t *) __va(runtime->reset_system), \
- reset_type, status, data_size, adata); \
- /* should not return, but just in case... */ \
- ia64_load_scratch_fpregs(fr); \
-}
-
-#define phys_ptr(arg) ((__typeof__(arg)) ia64_tpa(arg))
-
-STUB_GET_TIME(phys, phys_ptr)
-STUB_SET_TIME(phys, phys_ptr)
-STUB_GET_WAKEUP_TIME(phys, phys_ptr)
-STUB_SET_WAKEUP_TIME(phys, phys_ptr)
-STUB_GET_VARIABLE(phys, phys_ptr)
-STUB_GET_NEXT_VARIABLE(phys, phys_ptr)
-STUB_SET_VARIABLE(phys, phys_ptr)
-STUB_GET_NEXT_HIGH_MONO_COUNT(phys, phys_ptr)
-STUB_RESET_SYSTEM(phys, phys_ptr)
-
-#define id(arg) arg
-
-STUB_GET_TIME(virt, id)
-STUB_SET_TIME(virt, id)
-STUB_GET_WAKEUP_TIME(virt, id)
-STUB_SET_WAKEUP_TIME(virt, id)
-STUB_GET_VARIABLE(virt, id)
-STUB_GET_NEXT_VARIABLE(virt, id)
-STUB_SET_VARIABLE(virt, id)
-STUB_GET_NEXT_HIGH_MONO_COUNT(virt, id)
-STUB_RESET_SYSTEM(virt, id)
-
-void
-efi_gettimeofday (struct timespec64 *ts)
-{
- efi_time_t tm;
-
- if ((*efi.get_time)(&tm, NULL) != EFI_SUCCESS) {
- memset(ts, 0, sizeof(*ts));
- return;
- }
-
- ts->tv_sec = mktime64(tm.year, tm.month, tm.day,
- tm.hour, tm.minute, tm.second);
- ts->tv_nsec = tm.nanosecond;
-}
-
-static int
-is_memory_available (efi_memory_desc_t *md)
-{
- if (!(md->attribute & EFI_MEMORY_WB))
- return 0;
-
- switch (md->type) {
- case EFI_LOADER_CODE:
- case EFI_LOADER_DATA:
- case EFI_BOOT_SERVICES_CODE:
- case EFI_BOOT_SERVICES_DATA:
- case EFI_CONVENTIONAL_MEMORY:
- return 1;
- }
- return 0;
-}
-
-typedef struct kern_memdesc {
- u64 attribute;
- u64 start;
- u64 num_pages;
-} kern_memdesc_t;
-
-static kern_memdesc_t *kern_memmap;
-
-#define efi_md_size(md) (md->num_pages << EFI_PAGE_SHIFT)
-
-static inline u64
-kmd_end(kern_memdesc_t *kmd)
-{
- return (kmd->start + (kmd->num_pages << EFI_PAGE_SHIFT));
-}
-
-static inline u64
-efi_md_end(efi_memory_desc_t *md)
-{
- return (md->phys_addr + efi_md_size(md));
-}
-
-static inline int
-efi_wb(efi_memory_desc_t *md)
-{
- return (md->attribute & EFI_MEMORY_WB);
-}
-
-static inline int
-efi_uc(efi_memory_desc_t *md)
-{
- return (md->attribute & EFI_MEMORY_UC);
-}
-
-static void
-walk (efi_freemem_callback_t callback, void *arg, u64 attr)
-{
- kern_memdesc_t *k;
- u64 start, end, voff;
-
- voff = (attr == EFI_MEMORY_WB) ? PAGE_OFFSET : __IA64_UNCACHED_OFFSET;
- for (k = kern_memmap; k->start != ~0UL; k++) {
- if (k->attribute != attr)
- continue;
- start = PAGE_ALIGN(k->start);
- end = (k->start + (k->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK;
- if (start < end)
- if ((*callback)(start + voff, end + voff, arg) < 0)
- return;
- }
-}
-
-/*
- * Walk the EFI memory map and call CALLBACK once for each EFI memory
- * descriptor that has memory that is available for OS use.
- */
-void
-efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
-{
- walk(callback, arg, EFI_MEMORY_WB);
-}
-
-/*
- * Walk the EFI memory map and call CALLBACK once for each EFI memory
- * descriptor that has memory that is available for uncached allocator.
- */
-void
-efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg)
-{
- walk(callback, arg, EFI_MEMORY_UC);
-}
-
-/*
- * Look for the PAL_CODE region reported by EFI and map it using an
- * ITR to enable safe PAL calls in virtual mode. See IA-64 Processor
- * Abstraction Layer chapter 11 in ADAG
- */
-void *
-efi_get_pal_addr (void)
-{
- void *efi_map_start, *efi_map_end, *p;
- efi_memory_desc_t *md;
- u64 efi_desc_size;
- int pal_code_count = 0;
- u64 vaddr, mask;
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
- for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
- md = p;
- if (md->type != EFI_PAL_CODE)
- continue;
-
- if (++pal_code_count > 1) {
- printk(KERN_ERR "Too many EFI Pal Code memory ranges, "
- "dropped @ %llx\n", md->phys_addr);
- continue;
- }
- /*
- * The only ITLB entry in region 7 that is used is the one
- * installed by __start(). That entry covers a 64MB range.
- */
- mask = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1);
- vaddr = PAGE_OFFSET + md->phys_addr;
-
- /*
- * We must check that the PAL mapping won't overlap with the
- * kernel mapping.
- *
- * PAL code is guaranteed to be aligned on a power of 2 between
- * 4k and 256KB and that only one ITR is needed to map it. This
- * implies that the PAL code is always aligned on its size,
- * i.e., the closest matching page size supported by the TLB.
- * Therefore PAL code is guaranteed never to cross a 64MB unless
- * it is bigger than 64MB (very unlikely!). So for now the
- * following test is enough to determine whether or not we need
- * a dedicated ITR for the PAL code.
- */
- if ((vaddr & mask) == (KERNEL_START & mask)) {
- printk(KERN_INFO "%s: no need to install ITR for PAL code\n",
- __func__);
- continue;
- }
-
- if (efi_md_size(md) > IA64_GRANULE_SIZE)
- panic("Whoa! PAL code size bigger than a granule!");
-
-#if EFI_DEBUG
- mask = ~((1 << IA64_GRANULE_SHIFT) - 1);
-
- printk(KERN_INFO "CPU %d: mapping PAL code "
- "[0x%llx-0x%llx) into [0x%llx-0x%llx)\n",
- smp_processor_id(), md->phys_addr,
- md->phys_addr + efi_md_size(md),
- vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
-#endif
- return __va(md->phys_addr);
- }
- printk(KERN_WARNING "%s: no PAL-code memory-descriptor found\n",
- __func__);
- return NULL;
-}
-
-
-static u8 __init palo_checksum(u8 *buffer, u32 length)
-{
- u8 sum = 0;
- u8 *end = buffer + length;
-
- while (buffer < end)
- sum = (u8) (sum + *(buffer++));
-
- return sum;
-}
-
-/*
- * Parse and handle PALO table which is published at:
- * http://www.dig64.org/home/DIG64_PALO_R1_0.pdf
- */
-static void __init handle_palo(unsigned long phys_addr)
-{
- struct palo_table *palo = __va(phys_addr);
- u8 checksum;
-
- if (strncmp(palo->signature, PALO_SIG, sizeof(PALO_SIG) - 1)) {
- printk(KERN_INFO "PALO signature incorrect.\n");
- return;
- }
-
- checksum = palo_checksum((u8 *)palo, palo->length);
- if (checksum) {
- printk(KERN_INFO "PALO checksum incorrect.\n");
- return;
- }
-
- setup_ptcg_sem(palo->max_tlb_purges, NPTCG_FROM_PALO);
-}
-
-void
-efi_map_pal_code (void)
-{
- void *pal_vaddr = efi_get_pal_addr ();
- u64 psr;
-
- if (!pal_vaddr)
- return;
-
- /*
- * Cannot write to CRx with PSR.ic=1
- */
- psr = ia64_clear_ic();
- ia64_itr(0x1, IA64_TR_PALCODE,
- GRANULEROUNDDOWN((unsigned long) pal_vaddr),
- pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)),
- IA64_GRANULE_SHIFT);
- ia64_set_psr(psr); /* restore psr */
-}
-
-void __init
-efi_init (void)
-{
- const efi_system_table_t *efi_systab;
- void *efi_map_start, *efi_map_end;
- u64 efi_desc_size;
- char *cp;
-
- set_bit(EFI_BOOT, &efi.flags);
- set_bit(EFI_64BIT, &efi.flags);
-
- /*
- * It's too early to be able to use the standard kernel command line
- * support...
- */
- for (cp = boot_command_line; *cp; ) {
- if (memcmp(cp, "mem=", 4) == 0) {
- mem_limit = memparse(cp + 4, &cp);
- } else if (memcmp(cp, "max_addr=", 9) == 0) {
- max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp));
- } else if (memcmp(cp, "min_addr=", 9) == 0) {
- min_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp));
- } else {
- while (*cp != ' ' && *cp)
- ++cp;
- while (*cp == ' ')
- ++cp;
- }
- }
- if (min_addr != 0UL)
- printk(KERN_INFO "Ignoring memory below %lluMB\n",
- min_addr >> 20);
- if (max_addr != ~0UL)
- printk(KERN_INFO "Ignoring memory above %lluMB\n",
- max_addr >> 20);
-
- efi_systab = __va(ia64_boot_param->efi_systab);
-
- /*
- * Verify the EFI Table
- */
- if (efi_systab == NULL)
- panic("Whoa! Can't find EFI system table.\n");
- if (efi_systab_check_header(&efi_systab->hdr))
- panic("Whoa! EFI system table signature incorrect\n");
-
- efi_systab_report_header(&efi_systab->hdr, efi_systab->fw_vendor);
-
- palo_phys = EFI_INVALID_TABLE_ADDR;
-
- if (efi_config_parse_tables(__va(efi_systab->tables),
- efi_systab->nr_tables,
- arch_tables) != 0)
- return;
-
- if (palo_phys != EFI_INVALID_TABLE_ADDR)
- handle_palo(palo_phys);
-
- runtime = __va(efi_systab->runtime);
- efi.get_time = phys_get_time;
- efi.set_time = phys_set_time;
- efi.get_wakeup_time = phys_get_wakeup_time;
- efi.set_wakeup_time = phys_set_wakeup_time;
- efi.get_variable = phys_get_variable;
- efi.get_next_variable = phys_get_next_variable;
- efi.set_variable = phys_set_variable;
- efi.get_next_high_mono_count = phys_get_next_high_mono_count;
- efi.reset_system = phys_reset_system;
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
-#if EFI_DEBUG
- /* print EFI memory map: */
- {
- efi_memory_desc_t *md;
- void *p;
- unsigned int i;
-
- for (i = 0, p = efi_map_start; p < efi_map_end;
- ++i, p += efi_desc_size)
- {
- const char *unit;
- unsigned long size;
- char buf[64];
-
- md = p;
- size = md->num_pages << EFI_PAGE_SHIFT;
-
- if ((size >> 40) > 0) {
- size >>= 40;
- unit = "TB";
- } else if ((size >> 30) > 0) {
- size >>= 30;
- unit = "GB";
- } else if ((size >> 20) > 0) {
- size >>= 20;
- unit = "MB";
- } else {
- size >>= 10;
- unit = "KB";
- }
-
- printk("mem%02d: %s "
- "range=[0x%016llx-0x%016llx) (%4lu%s)\n",
- i, efi_md_typeattr_format(buf, sizeof(buf), md),
- md->phys_addr,
- md->phys_addr + efi_md_size(md), size, unit);
- }
- }
-#endif
-
- efi_map_pal_code();
- efi_enter_virtual_mode();
-}
-
-void
-efi_enter_virtual_mode (void)
-{
- void *efi_map_start, *efi_map_end, *p;
- efi_memory_desc_t *md;
- efi_status_t status;
- u64 efi_desc_size;
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
- for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
- md = p;
- if (md->attribute & EFI_MEMORY_RUNTIME) {
- /*
- * Some descriptors have multiple bits set, so the
- * order of the tests is relevant.
- */
- if (md->attribute & EFI_MEMORY_WB) {
- md->virt_addr = (u64) __va(md->phys_addr);
- } else if (md->attribute & EFI_MEMORY_UC) {
- md->virt_addr = (u64) ioremap(md->phys_addr, 0);
- } else if (md->attribute & EFI_MEMORY_WC) {
-#if 0
- md->virt_addr = ia64_remap(md->phys_addr,
- (_PAGE_A |
- _PAGE_P |
- _PAGE_D |
- _PAGE_MA_WC |
- _PAGE_PL_0 |
- _PAGE_AR_RW));
-#else
- printk(KERN_INFO "EFI_MEMORY_WC mapping\n");
- md->virt_addr = (u64) ioremap(md->phys_addr, 0);
-#endif
- } else if (md->attribute & EFI_MEMORY_WT) {
-#if 0
- md->virt_addr = ia64_remap(md->phys_addr,
- (_PAGE_A |
- _PAGE_P |
- _PAGE_D |
- _PAGE_MA_WT |
- _PAGE_PL_0 |
- _PAGE_AR_RW));
-#else
- printk(KERN_INFO "EFI_MEMORY_WT mapping\n");
- md->virt_addr = (u64) ioremap(md->phys_addr, 0);
-#endif
- }
- }
- }
-
- status = efi_call_phys(__va(runtime->set_virtual_address_map),
- ia64_boot_param->efi_memmap_size,
- efi_desc_size,
- ia64_boot_param->efi_memdesc_version,
- ia64_boot_param->efi_memmap);
- if (status != EFI_SUCCESS) {
- printk(KERN_WARNING "warning: unable to switch EFI into "
- "virtual mode (status=%lu)\n", status);
- return;
- }
-
- set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
-
- /*
- * Now that EFI is in virtual mode, we call the EFI functions more
- * efficiently:
- */
- efi.get_time = virt_get_time;
- efi.set_time = virt_set_time;
- efi.get_wakeup_time = virt_get_wakeup_time;
- efi.set_wakeup_time = virt_set_wakeup_time;
- efi.get_variable = virt_get_variable;
- efi.get_next_variable = virt_get_next_variable;
- efi.set_variable = virt_set_variable;
- efi.get_next_high_mono_count = virt_get_next_high_mono_count;
- efi.reset_system = virt_reset_system;
-}
-
-/*
- * Walk the EFI memory map looking for the I/O port range. There can only be
- * one entry of this type, other I/O port ranges should be described via ACPI.
- */
-u64
-efi_get_iobase (void)
-{
- void *efi_map_start, *efi_map_end, *p;
- efi_memory_desc_t *md;
- u64 efi_desc_size;
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
- for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
- md = p;
- if (md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) {
- if (md->attribute & EFI_MEMORY_UC)
- return md->phys_addr;
- }
- }
- return 0;
-}
-
-static struct kern_memdesc *
-kern_memory_descriptor (unsigned long phys_addr)
-{
- struct kern_memdesc *md;
-
- for (md = kern_memmap; md->start != ~0UL; md++) {
- if (phys_addr - md->start < (md->num_pages << EFI_PAGE_SHIFT))
- return md;
- }
- return NULL;
-}
-
-static efi_memory_desc_t *
-efi_memory_descriptor (unsigned long phys_addr)
-{
- void *efi_map_start, *efi_map_end, *p;
- efi_memory_desc_t *md;
- u64 efi_desc_size;
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
- for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
- md = p;
-
- if (phys_addr - md->phys_addr < efi_md_size(md))
- return md;
- }
- return NULL;
-}
-
-static int
-efi_memmap_intersects (unsigned long phys_addr, unsigned long size)
-{
- void *efi_map_start, *efi_map_end, *p;
- efi_memory_desc_t *md;
- u64 efi_desc_size;
- unsigned long end;
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
- end = phys_addr + size;
-
- for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
- md = p;
- if (md->phys_addr < end && efi_md_end(md) > phys_addr)
- return 1;
- }
- return 0;
-}
-
-int
-efi_mem_type (unsigned long phys_addr)
-{
- efi_memory_desc_t *md = efi_memory_descriptor(phys_addr);
-
- if (md)
- return md->type;
- return -EINVAL;
-}
-
-u64
-efi_mem_attributes (unsigned long phys_addr)
-{
- efi_memory_desc_t *md = efi_memory_descriptor(phys_addr);
-
- if (md)
- return md->attribute;
- return 0;
-}
-EXPORT_SYMBOL(efi_mem_attributes);
-
-u64
-efi_mem_attribute (unsigned long phys_addr, unsigned long size)
-{
- unsigned long end = phys_addr + size;
- efi_memory_desc_t *md = efi_memory_descriptor(phys_addr);
- u64 attr;
-
- if (!md)
- return 0;
-
- /*
- * EFI_MEMORY_RUNTIME is not a memory attribute; it just tells
- * the kernel that firmware needs this region mapped.
- */
- attr = md->attribute & ~EFI_MEMORY_RUNTIME;
- do {
- unsigned long md_end = efi_md_end(md);
-
- if (end <= md_end)
- return attr;
-
- md = efi_memory_descriptor(md_end);
- if (!md || (md->attribute & ~EFI_MEMORY_RUNTIME) != attr)
- return 0;
- } while (md);
- return 0; /* never reached */
-}
-
-u64
-kern_mem_attribute (unsigned long phys_addr, unsigned long size)
-{
- unsigned long end = phys_addr + size;
- struct kern_memdesc *md;
- u64 attr;
-
- /*
- * This is a hack for ioremap calls before we set up kern_memmap.
- * Maybe we should do efi_memmap_init() earlier instead.
- */
- if (!kern_memmap) {
- attr = efi_mem_attribute(phys_addr, size);
- if (attr & EFI_MEMORY_WB)
- return EFI_MEMORY_WB;
- return 0;
- }
-
- md = kern_memory_descriptor(phys_addr);
- if (!md)
- return 0;
-
- attr = md->attribute;
- do {
- unsigned long md_end = kmd_end(md);
-
- if (end <= md_end)
- return attr;
-
- md = kern_memory_descriptor(md_end);
- if (!md || md->attribute != attr)
- return 0;
- } while (md);
- return 0; /* never reached */
-}
-
-int
-valid_phys_addr_range (phys_addr_t phys_addr, unsigned long size)
-{
- u64 attr;
-
- /*
- * /dev/mem reads and writes use copy_to_user(), which implicitly
- * uses a granule-sized kernel identity mapping. It's really
- * only safe to do this for regions in kern_memmap. For more
- * details, see Documentation/arch/ia64/aliasing.rst.
- */
- attr = kern_mem_attribute(phys_addr, size);
- if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC)
- return 1;
- return 0;
-}
-
-int
-valid_mmap_phys_addr_range (unsigned long pfn, unsigned long size)
-{
- unsigned long phys_addr = pfn << PAGE_SHIFT;
- u64 attr;
-
- attr = efi_mem_attribute(phys_addr, size);
-
- /*
- * /dev/mem mmap uses normal user pages, so we don't need the entire
- * granule, but the entire region we're mapping must support the same
- * attribute.
- */
- if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC)
- return 1;
-
- /*
- * Intel firmware doesn't tell us about all the MMIO regions, so
- * in general we have to allow mmap requests. But if EFI *does*
- * tell us about anything inside this region, we should deny it.
- * The user can always map a smaller region to avoid the overlap.
- */
- if (efi_memmap_intersects(phys_addr, size))
- return 0;
-
- return 1;
-}
-
-pgprot_t
-phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size,
- pgprot_t vma_prot)
-{
- unsigned long phys_addr = pfn << PAGE_SHIFT;
- u64 attr;
-
- /*
- * For /dev/mem mmap, we use user mappings, but if the region is
- * in kern_memmap (and hence may be covered by a kernel mapping),
- * we must use the same attribute as the kernel mapping.
- */
- attr = kern_mem_attribute(phys_addr, size);
- if (attr & EFI_MEMORY_WB)
- return pgprot_cacheable(vma_prot);
- else if (attr & EFI_MEMORY_UC)
- return pgprot_noncached(vma_prot);
-
- /*
- * Some chipsets don't support UC access to memory. If
- * WB is supported, we prefer that.
- */
- if (efi_mem_attribute(phys_addr, size) & EFI_MEMORY_WB)
- return pgprot_cacheable(vma_prot);
-
- return pgprot_noncached(vma_prot);
-}
-
-int __init
-efi_uart_console_only(void)
-{
- efi_status_t status;
- char *s, name[] = "ConOut";
- efi_guid_t guid = EFI_GLOBAL_VARIABLE_GUID;
- efi_char16_t *utf16, name_utf16[32];
- unsigned char data[1024];
- unsigned long size = sizeof(data);
- struct efi_generic_dev_path *hdr, *end_addr;
- int uart = 0;
-
- /* Convert to UTF-16 */
- utf16 = name_utf16;
- s = name;
- while (*s)
- *utf16++ = *s++ & 0x7f;
- *utf16 = 0;
-
- status = efi.get_variable(name_utf16, &guid, NULL, &size, data);
- if (status != EFI_SUCCESS) {
- printk(KERN_ERR "No EFI %s variable?\n", name);
- return 0;
- }
-
- hdr = (struct efi_generic_dev_path *) data;
- end_addr = (struct efi_generic_dev_path *) ((u8 *) data + size);
- while (hdr < end_addr) {
- if (hdr->type == EFI_DEV_MSG &&
- hdr->sub_type == EFI_DEV_MSG_UART)
- uart = 1;
- else if (hdr->type == EFI_DEV_END_PATH ||
- hdr->type == EFI_DEV_END_PATH2) {
- if (!uart)
- return 0;
- if (hdr->sub_type == EFI_DEV_END_ENTIRE)
- return 1;
- uart = 0;
- }
- hdr = (struct efi_generic_dev_path *)((u8 *) hdr + hdr->length);
- }
- printk(KERN_ERR "Malformed %s value\n", name);
- return 0;
-}
-
-/*
- * Look for the first granule aligned memory descriptor memory
- * that is big enough to hold EFI memory map. Make sure this
- * descriptor is at least granule sized so it does not get trimmed
- */
-struct kern_memdesc *
-find_memmap_space (void)
-{
- u64 contig_low=0, contig_high=0;
- u64 as = 0, ae;
- void *efi_map_start, *efi_map_end, *p, *q;
- efi_memory_desc_t *md, *pmd = NULL, *check_md;
- u64 space_needed, efi_desc_size;
- unsigned long total_mem = 0;
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
- /*
- * Worst case: we need 3 kernel descriptors for each efi descriptor
- * (if every entry has a WB part in the middle, and UC head and tail),
- * plus one for the end marker.
- */
- space_needed = sizeof(kern_memdesc_t) *
- (3 * (ia64_boot_param->efi_memmap_size/efi_desc_size) + 1);
-
- for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) {
- md = p;
- if (!efi_wb(md)) {
- continue;
- }
- if (pmd == NULL || !efi_wb(pmd) ||
- efi_md_end(pmd) != md->phys_addr) {
- contig_low = GRANULEROUNDUP(md->phys_addr);
- contig_high = efi_md_end(md);
- for (q = p + efi_desc_size; q < efi_map_end;
- q += efi_desc_size) {
- check_md = q;
- if (!efi_wb(check_md))
- break;
- if (contig_high != check_md->phys_addr)
- break;
- contig_high = efi_md_end(check_md);
- }
- contig_high = GRANULEROUNDDOWN(contig_high);
- }
- if (!is_memory_available(md) || md->type == EFI_LOADER_DATA)
- continue;
-
- /* Round ends inward to granule boundaries */
- as = max(contig_low, md->phys_addr);
- ae = min(contig_high, efi_md_end(md));
-
- /* keep within max_addr= and min_addr= command line arg */
- as = max(as, min_addr);
- ae = min(ae, max_addr);
- if (ae <= as)
- continue;
-
- /* avoid going over mem= command line arg */
- if (total_mem + (ae - as) > mem_limit)
- ae -= total_mem + (ae - as) - mem_limit;
-
- if (ae <= as)
- continue;
-
- if (ae - as > space_needed)
- break;
- }
- if (p >= efi_map_end)
- panic("Can't allocate space for kernel memory descriptors");
-
- return __va(as);
-}
-
-/*
- * Walk the EFI memory map and gather all memory available for kernel
- * to use. We can allocate partial granules only if the unavailable
- * parts exist, and are WB.
- */
-unsigned long
-efi_memmap_init(u64 *s, u64 *e)
-{
- struct kern_memdesc *k, *prev = NULL;
- u64 contig_low=0, contig_high=0;
- u64 as, ae, lim;
- void *efi_map_start, *efi_map_end, *p, *q;
- efi_memory_desc_t *md, *pmd = NULL, *check_md;
- u64 efi_desc_size;
- unsigned long total_mem = 0;
-
- k = kern_memmap = find_memmap_space();
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
- for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) {
- md = p;
- if (!efi_wb(md)) {
- if (efi_uc(md) &&
- (md->type == EFI_CONVENTIONAL_MEMORY ||
- md->type == EFI_BOOT_SERVICES_DATA)) {
- k->attribute = EFI_MEMORY_UC;
- k->start = md->phys_addr;
- k->num_pages = md->num_pages;
- k++;
- }
- continue;
- }
- if (pmd == NULL || !efi_wb(pmd) ||
- efi_md_end(pmd) != md->phys_addr) {
- contig_low = GRANULEROUNDUP(md->phys_addr);
- contig_high = efi_md_end(md);
- for (q = p + efi_desc_size; q < efi_map_end;
- q += efi_desc_size) {
- check_md = q;
- if (!efi_wb(check_md))
- break;
- if (contig_high != check_md->phys_addr)
- break;
- contig_high = efi_md_end(check_md);
- }
- contig_high = GRANULEROUNDDOWN(contig_high);
- }
- if (!is_memory_available(md))
- continue;
-
- /*
- * Round ends inward to granule boundaries
- * Give trimmings to uncached allocator
- */
- if (md->phys_addr < contig_low) {
- lim = min(efi_md_end(md), contig_low);
- if (efi_uc(md)) {
- if (k > kern_memmap &&
- (k-1)->attribute == EFI_MEMORY_UC &&
- kmd_end(k-1) == md->phys_addr) {
- (k-1)->num_pages +=
- (lim - md->phys_addr)
- >> EFI_PAGE_SHIFT;
- } else {
- k->attribute = EFI_MEMORY_UC;
- k->start = md->phys_addr;
- k->num_pages = (lim - md->phys_addr)
- >> EFI_PAGE_SHIFT;
- k++;
- }
- }
- as = contig_low;
- } else
- as = md->phys_addr;
-
- if (efi_md_end(md) > contig_high) {
- lim = max(md->phys_addr, contig_high);
- if (efi_uc(md)) {
- if (lim == md->phys_addr && k > kern_memmap &&
- (k-1)->attribute == EFI_MEMORY_UC &&
- kmd_end(k-1) == md->phys_addr) {
- (k-1)->num_pages += md->num_pages;
- } else {
- k->attribute = EFI_MEMORY_UC;
- k->start = lim;
- k->num_pages = (efi_md_end(md) - lim)
- >> EFI_PAGE_SHIFT;
- k++;
- }
- }
- ae = contig_high;
- } else
- ae = efi_md_end(md);
-
- /* keep within max_addr= and min_addr= command line arg */
- as = max(as, min_addr);
- ae = min(ae, max_addr);
- if (ae <= as)
- continue;
-
- /* avoid going over mem= command line arg */
- if (total_mem + (ae - as) > mem_limit)
- ae -= total_mem + (ae - as) - mem_limit;
-
- if (ae <= as)
- continue;
- if (prev && kmd_end(prev) == md->phys_addr) {
- prev->num_pages += (ae - as) >> EFI_PAGE_SHIFT;
- total_mem += ae - as;
- continue;
- }
- k->attribute = EFI_MEMORY_WB;
- k->start = as;
- k->num_pages = (ae - as) >> EFI_PAGE_SHIFT;
- total_mem += ae - as;
- prev = k++;
- }
- k->start = ~0L; /* end-marker */
-
- /* reserve the memory we are using for kern_memmap */
- *s = (u64)kern_memmap;
- *e = (u64)++k;
-
- return total_mem;
-}
-
-void
-efi_initialize_iomem_resources(struct resource *code_resource,
- struct resource *data_resource,
- struct resource *bss_resource)
-{
- struct resource *res;
- void *efi_map_start, *efi_map_end, *p;
- efi_memory_desc_t *md;
- u64 efi_desc_size;
- char *name;
- unsigned long flags, desc;
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
- res = NULL;
-
- for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
- md = p;
-
- if (md->num_pages == 0) /* should not happen */
- continue;
-
- flags = IORESOURCE_MEM | IORESOURCE_BUSY;
- desc = IORES_DESC_NONE;
-
- switch (md->type) {
-
- case EFI_MEMORY_MAPPED_IO:
- case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
- continue;
-
- case EFI_LOADER_CODE:
- case EFI_LOADER_DATA:
- case EFI_BOOT_SERVICES_DATA:
- case EFI_BOOT_SERVICES_CODE:
- case EFI_CONVENTIONAL_MEMORY:
- if (md->attribute & EFI_MEMORY_WP) {
- name = "System ROM";
- flags |= IORESOURCE_READONLY;
- } else if (md->attribute == EFI_MEMORY_UC) {
- name = "Uncached RAM";
- } else {
- name = "System RAM";
- flags |= IORESOURCE_SYSRAM;
- }
- break;
-
- case EFI_ACPI_MEMORY_NVS:
- name = "ACPI Non-volatile Storage";
- desc = IORES_DESC_ACPI_NV_STORAGE;
- break;
-
- case EFI_UNUSABLE_MEMORY:
- name = "reserved";
- flags |= IORESOURCE_DISABLED;
- break;
-
- case EFI_PERSISTENT_MEMORY:
- name = "Persistent Memory";
- desc = IORES_DESC_PERSISTENT_MEMORY;
- break;
-
- case EFI_RESERVED_TYPE:
- case EFI_RUNTIME_SERVICES_CODE:
- case EFI_RUNTIME_SERVICES_DATA:
- case EFI_ACPI_RECLAIM_MEMORY:
- default:
- name = "reserved";
- break;
- }
-
- if ((res = kzalloc(sizeof(struct resource),
- GFP_KERNEL)) == NULL) {
- printk(KERN_ERR
- "failed to allocate resource for iomem\n");
- return;
- }
-
- res->name = name;
- res->start = md->phys_addr;
- res->end = md->phys_addr + efi_md_size(md) - 1;
- res->flags = flags;
- res->desc = desc;
-
- if (insert_resource(&iomem_resource, res) < 0)
- kfree(res);
- else {
- /*
- * We don't know which region contains
- * kernel data so we try it repeatedly and
- * let the resource manager test it.
- */
- insert_resource(res, code_resource);
- insert_resource(res, data_resource);
- insert_resource(res, bss_resource);
-#ifdef CONFIG_KEXEC
- insert_resource(res, &efi_memmap_res);
- insert_resource(res, &boot_param_res);
- if (crashk_res.end > crashk_res.start)
- insert_resource(res, &crashk_res);
-#endif
- }
- }
-}
-
-#ifdef CONFIG_KEXEC
-/* find a block of memory aligned to 64M exclude reserved regions
- rsvd_regions are sorted
- */
-unsigned long __init
-kdump_find_rsvd_region (unsigned long size, struct rsvd_region *r, int n)
-{
- int i;
- u64 start, end;
- u64 alignment = 1UL << _PAGE_SIZE_64M;
- void *efi_map_start, *efi_map_end, *p;
- efi_memory_desc_t *md;
- u64 efi_desc_size;
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
- for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
- md = p;
- if (!efi_wb(md))
- continue;
- start = ALIGN(md->phys_addr, alignment);
- end = efi_md_end(md);
- for (i = 0; i < n; i++) {
- if (__pa(r[i].start) >= start && __pa(r[i].end) < end) {
- if (__pa(r[i].start) > start + size)
- return start;
- start = ALIGN(__pa(r[i].end), alignment);
- if (i < n-1 &&
- __pa(r[i+1].start) < start + size)
- continue;
- else
- break;
- }
- }
- if (end > start + size)
- return start;
- }
-
- printk(KERN_WARNING
- "Cannot reserve 0x%lx byte of memory for crashdump\n", size);
- return ~0UL;
-}
-#endif
-
-#ifdef CONFIG_CRASH_DUMP
-/* locate the size find a the descriptor at a certain address */
-unsigned long __init
-vmcore_find_descriptor_size (unsigned long address)
-{
- void *efi_map_start, *efi_map_end, *p;
- efi_memory_desc_t *md;
- u64 efi_desc_size;
- unsigned long ret = 0;
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
- for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
- md = p;
- if (efi_wb(md) && md->type == EFI_LOADER_DATA
- && md->phys_addr == address) {
- ret = efi_md_size(md);
- break;
- }
- }
-
- if (ret == 0)
- printk(KERN_WARNING "Cannot locate EFI vmcore descriptor\n");
-
- return ret;
-}
-#endif
-
-char *efi_systab_show_arch(char *str)
-{
- if (mps_phys != EFI_INVALID_TABLE_ADDR)
- str += sprintf(str, "MPS=0x%lx\n", mps_phys);
- if (hcdp_phys != EFI_INVALID_TABLE_ADDR)
- str += sprintf(str, "HCDP=0x%lx\n", hcdp_phys);
- return str;
-}
diff --git a/arch/ia64/kernel/efi_stub.S b/arch/ia64/kernel/efi_stub.S
deleted file mode 100644
index 1fd61b78fb29..000000000000
--- a/arch/ia64/kernel/efi_stub.S
+++ /dev/null
@@ -1,87 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * EFI call stub.
- *
- * Copyright (C) 1999-2001 Hewlett-Packard Co
- * David Mosberger <davidm@hpl.hp.com>
- *
- * This stub allows us to make EFI calls in physical mode with interrupts
- * turned off. We need this because we can't call SetVirtualMap() until
- * the kernel has booted far enough to allow allocation of struct vm_area_struct
- * entries (which we would need to map stuff with memory attributes other
- * than uncached or writeback...). Since the GetTime() service gets called
- * earlier than that, we need to be able to make physical mode EFI calls from
- * the kernel.
- */
-
-/*
- * PSR settings as per SAL spec (Chapter 8 in the "IA-64 System
- * Abstraction Layer Specification", revision 2.6e). Note that
- * psr.dfl and psr.dfh MUST be cleared, despite what this manual says.
- * Otherwise, SAL dies whenever it's trying to do an IA-32 BIOS call
- * (the br.ia instruction fails unless psr.dfl and psr.dfh are
- * cleared). Fortunately, SAL promises not to touch the floating
- * point regs, so at least we don't have to save f2-f127.
- */
-#define PSR_BITS_TO_CLEAR \
- (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_RT | \
- IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED | \
- IA64_PSR_DFL | IA64_PSR_DFH)
-
-#define PSR_BITS_TO_SET \
- (IA64_PSR_BN)
-
-#include <asm/processor.h>
-#include <asm/asmmacro.h>
-
-/*
- * Inputs:
- * in0 = address of function descriptor of EFI routine to call
- * in1..in7 = arguments to routine
- *
- * Outputs:
- * r8 = EFI_STATUS returned by called function
- */
-
-GLOBAL_ENTRY(efi_call_phys)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
- alloc loc1=ar.pfs,8,7,7,0
- ld8 r2=[in0],8 // load EFI function's entry point
- mov loc0=rp
- .body
- ;;
- mov loc2=gp // save global pointer
- mov loc4=ar.rsc // save RSE configuration
- mov ar.rsc=0 // put RSE in enforced lazy, LE mode
- ;;
- ld8 gp=[in0] // load EFI function's global pointer
- movl r16=PSR_BITS_TO_CLEAR
- mov loc3=psr // save processor status word
- movl r17=PSR_BITS_TO_SET
- ;;
- or loc3=loc3,r17
- mov b6=r2
- ;;
- andcm r16=loc3,r16 // get psr with IT, DT, and RT bits cleared
- br.call.sptk.many rp=ia64_switch_mode_phys
-.ret0: mov out4=in5
- mov out0=in1
- mov out1=in2
- mov out2=in3
- mov out3=in4
- mov out5=in6
- mov out6=in7
- mov loc5=r19
- mov loc6=r20
- br.call.sptk.many rp=b6 // call the EFI function
-.ret1: mov ar.rsc=0 // put RSE in enforced lazy, LE mode
- mov r16=loc3
- mov r19=loc5
- mov r20=loc6
- br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
-.ret2: mov ar.rsc=loc4 // restore RSE configuration
- mov ar.pfs=loc1
- mov rp=loc0
- mov gp=loc2
- br.ret.sptk.many rp
-END(efi_call_phys)
diff --git a/arch/ia64/kernel/elfcore.c b/arch/ia64/kernel/elfcore.c
deleted file mode 100644
index 8895df121540..000000000000
--- a/arch/ia64/kernel/elfcore.c
+++ /dev/null
@@ -1,77 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/elf.h>
-#include <linux/coredump.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-
-#include <asm/elf.h>
-
-
-Elf64_Half elf_core_extra_phdrs(struct coredump_params *cprm)
-{
- return GATE_EHDR->e_phnum;
-}
-
-int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
-{
- const struct elf_phdr *const gate_phdrs =
- (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
- int i;
- Elf64_Off ofs = 0;
-
- for (i = 0; i < GATE_EHDR->e_phnum; ++i) {
- struct elf_phdr phdr = gate_phdrs[i];
-
- if (phdr.p_type == PT_LOAD) {
- phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz);
- phdr.p_filesz = phdr.p_memsz;
- if (ofs == 0) {
- ofs = phdr.p_offset = offset;
- offset += phdr.p_filesz;
- } else {
- phdr.p_offset = ofs;
- }
- } else {
- phdr.p_offset += ofs;
- }
- phdr.p_paddr = 0; /* match other core phdrs */
- if (!dump_emit(cprm, &phdr, sizeof(phdr)))
- return 0;
- }
- return 1;
-}
-
-int elf_core_write_extra_data(struct coredump_params *cprm)
-{
- const struct elf_phdr *const gate_phdrs =
- (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
- int i;
-
- for (i = 0; i < GATE_EHDR->e_phnum; ++i) {
- if (gate_phdrs[i].p_type == PT_LOAD) {
- void *addr = (void *)gate_phdrs[i].p_vaddr;
- size_t memsz = PAGE_ALIGN(gate_phdrs[i].p_memsz);
-
- if (!dump_emit(cprm, addr, memsz))
- return 0;
- break;
- }
- }
- return 1;
-}
-
-size_t elf_core_extra_data_size(struct coredump_params *cprm)
-{
- const struct elf_phdr *const gate_phdrs =
- (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
- int i;
- size_t size = 0;
-
- for (i = 0; i < GATE_EHDR->e_phnum; ++i) {
- if (gate_phdrs[i].p_type == PT_LOAD) {
- size += PAGE_ALIGN(gate_phdrs[i].p_memsz);
- break;
- }
- }
- return size;
-}
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
deleted file mode 100644
index ac06d44b9b27..000000000000
--- a/arch/ia64/kernel/entry.S
+++ /dev/null
@@ -1,1427 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * arch/ia64/kernel/entry.S
- *
- * Kernel entry points.
- *
- * Copyright (C) 1998-2003, 2005 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999, 2002-2003
- * Asit Mallick <Asit.K.Mallick@intel.com>
- * Don Dugger <Don.Dugger@intel.com>
- * Suresh Siddha <suresh.b.siddha@intel.com>
- * Fenghua Yu <fenghua.yu@intel.com>
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- */
-/*
- * ia64_switch_to now places correct virtual mapping in in TR2 for
- * kernel stack. This allows us to handle interrupts without changing
- * to physical mode.
- *
- * Jonathan Nicklin <nicklin@missioncriticallinux.com>
- * Patrick O'Rourke <orourke@missioncriticallinux.com>
- * 11/07/2000
- */
-/*
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- * VA Linux Systems Japan K.K.
- * pv_ops.
- */
-/*
- * Global (preserved) predicate usage on syscall entry/exit path:
- *
- * pKStk: See entry.h.
- * pUStk: See entry.h.
- * pSys: See entry.h.
- * pNonSys: !pSys
- */
-
-#include <linux/export.h>
-#include <linux/pgtable.h>
-#include <asm/asmmacro.h>
-#include <asm/cache.h>
-#include <asm/errno.h>
-#include <asm/kregs.h>
-#include <asm/asm-offsets.h>
-#include <asm/percpu.h>
-#include <asm/processor.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/ftrace.h>
-
-#include "minstate.h"
-
- /*
- * execve() is special because in case of success, we need to
- * setup a null register window frame.
- */
-ENTRY(ia64_execve)
- /*
- * Allocate 8 input registers since ptrace() may clobber them
- */
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
- alloc loc1=ar.pfs,8,2,3,0
- mov loc0=rp
- .body
- mov out0=in0 // filename
- ;; // stop bit between alloc and call
- mov out1=in1 // argv
- mov out2=in2 // envp
- br.call.sptk.many rp=sys_execve
-.ret0:
- cmp4.ge p6,p7=r8,r0
- mov ar.pfs=loc1 // restore ar.pfs
- sxt4 r8=r8 // return 64-bit result
- ;;
- stf.spill [sp]=f0
- mov rp=loc0
-(p6) mov ar.pfs=r0 // clear ar.pfs on success
-(p7) br.ret.sptk.many rp
-
- /*
- * In theory, we'd have to zap this state only to prevent leaking of
- * security sensitive state (e.g., if current->mm->dumpable is zero). However,
- * this executes in less than 20 cycles even on Itanium, so it's not worth
- * optimizing for...).
- */
- mov ar.unat=0; mov ar.lc=0
- mov r4=0; mov f2=f0; mov b1=r0
- mov r5=0; mov f3=f0; mov b2=r0
- mov r6=0; mov f4=f0; mov b3=r0
- mov r7=0; mov f5=f0; mov b4=r0
- ldf.fill f12=[sp]; mov f13=f0; mov b5=r0
- ldf.fill f14=[sp]; ldf.fill f15=[sp]; mov f16=f0
- ldf.fill f17=[sp]; ldf.fill f18=[sp]; mov f19=f0
- ldf.fill f20=[sp]; ldf.fill f21=[sp]; mov f22=f0
- ldf.fill f23=[sp]; ldf.fill f24=[sp]; mov f25=f0
- ldf.fill f26=[sp]; ldf.fill f27=[sp]; mov f28=f0
- ldf.fill f29=[sp]; ldf.fill f30=[sp]; mov f31=f0
- br.ret.sptk.many rp
-END(ia64_execve)
-
-/*
- * sys_clone2(u64 flags, u64 ustack_base, u64 ustack_size, u64 parent_tidptr, u64 child_tidptr,
- * u64 tls)
- */
-GLOBAL_ENTRY(sys_clone2)
- /*
- * Allocate 8 input registers since ptrace() may clobber them
- */
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
- alloc r16=ar.pfs,8,2,6,0
- DO_SAVE_SWITCH_STACK
- mov loc0=rp
- mov loc1=r16 // save ar.pfs across ia64_clone
- .body
- mov out0=in0
- mov out1=in1
- mov out2=in2
- mov out3=in3
- mov out4=in4
- mov out5=in5
- br.call.sptk.many rp=ia64_clone
-.ret1: .restore sp
- adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack
- mov ar.pfs=loc1
- mov rp=loc0
- br.ret.sptk.many rp
-END(sys_clone2)
-
-/*
- * sys_clone(u64 flags, u64 ustack_base, u64 parent_tidptr, u64 child_tidptr, u64 tls)
- * Deprecated. Use sys_clone2() instead.
- */
-GLOBAL_ENTRY(sys_clone)
- /*
- * Allocate 8 input registers since ptrace() may clobber them
- */
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
- alloc r16=ar.pfs,8,2,6,0
- DO_SAVE_SWITCH_STACK
- mov loc0=rp
- mov loc1=r16 // save ar.pfs across ia64_clone
- .body
- mov out0=in0
- mov out1=in1
- mov out2=16 // stacksize (compensates for 16-byte scratch area)
- mov out3=in3
- mov out4=in4
- mov out5=in5
- br.call.sptk.many rp=ia64_clone
-.ret2: .restore sp
- adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack
- mov ar.pfs=loc1
- mov rp=loc0
- br.ret.sptk.many rp
-END(sys_clone)
-
-/*
- * prev_task <- ia64_switch_to(struct task_struct *next)
- * With Ingo's new scheduler, interrupts are disabled when this routine gets
- * called. The code starting at .map relies on this. The rest of the code
- * doesn't care about the interrupt masking status.
- */
-GLOBAL_ENTRY(ia64_switch_to)
- .prologue
- alloc r16=ar.pfs,1,0,0,0
- DO_SAVE_SWITCH_STACK
- .body
-
- adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13
- movl r25=init_task
- mov r27=IA64_KR(CURRENT_STACK)
- adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0
- dep r20=0,in0,61,3 // physical address of "next"
- ;;
- st8 [r22]=sp // save kernel stack pointer of old task
- shr.u r26=r20,IA64_GRANULE_SHIFT
- cmp.eq p7,p6=r25,in0
- ;;
- /*
- * If we've already mapped this task's page, we can skip doing it again.
- */
-(p6) cmp.eq p7,p6=r26,r27
-(p6) br.cond.dpnt .map
- ;;
-.done:
- ld8 sp=[r21] // load kernel stack pointer of new task
- MOV_TO_KR(CURRENT, in0, r8, r9) // update "current" application register
- mov r8=r13 // return pointer to previously running task
- mov r13=in0 // set "current" pointer
- ;;
- DO_LOAD_SWITCH_STACK
-
-#ifdef CONFIG_SMP
- sync.i // ensure "fc"s done by this CPU are visible on other CPUs
-#endif
- br.ret.sptk.many rp // boogie on out in new context
-
-.map:
- RSM_PSR_IC(r25) // interrupts (psr.i) are already disabled here
- movl r25=PAGE_KERNEL
- ;;
- srlz.d
- or r23=r25,r20 // construct PA | page properties
- mov r25=IA64_GRANULE_SHIFT<<2
- ;;
- MOV_TO_ITIR(p0, r25, r8)
- MOV_TO_IFA(in0, r8) // VA of next task...
- ;;
- mov r25=IA64_TR_CURRENT_STACK
- MOV_TO_KR(CURRENT_STACK, r26, r8, r9) // remember last page we mapped...
- ;;
- itr.d dtr[r25]=r23 // wire in new mapping...
- SSM_PSR_IC_AND_SRLZ_D(r8, r9) // reenable the psr.ic bit
- br.cond.sptk .done
-END(ia64_switch_to)
-
-/*
- * Note that interrupts are enabled during save_switch_stack and load_switch_stack. This
- * means that we may get an interrupt with "sp" pointing to the new kernel stack while
- * ar.bspstore is still pointing to the old kernel backing store area. Since ar.rsc,
- * ar.rnat, ar.bsp, and ar.bspstore are all preserved by interrupts, this is not a
- * problem. Also, we don't need to specify unwind information for preserved registers
- * that are not modified in save_switch_stack as the right unwind information is already
- * specified at the call-site of save_switch_stack.
- */
-
-/*
- * save_switch_stack:
- * - r16 holds ar.pfs
- * - b7 holds address to return to
- * - rp (b0) holds return address to save
- */
-GLOBAL_ENTRY(save_switch_stack)
- .prologue
- .altrp b7
- flushrs // flush dirty regs to backing store (must be first in insn group)
- .save @priunat,r17
- mov r17=ar.unat // preserve caller's
- .body
-#ifdef CONFIG_ITANIUM
- adds r2=16+128,sp
- adds r3=16+64,sp
- adds r14=SW(R4)+16,sp
- ;;
- st8.spill [r14]=r4,16 // spill r4
- lfetch.fault.excl.nt1 [r3],128
- ;;
- lfetch.fault.excl.nt1 [r2],128
- lfetch.fault.excl.nt1 [r3],128
- ;;
- lfetch.fault.excl [r2]
- lfetch.fault.excl [r3]
- adds r15=SW(R5)+16,sp
-#else
- add r2=16+3*128,sp
- add r3=16,sp
- add r14=SW(R4)+16,sp
- ;;
- st8.spill [r14]=r4,SW(R6)-SW(R4) // spill r4 and prefetch offset 0x1c0
- lfetch.fault.excl.nt1 [r3],128 // prefetch offset 0x010
- ;;
- lfetch.fault.excl.nt1 [r3],128 // prefetch offset 0x090
- lfetch.fault.excl.nt1 [r2],128 // prefetch offset 0x190
- ;;
- lfetch.fault.excl.nt1 [r3] // prefetch offset 0x110
- lfetch.fault.excl.nt1 [r2] // prefetch offset 0x210
- adds r15=SW(R5)+16,sp
-#endif
- ;;
- st8.spill [r15]=r5,SW(R7)-SW(R5) // spill r5
- mov.m ar.rsc=0 // put RSE in mode: enforced lazy, little endian, pl 0
- add r2=SW(F2)+16,sp // r2 = &sw->f2
- ;;
- st8.spill [r14]=r6,SW(B0)-SW(R6) // spill r6
- mov.m r18=ar.fpsr // preserve fpsr
- add r3=SW(F3)+16,sp // r3 = &sw->f3
- ;;
- stf.spill [r2]=f2,32
- mov.m r19=ar.rnat
- mov r21=b0
-
- stf.spill [r3]=f3,32
- st8.spill [r15]=r7,SW(B2)-SW(R7) // spill r7
- mov r22=b1
- ;;
- // since we're done with the spills, read and save ar.unat:
- mov.m r29=ar.unat
- mov.m r20=ar.bspstore
- mov r23=b2
- stf.spill [r2]=f4,32
- stf.spill [r3]=f5,32
- mov r24=b3
- ;;
- st8 [r14]=r21,SW(B1)-SW(B0) // save b0
- st8 [r15]=r23,SW(B3)-SW(B2) // save b2
- mov r25=b4
- mov r26=b5
- ;;
- st8 [r14]=r22,SW(B4)-SW(B1) // save b1
- st8 [r15]=r24,SW(AR_PFS)-SW(B3) // save b3
- mov r21=ar.lc // I-unit
- stf.spill [r2]=f12,32
- stf.spill [r3]=f13,32
- ;;
- st8 [r14]=r25,SW(B5)-SW(B4) // save b4
- st8 [r15]=r16,SW(AR_LC)-SW(AR_PFS) // save ar.pfs
- stf.spill [r2]=f14,32
- stf.spill [r3]=f15,32
- ;;
- st8 [r14]=r26 // save b5
- st8 [r15]=r21 // save ar.lc
- stf.spill [r2]=f16,32
- stf.spill [r3]=f17,32
- ;;
- stf.spill [r2]=f18,32
- stf.spill [r3]=f19,32
- ;;
- stf.spill [r2]=f20,32
- stf.spill [r3]=f21,32
- ;;
- stf.spill [r2]=f22,32
- stf.spill [r3]=f23,32
- ;;
- stf.spill [r2]=f24,32
- stf.spill [r3]=f25,32
- ;;
- stf.spill [r2]=f26,32
- stf.spill [r3]=f27,32
- ;;
- stf.spill [r2]=f28,32
- stf.spill [r3]=f29,32
- ;;
- stf.spill [r2]=f30,SW(AR_UNAT)-SW(F30)
- stf.spill [r3]=f31,SW(PR)-SW(F31)
- add r14=SW(CALLER_UNAT)+16,sp
- ;;
- st8 [r2]=r29,SW(AR_RNAT)-SW(AR_UNAT) // save ar.unat
- st8 [r14]=r17,SW(AR_FPSR)-SW(CALLER_UNAT) // save caller_unat
- mov r21=pr
- ;;
- st8 [r2]=r19,SW(AR_BSPSTORE)-SW(AR_RNAT) // save ar.rnat
- st8 [r3]=r21 // save predicate registers
- ;;
- st8 [r2]=r20 // save ar.bspstore
- st8 [r14]=r18 // save fpsr
- mov ar.rsc=3 // put RSE back into eager mode, pl 0
- br.cond.sptk.many b7
-END(save_switch_stack)
-
-/*
- * load_switch_stack:
- * - "invala" MUST be done at call site (normally in DO_LOAD_SWITCH_STACK)
- * - b7 holds address to return to
- * - must not touch r8-r11
- */
-GLOBAL_ENTRY(load_switch_stack)
- .prologue
- .altrp b7
-
- .body
- lfetch.fault.nt1 [sp]
- adds r2=SW(AR_BSPSTORE)+16,sp
- adds r3=SW(AR_UNAT)+16,sp
- mov ar.rsc=0 // put RSE into enforced lazy mode
- adds r14=SW(CALLER_UNAT)+16,sp
- adds r15=SW(AR_FPSR)+16,sp
- ;;
- ld8 r27=[r2],(SW(B0)-SW(AR_BSPSTORE)) // bspstore
- ld8 r29=[r3],(SW(B1)-SW(AR_UNAT)) // unat
- ;;
- ld8 r21=[r2],16 // restore b0
- ld8 r22=[r3],16 // restore b1
- ;;
- ld8 r23=[r2],16 // restore b2
- ld8 r24=[r3],16 // restore b3
- ;;
- ld8 r25=[r2],16 // restore b4
- ld8 r26=[r3],16 // restore b5
- ;;
- ld8 r16=[r2],(SW(PR)-SW(AR_PFS)) // ar.pfs
- ld8 r17=[r3],(SW(AR_RNAT)-SW(AR_LC)) // ar.lc
- ;;
- ld8 r28=[r2] // restore pr
- ld8 r30=[r3] // restore rnat
- ;;
- ld8 r18=[r14],16 // restore caller's unat
- ld8 r19=[r15],24 // restore fpsr
- ;;
- ldf.fill f2=[r14],32
- ldf.fill f3=[r15],32
- ;;
- ldf.fill f4=[r14],32
- ldf.fill f5=[r15],32
- ;;
- ldf.fill f12=[r14],32
- ldf.fill f13=[r15],32
- ;;
- ldf.fill f14=[r14],32
- ldf.fill f15=[r15],32
- ;;
- ldf.fill f16=[r14],32
- ldf.fill f17=[r15],32
- ;;
- ldf.fill f18=[r14],32
- ldf.fill f19=[r15],32
- mov b0=r21
- ;;
- ldf.fill f20=[r14],32
- ldf.fill f21=[r15],32
- mov b1=r22
- ;;
- ldf.fill f22=[r14],32
- ldf.fill f23=[r15],32
- mov b2=r23
- ;;
- mov ar.bspstore=r27
- mov ar.unat=r29 // establish unat holding the NaT bits for r4-r7
- mov b3=r24
- ;;
- ldf.fill f24=[r14],32
- ldf.fill f25=[r15],32
- mov b4=r25
- ;;
- ldf.fill f26=[r14],32
- ldf.fill f27=[r15],32
- mov b5=r26
- ;;
- ldf.fill f28=[r14],32
- ldf.fill f29=[r15],32
- mov ar.pfs=r16
- ;;
- ldf.fill f30=[r14],32
- ldf.fill f31=[r15],24
- mov ar.lc=r17
- ;;
- ld8.fill r4=[r14],16
- ld8.fill r5=[r15],16
- mov pr=r28,-1
- ;;
- ld8.fill r6=[r14],16
- ld8.fill r7=[r15],16
-
- mov ar.unat=r18 // restore caller's unat
- mov ar.rnat=r30 // must restore after bspstore but before rsc!
- mov ar.fpsr=r19 // restore fpsr
- mov ar.rsc=3 // put RSE back into eager mode, pl 0
- br.cond.sptk.many b7
-END(load_switch_stack)
-
- /*
- * Invoke a system call, but do some tracing before and after the call.
- * We MUST preserve the current register frame throughout this routine
- * because some system calls (such as ia64_execve) directly
- * manipulate ar.pfs.
- */
-GLOBAL_ENTRY(ia64_trace_syscall)
- PT_REGS_UNWIND_INFO(0)
- /*
- * We need to preserve the scratch registers f6-f11 in case the system
- * call is sigreturn.
- */
- adds r16=PT(F6)+16,sp
- adds r17=PT(F7)+16,sp
- ;;
- stf.spill [r16]=f6,32
- stf.spill [r17]=f7,32
- ;;
- stf.spill [r16]=f8,32
- stf.spill [r17]=f9,32
- ;;
- stf.spill [r16]=f10
- stf.spill [r17]=f11
- br.call.sptk.many rp=syscall_trace_enter // give parent a chance to catch syscall args
- cmp.lt p6,p0=r8,r0 // check tracehook
- adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8
- adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10
- mov r10=0
-(p6) br.cond.sptk strace_error // syscall failed ->
- adds r16=PT(F6)+16,sp
- adds r17=PT(F7)+16,sp
- ;;
- ldf.fill f6=[r16],32
- ldf.fill f7=[r17],32
- ;;
- ldf.fill f8=[r16],32
- ldf.fill f9=[r17],32
- ;;
- ldf.fill f10=[r16]
- ldf.fill f11=[r17]
- // the syscall number may have changed, so re-load it and re-calculate the
- // syscall entry-point:
- adds r15=PT(R15)+16,sp // r15 = &pt_regs.r15 (syscall #)
- ;;
- ld8 r15=[r15]
- mov r3=NR_syscalls - 1
- ;;
- adds r15=-1024,r15
- movl r16=sys_call_table
- ;;
- shladd r20=r15,3,r16 // r20 = sys_call_table + 8*(syscall-1024)
- cmp.leu p6,p7=r15,r3
- ;;
-(p6) ld8 r20=[r20] // load address of syscall entry point
-(p7) movl r20=sys_ni_syscall
- ;;
- mov b6=r20
- br.call.sptk.many rp=b6 // do the syscall
-.strace_check_retval:
- cmp.lt p6,p0=r8,r0 // syscall failed?
- adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8
- adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10
- mov r10=0
-(p6) br.cond.sptk strace_error // syscall failed ->
- ;; // avoid RAW on r10
-.strace_save_retval:
-.mem.offset 0,0; st8.spill [r2]=r8 // store return value in slot for r8
-.mem.offset 8,0; st8.spill [r3]=r10 // clear error indication in slot for r10
- br.call.sptk.many rp=syscall_trace_leave // give parent a chance to catch return value
-.ret3:
-(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
-(pUStk) rsm psr.i // disable interrupts
- br.cond.sptk ia64_work_pending_syscall_end
-
-strace_error:
- ld8 r3=[r2] // load pt_regs.r8
- sub r9=0,r8 // negate return value to get errno value
- ;;
- cmp.ne p6,p0=r3,r0 // is pt_regs.r8!=0?
- adds r3=16,r2 // r3=&pt_regs.r10
- ;;
-(p6) mov r10=-1
-(p6) mov r8=r9
- br.cond.sptk .strace_save_retval
-END(ia64_trace_syscall)
-
- /*
- * When traced and returning from sigreturn, we invoke syscall_trace but then
- * go straight to ia64_leave_kernel rather than ia64_leave_syscall.
- */
-GLOBAL_ENTRY(ia64_strace_leave_kernel)
- PT_REGS_UNWIND_INFO(0)
-{ /*
- * Some versions of gas generate bad unwind info if the first instruction of a
- * procedure doesn't go into the first slot of a bundle. This is a workaround.
- */
- nop.m 0
- nop.i 0
- br.call.sptk.many rp=syscall_trace_leave // give parent a chance to catch return value
-}
-.ret4: br.cond.sptk ia64_leave_kernel
-END(ia64_strace_leave_kernel)
-
-ENTRY(call_payload)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(0)
- /* call the kernel_thread payload; fn is in r4, arg - in r5 */
- alloc loc1=ar.pfs,0,3,1,0
- mov loc0=rp
- mov loc2=gp
- mov out0=r5 // arg
- ld8 r14 = [r4], 8 // fn.address
- ;;
- mov b6 = r14
- ld8 gp = [r4] // fn.gp
- ;;
- br.call.sptk.many rp=b6 // fn(arg)
-.ret12: mov gp=loc2
- mov rp=loc0
- mov ar.pfs=loc1
- /* ... and if it has returned, we are going to userland */
- cmp.ne pKStk,pUStk=r0,r0
- br.ret.sptk.many rp
-END(call_payload)
-
-GLOBAL_ENTRY(ia64_ret_from_clone)
- PT_REGS_UNWIND_INFO(0)
-{ /*
- * Some versions of gas generate bad unwind info if the first instruction of a
- * procedure doesn't go into the first slot of a bundle. This is a workaround.
- */
- nop.m 0
- nop.i 0
- /*
- * We need to call schedule_tail() to complete the scheduling process.
- * Called by ia64_switch_to() after ia64_clone()->copy_thread(). r8 contains the
- * address of the previously executing task.
- */
- br.call.sptk.many rp=ia64_invoke_schedule_tail
-}
-.ret8:
-(pKStk) br.call.sptk.many rp=call_payload
- adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
- ;;
- ld4 r2=[r2]
- ;;
- mov r8=0
- and r2=_TIF_SYSCALL_TRACEAUDIT,r2
- ;;
- cmp.ne p6,p0=r2,r0
-(p6) br.cond.spnt .strace_check_retval
- ;; // added stop bits to prevent r8 dependency
-END(ia64_ret_from_clone)
- // fall through
-GLOBAL_ENTRY(ia64_ret_from_syscall)
- PT_REGS_UNWIND_INFO(0)
- cmp.ge p6,p7=r8,r0 // syscall executed successfully?
- adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8
- mov r10=r0 // clear error indication in r10
-(p7) br.cond.spnt handle_syscall_error // handle potential syscall failure
-END(ia64_ret_from_syscall)
- // fall through
-
-/*
- * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
- * need to switch to bank 0 and doesn't restore the scratch registers.
- * To avoid leaking kernel bits, the scratch registers are set to
- * the following known-to-be-safe values:
- *
- * r1: restored (global pointer)
- * r2: cleared
- * r3: 1 (when returning to user-level)
- * r8-r11: restored (syscall return value(s))
- * r12: restored (user-level stack pointer)
- * r13: restored (user-level thread pointer)
- * r14: set to __kernel_syscall_via_epc
- * r15: restored (syscall #)
- * r16-r17: cleared
- * r18: user-level b6
- * r19: cleared
- * r20: user-level ar.fpsr
- * r21: user-level b0
- * r22: cleared
- * r23: user-level ar.bspstore
- * r24: user-level ar.rnat
- * r25: user-level ar.unat
- * r26: user-level ar.pfs
- * r27: user-level ar.rsc
- * r28: user-level ip
- * r29: user-level psr
- * r30: user-level cfm
- * r31: user-level pr
- * f6-f11: cleared
- * pr: restored (user-level pr)
- * b0: restored (user-level rp)
- * b6: restored
- * b7: set to __kernel_syscall_via_epc
- * ar.unat: restored (user-level ar.unat)
- * ar.pfs: restored (user-level ar.pfs)
- * ar.rsc: restored (user-level ar.rsc)
- * ar.rnat: restored (user-level ar.rnat)
- * ar.bspstore: restored (user-level ar.bspstore)
- * ar.fpsr: restored (user-level ar.fpsr)
- * ar.ccv: cleared
- * ar.csd: cleared
- * ar.ssd: cleared
- */
-GLOBAL_ENTRY(ia64_leave_syscall)
- PT_REGS_UNWIND_INFO(0)
- /*
- * work.need_resched etc. mustn't get changed by this CPU before it returns to
- * user- or fsys-mode, hence we disable interrupts early on.
- *
- * p6 controls whether current_thread_info()->flags needs to be check for
- * extra work. We always check for extra work when returning to user-level.
- * With CONFIG_PREEMPTION, we also check for extra work when the preempt_count
- * is 0. After extra work processing has been completed, execution
- * resumes at ia64_work_processed_syscall with p6 set to 1 if the extra-work-check
- * needs to be redone.
- */
-#ifdef CONFIG_PREEMPTION
- RSM_PSR_I(p0, r2, r18) // disable interrupts
- cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
-(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
- ;;
- .pred.rel.mutex pUStk,pKStk
-(pKStk) ld4 r21=[r20] // r21 <- preempt_count
-(pUStk) mov r21=0 // r21 <- 0
- ;;
- cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0)
-#else /* !CONFIG_PREEMPTION */
- RSM_PSR_I(pUStk, r2, r18)
- cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
-(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
-#endif
-.global ia64_work_processed_syscall;
-ia64_work_processed_syscall:
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
- adds r2=PT(LOADRS)+16,r12
- MOV_FROM_ITC(pUStk, p9, r22, r19) // fetch time at leave
- adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
- ;;
-(p6) ld4 r31=[r18] // load current_thread_info()->flags
- ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs"
- adds r3=PT(AR_BSPSTORE)+16,r12 // deferred
- ;;
-#else
- adds r2=PT(LOADRS)+16,r12
- adds r3=PT(AR_BSPSTORE)+16,r12
- adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
- ;;
-(p6) ld4 r31=[r18] // load current_thread_info()->flags
- ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs"
- nop.i 0
- ;;
-#endif
- mov r16=ar.bsp // M2 get existing backing store pointer
- ld8 r18=[r2],PT(R9)-PT(B6) // load b6
-(p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE?
- ;;
- ld8 r23=[r3],PT(R11)-PT(AR_BSPSTORE) // load ar.bspstore (may be garbage)
-(p6) cmp4.ne.unc p6,p0=r15, r0 // any special work pending?
-(p6) br.cond.spnt .work_pending_syscall
- ;;
- // start restoring the state saved on the kernel stack (struct pt_regs):
- ld8 r9=[r2],PT(CR_IPSR)-PT(R9)
- ld8 r11=[r3],PT(CR_IIP)-PT(R11)
-(pNonSys) break 0 // bug check: we shouldn't be here if pNonSys is TRUE!
- ;;
- invala // M0|1 invalidate ALAT
- RSM_PSR_I_IC(r28, r29, r30) // M2 turn off interrupts and interruption collection
- cmp.eq p9,p0=r0,r0 // A set p9 to indicate that we should restore cr.ifs
-
- ld8 r29=[r2],16 // M0|1 load cr.ipsr
- ld8 r28=[r3],16 // M0|1 load cr.iip
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
-(pUStk) add r14=TI_AC_LEAVE+IA64_TASK_SIZE,r13
- ;;
- ld8 r30=[r2],16 // M0|1 load cr.ifs
- ld8 r25=[r3],16 // M0|1 load ar.unat
-(pUStk) add r15=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
- ;;
-#else
- mov r22=r0 // A clear r22
- ;;
- ld8 r30=[r2],16 // M0|1 load cr.ifs
- ld8 r25=[r3],16 // M0|1 load ar.unat
-(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
- ;;
-#endif
- ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs
- MOV_FROM_PSR(pKStk, r22, r21) // M2 read PSR now that interrupts are disabled
- nop 0
- ;;
- ld8 r21=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0
- ld8 r27=[r3],PT(PR)-PT(AR_RSC) // M0|1 load ar.rsc
- mov f6=f0 // F clear f6
- ;;
- ld8 r24=[r2],PT(AR_FPSR)-PT(AR_RNAT) // M0|1 load ar.rnat (may be garbage)
- ld8 r31=[r3],PT(R1)-PT(PR) // M0|1 load predicates
- mov f7=f0 // F clear f7
- ;;
- ld8 r20=[r2],PT(R12)-PT(AR_FPSR) // M0|1 load ar.fpsr
- ld8.fill r1=[r3],16 // M0|1 load r1
-(pUStk) mov r17=1 // A
- ;;
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
-(pUStk) st1 [r15]=r17 // M2|3
-#else
-(pUStk) st1 [r14]=r17 // M2|3
-#endif
- ld8.fill r13=[r3],16 // M0|1
- mov f8=f0 // F clear f8
- ;;
- ld8.fill r12=[r2] // M0|1 restore r12 (sp)
- ld8.fill r15=[r3] // M0|1 restore r15
- mov b6=r18 // I0 restore b6
-
- LOAD_PHYS_STACK_REG_SIZE(r17)
- mov f9=f0 // F clear f9
-(pKStk) br.cond.dpnt.many skip_rbs_switch // B
-
- srlz.d // M0 ensure interruption collection is off (for cover)
- shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition
- COVER // B add current frame into dirty partition & set cr.ifs
- ;;
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
- mov r19=ar.bsp // M2 get new backing store pointer
- st8 [r14]=r22 // M save time at leave
- mov f10=f0 // F clear f10
-
- mov r22=r0 // A clear r22
- movl r14=__kernel_syscall_via_epc // X
- ;;
-#else
- mov r19=ar.bsp // M2 get new backing store pointer
- mov f10=f0 // F clear f10
-
- nop.m 0
- movl r14=__kernel_syscall_via_epc // X
- ;;
-#endif
- mov.m ar.csd=r0 // M2 clear ar.csd
- mov.m ar.ccv=r0 // M2 clear ar.ccv
- mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc)
-
- mov.m ar.ssd=r0 // M2 clear ar.ssd
- mov f11=f0 // F clear f11
- br.cond.sptk.many rbs_switch // B
-END(ia64_leave_syscall)
-
-GLOBAL_ENTRY(ia64_leave_kernel)
- PT_REGS_UNWIND_INFO(0)
- /*
- * work.need_resched etc. mustn't get changed by this CPU before it returns to
- * user- or fsys-mode, hence we disable interrupts early on.
- *
- * p6 controls whether current_thread_info()->flags needs to be check for
- * extra work. We always check for extra work when returning to user-level.
- * With CONFIG_PREEMPTION, we also check for extra work when the preempt_count
- * is 0. After extra work processing has been completed, execution
- * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
- * needs to be redone.
- */
-#ifdef CONFIG_PREEMPTION
- RSM_PSR_I(p0, r17, r31) // disable interrupts
- cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel
-(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
- ;;
- .pred.rel.mutex pUStk,pKStk
-(pKStk) ld4 r21=[r20] // r21 <- preempt_count
-(pUStk) mov r21=0 // r21 <- 0
- ;;
- cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0)
-#else
- RSM_PSR_I(pUStk, r17, r31)
- cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel
-(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
-#endif
-.work_processed_kernel:
- adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
- ;;
-(p6) ld4 r31=[r17] // load current_thread_info()->flags
- adds r21=PT(PR)+16,r12
- ;;
-
- lfetch [r21],PT(CR_IPSR)-PT(PR)
- adds r2=PT(B6)+16,r12
- adds r3=PT(R16)+16,r12
- ;;
- lfetch [r21]
- ld8 r28=[r2],8 // load b6
- adds r29=PT(R24)+16,r12
-
- ld8.fill r16=[r3],PT(AR_CSD)-PT(R16)
- adds r30=PT(AR_CCV)+16,r12
-(p6) and r19=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE?
- ;;
- ld8.fill r24=[r29]
- ld8 r15=[r30] // load ar.ccv
-(p6) cmp4.ne.unc p6,p0=r19, r0 // any special work pending?
- ;;
- ld8 r29=[r2],16 // load b7
- ld8 r30=[r3],16 // load ar.csd
-(p6) br.cond.spnt .work_pending
- ;;
- ld8 r31=[r2],16 // load ar.ssd
- ld8.fill r8=[r3],16
- ;;
- ld8.fill r9=[r2],16
- ld8.fill r10=[r3],PT(R17)-PT(R10)
- ;;
- ld8.fill r11=[r2],PT(R18)-PT(R11)
- ld8.fill r17=[r3],16
- ;;
- ld8.fill r18=[r2],16
- ld8.fill r19=[r3],16
- ;;
- ld8.fill r20=[r2],16
- ld8.fill r21=[r3],16
- mov ar.csd=r30
- mov ar.ssd=r31
- ;;
- RSM_PSR_I_IC(r23, r22, r25) // initiate turning off of interrupt and interruption collection
- invala // invalidate ALAT
- ;;
- ld8.fill r22=[r2],24
- ld8.fill r23=[r3],24
- mov b6=r28
- ;;
- ld8.fill r25=[r2],16
- ld8.fill r26=[r3],16
- mov b7=r29
- ;;
- ld8.fill r27=[r2],16
- ld8.fill r28=[r3],16
- ;;
- ld8.fill r29=[r2],16
- ld8.fill r30=[r3],24
- ;;
- ld8.fill r31=[r2],PT(F9)-PT(R31)
- adds r3=PT(F10)-PT(F6),r3
- ;;
- ldf.fill f9=[r2],PT(F6)-PT(F9)
- ldf.fill f10=[r3],PT(F8)-PT(F10)
- ;;
- ldf.fill f6=[r2],PT(F7)-PT(F6)
- ;;
- ldf.fill f7=[r2],PT(F11)-PT(F7)
- ldf.fill f8=[r3],32
- ;;
- srlz.d // ensure that inter. collection is off (VHPT is don't care, since text is pinned)
- mov ar.ccv=r15
- ;;
- ldf.fill f11=[r2]
- BSW_0(r2, r3, r15) // switch back to bank 0 (no stop bit required beforehand...)
- ;;
-(pUStk) mov r18=IA64_KR(CURRENT)// M2 (12 cycle read latency)
- adds r16=PT(CR_IPSR)+16,r12
- adds r17=PT(CR_IIP)+16,r12
-
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
- .pred.rel.mutex pUStk,pKStk
- MOV_FROM_PSR(pKStk, r22, r29) // M2 read PSR now that interrupts are disabled
- MOV_FROM_ITC(pUStk, p9, r22, r29) // M fetch time at leave
- nop.i 0
- ;;
-#else
- MOV_FROM_PSR(pKStk, r22, r29) // M2 read PSR now that interrupts are disabled
- nop.i 0
- nop.i 0
- ;;
-#endif
- ld8 r29=[r16],16 // load cr.ipsr
- ld8 r28=[r17],16 // load cr.iip
- ;;
- ld8 r30=[r16],16 // load cr.ifs
- ld8 r25=[r17],16 // load ar.unat
- ;;
- ld8 r26=[r16],16 // load ar.pfs
- ld8 r27=[r17],16 // load ar.rsc
- cmp.eq p9,p0=r0,r0 // set p9 to indicate that we should restore cr.ifs
- ;;
- ld8 r24=[r16],16 // load ar.rnat (may be garbage)
- ld8 r23=[r17],16 // load ar.bspstore (may be garbage)
- ;;
- ld8 r31=[r16],16 // load predicates
- ld8 r21=[r17],16 // load b0
- ;;
- ld8 r19=[r16],16 // load ar.rsc value for "loadrs"
- ld8.fill r1=[r17],16 // load r1
- ;;
- ld8.fill r12=[r16],16
- ld8.fill r13=[r17],16
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
-(pUStk) adds r3=TI_AC_LEAVE+IA64_TASK_SIZE,r18
-#else
-(pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18
-#endif
- ;;
- ld8 r20=[r16],16 // ar.fpsr
- ld8.fill r15=[r17],16
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
-(pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18 // deferred
-#endif
- ;;
- ld8.fill r14=[r16],16
- ld8.fill r2=[r17]
-(pUStk) mov r17=1
- ;;
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
- // mmi_ : ld8 st1 shr;; mmi_ : st8 st1 shr;;
- // mib : mov add br -> mib : ld8 add br
- // bbb_ : br nop cover;; mbb_ : mov br cover;;
- //
- // no one require bsp in r16 if (pKStk) branch is selected.
-(pUStk) st8 [r3]=r22 // save time at leave
-(pUStk) st1 [r18]=r17 // restore current->thread.on_ustack
- shr.u r18=r19,16 // get byte size of existing "dirty" partition
- ;;
- ld8.fill r3=[r16] // deferred
- LOAD_PHYS_STACK_REG_SIZE(r17)
-(pKStk) br.cond.dpnt skip_rbs_switch
- mov r16=ar.bsp // get existing backing store pointer
-#else
- ld8.fill r3=[r16]
-(pUStk) st1 [r18]=r17 // restore current->thread.on_ustack
- shr.u r18=r19,16 // get byte size of existing "dirty" partition
- ;;
- mov r16=ar.bsp // get existing backing store pointer
- LOAD_PHYS_STACK_REG_SIZE(r17)
-(pKStk) br.cond.dpnt skip_rbs_switch
-#endif
-
- /*
- * Restore user backing store.
- *
- * NOTE: alloc, loadrs, and cover can't be predicated.
- */
-(pNonSys) br.cond.dpnt dont_preserve_current_frame
- COVER // add current frame into dirty partition and set cr.ifs
- ;;
- mov r19=ar.bsp // get new backing store pointer
-rbs_switch:
- sub r16=r16,r18 // krbs = old bsp - size of dirty partition
- cmp.ne p9,p0=r0,r0 // clear p9 to skip restore of cr.ifs
- ;;
- sub r19=r19,r16 // calculate total byte size of dirty partition
- add r18=64,r18 // don't force in0-in7 into memory...
- ;;
- shl r19=r19,16 // shift size of dirty partition into loadrs position
- ;;
-dont_preserve_current_frame:
- /*
- * To prevent leaking bits between the kernel and user-space,
- * we must clear the stacked registers in the "invalid" partition here.
- * Not pretty, but at least it's fast (3.34 registers/cycle on Itanium,
- * 5 registers/cycle on McKinley).
- */
-# define pRecurse p6
-# define pReturn p7
-#ifdef CONFIG_ITANIUM
-# define Nregs 10
-#else
-# define Nregs 14
-#endif
- alloc loc0=ar.pfs,2,Nregs-2,2,0
- shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8))
- sub r17=r17,r18 // r17 = (physStackedSize + 8) - dirtySize
- ;;
- mov ar.rsc=r19 // load ar.rsc to be used for "loadrs"
- shladd in0=loc1,3,r17
- mov in1=0
- ;;
- TEXT_ALIGN(32)
-rse_clear_invalid:
-#ifdef CONFIG_ITANIUM
- // cycle 0
- { .mii
- alloc loc0=ar.pfs,2,Nregs-2,2,0
- cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse
- add out0=-Nregs*8,in0
-}{ .mfb
- add out1=1,in1 // increment recursion count
- nop.f 0
- nop.b 0 // can't do br.call here because of alloc (WAW on CFM)
- ;;
-}{ .mfi // cycle 1
- mov loc1=0
- nop.f 0
- mov loc2=0
-}{ .mib
- mov loc3=0
- mov loc4=0
-(pRecurse) br.call.sptk.many b0=rse_clear_invalid
-
-}{ .mfi // cycle 2
- mov loc5=0
- nop.f 0
- cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret
-}{ .mib
- mov loc6=0
- mov loc7=0
-(pReturn) br.ret.sptk.many b0
-}
-#else /* !CONFIG_ITANIUM */
- alloc loc0=ar.pfs,2,Nregs-2,2,0
- cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse
- add out0=-Nregs*8,in0
- add out1=1,in1 // increment recursion count
- mov loc1=0
- mov loc2=0
- ;;
- mov loc3=0
- mov loc4=0
- mov loc5=0
- mov loc6=0
- mov loc7=0
-(pRecurse) br.call.dptk.few b0=rse_clear_invalid
- ;;
- mov loc8=0
- mov loc9=0
- cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret
- mov loc10=0
- mov loc11=0
-(pReturn) br.ret.dptk.many b0
-#endif /* !CONFIG_ITANIUM */
-# undef pRecurse
-# undef pReturn
- ;;
- alloc r17=ar.pfs,0,0,0,0 // drop current register frame
- ;;
- loadrs
- ;;
-skip_rbs_switch:
- mov ar.unat=r25 // M2
-(pKStk) extr.u r22=r22,21,1 // I0 extract current value of psr.pp from r22
-(pLvSys)mov r19=r0 // A clear r19 for leave_syscall, no-op otherwise
- ;;
-(pUStk) mov ar.bspstore=r23 // M2
-(pKStk) dep r29=r22,r29,21,1 // I0 update ipsr.pp with psr.pp
-(pLvSys)mov r16=r0 // A clear r16 for leave_syscall, no-op otherwise
- ;;
- MOV_TO_IPSR(p0, r29, r25) // M2
- mov ar.pfs=r26 // I0
-(pLvSys)mov r17=r0 // A clear r17 for leave_syscall, no-op otherwise
-
- MOV_TO_IFS(p9, r30, r25)// M2
- mov b0=r21 // I0
-(pLvSys)mov r18=r0 // A clear r18 for leave_syscall, no-op otherwise
-
- mov ar.fpsr=r20 // M2
- MOV_TO_IIP(r28, r25) // M2
- nop 0
- ;;
-(pUStk) mov ar.rnat=r24 // M2 must happen with RSE in lazy mode
- nop 0
-(pLvSys)mov r2=r0
-
- mov ar.rsc=r27 // M2
- mov pr=r31,-1 // I0
- RFI // B
-
- /*
- * On entry:
- * r20 = &current->thread_info->pre_count (if CONFIG_PREEMPTION)
- * r31 = current->thread_info->flags
- * On exit:
- * p6 = TRUE if work-pending-check needs to be redone
- *
- * Interrupts are disabled on entry, reenabled depend on work, and
- * disabled on exit.
- */
-.work_pending_syscall:
- add r2=-8,r2
- add r3=-8,r3
- ;;
- st8 [r2]=r8
- st8 [r3]=r10
-.work_pending:
- tbit.z p6,p0=r31,TIF_NEED_RESCHED // is resched not needed?
-(p6) br.cond.sptk.few .notify
- br.call.spnt.many rp=preempt_schedule_irq
-.ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 (re-check)
-(pLvSys)br.cond.sptk.few ia64_work_pending_syscall_end
- br.cond.sptk.many .work_processed_kernel
-
-.notify:
-(pUStk) br.call.spnt.many rp=notify_resume_user
-.ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0 (don't re-check)
-(pLvSys)br.cond.sptk.few ia64_work_pending_syscall_end
- br.cond.sptk.many .work_processed_kernel
-
-.global ia64_work_pending_syscall_end;
-ia64_work_pending_syscall_end:
- adds r2=PT(R8)+16,r12
- adds r3=PT(R10)+16,r12
- ;;
- ld8 r8=[r2]
- ld8 r10=[r3]
- br.cond.sptk.many ia64_work_processed_syscall
-END(ia64_leave_kernel)
-
-ENTRY(handle_syscall_error)
- /*
- * Some system calls (e.g., ptrace, mmap) can return arbitrary values which could
- * lead us to mistake a negative return value as a failed syscall. Those syscall
- * must deposit a non-zero value in pt_regs.r8 to indicate an error. If
- * pt_regs.r8 is zero, we assume that the call completed successfully.
- */
- PT_REGS_UNWIND_INFO(0)
- ld8 r3=[r2] // load pt_regs.r8
- ;;
- cmp.eq p6,p7=r3,r0 // is pt_regs.r8==0?
- ;;
-(p7) mov r10=-1
-(p7) sub r8=0,r8 // negate return value to get errno
- br.cond.sptk ia64_leave_syscall
-END(handle_syscall_error)
-
- /*
- * Invoke schedule_tail(task) while preserving in0-in7, which may be needed
- * in case a system call gets restarted.
- */
-GLOBAL_ENTRY(ia64_invoke_schedule_tail)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
- alloc loc1=ar.pfs,8,2,1,0
- mov loc0=rp
- mov out0=r8 // Address of previous task
- ;;
- br.call.sptk.many rp=schedule_tail
-.ret11: mov ar.pfs=loc1
- mov rp=loc0
- br.ret.sptk.many rp
-END(ia64_invoke_schedule_tail)
-
- /*
- * Setup stack and call do_notify_resume_user(), keeping interrupts
- * disabled.
- *
- * Note that pSys and pNonSys need to be set up by the caller.
- * We declare 8 input registers so the system call args get preserved,
- * in case we need to restart a system call.
- */
-GLOBAL_ENTRY(notify_resume_user)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
- alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
- mov r9=ar.unat
- mov loc0=rp // save return address
- mov out0=0 // there is no "oldset"
- adds out1=8,sp // out1=&sigscratch->ar_pfs
-(pSys) mov out2=1 // out2==1 => we're in a syscall
- ;;
-(pNonSys) mov out2=0 // out2==0 => not a syscall
- .fframe 16
- .spillsp ar.unat, 16
- st8 [sp]=r9,-16 // allocate space for ar.unat and save it
- st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch
- .body
- br.call.sptk.many rp=do_notify_resume_user
-.ret15: .restore sp
- adds sp=16,sp // pop scratch stack space
- ;;
- ld8 r9=[sp] // load new unat from sigscratch->scratch_unat
- mov rp=loc0
- ;;
- mov ar.unat=r9
- mov ar.pfs=loc1
- br.ret.sptk.many rp
-END(notify_resume_user)
-
-ENTRY(sys_rt_sigreturn)
- PT_REGS_UNWIND_INFO(0)
- /*
- * Allocate 8 input registers since ptrace() may clobber them
- */
- alloc r2=ar.pfs,8,0,1,0
- .prologue
- PT_REGS_SAVES(16)
- adds sp=-16,sp
- .body
- cmp.eq pNonSys,pSys=r0,r0 // sigreturn isn't a normal syscall...
- ;;
- /*
- * leave_kernel() restores f6-f11 from pt_regs, but since the streamlined
- * syscall-entry path does not save them we save them here instead. Note: we
- * don't need to save any other registers that are not saved by the stream-lined
- * syscall path, because restore_sigcontext() restores them.
- */
- adds r16=PT(F6)+32,sp
- adds r17=PT(F7)+32,sp
- ;;
- stf.spill [r16]=f6,32
- stf.spill [r17]=f7,32
- ;;
- stf.spill [r16]=f8,32
- stf.spill [r17]=f9,32
- ;;
- stf.spill [r16]=f10
- stf.spill [r17]=f11
- adds out0=16,sp // out0 = &sigscratch
- br.call.sptk.many rp=ia64_rt_sigreturn
-.ret19: .restore sp,0
- adds sp=16,sp
- ;;
- ld8 r9=[sp] // load new ar.unat
- mov.sptk b7=r8,ia64_leave_kernel
- ;;
- mov ar.unat=r9
- br.many b7
-END(sys_rt_sigreturn)
-
-GLOBAL_ENTRY(ia64_prepare_handle_unaligned)
- .prologue
- /*
- * r16 = fake ar.pfs, we simply need to make sure privilege is still 0
- */
- mov r16=r0
- DO_SAVE_SWITCH_STACK
- br.call.sptk.many rp=ia64_handle_unaligned // stack frame setup in ivt
-.ret21: .body
- DO_LOAD_SWITCH_STACK
- br.cond.sptk.many rp // goes to ia64_leave_kernel
-END(ia64_prepare_handle_unaligned)
-
- //
- // unw_init_running(void (*callback)(info, arg), void *arg)
- //
-# define EXTRA_FRAME_SIZE ((UNW_FRAME_INFO_SIZE+15)&~15)
-
-GLOBAL_ENTRY(unw_init_running)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
- alloc loc1=ar.pfs,2,3,3,0
- ;;
- ld8 loc2=[in0],8
- mov loc0=rp
- mov r16=loc1
- DO_SAVE_SWITCH_STACK
- .body
-
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
- .fframe IA64_SWITCH_STACK_SIZE+EXTRA_FRAME_SIZE
- SWITCH_STACK_SAVES(EXTRA_FRAME_SIZE)
- adds sp=-EXTRA_FRAME_SIZE,sp
- .body
- ;;
- adds out0=16,sp // &info
- mov out1=r13 // current
- adds out2=16+EXTRA_FRAME_SIZE,sp // &switch_stack
- br.call.sptk.many rp=unw_init_frame_info
-1: adds out0=16,sp // &info
- mov b6=loc2
- mov loc2=gp // save gp across indirect function call
- ;;
- ld8 gp=[in0]
- mov out1=in1 // arg
- br.call.sptk.many rp=b6 // invoke the callback function
-1: mov gp=loc2 // restore gp
-
- // For now, we don't allow changing registers from within
- // unw_init_running; if we ever want to allow that, we'd
- // have to do a load_switch_stack here:
- .restore sp
- adds sp=IA64_SWITCH_STACK_SIZE+EXTRA_FRAME_SIZE,sp
-
- mov ar.pfs=loc1
- mov rp=loc0
- br.ret.sptk.many rp
-END(unw_init_running)
-EXPORT_SYMBOL(unw_init_running)
-
-#ifdef CONFIG_FUNCTION_TRACER
-#ifdef CONFIG_DYNAMIC_FTRACE
-GLOBAL_ENTRY(_mcount)
- br ftrace_stub
-END(_mcount)
-EXPORT_SYMBOL(_mcount)
-
-.here:
- br.ret.sptk.many b0
-
-GLOBAL_ENTRY(ftrace_caller)
- alloc out0 = ar.pfs, 8, 0, 4, 0
- mov out3 = r0
- ;;
- mov out2 = b0
- add r3 = 0x20, r3
- mov out1 = r1;
- br.call.sptk.many b0 = ftrace_patch_gp
- //this might be called from module, so we must patch gp
-ftrace_patch_gp:
- movl gp=__gp
- mov b0 = r3
- ;;
-.global ftrace_call;
-ftrace_call:
-{
- .mlx
- nop.m 0x0
- movl r3 = .here;;
-}
- alloc loc0 = ar.pfs, 4, 4, 2, 0
- ;;
- mov loc1 = b0
- mov out0 = b0
- mov loc2 = r8
- mov loc3 = r15
- ;;
- adds out0 = -MCOUNT_INSN_SIZE, out0
- mov out1 = in2
- mov b6 = r3
-
- br.call.sptk.many b0 = b6
- ;;
- mov ar.pfs = loc0
- mov b0 = loc1
- mov r8 = loc2
- mov r15 = loc3
- br ftrace_stub
- ;;
-END(ftrace_caller)
-
-#else
-GLOBAL_ENTRY(_mcount)
- movl r2 = ftrace_stub
- movl r3 = ftrace_trace_function;;
- ld8 r3 = [r3];;
- ld8 r3 = [r3];;
- cmp.eq p7,p0 = r2, r3
-(p7) br.sptk.many ftrace_stub
- ;;
-
- alloc loc0 = ar.pfs, 4, 4, 2, 0
- ;;
- mov loc1 = b0
- mov out0 = b0
- mov loc2 = r8
- mov loc3 = r15
- ;;
- adds out0 = -MCOUNT_INSN_SIZE, out0
- mov out1 = in2
- mov b6 = r3
-
- br.call.sptk.many b0 = b6
- ;;
- mov ar.pfs = loc0
- mov b0 = loc1
- mov r8 = loc2
- mov r15 = loc3
- br ftrace_stub
- ;;
-END(_mcount)
-#endif
-
-GLOBAL_ENTRY(ftrace_stub)
- mov r3 = b0
- movl r2 = _mcount_ret_helper
- ;;
- mov b6 = r2
- mov b7 = r3
- br.ret.sptk.many b6
-
-_mcount_ret_helper:
- mov b0 = r42
- mov r1 = r41
- mov ar.pfs = r40
- br b7
-END(ftrace_stub)
-
-#endif /* CONFIG_FUNCTION_TRACER */
-
-#define __SYSCALL(nr, entry) data8 entry
- .rodata
- .align 8
- .globl sys_call_table
-sys_call_table:
-#include <asm/syscall_table.h>
diff --git a/arch/ia64/kernel/entry.h b/arch/ia64/kernel/entry.h
deleted file mode 100644
index 6463dc316263..000000000000
--- a/arch/ia64/kernel/entry.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-/*
- * Preserved registers that are shared between code in ivt.S and
- * entry.S. Be careful not to step on these!
- */
-#define PRED_LEAVE_SYSCALL 1 /* TRUE iff leave from syscall */
-#define PRED_KERNEL_STACK 2 /* returning to kernel-stacks? */
-#define PRED_USER_STACK 3 /* returning to user-stacks? */
-#define PRED_SYSCALL 4 /* inside a system call? */
-#define PRED_NON_SYSCALL 5 /* complement of PRED_SYSCALL */
-
-#ifdef __ASSEMBLY__
-# define PASTE2(x,y) x##y
-# define PASTE(x,y) PASTE2(x,y)
-
-# define pLvSys PASTE(p,PRED_LEAVE_SYSCALL)
-# define pKStk PASTE(p,PRED_KERNEL_STACK)
-# define pUStk PASTE(p,PRED_USER_STACK)
-# define pSys PASTE(p,PRED_SYSCALL)
-# define pNonSys PASTE(p,PRED_NON_SYSCALL)
-#endif
-
-#define PT(f) (IA64_PT_REGS_##f##_OFFSET)
-#define SW(f) (IA64_SWITCH_STACK_##f##_OFFSET)
-#define SOS(f) (IA64_SAL_OS_STATE_##f##_OFFSET)
-
-#define PT_REGS_SAVES(off) \
- .unwabi 3, 'i'; \
- .fframe IA64_PT_REGS_SIZE+16+(off); \
- .spillsp rp, PT(CR_IIP)+16+(off); \
- .spillsp ar.pfs, PT(CR_IFS)+16+(off); \
- .spillsp ar.unat, PT(AR_UNAT)+16+(off); \
- .spillsp ar.fpsr, PT(AR_FPSR)+16+(off); \
- .spillsp pr, PT(PR)+16+(off);
-
-#define PT_REGS_UNWIND_INFO(off) \
- .prologue; \
- PT_REGS_SAVES(off); \
- .body
-
-#define SWITCH_STACK_SAVES(off) \
- .savesp ar.unat,SW(CALLER_UNAT)+16+(off); \
- .savesp ar.fpsr,SW(AR_FPSR)+16+(off); \
- .spillsp f2,SW(F2)+16+(off); .spillsp f3,SW(F3)+16+(off); \
- .spillsp f4,SW(F4)+16+(off); .spillsp f5,SW(F5)+16+(off); \
- .spillsp f16,SW(F16)+16+(off); .spillsp f17,SW(F17)+16+(off); \
- .spillsp f18,SW(F18)+16+(off); .spillsp f19,SW(F19)+16+(off); \
- .spillsp f20,SW(F20)+16+(off); .spillsp f21,SW(F21)+16+(off); \
- .spillsp f22,SW(F22)+16+(off); .spillsp f23,SW(F23)+16+(off); \
- .spillsp f24,SW(F24)+16+(off); .spillsp f25,SW(F25)+16+(off); \
- .spillsp f26,SW(F26)+16+(off); .spillsp f27,SW(F27)+16+(off); \
- .spillsp f28,SW(F28)+16+(off); .spillsp f29,SW(F29)+16+(off); \
- .spillsp f30,SW(F30)+16+(off); .spillsp f31,SW(F31)+16+(off); \
- .spillsp r4,SW(R4)+16+(off); .spillsp r5,SW(R5)+16+(off); \
- .spillsp r6,SW(R6)+16+(off); .spillsp r7,SW(R7)+16+(off); \
- .spillsp b0,SW(B0)+16+(off); .spillsp b1,SW(B1)+16+(off); \
- .spillsp b2,SW(B2)+16+(off); .spillsp b3,SW(B3)+16+(off); \
- .spillsp b4,SW(B4)+16+(off); .spillsp b5,SW(B5)+16+(off); \
- .spillsp ar.pfs,SW(AR_PFS)+16+(off); .spillsp ar.lc,SW(AR_LC)+16+(off); \
- .spillsp @priunat,SW(AR_UNAT)+16+(off); \
- .spillsp ar.rnat,SW(AR_RNAT)+16+(off); \
- .spillsp ar.bspstore,SW(AR_BSPSTORE)+16+(off); \
- .spillsp pr,SW(PR)+16+(off)
-
-#define DO_SAVE_SWITCH_STACK \
- movl r28=1f; \
- ;; \
- .fframe IA64_SWITCH_STACK_SIZE; \
- adds sp=-IA64_SWITCH_STACK_SIZE,sp; \
- mov.ret.sptk b7=r28,1f; \
- SWITCH_STACK_SAVES(0); \
- br.cond.sptk.many save_switch_stack; \
-1:
-
-#define DO_LOAD_SWITCH_STACK \
- movl r28=1f; \
- ;; \
- invala; \
- mov.ret.sptk b7=r28,1f; \
- br.cond.sptk.many load_switch_stack; \
-1: .restore sp; \
- adds sp=IA64_SWITCH_STACK_SIZE,sp
diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c
deleted file mode 100644
index dd5bfed52031..000000000000
--- a/arch/ia64/kernel/err_inject.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * err_inject.c -
- * 1.) Inject errors to a processor.
- * 2.) Query error injection capabilities.
- * This driver along with user space code can be acting as an error
- * injection tool.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Written by: Fenghua Yu <fenghua.yu@intel.com>, Intel Corporation
- * Copyright (C) 2006, Intel Corp. All rights reserved.
- *
- */
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/cpu.h>
-#include <linux/module.h>
-
-#define ERR_INJ_DEBUG
-
-#define ERR_DATA_BUFFER_SIZE 3 // Three 8-byte;
-
-#define define_one_ro(name) \
-static DEVICE_ATTR(name, 0444, show_##name, NULL)
-
-#define define_one_rw(name) \
-static DEVICE_ATTR(name, 0644, show_##name, store_##name)
-
-static u64 call_start[NR_CPUS];
-static u64 phys_addr[NR_CPUS];
-static u64 err_type_info[NR_CPUS];
-static u64 err_struct_info[NR_CPUS];
-static struct {
- u64 data1;
- u64 data2;
- u64 data3;
-} __attribute__((__aligned__(16))) err_data_buffer[NR_CPUS];
-static s64 status[NR_CPUS];
-static u64 capabilities[NR_CPUS];
-static u64 resources[NR_CPUS];
-
-#define show(name) \
-static ssize_t \
-show_##name(struct device *dev, struct device_attribute *attr, \
- char *buf) \
-{ \
- u32 cpu=dev->id; \
- return sprintf(buf, "%llx\n", name[cpu]); \
-}
-
-#define store(name) \
-static ssize_t \
-store_##name(struct device *dev, struct device_attribute *attr, \
- const char *buf, size_t size) \
-{ \
- unsigned int cpu=dev->id; \
- name[cpu] = simple_strtoull(buf, NULL, 16); \
- return size; \
-}
-
-show(call_start)
-
-/* It's user's responsibility to call the PAL procedure on a specific
- * processor. The cpu number in driver is only used for storing data.
- */
-static ssize_t
-store_call_start(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t size)
-{
- unsigned int cpu=dev->id;
- unsigned long call_start = simple_strtoull(buf, NULL, 16);
-
-#ifdef ERR_INJ_DEBUG
- printk(KERN_DEBUG "pal_mc_err_inject for cpu%d:\n", cpu);
- printk(KERN_DEBUG "err_type_info=%llx,\n", err_type_info[cpu]);
- printk(KERN_DEBUG "err_struct_info=%llx,\n", err_struct_info[cpu]);
- printk(KERN_DEBUG "err_data_buffer=%llx, %llx, %llx.\n",
- err_data_buffer[cpu].data1,
- err_data_buffer[cpu].data2,
- err_data_buffer[cpu].data3);
-#endif
- switch (call_start) {
- case 0: /* Do nothing. */
- break;
- case 1: /* Call pal_mc_error_inject in physical mode. */
- status[cpu]=ia64_pal_mc_error_inject_phys(err_type_info[cpu],
- err_struct_info[cpu],
- ia64_tpa(&err_data_buffer[cpu]),
- &capabilities[cpu],
- &resources[cpu]);
- break;
- case 2: /* Call pal_mc_error_inject in virtual mode. */
- status[cpu]=ia64_pal_mc_error_inject_virt(err_type_info[cpu],
- err_struct_info[cpu],
- ia64_tpa(&err_data_buffer[cpu]),
- &capabilities[cpu],
- &resources[cpu]);
- break;
- default:
- status[cpu] = -EINVAL;
- break;
- }
-
-#ifdef ERR_INJ_DEBUG
- printk(KERN_DEBUG "Returns: status=%d,\n", (int)status[cpu]);
- printk(KERN_DEBUG "capabilities=%llx,\n", capabilities[cpu]);
- printk(KERN_DEBUG "resources=%llx\n", resources[cpu]);
-#endif
- return size;
-}
-
-show(err_type_info)
-store(err_type_info)
-
-static ssize_t
-show_virtual_to_phys(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- unsigned int cpu=dev->id;
- return sprintf(buf, "%llx\n", phys_addr[cpu]);
-}
-
-static ssize_t
-store_virtual_to_phys(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t size)
-{
- unsigned int cpu=dev->id;
- u64 virt_addr=simple_strtoull(buf, NULL, 16);
- int ret;
-
- ret = get_user_pages_fast(virt_addr, 1, FOLL_WRITE, NULL);
- if (ret<=0) {
-#ifdef ERR_INJ_DEBUG
- printk("Virtual address %llx is not existing.\n", virt_addr);
-#endif
- return -EINVAL;
- }
-
- phys_addr[cpu] = ia64_tpa(virt_addr);
- return size;
-}
-
-show(err_struct_info)
-store(err_struct_info)
-
-static ssize_t
-show_err_data_buffer(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- unsigned int cpu=dev->id;
-
- return sprintf(buf, "%llx, %llx, %llx\n",
- err_data_buffer[cpu].data1,
- err_data_buffer[cpu].data2,
- err_data_buffer[cpu].data3);
-}
-
-static ssize_t
-store_err_data_buffer(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
-{
- unsigned int cpu=dev->id;
- int ret;
-
-#ifdef ERR_INJ_DEBUG
- printk("write err_data_buffer=[%llx,%llx,%llx] on cpu%d\n",
- err_data_buffer[cpu].data1,
- err_data_buffer[cpu].data2,
- err_data_buffer[cpu].data3,
- cpu);
-#endif
- ret = sscanf(buf, "%llx, %llx, %llx",
- &err_data_buffer[cpu].data1,
- &err_data_buffer[cpu].data2,
- &err_data_buffer[cpu].data3);
- if (ret!=ERR_DATA_BUFFER_SIZE)
- return -EINVAL;
-
- return size;
-}
-
-show(status)
-show(capabilities)
-show(resources)
-
-define_one_rw(call_start);
-define_one_rw(err_type_info);
-define_one_rw(err_struct_info);
-define_one_rw(err_data_buffer);
-define_one_rw(virtual_to_phys);
-define_one_ro(status);
-define_one_ro(capabilities);
-define_one_ro(resources);
-
-static struct attribute *default_attrs[] = {
- &dev_attr_call_start.attr,
- &dev_attr_virtual_to_phys.attr,
- &dev_attr_err_type_info.attr,
- &dev_attr_err_struct_info.attr,
- &dev_attr_err_data_buffer.attr,
- &dev_attr_status.attr,
- &dev_attr_capabilities.attr,
- &dev_attr_resources.attr,
- NULL
-};
-
-static struct attribute_group err_inject_attr_group = {
- .attrs = default_attrs,
- .name = "err_inject"
-};
-/* Add/Remove err_inject interface for CPU device */
-static int err_inject_add_dev(unsigned int cpu)
-{
- struct device *sys_dev = get_cpu_device(cpu);
-
- return sysfs_create_group(&sys_dev->kobj, &err_inject_attr_group);
-}
-
-static int err_inject_remove_dev(unsigned int cpu)
-{
- struct device *sys_dev = get_cpu_device(cpu);
-
- sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group);
- return 0;
-}
-
-static enum cpuhp_state hp_online;
-
-static int __init err_inject_init(void)
-{
- int ret;
-#ifdef ERR_INJ_DEBUG
- printk(KERN_INFO "Enter error injection driver.\n");
-#endif
-
- ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/err_inj:online",
- err_inject_add_dev, err_inject_remove_dev);
- if (ret >= 0) {
- hp_online = ret;
- ret = 0;
- }
- return ret;
-}
-
-static void __exit err_inject_exit(void)
-{
-#ifdef ERR_INJ_DEBUG
- printk(KERN_INFO "Exit error injection driver.\n");
-#endif
- cpuhp_remove_state(hp_online);
-}
-
-module_init(err_inject_init);
-module_exit(err_inject_exit);
-
-MODULE_AUTHOR("Fenghua Yu <fenghua.yu@intel.com>");
-MODULE_DESCRIPTION("MC error injection kernel sysfs interface");
-MODULE_LICENSE("GPL");
diff --git a/arch/ia64/kernel/esi.c b/arch/ia64/kernel/esi.c
deleted file mode 100644
index 4df57c93e0a8..000000000000
--- a/arch/ia64/kernel/esi.c
+++ /dev/null
@@ -1,193 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Extensible SAL Interface (ESI) support routines.
- *
- * Copyright (C) 2006 Hewlett-Packard Co
- * Alex Williamson <alex.williamson@hp.com>
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-
-#include <asm/esi.h>
-#include <asm/sal.h>
-
-MODULE_AUTHOR("Alex Williamson <alex.williamson@hp.com>");
-MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
-MODULE_LICENSE("GPL");
-
-#define MODULE_NAME "esi"
-
-enum esi_systab_entry_type {
- ESI_DESC_ENTRY_POINT = 0
-};
-
-/*
- * Entry type: Size:
- * 0 48
- */
-#define ESI_DESC_SIZE(type) "\060"[(unsigned) (type)]
-
-typedef struct ia64_esi_desc_entry_point {
- u8 type;
- u8 reserved1[15];
- u64 esi_proc;
- u64 gp;
- efi_guid_t guid;
-} ia64_esi_desc_entry_point_t;
-
-struct pdesc {
- void *addr;
- void *gp;
-};
-
-static struct ia64_sal_systab *esi_systab;
-
-extern unsigned long esi_phys;
-
-static int __init esi_init (void)
-{
- struct ia64_sal_systab *systab;
- char *p;
- int i;
-
- if (esi_phys == EFI_INVALID_TABLE_ADDR)
- return -ENODEV;
-
- systab = __va(esi_phys);
-
- if (strncmp(systab->signature, "ESIT", 4) != 0) {
- printk(KERN_ERR "bad signature in ESI system table!");
- return -ENODEV;
- }
-
- p = (char *) (systab + 1);
- for (i = 0; i < systab->entry_count; i++) {
- /*
- * The first byte of each entry type contains the type
- * descriptor.
- */
- switch (*p) {
- case ESI_DESC_ENTRY_POINT:
- break;
- default:
- printk(KERN_WARNING "Unknown table type %d found in "
- "ESI table, ignoring rest of table\n", *p);
- return -ENODEV;
- }
-
- p += ESI_DESC_SIZE(*p);
- }
-
- esi_systab = systab;
- return 0;
-}
-
-
-int ia64_esi_call (efi_guid_t guid, struct ia64_sal_retval *isrvp,
- enum esi_proc_type proc_type, u64 func,
- u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
- u64 arg7)
-{
- struct ia64_fpreg fr[6];
- unsigned long flags = 0;
- int i;
- char *p;
-
- if (!esi_systab)
- return -1;
-
- p = (char *) (esi_systab + 1);
- for (i = 0; i < esi_systab->entry_count; i++) {
- if (*p == ESI_DESC_ENTRY_POINT) {
- ia64_esi_desc_entry_point_t *esi = (void *)p;
- if (!efi_guidcmp(guid, esi->guid)) {
- ia64_sal_handler esi_proc;
- struct pdesc pdesc;
-
- pdesc.addr = __va(esi->esi_proc);
- pdesc.gp = __va(esi->gp);
-
- esi_proc = (ia64_sal_handler) &pdesc;
-
- ia64_save_scratch_fpregs(fr);
- if (proc_type == ESI_PROC_SERIALIZED)
- spin_lock_irqsave(&sal_lock, flags);
- else if (proc_type == ESI_PROC_MP_SAFE)
- local_irq_save(flags);
- else
- preempt_disable();
- *isrvp = (*esi_proc)(func, arg1, arg2, arg3,
- arg4, arg5, arg6, arg7);
- if (proc_type == ESI_PROC_SERIALIZED)
- spin_unlock_irqrestore(&sal_lock,
- flags);
- else if (proc_type == ESI_PROC_MP_SAFE)
- local_irq_restore(flags);
- else
- preempt_enable();
- ia64_load_scratch_fpregs(fr);
- return 0;
- }
- }
- p += ESI_DESC_SIZE(*p);
- }
- return -1;
-}
-EXPORT_SYMBOL_GPL(ia64_esi_call);
-
-int ia64_esi_call_phys (efi_guid_t guid, struct ia64_sal_retval *isrvp,
- u64 func, u64 arg1, u64 arg2, u64 arg3, u64 arg4,
- u64 arg5, u64 arg6, u64 arg7)
-{
- struct ia64_fpreg fr[6];
- unsigned long flags;
- u64 esi_params[8];
- char *p;
- int i;
-
- if (!esi_systab)
- return -1;
-
- p = (char *) (esi_systab + 1);
- for (i = 0; i < esi_systab->entry_count; i++) {
- if (*p == ESI_DESC_ENTRY_POINT) {
- ia64_esi_desc_entry_point_t *esi = (void *)p;
- if (!efi_guidcmp(guid, esi->guid)) {
- ia64_sal_handler esi_proc;
- struct pdesc pdesc;
-
- pdesc.addr = (void *)esi->esi_proc;
- pdesc.gp = (void *)esi->gp;
-
- esi_proc = (ia64_sal_handler) &pdesc;
-
- esi_params[0] = func;
- esi_params[1] = arg1;
- esi_params[2] = arg2;
- esi_params[3] = arg3;
- esi_params[4] = arg4;
- esi_params[5] = arg5;
- esi_params[6] = arg6;
- esi_params[7] = arg7;
- ia64_save_scratch_fpregs(fr);
- spin_lock_irqsave(&sal_lock, flags);
- *isrvp = esi_call_phys(esi_proc, esi_params);
- spin_unlock_irqrestore(&sal_lock, flags);
- ia64_load_scratch_fpregs(fr);
- return 0;
- }
- }
- p += ESI_DESC_SIZE(*p);
- }
- return -1;
-}
-EXPORT_SYMBOL_GPL(ia64_esi_call_phys);
-
-static void __exit esi_exit (void)
-{
-}
-
-module_init(esi_init);
-module_exit(esi_exit); /* makes module removable... */
diff --git a/arch/ia64/kernel/esi_stub.S b/arch/ia64/kernel/esi_stub.S
deleted file mode 100644
index 9928c5b2957c..000000000000
--- a/arch/ia64/kernel/esi_stub.S
+++ /dev/null
@@ -1,99 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * ESI call stub.
- *
- * Copyright (C) 2005 Hewlett-Packard Co
- * Alex Williamson <alex.williamson@hp.com>
- *
- * Based on EFI call stub by David Mosberger. The stub is virtually
- * identical to the one for EFI phys-mode calls, except that ESI
- * calls may have up to 8 arguments, so they get passed to this routine
- * through memory.
- *
- * This stub allows us to make ESI calls in physical mode with interrupts
- * turned off. ESI calls may not support calling from virtual mode.
- *
- * Google for "Extensible SAL specification" for a document describing the
- * ESI standard.
- */
-
-/*
- * PSR settings as per SAL spec (Chapter 8 in the "IA-64 System
- * Abstraction Layer Specification", revision 2.6e). Note that
- * psr.dfl and psr.dfh MUST be cleared, despite what this manual says.
- * Otherwise, SAL dies whenever it's trying to do an IA-32 BIOS call
- * (the br.ia instruction fails unless psr.dfl and psr.dfh are
- * cleared). Fortunately, SAL promises not to touch the floating
- * point regs, so at least we don't have to save f2-f127.
- */
-#define PSR_BITS_TO_CLEAR \
- (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_RT | \
- IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED | \
- IA64_PSR_DFL | IA64_PSR_DFH)
-
-#define PSR_BITS_TO_SET \
- (IA64_PSR_BN)
-
-#include <linux/export.h>
-#include <asm/processor.h>
-#include <asm/asmmacro.h>
-
-/*
- * Inputs:
- * in0 = address of function descriptor of ESI routine to call
- * in1 = address of array of ESI parameters
- *
- * Outputs:
- * r8 = result returned by called function
- */
-GLOBAL_ENTRY(esi_call_phys)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
- alloc loc1=ar.pfs,2,7,8,0
- ld8 r2=[in0],8 // load ESI function's entry point
- mov loc0=rp
- .body
- ;;
- ld8 out0=[in1],8 // ESI params loaded from array
- ;; // passing all as inputs doesn't work
- ld8 out1=[in1],8
- ;;
- ld8 out2=[in1],8
- ;;
- ld8 out3=[in1],8
- ;;
- ld8 out4=[in1],8
- ;;
- ld8 out5=[in1],8
- ;;
- ld8 out6=[in1],8
- ;;
- ld8 out7=[in1]
- mov loc2=gp // save global pointer
- mov loc4=ar.rsc // save RSE configuration
- mov ar.rsc=0 // put RSE in enforced lazy, LE mode
- ;;
- ld8 gp=[in0] // load ESI function's global pointer
- movl r16=PSR_BITS_TO_CLEAR
- mov loc3=psr // save processor status word
- movl r17=PSR_BITS_TO_SET
- ;;
- or loc3=loc3,r17
- mov b6=r2
- ;;
- andcm r16=loc3,r16 // get psr with IT, DT, and RT bits cleared
- br.call.sptk.many rp=ia64_switch_mode_phys
-.ret0: mov loc5=r19 // old ar.bsp
- mov loc6=r20 // old sp
- br.call.sptk.many rp=b6 // call the ESI function
-.ret1: mov ar.rsc=0 // put RSE in enforced lazy, LE mode
- mov r16=loc3 // save virtual mode psr
- mov r19=loc5 // save virtual mode bspstore
- mov r20=loc6 // save virtual mode sp
- br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
-.ret2: mov ar.rsc=loc4 // restore RSE configuration
- mov ar.pfs=loc1
- mov rp=loc0
- mov gp=loc2
- br.ret.sptk.many rp
-END(esi_call_phys)
-EXPORT_SYMBOL_GPL(esi_call_phys)
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
deleted file mode 100644
index cc4733e9990a..000000000000
--- a/arch/ia64/kernel/fsys.S
+++ /dev/null
@@ -1,837 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * This file contains the light-weight system call handlers (fsyscall-handlers).
- *
- * Copyright (C) 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * 25-Sep-03 davidm Implement fsys_rt_sigprocmask().
- * 18-Feb-03 louisk Implement fsys_gettimeofday().
- * 28-Feb-03 davidm Fixed several bugs in fsys_gettimeofday(). Tuned it some more,
- * probably broke it along the way... ;-)
- * 13-Jul-04 clameter Implement fsys_clock_gettime and revise fsys_gettimeofday to make
- * it capable of using memory based clocks without falling back to C code.
- * 08-Feb-07 Fenghua Yu Implement fsys_getcpu.
- *
- */
-
-#include <asm/asmmacro.h>
-#include <asm/errno.h>
-#include <asm/asm-offsets.h>
-#include <asm/percpu.h>
-#include <asm/thread_info.h>
-#include <asm/sal.h>
-#include <asm/signal.h>
-#include <asm/unistd.h>
-
-#include "entry.h"
-#include <asm/native/inst.h>
-
-/*
- * See Documentation/arch/ia64/fsys.rst for details on fsyscalls.
- *
- * On entry to an fsyscall handler:
- * r10 = 0 (i.e., defaults to "successful syscall return")
- * r11 = saved ar.pfs (a user-level value)
- * r15 = system call number
- * r16 = "current" task pointer (in normal kernel-mode, this is in r13)
- * r32-r39 = system call arguments
- * b6 = return address (a user-level value)
- * ar.pfs = previous frame-state (a user-level value)
- * PSR.be = cleared to zero (i.e., little-endian byte order is in effect)
- * all other registers may contain values passed in from user-mode
- *
- * On return from an fsyscall handler:
- * r11 = saved ar.pfs (as passed into the fsyscall handler)
- * r15 = system call number (as passed into the fsyscall handler)
- * r32-r39 = system call arguments (as passed into the fsyscall handler)
- * b6 = return address (as passed into the fsyscall handler)
- * ar.pfs = previous frame-state (as passed into the fsyscall handler)
- */
-
-ENTRY(fsys_ni_syscall)
- .prologue
- .altrp b6
- .body
- mov r8=ENOSYS
- mov r10=-1
- FSYS_RETURN
-END(fsys_ni_syscall)
-
-ENTRY(fsys_getpid)
- .prologue
- .altrp b6
- .body
- add r17=IA64_TASK_SIGNAL_OFFSET,r16
- ;;
- ld8 r17=[r17] // r17 = current->signal
- add r9=TI_FLAGS+IA64_TASK_SIZE,r16
- ;;
- ld4 r9=[r9]
- add r17=IA64_SIGNAL_PIDS_TGID_OFFSET,r17
- ;;
- and r9=TIF_ALLWORK_MASK,r9
- ld8 r17=[r17] // r17 = current->signal->pids[PIDTYPE_TGID]
- ;;
- add r8=IA64_PID_LEVEL_OFFSET,r17
- ;;
- ld4 r8=[r8] // r8 = pid->level
- add r17=IA64_PID_UPID_OFFSET,r17 // r17 = &pid->numbers[0]
- ;;
- shl r8=r8,IA64_UPID_SHIFT
- ;;
- add r17=r17,r8 // r17 = &pid->numbers[pid->level]
- ;;
- ld4 r8=[r17] // r8 = pid->numbers[pid->level].nr
- ;;
- mov r17=0
- ;;
- cmp.ne p8,p0=0,r9
-(p8) br.spnt.many fsys_fallback_syscall
- FSYS_RETURN
-END(fsys_getpid)
-
-ENTRY(fsys_set_tid_address)
- .prologue
- .altrp b6
- .body
- add r9=TI_FLAGS+IA64_TASK_SIZE,r16
- add r17=IA64_TASK_THREAD_PID_OFFSET,r16
- ;;
- ld4 r9=[r9]
- tnat.z p6,p7=r32 // check argument register for being NaT
- ld8 r17=[r17] // r17 = current->thread_pid
- ;;
- and r9=TIF_ALLWORK_MASK,r9
- add r8=IA64_PID_LEVEL_OFFSET,r17
- add r18=IA64_TASK_CLEAR_CHILD_TID_OFFSET,r16
- ;;
- ld4 r8=[r8] // r8 = pid->level
- add r17=IA64_PID_UPID_OFFSET,r17 // r17 = &pid->numbers[0]
- ;;
- shl r8=r8,IA64_UPID_SHIFT
- ;;
- add r17=r17,r8 // r17 = &pid->numbers[pid->level]
- ;;
- ld4 r8=[r17] // r8 = pid->numbers[pid->level].nr
- ;;
- cmp.ne p8,p0=0,r9
- mov r17=-1
- ;;
-(p6) st8 [r18]=r32
-(p7) st8 [r18]=r17
-(p8) br.spnt.many fsys_fallback_syscall
- ;;
- mov r17=0 // i must not leak kernel bits...
- mov r18=0 // i must not leak kernel bits...
- FSYS_RETURN
-END(fsys_set_tid_address)
-
-#if IA64_GTOD_SEQ_OFFSET !=0
-#error fsys_gettimeofday incompatible with changes to struct fsyscall_gtod_data_t
-#endif
-#if IA64_ITC_JITTER_OFFSET !=0
-#error fsys_gettimeofday incompatible with changes to struct itc_jitter_data_t
-#endif
-#define CLOCK_REALTIME 0
-#define CLOCK_MONOTONIC 1
-#define CLOCK_DIVIDE_BY_1000 0x4000
-#define CLOCK_ADD_MONOTONIC 0x8000
-
-ENTRY(fsys_gettimeofday)
- .prologue
- .altrp b6
- .body
- mov r31 = r32
- tnat.nz p6,p0 = r33 // guard against NaT argument
-(p6) br.cond.spnt.few .fail_einval
- mov r30 = CLOCK_DIVIDE_BY_1000
- ;;
-.gettime:
- // Register map
- // Incoming r31 = pointer to address where to place result
- // r30 = flags determining how time is processed
- // r2,r3 = temp r4-r7 preserved
- // r8 = result nanoseconds
- // r9 = result seconds
- // r10 = temporary storage for clock difference
- // r11 = preserved: saved ar.pfs
- // r12 = preserved: memory stack
- // r13 = preserved: thread pointer
- // r14 = address of mask / mask value
- // r15 = preserved: system call number
- // r16 = preserved: current task pointer
- // r17 = (not used)
- // r18 = (not used)
- // r19 = address of itc_lastcycle
- // r20 = struct fsyscall_gtod_data (= address of gtod_lock.sequence)
- // r21 = address of mmio_ptr
- // r22 = address of wall_time or monotonic_time
- // r23 = address of shift / value
- // r24 = address mult factor / cycle_last value
- // r25 = itc_lastcycle value
- // r26 = address clocksource cycle_last
- // r27 = (not used)
- // r28 = sequence number at the beginning of critical section
- // r29 = address of itc_jitter
- // r30 = time processing flags / memory address
- // r31 = pointer to result
- // Predicates
- // p6,p7 short term use
- // p8 = timesource ar.itc
- // p9 = timesource mmio64
- // p10 = timesource mmio32 - not used
- // p11 = timesource not to be handled by asm code
- // p12 = memory time source ( = p9 | p10) - not used
- // p13 = do cmpxchg with itc_lastcycle
- // p14 = Divide by 1000
- // p15 = Add monotonic
- //
- // Note that instructions are optimized for McKinley. McKinley can
- // process two bundles simultaneously and therefore we continuously
- // try to feed the CPU two bundles and then a stop.
-
- add r2 = TI_FLAGS+IA64_TASK_SIZE,r16
- tnat.nz p6,p0 = r31 // guard against Nat argument
-(p6) br.cond.spnt.few .fail_einval
- movl r20 = fsyscall_gtod_data // load fsyscall gettimeofday data address
- ;;
- ld4 r2 = [r2] // process work pending flags
- movl r29 = itc_jitter_data // itc_jitter
- add r22 = IA64_GTOD_WALL_TIME_OFFSET,r20 // wall_time
- add r21 = IA64_CLKSRC_MMIO_OFFSET,r20
- mov pr = r30,0xc000 // Set predicates according to function
- ;;
- and r2 = TIF_ALLWORK_MASK,r2
- add r19 = IA64_ITC_LASTCYCLE_OFFSET,r29
-(p15) add r22 = IA64_GTOD_MONO_TIME_OFFSET,r20 // monotonic_time
- ;;
- add r26 = IA64_CLKSRC_CYCLE_LAST_OFFSET,r20 // clksrc_cycle_last
- cmp.ne p6, p0 = 0, r2 // Fallback if work is scheduled
-(p6) br.cond.spnt.many fsys_fallback_syscall
- ;;
- // Begin critical section
-.time_redo:
- ld4.acq r28 = [r20] // gtod_lock.sequence, Must take first
- ;;
- and r28 = ~1,r28 // And make sequence even to force retry if odd
- ;;
- ld8 r30 = [r21] // clocksource->mmio_ptr
- add r24 = IA64_CLKSRC_MULT_OFFSET,r20
- ld4 r2 = [r29] // itc_jitter value
- add r23 = IA64_CLKSRC_SHIFT_OFFSET,r20
- add r14 = IA64_CLKSRC_MASK_OFFSET,r20
- ;;
- ld4 r3 = [r24] // clocksource mult value
- ld8 r14 = [r14] // clocksource mask value
- cmp.eq p8,p9 = 0,r30 // use cpu timer if no mmio_ptr
- ;;
- setf.sig f7 = r3 // Setup for mult scaling of counter
-(p8) cmp.ne p13,p0 = r2,r0 // need itc_jitter compensation, set p13
- ld4 r23 = [r23] // clocksource shift value
- ld8 r24 = [r26] // get clksrc_cycle_last value
-(p9) cmp.eq p13,p0 = 0,r30 // if mmio_ptr, clear p13 jitter control
- ;;
- .pred.rel.mutex p8,p9
- MOV_FROM_ITC(p8, p6, r2, r10) // CPU_TIMER. 36 clocks latency!!!
-(p9) ld8 r2 = [r30] // MMIO_TIMER. Could also have latency issues..
-(p13) ld8 r25 = [r19] // get itc_lastcycle value
- ld8 r9 = [r22],IA64_TIME_SN_SPEC_SNSEC_OFFSET // sec
- ;;
- ld8 r8 = [r22],-IA64_TIME_SN_SPEC_SNSEC_OFFSET // snsec
-(p13) sub r3 = r25,r2 // Diff needed before comparison (thanks davidm)
- ;;
-(p13) cmp.gt.unc p6,p7 = r3,r0 // check if it is less than last. p6,p7 cleared
- sub r10 = r2,r24 // current_cycle - last_cycle
- ;;
-(p6) sub r10 = r25,r24 // time we got was less than last_cycle
-(p7) mov ar.ccv = r25 // more than last_cycle. Prep for cmpxchg
- ;;
-(p7) cmpxchg8.rel r3 = [r19],r2,ar.ccv
- ;;
-(p7) cmp.ne p7,p0 = r25,r3 // if cmpxchg not successful
- ;;
-(p7) sub r10 = r3,r24 // then use new last_cycle instead
- ;;
- and r10 = r10,r14 // Apply mask
- ;;
- setf.sig f8 = r10
- nop.i 123
- ;;
- // fault check takes 5 cycles and we have spare time
-EX(.fail_efault, probe.w.fault r31, 3)
- xmpy.l f8 = f8,f7 // nsec_per_cyc*(counter-last_counter)
- ;;
- getf.sig r2 = f8
- mf
- ;;
- ld4 r10 = [r20] // gtod_lock.sequence
- add r8 = r8,r2 // Add xtime.nsecs
- ;;
- shr.u r8 = r8,r23 // shift by factor
- cmp4.ne p7,p0 = r28,r10
-(p7) br.cond.dpnt.few .time_redo // sequence number changed, redo
- // End critical section.
- // Now r8=tv->tv_nsec and r9=tv->tv_sec
- mov r10 = r0
- movl r2 = 1000000000
- add r23 = IA64_TIMESPEC_TV_NSEC_OFFSET, r31
-(p14) movl r3 = 2361183241434822607 // Prep for / 1000 hack
- ;;
-.time_normalize:
- mov r21 = r8
- cmp.ge p6,p0 = r8,r2
-(p14) shr.u r20 = r8, 3 // We can repeat this if necessary just wasting time
- ;;
-(p14) setf.sig f8 = r20
-(p6) sub r8 = r8,r2
-(p6) add r9 = 1,r9 // two nops before the branch.
-(p14) setf.sig f7 = r3 // Chances for repeats are 1 in 10000 for gettod
-(p6) br.cond.dpnt.few .time_normalize
- ;;
- // Divided by 8 though shift. Now divide by 125
- // The compiler was able to do that with a multiply
- // and a shift and we do the same
-EX(.fail_efault, probe.w.fault r23, 3) // This also costs 5 cycles
-(p14) xmpy.hu f8 = f8, f7 // xmpy has 5 cycles latency so use it
- ;;
-(p14) getf.sig r2 = f8
- ;;
- mov r8 = r0
-(p14) shr.u r21 = r2, 4
- ;;
-EX(.fail_efault, st8 [r31] = r9)
-EX(.fail_efault, st8 [r23] = r21)
- FSYS_RETURN
-.fail_einval:
- mov r8 = EINVAL
- mov r10 = -1
- FSYS_RETURN
-.fail_efault:
- mov r8 = EFAULT
- mov r10 = -1
- FSYS_RETURN
-END(fsys_gettimeofday)
-
-ENTRY(fsys_clock_gettime)
- .prologue
- .altrp b6
- .body
- cmp4.ltu p6, p0 = CLOCK_MONOTONIC, r32
- // Fallback if this is not CLOCK_REALTIME or CLOCK_MONOTONIC
-(p6) br.spnt.few fsys_fallback_syscall
- mov r31 = r33
- shl r30 = r32,15
- br.many .gettime
-END(fsys_clock_gettime)
-
-/*
- * fsys_getcpu doesn't use the third parameter in this implementation. It reads
- * current_thread_info()->cpu and corresponding node in cpu_to_node_map.
- */
-ENTRY(fsys_getcpu)
- .prologue
- .altrp b6
- .body
- ;;
- add r2=TI_FLAGS+IA64_TASK_SIZE,r16
- tnat.nz p6,p0 = r32 // guard against NaT argument
- add r3=TI_CPU+IA64_TASK_SIZE,r16
- ;;
- ld4 r3=[r3] // M r3 = thread_info->cpu
- ld4 r2=[r2] // M r2 = thread_info->flags
-(p6) br.cond.spnt.few .fail_einval // B
- ;;
- tnat.nz p7,p0 = r33 // I guard against NaT argument
-(p7) br.cond.spnt.few .fail_einval // B
- ;;
- cmp.ne p6,p0=r32,r0
- cmp.ne p7,p0=r33,r0
- ;;
-#ifdef CONFIG_NUMA
- movl r17=cpu_to_node_map
- ;;
-EX(.fail_efault, (p6) probe.w.fault r32, 3) // M This takes 5 cycles
-EX(.fail_efault, (p7) probe.w.fault r33, 3) // M This takes 5 cycles
- shladd r18=r3,1,r17
- ;;
- ld2 r20=[r18] // r20 = cpu_to_node_map[cpu]
- and r2 = TIF_ALLWORK_MASK,r2
- ;;
- cmp.ne p8,p0=0,r2
-(p8) br.spnt.many fsys_fallback_syscall
- ;;
- ;;
-EX(.fail_efault, (p6) st4 [r32] = r3)
-EX(.fail_efault, (p7) st2 [r33] = r20)
- mov r8=0
- ;;
-#else
-EX(.fail_efault, (p6) probe.w.fault r32, 3) // M This takes 5 cycles
-EX(.fail_efault, (p7) probe.w.fault r33, 3) // M This takes 5 cycles
- and r2 = TIF_ALLWORK_MASK,r2
- ;;
- cmp.ne p8,p0=0,r2
-(p8) br.spnt.many fsys_fallback_syscall
- ;;
-EX(.fail_efault, (p6) st4 [r32] = r3)
-EX(.fail_efault, (p7) st2 [r33] = r0)
- mov r8=0
- ;;
-#endif
- FSYS_RETURN
-END(fsys_getcpu)
-
-ENTRY(fsys_fallback_syscall)
- .prologue
- .altrp b6
- .body
- /*
- * We only get here from light-weight syscall handlers. Thus, we already
- * know that r15 contains a valid syscall number. No need to re-check.
- */
- adds r17=-1024,r15
- movl r14=sys_call_table
- ;;
- RSM_PSR_I(p0, r26, r27)
- shladd r18=r17,3,r14
- ;;
- ld8 r18=[r18] // load normal (heavy-weight) syscall entry-point
- MOV_FROM_PSR(p0, r29, r26) // read psr (12 cyc load latency)
- mov r27=ar.rsc
- mov r21=ar.fpsr
- mov r26=ar.pfs
-END(fsys_fallback_syscall)
- /* FALL THROUGH */
-GLOBAL_ENTRY(fsys_bubble_down)
- .prologue
- .altrp b6
- .body
- /*
- * We get here for syscalls that don't have a lightweight
- * handler. For those, we need to bubble down into the kernel
- * and that requires setting up a minimal pt_regs structure,
- * and initializing the CPU state more or less as if an
- * interruption had occurred. To make syscall-restarts work,
- * we setup pt_regs such that cr_iip points to the second
- * instruction in syscall_via_break. Decrementing the IP
- * hence will restart the syscall via break and not
- * decrementing IP will return us to the caller, as usual.
- * Note that we preserve the value of psr.pp rather than
- * initializing it from dcr.pp. This makes it possible to
- * distinguish fsyscall execution from other privileged
- * execution.
- *
- * On entry:
- * - normal fsyscall handler register usage, except
- * that we also have:
- * - r18: address of syscall entry point
- * - r21: ar.fpsr
- * - r26: ar.pfs
- * - r27: ar.rsc
- * - r29: psr
- *
- * We used to clear some PSR bits here but that requires slow
- * serialization. Fortunately, that isn't really necessary.
- * The rationale is as follows: we used to clear bits
- * ~PSR_PRESERVED_BITS in PSR.L. Since
- * PSR_PRESERVED_BITS==PSR.{UP,MFL,MFH,PK,DT,PP,SP,RT,IC}, we
- * ended up clearing PSR.{BE,AC,I,DFL,DFH,DI,DB,SI,TB}.
- * However,
- *
- * PSR.BE : already is turned off in __kernel_syscall_via_epc()
- * PSR.AC : don't care (kernel normally turns PSR.AC on)
- * PSR.I : already turned off by the time fsys_bubble_down gets
- * invoked
- * PSR.DFL: always 0 (kernel never turns it on)
- * PSR.DFH: don't care --- kernel never touches f32-f127 on its own
- * initiative
- * PSR.DI : always 0 (kernel never turns it on)
- * PSR.SI : always 0 (kernel never turns it on)
- * PSR.DB : don't care --- kernel never enables kernel-level
- * breakpoints
- * PSR.TB : must be 0 already; if it wasn't zero on entry to
- * __kernel_syscall_via_epc, the branch to fsys_bubble_down
- * will trigger a taken branch; the taken-trap-handler then
- * converts the syscall into a break-based system-call.
- */
- /*
- * Reading psr.l gives us only bits 0-31, psr.it, and psr.mc.
- * The rest we have to synthesize.
- */
-# define PSR_ONE_BITS ((3 << IA64_PSR_CPL0_BIT) \
- | (0x1 << IA64_PSR_RI_BIT) \
- | IA64_PSR_BN | IA64_PSR_I)
-
- invala // M0|1
- movl r14=ia64_ret_from_syscall // X
-
- nop.m 0
- movl r28=__kernel_syscall_via_break // X create cr.iip
- ;;
-
- mov r2=r16 // A get task addr to addl-addressable register
- adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 // A
- mov r31=pr // I0 save pr (2 cyc)
- ;;
- st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag
- addl r22=IA64_RBS_OFFSET,r2 // A compute base of RBS
- add r3=TI_FLAGS+IA64_TASK_SIZE,r2 // A
- ;;
- ld4 r3=[r3] // M0|1 r3 = current_thread_info()->flags
- lfetch.fault.excl.nt1 [r22] // M0|1 prefetch register backing-store
- nop.i 0
- ;;
- mov ar.rsc=0 // M2 set enforced lazy mode, pl 0, LE, loadrs=0
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
- MOV_FROM_ITC(p0, p6, r30, r23) // M get cycle for accounting
-#else
- nop.m 0
-#endif
- nop.i 0
- ;;
- mov r23=ar.bspstore // M2 (12 cyc) save ar.bspstore
- mov.m r24=ar.rnat // M2 (5 cyc) read ar.rnat (dual-issues!)
- nop.i 0
- ;;
- mov ar.bspstore=r22 // M2 (6 cyc) switch to kernel RBS
- movl r8=PSR_ONE_BITS // X
- ;;
- mov r25=ar.unat // M2 (5 cyc) save ar.unat
- mov r19=b6 // I0 save b6 (2 cyc)
- mov r20=r1 // A save caller's gp in r20
- ;;
- or r29=r8,r29 // A construct cr.ipsr value to save
- mov b6=r18 // I0 copy syscall entry-point to b6 (7 cyc)
- addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2 // A compute base of memory stack
-
- mov r18=ar.bsp // M2 save (kernel) ar.bsp (12 cyc)
- cmp.ne pKStk,pUStk=r0,r0 // A set pKStk <- 0, pUStk <- 1
- br.call.sptk.many b7=ia64_syscall_setup // B
- ;;
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
- // mov.m r30=ar.itc is called in advance
- add r16=TI_AC_STAMP+IA64_TASK_SIZE,r2
- add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r2
- ;;
- ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // time at last check in kernel
- ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // time at leave kernel
- ;;
- ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME // cumulated stime
- ld8 r21=[r17] // cumulated utime
- sub r22=r19,r18 // stime before leave kernel
- ;;
- st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP // update stamp
- sub r18=r30,r19 // elapsed time in user mode
- ;;
- add r20=r20,r22 // sum stime
- add r21=r21,r18 // sum utime
- ;;
- st8 [r16]=r20 // update stime
- st8 [r17]=r21 // update utime
- ;;
-#endif
- mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0
- mov rp=r14 // I0 set the real return addr
- and r3=_TIF_SYSCALL_TRACEAUDIT,r3 // A
- ;;
- SSM_PSR_I(p0, p6, r22) // M2 we're on kernel stacks now, reenable irqs
- cmp.eq p8,p0=r3,r0 // A
-(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT
-
- nop.m 0
-(p8) br.call.sptk.many b6=b6 // B (ignore return address)
- br.cond.spnt ia64_trace_syscall // B
-END(fsys_bubble_down)
-
- .rodata
- .align 8
- .globl fsyscall_table
-
- data8 fsys_bubble_down
-fsyscall_table:
- data8 fsys_ni_syscall
- data8 0 // exit // 1025
- data8 0 // read
- data8 0 // write
- data8 0 // open
- data8 0 // close
- data8 0 // creat // 1030
- data8 0 // link
- data8 0 // unlink
- data8 0 // execve
- data8 0 // chdir
- data8 0 // fchdir // 1035
- data8 0 // utimes
- data8 0 // mknod
- data8 0 // chmod
- data8 0 // chown
- data8 0 // lseek // 1040
- data8 fsys_getpid // getpid
- data8 0 // getppid
- data8 0 // mount
- data8 0 // umount
- data8 0 // setuid // 1045
- data8 0 // getuid
- data8 0 // geteuid
- data8 0 // ptrace
- data8 0 // access
- data8 0 // sync // 1050
- data8 0 // fsync
- data8 0 // fdatasync
- data8 0 // kill
- data8 0 // rename
- data8 0 // mkdir // 1055
- data8 0 // rmdir
- data8 0 // dup
- data8 0 // pipe
- data8 0 // times
- data8 0 // brk // 1060
- data8 0 // setgid
- data8 0 // getgid
- data8 0 // getegid
- data8 0 // acct
- data8 0 // ioctl // 1065
- data8 0 // fcntl
- data8 0 // umask
- data8 0 // chroot
- data8 0 // ustat
- data8 0 // dup2 // 1070
- data8 0 // setreuid
- data8 0 // setregid
- data8 0 // getresuid
- data8 0 // setresuid
- data8 0 // getresgid // 1075
- data8 0 // setresgid
- data8 0 // getgroups
- data8 0 // setgroups
- data8 0 // getpgid
- data8 0 // setpgid // 1080
- data8 0 // setsid
- data8 0 // getsid
- data8 0 // sethostname
- data8 0 // setrlimit
- data8 0 // getrlimit // 1085
- data8 0 // getrusage
- data8 fsys_gettimeofday // gettimeofday
- data8 0 // settimeofday
- data8 0 // select
- data8 0 // poll // 1090
- data8 0 // symlink
- data8 0 // readlink
- data8 0 // uselib
- data8 0 // swapon
- data8 0 // swapoff // 1095
- data8 0 // reboot
- data8 0 // truncate
- data8 0 // ftruncate
- data8 0 // fchmod
- data8 0 // fchown // 1100
- data8 0 // getpriority
- data8 0 // setpriority
- data8 0 // statfs
- data8 0 // fstatfs
- data8 0 // gettid // 1105
- data8 0 // semget
- data8 0 // semop
- data8 0 // semctl
- data8 0 // msgget
- data8 0 // msgsnd // 1110
- data8 0 // msgrcv
- data8 0 // msgctl
- data8 0 // shmget
- data8 0 // shmat
- data8 0 // shmdt // 1115
- data8 0 // shmctl
- data8 0 // syslog
- data8 0 // setitimer
- data8 0 // getitimer
- data8 0 // 1120
- data8 0
- data8 0
- data8 0 // vhangup
- data8 0 // lchown
- data8 0 // remap_file_pages // 1125
- data8 0 // wait4
- data8 0 // sysinfo
- data8 0 // clone
- data8 0 // setdomainname
- data8 0 // newuname // 1130
- data8 0 // adjtimex
- data8 0
- data8 0 // init_module
- data8 0 // delete_module
- data8 0 // 1135
- data8 0
- data8 0 // quotactl
- data8 0 // bdflush
- data8 0 // sysfs
- data8 0 // personality // 1140
- data8 0 // afs_syscall
- data8 0 // setfsuid
- data8 0 // setfsgid
- data8 0 // getdents
- data8 0 // flock // 1145
- data8 0 // readv
- data8 0 // writev
- data8 0 // pread64
- data8 0 // pwrite64
- data8 0 // sysctl // 1150
- data8 0 // mmap
- data8 0 // munmap
- data8 0 // mlock
- data8 0 // mlockall
- data8 0 // mprotect // 1155
- data8 0 // mremap
- data8 0 // msync
- data8 0 // munlock
- data8 0 // munlockall
- data8 0 // sched_getparam // 1160
- data8 0 // sched_setparam
- data8 0 // sched_getscheduler
- data8 0 // sched_setscheduler
- data8 0 // sched_yield
- data8 0 // sched_get_priority_max // 1165
- data8 0 // sched_get_priority_min
- data8 0 // sched_rr_get_interval
- data8 0 // nanosleep
- data8 0 // nfsservctl
- data8 0 // prctl // 1170
- data8 0 // getpagesize
- data8 0 // mmap2
- data8 0 // pciconfig_read
- data8 0 // pciconfig_write
- data8 0 // perfmonctl // 1175
- data8 0 // sigaltstack
- data8 0 // rt_sigaction
- data8 0 // rt_sigpending
- data8 0 // rt_sigprocmask
- data8 0 // rt_sigqueueinfo // 1180
- data8 0 // rt_sigreturn
- data8 0 // rt_sigsuspend
- data8 0 // rt_sigtimedwait
- data8 0 // getcwd
- data8 0 // capget // 1185
- data8 0 // capset
- data8 0 // sendfile
- data8 0
- data8 0
- data8 0 // socket // 1190
- data8 0 // bind
- data8 0 // connect
- data8 0 // listen
- data8 0 // accept
- data8 0 // getsockname // 1195
- data8 0 // getpeername
- data8 0 // socketpair
- data8 0 // send
- data8 0 // sendto
- data8 0 // recv // 1200
- data8 0 // recvfrom
- data8 0 // shutdown
- data8 0 // setsockopt
- data8 0 // getsockopt
- data8 0 // sendmsg // 1205
- data8 0 // recvmsg
- data8 0 // pivot_root
- data8 0 // mincore
- data8 0 // madvise
- data8 0 // newstat // 1210
- data8 0 // newlstat
- data8 0 // newfstat
- data8 0 // clone2
- data8 0 // getdents64
- data8 0 // getunwind // 1215
- data8 0 // readahead
- data8 0 // setxattr
- data8 0 // lsetxattr
- data8 0 // fsetxattr
- data8 0 // getxattr // 1220
- data8 0 // lgetxattr
- data8 0 // fgetxattr
- data8 0 // listxattr
- data8 0 // llistxattr
- data8 0 // flistxattr // 1225
- data8 0 // removexattr
- data8 0 // lremovexattr
- data8 0 // fremovexattr
- data8 0 // tkill
- data8 0 // futex // 1230
- data8 0 // sched_setaffinity
- data8 0 // sched_getaffinity
- data8 fsys_set_tid_address // set_tid_address
- data8 0 // fadvise64_64
- data8 0 // tgkill // 1235
- data8 0 // exit_group
- data8 0 // lookup_dcookie
- data8 0 // io_setup
- data8 0 // io_destroy
- data8 0 // io_getevents // 1240
- data8 0 // io_submit
- data8 0 // io_cancel
- data8 0 // epoll_create
- data8 0 // epoll_ctl
- data8 0 // epoll_wait // 1245
- data8 0 // restart_syscall
- data8 0 // semtimedop
- data8 0 // timer_create
- data8 0 // timer_settime
- data8 0 // timer_gettime // 1250
- data8 0 // timer_getoverrun
- data8 0 // timer_delete
- data8 0 // clock_settime
- data8 fsys_clock_gettime // clock_gettime
- data8 0 // clock_getres // 1255
- data8 0 // clock_nanosleep
- data8 0 // fstatfs64
- data8 0 // statfs64
- data8 0 // mbind
- data8 0 // get_mempolicy // 1260
- data8 0 // set_mempolicy
- data8 0 // mq_open
- data8 0 // mq_unlink
- data8 0 // mq_timedsend
- data8 0 // mq_timedreceive // 1265
- data8 0 // mq_notify
- data8 0 // mq_getsetattr
- data8 0 // kexec_load
- data8 0 // vserver
- data8 0 // waitid // 1270
- data8 0 // add_key
- data8 0 // request_key
- data8 0 // keyctl
- data8 0 // ioprio_set
- data8 0 // ioprio_get // 1275
- data8 0 // move_pages
- data8 0 // inotify_init
- data8 0 // inotify_add_watch
- data8 0 // inotify_rm_watch
- data8 0 // migrate_pages // 1280
- data8 0 // openat
- data8 0 // mkdirat
- data8 0 // mknodat
- data8 0 // fchownat
- data8 0 // futimesat // 1285
- data8 0 // newfstatat
- data8 0 // unlinkat
- data8 0 // renameat
- data8 0 // linkat
- data8 0 // symlinkat // 1290
- data8 0 // readlinkat
- data8 0 // fchmodat
- data8 0 // faccessat
- data8 0
- data8 0 // 1295
- data8 0 // unshare
- data8 0 // splice
- data8 0 // set_robust_list
- data8 0 // get_robust_list
- data8 0 // sync_file_range // 1300
- data8 0 // tee
- data8 0 // vmsplice
- data8 0
- data8 fsys_getcpu // getcpu // 1304
-
- // fill in zeros for the remaining entries
- .zero:
- .space fsyscall_table + 8*NR_syscalls - .zero, 0
diff --git a/arch/ia64/kernel/fsyscall_gtod_data.h b/arch/ia64/kernel/fsyscall_gtod_data.h
deleted file mode 100644
index cc2861445965..000000000000
--- a/arch/ia64/kernel/fsyscall_gtod_data.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
- * Contributed by Peter Keilty <peter.keilty@hp.com>
- *
- * fsyscall gettimeofday data
- */
-
-/* like timespec, but includes "shifted nanoseconds" */
-struct time_sn_spec {
- u64 sec;
- u64 snsec;
-};
-
-struct fsyscall_gtod_data_t {
- seqcount_t seq;
- struct time_sn_spec wall_time;
- struct time_sn_spec monotonic_time;
- u64 clk_mask;
- u32 clk_mult;
- u32 clk_shift;
- void *clk_fsys_mmio;
- u64 clk_cycle_last;
-} ____cacheline_aligned;
-
-struct itc_jitter_data_t {
- int itc_jitter;
- u64 itc_lastcycle;
-} ____cacheline_aligned;
-
diff --git a/arch/ia64/kernel/ftrace.c b/arch/ia64/kernel/ftrace.c
deleted file mode 100644
index d6360fd404ab..000000000000
--- a/arch/ia64/kernel/ftrace.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Dynamic function tracing support.
- *
- * Copyright (C) 2008 Shaohua Li <shaohua.li@intel.com>
- *
- * For licencing details, see COPYING.
- *
- * Defines low-level handling of mcount calls when the kernel
- * is compiled with the -pg flag. When using dynamic ftrace, the
- * mcount call-sites get patched lazily with NOP till they are
- * enabled. All code mutation routines here take effect atomically.
- */
-
-#include <linux/uaccess.h>
-#include <linux/ftrace.h>
-
-#include <asm/cacheflush.h>
-#include <asm/patch.h>
-
-/* In IA64, each function will be added below two bundles with -pg option */
-static unsigned char __attribute__((aligned(8)))
-ftrace_orig_code[MCOUNT_INSN_SIZE] = {
- 0x02, 0x40, 0x31, 0x10, 0x80, 0x05, /* alloc r40=ar.pfs,12,8,0 */
- 0xb0, 0x02, 0x00, 0x00, 0x42, 0x40, /* mov r43=r0;; */
- 0x05, 0x00, 0xc4, 0x00, /* mov r42=b0 */
- 0x11, 0x48, 0x01, 0x02, 0x00, 0x21, /* mov r41=r1 */
- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* nop.i 0x0 */
- 0x08, 0x00, 0x00, 0x50 /* br.call.sptk.many b0 = _mcount;; */
-};
-
-struct ftrace_orig_insn {
- u64 dummy1, dummy2, dummy3;
- u64 dummy4:64-41+13;
- u64 imm20:20;
- u64 dummy5:3;
- u64 sign:1;
- u64 dummy6:4;
-};
-
-/* mcount stub will be converted below for nop */
-static unsigned char ftrace_nop_code[MCOUNT_INSN_SIZE] = {
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MII] nop.m 0x0 */
- 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, /* mov r3=ip */
- 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0 */
- 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0x0 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* nop.x 0x0;; */
- 0x00, 0x00, 0x04, 0x00
-};
-
-static unsigned char *ftrace_nop_replace(void)
-{
- return ftrace_nop_code;
-}
-
-/*
- * mcount stub will be converted below for call
- * Note: Just the last instruction is changed against nop
- * */
-static unsigned char __attribute__((aligned(8)))
-ftrace_call_code[MCOUNT_INSN_SIZE] = {
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MII] nop.m 0x0 */
- 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, /* mov r3=ip */
- 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0 */
- 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0x0 */
- 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, /* brl.many .;;*/
- 0xf8, 0xff, 0xff, 0xc8
-};
-
-struct ftrace_call_insn {
- u64 dummy1, dummy2;
- u64 dummy3:48;
- u64 imm39_l:16;
- u64 imm39_h:23;
- u64 dummy4:13;
- u64 imm20:20;
- u64 dummy5:3;
- u64 i:1;
- u64 dummy6:4;
-};
-
-static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
-{
- struct ftrace_call_insn *code = (void *)ftrace_call_code;
- unsigned long offset = addr - (ip + 0x10);
-
- code->imm39_l = offset >> 24;
- code->imm39_h = offset >> 40;
- code->imm20 = offset >> 4;
- code->i = offset >> 63;
- return ftrace_call_code;
-}
-
-static int
-ftrace_modify_code(unsigned long ip, unsigned char *old_code,
- unsigned char *new_code, int do_check)
-{
- unsigned char replaced[MCOUNT_INSN_SIZE];
-
- /*
- * Note:
- * We are paranoid about modifying text, as if a bug was to happen, it
- * could cause us to read or write to someplace that could cause harm.
- * Carefully read and modify the code with probe_kernel_*(), and make
- * sure what we read is what we expected it to be before modifying it.
- */
-
- if (!do_check)
- goto skip_check;
-
- /* read the text we want to modify */
- if (copy_from_kernel_nofault(replaced, (void *)ip, MCOUNT_INSN_SIZE))
- return -EFAULT;
-
- /* Make sure it is what we expect it to be */
- if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0)
- return -EINVAL;
-
-skip_check:
- /* replace the text with the new text */
- if (copy_to_kernel_nofault(((void *)ip), new_code, MCOUNT_INSN_SIZE))
- return -EPERM;
- flush_icache_range(ip, ip + MCOUNT_INSN_SIZE);
-
- return 0;
-}
-
-static int ftrace_make_nop_check(struct dyn_ftrace *rec, unsigned long addr)
-{
- unsigned char __attribute__((aligned(8))) replaced[MCOUNT_INSN_SIZE];
- unsigned long ip = rec->ip;
-
- if (copy_from_kernel_nofault(replaced, (void *)ip, MCOUNT_INSN_SIZE))
- return -EFAULT;
- if (rec->flags & FTRACE_FL_CONVERTED) {
- struct ftrace_call_insn *call_insn, *tmp_call;
-
- call_insn = (void *)ftrace_call_code;
- tmp_call = (void *)replaced;
- call_insn->imm39_l = tmp_call->imm39_l;
- call_insn->imm39_h = tmp_call->imm39_h;
- call_insn->imm20 = tmp_call->imm20;
- call_insn->i = tmp_call->i;
- if (memcmp(replaced, ftrace_call_code, MCOUNT_INSN_SIZE) != 0)
- return -EINVAL;
- return 0;
- } else {
- struct ftrace_orig_insn *call_insn, *tmp_call;
-
- call_insn = (void *)ftrace_orig_code;
- tmp_call = (void *)replaced;
- call_insn->sign = tmp_call->sign;
- call_insn->imm20 = tmp_call->imm20;
- if (memcmp(replaced, ftrace_orig_code, MCOUNT_INSN_SIZE) != 0)
- return -EINVAL;
- return 0;
- }
-}
-
-int ftrace_make_nop(struct module *mod,
- struct dyn_ftrace *rec, unsigned long addr)
-{
- int ret;
- char *new;
-
- ret = ftrace_make_nop_check(rec, addr);
- if (ret)
- return ret;
- new = ftrace_nop_replace();
- return ftrace_modify_code(rec->ip, NULL, new, 0);
-}
-
-int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
-{
- unsigned long ip = rec->ip;
- unsigned char *old, *new;
-
- old= ftrace_nop_replace();
- new = ftrace_call_replace(ip, addr);
- return ftrace_modify_code(ip, old, new, 1);
-}
-
-/* in IA64, _mcount can't directly call ftrace_stub. Only jump is ok */
-int ftrace_update_ftrace_func(ftrace_func_t func)
-{
- unsigned long ip;
- unsigned long addr = ((struct fnptr *)ftrace_call)->ip;
-
- if (func == ftrace_stub)
- return 0;
- ip = ((struct fnptr *)func)->ip;
-
- ia64_patch_imm64(addr + 2, ip);
-
- flush_icache_range(addr, addr + 16);
- return 0;
-}
diff --git a/arch/ia64/kernel/gate-data.S b/arch/ia64/kernel/gate-data.S
deleted file mode 100644
index b3ef1c72e132..000000000000
--- a/arch/ia64/kernel/gate-data.S
+++ /dev/null
@@ -1,3 +0,0 @@
- .section .data..gate, "aw"
-
- .incbin "arch/ia64/kernel/gate.so"
diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S
deleted file mode 100644
index 9f235cd551ab..000000000000
--- a/arch/ia64/kernel/gate.S
+++ /dev/null
@@ -1,380 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * This file contains the code that gets mapped at the upper end of each task's text
- * region. For now, it contains the signal trampoline code only.
- *
- * Copyright (C) 1999-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-
-#include <asm/asmmacro.h>
-#include <asm/errno.h>
-#include <asm/asm-offsets.h>
-#include <asm/sigcontext.h>
-#include <asm/unistd.h>
-#include <asm/kregs.h>
-#include <asm/page.h>
-#include <asm/native/inst.h>
-
-/*
- * We can't easily refer to symbols inside the kernel. To avoid full runtime relocation,
- * complications with the linker (which likes to create PLT stubs for branches
- * to targets outside the shared object) and to avoid multi-phase kernel builds, we
- * simply create minimalistic "patch lists" in special ELF sections.
- */
- .section ".data..patch.fsyscall_table", "a"
- .previous
-#define LOAD_FSYSCALL_TABLE(reg) \
-[1:] movl reg=0; \
- .xdata4 ".data..patch.fsyscall_table", 1b-.
-
- .section ".data..patch.brl_fsys_bubble_down", "a"
- .previous
-#define BRL_COND_FSYS_BUBBLE_DOWN(pr) \
-[1:](pr)brl.cond.sptk 0; \
- ;; \
- .xdata4 ".data..patch.brl_fsys_bubble_down", 1b-.
-
-GLOBAL_ENTRY(__kernel_syscall_via_break)
- .prologue
- .altrp b6
- .body
- /*
- * Note: for (fast) syscall restart to work, the break instruction must be
- * the first one in the bundle addressed by syscall_via_break.
- */
-{ .mib
- break 0x100000
- nop.i 0
- br.ret.sptk.many b6
-}
-END(__kernel_syscall_via_break)
-
-# define ARG0_OFF (16 + IA64_SIGFRAME_ARG0_OFFSET)
-# define ARG1_OFF (16 + IA64_SIGFRAME_ARG1_OFFSET)
-# define ARG2_OFF (16 + IA64_SIGFRAME_ARG2_OFFSET)
-# define SIGHANDLER_OFF (16 + IA64_SIGFRAME_HANDLER_OFFSET)
-# define SIGCONTEXT_OFF (16 + IA64_SIGFRAME_SIGCONTEXT_OFFSET)
-
-# define FLAGS_OFF IA64_SIGCONTEXT_FLAGS_OFFSET
-# define CFM_OFF IA64_SIGCONTEXT_CFM_OFFSET
-# define FR6_OFF IA64_SIGCONTEXT_FR6_OFFSET
-# define BSP_OFF IA64_SIGCONTEXT_AR_BSP_OFFSET
-# define RNAT_OFF IA64_SIGCONTEXT_AR_RNAT_OFFSET
-# define UNAT_OFF IA64_SIGCONTEXT_AR_UNAT_OFFSET
-# define FPSR_OFF IA64_SIGCONTEXT_AR_FPSR_OFFSET
-# define PR_OFF IA64_SIGCONTEXT_PR_OFFSET
-# define RP_OFF IA64_SIGCONTEXT_IP_OFFSET
-# define SP_OFF IA64_SIGCONTEXT_R12_OFFSET
-# define RBS_BASE_OFF IA64_SIGCONTEXT_RBS_BASE_OFFSET
-# define LOADRS_OFF IA64_SIGCONTEXT_LOADRS_OFFSET
-# define base0 r2
-# define base1 r3
- /*
- * When we get here, the memory stack looks like this:
- *
- * +===============================+
- * | |
- * // struct sigframe //
- * | |
- * +-------------------------------+ <-- sp+16
- * | 16 byte of scratch |
- * | space |
- * +-------------------------------+ <-- sp
- *
- * The register stack looks _exactly_ the way it looked at the time the signal
- * occurred. In other words, we're treading on a potential mine-field: each
- * incoming general register may be a NaT value (including sp, in which case the
- * process ends up dying with a SIGSEGV).
- *
- * The first thing need to do is a cover to get the registers onto the backing
- * store. Once that is done, we invoke the signal handler which may modify some
- * of the machine state. After returning from the signal handler, we return
- * control to the previous context by executing a sigreturn system call. A signal
- * handler may call the rt_sigreturn() function to directly return to a given
- * sigcontext. However, the user-level sigreturn() needs to do much more than
- * calling the rt_sigreturn() system call as it needs to unwind the stack to
- * restore preserved registers that may have been saved on the signal handler's
- * call stack.
- */
-
-#define SIGTRAMP_SAVES \
- .unwabi 3, 's'; /* mark this as a sigtramp handler (saves scratch regs) */ \
- .unwabi @svr4, 's'; /* backwards compatibility with old unwinders (remove in v2.7) */ \
- .savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF; \
- .savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF; \
- .savesp pr, PR_OFF+SIGCONTEXT_OFF; \
- .savesp rp, RP_OFF+SIGCONTEXT_OFF; \
- .savesp ar.pfs, CFM_OFF+SIGCONTEXT_OFF; \
- .vframesp SP_OFF+SIGCONTEXT_OFF
-
-GLOBAL_ENTRY(__kernel_sigtramp)
- // describe the state that is active when we get here:
- .prologue
- SIGTRAMP_SAVES
- .body
-
- .label_state 1
-
- adds base0=SIGHANDLER_OFF,sp
- adds base1=RBS_BASE_OFF+SIGCONTEXT_OFF,sp
- br.call.sptk.many rp=1f
-1:
- ld8 r17=[base0],(ARG0_OFF-SIGHANDLER_OFF) // get pointer to signal handler's plabel
- ld8 r15=[base1] // get address of new RBS base (or NULL)
- cover // push args in interrupted frame onto backing store
- ;;
- cmp.ne p1,p0=r15,r0 // do we need to switch rbs? (note: pr is saved by kernel)
- mov.m r9=ar.bsp // fetch ar.bsp
- .spillsp.p p1, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
-(p1) br.cond.spnt setup_rbs // yup -> (clobbers p8, r14-r16, and r18-r20)
-back_from_setup_rbs:
- alloc r8=ar.pfs,0,0,3,0
- ld8 out0=[base0],16 // load arg0 (signum)
- adds base1=(ARG1_OFF-(RBS_BASE_OFF+SIGCONTEXT_OFF)),base1
- ;;
- ld8 out1=[base1] // load arg1 (siginfop)
- ld8 r10=[r17],8 // get signal handler entry point
- ;;
- ld8 out2=[base0] // load arg2 (sigcontextp)
- ld8 gp=[r17] // get signal handler's global pointer
- adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
- ;;
- .spillsp ar.bsp, BSP_OFF+SIGCONTEXT_OFF
- st8 [base0]=r9 // save sc_ar_bsp
- adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
- adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
- ;;
- stf.spill [base0]=f6,32
- stf.spill [base1]=f7,32
- ;;
- stf.spill [base0]=f8,32
- stf.spill [base1]=f9,32
- mov b6=r10
- ;;
- stf.spill [base0]=f10,32
- stf.spill [base1]=f11,32
- ;;
- stf.spill [base0]=f12,32
- stf.spill [base1]=f13,32
- ;;
- stf.spill [base0]=f14,32
- stf.spill [base1]=f15,32
- br.call.sptk.many rp=b6 // call the signal handler
-.ret0: adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
- ;;
- ld8 r15=[base0] // fetch sc_ar_bsp
- mov r14=ar.bsp
- ;;
- cmp.ne p1,p0=r14,r15 // do we need to restore the rbs?
-(p1) br.cond.spnt restore_rbs // yup -> (clobbers r14-r18, f6 & f7)
- ;;
-back_from_restore_rbs:
- adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
- adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
- ;;
- ldf.fill f6=[base0],32
- ldf.fill f7=[base1],32
- ;;
- ldf.fill f8=[base0],32
- ldf.fill f9=[base1],32
- ;;
- ldf.fill f10=[base0],32
- ldf.fill f11=[base1],32
- ;;
- ldf.fill f12=[base0],32
- ldf.fill f13=[base1],32
- ;;
- ldf.fill f14=[base0],32
- ldf.fill f15=[base1],32
- mov r15=__NR_rt_sigreturn
- .restore sp // pop .prologue
- break __BREAK_SYSCALL
-
- .prologue
- SIGTRAMP_SAVES
-setup_rbs:
- mov ar.rsc=0 // put RSE into enforced lazy mode
- ;;
- .save ar.rnat, r19
- mov r19=ar.rnat // save RNaT before switching backing store area
- adds r14=(RNAT_OFF+SIGCONTEXT_OFF),sp
-
- mov r18=ar.bspstore
- mov ar.bspstore=r15 // switch over to new register backing store area
- ;;
-
- .spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
- st8 [r14]=r19 // save sc_ar_rnat
- .body
- mov.m r16=ar.bsp // sc_loadrs <- (new bsp - new bspstore) << 16
- adds r14=(LOADRS_OFF+SIGCONTEXT_OFF),sp
- ;;
- invala
- sub r15=r16,r15
- extr.u r20=r18,3,6
- ;;
- mov ar.rsc=0xf // set RSE into eager mode, pl 3
- cmp.eq p8,p0=63,r20
- shl r15=r15,16
- ;;
- st8 [r14]=r15 // save sc_loadrs
-(p8) st8 [r18]=r19 // if bspstore points at RNaT slot, store RNaT there now
- .restore sp // pop .prologue
- br.cond.sptk back_from_setup_rbs
-
- .prologue
- SIGTRAMP_SAVES
- .spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
- .body
-restore_rbs:
- // On input:
- // r14 = bsp1 (bsp at the time of return from signal handler)
- // r15 = bsp0 (bsp at the time the signal occurred)
- //
- // Here, we need to calculate bspstore0, the value that ar.bspstore needs
- // to be set to, based on bsp0 and the size of the dirty partition on
- // the alternate stack (sc_loadrs >> 16). This can be done with the
- // following algorithm:
- //
- // bspstore0 = rse_skip_regs(bsp0, -rse_num_regs(bsp1 - (loadrs >> 19), bsp1));
- //
- // This is what the code below does.
- //
- alloc r2=ar.pfs,0,0,0,0 // alloc null frame
- adds r16=(LOADRS_OFF+SIGCONTEXT_OFF),sp
- adds r18=(RNAT_OFF+SIGCONTEXT_OFF),sp
- ;;
- ld8 r17=[r16]
- ld8 r16=[r18] // get new rnat
- extr.u r18=r15,3,6 // r18 <- rse_slot_num(bsp0)
- ;;
- mov ar.rsc=r17 // put RSE into enforced lazy mode
- shr.u r17=r17,16
- ;;
- sub r14=r14,r17 // r14 (bspstore1) <- bsp1 - (sc_loadrs >> 16)
- shr.u r17=r17,3 // r17 <- (sc_loadrs >> 19)
- ;;
- loadrs // restore dirty partition
- extr.u r14=r14,3,6 // r14 <- rse_slot_num(bspstore1)
- ;;
- add r14=r14,r17 // r14 <- rse_slot_num(bspstore1) + (sc_loadrs >> 19)
- ;;
- shr.u r14=r14,6 // r14 <- (rse_slot_num(bspstore1) + (sc_loadrs >> 19))/0x40
- ;;
- sub r14=r14,r17 // r14 <- -rse_num_regs(bspstore1, bsp1)
- movl r17=0x8208208208208209
- ;;
- add r18=r18,r14 // r18 (delta) <- rse_slot_num(bsp0) - rse_num_regs(bspstore1,bsp1)
- setf.sig f7=r17
- cmp.lt p7,p0=r14,r0 // p7 <- (r14 < 0)?
- ;;
-(p7) adds r18=-62,r18 // delta -= 62
- ;;
- setf.sig f6=r18
- ;;
- xmpy.h f6=f6,f7
- ;;
- getf.sig r17=f6
- ;;
- add r17=r17,r18
- shr r18=r18,63
- ;;
- shr r17=r17,5
- ;;
- sub r17=r17,r18 // r17 = delta/63
- ;;
- add r17=r14,r17 // r17 <- delta/63 - rse_num_regs(bspstore1, bsp1)
- ;;
- shladd r15=r17,3,r15 // r15 <- bsp0 + 8*(delta/63 - rse_num_regs(bspstore1, bsp1))
- ;;
- mov ar.bspstore=r15 // switch back to old register backing store area
- ;;
- mov ar.rnat=r16 // restore RNaT
- mov ar.rsc=0xf // (will be restored later on from sc_ar_rsc)
- // invala not necessary as that will happen when returning to user-mode
- br.cond.sptk back_from_restore_rbs
-END(__kernel_sigtramp)
-
-/*
- * On entry:
- * r11 = saved ar.pfs
- * r15 = system call #
- * b0 = saved return address
- * b6 = return address
- * On exit:
- * r11 = saved ar.pfs
- * r15 = system call #
- * b0 = saved return address
- * all other "scratch" registers: undefined
- * all "preserved" registers: same as on entry
- */
-
-GLOBAL_ENTRY(__kernel_syscall_via_epc)
- .prologue
- .altrp b6
- .body
-{
- /*
- * Note: the kernel cannot assume that the first two instructions in this
- * bundle get executed. The remaining code must be safe even if
- * they do not get executed.
- */
- adds r17=-1024,r15 // A
- mov r10=0 // A default to successful syscall execution
- epc // B causes split-issue
-}
- ;;
- RSM_PSR_BE_I(r20, r22) // M2 (5 cyc to srlz.d)
- LOAD_FSYSCALL_TABLE(r14) // X
- ;;
- mov r16=IA64_KR(CURRENT) // M2 (12 cyc)
- shladd r18=r17,3,r14 // A
- mov r19=NR_syscalls-1 // A
- ;;
- lfetch [r18] // M0|1
- MOV_FROM_PSR(p0, r29, r8) // M2 (12 cyc)
- // If r17 is a NaT, p6 will be zero
- cmp.geu p6,p7=r19,r17 // A (sysnr > 0 && sysnr < 1024+NR_syscalls)?
- ;;
- mov r21=ar.fpsr // M2 (12 cyc)
- tnat.nz p10,p9=r15 // I0
- mov.i r26=ar.pfs // I0 (would stall anyhow due to srlz.d...)
- ;;
- srlz.d // M0 (forces split-issue) ensure PSR.BE==0
-(p6) ld8 r18=[r18] // M0|1
- nop.i 0
- ;;
- nop.m 0
-(p6) tbit.z.unc p8,p0=r18,0 // I0 (dual-issues with "mov b7=r18"!)
- nop.i 0
- ;;
- SSM_PSR_I(p8, p14, r25)
-(p6) mov b7=r18 // I0
-(p8) br.dptk.many b7 // B
-
- mov r27=ar.rsc // M2 (12 cyc)
-/*
- * brl.cond doesn't work as intended because the linker would convert this branch
- * into a branch to a PLT. Perhaps there will be a way to avoid this with some
- * future version of the linker. In the meantime, we just use an indirect branch
- * instead.
- */
-#ifdef CONFIG_ITANIUM
-(p6) add r14=-8,r14 // r14 <- addr of fsys_bubble_down entry
- ;;
-(p6) ld8 r14=[r14] // r14 <- fsys_bubble_down
- ;;
-(p6) mov b7=r14
-(p6) br.sptk.many b7
-#else
- BRL_COND_FSYS_BUBBLE_DOWN(p6)
-#endif
- SSM_PSR_I(p0, p14, r10)
- mov r10=-1
-(p10) mov r8=EINVAL
-(p9) mov r8=ENOSYS
- FSYS_RETURN
-
-END(__kernel_syscall_via_epc)
diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S
deleted file mode 100644
index 461c7e69d465..000000000000
--- a/arch/ia64/kernel/gate.lds.S
+++ /dev/null
@@ -1,108 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Linker script for gate DSO. The gate pages are an ELF shared object
- * prelinked to its virtual address, with only one read-only segment and
- * one execute-only segment (both fit in one page). This script controls
- * its layout.
- */
-
-#include <asm/page.h>
-
-SECTIONS
-{
- . = GATE_ADDR + SIZEOF_HEADERS;
-
- .hash : { *(.hash) } :readable
- .gnu.hash : { *(.gnu.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
-
- .note : { *(.note*) } :readable :note
-
- .dynamic : { *(.dynamic) } :readable :dynamic
-
- /*
- * This linker script is used both with -r and with -shared. For
- * the layouts to match, we need to skip more than enough space for
- * the dynamic symbol table et al. If this amount is insufficient,
- * ld -shared will barf. Just increase it here.
- */
- . = GATE_ADDR + 0x600;
-
- .data..patch : {
- __start_gate_mckinley_e9_patchlist = .;
- *(.data..patch.mckinley_e9)
- __end_gate_mckinley_e9_patchlist = .;
-
- __start_gate_vtop_patchlist = .;
- *(.data..patch.vtop)
- __end_gate_vtop_patchlist = .;
-
- __start_gate_fsyscall_patchlist = .;
- *(.data..patch.fsyscall_table)
- __end_gate_fsyscall_patchlist = .;
-
- __start_gate_brl_fsys_bubble_down_patchlist = .;
- *(.data..patch.brl_fsys_bubble_down)
- __end_gate_brl_fsys_bubble_down_patchlist = .;
- } :readable
-
- .IA_64.unwind_info : { *(.IA_64.unwind_info*) }
- .IA_64.unwind : { *(.IA_64.unwind*) } :readable :unwind
-#ifdef HAVE_BUGGY_SEGREL
- .text (GATE_ADDR + PAGE_SIZE) : { *(.text) *(.text.*) } :readable
-#else
- . = ALIGN(PERCPU_PAGE_SIZE) + (. & (PERCPU_PAGE_SIZE - 1));
- .text : { *(.text) *(.text.*) } :epc
-#endif
-
- /DISCARD/ : {
- *(.got.plt) *(.got)
- *(.data .data.* .gnu.linkonce.d.*)
- *(.dynbss)
- *(.bss .bss.* .gnu.linkonce.b.*)
- *(__ex_table)
- *(__mca_table)
- }
-}
-
-/*
- * ld does not recognize this name token; use the constant.
- */
-#define PT_IA_64_UNWIND 0x70000001
-
-/*
- * We must supply the ELF program headers explicitly to get just one
- * PT_LOAD segment, and set the flags explicitly to make segments read-only.
- */
-PHDRS
-{
- readable PT_LOAD FILEHDR PHDRS FLAGS(4); /* PF_R */
-#ifndef HAVE_BUGGY_SEGREL
- epc PT_LOAD FILEHDR PHDRS FLAGS(1); /* PF_X */
-#endif
- dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
- note PT_NOTE FLAGS(4); /* PF_R */
- unwind PT_IA_64_UNWIND;
-}
-
-/*
- * This controls what symbols we export from the DSO.
- */
-VERSION
-{
- LINUX_2.5 {
- global:
- __kernel_syscall_via_break;
- __kernel_syscall_via_epc;
- __kernel_sigtramp;
-
- local: *;
- };
-}
-
-/* The ELF entry point can be used to set the AT_SYSINFO value. */
-ENTRY(__kernel_syscall_via_epc)
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
deleted file mode 100644
index 85c8a57da402..000000000000
--- a/arch/ia64/kernel/head.S
+++ /dev/null
@@ -1,1167 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Here is where the ball gets rolling as far as the kernel is concerned.
- * When control is transferred to _start, the bootload has already
- * loaded us to the correct address. All that's left to do here is
- * to set up the kernel's global pointer and jump to the kernel
- * entry point.
- *
- * Copyright (C) 1998-2001, 2003, 2005 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999 Intel Corp.
- * Copyright (C) 1999 Asit Mallick <Asit.K.Mallick@intel.com>
- * Copyright (C) 1999 Don Dugger <Don.Dugger@intel.com>
- * Copyright (C) 2002 Fenghua Yu <fenghua.yu@intel.com>
- * -Optimize __ia64_save_fpu() and __ia64_load_fpu() for Itanium 2.
- * Copyright (C) 2004 Ashok Raj <ashok.raj@intel.com>
- * Support for CPU Hotplug
- */
-
-#include <linux/export.h>
-#include <linux/pgtable.h>
-#include <asm/asmmacro.h>
-#include <asm/fpu.h>
-#include <asm/kregs.h>
-#include <asm/mmu_context.h>
-#include <asm/asm-offsets.h>
-#include <asm/pal.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/mca_asm.h>
-#include <linux/init.h>
-#include <linux/linkage.h>
-
-#ifdef CONFIG_HOTPLUG_CPU
-#define SAL_PSR_BITS_TO_SET \
- (IA64_PSR_AC | IA64_PSR_BN | IA64_PSR_MFH | IA64_PSR_MFL)
-
-#define SAVE_FROM_REG(src, ptr, dest) \
- mov dest=src;; \
- st8 [ptr]=dest,0x08
-
-#define RESTORE_REG(reg, ptr, _tmp) \
- ld8 _tmp=[ptr],0x08;; \
- mov reg=_tmp
-
-#define SAVE_BREAK_REGS(ptr, _idx, _breg, _dest)\
- mov ar.lc=IA64_NUM_DBG_REGS-1;; \
- mov _idx=0;; \
-1: \
- SAVE_FROM_REG(_breg[_idx], ptr, _dest);; \
- add _idx=1,_idx;; \
- br.cloop.sptk.many 1b
-
-#define RESTORE_BREAK_REGS(ptr, _idx, _breg, _tmp, _lbl)\
- mov ar.lc=IA64_NUM_DBG_REGS-1;; \
- mov _idx=0;; \
-_lbl: RESTORE_REG(_breg[_idx], ptr, _tmp);; \
- add _idx=1, _idx;; \
- br.cloop.sptk.many _lbl
-
-#define SAVE_ONE_RR(num, _reg, _tmp) \
- movl _tmp=(num<<61);; \
- mov _reg=rr[_tmp]
-
-#define SAVE_REGION_REGS(_tmp, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) \
- SAVE_ONE_RR(0,_r0, _tmp);; \
- SAVE_ONE_RR(1,_r1, _tmp);; \
- SAVE_ONE_RR(2,_r2, _tmp);; \
- SAVE_ONE_RR(3,_r3, _tmp);; \
- SAVE_ONE_RR(4,_r4, _tmp);; \
- SAVE_ONE_RR(5,_r5, _tmp);; \
- SAVE_ONE_RR(6,_r6, _tmp);; \
- SAVE_ONE_RR(7,_r7, _tmp);;
-
-#define STORE_REGION_REGS(ptr, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) \
- st8 [ptr]=_r0, 8;; \
- st8 [ptr]=_r1, 8;; \
- st8 [ptr]=_r2, 8;; \
- st8 [ptr]=_r3, 8;; \
- st8 [ptr]=_r4, 8;; \
- st8 [ptr]=_r5, 8;; \
- st8 [ptr]=_r6, 8;; \
- st8 [ptr]=_r7, 8;;
-
-#define RESTORE_REGION_REGS(ptr, _idx1, _idx2, _tmp) \
- mov ar.lc=0x08-1;; \
- movl _idx1=0x00;; \
-RestRR: \
- dep.z _idx2=_idx1,61,3;; \
- ld8 _tmp=[ptr],8;; \
- mov rr[_idx2]=_tmp;; \
- srlz.d;; \
- add _idx1=1,_idx1;; \
- br.cloop.sptk.few RestRR
-
-#define SET_AREA_FOR_BOOTING_CPU(reg1, reg2) \
- movl reg1=sal_state_for_booting_cpu;; \
- ld8 reg2=[reg1];;
-
-/*
- * Adjust region registers saved before starting to save
- * break regs and rest of the states that need to be preserved.
- */
-#define SAL_TO_OS_BOOT_HANDOFF_STATE_SAVE(_reg1,_reg2,_pred) \
- SAVE_FROM_REG(b0,_reg1,_reg2);; \
- SAVE_FROM_REG(b1,_reg1,_reg2);; \
- SAVE_FROM_REG(b2,_reg1,_reg2);; \
- SAVE_FROM_REG(b3,_reg1,_reg2);; \
- SAVE_FROM_REG(b4,_reg1,_reg2);; \
- SAVE_FROM_REG(b5,_reg1,_reg2);; \
- st8 [_reg1]=r1,0x08;; \
- st8 [_reg1]=r12,0x08;; \
- st8 [_reg1]=r13,0x08;; \
- SAVE_FROM_REG(ar.fpsr,_reg1,_reg2);; \
- SAVE_FROM_REG(ar.pfs,_reg1,_reg2);; \
- SAVE_FROM_REG(ar.rnat,_reg1,_reg2);; \
- SAVE_FROM_REG(ar.unat,_reg1,_reg2);; \
- SAVE_FROM_REG(ar.bspstore,_reg1,_reg2);; \
- SAVE_FROM_REG(cr.dcr,_reg1,_reg2);; \
- SAVE_FROM_REG(cr.iva,_reg1,_reg2);; \
- SAVE_FROM_REG(cr.pta,_reg1,_reg2);; \
- SAVE_FROM_REG(cr.itv,_reg1,_reg2);; \
- SAVE_FROM_REG(cr.pmv,_reg1,_reg2);; \
- SAVE_FROM_REG(cr.cmcv,_reg1,_reg2);; \
- SAVE_FROM_REG(cr.lrr0,_reg1,_reg2);; \
- SAVE_FROM_REG(cr.lrr1,_reg1,_reg2);; \
- st8 [_reg1]=r4,0x08;; \
- st8 [_reg1]=r5,0x08;; \
- st8 [_reg1]=r6,0x08;; \
- st8 [_reg1]=r7,0x08;; \
- st8 [_reg1]=_pred,0x08;; \
- SAVE_FROM_REG(ar.lc, _reg1, _reg2);; \
- stf.spill.nta [_reg1]=f2,16;; \
- stf.spill.nta [_reg1]=f3,16;; \
- stf.spill.nta [_reg1]=f4,16;; \
- stf.spill.nta [_reg1]=f5,16;; \
- stf.spill.nta [_reg1]=f16,16;; \
- stf.spill.nta [_reg1]=f17,16;; \
- stf.spill.nta [_reg1]=f18,16;; \
- stf.spill.nta [_reg1]=f19,16;; \
- stf.spill.nta [_reg1]=f20,16;; \
- stf.spill.nta [_reg1]=f21,16;; \
- stf.spill.nta [_reg1]=f22,16;; \
- stf.spill.nta [_reg1]=f23,16;; \
- stf.spill.nta [_reg1]=f24,16;; \
- stf.spill.nta [_reg1]=f25,16;; \
- stf.spill.nta [_reg1]=f26,16;; \
- stf.spill.nta [_reg1]=f27,16;; \
- stf.spill.nta [_reg1]=f28,16;; \
- stf.spill.nta [_reg1]=f29,16;; \
- stf.spill.nta [_reg1]=f30,16;; \
- stf.spill.nta [_reg1]=f31,16;;
-
-#else
-#define SET_AREA_FOR_BOOTING_CPU(a1, a2)
-#define SAL_TO_OS_BOOT_HANDOFF_STATE_SAVE(a1,a2, a3)
-#define SAVE_REGION_REGS(_tmp, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7)
-#define STORE_REGION_REGS(ptr, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7)
-#endif
-
-#define SET_ONE_RR(num, pgsize, _tmp1, _tmp2, vhpt) \
- movl _tmp1=(num << 61);; \
- mov _tmp2=((ia64_rid(IA64_REGION_ID_KERNEL, (num<<61)) << 8) | (pgsize << 2) | vhpt);; \
- mov rr[_tmp1]=_tmp2
-
- __PAGE_ALIGNED_DATA
-
- .global empty_zero_page
-EXPORT_SYMBOL_GPL(empty_zero_page)
-empty_zero_page:
- .skip PAGE_SIZE
-
- .global swapper_pg_dir
-swapper_pg_dir:
- .skip PAGE_SIZE
-
- .rodata
-halt_msg:
- stringz "Halting kernel\n"
-
- __REF
-
- .global start_ap
-
- /*
- * Start the kernel. When the bootloader passes control to _start(), r28
- * points to the address of the boot parameter area. Execution reaches
- * here in physical mode.
- */
-GLOBAL_ENTRY(_start)
-start_ap:
- .prologue
- .save rp, r0 // terminate unwind chain with a NULL rp
- .body
-
- rsm psr.i | psr.ic
- ;;
- srlz.i
- ;;
- {
- flushrs // must be first insn in group
- srlz.i
- }
- ;;
- /*
- * Save the region registers, predicate before they get clobbered
- */
- SAVE_REGION_REGS(r2, r8,r9,r10,r11,r12,r13,r14,r15);
- mov r25=pr;;
-
- /*
- * Initialize kernel region registers:
- * rr[0]: VHPT enabled, page size = PAGE_SHIFT
- * rr[1]: VHPT enabled, page size = PAGE_SHIFT
- * rr[2]: VHPT enabled, page size = PAGE_SHIFT
- * rr[3]: VHPT enabled, page size = PAGE_SHIFT
- * rr[4]: VHPT enabled, page size = PAGE_SHIFT
- * rr[5]: VHPT enabled, page size = PAGE_SHIFT
- * rr[6]: VHPT disabled, page size = IA64_GRANULE_SHIFT
- * rr[7]: VHPT disabled, page size = IA64_GRANULE_SHIFT
- * We initialize all of them to prevent inadvertently assuming
- * something about the state of address translation early in boot.
- */
- SET_ONE_RR(0, PAGE_SHIFT, r2, r16, 1);;
- SET_ONE_RR(1, PAGE_SHIFT, r2, r16, 1);;
- SET_ONE_RR(2, PAGE_SHIFT, r2, r16, 1);;
- SET_ONE_RR(3, PAGE_SHIFT, r2, r16, 1);;
- SET_ONE_RR(4, PAGE_SHIFT, r2, r16, 1);;
- SET_ONE_RR(5, PAGE_SHIFT, r2, r16, 1);;
- SET_ONE_RR(6, IA64_GRANULE_SHIFT, r2, r16, 0);;
- SET_ONE_RR(7, IA64_GRANULE_SHIFT, r2, r16, 0);;
- /*
- * Now pin mappings into the TLB for kernel text and data
- */
- mov r18=KERNEL_TR_PAGE_SHIFT<<2
- movl r17=KERNEL_START
- ;;
- mov cr.itir=r18
- mov cr.ifa=r17
- mov r16=IA64_TR_KERNEL
- mov r3=ip
- movl r18=PAGE_KERNEL
- ;;
- dep r2=0,r3,0,KERNEL_TR_PAGE_SHIFT
- ;;
- or r18=r2,r18
- ;;
- srlz.i
- ;;
- itr.i itr[r16]=r18
- ;;
- itr.d dtr[r16]=r18
- ;;
- srlz.i
-
- /*
- * Switch into virtual mode:
- */
- movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \
- |IA64_PSR_DI)
- ;;
- mov cr.ipsr=r16
- movl r17=1f
- ;;
- mov cr.iip=r17
- mov cr.ifs=r0
- ;;
- rfi
- ;;
-1: // now we are in virtual mode
-
- SET_AREA_FOR_BOOTING_CPU(r2, r16);
-
- STORE_REGION_REGS(r16, r8,r9,r10,r11,r12,r13,r14,r15);
- SAL_TO_OS_BOOT_HANDOFF_STATE_SAVE(r16,r17,r25)
- ;;
-
- // set IVT entry point---can't access I/O ports without it
- movl r3=ia64_ivt
- ;;
- mov cr.iva=r3
- movl r2=FPSR_DEFAULT
- ;;
- srlz.i
- movl gp=__gp
-
- mov ar.fpsr=r2
- ;;
-
-#define isAP p2 // are we an Application Processor?
-#define isBP p3 // are we the Bootstrap Processor?
-
-#ifdef CONFIG_SMP
- /*
- * Find the init_task for the currently booting CPU. At poweron, and in
- * UP mode, task_for_booting_cpu is NULL.
- */
- movl r3=task_for_booting_cpu
- ;;
- ld8 r3=[r3]
- movl r2=init_task
- ;;
- cmp.eq isBP,isAP=r3,r0
- ;;
-(isAP) mov r2=r3
-#else
- movl r2=init_task
- cmp.eq isBP,isAP=r0,r0
-#endif
- ;;
- tpa r3=r2 // r3 == phys addr of task struct
- mov r16=-1
-(isBP) br.cond.dpnt .load_current // BP stack is on region 5 --- no need to map it
-
- // load mapping for stack (virtaddr in r2, physaddr in r3)
- rsm psr.ic
- movl r17=PAGE_KERNEL
- ;;
- srlz.d
- dep r18=0,r3,0,12
- ;;
- or r18=r17,r18
- dep r2=-1,r3,61,3 // IMVA of task
- ;;
- mov r17=rr[r2]
- shr.u r16=r3,IA64_GRANULE_SHIFT
- ;;
- dep r17=0,r17,8,24
- ;;
- mov cr.itir=r17
- mov cr.ifa=r2
-
- mov r19=IA64_TR_CURRENT_STACK
- ;;
- itr.d dtr[r19]=r18
- ;;
- ssm psr.ic
- srlz.d
- ;;
-
-.load_current:
- // load the "current" pointer (r13) and ar.k6 with the current task
- mov IA64_KR(CURRENT)=r2 // virtual address
- mov IA64_KR(CURRENT_STACK)=r16
- mov r13=r2
- /*
- * Reserve space at the top of the stack for "struct pt_regs". Kernel
- * threads don't store interesting values in that structure, but the space
- * still needs to be there because time-critical stuff such as the context
- * switching can be implemented more efficiently (for example, __switch_to()
- * always sets the psr.dfh bit of the task it is switching to).
- */
-
- addl r12=IA64_STK_OFFSET-IA64_PT_REGS_SIZE-16,r2
- addl r2=IA64_RBS_OFFSET,r2 // initialize the RSE
- mov ar.rsc=0 // place RSE in enforced lazy mode
- ;;
- loadrs // clear the dirty partition
- movl r19=__phys_per_cpu_start
- mov r18=PERCPU_PAGE_SIZE
- ;;
-#ifndef CONFIG_SMP
- add r19=r19,r18
- ;;
-#else
-(isAP) br.few 2f
- movl r20=__cpu0_per_cpu
- ;;
- shr.u r18=r18,3
-1:
- ld8 r21=[r19],8;;
- st8[r20]=r21,8
- adds r18=-1,r18;;
- cmp4.lt p7,p6=0,r18
-(p7) br.cond.dptk.few 1b
- mov r19=r20
- ;;
-2:
-#endif
- tpa r19=r19
- ;;
- .pred.rel.mutex isBP,isAP
-(isBP) mov IA64_KR(PER_CPU_DATA)=r19 // per-CPU base for cpu0
-(isAP) mov IA64_KR(PER_CPU_DATA)=r0 // clear physical per-CPU base
- ;;
- mov ar.bspstore=r2 // establish the new RSE stack
- ;;
- mov ar.rsc=0x3 // place RSE in eager mode
-
-(isBP) dep r28=-1,r28,61,3 // make address virtual
-(isBP) movl r2=ia64_boot_param
- ;;
-(isBP) st8 [r2]=r28 // save the address of the boot param area passed by the bootloader
-
-#ifdef CONFIG_SMP
-(isAP) br.call.sptk.many rp=start_secondary
-.ret0:
-(isAP) br.cond.sptk self
-#endif
-
- // This is executed by the bootstrap processor (bsp) only:
-
- br.call.sptk.many rp=start_kernel
-.ret2: addl r3=@ltoff(halt_msg),gp
- ;;
- alloc r2=ar.pfs,8,0,2,0
- ;;
- ld8 out0=[r3]
- br.call.sptk.many b0=console_print
-
-self: hint @pause
- br.sptk.many self // endless loop
-END(_start)
-
- .text
-
-GLOBAL_ENTRY(ia64_save_debug_regs)
- alloc r16=ar.pfs,1,0,0,0
- mov r20=ar.lc // preserve ar.lc
- mov ar.lc=IA64_NUM_DBG_REGS-1
- mov r18=0
- add r19=IA64_NUM_DBG_REGS*8,in0
- ;;
-1: mov r16=dbr[r18]
-#ifdef CONFIG_ITANIUM
- ;;
- srlz.d
-#endif
- mov r17=ibr[r18]
- add r18=1,r18
- ;;
- st8.nta [in0]=r16,8
- st8.nta [r19]=r17,8
- br.cloop.sptk.many 1b
- ;;
- mov ar.lc=r20 // restore ar.lc
- br.ret.sptk.many rp
-END(ia64_save_debug_regs)
-
-GLOBAL_ENTRY(ia64_load_debug_regs)
- alloc r16=ar.pfs,1,0,0,0
- lfetch.nta [in0]
- mov r20=ar.lc // preserve ar.lc
- add r19=IA64_NUM_DBG_REGS*8,in0
- mov ar.lc=IA64_NUM_DBG_REGS-1
- mov r18=-1
- ;;
-1: ld8.nta r16=[in0],8
- ld8.nta r17=[r19],8
- add r18=1,r18
- ;;
- mov dbr[r18]=r16
-#ifdef CONFIG_ITANIUM
- ;;
- srlz.d // Errata 132 (NoFix status)
-#endif
- mov ibr[r18]=r17
- br.cloop.sptk.many 1b
- ;;
- mov ar.lc=r20 // restore ar.lc
- br.ret.sptk.many rp
-END(ia64_load_debug_regs)
-
-GLOBAL_ENTRY(__ia64_save_fpu)
- alloc r2=ar.pfs,1,4,0,0
- adds loc0=96*16-16,in0
- adds loc1=96*16-16-128,in0
- ;;
- stf.spill.nta [loc0]=f127,-256
- stf.spill.nta [loc1]=f119,-256
- ;;
- stf.spill.nta [loc0]=f111,-256
- stf.spill.nta [loc1]=f103,-256
- ;;
- stf.spill.nta [loc0]=f95,-256
- stf.spill.nta [loc1]=f87,-256
- ;;
- stf.spill.nta [loc0]=f79,-256
- stf.spill.nta [loc1]=f71,-256
- ;;
- stf.spill.nta [loc0]=f63,-256
- stf.spill.nta [loc1]=f55,-256
- adds loc2=96*16-32,in0
- ;;
- stf.spill.nta [loc0]=f47,-256
- stf.spill.nta [loc1]=f39,-256
- adds loc3=96*16-32-128,in0
- ;;
- stf.spill.nta [loc2]=f126,-256
- stf.spill.nta [loc3]=f118,-256
- ;;
- stf.spill.nta [loc2]=f110,-256
- stf.spill.nta [loc3]=f102,-256
- ;;
- stf.spill.nta [loc2]=f94,-256
- stf.spill.nta [loc3]=f86,-256
- ;;
- stf.spill.nta [loc2]=f78,-256
- stf.spill.nta [loc3]=f70,-256
- ;;
- stf.spill.nta [loc2]=f62,-256
- stf.spill.nta [loc3]=f54,-256
- adds loc0=96*16-48,in0
- ;;
- stf.spill.nta [loc2]=f46,-256
- stf.spill.nta [loc3]=f38,-256
- adds loc1=96*16-48-128,in0
- ;;
- stf.spill.nta [loc0]=f125,-256
- stf.spill.nta [loc1]=f117,-256
- ;;
- stf.spill.nta [loc0]=f109,-256
- stf.spill.nta [loc1]=f101,-256
- ;;
- stf.spill.nta [loc0]=f93,-256
- stf.spill.nta [loc1]=f85,-256
- ;;
- stf.spill.nta [loc0]=f77,-256
- stf.spill.nta [loc1]=f69,-256
- ;;
- stf.spill.nta [loc0]=f61,-256
- stf.spill.nta [loc1]=f53,-256
- adds loc2=96*16-64,in0
- ;;
- stf.spill.nta [loc0]=f45,-256
- stf.spill.nta [loc1]=f37,-256
- adds loc3=96*16-64-128,in0
- ;;
- stf.spill.nta [loc2]=f124,-256
- stf.spill.nta [loc3]=f116,-256
- ;;
- stf.spill.nta [loc2]=f108,-256
- stf.spill.nta [loc3]=f100,-256
- ;;
- stf.spill.nta [loc2]=f92,-256
- stf.spill.nta [loc3]=f84,-256
- ;;
- stf.spill.nta [loc2]=f76,-256
- stf.spill.nta [loc3]=f68,-256
- ;;
- stf.spill.nta [loc2]=f60,-256
- stf.spill.nta [loc3]=f52,-256
- adds loc0=96*16-80,in0
- ;;
- stf.spill.nta [loc2]=f44,-256
- stf.spill.nta [loc3]=f36,-256
- adds loc1=96*16-80-128,in0
- ;;
- stf.spill.nta [loc0]=f123,-256
- stf.spill.nta [loc1]=f115,-256
- ;;
- stf.spill.nta [loc0]=f107,-256
- stf.spill.nta [loc1]=f99,-256
- ;;
- stf.spill.nta [loc0]=f91,-256
- stf.spill.nta [loc1]=f83,-256
- ;;
- stf.spill.nta [loc0]=f75,-256
- stf.spill.nta [loc1]=f67,-256
- ;;
- stf.spill.nta [loc0]=f59,-256
- stf.spill.nta [loc1]=f51,-256
- adds loc2=96*16-96,in0
- ;;
- stf.spill.nta [loc0]=f43,-256
- stf.spill.nta [loc1]=f35,-256
- adds loc3=96*16-96-128,in0
- ;;
- stf.spill.nta [loc2]=f122,-256
- stf.spill.nta [loc3]=f114,-256
- ;;
- stf.spill.nta [loc2]=f106,-256
- stf.spill.nta [loc3]=f98,-256
- ;;
- stf.spill.nta [loc2]=f90,-256
- stf.spill.nta [loc3]=f82,-256
- ;;
- stf.spill.nta [loc2]=f74,-256
- stf.spill.nta [loc3]=f66,-256
- ;;
- stf.spill.nta [loc2]=f58,-256
- stf.spill.nta [loc3]=f50,-256
- adds loc0=96*16-112,in0
- ;;
- stf.spill.nta [loc2]=f42,-256
- stf.spill.nta [loc3]=f34,-256
- adds loc1=96*16-112-128,in0
- ;;
- stf.spill.nta [loc0]=f121,-256
- stf.spill.nta [loc1]=f113,-256
- ;;
- stf.spill.nta [loc0]=f105,-256
- stf.spill.nta [loc1]=f97,-256
- ;;
- stf.spill.nta [loc0]=f89,-256
- stf.spill.nta [loc1]=f81,-256
- ;;
- stf.spill.nta [loc0]=f73,-256
- stf.spill.nta [loc1]=f65,-256
- ;;
- stf.spill.nta [loc0]=f57,-256
- stf.spill.nta [loc1]=f49,-256
- adds loc2=96*16-128,in0
- ;;
- stf.spill.nta [loc0]=f41,-256
- stf.spill.nta [loc1]=f33,-256
- adds loc3=96*16-128-128,in0
- ;;
- stf.spill.nta [loc2]=f120,-256
- stf.spill.nta [loc3]=f112,-256
- ;;
- stf.spill.nta [loc2]=f104,-256
- stf.spill.nta [loc3]=f96,-256
- ;;
- stf.spill.nta [loc2]=f88,-256
- stf.spill.nta [loc3]=f80,-256
- ;;
- stf.spill.nta [loc2]=f72,-256
- stf.spill.nta [loc3]=f64,-256
- ;;
- stf.spill.nta [loc2]=f56,-256
- stf.spill.nta [loc3]=f48,-256
- ;;
- stf.spill.nta [loc2]=f40
- stf.spill.nta [loc3]=f32
- br.ret.sptk.many rp
-END(__ia64_save_fpu)
-
-GLOBAL_ENTRY(__ia64_load_fpu)
- alloc r2=ar.pfs,1,2,0,0
- adds r3=128,in0
- adds r14=256,in0
- adds r15=384,in0
- mov loc0=512
- mov loc1=-1024+16
- ;;
- ldf.fill.nta f32=[in0],loc0
- ldf.fill.nta f40=[ r3],loc0
- ldf.fill.nta f48=[r14],loc0
- ldf.fill.nta f56=[r15],loc0
- ;;
- ldf.fill.nta f64=[in0],loc0
- ldf.fill.nta f72=[ r3],loc0
- ldf.fill.nta f80=[r14],loc0
- ldf.fill.nta f88=[r15],loc0
- ;;
- ldf.fill.nta f96=[in0],loc1
- ldf.fill.nta f104=[ r3],loc1
- ldf.fill.nta f112=[r14],loc1
- ldf.fill.nta f120=[r15],loc1
- ;;
- ldf.fill.nta f33=[in0],loc0
- ldf.fill.nta f41=[ r3],loc0
- ldf.fill.nta f49=[r14],loc0
- ldf.fill.nta f57=[r15],loc0
- ;;
- ldf.fill.nta f65=[in0],loc0
- ldf.fill.nta f73=[ r3],loc0
- ldf.fill.nta f81=[r14],loc0
- ldf.fill.nta f89=[r15],loc0
- ;;
- ldf.fill.nta f97=[in0],loc1
- ldf.fill.nta f105=[ r3],loc1
- ldf.fill.nta f113=[r14],loc1
- ldf.fill.nta f121=[r15],loc1
- ;;
- ldf.fill.nta f34=[in0],loc0
- ldf.fill.nta f42=[ r3],loc0
- ldf.fill.nta f50=[r14],loc0
- ldf.fill.nta f58=[r15],loc0
- ;;
- ldf.fill.nta f66=[in0],loc0
- ldf.fill.nta f74=[ r3],loc0
- ldf.fill.nta f82=[r14],loc0
- ldf.fill.nta f90=[r15],loc0
- ;;
- ldf.fill.nta f98=[in0],loc1
- ldf.fill.nta f106=[ r3],loc1
- ldf.fill.nta f114=[r14],loc1
- ldf.fill.nta f122=[r15],loc1
- ;;
- ldf.fill.nta f35=[in0],loc0
- ldf.fill.nta f43=[ r3],loc0
- ldf.fill.nta f51=[r14],loc0
- ldf.fill.nta f59=[r15],loc0
- ;;
- ldf.fill.nta f67=[in0],loc0
- ldf.fill.nta f75=[ r3],loc0
- ldf.fill.nta f83=[r14],loc0
- ldf.fill.nta f91=[r15],loc0
- ;;
- ldf.fill.nta f99=[in0],loc1
- ldf.fill.nta f107=[ r3],loc1
- ldf.fill.nta f115=[r14],loc1
- ldf.fill.nta f123=[r15],loc1
- ;;
- ldf.fill.nta f36=[in0],loc0
- ldf.fill.nta f44=[ r3],loc0
- ldf.fill.nta f52=[r14],loc0
- ldf.fill.nta f60=[r15],loc0
- ;;
- ldf.fill.nta f68=[in0],loc0
- ldf.fill.nta f76=[ r3],loc0
- ldf.fill.nta f84=[r14],loc0
- ldf.fill.nta f92=[r15],loc0
- ;;
- ldf.fill.nta f100=[in0],loc1
- ldf.fill.nta f108=[ r3],loc1
- ldf.fill.nta f116=[r14],loc1
- ldf.fill.nta f124=[r15],loc1
- ;;
- ldf.fill.nta f37=[in0],loc0
- ldf.fill.nta f45=[ r3],loc0
- ldf.fill.nta f53=[r14],loc0
- ldf.fill.nta f61=[r15],loc0
- ;;
- ldf.fill.nta f69=[in0],loc0
- ldf.fill.nta f77=[ r3],loc0
- ldf.fill.nta f85=[r14],loc0
- ldf.fill.nta f93=[r15],loc0
- ;;
- ldf.fill.nta f101=[in0],loc1
- ldf.fill.nta f109=[ r3],loc1
- ldf.fill.nta f117=[r14],loc1
- ldf.fill.nta f125=[r15],loc1
- ;;
- ldf.fill.nta f38 =[in0],loc0
- ldf.fill.nta f46 =[ r3],loc0
- ldf.fill.nta f54 =[r14],loc0
- ldf.fill.nta f62 =[r15],loc0
- ;;
- ldf.fill.nta f70 =[in0],loc0
- ldf.fill.nta f78 =[ r3],loc0
- ldf.fill.nta f86 =[r14],loc0
- ldf.fill.nta f94 =[r15],loc0
- ;;
- ldf.fill.nta f102=[in0],loc1
- ldf.fill.nta f110=[ r3],loc1
- ldf.fill.nta f118=[r14],loc1
- ldf.fill.nta f126=[r15],loc1
- ;;
- ldf.fill.nta f39 =[in0],loc0
- ldf.fill.nta f47 =[ r3],loc0
- ldf.fill.nta f55 =[r14],loc0
- ldf.fill.nta f63 =[r15],loc0
- ;;
- ldf.fill.nta f71 =[in0],loc0
- ldf.fill.nta f79 =[ r3],loc0
- ldf.fill.nta f87 =[r14],loc0
- ldf.fill.nta f95 =[r15],loc0
- ;;
- ldf.fill.nta f103=[in0]
- ldf.fill.nta f111=[ r3]
- ldf.fill.nta f119=[r14]
- ldf.fill.nta f127=[r15]
- br.ret.sptk.many rp
-END(__ia64_load_fpu)
-
-GLOBAL_ENTRY(__ia64_init_fpu)
- stf.spill [sp]=f0 // M3
- mov f32=f0 // F
- nop.b 0
-
- ldfps f33,f34=[sp] // M0
- ldfps f35,f36=[sp] // M1
- mov f37=f0 // F
- ;;
-
- setf.s f38=r0 // M2
- setf.s f39=r0 // M3
- mov f40=f0 // F
-
- ldfps f41,f42=[sp] // M0
- ldfps f43,f44=[sp] // M1
- mov f45=f0 // F
-
- setf.s f46=r0 // M2
- setf.s f47=r0 // M3
- mov f48=f0 // F
-
- ldfps f49,f50=[sp] // M0
- ldfps f51,f52=[sp] // M1
- mov f53=f0 // F
-
- setf.s f54=r0 // M2
- setf.s f55=r0 // M3
- mov f56=f0 // F
-
- ldfps f57,f58=[sp] // M0
- ldfps f59,f60=[sp] // M1
- mov f61=f0 // F
-
- setf.s f62=r0 // M2
- setf.s f63=r0 // M3
- mov f64=f0 // F
-
- ldfps f65,f66=[sp] // M0
- ldfps f67,f68=[sp] // M1
- mov f69=f0 // F
-
- setf.s f70=r0 // M2
- setf.s f71=r0 // M3
- mov f72=f0 // F
-
- ldfps f73,f74=[sp] // M0
- ldfps f75,f76=[sp] // M1
- mov f77=f0 // F
-
- setf.s f78=r0 // M2
- setf.s f79=r0 // M3
- mov f80=f0 // F
-
- ldfps f81,f82=[sp] // M0
- ldfps f83,f84=[sp] // M1
- mov f85=f0 // F
-
- setf.s f86=r0 // M2
- setf.s f87=r0 // M3
- mov f88=f0 // F
-
- /*
- * When the instructions are cached, it would be faster to initialize
- * the remaining registers with simply mov instructions (F-unit).
- * This gets the time down to ~29 cycles. However, this would use up
- * 33 bundles, whereas continuing with the above pattern yields
- * 10 bundles and ~30 cycles.
- */
-
- ldfps f89,f90=[sp] // M0
- ldfps f91,f92=[sp] // M1
- mov f93=f0 // F
-
- setf.s f94=r0 // M2
- setf.s f95=r0 // M3
- mov f96=f0 // F
-
- ldfps f97,f98=[sp] // M0
- ldfps f99,f100=[sp] // M1
- mov f101=f0 // F
-
- setf.s f102=r0 // M2
- setf.s f103=r0 // M3
- mov f104=f0 // F
-
- ldfps f105,f106=[sp] // M0
- ldfps f107,f108=[sp] // M1
- mov f109=f0 // F
-
- setf.s f110=r0 // M2
- setf.s f111=r0 // M3
- mov f112=f0 // F
-
- ldfps f113,f114=[sp] // M0
- ldfps f115,f116=[sp] // M1
- mov f117=f0 // F
-
- setf.s f118=r0 // M2
- setf.s f119=r0 // M3
- mov f120=f0 // F
-
- ldfps f121,f122=[sp] // M0
- ldfps f123,f124=[sp] // M1
- mov f125=f0 // F
-
- setf.s f126=r0 // M2
- setf.s f127=r0 // M3
- br.ret.sptk.many rp // F
-END(__ia64_init_fpu)
-
-/*
- * Switch execution mode from virtual to physical
- *
- * Inputs:
- * r16 = new psr to establish
- * Output:
- * r19 = old virtual address of ar.bsp
- * r20 = old virtual address of sp
- *
- * Note: RSE must already be in enforced lazy mode
- */
-GLOBAL_ENTRY(ia64_switch_mode_phys)
- {
- rsm psr.i | psr.ic // disable interrupts and interrupt collection
- mov r15=ip
- }
- ;;
- {
- flushrs // must be first insn in group
- srlz.i
- }
- ;;
- mov cr.ipsr=r16 // set new PSR
- add r3=1f-ia64_switch_mode_phys,r15
-
- mov r19=ar.bsp
- mov r20=sp
- mov r14=rp // get return address into a general register
- ;;
-
- // going to physical mode, use tpa to translate virt->phys
- tpa r17=r19
- tpa r3=r3
- tpa sp=sp
- tpa r14=r14
- ;;
-
- mov r18=ar.rnat // save ar.rnat
- mov ar.bspstore=r17 // this steps on ar.rnat
- mov cr.iip=r3
- mov cr.ifs=r0
- ;;
- mov ar.rnat=r18 // restore ar.rnat
- rfi // must be last insn in group
- ;;
-1: mov rp=r14
- br.ret.sptk.many rp
-END(ia64_switch_mode_phys)
-
-/*
- * Switch execution mode from physical to virtual
- *
- * Inputs:
- * r16 = new psr to establish
- * r19 = new bspstore to establish
- * r20 = new sp to establish
- *
- * Note: RSE must already be in enforced lazy mode
- */
-GLOBAL_ENTRY(ia64_switch_mode_virt)
- {
- rsm psr.i | psr.ic // disable interrupts and interrupt collection
- mov r15=ip
- }
- ;;
- {
- flushrs // must be first insn in group
- srlz.i
- }
- ;;
- mov cr.ipsr=r16 // set new PSR
- add r3=1f-ia64_switch_mode_virt,r15
-
- mov r14=rp // get return address into a general register
- ;;
-
- // going to virtual
- // - for code addresses, set upper bits of addr to KERNEL_START
- // - for stack addresses, copy from input argument
- movl r18=KERNEL_START
- dep r3=0,r3,KERNEL_TR_PAGE_SHIFT,64-KERNEL_TR_PAGE_SHIFT
- dep r14=0,r14,KERNEL_TR_PAGE_SHIFT,64-KERNEL_TR_PAGE_SHIFT
- mov sp=r20
- ;;
- or r3=r3,r18
- or r14=r14,r18
- ;;
-
- mov r18=ar.rnat // save ar.rnat
- mov ar.bspstore=r19 // this steps on ar.rnat
- mov cr.iip=r3
- mov cr.ifs=r0
- ;;
- mov ar.rnat=r18 // restore ar.rnat
- rfi // must be last insn in group
- ;;
-1: mov rp=r14
- br.ret.sptk.many rp
-END(ia64_switch_mode_virt)
-
-GLOBAL_ENTRY(ia64_delay_loop)
- .prologue
-{ nop 0 // work around GAS unwind info generation bug...
- .save ar.lc,r2
- mov r2=ar.lc
- .body
- ;;
- mov ar.lc=r32
-}
- ;;
- // force loop to be 32-byte aligned (GAS bug means we cannot use .align
- // inside function body without corrupting unwind info).
-{ nop 0 }
-1: br.cloop.sptk.few 1b
- ;;
- mov ar.lc=r2
- br.ret.sptk.many rp
-END(ia64_delay_loop)
-
-/*
- * Return a CPU-local timestamp in nano-seconds. This timestamp is
- * NOT synchronized across CPUs its return value must never be
- * compared against the values returned on another CPU. The usage in
- * kernel/sched/core.c ensures that.
- *
- * The return-value of sched_clock() is NOT supposed to wrap-around.
- * If it did, it would cause some scheduling hiccups (at the worst).
- * Fortunately, with a 64-bit cycle-counter ticking at 100GHz, even
- * that would happen only once every 5+ years.
- *
- * The code below basically calculates:
- *
- * (ia64_get_itc() * local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT
- *
- * except that the multiplication and the shift are done with 128-bit
- * intermediate precision so that we can produce a full 64-bit result.
- */
-GLOBAL_ENTRY(ia64_native_sched_clock)
- addl r8=THIS_CPU(ia64_cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0
- mov.m r9=ar.itc // fetch cycle-counter (35 cyc)
- ;;
- ldf8 f8=[r8]
- ;;
- setf.sig f9=r9 // certain to stall, so issue it _after_ ldf8...
- ;;
- xmpy.lu f10=f9,f8 // calculate low 64 bits of 128-bit product (4 cyc)
- xmpy.hu f11=f9,f8 // calculate high 64 bits of 128-bit product
- ;;
- getf.sig r8=f10 // (5 cyc)
- getf.sig r9=f11
- ;;
- shrp r8=r9,r8,IA64_NSEC_PER_CYC_SHIFT
- br.ret.sptk.many rp
-END(ia64_native_sched_clock)
-
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
-GLOBAL_ENTRY(cycle_to_nsec)
- alloc r16=ar.pfs,1,0,0,0
- addl r8=THIS_CPU(ia64_cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0
- ;;
- ldf8 f8=[r8]
- ;;
- setf.sig f9=r32
- ;;
- xmpy.lu f10=f9,f8 // calculate low 64 bits of 128-bit product (4 cyc)
- xmpy.hu f11=f9,f8 // calculate high 64 bits of 128-bit product
- ;;
- getf.sig r8=f10 // (5 cyc)
- getf.sig r9=f11
- ;;
- shrp r8=r9,r8,IA64_NSEC_PER_CYC_SHIFT
- br.ret.sptk.many rp
-END(cycle_to_nsec)
-#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
-
-#ifdef CONFIG_IA64_BRL_EMU
-
-/*
- * Assembly routines used by brl_emu.c to set preserved register state.
- */
-
-#define SET_REG(reg) \
- GLOBAL_ENTRY(ia64_set_##reg); \
- alloc r16=ar.pfs,1,0,0,0; \
- mov reg=r32; \
- ;; \
- br.ret.sptk.many rp; \
- END(ia64_set_##reg)
-
-SET_REG(b1);
-SET_REG(b2);
-SET_REG(b3);
-SET_REG(b4);
-SET_REG(b5);
-
-#endif /* CONFIG_IA64_BRL_EMU */
-
-#ifdef CONFIG_SMP
-
-#ifdef CONFIG_HOTPLUG_CPU
-GLOBAL_ENTRY(ia64_jump_to_sal)
- alloc r16=ar.pfs,1,0,0,0;;
- rsm psr.i | psr.ic
-{
- flushrs
- srlz.i
-}
- tpa r25=in0
- movl r18=tlb_purge_done;;
- DATA_VA_TO_PA(r18);;
- mov b1=r18 // Return location
- movl r18=ia64_do_tlb_purge;;
- DATA_VA_TO_PA(r18);;
- mov b2=r18 // doing tlb_flush work
- mov ar.rsc=0 // Put RSE in enforced lazy, LE mode
- movl r17=1f;;
- DATA_VA_TO_PA(r17);;
- mov cr.iip=r17
- movl r16=SAL_PSR_BITS_TO_SET;;
- mov cr.ipsr=r16
- mov cr.ifs=r0;;
- rfi;; // note: this unmask MCA/INIT (psr.mc)
-1:
- /*
- * Invalidate all TLB data/inst
- */
- br.sptk.many b2;; // jump to tlb purge code
-
-tlb_purge_done:
- RESTORE_REGION_REGS(r25, r17,r18,r19);;
- RESTORE_REG(b0, r25, r17);;
- RESTORE_REG(b1, r25, r17);;
- RESTORE_REG(b2, r25, r17);;
- RESTORE_REG(b3, r25, r17);;
- RESTORE_REG(b4, r25, r17);;
- RESTORE_REG(b5, r25, r17);;
- ld8 r1=[r25],0x08;;
- ld8 r12=[r25],0x08;;
- ld8 r13=[r25],0x08;;
- RESTORE_REG(ar.fpsr, r25, r17);;
- RESTORE_REG(ar.pfs, r25, r17);;
- RESTORE_REG(ar.rnat, r25, r17);;
- RESTORE_REG(ar.unat, r25, r17);;
- RESTORE_REG(ar.bspstore, r25, r17);;
- RESTORE_REG(cr.dcr, r25, r17);;
- RESTORE_REG(cr.iva, r25, r17);;
- RESTORE_REG(cr.pta, r25, r17);;
- srlz.d;; // required not to violate RAW dependency
- RESTORE_REG(cr.itv, r25, r17);;
- RESTORE_REG(cr.pmv, r25, r17);;
- RESTORE_REG(cr.cmcv, r25, r17);;
- RESTORE_REG(cr.lrr0, r25, r17);;
- RESTORE_REG(cr.lrr1, r25, r17);;
- ld8 r4=[r25],0x08;;
- ld8 r5=[r25],0x08;;
- ld8 r6=[r25],0x08;;
- ld8 r7=[r25],0x08;;
- ld8 r17=[r25],0x08;;
- mov pr=r17,-1;;
- RESTORE_REG(ar.lc, r25, r17);;
- /*
- * Now Restore floating point regs
- */
- ldf.fill.nta f2=[r25],16;;
- ldf.fill.nta f3=[r25],16;;
- ldf.fill.nta f4=[r25],16;;
- ldf.fill.nta f5=[r25],16;;
- ldf.fill.nta f16=[r25],16;;
- ldf.fill.nta f17=[r25],16;;
- ldf.fill.nta f18=[r25],16;;
- ldf.fill.nta f19=[r25],16;;
- ldf.fill.nta f20=[r25],16;;
- ldf.fill.nta f21=[r25],16;;
- ldf.fill.nta f22=[r25],16;;
- ldf.fill.nta f23=[r25],16;;
- ldf.fill.nta f24=[r25],16;;
- ldf.fill.nta f25=[r25],16;;
- ldf.fill.nta f26=[r25],16;;
- ldf.fill.nta f27=[r25],16;;
- ldf.fill.nta f28=[r25],16;;
- ldf.fill.nta f29=[r25],16;;
- ldf.fill.nta f30=[r25],16;;
- ldf.fill.nta f31=[r25],16;;
-
- /*
- * Now that we have done all the register restores
- * we are now ready for the big DIVE to SAL Land
- */
- ssm psr.ic;;
- srlz.d;;
- br.ret.sptk.many b0;;
-END(ia64_jump_to_sal)
-#endif /* CONFIG_HOTPLUG_CPU */
-
-#endif /* CONFIG_SMP */
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
deleted file mode 100644
index 99300850abc1..000000000000
--- a/arch/ia64/kernel/iosapic.c
+++ /dev/null
@@ -1,1137 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * I/O SAPIC support.
- *
- * Copyright (C) 1999 Intel Corp.
- * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * Copyright (C) 2000-2002 J.I. Lee <jung-ik.lee@intel.com>
- * Copyright (C) 1999-2000, 2002-2003 Hewlett-Packard Co.
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
- *
- * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O
- * APIC code. In particular, we now have separate
- * handlers for edge and level triggered
- * interrupts.
- * 00/10/27 Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector
- * allocation PCI to vector mapping, shared PCI
- * interrupts.
- * 00/10/27 D. Mosberger Document things a bit more to make them more
- * understandable. Clean up much of the old
- * IOSAPIC cruft.
- * 01/07/27 J.I. Lee PCI irq routing, Platform/Legacy interrupts
- * and fixes for ACPI S5(SoftOff) support.
- * 02/01/23 J.I. Lee iosapic pgm fixes for PCI irq routing from _PRT
- * 02/01/07 E. Focht <efocht@ess.nec.de> Redirectable interrupt
- * vectors in iosapic_set_affinity(),
- * initializations for /proc/irq/#/smp_affinity
- * 02/04/02 P. Diefenbaugh Cleaned up ACPI PCI IRQ routing.
- * 02/04/18 J.I. Lee bug fix in iosapic_init_pci_irq
- * 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to
- * IOSAPIC mapping error
- * 02/07/29 T. Kochi Allocate interrupt vectors dynamically
- * 02/08/04 T. Kochi Cleaned up terminology (irq, global system
- * interrupt, vector, etc.)
- * 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's
- * pci_irq code.
- * 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC.
- * Remove iosapic_address & gsi_base from
- * external interfaces. Rationalize
- * __init/__devinit attributes.
- * 04/12/04 Ashok Raj <ashok.raj@intel.com> Intel Corporation 2004
- * Updated to work with irq migration necessary
- * for CPU Hotplug
- */
-/*
- * Here is what the interrupt logic between a PCI device and the kernel looks
- * like:
- *
- * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC,
- * INTD). The device is uniquely identified by its bus-, and slot-number
- * (the function number does not matter here because all functions share
- * the same interrupt lines).
- *
- * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC
- * controller. Multiple interrupt lines may have to share the same
- * IOSAPIC pin (if they're level triggered and use the same polarity).
- * Each interrupt line has a unique Global System Interrupt (GSI) number
- * which can be calculated as the sum of the controller's base GSI number
- * and the IOSAPIC pin number to which the line connects.
- *
- * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the
- * IOSAPIC pin into the IA-64 interrupt vector. This interrupt vector is then
- * sent to the CPU.
- *
- * (4) The kernel recognizes an interrupt as an IRQ. The IRQ interface is
- * used as architecture-independent interrupt handling mechanism in Linux.
- * As an IRQ is a number, we have to have
- * IA-64 interrupt vector number <-> IRQ number mapping. On smaller
- * systems, we use one-to-one mapping between IA-64 vector and IRQ.
- *
- * To sum up, there are three levels of mappings involved:
- *
- * PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ
- *
- * Note: The term "IRQ" is loosely used everywhere in Linux kernel to
- * describe interrupts. Now we use "IRQ" only for Linux IRQ's. ISA IRQ
- * (isa_irq) is the only exception in this source code.
- */
-
-#include <linux/acpi.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/smp.h>
-#include <linux/string.h>
-#include <linux/memblock.h>
-
-#include <asm/delay.h>
-#include <asm/hw_irq.h>
-#include <asm/io.h>
-#include <asm/iosapic.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/xtp.h>
-
-#undef DEBUG_INTERRUPT_ROUTING
-
-#ifdef DEBUG_INTERRUPT_ROUTING
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG(fmt...)
-#endif
-
-static DEFINE_SPINLOCK(iosapic_lock);
-
-/*
- * These tables map IA-64 vectors to the IOSAPIC pin that generates this
- * vector.
- */
-
-#define NO_REF_RTE 0
-
-static struct iosapic {
- char __iomem *addr; /* base address of IOSAPIC */
- unsigned int gsi_base; /* GSI base */
- unsigned short num_rte; /* # of RTEs on this IOSAPIC */
- int rtes_inuse; /* # of RTEs in use on this IOSAPIC */
-#ifdef CONFIG_NUMA
- unsigned short node; /* numa node association via pxm */
-#endif
- spinlock_t lock; /* lock for indirect reg access */
-} iosapic_lists[NR_IOSAPICS];
-
-struct iosapic_rte_info {
- struct list_head rte_list; /* RTEs sharing the same vector */
- char rte_index; /* IOSAPIC RTE index */
- int refcnt; /* reference counter */
- struct iosapic *iosapic;
-} ____cacheline_aligned;
-
-static struct iosapic_intr_info {
- struct list_head rtes; /* RTEs using this vector (empty =>
- * not an IOSAPIC interrupt) */
- int count; /* # of registered RTEs */
- u32 low32; /* current value of low word of
- * Redirection table entry */
- unsigned int dest; /* destination CPU physical ID */
- unsigned char dmode : 3; /* delivery mode (see iosapic.h) */
- unsigned char polarity: 1; /* interrupt polarity
- * (see iosapic.h) */
- unsigned char trigger : 1; /* trigger mode (see iosapic.h) */
-} iosapic_intr_info[NR_IRQS];
-
-static unsigned char pcat_compat; /* 8259 compatibility flag */
-
-static inline void
-iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&iosapic->lock, flags);
- __iosapic_write(iosapic->addr, reg, val);
- spin_unlock_irqrestore(&iosapic->lock, flags);
-}
-
-/*
- * Find an IOSAPIC associated with a GSI
- */
-static inline int
-find_iosapic (unsigned int gsi)
-{
- int i;
-
- for (i = 0; i < NR_IOSAPICS; i++) {
- if ((unsigned) (gsi - iosapic_lists[i].gsi_base) <
- iosapic_lists[i].num_rte)
- return i;
- }
-
- return -1;
-}
-
-static inline int __gsi_to_irq(unsigned int gsi)
-{
- int irq;
- struct iosapic_intr_info *info;
- struct iosapic_rte_info *rte;
-
- for (irq = 0; irq < NR_IRQS; irq++) {
- info = &iosapic_intr_info[irq];
- list_for_each_entry(rte, &info->rtes, rte_list)
- if (rte->iosapic->gsi_base + rte->rte_index == gsi)
- return irq;
- }
- return -1;
-}
-
-int
-gsi_to_irq (unsigned int gsi)
-{
- unsigned long flags;
- int irq;
-
- spin_lock_irqsave(&iosapic_lock, flags);
- irq = __gsi_to_irq(gsi);
- spin_unlock_irqrestore(&iosapic_lock, flags);
- return irq;
-}
-
-static struct iosapic_rte_info *find_rte(unsigned int irq, unsigned int gsi)
-{
- struct iosapic_rte_info *rte;
-
- list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
- if (rte->iosapic->gsi_base + rte->rte_index == gsi)
- return rte;
- return NULL;
-}
-
-static void
-set_rte (unsigned int gsi, unsigned int irq, unsigned int dest, int mask)
-{
- unsigned long pol, trigger, dmode;
- u32 low32, high32;
- int rte_index;
- char redir;
- struct iosapic_rte_info *rte;
- ia64_vector vector = irq_to_vector(irq);
-
- DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
-
- rte = find_rte(irq, gsi);
- if (!rte)
- return; /* not an IOSAPIC interrupt */
-
- rte_index = rte->rte_index;
- pol = iosapic_intr_info[irq].polarity;
- trigger = iosapic_intr_info[irq].trigger;
- dmode = iosapic_intr_info[irq].dmode;
-
- redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0;
-
-#ifdef CONFIG_SMP
- set_irq_affinity_info(irq, (int)(dest & 0xffff), redir);
-#endif
-
- low32 = ((pol << IOSAPIC_POLARITY_SHIFT) |
- (trigger << IOSAPIC_TRIGGER_SHIFT) |
- (dmode << IOSAPIC_DELIVERY_SHIFT) |
- ((mask ? 1 : 0) << IOSAPIC_MASK_SHIFT) |
- vector);
-
- /* dest contains both id and eid */
- high32 = (dest << IOSAPIC_DEST_SHIFT);
-
- iosapic_write(rte->iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
- iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
- iosapic_intr_info[irq].low32 = low32;
- iosapic_intr_info[irq].dest = dest;
-}
-
-static void
-iosapic_nop (struct irq_data *data)
-{
- /* do nothing... */
-}
-
-
-#ifdef CONFIG_KEXEC
-void
-kexec_disable_iosapic(void)
-{
- struct iosapic_intr_info *info;
- struct iosapic_rte_info *rte;
- ia64_vector vec;
- int irq;
-
- for (irq = 0; irq < NR_IRQS; irq++) {
- info = &iosapic_intr_info[irq];
- vec = irq_to_vector(irq);
- list_for_each_entry(rte, &info->rtes,
- rte_list) {
- iosapic_write(rte->iosapic,
- IOSAPIC_RTE_LOW(rte->rte_index),
- IOSAPIC_MASK|vec);
- iosapic_eoi(rte->iosapic->addr, vec);
- }
- }
-}
-#endif
-
-static void
-mask_irq (struct irq_data *data)
-{
- unsigned int irq = data->irq;
- u32 low32;
- int rte_index;
- struct iosapic_rte_info *rte;
-
- if (!iosapic_intr_info[irq].count)
- return; /* not an IOSAPIC interrupt! */
-
- /* set only the mask bit */
- low32 = iosapic_intr_info[irq].low32 |= IOSAPIC_MASK;
- list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) {
- rte_index = rte->rte_index;
- iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
- }
-}
-
-static void
-unmask_irq (struct irq_data *data)
-{
- unsigned int irq = data->irq;
- u32 low32;
- int rte_index;
- struct iosapic_rte_info *rte;
-
- if (!iosapic_intr_info[irq].count)
- return; /* not an IOSAPIC interrupt! */
-
- low32 = iosapic_intr_info[irq].low32 &= ~IOSAPIC_MASK;
- list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) {
- rte_index = rte->rte_index;
- iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
- }
-}
-
-
-static int
-iosapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
- bool force)
-{
-#ifdef CONFIG_SMP
- unsigned int irq = data->irq;
- u32 high32, low32;
- int cpu, dest, rte_index;
- int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
- struct iosapic_rte_info *rte;
- struct iosapic *iosapic;
-
- irq &= (~IA64_IRQ_REDIRECTED);
-
- cpu = cpumask_first_and(cpu_online_mask, mask);
- if (cpu >= nr_cpu_ids)
- return -1;
-
- if (irq_prepare_move(irq, cpu))
- return -1;
-
- dest = cpu_physical_id(cpu);
-
- if (!iosapic_intr_info[irq].count)
- return -1; /* not an IOSAPIC interrupt */
-
- set_irq_affinity_info(irq, dest, redir);
-
- /* dest contains both id and eid */
- high32 = dest << IOSAPIC_DEST_SHIFT;
-
- low32 = iosapic_intr_info[irq].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT);
- if (redir)
- /* change delivery mode to lowest priority */
- low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
- else
- /* change delivery mode to fixed */
- low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
- low32 &= IOSAPIC_VECTOR_MASK;
- low32 |= irq_to_vector(irq);
-
- iosapic_intr_info[irq].low32 = low32;
- iosapic_intr_info[irq].dest = dest;
- list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) {
- iosapic = rte->iosapic;
- rte_index = rte->rte_index;
- iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
- iosapic_write(iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
- }
-
-#endif
- return 0;
-}
-
-/*
- * Handlers for level-triggered interrupts.
- */
-
-static unsigned int
-iosapic_startup_level_irq (struct irq_data *data)
-{
- unmask_irq(data);
- return 0;
-}
-
-static void
-iosapic_unmask_level_irq (struct irq_data *data)
-{
- unsigned int irq = data->irq;
- ia64_vector vec = irq_to_vector(irq);
- struct iosapic_rte_info *rte;
- int do_unmask_irq = 0;
-
- irq_complete_move(irq);
- if (unlikely(irqd_is_setaffinity_pending(data))) {
- do_unmask_irq = 1;
- mask_irq(data);
- } else
- unmask_irq(data);
-
- list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
- iosapic_eoi(rte->iosapic->addr, vec);
-
- if (unlikely(do_unmask_irq)) {
- irq_move_masked_irq(data);
- unmask_irq(data);
- }
-}
-
-#define iosapic_shutdown_level_irq mask_irq
-#define iosapic_enable_level_irq unmask_irq
-#define iosapic_disable_level_irq mask_irq
-#define iosapic_ack_level_irq iosapic_nop
-
-static struct irq_chip irq_type_iosapic_level = {
- .name = "IO-SAPIC-level",
- .irq_startup = iosapic_startup_level_irq,
- .irq_shutdown = iosapic_shutdown_level_irq,
- .irq_enable = iosapic_enable_level_irq,
- .irq_disable = iosapic_disable_level_irq,
- .irq_ack = iosapic_ack_level_irq,
- .irq_mask = mask_irq,
- .irq_unmask = iosapic_unmask_level_irq,
- .irq_set_affinity = iosapic_set_affinity
-};
-
-/*
- * Handlers for edge-triggered interrupts.
- */
-
-static unsigned int
-iosapic_startup_edge_irq (struct irq_data *data)
-{
- unmask_irq(data);
- /*
- * IOSAPIC simply drops interrupts pended while the
- * corresponding pin was masked, so we can't know if an
- * interrupt is pending already. Let's hope not...
- */
- return 0;
-}
-
-static void
-iosapic_ack_edge_irq (struct irq_data *data)
-{
- irq_complete_move(data->irq);
- irq_move_irq(data);
-}
-
-#define iosapic_enable_edge_irq unmask_irq
-#define iosapic_disable_edge_irq iosapic_nop
-
-static struct irq_chip irq_type_iosapic_edge = {
- .name = "IO-SAPIC-edge",
- .irq_startup = iosapic_startup_edge_irq,
- .irq_shutdown = iosapic_disable_edge_irq,
- .irq_enable = iosapic_enable_edge_irq,
- .irq_disable = iosapic_disable_edge_irq,
- .irq_ack = iosapic_ack_edge_irq,
- .irq_mask = mask_irq,
- .irq_unmask = unmask_irq,
- .irq_set_affinity = iosapic_set_affinity
-};
-
-static unsigned int
-iosapic_version (char __iomem *addr)
-{
- /*
- * IOSAPIC Version Register return 32 bit structure like:
- * {
- * unsigned int version : 8;
- * unsigned int reserved1 : 8;
- * unsigned int max_redir : 8;
- * unsigned int reserved2 : 8;
- * }
- */
- return __iosapic_read(addr, IOSAPIC_VERSION);
-}
-
-static int iosapic_find_sharable_irq(unsigned long trigger, unsigned long pol)
-{
- int i, irq = -ENOSPC, min_count = -1;
- struct iosapic_intr_info *info;
-
- /*
- * shared vectors for edge-triggered interrupts are not
- * supported yet
- */
- if (trigger == IOSAPIC_EDGE)
- return -EINVAL;
-
- for (i = 0; i < NR_IRQS; i++) {
- info = &iosapic_intr_info[i];
- if (info->trigger == trigger && info->polarity == pol &&
- (info->dmode == IOSAPIC_FIXED ||
- info->dmode == IOSAPIC_LOWEST_PRIORITY) &&
- can_request_irq(i, IRQF_SHARED)) {
- if (min_count == -1 || info->count < min_count) {
- irq = i;
- min_count = info->count;
- }
- }
- }
- return irq;
-}
-
-/*
- * if the given vector is already owned by other,
- * assign a new vector for the other and make the vector available
- */
-static void __init
-iosapic_reassign_vector (int irq)
-{
- int new_irq;
-
- if (iosapic_intr_info[irq].count) {
- new_irq = create_irq();
- if (new_irq < 0)
- panic("%s: out of interrupt vectors!\n", __func__);
- printk(KERN_INFO "Reassigning vector %d to %d\n",
- irq_to_vector(irq), irq_to_vector(new_irq));
- memcpy(&iosapic_intr_info[new_irq], &iosapic_intr_info[irq],
- sizeof(struct iosapic_intr_info));
- INIT_LIST_HEAD(&iosapic_intr_info[new_irq].rtes);
- list_move(iosapic_intr_info[irq].rtes.next,
- &iosapic_intr_info[new_irq].rtes);
- memset(&iosapic_intr_info[irq], 0,
- sizeof(struct iosapic_intr_info));
- iosapic_intr_info[irq].low32 = IOSAPIC_MASK;
- INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
- }
-}
-
-static inline int irq_is_shared (int irq)
-{
- return (iosapic_intr_info[irq].count > 1);
-}
-
-struct irq_chip*
-ia64_native_iosapic_get_irq_chip(unsigned long trigger)
-{
- if (trigger == IOSAPIC_EDGE)
- return &irq_type_iosapic_edge;
- else
- return &irq_type_iosapic_level;
-}
-
-static int
-register_intr (unsigned int gsi, int irq, unsigned char delivery,
- unsigned long polarity, unsigned long trigger)
-{
- struct irq_chip *chip, *irq_type;
- int index;
- struct iosapic_rte_info *rte;
-
- index = find_iosapic(gsi);
- if (index < 0) {
- printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",
- __func__, gsi);
- return -ENODEV;
- }
-
- rte = find_rte(irq, gsi);
- if (!rte) {
- rte = kzalloc(sizeof (*rte), GFP_ATOMIC);
- if (!rte) {
- printk(KERN_WARNING "%s: cannot allocate memory\n",
- __func__);
- return -ENOMEM;
- }
-
- rte->iosapic = &iosapic_lists[index];
- rte->rte_index = gsi - rte->iosapic->gsi_base;
- rte->refcnt++;
- list_add_tail(&rte->rte_list, &iosapic_intr_info[irq].rtes);
- iosapic_intr_info[irq].count++;
- iosapic_lists[index].rtes_inuse++;
- }
- else if (rte->refcnt == NO_REF_RTE) {
- struct iosapic_intr_info *info = &iosapic_intr_info[irq];
- if (info->count > 0 &&
- (info->trigger != trigger || info->polarity != polarity)){
- printk (KERN_WARNING
- "%s: cannot override the interrupt\n",
- __func__);
- return -EINVAL;
- }
- rte->refcnt++;
- iosapic_intr_info[irq].count++;
- iosapic_lists[index].rtes_inuse++;
- }
-
- iosapic_intr_info[irq].polarity = polarity;
- iosapic_intr_info[irq].dmode = delivery;
- iosapic_intr_info[irq].trigger = trigger;
-
- irq_type = iosapic_get_irq_chip(trigger);
-
- chip = irq_get_chip(irq);
- if (irq_type != NULL && chip != irq_type) {
- if (chip != &no_irq_chip)
- printk(KERN_WARNING
- "%s: changing vector %d from %s to %s\n",
- __func__, irq_to_vector(irq),
- chip->name, irq_type->name);
- chip = irq_type;
- }
- irq_set_chip_handler_name_locked(irq_get_irq_data(irq), chip,
- trigger == IOSAPIC_EDGE ? handle_edge_irq : handle_level_irq,
- NULL);
- return 0;
-}
-
-static unsigned int
-get_target_cpu (unsigned int gsi, int irq)
-{
-#ifdef CONFIG_SMP
- static int cpu = -1;
- extern int cpe_vector;
- cpumask_t domain = irq_to_domain(irq);
-
- /*
- * In case of vector shared by multiple RTEs, all RTEs that
- * share the vector need to use the same destination CPU.
- */
- if (iosapic_intr_info[irq].count)
- return iosapic_intr_info[irq].dest;
-
- /*
- * If the platform supports redirection via XTP, let it
- * distribute interrupts.
- */
- if (smp_int_redirect & SMP_IRQ_REDIRECTION)
- return cpu_physical_id(smp_processor_id());
-
- /*
- * Some interrupts (ACPI SCI, for instance) are registered
- * before the BSP is marked as online.
- */
- if (!cpu_online(smp_processor_id()))
- return cpu_physical_id(smp_processor_id());
-
- if (cpe_vector > 0 && irq_to_vector(irq) == IA64_CPEP_VECTOR)
- return get_cpei_target_cpu();
-
-#ifdef CONFIG_NUMA
- {
- int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0;
- const struct cpumask *cpu_mask;
-
- iosapic_index = find_iosapic(gsi);
- if (iosapic_index < 0 ||
- iosapic_lists[iosapic_index].node == MAX_NUMNODES)
- goto skip_numa_setup;
-
- cpu_mask = cpumask_of_node(iosapic_lists[iosapic_index].node);
- num_cpus = 0;
- for_each_cpu_and(numa_cpu, cpu_mask, &domain) {
- if (cpu_online(numa_cpu))
- num_cpus++;
- }
-
- if (!num_cpus)
- goto skip_numa_setup;
-
- /* Use irq assignment to distribute across cpus in node */
- cpu_index = irq % num_cpus;
-
- for_each_cpu_and(numa_cpu, cpu_mask, &domain)
- if (cpu_online(numa_cpu) && i++ >= cpu_index)
- break;
-
- if (numa_cpu < nr_cpu_ids)
- return cpu_physical_id(numa_cpu);
- }
-skip_numa_setup:
-#endif
- /*
- * Otherwise, round-robin interrupt vectors across all the
- * processors. (It'd be nice if we could be smarter in the
- * case of NUMA.)
- */
- do {
- if (++cpu >= nr_cpu_ids)
- cpu = 0;
- } while (!cpu_online(cpu) || !cpumask_test_cpu(cpu, &domain));
-
- return cpu_physical_id(cpu);
-#else /* CONFIG_SMP */
- return cpu_physical_id(smp_processor_id());
-#endif
-}
-
-static inline unsigned char choose_dmode(void)
-{
-#ifdef CONFIG_SMP
- if (smp_int_redirect & SMP_IRQ_REDIRECTION)
- return IOSAPIC_LOWEST_PRIORITY;
-#endif
- return IOSAPIC_FIXED;
-}
-
-/*
- * ACPI can describe IOSAPIC interrupts via static tables and namespace
- * methods. This provides an interface to register those interrupts and
- * program the IOSAPIC RTE.
- */
-int
-iosapic_register_intr (unsigned int gsi,
- unsigned long polarity, unsigned long trigger)
-{
- int irq, mask = 1, err;
- unsigned int dest;
- unsigned long flags;
- struct iosapic_rte_info *rte;
- u32 low32;
- unsigned char dmode;
- struct irq_desc *desc;
-
- /*
- * If this GSI has already been registered (i.e., it's a
- * shared interrupt, or we lost a race to register it),
- * don't touch the RTE.
- */
- spin_lock_irqsave(&iosapic_lock, flags);
- irq = __gsi_to_irq(gsi);
- if (irq > 0) {
- rte = find_rte(irq, gsi);
- if(iosapic_intr_info[irq].count == 0) {
- assign_irq_vector(irq);
- irq_init_desc(irq);
- } else if (rte->refcnt != NO_REF_RTE) {
- rte->refcnt++;
- goto unlock_iosapic_lock;
- }
- } else
- irq = create_irq();
-
- /* If vector is running out, we try to find a sharable vector */
- if (irq < 0) {
- irq = iosapic_find_sharable_irq(trigger, polarity);
- if (irq < 0)
- goto unlock_iosapic_lock;
- }
-
- desc = irq_to_desc(irq);
- raw_spin_lock(&desc->lock);
- dest = get_target_cpu(gsi, irq);
- dmode = choose_dmode();
- err = register_intr(gsi, irq, dmode, polarity, trigger);
- if (err < 0) {
- raw_spin_unlock(&desc->lock);
- irq = err;
- goto unlock_iosapic_lock;
- }
-
- /*
- * If the vector is shared and already unmasked for other
- * interrupt sources, don't mask it.
- */
- low32 = iosapic_intr_info[irq].low32;
- if (irq_is_shared(irq) && !(low32 & IOSAPIC_MASK))
- mask = 0;
- set_rte(gsi, irq, dest, mask);
-
- printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
- gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
- (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
- cpu_logical_id(dest), dest, irq_to_vector(irq));
-
- raw_spin_unlock(&desc->lock);
- unlock_iosapic_lock:
- spin_unlock_irqrestore(&iosapic_lock, flags);
- return irq;
-}
-
-void
-iosapic_unregister_intr (unsigned int gsi)
-{
- unsigned long flags;
- int irq, index;
- u32 low32;
- unsigned long trigger, polarity;
- unsigned int dest;
- struct iosapic_rte_info *rte;
-
- /*
- * If the irq associated with the gsi is not found,
- * iosapic_unregister_intr() is unbalanced. We need to check
- * this again after getting locks.
- */
- irq = gsi_to_irq(gsi);
- if (irq < 0) {
- printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n",
- gsi);
- WARN_ON(1);
- return;
- }
-
- spin_lock_irqsave(&iosapic_lock, flags);
- if ((rte = find_rte(irq, gsi)) == NULL) {
- printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n",
- gsi);
- WARN_ON(1);
- goto out;
- }
-
- if (--rte->refcnt > 0)
- goto out;
-
- rte->refcnt = NO_REF_RTE;
-
- /* Mask the interrupt */
- low32 = iosapic_intr_info[irq].low32 | IOSAPIC_MASK;
- iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32);
-
- iosapic_intr_info[irq].count--;
- index = find_iosapic(gsi);
- iosapic_lists[index].rtes_inuse--;
- WARN_ON(iosapic_lists[index].rtes_inuse < 0);
-
- trigger = iosapic_intr_info[irq].trigger;
- polarity = iosapic_intr_info[irq].polarity;
- dest = iosapic_intr_info[irq].dest;
- printk(KERN_INFO
- "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n",
- gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
- (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
- cpu_logical_id(dest), dest, irq_to_vector(irq));
-
- if (iosapic_intr_info[irq].count == 0) {
-#ifdef CONFIG_SMP
- /* Clear affinity */
- irq_data_update_affinity(irq_get_irq_data(irq), cpu_all_mask);
-#endif
- /* Clear the interrupt information */
- iosapic_intr_info[irq].dest = 0;
- iosapic_intr_info[irq].dmode = 0;
- iosapic_intr_info[irq].polarity = 0;
- iosapic_intr_info[irq].trigger = 0;
- iosapic_intr_info[irq].low32 |= IOSAPIC_MASK;
-
- /* Destroy and reserve IRQ */
- destroy_and_reserve_irq(irq);
- }
- out:
- spin_unlock_irqrestore(&iosapic_lock, flags);
-}
-
-/*
- * ACPI calls this when it finds an entry for a platform interrupt.
- */
-int __init
-iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
- int iosapic_vector, u16 eid, u16 id,
- unsigned long polarity, unsigned long trigger)
-{
- static const char * const name[] = {"unknown", "PMI", "INIT", "CPEI"};
- unsigned char delivery;
- int irq, vector, mask = 0;
- unsigned int dest = ((id << 8) | eid) & 0xffff;
-
- switch (int_type) {
- case ACPI_INTERRUPT_PMI:
- irq = vector = iosapic_vector;
- bind_irq_vector(irq, vector, CPU_MASK_ALL);
- /*
- * since PMI vector is alloc'd by FW(ACPI) not by kernel,
- * we need to make sure the vector is available
- */
- iosapic_reassign_vector(irq);
- delivery = IOSAPIC_PMI;
- break;
- case ACPI_INTERRUPT_INIT:
- irq = create_irq();
- if (irq < 0)
- panic("%s: out of interrupt vectors!\n", __func__);
- vector = irq_to_vector(irq);
- delivery = IOSAPIC_INIT;
- break;
- case ACPI_INTERRUPT_CPEI:
- irq = vector = IA64_CPE_VECTOR;
- BUG_ON(bind_irq_vector(irq, vector, CPU_MASK_ALL));
- delivery = IOSAPIC_FIXED;
- mask = 1;
- break;
- default:
- printk(KERN_ERR "%s: invalid int type 0x%x\n", __func__,
- int_type);
- return -1;
- }
-
- register_intr(gsi, irq, delivery, polarity, trigger);
-
- printk(KERN_INFO
- "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)"
- " vector %d\n",
- int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown",
- int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
- (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
- cpu_logical_id(dest), dest, vector);
-
- set_rte(gsi, irq, dest, mask);
- return vector;
-}
-
-/*
- * ACPI calls this when it finds an entry for a legacy ISA IRQ override.
- */
-void iosapic_override_isa_irq(unsigned int isa_irq, unsigned int gsi,
- unsigned long polarity, unsigned long trigger)
-{
- int vector, irq;
- unsigned int dest = cpu_physical_id(smp_processor_id());
- unsigned char dmode;
-
- irq = vector = isa_irq_to_vector(isa_irq);
- BUG_ON(bind_irq_vector(irq, vector, CPU_MASK_ALL));
- dmode = choose_dmode();
- register_intr(gsi, irq, dmode, polarity, trigger);
-
- DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n",
- isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level",
- polarity == IOSAPIC_POL_HIGH ? "high" : "low",
- cpu_logical_id(dest), dest, vector);
-
- set_rte(gsi, irq, dest, 1);
-}
-
-void __init
-ia64_native_iosapic_pcat_compat_init(void)
-{
- if (pcat_compat) {
- /*
- * Disable the compatibility mode interrupts (8259 style),
- * needs IN/OUT support enabled.
- */
- printk(KERN_INFO
- "%s: Disabling PC-AT compatible 8259 interrupts\n",
- __func__);
- outb(0xff, 0xA1);
- outb(0xff, 0x21);
- }
-}
-
-void __init
-iosapic_system_init (int system_pcat_compat)
-{
- int irq;
-
- for (irq = 0; irq < NR_IRQS; ++irq) {
- iosapic_intr_info[irq].low32 = IOSAPIC_MASK;
- /* mark as unused */
- INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
-
- iosapic_intr_info[irq].count = 0;
- }
-
- pcat_compat = system_pcat_compat;
- if (pcat_compat)
- iosapic_pcat_compat_init();
-}
-
-static inline int
-iosapic_alloc (void)
-{
- int index;
-
- for (index = 0; index < NR_IOSAPICS; index++)
- if (!iosapic_lists[index].addr)
- return index;
-
- printk(KERN_WARNING "%s: failed to allocate iosapic\n", __func__);
- return -1;
-}
-
-static inline void
-iosapic_free (int index)
-{
- memset(&iosapic_lists[index], 0, sizeof(iosapic_lists[0]));
-}
-
-static inline int
-iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver)
-{
- int index;
- unsigned int gsi_end, base, end;
-
- /* check gsi range */
- gsi_end = gsi_base + ((ver >> 16) & 0xff);
- for (index = 0; index < NR_IOSAPICS; index++) {
- if (!iosapic_lists[index].addr)
- continue;
-
- base = iosapic_lists[index].gsi_base;
- end = base + iosapic_lists[index].num_rte - 1;
-
- if (gsi_end < base || end < gsi_base)
- continue; /* OK */
-
- return -EBUSY;
- }
- return 0;
-}
-
-static int
-iosapic_delete_rte(unsigned int irq, unsigned int gsi)
-{
- struct iosapic_rte_info *rte, *temp;
-
- list_for_each_entry_safe(rte, temp, &iosapic_intr_info[irq].rtes,
- rte_list) {
- if (rte->iosapic->gsi_base + rte->rte_index == gsi) {
- if (rte->refcnt)
- return -EBUSY;
-
- list_del(&rte->rte_list);
- kfree(rte);
- return 0;
- }
- }
-
- return -EINVAL;
-}
-
-int iosapic_init(unsigned long phys_addr, unsigned int gsi_base)
-{
- int num_rte, err, index;
- unsigned int isa_irq, ver;
- char __iomem *addr;
- unsigned long flags;
-
- spin_lock_irqsave(&iosapic_lock, flags);
- index = find_iosapic(gsi_base);
- if (index >= 0) {
- spin_unlock_irqrestore(&iosapic_lock, flags);
- return -EBUSY;
- }
-
- addr = ioremap(phys_addr, 0);
- if (addr == NULL) {
- spin_unlock_irqrestore(&iosapic_lock, flags);
- return -ENOMEM;
- }
- ver = iosapic_version(addr);
- if ((err = iosapic_check_gsi_range(gsi_base, ver))) {
- iounmap(addr);
- spin_unlock_irqrestore(&iosapic_lock, flags);
- return err;
- }
-
- /*
- * The MAX_REDIR register holds the highest input pin number
- * (starting from 0). We add 1 so that we can use it for
- * number of pins (= RTEs)
- */
- num_rte = ((ver >> 16) & 0xff) + 1;
-
- index = iosapic_alloc();
- iosapic_lists[index].addr = addr;
- iosapic_lists[index].gsi_base = gsi_base;
- iosapic_lists[index].num_rte = num_rte;
-#ifdef CONFIG_NUMA
- iosapic_lists[index].node = MAX_NUMNODES;
-#endif
- spin_lock_init(&iosapic_lists[index].lock);
- spin_unlock_irqrestore(&iosapic_lock, flags);
-
- if ((gsi_base == 0) && pcat_compat) {
- /*
- * Map the legacy ISA devices into the IOSAPIC data. Some of
- * these may get reprogrammed later on with data from the ACPI
- * Interrupt Source Override table.
- */
- for (isa_irq = 0; isa_irq < 16; ++isa_irq)
- iosapic_override_isa_irq(isa_irq, isa_irq,
- IOSAPIC_POL_HIGH,
- IOSAPIC_EDGE);
- }
- return 0;
-}
-
-int iosapic_remove(unsigned int gsi_base)
-{
- int i, irq, index, err = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&iosapic_lock, flags);
- index = find_iosapic(gsi_base);
- if (index < 0) {
- printk(KERN_WARNING "%s: No IOSAPIC for GSI base %u\n",
- __func__, gsi_base);
- goto out;
- }
-
- if (iosapic_lists[index].rtes_inuse) {
- err = -EBUSY;
- printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n",
- __func__, gsi_base);
- goto out;
- }
-
- for (i = gsi_base; i < gsi_base + iosapic_lists[index].num_rte; i++) {
- irq = __gsi_to_irq(i);
- if (irq < 0)
- continue;
-
- err = iosapic_delete_rte(irq, i);
- if (err)
- goto out;
- }
-
- iounmap(iosapic_lists[index].addr);
- iosapic_free(index);
- out:
- spin_unlock_irqrestore(&iosapic_lock, flags);
- return err;
-}
-
-#ifdef CONFIG_NUMA
-void map_iosapic_to_node(unsigned int gsi_base, int node)
-{
- int index;
-
- index = find_iosapic(gsi_base);
- if (index < 0) {
- printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",
- __func__, gsi_base);
- return;
- }
- iosapic_lists[index].node = node;
- return;
-}
-#endif
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
deleted file mode 100644
index 275b9ea58c64..000000000000
--- a/arch/ia64/kernel/irq.c
+++ /dev/null
@@ -1,181 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * linux/arch/ia64/kernel/irq.c
- *
- * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
- *
- * This file contains the code used by various IRQ handling routines:
- * asking for different IRQs should be done through these routines
- * instead of just grabbing them. Thus setups with different IRQ numbers
- * shouldn't result in any weird surprises, and installing new handlers
- * should be easier.
- *
- * Copyright (C) Ashok Raj<ashok.raj@intel.com>, Intel Corporation 2004
- *
- * 4/14/2004: Added code to handle cpu migration and do safe irq
- * migration without losing interrupts for iosapic
- * architecture.
- */
-
-#include <asm/delay.h>
-#include <linux/uaccess.h>
-#include <linux/module.h>
-#include <linux/seq_file.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-
-#include <asm/mca.h>
-#include <asm/xtp.h>
-
-/*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves.
- */
-void ack_bad_irq(unsigned int irq)
-{
- printk(KERN_ERR "Unexpected irq vector 0x%x on CPU %u!\n", irq, smp_processor_id());
-}
-
-/*
- * Interrupt statistics:
- */
-
-atomic_t irq_err_count;
-
-/*
- * /proc/interrupts printing:
- */
-int arch_show_interrupts(struct seq_file *p, int prec)
-{
- seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
- return 0;
-}
-
-#ifdef CONFIG_SMP
-static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 };
-
-void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
-{
- if (irq < NR_IRQS) {
- irq_data_update_affinity(irq_get_irq_data(irq),
- cpumask_of(cpu_logical_id(hwid)));
- irq_redir[irq] = (char) (redir & 0xff);
- }
-}
-#endif /* CONFIG_SMP */
-
-int __init arch_early_irq_init(void)
-{
- ia64_mca_irq_init();
- return 0;
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-unsigned int vectors_in_migration[NR_IRQS];
-
-/*
- * Since cpu_online_mask is already updated, we just need to check for
- * affinity that has zeros
- */
-static void migrate_irqs(void)
-{
- int irq, new_cpu;
-
- for (irq=0; irq < NR_IRQS; irq++) {
- struct irq_desc *desc = irq_to_desc(irq);
- struct irq_data *data = irq_desc_get_irq_data(desc);
- struct irq_chip *chip = irq_data_get_irq_chip(data);
-
- if (irqd_irq_disabled(data))
- continue;
-
- /*
- * No handling for now.
- * TBD: Implement a disable function so we can now
- * tell CPU not to respond to these local intr sources.
- * such as ITV,CPEI,MCA etc.
- */
- if (irqd_is_per_cpu(data))
- continue;
-
- if (cpumask_any_and(irq_data_get_affinity_mask(data),
- cpu_online_mask) >= nr_cpu_ids) {
- /*
- * Save it for phase 2 processing
- */
- vectors_in_migration[irq] = irq;
-
- new_cpu = cpumask_any(cpu_online_mask);
-
- /*
- * Al three are essential, currently WARN_ON.. maybe panic?
- */
- if (chip && chip->irq_disable &&
- chip->irq_enable && chip->irq_set_affinity) {
- chip->irq_disable(data);
- chip->irq_set_affinity(data,
- cpumask_of(new_cpu), false);
- chip->irq_enable(data);
- } else {
- WARN_ON((!chip || !chip->irq_disable ||
- !chip->irq_enable ||
- !chip->irq_set_affinity));
- }
- }
- }
-}
-
-void fixup_irqs(void)
-{
- unsigned int irq;
- extern void ia64_process_pending_intr(void);
- extern volatile int time_keeper_id;
-
- /* Mask ITV to disable timer */
- ia64_set_itv(1 << 16);
-
- /*
- * Find a new timesync master
- */
- if (smp_processor_id() == time_keeper_id) {
- time_keeper_id = cpumask_first(cpu_online_mask);
- printk ("CPU %d is now promoted to time-keeper master\n", time_keeper_id);
- }
-
- /*
- * Phase 1: Locate IRQs bound to this cpu and
- * relocate them for cpu removal.
- */
- migrate_irqs();
-
- /*
- * Phase 2: Perform interrupt processing for all entries reported in
- * local APIC.
- */
- ia64_process_pending_intr();
-
- /*
- * Phase 3: Now handle any interrupts not captured in local APIC.
- * This is to account for cases that device interrupted during the time the
- * rte was being disabled and re-programmed.
- */
- for (irq=0; irq < NR_IRQS; irq++) {
- if (vectors_in_migration[irq]) {
- struct pt_regs *old_regs = set_irq_regs(NULL);
-
- vectors_in_migration[irq]=0;
- generic_handle_irq(irq);
- set_irq_regs(old_regs);
- }
- }
-
- /*
- * Now let processor die. We do irq disable and max_xtp() to
- * ensure there is no more interrupts routed to this processor.
- * But the local timer interrupt can have 1 pending which we
- * take care in timer_interrupt().
- */
- max_xtp();
- local_irq_disable();
-}
-#endif
diff --git a/arch/ia64/kernel/irq.h b/arch/ia64/kernel/irq.h
deleted file mode 100644
index 4d16f3cbeb1d..000000000000
--- a/arch/ia64/kernel/irq.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-extern void register_percpu_irq(ia64_vector vec, irq_handler_t handler,
- unsigned long flags, const char *name);
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
deleted file mode 100644
index 46e33c5cb53d..000000000000
--- a/arch/ia64/kernel/irq_ia64.c
+++ /dev/null
@@ -1,645 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * linux/arch/ia64/kernel/irq_ia64.c
- *
- * Copyright (C) 1998-2001 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * 6/10/99: Updated to bring in sync with x86 version to facilitate
- * support for SMP and different interrupt controllers.
- *
- * 09/15/00 Goutham Rao <goutham.rao@intel.com> Implemented pci_irq_to_vector
- * PCI to vector allocation routine.
- * 04/14/2004 Ashok Raj <ashok.raj@intel.com>
- * Added CPU Hotplug handling for IPF.
- */
-
-#include <linux/module.h>
-#include <linux/pgtable.h>
-
-#include <linux/jiffies.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/kernel_stat.h>
-#include <linux/ptrace.h>
-#include <linux/signal.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-#include <linux/bitops.h>
-#include <linux/irq.h>
-#include <linux/ratelimit.h>
-#include <linux/acpi.h>
-#include <linux/sched.h>
-
-#include <asm/delay.h>
-#include <asm/intrinsics.h>
-#include <asm/io.h>
-#include <asm/hw_irq.h>
-#include <asm/tlbflush.h>
-
-#define IRQ_DEBUG 0
-
-#define IRQ_VECTOR_UNASSIGNED (0)
-
-#define IRQ_UNUSED (0)
-#define IRQ_USED (1)
-#define IRQ_RSVD (2)
-
-int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR;
-int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR;
-
-/* default base addr of IPI table */
-void __iomem *ipi_base_addr = ((void __iomem *)
- (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR));
-
-static cpumask_t vector_allocation_domain(int cpu);
-
-/*
- * Legacy IRQ to IA-64 vector translation table.
- */
-__u8 isa_irq_to_vector_map[16] = {
- /* 8259 IRQ translation, first 16 entries */
- 0x2f, 0x20, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
- 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21
-};
-EXPORT_SYMBOL(isa_irq_to_vector_map);
-
-DEFINE_SPINLOCK(vector_lock);
-
-struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = {
- [0 ... NR_IRQS - 1] = {
- .vector = IRQ_VECTOR_UNASSIGNED,
- .domain = CPU_MASK_NONE
- }
-};
-
-DEFINE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq) = {
- [0 ... IA64_NUM_VECTORS - 1] = -1
-};
-
-static cpumask_t vector_table[IA64_NUM_VECTORS] = {
- [0 ... IA64_NUM_VECTORS - 1] = CPU_MASK_NONE
-};
-
-static int irq_status[NR_IRQS] = {
- [0 ... NR_IRQS -1] = IRQ_UNUSED
-};
-
-static inline int find_unassigned_irq(void)
-{
- int irq;
-
- for (irq = IA64_FIRST_DEVICE_VECTOR; irq < NR_IRQS; irq++)
- if (irq_status[irq] == IRQ_UNUSED)
- return irq;
- return -ENOSPC;
-}
-
-static inline int find_unassigned_vector(cpumask_t domain)
-{
- cpumask_t mask;
- int pos, vector;
-
- cpumask_and(&mask, &domain, cpu_online_mask);
- if (cpumask_empty(&mask))
- return -EINVAL;
-
- for (pos = 0; pos < IA64_NUM_DEVICE_VECTORS; pos++) {
- vector = IA64_FIRST_DEVICE_VECTOR + pos;
- cpumask_and(&mask, &domain, &vector_table[vector]);
- if (!cpumask_empty(&mask))
- continue;
- return vector;
- }
- return -ENOSPC;
-}
-
-static int __bind_irq_vector(int irq, int vector, cpumask_t domain)
-{
- cpumask_t mask;
- int cpu;
- struct irq_cfg *cfg = &irq_cfg[irq];
-
- BUG_ON((unsigned)irq >= NR_IRQS);
- BUG_ON((unsigned)vector >= IA64_NUM_VECTORS);
-
- cpumask_and(&mask, &domain, cpu_online_mask);
- if (cpumask_empty(&mask))
- return -EINVAL;
- if ((cfg->vector == vector) && cpumask_equal(&cfg->domain, &domain))
- return 0;
- if (cfg->vector != IRQ_VECTOR_UNASSIGNED)
- return -EBUSY;
- for_each_cpu(cpu, &mask)
- per_cpu(vector_irq, cpu)[vector] = irq;
- cfg->vector = vector;
- cfg->domain = domain;
- irq_status[irq] = IRQ_USED;
- cpumask_or(&vector_table[vector], &vector_table[vector], &domain);
- return 0;
-}
-
-int bind_irq_vector(int irq, int vector, cpumask_t domain)
-{
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&vector_lock, flags);
- ret = __bind_irq_vector(irq, vector, domain);
- spin_unlock_irqrestore(&vector_lock, flags);
- return ret;
-}
-
-static void __clear_irq_vector(int irq)
-{
- int vector, cpu;
- cpumask_t domain;
- struct irq_cfg *cfg = &irq_cfg[irq];
-
- BUG_ON((unsigned)irq >= NR_IRQS);
- BUG_ON(cfg->vector == IRQ_VECTOR_UNASSIGNED);
- vector = cfg->vector;
- domain = cfg->domain;
- for_each_cpu_and(cpu, &cfg->domain, cpu_online_mask)
- per_cpu(vector_irq, cpu)[vector] = -1;
- cfg->vector = IRQ_VECTOR_UNASSIGNED;
- cfg->domain = CPU_MASK_NONE;
- irq_status[irq] = IRQ_UNUSED;
- cpumask_andnot(&vector_table[vector], &vector_table[vector], &domain);
-}
-
-static void clear_irq_vector(int irq)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&vector_lock, flags);
- __clear_irq_vector(irq);
- spin_unlock_irqrestore(&vector_lock, flags);
-}
-
-int
-ia64_native_assign_irq_vector (int irq)
-{
- unsigned long flags;
- int vector, cpu;
- cpumask_t domain = CPU_MASK_NONE;
-
- vector = -ENOSPC;
-
- spin_lock_irqsave(&vector_lock, flags);
- for_each_online_cpu(cpu) {
- domain = vector_allocation_domain(cpu);
- vector = find_unassigned_vector(domain);
- if (vector >= 0)
- break;
- }
- if (vector < 0)
- goto out;
- if (irq == AUTO_ASSIGN)
- irq = vector;
- BUG_ON(__bind_irq_vector(irq, vector, domain));
- out:
- spin_unlock_irqrestore(&vector_lock, flags);
- return vector;
-}
-
-void
-ia64_native_free_irq_vector (int vector)
-{
- if (vector < IA64_FIRST_DEVICE_VECTOR ||
- vector > IA64_LAST_DEVICE_VECTOR)
- return;
- clear_irq_vector(vector);
-}
-
-int
-reserve_irq_vector (int vector)
-{
- if (vector < IA64_FIRST_DEVICE_VECTOR ||
- vector > IA64_LAST_DEVICE_VECTOR)
- return -EINVAL;
- return !!bind_irq_vector(vector, vector, CPU_MASK_ALL);
-}
-
-/*
- * Initialize vector_irq on a new cpu. This function must be called
- * with vector_lock held.
- */
-void __setup_vector_irq(int cpu)
-{
- int irq, vector;
-
- /* Clear vector_irq */
- for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
- per_cpu(vector_irq, cpu)[vector] = -1;
- /* Mark the inuse vectors */
- for (irq = 0; irq < NR_IRQS; ++irq) {
- if (!cpumask_test_cpu(cpu, &irq_cfg[irq].domain))
- continue;
- vector = irq_to_vector(irq);
- per_cpu(vector_irq, cpu)[vector] = irq;
- }
-}
-
-#ifdef CONFIG_SMP
-
-static enum vector_domain_type {
- VECTOR_DOMAIN_NONE,
- VECTOR_DOMAIN_PERCPU
-} vector_domain_type = VECTOR_DOMAIN_NONE;
-
-static cpumask_t vector_allocation_domain(int cpu)
-{
- if (vector_domain_type == VECTOR_DOMAIN_PERCPU)
- return *cpumask_of(cpu);
- return CPU_MASK_ALL;
-}
-
-static int __irq_prepare_move(int irq, int cpu)
-{
- struct irq_cfg *cfg = &irq_cfg[irq];
- int vector;
- cpumask_t domain;
-
- if (cfg->move_in_progress || cfg->move_cleanup_count)
- return -EBUSY;
- if (cfg->vector == IRQ_VECTOR_UNASSIGNED || !cpu_online(cpu))
- return -EINVAL;
- if (cpumask_test_cpu(cpu, &cfg->domain))
- return 0;
- domain = vector_allocation_domain(cpu);
- vector = find_unassigned_vector(domain);
- if (vector < 0)
- return -ENOSPC;
- cfg->move_in_progress = 1;
- cfg->old_domain = cfg->domain;
- cfg->vector = IRQ_VECTOR_UNASSIGNED;
- cfg->domain = CPU_MASK_NONE;
- BUG_ON(__bind_irq_vector(irq, vector, domain));
- return 0;
-}
-
-int irq_prepare_move(int irq, int cpu)
-{
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&vector_lock, flags);
- ret = __irq_prepare_move(irq, cpu);
- spin_unlock_irqrestore(&vector_lock, flags);
- return ret;
-}
-
-void irq_complete_move(unsigned irq)
-{
- struct irq_cfg *cfg = &irq_cfg[irq];
- cpumask_t cleanup_mask;
- int i;
-
- if (likely(!cfg->move_in_progress))
- return;
-
- if (unlikely(cpumask_test_cpu(smp_processor_id(), &cfg->old_domain)))
- return;
-
- cpumask_and(&cleanup_mask, &cfg->old_domain, cpu_online_mask);
- cfg->move_cleanup_count = cpumask_weight(&cleanup_mask);
- for_each_cpu(i, &cleanup_mask)
- ia64_send_ipi(i, IA64_IRQ_MOVE_VECTOR, IA64_IPI_DM_INT, 0);
- cfg->move_in_progress = 0;
-}
-
-static irqreturn_t smp_irq_move_cleanup_interrupt(int irq, void *dev_id)
-{
- int me = smp_processor_id();
- ia64_vector vector;
- unsigned long flags;
-
- for (vector = IA64_FIRST_DEVICE_VECTOR;
- vector < IA64_LAST_DEVICE_VECTOR; vector++) {
- int irq;
- struct irq_desc *desc;
- struct irq_cfg *cfg;
- irq = __this_cpu_read(vector_irq[vector]);
- if (irq < 0)
- continue;
-
- desc = irq_to_desc(irq);
- cfg = irq_cfg + irq;
- raw_spin_lock(&desc->lock);
- if (!cfg->move_cleanup_count)
- goto unlock;
-
- if (!cpumask_test_cpu(me, &cfg->old_domain))
- goto unlock;
-
- spin_lock_irqsave(&vector_lock, flags);
- __this_cpu_write(vector_irq[vector], -1);
- cpumask_clear_cpu(me, &vector_table[vector]);
- spin_unlock_irqrestore(&vector_lock, flags);
- cfg->move_cleanup_count--;
- unlock:
- raw_spin_unlock(&desc->lock);
- }
- return IRQ_HANDLED;
-}
-
-static int __init parse_vector_domain(char *arg)
-{
- if (!arg)
- return -EINVAL;
- if (!strcmp(arg, "percpu")) {
- vector_domain_type = VECTOR_DOMAIN_PERCPU;
- no_int_routing = 1;
- }
- return 0;
-}
-early_param("vector", parse_vector_domain);
-#else
-static cpumask_t vector_allocation_domain(int cpu)
-{
- return CPU_MASK_ALL;
-}
-#endif
-
-
-void destroy_and_reserve_irq(unsigned int irq)
-{
- unsigned long flags;
-
- irq_init_desc(irq);
- spin_lock_irqsave(&vector_lock, flags);
- __clear_irq_vector(irq);
- irq_status[irq] = IRQ_RSVD;
- spin_unlock_irqrestore(&vector_lock, flags);
-}
-
-/*
- * Dynamic irq allocate and deallocation for MSI
- */
-int create_irq(void)
-{
- unsigned long flags;
- int irq, vector, cpu;
- cpumask_t domain = CPU_MASK_NONE;
-
- irq = vector = -ENOSPC;
- spin_lock_irqsave(&vector_lock, flags);
- for_each_online_cpu(cpu) {
- domain = vector_allocation_domain(cpu);
- vector = find_unassigned_vector(domain);
- if (vector >= 0)
- break;
- }
- if (vector < 0)
- goto out;
- irq = find_unassigned_irq();
- if (irq < 0)
- goto out;
- BUG_ON(__bind_irq_vector(irq, vector, domain));
- out:
- spin_unlock_irqrestore(&vector_lock, flags);
- if (irq >= 0)
- irq_init_desc(irq);
- return irq;
-}
-
-void destroy_irq(unsigned int irq)
-{
- irq_init_desc(irq);
- clear_irq_vector(irq);
-}
-
-#ifdef CONFIG_SMP
-# define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE)
-# define IS_LOCAL_TLB_FLUSH(vec) (vec == IA64_IPI_LOCAL_TLB_FLUSH)
-#else
-# define IS_RESCHEDULE(vec) (0)
-# define IS_LOCAL_TLB_FLUSH(vec) (0)
-#endif
-/*
- * That's where the IVT branches when we get an external
- * interrupt. This branches to the correct hardware IRQ handler via
- * function ptr.
- */
-void
-ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
-{
- struct pt_regs *old_regs = set_irq_regs(regs);
- unsigned long saved_tpr;
-
-#if IRQ_DEBUG
- {
- unsigned long bsp, sp;
-
- /*
- * Note: if the interrupt happened while executing in
- * the context switch routine (ia64_switch_to), we may
- * get a spurious stack overflow here. This is
- * because the register and the memory stack are not
- * switched atomically.
- */
- bsp = ia64_getreg(_IA64_REG_AR_BSP);
- sp = ia64_getreg(_IA64_REG_SP);
-
- if ((sp - bsp) < 1024) {
- static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5);
-
- if (__ratelimit(&ratelimit)) {
- printk("ia64_handle_irq: DANGER: less than "
- "1KB of free stack space!!\n"
- "(bsp=0x%lx, sp=%lx)\n", bsp, sp);
- }
- }
- }
-#endif /* IRQ_DEBUG */
-
- /*
- * Always set TPR to limit maximum interrupt nesting depth to
- * 16 (without this, it would be ~240, which could easily lead
- * to kernel stack overflows).
- */
- irq_enter();
- saved_tpr = ia64_getreg(_IA64_REG_CR_TPR);
- ia64_srlz_d();
- while (vector != IA64_SPURIOUS_INT_VECTOR) {
- int irq = local_vector_to_irq(vector);
-
- if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
- smp_local_flush_tlb();
- kstat_incr_irq_this_cpu(irq);
- } else if (unlikely(IS_RESCHEDULE(vector))) {
- scheduler_ipi();
- kstat_incr_irq_this_cpu(irq);
- } else {
- ia64_setreg(_IA64_REG_CR_TPR, vector);
- ia64_srlz_d();
-
- if (unlikely(irq < 0)) {
- printk(KERN_ERR "%s: Unexpected interrupt "
- "vector %d on CPU %d is not mapped "
- "to any IRQ!\n", __func__, vector,
- smp_processor_id());
- } else
- generic_handle_irq(irq);
-
- /*
- * Disable interrupts and send EOI:
- */
- local_irq_disable();
- ia64_setreg(_IA64_REG_CR_TPR, saved_tpr);
- }
- ia64_eoi();
- vector = ia64_get_ivr();
- }
- /*
- * This must be done *after* the ia64_eoi(). For example, the keyboard softirq
- * handler needs to be able to wait for further keyboard interrupts, which can't
- * come through until ia64_eoi() has been done.
- */
- irq_exit();
- set_irq_regs(old_regs);
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * This function emulates a interrupt processing when a cpu is about to be
- * brought down.
- */
-void ia64_process_pending_intr(void)
-{
- ia64_vector vector;
- unsigned long saved_tpr;
- extern unsigned int vectors_in_migration[NR_IRQS];
-
- vector = ia64_get_ivr();
-
- irq_enter();
- saved_tpr = ia64_getreg(_IA64_REG_CR_TPR);
- ia64_srlz_d();
-
- /*
- * Perform normal interrupt style processing
- */
- while (vector != IA64_SPURIOUS_INT_VECTOR) {
- int irq = local_vector_to_irq(vector);
-
- if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
- smp_local_flush_tlb();
- kstat_incr_irq_this_cpu(irq);
- } else if (unlikely(IS_RESCHEDULE(vector))) {
- kstat_incr_irq_this_cpu(irq);
- } else {
- struct pt_regs *old_regs = set_irq_regs(NULL);
-
- ia64_setreg(_IA64_REG_CR_TPR, vector);
- ia64_srlz_d();
-
- /*
- * Now try calling normal ia64_handle_irq as it would have got called
- * from a real intr handler. Try passing null for pt_regs, hopefully
- * it will work. I hope it works!.
- * Probably could shared code.
- */
- if (unlikely(irq < 0)) {
- printk(KERN_ERR "%s: Unexpected interrupt "
- "vector %d on CPU %d not being mapped "
- "to any IRQ!!\n", __func__, vector,
- smp_processor_id());
- } else {
- vectors_in_migration[irq]=0;
- generic_handle_irq(irq);
- }
- set_irq_regs(old_regs);
-
- /*
- * Disable interrupts and send EOI
- */
- local_irq_disable();
- ia64_setreg(_IA64_REG_CR_TPR, saved_tpr);
- }
- ia64_eoi();
- vector = ia64_get_ivr();
- }
- irq_exit();
-}
-#endif
-
-
-#ifdef CONFIG_SMP
-
-static irqreturn_t dummy_handler (int irq, void *dev_id)
-{
- BUG();
- return IRQ_NONE;
-}
-
-/*
- * KVM uses this interrupt to force a cpu out of guest mode
- */
-
-#endif
-
-void
-register_percpu_irq(ia64_vector vec, irq_handler_t handler, unsigned long flags,
- const char *name)
-{
- unsigned int irq;
-
- irq = vec;
- BUG_ON(bind_irq_vector(irq, vec, CPU_MASK_ALL));
- irq_set_status_flags(irq, IRQ_PER_CPU);
- irq_set_chip(irq, &irq_type_ia64_lsapic);
- if (handler)
- if (request_irq(irq, handler, flags, name, NULL))
- pr_err("Failed to request irq %u (%s)\n", irq, name);
- irq_set_handler(irq, handle_percpu_irq);
-}
-
-void __init
-ia64_native_register_ipi(void)
-{
-#ifdef CONFIG_SMP
- register_percpu_irq(IA64_IPI_VECTOR, handle_IPI, 0, "IPI");
- register_percpu_irq(IA64_IPI_RESCHEDULE, dummy_handler, 0, "resched");
- register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, dummy_handler, 0,
- "tlb_flush");
-#endif
-}
-
-void __init
-init_IRQ (void)
-{
- acpi_boot_init();
- ia64_register_ipi();
- register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL, 0, NULL);
-#ifdef CONFIG_SMP
- if (vector_domain_type != VECTOR_DOMAIN_NONE) {
- register_percpu_irq(IA64_IRQ_MOVE_VECTOR,
- smp_irq_move_cleanup_interrupt, 0,
- "irq_move");
- }
-#endif
-}
-
-void
-ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect)
-{
- void __iomem *ipi_addr;
- unsigned long ipi_data;
- unsigned long phys_cpu_id;
-
- phys_cpu_id = cpu_physical_id(cpu);
-
- /*
- * cpu number is in 8bit ID and 8bit EID
- */
-
- ipi_data = (delivery_mode << 8) | (vector & 0xff);
- ipi_addr = ipi_base_addr + ((phys_cpu_id << 4) | ((redirect & 1) << 3));
-
- writeq(ipi_data, ipi_addr);
-}
diff --git a/arch/ia64/kernel/irq_lsapic.c b/arch/ia64/kernel/irq_lsapic.c
deleted file mode 100644
index 23bf4499a75d..000000000000
--- a/arch/ia64/kernel/irq_lsapic.c
+++ /dev/null
@@ -1,45 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * LSAPIC Interrupt Controller
- *
- * This takes care of interrupts that are generated by the CPU's
- * internal Streamlined Advanced Programmable Interrupt Controller
- * (LSAPIC), such as the ITC and IPI interrupts.
- *
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 2000 Hewlett-Packard Co
- * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/sched.h>
-#include <linux/irq.h>
-
-static unsigned int
-lsapic_noop_startup (struct irq_data *data)
-{
- return 0;
-}
-
-static void
-lsapic_noop (struct irq_data *data)
-{
- /* nothing to do... */
-}
-
-static int lsapic_retrigger(struct irq_data *data)
-{
- ia64_resend_irq(data->irq);
-
- return 1;
-}
-
-struct irq_chip irq_type_ia64_lsapic = {
- .name = "LSAPIC",
- .irq_startup = lsapic_noop_startup,
- .irq_shutdown = lsapic_noop,
- .irq_enable = lsapic_noop,
- .irq_disable = lsapic_noop,
- .irq_ack = lsapic_noop,
- .irq_retrigger = lsapic_retrigger,
-};
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
deleted file mode 100644
index da90c49df628..000000000000
--- a/arch/ia64/kernel/ivt.S
+++ /dev/null
@@ -1,1688 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * arch/ia64/kernel/ivt.S
- *
- * Copyright (C) 1998-2001, 2003, 2005 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- * David Mosberger <davidm@hpl.hp.com>
- * Copyright (C) 2000, 2002-2003 Intel Co
- * Asit Mallick <asit.k.mallick@intel.com>
- * Suresh Siddha <suresh.b.siddha@intel.com>
- * Kenneth Chen <kenneth.w.chen@intel.com>
- * Fenghua Yu <fenghua.yu@intel.com>
- *
- * 00/08/23 Asit Mallick <asit.k.mallick@intel.com> TLB handling for SMP
- * 00/12/20 David Mosberger-Tang <davidm@hpl.hp.com> DTLB/ITLB handler now uses virtual PT.
- *
- * Copyright (C) 2005 Hewlett-Packard Co
- * Dan Magenheimer <dan.magenheimer@hp.com>
- * Xen paravirtualization
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- * VA Linux Systems Japan K.K.
- * pv_ops.
- * Yaozu (Eddie) Dong <eddie.dong@intel.com>
- */
-/*
- * This file defines the interruption vector table used by the CPU.
- * It does not include one entry per possible cause of interruption.
- *
- * The first 20 entries of the table contain 64 bundles each while the
- * remaining 48 entries contain only 16 bundles each.
- *
- * The 64 bundles are used to allow inlining the whole handler for critical
- * interruptions like TLB misses.
- *
- * For each entry, the comment is as follows:
- *
- * // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
- * entry offset ----/ / / / /
- * entry number ---------/ / / /
- * size of the entry -------------/ / /
- * vector name -------------------------------------/ /
- * interruptions triggering this vector ----------------------/
- *
- * The table is 32KB in size and must be aligned on 32KB boundary.
- * (The CPU ignores the 15 lower bits of the address)
- *
- * Table is based upon EAS2.6 (Oct 1999)
- */
-
-#include <linux/export.h>
-#include <linux/pgtable.h>
-#include <asm/asmmacro.h>
-#include <asm/break.h>
-#include <asm/kregs.h>
-#include <asm/asm-offsets.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/errno.h>
-
-#if 0
-# define PSR_DEFAULT_BITS psr.ac
-#else
-# define PSR_DEFAULT_BITS 0
-#endif
-
-#if 0
- /*
- * This lets you track the last eight faults that occurred on the CPU. Make sure ar.k2 isn't
- * needed for something else before enabling this...
- */
-# define DBG_FAULT(i) mov r16=ar.k2;; shl r16=r16,8;; add r16=(i),r16;;mov ar.k2=r16
-#else
-# define DBG_FAULT(i)
-#endif
-
-#include "minstate.h"
-
-#define FAULT(n) \
- mov r31=pr; \
- mov r19=n;; /* prepare to save predicates */ \
- br.sptk.many dispatch_to_fault_handler
-
- .section .text..ivt,"ax"
-
- .align 32768 // align on 32KB boundary
- .global ia64_ivt
- EXPORT_SYMBOL(ia64_ivt)
-ia64_ivt:
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
-ENTRY(vhpt_miss)
- DBG_FAULT(0)
- /*
- * The VHPT vector is invoked when the TLB entry for the virtual page table
- * is missing. This happens only as a result of a previous
- * (the "original") TLB miss, which may either be caused by an instruction
- * fetch or a data access (or non-access).
- *
- * What we do here is normal TLB miss handing for the _original_ miss,
- * followed by inserting the TLB entry for the virtual page table page
- * that the VHPT walker was attempting to access. The latter gets
- * inserted as long as page table entry above pte level have valid
- * mappings for the faulting address. The TLB entry for the original
- * miss gets inserted only if the pte entry indicates that the page is
- * present.
- *
- * do_page_fault gets invoked in the following cases:
- * - the faulting virtual address uses unimplemented address bits
- * - the faulting virtual address has no valid page table mapping
- */
- MOV_FROM_IFA(r16) // get address that caused the TLB miss
-#ifdef CONFIG_HUGETLB_PAGE
- movl r18=PAGE_SHIFT
- MOV_FROM_ITIR(r25)
-#endif
- ;;
- RSM_PSR_DT // use physical addressing for data
- mov r31=pr // save the predicate registers
- mov r19=IA64_KR(PT_BASE) // get page table base address
- shl r21=r16,3 // shift bit 60 into sign bit
- shr.u r17=r16,61 // get the region number into r17
- ;;
- shr.u r22=r21,3
-#ifdef CONFIG_HUGETLB_PAGE
- extr.u r26=r25,2,6
- ;;
- cmp.ne p8,p0=r18,r26
- sub r27=r26,r18
- ;;
-(p8) dep r25=r18,r25,2,6
-(p8) shr r22=r22,r27
-#endif
- ;;
- cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
- shr.u r18=r22,PGDIR_SHIFT // get bottom portion of pgd index bit
- ;;
-(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
-
- srlz.d
- LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
-
- .pred.rel "mutex", p6, p7
-(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
-(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
- ;;
-(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
-(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
- cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
-#if CONFIG_PGTABLE_LEVELS == 4
- shr.u r28=r22,PUD_SHIFT // shift pud index into position
-#else
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
-#endif
- ;;
- ld8 r17=[r17] // get *pgd (may be 0)
- ;;
-(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
-#if CONFIG_PGTABLE_LEVELS == 4
- dep r28=r28,r17,3,(PAGE_SHIFT-3) // r28=pud_offset(pgd,addr)
- ;;
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
-(p7) ld8 r29=[r28] // get *pud (may be 0)
- ;;
-(p7) cmp.eq.or.andcm p6,p7=r29,r0 // was pud_present(*pud) == NULL?
- dep r17=r18,r29,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
-#else
- dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pgd,addr)
-#endif
- ;;
-(p7) ld8 r20=[r17] // get *pmd (may be 0)
- shr.u r19=r22,PAGE_SHIFT // shift pte index into position
- ;;
-(p7) cmp.eq.or.andcm p6,p7=r20,r0 // was pmd_present(*pmd) == NULL?
- dep r21=r19,r20,3,(PAGE_SHIFT-3) // r21=pte_offset(pmd,addr)
- ;;
-(p7) ld8 r18=[r21] // read *pte
- MOV_FROM_ISR(r19) // cr.isr bit 32 tells us if this is an insn miss
- ;;
-(p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared?
- MOV_FROM_IHA(r22) // get the VHPT address that caused the TLB miss
- ;; // avoid RAW on p7
-(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss?
- dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address
- ;;
- ITC_I_AND_D(p10, p11, r18, r24) // insert the instruction TLB entry and
- // insert the data TLB entry
-(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault)
- MOV_TO_IFA(r22, r24)
-
-#ifdef CONFIG_HUGETLB_PAGE
- MOV_TO_ITIR(p8, r25, r24) // change to default page-size for VHPT
-#endif
-
- /*
- * Now compute and insert the TLB entry for the virtual page table. We never
- * execute in a page table page so there is no need to set the exception deferral
- * bit.
- */
- adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
- ;;
- ITC_D(p7, r24, r25)
- ;;
-#ifdef CONFIG_SMP
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- /*
- * Re-check pagetable entry. If they changed, we may have received a ptc.g
- * between reading the pagetable and the "itc". If so, flush the entry we
- * inserted and retry. At this point, we have:
- *
- * r28 = equivalent of pud_offset(pgd, ifa)
- * r17 = equivalent of pmd_offset(pud, ifa)
- * r21 = equivalent of pte_offset(pmd, ifa)
- *
- * r29 = *pud
- * r20 = *pmd
- * r18 = *pte
- */
- ld8 r25=[r21] // read *pte again
- ld8 r26=[r17] // read *pmd again
-#if CONFIG_PGTABLE_LEVELS == 4
- ld8 r19=[r28] // read *pud again
-#endif
- cmp.ne p6,p7=r0,r0
- ;;
- cmp.ne.or.andcm p6,p7=r26,r20 // did *pmd change
-#if CONFIG_PGTABLE_LEVELS == 4
- cmp.ne.or.andcm p6,p7=r19,r29 // did *pud change
-#endif
- mov r27=PAGE_SHIFT<<2
- ;;
-(p6) ptc.l r22,r27 // purge PTE page translation
-(p7) cmp.ne.or.andcm p6,p7=r25,r18 // did *pte change
- ;;
-(p6) ptc.l r16,r27 // purge translation
-#endif
-
- mov pr=r31,-1 // restore predicate registers
- RFI
-END(vhpt_miss)
-
- .org ia64_ivt+0x400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
-ENTRY(itlb_miss)
- DBG_FAULT(1)
- /*
- * The ITLB handler accesses the PTE via the virtually mapped linear
- * page table. If a nested TLB miss occurs, we switch into physical
- * mode, walk the page table, and then re-execute the PTE read and
- * go on normally after that.
- */
- MOV_FROM_IFA(r16) // get virtual address
- mov r29=b0 // save b0
- mov r31=pr // save predicates
-.itlb_fault:
- MOV_FROM_IHA(r17) // get virtual address of PTE
- movl r30=1f // load nested fault continuation point
- ;;
-1: ld8 r18=[r17] // read *pte
- ;;
- mov b0=r29
- tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
-(p6) br.cond.spnt page_fault
- ;;
- ITC_I(p0, r18, r19)
- ;;
-#ifdef CONFIG_SMP
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- ld8 r19=[r17] // read *pte again and see if same
- mov r20=PAGE_SHIFT<<2 // setup page size for purge
- ;;
- cmp.ne p7,p0=r18,r19
- ;;
-(p7) ptc.l r16,r20
-#endif
- mov pr=r31,-1
- RFI
-END(itlb_miss)
-
- .org ia64_ivt+0x0800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
-ENTRY(dtlb_miss)
- DBG_FAULT(2)
- /*
- * The DTLB handler accesses the PTE via the virtually mapped linear
- * page table. If a nested TLB miss occurs, we switch into physical
- * mode, walk the page table, and then re-execute the PTE read and
- * go on normally after that.
- */
- MOV_FROM_IFA(r16) // get virtual address
- mov r29=b0 // save b0
- mov r31=pr // save predicates
-dtlb_fault:
- MOV_FROM_IHA(r17) // get virtual address of PTE
- movl r30=1f // load nested fault continuation point
- ;;
-1: ld8 r18=[r17] // read *pte
- ;;
- mov b0=r29
- tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
-(p6) br.cond.spnt page_fault
- ;;
- ITC_D(p0, r18, r19)
- ;;
-#ifdef CONFIG_SMP
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- ld8 r19=[r17] // read *pte again and see if same
- mov r20=PAGE_SHIFT<<2 // setup page size for purge
- ;;
- cmp.ne p7,p0=r18,r19
- ;;
-(p7) ptc.l r16,r20
-#endif
- mov pr=r31,-1
- RFI
-END(dtlb_miss)
-
- .org ia64_ivt+0x0c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
-ENTRY(alt_itlb_miss)
- DBG_FAULT(3)
- MOV_FROM_IFA(r16) // get address that caused the TLB miss
- movl r17=PAGE_KERNEL
- MOV_FROM_IPSR(p0, r21)
- movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
- mov r31=pr
- ;;
-#ifdef CONFIG_DISABLE_VHPT
- shr.u r22=r16,61 // get the region number into r21
- ;;
- cmp.gt p8,p0=6,r22 // user mode
- ;;
- THASH(p8, r17, r16, r23)
- ;;
- MOV_TO_IHA(p8, r17, r23)
-(p8) mov r29=b0 // save b0
-(p8) br.cond.dptk .itlb_fault
-#endif
- extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
- and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
- shr.u r18=r16,57 // move address bit 61 to bit 4
- ;;
- andcm r18=0x10,r18 // bit 4=~address-bit(61)
- cmp.ne p8,p0=r0,r23 // psr.cpl != 0?
- or r19=r17,r19 // insert PTE control bits into r19
- ;;
- or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
-(p8) br.cond.spnt page_fault
- ;;
- ITC_I(p0, r19, r18) // insert the TLB entry
- mov pr=r31,-1
- RFI
-END(alt_itlb_miss)
-
- .org ia64_ivt+0x1000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
-ENTRY(alt_dtlb_miss)
- DBG_FAULT(4)
- MOV_FROM_IFA(r16) // get address that caused the TLB miss
- movl r17=PAGE_KERNEL
- MOV_FROM_ISR(r20)
- movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
- MOV_FROM_IPSR(p0, r21)
- mov r31=pr
- mov r24=PERCPU_ADDR
- ;;
-#ifdef CONFIG_DISABLE_VHPT
- shr.u r22=r16,61 // get the region number into r21
- ;;
- cmp.gt p8,p0=6,r22 // access to region 0-5
- ;;
- THASH(p8, r17, r16, r25)
- ;;
- MOV_TO_IHA(p8, r17, r25)
-(p8) mov r29=b0 // save b0
-(p8) br.cond.dptk dtlb_fault
-#endif
- cmp.ge p10,p11=r16,r24 // access to per_cpu_data?
- tbit.z p12,p0=r16,61 // access to region 6?
- mov r25=PERCPU_PAGE_SHIFT << 2
- mov r26=PERCPU_PAGE_SIZE
- nop.m 0
- nop.b 0
- ;;
-(p10) mov r19=IA64_KR(PER_CPU_DATA)
-(p11) and r19=r19,r16 // clear non-ppn fields
- extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
- and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field
- tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
- tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
- ;;
-(p10) sub r19=r19,r26
- MOV_TO_ITIR(p10, r25, r24)
- cmp.ne p8,p0=r0,r23
-(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field
-(p12) dep r17=-1,r17,4,1 // set ma=UC for region 6 addr
-(p8) br.cond.spnt page_fault
-
- dep r21=-1,r21,IA64_PSR_ED_BIT,1
- ;;
- or r19=r19,r17 // insert PTE control bits into r19
- MOV_TO_IPSR(p6, r21, r24)
- ;;
- ITC_D(p7, r19, r18) // insert the TLB entry
- mov pr=r31,-1
- RFI
-END(alt_dtlb_miss)
-
- .org ia64_ivt+0x1400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
-ENTRY(nested_dtlb_miss)
- /*
- * In the absence of kernel bugs, we get here when the virtually mapped linear
- * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction
- * Access-bit, or Data Access-bit faults). If the DTLB entry for the virtual page
- * table is missing, a nested TLB miss fault is triggered and control is
- * transferred to this point. When this happens, we lookup the pte for the
- * faulting address by walking the page table in physical mode and return to the
- * continuation point passed in register r30 (or call page_fault if the address is
- * not mapped).
- *
- * Input: r16: faulting address
- * r29: saved b0
- * r30: continuation address
- * r31: saved pr
- *
- * Output: r17: physical address of PTE of faulting address
- * r29: saved b0
- * r30: continuation address
- * r31: saved pr
- *
- * Clobbered: b0, r18, r19, r21, r22, psr.dt (cleared)
- */
- RSM_PSR_DT // switch to using physical data addressing
- mov r19=IA64_KR(PT_BASE) // get the page table base address
- shl r21=r16,3 // shift bit 60 into sign bit
- MOV_FROM_ITIR(r18)
- ;;
- shr.u r17=r16,61 // get the region number into r17
- extr.u r18=r18,2,6 // get the faulting page size
- ;;
- cmp.eq p6,p7=5,r17 // is faulting address in region 5?
- add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
- add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
- ;;
- shr.u r22=r16,r22
- shr.u r18=r16,r18
-(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
-
- srlz.d
- LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
-
- .pred.rel "mutex", p6, p7
-(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
-(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
- ;;
-(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
-(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
- cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
-#if CONFIG_PGTABLE_LEVELS == 4
- shr.u r18=r22,PUD_SHIFT // shift pud index into position
-#else
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
-#endif
- ;;
- ld8 r17=[r17] // get *pgd (may be 0)
- ;;
-(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
- dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=p[u|m]d_offset(pgd,addr)
- ;;
-#if CONFIG_PGTABLE_LEVELS == 4
-(p7) ld8 r17=[r17] // get *pud (may be 0)
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
- ;;
-(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) == NULL?
- dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
- ;;
-#endif
-(p7) ld8 r17=[r17] // get *pmd (may be 0)
- shr.u r19=r22,PAGE_SHIFT // shift pte index into position
- ;;
-(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) == NULL?
- dep r17=r19,r17,3,(PAGE_SHIFT-3) // r17=pte_offset(pmd,addr);
-(p6) br.cond.spnt page_fault
- mov b0=r30
- br.sptk.many b0 // return to continuation point
-END(nested_dtlb_miss)
-
- .org ia64_ivt+0x1800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
-ENTRY(ikey_miss)
- DBG_FAULT(6)
- FAULT(6)
-END(ikey_miss)
-
- .org ia64_ivt+0x1c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
-ENTRY(dkey_miss)
- DBG_FAULT(7)
- FAULT(7)
-END(dkey_miss)
-
- .org ia64_ivt+0x2000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
-ENTRY(dirty_bit)
- DBG_FAULT(8)
- /*
- * What we do here is to simply turn on the dirty bit in the PTE. We need to
- * update both the page-table and the TLB entry. To efficiently access the PTE,
- * we address it through the virtual page table. Most likely, the TLB entry for
- * the relevant virtual page table page is still present in the TLB so we can
- * normally do this without additional TLB misses. In case the necessary virtual
- * page table TLB entry isn't present, we take a nested TLB miss hit where we look
- * up the physical address of the L3 PTE and then continue at label 1 below.
- */
- MOV_FROM_IFA(r16) // get the address that caused the fault
- movl r30=1f // load continuation point in case of nested fault
- ;;
- THASH(p0, r17, r16, r18) // compute virtual address of L3 PTE
- mov r29=b0 // save b0 in case of nested fault
- mov r31=pr // save pr
-#ifdef CONFIG_SMP
- mov r28=ar.ccv // save ar.ccv
- ;;
-1: ld8 r18=[r17]
- ;; // avoid RAW on r18
- mov ar.ccv=r18 // set compare value for cmpxchg
- or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
- tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
- ;;
-(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only update if page is present
- mov r24=PAGE_SHIFT<<2
- ;;
-(p6) cmp.eq p6,p7=r26,r18 // Only compare if page is present
- ;;
- ITC_D(p6, r25, r18) // install updated PTE
- ;;
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- ld8 r18=[r17] // read PTE again
- ;;
- cmp.eq p6,p7=r18,r25 // is it same as the newly installed
- ;;
-(p7) ptc.l r16,r24
- mov b0=r29 // restore b0
- mov ar.ccv=r28
-#else
- ;;
-1: ld8 r18=[r17]
- ;; // avoid RAW on r18
- or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
- mov b0=r29 // restore b0
- ;;
- st8 [r17]=r18 // store back updated PTE
- ITC_D(p0, r18, r16) // install updated PTE
-#endif
- mov pr=r31,-1 // restore pr
- RFI
-END(dirty_bit)
-
- .org ia64_ivt+0x2400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
-ENTRY(iaccess_bit)
- DBG_FAULT(9)
- // Like Entry 8, except for instruction access
- MOV_FROM_IFA(r16) // get the address that caused the fault
- movl r30=1f // load continuation point in case of nested fault
- mov r31=pr // save predicates
-#ifdef CONFIG_ITANIUM
- /*
- * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
- */
- MOV_FROM_IPSR(p0, r17)
- ;;
- MOV_FROM_IIP(r18)
- tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set?
- ;;
-(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa
-#endif /* CONFIG_ITANIUM */
- ;;
- THASH(p0, r17, r16, r18) // compute virtual address of L3 PTE
- mov r29=b0 // save b0 in case of nested fault)
-#ifdef CONFIG_SMP
- mov r28=ar.ccv // save ar.ccv
- ;;
-1: ld8 r18=[r17]
- ;;
- mov ar.ccv=r18 // set compare value for cmpxchg
- or r25=_PAGE_A,r18 // set the accessed bit
- tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
- ;;
-(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present
- mov r24=PAGE_SHIFT<<2
- ;;
-(p6) cmp.eq p6,p7=r26,r18 // Only if page present
- ;;
- ITC_I(p6, r25, r26) // install updated PTE
- ;;
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- ld8 r18=[r17] // read PTE again
- ;;
- cmp.eq p6,p7=r18,r25 // is it same as the newly installed
- ;;
-(p7) ptc.l r16,r24
- mov b0=r29 // restore b0
- mov ar.ccv=r28
-#else /* !CONFIG_SMP */
- ;;
-1: ld8 r18=[r17]
- ;;
- or r18=_PAGE_A,r18 // set the accessed bit
- mov b0=r29 // restore b0
- ;;
- st8 [r17]=r18 // store back updated PTE
- ITC_I(p0, r18, r16) // install updated PTE
-#endif /* !CONFIG_SMP */
- mov pr=r31,-1
- RFI
-END(iaccess_bit)
-
- .org ia64_ivt+0x2800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
-ENTRY(daccess_bit)
- DBG_FAULT(10)
- // Like Entry 8, except for data access
- MOV_FROM_IFA(r16) // get the address that caused the fault
- movl r30=1f // load continuation point in case of nested fault
- ;;
- THASH(p0, r17, r16, r18) // compute virtual address of L3 PTE
- mov r31=pr
- mov r29=b0 // save b0 in case of nested fault)
-#ifdef CONFIG_SMP
- mov r28=ar.ccv // save ar.ccv
- ;;
-1: ld8 r18=[r17]
- ;; // avoid RAW on r18
- mov ar.ccv=r18 // set compare value for cmpxchg
- or r25=_PAGE_A,r18 // set the dirty bit
- tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
- ;;
-(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page is present
- mov r24=PAGE_SHIFT<<2
- ;;
-(p6) cmp.eq p6,p7=r26,r18 // Only if page is present
- ;;
- ITC_D(p6, r25, r26) // install updated PTE
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
- ;;
- ld8 r18=[r17] // read PTE again
- ;;
- cmp.eq p6,p7=r18,r25 // is it same as the newly installed
- ;;
-(p7) ptc.l r16,r24
- mov ar.ccv=r28
-#else
- ;;
-1: ld8 r18=[r17]
- ;; // avoid RAW on r18
- or r18=_PAGE_A,r18 // set the accessed bit
- ;;
- st8 [r17]=r18 // store back updated PTE
- ITC_D(p0, r18, r16) // install updated PTE
-#endif
- mov b0=r29 // restore b0
- mov pr=r31,-1
- RFI
-END(daccess_bit)
-
- .org ia64_ivt+0x2c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
-ENTRY(break_fault)
- /*
- * The streamlined system call entry/exit paths only save/restore the initial part
- * of pt_regs. This implies that the callers of system-calls must adhere to the
- * normal procedure calling conventions.
- *
- * Registers to be saved & restored:
- * CR registers: cr.ipsr, cr.iip, cr.ifs
- * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr
- * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15
- * Registers to be restored only:
- * r8-r11: output value from the system call.
- *
- * During system call exit, scratch registers (including r15) are modified/cleared
- * to prevent leaking bits from kernel to user level.
- */
- DBG_FAULT(11)
- mov.m r16=IA64_KR(CURRENT) // M2 r16 <- current task (12 cyc)
- MOV_FROM_IPSR(p0, r29) // M2 (12 cyc)
- mov r31=pr // I0 (2 cyc)
-
- MOV_FROM_IIM(r17) // M2 (2 cyc)
- mov.m r27=ar.rsc // M2 (12 cyc)
- mov r18=__IA64_BREAK_SYSCALL // A
-
- mov.m ar.rsc=0 // M2
- mov.m r21=ar.fpsr // M2 (12 cyc)
- mov r19=b6 // I0 (2 cyc)
- ;;
- mov.m r23=ar.bspstore // M2 (12 cyc)
- mov.m r24=ar.rnat // M2 (5 cyc)
- mov.i r26=ar.pfs // I0 (2 cyc)
-
- invala // M0|1
- nop.m 0 // M
- mov r20=r1 // A save r1
-
- nop.m 0
- movl r30=sys_call_table // X
-
- MOV_FROM_IIP(r28) // M2 (2 cyc)
- cmp.eq p0,p7=r18,r17 // I0 is this a system call?
-(p7) br.cond.spnt non_syscall // B no ->
- //
- // From this point on, we are definitely on the syscall-path
- // and we can use (non-banked) scratch registers.
- //
-///////////////////////////////////////////////////////////////////////
- mov r1=r16 // A move task-pointer to "addl"-addressable reg
- mov r2=r16 // A setup r2 for ia64_syscall_setup
- add r9=TI_FLAGS+IA64_TASK_SIZE,r16 // A r9 = &current_thread_info()->flags
-
- adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16
- adds r15=-1024,r15 // A subtract 1024 from syscall number
- mov r3=NR_syscalls - 1
- ;;
- ld1.bias r17=[r16] // M0|1 r17 = current->thread.on_ustack flag
- ld4 r9=[r9] // M0|1 r9 = current_thread_info()->flags
- extr.u r8=r29,41,2 // I0 extract ei field from cr.ipsr
-
- shladd r30=r15,3,r30 // A r30 = sys_call_table + 8*(syscall-1024)
- addl r22=IA64_RBS_OFFSET,r1 // A compute base of RBS
- cmp.leu p6,p7=r15,r3 // A syscall number in range?
- ;;
-
- lfetch.fault.excl.nt1 [r22] // M0|1 prefetch RBS
-(p6) ld8 r30=[r30] // M0|1 load address of syscall entry point
- tnat.nz.or p7,p0=r15 // I0 is syscall nr a NaT?
-
- mov.m ar.bspstore=r22 // M2 switch to kernel RBS
- cmp.eq p8,p9=2,r8 // A isr.ei==2?
- ;;
-
-(p8) mov r8=0 // A clear ei to 0
-(p7) movl r30=sys_ni_syscall // X
-
-(p8) adds r28=16,r28 // A switch cr.iip to next bundle
-(p9) adds r8=1,r8 // A increment ei to next slot
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
- ;;
- mov b6=r30 // I0 setup syscall handler branch reg early
-#else
- nop.i 0
- ;;
-#endif
-
- mov.m r25=ar.unat // M2 (5 cyc)
- dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr
- adds r15=1024,r15 // A restore original syscall number
- //
- // If any of the above loads miss in L1D, we'll stall here until
- // the data arrives.
- //
-///////////////////////////////////////////////////////////////////////
- st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
- MOV_FROM_ITC(p0, p14, r30, r18) // M get cycle for accounting
-#else
- mov b6=r30 // I0 setup syscall handler branch reg early
-#endif
- cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already?
-
- and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit
- mov r18=ar.bsp // M2 (12 cyc)
-(pKStk) br.cond.spnt .break_fixup // B we're already in kernel-mode -- fix up RBS
- ;;
-.back_from_break_fixup:
-(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A compute base of memory stack
- cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited?
- br.call.sptk.many b7=ia64_syscall_setup // B
-1:
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
- // mov.m r30=ar.itc is called in advance, and r13 is current
- add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13 // A
- add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13 // A
-(pKStk) br.cond.spnt .skip_accounting // B unlikely skip
- ;;
- ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // M get last stamp
- ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // M time at leave
- ;;
- ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME // M cumulated stime
- ld8 r21=[r17] // M cumulated utime
- sub r22=r19,r18 // A stime before leave
- ;;
- st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP // M update stamp
- sub r18=r30,r19 // A elapsed time in user
- ;;
- add r20=r20,r22 // A sum stime
- add r21=r21,r18 // A sum utime
- ;;
- st8 [r16]=r20 // M update stime
- st8 [r17]=r21 // M update utime
- ;;
-.skip_accounting:
-#endif
- mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0
- nop 0
- BSW_1(r2, r14) // B (6 cyc) regs are saved, switch to bank 1
- ;;
-
- SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r16) // M2 now it's safe to re-enable intr.-collection
- // M0 ensure interruption collection is on
- movl r3=ia64_ret_from_syscall // X
- ;;
- mov rp=r3 // I0 set the real return addr
-(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT
-
- SSM_PSR_I(p15, p15, r16) // M2 restore psr.i
-(p14) br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr)
- br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic
- // NOT REACHED
-///////////////////////////////////////////////////////////////////////
- // On entry, we optimistically assumed that we're coming from user-space.
- // For the rare cases where a system-call is done from within the kernel,
- // we fix things up at this point:
-.break_fixup:
- add r1=-IA64_PT_REGS_SIZE,sp // A allocate space for pt_regs structure
- mov ar.rnat=r24 // M2 restore kernel's AR.RNAT
- ;;
- mov ar.bspstore=r23 // M2 restore kernel's AR.BSPSTORE
- br.cond.sptk .back_from_break_fixup
-END(break_fault)
-
- .org ia64_ivt+0x3000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
-ENTRY(interrupt)
- /* interrupt handler has become too big to fit this area. */
- br.sptk.many __interrupt
-END(interrupt)
-
- .org ia64_ivt+0x3400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x3400 Entry 13 (size 64 bundles) Reserved
- DBG_FAULT(13)
- FAULT(13)
-
- .org ia64_ivt+0x3800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x3800 Entry 14 (size 64 bundles) Reserved
- DBG_FAULT(14)
- FAULT(14)
-
- /*
- * There is no particular reason for this code to be here, other than that
- * there happens to be space here that would go unused otherwise. If this
- * fault ever gets "unreserved", simply moved the following code to a more
- * suitable spot...
- *
- * ia64_syscall_setup() is a separate subroutine so that it can
- * allocate stacked registers so it can safely demine any
- * potential NaT values from the input registers.
- *
- * On entry:
- * - executing on bank 0 or bank 1 register set (doesn't matter)
- * - r1: stack pointer
- * - r2: current task pointer
- * - r3: preserved
- * - r11: original contents (saved ar.pfs to be saved)
- * - r12: original contents (sp to be saved)
- * - r13: original contents (tp to be saved)
- * - r15: original contents (syscall # to be saved)
- * - r18: saved bsp (after switching to kernel stack)
- * - r19: saved b6
- * - r20: saved r1 (gp)
- * - r21: saved ar.fpsr
- * - r22: kernel's register backing store base (krbs_base)
- * - r23: saved ar.bspstore
- * - r24: saved ar.rnat
- * - r25: saved ar.unat
- * - r26: saved ar.pfs
- * - r27: saved ar.rsc
- * - r28: saved cr.iip
- * - r29: saved cr.ipsr
- * - r30: ar.itc for accounting (don't touch)
- * - r31: saved pr
- * - b0: original contents (to be saved)
- * On exit:
- * - p10: TRUE if syscall is invoked with more than 8 out
- * registers or r15's Nat is true
- * - r1: kernel's gp
- * - r3: preserved (same as on entry)
- * - r8: -EINVAL if p10 is true
- * - r12: points to kernel stack
- * - r13: points to current task
- * - r14: preserved (same as on entry)
- * - p13: preserved
- * - p15: TRUE if interrupts need to be re-enabled
- * - ar.fpsr: set to kernel settings
- * - b6: preserved (same as on entry)
- */
-GLOBAL_ENTRY(ia64_syscall_setup)
-#if PT(B6) != 0
-# error This code assumes that b6 is the first field in pt_regs.
-#endif
- st8 [r1]=r19 // save b6
- add r16=PT(CR_IPSR),r1 // initialize first base pointer
- add r17=PT(R11),r1 // initialize second base pointer
- ;;
- alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable
- st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr
- tnat.nz p8,p0=in0
-
- st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11
- tnat.nz p9,p0=in1
-(pKStk) mov r18=r0 // make sure r18 isn't NaT
- ;;
-
- st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs
- st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip
- mov r28=b0 // save b0 (2 cyc)
- ;;
-
- st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat
- dep r19=0,r19,38,26 // clear all bits but 0..37 [I0]
-(p8) mov in0=-1
- ;;
-
- st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs
- extr.u r11=r19,7,7 // I0 // get sol of ar.pfs
- and r8=0x7f,r19 // A // get sof of ar.pfs
-
- st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc
- tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0
-(p9) mov in1=-1
- ;;
-
-(pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8
- tnat.nz p10,p0=in2
- add r11=8,r11
- ;;
-(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field
-(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field
- tnat.nz p11,p0=in3
- ;;
-(p10) mov in2=-1
- tnat.nz p12,p0=in4 // [I0]
-(p11) mov in3=-1
- ;;
-(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat
-(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore
- shl r18=r18,16 // compute ar.rsc to be used for "loadrs"
- ;;
- st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates
- st8 [r17]=r28,PT(R1)-PT(B0) // save b0
- tnat.nz p13,p0=in5 // [I0]
- ;;
- st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs"
- st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1
-(p12) mov in4=-1
- ;;
-
-.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12
-.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13
-(p13) mov in5=-1
- ;;
- st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr
- tnat.nz p13,p0=in6
- cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8
- ;;
- mov r8=1
-(p9) tnat.nz p10,p0=r15
- adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch)
-
- st8.spill [r17]=r15 // save r15
- tnat.nz p8,p0=in7
- nop.i 0
-
- mov r13=r2 // establish `current'
- movl r1=__gp // establish kernel global pointer
- ;;
- st8 [r16]=r8 // ensure pt_regs.r8 != 0 (see handle_syscall_error)
-(p13) mov in6=-1
-(p8) mov in7=-1
-
- cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
- movl r17=FPSR_DEFAULT
- ;;
- mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value
-(p10) mov r8=-EINVAL
- br.ret.sptk.many b7
-END(ia64_syscall_setup)
-
- .org ia64_ivt+0x3c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x3c00 Entry 15 (size 64 bundles) Reserved
- DBG_FAULT(15)
- FAULT(15)
-
- .org ia64_ivt+0x4000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x4000 Entry 16 (size 64 bundles) Reserved
- DBG_FAULT(16)
- FAULT(16)
-
-#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE)
- /*
- * There is no particular reason for this code to be here, other than
- * that there happens to be space here that would go unused otherwise.
- * If this fault ever gets "unreserved", simply moved the following
- * code to a more suitable spot...
- *
- * account_sys_enter is called from SAVE_MIN* macros if accounting is
- * enabled and if the macro is entered from user mode.
- */
-GLOBAL_ENTRY(account_sys_enter)
- // mov.m r20=ar.itc is called in advance, and r13 is current
- add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13
- add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13
- ;;
- ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // time at last check in kernel
- ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // time at left from kernel
- ;;
- ld8 r23=[r16],TI_AC_STAMP-TI_AC_STIME // cumulated stime
- ld8 r21=[r17] // cumulated utime
- sub r22=r19,r18 // stime before leave kernel
- ;;
- st8 [r16]=r20,TI_AC_STIME-TI_AC_STAMP // update stamp
- sub r18=r20,r19 // elapsed time in user mode
- ;;
- add r23=r23,r22 // sum stime
- add r21=r21,r18 // sum utime
- ;;
- st8 [r16]=r23 // update stime
- st8 [r17]=r21 // update utime
- ;;
- br.ret.sptk.many rp
-END(account_sys_enter)
-#endif
-
- .org ia64_ivt+0x4400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x4400 Entry 17 (size 64 bundles) Reserved
- DBG_FAULT(17)
- FAULT(17)
-
- .org ia64_ivt+0x4800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x4800 Entry 18 (size 64 bundles) Reserved
- DBG_FAULT(18)
- FAULT(18)
-
- .org ia64_ivt+0x4c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x4c00 Entry 19 (size 64 bundles) Reserved
- DBG_FAULT(19)
- FAULT(19)
-
-//
-// --- End of long entries, Beginning of short entries
-//
-
- .org ia64_ivt+0x5000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
-ENTRY(page_not_present)
- DBG_FAULT(20)
- MOV_FROM_IFA(r16)
- RSM_PSR_DT
- /*
- * The Linux page fault handler doesn't expect non-present pages to be in
- * the TLB. Flush the existing entry now, so we meet that expectation.
- */
- mov r17=PAGE_SHIFT<<2
- ;;
- ptc.l r16,r17
- ;;
- mov r31=pr
- srlz.d
- br.sptk.many page_fault
-END(page_not_present)
-
- .org ia64_ivt+0x5100
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
-ENTRY(key_permission)
- DBG_FAULT(21)
- MOV_FROM_IFA(r16)
- RSM_PSR_DT
- mov r31=pr
- ;;
- srlz.d
- br.sptk.many page_fault
-END(key_permission)
-
- .org ia64_ivt+0x5200
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
-ENTRY(iaccess_rights)
- DBG_FAULT(22)
- MOV_FROM_IFA(r16)
- RSM_PSR_DT
- mov r31=pr
- ;;
- srlz.d
- br.sptk.many page_fault
-END(iaccess_rights)
-
- .org ia64_ivt+0x5300
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
-ENTRY(daccess_rights)
- DBG_FAULT(23)
- MOV_FROM_IFA(r16)
- RSM_PSR_DT
- mov r31=pr
- ;;
- srlz.d
- br.sptk.many page_fault
-END(daccess_rights)
-
- .org ia64_ivt+0x5400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
-ENTRY(general_exception)
- DBG_FAULT(24)
- MOV_FROM_ISR(r16)
- mov r31=pr
- ;;
- cmp4.eq p6,p0=0,r16
-(p6) br.sptk.many dispatch_illegal_op_fault
- ;;
- mov r19=24 // fault number
- br.sptk.many dispatch_to_fault_handler
-END(general_exception)
-
- .org ia64_ivt+0x5500
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
-ENTRY(disabled_fp_reg)
- DBG_FAULT(25)
- rsm psr.dfh // ensure we can access fph
- ;;
- srlz.d
- mov r31=pr
- mov r19=25
- br.sptk.many dispatch_to_fault_handler
-END(disabled_fp_reg)
-
- .org ia64_ivt+0x5600
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
-ENTRY(nat_consumption)
- DBG_FAULT(26)
-
- MOV_FROM_IPSR(p0, r16)
- MOV_FROM_ISR(r17)
- mov r31=pr // save PR
- ;;
- and r18=0xf,r17 // r18 = cr.ipsr.code{3:0}
- tbit.z p6,p0=r17,IA64_ISR_NA_BIT
- ;;
- cmp.ne.or p6,p0=IA64_ISR_CODE_LFETCH,r18
- dep r16=-1,r16,IA64_PSR_ED_BIT,1
-(p6) br.cond.spnt 1f // branch if (cr.ispr.na == 0 || cr.ipsr.code{3:0} != LFETCH)
- ;;
- MOV_TO_IPSR(p0, r16, r18)
- mov pr=r31,-1
- ;;
- RFI
-
-1: mov pr=r31,-1
- ;;
- FAULT(26)
-END(nat_consumption)
-
- .org ia64_ivt+0x5700
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
-ENTRY(speculation_vector)
- DBG_FAULT(27)
- /*
- * A [f]chk.[as] instruction needs to take the branch to the recovery code but
- * this part of the architecture is not implemented in hardware on some CPUs, such
- * as Itanium. Thus, in general we need to emulate the behavior. IIM contains
- * the relative target (not yet sign extended). So after sign extending it we
- * simply add it to IIP. We also need to reset the EI field of the IPSR to zero,
- * i.e., the slot to restart into.
- *
- * cr.imm contains zero_ext(imm21)
- */
- MOV_FROM_IIM(r18)
- ;;
- MOV_FROM_IIP(r17)
- shl r18=r18,43 // put sign bit in position (43=64-21)
- ;;
-
- MOV_FROM_IPSR(p0, r16)
- shr r18=r18,39 // sign extend (39=43-4)
- ;;
-
- add r17=r17,r18 // now add the offset
- ;;
- MOV_TO_IIP(r17, r19)
- dep r16=0,r16,41,2 // clear EI
- ;;
-
- MOV_TO_IPSR(p0, r16, r19)
- ;;
-
- RFI
-END(speculation_vector)
-
- .org ia64_ivt+0x5800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5800 Entry 28 (size 16 bundles) Reserved
- DBG_FAULT(28)
- FAULT(28)
-
- .org ia64_ivt+0x5900
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
-ENTRY(debug_vector)
- DBG_FAULT(29)
- FAULT(29)
-END(debug_vector)
-
- .org ia64_ivt+0x5a00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
-ENTRY(unaligned_access)
- DBG_FAULT(30)
- mov r31=pr // prepare to save predicates
- ;;
- br.sptk.many dispatch_unaligned_handler
-END(unaligned_access)
-
- .org ia64_ivt+0x5b00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
-ENTRY(unsupported_data_reference)
- DBG_FAULT(31)
- FAULT(31)
-END(unsupported_data_reference)
-
- .org ia64_ivt+0x5c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
-ENTRY(floating_point_fault)
- DBG_FAULT(32)
- FAULT(32)
-END(floating_point_fault)
-
- .org ia64_ivt+0x5d00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
-ENTRY(floating_point_trap)
- DBG_FAULT(33)
- FAULT(33)
-END(floating_point_trap)
-
- .org ia64_ivt+0x5e00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
-ENTRY(lower_privilege_trap)
- DBG_FAULT(34)
- FAULT(34)
-END(lower_privilege_trap)
-
- .org ia64_ivt+0x5f00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
-ENTRY(taken_branch_trap)
- DBG_FAULT(35)
- FAULT(35)
-END(taken_branch_trap)
-
- .org ia64_ivt+0x6000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
-ENTRY(single_step_trap)
- DBG_FAULT(36)
- FAULT(36)
-END(single_step_trap)
-
- .org ia64_ivt+0x6100
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6100 Entry 37 (size 16 bundles) Reserved
- DBG_FAULT(37)
- FAULT(37)
-
- .org ia64_ivt+0x6200
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6200 Entry 38 (size 16 bundles) Reserved
- DBG_FAULT(38)
- FAULT(38)
-
- .org ia64_ivt+0x6300
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6300 Entry 39 (size 16 bundles) Reserved
- DBG_FAULT(39)
- FAULT(39)
-
- .org ia64_ivt+0x6400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6400 Entry 40 (size 16 bundles) Reserved
- DBG_FAULT(40)
- FAULT(40)
-
- .org ia64_ivt+0x6500
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6500 Entry 41 (size 16 bundles) Reserved
- DBG_FAULT(41)
- FAULT(41)
-
- .org ia64_ivt+0x6600
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6600 Entry 42 (size 16 bundles) Reserved
- DBG_FAULT(42)
- FAULT(42)
-
- .org ia64_ivt+0x6700
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6700 Entry 43 (size 16 bundles) Reserved
- DBG_FAULT(43)
- FAULT(43)
-
- .org ia64_ivt+0x6800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6800 Entry 44 (size 16 bundles) Reserved
- DBG_FAULT(44)
- FAULT(44)
-
- .org ia64_ivt+0x6900
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
-ENTRY(ia32_exception)
- DBG_FAULT(45)
- FAULT(45)
-END(ia32_exception)
-
- .org ia64_ivt+0x6a00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71)
-ENTRY(ia32_intercept)
- DBG_FAULT(46)
- FAULT(46)
-END(ia32_intercept)
-
- .org ia64_ivt+0x6b00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74)
-ENTRY(ia32_interrupt)
- DBG_FAULT(47)
- FAULT(47)
-END(ia32_interrupt)
-
- .org ia64_ivt+0x6c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6c00 Entry 48 (size 16 bundles) Reserved
- DBG_FAULT(48)
- FAULT(48)
-
- .org ia64_ivt+0x6d00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6d00 Entry 49 (size 16 bundles) Reserved
- DBG_FAULT(49)
- FAULT(49)
-
- .org ia64_ivt+0x6e00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6e00 Entry 50 (size 16 bundles) Reserved
- DBG_FAULT(50)
- FAULT(50)
-
- .org ia64_ivt+0x6f00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6f00 Entry 51 (size 16 bundles) Reserved
- DBG_FAULT(51)
- FAULT(51)
-
- .org ia64_ivt+0x7000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7000 Entry 52 (size 16 bundles) Reserved
- DBG_FAULT(52)
- FAULT(52)
-
- .org ia64_ivt+0x7100
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7100 Entry 53 (size 16 bundles) Reserved
- DBG_FAULT(53)
- FAULT(53)
-
- .org ia64_ivt+0x7200
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7200 Entry 54 (size 16 bundles) Reserved
- DBG_FAULT(54)
- FAULT(54)
-
- .org ia64_ivt+0x7300
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7300 Entry 55 (size 16 bundles) Reserved
- DBG_FAULT(55)
- FAULT(55)
-
- .org ia64_ivt+0x7400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7400 Entry 56 (size 16 bundles) Reserved
- DBG_FAULT(56)
- FAULT(56)
-
- .org ia64_ivt+0x7500
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7500 Entry 57 (size 16 bundles) Reserved
- DBG_FAULT(57)
- FAULT(57)
-
- .org ia64_ivt+0x7600
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7600 Entry 58 (size 16 bundles) Reserved
- DBG_FAULT(58)
- FAULT(58)
-
- .org ia64_ivt+0x7700
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7700 Entry 59 (size 16 bundles) Reserved
- DBG_FAULT(59)
- FAULT(59)
-
- .org ia64_ivt+0x7800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7800 Entry 60 (size 16 bundles) Reserved
- DBG_FAULT(60)
- FAULT(60)
-
- .org ia64_ivt+0x7900
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7900 Entry 61 (size 16 bundles) Reserved
- DBG_FAULT(61)
- FAULT(61)
-
- .org ia64_ivt+0x7a00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7a00 Entry 62 (size 16 bundles) Reserved
- DBG_FAULT(62)
- FAULT(62)
-
- .org ia64_ivt+0x7b00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7b00 Entry 63 (size 16 bundles) Reserved
- DBG_FAULT(63)
- FAULT(63)
-
- .org ia64_ivt+0x7c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7c00 Entry 64 (size 16 bundles) Reserved
- DBG_FAULT(64)
- FAULT(64)
-
- .org ia64_ivt+0x7d00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7d00 Entry 65 (size 16 bundles) Reserved
- DBG_FAULT(65)
- FAULT(65)
-
- .org ia64_ivt+0x7e00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7e00 Entry 66 (size 16 bundles) Reserved
- DBG_FAULT(66)
- FAULT(66)
-
- .org ia64_ivt+0x7f00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7f00 Entry 67 (size 16 bundles) Reserved
- DBG_FAULT(67)
- FAULT(67)
-
- //-----------------------------------------------------------------------------------
- // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
-ENTRY(page_fault)
- SSM_PSR_DT_AND_SRLZ_I
- ;;
- SAVE_MIN_WITH_COVER
- alloc r15=ar.pfs,0,0,3,0
- MOV_FROM_IFA(out0)
- MOV_FROM_ISR(out1)
- SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r14, r3)
- adds r3=8,r2 // set up second base pointer
- SSM_PSR_I(p15, p15, r14) // restore psr.i
- movl r14=ia64_leave_kernel
- ;;
- SAVE_REST
- mov rp=r14
- ;;
- adds out2=16,r12 // out2 = pointer to pt_regs
- br.call.sptk.many b6=ia64_do_page_fault // ignore return address
-END(page_fault)
-
-ENTRY(non_syscall)
- mov ar.rsc=r27 // restore ar.rsc before SAVE_MIN_WITH_COVER
- ;;
- SAVE_MIN_WITH_COVER
-
- // There is no particular reason for this code to be here, other than that
- // there happens to be space here that would go unused otherwise. If this
- // fault ever gets "unreserved", simply moved the following code to a more
- // suitable spot...
-
- alloc r14=ar.pfs,0,0,2,0
- MOV_FROM_IIM(out0)
- add out1=16,sp
- adds r3=8,r2 // set up second base pointer for SAVE_REST
-
- SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r15, r24)
- // guarantee that interruption collection is on
- SSM_PSR_I(p15, p15, r15) // restore psr.i
- movl r15=ia64_leave_kernel
- ;;
- SAVE_REST
- mov rp=r15
- ;;
- br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr
-END(non_syscall)
-
-ENTRY(__interrupt)
- DBG_FAULT(12)
- mov r31=pr // prepare to save predicates
- ;;
- SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3
- SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r14)
- // ensure everybody knows psr.ic is back on
- adds r3=8,r2 // set up second base pointer for SAVE_REST
- ;;
- SAVE_REST
- ;;
- MCA_RECOVER_RANGE(interrupt)
- alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
- MOV_FROM_IVR(out0, r8) // pass cr.ivr as first arg
- add out1=16,sp // pass pointer to pt_regs as second arg
- ;;
- srlz.d // make sure we see the effect of cr.ivr
- movl r14=ia64_leave_kernel
- ;;
- mov rp=r14
- br.call.sptk.many b6=ia64_handle_irq
-END(__interrupt)
-
- /*
- * There is no particular reason for this code to be here, other than that
- * there happens to be space here that would go unused otherwise. If this
- * fault ever gets "unreserved", simply moved the following code to a more
- * suitable spot...
- */
-
-ENTRY(dispatch_unaligned_handler)
- SAVE_MIN_WITH_COVER
- ;;
- alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
- MOV_FROM_IFA(out0)
- adds out1=16,sp
-
- SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24)
- // guarantee that interruption collection is on
- SSM_PSR_I(p15, p15, r3) // restore psr.i
- adds r3=8,r2 // set up second base pointer
- ;;
- SAVE_REST
- movl r14=ia64_leave_kernel
- ;;
- mov rp=r14
- br.sptk.many ia64_prepare_handle_unaligned
-END(dispatch_unaligned_handler)
-
- /*
- * There is no particular reason for this code to be here, other than that
- * there happens to be space here that would go unused otherwise. If this
- * fault ever gets "unreserved", simply moved the following code to a more
- * suitable spot...
- */
-
-ENTRY(dispatch_to_fault_handler)
- /*
- * Input:
- * psr.ic: off
- * r19: fault vector number (e.g., 24 for General Exception)
- * r31: contains saved predicates (pr)
- */
- SAVE_MIN_WITH_COVER_R19
- alloc r14=ar.pfs,0,0,5,0
- MOV_FROM_ISR(out1)
- MOV_FROM_IFA(out2)
- MOV_FROM_IIM(out3)
- MOV_FROM_ITIR(out4)
- ;;
- SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, out0)
- // guarantee that interruption collection is on
- mov out0=r15
- ;;
- SSM_PSR_I(p15, p15, r3) // restore psr.i
- adds r3=8,r2 // set up second base pointer for SAVE_REST
- ;;
- SAVE_REST
- movl r14=ia64_leave_kernel
- ;;
- mov rp=r14
- br.call.sptk.many b6=ia64_fault
-END(dispatch_to_fault_handler)
-
- /*
- * Squatting in this space ...
- *
- * This special case dispatcher for illegal operation faults allows preserved
- * registers to be modified through a callback function (asm only) that is handed
- * back from the fault handler in r8. Up to three arguments can be passed to the
- * callback function by returning an aggregate with the callback as its first
- * element, followed by the arguments.
- */
-ENTRY(dispatch_illegal_op_fault)
- .prologue
- .body
- SAVE_MIN_WITH_COVER
- SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24)
- // guarantee that interruption collection is on
- ;;
- SSM_PSR_I(p15, p15, r3) // restore psr.i
- adds r3=8,r2 // set up second base pointer for SAVE_REST
- ;;
- alloc r14=ar.pfs,0,0,1,0 // must be first in insn group
- mov out0=ar.ec
- ;;
- SAVE_REST
- PT_REGS_UNWIND_INFO(0)
- ;;
- br.call.sptk.many rp=ia64_illegal_op_fault
-.ret0: ;;
- alloc r14=ar.pfs,0,0,3,0 // must be first in insn group
- mov out0=r9
- mov out1=r10
- mov out2=r11
- movl r15=ia64_leave_kernel
- ;;
- mov rp=r15
- mov b6=r8
- ;;
- cmp.ne p6,p0=0,r8
-(p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel
- br.sptk.many ia64_leave_kernel
-END(dispatch_illegal_op_fault)
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
deleted file mode 100644
index ca34e51e84b4..000000000000
--- a/arch/ia64/kernel/kprobes.c
+++ /dev/null
@@ -1,911 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Kernel Probes (KProbes)
- * arch/ia64/kernel/kprobes.c
- *
- * Copyright (C) IBM Corporation, 2002, 2004
- * Copyright (C) Intel Corporation, 2005
- *
- * 2005-Apr Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
- * <anil.s.keshavamurthy@intel.com> adapted from i386
- */
-
-#include <linux/kprobes.h>
-#include <linux/ptrace.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/preempt.h>
-#include <linux/extable.h>
-#include <linux/kdebug.h>
-#include <linux/pgtable.h>
-
-#include <asm/sections.h>
-#include <asm/exception.h>
-
-DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
-DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
-
-struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
-
-enum instruction_type {A, I, M, F, B, L, X, u};
-static enum instruction_type bundle_encoding[32][3] = {
- [0x00] = { M, I, I },
- [0x01] = { M, I, I },
- [0x02] = { M, I, I },
- [0x03] = { M, I, I },
- [0x04] = { M, L, X },
- [0x05] = { M, L, X },
- [0x06] = { u, u, u },
- [0x07] = { u, u, u },
- [0x08] = { M, M, I },
- [0x09] = { M, M, I },
- [0x0A] = { M, M, I },
- [0x0B] = { M, M, I },
- [0x0C] = { M, F, I },
- [0x0D] = { M, F, I },
- [0x0E] = { M, M, F },
- [0x0F] = { M, M, F },
- [0x10] = { M, I, B },
- [0x11] = { M, I, B },
- [0x12] = { M, B, B },
- [0x13] = { M, B, B },
- [0x14] = { u, u, u },
- [0x15] = { u, u, u },
- [0x16] = { B, B, B },
- [0x17] = { B, B, B },
- [0x18] = { M, M, B },
- [0x19] = { M, M, B },
- [0x1A] = { u, u, u },
- [0x1B] = { u, u, u },
- [0x1C] = { M, F, B },
- [0x1D] = { M, F, B },
- [0x1E] = { u, u, u },
- [0x1F] = { u, u, u },
-};
-
-/* Insert a long branch code */
-static void __kprobes set_brl_inst(void *from, void *to)
-{
- s64 rel = ((s64) to - (s64) from) >> 4;
- bundle_t *brl;
- brl = (bundle_t *) ((u64) from & ~0xf);
- brl->quad0.template = 0x05; /* [MLX](stop) */
- brl->quad0.slot0 = NOP_M_INST; /* nop.m 0x0 */
- brl->quad0.slot1_p0 = ((rel >> 20) & 0x7fffffffff) << 2;
- brl->quad1.slot1_p1 = (((rel >> 20) & 0x7fffffffff) << 2) >> (64 - 46);
- /* brl.cond.sptk.many.clr rel<<4 (qp=0) */
- brl->quad1.slot2 = BRL_INST(rel >> 59, rel & 0xfffff);
-}
-
-/*
- * In this function we check to see if the instruction
- * is IP relative instruction and update the kprobe
- * inst flag accordingly
- */
-static void __kprobes update_kprobe_inst_flag(uint template, uint slot,
- uint major_opcode,
- unsigned long kprobe_inst,
- struct kprobe *p)
-{
- p->ainsn.inst_flag = 0;
- p->ainsn.target_br_reg = 0;
- p->ainsn.slot = slot;
-
- /* Check for Break instruction
- * Bits 37:40 Major opcode to be zero
- * Bits 27:32 X6 to be zero
- * Bits 32:35 X3 to be zero
- */
- if ((!major_opcode) && (!((kprobe_inst >> 27) & 0x1FF)) ) {
- /* is a break instruction */
- p->ainsn.inst_flag |= INST_FLAG_BREAK_INST;
- return;
- }
-
- if (bundle_encoding[template][slot] == B) {
- switch (major_opcode) {
- case INDIRECT_CALL_OPCODE:
- p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG;
- p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7);
- break;
- case IP_RELATIVE_PREDICT_OPCODE:
- case IP_RELATIVE_BRANCH_OPCODE:
- p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR;
- break;
- case IP_RELATIVE_CALL_OPCODE:
- p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR;
- p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG;
- p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7);
- break;
- }
- } else if (bundle_encoding[template][slot] == X) {
- switch (major_opcode) {
- case LONG_CALL_OPCODE:
- p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG;
- p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7);
- break;
- }
- }
- return;
-}
-
-/*
- * In this function we check to see if the instruction
- * (qp) cmpx.crel.ctype p1,p2=r2,r3
- * on which we are inserting kprobe is cmp instruction
- * with ctype as unc.
- */
-static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot,
- uint major_opcode,
- unsigned long kprobe_inst)
-{
- cmp_inst_t cmp_inst;
- uint ctype_unc = 0;
-
- if (!((bundle_encoding[template][slot] == I) ||
- (bundle_encoding[template][slot] == M)))
- goto out;
-
- if (!((major_opcode == 0xC) || (major_opcode == 0xD) ||
- (major_opcode == 0xE)))
- goto out;
-
- cmp_inst.l = kprobe_inst;
- if ((cmp_inst.f.x2 == 0) || (cmp_inst.f.x2 == 1)) {
- /* Integer compare - Register Register (A6 type)*/
- if ((cmp_inst.f.tb == 0) && (cmp_inst.f.ta == 0)
- &&(cmp_inst.f.c == 1))
- ctype_unc = 1;
- } else if ((cmp_inst.f.x2 == 2)||(cmp_inst.f.x2 == 3)) {
- /* Integer compare - Immediate Register (A8 type)*/
- if ((cmp_inst.f.ta == 0) &&(cmp_inst.f.c == 1))
- ctype_unc = 1;
- }
-out:
- return ctype_unc;
-}
-
-/*
- * In this function we check to see if the instruction
- * on which we are inserting kprobe is supported.
- * Returns qp value if supported
- * Returns -EINVAL if unsupported
- */
-static int __kprobes unsupported_inst(uint template, uint slot,
- uint major_opcode,
- unsigned long kprobe_inst,
- unsigned long addr)
-{
- int qp;
-
- qp = kprobe_inst & 0x3f;
- if (is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) {
- if (slot == 1 && qp) {
- printk(KERN_WARNING "Kprobes on cmp unc "
- "instruction on slot 1 at <0x%lx> "
- "is not supported\n", addr);
- return -EINVAL;
-
- }
- qp = 0;
- }
- else if (bundle_encoding[template][slot] == I) {
- if (major_opcode == 0) {
- /*
- * Check for Integer speculation instruction
- * - Bit 33-35 to be equal to 0x1
- */
- if (((kprobe_inst >> 33) & 0x7) == 1) {
- printk(KERN_WARNING
- "Kprobes on speculation inst at <0x%lx> not supported\n",
- addr);
- return -EINVAL;
- }
- /*
- * IP relative mov instruction
- * - Bit 27-35 to be equal to 0x30
- */
- if (((kprobe_inst >> 27) & 0x1FF) == 0x30) {
- printk(KERN_WARNING
- "Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n",
- addr);
- return -EINVAL;
-
- }
- }
- else if ((major_opcode == 5) && !(kprobe_inst & (0xFUl << 33)) &&
- (kprobe_inst & (0x1UL << 12))) {
- /* test bit instructions, tbit,tnat,tf
- * bit 33-36 to be equal to 0
- * bit 12 to be equal to 1
- */
- if (slot == 1 && qp) {
- printk(KERN_WARNING "Kprobes on test bit "
- "instruction on slot at <0x%lx> "
- "is not supported\n", addr);
- return -EINVAL;
- }
- qp = 0;
- }
- }
- else if (bundle_encoding[template][slot] == B) {
- if (major_opcode == 7) {
- /* IP-Relative Predict major code is 7 */
- printk(KERN_WARNING "Kprobes on IP-Relative"
- "Predict is not supported\n");
- return -EINVAL;
- }
- else if (major_opcode == 2) {
- /* Indirect Predict, major code is 2
- * bit 27-32 to be equal to 10 or 11
- */
- int x6=(kprobe_inst >> 27) & 0x3F;
- if ((x6 == 0x10) || (x6 == 0x11)) {
- printk(KERN_WARNING "Kprobes on "
- "Indirect Predict is not supported\n");
- return -EINVAL;
- }
- }
- }
- /* kernel does not use float instruction, here for safety kprobe
- * will judge whether it is fcmp/flass/float approximation instruction
- */
- else if (unlikely(bundle_encoding[template][slot] == F)) {
- if ((major_opcode == 4 || major_opcode == 5) &&
- (kprobe_inst & (0x1 << 12))) {
- /* fcmp/fclass unc instruction */
- if (slot == 1 && qp) {
- printk(KERN_WARNING "Kprobes on fcmp/fclass "
- "instruction on slot at <0x%lx> "
- "is not supported\n", addr);
- return -EINVAL;
-
- }
- qp = 0;
- }
- if ((major_opcode == 0 || major_opcode == 1) &&
- (kprobe_inst & (0x1UL << 33))) {
- /* float Approximation instruction */
- if (slot == 1 && qp) {
- printk(KERN_WARNING "Kprobes on float Approx "
- "instr at <0x%lx> is not supported\n",
- addr);
- return -EINVAL;
- }
- qp = 0;
- }
- }
- return qp;
-}
-
-/*
- * In this function we override the bundle with
- * the break instruction at the given slot.
- */
-static void __kprobes prepare_break_inst(uint template, uint slot,
- uint major_opcode,
- unsigned long kprobe_inst,
- struct kprobe *p,
- int qp)
-{
- unsigned long break_inst = BREAK_INST;
- bundle_t *bundle = &p->opcode.bundle;
-
- /*
- * Copy the original kprobe_inst qualifying predicate(qp)
- * to the break instruction
- */
- break_inst |= qp;
-
- switch (slot) {
- case 0:
- bundle->quad0.slot0 = break_inst;
- break;
- case 1:
- bundle->quad0.slot1_p0 = break_inst;
- bundle->quad1.slot1_p1 = break_inst >> (64-46);
- break;
- case 2:
- bundle->quad1.slot2 = break_inst;
- break;
- }
-
- /*
- * Update the instruction flag, so that we can
- * emulate the instruction properly after we
- * single step on original instruction
- */
- update_kprobe_inst_flag(template, slot, major_opcode, kprobe_inst, p);
-}
-
-static void __kprobes get_kprobe_inst(bundle_t *bundle, uint slot,
- unsigned long *kprobe_inst, uint *major_opcode)
-{
- unsigned long kprobe_inst_p0, kprobe_inst_p1;
- unsigned int template;
-
- template = bundle->quad0.template;
-
- switch (slot) {
- case 0:
- *major_opcode = (bundle->quad0.slot0 >> SLOT0_OPCODE_SHIFT);
- *kprobe_inst = bundle->quad0.slot0;
- break;
- case 1:
- *major_opcode = (bundle->quad1.slot1_p1 >> SLOT1_p1_OPCODE_SHIFT);
- kprobe_inst_p0 = bundle->quad0.slot1_p0;
- kprobe_inst_p1 = bundle->quad1.slot1_p1;
- *kprobe_inst = kprobe_inst_p0 | (kprobe_inst_p1 << (64-46));
- break;
- case 2:
- *major_opcode = (bundle->quad1.slot2 >> SLOT2_OPCODE_SHIFT);
- *kprobe_inst = bundle->quad1.slot2;
- break;
- }
-}
-
-/* Returns non-zero if the addr is in the Interrupt Vector Table */
-static int __kprobes in_ivt_functions(unsigned long addr)
-{
- return (addr >= (unsigned long)__start_ivt_text
- && addr < (unsigned long)__end_ivt_text);
-}
-
-static int __kprobes valid_kprobe_addr(int template, int slot,
- unsigned long addr)
-{
- if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) {
- printk(KERN_WARNING "Attempting to insert unaligned kprobe "
- "at 0x%lx\n", addr);
- return -EINVAL;
- }
-
- if (in_ivt_functions(addr)) {
- printk(KERN_WARNING "Kprobes can't be inserted inside "
- "IVT functions at 0x%lx\n", addr);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
-{
- unsigned int i;
- i = atomic_add_return(1, &kcb->prev_kprobe_index);
- kcb->prev_kprobe[i-1].kp = kprobe_running();
- kcb->prev_kprobe[i-1].status = kcb->kprobe_status;
-}
-
-static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
-{
- unsigned int i;
- i = atomic_read(&kcb->prev_kprobe_index);
- __this_cpu_write(current_kprobe, kcb->prev_kprobe[i-1].kp);
- kcb->kprobe_status = kcb->prev_kprobe[i-1].status;
- atomic_sub(1, &kcb->prev_kprobe_index);
-}
-
-static void __kprobes set_current_kprobe(struct kprobe *p,
- struct kprobe_ctlblk *kcb)
-{
- __this_cpu_write(current_kprobe, p);
-}
-
-void __kretprobe_trampoline(void)
-{
-}
-
-int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
-{
- regs->cr_iip = __kretprobe_trampoline_handler(regs, NULL);
- /*
- * By returning a non-zero value, we are telling
- * kprobe_handler() that we don't want the post_handler
- * to run (and have re-enabled preemption)
- */
- return 1;
-}
-
-void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
- struct pt_regs *regs)
-{
- ri->ret_addr = (kprobe_opcode_t *)regs->b0;
- ri->fp = NULL;
-
- /* Replace the return addr with trampoline addr */
- regs->b0 = (unsigned long)dereference_function_descriptor(__kretprobe_trampoline);
-}
-
-/* Check the instruction in the slot is break */
-static int __kprobes __is_ia64_break_inst(bundle_t *bundle, uint slot)
-{
- unsigned int major_opcode;
- unsigned int template = bundle->quad0.template;
- unsigned long kprobe_inst;
-
- /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
- if (slot == 1 && bundle_encoding[template][1] == L)
- slot++;
-
- /* Get Kprobe probe instruction at given slot*/
- get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
-
- /* For break instruction,
- * Bits 37:40 Major opcode to be zero
- * Bits 27:32 X6 to be zero
- * Bits 32:35 X3 to be zero
- */
- if (major_opcode || ((kprobe_inst >> 27) & 0x1FF)) {
- /* Not a break instruction */
- return 0;
- }
-
- /* Is a break instruction */
- return 1;
-}
-
-/*
- * In this function, we check whether the target bundle modifies IP or
- * it triggers an exception. If so, it cannot be boostable.
- */
-static int __kprobes can_boost(bundle_t *bundle, uint slot,
- unsigned long bundle_addr)
-{
- unsigned int template = bundle->quad0.template;
-
- do {
- if (search_exception_tables(bundle_addr + slot) ||
- __is_ia64_break_inst(bundle, slot))
- return 0; /* exception may occur in this bundle*/
- } while ((++slot) < 3);
- template &= 0x1e;
- if (template >= 0x10 /* including B unit */ ||
- template == 0x04 /* including X unit */ ||
- template == 0x06) /* undefined */
- return 0;
-
- return 1;
-}
-
-/* Prepare long jump bundle and disables other boosters if need */
-static void __kprobes prepare_booster(struct kprobe *p)
-{
- unsigned long addr = (unsigned long)p->addr & ~0xFULL;
- unsigned int slot = (unsigned long)p->addr & 0xf;
- struct kprobe *other_kp;
-
- if (can_boost(&p->ainsn.insn[0].bundle, slot, addr)) {
- set_brl_inst(&p->ainsn.insn[1].bundle, (bundle_t *)addr + 1);
- p->ainsn.inst_flag |= INST_FLAG_BOOSTABLE;
- }
-
- /* disables boosters in previous slots */
- for (; addr < (unsigned long)p->addr; addr++) {
- other_kp = get_kprobe((void *)addr);
- if (other_kp)
- other_kp->ainsn.inst_flag &= ~INST_FLAG_BOOSTABLE;
- }
-}
-
-int __kprobes arch_prepare_kprobe(struct kprobe *p)
-{
- unsigned long addr = (unsigned long) p->addr;
- unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL);
- unsigned long kprobe_inst=0;
- unsigned int slot = addr & 0xf, template, major_opcode = 0;
- bundle_t *bundle;
- int qp;
-
- bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle;
- template = bundle->quad0.template;
-
- if(valid_kprobe_addr(template, slot, addr))
- return -EINVAL;
-
- /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
- if (slot == 1 && bundle_encoding[template][1] == L)
- slot++;
-
- /* Get kprobe_inst and major_opcode from the bundle */
- get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
-
- qp = unsupported_inst(template, slot, major_opcode, kprobe_inst, addr);
- if (qp < 0)
- return -EINVAL;
-
- p->ainsn.insn = get_insn_slot();
- if (!p->ainsn.insn)
- return -ENOMEM;
- memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t));
- memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t));
-
- prepare_break_inst(template, slot, major_opcode, kprobe_inst, p, qp);
-
- prepare_booster(p);
-
- return 0;
-}
-
-void __kprobes arch_arm_kprobe(struct kprobe *p)
-{
- unsigned long arm_addr;
- bundle_t *src, *dest;
-
- arm_addr = ((unsigned long)p->addr) & ~0xFUL;
- dest = &((kprobe_opcode_t *)arm_addr)->bundle;
- src = &p->opcode.bundle;
-
- flush_icache_range((unsigned long)p->ainsn.insn,
- (unsigned long)p->ainsn.insn +
- sizeof(kprobe_opcode_t) * MAX_INSN_SIZE);
-
- switch (p->ainsn.slot) {
- case 0:
- dest->quad0.slot0 = src->quad0.slot0;
- break;
- case 1:
- dest->quad1.slot1_p1 = src->quad1.slot1_p1;
- break;
- case 2:
- dest->quad1.slot2 = src->quad1.slot2;
- break;
- }
- flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
-}
-
-void __kprobes arch_disarm_kprobe(struct kprobe *p)
-{
- unsigned long arm_addr;
- bundle_t *src, *dest;
-
- arm_addr = ((unsigned long)p->addr) & ~0xFUL;
- dest = &((kprobe_opcode_t *)arm_addr)->bundle;
- /* p->ainsn.insn contains the original unaltered kprobe_opcode_t */
- src = &p->ainsn.insn->bundle;
- switch (p->ainsn.slot) {
- case 0:
- dest->quad0.slot0 = src->quad0.slot0;
- break;
- case 1:
- dest->quad1.slot1_p1 = src->quad1.slot1_p1;
- break;
- case 2:
- dest->quad1.slot2 = src->quad1.slot2;
- break;
- }
- flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
-}
-
-void __kprobes arch_remove_kprobe(struct kprobe *p)
-{
- if (p->ainsn.insn) {
- free_insn_slot(p->ainsn.insn,
- p->ainsn.inst_flag & INST_FLAG_BOOSTABLE);
- p->ainsn.insn = NULL;
- }
-}
-/*
- * We are resuming execution after a single step fault, so the pt_regs
- * structure reflects the register state after we executed the instruction
- * located in the kprobe (p->ainsn.insn->bundle). We still need to adjust
- * the ip to point back to the original stack address. To set the IP address
- * to original stack address, handle the case where we need to fixup the
- * relative IP address and/or fixup branch register.
- */
-static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
-{
- unsigned long bundle_addr = (unsigned long) (&p->ainsn.insn->bundle);
- unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL;
- unsigned long template;
- int slot = ((unsigned long)p->addr & 0xf);
-
- template = p->ainsn.insn->bundle.quad0.template;
-
- if (slot == 1 && bundle_encoding[template][1] == L)
- slot = 2;
-
- if (p->ainsn.inst_flag & ~INST_FLAG_BOOSTABLE) {
-
- if (p->ainsn.inst_flag & INST_FLAG_FIX_RELATIVE_IP_ADDR) {
- /* Fix relative IP address */
- regs->cr_iip = (regs->cr_iip - bundle_addr) +
- resume_addr;
- }
-
- if (p->ainsn.inst_flag & INST_FLAG_FIX_BRANCH_REG) {
- /*
- * Fix target branch register, software convention is
- * to use either b0 or b6 or b7, so just checking
- * only those registers
- */
- switch (p->ainsn.target_br_reg) {
- case 0:
- if ((regs->b0 == bundle_addr) ||
- (regs->b0 == bundle_addr + 0x10)) {
- regs->b0 = (regs->b0 - bundle_addr) +
- resume_addr;
- }
- break;
- case 6:
- if ((regs->b6 == bundle_addr) ||
- (regs->b6 == bundle_addr + 0x10)) {
- regs->b6 = (regs->b6 - bundle_addr) +
- resume_addr;
- }
- break;
- case 7:
- if ((regs->b7 == bundle_addr) ||
- (regs->b7 == bundle_addr + 0x10)) {
- regs->b7 = (regs->b7 - bundle_addr) +
- resume_addr;
- }
- break;
- } /* end switch */
- }
- goto turn_ss_off;
- }
-
- if (slot == 2) {
- if (regs->cr_iip == bundle_addr + 0x10) {
- regs->cr_iip = resume_addr + 0x10;
- }
- } else {
- if (regs->cr_iip == bundle_addr) {
- regs->cr_iip = resume_addr;
- }
- }
-
-turn_ss_off:
- /* Turn off Single Step bit */
- ia64_psr(regs)->ss = 0;
-}
-
-static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
-{
- unsigned long bundle_addr = (unsigned long) &p->ainsn.insn->bundle;
- unsigned long slot = (unsigned long)p->addr & 0xf;
-
- /* single step inline if break instruction */
- if (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)
- regs->cr_iip = (unsigned long)p->addr & ~0xFULL;
- else
- regs->cr_iip = bundle_addr & ~0xFULL;
-
- if (slot > 2)
- slot = 0;
-
- ia64_psr(regs)->ri = slot;
-
- /* turn on single stepping */
- ia64_psr(regs)->ss = 1;
-}
-
-static int __kprobes is_ia64_break_inst(struct pt_regs *regs)
-{
- unsigned int slot = ia64_psr(regs)->ri;
- unsigned long *kprobe_addr = (unsigned long *)regs->cr_iip;
- bundle_t bundle;
-
- memcpy(&bundle, kprobe_addr, sizeof(bundle_t));
-
- return __is_ia64_break_inst(&bundle, slot);
-}
-
-static int __kprobes pre_kprobes_handler(struct die_args *args)
-{
- struct kprobe *p;
- int ret = 0;
- struct pt_regs *regs = args->regs;
- kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs);
- struct kprobe_ctlblk *kcb;
-
- /*
- * We don't want to be preempted for the entire
- * duration of kprobe processing
- */
- preempt_disable();
- kcb = get_kprobe_ctlblk();
-
- /* Handle recursion cases */
- if (kprobe_running()) {
- p = get_kprobe(addr);
- if (p) {
- if ((kcb->kprobe_status == KPROBE_HIT_SS) &&
- (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) {
- ia64_psr(regs)->ss = 0;
- goto no_kprobe;
- }
- /* We have reentered the pre_kprobe_handler(), since
- * another probe was hit while within the handler.
- * We here save the original kprobes variables and
- * just single step on the instruction of the new probe
- * without calling any user handlers.
- */
- save_previous_kprobe(kcb);
- set_current_kprobe(p, kcb);
- kprobes_inc_nmissed_count(p);
- prepare_ss(p, regs);
- kcb->kprobe_status = KPROBE_REENTER;
- return 1;
- } else if (!is_ia64_break_inst(regs)) {
- /* The breakpoint instruction was removed by
- * another cpu right after we hit, no further
- * handling of this interrupt is appropriate
- */
- ret = 1;
- goto no_kprobe;
- } else {
- /* Not our break */
- goto no_kprobe;
- }
- }
-
- p = get_kprobe(addr);
- if (!p) {
- if (!is_ia64_break_inst(regs)) {
- /*
- * The breakpoint instruction was removed right
- * after we hit it. Another cpu has removed
- * either a probepoint or a debugger breakpoint
- * at this address. In either case, no further
- * handling of this interrupt is appropriate.
- */
- ret = 1;
-
- }
-
- /* Not one of our break, let kernel handle it */
- goto no_kprobe;
- }
-
- set_current_kprobe(p, kcb);
- kcb->kprobe_status = KPROBE_HIT_ACTIVE;
-
- if (p->pre_handler && p->pre_handler(p, regs)) {
- reset_current_kprobe();
- preempt_enable_no_resched();
- return 1;
- }
-
-#if !defined(CONFIG_PREEMPTION)
- if (p->ainsn.inst_flag == INST_FLAG_BOOSTABLE && !p->post_handler) {
- /* Boost up -- we can execute copied instructions directly */
- ia64_psr(regs)->ri = p->ainsn.slot;
- regs->cr_iip = (unsigned long)&p->ainsn.insn->bundle & ~0xFULL;
- /* turn single stepping off */
- ia64_psr(regs)->ss = 0;
-
- reset_current_kprobe();
- preempt_enable_no_resched();
- return 1;
- }
-#endif
- prepare_ss(p, regs);
- kcb->kprobe_status = KPROBE_HIT_SS;
- return 1;
-
-no_kprobe:
- preempt_enable_no_resched();
- return ret;
-}
-
-static int __kprobes post_kprobes_handler(struct pt_regs *regs)
-{
- struct kprobe *cur = kprobe_running();
- struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-
- if (!cur)
- return 0;
-
- if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
- kcb->kprobe_status = KPROBE_HIT_SSDONE;
- cur->post_handler(cur, regs, 0);
- }
-
- resume_execution(cur, regs);
-
- /*Restore back the original saved kprobes variables and continue. */
- if (kcb->kprobe_status == KPROBE_REENTER) {
- restore_previous_kprobe(kcb);
- goto out;
- }
- reset_current_kprobe();
-
-out:
- preempt_enable_no_resched();
- return 1;
-}
-
-int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
-{
- struct kprobe *cur = kprobe_running();
- struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-
-
- switch(kcb->kprobe_status) {
- case KPROBE_HIT_SS:
- case KPROBE_REENTER:
- /*
- * We are here because the instruction being single
- * stepped caused a page fault. We reset the current
- * kprobe and the instruction pointer points back to
- * the probe address and allow the page fault handler
- * to continue as a normal page fault.
- */
- regs->cr_iip = ((unsigned long)cur->addr) & ~0xFULL;
- ia64_psr(regs)->ri = ((unsigned long)cur->addr) & 0xf;
- if (kcb->kprobe_status == KPROBE_REENTER)
- restore_previous_kprobe(kcb);
- else
- reset_current_kprobe();
- preempt_enable_no_resched();
- break;
- case KPROBE_HIT_ACTIVE:
- case KPROBE_HIT_SSDONE:
- /*
- * In case the user-specified fault handler returned
- * zero, try to fix up.
- */
- if (ia64_done_with_exception(regs))
- return 1;
-
- /*
- * Let ia64_do_page_fault() fix it.
- */
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data)
-{
- struct die_args *args = (struct die_args *)data;
- int ret = NOTIFY_DONE;
-
- if (args->regs && user_mode(args->regs))
- return ret;
-
- switch(val) {
- case DIE_BREAK:
- /* err is break number from ia64_bad_break() */
- if ((args->err >> 12) == (__IA64_BREAK_KPROBE >> 12)
- || args->err == 0)
- if (pre_kprobes_handler(args))
- ret = NOTIFY_STOP;
- break;
- case DIE_FAULT:
- /* err is vector number from ia64_fault() */
- if (args->err == 36)
- if (post_kprobes_handler(args->regs))
- ret = NOTIFY_STOP;
- break;
- default:
- break;
- }
- return ret;
-}
-
-static struct kprobe trampoline_p = {
- .pre_handler = trampoline_probe_handler
-};
-
-int __init arch_init_kprobes(void)
-{
- trampoline_p.addr =
- dereference_function_descriptor(__kretprobe_trampoline);
- return register_kprobe(&trampoline_p);
-}
-
-int __kprobes arch_trampoline_kprobe(struct kprobe *p)
-{
- if (p->addr ==
- dereference_function_descriptor(__kretprobe_trampoline))
- return 1;
-
- return 0;
-}
diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
deleted file mode 100644
index 4db9ca144fa5..000000000000
--- a/arch/ia64/kernel/machine_kexec.c
+++ /dev/null
@@ -1,163 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/ia64/kernel/machine_kexec.c
- *
- * Handle transition of Linux booting another kernel
- * Copyright (C) 2005 Hewlett-Packard Development Comapny, L.P.
- * Copyright (C) 2005 Khalid Aziz <khalid.aziz@hp.com>
- * Copyright (C) 2006 Intel Corp, Zou Nan hai <nanhai.zou@intel.com>
- */
-
-#include <linux/mm.h>
-#include <linux/kexec.h>
-#include <linux/cpu.h>
-#include <linux/irq.h>
-#include <linux/efi.h>
-#include <linux/numa.h>
-#include <linux/mmzone.h>
-
-#include <asm/efi.h>
-#include <asm/numa.h>
-#include <asm/mmu_context.h>
-#include <asm/setup.h>
-#include <asm/delay.h>
-#include <asm/meminit.h>
-#include <asm/processor.h>
-#include <asm/sal.h>
-#include <asm/mca.h>
-
-typedef void (*relocate_new_kernel_t)(
- unsigned long indirection_page,
- unsigned long start_address,
- struct ia64_boot_param *boot_param,
- unsigned long pal_addr) __noreturn;
-
-struct kimage *ia64_kimage;
-
-struct resource efi_memmap_res = {
- .name = "EFI Memory Map",
- .start = 0,
- .end = 0,
- .flags = IORESOURCE_BUSY | IORESOURCE_MEM
-};
-
-struct resource boot_param_res = {
- .name = "Boot parameter",
- .start = 0,
- .end = 0,
- .flags = IORESOURCE_BUSY | IORESOURCE_MEM
-};
-
-
-/*
- * Do what every setup is needed on image and the
- * reboot code buffer to allow us to avoid allocations
- * later.
- */
-int machine_kexec_prepare(struct kimage *image)
-{
- void *control_code_buffer;
- const unsigned long *func;
-
- func = (unsigned long *)&relocate_new_kernel;
- /* Pre-load control code buffer to minimize work in kexec path */
- control_code_buffer = page_address(image->control_code_page);
- memcpy((void *)control_code_buffer, (const void *)func[0],
- relocate_new_kernel_size);
- flush_icache_range((unsigned long)control_code_buffer,
- (unsigned long)control_code_buffer + relocate_new_kernel_size);
- ia64_kimage = image;
-
- return 0;
-}
-
-void machine_kexec_cleanup(struct kimage *image)
-{
-}
-
-/*
- * Do not allocate memory (or fail in any way) in machine_kexec().
- * We are past the point of no return, committed to rebooting now.
- */
-static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
-{
- struct kimage *image = arg;
- relocate_new_kernel_t rnk;
- void *pal_addr = efi_get_pal_addr();
- unsigned long code_addr;
- int ii;
- u64 fp, gp;
- ia64_fptr_t *init_handler = (ia64_fptr_t *)ia64_os_init_on_kdump;
-
- BUG_ON(!image);
- code_addr = (unsigned long)page_address(image->control_code_page);
- if (image->type == KEXEC_TYPE_CRASH) {
- crash_save_this_cpu();
- current->thread.ksp = (__u64)info->sw - 16;
-
- /* Register noop init handler */
- fp = ia64_tpa(init_handler->fp);
- gp = ia64_tpa(ia64_getreg(_IA64_REG_GP));
- ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, fp, gp, 0, fp, gp, 0);
- } else {
- /* Unregister init handlers of current kernel */
- ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, 0, 0, 0, 0, 0, 0);
- }
-
- /* Unregister mca handler - No more recovery on current kernel */
- ia64_sal_set_vectors(SAL_VECTOR_OS_MCA, 0, 0, 0, 0, 0, 0);
-
- /* Interrupts aren't acceptable while we reboot */
- local_irq_disable();
-
- /* Mask CMC and Performance Monitor interrupts */
- ia64_setreg(_IA64_REG_CR_PMV, 1 << 16);
- ia64_setreg(_IA64_REG_CR_CMCV, 1 << 16);
-
- /* Mask ITV and Local Redirect Registers */
- ia64_set_itv(1 << 16);
- ia64_set_lrr0(1 << 16);
- ia64_set_lrr1(1 << 16);
-
- /* terminate possible nested in-service interrupts */
- for (ii = 0; ii < 16; ii++)
- ia64_eoi();
-
- /* unmask TPR and clear any pending interrupts */
- ia64_setreg(_IA64_REG_CR_TPR, 0);
- ia64_srlz_d();
- while (ia64_get_ivr() != IA64_SPURIOUS_INT_VECTOR)
- ia64_eoi();
- rnk = (relocate_new_kernel_t)&code_addr;
- (*rnk)(image->head, image->start, ia64_boot_param,
- GRANULEROUNDDOWN((unsigned long) pal_addr));
- BUG();
-}
-
-void machine_kexec(struct kimage *image)
-{
- BUG_ON(!image);
- unw_init_running(ia64_machine_kexec, image);
- for(;;);
-}
-
-void arch_crash_save_vmcoreinfo(void)
-{
-#if defined(CONFIG_SPARSEMEM)
- VMCOREINFO_SYMBOL(pgdat_list);
- VMCOREINFO_LENGTH(pgdat_list, MAX_NUMNODES);
-#endif
-#ifdef CONFIG_NUMA
- VMCOREINFO_SYMBOL(node_memblk);
- VMCOREINFO_LENGTH(node_memblk, NR_NODE_MEMBLKS);
- VMCOREINFO_STRUCT_SIZE(node_memblk_s);
- VMCOREINFO_OFFSET(node_memblk_s, start_paddr);
- VMCOREINFO_OFFSET(node_memblk_s, size);
-#endif
-#if CONFIG_PGTABLE_LEVELS == 3
- VMCOREINFO_CONFIG(PGTABLE_3);
-#elif CONFIG_PGTABLE_LEVELS == 4
- VMCOREINFO_CONFIG(PGTABLE_4);
-#endif
-}
-
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
deleted file mode 100644
index 2671688d349a..000000000000
--- a/arch/ia64/kernel/mca.c
+++ /dev/null
@@ -1,2111 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * File: mca.c
- * Purpose: Generic MCA handling layer
- *
- * Copyright (C) 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * Copyright (C) 2002 Dell Inc.
- * Copyright (C) Matt Domsch <Matt_Domsch@dell.com>
- *
- * Copyright (C) 2002 Intel
- * Copyright (C) Jenna Hall <jenna.s.hall@intel.com>
- *
- * Copyright (C) 2001 Intel
- * Copyright (C) Fred Lewis <frederick.v.lewis@intel.com>
- *
- * Copyright (C) 2000 Intel
- * Copyright (C) Chuck Fleckenstein <cfleck@co.intel.com>
- *
- * Copyright (C) 1999, 2004-2008 Silicon Graphics, Inc.
- * Copyright (C) Vijay Chander <vijay@engr.sgi.com>
- *
- * Copyright (C) 2006 FUJITSU LIMITED
- * Copyright (C) Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
- *
- * 2000-03-29 Chuck Fleckenstein <cfleck@co.intel.com>
- * Fixed PAL/SAL update issues, began MCA bug fixes, logging issues,
- * added min save state dump, added INIT handler.
- *
- * 2001-01-03 Fred Lewis <frederick.v.lewis@intel.com>
- * Added setup of CMCI and CPEI IRQs, logging of corrected platform
- * errors, completed code for logging of corrected & uncorrected
- * machine check errors, and updated for conformance with Nov. 2000
- * revision of the SAL 3.0 spec.
- *
- * 2002-01-04 Jenna Hall <jenna.s.hall@intel.com>
- * Aligned MCA stack to 16 bytes, added platform vs. CPU error flag,
- * set SAL default return values, changed error record structure to
- * linked list, added init call to sal_get_state_info_size().
- *
- * 2002-03-25 Matt Domsch <Matt_Domsch@dell.com>
- * GUID cleanups.
- *
- * 2003-04-15 David Mosberger-Tang <davidm@hpl.hp.com>
- * Added INIT backtrace support.
- *
- * 2003-12-08 Keith Owens <kaos@sgi.com>
- * smp_call_function() must not be called from interrupt context
- * (can deadlock on tasklist_lock).
- * Use keventd to call smp_call_function().
- *
- * 2004-02-01 Keith Owens <kaos@sgi.com>
- * Avoid deadlock when using printk() for MCA and INIT records.
- * Delete all record printing code, moved to salinfo_decode in user
- * space. Mark variables and functions static where possible.
- * Delete dead variables and functions. Reorder to remove the need
- * for forward declarations and to consolidate related code.
- *
- * 2005-08-12 Keith Owens <kaos@sgi.com>
- * Convert MCA/INIT handlers to use per event stacks and SAL/OS
- * state.
- *
- * 2005-10-07 Keith Owens <kaos@sgi.com>
- * Add notify_die() hooks.
- *
- * 2006-09-15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
- * Add printing support for MCA/INIT.
- *
- * 2007-04-27 Russ Anderson <rja@sgi.com>
- * Support multiple cpus going through OS_MCA in the same event.
- */
-#include <linux/jiffies.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/sched/signal.h>
-#include <linux/sched/debug.h>
-#include <linux/sched/task.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/memblock.h>
-#include <linux/acpi.h>
-#include <linux/timer.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/smp.h>
-#include <linux/workqueue.h>
-#include <linux/cpumask.h>
-#include <linux/kdebug.h>
-#include <linux/cpu.h>
-#include <linux/gfp.h>
-
-#include <asm/delay.h>
-#include <asm/efi.h>
-#include <asm/meminit.h>
-#include <asm/page.h>
-#include <asm/ptrace.h>
-#include <asm/sal.h>
-#include <asm/mca.h>
-#include <asm/mca_asm.h>
-#include <asm/kexec.h>
-
-#include <asm/irq.h>
-#include <asm/hw_irq.h>
-#include <asm/tlb.h>
-
-#include "mca_drv.h"
-#include "entry.h"
-#include "irq.h"
-
-#if defined(IA64_MCA_DEBUG_INFO)
-# define IA64_MCA_DEBUG(fmt...) printk(fmt)
-#else
-# define IA64_MCA_DEBUG(fmt...) do {} while (0)
-#endif
-
-#define NOTIFY_INIT(event, regs, arg, spin) \
-do { \
- if ((notify_die((event), "INIT", (regs), (arg), 0, 0) \
- == NOTIFY_STOP) && ((spin) == 1)) \
- ia64_mca_spin(__func__); \
-} while (0)
-
-#define NOTIFY_MCA(event, regs, arg, spin) \
-do { \
- if ((notify_die((event), "MCA", (regs), (arg), 0, 0) \
- == NOTIFY_STOP) && ((spin) == 1)) \
- ia64_mca_spin(__func__); \
-} while (0)
-
-/* Used by mca_asm.S */
-DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */
-DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */
-DEFINE_PER_CPU(u64, ia64_mca_pal_pte); /* PTE to map PAL code */
-DEFINE_PER_CPU(u64, ia64_mca_pal_base); /* vaddr PAL code granule */
-DEFINE_PER_CPU(u64, ia64_mca_tr_reload); /* Flag for TR reload */
-
-unsigned long __per_cpu_mca[NR_CPUS];
-
-/* In mca_asm.S */
-extern void ia64_os_init_dispatch_monarch (void);
-extern void ia64_os_init_dispatch_slave (void);
-
-static int monarch_cpu = -1;
-
-static ia64_mc_info_t ia64_mc_info;
-
-#define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */
-#define MIN_CPE_POLL_INTERVAL (2*60*HZ) /* 2 minutes */
-#define CMC_POLL_INTERVAL (1*60*HZ) /* 1 minute */
-#define CPE_HISTORY_LENGTH 5
-#define CMC_HISTORY_LENGTH 5
-
-static struct timer_list cpe_poll_timer;
-static struct timer_list cmc_poll_timer;
-/*
- * This variable tells whether we are currently in polling mode.
- * Start with this in the wrong state so we won't play w/ timers
- * before the system is ready.
- */
-static int cmc_polling_enabled = 1;
-
-/*
- * Clearing this variable prevents CPE polling from getting activated
- * in mca_late_init. Use it if your system doesn't provide a CPEI,
- * but encounters problems retrieving CPE logs. This should only be
- * necessary for debugging.
- */
-static int cpe_poll_enabled = 1;
-
-extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe);
-
-static int mca_init __initdata;
-
-/*
- * limited & delayed printing support for MCA/INIT handler
- */
-
-#define mprintk(fmt...) ia64_mca_printk(fmt)
-
-#define MLOGBUF_SIZE (512+256*NR_CPUS)
-#define MLOGBUF_MSGMAX 256
-static char mlogbuf[MLOGBUF_SIZE];
-static DEFINE_SPINLOCK(mlogbuf_wlock); /* mca context only */
-static DEFINE_SPINLOCK(mlogbuf_rlock); /* normal context only */
-static unsigned long mlogbuf_start;
-static unsigned long mlogbuf_end;
-static unsigned int mlogbuf_finished = 0;
-static unsigned long mlogbuf_timestamp = 0;
-
-static int loglevel_save = -1;
-#define BREAK_LOGLEVEL(__console_loglevel) \
- oops_in_progress = 1; \
- if (loglevel_save < 0) \
- loglevel_save = __console_loglevel; \
- __console_loglevel = 15;
-
-#define RESTORE_LOGLEVEL(__console_loglevel) \
- if (loglevel_save >= 0) { \
- __console_loglevel = loglevel_save; \
- loglevel_save = -1; \
- } \
- mlogbuf_finished = 0; \
- oops_in_progress = 0;
-
-/*
- * Push messages into buffer, print them later if not urgent.
- */
-void ia64_mca_printk(const char *fmt, ...)
-{
- va_list args;
- int printed_len;
- char temp_buf[MLOGBUF_MSGMAX];
- char *p;
-
- va_start(args, fmt);
- printed_len = vscnprintf(temp_buf, sizeof(temp_buf), fmt, args);
- va_end(args);
-
- /* Copy the output into mlogbuf */
- if (oops_in_progress) {
- /* mlogbuf was abandoned, use printk directly instead. */
- printk("%s", temp_buf);
- } else {
- spin_lock(&mlogbuf_wlock);
- for (p = temp_buf; *p; p++) {
- unsigned long next = (mlogbuf_end + 1) % MLOGBUF_SIZE;
- if (next != mlogbuf_start) {
- mlogbuf[mlogbuf_end] = *p;
- mlogbuf_end = next;
- } else {
- /* buffer full */
- break;
- }
- }
- mlogbuf[mlogbuf_end] = '\0';
- spin_unlock(&mlogbuf_wlock);
- }
-}
-EXPORT_SYMBOL(ia64_mca_printk);
-
-/*
- * Print buffered messages.
- * NOTE: call this after returning normal context. (ex. from salinfod)
- */
-void ia64_mlogbuf_dump(void)
-{
- char temp_buf[MLOGBUF_MSGMAX];
- char *p;
- unsigned long index;
- unsigned long flags;
- unsigned int printed_len;
-
- /* Get output from mlogbuf */
- while (mlogbuf_start != mlogbuf_end) {
- temp_buf[0] = '\0';
- p = temp_buf;
- printed_len = 0;
-
- spin_lock_irqsave(&mlogbuf_rlock, flags);
-
- index = mlogbuf_start;
- while (index != mlogbuf_end) {
- *p = mlogbuf[index];
- index = (index + 1) % MLOGBUF_SIZE;
- if (!*p)
- break;
- p++;
- if (++printed_len >= MLOGBUF_MSGMAX - 1)
- break;
- }
- *p = '\0';
- if (temp_buf[0])
- printk("%s", temp_buf);
- mlogbuf_start = index;
-
- mlogbuf_timestamp = 0;
- spin_unlock_irqrestore(&mlogbuf_rlock, flags);
- }
-}
-EXPORT_SYMBOL(ia64_mlogbuf_dump);
-
-/*
- * Call this if system is going to down or if immediate flushing messages to
- * console is required. (ex. recovery was failed, crash dump is going to be
- * invoked, long-wait rendezvous etc.)
- * NOTE: this should be called from monarch.
- */
-static void ia64_mlogbuf_finish(int wait)
-{
- BREAK_LOGLEVEL(console_loglevel);
-
- ia64_mlogbuf_dump();
- printk(KERN_EMERG "mlogbuf_finish: printing switched to urgent mode, "
- "MCA/INIT might be dodgy or fail.\n");
-
- if (!wait)
- return;
-
- /* wait for console */
- printk("Delaying for 5 seconds...\n");
- udelay(5*1000000);
-
- mlogbuf_finished = 1;
-}
-
-/*
- * Print buffered messages from INIT context.
- */
-static void ia64_mlogbuf_dump_from_init(void)
-{
- if (mlogbuf_finished)
- return;
-
- if (mlogbuf_timestamp &&
- time_before(jiffies, mlogbuf_timestamp + 30 * HZ)) {
- printk(KERN_ERR "INIT: mlogbuf_dump is interrupted by INIT "
- " and the system seems to be messed up.\n");
- ia64_mlogbuf_finish(0);
- return;
- }
-
- if (!spin_trylock(&mlogbuf_rlock)) {
- printk(KERN_ERR "INIT: mlogbuf_dump is interrupted by INIT. "
- "Generated messages other than stack dump will be "
- "buffered to mlogbuf and will be printed later.\n");
- printk(KERN_ERR "INIT: If messages would not printed after "
- "this INIT, wait 30sec and assert INIT again.\n");
- if (!mlogbuf_timestamp)
- mlogbuf_timestamp = jiffies;
- return;
- }
- spin_unlock(&mlogbuf_rlock);
- ia64_mlogbuf_dump();
-}
-
-static inline void
-ia64_mca_spin(const char *func)
-{
- if (monarch_cpu == smp_processor_id())
- ia64_mlogbuf_finish(0);
- mprintk(KERN_EMERG "%s: spinning here, not returning to SAL\n", func);
- while (1)
- cpu_relax();
-}
-/*
- * IA64_MCA log support
- */
-#define IA64_MAX_LOGS 2 /* Double-buffering for nested MCAs */
-#define IA64_MAX_LOG_TYPES 4 /* MCA, INIT, CMC, CPE */
-
-typedef struct ia64_state_log_s
-{
- spinlock_t isl_lock;
- int isl_index;
- unsigned long isl_count;
- ia64_err_rec_t *isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */
-} ia64_state_log_t;
-
-static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES];
-
-#define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock)
-#define IA64_LOG_LOCK(it) spin_lock_irqsave(&ia64_state_log[it].isl_lock, s)
-#define IA64_LOG_UNLOCK(it) spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s)
-#define IA64_LOG_NEXT_INDEX(it) ia64_state_log[it].isl_index
-#define IA64_LOG_CURR_INDEX(it) 1 - ia64_state_log[it].isl_index
-#define IA64_LOG_INDEX_INC(it) \
- {ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index; \
- ia64_state_log[it].isl_count++;}
-#define IA64_LOG_INDEX_DEC(it) \
- ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index
-#define IA64_LOG_NEXT_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)]))
-#define IA64_LOG_CURR_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)]))
-#define IA64_LOG_COUNT(it) ia64_state_log[it].isl_count
-
-static inline void ia64_log_allocate(int it, u64 size)
-{
- ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] =
- (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES);
- if (!ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)])
- panic("%s: Failed to allocate %llu bytes\n", __func__, size);
-
- ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] =
- (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES);
- if (!ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)])
- panic("%s: Failed to allocate %llu bytes\n", __func__, size);
-}
-
-/*
- * ia64_log_init
- * Reset the OS ia64 log buffer
- * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
- * Outputs : None
- */
-static void __init
-ia64_log_init(int sal_info_type)
-{
- u64 max_size = 0;
-
- IA64_LOG_NEXT_INDEX(sal_info_type) = 0;
- IA64_LOG_LOCK_INIT(sal_info_type);
-
- // SAL will tell us the maximum size of any error record of this type
- max_size = ia64_sal_get_state_info_size(sal_info_type);
- if (!max_size)
- /* alloc_bootmem() doesn't like zero-sized allocations! */
- return;
-
- // set up OS data structures to hold error info
- ia64_log_allocate(sal_info_type, max_size);
-}
-
-/*
- * ia64_log_get
- *
- * Get the current MCA log from SAL and copy it into the OS log buffer.
- *
- * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
- * irq_safe whether you can use printk at this point
- * Outputs : size (total record length)
- * *buffer (ptr to error record)
- *
- */
-static u64
-ia64_log_get(int sal_info_type, u8 **buffer, int irq_safe)
-{
- sal_log_record_header_t *log_buffer;
- u64 total_len = 0;
- unsigned long s;
-
- IA64_LOG_LOCK(sal_info_type);
-
- /* Get the process state information */
- log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type);
-
- total_len = ia64_sal_get_state_info(sal_info_type, (u64 *)log_buffer);
-
- if (total_len) {
- IA64_LOG_INDEX_INC(sal_info_type);
- IA64_LOG_UNLOCK(sal_info_type);
- if (irq_safe) {
- IA64_MCA_DEBUG("%s: SAL error record type %d retrieved. Record length = %ld\n",
- __func__, sal_info_type, total_len);
- }
- *buffer = (u8 *) log_buffer;
- return total_len;
- } else {
- IA64_LOG_UNLOCK(sal_info_type);
- return 0;
- }
-}
-
-/*
- * ia64_mca_log_sal_error_record
- *
- * This function retrieves a specified error record type from SAL
- * and wakes up any processes waiting for error records.
- *
- * Inputs : sal_info_type (Type of error record MCA/CMC/CPE)
- * FIXME: remove MCA and irq_safe.
- */
-static void
-ia64_mca_log_sal_error_record(int sal_info_type)
-{
- u8 *buffer;
- sal_log_record_header_t *rh;
- u64 size;
- int irq_safe = sal_info_type != SAL_INFO_TYPE_MCA;
-#ifdef IA64_MCA_DEBUG_INFO
- static const char * const rec_name[] = { "MCA", "INIT", "CMC", "CPE" };
-#endif
-
- size = ia64_log_get(sal_info_type, &buffer, irq_safe);
- if (!size)
- return;
-
- salinfo_log_wakeup(sal_info_type, buffer, size, irq_safe);
-
- if (irq_safe)
- IA64_MCA_DEBUG("CPU %d: SAL log contains %s error record\n",
- smp_processor_id(),
- sal_info_type < ARRAY_SIZE(rec_name) ? rec_name[sal_info_type] : "UNKNOWN");
-
- /* Clear logs from corrected errors in case there's no user-level logger */
- rh = (sal_log_record_header_t *)buffer;
- if (rh->severity == sal_log_severity_corrected)
- ia64_sal_clear_state_info(sal_info_type);
-}
-
-/*
- * search_mca_table
- * See if the MCA surfaced in an instruction range
- * that has been tagged as recoverable.
- *
- * Inputs
- * first First address range to check
- * last Last address range to check
- * ip Instruction pointer, address we are looking for
- *
- * Return value:
- * 1 on Success (in the table)/ 0 on Failure (not in the table)
- */
-int
-search_mca_table (const struct mca_table_entry *first,
- const struct mca_table_entry *last,
- unsigned long ip)
-{
- const struct mca_table_entry *curr;
- u64 curr_start, curr_end;
-
- curr = first;
- while (curr <= last) {
- curr_start = (u64) &curr->start_addr + curr->start_addr;
- curr_end = (u64) &curr->end_addr + curr->end_addr;
-
- if ((ip >= curr_start) && (ip <= curr_end)) {
- return 1;
- }
- curr++;
- }
- return 0;
-}
-
-/* Given an address, look for it in the mca tables. */
-int mca_recover_range(unsigned long addr)
-{
- extern struct mca_table_entry __start___mca_table[];
- extern struct mca_table_entry __stop___mca_table[];
-
- return search_mca_table(__start___mca_table, __stop___mca_table-1, addr);
-}
-EXPORT_SYMBOL_GPL(mca_recover_range);
-
-int cpe_vector = -1;
-int ia64_cpe_irq = -1;
-
-static irqreturn_t
-ia64_mca_cpe_int_handler (int cpe_irq, void *arg)
-{
- static unsigned long cpe_history[CPE_HISTORY_LENGTH];
- static int index;
- static DEFINE_SPINLOCK(cpe_history_lock);
-
- IA64_MCA_DEBUG("%s: received interrupt vector = %#x on CPU %d\n",
- __func__, cpe_irq, smp_processor_id());
-
- /* SAL spec states this should run w/ interrupts enabled */
- local_irq_enable();
-
- spin_lock(&cpe_history_lock);
- if (!cpe_poll_enabled && cpe_vector >= 0) {
-
- int i, count = 1; /* we know 1 happened now */
- unsigned long now = jiffies;
-
- for (i = 0; i < CPE_HISTORY_LENGTH; i++) {
- if (now - cpe_history[i] <= HZ)
- count++;
- }
-
- IA64_MCA_DEBUG(KERN_INFO "CPE threshold %d/%d\n", count, CPE_HISTORY_LENGTH);
- if (count >= CPE_HISTORY_LENGTH) {
-
- cpe_poll_enabled = 1;
- spin_unlock(&cpe_history_lock);
- disable_irq_nosync(local_vector_to_irq(IA64_CPE_VECTOR));
-
- /*
- * Corrected errors will still be corrected, but
- * make sure there's a log somewhere that indicates
- * something is generating more than we can handle.
- */
- printk(KERN_WARNING "WARNING: Switching to polling CPE handler; error records may be lost\n");
-
- mod_timer(&cpe_poll_timer, jiffies + MIN_CPE_POLL_INTERVAL);
-
- /* lock already released, get out now */
- goto out;
- } else {
- cpe_history[index++] = now;
- if (index == CPE_HISTORY_LENGTH)
- index = 0;
- }
- }
- spin_unlock(&cpe_history_lock);
-out:
- /* Get the CPE error record and log it */
- ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
-
- local_irq_disable();
-
- return IRQ_HANDLED;
-}
-
-/*
- * ia64_mca_register_cpev
- *
- * Register the corrected platform error vector with SAL.
- *
- * Inputs
- * cpev Corrected Platform Error Vector number
- *
- * Outputs
- * None
- */
-void
-ia64_mca_register_cpev (int cpev)
-{
- /* Register the CPE interrupt vector with SAL */
- struct ia64_sal_retval isrv;
-
- isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0);
- if (isrv.status) {
- printk(KERN_ERR "Failed to register Corrected Platform "
- "Error interrupt vector with SAL (status %ld)\n", isrv.status);
- return;
- }
-
- IA64_MCA_DEBUG("%s: corrected platform error "
- "vector %#x registered\n", __func__, cpev);
-}
-
-/*
- * ia64_mca_cmc_vector_setup
- *
- * Setup the corrected machine check vector register in the processor.
- * (The interrupt is masked on boot. ia64_mca_late_init unmask this.)
- * This function is invoked on a per-processor basis.
- *
- * Inputs
- * None
- *
- * Outputs
- * None
- */
-void
-ia64_mca_cmc_vector_setup (void)
-{
- cmcv_reg_t cmcv;
-
- cmcv.cmcv_regval = 0;
- cmcv.cmcv_mask = 1; /* Mask/disable interrupt at first */
- cmcv.cmcv_vector = IA64_CMC_VECTOR;
- ia64_setreg(_IA64_REG_CR_CMCV, cmcv.cmcv_regval);
-
- IA64_MCA_DEBUG("%s: CPU %d corrected machine check vector %#x registered.\n",
- __func__, smp_processor_id(), IA64_CMC_VECTOR);
-
- IA64_MCA_DEBUG("%s: CPU %d CMCV = %#016lx\n",
- __func__, smp_processor_id(), ia64_getreg(_IA64_REG_CR_CMCV));
-}
-
-/*
- * ia64_mca_cmc_vector_disable
- *
- * Mask the corrected machine check vector register in the processor.
- * This function is invoked on a per-processor basis.
- *
- * Inputs
- * dummy(unused)
- *
- * Outputs
- * None
- */
-static void
-ia64_mca_cmc_vector_disable (void *dummy)
-{
- cmcv_reg_t cmcv;
-
- cmcv.cmcv_regval = ia64_getreg(_IA64_REG_CR_CMCV);
-
- cmcv.cmcv_mask = 1; /* Mask/disable interrupt */
- ia64_setreg(_IA64_REG_CR_CMCV, cmcv.cmcv_regval);
-
- IA64_MCA_DEBUG("%s: CPU %d corrected machine check vector %#x disabled.\n",
- __func__, smp_processor_id(), cmcv.cmcv_vector);
-}
-
-/*
- * ia64_mca_cmc_vector_enable
- *
- * Unmask the corrected machine check vector register in the processor.
- * This function is invoked on a per-processor basis.
- *
- * Inputs
- * dummy(unused)
- *
- * Outputs
- * None
- */
-static void
-ia64_mca_cmc_vector_enable (void *dummy)
-{
- cmcv_reg_t cmcv;
-
- cmcv.cmcv_regval = ia64_getreg(_IA64_REG_CR_CMCV);
-
- cmcv.cmcv_mask = 0; /* Unmask/enable interrupt */
- ia64_setreg(_IA64_REG_CR_CMCV, cmcv.cmcv_regval);
-
- IA64_MCA_DEBUG("%s: CPU %d corrected machine check vector %#x enabled.\n",
- __func__, smp_processor_id(), cmcv.cmcv_vector);
-}
-
-/*
- * ia64_mca_cmc_vector_disable_keventd
- *
- * Called via keventd (smp_call_function() is not safe in interrupt context) to
- * disable the cmc interrupt vector.
- */
-static void
-ia64_mca_cmc_vector_disable_keventd(struct work_struct *unused)
-{
- on_each_cpu(ia64_mca_cmc_vector_disable, NULL, 0);
-}
-
-/*
- * ia64_mca_cmc_vector_enable_keventd
- *
- * Called via keventd (smp_call_function() is not safe in interrupt context) to
- * enable the cmc interrupt vector.
- */
-static void
-ia64_mca_cmc_vector_enable_keventd(struct work_struct *unused)
-{
- on_each_cpu(ia64_mca_cmc_vector_enable, NULL, 0);
-}
-
-/*
- * ia64_mca_wakeup
- *
- * Send an inter-cpu interrupt to wake-up a particular cpu.
- *
- * Inputs : cpuid
- * Outputs : None
- */
-static void
-ia64_mca_wakeup(int cpu)
-{
- ia64_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0);
-}
-
-/*
- * ia64_mca_wakeup_all
- *
- * Wakeup all the slave cpus which have rendez'ed previously.
- *
- * Inputs : None
- * Outputs : None
- */
-static void
-ia64_mca_wakeup_all(void)
-{
- int cpu;
-
- /* Clear the Rendez checkin flag for all cpus */
- for_each_online_cpu(cpu) {
- if (ia64_mc_info.imi_rendez_checkin[cpu] == IA64_MCA_RENDEZ_CHECKIN_DONE)
- ia64_mca_wakeup(cpu);
- }
-
-}
-
-/*
- * ia64_mca_rendez_interrupt_handler
- *
- * This is handler used to put slave processors into spinloop
- * while the monarch processor does the mca handling and later
- * wake each slave up once the monarch is done. The state
- * IA64_MCA_RENDEZ_CHECKIN_DONE indicates the cpu is rendez'ed
- * in SAL. The state IA64_MCA_RENDEZ_CHECKIN_NOTDONE indicates
- * the cpu has come out of OS rendezvous.
- *
- * Inputs : None
- * Outputs : None
- */
-static irqreturn_t
-ia64_mca_rendez_int_handler(int rendez_irq, void *arg)
-{
- unsigned long flags;
- int cpu = smp_processor_id();
- struct ia64_mca_notify_die nd =
- { .sos = NULL, .monarch_cpu = &monarch_cpu };
-
- /* Mask all interrupts */
- local_irq_save(flags);
-
- NOTIFY_MCA(DIE_MCA_RENDZVOUS_ENTER, get_irq_regs(), (long)&nd, 1);
-
- ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE;
- /* Register with the SAL monarch that the slave has
- * reached SAL
- */
- ia64_sal_mc_rendez();
-
- NOTIFY_MCA(DIE_MCA_RENDZVOUS_PROCESS, get_irq_regs(), (long)&nd, 1);
-
- /* Wait for the monarch cpu to exit. */
- while (monarch_cpu != -1)
- cpu_relax(); /* spin until monarch leaves */
-
- NOTIFY_MCA(DIE_MCA_RENDZVOUS_LEAVE, get_irq_regs(), (long)&nd, 1);
-
- ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
- /* Enable all interrupts */
- local_irq_restore(flags);
- return IRQ_HANDLED;
-}
-
-/*
- * ia64_mca_wakeup_int_handler
- *
- * The interrupt handler for processing the inter-cpu interrupt to the
- * slave cpu which was spinning in the rendez loop.
- * Since this spinning is done by turning off the interrupts and
- * polling on the wakeup-interrupt bit in the IRR, there is
- * nothing useful to be done in the handler.
- *
- * Inputs : wakeup_irq (Wakeup-interrupt bit)
- * arg (Interrupt handler specific argument)
- * Outputs : None
- *
- */
-static irqreturn_t
-ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg)
-{
- return IRQ_HANDLED;
-}
-
-/* Function pointer for extra MCA recovery */
-int (*ia64_mca_ucmc_extension)
- (void*,struct ia64_sal_os_state*)
- = NULL;
-
-int
-ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *))
-{
- if (ia64_mca_ucmc_extension)
- return 1;
-
- ia64_mca_ucmc_extension = fn;
- return 0;
-}
-
-void
-ia64_unreg_MCA_extension(void)
-{
- if (ia64_mca_ucmc_extension)
- ia64_mca_ucmc_extension = NULL;
-}
-
-EXPORT_SYMBOL(ia64_reg_MCA_extension);
-EXPORT_SYMBOL(ia64_unreg_MCA_extension);
-
-
-static inline void
-copy_reg(const u64 *fr, u64 fnat, unsigned long *tr, unsigned long *tnat)
-{
- u64 fslot, tslot, nat;
- *tr = *fr;
- fslot = ((unsigned long)fr >> 3) & 63;
- tslot = ((unsigned long)tr >> 3) & 63;
- *tnat &= ~(1UL << tslot);
- nat = (fnat >> fslot) & 1;
- *tnat |= (nat << tslot);
-}
-
-/* Change the comm field on the MCA/INT task to include the pid that
- * was interrupted, it makes for easier debugging. If that pid was 0
- * (swapper or nested MCA/INIT) then use the start of the previous comm
- * field suffixed with its cpu.
- */
-
-static void
-ia64_mca_modify_comm(const struct task_struct *previous_current)
-{
- char *p, comm[sizeof(current->comm)];
- if (previous_current->pid)
- snprintf(comm, sizeof(comm), "%s %d",
- current->comm, previous_current->pid);
- else {
- int l;
- if ((p = strchr(previous_current->comm, ' ')))
- l = p - previous_current->comm;
- else
- l = strlen(previous_current->comm);
- snprintf(comm, sizeof(comm), "%s %*s %d",
- current->comm, l, previous_current->comm,
- task_thread_info(previous_current)->cpu);
- }
- memcpy(current->comm, comm, sizeof(current->comm));
-}
-
-static void
-finish_pt_regs(struct pt_regs *regs, struct ia64_sal_os_state *sos,
- unsigned long *nat)
-{
- const struct pal_min_state_area *ms = sos->pal_min_state;
- const u64 *bank;
-
- /* If ipsr.ic then use pmsa_{iip,ipsr,ifs}, else use
- * pmsa_{xip,xpsr,xfs}
- */
- if (ia64_psr(regs)->ic) {
- regs->cr_iip = ms->pmsa_iip;
- regs->cr_ipsr = ms->pmsa_ipsr;
- regs->cr_ifs = ms->pmsa_ifs;
- } else {
- regs->cr_iip = ms->pmsa_xip;
- regs->cr_ipsr = ms->pmsa_xpsr;
- regs->cr_ifs = ms->pmsa_xfs;
-
- sos->iip = ms->pmsa_iip;
- sos->ipsr = ms->pmsa_ipsr;
- sos->ifs = ms->pmsa_ifs;
- }
- regs->pr = ms->pmsa_pr;
- regs->b0 = ms->pmsa_br0;
- regs->ar_rsc = ms->pmsa_rsc;
- copy_reg(&ms->pmsa_gr[1-1], ms->pmsa_nat_bits, &regs->r1, nat);
- copy_reg(&ms->pmsa_gr[2-1], ms->pmsa_nat_bits, &regs->r2, nat);
- copy_reg(&ms->pmsa_gr[3-1], ms->pmsa_nat_bits, &regs->r3, nat);
- copy_reg(&ms->pmsa_gr[8-1], ms->pmsa_nat_bits, &regs->r8, nat);
- copy_reg(&ms->pmsa_gr[9-1], ms->pmsa_nat_bits, &regs->r9, nat);
- copy_reg(&ms->pmsa_gr[10-1], ms->pmsa_nat_bits, &regs->r10, nat);
- copy_reg(&ms->pmsa_gr[11-1], ms->pmsa_nat_bits, &regs->r11, nat);
- copy_reg(&ms->pmsa_gr[12-1], ms->pmsa_nat_bits, &regs->r12, nat);
- copy_reg(&ms->pmsa_gr[13-1], ms->pmsa_nat_bits, &regs->r13, nat);
- copy_reg(&ms->pmsa_gr[14-1], ms->pmsa_nat_bits, &regs->r14, nat);
- copy_reg(&ms->pmsa_gr[15-1], ms->pmsa_nat_bits, &regs->r15, nat);
- if (ia64_psr(regs)->bn)
- bank = ms->pmsa_bank1_gr;
- else
- bank = ms->pmsa_bank0_gr;
- copy_reg(&bank[16-16], ms->pmsa_nat_bits, &regs->r16, nat);
- copy_reg(&bank[17-16], ms->pmsa_nat_bits, &regs->r17, nat);
- copy_reg(&bank[18-16], ms->pmsa_nat_bits, &regs->r18, nat);
- copy_reg(&bank[19-16], ms->pmsa_nat_bits, &regs->r19, nat);
- copy_reg(&bank[20-16], ms->pmsa_nat_bits, &regs->r20, nat);
- copy_reg(&bank[21-16], ms->pmsa_nat_bits, &regs->r21, nat);
- copy_reg(&bank[22-16], ms->pmsa_nat_bits, &regs->r22, nat);
- copy_reg(&bank[23-16], ms->pmsa_nat_bits, &regs->r23, nat);
- copy_reg(&bank[24-16], ms->pmsa_nat_bits, &regs->r24, nat);
- copy_reg(&bank[25-16], ms->pmsa_nat_bits, &regs->r25, nat);
- copy_reg(&bank[26-16], ms->pmsa_nat_bits, &regs->r26, nat);
- copy_reg(&bank[27-16], ms->pmsa_nat_bits, &regs->r27, nat);
- copy_reg(&bank[28-16], ms->pmsa_nat_bits, &regs->r28, nat);
- copy_reg(&bank[29-16], ms->pmsa_nat_bits, &regs->r29, nat);
- copy_reg(&bank[30-16], ms->pmsa_nat_bits, &regs->r30, nat);
- copy_reg(&bank[31-16], ms->pmsa_nat_bits, &regs->r31, nat);
-}
-
-/* On entry to this routine, we are running on the per cpu stack, see
- * mca_asm.h. The original stack has not been touched by this event. Some of
- * the original stack's registers will be in the RBS on this stack. This stack
- * also contains a partial pt_regs and switch_stack, the rest of the data is in
- * PAL minstate.
- *
- * The first thing to do is modify the original stack to look like a blocked
- * task so we can run backtrace on the original task. Also mark the per cpu
- * stack as current to ensure that we use the correct task state, it also means
- * that we can do backtrace on the MCA/INIT handler code itself.
- */
-
-static struct task_struct *
-ia64_mca_modify_original_stack(struct pt_regs *regs,
- const struct switch_stack *sw,
- struct ia64_sal_os_state *sos,
- const char *type)
-{
- char *p;
- ia64_va va;
- extern char ia64_leave_kernel[]; /* Need asm address, not function descriptor */
- const struct pal_min_state_area *ms = sos->pal_min_state;
- struct task_struct *previous_current;
- struct pt_regs *old_regs;
- struct switch_stack *old_sw;
- unsigned size = sizeof(struct pt_regs) +
- sizeof(struct switch_stack) + 16;
- unsigned long *old_bspstore, *old_bsp;
- unsigned long *new_bspstore, *new_bsp;
- unsigned long old_unat, old_rnat, new_rnat, nat;
- u64 slots, loadrs = regs->loadrs;
- u64 r12 = ms->pmsa_gr[12-1], r13 = ms->pmsa_gr[13-1];
- u64 ar_bspstore = regs->ar_bspstore;
- u64 ar_bsp = regs->ar_bspstore + (loadrs >> 16);
- const char *msg;
- int cpu = smp_processor_id();
-
- previous_current = curr_task(cpu);
- ia64_set_curr_task(cpu, current);
- if ((p = strchr(current->comm, ' ')))
- *p = '\0';
-
- /* Best effort attempt to cope with MCA/INIT delivered while in
- * physical mode.
- */
- regs->cr_ipsr = ms->pmsa_ipsr;
- if (ia64_psr(regs)->dt == 0) {
- va.l = r12;
- if (va.f.reg == 0) {
- va.f.reg = 7;
- r12 = va.l;
- }
- va.l = r13;
- if (va.f.reg == 0) {
- va.f.reg = 7;
- r13 = va.l;
- }
- }
- if (ia64_psr(regs)->rt == 0) {
- va.l = ar_bspstore;
- if (va.f.reg == 0) {
- va.f.reg = 7;
- ar_bspstore = va.l;
- }
- va.l = ar_bsp;
- if (va.f.reg == 0) {
- va.f.reg = 7;
- ar_bsp = va.l;
- }
- }
-
- /* mca_asm.S ia64_old_stack() cannot assume that the dirty registers
- * have been copied to the old stack, the old stack may fail the
- * validation tests below. So ia64_old_stack() must restore the dirty
- * registers from the new stack. The old and new bspstore probably
- * have different alignments, so loadrs calculated on the old bsp
- * cannot be used to restore from the new bsp. Calculate a suitable
- * loadrs for the new stack and save it in the new pt_regs, where
- * ia64_old_stack() can get it.
- */
- old_bspstore = (unsigned long *)ar_bspstore;
- old_bsp = (unsigned long *)ar_bsp;
- slots = ia64_rse_num_regs(old_bspstore, old_bsp);
- new_bspstore = (unsigned long *)((u64)current + IA64_RBS_OFFSET);
- new_bsp = ia64_rse_skip_regs(new_bspstore, slots);
- regs->loadrs = (new_bsp - new_bspstore) * 8 << 16;
-
- /* Verify the previous stack state before we change it */
- if (user_mode(regs)) {
- msg = "occurred in user space";
- /* previous_current is guaranteed to be valid when the task was
- * in user space, so ...
- */
- ia64_mca_modify_comm(previous_current);
- goto no_mod;
- }
-
- if (r13 != sos->prev_IA64_KR_CURRENT) {
- msg = "inconsistent previous current and r13";
- goto no_mod;
- }
-
- if (!mca_recover_range(ms->pmsa_iip)) {
- if ((r12 - r13) >= KERNEL_STACK_SIZE) {
- msg = "inconsistent r12 and r13";
- goto no_mod;
- }
- if ((ar_bspstore - r13) >= KERNEL_STACK_SIZE) {
- msg = "inconsistent ar.bspstore and r13";
- goto no_mod;
- }
- va.p = old_bspstore;
- if (va.f.reg < 5) {
- msg = "old_bspstore is in the wrong region";
- goto no_mod;
- }
- if ((ar_bsp - r13) >= KERNEL_STACK_SIZE) {
- msg = "inconsistent ar.bsp and r13";
- goto no_mod;
- }
- size += (ia64_rse_skip_regs(old_bspstore, slots) - old_bspstore) * 8;
- if (ar_bspstore + size > r12) {
- msg = "no room for blocked state";
- goto no_mod;
- }
- }
-
- ia64_mca_modify_comm(previous_current);
-
- /* Make the original task look blocked. First stack a struct pt_regs,
- * describing the state at the time of interrupt. mca_asm.S built a
- * partial pt_regs, copy it and fill in the blanks using minstate.
- */
- p = (char *)r12 - sizeof(*regs);
- old_regs = (struct pt_regs *)p;
- memcpy(old_regs, regs, sizeof(*regs));
- old_regs->loadrs = loadrs;
- old_unat = old_regs->ar_unat;
- finish_pt_regs(old_regs, sos, &old_unat);
-
- /* Next stack a struct switch_stack. mca_asm.S built a partial
- * switch_stack, copy it and fill in the blanks using pt_regs and
- * minstate.
- *
- * In the synthesized switch_stack, b0 points to ia64_leave_kernel,
- * ar.pfs is set to 0.
- *
- * unwind.c::unw_unwind() does special processing for interrupt frames.
- * It checks if the PRED_NON_SYSCALL predicate is set, if the predicate
- * is clear then unw_unwind() does _not_ adjust bsp over pt_regs. Not
- * that this is documented, of course. Set PRED_NON_SYSCALL in the
- * switch_stack on the original stack so it will unwind correctly when
- * unwind.c reads pt_regs.
- *
- * thread.ksp is updated to point to the synthesized switch_stack.
- */
- p -= sizeof(struct switch_stack);
- old_sw = (struct switch_stack *)p;
- memcpy(old_sw, sw, sizeof(*sw));
- old_sw->caller_unat = old_unat;
- old_sw->ar_fpsr = old_regs->ar_fpsr;
- copy_reg(&ms->pmsa_gr[4-1], ms->pmsa_nat_bits, &old_sw->r4, &old_unat);
- copy_reg(&ms->pmsa_gr[5-1], ms->pmsa_nat_bits, &old_sw->r5, &old_unat);
- copy_reg(&ms->pmsa_gr[6-1], ms->pmsa_nat_bits, &old_sw->r6, &old_unat);
- copy_reg(&ms->pmsa_gr[7-1], ms->pmsa_nat_bits, &old_sw->r7, &old_unat);
- old_sw->b0 = (u64)ia64_leave_kernel;
- old_sw->b1 = ms->pmsa_br1;
- old_sw->ar_pfs = 0;
- old_sw->ar_unat = old_unat;
- old_sw->pr = old_regs->pr | (1UL << PRED_NON_SYSCALL);
- previous_current->thread.ksp = (u64)p - 16;
-
- /* Finally copy the original stack's registers back to its RBS.
- * Registers from ar.bspstore through ar.bsp at the time of the event
- * are in the current RBS, copy them back to the original stack. The
- * copy must be done register by register because the original bspstore
- * and the current one have different alignments, so the saved RNAT
- * data occurs at different places.
- *
- * mca_asm does cover, so the old_bsp already includes all registers at
- * the time of MCA/INIT. It also does flushrs, so all registers before
- * this function have been written to backing store on the MCA/INIT
- * stack.
- */
- new_rnat = ia64_get_rnat(ia64_rse_rnat_addr(new_bspstore));
- old_rnat = regs->ar_rnat;
- while (slots--) {
- if (ia64_rse_is_rnat_slot(new_bspstore)) {
- new_rnat = ia64_get_rnat(new_bspstore++);
- }
- if (ia64_rse_is_rnat_slot(old_bspstore)) {
- *old_bspstore++ = old_rnat;
- old_rnat = 0;
- }
- nat = (new_rnat >> ia64_rse_slot_num(new_bspstore)) & 1UL;
- old_rnat &= ~(1UL << ia64_rse_slot_num(old_bspstore));
- old_rnat |= (nat << ia64_rse_slot_num(old_bspstore));
- *old_bspstore++ = *new_bspstore++;
- }
- old_sw->ar_bspstore = (unsigned long)old_bspstore;
- old_sw->ar_rnat = old_rnat;
-
- sos->prev_task = previous_current;
- return previous_current;
-
-no_mod:
- mprintk(KERN_INFO "cpu %d, %s %s, original stack not modified\n",
- smp_processor_id(), type, msg);
- old_unat = regs->ar_unat;
- finish_pt_regs(regs, sos, &old_unat);
- return previous_current;
-}
-
-/* The monarch/slave interaction is based on monarch_cpu and requires that all
- * slaves have entered rendezvous before the monarch leaves. If any cpu has
- * not entered rendezvous yet then wait a bit. The assumption is that any
- * slave that has not rendezvoused after a reasonable time is never going to do
- * so. In this context, slave includes cpus that respond to the MCA rendezvous
- * interrupt, as well as cpus that receive the INIT slave event.
- */
-
-static void
-ia64_wait_for_slaves(int monarch, const char *type)
-{
- int c, i , wait;
-
- /*
- * wait 5 seconds total for slaves (arbitrary)
- */
- for (i = 0; i < 5000; i++) {
- wait = 0;
- for_each_online_cpu(c) {
- if (c == monarch)
- continue;
- if (ia64_mc_info.imi_rendez_checkin[c]
- == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) {
- udelay(1000); /* short wait */
- wait = 1;
- break;
- }
- }
- if (!wait)
- goto all_in;
- }
-
- /*
- * Maybe slave(s) dead. Print buffered messages immediately.
- */
- ia64_mlogbuf_finish(0);
- mprintk(KERN_INFO "OS %s slave did not rendezvous on cpu", type);
- for_each_online_cpu(c) {
- if (c == monarch)
- continue;
- if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE)
- mprintk(" %d", c);
- }
- mprintk("\n");
- return;
-
-all_in:
- mprintk(KERN_INFO "All OS %s slaves have reached rendezvous\n", type);
- return;
-}
-
-/* mca_insert_tr
- *
- * Switch rid when TR reload and needed!
- * iord: 1: itr, 2: itr;
- *
-*/
-static void mca_insert_tr(u64 iord)
-{
-
- int i;
- u64 old_rr;
- struct ia64_tr_entry *p;
- unsigned long psr;
- int cpu = smp_processor_id();
-
- if (!ia64_idtrs[cpu])
- return;
-
- psr = ia64_clear_ic();
- for (i = IA64_TR_ALLOC_BASE; i < IA64_TR_ALLOC_MAX; i++) {
- p = ia64_idtrs[cpu] + (iord - 1) * IA64_TR_ALLOC_MAX;
- if (p->pte & 0x1) {
- old_rr = ia64_get_rr(p->ifa);
- if (old_rr != p->rr) {
- ia64_set_rr(p->ifa, p->rr);
- ia64_srlz_d();
- }
- ia64_ptr(iord, p->ifa, p->itir >> 2);
- ia64_srlz_i();
- if (iord & 0x1) {
- ia64_itr(0x1, i, p->ifa, p->pte, p->itir >> 2);
- ia64_srlz_i();
- }
- if (iord & 0x2) {
- ia64_itr(0x2, i, p->ifa, p->pte, p->itir >> 2);
- ia64_srlz_i();
- }
- if (old_rr != p->rr) {
- ia64_set_rr(p->ifa, old_rr);
- ia64_srlz_d();
- }
- }
- }
- ia64_set_psr(psr);
-}
-
-/*
- * ia64_mca_handler
- *
- * This is uncorrectable machine check handler called from OS_MCA
- * dispatch code which is in turn called from SAL_CHECK().
- * This is the place where the core of OS MCA handling is done.
- * Right now the logs are extracted and displayed in a well-defined
- * format. This handler code is supposed to be run only on the
- * monarch processor. Once the monarch is done with MCA handling
- * further MCA logging is enabled by clearing logs.
- * Monarch also has the duty of sending wakeup-IPIs to pull the
- * slave processors out of rendezvous spinloop.
- *
- * If multiple processors call into OS_MCA, the first will become
- * the monarch. Subsequent cpus will be recorded in the mca_cpu
- * bitmask. After the first monarch has processed its MCA, it
- * will wake up the next cpu in the mca_cpu bitmask and then go
- * into the rendezvous loop. When all processors have serviced
- * their MCA, the last monarch frees up the rest of the processors.
- */
-void
-ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
- struct ia64_sal_os_state *sos)
-{
- int recover, cpu = smp_processor_id();
- struct task_struct *previous_current;
- struct ia64_mca_notify_die nd =
- { .sos = sos, .monarch_cpu = &monarch_cpu, .data = &recover };
- static atomic_t mca_count;
- static cpumask_t mca_cpu;
-
- if (atomic_add_return(1, &mca_count) == 1) {
- monarch_cpu = cpu;
- sos->monarch = 1;
- } else {
- cpumask_set_cpu(cpu, &mca_cpu);
- sos->monarch = 0;
- }
- mprintk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d "
- "monarch=%ld\n", sos->proc_state_param, cpu, sos->monarch);
-
- previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
-
- NOTIFY_MCA(DIE_MCA_MONARCH_ENTER, regs, (long)&nd, 1);
-
- ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA;
- if (sos->monarch) {
- ia64_wait_for_slaves(cpu, "MCA");
-
- /* Wakeup all the processors which are spinning in the
- * rendezvous loop. They will leave SAL, then spin in the OS
- * with interrupts disabled until this monarch cpu leaves the
- * MCA handler. That gets control back to the OS so we can
- * backtrace the other cpus, backtrace when spinning in SAL
- * does not work.
- */
- ia64_mca_wakeup_all();
- } else {
- while (cpumask_test_cpu(cpu, &mca_cpu))
- cpu_relax(); /* spin until monarch wakes us */
- }
-
- NOTIFY_MCA(DIE_MCA_MONARCH_PROCESS, regs, (long)&nd, 1);
-
- /* Get the MCA error record and log it */
- ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
-
- /* MCA error recovery */
- recover = (ia64_mca_ucmc_extension
- && ia64_mca_ucmc_extension(
- IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA),
- sos));
-
- if (recover) {
- sal_log_record_header_t *rh = IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA);
- rh->severity = sal_log_severity_corrected;
- ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA);
- sos->os_status = IA64_MCA_CORRECTED;
- } else {
- /* Dump buffered message to console */
- ia64_mlogbuf_finish(1);
- }
-
- if (__this_cpu_read(ia64_mca_tr_reload)) {
- mca_insert_tr(0x1); /*Reload dynamic itrs*/
- mca_insert_tr(0x2); /*Reload dynamic itrs*/
- }
-
- NOTIFY_MCA(DIE_MCA_MONARCH_LEAVE, regs, (long)&nd, 1);
-
- if (atomic_dec_return(&mca_count) > 0) {
- int i;
-
- /* wake up the next monarch cpu,
- * and put this cpu in the rendez loop.
- */
- for_each_online_cpu(i) {
- if (cpumask_test_cpu(i, &mca_cpu)) {
- monarch_cpu = i;
- cpumask_clear_cpu(i, &mca_cpu); /* wake next cpu */
- while (monarch_cpu != -1)
- cpu_relax(); /* spin until last cpu leaves */
- ia64_set_curr_task(cpu, previous_current);
- ia64_mc_info.imi_rendez_checkin[cpu]
- = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
- return;
- }
- }
- }
- ia64_set_curr_task(cpu, previous_current);
- ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
- monarch_cpu = -1; /* This frees the slaves and previous monarchs */
-}
-
-static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd);
-static DECLARE_WORK(cmc_enable_work, ia64_mca_cmc_vector_enable_keventd);
-
-/*
- * ia64_mca_cmc_int_handler
- *
- * This is corrected machine check interrupt handler.
- * Right now the logs are extracted and displayed in a well-defined
- * format.
- *
- * Inputs
- * interrupt number
- * client data arg ptr
- *
- * Outputs
- * None
- */
-static irqreturn_t
-ia64_mca_cmc_int_handler(int cmc_irq, void *arg)
-{
- static unsigned long cmc_history[CMC_HISTORY_LENGTH];
- static int index;
- static DEFINE_SPINLOCK(cmc_history_lock);
-
- IA64_MCA_DEBUG("%s: received interrupt vector = %#x on CPU %d\n",
- __func__, cmc_irq, smp_processor_id());
-
- /* SAL spec states this should run w/ interrupts enabled */
- local_irq_enable();
-
- spin_lock(&cmc_history_lock);
- if (!cmc_polling_enabled) {
- int i, count = 1; /* we know 1 happened now */
- unsigned long now = jiffies;
-
- for (i = 0; i < CMC_HISTORY_LENGTH; i++) {
- if (now - cmc_history[i] <= HZ)
- count++;
- }
-
- IA64_MCA_DEBUG(KERN_INFO "CMC threshold %d/%d\n", count, CMC_HISTORY_LENGTH);
- if (count >= CMC_HISTORY_LENGTH) {
-
- cmc_polling_enabled = 1;
- spin_unlock(&cmc_history_lock);
- /* If we're being hit with CMC interrupts, we won't
- * ever execute the schedule_work() below. Need to
- * disable CMC interrupts on this processor now.
- */
- ia64_mca_cmc_vector_disable(NULL);
- schedule_work(&cmc_disable_work);
-
- /*
- * Corrected errors will still be corrected, but
- * make sure there's a log somewhere that indicates
- * something is generating more than we can handle.
- */
- printk(KERN_WARNING "WARNING: Switching to polling CMC handler; error records may be lost\n");
-
- mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL);
-
- /* lock already released, get out now */
- goto out;
- } else {
- cmc_history[index++] = now;
- if (index == CMC_HISTORY_LENGTH)
- index = 0;
- }
- }
- spin_unlock(&cmc_history_lock);
-out:
- /* Get the CMC error record and log it */
- ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC);
-
- local_irq_disable();
-
- return IRQ_HANDLED;
-}
-
-/*
- * ia64_mca_cmc_int_caller
- *
- * Triggered by sw interrupt from CMC polling routine. Calls
- * real interrupt handler and either triggers a sw interrupt
- * on the next cpu or does cleanup at the end.
- *
- * Inputs
- * interrupt number
- * client data arg ptr
- * Outputs
- * handled
- */
-static irqreturn_t
-ia64_mca_cmc_int_caller(int cmc_irq, void *arg)
-{
- static int start_count = -1;
- unsigned int cpuid;
-
- cpuid = smp_processor_id();
-
- /* If first cpu, update count */
- if (start_count == -1)
- start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CMC);
-
- ia64_mca_cmc_int_handler(cmc_irq, arg);
-
- cpuid = cpumask_next(cpuid+1, cpu_online_mask);
-
- if (cpuid < nr_cpu_ids) {
- ia64_send_ipi(cpuid, IA64_CMCP_VECTOR, IA64_IPI_DM_INT, 0);
- } else {
- /* If no log record, switch out of polling mode */
- if (start_count == IA64_LOG_COUNT(SAL_INFO_TYPE_CMC)) {
-
- printk(KERN_WARNING "Returning to interrupt driven CMC handler\n");
- schedule_work(&cmc_enable_work);
- cmc_polling_enabled = 0;
-
- } else {
-
- mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL);
- }
-
- start_count = -1;
- }
-
- return IRQ_HANDLED;
-}
-
-/*
- * ia64_mca_cmc_poll
- *
- * Poll for Corrected Machine Checks (CMCs)
- *
- * Inputs : dummy(unused)
- * Outputs : None
- *
- */
-static void
-ia64_mca_cmc_poll (struct timer_list *unused)
-{
- /* Trigger a CMC interrupt cascade */
- ia64_send_ipi(cpumask_first(cpu_online_mask), IA64_CMCP_VECTOR,
- IA64_IPI_DM_INT, 0);
-}
-
-/*
- * ia64_mca_cpe_int_caller
- *
- * Triggered by sw interrupt from CPE polling routine. Calls
- * real interrupt handler and either triggers a sw interrupt
- * on the next cpu or does cleanup at the end.
- *
- * Inputs
- * interrupt number
- * client data arg ptr
- * Outputs
- * handled
- */
-static irqreturn_t
-ia64_mca_cpe_int_caller(int cpe_irq, void *arg)
-{
- static int start_count = -1;
- static int poll_time = MIN_CPE_POLL_INTERVAL;
- unsigned int cpuid;
-
- cpuid = smp_processor_id();
-
- /* If first cpu, update count */
- if (start_count == -1)
- start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CPE);
-
- ia64_mca_cpe_int_handler(cpe_irq, arg);
-
- cpuid = cpumask_next(cpuid+1, cpu_online_mask);
-
- if (cpuid < NR_CPUS) {
- ia64_send_ipi(cpuid, IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0);
- } else {
- /*
- * If a log was recorded, increase our polling frequency,
- * otherwise, backoff or return to interrupt mode.
- */
- if (start_count != IA64_LOG_COUNT(SAL_INFO_TYPE_CPE)) {
- poll_time = max(MIN_CPE_POLL_INTERVAL, poll_time / 2);
- } else if (cpe_vector < 0) {
- poll_time = min(MAX_CPE_POLL_INTERVAL, poll_time * 2);
- } else {
- poll_time = MIN_CPE_POLL_INTERVAL;
-
- printk(KERN_WARNING "Returning to interrupt driven CPE handler\n");
- enable_irq(local_vector_to_irq(IA64_CPE_VECTOR));
- cpe_poll_enabled = 0;
- }
-
- if (cpe_poll_enabled)
- mod_timer(&cpe_poll_timer, jiffies + poll_time);
- start_count = -1;
- }
-
- return IRQ_HANDLED;
-}
-
-/*
- * ia64_mca_cpe_poll
- *
- * Poll for Corrected Platform Errors (CPEs), trigger interrupt
- * on first cpu, from there it will trickle through all the cpus.
- *
- * Inputs : dummy(unused)
- * Outputs : None
- *
- */
-static void
-ia64_mca_cpe_poll (struct timer_list *unused)
-{
- /* Trigger a CPE interrupt cascade */
- ia64_send_ipi(cpumask_first(cpu_online_mask), IA64_CPEP_VECTOR,
- IA64_IPI_DM_INT, 0);
-}
-
-static int
-default_monarch_init_process(struct notifier_block *self, unsigned long val, void *data)
-{
- int c;
- struct task_struct *g, *t;
- if (val != DIE_INIT_MONARCH_PROCESS)
- return NOTIFY_DONE;
-#ifdef CONFIG_KEXEC
- if (atomic_read(&kdump_in_progress))
- return NOTIFY_DONE;
-#endif
-
- /*
- * FIXME: mlogbuf will brim over with INIT stack dumps.
- * To enable show_stack from INIT, we use oops_in_progress which should
- * be used in real oops. This would cause something wrong after INIT.
- */
- BREAK_LOGLEVEL(console_loglevel);
- ia64_mlogbuf_dump_from_init();
-
- printk(KERN_ERR "Processes interrupted by INIT -");
- for_each_online_cpu(c) {
- struct ia64_sal_os_state *s;
- t = __va(__per_cpu_mca[c] + IA64_MCA_CPU_INIT_STACK_OFFSET);
- s = (struct ia64_sal_os_state *)((char *)t + MCA_SOS_OFFSET);
- g = s->prev_task;
- if (g) {
- if (g->pid)
- printk(" %d", g->pid);
- else
- printk(" %d (cpu %d task 0x%p)", g->pid, task_cpu(g), g);
- }
- }
- printk("\n\n");
- if (read_trylock(&tasklist_lock)) {
- for_each_process_thread(g, t) {
- printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm);
- show_stack(t, NULL, KERN_DEFAULT);
- }
- read_unlock(&tasklist_lock);
- }
- /* FIXME: This will not restore zapped printk locks. */
- RESTORE_LOGLEVEL(console_loglevel);
- return NOTIFY_DONE;
-}
-
-/*
- * C portion of the OS INIT handler
- *
- * Called from ia64_os_init_dispatch
- *
- * Inputs: pointer to pt_regs where processor info was saved. SAL/OS state for
- * this event. This code is used for both monarch and slave INIT events, see
- * sos->monarch.
- *
- * All INIT events switch to the INIT stack and change the previous process to
- * blocked status. If one of the INIT events is the monarch then we are
- * probably processing the nmi button/command. Use the monarch cpu to dump all
- * the processes. The slave INIT events all spin until the monarch cpu
- * returns. We can also get INIT slave events for MCA, in which case the MCA
- * process is the monarch.
- */
-
-void
-ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
- struct ia64_sal_os_state *sos)
-{
- static atomic_t slaves;
- static atomic_t monarchs;
- struct task_struct *previous_current;
- int cpu = smp_processor_id();
- struct ia64_mca_notify_die nd =
- { .sos = sos, .monarch_cpu = &monarch_cpu };
-
- NOTIFY_INIT(DIE_INIT_ENTER, regs, (long)&nd, 0);
-
- mprintk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
- sos->proc_state_param, cpu, sos->monarch);
- salinfo_log_wakeup(SAL_INFO_TYPE_INIT, NULL, 0, 0);
-
- previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "INIT");
- sos->os_status = IA64_INIT_RESUME;
-
- /* FIXME: Workaround for broken proms that drive all INIT events as
- * slaves. The last slave that enters is promoted to be a monarch.
- * Remove this code in September 2006, that gives platforms a year to
- * fix their proms and get their customers updated.
- */
- if (!sos->monarch && atomic_add_return(1, &slaves) == num_online_cpus()) {
- mprintk(KERN_WARNING "%s: Promoting cpu %d to monarch.\n",
- __func__, cpu);
- atomic_dec(&slaves);
- sos->monarch = 1;
- }
-
- /* FIXME: Workaround for broken proms that drive all INIT events as
- * monarchs. Second and subsequent monarchs are demoted to slaves.
- * Remove this code in September 2006, that gives platforms a year to
- * fix their proms and get their customers updated.
- */
- if (sos->monarch && atomic_add_return(1, &monarchs) > 1) {
- mprintk(KERN_WARNING "%s: Demoting cpu %d to slave.\n",
- __func__, cpu);
- atomic_dec(&monarchs);
- sos->monarch = 0;
- }
-
- if (!sos->monarch) {
- ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT;
-
-#ifdef CONFIG_KEXEC
- while (monarch_cpu == -1 && !atomic_read(&kdump_in_progress))
- udelay(1000);
-#else
- while (monarch_cpu == -1)
- cpu_relax(); /* spin until monarch enters */
-#endif
-
- NOTIFY_INIT(DIE_INIT_SLAVE_ENTER, regs, (long)&nd, 1);
- NOTIFY_INIT(DIE_INIT_SLAVE_PROCESS, regs, (long)&nd, 1);
-
-#ifdef CONFIG_KEXEC
- while (monarch_cpu != -1 && !atomic_read(&kdump_in_progress))
- udelay(1000);
-#else
- while (monarch_cpu != -1)
- cpu_relax(); /* spin until monarch leaves */
-#endif
-
- NOTIFY_INIT(DIE_INIT_SLAVE_LEAVE, regs, (long)&nd, 1);
-
- mprintk("Slave on cpu %d returning to normal service.\n", cpu);
- ia64_set_curr_task(cpu, previous_current);
- ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
- atomic_dec(&slaves);
- return;
- }
-
- monarch_cpu = cpu;
- NOTIFY_INIT(DIE_INIT_MONARCH_ENTER, regs, (long)&nd, 1);
-
- /*
- * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be
- * generated via the BMC's command-line interface, but since the console is on the
- * same serial line, the user will need some time to switch out of the BMC before
- * the dump begins.
- */
- mprintk("Delaying for 5 seconds...\n");
- udelay(5*1000000);
- ia64_wait_for_slaves(cpu, "INIT");
- /* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through
- * to default_monarch_init_process() above and just print all the
- * tasks.
- */
- NOTIFY_INIT(DIE_INIT_MONARCH_PROCESS, regs, (long)&nd, 1);
- NOTIFY_INIT(DIE_INIT_MONARCH_LEAVE, regs, (long)&nd, 1);
-
- mprintk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu);
- atomic_dec(&monarchs);
- ia64_set_curr_task(cpu, previous_current);
- monarch_cpu = -1;
- return;
-}
-
-static int __init
-ia64_mca_disable_cpe_polling(char *str)
-{
- cpe_poll_enabled = 0;
- return 1;
-}
-
-__setup("disable_cpe_poll", ia64_mca_disable_cpe_polling);
-
-/* Minimal format of the MCA/INIT stacks. The pseudo processes that run on
- * these stacks can never sleep, they cannot return from the kernel to user
- * space, they do not appear in a normal ps listing. So there is no need to
- * format most of the fields.
- */
-
-static void
-format_mca_init_stack(void *mca_data, unsigned long offset,
- const char *type, int cpu)
-{
- struct task_struct *p = (struct task_struct *)((char *)mca_data + offset);
- struct thread_info *ti;
- memset(p, 0, KERNEL_STACK_SIZE);
- ti = task_thread_info(p);
- ti->flags = _TIF_MCA_INIT;
- ti->preempt_count = 1;
- ti->task = p;
- ti->cpu = cpu;
- p->stack = ti;
- p->__state = TASK_UNINTERRUPTIBLE;
- cpumask_set_cpu(cpu, &p->cpus_mask);
- INIT_LIST_HEAD(&p->tasks);
- p->parent = p->real_parent = p->group_leader = p;
- INIT_LIST_HEAD(&p->children);
- INIT_LIST_HEAD(&p->sibling);
- strscpy(p->comm, type, sizeof(p->comm)-1);
-}
-
-/* Caller prevents this from being called after init */
-static void * __ref mca_bootmem(void)
-{
- return memblock_alloc(sizeof(struct ia64_mca_cpu), KERNEL_STACK_SIZE);
-}
-
-/* Do per-CPU MCA-related initialization. */
-void
-ia64_mca_cpu_init(void *cpu_data)
-{
- void *pal_vaddr;
- void *data;
- long sz = sizeof(struct ia64_mca_cpu);
- int cpu = smp_processor_id();
- static int first_time = 1;
-
- /*
- * Structure will already be allocated if cpu has been online,
- * then offlined.
- */
- if (__per_cpu_mca[cpu]) {
- data = __va(__per_cpu_mca[cpu]);
- } else {
- if (first_time) {
- data = mca_bootmem();
- first_time = 0;
- } else
- data = (void *)__get_free_pages(GFP_ATOMIC,
- get_order(sz));
- if (!data)
- panic("Could not allocate MCA memory for cpu %d\n",
- cpu);
- }
- format_mca_init_stack(data, offsetof(struct ia64_mca_cpu, mca_stack),
- "MCA", cpu);
- format_mca_init_stack(data, offsetof(struct ia64_mca_cpu, init_stack),
- "INIT", cpu);
- __this_cpu_write(ia64_mca_data, (__per_cpu_mca[cpu] = __pa(data)));
-
- /*
- * Stash away a copy of the PTE needed to map the per-CPU page.
- * We may need it during MCA recovery.
- */
- __this_cpu_write(ia64_mca_per_cpu_pte,
- pte_val(mk_pte_phys(__pa(cpu_data), PAGE_KERNEL)));
-
- /*
- * Also, stash away a copy of the PAL address and the PTE
- * needed to map it.
- */
- pal_vaddr = efi_get_pal_addr();
- if (!pal_vaddr)
- return;
- __this_cpu_write(ia64_mca_pal_base,
- GRANULEROUNDDOWN((unsigned long) pal_vaddr));
- __this_cpu_write(ia64_mca_pal_pte, pte_val(mk_pte_phys(__pa(pal_vaddr),
- PAGE_KERNEL)));
-}
-
-static int ia64_mca_cpu_online(unsigned int cpu)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- if (!cmc_polling_enabled)
- ia64_mca_cmc_vector_enable(NULL);
- local_irq_restore(flags);
- return 0;
-}
-
-/*
- * ia64_mca_init
- *
- * Do all the system level mca specific initialization.
- *
- * 1. Register spinloop and wakeup request interrupt vectors
- *
- * 2. Register OS_MCA handler entry point
- *
- * 3. Register OS_INIT handler entry point
- *
- * 4. Initialize MCA/CMC/INIT related log buffers maintained by the OS.
- *
- * Note that this initialization is done very early before some kernel
- * services are available.
- *
- * Inputs : None
- *
- * Outputs : None
- */
-void __init
-ia64_mca_init(void)
-{
- ia64_fptr_t *init_hldlr_ptr_monarch = (ia64_fptr_t *)ia64_os_init_dispatch_monarch;
- ia64_fptr_t *init_hldlr_ptr_slave = (ia64_fptr_t *)ia64_os_init_dispatch_slave;
- ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;
- int i;
- long rc;
- struct ia64_sal_retval isrv;
- unsigned long timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */
- static struct notifier_block default_init_monarch_nb = {
- .notifier_call = default_monarch_init_process,
- .priority = 0/* we need to notified last */
- };
-
- IA64_MCA_DEBUG("%s: begin\n", __func__);
-
- /* Clear the Rendez checkin flag for all cpus */
- for(i = 0 ; i < NR_CPUS; i++)
- ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
-
- /*
- * Register the rendezvous spinloop and wakeup mechanism with SAL
- */
-
- /* Register the rendezvous interrupt vector with SAL */
- while (1) {
- isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
- SAL_MC_PARAM_MECHANISM_INT,
- IA64_MCA_RENDEZ_VECTOR,
- timeout,
- SAL_MC_PARAM_RZ_ALWAYS);
- rc = isrv.status;
- if (rc == 0)
- break;
- if (rc == -2) {
- printk(KERN_INFO "Increasing MCA rendezvous timeout from "
- "%ld to %ld milliseconds\n", timeout, isrv.v0);
- timeout = isrv.v0;
- NOTIFY_MCA(DIE_MCA_NEW_TIMEOUT, NULL, timeout, 0);
- continue;
- }
- printk(KERN_ERR "Failed to register rendezvous interrupt "
- "with SAL (status %ld)\n", rc);
- return;
- }
-
- /* Register the wakeup interrupt vector with SAL */
- isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
- SAL_MC_PARAM_MECHANISM_INT,
- IA64_MCA_WAKEUP_VECTOR,
- 0, 0);
- rc = isrv.status;
- if (rc) {
- printk(KERN_ERR "Failed to register wakeup interrupt with SAL "
- "(status %ld)\n", rc);
- return;
- }
-
- IA64_MCA_DEBUG("%s: registered MCA rendezvous spinloop and wakeup mech.\n", __func__);
-
- ia64_mc_info.imi_mca_handler = ia64_tpa(mca_hldlr_ptr->fp);
- /*
- * XXX - disable SAL checksum by setting size to 0; should be
- * ia64_tpa(ia64_os_mca_dispatch_end) - ia64_tpa(ia64_os_mca_dispatch);
- */
- ia64_mc_info.imi_mca_handler_size = 0;
-
- /* Register the os mca handler with SAL */
- if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,
- ia64_mc_info.imi_mca_handler,
- ia64_tpa(mca_hldlr_ptr->gp),
- ia64_mc_info.imi_mca_handler_size,
- 0, 0, 0)))
- {
- printk(KERN_ERR "Failed to register OS MCA handler with SAL "
- "(status %ld)\n", rc);
- return;
- }
-
- IA64_MCA_DEBUG("%s: registered OS MCA handler with SAL at 0x%lx, gp = 0x%lx\n", __func__,
- ia64_mc_info.imi_mca_handler, ia64_tpa(mca_hldlr_ptr->gp));
-
- /*
- * XXX - disable SAL checksum by setting size to 0, should be
- * size of the actual init handler in mca_asm.S.
- */
- ia64_mc_info.imi_monarch_init_handler = ia64_tpa(init_hldlr_ptr_monarch->fp);
- ia64_mc_info.imi_monarch_init_handler_size = 0;
- ia64_mc_info.imi_slave_init_handler = ia64_tpa(init_hldlr_ptr_slave->fp);
- ia64_mc_info.imi_slave_init_handler_size = 0;
-
- IA64_MCA_DEBUG("%s: OS INIT handler at %lx\n", __func__,
- ia64_mc_info.imi_monarch_init_handler);
-
- /* Register the os init handler with SAL */
- if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT,
- ia64_mc_info.imi_monarch_init_handler,
- ia64_tpa(ia64_getreg(_IA64_REG_GP)),
- ia64_mc_info.imi_monarch_init_handler_size,
- ia64_mc_info.imi_slave_init_handler,
- ia64_tpa(ia64_getreg(_IA64_REG_GP)),
- ia64_mc_info.imi_slave_init_handler_size)))
- {
- printk(KERN_ERR "Failed to register m/s INIT handlers with SAL "
- "(status %ld)\n", rc);
- return;
- }
- if (register_die_notifier(&default_init_monarch_nb)) {
- printk(KERN_ERR "Failed to register default monarch INIT process\n");
- return;
- }
-
- IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __func__);
-
- /* Initialize the areas set aside by the OS to buffer the
- * platform/processor error states for MCA/INIT/CMC
- * handling.
- */
- ia64_log_init(SAL_INFO_TYPE_MCA);
- ia64_log_init(SAL_INFO_TYPE_INIT);
- ia64_log_init(SAL_INFO_TYPE_CMC);
- ia64_log_init(SAL_INFO_TYPE_CPE);
-
- mca_init = 1;
- printk(KERN_INFO "MCA related initialization done\n");
-}
-
-
-/*
- * These pieces cannot be done in ia64_mca_init() because it is called before
- * early_irq_init() which would wipe out our percpu irq registrations. But we
- * cannot leave them until ia64_mca_late_init() because by then all the other
- * processors have been brought online and have set their own CMC vectors to
- * point at a non-existant action. Called from arch_early_irq_init().
- */
-void __init ia64_mca_irq_init(void)
-{
- /*
- * Configure the CMCI/P vector and handler. Interrupts for CMC are
- * per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
- */
- register_percpu_irq(IA64_CMC_VECTOR, ia64_mca_cmc_int_handler, 0,
- "cmc_hndlr");
- register_percpu_irq(IA64_CMCP_VECTOR, ia64_mca_cmc_int_caller, 0,
- "cmc_poll");
- ia64_mca_cmc_vector_setup(); /* Setup vector on BSP */
-
- /* Setup the MCA rendezvous interrupt vector */
- register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, ia64_mca_rendez_int_handler,
- 0, "mca_rdzv");
-
- /* Setup the MCA wakeup interrupt vector */
- register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, ia64_mca_wakeup_int_handler,
- 0, "mca_wkup");
-
- /* Setup the CPEI/P handler */
- register_percpu_irq(IA64_CPEP_VECTOR, ia64_mca_cpe_int_caller, 0,
- "cpe_poll");
-}
-
-/*
- * ia64_mca_late_init
- *
- * Opportunity to setup things that require initialization later
- * than ia64_mca_init. Setup a timer to poll for CPEs if the
- * platform doesn't support an interrupt driven mechanism.
- *
- * Inputs : None
- * Outputs : Status
- */
-static int __init
-ia64_mca_late_init(void)
-{
- if (!mca_init)
- return 0;
-
- /* Setup the CMCI/P vector and handler */
- timer_setup(&cmc_poll_timer, ia64_mca_cmc_poll, 0);
-
- /* Unmask/enable the vector */
- cmc_polling_enabled = 0;
- cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/mca:online",
- ia64_mca_cpu_online, NULL);
- IA64_MCA_DEBUG("%s: CMCI/P setup and enabled.\n", __func__);
-
- /* Setup the CPEI/P vector and handler */
- cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI);
- timer_setup(&cpe_poll_timer, ia64_mca_cpe_poll, 0);
-
- {
- unsigned int irq;
-
- if (cpe_vector >= 0) {
- /* If platform supports CPEI, enable the irq. */
- irq = local_vector_to_irq(cpe_vector);
- if (irq > 0) {
- cpe_poll_enabled = 0;
- irq_set_status_flags(irq, IRQ_PER_CPU);
- if (request_irq(irq, ia64_mca_cpe_int_handler,
- 0, "cpe_hndlr", NULL))
- pr_err("Failed to register cpe_hndlr interrupt\n");
- ia64_cpe_irq = irq;
- ia64_mca_register_cpev(cpe_vector);
- IA64_MCA_DEBUG("%s: CPEI/P setup and enabled.\n",
- __func__);
- return 0;
- }
- printk(KERN_ERR "%s: Failed to find irq for CPE "
- "interrupt handler, vector %d\n",
- __func__, cpe_vector);
- }
- /* If platform doesn't support CPEI, get the timer going. */
- if (cpe_poll_enabled) {
- ia64_mca_cpe_poll(0UL);
- IA64_MCA_DEBUG("%s: CPEP setup and enabled.\n", __func__);
- }
- }
-
- return 0;
-}
-
-device_initcall(ia64_mca_late_init);
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
deleted file mode 100644
index 0d6b8cf9d1d0..000000000000
--- a/arch/ia64/kernel/mca_asm.S
+++ /dev/null
@@ -1,1123 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * File: mca_asm.S
- * Purpose: assembly portion of the IA64 MCA handling
- *
- * Mods by cfleck to integrate into kernel build
- *
- * 2000-03-15 David Mosberger-Tang <davidm@hpl.hp.com>
- * Added various stop bits to get a clean compile
- *
- * 2000-03-29 Chuck Fleckenstein <cfleck@co.intel.com>
- * Added code to save INIT handoff state in pt_regs format,
- * switch to temp kstack, switch modes, jump to C INIT handler
- *
- * 2002-01-04 J.Hall <jenna.s.hall@intel.com>
- * Before entering virtual mode code:
- * 1. Check for TLB CPU error
- * 2. Restore current thread pointer to kr6
- * 3. Move stack ptr 16 bytes to conform to C calling convention
- *
- * 2004-11-12 Russ Anderson <rja@sgi.com>
- * Added per cpu MCA/INIT stack save areas.
- *
- * 2005-12-08 Keith Owens <kaos@sgi.com>
- * Use per cpu MCA/INIT stacks for all data.
- */
-#include <linux/threads.h>
-#include <linux/pgtable.h>
-
-#include <asm/asmmacro.h>
-#include <asm/processor.h>
-#include <asm/mca_asm.h>
-#include <asm/mca.h>
-
-#include "entry.h"
-
-#define GET_IA64_MCA_DATA(reg) \
- GET_THIS_PADDR(reg, ia64_mca_data) \
- ;; \
- ld8 reg=[reg]
-
- .global ia64_do_tlb_purge
- .global ia64_os_mca_dispatch
- .global ia64_os_init_on_kdump
- .global ia64_os_init_dispatch_monarch
- .global ia64_os_init_dispatch_slave
-
- .text
- .align 16
-
-//StartMain////////////////////////////////////////////////////////////////////
-
-/*
- * Just the TLB purge part is moved to a separate function
- * so we can re-use the code for cpu hotplug code as well
- * Caller should now setup b1, so we can branch once the
- * tlb flush is complete.
- */
-
-ia64_do_tlb_purge:
-#define O(member) IA64_CPUINFO_##member##_OFFSET
-
- GET_THIS_PADDR(r2, ia64_cpu_info) // load phys addr of cpu_info into r2
- ;;
- addl r17=O(PTCE_STRIDE),r2
- addl r2=O(PTCE_BASE),r2
- ;;
- ld8 r18=[r2],(O(PTCE_COUNT)-O(PTCE_BASE));; // r18=ptce_base
- ld4 r19=[r2],4 // r19=ptce_count[0]
- ld4 r21=[r17],4 // r21=ptce_stride[0]
- ;;
- ld4 r20=[r2] // r20=ptce_count[1]
- ld4 r22=[r17] // r22=ptce_stride[1]
- mov r24=0
- ;;
- adds r20=-1,r20
- ;;
-#undef O
-
-2:
- cmp.ltu p6,p7=r24,r19
-(p7) br.cond.dpnt.few 4f
- mov ar.lc=r20
-3:
- ptc.e r18
- ;;
- add r18=r22,r18
- br.cloop.sptk.few 3b
- ;;
- add r18=r21,r18
- add r24=1,r24
- ;;
- br.sptk.few 2b
-4:
- srlz.i // srlz.i implies srlz.d
- ;;
-
- // Now purge addresses formerly mapped by TR registers
- // 1. Purge ITR&DTR for kernel.
- movl r16=KERNEL_START
- mov r18=KERNEL_TR_PAGE_SHIFT<<2
- ;;
- ptr.i r16, r18
- ptr.d r16, r18
- ;;
- srlz.i
- ;;
- srlz.d
- ;;
- // 3. Purge ITR for PAL code.
- GET_THIS_PADDR(r2, ia64_mca_pal_base)
- ;;
- ld8 r16=[r2]
- mov r18=IA64_GRANULE_SHIFT<<2
- ;;
- ptr.i r16,r18
- ;;
- srlz.i
- ;;
- // 4. Purge DTR for stack.
- mov r16=IA64_KR(CURRENT_STACK)
- ;;
- shl r16=r16,IA64_GRANULE_SHIFT
- movl r19=PAGE_OFFSET
- ;;
- add r16=r19,r16
- mov r18=IA64_GRANULE_SHIFT<<2
- ;;
- ptr.d r16,r18
- ;;
- srlz.i
- ;;
- // Now branch away to caller.
- br.sptk.many b1
- ;;
-
-//EndMain//////////////////////////////////////////////////////////////////////
-
-//StartMain////////////////////////////////////////////////////////////////////
-
-ia64_os_mca_dispatch:
- mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack
- LOAD_PHYSICAL(p0,r2,1f) // return address
- mov r19=1 // All MCA events are treated as monarch (for now)
- br.sptk ia64_state_save // save the state that is not in minstate
-1:
-
- GET_IA64_MCA_DATA(r2)
- // Using MCA stack, struct ia64_sal_os_state, variable proc_state_param
- ;;
- add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+SOS(PROC_STATE_PARAM), r2
- ;;
- ld8 r18=[r3] // Get processor state parameter on existing PALE_CHECK.
- ;;
- tbit.nz p6,p7=r18,60
-(p7) br.spnt done_tlb_purge_and_reload
-
- // The following code purges TC and TR entries. Then reload all TC entries.
- // Purge percpu data TC entries.
-begin_tlb_purge_and_reload:
- movl r18=ia64_reload_tr;;
- LOAD_PHYSICAL(p0,r18,ia64_reload_tr);;
- mov b1=r18;;
- br.sptk.many ia64_do_tlb_purge;;
-
-ia64_reload_tr:
- // Finally reload the TR registers.
- // 1. Reload DTR/ITR registers for kernel.
- mov r18=KERNEL_TR_PAGE_SHIFT<<2
- movl r17=KERNEL_START
- ;;
- mov cr.itir=r18
- mov cr.ifa=r17
- mov r16=IA64_TR_KERNEL
- mov r19=ip
- movl r18=PAGE_KERNEL
- ;;
- dep r17=0,r19,0, KERNEL_TR_PAGE_SHIFT
- ;;
- or r18=r17,r18
- ;;
- itr.i itr[r16]=r18
- ;;
- itr.d dtr[r16]=r18
- ;;
- srlz.i
- srlz.d
- ;;
- // 3. Reload ITR for PAL code.
- GET_THIS_PADDR(r2, ia64_mca_pal_pte)
- ;;
- ld8 r18=[r2] // load PAL PTE
- ;;
- GET_THIS_PADDR(r2, ia64_mca_pal_base)
- ;;
- ld8 r16=[r2] // load PAL vaddr
- mov r19=IA64_GRANULE_SHIFT<<2
- ;;
- mov cr.itir=r19
- mov cr.ifa=r16
- mov r20=IA64_TR_PALCODE
- ;;
- itr.i itr[r20]=r18
- ;;
- srlz.i
- ;;
- // 4. Reload DTR for stack.
- mov r16=IA64_KR(CURRENT_STACK)
- ;;
- shl r16=r16,IA64_GRANULE_SHIFT
- movl r19=PAGE_OFFSET
- ;;
- add r18=r19,r16
- movl r20=PAGE_KERNEL
- ;;
- add r16=r20,r16
- mov r19=IA64_GRANULE_SHIFT<<2
- ;;
- mov cr.itir=r19
- mov cr.ifa=r18
- mov r20=IA64_TR_CURRENT_STACK
- ;;
- itr.d dtr[r20]=r16
- GET_THIS_PADDR(r2, ia64_mca_tr_reload)
- mov r18 = 1
- ;;
- srlz.d
- ;;
- st8 [r2] =r18
- ;;
-
-done_tlb_purge_and_reload:
-
- // switch to per cpu MCA stack
- mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack
- LOAD_PHYSICAL(p0,r2,1f) // return address
- br.sptk ia64_new_stack
-1:
-
- // everything saved, now we can set the kernel registers
- mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack
- LOAD_PHYSICAL(p0,r2,1f) // return address
- br.sptk ia64_set_kernel_registers
-1:
-
- // This must be done in physical mode
- GET_IA64_MCA_DATA(r2)
- ;;
- mov r7=r2
-
- // Enter virtual mode from physical mode
- VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4)
-
- // This code returns to SAL via SOS r2, in general SAL has no unwind
- // data. To get a clean termination when backtracing the C MCA/INIT
- // handler, set a dummy return address of 0 in this routine. That
- // requires that ia64_os_mca_virtual_begin be a global function.
-ENTRY(ia64_os_mca_virtual_begin)
- .prologue
- .save rp,r0
- .body
-
- mov ar.rsc=3 // set eager mode for C handler
- mov r2=r7 // see GET_IA64_MCA_DATA above
- ;;
-
- // Call virtual mode handler
- alloc r14=ar.pfs,0,0,3,0
- ;;
- DATA_PA_TO_VA(r2,r7)
- ;;
- add out0=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_PT_REGS_OFFSET, r2
- add out1=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SWITCH_STACK_OFFSET, r2
- add out2=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET, r2
- br.call.sptk.many b0=ia64_mca_handler
-
- // Revert back to physical mode before going back to SAL
- PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4)
-ia64_os_mca_virtual_end:
-
-END(ia64_os_mca_virtual_begin)
-
- // switch back to previous stack
- alloc r14=ar.pfs,0,0,0,0 // remove the MCA handler frame
- mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack
- LOAD_PHYSICAL(p0,r2,1f) // return address
- br.sptk ia64_old_stack
-1:
-
- mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack
- LOAD_PHYSICAL(p0,r2,1f) // return address
- br.sptk ia64_state_restore // restore the SAL state
-1:
-
- mov b0=r12 // SAL_CHECK return address
-
- br b0
-
-//EndMain//////////////////////////////////////////////////////////////////////
-
-//StartMain////////////////////////////////////////////////////////////////////
-
-//
-// NOP init handler for kdump. In panic situation, we may receive INIT
-// while kernel transition. Since we initialize registers on leave from
-// current kernel, no longer monarch/slave handlers of current kernel in
-// virtual mode are called safely.
-// We can unregister these init handlers from SAL, however then the INIT
-// will result in warmboot by SAL and we cannot retrieve the crashdump.
-// Therefore register this NOP function to SAL, to prevent entering virtual
-// mode and resulting warmboot by SAL.
-//
-ia64_os_init_on_kdump:
- mov r8=r0 // IA64_INIT_RESUME
- mov r9=r10 // SAL_GP
- mov r22=r17 // *minstate
- ;;
- mov r10=r0 // return to same context
- mov b0=r12 // SAL_CHECK return address
- br b0
-
-//
-// SAL to OS entry point for INIT on all processors. This has been defined for
-// registration purposes with SAL as a part of ia64_mca_init. Monarch and
-// slave INIT have identical processing, except for the value of the
-// sos->monarch flag in r19.
-//
-
-ia64_os_init_dispatch_monarch:
- mov r19=1 // Bow, bow, ye lower middle classes!
- br.sptk ia64_os_init_dispatch
-
-ia64_os_init_dispatch_slave:
- mov r19=0 // <igor>yeth, mathter</igor>
-
-ia64_os_init_dispatch:
-
- mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack
- LOAD_PHYSICAL(p0,r2,1f) // return address
- br.sptk ia64_state_save // save the state that is not in minstate
-1:
-
- // switch to per cpu INIT stack
- mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack
- LOAD_PHYSICAL(p0,r2,1f) // return address
- br.sptk ia64_new_stack
-1:
-
- // everything saved, now we can set the kernel registers
- mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack
- LOAD_PHYSICAL(p0,r2,1f) // return address
- br.sptk ia64_set_kernel_registers
-1:
-
- // This must be done in physical mode
- GET_IA64_MCA_DATA(r2)
- ;;
- mov r7=r2
-
- // Enter virtual mode from physical mode
- VIRTUAL_MODE_ENTER(r2, r3, ia64_os_init_virtual_begin, r4)
-
- // This code returns to SAL via SOS r2, in general SAL has no unwind
- // data. To get a clean termination when backtracing the C MCA/INIT
- // handler, set a dummy return address of 0 in this routine. That
- // requires that ia64_os_init_virtual_begin be a global function.
-ENTRY(ia64_os_init_virtual_begin)
- .prologue
- .save rp,r0
- .body
-
- mov ar.rsc=3 // set eager mode for C handler
- mov r2=r7 // see GET_IA64_MCA_DATA above
- ;;
-
- // Call virtual mode handler
- alloc r14=ar.pfs,0,0,3,0
- ;;
- DATA_PA_TO_VA(r2,r7)
- ;;
- add out0=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_PT_REGS_OFFSET, r2
- add out1=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_SWITCH_STACK_OFFSET, r2
- add out2=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_SOS_OFFSET, r2
- br.call.sptk.many b0=ia64_init_handler
-
- // Revert back to physical mode before going back to SAL
- PHYSICAL_MODE_ENTER(r2, r3, ia64_os_init_virtual_end, r4)
-ia64_os_init_virtual_end:
-
-END(ia64_os_init_virtual_begin)
-
- mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack
- LOAD_PHYSICAL(p0,r2,1f) // return address
- br.sptk ia64_state_restore // restore the SAL state
-1:
-
- // switch back to previous stack
- alloc r14=ar.pfs,0,0,0,0 // remove the INIT handler frame
- mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack
- LOAD_PHYSICAL(p0,r2,1f) // return address
- br.sptk ia64_old_stack
-1:
-
- mov b0=r12 // SAL_CHECK return address
- br b0
-
-//EndMain//////////////////////////////////////////////////////////////////////
-
-// common defines for the stubs
-#define ms r4
-#define regs r5
-#define temp1 r2 /* careful, it overlaps with input registers */
-#define temp2 r3 /* careful, it overlaps with input registers */
-#define temp3 r7
-#define temp4 r14
-
-
-//++
-// Name:
-// ia64_state_save()
-//
-// Stub Description:
-//
-// Save the state that is not in minstate. This is sensitive to the layout of
-// struct ia64_sal_os_state in mca.h.
-//
-// r2 contains the return address, r3 contains either
-// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
-//
-// The OS to SAL section of struct ia64_sal_os_state is set to a default
-// value of cold boot (MCA) or warm boot (INIT) and return to the same
-// context. ia64_sal_os_state is also used to hold some registers that
-// need to be saved and restored across the stack switches.
-//
-// Most input registers to this stub come from PAL/SAL
-// r1 os gp, physical
-// r8 pal_proc entry point
-// r9 sal_proc entry point
-// r10 sal gp
-// r11 MCA - rendevzous state, INIT - reason code
-// r12 sal return address
-// r17 pal min_state
-// r18 processor state parameter
-// r19 monarch flag, set by the caller of this routine
-//
-// In addition to the SAL to OS state, this routine saves all the
-// registers that appear in struct pt_regs and struct switch_stack,
-// excluding those that are already in the PAL minstate area. This
-// results in a partial pt_regs and switch_stack, the C code copies the
-// remaining registers from PAL minstate to pt_regs and switch_stack. The
-// resulting structures contain all the state of the original process when
-// MCA/INIT occurred.
-//
-//--
-
-ia64_state_save:
- add regs=MCA_SOS_OFFSET, r3
- add ms=MCA_SOS_OFFSET+8, r3
- mov b0=r2 // save return address
- cmp.eq p1,p2=IA64_MCA_CPU_MCA_STACK_OFFSET, r3
- ;;
- GET_IA64_MCA_DATA(temp2)
- ;;
- add temp1=temp2, regs // struct ia64_sal_os_state on MCA or INIT stack
- add temp2=temp2, ms // struct ia64_sal_os_state+8 on MCA or INIT stack
- ;;
- mov regs=temp1 // save the start of sos
- st8 [temp1]=r1,16 // os_gp
- st8 [temp2]=r8,16 // pal_proc
- ;;
- st8 [temp1]=r9,16 // sal_proc
- st8 [temp2]=r11,16 // rv_rc
- mov r11=cr.iipa
- ;;
- st8 [temp1]=r18 // proc_state_param
- st8 [temp2]=r19 // monarch
- mov r6=IA64_KR(CURRENT)
- add temp1=SOS(SAL_RA), regs
- add temp2=SOS(SAL_GP), regs
- ;;
- st8 [temp1]=r12,16 // sal_ra
- st8 [temp2]=r10,16 // sal_gp
- mov r12=cr.isr
- ;;
- st8 [temp1]=r17,16 // pal_min_state
- st8 [temp2]=r6,16 // prev_IA64_KR_CURRENT
- mov r6=IA64_KR(CURRENT_STACK)
- ;;
- st8 [temp1]=r6,16 // prev_IA64_KR_CURRENT_STACK
- st8 [temp2]=r0,16 // prev_task, starts off as NULL
- mov r6=cr.ifa
- ;;
- st8 [temp1]=r12,16 // cr.isr
- st8 [temp2]=r6,16 // cr.ifa
- mov r12=cr.itir
- ;;
- st8 [temp1]=r12,16 // cr.itir
- st8 [temp2]=r11,16 // cr.iipa
- mov r12=cr.iim
- ;;
- st8 [temp1]=r12 // cr.iim
-(p1) mov r12=IA64_MCA_COLD_BOOT
-(p2) mov r12=IA64_INIT_WARM_BOOT
- mov r6=cr.iha
- add temp1=SOS(OS_STATUS), regs
- ;;
- st8 [temp2]=r6 // cr.iha
- add temp2=SOS(CONTEXT), regs
- st8 [temp1]=r12 // os_status, default is cold boot
- mov r6=IA64_MCA_SAME_CONTEXT
- ;;
- st8 [temp2]=r6 // context, default is same context
-
- // Save the pt_regs data that is not in minstate. The previous code
- // left regs at sos.
- add regs=MCA_PT_REGS_OFFSET-MCA_SOS_OFFSET, regs
- ;;
- add temp1=PT(B6), regs
- mov temp3=b6
- mov temp4=b7
- add temp2=PT(B7), regs
- ;;
- st8 [temp1]=temp3,PT(AR_CSD)-PT(B6) // save b6
- st8 [temp2]=temp4,PT(AR_SSD)-PT(B7) // save b7
- mov temp3=ar.csd
- mov temp4=ar.ssd
- cover // must be last in group
- ;;
- st8 [temp1]=temp3,PT(AR_UNAT)-PT(AR_CSD) // save ar.csd
- st8 [temp2]=temp4,PT(AR_PFS)-PT(AR_SSD) // save ar.ssd
- mov temp3=ar.unat
- mov temp4=ar.pfs
- ;;
- st8 [temp1]=temp3,PT(AR_RNAT)-PT(AR_UNAT) // save ar.unat
- st8 [temp2]=temp4,PT(AR_BSPSTORE)-PT(AR_PFS) // save ar.pfs
- mov temp3=ar.rnat
- mov temp4=ar.bspstore
- ;;
- st8 [temp1]=temp3,PT(LOADRS)-PT(AR_RNAT) // save ar.rnat
- st8 [temp2]=temp4,PT(AR_FPSR)-PT(AR_BSPSTORE) // save ar.bspstore
- mov temp3=ar.bsp
- ;;
- sub temp3=temp3, temp4 // ar.bsp - ar.bspstore
- mov temp4=ar.fpsr
- ;;
- shl temp3=temp3,16 // compute ar.rsc to be used for "loadrs"
- ;;
- st8 [temp1]=temp3,PT(AR_CCV)-PT(LOADRS) // save loadrs
- st8 [temp2]=temp4,PT(F6)-PT(AR_FPSR) // save ar.fpsr
- mov temp3=ar.ccv
- ;;
- st8 [temp1]=temp3,PT(F7)-PT(AR_CCV) // save ar.ccv
- stf.spill [temp2]=f6,PT(F8)-PT(F6)
- ;;
- stf.spill [temp1]=f7,PT(F9)-PT(F7)
- stf.spill [temp2]=f8,PT(F10)-PT(F8)
- ;;
- stf.spill [temp1]=f9,PT(F11)-PT(F9)
- stf.spill [temp2]=f10
- ;;
- stf.spill [temp1]=f11
-
- // Save the switch_stack data that is not in minstate nor pt_regs. The
- // previous code left regs at pt_regs.
- add regs=MCA_SWITCH_STACK_OFFSET-MCA_PT_REGS_OFFSET, regs
- ;;
- add temp1=SW(F2), regs
- add temp2=SW(F3), regs
- ;;
- stf.spill [temp1]=f2,32
- stf.spill [temp2]=f3,32
- ;;
- stf.spill [temp1]=f4,32
- stf.spill [temp2]=f5,32
- ;;
- stf.spill [temp1]=f12,32
- stf.spill [temp2]=f13,32
- ;;
- stf.spill [temp1]=f14,32
- stf.spill [temp2]=f15,32
- ;;
- stf.spill [temp1]=f16,32
- stf.spill [temp2]=f17,32
- ;;
- stf.spill [temp1]=f18,32
- stf.spill [temp2]=f19,32
- ;;
- stf.spill [temp1]=f20,32
- stf.spill [temp2]=f21,32
- ;;
- stf.spill [temp1]=f22,32
- stf.spill [temp2]=f23,32
- ;;
- stf.spill [temp1]=f24,32
- stf.spill [temp2]=f25,32
- ;;
- stf.spill [temp1]=f26,32
- stf.spill [temp2]=f27,32
- ;;
- stf.spill [temp1]=f28,32
- stf.spill [temp2]=f29,32
- ;;
- stf.spill [temp1]=f30,SW(B2)-SW(F30)
- stf.spill [temp2]=f31,SW(B3)-SW(F31)
- mov temp3=b2
- mov temp4=b3
- ;;
- st8 [temp1]=temp3,16 // save b2
- st8 [temp2]=temp4,16 // save b3
- mov temp3=b4
- mov temp4=b5
- ;;
- st8 [temp1]=temp3,SW(AR_LC)-SW(B4) // save b4
- st8 [temp2]=temp4 // save b5
- mov temp3=ar.lc
- ;;
- st8 [temp1]=temp3 // save ar.lc
-
- // FIXME: Some proms are incorrectly accessing the minstate area as
- // cached data. The C code uses region 6, uncached virtual. Ensure
- // that there is no cache data lying around for the first 1K of the
- // minstate area.
- // Remove this code in September 2006, that gives platforms a year to
- // fix their proms and get their customers updated.
-
- add r1=32*1,r17
- add r2=32*2,r17
- add r3=32*3,r17
- add r4=32*4,r17
- add r5=32*5,r17
- add r6=32*6,r17
- add r7=32*7,r17
- ;;
- fc r17
- fc r1
- fc r2
- fc r3
- fc r4
- fc r5
- fc r6
- fc r7
- add r17=32*8,r17
- add r1=32*8,r1
- add r2=32*8,r2
- add r3=32*8,r3
- add r4=32*8,r4
- add r5=32*8,r5
- add r6=32*8,r6
- add r7=32*8,r7
- ;;
- fc r17
- fc r1
- fc r2
- fc r3
- fc r4
- fc r5
- fc r6
- fc r7
- add r17=32*8,r17
- add r1=32*8,r1
- add r2=32*8,r2
- add r3=32*8,r3
- add r4=32*8,r4
- add r5=32*8,r5
- add r6=32*8,r6
- add r7=32*8,r7
- ;;
- fc r17
- fc r1
- fc r2
- fc r3
- fc r4
- fc r5
- fc r6
- fc r7
- add r17=32*8,r17
- add r1=32*8,r1
- add r2=32*8,r2
- add r3=32*8,r3
- add r4=32*8,r4
- add r5=32*8,r5
- add r6=32*8,r6
- add r7=32*8,r7
- ;;
- fc r17
- fc r1
- fc r2
- fc r3
- fc r4
- fc r5
- fc r6
- fc r7
-
- br.sptk b0
-
-//EndStub//////////////////////////////////////////////////////////////////////
-
-
-//++
-// Name:
-// ia64_state_restore()
-//
-// Stub Description:
-//
-// Restore the SAL/OS state. This is sensitive to the layout of struct
-// ia64_sal_os_state in mca.h.
-//
-// r2 contains the return address, r3 contains either
-// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
-//
-// In addition to the SAL to OS state, this routine restores all the
-// registers that appear in struct pt_regs and struct switch_stack,
-// excluding those in the PAL minstate area.
-//
-//--
-
-ia64_state_restore:
- // Restore the switch_stack data that is not in minstate nor pt_regs.
- add regs=MCA_SWITCH_STACK_OFFSET, r3
- mov b0=r2 // save return address
- ;;
- GET_IA64_MCA_DATA(temp2)
- ;;
- add regs=temp2, regs
- ;;
- add temp1=SW(F2), regs
- add temp2=SW(F3), regs
- ;;
- ldf.fill f2=[temp1],32
- ldf.fill f3=[temp2],32
- ;;
- ldf.fill f4=[temp1],32
- ldf.fill f5=[temp2],32
- ;;
- ldf.fill f12=[temp1],32
- ldf.fill f13=[temp2],32
- ;;
- ldf.fill f14=[temp1],32
- ldf.fill f15=[temp2],32
- ;;
- ldf.fill f16=[temp1],32
- ldf.fill f17=[temp2],32
- ;;
- ldf.fill f18=[temp1],32
- ldf.fill f19=[temp2],32
- ;;
- ldf.fill f20=[temp1],32
- ldf.fill f21=[temp2],32
- ;;
- ldf.fill f22=[temp1],32
- ldf.fill f23=[temp2],32
- ;;
- ldf.fill f24=[temp1],32
- ldf.fill f25=[temp2],32
- ;;
- ldf.fill f26=[temp1],32
- ldf.fill f27=[temp2],32
- ;;
- ldf.fill f28=[temp1],32
- ldf.fill f29=[temp2],32
- ;;
- ldf.fill f30=[temp1],SW(B2)-SW(F30)
- ldf.fill f31=[temp2],SW(B3)-SW(F31)
- ;;
- ld8 temp3=[temp1],16 // restore b2
- ld8 temp4=[temp2],16 // restore b3
- ;;
- mov b2=temp3
- mov b3=temp4
- ld8 temp3=[temp1],SW(AR_LC)-SW(B4) // restore b4
- ld8 temp4=[temp2] // restore b5
- ;;
- mov b4=temp3
- mov b5=temp4
- ld8 temp3=[temp1] // restore ar.lc
- ;;
- mov ar.lc=temp3
-
- // Restore the pt_regs data that is not in minstate. The previous code
- // left regs at switch_stack.
- add regs=MCA_PT_REGS_OFFSET-MCA_SWITCH_STACK_OFFSET, regs
- ;;
- add temp1=PT(B6), regs
- add temp2=PT(B7), regs
- ;;
- ld8 temp3=[temp1],PT(AR_CSD)-PT(B6) // restore b6
- ld8 temp4=[temp2],PT(AR_SSD)-PT(B7) // restore b7
- ;;
- mov b6=temp3
- mov b7=temp4
- ld8 temp3=[temp1],PT(AR_UNAT)-PT(AR_CSD) // restore ar.csd
- ld8 temp4=[temp2],PT(AR_PFS)-PT(AR_SSD) // restore ar.ssd
- ;;
- mov ar.csd=temp3
- mov ar.ssd=temp4
- ld8 temp3=[temp1] // restore ar.unat
- add temp1=PT(AR_CCV)-PT(AR_UNAT), temp1
- ld8 temp4=[temp2],PT(AR_FPSR)-PT(AR_PFS) // restore ar.pfs
- ;;
- mov ar.unat=temp3
- mov ar.pfs=temp4
- // ar.rnat, ar.bspstore, loadrs are restore in ia64_old_stack.
- ld8 temp3=[temp1],PT(F6)-PT(AR_CCV) // restore ar.ccv
- ld8 temp4=[temp2],PT(F7)-PT(AR_FPSR) // restore ar.fpsr
- ;;
- mov ar.ccv=temp3
- mov ar.fpsr=temp4
- ldf.fill f6=[temp1],PT(F8)-PT(F6)
- ldf.fill f7=[temp2],PT(F9)-PT(F7)
- ;;
- ldf.fill f8=[temp1],PT(F10)-PT(F8)
- ldf.fill f9=[temp2],PT(F11)-PT(F9)
- ;;
- ldf.fill f10=[temp1]
- ldf.fill f11=[temp2]
-
- // Restore the SAL to OS state. The previous code left regs at pt_regs.
- add regs=MCA_SOS_OFFSET-MCA_PT_REGS_OFFSET, regs
- ;;
- add temp1=SOS(SAL_RA), regs
- add temp2=SOS(SAL_GP), regs
- ;;
- ld8 r12=[temp1],16 // sal_ra
- ld8 r9=[temp2],16 // sal_gp
- ;;
- ld8 r22=[temp1],16 // pal_min_state, virtual
- ld8 r13=[temp2],16 // prev_IA64_KR_CURRENT
- ;;
- ld8 r16=[temp1],16 // prev_IA64_KR_CURRENT_STACK
- ld8 r20=[temp2],16 // prev_task
- ;;
- ld8 temp3=[temp1],16 // cr.isr
- ld8 temp4=[temp2],16 // cr.ifa
- ;;
- mov cr.isr=temp3
- mov cr.ifa=temp4
- ld8 temp3=[temp1],16 // cr.itir
- ld8 temp4=[temp2],16 // cr.iipa
- ;;
- mov cr.itir=temp3
- mov cr.iipa=temp4
- ld8 temp3=[temp1] // cr.iim
- ld8 temp4=[temp2] // cr.iha
- add temp1=SOS(OS_STATUS), regs
- add temp2=SOS(CONTEXT), regs
- ;;
- mov cr.iim=temp3
- mov cr.iha=temp4
- dep r22=0,r22,62,1 // pal_min_state, physical, uncached
- mov IA64_KR(CURRENT)=r13
- ld8 r8=[temp1] // os_status
- ld8 r10=[temp2] // context
-
- /* Wire IA64_TR_CURRENT_STACK to the stack that we are resuming to. To
- * avoid any dependencies on the algorithm in ia64_switch_to(), just
- * purge any existing CURRENT_STACK mapping and insert the new one.
- *
- * r16 contains prev_IA64_KR_CURRENT_STACK, r13 contains
- * prev_IA64_KR_CURRENT, these values may have been changed by the C
- * code. Do not use r8, r9, r10, r22, they contain values ready for
- * the return to SAL.
- */
-
- mov r15=IA64_KR(CURRENT_STACK) // physical granule mapped by IA64_TR_CURRENT_STACK
- ;;
- shl r15=r15,IA64_GRANULE_SHIFT
- ;;
- dep r15=-1,r15,61,3 // virtual granule
- mov r18=IA64_GRANULE_SHIFT<<2 // for cr.itir.ps
- ;;
- ptr.d r15,r18
- ;;
- srlz.d
-
- extr.u r19=r13,61,3 // r13 = prev_IA64_KR_CURRENT
- shl r20=r16,IA64_GRANULE_SHIFT // r16 = prev_IA64_KR_CURRENT_STACK
- movl r21=PAGE_KERNEL // page properties
- ;;
- mov IA64_KR(CURRENT_STACK)=r16
- cmp.ne p6,p0=RGN_KERNEL,r19 // new stack is in the kernel region?
- or r21=r20,r21 // construct PA | page properties
-(p6) br.spnt 1f // the dreaded cpu 0 idle task in region 5:(
- ;;
- mov cr.itir=r18
- mov cr.ifa=r13
- mov r20=IA64_TR_CURRENT_STACK
- ;;
- itr.d dtr[r20]=r21
- ;;
- srlz.d
-1:
-
- br.sptk b0
-
-//EndStub//////////////////////////////////////////////////////////////////////
-
-
-//++
-// Name:
-// ia64_new_stack()
-//
-// Stub Description:
-//
-// Switch to the MCA/INIT stack.
-//
-// r2 contains the return address, r3 contains either
-// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
-//
-// On entry RBS is still on the original stack, this routine switches RBS
-// to use the MCA/INIT stack.
-//
-// On entry, sos->pal_min_state is physical, on exit it is virtual.
-//
-//--
-
-ia64_new_stack:
- add regs=MCA_PT_REGS_OFFSET, r3
- add temp2=MCA_SOS_OFFSET+SOS(PAL_MIN_STATE), r3
- mov b0=r2 // save return address
- GET_IA64_MCA_DATA(temp1)
- invala
- ;;
- add temp2=temp2, temp1 // struct ia64_sal_os_state.pal_min_state on MCA or INIT stack
- add regs=regs, temp1 // struct pt_regs on MCA or INIT stack
- ;;
- // Address of minstate area provided by PAL is physical, uncacheable.
- // Convert to Linux virtual address in region 6 for C code.
- ld8 ms=[temp2] // pal_min_state, physical
- ;;
- dep temp1=-1,ms,62,2 // set region 6
- mov temp3=IA64_RBS_OFFSET-MCA_PT_REGS_OFFSET
- ;;
- st8 [temp2]=temp1 // pal_min_state, virtual
-
- add temp4=temp3, regs // start of bspstore on new stack
- ;;
- mov ar.bspstore=temp4 // switch RBS to MCA/INIT stack
- ;;
- flushrs // must be first in group
- br.sptk b0
-
-//EndStub//////////////////////////////////////////////////////////////////////
-
-
-//++
-// Name:
-// ia64_old_stack()
-//
-// Stub Description:
-//
-// Switch to the old stack.
-//
-// r2 contains the return address, r3 contains either
-// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
-//
-// On entry, pal_min_state is virtual, on exit it is physical.
-//
-// On entry RBS is on the MCA/INIT stack, this routine switches RBS
-// back to the previous stack.
-//
-// The psr is set to all zeroes. SAL return requires either all zeroes or
-// just psr.mc set. Leaving psr.mc off allows INIT to be issued if this
-// code does not perform correctly.
-//
-// The dirty registers at the time of the event were flushed to the
-// MCA/INIT stack in ia64_pt_regs_save(). Restore the dirty registers
-// before reverting to the previous bspstore.
-//--
-
-ia64_old_stack:
- add regs=MCA_PT_REGS_OFFSET, r3
- mov b0=r2 // save return address
- GET_IA64_MCA_DATA(temp2)
- LOAD_PHYSICAL(p0,temp1,1f)
- ;;
- mov cr.ipsr=r0
- mov cr.ifs=r0
- mov cr.iip=temp1
- ;;
- invala
- rfi
-1:
-
- add regs=regs, temp2 // struct pt_regs on MCA or INIT stack
- ;;
- add temp1=PT(LOADRS), regs
- ;;
- ld8 temp2=[temp1],PT(AR_BSPSTORE)-PT(LOADRS) // restore loadrs
- ;;
- ld8 temp3=[temp1],PT(AR_RNAT)-PT(AR_BSPSTORE) // restore ar.bspstore
- mov ar.rsc=temp2
- ;;
- loadrs
- ld8 temp4=[temp1] // restore ar.rnat
- ;;
- mov ar.bspstore=temp3 // back to old stack
- ;;
- mov ar.rnat=temp4
- ;;
-
- br.sptk b0
-
-//EndStub//////////////////////////////////////////////////////////////////////
-
-
-//++
-// Name:
-// ia64_set_kernel_registers()
-//
-// Stub Description:
-//
-// Set the registers that are required by the C code in order to run on an
-// MCA/INIT stack.
-//
-// r2 contains the return address, r3 contains either
-// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
-//
-//--
-
-ia64_set_kernel_registers:
- add temp3=MCA_SP_OFFSET, r3
- mov b0=r2 // save return address
- GET_IA64_MCA_DATA(temp1)
- ;;
- add r12=temp1, temp3 // kernel stack pointer on MCA/INIT stack
- add r13=temp1, r3 // set current to start of MCA/INIT stack
- add r20=temp1, r3 // physical start of MCA/INIT stack
- ;;
- DATA_PA_TO_VA(r12,temp2)
- DATA_PA_TO_VA(r13,temp3)
- ;;
- mov IA64_KR(CURRENT)=r13
-
- /* Wire IA64_TR_CURRENT_STACK to the MCA/INIT handler stack. To avoid
- * any dependencies on the algorithm in ia64_switch_to(), just purge
- * any existing CURRENT_STACK mapping and insert the new one.
- */
-
- mov r16=IA64_KR(CURRENT_STACK) // physical granule mapped by IA64_TR_CURRENT_STACK
- ;;
- shl r16=r16,IA64_GRANULE_SHIFT
- ;;
- dep r16=-1,r16,61,3 // virtual granule
- mov r18=IA64_GRANULE_SHIFT<<2 // for cr.itir.ps
- ;;
- ptr.d r16,r18
- ;;
- srlz.d
-
- shr.u r16=r20,IA64_GRANULE_SHIFT // r20 = physical start of MCA/INIT stack
- movl r21=PAGE_KERNEL // page properties
- ;;
- mov IA64_KR(CURRENT_STACK)=r16
- or r21=r20,r21 // construct PA | page properties
- ;;
- mov cr.itir=r18
- mov cr.ifa=r13
- mov r20=IA64_TR_CURRENT_STACK
-
- movl r17=FPSR_DEFAULT
- ;;
- mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value
- ;;
- itr.d dtr[r20]=r21
- ;;
- srlz.d
-
- br.sptk b0
-
-//EndStub//////////////////////////////////////////////////////////////////////
-
-#undef ms
-#undef regs
-#undef temp1
-#undef temp2
-#undef temp3
-#undef temp4
-
-
-// Support function for mca.c, it is here to avoid using inline asm. Given the
-// address of an rnat slot, if that address is below the current ar.bspstore
-// then return the contents of that slot, otherwise return the contents of
-// ar.rnat.
-GLOBAL_ENTRY(ia64_get_rnat)
- alloc r14=ar.pfs,1,0,0,0
- mov ar.rsc=0
- ;;
- mov r14=ar.bspstore
- ;;
- cmp.lt p6,p7=in0,r14
- ;;
-(p6) ld8 r8=[in0]
-(p7) mov r8=ar.rnat
- mov ar.rsc=3
- br.ret.sptk.many rp
-END(ia64_get_rnat)
-
-
-// void ia64_set_psr_mc(void)
-//
-// Set psr.mc bit to mask MCA/INIT.
-GLOBAL_ENTRY(ia64_set_psr_mc)
- rsm psr.i | psr.ic // disable interrupts
- ;;
- srlz.d
- ;;
- mov r14 = psr // get psr{36:35,31:0}
- movl r15 = 1f
- ;;
- dep r14 = -1, r14, PSR_MC, 1 // set psr.mc
- ;;
- dep r14 = -1, r14, PSR_IC, 1 // set psr.ic
- ;;
- dep r14 = -1, r14, PSR_BN, 1 // keep bank1 in use
- ;;
- mov cr.ipsr = r14
- mov cr.ifs = r0
- mov cr.iip = r15
- ;;
- rfi
-1:
- br.ret.sptk.many rp
-END(ia64_set_psr_mc)
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
deleted file mode 100644
index 23c203639a96..000000000000
--- a/arch/ia64/kernel/mca_drv.c
+++ /dev/null
@@ -1,796 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * File: mca_drv.c
- * Purpose: Generic MCA handling layer
- *
- * Copyright (C) 2004 FUJITSU LIMITED
- * Copyright (C) 2004 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
- * Copyright (C) 2005 Silicon Graphics, Inc
- * Copyright (C) 2005 Keith Owens <kaos@sgi.com>
- * Copyright (C) 2006 Russ Anderson <rja@sgi.com>
- */
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kallsyms.h>
-#include <linux/memblock.h>
-#include <linux/acpi.h>
-#include <linux/timer.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/smp.h>
-#include <linux/workqueue.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-#include <asm/delay.h>
-#include <asm/page.h>
-#include <asm/ptrace.h>
-#include <asm/sal.h>
-#include <asm/mca.h>
-
-#include <asm/irq.h>
-#include <asm/hw_irq.h>
-
-#include "mca_drv.h"
-
-/* max size of SAL error record (default) */
-static int sal_rec_max = 10000;
-
-/* from mca_drv_asm.S */
-extern void *mca_handler_bhhook(void);
-
-static DEFINE_SPINLOCK(mca_bh_lock);
-
-typedef enum {
- MCA_IS_LOCAL = 0,
- MCA_IS_GLOBAL = 1
-} mca_type_t;
-
-#define MAX_PAGE_ISOLATE 1024
-
-static struct page *page_isolate[MAX_PAGE_ISOLATE];
-static int num_page_isolate = 0;
-
-typedef enum {
- ISOLATE_NG,
- ISOLATE_OK,
- ISOLATE_NONE
-} isolate_status_t;
-
-typedef enum {
- MCA_NOT_RECOVERED = 0,
- MCA_RECOVERED = 1
-} recovery_status_t;
-
-/*
- * This pool keeps pointers to the section part of SAL error record
- */
-static struct {
- slidx_list_t *buffer; /* section pointer list pool */
- int cur_idx; /* Current index of section pointer list pool */
- int max_idx; /* Maximum index of section pointer list pool */
-} slidx_pool;
-
-static int
-fatal_mca(const char *fmt, ...)
-{
- va_list args;
- char buf[256];
-
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- ia64_mca_printk(KERN_ALERT "MCA: %s\n", buf);
-
- return MCA_NOT_RECOVERED;
-}
-
-static int
-mca_recovered(const char *fmt, ...)
-{
- va_list args;
- char buf[256];
-
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- ia64_mca_printk(KERN_INFO "MCA: %s\n", buf);
-
- return MCA_RECOVERED;
-}
-
-/**
- * mca_page_isolate - isolate a poisoned page in order not to use it later
- * @paddr: poisoned memory location
- *
- * Return value:
- * one of isolate_status_t, ISOLATE_OK/NG/NONE.
- */
-
-static isolate_status_t
-mca_page_isolate(unsigned long paddr)
-{
- int i;
- struct page *p;
-
- /* whether physical address is valid or not */
- if (!ia64_phys_addr_valid(paddr))
- return ISOLATE_NONE;
-
- if (!pfn_valid(paddr >> PAGE_SHIFT))
- return ISOLATE_NONE;
-
- /* convert physical address to physical page number */
- p = pfn_to_page(paddr>>PAGE_SHIFT);
-
- /* check whether a page number have been already registered or not */
- for (i = 0; i < num_page_isolate; i++)
- if (page_isolate[i] == p)
- return ISOLATE_OK; /* already listed */
-
- /* limitation check */
- if (num_page_isolate == MAX_PAGE_ISOLATE)
- return ISOLATE_NG;
-
- /* kick pages having attribute 'SLAB' or 'Reserved' */
- if (PageSlab(p) || PageReserved(p))
- return ISOLATE_NG;
-
- /* add attribute 'Reserved' and register the page */
- get_page(p);
- SetPageReserved(p);
- page_isolate[num_page_isolate++] = p;
-
- return ISOLATE_OK;
-}
-
-/**
- * mca_hanlder_bh - Kill the process which occurred memory read error
- * @paddr: poisoned address received from MCA Handler
- */
-
-void
-mca_handler_bh(unsigned long paddr, void *iip, unsigned long ipsr)
-{
- ia64_mlogbuf_dump();
- printk(KERN_ERR "OS_MCA: process [cpu %d, pid: %d, uid: %d, "
- "iip: %p, psr: 0x%lx,paddr: 0x%lx](%s) encounters MCA.\n",
- raw_smp_processor_id(), current->pid,
- from_kuid(&init_user_ns, current_uid()),
- iip, ipsr, paddr, current->comm);
-
- spin_lock(&mca_bh_lock);
- switch (mca_page_isolate(paddr)) {
- case ISOLATE_OK:
- printk(KERN_DEBUG "Page isolation: ( %lx ) success.\n", paddr);
- break;
- case ISOLATE_NG:
- printk(KERN_CRIT "Page isolation: ( %lx ) failure.\n", paddr);
- break;
- default:
- break;
- }
- spin_unlock(&mca_bh_lock);
-
- /* This process is about to be killed itself */
- make_task_dead(SIGKILL);
-}
-
-/**
- * mca_make_peidx - Make index of processor error section
- * @slpi: pointer to record of processor error section
- * @peidx: pointer to index of processor error section
- */
-
-static void
-mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
-{
- /*
- * calculate the start address of
- * "struct cpuid_info" and "sal_processor_static_info_t".
- */
- u64 total_check_num = slpi->valid.num_cache_check
- + slpi->valid.num_tlb_check
- + slpi->valid.num_bus_check
- + slpi->valid.num_reg_file_check
- + slpi->valid.num_ms_check;
- u64 head_size = sizeof(sal_log_mod_error_info_t) * total_check_num
- + sizeof(sal_log_processor_info_t);
- u64 mid_size = slpi->valid.cpuid_info * sizeof(struct sal_cpuid_info);
-
- peidx_head(peidx) = slpi;
- peidx_mid(peidx) = (struct sal_cpuid_info *)
- (slpi->valid.cpuid_info ? ((char*)slpi + head_size) : NULL);
- peidx_bottom(peidx) = (sal_processor_static_info_t *)
- (slpi->valid.psi_static_struct ?
- ((char*)slpi + head_size + mid_size) : NULL);
-}
-
-/**
- * mca_make_slidx - Make index of SAL error record
- * @buffer: pointer to SAL error record
- * @slidx: pointer to index of SAL error record
- *
- * Return value:
- * 1 if record has platform error / 0 if not
- */
-#define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \
- {slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \
- hl->hdr = ptr; \
- list_add(&hl->list, &(sect)); \
- slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; }
-
-static int
-mca_make_slidx(void *buffer, slidx_table_t *slidx)
-{
- int platform_err = 0;
- int record_len = ((sal_log_record_header_t*)buffer)->len;
- u32 ercd_pos;
- int sects;
- sal_log_section_hdr_t *sp;
-
- /*
- * Initialize index referring current record
- */
- INIT_LIST_HEAD(&(slidx->proc_err));
- INIT_LIST_HEAD(&(slidx->mem_dev_err));
- INIT_LIST_HEAD(&(slidx->sel_dev_err));
- INIT_LIST_HEAD(&(slidx->pci_bus_err));
- INIT_LIST_HEAD(&(slidx->smbios_dev_err));
- INIT_LIST_HEAD(&(slidx->pci_comp_err));
- INIT_LIST_HEAD(&(slidx->plat_specific_err));
- INIT_LIST_HEAD(&(slidx->host_ctlr_err));
- INIT_LIST_HEAD(&(slidx->plat_bus_err));
- INIT_LIST_HEAD(&(slidx->unsupported));
-
- /*
- * Extract a Record Header
- */
- slidx->header = buffer;
-
- /*
- * Extract each section records
- * (arranged from "int ia64_log_platform_info_print()")
- */
- for (ercd_pos = sizeof(sal_log_record_header_t), sects = 0;
- ercd_pos < record_len; ercd_pos += sp->len, sects++) {
- sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos);
- if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) {
- LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp);
- } else if (!efi_guidcmp(sp->guid,
- SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) {
- platform_err = 1;
- LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp);
- } else if (!efi_guidcmp(sp->guid,
- SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) {
- platform_err = 1;
- LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp);
- } else if (!efi_guidcmp(sp->guid,
- SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) {
- platform_err = 1;
- LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp);
- } else if (!efi_guidcmp(sp->guid,
- SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) {
- platform_err = 1;
- LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp);
- } else if (!efi_guidcmp(sp->guid,
- SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) {
- platform_err = 1;
- LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp);
- } else if (!efi_guidcmp(sp->guid,
- SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) {
- platform_err = 1;
- LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp);
- } else if (!efi_guidcmp(sp->guid,
- SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) {
- platform_err = 1;
- LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp);
- } else if (!efi_guidcmp(sp->guid,
- SAL_PLAT_BUS_ERR_SECT_GUID)) {
- platform_err = 1;
- LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp);
- } else {
- LOG_INDEX_ADD_SECT_PTR(slidx->unsupported, sp);
- }
- }
- slidx->n_sections = sects;
-
- return platform_err;
-}
-
-/**
- * init_record_index_pools - Initialize pool of lists for SAL record index
- *
- * Return value:
- * 0 on Success / -ENOMEM on Failure
- */
-static int
-init_record_index_pools(void)
-{
- int i;
- int rec_max_size; /* Maximum size of SAL error records */
- int sect_min_size; /* Minimum size of SAL error sections */
- /* minimum size table of each section */
- static int sal_log_sect_min_sizes[] = {
- sizeof(sal_log_processor_info_t)
- + sizeof(sal_processor_static_info_t),
- sizeof(sal_log_mem_dev_err_info_t),
- sizeof(sal_log_sel_dev_err_info_t),
- sizeof(sal_log_pci_bus_err_info_t),
- sizeof(sal_log_smbios_dev_err_info_t),
- sizeof(sal_log_pci_comp_err_info_t),
- sizeof(sal_log_plat_specific_err_info_t),
- sizeof(sal_log_host_ctlr_err_info_t),
- sizeof(sal_log_plat_bus_err_info_t),
- };
-
- /*
- * MCA handler cannot allocate new memory on flight,
- * so we preallocate enough memory to handle a SAL record.
- *
- * Initialize a handling set of slidx_pool:
- * 1. Pick up the max size of SAL error records
- * 2. Pick up the min size of SAL error sections
- * 3. Allocate the pool as enough to 2 SAL records
- * (now we can estimate the maxinum of section in a record.)
- */
-
- /* - 1 - */
- rec_max_size = sal_rec_max;
-
- /* - 2 - */
- sect_min_size = sal_log_sect_min_sizes[0];
- for (i = 1; i < ARRAY_SIZE(sal_log_sect_min_sizes); i++)
- if (sect_min_size > sal_log_sect_min_sizes[i])
- sect_min_size = sal_log_sect_min_sizes[i];
-
- /* - 3 - */
- slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1;
- slidx_pool.buffer =
- kmalloc_array(slidx_pool.max_idx, sizeof(slidx_list_t),
- GFP_KERNEL);
-
- return slidx_pool.buffer ? 0 : -ENOMEM;
-}
-
-
-/*****************************************************************************
- * Recovery functions *
- *****************************************************************************/
-
-/**
- * is_mca_global - Check whether this MCA is global or not
- * @peidx: pointer of index of processor error section
- * @pbci: pointer to pal_bus_check_info_t
- * @sos: pointer to hand off struct between SAL and OS
- *
- * Return value:
- * MCA_IS_LOCAL / MCA_IS_GLOBAL
- */
-
-static mca_type_t
-is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci,
- struct ia64_sal_os_state *sos)
-{
- pal_processor_state_info_t *psp =
- (pal_processor_state_info_t*)peidx_psp(peidx);
-
- /*
- * PAL can request a rendezvous, if the MCA has a global scope.
- * If "rz_always" flag is set, SAL requests MCA rendezvous
- * in spite of global MCA.
- * Therefore it is local MCA when rendezvous has not been requested.
- * Failed to rendezvous, the system must be down.
- */
- switch (sos->rv_rc) {
- case -1: /* SAL rendezvous unsuccessful */
- return MCA_IS_GLOBAL;
- case 0: /* SAL rendezvous not required */
- return MCA_IS_LOCAL;
- case 1: /* SAL rendezvous successful int */
- case 2: /* SAL rendezvous successful int with init */
- default:
- break;
- }
-
- /*
- * If One or more Cache/TLB/Reg_File/Uarch_Check is here,
- * it would be a local MCA. (i.e. processor internal error)
- */
- if (psp->tc || psp->cc || psp->rc || psp->uc)
- return MCA_IS_LOCAL;
-
- /*
- * Bus_Check structure with Bus_Check.ib (internal bus error) flag set
- * would be a global MCA. (e.g. a system bus address parity error)
- */
- if (!pbci || pbci->ib)
- return MCA_IS_GLOBAL;
-
- /*
- * Bus_Check structure with Bus_Check.eb (external bus error) flag set
- * could be either a local MCA or a global MCA.
- *
- * Referring Bus_Check.bsi:
- * 0: Unknown/unclassified
- * 1: BERR#
- * 2: BINIT#
- * 3: Hard Fail
- * (FIXME: Are these SGI specific or generic bsi values?)
- */
- if (pbci->eb)
- switch (pbci->bsi) {
- case 0:
- /* e.g. a load from poisoned memory */
- return MCA_IS_LOCAL;
- case 1:
- case 2:
- case 3:
- return MCA_IS_GLOBAL;
- }
-
- return MCA_IS_GLOBAL;
-}
-
-/**
- * get_target_identifier - Get the valid Cache or Bus check target identifier.
- * @peidx: pointer of index of processor error section
- *
- * Return value:
- * target address on Success / 0 on Failure
- */
-static u64
-get_target_identifier(peidx_table_t *peidx)
-{
- u64 target_address = 0;
- sal_log_mod_error_info_t *smei;
- pal_cache_check_info_t *pcci;
- int i, level = 9;
-
- /*
- * Look through the cache checks for a valid target identifier
- * If more than one valid target identifier, return the one
- * with the lowest cache level.
- */
- for (i = 0; i < peidx_cache_check_num(peidx); i++) {
- smei = (sal_log_mod_error_info_t *)peidx_cache_check(peidx, i);
- if (smei->valid.target_identifier && smei->target_identifier) {
- pcci = (pal_cache_check_info_t *)&(smei->check_info);
- if (!target_address || (pcci->level < level)) {
- target_address = smei->target_identifier;
- level = pcci->level;
- continue;
- }
- }
- }
- if (target_address)
- return target_address;
-
- /*
- * Look at the bus check for a valid target identifier
- */
- smei = peidx_bus_check(peidx, 0);
- if (smei && smei->valid.target_identifier)
- return smei->target_identifier;
-
- return 0;
-}
-
-/**
- * recover_from_read_error - Try to recover the errors which type are "read"s.
- * @slidx: pointer of index of SAL error record
- * @peidx: pointer of index of processor error section
- * @pbci: pointer of pal_bus_check_info
- * @sos: pointer to hand off struct between SAL and OS
- *
- * Return value:
- * 1 on Success / 0 on Failure
- */
-
-static int
-recover_from_read_error(slidx_table_t *slidx,
- peidx_table_t *peidx, pal_bus_check_info_t *pbci,
- struct ia64_sal_os_state *sos)
-{
- u64 target_identifier;
- struct pal_min_state_area *pmsa;
- struct ia64_psr *psr1, *psr2;
- ia64_fptr_t *mca_hdlr_bh = (ia64_fptr_t*)mca_handler_bhhook;
-
- /* Is target address valid? */
- target_identifier = get_target_identifier(peidx);
- if (!target_identifier)
- return fatal_mca("target address not valid");
-
- /*
- * cpu read or memory-mapped io read
- *
- * offending process affected process OS MCA do
- * kernel mode kernel mode down system
- * kernel mode user mode kill the process
- * user mode kernel mode down system (*)
- * user mode user mode kill the process
- *
- * (*) You could terminate offending user-mode process
- * if (pbci->pv && pbci->pl != 0) *and* if you sure
- * the process not have any locks of kernel.
- */
-
- /* Is minstate valid? */
- if (!peidx_bottom(peidx) || !(peidx_bottom(peidx)->valid.minstate))
- return fatal_mca("minstate not valid");
- psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr);
- psr2 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_xpsr);
-
- /*
- * Check the privilege level of interrupted context.
- * If it is user-mode, then terminate affected process.
- */
-
- pmsa = sos->pal_min_state;
- if (psr1->cpl != 0 ||
- ((psr2->cpl != 0) && mca_recover_range(pmsa->pmsa_iip))) {
- /*
- * setup for resume to bottom half of MCA,
- * "mca_handler_bhhook"
- */
- /* pass to bhhook as argument (gr8, ...) */
- pmsa->pmsa_gr[8-1] = target_identifier;
- pmsa->pmsa_gr[9-1] = pmsa->pmsa_iip;
- pmsa->pmsa_gr[10-1] = pmsa->pmsa_ipsr;
- /* set interrupted return address (but no use) */
- pmsa->pmsa_br0 = pmsa->pmsa_iip;
- /* change resume address to bottom half */
- pmsa->pmsa_iip = mca_hdlr_bh->fp;
- pmsa->pmsa_gr[1-1] = mca_hdlr_bh->gp;
- /* set cpl with kernel mode */
- psr2 = (struct ia64_psr *)&pmsa->pmsa_ipsr;
- psr2->cpl = 0;
- psr2->ri = 0;
- psr2->bn = 1;
- psr2->i = 0;
-
- return mca_recovered("user memory corruption. "
- "kill affected process - recovered.");
- }
-
- return fatal_mca("kernel context not recovered, iip 0x%lx\n",
- pmsa->pmsa_iip);
-}
-
-/**
- * recover_from_platform_error - Recover from platform error.
- * @slidx: pointer of index of SAL error record
- * @peidx: pointer of index of processor error section
- * @pbci: pointer of pal_bus_check_info
- * @sos: pointer to hand off struct between SAL and OS
- *
- * Return value:
- * 1 on Success / 0 on Failure
- */
-
-static int
-recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx,
- pal_bus_check_info_t *pbci,
- struct ia64_sal_os_state *sos)
-{
- int status = 0;
- pal_processor_state_info_t *psp =
- (pal_processor_state_info_t*)peidx_psp(peidx);
-
- if (psp->bc && pbci->eb && pbci->bsi == 0) {
- switch(pbci->type) {
- case 1: /* partial read */
- case 3: /* full line(cpu) read */
- case 9: /* I/O space read */
- status = recover_from_read_error(slidx, peidx, pbci,
- sos);
- break;
- case 0: /* unknown */
- case 2: /* partial write */
- case 4: /* full line write */
- case 5: /* implicit or explicit write-back operation */
- case 6: /* snoop probe */
- case 7: /* incoming or outgoing ptc.g */
- case 8: /* write coalescing transactions */
- case 10: /* I/O space write */
- case 11: /* inter-processor interrupt message(IPI) */
- case 12: /* interrupt acknowledge or
- external task priority cycle */
- default:
- break;
- }
- } else if (psp->cc && !psp->bc) { /* Cache error */
- status = recover_from_read_error(slidx, peidx, pbci, sos);
- }
-
- return status;
-}
-
-/*
- * recover_from_tlb_check
- * @peidx: pointer of index of processor error section
- *
- * Return value:
- * 1 on Success / 0 on Failure
- */
-static int
-recover_from_tlb_check(peidx_table_t *peidx)
-{
- sal_log_mod_error_info_t *smei;
- pal_tlb_check_info_t *ptci;
-
- smei = (sal_log_mod_error_info_t *)peidx_tlb_check(peidx, 0);
- ptci = (pal_tlb_check_info_t *)&(smei->check_info);
-
- /*
- * Look for signature of a duplicate TLB DTC entry, which is
- * a SW bug and always fatal.
- */
- if (ptci->op == PAL_TLB_CHECK_OP_PURGE
- && !(ptci->itr || ptci->dtc || ptci->itc))
- return fatal_mca("Duplicate TLB entry");
-
- return mca_recovered("TLB check recovered");
-}
-
-/**
- * recover_from_processor_error
- * @platform: whether there are some platform error section or not
- * @slidx: pointer of index of SAL error record
- * @peidx: pointer of index of processor error section
- * @pbci: pointer of pal_bus_check_info
- * @sos: pointer to hand off struct between SAL and OS
- *
- * Return value:
- * 1 on Success / 0 on Failure
- */
-
-static int
-recover_from_processor_error(int platform, slidx_table_t *slidx,
- peidx_table_t *peidx, pal_bus_check_info_t *pbci,
- struct ia64_sal_os_state *sos)
-{
- pal_processor_state_info_t *psp =
- (pal_processor_state_info_t*)peidx_psp(peidx);
-
- /*
- * Processor recovery status must key off of the PAL recovery
- * status in the Processor State Parameter.
- */
-
- /*
- * The machine check is corrected.
- */
- if (psp->cm == 1)
- return mca_recovered("machine check is already corrected.");
-
- /*
- * The error was not contained. Software must be reset.
- */
- if (psp->us || psp->ci == 0)
- return fatal_mca("error not contained");
-
- /*
- * Look for recoverable TLB check
- */
- if (psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc))
- return recover_from_tlb_check(peidx);
-
- /*
- * The cache check and bus check bits have four possible states
- * cc bc
- * 1 1 Memory error, attempt recovery
- * 1 0 Cache error, attempt recovery
- * 0 1 I/O error, attempt recovery
- * 0 0 Other error type, not recovered
- */
- if (psp->cc == 0 && (psp->bc == 0 || pbci == NULL))
- return fatal_mca("No cache or bus check");
-
- /*
- * Cannot handle more than one bus check.
- */
- if (peidx_bus_check_num(peidx) > 1)
- return fatal_mca("Too many bus checks");
-
- if (pbci->ib)
- return fatal_mca("Internal Bus error");
- if (pbci->eb && pbci->bsi > 0)
- return fatal_mca("External bus check fatal status");
-
- /*
- * This is a local MCA and estimated as a recoverable error.
- */
- if (platform)
- return recover_from_platform_error(slidx, peidx, pbci, sos);
-
- /*
- * On account of strange SAL error record, we cannot recover.
- */
- return fatal_mca("Strange SAL record");
-}
-
-/**
- * mca_try_to_recover - Try to recover from MCA
- * @rec: pointer to a SAL error record
- * @sos: pointer to hand off struct between SAL and OS
- *
- * Return value:
- * 1 on Success / 0 on Failure
- */
-
-static int
-mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
-{
- int platform_err;
- int n_proc_err;
- slidx_table_t slidx;
- peidx_table_t peidx;
- pal_bus_check_info_t pbci;
-
- /* Make index of SAL error record */
- platform_err = mca_make_slidx(rec, &slidx);
-
- /* Count processor error sections */
- n_proc_err = slidx_count(&slidx, proc_err);
-
- /* Now, OS can recover when there is one processor error section */
- if (n_proc_err > 1)
- return fatal_mca("Too Many Errors");
- else if (n_proc_err == 0)
- /* Weird SAL record ... We can't do anything */
- return fatal_mca("Weird SAL record");
-
- /* Make index of processor error section */
- mca_make_peidx((sal_log_processor_info_t*)
- slidx_first_entry(&slidx.proc_err)->hdr, &peidx);
-
- /* Extract Processor BUS_CHECK[0] */
- *((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0);
-
- /* Check whether MCA is global or not */
- if (is_mca_global(&peidx, &pbci, sos))
- return fatal_mca("global MCA");
-
- /* Try to recover a processor error */
- return recover_from_processor_error(platform_err, &slidx, &peidx,
- &pbci, sos);
-}
-
-/*
- * =============================================================================
- */
-
-int __init mca_external_handler_init(void)
-{
- if (init_record_index_pools())
- return -ENOMEM;
-
- /* register external mca handlers */
- if (ia64_reg_MCA_extension(mca_try_to_recover)) {
- printk(KERN_ERR "ia64_reg_MCA_extension failed.\n");
- kfree(slidx_pool.buffer);
- return -EFAULT;
- }
- return 0;
-}
-
-void __exit mca_external_handler_exit(void)
-{
- /* unregister external mca handlers */
- ia64_unreg_MCA_extension();
- kfree(slidx_pool.buffer);
-}
-
-module_init(mca_external_handler_init);
-module_exit(mca_external_handler_exit);
-
-module_param(sal_rec_max, int, 0644);
-MODULE_PARM_DESC(sal_rec_max, "Max size of SAL error record");
-
-MODULE_DESCRIPTION("ia64 platform dependent mca handler driver");
-MODULE_LICENSE("GPL");
diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h
deleted file mode 100644
index 45bc4e3ae14f..000000000000
--- a/arch/ia64/kernel/mca_drv.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * File: mca_drv.h
- * Purpose: Define helpers for Generic MCA handling
- *
- * Copyright (C) 2004 FUJITSU LIMITED
- * Copyright (C) 2004 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
- */
-/*
- * Processor error section:
- *
- * +-sal_log_processor_info_t *info-------------+
- * | sal_log_section_hdr_t header; |
- * | ... |
- * | sal_log_mod_error_info_t info[0]; |
- * +-+----------------+-------------------------+
- * | CACHE_CHECK | ^ num_cache_check v
- * +----------------+
- * | TLB_CHECK | ^ num_tlb_check v
- * +----------------+
- * | BUS_CHECK | ^ num_bus_check v
- * +----------------+
- * | REG_FILE_CHECK | ^ num_reg_file_check v
- * +----------------+
- * | MS_CHECK | ^ num_ms_check v
- * +-struct cpuid_info *id----------------------+
- * | regs[5]; |
- * | reserved; |
- * +-sal_processor_static_info_t *regs----------+
- * | valid; |
- * | ... |
- * | fr[128]; |
- * +--------------------------------------------+
- */
-
-/* peidx: index of processor error section */
-typedef struct peidx_table {
- sal_log_processor_info_t *info;
- struct sal_cpuid_info *id;
- sal_processor_static_info_t *regs;
-} peidx_table_t;
-
-#define peidx_head(p) (((p)->info))
-#define peidx_mid(p) (((p)->id))
-#define peidx_bottom(p) (((p)->regs))
-
-#define peidx_psp(p) (&(peidx_head(p)->proc_state_parameter))
-#define peidx_field_valid(p) (&(peidx_head(p)->valid))
-#define peidx_minstate_area(p) (&(peidx_bottom(p)->min_state_area))
-
-#define peidx_cache_check_num(p) (peidx_head(p)->valid.num_cache_check)
-#define peidx_tlb_check_num(p) (peidx_head(p)->valid.num_tlb_check)
-#define peidx_bus_check_num(p) (peidx_head(p)->valid.num_bus_check)
-#define peidx_reg_file_check_num(p) (peidx_head(p)->valid.num_reg_file_check)
-#define peidx_ms_check_num(p) (peidx_head(p)->valid.num_ms_check)
-
-#define peidx_cache_check_idx(p, n) (n)
-#define peidx_tlb_check_idx(p, n) (peidx_cache_check_idx(p, peidx_cache_check_num(p)) + n)
-#define peidx_bus_check_idx(p, n) (peidx_tlb_check_idx(p, peidx_tlb_check_num(p)) + n)
-#define peidx_reg_file_check_idx(p, n) (peidx_bus_check_idx(p, peidx_bus_check_num(p)) + n)
-#define peidx_ms_check_idx(p, n) (peidx_reg_file_check_idx(p, peidx_reg_file_check_num(p)) + n)
-
-#define peidx_mod_error_info(p, name, n) \
-({ int __idx = peidx_##name##_idx(p, n); \
- sal_log_mod_error_info_t *__ret = NULL; \
- if (peidx_##name##_num(p) > n) /*BUG*/ \
- __ret = &(peidx_head(p)->info[__idx]); \
- __ret; })
-
-#define peidx_cache_check(p, n) peidx_mod_error_info(p, cache_check, n)
-#define peidx_tlb_check(p, n) peidx_mod_error_info(p, tlb_check, n)
-#define peidx_bus_check(p, n) peidx_mod_error_info(p, bus_check, n)
-#define peidx_reg_file_check(p, n) peidx_mod_error_info(p, reg_file_check, n)
-#define peidx_ms_check(p, n) peidx_mod_error_info(p, ms_check, n)
-
-#define peidx_check_info(proc, name, n) \
-({ \
- sal_log_mod_error_info_t *__info = peidx_mod_error_info(proc, name, n);\
- u64 __temp = __info && __info->valid.check_info \
- ? __info->check_info : 0; \
- __temp; })
-
-/* slidx: index of SAL log error record */
-
-typedef struct slidx_list {
- struct list_head list;
- sal_log_section_hdr_t *hdr;
-} slidx_list_t;
-
-typedef struct slidx_table {
- sal_log_record_header_t *header;
- int n_sections; /* # of section headers */
- struct list_head proc_err;
- struct list_head mem_dev_err;
- struct list_head sel_dev_err;
- struct list_head pci_bus_err;
- struct list_head smbios_dev_err;
- struct list_head pci_comp_err;
- struct list_head plat_specific_err;
- struct list_head host_ctlr_err;
- struct list_head plat_bus_err;
- struct list_head unsupported; /* list of unsupported sections */
-} slidx_table_t;
-
-#define slidx_foreach_entry(pos, head) \
- list_for_each_entry(pos, head, list)
-#define slidx_first_entry(head) \
- (((head)->next != (head)) ? list_entry((head)->next, typeof(slidx_list_t), list) : NULL)
-#define slidx_count(slidx, sec) \
-({ int __count = 0; \
- slidx_list_t *__pos; \
- slidx_foreach_entry(__pos, &((slidx)->sec)) { __count++; }\
- __count; })
-
-struct mca_table_entry {
- int start_addr; /* location-relative starting address of MCA recoverable range */
- int end_addr; /* location-relative ending address of MCA recoverable range */
-};
-
-extern const struct mca_table_entry *search_mca_tables (unsigned long addr);
-extern int mca_recover_range(unsigned long);
-extern void ia64_mlogbuf_dump(void);
-
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
deleted file mode 100644
index 4428f57bee73..000000000000
--- a/arch/ia64/kernel/mca_drv_asm.S
+++ /dev/null
@@ -1,56 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * File: mca_drv_asm.S
- * Purpose: Assembly portion of Generic MCA handling
- *
- * Copyright (C) 2004 FUJITSU LIMITED
- * Copyright (C) 2004 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
- */
-#include <linux/threads.h>
-
-#include <asm/asmmacro.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-
-GLOBAL_ENTRY(mca_handler_bhhook)
- invala // clear RSE ?
- cover
- ;;
- clrrrb
- ;;
- alloc r16=ar.pfs,0,2,3,0 // make a new frame
- mov ar.rsc=0
- mov r13=IA64_KR(CURRENT) // current task pointer
- ;;
- mov r2=r13
- ;;
- addl r22=IA64_RBS_OFFSET,r2
- ;;
- mov ar.bspstore=r22
- addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2
- ;;
- adds r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
- ;;
- st1 [r2]=r0 // clear current->thread.on_ustack flag
- mov loc0=r16
- movl loc1=mca_handler_bh // recovery C function
- ;;
- mov out0=r8 // poisoned address
- mov out1=r9 // iip
- mov out2=r10 // psr
- mov b6=loc1
- ;;
- mov loc1=rp
- ssm psr.ic
- ;;
- srlz.i
- ;;
- ssm psr.i
- br.call.sptk.many rp=b6 // does not return ...
- ;;
- mov ar.pfs=loc0
- mov rp=loc1
- ;;
- mov r8=r0
- br.ret.sptk.many rp
-END(mca_handler_bhhook)
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
deleted file mode 100644
index d6eab2a1084d..000000000000
--- a/arch/ia64/kernel/minstate.h
+++ /dev/null
@@ -1,251 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#include <asm/cache.h>
-
-#include "entry.h"
-#include <asm/native/inst.h>
-
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
-/* read ar.itc in advance, and use it before leaving bank 0 */
-#define ACCOUNT_GET_STAMP \
-(pUStk) mov.m r20=ar.itc;
-#define ACCOUNT_SYS_ENTER \
-(pUStk) br.call.spnt rp=account_sys_enter \
- ;;
-#else
-#define ACCOUNT_GET_STAMP
-#define ACCOUNT_SYS_ENTER
-#endif
-
-.section ".data..patch.rse", "a"
-.previous
-
-/*
- * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
- * the minimum state necessary that allows us to turn psr.ic back
- * on.
- *
- * Assumed state upon entry:
- * psr.ic: off
- * r31: contains saved predicates (pr)
- *
- * Upon exit, the state is as follows:
- * psr.ic: off
- * r2 = points to &pt_regs.r16
- * r8 = contents of ar.ccv
- * r9 = contents of ar.csd
- * r10 = contents of ar.ssd
- * r11 = FPSR_DEFAULT
- * r12 = kernel sp (kernel virtual address)
- * r13 = points to current task_struct (kernel virtual address)
- * p15 = TRUE if psr.i is set in cr.ipsr
- * predicate registers (other than p2, p3, and p15), b6, r3, r14, r15:
- * preserved
- *
- * Note that psr.ic is NOT turned on by this macro. This is so that
- * we can pass interruption state as arguments to a handler.
- */
-#define IA64_NATIVE_DO_SAVE_MIN(__COVER,SAVE_IFS,EXTRA,WORKAROUND) \
- mov r16=IA64_KR(CURRENT); /* M */ \
- mov r27=ar.rsc; /* M */ \
- mov r20=r1; /* A */ \
- mov r25=ar.unat; /* M */ \
- MOV_FROM_IPSR(p0,r29); /* M */ \
- mov r26=ar.pfs; /* I */ \
- MOV_FROM_IIP(r28); /* M */ \
- mov r21=ar.fpsr; /* M */ \
- __COVER; /* B;; (or nothing) */ \
- ;; \
- adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16; \
- ;; \
- ld1 r17=[r16]; /* load current->thread.on_ustack flag */ \
- st1 [r16]=r0; /* clear current->thread.on_ustack flag */ \
- adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 \
- /* switch from user to kernel RBS: */ \
- ;; \
- invala; /* M */ \
- SAVE_IFS; \
- cmp.eq pKStk,pUStk=r0,r17; /* are we in kernel mode already? */ \
- ;; \
-(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \
- ;; \
-(pUStk) mov.m r24=ar.rnat; \
-(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \
-(pKStk) mov r1=sp; /* get sp */ \
- ;; \
-(pUStk) lfetch.fault.excl.nt1 [r22]; \
-(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \
-(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \
- ;; \
-(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \
-(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
- ;; \
-(pUStk) mov r18=ar.bsp; \
-(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \
- adds r17=2*L1_CACHE_BYTES,r1; /* really: biggest cache-line size */ \
- adds r16=PT(CR_IPSR),r1; \
- ;; \
- lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES; \
- st8 [r16]=r29; /* save cr.ipsr */ \
- ;; \
- lfetch.fault.excl.nt1 [r17]; \
- tbit.nz p15,p0=r29,IA64_PSR_I_BIT; \
- mov r29=b0 \
- ;; \
- WORKAROUND; \
- adds r16=PT(R8),r1; /* initialize first base pointer */ \
- adds r17=PT(R9),r1; /* initialize second base pointer */ \
-(pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \
- ;; \
-.mem.offset 0,0; st8.spill [r16]=r8,16; \
-.mem.offset 8,0; st8.spill [r17]=r9,16; \
- ;; \
-.mem.offset 0,0; st8.spill [r16]=r10,24; \
-.mem.offset 8,0; st8.spill [r17]=r11,24; \
- ;; \
- st8 [r16]=r28,16; /* save cr.iip */ \
- st8 [r17]=r30,16; /* save cr.ifs */ \
-(pUStk) sub r18=r18,r22; /* r18=RSE.ndirty*8 */ \
- mov r8=ar.ccv; \
- mov r9=ar.csd; \
- mov r10=ar.ssd; \
- movl r11=FPSR_DEFAULT; /* L-unit */ \
- ;; \
- st8 [r16]=r25,16; /* save ar.unat */ \
- st8 [r17]=r26,16; /* save ar.pfs */ \
- shl r18=r18,16; /* compute ar.rsc to be used for "loadrs" */ \
- ;; \
- st8 [r16]=r27,16; /* save ar.rsc */ \
-(pUStk) st8 [r17]=r24,16; /* save ar.rnat */ \
-(pKStk) adds r17=16,r17; /* skip over ar_rnat field */ \
- ;; /* avoid RAW on r16 & r17 */ \
-(pUStk) st8 [r16]=r23,16; /* save ar.bspstore */ \
- st8 [r17]=r31,16; /* save predicates */ \
-(pKStk) adds r16=16,r16; /* skip over ar_bspstore field */ \
- ;; \
- st8 [r16]=r29,16; /* save b0 */ \
- st8 [r17]=r18,16; /* save ar.rsc value for "loadrs" */ \
- cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \
- ;; \
-.mem.offset 0,0; st8.spill [r16]=r20,16; /* save original r1 */ \
-.mem.offset 8,0; st8.spill [r17]=r12,16; \
- adds r12=-16,r1; /* switch to kernel memory stack (with 16 bytes of scratch) */ \
- ;; \
-.mem.offset 0,0; st8.spill [r16]=r13,16; \
-.mem.offset 8,0; st8.spill [r17]=r21,16; /* save ar.fpsr */ \
- mov r13=IA64_KR(CURRENT); /* establish `current' */ \
- ;; \
-.mem.offset 0,0; st8.spill [r16]=r15,16; \
-.mem.offset 8,0; st8.spill [r17]=r14,16; \
- ;; \
-.mem.offset 0,0; st8.spill [r16]=r2,16; \
-.mem.offset 8,0; st8.spill [r17]=r3,16; \
- ACCOUNT_GET_STAMP \
- adds r2=IA64_PT_REGS_R16_OFFSET,r1; \
- ;; \
- EXTRA; \
- movl r1=__gp; /* establish kernel global pointer */ \
- ;; \
- ACCOUNT_SYS_ENTER \
- bsw.1; /* switch back to bank 1 (must be last in insn group) */ \
- ;;
-
-/*
- * SAVE_REST saves the remainder of pt_regs (with psr.ic on).
- *
- * Assumed state upon entry:
- * psr.ic: on
- * r2: points to &pt_regs.r16
- * r3: points to &pt_regs.r17
- * r8: contents of ar.ccv
- * r9: contents of ar.csd
- * r10: contents of ar.ssd
- * r11: FPSR_DEFAULT
- *
- * Registers r14 and r15 are guaranteed not to be touched by SAVE_REST.
- */
-#define SAVE_REST \
-.mem.offset 0,0; st8.spill [r2]=r16,16; \
-.mem.offset 8,0; st8.spill [r3]=r17,16; \
- ;; \
-.mem.offset 0,0; st8.spill [r2]=r18,16; \
-.mem.offset 8,0; st8.spill [r3]=r19,16; \
- ;; \
-.mem.offset 0,0; st8.spill [r2]=r20,16; \
-.mem.offset 8,0; st8.spill [r3]=r21,16; \
- mov r18=b6; \
- ;; \
-.mem.offset 0,0; st8.spill [r2]=r22,16; \
-.mem.offset 8,0; st8.spill [r3]=r23,16; \
- mov r19=b7; \
- ;; \
-.mem.offset 0,0; st8.spill [r2]=r24,16; \
-.mem.offset 8,0; st8.spill [r3]=r25,16; \
- ;; \
-.mem.offset 0,0; st8.spill [r2]=r26,16; \
-.mem.offset 8,0; st8.spill [r3]=r27,16; \
- ;; \
-.mem.offset 0,0; st8.spill [r2]=r28,16; \
-.mem.offset 8,0; st8.spill [r3]=r29,16; \
- ;; \
-.mem.offset 0,0; st8.spill [r2]=r30,16; \
-.mem.offset 8,0; st8.spill [r3]=r31,32; \
- ;; \
- mov ar.fpsr=r11; /* M-unit */ \
- st8 [r2]=r8,8; /* ar.ccv */ \
- adds r24=PT(B6)-PT(F7),r3; \
- ;; \
- stf.spill [r2]=f6,32; \
- stf.spill [r3]=f7,32; \
- ;; \
- stf.spill [r2]=f8,32; \
- stf.spill [r3]=f9,32; \
- ;; \
- stf.spill [r2]=f10; \
- stf.spill [r3]=f11; \
- adds r25=PT(B7)-PT(F11),r3; \
- ;; \
- st8 [r24]=r18,16; /* b6 */ \
- st8 [r25]=r19,16; /* b7 */ \
- ;; \
- st8 [r24]=r9; /* ar.csd */ \
- st8 [r25]=r10; /* ar.ssd */ \
- ;;
-
-#define RSE_WORKAROUND \
-(pUStk) extr.u r17=r18,3,6; \
-(pUStk) sub r16=r18,r22; \
-[1:](pKStk) br.cond.sptk.many 1f; \
- .xdata4 ".data..patch.rse",1b-. \
- ;; \
- cmp.ge p6,p7 = 33,r17; \
- ;; \
-(p6) mov r17=0x310; \
-(p7) mov r17=0x308; \
- ;; \
- cmp.leu p1,p0=r16,r17; \
-(p1) br.cond.sptk.many 1f; \
- dep.z r17=r26,0,62; \
- movl r16=2f; \
- ;; \
- mov ar.pfs=r17; \
- dep r27=r0,r27,16,14; \
- mov b0=r16; \
- ;; \
- br.ret.sptk b0; \
- ;; \
-2: \
- mov ar.rsc=r0 \
- ;; \
- flushrs; \
- ;; \
- mov ar.bspstore=r22 \
- ;; \
- mov r18=ar.bsp; \
- ;; \
-1: \
- .pred.rel "mutex", pKStk, pUStk
-
-#define SAVE_MIN_WITH_COVER DO_SAVE_MIN(COVER, mov r30=cr.ifs, , RSE_WORKAROUND)
-#define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(COVER, mov r30=cr.ifs, mov r15=r19, RSE_WORKAROUND)
-#define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, , )
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
deleted file mode 100644
index 3661135da9d9..000000000000
--- a/arch/ia64/kernel/module.c
+++ /dev/null
@@ -1,959 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * IA-64-specific support for kernel module loader.
- *
- * Copyright (C) 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * Loosely based on patch by Rusty Russell.
- */
-
-/* relocs tested so far:
-
- DIR64LSB
- FPTR64LSB
- GPREL22
- LDXMOV
- LDXMOV
- LTOFF22
- LTOFF22X
- LTOFF22X
- LTOFF_FPTR22
- PCREL21B (for br.call only; br.cond is not supported out of modules!)
- PCREL60B (for brl.cond only; brl.call is not supported for modules!)
- PCREL64LSB
- SECREL32LSB
- SEGREL64LSB
- */
-
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/elf.h>
-#include <linux/moduleloader.h>
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-
-#include <asm/patch.h>
-#include <asm/unaligned.h>
-#include <asm/sections.h>
-
-#define ARCH_MODULE_DEBUG 0
-
-#if ARCH_MODULE_DEBUG
-# define DEBUGP printk
-# define inline
-#else
-# define DEBUGP(fmt , a...)
-#endif
-
-#ifdef CONFIG_ITANIUM
-# define USE_BRL 0
-#else
-# define USE_BRL 1
-#endif
-
-#define MAX_LTOFF ((uint64_t) (1 << 22)) /* max. allowable linkage-table offset */
-
-/* Define some relocation helper macros/types: */
-
-#define FORMAT_SHIFT 0
-#define FORMAT_BITS 3
-#define FORMAT_MASK ((1 << FORMAT_BITS) - 1)
-#define VALUE_SHIFT 3
-#define VALUE_BITS 5
-#define VALUE_MASK ((1 << VALUE_BITS) - 1)
-
-enum reloc_target_format {
- /* direct encoded formats: */
- RF_NONE = 0,
- RF_INSN14 = 1,
- RF_INSN22 = 2,
- RF_INSN64 = 3,
- RF_32MSB = 4,
- RF_32LSB = 5,
- RF_64MSB = 6,
- RF_64LSB = 7,
-
- /* formats that cannot be directly decoded: */
- RF_INSN60,
- RF_INSN21B, /* imm21 form 1 */
- RF_INSN21M, /* imm21 form 2 */
- RF_INSN21F /* imm21 form 3 */
-};
-
-enum reloc_value_formula {
- RV_DIRECT = 4, /* S + A */
- RV_GPREL = 5, /* @gprel(S + A) */
- RV_LTREL = 6, /* @ltoff(S + A) */
- RV_PLTREL = 7, /* @pltoff(S + A) */
- RV_FPTR = 8, /* @fptr(S + A) */
- RV_PCREL = 9, /* S + A - P */
- RV_LTREL_FPTR = 10, /* @ltoff(@fptr(S + A)) */
- RV_SEGREL = 11, /* @segrel(S + A) */
- RV_SECREL = 12, /* @secrel(S + A) */
- RV_BDREL = 13, /* BD + A */
- RV_LTV = 14, /* S + A (like RV_DIRECT, except frozen at static link-time) */
- RV_PCREL2 = 15, /* S + A - P */
- RV_SPECIAL = 16, /* various (see below) */
- RV_RSVD17 = 17,
- RV_TPREL = 18, /* @tprel(S + A) */
- RV_LTREL_TPREL = 19, /* @ltoff(@tprel(S + A)) */
- RV_DTPMOD = 20, /* @dtpmod(S + A) */
- RV_LTREL_DTPMOD = 21, /* @ltoff(@dtpmod(S + A)) */
- RV_DTPREL = 22, /* @dtprel(S + A) */
- RV_LTREL_DTPREL = 23, /* @ltoff(@dtprel(S + A)) */
- RV_RSVD24 = 24,
- RV_RSVD25 = 25,
- RV_RSVD26 = 26,
- RV_RSVD27 = 27
- /* 28-31 reserved for implementation-specific purposes. */
-};
-
-#define N(reloc) [R_IA64_##reloc] = #reloc
-
-static const char *reloc_name[256] = {
- N(NONE), N(IMM14), N(IMM22), N(IMM64),
- N(DIR32MSB), N(DIR32LSB), N(DIR64MSB), N(DIR64LSB),
- N(GPREL22), N(GPREL64I), N(GPREL32MSB), N(GPREL32LSB),
- N(GPREL64MSB), N(GPREL64LSB), N(LTOFF22), N(LTOFF64I),
- N(PLTOFF22), N(PLTOFF64I), N(PLTOFF64MSB), N(PLTOFF64LSB),
- N(FPTR64I), N(FPTR32MSB), N(FPTR32LSB), N(FPTR64MSB),
- N(FPTR64LSB), N(PCREL60B), N(PCREL21B), N(PCREL21M),
- N(PCREL21F), N(PCREL32MSB), N(PCREL32LSB), N(PCREL64MSB),
- N(PCREL64LSB), N(LTOFF_FPTR22), N(LTOFF_FPTR64I), N(LTOFF_FPTR32MSB),
- N(LTOFF_FPTR32LSB), N(LTOFF_FPTR64MSB), N(LTOFF_FPTR64LSB), N(SEGREL32MSB),
- N(SEGREL32LSB), N(SEGREL64MSB), N(SEGREL64LSB), N(SECREL32MSB),
- N(SECREL32LSB), N(SECREL64MSB), N(SECREL64LSB), N(REL32MSB),
- N(REL32LSB), N(REL64MSB), N(REL64LSB), N(LTV32MSB),
- N(LTV32LSB), N(LTV64MSB), N(LTV64LSB), N(PCREL21BI),
- N(PCREL22), N(PCREL64I), N(IPLTMSB), N(IPLTLSB),
- N(COPY), N(LTOFF22X), N(LDXMOV), N(TPREL14),
- N(TPREL22), N(TPREL64I), N(TPREL64MSB), N(TPREL64LSB),
- N(LTOFF_TPREL22), N(DTPMOD64MSB), N(DTPMOD64LSB), N(LTOFF_DTPMOD22),
- N(DTPREL14), N(DTPREL22), N(DTPREL64I), N(DTPREL32MSB),
- N(DTPREL32LSB), N(DTPREL64MSB), N(DTPREL64LSB), N(LTOFF_DTPREL22)
-};
-
-#undef N
-
-/* Opaque struct for insns, to protect against derefs. */
-struct insn;
-
-static inline uint64_t
-bundle (const struct insn *insn)
-{
- return (uint64_t) insn & ~0xfUL;
-}
-
-static inline int
-slot (const struct insn *insn)
-{
- return (uint64_t) insn & 0x3;
-}
-
-static int
-apply_imm64 (struct module *mod, struct insn *insn, uint64_t val)
-{
- if (slot(insn) != 1 && slot(insn) != 2) {
- printk(KERN_ERR "%s: invalid slot number %d for IMM64\n",
- mod->name, slot(insn));
- return 0;
- }
- ia64_patch_imm64((u64) insn, val);
- return 1;
-}
-
-static int
-apply_imm60 (struct module *mod, struct insn *insn, uint64_t val)
-{
- if (slot(insn) != 1 && slot(insn) != 2) {
- printk(KERN_ERR "%s: invalid slot number %d for IMM60\n",
- mod->name, slot(insn));
- return 0;
- }
- if (val + ((uint64_t) 1 << 59) >= (1UL << 60)) {
- printk(KERN_ERR "%s: value %ld out of IMM60 range\n",
- mod->name, (long) val);
- return 0;
- }
- ia64_patch_imm60((u64) insn, val);
- return 1;
-}
-
-static int
-apply_imm22 (struct module *mod, struct insn *insn, uint64_t val)
-{
- if (val + (1 << 21) >= (1 << 22)) {
- printk(KERN_ERR "%s: value %li out of IMM22 range\n",
- mod->name, (long)val);
- return 0;
- }
- ia64_patch((u64) insn, 0x01fffcfe000UL, ( ((val & 0x200000UL) << 15) /* bit 21 -> 36 */
- | ((val & 0x1f0000UL) << 6) /* bit 16 -> 22 */
- | ((val & 0x00ff80UL) << 20) /* bit 7 -> 27 */
- | ((val & 0x00007fUL) << 13) /* bit 0 -> 13 */));
- return 1;
-}
-
-static int
-apply_imm21b (struct module *mod, struct insn *insn, uint64_t val)
-{
- if (val + (1 << 20) >= (1 << 21)) {
- printk(KERN_ERR "%s: value %li out of IMM21b range\n",
- mod->name, (long)val);
- return 0;
- }
- ia64_patch((u64) insn, 0x11ffffe000UL, ( ((val & 0x100000UL) << 16) /* bit 20 -> 36 */
- | ((val & 0x0fffffUL) << 13) /* bit 0 -> 13 */));
- return 1;
-}
-
-#if USE_BRL
-
-struct plt_entry {
- /* Three instruction bundles in PLT. */
- unsigned char bundle[2][16];
-};
-
-static const struct plt_entry ia64_plt_template = {
- {
- {
- 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, /* movl gp=TARGET_GP */
- 0x00, 0x00, 0x00, 0x60
- },
- {
- 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* brl.many gp=TARGET_GP */
- 0x08, 0x00, 0x00, 0xc0
- }
- }
-};
-
-static int
-patch_plt (struct module *mod, struct plt_entry *plt, long target_ip, unsigned long target_gp)
-{
- if (apply_imm64(mod, (struct insn *) (plt->bundle[0] + 2), target_gp)
- && apply_imm60(mod, (struct insn *) (plt->bundle[1] + 2),
- (target_ip - (int64_t) plt->bundle[1]) / 16))
- return 1;
- return 0;
-}
-
-unsigned long
-plt_target (struct plt_entry *plt)
-{
- uint64_t b0, b1, *b = (uint64_t *) plt->bundle[1];
- long off;
-
- b0 = b[0]; b1 = b[1];
- off = ( ((b1 & 0x00fffff000000000UL) >> 36) /* imm20b -> bit 0 */
- | ((b0 >> 48) << 20) | ((b1 & 0x7fffffUL) << 36) /* imm39 -> bit 20 */
- | ((b1 & 0x0800000000000000UL) << 0)); /* i -> bit 59 */
- return (long) plt->bundle[1] + 16*off;
-}
-
-#else /* !USE_BRL */
-
-struct plt_entry {
- /* Three instruction bundles in PLT. */
- unsigned char bundle[3][16];
-};
-
-static const struct plt_entry ia64_plt_template = {
- {
- {
- 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* movl r16=TARGET_IP */
- 0x02, 0x00, 0x00, 0x60
- },
- {
- 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, /* movl gp=TARGET_GP */
- 0x00, 0x00, 0x00, 0x60
- },
- {
- 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MIB] nop.m 0 */
- 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /* mov b6=r16 */
- 0x60, 0x00, 0x80, 0x00 /* br.few b6 */
- }
- }
-};
-
-static int
-patch_plt (struct module *mod, struct plt_entry *plt, long target_ip, unsigned long target_gp)
-{
- if (apply_imm64(mod, (struct insn *) (plt->bundle[0] + 2), target_ip)
- && apply_imm64(mod, (struct insn *) (plt->bundle[1] + 2), target_gp))
- return 1;
- return 0;
-}
-
-unsigned long
-plt_target (struct plt_entry *plt)
-{
- uint64_t b0, b1, *b = (uint64_t *) plt->bundle[0];
-
- b0 = b[0]; b1 = b[1];
- return ( ((b1 & 0x000007f000000000) >> 36) /* imm7b -> bit 0 */
- | ((b1 & 0x07fc000000000000) >> 43) /* imm9d -> bit 7 */
- | ((b1 & 0x0003e00000000000) >> 29) /* imm5c -> bit 16 */
- | ((b1 & 0x0000100000000000) >> 23) /* ic -> bit 21 */
- | ((b0 >> 46) << 22) | ((b1 & 0x7fffff) << 40) /* imm41 -> bit 22 */
- | ((b1 & 0x0800000000000000) << 4)); /* i -> bit 63 */
-}
-
-#endif /* !USE_BRL */
-
-void
-module_arch_freeing_init (struct module *mod)
-{
- if (mod->arch.init_unw_table) {
- unw_remove_unwind_table(mod->arch.init_unw_table);
- mod->arch.init_unw_table = NULL;
- }
-}
-
-/* Have we already seen one of these relocations? */
-/* FIXME: we could look in other sections, too --RR */
-static int
-duplicate_reloc (const Elf64_Rela *rela, unsigned int num)
-{
- unsigned int i;
-
- for (i = 0; i < num; i++) {
- if (rela[i].r_info == rela[num].r_info && rela[i].r_addend == rela[num].r_addend)
- return 1;
- }
- return 0;
-}
-
-/* Count how many GOT entries we may need */
-static unsigned int
-count_gots (const Elf64_Rela *rela, unsigned int num)
-{
- unsigned int i, ret = 0;
-
- /* Sure, this is order(n^2), but it's usually short, and not
- time critical */
- for (i = 0; i < num; i++) {
- switch (ELF64_R_TYPE(rela[i].r_info)) {
- case R_IA64_LTOFF22:
- case R_IA64_LTOFF22X:
- case R_IA64_LTOFF64I:
- case R_IA64_LTOFF_FPTR22:
- case R_IA64_LTOFF_FPTR64I:
- case R_IA64_LTOFF_FPTR32MSB:
- case R_IA64_LTOFF_FPTR32LSB:
- case R_IA64_LTOFF_FPTR64MSB:
- case R_IA64_LTOFF_FPTR64LSB:
- if (!duplicate_reloc(rela, i))
- ret++;
- break;
- }
- }
- return ret;
-}
-
-/* Count how many PLT entries we may need */
-static unsigned int
-count_plts (const Elf64_Rela *rela, unsigned int num)
-{
- unsigned int i, ret = 0;
-
- /* Sure, this is order(n^2), but it's usually short, and not
- time critical */
- for (i = 0; i < num; i++) {
- switch (ELF64_R_TYPE(rela[i].r_info)) {
- case R_IA64_PCREL21B:
- case R_IA64_PLTOFF22:
- case R_IA64_PLTOFF64I:
- case R_IA64_PLTOFF64MSB:
- case R_IA64_PLTOFF64LSB:
- case R_IA64_IPLTMSB:
- case R_IA64_IPLTLSB:
- if (!duplicate_reloc(rela, i))
- ret++;
- break;
- }
- }
- return ret;
-}
-
-/* We need to create an function-descriptors for any internal function
- which is referenced. */
-static unsigned int
-count_fdescs (const Elf64_Rela *rela, unsigned int num)
-{
- unsigned int i, ret = 0;
-
- /* Sure, this is order(n^2), but it's usually short, and not time critical. */
- for (i = 0; i < num; i++) {
- switch (ELF64_R_TYPE(rela[i].r_info)) {
- case R_IA64_FPTR64I:
- case R_IA64_FPTR32LSB:
- case R_IA64_FPTR32MSB:
- case R_IA64_FPTR64LSB:
- case R_IA64_FPTR64MSB:
- case R_IA64_LTOFF_FPTR22:
- case R_IA64_LTOFF_FPTR32LSB:
- case R_IA64_LTOFF_FPTR32MSB:
- case R_IA64_LTOFF_FPTR64I:
- case R_IA64_LTOFF_FPTR64LSB:
- case R_IA64_LTOFF_FPTR64MSB:
- case R_IA64_IPLTMSB:
- case R_IA64_IPLTLSB:
- /*
- * Jumps to static functions sometimes go straight to their
- * offset. Of course, that may not be possible if the jump is
- * from init -> core or vice. versa, so we need to generate an
- * FDESC (and PLT etc) for that.
- */
- case R_IA64_PCREL21B:
- if (!duplicate_reloc(rela, i))
- ret++;
- break;
- }
- }
- return ret;
-}
-
-int
-module_frob_arch_sections (Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, char *secstrings,
- struct module *mod)
-{
- unsigned long core_plts = 0, init_plts = 0, gots = 0, fdescs = 0;
- Elf64_Shdr *s, *sechdrs_end = sechdrs + ehdr->e_shnum;
-
- /*
- * To store the PLTs and function-descriptors, we expand the .text section for
- * core module-code and the .init.text section for initialization code.
- */
- for (s = sechdrs; s < sechdrs_end; ++s)
- if (strcmp(".core.plt", secstrings + s->sh_name) == 0)
- mod->arch.core_plt = s;
- else if (strcmp(".init.plt", secstrings + s->sh_name) == 0)
- mod->arch.init_plt = s;
- else if (strcmp(".got", secstrings + s->sh_name) == 0)
- mod->arch.got = s;
- else if (strcmp(".opd", secstrings + s->sh_name) == 0)
- mod->arch.opd = s;
- else if (strcmp(".IA_64.unwind", secstrings + s->sh_name) == 0)
- mod->arch.unwind = s;
-
- if (!mod->arch.core_plt || !mod->arch.init_plt || !mod->arch.got || !mod->arch.opd) {
- printk(KERN_ERR "%s: sections missing\n", mod->name);
- return -ENOEXEC;
- }
-
- /* GOT and PLTs can occur in any relocated section... */
- for (s = sechdrs + 1; s < sechdrs_end; ++s) {
- const Elf64_Rela *rels = (void *)ehdr + s->sh_offset;
- unsigned long numrels = s->sh_size/sizeof(Elf64_Rela);
-
- if (s->sh_type != SHT_RELA)
- continue;
-
- gots += count_gots(rels, numrels);
- fdescs += count_fdescs(rels, numrels);
- if (strstr(secstrings + s->sh_name, ".init"))
- init_plts += count_plts(rels, numrels);
- else
- core_plts += count_plts(rels, numrels);
- }
-
- mod->arch.core_plt->sh_type = SHT_NOBITS;
- mod->arch.core_plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
- mod->arch.core_plt->sh_addralign = 16;
- mod->arch.core_plt->sh_size = core_plts * sizeof(struct plt_entry);
- mod->arch.init_plt->sh_type = SHT_NOBITS;
- mod->arch.init_plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
- mod->arch.init_plt->sh_addralign = 16;
- mod->arch.init_plt->sh_size = init_plts * sizeof(struct plt_entry);
- mod->arch.got->sh_type = SHT_NOBITS;
- mod->arch.got->sh_flags = ARCH_SHF_SMALL | SHF_ALLOC;
- mod->arch.got->sh_addralign = 8;
- mod->arch.got->sh_size = gots * sizeof(struct got_entry);
- mod->arch.opd->sh_type = SHT_NOBITS;
- mod->arch.opd->sh_flags = SHF_ALLOC;
- mod->arch.opd->sh_addralign = 8;
- mod->arch.opd->sh_size = fdescs * sizeof(struct fdesc);
- DEBUGP("%s: core.plt=%lx, init.plt=%lx, got=%lx, fdesc=%lx\n",
- __func__, mod->arch.core_plt->sh_size, mod->arch.init_plt->sh_size,
- mod->arch.got->sh_size, mod->arch.opd->sh_size);
- return 0;
-}
-
-static inline bool
-in_init (const struct module *mod, uint64_t addr)
-{
- return within_module_init(addr, mod);
-}
-
-static inline bool
-in_core (const struct module *mod, uint64_t addr)
-{
- return within_module_core(addr, mod);
-}
-
-static inline bool
-is_internal (const struct module *mod, uint64_t value)
-{
- return in_init(mod, value) || in_core(mod, value);
-}
-
-/*
- * Get gp-relative offset for the linkage-table entry of VALUE.
- */
-static uint64_t
-get_ltoff (struct module *mod, uint64_t value, int *okp)
-{
- struct got_entry *got, *e;
-
- if (!*okp)
- return 0;
-
- got = (void *) mod->arch.got->sh_addr;
- for (e = got; e < got + mod->arch.next_got_entry; ++e)
- if (e->val == value)
- goto found;
-
- /* Not enough GOT entries? */
- BUG_ON(e >= (struct got_entry *) (mod->arch.got->sh_addr + mod->arch.got->sh_size));
-
- e->val = value;
- ++mod->arch.next_got_entry;
- found:
- return (uint64_t) e - mod->arch.gp;
-}
-
-static inline int
-gp_addressable (struct module *mod, uint64_t value)
-{
- return value - mod->arch.gp + MAX_LTOFF/2 < MAX_LTOFF;
-}
-
-/* Get PC-relative PLT entry for this value. Returns 0 on failure. */
-static uint64_t
-get_plt (struct module *mod, const struct insn *insn, uint64_t value, int *okp)
-{
- struct plt_entry *plt, *plt_end;
- uint64_t target_ip, target_gp;
-
- if (!*okp)
- return 0;
-
- if (in_init(mod, (uint64_t) insn)) {
- plt = (void *) mod->arch.init_plt->sh_addr;
- plt_end = (void *) plt + mod->arch.init_plt->sh_size;
- } else {
- plt = (void *) mod->arch.core_plt->sh_addr;
- plt_end = (void *) plt + mod->arch.core_plt->sh_size;
- }
-
- /* "value" is a pointer to a function-descriptor; fetch the target ip/gp from it: */
- target_ip = ((uint64_t *) value)[0];
- target_gp = ((uint64_t *) value)[1];
-
- /* Look for existing PLT entry. */
- while (plt->bundle[0][0]) {
- if (plt_target(plt) == target_ip)
- goto found;
- if (++plt >= plt_end)
- BUG();
- }
- *plt = ia64_plt_template;
- if (!patch_plt(mod, plt, target_ip, target_gp)) {
- *okp = 0;
- return 0;
- }
-#if ARCH_MODULE_DEBUG
- if (plt_target(plt) != target_ip) {
- printk("%s: mistargeted PLT: wanted %lx, got %lx\n",
- __func__, target_ip, plt_target(plt));
- *okp = 0;
- return 0;
- }
-#endif
- found:
- return (uint64_t) plt;
-}
-
-/* Get function descriptor for VALUE. */
-static uint64_t
-get_fdesc (struct module *mod, uint64_t value, int *okp)
-{
- struct fdesc *fdesc = (void *) mod->arch.opd->sh_addr;
-
- if (!*okp)
- return 0;
-
- if (!value) {
- printk(KERN_ERR "%s: fdesc for zero requested!\n", mod->name);
- return 0;
- }
-
- if (!is_internal(mod, value))
- /*
- * If it's not a module-local entry-point, "value" already points to a
- * function-descriptor.
- */
- return value;
-
- /* Look for existing function descriptor. */
- while (fdesc->addr) {
- if (fdesc->addr == value)
- return (uint64_t)fdesc;
- if ((uint64_t) ++fdesc >= mod->arch.opd->sh_addr + mod->arch.opd->sh_size)
- BUG();
- }
-
- /* Create new one */
- fdesc->addr = value;
- fdesc->gp = mod->arch.gp;
- return (uint64_t) fdesc;
-}
-
-static inline int
-do_reloc (struct module *mod, uint8_t r_type, Elf64_Sym *sym, uint64_t addend,
- Elf64_Shdr *sec, void *location)
-{
- enum reloc_target_format format = (r_type >> FORMAT_SHIFT) & FORMAT_MASK;
- enum reloc_value_formula formula = (r_type >> VALUE_SHIFT) & VALUE_MASK;
- uint64_t val;
- int ok = 1;
-
- val = sym->st_value + addend;
-
- switch (formula) {
- case RV_SEGREL: /* segment base is arbitrarily chosen to be 0 for kernel modules */
- case RV_DIRECT:
- break;
-
- case RV_GPREL: val -= mod->arch.gp; break;
- case RV_LTREL: val = get_ltoff(mod, val, &ok); break;
- case RV_PLTREL: val = get_plt(mod, location, val, &ok); break;
- case RV_FPTR: val = get_fdesc(mod, val, &ok); break;
- case RV_SECREL: val -= sec->sh_addr; break;
- case RV_LTREL_FPTR: val = get_ltoff(mod, get_fdesc(mod, val, &ok), &ok); break;
-
- case RV_PCREL:
- switch (r_type) {
- case R_IA64_PCREL21B:
- if ((in_init(mod, val) && in_core(mod, (uint64_t)location)) ||
- (in_core(mod, val) && in_init(mod, (uint64_t)location))) {
- /*
- * Init section may have been allocated far away from core,
- * if the branch won't reach, then allocate a plt for it.
- */
- uint64_t delta = ((int64_t)val - (int64_t)location) / 16;
- if (delta + (1 << 20) >= (1 << 21)) {
- val = get_fdesc(mod, val, &ok);
- val = get_plt(mod, location, val, &ok);
- }
- } else if (!is_internal(mod, val))
- val = get_plt(mod, location, val, &ok);
- fallthrough;
- default:
- val -= bundle(location);
- break;
-
- case R_IA64_PCREL32MSB:
- case R_IA64_PCREL32LSB:
- case R_IA64_PCREL64MSB:
- case R_IA64_PCREL64LSB:
- val -= (uint64_t) location;
- break;
-
- }
- switch (r_type) {
- case R_IA64_PCREL60B: format = RF_INSN60; break;
- case R_IA64_PCREL21B: format = RF_INSN21B; break;
- case R_IA64_PCREL21M: format = RF_INSN21M; break;
- case R_IA64_PCREL21F: format = RF_INSN21F; break;
- default: break;
- }
- break;
-
- case RV_BDREL:
- val -= (uint64_t) (in_init(mod, val) ? mod->mem[MOD_INIT_TEXT].base :
- mod->mem[MOD_TEXT].base);
- break;
-
- case RV_LTV:
- /* can link-time value relocs happen here? */
- BUG();
- break;
-
- case RV_PCREL2:
- if (r_type == R_IA64_PCREL21BI) {
- if (!is_internal(mod, val)) {
- printk(KERN_ERR "%s: %s reloc against "
- "non-local symbol (%lx)\n", __func__,
- reloc_name[r_type], (unsigned long)val);
- return -ENOEXEC;
- }
- format = RF_INSN21B;
- }
- val -= bundle(location);
- break;
-
- case RV_SPECIAL:
- switch (r_type) {
- case R_IA64_IPLTMSB:
- case R_IA64_IPLTLSB:
- val = get_fdesc(mod, get_plt(mod, location, val, &ok), &ok);
- format = RF_64LSB;
- if (r_type == R_IA64_IPLTMSB)
- format = RF_64MSB;
- break;
-
- case R_IA64_SUB:
- val = addend - sym->st_value;
- format = RF_INSN64;
- break;
-
- case R_IA64_LTOFF22X:
- if (gp_addressable(mod, val))
- val -= mod->arch.gp;
- else
- val = get_ltoff(mod, val, &ok);
- format = RF_INSN22;
- break;
-
- case R_IA64_LDXMOV:
- if (gp_addressable(mod, val)) {
- /* turn "ld8" into "mov": */
- DEBUGP("%s: patching ld8 at %p to mov\n", __func__, location);
- ia64_patch((u64) location, 0x1fff80fe000UL, 0x10000000000UL);
- }
- return 0;
-
- default:
- if (reloc_name[r_type])
- printk(KERN_ERR "%s: special reloc %s not supported",
- mod->name, reloc_name[r_type]);
- else
- printk(KERN_ERR "%s: unknown special reloc %x\n",
- mod->name, r_type);
- return -ENOEXEC;
- }
- break;
-
- case RV_TPREL:
- case RV_LTREL_TPREL:
- case RV_DTPMOD:
- case RV_LTREL_DTPMOD:
- case RV_DTPREL:
- case RV_LTREL_DTPREL:
- printk(KERN_ERR "%s: %s reloc not supported\n",
- mod->name, reloc_name[r_type] ? reloc_name[r_type] : "?");
- return -ENOEXEC;
-
- default:
- printk(KERN_ERR "%s: unknown reloc %x\n", mod->name, r_type);
- return -ENOEXEC;
- }
-
- if (!ok)
- return -ENOEXEC;
-
- DEBUGP("%s: [%p]<-%016lx = %s(%lx)\n", __func__, location, val,
- reloc_name[r_type] ? reloc_name[r_type] : "?", sym->st_value + addend);
-
- switch (format) {
- case RF_INSN21B: ok = apply_imm21b(mod, location, (int64_t) val / 16); break;
- case RF_INSN22: ok = apply_imm22(mod, location, val); break;
- case RF_INSN64: ok = apply_imm64(mod, location, val); break;
- case RF_INSN60: ok = apply_imm60(mod, location, (int64_t) val / 16); break;
- case RF_32LSB: put_unaligned(val, (uint32_t *) location); break;
- case RF_64LSB: put_unaligned(val, (uint64_t *) location); break;
- case RF_32MSB: /* ia64 Linux is little-endian... */
- case RF_64MSB: /* ia64 Linux is little-endian... */
- case RF_INSN14: /* must be within-module, i.e., resolved by "ld -r" */
- case RF_INSN21M: /* must be within-module, i.e., resolved by "ld -r" */
- case RF_INSN21F: /* must be within-module, i.e., resolved by "ld -r" */
- printk(KERN_ERR "%s: format %u needed by %s reloc is not supported\n",
- mod->name, format, reloc_name[r_type] ? reloc_name[r_type] : "?");
- return -ENOEXEC;
-
- default:
- printk(KERN_ERR "%s: relocation %s resulted in unknown format %u\n",
- mod->name, reloc_name[r_type] ? reloc_name[r_type] : "?", format);
- return -ENOEXEC;
- }
- return ok ? 0 : -ENOEXEC;
-}
-
-int
-apply_relocate_add (Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex,
- unsigned int relsec, struct module *mod)
-{
- unsigned int i, n = sechdrs[relsec].sh_size / sizeof(Elf64_Rela);
- Elf64_Rela *rela = (void *) sechdrs[relsec].sh_addr;
- Elf64_Shdr *target_sec;
- int ret;
-
- DEBUGP("%s: applying section %u (%u relocs) to %u\n", __func__,
- relsec, n, sechdrs[relsec].sh_info);
-
- target_sec = sechdrs + sechdrs[relsec].sh_info;
-
- if (target_sec->sh_entsize == ~0UL)
- /*
- * If target section wasn't allocated, we don't need to relocate it.
- * Happens, e.g., for debug sections.
- */
- return 0;
-
- if (!mod->arch.gp) {
- /*
- * XXX Should have an arch-hook for running this after final section
- * addresses have been selected...
- */
- uint64_t gp;
- struct module_memory *mod_mem;
-
- mod_mem = &mod->mem[MOD_DATA];
- if (mod_mem->size > MAX_LTOFF)
- /*
- * This takes advantage of fact that SHF_ARCH_SMALL gets allocated
- * at the end of the module.
- */
- gp = mod_mem->size - MAX_LTOFF / 2;
- else
- gp = mod_mem->size / 2;
- gp = (uint64_t) mod_mem->base + ((gp + 7) & -8);
- mod->arch.gp = gp;
- DEBUGP("%s: placing gp at 0x%lx\n", __func__, gp);
- }
-
- for (i = 0; i < n; i++) {
- ret = do_reloc(mod, ELF64_R_TYPE(rela[i].r_info),
- ((Elf64_Sym *) sechdrs[symindex].sh_addr
- + ELF64_R_SYM(rela[i].r_info)),
- rela[i].r_addend, target_sec,
- (void *) target_sec->sh_addr + rela[i].r_offset);
- if (ret < 0)
- return ret;
- }
- return 0;
-}
-
-/*
- * Modules contain a single unwind table which covers both the core and the init text
- * sections but since the two are not contiguous, we need to split this table up such that
- * we can register (and unregister) each "segment" separately. Fortunately, this sounds
- * more complicated than it really is.
- */
-static void
-register_unwind_table (struct module *mod)
-{
- struct unw_table_entry *start = (void *) mod->arch.unwind->sh_addr;
- struct unw_table_entry *end = start + mod->arch.unwind->sh_size / sizeof (*start);
- struct unw_table_entry *e1, *e2, *core, *init;
- unsigned long num_init = 0, num_core = 0;
-
- /* First, count how many init and core unwind-table entries there are. */
- for (e1 = start; e1 < end; ++e1)
- if (in_init(mod, e1->start_offset))
- ++num_init;
- else
- ++num_core;
- /*
- * Second, sort the table such that all unwind-table entries for the init and core
- * text sections are nicely separated. We do this with a stupid bubble sort
- * (unwind tables don't get ridiculously huge).
- */
- for (e1 = start; e1 < end; ++e1) {
- for (e2 = e1 + 1; e2 < end; ++e2) {
- if (e2->start_offset < e1->start_offset) {
- swap(*e1, *e2);
- }
- }
- }
- /*
- * Third, locate the init and core segments in the unwind table:
- */
- if (in_init(mod, start->start_offset)) {
- init = start;
- core = start + num_init;
- } else {
- core = start;
- init = start + num_core;
- }
-
- DEBUGP("%s: name=%s, gp=%lx, num_init=%lu, num_core=%lu\n", __func__,
- mod->name, mod->arch.gp, num_init, num_core);
-
- /*
- * Fourth, register both tables (if not empty).
- */
- if (num_core > 0) {
- mod->arch.core_unw_table = unw_add_unwind_table(mod->name, 0, mod->arch.gp,
- core, core + num_core);
- DEBUGP("%s: core: handle=%p [%p-%p)\n", __func__,
- mod->arch.core_unw_table, core, core + num_core);
- }
- if (num_init > 0) {
- mod->arch.init_unw_table = unw_add_unwind_table(mod->name, 0, mod->arch.gp,
- init, init + num_init);
- DEBUGP("%s: init: handle=%p [%p-%p)\n", __func__,
- mod->arch.init_unw_table, init, init + num_init);
- }
-}
-
-int
-module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod)
-{
- struct mod_arch_specific *mas = &mod->arch;
-
- DEBUGP("%s: init: entry=%p\n", __func__, mod->init);
- if (mas->unwind)
- register_unwind_table(mod);
-
- /*
- * ".opd" was already relocated to the final destination. Store
- * it's address for use in symbolizer.
- */
- mas->opd_addr = (void *)mas->opd->sh_addr;
- mas->opd_size = mas->opd->sh_size;
-
- /*
- * Module relocation was already done at this point. Section
- * headers are about to be deleted. Wipe out load-time context.
- */
- mas->core_plt = NULL;
- mas->init_plt = NULL;
- mas->got = NULL;
- mas->opd = NULL;
- mas->unwind = NULL;
- mas->gp = 0;
- mas->next_got_entry = 0;
-
- return 0;
-}
-
-void
-module_arch_cleanup (struct module *mod)
-{
- if (mod->arch.init_unw_table) {
- unw_remove_unwind_table(mod->arch.init_unw_table);
- mod->arch.init_unw_table = NULL;
- }
- if (mod->arch.core_unw_table) {
- unw_remove_unwind_table(mod->arch.core_unw_table);
- mod->arch.core_unw_table = NULL;
- }
-}
-
-void *dereference_module_function_descriptor(struct module *mod, void *ptr)
-{
- struct mod_arch_specific *mas = &mod->arch;
-
- if (ptr < mas->opd_addr || ptr >= mas->opd_addr + mas->opd_size)
- return ptr;
-
- return dereference_function_descriptor(ptr);
-}
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
deleted file mode 100644
index 025e5133c860..000000000000
--- a/arch/ia64/kernel/msi_ia64.c
+++ /dev/null
@@ -1,198 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * MSI hooks for standard x86 apic
- */
-
-#include <linux/pci.h>
-#include <linux/irq.h>
-#include <linux/msi.h>
-#include <linux/dmar.h>
-#include <asm/smp.h>
-#include <asm/msidef.h>
-
-static struct irq_chip ia64_msi_chip;
-
-#ifdef CONFIG_SMP
-static int ia64_set_msi_irq_affinity(struct irq_data *idata,
- const cpumask_t *cpu_mask, bool force)
-{
- struct msi_msg msg;
- u32 addr, data;
- int cpu = cpumask_first_and(cpu_mask, cpu_online_mask);
- unsigned int irq = idata->irq;
-
- if (irq_prepare_move(irq, cpu))
- return -1;
-
- __get_cached_msi_msg(irq_data_get_msi_desc(idata), &msg);
-
- addr = msg.address_lo;
- addr &= MSI_ADDR_DEST_ID_MASK;
- addr |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu));
- msg.address_lo = addr;
-
- data = msg.data;
- data &= MSI_DATA_VECTOR_MASK;
- data |= MSI_DATA_VECTOR(irq_to_vector(irq));
- msg.data = data;
-
- pci_write_msi_msg(irq, &msg);
- irq_data_update_affinity(idata, cpumask_of(cpu));
-
- return 0;
-}
-#endif /* CONFIG_SMP */
-
-int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
-{
- struct msi_msg msg;
- unsigned long dest_phys_id;
- int irq, vector;
-
- irq = create_irq();
- if (irq < 0)
- return irq;
-
- irq_set_msi_desc(irq, desc);
- dest_phys_id = cpu_physical_id(cpumask_any_and(&(irq_to_domain(irq)),
- cpu_online_mask));
- vector = irq_to_vector(irq);
-
- msg.address_hi = 0;
- msg.address_lo =
- MSI_ADDR_HEADER |
- MSI_ADDR_DEST_MODE_PHYS |
- MSI_ADDR_REDIRECTION_CPU |
- MSI_ADDR_DEST_ID_CPU(dest_phys_id);
-
- msg.data =
- MSI_DATA_TRIGGER_EDGE |
- MSI_DATA_LEVEL_ASSERT |
- MSI_DATA_DELIVERY_FIXED |
- MSI_DATA_VECTOR(vector);
-
- pci_write_msi_msg(irq, &msg);
- irq_set_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
-
- return 0;
-}
-
-void arch_teardown_msi_irq(unsigned int irq)
-{
- destroy_irq(irq);
-}
-
-static void ia64_ack_msi_irq(struct irq_data *data)
-{
- irq_complete_move(data->irq);
- irq_move_irq(data);
- ia64_eoi();
-}
-
-static int ia64_msi_retrigger_irq(struct irq_data *data)
-{
- unsigned int vector = irq_to_vector(data->irq);
- ia64_resend_irq(vector);
-
- return 1;
-}
-
-/*
- * Generic ops used on most IA64 platforms.
- */
-static struct irq_chip ia64_msi_chip = {
- .name = "PCI-MSI",
- .irq_mask = pci_msi_mask_irq,
- .irq_unmask = pci_msi_unmask_irq,
- .irq_ack = ia64_ack_msi_irq,
-#ifdef CONFIG_SMP
- .irq_set_affinity = ia64_set_msi_irq_affinity,
-#endif
- .irq_retrigger = ia64_msi_retrigger_irq,
-};
-
-#ifdef CONFIG_INTEL_IOMMU
-#ifdef CONFIG_SMP
-static int dmar_msi_set_affinity(struct irq_data *data,
- const struct cpumask *mask, bool force)
-{
- unsigned int irq = data->irq;
- struct irq_cfg *cfg = irq_cfg + irq;
- struct msi_msg msg;
- int cpu = cpumask_first_and(mask, cpu_online_mask);
-
- if (irq_prepare_move(irq, cpu))
- return -1;
-
- dmar_msi_read(irq, &msg);
-
- msg.data &= ~MSI_DATA_VECTOR_MASK;
- msg.data |= MSI_DATA_VECTOR(cfg->vector);
- msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
- msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu));
-
- dmar_msi_write(irq, &msg);
- irq_data_update_affinity(data, mask);
-
- return 0;
-}
-#endif /* CONFIG_SMP */
-
-static struct irq_chip dmar_msi_type = {
- .name = "DMAR_MSI",
- .irq_unmask = dmar_msi_unmask,
- .irq_mask = dmar_msi_mask,
- .irq_ack = ia64_ack_msi_irq,
-#ifdef CONFIG_SMP
- .irq_set_affinity = dmar_msi_set_affinity,
-#endif
- .irq_retrigger = ia64_msi_retrigger_irq,
-};
-
-static void
-msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
-{
- struct irq_cfg *cfg = irq_cfg + irq;
- unsigned dest;
-
- dest = cpu_physical_id(cpumask_first_and(&(irq_to_domain(irq)),
- cpu_online_mask));
-
- msg->address_hi = 0;
- msg->address_lo =
- MSI_ADDR_HEADER |
- MSI_ADDR_DEST_MODE_PHYS |
- MSI_ADDR_REDIRECTION_CPU |
- MSI_ADDR_DEST_ID_CPU(dest);
-
- msg->data =
- MSI_DATA_TRIGGER_EDGE |
- MSI_DATA_LEVEL_ASSERT |
- MSI_DATA_DELIVERY_FIXED |
- MSI_DATA_VECTOR(cfg->vector);
-}
-
-int dmar_alloc_hwirq(int id, int node, void *arg)
-{
- int irq;
- struct msi_msg msg;
-
- irq = create_irq();
- if (irq > 0) {
- irq_set_handler_data(irq, arg);
- irq_set_chip_and_handler_name(irq, &dmar_msi_type,
- handle_edge_irq, "edge");
- msi_compose_msg(NULL, irq, &msg);
- dmar_msi_write(irq, &msg);
- }
-
- return irq;
-}
-
-void dmar_free_hwirq(int irq)
-{
- irq_set_handler_data(irq, NULL);
- destroy_irq(irq);
-}
-#endif /* CONFIG_INTEL_IOMMU */
-
diff --git a/arch/ia64/kernel/numa.c b/arch/ia64/kernel/numa.c
deleted file mode 100644
index 8a959f20662d..000000000000
--- a/arch/ia64/kernel/numa.c
+++ /dev/null
@@ -1,73 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- * ia64 kernel NUMA specific stuff
- *
- * Copyright (C) 2002 Erich Focht <efocht@ess.nec.de>
- * Copyright (C) 2004 Silicon Graphics, Inc.
- * Jesse Barnes <jbarnes@sgi.com>
- */
-#include <linux/topology.h>
-#include <linux/module.h>
-#include <asm/processor.h>
-#include <asm/smp.h>
-
-u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(cpu_to_node_map);
-
-cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
-EXPORT_SYMBOL(node_to_cpu_mask);
-
-void map_cpu_to_node(int cpu, int nid)
-{
- int oldnid;
- if (nid < 0) { /* just initialize by zero */
- cpu_to_node_map[cpu] = 0;
- return;
- }
- /* sanity check first */
- oldnid = cpu_to_node_map[cpu];
- if (cpumask_test_cpu(cpu, &node_to_cpu_mask[oldnid])) {
- return; /* nothing to do */
- }
- /* we don't have cpu-driven node hot add yet...
- In usual case, node is created from SRAT at boot time. */
- if (!node_online(nid))
- nid = first_online_node;
- cpu_to_node_map[cpu] = nid;
- cpumask_set_cpu(cpu, &node_to_cpu_mask[nid]);
- return;
-}
-
-void unmap_cpu_from_node(int cpu, int nid)
-{
- WARN_ON(!cpumask_test_cpu(cpu, &node_to_cpu_mask[nid]));
- WARN_ON(cpu_to_node_map[cpu] != nid);
- cpu_to_node_map[cpu] = 0;
- cpumask_clear_cpu(cpu, &node_to_cpu_mask[nid]);
-}
-
-
-/**
- * build_cpu_to_node_map - setup cpu to node and node to cpumask arrays
- *
- * Build cpu to node mapping and initialize the per node cpu masks using
- * info from the node_cpuid array handed to us by ACPI.
- */
-void __init build_cpu_to_node_map(void)
-{
- int cpu, i, node;
-
- for(node=0; node < MAX_NUMNODES; node++)
- cpumask_clear(&node_to_cpu_mask[node]);
-
- for_each_possible_early_cpu(cpu) {
- node = NUMA_NO_NODE;
- for (i = 0; i < NR_CPUS; ++i)
- if (cpu_physical_id(cpu) == node_cpuid[i].phys_id) {
- node = node_cpuid[i].nid;
- break;
- }
- map_cpu_to_node(cpu, node);
- }
-}
diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S
deleted file mode 100644
index fb6db6966f70..000000000000
--- a/arch/ia64/kernel/pal.S
+++ /dev/null
@@ -1,306 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * PAL Firmware support
- * IA-64 Processor Programmers Reference Vol 2
- *
- * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999-2001, 2003 Hewlett-Packard Co
- * David Mosberger <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- *
- * 05/22/2000 eranian Added support for stacked register calls
- * 05/24/2000 eranian Added support for physical mode static calls
- */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-#include <asm/processor.h>
-
- .data
-pal_entry_point:
- data8 ia64_pal_default_handler
- .text
-
-/*
- * Set the PAL entry point address. This could be written in C code, but we
- * do it here to keep it all in one module (besides, it's so trivial that it's
- * not a big deal).
- *
- * in0 Address of the PAL entry point (text address, NOT a function
- * descriptor).
- */
-GLOBAL_ENTRY(ia64_pal_handler_init)
- alloc r3=ar.pfs,1,0,0,0
- movl r2=pal_entry_point
- ;;
- st8 [r2]=in0
- br.ret.sptk.many rp
-END(ia64_pal_handler_init)
-
-/*
- * Default PAL call handler. This needs to be coded in assembly because it
- * uses the static calling convention, i.e., the RSE may not be used and
- * calls are done via "br.cond" (not "br.call").
- */
-GLOBAL_ENTRY(ia64_pal_default_handler)
- mov r8=-1
- br.cond.sptk.many rp
-END(ia64_pal_default_handler)
-
-/*
- * Make a PAL call using the static calling convention.
- *
- * in0 Index of PAL service
- * in1 - in3 Remaining PAL arguments
- */
-GLOBAL_ENTRY(ia64_pal_call_static)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
- alloc loc1 = ar.pfs,4,5,0,0
- movl loc2 = pal_entry_point
-1: {
- mov r28 = in0
- mov r29 = in1
- mov r8 = ip
- }
- ;;
- ld8 loc2 = [loc2] // loc2 <- entry point
- adds r8 = 1f-1b,r8
- mov loc4=ar.rsc // save RSE configuration
- ;;
- mov ar.rsc=0 // put RSE in enforced lazy, LE mode
- mov loc3 = psr
- mov loc0 = rp
- .body
- mov r30 = in2
-
- mov r31 = in3
- mov b7 = loc2
-
- rsm psr.i
- ;;
- mov rp = r8
- br.cond.sptk.many b7
-1: mov psr.l = loc3
- mov ar.rsc = loc4 // restore RSE configuration
- mov ar.pfs = loc1
- mov rp = loc0
- ;;
- srlz.d // serialize restoration of psr.l
- br.ret.sptk.many b0
-END(ia64_pal_call_static)
-EXPORT_SYMBOL(ia64_pal_call_static)
-
-/*
- * Make a PAL call using the stacked registers calling convention.
- *
- * Inputs:
- * in0 Index of PAL service
- * in2 - in3 Remaining PAL arguments
- */
-GLOBAL_ENTRY(ia64_pal_call_stacked)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
- alloc loc1 = ar.pfs,4,4,4,0
- movl loc2 = pal_entry_point
-
- mov r28 = in0 // Index MUST be copied to r28
- mov out0 = in0 // AND in0 of PAL function
- mov loc0 = rp
- .body
- ;;
- ld8 loc2 = [loc2] // loc2 <- entry point
- mov out1 = in1
- mov out2 = in2
- mov out3 = in3
- mov loc3 = psr
- ;;
- rsm psr.i
- mov b7 = loc2
- ;;
- br.call.sptk.many rp=b7 // now make the call
-.ret0: mov psr.l = loc3
- mov ar.pfs = loc1
- mov rp = loc0
- ;;
- srlz.d // serialize restoration of psr.l
- br.ret.sptk.many b0
-END(ia64_pal_call_stacked)
-EXPORT_SYMBOL(ia64_pal_call_stacked)
-
-/*
- * Make a physical mode PAL call using the static registers calling convention.
- *
- * Inputs:
- * in0 Index of PAL service
- * in2 - in3 Remaining PAL arguments
- *
- * PSR_LP, PSR_TB, PSR_ID, PSR_DA are never set by the kernel.
- * So we don't need to clear them.
- */
-#define PAL_PSR_BITS_TO_CLEAR \
- (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_DB | IA64_PSR_RT |\
- IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED | \
- IA64_PSR_DFL | IA64_PSR_DFH)
-
-#define PAL_PSR_BITS_TO_SET \
- (IA64_PSR_BN)
-
-
-GLOBAL_ENTRY(ia64_pal_call_phys_static)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
- alloc loc1 = ar.pfs,4,7,0,0
- movl loc2 = pal_entry_point
-1: {
- mov r28 = in0 // copy procedure index
- mov r8 = ip // save ip to compute branch
- mov loc0 = rp // save rp
- }
- .body
- ;;
- ld8 loc2 = [loc2] // loc2 <- entry point
- mov r29 = in1 // first argument
- mov r30 = in2 // copy arg2
- mov r31 = in3 // copy arg3
- ;;
- mov loc3 = psr // save psr
- adds r8 = 1f-1b,r8 // calculate return address for call
- ;;
- mov loc4=ar.rsc // save RSE configuration
- dep.z loc2=loc2,0,61 // convert pal entry point to physical
- tpa r8=r8 // convert rp to physical
- ;;
- mov b7 = loc2 // install target to branch reg
- mov ar.rsc=0 // put RSE in enforced lazy, LE mode
- movl r16=PAL_PSR_BITS_TO_CLEAR
- movl r17=PAL_PSR_BITS_TO_SET
- ;;
- or loc3=loc3,r17 // add in psr the bits to set
- ;;
- andcm r16=loc3,r16 // removes bits to clear from psr
- br.call.sptk.many rp=ia64_switch_mode_phys
- mov rp = r8 // install return address (physical)
- mov loc5 = r19
- mov loc6 = r20
- br.cond.sptk.many b7
-1:
- mov ar.rsc=0 // put RSE in enforced lazy, LE mode
- mov r16=loc3 // r16= original psr
- mov r19=loc5
- mov r20=loc6
- br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
- mov psr.l = loc3 // restore init PSR
-
- mov ar.pfs = loc1
- mov rp = loc0
- ;;
- mov ar.rsc=loc4 // restore RSE configuration
- srlz.d // serialize restoration of psr.l
- br.ret.sptk.many b0
-END(ia64_pal_call_phys_static)
-EXPORT_SYMBOL(ia64_pal_call_phys_static)
-
-/*
- * Make a PAL call using the stacked registers in physical mode.
- *
- * Inputs:
- * in0 Index of PAL service
- * in2 - in3 Remaining PAL arguments
- */
-GLOBAL_ENTRY(ia64_pal_call_phys_stacked)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
- alloc loc1 = ar.pfs,5,7,4,0
- movl loc2 = pal_entry_point
-1: {
- mov r28 = in0 // copy procedure index
- mov loc0 = rp // save rp
- }
- .body
- ;;
- ld8 loc2 = [loc2] // loc2 <- entry point
- mov loc3 = psr // save psr
- ;;
- mov loc4=ar.rsc // save RSE configuration
- dep.z loc2=loc2,0,61 // convert pal entry point to physical
- ;;
- mov ar.rsc=0 // put RSE in enforced lazy, LE mode
- movl r16=PAL_PSR_BITS_TO_CLEAR
- movl r17=PAL_PSR_BITS_TO_SET
- ;;
- or loc3=loc3,r17 // add in psr the bits to set
- mov b7 = loc2 // install target to branch reg
- ;;
- andcm r16=loc3,r16 // removes bits to clear from psr
- br.call.sptk.many rp=ia64_switch_mode_phys
-
- mov out0 = in0 // first argument
- mov out1 = in1 // copy arg2
- mov out2 = in2 // copy arg3
- mov out3 = in3 // copy arg3
- mov loc5 = r19
- mov loc6 = r20
-
- br.call.sptk.many rp=b7 // now make the call
-
- mov ar.rsc=0 // put RSE in enforced lazy, LE mode
- mov r16=loc3 // r16= original psr
- mov r19=loc5
- mov r20=loc6
- br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
-
- mov psr.l = loc3 // restore init PSR
- mov ar.pfs = loc1
- mov rp = loc0
- ;;
- mov ar.rsc=loc4 // restore RSE configuration
- srlz.d // serialize restoration of psr.l
- br.ret.sptk.many b0
-END(ia64_pal_call_phys_stacked)
-EXPORT_SYMBOL(ia64_pal_call_phys_stacked)
-
-/*
- * Save scratch fp scratch regs which aren't saved in pt_regs already
- * (fp10-fp15).
- *
- * NOTE: We need to do this since firmware (SAL and PAL) may use any of the
- * scratch regs fp-low partition.
- *
- * Inputs:
- * in0 Address of stack storage for fp regs
- */
-GLOBAL_ENTRY(ia64_save_scratch_fpregs)
- alloc r3=ar.pfs,1,0,0,0
- add r2=16,in0
- ;;
- stf.spill [in0] = f10,32
- stf.spill [r2] = f11,32
- ;;
- stf.spill [in0] = f12,32
- stf.spill [r2] = f13,32
- ;;
- stf.spill [in0] = f14,32
- stf.spill [r2] = f15,32
- br.ret.sptk.many rp
-END(ia64_save_scratch_fpregs)
-EXPORT_SYMBOL(ia64_save_scratch_fpregs)
-
-/*
- * Load scratch fp scratch regs (fp10-fp15)
- *
- * Inputs:
- * in0 Address of stack storage for fp regs
- */
-GLOBAL_ENTRY(ia64_load_scratch_fpregs)
- alloc r3=ar.pfs,1,0,0,0
- add r2=16,in0
- ;;
- ldf.fill f10 = [in0],32
- ldf.fill f11 = [r2],32
- ;;
- ldf.fill f12 = [in0],32
- ldf.fill f13 = [r2],32
- ;;
- ldf.fill f14 = [in0],32
- ldf.fill f15 = [r2],32
- br.ret.sptk.many rp
-END(ia64_load_scratch_fpregs)
-EXPORT_SYMBOL(ia64_load_scratch_fpregs)
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
deleted file mode 100644
index b9ae093bfe37..000000000000
--- a/arch/ia64/kernel/palinfo.c
+++ /dev/null
@@ -1,942 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * palinfo.c
- *
- * Prints processor specific information reported by PAL.
- * This code is based on specification of PAL as of the
- * Intel IA-64 Architecture Software Developer's Manual v1.0.
- *
- *
- * Copyright (C) 2000-2001, 2003 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 2004 Intel Corporation
- * Ashok Raj <ashok.raj@intel.com>
- *
- * 05/26/2000 S.Eranian initial release
- * 08/21/2000 S.Eranian updated to July 2000 PAL specs
- * 02/05/2001 S.Eranian fixed module support
- * 10/23/2001 S.Eranian updated pal_perf_mon_info bug fixes
- * 03/24/2004 Ashok Raj updated to work with CPU Hotplug
- * 10/26/2006 Russ Anderson updated processor features to rev 2.2 spec
- */
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/efi.h>
-#include <linux/notifier.h>
-#include <linux/cpu.h>
-#include <linux/cpumask.h>
-
-#include <asm/pal.h>
-#include <asm/sal.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <linux/smp.h>
-
-MODULE_AUTHOR("Stephane Eranian <eranian@hpl.hp.com>");
-MODULE_DESCRIPTION("/proc interface to IA-64 PAL");
-MODULE_LICENSE("GPL");
-
-#define PALINFO_VERSION "0.5"
-
-typedef int (*palinfo_func_t)(struct seq_file *);
-
-typedef struct {
- const char *name; /* name of the proc entry */
- palinfo_func_t proc_read; /* function to call for reading */
- struct proc_dir_entry *entry; /* registered entry (removal) */
-} palinfo_entry_t;
-
-
-/*
- * A bunch of string array to get pretty printing
- */
-
-static const char *cache_types[] = {
- "", /* not used */
- "Instruction",
- "Data",
- "Data/Instruction" /* unified */
-};
-
-static const char *cache_mattrib[]={
- "WriteThrough",
- "WriteBack",
- "", /* reserved */
- "" /* reserved */
-};
-
-static const char *cache_st_hints[]={
- "Temporal, level 1",
- "Reserved",
- "Reserved",
- "Non-temporal, all levels",
- "Reserved",
- "Reserved",
- "Reserved",
- "Reserved"
-};
-
-static const char *cache_ld_hints[]={
- "Temporal, level 1",
- "Non-temporal, level 1",
- "Reserved",
- "Non-temporal, all levels",
- "Reserved",
- "Reserved",
- "Reserved",
- "Reserved"
-};
-
-static const char *rse_hints[]={
- "enforced lazy",
- "eager stores",
- "eager loads",
- "eager loads and stores"
-};
-
-#define RSE_HINTS_COUNT ARRAY_SIZE(rse_hints)
-
-static const char *mem_attrib[]={
- "WB", /* 000 */
- "SW", /* 001 */
- "010", /* 010 */
- "011", /* 011 */
- "UC", /* 100 */
- "UCE", /* 101 */
- "WC", /* 110 */
- "NaTPage" /* 111 */
-};
-
-/*
- * Take a 64bit vector and produces a string such that
- * if bit n is set then 2^n in clear text is generated. The adjustment
- * to the right unit is also done.
- *
- * Input:
- * - a pointer to a buffer to hold the string
- * - a 64-bit vector
- * Output:
- * - a pointer to the end of the buffer
- *
- */
-static void bitvector_process(struct seq_file *m, u64 vector)
-{
- int i,j;
- static const char *units[]={ "", "K", "M", "G", "T" };
-
- for (i=0, j=0; i < 64; i++ , j=i/10) {
- if (vector & 0x1)
- seq_printf(m, "%d%s ", 1 << (i-j*10), units[j]);
- vector >>= 1;
- }
-}
-
-/*
- * Take a 64bit vector and produces a string such that
- * if bit n is set then register n is present. The function
- * takes into account consecutive registers and prints out ranges.
- *
- * Input:
- * - a pointer to a buffer to hold the string
- * - a 64-bit vector
- * Ouput:
- * - a pointer to the end of the buffer
- *
- */
-static void bitregister_process(struct seq_file *m, u64 *reg_info, int max)
-{
- int i, begin, skip = 0;
- u64 value = reg_info[0];
-
- value >>= i = begin = ffs(value) - 1;
-
- for(; i < max; i++ ) {
-
- if (i != 0 && (i%64) == 0) value = *++reg_info;
-
- if ((value & 0x1) == 0 && skip == 0) {
- if (begin <= i - 2)
- seq_printf(m, "%d-%d ", begin, i-1);
- else
- seq_printf(m, "%d ", i-1);
- skip = 1;
- begin = -1;
- } else if ((value & 0x1) && skip == 1) {
- skip = 0;
- begin = i;
- }
- value >>=1;
- }
- if (begin > -1) {
- if (begin < 127)
- seq_printf(m, "%d-127", begin);
- else
- seq_puts(m, "127");
- }
-}
-
-static int power_info(struct seq_file *m)
-{
- s64 status;
- u64 halt_info_buffer[8];
- pal_power_mgmt_info_u_t *halt_info =(pal_power_mgmt_info_u_t *)halt_info_buffer;
- int i;
-
- status = ia64_pal_halt_info(halt_info);
- if (status != 0) return 0;
-
- for (i=0; i < 8 ; i++ ) {
- if (halt_info[i].pal_power_mgmt_info_s.im == 1) {
- seq_printf(m,
- "Power level %d:\n"
- "\tentry_latency : %d cycles\n"
- "\texit_latency : %d cycles\n"
- "\tpower consumption : %d mW\n"
- "\tCache+TLB coherency : %s\n", i,
- halt_info[i].pal_power_mgmt_info_s.entry_latency,
- halt_info[i].pal_power_mgmt_info_s.exit_latency,
- halt_info[i].pal_power_mgmt_info_s.power_consumption,
- halt_info[i].pal_power_mgmt_info_s.co ? "Yes" : "No");
- } else {
- seq_printf(m,"Power level %d: not implemented\n", i);
- }
- }
- return 0;
-}
-
-static int cache_info(struct seq_file *m)
-{
- unsigned long i, levels, unique_caches;
- pal_cache_config_info_t cci;
- int j, k;
- long status;
-
- if ((status = ia64_pal_cache_summary(&levels, &unique_caches)) != 0) {
- printk(KERN_ERR "ia64_pal_cache_summary=%ld\n", status);
- return 0;
- }
-
- seq_printf(m, "Cache levels : %ld\nUnique caches : %ld\n\n",
- levels, unique_caches);
-
- for (i=0; i < levels; i++) {
- for (j=2; j >0 ; j--) {
- /* even without unification some level may not be present */
- if ((status=ia64_pal_cache_config_info(i,j, &cci)) != 0)
- continue;
-
- seq_printf(m,
- "%s Cache level %lu:\n"
- "\tSize : %u bytes\n"
- "\tAttributes : ",
- cache_types[j+cci.pcci_unified], i+1,
- cci.pcci_cache_size);
-
- if (cci.pcci_unified)
- seq_puts(m, "Unified ");
-
- seq_printf(m, "%s\n", cache_mattrib[cci.pcci_cache_attr]);
-
- seq_printf(m,
- "\tAssociativity : %d\n"
- "\tLine size : %d bytes\n"
- "\tStride : %d bytes\n",
- cci.pcci_assoc,
- 1<<cci.pcci_line_size,
- 1<<cci.pcci_stride);
- if (j == 1)
- seq_puts(m, "\tStore latency : N/A\n");
- else
- seq_printf(m, "\tStore latency : %d cycle(s)\n",
- cci.pcci_st_latency);
-
- seq_printf(m,
- "\tLoad latency : %d cycle(s)\n"
- "\tStore hints : ", cci.pcci_ld_latency);
-
- for(k=0; k < 8; k++ ) {
- if ( cci.pcci_st_hints & 0x1)
- seq_printf(m, "[%s]", cache_st_hints[k]);
- cci.pcci_st_hints >>=1;
- }
- seq_puts(m, "\n\tLoad hints : ");
-
- for(k=0; k < 8; k++ ) {
- if (cci.pcci_ld_hints & 0x1)
- seq_printf(m, "[%s]", cache_ld_hints[k]);
- cci.pcci_ld_hints >>=1;
- }
- seq_printf(m,
- "\n\tAlias boundary : %d byte(s)\n"
- "\tTag LSB : %d\n"
- "\tTag MSB : %d\n",
- 1<<cci.pcci_alias_boundary, cci.pcci_tag_lsb,
- cci.pcci_tag_msb);
-
- /* when unified, data(j=2) is enough */
- if (cci.pcci_unified)
- break;
- }
- }
- return 0;
-}
-
-
-static int vm_info(struct seq_file *m)
-{
- u64 tr_pages =0, vw_pages=0, tc_pages;
- u64 attrib;
- pal_vm_info_1_u_t vm_info_1;
- pal_vm_info_2_u_t vm_info_2;
- pal_tc_info_u_t tc_info;
- ia64_ptce_info_t ptce;
- const char *sep;
- int i, j;
- long status;
-
- if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) {
- printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
- } else {
-
- seq_printf(m,
- "Physical Address Space : %d bits\n"
- "Virtual Address Space : %d bits\n"
- "Protection Key Registers(PKR) : %d\n"
- "Implemented bits in PKR.key : %d\n"
- "Hash Tag ID : 0x%x\n"
- "Size of RR.rid : %d\n"
- "Max Purges : ",
- vm_info_1.pal_vm_info_1_s.phys_add_size,
- vm_info_2.pal_vm_info_2_s.impl_va_msb+1,
- vm_info_1.pal_vm_info_1_s.max_pkr+1,
- vm_info_1.pal_vm_info_1_s.key_size,
- vm_info_1.pal_vm_info_1_s.hash_tag_id,
- vm_info_2.pal_vm_info_2_s.rid_size);
- if (vm_info_2.pal_vm_info_2_s.max_purges == PAL_MAX_PURGES)
- seq_puts(m, "unlimited\n");
- else
- seq_printf(m, "%d\n",
- vm_info_2.pal_vm_info_2_s.max_purges ?
- vm_info_2.pal_vm_info_2_s.max_purges : 1);
- }
-
- if (ia64_pal_mem_attrib(&attrib) == 0) {
- seq_puts(m, "Supported memory attributes : ");
- sep = "";
- for (i = 0; i < 8; i++) {
- if (attrib & (1 << i)) {
- seq_printf(m, "%s%s", sep, mem_attrib[i]);
- sep = ", ";
- }
- }
- seq_putc(m, '\n');
- }
-
- if ((status = ia64_pal_vm_page_size(&tr_pages, &vw_pages)) !=0) {
- printk(KERN_ERR "ia64_pal_vm_page_size=%ld\n", status);
- } else {
-
- seq_printf(m,
- "\nTLB walker : %simplemented\n"
- "Number of DTR : %d\n"
- "Number of ITR : %d\n"
- "TLB insertable page sizes : ",
- vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
- vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
- vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
-
- bitvector_process(m, tr_pages);
-
- seq_puts(m, "\nTLB purgeable page sizes : ");
-
- bitvector_process(m, vw_pages);
- }
-
- if ((status = ia64_get_ptce(&ptce)) != 0) {
- printk(KERN_ERR "ia64_get_ptce=%ld\n", status);
- } else {
- seq_printf(m,
- "\nPurge base address : 0x%016lx\n"
- "Purge outer loop count : %d\n"
- "Purge inner loop count : %d\n"
- "Purge outer loop stride : %d\n"
- "Purge inner loop stride : %d\n",
- ptce.base, ptce.count[0], ptce.count[1],
- ptce.stride[0], ptce.stride[1]);
-
- seq_printf(m,
- "TC Levels : %d\n"
- "Unique TC(s) : %d\n",
- vm_info_1.pal_vm_info_1_s.num_tc_levels,
- vm_info_1.pal_vm_info_1_s.max_unique_tcs);
-
- for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {
- for (j=2; j>0 ; j--) {
- tc_pages = 0; /* just in case */
-
- /* even without unification, some levels may not be present */
- if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0)
- continue;
-
- seq_printf(m,
- "\n%s Translation Cache Level %d:\n"
- "\tHash sets : %d\n"
- "\tAssociativity : %d\n"
- "\tNumber of entries : %d\n"
- "\tFlags : ",
- cache_types[j+tc_info.tc_unified], i+1,
- tc_info.tc_num_sets,
- tc_info.tc_associativity,
- tc_info.tc_num_entries);
-
- if (tc_info.tc_pf)
- seq_puts(m, "PreferredPageSizeOptimized ");
- if (tc_info.tc_unified)
- seq_puts(m, "Unified ");
- if (tc_info.tc_reduce_tr)
- seq_puts(m, "TCReduction");
-
- seq_puts(m, "\n\tSupported page sizes: ");
-
- bitvector_process(m, tc_pages);
-
- /* when unified date (j=2) is enough */
- if (tc_info.tc_unified)
- break;
- }
- }
- }
-
- seq_putc(m, '\n');
- return 0;
-}
-
-
-static int register_info(struct seq_file *m)
-{
- u64 reg_info[2];
- u64 info;
- unsigned long phys_stacked;
- pal_hints_u_t hints;
- unsigned long iregs, dregs;
- static const char * const info_type[] = {
- "Implemented AR(s)",
- "AR(s) with read side-effects",
- "Implemented CR(s)",
- "CR(s) with read side-effects",
- };
-
- for(info=0; info < 4; info++) {
- if (ia64_pal_register_info(info, &reg_info[0], &reg_info[1]) != 0)
- return 0;
- seq_printf(m, "%-32s : ", info_type[info]);
- bitregister_process(m, reg_info, 128);
- seq_putc(m, '\n');
- }
-
- if (ia64_pal_rse_info(&phys_stacked, &hints) == 0)
- seq_printf(m,
- "RSE stacked physical registers : %ld\n"
- "RSE load/store hints : %ld (%s)\n",
- phys_stacked, hints.ph_data,
- hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");
-
- if (ia64_pal_debug_info(&iregs, &dregs))
- return 0;
-
- seq_printf(m,
- "Instruction debug register pairs : %ld\n"
- "Data debug register pairs : %ld\n", iregs, dregs);
-
- return 0;
-}
-
-static const char *const proc_features_0[]={ /* Feature set 0 */
- NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
- NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
- NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
- NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,
- "Unimplemented instruction address fault",
- "INIT, PMI, and LINT pins",
- "Simple unimplemented instr addresses",
- "Variable P-state performance",
- "Virtual machine features implemented",
- "XIP,XPSR,XFS implemented",
- "XR1-XR3 implemented",
- "Disable dynamic predicate prediction",
- "Disable processor physical number",
- "Disable dynamic data cache prefetch",
- "Disable dynamic inst cache prefetch",
- "Disable dynamic branch prediction",
- NULL, NULL, NULL, NULL,
- "Disable P-states",
- "Enable MCA on Data Poisoning",
- "Enable vmsw instruction",
- "Enable extern environmental notification",
- "Disable BINIT on processor time-out",
- "Disable dynamic power management (DPM)",
- "Disable coherency",
- "Disable cache",
- "Enable CMCI promotion",
- "Enable MCA to BINIT promotion",
- "Enable MCA promotion",
- "Enable BERR promotion"
-};
-
-static const char *const proc_features_16[]={ /* Feature set 16 */
- "Disable ETM",
- "Enable ETM",
- "Enable MCA on half-way timer",
- "Enable snoop WC",
- NULL,
- "Enable Fast Deferral",
- "Disable MCA on memory aliasing",
- "Enable RSB",
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- "DP system processor",
- "Low Voltage",
- "HT supported",
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL
-};
-
-static const char *const *const proc_features[]={
- proc_features_0,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- proc_features_16,
- NULL, NULL, NULL, NULL,
-};
-
-static void feature_set_info(struct seq_file *m, u64 avail, u64 status, u64 control,
- unsigned long set)
-{
- const char *const *vf, *const *v;
- int i;
-
- vf = v = proc_features[set];
- for(i=0; i < 64; i++, avail >>=1, status >>=1, control >>=1) {
-
- if (!(control)) /* No remaining bits set */
- break;
- if (!(avail & 0x1)) /* Print only bits that are available */
- continue;
- if (vf)
- v = vf + i;
- if ( v && *v ) {
- seq_printf(m, "%-40s : %s %s\n", *v,
- avail & 0x1 ? (status & 0x1 ?
- "On " : "Off"): "",
- avail & 0x1 ? (control & 0x1 ?
- "Ctrl" : "NoCtrl"): "");
- } else {
- seq_printf(m, "Feature set %2ld bit %2d\t\t\t"
- " : %s %s\n",
- set, i,
- avail & 0x1 ? (status & 0x1 ?
- "On " : "Off"): "",
- avail & 0x1 ? (control & 0x1 ?
- "Ctrl" : "NoCtrl"): "");
- }
- }
-}
-
-static int processor_info(struct seq_file *m)
-{
- u64 avail=1, status=1, control=1, feature_set=0;
- s64 ret;
-
- do {
- ret = ia64_pal_proc_get_features(&avail, &status, &control,
- feature_set);
- if (ret < 0)
- return 0;
-
- if (ret == 1) {
- feature_set++;
- continue;
- }
-
- feature_set_info(m, avail, status, control, feature_set);
- feature_set++;
- } while(1);
-
- return 0;
-}
-
-static const char *const bus_features[]={
- NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
- NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
- NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
- NULL,NULL,
- "Request Bus Parking",
- "Bus Lock Mask",
- "Enable Half Transfer",
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- "Enable Cache Line Repl. Shared",
- "Enable Cache Line Repl. Exclusive",
- "Disable Transaction Queuing",
- "Disable Response Error Checking",
- "Disable Bus Error Checking",
- "Disable Bus Requester Internal Error Signalling",
- "Disable Bus Requester Error Signalling",
- "Disable Bus Initialization Event Checking",
- "Disable Bus Initialization Event Signalling",
- "Disable Bus Address Error Checking",
- "Disable Bus Address Error Signalling",
- "Disable Bus Data Error Checking"
-};
-
-
-static int bus_info(struct seq_file *m)
-{
- const char *const *v = bus_features;
- pal_bus_features_u_t av, st, ct;
- u64 avail, status, control;
- int i;
- s64 ret;
-
- if ((ret=ia64_pal_bus_get_features(&av, &st, &ct)) != 0)
- return 0;
-
- avail = av.pal_bus_features_val;
- status = st.pal_bus_features_val;
- control = ct.pal_bus_features_val;
-
- for(i=0; i < 64; i++, v++, avail >>=1, status >>=1, control >>=1) {
- if ( ! *v )
- continue;
- seq_printf(m, "%-48s : %s%s %s\n", *v,
- avail & 0x1 ? "" : "NotImpl",
- avail & 0x1 ? (status & 0x1 ? "On" : "Off"): "",
- avail & 0x1 ? (control & 0x1 ? "Ctrl" : "NoCtrl"): "");
- }
- return 0;
-}
-
-static int version_info(struct seq_file *m)
-{
- pal_version_u_t min_ver, cur_ver;
-
- if (ia64_pal_version(&min_ver, &cur_ver) != 0)
- return 0;
-
- seq_printf(m,
- "PAL_vendor : 0x%02x (min=0x%02x)\n"
- "PAL_A : %02x.%02x (min=%02x.%02x)\n"
- "PAL_B : %02x.%02x (min=%02x.%02x)\n",
- cur_ver.pal_version_s.pv_pal_vendor,
- min_ver.pal_version_s.pv_pal_vendor,
- cur_ver.pal_version_s.pv_pal_a_model,
- cur_ver.pal_version_s.pv_pal_a_rev,
- min_ver.pal_version_s.pv_pal_a_model,
- min_ver.pal_version_s.pv_pal_a_rev,
- cur_ver.pal_version_s.pv_pal_b_model,
- cur_ver.pal_version_s.pv_pal_b_rev,
- min_ver.pal_version_s.pv_pal_b_model,
- min_ver.pal_version_s.pv_pal_b_rev);
- return 0;
-}
-
-static int frequency_info(struct seq_file *m)
-{
- struct pal_freq_ratio proc, itc, bus;
- unsigned long base;
-
- if (ia64_pal_freq_base(&base) == -1)
- seq_puts(m, "Output clock : not implemented\n");
- else
- seq_printf(m, "Output clock : %ld ticks/s\n", base);
-
- if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0;
-
- seq_printf(m,
- "Processor/Clock ratio : %d/%d\n"
- "Bus/Clock ratio : %d/%d\n"
- "ITC/Clock ratio : %d/%d\n",
- proc.num, proc.den, bus.num, bus.den, itc.num, itc.den);
- return 0;
-}
-
-static int tr_info(struct seq_file *m)
-{
- long status;
- pal_tr_valid_u_t tr_valid;
- u64 tr_buffer[4];
- pal_vm_info_1_u_t vm_info_1;
- pal_vm_info_2_u_t vm_info_2;
- unsigned long i, j;
- unsigned long max[3], pgm;
- struct ifa_reg {
- unsigned long valid:1;
- unsigned long ig:11;
- unsigned long vpn:52;
- } *ifa_reg;
- struct itir_reg {
- unsigned long rv1:2;
- unsigned long ps:6;
- unsigned long key:24;
- unsigned long rv2:32;
- } *itir_reg;
- struct gr_reg {
- unsigned long p:1;
- unsigned long rv1:1;
- unsigned long ma:3;
- unsigned long a:1;
- unsigned long d:1;
- unsigned long pl:2;
- unsigned long ar:3;
- unsigned long ppn:38;
- unsigned long rv2:2;
- unsigned long ed:1;
- unsigned long ig:11;
- } *gr_reg;
- struct rid_reg {
- unsigned long ig1:1;
- unsigned long rv1:1;
- unsigned long ig2:6;
- unsigned long rid:24;
- unsigned long rv2:32;
- } *rid_reg;
-
- if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) {
- printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
- return 0;
- }
- max[0] = vm_info_1.pal_vm_info_1_s.max_itr_entry+1;
- max[1] = vm_info_1.pal_vm_info_1_s.max_dtr_entry+1;
-
- for (i=0; i < 2; i++ ) {
- for (j=0; j < max[i]; j++) {
-
- status = ia64_pal_tr_read(j, i, tr_buffer, &tr_valid);
- if (status != 0) {
- printk(KERN_ERR "palinfo: pal call failed on tr[%lu:%lu]=%ld\n",
- i, j, status);
- continue;
- }
-
- ifa_reg = (struct ifa_reg *)&tr_buffer[2];
-
- if (ifa_reg->valid == 0)
- continue;
-
- gr_reg = (struct gr_reg *)tr_buffer;
- itir_reg = (struct itir_reg *)&tr_buffer[1];
- rid_reg = (struct rid_reg *)&tr_buffer[3];
-
- pgm = -1 << (itir_reg->ps - 12);
- seq_printf(m,
- "%cTR%lu: av=%d pv=%d dv=%d mv=%d\n"
- "\tppn : 0x%lx\n"
- "\tvpn : 0x%lx\n"
- "\tps : ",
- "ID"[i], j,
- tr_valid.pal_tr_valid_s.access_rights_valid,
- tr_valid.pal_tr_valid_s.priv_level_valid,
- tr_valid.pal_tr_valid_s.dirty_bit_valid,
- tr_valid.pal_tr_valid_s.mem_attr_valid,
- (gr_reg->ppn & pgm)<< 12, (ifa_reg->vpn & pgm)<< 12);
-
- bitvector_process(m, 1<< itir_reg->ps);
-
- seq_printf(m,
- "\n\tpl : %d\n"
- "\tar : %d\n"
- "\trid : %x\n"
- "\tp : %d\n"
- "\tma : %d\n"
- "\td : %d\n",
- gr_reg->pl, gr_reg->ar, rid_reg->rid, gr_reg->p, gr_reg->ma,
- gr_reg->d);
- }
- }
- return 0;
-}
-
-
-
-/*
- * List {name,function} pairs for every entry in /proc/palinfo/cpu*
- */
-static const palinfo_entry_t palinfo_entries[]={
- { "version_info", version_info, },
- { "vm_info", vm_info, },
- { "cache_info", cache_info, },
- { "power_info", power_info, },
- { "register_info", register_info, },
- { "processor_info", processor_info, },
- { "frequency_info", frequency_info, },
- { "bus_info", bus_info },
- { "tr_info", tr_info, }
-};
-
-#define NR_PALINFO_ENTRIES (int) ARRAY_SIZE(palinfo_entries)
-
-static struct proc_dir_entry *palinfo_dir;
-
-/*
- * This data structure is used to pass which cpu,function is being requested
- * It must fit in a 64bit quantity to be passed to the proc callback routine
- *
- * In SMP mode, when we get a request for another CPU, we must call that
- * other CPU using IPI and wait for the result before returning.
- */
-typedef union {
- u64 value;
- struct {
- unsigned req_cpu: 32; /* for which CPU this info is */
- unsigned func_id: 32; /* which function is requested */
- } pal_func_cpu;
-} pal_func_cpu_u_t;
-
-#define req_cpu pal_func_cpu.req_cpu
-#define func_id pal_func_cpu.func_id
-
-#ifdef CONFIG_SMP
-
-/*
- * used to hold information about final function to call
- */
-typedef struct {
- palinfo_func_t func; /* pointer to function to call */
- struct seq_file *m; /* buffer to store results */
- int ret; /* return value from call */
-} palinfo_smp_data_t;
-
-
-/*
- * this function does the actual final call and he called
- * from the smp code, i.e., this is the palinfo callback routine
- */
-static void
-palinfo_smp_call(void *info)
-{
- palinfo_smp_data_t *data = (palinfo_smp_data_t *)info;
- data->ret = (*data->func)(data->m);
-}
-
-/*
- * function called to trigger the IPI, we need to access a remote CPU
- * Return:
- * 0 : error or nothing to output
- * otherwise how many bytes in the "page" buffer were written
- */
-static
-int palinfo_handle_smp(struct seq_file *m, pal_func_cpu_u_t *f)
-{
- palinfo_smp_data_t ptr;
- int ret;
-
- ptr.func = palinfo_entries[f->func_id].proc_read;
- ptr.m = m;
- ptr.ret = 0; /* just in case */
-
-
- /* will send IPI to other CPU and wait for completion of remote call */
- if ((ret=smp_call_function_single(f->req_cpu, palinfo_smp_call, &ptr, 1))) {
- printk(KERN_ERR "palinfo: remote CPU call from %d to %d on function %d: "
- "error %d\n", smp_processor_id(), f->req_cpu, f->func_id, ret);
- return 0;
- }
- return ptr.ret;
-}
-#else /* ! CONFIG_SMP */
-static
-int palinfo_handle_smp(struct seq_file *m, pal_func_cpu_u_t *f)
-{
- printk(KERN_ERR "palinfo: should not be called with non SMP kernel\n");
- return 0;
-}
-#endif /* CONFIG_SMP */
-
-/*
- * Entry point routine: all calls go through this function
- */
-static int proc_palinfo_show(struct seq_file *m, void *v)
-{
- pal_func_cpu_u_t *f = (pal_func_cpu_u_t *)&m->private;
-
- /*
- * in SMP mode, we may need to call another CPU to get correct
- * information. PAL, by definition, is processor specific
- */
- if (f->req_cpu == get_cpu())
- (*palinfo_entries[f->func_id].proc_read)(m);
- else
- palinfo_handle_smp(m, f);
-
- put_cpu();
- return 0;
-}
-
-static int palinfo_add_proc(unsigned int cpu)
-{
- pal_func_cpu_u_t f;
- struct proc_dir_entry *cpu_dir;
- int j;
- char cpustr[3+4+1]; /* cpu numbers are up to 4095 on itanic */
- sprintf(cpustr, "cpu%d", cpu);
-
- cpu_dir = proc_mkdir(cpustr, palinfo_dir);
- if (!cpu_dir)
- return -EINVAL;
-
- f.req_cpu = cpu;
-
- for (j=0; j < NR_PALINFO_ENTRIES; j++) {
- f.func_id = j;
- proc_create_single_data(palinfo_entries[j].name, 0, cpu_dir,
- proc_palinfo_show, (void *)f.value);
- }
- return 0;
-}
-
-static int palinfo_del_proc(unsigned int hcpu)
-{
- char cpustr[3+4+1]; /* cpu numbers are up to 4095 on itanic */
-
- sprintf(cpustr, "cpu%d", hcpu);
- remove_proc_subtree(cpustr, palinfo_dir);
- return 0;
-}
-
-static enum cpuhp_state hp_online;
-
-static int __init palinfo_init(void)
-{
- int i = 0;
-
- printk(KERN_INFO "PAL Information Facility v%s\n", PALINFO_VERSION);
- palinfo_dir = proc_mkdir("pal", NULL);
- if (!palinfo_dir)
- return -ENOMEM;
-
- i = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/palinfo:online",
- palinfo_add_proc, palinfo_del_proc);
- if (i < 0) {
- remove_proc_subtree("pal", NULL);
- return i;
- }
- hp_online = i;
- return 0;
-}
-
-static void __exit palinfo_exit(void)
-{
- cpuhp_remove_state(hp_online);
- remove_proc_subtree("pal", NULL);
-}
-
-module_init(palinfo_init);
-module_exit(palinfo_exit);
diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c
deleted file mode 100644
index 7f21a8c57ed7..000000000000
--- a/arch/ia64/kernel/patch.c
+++ /dev/null
@@ -1,237 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Instruction-patching support.
- *
- * Copyright (C) 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#include <linux/init.h>
-#include <linux/string.h>
-
-#include <asm/patch.h>
-#include <asm/processor.h>
-#include <asm/sections.h>
-#include <asm/unistd.h>
-
-/*
- * This was adapted from code written by Tony Luck:
- *
- * The 64-bit value in a "movl reg=value" is scattered between the two words of the bundle
- * like this:
- *
- * 6 6 5 4 3 2 1
- * 3210987654321098765432109876543210987654321098765432109876543210
- * ABBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCDEEEEEFFFFFFFFFGGGGGGG
- *
- * CCCCCCCCCCCCCCCCCCxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- * xxxxAFFFFFFFFFEEEEEDxGGGGGGGxxxxxxxxxxxxxBBBBBBBBBBBBBBBBBBBBBBB
- */
-static u64
-get_imm64 (u64 insn_addr)
-{
- u64 *p = (u64 *) (insn_addr & -16); /* mask out slot number */
-
- return ( (p[1] & 0x0800000000000000UL) << 4) | /*A*/
- ((p[1] & 0x00000000007fffffUL) << 40) | /*B*/
- ((p[0] & 0xffffc00000000000UL) >> 24) | /*C*/
- ((p[1] & 0x0000100000000000UL) >> 23) | /*D*/
- ((p[1] & 0x0003e00000000000UL) >> 29) | /*E*/
- ((p[1] & 0x07fc000000000000UL) >> 43) | /*F*/
- ((p[1] & 0x000007f000000000UL) >> 36); /*G*/
-}
-
-/* Patch instruction with "val" where "mask" has 1 bits. */
-void
-ia64_patch (u64 insn_addr, u64 mask, u64 val)
-{
- u64 m0, m1, v0, v1, b0, b1, *b = (u64 *) (insn_addr & -16);
-# define insn_mask ((1UL << 41) - 1)
- unsigned long shift;
-
- b0 = b[0]; b1 = b[1];
- shift = 5 + 41 * (insn_addr % 16); /* 5 bits of template, then 3 x 41-bit instructions */
- if (shift >= 64) {
- m1 = mask << (shift - 64);
- v1 = val << (shift - 64);
- } else {
- m0 = mask << shift; m1 = mask >> (64 - shift);
- v0 = val << shift; v1 = val >> (64 - shift);
- b[0] = (b0 & ~m0) | (v0 & m0);
- }
- b[1] = (b1 & ~m1) | (v1 & m1);
-}
-
-void
-ia64_patch_imm64 (u64 insn_addr, u64 val)
-{
- /* The assembler may generate offset pointing to either slot 1
- or slot 2 for a long (2-slot) instruction, occupying slots 1
- and 2. */
- insn_addr &= -16UL;
- ia64_patch(insn_addr + 2,
- 0x01fffefe000UL, ( ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */
- | ((val & 0x0000000000200000UL) << 0) /* bit 21 -> 21 */
- | ((val & 0x00000000001f0000UL) << 6) /* bit 16 -> 22 */
- | ((val & 0x000000000000ff80UL) << 20) /* bit 7 -> 27 */
- | ((val & 0x000000000000007fUL) << 13) /* bit 0 -> 13 */));
- ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22);
-}
-
-void
-ia64_patch_imm60 (u64 insn_addr, u64 val)
-{
- /* The assembler may generate offset pointing to either slot 1
- or slot 2 for a long (2-slot) instruction, occupying slots 1
- and 2. */
- insn_addr &= -16UL;
- ia64_patch(insn_addr + 2,
- 0x011ffffe000UL, ( ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */
- | ((val & 0x00000000000fffffUL) << 13) /* bit 0 -> 13 */));
- ia64_patch(insn_addr + 1, 0x1fffffffffcUL, val >> 18);
-}
-
-/*
- * We need sometimes to load the physical address of a kernel
- * object. Often we can convert the virtual address to physical
- * at execution time, but sometimes (either for performance reasons
- * or during error recovery) we cannot to this. Patch the marked
- * bundles to load the physical address.
- */
-void __init
-ia64_patch_vtop (unsigned long start, unsigned long end)
-{
- s32 *offp = (s32 *) start;
- u64 ip;
-
- while (offp < (s32 *) end) {
- ip = (u64) offp + *offp;
-
- /* replace virtual address with corresponding physical address: */
- ia64_patch_imm64(ip, ia64_tpa(get_imm64(ip)));
- ia64_fc((void *) ip);
- ++offp;
- }
- ia64_sync_i();
- ia64_srlz_i();
-}
-
-/*
- * Disable the RSE workaround by turning the conditional branch
- * that we tagged in each place the workaround was used into an
- * unconditional branch.
- */
-void __init
-ia64_patch_rse (unsigned long start, unsigned long end)
-{
- s32 *offp = (s32 *) start;
- u64 ip, *b;
-
- while (offp < (s32 *) end) {
- ip = (u64) offp + *offp;
-
- b = (u64 *)(ip & -16);
- b[1] &= ~0xf800000L;
- ia64_fc((void *) ip);
- ++offp;
- }
- ia64_sync_i();
- ia64_srlz_i();
-}
-
-void __init
-ia64_patch_mckinley_e9 (unsigned long start, unsigned long end)
-{
- static int first_time = 1;
- int need_workaround;
- s32 *offp = (s32 *) start;
- u64 *wp;
-
- need_workaround = (local_cpu_data->family == 0x1f && local_cpu_data->model == 0);
-
- if (first_time) {
- first_time = 0;
- if (need_workaround)
- printk(KERN_INFO "Leaving McKinley Errata 9 workaround enabled\n");
- }
- if (need_workaround)
- return;
-
- while (offp < (s32 *) end) {
- wp = (u64 *) ia64_imva((char *) offp + *offp);
- wp[0] = 0x0000000100000011UL; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */
- wp[1] = 0x0084006880000200UL;
- wp[2] = 0x0000000100000000UL; /* nop.m 0; nop.i 0; nop.i 0 */
- wp[3] = 0x0004000000000200UL;
- ia64_fc(wp); ia64_fc(wp + 2);
- ++offp;
- }
- ia64_sync_i();
- ia64_srlz_i();
-}
-
-static void __init
-patch_fsyscall_table (unsigned long start, unsigned long end)
-{
- extern unsigned long fsyscall_table[NR_syscalls];
- s32 *offp = (s32 *) start;
- u64 ip;
-
- while (offp < (s32 *) end) {
- ip = (u64) ia64_imva((char *) offp + *offp);
- ia64_patch_imm64(ip, (u64) fsyscall_table);
- ia64_fc((void *) ip);
- ++offp;
- }
- ia64_sync_i();
- ia64_srlz_i();
-}
-
-static void __init
-patch_brl_fsys_bubble_down (unsigned long start, unsigned long end)
-{
- extern char fsys_bubble_down[];
- s32 *offp = (s32 *) start;
- u64 ip;
-
- while (offp < (s32 *) end) {
- ip = (u64) offp + *offp;
- ia64_patch_imm60((u64) ia64_imva((void *) ip),
- (u64) (fsys_bubble_down - (ip & -16)) / 16);
- ia64_fc((void *) ip);
- ++offp;
- }
- ia64_sync_i();
- ia64_srlz_i();
-}
-
-void __init
-ia64_patch_gate (void)
-{
-# define START(name) ((unsigned long) __start_gate_##name##_patchlist)
-# define END(name) ((unsigned long)__end_gate_##name##_patchlist)
-
- patch_fsyscall_table(START(fsyscall), END(fsyscall));
- patch_brl_fsys_bubble_down(START(brl_fsys_bubble_down), END(brl_fsys_bubble_down));
- ia64_patch_vtop(START(vtop), END(vtop));
- ia64_patch_mckinley_e9(START(mckinley_e9), END(mckinley_e9));
-}
-
-void ia64_patch_phys_stack_reg(unsigned long val)
-{
- s32 * offp = (s32 *) __start___phys_stack_reg_patchlist;
- s32 * end = (s32 *) __end___phys_stack_reg_patchlist;
- u64 ip, mask, imm;
-
- /* see instruction format A4: adds r1 = imm13, r3 */
- mask = (0x3fUL << 27) | (0x7f << 13);
- imm = (((val >> 7) & 0x3f) << 27) | (val & 0x7f) << 13;
-
- while (offp < end) {
- ip = (u64) offp + *offp;
- ia64_patch(ip, mask, imm);
- ia64_fc((void *)ip);
- ++offp;
- }
- ia64_sync_i();
- ia64_srlz_i();
-}
diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c
deleted file mode 100644
index c90221733c6b..000000000000
--- a/arch/ia64/kernel/pci-dma.c
+++ /dev/null
@@ -1,33 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Dynamic DMA mapping support.
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <linux/module.h>
-#include <linux/dmar.h>
-#include <asm/iommu.h>
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <asm/page.h>
-
-int no_iommu __read_mostly;
-#ifdef CONFIG_IOMMU_DEBUG
-int force_iommu __read_mostly = 1;
-#else
-int force_iommu __read_mostly;
-#endif
-
-static int __init pci_iommu_init(void)
-{
- if (iommu_detected)
- intel_iommu_init();
-
- return 0;
-}
-
-/* Must execute after PCI subsystem */
-fs_initcall(pci_iommu_init);
diff --git a/arch/ia64/kernel/perfmon_itanium.h b/arch/ia64/kernel/perfmon_itanium.h
deleted file mode 100644
index dbd04028aafa..000000000000
--- a/arch/ia64/kernel/perfmon_itanium.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * This file contains the Itanium PMU register description tables
- * and pmc checker.
- *
- * Copyright (C) 2002-2003 Hewlett Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- */
-static int pfm_ita_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
-
-static pfm_reg_desc_t pfm_ita_pmc_desc[PMU_MAX_PMCS]={
-/* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc2 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc3 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc4 */ { PFM_REG_COUNTING, 6, 0x0UL, -1UL, NULL, NULL, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc5 */ { PFM_REG_COUNTING, 6, 0x0UL, -1UL, NULL, NULL, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc6 */ { PFM_REG_COUNTING, 6, 0x0UL, -1UL, NULL, NULL, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc7 */ { PFM_REG_COUNTING, 6, 0x0UL, -1UL, NULL, NULL, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc8 */ { PFM_REG_CONFIG , 0, 0xf00000003ffffff8UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc9 */ { PFM_REG_CONFIG , 0, 0xf00000003ffffff8UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc10 */ { PFM_REG_MONITOR , 6, 0x0UL, -1UL, NULL, NULL, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc11 */ { PFM_REG_MONITOR , 6, 0x0000000010000000UL, -1UL, NULL, pfm_ita_pmc_check, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc12 */ { PFM_REG_MONITOR , 6, 0x0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc13 */ { PFM_REG_CONFIG , 0, 0x0003ffff00000001UL, -1UL, NULL, pfm_ita_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
- { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */
-};
-
-static pfm_reg_desc_t pfm_ita_pmd_desc[PMU_MAX_PMDS]={
-/* pmd0 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(1),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}},
-/* pmd1 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(0),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}},
-/* pmd2 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
-/* pmd3 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(2)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
-/* pmd4 */ { PFM_REG_COUNTING, 0, 0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}},
-/* pmd5 */ { PFM_REG_COUNTING, 0, 0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}},
-/* pmd6 */ { PFM_REG_COUNTING, 0, 0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}},
-/* pmd7 */ { PFM_REG_COUNTING, 0, 0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}},
-/* pmd8 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
-/* pmd9 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
-/* pmd10 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
-/* pmd11 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
-/* pmd12 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
-/* pmd13 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
-/* pmd14 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
-/* pmd15 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
-/* pmd16 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
-/* pmd17 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(2)|RDEP(3),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
- { PFM_REG_END , 0, 0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */
-};
-
-static int
-pfm_ita_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs)
-{
- int ret;
- int is_loaded;
-
- /* sanitfy check */
- if (ctx == NULL) return -EINVAL;
-
- is_loaded = ctx->ctx_state == PFM_CTX_LOADED || ctx->ctx_state == PFM_CTX_MASKED;
-
- /*
- * we must clear the (instruction) debug registers if pmc13.ta bit is cleared
- * before they are written (fl_using_dbreg==0) to avoid picking up stale information.
- */
- if (cnum == 13 && is_loaded && ((*val & 0x1) == 0UL) && ctx->ctx_fl_using_dbreg == 0) {
-
- DPRINT(("pmc[%d]=0x%lx has active pmc13.ta cleared, clearing ibr\n", cnum, *val));
-
- /* don't mix debug with perfmon */
- if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
-
- /*
- * a count of 0 will mark the debug registers as in use and also
- * ensure that they are properly cleared.
- */
- ret = pfm_write_ibr_dbr(1, ctx, NULL, 0, regs);
- if (ret) return ret;
- }
-
- /*
- * we must clear the (data) debug registers if pmc11.pt bit is cleared
- * before they are written (fl_using_dbreg==0) to avoid picking up stale information.
- */
- if (cnum == 11 && is_loaded && ((*val >> 28)& 0x1) == 0 && ctx->ctx_fl_using_dbreg == 0) {
-
- DPRINT(("pmc[%d]=0x%lx has active pmc11.pt cleared, clearing dbr\n", cnum, *val));
-
- /* don't mix debug with perfmon */
- if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
-
- /*
- * a count of 0 will mark the debug registers as in use and also
- * ensure that they are properly cleared.
- */
- ret = pfm_write_ibr_dbr(0, ctx, NULL, 0, regs);
- if (ret) return ret;
- }
- return 0;
-}
-
-/*
- * impl_pmcs, impl_pmds are computed at runtime to minimize errors!
- */
-static pmu_config_t pmu_conf_ita={
- .pmu_name = "Itanium",
- .pmu_family = 0x7,
- .ovfl_val = (1UL << 32) - 1,
- .pmd_desc = pfm_ita_pmd_desc,
- .pmc_desc = pfm_ita_pmc_desc,
- .num_ibrs = 8,
- .num_dbrs = 8,
- .use_rr_dbregs = 1, /* debug register are use for range retrictions */
-};
-
-
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
deleted file mode 100644
index 9a5cd9fad3a9..000000000000
--- a/arch/ia64/kernel/process.c
+++ /dev/null
@@ -1,611 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Architecture-specific setup.
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * 04/11/17 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support
- *
- * 2005-10-07 Keith Owens <kaos@sgi.com>
- * Add notify_die() hooks.
- */
-#include <linux/cpu.h>
-#include <linux/pm.h>
-#include <linux/elf.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/notifier.h>
-#include <linux/personality.h>
-#include <linux/reboot.h>
-#include <linux/sched.h>
-#include <linux/sched/debug.h>
-#include <linux/sched/hotplug.h>
-#include <linux/sched/task.h>
-#include <linux/sched/task_stack.h>
-#include <linux/stddef.h>
-#include <linux/thread_info.h>
-#include <linux/unistd.h>
-#include <linux/efi.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/kdebug.h>
-#include <linux/utsname.h>
-#include <linux/resume_user_mode.h>
-#include <linux/rcupdate.h>
-
-#include <asm/cpu.h>
-#include <asm/delay.h>
-#include <asm/elf.h>
-#include <asm/irq.h>
-#include <asm/kexec.h>
-#include <asm/processor.h>
-#include <asm/sal.h>
-#include <asm/switch_to.h>
-#include <asm/tlbflush.h>
-#include <linux/uaccess.h>
-#include <asm/unwind.h>
-#include <asm/user.h>
-#include <asm/xtp.h>
-
-#include "entry.h"
-
-#include "sigframe.h"
-
-void (*ia64_mark_idle)(int);
-
-unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE;
-EXPORT_SYMBOL(boot_option_idle_override);
-void (*pm_power_off) (void);
-EXPORT_SYMBOL(pm_power_off);
-
-static void
-ia64_do_show_stack (struct unw_frame_info *info, void *arg)
-{
- unsigned long ip, sp, bsp;
- const char *loglvl = arg;
-
- printk("%s\nCall Trace:\n", loglvl);
- do {
- unw_get_ip(info, &ip);
- if (ip == 0)
- break;
-
- unw_get_sp(info, &sp);
- unw_get_bsp(info, &bsp);
- printk("%s [<%016lx>] %pS\n"
- " sp=%016lx bsp=%016lx\n",
- loglvl, ip, (void *)ip, sp, bsp);
- } while (unw_unwind(info) >= 0);
-}
-
-void
-show_stack (struct task_struct *task, unsigned long *sp, const char *loglvl)
-{
- if (!task)
- unw_init_running(ia64_do_show_stack, (void *)loglvl);
- else {
- struct unw_frame_info info;
-
- unw_init_from_blocked_task(&info, task);
- ia64_do_show_stack(&info, (void *)loglvl);
- }
-}
-
-void
-show_regs (struct pt_regs *regs)
-{
- unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
-
- print_modules();
- printk("\n");
- show_regs_print_info(KERN_DEFAULT);
- printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s (%s)\n",
- regs->cr_ipsr, regs->cr_ifs, ip, print_tainted(),
- init_utsname()->release);
- printk("ip is at %pS\n", (void *)ip);
- printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
- regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
- printk("rnat: %016lx bsps: %016lx pr : %016lx\n",
- regs->ar_rnat, regs->ar_bspstore, regs->pr);
- printk("ldrs: %016lx ccv : %016lx fpsr: %016lx\n",
- regs->loadrs, regs->ar_ccv, regs->ar_fpsr);
- printk("csd : %016lx ssd : %016lx\n", regs->ar_csd, regs->ar_ssd);
- printk("b0 : %016lx b6 : %016lx b7 : %016lx\n", regs->b0, regs->b6, regs->b7);
- printk("f6 : %05lx%016lx f7 : %05lx%016lx\n",
- regs->f6.u.bits[1], regs->f6.u.bits[0],
- regs->f7.u.bits[1], regs->f7.u.bits[0]);
- printk("f8 : %05lx%016lx f9 : %05lx%016lx\n",
- regs->f8.u.bits[1], regs->f8.u.bits[0],
- regs->f9.u.bits[1], regs->f9.u.bits[0]);
- printk("f10 : %05lx%016lx f11 : %05lx%016lx\n",
- regs->f10.u.bits[1], regs->f10.u.bits[0],
- regs->f11.u.bits[1], regs->f11.u.bits[0]);
-
- printk("r1 : %016lx r2 : %016lx r3 : %016lx\n", regs->r1, regs->r2, regs->r3);
- printk("r8 : %016lx r9 : %016lx r10 : %016lx\n", regs->r8, regs->r9, regs->r10);
- printk("r11 : %016lx r12 : %016lx r13 : %016lx\n", regs->r11, regs->r12, regs->r13);
- printk("r14 : %016lx r15 : %016lx r16 : %016lx\n", regs->r14, regs->r15, regs->r16);
- printk("r17 : %016lx r18 : %016lx r19 : %016lx\n", regs->r17, regs->r18, regs->r19);
- printk("r20 : %016lx r21 : %016lx r22 : %016lx\n", regs->r20, regs->r21, regs->r22);
- printk("r23 : %016lx r24 : %016lx r25 : %016lx\n", regs->r23, regs->r24, regs->r25);
- printk("r26 : %016lx r27 : %016lx r28 : %016lx\n", regs->r26, regs->r27, regs->r28);
- printk("r29 : %016lx r30 : %016lx r31 : %016lx\n", regs->r29, regs->r30, regs->r31);
-
- if (user_mode(regs)) {
- /* print the stacked registers */
- unsigned long val, *bsp, ndirty;
- int i, sof, is_nat = 0;
-
- sof = regs->cr_ifs & 0x7f; /* size of frame */
- ndirty = (regs->loadrs >> 19);
- bsp = ia64_rse_skip_regs((unsigned long *) regs->ar_bspstore, ndirty);
- for (i = 0; i < sof; ++i) {
- get_user(val, (unsigned long __user *) ia64_rse_skip_regs(bsp, i));
- printk("r%-3u:%c%016lx%s", 32 + i, is_nat ? '*' : ' ', val,
- ((i == sof - 1) || (i % 3) == 2) ? "\n" : " ");
- }
- } else
- show_stack(NULL, NULL, KERN_DEFAULT);
-}
-
-/* local support for deprecated console_print */
-void
-console_print(const char *s)
-{
- printk(KERN_EMERG "%s", s);
-}
-
-void
-do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall)
-{
- if (fsys_mode(current, &scr->pt)) {
- /*
- * defer signal-handling etc. until we return to
- * privilege-level 0.
- */
- if (!ia64_psr(&scr->pt)->lp)
- ia64_psr(&scr->pt)->lp = 1;
- return;
- }
-
- /* deal with pending signal delivery */
- if (test_thread_flag(TIF_SIGPENDING) ||
- test_thread_flag(TIF_NOTIFY_SIGNAL)) {
- local_irq_enable(); /* force interrupt enable */
- ia64_do_signal(scr, in_syscall);
- }
-
- if (test_thread_flag(TIF_NOTIFY_RESUME)) {
- local_irq_enable(); /* force interrupt enable */
- resume_user_mode_work(&scr->pt);
- }
-
- /* copy user rbs to kernel rbs */
- if (unlikely(test_thread_flag(TIF_RESTORE_RSE))) {
- local_irq_enable(); /* force interrupt enable */
- ia64_sync_krbs();
- }
-
- local_irq_disable(); /* force interrupt disable */
-}
-
-static int __init nohalt_setup(char * str)
-{
- cpu_idle_poll_ctrl(true);
- return 1;
-}
-__setup("nohalt", nohalt_setup);
-
-#ifdef CONFIG_HOTPLUG_CPU
-/* We don't actually take CPU down, just spin without interrupts. */
-static inline void __noreturn play_dead(void)
-{
- unsigned int this_cpu = smp_processor_id();
-
- /* Ack it */
- __this_cpu_write(cpu_state, CPU_DEAD);
-
- max_xtp();
- local_irq_disable();
- idle_task_exit();
- ia64_jump_to_sal(&sal_boot_rendez_state[this_cpu]);
- /*
- * The above is a point of no-return, the processor is
- * expected to be in SAL loop now.
- */
- BUG();
-}
-#else
-static inline void __noreturn play_dead(void)
-{
- BUG();
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
-void __noreturn arch_cpu_idle_dead(void)
-{
- play_dead();
-}
-
-void arch_cpu_idle(void)
-{
- void (*mark_idle)(int) = ia64_mark_idle;
-
-#ifdef CONFIG_SMP
- min_xtp();
-#endif
- rmb();
- if (mark_idle)
- (*mark_idle)(1);
-
- raw_safe_halt();
- raw_local_irq_disable();
-
- if (mark_idle)
- (*mark_idle)(0);
-#ifdef CONFIG_SMP
- normal_xtp();
-#endif
-}
-
-void
-ia64_save_extra (struct task_struct *task)
-{
- if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0)
- ia64_save_debug_regs(&task->thread.dbr[0]);
-}
-
-void
-ia64_load_extra (struct task_struct *task)
-{
- if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0)
- ia64_load_debug_regs(&task->thread.dbr[0]);
-}
-
-/*
- * Copy the state of an ia-64 thread.
- *
- * We get here through the following call chain:
- *
- * from user-level: from kernel:
- *
- * <clone syscall> <some kernel call frames>
- * sys_clone :
- * kernel_clone kernel_clone
- * copy_thread copy_thread
- *
- * This means that the stack layout is as follows:
- *
- * +---------------------+ (highest addr)
- * | struct pt_regs |
- * +---------------------+
- * | struct switch_stack |
- * +---------------------+
- * | |
- * | memory stack |
- * | | <-- sp (lowest addr)
- * +---------------------+
- *
- * Observe that we copy the unat values that are in pt_regs and switch_stack. Spilling an
- * integer to address X causes bit N in ar.unat to be set to the NaT bit of the register,
- * with N=(X & 0x1ff)/8. Thus, copying the unat value preserves the NaT bits ONLY if the
- * pt_regs structure in the parent is congruent to that of the child, modulo 512. Since
- * the stack is page aligned and the page size is at least 4KB, this is always the case,
- * so there is nothing to worry about.
- */
-int
-copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
-{
- unsigned long clone_flags = args->flags;
- unsigned long user_stack_base = args->stack;
- unsigned long user_stack_size = args->stack_size;
- unsigned long tls = args->tls;
- extern char ia64_ret_from_clone;
- struct switch_stack *child_stack, *stack;
- unsigned long rbs, child_rbs, rbs_size;
- struct pt_regs *child_ptregs;
- struct pt_regs *regs = current_pt_regs();
- int retval = 0;
-
- child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1;
- child_stack = (struct switch_stack *) child_ptregs - 1;
-
- rbs = (unsigned long) current + IA64_RBS_OFFSET;
- child_rbs = (unsigned long) p + IA64_RBS_OFFSET;
-
- /* copy parts of thread_struct: */
- p->thread.ksp = (unsigned long) child_stack - 16;
-
- /*
- * NOTE: The calling convention considers all floating point
- * registers in the high partition (fph) to be scratch. Since
- * the only way to get to this point is through a system call,
- * we know that the values in fph are all dead. Hence, there
- * is no need to inherit the fph state from the parent to the
- * child and all we have to do is to make sure that
- * IA64_THREAD_FPH_VALID is cleared in the child.
- *
- * XXX We could push this optimization a bit further by
- * clearing IA64_THREAD_FPH_VALID on ANY system call.
- * However, it's not clear this is worth doing. Also, it
- * would be a slight deviation from the normal Linux system
- * call behavior where scratch registers are preserved across
- * system calls (unless used by the system call itself).
- */
-# define THREAD_FLAGS_TO_CLEAR (IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID \
- | IA64_THREAD_PM_VALID)
-# define THREAD_FLAGS_TO_SET 0
- p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
- | THREAD_FLAGS_TO_SET);
-
- ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */
-
- if (unlikely(args->fn)) {
- if (unlikely(args->idle)) {
- /* fork_idle() called us */
- return 0;
- }
- memset(child_stack, 0, sizeof(*child_ptregs) + sizeof(*child_stack));
- child_stack->r4 = (unsigned long) args->fn;
- child_stack->r5 = (unsigned long) args->fn_arg;
- /*
- * Preserve PSR bits, except for bits 32-34 and 37-45,
- * which we can't read.
- */
- child_ptregs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
- /* mark as valid, empty frame */
- child_ptregs->cr_ifs = 1UL << 63;
- child_stack->ar_fpsr = child_ptregs->ar_fpsr
- = ia64_getreg(_IA64_REG_AR_FPSR);
- child_stack->pr = (1 << PRED_KERNEL_STACK);
- child_stack->ar_bspstore = child_rbs;
- child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
-
- /* stop some PSR bits from being inherited.
- * the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
- * therefore we must specify them explicitly here and not include them in
- * IA64_PSR_BITS_TO_CLEAR.
- */
- child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
- & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
-
- return 0;
- }
- stack = ((struct switch_stack *) regs) - 1;
- /* copy parent's switch_stack & pt_regs to child: */
- memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
-
- /* copy the parent's register backing store to the child: */
- rbs_size = stack->ar_bspstore - rbs;
- memcpy((void *) child_rbs, (void *) rbs, rbs_size);
- if (clone_flags & CLONE_SETTLS)
- child_ptregs->r13 = tls;
- if (user_stack_base) {
- child_ptregs->r12 = user_stack_base + user_stack_size - 16;
- child_ptregs->ar_bspstore = user_stack_base;
- child_ptregs->ar_rnat = 0;
- child_ptregs->loadrs = 0;
- }
- child_stack->ar_bspstore = child_rbs + rbs_size;
- child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
-
- /* stop some PSR bits from being inherited.
- * the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
- * therefore we must specify them explicitly here and not include them in
- * IA64_PSR_BITS_TO_CLEAR.
- */
- child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
- & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
- return retval;
-}
-
-asmlinkage long ia64_clone(unsigned long clone_flags, unsigned long stack_start,
- unsigned long stack_size, unsigned long parent_tidptr,
- unsigned long child_tidptr, unsigned long tls)
-{
- struct kernel_clone_args args = {
- .flags = (lower_32_bits(clone_flags) & ~CSIGNAL),
- .pidfd = (int __user *)parent_tidptr,
- .child_tid = (int __user *)child_tidptr,
- .parent_tid = (int __user *)parent_tidptr,
- .exit_signal = (lower_32_bits(clone_flags) & CSIGNAL),
- .stack = stack_start,
- .stack_size = stack_size,
- .tls = tls,
- };
-
- return kernel_clone(&args);
-}
-
-static void
-do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg)
-{
- unsigned long mask, sp, nat_bits = 0, ar_rnat, urbs_end, cfm;
- unsigned long ip;
- elf_greg_t *dst = arg;
- struct pt_regs *pt;
- char nat;
- int i;
-
- memset(dst, 0, sizeof(elf_gregset_t)); /* don't leak any kernel bits to user-level */
-
- if (unw_unwind_to_user(info) < 0)
- return;
-
- unw_get_sp(info, &sp);
- pt = (struct pt_regs *) (sp + 16);
-
- urbs_end = ia64_get_user_rbs_end(task, pt, &cfm);
-
- if (ia64_sync_user_rbs(task, info->sw, pt->ar_bspstore, urbs_end) < 0)
- return;
-
- ia64_peek(task, info->sw, urbs_end, (long) ia64_rse_rnat_addr((long *) urbs_end),
- &ar_rnat);
-
- /*
- * coredump format:
- * r0-r31
- * NaT bits (for r0-r31; bit N == 1 iff rN is a NaT)
- * predicate registers (p0-p63)
- * b0-b7
- * ip cfm user-mask
- * ar.rsc ar.bsp ar.bspstore ar.rnat
- * ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec
- */
-
- /* r0 is zero */
- for (i = 1, mask = (1UL << i); i < 32; ++i) {
- unw_get_gr(info, i, &dst[i], &nat);
- if (nat)
- nat_bits |= mask;
- mask <<= 1;
- }
- dst[32] = nat_bits;
- unw_get_pr(info, &dst[33]);
-
- for (i = 0; i < 8; ++i)
- unw_get_br(info, i, &dst[34 + i]);
-
- unw_get_rp(info, &ip);
- dst[42] = ip + ia64_psr(pt)->ri;
- dst[43] = cfm;
- dst[44] = pt->cr_ipsr & IA64_PSR_UM;
-
- unw_get_ar(info, UNW_AR_RSC, &dst[45]);
- /*
- * For bsp and bspstore, unw_get_ar() would return the kernel
- * addresses, but we need the user-level addresses instead:
- */
- dst[46] = urbs_end; /* note: by convention PT_AR_BSP points to the end of the urbs! */
- dst[47] = pt->ar_bspstore;
- dst[48] = ar_rnat;
- unw_get_ar(info, UNW_AR_CCV, &dst[49]);
- unw_get_ar(info, UNW_AR_UNAT, &dst[50]);
- unw_get_ar(info, UNW_AR_FPSR, &dst[51]);
- dst[52] = pt->ar_pfs; /* UNW_AR_PFS is == to pt->cr_ifs for interrupt frames */
- unw_get_ar(info, UNW_AR_LC, &dst[53]);
- unw_get_ar(info, UNW_AR_EC, &dst[54]);
- unw_get_ar(info, UNW_AR_CSD, &dst[55]);
- unw_get_ar(info, UNW_AR_SSD, &dst[56]);
-}
-
-static void
-do_copy_regs (struct unw_frame_info *info, void *arg)
-{
- do_copy_task_regs(current, info, arg);
-}
-
-void
-ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
-{
- unw_init_running(do_copy_regs, dst);
-}
-
-/*
- * Flush thread state. This is called when a thread does an execve().
- */
-void
-flush_thread (void)
-{
- /* drop floating-point and debug-register state if it exists: */
- current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
- ia64_drop_fpu(current);
-}
-
-/*
- * Clean up state associated with a thread. This is called when
- * the thread calls exit().
- */
-void
-exit_thread (struct task_struct *tsk)
-{
-
- ia64_drop_fpu(tsk);
-}
-
-unsigned long
-__get_wchan (struct task_struct *p)
-{
- struct unw_frame_info info;
- unsigned long ip;
- int count = 0;
-
- /*
- * Note: p may not be a blocked task (it could be current or
- * another process running on some other CPU. Rather than
- * trying to determine if p is really blocked, we just assume
- * it's blocked and rely on the unwind routines to fail
- * gracefully if the process wasn't really blocked after all.
- * --davidm 99/12/15
- */
- unw_init_from_blocked_task(&info, p);
- do {
- if (task_is_running(p))
- return 0;
- if (unw_unwind(&info) < 0)
- return 0;
- unw_get_ip(&info, &ip);
- if (!in_sched_functions(ip))
- return ip;
- } while (count++ < 16);
- return 0;
-}
-
-void
-cpu_halt (void)
-{
- pal_power_mgmt_info_u_t power_info[8];
- unsigned long min_power;
- int i, min_power_state;
-
- if (ia64_pal_halt_info(power_info) != 0)
- return;
-
- min_power_state = 0;
- min_power = power_info[0].pal_power_mgmt_info_s.power_consumption;
- for (i = 1; i < 8; ++i)
- if (power_info[i].pal_power_mgmt_info_s.im
- && power_info[i].pal_power_mgmt_info_s.power_consumption < min_power) {
- min_power = power_info[i].pal_power_mgmt_info_s.power_consumption;
- min_power_state = i;
- }
-
- while (1)
- ia64_pal_halt(min_power_state);
-}
-
-void machine_shutdown(void)
-{
- smp_shutdown_nonboot_cpus(reboot_cpu);
-
-#ifdef CONFIG_KEXEC
- kexec_disable_iosapic();
-#endif
-}
-
-void
-machine_restart (char *restart_cmd)
-{
- (void) notify_die(DIE_MACHINE_RESTART, restart_cmd, NULL, 0, 0, 0);
- efi_reboot(REBOOT_WARM, NULL);
-}
-
-void
-machine_halt (void)
-{
- (void) notify_die(DIE_MACHINE_HALT, "", NULL, 0, 0, 0);
- cpu_halt();
-}
-
-void
-machine_power_off (void)
-{
- do_kernel_power_off();
- machine_halt();
-}
-
-EXPORT_SYMBOL(ia64_delay_loop);
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
deleted file mode 100644
index 4c41912c550f..000000000000
--- a/arch/ia64/kernel/ptrace.c
+++ /dev/null
@@ -1,2012 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Kernel support for the ptrace() and syscall tracing interfaces.
- *
- * Copyright (C) 1999-2005 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2006 Intel Co
- * 2006-08-12 - IA64 Native Utrace implementation support added by
- * Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- *
- * Derived from the x86 and Alpha versions.
- */
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/sched/task.h>
-#include <linux/sched/task_stack.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/user.h>
-#include <linux/security.h>
-#include <linux/audit.h>
-#include <linux/signal.h>
-#include <linux/regset.h>
-#include <linux/elf.h>
-#include <linux/resume_user_mode.h>
-
-#include <asm/processor.h>
-#include <asm/ptrace_offsets.h>
-#include <asm/rse.h>
-#include <linux/uaccess.h>
-#include <asm/unwind.h>
-
-#include "entry.h"
-
-/*
- * Bits in the PSR that we allow ptrace() to change:
- * be, up, ac, mfl, mfh (the user mask; five bits total)
- * db (debug breakpoint fault; one bit)
- * id (instruction debug fault disable; one bit)
- * dd (data debug fault disable; one bit)
- * ri (restart instruction; two bits)
- * is (instruction set; one bit)
- */
-#define IPSR_MASK (IA64_PSR_UM | IA64_PSR_DB | IA64_PSR_IS \
- | IA64_PSR_ID | IA64_PSR_DD | IA64_PSR_RI)
-
-#define MASK(nbits) ((1UL << (nbits)) - 1) /* mask with NBITS bits set */
-#define PFM_MASK MASK(38)
-
-#define PTRACE_DEBUG 0
-
-#if PTRACE_DEBUG
-# define dprintk(format...) printk(format)
-# define inline
-#else
-# define dprintk(format...)
-#endif
-
-/* Return TRUE if PT was created due to kernel-entry via a system-call. */
-
-static inline int
-in_syscall (struct pt_regs *pt)
-{
- return (long) pt->cr_ifs >= 0;
-}
-
-/*
- * Collect the NaT bits for r1-r31 from scratch_unat and return a NaT
- * bitset where bit i is set iff the NaT bit of register i is set.
- */
-unsigned long
-ia64_get_scratch_nat_bits (struct pt_regs *pt, unsigned long scratch_unat)
-{
-# define GET_BITS(first, last, unat) \
- ({ \
- unsigned long bit = ia64_unat_pos(&pt->r##first); \
- unsigned long nbits = (last - first + 1); \
- unsigned long mask = MASK(nbits) << first; \
- unsigned long dist; \
- if (bit < first) \
- dist = 64 + bit - first; \
- else \
- dist = bit - first; \
- ia64_rotr(unat, dist) & mask; \
- })
- unsigned long val;
-
- /*
- * Registers that are stored consecutively in struct pt_regs
- * can be handled in parallel. If the register order in
- * struct_pt_regs changes, this code MUST be updated.
- */
- val = GET_BITS( 1, 1, scratch_unat);
- val |= GET_BITS( 2, 3, scratch_unat);
- val |= GET_BITS(12, 13, scratch_unat);
- val |= GET_BITS(14, 14, scratch_unat);
- val |= GET_BITS(15, 15, scratch_unat);
- val |= GET_BITS( 8, 11, scratch_unat);
- val |= GET_BITS(16, 31, scratch_unat);
- return val;
-
-# undef GET_BITS
-}
-
-/*
- * Set the NaT bits for the scratch registers according to NAT and
- * return the resulting unat (assuming the scratch registers are
- * stored in PT).
- */
-unsigned long
-ia64_put_scratch_nat_bits (struct pt_regs *pt, unsigned long nat)
-{
-# define PUT_BITS(first, last, nat) \
- ({ \
- unsigned long bit = ia64_unat_pos(&pt->r##first); \
- unsigned long nbits = (last - first + 1); \
- unsigned long mask = MASK(nbits) << first; \
- long dist; \
- if (bit < first) \
- dist = 64 + bit - first; \
- else \
- dist = bit - first; \
- ia64_rotl(nat & mask, dist); \
- })
- unsigned long scratch_unat;
-
- /*
- * Registers that are stored consecutively in struct pt_regs
- * can be handled in parallel. If the register order in
- * struct_pt_regs changes, this code MUST be updated.
- */
- scratch_unat = PUT_BITS( 1, 1, nat);
- scratch_unat |= PUT_BITS( 2, 3, nat);
- scratch_unat |= PUT_BITS(12, 13, nat);
- scratch_unat |= PUT_BITS(14, 14, nat);
- scratch_unat |= PUT_BITS(15, 15, nat);
- scratch_unat |= PUT_BITS( 8, 11, nat);
- scratch_unat |= PUT_BITS(16, 31, nat);
-
- return scratch_unat;
-
-# undef PUT_BITS
-}
-
-#define IA64_MLX_TEMPLATE 0x2
-#define IA64_MOVL_OPCODE 6
-
-void
-ia64_increment_ip (struct pt_regs *regs)
-{
- unsigned long w0, ri = ia64_psr(regs)->ri + 1;
-
- if (ri > 2) {
- ri = 0;
- regs->cr_iip += 16;
- } else if (ri == 2) {
- get_user(w0, (char __user *) regs->cr_iip + 0);
- if (((w0 >> 1) & 0xf) == IA64_MLX_TEMPLATE) {
- /*
- * rfi'ing to slot 2 of an MLX bundle causes
- * an illegal operation fault. We don't want
- * that to happen...
- */
- ri = 0;
- regs->cr_iip += 16;
- }
- }
- ia64_psr(regs)->ri = ri;
-}
-
-void
-ia64_decrement_ip (struct pt_regs *regs)
-{
- unsigned long w0, ri = ia64_psr(regs)->ri - 1;
-
- if (ia64_psr(regs)->ri == 0) {
- regs->cr_iip -= 16;
- ri = 2;
- get_user(w0, (char __user *) regs->cr_iip + 0);
- if (((w0 >> 1) & 0xf) == IA64_MLX_TEMPLATE) {
- /*
- * rfi'ing to slot 2 of an MLX bundle causes
- * an illegal operation fault. We don't want
- * that to happen...
- */
- ri = 1;
- }
- }
- ia64_psr(regs)->ri = ri;
-}
-
-/*
- * This routine is used to read an rnat bits that are stored on the
- * kernel backing store. Since, in general, the alignment of the user
- * and kernel are different, this is not completely trivial. In
- * essence, we need to construct the user RNAT based on up to two
- * kernel RNAT values and/or the RNAT value saved in the child's
- * pt_regs.
- *
- * user rbs
- *
- * +--------+ <-- lowest address
- * | slot62 |
- * +--------+
- * | rnat | 0x....1f8
- * +--------+
- * | slot00 | \
- * +--------+ |
- * | slot01 | > child_regs->ar_rnat
- * +--------+ |
- * | slot02 | / kernel rbs
- * +--------+ +--------+
- * <- child_regs->ar_bspstore | slot61 | <-- krbs
- * +- - - - + +--------+
- * | slot62 |
- * +- - - - + +--------+
- * | rnat |
- * +- - - - + +--------+
- * vrnat | slot00 |
- * +- - - - + +--------+
- * = =
- * +--------+
- * | slot00 | \
- * +--------+ |
- * | slot01 | > child_stack->ar_rnat
- * +--------+ |
- * | slot02 | /
- * +--------+
- * <--- child_stack->ar_bspstore
- *
- * The way to think of this code is as follows: bit 0 in the user rnat
- * corresponds to some bit N (0 <= N <= 62) in one of the kernel rnat
- * value. The kernel rnat value holding this bit is stored in
- * variable rnat0. rnat1 is loaded with the kernel rnat value that
- * form the upper bits of the user rnat value.
- *
- * Boundary cases:
- *
- * o when reading the rnat "below" the first rnat slot on the kernel
- * backing store, rnat0/rnat1 are set to 0 and the low order bits are
- * merged in from pt->ar_rnat.
- *
- * o when reading the rnat "above" the last rnat slot on the kernel
- * backing store, rnat0/rnat1 gets its value from sw->ar_rnat.
- */
-static unsigned long
-get_rnat (struct task_struct *task, struct switch_stack *sw,
- unsigned long *krbs, unsigned long *urnat_addr,
- unsigned long *urbs_end)
-{
- unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr;
- unsigned long umask = 0, mask, m;
- unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift;
- long num_regs, nbits;
- struct pt_regs *pt;
-
- pt = task_pt_regs(task);
- kbsp = (unsigned long *) sw->ar_bspstore;
- ubspstore = (unsigned long *) pt->ar_bspstore;
-
- if (urbs_end < urnat_addr)
- nbits = ia64_rse_num_regs(urnat_addr - 63, urbs_end);
- else
- nbits = 63;
- mask = MASK(nbits);
- /*
- * First, figure out which bit number slot 0 in user-land maps
- * to in the kernel rnat. Do this by figuring out how many
- * register slots we're beyond the user's backingstore and
- * then computing the equivalent address in kernel space.
- */
- num_regs = ia64_rse_num_regs(ubspstore, urnat_addr + 1);
- slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs);
- shift = ia64_rse_slot_num(slot0_kaddr);
- rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr);
- rnat0_kaddr = rnat1_kaddr - 64;
-
- if (ubspstore + 63 > urnat_addr) {
- /* some bits need to be merged in from pt->ar_rnat */
- umask = MASK(ia64_rse_slot_num(ubspstore)) & mask;
- urnat = (pt->ar_rnat & umask);
- mask &= ~umask;
- if (!mask)
- return urnat;
- }
-
- m = mask << shift;
- if (rnat0_kaddr >= kbsp)
- rnat0 = sw->ar_rnat;
- else if (rnat0_kaddr > krbs)
- rnat0 = *rnat0_kaddr;
- urnat |= (rnat0 & m) >> shift;
-
- m = mask >> (63 - shift);
- if (rnat1_kaddr >= kbsp)
- rnat1 = sw->ar_rnat;
- else if (rnat1_kaddr > krbs)
- rnat1 = *rnat1_kaddr;
- urnat |= (rnat1 & m) << (63 - shift);
- return urnat;
-}
-
-/*
- * The reverse of get_rnat.
- */
-static void
-put_rnat (struct task_struct *task, struct switch_stack *sw,
- unsigned long *krbs, unsigned long *urnat_addr, unsigned long urnat,
- unsigned long *urbs_end)
-{
- unsigned long rnat0 = 0, rnat1 = 0, *slot0_kaddr, umask = 0, mask, m;
- unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift;
- long num_regs, nbits;
- struct pt_regs *pt;
- unsigned long cfm, *urbs_kargs;
-
- pt = task_pt_regs(task);
- kbsp = (unsigned long *) sw->ar_bspstore;
- ubspstore = (unsigned long *) pt->ar_bspstore;
-
- urbs_kargs = urbs_end;
- if (in_syscall(pt)) {
- /*
- * If entered via syscall, don't allow user to set rnat bits
- * for syscall args.
- */
- cfm = pt->cr_ifs;
- urbs_kargs = ia64_rse_skip_regs(urbs_end, -(cfm & 0x7f));
- }
-
- if (urbs_kargs >= urnat_addr)
- nbits = 63;
- else {
- if ((urnat_addr - 63) >= urbs_kargs)
- return;
- nbits = ia64_rse_num_regs(urnat_addr - 63, urbs_kargs);
- }
- mask = MASK(nbits);
-
- /*
- * First, figure out which bit number slot 0 in user-land maps
- * to in the kernel rnat. Do this by figuring out how many
- * register slots we're beyond the user's backingstore and
- * then computing the equivalent address in kernel space.
- */
- num_regs = ia64_rse_num_regs(ubspstore, urnat_addr + 1);
- slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs);
- shift = ia64_rse_slot_num(slot0_kaddr);
- rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr);
- rnat0_kaddr = rnat1_kaddr - 64;
-
- if (ubspstore + 63 > urnat_addr) {
- /* some bits need to be place in pt->ar_rnat: */
- umask = MASK(ia64_rse_slot_num(ubspstore)) & mask;
- pt->ar_rnat = (pt->ar_rnat & ~umask) | (urnat & umask);
- mask &= ~umask;
- if (!mask)
- return;
- }
- /*
- * Note: Section 11.1 of the EAS guarantees that bit 63 of an
- * rnat slot is ignored. so we don't have to clear it here.
- */
- rnat0 = (urnat << shift);
- m = mask << shift;
- if (rnat0_kaddr >= kbsp)
- sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat0 & m);
- else if (rnat0_kaddr > krbs)
- *rnat0_kaddr = ((*rnat0_kaddr & ~m) | (rnat0 & m));
-
- rnat1 = (urnat >> (63 - shift));
- m = mask >> (63 - shift);
- if (rnat1_kaddr >= kbsp)
- sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat1 & m);
- else if (rnat1_kaddr > krbs)
- *rnat1_kaddr = ((*rnat1_kaddr & ~m) | (rnat1 & m));
-}
-
-static inline int
-on_kernel_rbs (unsigned long addr, unsigned long bspstore,
- unsigned long urbs_end)
-{
- unsigned long *rnat_addr = ia64_rse_rnat_addr((unsigned long *)
- urbs_end);
- return (addr >= bspstore && addr <= (unsigned long) rnat_addr);
-}
-
-/*
- * Read a word from the user-level backing store of task CHILD. ADDR
- * is the user-level address to read the word from, VAL a pointer to
- * the return value, and USER_BSP gives the end of the user-level
- * backing store (i.e., it's the address that would be in ar.bsp after
- * the user executed a "cover" instruction).
- *
- * This routine takes care of accessing the kernel register backing
- * store for those registers that got spilled there. It also takes
- * care of calculating the appropriate RNaT collection words.
- */
-long
-ia64_peek (struct task_struct *child, struct switch_stack *child_stack,
- unsigned long user_rbs_end, unsigned long addr, long *val)
-{
- unsigned long *bspstore, *krbs, regnum, *laddr, *urbs_end, *rnat_addr;
- struct pt_regs *child_regs;
- size_t copied;
- long ret;
-
- urbs_end = (long *) user_rbs_end;
- laddr = (unsigned long *) addr;
- child_regs = task_pt_regs(child);
- bspstore = (unsigned long *) child_regs->ar_bspstore;
- krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
- if (on_kernel_rbs(addr, (unsigned long) bspstore,
- (unsigned long) urbs_end))
- {
- /*
- * Attempt to read the RBS in an area that's actually
- * on the kernel RBS => read the corresponding bits in
- * the kernel RBS.
- */
- rnat_addr = ia64_rse_rnat_addr(laddr);
- ret = get_rnat(child, child_stack, krbs, rnat_addr, urbs_end);
-
- if (laddr == rnat_addr) {
- /* return NaT collection word itself */
- *val = ret;
- return 0;
- }
-
- if (((1UL << ia64_rse_slot_num(laddr)) & ret) != 0) {
- /*
- * It is implementation dependent whether the
- * data portion of a NaT value gets saved on a
- * st8.spill or RSE spill (e.g., see EAS 2.6,
- * 4.4.4.6 Register Spill and Fill). To get
- * consistent behavior across all possible
- * IA-64 implementations, we return zero in
- * this case.
- */
- *val = 0;
- return 0;
- }
-
- if (laddr < urbs_end) {
- /*
- * The desired word is on the kernel RBS and
- * is not a NaT.
- */
- regnum = ia64_rse_num_regs(bspstore, laddr);
- *val = *ia64_rse_skip_regs(krbs, regnum);
- return 0;
- }
- }
- copied = access_process_vm(child, addr, &ret, sizeof(ret), FOLL_FORCE);
- if (copied != sizeof(ret))
- return -EIO;
- *val = ret;
- return 0;
-}
-
-long
-ia64_poke (struct task_struct *child, struct switch_stack *child_stack,
- unsigned long user_rbs_end, unsigned long addr, long val)
-{
- unsigned long *bspstore, *krbs, regnum, *laddr;
- unsigned long *urbs_end = (long *) user_rbs_end;
- struct pt_regs *child_regs;
-
- laddr = (unsigned long *) addr;
- child_regs = task_pt_regs(child);
- bspstore = (unsigned long *) child_regs->ar_bspstore;
- krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
- if (on_kernel_rbs(addr, (unsigned long) bspstore,
- (unsigned long) urbs_end))
- {
- /*
- * Attempt to write the RBS in an area that's actually
- * on the kernel RBS => write the corresponding bits
- * in the kernel RBS.
- */
- if (ia64_rse_is_rnat_slot(laddr))
- put_rnat(child, child_stack, krbs, laddr, val,
- urbs_end);
- else {
- if (laddr < urbs_end) {
- regnum = ia64_rse_num_regs(bspstore, laddr);
- *ia64_rse_skip_regs(krbs, regnum) = val;
- }
- }
- } else if (access_process_vm(child, addr, &val, sizeof(val),
- FOLL_FORCE | FOLL_WRITE)
- != sizeof(val))
- return -EIO;
- return 0;
-}
-
-/*
- * Calculate the address of the end of the user-level register backing
- * store. This is the address that would have been stored in ar.bsp
- * if the user had executed a "cover" instruction right before
- * entering the kernel. If CFMP is not NULL, it is used to return the
- * "current frame mask" that was active at the time the kernel was
- * entered.
- */
-unsigned long
-ia64_get_user_rbs_end (struct task_struct *child, struct pt_regs *pt,
- unsigned long *cfmp)
-{
- unsigned long *krbs, *bspstore, cfm = pt->cr_ifs;
- long ndirty;
-
- krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
- bspstore = (unsigned long *) pt->ar_bspstore;
- ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19));
-
- if (in_syscall(pt))
- ndirty += (cfm & 0x7f);
- else
- cfm &= ~(1UL << 63); /* clear valid bit */
-
- if (cfmp)
- *cfmp = cfm;
- return (unsigned long) ia64_rse_skip_regs(bspstore, ndirty);
-}
-
-/*
- * Synchronize (i.e, write) the RSE backing store living in kernel
- * space to the VM of the CHILD task. SW and PT are the pointers to
- * the switch_stack and pt_regs structures, respectively.
- * USER_RBS_END is the user-level address at which the backing store
- * ends.
- */
-long
-ia64_sync_user_rbs (struct task_struct *child, struct switch_stack *sw,
- unsigned long user_rbs_start, unsigned long user_rbs_end)
-{
- unsigned long addr, val;
- long ret;
-
- /* now copy word for word from kernel rbs to user rbs: */
- for (addr = user_rbs_start; addr < user_rbs_end; addr += 8) {
- ret = ia64_peek(child, sw, user_rbs_end, addr, &val);
- if (ret < 0)
- return ret;
- if (access_process_vm(child, addr, &val, sizeof(val),
- FOLL_FORCE | FOLL_WRITE)
- != sizeof(val))
- return -EIO;
- }
- return 0;
-}
-
-static long
-ia64_sync_kernel_rbs (struct task_struct *child, struct switch_stack *sw,
- unsigned long user_rbs_start, unsigned long user_rbs_end)
-{
- unsigned long addr, val;
- long ret;
-
- /* now copy word for word from user rbs to kernel rbs: */
- for (addr = user_rbs_start; addr < user_rbs_end; addr += 8) {
- if (access_process_vm(child, addr, &val, sizeof(val),
- FOLL_FORCE)
- != sizeof(val))
- return -EIO;
-
- ret = ia64_poke(child, sw, user_rbs_end, addr, val);
- if (ret < 0)
- return ret;
- }
- return 0;
-}
-
-typedef long (*syncfunc_t)(struct task_struct *, struct switch_stack *,
- unsigned long, unsigned long);
-
-static void do_sync_rbs(struct unw_frame_info *info, void *arg)
-{
- struct pt_regs *pt;
- unsigned long urbs_end;
- syncfunc_t fn = arg;
-
- if (unw_unwind_to_user(info) < 0)
- return;
- pt = task_pt_regs(info->task);
- urbs_end = ia64_get_user_rbs_end(info->task, pt, NULL);
-
- fn(info->task, info->sw, pt->ar_bspstore, urbs_end);
-}
-
-/*
- * when a thread is stopped (ptraced), debugger might change thread's user
- * stack (change memory directly), and we must avoid the RSE stored in kernel
- * to override user stack (user space's RSE is newer than kernel's in the
- * case). To workaround the issue, we copy kernel RSE to user RSE before the
- * task is stopped, so user RSE has updated data. we then copy user RSE to
- * kernel after the task is resummed from traced stop and kernel will use the
- * newer RSE to return to user. TIF_RESTORE_RSE is the flag to indicate we need
- * synchronize user RSE to kernel.
- */
-void ia64_ptrace_stop(void)
-{
- if (test_and_set_tsk_thread_flag(current, TIF_RESTORE_RSE))
- return;
- set_notify_resume(current);
- unw_init_running(do_sync_rbs, ia64_sync_user_rbs);
-}
-
-/*
- * This is called to read back the register backing store.
- */
-void ia64_sync_krbs(void)
-{
- clear_tsk_thread_flag(current, TIF_RESTORE_RSE);
-
- unw_init_running(do_sync_rbs, ia64_sync_kernel_rbs);
-}
-
-/*
- * Write f32-f127 back to task->thread.fph if it has been modified.
- */
-inline void
-ia64_flush_fph (struct task_struct *task)
-{
- struct ia64_psr *psr = ia64_psr(task_pt_regs(task));
-
- /*
- * Prevent migrating this task while
- * we're fiddling with the FPU state
- */
- preempt_disable();
- if (ia64_is_local_fpu_owner(task) && psr->mfh) {
- psr->mfh = 0;
- task->thread.flags |= IA64_THREAD_FPH_VALID;
- ia64_save_fpu(&task->thread.fph[0]);
- }
- preempt_enable();
-}
-
-/*
- * Sync the fph state of the task so that it can be manipulated
- * through thread.fph. If necessary, f32-f127 are written back to
- * thread.fph or, if the fph state hasn't been used before, thread.fph
- * is cleared to zeroes. Also, access to f32-f127 is disabled to
- * ensure that the task picks up the state from thread.fph when it
- * executes again.
- */
-void
-ia64_sync_fph (struct task_struct *task)
-{
- struct ia64_psr *psr = ia64_psr(task_pt_regs(task));
-
- ia64_flush_fph(task);
- if (!(task->thread.flags & IA64_THREAD_FPH_VALID)) {
- task->thread.flags |= IA64_THREAD_FPH_VALID;
- memset(&task->thread.fph, 0, sizeof(task->thread.fph));
- }
- ia64_drop_fpu(task);
- psr->dfh = 1;
-}
-
-/*
- * Change the machine-state of CHILD such that it will return via the normal
- * kernel exit-path, rather than the syscall-exit path.
- */
-static void
-convert_to_non_syscall (struct task_struct *child, struct pt_regs *pt,
- unsigned long cfm)
-{
- struct unw_frame_info info, prev_info;
- unsigned long ip, sp, pr;
-
- unw_init_from_blocked_task(&info, child);
- while (1) {
- prev_info = info;
- if (unw_unwind(&info) < 0)
- return;
-
- unw_get_sp(&info, &sp);
- if ((long)((unsigned long)child + IA64_STK_OFFSET - sp)
- < IA64_PT_REGS_SIZE) {
- dprintk("ptrace.%s: ran off the top of the kernel "
- "stack\n", __func__);
- return;
- }
- if (unw_get_pr (&prev_info, &pr) < 0) {
- unw_get_rp(&prev_info, &ip);
- dprintk("ptrace.%s: failed to read "
- "predicate register (ip=0x%lx)\n",
- __func__, ip);
- return;
- }
- if (unw_is_intr_frame(&info)
- && (pr & (1UL << PRED_USER_STACK)))
- break;
- }
-
- /*
- * Note: at the time of this call, the target task is blocked
- * in notify_resume_user() and by clearling PRED_LEAVE_SYSCALL
- * (aka, "pLvSys") we redirect execution from
- * .work_pending_syscall_end to .work_processed_kernel.
- */
- unw_get_pr(&prev_info, &pr);
- pr &= ~((1UL << PRED_SYSCALL) | (1UL << PRED_LEAVE_SYSCALL));
- pr |= (1UL << PRED_NON_SYSCALL);
- unw_set_pr(&prev_info, pr);
-
- pt->cr_ifs = (1UL << 63) | cfm;
- /*
- * Clear the memory that is NOT written on syscall-entry to
- * ensure we do not leak kernel-state to user when execution
- * resumes.
- */
- pt->r2 = 0;
- pt->r3 = 0;
- pt->r14 = 0;
- memset(&pt->r16, 0, 16*8); /* clear r16-r31 */
- memset(&pt->f6, 0, 6*16); /* clear f6-f11 */
- pt->b7 = 0;
- pt->ar_ccv = 0;
- pt->ar_csd = 0;
- pt->ar_ssd = 0;
-}
-
-static int
-access_nat_bits (struct task_struct *child, struct pt_regs *pt,
- struct unw_frame_info *info,
- unsigned long *data, int write_access)
-{
- unsigned long regnum, nat_bits, scratch_unat, dummy = 0;
- char nat = 0;
-
- if (write_access) {
- nat_bits = *data;
- scratch_unat = ia64_put_scratch_nat_bits(pt, nat_bits);
- if (unw_set_ar(info, UNW_AR_UNAT, scratch_unat) < 0) {
- dprintk("ptrace: failed to set ar.unat\n");
- return -1;
- }
- for (regnum = 4; regnum <= 7; ++regnum) {
- unw_get_gr(info, regnum, &dummy, &nat);
- unw_set_gr(info, regnum, dummy,
- (nat_bits >> regnum) & 1);
- }
- } else {
- if (unw_get_ar(info, UNW_AR_UNAT, &scratch_unat) < 0) {
- dprintk("ptrace: failed to read ar.unat\n");
- return -1;
- }
- nat_bits = ia64_get_scratch_nat_bits(pt, scratch_unat);
- for (regnum = 4; regnum <= 7; ++regnum) {
- unw_get_gr(info, regnum, &dummy, &nat);
- nat_bits |= (nat != 0) << regnum;
- }
- *data = nat_bits;
- }
- return 0;
-}
-
-static int
-access_elf_reg(struct task_struct *target, struct unw_frame_info *info,
- unsigned long addr, unsigned long *data, int write_access);
-
-static long
-ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
-{
- unsigned long psr, ec, lc, rnat, bsp, cfm, nat_bits, val;
- struct unw_frame_info info;
- struct ia64_fpreg fpval;
- struct switch_stack *sw;
- struct pt_regs *pt;
- long ret, retval = 0;
- char nat = 0;
- int i;
-
- if (!access_ok(ppr, sizeof(struct pt_all_user_regs)))
- return -EIO;
-
- pt = task_pt_regs(child);
- sw = (struct switch_stack *) (child->thread.ksp + 16);
- unw_init_from_blocked_task(&info, child);
- if (unw_unwind_to_user(&info) < 0) {
- return -EIO;
- }
-
- if (((unsigned long) ppr & 0x7) != 0) {
- dprintk("ptrace:unaligned register address %p\n", ppr);
- return -EIO;
- }
-
- if (access_elf_reg(child, &info, ELF_CR_IPSR_OFFSET, &psr, 0) < 0 ||
- access_elf_reg(child, &info, ELF_AR_EC_OFFSET, &ec, 0) < 0 ||
- access_elf_reg(child, &info, ELF_AR_LC_OFFSET, &lc, 0) < 0 ||
- access_elf_reg(child, &info, ELF_AR_RNAT_OFFSET, &rnat, 0) < 0 ||
- access_elf_reg(child, &info, ELF_AR_BSP_OFFSET, &bsp, 0) < 0 ||
- access_elf_reg(child, &info, ELF_CFM_OFFSET, &cfm, 0) < 0 ||
- access_elf_reg(child, &info, ELF_NAT_OFFSET, &nat_bits, 0) < 0)
- return -EIO;
-
- /* control regs */
-
- retval |= __put_user(pt->cr_iip, &ppr->cr_iip);
- retval |= __put_user(psr, &ppr->cr_ipsr);
-
- /* app regs */
-
- retval |= __put_user(pt->ar_pfs, &ppr->ar[PT_AUR_PFS]);
- retval |= __put_user(pt->ar_rsc, &ppr->ar[PT_AUR_RSC]);
- retval |= __put_user(pt->ar_bspstore, &ppr->ar[PT_AUR_BSPSTORE]);
- retval |= __put_user(pt->ar_unat, &ppr->ar[PT_AUR_UNAT]);
- retval |= __put_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]);
- retval |= __put_user(pt->ar_fpsr, &ppr->ar[PT_AUR_FPSR]);
-
- retval |= __put_user(ec, &ppr->ar[PT_AUR_EC]);
- retval |= __put_user(lc, &ppr->ar[PT_AUR_LC]);
- retval |= __put_user(rnat, &ppr->ar[PT_AUR_RNAT]);
- retval |= __put_user(bsp, &ppr->ar[PT_AUR_BSP]);
- retval |= __put_user(cfm, &ppr->cfm);
-
- /* gr1-gr3 */
-
- retval |= __copy_to_user(&ppr->gr[1], &pt->r1, sizeof(long));
- retval |= __copy_to_user(&ppr->gr[2], &pt->r2, sizeof(long) *2);
-
- /* gr4-gr7 */
-
- for (i = 4; i < 8; i++) {
- if (unw_access_gr(&info, i, &val, &nat, 0) < 0)
- return -EIO;
- retval |= __put_user(val, &ppr->gr[i]);
- }
-
- /* gr8-gr11 */
-
- retval |= __copy_to_user(&ppr->gr[8], &pt->r8, sizeof(long) * 4);
-
- /* gr12-gr15 */
-
- retval |= __copy_to_user(&ppr->gr[12], &pt->r12, sizeof(long) * 2);
- retval |= __copy_to_user(&ppr->gr[14], &pt->r14, sizeof(long));
- retval |= __copy_to_user(&ppr->gr[15], &pt->r15, sizeof(long));
-
- /* gr16-gr31 */
-
- retval |= __copy_to_user(&ppr->gr[16], &pt->r16, sizeof(long) * 16);
-
- /* b0 */
-
- retval |= __put_user(pt->b0, &ppr->br[0]);
-
- /* b1-b5 */
-
- for (i = 1; i < 6; i++) {
- if (unw_access_br(&info, i, &val, 0) < 0)
- return -EIO;
- __put_user(val, &ppr->br[i]);
- }
-
- /* b6-b7 */
-
- retval |= __put_user(pt->b6, &ppr->br[6]);
- retval |= __put_user(pt->b7, &ppr->br[7]);
-
- /* fr2-fr5 */
-
- for (i = 2; i < 6; i++) {
- if (unw_get_fr(&info, i, &fpval) < 0)
- return -EIO;
- retval |= __copy_to_user(&ppr->fr[i], &fpval, sizeof (fpval));
- }
-
- /* fr6-fr11 */
-
- retval |= __copy_to_user(&ppr->fr[6], &pt->f6,
- sizeof(struct ia64_fpreg) * 6);
-
- /* fp scratch regs(12-15) */
-
- retval |= __copy_to_user(&ppr->fr[12], &sw->f12,
- sizeof(struct ia64_fpreg) * 4);
-
- /* fr16-fr31 */
-
- for (i = 16; i < 32; i++) {
- if (unw_get_fr(&info, i, &fpval) < 0)
- return -EIO;
- retval |= __copy_to_user(&ppr->fr[i], &fpval, sizeof (fpval));
- }
-
- /* fph */
-
- ia64_flush_fph(child);
- retval |= __copy_to_user(&ppr->fr[32], &child->thread.fph,
- sizeof(ppr->fr[32]) * 96);
-
- /* preds */
-
- retval |= __put_user(pt->pr, &ppr->pr);
-
- /* nat bits */
-
- retval |= __put_user(nat_bits, &ppr->nat);
-
- ret = retval ? -EIO : 0;
- return ret;
-}
-
-static long
-ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
-{
- unsigned long psr, rsc, ec, lc, rnat, bsp, cfm, nat_bits, val = 0;
- struct unw_frame_info info;
- struct switch_stack *sw;
- struct ia64_fpreg fpval;
- struct pt_regs *pt;
- long retval = 0;
- int i;
-
- memset(&fpval, 0, sizeof(fpval));
-
- if (!access_ok(ppr, sizeof(struct pt_all_user_regs)))
- return -EIO;
-
- pt = task_pt_regs(child);
- sw = (struct switch_stack *) (child->thread.ksp + 16);
- unw_init_from_blocked_task(&info, child);
- if (unw_unwind_to_user(&info) < 0) {
- return -EIO;
- }
-
- if (((unsigned long) ppr & 0x7) != 0) {
- dprintk("ptrace:unaligned register address %p\n", ppr);
- return -EIO;
- }
-
- /* control regs */
-
- retval |= __get_user(pt->cr_iip, &ppr->cr_iip);
- retval |= __get_user(psr, &ppr->cr_ipsr);
-
- /* app regs */
-
- retval |= __get_user(pt->ar_pfs, &ppr->ar[PT_AUR_PFS]);
- retval |= __get_user(rsc, &ppr->ar[PT_AUR_RSC]);
- retval |= __get_user(pt->ar_bspstore, &ppr->ar[PT_AUR_BSPSTORE]);
- retval |= __get_user(pt->ar_unat, &ppr->ar[PT_AUR_UNAT]);
- retval |= __get_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]);
- retval |= __get_user(pt->ar_fpsr, &ppr->ar[PT_AUR_FPSR]);
-
- retval |= __get_user(ec, &ppr->ar[PT_AUR_EC]);
- retval |= __get_user(lc, &ppr->ar[PT_AUR_LC]);
- retval |= __get_user(rnat, &ppr->ar[PT_AUR_RNAT]);
- retval |= __get_user(bsp, &ppr->ar[PT_AUR_BSP]);
- retval |= __get_user(cfm, &ppr->cfm);
-
- /* gr1-gr3 */
-
- retval |= __copy_from_user(&pt->r1, &ppr->gr[1], sizeof(long));
- retval |= __copy_from_user(&pt->r2, &ppr->gr[2], sizeof(long) * 2);
-
- /* gr4-gr7 */
-
- for (i = 4; i < 8; i++) {
- retval |= __get_user(val, &ppr->gr[i]);
- /* NaT bit will be set via PT_NAT_BITS: */
- if (unw_set_gr(&info, i, val, 0) < 0)
- return -EIO;
- }
-
- /* gr8-gr11 */
-
- retval |= __copy_from_user(&pt->r8, &ppr->gr[8], sizeof(long) * 4);
-
- /* gr12-gr15 */
-
- retval |= __copy_from_user(&pt->r12, &ppr->gr[12], sizeof(long) * 2);
- retval |= __copy_from_user(&pt->r14, &ppr->gr[14], sizeof(long));
- retval |= __copy_from_user(&pt->r15, &ppr->gr[15], sizeof(long));
-
- /* gr16-gr31 */
-
- retval |= __copy_from_user(&pt->r16, &ppr->gr[16], sizeof(long) * 16);
-
- /* b0 */
-
- retval |= __get_user(pt->b0, &ppr->br[0]);
-
- /* b1-b5 */
-
- for (i = 1; i < 6; i++) {
- retval |= __get_user(val, &ppr->br[i]);
- unw_set_br(&info, i, val);
- }
-
- /* b6-b7 */
-
- retval |= __get_user(pt->b6, &ppr->br[6]);
- retval |= __get_user(pt->b7, &ppr->br[7]);
-
- /* fr2-fr5 */
-
- for (i = 2; i < 6; i++) {
- retval |= __copy_from_user(&fpval, &ppr->fr[i], sizeof(fpval));
- if (unw_set_fr(&info, i, fpval) < 0)
- return -EIO;
- }
-
- /* fr6-fr11 */
-
- retval |= __copy_from_user(&pt->f6, &ppr->fr[6],
- sizeof(ppr->fr[6]) * 6);
-
- /* fp scratch regs(12-15) */
-
- retval |= __copy_from_user(&sw->f12, &ppr->fr[12],
- sizeof(ppr->fr[12]) * 4);
-
- /* fr16-fr31 */
-
- for (i = 16; i < 32; i++) {
- retval |= __copy_from_user(&fpval, &ppr->fr[i],
- sizeof(fpval));
- if (unw_set_fr(&info, i, fpval) < 0)
- return -EIO;
- }
-
- /* fph */
-
- ia64_sync_fph(child);
- retval |= __copy_from_user(&child->thread.fph, &ppr->fr[32],
- sizeof(ppr->fr[32]) * 96);
-
- /* preds */
-
- retval |= __get_user(pt->pr, &ppr->pr);
-
- /* nat bits */
-
- retval |= __get_user(nat_bits, &ppr->nat);
-
- retval |= access_elf_reg(child, &info, ELF_CR_IPSR_OFFSET, &psr, 1);
- retval |= access_elf_reg(child, &info, ELF_AR_RSC_OFFSET, &rsc, 1);
- retval |= access_elf_reg(child, &info, ELF_AR_EC_OFFSET, &ec, 1);
- retval |= access_elf_reg(child, &info, ELF_AR_LC_OFFSET, &lc, 1);
- retval |= access_elf_reg(child, &info, ELF_AR_RNAT_OFFSET, &rnat, 1);
- retval |= access_elf_reg(child, &info, ELF_AR_BSP_OFFSET, &bsp, 1);
- retval |= access_elf_reg(child, &info, ELF_CFM_OFFSET, &cfm, 1);
- retval |= access_elf_reg(child, &info, ELF_NAT_OFFSET, &nat_bits, 1);
-
- return retval ? -EIO : 0;
-}
-
-void
-user_enable_single_step (struct task_struct *child)
-{
- struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child));
-
- set_tsk_thread_flag(child, TIF_SINGLESTEP);
- child_psr->ss = 1;
-}
-
-void
-user_enable_block_step (struct task_struct *child)
-{
- struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child));
-
- set_tsk_thread_flag(child, TIF_SINGLESTEP);
- child_psr->tb = 1;
-}
-
-void
-user_disable_single_step (struct task_struct *child)
-{
- struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child));
-
- /* make sure the single step/taken-branch trap bits are not set: */
- clear_tsk_thread_flag(child, TIF_SINGLESTEP);
- child_psr->ss = 0;
- child_psr->tb = 0;
-}
-
-/*
- * Called by kernel/ptrace.c when detaching..
- *
- * Make sure the single step bit is not set.
- */
-void
-ptrace_disable (struct task_struct *child)
-{
- user_disable_single_step(child);
-}
-
-static int
-access_uarea (struct task_struct *child, unsigned long addr,
- unsigned long *data, int write_access);
-
-long
-arch_ptrace (struct task_struct *child, long request,
- unsigned long addr, unsigned long data)
-{
- switch (request) {
- case PTRACE_PEEKTEXT:
- case PTRACE_PEEKDATA:
- /* read word at location addr */
- if (ptrace_access_vm(child, addr, &data, sizeof(data),
- FOLL_FORCE)
- != sizeof(data))
- return -EIO;
- /* ensure return value is not mistaken for error code */
- force_successful_syscall_return();
- return data;
-
- /* PTRACE_POKETEXT and PTRACE_POKEDATA is handled
- * by the generic ptrace_request().
- */
-
- case PTRACE_PEEKUSR:
- /* read the word at addr in the USER area */
- if (access_uarea(child, addr, &data, 0) < 0)
- return -EIO;
- /* ensure return value is not mistaken for error code */
- force_successful_syscall_return();
- return data;
-
- case PTRACE_POKEUSR:
- /* write the word at addr in the USER area */
- if (access_uarea(child, addr, &data, 1) < 0)
- return -EIO;
- return 0;
-
- case PTRACE_OLD_GETSIGINFO:
- /* for backwards-compatibility */
- return ptrace_request(child, PTRACE_GETSIGINFO, addr, data);
-
- case PTRACE_OLD_SETSIGINFO:
- /* for backwards-compatibility */
- return ptrace_request(child, PTRACE_SETSIGINFO, addr, data);
-
- case PTRACE_GETREGS:
- return ptrace_getregs(child,
- (struct pt_all_user_regs __user *) data);
-
- case PTRACE_SETREGS:
- return ptrace_setregs(child,
- (struct pt_all_user_regs __user *) data);
-
- default:
- return ptrace_request(child, request, addr, data);
- }
-}
-
-
-/* "asmlinkage" so the input arguments are preserved... */
-
-asmlinkage long
-syscall_trace_enter (long arg0, long arg1, long arg2, long arg3,
- long arg4, long arg5, long arg6, long arg7,
- struct pt_regs regs)
-{
- if (test_thread_flag(TIF_SYSCALL_TRACE))
- if (ptrace_report_syscall_entry(&regs))
- return -ENOSYS;
-
- /* copy user rbs to kernel rbs */
- if (test_thread_flag(TIF_RESTORE_RSE))
- ia64_sync_krbs();
-
-
- audit_syscall_entry(regs.r15, arg0, arg1, arg2, arg3);
-
- return 0;
-}
-
-/* "asmlinkage" so the input arguments are preserved... */
-
-asmlinkage void
-syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
- long arg4, long arg5, long arg6, long arg7,
- struct pt_regs regs)
-{
- int step;
-
- audit_syscall_exit(&regs);
-
- step = test_thread_flag(TIF_SINGLESTEP);
- if (step || test_thread_flag(TIF_SYSCALL_TRACE))
- ptrace_report_syscall_exit(&regs, step);
-
- /* copy user rbs to kernel rbs */
- if (test_thread_flag(TIF_RESTORE_RSE))
- ia64_sync_krbs();
-}
-
-/* Utrace implementation starts here */
-struct regset_get {
- void *kbuf;
- void __user *ubuf;
-};
-
-struct regset_set {
- const void *kbuf;
- const void __user *ubuf;
-};
-
-struct regset_getset {
- struct task_struct *target;
- const struct user_regset *regset;
- union {
- struct regset_get get;
- struct regset_set set;
- } u;
- unsigned int pos;
- unsigned int count;
- int ret;
-};
-
-static const ptrdiff_t pt_offsets[32] =
-{
-#define R(n) offsetof(struct pt_regs, r##n)
- [0] = -1, R(1), R(2), R(3),
- [4] = -1, [5] = -1, [6] = -1, [7] = -1,
- R(8), R(9), R(10), R(11), R(12), R(13), R(14), R(15),
- R(16), R(17), R(18), R(19), R(20), R(21), R(22), R(23),
- R(24), R(25), R(26), R(27), R(28), R(29), R(30), R(31),
-#undef R
-};
-
-static int
-access_elf_gpreg(struct task_struct *target, struct unw_frame_info *info,
- unsigned long addr, unsigned long *data, int write_access)
-{
- struct pt_regs *pt = task_pt_regs(target);
- unsigned reg = addr / sizeof(unsigned long);
- ptrdiff_t d = pt_offsets[reg];
-
- if (d >= 0) {
- unsigned long *ptr = (void *)pt + d;
- if (write_access)
- *ptr = *data;
- else
- *data = *ptr;
- return 0;
- } else {
- char nat = 0;
- if (write_access) {
- /* read NaT bit first: */
- unsigned long dummy;
- int ret = unw_get_gr(info, reg, &dummy, &nat);
- if (ret < 0)
- return ret;
- }
- return unw_access_gr(info, reg, data, &nat, write_access);
- }
-}
-
-static int
-access_elf_breg(struct task_struct *target, struct unw_frame_info *info,
- unsigned long addr, unsigned long *data, int write_access)
-{
- struct pt_regs *pt;
- unsigned long *ptr = NULL;
-
- pt = task_pt_regs(target);
- switch (addr) {
- case ELF_BR_OFFSET(0):
- ptr = &pt->b0;
- break;
- case ELF_BR_OFFSET(1) ... ELF_BR_OFFSET(5):
- return unw_access_br(info, (addr - ELF_BR_OFFSET(0))/8,
- data, write_access);
- case ELF_BR_OFFSET(6):
- ptr = &pt->b6;
- break;
- case ELF_BR_OFFSET(7):
- ptr = &pt->b7;
- }
- if (write_access)
- *ptr = *data;
- else
- *data = *ptr;
- return 0;
-}
-
-static int
-access_elf_areg(struct task_struct *target, struct unw_frame_info *info,
- unsigned long addr, unsigned long *data, int write_access)
-{
- struct pt_regs *pt;
- unsigned long cfm, urbs_end;
- unsigned long *ptr = NULL;
-
- pt = task_pt_regs(target);
- if (addr >= ELF_AR_RSC_OFFSET && addr <= ELF_AR_SSD_OFFSET) {
- switch (addr) {
- case ELF_AR_RSC_OFFSET:
- /* force PL3 */
- if (write_access)
- pt->ar_rsc = *data | (3 << 2);
- else
- *data = pt->ar_rsc;
- return 0;
- case ELF_AR_BSP_OFFSET:
- /*
- * By convention, we use PT_AR_BSP to refer to
- * the end of the user-level backing store.
- * Use ia64_rse_skip_regs(PT_AR_BSP, -CFM.sof)
- * to get the real value of ar.bsp at the time
- * the kernel was entered.
- *
- * Furthermore, when changing the contents of
- * PT_AR_BSP (or PT_CFM) while the task is
- * blocked in a system call, convert the state
- * so that the non-system-call exit
- * path is used. This ensures that the proper
- * state will be picked up when resuming
- * execution. However, it *also* means that
- * once we write PT_AR_BSP/PT_CFM, it won't be
- * possible to modify the syscall arguments of
- * the pending system call any longer. This
- * shouldn't be an issue because modifying
- * PT_AR_BSP/PT_CFM generally implies that
- * we're either abandoning the pending system
- * call or that we defer it's re-execution
- * (e.g., due to GDB doing an inferior
- * function call).
- */
- urbs_end = ia64_get_user_rbs_end(target, pt, &cfm);
- if (write_access) {
- if (*data != urbs_end) {
- if (in_syscall(pt))
- convert_to_non_syscall(target,
- pt,
- cfm);
- /*
- * Simulate user-level write
- * of ar.bsp:
- */
- pt->loadrs = 0;
- pt->ar_bspstore = *data;
- }
- } else
- *data = urbs_end;
- return 0;
- case ELF_AR_BSPSTORE_OFFSET:
- ptr = &pt->ar_bspstore;
- break;
- case ELF_AR_RNAT_OFFSET:
- ptr = &pt->ar_rnat;
- break;
- case ELF_AR_CCV_OFFSET:
- ptr = &pt->ar_ccv;
- break;
- case ELF_AR_UNAT_OFFSET:
- ptr = &pt->ar_unat;
- break;
- case ELF_AR_FPSR_OFFSET:
- ptr = &pt->ar_fpsr;
- break;
- case ELF_AR_PFS_OFFSET:
- ptr = &pt->ar_pfs;
- break;
- case ELF_AR_LC_OFFSET:
- return unw_access_ar(info, UNW_AR_LC, data,
- write_access);
- case ELF_AR_EC_OFFSET:
- return unw_access_ar(info, UNW_AR_EC, data,
- write_access);
- case ELF_AR_CSD_OFFSET:
- ptr = &pt->ar_csd;
- break;
- case ELF_AR_SSD_OFFSET:
- ptr = &pt->ar_ssd;
- }
- } else if (addr >= ELF_CR_IIP_OFFSET && addr <= ELF_CR_IPSR_OFFSET) {
- switch (addr) {
- case ELF_CR_IIP_OFFSET:
- ptr = &pt->cr_iip;
- break;
- case ELF_CFM_OFFSET:
- urbs_end = ia64_get_user_rbs_end(target, pt, &cfm);
- if (write_access) {
- if (((cfm ^ *data) & PFM_MASK) != 0) {
- if (in_syscall(pt))
- convert_to_non_syscall(target,
- pt,
- cfm);
- pt->cr_ifs = ((pt->cr_ifs & ~PFM_MASK)
- | (*data & PFM_MASK));
- }
- } else
- *data = cfm;
- return 0;
- case ELF_CR_IPSR_OFFSET:
- if (write_access) {
- unsigned long tmp = *data;
- /* psr.ri==3 is a reserved value: SDM 2:25 */
- if ((tmp & IA64_PSR_RI) == IA64_PSR_RI)
- tmp &= ~IA64_PSR_RI;
- pt->cr_ipsr = ((tmp & IPSR_MASK)
- | (pt->cr_ipsr & ~IPSR_MASK));
- } else
- *data = (pt->cr_ipsr & IPSR_MASK);
- return 0;
- }
- } else if (addr == ELF_NAT_OFFSET)
- return access_nat_bits(target, pt, info,
- data, write_access);
- else if (addr == ELF_PR_OFFSET)
- ptr = &pt->pr;
- else
- return -1;
-
- if (write_access)
- *ptr = *data;
- else
- *data = *ptr;
-
- return 0;
-}
-
-static int
-access_elf_reg(struct task_struct *target, struct unw_frame_info *info,
- unsigned long addr, unsigned long *data, int write_access)
-{
- if (addr >= ELF_GR_OFFSET(1) && addr <= ELF_GR_OFFSET(31))
- return access_elf_gpreg(target, info, addr, data, write_access);
- else if (addr >= ELF_BR_OFFSET(0) && addr <= ELF_BR_OFFSET(7))
- return access_elf_breg(target, info, addr, data, write_access);
- else
- return access_elf_areg(target, info, addr, data, write_access);
-}
-
-struct regset_membuf {
- struct membuf to;
- int ret;
-};
-
-static void do_gpregs_get(struct unw_frame_info *info, void *arg)
-{
- struct regset_membuf *dst = arg;
- struct membuf to = dst->to;
- unsigned int n;
- elf_greg_t reg;
-
- if (unw_unwind_to_user(info) < 0)
- return;
-
- /*
- * coredump format:
- * r0-r31
- * NaT bits (for r0-r31; bit N == 1 iff rN is a NaT)
- * predicate registers (p0-p63)
- * b0-b7
- * ip cfm user-mask
- * ar.rsc ar.bsp ar.bspstore ar.rnat
- * ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec
- */
-
-
- /* Skip r0 */
- membuf_zero(&to, 8);
- for (n = 8; to.left && n < ELF_AR_END_OFFSET; n += 8) {
- if (access_elf_reg(info->task, info, n, &reg, 0) < 0) {
- dst->ret = -EIO;
- return;
- }
- membuf_store(&to, reg);
- }
-}
-
-static void do_gpregs_set(struct unw_frame_info *info, void *arg)
-{
- struct regset_getset *dst = arg;
-
- if (unw_unwind_to_user(info) < 0)
- return;
-
- if (!dst->count)
- return;
- /* Skip r0 */
- if (dst->pos < ELF_GR_OFFSET(1)) {
- user_regset_copyin_ignore(&dst->pos, &dst->count,
- &dst->u.set.kbuf, &dst->u.set.ubuf,
- 0, ELF_GR_OFFSET(1));
- dst->ret = 0;
- }
-
- while (dst->count && dst->pos < ELF_AR_END_OFFSET) {
- unsigned int n, from, to;
- elf_greg_t tmp[16];
-
- from = dst->pos;
- to = from + sizeof(tmp);
- if (to > ELF_AR_END_OFFSET)
- to = ELF_AR_END_OFFSET;
- /* get up to 16 values */
- dst->ret = user_regset_copyin(&dst->pos, &dst->count,
- &dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
- from, to);
- if (dst->ret)
- return;
- /* now copy them into registers */
- for (n = 0; from < dst->pos; from += sizeof(elf_greg_t), n++)
- if (access_elf_reg(dst->target, info, from,
- &tmp[n], 1) < 0) {
- dst->ret = -EIO;
- return;
- }
- }
-}
-
-#define ELF_FP_OFFSET(i) (i * sizeof(elf_fpreg_t))
-
-static void do_fpregs_get(struct unw_frame_info *info, void *arg)
-{
- struct task_struct *task = info->task;
- struct regset_membuf *dst = arg;
- struct membuf to = dst->to;
- elf_fpreg_t reg;
- unsigned int n;
-
- if (unw_unwind_to_user(info) < 0)
- return;
-
- /* Skip pos 0 and 1 */
- membuf_zero(&to, 2 * sizeof(elf_fpreg_t));
-
- /* fr2-fr31 */
- for (n = 2; to.left && n < 32; n++) {
- if (unw_get_fr(info, n, &reg)) {
- dst->ret = -EIO;
- return;
- }
- membuf_write(&to, &reg, sizeof(reg));
- }
-
- /* fph */
- if (!to.left)
- return;
-
- ia64_flush_fph(task);
- if (task->thread.flags & IA64_THREAD_FPH_VALID)
- membuf_write(&to, &task->thread.fph, 96 * sizeof(reg));
- else
- membuf_zero(&to, 96 * sizeof(reg));
-}
-
-static void do_fpregs_set(struct unw_frame_info *info, void *arg)
-{
- struct regset_getset *dst = arg;
- elf_fpreg_t fpreg, tmp[30];
- int index, start, end;
-
- if (unw_unwind_to_user(info) < 0)
- return;
-
- /* Skip pos 0 and 1 */
- if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(2)) {
- user_regset_copyin_ignore(&dst->pos, &dst->count,
- &dst->u.set.kbuf, &dst->u.set.ubuf,
- 0, ELF_FP_OFFSET(2));
- dst->ret = 0;
- if (dst->count == 0)
- return;
- }
-
- /* fr2-fr31 */
- if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(32)) {
- start = dst->pos;
- end = min(((unsigned int)ELF_FP_OFFSET(32)),
- dst->pos + dst->count);
- dst->ret = user_regset_copyin(&dst->pos, &dst->count,
- &dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
- ELF_FP_OFFSET(2), ELF_FP_OFFSET(32));
- if (dst->ret)
- return;
-
- if (start & 0xF) { /* only write high part */
- if (unw_get_fr(info, start / sizeof(elf_fpreg_t),
- &fpreg)) {
- dst->ret = -EIO;
- return;
- }
- tmp[start / sizeof(elf_fpreg_t) - 2].u.bits[0]
- = fpreg.u.bits[0];
- start &= ~0xFUL;
- }
- if (end & 0xF) { /* only write low part */
- if (unw_get_fr(info, end / sizeof(elf_fpreg_t),
- &fpreg)) {
- dst->ret = -EIO;
- return;
- }
- tmp[end / sizeof(elf_fpreg_t) - 2].u.bits[1]
- = fpreg.u.bits[1];
- end = (end + 0xF) & ~0xFUL;
- }
-
- for ( ; start < end ; start += sizeof(elf_fpreg_t)) {
- index = start / sizeof(elf_fpreg_t);
- if (unw_set_fr(info, index, tmp[index - 2])) {
- dst->ret = -EIO;
- return;
- }
- }
- if (dst->ret || dst->count == 0)
- return;
- }
-
- /* fph */
- if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(128)) {
- ia64_sync_fph(dst->target);
- dst->ret = user_regset_copyin(&dst->pos, &dst->count,
- &dst->u.set.kbuf,
- &dst->u.set.ubuf,
- &dst->target->thread.fph,
- ELF_FP_OFFSET(32), -1);
- }
-}
-
-static void
-unwind_and_call(void (*call)(struct unw_frame_info *, void *),
- struct task_struct *target, void *data)
-{
- if (target == current)
- unw_init_running(call, data);
- else {
- struct unw_frame_info info;
- memset(&info, 0, sizeof(info));
- unw_init_from_blocked_task(&info, target);
- (*call)(&info, data);
- }
-}
-
-static int
-do_regset_call(void (*call)(struct unw_frame_info *, void *),
- struct task_struct *target,
- const struct user_regset *regset,
- unsigned int pos, unsigned int count,
- const void *kbuf, const void __user *ubuf)
-{
- struct regset_getset info = { .target = target, .regset = regset,
- .pos = pos, .count = count,
- .u.set = { .kbuf = kbuf, .ubuf = ubuf },
- .ret = 0 };
- unwind_and_call(call, target, &info);
- return info.ret;
-}
-
-static int
-gpregs_get(struct task_struct *target,
- const struct user_regset *regset,
- struct membuf to)
-{
- struct regset_membuf info = {.to = to};
- unwind_and_call(do_gpregs_get, target, &info);
- return info.ret;
-}
-
-static int gpregs_set(struct task_struct *target,
- const struct user_regset *regset,
- unsigned int pos, unsigned int count,
- const void *kbuf, const void __user *ubuf)
-{
- return do_regset_call(do_gpregs_set, target, regset, pos, count,
- kbuf, ubuf);
-}
-
-static void do_gpregs_writeback(struct unw_frame_info *info, void *arg)
-{
- do_sync_rbs(info, ia64_sync_user_rbs);
-}
-
-/*
- * This is called to write back the register backing store.
- * ptrace does this before it stops, so that a tracer reading the user
- * memory after the thread stops will get the current register data.
- */
-static int
-gpregs_writeback(struct task_struct *target,
- const struct user_regset *regset,
- int now)
-{
- if (test_and_set_tsk_thread_flag(target, TIF_RESTORE_RSE))
- return 0;
- set_notify_resume(target);
- return do_regset_call(do_gpregs_writeback, target, regset, 0, 0,
- NULL, NULL);
-}
-
-static int
-fpregs_active(struct task_struct *target, const struct user_regset *regset)
-{
- return (target->thread.flags & IA64_THREAD_FPH_VALID) ? 128 : 32;
-}
-
-static int fpregs_get(struct task_struct *target,
- const struct user_regset *regset,
- struct membuf to)
-{
- struct regset_membuf info = {.to = to};
- unwind_and_call(do_fpregs_get, target, &info);
- return info.ret;
-}
-
-static int fpregs_set(struct task_struct *target,
- const struct user_regset *regset,
- unsigned int pos, unsigned int count,
- const void *kbuf, const void __user *ubuf)
-{
- return do_regset_call(do_fpregs_set, target, regset, pos, count,
- kbuf, ubuf);
-}
-
-static int
-access_uarea(struct task_struct *child, unsigned long addr,
- unsigned long *data, int write_access)
-{
- unsigned int pos = -1; /* an invalid value */
- unsigned long *ptr, regnum;
-
- if ((addr & 0x7) != 0) {
- dprintk("ptrace: unaligned register address 0x%lx\n", addr);
- return -1;
- }
- if ((addr >= PT_NAT_BITS + 8 && addr < PT_F2) ||
- (addr >= PT_R7 + 8 && addr < PT_B1) ||
- (addr >= PT_AR_LC + 8 && addr < PT_CR_IPSR) ||
- (addr >= PT_AR_SSD + 8 && addr < PT_DBR)) {
- dprintk("ptrace: rejecting access to register "
- "address 0x%lx\n", addr);
- return -1;
- }
-
- switch (addr) {
- case PT_F32 ... (PT_F127 + 15):
- pos = addr - PT_F32 + ELF_FP_OFFSET(32);
- break;
- case PT_F2 ... (PT_F5 + 15):
- pos = addr - PT_F2 + ELF_FP_OFFSET(2);
- break;
- case PT_F10 ... (PT_F31 + 15):
- pos = addr - PT_F10 + ELF_FP_OFFSET(10);
- break;
- case PT_F6 ... (PT_F9 + 15):
- pos = addr - PT_F6 + ELF_FP_OFFSET(6);
- break;
- }
-
- if (pos != -1) {
- unsigned reg = pos / sizeof(elf_fpreg_t);
- int which_half = (pos / sizeof(unsigned long)) & 1;
-
- if (reg < 32) { /* fr2-fr31 */
- struct unw_frame_info info;
- elf_fpreg_t fpreg;
-
- memset(&info, 0, sizeof(info));
- unw_init_from_blocked_task(&info, child);
- if (unw_unwind_to_user(&info) < 0)
- return 0;
-
- if (unw_get_fr(&info, reg, &fpreg))
- return -1;
- if (write_access) {
- fpreg.u.bits[which_half] = *data;
- if (unw_set_fr(&info, reg, fpreg))
- return -1;
- } else {
- *data = fpreg.u.bits[which_half];
- }
- } else { /* fph */
- elf_fpreg_t *p = &child->thread.fph[reg - 32];
- unsigned long *bits = &p->u.bits[which_half];
-
- ia64_sync_fph(child);
- if (write_access)
- *bits = *data;
- else if (child->thread.flags & IA64_THREAD_FPH_VALID)
- *data = *bits;
- else
- *data = 0;
- }
- return 0;
- }
-
- switch (addr) {
- case PT_NAT_BITS:
- pos = ELF_NAT_OFFSET;
- break;
- case PT_R4 ... PT_R7:
- pos = addr - PT_R4 + ELF_GR_OFFSET(4);
- break;
- case PT_B1 ... PT_B5:
- pos = addr - PT_B1 + ELF_BR_OFFSET(1);
- break;
- case PT_AR_EC:
- pos = ELF_AR_EC_OFFSET;
- break;
- case PT_AR_LC:
- pos = ELF_AR_LC_OFFSET;
- break;
- case PT_CR_IPSR:
- pos = ELF_CR_IPSR_OFFSET;
- break;
- case PT_CR_IIP:
- pos = ELF_CR_IIP_OFFSET;
- break;
- case PT_CFM:
- pos = ELF_CFM_OFFSET;
- break;
- case PT_AR_UNAT:
- pos = ELF_AR_UNAT_OFFSET;
- break;
- case PT_AR_PFS:
- pos = ELF_AR_PFS_OFFSET;
- break;
- case PT_AR_RSC:
- pos = ELF_AR_RSC_OFFSET;
- break;
- case PT_AR_RNAT:
- pos = ELF_AR_RNAT_OFFSET;
- break;
- case PT_AR_BSPSTORE:
- pos = ELF_AR_BSPSTORE_OFFSET;
- break;
- case PT_PR:
- pos = ELF_PR_OFFSET;
- break;
- case PT_B6:
- pos = ELF_BR_OFFSET(6);
- break;
- case PT_AR_BSP:
- pos = ELF_AR_BSP_OFFSET;
- break;
- case PT_R1 ... PT_R3:
- pos = addr - PT_R1 + ELF_GR_OFFSET(1);
- break;
- case PT_R12 ... PT_R15:
- pos = addr - PT_R12 + ELF_GR_OFFSET(12);
- break;
- case PT_R8 ... PT_R11:
- pos = addr - PT_R8 + ELF_GR_OFFSET(8);
- break;
- case PT_R16 ... PT_R31:
- pos = addr - PT_R16 + ELF_GR_OFFSET(16);
- break;
- case PT_AR_CCV:
- pos = ELF_AR_CCV_OFFSET;
- break;
- case PT_AR_FPSR:
- pos = ELF_AR_FPSR_OFFSET;
- break;
- case PT_B0:
- pos = ELF_BR_OFFSET(0);
- break;
- case PT_B7:
- pos = ELF_BR_OFFSET(7);
- break;
- case PT_AR_CSD:
- pos = ELF_AR_CSD_OFFSET;
- break;
- case PT_AR_SSD:
- pos = ELF_AR_SSD_OFFSET;
- break;
- }
-
- if (pos != -1) {
- struct unw_frame_info info;
-
- memset(&info, 0, sizeof(info));
- unw_init_from_blocked_task(&info, child);
- if (unw_unwind_to_user(&info) < 0)
- return 0;
-
- return access_elf_reg(child, &info, pos, data, write_access);
- }
-
- /* access debug registers */
- if (addr >= PT_IBR) {
- regnum = (addr - PT_IBR) >> 3;
- ptr = &child->thread.ibr[0];
- } else {
- regnum = (addr - PT_DBR) >> 3;
- ptr = &child->thread.dbr[0];
- }
-
- if (regnum >= 8) {
- dprintk("ptrace: rejecting access to register "
- "address 0x%lx\n", addr);
- return -1;
- }
-
- if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) {
- child->thread.flags |= IA64_THREAD_DBG_VALID;
- memset(child->thread.dbr, 0,
- sizeof(child->thread.dbr));
- memset(child->thread.ibr, 0,
- sizeof(child->thread.ibr));
- }
-
- ptr += regnum;
-
- if ((regnum & 1) && write_access) {
- /* don't let the user set kernel-level breakpoints: */
- *ptr = *data & ~(7UL << 56);
- return 0;
- }
- if (write_access)
- *ptr = *data;
- else
- *data = *ptr;
- return 0;
-}
-
-static const struct user_regset native_regsets[] = {
- {
- .core_note_type = NT_PRSTATUS,
- .n = ELF_NGREG,
- .size = sizeof(elf_greg_t), .align = sizeof(elf_greg_t),
- .regset_get = gpregs_get, .set = gpregs_set,
- .writeback = gpregs_writeback
- },
- {
- .core_note_type = NT_PRFPREG,
- .n = ELF_NFPREG,
- .size = sizeof(elf_fpreg_t), .align = sizeof(elf_fpreg_t),
- .regset_get = fpregs_get, .set = fpregs_set, .active = fpregs_active
- },
-};
-
-static const struct user_regset_view user_ia64_view = {
- .name = "ia64",
- .e_machine = EM_IA_64,
- .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets)
-};
-
-const struct user_regset_view *task_user_regset_view(struct task_struct *tsk)
-{
- return &user_ia64_view;
-}
-
-struct syscall_get_args {
- unsigned int i;
- unsigned int n;
- unsigned long *args;
- struct pt_regs *regs;
-};
-
-static void syscall_get_args_cb(struct unw_frame_info *info, void *data)
-{
- struct syscall_get_args *args = data;
- struct pt_regs *pt = args->regs;
- unsigned long *krbs, cfm, ndirty, nlocals, nouts;
- int i, count;
-
- if (unw_unwind_to_user(info) < 0)
- return;
-
- /*
- * We get here via a few paths:
- * - break instruction: cfm is shared with caller.
- * syscall args are in out= regs, locals are non-empty.
- * - epsinstruction: cfm is set by br.call
- * locals don't exist.
- *
- * For both cases arguments are reachable in cfm.sof - cfm.sol.
- * CFM: [ ... | sor: 17..14 | sol : 13..7 | sof : 6..0 ]
- */
- cfm = pt->cr_ifs;
- nlocals = (cfm >> 7) & 0x7f; /* aka sol */
- nouts = (cfm & 0x7f) - nlocals; /* aka sof - sol */
- krbs = (unsigned long *)info->task + IA64_RBS_OFFSET/8;
- ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19));
-
- count = 0;
- if (in_syscall(pt))
- count = min_t(int, args->n, nouts);
-
- /* Iterate over outs. */
- for (i = 0; i < count; i++) {
- int j = ndirty + nlocals + i + args->i;
- args->args[i] = *ia64_rse_skip_regs(krbs, j);
- }
-
- while (i < args->n) {
- args->args[i] = 0;
- i++;
- }
-}
-
-void syscall_get_arguments(struct task_struct *task,
- struct pt_regs *regs, unsigned long *args)
-{
- struct syscall_get_args data = {
- .i = 0,
- .n = 6,
- .args = args,
- .regs = regs,
- };
-
- if (task == current)
- unw_init_running(syscall_get_args_cb, &data);
- else {
- struct unw_frame_info ufi;
- memset(&ufi, 0, sizeof(ufi));
- unw_init_from_blocked_task(&ufi, task);
- syscall_get_args_cb(&ufi, &data);
- }
-}
diff --git a/arch/ia64/kernel/relocate_kernel.S b/arch/ia64/kernel/relocate_kernel.S
deleted file mode 100644
index 527a7b896a6e..000000000000
--- a/arch/ia64/kernel/relocate_kernel.S
+++ /dev/null
@@ -1,321 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/ia64/kernel/relocate_kernel.S
- *
- * Relocate kexec'able kernel and start it
- *
- * Copyright (C) 2005 Hewlett-Packard Development Company, L.P.
- * Copyright (C) 2005 Khalid Aziz <khalid.aziz@hp.com>
- * Copyright (C) 2005 Intel Corp, Zou Nan hai <nanhai.zou@intel.com>
- */
-#include <linux/pgtable.h>
-#include <asm/asmmacro.h>
-#include <asm/kregs.h>
-#include <asm/page.h>
-#include <asm/mca_asm.h>
-
- /* Must be relocatable PIC code callable as a C function
- */
-GLOBAL_ENTRY(relocate_new_kernel)
- .prologue
- alloc r31=ar.pfs,4,0,0,0
- .body
-.reloc_entry:
-{
- rsm psr.i| psr.ic
- mov r2=ip
-}
- ;;
-{
- flushrs // must be first insn in group
- srlz.i
-}
- ;;
- dep r2=0,r2,61,3 //to physical address
- ;;
- //first switch to physical mode
- add r3=1f-.reloc_entry, r2
- movl r16 = IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_IC
- mov ar.rsc=0 // put RSE in enforced lazy mode
- ;;
- add sp=(memory_stack_end - 16 - .reloc_entry),r2
- add r8=(register_stack - .reloc_entry),r2
- ;;
- mov r18=ar.rnat
- mov ar.bspstore=r8
- ;;
- mov cr.ipsr=r16
- mov cr.iip=r3
- mov cr.ifs=r0
- srlz.i
- ;;
- mov ar.rnat=r18
- rfi // note: this unmask MCA/INIT (psr.mc)
- ;;
-1:
- //physical mode code begin
- mov b6=in1
- dep r28=0,in2,61,3 //to physical address
-
- // purge all TC entries
-#define O(member) IA64_CPUINFO_##member##_OFFSET
- GET_THIS_PADDR(r2, ia64_cpu_info) // load phys addr of cpu_info into r2
- ;;
- addl r17=O(PTCE_STRIDE),r2
- addl r2=O(PTCE_BASE),r2
- ;;
- ld8 r18=[r2],(O(PTCE_COUNT)-O(PTCE_BASE));; // r18=ptce_base
- ld4 r19=[r2],4 // r19=ptce_count[0]
- ld4 r21=[r17],4 // r21=ptce_stride[0]
- ;;
- ld4 r20=[r2] // r20=ptce_count[1]
- ld4 r22=[r17] // r22=ptce_stride[1]
- mov r24=r0
- ;;
- adds r20=-1,r20
- ;;
-#undef O
-2:
- cmp.ltu p6,p7=r24,r19
-(p7) br.cond.dpnt.few 4f
- mov ar.lc=r20
-3:
- ptc.e r18
- ;;
- add r18=r22,r18
- br.cloop.sptk.few 3b
- ;;
- add r18=r21,r18
- add r24=1,r24
- ;;
- br.sptk.few 2b
-4:
- srlz.i
- ;;
- // purge TR entry for kernel text and data
- movl r16=KERNEL_START
- mov r18=KERNEL_TR_PAGE_SHIFT<<2
- ;;
- ptr.i r16, r18
- ptr.d r16, r18
- ;;
- srlz.i
- ;;
-
- // purge TR entry for pal code
- mov r16=in3
- mov r18=IA64_GRANULE_SHIFT<<2
- ;;
- ptr.i r16,r18
- ;;
- srlz.i
- ;;
-
- // purge TR entry for stack
- mov r16=IA64_KR(CURRENT_STACK)
- ;;
- shl r16=r16,IA64_GRANULE_SHIFT
- movl r19=PAGE_OFFSET
- ;;
- add r16=r19,r16
- mov r18=IA64_GRANULE_SHIFT<<2
- ;;
- ptr.d r16,r18
- ;;
- srlz.i
- ;;
-
- //copy segments
- movl r16=PAGE_MASK
- mov r30=in0 // in0 is page_list
- br.sptk.few .dest_page
- ;;
-.loop:
- ld8 r30=[in0], 8;;
-.dest_page:
- tbit.z p0, p6=r30, 0;; // 0x1 dest page
-(p6) and r17=r30, r16
-(p6) br.cond.sptk.few .loop;;
-
- tbit.z p0, p6=r30, 1;; // 0x2 indirect page
-(p6) and in0=r30, r16
-(p6) br.cond.sptk.few .loop;;
-
- tbit.z p0, p6=r30, 2;; // 0x4 end flag
-(p6) br.cond.sptk.few .end_loop;;
-
- tbit.z p6, p0=r30, 3;; // 0x8 source page
-(p6) br.cond.sptk.few .loop
-
- and r18=r30, r16
-
- // simple copy page, may optimize later
- movl r14=PAGE_SIZE/8 - 1;;
- mov ar.lc=r14;;
-1:
- ld8 r14=[r18], 8;;
- st8 [r17]=r14;;
- fc.i r17
- add r17=8, r17
- br.ctop.sptk.few 1b
- br.sptk.few .loop
- ;;
-
-.end_loop:
- sync.i // for fc.i
- ;;
- srlz.i
- ;;
- srlz.d
- ;;
- br.call.sptk.many b0=b6;;
-
-.align 32
-memory_stack:
- .fill 8192, 1, 0
-memory_stack_end:
-register_stack:
- .fill 8192, 1, 0
-register_stack_end:
-relocate_new_kernel_end:
-END(relocate_new_kernel)
-
-.global relocate_new_kernel_size
-relocate_new_kernel_size:
- data8 relocate_new_kernel_end - relocate_new_kernel
-
-GLOBAL_ENTRY(ia64_dump_cpu_regs)
- .prologue
- alloc loc0=ar.pfs,1,2,0,0
- .body
- mov ar.rsc=0 // put RSE in enforced lazy mode
- add loc1=4*8, in0 // save r4 and r5 first
- ;;
-{
- flushrs // flush dirty regs to backing store
- srlz.i
-}
- st8 [loc1]=r4, 8
- ;;
- st8 [loc1]=r5, 8
- ;;
- add loc1=32*8, in0
- mov r4=ar.rnat
- ;;
- st8 [in0]=r0, 8 // r0
- st8 [loc1]=r4, 8 // rnat
- mov r5=pr
- ;;
- st8 [in0]=r1, 8 // r1
- st8 [loc1]=r5, 8 // pr
- mov r4=b0
- ;;
- st8 [in0]=r2, 8 // r2
- st8 [loc1]=r4, 8 // b0
- mov r5=b1;
- ;;
- st8 [in0]=r3, 24 // r3
- st8 [loc1]=r5, 8 // b1
- mov r4=b2
- ;;
- st8 [in0]=r6, 8 // r6
- st8 [loc1]=r4, 8 // b2
- mov r5=b3
- ;;
- st8 [in0]=r7, 8 // r7
- st8 [loc1]=r5, 8 // b3
- mov r4=b4
- ;;
- st8 [in0]=r8, 8 // r8
- st8 [loc1]=r4, 8 // b4
- mov r5=b5
- ;;
- st8 [in0]=r9, 8 // r9
- st8 [loc1]=r5, 8 // b5
- mov r4=b6
- ;;
- st8 [in0]=r10, 8 // r10
- st8 [loc1]=r5, 8 // b6
- mov r5=b7
- ;;
- st8 [in0]=r11, 8 // r11
- st8 [loc1]=r5, 8 // b7
- mov r4=b0
- ;;
- st8 [in0]=r12, 8 // r12
- st8 [loc1]=r4, 8 // ip
- mov r5=loc0
- ;;
- st8 [in0]=r13, 8 // r13
- extr.u r5=r5, 0, 38 // ar.pfs.pfm
- mov r4=r0 // user mask
- ;;
- st8 [in0]=r14, 8 // r14
- st8 [loc1]=r5, 8 // cfm
- ;;
- st8 [in0]=r15, 8 // r15
- st8 [loc1]=r4, 8 // user mask
- mov r5=ar.rsc
- ;;
- st8 [in0]=r16, 8 // r16
- st8 [loc1]=r5, 8 // ar.rsc
- mov r4=ar.bsp
- ;;
- st8 [in0]=r17, 8 // r17
- st8 [loc1]=r4, 8 // ar.bsp
- mov r5=ar.bspstore
- ;;
- st8 [in0]=r18, 8 // r18
- st8 [loc1]=r5, 8 // ar.bspstore
- mov r4=ar.rnat
- ;;
- st8 [in0]=r19, 8 // r19
- st8 [loc1]=r4, 8 // ar.rnat
- mov r5=ar.ccv
- ;;
- st8 [in0]=r20, 8 // r20
- st8 [loc1]=r5, 8 // ar.ccv
- mov r4=ar.unat
- ;;
- st8 [in0]=r21, 8 // r21
- st8 [loc1]=r4, 8 // ar.unat
- mov r5 = ar.fpsr
- ;;
- st8 [in0]=r22, 8 // r22
- st8 [loc1]=r5, 8 // ar.fpsr
- mov r4 = ar.unat
- ;;
- st8 [in0]=r23, 8 // r23
- st8 [loc1]=r4, 8 // unat
- mov r5 = ar.fpsr
- ;;
- st8 [in0]=r24, 8 // r24
- st8 [loc1]=r5, 8 // fpsr
- mov r4 = ar.pfs
- ;;
- st8 [in0]=r25, 8 // r25
- st8 [loc1]=r4, 8 // ar.pfs
- mov r5 = ar.lc
- ;;
- st8 [in0]=r26, 8 // r26
- st8 [loc1]=r5, 8 // ar.lc
- mov r4 = ar.ec
- ;;
- st8 [in0]=r27, 8 // r27
- st8 [loc1]=r4, 8 // ar.ec
- mov r5 = ar.csd
- ;;
- st8 [in0]=r28, 8 // r28
- st8 [loc1]=r5, 8 // ar.csd
- mov r4 = ar.ssd
- ;;
- st8 [in0]=r29, 8 // r29
- st8 [loc1]=r4, 8 // ar.ssd
- ;;
- st8 [in0]=r30, 8 // r30
- ;;
- st8 [in0]=r31, 8 // r31
- mov ar.pfs=loc0
- ;;
- br.ret.sptk.many rp
-END(ia64_dump_cpu_regs)
diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
deleted file mode 100644
index e4f0705c0282..000000000000
--- a/arch/ia64/kernel/sal.c
+++ /dev/null
@@ -1,400 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * System Abstraction Layer (SAL) interface routines.
- *
- * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-
-#include <asm/delay.h>
-#include <asm/page.h>
-#include <asm/sal.h>
-#include <asm/pal.h>
-#include <asm/xtp.h>
-
- __cacheline_aligned DEFINE_SPINLOCK(sal_lock);
-unsigned long sal_platform_features;
-
-unsigned short sal_revision;
-unsigned short sal_version;
-
-#define SAL_MAJOR(x) ((x) >> 8)
-#define SAL_MINOR(x) ((x) & 0xff)
-
-static struct {
- void *addr; /* function entry point */
- void *gpval; /* gp value to use */
-} pdesc;
-
-static long
-default_handler (void)
-{
- return -1;
-}
-
-ia64_sal_handler ia64_sal = (ia64_sal_handler) default_handler;
-ia64_sal_desc_ptc_t *ia64_ptc_domain_info;
-
-const char *
-ia64_sal_strerror (long status)
-{
- const char *str;
- switch (status) {
- case 0: str = "Call completed without error"; break;
- case 1: str = "Effect a warm boot of the system to complete "
- "the update"; break;
- case -1: str = "Not implemented"; break;
- case -2: str = "Invalid argument"; break;
- case -3: str = "Call completed with error"; break;
- case -4: str = "Virtual address not registered"; break;
- case -5: str = "No information available"; break;
- case -6: str = "Insufficient space to add the entry"; break;
- case -7: str = "Invalid entry_addr value"; break;
- case -8: str = "Invalid interrupt vector"; break;
- case -9: str = "Requested memory not available"; break;
- case -10: str = "Unable to write to the NVM device"; break;
- case -11: str = "Invalid partition type specified"; break;
- case -12: str = "Invalid NVM_Object id specified"; break;
- case -13: str = "NVM_Object already has the maximum number "
- "of partitions"; break;
- case -14: str = "Insufficient space in partition for the "
- "requested write sub-function"; break;
- case -15: str = "Insufficient data buffer space for the "
- "requested read record sub-function"; break;
- case -16: str = "Scratch buffer required for the write/delete "
- "sub-function"; break;
- case -17: str = "Insufficient space in the NVM_Object for the "
- "requested create sub-function"; break;
- case -18: str = "Invalid value specified in the partition_rec "
- "argument"; break;
- case -19: str = "Record oriented I/O not supported for this "
- "partition"; break;
- case -20: str = "Bad format of record to be written or "
- "required keyword variable not "
- "specified"; break;
- default: str = "Unknown SAL status code"; break;
- }
- return str;
-}
-
-void __init
-ia64_sal_handler_init (void *entry_point, void *gpval)
-{
- /* fill in the SAL procedure descriptor and point ia64_sal to it: */
- pdesc.addr = entry_point;
- pdesc.gpval = gpval;
- ia64_sal = (ia64_sal_handler) &pdesc;
-}
-
-static void __init
-check_versions (struct ia64_sal_systab *systab)
-{
- sal_revision = (systab->sal_rev_major << 8) | systab->sal_rev_minor;
- sal_version = (systab->sal_b_rev_major << 8) | systab->sal_b_rev_minor;
-
- /* Check for broken firmware */
- if ((sal_revision == SAL_VERSION_CODE(49, 29))
- && (sal_version == SAL_VERSION_CODE(49, 29)))
- {
- /*
- * Old firmware for zx2000 prototypes have this weird version number,
- * reset it to something sane.
- */
- sal_revision = SAL_VERSION_CODE(2, 8);
- sal_version = SAL_VERSION_CODE(0, 0);
- }
-}
-
-static void __init
-sal_desc_entry_point (void *p)
-{
- struct ia64_sal_desc_entry_point *ep = p;
- ia64_pal_handler_init(__va(ep->pal_proc));
- ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp));
-}
-
-#ifdef CONFIG_SMP
-static void __init
-set_smp_redirect (int flag)
-{
-#ifndef CONFIG_HOTPLUG_CPU
- if (no_int_routing)
- smp_int_redirect &= ~flag;
- else
- smp_int_redirect |= flag;
-#else
- /*
- * For CPU Hotplug we dont want to do any chipset supported
- * interrupt redirection. The reason is this would require that
- * All interrupts be stopped and hard bind the irq to a cpu.
- * Later when the interrupt is fired we need to set the redir hint
- * on again in the vector. This is cumbersome for something that the
- * user mode irq balancer will solve anyways.
- */
- no_int_routing=1;
- smp_int_redirect &= ~flag;
-#endif
-}
-#else
-#define set_smp_redirect(flag) do { } while (0)
-#endif
-
-static void __init
-sal_desc_platform_feature (void *p)
-{
- struct ia64_sal_desc_platform_feature *pf = p;
- sal_platform_features = pf->feature_mask;
-
- printk(KERN_INFO "SAL Platform features:");
- if (!sal_platform_features) {
- printk(" None\n");
- return;
- }
-
- if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_BUS_LOCK)
- printk(" BusLock");
- if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT) {
- printk(" IRQ_Redirection");
- set_smp_redirect(SMP_IRQ_REDIRECTION);
- }
- if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT) {
- printk(" IPI_Redirection");
- set_smp_redirect(SMP_IPI_REDIRECTION);
- }
- if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)
- printk(" ITC_Drift");
- printk("\n");
-}
-
-#ifdef CONFIG_SMP
-static void __init
-sal_desc_ap_wakeup (void *p)
-{
- struct ia64_sal_desc_ap_wakeup *ap = p;
-
- switch (ap->mechanism) {
- case IA64_SAL_AP_EXTERNAL_INT:
- ap_wakeup_vector = ap->vector;
- printk(KERN_INFO "SAL: AP wakeup using external interrupt "
- "vector 0x%lx\n", ap_wakeup_vector);
- break;
- default:
- printk(KERN_ERR "SAL: AP wakeup mechanism unsupported!\n");
- break;
- }
-}
-
-static void __init
-chk_nointroute_opt(void)
-{
- char *cp;
-
- for (cp = boot_command_line; *cp; ) {
- if (memcmp(cp, "nointroute", 10) == 0) {
- no_int_routing = 1;
- printk ("no_int_routing on\n");
- break;
- } else {
- while (*cp != ' ' && *cp)
- ++cp;
- while (*cp == ' ')
- ++cp;
- }
- }
-}
-
-#else
-static void __init sal_desc_ap_wakeup(void *p) { }
-#endif
-
-/*
- * HP rx5670 firmware polls for interrupts during SAL_CACHE_FLUSH by reading
- * cr.ivr, but it never writes cr.eoi. This leaves any interrupt marked as
- * "in-service" and masks other interrupts of equal or lower priority.
- *
- * HP internal defect reports: F1859, F2775, F3031.
- */
-static int sal_cache_flush_drops_interrupts;
-
-static int __init
-force_pal_cache_flush(char *str)
-{
- sal_cache_flush_drops_interrupts = 1;
- return 0;
-}
-early_param("force_pal_cache_flush", force_pal_cache_flush);
-
-void __init
-check_sal_cache_flush (void)
-{
- unsigned long flags;
- int cpu;
- u64 vector, cache_type = 3;
- struct ia64_sal_retval isrv;
-
- if (sal_cache_flush_drops_interrupts)
- return;
-
- cpu = get_cpu();
- local_irq_save(flags);
-
- /*
- * Send ourselves a timer interrupt, wait until it's reported, and see
- * if SAL_CACHE_FLUSH drops it.
- */
- ia64_send_ipi(cpu, IA64_TIMER_VECTOR, IA64_IPI_DM_INT, 0);
-
- while (!ia64_get_irr(IA64_TIMER_VECTOR))
- cpu_relax();
-
- SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0);
-
- if (isrv.status)
- printk(KERN_ERR "SAL_CAL_FLUSH failed with %ld\n", isrv.status);
-
- if (ia64_get_irr(IA64_TIMER_VECTOR)) {
- vector = ia64_get_ivr();
- ia64_eoi();
- WARN_ON(vector != IA64_TIMER_VECTOR);
- } else {
- sal_cache_flush_drops_interrupts = 1;
- printk(KERN_ERR "SAL: SAL_CACHE_FLUSH drops interrupts; "
- "PAL_CACHE_FLUSH will be used instead\n");
- ia64_eoi();
- }
-
- local_irq_restore(flags);
- put_cpu();
-}
-
-s64
-ia64_sal_cache_flush (u64 cache_type)
-{
- struct ia64_sal_retval isrv;
-
- if (sal_cache_flush_drops_interrupts) {
- unsigned long flags;
- u64 progress;
- s64 rc;
-
- progress = 0;
- local_irq_save(flags);
- rc = ia64_pal_cache_flush(cache_type,
- PAL_CACHE_FLUSH_INVALIDATE, &progress, NULL);
- local_irq_restore(flags);
- return rc;
- }
-
- SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0);
- return isrv.status;
-}
-EXPORT_SYMBOL_GPL(ia64_sal_cache_flush);
-
-void __init
-ia64_sal_init (struct ia64_sal_systab *systab)
-{
- char *p;
- int i;
-
- if (!systab) {
- printk(KERN_WARNING "Hmm, no SAL System Table.\n");
- return;
- }
-
- if (strncmp(systab->signature, "SST_", 4) != 0)
- printk(KERN_ERR "bad signature in system table!");
-
- check_versions(systab);
-#ifdef CONFIG_SMP
- chk_nointroute_opt();
-#endif
-
- /* revisions are coded in BCD, so %x does the job for us */
- printk(KERN_INFO "SAL %x.%x: %.32s %.32s%sversion %x.%x\n",
- SAL_MAJOR(sal_revision), SAL_MINOR(sal_revision),
- systab->oem_id, systab->product_id,
- systab->product_id[0] ? " " : "",
- SAL_MAJOR(sal_version), SAL_MINOR(sal_version));
-
- p = (char *) (systab + 1);
- for (i = 0; i < systab->entry_count; i++) {
- /*
- * The first byte of each entry type contains the type
- * descriptor.
- */
- switch (*p) {
- case SAL_DESC_ENTRY_POINT:
- sal_desc_entry_point(p);
- break;
- case SAL_DESC_PLATFORM_FEATURE:
- sal_desc_platform_feature(p);
- break;
- case SAL_DESC_PTC:
- ia64_ptc_domain_info = (ia64_sal_desc_ptc_t *)p;
- break;
- case SAL_DESC_AP_WAKEUP:
- sal_desc_ap_wakeup(p);
- break;
- }
- p += SAL_DESC_SIZE(*p);
- }
-
-}
-
-int
-ia64_sal_oemcall(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1,
- u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7)
-{
- if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
- return -1;
- SAL_CALL(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
- return 0;
-}
-EXPORT_SYMBOL(ia64_sal_oemcall);
-
-int
-ia64_sal_oemcall_nolock(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1,
- u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
- u64 arg7)
-{
- if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
- return -1;
- SAL_CALL_NOLOCK(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6,
- arg7);
- return 0;
-}
-EXPORT_SYMBOL(ia64_sal_oemcall_nolock);
-
-int
-ia64_sal_oemcall_reentrant(struct ia64_sal_retval *isrvp, u64 oemfunc,
- u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5,
- u64 arg6, u64 arg7)
-{
- if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
- return -1;
- SAL_CALL_REENTRANT(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6,
- arg7);
- return 0;
-}
-EXPORT_SYMBOL(ia64_sal_oemcall_reentrant);
-
-long
-ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second,
- unsigned long *drift_info)
-{
- struct ia64_sal_retval isrv;
-
- SAL_CALL(isrv, SAL_FREQ_BASE, which, 0, 0, 0, 0, 0, 0);
- *ticks_per_second = isrv.v0;
- *drift_info = isrv.v1;
- return isrv.status;
-}
-EXPORT_SYMBOL_GPL(ia64_sal_freq_base);
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
deleted file mode 100644
index 03b632c56899..000000000000
--- a/arch/ia64/kernel/salinfo.c
+++ /dev/null
@@ -1,646 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * salinfo.c
- *
- * Creates entries in /proc/sal for various system features.
- *
- * Copyright (c) 2003, 2006 Silicon Graphics, Inc. All rights reserved.
- * Copyright (c) 2003 Hewlett-Packard Co
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- *
- * 10/30/2001 jbarnes@sgi.com copied much of Stephane's palinfo
- * code to create this file
- * Oct 23 2003 kaos@sgi.com
- * Replace IPI with set_cpus_allowed() to read a record from the required cpu.
- * Redesign salinfo log processing to separate interrupt and user space
- * contexts.
- * Cache the record across multi-block reads from user space.
- * Support > 64 cpus.
- * Delete module_exit and MOD_INC/DEC_COUNT, salinfo cannot be a module.
- *
- * Jan 28 2004 kaos@sgi.com
- * Periodically check for outstanding MCA or INIT records.
- *
- * Dec 5 2004 kaos@sgi.com
- * Standardize which records are cleared automatically.
- *
- * Aug 18 2005 kaos@sgi.com
- * mca.c may not pass a buffer, a NULL buffer just indicates that a new
- * record is available in SAL.
- * Replace some NR_CPUS by cpus_online, for hotplug cpu.
- *
- * Jan 5 2006 kaos@sgi.com
- * Handle hotplug cpus coming online.
- * Handle hotplug cpus going offline while they still have outstanding records.
- * Use the cpu_* macros consistently.
- * Replace the counting semaphore with a mutex and a test if the cpumask is non-empty.
- * Modify the locking to make the test for "work to do" an atomic operation.
- */
-
-#include <linux/capability.h>
-#include <linux/cpu.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/smp.h>
-#include <linux/timer.h>
-#include <linux/vmalloc.h>
-#include <linux/semaphore.h>
-
-#include <asm/sal.h>
-#include <linux/uaccess.h>
-
-MODULE_AUTHOR("Jesse Barnes <jbarnes@sgi.com>");
-MODULE_DESCRIPTION("/proc interface to IA-64 SAL features");
-MODULE_LICENSE("GPL");
-
-typedef struct {
- const char *name; /* name of the proc entry */
- unsigned long feature; /* feature bit */
- struct proc_dir_entry *entry; /* registered entry (removal) */
-} salinfo_entry_t;
-
-/*
- * List {name,feature} pairs for every entry in /proc/sal/<feature>
- * that this module exports
- */
-static const salinfo_entry_t salinfo_entries[]={
- { "bus_lock", IA64_SAL_PLATFORM_FEATURE_BUS_LOCK, },
- { "irq_redirection", IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT, },
- { "ipi_redirection", IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT, },
- { "itc_drift", IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT, },
-};
-
-#define NR_SALINFO_ENTRIES ARRAY_SIZE(salinfo_entries)
-
-static char *salinfo_log_name[] = {
- "mca",
- "init",
- "cmc",
- "cpe",
-};
-
-static struct proc_dir_entry *salinfo_proc_entries[
- ARRAY_SIZE(salinfo_entries) + /* /proc/sal/bus_lock */
- ARRAY_SIZE(salinfo_log_name) + /* /proc/sal/{mca,...} */
- (2 * ARRAY_SIZE(salinfo_log_name)) + /* /proc/sal/mca/{event,data} */
- 1]; /* /proc/sal */
-
-/* Some records we get ourselves, some are accessed as saved data in buffers
- * that are owned by mca.c.
- */
-struct salinfo_data_saved {
- u8* buffer;
- u64 size;
- u64 id;
- int cpu;
-};
-
-/* State transitions. Actions are :-
- * Write "read <cpunum>" to the data file.
- * Write "clear <cpunum>" to the data file.
- * Write "oemdata <cpunum> <offset> to the data file.
- * Read from the data file.
- * Close the data file.
- *
- * Start state is NO_DATA.
- *
- * NO_DATA
- * write "read <cpunum>" -> NO_DATA or LOG_RECORD.
- * write "clear <cpunum>" -> NO_DATA or LOG_RECORD.
- * write "oemdata <cpunum> <offset> -> return -EINVAL.
- * read data -> return EOF.
- * close -> unchanged. Free record areas.
- *
- * LOG_RECORD
- * write "read <cpunum>" -> NO_DATA or LOG_RECORD.
- * write "clear <cpunum>" -> NO_DATA or LOG_RECORD.
- * write "oemdata <cpunum> <offset> -> format the oem data, goto OEMDATA.
- * read data -> return the INIT/MCA/CMC/CPE record.
- * close -> unchanged. Keep record areas.
- *
- * OEMDATA
- * write "read <cpunum>" -> NO_DATA or LOG_RECORD.
- * write "clear <cpunum>" -> NO_DATA or LOG_RECORD.
- * write "oemdata <cpunum> <offset> -> format the oem data, goto OEMDATA.
- * read data -> return the formatted oemdata.
- * close -> unchanged. Keep record areas.
- *
- * Closing the data file does not change the state. This allows shell scripts
- * to manipulate salinfo data, each shell redirection opens the file, does one
- * action then closes it again. The record areas are only freed at close when
- * the state is NO_DATA.
- */
-enum salinfo_state {
- STATE_NO_DATA,
- STATE_LOG_RECORD,
- STATE_OEMDATA,
-};
-
-struct salinfo_data {
- cpumask_t cpu_event; /* which cpus have outstanding events */
- wait_queue_head_t read_wait;
- u8 *log_buffer;
- u64 log_size;
- u8 *oemdata; /* decoded oem data */
- u64 oemdata_size;
- int open; /* single-open to prevent races */
- u8 type;
- u8 saved_num; /* using a saved record? */
- enum salinfo_state state :8; /* processing state */
- u8 padding;
- int cpu_check; /* next CPU to check */
- struct salinfo_data_saved data_saved[5];/* save last 5 records from mca.c, must be < 255 */
-};
-
-static struct salinfo_data salinfo_data[ARRAY_SIZE(salinfo_log_name)];
-
-static DEFINE_SPINLOCK(data_lock);
-static DEFINE_SPINLOCK(data_saved_lock);
-
-/** salinfo_platform_oemdata - optional callback to decode oemdata from an error
- * record.
- * @sect_header: pointer to the start of the section to decode.
- * @oemdata: returns vmalloc area containing the decoded output.
- * @oemdata_size: returns length of decoded output (strlen).
- *
- * Description: If user space asks for oem data to be decoded by the kernel
- * and/or prom and the platform has set salinfo_platform_oemdata to the address
- * of a platform specific routine then call that routine. salinfo_platform_oemdata
- * vmalloc's and formats its output area, returning the address of the text
- * and its strlen. Returns 0 for success, -ve for error. The callback is
- * invoked on the cpu that generated the error record.
- */
-int (*salinfo_platform_oemdata)(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size);
-
-struct salinfo_platform_oemdata_parms {
- const u8 *efi_guid;
- u8 **oemdata;
- u64 *oemdata_size;
-};
-
-static long
-salinfo_platform_oemdata_cpu(void *context)
-{
- struct salinfo_platform_oemdata_parms *parms = context;
-
- return salinfo_platform_oemdata(parms->efi_guid, parms->oemdata, parms->oemdata_size);
-}
-
-static void
-shift1_data_saved (struct salinfo_data *data, int shift)
-{
- memcpy(data->data_saved+shift, data->data_saved+shift+1,
- (ARRAY_SIZE(data->data_saved) - (shift+1)) * sizeof(data->data_saved[0]));
- memset(data->data_saved + ARRAY_SIZE(data->data_saved) - 1, 0,
- sizeof(data->data_saved[0]));
-}
-
-/* This routine is invoked in interrupt context. Note: mca.c enables
- * interrupts before calling this code for CMC/CPE. MCA and INIT events are
- * not irq safe, do not call any routines that use spinlocks, they may deadlock.
- * MCA and INIT records are recorded, a timer event will look for any
- * outstanding events and wake up the user space code.
- *
- * The buffer passed from mca.c points to the output from ia64_log_get. This is
- * a persistent buffer but its contents can change between the interrupt and
- * when user space processes the record. Save the record id to identify
- * changes. If the buffer is NULL then just update the bitmap.
- */
-void
-salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
-{
- struct salinfo_data *data = salinfo_data + type;
- struct salinfo_data_saved *data_saved;
- unsigned long flags = 0;
- int i;
- int saved_size = ARRAY_SIZE(data->data_saved);
-
- BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));
-
- if (irqsafe)
- spin_lock_irqsave(&data_saved_lock, flags);
- if (buffer) {
- for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
- if (!data_saved->buffer)
- break;
- }
- if (i == saved_size) {
- if (!data->saved_num) {
- shift1_data_saved(data, 0);
- data_saved = data->data_saved + saved_size - 1;
- } else
- data_saved = NULL;
- }
- if (data_saved) {
- data_saved->cpu = smp_processor_id();
- data_saved->id = ((sal_log_record_header_t *)buffer)->id;
- data_saved->size = size;
- data_saved->buffer = buffer;
- }
- }
- cpumask_set_cpu(smp_processor_id(), &data->cpu_event);
- if (irqsafe) {
- wake_up_interruptible(&data->read_wait);
- spin_unlock_irqrestore(&data_saved_lock, flags);
- }
-}
-
-/* Check for outstanding MCA/INIT records every minute (arbitrary) */
-#define SALINFO_TIMER_DELAY (60*HZ)
-static struct timer_list salinfo_timer;
-extern void ia64_mlogbuf_dump(void);
-
-static void
-salinfo_timeout_check(struct salinfo_data *data)
-{
- if (!data->open)
- return;
- if (!cpumask_empty(&data->cpu_event))
- wake_up_interruptible(&data->read_wait);
-}
-
-static void
-salinfo_timeout(struct timer_list *unused)
-{
- ia64_mlogbuf_dump();
- salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA);
- salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_INIT);
- salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY;
- add_timer(&salinfo_timer);
-}
-
-static int
-salinfo_event_open(struct inode *inode, struct file *file)
-{
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- return 0;
-}
-
-static ssize_t
-salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
- struct salinfo_data *data = pde_data(file_inode(file));
- char cmd[32];
- size_t size;
- int i, n, cpu = -1;
-
-retry:
- if (cpumask_empty(&data->cpu_event)) {
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
- if (wait_event_interruptible(data->read_wait,
- !cpumask_empty(&data->cpu_event)))
- return -EINTR;
- }
-
- n = data->cpu_check;
- for (i = 0; i < nr_cpu_ids; i++) {
- if (cpumask_test_cpu(n, &data->cpu_event)) {
- if (!cpu_online(n)) {
- cpumask_clear_cpu(n, &data->cpu_event);
- continue;
- }
- cpu = n;
- break;
- }
- if (++n == nr_cpu_ids)
- n = 0;
- }
-
- if (cpu == -1)
- goto retry;
-
- ia64_mlogbuf_dump();
-
- /* for next read, start checking at next CPU */
- data->cpu_check = cpu;
- if (++data->cpu_check == nr_cpu_ids)
- data->cpu_check = 0;
-
- snprintf(cmd, sizeof(cmd), "read %d\n", cpu);
-
- size = strlen(cmd);
- if (size > count)
- size = count;
- if (copy_to_user(buffer, cmd, size))
- return -EFAULT;
-
- return size;
-}
-
-static const struct proc_ops salinfo_event_proc_ops = {
- .proc_open = salinfo_event_open,
- .proc_read = salinfo_event_read,
- .proc_lseek = noop_llseek,
-};
-
-static int
-salinfo_log_open(struct inode *inode, struct file *file)
-{
- struct salinfo_data *data = pde_data(inode);
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- spin_lock(&data_lock);
- if (data->open) {
- spin_unlock(&data_lock);
- return -EBUSY;
- }
- data->open = 1;
- spin_unlock(&data_lock);
-
- if (data->state == STATE_NO_DATA &&
- !(data->log_buffer = vmalloc(ia64_sal_get_state_info_size(data->type)))) {
- data->open = 0;
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int
-salinfo_log_release(struct inode *inode, struct file *file)
-{
- struct salinfo_data *data = pde_data(inode);
-
- if (data->state == STATE_NO_DATA) {
- vfree(data->log_buffer);
- vfree(data->oemdata);
- data->log_buffer = NULL;
- data->oemdata = NULL;
- }
- spin_lock(&data_lock);
- data->open = 0;
- spin_unlock(&data_lock);
- return 0;
-}
-
-static long
-salinfo_log_read_cpu(void *context)
-{
- struct salinfo_data *data = context;
- sal_log_record_header_t *rh;
- data->log_size = ia64_sal_get_state_info(data->type, (u64 *) data->log_buffer);
- rh = (sal_log_record_header_t *)(data->log_buffer);
- /* Clear corrected errors as they are read from SAL */
- if (rh->severity == sal_log_severity_corrected)
- ia64_sal_clear_state_info(data->type);
- return 0;
-}
-
-static void
-salinfo_log_new_read(int cpu, struct salinfo_data *data)
-{
- struct salinfo_data_saved *data_saved;
- unsigned long flags;
- int i;
- int saved_size = ARRAY_SIZE(data->data_saved);
-
- data->saved_num = 0;
- spin_lock_irqsave(&data_saved_lock, flags);
-retry:
- for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
- if (data_saved->buffer && data_saved->cpu == cpu) {
- sal_log_record_header_t *rh = (sal_log_record_header_t *)(data_saved->buffer);
- data->log_size = data_saved->size;
- memcpy(data->log_buffer, rh, data->log_size);
- barrier(); /* id check must not be moved */
- if (rh->id == data_saved->id) {
- data->saved_num = i+1;
- break;
- }
- /* saved record changed by mca.c since interrupt, discard it */
- shift1_data_saved(data, i);
- goto retry;
- }
- }
- spin_unlock_irqrestore(&data_saved_lock, flags);
-
- if (!data->saved_num)
- work_on_cpu_safe(cpu, salinfo_log_read_cpu, data);
- if (!data->log_size) {
- data->state = STATE_NO_DATA;
- cpumask_clear_cpu(cpu, &data->cpu_event);
- } else {
- data->state = STATE_LOG_RECORD;
- }
-}
-
-static ssize_t
-salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
- struct salinfo_data *data = pde_data(file_inode(file));
- u8 *buf;
- u64 bufsize;
-
- if (data->state == STATE_LOG_RECORD) {
- buf = data->log_buffer;
- bufsize = data->log_size;
- } else if (data->state == STATE_OEMDATA) {
- buf = data->oemdata;
- bufsize = data->oemdata_size;
- } else {
- buf = NULL;
- bufsize = 0;
- }
- return simple_read_from_buffer(buffer, count, ppos, buf, bufsize);
-}
-
-static long
-salinfo_log_clear_cpu(void *context)
-{
- struct salinfo_data *data = context;
-
- ia64_sal_clear_state_info(data->type);
- return 0;
-}
-
-static int
-salinfo_log_clear(struct salinfo_data *data, int cpu)
-{
- sal_log_record_header_t *rh;
- unsigned long flags;
- spin_lock_irqsave(&data_saved_lock, flags);
- data->state = STATE_NO_DATA;
- if (!cpumask_test_cpu(cpu, &data->cpu_event)) {
- spin_unlock_irqrestore(&data_saved_lock, flags);
- return 0;
- }
- cpumask_clear_cpu(cpu, &data->cpu_event);
- if (data->saved_num) {
- shift1_data_saved(data, data->saved_num - 1);
- data->saved_num = 0;
- }
- spin_unlock_irqrestore(&data_saved_lock, flags);
- rh = (sal_log_record_header_t *)(data->log_buffer);
- /* Corrected errors have already been cleared from SAL */
- if (rh->severity != sal_log_severity_corrected)
- work_on_cpu_safe(cpu, salinfo_log_clear_cpu, data);
- /* clearing a record may make a new record visible */
- salinfo_log_new_read(cpu, data);
- if (data->state == STATE_LOG_RECORD) {
- spin_lock_irqsave(&data_saved_lock, flags);
- cpumask_set_cpu(cpu, &data->cpu_event);
- wake_up_interruptible(&data->read_wait);
- spin_unlock_irqrestore(&data_saved_lock, flags);
- }
- return 0;
-}
-
-static ssize_t
-salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
- struct salinfo_data *data = pde_data(file_inode(file));
- char cmd[32];
- size_t size;
- u32 offset;
- int cpu;
-
- size = sizeof(cmd);
- if (count < size)
- size = count;
- if (copy_from_user(cmd, buffer, size))
- return -EFAULT;
-
- if (sscanf(cmd, "read %d", &cpu) == 1) {
- salinfo_log_new_read(cpu, data);
- } else if (sscanf(cmd, "clear %d", &cpu) == 1) {
- int ret;
- if ((ret = salinfo_log_clear(data, cpu)))
- count = ret;
- } else if (sscanf(cmd, "oemdata %d %d", &cpu, &offset) == 2) {
- if (data->state != STATE_LOG_RECORD && data->state != STATE_OEMDATA)
- return -EINVAL;
- if (offset > data->log_size - sizeof(efi_guid_t))
- return -EINVAL;
- data->state = STATE_OEMDATA;
- if (salinfo_platform_oemdata) {
- struct salinfo_platform_oemdata_parms parms = {
- .efi_guid = data->log_buffer + offset,
- .oemdata = &data->oemdata,
- .oemdata_size = &data->oemdata_size
- };
- count = work_on_cpu_safe(cpu, salinfo_platform_oemdata_cpu,
- &parms);
- } else
- data->oemdata_size = 0;
- } else
- return -EINVAL;
-
- return count;
-}
-
-static const struct proc_ops salinfo_data_proc_ops = {
- .proc_open = salinfo_log_open,
- .proc_release = salinfo_log_release,
- .proc_read = salinfo_log_read,
- .proc_write = salinfo_log_write,
- .proc_lseek = default_llseek,
-};
-
-static int salinfo_cpu_online(unsigned int cpu)
-{
- unsigned int i, end = ARRAY_SIZE(salinfo_data);
- struct salinfo_data *data;
-
- spin_lock_irq(&data_saved_lock);
- for (i = 0, data = salinfo_data; i < end; ++i, ++data) {
- cpumask_set_cpu(cpu, &data->cpu_event);
- wake_up_interruptible(&data->read_wait);
- }
- spin_unlock_irq(&data_saved_lock);
- return 0;
-}
-
-static int salinfo_cpu_pre_down(unsigned int cpu)
-{
- unsigned int i, end = ARRAY_SIZE(salinfo_data);
- struct salinfo_data *data;
-
- spin_lock_irq(&data_saved_lock);
- for (i = 0, data = salinfo_data; i < end; ++i, ++data) {
- struct salinfo_data_saved *data_saved;
- int j = ARRAY_SIZE(data->data_saved) - 1;
-
- for (data_saved = data->data_saved + j; j >= 0;
- --j, --data_saved) {
- if (data_saved->buffer && data_saved->cpu == cpu)
- shift1_data_saved(data, j);
- }
- cpumask_clear_cpu(cpu, &data->cpu_event);
- }
- spin_unlock_irq(&data_saved_lock);
- return 0;
-}
-
-/*
- * 'data' contains an integer that corresponds to the feature we're
- * testing
- */
-static int __maybe_unused proc_salinfo_show(struct seq_file *m, void *v)
-{
- unsigned long data = (unsigned long)v;
- seq_puts(m, (sal_platform_features & data) ? "1\n" : "0\n");
- return 0;
-}
-
-static int __init
-salinfo_init(void)
-{
- struct proc_dir_entry *salinfo_dir; /* /proc/sal dir entry */
- struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */
- struct proc_dir_entry *dir, *entry;
- struct salinfo_data *data;
- int i;
-
- salinfo_dir = proc_mkdir("sal", NULL);
- if (!salinfo_dir)
- return 0;
-
- for (i=0; i < NR_SALINFO_ENTRIES; i++) {
- /* pass the feature bit in question as misc data */
- *sdir++ = proc_create_single_data(salinfo_entries[i].name, 0,
- salinfo_dir, proc_salinfo_show,
- (void *)salinfo_entries[i].feature);
- }
-
- for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
- data = salinfo_data + i;
- data->type = i;
- init_waitqueue_head(&data->read_wait);
- dir = proc_mkdir(salinfo_log_name[i], salinfo_dir);
- if (!dir)
- continue;
-
- entry = proc_create_data("event", S_IRUSR, dir,
- &salinfo_event_proc_ops, data);
- if (!entry)
- continue;
- *sdir++ = entry;
-
- entry = proc_create_data("data", S_IRUSR | S_IWUSR, dir,
- &salinfo_data_proc_ops, data);
- if (!entry)
- continue;
- *sdir++ = entry;
-
- *sdir++ = dir;
- }
-
- *sdir++ = salinfo_dir;
-
- timer_setup(&salinfo_timer, salinfo_timeout, 0);
- salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY;
- add_timer(&salinfo_timer);
-
- i = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/salinfo:online",
- salinfo_cpu_online, salinfo_cpu_pre_down);
- WARN_ON(i < 0);
- return 0;
-}
-
-module_init(salinfo_init);
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
deleted file mode 100644
index 5a55ac82c13a..000000000000
--- a/arch/ia64/kernel/setup.c
+++ /dev/null
@@ -1,1081 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Architecture-specific setup.
- *
- * Copyright (C) 1998-2001, 2003-2004 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 2000, 2004 Intel Corp
- * Rohit Seth <rohit.seth@intel.com>
- * Suresh Siddha <suresh.b.siddha@intel.com>
- * Gordon Jin <gordon.jin@intel.com>
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- *
- * 12/26/04 S.Siddha, G.Jin, R.Seth
- * Add multi-threading and multi-core detection
- * 11/12/01 D.Mosberger Convert get_cpuinfo() to seq_file based show_cpuinfo().
- * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map
- * 03/31/00 R.Seth cpu_initialized and current->processor fixes
- * 02/04/00 D.Mosberger some more get_cpuinfo fixes...
- * 02/01/00 R.Seth fixed get_cpuinfo for SMP
- * 01/07/99 S.Eranian added the support for command line argument
- * 06/24/99 W.Drummond added boot_cpu_data.
- * 05/28/05 Z. Menyhart Dynamic stride size for "flush_icache_range()"
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pgtable.h>
-
-#include <linux/acpi.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/cpu.h>
-#include <linux/kdev_t.h>
-#include <linux/kernel.h>
-#include <linux/memblock.h>
-#include <linux/reboot.h>
-#include <linux/sched/mm.h>
-#include <linux/sched/clock.h>
-#include <linux/sched/task_stack.h>
-#include <linux/seq_file.h>
-#include <linux/string.h>
-#include <linux/threads.h>
-#include <linux/screen_info.h>
-#include <linux/dmi.h>
-#include <linux/root_dev.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/efi.h>
-#include <linux/initrd.h>
-#include <linux/pm.h>
-#include <linux/cpufreq.h>
-#include <linux/kexec.h>
-#include <linux/crash_dump.h>
-
-#include <asm/mca.h>
-#include <asm/meminit.h>
-#include <asm/page.h>
-#include <asm/patch.h>
-#include <asm/processor.h>
-#include <asm/sal.h>
-#include <asm/sections.h>
-#include <asm/setup.h>
-#include <asm/smp.h>
-#include <asm/tlbflush.h>
-#include <asm/unistd.h>
-#include <asm/uv/uv.h>
-#include <asm/xtp.h>
-
-#if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE)
-# error "struct cpuinfo_ia64 too big!"
-#endif
-
-char ia64_platform_name[64];
-
-#ifdef CONFIG_SMP
-unsigned long __per_cpu_offset[NR_CPUS];
-EXPORT_SYMBOL(__per_cpu_offset);
-#endif
-
-DEFINE_PER_CPU(struct cpuinfo_ia64, ia64_cpu_info);
-EXPORT_SYMBOL(ia64_cpu_info);
-DEFINE_PER_CPU(unsigned long, local_per_cpu_offset);
-#ifdef CONFIG_SMP
-EXPORT_SYMBOL(local_per_cpu_offset);
-#endif
-unsigned long ia64_cycles_per_usec;
-struct ia64_boot_param *ia64_boot_param;
-struct screen_info screen_info;
-unsigned long vga_console_iobase;
-unsigned long vga_console_membase;
-
-static struct resource data_resource = {
- .name = "Kernel data",
- .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
-};
-
-static struct resource code_resource = {
- .name = "Kernel code",
- .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
-};
-
-static struct resource bss_resource = {
- .name = "Kernel bss",
- .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
-};
-
-unsigned long ia64_max_cacheline_size;
-
-unsigned long ia64_iobase; /* virtual address for I/O accesses */
-EXPORT_SYMBOL(ia64_iobase);
-struct io_space io_space[MAX_IO_SPACES];
-EXPORT_SYMBOL(io_space);
-unsigned int num_io_spaces;
-
-/*
- * "flush_icache_range()" needs to know what processor dependent stride size to use
- * when it makes i-cache(s) coherent with d-caches.
- */
-#define I_CACHE_STRIDE_SHIFT 5 /* Safest way to go: 32 bytes by 32 bytes */
-unsigned long ia64_i_cache_stride_shift = ~0;
-/*
- * "clflush_cache_range()" needs to know what processor dependent stride size to
- * use when it flushes cache lines including both d-cache and i-cache.
- */
-/* Safest way to go: 32 bytes by 32 bytes */
-#define CACHE_STRIDE_SHIFT 5
-unsigned long ia64_cache_stride_shift = ~0;
-
-/*
- * We use a special marker for the end of memory and it uses the extra (+1) slot
- */
-struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1] __initdata;
-static int num_rsvd_regions __initdata;
-
-
-/*
- * Filter incoming memory segments based on the primitive map created from the boot
- * parameters. Segments contained in the map are removed from the memory ranges. A
- * caller-specified function is called with the memory ranges that remain after filtering.
- * This routine does not assume the incoming segments are sorted.
- */
-int __init
-filter_rsvd_memory (u64 start, u64 end, void *arg)
-{
- u64 range_start, range_end, prev_start;
- void (*func)(unsigned long, unsigned long, int);
- int i;
-
-#if IGNORE_PFN0
- if (start == PAGE_OFFSET) {
- printk(KERN_WARNING "warning: skipping physical page 0\n");
- start += PAGE_SIZE;
- if (start >= end) return 0;
- }
-#endif
- /*
- * lowest possible address(walker uses virtual)
- */
- prev_start = PAGE_OFFSET;
- func = arg;
-
- for (i = 0; i < num_rsvd_regions; ++i) {
- range_start = max(start, prev_start);
- range_end = min(end, rsvd_region[i].start);
-
- if (range_start < range_end)
- call_pernode_memory(__pa(range_start), range_end - range_start, func);
-
- /* nothing more available in this segment */
- if (range_end == end) return 0;
-
- prev_start = rsvd_region[i].end;
- }
- /* end of memory marker allows full processing inside loop body */
- return 0;
-}
-
-/*
- * Similar to "filter_rsvd_memory()", but the reserved memory ranges
- * are not filtered out.
- */
-int __init
-filter_memory(u64 start, u64 end, void *arg)
-{
- void (*func)(unsigned long, unsigned long, int);
-
-#if IGNORE_PFN0
- if (start == PAGE_OFFSET) {
- printk(KERN_WARNING "warning: skipping physical page 0\n");
- start += PAGE_SIZE;
- if (start >= end)
- return 0;
- }
-#endif
- func = arg;
- if (start < end)
- call_pernode_memory(__pa(start), end - start, func);
- return 0;
-}
-
-static void __init
-sort_regions (struct rsvd_region *rsvd_region, int max)
-{
- int j;
-
- /* simple bubble sorting */
- while (max--) {
- for (j = 0; j < max; ++j) {
- if (rsvd_region[j].start > rsvd_region[j+1].start) {
- swap(rsvd_region[j], rsvd_region[j + 1]);
- }
- }
- }
-}
-
-/* merge overlaps */
-static int __init
-merge_regions (struct rsvd_region *rsvd_region, int max)
-{
- int i;
- for (i = 1; i < max; ++i) {
- if (rsvd_region[i].start >= rsvd_region[i-1].end)
- continue;
- if (rsvd_region[i].end > rsvd_region[i-1].end)
- rsvd_region[i-1].end = rsvd_region[i].end;
- --max;
- memmove(&rsvd_region[i], &rsvd_region[i+1],
- (max - i) * sizeof(struct rsvd_region));
- }
- return max;
-}
-
-/*
- * Request address space for all standard resources
- */
-static int __init register_memory(void)
-{
- code_resource.start = ia64_tpa(_text);
- code_resource.end = ia64_tpa(_etext) - 1;
- data_resource.start = ia64_tpa(_etext);
- data_resource.end = ia64_tpa(_edata) - 1;
- bss_resource.start = ia64_tpa(__bss_start);
- bss_resource.end = ia64_tpa(_end) - 1;
- efi_initialize_iomem_resources(&code_resource, &data_resource,
- &bss_resource);
-
- return 0;
-}
-
-__initcall(register_memory);
-
-
-#ifdef CONFIG_KEXEC
-
-/*
- * This function checks if the reserved crashkernel is allowed on the specific
- * IA64 machine flavour. Machines without an IO TLB use swiotlb and require
- * some memory below 4 GB (i.e. in 32 bit area), see the implementation of
- * kernel/dma/swiotlb.c. The hpzx1 architecture has an IO TLB but cannot use that
- * in kdump case. See the comment in sba_init() in sba_iommu.c.
- *
- * So, the only machvec that really supports loading the kdump kernel
- * over 4 GB is "uv".
- */
-static int __init check_crashkernel_memory(unsigned long pbase, size_t size)
-{
- if (is_uv_system())
- return 1;
- else
- return pbase < (1UL << 32);
-}
-
-static void __init setup_crashkernel(unsigned long total, int *n)
-{
- unsigned long long base = 0, size = 0;
- int ret;
-
- ret = parse_crashkernel(boot_command_line, total,
- &size, &base);
- if (ret == 0 && size > 0) {
- if (!base) {
- sort_regions(rsvd_region, *n);
- *n = merge_regions(rsvd_region, *n);
- base = kdump_find_rsvd_region(size,
- rsvd_region, *n);
- }
-
- if (!check_crashkernel_memory(base, size)) {
- pr_warn("crashkernel: There would be kdump memory "
- "at %ld GB but this is unusable because it "
- "must\nbe below 4 GB. Change the memory "
- "configuration of the machine.\n",
- (unsigned long)(base >> 30));
- return;
- }
-
- if (base != ~0UL) {
- printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
- "for crashkernel (System RAM: %ldMB)\n",
- (unsigned long)(size >> 20),
- (unsigned long)(base >> 20),
- (unsigned long)(total >> 20));
- rsvd_region[*n].start =
- (unsigned long)__va(base);
- rsvd_region[*n].end =
- (unsigned long)__va(base + size);
- (*n)++;
- crashk_res.start = base;
- crashk_res.end = base + size - 1;
- }
- }
- efi_memmap_res.start = ia64_boot_param->efi_memmap;
- efi_memmap_res.end = efi_memmap_res.start +
- ia64_boot_param->efi_memmap_size;
- boot_param_res.start = __pa(ia64_boot_param);
- boot_param_res.end = boot_param_res.start +
- sizeof(*ia64_boot_param);
-}
-#else
-static inline void __init setup_crashkernel(unsigned long total, int *n)
-{}
-#endif
-
-#ifdef CONFIG_CRASH_DUMP
-static int __init reserve_elfcorehdr(u64 *start, u64 *end)
-{
- u64 length;
-
- /* We get the address using the kernel command line,
- * but the size is extracted from the EFI tables.
- * Both address and size are required for reservation
- * to work properly.
- */
-
- if (!is_vmcore_usable())
- return -EINVAL;
-
- if ((length = vmcore_find_descriptor_size(elfcorehdr_addr)) == 0) {
- vmcore_unusable();
- return -EINVAL;
- }
-
- *start = (unsigned long)__va(elfcorehdr_addr);
- *end = *start + length;
- return 0;
-}
-#endif /* CONFIG_CRASH_DUMP */
-
-/**
- * reserve_memory - setup reserved memory areas
- *
- * Setup the reserved memory areas set aside for the boot parameters,
- * initrd, etc. There are currently %IA64_MAX_RSVD_REGIONS defined,
- * see arch/ia64/include/asm/meminit.h if you need to define more.
- */
-void __init
-reserve_memory (void)
-{
- int n = 0;
- unsigned long total_memory;
-
- /*
- * none of the entries in this table overlap
- */
- rsvd_region[n].start = (unsigned long) ia64_boot_param;
- rsvd_region[n].end = rsvd_region[n].start + sizeof(*ia64_boot_param);
- n++;
-
- rsvd_region[n].start = (unsigned long) __va(ia64_boot_param->efi_memmap);
- rsvd_region[n].end = rsvd_region[n].start + ia64_boot_param->efi_memmap_size;
- n++;
-
- rsvd_region[n].start = (unsigned long) __va(ia64_boot_param->command_line);
- rsvd_region[n].end = (rsvd_region[n].start
- + strlen(__va(ia64_boot_param->command_line)) + 1);
- n++;
-
- rsvd_region[n].start = (unsigned long) ia64_imva((void *)KERNEL_START);
- rsvd_region[n].end = (unsigned long) ia64_imva(_end);
- n++;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (ia64_boot_param->initrd_start) {
- rsvd_region[n].start = (unsigned long)__va(ia64_boot_param->initrd_start);
- rsvd_region[n].end = rsvd_region[n].start + ia64_boot_param->initrd_size;
- n++;
- }
-#endif
-
-#ifdef CONFIG_CRASH_DUMP
- if (reserve_elfcorehdr(&rsvd_region[n].start,
- &rsvd_region[n].end) == 0)
- n++;
-#endif
-
- total_memory = efi_memmap_init(&rsvd_region[n].start, &rsvd_region[n].end);
- n++;
-
- setup_crashkernel(total_memory, &n);
-
- /* end of memory marker */
- rsvd_region[n].start = ~0UL;
- rsvd_region[n].end = ~0UL;
- n++;
-
- num_rsvd_regions = n;
- BUG_ON(IA64_MAX_RSVD_REGIONS + 1 < n);
-
- sort_regions(rsvd_region, num_rsvd_regions);
- num_rsvd_regions = merge_regions(rsvd_region, num_rsvd_regions);
-
- /* reserve all regions except the end of memory marker with memblock */
- for (n = 0; n < num_rsvd_regions - 1; n++) {
- struct rsvd_region *region = &rsvd_region[n];
- phys_addr_t addr = __pa(region->start);
- phys_addr_t size = region->end - region->start;
-
- memblock_reserve(addr, size);
- }
-}
-
-/**
- * find_initrd - get initrd parameters from the boot parameter structure
- *
- * Grab the initrd start and end from the boot parameter struct given us by
- * the boot loader.
- */
-void __init
-find_initrd (void)
-{
-#ifdef CONFIG_BLK_DEV_INITRD
- if (ia64_boot_param->initrd_start) {
- initrd_start = (unsigned long)__va(ia64_boot_param->initrd_start);
- initrd_end = initrd_start+ia64_boot_param->initrd_size;
-
- printk(KERN_INFO "Initial ramdisk at: 0x%lx (%llu bytes)\n",
- initrd_start, ia64_boot_param->initrd_size);
- }
-#endif
-}
-
-static void __init
-io_port_init (void)
-{
- unsigned long phys_iobase;
-
- /*
- * Set `iobase' based on the EFI memory map or, failing that, the
- * value firmware left in ar.k0.
- *
- * Note that in ia32 mode, IN/OUT instructions use ar.k0 to compute
- * the port's virtual address, so ia32_load_state() loads it with a
- * user virtual address. But in ia64 mode, glibc uses the
- * *physical* address in ar.k0 to mmap the appropriate area from
- * /dev/mem, and the inX()/outX() interfaces use MMIO. In both
- * cases, user-mode can only use the legacy 0-64K I/O port space.
- *
- * ar.k0 is not involved in kernel I/O port accesses, which can use
- * any of the I/O port spaces and are done via MMIO using the
- * virtual mmio_base from the appropriate io_space[].
- */
- phys_iobase = efi_get_iobase();
- if (!phys_iobase) {
- phys_iobase = ia64_get_kr(IA64_KR_IO_BASE);
- printk(KERN_INFO "No I/O port range found in EFI memory map, "
- "falling back to AR.KR0 (0x%lx)\n", phys_iobase);
- }
- ia64_iobase = (unsigned long) ioremap(phys_iobase, 0);
- ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
-
- /* setup legacy IO port space */
- io_space[0].mmio_base = ia64_iobase;
- io_space[0].sparse = 1;
- num_io_spaces = 1;
-}
-
-/**
- * early_console_setup - setup debugging console
- *
- * Consoles started here require little enough setup that we can start using
- * them very early in the boot process, either right after the machine
- * vector initialization, or even before if the drivers can detect their hw.
- *
- * Returns non-zero if a console couldn't be setup.
- */
-static inline int __init
-early_console_setup (char *cmdline)
-{
-#ifdef CONFIG_EFI_PCDP
- if (!efi_setup_pcdp_console(cmdline))
- return 0;
-#endif
- return -1;
-}
-
-static void __init
-screen_info_setup(void)
-{
- unsigned int orig_x, orig_y, num_cols, num_rows, font_height;
-
- memset(&screen_info, 0, sizeof(screen_info));
-
- if (!ia64_boot_param->console_info.num_rows ||
- !ia64_boot_param->console_info.num_cols) {
- printk(KERN_WARNING "invalid screen-info, guessing 80x25\n");
- orig_x = 0;
- orig_y = 0;
- num_cols = 80;
- num_rows = 25;
- font_height = 16;
- } else {
- orig_x = ia64_boot_param->console_info.orig_x;
- orig_y = ia64_boot_param->console_info.orig_y;
- num_cols = ia64_boot_param->console_info.num_cols;
- num_rows = ia64_boot_param->console_info.num_rows;
- font_height = 400 / num_rows;
- }
-
- screen_info.orig_x = orig_x;
- screen_info.orig_y = orig_y;
- screen_info.orig_video_cols = num_cols;
- screen_info.orig_video_lines = num_rows;
- screen_info.orig_video_points = font_height;
- screen_info.orig_video_mode = 3; /* XXX fake */
- screen_info.orig_video_isVGA = 1; /* XXX fake */
- screen_info.orig_video_ega_bx = 3; /* XXX fake */
-}
-
-static inline void
-mark_bsp_online (void)
-{
-#ifdef CONFIG_SMP
- /* If we register an early console, allow CPU 0 to printk */
- set_cpu_online(smp_processor_id(), true);
-#endif
-}
-
-static __initdata int nomca;
-static __init int setup_nomca(char *s)
-{
- nomca = 1;
- return 0;
-}
-early_param("nomca", setup_nomca);
-
-void __init
-setup_arch (char **cmdline_p)
-{
- unw_init();
-
- ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist);
-
- *cmdline_p = __va(ia64_boot_param->command_line);
- strscpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE);
-
- efi_init();
- io_port_init();
-
- uv_probe_system_type();
- parse_early_param();
-
- if (early_console_setup(*cmdline_p) == 0)
- mark_bsp_online();
-
- /* Initialize the ACPI boot-time table parser */
- acpi_table_init();
- early_acpi_boot_init();
-#ifdef CONFIG_ACPI_NUMA
- acpi_numa_init();
- acpi_numa_fixup();
-#ifdef CONFIG_ACPI_HOTPLUG_CPU
- prefill_possible_map();
-#endif
- per_cpu_scan_finalize((cpumask_empty(&early_cpu_possible_map) ?
- 32 : cpumask_weight(&early_cpu_possible_map)),
- additional_cpus > 0 ? additional_cpus : 0);
-#endif /* CONFIG_ACPI_NUMA */
-
-#ifdef CONFIG_SMP
- smp_build_cpu_map();
-#endif
- find_memory();
-
- /* process SAL system table: */
- ia64_sal_init(__va(sal_systab_phys));
-
-#ifdef CONFIG_ITANIUM
- ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist);
-#else
- {
- unsigned long num_phys_stacked;
-
- if (ia64_pal_rse_info(&num_phys_stacked, 0) == 0 && num_phys_stacked > 96)
- ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist);
- }
-#endif
-
-#ifdef CONFIG_SMP
- cpu_physical_id(0) = hard_smp_processor_id();
-#endif
-
- cpu_init(); /* initialize the bootstrap CPU */
- mmu_context_init(); /* initialize context_id bitmap */
-
-#ifdef CONFIG_VT
- if (!conswitchp) {
-# if defined(CONFIG_VGA_CONSOLE)
- /*
- * Non-legacy systems may route legacy VGA MMIO range to system
- * memory. vga_con probes the MMIO hole, so memory looks like
- * a VGA device to it. The EFI memory map can tell us if it's
- * memory so we can avoid this problem.
- */
- if (efi_mem_type(0xA0000) != EFI_CONVENTIONAL_MEMORY)
- conswitchp = &vga_con;
-# endif
- }
-#endif
-
- /* enable IA-64 Machine Check Abort Handling unless disabled */
- if (!nomca)
- ia64_mca_init();
-
- /*
- * Default to /dev/sda2. This assumes that the EFI partition
- * is physical disk 1 partition 1 and the Linux root disk is
- * physical disk 1 partition 2.
- */
- ROOT_DEV = MKDEV(SCSI_DISK0_MAJOR, 2);
-
- if (is_uv_system())
- uv_setup(cmdline_p);
-#ifdef CONFIG_SMP
- else
- init_smp_config();
-#endif
-
- screen_info_setup();
- paging_init();
-
- clear_sched_clock_stable();
-}
-
-/*
- * Display cpu info for all CPUs.
- */
-static int
-show_cpuinfo (struct seq_file *m, void *v)
-{
-#ifdef CONFIG_SMP
-# define lpj c->loops_per_jiffy
-# define cpunum c->cpu
-#else
-# define lpj loops_per_jiffy
-# define cpunum 0
-#endif
- static struct {
- unsigned long mask;
- const char *feature_name;
- } feature_bits[] = {
- { 1UL << 0, "branchlong" },
- { 1UL << 1, "spontaneous deferral"},
- { 1UL << 2, "16-byte atomic ops" }
- };
- char features[128], *cp, *sep;
- struct cpuinfo_ia64 *c = v;
- unsigned long mask;
- unsigned long proc_freq;
- int i, size;
-
- mask = c->features;
-
- /* build the feature string: */
- memcpy(features, "standard", 9);
- cp = features;
- size = sizeof(features);
- sep = "";
- for (i = 0; i < ARRAY_SIZE(feature_bits) && size > 1; ++i) {
- if (mask & feature_bits[i].mask) {
- cp += snprintf(cp, size, "%s%s", sep,
- feature_bits[i].feature_name),
- sep = ", ";
- mask &= ~feature_bits[i].mask;
- size = sizeof(features) - (cp - features);
- }
- }
- if (mask && size > 1) {
- /* print unknown features as a hex value */
- snprintf(cp, size, "%s0x%lx", sep, mask);
- }
-
- proc_freq = cpufreq_quick_get(cpunum);
- if (!proc_freq)
- proc_freq = c->proc_freq / 1000;
-
- seq_printf(m,
- "processor : %d\n"
- "vendor : %s\n"
- "arch : IA-64\n"
- "family : %u\n"
- "model : %u\n"
- "model name : %s\n"
- "revision : %u\n"
- "archrev : %u\n"
- "features : %s\n"
- "cpu number : %lu\n"
- "cpu regs : %u\n"
- "cpu MHz : %lu.%03lu\n"
- "itc MHz : %lu.%06lu\n"
- "BogoMIPS : %lu.%02lu\n",
- cpunum, c->vendor, c->family, c->model,
- c->model_name, c->revision, c->archrev,
- features, c->ppn, c->number,
- proc_freq / 1000, proc_freq % 1000,
- c->itc_freq / 1000000, c->itc_freq % 1000000,
- lpj*HZ/500000, (lpj*HZ/5000) % 100);
-#ifdef CONFIG_SMP
- seq_printf(m, "siblings : %u\n",
- cpumask_weight(&cpu_core_map[cpunum]));
- if (c->socket_id != -1)
- seq_printf(m, "physical id: %u\n", c->socket_id);
- if (c->threads_per_core > 1 || c->cores_per_socket > 1)
- seq_printf(m,
- "core id : %u\n"
- "thread id : %u\n",
- c->core_id, c->thread_id);
-#endif
- seq_printf(m,"\n");
-
- return 0;
-}
-
-static void *
-c_start (struct seq_file *m, loff_t *pos)
-{
-#ifdef CONFIG_SMP
- while (*pos < nr_cpu_ids && !cpu_online(*pos))
- ++*pos;
-#endif
- return *pos < nr_cpu_ids ? cpu_data(*pos) : NULL;
-}
-
-static void *
-c_next (struct seq_file *m, void *v, loff_t *pos)
-{
- ++*pos;
- return c_start(m, pos);
-}
-
-static void
-c_stop (struct seq_file *m, void *v)
-{
-}
-
-const struct seq_operations cpuinfo_op = {
- .start = c_start,
- .next = c_next,
- .stop = c_stop,
- .show = show_cpuinfo
-};
-
-#define MAX_BRANDS 8
-static char brandname[MAX_BRANDS][128];
-
-static char *
-get_model_name(__u8 family, __u8 model)
-{
- static int overflow;
- char brand[128];
- int i;
-
- memcpy(brand, "Unknown", 8);
- if (ia64_pal_get_brand_info(brand)) {
- if (family == 0x7)
- memcpy(brand, "Merced", 7);
- else if (family == 0x1f) switch (model) {
- case 0: memcpy(brand, "McKinley", 9); break;
- case 1: memcpy(brand, "Madison", 8); break;
- case 2: memcpy(brand, "Madison up to 9M cache", 23); break;
- }
- }
- for (i = 0; i < MAX_BRANDS; i++)
- if (strcmp(brandname[i], brand) == 0)
- return brandname[i];
- for (i = 0; i < MAX_BRANDS; i++)
- if (brandname[i][0] == '\0')
- return strcpy(brandname[i], brand);
- if (overflow++ == 0)
- printk(KERN_ERR
- "%s: Table overflow. Some processor model information will be missing\n",
- __func__);
- return "Unknown";
-}
-
-static void
-identify_cpu (struct cpuinfo_ia64 *c)
-{
- union {
- unsigned long bits[5];
- struct {
- /* id 0 & 1: */
- char vendor[16];
-
- /* id 2 */
- u64 ppn; /* processor serial number */
-
- /* id 3: */
- unsigned number : 8;
- unsigned revision : 8;
- unsigned model : 8;
- unsigned family : 8;
- unsigned archrev : 8;
- unsigned reserved : 24;
-
- /* id 4: */
- u64 features;
- } field;
- } cpuid;
- pal_vm_info_1_u_t vm1;
- pal_vm_info_2_u_t vm2;
- pal_status_t status;
- unsigned long impl_va_msb = 50, phys_addr_size = 44; /* Itanium defaults */
- int i;
- for (i = 0; i < 5; ++i)
- cpuid.bits[i] = ia64_get_cpuid(i);
-
- memcpy(c->vendor, cpuid.field.vendor, 16);
-#ifdef CONFIG_SMP
- c->cpu = smp_processor_id();
-
- /* below default values will be overwritten by identify_siblings()
- * for Multi-Threading/Multi-Core capable CPUs
- */
- c->threads_per_core = c->cores_per_socket = c->num_log = 1;
- c->socket_id = -1;
-
- identify_siblings(c);
-
- if (c->threads_per_core > smp_num_siblings)
- smp_num_siblings = c->threads_per_core;
-#endif
- c->ppn = cpuid.field.ppn;
- c->number = cpuid.field.number;
- c->revision = cpuid.field.revision;
- c->model = cpuid.field.model;
- c->family = cpuid.field.family;
- c->archrev = cpuid.field.archrev;
- c->features = cpuid.field.features;
- c->model_name = get_model_name(c->family, c->model);
-
- status = ia64_pal_vm_summary(&vm1, &vm2);
- if (status == PAL_STATUS_SUCCESS) {
- impl_va_msb = vm2.pal_vm_info_2_s.impl_va_msb;
- phys_addr_size = vm1.pal_vm_info_1_s.phys_add_size;
- }
- c->unimpl_va_mask = ~((7L<<61) | ((1L << (impl_va_msb + 1)) - 1));
- c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1));
-}
-
-/*
- * Do the following calculations:
- *
- * 1. the max. cache line size.
- * 2. the minimum of the i-cache stride sizes for "flush_icache_range()".
- * 3. the minimum of the cache stride sizes for "clflush_cache_range()".
- */
-static void
-get_cache_info(void)
-{
- unsigned long line_size, max = 1;
- unsigned long l, levels, unique_caches;
- pal_cache_config_info_t cci;
- long status;
-
- status = ia64_pal_cache_summary(&levels, &unique_caches);
- if (status != 0) {
- printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n",
- __func__, status);
- max = SMP_CACHE_BYTES;
- /* Safest setup for "flush_icache_range()" */
- ia64_i_cache_stride_shift = I_CACHE_STRIDE_SHIFT;
- /* Safest setup for "clflush_cache_range()" */
- ia64_cache_stride_shift = CACHE_STRIDE_SHIFT;
- goto out;
- }
-
- for (l = 0; l < levels; ++l) {
- /* cache_type (data_or_unified)=2 */
- status = ia64_pal_cache_config_info(l, 2, &cci);
- if (status != 0) {
- printk(KERN_ERR "%s: ia64_pal_cache_config_info"
- "(l=%lu, 2) failed (status=%ld)\n",
- __func__, l, status);
- max = SMP_CACHE_BYTES;
- /* The safest setup for "flush_icache_range()" */
- cci.pcci_stride = I_CACHE_STRIDE_SHIFT;
- /* The safest setup for "clflush_cache_range()" */
- ia64_cache_stride_shift = CACHE_STRIDE_SHIFT;
- cci.pcci_unified = 1;
- } else {
- if (cci.pcci_stride < ia64_cache_stride_shift)
- ia64_cache_stride_shift = cci.pcci_stride;
-
- line_size = 1 << cci.pcci_line_size;
- if (line_size > max)
- max = line_size;
- }
-
- if (!cci.pcci_unified) {
- /* cache_type (instruction)=1*/
- status = ia64_pal_cache_config_info(l, 1, &cci);
- if (status != 0) {
- printk(KERN_ERR "%s: ia64_pal_cache_config_info"
- "(l=%lu, 1) failed (status=%ld)\n",
- __func__, l, status);
- /* The safest setup for flush_icache_range() */
- cci.pcci_stride = I_CACHE_STRIDE_SHIFT;
- }
- }
- if (cci.pcci_stride < ia64_i_cache_stride_shift)
- ia64_i_cache_stride_shift = cci.pcci_stride;
- }
- out:
- if (max > ia64_max_cacheline_size)
- ia64_max_cacheline_size = max;
-}
-
-/*
- * cpu_init() initializes state that is per-CPU. This function acts
- * as a 'CPU state barrier', nothing should get across.
- */
-void
-cpu_init (void)
-{
- extern void ia64_mmu_init(void *);
- static unsigned long max_num_phys_stacked = IA64_NUM_PHYS_STACK_REG;
- unsigned long num_phys_stacked;
- pal_vm_info_2_u_t vmi;
- unsigned int max_ctx;
- struct cpuinfo_ia64 *cpu_info;
- void *cpu_data;
-
- cpu_data = per_cpu_init();
-#ifdef CONFIG_SMP
- /*
- * insert boot cpu into sibling and core mapes
- * (must be done after per_cpu area is setup)
- */
- if (smp_processor_id() == 0) {
- cpumask_set_cpu(0, &per_cpu(cpu_sibling_map, 0));
- cpumask_set_cpu(0, &cpu_core_map[0]);
- } else {
- /*
- * Set ar.k3 so that assembly code in MCA handler can compute
- * physical addresses of per cpu variables with a simple:
- * phys = ar.k3 + &per_cpu_var
- * and the alt-dtlb-miss handler can set per-cpu mapping into
- * the TLB when needed. head.S already did this for cpu0.
- */
- ia64_set_kr(IA64_KR_PER_CPU_DATA,
- ia64_tpa(cpu_data) - (long) __per_cpu_start);
- }
-#endif
-
- get_cache_info();
-
- /*
- * We can't pass "local_cpu_data" to identify_cpu() because we haven't called
- * ia64_mmu_init() yet. And we can't call ia64_mmu_init() first because it
- * depends on the data returned by identify_cpu(). We break the dependency by
- * accessing cpu_data() through the canonical per-CPU address.
- */
- cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var(ia64_cpu_info) - __per_cpu_start);
- identify_cpu(cpu_info);
-
-#ifdef CONFIG_MCKINLEY
- {
-# define FEATURE_SET 16
- struct ia64_pal_retval iprv;
-
- if (cpu_info->family == 0x1f) {
- PAL_CALL_PHYS(iprv, PAL_PROC_GET_FEATURES, 0, FEATURE_SET, 0);
- if ((iprv.status == 0) && (iprv.v0 & 0x80) && (iprv.v2 & 0x80))
- PAL_CALL_PHYS(iprv, PAL_PROC_SET_FEATURES,
- (iprv.v1 | 0x80), FEATURE_SET, 0);
- }
- }
-#endif
-
- /* Clear the stack memory reserved for pt_regs: */
- memset(task_pt_regs(current), 0, sizeof(struct pt_regs));
-
- ia64_set_kr(IA64_KR_FPU_OWNER, 0);
-
- /*
- * Initialize the page-table base register to a global
- * directory with all zeroes. This ensure that we can handle
- * TLB-misses to user address-space even before we created the
- * first user address-space. This may happen, e.g., due to
- * aggressive use of lfetch.fault.
- */
- ia64_set_kr(IA64_KR_PT_BASE, __pa(ia64_imva(empty_zero_page)));
-
- /*
- * Initialize default control register to defer speculative faults except
- * for those arising from TLB misses, which are not deferred. The
- * kernel MUST NOT depend on a particular setting of these bits (in other words,
- * the kernel must have recovery code for all speculative accesses). Turn on
- * dcr.lc as per recommendation by the architecture team. Most IA-32 apps
- * shouldn't be affected by this (moral: keep your ia32 locks aligned and you'll
- * be fine).
- */
- ia64_setreg(_IA64_REG_CR_DCR, ( IA64_DCR_DP | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_DR
- | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC));
- mmgrab(&init_mm);
- current->active_mm = &init_mm;
- BUG_ON(current->mm);
-
- ia64_mmu_init(ia64_imva(cpu_data));
- ia64_mca_cpu_init(ia64_imva(cpu_data));
-
- /* Clear ITC to eliminate sched_clock() overflows in human time. */
- ia64_set_itc(0);
-
- /* disable all local interrupt sources: */
- ia64_set_itv(1 << 16);
- ia64_set_lrr0(1 << 16);
- ia64_set_lrr1(1 << 16);
- ia64_setreg(_IA64_REG_CR_PMV, 1 << 16);
- ia64_setreg(_IA64_REG_CR_CMCV, 1 << 16);
-
- /* clear TPR & XTP to enable all interrupt classes: */
- ia64_setreg(_IA64_REG_CR_TPR, 0);
-
- /* Clear any pending interrupts left by SAL/EFI */
- while (ia64_get_ivr() != IA64_SPURIOUS_INT_VECTOR)
- ia64_eoi();
-
-#ifdef CONFIG_SMP
- normal_xtp();
-#endif
-
- /* set ia64_ctx.max_rid to the maximum RID that is supported by all CPUs: */
- if (ia64_pal_vm_summary(NULL, &vmi) == 0) {
- max_ctx = (1U << (vmi.pal_vm_info_2_s.rid_size - 3)) - 1;
- setup_ptcg_sem(vmi.pal_vm_info_2_s.max_purges, NPTCG_FROM_PAL);
- } else {
- printk(KERN_WARNING "cpu_init: PAL VM summary failed, assuming 18 RID bits\n");
- max_ctx = (1U << 15) - 1; /* use architected minimum */
- }
- while (max_ctx < ia64_ctx.max_ctx) {
- unsigned int old = ia64_ctx.max_ctx;
- if (cmpxchg(&ia64_ctx.max_ctx, old, max_ctx) == old)
- break;
- }
-
- if (ia64_pal_rse_info(&num_phys_stacked, NULL) != 0) {
- printk(KERN_WARNING "cpu_init: PAL RSE info failed; assuming 96 physical "
- "stacked regs\n");
- num_phys_stacked = 96;
- }
- /* size of physical stacked register partition plus 8 bytes: */
- if (num_phys_stacked > max_num_phys_stacked) {
- ia64_patch_phys_stack_reg(num_phys_stacked*8 + 8);
- max_num_phys_stacked = num_phys_stacked;
- }
-}
-
-void __init arch_cpu_finalize_init(void)
-{
- ia64_patch_mckinley_e9((unsigned long) __start___mckinley_e9_bundles,
- (unsigned long) __end___mckinley_e9_bundles);
-}
-
-static int __init run_dmi_scan(void)
-{
- dmi_setup();
- return 0;
-}
-core_initcall(run_dmi_scan);
diff --git a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h
deleted file mode 100644
index 58a36ce6c26e..000000000000
--- a/arch/ia64/kernel/sigframe.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-struct sigscratch {
- unsigned long scratch_unat; /* ar.unat for the general registers saved in pt */
- unsigned long ar_pfs; /* for syscalls, the user-level function-state */
- struct pt_regs pt;
-};
-
-struct sigframe {
- /*
- * Place signal handler args where user-level unwinder can find them easily.
- * DO NOT MOVE THESE. They are part of the IA-64 Linux ABI and there is
- * user-level code that depends on their presence!
- */
- unsigned long arg0; /* signum */
- unsigned long arg1; /* siginfo pointer */
- unsigned long arg2; /* sigcontext pointer */
- /*
- * End of architected state.
- */
-
- void __user *handler; /* pointer to the plabel of the signal handler */
- struct siginfo info;
- struct sigcontext sc;
-};
-
-extern void ia64_do_signal (struct sigscratch *, long);
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
deleted file mode 100644
index 51cf6a7ec158..000000000000
--- a/arch/ia64/kernel/signal.c
+++ /dev/null
@@ -1,412 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Architecture-specific signal handling support.
- *
- * Copyright (C) 1999-2004 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * Derived from i386 and Alpha versions.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/ptrace.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/smp.h>
-#include <linux/stddef.h>
-#include <linux/tty.h>
-#include <linux/binfmts.h>
-#include <linux/unistd.h>
-#include <linux/wait.h>
-
-#include <asm/intrinsics.h>
-#include <linux/uaccess.h>
-#include <asm/rse.h>
-#include <asm/sigcontext.h>
-
-#include "sigframe.h"
-
-#define DEBUG_SIG 0
-#define STACK_ALIGN 16 /* minimal alignment for stack pointer */
-
-#if _NSIG_WORDS > 1
-# define PUT_SIGSET(k,u) __copy_to_user((u)->sig, (k)->sig, sizeof(sigset_t))
-# define GET_SIGSET(k,u) __copy_from_user((k)->sig, (u)->sig, sizeof(sigset_t))
-#else
-# define PUT_SIGSET(k,u) __put_user((k)->sig[0], &(u)->sig[0])
-# define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0])
-#endif
-
-static long
-restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
-{
- unsigned long ip, flags, nat, um, cfm, rsc;
- long err;
-
- /* Always make any pending restarted system calls return -EINTR */
- current->restart_block.fn = do_no_restart_syscall;
-
- /* restore scratch that always needs gets updated during signal delivery: */
- err = __get_user(flags, &sc->sc_flags);
- err |= __get_user(nat, &sc->sc_nat);
- err |= __get_user(ip, &sc->sc_ip); /* instruction pointer */
- err |= __get_user(cfm, &sc->sc_cfm);
- err |= __get_user(um, &sc->sc_um); /* user mask */
- err |= __get_user(rsc, &sc->sc_ar_rsc);
- err |= __get_user(scr->pt.ar_unat, &sc->sc_ar_unat);
- err |= __get_user(scr->pt.ar_fpsr, &sc->sc_ar_fpsr);
- err |= __get_user(scr->pt.ar_pfs, &sc->sc_ar_pfs);
- err |= __get_user(scr->pt.pr, &sc->sc_pr); /* predicates */
- err |= __get_user(scr->pt.b0, &sc->sc_br[0]); /* b0 (rp) */
- err |= __get_user(scr->pt.b6, &sc->sc_br[6]); /* b6 */
- err |= __copy_from_user(&scr->pt.r1, &sc->sc_gr[1], 8); /* r1 */
- err |= __copy_from_user(&scr->pt.r8, &sc->sc_gr[8], 4*8); /* r8-r11 */
- err |= __copy_from_user(&scr->pt.r12, &sc->sc_gr[12], 2*8); /* r12-r13 */
- err |= __copy_from_user(&scr->pt.r15, &sc->sc_gr[15], 8); /* r15 */
-
- scr->pt.cr_ifs = cfm | (1UL << 63);
- scr->pt.ar_rsc = rsc | (3 << 2); /* force PL3 */
-
- /* establish new instruction pointer: */
- scr->pt.cr_iip = ip & ~0x3UL;
- ia64_psr(&scr->pt)->ri = ip & 0x3;
- scr->pt.cr_ipsr = (scr->pt.cr_ipsr & ~IA64_PSR_UM) | (um & IA64_PSR_UM);
-
- scr->scratch_unat = ia64_put_scratch_nat_bits(&scr->pt, nat);
-
- if (!(flags & IA64_SC_FLAG_IN_SYSCALL)) {
- /* Restore most scratch-state only when not in syscall. */
- err |= __get_user(scr->pt.ar_ccv, &sc->sc_ar_ccv); /* ar.ccv */
- err |= __get_user(scr->pt.b7, &sc->sc_br[7]); /* b7 */
- err |= __get_user(scr->pt.r14, &sc->sc_gr[14]); /* r14 */
- err |= __copy_from_user(&scr->pt.ar_csd, &sc->sc_ar25, 2*8); /* ar.csd & ar.ssd */
- err |= __copy_from_user(&scr->pt.r2, &sc->sc_gr[2], 2*8); /* r2-r3 */
- err |= __copy_from_user(&scr->pt.r16, &sc->sc_gr[16], 16*8); /* r16-r31 */
- }
-
- if ((flags & IA64_SC_FLAG_FPH_VALID) != 0) {
- struct ia64_psr *psr = ia64_psr(&scr->pt);
-
- err |= __copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16);
- psr->mfh = 0; /* drop signal handler's fph contents... */
- preempt_disable();
- if (psr->dfh)
- ia64_drop_fpu(current);
- else {
- /* We already own the local fph, otherwise psr->dfh wouldn't be 0. */
- __ia64_load_fpu(current->thread.fph);
- ia64_set_local_fpu_owner(current);
- }
- preempt_enable();
- }
- return err;
-}
-
-long
-ia64_rt_sigreturn (struct sigscratch *scr)
-{
- extern char ia64_strace_leave_kernel, ia64_leave_kernel;
- struct sigcontext __user *sc;
- sigset_t set;
- long retval;
-
- sc = &((struct sigframe __user *) (scr->pt.r12 + 16))->sc;
-
- /*
- * When we return to the previously executing context, r8 and r10 have already
- * been setup the way we want them. Indeed, if the signal wasn't delivered while
- * in a system call, we must not touch r8 or r10 as otherwise user-level state
- * could be corrupted.
- */
- retval = (long) &ia64_leave_kernel;
- if (test_thread_flag(TIF_SYSCALL_TRACE)
- || test_thread_flag(TIF_SYSCALL_AUDIT))
- /*
- * strace expects to be notified after sigreturn returns even though the
- * context to which we return may not be in the middle of a syscall.
- * Thus, the return-value that strace displays for sigreturn is
- * meaningless.
- */
- retval = (long) &ia64_strace_leave_kernel;
-
- if (!access_ok(sc, sizeof(*sc)))
- goto give_sigsegv;
-
- if (GET_SIGSET(&set, &sc->sc_mask))
- goto give_sigsegv;
-
- set_current_blocked(&set);
-
- if (restore_sigcontext(sc, scr))
- goto give_sigsegv;
-
-#if DEBUG_SIG
- printk("SIG return (%s:%d): sp=%lx ip=%lx\n",
- current->comm, current->pid, scr->pt.r12, scr->pt.cr_iip);
-#endif
- if (restore_altstack(&sc->sc_stack))
- goto give_sigsegv;
- return retval;
-
- give_sigsegv:
- force_sig(SIGSEGV);
- return retval;
-}
-
-/*
- * This does just the minimum required setup of sigcontext.
- * Specifically, it only installs data that is either not knowable at
- * the user-level or that gets modified before execution in the
- * trampoline starts. Everything else is done at the user-level.
- */
-static long
-setup_sigcontext (struct sigcontext __user *sc, sigset_t *mask, struct sigscratch *scr)
-{
- unsigned long flags = 0, ifs, cfm, nat;
- long err = 0;
-
- ifs = scr->pt.cr_ifs;
-
- if (on_sig_stack((unsigned long) sc))
- flags |= IA64_SC_FLAG_ONSTACK;
- if ((ifs & (1UL << 63)) == 0)
- /* if cr_ifs doesn't have the valid bit set, we got here through a syscall */
- flags |= IA64_SC_FLAG_IN_SYSCALL;
- cfm = ifs & ((1UL << 38) - 1);
- ia64_flush_fph(current);
- if ((current->thread.flags & IA64_THREAD_FPH_VALID)) {
- flags |= IA64_SC_FLAG_FPH_VALID;
- err = __copy_to_user(&sc->sc_fr[32], current->thread.fph, 96*16);
- }
-
- nat = ia64_get_scratch_nat_bits(&scr->pt, scr->scratch_unat);
-
- err |= __put_user(flags, &sc->sc_flags);
- err |= __put_user(nat, &sc->sc_nat);
- err |= PUT_SIGSET(mask, &sc->sc_mask);
- err |= __put_user(cfm, &sc->sc_cfm);
- err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um);
- err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc);
- err |= __put_user(scr->pt.ar_unat, &sc->sc_ar_unat); /* ar.unat */
- err |= __put_user(scr->pt.ar_fpsr, &sc->sc_ar_fpsr); /* ar.fpsr */
- err |= __put_user(scr->pt.ar_pfs, &sc->sc_ar_pfs);
- err |= __put_user(scr->pt.pr, &sc->sc_pr); /* predicates */
- err |= __put_user(scr->pt.b0, &sc->sc_br[0]); /* b0 (rp) */
- err |= __put_user(scr->pt.b6, &sc->sc_br[6]); /* b6 */
- err |= __copy_to_user(&sc->sc_gr[1], &scr->pt.r1, 8); /* r1 */
- err |= __copy_to_user(&sc->sc_gr[8], &scr->pt.r8, 4*8); /* r8-r11 */
- err |= __copy_to_user(&sc->sc_gr[12], &scr->pt.r12, 2*8); /* r12-r13 */
- err |= __copy_to_user(&sc->sc_gr[15], &scr->pt.r15, 8); /* r15 */
- err |= __put_user(scr->pt.cr_iip + ia64_psr(&scr->pt)->ri, &sc->sc_ip);
-
- if (!(flags & IA64_SC_FLAG_IN_SYSCALL)) {
- /* Copy scratch regs to sigcontext if the signal didn't interrupt a syscall. */
- err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv); /* ar.ccv */
- err |= __put_user(scr->pt.b7, &sc->sc_br[7]); /* b7 */
- err |= __put_user(scr->pt.r14, &sc->sc_gr[14]); /* r14 */
- err |= __copy_to_user(&sc->sc_ar25, &scr->pt.ar_csd, 2*8); /* ar.csd & ar.ssd */
- err |= __copy_to_user(&sc->sc_gr[2], &scr->pt.r2, 2*8); /* r2-r3 */
- err |= __copy_to_user(&sc->sc_gr[16], &scr->pt.r16, 16*8); /* r16-r31 */
- }
- return err;
-}
-
-/*
- * Check whether the register-backing store is already on the signal stack.
- */
-static inline int
-rbs_on_sig_stack (unsigned long bsp)
-{
- return (bsp - current->sas_ss_sp < current->sas_ss_size);
-}
-
-static long
-setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr)
-{
- extern char __kernel_sigtramp[];
- unsigned long tramp_addr, new_rbs = 0, new_sp;
- struct sigframe __user *frame;
- long err;
-
- new_sp = scr->pt.r12;
- tramp_addr = (unsigned long) __kernel_sigtramp;
- if (ksig->ka.sa.sa_flags & SA_ONSTACK) {
- int onstack = sas_ss_flags(new_sp);
-
- if (onstack == 0) {
- new_sp = current->sas_ss_sp + current->sas_ss_size;
- /*
- * We need to check for the register stack being on the
- * signal stack separately, because it's switched
- * separately (memory stack is switched in the kernel,
- * register stack is switched in the signal trampoline).
- */
- if (!rbs_on_sig_stack(scr->pt.ar_bspstore))
- new_rbs = ALIGN(current->sas_ss_sp,
- sizeof(long));
- } else if (onstack == SS_ONSTACK) {
- unsigned long check_sp;
-
- /*
- * If we are on the alternate signal stack and would
- * overflow it, don't. Return an always-bogus address
- * instead so we will die with SIGSEGV.
- */
- check_sp = (new_sp - sizeof(*frame)) & -STACK_ALIGN;
- if (!likely(on_sig_stack(check_sp))) {
- force_sigsegv(ksig->sig);
- return 1;
- }
- }
- }
- frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN);
-
- if (!access_ok(frame, sizeof(*frame))) {
- force_sigsegv(ksig->sig);
- return 1;
- }
-
- err = __put_user(ksig->sig, &frame->arg0);
- err |= __put_user(&frame->info, &frame->arg1);
- err |= __put_user(&frame->sc, &frame->arg2);
- err |= __put_user(new_rbs, &frame->sc.sc_rbs_base);
- err |= __put_user(0, &frame->sc.sc_loadrs); /* initialize to zero */
- err |= __put_user(ksig->ka.sa.sa_handler, &frame->handler);
-
- err |= copy_siginfo_to_user(&frame->info, &ksig->info);
-
- err |= __save_altstack(&frame->sc.sc_stack, scr->pt.r12);
- err |= setup_sigcontext(&frame->sc, set, scr);
-
- if (unlikely(err)) {
- force_sigsegv(ksig->sig);
- return 1;
- }
-
- scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */
- scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */
- scr->pt.cr_iip = tramp_addr;
- ia64_psr(&scr->pt)->ri = 0; /* start executing in first slot */
- ia64_psr(&scr->pt)->be = 0; /* force little-endian byte-order */
- /*
- * Force the interruption function mask to zero. This has no effect when a
- * system-call got interrupted by a signal (since, in that case, scr->pt_cr_ifs is
- * ignored), but it has the desirable effect of making it possible to deliver a
- * signal with an incomplete register frame (which happens when a mandatory RSE
- * load faults). Furthermore, it has no negative effect on the getting the user's
- * dirty partition preserved, because that's governed by scr->pt.loadrs.
- */
- scr->pt.cr_ifs = (1UL << 63);
-
- /*
- * Note: this affects only the NaT bits of the scratch regs (the ones saved in
- * pt_regs), which is exactly what we want.
- */
- scr->scratch_unat = 0; /* ensure NaT bits of r12 is clear */
-
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sig=%d sp=%lx ip=%lx handler=%p\n",
- current->comm, current->pid, ksig->sig, scr->pt.r12, frame->sc.sc_ip, frame->handler);
-#endif
- return 0;
-}
-
-static long
-handle_signal (struct ksignal *ksig, struct sigscratch *scr)
-{
- int ret = setup_frame(ksig, sigmask_to_save(), scr);
-
- if (!ret)
- signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
-
- return ret;
-}
-
-/*
- * Note that `init' is a special process: it doesn't get signals it doesn't want to
- * handle. Thus you cannot kill init even with a SIGKILL even by mistake.
- */
-void
-ia64_do_signal (struct sigscratch *scr, long in_syscall)
-{
- long restart = in_syscall;
- long errno = scr->pt.r8;
- struct ksignal ksig;
-
- /*
- * This only loops in the rare cases of handle_signal() failing, in which case we
- * need to push through a forced SIGSEGV.
- */
- while (1) {
- if (!get_signal(&ksig))
- break;
-
- /*
- * get_signal() may have run a debugger (via notify_parent())
- * and the debugger may have modified the state (e.g., to arrange for an
- * inferior call), thus it's important to check for restarting _after_
- * get_signal().
- */
- if ((long) scr->pt.r10 != -1)
- /*
- * A system calls has to be restarted only if one of the error codes
- * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned. If r10
- * isn't -1 then r8 doesn't hold an error code and we don't need to
- * restart the syscall, so we can clear the "restart" flag here.
- */
- restart = 0;
-
- if (ksig.sig <= 0)
- break;
-
- if (unlikely(restart)) {
- switch (errno) {
- case ERESTART_RESTARTBLOCK:
- case ERESTARTNOHAND:
- scr->pt.r8 = EINTR;
- /* note: scr->pt.r10 is already -1 */
- break;
- case ERESTARTSYS:
- if ((ksig.ka.sa.sa_flags & SA_RESTART) == 0) {
- scr->pt.r8 = EINTR;
- /* note: scr->pt.r10 is already -1 */
- break;
- }
- fallthrough;
- case ERESTARTNOINTR:
- ia64_decrement_ip(&scr->pt);
- restart = 0; /* don't restart twice if handle_signal() fails... */
- }
- }
-
- /*
- * Whee! Actually deliver the signal. If the delivery failed, we need to
- * continue to iterate in this loop so we can deliver the SIGSEGV...
- */
- if (handle_signal(&ksig, scr))
- return;
- }
-
- /* Did we come from a system call? */
- if (restart) {
- /* Restart the system call - no handlers present */
- if (errno == ERESTARTNOHAND || errno == ERESTARTSYS || errno == ERESTARTNOINTR
- || errno == ERESTART_RESTARTBLOCK)
- {
- /*
- * Note: the syscall number is in r15 which is saved in
- * pt_regs so all we need to do here is adjust ip so that
- * the "break" instruction gets re-executed.
- */
- ia64_decrement_ip(&scr->pt);
- if (errno == ERESTART_RESTARTBLOCK)
- scr->pt.r15 = __NR_restart_syscall;
- }
- }
-
- /* if there's no signal to deliver, we just put the saved sigmask
- * back */
- restore_saved_sigmask();
-}
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
deleted file mode 100644
index ea4f009a232b..000000000000
--- a/arch/ia64/kernel/smp.c
+++ /dev/null
@@ -1,335 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * SMP Support
- *
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999, 2001, 2003 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * Lots of stuff stolen from arch/alpha/kernel/smp.c
- *
- * 01/05/16 Rohit Seth <rohit.seth@intel.com> IA64-SMP functions. Reorganized
- * the existing code (on the lines of x86 port).
- * 00/09/11 David Mosberger <davidm@hpl.hp.com> Do loops_per_jiffy
- * calibration on each CPU.
- * 00/08/23 Asit Mallick <asit.k.mallick@intel.com> fixed logical processor id
- * 00/03/31 Rohit Seth <rohit.seth@intel.com> Fixes for Bootstrap Processor
- * & cpu_online_map now gets done here (instead of setup.c)
- * 99/10/05 davidm Update to bring it in sync with new command-line processing
- * scheme.
- * 10/13/00 Goutham Rao <goutham.rao@intel.com> Updated smp_call_function and
- * smp_call_function_single to resend IPI on timeouts
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/smp.h>
-#include <linux/kernel_stat.h>
-#include <linux/mm.h>
-#include <linux/cache.h>
-#include <linux/delay.h>
-#include <linux/efi.h>
-#include <linux/bitops.h>
-#include <linux/kexec.h>
-
-#include <linux/atomic.h>
-#include <asm/current.h>
-#include <asm/delay.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/sal.h>
-#include <asm/tlbflush.h>
-#include <asm/unistd.h>
-#include <asm/mca.h>
-#include <asm/xtp.h>
-
-/*
- * Note: alignment of 4 entries/cacheline was empirically determined
- * to be a good tradeoff between hot cachelines & spreading the array
- * across too many cacheline.
- */
-static struct local_tlb_flush_counts {
- unsigned int count;
-} __attribute__((__aligned__(32))) local_tlb_flush_counts[NR_CPUS];
-
-static DEFINE_PER_CPU_SHARED_ALIGNED(unsigned short [NR_CPUS],
- shadow_flush_counts);
-
-#define IPI_CALL_FUNC 0
-#define IPI_CPU_STOP 1
-#define IPI_CALL_FUNC_SINGLE 2
-#define IPI_KDUMP_CPU_STOP 3
-
-/* This needs to be cacheline aligned because it is written to by *other* CPUs. */
-static DEFINE_PER_CPU_SHARED_ALIGNED(unsigned long, ipi_operation);
-
-extern void cpu_halt (void);
-
-static void
-stop_this_cpu(void)
-{
- /*
- * Remove this CPU:
- */
- set_cpu_online(smp_processor_id(), false);
- max_xtp();
- local_irq_disable();
- cpu_halt();
-}
-
-void
-cpu_die(void)
-{
- max_xtp();
- local_irq_disable();
- cpu_halt();
- /* Should never be here */
- BUG();
- for (;;);
-}
-
-irqreturn_t
-handle_IPI (int irq, void *dev_id)
-{
- int this_cpu = get_cpu();
- unsigned long *pending_ipis = &__ia64_per_cpu_var(ipi_operation);
- unsigned long ops;
-
- mb(); /* Order interrupt and bit testing. */
- while ((ops = xchg(pending_ipis, 0)) != 0) {
- mb(); /* Order bit clearing and data access. */
- do {
- unsigned long which;
-
- which = ffz(~ops);
- ops &= ~(1 << which);
-
- switch (which) {
- case IPI_CPU_STOP:
- stop_this_cpu();
- break;
- case IPI_CALL_FUNC:
- generic_smp_call_function_interrupt();
- break;
- case IPI_CALL_FUNC_SINGLE:
- generic_smp_call_function_single_interrupt();
- break;
-#ifdef CONFIG_KEXEC
- case IPI_KDUMP_CPU_STOP:
- unw_init_running(kdump_cpu_freeze, NULL);
- break;
-#endif
- default:
- printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n",
- this_cpu, which);
- break;
- }
- } while (ops);
- mb(); /* Order data access and bit testing. */
- }
- put_cpu();
- return IRQ_HANDLED;
-}
-
-
-
-/*
- * Called with preemption disabled.
- */
-static inline void
-send_IPI_single (int dest_cpu, int op)
-{
- set_bit(op, &per_cpu(ipi_operation, dest_cpu));
- ia64_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0);
-}
-
-/*
- * Called with preemption disabled.
- */
-static inline void
-send_IPI_allbutself (int op)
-{
- unsigned int i;
-
- for_each_online_cpu(i) {
- if (i != smp_processor_id())
- send_IPI_single(i, op);
- }
-}
-
-/*
- * Called with preemption disabled.
- */
-static inline void
-send_IPI_mask(const struct cpumask *mask, int op)
-{
- unsigned int cpu;
-
- for_each_cpu(cpu, mask) {
- send_IPI_single(cpu, op);
- }
-}
-
-/*
- * Called with preemption disabled.
- */
-static inline void
-send_IPI_all (int op)
-{
- int i;
-
- for_each_online_cpu(i) {
- send_IPI_single(i, op);
- }
-}
-
-/*
- * Called with preemption disabled.
- */
-static inline void
-send_IPI_self (int op)
-{
- send_IPI_single(smp_processor_id(), op);
-}
-
-#ifdef CONFIG_KEXEC
-void
-kdump_smp_send_stop(void)
-{
- send_IPI_allbutself(IPI_KDUMP_CPU_STOP);
-}
-
-void
-kdump_smp_send_init(void)
-{
- unsigned int cpu, self_cpu;
- self_cpu = smp_processor_id();
- for_each_online_cpu(cpu) {
- if (cpu != self_cpu) {
- if(kdump_status[cpu] == 0)
- ia64_send_ipi(cpu, 0, IA64_IPI_DM_INIT, 0);
- }
- }
-}
-#endif
-/*
- * Called with preemption disabled.
- */
-void
-arch_smp_send_reschedule (int cpu)
-{
- ia64_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
-}
-EXPORT_SYMBOL_GPL(arch_smp_send_reschedule);
-
-/*
- * Called with preemption disabled.
- */
-static void
-smp_send_local_flush_tlb (int cpu)
-{
- ia64_send_ipi(cpu, IA64_IPI_LOCAL_TLB_FLUSH, IA64_IPI_DM_INT, 0);
-}
-
-void
-smp_local_flush_tlb(void)
-{
- /*
- * Use atomic ops. Otherwise, the load/increment/store sequence from
- * a "++" operation can have the line stolen between the load & store.
- * The overhead of the atomic op in negligible in this case & offers
- * significant benefit for the brief periods where lots of cpus
- * are simultaneously flushing TLBs.
- */
- ia64_fetchadd(1, &local_tlb_flush_counts[smp_processor_id()].count, acq);
- local_flush_tlb_all();
-}
-
-#define FLUSH_DELAY 5 /* Usec backoff to eliminate excessive cacheline bouncing */
-
-void
-smp_flush_tlb_cpumask(cpumask_t xcpumask)
-{
- unsigned short *counts = __ia64_per_cpu_var(shadow_flush_counts);
- cpumask_t cpumask = xcpumask;
- int mycpu, cpu, flush_mycpu = 0;
-
- preempt_disable();
- mycpu = smp_processor_id();
-
- for_each_cpu(cpu, &cpumask)
- counts[cpu] = local_tlb_flush_counts[cpu].count & 0xffff;
-
- mb();
- for_each_cpu(cpu, &cpumask) {
- if (cpu == mycpu)
- flush_mycpu = 1;
- else
- smp_send_local_flush_tlb(cpu);
- }
-
- if (flush_mycpu)
- smp_local_flush_tlb();
-
- for_each_cpu(cpu, &cpumask)
- while(counts[cpu] == (local_tlb_flush_counts[cpu].count & 0xffff))
- udelay(FLUSH_DELAY);
-
- preempt_enable();
-}
-
-void
-smp_flush_tlb_all (void)
-{
- on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1);
-}
-
-void
-smp_flush_tlb_mm (struct mm_struct *mm)
-{
- cpumask_var_t cpus;
- preempt_disable();
- /* this happens for the common case of a single-threaded fork(): */
- if (likely(mm == current->active_mm && atomic_read(&mm->mm_users) == 1))
- {
- local_finish_flush_tlb_mm(mm);
- preempt_enable();
- return;
- }
- if (!alloc_cpumask_var(&cpus, GFP_ATOMIC)) {
- smp_call_function((void (*)(void *))local_finish_flush_tlb_mm,
- mm, 1);
- } else {
- cpumask_copy(cpus, mm_cpumask(mm));
- smp_call_function_many(cpus,
- (void (*)(void *))local_finish_flush_tlb_mm, mm, 1);
- free_cpumask_var(cpus);
- }
- local_irq_disable();
- local_finish_flush_tlb_mm(mm);
- local_irq_enable();
- preempt_enable();
-}
-
-void arch_send_call_function_single_ipi(int cpu)
-{
- send_IPI_single(cpu, IPI_CALL_FUNC_SINGLE);
-}
-
-void arch_send_call_function_ipi_mask(const struct cpumask *mask)
-{
- send_IPI_mask(mask, IPI_CALL_FUNC);
-}
-
-/*
- * this function calls the 'stop' function on all other CPUs in the system.
- */
-void
-smp_send_stop (void)
-{
- send_IPI_allbutself(IPI_CPU_STOP);
-}
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
deleted file mode 100644
index d0e935cf2093..000000000000
--- a/arch/ia64/kernel/smpboot.c
+++ /dev/null
@@ -1,839 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * SMP boot-related support
- *
- * Copyright (C) 1998-2003, 2005 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2001, 2004-2005 Intel Corp
- * Rohit Seth <rohit.seth@intel.com>
- * Suresh Siddha <suresh.b.siddha@intel.com>
- * Gordon Jin <gordon.jin@intel.com>
- * Ashok Raj <ashok.raj@intel.com>
- *
- * 01/05/16 Rohit Seth <rohit.seth@intel.com> Moved SMP booting functions from smp.c to here.
- * 01/04/27 David Mosberger <davidm@hpl.hp.com> Added ITC synching code.
- * 02/07/31 David Mosberger <davidm@hpl.hp.com> Switch over to hotplug-CPU boot-sequence.
- * smp_boot_cpus()/smp_commence() is replaced by
- * smp_prepare_cpus()/__cpu_up()/smp_cpus_done().
- * 04/06/21 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support
- * 04/12/26 Jin Gordon <gordon.jin@intel.com>
- * 04/12/26 Rohit Seth <rohit.seth@intel.com>
- * Add multi-threading and multi-core detection
- * 05/01/30 Suresh Siddha <suresh.b.siddha@intel.com>
- * Setup cpu_sibling_map and cpu_core_map
- */
-
-#include <linux/module.h>
-#include <linux/acpi.h>
-#include <linux/memblock.h>
-#include <linux/cpu.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/kernel_stat.h>
-#include <linux/mm.h>
-#include <linux/notifier.h>
-#include <linux/smp.h>
-#include <linux/spinlock.h>
-#include <linux/efi.h>
-#include <linux/percpu.h>
-#include <linux/bitops.h>
-
-#include <linux/atomic.h>
-#include <asm/cache.h>
-#include <asm/current.h>
-#include <asm/delay.h>
-#include <asm/efi.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mca.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/sal.h>
-#include <asm/tlbflush.h>
-#include <asm/unistd.h>
-
-#define SMP_DEBUG 0
-
-#if SMP_DEBUG
-#define Dprintk(x...) printk(x)
-#else
-#define Dprintk(x...)
-#endif
-
-#ifdef CONFIG_HOTPLUG_CPU
-#ifdef CONFIG_PERMIT_BSP_REMOVE
-#define bsp_remove_ok 1
-#else
-#define bsp_remove_ok 0
-#endif
-
-/*
- * Global array allocated for NR_CPUS at boot time
- */
-struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS];
-
-/*
- * start_ap in head.S uses this to store current booting cpu
- * info.
- */
-struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0];
-
-#define set_brendez_area(x) (sal_state_for_booting_cpu = &sal_boot_rendez_state[(x)]);
-
-#else
-#define set_brendez_area(x)
-#endif
-
-
-/*
- * ITC synchronization related stuff:
- */
-#define MASTER (0)
-#define SLAVE (SMP_CACHE_BYTES/8)
-
-#define NUM_ROUNDS 64 /* magic value */
-#define NUM_ITERS 5 /* likewise */
-
-static DEFINE_SPINLOCK(itc_sync_lock);
-static volatile unsigned long go[SLAVE + 1];
-
-#define DEBUG_ITC_SYNC 0
-
-extern void start_ap (void);
-extern unsigned long ia64_iobase;
-
-struct task_struct *task_for_booting_cpu;
-
-/*
- * State for each CPU
- */
-DEFINE_PER_CPU(int, cpu_state);
-
-cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(cpu_core_map);
-DEFINE_PER_CPU_SHARED_ALIGNED(cpumask_t, cpu_sibling_map);
-EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
-
-int smp_num_siblings = 1;
-
-/* which logical CPU number maps to which CPU (physical APIC ID) */
-volatile int ia64_cpu_to_sapicid[NR_CPUS];
-EXPORT_SYMBOL(ia64_cpu_to_sapicid);
-
-static cpumask_t cpu_callin_map;
-
-struct smp_boot_data smp_boot_data __initdata;
-
-unsigned long ap_wakeup_vector = -1; /* External Int use to wakeup APs */
-
-char __initdata no_int_routing;
-
-unsigned char smp_int_redirect; /* are INT and IPI redirectable by the chipset? */
-
-#ifdef CONFIG_FORCE_CPEI_RETARGET
-#define CPEI_OVERRIDE_DEFAULT (1)
-#else
-#define CPEI_OVERRIDE_DEFAULT (0)
-#endif
-
-unsigned int force_cpei_retarget = CPEI_OVERRIDE_DEFAULT;
-
-static int __init
-cmdl_force_cpei(char *str)
-{
- int value=0;
-
- get_option (&str, &value);
- force_cpei_retarget = value;
-
- return 1;
-}
-
-__setup("force_cpei=", cmdl_force_cpei);
-
-static int __init
-nointroute (char *str)
-{
- no_int_routing = 1;
- printk ("no_int_routing on\n");
- return 1;
-}
-
-__setup("nointroute", nointroute);
-
-static void fix_b0_for_bsp(void)
-{
-#ifdef CONFIG_HOTPLUG_CPU
- int cpuid;
- static int fix_bsp_b0 = 1;
-
- cpuid = smp_processor_id();
-
- /*
- * Cache the b0 value on the first AP that comes up
- */
- if (!(fix_bsp_b0 && cpuid))
- return;
-
- sal_boot_rendez_state[0].br[0] = sal_boot_rendez_state[cpuid].br[0];
- printk ("Fixed BSP b0 value from CPU %d\n", cpuid);
-
- fix_bsp_b0 = 0;
-#endif
-}
-
-void
-sync_master (void *arg)
-{
- unsigned long flags, i;
-
- go[MASTER] = 0;
-
- local_irq_save(flags);
- {
- for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
- while (!go[MASTER])
- cpu_relax();
- go[MASTER] = 0;
- go[SLAVE] = ia64_get_itc();
- }
- }
- local_irq_restore(flags);
-}
-
-/*
- * Return the number of cycles by which our itc differs from the itc on the master
- * (time-keeper) CPU. A positive number indicates our itc is ahead of the master,
- * negative that it is behind.
- */
-static inline long
-get_delta (long *rt, long *master)
-{
- unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
- unsigned long tcenter, t0, t1, tm;
- long i;
-
- for (i = 0; i < NUM_ITERS; ++i) {
- t0 = ia64_get_itc();
- go[MASTER] = 1;
- while (!(tm = go[SLAVE]))
- cpu_relax();
- go[SLAVE] = 0;
- t1 = ia64_get_itc();
-
- if (t1 - t0 < best_t1 - best_t0)
- best_t0 = t0, best_t1 = t1, best_tm = tm;
- }
-
- *rt = best_t1 - best_t0;
- *master = best_tm - best_t0;
-
- /* average best_t0 and best_t1 without overflow: */
- tcenter = (best_t0/2 + best_t1/2);
- if (best_t0 % 2 + best_t1 % 2 == 2)
- ++tcenter;
- return tcenter - best_tm;
-}
-
-/*
- * Synchronize ar.itc of the current (slave) CPU with the ar.itc of the MASTER CPU
- * (normally the time-keeper CPU). We use a closed loop to eliminate the possibility of
- * unaccounted-for errors (such as getting a machine check in the middle of a calibration
- * step). The basic idea is for the slave to ask the master what itc value it has and to
- * read its own itc before and after the master responds. Each iteration gives us three
- * timestamps:
- *
- * slave master
- *
- * t0 ---\
- * ---\
- * --->
- * tm
- * /---
- * /---
- * t1 <---
- *
- *
- * The goal is to adjust the slave's ar.itc such that tm falls exactly half-way between t0
- * and t1. If we achieve this, the clocks are synchronized provided the interconnect
- * between the slave and the master is symmetric. Even if the interconnect were
- * asymmetric, we would still know that the synchronization error is smaller than the
- * roundtrip latency (t0 - t1).
- *
- * When the interconnect is quiet and symmetric, this lets us synchronize the itc to
- * within one or two cycles. However, we can only *guarantee* that the synchronization is
- * accurate to within a round-trip time, which is typically in the range of several
- * hundred cycles (e.g., ~500 cycles). In practice, this means that the itc's are usually
- * almost perfectly synchronized, but we shouldn't assume that the accuracy is much better
- * than half a micro second or so.
- */
-void
-ia64_sync_itc (unsigned int master)
-{
- long i, delta, adj, adjust_latency = 0, done = 0;
- unsigned long flags, rt, master_time_stamp, bound;
-#if DEBUG_ITC_SYNC
- struct {
- long rt; /* roundtrip time */
- long master; /* master's timestamp */
- long diff; /* difference between midpoint and master's timestamp */
- long lat; /* estimate of itc adjustment latency */
- } t[NUM_ROUNDS];
-#endif
-
- /*
- * Make sure local timer ticks are disabled while we sync. If
- * they were enabled, we'd have to worry about nasty issues
- * like setting the ITC ahead of (or a long time before) the
- * next scheduled tick.
- */
- BUG_ON((ia64_get_itv() & (1 << 16)) == 0);
-
- go[MASTER] = 1;
-
- if (smp_call_function_single(master, sync_master, NULL, 0) < 0) {
- printk(KERN_ERR "sync_itc: failed to get attention of CPU %u!\n", master);
- return;
- }
-
- while (go[MASTER])
- cpu_relax(); /* wait for master to be ready */
-
- spin_lock_irqsave(&itc_sync_lock, flags);
- {
- for (i = 0; i < NUM_ROUNDS; ++i) {
- delta = get_delta(&rt, &master_time_stamp);
- if (delta == 0) {
- done = 1; /* let's lock on to this... */
- bound = rt;
- }
-
- if (!done) {
- if (i > 0) {
- adjust_latency += -delta;
- adj = -delta + adjust_latency/4;
- } else
- adj = -delta;
-
- ia64_set_itc(ia64_get_itc() + adj);
- }
-#if DEBUG_ITC_SYNC
- t[i].rt = rt;
- t[i].master = master_time_stamp;
- t[i].diff = delta;
- t[i].lat = adjust_latency/4;
-#endif
- }
- }
- spin_unlock_irqrestore(&itc_sync_lock, flags);
-
-#if DEBUG_ITC_SYNC
- for (i = 0; i < NUM_ROUNDS; ++i)
- printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
- t[i].rt, t[i].master, t[i].diff, t[i].lat);
-#endif
-
- printk(KERN_INFO "CPU %d: synchronized ITC with CPU %u (last diff %ld cycles, "
- "maxerr %lu cycles)\n", smp_processor_id(), master, delta, rt);
-}
-
-/*
- * Ideally sets up per-cpu profiling hooks. Doesn't do much now...
- */
-static inline void smp_setup_percpu_timer(void)
-{
-}
-
-static void
-smp_callin (void)
-{
- int cpuid, phys_id, itc_master;
- struct cpuinfo_ia64 *last_cpuinfo, *this_cpuinfo;
- extern void ia64_init_itm(void);
- extern volatile int time_keeper_id;
-
- cpuid = smp_processor_id();
- phys_id = hard_smp_processor_id();
- itc_master = time_keeper_id;
-
- if (cpu_online(cpuid)) {
- printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n",
- phys_id, cpuid);
- BUG();
- }
-
- fix_b0_for_bsp();
-
- /*
- * numa_node_id() works after this.
- */
- set_numa_node(cpu_to_node_map[cpuid]);
- set_numa_mem(local_memory_node(cpu_to_node_map[cpuid]));
-
- spin_lock(&vector_lock);
- /* Setup the per cpu irq handling data structures */
- __setup_vector_irq(cpuid);
- notify_cpu_starting(cpuid);
- set_cpu_online(cpuid, true);
- per_cpu(cpu_state, cpuid) = CPU_ONLINE;
- spin_unlock(&vector_lock);
-
- smp_setup_percpu_timer();
-
- ia64_mca_cmc_vector_setup(); /* Setup vector on AP */
-
- local_irq_enable();
-
- if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
- /*
- * Synchronize the ITC with the BP. Need to do this after irqs are
- * enabled because ia64_sync_itc() calls smp_call_function_single(), which
- * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls
- * local_bh_enable(), which bugs out if irqs are not enabled...
- */
- Dprintk("Going to syncup ITC with ITC Master.\n");
- ia64_sync_itc(itc_master);
- }
-
- /*
- * Get our bogomips.
- */
- ia64_init_itm();
-
- /*
- * Delay calibration can be skipped if new processor is identical to the
- * previous processor.
- */
- last_cpuinfo = cpu_data(cpuid - 1);
- this_cpuinfo = local_cpu_data;
- if (last_cpuinfo->itc_freq != this_cpuinfo->itc_freq ||
- last_cpuinfo->proc_freq != this_cpuinfo->proc_freq ||
- last_cpuinfo->features != this_cpuinfo->features ||
- last_cpuinfo->revision != this_cpuinfo->revision ||
- last_cpuinfo->family != this_cpuinfo->family ||
- last_cpuinfo->archrev != this_cpuinfo->archrev ||
- last_cpuinfo->model != this_cpuinfo->model)
- calibrate_delay();
- local_cpu_data->loops_per_jiffy = loops_per_jiffy;
-
- /*
- * Allow the master to continue.
- */
- cpumask_set_cpu(cpuid, &cpu_callin_map);
- Dprintk("Stack on CPU %d at about %p\n",cpuid, &cpuid);
-}
-
-
-/*
- * Activate a secondary processor. head.S calls this.
- */
-int
-start_secondary (void *unused)
-{
- /* Early console may use I/O ports */
- ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
-#ifndef CONFIG_PRINTK_TIME
- Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
-#endif
- efi_map_pal_code();
- cpu_init();
- smp_callin();
-
- cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
- return 0;
-}
-
-static int
-do_boot_cpu (int sapicid, int cpu, struct task_struct *idle)
-{
- int timeout;
-
- task_for_booting_cpu = idle;
- Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
-
- set_brendez_area(cpu);
- ia64_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
-
- /*
- * Wait 10s total for the AP to start
- */
- Dprintk("Waiting on callin_map ...");
- for (timeout = 0; timeout < 100000; timeout++) {
- if (cpumask_test_cpu(cpu, &cpu_callin_map))
- break; /* It has booted */
- barrier(); /* Make sure we re-read cpu_callin_map */
- udelay(100);
- }
- Dprintk("\n");
-
- if (!cpumask_test_cpu(cpu, &cpu_callin_map)) {
- printk(KERN_ERR "Processor 0x%x/0x%x is stuck.\n", cpu, sapicid);
- ia64_cpu_to_sapicid[cpu] = -1;
- set_cpu_online(cpu, false); /* was set in smp_callin() */
- return -EINVAL;
- }
- return 0;
-}
-
-static int __init
-decay (char *str)
-{
- int ticks;
- get_option (&str, &ticks);
- return 1;
-}
-
-__setup("decay=", decay);
-
-/*
- * Initialize the logical CPU number to SAPICID mapping
- */
-void __init
-smp_build_cpu_map (void)
-{
- int sapicid, cpu, i;
- int boot_cpu_id = hard_smp_processor_id();
-
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- ia64_cpu_to_sapicid[cpu] = -1;
- }
-
- ia64_cpu_to_sapicid[0] = boot_cpu_id;
- init_cpu_present(cpumask_of(0));
- set_cpu_possible(0, true);
- for (cpu = 1, i = 0; i < smp_boot_data.cpu_count; i++) {
- sapicid = smp_boot_data.cpu_phys_id[i];
- if (sapicid == boot_cpu_id)
- continue;
- set_cpu_present(cpu, true);
- set_cpu_possible(cpu, true);
- ia64_cpu_to_sapicid[cpu] = sapicid;
- cpu++;
- }
-}
-
-/*
- * Cycle through the APs sending Wakeup IPIs to boot each.
- */
-void __init
-smp_prepare_cpus (unsigned int max_cpus)
-{
- int boot_cpu_id = hard_smp_processor_id();
-
- /*
- * Initialize the per-CPU profiling counter/multiplier
- */
-
- smp_setup_percpu_timer();
-
- cpumask_set_cpu(0, &cpu_callin_map);
-
- local_cpu_data->loops_per_jiffy = loops_per_jiffy;
- ia64_cpu_to_sapicid[0] = boot_cpu_id;
-
- printk(KERN_INFO "Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id);
-
- current_thread_info()->cpu = 0;
-
- /*
- * If SMP should be disabled, then really disable it!
- */
- if (!max_cpus) {
- printk(KERN_INFO "SMP mode deactivated.\n");
- init_cpu_online(cpumask_of(0));
- init_cpu_present(cpumask_of(0));
- init_cpu_possible(cpumask_of(0));
- return;
- }
-}
-
-void smp_prepare_boot_cpu(void)
-{
- set_cpu_online(smp_processor_id(), true);
- cpumask_set_cpu(smp_processor_id(), &cpu_callin_map);
- set_numa_node(cpu_to_node_map[smp_processor_id()]);
- per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-static inline void
-clear_cpu_sibling_map(int cpu)
-{
- int i;
-
- for_each_cpu(i, &per_cpu(cpu_sibling_map, cpu))
- cpumask_clear_cpu(cpu, &per_cpu(cpu_sibling_map, i));
- for_each_cpu(i, &cpu_core_map[cpu])
- cpumask_clear_cpu(cpu, &cpu_core_map[i]);
-
- per_cpu(cpu_sibling_map, cpu) = cpu_core_map[cpu] = CPU_MASK_NONE;
-}
-
-static void
-remove_siblinginfo(int cpu)
-{
- if (cpu_data(cpu)->threads_per_core == 1 &&
- cpu_data(cpu)->cores_per_socket == 1) {
- cpumask_clear_cpu(cpu, &cpu_core_map[cpu]);
- cpumask_clear_cpu(cpu, &per_cpu(cpu_sibling_map, cpu));
- return;
- }
-
- /* remove it from all sibling map's */
- clear_cpu_sibling_map(cpu);
-}
-
-extern void fixup_irqs(void);
-
-int migrate_platform_irqs(unsigned int cpu)
-{
- int new_cpei_cpu;
- struct irq_data *data = NULL;
- const struct cpumask *mask;
- int retval = 0;
-
- /*
- * dont permit CPEI target to removed.
- */
- if (cpe_vector > 0 && is_cpu_cpei_target(cpu)) {
- printk ("CPU (%d) is CPEI Target\n", cpu);
- if (can_cpei_retarget()) {
- /*
- * Now re-target the CPEI to a different processor
- */
- new_cpei_cpu = cpumask_any(cpu_online_mask);
- mask = cpumask_of(new_cpei_cpu);
- set_cpei_target_cpu(new_cpei_cpu);
- data = irq_get_irq_data(ia64_cpe_irq);
- /*
- * Switch for now, immediately, we need to do fake intr
- * as other interrupts, but need to study CPEI behaviour with
- * polling before making changes.
- */
- if (data && data->chip) {
- data->chip->irq_disable(data);
- data->chip->irq_set_affinity(data, mask, false);
- data->chip->irq_enable(data);
- printk ("Re-targeting CPEI to cpu %d\n", new_cpei_cpu);
- }
- }
- if (!data) {
- printk ("Unable to retarget CPEI, offline cpu [%d] failed\n", cpu);
- retval = -EBUSY;
- }
- }
- return retval;
-}
-
-/* must be called with cpucontrol mutex held */
-int __cpu_disable(void)
-{
- int cpu = smp_processor_id();
-
- /*
- * dont permit boot processor for now
- */
- if (cpu == 0 && !bsp_remove_ok) {
- printk ("Your platform does not support removal of BSP\n");
- return (-EBUSY);
- }
-
- set_cpu_online(cpu, false);
-
- if (migrate_platform_irqs(cpu)) {
- set_cpu_online(cpu, true);
- return -EBUSY;
- }
-
- remove_siblinginfo(cpu);
- fixup_irqs();
- local_flush_tlb_all();
- cpumask_clear_cpu(cpu, &cpu_callin_map);
- return 0;
-}
-
-void __cpu_die(unsigned int cpu)
-{
- unsigned int i;
-
- for (i = 0; i < 100; i++) {
- /* They ack this in play_dead by setting CPU_DEAD */
- if (per_cpu(cpu_state, cpu) == CPU_DEAD)
- {
- printk ("CPU %d is now offline\n", cpu);
- return;
- }
- msleep(100);
- }
- printk(KERN_ERR "CPU %u didn't die...\n", cpu);
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
-void
-smp_cpus_done (unsigned int dummy)
-{
- int cpu;
- unsigned long bogosum = 0;
-
- /*
- * Allow the user to impress friends.
- */
-
- for_each_online_cpu(cpu) {
- bogosum += cpu_data(cpu)->loops_per_jiffy;
- }
-
- printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
- (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
-}
-
-static inline void set_cpu_sibling_map(int cpu)
-{
- int i;
-
- for_each_online_cpu(i) {
- if ((cpu_data(cpu)->socket_id == cpu_data(i)->socket_id)) {
- cpumask_set_cpu(i, &cpu_core_map[cpu]);
- cpumask_set_cpu(cpu, &cpu_core_map[i]);
- if (cpu_data(cpu)->core_id == cpu_data(i)->core_id) {
- cpumask_set_cpu(i,
- &per_cpu(cpu_sibling_map, cpu));
- cpumask_set_cpu(cpu,
- &per_cpu(cpu_sibling_map, i));
- }
- }
- }
-}
-
-int
-__cpu_up(unsigned int cpu, struct task_struct *tidle)
-{
- int ret;
- int sapicid;
-
- sapicid = ia64_cpu_to_sapicid[cpu];
- if (sapicid == -1)
- return -EINVAL;
-
- /*
- * Already booted cpu? not valid anymore since we dont
- * do idle loop tightspin anymore.
- */
- if (cpumask_test_cpu(cpu, &cpu_callin_map))
- return -EINVAL;
-
- per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
- /* Processor goes to start_secondary(), sets online flag */
- ret = do_boot_cpu(sapicid, cpu, tidle);
- if (ret < 0)
- return ret;
-
- if (cpu_data(cpu)->threads_per_core == 1 &&
- cpu_data(cpu)->cores_per_socket == 1) {
- cpumask_set_cpu(cpu, &per_cpu(cpu_sibling_map, cpu));
- cpumask_set_cpu(cpu, &cpu_core_map[cpu]);
- return 0;
- }
-
- set_cpu_sibling_map(cpu);
-
- return 0;
-}
-
-/*
- * Assume that CPUs have been discovered by some platform-dependent interface. For
- * SoftSDV/Lion, that would be ACPI.
- *
- * Setup of the IPI irq handler is done in irq.c:init_IRQ_SMP().
- */
-void __init
-init_smp_config(void)
-{
- struct fptr {
- unsigned long fp;
- unsigned long gp;
- } *ap_startup;
- long sal_ret;
-
- /* Tell SAL where to drop the APs. */
- ap_startup = (struct fptr *) start_ap;
- sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ,
- ia64_tpa(ap_startup->fp), ia64_tpa(ap_startup->gp), 0, 0, 0, 0);
- if (sal_ret < 0)
- printk(KERN_ERR "SMP: Can't set SAL AP Boot Rendezvous: %s\n",
- ia64_sal_strerror(sal_ret));
-}
-
-/*
- * identify_siblings(cpu) gets called from identify_cpu. This populates the
- * information related to logical execution units in per_cpu_data structure.
- */
-void identify_siblings(struct cpuinfo_ia64 *c)
-{
- long status;
- u16 pltid;
- pal_logical_to_physical_t info;
-
- status = ia64_pal_logical_to_phys(-1, &info);
- if (status != PAL_STATUS_SUCCESS) {
- if (status != PAL_STATUS_UNIMPLEMENTED) {
- printk(KERN_ERR
- "ia64_pal_logical_to_phys failed with %ld\n",
- status);
- return;
- }
-
- info.overview_ppid = 0;
- info.overview_cpp = 1;
- info.overview_tpc = 1;
- }
-
- status = ia64_sal_physical_id_info(&pltid);
- if (status != PAL_STATUS_SUCCESS) {
- if (status != PAL_STATUS_UNIMPLEMENTED)
- printk(KERN_ERR
- "ia64_sal_pltid failed with %ld\n",
- status);
- return;
- }
-
- c->socket_id = (pltid << 8) | info.overview_ppid;
-
- if (info.overview_cpp == 1 && info.overview_tpc == 1)
- return;
-
- c->cores_per_socket = info.overview_cpp;
- c->threads_per_core = info.overview_tpc;
- c->num_log = info.overview_num_log;
-
- c->core_id = info.log1_cid;
- c->thread_id = info.log1_tid;
-}
-
-/*
- * returns non zero, if multi-threading is enabled
- * on at least one physical package. Due to hotplug cpu
- * and (maxcpus=), all threads may not necessarily be enabled
- * even though the processor supports multi-threading.
- */
-int is_multithreading_enabled(void)
-{
- int i, j;
-
- for_each_present_cpu(i) {
- for_each_present_cpu(j) {
- if (j == i)
- continue;
- if ((cpu_data(j)->socket_id == cpu_data(i)->socket_id)) {
- if (cpu_data(j)->core_id == cpu_data(i)->core_id)
- return 1;
- }
- }
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(is_multithreading_enabled);
diff --git a/arch/ia64/kernel/stacktrace.c b/arch/ia64/kernel/stacktrace.c
deleted file mode 100644
index 6e583a6bd2f6..000000000000
--- a/arch/ia64/kernel/stacktrace.c
+++ /dev/null
@@ -1,40 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/ia64/kernel/stacktrace.c
- *
- * Stack trace management functions
- *
- */
-#include <linux/sched.h>
-#include <linux/stacktrace.h>
-#include <linux/module.h>
-
-static void
-ia64_do_save_stack(struct unw_frame_info *info, void *arg)
-{
- struct stack_trace *trace = arg;
- unsigned long ip;
- int skip = trace->skip;
-
- trace->nr_entries = 0;
- do {
- unw_get_ip(info, &ip);
- if (ip == 0)
- break;
- if (skip == 0) {
- trace->entries[trace->nr_entries++] = ip;
- if (trace->nr_entries == trace->max_entries)
- break;
- } else
- skip--;
- } while (unw_unwind(info) >= 0);
-}
-
-/*
- * Save stack-backtrace addresses into a stack_trace buffer.
- */
-void save_stack_trace(struct stack_trace *trace)
-{
- unw_init_running(ia64_do_save_stack, trace);
-}
-EXPORT_SYMBOL(save_stack_trace);
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
deleted file mode 100644
index eb561cc93632..000000000000
--- a/arch/ia64/kernel/sys_ia64.c
+++ /dev/null
@@ -1,197 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This file contains various system calls that have different calling
- * conventions on different platforms.
- *
- * Copyright (C) 1999-2000, 2002-2003, 2005 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/sched.h>
-#include <linux/sched/mm.h>
-#include <linux/sched/task_stack.h>
-#include <linux/shm.h>
-#include <linux/file.h> /* doh, must come after sched.h... */
-#include <linux/smp.h>
-#include <linux/syscalls.h>
-#include <linux/highuid.h>
-#include <linux/hugetlb.h>
-
-#include <asm/shmparam.h>
-#include <linux/uaccess.h>
-
-unsigned long
-arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len,
- unsigned long pgoff, unsigned long flags)
-{
- long map_shared = (flags & MAP_SHARED);
- unsigned long align_mask = 0;
- struct mm_struct *mm = current->mm;
- struct vm_unmapped_area_info info;
-
- if (len > RGN_MAP_LIMIT)
- return -ENOMEM;
-
- /* handle fixed mapping: prevent overlap with huge pages */
- if (flags & MAP_FIXED) {
- if (is_hugepage_only_range(mm, addr, len))
- return -EINVAL;
- return addr;
- }
-
-#ifdef CONFIG_HUGETLB_PAGE
- if (REGION_NUMBER(addr) == RGN_HPAGE)
- addr = 0;
-#endif
- if (!addr)
- addr = TASK_UNMAPPED_BASE;
-
- if (map_shared && (TASK_SIZE > 0xfffffffful))
- /*
- * For 64-bit tasks, align shared segments to 1MB to avoid potential
- * performance penalty due to virtual aliasing (see ASDM). For 32-bit
- * tasks, we prefer to avoid exhausting the address space too quickly by
- * limiting alignment to a single page.
- */
- align_mask = PAGE_MASK & (SHMLBA - 1);
-
- info.flags = 0;
- info.length = len;
- info.low_limit = addr;
- info.high_limit = TASK_SIZE;
- info.align_mask = align_mask;
- info.align_offset = pgoff << PAGE_SHIFT;
- return vm_unmapped_area(&info);
-}
-
-asmlinkage long
-ia64_getpriority (int which, int who)
-{
- long prio;
-
- prio = sys_getpriority(which, who);
- if (prio >= 0) {
- force_successful_syscall_return();
- prio = 20 - prio;
- }
- return prio;
-}
-
-/* XXX obsolete, but leave it here until the old libc is gone... */
-asmlinkage unsigned long
-sys_getpagesize (void)
-{
- return PAGE_SIZE;
-}
-
-asmlinkage unsigned long
-ia64_brk (unsigned long brk)
-{
- unsigned long retval = sys_brk(brk);
- force_successful_syscall_return();
- return retval;
-}
-
-/*
- * On IA-64, we return the two file descriptors in ret0 and ret1 (r8
- * and r9) as this is faster than doing a copy_to_user().
- */
-asmlinkage long
-sys_ia64_pipe (void)
-{
- struct pt_regs *regs = task_pt_regs(current);
- int fd[2];
- int retval;
-
- retval = do_pipe_flags(fd, 0);
- if (retval)
- goto out;
- retval = fd[0];
- regs->r9 = fd[1];
- out:
- return retval;
-}
-
-int ia64_mmap_check(unsigned long addr, unsigned long len,
- unsigned long flags)
-{
- unsigned long roff;
-
- /*
- * Don't permit mappings into unmapped space, the virtual page table
- * of a region, or across a region boundary. Note: RGN_MAP_LIMIT is
- * equal to 2^n-PAGE_SIZE (for some integer n <= 61) and len > 0.
- */
- roff = REGION_OFFSET(addr);
- if ((len > RGN_MAP_LIMIT) || (roff > (RGN_MAP_LIMIT - len)))
- return -EINVAL;
- return 0;
-}
-
-/*
- * mmap2() is like mmap() except that the offset is expressed in units
- * of PAGE_SIZE (instead of bytes). This allows to mmap2() (pieces
- * of) files that are larger than the address space of the CPU.
- */
-asmlinkage unsigned long
-sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff)
-{
- addr = ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
- if (!IS_ERR_VALUE(addr))
- force_successful_syscall_return();
- return addr;
-}
-
-asmlinkage unsigned long
-sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, int fd, long off)
-{
- if (offset_in_page(off) != 0)
- return -EINVAL;
-
- addr = ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
- if (!IS_ERR_VALUE(addr))
- force_successful_syscall_return();
- return addr;
-}
-
-asmlinkage unsigned long
-ia64_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags,
- unsigned long new_addr)
-{
- addr = sys_mremap(addr, old_len, new_len, flags, new_addr);
- if (!IS_ERR_VALUE(addr))
- force_successful_syscall_return();
- return addr;
-}
-
-asmlinkage long
-ia64_clock_getres(const clockid_t which_clock, struct __kernel_timespec __user *tp)
-{
- struct timespec64 rtn_tp;
- s64 tick_ns;
-
- /*
- * ia64's clock_gettime() syscall is implemented as a vdso call
- * fsys_clock_gettime(). Currently it handles only
- * CLOCK_REALTIME and CLOCK_MONOTONIC. Both are based on
- * 'ar.itc' counter which gets incremented at a constant
- * frequency. It's usually 400MHz, ~2.5x times slower than CPU
- * clock frequency. Which is almost a 1ns hrtimer, but not quite.
- *
- * Let's special-case these timers to report correct precision
- * based on ITC frequency and not HZ frequency for supported
- * clocks.
- */
- switch (which_clock) {
- case CLOCK_REALTIME:
- case CLOCK_MONOTONIC:
- tick_ns = DIV_ROUND_UP(NSEC_PER_SEC, local_cpu_data->itc_freq);
- rtn_tp = ns_to_timespec64(tick_ns);
- return put_timespec64(&rtn_tp, tp);
- }
-
- return sys_clock_getres(which_clock, tp);
-}
diff --git a/arch/ia64/kernel/syscalls/Makefile b/arch/ia64/kernel/syscalls/Makefile
deleted file mode 100644
index d009f927a048..000000000000
--- a/arch/ia64/kernel/syscalls/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-kapi := arch/$(SRCARCH)/include/generated/asm
-uapi := arch/$(SRCARCH)/include/generated/uapi/asm
-
-$(shell mkdir -p $(uapi) $(kapi))
-
-syscall := $(src)/syscall.tbl
-syshdr := $(srctree)/scripts/syscallhdr.sh
-systbl := $(srctree)/scripts/syscalltbl.sh
-
-quiet_cmd_syshdr = SYSHDR $@
- cmd_syshdr = $(CONFIG_SHELL) $(syshdr) --emit-nr --offset __NR_Linux $< $@
-
-quiet_cmd_systbl = SYSTBL $@
- cmd_systbl = $(CONFIG_SHELL) $(systbl) $< $@
-
-$(uapi)/unistd_64.h: $(syscall) $(syshdr) FORCE
- $(call if_changed,syshdr)
-
-$(kapi)/syscall_table.h: $(syscall) $(systbl) FORCE
- $(call if_changed,systbl)
-
-uapisyshdr-y += unistd_64.h
-kapisyshdr-y += syscall_table.h
-
-uapisyshdr-y := $(addprefix $(uapi)/, $(uapisyshdr-y))
-kapisyshdr-y := $(addprefix $(kapi)/, $(kapisyshdr-y))
-targets += $(addprefix ../../../../, $(uapisyshdr-y) $(kapisyshdr-y))
-
-PHONY += all
-all: $(uapisyshdr-y) $(kapisyshdr-y)
- @:
diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl
deleted file mode 100644
index 83d8609aec03..000000000000
--- a/arch/ia64/kernel/syscalls/syscall.tbl
+++ /dev/null
@@ -1,375 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-#
-# Linux system call numbers and entry vectors for ia64
-#
-# The format is:
-# <number> <abi> <name> <entry point>
-#
-# Add 1024 to <number> will get the actual system call number
-#
-# The <abi> is always "common" for this file
-#
-0 common ni_syscall sys_ni_syscall
-1 common exit sys_exit
-2 common read sys_read
-3 common write sys_write
-4 common open sys_open
-5 common close sys_close
-6 common creat sys_creat
-7 common link sys_link
-8 common unlink sys_unlink
-9 common execve ia64_execve
-10 common chdir sys_chdir
-11 common fchdir sys_fchdir
-12 common utimes sys_utimes
-13 common mknod sys_mknod
-14 common chmod sys_chmod
-15 common chown sys_chown
-16 common lseek sys_lseek
-17 common getpid sys_getpid
-18 common getppid sys_getppid
-19 common mount sys_mount
-20 common umount2 sys_umount
-21 common setuid sys_setuid
-22 common getuid sys_getuid
-23 common geteuid sys_geteuid
-24 common ptrace sys_ptrace
-25 common access sys_access
-26 common sync sys_sync
-27 common fsync sys_fsync
-28 common fdatasync sys_fdatasync
-29 common kill sys_kill
-30 common rename sys_rename
-31 common mkdir sys_mkdir
-32 common rmdir sys_rmdir
-33 common dup sys_dup
-34 common pipe sys_ia64_pipe
-35 common times sys_times
-36 common brk ia64_brk
-37 common setgid sys_setgid
-38 common getgid sys_getgid
-39 common getegid sys_getegid
-40 common acct sys_acct
-41 common ioctl sys_ioctl
-42 common fcntl sys_fcntl
-43 common umask sys_umask
-44 common chroot sys_chroot
-45 common ustat sys_ustat
-46 common dup2 sys_dup2
-47 common setreuid sys_setreuid
-48 common setregid sys_setregid
-49 common getresuid sys_getresuid
-50 common setresuid sys_setresuid
-51 common getresgid sys_getresgid
-52 common setresgid sys_setresgid
-53 common getgroups sys_getgroups
-54 common setgroups sys_setgroups
-55 common getpgid sys_getpgid
-56 common setpgid sys_setpgid
-57 common setsid sys_setsid
-58 common getsid sys_getsid
-59 common sethostname sys_sethostname
-60 common setrlimit sys_setrlimit
-61 common getrlimit sys_getrlimit
-62 common getrusage sys_getrusage
-63 common gettimeofday sys_gettimeofday
-64 common settimeofday sys_settimeofday
-65 common select sys_select
-66 common poll sys_poll
-67 common symlink sys_symlink
-68 common readlink sys_readlink
-69 common uselib sys_uselib
-70 common swapon sys_swapon
-71 common swapoff sys_swapoff
-72 common reboot sys_reboot
-73 common truncate sys_truncate
-74 common ftruncate sys_ftruncate
-75 common fchmod sys_fchmod
-76 common fchown sys_fchown
-77 common getpriority ia64_getpriority
-78 common setpriority sys_setpriority
-79 common statfs sys_statfs
-80 common fstatfs sys_fstatfs
-81 common gettid sys_gettid
-82 common semget sys_semget
-83 common semop sys_semop
-84 common semctl sys_semctl
-85 common msgget sys_msgget
-86 common msgsnd sys_msgsnd
-87 common msgrcv sys_msgrcv
-88 common msgctl sys_msgctl
-89 common shmget sys_shmget
-90 common shmat sys_shmat
-91 common shmdt sys_shmdt
-92 common shmctl sys_shmctl
-93 common syslog sys_syslog
-94 common setitimer sys_setitimer
-95 common getitimer sys_getitimer
-# 1120 was old_stat
-# 1121 was old_lstat
-# 1122 was old_fstat
-99 common vhangup sys_vhangup
-100 common lchown sys_lchown
-101 common remap_file_pages sys_remap_file_pages
-102 common wait4 sys_wait4
-103 common sysinfo sys_sysinfo
-104 common clone sys_clone
-105 common setdomainname sys_setdomainname
-106 common uname sys_newuname
-107 common adjtimex sys_adjtimex
-# 1132 was create_module
-109 common init_module sys_init_module
-110 common delete_module sys_delete_module
-# 1135 was get_kernel_syms
-# 1136 was query_module
-113 common quotactl sys_quotactl
-114 common bdflush sys_ni_syscall
-115 common sysfs sys_sysfs
-116 common personality sys_personality
-117 common afs_syscall sys_ni_syscall
-118 common setfsuid sys_setfsuid
-119 common setfsgid sys_setfsgid
-120 common getdents sys_getdents
-121 common flock sys_flock
-122 common readv sys_readv
-123 common writev sys_writev
-124 common pread64 sys_pread64
-125 common pwrite64 sys_pwrite64
-126 common _sysctl sys_ni_syscall
-127 common mmap sys_mmap
-128 common munmap sys_munmap
-129 common mlock sys_mlock
-130 common mlockall sys_mlockall
-131 common mprotect sys_mprotect
-132 common mremap ia64_mremap
-133 common msync sys_msync
-134 common munlock sys_munlock
-135 common munlockall sys_munlockall
-136 common sched_getparam sys_sched_getparam
-137 common sched_setparam sys_sched_setparam
-138 common sched_getscheduler sys_sched_getscheduler
-139 common sched_setscheduler sys_sched_setscheduler
-140 common sched_yield sys_sched_yield
-141 common sched_get_priority_max sys_sched_get_priority_max
-142 common sched_get_priority_min sys_sched_get_priority_min
-143 common sched_rr_get_interval sys_sched_rr_get_interval
-144 common nanosleep sys_nanosleep
-145 common nfsservctl sys_ni_syscall
-146 common prctl sys_prctl
-147 common old_getpagesize sys_getpagesize
-148 common mmap2 sys_mmap2
-149 common pciconfig_read sys_pciconfig_read
-150 common pciconfig_write sys_pciconfig_write
-151 common perfmonctl sys_ni_syscall
-152 common sigaltstack sys_sigaltstack
-153 common rt_sigaction sys_rt_sigaction
-154 common rt_sigpending sys_rt_sigpending
-155 common rt_sigprocmask sys_rt_sigprocmask
-156 common rt_sigqueueinfo sys_rt_sigqueueinfo
-157 common rt_sigreturn sys_rt_sigreturn
-158 common rt_sigsuspend sys_rt_sigsuspend
-159 common rt_sigtimedwait sys_rt_sigtimedwait
-160 common getcwd sys_getcwd
-161 common capget sys_capget
-162 common capset sys_capset
-163 common sendfile sys_sendfile64
-164 common getpmsg sys_ni_syscall
-165 common putpmsg sys_ni_syscall
-166 common socket sys_socket
-167 common bind sys_bind
-168 common connect sys_connect
-169 common listen sys_listen
-170 common accept sys_accept
-171 common getsockname sys_getsockname
-172 common getpeername sys_getpeername
-173 common socketpair sys_socketpair
-174 common send sys_send
-175 common sendto sys_sendto
-176 common recv sys_recv
-177 common recvfrom sys_recvfrom
-178 common shutdown sys_shutdown
-179 common setsockopt sys_setsockopt
-180 common getsockopt sys_getsockopt
-181 common sendmsg sys_sendmsg
-182 common recvmsg sys_recvmsg
-183 common pivot_root sys_pivot_root
-184 common mincore sys_mincore
-185 common madvise sys_madvise
-186 common stat sys_newstat
-187 common lstat sys_newlstat
-188 common fstat sys_newfstat
-189 common clone2 sys_clone2
-190 common getdents64 sys_getdents64
-191 common getunwind sys_getunwind
-192 common readahead sys_readahead
-193 common setxattr sys_setxattr
-194 common lsetxattr sys_lsetxattr
-195 common fsetxattr sys_fsetxattr
-196 common getxattr sys_getxattr
-197 common lgetxattr sys_lgetxattr
-198 common fgetxattr sys_fgetxattr
-199 common listxattr sys_listxattr
-200 common llistxattr sys_llistxattr
-201 common flistxattr sys_flistxattr
-202 common removexattr sys_removexattr
-203 common lremovexattr sys_lremovexattr
-204 common fremovexattr sys_fremovexattr
-205 common tkill sys_tkill
-206 common futex sys_futex
-207 common sched_setaffinity sys_sched_setaffinity
-208 common sched_getaffinity sys_sched_getaffinity
-209 common set_tid_address sys_set_tid_address
-210 common fadvise64 sys_fadvise64_64
-211 common tgkill sys_tgkill
-212 common exit_group sys_exit_group
-213 common lookup_dcookie sys_lookup_dcookie
-214 common io_setup sys_io_setup
-215 common io_destroy sys_io_destroy
-216 common io_getevents sys_io_getevents
-217 common io_submit sys_io_submit
-218 common io_cancel sys_io_cancel
-219 common epoll_create sys_epoll_create
-220 common epoll_ctl sys_epoll_ctl
-221 common epoll_wait sys_epoll_wait
-222 common restart_syscall sys_restart_syscall
-223 common semtimedop sys_semtimedop
-224 common timer_create sys_timer_create
-225 common timer_settime sys_timer_settime
-226 common timer_gettime sys_timer_gettime
-227 common timer_getoverrun sys_timer_getoverrun
-228 common timer_delete sys_timer_delete
-229 common clock_settime sys_clock_settime
-230 common clock_gettime sys_clock_gettime
-231 common clock_getres ia64_clock_getres
-232 common clock_nanosleep sys_clock_nanosleep
-233 common fstatfs64 sys_fstatfs64
-234 common statfs64 sys_statfs64
-235 common mbind sys_mbind
-236 common get_mempolicy sys_get_mempolicy
-237 common set_mempolicy sys_set_mempolicy
-238 common mq_open sys_mq_open
-239 common mq_unlink sys_mq_unlink
-240 common mq_timedsend sys_mq_timedsend
-241 common mq_timedreceive sys_mq_timedreceive
-242 common mq_notify sys_mq_notify
-243 common mq_getsetattr sys_mq_getsetattr
-244 common kexec_load sys_kexec_load
-245 common vserver sys_ni_syscall
-246 common waitid sys_waitid
-247 common add_key sys_add_key
-248 common request_key sys_request_key
-249 common keyctl sys_keyctl
-250 common ioprio_set sys_ioprio_set
-251 common ioprio_get sys_ioprio_get
-252 common move_pages sys_move_pages
-253 common inotify_init sys_inotify_init
-254 common inotify_add_watch sys_inotify_add_watch
-255 common inotify_rm_watch sys_inotify_rm_watch
-256 common migrate_pages sys_migrate_pages
-257 common openat sys_openat
-258 common mkdirat sys_mkdirat
-259 common mknodat sys_mknodat
-260 common fchownat sys_fchownat
-261 common futimesat sys_futimesat
-262 common newfstatat sys_newfstatat
-263 common unlinkat sys_unlinkat
-264 common renameat sys_renameat
-265 common linkat sys_linkat
-266 common symlinkat sys_symlinkat
-267 common readlinkat sys_readlinkat
-268 common fchmodat sys_fchmodat
-269 common faccessat sys_faccessat
-270 common pselect6 sys_pselect6
-271 common ppoll sys_ppoll
-272 common unshare sys_unshare
-273 common splice sys_splice
-274 common set_robust_list sys_set_robust_list
-275 common get_robust_list sys_get_robust_list
-276 common sync_file_range sys_sync_file_range
-277 common tee sys_tee
-278 common vmsplice sys_vmsplice
-279 common fallocate sys_fallocate
-280 common getcpu sys_getcpu
-281 common epoll_pwait sys_epoll_pwait
-282 common utimensat sys_utimensat
-283 common signalfd sys_signalfd
-284 common timerfd sys_ni_syscall
-285 common eventfd sys_eventfd
-286 common timerfd_create sys_timerfd_create
-287 common timerfd_settime sys_timerfd_settime
-288 common timerfd_gettime sys_timerfd_gettime
-289 common signalfd4 sys_signalfd4
-290 common eventfd2 sys_eventfd2
-291 common epoll_create1 sys_epoll_create1
-292 common dup3 sys_dup3
-293 common pipe2 sys_pipe2
-294 common inotify_init1 sys_inotify_init1
-295 common preadv sys_preadv
-296 common pwritev sys_pwritev
-297 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo
-298 common recvmmsg sys_recvmmsg
-299 common fanotify_init sys_fanotify_init
-300 common fanotify_mark sys_fanotify_mark
-301 common prlimit64 sys_prlimit64
-302 common name_to_handle_at sys_name_to_handle_at
-303 common open_by_handle_at sys_open_by_handle_at
-304 common clock_adjtime sys_clock_adjtime
-305 common syncfs sys_syncfs
-306 common setns sys_setns
-307 common sendmmsg sys_sendmmsg
-308 common process_vm_readv sys_process_vm_readv
-309 common process_vm_writev sys_process_vm_writev
-310 common accept4 sys_accept4
-311 common finit_module sys_finit_module
-312 common sched_setattr sys_sched_setattr
-313 common sched_getattr sys_sched_getattr
-314 common renameat2 sys_renameat2
-315 common getrandom sys_getrandom
-316 common memfd_create sys_memfd_create
-317 common bpf sys_bpf
-318 common execveat sys_execveat
-319 common userfaultfd sys_userfaultfd
-320 common membarrier sys_membarrier
-321 common kcmp sys_kcmp
-322 common mlock2 sys_mlock2
-323 common copy_file_range sys_copy_file_range
-324 common preadv2 sys_preadv2
-325 common pwritev2 sys_pwritev2
-326 common statx sys_statx
-327 common io_pgetevents sys_io_pgetevents
-328 common perf_event_open sys_perf_event_open
-329 common seccomp sys_seccomp
-330 common pkey_mprotect sys_pkey_mprotect
-331 common pkey_alloc sys_pkey_alloc
-332 common pkey_free sys_pkey_free
-333 common rseq sys_rseq
-# 334 through 423 are reserved to sync up with other architectures
-424 common pidfd_send_signal sys_pidfd_send_signal
-425 common io_uring_setup sys_io_uring_setup
-426 common io_uring_enter sys_io_uring_enter
-427 common io_uring_register sys_io_uring_register
-428 common open_tree sys_open_tree
-429 common move_mount sys_move_mount
-430 common fsopen sys_fsopen
-431 common fsconfig sys_fsconfig
-432 common fsmount sys_fsmount
-433 common fspick sys_fspick
-434 common pidfd_open sys_pidfd_open
-# 435 reserved for clone3
-436 common close_range sys_close_range
-437 common openat2 sys_openat2
-438 common pidfd_getfd sys_pidfd_getfd
-439 common faccessat2 sys_faccessat2
-440 common process_madvise sys_process_madvise
-441 common epoll_pwait2 sys_epoll_pwait2
-442 common mount_setattr sys_mount_setattr
-443 common quotactl_fd sys_quotactl_fd
-444 common landlock_create_ruleset sys_landlock_create_ruleset
-445 common landlock_add_rule sys_landlock_add_rule
-446 common landlock_restrict_self sys_landlock_restrict_self
-# 447 reserved for memfd_secret
-448 common process_mrelease sys_process_mrelease
-449 common futex_waitv sys_futex_waitv
-450 common set_mempolicy_home_node sys_set_mempolicy_home_node
-451 common cachestat sys_cachestat
-452 common fchmodat2 sys_fchmodat2
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
deleted file mode 100644
index 83ef044b63ef..000000000000
--- a/arch/ia64/kernel/time.c
+++ /dev/null
@@ -1,463 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/ia64/kernel/time.c
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- * David Mosberger <davidm@hpl.hp.com>
- * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
- * Copyright (C) 1999-2000 VA Linux Systems
- * Copyright (C) 1999-2000 Walt Drummond <drummond@valinux.com>
- */
-
-#include <linux/cpu.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/profile.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/nmi.h>
-#include <linux/interrupt.h>
-#include <linux/efi.h>
-#include <linux/timex.h>
-#include <linux/timekeeper_internal.h>
-#include <linux/platform_device.h>
-#include <linux/sched/cputime.h>
-
-#include <asm/cputime.h>
-#include <asm/delay.h>
-#include <asm/efi.h>
-#include <asm/hw_irq.h>
-#include <asm/ptrace.h>
-#include <asm/sal.h>
-#include <asm/sections.h>
-
-#include "fsyscall_gtod_data.h"
-#include "irq.h"
-
-static u64 itc_get_cycles(struct clocksource *cs);
-
-struct fsyscall_gtod_data_t fsyscall_gtod_data;
-
-struct itc_jitter_data_t itc_jitter_data;
-
-volatile int time_keeper_id = 0; /* smp_processor_id() of time-keeper */
-
-#ifdef CONFIG_IA64_DEBUG_IRQ
-
-unsigned long last_cli_ip;
-EXPORT_SYMBOL(last_cli_ip);
-
-#endif
-
-static struct clocksource clocksource_itc = {
- .name = "itc",
- .rating = 350,
- .read = itc_get_cycles,
- .mask = CLOCKSOURCE_MASK(64),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-static struct clocksource *itc_clocksource;
-
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
-
-#include <linux/kernel_stat.h>
-
-extern u64 cycle_to_nsec(u64 cyc);
-
-void vtime_flush(struct task_struct *tsk)
-{
- struct thread_info *ti = task_thread_info(tsk);
- u64 delta;
-
- if (ti->utime)
- account_user_time(tsk, cycle_to_nsec(ti->utime));
-
- if (ti->gtime)
- account_guest_time(tsk, cycle_to_nsec(ti->gtime));
-
- if (ti->idle_time)
- account_idle_time(cycle_to_nsec(ti->idle_time));
-
- if (ti->stime) {
- delta = cycle_to_nsec(ti->stime);
- account_system_index_time(tsk, delta, CPUTIME_SYSTEM);
- }
-
- if (ti->hardirq_time) {
- delta = cycle_to_nsec(ti->hardirq_time);
- account_system_index_time(tsk, delta, CPUTIME_IRQ);
- }
-
- if (ti->softirq_time) {
- delta = cycle_to_nsec(ti->softirq_time);
- account_system_index_time(tsk, delta, CPUTIME_SOFTIRQ);
- }
-
- ti->utime = 0;
- ti->gtime = 0;
- ti->idle_time = 0;
- ti->stime = 0;
- ti->hardirq_time = 0;
- ti->softirq_time = 0;
-}
-
-/*
- * Called from the context switch with interrupts disabled, to charge all
- * accumulated times to the current process, and to prepare accounting on
- * the next process.
- */
-void arch_vtime_task_switch(struct task_struct *prev)
-{
- struct thread_info *pi = task_thread_info(prev);
- struct thread_info *ni = task_thread_info(current);
-
- ni->ac_stamp = pi->ac_stamp;
- ni->ac_stime = ni->ac_utime = 0;
-}
-
-/*
- * Account time for a transition between system, hard irq or soft irq state.
- * Note that this function is called with interrupts enabled.
- */
-static __u64 vtime_delta(struct task_struct *tsk)
-{
- struct thread_info *ti = task_thread_info(tsk);
- __u64 now, delta_stime;
-
- WARN_ON_ONCE(!irqs_disabled());
-
- now = ia64_get_itc();
- delta_stime = now - ti->ac_stamp;
- ti->ac_stamp = now;
-
- return delta_stime;
-}
-
-void vtime_account_kernel(struct task_struct *tsk)
-{
- struct thread_info *ti = task_thread_info(tsk);
- __u64 stime = vtime_delta(tsk);
-
- if (tsk->flags & PF_VCPU)
- ti->gtime += stime;
- else
- ti->stime += stime;
-}
-EXPORT_SYMBOL_GPL(vtime_account_kernel);
-
-void vtime_account_idle(struct task_struct *tsk)
-{
- struct thread_info *ti = task_thread_info(tsk);
-
- ti->idle_time += vtime_delta(tsk);
-}
-
-void vtime_account_softirq(struct task_struct *tsk)
-{
- struct thread_info *ti = task_thread_info(tsk);
-
- ti->softirq_time += vtime_delta(tsk);
-}
-
-void vtime_account_hardirq(struct task_struct *tsk)
-{
- struct thread_info *ti = task_thread_info(tsk);
-
- ti->hardirq_time += vtime_delta(tsk);
-}
-
-#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
-
-static irqreturn_t
-timer_interrupt (int irq, void *dev_id)
-{
- unsigned long new_itm;
-
- if (cpu_is_offline(smp_processor_id())) {
- return IRQ_HANDLED;
- }
-
- new_itm = local_cpu_data->itm_next;
-
- if (!time_after(ia64_get_itc(), new_itm))
- printk(KERN_ERR "Oops: timer tick before it's due (itc=%lx,itm=%lx)\n",
- ia64_get_itc(), new_itm);
-
- while (1) {
- new_itm += local_cpu_data->itm_delta;
-
- legacy_timer_tick(smp_processor_id() == time_keeper_id);
-
- local_cpu_data->itm_next = new_itm;
-
- if (time_after(new_itm, ia64_get_itc()))
- break;
-
- /*
- * Allow IPIs to interrupt the timer loop.
- */
- local_irq_enable();
- local_irq_disable();
- }
-
- do {
- /*
- * If we're too close to the next clock tick for
- * comfort, we increase the safety margin by
- * intentionally dropping the next tick(s). We do NOT
- * update itm.next because that would force us to call
- * xtime_update() which in turn would let our clock run
- * too fast (with the potentially devastating effect
- * of losing monotony of time).
- */
- while (!time_after(new_itm, ia64_get_itc() + local_cpu_data->itm_delta/2))
- new_itm += local_cpu_data->itm_delta;
- ia64_set_itm(new_itm);
- /* double check, in case we got hit by a (slow) PMI: */
- } while (time_after_eq(ia64_get_itc(), new_itm));
- return IRQ_HANDLED;
-}
-
-/*
- * Encapsulate access to the itm structure for SMP.
- */
-void
-ia64_cpu_local_tick (void)
-{
- int cpu = smp_processor_id();
- unsigned long shift = 0, delta;
-
- /* arrange for the cycle counter to generate a timer interrupt: */
- ia64_set_itv(IA64_TIMER_VECTOR);
-
- delta = local_cpu_data->itm_delta;
- /*
- * Stagger the timer tick for each CPU so they don't occur all at (almost) the
- * same time:
- */
- if (cpu) {
- unsigned long hi = 1UL << ia64_fls(cpu);
- shift = (2*(cpu - hi) + 1) * delta/hi/2;
- }
- local_cpu_data->itm_next = ia64_get_itc() + delta + shift;
- ia64_set_itm(local_cpu_data->itm_next);
-}
-
-static int nojitter;
-
-static int __init nojitter_setup(char *str)
-{
- nojitter = 1;
- printk("Jitter checking for ITC timers disabled\n");
- return 1;
-}
-
-__setup("nojitter", nojitter_setup);
-
-
-void ia64_init_itm(void)
-{
- unsigned long platform_base_freq, itc_freq;
- struct pal_freq_ratio itc_ratio, proc_ratio;
- long status, platform_base_drift, itc_drift;
-
- /*
- * According to SAL v2.6, we need to use a SAL call to determine the platform base
- * frequency and then a PAL call to determine the frequency ratio between the ITC
- * and the base frequency.
- */
- status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM,
- &platform_base_freq, &platform_base_drift);
- if (status != 0) {
- printk(KERN_ERR "SAL_FREQ_BASE_PLATFORM failed: %s\n", ia64_sal_strerror(status));
- } else {
- status = ia64_pal_freq_ratios(&proc_ratio, NULL, &itc_ratio);
- if (status != 0)
- printk(KERN_ERR "PAL_FREQ_RATIOS failed with status=%ld\n", status);
- }
- if (status != 0) {
- /* invent "random" values */
- printk(KERN_ERR
- "SAL/PAL failed to obtain frequency info---inventing reasonable values\n");
- platform_base_freq = 100000000;
- platform_base_drift = -1; /* no drift info */
- itc_ratio.num = 3;
- itc_ratio.den = 1;
- }
- if (platform_base_freq < 40000000) {
- printk(KERN_ERR "Platform base frequency %lu bogus---resetting to 75MHz!\n",
- platform_base_freq);
- platform_base_freq = 75000000;
- platform_base_drift = -1;
- }
- if (!proc_ratio.den)
- proc_ratio.den = 1; /* avoid division by zero */
- if (!itc_ratio.den)
- itc_ratio.den = 1; /* avoid division by zero */
-
- itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den;
-
- local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ;
- printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%u/%u, "
- "ITC freq=%lu.%03luMHz", smp_processor_id(),
- platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000,
- itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000);
-
- if (platform_base_drift != -1) {
- itc_drift = platform_base_drift*itc_ratio.num/itc_ratio.den;
- printk("+/-%ldppm\n", itc_drift);
- } else {
- itc_drift = -1;
- printk("\n");
- }
-
- local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den;
- local_cpu_data->itc_freq = itc_freq;
- local_cpu_data->cyc_per_usec = (itc_freq + USEC_PER_SEC/2) / USEC_PER_SEC;
- local_cpu_data->nsec_per_cyc = ((NSEC_PER_SEC<<IA64_NSEC_PER_CYC_SHIFT)
- + itc_freq/2)/itc_freq;
-
- if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
-#ifdef CONFIG_SMP
- /* On IA64 in an SMP configuration ITCs are never accurately synchronized.
- * Jitter compensation requires a cmpxchg which may limit
- * the scalability of the syscalls for retrieving time.
- * The ITC synchronization is usually successful to within a few
- * ITC ticks but this is not a sure thing. If you need to improve
- * timer performance in SMP situations then boot the kernel with the
- * "nojitter" option. However, doing so may result in time fluctuating (maybe
- * even going backward) if the ITC offsets between the individual CPUs
- * are too large.
- */
- if (!nojitter)
- itc_jitter_data.itc_jitter = 1;
-#endif
- } else
- /*
- * ITC is drifty and we have not synchronized the ITCs in smpboot.c.
- * ITC values may fluctuate significantly between processors.
- * Clock should not be used for hrtimers. Mark itc as only
- * useful for boot and testing.
- *
- * Note that jitter compensation is off! There is no point of
- * synchronizing ITCs since they may be large differentials
- * that change over time.
- *
- * The only way to fix this would be to repeatedly sync the
- * ITCs. Until that time we have to avoid ITC.
- */
- clocksource_itc.rating = 50;
-
- /* avoid softlock up message when cpu is unplug and plugged again. */
- touch_softlockup_watchdog();
-
- /* Setup the CPU local timer tick */
- ia64_cpu_local_tick();
-
- if (!itc_clocksource) {
- clocksource_register_hz(&clocksource_itc,
- local_cpu_data->itc_freq);
- itc_clocksource = &clocksource_itc;
- }
-}
-
-static u64 itc_get_cycles(struct clocksource *cs)
-{
- unsigned long lcycle, now, ret;
-
- if (!itc_jitter_data.itc_jitter)
- return get_cycles();
-
- lcycle = itc_jitter_data.itc_lastcycle;
- now = get_cycles();
- if (lcycle && time_after(lcycle, now))
- return lcycle;
-
- /*
- * Keep track of the last timer value returned.
- * In an SMP environment, you could lose out in contention of
- * cmpxchg. If so, your cmpxchg returns new value which the
- * winner of contention updated to. Use the new value instead.
- */
- ret = cmpxchg(&itc_jitter_data.itc_lastcycle, lcycle, now);
- if (unlikely(ret != lcycle))
- return ret;
-
- return now;
-}
-
-void read_persistent_clock64(struct timespec64 *ts)
-{
- efi_gettimeofday(ts);
-}
-
-void __init
-time_init (void)
-{
- register_percpu_irq(IA64_TIMER_VECTOR, timer_interrupt, IRQF_IRQPOLL,
- "timer");
- ia64_init_itm();
-}
-
-/*
- * Generic udelay assumes that if preemption is allowed and the thread
- * migrates to another CPU, that the ITC values are synchronized across
- * all CPUs.
- */
-static void
-ia64_itc_udelay (unsigned long usecs)
-{
- unsigned long start = ia64_get_itc();
- unsigned long end = start + usecs*local_cpu_data->cyc_per_usec;
-
- while (time_before(ia64_get_itc(), end))
- cpu_relax();
-}
-
-void (*ia64_udelay)(unsigned long usecs) = &ia64_itc_udelay;
-
-void
-udelay (unsigned long usecs)
-{
- (*ia64_udelay)(usecs);
-}
-EXPORT_SYMBOL(udelay);
-
-/* IA64 doesn't cache the timezone */
-void update_vsyscall_tz(void)
-{
-}
-
-void update_vsyscall(struct timekeeper *tk)
-{
- write_seqcount_begin(&fsyscall_gtod_data.seq);
-
- /* copy vsyscall data */
- fsyscall_gtod_data.clk_mask = tk->tkr_mono.mask;
- fsyscall_gtod_data.clk_mult = tk->tkr_mono.mult;
- fsyscall_gtod_data.clk_shift = tk->tkr_mono.shift;
- fsyscall_gtod_data.clk_fsys_mmio = tk->tkr_mono.clock->archdata.fsys_mmio;
- fsyscall_gtod_data.clk_cycle_last = tk->tkr_mono.cycle_last;
-
- fsyscall_gtod_data.wall_time.sec = tk->xtime_sec;
- fsyscall_gtod_data.wall_time.snsec = tk->tkr_mono.xtime_nsec;
-
- fsyscall_gtod_data.monotonic_time.sec = tk->xtime_sec
- + tk->wall_to_monotonic.tv_sec;
- fsyscall_gtod_data.monotonic_time.snsec = tk->tkr_mono.xtime_nsec
- + ((u64)tk->wall_to_monotonic.tv_nsec
- << tk->tkr_mono.shift);
-
- /* normalize */
- while (fsyscall_gtod_data.monotonic_time.snsec >=
- (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
- fsyscall_gtod_data.monotonic_time.snsec -=
- ((u64)NSEC_PER_SEC) << tk->tkr_mono.shift;
- fsyscall_gtod_data.monotonic_time.sec++;
- }
-
- write_seqcount_end(&fsyscall_gtod_data.seq);
-}
-
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
deleted file mode 100644
index 94a848b06f15..000000000000
--- a/arch/ia64/kernel/topology.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * This file contains NUMA specific variables and functions which are used on
- * NUMA machines with contiguous memory.
- * 2002/08/07 Erich Focht <efocht@ess.nec.de>
- * Populate cpu entries in sysfs for non-numa systems as well
- * Intel Corporation - Ashok Raj
- * 02/27/2006 Zhang, Yanmin
- * Populate cpu cache entries in sysfs for cpu cache info
- */
-
-#include <linux/cpu.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/node.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/memblock.h>
-#include <linux/nodemask.h>
-#include <linux/notifier.h>
-#include <linux/export.h>
-#include <asm/mmzone.h>
-#include <asm/numa.h>
-#include <asm/cpu.h>
-
-static struct ia64_cpu *sysfs_cpus;
-
-void arch_fix_phys_package_id(int num, u32 slot)
-{
-#ifdef CONFIG_SMP
- if (cpu_data(num)->socket_id == -1)
- cpu_data(num)->socket_id = slot;
-#endif
-}
-EXPORT_SYMBOL_GPL(arch_fix_phys_package_id);
-
-
-#ifdef CONFIG_HOTPLUG_CPU
-int __ref arch_register_cpu(int num)
-{
- /*
- * If CPEI can be re-targeted or if this is not
- * CPEI target, then it is hotpluggable
- */
- if (can_cpei_retarget() || !is_cpu_cpei_target(num))
- sysfs_cpus[num].cpu.hotpluggable = 1;
- map_cpu_to_node(num, node_cpuid[num].nid);
- return register_cpu(&sysfs_cpus[num].cpu, num);
-}
-EXPORT_SYMBOL(arch_register_cpu);
-
-void __ref arch_unregister_cpu(int num)
-{
- unregister_cpu(&sysfs_cpus[num].cpu);
- unmap_cpu_from_node(num, cpu_to_node(num));
-}
-EXPORT_SYMBOL(arch_unregister_cpu);
-#else
-static int __init arch_register_cpu(int num)
-{
- return register_cpu(&sysfs_cpus[num].cpu, num);
-}
-#endif /*CONFIG_HOTPLUG_CPU*/
-
-
-static int __init topology_init(void)
-{
- int i, err = 0;
-
- sysfs_cpus = kcalloc(NR_CPUS, sizeof(struct ia64_cpu), GFP_KERNEL);
- if (!sysfs_cpus)
- panic("kzalloc in topology_init failed - NR_CPUS too big?");
-
- for_each_present_cpu(i) {
- if((err = arch_register_cpu(i)))
- goto out;
- }
-out:
- return err;
-}
-
-subsys_initcall(topology_init);
-
-
-/*
- * Export cpu cache information through sysfs
- */
-
-/*
- * A bunch of string array to get pretty printing
- */
-static const char *cache_types[] = {
- "", /* not used */
- "Instruction",
- "Data",
- "Unified" /* unified */
-};
-
-static const char *cache_mattrib[]={
- "WriteThrough",
- "WriteBack",
- "", /* reserved */
- "" /* reserved */
-};
-
-struct cache_info {
- pal_cache_config_info_t cci;
- cpumask_t shared_cpu_map;
- int level;
- int type;
- struct kobject kobj;
-};
-
-struct cpu_cache_info {
- struct cache_info *cache_leaves;
- int num_cache_leaves;
- struct kobject kobj;
-};
-
-static struct cpu_cache_info all_cpu_cache_info[NR_CPUS];
-#define LEAF_KOBJECT_PTR(x,y) (&all_cpu_cache_info[x].cache_leaves[y])
-
-#ifdef CONFIG_SMP
-static void cache_shared_cpu_map_setup(unsigned int cpu,
- struct cache_info * this_leaf)
-{
- pal_cache_shared_info_t csi;
- int num_shared, i = 0;
- unsigned int j;
-
- if (cpu_data(cpu)->threads_per_core <= 1 &&
- cpu_data(cpu)->cores_per_socket <= 1) {
- cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map);
- return;
- }
-
- if (ia64_pal_cache_shared_info(this_leaf->level,
- this_leaf->type,
- 0,
- &csi) != PAL_STATUS_SUCCESS)
- return;
-
- num_shared = (int) csi.num_shared;
- do {
- for_each_possible_cpu(j)
- if (cpu_data(cpu)->socket_id == cpu_data(j)->socket_id
- && cpu_data(j)->core_id == csi.log1_cid
- && cpu_data(j)->thread_id == csi.log1_tid)
- cpumask_set_cpu(j, &this_leaf->shared_cpu_map);
-
- i++;
- } while (i < num_shared &&
- ia64_pal_cache_shared_info(this_leaf->level,
- this_leaf->type,
- i,
- &csi) == PAL_STATUS_SUCCESS);
-}
-#else
-static void cache_shared_cpu_map_setup(unsigned int cpu,
- struct cache_info * this_leaf)
-{
- cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map);
- return;
-}
-#endif
-
-static ssize_t show_coherency_line_size(struct cache_info *this_leaf,
- char *buf)
-{
- return sprintf(buf, "%u\n", 1 << this_leaf->cci.pcci_line_size);
-}
-
-static ssize_t show_ways_of_associativity(struct cache_info *this_leaf,
- char *buf)
-{
- return sprintf(buf, "%u\n", this_leaf->cci.pcci_assoc);
-}
-
-static ssize_t show_attributes(struct cache_info *this_leaf, char *buf)
-{
- return sprintf(buf,
- "%s\n",
- cache_mattrib[this_leaf->cci.pcci_cache_attr]);
-}
-
-static ssize_t show_size(struct cache_info *this_leaf, char *buf)
-{
- return sprintf(buf, "%uK\n", this_leaf->cci.pcci_cache_size / 1024);
-}
-
-static ssize_t show_number_of_sets(struct cache_info *this_leaf, char *buf)
-{
- unsigned number_of_sets = this_leaf->cci.pcci_cache_size;
- number_of_sets /= this_leaf->cci.pcci_assoc;
- number_of_sets /= 1 << this_leaf->cci.pcci_line_size;
-
- return sprintf(buf, "%u\n", number_of_sets);
-}
-
-static ssize_t show_shared_cpu_map(struct cache_info *this_leaf, char *buf)
-{
- cpumask_t shared_cpu_map;
-
- cpumask_and(&shared_cpu_map,
- &this_leaf->shared_cpu_map, cpu_online_mask);
- return scnprintf(buf, PAGE_SIZE, "%*pb\n",
- cpumask_pr_args(&shared_cpu_map));
-}
-
-static ssize_t show_type(struct cache_info *this_leaf, char *buf)
-{
- int type = this_leaf->type + this_leaf->cci.pcci_unified;
- return sprintf(buf, "%s\n", cache_types[type]);
-}
-
-static ssize_t show_level(struct cache_info *this_leaf, char *buf)
-{
- return sprintf(buf, "%u\n", this_leaf->level);
-}
-
-struct cache_attr {
- struct attribute attr;
- ssize_t (*show)(struct cache_info *, char *);
- ssize_t (*store)(struct cache_info *, const char *, size_t count);
-};
-
-#ifdef define_one_ro
- #undef define_one_ro
-#endif
-#define define_one_ro(_name) \
- static struct cache_attr _name = \
-__ATTR(_name, 0444, show_##_name, NULL)
-
-define_one_ro(level);
-define_one_ro(type);
-define_one_ro(coherency_line_size);
-define_one_ro(ways_of_associativity);
-define_one_ro(size);
-define_one_ro(number_of_sets);
-define_one_ro(shared_cpu_map);
-define_one_ro(attributes);
-
-static struct attribute * cache_default_attrs[] = {
- &type.attr,
- &level.attr,
- &coherency_line_size.attr,
- &ways_of_associativity.attr,
- &attributes.attr,
- &size.attr,
- &number_of_sets.attr,
- &shared_cpu_map.attr,
- NULL
-};
-ATTRIBUTE_GROUPS(cache_default);
-
-#define to_object(k) container_of(k, struct cache_info, kobj)
-#define to_attr(a) container_of(a, struct cache_attr, attr)
-
-static ssize_t ia64_cache_show(struct kobject * kobj, struct attribute * attr, char * buf)
-{
- struct cache_attr *fattr = to_attr(attr);
- struct cache_info *this_leaf = to_object(kobj);
- ssize_t ret;
-
- ret = fattr->show ? fattr->show(this_leaf, buf) : 0;
- return ret;
-}
-
-static const struct sysfs_ops cache_sysfs_ops = {
- .show = ia64_cache_show
-};
-
-static struct kobj_type cache_ktype = {
- .sysfs_ops = &cache_sysfs_ops,
- .default_groups = cache_default_groups,
-};
-
-static struct kobj_type cache_ktype_percpu_entry = {
- .sysfs_ops = &cache_sysfs_ops,
-};
-
-static void cpu_cache_sysfs_exit(unsigned int cpu)
-{
- kfree(all_cpu_cache_info[cpu].cache_leaves);
- all_cpu_cache_info[cpu].cache_leaves = NULL;
- all_cpu_cache_info[cpu].num_cache_leaves = 0;
- memset(&all_cpu_cache_info[cpu].kobj, 0, sizeof(struct kobject));
- return;
-}
-
-static int cpu_cache_sysfs_init(unsigned int cpu)
-{
- unsigned long i, levels, unique_caches;
- pal_cache_config_info_t cci;
- int j;
- long status;
- struct cache_info *this_cache;
- int num_cache_leaves = 0;
-
- if ((status = ia64_pal_cache_summary(&levels, &unique_caches)) != 0) {
- printk(KERN_ERR "ia64_pal_cache_summary=%ld\n", status);
- return -1;
- }
-
- this_cache=kcalloc(unique_caches, sizeof(struct cache_info),
- GFP_KERNEL);
- if (this_cache == NULL)
- return -ENOMEM;
-
- for (i=0; i < levels; i++) {
- for (j=2; j >0 ; j--) {
- if ((status=ia64_pal_cache_config_info(i,j, &cci)) !=
- PAL_STATUS_SUCCESS)
- continue;
-
- this_cache[num_cache_leaves].cci = cci;
- this_cache[num_cache_leaves].level = i + 1;
- this_cache[num_cache_leaves].type = j;
-
- cache_shared_cpu_map_setup(cpu,
- &this_cache[num_cache_leaves]);
- num_cache_leaves ++;
- }
- }
-
- all_cpu_cache_info[cpu].cache_leaves = this_cache;
- all_cpu_cache_info[cpu].num_cache_leaves = num_cache_leaves;
-
- memset(&all_cpu_cache_info[cpu].kobj, 0, sizeof(struct kobject));
-
- return 0;
-}
-
-/* Add cache interface for CPU device */
-static int cache_add_dev(unsigned int cpu)
-{
- struct device *sys_dev = get_cpu_device(cpu);
- unsigned long i, j;
- struct cache_info *this_object;
- int retval = 0;
-
- if (all_cpu_cache_info[cpu].kobj.parent)
- return 0;
-
-
- retval = cpu_cache_sysfs_init(cpu);
- if (unlikely(retval < 0))
- return retval;
-
- retval = kobject_init_and_add(&all_cpu_cache_info[cpu].kobj,
- &cache_ktype_percpu_entry, &sys_dev->kobj,
- "%s", "cache");
- if (unlikely(retval < 0)) {
- cpu_cache_sysfs_exit(cpu);
- return retval;
- }
-
- for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++) {
- this_object = LEAF_KOBJECT_PTR(cpu,i);
- retval = kobject_init_and_add(&(this_object->kobj),
- &cache_ktype,
- &all_cpu_cache_info[cpu].kobj,
- "index%1lu", i);
- if (unlikely(retval)) {
- for (j = 0; j < i; j++) {
- kobject_put(&(LEAF_KOBJECT_PTR(cpu,j)->kobj));
- }
- kobject_put(&all_cpu_cache_info[cpu].kobj);
- cpu_cache_sysfs_exit(cpu);
- return retval;
- }
- kobject_uevent(&(this_object->kobj), KOBJ_ADD);
- }
- kobject_uevent(&all_cpu_cache_info[cpu].kobj, KOBJ_ADD);
- return retval;
-}
-
-/* Remove cache interface for CPU device */
-static int cache_remove_dev(unsigned int cpu)
-{
- unsigned long i;
-
- for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++)
- kobject_put(&(LEAF_KOBJECT_PTR(cpu,i)->kobj));
-
- if (all_cpu_cache_info[cpu].kobj.parent) {
- kobject_put(&all_cpu_cache_info[cpu].kobj);
- memset(&all_cpu_cache_info[cpu].kobj,
- 0,
- sizeof(struct kobject));
- }
-
- cpu_cache_sysfs_exit(cpu);
-
- return 0;
-}
-
-static int __init cache_sysfs_init(void)
-{
- int ret;
-
- ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/topology:online",
- cache_add_dev, cache_remove_dev);
- WARN_ON(ret < 0);
- return 0;
-}
-device_initcall(cache_sysfs_init);
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
deleted file mode 100644
index 53735b1d1be3..000000000000
--- a/arch/ia64/kernel/traps.c
+++ /dev/null
@@ -1,612 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Architecture-specific trap handling.
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sched/signal.h>
-#include <linux/sched/debug.h>
-#include <linux/tty.h>
-#include <linux/vt_kern.h> /* For unblank_screen() */
-#include <linux/export.h>
-#include <linux/extable.h>
-#include <linux/hardirq.h>
-#include <linux/kprobes.h>
-#include <linux/delay.h> /* for ssleep() */
-#include <linux/kdebug.h>
-#include <linux/uaccess.h>
-
-#include <asm/fpswa.h>
-#include <asm/intrinsics.h>
-#include <asm/processor.h>
-#include <asm/exception.h>
-#include <asm/setup.h>
-
-fpswa_interface_t *fpswa_interface;
-EXPORT_SYMBOL(fpswa_interface);
-
-void __init
-trap_init (void)
-{
- if (ia64_boot_param->fpswa)
- /* FPSWA fixup: make the interface pointer a kernel virtual address: */
- fpswa_interface = __va(ia64_boot_param->fpswa);
-}
-
-int
-die (const char *str, struct pt_regs *regs, long err)
-{
- static struct {
- spinlock_t lock;
- u32 lock_owner;
- int lock_owner_depth;
- } die = {
- .lock = __SPIN_LOCK_UNLOCKED(die.lock),
- .lock_owner = -1,
- .lock_owner_depth = 0
- };
- static int die_counter;
- int cpu = get_cpu();
-
- if (die.lock_owner != cpu) {
- console_verbose();
- spin_lock_irq(&die.lock);
- die.lock_owner = cpu;
- die.lock_owner_depth = 0;
- bust_spinlocks(1);
- }
- put_cpu();
-
- if (++die.lock_owner_depth < 3) {
- printk("%s[%d]: %s %ld [%d]\n",
- current->comm, task_pid_nr(current), str, err, ++die_counter);
- if (notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV)
- != NOTIFY_STOP)
- show_regs(regs);
- else
- regs = NULL;
- } else
- printk(KERN_ERR "Recursive die() failure, output suppressed\n");
-
- bust_spinlocks(0);
- die.lock_owner = -1;
- add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
- spin_unlock_irq(&die.lock);
-
- if (!regs)
- return 1;
-
- if (panic_on_oops)
- panic("Fatal exception");
-
- make_task_dead(SIGSEGV);
- return 0;
-}
-
-int
-die_if_kernel (char *str, struct pt_regs *regs, long err)
-{
- if (!user_mode(regs))
- return die(str, regs, err);
- return 0;
-}
-
-void
-__kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
-{
- int sig, code;
-
- switch (break_num) {
- case 0: /* unknown error (used by GCC for __builtin_abort()) */
- if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP)
- == NOTIFY_STOP)
- return;
- if (die_if_kernel("bugcheck!", regs, break_num))
- return;
- sig = SIGILL; code = ILL_ILLOPC;
- break;
-
- case 1: /* integer divide by zero */
- sig = SIGFPE; code = FPE_INTDIV;
- break;
-
- case 2: /* integer overflow */
- sig = SIGFPE; code = FPE_INTOVF;
- break;
-
- case 3: /* range check/bounds check */
- sig = SIGFPE; code = FPE_FLTSUB;
- break;
-
- case 4: /* null pointer dereference */
- sig = SIGSEGV; code = SEGV_MAPERR;
- break;
-
- case 5: /* misaligned data */
- sig = SIGSEGV; code = BUS_ADRALN;
- break;
-
- case 6: /* decimal overflow */
- sig = SIGFPE; code = __FPE_DECOVF;
- break;
-
- case 7: /* decimal divide by zero */
- sig = SIGFPE; code = __FPE_DECDIV;
- break;
-
- case 8: /* packed decimal error */
- sig = SIGFPE; code = __FPE_DECERR;
- break;
-
- case 9: /* invalid ASCII digit */
- sig = SIGFPE; code = __FPE_INVASC;
- break;
-
- case 10: /* invalid decimal digit */
- sig = SIGFPE; code = __FPE_INVDEC;
- break;
-
- case 11: /* paragraph stack overflow */
- sig = SIGSEGV; code = __SEGV_PSTKOVF;
- break;
-
- case 0x3f000 ... 0x3ffff: /* bundle-update in progress */
- sig = SIGILL; code = __ILL_BNDMOD;
- break;
-
- default:
- if ((break_num < 0x40000 || break_num > 0x100000)
- && die_if_kernel("Bad break", regs, break_num))
- return;
-
- if (break_num < 0x80000) {
- sig = SIGILL; code = __ILL_BREAK;
- } else {
- if (notify_die(DIE_BREAK, "bad break", regs, break_num, TRAP_BRKPT, SIGTRAP)
- == NOTIFY_STOP)
- return;
- sig = SIGTRAP; code = TRAP_BRKPT;
- }
- }
- force_sig_fault(sig, code,
- (void __user *) (regs->cr_iip + ia64_psr(regs)->ri),
- break_num, 0 /* clear __ISR_VALID */, 0);
-}
-
-/*
- * disabled_fph_fault() is called when a user-level process attempts to access f32..f127
- * and it doesn't own the fp-high register partition. When this happens, we save the
- * current fph partition in the task_struct of the fpu-owner (if necessary) and then load
- * the fp-high partition of the current task (if necessary). Note that the kernel has
- * access to fph by the time we get here, as the IVT's "Disabled FP-Register" handler takes
- * care of clearing psr.dfh.
- */
-static inline void
-disabled_fph_fault (struct pt_regs *regs)
-{
- struct ia64_psr *psr = ia64_psr(regs);
-
- /* first, grant user-level access to fph partition: */
- psr->dfh = 0;
-
- /*
- * Make sure that no other task gets in on this processor
- * while we're claiming the FPU
- */
- preempt_disable();
-#ifndef CONFIG_SMP
- {
- struct task_struct *fpu_owner
- = (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER);
-
- if (ia64_is_local_fpu_owner(current)) {
- preempt_enable_no_resched();
- return;
- }
-
- if (fpu_owner)
- ia64_flush_fph(fpu_owner);
- }
-#endif /* !CONFIG_SMP */
- ia64_set_local_fpu_owner(current);
- if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) {
- __ia64_load_fpu(current->thread.fph);
- psr->mfh = 0;
- } else {
- __ia64_init_fpu();
- /*
- * Set mfh because the state in thread.fph does not match the state in
- * the fph partition.
- */
- psr->mfh = 1;
- }
- preempt_enable_no_resched();
-}
-
-static inline int
-fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long *pr, long *ifs,
- struct pt_regs *regs)
-{
- fp_state_t fp_state;
- fpswa_ret_t ret;
-
- if (!fpswa_interface)
- return -1;
-
- memset(&fp_state, 0, sizeof(fp_state_t));
-
- /*
- * compute fp_state. only FP registers f6 - f11 are used by the
- * kernel, so set those bits in the mask and set the low volatile
- * pointer to point to these registers.
- */
- fp_state.bitmask_low64 = 0xfc0; /* bit6..bit11 */
-
- fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) &regs->f6;
- /*
- * unsigned long (*EFI_FPSWA) (
- * unsigned long trap_type,
- * void *Bundle,
- * unsigned long *pipsr,
- * unsigned long *pfsr,
- * unsigned long *pisr,
- * unsigned long *ppreds,
- * unsigned long *pifs,
- * void *fp_state);
- */
- ret = (*fpswa_interface->fpswa)((unsigned long) fp_fault, bundle,
- (unsigned long *) ipsr, (unsigned long *) fpsr,
- (unsigned long *) isr, (unsigned long *) pr,
- (unsigned long *) ifs, &fp_state);
-
- return ret.status;
-}
-
-struct fpu_swa_msg {
- unsigned long count;
- unsigned long time;
-};
-static DEFINE_PER_CPU(struct fpu_swa_msg, cpulast);
-DECLARE_PER_CPU(struct fpu_swa_msg, cpulast);
-static struct fpu_swa_msg last __cacheline_aligned;
-
-
-/*
- * Handle floating-point assist faults and traps.
- */
-static int
-handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
-{
- long exception, bundle[2];
- unsigned long fault_ip;
-
- fault_ip = regs->cr_iip;
- if (!fp_fault && (ia64_psr(regs)->ri == 0))
- fault_ip -= 16;
- if (copy_from_user(bundle, (void __user *) fault_ip, sizeof(bundle)))
- return -1;
-
- if (!(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
- unsigned long count, current_jiffies = jiffies;
- struct fpu_swa_msg *cp = this_cpu_ptr(&cpulast);
-
- if (unlikely(current_jiffies > cp->time))
- cp->count = 0;
- if (unlikely(cp->count < 5)) {
- cp->count++;
- cp->time = current_jiffies + 5 * HZ;
-
- /* minimize races by grabbing a copy of count BEFORE checking last.time. */
- count = last.count;
- barrier();
-
- /*
- * Lower 4 bits are used as a count. Upper bits are a sequence
- * number that is updated when count is reset. The cmpxchg will
- * fail is seqno has changed. This minimizes multiple cpus
- * resetting the count.
- */
- if (current_jiffies > last.time)
- (void) cmpxchg_acq(&last.count, count, 16 + (count & ~15));
-
- /* used fetchadd to atomically update the count */
- if ((last.count & 15) < 5 && (ia64_fetchadd(1, &last.count, acq) & 15) < 5) {
- last.time = current_jiffies + 5 * HZ;
- printk(KERN_WARNING
- "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
- current->comm, task_pid_nr(current), regs->cr_iip + ia64_psr(regs)->ri, isr);
- }
- }
- }
-
- exception = fp_emulate(fp_fault, bundle, &regs->cr_ipsr, &regs->ar_fpsr, &isr, &regs->pr,
- &regs->cr_ifs, regs);
- if (fp_fault) {
- if (exception == 0) {
- /* emulation was successful */
- ia64_increment_ip(regs);
- } else if (exception == -1) {
- printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
- return -1;
- } else {
- /* is next instruction a trap? */
- int si_code;
-
- if (exception & 2) {
- ia64_increment_ip(regs);
- }
- si_code = FPE_FLTUNK; /* default code */
- if (isr & 0x11) {
- si_code = FPE_FLTINV;
- } else if (isr & 0x22) {
- /* denormal operand gets the same si_code as underflow
- * see arch/i386/kernel/traps.c:math_error() */
- si_code = FPE_FLTUND;
- } else if (isr & 0x44) {
- si_code = FPE_FLTDIV;
- }
- force_sig_fault(SIGFPE, si_code,
- (void __user *) (regs->cr_iip + ia64_psr(regs)->ri),
- 0, __ISR_VALID, isr);
- }
- } else {
- if (exception == -1) {
- printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
- return -1;
- } else if (exception != 0) {
- /* raise exception */
- int si_code;
-
- si_code = FPE_FLTUNK; /* default code */
- if (isr & 0x880) {
- si_code = FPE_FLTOVF;
- } else if (isr & 0x1100) {
- si_code = FPE_FLTUND;
- } else if (isr & 0x2200) {
- si_code = FPE_FLTRES;
- }
- force_sig_fault(SIGFPE, si_code,
- (void __user *) (regs->cr_iip + ia64_psr(regs)->ri),
- 0, __ISR_VALID, isr);
- }
- }
- return 0;
-}
-
-struct illegal_op_return {
- unsigned long fkt, arg1, arg2, arg3;
-};
-
-struct illegal_op_return
-ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
- long arg4, long arg5, long arg6, long arg7,
- struct pt_regs regs)
-{
- struct illegal_op_return rv;
- char buf[128];
-
-#ifdef CONFIG_IA64_BRL_EMU
- {
- extern struct illegal_op_return ia64_emulate_brl (struct pt_regs *, unsigned long);
-
- rv = ia64_emulate_brl(&regs, ec);
- if (rv.fkt != (unsigned long) -1)
- return rv;
- }
-#endif
-
- sprintf(buf, "IA-64 Illegal operation fault");
- rv.fkt = 0;
- if (die_if_kernel(buf, &regs, 0))
- return rv;
-
- force_sig_fault(SIGILL, ILL_ILLOPC,
- (void __user *) (regs.cr_iip + ia64_psr(&regs)->ri),
- 0, 0, 0);
- return rv;
-}
-
-void __kprobes
-ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
- unsigned long iim, unsigned long itir, long arg5, long arg6,
- long arg7, struct pt_regs regs)
-{
- unsigned long code, error = isr, iip;
- char buf[128];
- int result, sig, si_code;
- static const char *reason[] = {
- "IA-64 Illegal Operation fault",
- "IA-64 Privileged Operation fault",
- "IA-64 Privileged Register fault",
- "IA-64 Reserved Register/Field fault",
- "Disabled Instruction Set Transition fault",
- "Unknown fault 5", "Unknown fault 6", "Unknown fault 7", "Illegal Hazard fault",
- "Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12",
- "Unknown fault 13", "Unknown fault 14", "Unknown fault 15"
- };
-
- if ((isr & IA64_ISR_NA) && ((isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) {
- /*
- * This fault was due to lfetch.fault, set "ed" bit in the psr to cancel
- * the lfetch.
- */
- ia64_psr(&regs)->ed = 1;
- return;
- }
-
- iip = regs.cr_iip + ia64_psr(&regs)->ri;
-
- switch (vector) {
- case 24: /* General Exception */
- code = (isr >> 4) & 0xf;
- sprintf(buf, "General Exception: %s%s", reason[code],
- (code == 3) ? ((isr & (1UL << 37))
- ? " (RSE access)" : " (data access)") : "");
- if (code == 8) {
-# ifdef CONFIG_IA64_PRINT_HAZARDS
- printk("%s[%d]: possible hazard @ ip=%016lx (pr = %016lx)\n",
- current->comm, task_pid_nr(current),
- regs.cr_iip + ia64_psr(&regs)->ri, regs.pr);
-# endif
- return;
- }
- break;
-
- case 25: /* Disabled FP-Register */
- if (isr & 2) {
- disabled_fph_fault(&regs);
- return;
- }
- sprintf(buf, "Disabled FPL fault---not supposed to happen!");
- break;
-
- case 26: /* NaT Consumption */
- if (user_mode(&regs)) {
- void __user *addr;
-
- if (((isr >> 4) & 0xf) == 2) {
- /* NaT page consumption */
- sig = SIGSEGV;
- code = SEGV_ACCERR;
- addr = (void __user *) ifa;
- } else {
- /* register NaT consumption */
- sig = SIGILL;
- code = ILL_ILLOPN;
- addr = (void __user *) (regs.cr_iip
- + ia64_psr(&regs)->ri);
- }
- force_sig_fault(sig, code, addr,
- vector, __ISR_VALID, isr);
- return;
- } else if (ia64_done_with_exception(&regs))
- return;
- sprintf(buf, "NaT consumption");
- break;
-
- case 31: /* Unsupported Data Reference */
- if (user_mode(&regs)) {
- force_sig_fault(SIGILL, ILL_ILLOPN, (void __user *) iip,
- vector, __ISR_VALID, isr);
- return;
- }
- sprintf(buf, "Unsupported data reference");
- break;
-
- case 29: /* Debug */
- case 35: /* Taken Branch Trap */
- case 36: /* Single Step Trap */
- if (fsys_mode(current, &regs)) {
- extern char __kernel_syscall_via_break[];
- /*
- * Got a trap in fsys-mode: Taken Branch Trap
- * and Single Step trap need special handling;
- * Debug trap is ignored (we disable it here
- * and re-enable it in the lower-privilege trap).
- */
- if (unlikely(vector == 29)) {
- set_thread_flag(TIF_DB_DISABLED);
- ia64_psr(&regs)->db = 0;
- ia64_psr(&regs)->lp = 1;
- return;
- }
- /* re-do the system call via break 0x100000: */
- regs.cr_iip = (unsigned long) __kernel_syscall_via_break;
- ia64_psr(&regs)->ri = 0;
- ia64_psr(&regs)->cpl = 3;
- return;
- }
- switch (vector) {
- default:
- case 29:
- si_code = TRAP_HWBKPT;
-#ifdef CONFIG_ITANIUM
- /*
- * Erratum 10 (IFA may contain incorrect address) now has
- * "NoFix" status. There are no plans for fixing this.
- */
- if (ia64_psr(&regs)->is == 0)
- ifa = regs.cr_iip;
-#endif
- break;
- case 35: si_code = TRAP_BRANCH; ifa = 0; break;
- case 36: si_code = TRAP_TRACE; ifa = 0; break;
- }
- if (notify_die(DIE_FAULT, "ia64_fault", &regs, vector, si_code, SIGTRAP)
- == NOTIFY_STOP)
- return;
- force_sig_fault(SIGTRAP, si_code, (void __user *) ifa,
- 0, __ISR_VALID, isr);
- return;
-
- case 32: /* fp fault */
- case 33: /* fp trap */
- result = handle_fpu_swa((vector == 32) ? 1 : 0, &regs, isr);
- if ((result < 0) || (current->thread.flags & IA64_THREAD_FPEMU_SIGFPE)) {
- force_sig_fault(SIGFPE, FPE_FLTINV, (void __user *) iip,
- 0, __ISR_VALID, isr);
- }
- return;
-
- case 34:
- if (isr & 0x2) {
- /* Lower-Privilege Transfer Trap */
-
- /* If we disabled debug traps during an fsyscall,
- * re-enable them here.
- */
- if (test_thread_flag(TIF_DB_DISABLED)) {
- clear_thread_flag(TIF_DB_DISABLED);
- ia64_psr(&regs)->db = 1;
- }
-
- /*
- * Just clear PSR.lp and then return immediately:
- * all the interesting work (e.g., signal delivery)
- * is done in the kernel exit path.
- */
- ia64_psr(&regs)->lp = 0;
- return;
- } else {
- /* Unimplemented Instr. Address Trap */
- if (user_mode(&regs)) {
- force_sig_fault(SIGILL, ILL_BADIADDR,
- (void __user *) iip,
- 0, 0, 0);
- return;
- }
- sprintf(buf, "Unimplemented Instruction Address fault");
- }
- break;
-
- case 45:
- printk(KERN_ERR "Unexpected IA-32 exception (Trap 45)\n");
- printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n",
- iip, ifa, isr);
- force_sig(SIGSEGV);
- return;
-
- case 46:
- printk(KERN_ERR "Unexpected IA-32 intercept trap (Trap 46)\n");
- printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n",
- iip, ifa, isr, iim);
- force_sig(SIGSEGV);
- return;
-
- case 47:
- sprintf(buf, "IA-32 Interruption Fault (int 0x%lx)", isr >> 16);
- break;
-
- default:
- sprintf(buf, "Fault %lu", vector);
- break;
- }
- if (!die_if_kernel(buf, &regs, error))
- force_sig(SIGILL);
-}
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
deleted file mode 100644
index 0acb5a0cd7ab..000000000000
--- a/arch/ia64/kernel/unaligned.c
+++ /dev/null
@@ -1,1560 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Architecture-specific unaligned trap handling.
- *
- * Copyright (C) 1999-2002, 2004 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * 2002/12/09 Fix rotating register handling (off-by-1 error, missing fr-rotation). Fix
- * get_rse_reg() to not leak kernel bits to user-level (reading an out-of-frame
- * stacked register returns an undefined value; it does NOT trigger a
- * "rsvd register fault").
- * 2001/10/11 Fix unaligned access to rotating registers in s/w pipelined loops.
- * 2001/08/13 Correct size of extended floats (float_fsz) from 16 to 10 bytes.
- * 2001/01/17 Add support emulation of unaligned kernel accesses.
- */
-#include <linux/jiffies.h>
-#include <linux/kernel.h>
-#include <linux/sched/signal.h>
-#include <linux/tty.h>
-#include <linux/extable.h>
-#include <linux/ratelimit.h>
-#include <linux/uaccess.h>
-
-#include <asm/intrinsics.h>
-#include <asm/processor.h>
-#include <asm/rse.h>
-#include <asm/exception.h>
-#include <asm/unaligned.h>
-
-extern int die_if_kernel(char *str, struct pt_regs *regs, long err);
-
-#undef DEBUG_UNALIGNED_TRAP
-
-#ifdef DEBUG_UNALIGNED_TRAP
-# define DPRINT(a...) do { printk("%s %u: ", __func__, __LINE__); printk (a); } while (0)
-# define DDUMP(str,vp,len) dump(str, vp, len)
-
-static void
-dump (const char *str, void *vp, size_t len)
-{
- unsigned char *cp = vp;
- int i;
-
- printk("%s", str);
- for (i = 0; i < len; ++i)
- printk (" %02x", *cp++);
- printk("\n");
-}
-#else
-# define DPRINT(a...)
-# define DDUMP(str,vp,len)
-#endif
-
-#define IA64_FIRST_STACKED_GR 32
-#define IA64_FIRST_ROTATING_FR 32
-#define SIGN_EXT9 0xffffffffffffff00ul
-
-/*
- * sysctl settable hook which tells the kernel whether to honor the
- * IA64_THREAD_UAC_NOPRINT prctl. Because this is user settable, we want
- * to allow the super user to enable/disable this for security reasons
- * (i.e. don't allow attacker to fill up logs with unaligned accesses).
- */
-int no_unaligned_warning;
-int unaligned_dump_stack;
-
-/*
- * For M-unit:
- *
- * opcode | m | x6 |
- * --------|------|---------|
- * [40-37] | [36] | [35:30] |
- * --------|------|---------|
- * 4 | 1 | 6 | = 11 bits
- * --------------------------
- * However bits [31:30] are not directly useful to distinguish between
- * load/store so we can use [35:32] instead, which gives the following
- * mask ([40:32]) using 9 bits. The 'e' comes from the fact that we defer
- * checking the m-bit until later in the load/store emulation.
- */
-#define IA64_OPCODE_MASK 0x1ef
-#define IA64_OPCODE_SHIFT 32
-
-/*
- * Table C-28 Integer Load/Store
- *
- * We ignore [35:32]= 0x6, 0x7, 0xE, 0xF
- *
- * ld8.fill, st8.fill MUST be aligned because the RNATs are based on
- * the address (bits [8:3]), so we must failed.
- */
-#define LD_OP 0x080
-#define LDS_OP 0x081
-#define LDA_OP 0x082
-#define LDSA_OP 0x083
-#define LDBIAS_OP 0x084
-#define LDACQ_OP 0x085
-/* 0x086, 0x087 are not relevant */
-#define LDCCLR_OP 0x088
-#define LDCNC_OP 0x089
-#define LDCCLRACQ_OP 0x08a
-#define ST_OP 0x08c
-#define STREL_OP 0x08d
-/* 0x08e,0x8f are not relevant */
-
-/*
- * Table C-29 Integer Load +Reg
- *
- * we use the ld->m (bit [36:36]) field to determine whether or not we have
- * a load/store of this form.
- */
-
-/*
- * Table C-30 Integer Load/Store +Imm
- *
- * We ignore [35:32]= 0x6, 0x7, 0xE, 0xF
- *
- * ld8.fill, st8.fill must be aligned because the Nat register are based on
- * the address, so we must fail and the program must be fixed.
- */
-#define LD_IMM_OP 0x0a0
-#define LDS_IMM_OP 0x0a1
-#define LDA_IMM_OP 0x0a2
-#define LDSA_IMM_OP 0x0a3
-#define LDBIAS_IMM_OP 0x0a4
-#define LDACQ_IMM_OP 0x0a5
-/* 0x0a6, 0xa7 are not relevant */
-#define LDCCLR_IMM_OP 0x0a8
-#define LDCNC_IMM_OP 0x0a9
-#define LDCCLRACQ_IMM_OP 0x0aa
-#define ST_IMM_OP 0x0ac
-#define STREL_IMM_OP 0x0ad
-/* 0x0ae,0xaf are not relevant */
-
-/*
- * Table C-32 Floating-point Load/Store
- */
-#define LDF_OP 0x0c0
-#define LDFS_OP 0x0c1
-#define LDFA_OP 0x0c2
-#define LDFSA_OP 0x0c3
-/* 0x0c6 is irrelevant */
-#define LDFCCLR_OP 0x0c8
-#define LDFCNC_OP 0x0c9
-/* 0x0cb is irrelevant */
-#define STF_OP 0x0cc
-
-/*
- * Table C-33 Floating-point Load +Reg
- *
- * we use the ld->m (bit [36:36]) field to determine whether or not we have
- * a load/store of this form.
- */
-
-/*
- * Table C-34 Floating-point Load/Store +Imm
- */
-#define LDF_IMM_OP 0x0e0
-#define LDFS_IMM_OP 0x0e1
-#define LDFA_IMM_OP 0x0e2
-#define LDFSA_IMM_OP 0x0e3
-/* 0x0e6 is irrelevant */
-#define LDFCCLR_IMM_OP 0x0e8
-#define LDFCNC_IMM_OP 0x0e9
-#define STF_IMM_OP 0x0ec
-
-typedef struct {
- unsigned long qp:6; /* [0:5] */
- unsigned long r1:7; /* [6:12] */
- unsigned long imm:7; /* [13:19] */
- unsigned long r3:7; /* [20:26] */
- unsigned long x:1; /* [27:27] */
- unsigned long hint:2; /* [28:29] */
- unsigned long x6_sz:2; /* [30:31] */
- unsigned long x6_op:4; /* [32:35], x6 = x6_sz|x6_op */
- unsigned long m:1; /* [36:36] */
- unsigned long op:4; /* [37:40] */
- unsigned long pad:23; /* [41:63] */
-} load_store_t;
-
-
-typedef enum {
- UPD_IMMEDIATE, /* ldXZ r1=[r3],imm(9) */
- UPD_REG /* ldXZ r1=[r3],r2 */
-} update_t;
-
-/*
- * We use tables to keep track of the offsets of registers in the saved state.
- * This way we save having big switch/case statements.
- *
- * We use bit 0 to indicate switch_stack or pt_regs.
- * The offset is simply shifted by 1 bit.
- * A 2-byte value should be enough to hold any kind of offset
- *
- * In case the calling convention changes (and thus pt_regs/switch_stack)
- * simply use RSW instead of RPT or vice-versa.
- */
-
-#define RPO(x) ((size_t) &((struct pt_regs *)0)->x)
-#define RSO(x) ((size_t) &((struct switch_stack *)0)->x)
-
-#define RPT(x) (RPO(x) << 1)
-#define RSW(x) (1| RSO(x)<<1)
-
-#define GR_OFFS(x) (gr_info[x]>>1)
-#define GR_IN_SW(x) (gr_info[x] & 0x1)
-
-#define FR_OFFS(x) (fr_info[x]>>1)
-#define FR_IN_SW(x) (fr_info[x] & 0x1)
-
-static u16 gr_info[32]={
- 0, /* r0 is read-only : WE SHOULD NEVER GET THIS */
-
- RPT(r1), RPT(r2), RPT(r3),
-
- RSW(r4), RSW(r5), RSW(r6), RSW(r7),
-
- RPT(r8), RPT(r9), RPT(r10), RPT(r11),
- RPT(r12), RPT(r13), RPT(r14), RPT(r15),
-
- RPT(r16), RPT(r17), RPT(r18), RPT(r19),
- RPT(r20), RPT(r21), RPT(r22), RPT(r23),
- RPT(r24), RPT(r25), RPT(r26), RPT(r27),
- RPT(r28), RPT(r29), RPT(r30), RPT(r31)
-};
-
-static u16 fr_info[32]={
- 0, /* constant : WE SHOULD NEVER GET THIS */
- 0, /* constant : WE SHOULD NEVER GET THIS */
-
- RSW(f2), RSW(f3), RSW(f4), RSW(f5),
-
- RPT(f6), RPT(f7), RPT(f8), RPT(f9),
- RPT(f10), RPT(f11),
-
- RSW(f12), RSW(f13), RSW(f14),
- RSW(f15), RSW(f16), RSW(f17), RSW(f18), RSW(f19),
- RSW(f20), RSW(f21), RSW(f22), RSW(f23), RSW(f24),
- RSW(f25), RSW(f26), RSW(f27), RSW(f28), RSW(f29),
- RSW(f30), RSW(f31)
-};
-
-/* Invalidate ALAT entry for integer register REGNO. */
-static void
-invala_gr (int regno)
-{
-# define F(reg) case reg: ia64_invala_gr(reg); break
-
- switch (regno) {
- F( 0); F( 1); F( 2); F( 3); F( 4); F( 5); F( 6); F( 7);
- F( 8); F( 9); F( 10); F( 11); F( 12); F( 13); F( 14); F( 15);
- F( 16); F( 17); F( 18); F( 19); F( 20); F( 21); F( 22); F( 23);
- F( 24); F( 25); F( 26); F( 27); F( 28); F( 29); F( 30); F( 31);
- F( 32); F( 33); F( 34); F( 35); F( 36); F( 37); F( 38); F( 39);
- F( 40); F( 41); F( 42); F( 43); F( 44); F( 45); F( 46); F( 47);
- F( 48); F( 49); F( 50); F( 51); F( 52); F( 53); F( 54); F( 55);
- F( 56); F( 57); F( 58); F( 59); F( 60); F( 61); F( 62); F( 63);
- F( 64); F( 65); F( 66); F( 67); F( 68); F( 69); F( 70); F( 71);
- F( 72); F( 73); F( 74); F( 75); F( 76); F( 77); F( 78); F( 79);
- F( 80); F( 81); F( 82); F( 83); F( 84); F( 85); F( 86); F( 87);
- F( 88); F( 89); F( 90); F( 91); F( 92); F( 93); F( 94); F( 95);
- F( 96); F( 97); F( 98); F( 99); F(100); F(101); F(102); F(103);
- F(104); F(105); F(106); F(107); F(108); F(109); F(110); F(111);
- F(112); F(113); F(114); F(115); F(116); F(117); F(118); F(119);
- F(120); F(121); F(122); F(123); F(124); F(125); F(126); F(127);
- }
-# undef F
-}
-
-/* Invalidate ALAT entry for floating-point register REGNO. */
-static void
-invala_fr (int regno)
-{
-# define F(reg) case reg: ia64_invala_fr(reg); break
-
- switch (regno) {
- F( 0); F( 1); F( 2); F( 3); F( 4); F( 5); F( 6); F( 7);
- F( 8); F( 9); F( 10); F( 11); F( 12); F( 13); F( 14); F( 15);
- F( 16); F( 17); F( 18); F( 19); F( 20); F( 21); F( 22); F( 23);
- F( 24); F( 25); F( 26); F( 27); F( 28); F( 29); F( 30); F( 31);
- F( 32); F( 33); F( 34); F( 35); F( 36); F( 37); F( 38); F( 39);
- F( 40); F( 41); F( 42); F( 43); F( 44); F( 45); F( 46); F( 47);
- F( 48); F( 49); F( 50); F( 51); F( 52); F( 53); F( 54); F( 55);
- F( 56); F( 57); F( 58); F( 59); F( 60); F( 61); F( 62); F( 63);
- F( 64); F( 65); F( 66); F( 67); F( 68); F( 69); F( 70); F( 71);
- F( 72); F( 73); F( 74); F( 75); F( 76); F( 77); F( 78); F( 79);
- F( 80); F( 81); F( 82); F( 83); F( 84); F( 85); F( 86); F( 87);
- F( 88); F( 89); F( 90); F( 91); F( 92); F( 93); F( 94); F( 95);
- F( 96); F( 97); F( 98); F( 99); F(100); F(101); F(102); F(103);
- F(104); F(105); F(106); F(107); F(108); F(109); F(110); F(111);
- F(112); F(113); F(114); F(115); F(116); F(117); F(118); F(119);
- F(120); F(121); F(122); F(123); F(124); F(125); F(126); F(127);
- }
-# undef F
-}
-
-static inline unsigned long
-rotate_reg (unsigned long sor, unsigned long rrb, unsigned long reg)
-{
- reg += rrb;
- if (reg >= sor)
- reg -= sor;
- return reg;
-}
-
-static void
-set_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long val, int nat)
-{
- struct switch_stack *sw = (struct switch_stack *) regs - 1;
- unsigned long *bsp, *bspstore, *addr, *rnat_addr, *ubs_end;
- unsigned long *kbs = (void *) current + IA64_RBS_OFFSET;
- unsigned long rnats, nat_mask;
- unsigned long on_kbs;
- long sof = (regs->cr_ifs) & 0x7f;
- long sor = 8 * ((regs->cr_ifs >> 14) & 0xf);
- long rrb_gr = (regs->cr_ifs >> 18) & 0x7f;
- long ridx = r1 - 32;
-
- if (ridx >= sof) {
- /* this should never happen, as the "rsvd register fault" has higher priority */
- DPRINT("ignoring write to r%lu; only %lu registers are allocated!\n", r1, sof);
- return;
- }
-
- if (ridx < sor)
- ridx = rotate_reg(sor, rrb_gr, ridx);
-
- DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n",
- r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx);
-
- on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore);
- addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + ridx);
- if (addr >= kbs) {
- /* the register is on the kernel backing store: easy... */
- rnat_addr = ia64_rse_rnat_addr(addr);
- if ((unsigned long) rnat_addr >= sw->ar_bspstore)
- rnat_addr = &sw->ar_rnat;
- nat_mask = 1UL << ia64_rse_slot_num(addr);
-
- *addr = val;
- if (nat)
- *rnat_addr |= nat_mask;
- else
- *rnat_addr &= ~nat_mask;
- return;
- }
-
- if (!user_stack(current, regs)) {
- DPRINT("ignoring kernel write to r%lu; register isn't on the kernel RBS!", r1);
- return;
- }
-
- bspstore = (unsigned long *)regs->ar_bspstore;
- ubs_end = ia64_rse_skip_regs(bspstore, on_kbs);
- bsp = ia64_rse_skip_regs(ubs_end, -sof);
- addr = ia64_rse_skip_regs(bsp, ridx);
-
- DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr);
-
- ia64_poke(current, sw, (unsigned long) ubs_end, (unsigned long) addr, val);
-
- rnat_addr = ia64_rse_rnat_addr(addr);
-
- ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, &rnats);
- DPRINT("rnat @%p = 0x%lx nat=%d old nat=%ld\n",
- (void *) rnat_addr, rnats, nat, (rnats >> ia64_rse_slot_num(addr)) & 1);
-
- nat_mask = 1UL << ia64_rse_slot_num(addr);
- if (nat)
- rnats |= nat_mask;
- else
- rnats &= ~nat_mask;
- ia64_poke(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, rnats);
-
- DPRINT("rnat changed to @%p = 0x%lx\n", (void *) rnat_addr, rnats);
-}
-
-
-static void
-get_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long *val, int *nat)
-{
- struct switch_stack *sw = (struct switch_stack *) regs - 1;
- unsigned long *bsp, *addr, *rnat_addr, *ubs_end, *bspstore;
- unsigned long *kbs = (void *) current + IA64_RBS_OFFSET;
- unsigned long rnats, nat_mask;
- unsigned long on_kbs;
- long sof = (regs->cr_ifs) & 0x7f;
- long sor = 8 * ((regs->cr_ifs >> 14) & 0xf);
- long rrb_gr = (regs->cr_ifs >> 18) & 0x7f;
- long ridx = r1 - 32;
-
- if (ridx >= sof) {
- /* read of out-of-frame register returns an undefined value; 0 in our case. */
- DPRINT("ignoring read from r%lu; only %lu registers are allocated!\n", r1, sof);
- goto fail;
- }
-
- if (ridx < sor)
- ridx = rotate_reg(sor, rrb_gr, ridx);
-
- DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n",
- r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx);
-
- on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore);
- addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + ridx);
- if (addr >= kbs) {
- /* the register is on the kernel backing store: easy... */
- *val = *addr;
- if (nat) {
- rnat_addr = ia64_rse_rnat_addr(addr);
- if ((unsigned long) rnat_addr >= sw->ar_bspstore)
- rnat_addr = &sw->ar_rnat;
- nat_mask = 1UL << ia64_rse_slot_num(addr);
- *nat = (*rnat_addr & nat_mask) != 0;
- }
- return;
- }
-
- if (!user_stack(current, regs)) {
- DPRINT("ignoring kernel read of r%lu; register isn't on the RBS!", r1);
- goto fail;
- }
-
- bspstore = (unsigned long *)regs->ar_bspstore;
- ubs_end = ia64_rse_skip_regs(bspstore, on_kbs);
- bsp = ia64_rse_skip_regs(ubs_end, -sof);
- addr = ia64_rse_skip_regs(bsp, ridx);
-
- DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr);
-
- ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) addr, val);
-
- if (nat) {
- rnat_addr = ia64_rse_rnat_addr(addr);
- nat_mask = 1UL << ia64_rse_slot_num(addr);
-
- DPRINT("rnat @%p = 0x%lx\n", (void *) rnat_addr, rnats);
-
- ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, &rnats);
- *nat = (rnats & nat_mask) != 0;
- }
- return;
-
- fail:
- *val = 0;
- if (nat)
- *nat = 0;
- return;
-}
-
-
-static void
-setreg (unsigned long regnum, unsigned long val, int nat, struct pt_regs *regs)
-{
- struct switch_stack *sw = (struct switch_stack *) regs - 1;
- unsigned long addr;
- unsigned long bitmask;
- unsigned long *unat;
-
- /*
- * First takes care of stacked registers
- */
- if (regnum >= IA64_FIRST_STACKED_GR) {
- set_rse_reg(regs, regnum, val, nat);
- return;
- }
-
- /*
- * Using r0 as a target raises a General Exception fault which has higher priority
- * than the Unaligned Reference fault.
- */
-
- /*
- * Now look at registers in [0-31] range and init correct UNAT
- */
- if (GR_IN_SW(regnum)) {
- addr = (unsigned long)sw;
- unat = &sw->ar_unat;
- } else {
- addr = (unsigned long)regs;
- unat = &sw->caller_unat;
- }
- DPRINT("tmp_base=%lx switch_stack=%s offset=%d\n",
- addr, unat==&sw->ar_unat ? "yes":"no", GR_OFFS(regnum));
- /*
- * add offset from base of struct
- * and do it !
- */
- addr += GR_OFFS(regnum);
-
- *(unsigned long *)addr = val;
-
- /*
- * We need to clear the corresponding UNAT bit to fully emulate the load
- * UNAT bit_pos = GR[r3]{8:3} form EAS-2.4
- */
- bitmask = 1UL << (addr >> 3 & 0x3f);
- DPRINT("*0x%lx=0x%lx NaT=%d prev_unat @%p=%lx\n", addr, val, nat, (void *) unat, *unat);
- if (nat) {
- *unat |= bitmask;
- } else {
- *unat &= ~bitmask;
- }
- DPRINT("*0x%lx=0x%lx NaT=%d new unat: %p=%lx\n", addr, val, nat, (void *) unat,*unat);
-}
-
-/*
- * Return the (rotated) index for floating point register REGNUM (REGNUM must be in the
- * range from 32-127, result is in the range from 0-95.
- */
-static inline unsigned long
-fph_index (struct pt_regs *regs, long regnum)
-{
- unsigned long rrb_fr = (regs->cr_ifs >> 25) & 0x7f;
- return rotate_reg(96, rrb_fr, (regnum - IA64_FIRST_ROTATING_FR));
-}
-
-static void
-setfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs)
-{
- struct switch_stack *sw = (struct switch_stack *)regs - 1;
- unsigned long addr;
-
- /*
- * From EAS-2.5: FPDisableFault has higher priority than Unaligned
- * Fault. Thus, when we get here, we know the partition is enabled.
- * To update f32-f127, there are three choices:
- *
- * (1) save f32-f127 to thread.fph and update the values there
- * (2) use a gigantic switch statement to directly access the registers
- * (3) generate code on the fly to update the desired register
- *
- * For now, we are using approach (1).
- */
- if (regnum >= IA64_FIRST_ROTATING_FR) {
- ia64_sync_fph(current);
- current->thread.fph[fph_index(regs, regnum)] = *fpval;
- } else {
- /*
- * pt_regs or switch_stack ?
- */
- if (FR_IN_SW(regnum)) {
- addr = (unsigned long)sw;
- } else {
- addr = (unsigned long)regs;
- }
-
- DPRINT("tmp_base=%lx offset=%d\n", addr, FR_OFFS(regnum));
-
- addr += FR_OFFS(regnum);
- *(struct ia64_fpreg *)addr = *fpval;
-
- /*
- * mark the low partition as being used now
- *
- * It is highly unlikely that this bit is not already set, but
- * let's do it for safety.
- */
- regs->cr_ipsr |= IA64_PSR_MFL;
- }
-}
-
-/*
- * Those 2 inline functions generate the spilled versions of the constant floating point
- * registers which can be used with stfX
- */
-static inline void
-float_spill_f0 (struct ia64_fpreg *final)
-{
- ia64_stf_spill(final, 0);
-}
-
-static inline void
-float_spill_f1 (struct ia64_fpreg *final)
-{
- ia64_stf_spill(final, 1);
-}
-
-static void
-getfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs)
-{
- struct switch_stack *sw = (struct switch_stack *) regs - 1;
- unsigned long addr;
-
- /*
- * From EAS-2.5: FPDisableFault has higher priority than
- * Unaligned Fault. Thus, when we get here, we know the partition is
- * enabled.
- *
- * When regnum > 31, the register is still live and we need to force a save
- * to current->thread.fph to get access to it. See discussion in setfpreg()
- * for reasons and other ways of doing this.
- */
- if (regnum >= IA64_FIRST_ROTATING_FR) {
- ia64_flush_fph(current);
- *fpval = current->thread.fph[fph_index(regs, regnum)];
- } else {
- /*
- * f0 = 0.0, f1= 1.0. Those registers are constant and are thus
- * not saved, we must generate their spilled form on the fly
- */
- switch(regnum) {
- case 0:
- float_spill_f0(fpval);
- break;
- case 1:
- float_spill_f1(fpval);
- break;
- default:
- /*
- * pt_regs or switch_stack ?
- */
- addr = FR_IN_SW(regnum) ? (unsigned long)sw
- : (unsigned long)regs;
-
- DPRINT("is_sw=%d tmp_base=%lx offset=0x%x\n",
- FR_IN_SW(regnum), addr, FR_OFFS(regnum));
-
- addr += FR_OFFS(regnum);
- *fpval = *(struct ia64_fpreg *)addr;
- }
- }
-}
-
-
-static void
-getreg (unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs)
-{
- struct switch_stack *sw = (struct switch_stack *) regs - 1;
- unsigned long addr, *unat;
-
- if (regnum >= IA64_FIRST_STACKED_GR) {
- get_rse_reg(regs, regnum, val, nat);
- return;
- }
-
- /*
- * take care of r0 (read-only always evaluate to 0)
- */
- if (regnum == 0) {
- *val = 0;
- if (nat)
- *nat = 0;
- return;
- }
-
- /*
- * Now look at registers in [0-31] range and init correct UNAT
- */
- if (GR_IN_SW(regnum)) {
- addr = (unsigned long)sw;
- unat = &sw->ar_unat;
- } else {
- addr = (unsigned long)regs;
- unat = &sw->caller_unat;
- }
-
- DPRINT("addr_base=%lx offset=0x%x\n", addr, GR_OFFS(regnum));
-
- addr += GR_OFFS(regnum);
-
- *val = *(unsigned long *)addr;
-
- /*
- * do it only when requested
- */
- if (nat)
- *nat = (*unat >> (addr >> 3 & 0x3f)) & 0x1UL;
-}
-
-static void
-emulate_load_updates (update_t type, load_store_t ld, struct pt_regs *regs, unsigned long ifa)
-{
- /*
- * IMPORTANT:
- * Given the way we handle unaligned speculative loads, we should
- * not get to this point in the code but we keep this sanity check,
- * just in case.
- */
- if (ld.x6_op == 1 || ld.x6_op == 3) {
- printk(KERN_ERR "%s: register update on speculative load, error\n", __func__);
- if (die_if_kernel("unaligned reference on speculative load with register update\n",
- regs, 30))
- return;
- }
-
-
- /*
- * at this point, we know that the base register to update is valid i.e.,
- * it's not r0
- */
- if (type == UPD_IMMEDIATE) {
- unsigned long imm;
-
- /*
- * Load +Imm: ldXZ r1=[r3],imm(9)
- *
- *
- * form imm9: [13:19] contain the first 7 bits
- */
- imm = ld.x << 7 | ld.imm;
-
- /*
- * sign extend (1+8bits) if m set
- */
- if (ld.m) imm |= SIGN_EXT9;
-
- /*
- * ifa == r3 and we know that the NaT bit on r3 was clear so
- * we can directly use ifa.
- */
- ifa += imm;
-
- setreg(ld.r3, ifa, 0, regs);
-
- DPRINT("ld.x=%d ld.m=%d imm=%ld r3=0x%lx\n", ld.x, ld.m, imm, ifa);
-
- } else if (ld.m) {
- unsigned long r2;
- int nat_r2;
-
- /*
- * Load +Reg Opcode: ldXZ r1=[r3],r2
- *
- * Note: that we update r3 even in the case of ldfX.a
- * (where the load does not happen)
- *
- * The way the load algorithm works, we know that r3 does not
- * have its NaT bit set (would have gotten NaT consumption
- * before getting the unaligned fault). So we can use ifa
- * which equals r3 at this point.
- *
- * IMPORTANT:
- * The above statement holds ONLY because we know that we
- * never reach this code when trying to do a ldX.s.
- * If we ever make it to here on an ldfX.s then
- */
- getreg(ld.imm, &r2, &nat_r2, regs);
-
- ifa += r2;
-
- /*
- * propagate Nat r2 -> r3
- */
- setreg(ld.r3, ifa, nat_r2, regs);
-
- DPRINT("imm=%d r2=%ld r3=0x%lx nat_r2=%d\n",ld.imm, r2, ifa, nat_r2);
- }
-}
-
-static int emulate_store(unsigned long ifa, void *val, int len, bool kernel_mode)
-{
- if (kernel_mode)
- return copy_to_kernel_nofault((void *)ifa, val, len);
-
- return copy_to_user((void __user *)ifa, val, len);
-}
-
-static int emulate_load(void *val, unsigned long ifa, int len, bool kernel_mode)
-{
- if (kernel_mode)
- return copy_from_kernel_nofault(val, (void *)ifa, len);
-
- return copy_from_user(val, (void __user *)ifa, len);
-}
-
-static int
-emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs,
- bool kernel_mode)
-{
- unsigned int len = 1 << ld.x6_sz;
- unsigned long val = 0;
-
- /*
- * r0, as target, doesn't need to be checked because Illegal Instruction
- * faults have higher priority than unaligned faults.
- *
- * r0 cannot be found as the base as it would never generate an
- * unaligned reference.
- */
-
- /*
- * ldX.a we will emulate load and also invalidate the ALAT entry.
- * See comment below for explanation on how we handle ldX.a
- */
-
- if (len != 2 && len != 4 && len != 8) {
- DPRINT("unknown size: x6=%d\n", ld.x6_sz);
- return -1;
- }
- /* this assumes little-endian byte-order: */
- if (emulate_load(&val, ifa, len, kernel_mode))
- return -1;
- setreg(ld.r1, val, 0, regs);
-
- /*
- * check for updates on any kind of loads
- */
- if (ld.op == 0x5 || ld.m)
- emulate_load_updates(ld.op == 0x5 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa);
-
- /*
- * handling of various loads (based on EAS2.4):
- *
- * ldX.acq (ordered load):
- * - acquire semantics would have been used, so force fence instead.
- *
- * ldX.c.clr (check load and clear):
- * - if we get to this handler, it's because the entry was not in the ALAT.
- * Therefore the operation reverts to a normal load
- *
- * ldX.c.nc (check load no clear):
- * - same as previous one
- *
- * ldX.c.clr.acq (ordered check load and clear):
- * - same as above for c.clr part. The load needs to have acquire semantics. So
- * we use the fence semantics which is stronger and thus ensures correctness.
- *
- * ldX.a (advanced load):
- * - suppose ldX.a r1=[r3]. If we get to the unaligned trap it's because the
- * address doesn't match requested size alignment. This means that we would
- * possibly need more than one load to get the result.
- *
- * The load part can be handled just like a normal load, however the difficult
- * part is to get the right thing into the ALAT. The critical piece of information
- * in the base address of the load & size. To do that, a ld.a must be executed,
- * clearly any address can be pushed into the table by using ld1.a r1=[r3]. Now
- * if we use the same target register, we will be okay for the check.a instruction.
- * If we look at the store, basically a stX [r3]=r1 checks the ALAT for any entry
- * which would overlap within [r3,r3+X] (the size of the load was store in the
- * ALAT). If such an entry is found the entry is invalidated. But this is not good
- * enough, take the following example:
- * r3=3
- * ld4.a r1=[r3]
- *
- * Could be emulated by doing:
- * ld1.a r1=[r3],1
- * store to temporary;
- * ld1.a r1=[r3],1
- * store & shift to temporary;
- * ld1.a r1=[r3],1
- * store & shift to temporary;
- * ld1.a r1=[r3]
- * store & shift to temporary;
- * r1=temporary
- *
- * So in this case, you would get the right value is r1 but the wrong info in
- * the ALAT. Notice that you could do it in reverse to finish with address 3
- * but you would still get the size wrong. To get the size right, one needs to
- * execute exactly the same kind of load. You could do it from a aligned
- * temporary location, but you would get the address wrong.
- *
- * So no matter what, it is not possible to emulate an advanced load
- * correctly. But is that really critical ?
- *
- * We will always convert ld.a into a normal load with ALAT invalidated. This
- * will enable compiler to do optimization where certain code path after ld.a
- * is not required to have ld.c/chk.a, e.g., code path with no intervening stores.
- *
- * If there is a store after the advanced load, one must either do a ld.c.* or
- * chk.a.* to reuse the value stored in the ALAT. Both can "fail" (meaning no
- * entry found in ALAT), and that's perfectly ok because:
- *
- * - ld.c.*, if the entry is not present a normal load is executed
- * - chk.a.*, if the entry is not present, execution jumps to recovery code
- *
- * In either case, the load can be potentially retried in another form.
- *
- * ALAT must be invalidated for the register (so that chk.a or ld.c don't pick
- * up a stale entry later). The register base update MUST also be performed.
- */
-
- /*
- * when the load has the .acq completer then
- * use ordering fence.
- */
- if (ld.x6_op == 0x5 || ld.x6_op == 0xa)
- mb();
-
- /*
- * invalidate ALAT entry in case of advanced load
- */
- if (ld.x6_op == 0x2)
- invala_gr(ld.r1);
-
- return 0;
-}
-
-static int
-emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs,
- bool kernel_mode)
-{
- unsigned long r2;
- unsigned int len = 1 << ld.x6_sz;
-
- /*
- * if we get to this handler, Nat bits on both r3 and r2 have already
- * been checked. so we don't need to do it
- *
- * extract the value to be stored
- */
- getreg(ld.imm, &r2, NULL, regs);
-
- /*
- * we rely on the macros in unaligned.h for now i.e.,
- * we let the compiler figure out how to read memory gracefully.
- *
- * We need this switch/case because the way the inline function
- * works. The code is optimized by the compiler and looks like
- * a single switch/case.
- */
- DPRINT("st%d [%lx]=%lx\n", len, ifa, r2);
-
- if (len != 2 && len != 4 && len != 8) {
- DPRINT("unknown size: x6=%d\n", ld.x6_sz);
- return -1;
- }
-
- /* this assumes little-endian byte-order: */
- if (emulate_store(ifa, &r2, len, kernel_mode))
- return -1;
-
- /*
- * stX [r3]=r2,imm(9)
- *
- * NOTE:
- * ld.r3 can never be r0, because r0 would not generate an
- * unaligned access.
- */
- if (ld.op == 0x5) {
- unsigned long imm;
-
- /*
- * form imm9: [12:6] contain first 7bits
- */
- imm = ld.x << 7 | ld.r1;
- /*
- * sign extend (8bits) if m set
- */
- if (ld.m) imm |= SIGN_EXT9;
- /*
- * ifa == r3 (NaT is necessarily cleared)
- */
- ifa += imm;
-
- DPRINT("imm=%lx r3=%lx\n", imm, ifa);
-
- setreg(ld.r3, ifa, 0, regs);
- }
- /*
- * we don't have alat_invalidate_multiple() so we need
- * to do the complete flush :-<<
- */
- ia64_invala();
-
- /*
- * stX.rel: use fence instead of release
- */
- if (ld.x6_op == 0xd)
- mb();
-
- return 0;
-}
-
-/*
- * floating point operations sizes in bytes
- */
-static const unsigned char float_fsz[4]={
- 10, /* extended precision (e) */
- 8, /* integer (8) */
- 4, /* single precision (s) */
- 8 /* double precision (d) */
-};
-
-static inline void
-mem2float_extended (struct ia64_fpreg *init, struct ia64_fpreg *final)
-{
- ia64_ldfe(6, init);
- ia64_stop();
- ia64_stf_spill(final, 6);
-}
-
-static inline void
-mem2float_integer (struct ia64_fpreg *init, struct ia64_fpreg *final)
-{
- ia64_ldf8(6, init);
- ia64_stop();
- ia64_stf_spill(final, 6);
-}
-
-static inline void
-mem2float_single (struct ia64_fpreg *init, struct ia64_fpreg *final)
-{
- ia64_ldfs(6, init);
- ia64_stop();
- ia64_stf_spill(final, 6);
-}
-
-static inline void
-mem2float_double (struct ia64_fpreg *init, struct ia64_fpreg *final)
-{
- ia64_ldfd(6, init);
- ia64_stop();
- ia64_stf_spill(final, 6);
-}
-
-static inline void
-float2mem_extended (struct ia64_fpreg *init, struct ia64_fpreg *final)
-{
- ia64_ldf_fill(6, init);
- ia64_stop();
- ia64_stfe(final, 6);
-}
-
-static inline void
-float2mem_integer (struct ia64_fpreg *init, struct ia64_fpreg *final)
-{
- ia64_ldf_fill(6, init);
- ia64_stop();
- ia64_stf8(final, 6);
-}
-
-static inline void
-float2mem_single (struct ia64_fpreg *init, struct ia64_fpreg *final)
-{
- ia64_ldf_fill(6, init);
- ia64_stop();
- ia64_stfs(final, 6);
-}
-
-static inline void
-float2mem_double (struct ia64_fpreg *init, struct ia64_fpreg *final)
-{
- ia64_ldf_fill(6, init);
- ia64_stop();
- ia64_stfd(final, 6);
-}
-
-static int
-emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs, bool kernel_mode)
-{
- struct ia64_fpreg fpr_init[2];
- struct ia64_fpreg fpr_final[2];
- unsigned long len = float_fsz[ld.x6_sz];
-
- /*
- * fr0 & fr1 don't need to be checked because Illegal Instruction faults have
- * higher priority than unaligned faults.
- *
- * r0 cannot be found as the base as it would never generate an unaligned
- * reference.
- */
-
- /*
- * make sure we get clean buffers
- */
- memset(&fpr_init, 0, sizeof(fpr_init));
- memset(&fpr_final, 0, sizeof(fpr_final));
-
- /*
- * ldfpX.a: we don't try to emulate anything but we must
- * invalidate the ALAT entry and execute updates, if any.
- */
- if (ld.x6_op != 0x2) {
- /*
- * This assumes little-endian byte-order. Note that there is no "ldfpe"
- * instruction:
- */
- if (emulate_load(&fpr_init[0], ifa, len, kernel_mode)
- || emulate_load(&fpr_init[1], (ifa + len), len, kernel_mode))
- return -1;
-
- DPRINT("ld.r1=%d ld.imm=%d x6_sz=%d\n", ld.r1, ld.imm, ld.x6_sz);
- DDUMP("frp_init =", &fpr_init, 2*len);
- /*
- * XXX fixme
- * Could optimize inlines by using ldfpX & 2 spills
- */
- switch( ld.x6_sz ) {
- case 0:
- mem2float_extended(&fpr_init[0], &fpr_final[0]);
- mem2float_extended(&fpr_init[1], &fpr_final[1]);
- break;
- case 1:
- mem2float_integer(&fpr_init[0], &fpr_final[0]);
- mem2float_integer(&fpr_init[1], &fpr_final[1]);
- break;
- case 2:
- mem2float_single(&fpr_init[0], &fpr_final[0]);
- mem2float_single(&fpr_init[1], &fpr_final[1]);
- break;
- case 3:
- mem2float_double(&fpr_init[0], &fpr_final[0]);
- mem2float_double(&fpr_init[1], &fpr_final[1]);
- break;
- }
- DDUMP("fpr_final =", &fpr_final, 2*len);
- /*
- * XXX fixme
- *
- * A possible optimization would be to drop fpr_final and directly
- * use the storage from the saved context i.e., the actual final
- * destination (pt_regs, switch_stack or thread structure).
- */
- setfpreg(ld.r1, &fpr_final[0], regs);
- setfpreg(ld.imm, &fpr_final[1], regs);
- }
-
- /*
- * Check for updates: only immediate updates are available for this
- * instruction.
- */
- if (ld.m) {
- /*
- * the immediate is implicit given the ldsz of the operation:
- * single: 8 (2x4) and for all others it's 16 (2x8)
- */
- ifa += len<<1;
-
- /*
- * IMPORTANT:
- * the fact that we force the NaT of r3 to zero is ONLY valid
- * as long as we don't come here with a ldfpX.s.
- * For this reason we keep this sanity check
- */
- if (ld.x6_op == 1 || ld.x6_op == 3)
- printk(KERN_ERR "%s: register update on speculative load pair, error\n",
- __func__);
-
- setreg(ld.r3, ifa, 0, regs);
- }
-
- /*
- * Invalidate ALAT entries, if any, for both registers.
- */
- if (ld.x6_op == 0x2) {
- invala_fr(ld.r1);
- invala_fr(ld.imm);
- }
- return 0;
-}
-
-
-static int
-emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs,
- bool kernel_mode)
-{
- struct ia64_fpreg fpr_init;
- struct ia64_fpreg fpr_final;
- unsigned long len = float_fsz[ld.x6_sz];
-
- /*
- * fr0 & fr1 don't need to be checked because Illegal Instruction
- * faults have higher priority than unaligned faults.
- *
- * r0 cannot be found as the base as it would never generate an
- * unaligned reference.
- */
-
- /*
- * make sure we get clean buffers
- */
- memset(&fpr_init,0, sizeof(fpr_init));
- memset(&fpr_final,0, sizeof(fpr_final));
-
- /*
- * ldfX.a we don't try to emulate anything but we must
- * invalidate the ALAT entry.
- * See comments in ldX for descriptions on how the various loads are handled.
- */
- if (ld.x6_op != 0x2) {
- if (emulate_load(&fpr_init, ifa, len, kernel_mode))
- return -1;
-
- DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz);
- DDUMP("fpr_init =", &fpr_init, len);
- /*
- * we only do something for x6_op={0,8,9}
- */
- switch( ld.x6_sz ) {
- case 0:
- mem2float_extended(&fpr_init, &fpr_final);
- break;
- case 1:
- mem2float_integer(&fpr_init, &fpr_final);
- break;
- case 2:
- mem2float_single(&fpr_init, &fpr_final);
- break;
- case 3:
- mem2float_double(&fpr_init, &fpr_final);
- break;
- }
- DDUMP("fpr_final =", &fpr_final, len);
- /*
- * XXX fixme
- *
- * A possible optimization would be to drop fpr_final and directly
- * use the storage from the saved context i.e., the actual final
- * destination (pt_regs, switch_stack or thread structure).
- */
- setfpreg(ld.r1, &fpr_final, regs);
- }
-
- /*
- * check for updates on any loads
- */
- if (ld.op == 0x7 || ld.m)
- emulate_load_updates(ld.op == 0x7 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa);
-
- /*
- * invalidate ALAT entry in case of advanced floating point loads
- */
- if (ld.x6_op == 0x2)
- invala_fr(ld.r1);
-
- return 0;
-}
-
-
-static int
-emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs,
- bool kernel_mode)
-{
- struct ia64_fpreg fpr_init;
- struct ia64_fpreg fpr_final;
- unsigned long len = float_fsz[ld.x6_sz];
-
- /*
- * make sure we get clean buffers
- */
- memset(&fpr_init,0, sizeof(fpr_init));
- memset(&fpr_final,0, sizeof(fpr_final));
-
- /*
- * if we get to this handler, Nat bits on both r3 and r2 have already
- * been checked. so we don't need to do it
- *
- * extract the value to be stored
- */
- getfpreg(ld.imm, &fpr_init, regs);
- /*
- * during this step, we extract the spilled registers from the saved
- * context i.e., we refill. Then we store (no spill) to temporary
- * aligned location
- */
- switch( ld.x6_sz ) {
- case 0:
- float2mem_extended(&fpr_init, &fpr_final);
- break;
- case 1:
- float2mem_integer(&fpr_init, &fpr_final);
- break;
- case 2:
- float2mem_single(&fpr_init, &fpr_final);
- break;
- case 3:
- float2mem_double(&fpr_init, &fpr_final);
- break;
- }
- DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz);
- DDUMP("fpr_init =", &fpr_init, len);
- DDUMP("fpr_final =", &fpr_final, len);
-
- if (emulate_store(ifa, &fpr_final, len, kernel_mode))
- return -1;
-
- /*
- * stfX [r3]=r2,imm(9)
- *
- * NOTE:
- * ld.r3 can never be r0, because r0 would not generate an
- * unaligned access.
- */
- if (ld.op == 0x7) {
- unsigned long imm;
-
- /*
- * form imm9: [12:6] contain first 7bits
- */
- imm = ld.x << 7 | ld.r1;
- /*
- * sign extend (8bits) if m set
- */
- if (ld.m)
- imm |= SIGN_EXT9;
- /*
- * ifa == r3 (NaT is necessarily cleared)
- */
- ifa += imm;
-
- DPRINT("imm=%lx r3=%lx\n", imm, ifa);
-
- setreg(ld.r3, ifa, 0, regs);
- }
- /*
- * we don't have alat_invalidate_multiple() so we need
- * to do the complete flush :-<<
- */
- ia64_invala();
-
- return 0;
-}
-
-/*
- * Make sure we log the unaligned access, so that user/sysadmin can notice it and
- * eventually fix the program. However, we don't want to do that for every access so we
- * pace it with jiffies.
- */
-static DEFINE_RATELIMIT_STATE(logging_rate_limit, 5 * HZ, 5);
-
-void
-ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
-{
- struct ia64_psr *ipsr = ia64_psr(regs);
- unsigned long bundle[2];
- unsigned long opcode;
- const struct exception_table_entry *eh = NULL;
- union {
- unsigned long l;
- load_store_t insn;
- } u;
- int ret = -1;
- bool kernel_mode = false;
-
- if (ia64_psr(regs)->be) {
- /* we don't support big-endian accesses */
- if (die_if_kernel("big-endian unaligned accesses are not supported", regs, 0))
- return;
- goto force_sigbus;
- }
-
- /*
- * Treat kernel accesses for which there is an exception handler entry the same as
- * user-level unaligned accesses. Otherwise, a clever program could trick this
- * handler into reading an arbitrary kernel addresses...
- */
- if (!user_mode(regs))
- eh = search_exception_tables(regs->cr_iip + ia64_psr(regs)->ri);
- if (user_mode(regs) || eh) {
- if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0)
- goto force_sigbus;
-
- if (!no_unaligned_warning &&
- !(current->thread.flags & IA64_THREAD_UAC_NOPRINT) &&
- __ratelimit(&logging_rate_limit))
- {
- char buf[200]; /* comm[] is at most 16 bytes... */
- size_t len;
-
- len = sprintf(buf, "%s(%d): unaligned access to 0x%016lx, "
- "ip=0x%016lx\n\r", current->comm,
- task_pid_nr(current),
- ifa, regs->cr_iip + ipsr->ri);
- /*
- * Don't call tty_write_message() if we're in the kernel; we might
- * be holding locks...
- */
- if (user_mode(regs)) {
- struct tty_struct *tty = get_current_tty();
- tty_write_message(tty, buf);
- tty_kref_put(tty);
- }
- buf[len-1] = '\0'; /* drop '\r' */
- /* watch for command names containing %s */
- printk(KERN_WARNING "%s", buf);
- } else {
- if (no_unaligned_warning) {
- printk_once(KERN_WARNING "%s(%d) encountered an "
- "unaligned exception which required\n"
- "kernel assistance, which degrades "
- "the performance of the application.\n"
- "Unaligned exception warnings have "
- "been disabled by the system "
- "administrator\n"
- "echo 0 > /proc/sys/kernel/ignore-"
- "unaligned-usertrap to re-enable\n",
- current->comm, task_pid_nr(current));
- }
- }
- } else {
- if (__ratelimit(&logging_rate_limit)) {
- printk(KERN_WARNING "kernel unaligned access to 0x%016lx, ip=0x%016lx\n",
- ifa, regs->cr_iip + ipsr->ri);
- if (unaligned_dump_stack)
- dump_stack();
- }
- kernel_mode = true;
- }
-
- DPRINT("iip=%lx ifa=%lx isr=%lx (ei=%d, sp=%d)\n",
- regs->cr_iip, ifa, regs->cr_ipsr, ipsr->ri, ipsr->it);
-
- if (emulate_load(bundle, regs->cr_iip, 16, kernel_mode))
- goto failure;
-
- /*
- * extract the instruction from the bundle given the slot number
- */
- switch (ipsr->ri) {
- default:
- case 0: u.l = (bundle[0] >> 5); break;
- case 1: u.l = (bundle[0] >> 46) | (bundle[1] << 18); break;
- case 2: u.l = (bundle[1] >> 23); break;
- }
- opcode = (u.l >> IA64_OPCODE_SHIFT) & IA64_OPCODE_MASK;
-
- DPRINT("opcode=%lx ld.qp=%d ld.r1=%d ld.imm=%d ld.r3=%d ld.x=%d ld.hint=%d "
- "ld.x6=0x%x ld.m=%d ld.op=%d\n", opcode, u.insn.qp, u.insn.r1, u.insn.imm,
- u.insn.r3, u.insn.x, u.insn.hint, u.insn.x6_sz, u.insn.m, u.insn.op);
-
- /*
- * IMPORTANT:
- * Notice that the switch statement DOES not cover all possible instructions
- * that DO generate unaligned references. This is made on purpose because for some
- * instructions it DOES NOT make sense to try and emulate the access. Sometimes it
- * is WRONG to try and emulate. Here is a list of instruction we don't emulate i.e.,
- * the program will get a signal and die:
- *
- * load/store:
- * - ldX.spill
- * - stX.spill
- * Reason: RNATs are based on addresses
- * - ld16
- * - st16
- * Reason: ld16 and st16 are supposed to occur in a single
- * memory op
- *
- * synchronization:
- * - cmpxchg
- * - fetchadd
- * - xchg
- * Reason: ATOMIC operations cannot be emulated properly using multiple
- * instructions.
- *
- * speculative loads:
- * - ldX.sZ
- * Reason: side effects, code must be ready to deal with failure so simpler
- * to let the load fail.
- * ---------------------------------------------------------------------------------
- * XXX fixme
- *
- * I would like to get rid of this switch case and do something
- * more elegant.
- */
- switch (opcode) {
- case LDS_OP:
- case LDSA_OP:
- if (u.insn.x)
- /* oops, really a semaphore op (cmpxchg, etc) */
- goto failure;
- fallthrough;
- case LDS_IMM_OP:
- case LDSA_IMM_OP:
- case LDFS_OP:
- case LDFSA_OP:
- case LDFS_IMM_OP:
- /*
- * The instruction will be retried with deferred exceptions turned on, and
- * we should get Nat bit installed
- *
- * IMPORTANT: When PSR_ED is set, the register & immediate update forms
- * are actually executed even though the operation failed. So we don't
- * need to take care of this.
- */
- DPRINT("forcing PSR_ED\n");
- regs->cr_ipsr |= IA64_PSR_ED;
- goto done;
-
- case LD_OP:
- case LDA_OP:
- case LDBIAS_OP:
- case LDACQ_OP:
- case LDCCLR_OP:
- case LDCNC_OP:
- case LDCCLRACQ_OP:
- if (u.insn.x)
- /* oops, really a semaphore op (cmpxchg, etc) */
- goto failure;
- fallthrough;
- case LD_IMM_OP:
- case LDA_IMM_OP:
- case LDBIAS_IMM_OP:
- case LDACQ_IMM_OP:
- case LDCCLR_IMM_OP:
- case LDCNC_IMM_OP:
- case LDCCLRACQ_IMM_OP:
- ret = emulate_load_int(ifa, u.insn, regs, kernel_mode);
- break;
-
- case ST_OP:
- case STREL_OP:
- if (u.insn.x)
- /* oops, really a semaphore op (cmpxchg, etc) */
- goto failure;
- fallthrough;
- case ST_IMM_OP:
- case STREL_IMM_OP:
- ret = emulate_store_int(ifa, u.insn, regs, kernel_mode);
- break;
-
- case LDF_OP:
- case LDFA_OP:
- case LDFCCLR_OP:
- case LDFCNC_OP:
- if (u.insn.x)
- ret = emulate_load_floatpair(ifa, u.insn, regs, kernel_mode);
- else
- ret = emulate_load_float(ifa, u.insn, regs, kernel_mode);
- break;
-
- case LDF_IMM_OP:
- case LDFA_IMM_OP:
- case LDFCCLR_IMM_OP:
- case LDFCNC_IMM_OP:
- ret = emulate_load_float(ifa, u.insn, regs, kernel_mode);
- break;
-
- case STF_OP:
- case STF_IMM_OP:
- ret = emulate_store_float(ifa, u.insn, regs, kernel_mode);
- break;
-
- default:
- goto failure;
- }
- DPRINT("ret=%d\n", ret);
- if (ret)
- goto failure;
-
- if (ipsr->ri == 2)
- /*
- * given today's architecture this case is not likely to happen because a
- * memory access instruction (M) can never be in the last slot of a
- * bundle. But let's keep it for now.
- */
- regs->cr_iip += 16;
- ipsr->ri = (ipsr->ri + 1) & 0x3;
-
- DPRINT("ipsr->ri=%d iip=%lx\n", ipsr->ri, regs->cr_iip);
- done:
- return;
-
- failure:
- /* something went wrong... */
- if (!user_mode(regs)) {
- if (eh) {
- ia64_handle_exception(regs, eh);
- goto done;
- }
- if (die_if_kernel("error during unaligned kernel access\n", regs, ret))
- return;
- /* NOT_REACHED */
- }
- force_sigbus:
- force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *) ifa,
- 0, 0, 0);
- goto done;
-}
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
deleted file mode 100644
index a0fec82c56b8..000000000000
--- a/arch/ia64/kernel/uncached.c
+++ /dev/null
@@ -1,273 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2001-2008 Silicon Graphics, Inc. All rights reserved.
- *
- * A simple uncached page allocator using the generic allocator. This
- * allocator first utilizes the spare (spill) pages found in the EFI
- * memmap and will then start converting cached pages to uncached ones
- * at a granule at a time. Node awareness is implemented by having a
- * pool of pages per node.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/efi.h>
-#include <linux/nmi.h>
-#include <linux/genalloc.h>
-#include <linux/gfp.h>
-#include <linux/pgtable.h>
-#include <asm/efi.h>
-#include <asm/page.h>
-#include <asm/pal.h>
-#include <linux/atomic.h>
-#include <asm/tlbflush.h>
-
-struct uncached_pool {
- struct gen_pool *pool;
- struct mutex add_chunk_mutex; /* serialize adding a converted chunk */
- int nchunks_added; /* #of converted chunks added to pool */
- atomic_t status; /* smp called function's return status*/
-};
-
-#define MAX_CONVERTED_CHUNKS_PER_NODE 2
-
-struct uncached_pool uncached_pools[MAX_NUMNODES];
-
-
-static void uncached_ipi_visibility(void *data)
-{
- int status;
- struct uncached_pool *uc_pool = (struct uncached_pool *)data;
-
- status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
- if ((status != PAL_VISIBILITY_OK) &&
- (status != PAL_VISIBILITY_OK_REMOTE_NEEDED))
- atomic_inc(&uc_pool->status);
-}
-
-
-static void uncached_ipi_mc_drain(void *data)
-{
- int status;
- struct uncached_pool *uc_pool = (struct uncached_pool *)data;
-
- status = ia64_pal_mc_drain();
- if (status != PAL_STATUS_SUCCESS)
- atomic_inc(&uc_pool->status);
-}
-
-
-/*
- * Add a new chunk of uncached memory pages to the specified pool.
- *
- * @pool: pool to add new chunk of uncached memory to
- * @nid: node id of node to allocate memory from, or -1
- *
- * This is accomplished by first allocating a granule of cached memory pages
- * and then converting them to uncached memory pages.
- */
-static int uncached_add_chunk(struct uncached_pool *uc_pool, int nid)
-{
- struct page *page;
- int status, i, nchunks_added = uc_pool->nchunks_added;
- unsigned long c_addr, uc_addr;
-
- if (mutex_lock_interruptible(&uc_pool->add_chunk_mutex) != 0)
- return -1; /* interrupted by a signal */
-
- if (uc_pool->nchunks_added > nchunks_added) {
- /* someone added a new chunk while we were waiting */
- mutex_unlock(&uc_pool->add_chunk_mutex);
- return 0;
- }
-
- if (uc_pool->nchunks_added >= MAX_CONVERTED_CHUNKS_PER_NODE) {
- mutex_unlock(&uc_pool->add_chunk_mutex);
- return -1;
- }
-
- /* attempt to allocate a granule's worth of cached memory pages */
-
- page = __alloc_pages_node(nid,
- GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE,
- IA64_GRANULE_SHIFT-PAGE_SHIFT);
- if (!page) {
- mutex_unlock(&uc_pool->add_chunk_mutex);
- return -1;
- }
-
- /* convert the memory pages from cached to uncached */
-
- c_addr = (unsigned long)page_address(page);
- uc_addr = c_addr - PAGE_OFFSET + __IA64_UNCACHED_OFFSET;
-
- /*
- * There's a small race here where it's possible for someone to
- * access the page through /dev/mem halfway through the conversion
- * to uncached - not sure it's really worth bothering about
- */
- for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++)
- SetPageUncached(&page[i]);
-
- flush_tlb_kernel_range(uc_addr, uc_addr + IA64_GRANULE_SIZE);
-
- status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
- if (status == PAL_VISIBILITY_OK_REMOTE_NEEDED) {
- atomic_set(&uc_pool->status, 0);
- smp_call_function(uncached_ipi_visibility, uc_pool, 1);
- if (atomic_read(&uc_pool->status))
- goto failed;
- } else if (status != PAL_VISIBILITY_OK)
- goto failed;
-
- preempt_disable();
-
- flush_icache_range(uc_addr, uc_addr + IA64_GRANULE_SIZE);
-
- /* flush the just introduced uncached translation from the TLB */
- local_flush_tlb_all();
-
- preempt_enable();
-
- status = ia64_pal_mc_drain();
- if (status != PAL_STATUS_SUCCESS)
- goto failed;
- atomic_set(&uc_pool->status, 0);
- smp_call_function(uncached_ipi_mc_drain, uc_pool, 1);
- if (atomic_read(&uc_pool->status))
- goto failed;
-
- /*
- * The chunk of memory pages has been converted to uncached so now we
- * can add it to the pool.
- */
- status = gen_pool_add(uc_pool->pool, uc_addr, IA64_GRANULE_SIZE, nid);
- if (status)
- goto failed;
-
- uc_pool->nchunks_added++;
- mutex_unlock(&uc_pool->add_chunk_mutex);
- return 0;
-
- /* failed to convert or add the chunk so give it back to the kernel */
-failed:
- for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++)
- ClearPageUncached(&page[i]);
-
- free_pages(c_addr, IA64_GRANULE_SHIFT-PAGE_SHIFT);
- mutex_unlock(&uc_pool->add_chunk_mutex);
- return -1;
-}
-
-
-/*
- * uncached_alloc_page
- *
- * @starting_nid: node id of node to start with, or -1
- * @n_pages: number of contiguous pages to allocate
- *
- * Allocate the specified number of contiguous uncached pages on the
- * requested node. If not enough contiguous uncached pages are available
- * on the requested node, roundrobin starting with the next higher node.
- */
-unsigned long uncached_alloc_page(int starting_nid, int n_pages)
-{
- unsigned long uc_addr;
- struct uncached_pool *uc_pool;
- int nid;
-
- if (unlikely(starting_nid >= MAX_NUMNODES))
- return 0;
-
- if (starting_nid < 0)
- starting_nid = numa_node_id();
- nid = starting_nid;
-
- do {
- if (!node_state(nid, N_HIGH_MEMORY))
- continue;
- uc_pool = &uncached_pools[nid];
- if (uc_pool->pool == NULL)
- continue;
- do {
- uc_addr = gen_pool_alloc(uc_pool->pool,
- n_pages * PAGE_SIZE);
- if (uc_addr != 0)
- return uc_addr;
- } while (uncached_add_chunk(uc_pool, nid) == 0);
-
- } while ((nid = (nid + 1) % MAX_NUMNODES) != starting_nid);
-
- return 0;
-}
-EXPORT_SYMBOL(uncached_alloc_page);
-
-
-/*
- * uncached_free_page
- *
- * @uc_addr: uncached address of first page to free
- * @n_pages: number of contiguous pages to free
- *
- * Free the specified number of uncached pages.
- */
-void uncached_free_page(unsigned long uc_addr, int n_pages)
-{
- int nid = paddr_to_nid(uc_addr - __IA64_UNCACHED_OFFSET);
- struct gen_pool *pool = uncached_pools[nid].pool;
-
- if (unlikely(pool == NULL))
- return;
-
- if ((uc_addr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET)
- panic("uncached_free_page invalid address %lx\n", uc_addr);
-
- gen_pool_free(pool, uc_addr, n_pages * PAGE_SIZE);
-}
-EXPORT_SYMBOL(uncached_free_page);
-
-
-/*
- * uncached_build_memmap,
- *
- * @uc_start: uncached starting address of a chunk of uncached memory
- * @uc_end: uncached ending address of a chunk of uncached memory
- * @arg: ignored, (NULL argument passed in on call to efi_memmap_walk_uc())
- *
- * Called at boot time to build a map of pages that can be used for
- * memory special operations.
- */
-static int __init uncached_build_memmap(u64 uc_start, u64 uc_end, void *arg)
-{
- int nid = paddr_to_nid(uc_start - __IA64_UNCACHED_OFFSET);
- struct gen_pool *pool = uncached_pools[nid].pool;
- size_t size = uc_end - uc_start;
-
- touch_softlockup_watchdog();
-
- if (pool != NULL) {
- memset((char *)uc_start, 0, size);
- (void) gen_pool_add(pool, uc_start, size, nid);
- }
- return 0;
-}
-
-
-static int __init uncached_init(void)
-{
- int nid;
-
- for_each_online_node(nid) {
- uncached_pools[nid].pool = gen_pool_create(PAGE_SHIFT, nid);
- mutex_init(&uncached_pools[nid].add_chunk_mutex);
- }
-
- efi_memmap_walk_uc(uncached_build_memmap, NULL);
- return 0;
-}
-
-__initcall(uncached_init);
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
deleted file mode 100644
index 6bd64c35e691..000000000000
--- a/arch/ia64/kernel/unwind.c
+++ /dev/null
@@ -1,2320 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 1999-2004 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2003 Fenghua Yu <fenghua.yu@intel.com>
- * - Change pt_regs_off() to make it less dependent on pt_regs structure.
- */
-/*
- * This file implements call frame unwind support for the Linux
- * kernel. Parsing and processing the unwind information is
- * time-consuming, so this implementation translates the unwind
- * descriptors into unwind scripts. These scripts are very simple
- * (basically a sequence of assignments) and efficient to execute.
- * They are cached for later re-use. Each script is specific for a
- * given instruction pointer address and the set of predicate values
- * that the script depends on (most unwind descriptors are
- * unconditional and scripts often do not depend on predicates at
- * all). This code is based on the unwind conventions described in
- * the "IA-64 Software Conventions and Runtime Architecture" manual.
- *
- * SMP conventions:
- * o updates to the global unwind data (in structure "unw") are serialized
- * by the unw.lock spinlock
- * o each unwind script has its own read-write lock; a thread must acquire
- * a read lock before executing a script and must acquire a write lock
- * before modifying a script
- * o if both the unw.lock spinlock and a script's read-write lock must be
- * acquired, then the read-write lock must be acquired first.
- */
-#include <linux/module.h>
-#include <linux/memblock.h>
-#include <linux/elf.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include <asm/unwind.h>
-
-#include <asm/delay.h>
-#include <asm/page.h>
-#include <asm/ptrace.h>
-#include <asm/ptrace_offsets.h>
-#include <asm/rse.h>
-#include <asm/sections.h>
-#include <linux/uaccess.h>
-
-#include "entry.h"
-#include "unwind_i.h"
-
-#define UNW_LOG_CACHE_SIZE 7 /* each unw_script is ~256 bytes in size */
-#define UNW_CACHE_SIZE (1 << UNW_LOG_CACHE_SIZE)
-
-#define UNW_LOG_HASH_SIZE (UNW_LOG_CACHE_SIZE + 1)
-#define UNW_HASH_SIZE (1 << UNW_LOG_HASH_SIZE)
-
-#define UNW_STATS 0 /* WARNING: this disabled interrupts for long time-spans!! */
-
-#ifdef UNW_DEBUG
- static unsigned int unw_debug_level = UNW_DEBUG;
-# define UNW_DEBUG_ON(n) unw_debug_level >= n
- /* Do not code a printk level, not all debug lines end in newline */
-# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
-# undef inline
-# define inline
-#else /* !UNW_DEBUG */
-# define UNW_DEBUG_ON(n) 0
-# define UNW_DPRINT(n, ...)
-#endif /* UNW_DEBUG */
-
-#if UNW_STATS
-# define STAT(x...) x
-#else
-# define STAT(x...)
-#endif
-
-#define alloc_reg_state() kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC)
-#define free_reg_state(usr) kfree(usr)
-#define alloc_labeled_state() kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC)
-#define free_labeled_state(usr) kfree(usr)
-
-typedef unsigned long unw_word;
-typedef unsigned char unw_hash_index_t;
-
-static struct {
- spinlock_t lock; /* spinlock for unwind data */
-
- /* list of unwind tables (one per load-module) */
- struct unw_table *tables;
-
- unsigned long r0; /* constant 0 for r0 */
-
- /* table of registers that prologues can save (and order in which they're saved): */
- const unsigned char save_order[8];
-
- /* maps a preserved register index (preg_index) to corresponding switch_stack offset: */
- unsigned short sw_off[sizeof(struct unw_frame_info) / 8];
-
- unsigned short lru_head; /* index of lead-recently used script */
- unsigned short lru_tail; /* index of most-recently used script */
-
- /* index into unw_frame_info for preserved register i */
- unsigned short preg_index[UNW_NUM_REGS];
-
- short pt_regs_offsets[32];
-
- /* unwind table for the kernel: */
- struct unw_table kernel_table;
-
- /* unwind table describing the gate page (kernel code that is mapped into user space): */
- size_t gate_table_size;
- unsigned long *gate_table;
-
- /* hash table that maps instruction pointer to script index: */
- unsigned short hash[UNW_HASH_SIZE];
-
- /* script cache: */
- struct unw_script cache[UNW_CACHE_SIZE];
-
-# ifdef UNW_DEBUG
- const char *preg_name[UNW_NUM_REGS];
-# endif
-# if UNW_STATS
- struct {
- struct {
- int lookups;
- int hinted_hits;
- int normal_hits;
- int collision_chain_traversals;
- } cache;
- struct {
- unsigned long build_time;
- unsigned long run_time;
- unsigned long parse_time;
- int builds;
- int news;
- int collisions;
- int runs;
- } script;
- struct {
- unsigned long init_time;
- unsigned long unwind_time;
- int inits;
- int unwinds;
- } api;
- } stat;
-# endif
-} unw = {
- .tables = &unw.kernel_table,
- .lock = __SPIN_LOCK_UNLOCKED(unw.lock),
- .save_order = {
- UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,
- UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
- },
- .preg_index = {
- offsetof(struct unw_frame_info, pri_unat_loc)/8, /* PRI_UNAT_GR */
- offsetof(struct unw_frame_info, pri_unat_loc)/8, /* PRI_UNAT_MEM */
- offsetof(struct unw_frame_info, bsp_loc)/8,
- offsetof(struct unw_frame_info, bspstore_loc)/8,
- offsetof(struct unw_frame_info, pfs_loc)/8,
- offsetof(struct unw_frame_info, rnat_loc)/8,
- offsetof(struct unw_frame_info, psp)/8,
- offsetof(struct unw_frame_info, rp_loc)/8,
- offsetof(struct unw_frame_info, r4)/8,
- offsetof(struct unw_frame_info, r5)/8,
- offsetof(struct unw_frame_info, r6)/8,
- offsetof(struct unw_frame_info, r7)/8,
- offsetof(struct unw_frame_info, unat_loc)/8,
- offsetof(struct unw_frame_info, pr_loc)/8,
- offsetof(struct unw_frame_info, lc_loc)/8,
- offsetof(struct unw_frame_info, fpsr_loc)/8,
- offsetof(struct unw_frame_info, b1_loc)/8,
- offsetof(struct unw_frame_info, b2_loc)/8,
- offsetof(struct unw_frame_info, b3_loc)/8,
- offsetof(struct unw_frame_info, b4_loc)/8,
- offsetof(struct unw_frame_info, b5_loc)/8,
- offsetof(struct unw_frame_info, f2_loc)/8,
- offsetof(struct unw_frame_info, f3_loc)/8,
- offsetof(struct unw_frame_info, f4_loc)/8,
- offsetof(struct unw_frame_info, f5_loc)/8,
- offsetof(struct unw_frame_info, fr_loc[16 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[17 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[18 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[19 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[20 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[21 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[22 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[23 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[24 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[25 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[26 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[27 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[28 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[29 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[30 - 16])/8,
- offsetof(struct unw_frame_info, fr_loc[31 - 16])/8,
- },
- .pt_regs_offsets = {
- [0] = -1,
- offsetof(struct pt_regs, r1),
- offsetof(struct pt_regs, r2),
- offsetof(struct pt_regs, r3),
- [4] = -1, [5] = -1, [6] = -1, [7] = -1,
- offsetof(struct pt_regs, r8),
- offsetof(struct pt_regs, r9),
- offsetof(struct pt_regs, r10),
- offsetof(struct pt_regs, r11),
- offsetof(struct pt_regs, r12),
- offsetof(struct pt_regs, r13),
- offsetof(struct pt_regs, r14),
- offsetof(struct pt_regs, r15),
- offsetof(struct pt_regs, r16),
- offsetof(struct pt_regs, r17),
- offsetof(struct pt_regs, r18),
- offsetof(struct pt_regs, r19),
- offsetof(struct pt_regs, r20),
- offsetof(struct pt_regs, r21),
- offsetof(struct pt_regs, r22),
- offsetof(struct pt_regs, r23),
- offsetof(struct pt_regs, r24),
- offsetof(struct pt_regs, r25),
- offsetof(struct pt_regs, r26),
- offsetof(struct pt_regs, r27),
- offsetof(struct pt_regs, r28),
- offsetof(struct pt_regs, r29),
- offsetof(struct pt_regs, r30),
- offsetof(struct pt_regs, r31),
- },
- .hash = { [0 ... UNW_HASH_SIZE - 1] = -1 },
-#ifdef UNW_DEBUG
- .preg_name = {
- "pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp",
- "r4", "r5", "r6", "r7",
- "ar.unat", "pr", "ar.lc", "ar.fpsr",
- "b1", "b2", "b3", "b4", "b5",
- "f2", "f3", "f4", "f5",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
- }
-#endif
-};
-
-static inline int
-read_only (void *addr)
-{
- return (unsigned long) ((char *) addr - (char *) &unw.r0) < sizeof(unw.r0);
-}
-
-/*
- * Returns offset of rREG in struct pt_regs.
- */
-static inline unsigned long
-pt_regs_off (unsigned long reg)
-{
- short off = -1;
-
- if (reg < ARRAY_SIZE(unw.pt_regs_offsets))
- off = unw.pt_regs_offsets[reg];
-
- if (off < 0) {
- UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __func__, reg);
- off = 0;
- }
- return (unsigned long) off;
-}
-
-static inline struct pt_regs *
-get_scratch_regs (struct unw_frame_info *info)
-{
- if (!info->pt) {
- /* This should not happen with valid unwind info. */
- UNW_DPRINT(0, "unwind.%s: bad unwind info: resetting info->pt\n", __func__);
- if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
- info->pt = (unsigned long) ((struct pt_regs *) info->psp - 1);
- else
- info->pt = info->sp - 16;
- }
- UNW_DPRINT(3, "unwind.%s: sp 0x%lx pt 0x%lx\n", __func__, info->sp, info->pt);
- return (struct pt_regs *) info->pt;
-}
-
-/* Unwind accessors. */
-
-int
-unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char *nat, int write)
-{
- unsigned long *addr, *nat_addr, nat_mask = 0, dummy_nat;
- struct unw_ireg *ireg;
- struct pt_regs *pt;
-
- if ((unsigned) regnum - 1 >= 127) {
- if (regnum == 0 && !write) {
- *val = 0; /* read r0 always returns 0 */
- *nat = 0;
- return 0;
- }
- UNW_DPRINT(0, "unwind.%s: trying to access non-existent r%u\n",
- __func__, regnum);
- return -1;
- }
-
- if (regnum < 32) {
- if (regnum >= 4 && regnum <= 7) {
- /* access a preserved register */
- ireg = &info->r4 + (regnum - 4);
- addr = ireg->loc;
- if (addr) {
- nat_addr = addr + ireg->nat.off;
- switch (ireg->nat.type) {
- case UNW_NAT_VAL:
- /* simulate getf.sig/setf.sig */
- if (write) {
- if (*nat) {
- /* write NaTVal and be done with it */
- addr[0] = 0;
- addr[1] = 0x1fffe;
- return 0;
- }
- addr[1] = 0x1003e;
- } else {
- if (addr[0] == 0 && addr[1] == 0x1ffe) {
- /* return NaT and be done with it */
- *val = 0;
- *nat = 1;
- return 0;
- }
- }
- fallthrough;
- case UNW_NAT_NONE:
- dummy_nat = 0;
- nat_addr = &dummy_nat;
- break;
-
- case UNW_NAT_MEMSTK:
- nat_mask = (1UL << ((long) addr & 0x1f8)/8);
- break;
-
- case UNW_NAT_REGSTK:
- nat_addr = ia64_rse_rnat_addr(addr);
- if ((unsigned long) addr < info->regstk.limit
- || (unsigned long) addr >= info->regstk.top)
- {
- UNW_DPRINT(0, "unwind.%s: %p outside of regstk "
- "[0x%lx-0x%lx)\n",
- __func__, (void *) addr,
- info->regstk.limit,
- info->regstk.top);
- return -1;
- }
- if ((unsigned long) nat_addr >= info->regstk.top)
- nat_addr = &info->sw->ar_rnat;
- nat_mask = (1UL << ia64_rse_slot_num(addr));
- break;
- }
- } else {
- addr = &info->sw->r4 + (regnum - 4);
- nat_addr = &info->sw->ar_unat;
- nat_mask = (1UL << ((long) addr & 0x1f8)/8);
- }
- } else {
- /* access a scratch register */
- pt = get_scratch_regs(info);
- addr = (unsigned long *) ((unsigned long)pt + pt_regs_off(regnum));
- if (info->pri_unat_loc)
- nat_addr = info->pri_unat_loc;
- else
- nat_addr = &info->sw->caller_unat;
- nat_mask = (1UL << ((long) addr & 0x1f8)/8);
- }
- } else {
- /* access a stacked register */
- addr = ia64_rse_skip_regs((unsigned long *) info->bsp, regnum - 32);
- nat_addr = ia64_rse_rnat_addr(addr);
- if ((unsigned long) addr < info->regstk.limit
- || (unsigned long) addr >= info->regstk.top)
- {
- UNW_DPRINT(0, "unwind.%s: ignoring attempt to access register outside "
- "of rbs\n", __func__);
- return -1;
- }
- if ((unsigned long) nat_addr >= info->regstk.top)
- nat_addr = &info->sw->ar_rnat;
- nat_mask = (1UL << ia64_rse_slot_num(addr));
- }
-
- if (write) {
- if (read_only(addr)) {
- UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
- __func__);
- } else {
- *addr = *val;
- if (*nat)
- *nat_addr |= nat_mask;
- else
- *nat_addr &= ~nat_mask;
- }
- } else {
- if ((*nat_addr & nat_mask) == 0) {
- *val = *addr;
- *nat = 0;
- } else {
- *val = 0; /* if register is a NaT, *addr may contain kernel data! */
- *nat = 1;
- }
- }
- return 0;
-}
-EXPORT_SYMBOL(unw_access_gr);
-
-int
-unw_access_br (struct unw_frame_info *info, int regnum, unsigned long *val, int write)
-{
- unsigned long *addr;
- struct pt_regs *pt;
-
- switch (regnum) {
- /* scratch: */
- case 0: pt = get_scratch_regs(info); addr = &pt->b0; break;
- case 6: pt = get_scratch_regs(info); addr = &pt->b6; break;
- case 7: pt = get_scratch_regs(info); addr = &pt->b7; break;
-
- /* preserved: */
- case 1: case 2: case 3: case 4: case 5:
- addr = *(&info->b1_loc + (regnum - 1));
- if (!addr)
- addr = &info->sw->b1 + (regnum - 1);
- break;
-
- default:
- UNW_DPRINT(0, "unwind.%s: trying to access non-existent b%u\n",
- __func__, regnum);
- return -1;
- }
- if (write)
- if (read_only(addr)) {
- UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
- __func__);
- } else
- *addr = *val;
- else
- *val = *addr;
- return 0;
-}
-EXPORT_SYMBOL(unw_access_br);
-
-int
-unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val, int write)
-{
- struct ia64_fpreg *addr = NULL;
- struct pt_regs *pt;
-
- if ((unsigned) (regnum - 2) >= 126) {
- UNW_DPRINT(0, "unwind.%s: trying to access non-existent f%u\n",
- __func__, regnum);
- return -1;
- }
-
- if (regnum <= 5) {
- addr = *(&info->f2_loc + (regnum - 2));
- if (!addr)
- addr = &info->sw->f2 + (regnum - 2);
- } else if (regnum <= 15) {
- if (regnum <= 11) {
- pt = get_scratch_regs(info);
- addr = &pt->f6 + (regnum - 6);
- }
- else
- addr = &info->sw->f12 + (regnum - 12);
- } else if (regnum <= 31) {
- addr = info->fr_loc[regnum - 16];
- if (!addr)
- addr = &info->sw->f16 + (regnum - 16);
- } else {
- struct task_struct *t = info->task;
-
- if (write)
- ia64_sync_fph(t);
- else
- ia64_flush_fph(t);
- addr = t->thread.fph + (regnum - 32);
- }
-
- if (write)
- if (read_only(addr)) {
- UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
- __func__);
- } else
- *addr = *val;
- else
- *val = *addr;
- return 0;
-}
-EXPORT_SYMBOL(unw_access_fr);
-
-int
-unw_access_ar (struct unw_frame_info *info, int regnum, unsigned long *val, int write)
-{
- unsigned long *addr;
- struct pt_regs *pt;
-
- switch (regnum) {
- case UNW_AR_BSP:
- addr = info->bsp_loc;
- if (!addr)
- addr = &info->sw->ar_bspstore;
- break;
-
- case UNW_AR_BSPSTORE:
- addr = info->bspstore_loc;
- if (!addr)
- addr = &info->sw->ar_bspstore;
- break;
-
- case UNW_AR_PFS:
- addr = info->pfs_loc;
- if (!addr)
- addr = &info->sw->ar_pfs;
- break;
-
- case UNW_AR_RNAT:
- addr = info->rnat_loc;
- if (!addr)
- addr = &info->sw->ar_rnat;
- break;
-
- case UNW_AR_UNAT:
- addr = info->unat_loc;
- if (!addr)
- addr = &info->sw->caller_unat;
- break;
-
- case UNW_AR_LC:
- addr = info->lc_loc;
- if (!addr)
- addr = &info->sw->ar_lc;
- break;
-
- case UNW_AR_EC:
- if (!info->cfm_loc)
- return -1;
- if (write)
- *info->cfm_loc =
- (*info->cfm_loc & ~(0x3fUL << 52)) | ((*val & 0x3f) << 52);
- else
- *val = (*info->cfm_loc >> 52) & 0x3f;
- return 0;
-
- case UNW_AR_FPSR:
- addr = info->fpsr_loc;
- if (!addr)
- addr = &info->sw->ar_fpsr;
- break;
-
- case UNW_AR_RSC:
- pt = get_scratch_regs(info);
- addr = &pt->ar_rsc;
- break;
-
- case UNW_AR_CCV:
- pt = get_scratch_regs(info);
- addr = &pt->ar_ccv;
- break;
-
- case UNW_AR_CSD:
- pt = get_scratch_regs(info);
- addr = &pt->ar_csd;
- break;
-
- case UNW_AR_SSD:
- pt = get_scratch_regs(info);
- addr = &pt->ar_ssd;
- break;
-
- default:
- UNW_DPRINT(0, "unwind.%s: trying to access non-existent ar%u\n",
- __func__, regnum);
- return -1;
- }
-
- if (write) {
- if (read_only(addr)) {
- UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
- __func__);
- } else
- *addr = *val;
- } else
- *val = *addr;
- return 0;
-}
-EXPORT_SYMBOL(unw_access_ar);
-
-int
-unw_access_pr (struct unw_frame_info *info, unsigned long *val, int write)
-{
- unsigned long *addr;
-
- addr = info->pr_loc;
- if (!addr)
- addr = &info->sw->pr;
-
- if (write) {
- if (read_only(addr)) {
- UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
- __func__);
- } else
- *addr = *val;
- } else
- *val = *addr;
- return 0;
-}
-EXPORT_SYMBOL(unw_access_pr);
-
-
-/* Routines to manipulate the state stack. */
-
-static inline void
-push (struct unw_state_record *sr)
-{
- struct unw_reg_state *rs;
-
- rs = alloc_reg_state();
- if (!rs) {
- printk(KERN_ERR "unwind: cannot stack reg state!\n");
- return;
- }
- memcpy(rs, &sr->curr, sizeof(*rs));
- sr->curr.next = rs;
-}
-
-static void
-pop (struct unw_state_record *sr)
-{
- struct unw_reg_state *rs = sr->curr.next;
-
- if (!rs) {
- printk(KERN_ERR "unwind: stack underflow!\n");
- return;
- }
- memcpy(&sr->curr, rs, sizeof(*rs));
- free_reg_state(rs);
-}
-
-/* Make a copy of the state stack. Non-recursive to avoid stack overflows. */
-static struct unw_reg_state *
-dup_state_stack (struct unw_reg_state *rs)
-{
- struct unw_reg_state *copy, *prev = NULL, *first = NULL;
-
- while (rs) {
- copy = alloc_reg_state();
- if (!copy) {
- printk(KERN_ERR "unwind.dup_state_stack: out of memory\n");
- return NULL;
- }
- memcpy(copy, rs, sizeof(*copy));
- if (first)
- prev->next = copy;
- else
- first = copy;
- rs = rs->next;
- prev = copy;
- }
- return first;
-}
-
-/* Free all stacked register states (but not RS itself). */
-static void
-free_state_stack (struct unw_reg_state *rs)
-{
- struct unw_reg_state *p, *next;
-
- for (p = rs->next; p != NULL; p = next) {
- next = p->next;
- free_reg_state(p);
- }
- rs->next = NULL;
-}
-
-/* Unwind decoder routines */
-
-static enum unw_register_index __attribute_const__
-decode_abreg (unsigned char abreg, int memory)
-{
- switch (abreg) {
- case 0x04 ... 0x07: return UNW_REG_R4 + (abreg - 0x04);
- case 0x22 ... 0x25: return UNW_REG_F2 + (abreg - 0x22);
- case 0x30 ... 0x3f: return UNW_REG_F16 + (abreg - 0x30);
- case 0x41 ... 0x45: return UNW_REG_B1 + (abreg - 0x41);
- case 0x60: return UNW_REG_PR;
- case 0x61: return UNW_REG_PSP;
- case 0x62: return memory ? UNW_REG_PRI_UNAT_MEM : UNW_REG_PRI_UNAT_GR;
- case 0x63: return UNW_REG_RP;
- case 0x64: return UNW_REG_BSP;
- case 0x65: return UNW_REG_BSPSTORE;
- case 0x66: return UNW_REG_RNAT;
- case 0x67: return UNW_REG_UNAT;
- case 0x68: return UNW_REG_FPSR;
- case 0x69: return UNW_REG_PFS;
- case 0x6a: return UNW_REG_LC;
- default:
- break;
- }
- UNW_DPRINT(0, "unwind.%s: bad abreg=0x%x\n", __func__, abreg);
- return UNW_REG_LC;
-}
-
-static void
-set_reg (struct unw_reg_info *reg, enum unw_where where, int when, unsigned long val)
-{
- reg->val = val;
- reg->where = where;
- if (reg->when == UNW_WHEN_NEVER)
- reg->when = when;
-}
-
-static void
-alloc_spill_area (unsigned long *offp, unsigned long regsize,
- struct unw_reg_info *lo, struct unw_reg_info *hi)
-{
- struct unw_reg_info *reg;
-
- for (reg = hi; reg >= lo; --reg) {
- if (reg->where == UNW_WHERE_SPILL_HOME) {
- reg->where = UNW_WHERE_PSPREL;
- *offp -= regsize;
- reg->val = *offp;
- }
- }
-}
-
-static inline void
-spill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim, unw_word t)
-{
- struct unw_reg_info *reg;
-
- for (reg = *regp; reg <= lim; ++reg) {
- if (reg->where == UNW_WHERE_SPILL_HOME) {
- reg->when = t;
- *regp = reg + 1;
- return;
- }
- }
- UNW_DPRINT(0, "unwind.%s: excess spill!\n", __func__);
-}
-
-static inline void
-finish_prologue (struct unw_state_record *sr)
-{
- struct unw_reg_info *reg;
- unsigned long off;
- int i;
-
- /*
- * First, resolve implicit register save locations (see Section "11.4.2.3 Rules
- * for Using Unwind Descriptors", rule 3):
- */
- for (i = 0; i < (int) ARRAY_SIZE(unw.save_order); ++i) {
- reg = sr->curr.reg + unw.save_order[i];
- if (reg->where == UNW_WHERE_GR_SAVE) {
- reg->where = UNW_WHERE_GR;
- reg->val = sr->gr_save_loc++;
- }
- }
-
- /*
- * Next, compute when the fp, general, and branch registers get
- * saved. This must come before alloc_spill_area() because
- * we need to know which registers are spilled to their home
- * locations.
- */
- if (sr->imask) {
- unsigned char kind, mask = 0, *cp = sr->imask;
- int t;
- static const unsigned char limit[3] = {
- UNW_REG_F31, UNW_REG_R7, UNW_REG_B5
- };
- struct unw_reg_info *(regs[3]);
-
- regs[0] = sr->curr.reg + UNW_REG_F2;
- regs[1] = sr->curr.reg + UNW_REG_R4;
- regs[2] = sr->curr.reg + UNW_REG_B1;
-
- for (t = 0; t < sr->region_len; ++t) {
- if ((t & 3) == 0)
- mask = *cp++;
- kind = (mask >> 2*(3-(t & 3))) & 3;
- if (kind > 0)
- spill_next_when(&regs[kind - 1], sr->curr.reg + limit[kind - 1],
- sr->region_start + t);
- }
- }
- /*
- * Next, lay out the memory stack spill area:
- */
- if (sr->any_spills) {
- off = sr->spill_offset;
- alloc_spill_area(&off, 16, sr->curr.reg + UNW_REG_F2, sr->curr.reg + UNW_REG_F31);
- alloc_spill_area(&off, 8, sr->curr.reg + UNW_REG_B1, sr->curr.reg + UNW_REG_B5);
- alloc_spill_area(&off, 8, sr->curr.reg + UNW_REG_R4, sr->curr.reg + UNW_REG_R7);
- }
-}
-
-/*
- * Region header descriptors.
- */
-
-static void
-desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave,
- struct unw_state_record *sr)
-{
- int i, region_start;
-
- if (!(sr->in_body || sr->first_region))
- finish_prologue(sr);
- sr->first_region = 0;
-
- /* check if we're done: */
- if (sr->when_target < sr->region_start + sr->region_len) {
- sr->done = 1;
- return;
- }
-
- region_start = sr->region_start + sr->region_len;
-
- for (i = 0; i < sr->epilogue_count; ++i)
- pop(sr);
- sr->epilogue_count = 0;
- sr->epilogue_start = UNW_WHEN_NEVER;
-
- sr->region_start = region_start;
- sr->region_len = rlen;
- sr->in_body = body;
-
- if (!body) {
- push(sr);
-
- for (i = 0; i < 4; ++i) {
- if (mask & 0x8)
- set_reg(sr->curr.reg + unw.save_order[i], UNW_WHERE_GR,
- sr->region_start + sr->region_len - 1, grsave++);
- mask <<= 1;
- }
- sr->gr_save_loc = grsave;
- sr->any_spills = 0;
- sr->imask = NULL;
- sr->spill_offset = 0x10; /* default to psp+16 */
- }
-}
-
-/*
- * Prologue descriptors.
- */
-
-static inline void
-desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr)
-{
- if (abi == 3 && context == 'i') {
- sr->flags |= UNW_FLAG_INTERRUPT_FRAME;
- UNW_DPRINT(3, "unwind.%s: interrupt frame\n", __func__);
- }
- else
- UNW_DPRINT(0, "unwind%s: ignoring unwabi(abi=0x%x,context=0x%x)\n",
- __func__, abi, context);
-}
-
-static inline void
-desc_br_gr (unsigned char brmask, unsigned char gr, struct unw_state_record *sr)
-{
- int i;
-
- for (i = 0; i < 5; ++i) {
- if (brmask & 1)
- set_reg(sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_GR,
- sr->region_start + sr->region_len - 1, gr++);
- brmask >>= 1;
- }
-}
-
-static inline void
-desc_br_mem (unsigned char brmask, struct unw_state_record *sr)
-{
- int i;
-
- for (i = 0; i < 5; ++i) {
- if (brmask & 1) {
- set_reg(sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_SPILL_HOME,
- sr->region_start + sr->region_len - 1, 0);
- sr->any_spills = 1;
- }
- brmask >>= 1;
- }
-}
-
-static inline void
-desc_frgr_mem (unsigned char grmask, unw_word frmask, struct unw_state_record *sr)
-{
- int i;
-
- for (i = 0; i < 4; ++i) {
- if ((grmask & 1) != 0) {
- set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
- sr->region_start + sr->region_len - 1, 0);
- sr->any_spills = 1;
- }
- grmask >>= 1;
- }
- for (i = 0; i < 20; ++i) {
- if ((frmask & 1) != 0) {
- int base = (i < 4) ? UNW_REG_F2 : UNW_REG_F16 - 4;
- set_reg(sr->curr.reg + base + i, UNW_WHERE_SPILL_HOME,
- sr->region_start + sr->region_len - 1, 0);
- sr->any_spills = 1;
- }
- frmask >>= 1;
- }
-}
-
-static inline void
-desc_fr_mem (unsigned char frmask, struct unw_state_record *sr)
-{
- int i;
-
- for (i = 0; i < 4; ++i) {
- if ((frmask & 1) != 0) {
- set_reg(sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,
- sr->region_start + sr->region_len - 1, 0);
- sr->any_spills = 1;
- }
- frmask >>= 1;
- }
-}
-
-static inline void
-desc_gr_gr (unsigned char grmask, unsigned char gr, struct unw_state_record *sr)
-{
- int i;
-
- for (i = 0; i < 4; ++i) {
- if ((grmask & 1) != 0)
- set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_GR,
- sr->region_start + sr->region_len - 1, gr++);
- grmask >>= 1;
- }
-}
-
-static inline void
-desc_gr_mem (unsigned char grmask, struct unw_state_record *sr)
-{
- int i;
-
- for (i = 0; i < 4; ++i) {
- if ((grmask & 1) != 0) {
- set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
- sr->region_start + sr->region_len - 1, 0);
- sr->any_spills = 1;
- }
- grmask >>= 1;
- }
-}
-
-static inline void
-desc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr)
-{
- set_reg(sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE,
- sr->region_start + min_t(int, t, sr->region_len - 1), 16*size);
-}
-
-static inline void
-desc_mem_stack_v (unw_word t, struct unw_state_record *sr)
-{
- sr->curr.reg[UNW_REG_PSP].when = sr->region_start + min_t(int, t, sr->region_len - 1);
-}
-
-static inline void
-desc_reg_gr (unsigned char reg, unsigned char dst, struct unw_state_record *sr)
-{
- set_reg(sr->curr.reg + reg, UNW_WHERE_GR, sr->region_start + sr->region_len - 1, dst);
-}
-
-static inline void
-desc_reg_psprel (unsigned char reg, unw_word pspoff, struct unw_state_record *sr)
-{
- set_reg(sr->curr.reg + reg, UNW_WHERE_PSPREL, sr->region_start + sr->region_len - 1,
- 0x10 - 4*pspoff);
-}
-
-static inline void
-desc_reg_sprel (unsigned char reg, unw_word spoff, struct unw_state_record *sr)
-{
- set_reg(sr->curr.reg + reg, UNW_WHERE_SPREL, sr->region_start + sr->region_len - 1,
- 4*spoff);
-}
-
-static inline void
-desc_rp_br (unsigned char dst, struct unw_state_record *sr)
-{
- sr->return_link_reg = dst;
-}
-
-static inline void
-desc_reg_when (unsigned char regnum, unw_word t, struct unw_state_record *sr)
-{
- struct unw_reg_info *reg = sr->curr.reg + regnum;
-
- if (reg->where == UNW_WHERE_NONE)
- reg->where = UNW_WHERE_GR_SAVE;
- reg->when = sr->region_start + min_t(int, t, sr->region_len - 1);
-}
-
-static inline void
-desc_spill_base (unw_word pspoff, struct unw_state_record *sr)
-{
- sr->spill_offset = 0x10 - 4*pspoff;
-}
-
-static inline unsigned char *
-desc_spill_mask (unsigned char *imaskp, struct unw_state_record *sr)
-{
- sr->imask = imaskp;
- return imaskp + (2*sr->region_len + 7)/8;
-}
-
-/*
- * Body descriptors.
- */
-static inline void
-desc_epilogue (unw_word t, unw_word ecount, struct unw_state_record *sr)
-{
- sr->epilogue_start = sr->region_start + sr->region_len - 1 - t;
- sr->epilogue_count = ecount + 1;
-}
-
-static inline void
-desc_copy_state (unw_word label, struct unw_state_record *sr)
-{
- struct unw_labeled_state *ls;
-
- for (ls = sr->labeled_states; ls; ls = ls->next) {
- if (ls->label == label) {
- free_state_stack(&sr->curr);
- memcpy(&sr->curr, &ls->saved_state, sizeof(sr->curr));
- sr->curr.next = dup_state_stack(ls->saved_state.next);
- return;
- }
- }
- printk(KERN_ERR "unwind: failed to find state labeled 0x%lx\n", label);
-}
-
-static inline void
-desc_label_state (unw_word label, struct unw_state_record *sr)
-{
- struct unw_labeled_state *ls;
-
- ls = alloc_labeled_state();
- if (!ls) {
- printk(KERN_ERR "unwind.desc_label_state(): out of memory\n");
- return;
- }
- ls->label = label;
- memcpy(&ls->saved_state, &sr->curr, sizeof(ls->saved_state));
- ls->saved_state.next = dup_state_stack(sr->curr.next);
-
- /* insert into list of labeled states: */
- ls->next = sr->labeled_states;
- sr->labeled_states = ls;
-}
-
-/*
- * General descriptors.
- */
-
-static inline int
-desc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr)
-{
- if (sr->when_target <= sr->region_start + min_t(int, t, sr->region_len - 1))
- return 0;
- if (qp > 0) {
- if ((sr->pr_val & (1UL << qp)) == 0)
- return 0;
- sr->pr_mask |= (1UL << qp);
- }
- return 1;
-}
-
-static inline void
-desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg, struct unw_state_record *sr)
-{
- struct unw_reg_info *r;
-
- if (!desc_is_active(qp, t, sr))
- return;
-
- r = sr->curr.reg + decode_abreg(abreg, 0);
- r->where = UNW_WHERE_NONE;
- r->when = UNW_WHEN_NEVER;
- r->val = 0;
-}
-
-static inline void
-desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg, unsigned char x,
- unsigned char ytreg, struct unw_state_record *sr)
-{
- enum unw_where where = UNW_WHERE_GR;
- struct unw_reg_info *r;
-
- if (!desc_is_active(qp, t, sr))
- return;
-
- if (x)
- where = UNW_WHERE_BR;
- else if (ytreg & 0x80)
- where = UNW_WHERE_FR;
-
- r = sr->curr.reg + decode_abreg(abreg, 0);
- r->where = where;
- r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
- r->val = (ytreg & 0x7f);
-}
-
-static inline void
-desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word pspoff,
- struct unw_state_record *sr)
-{
- struct unw_reg_info *r;
-
- if (!desc_is_active(qp, t, sr))
- return;
-
- r = sr->curr.reg + decode_abreg(abreg, 1);
- r->where = UNW_WHERE_PSPREL;
- r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
- r->val = 0x10 - 4*pspoff;
-}
-
-static inline void
-desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word spoff,
- struct unw_state_record *sr)
-{
- struct unw_reg_info *r;
-
- if (!desc_is_active(qp, t, sr))
- return;
-
- r = sr->curr.reg + decode_abreg(abreg, 1);
- r->where = UNW_WHERE_SPREL;
- r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
- r->val = 4*spoff;
-}
-
-#define UNW_DEC_BAD_CODE(code) printk(KERN_ERR "unwind: unknown code 0x%02x\n", \
- code);
-
-/*
- * region headers:
- */
-#define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg) desc_prologue(0,r,m,gr,arg)
-#define UNW_DEC_PROLOGUE(fmt,b,r,arg) desc_prologue(b,r,0,32,arg)
-/*
- * prologue descriptors:
- */
-#define UNW_DEC_ABI(fmt,a,c,arg) desc_abi(a,c,arg)
-#define UNW_DEC_BR_GR(fmt,b,g,arg) desc_br_gr(b,g,arg)
-#define UNW_DEC_BR_MEM(fmt,b,arg) desc_br_mem(b,arg)
-#define UNW_DEC_FRGR_MEM(fmt,g,f,arg) desc_frgr_mem(g,f,arg)
-#define UNW_DEC_FR_MEM(fmt,f,arg) desc_fr_mem(f,arg)
-#define UNW_DEC_GR_GR(fmt,m,g,arg) desc_gr_gr(m,g,arg)
-#define UNW_DEC_GR_MEM(fmt,m,arg) desc_gr_mem(m,arg)
-#define UNW_DEC_MEM_STACK_F(fmt,t,s,arg) desc_mem_stack_f(t,s,arg)
-#define UNW_DEC_MEM_STACK_V(fmt,t,arg) desc_mem_stack_v(t,arg)
-#define UNW_DEC_REG_GR(fmt,r,d,arg) desc_reg_gr(r,d,arg)
-#define UNW_DEC_REG_PSPREL(fmt,r,o,arg) desc_reg_psprel(r,o,arg)
-#define UNW_DEC_REG_SPREL(fmt,r,o,arg) desc_reg_sprel(r,o,arg)
-#define UNW_DEC_REG_WHEN(fmt,r,t,arg) desc_reg_when(r,t,arg)
-#define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) desc_reg_when(UNW_REG_PRI_UNAT_GR,t,arg)
-#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) desc_reg_when(UNW_REG_PRI_UNAT_MEM,t,arg)
-#define UNW_DEC_PRIUNAT_GR(fmt,r,arg) desc_reg_gr(UNW_REG_PRI_UNAT_GR,r,arg)
-#define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg) desc_reg_psprel(UNW_REG_PRI_UNAT_MEM,o,arg)
-#define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg) desc_reg_sprel(UNW_REG_PRI_UNAT_MEM,o,arg)
-#define UNW_DEC_RP_BR(fmt,d,arg) desc_rp_br(d,arg)
-#define UNW_DEC_SPILL_BASE(fmt,o,arg) desc_spill_base(o,arg)
-#define UNW_DEC_SPILL_MASK(fmt,m,arg) (m = desc_spill_mask(m,arg))
-/*
- * body descriptors:
- */
-#define UNW_DEC_EPILOGUE(fmt,t,c,arg) desc_epilogue(t,c,arg)
-#define UNW_DEC_COPY_STATE(fmt,l,arg) desc_copy_state(l,arg)
-#define UNW_DEC_LABEL_STATE(fmt,l,arg) desc_label_state(l,arg)
-/*
- * general unwind descriptors:
- */
-#define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg) desc_spill_reg_p(p,t,a,x,y,arg)
-#define UNW_DEC_SPILL_REG(f,t,a,x,y,arg) desc_spill_reg_p(0,t,a,x,y,arg)
-#define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg) desc_spill_psprel_p(p,t,a,o,arg)
-#define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg) desc_spill_psprel_p(0,t,a,o,arg)
-#define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg) desc_spill_sprel_p(p,t,a,o,arg)
-#define UNW_DEC_SPILL_SPREL(f,t,a,o,arg) desc_spill_sprel_p(0,t,a,o,arg)
-#define UNW_DEC_RESTORE_P(f,p,t,a,arg) desc_restore_p(p,t,a,arg)
-#define UNW_DEC_RESTORE(f,t,a,arg) desc_restore_p(0,t,a,arg)
-
-#include "unwind_decoder.c"
-
-
-/* Unwind scripts. */
-
-static inline unw_hash_index_t
-hash (unsigned long ip)
-{
- /* magic number = ((sqrt(5)-1)/2)*2^64 */
- static const unsigned long hashmagic = 0x9e3779b97f4a7c16UL;
-
- return (ip >> 4) * hashmagic >> (64 - UNW_LOG_HASH_SIZE);
-}
-
-static inline long
-cache_match (struct unw_script *script, unsigned long ip, unsigned long pr)
-{
- read_lock(&script->lock);
- if (ip == script->ip && ((pr ^ script->pr_val) & script->pr_mask) == 0)
- /* keep the read lock... */
- return 1;
- read_unlock(&script->lock);
- return 0;
-}
-
-static inline struct unw_script *
-script_lookup (struct unw_frame_info *info)
-{
- struct unw_script *script = unw.cache + info->hint;
- unsigned short index;
- unsigned long ip, pr;
-
- if (UNW_DEBUG_ON(0))
- return NULL; /* Always regenerate scripts in debug mode */
-
- STAT(++unw.stat.cache.lookups);
-
- ip = info->ip;
- pr = info->pr;
-
- if (cache_match(script, ip, pr)) {
- STAT(++unw.stat.cache.hinted_hits);
- return script;
- }
-
- index = unw.hash[hash(ip)];
- if (index >= UNW_CACHE_SIZE)
- return NULL;
-
- script = unw.cache + index;
- while (1) {
- if (cache_match(script, ip, pr)) {
- /* update hint; no locking required as single-word writes are atomic */
- STAT(++unw.stat.cache.normal_hits);
- unw.cache[info->prev_script].hint = script - unw.cache;
- return script;
- }
- if (script->coll_chain >= UNW_HASH_SIZE)
- return NULL;
- script = unw.cache + script->coll_chain;
- STAT(++unw.stat.cache.collision_chain_traversals);
- }
-}
-
-/*
- * On returning, a write lock for the SCRIPT is still being held.
- */
-static inline struct unw_script *
-script_new (unsigned long ip)
-{
- struct unw_script *script, *prev, *tmp;
- unw_hash_index_t index;
- unsigned short head;
-
- STAT(++unw.stat.script.news);
-
- /*
- * Can't (easily) use cmpxchg() here because of ABA problem
- * that is intrinsic in cmpxchg()...
- */
- head = unw.lru_head;
- script = unw.cache + head;
- unw.lru_head = script->lru_chain;
-
- /*
- * We'd deadlock here if we interrupted a thread that is holding a read lock on
- * script->lock. Thus, if the write_trylock() fails, we simply bail out. The
- * alternative would be to disable interrupts whenever we hold a read-lock, but
- * that seems silly.
- */
- if (!write_trylock(&script->lock))
- return NULL;
-
- /* re-insert script at the tail of the LRU chain: */
- unw.cache[unw.lru_tail].lru_chain = head;
- unw.lru_tail = head;
-
- /* remove the old script from the hash table (if it's there): */
- if (script->ip) {
- index = hash(script->ip);
- tmp = unw.cache + unw.hash[index];
- prev = NULL;
- while (1) {
- if (tmp == script) {
- if (prev)
- prev->coll_chain = tmp->coll_chain;
- else
- unw.hash[index] = tmp->coll_chain;
- break;
- } else
- prev = tmp;
- if (tmp->coll_chain >= UNW_CACHE_SIZE)
- /* old script wasn't in the hash-table */
- break;
- tmp = unw.cache + tmp->coll_chain;
- }
- }
-
- /* enter new script in the hash table */
- index = hash(ip);
- script->coll_chain = unw.hash[index];
- unw.hash[index] = script - unw.cache;
-
- script->ip = ip; /* set new IP while we're holding the locks */
-
- STAT(if (script->coll_chain < UNW_CACHE_SIZE) ++unw.stat.script.collisions);
-
- script->flags = 0;
- script->hint = 0;
- script->count = 0;
- return script;
-}
-
-static void
-script_finalize (struct unw_script *script, struct unw_state_record *sr)
-{
- script->pr_mask = sr->pr_mask;
- script->pr_val = sr->pr_val;
- /*
- * We could down-grade our write-lock on script->lock here but
- * the rwlock API doesn't offer atomic lock downgrading, so
- * we'll just keep the write-lock and release it later when
- * we're done using the script.
- */
-}
-
-static inline void
-script_emit (struct unw_script *script, struct unw_insn insn)
-{
- if (script->count >= UNW_MAX_SCRIPT_LEN) {
- UNW_DPRINT(0, "unwind.%s: script exceeds maximum size of %u instructions!\n",
- __func__, UNW_MAX_SCRIPT_LEN);
- return;
- }
- script->insn[script->count++] = insn;
-}
-
-static inline void
-emit_nat_info (struct unw_state_record *sr, int i, struct unw_script *script)
-{
- struct unw_reg_info *r = sr->curr.reg + i;
- enum unw_insn_opcode opc;
- struct unw_insn insn;
- unsigned long val = 0;
-
- switch (r->where) {
- case UNW_WHERE_GR:
- if (r->val >= 32) {
- /* register got spilled to a stacked register */
- opc = UNW_INSN_SETNAT_TYPE;
- val = UNW_NAT_REGSTK;
- } else
- /* register got spilled to a scratch register */
- opc = UNW_INSN_SETNAT_MEMSTK;
- break;
-
- case UNW_WHERE_FR:
- opc = UNW_INSN_SETNAT_TYPE;
- val = UNW_NAT_VAL;
- break;
-
- case UNW_WHERE_BR:
- opc = UNW_INSN_SETNAT_TYPE;
- val = UNW_NAT_NONE;
- break;
-
- case UNW_WHERE_PSPREL:
- case UNW_WHERE_SPREL:
- opc = UNW_INSN_SETNAT_MEMSTK;
- break;
-
- default:
- UNW_DPRINT(0, "unwind.%s: don't know how to emit nat info for where = %u\n",
- __func__, r->where);
- return;
- }
- insn.opc = opc;
- insn.dst = unw.preg_index[i];
- insn.val = val;
- script_emit(script, insn);
-}
-
-static void
-compile_reg (struct unw_state_record *sr, int i, struct unw_script *script)
-{
- struct unw_reg_info *r = sr->curr.reg + i;
- enum unw_insn_opcode opc;
- unsigned long val, rval;
- struct unw_insn insn;
- long need_nat_info;
-
- if (r->where == UNW_WHERE_NONE || r->when >= sr->when_target)
- return;
-
- opc = UNW_INSN_MOVE;
- val = rval = r->val;
- need_nat_info = (i >= UNW_REG_R4 && i <= UNW_REG_R7);
-
- switch (r->where) {
- case UNW_WHERE_GR:
- if (rval >= 32) {
- opc = UNW_INSN_MOVE_STACKED;
- val = rval - 32;
- } else if (rval >= 4 && rval <= 7) {
- if (need_nat_info) {
- opc = UNW_INSN_MOVE2;
- need_nat_info = 0;
- }
- val = unw.preg_index[UNW_REG_R4 + (rval - 4)];
- } else if (rval == 0) {
- opc = UNW_INSN_MOVE_CONST;
- val = 0;
- } else {
- /* register got spilled to a scratch register */
- opc = UNW_INSN_MOVE_SCRATCH;
- val = pt_regs_off(rval);
- }
- break;
-
- case UNW_WHERE_FR:
- if (rval <= 5)
- val = unw.preg_index[UNW_REG_F2 + (rval - 2)];
- else if (rval >= 16 && rval <= 31)
- val = unw.preg_index[UNW_REG_F16 + (rval - 16)];
- else {
- opc = UNW_INSN_MOVE_SCRATCH;
- if (rval <= 11)
- val = offsetof(struct pt_regs, f6) + 16*(rval - 6);
- else
- UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n",
- __func__, rval);
- }
- break;
-
- case UNW_WHERE_BR:
- if (rval >= 1 && rval <= 5)
- val = unw.preg_index[UNW_REG_B1 + (rval - 1)];
- else {
- opc = UNW_INSN_MOVE_SCRATCH;
- if (rval == 0)
- val = offsetof(struct pt_regs, b0);
- else if (rval == 6)
- val = offsetof(struct pt_regs, b6);
- else
- val = offsetof(struct pt_regs, b7);
- }
- break;
-
- case UNW_WHERE_SPREL:
- opc = UNW_INSN_ADD_SP;
- break;
-
- case UNW_WHERE_PSPREL:
- opc = UNW_INSN_ADD_PSP;
- break;
-
- default:
- UNW_DPRINT(0, "unwind%s: register %u has unexpected `where' value of %u\n",
- __func__, i, r->where);
- break;
- }
- insn.opc = opc;
- insn.dst = unw.preg_index[i];
- insn.val = val;
- script_emit(script, insn);
- if (need_nat_info)
- emit_nat_info(sr, i, script);
-
- if (i == UNW_REG_PSP) {
- /*
- * info->psp must contain the _value_ of the previous
- * sp, not it's save location. We get this by
- * dereferencing the value we just stored in
- * info->psp:
- */
- insn.opc = UNW_INSN_LOAD;
- insn.dst = insn.val = unw.preg_index[UNW_REG_PSP];
- script_emit(script, insn);
- }
-}
-
-static inline const struct unw_table_entry *
-lookup (struct unw_table *table, unsigned long rel_ip)
-{
- const struct unw_table_entry *e = NULL;
- unsigned long lo, hi, mid;
-
- /* do a binary search for right entry: */
- for (lo = 0, hi = table->length; lo < hi; ) {
- mid = (lo + hi) / 2;
- e = &table->array[mid];
- if (rel_ip < e->start_offset)
- hi = mid;
- else if (rel_ip >= e->end_offset)
- lo = mid + 1;
- else
- break;
- }
- if (rel_ip < e->start_offset || rel_ip >= e->end_offset)
- return NULL;
- return e;
-}
-
-/*
- * Build an unwind script that unwinds from state OLD_STATE to the
- * entrypoint of the function that called OLD_STATE.
- */
-static inline struct unw_script *
-build_script (struct unw_frame_info *info)
-{
- const struct unw_table_entry *e = NULL;
- struct unw_script *script = NULL;
- struct unw_labeled_state *ls, *next;
- unsigned long ip = info->ip;
- struct unw_state_record sr;
- struct unw_table *table, *prev;
- struct unw_reg_info *r;
- struct unw_insn insn;
- u8 *dp, *desc_end;
- u64 hdr;
- int i;
- STAT(unsigned long start, parse_start;)
-
- STAT(++unw.stat.script.builds; start = ia64_get_itc());
-
- /* build state record */
- memset(&sr, 0, sizeof(sr));
- for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r)
- r->when = UNW_WHEN_NEVER;
- sr.pr_val = info->pr;
-
- UNW_DPRINT(3, "unwind.%s: ip 0x%lx\n", __func__, ip);
- script = script_new(ip);
- if (!script) {
- UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n", __func__);
- STAT(unw.stat.script.build_time += ia64_get_itc() - start);
- return NULL;
- }
- unw.cache[info->prev_script].hint = script - unw.cache;
-
- /* search the kernels and the modules' unwind tables for IP: */
-
- STAT(parse_start = ia64_get_itc());
-
- prev = NULL;
- for (table = unw.tables; table; table = table->next) {
- if (ip >= table->start && ip < table->end) {
- /*
- * Leave the kernel unwind table at the very front,
- * lest moving it breaks some assumption elsewhere.
- * Otherwise, move the matching table to the second
- * position in the list so that traversals can benefit
- * from commonality in backtrace paths.
- */
- if (prev && prev != unw.tables) {
- /* unw is safe - we're already spinlocked */
- prev->next = table->next;
- table->next = unw.tables->next;
- unw.tables->next = table;
- }
- e = lookup(table, ip - table->segment_base);
- break;
- }
- prev = table;
- }
- if (!e) {
- /* no info, return default unwinder (leaf proc, no mem stack, no saved regs) */
- UNW_DPRINT(1, "unwind.%s: no unwind info for ip=0x%lx (prev ip=0x%lx)\n",
- __func__, ip, unw.cache[info->prev_script].ip);
- sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
- sr.curr.reg[UNW_REG_RP].when = -1;
- sr.curr.reg[UNW_REG_RP].val = 0;
- compile_reg(&sr, UNW_REG_RP, script);
- script_finalize(script, &sr);
- STAT(unw.stat.script.parse_time += ia64_get_itc() - parse_start);
- STAT(unw.stat.script.build_time += ia64_get_itc() - start);
- return script;
- }
-
- sr.when_target = (3*((ip & ~0xfUL) - (table->segment_base + e->start_offset))/16
- + (ip & 0xfUL));
- hdr = *(u64 *) (table->segment_base + e->info_offset);
- dp = (u8 *) (table->segment_base + e->info_offset + 8);
- desc_end = dp + 8*UNW_LENGTH(hdr);
-
- while (!sr.done && dp < desc_end)
- dp = unw_decode(dp, sr.in_body, &sr);
-
- if (sr.when_target > sr.epilogue_start) {
- /*
- * sp has been restored and all values on the memory stack below
- * psp also have been restored.
- */
- sr.curr.reg[UNW_REG_PSP].val = 0;
- sr.curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;
- sr.curr.reg[UNW_REG_PSP].when = UNW_WHEN_NEVER;
- for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r)
- if ((r->where == UNW_WHERE_PSPREL && r->val <= 0x10)
- || r->where == UNW_WHERE_SPREL)
- {
- r->val = 0;
- r->where = UNW_WHERE_NONE;
- r->when = UNW_WHEN_NEVER;
- }
- }
-
- script->flags = sr.flags;
-
- /*
- * If RP did't get saved, generate entry for the return link
- * register.
- */
- if (sr.curr.reg[UNW_REG_RP].when >= sr.when_target) {
- sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
- sr.curr.reg[UNW_REG_RP].when = -1;
- sr.curr.reg[UNW_REG_RP].val = sr.return_link_reg;
- UNW_DPRINT(1, "unwind.%s: using default for rp at ip=0x%lx where=%d val=0x%lx\n",
- __func__, ip, sr.curr.reg[UNW_REG_RP].where,
- sr.curr.reg[UNW_REG_RP].val);
- }
-
-#ifdef UNW_DEBUG
- UNW_DPRINT(1, "unwind.%s: state record for func 0x%lx, t=%u:\n",
- __func__, table->segment_base + e->start_offset, sr.when_target);
- for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) {
- if (r->where != UNW_WHERE_NONE || r->when != UNW_WHEN_NEVER) {
- UNW_DPRINT(1, " %s <- ", unw.preg_name[r - sr.curr.reg]);
- switch (r->where) {
- case UNW_WHERE_GR: UNW_DPRINT(1, "r%lu", r->val); break;
- case UNW_WHERE_FR: UNW_DPRINT(1, "f%lu", r->val); break;
- case UNW_WHERE_BR: UNW_DPRINT(1, "b%lu", r->val); break;
- case UNW_WHERE_SPREL: UNW_DPRINT(1, "[sp+0x%lx]", r->val); break;
- case UNW_WHERE_PSPREL: UNW_DPRINT(1, "[psp+0x%lx]", r->val); break;
- case UNW_WHERE_NONE:
- UNW_DPRINT(1, "%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val);
- break;
-
- default:
- UNW_DPRINT(1, "BADWHERE(%d)", r->where);
- break;
- }
- UNW_DPRINT(1, "\t\t%d\n", r->when);
- }
- }
-#endif
-
- STAT(unw.stat.script.parse_time += ia64_get_itc() - parse_start);
-
- /* translate state record into unwinder instructions: */
-
- /*
- * First, set psp if we're dealing with a fixed-size frame;
- * subsequent instructions may depend on this value.
- */
- if (sr.when_target > sr.curr.reg[UNW_REG_PSP].when
- && (sr.curr.reg[UNW_REG_PSP].where == UNW_WHERE_NONE)
- && sr.curr.reg[UNW_REG_PSP].val != 0) {
- /* new psp is sp plus frame size */
- insn.opc = UNW_INSN_ADD;
- insn.dst = offsetof(struct unw_frame_info, psp)/8;
- insn.val = sr.curr.reg[UNW_REG_PSP].val; /* frame size */
- script_emit(script, insn);
- }
-
- /* determine where the primary UNaT is: */
- if (sr.when_target < sr.curr.reg[UNW_REG_PRI_UNAT_GR].when)
- i = UNW_REG_PRI_UNAT_MEM;
- else if (sr.when_target < sr.curr.reg[UNW_REG_PRI_UNAT_MEM].when)
- i = UNW_REG_PRI_UNAT_GR;
- else if (sr.curr.reg[UNW_REG_PRI_UNAT_MEM].when > sr.curr.reg[UNW_REG_PRI_UNAT_GR].when)
- i = UNW_REG_PRI_UNAT_MEM;
- else
- i = UNW_REG_PRI_UNAT_GR;
-
- compile_reg(&sr, i, script);
-
- for (i = UNW_REG_BSP; i < UNW_NUM_REGS; ++i)
- compile_reg(&sr, i, script);
-
- /* free labeled register states & stack: */
-
- STAT(parse_start = ia64_get_itc());
- for (ls = sr.labeled_states; ls; ls = next) {
- next = ls->next;
- free_state_stack(&ls->saved_state);
- free_labeled_state(ls);
- }
- free_state_stack(&sr.curr);
- STAT(unw.stat.script.parse_time += ia64_get_itc() - parse_start);
-
- script_finalize(script, &sr);
- STAT(unw.stat.script.build_time += ia64_get_itc() - start);
- return script;
-}
-
-/*
- * Apply the unwinding actions represented by OPS and update SR to
- * reflect the state that existed upon entry to the function that this
- * unwinder represents.
- */
-static inline void
-run_script (struct unw_script *script, struct unw_frame_info *state)
-{
- struct unw_insn *ip, *limit, next_insn;
- unsigned long opc, dst, val, off;
- unsigned long *s = (unsigned long *) state;
- STAT(unsigned long start;)
-
- STAT(++unw.stat.script.runs; start = ia64_get_itc());
- state->flags = script->flags;
- ip = script->insn;
- limit = script->insn + script->count;
- next_insn = *ip;
-
- while (ip++ < limit) {
- opc = next_insn.opc;
- dst = next_insn.dst;
- val = next_insn.val;
- next_insn = *ip;
-
- redo:
- switch (opc) {
- case UNW_INSN_ADD:
- s[dst] += val;
- break;
-
- case UNW_INSN_MOVE2:
- if (!s[val])
- goto lazy_init;
- s[dst+1] = s[val+1];
- s[dst] = s[val];
- break;
-
- case UNW_INSN_MOVE:
- if (!s[val])
- goto lazy_init;
- s[dst] = s[val];
- break;
-
- case UNW_INSN_MOVE_SCRATCH:
- if (state->pt) {
- s[dst] = (unsigned long) get_scratch_regs(state) + val;
- } else {
- s[dst] = 0;
- UNW_DPRINT(0, "unwind.%s: no state->pt, dst=%ld, val=%ld\n",
- __func__, dst, val);
- }
- break;
-
- case UNW_INSN_MOVE_CONST:
- if (val == 0)
- s[dst] = (unsigned long) &unw.r0;
- else {
- s[dst] = 0;
- UNW_DPRINT(0, "unwind.%s: UNW_INSN_MOVE_CONST bad val=%ld\n",
- __func__, val);
- }
- break;
-
-
- case UNW_INSN_MOVE_STACKED:
- s[dst] = (unsigned long) ia64_rse_skip_regs((unsigned long *)state->bsp,
- val);
- break;
-
- case UNW_INSN_ADD_PSP:
- s[dst] = state->psp + val;
- break;
-
- case UNW_INSN_ADD_SP:
- s[dst] = state->sp + val;
- break;
-
- case UNW_INSN_SETNAT_MEMSTK:
- if (!state->pri_unat_loc)
- state->pri_unat_loc = &state->sw->caller_unat;
- /* register off. is a multiple of 8, so the least 3 bits (type) are 0 */
- s[dst+1] = ((unsigned long) state->pri_unat_loc - s[dst]) | UNW_NAT_MEMSTK;
- break;
-
- case UNW_INSN_SETNAT_TYPE:
- s[dst+1] = val;
- break;
-
- case UNW_INSN_LOAD:
-#ifdef UNW_DEBUG
- if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0
- || s[val] < TASK_SIZE)
- {
- UNW_DPRINT(0, "unwind.%s: rejecting bad psp=0x%lx\n",
- __func__, s[val]);
- break;
- }
-#endif
- s[dst] = *(unsigned long *) s[val];
- break;
- }
- }
- STAT(unw.stat.script.run_time += ia64_get_itc() - start);
- return;
-
- lazy_init:
- off = unw.sw_off[val];
- s[val] = (unsigned long) state->sw + off;
- if (off >= offsetof(struct switch_stack, r4) && off <= offsetof(struct switch_stack, r7))
- /*
- * We're initializing a general register: init NaT info, too. Note that
- * the offset is a multiple of 8 which gives us the 3 bits needed for
- * the type field.
- */
- s[val+1] = (offsetof(struct switch_stack, ar_unat) - off) | UNW_NAT_MEMSTK;
- goto redo;
-}
-
-static int
-find_save_locs (struct unw_frame_info *info)
-{
- int have_write_lock = 0;
- struct unw_script *scr;
- unsigned long flags = 0;
-
- if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) {
- /* don't let obviously bad addresses pollute the cache */
- /* FIXME: should really be level 0 but it occurs too often. KAO */
- UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __func__, info->ip);
- info->rp_loc = NULL;
- return -1;
- }
-
- scr = script_lookup(info);
- if (!scr) {
- spin_lock_irqsave(&unw.lock, flags);
- scr = build_script(info);
- if (!scr) {
- spin_unlock_irqrestore(&unw.lock, flags);
- UNW_DPRINT(0,
- "unwind.%s: failed to locate/build unwind script for ip %lx\n",
- __func__, info->ip);
- return -1;
- }
- have_write_lock = 1;
- }
- info->hint = scr->hint;
- info->prev_script = scr - unw.cache;
-
- run_script(scr, info);
-
- if (have_write_lock) {
- write_unlock(&scr->lock);
- spin_unlock_irqrestore(&unw.lock, flags);
- } else
- read_unlock(&scr->lock);
- return 0;
-}
-
-static int
-unw_valid(const struct unw_frame_info *info, unsigned long* p)
-{
- unsigned long loc = (unsigned long)p;
- return (loc >= info->regstk.limit && loc < info->regstk.top) ||
- (loc >= info->memstk.top && loc < info->memstk.limit);
-}
-
-int
-unw_unwind (struct unw_frame_info *info)
-{
- unsigned long prev_ip, prev_sp, prev_bsp;
- unsigned long ip, pr, num_regs;
- STAT(unsigned long start, flags;)
- int retval;
-
- STAT(local_irq_save(flags); ++unw.stat.api.unwinds; start = ia64_get_itc());
-
- prev_ip = info->ip;
- prev_sp = info->sp;
- prev_bsp = info->bsp;
-
- /* validate the return IP pointer */
- if (!unw_valid(info, info->rp_loc)) {
- /* FIXME: should really be level 0 but it occurs too often. KAO */
- UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n",
- __func__, info->ip);
- STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
- return -1;
- }
- /* restore the ip */
- ip = info->ip = *info->rp_loc;
- if (ip < GATE_ADDR) {
- UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __func__, ip);
- STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
- return -1;
- }
-
- /* validate the previous stack frame pointer */
- if (!unw_valid(info, info->pfs_loc)) {
- UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __func__);
- STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
- return -1;
- }
- /* restore the cfm: */
- info->cfm_loc = info->pfs_loc;
-
- /* restore the bsp: */
- pr = info->pr;
- num_regs = 0;
- if ((info->flags & UNW_FLAG_INTERRUPT_FRAME)) {
- info->pt = info->sp + 16;
- if ((pr & (1UL << PRED_NON_SYSCALL)) != 0)
- num_regs = *info->cfm_loc & 0x7f; /* size of frame */
- info->pfs_loc =
- (unsigned long *) (info->pt + offsetof(struct pt_regs, ar_pfs));
- UNW_DPRINT(3, "unwind.%s: interrupt_frame pt 0x%lx\n", __func__, info->pt);
- } else
- num_regs = (*info->cfm_loc >> 7) & 0x7f; /* size of locals */
- info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -num_regs);
- if (info->bsp < info->regstk.limit || info->bsp > info->regstk.top) {
- UNW_DPRINT(0, "unwind.%s: bsp (0x%lx) out of range [0x%lx-0x%lx]\n",
- __func__, info->bsp, info->regstk.limit, info->regstk.top);
- STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
- return -1;
- }
-
- /* restore the sp: */
- info->sp = info->psp;
- if (info->sp < info->memstk.top || info->sp > info->memstk.limit) {
- UNW_DPRINT(0, "unwind.%s: sp (0x%lx) out of range [0x%lx-0x%lx]\n",
- __func__, info->sp, info->memstk.top, info->memstk.limit);
- STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
- return -1;
- }
-
- if (info->ip == prev_ip && info->sp == prev_sp && info->bsp == prev_bsp) {
- UNW_DPRINT(0, "unwind.%s: ip, sp, bsp unchanged; stopping here (ip=0x%lx)\n",
- __func__, ip);
- STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
- return -1;
- }
-
- /* as we unwind, the saved ar.unat becomes the primary unat: */
- info->pri_unat_loc = info->unat_loc;
-
- /* finally, restore the predicates: */
- unw_get_pr(info, &info->pr);
-
- retval = find_save_locs(info);
- STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
- return retval;
-}
-EXPORT_SYMBOL(unw_unwind);
-
-int
-unw_unwind_to_user (struct unw_frame_info *info)
-{
- unsigned long ip, sp, pr = info->pr;
-
- do {
- unw_get_sp(info, &sp);
- if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp)
- < IA64_PT_REGS_SIZE) {
- UNW_DPRINT(0, "unwind.%s: ran off the top of the kernel stack\n",
- __func__);
- break;
- }
- if (unw_is_intr_frame(info) &&
- (pr & (1UL << PRED_USER_STACK)))
- return 0;
- if (unw_get_pr (info, &pr) < 0) {
- unw_get_rp(info, &ip);
- UNW_DPRINT(0, "unwind.%s: failed to read "
- "predicate register (ip=0x%lx)\n",
- __func__, ip);
- return -1;
- }
- } while (unw_unwind(info) >= 0);
- unw_get_ip(info, &ip);
- UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n",
- __func__, ip);
- return -1;
-}
-EXPORT_SYMBOL(unw_unwind_to_user);
-
-static void
-init_frame_info (struct unw_frame_info *info, struct task_struct *t,
- struct switch_stack *sw, unsigned long stktop)
-{
- unsigned long rbslimit, rbstop, stklimit;
- STAT(unsigned long start, flags;)
-
- STAT(local_irq_save(flags); ++unw.stat.api.inits; start = ia64_get_itc());
-
- /*
- * Subtle stuff here: we _could_ unwind through the switch_stack frame but we
- * don't want to do that because it would be slow as each preserved register would
- * have to be processed. Instead, what we do here is zero out the frame info and
- * start the unwind process at the function that created the switch_stack frame.
- * When a preserved value in switch_stack needs to be accessed, run_script() will
- * initialize the appropriate pointer on demand.
- */
- memset(info, 0, sizeof(*info));
-
- rbslimit = (unsigned long) t + IA64_RBS_OFFSET;
- stklimit = (unsigned long) t + IA64_STK_OFFSET;
-
- rbstop = sw->ar_bspstore;
- if (rbstop > stklimit || rbstop < rbslimit)
- rbstop = rbslimit;
-
- if (stktop <= rbstop)
- stktop = rbstop;
- if (stktop > stklimit)
- stktop = stklimit;
-
- info->regstk.limit = rbslimit;
- info->regstk.top = rbstop;
- info->memstk.limit = stklimit;
- info->memstk.top = stktop;
- info->task = t;
- info->sw = sw;
- info->sp = info->psp = stktop;
- info->pr = sw->pr;
- UNW_DPRINT(3, "unwind.%s:\n"
- " task 0x%lx\n"
- " rbs = [0x%lx-0x%lx)\n"
- " stk = [0x%lx-0x%lx)\n"
- " pr 0x%lx\n"
- " sw 0x%lx\n"
- " sp 0x%lx\n",
- __func__, (unsigned long) t, rbslimit, rbstop, stktop, stklimit,
- info->pr, (unsigned long) info->sw, info->sp);
- STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags));
-}
-
-void
-unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw)
-{
- unsigned long sol;
-
- init_frame_info(info, t, sw, (unsigned long) (sw + 1) - 16);
- info->cfm_loc = &sw->ar_pfs;
- sol = (*info->cfm_loc >> 7) & 0x7f;
- info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol);
- info->ip = sw->b0;
- UNW_DPRINT(3, "unwind.%s:\n"
- " bsp 0x%lx\n"
- " sol 0x%lx\n"
- " ip 0x%lx\n",
- __func__, info->bsp, sol, info->ip);
- find_save_locs(info);
-}
-
-EXPORT_SYMBOL(unw_init_frame_info);
-
-void
-unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t)
-{
- struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16);
-
- UNW_DPRINT(1, "unwind.%s\n", __func__);
- unw_init_frame_info(info, t, sw);
-}
-EXPORT_SYMBOL(unw_init_from_blocked_task);
-
-static void
-init_unwind_table (struct unw_table *table, const char *name, unsigned long segment_base,
- unsigned long gp, const void *table_start, const void *table_end)
-{
- const struct unw_table_entry *start = table_start, *end = table_end;
-
- table->name = name;
- table->segment_base = segment_base;
- table->gp = gp;
- table->start = segment_base + start[0].start_offset;
- table->end = segment_base + end[-1].end_offset;
- table->array = start;
- table->length = end - start;
-}
-
-void *
-unw_add_unwind_table (const char *name, unsigned long segment_base, unsigned long gp,
- const void *table_start, const void *table_end)
-{
- const struct unw_table_entry *start = table_start, *end = table_end;
- struct unw_table *table;
- unsigned long flags;
-
- if (end - start <= 0) {
- UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n",
- __func__);
- return NULL;
- }
-
- table = kmalloc(sizeof(*table), GFP_USER);
- if (!table)
- return NULL;
-
- init_unwind_table(table, name, segment_base, gp, table_start, table_end);
-
- spin_lock_irqsave(&unw.lock, flags);
- {
- /* keep kernel unwind table at the front (it's searched most commonly): */
- table->next = unw.tables->next;
- unw.tables->next = table;
- }
- spin_unlock_irqrestore(&unw.lock, flags);
-
- return table;
-}
-
-void
-unw_remove_unwind_table (void *handle)
-{
- struct unw_table *table, *prev;
- struct unw_script *tmp;
- unsigned long flags;
- long index;
-
- if (!handle) {
- UNW_DPRINT(0, "unwind.%s: ignoring attempt to remove non-existent unwind table\n",
- __func__);
- return;
- }
-
- table = handle;
- if (table == &unw.kernel_table) {
- UNW_DPRINT(0, "unwind.%s: sorry, freeing the kernel's unwind table is a "
- "no-can-do!\n", __func__);
- return;
- }
-
- spin_lock_irqsave(&unw.lock, flags);
- {
- /* first, delete the table: */
-
- for (prev = (struct unw_table *) &unw.tables; prev; prev = prev->next)
- if (prev->next == table)
- break;
- if (!prev) {
- UNW_DPRINT(0, "unwind.%s: failed to find unwind table %p\n",
- __func__, (void *) table);
- spin_unlock_irqrestore(&unw.lock, flags);
- return;
- }
- prev->next = table->next;
- }
- spin_unlock_irqrestore(&unw.lock, flags);
-
- /* next, remove hash table entries for this table */
-
- for (index = 0; index < UNW_HASH_SIZE; ++index) {
- tmp = unw.cache + unw.hash[index];
- if (unw.hash[index] >= UNW_CACHE_SIZE
- || tmp->ip < table->start || tmp->ip >= table->end)
- continue;
-
- write_lock(&tmp->lock);
- {
- if (tmp->ip >= table->start && tmp->ip < table->end) {
- unw.hash[index] = tmp->coll_chain;
- tmp->ip = 0;
- }
- }
- write_unlock(&tmp->lock);
- }
-
- kfree(table);
-}
-
-static int __init
-create_gate_table (void)
-{
- const struct unw_table_entry *entry, *start, *end;
- unsigned long *lp, segbase = GATE_ADDR;
- size_t info_size, size;
- char *info;
- Elf64_Phdr *punw = NULL, *phdr = (Elf64_Phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
- int i;
-
- for (i = 0; i < GATE_EHDR->e_phnum; ++i, ++phdr)
- if (phdr->p_type == PT_IA_64_UNWIND) {
- punw = phdr;
- break;
- }
-
- if (!punw) {
- printk("%s: failed to find gate DSO's unwind table!\n", __func__);
- return 0;
- }
-
- start = (const struct unw_table_entry *) punw->p_vaddr;
- end = (struct unw_table_entry *) ((char *) start + punw->p_memsz);
- size = 0;
-
- unw_add_unwind_table("linux-gate.so", segbase, 0, start, end);
-
- for (entry = start; entry < end; ++entry)
- size += 3*8 + 8 + 8*UNW_LENGTH(*(u64 *) (segbase + entry->info_offset));
- size += 8; /* reserve space for "end of table" marker */
-
- unw.gate_table = kmalloc(size, GFP_KERNEL);
- if (!unw.gate_table) {
- unw.gate_table_size = 0;
- printk(KERN_ERR "%s: unable to create unwind data for gate page!\n", __func__);
- return 0;
- }
- unw.gate_table_size = size;
-
- lp = unw.gate_table;
- info = (char *) unw.gate_table + size;
-
- for (entry = start; entry < end; ++entry, lp += 3) {
- info_size = 8 + 8*UNW_LENGTH(*(u64 *) (segbase + entry->info_offset));
- info -= info_size;
- memcpy(info, (char *) segbase + entry->info_offset, info_size);
-
- lp[0] = segbase + entry->start_offset; /* start */
- lp[1] = segbase + entry->end_offset; /* end */
- lp[2] = info - (char *) unw.gate_table; /* info */
- }
- *lp = 0; /* end-of-table marker */
- return 0;
-}
-
-__initcall(create_gate_table);
-
-void __init
-unw_init (void)
-{
- extern char __gp[];
- extern void unw_hash_index_t_is_too_narrow (void);
- long i, off;
-
- if (8*sizeof(unw_hash_index_t) < UNW_LOG_HASH_SIZE)
- unw_hash_index_t_is_too_narrow();
-
- unw.sw_off[unw.preg_index[UNW_REG_PRI_UNAT_GR]] = SW(CALLER_UNAT);
- unw.sw_off[unw.preg_index[UNW_REG_BSPSTORE]] = SW(AR_BSPSTORE);
- unw.sw_off[unw.preg_index[UNW_REG_PFS]] = SW(AR_PFS);
- unw.sw_off[unw.preg_index[UNW_REG_RP]] = SW(B0);
- unw.sw_off[unw.preg_index[UNW_REG_UNAT]] = SW(CALLER_UNAT);
- unw.sw_off[unw.preg_index[UNW_REG_PR]] = SW(PR);
- unw.sw_off[unw.preg_index[UNW_REG_LC]] = SW(AR_LC);
- unw.sw_off[unw.preg_index[UNW_REG_FPSR]] = SW(AR_FPSR);
- for (i = UNW_REG_R4, off = SW(R4); i <= UNW_REG_R7; ++i, off += 8)
- unw.sw_off[unw.preg_index[i]] = off;
- for (i = UNW_REG_B1, off = SW(B1); i <= UNW_REG_B5; ++i, off += 8)
- unw.sw_off[unw.preg_index[i]] = off;
- for (i = UNW_REG_F2, off = SW(F2); i <= UNW_REG_F5; ++i, off += 16)
- unw.sw_off[unw.preg_index[i]] = off;
- for (i = UNW_REG_F16, off = SW(F16); i <= UNW_REG_F31; ++i, off += 16)
- unw.sw_off[unw.preg_index[i]] = off;
-
- for (i = 0; i < UNW_CACHE_SIZE; ++i) {
- if (i > 0)
- unw.cache[i].lru_chain = (i - 1);
- unw.cache[i].coll_chain = -1;
- rwlock_init(&unw.cache[i].lock);
- }
- unw.lru_head = UNW_CACHE_SIZE - 1;
- unw.lru_tail = 0;
-
- init_unwind_table(&unw.kernel_table, "kernel", KERNEL_START, (unsigned long) __gp,
- __start_unwind, __end_unwind);
-}
-
-/*
- * DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
- *
- * This system call has been deprecated. The new and improved way to get
- * at the kernel's unwind info is via the gate DSO. The address of the
- * ELF header for this DSO is passed to user-level via AT_SYSINFO_EHDR.
- *
- * DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
- *
- * This system call copies the unwind data into the buffer pointed to by BUF and returns
- * the size of the unwind data. If BUF_SIZE is smaller than the size of the unwind data
- * or if BUF is NULL, nothing is copied, but the system call still returns the size of the
- * unwind data.
- *
- * The first portion of the unwind data contains an unwind table and rest contains the
- * associated unwind info (in no particular order). The unwind table consists of a table
- * of entries of the form:
- *
- * u64 start; (64-bit address of start of function)
- * u64 end; (64-bit address of start of function)
- * u64 info; (BUF-relative offset to unwind info)
- *
- * The end of the unwind table is indicated by an entry with a START address of zero.
- *
- * Please see the IA-64 Software Conventions and Runtime Architecture manual for details
- * on the format of the unwind info.
- *
- * ERRORS
- * EFAULT BUF points outside your accessible address space.
- */
-asmlinkage long
-sys_getunwind (void __user *buf, size_t buf_size)
-{
- if (buf && buf_size >= unw.gate_table_size)
- if (copy_to_user(buf, unw.gate_table, unw.gate_table_size) != 0)
- return -EFAULT;
- return unw.gate_table_size;
-}
diff --git a/arch/ia64/kernel/unwind_decoder.c b/arch/ia64/kernel/unwind_decoder.c
deleted file mode 100644
index 83f54f7929b5..000000000000
--- a/arch/ia64/kernel/unwind_decoder.c
+++ /dev/null
@@ -1,460 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2000 Hewlett-Packard Co
- * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * Generic IA-64 unwind info decoder.
- *
- * This file is used both by the Linux kernel and objdump. Please keep
- * the two copies of this file in sync.
- *
- * You need to customize the decoder by defining the following
- * macros/constants before including this file:
- *
- * Types:
- * unw_word Unsigned integer type with at least 64 bits
- *
- * Register names:
- * UNW_REG_BSP
- * UNW_REG_BSPSTORE
- * UNW_REG_FPSR
- * UNW_REG_LC
- * UNW_REG_PFS
- * UNW_REG_PR
- * UNW_REG_RNAT
- * UNW_REG_PSP
- * UNW_REG_RP
- * UNW_REG_UNAT
- *
- * Decoder action macros:
- * UNW_DEC_BAD_CODE(code)
- * UNW_DEC_ABI(fmt,abi,context,arg)
- * UNW_DEC_BR_GR(fmt,brmask,gr,arg)
- * UNW_DEC_BR_MEM(fmt,brmask,arg)
- * UNW_DEC_COPY_STATE(fmt,label,arg)
- * UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
- * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
- * UNW_DEC_FR_MEM(fmt,frmask,arg)
- * UNW_DEC_GR_GR(fmt,grmask,gr,arg)
- * UNW_DEC_GR_MEM(fmt,grmask,arg)
- * UNW_DEC_LABEL_STATE(fmt,label,arg)
- * UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
- * UNW_DEC_MEM_STACK_V(fmt,t,arg)
- * UNW_DEC_PRIUNAT_GR(fmt,r,arg)
- * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
- * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
- * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
- * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
- * UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
- * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
- * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
- * UNW_DEC_REG_REG(fmt,src,dst,arg)
- * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
- * UNW_DEC_REG_WHEN(fmt,reg,t,arg)
- * UNW_DEC_RESTORE(fmt,t,abreg,arg)
- * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
- * UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
- * UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
- * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
- * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
- * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
- * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
- * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
- * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
- */
-
-static unw_word
-unw_decode_uleb128 (unsigned char **dpp)
-{
- unsigned shift = 0;
- unw_word byte, result = 0;
- unsigned char *bp = *dpp;
-
- while (1)
- {
- byte = *bp++;
- result |= (byte & 0x7f) << shift;
- if ((byte & 0x80) == 0)
- break;
- shift += 7;
- }
- *dpp = bp;
- return result;
-}
-
-static unsigned char *
-unw_decode_x1 (unsigned char *dp, unsigned char code, void *arg)
-{
- unsigned char byte1, abreg;
- unw_word t, off;
-
- byte1 = *dp++;
- t = unw_decode_uleb128 (&dp);
- off = unw_decode_uleb128 (&dp);
- abreg = (byte1 & 0x7f);
- if (byte1 & 0x80)
- UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg);
- else
- UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg);
- return dp;
-}
-
-static unsigned char *
-unw_decode_x2 (unsigned char *dp, unsigned char code, void *arg)
-{
- unsigned char byte1, byte2, abreg, x, ytreg;
- unw_word t;
-
- byte1 = *dp++; byte2 = *dp++;
- t = unw_decode_uleb128 (&dp);
- abreg = (byte1 & 0x7f);
- ytreg = byte2;
- x = (byte1 >> 7) & 1;
- if ((byte1 & 0x80) == 0 && ytreg == 0)
- UNW_DEC_RESTORE(X2, t, abreg, arg);
- else
- UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg);
- return dp;
-}
-
-static unsigned char *
-unw_decode_x3 (unsigned char *dp, unsigned char code, void *arg)
-{
- unsigned char byte1, byte2, abreg, qp;
- unw_word t, off;
-
- byte1 = *dp++; byte2 = *dp++;
- t = unw_decode_uleb128 (&dp);
- off = unw_decode_uleb128 (&dp);
-
- qp = (byte1 & 0x3f);
- abreg = (byte2 & 0x7f);
-
- if (byte1 & 0x80)
- UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg);
- else
- UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg);
- return dp;
-}
-
-static unsigned char *
-unw_decode_x4 (unsigned char *dp, unsigned char code, void *arg)
-{
- unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
- unw_word t;
-
- byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
- t = unw_decode_uleb128 (&dp);
-
- qp = (byte1 & 0x3f);
- abreg = (byte2 & 0x7f);
- x = (byte2 >> 7) & 1;
- ytreg = byte3;
-
- if ((byte2 & 0x80) == 0 && byte3 == 0)
- UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg);
- else
- UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg);
- return dp;
-}
-
-static unsigned char *
-unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
-{
- int body = (code & 0x20) != 0;
- unw_word rlen;
-
- rlen = (code & 0x1f);
- UNW_DEC_PROLOGUE(R1, body, rlen, arg);
- return dp;
-}
-
-static unsigned char *
-unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
-{
- unsigned char byte1, mask, grsave;
- unw_word rlen;
-
- byte1 = *dp++;
-
- mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
- grsave = (byte1 & 0x7f);
- rlen = unw_decode_uleb128 (&dp);
- UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg);
- return dp;
-}
-
-static unsigned char *
-unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
-{
- unw_word rlen;
-
- rlen = unw_decode_uleb128 (&dp);
- UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg);
- return dp;
-}
-
-static unsigned char *
-unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
-{
- unsigned char brmask = (code & 0x1f);
-
- UNW_DEC_BR_MEM(P1, brmask, arg);
- return dp;
-}
-
-static unsigned char *
-unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
-{
- if ((code & 0x10) == 0)
- {
- unsigned char byte1 = *dp++;
-
- UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
- (byte1 & 0x7f), arg);
- }
- else if ((code & 0x08) == 0)
- {
- unsigned char byte1 = *dp++, r, dst;
-
- r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
- dst = (byte1 & 0x7f);
- switch (r)
- {
- case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break;
- case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break;
- case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break;
- case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break;
- case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break;
- case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break;
- case 6: UNW_DEC_RP_BR(P3, dst, arg); break;
- case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break;
- case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break;
- case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break;
- case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break;
- case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break;
- default: UNW_DEC_BAD_CODE(r); break;
- }
- }
- else if ((code & 0x7) == 0)
- UNW_DEC_SPILL_MASK(P4, dp, arg);
- else if ((code & 0x7) == 1)
- {
- unw_word grmask, frmask, byte1, byte2, byte3;
-
- byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
- grmask = ((byte1 >> 4) & 0xf);
- frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
- UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg);
- }
- else
- UNW_DEC_BAD_CODE(code);
- return dp;
-}
-
-static unsigned char *
-unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
-{
- int gregs = (code & 0x10) != 0;
- unsigned char mask = (code & 0x0f);
-
- if (gregs)
- UNW_DEC_GR_MEM(P6, mask, arg);
- else
- UNW_DEC_FR_MEM(P6, mask, arg);
- return dp;
-}
-
-static unsigned char *
-unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
-{
- unsigned char r, byte1, byte2;
- unw_word t, size;
-
- if ((code & 0x10) == 0)
- {
- r = (code & 0xf);
- t = unw_decode_uleb128 (&dp);
- switch (r)
- {
- case 0:
- size = unw_decode_uleb128 (&dp);
- UNW_DEC_MEM_STACK_F(P7, t, size, arg);
- break;
-
- case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break;
- case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break;
- case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break;
- case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break;
- case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break;
- case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break;
- case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break;
- case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break;
- case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break;
- case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break;
- case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break;
- case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break;
- case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break;
- case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break;
- case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break;
- default: UNW_DEC_BAD_CODE(r); break;
- }
- }
- else
- {
- switch (code & 0xf)
- {
- case 0x0: /* p8 */
- {
- r = *dp++;
- t = unw_decode_uleb128 (&dp);
- switch (r)
- {
- case 1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break;
- case 2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break;
- case 3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break;
- case 4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break;
- case 5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break;
- case 6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break;
- case 7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break;
- case 8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break;
- case 9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break;
- case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break;
- case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
- case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
- case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break;
- case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break;
- case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break;
- case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break;
- case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break;
- case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break;
- case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break;
- default: UNW_DEC_BAD_CODE(r); break;
- }
- }
- break;
-
- case 0x1:
- byte1 = *dp++; byte2 = *dp++;
- UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
- break;
-
- case 0xf: /* p10 */
- byte1 = *dp++; byte2 = *dp++;
- UNW_DEC_ABI(P10, byte1, byte2, arg);
- break;
-
- case 0x9:
- return unw_decode_x1 (dp, code, arg);
-
- case 0xa:
- return unw_decode_x2 (dp, code, arg);
-
- case 0xb:
- return unw_decode_x3 (dp, code, arg);
-
- case 0xc:
- return unw_decode_x4 (dp, code, arg);
-
- default:
- UNW_DEC_BAD_CODE(code);
- break;
- }
- }
- return dp;
-}
-
-static unsigned char *
-unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
-{
- unw_word label = (code & 0x1f);
-
- if ((code & 0x20) != 0)
- UNW_DEC_COPY_STATE(B1, label, arg);
- else
- UNW_DEC_LABEL_STATE(B1, label, arg);
- return dp;
-}
-
-static unsigned char *
-unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
-{
- unw_word t;
-
- t = unw_decode_uleb128 (&dp);
- UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg);
- return dp;
-}
-
-static unsigned char *
-unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
-{
- unw_word t, ecount, label;
-
- if ((code & 0x10) == 0)
- {
- t = unw_decode_uleb128 (&dp);
- ecount = unw_decode_uleb128 (&dp);
- UNW_DEC_EPILOGUE(B3, t, ecount, arg);
- }
- else if ((code & 0x07) == 0)
- {
- label = unw_decode_uleb128 (&dp);
- if ((code & 0x08) != 0)
- UNW_DEC_COPY_STATE(B4, label, arg);
- else
- UNW_DEC_LABEL_STATE(B4, label, arg);
- }
- else
- switch (code & 0x7)
- {
- case 1: return unw_decode_x1 (dp, code, arg);
- case 2: return unw_decode_x2 (dp, code, arg);
- case 3: return unw_decode_x3 (dp, code, arg);
- case 4: return unw_decode_x4 (dp, code, arg);
- default: UNW_DEC_BAD_CODE(code); break;
- }
- return dp;
-}
-
-typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
-
-static unw_decoder unw_decode_table[2][8] =
-{
- /* prologue table: */
- {
- unw_decode_r1, /* 0 */
- unw_decode_r1,
- unw_decode_r2,
- unw_decode_r3,
- unw_decode_p1, /* 4 */
- unw_decode_p2_p5,
- unw_decode_p6,
- unw_decode_p7_p10
- },
- {
- unw_decode_r1, /* 0 */
- unw_decode_r1,
- unw_decode_r2,
- unw_decode_r3,
- unw_decode_b1, /* 4 */
- unw_decode_b1,
- unw_decode_b2,
- unw_decode_b3_x4
- }
-};
-
-/*
- * Decode one descriptor and return address of next descriptor.
- */
-static inline unsigned char *
-unw_decode (unsigned char *dp, int inside_body, void *arg)
-{
- unw_decoder decoder;
- unsigned char code;
-
- code = *dp++;
- decoder = unw_decode_table[inside_body][code >> 5];
- dp = (*decoder) (dp, code, arg);
- return dp;
-}
diff --git a/arch/ia64/kernel/unwind_i.h b/arch/ia64/kernel/unwind_i.h
deleted file mode 100644
index 1dd57ba44327..000000000000
--- a/arch/ia64/kernel/unwind_i.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2000, 2002-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * Kernel unwind support.
- */
-
-#define UNW_VER(x) ((x) >> 48)
-#define UNW_FLAG_MASK 0x0000ffff00000000
-#define UNW_FLAG_OSMASK 0x0000f00000000000
-#define UNW_FLAG_EHANDLER(x) ((x) & 0x0000000100000000L)
-#define UNW_FLAG_UHANDLER(x) ((x) & 0x0000000200000000L)
-#define UNW_LENGTH(x) ((x) & 0x00000000ffffffffL)
-
-enum unw_register_index {
- /* primary unat: */
- UNW_REG_PRI_UNAT_GR,
- UNW_REG_PRI_UNAT_MEM,
-
- /* register stack */
- UNW_REG_BSP, /* register stack pointer */
- UNW_REG_BSPSTORE,
- UNW_REG_PFS, /* previous function state */
- UNW_REG_RNAT,
- /* memory stack */
- UNW_REG_PSP, /* previous memory stack pointer */
- /* return pointer: */
- UNW_REG_RP,
-
- /* preserved registers: */
- UNW_REG_R4, UNW_REG_R5, UNW_REG_R6, UNW_REG_R7,
- UNW_REG_UNAT, UNW_REG_PR, UNW_REG_LC, UNW_REG_FPSR,
- UNW_REG_B1, UNW_REG_B2, UNW_REG_B3, UNW_REG_B4, UNW_REG_B5,
- UNW_REG_F2, UNW_REG_F3, UNW_REG_F4, UNW_REG_F5,
- UNW_REG_F16, UNW_REG_F17, UNW_REG_F18, UNW_REG_F19,
- UNW_REG_F20, UNW_REG_F21, UNW_REG_F22, UNW_REG_F23,
- UNW_REG_F24, UNW_REG_F25, UNW_REG_F26, UNW_REG_F27,
- UNW_REG_F28, UNW_REG_F29, UNW_REG_F30, UNW_REG_F31,
- UNW_NUM_REGS
-};
-
-struct unw_info_block {
- u64 header;
- u64 desc[]; /* unwind descriptors */
- /* personality routine and language-specific data follow behind descriptors */
-};
-
-struct unw_table {
- struct unw_table *next; /* must be first member! */
- const char *name;
- unsigned long gp; /* global pointer for this load-module */
- unsigned long segment_base; /* base for offsets in the unwind table entries */
- unsigned long start;
- unsigned long end;
- const struct unw_table_entry *array;
- unsigned long length;
-};
-
-enum unw_where {
- UNW_WHERE_NONE, /* register isn't saved at all */
- UNW_WHERE_GR, /* register is saved in a general register */
- UNW_WHERE_FR, /* register is saved in a floating-point register */
- UNW_WHERE_BR, /* register is saved in a branch register */
- UNW_WHERE_SPREL, /* register is saved on memstack (sp-relative) */
- UNW_WHERE_PSPREL, /* register is saved on memstack (psp-relative) */
- /*
- * At the end of each prologue these locations get resolved to
- * UNW_WHERE_PSPREL and UNW_WHERE_GR, respectively:
- */
- UNW_WHERE_SPILL_HOME, /* register is saved in its spill home */
- UNW_WHERE_GR_SAVE /* register is saved in next general register */
-};
-
-#define UNW_WHEN_NEVER 0x7fffffff
-
-struct unw_reg_info {
- unsigned long val; /* save location: register number or offset */
- enum unw_where where; /* where the register gets saved */
- int when; /* when the register gets saved */
-};
-
-struct unw_reg_state {
- struct unw_reg_state *next; /* next (outer) element on state stack */
- struct unw_reg_info reg[UNW_NUM_REGS]; /* register save locations */
-};
-
-struct unw_labeled_state {
- struct unw_labeled_state *next; /* next labeled state (or NULL) */
- unsigned long label; /* label for this state */
- struct unw_reg_state saved_state;
-};
-
-struct unw_state_record {
- unsigned int first_region : 1; /* is this the first region? */
- unsigned int done : 1; /* are we done scanning descriptors? */
- unsigned int any_spills : 1; /* got any register spills? */
- unsigned int in_body : 1; /* are we inside a body (as opposed to a prologue)? */
- unsigned long flags; /* see UNW_FLAG_* in unwind.h */
-
- u8 *imask; /* imask of spill_mask record or NULL */
- unsigned long pr_val; /* predicate values */
- unsigned long pr_mask; /* predicate mask */
- long spill_offset; /* psp-relative offset for spill base */
- int region_start;
- int region_len;
- int epilogue_start;
- int epilogue_count;
- int when_target;
-
- u8 gr_save_loc; /* next general register to use for saving a register */
- u8 return_link_reg; /* branch register in which the return link is passed */
-
- struct unw_labeled_state *labeled_states; /* list of all labeled states */
- struct unw_reg_state curr; /* current state */
-};
-
-enum unw_nat_type {
- UNW_NAT_NONE, /* NaT not represented */
- UNW_NAT_VAL, /* NaT represented by NaT value (fp reg) */
- UNW_NAT_MEMSTK, /* NaT value is in unat word at offset OFF */
- UNW_NAT_REGSTK /* NaT is in rnat */
-};
-
-enum unw_insn_opcode {
- UNW_INSN_ADD, /* s[dst] += val */
- UNW_INSN_ADD_PSP, /* s[dst] = (s.psp + val) */
- UNW_INSN_ADD_SP, /* s[dst] = (s.sp + val) */
- UNW_INSN_MOVE, /* s[dst] = s[val] */
- UNW_INSN_MOVE2, /* s[dst] = s[val]; s[dst+1] = s[val+1] */
- UNW_INSN_MOVE_STACKED, /* s[dst] = ia64_rse_skip(*s.bsp, val) */
- UNW_INSN_SETNAT_MEMSTK, /* s[dst+1].nat.type = MEMSTK;
- s[dst+1].nat.off = *s.pri_unat - s[dst] */
- UNW_INSN_SETNAT_TYPE, /* s[dst+1].nat.type = val */
- UNW_INSN_LOAD, /* s[dst] = *s[val] */
- UNW_INSN_MOVE_SCRATCH, /* s[dst] = scratch reg "val" */
- UNW_INSN_MOVE_CONST, /* s[dst] = constant reg "val" */
-};
-
-struct unw_insn {
- unsigned int opc : 4;
- unsigned int dst : 9;
- signed int val : 19;
-};
-
-/*
- * Preserved general static registers (r4-r7) give rise to two script
- * instructions; everything else yields at most one instruction; at
- * the end of the script, the psp gets popped, accounting for one more
- * instruction.
- */
-#define UNW_MAX_SCRIPT_LEN (UNW_NUM_REGS + 5)
-
-struct unw_script {
- unsigned long ip; /* ip this script is for */
- unsigned long pr_mask; /* mask of predicates script depends on */
- unsigned long pr_val; /* predicate values this script is for */
- rwlock_t lock;
- unsigned int flags; /* see UNW_FLAG_* in unwind.h */
- unsigned short lru_chain; /* used for least-recently-used chain */
- unsigned short coll_chain; /* used for hash collisions */
- unsigned short hint; /* hint for next script to try (or -1) */
- unsigned short count; /* number of instructions in script */
- struct unw_insn insn[UNW_MAX_SCRIPT_LEN];
-};
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
deleted file mode 100644
index 53dfde161c8a..000000000000
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ /dev/null
@@ -1,224 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#include <linux/pgtable.h>
-#include <asm/cache.h>
-#include <asm/ptrace.h>
-#include <asm/thread_info.h>
-
-#define EMITS_PT_NOTE
-#define RO_EXCEPTION_TABLE_ALIGN 16
-
-#include <asm-generic/vmlinux.lds.h>
-
-OUTPUT_FORMAT("elf64-ia64-little")
-OUTPUT_ARCH(ia64)
-ENTRY(phys_start)
-jiffies = jiffies_64;
-
-PHDRS {
- text PT_LOAD;
- percpu PT_LOAD;
- data PT_LOAD;
- note PT_NOTE;
- unwind 0x70000001; /* PT_IA_64_UNWIND, but ld doesn't match the name */
-}
-
-SECTIONS {
- /*
- * unwind exit sections must be discarded before
- * the rest of the sections get included.
- */
- /DISCARD/ : {
- *(.IA_64.unwind.exit.text)
- *(.IA_64.unwind_info.exit.text)
- *(.comment)
- *(.note)
- }
-
- v = PAGE_OFFSET; /* this symbol is here to make debugging easier... */
- phys_start = _start - LOAD_OFFSET;
-
- code : {
- } :text
- . = KERNEL_START;
-
- _text = .;
- _stext = .;
-
- .text : AT(ADDR(.text) - LOAD_OFFSET) {
- __start_ivt_text = .;
- *(.text..ivt)
- __end_ivt_text = .;
- TEXT_TEXT
- SCHED_TEXT
- LOCK_TEXT
- KPROBES_TEXT
- IRQENTRY_TEXT
- SOFTIRQENTRY_TEXT
- *(.gnu.linkonce.t*)
- }
-
- .text2 : AT(ADDR(.text2) - LOAD_OFFSET) {
- *(.text2)
- }
-
-#ifdef CONFIG_SMP
- .text..lock : AT(ADDR(.text..lock) - LOAD_OFFSET) {
- *(.text..lock)
- }
-#endif
- _etext = .;
-
- /*
- * Read-only data
- */
-
- /* MCA table */
- . = ALIGN(16);
- __mca_table : AT(ADDR(__mca_table) - LOAD_OFFSET) {
- __start___mca_table = .;
- *(__mca_table)
- __stop___mca_table = .;
- }
-
- .data..patch.phys_stack_reg : AT(ADDR(.data..patch.phys_stack_reg) - LOAD_OFFSET) {
- __start___phys_stack_reg_patchlist = .;
- *(.data..patch.phys_stack_reg)
- __end___phys_stack_reg_patchlist = .;
- }
-
- /*
- * Global data
- */
- _data = .;
-
- /* Unwind info & table: */
- . = ALIGN(8);
- .IA_64.unwind_info : AT(ADDR(.IA_64.unwind_info) - LOAD_OFFSET) {
- *(.IA_64.unwind_info*)
- }
- .IA_64.unwind : AT(ADDR(.IA_64.unwind) - LOAD_OFFSET) {
- __start_unwind = .;
- *(.IA_64.unwind*)
- __end_unwind = .;
- } :text :unwind
- code_continues2 : {
- } :text
-
- RO_DATA(4096)
-
- .opd : AT(ADDR(.opd) - LOAD_OFFSET) {
- __start_opd = .;
- *(.opd)
- __end_opd = .;
- }
-
- /*
- * Initialization code and data:
- */
- . = ALIGN(PAGE_SIZE);
- __init_begin = .;
-
- INIT_TEXT_SECTION(PAGE_SIZE)
- INIT_DATA_SECTION(16)
-
- .data..patch.vtop : AT(ADDR(.data..patch.vtop) - LOAD_OFFSET) {
- __start___vtop_patchlist = .;
- *(.data..patch.vtop)
- __end___vtop_patchlist = .;
- }
-
- .data..patch.rse : AT(ADDR(.data..patch.rse) - LOAD_OFFSET) {
- __start___rse_patchlist = .;
- *(.data..patch.rse)
- __end___rse_patchlist = .;
- }
-
- .data..patch.mckinley_e9 : AT(ADDR(.data..patch.mckinley_e9) - LOAD_OFFSET) {
- __start___mckinley_e9_bundles = .;
- *(.data..patch.mckinley_e9)
- __end___mckinley_e9_bundles = .;
- }
-
-#ifdef CONFIG_SMP
- . = ALIGN(PERCPU_PAGE_SIZE);
- __cpu0_per_cpu = .;
- . = . + PERCPU_PAGE_SIZE; /* cpu0 per-cpu space */
-#endif
-
- . = ALIGN(PAGE_SIZE);
- __init_end = .;
-
- .data..page_aligned : AT(ADDR(.data..page_aligned) - LOAD_OFFSET) {
- PAGE_ALIGNED_DATA(PAGE_SIZE)
- . = ALIGN(PAGE_SIZE);
- __start_gate_section = .;
- *(.data..gate)
- __stop_gate_section = .;
- }
- /*
- * make sure the gate page doesn't expose
- * kernel data
- */
- . = ALIGN(PAGE_SIZE);
-
- /* Per-cpu data: */
- . = ALIGN(PERCPU_PAGE_SIZE);
- PERCPU_VADDR(SMP_CACHE_BYTES, PERCPU_ADDR, :percpu)
- __phys_per_cpu_start = __per_cpu_load;
- /*
- * ensure percpu data fits
- * into percpu page size
- */
- . = __phys_per_cpu_start + PERCPU_PAGE_SIZE;
-
- data : {
- } :data
- .data : AT(ADDR(.data) - LOAD_OFFSET) {
- _sdata = .;
- INIT_TASK_DATA(PAGE_SIZE)
- CACHELINE_ALIGNED_DATA(SMP_CACHE_BYTES)
- READ_MOSTLY_DATA(SMP_CACHE_BYTES)
- DATA_DATA
- *(.data1)
- *(.gnu.linkonce.d*)
- CONSTRUCTORS
- }
-
- BUG_TABLE
-
- . = ALIGN(16); /* gp must be 16-byte aligned for exc. table */
- .got : AT(ADDR(.got) - LOAD_OFFSET) {
- *(.got.plt)
- *(.got)
- }
- __gp = ADDR(.got) + 0x200000;
-
- /*
- * We want the small data sections together,
- * so single-instruction offsets can access
- * them all, and initialized data all before
- * uninitialized, so we can shorten the
- * on-disk segment size.
- */
- .sdata : AT(ADDR(.sdata) - LOAD_OFFSET) {
- *(.sdata)
- *(.sdata1)
- *(.srdata)
- }
- _edata = .;
-
- BSS_SECTION(0, 0, 0)
-
- _end = .;
-
- code : {
- } :text
-
- STABS_DEBUG
- DWARF_DEBUG
- ELF_DETAILS
-
- /* Default discards */
- DISCARDS
-}
diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
deleted file mode 100644
index 081fcba01dc0..000000000000
--- a/arch/ia64/lib/Makefile
+++ /dev/null
@@ -1,48 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for ia64-specific library routines..
-#
-
-lib-y := io.o __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
- __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \
- checksum.o clear_page.o csum_partial_copy.o \
- clear_user.o strncpy_from_user.o strnlen_user.o \
- flush.o ip_fast_csum.o do_csum.o \
- memset.o strlen.o xor.o
-
-lib-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o
-lib-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o
-
-AFLAGS___divdi3.o =
-AFLAGS___udivdi3.o = -DUNSIGNED
-AFLAGS___moddi3.o = -DMODULO
-AFLAGS___umoddi3.o = -DUNSIGNED -DMODULO
-
-AFLAGS___divsi3.o =
-AFLAGS___udivsi3.o = -DUNSIGNED
-AFLAGS___modsi3.o = -DMODULO
-AFLAGS___umodsi3.o = -DUNSIGNED -DMODULO
-
-$(obj)/__divdi3.o: $(src)/idiv64.S FORCE
- $(call if_changed_rule,as_o_S)
-
-$(obj)/__udivdi3.o: $(src)/idiv64.S FORCE
- $(call if_changed_rule,as_o_S)
-
-$(obj)/__moddi3.o: $(src)/idiv64.S FORCE
- $(call if_changed_rule,as_o_S)
-
-$(obj)/__umoddi3.o: $(src)/idiv64.S FORCE
- $(call if_changed_rule,as_o_S)
-
-$(obj)/__divsi3.o: $(src)/idiv32.S FORCE
- $(call if_changed_rule,as_o_S)
-
-$(obj)/__udivsi3.o: $(src)/idiv32.S FORCE
- $(call if_changed_rule,as_o_S)
-
-$(obj)/__modsi3.o: $(src)/idiv32.S FORCE
- $(call if_changed_rule,as_o_S)
-
-$(obj)/__umodsi3.o: $(src)/idiv32.S FORCE
- $(call if_changed_rule,as_o_S)
diff --git a/arch/ia64/lib/checksum.c b/arch/ia64/lib/checksum.c
deleted file mode 100644
index d26517fe3500..000000000000
--- a/arch/ia64/lib/checksum.c
+++ /dev/null
@@ -1,102 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Network checksum routines
- *
- * Copyright (C) 1999, 2003 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- *
- * Most of the code coming from arch/alpha/lib/checksum.c
- *
- * This file contains network checksum routines that are better done
- * in an architecture-specific manner due to speed..
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-
-#include <asm/byteorder.h>
-
-static inline unsigned short
-from64to16 (unsigned long x)
-{
- /* add up 32-bit words for 33 bits */
- x = (x & 0xffffffff) + (x >> 32);
- /* add up 16-bit and 17-bit words for 17+c bits */
- x = (x & 0xffff) + (x >> 16);
- /* add up 16-bit and 2-bit for 16+c bit */
- x = (x & 0xffff) + (x >> 16);
- /* add up carry.. */
- x = (x & 0xffff) + (x >> 16);
- return x;
-}
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented.
- */
-__sum16
-csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len,
- __u8 proto, __wsum sum)
-{
- return (__force __sum16)~from64to16(
- (__force u64)saddr + (__force u64)daddr +
- (__force u64)sum + ((len + proto) << 8));
-}
-
-EXPORT_SYMBOL(csum_tcpudp_magic);
-
-__wsum
-csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len,
- __u8 proto, __wsum sum)
-{
- unsigned long result;
-
- result = (__force u64)saddr + (__force u64)daddr +
- (__force u64)sum + ((len + proto) << 8);
-
- /* Fold down to 32-bits so we don't lose in the typedef-less network stack. */
- /* 64 to 33 */
- result = (result & 0xffffffff) + (result >> 32);
- /* 33 to 32 */
- result = (result & 0xffffffff) + (result >> 32);
- return (__force __wsum)result;
-}
-EXPORT_SYMBOL(csum_tcpudp_nofold);
-
-extern unsigned long do_csum (const unsigned char *, long);
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum)
-{
- u64 result = do_csum(buff, len);
-
- /* add in old sum, and carry.. */
- result += (__force u32)sum;
- /* 32+c bits -> 32 bits */
- result = (result & 0xffffffff) + (result >> 32);
- return (__force __wsum)result;
-}
-
-EXPORT_SYMBOL(csum_partial);
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-__sum16 ip_compute_csum (const void *buff, int len)
-{
- return (__force __sum16)~do_csum(buff,len);
-}
-
-EXPORT_SYMBOL(ip_compute_csum);
diff --git a/arch/ia64/lib/clear_page.S b/arch/ia64/lib/clear_page.S
deleted file mode 100644
index ba0dd2538fa5..000000000000
--- a/arch/ia64/lib/clear_page.S
+++ /dev/null
@@ -1,79 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 1999-2002 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2002 Ken Chen <kenneth.w.chen@intel.com>
- *
- * 1/06/01 davidm Tuned for Itanium.
- * 2/12/02 kchen Tuned for both Itanium and McKinley
- * 3/08/02 davidm Some more tweaking
- */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-#include <asm/page.h>
-
-#ifdef CONFIG_ITANIUM
-# define L3_LINE_SIZE 64 // Itanium L3 line size
-# define PREFETCH_LINES 9 // magic number
-#else
-# define L3_LINE_SIZE 128 // McKinley L3 line size
-# define PREFETCH_LINES 12 // magic number
-#endif
-
-#define saved_lc r2
-#define dst_fetch r3
-#define dst1 r8
-#define dst2 r9
-#define dst3 r10
-#define dst4 r11
-
-#define dst_last r31
-
-GLOBAL_ENTRY(clear_page)
- .prologue
- .regstk 1,0,0,0
- mov r16 = PAGE_SIZE/L3_LINE_SIZE-1 // main loop count, -1=repeat/until
- .save ar.lc, saved_lc
- mov saved_lc = ar.lc
-
- .body
- mov ar.lc = (PREFETCH_LINES - 1)
- mov dst_fetch = in0
- adds dst1 = 16, in0
- adds dst2 = 32, in0
- ;;
-.fetch: stf.spill.nta [dst_fetch] = f0, L3_LINE_SIZE
- adds dst3 = 48, in0 // executing this multiple times is harmless
- br.cloop.sptk.few .fetch
- ;;
- addl dst_last = (PAGE_SIZE - PREFETCH_LINES*L3_LINE_SIZE), dst_fetch
- mov ar.lc = r16 // one L3 line per iteration
- adds dst4 = 64, in0
- ;;
-#ifdef CONFIG_ITANIUM
- // Optimized for Itanium
-1: stf.spill.nta [dst1] = f0, 64
- stf.spill.nta [dst2] = f0, 64
- cmp.lt p8,p0=dst_fetch, dst_last
- ;;
-#else
- // Optimized for McKinley
-1: stf.spill.nta [dst1] = f0, 64
- stf.spill.nta [dst2] = f0, 64
- stf.spill.nta [dst3] = f0, 64
- stf.spill.nta [dst4] = f0, 128
- cmp.lt p8,p0=dst_fetch, dst_last
- ;;
- stf.spill.nta [dst1] = f0, 64
- stf.spill.nta [dst2] = f0, 64
-#endif
- stf.spill.nta [dst3] = f0, 64
-(p8) stf.spill.nta [dst_fetch] = f0, L3_LINE_SIZE
- br.cloop.sptk.few 1b
- ;;
- mov ar.lc = saved_lc // restore lc
- br.ret.sptk.many rp
-END(clear_page)
-EXPORT_SYMBOL(clear_page)
diff --git a/arch/ia64/lib/clear_user.S b/arch/ia64/lib/clear_user.S
deleted file mode 100644
index 1d9e45ccf8e5..000000000000
--- a/arch/ia64/lib/clear_user.S
+++ /dev/null
@@ -1,212 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * This routine clears to zero a linear memory buffer in user space.
- *
- * Inputs:
- * in0: address of buffer
- * in1: length of buffer in bytes
- * Outputs:
- * r8: number of bytes that didn't get cleared due to a fault
- *
- * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-
-//
-// arguments
-//
-#define buf r32
-#define len r33
-
-//
-// local registers
-//
-#define cnt r16
-#define buf2 r17
-#define saved_lc r18
-#define saved_pfs r19
-#define tmp r20
-#define len2 r21
-#define len3 r22
-
-//
-// Theory of operations:
-// - we check whether or not the buffer is small, i.e., less than 17
-// in which case we do the byte by byte loop.
-//
-// - Otherwise we go progressively from 1 byte store to 8byte store in
-// the head part, the body is a 16byte store loop and we finish we the
-// tail for the last 15 bytes.
-// The good point about this breakdown is that the long buffer handling
-// contains only 2 branches.
-//
-// The reason for not using shifting & masking for both the head and the
-// tail is to stay semantically correct. This routine is not supposed
-// to write bytes outside of the buffer. While most of the time this would
-// be ok, we can't tolerate a mistake. A classical example is the case
-// of multithreaded code were to the extra bytes touched is actually owned
-// by another thread which runs concurrently to ours. Another, less likely,
-// example is with device drivers where reading an I/O mapped location may
-// have side effects (same thing for writing).
-//
-
-GLOBAL_ENTRY(__do_clear_user)
- .prologue
- .save ar.pfs, saved_pfs
- alloc saved_pfs=ar.pfs,2,0,0,0
- cmp.eq p6,p0=r0,len // check for zero length
- .save ar.lc, saved_lc
- mov saved_lc=ar.lc // preserve ar.lc (slow)
- .body
- ;; // avoid WAW on CFM
- adds tmp=-1,len // br.ctop is repeat/until
- mov ret0=len // return value is length at this point
-(p6) br.ret.spnt.many rp
- ;;
- cmp.lt p6,p0=16,len // if len > 16 then long memset
- mov ar.lc=tmp // initialize lc for small count
-(p6) br.cond.dptk .long_do_clear
- ;; // WAR on ar.lc
- //
- // worst case 16 iterations, avg 8 iterations
- //
- // We could have played with the predicates to use the extra
- // M slot for 2 stores/iteration but the cost the initialization
- // the various counters compared to how long the loop is supposed
- // to last on average does not make this solution viable.
- //
-1:
- EX( .Lexit1, st1 [buf]=r0,1 )
- adds len=-1,len // countdown length using len
- br.cloop.dptk 1b
- ;; // avoid RAW on ar.lc
- //
- // .Lexit4: comes from byte by byte loop
- // len contains bytes left
-.Lexit1:
- mov ret0=len // faster than using ar.lc
- mov ar.lc=saved_lc
- br.ret.sptk.many rp // end of short clear_user
-
-
- //
- // At this point we know we have more than 16 bytes to copy
- // so we focus on alignment (no branches required)
- //
- // The use of len/len2 for countdown of the number of bytes left
- // instead of ret0 is due to the fact that the exception code
- // changes the values of r8.
- //
-.long_do_clear:
- tbit.nz p6,p0=buf,0 // odd alignment (for long_do_clear)
- ;;
- EX( .Lexit3, (p6) st1 [buf]=r0,1 ) // 1-byte aligned
-(p6) adds len=-1,len;; // sync because buf is modified
- tbit.nz p6,p0=buf,1
- ;;
- EX( .Lexit3, (p6) st2 [buf]=r0,2 ) // 2-byte aligned
-(p6) adds len=-2,len;;
- tbit.nz p6,p0=buf,2
- ;;
- EX( .Lexit3, (p6) st4 [buf]=r0,4 ) // 4-byte aligned
-(p6) adds len=-4,len;;
- tbit.nz p6,p0=buf,3
- ;;
- EX( .Lexit3, (p6) st8 [buf]=r0,8 ) // 8-byte aligned
-(p6) adds len=-8,len;;
- shr.u cnt=len,4 // number of 128-bit (2x64bit) words
- ;;
- cmp.eq p6,p0=r0,cnt
- adds tmp=-1,cnt
-(p6) br.cond.dpnt .dotail // we have less than 16 bytes left
- ;;
- adds buf2=8,buf // setup second base pointer
- mov ar.lc=tmp
- ;;
-
- //
- // 16bytes/iteration core loop
- //
- // The second store can never generate a fault because
- // we come into the loop only when we are 16-byte aligned.
- // This means that if we cross a page then it will always be
- // in the first store and never in the second.
- //
- //
- // We need to keep track of the remaining length. A possible (optimistic)
- // way would be to use ar.lc and derive how many byte were left by
- // doing : left= 16*ar.lc + 16. this would avoid the addition at
- // every iteration.
- // However we need to keep the synchronization point. A template
- // M;;MB does not exist and thus we can keep the addition at no
- // extra cycle cost (use a nop slot anyway). It also simplifies the
- // (unlikely) error recovery code
- //
-
-2: EX(.Lexit3, st8 [buf]=r0,16 )
- ;; // needed to get len correct when error
- st8 [buf2]=r0,16
- adds len=-16,len
- br.cloop.dptk 2b
- ;;
- mov ar.lc=saved_lc
- //
- // tail correction based on len only
- //
- // We alternate the use of len3,len2 to allow parallelism and correct
- // error handling. We also reuse p6/p7 to return correct value.
- // The addition of len2/len3 does not cost anything more compared to
- // the regular memset as we had empty slots.
- //
-.dotail:
- mov len2=len // for parallelization of error handling
- mov len3=len
- tbit.nz p6,p0=len,3
- ;;
- EX( .Lexit2, (p6) st8 [buf]=r0,8 ) // at least 8 bytes
-(p6) adds len3=-8,len2
- tbit.nz p7,p6=len,2
- ;;
- EX( .Lexit2, (p7) st4 [buf]=r0,4 ) // at least 4 bytes
-(p7) adds len2=-4,len3
- tbit.nz p6,p7=len,1
- ;;
- EX( .Lexit2, (p6) st2 [buf]=r0,2 ) // at least 2 bytes
-(p6) adds len3=-2,len2
- tbit.nz p7,p6=len,0
- ;;
- EX( .Lexit2, (p7) st1 [buf]=r0 ) // only 1 byte left
- mov ret0=r0 // success
- br.ret.sptk.many rp // end of most likely path
-
- //
- // Outlined error handling code
- //
-
- //
- // .Lexit3: comes from core loop, need restore pr/lc
- // len contains bytes left
- //
- //
- // .Lexit2:
- // if p6 -> coming from st8 or st2 : len2 contains what's left
- // if p7 -> coming from st4 or st1 : len3 contains what's left
- // We must restore lc/pr even though might not have been used.
-.Lexit2:
- .pred.rel "mutex", p6, p7
-(p6) mov len=len2
-(p7) mov len=len3
- ;;
- //
- // .Lexit4: comes from head, need not restore pr/lc
- // len contains bytes left
- //
-.Lexit3:
- mov ret0=len
- mov ar.lc=saved_lc
- br.ret.sptk.many rp
-END(__do_clear_user)
-EXPORT_SYMBOL(__do_clear_user)
diff --git a/arch/ia64/lib/copy_page.S b/arch/ia64/lib/copy_page.S
deleted file mode 100644
index c0a0e6b2af00..000000000000
--- a/arch/ia64/lib/copy_page.S
+++ /dev/null
@@ -1,101 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *
- * Optimized version of the standard copy_page() function
- *
- * Inputs:
- * in0: address of target page
- * in1: address of source page
- * Output:
- * no return value
- *
- * Copyright (C) 1999, 2001 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- * David Mosberger <davidm@hpl.hp.com>
- *
- * 4/06/01 davidm Tuned to make it perform well both for cached and uncached copies.
- */
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-#include <asm/page.h>
-
-#define PIPE_DEPTH 3
-#define EPI p[PIPE_DEPTH-1]
-
-#define lcount r16
-#define saved_pr r17
-#define saved_lc r18
-#define saved_pfs r19
-#define src1 r20
-#define src2 r21
-#define tgt1 r22
-#define tgt2 r23
-#define srcf r24
-#define tgtf r25
-#define tgt_last r26
-
-#define Nrot ((8*PIPE_DEPTH+7)&~7)
-
-GLOBAL_ENTRY(copy_page)
- .prologue
- .save ar.pfs, saved_pfs
- alloc saved_pfs=ar.pfs,3,Nrot-3,0,Nrot
-
- .rotr t1[PIPE_DEPTH], t2[PIPE_DEPTH], t3[PIPE_DEPTH], t4[PIPE_DEPTH], \
- t5[PIPE_DEPTH], t6[PIPE_DEPTH], t7[PIPE_DEPTH], t8[PIPE_DEPTH]
- .rotp p[PIPE_DEPTH]
-
- .save ar.lc, saved_lc
- mov saved_lc=ar.lc
- mov ar.ec=PIPE_DEPTH
-
- mov lcount=PAGE_SIZE/64-1
- .save pr, saved_pr
- mov saved_pr=pr
- mov pr.rot=1<<16
-
- .body
-
- mov src1=in1
- adds src2=8,in1
- mov tgt_last = PAGE_SIZE
- ;;
- adds tgt2=8,in0
- add srcf=512,in1
- mov ar.lc=lcount
- mov tgt1=in0
- add tgtf=512,in0
- add tgt_last = tgt_last, in0
- ;;
-1:
-(p[0]) ld8 t1[0]=[src1],16
-(EPI) st8 [tgt1]=t1[PIPE_DEPTH-1],16
-(p[0]) ld8 t2[0]=[src2],16
-(EPI) st8 [tgt2]=t2[PIPE_DEPTH-1],16
- cmp.ltu p6,p0 = tgtf, tgt_last
- ;;
-(p[0]) ld8 t3[0]=[src1],16
-(EPI) st8 [tgt1]=t3[PIPE_DEPTH-1],16
-(p[0]) ld8 t4[0]=[src2],16
-(EPI) st8 [tgt2]=t4[PIPE_DEPTH-1],16
- ;;
-(p[0]) ld8 t5[0]=[src1],16
-(EPI) st8 [tgt1]=t5[PIPE_DEPTH-1],16
-(p[0]) ld8 t6[0]=[src2],16
-(EPI) st8 [tgt2]=t6[PIPE_DEPTH-1],16
- ;;
-(p[0]) ld8 t7[0]=[src1],16
-(EPI) st8 [tgt1]=t7[PIPE_DEPTH-1],16
-(p[0]) ld8 t8[0]=[src2],16
-(EPI) st8 [tgt2]=t8[PIPE_DEPTH-1],16
-
-(p6) lfetch [srcf], 64
-(p6) lfetch [tgtf], 64
- br.ctop.sptk.few 1b
- ;;
- mov pr=saved_pr,0xffffffffffff0000 // restore predicates
- mov ar.pfs=saved_pfs
- mov ar.lc=saved_lc
- br.ret.sptk.many rp
-END(copy_page)
-EXPORT_SYMBOL(copy_page)
diff --git a/arch/ia64/lib/copy_page_mck.S b/arch/ia64/lib/copy_page_mck.S
deleted file mode 100644
index 5e8bb4b4b535..000000000000
--- a/arch/ia64/lib/copy_page_mck.S
+++ /dev/null
@@ -1,188 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * McKinley-optimized version of copy_page().
- *
- * Copyright (C) 2002 Hewlett-Packard Co
- * David Mosberger <davidm@hpl.hp.com>
- *
- * Inputs:
- * in0: address of target page
- * in1: address of source page
- * Output:
- * no return value
- *
- * General idea:
- * - use regular loads and stores to prefetch data to avoid consuming M-slot just for
- * lfetches => good for in-cache performance
- * - avoid l2 bank-conflicts by not storing into the same 16-byte bank within a single
- * cycle
- *
- * Principle of operation:
- * First, note that L1 has a line-size of 64 bytes and L2 a line-size of 128 bytes.
- * To avoid secondary misses in L2, we prefetch both source and destination with a line-size
- * of 128 bytes. When both of these lines are in the L2 and the first half of the
- * source line is in L1, we start copying the remaining words. The second half of the
- * source line is prefetched in an earlier iteration, so that by the time we start
- * accessing it, it's also present in the L1.
- *
- * We use a software-pipelined loop to control the overall operation. The pipeline
- * has 2*PREFETCH_DIST+K stages. The first PREFETCH_DIST stages are used for prefetching
- * source cache-lines. The second PREFETCH_DIST stages are used for prefetching destination
- * cache-lines, the last K stages are used to copy the cache-line words not copied by
- * the prefetches. The four relevant points in the pipelined are called A, B, C, D:
- * p[A] is TRUE if a source-line should be prefetched, p[B] is TRUE if a destination-line
- * should be prefetched, p[C] is TRUE if the second half of an L2 line should be brought
- * into L1D and p[D] is TRUE if a cacheline needs to be copied.
- *
- * This all sounds very complicated, but thanks to the modulo-scheduled loop support,
- * the resulting code is very regular and quite easy to follow (once you get the idea).
- *
- * As a secondary optimization, the first 2*PREFETCH_DIST iterations are implemented
- * as the separate .prefetch_loop. Logically, this loop performs exactly like the
- * main-loop (.line_copy), but has all known-to-be-predicated-off instructions removed,
- * so that each loop iteration is faster (again, good for cached case).
- *
- * When reading the code, it helps to keep the following picture in mind:
- *
- * word 0 word 1
- * +------+------+---
- * | v[x] | t1 | ^
- * | t2 | t3 | |
- * | t4 | t5 | |
- * | t6 | t7 | | 128 bytes
- * | n[y] | t9 | | (L2 cache line)
- * | t10 | t11 | |
- * | t12 | t13 | |
- * | t14 | t15 | v
- * +------+------+---
- *
- * Here, v[x] is copied by the (memory) prefetch. n[y] is loaded at p[C]
- * to fetch the second-half of the L2 cache line into L1, and the tX words are copied in
- * an order that avoids bank conflicts.
- */
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-#include <asm/page.h>
-
-#define PREFETCH_DIST 8 // McKinley sustains 16 outstanding L2 misses (8 ld, 8 st)
-
-#define src0 r2
-#define src1 r3
-#define dst0 r9
-#define dst1 r10
-#define src_pre_mem r11
-#define dst_pre_mem r14
-#define src_pre_l2 r15
-#define dst_pre_l2 r16
-#define t1 r17
-#define t2 r18
-#define t3 r19
-#define t4 r20
-#define t5 t1 // alias!
-#define t6 t2 // alias!
-#define t7 t3 // alias!
-#define t9 t5 // alias!
-#define t10 t4 // alias!
-#define t11 t7 // alias!
-#define t12 t6 // alias!
-#define t14 t10 // alias!
-#define t13 r21
-#define t15 r22
-
-#define saved_lc r23
-#define saved_pr r24
-
-#define A 0
-#define B (PREFETCH_DIST)
-#define C (B + PREFETCH_DIST)
-#define D (C + 3)
-#define N (D + 1)
-#define Nrot ((N + 7) & ~7)
-
-GLOBAL_ENTRY(copy_page)
- .prologue
- alloc r8 = ar.pfs, 2, Nrot-2, 0, Nrot
-
- .rotr v[2*PREFETCH_DIST], n[D-C+1]
- .rotp p[N]
-
- .save ar.lc, saved_lc
- mov saved_lc = ar.lc
- .save pr, saved_pr
- mov saved_pr = pr
- .body
-
- mov src_pre_mem = in1
- mov pr.rot = 0x10000
- mov ar.ec = 1 // special unrolled loop
-
- mov dst_pre_mem = in0
- mov ar.lc = 2*PREFETCH_DIST - 1
-
- add src_pre_l2 = 8*8, in1
- add dst_pre_l2 = 8*8, in0
- add src0 = 8, in1 // first t1 src
- add src1 = 3*8, in1 // first t3 src
- add dst0 = 8, in0 // first t1 dst
- add dst1 = 3*8, in0 // first t3 dst
- mov t1 = (PAGE_SIZE/128) - (2*PREFETCH_DIST) - 1
- nop.m 0
- nop.i 0
- ;;
- // same as .line_copy loop, but with all predicated-off instructions removed:
-.prefetch_loop:
-(p[A]) ld8 v[A] = [src_pre_mem], 128 // M0
-(p[B]) st8 [dst_pre_mem] = v[B], 128 // M2
- br.ctop.sptk .prefetch_loop
- ;;
- cmp.eq p16, p0 = r0, r0 // reset p16 to 1 (br.ctop cleared it to zero)
- mov ar.lc = t1 // with 64KB pages, t1 is too big to fit in 8 bits!
- mov ar.ec = N // # of stages in pipeline
- ;;
-.line_copy:
-(p[D]) ld8 t2 = [src0], 3*8 // M0
-(p[D]) ld8 t4 = [src1], 3*8 // M1
-(p[B]) st8 [dst_pre_mem] = v[B], 128 // M2 prefetch dst from memory
-(p[D]) st8 [dst_pre_l2] = n[D-C], 128 // M3 prefetch dst from L2
- ;;
-(p[A]) ld8 v[A] = [src_pre_mem], 128 // M0 prefetch src from memory
-(p[C]) ld8 n[0] = [src_pre_l2], 128 // M1 prefetch src from L2
-(p[D]) st8 [dst0] = t1, 8 // M2
-(p[D]) st8 [dst1] = t3, 8 // M3
- ;;
-(p[D]) ld8 t5 = [src0], 8
-(p[D]) ld8 t7 = [src1], 3*8
-(p[D]) st8 [dst0] = t2, 3*8
-(p[D]) st8 [dst1] = t4, 3*8
- ;;
-(p[D]) ld8 t6 = [src0], 3*8
-(p[D]) ld8 t10 = [src1], 8
-(p[D]) st8 [dst0] = t5, 8
-(p[D]) st8 [dst1] = t7, 3*8
- ;;
-(p[D]) ld8 t9 = [src0], 3*8
-(p[D]) ld8 t11 = [src1], 3*8
-(p[D]) st8 [dst0] = t6, 3*8
-(p[D]) st8 [dst1] = t10, 8
- ;;
-(p[D]) ld8 t12 = [src0], 8
-(p[D]) ld8 t14 = [src1], 8
-(p[D]) st8 [dst0] = t9, 3*8
-(p[D]) st8 [dst1] = t11, 3*8
- ;;
-(p[D]) ld8 t13 = [src0], 4*8
-(p[D]) ld8 t15 = [src1], 4*8
-(p[D]) st8 [dst0] = t12, 8
-(p[D]) st8 [dst1] = t14, 8
- ;;
-(p[D-1])ld8 t1 = [src0], 8
-(p[D-1])ld8 t3 = [src1], 8
-(p[D]) st8 [dst0] = t13, 4*8
-(p[D]) st8 [dst1] = t15, 4*8
- br.ctop.sptk .line_copy
- ;;
- mov ar.lc = saved_lc
- mov pr = saved_pr, -1
- br.ret.sptk.many rp
-END(copy_page)
-EXPORT_SYMBOL(copy_page)
diff --git a/arch/ia64/lib/copy_user.S b/arch/ia64/lib/copy_user.S
deleted file mode 100644
index 8daab72cfe77..000000000000
--- a/arch/ia64/lib/copy_user.S
+++ /dev/null
@@ -1,613 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *
- * Optimized version of the copy_user() routine.
- * It is used to copy date across the kernel/user boundary.
- *
- * The source and destination are always on opposite side of
- * the boundary. When reading from user space we must catch
- * faults on loads. When writing to user space we must catch
- * errors on stores. Note that because of the nature of the copy
- * we don't need to worry about overlapping regions.
- *
- *
- * Inputs:
- * in0 address of source buffer
- * in1 address of destination buffer
- * in2 number of bytes to copy
- *
- * Outputs:
- * ret0 0 in case of success. The number of bytes NOT copied in
- * case of error.
- *
- * Copyright (C) 2000-2001 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- *
- * Fixme:
- * - handle the case where we have more than 16 bytes and the alignment
- * are different.
- * - more benchmarking
- * - fix extraneous stop bit introduced by the EX() macro.
- */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-
-//
-// Tuneable parameters
-//
-#define COPY_BREAK 16 // we do byte copy below (must be >=16)
-#define PIPE_DEPTH 21 // pipe depth
-
-#define EPI p[PIPE_DEPTH-1]
-
-//
-// arguments
-//
-#define dst in0
-#define src in1
-#define len in2
-
-//
-// local registers
-//
-#define t1 r2 // rshift in bytes
-#define t2 r3 // lshift in bytes
-#define rshift r14 // right shift in bits
-#define lshift r15 // left shift in bits
-#define word1 r16
-#define word2 r17
-#define cnt r18
-#define len2 r19
-#define saved_lc r20
-#define saved_pr r21
-#define tmp r22
-#define val r23
-#define src1 r24
-#define dst1 r25
-#define src2 r26
-#define dst2 r27
-#define len1 r28
-#define enddst r29
-#define endsrc r30
-#define saved_pfs r31
-
-GLOBAL_ENTRY(__copy_user)
- .prologue
- .save ar.pfs, saved_pfs
- alloc saved_pfs=ar.pfs,3,((2*PIPE_DEPTH+7)&~7),0,((2*PIPE_DEPTH+7)&~7)
-
- .rotr val1[PIPE_DEPTH],val2[PIPE_DEPTH]
- .rotp p[PIPE_DEPTH]
-
- adds len2=-1,len // br.ctop is repeat/until
- mov ret0=r0
-
- ;; // RAW of cfm when len=0
- cmp.eq p8,p0=r0,len // check for zero length
- .save ar.lc, saved_lc
- mov saved_lc=ar.lc // preserve ar.lc (slow)
-(p8) br.ret.spnt.many rp // empty mempcy()
- ;;
- add enddst=dst,len // first byte after end of source
- add endsrc=src,len // first byte after end of destination
- .save pr, saved_pr
- mov saved_pr=pr // preserve predicates
-
- .body
-
- mov dst1=dst // copy because of rotation
- mov ar.ec=PIPE_DEPTH
- mov pr.rot=1<<16 // p16=true all others are false
-
- mov src1=src // copy because of rotation
- mov ar.lc=len2 // initialize lc for small count
- cmp.lt p10,p7=COPY_BREAK,len // if len > COPY_BREAK then long copy
-
- xor tmp=src,dst // same alignment test prepare
-(p10) br.cond.dptk .long_copy_user
- ;; // RAW pr.rot/p16 ?
- //
- // Now we do the byte by byte loop with software pipeline
- //
- // p7 is necessarily false by now
-1:
- EX(.failure_in_pipe1,(p16) ld1 val1[0]=[src1],1)
- EX(.failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
- br.ctop.dptk.few 1b
- ;;
- mov ar.lc=saved_lc
- mov pr=saved_pr,0xffffffffffff0000
- mov ar.pfs=saved_pfs // restore ar.ec
- br.ret.sptk.many rp // end of short memcpy
-
- //
- // Not 8-byte aligned
- //
-.diff_align_copy_user:
- // At this point we know we have more than 16 bytes to copy
- // and also that src and dest do _not_ have the same alignment.
- and src2=0x7,src1 // src offset
- and dst2=0x7,dst1 // dst offset
- ;;
- // The basic idea is that we copy byte-by-byte at the head so
- // that we can reach 8-byte alignment for both src1 and dst1.
- // Then copy the body using software pipelined 8-byte copy,
- // shifting the two back-to-back words right and left, then copy
- // the tail by copying byte-by-byte.
- //
- // Fault handling. If the byte-by-byte at the head fails on the
- // load, then restart and finish the pipleline by copying zeros
- // to the dst1. Then copy zeros for the rest of dst1.
- // If 8-byte software pipeline fails on the load, do the same as
- // failure_in3 does. If the byte-by-byte at the tail fails, it is
- // handled simply by failure_in_pipe1.
- //
- // The case p14 represents the source has more bytes in the
- // the first word (by the shifted part), whereas the p15 needs to
- // copy some bytes from the 2nd word of the source that has the
- // tail of the 1st of the destination.
- //
-
- //
- // Optimization. If dst1 is 8-byte aligned (quite common), we don't need
- // to copy the head to dst1, to start 8-byte copy software pipeline.
- // We know src1 is not 8-byte aligned in this case.
- //
- cmp.eq p14,p15=r0,dst2
-(p15) br.cond.spnt 1f
- ;;
- sub t1=8,src2
- mov t2=src2
- ;;
- shl rshift=t2,3
- sub len1=len,t1 // set len1
- ;;
- sub lshift=64,rshift
- ;;
- br.cond.spnt .word_copy_user
- ;;
-1:
- cmp.leu p14,p15=src2,dst2
- sub t1=dst2,src2
- ;;
- .pred.rel "mutex", p14, p15
-(p14) sub word1=8,src2 // (8 - src offset)
-(p15) sub t1=r0,t1 // absolute value
-(p15) sub word1=8,dst2 // (8 - dst offset)
- ;;
- // For the case p14, we don't need to copy the shifted part to
- // the 1st word of destination.
- sub t2=8,t1
-(p14) sub word1=word1,t1
- ;;
- sub len1=len,word1 // resulting len
-(p15) shl rshift=t1,3 // in bits
-(p14) shl rshift=t2,3
- ;;
-(p14) sub len1=len1,t1
- adds cnt=-1,word1
- ;;
- sub lshift=64,rshift
- mov ar.ec=PIPE_DEPTH
- mov pr.rot=1<<16 // p16=true all others are false
- mov ar.lc=cnt
- ;;
-2:
- EX(.failure_in_pipe2,(p16) ld1 val1[0]=[src1],1)
- EX(.failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
- br.ctop.dptk.few 2b
- ;;
- clrrrb
- ;;
-.word_copy_user:
- cmp.gtu p9,p0=16,len1
-(p9) br.cond.spnt 4f // if (16 > len1) skip 8-byte copy
- ;;
- shr.u cnt=len1,3 // number of 64-bit words
- ;;
- adds cnt=-1,cnt
- ;;
- .pred.rel "mutex", p14, p15
-(p14) sub src1=src1,t2
-(p15) sub src1=src1,t1
- //
- // Now both src1 and dst1 point to an 8-byte aligned address. And
- // we have more than 8 bytes to copy.
- //
- mov ar.lc=cnt
- mov ar.ec=PIPE_DEPTH
- mov pr.rot=1<<16 // p16=true all others are false
- ;;
-3:
- //
- // The pipleline consists of 3 stages:
- // 1 (p16): Load a word from src1
- // 2 (EPI_1): Shift right pair, saving to tmp
- // 3 (EPI): Store tmp to dst1
- //
- // To make it simple, use at least 2 (p16) loops to set up val1[n]
- // because we need 2 back-to-back val1[] to get tmp.
- // Note that this implies EPI_2 must be p18 or greater.
- //
-
-#define EPI_1 p[PIPE_DEPTH-2]
-#define SWITCH(pred, shift) cmp.eq pred,p0=shift,rshift
-#define CASE(pred, shift) \
- (pred) br.cond.spnt .copy_user_bit##shift
-#define BODY(rshift) \
-.copy_user_bit##rshift: \
-1: \
- EX(.failure_out,(EPI) st8 [dst1]=tmp,8); \
-(EPI_1) shrp tmp=val1[PIPE_DEPTH-2],val1[PIPE_DEPTH-1],rshift; \
- EX(3f,(p16) ld8 val1[1]=[src1],8); \
-(p16) mov val1[0]=r0; \
- br.ctop.dptk 1b; \
- ;; \
- br.cond.sptk.many .diff_align_do_tail; \
-2: \
-(EPI) st8 [dst1]=tmp,8; \
-(EPI_1) shrp tmp=val1[PIPE_DEPTH-2],val1[PIPE_DEPTH-1],rshift; \
-3: \
-(p16) mov val1[1]=r0; \
-(p16) mov val1[0]=r0; \
- br.ctop.dptk 2b; \
- ;; \
- br.cond.sptk.many .failure_in2
-
- //
- // Since the instruction 'shrp' requires a fixed 128-bit value
- // specifying the bits to shift, we need to provide 7 cases
- // below.
- //
- SWITCH(p6, 8)
- SWITCH(p7, 16)
- SWITCH(p8, 24)
- SWITCH(p9, 32)
- SWITCH(p10, 40)
- SWITCH(p11, 48)
- SWITCH(p12, 56)
- ;;
- CASE(p6, 8)
- CASE(p7, 16)
- CASE(p8, 24)
- CASE(p9, 32)
- CASE(p10, 40)
- CASE(p11, 48)
- CASE(p12, 56)
- ;;
- BODY(8)
- BODY(16)
- BODY(24)
- BODY(32)
- BODY(40)
- BODY(48)
- BODY(56)
- ;;
-.diff_align_do_tail:
- .pred.rel "mutex", p14, p15
-(p14) sub src1=src1,t1
-(p14) adds dst1=-8,dst1
-(p15) sub dst1=dst1,t1
- ;;
-4:
- // Tail correction.
- //
- // The problem with this piplelined loop is that the last word is not
- // loaded and thus parf of the last word written is not correct.
- // To fix that, we simply copy the tail byte by byte.
-
- sub len1=endsrc,src1,1
- clrrrb
- ;;
- mov ar.ec=PIPE_DEPTH
- mov pr.rot=1<<16 // p16=true all others are false
- mov ar.lc=len1
- ;;
-5:
- EX(.failure_in_pipe1,(p16) ld1 val1[0]=[src1],1)
- EX(.failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
- br.ctop.dptk.few 5b
- ;;
- mov ar.lc=saved_lc
- mov pr=saved_pr,0xffffffffffff0000
- mov ar.pfs=saved_pfs
- br.ret.sptk.many rp
-
- //
- // Beginning of long mempcy (i.e. > 16 bytes)
- //
-.long_copy_user:
- tbit.nz p6,p7=src1,0 // odd alignment
- and tmp=7,tmp
- ;;
- cmp.eq p10,p8=r0,tmp
- mov len1=len // copy because of rotation
-(p8) br.cond.dpnt .diff_align_copy_user
- ;;
- // At this point we know we have more than 16 bytes to copy
- // and also that both src and dest have the same alignment
- // which may not be the one we want. So for now we must move
- // forward slowly until we reach 16byte alignment: no need to
- // worry about reaching the end of buffer.
- //
- EX(.failure_in1,(p6) ld1 val1[0]=[src1],1) // 1-byte aligned
-(p6) adds len1=-1,len1;;
- tbit.nz p7,p0=src1,1
- ;;
- EX(.failure_in1,(p7) ld2 val1[1]=[src1],2) // 2-byte aligned
-(p7) adds len1=-2,len1;;
- tbit.nz p8,p0=src1,2
- ;;
- //
- // Stop bit not required after ld4 because if we fail on ld4
- // we have never executed the ld1, therefore st1 is not executed.
- //
- EX(.failure_in1,(p8) ld4 val2[0]=[src1],4) // 4-byte aligned
- ;;
- EX(.failure_out,(p6) st1 [dst1]=val1[0],1)
- tbit.nz p9,p0=src1,3
- ;;
- //
- // Stop bit not required after ld8 because if we fail on ld8
- // we have never executed the ld2, therefore st2 is not executed.
- //
- EX(.failure_in1,(p9) ld8 val2[1]=[src1],8) // 8-byte aligned
- EX(.failure_out,(p7) st2 [dst1]=val1[1],2)
-(p8) adds len1=-4,len1
- ;;
- EX(.failure_out, (p8) st4 [dst1]=val2[0],4)
-(p9) adds len1=-8,len1;;
- shr.u cnt=len1,4 // number of 128-bit (2x64bit) words
- ;;
- EX(.failure_out, (p9) st8 [dst1]=val2[1],8)
- tbit.nz p6,p0=len1,3
- cmp.eq p7,p0=r0,cnt
- adds tmp=-1,cnt // br.ctop is repeat/until
-(p7) br.cond.dpnt .dotail // we have less than 16 bytes left
- ;;
- adds src2=8,src1
- adds dst2=8,dst1
- mov ar.lc=tmp
- ;;
- //
- // 16bytes/iteration
- //
-2:
- EX(.failure_in3,(p16) ld8 val1[0]=[src1],16)
-(p16) ld8 val2[0]=[src2],16
-
- EX(.failure_out, (EPI) st8 [dst1]=val1[PIPE_DEPTH-1],16)
-(EPI) st8 [dst2]=val2[PIPE_DEPTH-1],16
- br.ctop.dptk 2b
- ;; // RAW on src1 when fall through from loop
- //
- // Tail correction based on len only
- //
- // No matter where we come from (loop or test) the src1 pointer
- // is 16 byte aligned AND we have less than 16 bytes to copy.
- //
-.dotail:
- EX(.failure_in1,(p6) ld8 val1[0]=[src1],8) // at least 8 bytes
- tbit.nz p7,p0=len1,2
- ;;
- EX(.failure_in1,(p7) ld4 val1[1]=[src1],4) // at least 4 bytes
- tbit.nz p8,p0=len1,1
- ;;
- EX(.failure_in1,(p8) ld2 val2[0]=[src1],2) // at least 2 bytes
- tbit.nz p9,p0=len1,0
- ;;
- EX(.failure_out, (p6) st8 [dst1]=val1[0],8)
- ;;
- EX(.failure_in1,(p9) ld1 val2[1]=[src1]) // only 1 byte left
- mov ar.lc=saved_lc
- ;;
- EX(.failure_out,(p7) st4 [dst1]=val1[1],4)
- mov pr=saved_pr,0xffffffffffff0000
- ;;
- EX(.failure_out, (p8) st2 [dst1]=val2[0],2)
- mov ar.pfs=saved_pfs
- ;;
- EX(.failure_out, (p9) st1 [dst1]=val2[1])
- br.ret.sptk.many rp
-
-
- //
- // Here we handle the case where the byte by byte copy fails
- // on the load.
- // Several factors make the zeroing of the rest of the buffer kind of
- // tricky:
- // - the pipeline: loads/stores are not in sync (pipeline)
- //
- // In the same loop iteration, the dst1 pointer does not directly
- // reflect where the faulty load was.
- //
- // - pipeline effect
- // When you get a fault on load, you may have valid data from
- // previous loads not yet store in transit. Such data must be
- // store normally before moving onto zeroing the rest.
- //
- // - single/multi dispersal independence.
- //
- // solution:
- // - we don't disrupt the pipeline, i.e. data in transit in
- // the software pipeline will be eventually move to memory.
- // We simply replace the load with a simple mov and keep the
- // pipeline going. We can't really do this inline because
- // p16 is always reset to 1 when lc > 0.
- //
-.failure_in_pipe1:
- sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
-1:
-(p16) mov val1[0]=r0
-(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1
- br.ctop.dptk 1b
- ;;
- mov pr=saved_pr,0xffffffffffff0000
- mov ar.lc=saved_lc
- mov ar.pfs=saved_pfs
- br.ret.sptk.many rp
-
- //
- // This is the case where the byte by byte copy fails on the load
- // when we copy the head. We need to finish the pipeline and copy
- // zeros for the rest of the destination. Since this happens
- // at the top we still need to fill the body and tail.
-.failure_in_pipe2:
- sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
-2:
-(p16) mov val1[0]=r0
-(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1
- br.ctop.dptk 2b
- ;;
- sub len=enddst,dst1,1 // precompute len
- br.cond.dptk.many .failure_in1bis
- ;;
-
- //
- // Here we handle the head & tail part when we check for alignment.
- // The following code handles only the load failures. The
- // main diffculty comes from the fact that loads/stores are
- // scheduled. So when you fail on a load, the stores corresponding
- // to previous successful loads must be executed.
- //
- // However some simplifications are possible given the way
- // things work.
- //
- // 1) HEAD
- // Theory of operation:
- //
- // Page A | Page B
- // ---------|-----
- // 1|8 x
- // 1 2|8 x
- // 4|8 x
- // 1 4|8 x
- // 2 4|8 x
- // 1 2 4|8 x
- // |1
- // |2 x
- // |4 x
- //
- // page_size >= 4k (2^12). (x means 4, 2, 1)
- // Here we suppose Page A exists and Page B does not.
- //
- // As we move towards eight byte alignment we may encounter faults.
- // The numbers on each page show the size of the load (current alignment).
- //
- // Key point:
- // - if you fail on 1, 2, 4 then you have never executed any smaller
- // size loads, e.g. failing ld4 means no ld1 nor ld2 executed
- // before.
- //
- // This allows us to simplify the cleanup code, because basically you
- // only have to worry about "pending" stores in the case of a failing
- // ld8(). Given the way the code is written today, this means only
- // worry about st2, st4. There we can use the information encapsulated
- // into the predicates.
- //
- // Other key point:
- // - if you fail on the ld8 in the head, it means you went straight
- // to it, i.e. 8byte alignment within an unexisting page.
- // Again this comes from the fact that if you crossed just for the ld8 then
- // you are 8byte aligned but also 16byte align, therefore you would
- // either go for the 16byte copy loop OR the ld8 in the tail part.
- // The combination ld1, ld2, ld4, ld8 where you fail on ld8 is impossible
- // because it would mean you had 15bytes to copy in which case you
- // would have defaulted to the byte by byte copy.
- //
- //
- // 2) TAIL
- // Here we now we have less than 16 bytes AND we are either 8 or 16 byte
- // aligned.
- //
- // Key point:
- // This means that we either:
- // - are right on a page boundary
- // OR
- // - are at more than 16 bytes from a page boundary with
- // at most 15 bytes to copy: no chance of crossing.
- //
- // This allows us to assume that if we fail on a load we haven't possibly
- // executed any of the previous (tail) ones, so we don't need to do
- // any stores. For instance, if we fail on ld2, this means we had
- // 2 or 3 bytes left to copy and we did not execute the ld8 nor ld4.
- //
- // This means that we are in a situation similar the a fault in the
- // head part. That's nice!
- //
-.failure_in1:
- sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
- sub len=endsrc,src1,1
- //
- // we know that ret0 can never be zero at this point
- // because we failed why trying to do a load, i.e. there is still
- // some work to do.
- // The failure_in1bis and length problem is taken care of at the
- // calling side.
- //
- ;;
-.failure_in1bis: // from (.failure_in3)
- mov ar.lc=len // Continue with a stupid byte store.
- ;;
-5:
- st1 [dst1]=r0,1
- br.cloop.dptk 5b
- ;;
- mov pr=saved_pr,0xffffffffffff0000
- mov ar.lc=saved_lc
- mov ar.pfs=saved_pfs
- br.ret.sptk.many rp
-
- //
- // Here we simply restart the loop but instead
- // of doing loads we fill the pipeline with zeroes
- // We can't simply store r0 because we may have valid
- // data in transit in the pipeline.
- // ar.lc and ar.ec are setup correctly at this point
- //
- // we MUST use src1/endsrc here and not dst1/enddst because
- // of the pipeline effect.
- //
-.failure_in3:
- sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
- ;;
-2:
-(p16) mov val1[0]=r0
-(p16) mov val2[0]=r0
-(EPI) st8 [dst1]=val1[PIPE_DEPTH-1],16
-(EPI) st8 [dst2]=val2[PIPE_DEPTH-1],16
- br.ctop.dptk 2b
- ;;
- cmp.ne p6,p0=dst1,enddst // Do we need to finish the tail ?
- sub len=enddst,dst1,1 // precompute len
-(p6) br.cond.dptk .failure_in1bis
- ;;
- mov pr=saved_pr,0xffffffffffff0000
- mov ar.lc=saved_lc
- mov ar.pfs=saved_pfs
- br.ret.sptk.many rp
-
-.failure_in2:
- sub ret0=endsrc,src1
- cmp.ne p6,p0=dst1,enddst // Do we need to finish the tail ?
- sub len=enddst,dst1,1 // precompute len
-(p6) br.cond.dptk .failure_in1bis
- ;;
- mov pr=saved_pr,0xffffffffffff0000
- mov ar.lc=saved_lc
- mov ar.pfs=saved_pfs
- br.ret.sptk.many rp
-
- //
- // handling of failures on stores: that's the easy part
- //
-.failure_out:
- sub ret0=enddst,dst1
- mov pr=saved_pr,0xffffffffffff0000
- mov ar.lc=saved_lc
-
- mov ar.pfs=saved_pfs
- br.ret.sptk.many rp
-END(__copy_user)
-EXPORT_SYMBOL(__copy_user)
diff --git a/arch/ia64/lib/csum_partial_copy.c b/arch/ia64/lib/csum_partial_copy.c
deleted file mode 100644
index 917e3138b277..000000000000
--- a/arch/ia64/lib/csum_partial_copy.c
+++ /dev/null
@@ -1,98 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Network Checksum & Copy routine
- *
- * Copyright (C) 1999, 2003-2004 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- *
- * Most of the code has been imported from Linux/Alpha
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/string.h>
-
-#include <net/checksum.h>
-
-/*
- * XXX Fixme: those 2 inlines are meant for debugging and will go away
- */
-static inline unsigned
-short from64to16(unsigned long x)
-{
- /* add up 32-bit words for 33 bits */
- x = (x & 0xffffffff) + (x >> 32);
- /* add up 16-bit and 17-bit words for 17+c bits */
- x = (x & 0xffff) + (x >> 16);
- /* add up 16-bit and 2-bit for 16+c bit */
- x = (x & 0xffff) + (x >> 16);
- /* add up carry.. */
- x = (x & 0xffff) + (x >> 16);
- return x;
-}
-
-static inline
-unsigned long do_csum_c(const unsigned char * buff, int len, unsigned int psum)
-{
- int odd, count;
- unsigned long result = (unsigned long)psum;
-
- if (len <= 0)
- goto out;
- odd = 1 & (unsigned long) buff;
- if (odd) {
- result = *buff << 8;
- len--;
- buff++;
- }
- count = len >> 1; /* nr of 16-bit words.. */
- if (count) {
- if (2 & (unsigned long) buff) {
- result += *(unsigned short *) buff;
- count--;
- len -= 2;
- buff += 2;
- }
- count >>= 1; /* nr of 32-bit words.. */
- if (count) {
- if (4 & (unsigned long) buff) {
- result += *(unsigned int *) buff;
- count--;
- len -= 4;
- buff += 4;
- }
- count >>= 1; /* nr of 64-bit words.. */
- if (count) {
- unsigned long carry = 0;
- do {
- unsigned long w = *(unsigned long *) buff;
- count--;
- buff += 8;
- result += carry;
- result += w;
- carry = (w > result);
- } while (count);
- result += carry;
- result = (result & 0xffffffff) + (result >> 32);
- }
- if (len & 4) {
- result += *(unsigned int *) buff;
- buff += 4;
- }
- }
- if (len & 2) {
- result += *(unsigned short *) buff;
- buff += 2;
- }
- }
- if (len & 1)
- result += *buff;
-
- result = from64to16(result);
-
- if (odd)
- result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
-
-out:
- return result;
-}
diff --git a/arch/ia64/lib/do_csum.S b/arch/ia64/lib/do_csum.S
deleted file mode 100644
index 6004dad2597c..000000000000
--- a/arch/ia64/lib/do_csum.S
+++ /dev/null
@@ -1,324 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *
- * Optmized version of the standard do_csum() function
- *
- * Return: a 64bit quantity containing the 16bit Internet checksum
- *
- * Inputs:
- * in0: address of buffer to checksum (char *)
- * in1: length of the buffer (int)
- *
- * Copyright (C) 1999, 2001-2002 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- *
- * 02/04/22 Ken Chen <kenneth.w.chen@intel.com>
- * Data locality study on the checksum buffer.
- * More optimization cleanup - remove excessive stop bits.
- * 02/04/08 David Mosberger <davidm@hpl.hp.com>
- * More cleanup and tuning.
- * 01/04/18 Jun Nakajima <jun.nakajima@intel.com>
- * Clean up and optimize and the software pipeline, loading two
- * back-to-back 8-byte words per loop. Clean up the initialization
- * for the loop. Support the cases where load latency = 1 or 2.
- * Set CONFIG_IA64_LOAD_LATENCY to 1 or 2 (default).
- */
-
-#include <asm/asmmacro.h>
-
-//
-// Theory of operations:
-// The goal is to go as quickly as possible to the point where
-// we can checksum 16 bytes/loop. Before reaching that point we must
-// take care of incorrect alignment of first byte.
-//
-// The code hereafter also takes care of the "tail" part of the buffer
-// before entering the core loop, if any. The checksum is a sum so it
-// allows us to commute operations. So we do the "head" and "tail"
-// first to finish at full speed in the body. Once we get the head and
-// tail values, we feed them into the pipeline, very handy initialization.
-//
-// Of course we deal with the special case where the whole buffer fits
-// into one 8 byte word. In this case we have only one entry in the pipeline.
-//
-// We use a (LOAD_LATENCY+2)-stage pipeline in the loop to account for
-// possible load latency and also to accommodate for head and tail.
-//
-// The end of the function deals with folding the checksum from 64bits
-// down to 16bits taking care of the carry.
-//
-// This version avoids synchronization in the core loop by also using a
-// pipeline for the accumulation of the checksum in resultx[] (x=1,2).
-//
-// wordx[] (x=1,2)
-// |---|
-// | | 0 : new value loaded in pipeline
-// |---|
-// | | - : in transit data
-// |---|
-// | | LOAD_LATENCY : current value to add to checksum
-// |---|
-// | | LOAD_LATENCY+1 : previous value added to checksum
-// |---| (previous iteration)
-//
-// resultx[] (x=1,2)
-// |---|
-// | | 0 : initial value
-// |---|
-// | | LOAD_LATENCY-1 : new checksum
-// |---|
-// | | LOAD_LATENCY : previous value of checksum
-// |---|
-// | | LOAD_LATENCY+1 : final checksum when out of the loop
-// |---|
-//
-//
-// See RFC1071 "Computing the Internet Checksum" for various techniques for
-// calculating the Internet checksum.
-//
-// NOT YET DONE:
-// - Maybe another algorithm which would take care of the folding at the
-// end in a different manner
-// - Work with people more knowledgeable than me on the network stack
-// to figure out if we could not split the function depending on the
-// type of packet or alignment we get. Like the ip_fast_csum() routine
-// where we know we have at least 20bytes worth of data to checksum.
-// - Do a better job of handling small packets.
-// - Note on prefetching: it was found that under various load, i.e. ftp read/write,
-// nfs read/write, the L1 cache hit rate is at 60% and L2 cache hit rate is at 99.8%
-// on the data that buffer points to (partly because the checksum is often preceded by
-// a copy_from_user()). This finding indiate that lfetch will not be beneficial since
-// the data is already in the cache.
-//
-
-#define saved_pfs r11
-#define hmask r16
-#define tmask r17
-#define first1 r18
-#define firstval r19
-#define firstoff r20
-#define last r21
-#define lastval r22
-#define lastoff r23
-#define saved_lc r24
-#define saved_pr r25
-#define tmp1 r26
-#define tmp2 r27
-#define tmp3 r28
-#define carry1 r29
-#define carry2 r30
-#define first2 r31
-
-#define buf in0
-#define len in1
-
-#define LOAD_LATENCY 2 // XXX fix me
-
-#if (LOAD_LATENCY != 1) && (LOAD_LATENCY != 2)
-# error "Only 1 or 2 is supported/tested for LOAD_LATENCY."
-#endif
-
-#define PIPE_DEPTH (LOAD_LATENCY+2)
-#define ELD p[LOAD_LATENCY] // end of load
-#define ELD_1 p[LOAD_LATENCY+1] // and next stage
-
-// unsigned long do_csum(unsigned char *buf,long len)
-
-GLOBAL_ENTRY(do_csum)
- .prologue
- .save ar.pfs, saved_pfs
- alloc saved_pfs=ar.pfs,2,16,0,16
- .rotr word1[4], word2[4],result1[LOAD_LATENCY+2],result2[LOAD_LATENCY+2]
- .rotp p[PIPE_DEPTH], pC1[2], pC2[2]
- mov ret0=r0 // in case we have zero length
- cmp.lt p0,p6=r0,len // check for zero length or negative (32bit len)
- ;;
- add tmp1=buf,len // last byte's address
- .save pr, saved_pr
- mov saved_pr=pr // preserve predicates (rotation)
-(p6) br.ret.spnt.many rp // return if zero or negative length
-
- mov hmask=-1 // initialize head mask
- tbit.nz p15,p0=buf,0 // is buf an odd address?
- and first1=-8,buf // 8-byte align down address of first1 element
-
- and firstoff=7,buf // how many bytes off for first1 element
- mov tmask=-1 // initialize tail mask
-
- ;;
- adds tmp2=-1,tmp1 // last-1
- and lastoff=7,tmp1 // how many bytes off for last element
- ;;
- sub tmp1=8,lastoff // complement to lastoff
- and last=-8,tmp2 // address of word containing last byte
- ;;
- sub tmp3=last,first1 // tmp3=distance from first1 to last
- .save ar.lc, saved_lc
- mov saved_lc=ar.lc // save lc
- cmp.eq p8,p9=last,first1 // everything fits in one word ?
-
- ld8 firstval=[first1],8 // load, ahead of time, "first1" word
- and tmp1=7, tmp1 // make sure that if tmp1==8 -> tmp1=0
- shl tmp2=firstoff,3 // number of bits
- ;;
-(p9) ld8 lastval=[last] // load, ahead of time, "last" word, if needed
- shl tmp1=tmp1,3 // number of bits
-(p9) adds tmp3=-8,tmp3 // effectively loaded
- ;;
-(p8) mov lastval=r0 // we don't need lastval if first1==last
- shl hmask=hmask,tmp2 // build head mask, mask off [0,first1off[
- shr.u tmask=tmask,tmp1 // build tail mask, mask off ]8,lastoff]
- ;;
- .body
-#define count tmp3
-
-(p8) and hmask=hmask,tmask // apply tail mask to head mask if 1 word only
-(p9) and word2[0]=lastval,tmask // mask last it as appropriate
- shr.u count=count,3 // how many 8-byte?
- ;;
- // If count is odd, finish this 8-byte word so that we can
- // load two back-to-back 8-byte words per loop thereafter.
- and word1[0]=firstval,hmask // and mask it as appropriate
- tbit.nz p10,p11=count,0 // if (count is odd)
- ;;
-(p8) mov result1[0]=word1[0]
-(p9) add result1[0]=word1[0],word2[0]
- ;;
- cmp.ltu p6,p0=result1[0],word1[0] // check the carry
- cmp.eq.or.andcm p8,p0=0,count // exit if zero 8-byte
- ;;
-(p6) adds result1[0]=1,result1[0]
-(p8) br.cond.dptk .do_csum_exit // if (within an 8-byte word)
-(p11) br.cond.dptk .do_csum16 // if (count is even)
-
- // Here count is odd.
- ld8 word1[1]=[first1],8 // load an 8-byte word
- cmp.eq p9,p10=1,count // if (count == 1)
- adds count=-1,count // loaded an 8-byte word
- ;;
- add result1[0]=result1[0],word1[1]
- ;;
- cmp.ltu p6,p0=result1[0],word1[1]
- ;;
-(p6) adds result1[0]=1,result1[0]
-(p9) br.cond.sptk .do_csum_exit // if (count == 1) exit
- // Fall through to calculate the checksum, feeding result1[0] as
- // the initial value in result1[0].
- //
- // Calculate the checksum loading two 8-byte words per loop.
- //
-.do_csum16:
- add first2=8,first1
- shr.u count=count,1 // we do 16 bytes per loop
- ;;
- adds count=-1,count
- mov carry1=r0
- mov carry2=r0
- brp.loop.imp 1f,2f
- ;;
- mov ar.ec=PIPE_DEPTH
- mov ar.lc=count // set lc
- mov pr.rot=1<<16
- // result1[0] must be initialized in advance.
- mov result2[0]=r0
- ;;
- .align 32
-1:
-(ELD_1) cmp.ltu pC1[0],p0=result1[LOAD_LATENCY],word1[LOAD_LATENCY+1]
-(pC1[1])adds carry1=1,carry1
-(ELD_1) cmp.ltu pC2[0],p0=result2[LOAD_LATENCY],word2[LOAD_LATENCY+1]
-(pC2[1])adds carry2=1,carry2
-(ELD) add result1[LOAD_LATENCY-1]=result1[LOAD_LATENCY],word1[LOAD_LATENCY]
-(ELD) add result2[LOAD_LATENCY-1]=result2[LOAD_LATENCY],word2[LOAD_LATENCY]
-2:
-(p[0]) ld8 word1[0]=[first1],16
-(p[0]) ld8 word2[0]=[first2],16
- br.ctop.sptk 1b
- ;;
- // Since len is a 32-bit value, carry cannot be larger than a 64-bit value.
-(pC1[1])adds carry1=1,carry1 // since we miss the last one
-(pC2[1])adds carry2=1,carry2
- ;;
- add result1[LOAD_LATENCY+1]=result1[LOAD_LATENCY+1],carry1
- add result2[LOAD_LATENCY+1]=result2[LOAD_LATENCY+1],carry2
- ;;
- cmp.ltu p6,p0=result1[LOAD_LATENCY+1],carry1
- cmp.ltu p7,p0=result2[LOAD_LATENCY+1],carry2
- ;;
-(p6) adds result1[LOAD_LATENCY+1]=1,result1[LOAD_LATENCY+1]
-(p7) adds result2[LOAD_LATENCY+1]=1,result2[LOAD_LATENCY+1]
- ;;
- add result1[0]=result1[LOAD_LATENCY+1],result2[LOAD_LATENCY+1]
- ;;
- cmp.ltu p6,p0=result1[0],result2[LOAD_LATENCY+1]
- ;;
-(p6) adds result1[0]=1,result1[0]
- ;;
-.do_csum_exit:
- //
- // now fold 64 into 16 bits taking care of carry
- // that's not very good because it has lots of sequentiality
- //
- mov tmp3=0xffff
- zxt4 tmp1=result1[0]
- shr.u tmp2=result1[0],32
- ;;
- add result1[0]=tmp1,tmp2
- ;;
- and tmp1=result1[0],tmp3
- shr.u tmp2=result1[0],16
- ;;
- add result1[0]=tmp1,tmp2
- ;;
- and tmp1=result1[0],tmp3
- shr.u tmp2=result1[0],16
- ;;
- add result1[0]=tmp1,tmp2
- ;;
- and tmp1=result1[0],tmp3
- shr.u tmp2=result1[0],16
- ;;
- add ret0=tmp1,tmp2
- mov pr=saved_pr,0xffffffffffff0000
- ;;
- // if buf was odd then swap bytes
- mov ar.pfs=saved_pfs // restore ar.ec
-(p15) mux1 ret0=ret0,@rev // reverse word
- ;;
- mov ar.lc=saved_lc
-(p15) shr.u ret0=ret0,64-16 // + shift back to position = swap bytes
- br.ret.sptk.many rp
-
-// I (Jun Nakajima) wrote an equivalent code (see below), but it was
-// not much better than the original. So keep the original there so that
-// someone else can challenge.
-//
-// shr.u word1[0]=result1[0],32
-// zxt4 result1[0]=result1[0]
-// ;;
-// add result1[0]=result1[0],word1[0]
-// ;;
-// zxt2 result2[0]=result1[0]
-// extr.u word1[0]=result1[0],16,16
-// shr.u carry1=result1[0],32
-// ;;
-// add result2[0]=result2[0],word1[0]
-// ;;
-// add result2[0]=result2[0],carry1
-// ;;
-// extr.u ret0=result2[0],16,16
-// ;;
-// add ret0=ret0,result2[0]
-// ;;
-// zxt2 ret0=ret0
-// mov ar.pfs=saved_pfs // restore ar.ec
-// mov pr=saved_pr,0xffffffffffff0000
-// ;;
-// // if buf was odd then swap bytes
-// mov ar.lc=saved_lc
-//(p15) mux1 ret0=ret0,@rev // reverse word
-// ;;
-//(p15) shr.u ret0=ret0,64-16 // + shift back to position = swap bytes
-// br.ret.sptk.many rp
-
-END(do_csum)
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
deleted file mode 100644
index f8e795fe45cb..000000000000
--- a/arch/ia64/lib/flush.S
+++ /dev/null
@@ -1,119 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Cache flushing routines.
- *
- * Copyright (C) 1999-2001, 2005 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * 05/28/05 Zoltan Menyhart Dynamic stride size
- */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-
- /*
- * flush_icache_range(start,end)
- *
- * Make i-cache(s) coherent with d-caches.
- *
- * Must deal with range from start to end-1 but nothing else (need to
- * be careful not to touch addresses that may be unmapped).
- *
- * Note: "in0" and "in1" are preserved for debugging purposes.
- */
- .section .kprobes.text,"ax"
-GLOBAL_ENTRY(flush_icache_range)
-
- .prologue
- alloc r2=ar.pfs,2,0,0,0
- movl r3=ia64_i_cache_stride_shift
- mov r21=1
- ;;
- ld8 r20=[r3] // r20: stride shift
- sub r22=in1,r0,1 // last byte address
- ;;
- shr.u r23=in0,r20 // start / (stride size)
- shr.u r22=r22,r20 // (last byte address) / (stride size)
- shl r21=r21,r20 // r21: stride size of the i-cache(s)
- ;;
- sub r8=r22,r23 // number of strides - 1
- shl r24=r23,r20 // r24: addresses for "fc.i" =
- // "start" rounded down to stride boundary
- .save ar.lc,r3
- mov r3=ar.lc // save ar.lc
- ;;
-
- .body
- mov ar.lc=r8
- ;;
- /*
- * 32 byte aligned loop, even number of (actually 2) bundles
- */
-.Loop: fc.i r24 // issuable on M0 only
- add r24=r21,r24 // we flush "stride size" bytes per iteration
- nop.i 0
- br.cloop.sptk.few .Loop
- ;;
- sync.i
- ;;
- srlz.i
- ;;
- mov ar.lc=r3 // restore ar.lc
- br.ret.sptk.many rp
-END(flush_icache_range)
-EXPORT_SYMBOL_GPL(flush_icache_range)
-
- /*
- * clflush_cache_range(start,size)
- *
- * Flush cache lines from start to start+size-1.
- *
- * Must deal with range from start to start+size-1 but nothing else
- * (need to be careful not to touch addresses that may be
- * unmapped).
- *
- * Note: "in0" and "in1" are preserved for debugging purposes.
- */
- .section .kprobes.text,"ax"
-GLOBAL_ENTRY(clflush_cache_range)
-
- .prologue
- alloc r2=ar.pfs,2,0,0,0
- movl r3=ia64_cache_stride_shift
- mov r21=1
- add r22=in1,in0
- ;;
- ld8 r20=[r3] // r20: stride shift
- sub r22=r22,r0,1 // last byte address
- ;;
- shr.u r23=in0,r20 // start / (stride size)
- shr.u r22=r22,r20 // (last byte address) / (stride size)
- shl r21=r21,r20 // r21: stride size of the i-cache(s)
- ;;
- sub r8=r22,r23 // number of strides - 1
- shl r24=r23,r20 // r24: addresses for "fc" =
- // "start" rounded down to stride
- // boundary
- .save ar.lc,r3
- mov r3=ar.lc // save ar.lc
- ;;
-
- .body
- mov ar.lc=r8
- ;;
- /*
- * 32 byte aligned loop, even number of (actually 2) bundles
- */
-.Loop_fc:
- fc r24 // issuable on M0 only
- add r24=r21,r24 // we flush "stride size" bytes per iteration
- nop.i 0
- br.cloop.sptk.few .Loop_fc
- ;;
- sync.i
- ;;
- srlz.i
- ;;
- mov ar.lc=r3 // restore ar.lc
- br.ret.sptk.many rp
-END(clflush_cache_range)
diff --git a/arch/ia64/lib/idiv32.S b/arch/ia64/lib/idiv32.S
deleted file mode 100644
index 83586fbc51ff..000000000000
--- a/arch/ia64/lib/idiv32.S
+++ /dev/null
@@ -1,86 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2000 Hewlett-Packard Co
- * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * 32-bit integer division.
- *
- * This code is based on the application note entitled "Divide, Square Root
- * and Remainder Algorithms for the IA-64 Architecture". This document
- * is available as Intel document number 248725-002 or via the web at
- * http://developer.intel.com/software/opensource/numerics/
- *
- * For more details on the theory behind these algorithms, see "IA-64
- * and Elementary Functions" by Peter Markstein; HP Professional Books
- * (http://www.goodreads.com/book/show/2019887.Ia_64_and_Elementary_Functions)
- */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-
-#ifdef MODULO
-# define OP mod
-#else
-# define OP div
-#endif
-
-#ifdef UNSIGNED
-# define SGN u
-# define EXTEND zxt4
-# define INT_TO_FP(a,b) fcvt.xuf.s1 a=b
-# define FP_TO_INT(a,b) fcvt.fxu.trunc.s1 a=b
-#else
-# define SGN
-# define EXTEND sxt4
-# define INT_TO_FP(a,b) fcvt.xf a=b
-# define FP_TO_INT(a,b) fcvt.fx.trunc.s1 a=b
-#endif
-
-#define PASTE1(a,b) a##b
-#define PASTE(a,b) PASTE1(a,b)
-#define NAME PASTE(PASTE(__,SGN),PASTE(OP,si3))
-
-GLOBAL_ENTRY(NAME)
- .regstk 2,0,0,0
- // Transfer inputs to FP registers.
- mov r2 = 0xffdd // r2 = -34 + 65535 (fp reg format bias)
- EXTEND in0 = in0 // in0 = a
- EXTEND in1 = in1 // in1 = b
- ;;
- setf.sig f8 = in0
- setf.sig f9 = in1
-#ifdef MODULO
- sub in1 = r0, in1 // in1 = -b
-#endif
- ;;
- // Convert the inputs to FP, to avoid FP software-assist faults.
- INT_TO_FP(f8, f8)
- INT_TO_FP(f9, f9)
- ;;
- setf.exp f7 = r2 // f7 = 2^-34
- frcpa.s1 f6, p6 = f8, f9 // y0 = frcpa(b)
- ;;
-(p6) fmpy.s1 f8 = f8, f6 // q0 = a*y0
-(p6) fnma.s1 f6 = f9, f6, f1 // e0 = -b*y0 + 1
- ;;
-#ifdef MODULO
- setf.sig f9 = in1 // f9 = -b
-#endif
-(p6) fma.s1 f8 = f6, f8, f8 // q1 = e0*q0 + q0
-(p6) fma.s1 f6 = f6, f6, f7 // e1 = e0*e0 + 2^-34
- ;;
-#ifdef MODULO
- setf.sig f7 = in0
-#endif
-(p6) fma.s1 f6 = f6, f8, f8 // q2 = e1*q1 + q1
- ;;
- FP_TO_INT(f6, f6) // q = trunc(q2)
- ;;
-#ifdef MODULO
- xma.l f6 = f6, f9, f7 // r = q*(-b) + a
- ;;
-#endif
- getf.sig r8 = f6 // transfer result to result register
- br.ret.sptk.many rp
-END(NAME)
-EXPORT_SYMBOL(NAME)
diff --git a/arch/ia64/lib/idiv64.S b/arch/ia64/lib/idiv64.S
deleted file mode 100644
index 5c9113691f72..000000000000
--- a/arch/ia64/lib/idiv64.S
+++ /dev/null
@@ -1,83 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 1999-2000 Hewlett-Packard Co
- * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * 64-bit integer division.
- *
- * This code is based on the application note entitled "Divide, Square Root
- * and Remainder Algorithms for the IA-64 Architecture". This document
- * is available as Intel document number 248725-002 or via the web at
- * http://developer.intel.com/software/opensource/numerics/
- *
- * For more details on the theory behind these algorithms, see "IA-64
- * and Elementary Functions" by Peter Markstein; HP Professional Books
- * (http://www.goodreads.com/book/show/2019887.Ia_64_and_Elementary_Functions)
- */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-
-#ifdef MODULO
-# define OP mod
-#else
-# define OP div
-#endif
-
-#ifdef UNSIGNED
-# define SGN u
-# define INT_TO_FP(a,b) fcvt.xuf.s1 a=b
-# define FP_TO_INT(a,b) fcvt.fxu.trunc.s1 a=b
-#else
-# define SGN
-# define INT_TO_FP(a,b) fcvt.xf a=b
-# define FP_TO_INT(a,b) fcvt.fx.trunc.s1 a=b
-#endif
-
-#define PASTE1(a,b) a##b
-#define PASTE(a,b) PASTE1(a,b)
-#define NAME PASTE(PASTE(__,SGN),PASTE(OP,di3))
-
-GLOBAL_ENTRY(NAME)
- .regstk 2,0,0,0
- // Transfer inputs to FP registers.
- setf.sig f8 = in0
- setf.sig f9 = in1
- ;;
- // Convert the inputs to FP, to avoid FP software-assist faults.
- INT_TO_FP(f8, f8)
- INT_TO_FP(f9, f9)
- ;;
- frcpa.s1 f11, p6 = f8, f9 // y0 = frcpa(b)
- ;;
-(p6) fmpy.s1 f7 = f8, f11 // q0 = a*y0
-(p6) fnma.s1 f6 = f9, f11, f1 // e0 = -b*y0 + 1
- ;;
-(p6) fma.s1 f10 = f7, f6, f7 // q1 = q0*e0 + q0
-(p6) fmpy.s1 f7 = f6, f6 // e1 = e0*e0
- ;;
-#ifdef MODULO
- sub in1 = r0, in1 // in1 = -b
-#endif
-(p6) fma.s1 f10 = f10, f7, f10 // q2 = q1*e1 + q1
-(p6) fma.s1 f6 = f11, f6, f11 // y1 = y0*e0 + y0
- ;;
-(p6) fma.s1 f6 = f6, f7, f6 // y2 = y1*e1 + y1
-(p6) fnma.s1 f7 = f9, f10, f8 // r = -b*q2 + a
- ;;
-#ifdef MODULO
- setf.sig f8 = in0 // f8 = a
- setf.sig f9 = in1 // f9 = -b
-#endif
-(p6) fma.s1 f11 = f7, f6, f10 // q3 = r*y2 + q2
- ;;
- FP_TO_INT(f11, f11) // q = trunc(q3)
- ;;
-#ifdef MODULO
- xma.l f11 = f11, f9, f8 // r = q*(-b) + a
- ;;
-#endif
- getf.sig r8 = f11 // transfer result to result register
- br.ret.sptk.many rp
-END(NAME)
-EXPORT_SYMBOL(NAME)
diff --git a/arch/ia64/lib/io.c b/arch/ia64/lib/io.c
deleted file mode 100644
index c3e02462ed16..000000000000
--- a/arch/ia64/lib/io.c
+++ /dev/null
@@ -1,51 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/module.h>
-#include <linux/types.h>
-
-#include <asm/io.h>
-
-/*
- * Copy data from IO memory space to "real" memory space.
- * This needs to be optimized.
- */
-void memcpy_fromio(void *to, const volatile void __iomem *from, long count)
-{
- char *dst = to;
-
- while (count) {
- count--;
- *dst++ = readb(from++);
- }
-}
-EXPORT_SYMBOL(memcpy_fromio);
-
-/*
- * Copy data from "real" memory space to IO memory space.
- * This needs to be optimized.
- */
-void memcpy_toio(volatile void __iomem *to, const void *from, long count)
-{
- const char *src = from;
-
- while (count) {
- count--;
- writeb(*src++, to++);
- }
-}
-EXPORT_SYMBOL(memcpy_toio);
-
-/*
- * "memset" on IO memory space.
- * This needs to be optimized.
- */
-void memset_io(volatile void __iomem *dst, int c, long count)
-{
- unsigned char ch = (char)(c & 0xff);
-
- while (count) {
- count--;
- writeb(ch, dst);
- dst++;
- }
-}
-EXPORT_SYMBOL(memset_io);
diff --git a/arch/ia64/lib/ip_fast_csum.S b/arch/ia64/lib/ip_fast_csum.S
deleted file mode 100644
index fcc0b812ce2e..000000000000
--- a/arch/ia64/lib/ip_fast_csum.S
+++ /dev/null
@@ -1,148 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Optmized version of the ip_fast_csum() function
- * Used for calculating IP header checksum
- *
- * Return: 16bit checksum, complemented
- *
- * Inputs:
- * in0: address of buffer to checksum (char *)
- * in1: length of the buffer (int)
- *
- * Copyright (C) 2002, 2006 Intel Corp.
- * Copyright (C) 2002, 2006 Ken Chen <kenneth.w.chen@intel.com>
- */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-
-/*
- * Since we know that most likely this function is called with buf aligned
- * on 4-byte boundary and 20 bytes in length, we can execution rather quickly
- * versus calling generic version of do_csum, which has lots of overhead in
- * handling various alignments and sizes. However, due to lack of constrains
- * put on the function input argument, cases with alignment not on 4-byte or
- * size not equal to 20 bytes will be handled by the generic do_csum function.
- */
-
-#define in0 r32
-#define in1 r33
-#define in2 r34
-#define in3 r35
-#define in4 r36
-#define ret0 r8
-
-GLOBAL_ENTRY(ip_fast_csum)
- .prologue
- .body
- cmp.ne p6,p7=5,in1 // size other than 20 byte?
- and r14=3,in0 // is it aligned on 4-byte?
- add r15=4,in0 // second source pointer
- ;;
- cmp.ne.or.andcm p6,p7=r14,r0
- ;;
-(p7) ld4 r20=[in0],8
-(p7) ld4 r21=[r15],8
-(p6) br.spnt .generic
- ;;
- ld4 r22=[in0],8
- ld4 r23=[r15],8
- ;;
- ld4 r24=[in0]
- add r20=r20,r21
- add r22=r22,r23
- ;;
- add r20=r20,r22
- ;;
- add r20=r20,r24
- ;;
- shr.u ret0=r20,16 // now need to add the carry
- zxt2 r20=r20
- ;;
- add r20=ret0,r20
- ;;
- shr.u ret0=r20,16 // add carry again
- zxt2 r20=r20
- ;;
- add r20=ret0,r20
- ;;
- shr.u ret0=r20,16
- zxt2 r20=r20
- ;;
- add r20=ret0,r20
- mov r9=0xffff
- ;;
- andcm ret0=r9,r20
- .restore sp // reset frame state
- br.ret.sptk.many b0
- ;;
-
-.generic:
- .prologue
- .save ar.pfs, r35
- alloc r35=ar.pfs,2,2,2,0
- .save rp, r34
- mov r34=b0
- .body
- dep.z out1=in1,2,30
- mov out0=in0
- ;;
- br.call.sptk.many b0=do_csum
- ;;
- andcm ret0=-1,ret0
- mov ar.pfs=r35
- mov b0=r34
- br.ret.sptk.many b0
-END(ip_fast_csum)
-EXPORT_SYMBOL(ip_fast_csum)
-
-GLOBAL_ENTRY(csum_ipv6_magic)
- ld4 r20=[in0],4
- ld4 r21=[in1],4
- zxt4 in2=in2
- ;;
- ld4 r22=[in0],4
- ld4 r23=[in1],4
- dep r15=in3,in2,32,16
- ;;
- ld4 r24=[in0],4
- ld4 r25=[in1],4
- mux1 r15=r15,@rev
- add r16=r20,r21
- add r17=r22,r23
- zxt4 in4=in4
- ;;
- ld4 r26=[in0],4
- ld4 r27=[in1],4
- shr.u r15=r15,16
- add r18=r24,r25
- add r8=r16,r17
- ;;
- add r19=r26,r27
- add r8=r8,r18
- ;;
- add r8=r8,r19
- add r15=r15,in4
- ;;
- add r8=r8,r15
- ;;
- shr.u r10=r8,32 // now fold sum into short
- zxt4 r11=r8
- ;;
- add r8=r10,r11
- ;;
- shr.u r10=r8,16 // yeah, keep it rolling
- zxt2 r11=r8
- ;;
- add r8=r10,r11
- ;;
- shr.u r10=r8,16 // three times lucky
- zxt2 r11=r8
- ;;
- add r8=r10,r11
- mov r9=0xffff
- ;;
- andcm r8=r9,r8
- br.ret.sptk.many b0
-END(csum_ipv6_magic)
-EXPORT_SYMBOL(csum_ipv6_magic)
diff --git a/arch/ia64/lib/memcpy.S b/arch/ia64/lib/memcpy.S
deleted file mode 100644
index 35c9069a8345..000000000000
--- a/arch/ia64/lib/memcpy.S
+++ /dev/null
@@ -1,304 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *
- * Optimized version of the standard memcpy() function
- *
- * Inputs:
- * in0: destination address
- * in1: source address
- * in2: number of bytes to copy
- * Output:
- * no return value
- *
- * Copyright (C) 2000-2001 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-
-GLOBAL_ENTRY(memcpy)
-
-# define MEM_LAT 21 /* latency to memory */
-
-# define dst r2
-# define src r3
-# define retval r8
-# define saved_pfs r9
-# define saved_lc r10
-# define saved_pr r11
-# define cnt r16
-# define src2 r17
-# define t0 r18
-# define t1 r19
-# define t2 r20
-# define t3 r21
-# define t4 r22
-# define src_end r23
-
-# define N (MEM_LAT + 4)
-# define Nrot ((N + 7) & ~7)
-
- /*
- * First, check if everything (src, dst, len) is a multiple of eight. If
- * so, we handle everything with no taken branches (other than the loop
- * itself) and a small icache footprint. Otherwise, we jump off to
- * the more general copy routine handling arbitrary
- * sizes/alignment etc.
- */
- .prologue
- .save ar.pfs, saved_pfs
- alloc saved_pfs=ar.pfs,3,Nrot,0,Nrot
- .save ar.lc, saved_lc
- mov saved_lc=ar.lc
- or t0=in0,in1
- ;;
-
- or t0=t0,in2
- .save pr, saved_pr
- mov saved_pr=pr
-
- .body
-
- cmp.eq p6,p0=in2,r0 // zero length?
- mov retval=in0 // return dst
-(p6) br.ret.spnt.many rp // zero length, return immediately
- ;;
-
- mov dst=in0 // copy because of rotation
- shr.u cnt=in2,3 // number of 8-byte words to copy
- mov pr.rot=1<<16
- ;;
-
- adds cnt=-1,cnt // br.ctop is repeat/until
- cmp.gtu p7,p0=16,in2 // copying less than 16 bytes?
- mov ar.ec=N
- ;;
-
- and t0=0x7,t0
- mov ar.lc=cnt
- ;;
- cmp.ne p6,p0=t0,r0
-
- mov src=in1 // copy because of rotation
-(p7) br.cond.spnt.few .memcpy_short
-(p6) br.cond.spnt.few .memcpy_long
- ;;
- nop.m 0
- ;;
- nop.m 0
- nop.i 0
- ;;
- nop.m 0
- ;;
- .rotr val[N]
- .rotp p[N]
- .align 32
-1: { .mib
-(p[0]) ld8 val[0]=[src],8
- nop.i 0
- brp.loop.imp 1b, 2f
-}
-2: { .mfb
-(p[N-1])st8 [dst]=val[N-1],8
- nop.f 0
- br.ctop.dptk.few 1b
-}
- ;;
- mov ar.lc=saved_lc
- mov pr=saved_pr,-1
- mov ar.pfs=saved_pfs
- br.ret.sptk.many rp
-
- /*
- * Small (<16 bytes) unaligned copying is done via a simple byte-at-the-time
- * copy loop. This performs relatively poorly on Itanium, but it doesn't
- * get used very often (gcc inlines small copies) and due to atomicity
- * issues, we want to avoid read-modify-write of entire words.
- */
- .align 32
-.memcpy_short:
- adds cnt=-1,in2 // br.ctop is repeat/until
- mov ar.ec=MEM_LAT
- brp.loop.imp 1f, 2f
- ;;
- mov ar.lc=cnt
- ;;
- nop.m 0
- ;;
- nop.m 0
- nop.i 0
- ;;
- nop.m 0
- ;;
- nop.m 0
- ;;
- /*
- * It is faster to put a stop bit in the loop here because it makes
- * the pipeline shorter (and latency is what matters on short copies).
- */
- .align 32
-1: { .mib
-(p[0]) ld1 val[0]=[src],1
- nop.i 0
- brp.loop.imp 1b, 2f
-} ;;
-2: { .mfb
-(p[MEM_LAT-1])st1 [dst]=val[MEM_LAT-1],1
- nop.f 0
- br.ctop.dptk.few 1b
-} ;;
- mov ar.lc=saved_lc
- mov pr=saved_pr,-1
- mov ar.pfs=saved_pfs
- br.ret.sptk.many rp
-
- /*
- * Large (>= 16 bytes) copying is done in a fancy way. Latency isn't
- * an overriding concern here, but throughput is. We first do
- * sub-word copying until the destination is aligned, then we check
- * if the source is also aligned. If so, we do a simple load/store-loop
- * until there are less than 8 bytes left over and then we do the tail,
- * by storing the last few bytes using sub-word copying. If the source
- * is not aligned, we branch off to the non-congruent loop.
- *
- * stage: op:
- * 0 ld
- * :
- * MEM_LAT+3 shrp
- * MEM_LAT+4 st
- *
- * On Itanium, the pipeline itself runs without stalls. However, br.ctop
- * seems to introduce an unavoidable bubble in the pipeline so the overall
- * latency is 2 cycles/iteration. This gives us a _copy_ throughput
- * of 4 byte/cycle. Still not bad.
- */
-# undef N
-# undef Nrot
-# define N (MEM_LAT + 5) /* number of stages */
-# define Nrot ((N+1 + 2 + 7) & ~7) /* number of rotating regs */
-
-#define LOG_LOOP_SIZE 6
-
-.memcpy_long:
- alloc t3=ar.pfs,3,Nrot,0,Nrot // resize register frame
- and t0=-8,src // t0 = src & ~7
- and t2=7,src // t2 = src & 7
- ;;
- ld8 t0=[t0] // t0 = 1st source word
- adds src2=7,src // src2 = (src + 7)
- sub t4=r0,dst // t4 = -dst
- ;;
- and src2=-8,src2 // src2 = (src + 7) & ~7
- shl t2=t2,3 // t2 = 8*(src & 7)
- shl t4=t4,3 // t4 = 8*(dst & 7)
- ;;
- ld8 t1=[src2] // t1 = 1st source word if src is 8-byte aligned, 2nd otherwise
- sub t3=64,t2 // t3 = 64-8*(src & 7)
- shr.u t0=t0,t2
- ;;
- add src_end=src,in2
- shl t1=t1,t3
- mov pr=t4,0x38 // (p5,p4,p3)=(dst & 7)
- ;;
- or t0=t0,t1
- mov cnt=r0
- adds src_end=-1,src_end
- ;;
-(p3) st1 [dst]=t0,1
-(p3) shr.u t0=t0,8
-(p3) adds cnt=1,cnt
- ;;
-(p4) st2 [dst]=t0,2
-(p4) shr.u t0=t0,16
-(p4) adds cnt=2,cnt
- ;;
-(p5) st4 [dst]=t0,4
-(p5) adds cnt=4,cnt
- and src_end=-8,src_end // src_end = last word of source buffer
- ;;
-
- // At this point, dst is aligned to 8 bytes and there at least 16-7=9 bytes left to copy:
-
-1:{ add src=cnt,src // make src point to remainder of source buffer
- sub cnt=in2,cnt // cnt = number of bytes left to copy
- mov t4=ip
- } ;;
- and src2=-8,src // align source pointer
- adds t4=.memcpy_loops-1b,t4
- mov ar.ec=N
-
- and t0=7,src // t0 = src & 7
- shr.u t2=cnt,3 // t2 = number of 8-byte words left to copy
- shl cnt=cnt,3 // move bits 0-2 to 3-5
- ;;
-
- .rotr val[N+1], w[2]
- .rotp p[N]
-
- cmp.ne p6,p0=t0,r0 // is src aligned, too?
- shl t0=t0,LOG_LOOP_SIZE // t0 = 8*(src & 7)
- adds t2=-1,t2 // br.ctop is repeat/until
- ;;
- add t4=t0,t4
- mov pr=cnt,0x38 // set (p5,p4,p3) to # of bytes last-word bytes to copy
- mov ar.lc=t2
- ;;
- nop.m 0
- ;;
- nop.m 0
- nop.i 0
- ;;
- nop.m 0
- ;;
-(p6) ld8 val[1]=[src2],8 // prime the pump...
- mov b6=t4
- br.sptk.few b6
- ;;
-
-.memcpy_tail:
- // At this point, (p5,p4,p3) are set to the number of bytes left to copy (which is
- // less than 8) and t0 contains the last few bytes of the src buffer:
-(p5) st4 [dst]=t0,4
-(p5) shr.u t0=t0,32
- mov ar.lc=saved_lc
- ;;
-(p4) st2 [dst]=t0,2
-(p4) shr.u t0=t0,16
- mov ar.pfs=saved_pfs
- ;;
-(p3) st1 [dst]=t0
- mov pr=saved_pr,-1
- br.ret.sptk.many rp
-
-///////////////////////////////////////////////////////
- .align 64
-
-#define COPY(shift,index) \
- 1: { .mib \
- (p[0]) ld8 val[0]=[src2],8; \
- (p[MEM_LAT+3]) shrp w[0]=val[MEM_LAT+3],val[MEM_LAT+4-index],shift; \
- brp.loop.imp 1b, 2f \
- }; \
- 2: { .mfb \
- (p[MEM_LAT+4]) st8 [dst]=w[1],8; \
- nop.f 0; \
- br.ctop.dptk.few 1b; \
- }; \
- ;; \
- ld8 val[N-1]=[src_end]; /* load last word (may be same as val[N]) */ \
- ;; \
- shrp t0=val[N-1],val[N-index],shift; \
- br .memcpy_tail
-.memcpy_loops:
- COPY(0, 1) /* no point special casing this---it doesn't go any faster without shrp */
- COPY(8, 0)
- COPY(16, 0)
- COPY(24, 0)
- COPY(32, 0)
- COPY(40, 0)
- COPY(48, 0)
- COPY(56, 0)
-
-END(memcpy)
-EXPORT_SYMBOL(memcpy)
diff --git a/arch/ia64/lib/memcpy_mck.S b/arch/ia64/lib/memcpy_mck.S
deleted file mode 100644
index c0d4362217ae..000000000000
--- a/arch/ia64/lib/memcpy_mck.S
+++ /dev/null
@@ -1,659 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Itanium 2-optimized version of memcpy and copy_user function
- *
- * Inputs:
- * in0: destination address
- * in1: source address
- * in2: number of bytes to copy
- * Output:
- * for memcpy: return dest
- * for copy_user: return 0 if success,
- * or number of byte NOT copied if error occurred.
- *
- * Copyright (C) 2002 Intel Corp.
- * Copyright (C) 2002 Ken Chen <kenneth.w.chen@intel.com>
- */
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-#include <asm/page.h>
-
-#define EK(y...) EX(y)
-
-/* McKinley specific optimization */
-
-#define retval r8
-#define saved_pfs r31
-#define saved_lc r10
-#define saved_pr r11
-#define saved_in0 r14
-#define saved_in1 r15
-#define saved_in2 r16
-
-#define src0 r2
-#define src1 r3
-#define dst0 r17
-#define dst1 r18
-#define cnt r9
-
-/* r19-r30 are temp for each code section */
-#define PREFETCH_DIST 8
-#define src_pre_mem r19
-#define dst_pre_mem r20
-#define src_pre_l2 r21
-#define dst_pre_l2 r22
-#define t1 r23
-#define t2 r24
-#define t3 r25
-#define t4 r26
-#define t5 t1 // alias!
-#define t6 t2 // alias!
-#define t7 t3 // alias!
-#define n8 r27
-#define t9 t5 // alias!
-#define t10 t4 // alias!
-#define t11 t7 // alias!
-#define t12 t6 // alias!
-#define t14 t10 // alias!
-#define t13 r28
-#define t15 r29
-#define tmp r30
-
-/* defines for long_copy block */
-#define A 0
-#define B (PREFETCH_DIST)
-#define C (B + PREFETCH_DIST)
-#define D (C + 1)
-#define N (D + 1)
-#define Nrot ((N + 7) & ~7)
-
-/* alias */
-#define in0 r32
-#define in1 r33
-#define in2 r34
-
-GLOBAL_ENTRY(memcpy)
- and r28=0x7,in0
- and r29=0x7,in1
- mov f6=f0
- mov retval=in0
- br.cond.sptk .common_code
- ;;
-END(memcpy)
-EXPORT_SYMBOL(memcpy)
-GLOBAL_ENTRY(__copy_user)
- .prologue
-// check dest alignment
- and r28=0x7,in0
- and r29=0x7,in1
- mov f6=f1
- mov saved_in0=in0 // save dest pointer
- mov saved_in1=in1 // save src pointer
- mov retval=r0 // initialize return value
- ;;
-.common_code:
- cmp.gt p15,p0=8,in2 // check for small size
- cmp.ne p13,p0=0,r28 // check dest alignment
- cmp.ne p14,p0=0,r29 // check src alignment
- add src0=0,in1
- sub r30=8,r28 // for .align_dest
- mov saved_in2=in2 // save len
- ;;
- add dst0=0,in0
- add dst1=1,in0 // dest odd index
- cmp.le p6,p0 = 1,r30 // for .align_dest
-(p15) br.cond.dpnt .memcpy_short
-(p13) br.cond.dpnt .align_dest
-(p14) br.cond.dpnt .unaligned_src
- ;;
-
-// both dest and src are aligned on 8-byte boundary
-.aligned_src:
- .save ar.pfs, saved_pfs
- alloc saved_pfs=ar.pfs,3,Nrot-3,0,Nrot
- .save pr, saved_pr
- mov saved_pr=pr
-
- shr.u cnt=in2,7 // this much cache line
- ;;
- cmp.lt p6,p0=2*PREFETCH_DIST,cnt
- cmp.lt p7,p8=1,cnt
- .save ar.lc, saved_lc
- mov saved_lc=ar.lc
- .body
- add cnt=-1,cnt
- add src_pre_mem=0,in1 // prefetch src pointer
- add dst_pre_mem=0,in0 // prefetch dest pointer
- ;;
-(p7) mov ar.lc=cnt // prefetch count
-(p8) mov ar.lc=r0
-(p6) br.cond.dpnt .long_copy
- ;;
-
-.prefetch:
- lfetch.fault [src_pre_mem], 128
- lfetch.fault.excl [dst_pre_mem], 128
- br.cloop.dptk.few .prefetch
- ;;
-
-.medium_copy:
- and tmp=31,in2 // copy length after iteration
- shr.u r29=in2,5 // number of 32-byte iteration
- add dst1=8,dst0 // 2nd dest pointer
- ;;
- add cnt=-1,r29 // ctop iteration adjustment
- cmp.eq p10,p0=r29,r0 // do we really need to loop?
- add src1=8,src0 // 2nd src pointer
- cmp.le p6,p0=8,tmp
- ;;
- cmp.le p7,p0=16,tmp
- mov ar.lc=cnt // loop setup
- cmp.eq p16,p17 = r0,r0
- mov ar.ec=2
-(p10) br.dpnt.few .aligned_src_tail
- ;;
- TEXT_ALIGN(32)
-1:
-EX(.ex_handler, (p16) ld8 r34=[src0],16)
-EK(.ex_handler, (p16) ld8 r38=[src1],16)
-EX(.ex_handler, (p17) st8 [dst0]=r33,16)
-EK(.ex_handler, (p17) st8 [dst1]=r37,16)
- ;;
-EX(.ex_handler, (p16) ld8 r32=[src0],16)
-EK(.ex_handler, (p16) ld8 r36=[src1],16)
-EX(.ex_handler, (p16) st8 [dst0]=r34,16)
-EK(.ex_handler, (p16) st8 [dst1]=r38,16)
- br.ctop.dptk.few 1b
- ;;
-
-.aligned_src_tail:
-EX(.ex_handler, (p6) ld8 t1=[src0])
- mov ar.lc=saved_lc
- mov ar.pfs=saved_pfs
-EX(.ex_hndlr_s, (p7) ld8 t2=[src1],8)
- cmp.le p8,p0=24,tmp
- and r21=-8,tmp
- ;;
-EX(.ex_hndlr_s, (p8) ld8 t3=[src1])
-EX(.ex_handler, (p6) st8 [dst0]=t1) // store byte 1
- and in2=7,tmp // remaining length
-EX(.ex_hndlr_d, (p7) st8 [dst1]=t2,8) // store byte 2
- add src0=src0,r21 // setting up src pointer
- add dst0=dst0,r21 // setting up dest pointer
- ;;
-EX(.ex_handler, (p8) st8 [dst1]=t3) // store byte 3
- mov pr=saved_pr,-1
- br.dptk.many .memcpy_short
- ;;
-
-/* code taken from copy_page_mck */
-.long_copy:
- .rotr v[2*PREFETCH_DIST]
- .rotp p[N]
-
- mov src_pre_mem = src0
- mov pr.rot = 0x10000
- mov ar.ec = 1 // special unrolled loop
-
- mov dst_pre_mem = dst0
-
- add src_pre_l2 = 8*8, src0
- add dst_pre_l2 = 8*8, dst0
- ;;
- add src0 = 8, src_pre_mem // first t1 src
- mov ar.lc = 2*PREFETCH_DIST - 1
- shr.u cnt=in2,7 // number of lines
- add src1 = 3*8, src_pre_mem // first t3 src
- add dst0 = 8, dst_pre_mem // first t1 dst
- add dst1 = 3*8, dst_pre_mem // first t3 dst
- ;;
- and tmp=127,in2 // remaining bytes after this block
- add cnt = -(2*PREFETCH_DIST) - 1, cnt
- // same as .line_copy loop, but with all predicated-off instructions removed:
-.prefetch_loop:
-EX(.ex_hndlr_lcpy_1, (p[A]) ld8 v[A] = [src_pre_mem], 128) // M0
-EK(.ex_hndlr_lcpy_1, (p[B]) st8 [dst_pre_mem] = v[B], 128) // M2
- br.ctop.sptk .prefetch_loop
- ;;
- cmp.eq p16, p0 = r0, r0 // reset p16 to 1
- mov ar.lc = cnt
- mov ar.ec = N // # of stages in pipeline
- ;;
-.line_copy:
-EX(.ex_handler, (p[D]) ld8 t2 = [src0], 3*8) // M0
-EK(.ex_handler, (p[D]) ld8 t4 = [src1], 3*8) // M1
-EX(.ex_handler_lcpy, (p[B]) st8 [dst_pre_mem] = v[B], 128) // M2 prefetch dst from memory
-EK(.ex_handler_lcpy, (p[D]) st8 [dst_pre_l2] = n8, 128) // M3 prefetch dst from L2
- ;;
-EX(.ex_handler_lcpy, (p[A]) ld8 v[A] = [src_pre_mem], 128) // M0 prefetch src from memory
-EK(.ex_handler_lcpy, (p[C]) ld8 n8 = [src_pre_l2], 128) // M1 prefetch src from L2
-EX(.ex_handler, (p[D]) st8 [dst0] = t1, 8) // M2
-EK(.ex_handler, (p[D]) st8 [dst1] = t3, 8) // M3
- ;;
-EX(.ex_handler, (p[D]) ld8 t5 = [src0], 8)
-EK(.ex_handler, (p[D]) ld8 t7 = [src1], 3*8)
-EX(.ex_handler, (p[D]) st8 [dst0] = t2, 3*8)
-EK(.ex_handler, (p[D]) st8 [dst1] = t4, 3*8)
- ;;
-EX(.ex_handler, (p[D]) ld8 t6 = [src0], 3*8)
-EK(.ex_handler, (p[D]) ld8 t10 = [src1], 8)
-EX(.ex_handler, (p[D]) st8 [dst0] = t5, 8)
-EK(.ex_handler, (p[D]) st8 [dst1] = t7, 3*8)
- ;;
-EX(.ex_handler, (p[D]) ld8 t9 = [src0], 3*8)
-EK(.ex_handler, (p[D]) ld8 t11 = [src1], 3*8)
-EX(.ex_handler, (p[D]) st8 [dst0] = t6, 3*8)
-EK(.ex_handler, (p[D]) st8 [dst1] = t10, 8)
- ;;
-EX(.ex_handler, (p[D]) ld8 t12 = [src0], 8)
-EK(.ex_handler, (p[D]) ld8 t14 = [src1], 8)
-EX(.ex_handler, (p[D]) st8 [dst0] = t9, 3*8)
-EK(.ex_handler, (p[D]) st8 [dst1] = t11, 3*8)
- ;;
-EX(.ex_handler, (p[D]) ld8 t13 = [src0], 4*8)
-EK(.ex_handler, (p[D]) ld8 t15 = [src1], 4*8)
-EX(.ex_handler, (p[D]) st8 [dst0] = t12, 8)
-EK(.ex_handler, (p[D]) st8 [dst1] = t14, 8)
- ;;
-EX(.ex_handler, (p[C]) ld8 t1 = [src0], 8)
-EK(.ex_handler, (p[C]) ld8 t3 = [src1], 8)
-EX(.ex_handler, (p[D]) st8 [dst0] = t13, 4*8)
-EK(.ex_handler, (p[D]) st8 [dst1] = t15, 4*8)
- br.ctop.sptk .line_copy
- ;;
-
- add dst0=-8,dst0
- add src0=-8,src0
- mov in2=tmp
- .restore sp
- br.sptk.many .medium_copy
- ;;
-
-#define BLOCK_SIZE 128*32
-#define blocksize r23
-#define curlen r24
-
-// dest is on 8-byte boundary, src is not. We need to do
-// ld8-ld8, shrp, then st8. Max 8 byte copy per cycle.
-.unaligned_src:
- .prologue
- .save ar.pfs, saved_pfs
- alloc saved_pfs=ar.pfs,3,5,0,8
- .save ar.lc, saved_lc
- mov saved_lc=ar.lc
- .save pr, saved_pr
- mov saved_pr=pr
- .body
-.4k_block:
- mov saved_in0=dst0 // need to save all input arguments
- mov saved_in2=in2
- mov blocksize=BLOCK_SIZE
- ;;
- cmp.lt p6,p7=blocksize,in2
- mov saved_in1=src0
- ;;
-(p6) mov in2=blocksize
- ;;
- shr.u r21=in2,7 // this much cache line
- shr.u r22=in2,4 // number of 16-byte iteration
- and curlen=15,in2 // copy length after iteration
- and r30=7,src0 // source alignment
- ;;
- cmp.lt p7,p8=1,r21
- add cnt=-1,r21
- ;;
-
- add src_pre_mem=0,src0 // prefetch src pointer
- add dst_pre_mem=0,dst0 // prefetch dest pointer
- and src0=-8,src0 // 1st src pointer
-(p7) mov ar.lc = cnt
-(p8) mov ar.lc = r0
- ;;
- TEXT_ALIGN(32)
-1: lfetch.fault [src_pre_mem], 128
- lfetch.fault.excl [dst_pre_mem], 128
- br.cloop.dptk.few 1b
- ;;
-
- shladd dst1=r22,3,dst0 // 2nd dest pointer
- shladd src1=r22,3,src0 // 2nd src pointer
- cmp.eq p8,p9=r22,r0 // do we really need to loop?
- cmp.le p6,p7=8,curlen; // have at least 8 byte remaining?
- add cnt=-1,r22 // ctop iteration adjustment
- ;;
-EX(.ex_handler, (p9) ld8 r33=[src0],8) // loop primer
-EK(.ex_handler, (p9) ld8 r37=[src1],8)
-(p8) br.dpnt.few .noloop
- ;;
-
-// The jump address is calculated based on src alignment. The COPYU
-// macro below need to confine its size to power of two, so an entry
-// can be caulated using shl instead of an expensive multiply. The
-// size is then hard coded by the following #define to match the
-// actual size. This make it somewhat tedious when COPYU macro gets
-// changed and this need to be adjusted to match.
-#define LOOP_SIZE 6
-1:
- mov r29=ip // jmp_table thread
- mov ar.lc=cnt
- ;;
- add r29=.jump_table - 1b - (.jmp1-.jump_table), r29
- shl r28=r30, LOOP_SIZE // jmp_table thread
- mov ar.ec=2 // loop setup
- ;;
- add r29=r29,r28 // jmp_table thread
- cmp.eq p16,p17=r0,r0
- ;;
- mov b6=r29 // jmp_table thread
- ;;
- br.cond.sptk.few b6
-
-// for 8-15 byte case
-// We will skip the loop, but need to replicate the side effect
-// that the loop produces.
-.noloop:
-EX(.ex_handler, (p6) ld8 r37=[src1],8)
- add src0=8,src0
-(p6) shl r25=r30,3
- ;;
-EX(.ex_handler, (p6) ld8 r27=[src1])
-(p6) shr.u r28=r37,r25
-(p6) sub r26=64,r25
- ;;
-(p6) shl r27=r27,r26
- ;;
-(p6) or r21=r28,r27
-
-.unaligned_src_tail:
-/* check if we have more than blocksize to copy, if so go back */
- cmp.gt p8,p0=saved_in2,blocksize
- ;;
-(p8) add dst0=saved_in0,blocksize
-(p8) add src0=saved_in1,blocksize
-(p8) sub in2=saved_in2,blocksize
-(p8) br.dpnt .4k_block
- ;;
-
-/* we have up to 15 byte to copy in the tail.
- * part of work is already done in the jump table code
- * we are at the following state.
- * src side:
- *
- * xxxxxx xx <----- r21 has xxxxxxxx already
- * -------- -------- --------
- * 0 8 16
- * ^
- * |
- * src1
- *
- * dst
- * -------- -------- --------
- * ^
- * |
- * dst1
- */
-EX(.ex_handler, (p6) st8 [dst1]=r21,8) // more than 8 byte to copy
-(p6) add curlen=-8,curlen // update length
- mov ar.pfs=saved_pfs
- ;;
- mov ar.lc=saved_lc
- mov pr=saved_pr,-1
- mov in2=curlen // remaining length
- mov dst0=dst1 // dest pointer
- add src0=src1,r30 // forward by src alignment
- ;;
-
-// 7 byte or smaller.
-.memcpy_short:
- cmp.le p8,p9 = 1,in2
- cmp.le p10,p11 = 2,in2
- cmp.le p12,p13 = 3,in2
- cmp.le p14,p15 = 4,in2
- add src1=1,src0 // second src pointer
- add dst1=1,dst0 // second dest pointer
- ;;
-
-EX(.ex_handler_short, (p8) ld1 t1=[src0],2)
-EK(.ex_handler_short, (p10) ld1 t2=[src1],2)
-(p9) br.ret.dpnt rp // 0 byte copy
- ;;
-
-EX(.ex_handler_short, (p8) st1 [dst0]=t1,2)
-EK(.ex_handler_short, (p10) st1 [dst1]=t2,2)
-(p11) br.ret.dpnt rp // 1 byte copy
-
-EX(.ex_handler_short, (p12) ld1 t3=[src0],2)
-EK(.ex_handler_short, (p14) ld1 t4=[src1],2)
-(p13) br.ret.dpnt rp // 2 byte copy
- ;;
-
- cmp.le p6,p7 = 5,in2
- cmp.le p8,p9 = 6,in2
- cmp.le p10,p11 = 7,in2
-
-EX(.ex_handler_short, (p12) st1 [dst0]=t3,2)
-EK(.ex_handler_short, (p14) st1 [dst1]=t4,2)
-(p15) br.ret.dpnt rp // 3 byte copy
- ;;
-
-EX(.ex_handler_short, (p6) ld1 t5=[src0],2)
-EK(.ex_handler_short, (p8) ld1 t6=[src1],2)
-(p7) br.ret.dpnt rp // 4 byte copy
- ;;
-
-EX(.ex_handler_short, (p6) st1 [dst0]=t5,2)
-EK(.ex_handler_short, (p8) st1 [dst1]=t6,2)
-(p9) br.ret.dptk rp // 5 byte copy
-
-EX(.ex_handler_short, (p10) ld1 t7=[src0],2)
-(p11) br.ret.dptk rp // 6 byte copy
- ;;
-
-EX(.ex_handler_short, (p10) st1 [dst0]=t7,2)
- br.ret.dptk rp // done all cases
-
-
-/* Align dest to nearest 8-byte boundary. We know we have at
- * least 7 bytes to copy, enough to crawl to 8-byte boundary.
- * Actual number of byte to crawl depend on the dest alignment.
- * 7 byte or less is taken care at .memcpy_short
-
- * src0 - source even index
- * src1 - source odd index
- * dst0 - dest even index
- * dst1 - dest odd index
- * r30 - distance to 8-byte boundary
- */
-
-.align_dest:
- add src1=1,in1 // source odd index
- cmp.le p7,p0 = 2,r30 // for .align_dest
- cmp.le p8,p0 = 3,r30 // for .align_dest
-EX(.ex_handler_short, (p6) ld1 t1=[src0],2)
- cmp.le p9,p0 = 4,r30 // for .align_dest
- cmp.le p10,p0 = 5,r30
- ;;
-EX(.ex_handler_short, (p7) ld1 t2=[src1],2)
-EK(.ex_handler_short, (p8) ld1 t3=[src0],2)
- cmp.le p11,p0 = 6,r30
-EX(.ex_handler_short, (p6) st1 [dst0] = t1,2)
- cmp.le p12,p0 = 7,r30
- ;;
-EX(.ex_handler_short, (p9) ld1 t4=[src1],2)
-EK(.ex_handler_short, (p10) ld1 t5=[src0],2)
-EX(.ex_handler_short, (p7) st1 [dst1] = t2,2)
-EK(.ex_handler_short, (p8) st1 [dst0] = t3,2)
- ;;
-EX(.ex_handler_short, (p11) ld1 t6=[src1],2)
-EK(.ex_handler_short, (p12) ld1 t7=[src0],2)
- cmp.eq p6,p7=r28,r29
-EX(.ex_handler_short, (p9) st1 [dst1] = t4,2)
-EK(.ex_handler_short, (p10) st1 [dst0] = t5,2)
- sub in2=in2,r30
- ;;
-EX(.ex_handler_short, (p11) st1 [dst1] = t6,2)
-EK(.ex_handler_short, (p12) st1 [dst0] = t7)
- add dst0=in0,r30 // setup arguments
- add src0=in1,r30
-(p6) br.cond.dptk .aligned_src
-(p7) br.cond.dpnt .unaligned_src
- ;;
-
-/* main loop body in jump table format */
-#define COPYU(shift) \
-1: \
-EX(.ex_handler, (p16) ld8 r32=[src0],8); /* 1 */ \
-EK(.ex_handler, (p16) ld8 r36=[src1],8); \
- (p17) shrp r35=r33,r34,shift;; /* 1 */ \
-EX(.ex_handler, (p6) ld8 r22=[src1]); /* common, prime for tail section */ \
- nop.m 0; \
- (p16) shrp r38=r36,r37,shift; \
-EX(.ex_handler, (p17) st8 [dst0]=r35,8); /* 1 */ \
-EK(.ex_handler, (p17) st8 [dst1]=r39,8); \
- br.ctop.dptk.few 1b;; \
- (p7) add src1=-8,src1; /* back out for <8 byte case */ \
- shrp r21=r22,r38,shift; /* speculative work */ \
- br.sptk.few .unaligned_src_tail /* branch out of jump table */ \
- ;;
- TEXT_ALIGN(32)
-.jump_table:
- COPYU(8) // unaligned cases
-.jmp1:
- COPYU(16)
- COPYU(24)
- COPYU(32)
- COPYU(40)
- COPYU(48)
- COPYU(56)
-
-#undef A
-#undef B
-#undef C
-#undef D
-
-/*
- * Due to lack of local tag support in gcc 2.x assembler, it is not clear which
- * instruction failed in the bundle. The exception algorithm is that we
- * first figure out the faulting address, then detect if there is any
- * progress made on the copy, if so, redo the copy from last known copied
- * location up to the faulting address (exclusive). In the copy_from_user
- * case, remaining byte in kernel buffer will be zeroed.
- *
- * Take copy_from_user as an example, in the code there are multiple loads
- * in a bundle and those multiple loads could span over two pages, the
- * faulting address is calculated as page_round_down(max(src0, src1)).
- * This is based on knowledge that if we can access one byte in a page, we
- * can access any byte in that page.
- *
- * predicate used in the exception handler:
- * p6-p7: direction
- * p10-p11: src faulting addr calculation
- * p12-p13: dst faulting addr calculation
- */
-
-#define A r19
-#define B r20
-#define C r21
-#define D r22
-#define F r28
-
-#define saved_retval loc0
-#define saved_rtlink loc1
-#define saved_pfs_stack loc2
-
-.ex_hndlr_s:
- add src0=8,src0
- br.sptk .ex_handler
- ;;
-.ex_hndlr_d:
- add dst0=8,dst0
- br.sptk .ex_handler
- ;;
-.ex_hndlr_lcpy_1:
- mov src1=src_pre_mem
- mov dst1=dst_pre_mem
- cmp.gtu p10,p11=src_pre_mem,saved_in1
- cmp.gtu p12,p13=dst_pre_mem,saved_in0
- ;;
-(p10) add src0=8,saved_in1
-(p11) mov src0=saved_in1
-(p12) add dst0=8,saved_in0
-(p13) mov dst0=saved_in0
- br.sptk .ex_handler
-.ex_handler_lcpy:
- // in line_copy block, the preload addresses should always ahead
- // of the other two src/dst pointers. Furthermore, src1/dst1 should
- // always ahead of src0/dst0.
- mov src1=src_pre_mem
- mov dst1=dst_pre_mem
-.ex_handler:
- mov pr=saved_pr,-1 // first restore pr, lc, and pfs
- mov ar.lc=saved_lc
- mov ar.pfs=saved_pfs
- ;;
-.ex_handler_short: // fault occurred in these sections didn't change pr, lc, pfs
- cmp.ltu p6,p7=saved_in0, saved_in1 // get the copy direction
- cmp.ltu p10,p11=src0,src1
- cmp.ltu p12,p13=dst0,dst1
- fcmp.eq p8,p0=f6,f0 // is it memcpy?
- mov tmp = dst0
- ;;
-(p11) mov src1 = src0 // pick the larger of the two
-(p13) mov dst0 = dst1 // make dst0 the smaller one
-(p13) mov dst1 = tmp // and dst1 the larger one
- ;;
-(p6) dep F = r0,dst1,0,PAGE_SHIFT // usr dst round down to page boundary
-(p7) dep F = r0,src1,0,PAGE_SHIFT // usr src round down to page boundary
- ;;
-(p6) cmp.le p14,p0=dst0,saved_in0 // no progress has been made on store
-(p7) cmp.le p14,p0=src0,saved_in1 // no progress has been made on load
- mov retval=saved_in2
-(p8) ld1 tmp=[src1] // force an oops for memcpy call
-(p8) st1 [dst1]=r0 // force an oops for memcpy call
-(p14) br.ret.sptk.many rp
-
-/*
- * The remaining byte to copy is calculated as:
- *
- * A = (faulting_addr - orig_src) -> len to faulting ld address
- * or
- * (faulting_addr - orig_dst) -> len to faulting st address
- * B = (cur_dst - orig_dst) -> len copied so far
- * C = A - B -> len need to be copied
- * D = orig_len - A -> len need to be left along
- */
-(p6) sub A = F, saved_in0
-(p7) sub A = F, saved_in1
- clrrrb
- ;;
- alloc saved_pfs_stack=ar.pfs,3,3,3,0
- cmp.lt p8,p0=A,r0
- sub B = dst0, saved_in0 // how many byte copied so far
- ;;
-(p8) mov A = 0; // A shouldn't be negative, cap it
- ;;
- sub C = A, B
- sub D = saved_in2, A
- ;;
- cmp.gt p8,p0=C,r0 // more than 1 byte?
- mov r8=0
- mov saved_retval = D
- mov saved_rtlink = b0
-
- add out0=saved_in0, B
- add out1=saved_in1, B
- mov out2=C
-(p8) br.call.sptk.few b0=__copy_user // recursive call
- ;;
-
- add saved_retval=saved_retval,r8 // above might return non-zero value
- ;;
-
- mov retval=saved_retval
- mov ar.pfs=saved_pfs_stack
- mov b0=saved_rtlink
- br.ret.sptk.many rp
-
-/* end of McKinley specific optimization */
-END(__copy_user)
-EXPORT_SYMBOL(__copy_user)
diff --git a/arch/ia64/lib/memset.S b/arch/ia64/lib/memset.S
deleted file mode 100644
index 552c5c7e4d06..000000000000
--- a/arch/ia64/lib/memset.S
+++ /dev/null
@@ -1,365 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Optimized version of the standard memset() function.
-
- Copyright (c) 2002 Hewlett-Packard Co/CERN
- Sverre Jarp <Sverre.Jarp@cern.ch>
-
- Return: dest
-
- Inputs:
- in0: dest
- in1: value
- in2: count
-
- The algorithm is fairly straightforward: set byte by byte until we
- we get to a 16B-aligned address, then loop on 128 B chunks using an
- early store as prefetching, then loop on 32B chucks, then clear remaining
- words, finally clear remaining bytes.
- Since a stf.spill f0 can store 16B in one go, we use this instruction
- to get peak speed when value = 0. */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-#undef ret
-
-#define dest in0
-#define value in1
-#define cnt in2
-
-#define tmp r31
-#define save_lc r30
-#define ptr0 r29
-#define ptr1 r28
-#define ptr2 r27
-#define ptr3 r26
-#define ptr9 r24
-#define loopcnt r23
-#define linecnt r22
-#define bytecnt r21
-
-#define fvalue f6
-
-// This routine uses only scratch predicate registers (p6 - p15)
-#define p_scr p6 // default register for same-cycle branches
-#define p_nz p7
-#define p_zr p8
-#define p_unalgn p9
-#define p_y p11
-#define p_n p12
-#define p_yy p13
-#define p_nn p14
-
-#define MIN1 15
-#define MIN1P1HALF 8
-#define LINE_SIZE 128
-#define LSIZE_SH 7 // shift amount
-#define PREF_AHEAD 8
-
-GLOBAL_ENTRY(memset)
-{ .mmi
- .prologue
- alloc tmp = ar.pfs, 3, 0, 0, 0
- lfetch.nt1 [dest] //
- .save ar.lc, save_lc
- mov.i save_lc = ar.lc
- .body
-} { .mmi
- mov ret0 = dest // return value
- cmp.ne p_nz, p_zr = value, r0 // use stf.spill if value is zero
- cmp.eq p_scr, p0 = cnt, r0
-;; }
-{ .mmi
- and ptr2 = -(MIN1+1), dest // aligned address
- and tmp = MIN1, dest // prepare to check for correct alignment
- tbit.nz p_y, p_n = dest, 0 // Do we have an odd address? (M_B_U)
-} { .mib
- mov ptr1 = dest
- mux1 value = value, @brcst // create 8 identical bytes in word
-(p_scr) br.ret.dpnt.many rp // return immediately if count = 0
-;; }
-{ .mib
- cmp.ne p_unalgn, p0 = tmp, r0 //
-} { .mib
- sub bytecnt = (MIN1+1), tmp // NB: # of bytes to move is 1 higher than loopcnt
- cmp.gt p_scr, p0 = 16, cnt // is it a minimalistic task?
-(p_scr) br.cond.dptk.many .move_bytes_unaligned // go move just a few (M_B_U)
-;; }
-{ .mmi
-(p_unalgn) add ptr1 = (MIN1+1), ptr2 // after alignment
-(p_unalgn) add ptr2 = MIN1P1HALF, ptr2 // after alignment
-(p_unalgn) tbit.nz.unc p_y, p_n = bytecnt, 3 // should we do a st8 ?
-;; }
-{ .mib
-(p_y) add cnt = -8, cnt //
-(p_unalgn) tbit.nz.unc p_yy, p_nn = bytecnt, 2 // should we do a st4 ?
-} { .mib
-(p_y) st8 [ptr2] = value,-4 //
-(p_n) add ptr2 = 4, ptr2 //
-;; }
-{ .mib
-(p_yy) add cnt = -4, cnt //
-(p_unalgn) tbit.nz.unc p_y, p_n = bytecnt, 1 // should we do a st2 ?
-} { .mib
-(p_yy) st4 [ptr2] = value,-2 //
-(p_nn) add ptr2 = 2, ptr2 //
-;; }
-{ .mmi
- mov tmp = LINE_SIZE+1 // for compare
-(p_y) add cnt = -2, cnt //
-(p_unalgn) tbit.nz.unc p_yy, p_nn = bytecnt, 0 // should we do a st1 ?
-} { .mmi
- setf.sig fvalue=value // transfer value to FLP side
-(p_y) st2 [ptr2] = value,-1 //
-(p_n) add ptr2 = 1, ptr2 //
-;; }
-
-{ .mmi
-(p_yy) st1 [ptr2] = value //
- cmp.gt p_scr, p0 = tmp, cnt // is it a minimalistic task?
-} { .mbb
-(p_yy) add cnt = -1, cnt //
-(p_scr) br.cond.dpnt.many .fraction_of_line // go move just a few
-;; }
-
-{ .mib
- nop.m 0
- shr.u linecnt = cnt, LSIZE_SH
-(p_zr) br.cond.dptk.many .l1b // Jump to use stf.spill
-;; }
-
- TEXT_ALIGN(32) // --------------------- // L1A: store ahead into cache lines; fill later
-{ .mmi
- and tmp = -(LINE_SIZE), cnt // compute end of range
- mov ptr9 = ptr1 // used for prefetching
- and cnt = (LINE_SIZE-1), cnt // remainder
-} { .mmi
- mov loopcnt = PREF_AHEAD-1 // default prefetch loop
- cmp.gt p_scr, p0 = PREF_AHEAD, linecnt // check against actual value
-;; }
-{ .mmi
-(p_scr) add loopcnt = -1, linecnt //
- add ptr2 = 8, ptr1 // start of stores (beyond prefetch stores)
- add ptr1 = tmp, ptr1 // first address beyond total range
-;; }
-{ .mmi
- add tmp = -1, linecnt // next loop count
- mov.i ar.lc = loopcnt //
-;; }
-.pref_l1a:
-{ .mib
- stf8 [ptr9] = fvalue, 128 // Do stores one cache line apart
- nop.i 0
- br.cloop.dptk.few .pref_l1a
-;; }
-{ .mmi
- add ptr0 = 16, ptr2 // Two stores in parallel
- mov.i ar.lc = tmp //
-;; }
-.l1ax:
- { .mmi
- stf8 [ptr2] = fvalue, 8
- stf8 [ptr0] = fvalue, 8
- ;; }
- { .mmi
- stf8 [ptr2] = fvalue, 24
- stf8 [ptr0] = fvalue, 24
- ;; }
- { .mmi
- stf8 [ptr2] = fvalue, 8
- stf8 [ptr0] = fvalue, 8
- ;; }
- { .mmi
- stf8 [ptr2] = fvalue, 24
- stf8 [ptr0] = fvalue, 24
- ;; }
- { .mmi
- stf8 [ptr2] = fvalue, 8
- stf8 [ptr0] = fvalue, 8
- ;; }
- { .mmi
- stf8 [ptr2] = fvalue, 24
- stf8 [ptr0] = fvalue, 24
- ;; }
- { .mmi
- stf8 [ptr2] = fvalue, 8
- stf8 [ptr0] = fvalue, 32
- cmp.lt p_scr, p0 = ptr9, ptr1 // do we need more prefetching?
- ;; }
-{ .mmb
- stf8 [ptr2] = fvalue, 24
-(p_scr) stf8 [ptr9] = fvalue, 128
- br.cloop.dptk.few .l1ax
-;; }
-{ .mbb
- cmp.le p_scr, p0 = 8, cnt // just a few bytes left ?
-(p_scr) br.cond.dpnt.many .fraction_of_line // Branch no. 2
- br.cond.dpnt.many .move_bytes_from_alignment // Branch no. 3
-;; }
-
- TEXT_ALIGN(32)
-.l1b: // ------------------------------------ // L1B: store ahead into cache lines; fill later
-{ .mmi
- and tmp = -(LINE_SIZE), cnt // compute end of range
- mov ptr9 = ptr1 // used for prefetching
- and cnt = (LINE_SIZE-1), cnt // remainder
-} { .mmi
- mov loopcnt = PREF_AHEAD-1 // default prefetch loop
- cmp.gt p_scr, p0 = PREF_AHEAD, linecnt // check against actual value
-;; }
-{ .mmi
-(p_scr) add loopcnt = -1, linecnt
- add ptr2 = 16, ptr1 // start of stores (beyond prefetch stores)
- add ptr1 = tmp, ptr1 // first address beyond total range
-;; }
-{ .mmi
- add tmp = -1, linecnt // next loop count
- mov.i ar.lc = loopcnt
-;; }
-.pref_l1b:
-{ .mib
- stf.spill [ptr9] = f0, 128 // Do stores one cache line apart
- nop.i 0
- br.cloop.dptk.few .pref_l1b
-;; }
-{ .mmi
- add ptr0 = 16, ptr2 // Two stores in parallel
- mov.i ar.lc = tmp
-;; }
-.l1bx:
- { .mmi
- stf.spill [ptr2] = f0, 32
- stf.spill [ptr0] = f0, 32
- ;; }
- { .mmi
- stf.spill [ptr2] = f0, 32
- stf.spill [ptr0] = f0, 32
- ;; }
- { .mmi
- stf.spill [ptr2] = f0, 32
- stf.spill [ptr0] = f0, 64
- cmp.lt p_scr, p0 = ptr9, ptr1 // do we need more prefetching?
- ;; }
-{ .mmb
- stf.spill [ptr2] = f0, 32
-(p_scr) stf.spill [ptr9] = f0, 128
- br.cloop.dptk.few .l1bx
-;; }
-{ .mib
- cmp.gt p_scr, p0 = 8, cnt // just a few bytes left ?
-(p_scr) br.cond.dpnt.many .move_bytes_from_alignment //
-;; }
-
-.fraction_of_line:
-{ .mib
- add ptr2 = 16, ptr1
- shr.u loopcnt = cnt, 5 // loopcnt = cnt / 32
-;; }
-{ .mib
- cmp.eq p_scr, p0 = loopcnt, r0
- add loopcnt = -1, loopcnt
-(p_scr) br.cond.dpnt.many .store_words
-;; }
-{ .mib
- and cnt = 0x1f, cnt // compute the remaining cnt
- mov.i ar.lc = loopcnt
-;; }
- TEXT_ALIGN(32)
-.l2: // ------------------------------------ // L2A: store 32B in 2 cycles
-{ .mmb
- stf8 [ptr1] = fvalue, 8
- stf8 [ptr2] = fvalue, 8
-;; } { .mmb
- stf8 [ptr1] = fvalue, 24
- stf8 [ptr2] = fvalue, 24
- br.cloop.dptk.many .l2
-;; }
-.store_words:
-{ .mib
- cmp.gt p_scr, p0 = 8, cnt // just a few bytes left ?
-(p_scr) br.cond.dpnt.many .move_bytes_from_alignment // Branch
-;; }
-
-{ .mmi
- stf8 [ptr1] = fvalue, 8 // store
- cmp.le p_y, p_n = 16, cnt
- add cnt = -8, cnt // subtract
-;; }
-{ .mmi
-(p_y) stf8 [ptr1] = fvalue, 8 // store
-(p_y) cmp.le.unc p_yy, p_nn = 16, cnt
-(p_y) add cnt = -8, cnt // subtract
-;; }
-{ .mmi // store
-(p_yy) stf8 [ptr1] = fvalue, 8
-(p_yy) add cnt = -8, cnt // subtract
-;; }
-
-.move_bytes_from_alignment:
-{ .mib
- cmp.eq p_scr, p0 = cnt, r0
- tbit.nz.unc p_y, p0 = cnt, 2 // should we terminate with a st4 ?
-(p_scr) br.cond.dpnt.few .restore_and_exit
-;; }
-{ .mib
-(p_y) st4 [ptr1] = value,4
- tbit.nz.unc p_yy, p0 = cnt, 1 // should we terminate with a st2 ?
-;; }
-{ .mib
-(p_yy) st2 [ptr1] = value,2
- tbit.nz.unc p_y, p0 = cnt, 0 // should we terminate with a st1 ?
-;; }
-
-{ .mib
-(p_y) st1 [ptr1] = value
-;; }
-.restore_and_exit:
-{ .mib
- nop.m 0
- mov.i ar.lc = save_lc
- br.ret.sptk.many rp
-;; }
-
-.move_bytes_unaligned:
-{ .mmi
- .pred.rel "mutex",p_y, p_n
- .pred.rel "mutex",p_yy, p_nn
-(p_n) cmp.le p_yy, p_nn = 4, cnt
-(p_y) cmp.le p_yy, p_nn = 5, cnt
-(p_n) add ptr2 = 2, ptr1
-} { .mmi
-(p_y) add ptr2 = 3, ptr1
-(p_y) st1 [ptr1] = value, 1 // fill 1 (odd-aligned) byte [15, 14 (or less) left]
-(p_y) add cnt = -1, cnt
-;; }
-{ .mmi
-(p_yy) cmp.le.unc p_y, p0 = 8, cnt
- add ptr3 = ptr1, cnt // prepare last store
- mov.i ar.lc = save_lc
-} { .mmi
-(p_yy) st2 [ptr1] = value, 4 // fill 2 (aligned) bytes
-(p_yy) st2 [ptr2] = value, 4 // fill 2 (aligned) bytes [11, 10 (o less) left]
-(p_yy) add cnt = -4, cnt
-;; }
-{ .mmi
-(p_y) cmp.le.unc p_yy, p0 = 8, cnt
- add ptr3 = -1, ptr3 // last store
- tbit.nz p_scr, p0 = cnt, 1 // will there be a st2 at the end ?
-} { .mmi
-(p_y) st2 [ptr1] = value, 4 // fill 2 (aligned) bytes
-(p_y) st2 [ptr2] = value, 4 // fill 2 (aligned) bytes [7, 6 (or less) left]
-(p_y) add cnt = -4, cnt
-;; }
-{ .mmi
-(p_yy) st2 [ptr1] = value, 4 // fill 2 (aligned) bytes
-(p_yy) st2 [ptr2] = value, 4 // fill 2 (aligned) bytes [3, 2 (or less) left]
- tbit.nz p_y, p0 = cnt, 0 // will there be a st1 at the end ?
-} { .mmi
-(p_yy) add cnt = -4, cnt
-;; }
-{ .mmb
-(p_scr) st2 [ptr1] = value // fill 2 (aligned) bytes
-(p_y) st1 [ptr3] = value // fill last byte (using ptr3)
- br.ret.sptk.many rp
-}
-END(memset)
-EXPORT_SYMBOL(memset)
diff --git a/arch/ia64/lib/strlen.S b/arch/ia64/lib/strlen.S
deleted file mode 100644
index 1f4a46c15127..000000000000
--- a/arch/ia64/lib/strlen.S
+++ /dev/null
@@ -1,195 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *
- * Optimized version of the standard strlen() function
- *
- *
- * Inputs:
- * in0 address of string
- *
- * Outputs:
- * ret0 the number of characters in the string (0 if empty string)
- * does not count the \0
- *
- * Copyright (C) 1999, 2001 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- *
- * 09/24/99 S.Eranian add speculation recovery code
- */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-
-//
-//
-// This is an enhanced version of the basic strlen. it includes a combination
-// of compute zero index (czx), parallel comparisons, speculative loads and
-// loop unroll using rotating registers.
-//
-// General Ideas about the algorithm:
-// The goal is to look at the string in chunks of 8 bytes.
-// so we need to do a few extra checks at the beginning because the
-// string may not be 8-byte aligned. In this case we load the 8byte
-// quantity which includes the start of the string and mask the unused
-// bytes with 0xff to avoid confusing czx.
-// We use speculative loads and software pipelining to hide memory
-// latency and do read ahead safely. This way we defer any exception.
-//
-// Because we don't want the kernel to be relying on particular
-// settings of the DCR register, we provide recovery code in case
-// speculation fails. The recovery code is going to "redo" the work using
-// only normal loads. If we still get a fault then we generate a
-// kernel panic. Otherwise we return the strlen as usual.
-//
-// The fact that speculation may fail can be caused, for instance, by
-// the DCR.dm bit being set. In this case TLB misses are deferred, i.e.,
-// a NaT bit will be set if the translation is not present. The normal
-// load, on the other hand, will cause the translation to be inserted
-// if the mapping exists.
-//
-// It should be noted that we execute recovery code only when we need
-// to use the data that has been speculatively loaded: we don't execute
-// recovery code on pure read ahead data.
-//
-// Remarks:
-// - the cmp r0,r0 is used as a fast way to initialize a predicate
-// register to 1. This is required to make sure that we get the parallel
-// compare correct.
-//
-// - we don't use the epilogue counter to exit the loop but we need to set
-// it to zero beforehand.
-//
-// - after the loop we must test for Nat values because neither the
-// czx nor cmp instruction raise a NaT consumption fault. We must be
-// careful not to look too far for a Nat for which we don't care.
-// For instance we don't need to look at a NaT in val2 if the zero byte
-// was in val1.
-//
-// - Clearly performance tuning is required.
-//
-//
-//
-#define saved_pfs r11
-#define tmp r10
-#define base r16
-#define orig r17
-#define saved_pr r18
-#define src r19
-#define mask r20
-#define val r21
-#define val1 r22
-#define val2 r23
-
-GLOBAL_ENTRY(strlen)
- .prologue
- .save ar.pfs, saved_pfs
- alloc saved_pfs=ar.pfs,11,0,0,8 // rotating must be multiple of 8
-
- .rotr v[2], w[2] // declares our 4 aliases
-
- extr.u tmp=in0,0,3 // tmp=least significant 3 bits
- mov orig=in0 // keep trackof initial byte address
- dep src=0,in0,0,3 // src=8byte-aligned in0 address
- .save pr, saved_pr
- mov saved_pr=pr // preserve predicates (rotation)
- ;;
-
- .body
-
- ld8 v[1]=[src],8 // must not speculate: can fail here
- shl tmp=tmp,3 // multiply by 8bits/byte
- mov mask=-1 // our mask
- ;;
- ld8.s w[1]=[src],8 // speculatively load next
- cmp.eq p6,p0=r0,r0 // sets p6 to true for cmp.and
- sub tmp=64,tmp // how many bits to shift our mask on the right
- ;;
- shr.u mask=mask,tmp // zero enough bits to hold v[1] valuable part
- mov ar.ec=r0 // clear epilogue counter (saved in ar.pfs)
- ;;
- add base=-16,src // keep track of aligned base
- or v[1]=v[1],mask // now we have a safe initial byte pattern
- ;;
-1:
- ld8.s v[0]=[src],8 // speculatively load next
- czx1.r val1=v[1] // search 0 byte from right
- czx1.r val2=w[1] // search 0 byte from right following 8bytes
- ;;
- ld8.s w[0]=[src],8 // speculatively load next to next
- cmp.eq.and p6,p0=8,val1 // p6 = p6 and val1==8
- cmp.eq.and p6,p0=8,val2 // p6 = p6 and mask==8
-(p6) br.wtop.dptk 1b // loop until p6 == 0
- ;;
- //
- // We must return try the recovery code iff
- // val1_is_nat || (val1==8 && val2_is_nat)
- //
- // XXX Fixme
- // - there must be a better way of doing the test
- //
- cmp.eq p8,p9=8,val1 // p6 = val1 had zero (disambiguate)
- tnat.nz p6,p7=val1 // test NaT on val1
-(p6) br.cond.spnt .recover // jump to recovery if val1 is NaT
- ;;
- //
- // if we come here p7 is true, i.e., initialized for // cmp
- //
- cmp.eq.and p7,p0=8,val1// val1==8?
- tnat.nz.and p7,p0=val2 // test NaT if val2
-(p7) br.cond.spnt .recover // jump to recovery if val2 is NaT
- ;;
-(p8) mov val1=val2 // the other test got us out of the loop
-(p8) adds src=-16,src // correct position when 3 ahead
-(p9) adds src=-24,src // correct position when 4 ahead
- ;;
- sub ret0=src,orig // distance from base
- sub tmp=8,val1 // which byte in word
- mov pr=saved_pr,0xffffffffffff0000
- ;;
- sub ret0=ret0,tmp // adjust
- mov ar.pfs=saved_pfs // because of ar.ec, restore no matter what
- br.ret.sptk.many rp // end of normal execution
-
- //
- // Outlined recovery code when speculation failed
- //
- // This time we don't use speculation and rely on the normal exception
- // mechanism. that's why the loop is not as good as the previous one
- // because read ahead is not possible
- //
- // IMPORTANT:
- // Please note that in the case of strlen() as opposed to strlen_user()
- // we don't use the exception mechanism, as this function is not
- // supposed to fail. If that happens it means we have a bug and the
- // code will cause of kernel fault.
- //
- // XXX Fixme
- // - today we restart from the beginning of the string instead
- // of trying to continue where we left off.
- //
-.recover:
- ld8 val=[base],8 // will fail if unrecoverable fault
- ;;
- or val=val,mask // remask first bytes
- cmp.eq p0,p6=r0,r0 // nullify first ld8 in loop
- ;;
- //
- // ar.ec is still zero here
- //
-2:
-(p6) ld8 val=[base],8 // will fail if unrecoverable fault
- ;;
- czx1.r val1=val // search 0 byte from right
- ;;
- cmp.eq p6,p0=8,val1 // val1==8 ?
-(p6) br.wtop.dptk 2b // loop until p6 == 0
- ;; // (avoid WAW on p63)
- sub ret0=base,orig // distance from base
- sub tmp=8,val1
- mov pr=saved_pr,0xffffffffffff0000
- ;;
- sub ret0=ret0,tmp // length=now - back -1
- mov ar.pfs=saved_pfs // because of ar.ec, restore no matter what
- br.ret.sptk.many rp // end of successful recovery code
-END(strlen)
-EXPORT_SYMBOL(strlen)
diff --git a/arch/ia64/lib/strncpy_from_user.S b/arch/ia64/lib/strncpy_from_user.S
deleted file mode 100644
index a287169bd953..000000000000
--- a/arch/ia64/lib/strncpy_from_user.S
+++ /dev/null
@@ -1,47 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Just like strncpy() except that if a fault occurs during copying,
- * -EFAULT is returned.
- *
- * Inputs:
- * in0: address of destination buffer
- * in1: address of string to be copied
- * in2: length of buffer in bytes
- * Outputs:
- * r8: -EFAULT in case of fault or number of bytes copied if no fault
- *
- * Copyright (C) 1998-2001 Hewlett-Packard Co
- * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * 00/03/06 D. Mosberger Fixed to return proper return value (bug found by
- * by Andreas Schwab <schwab@suse.de>).
- */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-
-GLOBAL_ENTRY(__strncpy_from_user)
- alloc r2=ar.pfs,3,0,0,0
- mov r8=0
- mov r9=in1
- ;;
- add r10=in1,in2
- cmp.eq p6,p0=r0,in2
-(p6) br.ret.spnt.many rp
-
- // XXX braindead copy loop---this needs to be optimized
-.Loop1:
- EX(.Lexit, ld1 r8=[in1],1)
- ;;
- EX(.Lexit, st1 [in0]=r8,1)
- cmp.ne p6,p7=r8,r0
- ;;
-(p6) cmp.ne.unc p8,p0=in1,r10
-(p8) br.cond.dpnt.few .Loop1
- ;;
-(p6) mov r8=in2 // buffer filled up---return buffer length
-(p7) sub r8=in1,r9,1 // return string length (excluding NUL character)
-[.Lexit:]
- br.ret.sptk.many rp
-END(__strncpy_from_user)
-EXPORT_SYMBOL(__strncpy_from_user)
diff --git a/arch/ia64/lib/strnlen_user.S b/arch/ia64/lib/strnlen_user.S
deleted file mode 100644
index a7eb56e840a9..000000000000
--- a/arch/ia64/lib/strnlen_user.S
+++ /dev/null
@@ -1,48 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Returns 0 if exception before NUL or reaching the supplied limit (N),
- * a value greater than N if the string is longer than the limit, else
- * strlen.
- *
- * Inputs:
- * in0: address of buffer
- * in1: string length limit N
- * Outputs:
- * r8: 0 in case of fault, strlen(buffer)+1 otherwise
- *
- * Copyright (C) 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-
-GLOBAL_ENTRY(__strnlen_user)
- .prologue
- alloc r2=ar.pfs,2,0,0,0
- .save ar.lc, r16
- mov r16=ar.lc // preserve ar.lc
-
- .body
-
- add r3=-1,in1
- ;;
- mov ar.lc=r3
- mov r9=0
- ;;
- // XXX braindead strlen loop---this needs to be optimized
-.Loop1:
- EXCLR(.Lexit, ld1 r8=[in0],1)
- add r9=1,r9
- ;;
- cmp.eq p6,p0=r8,r0
-(p6) br.cond.dpnt .Lexit
- br.cloop.dptk.few .Loop1
-
- add r9=1,in1 // NUL not found---return N+1
- ;;
-.Lexit:
- mov r8=r9
- mov ar.lc=r16 // restore ar.lc
- br.ret.sptk.many rp
-END(__strnlen_user)
-EXPORT_SYMBOL(__strnlen_user)
diff --git a/arch/ia64/lib/xor.S b/arch/ia64/lib/xor.S
deleted file mode 100644
index 6e2a69662c06..000000000000
--- a/arch/ia64/lib/xor.S
+++ /dev/null
@@ -1,181 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * arch/ia64/lib/xor.S
- *
- * Optimized RAID-5 checksumming functions for IA-64.
- */
-
-#include <linux/export.h>
-#include <asm/asmmacro.h>
-
-GLOBAL_ENTRY(xor_ia64_2)
- .prologue
- .fframe 0
- .save ar.pfs, r31
- alloc r31 = ar.pfs, 3, 0, 13, 16
- .save ar.lc, r30
- mov r30 = ar.lc
- .save pr, r29
- mov r29 = pr
- ;;
- .body
- mov r8 = in1
- mov ar.ec = 6 + 2
- shr in0 = in0, 3
- ;;
- adds in0 = -1, in0
- mov r16 = in1
- mov r17 = in2
- ;;
- mov ar.lc = in0
- mov pr.rot = 1 << 16
- ;;
- .rotr s1[6+1], s2[6+1], d[2]
- .rotp p[6+2]
-0:
-(p[0]) ld8.nta s1[0] = [r16], 8
-(p[0]) ld8.nta s2[0] = [r17], 8
-(p[6]) xor d[0] = s1[6], s2[6]
-(p[6+1])st8.nta [r8] = d[1], 8
- nop.f 0
- br.ctop.dptk.few 0b
- ;;
- mov ar.lc = r30
- mov pr = r29, -1
- br.ret.sptk.few rp
-END(xor_ia64_2)
-EXPORT_SYMBOL(xor_ia64_2)
-
-GLOBAL_ENTRY(xor_ia64_3)
- .prologue
- .fframe 0
- .save ar.pfs, r31
- alloc r31 = ar.pfs, 4, 0, 20, 24
- .save ar.lc, r30
- mov r30 = ar.lc
- .save pr, r29
- mov r29 = pr
- ;;
- .body
- mov r8 = in1
- mov ar.ec = 6 + 2
- shr in0 = in0, 3
- ;;
- adds in0 = -1, in0
- mov r16 = in1
- mov r17 = in2
- ;;
- mov r18 = in3
- mov ar.lc = in0
- mov pr.rot = 1 << 16
- ;;
- .rotr s1[6+1], s2[6+1], s3[6+1], d[2]
- .rotp p[6+2]
-0:
-(p[0]) ld8.nta s1[0] = [r16], 8
-(p[0]) ld8.nta s2[0] = [r17], 8
-(p[6]) xor d[0] = s1[6], s2[6]
- ;;
-(p[0]) ld8.nta s3[0] = [r18], 8
-(p[6+1])st8.nta [r8] = d[1], 8
-(p[6]) xor d[0] = d[0], s3[6]
- br.ctop.dptk.few 0b
- ;;
- mov ar.lc = r30
- mov pr = r29, -1
- br.ret.sptk.few rp
-END(xor_ia64_3)
-EXPORT_SYMBOL(xor_ia64_3)
-
-GLOBAL_ENTRY(xor_ia64_4)
- .prologue
- .fframe 0
- .save ar.pfs, r31
- alloc r31 = ar.pfs, 5, 0, 27, 32
- .save ar.lc, r30
- mov r30 = ar.lc
- .save pr, r29
- mov r29 = pr
- ;;
- .body
- mov r8 = in1
- mov ar.ec = 6 + 2
- shr in0 = in0, 3
- ;;
- adds in0 = -1, in0
- mov r16 = in1
- mov r17 = in2
- ;;
- mov r18 = in3
- mov ar.lc = in0
- mov pr.rot = 1 << 16
- mov r19 = in4
- ;;
- .rotr s1[6+1], s2[6+1], s3[6+1], s4[6+1], d[2]
- .rotp p[6+2]
-0:
-(p[0]) ld8.nta s1[0] = [r16], 8
-(p[0]) ld8.nta s2[0] = [r17], 8
-(p[6]) xor d[0] = s1[6], s2[6]
-(p[0]) ld8.nta s3[0] = [r18], 8
-(p[0]) ld8.nta s4[0] = [r19], 8
-(p[6]) xor r20 = s3[6], s4[6]
- ;;
-(p[6+1])st8.nta [r8] = d[1], 8
-(p[6]) xor d[0] = d[0], r20
- br.ctop.dptk.few 0b
- ;;
- mov ar.lc = r30
- mov pr = r29, -1
- br.ret.sptk.few rp
-END(xor_ia64_4)
-EXPORT_SYMBOL(xor_ia64_4)
-
-GLOBAL_ENTRY(xor_ia64_5)
- .prologue
- .fframe 0
- .save ar.pfs, r31
- alloc r31 = ar.pfs, 6, 0, 34, 40
- .save ar.lc, r30
- mov r30 = ar.lc
- .save pr, r29
- mov r29 = pr
- ;;
- .body
- mov r8 = in1
- mov ar.ec = 6 + 2
- shr in0 = in0, 3
- ;;
- adds in0 = -1, in0
- mov r16 = in1
- mov r17 = in2
- ;;
- mov r18 = in3
- mov ar.lc = in0
- mov pr.rot = 1 << 16
- mov r19 = in4
- mov r20 = in5
- ;;
- .rotr s1[6+1], s2[6+1], s3[6+1], s4[6+1], s5[6+1], d[2]
- .rotp p[6+2]
-0:
-(p[0]) ld8.nta s1[0] = [r16], 8
-(p[0]) ld8.nta s2[0] = [r17], 8
-(p[6]) xor d[0] = s1[6], s2[6]
-(p[0]) ld8.nta s3[0] = [r18], 8
-(p[0]) ld8.nta s4[0] = [r19], 8
-(p[6]) xor r21 = s3[6], s4[6]
- ;;
-(p[0]) ld8.nta s5[0] = [r20], 8
-(p[6+1])st8.nta [r8] = d[1], 8
-(p[6]) xor d[0] = d[0], r21
- ;;
-(p[6]) xor d[0] = d[0], s5[6]
- nop.f 0
- br.ctop.dptk.few 0b
- ;;
- mov ar.lc = r30
- mov pr = r29, -1
- br.ret.sptk.few rp
-END(xor_ia64_5)
-EXPORT_SYMBOL(xor_ia64_5)
diff --git a/arch/ia64/mm/Makefile b/arch/ia64/mm/Makefile
deleted file mode 100644
index c03f63c62ac4..000000000000
--- a/arch/ia64/mm/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the ia64-specific parts of the memory manager.
-#
-
-obj-y := init.o fault.o tlb.o extable.o ioremap.o
-
-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
-obj-$(CONFIG_NUMA) += numa.o
-obj-$(CONFIG_SPARSEMEM) += discontig.o
-obj-$(CONFIG_FLATMEM) += contig.o
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
deleted file mode 100644
index 1e9eaa107eb7..000000000000
--- a/arch/ia64/mm/contig.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com>
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 2003 Silicon Graphics, Inc. All rights reserved.
- *
- * Routines used by ia64 machines with contiguous (or virtually contiguous)
- * memory.
- */
-#include <linux/efi.h>
-#include <linux/memblock.h>
-#include <linux/mm.h>
-#include <linux/nmi.h>
-#include <linux/swap.h>
-#include <linux/sizes.h>
-
-#include <asm/efi.h>
-#include <asm/meminit.h>
-#include <asm/sections.h>
-#include <asm/mca.h>
-
-/* physical address where the bootmem map is located */
-unsigned long bootmap_start;
-
-#ifdef CONFIG_SMP
-static void *cpu_data;
-/**
- * per_cpu_init - setup per-cpu variables
- *
- * Allocate and setup per-cpu data areas.
- */
-void *per_cpu_init(void)
-{
- static bool first_time = true;
- void *cpu0_data = __cpu0_per_cpu;
- unsigned int cpu;
-
- if (!first_time)
- goto skip;
- first_time = false;
-
- /*
- * get_free_pages() cannot be used before cpu_init() done.
- * BSP allocates PERCPU_PAGE_SIZE bytes for all possible CPUs
- * to avoid that AP calls get_zeroed_page().
- */
- for_each_possible_cpu(cpu) {
- void *src = cpu == 0 ? cpu0_data : __phys_per_cpu_start;
-
- memcpy(cpu_data, src, __per_cpu_end - __per_cpu_start);
- __per_cpu_offset[cpu] = (char *)cpu_data - __per_cpu_start;
- per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
-
- /*
- * percpu area for cpu0 is moved from the __init area
- * which is setup by head.S and used till this point.
- * Update ar.k3. This move is ensures that percpu
- * area for cpu0 is on the correct node and its
- * virtual address isn't insanely far from other
- * percpu areas which is important for congruent
- * percpu allocator.
- */
- if (cpu == 0)
- ia64_set_kr(IA64_KR_PER_CPU_DATA, __pa(cpu_data) -
- (unsigned long)__per_cpu_start);
-
- cpu_data += PERCPU_PAGE_SIZE;
- }
-skip:
- return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
-}
-
-static inline __init void
-alloc_per_cpu_data(void)
-{
- size_t size = PERCPU_PAGE_SIZE * num_possible_cpus();
-
- cpu_data = memblock_alloc_from(size, PERCPU_PAGE_SIZE,
- __pa(MAX_DMA_ADDRESS));
- if (!cpu_data)
- panic("%s: Failed to allocate %lu bytes align=%lx from=%lx\n",
- __func__, size, PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
-}
-
-/**
- * setup_per_cpu_areas - setup percpu areas
- *
- * Arch code has already allocated and initialized percpu areas. All
- * this function has to do is to teach the determined layout to the
- * dynamic percpu allocator, which happens to be more complex than
- * creating whole new ones using helpers.
- */
-void __init
-setup_per_cpu_areas(void)
-{
- struct pcpu_alloc_info *ai;
- struct pcpu_group_info *gi;
- unsigned int cpu;
- ssize_t static_size, reserved_size, dyn_size;
-
- ai = pcpu_alloc_alloc_info(1, num_possible_cpus());
- if (!ai)
- panic("failed to allocate pcpu_alloc_info");
- gi = &ai->groups[0];
-
- /* units are assigned consecutively to possible cpus */
- for_each_possible_cpu(cpu)
- gi->cpu_map[gi->nr_units++] = cpu;
-
- /* set parameters */
- static_size = __per_cpu_end - __per_cpu_start;
- reserved_size = PERCPU_MODULE_RESERVE;
- dyn_size = PERCPU_PAGE_SIZE - static_size - reserved_size;
- if (dyn_size < 0)
- panic("percpu area overflow static=%zd reserved=%zd\n",
- static_size, reserved_size);
-
- ai->static_size = static_size;
- ai->reserved_size = reserved_size;
- ai->dyn_size = dyn_size;
- ai->unit_size = PERCPU_PAGE_SIZE;
- ai->atom_size = PAGE_SIZE;
- ai->alloc_size = PERCPU_PAGE_SIZE;
-
- pcpu_setup_first_chunk(ai, __per_cpu_start + __per_cpu_offset[0]);
- pcpu_free_alloc_info(ai);
-}
-#else
-#define alloc_per_cpu_data() do { } while (0)
-#endif /* CONFIG_SMP */
-
-/**
- * find_memory - setup memory map
- *
- * Walk the EFI memory map and find usable memory for the system, taking
- * into account reserved areas.
- */
-void __init
-find_memory (void)
-{
- reserve_memory();
-
- /* first find highest page frame number */
- min_low_pfn = ~0UL;
- max_low_pfn = 0;
- efi_memmap_walk(find_max_min_low_pfn, NULL);
- max_pfn = max_low_pfn;
-
- memblock_add_node(0, PFN_PHYS(max_low_pfn), 0, MEMBLOCK_NONE);
-
- find_initrd();
-
- alloc_per_cpu_data();
-}
-
-static int __init find_largest_hole(u64 start, u64 end, void *arg)
-{
- u64 *max_gap = arg;
-
- static u64 last_end = PAGE_OFFSET;
-
- /* NOTE: this algorithm assumes efi memmap table is ordered */
-
- if (*max_gap < (start - last_end))
- *max_gap = start - last_end;
- last_end = end;
- return 0;
-}
-
-static void __init verify_gap_absence(void)
-{
- unsigned long max_gap;
-
- /* Forbid FLATMEM if hole is > than 1G */
- efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
- if (max_gap >= SZ_1G)
- panic("Cannot use FLATMEM with %ldMB hole\n"
- "Please switch over to SPARSEMEM\n",
- (max_gap >> 20));
-}
-
-/*
- * Set up the page tables.
- */
-
-void __init
-paging_init (void)
-{
- unsigned long max_dma;
- unsigned long max_zone_pfns[MAX_NR_ZONES];
-
- memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
- max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
- max_zone_pfns[ZONE_DMA32] = max_dma;
- max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
-
- verify_gap_absence();
-
- free_area_init(max_zone_pfns);
- zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
-}
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
deleted file mode 100644
index 73d0db36edb6..000000000000
--- a/arch/ia64/mm/discontig.c
+++ /dev/null
@@ -1,635 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2000, 2003 Silicon Graphics, Inc. All rights reserved.
- * Copyright (c) 2001 Intel Corp.
- * Copyright (c) 2001 Tony Luck <tony.luck@intel.com>
- * Copyright (c) 2002 NEC Corp.
- * Copyright (c) 2002 Kimio Suganuma <k-suganuma@da.jp.nec.com>
- * Copyright (c) 2004 Silicon Graphics, Inc
- * Russ Anderson <rja@sgi.com>
- * Jesse Barnes <jbarnes@sgi.com>
- * Jack Steiner <steiner@sgi.com>
- */
-
-/*
- * Platform initialization for Discontig Memory
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/nmi.h>
-#include <linux/swap.h>
-#include <linux/memblock.h>
-#include <linux/acpi.h>
-#include <linux/efi.h>
-#include <linux/nodemask.h>
-#include <linux/slab.h>
-#include <asm/efi.h>
-#include <asm/tlb.h>
-#include <asm/meminit.h>
-#include <asm/numa.h>
-#include <asm/sections.h>
-
-/*
- * Track per-node information needed to setup the boot memory allocator, the
- * per-node areas, and the real VM.
- */
-struct early_node_data {
- struct ia64_node_data *node_data;
- unsigned long pernode_addr;
- unsigned long pernode_size;
- unsigned long min_pfn;
- unsigned long max_pfn;
-};
-
-static struct early_node_data mem_data[MAX_NUMNODES] __initdata;
-static nodemask_t memory_less_mask __initdata;
-
-pg_data_t *pgdat_list[MAX_NUMNODES];
-
-/*
- * To prevent cache aliasing effects, align per-node structures so that they
- * start at addresses that are strided by node number.
- */
-#define MAX_NODE_ALIGN_OFFSET (32 * 1024 * 1024)
-#define NODEDATA_ALIGN(addr, node) \
- ((((addr) + 1024*1024-1) & ~(1024*1024-1)) + \
- (((node)*PERCPU_PAGE_SIZE) & (MAX_NODE_ALIGN_OFFSET - 1)))
-
-/**
- * build_node_maps - callback to setup mem_data structs for each node
- * @start: physical start of range
- * @len: length of range
- * @node: node where this range resides
- *
- * Detect extents of each piece of memory that we wish to
- * treat as a virtually contiguous block (i.e. each node). Each such block
- * must start on an %IA64_GRANULE_SIZE boundary, so we round the address down
- * if necessary. Any non-existent pages will simply be part of the virtual
- * memmap.
- */
-static int __init build_node_maps(unsigned long start, unsigned long len,
- int node)
-{
- unsigned long spfn, epfn, end = start + len;
-
- epfn = GRANULEROUNDUP(end) >> PAGE_SHIFT;
- spfn = GRANULEROUNDDOWN(start) >> PAGE_SHIFT;
-
- if (!mem_data[node].min_pfn) {
- mem_data[node].min_pfn = spfn;
- mem_data[node].max_pfn = epfn;
- } else {
- mem_data[node].min_pfn = min(spfn, mem_data[node].min_pfn);
- mem_data[node].max_pfn = max(epfn, mem_data[node].max_pfn);
- }
-
- return 0;
-}
-
-/**
- * early_nr_cpus_node - return number of cpus on a given node
- * @node: node to check
- *
- * Count the number of cpus on @node. We can't use nr_cpus_node() yet because
- * acpi_boot_init() (which builds the node_to_cpu_mask array) hasn't been
- * called yet. Note that node 0 will also count all non-existent cpus.
- */
-static int early_nr_cpus_node(int node)
-{
- int cpu, n = 0;
-
- for_each_possible_early_cpu(cpu)
- if (node == node_cpuid[cpu].nid)
- n++;
-
- return n;
-}
-
-/**
- * compute_pernodesize - compute size of pernode data
- * @node: the node id.
- */
-static unsigned long compute_pernodesize(int node)
-{
- unsigned long pernodesize = 0, cpus;
-
- cpus = early_nr_cpus_node(node);
- pernodesize += PERCPU_PAGE_SIZE * cpus;
- pernodesize += node * L1_CACHE_BYTES;
- pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
- pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
- pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
- pernodesize = PAGE_ALIGN(pernodesize);
- return pernodesize;
-}
-
-/**
- * per_cpu_node_setup - setup per-cpu areas on each node
- * @cpu_data: per-cpu area on this node
- * @node: node to setup
- *
- * Copy the static per-cpu data into the region we just set aside and then
- * setup __per_cpu_offset for each CPU on this node. Return a pointer to
- * the end of the area.
- */
-static void *per_cpu_node_setup(void *cpu_data, int node)
-{
-#ifdef CONFIG_SMP
- int cpu;
-
- for_each_possible_early_cpu(cpu) {
- void *src = cpu == 0 ? __cpu0_per_cpu : __phys_per_cpu_start;
-
- if (node != node_cpuid[cpu].nid)
- continue;
-
- memcpy(__va(cpu_data), src, __per_cpu_end - __per_cpu_start);
- __per_cpu_offset[cpu] = (char *)__va(cpu_data) -
- __per_cpu_start;
-
- /*
- * percpu area for cpu0 is moved from the __init area
- * which is setup by head.S and used till this point.
- * Update ar.k3. This move is ensures that percpu
- * area for cpu0 is on the correct node and its
- * virtual address isn't insanely far from other
- * percpu areas which is important for congruent
- * percpu allocator.
- */
- if (cpu == 0)
- ia64_set_kr(IA64_KR_PER_CPU_DATA,
- (unsigned long)cpu_data -
- (unsigned long)__per_cpu_start);
-
- cpu_data += PERCPU_PAGE_SIZE;
- }
-#endif
- return cpu_data;
-}
-
-#ifdef CONFIG_SMP
-/**
- * setup_per_cpu_areas - setup percpu areas
- *
- * Arch code has already allocated and initialized percpu areas. All
- * this function has to do is to teach the determined layout to the
- * dynamic percpu allocator, which happens to be more complex than
- * creating whole new ones using helpers.
- */
-void __init setup_per_cpu_areas(void)
-{
- struct pcpu_alloc_info *ai;
- struct pcpu_group_info *gi;
- unsigned int *cpu_map;
- void *base;
- unsigned long base_offset;
- unsigned int cpu;
- ssize_t static_size, reserved_size, dyn_size;
- int node, prev_node, unit, nr_units;
-
- ai = pcpu_alloc_alloc_info(MAX_NUMNODES, nr_cpu_ids);
- if (!ai)
- panic("failed to allocate pcpu_alloc_info");
- cpu_map = ai->groups[0].cpu_map;
-
- /* determine base */
- base = (void *)ULONG_MAX;
- for_each_possible_cpu(cpu)
- base = min(base,
- (void *)(__per_cpu_offset[cpu] + __per_cpu_start));
- base_offset = (void *)__per_cpu_start - base;
-
- /* build cpu_map, units are grouped by node */
- unit = 0;
- for_each_node(node)
- for_each_possible_cpu(cpu)
- if (node == node_cpuid[cpu].nid)
- cpu_map[unit++] = cpu;
- nr_units = unit;
-
- /* set basic parameters */
- static_size = __per_cpu_end - __per_cpu_start;
- reserved_size = PERCPU_MODULE_RESERVE;
- dyn_size = PERCPU_PAGE_SIZE - static_size - reserved_size;
- if (dyn_size < 0)
- panic("percpu area overflow static=%zd reserved=%zd\n",
- static_size, reserved_size);
-
- ai->static_size = static_size;
- ai->reserved_size = reserved_size;
- ai->dyn_size = dyn_size;
- ai->unit_size = PERCPU_PAGE_SIZE;
- ai->atom_size = PAGE_SIZE;
- ai->alloc_size = PERCPU_PAGE_SIZE;
-
- /*
- * CPUs are put into groups according to node. Walk cpu_map
- * and create new groups at node boundaries.
- */
- prev_node = NUMA_NO_NODE;
- ai->nr_groups = 0;
- for (unit = 0; unit < nr_units; unit++) {
- cpu = cpu_map[unit];
- node = node_cpuid[cpu].nid;
-
- if (node == prev_node) {
- gi->nr_units++;
- continue;
- }
- prev_node = node;
-
- gi = &ai->groups[ai->nr_groups++];
- gi->nr_units = 1;
- gi->base_offset = __per_cpu_offset[cpu] + base_offset;
- gi->cpu_map = &cpu_map[unit];
- }
-
- pcpu_setup_first_chunk(ai, base);
- pcpu_free_alloc_info(ai);
-}
-#endif
-
-/**
- * fill_pernode - initialize pernode data.
- * @node: the node id.
- * @pernode: physical address of pernode data
- * @pernodesize: size of the pernode data
- */
-static void __init fill_pernode(int node, unsigned long pernode,
- unsigned long pernodesize)
-{
- void *cpu_data;
- int cpus = early_nr_cpus_node(node);
-
- mem_data[node].pernode_addr = pernode;
- mem_data[node].pernode_size = pernodesize;
- memset(__va(pernode), 0, pernodesize);
-
- cpu_data = (void *)pernode;
- pernode += PERCPU_PAGE_SIZE * cpus;
- pernode += node * L1_CACHE_BYTES;
-
- pgdat_list[node] = __va(pernode);
- pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
-
- mem_data[node].node_data = __va(pernode);
- pernode += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
- pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
-
- cpu_data = per_cpu_node_setup(cpu_data, node);
-
- return;
-}
-
-/**
- * find_pernode_space - allocate memory for memory map and per-node structures
- * @start: physical start of range
- * @len: length of range
- * @node: node where this range resides
- *
- * This routine reserves space for the per-cpu data struct, the list of
- * pg_data_ts and the per-node data struct. Each node will have something like
- * the following in the first chunk of addr. space large enough to hold it.
- *
- * ________________________
- * | |
- * |~~~~~~~~~~~~~~~~~~~~~~~~| <-- NODEDATA_ALIGN(start, node) for the first
- * | PERCPU_PAGE_SIZE * | start and length big enough
- * | cpus_on_this_node | Node 0 will also have entries for all non-existent cpus.
- * |------------------------|
- * | local pg_data_t * |
- * |------------------------|
- * | local ia64_node_data |
- * |------------------------|
- * | ??? |
- * |________________________|
- *
- * Once this space has been set aside, the bootmem maps are initialized. We
- * could probably move the allocation of the per-cpu and ia64_node_data space
- * outside of this function and use alloc_bootmem_node(), but doing it here
- * is straightforward and we get the alignments we want so...
- */
-static int __init find_pernode_space(unsigned long start, unsigned long len,
- int node)
-{
- unsigned long spfn, epfn;
- unsigned long pernodesize = 0, pernode;
-
- spfn = start >> PAGE_SHIFT;
- epfn = (start + len) >> PAGE_SHIFT;
-
- /*
- * Make sure this memory falls within this node's usable memory
- * since we may have thrown some away in build_maps().
- */
- if (spfn < mem_data[node].min_pfn || epfn > mem_data[node].max_pfn)
- return 0;
-
- /* Don't setup this node's local space twice... */
- if (mem_data[node].pernode_addr)
- return 0;
-
- /*
- * Calculate total size needed, incl. what's necessary
- * for good alignment and alias prevention.
- */
- pernodesize = compute_pernodesize(node);
- pernode = NODEDATA_ALIGN(start, node);
-
- /* Is this range big enough for what we want to store here? */
- if (start + len > (pernode + pernodesize))
- fill_pernode(node, pernode, pernodesize);
-
- return 0;
-}
-
-/**
- * reserve_pernode_space - reserve memory for per-node space
- *
- * Reserve the space used by the bootmem maps & per-node space in the boot
- * allocator so that when we actually create the real mem maps we don't
- * use their memory.
- */
-static void __init reserve_pernode_space(void)
-{
- unsigned long base, size;
- int node;
-
- for_each_online_node(node) {
- if (node_isset(node, memory_less_mask))
- continue;
-
- /* Now the per-node space */
- size = mem_data[node].pernode_size;
- base = __pa(mem_data[node].pernode_addr);
- memblock_reserve(base, size);
- }
-}
-
-static void scatter_node_data(void)
-{
- pg_data_t **dst;
- int node;
-
- /*
- * for_each_online_node() can't be used at here.
- * node_online_map is not set for hot-added nodes at this time,
- * because we are halfway through initialization of the new node's
- * structures. If for_each_online_node() is used, a new node's
- * pg_data_ptrs will be not initialized. Instead of using it,
- * pgdat_list[] is checked.
- */
- for_each_node(node) {
- if (pgdat_list[node]) {
- dst = LOCAL_DATA_ADDR(pgdat_list[node])->pg_data_ptrs;
- memcpy(dst, pgdat_list, sizeof(pgdat_list));
- }
- }
-}
-
-/**
- * initialize_pernode_data - fixup per-cpu & per-node pointers
- *
- * Each node's per-node area has a copy of the global pg_data_t list, so
- * we copy that to each node here, as well as setting the per-cpu pointer
- * to the local node data structure.
- */
-static void __init initialize_pernode_data(void)
-{
- int cpu, node;
-
- scatter_node_data();
-
-#ifdef CONFIG_SMP
- /* Set the node_data pointer for each per-cpu struct */
- for_each_possible_early_cpu(cpu) {
- node = node_cpuid[cpu].nid;
- per_cpu(ia64_cpu_info, cpu).node_data =
- mem_data[node].node_data;
- }
-#else
- {
- struct cpuinfo_ia64 *cpu0_cpu_info;
- cpu = 0;
- node = node_cpuid[cpu].nid;
- cpu0_cpu_info = (struct cpuinfo_ia64 *)(__phys_per_cpu_start +
- ((char *)&ia64_cpu_info - __per_cpu_start));
- cpu0_cpu_info->node_data = mem_data[node].node_data;
- }
-#endif /* CONFIG_SMP */
-}
-
-/**
- * memory_less_node_alloc - * attempt to allocate memory on the best NUMA slit
- * node but fall back to any other node when __alloc_bootmem_node fails
- * for best.
- * @nid: node id
- * @pernodesize: size of this node's pernode data
- */
-static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize)
-{
- void *ptr = NULL;
- u8 best = 0xff;
- int bestnode = NUMA_NO_NODE, node, anynode = 0;
-
- for_each_online_node(node) {
- if (node_isset(node, memory_less_mask))
- continue;
- else if (node_distance(nid, node) < best) {
- best = node_distance(nid, node);
- bestnode = node;
- }
- anynode = node;
- }
-
- if (bestnode == NUMA_NO_NODE)
- bestnode = anynode;
-
- ptr = memblock_alloc_try_nid(pernodesize, PERCPU_PAGE_SIZE,
- __pa(MAX_DMA_ADDRESS),
- MEMBLOCK_ALLOC_ACCESSIBLE,
- bestnode);
- if (!ptr)
- panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d from=%lx\n",
- __func__, pernodesize, PERCPU_PAGE_SIZE, bestnode,
- __pa(MAX_DMA_ADDRESS));
-
- return ptr;
-}
-
-/**
- * memory_less_nodes - allocate and initialize CPU only nodes pernode
- * information.
- */
-static void __init memory_less_nodes(void)
-{
- unsigned long pernodesize;
- void *pernode;
- int node;
-
- for_each_node_mask(node, memory_less_mask) {
- pernodesize = compute_pernodesize(node);
- pernode = memory_less_node_alloc(node, pernodesize);
- fill_pernode(node, __pa(pernode), pernodesize);
- }
-
- return;
-}
-
-/**
- * find_memory - walk the EFI memory map and setup the bootmem allocator
- *
- * Called early in boot to setup the bootmem allocator, and to
- * allocate the per-cpu and per-node structures.
- */
-void __init find_memory(void)
-{
- int node;
-
- reserve_memory();
- efi_memmap_walk(filter_memory, register_active_ranges);
-
- if (num_online_nodes() == 0) {
- printk(KERN_ERR "node info missing!\n");
- node_set_online(0);
- }
-
- nodes_or(memory_less_mask, memory_less_mask, node_online_map);
- min_low_pfn = -1;
- max_low_pfn = 0;
-
- /* These actually end up getting called by call_pernode_memory() */
- efi_memmap_walk(filter_rsvd_memory, build_node_maps);
- efi_memmap_walk(filter_rsvd_memory, find_pernode_space);
- efi_memmap_walk(find_max_min_low_pfn, NULL);
-
- for_each_online_node(node)
- if (mem_data[node].min_pfn)
- node_clear(node, memory_less_mask);
-
- reserve_pernode_space();
- memory_less_nodes();
- initialize_pernode_data();
-
- max_pfn = max_low_pfn;
-
- find_initrd();
-}
-
-#ifdef CONFIG_SMP
-/**
- * per_cpu_init - setup per-cpu variables
- *
- * find_pernode_space() does most of this already, we just need to set
- * local_per_cpu_offset
- */
-void *per_cpu_init(void)
-{
- int cpu;
- static int first_time = 1;
-
- if (first_time) {
- first_time = 0;
- for_each_possible_early_cpu(cpu)
- per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
- }
-
- return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
-}
-#endif /* CONFIG_SMP */
-
-/**
- * call_pernode_memory - use SRAT to call callback functions with node info
- * @start: physical start of range
- * @len: length of range
- * @arg: function to call for each range
- *
- * efi_memmap_walk() knows nothing about layout of memory across nodes. Find
- * out to which node a block of memory belongs. Ignore memory that we cannot
- * identify, and split blocks that run across multiple nodes.
- *
- * Take this opportunity to round the start address up and the end address
- * down to page boundaries.
- */
-void call_pernode_memory(unsigned long start, unsigned long len, void *arg)
-{
- unsigned long rs, re, end = start + len;
- void (*func)(unsigned long, unsigned long, int);
- int i;
-
- start = PAGE_ALIGN(start);
- end &= PAGE_MASK;
- if (start >= end)
- return;
-
- func = arg;
-
- if (!num_node_memblks) {
- /* No SRAT table, so assume one node (node 0) */
- if (start < end)
- (*func)(start, end - start, 0);
- return;
- }
-
- for (i = 0; i < num_node_memblks; i++) {
- rs = max(start, node_memblk[i].start_paddr);
- re = min(end, node_memblk[i].start_paddr +
- node_memblk[i].size);
-
- if (rs < re)
- (*func)(rs, re - rs, node_memblk[i].nid);
-
- if (re == end)
- break;
- }
-}
-
-/**
- * paging_init - setup page tables
- *
- * paging_init() sets up the page tables for each node of the system and frees
- * the bootmem allocator memory for general use.
- */
-void __init paging_init(void)
-{
- unsigned long max_dma;
- unsigned long max_zone_pfns[MAX_NR_ZONES];
-
- max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-
- sparse_init();
-
- memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
- max_zone_pfns[ZONE_DMA32] = max_dma;
- max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
- free_area_init(max_zone_pfns);
-
- zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
-}
-
-pg_data_t * __init arch_alloc_nodedata(int nid)
-{
- unsigned long size = compute_pernodesize(nid);
-
- return memblock_alloc(size, SMP_CACHE_BYTES);
-}
-
-void arch_refresh_nodedata(int update_node, pg_data_t *update_pgdat)
-{
- pgdat_list[update_node] = update_pgdat;
- scatter_node_data();
-}
-
-#ifdef CONFIG_SPARSEMEM_VMEMMAP
-int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
- struct vmem_altmap *altmap)
-{
- return vmemmap_populate_basepages(start, end, node, NULL);
-}
-
-void vmemmap_free(unsigned long start, unsigned long end,
- struct vmem_altmap *altmap)
-{
-}
-#endif
diff --git a/arch/ia64/mm/extable.c b/arch/ia64/mm/extable.c
deleted file mode 100644
index da477c11770b..000000000000
--- a/arch/ia64/mm/extable.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Kernel exception handling table support. Derived from arch/alpha/mm/extable.c.
- *
- * Copyright (C) 1998, 1999, 2001-2002, 2004 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <asm/ptrace.h>
-#include <asm/extable.h>
-#include <asm/errno.h>
-#include <asm/processor.h>
-
-void
-ia64_handle_exception (struct pt_regs *regs, const struct exception_table_entry *e)
-{
- long fix = (u64) &e->fixup + e->fixup;
-
- regs->r8 = -EFAULT;
- if (fix & 4)
- regs->r9 = 0;
- regs->cr_iip = fix & ~0xf;
- ia64_psr(regs)->ri = fix & 0x3; /* set continuation slot number */
-}
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
deleted file mode 100644
index 5458b52b4009..000000000000
--- a/arch/ia64/mm/fault.c
+++ /dev/null
@@ -1,251 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * MMU fault handling support.
- *
- * Copyright (C) 1998-2002 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#include <linux/sched/signal.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/extable.h>
-#include <linux/interrupt.h>
-#include <linux/kprobes.h>
-#include <linux/kdebug.h>
-#include <linux/prefetch.h>
-#include <linux/uaccess.h>
-#include <linux/perf_event.h>
-
-#include <asm/processor.h>
-#include <asm/exception.h>
-
-extern int die(char *, struct pt_regs *, long);
-
-/*
- * Return TRUE if ADDRESS points at a page in the kernel's mapped segment
- * (inside region 5, on ia64) and that page is present.
- */
-static int
-mapped_kernel_page_is_present (unsigned long address)
-{
- pgd_t *pgd;
- p4d_t *p4d;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *ptep, pte;
-
- pgd = pgd_offset_k(address);
- if (pgd_none(*pgd) || pgd_bad(*pgd))
- return 0;
-
- p4d = p4d_offset(pgd, address);
- if (p4d_none(*p4d) || p4d_bad(*p4d))
- return 0;
-
- pud = pud_offset(p4d, address);
- if (pud_none(*pud) || pud_bad(*pud))
- return 0;
-
- pmd = pmd_offset(pud, address);
- if (pmd_none(*pmd) || pmd_bad(*pmd))
- return 0;
-
- ptep = pte_offset_kernel(pmd, address);
- if (!ptep)
- return 0;
-
- pte = *ptep;
- return pte_present(pte);
-}
-
-# define VM_READ_BIT 0
-# define VM_WRITE_BIT 1
-# define VM_EXEC_BIT 2
-
-void __kprobes
-ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
-{
- int signal = SIGSEGV, code = SEGV_MAPERR;
- struct vm_area_struct *vma, *prev_vma;
- struct mm_struct *mm = current->mm;
- unsigned long mask;
- vm_fault_t fault;
- unsigned int flags = FAULT_FLAG_DEFAULT;
-
- mask = ((((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
- | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT));
-
- /* mmap_lock is performance critical.... */
- prefetchw(&mm->mmap_lock);
-
- /*
- * If we're in an interrupt or have no user context, we must not take the fault..
- */
- if (faulthandler_disabled() || !mm)
- goto no_context;
-
- /*
- * This is to handle the kprobes on user space access instructions
- */
- if (kprobe_page_fault(regs, TRAP_BRKPT))
- return;
-
- if (user_mode(regs))
- flags |= FAULT_FLAG_USER;
- if (mask & VM_WRITE)
- flags |= FAULT_FLAG_WRITE;
-
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
-retry:
- mmap_read_lock(mm);
-
- vma = find_vma_prev(mm, address, &prev_vma);
- if (!vma && !prev_vma )
- goto bad_area;
-
- /*
- * find_vma_prev() returns vma such that address < vma->vm_end or NULL
- *
- * May find no vma, but could be that the last vm area is the
- * register backing store that needs to expand upwards, in
- * this case vma will be null, but prev_vma will ne non-null
- */
- if (( !vma && prev_vma ) || (address < vma->vm_start) ) {
- vma = expand_stack(mm, address);
- if (!vma)
- goto bad_area_nosemaphore;
- }
-
- code = SEGV_ACCERR;
-
- /* OK, we've got a good vm_area for this memory area. Check the access permissions: */
-
-# if (((1 << VM_READ_BIT) != VM_READ || (1 << VM_WRITE_BIT) != VM_WRITE) \
- || (1 << VM_EXEC_BIT) != VM_EXEC)
-# error File is out of sync with <linux/mm.h>. Please update.
-# endif
-
- if (((isr >> IA64_ISR_R_BIT) & 1UL) && (!(vma->vm_flags & (VM_READ | VM_WRITE))))
- goto bad_area;
-
- if ((vma->vm_flags & mask) != mask)
- goto bad_area;
-
- /*
- * If for any reason at all we couldn't handle the fault, make
- * sure we exit gracefully rather than endlessly redo the
- * fault.
- */
- fault = handle_mm_fault(vma, address, flags, regs);
-
- if (fault_signal_pending(fault, regs)) {
- if (!user_mode(regs))
- goto no_context;
- return;
- }
-
- /* The fault is fully completed (including releasing mmap lock) */
- if (fault & VM_FAULT_COMPLETED)
- return;
-
- if (unlikely(fault & VM_FAULT_ERROR)) {
- /*
- * We ran out of memory, or some other thing happened
- * to us that made us unable to handle the page fault
- * gracefully.
- */
- if (fault & VM_FAULT_OOM) {
- goto out_of_memory;
- } else if (fault & VM_FAULT_SIGSEGV) {
- goto bad_area;
- } else if (fault & VM_FAULT_SIGBUS) {
- signal = SIGBUS;
- goto bad_area;
- }
- BUG();
- }
-
- if (fault & VM_FAULT_RETRY) {
- flags |= FAULT_FLAG_TRIED;
-
- /* No need to mmap_read_unlock(mm) as we would
- * have already released it in __lock_page_or_retry
- * in mm/filemap.c.
- */
-
- goto retry;
- }
-
- mmap_read_unlock(mm);
- return;
-
- bad_area:
- mmap_read_unlock(mm);
- bad_area_nosemaphore:
- if ((isr & IA64_ISR_SP)
- || ((isr & IA64_ISR_NA) && (isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH))
- {
- /*
- * This fault was due to a speculative load or lfetch.fault, set the "ed"
- * bit in the psr to ensure forward progress. (Target register will get a
- * NaT for ld.s, lfetch will be canceled.)
- */
- ia64_psr(regs)->ed = 1;
- return;
- }
- if (user_mode(regs)) {
- force_sig_fault(signal, code, (void __user *) address,
- 0, __ISR_VALID, isr);
- return;
- }
-
- no_context:
- if ((isr & IA64_ISR_SP)
- || ((isr & IA64_ISR_NA) && (isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH))
- {
- /*
- * This fault was due to a speculative load or lfetch.fault, set the "ed"
- * bit in the psr to ensure forward progress. (Target register will get a
- * NaT for ld.s, lfetch will be canceled.)
- */
- ia64_psr(regs)->ed = 1;
- return;
- }
-
- /*
- * Since we have no vma's for region 5, we might get here even if the address is
- * valid, due to the VHPT walker inserting a non present translation that becomes
- * stale. If that happens, the non present fault handler already purged the stale
- * translation, which fixed the problem. So, we check to see if the translation is
- * valid, and return if it is.
- */
- if (REGION_NUMBER(address) == 5 && mapped_kernel_page_is_present(address))
- return;
-
- if (ia64_done_with_exception(regs))
- return;
-
- /*
- * Oops. The kernel tried to access some bad page. We'll have to terminate things
- * with extreme prejudice.
- */
- bust_spinlocks(1);
-
- if (address < PAGE_SIZE)
- printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference (address %016lx)\n", address);
- else
- printk(KERN_ALERT "Unable to handle kernel paging request at "
- "virtual address %016lx\n", address);
- if (die("Oops", regs, isr))
- regs = NULL;
- bust_spinlocks(0);
- if (regs)
- make_task_dead(SIGKILL);
- return;
-
- out_of_memory:
- mmap_read_unlock(mm);
- if (!user_mode(regs))
- goto no_context;
- pagefault_out_of_memory();
-}
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
deleted file mode 100644
index adc49f2d22e8..000000000000
--- a/arch/ia64/mm/hugetlbpage.c
+++ /dev/null
@@ -1,186 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * IA-64 Huge TLB Page Support for Kernel.
- *
- * Copyright (C) 2002-2004 Rohit Seth <rohit.seth@intel.com>
- * Copyright (C) 2003-2004 Ken Chen <kenneth.w.chen@intel.com>
- *
- * Sep, 2003: add numa support
- * Feb, 2004: dynamic hugetlb page size via boot parameter
- */
-
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/hugetlb.h>
-#include <linux/pagemap.h>
-#include <linux/module.h>
-#include <linux/sysctl.h>
-#include <linux/log2.h>
-#include <asm/mman.h>
-#include <asm/tlb.h>
-#include <asm/tlbflush.h>
-
-unsigned int hpage_shift = HPAGE_SHIFT_DEFAULT;
-EXPORT_SYMBOL(hpage_shift);
-
-pte_t *
-huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma,
- unsigned long addr, unsigned long sz)
-{
- unsigned long taddr = htlbpage_to_page(addr);
- pgd_t *pgd;
- p4d_t *p4d;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte = NULL;
-
- pgd = pgd_offset(mm, taddr);
- p4d = p4d_offset(pgd, taddr);
- pud = pud_alloc(mm, p4d, taddr);
- if (pud) {
- pmd = pmd_alloc(mm, pud, taddr);
- if (pmd)
- pte = pte_alloc_huge(mm, pmd, taddr);
- }
- return pte;
-}
-
-pte_t *
-huge_pte_offset (struct mm_struct *mm, unsigned long addr, unsigned long sz)
-{
- unsigned long taddr = htlbpage_to_page(addr);
- pgd_t *pgd;
- p4d_t *p4d;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte = NULL;
-
- pgd = pgd_offset(mm, taddr);
- if (pgd_present(*pgd)) {
- p4d = p4d_offset(pgd, taddr);
- if (p4d_present(*p4d)) {
- pud = pud_offset(p4d, taddr);
- if (pud_present(*pud)) {
- pmd = pmd_offset(pud, taddr);
- if (pmd_present(*pmd))
- pte = pte_offset_huge(pmd, taddr);
- }
- }
- }
-
- return pte;
-}
-
-#define mk_pte_huge(entry) { pte_val(entry) |= _PAGE_P; }
-
-/*
- * Don't actually need to do any preparation, but need to make sure
- * the address is in the right region.
- */
-int prepare_hugepage_range(struct file *file,
- unsigned long addr, unsigned long len)
-{
- if (len & ~HPAGE_MASK)
- return -EINVAL;
- if (addr & ~HPAGE_MASK)
- return -EINVAL;
- if (REGION_NUMBER(addr) != RGN_HPAGE)
- return -EINVAL;
-
- return 0;
-}
-
-int pmd_huge(pmd_t pmd)
-{
- return 0;
-}
-
-int pud_huge(pud_t pud)
-{
- return 0;
-}
-
-void hugetlb_free_pgd_range(struct mmu_gather *tlb,
- unsigned long addr, unsigned long end,
- unsigned long floor, unsigned long ceiling)
-{
- /*
- * This is called to free hugetlb page tables.
- *
- * The offset of these addresses from the base of the hugetlb
- * region must be scaled down by HPAGE_SIZE/PAGE_SIZE so that
- * the standard free_pgd_range will free the right page tables.
- *
- * If floor and ceiling are also in the hugetlb region, they
- * must likewise be scaled down; but if outside, left unchanged.
- */
-
- addr = htlbpage_to_page(addr);
- end = htlbpage_to_page(end);
- if (REGION_NUMBER(floor) == RGN_HPAGE)
- floor = htlbpage_to_page(floor);
- if (REGION_NUMBER(ceiling) == RGN_HPAGE)
- ceiling = htlbpage_to_page(ceiling);
-
- free_pgd_range(tlb, addr, end, floor, ceiling);
-}
-
-unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
- unsigned long pgoff, unsigned long flags)
-{
- struct vm_unmapped_area_info info;
-
- if (len > RGN_MAP_LIMIT)
- return -ENOMEM;
- if (len & ~HPAGE_MASK)
- return -EINVAL;
-
- /* Handle MAP_FIXED */
- if (flags & MAP_FIXED) {
- if (prepare_hugepage_range(file, addr, len))
- return -EINVAL;
- return addr;
- }
-
- /* This code assumes that RGN_HPAGE != 0. */
- if ((REGION_NUMBER(addr) != RGN_HPAGE) || (addr & (HPAGE_SIZE - 1)))
- addr = HPAGE_REGION_BASE;
-
- info.flags = 0;
- info.length = len;
- info.low_limit = addr;
- info.high_limit = HPAGE_REGION_BASE + RGN_MAP_LIMIT;
- info.align_mask = PAGE_MASK & (HPAGE_SIZE - 1);
- info.align_offset = 0;
- return vm_unmapped_area(&info);
-}
-
-static int __init hugetlb_setup_sz(char *str)
-{
- u64 tr_pages;
- unsigned long long size;
-
- if (ia64_pal_vm_page_size(&tr_pages, NULL) != 0)
- /*
- * shouldn't happen, but just in case.
- */
- tr_pages = 0x15557000UL;
-
- size = memparse(str, &str);
- if (*str || !is_power_of_2(size) || !(tr_pages & size) ||
- size <= PAGE_SIZE ||
- size > (1UL << PAGE_SHIFT << MAX_ORDER)) {
- printk(KERN_WARNING "Invalid huge page size specified\n");
- return 1;
- }
-
- hpage_shift = __ffs(size);
- /*
- * boot cpu already executed ia64_mmu_init, and has HPAGE_SHIFT_DEFAULT
- * override here with new page shift.
- */
- ia64_set_rr(HPAGE_REGION_BASE, hpage_shift << 2);
- return 0;
-}
-early_param("hugepagesz", hugetlb_setup_sz);
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
deleted file mode 100644
index 05b0f2f0c073..000000000000
--- a/arch/ia64/mm/init.c
+++ /dev/null
@@ -1,532 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Initialize MMU support.
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <linux/dma-map-ops.h>
-#include <linux/dmar.h>
-#include <linux/efi.h>
-#include <linux/elf.h>
-#include <linux/memblock.h>
-#include <linux/mm.h>
-#include <linux/sched/signal.h>
-#include <linux/mmzone.h>
-#include <linux/module.h>
-#include <linux/personality.h>
-#include <linux/reboot.h>
-#include <linux/slab.h>
-#include <linux/swap.h>
-#include <linux/proc_fs.h>
-#include <linux/bitops.h>
-#include <linux/kexec.h>
-#include <linux/swiotlb.h>
-
-#include <asm/dma.h>
-#include <asm/efi.h>
-#include <asm/io.h>
-#include <asm/numa.h>
-#include <asm/patch.h>
-#include <asm/pgalloc.h>
-#include <asm/sal.h>
-#include <asm/sections.h>
-#include <asm/tlb.h>
-#include <linux/uaccess.h>
-#include <asm/unistd.h>
-#include <asm/mca.h>
-
-extern void ia64_tlb_init (void);
-
-unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL;
-
-struct page *zero_page_memmap_ptr; /* map entry for zero page */
-EXPORT_SYMBOL(zero_page_memmap_ptr);
-
-void
-__ia64_sync_icache_dcache (pte_t pte)
-{
- unsigned long addr;
- struct folio *folio;
-
- folio = page_folio(pte_page(pte));
- addr = (unsigned long)folio_address(folio);
-
- if (test_bit(PG_arch_1, &folio->flags))
- return; /* i-cache is already coherent with d-cache */
-
- flush_icache_range(addr, addr + folio_size(folio));
- set_bit(PG_arch_1, &folio->flags); /* mark page as clean */
-}
-
-/*
- * Since DMA is i-cache coherent, any (complete) folios that were written via
- * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to
- * flush them when they get mapped into an executable vm-area.
- */
-void arch_dma_mark_clean(phys_addr_t paddr, size_t size)
-{
- unsigned long pfn = PHYS_PFN(paddr);
- struct folio *folio = page_folio(pfn_to_page(pfn));
- ssize_t left = size;
- size_t offset = offset_in_folio(folio, paddr);
-
- if (offset) {
- left -= folio_size(folio) - offset;
- if (left <= 0)
- return;
- folio = folio_next(folio);
- }
-
- while (left >= (ssize_t)folio_size(folio)) {
- left -= folio_size(folio);
- set_bit(PG_arch_1, &pfn_to_page(pfn)->flags);
- if (!left)
- break;
- folio = folio_next(folio);
- }
-}
-
-inline void
-ia64_set_rbs_bot (void)
-{
- unsigned long stack_size = rlimit_max(RLIMIT_STACK) & -16;
-
- if (stack_size > MAX_USER_STACK_SIZE)
- stack_size = MAX_USER_STACK_SIZE;
- current->thread.rbs_bot = PAGE_ALIGN(current->mm->start_stack - stack_size);
-}
-
-/*
- * This performs some platform-dependent address space initialization.
- * On IA-64, we want to setup the VM area for the register backing
- * store (which grows upwards) and install the gateway page which is
- * used for signal trampolines, etc.
- */
-void
-ia64_init_addr_space (void)
-{
- struct vm_area_struct *vma;
-
- ia64_set_rbs_bot();
-
- /*
- * If we're out of memory and kmem_cache_alloc() returns NULL, we simply ignore
- * the problem. When the process attempts to write to the register backing store
- * for the first time, it will get a SEGFAULT in this case.
- */
- vma = vm_area_alloc(current->mm);
- if (vma) {
- vma_set_anonymous(vma);
- vma->vm_start = current->thread.rbs_bot & PAGE_MASK;
- vma->vm_end = vma->vm_start + PAGE_SIZE;
- vm_flags_init(vma, VM_DATA_DEFAULT_FLAGS|VM_GROWSUP|VM_ACCOUNT);
- vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
- mmap_write_lock(current->mm);
- if (insert_vm_struct(current->mm, vma)) {
- mmap_write_unlock(current->mm);
- vm_area_free(vma);
- return;
- }
- mmap_write_unlock(current->mm);
- }
-
- /* map NaT-page at address zero to speed up speculative dereferencing of NULL: */
- if (!(current->personality & MMAP_PAGE_ZERO)) {
- vma = vm_area_alloc(current->mm);
- if (vma) {
- vma_set_anonymous(vma);
- vma->vm_end = PAGE_SIZE;
- vma->vm_page_prot = __pgprot(pgprot_val(PAGE_READONLY) | _PAGE_MA_NAT);
- vm_flags_init(vma, VM_READ | VM_MAYREAD | VM_IO |
- VM_DONTEXPAND | VM_DONTDUMP);
- mmap_write_lock(current->mm);
- if (insert_vm_struct(current->mm, vma)) {
- mmap_write_unlock(current->mm);
- vm_area_free(vma);
- return;
- }
- mmap_write_unlock(current->mm);
- }
- }
-}
-
-void
-free_initmem (void)
-{
- free_reserved_area(ia64_imva(__init_begin), ia64_imva(__init_end),
- -1, "unused kernel");
-}
-
-void __init
-free_initrd_mem (unsigned long start, unsigned long end)
-{
- /*
- * EFI uses 4KB pages while the kernel can use 4KB or bigger.
- * Thus EFI and the kernel may have different page sizes. It is
- * therefore possible to have the initrd share the same page as
- * the end of the kernel (given current setup).
- *
- * To avoid freeing/using the wrong page (kernel sized) we:
- * - align up the beginning of initrd
- * - align down the end of initrd
- *
- * | |
- * |=============| a000
- * | |
- * | |
- * | | 9000
- * |/////////////|
- * |/////////////|
- * |=============| 8000
- * |///INITRD////|
- * |/////////////|
- * |/////////////| 7000
- * | |
- * |KKKKKKKKKKKKK|
- * |=============| 6000
- * |KKKKKKKKKKKKK|
- * |KKKKKKKKKKKKK|
- * K=kernel using 8KB pages
- *
- * In this example, we must free page 8000 ONLY. So we must align up
- * initrd_start and keep initrd_end as is.
- */
- start = PAGE_ALIGN(start);
- end = end & PAGE_MASK;
-
- if (start < end)
- printk(KERN_INFO "Freeing initrd memory: %ldkB freed\n", (end - start) >> 10);
-
- for (; start < end; start += PAGE_SIZE) {
- if (!virt_addr_valid(start))
- continue;
- free_reserved_page(virt_to_page(start));
- }
-}
-
-/*
- * This installs a clean page in the kernel's page table.
- */
-static struct page * __init
-put_kernel_page (struct page *page, unsigned long address, pgprot_t pgprot)
-{
- pgd_t *pgd;
- p4d_t *p4d;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
-
- pgd = pgd_offset_k(address); /* note: this is NOT pgd_offset()! */
-
- {
- p4d = p4d_alloc(&init_mm, pgd, address);
- if (!p4d)
- goto out;
- pud = pud_alloc(&init_mm, p4d, address);
- if (!pud)
- goto out;
- pmd = pmd_alloc(&init_mm, pud, address);
- if (!pmd)
- goto out;
- pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- goto out;
- if (!pte_none(*pte))
- goto out;
- set_pte(pte, mk_pte(page, pgprot));
- }
- out:
- /* no need for flush_tlb */
- return page;
-}
-
-static void __init
-setup_gate (void)
-{
- struct page *page;
-
- /*
- * Map the gate page twice: once read-only to export the ELF
- * headers etc. and once execute-only page to enable
- * privilege-promotion via "epc":
- */
- page = virt_to_page(ia64_imva(__start_gate_section));
- put_kernel_page(page, GATE_ADDR, PAGE_READONLY);
-#ifdef HAVE_BUGGY_SEGREL
- page = virt_to_page(ia64_imva(__start_gate_section + PAGE_SIZE));
- put_kernel_page(page, GATE_ADDR + PAGE_SIZE, PAGE_GATE);
-#else
- put_kernel_page(page, GATE_ADDR + PERCPU_PAGE_SIZE, PAGE_GATE);
- /* Fill in the holes (if any) with read-only zero pages: */
- {
- unsigned long addr;
-
- for (addr = GATE_ADDR + PAGE_SIZE;
- addr < GATE_ADDR + PERCPU_PAGE_SIZE;
- addr += PAGE_SIZE)
- {
- put_kernel_page(ZERO_PAGE(0), addr,
- PAGE_READONLY);
- put_kernel_page(ZERO_PAGE(0), addr + PERCPU_PAGE_SIZE,
- PAGE_READONLY);
- }
- }
-#endif
- ia64_patch_gate();
-}
-
-static struct vm_area_struct gate_vma;
-
-static int __init gate_vma_init(void)
-{
- vma_init(&gate_vma, NULL);
- gate_vma.vm_start = FIXADDR_USER_START;
- gate_vma.vm_end = FIXADDR_USER_END;
- vm_flags_init(&gate_vma, VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC);
- gate_vma.vm_page_prot = __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX);
-
- return 0;
-}
-__initcall(gate_vma_init);
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
- return &gate_vma;
-}
-
-int in_gate_area_no_mm(unsigned long addr)
-{
- if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
- return 1;
- return 0;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
- return in_gate_area_no_mm(addr);
-}
-
-void ia64_mmu_init(void *my_cpu_data)
-{
- unsigned long pta, impl_va_bits;
- extern void tlb_init(void);
-
-#ifdef CONFIG_DISABLE_VHPT
-# define VHPT_ENABLE_BIT 0
-#else
-# define VHPT_ENABLE_BIT 1
-#endif
-
- /*
- * Check if the virtually mapped linear page table (VMLPT) overlaps with a mapped
- * address space. The IA-64 architecture guarantees that at least 50 bits of
- * virtual address space are implemented but if we pick a large enough page size
- * (e.g., 64KB), the mapped address space is big enough that it will overlap with
- * VMLPT. I assume that once we run on machines big enough to warrant 64KB pages,
- * IMPL_VA_MSB will be significantly bigger, so this is unlikely to become a
- * problem in practice. Alternatively, we could truncate the top of the mapped
- * address space to not permit mappings that would overlap with the VMLPT.
- * --davidm 00/12/06
- */
-# define pte_bits 3
-# define mapped_space_bits (3*(PAGE_SHIFT - pte_bits) + PAGE_SHIFT)
- /*
- * The virtual page table has to cover the entire implemented address space within
- * a region even though not all of this space may be mappable. The reason for
- * this is that the Access bit and Dirty bit fault handlers perform
- * non-speculative accesses to the virtual page table, so the address range of the
- * virtual page table itself needs to be covered by virtual page table.
- */
-# define vmlpt_bits (impl_va_bits - PAGE_SHIFT + pte_bits)
-# define POW2(n) (1ULL << (n))
-
- impl_va_bits = ffz(~(local_cpu_data->unimpl_va_mask | (7UL << 61)));
-
- if (impl_va_bits < 51 || impl_va_bits > 61)
- panic("CPU has bogus IMPL_VA_MSB value of %lu!\n", impl_va_bits - 1);
- /*
- * mapped_space_bits - PAGE_SHIFT is the total number of ptes we need,
- * which must fit into "vmlpt_bits - pte_bits" slots. Second half of
- * the test makes sure that our mapped space doesn't overlap the
- * unimplemented hole in the middle of the region.
- */
- if ((mapped_space_bits - PAGE_SHIFT > vmlpt_bits - pte_bits) ||
- (mapped_space_bits > impl_va_bits - 1))
- panic("Cannot build a big enough virtual-linear page table"
- " to cover mapped address space.\n"
- " Try using a smaller page size.\n");
-
-
- /* place the VMLPT at the end of each page-table mapped region: */
- pta = POW2(61) - POW2(vmlpt_bits);
-
- /*
- * Set the (virtually mapped linear) page table address. Bit
- * 8 selects between the short and long format, bits 2-7 the
- * size of the table, and bit 0 whether the VHPT walker is
- * enabled.
- */
- ia64_set_pta(pta | (0 << 8) | (vmlpt_bits << 2) | VHPT_ENABLE_BIT);
-
- ia64_tlb_init();
-
-#ifdef CONFIG_HUGETLB_PAGE
- ia64_set_rr(HPAGE_REGION_BASE, HPAGE_SHIFT << 2);
- ia64_srlz_d();
-#endif
-}
-
-int __init register_active_ranges(u64 start, u64 len, int nid)
-{
- u64 end = start + len;
-
-#ifdef CONFIG_KEXEC
- if (start > crashk_res.start && start < crashk_res.end)
- start = crashk_res.end;
- if (end > crashk_res.start && end < crashk_res.end)
- end = crashk_res.start;
-#endif
-
- if (start < end)
- memblock_add_node(__pa(start), end - start, nid, MEMBLOCK_NONE);
- return 0;
-}
-
-int
-find_max_min_low_pfn (u64 start, u64 end, void *arg)
-{
- unsigned long pfn_start, pfn_end;
-#ifdef CONFIG_FLATMEM
- pfn_start = (PAGE_ALIGN(__pa(start))) >> PAGE_SHIFT;
- pfn_end = (PAGE_ALIGN(__pa(end - 1))) >> PAGE_SHIFT;
-#else
- pfn_start = GRANULEROUNDDOWN(__pa(start)) >> PAGE_SHIFT;
- pfn_end = GRANULEROUNDUP(__pa(end - 1)) >> PAGE_SHIFT;
-#endif
- min_low_pfn = min(min_low_pfn, pfn_start);
- max_low_pfn = max(max_low_pfn, pfn_end);
- return 0;
-}
-
-/*
- * Boot command-line option "nolwsys" can be used to disable the use of any light-weight
- * system call handler. When this option is in effect, all fsyscalls will end up bubbling
- * down into the kernel and calling the normal (heavy-weight) syscall handler. This is
- * useful for performance testing, but conceivably could also come in handy for debugging
- * purposes.
- */
-
-static int nolwsys __initdata;
-
-static int __init
-nolwsys_setup (char *s)
-{
- nolwsys = 1;
- return 1;
-}
-
-__setup("nolwsys", nolwsys_setup);
-
-void __init
-mem_init (void)
-{
- int i;
-
- BUG_ON(PTRS_PER_PGD * sizeof(pgd_t) != PAGE_SIZE);
- BUG_ON(PTRS_PER_PMD * sizeof(pmd_t) != PAGE_SIZE);
- BUG_ON(PTRS_PER_PTE * sizeof(pte_t) != PAGE_SIZE);
-
- /*
- * This needs to be called _after_ the command line has been parsed but
- * _before_ any drivers that may need the PCI DMA interface are
- * initialized or bootmem has been freed.
- */
- do {
-#ifdef CONFIG_INTEL_IOMMU
- detect_intel_iommu();
- if (iommu_detected)
- break;
-#endif
- swiotlb_init(true, SWIOTLB_VERBOSE);
- } while (0);
-
-#ifdef CONFIG_FLATMEM
- BUG_ON(!mem_map);
-#endif
-
- set_max_mapnr(max_low_pfn);
- high_memory = __va(max_low_pfn * PAGE_SIZE);
- memblock_free_all();
-
- /*
- * For fsyscall entrypoints with no light-weight handler, use the ordinary
- * (heavy-weight) handler, but mark it by setting bit 0, so the fsyscall entry
- * code can tell them apart.
- */
- for (i = 0; i < NR_syscalls; ++i) {
- extern unsigned long fsyscall_table[NR_syscalls];
- extern unsigned long sys_call_table[NR_syscalls];
-
- if (!fsyscall_table[i] || nolwsys)
- fsyscall_table[i] = sys_call_table[i] | 1;
- }
- setup_gate();
-}
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-int arch_add_memory(int nid, u64 start, u64 size,
- struct mhp_params *params)
-{
- unsigned long start_pfn = start >> PAGE_SHIFT;
- unsigned long nr_pages = size >> PAGE_SHIFT;
- int ret;
-
- if (WARN_ON_ONCE(params->pgprot.pgprot != PAGE_KERNEL.pgprot))
- return -EINVAL;
-
- ret = __add_pages(nid, start_pfn, nr_pages, params);
- if (ret)
- printk("%s: Problem encountered in __add_pages() as ret=%d\n",
- __func__, ret);
-
- return ret;
-}
-
-void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
-{
- unsigned long start_pfn = start >> PAGE_SHIFT;
- unsigned long nr_pages = size >> PAGE_SHIFT;
-
- __remove_pages(start_pfn, nr_pages, altmap);
-}
-#endif
-
-static const pgprot_t protection_map[16] = {
- [VM_NONE] = PAGE_NONE,
- [VM_READ] = PAGE_READONLY,
- [VM_WRITE] = PAGE_READONLY,
- [VM_WRITE | VM_READ] = PAGE_READONLY,
- [VM_EXEC] = __pgprot(__ACCESS_BITS | _PAGE_PL_3 |
- _PAGE_AR_X_RX),
- [VM_EXEC | VM_READ] = __pgprot(__ACCESS_BITS | _PAGE_PL_3 |
- _PAGE_AR_RX),
- [VM_EXEC | VM_WRITE] = PAGE_COPY_EXEC,
- [VM_EXEC | VM_WRITE | VM_READ] = PAGE_COPY_EXEC,
- [VM_SHARED] = PAGE_NONE,
- [VM_SHARED | VM_READ] = PAGE_READONLY,
- [VM_SHARED | VM_WRITE] = PAGE_SHARED,
- [VM_SHARED | VM_WRITE | VM_READ] = PAGE_SHARED,
- [VM_SHARED | VM_EXEC] = __pgprot(__ACCESS_BITS | _PAGE_PL_3 |
- _PAGE_AR_X_RX),
- [VM_SHARED | VM_EXEC | VM_READ] = __pgprot(__ACCESS_BITS | _PAGE_PL_3 |
- _PAGE_AR_RX),
- [VM_SHARED | VM_EXEC | VM_WRITE] = __pgprot(__ACCESS_BITS | _PAGE_PL_3 |
- _PAGE_AR_RWX),
- [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = __pgprot(__ACCESS_BITS | _PAGE_PL_3 |
- _PAGE_AR_RWX)
-};
-DECLARE_VM_GET_PAGE_PROT
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
deleted file mode 100644
index 711b6abc822e..000000000000
--- a/arch/ia64/mm/ioremap.c
+++ /dev/null
@@ -1,94 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * (c) Copyright 2006, 2007 Hewlett-Packard Development Company, L.P.
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- */
-
-#include <linux/compiler.h>
-#include <linux/module.h>
-#include <linux/efi.h>
-#include <linux/io.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <asm/io.h>
-#include <asm/meminit.h>
-
-static inline void __iomem *
-__ioremap_uc(unsigned long phys_addr)
-{
- return (void __iomem *) (__IA64_UNCACHED_OFFSET | phys_addr);
-}
-
-void __iomem *
-early_ioremap (unsigned long phys_addr, unsigned long size)
-{
- u64 attr;
- attr = kern_mem_attribute(phys_addr, size);
- if (attr & EFI_MEMORY_WB)
- return (void __iomem *) phys_to_virt(phys_addr);
- return __ioremap_uc(phys_addr);
-}
-
-void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
- unsigned long flags)
-{
- u64 attr;
- unsigned long gran_base, gran_size;
- unsigned long page_base;
-
- /*
- * For things in kern_memmap, we must use the same attribute
- * as the rest of the kernel. For more details, see
- * Documentation/arch/ia64/aliasing.rst.
- */
- attr = kern_mem_attribute(phys_addr, size);
- if (attr & EFI_MEMORY_WB)
- return (void __iomem *) phys_to_virt(phys_addr);
- else if (attr & EFI_MEMORY_UC)
- return __ioremap_uc(phys_addr);
-
- /*
- * Some chipsets don't support UC access to memory. If
- * WB is supported for the whole granule, we prefer that.
- */
- gran_base = GRANULEROUNDDOWN(phys_addr);
- gran_size = GRANULEROUNDUP(phys_addr + size) - gran_base;
- if (efi_mem_attribute(gran_base, gran_size) & EFI_MEMORY_WB)
- return (void __iomem *) phys_to_virt(phys_addr);
-
- /*
- * WB is not supported for the whole granule, so we can't use
- * the region 7 identity mapping. If we can safely cover the
- * area with kernel page table mappings, we can use those
- * instead.
- */
- page_base = phys_addr & PAGE_MASK;
- size = PAGE_ALIGN(phys_addr + size) - page_base;
- if (efi_mem_attribute(page_base, size) & EFI_MEMORY_WB)
- return generic_ioremap_prot(phys_addr, size, __pgprot(flags));
-
- return __ioremap_uc(phys_addr);
-}
-EXPORT_SYMBOL(ioremap_prot);
-
-void __iomem *
-ioremap_uc(unsigned long phys_addr, unsigned long size)
-{
- if (kern_mem_attribute(phys_addr, size) & EFI_MEMORY_WB)
- return NULL;
-
- return __ioremap_uc(phys_addr);
-}
-EXPORT_SYMBOL(ioremap_uc);
-
-void
-early_iounmap (volatile void __iomem *addr, unsigned long size)
-{
-}
-
-void iounmap(volatile void __iomem *addr)
-{
- if (REGION_NUMBER(addr) == RGN_GATE)
- vunmap((void *) ((unsigned long) addr & PAGE_MASK));
-}
-EXPORT_SYMBOL(iounmap);
diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c
deleted file mode 100644
index 4c7b1f50e3b7..000000000000
--- a/arch/ia64/mm/numa.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * This file contains NUMA specific variables and functions which are used on
- * NUMA machines with contiguous memory.
- *
- * 2002/08/07 Erich Focht <efocht@ess.nec.de>
- */
-
-#include <linux/cpu.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/node.h>
-#include <linux/init.h>
-#include <linux/memblock.h>
-#include <linux/module.h>
-#include <asm/mmzone.h>
-#include <asm/numa.h>
-
-
-/*
- * The following structures are usually initialized by ACPI or
- * similar mechanisms and describe the NUMA characteristics of the machine.
- */
-int num_node_memblks;
-struct node_memblk_s node_memblk[NR_NODE_MEMBLKS];
-struct node_cpuid_s node_cpuid[NR_CPUS] =
- { [0 ... NR_CPUS-1] = { .phys_id = 0, .nid = NUMA_NO_NODE } };
-
-/*
- * This is a matrix with "distances" between nodes, they should be
- * proportional to the memory access latency ratios.
- */
-u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
-
-int __node_distance(int from, int to)
-{
- return slit_distance(from, to);
-}
-EXPORT_SYMBOL(__node_distance);
-
-/* Identify which cnode a physical address resides on */
-int
-paddr_to_nid(unsigned long paddr)
-{
- int i;
-
- for (i = 0; i < num_node_memblks; i++)
- if (paddr >= node_memblk[i].start_paddr &&
- paddr < node_memblk[i].start_paddr + node_memblk[i].size)
- break;
-
- return (i < num_node_memblks) ? node_memblk[i].nid : (num_node_memblks ? -1 : 0);
-}
-EXPORT_SYMBOL(paddr_to_nid);
-
-#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_NUMA)
-void numa_clear_node(int cpu)
-{
- unmap_cpu_from_node(cpu, NUMA_NO_NODE);
-}
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-/*
- * SRAT information is stored in node_memblk[], then we can use SRAT
- * information at memory-hot-add if necessary.
- */
-
-int memory_add_physaddr_to_nid(u64 addr)
-{
- int nid = paddr_to_nid(addr);
- if (nid < 0)
- return 0;
- return nid;
-}
-EXPORT_SYMBOL(memory_add_physaddr_to_nid);
-#endif
-#endif
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
deleted file mode 100644
index ca060e7a2a46..000000000000
--- a/arch/ia64/mm/tlb.c
+++ /dev/null
@@ -1,591 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * TLB support routines.
- *
- * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * 08/02/00 A. Mallick <asit.k.mallick@intel.com>
- * Modified RID allocation for SMP
- * Goutham Rao <goutham.rao@intel.com>
- * IPI based ptc implementation and A-step IPI implementation.
- * Rohit Seth <rohit.seth@intel.com>
- * Ken Chen <kenneth.w.chen@intel.com>
- * Christophe de Dinechin <ddd@hp.com>: Avoid ptc.e on memory allocation
- * Copyright (C) 2007 Intel Corp
- * Fenghua Yu <fenghua.yu@intel.com>
- * Add multiple ptc.g/ptc.ga instruction support in global tlb purge.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/mm.h>
-#include <linux/memblock.h>
-#include <linux/slab.h>
-
-#include <asm/delay.h>
-#include <asm/mmu_context.h>
-#include <asm/pal.h>
-#include <asm/tlbflush.h>
-#include <asm/dma.h>
-#include <asm/processor.h>
-#include <asm/sal.h>
-#include <asm/tlb.h>
-
-static struct {
- u64 mask; /* mask of supported purge page-sizes */
- unsigned long max_bits; /* log2 of largest supported purge page-size */
-} purge;
-
-struct ia64_ctx ia64_ctx = {
- .lock = __SPIN_LOCK_UNLOCKED(ia64_ctx.lock),
- .next = 1,
- .max_ctx = ~0U
-};
-
-DEFINE_PER_CPU(u8, ia64_need_tlb_flush);
-DEFINE_PER_CPU(u8, ia64_tr_num); /*Number of TR slots in current processor*/
-DEFINE_PER_CPU(u8, ia64_tr_used); /*Max Slot number used by kernel*/
-
-struct ia64_tr_entry *ia64_idtrs[NR_CPUS];
-
-/*
- * Initializes the ia64_ctx.bitmap array based on max_ctx+1.
- * Called after cpu_init() has setup ia64_ctx.max_ctx based on
- * maximum RID that is supported by boot CPU.
- */
-void __init
-mmu_context_init (void)
-{
- ia64_ctx.bitmap = memblock_alloc((ia64_ctx.max_ctx + 1) >> 3,
- SMP_CACHE_BYTES);
- if (!ia64_ctx.bitmap)
- panic("%s: Failed to allocate %u bytes\n", __func__,
- (ia64_ctx.max_ctx + 1) >> 3);
- ia64_ctx.flushmap = memblock_alloc((ia64_ctx.max_ctx + 1) >> 3,
- SMP_CACHE_BYTES);
- if (!ia64_ctx.flushmap)
- panic("%s: Failed to allocate %u bytes\n", __func__,
- (ia64_ctx.max_ctx + 1) >> 3);
-}
-
-/*
- * Acquire the ia64_ctx.lock before calling this function!
- */
-void
-wrap_mmu_context (struct mm_struct *mm)
-{
- int i, cpu;
- unsigned long flush_bit;
-
- for (i=0; i <= ia64_ctx.max_ctx / BITS_PER_LONG; i++) {
- flush_bit = xchg(&ia64_ctx.flushmap[i], 0);
- ia64_ctx.bitmap[i] ^= flush_bit;
- }
-
- /* use offset at 300 to skip daemons */
- ia64_ctx.next = find_next_zero_bit(ia64_ctx.bitmap,
- ia64_ctx.max_ctx, 300);
- ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap,
- ia64_ctx.max_ctx, ia64_ctx.next);
-
- /*
- * can't call flush_tlb_all() here because of race condition
- * with O(1) scheduler [EF]
- */
- cpu = get_cpu(); /* prevent preemption/migration */
- for_each_online_cpu(i)
- if (i != cpu)
- per_cpu(ia64_need_tlb_flush, i) = 1;
- put_cpu();
- local_flush_tlb_all();
-}
-
-/*
- * Implement "spinaphores" ... like counting semaphores, but they
- * spin instead of sleeping. If there are ever any other users for
- * this primitive it can be moved up to a spinaphore.h header.
- */
-struct spinaphore {
- unsigned long ticket;
- unsigned long serve;
-};
-
-static inline void spinaphore_init(struct spinaphore *ss, int val)
-{
- ss->ticket = 0;
- ss->serve = val;
-}
-
-static inline void down_spin(struct spinaphore *ss)
-{
- unsigned long t = ia64_fetchadd(1, &ss->ticket, acq), serve;
-
- if (time_before(t, ss->serve))
- return;
-
- ia64_invala();
-
- for (;;) {
- asm volatile ("ld8.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory");
- if (time_before(t, serve))
- return;
- cpu_relax();
- }
-}
-
-static inline void up_spin(struct spinaphore *ss)
-{
- ia64_fetchadd(1, &ss->serve, rel);
-}
-
-static struct spinaphore ptcg_sem;
-static u16 nptcg = 1;
-static int need_ptcg_sem = 1;
-static int toolatetochangeptcgsem = 0;
-
-/*
- * Kernel parameter "nptcg=" overrides max number of concurrent global TLB
- * purges which is reported from either PAL or SAL PALO.
- *
- * We don't have sanity checking for nptcg value. It's the user's responsibility
- * for valid nptcg value on the platform. Otherwise, kernel may hang in some
- * cases.
- */
-static int __init
-set_nptcg(char *str)
-{
- int value = 0;
-
- get_option(&str, &value);
- setup_ptcg_sem(value, NPTCG_FROM_KERNEL_PARAMETER);
-
- return 1;
-}
-
-__setup("nptcg=", set_nptcg);
-
-/*
- * Maximum number of simultaneous ptc.g purges in the system can
- * be defined by PAL_VM_SUMMARY (in which case we should take
- * the smallest value for any cpu in the system) or by the PAL
- * override table (in which case we should ignore the value from
- * PAL_VM_SUMMARY).
- *
- * Kernel parameter "nptcg=" overrides maximum number of simultaneous ptc.g
- * purges defined in either PAL_VM_SUMMARY or PAL override table. In this case,
- * we should ignore the value from either PAL_VM_SUMMARY or PAL override table.
- *
- * Complicating the logic here is the fact that num_possible_cpus()
- * isn't fully setup until we start bringing cpus online.
- */
-void
-setup_ptcg_sem(int max_purges, int nptcg_from)
-{
- static int kp_override;
- static int palo_override;
- static int firstcpu = 1;
-
- if (toolatetochangeptcgsem) {
- if (nptcg_from == NPTCG_FROM_PAL && max_purges == 0)
- BUG_ON(1 < nptcg);
- else
- BUG_ON(max_purges < nptcg);
- return;
- }
-
- if (nptcg_from == NPTCG_FROM_KERNEL_PARAMETER) {
- kp_override = 1;
- nptcg = max_purges;
- goto resetsema;
- }
- if (kp_override) {
- need_ptcg_sem = num_possible_cpus() > nptcg;
- return;
- }
-
- if (nptcg_from == NPTCG_FROM_PALO) {
- palo_override = 1;
-
- /* In PALO max_purges == 0 really means it! */
- if (max_purges == 0)
- panic("Whoa! Platform does not support global TLB purges.\n");
- nptcg = max_purges;
- if (nptcg == PALO_MAX_TLB_PURGES) {
- need_ptcg_sem = 0;
- return;
- }
- goto resetsema;
- }
- if (palo_override) {
- if (nptcg != PALO_MAX_TLB_PURGES)
- need_ptcg_sem = (num_possible_cpus() > nptcg);
- return;
- }
-
- /* In PAL_VM_SUMMARY max_purges == 0 actually means 1 */
- if (max_purges == 0) max_purges = 1;
-
- if (firstcpu) {
- nptcg = max_purges;
- firstcpu = 0;
- }
- if (max_purges < nptcg)
- nptcg = max_purges;
- if (nptcg == PAL_MAX_PURGES) {
- need_ptcg_sem = 0;
- return;
- } else
- need_ptcg_sem = (num_possible_cpus() > nptcg);
-
-resetsema:
- spinaphore_init(&ptcg_sem, max_purges);
-}
-
-#ifdef CONFIG_SMP
-static void
-ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
- unsigned long end, unsigned long nbits)
-{
- struct mm_struct *active_mm = current->active_mm;
-
- toolatetochangeptcgsem = 1;
-
- if (mm != active_mm) {
- /* Restore region IDs for mm */
- if (mm && active_mm) {
- activate_context(mm);
- } else {
- flush_tlb_all();
- return;
- }
- }
-
- if (need_ptcg_sem)
- down_spin(&ptcg_sem);
-
- do {
- /*
- * Flush ALAT entries also.
- */
- ia64_ptcga(start, (nbits << 2));
- ia64_srlz_i();
- start += (1UL << nbits);
- } while (start < end);
-
- if (need_ptcg_sem)
- up_spin(&ptcg_sem);
-
- if (mm != active_mm) {
- activate_context(active_mm);
- }
-}
-#endif /* CONFIG_SMP */
-
-void
-local_flush_tlb_all (void)
-{
- unsigned long i, j, flags, count0, count1, stride0, stride1, addr;
-
- addr = local_cpu_data->ptce_base;
- count0 = local_cpu_data->ptce_count[0];
- count1 = local_cpu_data->ptce_count[1];
- stride0 = local_cpu_data->ptce_stride[0];
- stride1 = local_cpu_data->ptce_stride[1];
-
- local_irq_save(flags);
- for (i = 0; i < count0; ++i) {
- for (j = 0; j < count1; ++j) {
- ia64_ptce(addr);
- addr += stride1;
- }
- addr += stride0;
- }
- local_irq_restore(flags);
- ia64_srlz_i(); /* srlz.i implies srlz.d */
-}
-
-static void
-__flush_tlb_range (struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
- unsigned long size = end - start;
- unsigned long nbits;
-
-#ifndef CONFIG_SMP
- if (mm != current->active_mm) {
- mm->context = 0;
- return;
- }
-#endif
-
- nbits = ia64_fls(size + 0xfff);
- while (unlikely (((1UL << nbits) & purge.mask) == 0) &&
- (nbits < purge.max_bits))
- ++nbits;
- if (nbits > purge.max_bits)
- nbits = purge.max_bits;
- start &= ~((1UL << nbits) - 1);
-
- preempt_disable();
-#ifdef CONFIG_SMP
- if (mm != current->active_mm || cpumask_weight(mm_cpumask(mm)) != 1) {
- ia64_global_tlb_purge(mm, start, end, nbits);
- preempt_enable();
- return;
- }
-#endif
- do {
- ia64_ptcl(start, (nbits<<2));
- start += (1UL << nbits);
- } while (start < end);
- preempt_enable();
- ia64_srlz_i(); /* srlz.i implies srlz.d */
-}
-
-void flush_tlb_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
-{
- if (unlikely(end - start >= 1024*1024*1024*1024UL
- || REGION_NUMBER(start) != REGION_NUMBER(end - 1))) {
- /*
- * If we flush more than a tera-byte or across regions, we're
- * probably better off just flushing the entire TLB(s). This
- * should be very rare and is not worth optimizing for.
- */
- flush_tlb_all();
- } else {
- /* flush the address range from the tlb */
- __flush_tlb_range(vma, start, end);
- /* flush the virt. page-table area mapping the addr range */
- __flush_tlb_range(vma, ia64_thash(start), ia64_thash(end));
- }
-}
-EXPORT_SYMBOL(flush_tlb_range);
-
-void ia64_tlb_init(void)
-{
- ia64_ptce_info_t ptce_info;
- u64 tr_pgbits;
- long status;
- pal_vm_info_1_u_t vm_info_1;
- pal_vm_info_2_u_t vm_info_2;
- int cpu = smp_processor_id();
-
- if ((status = ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) != 0) {
- printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld; "
- "defaulting to architected purge page-sizes.\n", status);
- purge.mask = 0x115557000UL;
- }
- purge.max_bits = ia64_fls(purge.mask);
-
- ia64_get_ptce(&ptce_info);
- local_cpu_data->ptce_base = ptce_info.base;
- local_cpu_data->ptce_count[0] = ptce_info.count[0];
- local_cpu_data->ptce_count[1] = ptce_info.count[1];
- local_cpu_data->ptce_stride[0] = ptce_info.stride[0];
- local_cpu_data->ptce_stride[1] = ptce_info.stride[1];
-
- local_flush_tlb_all(); /* nuke left overs from bootstrapping... */
- status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2);
-
- if (status) {
- printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
- per_cpu(ia64_tr_num, cpu) = 8;
- return;
- }
- per_cpu(ia64_tr_num, cpu) = vm_info_1.pal_vm_info_1_s.max_itr_entry+1;
- if (per_cpu(ia64_tr_num, cpu) >
- (vm_info_1.pal_vm_info_1_s.max_dtr_entry+1))
- per_cpu(ia64_tr_num, cpu) =
- vm_info_1.pal_vm_info_1_s.max_dtr_entry+1;
- if (per_cpu(ia64_tr_num, cpu) > IA64_TR_ALLOC_MAX) {
- static int justonce = 1;
- per_cpu(ia64_tr_num, cpu) = IA64_TR_ALLOC_MAX;
- if (justonce) {
- justonce = 0;
- printk(KERN_DEBUG "TR register number exceeds "
- "IA64_TR_ALLOC_MAX!\n");
- }
- }
-}
-
-/*
- * is_tr_overlap
- *
- * Check overlap with inserted TRs.
- */
-static int is_tr_overlap(struct ia64_tr_entry *p, u64 va, u64 log_size)
-{
- u64 tr_log_size;
- u64 tr_end;
- u64 va_rr = ia64_get_rr(va);
- u64 va_rid = RR_TO_RID(va_rr);
- u64 va_end = va + (1<<log_size) - 1;
-
- if (va_rid != RR_TO_RID(p->rr))
- return 0;
- tr_log_size = (p->itir & 0xff) >> 2;
- tr_end = p->ifa + (1<<tr_log_size) - 1;
-
- if (va > tr_end || p->ifa > va_end)
- return 0;
- return 1;
-
-}
-
-/*
- * ia64_insert_tr in virtual mode. Allocate a TR slot
- *
- * target_mask : 0x1 : itr, 0x2 : dtr, 0x3 : idtr
- *
- * va : virtual address.
- * pte : pte entries inserted.
- * log_size: range to be covered.
- *
- * Return value: <0 : error No.
- *
- * >=0 : slot number allocated for TR.
- * Must be called with preemption disabled.
- */
-int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size)
-{
- int i, r;
- unsigned long psr;
- struct ia64_tr_entry *p;
- int cpu = smp_processor_id();
-
- if (!ia64_idtrs[cpu]) {
- ia64_idtrs[cpu] = kmalloc_array(2 * IA64_TR_ALLOC_MAX,
- sizeof(struct ia64_tr_entry),
- GFP_KERNEL);
- if (!ia64_idtrs[cpu])
- return -ENOMEM;
- }
- r = -EINVAL;
- /*Check overlap with existing TR entries*/
- if (target_mask & 0x1) {
- p = ia64_idtrs[cpu];
- for (i = IA64_TR_ALLOC_BASE; i <= per_cpu(ia64_tr_used, cpu);
- i++, p++) {
- if (p->pte & 0x1)
- if (is_tr_overlap(p, va, log_size)) {
- printk(KERN_DEBUG "Overlapped Entry"
- "Inserted for TR Register!!\n");
- goto out;
- }
- }
- }
- if (target_mask & 0x2) {
- p = ia64_idtrs[cpu] + IA64_TR_ALLOC_MAX;
- for (i = IA64_TR_ALLOC_BASE; i <= per_cpu(ia64_tr_used, cpu);
- i++, p++) {
- if (p->pte & 0x1)
- if (is_tr_overlap(p, va, log_size)) {
- printk(KERN_DEBUG "Overlapped Entry"
- "Inserted for TR Register!!\n");
- goto out;
- }
- }
- }
-
- for (i = IA64_TR_ALLOC_BASE; i < per_cpu(ia64_tr_num, cpu); i++) {
- switch (target_mask & 0x3) {
- case 1:
- if (!((ia64_idtrs[cpu] + i)->pte & 0x1))
- goto found;
- continue;
- case 2:
- if (!((ia64_idtrs[cpu] + IA64_TR_ALLOC_MAX + i)->pte & 0x1))
- goto found;
- continue;
- case 3:
- if (!((ia64_idtrs[cpu] + i)->pte & 0x1) &&
- !((ia64_idtrs[cpu] + IA64_TR_ALLOC_MAX + i)->pte & 0x1))
- goto found;
- continue;
- default:
- r = -EINVAL;
- goto out;
- }
- }
-found:
- if (i >= per_cpu(ia64_tr_num, cpu))
- return -EBUSY;
-
- /*Record tr info for mca handler use!*/
- if (i > per_cpu(ia64_tr_used, cpu))
- per_cpu(ia64_tr_used, cpu) = i;
-
- psr = ia64_clear_ic();
- if (target_mask & 0x1) {
- ia64_itr(0x1, i, va, pte, log_size);
- ia64_srlz_i();
- p = ia64_idtrs[cpu] + i;
- p->ifa = va;
- p->pte = pte;
- p->itir = log_size << 2;
- p->rr = ia64_get_rr(va);
- }
- if (target_mask & 0x2) {
- ia64_itr(0x2, i, va, pte, log_size);
- ia64_srlz_i();
- p = ia64_idtrs[cpu] + IA64_TR_ALLOC_MAX + i;
- p->ifa = va;
- p->pte = pte;
- p->itir = log_size << 2;
- p->rr = ia64_get_rr(va);
- }
- ia64_set_psr(psr);
- r = i;
-out:
- return r;
-}
-EXPORT_SYMBOL_GPL(ia64_itr_entry);
-
-/*
- * ia64_purge_tr
- *
- * target_mask: 0x1: purge itr, 0x2 : purge dtr, 0x3 purge idtr.
- * slot: slot number to be freed.
- *
- * Must be called with preemption disabled.
- */
-void ia64_ptr_entry(u64 target_mask, int slot)
-{
- int cpu = smp_processor_id();
- int i;
- struct ia64_tr_entry *p;
-
- if (slot < IA64_TR_ALLOC_BASE || slot >= per_cpu(ia64_tr_num, cpu))
- return;
-
- if (target_mask & 0x1) {
- p = ia64_idtrs[cpu] + slot;
- if ((p->pte&0x1) && is_tr_overlap(p, p->ifa, p->itir>>2)) {
- p->pte = 0;
- ia64_ptr(0x1, p->ifa, p->itir>>2);
- ia64_srlz_i();
- }
- }
-
- if (target_mask & 0x2) {
- p = ia64_idtrs[cpu] + IA64_TR_ALLOC_MAX + slot;
- if ((p->pte & 0x1) && is_tr_overlap(p, p->ifa, p->itir>>2)) {
- p->pte = 0;
- ia64_ptr(0x2, p->ifa, p->itir>>2);
- ia64_srlz_i();
- }
- }
-
- for (i = per_cpu(ia64_tr_used, cpu); i >= IA64_TR_ALLOC_BASE; i--) {
- if (((ia64_idtrs[cpu] + i)->pte & 0x1) ||
- ((ia64_idtrs[cpu] + IA64_TR_ALLOC_MAX + i)->pte & 0x1))
- break;
- }
- per_cpu(ia64_tr_used, cpu) = i;
-}
-EXPORT_SYMBOL_GPL(ia64_ptr_entry);
diff --git a/arch/ia64/pci/Makefile b/arch/ia64/pci/Makefile
deleted file mode 100644
index 81ea50eeb527..000000000000
--- a/arch/ia64/pci/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for the ia64-specific parts of the pci bus
-#
-obj-y := pci.o fixup.o
diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c
deleted file mode 100644
index 2bcdd7d3a1ad..000000000000
--- a/arch/ia64/pci/fixup.c
+++ /dev/null
@@ -1,80 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
- * Derived from fixup.c of i386 tree.
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/vgaarb.h>
-#include <linux/screen_info.h>
-#include <asm/uv/uv.h>
-
-/*
- * Fixup to mark boot BIOS video selected by BIOS before it changes
- *
- * From information provided by "Jon Smirl" <jonsmirl@gmail.com>
- *
- * The standard boot ROM sequence for an x86 machine uses the BIOS
- * to select an initial video card for boot display. This boot video
- * card will have its BIOS copied to 0xC0000 in system RAM.
- * IORESOURCE_ROM_SHADOW is used to associate the boot video
- * card with this copy. On laptops this copy has to be used since
- * the main ROM may be compressed or combined with another image.
- * See pci_map_rom() for use of this flag. Before marking the device
- * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
- * by either arch code or vga-arbitration; if so only apply the fixup to this
- * already-determined primary video card.
- */
-
-static void pci_fixup_video(struct pci_dev *pdev)
-{
- struct pci_dev *bridge;
- struct pci_bus *bus;
- u16 config;
- struct resource *res;
-
- if (is_uv_system())
- return;
- /* Maybe, this machine supports legacy memory map. */
-
- /* Is VGA routed to us? */
- bus = pdev->bus;
- while (bus) {
- bridge = bus->self;
-
- /*
- * From information provided by
- * "David Miller" <davem@davemloft.net>
- * The bridge control register is valid for PCI header
- * type BRIDGE, or CARDBUS. Host to PCI controllers use
- * PCI header type NORMAL.
- */
- if (bridge && (pci_is_bridge(bridge))) {
- pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
- &config);
- if (!(config & PCI_BRIDGE_CTL_VGA))
- return;
- }
- bus = bus->parent;
- }
- if (!vga_default_device() || pdev == vga_default_device()) {
- pci_read_config_word(pdev, PCI_COMMAND, &config);
- if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
- res = &pdev->resource[PCI_ROM_RESOURCE];
-
- pci_disable_rom(pdev);
- if (res->parent)
- release_resource(res);
-
- res->start = 0xC0000;
- res->end = res->start + 0x20000 - 1;
- res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
- IORESOURCE_PCI_FIXED;
- dev_info(&pdev->dev, "Video device with shadowed ROM at %pR\n",
- res);
- }
- }
-}
-DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video);
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
deleted file mode 100644
index 0a0328e61bef..000000000000
--- a/arch/ia64/pci/pci.c
+++ /dev/null
@@ -1,576 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * pci.c - Low-Level PCI Access in IA-64
- *
- * Derived from bios32.c of i386 tree.
- *
- * (c) Copyright 2002, 2005 Hewlett-Packard Development Company, L.P.
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- * Copyright (C) 2004 Silicon Graphics, Inc.
- *
- * Note: Above list of copyright holders is incomplete...
- */
-
-#include <linux/acpi.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/pci-acpi.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/memblock.h>
-#include <linux/export.h>
-
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/sal.h>
-#include <asm/smp.h>
-#include <asm/irq.h>
-#include <asm/hw_irq.h>
-
-/*
- * Low-level SAL-based PCI configuration access functions. Note that SAL
- * calls are already serialized (via sal_lock), so we don't need another
- * synchronization mechanism here.
- */
-
-#define PCI_SAL_ADDRESS(seg, bus, devfn, reg) \
- (((u64) seg << 24) | (bus << 16) | (devfn << 8) | (reg))
-
-/* SAL 3.2 adds support for extended config space. */
-
-#define PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg) \
- (((u64) seg << 28) | (bus << 20) | (devfn << 12) | (reg))
-
-int raw_pci_read(unsigned int seg, unsigned int bus, unsigned int devfn,
- int reg, int len, u32 *value)
-{
- u64 addr, data = 0;
- int mode, result;
-
- if (!value || (seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
- return -EINVAL;
-
- if ((seg | reg) <= 255) {
- addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg);
- mode = 0;
- } else if (sal_revision >= SAL_VERSION_CODE(3,2)) {
- addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg);
- mode = 1;
- } else {
- return -EINVAL;
- }
-
- result = ia64_sal_pci_config_read(addr, mode, len, &data);
- if (result != 0)
- return -EINVAL;
-
- *value = (u32) data;
- return 0;
-}
-
-int raw_pci_write(unsigned int seg, unsigned int bus, unsigned int devfn,
- int reg, int len, u32 value)
-{
- u64 addr;
- int mode, result;
-
- if ((seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
- return -EINVAL;
-
- if ((seg | reg) <= 255) {
- addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg);
- mode = 0;
- } else if (sal_revision >= SAL_VERSION_CODE(3,2)) {
- addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg);
- mode = 1;
- } else {
- return -EINVAL;
- }
- result = ia64_sal_pci_config_write(addr, mode, len, value);
- if (result != 0)
- return -EINVAL;
- return 0;
-}
-
-static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
- int size, u32 *value)
-{
- return raw_pci_read(pci_domain_nr(bus), bus->number,
- devfn, where, size, value);
-}
-
-static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
- int size, u32 value)
-{
- return raw_pci_write(pci_domain_nr(bus), bus->number,
- devfn, where, size, value);
-}
-
-struct pci_ops pci_root_ops = {
- .read = pci_read,
- .write = pci_write,
-};
-
-struct pci_root_info {
- struct acpi_pci_root_info common;
- struct pci_controller controller;
- struct list_head io_resources;
-};
-
-static unsigned int new_space(u64 phys_base, int sparse)
-{
- u64 mmio_base;
- int i;
-
- if (phys_base == 0)
- return 0; /* legacy I/O port space */
-
- mmio_base = (u64) ioremap(phys_base, 0);
- for (i = 0; i < num_io_spaces; i++)
- if (io_space[i].mmio_base == mmio_base &&
- io_space[i].sparse == sparse)
- return i;
-
- if (num_io_spaces == MAX_IO_SPACES) {
- pr_err("PCI: Too many IO port spaces "
- "(MAX_IO_SPACES=%lu)\n", MAX_IO_SPACES);
- return ~0;
- }
-
- i = num_io_spaces++;
- io_space[i].mmio_base = mmio_base;
- io_space[i].sparse = sparse;
-
- return i;
-}
-
-static int add_io_space(struct device *dev, struct pci_root_info *info,
- struct resource_entry *entry)
-{
- struct resource_entry *iospace;
- struct resource *resource, *res = entry->res;
- char *name;
- unsigned long base, min, max, base_port;
- unsigned int sparse = 0, space_nr, len;
-
- len = strlen(info->common.name) + 32;
- iospace = resource_list_create_entry(NULL, len);
- if (!iospace) {
- dev_err(dev, "PCI: No memory for %s I/O port space\n",
- info->common.name);
- return -ENOMEM;
- }
-
- if (res->flags & IORESOURCE_IO_SPARSE)
- sparse = 1;
- space_nr = new_space(entry->offset, sparse);
- if (space_nr == ~0)
- goto free_resource;
-
- name = (char *)(iospace + 1);
- min = res->start - entry->offset;
- max = res->end - entry->offset;
- base = __pa(io_space[space_nr].mmio_base);
- base_port = IO_SPACE_BASE(space_nr);
- snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->common.name,
- base_port + min, base_port + max);
-
- /*
- * The SDM guarantees the legacy 0-64K space is sparse, but if the
- * mapping is done by the processor (not the bridge), ACPI may not
- * mark it as sparse.
- */
- if (space_nr == 0)
- sparse = 1;
-
- resource = iospace->res;
- resource->name = name;
- resource->flags = IORESOURCE_MEM;
- resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min);
- resource->end = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max);
- if (insert_resource(&iomem_resource, resource)) {
- dev_err(dev,
- "can't allocate host bridge io space resource %pR\n",
- resource);
- goto free_resource;
- }
-
- entry->offset = base_port;
- res->start = min + base_port;
- res->end = max + base_port;
- resource_list_add_tail(iospace, &info->io_resources);
-
- return 0;
-
-free_resource:
- resource_list_free_entry(iospace);
- return -ENOSPC;
-}
-
-/*
- * An IO port or MMIO resource assigned to a PCI host bridge may be
- * consumed by the host bridge itself or available to its child
- * bus/devices. The ACPI specification defines a bit (Producer/Consumer)
- * to tell whether the resource is consumed by the host bridge itself,
- * but firmware hasn't used that bit consistently, so we can't rely on it.
- *
- * On x86 and IA64 platforms, all IO port and MMIO resources are assumed
- * to be available to child bus/devices except one special case:
- * IO port [0xCF8-0xCFF] is consumed by the host bridge itself
- * to access PCI configuration space.
- *
- * So explicitly filter out PCI CFG IO ports[0xCF8-0xCFF].
- */
-static bool resource_is_pcicfg_ioport(struct resource *res)
-{
- return (res->flags & IORESOURCE_IO) &&
- res->start == 0xCF8 && res->end == 0xCFF;
-}
-
-static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci)
-{
- struct device *dev = &ci->bridge->dev;
- struct pci_root_info *info;
- struct resource *res;
- struct resource_entry *entry, *tmp;
- int status;
-
- status = acpi_pci_probe_root_resources(ci);
- if (status > 0) {
- info = container_of(ci, struct pci_root_info, common);
- resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
- res = entry->res;
- if (res->flags & IORESOURCE_MEM) {
- /*
- * HP's firmware has a hack to work around a
- * Windows bug. Ignore these tiny memory ranges.
- */
- if (resource_size(res) <= 16) {
- resource_list_del(entry);
- insert_resource(&iomem_resource,
- entry->res);
- resource_list_add_tail(entry,
- &info->io_resources);
- }
- } else if (res->flags & IORESOURCE_IO) {
- if (resource_is_pcicfg_ioport(entry->res))
- resource_list_destroy_entry(entry);
- else if (add_io_space(dev, info, entry))
- resource_list_destroy_entry(entry);
- }
- }
- }
-
- return status;
-}
-
-static void pci_acpi_root_release_info(struct acpi_pci_root_info *ci)
-{
- struct pci_root_info *info;
- struct resource_entry *entry, *tmp;
-
- info = container_of(ci, struct pci_root_info, common);
- resource_list_for_each_entry_safe(entry, tmp, &info->io_resources) {
- release_resource(entry->res);
- resource_list_destroy_entry(entry);
- }
- kfree(info);
-}
-
-static struct acpi_pci_root_ops pci_acpi_root_ops = {
- .pci_ops = &pci_root_ops,
- .release_info = pci_acpi_root_release_info,
- .prepare_resources = pci_acpi_root_prepare_resources,
-};
-
-struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
-{
- struct acpi_device *device = root->device;
- struct pci_root_info *info;
-
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
- dev_err(&device->dev,
- "pci_bus %04x:%02x: ignored (out of memory)\n",
- root->segment, (int)root->secondary.start);
- return NULL;
- }
-
- info->controller.segment = root->segment;
- info->controller.companion = device;
- info->controller.node = acpi_get_node(device->handle);
- INIT_LIST_HEAD(&info->io_resources);
- return acpi_pci_root_create(root, &pci_acpi_root_ops,
- &info->common, &info->controller);
-}
-
-int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
-{
- /*
- * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL
- * here, pci_create_root_bus() has been called by someone else and
- * sysdata is likely to be different from what we expect. Let it go in
- * that case.
- */
- if (!bridge->dev.parent) {
- struct pci_controller *controller = bridge->bus->sysdata;
- ACPI_COMPANION_SET(&bridge->dev, controller->companion);
- }
- return 0;
-}
-
-void pcibios_fixup_device_resources(struct pci_dev *dev)
-{
- int idx;
-
- if (!dev->bus)
- return;
-
- for (idx = 0; idx < PCI_BRIDGE_RESOURCES; idx++) {
- struct resource *r = &dev->resource[idx];
-
- if (!r->flags || r->parent || !r->start)
- continue;
-
- pci_claim_resource(dev, idx);
- }
-}
-EXPORT_SYMBOL_GPL(pcibios_fixup_device_resources);
-
-static void pcibios_fixup_bridge_resources(struct pci_dev *dev)
-{
- int idx;
-
- if (!dev->bus)
- return;
-
- for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
- struct resource *r = &dev->resource[idx];
-
- if (!r->flags || r->parent || !r->start)
- continue;
-
- pci_claim_bridge_resource(dev, idx);
- }
-}
-
-/*
- * Called after each bus is probed, but before its children are examined.
- */
-void pcibios_fixup_bus(struct pci_bus *b)
-{
- struct pci_dev *dev;
-
- if (b->self) {
- pci_read_bridge_bases(b);
- pcibios_fixup_bridge_resources(b->self);
- }
- list_for_each_entry(dev, &b->devices, bus_list)
- pcibios_fixup_device_resources(dev);
-}
-
-void pcibios_add_bus(struct pci_bus *bus)
-{
- acpi_pci_add_bus(bus);
-}
-
-void pcibios_remove_bus(struct pci_bus *bus)
-{
- acpi_pci_remove_bus(bus);
-}
-
-void pcibios_set_master (struct pci_dev *dev)
-{
- /* No special bus mastering setup handling */
-}
-
-int
-pcibios_enable_device (struct pci_dev *dev, int mask)
-{
- int ret;
-
- ret = pci_enable_resources(dev, mask);
- if (ret < 0)
- return ret;
-
- if (!pci_dev_msi_enabled(dev))
- return acpi_pci_irq_enable(dev);
- return 0;
-}
-
-void
-pcibios_disable_device (struct pci_dev *dev)
-{
- BUG_ON(atomic_read(&dev->enable_cnt));
- if (!pci_dev_msi_enabled(dev))
- acpi_pci_irq_disable(dev);
-}
-
-/**
- * pci_get_legacy_mem - generic legacy mem routine
- * @bus: bus to get legacy memory base address for
- *
- * Find the base of legacy memory for @bus. This is typically the first
- * megabyte of bus address space for @bus or is simply 0 on platforms whose
- * chipsets support legacy I/O and memory routing. Returns the base address
- * or an error pointer if an error occurred.
- *
- * This is the ia64 generic version of this routine. Other platforms
- * are free to override it with a machine vector.
- */
-char *pci_get_legacy_mem(struct pci_bus *bus)
-{
- return (char *)__IA64_UNCACHED_OFFSET;
-}
-
-/**
- * pci_mmap_legacy_page_range - map legacy memory space to userland
- * @bus: bus whose legacy space we're mapping
- * @vma: vma passed in by mmap
- *
- * Map legacy memory space for this device back to userspace using a machine
- * vector to get the base address.
- */
-int
-pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state)
-{
- unsigned long size = vma->vm_end - vma->vm_start;
- pgprot_t prot;
- char *addr;
-
- /* We only support mmap'ing of legacy memory space */
- if (mmap_state != pci_mmap_mem)
- return -ENOSYS;
-
- /*
- * Avoid attribute aliasing. See Documentation/arch/ia64/aliasing.rst
- * for more details.
- */
- if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
- return -EINVAL;
- prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size,
- vma->vm_page_prot);
-
- addr = pci_get_legacy_mem(bus);
- if (IS_ERR(addr))
- return PTR_ERR(addr);
-
- vma->vm_pgoff += (unsigned long)addr >> PAGE_SHIFT;
- vma->vm_page_prot = prot;
-
- if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- size, vma->vm_page_prot))
- return -EAGAIN;
-
- return 0;
-}
-
-/**
- * pci_legacy_read - read from legacy I/O space
- * @bus: bus to read
- * @port: legacy port value
- * @val: caller allocated storage for returned value
- * @size: number of bytes to read
- *
- * Simply reads @size bytes from @port and puts the result in @val.
- *
- * Again, this (and the write routine) are generic versions that can be
- * overridden by the platform. This is necessary on platforms that don't
- * support legacy I/O routing or that hard fail on legacy I/O timeouts.
- */
-int pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
-{
- int ret = size;
-
- switch (size) {
- case 1:
- *val = inb(port);
- break;
- case 2:
- *val = inw(port);
- break;
- case 4:
- *val = inl(port);
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-/**
- * pci_legacy_write - perform a legacy I/O write
- * @bus: bus pointer
- * @port: port to write
- * @val: value to write
- * @size: number of bytes to write from @val
- *
- * Simply writes @size bytes of @val to @port.
- */
-int pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
-{
- int ret = size;
-
- switch (size) {
- case 1:
- outb(val, port);
- break;
- case 2:
- outw(val, port);
- break;
- case 4:
- outl(val, port);
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-/**
- * set_pci_cacheline_size - determine cacheline size for PCI devices
- *
- * We want to use the line-size of the outer-most cache. We assume
- * that this line-size is the same for all CPUs.
- *
- * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info().
- */
-static void __init set_pci_dfl_cacheline_size(void)
-{
- unsigned long levels, unique_caches;
- long status;
- pal_cache_config_info_t cci;
-
- status = ia64_pal_cache_summary(&levels, &unique_caches);
- if (status != 0) {
- pr_err("%s: ia64_pal_cache_summary() failed "
- "(status=%ld)\n", __func__, status);
- return;
- }
-
- status = ia64_pal_cache_config_info(levels - 1,
- /* cache_type (data_or_unified)= */ 2, &cci);
- if (status != 0) {
- pr_err("%s: ia64_pal_cache_config_info() failed "
- "(status=%ld)\n", __func__, status);
- return;
- }
- pci_dfl_cache_line_size = (1 << cci.pcci_line_size) / 4;
-}
-
-static int __init pcibios_init(void)
-{
- set_pci_dfl_cacheline_size();
- return 0;
-}
-
-subsys_initcall(pcibios_init);
diff --git a/arch/ia64/scripts/check-gas b/arch/ia64/scripts/check-gas
deleted file mode 100755
index 787cf9b6b04a..000000000000
--- a/arch/ia64/scripts/check-gas
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-dir=$(dirname $0)
-CC=$1
-OBJDUMP=$2
-tmp=${TMPDIR:-/tmp}
-out=$tmp/out$$.o
-$CC -c $dir/check-gas-asm.S -o $out
-res=$($OBJDUMP -r --section .data $out | fgrep 00004 | tr -s ' ' |cut -f3 -d' ')
-rm -f $out
-if [ $res != ".text" ]; then
- echo buggy
-else
- echo good
-fi
-exit 0
diff --git a/arch/ia64/scripts/check-gas-asm.S b/arch/ia64/scripts/check-gas-asm.S
deleted file mode 100644
index 010e1d227e5d..000000000000
--- a/arch/ia64/scripts/check-gas-asm.S
+++ /dev/null
@@ -1,2 +0,0 @@
-[1:] nop 0
- .xdata4 ".data", 0, 1b-.
diff --git a/arch/ia64/scripts/check-model.c b/arch/ia64/scripts/check-model.c
deleted file mode 100644
index e1d4e86e3d63..000000000000
--- a/arch/ia64/scripts/check-model.c
+++ /dev/null
@@ -1 +0,0 @@
-int __attribute__ ((__model__ (__small__))) x;
diff --git a/arch/ia64/scripts/check-segrel.S b/arch/ia64/scripts/check-segrel.S
deleted file mode 100644
index 65d6378adaaa..000000000000
--- a/arch/ia64/scripts/check-segrel.S
+++ /dev/null
@@ -1,5 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
- .rodata
- data4 @segrel(start)
- .data
-start:
diff --git a/arch/ia64/scripts/check-segrel.lds b/arch/ia64/scripts/check-segrel.lds
deleted file mode 100644
index c385d246e458..000000000000
--- a/arch/ia64/scripts/check-segrel.lds
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-SECTIONS {
- . = SIZEOF_HEADERS;
- .rodata : { *(.rodata) } :ro
- .note : { *(.note*) }
- . = 0xa0000;
- .data : { *(.data) } :dat
- /DISCARD/ : { *(*) }
-}
-PHDRS {
- ro PT_LOAD FILEHDR PHDRS;
- dat PT_LOAD;
-}
diff --git a/arch/ia64/scripts/check-serialize.S b/arch/ia64/scripts/check-serialize.S
deleted file mode 100644
index 0400c106806c..000000000000
--- a/arch/ia64/scripts/check-serialize.S
+++ /dev/null
@@ -1,2 +0,0 @@
- .serialize.data
- .serialize.instruction
diff --git a/arch/ia64/scripts/check-text-align.S b/arch/ia64/scripts/check-text-align.S
deleted file mode 100644
index 107fa1c88c2e..000000000000
--- a/arch/ia64/scripts/check-text-align.S
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
- .proc foo
- .prologue
-foo: .save rp, r2
- nop 0
- .align 64
- .endp foo
diff --git a/arch/ia64/scripts/toolchain-flags b/arch/ia64/scripts/toolchain-flags
deleted file mode 100755
index 12dff5c981cf..000000000000
--- a/arch/ia64/scripts/toolchain-flags
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-#
-# Check whether linker can handle cross-segment @segrel():
-#
-CPPFLAGS=""
-CC=$1
-OBJDUMP=$2
-READELF=$3
-dir=$(dirname $0)
-tmp=${TMPDIR:-/tmp}
-out=$tmp/out$$
-
-# Check whether cross-segment segment-relative relocs work fine. We need
-# that for building the gate DSO:
-
-$CC -nostdlib -static -Wl,-T$dir/check-segrel.lds $dir/check-segrel.S -o $out
-res=$($OBJDUMP --full --section .rodata $out | fgrep 000 | cut -f3 -d' ')
-rm -f $out
-if [ $res != 00000a00 ]; then
- CPPFLAGS="$CPPFLAGS -DHAVE_BUGGY_SEGREL"
- cat >&2 <<EOF
-warning: your linker cannot handle cross-segment segment-relative relocations.
- please upgrade to a newer version (it is safe to use this linker, but
- the kernel will be bigger than strictly necessary).
-EOF
-fi
-
-# Check whether .align inside a function works as expected.
-
-$CC -c $dir/check-text-align.S -o $out
-$READELF -u $out | fgrep -q 'prologue(rlen=12)'
-res=$?
-rm -f $out
-if [ $res -eq 0 ]; then
- CPPFLAGS="$CPPFLAGS -DHAVE_WORKING_TEXT_ALIGN"
-fi
-
-if ! $CC -c $dir/check-model.c -o $out 2>&1 | grep __model__ | grep -q attrib
-then
- CPPFLAGS="$CPPFLAGS -DHAVE_MODEL_SMALL_ATTRIBUTE"
-fi
-rm -f $out
-
-# Check whether assembler supports .serialize.{data,instruction} directive.
-
-$CC -c $dir/check-serialize.S -o $out 2>/dev/null
-res=$?
-rm -f $out
-if [ $res -eq 0 ]; then
- CPPFLAGS="$CPPFLAGS -DHAVE_SERIALIZE_DIRECTIVE"
-fi
-
-echo $CPPFLAGS
diff --git a/arch/ia64/scripts/unwcheck.py b/arch/ia64/scripts/unwcheck.py
deleted file mode 100644
index 9581742f0db2..000000000000
--- a/arch/ia64/scripts/unwcheck.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0
-#
-# Usage: unwcheck.py FILE
-#
-# This script checks the unwind info of each function in file FILE
-# and verifies that the sum of the region-lengths matches the total
-# length of the function.
-#
-# Based on a shell/awk script originally written by Harish Patil,
-# which was converted to Perl by Matthew Chapman, which was converted
-# to Python by David Mosberger.
-#
-import os
-import re
-import sys
-
-if len(sys.argv) != 2:
- print("Usage: %s FILE" % sys.argv[0])
- sys.exit(2)
-
-readelf = os.getenv("READELF", "readelf")
-
-start_pattern = re.compile("<([^>]*)>: \[0x([0-9a-f]+)-0x([0-9a-f]+)\]")
-rlen_pattern = re.compile(".*rlen=([0-9]+)")
-
-def check_func (func, slots, rlen_sum):
- if slots != rlen_sum:
- global num_errors
- num_errors += 1
- if not func: func = "[%#x-%#x]" % (start, end)
- print("ERROR: %s: %lu slots, total region length = %lu" % (func, slots, rlen_sum))
- return
-
-num_funcs = 0
-num_errors = 0
-func = False
-slots = 0
-rlen_sum = 0
-for line in os.popen("%s -u %s" % (readelf, sys.argv[1])):
- m = start_pattern.match(line)
- if m:
- check_func(func, slots, rlen_sum)
-
- func = m.group(1)
- start = int(m.group(2), 16)
- end = int(m.group(3), 16)
- slots = 3 * (end - start) / 16
- rlen_sum = 0
- num_funcs += 1
- else:
- m = rlen_pattern.match(line)
- if m:
- rlen_sum += int(m.group(1))
-check_func(func, slots, rlen_sum)
-
-if num_errors == 0:
- print("No errors detected in %u functions." % num_funcs)
-else:
- if num_errors > 1:
- err="errors"
- else:
- err="error"
- print("%u %s detected in %u functions." % (num_errors, err, num_funcs))
- sys.exit(1)
diff --git a/arch/ia64/uv/Makefile b/arch/ia64/uv/Makefile
deleted file mode 100644
index aa9f91947c49..000000000000
--- a/arch/ia64/uv/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# arch/ia64/uv/Makefile
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License. See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 2008 Silicon Graphics, Inc. All Rights Reserved.
-#
-# Makefile for the sn uv subplatform
-#
-
-obj-y += kernel/
diff --git a/arch/ia64/uv/kernel/Makefile b/arch/ia64/uv/kernel/Makefile
deleted file mode 100644
index 297196578d19..000000000000
--- a/arch/ia64/uv/kernel/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# arch/ia64/uv/kernel/Makefile
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License. See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 2008 Silicon Graphics, Inc. All Rights Reserved.
-#
-
-ccflags-y := -Iarch/ia64/sn/include
-
-obj-y += setup.o
diff --git a/arch/ia64/uv/kernel/setup.c b/arch/ia64/uv/kernel/setup.c
deleted file mode 100644
index bb025486d791..000000000000
--- a/arch/ia64/uv/kernel/setup.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * SGI UV Core Functions
- *
- * Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved.
- */
-
-#include <linux/acpi.h>
-#include <linux/efi.h>
-#include <linux/module.h>
-#include <linux/percpu.h>
-#include <asm/uv/uv.h>
-#include <asm/uv/uv_mmrs.h>
-#include <asm/uv/uv_hub.h>
-
-bool ia64_is_uv;
-EXPORT_SYMBOL_GPL(ia64_is_uv);
-
-DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
-EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info);
-
-struct redir_addr {
- unsigned long redirect;
- unsigned long alias;
-};
-
-#define DEST_SHIFT UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT
-
-static __initdata struct redir_addr redir_addrs[] = {
- {UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR, UVH_SI_ALIAS0_OVERLAY_CONFIG},
- {UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR, UVH_SI_ALIAS1_OVERLAY_CONFIG},
- {UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR, UVH_SI_ALIAS2_OVERLAY_CONFIG},
-};
-
-static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size)
-{
- union uvh_si_alias0_overlay_config_u alias;
- union uvh_rh_gam_alias210_redirect_config_2_mmr_u redirect;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(redir_addrs); i++) {
- alias.v = uv_read_local_mmr(redir_addrs[i].alias);
- if (alias.s.base == 0) {
- *size = (1UL << alias.s.m_alias);
- redirect.v = uv_read_local_mmr(redir_addrs[i].redirect);
- *base = (unsigned long)redirect.s.dest_base << DEST_SHIFT;
- return;
- }
- }
- BUG();
-}
-
-void __init uv_probe_system_type(void)
-{
- struct acpi_table_rsdp *rsdp;
- struct acpi_table_xsdt *xsdt;
-
- if (efi.acpi20 == EFI_INVALID_TABLE_ADDR) {
- pr_err("ACPI 2.0 RSDP not found.\n");
- return;
- }
-
- rsdp = (struct acpi_table_rsdp *)__va(efi.acpi20);
- if (strncmp(rsdp->signature, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1)) {
- pr_err("ACPI 2.0 RSDP signature incorrect.\n");
- return;
- }
-
- xsdt = (struct acpi_table_xsdt *)__va(rsdp->xsdt_physical_address);
- if (strncmp(xsdt->header.signature, ACPI_SIG_XSDT,
- sizeof(ACPI_SIG_XSDT) - 1)) {
- pr_err("ACPI 2.0 XSDT signature incorrect.\n");
- return;
- }
-
- if (!strcmp(xsdt->header.oem_id, "SGI") &&
- !strcmp(xsdt->header.oem_table_id + 4, "UV"))
- ia64_is_uv = true;
-}
-
-void __init uv_setup(char **cmdline_p)
-{
- union uvh_si_addr_map_config_u m_n_config;
- union uvh_node_id_u node_id;
- unsigned long gnode_upper;
- int nid, cpu, m_val, n_val;
- unsigned long mmr_base, lowmem_redir_base, lowmem_redir_size;
-
- get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size);
- node_id.v = uv_read_local_mmr(UVH_NODE_ID);
- m_n_config.v = uv_read_local_mmr(UVH_SI_ADDR_MAP_CONFIG);
- mmr_base = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) &
- ~UV_MMR_ENABLE;
-
- m_val = m_n_config.s.m_skt;
- n_val = m_n_config.s.n_skt;
- printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base);
-
- gnode_upper = (((unsigned long)node_id.s.node_id) &
- ~((1 << n_val) - 1)) << m_val;
-
- for_each_present_cpu(cpu) {
- nid = cpu_to_node(cpu);
- uv_cpu_hub_info(cpu)->lowmem_remap_base = lowmem_redir_base;
- uv_cpu_hub_info(cpu)->lowmem_remap_top =
- lowmem_redir_base + lowmem_redir_size;
- uv_cpu_hub_info(cpu)->m_val = m_val;
- uv_cpu_hub_info(cpu)->n_val = n_val;
- uv_cpu_hub_info(cpu)->pnode_mask = (1 << n_val) -1;
- uv_cpu_hub_info(cpu)->gpa_mask = (1 << (m_val + n_val)) - 1;
- uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;
- uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
- uv_cpu_hub_info(cpu)->coherency_domain_number = 0;/* ZZZ */
- printk(KERN_DEBUG "UV cpu %d, nid %d\n", cpu, nid);
- }
-}
-
diff --git a/arch/loongarch/Kbuild b/arch/loongarch/Kbuild
index b01f5cdb27e0..beb8499dd8ed 100644
--- a/arch/loongarch/Kbuild
+++ b/arch/loongarch/Kbuild
@@ -3,5 +3,7 @@ obj-y += mm/
obj-y += net/
obj-y += vdso/
+obj-$(CONFIG_KVM) += kvm/
+
# for cleaning
subdir- += boot
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index e14396a2ddcb..ee123820a476 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -129,12 +129,14 @@ config LOONGARCH
select HAVE_KPROBES
select HAVE_KPROBES_ON_FTRACE
select HAVE_KRETPROBES
+ select HAVE_KVM
select HAVE_MOD_ARCH_SPECIFIC
select HAVE_NMI
select HAVE_PCI
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_PREEMPT_DYNAMIC_KEY
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RETHOOK
select HAVE_RSEQ
@@ -263,6 +265,9 @@ config AS_HAS_LASX_EXTENSION
config AS_HAS_LBT_EXTENSION
def_bool $(as-instr,movscr2gr \$a0$(comma)\$scr0)
+config AS_HAS_LVZ_EXTENSION
+ def_bool $(as-instr,hvcl 0)
+
menu "Kernel type and options"
source "kernel/Kconfig.hz"
@@ -676,3 +681,5 @@ source "kernel/power/Kconfig"
source "drivers/acpi/Kconfig"
endmenu
+
+source "arch/loongarch/kvm/Kconfig"
diff --git a/arch/loongarch/Makefile b/arch/loongarch/Makefile
index fb0fada43197..4ba8d67ddb09 100644
--- a/arch/loongarch/Makefile
+++ b/arch/loongarch/Makefile
@@ -68,6 +68,9 @@ LDFLAGS_vmlinux += -static -n -nostdlib
ifdef CONFIG_AS_HAS_EXPLICIT_RELOCS
cflags-y += $(call cc-option,-mexplicit-relocs)
KBUILD_CFLAGS_KERNEL += $(call cc-option,-mdirect-extern-access)
+KBUILD_CFLAGS_KERNEL += $(call cc-option,-fdirect-access-external-data)
+KBUILD_AFLAGS_MODULE += $(call cc-option,-fno-direct-access-external-data)
+KBUILD_CFLAGS_MODULE += $(call cc-option,-fno-direct-access-external-data)
KBUILD_AFLAGS_MODULE += $(call cc-option,-mno-relax) $(call cc-option,-Wa$(comma)-mno-relax)
KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax) $(call cc-option,-Wa$(comma)-mno-relax)
else
@@ -80,7 +83,7 @@ endif
ifeq ($(CONFIG_RELOCATABLE),y)
KBUILD_CFLAGS_KERNEL += -fPIE
-LDFLAGS_vmlinux += -static -pie --no-dynamic-linker -z notext
+LDFLAGS_vmlinux += -static -pie --no-dynamic-linker -z notext $(call ld-option, --apply-dynamic-relocs)
endif
cflags-y += $(call cc-option, -mno-check-zero-division)
@@ -136,12 +139,12 @@ vdso_prepare: prepare0
$(Q)$(MAKE) $(build)=arch/loongarch/vdso include/generated/vdso-offsets.h
endif
-PHONY += vdso_install
-vdso_install:
- $(Q)$(MAKE) $(build)=arch/loongarch/vdso $@
+vdso-install-y += arch/loongarch/vdso/vdso.so.dbg
all: $(notdir $(KBUILD_IMAGE))
+vmlinuz.efi: vmlinux.efi
+
vmlinux.elf vmlinux.efi vmlinuz.efi: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(bootvars-y) $(boot)/$@
diff --git a/arch/loongarch/configs/loongson3_defconfig b/arch/loongarch/configs/loongson3_defconfig
index a3b52aaa83b3..33795e4a5bd6 100644
--- a/arch/loongarch/configs/loongson3_defconfig
+++ b/arch/loongarch/configs/loongson3_defconfig
@@ -66,6 +66,8 @@ CONFIG_EFI_ZBOOT=y
CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
CONFIG_EFI_CAPSULE_LOADER=m
CONFIG_EFI_TEST=m
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_FORCE_LOAD=y
diff --git a/arch/loongarch/crypto/crc32-loongarch.c b/arch/loongarch/crypto/crc32-loongarch.c
index 1f2a2c3839bc..a49e507af38c 100644
--- a/arch/loongarch/crypto/crc32-loongarch.c
+++ b/arch/loongarch/crypto/crc32-loongarch.c
@@ -239,7 +239,6 @@ static struct shash_alg crc32_alg = {
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
.cra_blocksize = CHKSUM_BLOCK_SIZE,
- .cra_alignmask = 0,
.cra_ctxsize = sizeof(struct chksum_ctx),
.cra_module = THIS_MODULE,
.cra_init = chksum_cra_init,
@@ -261,7 +260,6 @@ static struct shash_alg crc32c_alg = {
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
.cra_blocksize = CHKSUM_BLOCK_SIZE,
- .cra_alignmask = 0,
.cra_ctxsize = sizeof(struct chksum_ctx),
.cra_module = THIS_MODULE,
.cra_init = chksumc_cra_init,
diff --git a/arch/loongarch/include/asm/asmmacro.h b/arch/loongarch/include/asm/asmmacro.h
index c9544f358c33..655db7d7a427 100644
--- a/arch/loongarch/include/asm/asmmacro.h
+++ b/arch/loongarch/include/asm/asmmacro.h
@@ -609,8 +609,7 @@
lu32i.d \reg, 0
lu52i.d \reg, \reg, 0
.pushsection ".la_abs", "aw", %progbits
- 768:
- .dword 768b-766b
+ .dword 766b
.dword \sym
.popsection
#endif
diff --git a/arch/loongarch/include/asm/atomic.h b/arch/loongarch/include/asm/atomic.h
index e27f0c72d324..99af8b3160a8 100644
--- a/arch/loongarch/include/asm/atomic.h
+++ b/arch/loongarch/include/asm/atomic.h
@@ -36,19 +36,19 @@
static inline void arch_atomic_##op(int i, atomic_t *v) \
{ \
__asm__ __volatile__( \
- "am"#asm_op"_db.w" " $zero, %1, %0 \n" \
+ "am"#asm_op".w" " $zero, %1, %0 \n" \
: "+ZB" (v->counter) \
: "r" (I) \
: "memory"); \
}
-#define ATOMIC_OP_RETURN(op, I, asm_op, c_op) \
-static inline int arch_atomic_##op##_return_relaxed(int i, atomic_t *v) \
+#define ATOMIC_OP_RETURN(op, I, asm_op, c_op, mb, suffix) \
+static inline int arch_atomic_##op##_return##suffix(int i, atomic_t *v) \
{ \
int result; \
\
__asm__ __volatile__( \
- "am"#asm_op"_db.w" " %1, %2, %0 \n" \
+ "am"#asm_op#mb".w" " %1, %2, %0 \n" \
: "+ZB" (v->counter), "=&r" (result) \
: "r" (I) \
: "memory"); \
@@ -56,13 +56,13 @@ static inline int arch_atomic_##op##_return_relaxed(int i, atomic_t *v) \
return result c_op I; \
}
-#define ATOMIC_FETCH_OP(op, I, asm_op) \
-static inline int arch_atomic_fetch_##op##_relaxed(int i, atomic_t *v) \
+#define ATOMIC_FETCH_OP(op, I, asm_op, mb, suffix) \
+static inline int arch_atomic_fetch_##op##suffix(int i, atomic_t *v) \
{ \
int result; \
\
__asm__ __volatile__( \
- "am"#asm_op"_db.w" " %1, %2, %0 \n" \
+ "am"#asm_op#mb".w" " %1, %2, %0 \n" \
: "+ZB" (v->counter), "=&r" (result) \
: "r" (I) \
: "memory"); \
@@ -72,29 +72,53 @@ static inline int arch_atomic_fetch_##op##_relaxed(int i, atomic_t *v) \
#define ATOMIC_OPS(op, I, asm_op, c_op) \
ATOMIC_OP(op, I, asm_op) \
- ATOMIC_OP_RETURN(op, I, asm_op, c_op) \
- ATOMIC_FETCH_OP(op, I, asm_op)
+ ATOMIC_OP_RETURN(op, I, asm_op, c_op, _db, ) \
+ ATOMIC_OP_RETURN(op, I, asm_op, c_op, , _relaxed) \
+ ATOMIC_FETCH_OP(op, I, asm_op, _db, ) \
+ ATOMIC_FETCH_OP(op, I, asm_op, , _relaxed)
ATOMIC_OPS(add, i, add, +)
ATOMIC_OPS(sub, -i, add, +)
+#define arch_atomic_add_return arch_atomic_add_return
+#define arch_atomic_add_return_acquire arch_atomic_add_return
+#define arch_atomic_add_return_release arch_atomic_add_return
#define arch_atomic_add_return_relaxed arch_atomic_add_return_relaxed
+#define arch_atomic_sub_return arch_atomic_sub_return
+#define arch_atomic_sub_return_acquire arch_atomic_sub_return
+#define arch_atomic_sub_return_release arch_atomic_sub_return
#define arch_atomic_sub_return_relaxed arch_atomic_sub_return_relaxed
+#define arch_atomic_fetch_add arch_atomic_fetch_add
+#define arch_atomic_fetch_add_acquire arch_atomic_fetch_add
+#define arch_atomic_fetch_add_release arch_atomic_fetch_add
#define arch_atomic_fetch_add_relaxed arch_atomic_fetch_add_relaxed
+#define arch_atomic_fetch_sub arch_atomic_fetch_sub
+#define arch_atomic_fetch_sub_acquire arch_atomic_fetch_sub
+#define arch_atomic_fetch_sub_release arch_atomic_fetch_sub
#define arch_atomic_fetch_sub_relaxed arch_atomic_fetch_sub_relaxed
#undef ATOMIC_OPS
#define ATOMIC_OPS(op, I, asm_op) \
ATOMIC_OP(op, I, asm_op) \
- ATOMIC_FETCH_OP(op, I, asm_op)
+ ATOMIC_FETCH_OP(op, I, asm_op, _db, ) \
+ ATOMIC_FETCH_OP(op, I, asm_op, , _relaxed)
ATOMIC_OPS(and, i, and)
ATOMIC_OPS(or, i, or)
ATOMIC_OPS(xor, i, xor)
+#define arch_atomic_fetch_and arch_atomic_fetch_and
+#define arch_atomic_fetch_and_acquire arch_atomic_fetch_and
+#define arch_atomic_fetch_and_release arch_atomic_fetch_and
#define arch_atomic_fetch_and_relaxed arch_atomic_fetch_and_relaxed
+#define arch_atomic_fetch_or arch_atomic_fetch_or
+#define arch_atomic_fetch_or_acquire arch_atomic_fetch_or
+#define arch_atomic_fetch_or_release arch_atomic_fetch_or
#define arch_atomic_fetch_or_relaxed arch_atomic_fetch_or_relaxed
+#define arch_atomic_fetch_xor arch_atomic_fetch_xor
+#define arch_atomic_fetch_xor_acquire arch_atomic_fetch_xor
+#define arch_atomic_fetch_xor_release arch_atomic_fetch_xor
#define arch_atomic_fetch_xor_relaxed arch_atomic_fetch_xor_relaxed
#undef ATOMIC_OPS
@@ -172,18 +196,18 @@ static inline int arch_atomic_sub_if_positive(int i, atomic_t *v)
static inline void arch_atomic64_##op(long i, atomic64_t *v) \
{ \
__asm__ __volatile__( \
- "am"#asm_op"_db.d " " $zero, %1, %0 \n" \
+ "am"#asm_op".d " " $zero, %1, %0 \n" \
: "+ZB" (v->counter) \
: "r" (I) \
: "memory"); \
}
-#define ATOMIC64_OP_RETURN(op, I, asm_op, c_op) \
-static inline long arch_atomic64_##op##_return_relaxed(long i, atomic64_t *v) \
+#define ATOMIC64_OP_RETURN(op, I, asm_op, c_op, mb, suffix) \
+static inline long arch_atomic64_##op##_return##suffix(long i, atomic64_t *v) \
{ \
long result; \
__asm__ __volatile__( \
- "am"#asm_op"_db.d " " %1, %2, %0 \n" \
+ "am"#asm_op#mb".d " " %1, %2, %0 \n" \
: "+ZB" (v->counter), "=&r" (result) \
: "r" (I) \
: "memory"); \
@@ -191,13 +215,13 @@ static inline long arch_atomic64_##op##_return_relaxed(long i, atomic64_t *v) \
return result c_op I; \
}
-#define ATOMIC64_FETCH_OP(op, I, asm_op) \
-static inline long arch_atomic64_fetch_##op##_relaxed(long i, atomic64_t *v) \
+#define ATOMIC64_FETCH_OP(op, I, asm_op, mb, suffix) \
+static inline long arch_atomic64_fetch_##op##suffix(long i, atomic64_t *v) \
{ \
long result; \
\
__asm__ __volatile__( \
- "am"#asm_op"_db.d " " %1, %2, %0 \n" \
+ "am"#asm_op#mb".d " " %1, %2, %0 \n" \
: "+ZB" (v->counter), "=&r" (result) \
: "r" (I) \
: "memory"); \
@@ -207,29 +231,53 @@ static inline long arch_atomic64_fetch_##op##_relaxed(long i, atomic64_t *v) \
#define ATOMIC64_OPS(op, I, asm_op, c_op) \
ATOMIC64_OP(op, I, asm_op) \
- ATOMIC64_OP_RETURN(op, I, asm_op, c_op) \
- ATOMIC64_FETCH_OP(op, I, asm_op)
+ ATOMIC64_OP_RETURN(op, I, asm_op, c_op, _db, ) \
+ ATOMIC64_OP_RETURN(op, I, asm_op, c_op, , _relaxed) \
+ ATOMIC64_FETCH_OP(op, I, asm_op, _db, ) \
+ ATOMIC64_FETCH_OP(op, I, asm_op, , _relaxed)
ATOMIC64_OPS(add, i, add, +)
ATOMIC64_OPS(sub, -i, add, +)
+#define arch_atomic64_add_return arch_atomic64_add_return
+#define arch_atomic64_add_return_acquire arch_atomic64_add_return
+#define arch_atomic64_add_return_release arch_atomic64_add_return
#define arch_atomic64_add_return_relaxed arch_atomic64_add_return_relaxed
+#define arch_atomic64_sub_return arch_atomic64_sub_return
+#define arch_atomic64_sub_return_acquire arch_atomic64_sub_return
+#define arch_atomic64_sub_return_release arch_atomic64_sub_return
#define arch_atomic64_sub_return_relaxed arch_atomic64_sub_return_relaxed
+#define arch_atomic64_fetch_add arch_atomic64_fetch_add
+#define arch_atomic64_fetch_add_acquire arch_atomic64_fetch_add
+#define arch_atomic64_fetch_add_release arch_atomic64_fetch_add
#define arch_atomic64_fetch_add_relaxed arch_atomic64_fetch_add_relaxed
+#define arch_atomic64_fetch_sub arch_atomic64_fetch_sub
+#define arch_atomic64_fetch_sub_acquire arch_atomic64_fetch_sub
+#define arch_atomic64_fetch_sub_release arch_atomic64_fetch_sub
#define arch_atomic64_fetch_sub_relaxed arch_atomic64_fetch_sub_relaxed
#undef ATOMIC64_OPS
#define ATOMIC64_OPS(op, I, asm_op) \
ATOMIC64_OP(op, I, asm_op) \
- ATOMIC64_FETCH_OP(op, I, asm_op)
+ ATOMIC64_FETCH_OP(op, I, asm_op, _db, ) \
+ ATOMIC64_FETCH_OP(op, I, asm_op, , _relaxed)
ATOMIC64_OPS(and, i, and)
ATOMIC64_OPS(or, i, or)
ATOMIC64_OPS(xor, i, xor)
+#define arch_atomic64_fetch_and arch_atomic64_fetch_and
+#define arch_atomic64_fetch_and_acquire arch_atomic64_fetch_and
+#define arch_atomic64_fetch_and_release arch_atomic64_fetch_and
#define arch_atomic64_fetch_and_relaxed arch_atomic64_fetch_and_relaxed
+#define arch_atomic64_fetch_or arch_atomic64_fetch_or
+#define arch_atomic64_fetch_or_acquire arch_atomic64_fetch_or
+#define arch_atomic64_fetch_or_release arch_atomic64_fetch_or
#define arch_atomic64_fetch_or_relaxed arch_atomic64_fetch_or_relaxed
+#define arch_atomic64_fetch_xor arch_atomic64_fetch_xor
+#define arch_atomic64_fetch_xor_acquire arch_atomic64_fetch_xor
+#define arch_atomic64_fetch_xor_release arch_atomic64_fetch_xor
#define arch_atomic64_fetch_xor_relaxed arch_atomic64_fetch_xor_relaxed
#undef ATOMIC64_OPS
diff --git a/arch/loongarch/include/asm/efi.h b/arch/loongarch/include/asm/efi.h
index 091897d40b03..91d81f9730ab 100644
--- a/arch/loongarch/include/asm/efi.h
+++ b/arch/loongarch/include/asm/efi.h
@@ -32,6 +32,6 @@ static inline unsigned long efi_get_kimg_min_align(void)
#define EFI_KIMG_PREFERRED_ADDRESS PHYSADDR(VMLINUX_LOAD_ADDRESS)
-unsigned long kernel_entry_address(void);
+unsigned long kernel_entry_address(unsigned long kernel_addr);
#endif /* _ASM_LOONGARCH_EFI_H */
diff --git a/arch/loongarch/include/asm/elf.h b/arch/loongarch/include/asm/elf.h
index b9a4ab54285c..9b16a3b8e706 100644
--- a/arch/loongarch/include/asm/elf.h
+++ b/arch/loongarch/include/asm/elf.h
@@ -293,7 +293,7 @@ extern const char *__elf_platform;
#define ELF_PLAT_INIT(_r, load_addr) do { \
_r->regs[1] = _r->regs[2] = _r->regs[3] = _r->regs[4] = 0; \
_r->regs[5] = _r->regs[6] = _r->regs[7] = _r->regs[8] = 0; \
- _r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0; \
+ _r->regs[9] = _r->regs[10] /* syscall n */ = _r->regs[12] = 0; \
_r->regs[13] = _r->regs[14] = _r->regs[15] = _r->regs[16] = 0; \
_r->regs[17] = _r->regs[18] = _r->regs[19] = _r->regs[20] = 0; \
_r->regs[21] = _r->regs[22] = _r->regs[23] = _r->regs[24] = 0; \
diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h
index 71e1ed4165c8..d8f637f9e400 100644
--- a/arch/loongarch/include/asm/inst.h
+++ b/arch/loongarch/include/asm/inst.h
@@ -65,6 +65,16 @@ enum reg2_op {
revbd_op = 0x0f,
revh2w_op = 0x10,
revhd_op = 0x11,
+ extwh_op = 0x16,
+ extwb_op = 0x17,
+ iocsrrdb_op = 0x19200,
+ iocsrrdh_op = 0x19201,
+ iocsrrdw_op = 0x19202,
+ iocsrrdd_op = 0x19203,
+ iocsrwrb_op = 0x19204,
+ iocsrwrh_op = 0x19205,
+ iocsrwrw_op = 0x19206,
+ iocsrwrd_op = 0x19207,
};
enum reg2i5_op {
@@ -318,6 +328,13 @@ struct reg2bstrd_format {
unsigned int opcode : 10;
};
+struct reg2csr_format {
+ unsigned int rd : 5;
+ unsigned int rj : 5;
+ unsigned int csr : 14;
+ unsigned int opcode : 8;
+};
+
struct reg3_format {
unsigned int rd : 5;
unsigned int rj : 5;
@@ -346,6 +363,7 @@ union loongarch_instruction {
struct reg2i14_format reg2i14_format;
struct reg2i16_format reg2i16_format;
struct reg2bstrd_format reg2bstrd_format;
+ struct reg2csr_format reg2csr_format;
struct reg3_format reg3_format;
struct reg3sa2_format reg3sa2_format;
};
@@ -556,6 +574,8 @@ static inline void emit_##NAME(union loongarch_instruction *insn, \
DEF_EMIT_REG2_FORMAT(revb2h, revb2h_op)
DEF_EMIT_REG2_FORMAT(revb2w, revb2w_op)
DEF_EMIT_REG2_FORMAT(revbd, revbd_op)
+DEF_EMIT_REG2_FORMAT(extwh, extwh_op)
+DEF_EMIT_REG2_FORMAT(extwb, extwb_op)
#define DEF_EMIT_REG2I5_FORMAT(NAME, OP) \
static inline void emit_##NAME(union loongarch_instruction *insn, \
@@ -607,6 +627,9 @@ DEF_EMIT_REG2I12_FORMAT(lu52id, lu52id_op)
DEF_EMIT_REG2I12_FORMAT(andi, andi_op)
DEF_EMIT_REG2I12_FORMAT(ori, ori_op)
DEF_EMIT_REG2I12_FORMAT(xori, xori_op)
+DEF_EMIT_REG2I12_FORMAT(ldb, ldb_op)
+DEF_EMIT_REG2I12_FORMAT(ldh, ldh_op)
+DEF_EMIT_REG2I12_FORMAT(ldw, ldw_op)
DEF_EMIT_REG2I12_FORMAT(ldbu, ldbu_op)
DEF_EMIT_REG2I12_FORMAT(ldhu, ldhu_op)
DEF_EMIT_REG2I12_FORMAT(ldwu, ldwu_op)
@@ -685,9 +708,12 @@ static inline void emit_##NAME(union loongarch_instruction *insn, \
insn->reg3_format.rk = rk; \
}
+DEF_EMIT_REG3_FORMAT(addw, addw_op)
DEF_EMIT_REG3_FORMAT(addd, addd_op)
DEF_EMIT_REG3_FORMAT(subd, subd_op)
DEF_EMIT_REG3_FORMAT(muld, muld_op)
+DEF_EMIT_REG3_FORMAT(divd, divd_op)
+DEF_EMIT_REG3_FORMAT(modd, modd_op)
DEF_EMIT_REG3_FORMAT(divdu, divdu_op)
DEF_EMIT_REG3_FORMAT(moddu, moddu_op)
DEF_EMIT_REG3_FORMAT(and, and_op)
@@ -699,6 +725,9 @@ DEF_EMIT_REG3_FORMAT(srlw, srlw_op)
DEF_EMIT_REG3_FORMAT(srld, srld_op)
DEF_EMIT_REG3_FORMAT(sraw, sraw_op)
DEF_EMIT_REG3_FORMAT(srad, srad_op)
+DEF_EMIT_REG3_FORMAT(ldxb, ldxb_op)
+DEF_EMIT_REG3_FORMAT(ldxh, ldxh_op)
+DEF_EMIT_REG3_FORMAT(ldxw, ldxw_op)
DEF_EMIT_REG3_FORMAT(ldxbu, ldxbu_op)
DEF_EMIT_REG3_FORMAT(ldxhu, ldxhu_op)
DEF_EMIT_REG3_FORMAT(ldxwu, ldxwu_op)
diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h
index 0dcb36b32cb2..c486c2341b66 100644
--- a/arch/loongarch/include/asm/io.h
+++ b/arch/loongarch/include/asm/io.h
@@ -52,10 +52,9 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
* @offset: bus address of the memory
* @size: size of the resource to map
*/
-extern pgprot_t pgprot_wc;
-
#define ioremap_wc(offset, size) \
- ioremap_prot((offset), (size), pgprot_val(pgprot_wc))
+ ioremap_prot((offset), (size), \
+ pgprot_val(wc_enabled ? PAGE_KERNEL_WUC : PAGE_KERNEL_SUC))
#define ioremap_cache(offset, size) \
ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL))
diff --git a/arch/loongarch/include/asm/kvm_csr.h b/arch/loongarch/include/asm/kvm_csr.h
new file mode 100644
index 000000000000..724ca8b7b401
--- /dev/null
+++ b/arch/loongarch/include/asm/kvm_csr.h
@@ -0,0 +1,211 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef __ASM_LOONGARCH_KVM_CSR_H__
+#define __ASM_LOONGARCH_KVM_CSR_H__
+
+#include <linux/uaccess.h>
+#include <linux/kvm_host.h>
+#include <asm/loongarch.h>
+#include <asm/kvm_vcpu.h>
+
+#define gcsr_read(csr) \
+({ \
+ register unsigned long __v; \
+ __asm__ __volatile__( \
+ " gcsrrd %[val], %[reg]\n\t" \
+ : [val] "=r" (__v) \
+ : [reg] "i" (csr) \
+ : "memory"); \
+ __v; \
+})
+
+#define gcsr_write(v, csr) \
+({ \
+ register unsigned long __v = v; \
+ __asm__ __volatile__ ( \
+ " gcsrwr %[val], %[reg]\n\t" \
+ : [val] "+r" (__v) \
+ : [reg] "i" (csr) \
+ : "memory"); \
+})
+
+#define gcsr_xchg(v, m, csr) \
+({ \
+ register unsigned long __v = v; \
+ __asm__ __volatile__( \
+ " gcsrxchg %[val], %[mask], %[reg]\n\t" \
+ : [val] "+r" (__v) \
+ : [mask] "r" (m), [reg] "i" (csr) \
+ : "memory"); \
+ __v; \
+})
+
+/* Guest CSRS read and write */
+#define read_gcsr_crmd() gcsr_read(LOONGARCH_CSR_CRMD)
+#define write_gcsr_crmd(val) gcsr_write(val, LOONGARCH_CSR_CRMD)
+#define read_gcsr_prmd() gcsr_read(LOONGARCH_CSR_PRMD)
+#define write_gcsr_prmd(val) gcsr_write(val, LOONGARCH_CSR_PRMD)
+#define read_gcsr_euen() gcsr_read(LOONGARCH_CSR_EUEN)
+#define write_gcsr_euen(val) gcsr_write(val, LOONGARCH_CSR_EUEN)
+#define read_gcsr_misc() gcsr_read(LOONGARCH_CSR_MISC)
+#define write_gcsr_misc(val) gcsr_write(val, LOONGARCH_CSR_MISC)
+#define read_gcsr_ecfg() gcsr_read(LOONGARCH_CSR_ECFG)
+#define write_gcsr_ecfg(val) gcsr_write(val, LOONGARCH_CSR_ECFG)
+#define read_gcsr_estat() gcsr_read(LOONGARCH_CSR_ESTAT)
+#define write_gcsr_estat(val) gcsr_write(val, LOONGARCH_CSR_ESTAT)
+#define read_gcsr_era() gcsr_read(LOONGARCH_CSR_ERA)
+#define write_gcsr_era(val) gcsr_write(val, LOONGARCH_CSR_ERA)
+#define read_gcsr_badv() gcsr_read(LOONGARCH_CSR_BADV)
+#define write_gcsr_badv(val) gcsr_write(val, LOONGARCH_CSR_BADV)
+#define read_gcsr_badi() gcsr_read(LOONGARCH_CSR_BADI)
+#define write_gcsr_badi(val) gcsr_write(val, LOONGARCH_CSR_BADI)
+#define read_gcsr_eentry() gcsr_read(LOONGARCH_CSR_EENTRY)
+#define write_gcsr_eentry(val) gcsr_write(val, LOONGARCH_CSR_EENTRY)
+
+#define read_gcsr_asid() gcsr_read(LOONGARCH_CSR_ASID)
+#define write_gcsr_asid(val) gcsr_write(val, LOONGARCH_CSR_ASID)
+#define read_gcsr_pgdl() gcsr_read(LOONGARCH_CSR_PGDL)
+#define write_gcsr_pgdl(val) gcsr_write(val, LOONGARCH_CSR_PGDL)
+#define read_gcsr_pgdh() gcsr_read(LOONGARCH_CSR_PGDH)
+#define write_gcsr_pgdh(val) gcsr_write(val, LOONGARCH_CSR_PGDH)
+#define write_gcsr_pgd(val) gcsr_write(val, LOONGARCH_CSR_PGD)
+#define read_gcsr_pgd() gcsr_read(LOONGARCH_CSR_PGD)
+#define read_gcsr_pwctl0() gcsr_read(LOONGARCH_CSR_PWCTL0)
+#define write_gcsr_pwctl0(val) gcsr_write(val, LOONGARCH_CSR_PWCTL0)
+#define read_gcsr_pwctl1() gcsr_read(LOONGARCH_CSR_PWCTL1)
+#define write_gcsr_pwctl1(val) gcsr_write(val, LOONGARCH_CSR_PWCTL1)
+#define read_gcsr_stlbpgsize() gcsr_read(LOONGARCH_CSR_STLBPGSIZE)
+#define write_gcsr_stlbpgsize(val) gcsr_write(val, LOONGARCH_CSR_STLBPGSIZE)
+#define read_gcsr_rvacfg() gcsr_read(LOONGARCH_CSR_RVACFG)
+#define write_gcsr_rvacfg(val) gcsr_write(val, LOONGARCH_CSR_RVACFG)
+
+#define read_gcsr_cpuid() gcsr_read(LOONGARCH_CSR_CPUID)
+#define write_gcsr_cpuid(val) gcsr_write(val, LOONGARCH_CSR_CPUID)
+#define read_gcsr_prcfg1() gcsr_read(LOONGARCH_CSR_PRCFG1)
+#define write_gcsr_prcfg1(val) gcsr_write(val, LOONGARCH_CSR_PRCFG1)
+#define read_gcsr_prcfg2() gcsr_read(LOONGARCH_CSR_PRCFG2)
+#define write_gcsr_prcfg2(val) gcsr_write(val, LOONGARCH_CSR_PRCFG2)
+#define read_gcsr_prcfg3() gcsr_read(LOONGARCH_CSR_PRCFG3)
+#define write_gcsr_prcfg3(val) gcsr_write(val, LOONGARCH_CSR_PRCFG3)
+
+#define read_gcsr_kscratch0() gcsr_read(LOONGARCH_CSR_KS0)
+#define write_gcsr_kscratch0(val) gcsr_write(val, LOONGARCH_CSR_KS0)
+#define read_gcsr_kscratch1() gcsr_read(LOONGARCH_CSR_KS1)
+#define write_gcsr_kscratch1(val) gcsr_write(val, LOONGARCH_CSR_KS1)
+#define read_gcsr_kscratch2() gcsr_read(LOONGARCH_CSR_KS2)
+#define write_gcsr_kscratch2(val) gcsr_write(val, LOONGARCH_CSR_KS2)
+#define read_gcsr_kscratch3() gcsr_read(LOONGARCH_CSR_KS3)
+#define write_gcsr_kscratch3(val) gcsr_write(val, LOONGARCH_CSR_KS3)
+#define read_gcsr_kscratch4() gcsr_read(LOONGARCH_CSR_KS4)
+#define write_gcsr_kscratch4(val) gcsr_write(val, LOONGARCH_CSR_KS4)
+#define read_gcsr_kscratch5() gcsr_read(LOONGARCH_CSR_KS5)
+#define write_gcsr_kscratch5(val) gcsr_write(val, LOONGARCH_CSR_KS5)
+#define read_gcsr_kscratch6() gcsr_read(LOONGARCH_CSR_KS6)
+#define write_gcsr_kscratch6(val) gcsr_write(val, LOONGARCH_CSR_KS6)
+#define read_gcsr_kscratch7() gcsr_read(LOONGARCH_CSR_KS7)
+#define write_gcsr_kscratch7(val) gcsr_write(val, LOONGARCH_CSR_KS7)
+
+#define read_gcsr_timerid() gcsr_read(LOONGARCH_CSR_TMID)
+#define write_gcsr_timerid(val) gcsr_write(val, LOONGARCH_CSR_TMID)
+#define read_gcsr_timercfg() gcsr_read(LOONGARCH_CSR_TCFG)
+#define write_gcsr_timercfg(val) gcsr_write(val, LOONGARCH_CSR_TCFG)
+#define read_gcsr_timertick() gcsr_read(LOONGARCH_CSR_TVAL)
+#define write_gcsr_timertick(val) gcsr_write(val, LOONGARCH_CSR_TVAL)
+#define read_gcsr_timeroffset() gcsr_read(LOONGARCH_CSR_CNTC)
+#define write_gcsr_timeroffset(val) gcsr_write(val, LOONGARCH_CSR_CNTC)
+
+#define read_gcsr_llbctl() gcsr_read(LOONGARCH_CSR_LLBCTL)
+#define write_gcsr_llbctl(val) gcsr_write(val, LOONGARCH_CSR_LLBCTL)
+
+#define read_gcsr_tlbidx() gcsr_read(LOONGARCH_CSR_TLBIDX)
+#define write_gcsr_tlbidx(val) gcsr_write(val, LOONGARCH_CSR_TLBIDX)
+#define read_gcsr_tlbrentry() gcsr_read(LOONGARCH_CSR_TLBRENTRY)
+#define write_gcsr_tlbrentry(val) gcsr_write(val, LOONGARCH_CSR_TLBRENTRY)
+#define read_gcsr_tlbrbadv() gcsr_read(LOONGARCH_CSR_TLBRBADV)
+#define write_gcsr_tlbrbadv(val) gcsr_write(val, LOONGARCH_CSR_TLBRBADV)
+#define read_gcsr_tlbrera() gcsr_read(LOONGARCH_CSR_TLBRERA)
+#define write_gcsr_tlbrera(val) gcsr_write(val, LOONGARCH_CSR_TLBRERA)
+#define read_gcsr_tlbrsave() gcsr_read(LOONGARCH_CSR_TLBRSAVE)
+#define write_gcsr_tlbrsave(val) gcsr_write(val, LOONGARCH_CSR_TLBRSAVE)
+#define read_gcsr_tlbrelo0() gcsr_read(LOONGARCH_CSR_TLBRELO0)
+#define write_gcsr_tlbrelo0(val) gcsr_write(val, LOONGARCH_CSR_TLBRELO0)
+#define read_gcsr_tlbrelo1() gcsr_read(LOONGARCH_CSR_TLBRELO1)
+#define write_gcsr_tlbrelo1(val) gcsr_write(val, LOONGARCH_CSR_TLBRELO1)
+#define read_gcsr_tlbrehi() gcsr_read(LOONGARCH_CSR_TLBREHI)
+#define write_gcsr_tlbrehi(val) gcsr_write(val, LOONGARCH_CSR_TLBREHI)
+#define read_gcsr_tlbrprmd() gcsr_read(LOONGARCH_CSR_TLBRPRMD)
+#define write_gcsr_tlbrprmd(val) gcsr_write(val, LOONGARCH_CSR_TLBRPRMD)
+
+#define read_gcsr_directwin0() gcsr_read(LOONGARCH_CSR_DMWIN0)
+#define write_gcsr_directwin0(val) gcsr_write(val, LOONGARCH_CSR_DMWIN0)
+#define read_gcsr_directwin1() gcsr_read(LOONGARCH_CSR_DMWIN1)
+#define write_gcsr_directwin1(val) gcsr_write(val, LOONGARCH_CSR_DMWIN1)
+#define read_gcsr_directwin2() gcsr_read(LOONGARCH_CSR_DMWIN2)
+#define write_gcsr_directwin2(val) gcsr_write(val, LOONGARCH_CSR_DMWIN2)
+#define read_gcsr_directwin3() gcsr_read(LOONGARCH_CSR_DMWIN3)
+#define write_gcsr_directwin3(val) gcsr_write(val, LOONGARCH_CSR_DMWIN3)
+
+/* Guest related CSRs */
+#define read_csr_gtlbc() csr_read64(LOONGARCH_CSR_GTLBC)
+#define write_csr_gtlbc(val) csr_write64(val, LOONGARCH_CSR_GTLBC)
+#define read_csr_trgp() csr_read64(LOONGARCH_CSR_TRGP)
+#define read_csr_gcfg() csr_read64(LOONGARCH_CSR_GCFG)
+#define write_csr_gcfg(val) csr_write64(val, LOONGARCH_CSR_GCFG)
+#define read_csr_gstat() csr_read64(LOONGARCH_CSR_GSTAT)
+#define write_csr_gstat(val) csr_write64(val, LOONGARCH_CSR_GSTAT)
+#define read_csr_gintc() csr_read64(LOONGARCH_CSR_GINTC)
+#define write_csr_gintc(val) csr_write64(val, LOONGARCH_CSR_GINTC)
+#define read_csr_gcntc() csr_read64(LOONGARCH_CSR_GCNTC)
+#define write_csr_gcntc(val) csr_write64(val, LOONGARCH_CSR_GCNTC)
+
+#define __BUILD_GCSR_OP(name) __BUILD_CSR_COMMON(gcsr_##name)
+
+__BUILD_CSR_OP(gcfg)
+__BUILD_CSR_OP(gstat)
+__BUILD_CSR_OP(gtlbc)
+__BUILD_CSR_OP(gintc)
+__BUILD_GCSR_OP(llbctl)
+__BUILD_GCSR_OP(tlbidx)
+
+#define set_gcsr_estat(val) \
+ gcsr_xchg(val, val, LOONGARCH_CSR_ESTAT)
+#define clear_gcsr_estat(val) \
+ gcsr_xchg(~(val), val, LOONGARCH_CSR_ESTAT)
+
+#define kvm_read_hw_gcsr(id) gcsr_read(id)
+#define kvm_write_hw_gcsr(id, val) gcsr_write(val, id)
+
+#define kvm_save_hw_gcsr(csr, gid) (csr->csrs[gid] = gcsr_read(gid))
+#define kvm_restore_hw_gcsr(csr, gid) (gcsr_write(csr->csrs[gid], gid))
+
+int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu);
+
+static __always_inline unsigned long kvm_read_sw_gcsr(struct loongarch_csrs *csr, int gid)
+{
+ return csr->csrs[gid];
+}
+
+static __always_inline void kvm_write_sw_gcsr(struct loongarch_csrs *csr, int gid, unsigned long val)
+{
+ csr->csrs[gid] = val;
+}
+
+static __always_inline void kvm_set_sw_gcsr(struct loongarch_csrs *csr,
+ int gid, unsigned long val)
+{
+ csr->csrs[gid] |= val;
+}
+
+static __always_inline void kvm_change_sw_gcsr(struct loongarch_csrs *csr,
+ int gid, unsigned long mask, unsigned long val)
+{
+ unsigned long _mask = mask;
+
+ csr->csrs[gid] &= ~_mask;
+ csr->csrs[gid] |= val & _mask;
+}
+
+#endif /* __ASM_LOONGARCH_KVM_CSR_H__ */
diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
new file mode 100644
index 000000000000..11328700d4fa
--- /dev/null
+++ b/arch/loongarch/include/asm/kvm_host.h
@@ -0,0 +1,237 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef __ASM_LOONGARCH_KVM_HOST_H__
+#define __ASM_LOONGARCH_KVM_HOST_H__
+
+#include <linux/cpumask.h>
+#include <linux/hrtimer.h>
+#include <linux/interrupt.h>
+#include <linux/kvm.h>
+#include <linux/kvm_types.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/threads.h>
+#include <linux/types.h>
+
+#include <asm/inst.h>
+#include <asm/kvm_mmu.h>
+#include <asm/loongarch.h>
+
+/* Loongarch KVM register ids */
+#define KVM_GET_IOC_CSR_IDX(id) ((id & KVM_CSR_IDX_MASK) >> LOONGARCH_REG_SHIFT)
+#define KVM_GET_IOC_CPUCFG_IDX(id) ((id & KVM_CPUCFG_IDX_MASK) >> LOONGARCH_REG_SHIFT)
+
+#define KVM_MAX_VCPUS 256
+#define KVM_MAX_CPUCFG_REGS 21
+/* memory slots that does not exposed to userspace */
+#define KVM_PRIVATE_MEM_SLOTS 0
+
+#define KVM_HALT_POLL_NS_DEFAULT 500000
+
+struct kvm_vm_stat {
+ struct kvm_vm_stat_generic generic;
+ u64 pages;
+ u64 hugepages;
+};
+
+struct kvm_vcpu_stat {
+ struct kvm_vcpu_stat_generic generic;
+ u64 int_exits;
+ u64 idle_exits;
+ u64 cpucfg_exits;
+ u64 signal_exits;
+};
+
+struct kvm_arch_memory_slot {
+};
+
+struct kvm_context {
+ unsigned long vpid_cache;
+ struct kvm_vcpu *last_vcpu;
+};
+
+struct kvm_world_switch {
+ int (*exc_entry)(void);
+ int (*enter_guest)(struct kvm_run *run, struct kvm_vcpu *vcpu);
+ unsigned long page_order;
+};
+
+#define MAX_PGTABLE_LEVELS 4
+
+struct kvm_arch {
+ /* Guest physical mm */
+ kvm_pte_t *pgd;
+ unsigned long gpa_size;
+ unsigned long invalid_ptes[MAX_PGTABLE_LEVELS];
+ unsigned int pte_shifts[MAX_PGTABLE_LEVELS];
+ unsigned int root_level;
+
+ s64 time_offset;
+ struct kvm_context __percpu *vmcs;
+};
+
+#define CSR_MAX_NUMS 0x800
+
+struct loongarch_csrs {
+ unsigned long csrs[CSR_MAX_NUMS];
+};
+
+/* Resume Flags */
+#define RESUME_HOST 0
+#define RESUME_GUEST 1
+
+enum emulation_result {
+ EMULATE_DONE, /* no further processing */
+ EMULATE_DO_MMIO, /* kvm_run filled with MMIO request */
+ EMULATE_DO_IOCSR, /* handle IOCSR request */
+ EMULATE_FAIL, /* can't emulate this instruction */
+ EMULATE_EXCEPT, /* A guest exception has been generated */
+};
+
+#define KVM_LARCH_FPU (0x1 << 0)
+#define KVM_LARCH_SWCSR_LATEST (0x1 << 1)
+#define KVM_LARCH_HWCSR_USABLE (0x1 << 2)
+
+struct kvm_vcpu_arch {
+ /*
+ * Switch pointer-to-function type to unsigned long
+ * for loading the value into register directly.
+ */
+ unsigned long host_eentry;
+ unsigned long guest_eentry;
+
+ /* Pointers stored here for easy accessing from assembly code */
+ int (*handle_exit)(struct kvm_run *run, struct kvm_vcpu *vcpu);
+
+ /* Host registers preserved across guest mode execution */
+ unsigned long host_sp;
+ unsigned long host_tp;
+ unsigned long host_pgd;
+
+ /* Host CSRs are used when handling exits from guest */
+ unsigned long badi;
+ unsigned long badv;
+ unsigned long host_ecfg;
+ unsigned long host_estat;
+ unsigned long host_percpu;
+
+ /* GPRs */
+ unsigned long gprs[32];
+ unsigned long pc;
+
+ /* Which auxiliary state is loaded (KVM_LARCH_*) */
+ unsigned int aux_inuse;
+
+ /* FPU state */
+ struct loongarch_fpu fpu FPU_ALIGN;
+
+ /* CSR state */
+ struct loongarch_csrs *csr;
+
+ /* GPR used as IO source/target */
+ u32 io_gpr;
+
+ /* KVM register to control count timer */
+ u32 count_ctl;
+ struct hrtimer swtimer;
+
+ /* Bitmask of intr that are pending */
+ unsigned long irq_pending;
+ /* Bitmask of pending intr to be cleared */
+ unsigned long irq_clear;
+
+ /* Bitmask of exceptions that are pending */
+ unsigned long exception_pending;
+ unsigned int esubcode;
+
+ /* Cache for pages needed inside spinlock regions */
+ struct kvm_mmu_memory_cache mmu_page_cache;
+
+ /* vcpu's vpid */
+ u64 vpid;
+
+ /* Frequency of stable timer in Hz */
+ u64 timer_mhz;
+ ktime_t expire;
+
+ /* Last CPU the vCPU state was loaded on */
+ int last_sched_cpu;
+ /* mp state */
+ struct kvm_mp_state mp_state;
+ /* cpucfg */
+ u32 cpucfg[KVM_MAX_CPUCFG_REGS];
+};
+
+static inline unsigned long readl_sw_gcsr(struct loongarch_csrs *csr, int reg)
+{
+ return csr->csrs[reg];
+}
+
+static inline void writel_sw_gcsr(struct loongarch_csrs *csr, int reg, unsigned long val)
+{
+ csr->csrs[reg] = val;
+}
+
+/* Debug: dump vcpu state */
+int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu);
+
+/* MMU handling */
+void kvm_flush_tlb_all(void);
+void kvm_flush_tlb_gpa(struct kvm_vcpu *vcpu, unsigned long gpa);
+int kvm_handle_mm_fault(struct kvm_vcpu *vcpu, unsigned long badv, bool write);
+
+#define KVM_ARCH_WANT_MMU_NOTIFIER
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end, bool blockable);
+int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
+
+static inline void update_pc(struct kvm_vcpu_arch *arch)
+{
+ arch->pc += 4;
+}
+
+/*
+ * kvm_is_ifetch_fault() - Find whether a TLBL exception is due to ifetch fault.
+ * @vcpu: Virtual CPU.
+ *
+ * Returns: Whether the TLBL exception was likely due to an instruction
+ * fetch fault rather than a data load fault.
+ */
+static inline bool kvm_is_ifetch_fault(struct kvm_vcpu_arch *arch)
+{
+ return arch->pc == arch->badv;
+}
+
+/* Misc */
+static inline void kvm_arch_hardware_unsetup(void) {}
+static inline void kvm_arch_sync_events(struct kvm *kvm) {}
+static inline void kvm_arch_memslots_updated(struct kvm *kvm, u64 gen) {}
+static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
+static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {}
+static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}
+static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
+static inline void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *slot) {}
+void kvm_check_vpid(struct kvm_vcpu *vcpu);
+enum hrtimer_restart kvm_swtimer_wakeup(struct hrtimer *timer);
+void kvm_arch_flush_remote_tlbs_memslot(struct kvm *kvm, const struct kvm_memory_slot *memslot);
+void kvm_init_vmcs(struct kvm *kvm);
+void kvm_exc_entry(void);
+int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu);
+
+extern unsigned long vpid_mask;
+extern const unsigned long kvm_exception_size;
+extern const unsigned long kvm_enter_guest_size;
+extern struct kvm_world_switch *kvm_loongarch_ops;
+
+#define SW_GCSR (1 << 0)
+#define HW_GCSR (1 << 1)
+#define INVALID_GCSR (1 << 2)
+
+int get_gcsr_flag(int csr);
+void set_hw_gcsr(int csr_id, unsigned long val);
+
+#endif /* __ASM_LOONGARCH_KVM_HOST_H__ */
diff --git a/arch/loongarch/include/asm/kvm_mmu.h b/arch/loongarch/include/asm/kvm_mmu.h
new file mode 100644
index 000000000000..099bafc6f797
--- /dev/null
+++ b/arch/loongarch/include/asm/kvm_mmu.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef __ASM_LOONGARCH_KVM_MMU_H__
+#define __ASM_LOONGARCH_KVM_MMU_H__
+
+#include <linux/kvm_host.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+
+/*
+ * KVM_MMU_CACHE_MIN_PAGES is the number of GPA page table translation levels
+ * for which pages need to be cached.
+ */
+#define KVM_MMU_CACHE_MIN_PAGES (CONFIG_PGTABLE_LEVELS - 1)
+
+#define _KVM_FLUSH_PGTABLE 0x1
+#define _KVM_HAS_PGMASK 0x2
+#define kvm_pfn_pte(pfn, prot) (((pfn) << PFN_PTE_SHIFT) | pgprot_val(prot))
+#define kvm_pte_pfn(x) ((phys_addr_t)((x & _PFN_MASK) >> PFN_PTE_SHIFT))
+
+typedef unsigned long kvm_pte_t;
+typedef struct kvm_ptw_ctx kvm_ptw_ctx;
+typedef int (*kvm_pte_ops)(kvm_pte_t *pte, phys_addr_t addr, kvm_ptw_ctx *ctx);
+
+struct kvm_ptw_ctx {
+ kvm_pte_ops ops;
+ unsigned long flag;
+
+ /* for kvm_arch_mmu_enable_log_dirty_pt_masked use */
+ unsigned long mask;
+ unsigned long gfn;
+
+ /* page walk mmu info */
+ unsigned int level;
+ unsigned long pgtable_shift;
+ unsigned long invalid_entry;
+ unsigned long *invalid_ptes;
+ unsigned int *pte_shifts;
+ void *opaque;
+
+ /* free pte table page list */
+ struct list_head list;
+};
+
+kvm_pte_t *kvm_pgd_alloc(void);
+
+static inline void kvm_set_pte(kvm_pte_t *ptep, kvm_pte_t val)
+{
+ WRITE_ONCE(*ptep, val);
+}
+
+static inline int kvm_pte_write(kvm_pte_t pte) { return pte & _PAGE_WRITE; }
+static inline int kvm_pte_dirty(kvm_pte_t pte) { return pte & _PAGE_DIRTY; }
+static inline int kvm_pte_young(kvm_pte_t pte) { return pte & _PAGE_ACCESSED; }
+static inline int kvm_pte_huge(kvm_pte_t pte) { return pte & _PAGE_HUGE; }
+
+static inline kvm_pte_t kvm_pte_mkyoung(kvm_pte_t pte)
+{
+ return pte | _PAGE_ACCESSED;
+}
+
+static inline kvm_pte_t kvm_pte_mkold(kvm_pte_t pte)
+{
+ return pte & ~_PAGE_ACCESSED;
+}
+
+static inline kvm_pte_t kvm_pte_mkdirty(kvm_pte_t pte)
+{
+ return pte | _PAGE_DIRTY;
+}
+
+static inline kvm_pte_t kvm_pte_mkclean(kvm_pte_t pte)
+{
+ return pte & ~_PAGE_DIRTY;
+}
+
+static inline kvm_pte_t kvm_pte_mkhuge(kvm_pte_t pte)
+{
+ return pte | _PAGE_HUGE;
+}
+
+static inline kvm_pte_t kvm_pte_mksmall(kvm_pte_t pte)
+{
+ return pte & ~_PAGE_HUGE;
+}
+
+static inline int kvm_need_flush(kvm_ptw_ctx *ctx)
+{
+ return ctx->flag & _KVM_FLUSH_PGTABLE;
+}
+
+static inline kvm_pte_t *kvm_pgtable_offset(kvm_ptw_ctx *ctx, kvm_pte_t *table,
+ phys_addr_t addr)
+{
+
+ return table + ((addr >> ctx->pgtable_shift) & (PTRS_PER_PTE - 1));
+}
+
+static inline phys_addr_t kvm_pgtable_addr_end(kvm_ptw_ctx *ctx,
+ phys_addr_t addr, phys_addr_t end)
+{
+ phys_addr_t boundary, size;
+
+ size = 0x1UL << ctx->pgtable_shift;
+ boundary = (addr + size) & ~(size - 1);
+ return (boundary - 1 < end - 1) ? boundary : end;
+}
+
+static inline int kvm_pte_present(kvm_ptw_ctx *ctx, kvm_pte_t *entry)
+{
+ if (!ctx || ctx->level == 0)
+ return !!(*entry & _PAGE_PRESENT);
+
+ return *entry != ctx->invalid_entry;
+}
+
+static inline int kvm_pte_none(kvm_ptw_ctx *ctx, kvm_pte_t *entry)
+{
+ return *entry == ctx->invalid_entry;
+}
+
+static inline void kvm_ptw_enter(kvm_ptw_ctx *ctx)
+{
+ ctx->level--;
+ ctx->pgtable_shift = ctx->pte_shifts[ctx->level];
+ ctx->invalid_entry = ctx->invalid_ptes[ctx->level];
+}
+
+static inline void kvm_ptw_exit(kvm_ptw_ctx *ctx)
+{
+ ctx->level++;
+ ctx->pgtable_shift = ctx->pte_shifts[ctx->level];
+ ctx->invalid_entry = ctx->invalid_ptes[ctx->level];
+}
+
+#endif /* __ASM_LOONGARCH_KVM_MMU_H__ */
diff --git a/arch/loongarch/include/asm/kvm_types.h b/arch/loongarch/include/asm/kvm_types.h
new file mode 100644
index 000000000000..2fe1d4bdff66
--- /dev/null
+++ b/arch/loongarch/include/asm/kvm_types.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef _ASM_LOONGARCH_KVM_TYPES_H
+#define _ASM_LOONGARCH_KVM_TYPES_H
+
+#define KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE 40
+
+#endif /* _ASM_LOONGARCH_KVM_TYPES_H */
diff --git a/arch/loongarch/include/asm/kvm_vcpu.h b/arch/loongarch/include/asm/kvm_vcpu.h
new file mode 100644
index 000000000000..553cfa2b2b1c
--- /dev/null
+++ b/arch/loongarch/include/asm/kvm_vcpu.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef __ASM_LOONGARCH_KVM_VCPU_H__
+#define __ASM_LOONGARCH_KVM_VCPU_H__
+
+#include <linux/kvm_host.h>
+#include <asm/loongarch.h>
+
+/* Controlled by 0x5 guest estat */
+#define CPU_SIP0 (_ULCAST_(1))
+#define CPU_SIP1 (_ULCAST_(1) << 1)
+#define CPU_PMU (_ULCAST_(1) << 10)
+#define CPU_TIMER (_ULCAST_(1) << 11)
+#define CPU_IPI (_ULCAST_(1) << 12)
+
+/* Controlled by 0x52 guest exception VIP aligned to estat bit 5~12 */
+#define CPU_IP0 (_ULCAST_(1))
+#define CPU_IP1 (_ULCAST_(1) << 1)
+#define CPU_IP2 (_ULCAST_(1) << 2)
+#define CPU_IP3 (_ULCAST_(1) << 3)
+#define CPU_IP4 (_ULCAST_(1) << 4)
+#define CPU_IP5 (_ULCAST_(1) << 5)
+#define CPU_IP6 (_ULCAST_(1) << 6)
+#define CPU_IP7 (_ULCAST_(1) << 7)
+
+#define MNSEC_PER_SEC (NSEC_PER_SEC >> 20)
+
+/* KVM_IRQ_LINE irq field index values */
+#define KVM_LOONGSON_IRQ_TYPE_SHIFT 24
+#define KVM_LOONGSON_IRQ_TYPE_MASK 0xff
+#define KVM_LOONGSON_IRQ_VCPU_SHIFT 16
+#define KVM_LOONGSON_IRQ_VCPU_MASK 0xff
+#define KVM_LOONGSON_IRQ_NUM_SHIFT 0
+#define KVM_LOONGSON_IRQ_NUM_MASK 0xffff
+
+typedef union loongarch_instruction larch_inst;
+typedef int (*exit_handle_fn)(struct kvm_vcpu *);
+
+int kvm_emu_mmio_read(struct kvm_vcpu *vcpu, larch_inst inst);
+int kvm_emu_mmio_write(struct kvm_vcpu *vcpu, larch_inst inst);
+int kvm_complete_mmio_read(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_complete_iocsr_read(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_emu_idle(struct kvm_vcpu *vcpu);
+int kvm_pending_timer(struct kvm_vcpu *vcpu);
+int kvm_handle_fault(struct kvm_vcpu *vcpu, int fault);
+void kvm_deliver_intr(struct kvm_vcpu *vcpu);
+void kvm_deliver_exception(struct kvm_vcpu *vcpu);
+
+void kvm_own_fpu(struct kvm_vcpu *vcpu);
+void kvm_lose_fpu(struct kvm_vcpu *vcpu);
+void kvm_save_fpu(struct loongarch_fpu *fpu);
+void kvm_restore_fpu(struct loongarch_fpu *fpu);
+void kvm_restore_fcsr(struct loongarch_fpu *fpu);
+
+void kvm_acquire_timer(struct kvm_vcpu *vcpu);
+void kvm_init_timer(struct kvm_vcpu *vcpu, unsigned long hz);
+void kvm_reset_timer(struct kvm_vcpu *vcpu);
+void kvm_save_timer(struct kvm_vcpu *vcpu);
+void kvm_restore_timer(struct kvm_vcpu *vcpu);
+
+int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq);
+
+/*
+ * Loongarch KVM guest interrupt handling
+ */
+static inline void kvm_queue_irq(struct kvm_vcpu *vcpu, unsigned int irq)
+{
+ set_bit(irq, &vcpu->arch.irq_pending);
+ clear_bit(irq, &vcpu->arch.irq_clear);
+}
+
+static inline void kvm_dequeue_irq(struct kvm_vcpu *vcpu, unsigned int irq)
+{
+ clear_bit(irq, &vcpu->arch.irq_pending);
+ set_bit(irq, &vcpu->arch.irq_clear);
+}
+
+static inline int kvm_queue_exception(struct kvm_vcpu *vcpu,
+ unsigned int code, unsigned int subcode)
+{
+ /* only one exception can be injected */
+ if (!vcpu->arch.exception_pending) {
+ set_bit(code, &vcpu->arch.exception_pending);
+ vcpu->arch.esubcode = subcode;
+ return 0;
+ } else
+ return -1;
+}
+
+#endif /* __ASM_LOONGARCH_KVM_VCPU_H__ */
diff --git a/arch/loongarch/include/asm/linkage.h b/arch/loongarch/include/asm/linkage.h
index 81b0c4cfbf4f..e2eca1a25b4e 100644
--- a/arch/loongarch/include/asm/linkage.h
+++ b/arch/loongarch/include/asm/linkage.h
@@ -33,4 +33,12 @@
.cfi_endproc; \
SYM_END(name, SYM_T_FUNC)
+#define SYM_CODE_START(name) \
+ SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) \
+ .cfi_startproc;
+
+#define SYM_CODE_END(name) \
+ .cfi_endproc; \
+ SYM_END(name, SYM_T_NONE)
+
#endif
diff --git a/arch/loongarch/include/asm/local.h b/arch/loongarch/include/asm/local.h
index c49675852bdc..f53ea653af76 100644
--- a/arch/loongarch/include/asm/local.h
+++ b/arch/loongarch/include/asm/local.h
@@ -70,22 +70,27 @@ static inline bool local_try_cmpxchg(local_t *l, long *old, long new)
#define local_xchg(l, n) (atomic_long_xchg((&(l)->a), (n)))
/**
- * local_add_unless - add unless the number is a given value
+ * local_add_unless - add unless the number is already a given value
* @l: pointer of type local_t
* @a: the amount to add to l...
* @u: ...unless l is equal to u.
*
- * Atomically adds @a to @l, so long as it was not @u.
- * Returns non-zero if @l was not @u, and zero otherwise.
+ * Atomically adds @a to @l, if @v was not already @u.
+ * Returns true if the addition was done.
*/
-#define local_add_unless(l, a, u) \
-({ \
- long c, old; \
- c = local_read(l); \
- while (c != (u) && (old = local_cmpxchg((l), c, c + (a))) != c) \
- c = old; \
- c != (u); \
-})
+static inline bool
+local_add_unless(local_t *l, long a, long u)
+{
+ long c = local_read(l);
+
+ do {
+ if (unlikely(c == u))
+ return false;
+ } while (!local_try_cmpxchg(l, &c, c + a));
+
+ return true;
+}
+
#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
#define local_dec_return(l) local_sub_return(1, (l))
diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h
index 33531d432b49..46366e783c84 100644
--- a/arch/loongarch/include/asm/loongarch.h
+++ b/arch/loongarch/include/asm/loongarch.h
@@ -226,6 +226,7 @@
#define LOONGARCH_CSR_ECFG 0x4 /* Exception config */
#define CSR_ECFG_VS_SHIFT 16
#define CSR_ECFG_VS_WIDTH 3
+#define CSR_ECFG_VS_SHIFT_END (CSR_ECFG_VS_SHIFT + CSR_ECFG_VS_WIDTH - 1)
#define CSR_ECFG_VS (_ULCAST_(0x7) << CSR_ECFG_VS_SHIFT)
#define CSR_ECFG_IM_SHIFT 0
#define CSR_ECFG_IM_WIDTH 14
@@ -314,13 +315,14 @@
#define CSR_TLBLO1_V (_ULCAST_(0x1) << CSR_TLBLO1_V_SHIFT)
#define LOONGARCH_CSR_GTLBC 0x15 /* Guest TLB control */
-#define CSR_GTLBC_RID_SHIFT 16
-#define CSR_GTLBC_RID_WIDTH 8
-#define CSR_GTLBC_RID (_ULCAST_(0xff) << CSR_GTLBC_RID_SHIFT)
+#define CSR_GTLBC_TGID_SHIFT 16
+#define CSR_GTLBC_TGID_WIDTH 8
+#define CSR_GTLBC_TGID_SHIFT_END (CSR_GTLBC_TGID_SHIFT + CSR_GTLBC_TGID_WIDTH - 1)
+#define CSR_GTLBC_TGID (_ULCAST_(0xff) << CSR_GTLBC_TGID_SHIFT)
#define CSR_GTLBC_TOTI_SHIFT 13
#define CSR_GTLBC_TOTI (_ULCAST_(0x1) << CSR_GTLBC_TOTI_SHIFT)
-#define CSR_GTLBC_USERID_SHIFT 12
-#define CSR_GTLBC_USERID (_ULCAST_(0x1) << CSR_GTLBC_USERID_SHIFT)
+#define CSR_GTLBC_USETGID_SHIFT 12
+#define CSR_GTLBC_USETGID (_ULCAST_(0x1) << CSR_GTLBC_USETGID_SHIFT)
#define CSR_GTLBC_GMTLBSZ_SHIFT 0
#define CSR_GTLBC_GMTLBSZ_WIDTH 6
#define CSR_GTLBC_GMTLBSZ (_ULCAST_(0x3f) << CSR_GTLBC_GMTLBSZ_SHIFT)
@@ -475,6 +477,7 @@
#define LOONGARCH_CSR_GSTAT 0x50 /* Guest status */
#define CSR_GSTAT_GID_SHIFT 16
#define CSR_GSTAT_GID_WIDTH 8
+#define CSR_GSTAT_GID_SHIFT_END (CSR_GSTAT_GID_SHIFT + CSR_GSTAT_GID_WIDTH - 1)
#define CSR_GSTAT_GID (_ULCAST_(0xff) << CSR_GSTAT_GID_SHIFT)
#define CSR_GSTAT_GIDBIT_SHIFT 4
#define CSR_GSTAT_GIDBIT_WIDTH 6
@@ -525,6 +528,12 @@
#define CSR_GCFG_MATC_GUEST (_ULCAST_(0x0) << CSR_GCFG_MATC_SHITF)
#define CSR_GCFG_MATC_ROOT (_ULCAST_(0x1) << CSR_GCFG_MATC_SHITF)
#define CSR_GCFG_MATC_NEST (_ULCAST_(0x2) << CSR_GCFG_MATC_SHITF)
+#define CSR_GCFG_MATP_NEST_SHIFT 2
+#define CSR_GCFG_MATP_NEST (_ULCAST_(0x1) << CSR_GCFG_MATP_NEST_SHIFT)
+#define CSR_GCFG_MATP_ROOT_SHIFT 1
+#define CSR_GCFG_MATP_ROOT (_ULCAST_(0x1) << CSR_GCFG_MATP_ROOT_SHIFT)
+#define CSR_GCFG_MATP_GUEST_SHIFT 0
+#define CSR_GCFG_MATP_GUEST (_ULCAST_(0x1) << CSR_GCFG_MATP_GUEST_SHIFT)
#define LOONGARCH_CSR_GINTC 0x52 /* Guest interrupt control */
#define CSR_GINTC_HC_SHIFT 16
@@ -1089,12 +1098,11 @@
static __always_inline u64 drdtime(void)
{
- int rID = 0;
u64 val = 0;
__asm__ __volatile__(
- "rdtime.d %0, %1 \n\t"
- : "=r"(val), "=r"(rID)
+ "rdtime.d %0, $zero\n\t"
+ : "=r"(val)
:
);
return val;
diff --git a/arch/loongarch/include/asm/percpu.h b/arch/loongarch/include/asm/percpu.h
index b9f567e66016..9b36ac003f89 100644
--- a/arch/loongarch/include/asm/percpu.h
+++ b/arch/loongarch/include/asm/percpu.h
@@ -32,7 +32,7 @@ static inline void set_my_cpu_offset(unsigned long off)
#define __my_cpu_offset __my_cpu_offset
#define PERCPU_OP(op, asm_op, c_op) \
-static inline unsigned long __percpu_##op(void *ptr, \
+static __always_inline unsigned long __percpu_##op(void *ptr, \
unsigned long val, int size) \
{ \
unsigned long ret; \
@@ -40,13 +40,13 @@ static inline unsigned long __percpu_##op(void *ptr, \
switch (size) { \
case 4: \
__asm__ __volatile__( \
- "am"#asm_op".w" " %[ret], %[val], %[ptr] \n" \
+ "am"#asm_op".w" " %[ret], %[val], %[ptr] \n" \
: [ret] "=&r" (ret), [ptr] "+ZB"(*(u32 *)ptr) \
: [val] "r" (val)); \
break; \
case 8: \
__asm__ __volatile__( \
- "am"#asm_op".d" " %[ret], %[val], %[ptr] \n" \
+ "am"#asm_op".d" " %[ret], %[val], %[ptr] \n" \
: [ret] "=&r" (ret), [ptr] "+ZB"(*(u64 *)ptr) \
: [val] "r" (val)); \
break; \
@@ -63,7 +63,7 @@ PERCPU_OP(and, and, &)
PERCPU_OP(or, or, |)
#undef PERCPU_OP
-static inline unsigned long __percpu_read(void *ptr, int size)
+static __always_inline unsigned long __percpu_read(void __percpu *ptr, int size)
{
unsigned long ret;
@@ -100,7 +100,7 @@ static inline unsigned long __percpu_read(void *ptr, int size)
return ret;
}
-static inline void __percpu_write(void *ptr, unsigned long val, int size)
+static __always_inline void __percpu_write(void __percpu *ptr, unsigned long val, int size)
{
switch (size) {
case 1:
@@ -132,8 +132,7 @@ static inline void __percpu_write(void *ptr, unsigned long val, int size)
}
}
-static inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
- int size)
+static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val, int size)
{
switch (size) {
case 1:
diff --git a/arch/loongarch/include/asm/pgalloc.h b/arch/loongarch/include/asm/pgalloc.h
index 79470f0b4f1d..4e2d6b7ca2ee 100644
--- a/arch/loongarch/include/asm/pgalloc.h
+++ b/arch/loongarch/include/asm/pgalloc.h
@@ -84,6 +84,7 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
if (!ptdesc)
return NULL;
+ pagetable_pud_ctor(ptdesc);
pud = ptdesc_address(ptdesc);
pud_init(pud);
diff --git a/arch/loongarch/include/asm/pgtable-bits.h b/arch/loongarch/include/asm/pgtable-bits.h
index 35348d4c4209..21319c1e045c 100644
--- a/arch/loongarch/include/asm/pgtable-bits.h
+++ b/arch/loongarch/include/asm/pgtable-bits.h
@@ -105,13 +105,15 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot)
return __pgprot(prot);
}
+extern bool wc_enabled;
+
#define pgprot_writecombine pgprot_writecombine
static inline pgprot_t pgprot_writecombine(pgprot_t _prot)
{
unsigned long prot = pgprot_val(_prot);
- prot = (prot & ~_CACHE_MASK) | _CACHE_WUC;
+ prot = (prot & ~_CACHE_MASK) | (wc_enabled ? _CACHE_WUC : _CACHE_SUC);
return __pgprot(prot);
}
diff --git a/arch/loongarch/include/asm/setup.h b/arch/loongarch/include/asm/setup.h
index a0bc159ce8bd..ee52fb1e9963 100644
--- a/arch/loongarch/include/asm/setup.h
+++ b/arch/loongarch/include/asm/setup.h
@@ -25,7 +25,7 @@ extern void set_merr_handler(unsigned long offset, void *addr, unsigned long len
#ifdef CONFIG_RELOCATABLE
struct rela_la_abs {
- long offset;
+ long pc;
long symvalue;
};
diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h
new file mode 100644
index 000000000000..c6ad2ee6106c
--- /dev/null
+++ b/arch/loongarch/include/uapi/asm/kvm.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef __UAPI_ASM_LOONGARCH_KVM_H
+#define __UAPI_ASM_LOONGARCH_KVM_H
+
+#include <linux/types.h>
+
+/*
+ * KVM LoongArch specific structures and definitions.
+ *
+ * Some parts derived from the x86 version of this file.
+ */
+
+#define __KVM_HAVE_READONLY_MEM
+
+#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+#define KVM_DIRTY_LOG_PAGE_OFFSET 64
+
+/*
+ * for KVM_GET_REGS and KVM_SET_REGS
+ */
+struct kvm_regs {
+ /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+ __u64 gpr[32];
+ __u64 pc;
+};
+
+/*
+ * for KVM_GET_FPU and KVM_SET_FPU
+ */
+struct kvm_fpu {
+ __u32 fcsr;
+ __u64 fcc; /* 8x8 */
+ struct kvm_fpureg {
+ __u64 val64[4];
+ } fpr[32];
+};
+
+/*
+ * For LoongArch, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various
+ * registers. The id field is broken down as follows:
+ *
+ * bits[63..52] - As per linux/kvm.h
+ * bits[51..32] - Must be zero.
+ * bits[31..16] - Register set.
+ *
+ * Register set = 0: GP registers from kvm_regs (see definitions below).
+ *
+ * Register set = 1: CSR registers.
+ *
+ * Register set = 2: KVM specific registers (see definitions below).
+ *
+ * Register set = 3: FPU / SIMD registers (see definitions below).
+ *
+ * Other sets registers may be added in the future. Each set would
+ * have its own identifier in bits[31..16].
+ */
+
+#define KVM_REG_LOONGARCH_GPR (KVM_REG_LOONGARCH | 0x00000ULL)
+#define KVM_REG_LOONGARCH_CSR (KVM_REG_LOONGARCH | 0x10000ULL)
+#define KVM_REG_LOONGARCH_KVM (KVM_REG_LOONGARCH | 0x20000ULL)
+#define KVM_REG_LOONGARCH_FPSIMD (KVM_REG_LOONGARCH | 0x30000ULL)
+#define KVM_REG_LOONGARCH_CPUCFG (KVM_REG_LOONGARCH | 0x40000ULL)
+#define KVM_REG_LOONGARCH_MASK (KVM_REG_LOONGARCH | 0x70000ULL)
+#define KVM_CSR_IDX_MASK 0x7fff
+#define KVM_CPUCFG_IDX_MASK 0x7fff
+
+/*
+ * KVM_REG_LOONGARCH_KVM - KVM specific control registers.
+ */
+
+#define KVM_REG_LOONGARCH_COUNTER (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 1)
+#define KVM_REG_LOONGARCH_VCPU_RESET (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 2)
+
+#define LOONGARCH_REG_SHIFT 3
+#define LOONGARCH_REG_64(TYPE, REG) (TYPE | KVM_REG_SIZE_U64 | (REG << LOONGARCH_REG_SHIFT))
+#define KVM_IOC_CSRID(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CSR, REG)
+#define KVM_IOC_CPUCFG(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CPUCFG, REG)
+
+struct kvm_debug_exit_arch {
+};
+
+/* for KVM_SET_GUEST_DEBUG */
+struct kvm_guest_debug_arch {
+};
+
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
+/* dummy definition */
+struct kvm_sregs {
+};
+
+struct kvm_iocsr_entry {
+ __u32 addr;
+ __u32 pad;
+ __u64 data;
+};
+
+#define KVM_NR_IRQCHIPS 1
+#define KVM_IRQCHIP_NUM_PINS 64
+#define KVM_MAX_CORES 256
+
+#endif /* __UAPI_ASM_LOONGARCH_KVM_H */
diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
index 4fcc168f0732..3c808c680370 100644
--- a/arch/loongarch/kernel/Makefile
+++ b/arch/loongarch/kernel/Makefile
@@ -57,7 +57,7 @@ obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
obj-$(CONFIG_RELOCATABLE) += relocate.o
-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_UNWINDER_GUESS) += unwind_guess.o
diff --git a/arch/loongarch/kernel/asm-offsets.c b/arch/loongarch/kernel/asm-offsets.c
index 8da0726777ed..173fe514fc9e 100644
--- a/arch/loongarch/kernel/asm-offsets.c
+++ b/arch/loongarch/kernel/asm-offsets.c
@@ -9,6 +9,7 @@
#include <linux/mm.h>
#include <linux/kbuild.h>
#include <linux/suspend.h>
+#include <linux/kvm_host.h>
#include <asm/cpu-info.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
@@ -289,3 +290,34 @@ void output_fgraph_ret_regs_defines(void)
BLANK();
}
#endif
+
+void output_kvm_defines(void)
+{
+ COMMENT("KVM/LoongArch Specific offsets.");
+
+ OFFSET(VCPU_FCC, kvm_vcpu_arch, fpu.fcc);
+ OFFSET(VCPU_FCSR0, kvm_vcpu_arch, fpu.fcsr);
+ BLANK();
+
+ OFFSET(KVM_VCPU_ARCH, kvm_vcpu, arch);
+ OFFSET(KVM_VCPU_KVM, kvm_vcpu, kvm);
+ OFFSET(KVM_VCPU_RUN, kvm_vcpu, run);
+ BLANK();
+
+ OFFSET(KVM_ARCH_HSP, kvm_vcpu_arch, host_sp);
+ OFFSET(KVM_ARCH_HTP, kvm_vcpu_arch, host_tp);
+ OFFSET(KVM_ARCH_HPGD, kvm_vcpu_arch, host_pgd);
+ OFFSET(KVM_ARCH_HANDLE_EXIT, kvm_vcpu_arch, handle_exit);
+ OFFSET(KVM_ARCH_HEENTRY, kvm_vcpu_arch, host_eentry);
+ OFFSET(KVM_ARCH_GEENTRY, kvm_vcpu_arch, guest_eentry);
+ OFFSET(KVM_ARCH_GPC, kvm_vcpu_arch, pc);
+ OFFSET(KVM_ARCH_GGPR, kvm_vcpu_arch, gprs);
+ OFFSET(KVM_ARCH_HBADI, kvm_vcpu_arch, badi);
+ OFFSET(KVM_ARCH_HBADV, kvm_vcpu_arch, badv);
+ OFFSET(KVM_ARCH_HECFG, kvm_vcpu_arch, host_ecfg);
+ OFFSET(KVM_ARCH_HESTAT, kvm_vcpu_arch, host_estat);
+ OFFSET(KVM_ARCH_HPERCPU, kvm_vcpu_arch, host_percpu);
+
+ OFFSET(KVM_GPGD, kvm, arch.pgd);
+ BLANK();
+}
diff --git a/arch/loongarch/kernel/efi.c b/arch/loongarch/kernel/efi.c
index 9fc10cea21e1..acb5d3385675 100644
--- a/arch/loongarch/kernel/efi.c
+++ b/arch/loongarch/kernel/efi.c
@@ -68,6 +68,11 @@ void __init efi_runtime_init(void)
unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR;
+#if defined(CONFIG_SYSFB) || defined(CONFIG_EFI_EARLYCON)
+struct screen_info screen_info __section(".data");
+EXPORT_SYMBOL_GPL(screen_info);
+#endif
+
static void __init init_screen_info(void)
{
struct screen_info *si;
@@ -115,7 +120,8 @@ void __init efi_init(void)
set_bit(EFI_CONFIG_TABLES, &efi.flags);
- init_screen_info();
+ if (IS_ENABLED(CONFIG_EFI_EARLYCON) || IS_ENABLED(CONFIG_SYSFB))
+ init_screen_info();
if (boot_memmap == EFI_INVALID_TABLE_ADDR)
return;
diff --git a/arch/loongarch/kernel/entry.S b/arch/loongarch/kernel/entry.S
index 65518bb8f472..1ec8e4c4cc2b 100644
--- a/arch/loongarch/kernel/entry.S
+++ b/arch/loongarch/kernel/entry.S
@@ -18,7 +18,7 @@
.text
.cfi_sections .debug_frame
.align 5
-SYM_FUNC_START(handle_syscall)
+SYM_CODE_START(handle_syscall)
csrrd t0, PERCPU_BASE_KS
la.pcrel t1, kernelsp
add.d t1, t1, t0
@@ -71,7 +71,7 @@ SYM_FUNC_START(handle_syscall)
bl do_syscall
RESTORE_ALL_AND_RET
-SYM_FUNC_END(handle_syscall)
+SYM_CODE_END(handle_syscall)
_ASM_NOKPROBE(handle_syscall)
SYM_CODE_START(ret_from_fork)
diff --git a/arch/loongarch/kernel/genex.S b/arch/loongarch/kernel/genex.S
index 78f066384657..2bb3aa2dcfcb 100644
--- a/arch/loongarch/kernel/genex.S
+++ b/arch/loongarch/kernel/genex.S
@@ -31,7 +31,7 @@ SYM_FUNC_START(__arch_cpu_idle)
1: jr ra
SYM_FUNC_END(__arch_cpu_idle)
-SYM_FUNC_START(handle_vint)
+SYM_CODE_START(handle_vint)
BACKUP_T0T1
SAVE_ALL
la_abs t1, __arch_cpu_idle
@@ -46,11 +46,11 @@ SYM_FUNC_START(handle_vint)
la_abs t0, do_vint
jirl ra, t0, 0
RESTORE_ALL_AND_RET
-SYM_FUNC_END(handle_vint)
+SYM_CODE_END(handle_vint)
-SYM_FUNC_START(except_vec_cex)
+SYM_CODE_START(except_vec_cex)
b cache_parity_error
-SYM_FUNC_END(except_vec_cex)
+SYM_CODE_END(except_vec_cex)
.macro build_prep_badv
csrrd t0, LOONGARCH_CSR_BADV
@@ -66,7 +66,7 @@ SYM_FUNC_END(except_vec_cex)
.macro BUILD_HANDLER exception handler prep
.align 5
- SYM_FUNC_START(handle_\exception)
+ SYM_CODE_START(handle_\exception)
666:
BACKUP_T0T1
SAVE_ALL
@@ -76,7 +76,7 @@ SYM_FUNC_END(except_vec_cex)
jirl ra, t0, 0
668:
RESTORE_ALL_AND_RET
- SYM_FUNC_END(handle_\exception)
+ SYM_CODE_END(handle_\exception)
SYM_DATA(unwind_hint_\exception, .word 668b - 666b)
.endm
@@ -93,7 +93,7 @@ SYM_FUNC_END(except_vec_cex)
BUILD_HANDLER watch watch none
BUILD_HANDLER reserved reserved none /* others */
-SYM_FUNC_START(handle_sys)
+SYM_CODE_START(handle_sys)
la_abs t0, handle_syscall
jr t0
-SYM_FUNC_END(handle_sys)
+SYM_CODE_END(handle_sys)
diff --git a/arch/loongarch/kernel/image-vars.h b/arch/loongarch/kernel/image-vars.h
index e561989d02de..5087416b9678 100644
--- a/arch/loongarch/kernel/image-vars.h
+++ b/arch/loongarch/kernel/image-vars.h
@@ -12,7 +12,9 @@ __efistub_kernel_entry = kernel_entry;
__efistub_kernel_asize = kernel_asize;
__efistub_kernel_fsize = kernel_fsize;
__efistub_kernel_offset = kernel_offset;
+#if defined(CONFIG_EFI_EARLYCON) || defined(CONFIG_SYSFB)
__efistub_screen_info = screen_info;
+#endif
#endif
diff --git a/arch/loongarch/kernel/relocate.c b/arch/loongarch/kernel/relocate.c
index 6c3eff9af9fb..1acfa704c8d0 100644
--- a/arch/loongarch/kernel/relocate.c
+++ b/arch/loongarch/kernel/relocate.c
@@ -52,7 +52,7 @@ static inline void __init relocate_absolute(long random_offset)
for (p = begin; (void *)p < end; p++) {
long v = p->symvalue;
uint32_t lu12iw, ori, lu32id, lu52id;
- union loongarch_instruction *insn = (void *)p - p->offset;
+ union loongarch_instruction *insn = (void *)p->pc;
lu12iw = (v >> 12) & 0xfffff;
ori = v & 0xfff;
@@ -102,6 +102,14 @@ static inline __init unsigned long get_random_boot(void)
return hash;
}
+static int __init nokaslr(char *p)
+{
+ pr_info("KASLR is disabled.\n");
+
+ return 0; /* Print a notice and silence the boot warning */
+}
+early_param("nokaslr", nokaslr);
+
static inline __init bool kaslr_disabled(void)
{
char *str;
diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c
index 7783f0a3d742..d183a745fb85 100644
--- a/arch/loongarch/kernel/setup.c
+++ b/arch/loongarch/kernel/setup.c
@@ -16,7 +16,6 @@
#include <linux/dmi.h>
#include <linux/efi.h>
#include <linux/export.h>
-#include <linux/screen_info.h>
#include <linux/memblock.h>
#include <linux/initrd.h>
#include <linux/ioport.h>
@@ -57,8 +56,6 @@
#define SMBIOS_CORE_PACKAGE_OFFSET 0x23
#define LOONGSON_EFI_ENABLE (1 << 3)
-struct screen_info screen_info __section(".data");
-
unsigned long fw_arg0, fw_arg1, fw_arg2;
DEFINE_PER_CPU(unsigned long, kernelsp);
struct cpuinfo_loongarch cpu_data[NR_CPUS] __read_mostly;
@@ -161,19 +158,19 @@ static void __init smbios_parse(void)
}
#ifdef CONFIG_ARCH_WRITECOMBINE
-pgprot_t pgprot_wc = PAGE_KERNEL_WUC;
+bool wc_enabled = true;
#else
-pgprot_t pgprot_wc = PAGE_KERNEL_SUC;
+bool wc_enabled = false;
#endif
-EXPORT_SYMBOL(pgprot_wc);
+EXPORT_SYMBOL(wc_enabled);
static int __init setup_writecombine(char *p)
{
if (!strcmp(p, "on"))
- pgprot_wc = PAGE_KERNEL_WUC;
+ wc_enabled = true;
else if (!strcmp(p, "off"))
- pgprot_wc = PAGE_KERNEL_SUC;
+ wc_enabled = false;
else
pr_warn("Unknown writecombine setting \"%s\".\n", p);
@@ -267,7 +264,9 @@ static void __init arch_parse_crashkernel(void)
unsigned long long crash_base, crash_size;
total_mem = memblock_phys_mem_size();
- ret = parse_crashkernel(boot_command_line, total_mem, &crash_size, &crash_base);
+ ret = parse_crashkernel(boot_command_line, total_mem,
+ &crash_size, &crash_base,
+ NULL, NULL);
if (ret < 0 || crash_size <= 0)
return;
diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c
index ef35c871244f..5bca12d16e06 100644
--- a/arch/loongarch/kernel/smp.c
+++ b/arch/loongarch/kernel/smp.c
@@ -504,8 +504,9 @@ asmlinkage void start_secondary(void)
unsigned int cpu;
sync_counter();
- cpu = smp_processor_id();
+ cpu = raw_smp_processor_id();
set_my_cpu_offset(per_cpu_offset(cpu));
+ rcutree_report_cpu_starting(cpu);
cpu_probe();
constant_clockevent_init();
diff --git a/arch/loongarch/kernel/stacktrace.c b/arch/loongarch/kernel/stacktrace.c
index 92270f14db94..f623feb2129f 100644
--- a/arch/loongarch/kernel/stacktrace.c
+++ b/arch/loongarch/kernel/stacktrace.c
@@ -32,7 +32,7 @@ void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
}
for (unwind_start(&state, task, regs);
- !unwind_done(&state) && !unwind_error(&state); unwind_next_frame(&state)) {
+ !unwind_done(&state); unwind_next_frame(&state)) {
addr = unwind_get_return_address(&state);
if (!addr || !consume_entry(cookie, addr))
break;
diff --git a/arch/loongarch/kernel/time.c b/arch/loongarch/kernel/time.c
index 3064af94db9c..e7015f7b70e3 100644
--- a/arch/loongarch/kernel/time.c
+++ b/arch/loongarch/kernel/time.c
@@ -58,14 +58,16 @@ static int constant_set_state_oneshot(struct clock_event_device *evt)
return 0;
}
-static int constant_set_state_oneshot_stopped(struct clock_event_device *evt)
+static int constant_set_state_periodic(struct clock_event_device *evt)
{
+ unsigned long period;
unsigned long timer_config;
raw_spin_lock(&state_lock);
- timer_config = csr_read64(LOONGARCH_CSR_TCFG);
- timer_config &= ~CSR_TCFG_EN;
+ period = const_clock_freq / HZ;
+ timer_config = period & CSR_TCFG_VAL;
+ timer_config |= (CSR_TCFG_PERIOD | CSR_TCFG_EN);
csr_write64(timer_config, LOONGARCH_CSR_TCFG);
raw_spin_unlock(&state_lock);
@@ -73,16 +75,14 @@ static int constant_set_state_oneshot_stopped(struct clock_event_device *evt)
return 0;
}
-static int constant_set_state_periodic(struct clock_event_device *evt)
+static int constant_set_state_shutdown(struct clock_event_device *evt)
{
- unsigned long period;
unsigned long timer_config;
raw_spin_lock(&state_lock);
- period = const_clock_freq / HZ;
- timer_config = period & CSR_TCFG_VAL;
- timer_config |= (CSR_TCFG_PERIOD | CSR_TCFG_EN);
+ timer_config = csr_read64(LOONGARCH_CSR_TCFG);
+ timer_config &= ~CSR_TCFG_EN;
csr_write64(timer_config, LOONGARCH_CSR_TCFG);
raw_spin_unlock(&state_lock);
@@ -90,11 +90,6 @@ static int constant_set_state_periodic(struct clock_event_device *evt)
return 0;
}
-static int constant_set_state_shutdown(struct clock_event_device *evt)
-{
- return 0;
-}
-
static int constant_timer_next_event(unsigned long delta, struct clock_event_device *evt)
{
unsigned long timer_config;
@@ -161,7 +156,7 @@ int constant_clockevent_init(void)
cd->rating = 320;
cd->cpumask = cpumask_of(cpu);
cd->set_state_oneshot = constant_set_state_oneshot;
- cd->set_state_oneshot_stopped = constant_set_state_oneshot_stopped;
+ cd->set_state_oneshot_stopped = constant_set_state_shutdown;
cd->set_state_periodic = constant_set_state_periodic;
cd->set_state_shutdown = constant_set_state_shutdown;
cd->set_next_event = constant_timer_next_event;
diff --git a/arch/loongarch/kernel/unwind.c b/arch/loongarch/kernel/unwind.c
index ba324ba76fa1..a463d6961344 100644
--- a/arch/loongarch/kernel/unwind.c
+++ b/arch/loongarch/kernel/unwind.c
@@ -28,6 +28,5 @@ bool default_next_frame(struct unwind_state *state)
} while (!get_stack_info(state->sp, state->task, info));
- state->error = true;
return false;
}
diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kernel/unwind_prologue.c
index 55afc27320e1..929ae240280a 100644
--- a/arch/loongarch/kernel/unwind_prologue.c
+++ b/arch/loongarch/kernel/unwind_prologue.c
@@ -227,7 +227,7 @@ static bool next_frame(struct unwind_state *state)
} while (!get_stack_info(state->sp, state->task, info));
out:
- state->error = true;
+ state->stack_info.type = STACK_TYPE_UNKNOWN;
return false;
}
diff --git a/arch/loongarch/kvm/Kconfig b/arch/loongarch/kvm/Kconfig
new file mode 100644
index 000000000000..fda425babfb2
--- /dev/null
+++ b/arch/loongarch/kvm/Kconfig
@@ -0,0 +1,40 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# KVM configuration
+#
+
+source "virt/kvm/Kconfig"
+
+menuconfig VIRTUALIZATION
+ bool "Virtualization"
+ help
+ Say Y here to get to see options for using your Linux host to run
+ other operating systems inside virtual machines (guests).
+ This option alone does not add any kernel code.
+
+ If you say N, all options in this submenu will be skipped and
+ disabled.
+
+if VIRTUALIZATION
+
+config KVM
+ tristate "Kernel-based Virtual Machine (KVM) support"
+ depends on AS_HAS_LVZ_EXTENSION
+ depends on HAVE_KVM
+ select HAVE_KVM_DIRTY_RING_ACQ_REL
+ select HAVE_KVM_EVENTFD
+ select HAVE_KVM_VCPU_ASYNC_IOCTL
+ select KVM_GENERIC_DIRTYLOG_READ_PROTECT
+ select KVM_GENERIC_HARDWARE_ENABLING
+ select KVM_MMIO
+ select KVM_XFER_TO_GUEST_WORK
+ select MMU_NOTIFIER
+ select PREEMPT_NOTIFIERS
+ help
+ Support hosting virtualized guest machines using
+ hardware virtualization extensions. You will need
+ a processor equipped with virtualization extensions.
+
+ If unsure, say N.
+
+endif # VIRTUALIZATION
diff --git a/arch/loongarch/kvm/Makefile b/arch/loongarch/kvm/Makefile
new file mode 100644
index 000000000000..244467d7792a
--- /dev/null
+++ b/arch/loongarch/kvm/Makefile
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for LoongArch KVM support
+#
+
+ccflags-y += -I $(srctree)/$(src)
+
+include $(srctree)/virt/kvm/Makefile.kvm
+
+obj-$(CONFIG_KVM) += kvm.o
+
+kvm-y += exit.o
+kvm-y += interrupt.o
+kvm-y += main.o
+kvm-y += mmu.o
+kvm-y += switch.o
+kvm-y += timer.o
+kvm-y += tlb.o
+kvm-y += vcpu.o
+kvm-y += vm.o
+
+CFLAGS_exit.o += $(call cc-option,-Wno-override-init,)
diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
new file mode 100644
index 000000000000..ce8de3fa472c
--- /dev/null
+++ b/arch/loongarch/kvm/exit.c
@@ -0,0 +1,696 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/kvm_host.h>
+#include <linux/module.h>
+#include <linux/preempt.h>
+#include <linux/vmalloc.h>
+#include <asm/fpu.h>
+#include <asm/inst.h>
+#include <asm/loongarch.h>
+#include <asm/mmzone.h>
+#include <asm/numa.h>
+#include <asm/time.h>
+#include <asm/tlb.h>
+#include <asm/kvm_csr.h>
+#include <asm/kvm_vcpu.h>
+#include "trace.h"
+
+static unsigned long kvm_emu_read_csr(struct kvm_vcpu *vcpu, int csrid)
+{
+ unsigned long val = 0;
+ struct loongarch_csrs *csr = vcpu->arch.csr;
+
+ /*
+ * From LoongArch Reference Manual Volume 1 Chapter 4.2.1
+ * For undefined CSR id, return value is 0
+ */
+ if (get_gcsr_flag(csrid) & SW_GCSR)
+ val = kvm_read_sw_gcsr(csr, csrid);
+ else
+ pr_warn_once("Unsupported csrrd 0x%x with pc %lx\n", csrid, vcpu->arch.pc);
+
+ return val;
+}
+
+static unsigned long kvm_emu_write_csr(struct kvm_vcpu *vcpu, int csrid, unsigned long val)
+{
+ unsigned long old = 0;
+ struct loongarch_csrs *csr = vcpu->arch.csr;
+
+ if (get_gcsr_flag(csrid) & SW_GCSR) {
+ old = kvm_read_sw_gcsr(csr, csrid);
+ kvm_write_sw_gcsr(csr, csrid, val);
+ } else
+ pr_warn_once("Unsupported csrwr 0x%x with pc %lx\n", csrid, vcpu->arch.pc);
+
+ return old;
+}
+
+static unsigned long kvm_emu_xchg_csr(struct kvm_vcpu *vcpu, int csrid,
+ unsigned long csr_mask, unsigned long val)
+{
+ unsigned long old = 0;
+ struct loongarch_csrs *csr = vcpu->arch.csr;
+
+ if (get_gcsr_flag(csrid) & SW_GCSR) {
+ old = kvm_read_sw_gcsr(csr, csrid);
+ val = (old & ~csr_mask) | (val & csr_mask);
+ kvm_write_sw_gcsr(csr, csrid, val);
+ old = old & csr_mask;
+ } else
+ pr_warn_once("Unsupported csrxchg 0x%x with pc %lx\n", csrid, vcpu->arch.pc);
+
+ return old;
+}
+
+static int kvm_handle_csr(struct kvm_vcpu *vcpu, larch_inst inst)
+{
+ unsigned int rd, rj, csrid;
+ unsigned long csr_mask, val = 0;
+
+ /*
+ * CSR value mask imm
+ * rj = 0 means csrrd
+ * rj = 1 means csrwr
+ * rj != 0,1 means csrxchg
+ */
+ rd = inst.reg2csr_format.rd;
+ rj = inst.reg2csr_format.rj;
+ csrid = inst.reg2csr_format.csr;
+
+ /* Process CSR ops */
+ switch (rj) {
+ case 0: /* process csrrd */
+ val = kvm_emu_read_csr(vcpu, csrid);
+ vcpu->arch.gprs[rd] = val;
+ break;
+ case 1: /* process csrwr */
+ val = vcpu->arch.gprs[rd];
+ val = kvm_emu_write_csr(vcpu, csrid, val);
+ vcpu->arch.gprs[rd] = val;
+ break;
+ default: /* process csrxchg */
+ val = vcpu->arch.gprs[rd];
+ csr_mask = vcpu->arch.gprs[rj];
+ val = kvm_emu_xchg_csr(vcpu, csrid, csr_mask, val);
+ vcpu->arch.gprs[rd] = val;
+ }
+
+ return EMULATE_DONE;
+}
+
+int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+ int ret;
+ unsigned long val;
+ u32 addr, rd, rj, opcode;
+
+ /*
+ * Each IOCSR with different opcode
+ */
+ rd = inst.reg2_format.rd;
+ rj = inst.reg2_format.rj;
+ opcode = inst.reg2_format.opcode;
+ addr = vcpu->arch.gprs[rj];
+ ret = EMULATE_DO_IOCSR;
+ run->iocsr_io.phys_addr = addr;
+ run->iocsr_io.is_write = 0;
+
+ /* LoongArch is Little endian */
+ switch (opcode) {
+ case iocsrrdb_op:
+ run->iocsr_io.len = 1;
+ break;
+ case iocsrrdh_op:
+ run->iocsr_io.len = 2;
+ break;
+ case iocsrrdw_op:
+ run->iocsr_io.len = 4;
+ break;
+ case iocsrrdd_op:
+ run->iocsr_io.len = 8;
+ break;
+ case iocsrwrb_op:
+ run->iocsr_io.len = 1;
+ run->iocsr_io.is_write = 1;
+ break;
+ case iocsrwrh_op:
+ run->iocsr_io.len = 2;
+ run->iocsr_io.is_write = 1;
+ break;
+ case iocsrwrw_op:
+ run->iocsr_io.len = 4;
+ run->iocsr_io.is_write = 1;
+ break;
+ case iocsrwrd_op:
+ run->iocsr_io.len = 8;
+ run->iocsr_io.is_write = 1;
+ break;
+ default:
+ ret = EMULATE_FAIL;
+ break;
+ }
+
+ if (ret == EMULATE_DO_IOCSR) {
+ if (run->iocsr_io.is_write) {
+ val = vcpu->arch.gprs[rd];
+ memcpy(run->iocsr_io.data, &val, run->iocsr_io.len);
+ }
+ vcpu->arch.io_gpr = rd;
+ }
+
+ return ret;
+}
+
+int kvm_complete_iocsr_read(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+ enum emulation_result er = EMULATE_DONE;
+ unsigned long *gpr = &vcpu->arch.gprs[vcpu->arch.io_gpr];
+
+ switch (run->iocsr_io.len) {
+ case 1:
+ *gpr = *(s8 *)run->iocsr_io.data;
+ break;
+ case 2:
+ *gpr = *(s16 *)run->iocsr_io.data;
+ break;
+ case 4:
+ *gpr = *(s32 *)run->iocsr_io.data;
+ break;
+ case 8:
+ *gpr = *(s64 *)run->iocsr_io.data;
+ break;
+ default:
+ kvm_err("Bad IOCSR length: %d, addr is 0x%lx\n",
+ run->iocsr_io.len, vcpu->arch.badv);
+ er = EMULATE_FAIL;
+ break;
+ }
+
+ return er;
+}
+
+int kvm_emu_idle(struct kvm_vcpu *vcpu)
+{
+ ++vcpu->stat.idle_exits;
+ trace_kvm_exit_idle(vcpu, KVM_TRACE_EXIT_IDLE);
+
+ if (!kvm_arch_vcpu_runnable(vcpu)) {
+ /*
+ * Switch to the software timer before halt-polling/blocking as
+ * the guest's timer may be a break event for the vCPU, and the
+ * hypervisor timer runs only when the CPU is in guest mode.
+ * Switch before halt-polling so that KVM recognizes an expired
+ * timer before blocking.
+ */
+ kvm_save_timer(vcpu);
+ kvm_vcpu_block(vcpu);
+ }
+
+ return EMULATE_DONE;
+}
+
+static int kvm_trap_handle_gspr(struct kvm_vcpu *vcpu)
+{
+ int rd, rj;
+ unsigned int index;
+ unsigned long curr_pc;
+ larch_inst inst;
+ enum emulation_result er = EMULATE_DONE;
+ struct kvm_run *run = vcpu->run;
+
+ /* Fetch the instruction */
+ inst.word = vcpu->arch.badi;
+ curr_pc = vcpu->arch.pc;
+ update_pc(&vcpu->arch);
+
+ trace_kvm_exit_gspr(vcpu, inst.word);
+ er = EMULATE_FAIL;
+ switch (((inst.word >> 24) & 0xff)) {
+ case 0x0: /* CPUCFG GSPR */
+ if (inst.reg2_format.opcode == 0x1B) {
+ rd = inst.reg2_format.rd;
+ rj = inst.reg2_format.rj;
+ ++vcpu->stat.cpucfg_exits;
+ index = vcpu->arch.gprs[rj];
+ er = EMULATE_DONE;
+ /*
+ * By LoongArch Reference Manual 2.2.10.5
+ * return value is 0 for undefined cpucfg index
+ */
+ if (index < KVM_MAX_CPUCFG_REGS)
+ vcpu->arch.gprs[rd] = vcpu->arch.cpucfg[index];
+ else
+ vcpu->arch.gprs[rd] = 0;
+ }
+ break;
+ case 0x4: /* CSR{RD,WR,XCHG} GSPR */
+ er = kvm_handle_csr(vcpu, inst);
+ break;
+ case 0x6: /* Cache, Idle and IOCSR GSPR */
+ switch (((inst.word >> 22) & 0x3ff)) {
+ case 0x18: /* Cache GSPR */
+ er = EMULATE_DONE;
+ trace_kvm_exit_cache(vcpu, KVM_TRACE_EXIT_CACHE);
+ break;
+ case 0x19: /* Idle/IOCSR GSPR */
+ switch (((inst.word >> 15) & 0x1ffff)) {
+ case 0xc90: /* IOCSR GSPR */
+ er = kvm_emu_iocsr(inst, run, vcpu);
+ break;
+ case 0xc91: /* Idle GSPR */
+ er = kvm_emu_idle(vcpu);
+ break;
+ default:
+ er = EMULATE_FAIL;
+ break;
+ }
+ break;
+ default:
+ er = EMULATE_FAIL;
+ break;
+ }
+ break;
+ default:
+ er = EMULATE_FAIL;
+ break;
+ }
+
+ /* Rollback PC only if emulation was unsuccessful */
+ if (er == EMULATE_FAIL) {
+ kvm_err("[%#lx]%s: unsupported gspr instruction 0x%08x\n",
+ curr_pc, __func__, inst.word);
+
+ kvm_arch_vcpu_dump_regs(vcpu);
+ vcpu->arch.pc = curr_pc;
+ }
+
+ return er;
+}
+
+/*
+ * Trigger GSPR:
+ * 1) Execute CPUCFG instruction;
+ * 2) Execute CACOP/IDLE instructions;
+ * 3) Access to unimplemented CSRs/IOCSRs.
+ */
+static int kvm_handle_gspr(struct kvm_vcpu *vcpu)
+{
+ int ret = RESUME_GUEST;
+ enum emulation_result er = EMULATE_DONE;
+
+ er = kvm_trap_handle_gspr(vcpu);
+
+ if (er == EMULATE_DONE) {
+ ret = RESUME_GUEST;
+ } else if (er == EMULATE_DO_MMIO) {
+ vcpu->run->exit_reason = KVM_EXIT_MMIO;
+ ret = RESUME_HOST;
+ } else if (er == EMULATE_DO_IOCSR) {
+ vcpu->run->exit_reason = KVM_EXIT_LOONGARCH_IOCSR;
+ ret = RESUME_HOST;
+ } else {
+ kvm_queue_exception(vcpu, EXCCODE_INE, 0);
+ ret = RESUME_GUEST;
+ }
+
+ return ret;
+}
+
+int kvm_emu_mmio_read(struct kvm_vcpu *vcpu, larch_inst inst)
+{
+ int ret;
+ unsigned int op8, opcode, rd;
+ struct kvm_run *run = vcpu->run;
+
+ run->mmio.phys_addr = vcpu->arch.badv;
+ vcpu->mmio_needed = 2; /* signed */
+ op8 = (inst.word >> 24) & 0xff;
+ ret = EMULATE_DO_MMIO;
+
+ switch (op8) {
+ case 0x24 ... 0x27: /* ldptr.w/d process */
+ rd = inst.reg2i14_format.rd;
+ opcode = inst.reg2i14_format.opcode;
+
+ switch (opcode) {
+ case ldptrw_op:
+ run->mmio.len = 4;
+ break;
+ case ldptrd_op:
+ run->mmio.len = 8;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x28 ... 0x2e: /* ld.b/h/w/d, ld.bu/hu/wu process */
+ rd = inst.reg2i12_format.rd;
+ opcode = inst.reg2i12_format.opcode;
+
+ switch (opcode) {
+ case ldb_op:
+ run->mmio.len = 1;
+ break;
+ case ldbu_op:
+ vcpu->mmio_needed = 1; /* unsigned */
+ run->mmio.len = 1;
+ break;
+ case ldh_op:
+ run->mmio.len = 2;
+ break;
+ case ldhu_op:
+ vcpu->mmio_needed = 1; /* unsigned */
+ run->mmio.len = 2;
+ break;
+ case ldw_op:
+ run->mmio.len = 4;
+ break;
+ case ldwu_op:
+ vcpu->mmio_needed = 1; /* unsigned */
+ run->mmio.len = 4;
+ break;
+ case ldd_op:
+ run->mmio.len = 8;
+ break;
+ default:
+ ret = EMULATE_FAIL;
+ break;
+ }
+ break;
+ case 0x38: /* ldx.b/h/w/d, ldx.bu/hu/wu process */
+ rd = inst.reg3_format.rd;
+ opcode = inst.reg3_format.opcode;
+
+ switch (opcode) {
+ case ldxb_op:
+ run->mmio.len = 1;
+ break;
+ case ldxbu_op:
+ run->mmio.len = 1;
+ vcpu->mmio_needed = 1; /* unsigned */
+ break;
+ case ldxh_op:
+ run->mmio.len = 2;
+ break;
+ case ldxhu_op:
+ run->mmio.len = 2;
+ vcpu->mmio_needed = 1; /* unsigned */
+ break;
+ case ldxw_op:
+ run->mmio.len = 4;
+ break;
+ case ldxwu_op:
+ run->mmio.len = 4;
+ vcpu->mmio_needed = 1; /* unsigned */
+ break;
+ case ldxd_op:
+ run->mmio.len = 8;
+ break;
+ default:
+ ret = EMULATE_FAIL;
+ break;
+ }
+ break;
+ default:
+ ret = EMULATE_FAIL;
+ }
+
+ if (ret == EMULATE_DO_MMIO) {
+ /* Set for kvm_complete_mmio_read() use */
+ vcpu->arch.io_gpr = rd;
+ run->mmio.is_write = 0;
+ vcpu->mmio_is_write = 0;
+ } else {
+ kvm_err("Read not supported Inst=0x%08x @%lx BadVaddr:%#lx\n",
+ inst.word, vcpu->arch.pc, vcpu->arch.badv);
+ kvm_arch_vcpu_dump_regs(vcpu);
+ vcpu->mmio_needed = 0;
+ }
+
+ return ret;
+}
+
+int kvm_complete_mmio_read(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+ enum emulation_result er = EMULATE_DONE;
+ unsigned long *gpr = &vcpu->arch.gprs[vcpu->arch.io_gpr];
+
+ /* Update with new PC */
+ update_pc(&vcpu->arch);
+ switch (run->mmio.len) {
+ case 1:
+ if (vcpu->mmio_needed == 2)
+ *gpr = *(s8 *)run->mmio.data;
+ else
+ *gpr = *(u8 *)run->mmio.data;
+ break;
+ case 2:
+ if (vcpu->mmio_needed == 2)
+ *gpr = *(s16 *)run->mmio.data;
+ else
+ *gpr = *(u16 *)run->mmio.data;
+ break;
+ case 4:
+ if (vcpu->mmio_needed == 2)
+ *gpr = *(s32 *)run->mmio.data;
+ else
+ *gpr = *(u32 *)run->mmio.data;
+ break;
+ case 8:
+ *gpr = *(s64 *)run->mmio.data;
+ break;
+ default:
+ kvm_err("Bad MMIO length: %d, addr is 0x%lx\n",
+ run->mmio.len, vcpu->arch.badv);
+ er = EMULATE_FAIL;
+ break;
+ }
+
+ return er;
+}
+
+int kvm_emu_mmio_write(struct kvm_vcpu *vcpu, larch_inst inst)
+{
+ int ret;
+ unsigned int rd, op8, opcode;
+ unsigned long curr_pc, rd_val = 0;
+ struct kvm_run *run = vcpu->run;
+ void *data = run->mmio.data;
+
+ /*
+ * Update PC and hold onto current PC in case there is
+ * an error and we want to rollback the PC
+ */
+ curr_pc = vcpu->arch.pc;
+ update_pc(&vcpu->arch);
+
+ op8 = (inst.word >> 24) & 0xff;
+ run->mmio.phys_addr = vcpu->arch.badv;
+ ret = EMULATE_DO_MMIO;
+ switch (op8) {
+ case 0x24 ... 0x27: /* stptr.w/d process */
+ rd = inst.reg2i14_format.rd;
+ opcode = inst.reg2i14_format.opcode;
+
+ switch (opcode) {
+ case stptrw_op:
+ run->mmio.len = 4;
+ *(unsigned int *)data = vcpu->arch.gprs[rd];
+ break;
+ case stptrd_op:
+ run->mmio.len = 8;
+ *(unsigned long *)data = vcpu->arch.gprs[rd];
+ break;
+ default:
+ ret = EMULATE_FAIL;
+ break;
+ }
+ break;
+ case 0x28 ... 0x2e: /* st.b/h/w/d process */
+ rd = inst.reg2i12_format.rd;
+ opcode = inst.reg2i12_format.opcode;
+ rd_val = vcpu->arch.gprs[rd];
+
+ switch (opcode) {
+ case stb_op:
+ run->mmio.len = 1;
+ *(unsigned char *)data = rd_val;
+ break;
+ case sth_op:
+ run->mmio.len = 2;
+ *(unsigned short *)data = rd_val;
+ break;
+ case stw_op:
+ run->mmio.len = 4;
+ *(unsigned int *)data = rd_val;
+ break;
+ case std_op:
+ run->mmio.len = 8;
+ *(unsigned long *)data = rd_val;
+ break;
+ default:
+ ret = EMULATE_FAIL;
+ break;
+ }
+ break;
+ case 0x38: /* stx.b/h/w/d process */
+ rd = inst.reg3_format.rd;
+ opcode = inst.reg3_format.opcode;
+
+ switch (opcode) {
+ case stxb_op:
+ run->mmio.len = 1;
+ *(unsigned char *)data = vcpu->arch.gprs[rd];
+ break;
+ case stxh_op:
+ run->mmio.len = 2;
+ *(unsigned short *)data = vcpu->arch.gprs[rd];
+ break;
+ case stxw_op:
+ run->mmio.len = 4;
+ *(unsigned int *)data = vcpu->arch.gprs[rd];
+ break;
+ case stxd_op:
+ run->mmio.len = 8;
+ *(unsigned long *)data = vcpu->arch.gprs[rd];
+ break;
+ default:
+ ret = EMULATE_FAIL;
+ break;
+ }
+ break;
+ default:
+ ret = EMULATE_FAIL;
+ }
+
+ if (ret == EMULATE_DO_MMIO) {
+ run->mmio.is_write = 1;
+ vcpu->mmio_needed = 1;
+ vcpu->mmio_is_write = 1;
+ } else {
+ vcpu->arch.pc = curr_pc;
+ kvm_err("Write not supported Inst=0x%08x @%lx BadVaddr:%#lx\n",
+ inst.word, vcpu->arch.pc, vcpu->arch.badv);
+ kvm_arch_vcpu_dump_regs(vcpu);
+ /* Rollback PC if emulation was unsuccessful */
+ }
+
+ return ret;
+}
+
+static int kvm_handle_rdwr_fault(struct kvm_vcpu *vcpu, bool write)
+{
+ int ret;
+ larch_inst inst;
+ enum emulation_result er = EMULATE_DONE;
+ struct kvm_run *run = vcpu->run;
+ unsigned long badv = vcpu->arch.badv;
+
+ ret = kvm_handle_mm_fault(vcpu, badv, write);
+ if (ret) {
+ /* Treat as MMIO */
+ inst.word = vcpu->arch.badi;
+ if (write) {
+ er = kvm_emu_mmio_write(vcpu, inst);
+ } else {
+ /* A code fetch fault doesn't count as an MMIO */
+ if (kvm_is_ifetch_fault(&vcpu->arch)) {
+ kvm_queue_exception(vcpu, EXCCODE_ADE, EXSUBCODE_ADEF);
+ return RESUME_GUEST;
+ }
+
+ er = kvm_emu_mmio_read(vcpu, inst);
+ }
+ }
+
+ if (er == EMULATE_DONE) {
+ ret = RESUME_GUEST;
+ } else if (er == EMULATE_DO_MMIO) {
+ run->exit_reason = KVM_EXIT_MMIO;
+ ret = RESUME_HOST;
+ } else {
+ kvm_queue_exception(vcpu, EXCCODE_ADE, EXSUBCODE_ADEM);
+ ret = RESUME_GUEST;
+ }
+
+ return ret;
+}
+
+static int kvm_handle_read_fault(struct kvm_vcpu *vcpu)
+{
+ return kvm_handle_rdwr_fault(vcpu, false);
+}
+
+static int kvm_handle_write_fault(struct kvm_vcpu *vcpu)
+{
+ return kvm_handle_rdwr_fault(vcpu, true);
+}
+
+/**
+ * kvm_handle_fpu_disabled() - Guest used fpu however it is disabled at host
+ * @vcpu: Virtual CPU context.
+ *
+ * Handle when the guest attempts to use fpu which hasn't been allowed
+ * by the root context.
+ */
+static int kvm_handle_fpu_disabled(struct kvm_vcpu *vcpu)
+{
+ struct kvm_run *run = vcpu->run;
+
+ /*
+ * If guest FPU not present, the FPU operation should have been
+ * treated as a reserved instruction!
+ * If FPU already in use, we shouldn't get this at all.
+ */
+ if (WARN_ON(vcpu->arch.aux_inuse & KVM_LARCH_FPU)) {
+ kvm_err("%s internal error\n", __func__);
+ run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+ return RESUME_HOST;
+ }
+
+ kvm_own_fpu(vcpu);
+
+ return RESUME_GUEST;
+}
+
+/*
+ * LoongArch KVM callback handling for unimplemented guest exiting
+ */
+static int kvm_fault_ni(struct kvm_vcpu *vcpu)
+{
+ unsigned int ecode, inst;
+ unsigned long estat, badv;
+
+ /* Fetch the instruction */
+ inst = vcpu->arch.badi;
+ badv = vcpu->arch.badv;
+ estat = vcpu->arch.host_estat;
+ ecode = (estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
+ kvm_err("ECode: %d PC=%#lx Inst=0x%08x BadVaddr=%#lx ESTAT=%#lx\n",
+ ecode, vcpu->arch.pc, inst, badv, read_gcsr_estat());
+ kvm_arch_vcpu_dump_regs(vcpu);
+ kvm_queue_exception(vcpu, EXCCODE_INE, 0);
+
+ return RESUME_GUEST;
+}
+
+static exit_handle_fn kvm_fault_tables[EXCCODE_INT_START] = {
+ [0 ... EXCCODE_INT_START - 1] = kvm_fault_ni,
+ [EXCCODE_TLBI] = kvm_handle_read_fault,
+ [EXCCODE_TLBL] = kvm_handle_read_fault,
+ [EXCCODE_TLBS] = kvm_handle_write_fault,
+ [EXCCODE_TLBM] = kvm_handle_write_fault,
+ [EXCCODE_FPDIS] = kvm_handle_fpu_disabled,
+ [EXCCODE_GSPR] = kvm_handle_gspr,
+};
+
+int kvm_handle_fault(struct kvm_vcpu *vcpu, int fault)
+{
+ return kvm_fault_tables[fault](vcpu);
+}
diff --git a/arch/loongarch/kvm/interrupt.c b/arch/loongarch/kvm/interrupt.c
new file mode 100644
index 000000000000..4c3f22de4b40
--- /dev/null
+++ b/arch/loongarch/kvm/interrupt.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <asm/kvm_csr.h>
+#include <asm/kvm_vcpu.h>
+
+static unsigned int priority_to_irq[EXCCODE_INT_NUM] = {
+ [INT_TI] = CPU_TIMER,
+ [INT_IPI] = CPU_IPI,
+ [INT_SWI0] = CPU_SIP0,
+ [INT_SWI1] = CPU_SIP1,
+ [INT_HWI0] = CPU_IP0,
+ [INT_HWI1] = CPU_IP1,
+ [INT_HWI2] = CPU_IP2,
+ [INT_HWI3] = CPU_IP3,
+ [INT_HWI4] = CPU_IP4,
+ [INT_HWI5] = CPU_IP5,
+ [INT_HWI6] = CPU_IP6,
+ [INT_HWI7] = CPU_IP7,
+};
+
+static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
+{
+ unsigned int irq = 0;
+
+ clear_bit(priority, &vcpu->arch.irq_pending);
+ if (priority < EXCCODE_INT_NUM)
+ irq = priority_to_irq[priority];
+
+ switch (priority) {
+ case INT_TI:
+ case INT_IPI:
+ case INT_SWI0:
+ case INT_SWI1:
+ set_gcsr_estat(irq);
+ break;
+
+ case INT_HWI0 ... INT_HWI7:
+ set_csr_gintc(irq);
+ break;
+
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+static int kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned int priority)
+{
+ unsigned int irq = 0;
+
+ clear_bit(priority, &vcpu->arch.irq_clear);
+ if (priority < EXCCODE_INT_NUM)
+ irq = priority_to_irq[priority];
+
+ switch (priority) {
+ case INT_TI:
+ case INT_IPI:
+ case INT_SWI0:
+ case INT_SWI1:
+ clear_gcsr_estat(irq);
+ break;
+
+ case INT_HWI0 ... INT_HWI7:
+ clear_csr_gintc(irq);
+ break;
+
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+void kvm_deliver_intr(struct kvm_vcpu *vcpu)
+{
+ unsigned int priority;
+ unsigned long *pending = &vcpu->arch.irq_pending;
+ unsigned long *pending_clr = &vcpu->arch.irq_clear;
+
+ if (!(*pending) && !(*pending_clr))
+ return;
+
+ if (*pending_clr) {
+ priority = __ffs(*pending_clr);
+ while (priority <= INT_IPI) {
+ kvm_irq_clear(vcpu, priority);
+ priority = find_next_bit(pending_clr,
+ BITS_PER_BYTE * sizeof(*pending_clr),
+ priority + 1);
+ }
+ }
+
+ if (*pending) {
+ priority = __ffs(*pending);
+ while (priority <= INT_IPI) {
+ kvm_irq_deliver(vcpu, priority);
+ priority = find_next_bit(pending,
+ BITS_PER_BYTE * sizeof(*pending),
+ priority + 1);
+ }
+ }
+}
+
+int kvm_pending_timer(struct kvm_vcpu *vcpu)
+{
+ return test_bit(INT_TI, &vcpu->arch.irq_pending);
+}
+
+/*
+ * Only support illegal instruction or illegal Address Error exception,
+ * Other exceptions are injected by hardware in kvm mode
+ */
+static void _kvm_deliver_exception(struct kvm_vcpu *vcpu,
+ unsigned int code, unsigned int subcode)
+{
+ unsigned long val, vec_size;
+
+ /*
+ * BADV is added for EXCCODE_ADE exception
+ * Use PC register (GVA address) if it is instruction exeception
+ * Else use BADV from host side (GPA address) for data exeception
+ */
+ if (code == EXCCODE_ADE) {
+ if (subcode == EXSUBCODE_ADEF)
+ val = vcpu->arch.pc;
+ else
+ val = vcpu->arch.badv;
+ kvm_write_hw_gcsr(LOONGARCH_CSR_BADV, val);
+ }
+
+ /* Set exception instruction */
+ kvm_write_hw_gcsr(LOONGARCH_CSR_BADI, vcpu->arch.badi);
+
+ /*
+ * Save CRMD in PRMD
+ * Set IRQ disabled and PLV0 with CRMD
+ */
+ val = kvm_read_hw_gcsr(LOONGARCH_CSR_CRMD);
+ kvm_write_hw_gcsr(LOONGARCH_CSR_PRMD, val);
+ val = val & ~(CSR_CRMD_PLV | CSR_CRMD_IE);
+ kvm_write_hw_gcsr(LOONGARCH_CSR_CRMD, val);
+
+ /* Set exception PC address */
+ kvm_write_hw_gcsr(LOONGARCH_CSR_ERA, vcpu->arch.pc);
+
+ /*
+ * Set exception code
+ * Exception and interrupt can be inject at the same time
+ * Hardware will handle exception first and then extern interrupt
+ * Exception code is Ecode in ESTAT[16:21]
+ * Interrupt code in ESTAT[0:12]
+ */
+ val = kvm_read_hw_gcsr(LOONGARCH_CSR_ESTAT);
+ val = (val & ~CSR_ESTAT_EXC) | code;
+ kvm_write_hw_gcsr(LOONGARCH_CSR_ESTAT, val);
+
+ /* Calculate expcetion entry address */
+ val = kvm_read_hw_gcsr(LOONGARCH_CSR_ECFG);
+ vec_size = (val & CSR_ECFG_VS) >> CSR_ECFG_VS_SHIFT;
+ if (vec_size)
+ vec_size = (1 << vec_size) * 4;
+ val = kvm_read_hw_gcsr(LOONGARCH_CSR_EENTRY);
+ vcpu->arch.pc = val + code * vec_size;
+}
+
+void kvm_deliver_exception(struct kvm_vcpu *vcpu)
+{
+ unsigned int code;
+ unsigned long *pending = &vcpu->arch.exception_pending;
+
+ if (*pending) {
+ code = __ffs(*pending);
+ _kvm_deliver_exception(vcpu, code, vcpu->arch.esubcode);
+ *pending = 0;
+ vcpu->arch.esubcode = 0;
+ }
+}
diff --git a/arch/loongarch/kvm/main.c b/arch/loongarch/kvm/main.c
new file mode 100644
index 000000000000..1c1d5199500e
--- /dev/null
+++ b/arch/loongarch/kvm/main.c
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/kvm_host.h>
+#include <asm/cacheflush.h>
+#include <asm/cpufeature.h>
+#include <asm/kvm_csr.h>
+#include "trace.h"
+
+unsigned long vpid_mask;
+struct kvm_world_switch *kvm_loongarch_ops;
+static int gcsr_flag[CSR_MAX_NUMS];
+static struct kvm_context __percpu *vmcs;
+
+int get_gcsr_flag(int csr)
+{
+ if (csr < CSR_MAX_NUMS)
+ return gcsr_flag[csr];
+
+ return INVALID_GCSR;
+}
+
+static inline void set_gcsr_sw_flag(int csr)
+{
+ if (csr < CSR_MAX_NUMS)
+ gcsr_flag[csr] |= SW_GCSR;
+}
+
+static inline void set_gcsr_hw_flag(int csr)
+{
+ if (csr < CSR_MAX_NUMS)
+ gcsr_flag[csr] |= HW_GCSR;
+}
+
+/*
+ * The default value of gcsr_flag[CSR] is 0, and we use this
+ * function to set the flag to 1 (SW_GCSR) or 2 (HW_GCSR) if the
+ * gcsr is software or hardware. It will be used by get/set_gcsr,
+ * if gcsr_flag is HW we should use gcsrrd/gcsrwr to access it,
+ * else use software csr to emulate it.
+ */
+static void kvm_init_gcsr_flag(void)
+{
+ set_gcsr_hw_flag(LOONGARCH_CSR_CRMD);
+ set_gcsr_hw_flag(LOONGARCH_CSR_PRMD);
+ set_gcsr_hw_flag(LOONGARCH_CSR_EUEN);
+ set_gcsr_hw_flag(LOONGARCH_CSR_MISC);
+ set_gcsr_hw_flag(LOONGARCH_CSR_ECFG);
+ set_gcsr_hw_flag(LOONGARCH_CSR_ESTAT);
+ set_gcsr_hw_flag(LOONGARCH_CSR_ERA);
+ set_gcsr_hw_flag(LOONGARCH_CSR_BADV);
+ set_gcsr_hw_flag(LOONGARCH_CSR_BADI);
+ set_gcsr_hw_flag(LOONGARCH_CSR_EENTRY);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TLBIDX);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TLBEHI);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TLBELO0);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TLBELO1);
+ set_gcsr_hw_flag(LOONGARCH_CSR_ASID);
+ set_gcsr_hw_flag(LOONGARCH_CSR_PGDL);
+ set_gcsr_hw_flag(LOONGARCH_CSR_PGDH);
+ set_gcsr_hw_flag(LOONGARCH_CSR_PGD);
+ set_gcsr_hw_flag(LOONGARCH_CSR_PWCTL0);
+ set_gcsr_hw_flag(LOONGARCH_CSR_PWCTL1);
+ set_gcsr_hw_flag(LOONGARCH_CSR_STLBPGSIZE);
+ set_gcsr_hw_flag(LOONGARCH_CSR_RVACFG);
+ set_gcsr_hw_flag(LOONGARCH_CSR_CPUID);
+ set_gcsr_hw_flag(LOONGARCH_CSR_PRCFG1);
+ set_gcsr_hw_flag(LOONGARCH_CSR_PRCFG2);
+ set_gcsr_hw_flag(LOONGARCH_CSR_PRCFG3);
+ set_gcsr_hw_flag(LOONGARCH_CSR_KS0);
+ set_gcsr_hw_flag(LOONGARCH_CSR_KS1);
+ set_gcsr_hw_flag(LOONGARCH_CSR_KS2);
+ set_gcsr_hw_flag(LOONGARCH_CSR_KS3);
+ set_gcsr_hw_flag(LOONGARCH_CSR_KS4);
+ set_gcsr_hw_flag(LOONGARCH_CSR_KS5);
+ set_gcsr_hw_flag(LOONGARCH_CSR_KS6);
+ set_gcsr_hw_flag(LOONGARCH_CSR_KS7);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TMID);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TCFG);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TVAL);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TINTCLR);
+ set_gcsr_hw_flag(LOONGARCH_CSR_CNTC);
+ set_gcsr_hw_flag(LOONGARCH_CSR_LLBCTL);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TLBRENTRY);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TLBRBADV);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TLBRERA);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TLBRSAVE);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TLBRELO0);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TLBRELO1);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TLBREHI);
+ set_gcsr_hw_flag(LOONGARCH_CSR_TLBRPRMD);
+ set_gcsr_hw_flag(LOONGARCH_CSR_DMWIN0);
+ set_gcsr_hw_flag(LOONGARCH_CSR_DMWIN1);
+ set_gcsr_hw_flag(LOONGARCH_CSR_DMWIN2);
+ set_gcsr_hw_flag(LOONGARCH_CSR_DMWIN3);
+
+ set_gcsr_sw_flag(LOONGARCH_CSR_IMPCTL1);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IMPCTL2);
+ set_gcsr_sw_flag(LOONGARCH_CSR_MERRCTL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_MERRINFO1);
+ set_gcsr_sw_flag(LOONGARCH_CSR_MERRINFO2);
+ set_gcsr_sw_flag(LOONGARCH_CSR_MERRENTRY);
+ set_gcsr_sw_flag(LOONGARCH_CSR_MERRERA);
+ set_gcsr_sw_flag(LOONGARCH_CSR_MERRSAVE);
+ set_gcsr_sw_flag(LOONGARCH_CSR_CTAG);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DEBUG);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DERA);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DESAVE);
+
+ set_gcsr_sw_flag(LOONGARCH_CSR_FWPC);
+ set_gcsr_sw_flag(LOONGARCH_CSR_FWPS);
+ set_gcsr_sw_flag(LOONGARCH_CSR_MWPC);
+ set_gcsr_sw_flag(LOONGARCH_CSR_MWPS);
+
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB0ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB0MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB0CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB0ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB1ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB1MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB1CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB1ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB2ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB2MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB2CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB2ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB3ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB3MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB3CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB3ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB4ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB4MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB4CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB4ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB5ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB5MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB5CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB5ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB6ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB6MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB6CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB6ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB7ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB7MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB7CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_DB7ASID);
+
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB0ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB0MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB0CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB0ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB1ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB1MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB1CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB1ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB2ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB2MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB2CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB2ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB3ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB3MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB3CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB3ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB4ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB4MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB4CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB4ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB5ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB5MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB5CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB5ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB6ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB6MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB6CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB6ASID);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB7ADDR);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB7MASK);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB7CTRL);
+ set_gcsr_sw_flag(LOONGARCH_CSR_IB7ASID);
+
+ set_gcsr_sw_flag(LOONGARCH_CSR_PERFCTRL0);
+ set_gcsr_sw_flag(LOONGARCH_CSR_PERFCNTR0);
+ set_gcsr_sw_flag(LOONGARCH_CSR_PERFCTRL1);
+ set_gcsr_sw_flag(LOONGARCH_CSR_PERFCNTR1);
+ set_gcsr_sw_flag(LOONGARCH_CSR_PERFCTRL2);
+ set_gcsr_sw_flag(LOONGARCH_CSR_PERFCNTR2);
+ set_gcsr_sw_flag(LOONGARCH_CSR_PERFCTRL3);
+ set_gcsr_sw_flag(LOONGARCH_CSR_PERFCNTR3);
+}
+
+static void kvm_update_vpid(struct kvm_vcpu *vcpu, int cpu)
+{
+ unsigned long vpid;
+ struct kvm_context *context;
+
+ context = per_cpu_ptr(vcpu->kvm->arch.vmcs, cpu);
+ vpid = context->vpid_cache + 1;
+ if (!(vpid & vpid_mask)) {
+ /* finish round of vpid loop */
+ if (unlikely(!vpid))
+ vpid = vpid_mask + 1;
+
+ ++vpid; /* vpid 0 reserved for root */
+
+ /* start new vpid cycle */
+ kvm_flush_tlb_all();
+ }
+
+ context->vpid_cache = vpid;
+ vcpu->arch.vpid = vpid;
+}
+
+void kvm_check_vpid(struct kvm_vcpu *vcpu)
+{
+ int cpu;
+ bool migrated;
+ unsigned long ver, old, vpid;
+ struct kvm_context *context;
+
+ cpu = smp_processor_id();
+ /*
+ * Are we entering guest context on a different CPU to last time?
+ * If so, the vCPU's guest TLB state on this CPU may be stale.
+ */
+ context = per_cpu_ptr(vcpu->kvm->arch.vmcs, cpu);
+ migrated = (vcpu->cpu != cpu);
+
+ /*
+ * Check if our vpid is of an older version
+ *
+ * We also discard the stored vpid if we've executed on
+ * another CPU, as the guest mappings may have changed without
+ * hypervisor knowledge.
+ */
+ ver = vcpu->arch.vpid & ~vpid_mask;
+ old = context->vpid_cache & ~vpid_mask;
+ if (migrated || (ver != old)) {
+ kvm_update_vpid(vcpu, cpu);
+ trace_kvm_vpid_change(vcpu, vcpu->arch.vpid);
+ vcpu->cpu = cpu;
+ }
+
+ /* Restore GSTAT(0x50).vpid */
+ vpid = (vcpu->arch.vpid & vpid_mask) << CSR_GSTAT_GID_SHIFT;
+ change_csr_gstat(vpid_mask << CSR_GSTAT_GID_SHIFT, vpid);
+}
+
+void kvm_init_vmcs(struct kvm *kvm)
+{
+ kvm->arch.vmcs = vmcs;
+}
+
+long kvm_arch_dev_ioctl(struct file *filp,
+ unsigned int ioctl, unsigned long arg)
+{
+ return -ENOIOCTLCMD;
+}
+
+int kvm_arch_hardware_enable(void)
+{
+ unsigned long env, gcfg = 0;
+
+ env = read_csr_gcfg();
+
+ /* First init gcfg, gstat, gintc, gtlbc. All guest use the same config */
+ write_csr_gcfg(0);
+ write_csr_gstat(0);
+ write_csr_gintc(0);
+ clear_csr_gtlbc(CSR_GTLBC_USETGID | CSR_GTLBC_TOTI);
+
+ /*
+ * Enable virtualization features granting guest direct control of
+ * certain features:
+ * GCI=2: Trap on init or unimplement cache instruction.
+ * TORU=0: Trap on Root Unimplement.
+ * CACTRL=1: Root control cache.
+ * TOP=0: Trap on Previlege.
+ * TOE=0: Trap on Exception.
+ * TIT=0: Trap on Timer.
+ */
+ if (env & CSR_GCFG_GCIP_ALL)
+ gcfg |= CSR_GCFG_GCI_SECURE;
+ if (env & CSR_GCFG_MATC_ROOT)
+ gcfg |= CSR_GCFG_MATC_ROOT;
+
+ gcfg |= CSR_GCFG_TIT;
+ write_csr_gcfg(gcfg);
+
+ kvm_flush_tlb_all();
+
+ /* Enable using TGID */
+ set_csr_gtlbc(CSR_GTLBC_USETGID);
+ kvm_debug("GCFG:%lx GSTAT:%lx GINTC:%lx GTLBC:%lx",
+ read_csr_gcfg(), read_csr_gstat(), read_csr_gintc(), read_csr_gtlbc());
+
+ return 0;
+}
+
+void kvm_arch_hardware_disable(void)
+{
+ write_csr_gcfg(0);
+ write_csr_gstat(0);
+ write_csr_gintc(0);
+ clear_csr_gtlbc(CSR_GTLBC_USETGID | CSR_GTLBC_TOTI);
+
+ /* Flush any remaining guest TLB entries */
+ kvm_flush_tlb_all();
+}
+
+static int kvm_loongarch_env_init(void)
+{
+ int cpu, order;
+ void *addr;
+ struct kvm_context *context;
+
+ vmcs = alloc_percpu(struct kvm_context);
+ if (!vmcs) {
+ pr_err("kvm: failed to allocate percpu kvm_context\n");
+ return -ENOMEM;
+ }
+
+ kvm_loongarch_ops = kzalloc(sizeof(*kvm_loongarch_ops), GFP_KERNEL);
+ if (!kvm_loongarch_ops) {
+ free_percpu(vmcs);
+ vmcs = NULL;
+ return -ENOMEM;
+ }
+
+ /*
+ * PGD register is shared between root kernel and kvm hypervisor.
+ * So world switch entry should be in DMW area rather than TLB area
+ * to avoid page fault reenter.
+ *
+ * In future if hardware pagetable walking is supported, we won't
+ * need to copy world switch code to DMW area.
+ */
+ order = get_order(kvm_exception_size + kvm_enter_guest_size);
+ addr = (void *)__get_free_pages(GFP_KERNEL, order);
+ if (!addr) {
+ free_percpu(vmcs);
+ vmcs = NULL;
+ kfree(kvm_loongarch_ops);
+ kvm_loongarch_ops = NULL;
+ return -ENOMEM;
+ }
+
+ memcpy(addr, kvm_exc_entry, kvm_exception_size);
+ memcpy(addr + kvm_exception_size, kvm_enter_guest, kvm_enter_guest_size);
+ flush_icache_range((unsigned long)addr, (unsigned long)addr + kvm_exception_size + kvm_enter_guest_size);
+ kvm_loongarch_ops->exc_entry = addr;
+ kvm_loongarch_ops->enter_guest = addr + kvm_exception_size;
+ kvm_loongarch_ops->page_order = order;
+
+ vpid_mask = read_csr_gstat();
+ vpid_mask = (vpid_mask & CSR_GSTAT_GIDBIT) >> CSR_GSTAT_GIDBIT_SHIFT;
+ if (vpid_mask)
+ vpid_mask = GENMASK(vpid_mask - 1, 0);
+
+ for_each_possible_cpu(cpu) {
+ context = per_cpu_ptr(vmcs, cpu);
+ context->vpid_cache = vpid_mask + 1;
+ context->last_vcpu = NULL;
+ }
+
+ kvm_init_gcsr_flag();
+
+ return 0;
+}
+
+static void kvm_loongarch_env_exit(void)
+{
+ unsigned long addr;
+
+ if (vmcs)
+ free_percpu(vmcs);
+
+ if (kvm_loongarch_ops) {
+ if (kvm_loongarch_ops->exc_entry) {
+ addr = (unsigned long)kvm_loongarch_ops->exc_entry;
+ free_pages(addr, kvm_loongarch_ops->page_order);
+ }
+ kfree(kvm_loongarch_ops);
+ }
+}
+
+static int kvm_loongarch_init(void)
+{
+ int r;
+
+ if (!cpu_has_lvz) {
+ kvm_info("Hardware virtualization not available\n");
+ return -ENODEV;
+ }
+ r = kvm_loongarch_env_init();
+ if (r)
+ return r;
+
+ return kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE);
+}
+
+static void kvm_loongarch_exit(void)
+{
+ kvm_exit();
+ kvm_loongarch_env_exit();
+}
+
+module_init(kvm_loongarch_init);
+module_exit(kvm_loongarch_exit);
+
+#ifdef MODULE
+static const struct cpu_feature kvm_feature[] = {
+ { .feature = cpu_feature(LOONGARCH_LVZ) },
+ {},
+};
+MODULE_DEVICE_TABLE(cpu, kvm_feature);
+#endif
diff --git a/arch/loongarch/kvm/mmu.c b/arch/loongarch/kvm/mmu.c
new file mode 100644
index 000000000000..80480df5f550
--- /dev/null
+++ b/arch/loongarch/kvm/mmu.c
@@ -0,0 +1,914 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#include <linux/highmem.h>
+#include <linux/hugetlb.h>
+#include <linux/kvm_host.h>
+#include <linux/page-flags.h>
+#include <linux/uaccess.h>
+#include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+#include <asm/kvm_mmu.h>
+
+static inline void kvm_ptw_prepare(struct kvm *kvm, kvm_ptw_ctx *ctx)
+{
+ ctx->level = kvm->arch.root_level;
+ /* pte table */
+ ctx->invalid_ptes = kvm->arch.invalid_ptes;
+ ctx->pte_shifts = kvm->arch.pte_shifts;
+ ctx->pgtable_shift = ctx->pte_shifts[ctx->level];
+ ctx->invalid_entry = ctx->invalid_ptes[ctx->level];
+ ctx->opaque = kvm;
+}
+
+/*
+ * Mark a range of guest physical address space old (all accesses fault) in the
+ * VM's GPA page table to allow detection of commonly used pages.
+ */
+static int kvm_mkold_pte(kvm_pte_t *pte, phys_addr_t addr, kvm_ptw_ctx *ctx)
+{
+ if (kvm_pte_young(*pte)) {
+ *pte = kvm_pte_mkold(*pte);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Mark a range of guest physical address space clean (writes fault) in the VM's
+ * GPA page table to allow dirty page tracking.
+ */
+static int kvm_mkclean_pte(kvm_pte_t *pte, phys_addr_t addr, kvm_ptw_ctx *ctx)
+{
+ gfn_t offset;
+ kvm_pte_t val;
+
+ val = *pte;
+ /*
+ * For kvm_arch_mmu_enable_log_dirty_pt_masked with mask, start and end
+ * may cross hugepage, for first huge page parameter addr is equal to
+ * start, however for the second huge page addr is base address of
+ * this huge page, rather than start or end address
+ */
+ if ((ctx->flag & _KVM_HAS_PGMASK) && !kvm_pte_huge(val)) {
+ offset = (addr >> PAGE_SHIFT) - ctx->gfn;
+ if (!(BIT(offset) & ctx->mask))
+ return 0;
+ }
+
+ /*
+ * Need not split huge page now, just set write-proect pte bit
+ * Split huge page until next write fault
+ */
+ if (kvm_pte_dirty(val)) {
+ *pte = kvm_pte_mkclean(val);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Clear pte entry
+ */
+static int kvm_flush_pte(kvm_pte_t *pte, phys_addr_t addr, kvm_ptw_ctx *ctx)
+{
+ struct kvm *kvm;
+
+ kvm = ctx->opaque;
+ if (ctx->level)
+ kvm->stat.hugepages--;
+ else
+ kvm->stat.pages--;
+
+ *pte = ctx->invalid_entry;
+
+ return 1;
+}
+
+/*
+ * kvm_pgd_alloc() - Allocate and initialise a KVM GPA page directory.
+ *
+ * Allocate a blank KVM GPA page directory (PGD) for representing guest physical
+ * to host physical page mappings.
+ *
+ * Returns: Pointer to new KVM GPA page directory.
+ * NULL on allocation failure.
+ */
+kvm_pte_t *kvm_pgd_alloc(void)
+{
+ kvm_pte_t *pgd;
+
+ pgd = (kvm_pte_t *)__get_free_pages(GFP_KERNEL, 0);
+ if (pgd)
+ pgd_init((void *)pgd);
+
+ return pgd;
+}
+
+static void _kvm_pte_init(void *addr, unsigned long val)
+{
+ unsigned long *p, *end;
+
+ p = (unsigned long *)addr;
+ end = p + PTRS_PER_PTE;
+ do {
+ p[0] = val;
+ p[1] = val;
+ p[2] = val;
+ p[3] = val;
+ p[4] = val;
+ p += 8;
+ p[-3] = val;
+ p[-2] = val;
+ p[-1] = val;
+ } while (p != end);
+}
+
+/*
+ * Caller must hold kvm->mm_lock
+ *
+ * Walk the page tables of kvm to find the PTE corresponding to the
+ * address @addr. If page tables don't exist for @addr, they will be created
+ * from the MMU cache if @cache is not NULL.
+ */
+static kvm_pte_t *kvm_populate_gpa(struct kvm *kvm,
+ struct kvm_mmu_memory_cache *cache,
+ unsigned long addr, int level)
+{
+ kvm_ptw_ctx ctx;
+ kvm_pte_t *entry, *child;
+
+ kvm_ptw_prepare(kvm, &ctx);
+ child = kvm->arch.pgd;
+ while (ctx.level > level) {
+ entry = kvm_pgtable_offset(&ctx, child, addr);
+ if (kvm_pte_none(&ctx, entry)) {
+ if (!cache)
+ return NULL;
+
+ child = kvm_mmu_memory_cache_alloc(cache);
+ _kvm_pte_init(child, ctx.invalid_ptes[ctx.level - 1]);
+ kvm_set_pte(entry, __pa(child));
+ } else if (kvm_pte_huge(*entry)) {
+ return entry;
+ } else
+ child = (kvm_pte_t *)__va(PHYSADDR(*entry));
+ kvm_ptw_enter(&ctx);
+ }
+
+ entry = kvm_pgtable_offset(&ctx, child, addr);
+
+ return entry;
+}
+
+/*
+ * Page walker for VM shadow mmu at last level
+ * The last level is small pte page or huge pmd page
+ */
+static int kvm_ptw_leaf(kvm_pte_t *dir, phys_addr_t addr, phys_addr_t end, kvm_ptw_ctx *ctx)
+{
+ int ret;
+ phys_addr_t next, start, size;
+ struct list_head *list;
+ kvm_pte_t *entry, *child;
+
+ ret = 0;
+ start = addr;
+ child = (kvm_pte_t *)__va(PHYSADDR(*dir));
+ entry = kvm_pgtable_offset(ctx, child, addr);
+ do {
+ next = addr + (0x1UL << ctx->pgtable_shift);
+ if (!kvm_pte_present(ctx, entry))
+ continue;
+
+ ret |= ctx->ops(entry, addr, ctx);
+ } while (entry++, addr = next, addr < end);
+
+ if (kvm_need_flush(ctx)) {
+ size = 0x1UL << (ctx->pgtable_shift + PAGE_SHIFT - 3);
+ if (start + size == end) {
+ list = (struct list_head *)child;
+ list_add_tail(list, &ctx->list);
+ *dir = ctx->invalid_ptes[ctx->level + 1];
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Page walker for VM shadow mmu at page table dir level
+ */
+static int kvm_ptw_dir(kvm_pte_t *dir, phys_addr_t addr, phys_addr_t end, kvm_ptw_ctx *ctx)
+{
+ int ret;
+ phys_addr_t next, start, size;
+ struct list_head *list;
+ kvm_pte_t *entry, *child;
+
+ ret = 0;
+ start = addr;
+ child = (kvm_pte_t *)__va(PHYSADDR(*dir));
+ entry = kvm_pgtable_offset(ctx, child, addr);
+ do {
+ next = kvm_pgtable_addr_end(ctx, addr, end);
+ if (!kvm_pte_present(ctx, entry))
+ continue;
+
+ if (kvm_pte_huge(*entry)) {
+ ret |= ctx->ops(entry, addr, ctx);
+ continue;
+ }
+
+ kvm_ptw_enter(ctx);
+ if (ctx->level == 0)
+ ret |= kvm_ptw_leaf(entry, addr, next, ctx);
+ else
+ ret |= kvm_ptw_dir(entry, addr, next, ctx);
+ kvm_ptw_exit(ctx);
+ } while (entry++, addr = next, addr < end);
+
+ if (kvm_need_flush(ctx)) {
+ size = 0x1UL << (ctx->pgtable_shift + PAGE_SHIFT - 3);
+ if (start + size == end) {
+ list = (struct list_head *)child;
+ list_add_tail(list, &ctx->list);
+ *dir = ctx->invalid_ptes[ctx->level + 1];
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Page walker for VM shadow mmu at page root table
+ */
+static int kvm_ptw_top(kvm_pte_t *dir, phys_addr_t addr, phys_addr_t end, kvm_ptw_ctx *ctx)
+{
+ int ret;
+ phys_addr_t next;
+ kvm_pte_t *entry;
+
+ ret = 0;
+ entry = kvm_pgtable_offset(ctx, dir, addr);
+ do {
+ next = kvm_pgtable_addr_end(ctx, addr, end);
+ if (!kvm_pte_present(ctx, entry))
+ continue;
+
+ kvm_ptw_enter(ctx);
+ ret |= kvm_ptw_dir(entry, addr, next, ctx);
+ kvm_ptw_exit(ctx);
+ } while (entry++, addr = next, addr < end);
+
+ return ret;
+}
+
+/*
+ * kvm_flush_range() - Flush a range of guest physical addresses.
+ * @kvm: KVM pointer.
+ * @start_gfn: Guest frame number of first page in GPA range to flush.
+ * @end_gfn: Guest frame number of last page in GPA range to flush.
+ * @lock: Whether to hold mmu_lock or not
+ *
+ * Flushes a range of GPA mappings from the GPA page tables.
+ */
+static void kvm_flush_range(struct kvm *kvm, gfn_t start_gfn, gfn_t end_gfn, int lock)
+{
+ int ret;
+ kvm_ptw_ctx ctx;
+ struct list_head *pos, *temp;
+
+ ctx.ops = kvm_flush_pte;
+ ctx.flag = _KVM_FLUSH_PGTABLE;
+ kvm_ptw_prepare(kvm, &ctx);
+ INIT_LIST_HEAD(&ctx.list);
+
+ if (lock) {
+ spin_lock(&kvm->mmu_lock);
+ ret = kvm_ptw_top(kvm->arch.pgd, start_gfn << PAGE_SHIFT,
+ end_gfn << PAGE_SHIFT, &ctx);
+ spin_unlock(&kvm->mmu_lock);
+ } else
+ ret = kvm_ptw_top(kvm->arch.pgd, start_gfn << PAGE_SHIFT,
+ end_gfn << PAGE_SHIFT, &ctx);
+
+ /* Flush vpid for each vCPU individually */
+ if (ret)
+ kvm_flush_remote_tlbs(kvm);
+
+ /*
+ * free pte table page after mmu_lock
+ * the pte table page is linked together with ctx.list
+ */
+ list_for_each_safe(pos, temp, &ctx.list) {
+ list_del(pos);
+ free_page((unsigned long)pos);
+ }
+}
+
+/*
+ * kvm_mkclean_gpa_pt() - Make a range of guest physical addresses clean.
+ * @kvm: KVM pointer.
+ * @start_gfn: Guest frame number of first page in GPA range to flush.
+ * @end_gfn: Guest frame number of last page in GPA range to flush.
+ *
+ * Make a range of GPA mappings clean so that guest writes will fault and
+ * trigger dirty page logging.
+ *
+ * The caller must hold the @kvm->mmu_lock spinlock.
+ *
+ * Returns: Whether any GPA mappings were modified, which would require
+ * derived mappings (GVA page tables & TLB enties) to be
+ * invalidated.
+ */
+static int kvm_mkclean_gpa_pt(struct kvm *kvm, gfn_t start_gfn, gfn_t end_gfn)
+{
+ kvm_ptw_ctx ctx;
+
+ ctx.ops = kvm_mkclean_pte;
+ ctx.flag = 0;
+ kvm_ptw_prepare(kvm, &ctx);
+ return kvm_ptw_top(kvm->arch.pgd, start_gfn << PAGE_SHIFT, end_gfn << PAGE_SHIFT, &ctx);
+}
+
+/*
+ * kvm_arch_mmu_enable_log_dirty_pt_masked() - write protect dirty pages
+ * @kvm: The KVM pointer
+ * @slot: The memory slot associated with mask
+ * @gfn_offset: The gfn offset in memory slot
+ * @mask: The mask of dirty pages at offset 'gfn_offset' in this memory
+ * slot to be write protected
+ *
+ * Walks bits set in mask write protects the associated pte's. Caller must
+ * acquire @kvm->mmu_lock.
+ */
+void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm,
+ struct kvm_memory_slot *slot, gfn_t gfn_offset, unsigned long mask)
+{
+ kvm_ptw_ctx ctx;
+ gfn_t base_gfn = slot->base_gfn + gfn_offset;
+ gfn_t start = base_gfn + __ffs(mask);
+ gfn_t end = base_gfn + __fls(mask) + 1;
+
+ ctx.ops = kvm_mkclean_pte;
+ ctx.flag = _KVM_HAS_PGMASK;
+ ctx.mask = mask;
+ ctx.gfn = base_gfn;
+ kvm_ptw_prepare(kvm, &ctx);
+
+ kvm_ptw_top(kvm->arch.pgd, start << PAGE_SHIFT, end << PAGE_SHIFT, &ctx);
+}
+
+void kvm_arch_commit_memory_region(struct kvm *kvm,
+ struct kvm_memory_slot *old,
+ const struct kvm_memory_slot *new,
+ enum kvm_mr_change change)
+{
+ int needs_flush;
+
+ /*
+ * If dirty page logging is enabled, write protect all pages in the slot
+ * ready for dirty logging.
+ *
+ * There is no need to do this in any of the following cases:
+ * CREATE: No dirty mappings will already exist.
+ * MOVE/DELETE: The old mappings will already have been cleaned up by
+ * kvm_arch_flush_shadow_memslot()
+ */
+ if (change == KVM_MR_FLAGS_ONLY &&
+ (!(old->flags & KVM_MEM_LOG_DIRTY_PAGES) &&
+ new->flags & KVM_MEM_LOG_DIRTY_PAGES)) {
+ spin_lock(&kvm->mmu_lock);
+ /* Write protect GPA page table entries */
+ needs_flush = kvm_mkclean_gpa_pt(kvm, new->base_gfn,
+ new->base_gfn + new->npages);
+ spin_unlock(&kvm->mmu_lock);
+ if (needs_flush)
+ kvm_flush_remote_tlbs(kvm);
+ }
+}
+
+void kvm_arch_flush_shadow_all(struct kvm *kvm)
+{
+ kvm_flush_range(kvm, 0, kvm->arch.gpa_size >> PAGE_SHIFT, 0);
+}
+
+void kvm_arch_flush_shadow_memslot(struct kvm *kvm, struct kvm_memory_slot *slot)
+{
+ /*
+ * The slot has been made invalid (ready for moving or deletion), so we
+ * need to ensure that it can no longer be accessed by any guest vCPUs.
+ */
+ kvm_flush_range(kvm, slot->base_gfn, slot->base_gfn + slot->npages, 1);
+}
+
+bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
+{
+ kvm_ptw_ctx ctx;
+
+ ctx.flag = 0;
+ ctx.ops = kvm_flush_pte;
+ kvm_ptw_prepare(kvm, &ctx);
+ INIT_LIST_HEAD(&ctx.list);
+
+ return kvm_ptw_top(kvm->arch.pgd, range->start << PAGE_SHIFT,
+ range->end << PAGE_SHIFT, &ctx);
+}
+
+bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
+{
+ unsigned long prot_bits;
+ kvm_pte_t *ptep;
+ kvm_pfn_t pfn = pte_pfn(range->arg.pte);
+ gpa_t gpa = range->start << PAGE_SHIFT;
+
+ ptep = kvm_populate_gpa(kvm, NULL, gpa, 0);
+ if (!ptep)
+ return false;
+
+ /* Replacing an absent or old page doesn't need flushes */
+ if (!kvm_pte_present(NULL, ptep) || !kvm_pte_young(*ptep)) {
+ kvm_set_pte(ptep, 0);
+ return false;
+ }
+
+ /* Fill new pte if write protected or page migrated */
+ prot_bits = _PAGE_PRESENT | __READABLE;
+ prot_bits |= _CACHE_MASK & pte_val(range->arg.pte);
+
+ /*
+ * Set _PAGE_WRITE or _PAGE_DIRTY iff old and new pte both support
+ * _PAGE_WRITE for map_page_fast if next page write fault
+ * _PAGE_DIRTY since gpa has already recorded as dirty page
+ */
+ prot_bits |= __WRITEABLE & *ptep & pte_val(range->arg.pte);
+ kvm_set_pte(ptep, kvm_pfn_pte(pfn, __pgprot(prot_bits)));
+
+ return true;
+}
+
+bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
+{
+ kvm_ptw_ctx ctx;
+
+ ctx.flag = 0;
+ ctx.ops = kvm_mkold_pte;
+ kvm_ptw_prepare(kvm, &ctx);
+
+ return kvm_ptw_top(kvm->arch.pgd, range->start << PAGE_SHIFT,
+ range->end << PAGE_SHIFT, &ctx);
+}
+
+bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
+{
+ gpa_t gpa = range->start << PAGE_SHIFT;
+ kvm_pte_t *ptep = kvm_populate_gpa(kvm, NULL, gpa, 0);
+
+ if (ptep && kvm_pte_present(NULL, ptep) && kvm_pte_young(*ptep))
+ return true;
+
+ return false;
+}
+
+/*
+ * kvm_map_page_fast() - Fast path GPA fault handler.
+ * @vcpu: vCPU pointer.
+ * @gpa: Guest physical address of fault.
+ * @write: Whether the fault was due to a write.
+ *
+ * Perform fast path GPA fault handling, doing all that can be done without
+ * calling into KVM. This handles marking old pages young (for idle page
+ * tracking), and dirtying of clean pages (for dirty page logging).
+ *
+ * Returns: 0 on success, in which case we can update derived mappings and
+ * resume guest execution.
+ * -EFAULT on failure due to absent GPA mapping or write to
+ * read-only page, in which case KVM must be consulted.
+ */
+static int kvm_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa, bool write)
+{
+ int ret = 0;
+ kvm_pfn_t pfn = 0;
+ kvm_pte_t *ptep, changed, new;
+ gfn_t gfn = gpa >> PAGE_SHIFT;
+ struct kvm *kvm = vcpu->kvm;
+ struct kvm_memory_slot *slot;
+
+ spin_lock(&kvm->mmu_lock);
+
+ /* Fast path - just check GPA page table for an existing entry */
+ ptep = kvm_populate_gpa(kvm, NULL, gpa, 0);
+ if (!ptep || !kvm_pte_present(NULL, ptep)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ /* Track access to pages marked old */
+ new = *ptep;
+ if (!kvm_pte_young(new))
+ new = kvm_pte_mkyoung(new);
+ /* call kvm_set_pfn_accessed() after unlock */
+
+ if (write && !kvm_pte_dirty(new)) {
+ if (!kvm_pte_write(new)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (kvm_pte_huge(new)) {
+ /*
+ * Do not set write permission when dirty logging is
+ * enabled for HugePages
+ */
+ slot = gfn_to_memslot(kvm, gfn);
+ if (kvm_slot_dirty_track_enabled(slot)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ }
+
+ /* Track dirtying of writeable pages */
+ new = kvm_pte_mkdirty(new);
+ }
+
+ changed = new ^ (*ptep);
+ if (changed) {
+ kvm_set_pte(ptep, new);
+ pfn = kvm_pte_pfn(new);
+ }
+ spin_unlock(&kvm->mmu_lock);
+
+ /*
+ * Fixme: pfn may be freed after mmu_lock
+ * kvm_try_get_pfn(pfn)/kvm_release_pfn pair to prevent this?
+ */
+ if (kvm_pte_young(changed))
+ kvm_set_pfn_accessed(pfn);
+
+ if (kvm_pte_dirty(changed)) {
+ mark_page_dirty(kvm, gfn);
+ kvm_set_pfn_dirty(pfn);
+ }
+ return ret;
+out:
+ spin_unlock(&kvm->mmu_lock);
+ return ret;
+}
+
+static bool fault_supports_huge_mapping(struct kvm_memory_slot *memslot,
+ unsigned long hva, unsigned long map_size, bool write)
+{
+ size_t size;
+ gpa_t gpa_start;
+ hva_t uaddr_start, uaddr_end;
+
+ /* Disable dirty logging on HugePages */
+ if (kvm_slot_dirty_track_enabled(memslot) && write)
+ return false;
+
+ size = memslot->npages * PAGE_SIZE;
+ gpa_start = memslot->base_gfn << PAGE_SHIFT;
+ uaddr_start = memslot->userspace_addr;
+ uaddr_end = uaddr_start + size;
+
+ /*
+ * Pages belonging to memslots that don't have the same alignment
+ * within a PMD for userspace and GPA cannot be mapped with stage-2
+ * PMD entries, because we'll end up mapping the wrong pages.
+ *
+ * Consider a layout like the following:
+ *
+ * memslot->userspace_addr:
+ * +-----+--------------------+--------------------+---+
+ * |abcde|fgh Stage-1 block | Stage-1 block tv|xyz|
+ * +-----+--------------------+--------------------+---+
+ *
+ * memslot->base_gfn << PAGE_SIZE:
+ * +---+--------------------+--------------------+-----+
+ * |abc|def Stage-2 block | Stage-2 block |tvxyz|
+ * +---+--------------------+--------------------+-----+
+ *
+ * If we create those stage-2 blocks, we'll end up with this incorrect
+ * mapping:
+ * d -> f
+ * e -> g
+ * f -> h
+ */
+ if ((gpa_start & (map_size - 1)) != (uaddr_start & (map_size - 1)))
+ return false;
+
+ /*
+ * Next, let's make sure we're not trying to map anything not covered
+ * by the memslot. This means we have to prohibit block size mappings
+ * for the beginning and end of a non-block aligned and non-block sized
+ * memory slot (illustrated by the head and tail parts of the
+ * userspace view above containing pages 'abcde' and 'xyz',
+ * respectively).
+ *
+ * Note that it doesn't matter if we do the check using the
+ * userspace_addr or the base_gfn, as both are equally aligned (per
+ * the check above) and equally sized.
+ */
+ return (hva & ~(map_size - 1)) >= uaddr_start &&
+ (hva & ~(map_size - 1)) + map_size <= uaddr_end;
+}
+
+/*
+ * Lookup the mapping level for @gfn in the current mm.
+ *
+ * WARNING! Use of host_pfn_mapping_level() requires the caller and the end
+ * consumer to be tied into KVM's handlers for MMU notifier events!
+ *
+ * There are several ways to safely use this helper:
+ *
+ * - Check mmu_invalidate_retry_hva() after grabbing the mapping level, before
+ * consuming it. In this case, mmu_lock doesn't need to be held during the
+ * lookup, but it does need to be held while checking the MMU notifier.
+ *
+ * - Hold mmu_lock AND ensure there is no in-progress MMU notifier invalidation
+ * event for the hva. This can be done by explicit checking the MMU notifier
+ * or by ensuring that KVM already has a valid mapping that covers the hva.
+ *
+ * - Do not use the result to install new mappings, e.g. use the host mapping
+ * level only to decide whether or not to zap an entry. In this case, it's
+ * not required to hold mmu_lock (though it's highly likely the caller will
+ * want to hold mmu_lock anyways, e.g. to modify SPTEs).
+ *
+ * Note! The lookup can still race with modifications to host page tables, but
+ * the above "rules" ensure KVM will not _consume_ the result of the walk if a
+ * race with the primary MMU occurs.
+ */
+static int host_pfn_mapping_level(struct kvm *kvm, gfn_t gfn,
+ const struct kvm_memory_slot *slot)
+{
+ int level = 0;
+ unsigned long hva;
+ unsigned long flags;
+ pgd_t pgd;
+ p4d_t p4d;
+ pud_t pud;
+ pmd_t pmd;
+
+ /*
+ * Note, using the already-retrieved memslot and __gfn_to_hva_memslot()
+ * is not solely for performance, it's also necessary to avoid the
+ * "writable" check in __gfn_to_hva_many(), which will always fail on
+ * read-only memslots due to gfn_to_hva() assuming writes. Earlier
+ * page fault steps have already verified the guest isn't writing a
+ * read-only memslot.
+ */
+ hva = __gfn_to_hva_memslot(slot, gfn);
+
+ /*
+ * Disable IRQs to prevent concurrent tear down of host page tables,
+ * e.g. if the primary MMU promotes a P*D to a huge page and then frees
+ * the original page table.
+ */
+ local_irq_save(flags);
+
+ /*
+ * Read each entry once. As above, a non-leaf entry can be promoted to
+ * a huge page _during_ this walk. Re-reading the entry could send the
+ * walk into the weeks, e.g. p*d_large() returns false (sees the old
+ * value) and then p*d_offset() walks into the target huge page instead
+ * of the old page table (sees the new value).
+ */
+ pgd = READ_ONCE(*pgd_offset(kvm->mm, hva));
+ if (pgd_none(pgd))
+ goto out;
+
+ p4d = READ_ONCE(*p4d_offset(&pgd, hva));
+ if (p4d_none(p4d) || !p4d_present(p4d))
+ goto out;
+
+ pud = READ_ONCE(*pud_offset(&p4d, hva));
+ if (pud_none(pud) || !pud_present(pud))
+ goto out;
+
+ pmd = READ_ONCE(*pmd_offset(&pud, hva));
+ if (pmd_none(pmd) || !pmd_present(pmd))
+ goto out;
+
+ if (kvm_pte_huge(pmd_val(pmd)))
+ level = 1;
+
+out:
+ local_irq_restore(flags);
+ return level;
+}
+
+/*
+ * Split huge page
+ */
+static kvm_pte_t *kvm_split_huge(struct kvm_vcpu *vcpu, kvm_pte_t *ptep, gfn_t gfn)
+{
+ int i;
+ kvm_pte_t val, *child;
+ struct kvm *kvm = vcpu->kvm;
+ struct kvm_mmu_memory_cache *memcache;
+
+ memcache = &vcpu->arch.mmu_page_cache;
+ child = kvm_mmu_memory_cache_alloc(memcache);
+ val = kvm_pte_mksmall(*ptep);
+ for (i = 0; i < PTRS_PER_PTE; i++) {
+ kvm_set_pte(child + i, val);
+ val += PAGE_SIZE;
+ }
+
+ /* The later kvm_flush_tlb_gpa() will flush hugepage tlb */
+ kvm_set_pte(ptep, __pa(child));
+
+ kvm->stat.hugepages--;
+ kvm->stat.pages += PTRS_PER_PTE;
+
+ return child + (gfn & (PTRS_PER_PTE - 1));
+}
+
+/*
+ * kvm_map_page() - Map a guest physical page.
+ * @vcpu: vCPU pointer.
+ * @gpa: Guest physical address of fault.
+ * @write: Whether the fault was due to a write.
+ *
+ * Handle GPA faults by creating a new GPA mapping (or updating an existing
+ * one).
+ *
+ * This takes care of marking pages young or dirty (idle/dirty page tracking),
+ * asking KVM for the corresponding PFN, and creating a mapping in the GPA page
+ * tables. Derived mappings (GVA page tables and TLBs) must be handled by the
+ * caller.
+ *
+ * Returns: 0 on success
+ * -EFAULT if there is no memory region at @gpa or a write was
+ * attempted to a read-only memory region. This is usually handled
+ * as an MMIO access.
+ */
+static int kvm_map_page(struct kvm_vcpu *vcpu, unsigned long gpa, bool write)
+{
+ bool writeable;
+ int srcu_idx, err, retry_no = 0, level;
+ unsigned long hva, mmu_seq, prot_bits;
+ kvm_pfn_t pfn;
+ kvm_pte_t *ptep, new_pte;
+ gfn_t gfn = gpa >> PAGE_SHIFT;
+ struct kvm *kvm = vcpu->kvm;
+ struct kvm_memory_slot *memslot;
+ struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache;
+
+ /* Try the fast path to handle old / clean pages */
+ srcu_idx = srcu_read_lock(&kvm->srcu);
+ err = kvm_map_page_fast(vcpu, gpa, write);
+ if (!err)
+ goto out;
+
+ memslot = gfn_to_memslot(kvm, gfn);
+ hva = gfn_to_hva_memslot_prot(memslot, gfn, &writeable);
+ if (kvm_is_error_hva(hva) || (write && !writeable)) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ /* We need a minimum of cached pages ready for page table creation */
+ err = kvm_mmu_topup_memory_cache(memcache, KVM_MMU_CACHE_MIN_PAGES);
+ if (err)
+ goto out;
+
+retry:
+ /*
+ * Used to check for invalidations in progress, of the pfn that is
+ * returned by pfn_to_pfn_prot below.
+ */
+ mmu_seq = kvm->mmu_invalidate_seq;
+ /*
+ * Ensure the read of mmu_invalidate_seq isn't reordered with PTE reads in
+ * gfn_to_pfn_prot() (which calls get_user_pages()), so that we don't
+ * risk the page we get a reference to getting unmapped before we have a
+ * chance to grab the mmu_lock without mmu_invalidate_retry() noticing.
+ *
+ * This smp_rmb() pairs with the effective smp_wmb() of the combination
+ * of the pte_unmap_unlock() after the PTE is zapped, and the
+ * spin_lock() in kvm_mmu_invalidate_invalidate_<page|range_end>() before
+ * mmu_invalidate_seq is incremented.
+ */
+ smp_rmb();
+
+ /* Slow path - ask KVM core whether we can access this GPA */
+ pfn = gfn_to_pfn_prot(kvm, gfn, write, &writeable);
+ if (is_error_noslot_pfn(pfn)) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ /* Check if an invalidation has taken place since we got pfn */
+ spin_lock(&kvm->mmu_lock);
+ if (mmu_invalidate_retry_hva(kvm, mmu_seq, hva)) {
+ /*
+ * This can happen when mappings are changed asynchronously, but
+ * also synchronously if a COW is triggered by
+ * gfn_to_pfn_prot().
+ */
+ spin_unlock(&kvm->mmu_lock);
+ kvm_release_pfn_clean(pfn);
+ if (retry_no > 100) {
+ retry_no = 0;
+ schedule();
+ }
+ retry_no++;
+ goto retry;
+ }
+
+ /*
+ * For emulated devices such virtio device, actual cache attribute is
+ * determined by physical machine.
+ * For pass through physical device, it should be uncachable
+ */
+ prot_bits = _PAGE_PRESENT | __READABLE;
+ if (pfn_valid(pfn))
+ prot_bits |= _CACHE_CC;
+ else
+ prot_bits |= _CACHE_SUC;
+
+ if (writeable) {
+ prot_bits |= _PAGE_WRITE;
+ if (write)
+ prot_bits |= __WRITEABLE;
+ }
+
+ /* Disable dirty logging on HugePages */
+ level = 0;
+ if (!fault_supports_huge_mapping(memslot, hva, PMD_SIZE, write)) {
+ level = 0;
+ } else {
+ level = host_pfn_mapping_level(kvm, gfn, memslot);
+ if (level == 1) {
+ gfn = gfn & ~(PTRS_PER_PTE - 1);
+ pfn = pfn & ~(PTRS_PER_PTE - 1);
+ }
+ }
+
+ /* Ensure page tables are allocated */
+ ptep = kvm_populate_gpa(kvm, memcache, gpa, level);
+ new_pte = kvm_pfn_pte(pfn, __pgprot(prot_bits));
+ if (level == 1) {
+ new_pte = kvm_pte_mkhuge(new_pte);
+ /*
+ * previous pmd entry is invalid_pte_table
+ * there is invalid tlb with small page
+ * need flush these invalid tlbs for current vcpu
+ */
+ kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+ ++kvm->stat.hugepages;
+ } else if (kvm_pte_huge(*ptep) && write)
+ ptep = kvm_split_huge(vcpu, ptep, gfn);
+ else
+ ++kvm->stat.pages;
+ kvm_set_pte(ptep, new_pte);
+ spin_unlock(&kvm->mmu_lock);
+
+ if (prot_bits & _PAGE_DIRTY) {
+ mark_page_dirty_in_slot(kvm, memslot, gfn);
+ kvm_set_pfn_dirty(pfn);
+ }
+
+ kvm_set_pfn_accessed(pfn);
+ kvm_release_pfn_clean(pfn);
+out:
+ srcu_read_unlock(&kvm->srcu, srcu_idx);
+ return err;
+}
+
+int kvm_handle_mm_fault(struct kvm_vcpu *vcpu, unsigned long gpa, bool write)
+{
+ int ret;
+
+ ret = kvm_map_page(vcpu, gpa, write);
+ if (ret)
+ return ret;
+
+ /* Invalidate this entry in the TLB */
+ kvm_flush_tlb_gpa(vcpu, gpa);
+
+ return 0;
+}
+
+void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
+{
+}
+
+int kvm_arch_prepare_memory_region(struct kvm *kvm, const struct kvm_memory_slot *old,
+ struct kvm_memory_slot *new, enum kvm_mr_change change)
+{
+ return 0;
+}
+
+void kvm_arch_flush_remote_tlbs_memslot(struct kvm *kvm,
+ const struct kvm_memory_slot *memslot)
+{
+ kvm_flush_remote_tlbs(kvm);
+}
diff --git a/arch/loongarch/kvm/switch.S b/arch/loongarch/kvm/switch.S
new file mode 100644
index 000000000000..0ed9040307b7
--- /dev/null
+++ b/arch/loongarch/kvm/switch.S
@@ -0,0 +1,250 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/loongarch.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#define HGPR_OFFSET(x) (PT_R0 + 8*x)
+#define GGPR_OFFSET(x) (KVM_ARCH_GGPR + 8*x)
+
+.macro kvm_save_host_gpr base
+ .irp n,1,2,3,22,23,24,25,26,27,28,29,30,31
+ st.d $r\n, \base, HGPR_OFFSET(\n)
+ .endr
+.endm
+
+.macro kvm_restore_host_gpr base
+ .irp n,1,2,3,22,23,24,25,26,27,28,29,30,31
+ ld.d $r\n, \base, HGPR_OFFSET(\n)
+ .endr
+.endm
+
+/*
+ * Save and restore all GPRs except base register,
+ * and default value of base register is a2.
+ */
+.macro kvm_save_guest_gprs base
+ .irp n,1,2,3,4,5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+ st.d $r\n, \base, GGPR_OFFSET(\n)
+ .endr
+.endm
+
+.macro kvm_restore_guest_gprs base
+ .irp n,1,2,3,4,5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+ ld.d $r\n, \base, GGPR_OFFSET(\n)
+ .endr
+.endm
+
+/*
+ * Prepare switch to guest, save host regs and restore guest regs.
+ * a2: kvm_vcpu_arch, don't touch it until 'ertn'
+ * t0, t1: temp register
+ */
+.macro kvm_switch_to_guest
+ /* Set host ECFG.VS=0, all exceptions share one exception entry */
+ csrrd t0, LOONGARCH_CSR_ECFG
+ bstrins.w t0, zero, CSR_ECFG_VS_SHIFT_END, CSR_ECFG_VS_SHIFT
+ csrwr t0, LOONGARCH_CSR_ECFG
+
+ /* Load up the new EENTRY */
+ ld.d t0, a2, KVM_ARCH_GEENTRY
+ csrwr t0, LOONGARCH_CSR_EENTRY
+
+ /* Set Guest ERA */
+ ld.d t0, a2, KVM_ARCH_GPC
+ csrwr t0, LOONGARCH_CSR_ERA
+
+ /* Save host PGDL */
+ csrrd t0, LOONGARCH_CSR_PGDL
+ st.d t0, a2, KVM_ARCH_HPGD
+
+ /* Switch to kvm */
+ ld.d t1, a2, KVM_VCPU_KVM - KVM_VCPU_ARCH
+
+ /* Load guest PGDL */
+ li.w t0, KVM_GPGD
+ ldx.d t0, t1, t0
+ csrwr t0, LOONGARCH_CSR_PGDL
+
+ /* Mix GID and RID */
+ csrrd t1, LOONGARCH_CSR_GSTAT
+ bstrpick.w t1, t1, CSR_GSTAT_GID_SHIFT_END, CSR_GSTAT_GID_SHIFT
+ csrrd t0, LOONGARCH_CSR_GTLBC
+ bstrins.w t0, t1, CSR_GTLBC_TGID_SHIFT_END, CSR_GTLBC_TGID_SHIFT
+ csrwr t0, LOONGARCH_CSR_GTLBC
+
+ /*
+ * Enable intr in root mode with future ertn so that host interrupt
+ * can be responsed during VM runs
+ * Guest CRMD comes from separate GCSR_CRMD register
+ */
+ ori t0, zero, CSR_PRMD_PIE
+ csrxchg t0, t0, LOONGARCH_CSR_PRMD
+
+ /* Set PVM bit to setup ertn to guest context */
+ ori t0, zero, CSR_GSTAT_PVM
+ csrxchg t0, t0, LOONGARCH_CSR_GSTAT
+
+ /* Load Guest GPRs */
+ kvm_restore_guest_gprs a2
+ /* Load KVM_ARCH register */
+ ld.d a2, a2, (KVM_ARCH_GGPR + 8 * REG_A2)
+
+ ertn /* Switch to guest: GSTAT.PGM = 1, ERRCTL.ISERR = 0, TLBRPRMD.ISTLBR = 0 */
+.endm
+
+ /*
+ * Exception entry for general exception from guest mode
+ * - IRQ is disabled
+ * - kernel privilege in root mode
+ * - page mode keep unchanged from previous PRMD in root mode
+ * - Fixme: tlb exception cannot happen since registers relative with TLB
+ * - is still in guest mode, such as pgd table/vmid registers etc,
+ * - will fix with hw page walk enabled in future
+ * load kvm_vcpu from reserved CSR KVM_VCPU_KS, and save a2 to KVM_TEMP_KS
+ */
+ .text
+ .cfi_sections .debug_frame
+SYM_CODE_START(kvm_exc_entry)
+ csrwr a2, KVM_TEMP_KS
+ csrrd a2, KVM_VCPU_KS
+ addi.d a2, a2, KVM_VCPU_ARCH
+
+ /* After save GPRs, free to use any GPR */
+ kvm_save_guest_gprs a2
+ /* Save guest A2 */
+ csrrd t0, KVM_TEMP_KS
+ st.d t0, a2, (KVM_ARCH_GGPR + 8 * REG_A2)
+
+ /* A2 is kvm_vcpu_arch, A1 is free to use */
+ csrrd s1, KVM_VCPU_KS
+ ld.d s0, s1, KVM_VCPU_RUN
+
+ csrrd t0, LOONGARCH_CSR_ESTAT
+ st.d t0, a2, KVM_ARCH_HESTAT
+ csrrd t0, LOONGARCH_CSR_ERA
+ st.d t0, a2, KVM_ARCH_GPC
+ csrrd t0, LOONGARCH_CSR_BADV
+ st.d t0, a2, KVM_ARCH_HBADV
+ csrrd t0, LOONGARCH_CSR_BADI
+ st.d t0, a2, KVM_ARCH_HBADI
+
+ /* Restore host ECFG.VS */
+ csrrd t0, LOONGARCH_CSR_ECFG
+ ld.d t1, a2, KVM_ARCH_HECFG
+ or t0, t0, t1
+ csrwr t0, LOONGARCH_CSR_ECFG
+
+ /* Restore host EENTRY */
+ ld.d t0, a2, KVM_ARCH_HEENTRY
+ csrwr t0, LOONGARCH_CSR_EENTRY
+
+ /* Restore host pgd table */
+ ld.d t0, a2, KVM_ARCH_HPGD
+ csrwr t0, LOONGARCH_CSR_PGDL
+
+ /*
+ * Disable PGM bit to enter root mode by default with next ertn
+ */
+ ori t0, zero, CSR_GSTAT_PVM
+ csrxchg zero, t0, LOONGARCH_CSR_GSTAT
+
+ /*
+ * Clear GTLBC.TGID field
+ * 0: for root tlb update in future tlb instr
+ * others: for guest tlb update like gpa to hpa in future tlb instr
+ */
+ csrrd t0, LOONGARCH_CSR_GTLBC
+ bstrins.w t0, zero, CSR_GTLBC_TGID_SHIFT_END, CSR_GTLBC_TGID_SHIFT
+ csrwr t0, LOONGARCH_CSR_GTLBC
+ ld.d tp, a2, KVM_ARCH_HTP
+ ld.d sp, a2, KVM_ARCH_HSP
+ /* restore per cpu register */
+ ld.d u0, a2, KVM_ARCH_HPERCPU
+ addi.d sp, sp, -PT_SIZE
+
+ /* Prepare handle exception */
+ or a0, s0, zero
+ or a1, s1, zero
+ ld.d t8, a2, KVM_ARCH_HANDLE_EXIT
+ jirl ra, t8, 0
+
+ or a2, s1, zero
+ addi.d a2, a2, KVM_VCPU_ARCH
+
+ /* Resume host when ret <= 0 */
+ blez a0, ret_to_host
+
+ /*
+ * Return to guest
+ * Save per cpu register again, maybe switched to another cpu
+ */
+ st.d u0, a2, KVM_ARCH_HPERCPU
+
+ /* Save kvm_vcpu to kscratch */
+ csrwr s1, KVM_VCPU_KS
+ kvm_switch_to_guest
+
+ret_to_host:
+ ld.d a2, a2, KVM_ARCH_HSP
+ addi.d a2, a2, -PT_SIZE
+ kvm_restore_host_gpr a2
+ jr ra
+
+SYM_INNER_LABEL(kvm_exc_entry_end, SYM_L_LOCAL)
+SYM_CODE_END(kvm_exc_entry)
+
+/*
+ * int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu)
+ *
+ * @register_param:
+ * a0: kvm_run* run
+ * a1: kvm_vcpu* vcpu
+ */
+SYM_FUNC_START(kvm_enter_guest)
+ /* Allocate space in stack bottom */
+ addi.d a2, sp, -PT_SIZE
+ /* Save host GPRs */
+ kvm_save_host_gpr a2
+
+ /* Save host CRMD, PRMD to stack */
+ csrrd a3, LOONGARCH_CSR_CRMD
+ st.d a3, a2, PT_CRMD
+ csrrd a3, LOONGARCH_CSR_PRMD
+ st.d a3, a2, PT_PRMD
+
+ addi.d a2, a1, KVM_VCPU_ARCH
+ st.d sp, a2, KVM_ARCH_HSP
+ st.d tp, a2, KVM_ARCH_HTP
+ /* Save per cpu register */
+ st.d u0, a2, KVM_ARCH_HPERCPU
+
+ /* Save kvm_vcpu to kscratch */
+ csrwr a1, KVM_VCPU_KS
+ kvm_switch_to_guest
+SYM_INNER_LABEL(kvm_enter_guest_end, SYM_L_LOCAL)
+SYM_FUNC_END(kvm_enter_guest)
+
+SYM_FUNC_START(kvm_save_fpu)
+ fpu_save_csr a0 t1
+ fpu_save_double a0 t1
+ fpu_save_cc a0 t1 t2
+ jr ra
+SYM_FUNC_END(kvm_save_fpu)
+
+SYM_FUNC_START(kvm_restore_fpu)
+ fpu_restore_double a0 t1
+ fpu_restore_csr a0 t1 t2
+ fpu_restore_cc a0 t1 t2
+ jr ra
+SYM_FUNC_END(kvm_restore_fpu)
+
+ .section ".rodata"
+SYM_DATA(kvm_exception_size, .quad kvm_exc_entry_end - kvm_exc_entry)
+SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - kvm_enter_guest)
diff --git a/arch/loongarch/kvm/timer.c b/arch/loongarch/kvm/timer.c
new file mode 100644
index 000000000000..284bf553fefe
--- /dev/null
+++ b/arch/loongarch/kvm/timer.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#include <linux/kvm_host.h>
+#include <asm/kvm_csr.h>
+#include <asm/kvm_vcpu.h>
+
+/*
+ * ktime_to_tick() - Scale ktime_t to timer tick value.
+ */
+static inline u64 ktime_to_tick(struct kvm_vcpu *vcpu, ktime_t now)
+{
+ u64 delta;
+
+ delta = ktime_to_ns(now);
+ return div_u64(delta * vcpu->arch.timer_mhz, MNSEC_PER_SEC);
+}
+
+static inline u64 tick_to_ns(struct kvm_vcpu *vcpu, u64 tick)
+{
+ return div_u64(tick * MNSEC_PER_SEC, vcpu->arch.timer_mhz);
+}
+
+/*
+ * Push timer forward on timeout.
+ * Handle an hrtimer event by push the hrtimer forward a period.
+ */
+static enum hrtimer_restart kvm_count_timeout(struct kvm_vcpu *vcpu)
+{
+ unsigned long cfg, period;
+
+ /* Add periodic tick to current expire time */
+ cfg = kvm_read_sw_gcsr(vcpu->arch.csr, LOONGARCH_CSR_TCFG);
+ if (cfg & CSR_TCFG_PERIOD) {
+ period = tick_to_ns(vcpu, cfg & CSR_TCFG_VAL);
+ hrtimer_add_expires_ns(&vcpu->arch.swtimer, period);
+ return HRTIMER_RESTART;
+ } else
+ return HRTIMER_NORESTART;
+}
+
+/* Low level hrtimer wake routine */
+enum hrtimer_restart kvm_swtimer_wakeup(struct hrtimer *timer)
+{
+ struct kvm_vcpu *vcpu;
+
+ vcpu = container_of(timer, struct kvm_vcpu, arch.swtimer);
+ kvm_queue_irq(vcpu, INT_TI);
+ rcuwait_wake_up(&vcpu->wait);
+
+ return kvm_count_timeout(vcpu);
+}
+
+/*
+ * Initialise the timer to the specified frequency, zero it
+ */
+void kvm_init_timer(struct kvm_vcpu *vcpu, unsigned long timer_hz)
+{
+ vcpu->arch.timer_mhz = timer_hz >> 20;
+
+ /* Starting at 0 */
+ kvm_write_sw_gcsr(vcpu->arch.csr, LOONGARCH_CSR_TVAL, 0);
+}
+
+/*
+ * Restore hard timer state and enable guest to access timer registers
+ * without trap, should be called with irq disabled
+ */
+void kvm_acquire_timer(struct kvm_vcpu *vcpu)
+{
+ unsigned long cfg;
+
+ cfg = read_csr_gcfg();
+ if (!(cfg & CSR_GCFG_TIT))
+ return;
+
+ /* Enable guest access to hard timer */
+ write_csr_gcfg(cfg & ~CSR_GCFG_TIT);
+
+ /*
+ * Freeze the soft-timer and sync the guest stable timer with it. We do
+ * this with interrupts disabled to avoid latency.
+ */
+ hrtimer_cancel(&vcpu->arch.swtimer);
+}
+
+/*
+ * Restore soft timer state from saved context.
+ */
+void kvm_restore_timer(struct kvm_vcpu *vcpu)
+{
+ unsigned long cfg, delta, period;
+ ktime_t expire, now;
+ struct loongarch_csrs *csr = vcpu->arch.csr;
+
+ /*
+ * Set guest stable timer cfg csr
+ */
+ cfg = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_TCFG);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ESTAT);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TCFG);
+ if (!(cfg & CSR_TCFG_EN)) {
+ /* Guest timer is disabled, just restore timer registers */
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TVAL);
+ return;
+ }
+
+ /*
+ * Set remainder tick value if not expired
+ */
+ now = ktime_get();
+ expire = vcpu->arch.expire;
+ if (ktime_before(now, expire))
+ delta = ktime_to_tick(vcpu, ktime_sub(expire, now));
+ else {
+ if (cfg & CSR_TCFG_PERIOD) {
+ period = cfg & CSR_TCFG_VAL;
+ delta = ktime_to_tick(vcpu, ktime_sub(now, expire));
+ delta = period - (delta % period);
+ } else
+ delta = 0;
+ /*
+ * Inject timer here though sw timer should inject timer
+ * interrupt async already, since sw timer may be cancelled
+ * during injecting intr async in function kvm_acquire_timer
+ */
+ kvm_queue_irq(vcpu, INT_TI);
+ }
+
+ write_gcsr_timertick(delta);
+}
+
+/*
+ * Save guest timer state and switch to software emulation of guest
+ * timer. The hard timer must already be in use, so preemption should be
+ * disabled.
+ */
+static void _kvm_save_timer(struct kvm_vcpu *vcpu)
+{
+ unsigned long ticks, delta;
+ ktime_t expire;
+ struct loongarch_csrs *csr = vcpu->arch.csr;
+
+ ticks = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_TVAL);
+ delta = tick_to_ns(vcpu, ticks);
+ expire = ktime_add_ns(ktime_get(), delta);
+ vcpu->arch.expire = expire;
+ if (ticks) {
+ /*
+ * Update hrtimer to use new timeout
+ * HRTIMER_MODE_PINNED is suggested since vcpu may run in
+ * the same physical cpu in next time
+ */
+ hrtimer_cancel(&vcpu->arch.swtimer);
+ hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED);
+ } else
+ /*
+ * Inject timer interrupt so that hall polling can dectect and exit
+ */
+ kvm_queue_irq(vcpu, INT_TI);
+}
+
+/*
+ * Save guest timer state and switch to soft guest timer if hard timer was in
+ * use.
+ */
+void kvm_save_timer(struct kvm_vcpu *vcpu)
+{
+ unsigned long cfg;
+ struct loongarch_csrs *csr = vcpu->arch.csr;
+
+ preempt_disable();
+ cfg = read_csr_gcfg();
+ if (!(cfg & CSR_GCFG_TIT)) {
+ /* Disable guest use of hard timer */
+ write_csr_gcfg(cfg | CSR_GCFG_TIT);
+
+ /* Save hard timer state */
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TCFG);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TVAL);
+ if (kvm_read_sw_gcsr(csr, LOONGARCH_CSR_TCFG) & CSR_TCFG_EN)
+ _kvm_save_timer(vcpu);
+ }
+
+ /* Save timer-related state to vCPU context */
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ESTAT);
+ preempt_enable();
+}
+
+void kvm_reset_timer(struct kvm_vcpu *vcpu)
+{
+ write_gcsr_timercfg(0);
+ kvm_write_sw_gcsr(vcpu->arch.csr, LOONGARCH_CSR_TCFG, 0);
+ hrtimer_cancel(&vcpu->arch.swtimer);
+}
diff --git a/arch/loongarch/kvm/tlb.c b/arch/loongarch/kvm/tlb.c
new file mode 100644
index 000000000000..02535df6b51f
--- /dev/null
+++ b/arch/loongarch/kvm/tlb.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#include <linux/kvm_host.h>
+#include <asm/tlb.h>
+#include <asm/kvm_csr.h>
+
+/*
+ * kvm_flush_tlb_all() - Flush all root TLB entries for guests.
+ *
+ * Invalidate all entries including GVA-->GPA and GPA-->HPA mappings.
+ */
+void kvm_flush_tlb_all(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ invtlb_all(INVTLB_ALLGID, 0, 0);
+ local_irq_restore(flags);
+}
+
+void kvm_flush_tlb_gpa(struct kvm_vcpu *vcpu, unsigned long gpa)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ gpa &= (PAGE_MASK << 1);
+ invtlb(INVTLB_GID_ADDR, read_csr_gstat() & CSR_GSTAT_GID, gpa);
+ local_irq_restore(flags);
+}
diff --git a/arch/loongarch/kvm/trace.h b/arch/loongarch/kvm/trace.h
new file mode 100644
index 000000000000..a1e35d655418
--- /dev/null
+++ b/arch/loongarch/kvm/trace.h
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_KVM_H
+
+#include <linux/tracepoint.h>
+#include <asm/kvm_csr.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kvm
+
+/*
+ * Tracepoints for VM enters
+ */
+DECLARE_EVENT_CLASS(kvm_transition,
+ TP_PROTO(struct kvm_vcpu *vcpu),
+ TP_ARGS(vcpu),
+ TP_STRUCT__entry(
+ __field(unsigned long, pc)
+ ),
+
+ TP_fast_assign(
+ __entry->pc = vcpu->arch.pc;
+ ),
+
+ TP_printk("PC: 0x%08lx", __entry->pc)
+);
+
+DEFINE_EVENT(kvm_transition, kvm_enter,
+ TP_PROTO(struct kvm_vcpu *vcpu),
+ TP_ARGS(vcpu));
+
+DEFINE_EVENT(kvm_transition, kvm_reenter,
+ TP_PROTO(struct kvm_vcpu *vcpu),
+ TP_ARGS(vcpu));
+
+DEFINE_EVENT(kvm_transition, kvm_out,
+ TP_PROTO(struct kvm_vcpu *vcpu),
+ TP_ARGS(vcpu));
+
+/* Further exit reasons */
+#define KVM_TRACE_EXIT_IDLE 64
+#define KVM_TRACE_EXIT_CACHE 65
+
+/* Tracepoints for VM exits */
+#define kvm_trace_symbol_exit_types \
+ { KVM_TRACE_EXIT_IDLE, "IDLE" }, \
+ { KVM_TRACE_EXIT_CACHE, "CACHE" }
+
+DECLARE_EVENT_CLASS(kvm_exit,
+ TP_PROTO(struct kvm_vcpu *vcpu, unsigned int reason),
+ TP_ARGS(vcpu, reason),
+ TP_STRUCT__entry(
+ __field(unsigned long, pc)
+ __field(unsigned int, reason)
+ ),
+
+ TP_fast_assign(
+ __entry->pc = vcpu->arch.pc;
+ __entry->reason = reason;
+ ),
+
+ TP_printk("[%s]PC: 0x%08lx",
+ __print_symbolic(__entry->reason,
+ kvm_trace_symbol_exit_types),
+ __entry->pc)
+);
+
+DEFINE_EVENT(kvm_exit, kvm_exit_idle,
+ TP_PROTO(struct kvm_vcpu *vcpu, unsigned int reason),
+ TP_ARGS(vcpu, reason));
+
+DEFINE_EVENT(kvm_exit, kvm_exit_cache,
+ TP_PROTO(struct kvm_vcpu *vcpu, unsigned int reason),
+ TP_ARGS(vcpu, reason));
+
+DEFINE_EVENT(kvm_exit, kvm_exit,
+ TP_PROTO(struct kvm_vcpu *vcpu, unsigned int reason),
+ TP_ARGS(vcpu, reason));
+
+TRACE_EVENT(kvm_exit_gspr,
+ TP_PROTO(struct kvm_vcpu *vcpu, unsigned int inst_word),
+ TP_ARGS(vcpu, inst_word),
+ TP_STRUCT__entry(
+ __field(unsigned int, inst_word)
+ ),
+
+ TP_fast_assign(
+ __entry->inst_word = inst_word;
+ ),
+
+ TP_printk("Inst word: 0x%08x", __entry->inst_word)
+);
+
+#define KVM_TRACE_AUX_SAVE 0
+#define KVM_TRACE_AUX_RESTORE 1
+#define KVM_TRACE_AUX_ENABLE 2
+#define KVM_TRACE_AUX_DISABLE 3
+#define KVM_TRACE_AUX_DISCARD 4
+
+#define KVM_TRACE_AUX_FPU 1
+
+#define kvm_trace_symbol_aux_op \
+ { KVM_TRACE_AUX_SAVE, "save" }, \
+ { KVM_TRACE_AUX_RESTORE, "restore" }, \
+ { KVM_TRACE_AUX_ENABLE, "enable" }, \
+ { KVM_TRACE_AUX_DISABLE, "disable" }, \
+ { KVM_TRACE_AUX_DISCARD, "discard" }
+
+#define kvm_trace_symbol_aux_state \
+ { KVM_TRACE_AUX_FPU, "FPU" }
+
+TRACE_EVENT(kvm_aux,
+ TP_PROTO(struct kvm_vcpu *vcpu, unsigned int op,
+ unsigned int state),
+ TP_ARGS(vcpu, op, state),
+ TP_STRUCT__entry(
+ __field(unsigned long, pc)
+ __field(u8, op)
+ __field(u8, state)
+ ),
+
+ TP_fast_assign(
+ __entry->pc = vcpu->arch.pc;
+ __entry->op = op;
+ __entry->state = state;
+ ),
+
+ TP_printk("%s %s PC: 0x%08lx",
+ __print_symbolic(__entry->op,
+ kvm_trace_symbol_aux_op),
+ __print_symbolic(__entry->state,
+ kvm_trace_symbol_aux_state),
+ __entry->pc)
+);
+
+TRACE_EVENT(kvm_vpid_change,
+ TP_PROTO(struct kvm_vcpu *vcpu, unsigned long vpid),
+ TP_ARGS(vcpu, vpid),
+ TP_STRUCT__entry(
+ __field(unsigned long, vpid)
+ ),
+
+ TP_fast_assign(
+ __entry->vpid = vpid;
+ ),
+
+ TP_printk("VPID: 0x%08lx", __entry->vpid)
+);
+
+#endif /* _TRACE_KVM_H */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH ../../arch/loongarch/kvm
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
new file mode 100644
index 000000000000..73d0c2b9c1a5
--- /dev/null
+++ b/arch/loongarch/kvm/vcpu.c
@@ -0,0 +1,939 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/entry-kvm.h>
+#include <asm/fpu.h>
+#include <asm/loongarch.h>
+#include <asm/setup.h>
+#include <asm/time.h>
+
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ KVM_GENERIC_VCPU_STATS(),
+ STATS_DESC_COUNTER(VCPU, int_exits),
+ STATS_DESC_COUNTER(VCPU, idle_exits),
+ STATS_DESC_COUNTER(VCPU, cpucfg_exits),
+ STATS_DESC_COUNTER(VCPU, signal_exits),
+};
+
+const struct kvm_stats_header kvm_vcpu_stats_header = {
+ .name_size = KVM_STATS_NAME_SIZE,
+ .num_desc = ARRAY_SIZE(kvm_vcpu_stats_desc),
+ .id_offset = sizeof(struct kvm_stats_header),
+ .desc_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE,
+ .data_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE +
+ sizeof(kvm_vcpu_stats_desc),
+};
+
+/*
+ * kvm_check_requests - check and handle pending vCPU requests
+ *
+ * Return: RESUME_GUEST if we should enter the guest
+ * RESUME_HOST if we should exit to userspace
+ */
+static int kvm_check_requests(struct kvm_vcpu *vcpu)
+{
+ if (!kvm_request_pending(vcpu))
+ return RESUME_GUEST;
+
+ if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu))
+ vcpu->arch.vpid = 0; /* Drop vpid for this vCPU */
+
+ if (kvm_dirty_ring_check_request(vcpu))
+ return RESUME_HOST;
+
+ return RESUME_GUEST;
+}
+
+/*
+ * Check and handle pending signal and vCPU requests etc
+ * Run with irq enabled and preempt enabled
+ *
+ * Return: RESUME_GUEST if we should enter the guest
+ * RESUME_HOST if we should exit to userspace
+ * < 0 if we should exit to userspace, where the return value
+ * indicates an error
+ */
+static int kvm_enter_guest_check(struct kvm_vcpu *vcpu)
+{
+ int ret;
+
+ /*
+ * Check conditions before entering the guest
+ */
+ ret = xfer_to_guest_mode_handle_work(vcpu);
+ if (ret < 0)
+ return ret;
+
+ ret = kvm_check_requests(vcpu);
+
+ return ret;
+}
+
+/*
+ * Called with irq enabled
+ *
+ * Return: RESUME_GUEST if we should enter the guest, and irq disabled
+ * Others if we should exit to userspace
+ */
+static int kvm_pre_enter_guest(struct kvm_vcpu *vcpu)
+{
+ int ret;
+
+ do {
+ ret = kvm_enter_guest_check(vcpu);
+ if (ret != RESUME_GUEST)
+ break;
+
+ /*
+ * Handle vcpu timer, interrupts, check requests and
+ * check vmid before vcpu enter guest
+ */
+ local_irq_disable();
+ kvm_acquire_timer(vcpu);
+ kvm_deliver_intr(vcpu);
+ kvm_deliver_exception(vcpu);
+ /* Make sure the vcpu mode has been written */
+ smp_store_mb(vcpu->mode, IN_GUEST_MODE);
+ kvm_check_vpid(vcpu);
+ vcpu->arch.host_eentry = csr_read64(LOONGARCH_CSR_EENTRY);
+ /* Clear KVM_LARCH_SWCSR_LATEST as CSR will change when enter guest */
+ vcpu->arch.aux_inuse &= ~KVM_LARCH_SWCSR_LATEST;
+
+ if (kvm_request_pending(vcpu) || xfer_to_guest_mode_work_pending()) {
+ /* make sure the vcpu mode has been written */
+ smp_store_mb(vcpu->mode, OUTSIDE_GUEST_MODE);
+ local_irq_enable();
+ ret = -EAGAIN;
+ }
+ } while (ret != RESUME_GUEST);
+
+ return ret;
+}
+
+/*
+ * Return 1 for resume guest and "<= 0" for resume host.
+ */
+static int kvm_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+ int ret = RESUME_GUEST;
+ unsigned long estat = vcpu->arch.host_estat;
+ u32 intr = estat & 0x1fff; /* Ignore NMI */
+ u32 ecode = (estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
+
+ vcpu->mode = OUTSIDE_GUEST_MODE;
+
+ /* Set a default exit reason */
+ run->exit_reason = KVM_EXIT_UNKNOWN;
+
+ guest_timing_exit_irqoff();
+ guest_state_exit_irqoff();
+ local_irq_enable();
+
+ trace_kvm_exit(vcpu, ecode);
+ if (ecode) {
+ ret = kvm_handle_fault(vcpu, ecode);
+ } else {
+ WARN(!intr, "vm exiting with suspicious irq\n");
+ ++vcpu->stat.int_exits;
+ }
+
+ if (ret == RESUME_GUEST)
+ ret = kvm_pre_enter_guest(vcpu);
+
+ if (ret != RESUME_GUEST) {
+ local_irq_disable();
+ return ret;
+ }
+
+ guest_timing_enter_irqoff();
+ guest_state_enter_irqoff();
+ trace_kvm_reenter(vcpu);
+
+ return RESUME_GUEST;
+}
+
+int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
+{
+ return !!(vcpu->arch.irq_pending) &&
+ vcpu->arch.mp_state.mp_state == KVM_MP_STATE_RUNNABLE;
+}
+
+int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
+{
+ return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
+}
+
+bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
+{
+ return false;
+}
+
+vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+ return VM_FAULT_SIGBUS;
+}
+
+int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
+ struct kvm_translation *tr)
+{
+ return -EINVAL;
+}
+
+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+ return kvm_pending_timer(vcpu) ||
+ kvm_read_hw_gcsr(LOONGARCH_CSR_ESTAT) & (1 << INT_TI);
+}
+
+int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu)
+{
+ int i;
+
+ kvm_debug("vCPU Register Dump:\n");
+ kvm_debug("\tPC = 0x%08lx\n", vcpu->arch.pc);
+ kvm_debug("\tExceptions: %08lx\n", vcpu->arch.irq_pending);
+
+ for (i = 0; i < 32; i += 4) {
+ kvm_debug("\tGPR%02d: %08lx %08lx %08lx %08lx\n", i,
+ vcpu->arch.gprs[i], vcpu->arch.gprs[i + 1],
+ vcpu->arch.gprs[i + 2], vcpu->arch.gprs[i + 3]);
+ }
+
+ kvm_debug("\tCRMD: 0x%08lx, ESTAT: 0x%08lx\n",
+ kvm_read_hw_gcsr(LOONGARCH_CSR_CRMD),
+ kvm_read_hw_gcsr(LOONGARCH_CSR_ESTAT));
+
+ kvm_debug("\tERA: 0x%08lx\n", kvm_read_hw_gcsr(LOONGARCH_CSR_ERA));
+
+ return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
+ struct kvm_mp_state *mp_state)
+{
+ *mp_state = vcpu->arch.mp_state;
+
+ return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
+ struct kvm_mp_state *mp_state)
+{
+ int ret = 0;
+
+ switch (mp_state->mp_state) {
+ case KVM_MP_STATE_RUNNABLE:
+ vcpu->arch.mp_state = *mp_state;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
+ struct kvm_guest_debug *dbg)
+{
+ return -EINVAL;
+}
+
+/**
+ * kvm_migrate_count() - Migrate timer.
+ * @vcpu: Virtual CPU.
+ *
+ * Migrate hrtimer to the current CPU by cancelling and restarting it
+ * if the hrtimer is active.
+ *
+ * Must be called when the vCPU is migrated to a different CPU, so that
+ * the timer can interrupt the guest at the new CPU, and the timer irq can
+ * be delivered to the vCPU.
+ */
+static void kvm_migrate_count(struct kvm_vcpu *vcpu)
+{
+ if (hrtimer_cancel(&vcpu->arch.swtimer))
+ hrtimer_restart(&vcpu->arch.swtimer);
+}
+
+static int _kvm_getcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 *val)
+{
+ unsigned long gintc;
+ struct loongarch_csrs *csr = vcpu->arch.csr;
+
+ if (get_gcsr_flag(id) & INVALID_GCSR)
+ return -EINVAL;
+
+ if (id == LOONGARCH_CSR_ESTAT) {
+ /* ESTAT IP0~IP7 get from GINTC */
+ gintc = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_GINTC) & 0xff;
+ *val = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_ESTAT) | (gintc << 2);
+ return 0;
+ }
+
+ /*
+ * Get software CSR state since software state is consistent
+ * with hardware for synchronous ioctl
+ */
+ *val = kvm_read_sw_gcsr(csr, id);
+
+ return 0;
+}
+
+static int _kvm_setcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 val)
+{
+ int ret = 0, gintc;
+ struct loongarch_csrs *csr = vcpu->arch.csr;
+
+ if (get_gcsr_flag(id) & INVALID_GCSR)
+ return -EINVAL;
+
+ if (id == LOONGARCH_CSR_ESTAT) {
+ /* ESTAT IP0~IP7 inject through GINTC */
+ gintc = (val >> 2) & 0xff;
+ kvm_set_sw_gcsr(csr, LOONGARCH_CSR_GINTC, gintc);
+
+ gintc = val & ~(0xffUL << 2);
+ kvm_set_sw_gcsr(csr, LOONGARCH_CSR_ESTAT, gintc);
+
+ return ret;
+ }
+
+ kvm_write_sw_gcsr(csr, id, val);
+
+ return ret;
+}
+
+static int kvm_get_one_reg(struct kvm_vcpu *vcpu,
+ const struct kvm_one_reg *reg, u64 *v)
+{
+ int id, ret = 0;
+ u64 type = reg->id & KVM_REG_LOONGARCH_MASK;
+
+ switch (type) {
+ case KVM_REG_LOONGARCH_CSR:
+ id = KVM_GET_IOC_CSR_IDX(reg->id);
+ ret = _kvm_getcsr(vcpu, id, v);
+ break;
+ case KVM_REG_LOONGARCH_CPUCFG:
+ id = KVM_GET_IOC_CPUCFG_IDX(reg->id);
+ if (id >= 0 && id < KVM_MAX_CPUCFG_REGS)
+ *v = vcpu->arch.cpucfg[id];
+ else
+ ret = -EINVAL;
+ break;
+ case KVM_REG_LOONGARCH_KVM:
+ switch (reg->id) {
+ case KVM_REG_LOONGARCH_COUNTER:
+ *v = drdtime() + vcpu->kvm->arch.time_offset;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int kvm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+ int ret = 0;
+ u64 v, size = reg->id & KVM_REG_SIZE_MASK;
+
+ switch (size) {
+ case KVM_REG_SIZE_U64:
+ ret = kvm_get_one_reg(vcpu, reg, &v);
+ if (ret)
+ return ret;
+ ret = put_user(v, (u64 __user *)(long)reg->addr);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int kvm_set_one_reg(struct kvm_vcpu *vcpu,
+ const struct kvm_one_reg *reg, u64 v)
+{
+ int id, ret = 0;
+ u64 type = reg->id & KVM_REG_LOONGARCH_MASK;
+
+ switch (type) {
+ case KVM_REG_LOONGARCH_CSR:
+ id = KVM_GET_IOC_CSR_IDX(reg->id);
+ ret = _kvm_setcsr(vcpu, id, v);
+ break;
+ case KVM_REG_LOONGARCH_CPUCFG:
+ id = KVM_GET_IOC_CPUCFG_IDX(reg->id);
+ if (id >= 0 && id < KVM_MAX_CPUCFG_REGS)
+ vcpu->arch.cpucfg[id] = (u32)v;
+ else
+ ret = -EINVAL;
+ break;
+ case KVM_REG_LOONGARCH_KVM:
+ switch (reg->id) {
+ case KVM_REG_LOONGARCH_COUNTER:
+ /*
+ * gftoffset is relative with board, not vcpu
+ * only set for the first time for smp system
+ */
+ if (vcpu->vcpu_id == 0)
+ vcpu->kvm->arch.time_offset = (signed long)(v - drdtime());
+ break;
+ case KVM_REG_LOONGARCH_VCPU_RESET:
+ kvm_reset_timer(vcpu);
+ memset(&vcpu->arch.irq_pending, 0, sizeof(vcpu->arch.irq_pending));
+ memset(&vcpu->arch.irq_clear, 0, sizeof(vcpu->arch.irq_clear));
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int kvm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+ int ret = 0;
+ u64 v, size = reg->id & KVM_REG_SIZE_MASK;
+
+ switch (size) {
+ case KVM_REG_SIZE_U64:
+ ret = get_user(v, (u64 __user *)(long)reg->addr);
+ if (ret)
+ return ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return kvm_set_one_reg(vcpu, reg, v);
+}
+
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
+{
+ return -ENOIOCTLCMD;
+}
+
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
+{
+ return -ENOIOCTLCMD;
+}
+
+int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(vcpu->arch.gprs); i++)
+ regs->gpr[i] = vcpu->arch.gprs[i];
+
+ regs->pc = vcpu->arch.pc;
+
+ return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+ int i;
+
+ for (i = 1; i < ARRAY_SIZE(vcpu->arch.gprs); i++)
+ vcpu->arch.gprs[i] = regs->gpr[i];
+
+ vcpu->arch.gprs[0] = 0; /* zero is special, and cannot be set. */
+ vcpu->arch.pc = regs->pc;
+
+ return 0;
+}
+
+static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
+ struct kvm_enable_cap *cap)
+{
+ /* FPU is enabled by default, will support LSX/LASX later. */
+ return -EINVAL;
+}
+
+long kvm_arch_vcpu_ioctl(struct file *filp,
+ unsigned int ioctl, unsigned long arg)
+{
+ long r;
+ void __user *argp = (void __user *)arg;
+ struct kvm_vcpu *vcpu = filp->private_data;
+
+ /*
+ * Only software CSR should be modified
+ *
+ * If any hardware CSR register is modified, vcpu_load/vcpu_put pair
+ * should be used. Since CSR registers owns by this vcpu, if switch
+ * to other vcpus, other vcpus need reload CSR registers.
+ *
+ * If software CSR is modified, bit KVM_LARCH_HWCSR_USABLE should
+ * be clear in vcpu->arch.aux_inuse, and vcpu_load will check
+ * aux_inuse flag and reload CSR registers form software.
+ */
+
+ switch (ioctl) {
+ case KVM_SET_ONE_REG:
+ case KVM_GET_ONE_REG: {
+ struct kvm_one_reg reg;
+
+ r = -EFAULT;
+ if (copy_from_user(&reg, argp, sizeof(reg)))
+ break;
+ if (ioctl == KVM_SET_ONE_REG) {
+ r = kvm_set_reg(vcpu, &reg);
+ vcpu->arch.aux_inuse &= ~KVM_LARCH_HWCSR_USABLE;
+ } else
+ r = kvm_get_reg(vcpu, &reg);
+ break;
+ }
+ case KVM_ENABLE_CAP: {
+ struct kvm_enable_cap cap;
+
+ r = -EFAULT;
+ if (copy_from_user(&cap, argp, sizeof(cap)))
+ break;
+ r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
+ break;
+ }
+ default:
+ r = -ENOIOCTLCMD;
+ break;
+ }
+
+ return r;
+}
+
+int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+ int i = 0;
+
+ fpu->fcc = vcpu->arch.fpu.fcc;
+ fpu->fcsr = vcpu->arch.fpu.fcsr;
+ for (i = 0; i < NUM_FPU_REGS; i++)
+ memcpy(&fpu->fpr[i], &vcpu->arch.fpu.fpr[i], FPU_REG_WIDTH / 64);
+
+ return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+ int i = 0;
+
+ vcpu->arch.fpu.fcc = fpu->fcc;
+ vcpu->arch.fpu.fcsr = fpu->fcsr;
+ for (i = 0; i < NUM_FPU_REGS; i++)
+ memcpy(&vcpu->arch.fpu.fpr[i], &fpu->fpr[i], FPU_REG_WIDTH / 64);
+
+ return 0;
+}
+
+/* Enable FPU and restore context */
+void kvm_own_fpu(struct kvm_vcpu *vcpu)
+{
+ preempt_disable();
+
+ /* Enable FPU */
+ set_csr_euen(CSR_EUEN_FPEN);
+
+ kvm_restore_fpu(&vcpu->arch.fpu);
+ vcpu->arch.aux_inuse |= KVM_LARCH_FPU;
+ trace_kvm_aux(vcpu, KVM_TRACE_AUX_RESTORE, KVM_TRACE_AUX_FPU);
+
+ preempt_enable();
+}
+
+/* Save context and disable FPU */
+void kvm_lose_fpu(struct kvm_vcpu *vcpu)
+{
+ preempt_disable();
+
+ if (vcpu->arch.aux_inuse & KVM_LARCH_FPU) {
+ kvm_save_fpu(&vcpu->arch.fpu);
+ vcpu->arch.aux_inuse &= ~KVM_LARCH_FPU;
+ trace_kvm_aux(vcpu, KVM_TRACE_AUX_SAVE, KVM_TRACE_AUX_FPU);
+
+ /* Disable FPU */
+ clear_csr_euen(CSR_EUEN_FPEN);
+ }
+
+ preempt_enable();
+}
+
+int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
+{
+ int intr = (int)irq->irq;
+
+ if (intr > 0)
+ kvm_queue_irq(vcpu, intr);
+ else if (intr < 0)
+ kvm_dequeue_irq(vcpu, -intr);
+ else {
+ kvm_err("%s: invalid interrupt ioctl %d\n", __func__, irq->irq);
+ return -EINVAL;
+ }
+
+ kvm_vcpu_kick(vcpu);
+
+ return 0;
+}
+
+long kvm_arch_vcpu_async_ioctl(struct file *filp,
+ unsigned int ioctl, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ struct kvm_vcpu *vcpu = filp->private_data;
+
+ if (ioctl == KVM_INTERRUPT) {
+ struct kvm_interrupt irq;
+
+ if (copy_from_user(&irq, argp, sizeof(irq)))
+ return -EFAULT;
+
+ kvm_debug("[%d] %s: irq: %d\n", vcpu->vcpu_id, __func__, irq.irq);
+
+ return kvm_vcpu_ioctl_interrupt(vcpu, &irq);
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
+{
+ return 0;
+}
+
+int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
+{
+ unsigned long timer_hz;
+ struct loongarch_csrs *csr;
+
+ vcpu->arch.vpid = 0;
+
+ hrtimer_init(&vcpu->arch.swtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
+ vcpu->arch.swtimer.function = kvm_swtimer_wakeup;
+
+ vcpu->arch.handle_exit = kvm_handle_exit;
+ vcpu->arch.guest_eentry = (unsigned long)kvm_loongarch_ops->exc_entry;
+ vcpu->arch.csr = kzalloc(sizeof(struct loongarch_csrs), GFP_KERNEL);
+ if (!vcpu->arch.csr)
+ return -ENOMEM;
+
+ /*
+ * All kvm exceptions share one exception entry, and host <-> guest
+ * switch also switch ECFG.VS field, keep host ECFG.VS info here.
+ */
+ vcpu->arch.host_ecfg = (read_csr_ecfg() & CSR_ECFG_VS);
+
+ /* Init */
+ vcpu->arch.last_sched_cpu = -1;
+
+ /*
+ * Initialize guest register state to valid architectural reset state.
+ */
+ timer_hz = calc_const_freq();
+ kvm_init_timer(vcpu, timer_hz);
+
+ /* Set Initialize mode for guest */
+ csr = vcpu->arch.csr;
+ kvm_write_sw_gcsr(csr, LOONGARCH_CSR_CRMD, CSR_CRMD_DA);
+
+ /* Set cpuid */
+ kvm_write_sw_gcsr(csr, LOONGARCH_CSR_TMID, vcpu->vcpu_id);
+
+ /* Start with no pending virtual guest interrupts */
+ csr->csrs[LOONGARCH_CSR_GINTC] = 0;
+
+ return 0;
+}
+
+void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+{
+}
+
+void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+ int cpu;
+ struct kvm_context *context;
+
+ hrtimer_cancel(&vcpu->arch.swtimer);
+ kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
+ kfree(vcpu->arch.csr);
+
+ /*
+ * If the vCPU is freed and reused as another vCPU, we don't want the
+ * matching pointer wrongly hanging around in last_vcpu.
+ */
+ for_each_possible_cpu(cpu) {
+ context = per_cpu_ptr(vcpu->kvm->arch.vmcs, cpu);
+ if (context->last_vcpu == vcpu)
+ context->last_vcpu = NULL;
+ }
+}
+
+static int _kvm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+ bool migrated;
+ struct kvm_context *context;
+ struct loongarch_csrs *csr = vcpu->arch.csr;
+
+ /*
+ * Have we migrated to a different CPU?
+ * If so, any old guest TLB state may be stale.
+ */
+ migrated = (vcpu->arch.last_sched_cpu != cpu);
+
+ /*
+ * Was this the last vCPU to run on this CPU?
+ * If not, any old guest state from this vCPU will have been clobbered.
+ */
+ context = per_cpu_ptr(vcpu->kvm->arch.vmcs, cpu);
+ if (migrated || (context->last_vcpu != vcpu))
+ vcpu->arch.aux_inuse &= ~KVM_LARCH_HWCSR_USABLE;
+ context->last_vcpu = vcpu;
+
+ /* Restore timer state regardless */
+ kvm_restore_timer(vcpu);
+
+ /* Control guest page CCA attribute */
+ change_csr_gcfg(CSR_GCFG_MATC_MASK, CSR_GCFG_MATC_ROOT);
+
+ /* Don't bother restoring registers multiple times unless necessary */
+ if (vcpu->arch.aux_inuse & KVM_LARCH_HWCSR_USABLE)
+ return 0;
+
+ write_csr_gcntc((ulong)vcpu->kvm->arch.time_offset);
+
+ /* Restore guest CSR registers */
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_CRMD);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PRMD);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_EUEN);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_MISC);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ECFG);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ERA);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_BADV);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_BADI);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_EENTRY);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TLBIDX);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TLBEHI);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TLBELO0);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TLBELO1);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ASID);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PGDL);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PGDH);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PWCTL0);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PWCTL1);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_STLBPGSIZE);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_RVACFG);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_CPUID);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_KS0);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_KS1);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_KS2);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_KS3);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_KS4);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_KS5);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_KS6);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_KS7);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TMID);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_CNTC);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TLBRENTRY);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TLBRBADV);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TLBRERA);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TLBRSAVE);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TLBRELO0);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TLBRELO1);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TLBREHI);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_TLBRPRMD);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN0);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN1);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
+ kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_LLBCTL);
+
+ /* Restore Root.GINTC from unused Guest.GINTC register */
+ write_csr_gintc(csr->csrs[LOONGARCH_CSR_GINTC]);
+
+ /*
+ * We should clear linked load bit to break interrupted atomics. This
+ * prevents a SC on the next vCPU from succeeding by matching a LL on
+ * the previous vCPU.
+ */
+ if (vcpu->kvm->created_vcpus > 1)
+ set_gcsr_llbctl(CSR_LLBCTL_WCLLB);
+
+ vcpu->arch.aux_inuse |= KVM_LARCH_HWCSR_USABLE;
+
+ return 0;
+}
+
+void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (vcpu->arch.last_sched_cpu != cpu) {
+ kvm_debug("[%d->%d]KVM vCPU[%d] switch\n",
+ vcpu->arch.last_sched_cpu, cpu, vcpu->vcpu_id);
+ /*
+ * Migrate the timer interrupt to the current CPU so that it
+ * always interrupts the guest and synchronously triggers a
+ * guest timer interrupt.
+ */
+ kvm_migrate_count(vcpu);
+ }
+
+ /* Restore guest state to registers */
+ _kvm_vcpu_load(vcpu, cpu);
+ local_irq_restore(flags);
+}
+
+static int _kvm_vcpu_put(struct kvm_vcpu *vcpu, int cpu)
+{
+ struct loongarch_csrs *csr = vcpu->arch.csr;
+
+ kvm_lose_fpu(vcpu);
+
+ /*
+ * Update CSR state from hardware if software CSR state is stale,
+ * most CSR registers are kept unchanged during process context
+ * switch except CSR registers like remaining timer tick value and
+ * injected interrupt state.
+ */
+ if (vcpu->arch.aux_inuse & KVM_LARCH_SWCSR_LATEST)
+ goto out;
+
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_CRMD);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_PRMD);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_EUEN);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_MISC);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ECFG);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ERA);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_BADV);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_BADI);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_EENTRY);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TLBIDX);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TLBEHI);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TLBELO0);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TLBELO1);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ASID);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_PGDL);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_PGDH);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_PWCTL0);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_PWCTL1);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_STLBPGSIZE);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_RVACFG);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_CPUID);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_PRCFG1);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_PRCFG2);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_PRCFG3);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_KS0);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_KS1);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_KS2);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_KS3);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_KS4);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_KS5);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_KS6);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_KS7);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TMID);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_CNTC);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_LLBCTL);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TLBRENTRY);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TLBRBADV);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TLBRERA);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TLBRSAVE);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TLBRELO0);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TLBRELO1);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TLBREHI);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_TLBRPRMD);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN0);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN1);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
+ kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
+
+ vcpu->arch.aux_inuse |= KVM_LARCH_SWCSR_LATEST;
+
+out:
+ kvm_save_timer(vcpu);
+ /* Save Root.GINTC into unused Guest.GINTC register */
+ csr->csrs[LOONGARCH_CSR_GINTC] = read_csr_gintc();
+
+ return 0;
+}
+
+void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+{
+ int cpu;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ cpu = smp_processor_id();
+ vcpu->arch.last_sched_cpu = cpu;
+
+ /* Save guest state in registers */
+ _kvm_vcpu_put(vcpu, cpu);
+ local_irq_restore(flags);
+}
+
+int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
+{
+ int r = -EINTR;
+ struct kvm_run *run = vcpu->run;
+
+ if (vcpu->mmio_needed) {
+ if (!vcpu->mmio_is_write)
+ kvm_complete_mmio_read(vcpu, run);
+ vcpu->mmio_needed = 0;
+ }
+
+ if (run->exit_reason == KVM_EXIT_LOONGARCH_IOCSR) {
+ if (!run->iocsr_io.is_write)
+ kvm_complete_iocsr_read(vcpu, run);
+ }
+
+ if (run->immediate_exit)
+ return r;
+
+ /* Clear exit_reason */
+ run->exit_reason = KVM_EXIT_UNKNOWN;
+ lose_fpu(1);
+ vcpu_load(vcpu);
+ kvm_sigset_activate(vcpu);
+ r = kvm_pre_enter_guest(vcpu);
+ if (r != RESUME_GUEST)
+ goto out;
+
+ guest_timing_enter_irqoff();
+ guest_state_enter_irqoff();
+ trace_kvm_enter(vcpu);
+ r = kvm_loongarch_ops->enter_guest(run, vcpu);
+
+ trace_kvm_out(vcpu);
+ /*
+ * Guest exit is already recorded at kvm_handle_exit()
+ * return value must not be RESUME_GUEST
+ */
+ local_irq_enable();
+out:
+ kvm_sigset_deactivate(vcpu);
+ vcpu_put(vcpu);
+
+ return r;
+}
diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c
new file mode 100644
index 000000000000..0a37f6fa8f2d
--- /dev/null
+++ b/arch/loongarch/kvm/vm.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#include <linux/kvm_host.h>
+#include <asm/kvm_mmu.h>
+
+const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+ KVM_GENERIC_VM_STATS(),
+ STATS_DESC_ICOUNTER(VM, pages),
+ STATS_DESC_ICOUNTER(VM, hugepages),
+};
+
+const struct kvm_stats_header kvm_vm_stats_header = {
+ .name_size = KVM_STATS_NAME_SIZE,
+ .num_desc = ARRAY_SIZE(kvm_vm_stats_desc),
+ .id_offset = sizeof(struct kvm_stats_header),
+ .desc_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE,
+ .data_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE +
+ sizeof(kvm_vm_stats_desc),
+};
+
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
+{
+ int i;
+
+ /* Allocate page table to map GPA -> RPA */
+ kvm->arch.pgd = kvm_pgd_alloc();
+ if (!kvm->arch.pgd)
+ return -ENOMEM;
+
+ kvm_init_vmcs(kvm);
+ kvm->arch.gpa_size = BIT(cpu_vabits - 1);
+ kvm->arch.root_level = CONFIG_PGTABLE_LEVELS - 1;
+ kvm->arch.invalid_ptes[0] = 0;
+ kvm->arch.invalid_ptes[1] = (unsigned long)invalid_pte_table;
+#if CONFIG_PGTABLE_LEVELS > 2
+ kvm->arch.invalid_ptes[2] = (unsigned long)invalid_pmd_table;
+#endif
+#if CONFIG_PGTABLE_LEVELS > 3
+ kvm->arch.invalid_ptes[3] = (unsigned long)invalid_pud_table;
+#endif
+ for (i = 0; i <= kvm->arch.root_level; i++)
+ kvm->arch.pte_shifts[i] = PAGE_SHIFT + i * (PAGE_SHIFT - 3);
+
+ return 0;
+}
+
+void kvm_arch_destroy_vm(struct kvm *kvm)
+{
+ kvm_destroy_vcpus(kvm);
+ free_page((unsigned long)kvm->arch.pgd);
+ kvm->arch.pgd = NULL;
+}
+
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
+{
+ int r;
+
+ switch (ext) {
+ case KVM_CAP_ONE_REG:
+ case KVM_CAP_ENABLE_CAP:
+ case KVM_CAP_READONLY_MEM:
+ case KVM_CAP_SYNC_MMU:
+ case KVM_CAP_IMMEDIATE_EXIT:
+ case KVM_CAP_IOEVENTFD:
+ case KVM_CAP_MP_STATE:
+ r = 1;
+ break;
+ case KVM_CAP_NR_VCPUS:
+ r = num_online_cpus();
+ break;
+ case KVM_CAP_MAX_VCPUS:
+ r = KVM_MAX_VCPUS;
+ break;
+ case KVM_CAP_MAX_VCPU_ID:
+ r = KVM_MAX_VCPU_IDS;
+ break;
+ case KVM_CAP_NR_MEMSLOTS:
+ r = KVM_USER_MEM_SLOTS;
+ break;
+ default:
+ r = 0;
+ break;
+ }
+
+ return r;
+}
+
+int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
+{
+ return -ENOIOCTLCMD;
+}
diff --git a/arch/loongarch/mm/init.c b/arch/loongarch/mm/init.c
index f3fe8c06ba4d..4dd53427f657 100644
--- a/arch/loongarch/mm/init.c
+++ b/arch/loongarch/mm/init.c
@@ -43,11 +43,11 @@ void copy_user_highpage(struct page *to, struct page *from,
{
void *vfrom, *vto;
- vto = kmap_atomic(to);
- vfrom = kmap_atomic(from);
+ vfrom = kmap_local_page(from);
+ vto = kmap_local_page(to);
copy_page(vto, vfrom);
- kunmap_atomic(vfrom);
- kunmap_atomic(vto);
+ kunmap_local(vfrom);
+ kunmap_local(vto);
/* Make sure this page is cleared on other CPU's too before using it */
smp_wmb();
}
@@ -240,6 +240,7 @@ pgd_t swapper_pg_dir[_PTRS_PER_PGD] __section(".bss..swapper_pg_dir");
pgd_t invalid_pg_dir[_PTRS_PER_PGD] __page_aligned_bss;
#ifndef __PAGETABLE_PUD_FOLDED
pud_t invalid_pud_table[PTRS_PER_PUD] __page_aligned_bss;
+EXPORT_SYMBOL(invalid_pud_table);
#endif
#ifndef __PAGETABLE_PMD_FOLDED
pmd_t invalid_pmd_table[PTRS_PER_PMD] __page_aligned_bss;
diff --git a/arch/loongarch/mm/pgtable.c b/arch/loongarch/mm/pgtable.c
index 71d0539e2d0b..2aae72e63871 100644
--- a/arch/loongarch/mm/pgtable.c
+++ b/arch/loongarch/mm/pgtable.c
@@ -13,13 +13,13 @@ struct page *dmw_virt_to_page(unsigned long kaddr)
{
return pfn_to_page(virt_to_pfn(kaddr));
}
-EXPORT_SYMBOL_GPL(dmw_virt_to_page);
+EXPORT_SYMBOL(dmw_virt_to_page);
struct page *tlb_virt_to_page(unsigned long kaddr)
{
return pfn_to_page(pte_pfn(*virt_to_kpte(kaddr)));
}
-EXPORT_SYMBOL_GPL(tlb_virt_to_page);
+EXPORT_SYMBOL(tlb_virt_to_page);
pgd_t *pgd_alloc(struct mm_struct *mm)
{
diff --git a/arch/loongarch/mm/tlbex.S b/arch/loongarch/mm/tlbex.S
index ca17dd3a1915..d5d682f3d29f 100644
--- a/arch/loongarch/mm/tlbex.S
+++ b/arch/loongarch/mm/tlbex.S
@@ -17,7 +17,7 @@
#define PTRS_PER_PTE_BITS (PAGE_SHIFT - 3)
.macro tlb_do_page_fault, write
- SYM_FUNC_START(tlb_do_page_fault_\write)
+ SYM_CODE_START(tlb_do_page_fault_\write)
SAVE_ALL
csrrd a2, LOONGARCH_CSR_BADV
move a0, sp
@@ -25,13 +25,13 @@
li.w a1, \write
bl do_page_fault
RESTORE_ALL_AND_RET
- SYM_FUNC_END(tlb_do_page_fault_\write)
+ SYM_CODE_END(tlb_do_page_fault_\write)
.endm
tlb_do_page_fault 0
tlb_do_page_fault 1
-SYM_FUNC_START(handle_tlb_protect)
+SYM_CODE_START(handle_tlb_protect)
BACKUP_T0T1
SAVE_ALL
move a0, sp
@@ -41,9 +41,9 @@ SYM_FUNC_START(handle_tlb_protect)
la_abs t0, do_page_fault
jirl ra, t0, 0
RESTORE_ALL_AND_RET
-SYM_FUNC_END(handle_tlb_protect)
+SYM_CODE_END(handle_tlb_protect)
-SYM_FUNC_START(handle_tlb_load)
+SYM_CODE_START(handle_tlb_load)
csrwr t0, EXCEPTION_KS0
csrwr t1, EXCEPTION_KS1
csrwr ra, EXCEPTION_KS2
@@ -187,16 +187,16 @@ nopage_tlb_load:
csrrd ra, EXCEPTION_KS2
la_abs t0, tlb_do_page_fault_0
jr t0
-SYM_FUNC_END(handle_tlb_load)
+SYM_CODE_END(handle_tlb_load)
-SYM_FUNC_START(handle_tlb_load_ptw)
+SYM_CODE_START(handle_tlb_load_ptw)
csrwr t0, LOONGARCH_CSR_KS0
csrwr t1, LOONGARCH_CSR_KS1
la_abs t0, tlb_do_page_fault_0
jr t0
-SYM_FUNC_END(handle_tlb_load_ptw)
+SYM_CODE_END(handle_tlb_load_ptw)
-SYM_FUNC_START(handle_tlb_store)
+SYM_CODE_START(handle_tlb_store)
csrwr t0, EXCEPTION_KS0
csrwr t1, EXCEPTION_KS1
csrwr ra, EXCEPTION_KS2
@@ -343,16 +343,16 @@ nopage_tlb_store:
csrrd ra, EXCEPTION_KS2
la_abs t0, tlb_do_page_fault_1
jr t0
-SYM_FUNC_END(handle_tlb_store)
+SYM_CODE_END(handle_tlb_store)
-SYM_FUNC_START(handle_tlb_store_ptw)
+SYM_CODE_START(handle_tlb_store_ptw)
csrwr t0, LOONGARCH_CSR_KS0
csrwr t1, LOONGARCH_CSR_KS1
la_abs t0, tlb_do_page_fault_1
jr t0
-SYM_FUNC_END(handle_tlb_store_ptw)
+SYM_CODE_END(handle_tlb_store_ptw)
-SYM_FUNC_START(handle_tlb_modify)
+SYM_CODE_START(handle_tlb_modify)
csrwr t0, EXCEPTION_KS0
csrwr t1, EXCEPTION_KS1
csrwr ra, EXCEPTION_KS2
@@ -497,16 +497,16 @@ nopage_tlb_modify:
csrrd ra, EXCEPTION_KS2
la_abs t0, tlb_do_page_fault_1
jr t0
-SYM_FUNC_END(handle_tlb_modify)
+SYM_CODE_END(handle_tlb_modify)
-SYM_FUNC_START(handle_tlb_modify_ptw)
+SYM_CODE_START(handle_tlb_modify_ptw)
csrwr t0, LOONGARCH_CSR_KS0
csrwr t1, LOONGARCH_CSR_KS1
la_abs t0, tlb_do_page_fault_1
jr t0
-SYM_FUNC_END(handle_tlb_modify_ptw)
+SYM_CODE_END(handle_tlb_modify_ptw)
-SYM_FUNC_START(handle_tlb_refill)
+SYM_CODE_START(handle_tlb_refill)
csrwr t0, LOONGARCH_CSR_TLBRSAVE
csrrd t0, LOONGARCH_CSR_PGD
lddir t0, t0, 3
@@ -521,4 +521,4 @@ SYM_FUNC_START(handle_tlb_refill)
tlbfill
csrrd t0, LOONGARCH_CSR_TLBRSAVE
ertn
-SYM_FUNC_END(handle_tlb_refill)
+SYM_CODE_END(handle_tlb_refill)
diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
index db9342b2d0e6..4fcd6cd6da23 100644
--- a/arch/loongarch/net/bpf_jit.c
+++ b/arch/loongarch/net/bpf_jit.c
@@ -411,7 +411,11 @@ static int add_exception_handler(const struct bpf_insn *insn,
off_t offset;
struct exception_table_entry *ex;
- if (!ctx->image || !ctx->prog->aux->extable || BPF_MODE(insn->code) != BPF_PROBE_MEM)
+ if (!ctx->image || !ctx->prog->aux->extable)
+ return 0;
+
+ if (BPF_MODE(insn->code) != BPF_PROBE_MEM &&
+ BPF_MODE(insn->code) != BPF_PROBE_MEMSX)
return 0;
if (WARN_ON_ONCE(ctx->num_exentries >= ctx->prog->aux->num_exentries))
@@ -450,7 +454,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
{
u8 tm = -1;
u64 func_addr;
- bool func_addr_fixed;
+ bool func_addr_fixed, sign_extend;
int i = insn - ctx->prog->insnsi;
int ret, jmp_offset;
const u8 code = insn->code;
@@ -468,8 +472,25 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
/* dst = src */
case BPF_ALU | BPF_MOV | BPF_X:
case BPF_ALU64 | BPF_MOV | BPF_X:
- move_reg(ctx, dst, src);
- emit_zext_32(ctx, dst, is32);
+ switch (off) {
+ case 0:
+ move_reg(ctx, dst, src);
+ emit_zext_32(ctx, dst, is32);
+ break;
+ case 8:
+ move_reg(ctx, t1, src);
+ emit_insn(ctx, extwb, dst, t1);
+ emit_zext_32(ctx, dst, is32);
+ break;
+ case 16:
+ move_reg(ctx, t1, src);
+ emit_insn(ctx, extwh, dst, t1);
+ emit_zext_32(ctx, dst, is32);
+ break;
+ case 32:
+ emit_insn(ctx, addw, dst, src, LOONGARCH_GPR_ZERO);
+ break;
+ }
break;
/* dst = imm */
@@ -534,39 +555,71 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
/* dst = dst / src */
case BPF_ALU | BPF_DIV | BPF_X:
case BPF_ALU64 | BPF_DIV | BPF_X:
- emit_zext_32(ctx, dst, is32);
- move_reg(ctx, t1, src);
- emit_zext_32(ctx, t1, is32);
- emit_insn(ctx, divdu, dst, dst, t1);
- emit_zext_32(ctx, dst, is32);
+ if (!off) {
+ emit_zext_32(ctx, dst, is32);
+ move_reg(ctx, t1, src);
+ emit_zext_32(ctx, t1, is32);
+ emit_insn(ctx, divdu, dst, dst, t1);
+ emit_zext_32(ctx, dst, is32);
+ } else {
+ emit_sext_32(ctx, dst, is32);
+ move_reg(ctx, t1, src);
+ emit_sext_32(ctx, t1, is32);
+ emit_insn(ctx, divd, dst, dst, t1);
+ emit_sext_32(ctx, dst, is32);
+ }
break;
/* dst = dst / imm */
case BPF_ALU | BPF_DIV | BPF_K:
case BPF_ALU64 | BPF_DIV | BPF_K:
- move_imm(ctx, t1, imm, is32);
- emit_zext_32(ctx, dst, is32);
- emit_insn(ctx, divdu, dst, dst, t1);
- emit_zext_32(ctx, dst, is32);
+ if (!off) {
+ move_imm(ctx, t1, imm, is32);
+ emit_zext_32(ctx, dst, is32);
+ emit_insn(ctx, divdu, dst, dst, t1);
+ emit_zext_32(ctx, dst, is32);
+ } else {
+ move_imm(ctx, t1, imm, false);
+ emit_sext_32(ctx, t1, is32);
+ emit_sext_32(ctx, dst, is32);
+ emit_insn(ctx, divd, dst, dst, t1);
+ emit_sext_32(ctx, dst, is32);
+ }
break;
/* dst = dst % src */
case BPF_ALU | BPF_MOD | BPF_X:
case BPF_ALU64 | BPF_MOD | BPF_X:
- emit_zext_32(ctx, dst, is32);
- move_reg(ctx, t1, src);
- emit_zext_32(ctx, t1, is32);
- emit_insn(ctx, moddu, dst, dst, t1);
- emit_zext_32(ctx, dst, is32);
+ if (!off) {
+ emit_zext_32(ctx, dst, is32);
+ move_reg(ctx, t1, src);
+ emit_zext_32(ctx, t1, is32);
+ emit_insn(ctx, moddu, dst, dst, t1);
+ emit_zext_32(ctx, dst, is32);
+ } else {
+ emit_sext_32(ctx, dst, is32);
+ move_reg(ctx, t1, src);
+ emit_sext_32(ctx, t1, is32);
+ emit_insn(ctx, modd, dst, dst, t1);
+ emit_sext_32(ctx, dst, is32);
+ }
break;
/* dst = dst % imm */
case BPF_ALU | BPF_MOD | BPF_K:
case BPF_ALU64 | BPF_MOD | BPF_K:
- move_imm(ctx, t1, imm, is32);
- emit_zext_32(ctx, dst, is32);
- emit_insn(ctx, moddu, dst, dst, t1);
- emit_zext_32(ctx, dst, is32);
+ if (!off) {
+ move_imm(ctx, t1, imm, is32);
+ emit_zext_32(ctx, dst, is32);
+ emit_insn(ctx, moddu, dst, dst, t1);
+ emit_zext_32(ctx, dst, is32);
+ } else {
+ move_imm(ctx, t1, imm, false);
+ emit_sext_32(ctx, t1, is32);
+ emit_sext_32(ctx, dst, is32);
+ emit_insn(ctx, modd, dst, dst, t1);
+ emit_sext_32(ctx, dst, is32);
+ }
break;
/* dst = -dst */
@@ -712,6 +765,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
break;
case BPF_ALU | BPF_END | BPF_FROM_BE:
+ case BPF_ALU64 | BPF_END | BPF_FROM_LE:
switch (imm) {
case 16:
emit_insn(ctx, revb2h, dst, dst);
@@ -720,8 +774,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
break;
case 32:
emit_insn(ctx, revb2w, dst, dst);
- /* zero-extend 32 bits into 64 bits */
- emit_zext_32(ctx, dst, is32);
+ /* clear the upper 32 bits */
+ emit_zext_32(ctx, dst, true);
break;
case 64:
emit_insn(ctx, revbd, dst, dst);
@@ -828,7 +882,11 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
/* PC += off */
case BPF_JMP | BPF_JA:
- jmp_offset = bpf2la_offset(i, off, ctx);
+ case BPF_JMP32 | BPF_JA:
+ if (BPF_CLASS(code) == BPF_JMP)
+ jmp_offset = bpf2la_offset(i, off, ctx);
+ else
+ jmp_offset = bpf2la_offset(i, imm, ctx);
if (emit_uncond_jmp(ctx, jmp_offset) < 0)
goto toofar;
break;
@@ -855,8 +913,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
/* function return */
case BPF_JMP | BPF_EXIT:
- emit_sext_32(ctx, regmap[BPF_REG_0], true);
-
if (i == ctx->prog->len - 1)
break;
@@ -879,42 +935,61 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
case BPF_LDX | BPF_PROBE_MEM | BPF_W:
case BPF_LDX | BPF_PROBE_MEM | BPF_H:
case BPF_LDX | BPF_PROBE_MEM | BPF_B:
+ /* dst_reg = (s64)*(signed size *)(src_reg + off) */
+ case BPF_LDX | BPF_MEMSX | BPF_B:
+ case BPF_LDX | BPF_MEMSX | BPF_H:
+ case BPF_LDX | BPF_MEMSX | BPF_W:
+ case BPF_LDX | BPF_PROBE_MEMSX | BPF_B:
+ case BPF_LDX | BPF_PROBE_MEMSX | BPF_H:
+ case BPF_LDX | BPF_PROBE_MEMSX | BPF_W:
+ sign_extend = BPF_MODE(insn->code) == BPF_MEMSX ||
+ BPF_MODE(insn->code) == BPF_PROBE_MEMSX;
switch (BPF_SIZE(code)) {
case BPF_B:
if (is_signed_imm12(off)) {
- emit_insn(ctx, ldbu, dst, src, off);
+ if (sign_extend)
+ emit_insn(ctx, ldb, dst, src, off);
+ else
+ emit_insn(ctx, ldbu, dst, src, off);
} else {
move_imm(ctx, t1, off, is32);
- emit_insn(ctx, ldxbu, dst, src, t1);
+ if (sign_extend)
+ emit_insn(ctx, ldxb, dst, src, t1);
+ else
+ emit_insn(ctx, ldxbu, dst, src, t1);
}
break;
case BPF_H:
if (is_signed_imm12(off)) {
- emit_insn(ctx, ldhu, dst, src, off);
+ if (sign_extend)
+ emit_insn(ctx, ldh, dst, src, off);
+ else
+ emit_insn(ctx, ldhu, dst, src, off);
} else {
move_imm(ctx, t1, off, is32);
- emit_insn(ctx, ldxhu, dst, src, t1);
+ if (sign_extend)
+ emit_insn(ctx, ldxh, dst, src, t1);
+ else
+ emit_insn(ctx, ldxhu, dst, src, t1);
}
break;
case BPF_W:
if (is_signed_imm12(off)) {
- emit_insn(ctx, ldwu, dst, src, off);
- } else if (is_signed_imm14(off)) {
- emit_insn(ctx, ldptrw, dst, src, off);
+ if (sign_extend)
+ emit_insn(ctx, ldw, dst, src, off);
+ else
+ emit_insn(ctx, ldwu, dst, src, off);
} else {
move_imm(ctx, t1, off, is32);
- emit_insn(ctx, ldxwu, dst, src, t1);
+ if (sign_extend)
+ emit_insn(ctx, ldxw, dst, src, t1);
+ else
+ emit_insn(ctx, ldxwu, dst, src, t1);
}
break;
case BPF_DW:
- if (is_signed_imm12(off)) {
- emit_insn(ctx, ldd, dst, src, off);
- } else if (is_signed_imm14(off)) {
- emit_insn(ctx, ldptrd, dst, src, off);
- } else {
- move_imm(ctx, t1, off, is32);
- emit_insn(ctx, ldxd, dst, src, t1);
- }
+ move_imm(ctx, t1, off, is32);
+ emit_insn(ctx, ldxd, dst, src, t1);
break;
}
diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile
index 5c97d1463328..c74c9921304f 100644
--- a/arch/loongarch/vdso/Makefile
+++ b/arch/loongarch/vdso/Makefile
@@ -83,13 +83,3 @@ $(obj)/vdso.so: $(obj)/vdso.so.dbg FORCE
obj-y += vdso.o
$(obj)/vdso.o : $(obj)/vdso.so
-
-# install commands for the unstripped file
-quiet_cmd_vdso_install = INSTALL $@
- cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
-
-vdso.so: $(obj)/vdso.so.dbg
- @mkdir -p $(MODLIB)/vdso
- $(call cmd,vdso_install)
-
-vdso_install: vdso.so
diff --git a/arch/m68k/68000/entry.S b/arch/m68k/68000/entry.S
index 7d63e2f1555a..72e95663b62f 100644
--- a/arch/m68k/68000/entry.S
+++ b/arch/m68k/68000/entry.S
@@ -1,12 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ *
* entry.S -- non-mmu 68000 interrupt and exception entry points
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file README.legal in the main directory of this archive
- * for more details.
- *
* Linux/m68k support by Hamish Macdonald
*/
diff --git a/arch/m68k/68000/ints.c b/arch/m68k/68000/ints.c
index f9a5ec781408..2ba9926e91ae 100644
--- a/arch/m68k/68000/ints.c
+++ b/arch/m68k/68000/ints.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/cpu.h>
#include <asm/traps.h>
#include <asm/io.h>
#include <asm/machdep.h>
@@ -26,6 +27,8 @@
#include <asm/MC68328.h>
#endif
+#include "ints.h"
+
/* assembler routines */
asmlinkage void system_call(void);
asmlinkage void buserr(void);
@@ -74,7 +77,7 @@ asmlinkage irqreturn_t inthandler7(void);
* into one vector and look in the blasted mask register...
* This code is designed to be fast, almost constant time, not clean!
*/
-void process_int(int vec, struct pt_regs *fp)
+asmlinkage void process_int(int vec, struct pt_regs *fp)
{
int irq;
int mask;
diff --git a/arch/m68k/68000/ints.h b/arch/m68k/68000/ints.h
new file mode 100644
index 000000000000..d9cfd0eb9ffe
--- /dev/null
+++ b/arch/m68k/68000/ints.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <linux/linkage.h>
+
+struct pt_regs;
+
+asmlinkage void process_int(int vec, struct pt_regs *fp);
diff --git a/arch/m68k/68000/timers.c b/arch/m68k/68000/timers.c
index 0d0417cebc7f..00fb0dd12faa 100644
--- a/arch/m68k/68000/timers.c
+++ b/arch/m68k/68000/timers.c
@@ -25,6 +25,8 @@
#include <asm/machdep.h>
#include <asm/MC68VZ328.h>
+#include "m68328.h"
+
/***************************************************************************/
#if defined(CONFIG_DRAGEN2)
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 3e318bf9504c..4b3e93cac723 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -6,19 +6,22 @@ config M68K
select ARCH_HAS_BINFMT_FLAT
select ARCH_HAS_CPU_FINALIZE_INIT if MMU
select ARCH_HAS_CURRENT_STACK_POINTER
- select ARCH_HAS_DMA_PREP_COHERENT if HAS_DMA && MMU && !COLDFIRE
- select ARCH_HAS_SYNC_DMA_FOR_DEVICE if HAS_DMA
+ select ARCH_HAS_DMA_PREP_COHERENT if M68K_NONCOHERENT_DMA && !COLDFIRE
+ select ARCH_HAS_SYNC_DMA_FOR_DEVICE if M68K_NONCOHERENT_DMA
select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
select ARCH_MIGHT_HAVE_PC_PARPORT if ISA
select ARCH_NO_PREEMPT if !COLDFIRE
select ARCH_USE_MEMTEST if MMU_MOTOROLA
select ARCH_WANT_IPC_PARSE_VERSION
select BINFMT_FLAT_ARGVP_ENVP_ON_STACK
- select DMA_DIRECT_REMAP if HAS_DMA && MMU && !COLDFIRE
+ select DMA_DIRECT_REMAP if M68K_NONCOHERENT_DMA && !COLDFIRE
select GENERIC_ATOMIC64
select GENERIC_CPU_DEVICES
select GENERIC_IOMAP
select GENERIC_IRQ_SHOW
+ select GENERIC_LIB_ASHLDI3
+ select GENERIC_LIB_ASHRDI3
+ select GENERIC_LIB_LSHRDI3
select HAS_IOPORT if PCI || ISA || ATARI_ROM_ISA
select HAVE_ARCH_SECCOMP
select HAVE_ARCH_SECCOMP_FILTER
diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu
index b826e9c677b2..ad69b466a08b 100644
--- a/arch/m68k/Kconfig.cpu
+++ b/arch/m68k/Kconfig.cpu
@@ -535,3 +535,15 @@ config CACHE_COPYBACK
The ColdFire CPU cache is set into Copy-back mode.
endchoice
endif # HAVE_CACHE_CB
+
+# Coldfire cores that do not have a data cache configured can do coherent DMA.
+config COLDFIRE_COHERENT_DMA
+ bool
+ default y
+ depends on COLDFIRE
+ depends on !HAVE_CACHE_CB && !CACHE_D && !CACHE_BOTH
+
+config M68K_NONCOHERENT_DMA
+ bool
+ default y
+ depends on HAS_DMA && !COLDFIRE_COHERENT_DMA
diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine
index 1f3574aef638..d06b1c5d9b0c 100644
--- a/arch/m68k/Kconfig.machine
+++ b/arch/m68k/Kconfig.machine
@@ -441,7 +441,7 @@ config ROM
config ROMVEC
hex "Address of the base of the ROM vectors"
- default "0"
+ default "0x10c10000"
depends on ROM
help
This is almost always the same as the base of the ROM. Since on all
@@ -450,7 +450,7 @@ config ROMVEC
config ROMSTART
hex "Address of the base of system image in ROM"
- default "0x400"
+ default "0x10c10400"
depends on ROM
help
Define the start address of the system image in ROM. Commonly this
diff --git a/arch/m68k/amiga/amiga.h b/arch/m68k/amiga/amiga.h
new file mode 100644
index 000000000000..00392781442c
--- /dev/null
+++ b/arch/m68k/amiga/amiga.h
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/* amisound.c */
+void amiga_init_sound(void);
+void amiga_mksound(unsigned int hz, unsigned int ticks);
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index 442bdeee6bd7..714fe8ec6afa 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -16,6 +16,8 @@
#include <asm/amigahw.h>
+#include "amiga.h"
+
static unsigned short *snd_data;
static const signed char sine_data[] = {
0, 39, 75, 103, 121, 127, 121, 103, 75, 39,
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 3137b45750df..7791673e547b 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -39,6 +39,8 @@
#include <asm/io.h>
#include <asm/config.h>
+#include "amiga.h"
+
static unsigned long amiga_model;
unsigned long amiga_eclock;
@@ -96,9 +98,7 @@ static char amiga_model_name[13] = "Amiga ";
static void amiga_sched_init(void);
static void amiga_get_model(char *model);
static void amiga_get_hardware_list(struct seq_file *m);
-extern void amiga_mksound(unsigned int count, unsigned int ticks);
static void amiga_reset(void);
-extern void amiga_init_sound(void);
static void amiga_mem_console_write(struct console *co, const char *b,
unsigned int count);
#ifdef CONFIG_HEARTBEAT
diff --git a/arch/m68k/amiga/pcmcia.c b/arch/m68k/amiga/pcmcia.c
index 7106f0c3639b..63cce6b590df 100644
--- a/arch/m68k/amiga/pcmcia.c
+++ b/arch/m68k/amiga/pcmcia.c
@@ -26,11 +26,10 @@ static unsigned char cfg_byte = GAYLE_CFG_0V|GAYLE_CFG_150NS;
void pcmcia_reset(void)
{
unsigned long reset_start_time = jiffies;
- unsigned char b;
gayle_reset = 0x00;
while (time_before(jiffies, reset_start_time + 1*HZ/100));
- b = gayle_reset;
+ READ_ONCE(gayle_reset);
}
EXPORT_SYMBOL(pcmcia_reset);
diff --git a/arch/m68k/apollo/apollo.h b/arch/m68k/apollo/apollo.h
new file mode 100644
index 000000000000..1fe9d856df30
--- /dev/null
+++ b/arch/m68k/apollo/apollo.h
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* dn_ints.c */
+void dn_init_IRQ(void);
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index 42a8b8e2b664..e161ecd76035 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -4,7 +4,6 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/tty.h>
-#include <linux/console.h>
#include <linux/rtc.h>
#include <linux/vt_kern.h>
#include <linux/interrupt.h>
@@ -18,6 +17,8 @@
#include <asm/machdep.h>
#include <asm/config.h>
+#include "apollo.h"
+
u_long sio01_physaddr;
u_long sio23_physaddr;
u_long rtc_physaddr;
@@ -28,9 +29,8 @@ u_long timer_physaddr;
u_long apollo_model;
extern void dn_sched_init(void);
-extern void dn_init_IRQ(void);
extern int dn_dummy_hwclk(int, struct rtc_time *);
-extern void dn_dummy_reset(void);
+static void dn_dummy_reset(void);
#ifdef CONFIG_HEARTBEAT
static void dn_heartbeat(int on);
#endif
@@ -108,28 +108,7 @@ static void __init dn_setup_model(void)
}
-int dn_serial_console_wait_key(struct console *co) {
-
- while(!(sio01.srb_csrb & 1))
- barrier();
- return sio01.rhrb_thrb;
-}
-
-void dn_serial_console_write (struct console *co, const char *str,unsigned int count)
-{
- while(count--) {
- if (*str == '\n') {
- sio01.rhrb_thrb = (unsigned char)'\r';
- while (!(sio01.srb_csrb & 0x4))
- ;
- }
- sio01.rhrb_thrb = (unsigned char)*str++;
- while (!(sio01.srb_csrb & 0x4))
- ;
- }
-}
-
-void dn_serial_print (const char *str)
+static void dn_serial_print(const char *str)
{
while (*str) {
if (*str == '\n') {
@@ -168,13 +147,13 @@ void __init config_apollo(void)
irqreturn_t dn_timer_int(int irq, void *dev_id)
{
- volatile unsigned char x;
+ unsigned char *at = (unsigned char *)apollo_timer;
legacy_timer_tick(1);
timer_heartbeat();
- x = *(volatile unsigned char *)(apollo_timer + 3);
- x = *(volatile unsigned char *)(apollo_timer + 5);
+ READ_ONCE(*(at + 3));
+ READ_ONCE(*(at + 5));
return IRQ_HANDLED;
}
@@ -229,20 +208,14 @@ int dn_dummy_hwclk(int op, struct rtc_time *t) {
}
-void dn_dummy_reset(void) {
-
+static void dn_dummy_reset(void)
+{
dn_serial_print("The end !\n");
for(;;);
}
-void dn_dummy_waitbut(void) {
-
- dn_serial_print("waitbut\n");
-
-}
-
static void dn_get_model(char *model)
{
strcpy(model, "Apollo ");
diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c
index 02cff7efc834..ba96a92f8f18 100644
--- a/arch/m68k/apollo/dn_ints.c
+++ b/arch/m68k/apollo/dn_ints.c
@@ -5,7 +5,9 @@
#include <asm/traps.h>
#include <asm/apollohw.h>
-unsigned int apollo_irq_startup(struct irq_data *data)
+#include "apollo.h"
+
+static unsigned int apollo_irq_startup(struct irq_data *data)
{
unsigned int irq = data->irq;
@@ -16,7 +18,7 @@ unsigned int apollo_irq_startup(struct irq_data *data)
return 0;
}
-void apollo_irq_shutdown(struct irq_data *data)
+static void apollo_irq_shutdown(struct irq_data *data)
{
unsigned int irq = data->irq;
@@ -26,7 +28,7 @@ void apollo_irq_shutdown(struct irq_data *data)
*(volatile unsigned char *)(picb+1) |= (1 << (irq - 8));
}
-void apollo_irq_eoi(struct irq_data *data)
+static void apollo_irq_eoi(struct irq_data *data)
{
*(volatile unsigned char *)(pica) = 0x20;
*(volatile unsigned char *)(picb) = 0x20;
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index 56f02ea2c248..23256434191c 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -52,6 +52,7 @@
#include <asm/entry.h>
#include <asm/io.h>
+#include "atari.h"
/*
* Atari interrupt handling scheme:
@@ -81,8 +82,6 @@ __ALIGN_STR "\n\t"
"orw #0x200,%sp@\n\t" /* set saved ipl to 2 */
"rte");
-extern void atari_microwire_cmd(int cmd);
-
static unsigned int atari_irq_startup(struct irq_data *data)
{
unsigned int irq = data->irq;
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
index 5e0e682f9c61..49a9a459bdf4 100644
--- a/arch/m68k/atari/atakeyb.c
+++ b/arch/m68k/atari/atakeyb.c
@@ -332,7 +332,7 @@ void ikbd_write(const char *str, int len)
}
/* Reset (without touching the clock) */
-void ikbd_reset(void)
+static void ikbd_reset(void)
{
static const char cmd[2] = { 0x80, 0x01 };
diff --git a/arch/m68k/atari/atari.h b/arch/m68k/atari/atari.h
new file mode 100644
index 000000000000..494a03ddac3d
--- /dev/null
+++ b/arch/m68k/atari/atari.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+struct rtc_time;
+
+/* ataints.c */
+void atari_init_IRQ(void);
+
+/* atasound.c */
+void atari_microwire_cmd(int cmd);
+void atari_mksound(unsigned int hz, unsigned int ticks);
+
+/* time.c */
+void atari_sched_init(void);
+int atari_mste_hwclk(int op, struct rtc_time *t);
+int atari_tt_hwclk(int op, struct rtc_time *t);
diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c
index a8724d998c39..c38ef0e6078e 100644
--- a/arch/m68k/atari/atasound.c
+++ b/arch/m68k/atari/atasound.c
@@ -28,6 +28,7 @@
#include <asm/irq.h>
#include <asm/atariints.h>
+#include "atari.h"
/*
* stuff from the old atasound.c
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 38a7c0578105..b48a0606a000 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -48,6 +48,8 @@
#include <asm/io.h>
#include <asm/config.h>
+#include "atari.h"
+
u_long atari_mch_cookie;
EXPORT_SYMBOL(atari_mch_cookie);
@@ -69,19 +71,10 @@ int atari_rtc_year_offset;
static void atari_reset(void);
static void atari_get_model(char *model);
static void atari_get_hardware_list(struct seq_file *m);
-
-/* atari specific irq functions */
-extern void atari_init_IRQ (void);
-extern void atari_mksound(unsigned int count, unsigned int ticks);
#ifdef CONFIG_HEARTBEAT
static void atari_heartbeat(int on);
#endif
-/* atari specific timer functions (in time.c) */
-extern void atari_sched_init(void);
-extern int atari_mste_hwclk (int, struct rtc_time *);
-extern int atari_tt_hwclk (int, struct rtc_time *);
-
/* ++roman: This is a more elaborate test for an SCC chip, since the plain
* Medusa board generates DTACK at the SCC's standard addresses, but a SCC
* board in the Medusa is possible. Also, the addresses where the ST_ESCC
@@ -880,7 +873,7 @@ static const struct resource atari_falconide_rsrc[] __initconst = {
DEFINE_RES_MEM(FALCON_IDE_BASE + 0x38, 2),
};
-int __init atari_platform_init(void)
+static int __init atari_platform_init(void)
{
struct platform_device *pdev;
int rv = 0;
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index ce6818eff75e..155fefff19b0 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -61,6 +61,7 @@ static irqreturn_t stdma_int (int irq, void *dummy);
/**
* stdma_try_lock - attempt to acquire ST DMA interrupt "lock"
* @handler: interrupt handler to use after acquisition
+ * @data: cookie passed to the interrupt handler function
*
* Returns !0 if lock was acquired; otherwise 0.
*/
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index ce79b322a99c..922e53bcb853 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -115,7 +115,7 @@ void __init atari_stram_reserve_pages(void *start_mem)
* This function is called as arch initcall to reserve the pages needed for
* ST-RAM management, if the kernel does not reside in ST-RAM.
*/
-int __init atari_stram_map_pages(void)
+static int __init atari_stram_map_pages(void)
{
if (!kernel_in_stram) {
/*
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index 7e44d0e9d0f8..3453c6dc6b41 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -23,6 +23,8 @@
#include <asm/atariints.h>
#include <asm/machdep.h>
+#include "atari.h"
+
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL_GPL(rtc_lock);
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 3a1d90e399e0..8a2ee69a09f6 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* arch/m68k/bvme6000/config.c
*
@@ -8,10 +9,6 @@
* linux/amiga/config.c
*
* Copyright (C) 1993 Hamish Macdonald
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file README.legal in the main directory of this archive
- * for more details.
*/
#include <linux/types.h>
@@ -130,7 +127,7 @@ void __init config_bvme6000(void)
}
-irqreturn_t bvme6000_abort_int (int irq, void *dev_id)
+static irqreturn_t bvme6000_abort_int(int irq, void *dev_id)
{
unsigned long *new = (unsigned long *)vectors;
unsigned long *old = (unsigned long *)0xf8000000;
diff --git a/arch/m68k/coldfire/entry.S b/arch/m68k/coldfire/entry.S
index 35104c5417ff..4ea08336e2fb 100644
--- a/arch/m68k/coldfire/entry.S
+++ b/arch/m68k/coldfire/entry.S
@@ -1,4 +1,5 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ *
* entry.S -- interrupt and exception processing for ColdFire
*
* Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com)
@@ -13,10 +14,6 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file README.legal in the main directory of this archive
- * for more details.
- *
* Linux/m68k support by Hamish Macdonald
*
* 68060 fixes by Jesper Skov
diff --git a/arch/m68k/coldfire/intc.c b/arch/m68k/coldfire/intc.c
index 20c084e932c8..b434371e2b99 100644
--- a/arch/m68k/coldfire/intc.c
+++ b/arch/m68k/coldfire/intc.c
@@ -56,7 +56,7 @@ void mcf_clrimr(int index)
__raw_writew(imr & ~(0x1 << index), MCFSIM_IMR);
}
-void mcf_maskimr(unsigned int mask)
+static void mcf_maskimr(unsigned int mask)
{
u16 imr;
imr = __raw_readw(MCFSIM_IMR);
@@ -80,7 +80,7 @@ void mcf_clrimr(int index)
__raw_writel(imr & ~(0x1 << index), MCFSIM_IMR);
}
-void mcf_maskimr(unsigned int mask)
+static void mcf_maskimr(unsigned int mask)
{
u32 imr;
imr = __raw_readl(MCFSIM_IMR);
diff --git a/arch/m68k/coldfire/vectors.c b/arch/m68k/coldfire/vectors.c
index 3bf0d69eec9e..c26c255b530d 100644
--- a/arch/m68k/coldfire/vectors.c
+++ b/arch/m68k/coldfire/vectors.c
@@ -18,6 +18,8 @@
#include <asm/mcfsim.h>
#include <asm/mcfwdebug.h>
+#include "vectors.h"
+
/***************************************************************************/
#ifdef TRAP_DBG_INTERRUPT
diff --git a/arch/m68k/coldfire/vectors.h b/arch/m68k/coldfire/vectors.h
new file mode 100644
index 000000000000..0b01450a4353
--- /dev/null
+++ b/arch/m68k/coldfire/vectors.h
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+void trap_init(void);
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index 6deb8faa564b..7e6b74b6eecd 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -299,6 +299,7 @@ CONFIG_NET_IFE=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
+CONFIG_DM_KUNIT_TEST=m
CONFIG_CONNECTOR=m
CONFIG_PARPORT=m
CONFIG_PARPORT_AMIGA=m
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 802c161827f4..0b403e2efcd5 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -295,6 +295,7 @@ CONFIG_NET_IFE=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
+CONFIG_DM_KUNIT_TEST=m
CONFIG_CONNECTOR=m
CONFIG_ZRAM=m
CONFIG_BLK_DEV_LOOP=y
@@ -568,6 +569,7 @@ CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_PRIME_NUMBERS=m
CONFIG_CRC32_SELFTEST=m
CONFIG_XZ_DEC_TEST=m
+CONFIG_GLOB_SELFTEST=m
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_TEST_LOCKUP=m
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 2cb3d755873b..57aac3f4b001 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -302,6 +302,7 @@ CONFIG_NET_IFE=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
+CONFIG_DM_KUNIT_TEST=m
CONFIG_CONNECTOR=m
CONFIG_PARPORT=m
CONFIG_PARPORT_ATARI=m
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index b13552caa6b3..3c160636a2e9 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -292,6 +292,7 @@ CONFIG_NET_IFE=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
+CONFIG_DM_KUNIT_TEST=m
CONFIG_CONNECTOR=m
CONFIG_ZRAM=m
CONFIG_BLK_DEV_LOOP=y
@@ -560,6 +561,7 @@ CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_PRIME_NUMBERS=m
CONFIG_CRC32_SELFTEST=m
CONFIG_XZ_DEC_TEST=m
+CONFIG_GLOB_SELFTEST=m
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_TEST_LOCKUP=m
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index f88356c45440..23cf07c49d14 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -294,6 +294,7 @@ CONFIG_NET_IFE=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
+CONFIG_DM_KUNIT_TEST=m
CONFIG_CONNECTOR=m
CONFIG_ZRAM=m
CONFIG_BLK_DEV_LOOP=y
@@ -570,6 +571,7 @@ CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_PRIME_NUMBERS=m
CONFIG_CRC32_SELFTEST=m
CONFIG_XZ_DEC_TEST=m
+CONFIG_GLOB_SELFTEST=m
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_TEST_LOCKUP=m
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 7c2ebb616fba..619a0d93ce5b 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -296,6 +296,7 @@ CONFIG_NET_IFE=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
+CONFIG_DM_KUNIT_TEST=m
CONFIG_CONNECTOR=m
CONFIG_BLK_DEV_SWIM=m
CONFIG_ZRAM=m
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index d3b272910b38..d9430bc2b2de 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -316,6 +316,7 @@ CONFIG_NET_IFE=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
+CONFIG_DM_KUNIT_TEST=m
CONFIG_CONNECTOR=m
CONFIG_PARPORT=m
CONFIG_PARPORT_PC=m
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index 4529bc4b843c..eb6132f29bf5 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -291,6 +291,7 @@ CONFIG_NET_IFE=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
+CONFIG_DM_KUNIT_TEST=m
CONFIG_CONNECTOR=m
CONFIG_ZRAM=m
CONFIG_BLK_DEV_LOOP=y
@@ -559,6 +560,7 @@ CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_PRIME_NUMBERS=m
CONFIG_CRC32_SELFTEST=m
CONFIG_XZ_DEC_TEST=m
+CONFIG_GLOB_SELFTEST=m
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_TEST_LOCKUP=m
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index 30824032e4d5..d0bad674cbb7 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -292,6 +292,7 @@ CONFIG_NET_IFE=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
+CONFIG_DM_KUNIT_TEST=m
CONFIG_CONNECTOR=m
CONFIG_ZRAM=m
CONFIG_BLK_DEV_LOOP=y
@@ -560,6 +561,7 @@ CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_PRIME_NUMBERS=m
CONFIG_CRC32_SELFTEST=m
CONFIG_XZ_DEC_TEST=m
+CONFIG_GLOB_SELFTEST=m
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_TEST_LOCKUP=m
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index 3911211410ed..dad6bcfcaeed 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -293,6 +293,7 @@ CONFIG_NET_IFE=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
+CONFIG_DM_KUNIT_TEST=m
CONFIG_CONNECTOR=m
CONFIG_PARPORT=m
CONFIG_PARPORT_PC=m
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 991730c50957..eb1b489b3139 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -288,6 +288,7 @@ CONFIG_NET_IFE=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
+CONFIG_DM_KUNIT_TEST=m
CONFIG_CONNECTOR=m
CONFIG_ZRAM=m
CONFIG_BLK_DEV_LOOP=y
@@ -558,6 +559,7 @@ CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_PRIME_NUMBERS=m
CONFIG_CRC32_SELFTEST=m
CONFIG_XZ_DEC_TEST=m
+CONFIG_GLOB_SELFTEST=m
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_TEST_LOCKUP=m
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index e80d7509ab1d..939589826546 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -289,6 +289,7 @@ CONFIG_NET_IFE=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
+CONFIG_DM_KUNIT_TEST=m
CONFIG_CONNECTOR=m
CONFIG_ZRAM=m
CONFIG_BLK_DEV_LOOP=y
@@ -558,6 +559,7 @@ CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_PRIME_NUMBERS=m
CONFIG_CRC32_SELFTEST=m
CONFIG_XZ_DEC_TEST=m
+CONFIG_GLOB_SELFTEST=m
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_TEST_LOCKUP=m
diff --git a/arch/m68k/configs/virt_defconfig b/arch/m68k/configs/virt_defconfig
index 311b57e73316..ce725d39e488 100644
--- a/arch/m68k/configs/virt_defconfig
+++ b/arch/m68k/configs/virt_defconfig
@@ -45,8 +45,9 @@ CONFIG_INPUT_EVDEV=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_DRM=y
+CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_DRM_VIRTIO_GPU=y
-CONFIG_FB=y
+CONFIG_FB_DEVICE=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_VIRTIO=y
diff --git a/arch/m68k/emu/natfeat.c b/arch/m68k/emu/natfeat.c
index b19dc00026d9..777c7b42a50f 100644
--- a/arch/m68k/emu/natfeat.c
+++ b/arch/m68k/emu/natfeat.c
@@ -42,10 +42,10 @@ long nf_get_id(const char *feature_name)
{
/* feature_name may be in vmalloc()ed memory, so make a copy */
char name_copy[32];
- size_t n;
+ ssize_t n;
- n = strlcpy(name_copy, feature_name, sizeof(name_copy));
- if (n >= sizeof(name_copy))
+ n = strscpy(name_copy, feature_name, sizeof(name_copy));
+ if (n < 0)
return 0;
return nf_get_id_phys(virt_to_phys(name_copy));
@@ -56,10 +56,9 @@ void nfprint(const char *fmt, ...)
{
static char buf[256];
va_list ap;
- int n;
va_start(ap, fmt);
- n = vsnprintf(buf, 256, fmt, ap);
+ vsnprintf(buf, 256, fmt, ap);
nf_call(nf_get_id("NF_STDERR"), virt_to_phys(buf));
va_end(ap);
}
diff --git a/arch/m68k/emu/nfeth.c b/arch/m68k/emu/nfeth.c
index 1a5d1e8eb4c8..26e68813f351 100644
--- a/arch/m68k/emu/nfeth.c
+++ b/arch/m68k/emu/nfeth.c
@@ -39,7 +39,7 @@ enum {
#define MAX_UNIT 8
/* These identify the driver base version and may not be removed. */
-static const char version[] =
+static const char version[] __maybe_unused =
KERN_INFO KBUILD_MODNAME ".c:v" DRV_VERSION " " DRV_RELDATE
" S.Opichal, M.Jurik, P.Stehlik\n"
KERN_INFO " http://aranym.org/\n";
diff --git a/arch/m68k/fpsp040/slogn.S b/arch/m68k/fpsp040/slogn.S
index d98eaf641ec4..5f3da4aa7e45 100644
--- a/arch/m68k/fpsp040/slogn.S
+++ b/arch/m68k/fpsp040/slogn.S
@@ -261,56 +261,56 @@ slognd:
|----the value TWOTO100 is no longer needed.
|----Note that this code assumes the denormalized input is NON-ZERO.
- moveml %d2-%d7,-(%a7) | ...save some registers
- movel #0x00000000,%d3 | ...D3 is exponent of smallest norm. #
- movel 4(%a0),%d4
- movel 8(%a0),%d5 | ...(D4,D5) is (Hi_X,Lo_X)
- clrl %d2 | ...D2 used for holding K
+ moveml %d2-%d7,-(%a7) | ...save some registers
+ movel #0x00000000,%d3 | ...D3 is exponent of smallest norm. #
+ movel 4(%a0),%d4
+ movel 8(%a0),%d5 | ...(D4,D5) is (Hi_X,Lo_X)
+ clrl %d2 | ...D2 used for holding K
- tstl %d4
- bnes HiX_not0
+ tstl %d4
+ bnes HiX_not0
HiX_0:
- movel %d5,%d4
- clrl %d5
- movel #32,%d2
- clrl %d6
- bfffo %d4{#0:#32},%d6
- lsll %d6,%d4
- addl %d6,%d2 | ...(D3,D4,D5) is normalized
-
- movel %d3,X(%a6)
- movel %d4,XFRAC(%a6)
- movel %d5,XFRAC+4(%a6)
- negl %d2
- movel %d2,ADJK(%a6)
- fmovex X(%a6),%fp0
- moveml (%a7)+,%d2-%d7 | ...restore registers
- lea X(%a6),%a0
- bras LOGBGN | ...begin regular log(X)
+ movel %d5,%d4
+ clrl %d5
+ movel #32,%d2
+ clrl %d6
+ bfffo %d4{#0:#32},%d6
+ lsll %d6,%d4
+ addl %d6,%d2 | ...(D3,D4,D5) is normalized
+
+ movel %d3,X(%a6)
+ movel %d4,XFRAC(%a6)
+ movel %d5,XFRAC+4(%a6)
+ negl %d2
+ movel %d2,ADJK(%a6)
+ fmovex X(%a6),%fp0
+ moveml (%a7)+,%d2-%d7 | ...restore registers
+ lea X(%a6),%a0
+ bras LOGBGN | ...begin regular log(X)
HiX_not0:
- clrl %d6
- bfffo %d4{#0:#32},%d6 | ...find first 1
- movel %d6,%d2 | ...get k
- lsll %d6,%d4
- movel %d5,%d7 | ...a copy of D5
- lsll %d6,%d5
- negl %d6
- addil #32,%d6
- lsrl %d6,%d7
- orl %d7,%d4 | ...(D3,D4,D5) normalized
-
- movel %d3,X(%a6)
- movel %d4,XFRAC(%a6)
- movel %d5,XFRAC+4(%a6)
- negl %d2
- movel %d2,ADJK(%a6)
- fmovex X(%a6),%fp0
- moveml (%a7)+,%d2-%d7 | ...restore registers
- lea X(%a6),%a0
- bras LOGBGN | ...begin regular log(X)
+ clrl %d6
+ bfffo %d4{#0:#32},%d6 | ...find first 1
+ movel %d6,%d2 | ...get k
+ lsll %d6,%d4
+ movel %d5,%d7 | ...a copy of D5
+ lsll %d6,%d5
+ negl %d6
+ addil #32,%d6
+ lsrl %d6,%d7
+ orl %d7,%d4 | ...(D3,D4,D5) normalized
+
+ movel %d3,X(%a6)
+ movel %d4,XFRAC(%a6)
+ movel %d5,XFRAC+4(%a6)
+ negl %d2
+ movel %d2,ADJK(%a6)
+ fmovex X(%a6),%fp0
+ moveml (%a7)+,%d2-%d7 | ...restore registers
+ lea X(%a6),%a0
+ bras LOGBGN | ...begin regular log(X)
.global slogn
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index 1d1b7b3b5dd4..72621fb9f3e6 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -20,6 +20,8 @@
#include <asm/traps.h>
#include <asm/blinken.h>
+#include "time.h"
+
static u64 hp300_read_clk(struct clocksource *cs);
static struct clocksource hp300_clk = {
diff --git a/arch/m68k/ifpsp060/Makefile b/arch/m68k/ifpsp060/Makefile
index 56b530a96c2f..00d0621f547c 100644
--- a/arch/m68k/ifpsp060/Makefile
+++ b/arch/m68k/ifpsp060/Makefile
@@ -1,7 +1,5 @@
-# Makefile for 680x0 Linux 68060 integer/floating point support package
+# SPDX-License-Identifier: GPL-2.0-or-later
#
-# This file is subject to the terms and conditions of the GNU General Public
-# License. See the file "README.legal" in the main directory of this archive
-# for more details.
+# Makefile for 680x0 Linux 68060 integer/floating point support package
obj-y := fskeleton.o iskeleton.o os.o
diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h
index e984af71df6b..14c64a6f1217 100644
--- a/arch/m68k/include/asm/bitops.h
+++ b/arch/m68k/include/asm/bitops.h
@@ -319,6 +319,27 @@ arch___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
return test_and_change_bit(nr, addr);
}
+static inline bool xor_unlock_is_negative_byte(unsigned long mask,
+ volatile unsigned long *p)
+{
+#ifdef CONFIG_COLDFIRE
+ __asm__ __volatile__ ("eorl %1, %0"
+ : "+m" (*p)
+ : "d" (mask)
+ : "memory");
+ return *p & (1 << 7);
+#else
+ char result;
+ char *cp = (char *)p + 3; /* m68k is big-endian */
+
+ __asm__ __volatile__ ("eor.b %1, %2; smi %0"
+ : "=d" (result)
+ : "di" (mask), "o" (*cp)
+ : "memory");
+ return result;
+#endif
+}
+
/*
* The true 68020 and more advanced processors support the "bfffo"
* instruction for finding bits. ColdFire and simple 68000 parts
diff --git a/arch/m68k/include/asm/dvma.h b/arch/m68k/include/asm/dvma.h
index f609ec1de36d..d1d66d04844d 100644
--- a/arch/m68k/include/asm/dvma.h
+++ b/arch/m68k/include/asm/dvma.h
@@ -58,12 +58,16 @@ extern void dvma_free(void *vaddr);
#define dvma_vtob(x) dvma_vtop(x)
#define dvma_btov(x) dvma_ptov(x)
+void sun3_dvma_init(void);
+
static inline int dvma_map_cpu(unsigned long kaddr, unsigned long vaddr,
int len)
{
return 0;
}
+static inline void dvma_unmap_iommu(unsigned long baddr, int len) { }
+
#else /* Sun3x */
/* sun3x dvma page support */
@@ -78,9 +82,11 @@ static inline int dvma_map_cpu(unsigned long kaddr, unsigned long vaddr,
#define dvma_vtob(x) ((unsigned long)(x) & 0x00ffffff)
#define dvma_btov(x) ((unsigned long)(x) | 0xff000000)
-extern int dvma_map_cpu(unsigned long kaddr, unsigned long vaddr, int len);
+static inline void sun3_dvma_init(void) { }
+int dvma_map_cpu(unsigned long kaddr, unsigned long vaddr, int len);
+void dvma_unmap_iommu(unsigned long baddr, int len);
/* everything below this line is specific to dma used for the onboard
ESP scsi on sun3x */
diff --git a/arch/m68k/include/asm/fb.h b/arch/m68k/include/asm/fb.h
index 24273fc7ad91..9941b7434b69 100644
--- a/arch/m68k/include/asm/fb.h
+++ b/arch/m68k/include/asm/fb.h
@@ -5,26 +5,27 @@
#include <asm/page.h>
#include <asm/setup.h>
-struct file;
-
-static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
- unsigned long off)
+static inline pgprot_t pgprot_framebuffer(pgprot_t prot,
+ unsigned long vm_start, unsigned long vm_end,
+ unsigned long offset)
{
#ifdef CONFIG_MMU
#ifdef CONFIG_SUN3
- pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE;
+ pgprot_val(prot) |= SUN3_PAGE_NOCACHE;
#else
if (CPU_IS_020_OR_030)
- pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
+ pgprot_val(prot) |= _PAGE_NOCACHE030;
if (CPU_IS_040_OR_060) {
- pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
+ pgprot_val(prot) &= _CACHEMASK040;
/* Use no-cache mode, serialized */
- pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
+ pgprot_val(prot) |= _PAGE_NOCACHE_S;
}
#endif /* CONFIG_SUN3 */
#endif /* CONFIG_MMU */
+
+ return prot;
}
-#define fb_pgprotect fb_pgprotect
+#define pgprot_framebuffer pgprot_framebuffer
#include <asm-generic/fb.h>
diff --git a/arch/m68k/include/asm/io_mm.h b/arch/m68k/include/asm/io_mm.h
index 6a0abd4846c6..47525f2a57e1 100644
--- a/arch/m68k/include/asm/io_mm.h
+++ b/arch/m68k/include/asm/io_mm.h
@@ -272,20 +272,20 @@ static inline void isa_delay(void)
#define isa_outsb(port, buf, nr) raw_outsb(isa_itb(port), (u8 *)(buf), (nr))
#define isa_insw(port, buf, nr) \
- (ISA_SEX ? raw_insw(isa_itw(port), (u16 *)(buf), (nr)) : \
- raw_insw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
+ (ISA_SEX ? raw_insw(isa_itw(port), (u16 *)(buf), (nr)) : \
+ raw_insw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
#define isa_outsw(port, buf, nr) \
- (ISA_SEX ? raw_outsw(isa_itw(port), (u16 *)(buf), (nr)) : \
- raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
+ (ISA_SEX ? raw_outsw(isa_itw(port), (u16 *)(buf), (nr)) : \
+ raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
#define isa_insl(port, buf, nr) \
- (ISA_SEX ? raw_insl(isa_itl(port), (u32 *)(buf), (nr)) : \
- raw_insw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
+ (ISA_SEX ? raw_insl(isa_itl(port), (u32 *)(buf), (nr)) : \
+ raw_insw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
#define isa_outsl(port, buf, nr) \
- (ISA_SEX ? raw_outsl(isa_itl(port), (u32 *)(buf), (nr)) : \
- raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
+ (ISA_SEX ? raw_outsl(isa_itl(port), (u32 *)(buf), (nr)) : \
+ raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
#ifdef CONFIG_ATARI_ROM_ISA
@@ -297,14 +297,14 @@ static inline void isa_delay(void)
#define isa_rom_insb(port, buf, nr) raw_rom_insb(isa_itb(port), (u8 *)(buf), (nr))
#define isa_rom_insw(port, buf, nr) \
- (ISA_SEX ? raw_rom_insw(isa_itw(port), (u16 *)(buf), (nr)) : \
- raw_rom_insw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
+ (ISA_SEX ? raw_rom_insw(isa_itw(port), (u16 *)(buf), (nr)) : \
+ raw_rom_insw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
#define isa_rom_outsb(port, buf, nr) raw_rom_outsb(isa_itb(port), (u8 *)(buf), (nr))
#define isa_rom_outsw(port, buf, nr) \
- (ISA_SEX ? raw_rom_outsw(isa_itw(port), (u16 *)(buf), (nr)) : \
- raw_rom_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
+ (ISA_SEX ? raw_rom_outsw(isa_itw(port), (u16 *)(buf), (nr)) : \
+ raw_rom_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
#endif /* CONFIG_ATARI_ROM_ISA */
#endif /* CONFIG_ISA || CONFIG_ATARI_ROM_ISA */
diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h
index 7829e955ca04..14992fde7340 100644
--- a/arch/m68k/include/asm/irq.h
+++ b/arch/m68k/include/asm/irq.h
@@ -2,6 +2,9 @@
#ifndef _M68K_IRQ_H_
#define _M68K_IRQ_H_
+#include <linux/atomic.h>
+#include <linux/linkage.h>
+
/*
* This should be the same as the max(NUM_X_SOURCES) for all the
* different m68k hosts compiled into the kernel.
@@ -59,6 +62,8 @@
struct irq_data;
struct irq_chip;
struct irq_desc;
+struct pt_regs;
+
extern unsigned int m68k_irq_startup(struct irq_data *data);
extern unsigned int m68k_irq_startup_irq(unsigned int irq);
extern void m68k_irq_shutdown(struct irq_data *data);
diff --git a/arch/m68k/include/asm/kexec.h b/arch/m68k/include/asm/kexec.h
index f5a8b2defa4b..3b0b64f0a353 100644
--- a/arch/m68k/include/asm/kexec.h
+++ b/arch/m68k/include/asm/kexec.h
@@ -2,7 +2,7 @@
#ifndef _ASM_M68K_KEXEC_H
#define _ASM_M68K_KEXEC_H
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
/* Maximum physical address we can use pages from */
#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
@@ -25,6 +25,6 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
#endif /* __ASSEMBLY__ */
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
#endif /* _ASM_M68K_KEXEC_H */
diff --git a/arch/m68k/include/asm/mcfgpio.h b/arch/m68k/include/asm/mcfgpio.h
index 7abd322c019f..019f24439546 100644
--- a/arch/m68k/include/asm/mcfgpio.h
+++ b/arch/m68k/include/asm/mcfgpio.h
@@ -8,10 +8,6 @@
#ifndef mcfgpio_h
#define mcfgpio_h
-#ifdef CONFIG_GPIOLIB
-#include <linux/gpio.h>
-#else
-
int __mcfgpio_get_value(unsigned gpio);
void __mcfgpio_set_value(unsigned gpio, int value);
int __mcfgpio_direction_input(unsigned gpio);
@@ -19,6 +15,10 @@ int __mcfgpio_direction_output(unsigned gpio, int value);
int __mcfgpio_request(unsigned gpio);
void __mcfgpio_free(unsigned gpio);
+#ifdef CONFIG_GPIOLIB
+#include <linux/gpio.h>
+#else
+
/* our alternate 'gpiolib' functions */
static inline int __gpio_get_value(unsigned gpio)
{
diff --git a/arch/m68k/include/asm/nettel.h b/arch/m68k/include/asm/nettel.h
index 45716ead7b9d..3bd4b7a4613f 100644
--- a/arch/m68k/include/asm/nettel.h
+++ b/arch/m68k/include/asm/nettel.h
@@ -14,9 +14,8 @@
#define nettel_h
/****************************************************************************/
-
/****************************************************************************/
-#ifdef CONFIG_NETtel
+#if defined(CONFIG_NETtel) || defined(CONFIG_CLEOPATRA)
/****************************************************************************/
#ifdef CONFIG_COLDFIRE
@@ -26,7 +25,7 @@
#endif
/*---------------------------------------------------------------------------*/
-#if defined(CONFIG_M5307)
+#if defined(CONFIG_M5307) || defined(CONFIG_M5407)
/*
* NETtel/5307 based hardware first. DTR/DCD lines are wired to
* GPIO lines. Most of the LED's are driver through a latch
diff --git a/arch/m68k/include/asm/oplib.h b/arch/m68k/include/asm/oplib.h
index 48cb4fd09f8d..6d5ea67c65d0 100644
--- a/arch/m68k/include/asm/oplib.h
+++ b/arch/m68k/include/asm/oplib.h
@@ -9,6 +9,8 @@
#ifndef __SPARC_OPLIB_H
#define __SPARC_OPLIB_H
+#include <linux/compiler.h>
+
#include <asm/openprom.h>
/* The master romvec pointer... */
@@ -149,7 +151,7 @@ extern char prom_getchar(void);
extern void prom_putchar(char character);
/* Prom's internal printf routine, don't use in kernel/boot code. */
-void prom_printf(char *fmt, ...);
+__printf(1, 2) void prom_printf(char *fmt, ...);
/* Query for input device type */
diff --git a/arch/m68k/include/asm/page_mm.h b/arch/m68k/include/asm/page_mm.h
index 363aa0f9ba8a..e0ae4d5fc985 100644
--- a/arch/m68k/include/asm/page_mm.h
+++ b/arch/m68k/include/asm/page_mm.h
@@ -13,17 +13,16 @@
#ifdef CPU_M68040_OR_M68060_ONLY
static inline void copy_page(void *to, void *from)
{
- unsigned long tmp;
-
- __asm__ __volatile__("1:\t"
- ".chip 68040\n\t"
- "move16 %1@+,%0@+\n\t"
- "move16 %1@+,%0@+\n\t"
- ".chip 68k\n\t"
- "dbra %2,1b\n\t"
- : "=a" (to), "=a" (from), "=d" (tmp)
- : "0" (to), "1" (from) , "2" (PAGE_SIZE / 32 - 1)
- );
+ unsigned long tmp;
+
+ __asm__ __volatile__("1:\t"
+ ".chip 68040\n\t"
+ "move16 %1@+,%0@+\n\t"
+ "move16 %1@+,%0@+\n\t"
+ ".chip 68k\n\t"
+ "dbra %2,1b\n\t"
+ : "=a" (to), "=a" (from), "=d" (tmp)
+ : "0" (to), "1" (from), "2" (PAGE_SIZE / 32 - 1));
}
static inline void clear_page(void *page)
@@ -95,23 +94,23 @@ static inline void *__va(unsigned long paddr)
#define __pa(x) ___pa((unsigned long)(x))
static inline unsigned long ___pa(unsigned long x)
{
- if(x == 0)
- return 0;
- if(x >= PAGE_OFFSET)
- return (x-PAGE_OFFSET);
- else
- return (x+0x2000000);
+ if (x == 0)
+ return 0;
+ if (x >= PAGE_OFFSET)
+ return (x - PAGE_OFFSET);
+ else
+ return (x + 0x2000000);
}
static inline void *__va(unsigned long x)
{
- if(x == 0)
- return (void *)0;
+ if (x == 0)
+ return (void *)0;
- if(x < 0x2000000)
- return (void *)(x+PAGE_OFFSET);
- else
- return (void *)(x-0x2000000);
+ if (x < 0x2000000)
+ return (void *)(x + PAGE_OFFSET);
+ else
+ return (void *)(x - 0x2000000);
}
#endif /* CONFIG_SUN3 */
diff --git a/arch/m68k/include/asm/pgtable.h b/arch/m68k/include/asm/pgtable.h
index ad15d655a9bf..27525c6a12fd 100644
--- a/arch/m68k/include/asm/pgtable.h
+++ b/arch/m68k/include/asm/pgtable.h
@@ -1,6 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __M68K_PGTABLE_H
+#define __M68K_PGTABLE_H
+
#ifdef __uClinux__
#include <asm/pgtable_no.h>
#else
#include <asm/pgtable_mm.h>
#endif
+
+#ifndef __ASSEMBLY__
+extern void paging_init(void);
+#endif
+
+#endif /* __M68K_PGTABLE_H */
diff --git a/arch/m68k/include/asm/pgtable_no.h b/arch/m68k/include/asm/pgtable_no.h
index fc044df52b96..1a86c15b9008 100644
--- a/arch/m68k/include/asm/pgtable_no.h
+++ b/arch/m68k/include/asm/pgtable_no.h
@@ -28,7 +28,6 @@
#define PAGE_READONLY __pgprot(0)
#define PAGE_KERNEL __pgprot(0)
-extern void paging_init(void);
#define swapper_pg_dir ((pgd_t *) 0)
/*
diff --git a/arch/m68k/include/asm/raw_io.h b/arch/m68k/include/asm/raw_io.h
index 3ba40bc1dfaa..95a6ff694a68 100644
--- a/arch/m68k/include/asm/raw_io.h
+++ b/arch/m68k/include/asm/raw_io.h
@@ -17,15 +17,15 @@
* two accesses to memory, which may be undesirable for some devices.
*/
#define in_8(addr) \
- ({ u8 __v = (*(__force volatile u8 *) (unsigned long)(addr)); __v; })
+ ({ u8 __v = (*(__force const volatile u8 *) (unsigned long)(addr)); __v; })
#define in_be16(addr) \
- ({ u16 __v = (*(__force volatile u16 *) (unsigned long)(addr)); __v; })
+ ({ u16 __v = (*(__force const volatile u16 *) (unsigned long)(addr)); __v; })
#define in_be32(addr) \
- ({ u32 __v = (*(__force volatile u32 *) (unsigned long)(addr)); __v; })
+ ({ u32 __v = (*(__force const volatile u32 *) (unsigned long)(addr)); __v; })
#define in_le16(addr) \
- ({ u16 __v = le16_to_cpu(*(__force volatile __le16 *) (unsigned long)(addr)); __v; })
+ ({ u16 __v = le16_to_cpu(*(__force const volatile __le16 *) (unsigned long)(addr)); __v; })
#define in_le32(addr) \
- ({ u32 __v = le32_to_cpu(*(__force volatile __le32 *) (unsigned long)(addr)); __v; })
+ ({ u32 __v = le32_to_cpu(*(__force const volatile __le32 *) (unsigned long)(addr)); __v; })
#define out_8(addr,b) (void)((*(__force volatile u8 *) (unsigned long)(addr)) = (b))
#define out_be16(addr,w) (void)((*(__force volatile u16 *) (unsigned long)(addr)) = (w))
@@ -73,11 +73,11 @@
#if defined(CONFIG_ATARI_ROM_ISA)
#define rom_in_8(addr) \
- ({ u16 __v = (*(__force volatile u16 *) (addr)); __v >>= 8; __v; })
+ ({ u16 __v = (*(__force const volatile u16 *) (addr)); __v >>= 8; __v; })
#define rom_in_be16(addr) \
- ({ u16 __v = (*(__force volatile u16 *) (addr)); __v; })
+ ({ u16 __v = (*(__force const volatile u16 *) (addr)); __v; })
#define rom_in_le16(addr) \
- ({ u16 __v = le16_to_cpu(*(__force volatile u16 *) (addr)); __v; })
+ ({ u16 __v = le16_to_cpu(*(__force const volatile u16 *) (addr)); __v; })
#define rom_out_8(addr, b) \
(void)({u8 __maybe_unused __w, __v = (b); u32 _addr = ((u32) (addr)); \
@@ -98,7 +98,8 @@
#define raw_rom_outw(val, port) rom_out_be16((port), (val))
#endif /* CONFIG_ATARI_ROM_ISA */
-static inline void raw_insb(volatile u8 __iomem *port, u8 *buf, unsigned int len)
+static inline void raw_insb(const volatile u8 __iomem *port, u8 *buf,
+ unsigned int len)
{
unsigned int i;
@@ -146,7 +147,7 @@ static inline void raw_outsb(volatile u8 __iomem *port, const u8 *buf,
}
}
-static inline void raw_insw(volatile u16 __iomem *port, u16 *buf, unsigned int nr)
+static inline void raw_insw(volatile const u16 __iomem *port, u16 *buf, unsigned int nr)
{
unsigned int tmp;
@@ -225,7 +226,7 @@ static inline void raw_outsw(volatile u16 __iomem *port, const u16 *buf,
}
}
-static inline void raw_insl(volatile u32 __iomem *port, u32 *buf, unsigned int nr)
+static inline void raw_insl(const volatile u32 __iomem *port, u32 *buf, unsigned int nr)
{
unsigned int tmp;
@@ -305,7 +306,7 @@ static inline void raw_outsl(volatile u32 __iomem *port, const u32 *buf,
}
-static inline void raw_insw_swapw(volatile u16 __iomem *port, u16 *buf,
+static inline void raw_insw_swapw(const volatile u16 __iomem *port, u16 *buf,
unsigned int nr)
{
if ((nr) % 8)
@@ -413,7 +414,8 @@ static inline void raw_outsw_swapw(volatile u16 __iomem *port, const u16 *buf,
#if defined(CONFIG_ATARI_ROM_ISA)
-static inline void raw_rom_insb(volatile u8 __iomem *port, u8 *buf, unsigned int len)
+static inline void raw_rom_insb(const volatile u8 __iomem *port, u8 *buf,
+ unsigned int len)
{
unsigned int i;
@@ -430,7 +432,7 @@ static inline void raw_rom_outsb(volatile u8 __iomem *port, const u8 *buf,
rom_out_8(port, *buf++);
}
-static inline void raw_rom_insw(volatile u16 __iomem *port, u16 *buf,
+static inline void raw_rom_insw(const volatile u16 __iomem *port, u16 *buf,
unsigned int nr)
{
unsigned int i;
@@ -448,7 +450,7 @@ static inline void raw_rom_outsw(volatile u16 __iomem *port, const u16 *buf,
rom_out_be16(port, *buf++);
}
-static inline void raw_rom_insw_swapw(volatile u16 __iomem *port, u16 *buf,
+static inline void raw_rom_insw_swapw(const volatile u16 __iomem *port, u16 *buf,
unsigned int nr)
{
unsigned int i;
diff --git a/arch/m68k/include/asm/sun3_pgalloc.h b/arch/m68k/include/asm/sun3_pgalloc.h
index ff48573db2c0..4a137eecb6fe 100644
--- a/arch/m68k/include/asm/sun3_pgalloc.h
+++ b/arch/m68k/include/asm/sun3_pgalloc.h
@@ -41,12 +41,12 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t page
static inline pgd_t * pgd_alloc(struct mm_struct *mm)
{
- pgd_t *new_pgd;
+ pgd_t *new_pgd;
- new_pgd = (pgd_t *)get_zeroed_page(GFP_KERNEL);
- memcpy(new_pgd, swapper_pg_dir, PAGE_SIZE);
- memset(new_pgd, 0, (PAGE_OFFSET >> PGDIR_SHIFT));
- return new_pgd;
+ new_pgd = (pgd_t *)get_zeroed_page(GFP_KERNEL);
+ memcpy(new_pgd, swapper_pg_dir, PAGE_SIZE);
+ memset(new_pgd, 0, (PAGE_OFFSET >> PGDIR_SHIFT));
+ return new_pgd;
}
#endif /* SUN3_PGALLOC_H */
diff --git a/arch/m68k/include/asm/syscalls.h b/arch/m68k/include/asm/syscalls.h
new file mode 100644
index 000000000000..fb3639acd07b
--- /dev/null
+++ b/arch/m68k/include/asm/syscalls.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _ASM_M68K_SYSCALLS_H
+#define _ASM_M68K_SYSCALLS_H
+
+#include <linux/compiler_types.h>
+#include <linux/linkage.h>
+
+asmlinkage int sys_cacheflush(unsigned long addr, int scope, int cache,
+ unsigned long len);
+asmlinkage int sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3,
+ int d4, int d5, unsigned long __user *mem);
+asmlinkage int sys_getpagesize(void);
+asmlinkage unsigned long sys_get_thread_area(void);
+asmlinkage int sys_set_thread_area(unsigned long tp);
+asmlinkage int sys_atomic_barrier(void);
+
+#include <asm-generic/syscalls.h>
+
+#endif /* _ASM_M68K_SYSCALLS_H */
diff --git a/arch/m68k/include/asm/tlbflush.h b/arch/m68k/include/asm/tlbflush.h
index b882e2f4f551..6d42e2906887 100644
--- a/arch/m68k/include/asm/tlbflush.h
+++ b/arch/m68k/include/asm/tlbflush.h
@@ -112,53 +112,51 @@ extern unsigned char pmeg_ctx[SUN3_PMEGS_NUM];
sun?) */
static inline void flush_tlb_all(void)
{
- unsigned long addr;
- unsigned char ctx, oldctx;
-
- oldctx = sun3_get_context();
- for(addr = 0x00000000; addr < TASK_SIZE; addr += SUN3_PMEG_SIZE) {
- for(ctx = 0; ctx < 8; ctx++) {
- sun3_put_context(ctx);
- sun3_put_segmap(addr, SUN3_INVALID_PMEG);
- }
- }
-
- sun3_put_context(oldctx);
- /* erase all of the userspace pmeg maps, we've clobbered them
- all anyway */
- for(addr = 0; addr < SUN3_INVALID_PMEG; addr++) {
- if(pmeg_alloc[addr] == 1) {
- pmeg_alloc[addr] = 0;
- pmeg_ctx[addr] = 0;
- pmeg_vaddr[addr] = 0;
- }
- }
+ unsigned long addr;
+ unsigned char ctx, oldctx;
+ oldctx = sun3_get_context();
+ for (addr = 0x00000000; addr < TASK_SIZE; addr += SUN3_PMEG_SIZE) {
+ for (ctx = 0; ctx < 8; ctx++) {
+ sun3_put_context(ctx);
+ sun3_put_segmap(addr, SUN3_INVALID_PMEG);
+ }
+ }
+
+ sun3_put_context(oldctx);
+ /* erase all of the userspace pmeg maps, we've clobbered them
+ all anyway */
+ for (addr = 0; addr < SUN3_INVALID_PMEG; addr++) {
+ if (pmeg_alloc[addr] == 1) {
+ pmeg_alloc[addr] = 0;
+ pmeg_ctx[addr] = 0;
+ pmeg_vaddr[addr] = 0;
+ }
+ }
}
/* Clear user TLB entries within the context named in mm */
static inline void flush_tlb_mm (struct mm_struct *mm)
{
- unsigned char oldctx;
- unsigned char seg;
- unsigned long i;
-
- oldctx = sun3_get_context();
- sun3_put_context(mm->context);
+ unsigned char oldctx;
+ unsigned char seg;
+ unsigned long i;
- for(i = 0; i < TASK_SIZE; i += SUN3_PMEG_SIZE) {
- seg = sun3_get_segmap(i);
- if(seg == SUN3_INVALID_PMEG)
- continue;
+ oldctx = sun3_get_context();
+ sun3_put_context(mm->context);
- sun3_put_segmap(i, SUN3_INVALID_PMEG);
- pmeg_alloc[seg] = 0;
- pmeg_ctx[seg] = 0;
- pmeg_vaddr[seg] = 0;
- }
+ for (i = 0; i < TASK_SIZE; i += SUN3_PMEG_SIZE) {
+ seg = sun3_get_segmap(i);
+ if (seg == SUN3_INVALID_PMEG)
+ continue;
- sun3_put_context(oldctx);
+ sun3_put_segmap(i, SUN3_INVALID_PMEG);
+ pmeg_alloc[seg] = 0;
+ pmeg_ctx[seg] = 0;
+ pmeg_vaddr[seg] = 0;
+ }
+ sun3_put_context(oldctx);
}
/* Flush a single TLB page. In this case, we're limited to flushing a
@@ -208,6 +206,7 @@ static inline void flush_tlb_range (struct vm_area_struct *vma,
next:
start += SUN3_PMEG_SIZE;
}
+ sun3_put_context(oldctx);
}
static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index af015447dfb4..f335bf3268a1 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -23,9 +23,9 @@ obj-$(CONFIG_MMU_MOTOROLA) += ints.o vectors.o
obj-$(CONFIG_MMU_SUN3) += ints.o vectors.o
obj-$(CONFIG_PCI) += pcibios.o
-obj-$(CONFIG_HAS_DMA) += dma.o
+obj-$(CONFIG_M68K_NONCOHERENT_DMA) += dma.o
-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_BOOTINFO_PROC) += bootinfo_proc.o
obj-$(CONFIG_UBOOT) += uboot.o
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
index 2e192a5df949..16063783aa80 100644
--- a/arch/m68k/kernel/dma.c
+++ b/arch/m68k/kernel/dma.c
@@ -4,20 +4,11 @@
* for more details.
*/
-#undef DEBUG
-
#include <linux/dma-map-ops.h>
-#include <linux/device.h>
#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/export.h>
-
#include <asm/cacheflush.h>
-#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE)
+#ifndef CONFIG_COLDFIRE
void arch_dma_prep_coherent(struct page *page, size_t size)
{
cache_push(page_to_phys(page), size);
@@ -33,29 +24,6 @@ pgprot_t pgprot_dmacoherent(pgprot_t prot)
}
return prot;
}
-#else
-void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
- gfp_t gfp, unsigned long attrs)
-{
- void *ret;
-
- if (dev == NULL || (*dev->dma_mask < 0xffffffff))
- gfp |= GFP_DMA;
- ret = (void *)__get_free_pages(gfp, get_order(size));
-
- if (ret != NULL) {
- memset(ret, 0, size);
- *dma_handle = virt_to_phys(ret);
- }
- return ret;
-}
-
-void arch_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, unsigned long attrs)
-{
- free_pages((unsigned long)vaddr, get_order(size));
-}
-
#endif /* CONFIG_MMU && !CONFIG_COLDFIRE */
void arch_sync_dma_for_device(phys_addr_t handle, size_t size,
diff --git a/arch/m68k/kernel/early_printk.c b/arch/m68k/kernel/early_printk.c
index 7d3fe08a48eb..3cc944df04f6 100644
--- a/arch/m68k/kernel/early_printk.c
+++ b/arch/m68k/kernel/early_printk.c
@@ -12,8 +12,8 @@
#include <linux/string.h>
#include <asm/setup.h>
-extern void mvme16x_cons_write(struct console *co,
- const char *str, unsigned count);
+
+#include "../mvme16x/mvme16x.h"
asmlinkage void __init debug_cons_nputs(const char *s, unsigned n);
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 4dd2fd7acba9..3bcdd32a6b36 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -1,13 +1,10 @@
-/* -*- mode: asm -*-
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * -*- mode: asm -*-
*
* linux/arch/m68k/kernel/entry.S
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file README.legal in the main directory of this archive
- * for more details.
- *
* Linux/m68k support by Hamish Macdonald
*
* 68060 fixes by Jesper Skov
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 9e812d8606be..852255cf60de 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -1,4 +1,5 @@
-/* -*- mode: asm -*-
+/* SPDX-License-Identifier: GPL-2.0-or-later
+** -*- mode: asm -*-
**
** head.S -- This file contains the initial boot code for the
** Linux/68k kernel.
@@ -25,11 +26,6 @@
** for linux-2.1.115
** 1999/02/11 Richard Zidlicky: added Q40 support (initial version 99/01/01)
** 2004/05/13 Kars de Jong: Finalised HP300 support
-**
-** This file is subject to the terms and conditions of the GNU General Public
-** License. See the file README.legal in the main directory of this archive
-** for more details.
-**
*/
/*
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 5b8d66fbf383..cf2b13488476 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -26,6 +26,8 @@
#include <asm/q40ints.h>
#endif
+#include "ints.h"
+
extern u32 auto_irqhandler_fixup[];
extern u16 user_irqvec_fixup[];
diff --git a/arch/m68k/kernel/ints.h b/arch/m68k/kernel/ints.h
new file mode 100644
index 000000000000..ecac6011c1a4
--- /dev/null
+++ b/arch/m68k/kernel/ints.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <linux/linkage.h>
+
+struct pt_regs;
+
+asmlinkage void handle_badint(struct pt_regs *regs);
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index e06ce147c0b7..2584e94e2134 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -38,6 +38,7 @@
#include <asm/machdep.h>
#include <asm/setup.h>
+#include "process.h"
asmlinkage void ret_from_fork(void);
asmlinkage void ret_from_kernel_thread(void);
diff --git a/arch/m68k/kernel/process.h b/arch/m68k/kernel/process.h
new file mode 100644
index 000000000000..d31745f2e64b
--- /dev/null
+++ b/arch/m68k/kernel/process.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/linkage.h>
+
+struct pt_regs;
+
+asmlinkage int m68k_clone(struct pt_regs *regs);
+asmlinkage int m68k_clone3(struct pt_regs *regs);
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index cd0172d29430..c20d590e4297 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -26,6 +26,8 @@
#include <asm/page.h>
#include <asm/processor.h>
+#include "ptrace.h"
+
/*
* does not yet catch signals sent when the child dies.
* in exit.c or in signal.c.
diff --git a/arch/m68k/kernel/ptrace.h b/arch/m68k/kernel/ptrace.h
new file mode 100644
index 000000000000..77018037f10f
--- /dev/null
+++ b/arch/m68k/kernel/ptrace.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <linux/linkage.h>
+
+asmlinkage int syscall_trace_enter(void);
+asmlinkage void syscall_trace_leave(void);
diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
index 6f1ae01f322c..10310b04f77d 100644
--- a/arch/m68k/kernel/setup_mm.c
+++ b/arch/m68k/kernel/setup_mm.c
@@ -107,8 +107,6 @@ EXPORT_SYMBOL(isa_sex);
#define MASK_256K 0xfffc0000
-extern void paging_init(void);
-
static void __init m68k_parse_bootinfo(const struct bi_record *record)
{
const struct bi_record *first_record = record;
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index ba468b5f3f0b..e628b859ef21 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -51,6 +51,8 @@
#include <asm/ucontext.h>
#include <asm/cacheflush.h>
+#include "signal.h"
+
#ifdef CONFIG_MMU
/*
@@ -1109,7 +1111,7 @@ static void do_signal(struct pt_regs *regs)
restore_saved_sigmask();
}
-void do_notify_resume(struct pt_regs *regs)
+asmlinkage void do_notify_resume(struct pt_regs *regs)
{
if (test_thread_flag(TIF_NOTIFY_SIGNAL) ||
test_thread_flag(TIF_SIGPENDING))
diff --git a/arch/m68k/kernel/signal.h b/arch/m68k/kernel/signal.h
new file mode 100644
index 000000000000..498d84f82820
--- /dev/null
+++ b/arch/m68k/kernel/signal.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <linux/linkage.h>
+
+asmlinkage void do_notify_resume(struct pt_regs *regs);
+asmlinkage void *do_sigreturn(struct pt_regs *regs, struct switch_stack *sw);
+asmlinkage void *do_rt_sigreturn(struct pt_regs *regs, struct switch_stack *sw);
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index c586034d2a7a..1af5e6082467 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -27,6 +27,7 @@
#include <asm/cachectl.h>
#include <asm/traps.h>
#include <asm/page.h>
+#include <asm/syscalls.h>
#include <asm/unistd.h>
#include <asm/cacheflush.h>
@@ -34,8 +35,7 @@
#include <asm/tlb.h>
-asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
- unsigned long error_code);
+#include "../mm/fault.h"
asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl
index 259ceb125367..7a4b780e82cb 100644
--- a/arch/m68k/kernel/syscalls/syscall.tbl
+++ b/arch/m68k/kernel/syscalls/syscall.tbl
@@ -255,7 +255,7 @@
245 common io_cancel sys_io_cancel
246 common fadvise64 sys_fadvise64
247 common exit_group sys_exit_group
-248 common lookup_dcookie sys_lookup_dcookie
+248 common lookup_dcookie sys_ni_syscall
249 common epoll_create sys_epoll_create
250 common epoll_ctl sys_epoll_ctl
251 common epoll_wait sys_epoll_wait
@@ -452,3 +452,7 @@
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
451 common cachestat sys_cachestat
452 common fchmodat2 sys_fchmodat2
+453 common map_shadow_stack sys_map_shadow_stack
+454 common futex_wake sys_futex_wake
+455 common futex_wait sys_futex_wait
+456 common futex_requeue sys_futex_requeue
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index a700807c9b6d..53d0cf343d90 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -41,6 +41,9 @@
#include <asm/siginfo.h>
#include <asm/tlbflush.h>
+#include "traps.h"
+#include "../mm/fault.h"
+
static const char *vec_names[] = {
[VEC_RESETSP] = "RESET SP",
[VEC_RESETPC] = "RESET PC",
@@ -124,10 +127,6 @@ static const char *space_names[] = {
};
void die_if_kernel(char *,struct pt_regs *,int);
-asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
- unsigned long error_code);
-int send_fault_sig(struct pt_regs *regs);
-
asmlinkage void trap_c(struct frame *fp);
#if defined (CONFIG_M68060)
@@ -365,7 +364,7 @@ disable_wb:
#if defined(CONFIG_SUN3)
#include <asm/sun3mmu.h>
-extern int mmu_emu_handle_fault (unsigned long, int, int);
+#include "../sun3/sun3.h"
/* sun3 version of bus_error030 */
@@ -487,10 +486,10 @@ static inline void bus_error030 (struct frame *fp)
if (buserr_type & SUN3_BUSERR_INVALID) {
if (!mmu_emu_handle_fault(addr, 1, 0))
do_page_fault (&fp->ptregs, addr, 0);
- } else {
+ } else {
pr_debug("protection fault on insn access (segv).\n");
force_sig (SIGSEGV);
- }
+ }
}
#else
#if defined(CPU_M68020_OR_M68030)
@@ -851,9 +850,9 @@ void show_registers(struct pt_regs *regs)
pr_info("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
pr_info("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2);
pr_info("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
- regs->d0, regs->d1, regs->d2, regs->d3);
+ regs->d0, regs->d1, regs->d2, regs->d3);
pr_info("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
- regs->d4, regs->d5, regs->a0, regs->a1);
+ regs->d4, regs->d5, regs->a0, regs->a1);
pr_info("Process %s (pid: %d, task=%p)\n",
current->comm, task_pid_nr(current), current);
@@ -965,7 +964,7 @@ void show_stack(struct task_struct *task, unsigned long *stack,
* real 68k parts, but it won't hurt either.
*/
-void bad_super_trap (struct frame *fp)
+static void bad_super_trap(struct frame *fp)
{
int vector = (fp->ptregs.vector >> 2) & 0xff;
diff --git a/arch/m68k/kernel/traps.h b/arch/m68k/kernel/traps.h
new file mode 100644
index 000000000000..6414b4a0e558
--- /dev/null
+++ b/arch/m68k/kernel/traps.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <linux/linkage.h>
+
+struct frame;
+
+asmlinkage void buserr_c(struct frame *fp);
+asmlinkage void fpemu_signal(int signal, int code, void *addr);
+asmlinkage void fpsp040_die(void);
+asmlinkage void set_esp0(unsigned long ssp);
diff --git a/arch/m68k/kernel/uboot.c b/arch/m68k/kernel/uboot.c
index 928dbd33fc4a..8bb1cb3a7490 100644
--- a/arch/m68k/kernel/uboot.c
+++ b/arch/m68k/kernel/uboot.c
@@ -27,6 +27,7 @@
#include <asm/irq.h>
#include <asm/machdep.h>
#include <asm/sections.h>
+#include <asm/bootinfo.h>
/*
* parse_uboot_commandline
@@ -63,20 +64,22 @@ static void __init parse_uboot_commandline(char *commandp, int size)
{
extern unsigned long _init_sp;
unsigned long *sp;
- unsigned long uboot_kbd;
- unsigned long uboot_initrd_start, uboot_initrd_end;
unsigned long uboot_cmd_start, uboot_cmd_end;
+#if defined(CONFIG_BLK_DEV_INITRD)
+ unsigned long uboot_initrd_start, uboot_initrd_end;
+#endif /* if defined(CONFIG_BLK_DEV_INITRD) */
sp = (unsigned long *)_init_sp;
- uboot_kbd = sp[1];
- uboot_initrd_start = sp[2];
- uboot_initrd_end = sp[3];
uboot_cmd_start = sp[4];
uboot_cmd_end = sp[5];
if (uboot_cmd_start && uboot_cmd_end)
strncpy(commandp, (const char *)uboot_cmd_start, size);
+
#if defined(CONFIG_BLK_DEV_INITRD)
+ uboot_initrd_start = sp[2];
+ uboot_initrd_end = sp[3];
+
if (uboot_initrd_start && uboot_initrd_end &&
(uboot_initrd_end > uboot_initrd_start)) {
initrd_start = uboot_initrd_start;
diff --git a/arch/m68k/kernel/vectors.c b/arch/m68k/kernel/vectors.c
index 322c977bb9ec..667e848070f4 100644
--- a/arch/m68k/kernel/vectors.c
+++ b/arch/m68k/kernel/vectors.c
@@ -17,6 +17,7 @@
/*
* Sets up all exception vectors
*/
+#include <linux/cpu.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/linkage.h>
@@ -27,6 +28,8 @@
#include <asm/fpu.h>
#include <asm/traps.h>
+#include "vectors.h"
+
/* assembler routines */
asmlinkage void system_call(void);
asmlinkage void buserr(void);
diff --git a/arch/m68k/kernel/vectors.h b/arch/m68k/kernel/vectors.h
new file mode 100644
index 000000000000..897330737ec5
--- /dev/null
+++ b/arch/m68k/kernel/vectors.h
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+void base_trap_init(void);
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
index eca17f14b4d5..9158688e6cc6 100644
--- a/arch/m68k/lib/Makefile
+++ b/arch/m68k/lib/Makefile
@@ -4,8 +4,7 @@
# Makefile for m68k-specific library files..
#
-lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
- memcpy.o memset.o memmove.o
+lib-y := muldi3.o memcpy.o memset.o memmove.o
lib-$(CONFIG_MMU) += uaccess.o
lib-$(CONFIG_CPU_HAS_NO_MULDIV64) += mulsi3.o divsi3.o udivsi3.o
diff --git a/arch/m68k/lib/ashldi3.c b/arch/m68k/lib/ashldi3.c
deleted file mode 100644
index ac08f8141390..000000000000
--- a/arch/m68k/lib/ashldi3.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* ashrdi3.c extracted from gcc-2.95.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details. */
-
-#include <linux/compiler.h>
-#include <linux/export.h>
-
-#define BITS_PER_UNIT 8
-
-typedef int SItype __mode(SI);
-typedef unsigned int USItype __mode(SI);
-typedef int DItype __mode(DI);
-typedef int word_type __mode(__word__);
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
- struct DIstruct s;
- DItype ll;
-} DIunion;
-
-DItype
-__ashldi3 (DItype u, word_type b)
-{
- DIunion w;
- word_type bm;
- DIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- w.s.low = 0;
- w.s.high = (USItype)uu.s.low << -bm;
- }
- else
- {
- USItype carries = (USItype)uu.s.low >> bm;
- w.s.low = (USItype)uu.s.low << b;
- w.s.high = ((USItype)uu.s.high << b) | carries;
- }
-
- return w.ll;
-}
-EXPORT_SYMBOL(__ashldi3);
diff --git a/arch/m68k/lib/ashrdi3.c b/arch/m68k/lib/ashrdi3.c
deleted file mode 100644
index 5837b1dd3334..000000000000
--- a/arch/m68k/lib/ashrdi3.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details. */
-
-#include <linux/compiler.h>
-#include <linux/export.h>
-
-#define BITS_PER_UNIT 8
-
-typedef int SItype __mode(SI);
-typedef unsigned int USItype __mode(SI);
-typedef int DItype __mode(DI);
-typedef int word_type __mode(__word__);
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
- struct DIstruct s;
- DItype ll;
-} DIunion;
-
-DItype
-__ashrdi3 (DItype u, word_type b)
-{
- DIunion w;
- word_type bm;
- DIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- /* w.s.high = 1..1 or 0..0 */
- w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
- w.s.low = uu.s.high >> -bm;
- }
- else
- {
- USItype carries = (USItype)uu.s.high << bm;
- w.s.high = uu.s.high >> b;
- w.s.low = ((USItype)uu.s.low >> b) | carries;
- }
-
- return w.ll;
-}
-EXPORT_SYMBOL(__ashrdi3);
diff --git a/arch/m68k/lib/lshrdi3.c b/arch/m68k/lib/lshrdi3.c
deleted file mode 100644
index 7f40566be6c8..000000000000
--- a/arch/m68k/lib/lshrdi3.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details. */
-
-#include <linux/compiler.h>
-#include <linux/export.h>
-
-#define BITS_PER_UNIT 8
-
-typedef int SItype __mode(SI);
-typedef unsigned int USItype __mode(SI);
-typedef int DItype __mode(DI);
-typedef int word_type __mode(__word__);
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
- struct DIstruct s;
- DItype ll;
-} DIunion;
-
-DItype
-__lshrdi3 (DItype u, word_type b)
-{
- DIunion w;
- word_type bm;
- DIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- w.s.high = 0;
- w.s.low = (USItype)uu.s.high >> -bm;
- }
- else
- {
- USItype carries = (USItype)uu.s.high << bm;
- w.s.high = (USItype)uu.s.high >> b;
- w.s.low = ((USItype)uu.s.low >> b) | carries;
- }
-
- return w.ll;
-}
-EXPORT_SYMBOL(__lshrdi3);
diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c
index eb7d9d86ff66..5012a9b218c7 100644
--- a/arch/m68k/lib/muldi3.c
+++ b/arch/m68k/lib/muldi3.c
@@ -16,6 +16,7 @@ GNU General Public License for more details. */
#include <linux/compiler.h>
#include <linux/export.h>
+#include <linux/libgcc.h>
#ifdef CONFIG_CPU_HAS_NO_MULDIV64
diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c
index a7d280220662..5c97a7058bcd 100644
--- a/arch/m68k/mac/baboon.c
+++ b/arch/m68k/mac/baboon.c
@@ -15,6 +15,8 @@
#include <asm/macints.h>
#include <asm/mac_baboon.h>
+#include "mac.h"
+
int baboon_present;
static volatile struct baboon *baboon;
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 382f656c29ea..e324410ef239 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -50,22 +50,14 @@
#include <asm/mac_psc.h>
#include <asm/config.h>
+#include "mac.h"
+
/* Mac bootinfo struct */
struct mac_booter_data mac_bi_data;
/* The phys. video addr. - might be bogus on some machines */
static unsigned long mac_orig_videoaddr;
-extern int mac_hwclk(int, struct rtc_time *);
-extern void iop_init(void);
-extern void via_init(void);
-extern void via_init_clock(void);
-extern void oss_init(void);
-extern void psc_init(void);
-extern void baboon_init(void);
-
-extern void mac_mksound(unsigned int, unsigned int);
-
static void mac_get_model(char *str);
static void mac_identify(void);
static void mac_report_hardware(void);
@@ -958,7 +950,7 @@ static const struct pata_platform_info mac_pata_data __initconst = {
.ioport_shift = 2,
};
-int __init mac_platform_init(void)
+static int __init mac_platform_init(void)
{
phys_addr_t swim_base = 0;
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
index 010b3b5ae8e8..a92740d530ac 100644
--- a/arch/m68k/mac/iop.c
+++ b/arch/m68k/mac/iop.c
@@ -119,6 +119,8 @@
#include <asm/macints.h>
#include <asm/mac_iop.h>
+#include "mac.h"
+
#ifdef DEBUG
#define iop_pr_debug(fmt, ...) \
printk(KERN_DEBUG "%s: " fmt, __func__, ##__VA_ARGS__)
diff --git a/arch/m68k/mac/mac.h b/arch/m68k/mac/mac.h
new file mode 100644
index 000000000000..d3d142cea3b4
--- /dev/null
+++ b/arch/m68k/mac/mac.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+struct rtc_time;
+
+/* baboon.c */
+void baboon_init(void);
+
+/* iop.c */
+void iop_init(void);
+
+/* misc.c */
+int mac_hwclk(int op, struct rtc_time *t);
+
+/* macboing.c */
+void mac_mksound(unsigned int freq, unsigned int length);
+
+/* oss.c */
+void oss_init(void);
+
+/* psc.c */
+void psc_init(void);
+
+/* via.c */
+void via_init(void);
+void via_init_clock(void);
diff --git a/arch/m68k/mac/macboing.c b/arch/m68k/mac/macboing.c
index 4de6229c7bfd..faea2265a540 100644
--- a/arch/m68k/mac/macboing.c
+++ b/arch/m68k/mac/macboing.c
@@ -16,6 +16,8 @@
#include <asm/macintosh.h>
#include <asm/mac_asc.h>
+#include "mac.h"
+
static int mac_asc_inited;
/*
* dumb triangular wave table
@@ -23,15 +25,6 @@ static int mac_asc_inited;
static __u8 mac_asc_wave_tab[ 0x800 ];
/*
- * Alan's original sine table; needs interpolating to 0x800
- * (hint: interpolate or hardwire [0 -> Pi/2[, it's symmetric)
- */
-static const signed char sine_data[] = {
- 0, 39, 75, 103, 121, 127, 121, 103, 75, 39,
- 0, -39, -75, -103, -121, -127, -121, -103, -75, -39
-};
-
-/*
* where the ASC hides ...
*/
static volatile __u8* mac_asc_regs = ( void* )0x50F14000;
diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c
index c7cb29f0ff01..4c8f8cbfa05f 100644
--- a/arch/m68k/mac/misc.c
+++ b/arch/m68k/mac/misc.c
@@ -25,6 +25,8 @@
#include <asm/machdep.h>
+#include "mac.h"
+
/*
* Offset between Unix time (1970-based) and Mac time (1904-based). Cuda and PMU
* times wrap in 2040. If we need to handle later times, the read_time functions
@@ -554,7 +556,7 @@ static void unmktime(time64_t time, long offset,
/* Leap years. */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
- int days, rem, y, wday, yday;
+ int days, rem, y, wday;
const unsigned short int *ip;
days = div_u64_rem(time, SECS_PER_DAY, &rem);
@@ -592,7 +594,6 @@ static void unmktime(time64_t time, long offset,
y = yg;
}
*yearp = y - 1900;
- yday = days; /* day in the year. Not currently used. */
ip = __mon_yday[__isleap(y)];
for (y = 11; days < (long int) ip[y]; --y)
continue;
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index 921e6c092f2c..1641607f300d 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -27,6 +27,8 @@
#include <asm/mac_via.h>
#include <asm/mac_oss.h>
+#include "mac.h"
+
int oss_present;
volatile struct mac_oss *oss;
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c
index 0d0965b19c09..b4183cf66efe 100644
--- a/arch/m68k/mac/psc.c
+++ b/arch/m68k/mac/psc.c
@@ -26,6 +26,8 @@
#include <asm/macints.h>
#include <asm/mac_psc.h>
+#include "mac.h"
+
#define DEBUG_PSC
volatile __u8 *psc;
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 3d11d6219cdd..01e6b0e37f8d 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -38,6 +38,8 @@
#include <asm/mac_psc.h>
#include <asm/mac_oss.h>
+#include "mac.h"
+
volatile __u8 *via1, *via2;
int rbv_present;
int via_alt_mapping;
diff --git a/arch/m68k/math-emu/fp_arith.c b/arch/m68k/math-emu/fp_arith.c
index f4a06492cd7a..799c450fe322 100644
--- a/arch/m68k/math-emu/fp_arith.c
+++ b/arch/m68k/math-emu/fp_arith.c
@@ -28,8 +28,7 @@ const struct fp_ext fp_Inf =
/* let's start with the easy ones */
-struct fp_ext *
-fp_fabs(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fabs(struct fp_ext *dest, struct fp_ext *src)
{
dprint(PINSTR, "fabs\n");
@@ -40,8 +39,7 @@ fp_fabs(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fneg(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fneg(struct fp_ext *dest, struct fp_ext *src)
{
dprint(PINSTR, "fneg\n");
@@ -57,8 +55,7 @@ fp_fneg(struct fp_ext *dest, struct fp_ext *src)
/* fp_fadd: Implements the kernel of the FADD, FSADD, FDADD, FSUB,
FDSUB, and FCMP instructions. */
-struct fp_ext *
-fp_fadd(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fadd(struct fp_ext *dest, struct fp_ext *src)
{
int diff;
@@ -117,8 +114,7 @@ fp_fadd(struct fp_ext *dest, struct fp_ext *src)
Remember that the arguments are in assembler-syntax order! */
-struct fp_ext *
-fp_fsub(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsub(struct fp_ext *dest, struct fp_ext *src)
{
dprint(PINSTR, "fsub ");
@@ -127,8 +123,7 @@ fp_fsub(struct fp_ext *dest, struct fp_ext *src)
}
-struct fp_ext *
-fp_fcmp(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fcmp(struct fp_ext *dest, struct fp_ext *src)
{
dprint(PINSTR, "fcmp ");
@@ -137,8 +132,7 @@ fp_fcmp(struct fp_ext *dest, struct fp_ext *src)
return fp_fadd(&FPDATA->temp[1], src);
}
-struct fp_ext *
-fp_ftst(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_ftst(struct fp_ext *dest, struct fp_ext *src)
{
dprint(PINSTR, "ftst\n");
@@ -147,8 +141,7 @@ fp_ftst(struct fp_ext *dest, struct fp_ext *src)
return src;
}
-struct fp_ext *
-fp_fmul(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fmul(struct fp_ext *dest, struct fp_ext *src)
{
union fp_mant128 temp;
int exp;
@@ -225,8 +218,7 @@ fp_fmul(struct fp_ext *dest, struct fp_ext *src)
Note that the order of the operands is counter-intuitive: instead
of src / dest, the result is actually dest / src. */
-struct fp_ext *
-fp_fdiv(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fdiv(struct fp_ext *dest, struct fp_ext *src)
{
union fp_mant128 temp;
int exp;
@@ -306,8 +298,7 @@ fp_fdiv(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fsglmul(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsglmul(struct fp_ext *dest, struct fp_ext *src)
{
int exp;
@@ -363,8 +354,7 @@ fp_fsglmul(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fsgldiv(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsgldiv(struct fp_ext *dest, struct fp_ext *src)
{
int exp;
unsigned long quot, rem;
@@ -573,8 +563,8 @@ static void fp_roundint(struct fp_ext *dest, int mode)
(which are exactly the same, except for the rounding used on the
intermediate value) */
-static struct fp_ext *
-modrem_kernel(struct fp_ext *dest, struct fp_ext *src, int mode)
+static struct fp_ext *modrem_kernel(struct fp_ext *dest, struct fp_ext *src,
+ int mode)
{
struct fp_ext tmp;
@@ -607,8 +597,7 @@ modrem_kernel(struct fp_ext *dest, struct fp_ext *src, int mode)
fmod(src,dest) = (dest - (src * floor(dest / src))) */
-struct fp_ext *
-fp_fmod(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fmod(struct fp_ext *dest, struct fp_ext *src)
{
dprint(PINSTR, "fmod\n");
return modrem_kernel(dest, src, FPCR_ROUND_RZ);
@@ -619,15 +608,13 @@ fp_fmod(struct fp_ext *dest, struct fp_ext *src)
frem(src,dest) = (dest - (src * round(dest / src)))
*/
-struct fp_ext *
-fp_frem(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_frem(struct fp_ext *dest, struct fp_ext *src)
{
dprint(PINSTR, "frem\n");
return modrem_kernel(dest, src, FPCR_ROUND_RN);
}
-struct fp_ext *
-fp_fint(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fint(struct fp_ext *dest, struct fp_ext *src)
{
dprint(PINSTR, "fint\n");
@@ -638,8 +625,7 @@ fp_fint(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fintrz(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fintrz(struct fp_ext *dest, struct fp_ext *src)
{
dprint(PINSTR, "fintrz\n");
@@ -650,8 +636,7 @@ fp_fintrz(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fscale(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fscale(struct fp_ext *dest, struct fp_ext *src)
{
int scale, oldround;
diff --git a/arch/m68k/math-emu/fp_arith.h b/arch/m68k/math-emu/fp_arith.h
index 0fd3ed217f66..3f9c58b6d504 100644
--- a/arch/m68k/math-emu/fp_arith.h
+++ b/arch/m68k/math-emu/fp_arith.h
@@ -12,39 +12,28 @@
*/
-#ifndef FP_ARITH_H
-#define FP_ARITH_H
+#ifndef _FP_ARITH_H
+#define _FP_ARITH_H
/* easy ones */
-struct fp_ext *
-fp_fabs(struct fp_ext *dest, struct fp_ext *src);
-struct fp_ext *
-fp_fneg(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fabs(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fneg(struct fp_ext *dest, struct fp_ext *src);
/* straightforward arithmetic */
-struct fp_ext *
-fp_fadd(struct fp_ext *dest, struct fp_ext *src);
-struct fp_ext *
-fp_fsub(struct fp_ext *dest, struct fp_ext *src);
-struct fp_ext *
-fp_fcmp(struct fp_ext *dest, struct fp_ext *src);
-struct fp_ext *
-fp_ftst(struct fp_ext *dest, struct fp_ext *src);
-struct fp_ext *
-fp_fmul(struct fp_ext *dest, struct fp_ext *src);
-struct fp_ext *
-fp_fdiv(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fadd(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fsub(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fcmp(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_ftst(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fmul(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fdiv(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fsglmul(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fsgldiv(struct fp_ext *dest, struct fp_ext *src);
/* ones that do rounding and integer conversions */
-struct fp_ext *
-fp_fmod(struct fp_ext *dest, struct fp_ext *src);
-struct fp_ext *
-fp_frem(struct fp_ext *dest, struct fp_ext *src);
-struct fp_ext *
-fp_fint(struct fp_ext *dest, struct fp_ext *src);
-struct fp_ext *
-fp_fintrz(struct fp_ext *dest, struct fp_ext *src);
-struct fp_ext *
-fp_fscale(struct fp_ext *dest, struct fp_ext *src);
-
-#endif /* FP_ARITH__H */
+struct fp_ext *fp_fmod(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_frem(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fint(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fintrz(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fscale(struct fp_ext *dest, struct fp_ext *src);
+
+#endif /* _FP_ARITH_H */
diff --git a/arch/m68k/math-emu/fp_log.c b/arch/m68k/math-emu/fp_log.c
index 0663067870f2..71a8fc25575a 100644
--- a/arch/m68k/math-emu/fp_log.c
+++ b/arch/m68k/math-emu/fp_log.c
@@ -1,6 +1,6 @@
/*
- fp_trig.c: floating-point math routines for the Linux-m68k
+ fp_log.c: floating-point math routines for the Linux-m68k
floating point emulator.
Copyright (c) 1998-1999 David Huggins-Daines / Roman Zippel.
@@ -15,18 +15,15 @@
*/
+#include "fp_arith.h"
#include "fp_emu.h"
+#include "fp_log.h"
-static const struct fp_ext fp_one =
-{
+static const struct fp_ext fp_one = {
.exp = 0x3fff,
};
-extern struct fp_ext *fp_fadd(struct fp_ext *dest, const struct fp_ext *src);
-extern struct fp_ext *fp_fdiv(struct fp_ext *dest, const struct fp_ext *src);
-
-struct fp_ext *
-fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
{
struct fp_ext tmp, src2;
int i, exp;
@@ -70,7 +67,8 @@ fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
* sqrt(x) = 1 + 1/2*(x-1)
* = 1/2*(1+x)
*/
- fp_fadd(dest, &fp_one);
+ /* It is safe to cast away the constness, as fp_one is normalized */
+ fp_fadd(dest, (struct fp_ext *)&fp_one);
dest->exp--; /* * 1/2 */
/*
@@ -98,8 +96,7 @@ fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fetoxm1(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fetoxm1(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fetoxm1\n");
@@ -108,8 +105,7 @@ fp_fetoxm1(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fetox(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fetox(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fetox\n");
@@ -118,8 +114,7 @@ fp_fetox(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_ftwotox(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_ftwotox(struct fp_ext *dest, struct fp_ext *src)
{
uprint("ftwotox\n");
@@ -128,8 +123,7 @@ fp_ftwotox(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_ftentox(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_ftentox(struct fp_ext *dest, struct fp_ext *src)
{
uprint("ftentox\n");
@@ -138,8 +132,7 @@ fp_ftentox(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_flogn(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_flogn(struct fp_ext *dest, struct fp_ext *src)
{
uprint("flogn\n");
@@ -148,8 +141,7 @@ fp_flogn(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_flognp1(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_flognp1(struct fp_ext *dest, struct fp_ext *src)
{
uprint("flognp1\n");
@@ -158,8 +150,7 @@ fp_flognp1(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_flog10(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_flog10(struct fp_ext *dest, struct fp_ext *src)
{
uprint("flog10\n");
@@ -168,8 +159,7 @@ fp_flog10(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_flog2(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_flog2(struct fp_ext *dest, struct fp_ext *src)
{
uprint("flog2\n");
@@ -178,8 +168,7 @@ fp_flog2(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fgetexp(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fgetexp(struct fp_ext *dest, struct fp_ext *src)
{
dprint(PINSTR, "fgetexp\n");
@@ -199,8 +188,7 @@ fp_fgetexp(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fgetman(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fgetman(struct fp_ext *dest, struct fp_ext *src)
{
dprint(PINSTR, "fgetman\n");
diff --git a/arch/m68k/math-emu/fp_log.h b/arch/m68k/math-emu/fp_log.h
new file mode 100644
index 000000000000..c2bcfff11994
--- /dev/null
+++ b/arch/m68k/math-emu/fp_log.h
@@ -0,0 +1,44 @@
+/*
+
+ fp_log.h: floating-point math routines for the Linux-m68k
+ floating point emulator.
+
+ Copyright (c) 1998-1999 David Huggins-Daines / Roman Zippel.
+
+ I hereby give permission, free of charge, to copy, modify, and
+ redistribute this software, in source or binary form, provided that
+ the above copyright notice and the following disclaimer are included
+ in all such copies.
+
+ THIS SOFTWARE IS PROVIDED "AS IS", WITH ABSOLUTELY NO WARRANTY, REAL
+ OR IMPLIED.
+
+*/
+
+#ifndef _FP_LOG_H
+#define _FP_LOG_H
+
+#include "fp_emu.h"
+
+/* floating point logarithmic instructions:
+
+ the arguments to these are in the "internal" extended format, that
+ is, an "exploded" version of the 96-bit extended fp format used by
+ the 68881.
+
+ they return a status code, which should end up in %d0, if all goes
+ well. */
+
+struct fp_ext *fp_fsqrt(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fetoxm1(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fetox(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_ftwotox(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_ftentox(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_flogn(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_flognp1(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_flog10(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_flog2(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fgetexp(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fgetman(struct fp_ext *dest, struct fp_ext *src);
+
+#endif /* _FP_LOG_H */
diff --git a/arch/m68k/math-emu/fp_trig.c b/arch/m68k/math-emu/fp_trig.c
index 6361d0784df2..5f49de373753 100644
--- a/arch/m68k/math-emu/fp_trig.c
+++ b/arch/m68k/math-emu/fp_trig.c
@@ -18,8 +18,7 @@
#include "fp_emu.h"
#include "fp_trig.h"
-struct fp_ext *
-fp_fsin(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsin(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fsin\n");
@@ -28,8 +27,7 @@ fp_fsin(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fcos(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fcos(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fcos\n");
@@ -38,8 +36,7 @@ fp_fcos(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_ftan(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_ftan(struct fp_ext *dest, struct fp_ext *src)
{
uprint("ftan\n");
@@ -48,8 +45,7 @@ fp_ftan(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fasin(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fasin(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fasin\n");
@@ -58,8 +54,7 @@ fp_fasin(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_facos(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_facos(struct fp_ext *dest, struct fp_ext *src)
{
uprint("facos\n");
@@ -68,8 +63,7 @@ fp_facos(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fatan(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fatan(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fatan\n");
@@ -78,8 +72,7 @@ fp_fatan(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fsinh(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsinh(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fsinh\n");
@@ -88,8 +81,7 @@ fp_fsinh(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fcosh(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fcosh(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fcosh\n");
@@ -98,8 +90,7 @@ fp_fcosh(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_ftanh(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_ftanh(struct fp_ext *dest, struct fp_ext *src)
{
uprint("ftanh\n");
@@ -108,8 +99,7 @@ fp_ftanh(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fatanh(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fatanh(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fatanh\n");
@@ -118,64 +108,56 @@ fp_fatanh(struct fp_ext *dest, struct fp_ext *src)
return dest;
}
-struct fp_ext *
-fp_fsincos0(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsincos0(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fsincos0\n");
return dest;
}
-struct fp_ext *
-fp_fsincos1(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsincos1(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fsincos1\n");
return dest;
}
-struct fp_ext *
-fp_fsincos2(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsincos2(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fsincos2\n");
return dest;
}
-struct fp_ext *
-fp_fsincos3(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsincos3(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fsincos3\n");
return dest;
}
-struct fp_ext *
-fp_fsincos4(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsincos4(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fsincos4\n");
return dest;
}
-struct fp_ext *
-fp_fsincos5(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsincos5(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fsincos5\n");
return dest;
}
-struct fp_ext *
-fp_fsincos6(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsincos6(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fsincos6\n");
return dest;
}
-struct fp_ext *
-fp_fsincos7(struct fp_ext *dest, struct fp_ext *src)
+struct fp_ext *fp_fsincos7(struct fp_ext *dest, struct fp_ext *src)
{
uprint("fsincos7\n");
diff --git a/arch/m68k/math-emu/fp_trig.h b/arch/m68k/math-emu/fp_trig.h
index af8b247e9c98..1aae8ab1d41b 100644
--- a/arch/m68k/math-emu/fp_trig.h
+++ b/arch/m68k/math-emu/fp_trig.h
@@ -15,8 +15,8 @@
*/
-#ifndef FP_TRIG_H
-#define FP_TRIG_H
+#ifndef _FP_TRIG_H
+#define _FP_TRIG_H
#include "fp_emu.h"
@@ -29,4 +29,23 @@
they return a status code, which should end up in %d0, if all goes
well. */
-#endif /* FP_TRIG__H */
+struct fp_ext *fp_fsin(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fcos(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_ftan(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fasin(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_facos(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fatan(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fsinh(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fcosh(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_ftanh(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fatanh(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fsincos0(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fsincos1(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fsincos2(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fsincos3(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fsincos4(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fsincos5(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fsincos6(struct fp_ext *dest, struct fp_ext *src);
+struct fp_ext *fp_fsincos7(struct fp_ext *dest, struct fp_ext *src);
+
+#endif /* _FP_TRIG_H */
diff --git a/arch/m68k/math-emu/multi_arith.h b/arch/m68k/math-emu/multi_arith.h
index 232f58fe3483..f7d9e49fe259 100644
--- a/arch/m68k/math-emu/multi_arith.h
+++ b/arch/m68k/math-emu/multi_arith.h
@@ -15,8 +15,10 @@
implement the subset of integer arithmetic that we need in order to
multiply, divide, and normalize 128-bit unsigned mantissae. */
-#ifndef MULTI_ARITH_H
-#define MULTI_ARITH_H
+#ifndef _MULTI_ARITH_H
+#define _MULTI_ARITH_H
+
+#include "fp_emu.h"
static inline void fp_denormalize(struct fp_ext *reg, unsigned int cnt)
{
@@ -285,4 +287,4 @@ static inline void fp_putmant128(struct fp_ext *dest, union fp_mant128 *src,
}
}
-#endif /* MULTI_ARITH_H */
+#endif /* _MULTI_ARITH_H */
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index c290c5c0cfb9..fa3c5f38d989 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -17,6 +17,8 @@
#include <asm/setup.h>
#include <asm/traps.h>
+#include "fault.h"
+
extern void die_if_kernel(char *, struct pt_regs *, long);
int send_fault_sig(struct pt_regs *regs)
diff --git a/arch/m68k/mm/fault.h b/arch/m68k/mm/fault.h
new file mode 100644
index 000000000000..dab14ef7d4a1
--- /dev/null
+++ b/arch/m68k/mm/fault.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+struct pt_regs;
+
+int do_page_fault(struct pt_regs *regs, unsigned long address,
+ unsigned long error_code);
+int send_fault_sig(struct pt_regs *regs);
diff --git a/arch/m68k/mm/hwtest.c b/arch/m68k/mm/hwtest.c
index fe99aa99987e..8ee7a3368688 100644
--- a/arch/m68k/mm/hwtest.c
+++ b/arch/m68k/mm/hwtest.c
@@ -26,6 +26,8 @@
#include <linux/module.h>
+#include <asm/hwtest.h>
+
int hwreg_present(volatile void *regp)
{
int ret = 0;
diff --git a/arch/m68k/mm/mcfmmu.c b/arch/m68k/mm/mcfmmu.c
index a6efaa7cacde..9a6fa342e872 100644
--- a/arch/m68k/mm/mcfmmu.c
+++ b/arch/m68k/mm/mcfmmu.c
@@ -38,7 +38,7 @@ void __init paging_init(void)
pgd_t *pg_dir;
pte_t *pg_table;
unsigned long address, size;
- unsigned long next_pgtable, bootmem_end;
+ unsigned long next_pgtable;
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
int i;
@@ -57,7 +57,6 @@ void __init paging_init(void)
panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
__func__, size, PAGE_SIZE);
- bootmem_end = (next_pgtable + size + PAGE_SIZE) & PAGE_MASK;
pg_dir += PAGE_OFFSET >> PGDIR_SHIFT;
address = PAGE_OFFSET;
diff --git a/arch/m68k/mm/sun3kmap.c b/arch/m68k/mm/sun3kmap.c
index 4f2a7ef8348b..ac091892d82f 100644
--- a/arch/m68k/mm/sun3kmap.c
+++ b/arch/m68k/mm/sun3kmap.c
@@ -18,11 +18,9 @@
#include <asm/io.h>
#include <asm/sun3mmu.h>
-#undef SUN3_KMAP_DEBUG
+#include "../sun3/sun3.h"
-#ifdef SUN3_KMAP_DEBUG
-extern void print_pte_vaddr(unsigned long vaddr);
-#endif
+#undef SUN3_KMAP_DEBUG
extern void mmu_emu_map_pmeg (int context, int vaddr);
diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c
index c5e6a23e0262..494739c1783e 100644
--- a/arch/m68k/mm/sun3mmu.c
+++ b/arch/m68k/mm/sun3mmu.c
@@ -24,7 +24,7 @@
#include <asm/machdep.h>
#include <asm/io.h>
-extern void mmu_emu_init (unsigned long bootmem_end);
+#include "../sun3/sun3.h"
const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 4e6218115f43..8b5dc07f0811 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* arch/m68k/mvme147/config.c
*
@@ -7,10 +8,6 @@
* Based on:
*
* Copyright (C) 1993 Hamish Macdonald
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file README.legal in the main directory of this archive
- * for more details.
*/
#include <linux/types.h>
@@ -73,7 +70,7 @@ static void mvme147_get_model(char *model)
* the mvme147 IRQ handling routines.
*/
-void __init mvme147_init_IRQ(void)
+static void __init mvme147_init_IRQ(void)
{
m68k_setup_user_interrupt(VEC_USER, 192);
}
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index f00c7aa058de..d1fbd1704d65 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* arch/m68k/mvme16x/config.c
*
@@ -8,10 +9,6 @@
* linux/amiga/config.c
*
* Copyright (C) 1993 Hamish Macdonald
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file README.legal in the main directory of this archive
- * for more details.
*/
#include <linux/types.h>
@@ -38,6 +35,8 @@
#include <asm/mvme16xhw.h>
#include <asm/config.h>
+#include "mvme16x.h"
+
extern t_bdid mvme_bdid;
static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
@@ -208,7 +207,6 @@ static void __init mvme16x_init_IRQ (void)
void mvme16x_cons_write(struct console *co, const char *str, unsigned count)
{
volatile unsigned char *base_addr = (u_char *)CD2401_ADDR;
- volatile u_char sink;
u_char ier;
int port;
u_char do_lf = 0;
@@ -229,7 +227,7 @@ void mvme16x_cons_write(struct console *co, const char *str, unsigned count)
if (in_8(PCCSCCTICR) & 0x20)
{
/* We have a Tx int. Acknowledge it */
- sink = in_8(PCCTPIACKR);
+ in_8(PCCTPIACKR);
if ((base_addr[CyLICR] >> 2) == port) {
if (i == count) {
/* Last char of string is now output */
diff --git a/arch/m68k/mvme16x/mvme16x.h b/arch/m68k/mvme16x/mvme16x.h
new file mode 100644
index 000000000000..159c34b70039
--- /dev/null
+++ b/arch/m68k/mvme16x/mvme16x.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+struct console;
+
+/* config.c */
+void mvme16x_cons_write(struct console *co, const char *str, unsigned count);
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index c78ee709b458..de7870ad2a30 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* arch/m68k/q40/config.c
*
@@ -6,10 +7,6 @@
* originally based on:
*
* linux/bvme/config.c
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file README.legal in the main directory of this archive
- * for more details.
*/
#include <linux/errno.h>
@@ -36,16 +33,14 @@
#include <asm/q40_master.h>
#include <asm/config.h>
-extern void q40_init_IRQ(void);
+#include "q40.h"
+
static void q40_get_model(char *model);
-extern void q40_sched_init(void);
static int q40_hwclk(int, struct rtc_time *);
static int q40_get_rtc_pll(struct rtc_pll_info *pll);
static int q40_set_rtc_pll(struct rtc_pll_info *pll);
-extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/);
-
static void q40_mem_console_write(struct console *co, const char *b,
unsigned int count);
diff --git a/arch/m68k/q40/q40.h b/arch/m68k/q40/q40.h
new file mode 100644
index 000000000000..3146679bde0d
--- /dev/null
+++ b/arch/m68k/q40/q40.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/* q40ints.c */
+void q40_init_IRQ(void);
+void q40_mksound(unsigned int hz, unsigned int ticks);
+void q40_sched_init(void);
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index 127d7ecdbd49..10f1f294e91f 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -24,6 +24,8 @@
#include <asm/q40_master.h>
#include <asm/q40ints.h>
+#include "q40.h"
+
/*
* Q40 IRQs are defined as follows:
* 3,4,5,6,7,10,11,14,15 : ISA dev IRQs
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index 203f428a0344..cd8af809e0ca 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/memblock.h>
#include <linux/platform_device.h>
+#include <linux/linkage.h>
#include <asm/oplib.h>
#include <asm/setup.h>
@@ -32,12 +33,13 @@
#include <asm/irq.h>
#include <asm/sections.h>
#include <asm/sun3ints.h>
+#include <asm/config.h>
+
+#include "sun3.h"
char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
static void sun3_sched_init(void);
-extern void sun3_get_model (char* model);
-extern int sun3_hwclk(int set, struct rtc_time *t);
volatile char* clock_va;
extern unsigned long availmem;
@@ -48,7 +50,7 @@ static void sun3_get_hardware_list(struct seq_file *m)
seq_printf(m, "PROM Revision:\t%s\n", romvec->pv_monid);
}
-void __init sun3_init(void)
+asmlinkage void __init sun3_init(void)
{
unsigned char enable_register;
int i;
@@ -107,13 +109,10 @@ static void sun3_halt (void)
static void __init sun3_bootmem_alloc(unsigned long memory_start,
unsigned long memory_end)
{
- unsigned long start_page;
-
/* align start/end to page boundaries */
memory_start = ((memory_start + (PAGE_SIZE-1)) & PAGE_MASK);
memory_end = memory_end & PAGE_MASK;
- start_page = __pa(memory_start) >> PAGE_SHIFT;
max_pfn = num_pages = __pa(memory_end) >> PAGE_SHIFT;
high_memory = (void *)memory_end;
@@ -200,7 +199,7 @@ static const struct resource sun3_scsi_rsrc[] __initconst = {
},
};
-int __init sun3_platform_init(void)
+static int __init sun3_platform_init(void)
{
switch (idprom->id_machtype) {
case SM_SUN3 | SM_3_160:
diff --git a/arch/m68k/sun3/idprom.c b/arch/m68k/sun3/idprom.c
index 1ace5353d78f..ca633a5f5eb1 100644
--- a/arch/m68k/sun3/idprom.c
+++ b/arch/m68k/sun3/idprom.c
@@ -17,6 +17,8 @@
#include <asm/idprom.h>
#include <asm/machines.h> /* Fun with Sun released architectures. */
+#include "sun3.h"
+
struct idprom *idprom;
EXPORT_SYMBOL(idprom);
@@ -83,7 +85,7 @@ static void __init display_system_type(unsigned char machtype)
prom_halt();
}
-void sun3_get_model(unsigned char* model)
+void sun3_get_model(char *model)
{
register int i;
diff --git a/arch/m68k/sun3/intersil.c b/arch/m68k/sun3/intersil.c
index 8fc74864de81..29674cfa9bb3 100644
--- a/arch/m68k/sun3/intersil.c
+++ b/arch/m68k/sun3/intersil.c
@@ -17,6 +17,7 @@
#include <asm/intersil.h>
#include <asm/machdep.h>
+#include "sun3.h"
/* bits to set for start/run of the intersil */
#define STOP_VAL (INTERSIL_STOP | INTERSIL_INT_ENABLE | INTERSIL_24H_MODE)
diff --git a/arch/m68k/sun3/leds.c b/arch/m68k/sun3/leds.c
index 7c67b58ebf13..4bb95318fd54 100644
--- a/arch/m68k/sun3/leds.c
+++ b/arch/m68k/sun3/leds.c
@@ -3,6 +3,8 @@
#include <asm/sun3mmu.h>
#include <asm/io.h>
+#include "sun3.h"
+
void sun3_leds(unsigned char byte)
{
unsigned char dfc;
diff --git a/arch/m68k/sun3/mmu_emu.c b/arch/m68k/sun3/mmu_emu.c
index 7321b3b76283..119bd32efcfb 100644
--- a/arch/m68k/sun3/mmu_emu.c
+++ b/arch/m68k/sun3/mmu_emu.c
@@ -27,6 +27,7 @@
#include <asm/mmu_context.h>
#include <asm/dvma.h>
+#include "sun3.h"
#undef DEBUG_MMU_EMU
#define DEBUG_PROM_MAPS
@@ -67,7 +68,7 @@ static unsigned char ctx_avail = CONTEXTS_NUM-1;
unsigned long rom_pages[256];
/* Print a PTE value in symbolic form. For debugging. */
-void print_pte (pte_t pte)
+static void print_pte(pte_t pte)
{
#if 0
/* Verbose version. */
@@ -206,32 +207,32 @@ void __init mmu_emu_init(unsigned long bootmem_end)
context for when they're cleared */
void clear_context(unsigned long context)
{
- unsigned char oldctx;
- unsigned long i;
+ unsigned char oldctx;
+ unsigned long i;
- if(context) {
- if(!ctx_alloc[context])
- panic("%s: context not allocated\n", __func__);
+ if (context) {
+ if (!ctx_alloc[context])
+ panic("%s: context not allocated\n", __func__);
- ctx_alloc[context]->context = SUN3_INVALID_CONTEXT;
- ctx_alloc[context] = (struct mm_struct *)0;
- ctx_avail++;
- }
+ ctx_alloc[context]->context = SUN3_INVALID_CONTEXT;
+ ctx_alloc[context] = (struct mm_struct *)0;
+ ctx_avail++;
+ }
- oldctx = sun3_get_context();
+ oldctx = sun3_get_context();
- sun3_put_context(context);
+ sun3_put_context(context);
- for(i = 0; i < SUN3_INVALID_PMEG; i++) {
- if((pmeg_ctx[i] == context) && (pmeg_alloc[i] == 1)) {
- sun3_put_segmap(pmeg_vaddr[i], SUN3_INVALID_PMEG);
- pmeg_ctx[i] = 0;
- pmeg_alloc[i] = 0;
- pmeg_vaddr[i] = 0;
- }
- }
+ for (i = 0; i < SUN3_INVALID_PMEG; i++) {
+ if ((pmeg_ctx[i] == context) && (pmeg_alloc[i] == 1)) {
+ sun3_put_segmap(pmeg_vaddr[i], SUN3_INVALID_PMEG);
+ pmeg_ctx[i] = 0;
+ pmeg_alloc[i] = 0;
+ pmeg_vaddr[i] = 0;
+ }
+ }
- sun3_put_context(oldctx);
+ sun3_put_context(oldctx);
}
/* gets an empty context. if full, kills the next context listed to
diff --git a/arch/m68k/sun3/prom/printf.c b/arch/m68k/sun3/prom/printf.c
index b6724cc66795..db5537ef1250 100644
--- a/arch/m68k/sun3/prom/printf.c
+++ b/arch/m68k/sun3/prom/printf.c
@@ -25,15 +25,14 @@ prom_printf(char *fmt, ...)
{
va_list args;
char ch, *bptr;
- int i;
va_start(args, fmt);
#ifdef CONFIG_KGDB
ppbuf[0] = 'O';
- i = vsprintf(ppbuf + 1, fmt, args) + 1;
+ vsprintf(ppbuf + 1, fmt, args) + 1;
#else
- i = vsprintf(ppbuf, fmt, args);
+ vsprintf(ppbuf, fmt, args);
#endif
bptr = ppbuf;
diff --git a/arch/m68k/sun3/sun3.h b/arch/m68k/sun3/sun3.h
new file mode 100644
index 000000000000..8d98c0aaedc0
--- /dev/null
+++ b/arch/m68k/sun3/sun3.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/linkage.h>
+
+struct rtc_time;
+
+/* config.c */
+asmlinkage void sun3_init(void);
+
+/* idprom.c */
+void sun3_get_model(char *model);
+
+/* intersil.c */
+int sun3_hwclk(int set, struct rtc_time *t);
+
+/* leds.c */
+void sun3_leds(unsigned char byte);
+
+/* mmu_emu.c */
+void mmu_emu_init(unsigned long bootmem_end);
+int mmu_emu_handle_fault(unsigned long vaddr, int read_flag, int kernel_fault);
+void print_pte_vaddr(unsigned long vaddr);
diff --git a/arch/m68k/sun3/sun3dvma.c b/arch/m68k/sun3/sun3dvma.c
index 4b560f4d3960..6ebf52740ad7 100644
--- a/arch/m68k/sun3/sun3dvma.c
+++ b/arch/m68k/sun3/sun3dvma.c
@@ -20,18 +20,6 @@
#undef DVMA_DEBUG
-#ifdef CONFIG_SUN3X
-extern void dvma_unmap_iommu(unsigned long baddr, int len);
-#else
-static inline void dvma_unmap_iommu(unsigned long a, int b)
-{
-}
-#endif
-
-#ifdef CONFIG_SUN3
-extern void sun3_dvma_init(void);
-#endif
-
static unsigned long *iommu_use;
#define dvma_index(baddr) ((baddr - DVMA_START) >> DVMA_PAGE_SHIFT)
@@ -205,9 +193,7 @@ static inline int free_baddr(unsigned long baddr)
unsigned long len;
struct hole *hole;
struct list_head *cur;
- unsigned long orig_baddr;
- orig_baddr = baddr;
len = dvma_entry_use(baddr);
dvma_entry_use(baddr) = 0;
baddr &= DVMA_PAGE_MASK;
@@ -274,10 +260,7 @@ void __init dvma_init(void)
dvma_unmap_iommu(DVMA_START, DVMA_SIZE);
-#ifdef CONFIG_SUN3
sun3_dvma_init();
-#endif
-
}
unsigned long dvma_map_align(unsigned long kaddr, int len, int align)
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index 36cc280a4505..32eaf55f87be 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -17,7 +17,7 @@
#include <asm/irq_regs.h>
#include <linux/seq_file.h>
-extern void sun3_leds (unsigned char);
+#include "sun3.h"
void sun3_disable_interrupts(void)
{
@@ -29,11 +29,11 @@ void sun3_enable_interrupts(void)
sun3_enable_irq(0);
}
-static int led_pattern[8] = {
- ~(0x80), ~(0x01),
- ~(0x40), ~(0x02),
- ~(0x20), ~(0x04),
- ~(0x10), ~(0x08)
+static unsigned char led_pattern[8] = {
+ (u8)~(0x80), (u8)~(0x01),
+ (u8)~(0x40), (u8)~(0x02),
+ (u8)~(0x20), (u8)~(0x04),
+ (u8)~(0x10), (u8)~(0x08)
};
volatile unsigned char* sun3_intreg;
diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c
index 37121a0f1253..798ea72a0ea3 100644
--- a/arch/m68k/sun3x/config.c
+++ b/arch/m68k/sun3x/config.c
@@ -19,14 +19,14 @@
#include <asm/sun3ints.h>
#include <asm/setup.h>
#include <asm/oplib.h>
+#include <asm/config.h>
#include "time.h"
+#include "../sun3/sun3.h"
volatile char *clock_va;
-extern void sun3_get_model(char *model);
-
-void sun3_leds(unsigned int i)
+void sun3_leds(unsigned char byte)
{
}
diff --git a/arch/m68k/sun3x/dvma.c b/arch/m68k/sun3x/dvma.c
index a6034ba05845..5185b4818d40 100644
--- a/arch/m68k/sun3x/dvma.c
+++ b/arch/m68k/sun3x/dvma.c
@@ -60,7 +60,7 @@ static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU;
#ifdef DEBUG
/* code to print out a dvma mapping for debugging purposes */
-void dvma_print (unsigned long dvma_addr)
+static void dvma_print (unsigned long dvma_addr)
{
unsigned long index;
@@ -143,8 +143,7 @@ inline int dvma_map_cpu(unsigned long kaddr,
}
-inline int dvma_map_iommu(unsigned long kaddr, unsigned long baddr,
- int len)
+int dvma_map_iommu(unsigned long kaddr, unsigned long baddr, int len)
{
unsigned long end, index;
diff --git a/arch/m68k/sun3x/prom.c b/arch/m68k/sun3x/prom.c
index 64c23bfaa90c..8ac87d3dc607 100644
--- a/arch/m68k/sun3x/prom.c
+++ b/arch/m68k/sun3x/prom.c
@@ -30,7 +30,7 @@ struct linux_romvec *romvec;
e_vector *sun3x_prom_vbr;
/* Handle returning to the prom */
-void sun3x_halt(void)
+static void sun3x_halt(void)
{
unsigned long flags;
diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl
index a3798c2637fd..5b6a0b02b7de 100644
--- a/arch/microblaze/kernel/syscalls/syscall.tbl
+++ b/arch/microblaze/kernel/syscalls/syscall.tbl
@@ -260,7 +260,7 @@
250 common fadvise64 sys_fadvise64
# 251 is available for reuse (was briefly sys_set_zone_reclaim)
252 common exit_group sys_exit_group
-253 common lookup_dcookie sys_lookup_dcookie
+253 common lookup_dcookie sys_ni_syscall
254 common epoll_create sys_epoll_create
255 common epoll_ctl sys_epoll_ctl
256 common epoll_wait sys_epoll_wait
@@ -458,3 +458,7 @@
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
451 common cachestat sys_cachestat
452 common fchmodat2 sys_fchmodat2
+453 common map_shadow_stack sys_map_shadow_stack
+454 common futex_wake sys_futex_wake
+455 common futex_wait sys_futex_wait
+456 common futex_requeue sys_futex_requeue
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index caad195ba5c1..a2311c4bce6a 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -2,7 +2,6 @@
# All platforms listed in alphabetic order
platform-$(CONFIG_MIPS_ALCHEMY) += alchemy/
-platform-$(CONFIG_AR7) += ar7/
platform-$(CONFIG_ATH25) += ath25/
platform-$(CONFIG_ATH79) += ath79/
platform-$(CONFIG_BCM47XX) += bcm47xx/
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index bc8421859006..797ae590ebdb 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -202,28 +202,6 @@ config MIPS_ALCHEMY
select SYS_SUPPORTS_ZBOOT
select COMMON_CLK
-config AR7
- bool "Texas Instruments AR7"
- select BOOT_ELF32
- select COMMON_CLK
- select DMA_NONCOHERENT
- select CEVT_R4K
- select CSRC_R4K
- select IRQ_MIPS_CPU
- select NO_EXCEPT_FILL
- select SWAP_IO_SPACE
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_HAS_EARLY_PRINTK
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_LITTLE_ENDIAN
- select SYS_SUPPORTS_MIPS16
- select SYS_SUPPORTS_ZBOOT_UART16550
- select GPIOLIB
- select VLYNQ
- help
- Support for the Texas Instruments AR7 System-on-a-Chip
- family: TNETD7100, 7200 and 7300.
-
config ATH25
bool "Atheros AR231x/AR531x SoC support"
select CEVT_R4K
@@ -482,6 +460,7 @@ config MACH_LOONGSON2EF
config MACH_LOONGSON64
bool "Loongson 64-bit family of machines"
+ select ARCH_DMA_DEFAULT_COHERENT
select ARCH_SPARSEMEM_ENABLE
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
@@ -1273,6 +1252,7 @@ config CPU_LOONGSON64
select CPU_SUPPORTS_MSA
select CPU_DIEI_BROKEN if !LOONGSON3_ENHANCEMENT
select CPU_MIPSR2_IRQ_VI
+ select DMA_NONCOHERENT
select WEAK_ORDERING
select WEAK_REORDERING_BEYOND_LLSC
select MIPS_ASID_BITS_VARIABLE
diff --git a/arch/mips/Makefile.postlink b/arch/mips/Makefile.postlink
index 34e3bd71f3b0..6cfdc149d3bc 100644
--- a/arch/mips/Makefile.postlink
+++ b/arch/mips/Makefile.postlink
@@ -31,9 +31,6 @@ ifeq ($(CONFIG_RELOCATABLE),y)
$(call if_changed,relocs)
endif
-%.ko: FORCE
- @true
-
clean:
@true
diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile
deleted file mode 100644
index cd51c6c6e686..000000000000
--- a/arch/mips/ar7/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-obj-y := \
- prom.o \
- setup.o \
- memory.o \
- irq.o \
- time.o \
- platform.o \
- gpio.o \
- clock.o
diff --git a/arch/mips/ar7/Platform b/arch/mips/ar7/Platform
deleted file mode 100644
index a9257cc01c3c..000000000000
--- a/arch/mips/ar7/Platform
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Texas Instruments AR7
-#
-cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7
-load-$(CONFIG_AR7) += 0xffffffff94100000
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
deleted file mode 100644
index c717acbc5506..000000000000
--- a/arch/mips/ar7/clock.c
+++ /dev/null
@@ -1,439 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
- * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/export.h>
-#include <linux/delay.h>
-#include <linux/gcd.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/clkdev.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-
-#include <asm/addrspace.h>
-#include <asm/mach-ar7/ar7.h>
-
-#define BOOT_PLL_SOURCE_MASK 0x3
-#define CPU_PLL_SOURCE_SHIFT 16
-#define BUS_PLL_SOURCE_SHIFT 14
-#define USB_PLL_SOURCE_SHIFT 18
-#define DSP_PLL_SOURCE_SHIFT 22
-#define BOOT_PLL_SOURCE_AFE 0
-#define BOOT_PLL_SOURCE_BUS 0
-#define BOOT_PLL_SOURCE_REF 1
-#define BOOT_PLL_SOURCE_XTAL 2
-#define BOOT_PLL_SOURCE_CPU 3
-#define BOOT_PLL_BYPASS 0x00000020
-#define BOOT_PLL_ASYNC_MODE 0x02000000
-#define BOOT_PLL_2TO1_MODE 0x00008000
-
-#define TNETD7200_CLOCK_ID_CPU 0
-#define TNETD7200_CLOCK_ID_DSP 1
-#define TNETD7200_CLOCK_ID_USB 2
-
-#define TNETD7200_DEF_CPU_CLK 211000000
-#define TNETD7200_DEF_DSP_CLK 125000000
-#define TNETD7200_DEF_USB_CLK 48000000
-
-struct tnetd7300_clock {
- u32 ctrl;
-#define PREDIV_MASK 0x001f0000
-#define PREDIV_SHIFT 16
-#define POSTDIV_MASK 0x0000001f
- u32 unused1[3];
- u32 pll;
-#define MUL_MASK 0x0000f000
-#define MUL_SHIFT 12
-#define PLL_MODE_MASK 0x00000001
-#define PLL_NDIV 0x00000800
-#define PLL_DIV 0x00000002
-#define PLL_STATUS 0x00000001
- u32 unused2[3];
-};
-
-struct tnetd7300_clocks {
- struct tnetd7300_clock bus;
- struct tnetd7300_clock cpu;
- struct tnetd7300_clock usb;
- struct tnetd7300_clock dsp;
-};
-
-struct tnetd7200_clock {
- u32 ctrl;
- u32 unused1[3];
-#define DIVISOR_ENABLE_MASK 0x00008000
- u32 mul;
- u32 prediv;
- u32 postdiv;
- u32 postdiv2;
- u32 unused2[6];
- u32 cmd;
- u32 status;
- u32 cmden;
- u32 padding[15];
-};
-
-struct tnetd7200_clocks {
- struct tnetd7200_clock cpu;
- struct tnetd7200_clock dsp;
- struct tnetd7200_clock usb;
-};
-
-struct clk_rate {
- u32 rate;
-};
-static struct clk_rate bus_clk = {
- .rate = 125000000,
-};
-
-static struct clk_rate cpu_clk = {
- .rate = 150000000,
-};
-
-static void approximate(int base, int target, int *prediv,
- int *postdiv, int *mul)
-{
- int i, j, k, freq, res = target;
- for (i = 1; i <= 16; i++)
- for (j = 1; j <= 32; j++)
- for (k = 1; k <= 32; k++) {
- freq = abs(base / j * i / k - target);
- if (freq < res) {
- res = freq;
- *mul = i;
- *prediv = j;
- *postdiv = k;
- }
- }
-}
-
-static void calculate(int base, int target, int *prediv, int *postdiv,
- int *mul)
-{
- int tmp_gcd, tmp_base, tmp_freq;
-
- for (*prediv = 1; *prediv <= 32; (*prediv)++) {
- tmp_base = base / *prediv;
- tmp_gcd = gcd(target, tmp_base);
- *mul = target / tmp_gcd;
- *postdiv = tmp_base / tmp_gcd;
- if ((*mul < 1) || (*mul >= 16))
- continue;
- if ((*postdiv > 0) & (*postdiv <= 32))
- break;
- }
-
- if (base / *prediv * *mul / *postdiv != target) {
- approximate(base, target, prediv, postdiv, mul);
- tmp_freq = base / *prediv * *mul / *postdiv;
- printk(KERN_WARNING
- "Adjusted requested frequency %d to %d\n",
- target, tmp_freq);
- }
-
- printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
- *prediv, *postdiv, *mul);
-}
-
-static int tnetd7300_dsp_clock(void)
-{
- u32 didr1, didr2;
- u8 rev = ar7_chip_rev();
- didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
- didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
- if (didr2 & (1 << 23))
- return 0;
- if ((rev >= 0x23) && (rev != 0x57))
- return 250000000;
- if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
- > 4208000)
- return 250000000;
- return 0;
-}
-
-static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
- u32 *bootcr, u32 bus_clock)
-{
- int product;
- int base_clock = AR7_REF_CLOCK;
- u32 ctrl = readl(&clock->ctrl);
- u32 pll = readl(&clock->pll);
- int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
- int postdiv = (ctrl & POSTDIV_MASK) + 1;
- int divisor = prediv * postdiv;
- int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
-
- switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
- case BOOT_PLL_SOURCE_BUS:
- base_clock = bus_clock;
- break;
- case BOOT_PLL_SOURCE_REF:
- base_clock = AR7_REF_CLOCK;
- break;
- case BOOT_PLL_SOURCE_XTAL:
- base_clock = AR7_XTAL_CLOCK;
- break;
- case BOOT_PLL_SOURCE_CPU:
- base_clock = cpu_clk.rate;
- break;
- }
-
- if (*bootcr & BOOT_PLL_BYPASS)
- return base_clock / divisor;
-
- if ((pll & PLL_MODE_MASK) == 0)
- return (base_clock >> (mul / 16 + 1)) / divisor;
-
- if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
- product = (mul & 1) ?
- (base_clock * mul) >> 1 :
- (base_clock * (mul - 1)) >> 2;
- return product / divisor;
- }
-
- if (mul == 16)
- return base_clock / divisor;
-
- return base_clock * mul / divisor;
-}
-
-static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
- u32 *bootcr, u32 frequency)
-{
- int prediv, postdiv, mul;
- int base_clock = bus_clk.rate;
-
- switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
- case BOOT_PLL_SOURCE_BUS:
- base_clock = bus_clk.rate;
- break;
- case BOOT_PLL_SOURCE_REF:
- base_clock = AR7_REF_CLOCK;
- break;
- case BOOT_PLL_SOURCE_XTAL:
- base_clock = AR7_XTAL_CLOCK;
- break;
- case BOOT_PLL_SOURCE_CPU:
- base_clock = cpu_clk.rate;
- break;
- }
-
- calculate(base_clock, frequency, &prediv, &postdiv, &mul);
-
- writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
- mdelay(1);
- writel(4, &clock->pll);
- while (readl(&clock->pll) & PLL_STATUS)
- ;
- writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
- mdelay(75);
-}
-
-static void __init tnetd7300_init_clocks(void)
-{
- u32 *bootcr = (u32 *)ioremap(AR7_REGS_DCL, 4);
- struct tnetd7300_clocks *clocks =
- ioremap(UR8_REGS_CLOCKS,
- sizeof(struct tnetd7300_clocks));
- u32 dsp_clk;
- struct clk *clk;
-
- bus_clk.rate = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
- &clocks->bus, bootcr, AR7_AFE_CLOCK);
-
- if (*bootcr & BOOT_PLL_ASYNC_MODE)
- cpu_clk.rate = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
- &clocks->cpu, bootcr, AR7_AFE_CLOCK);
- else
- cpu_clk.rate = bus_clk.rate;
-
- dsp_clk = tnetd7300_dsp_clock();
- if (dsp_clk == 250000000)
- tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
- bootcr, dsp_clk);
-
- iounmap(clocks);
- iounmap(bootcr);
-
- clk = clk_register_fixed_rate(NULL, "cpu", NULL, 0, cpu_clk.rate);
- clkdev_create(clk, "cpu", NULL);
- clk = clk_register_fixed_rate(NULL, "dsp", NULL, 0, dsp_clk);
- clkdev_create(clk, "dsp", NULL);
-}
-
-static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
- int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
-{
- printk(KERN_INFO
- "Clocks: base = %d, frequency = %u, prediv = %d, "
- "postdiv = %d, postdiv2 = %d, mul = %d\n",
- base, frequency, prediv, postdiv, postdiv2, mul);
-
- writel(0, &clock->ctrl);
- writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
- writel((mul - 1) & 0xF, &clock->mul);
-
- while (readl(&clock->status) & 0x1)
- ; /* nop */
-
- writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
-
- writel(readl(&clock->cmden) | 1, &clock->cmden);
- writel(readl(&clock->cmd) | 1, &clock->cmd);
-
- while (readl(&clock->status) & 0x1)
- ; /* nop */
-
- writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
-
- writel(readl(&clock->cmden) | 1, &clock->cmden);
- writel(readl(&clock->cmd) | 1, &clock->cmd);
-
- while (readl(&clock->status) & 0x1)
- ; /* nop */
-
- writel(readl(&clock->ctrl) | 1, &clock->ctrl);
-}
-
-static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
-{
- if (*bootcr & BOOT_PLL_ASYNC_MODE)
- /* Async */
- switch (clock_id) {
- case TNETD7200_CLOCK_ID_DSP:
- return AR7_REF_CLOCK;
- default:
- return AR7_AFE_CLOCK;
- }
- else
- /* Sync */
- if (*bootcr & BOOT_PLL_2TO1_MODE)
- /* 2:1 */
- switch (clock_id) {
- case TNETD7200_CLOCK_ID_DSP:
- return AR7_REF_CLOCK;
- default:
- return AR7_AFE_CLOCK;
- }
- else
- /* 1:1 */
- return AR7_REF_CLOCK;
-}
-
-
-static void __init tnetd7200_init_clocks(void)
-{
- u32 *bootcr = (u32 *)ioremap(AR7_REGS_DCL, 4);
- struct tnetd7200_clocks *clocks =
- ioremap(AR7_REGS_CLOCKS,
- sizeof(struct tnetd7200_clocks));
- int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
- int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
- int usb_base, usb_mul, usb_prediv, usb_postdiv;
- struct clk *clk;
-
- cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
- dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
-
- if (*bootcr & BOOT_PLL_ASYNC_MODE) {
- printk(KERN_INFO "Clocks: Async mode\n");
-
- printk(KERN_INFO "Clocks: Setting DSP clock\n");
- calculate(dsp_base, TNETD7200_DEF_DSP_CLK,
- &dsp_prediv, &dsp_postdiv, &dsp_mul);
- bus_clk.rate =
- ((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;
- tnetd7200_set_clock(dsp_base, &clocks->dsp,
- dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
- bus_clk.rate);
-
- printk(KERN_INFO "Clocks: Setting CPU clock\n");
- calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
- &cpu_postdiv, &cpu_mul);
- cpu_clk.rate =
- ((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;
- tnetd7200_set_clock(cpu_base, &clocks->cpu,
- cpu_prediv, cpu_postdiv, -1, cpu_mul,
- cpu_clk.rate);
-
- } else
- if (*bootcr & BOOT_PLL_2TO1_MODE) {
- printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
-
- printk(KERN_INFO "Clocks: Setting CPU clock\n");
- calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
- &cpu_postdiv, &cpu_mul);
- cpu_clk.rate = ((cpu_base / cpu_prediv) * cpu_mul)
- / cpu_postdiv;
- tnetd7200_set_clock(cpu_base, &clocks->cpu,
- cpu_prediv, cpu_postdiv, -1, cpu_mul,
- cpu_clk.rate);
-
- printk(KERN_INFO "Clocks: Setting DSP clock\n");
- calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
- &dsp_postdiv, &dsp_mul);
- bus_clk.rate = cpu_clk.rate / 2;
- tnetd7200_set_clock(dsp_base, &clocks->dsp,
- dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
- dsp_mul * 2, bus_clk.rate);
- } else {
- printk(KERN_INFO "Clocks: Sync 1:1 mode\n");
-
- printk(KERN_INFO "Clocks: Setting DSP clock\n");
- calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
- &dsp_postdiv, &dsp_mul);
- bus_clk.rate = ((dsp_base / dsp_prediv) * dsp_mul)
- / dsp_postdiv;
- tnetd7200_set_clock(dsp_base, &clocks->dsp,
- dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
- dsp_mul * 2, bus_clk.rate);
-
- cpu_clk.rate = bus_clk.rate;
- }
-
- printk(KERN_INFO "Clocks: Setting USB clock\n");
- usb_base = bus_clk.rate;
- calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,
- &usb_postdiv, &usb_mul);
- tnetd7200_set_clock(usb_base, &clocks->usb,
- usb_prediv, usb_postdiv, -1, usb_mul,
- TNETD7200_DEF_USB_CLK);
-
- iounmap(clocks);
- iounmap(bootcr);
-
- clk = clk_register_fixed_rate(NULL, "cpu", NULL, 0, cpu_clk.rate);
- clkdev_create(clk, "cpu", NULL);
- clkdev_create(clk, "dsp", NULL);
-}
-
-void __init ar7_init_clocks(void)
-{
- struct clk *clk;
-
- switch (ar7_chip_id()) {
- case AR7_CHIP_7100:
- case AR7_CHIP_7200:
- tnetd7200_init_clocks();
- break;
- case AR7_CHIP_7300:
- tnetd7300_init_clocks();
- break;
- default:
- break;
- }
- clk = clk_register_fixed_rate(NULL, "bus", NULL, 0, bus_clk.rate);
- clkdev_create(clk, "bus", NULL);
- /* adjust vbus clock rate */
- clk = clk_register_fixed_factor(NULL, "vbus", "bus", 0, 1, 2);
- clkdev_create(clk, "vbus", NULL);
- clkdev_create(clk, "cpmac", "cpmac.1");
- clkdev_create(clk, "cpmac", "cpmac.1");
-}
diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c
deleted file mode 100644
index 4ed833b9cc2f..000000000000
--- a/arch/mips/ar7/gpio.c
+++ /dev/null
@@ -1,332 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
- * Copyright (C) 2009-2010 Florian Fainelli <florian@openwrt.org>
- */
-
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/gpio/driver.h>
-
-#include <asm/mach-ar7/ar7.h>
-
-#define AR7_GPIO_MAX 32
-#define TITAN_GPIO_MAX 51
-
-struct ar7_gpio_chip {
- void __iomem *regs;
- struct gpio_chip chip;
-};
-
-static int ar7_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
-{
- struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
- void __iomem *gpio_in = gpch->regs + AR7_GPIO_INPUT;
-
- return !!(readl(gpio_in) & (1 << gpio));
-}
-
-static int titan_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
-{
- struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
- void __iomem *gpio_in0 = gpch->regs + TITAN_GPIO_INPUT_0;
- void __iomem *gpio_in1 = gpch->regs + TITAN_GPIO_INPUT_1;
-
- return readl(gpio >> 5 ? gpio_in1 : gpio_in0) & (1 << (gpio & 0x1f));
-}
-
-static void ar7_gpio_set_value(struct gpio_chip *chip,
- unsigned gpio, int value)
-{
- struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
- void __iomem *gpio_out = gpch->regs + AR7_GPIO_OUTPUT;
- unsigned tmp;
-
- tmp = readl(gpio_out) & ~(1 << gpio);
- if (value)
- tmp |= 1 << gpio;
- writel(tmp, gpio_out);
-}
-
-static void titan_gpio_set_value(struct gpio_chip *chip,
- unsigned gpio, int value)
-{
- struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
- void __iomem *gpio_out0 = gpch->regs + TITAN_GPIO_OUTPUT_0;
- void __iomem *gpio_out1 = gpch->regs + TITAN_GPIO_OUTPUT_1;
- unsigned tmp;
-
- tmp = readl(gpio >> 5 ? gpio_out1 : gpio_out0) & ~(1 << (gpio & 0x1f));
- if (value)
- tmp |= 1 << (gpio & 0x1f);
- writel(tmp, gpio >> 5 ? gpio_out1 : gpio_out0);
-}
-
-static int ar7_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
-{
- struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
- void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
-
- writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
-
- return 0;
-}
-
-static int titan_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
-{
- struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
- void __iomem *gpio_dir0 = gpch->regs + TITAN_GPIO_DIR_0;
- void __iomem *gpio_dir1 = gpch->regs + TITAN_GPIO_DIR_1;
-
- if (gpio >= TITAN_GPIO_MAX)
- return -EINVAL;
-
- writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) | (1 << (gpio & 0x1f)),
- gpio >> 5 ? gpio_dir1 : gpio_dir0);
- return 0;
-}
-
-static int ar7_gpio_direction_output(struct gpio_chip *chip,
- unsigned gpio, int value)
-{
- struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
- void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
-
- ar7_gpio_set_value(chip, gpio, value);
- writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
-
- return 0;
-}
-
-static int titan_gpio_direction_output(struct gpio_chip *chip,
- unsigned gpio, int value)
-{
- struct ar7_gpio_chip *gpch = gpiochip_get_data(chip);
- void __iomem *gpio_dir0 = gpch->regs + TITAN_GPIO_DIR_0;
- void __iomem *gpio_dir1 = gpch->regs + TITAN_GPIO_DIR_1;
-
- if (gpio >= TITAN_GPIO_MAX)
- return -EINVAL;
-
- titan_gpio_set_value(chip, gpio, value);
- writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) & ~(1 <<
- (gpio & 0x1f)), gpio >> 5 ? gpio_dir1 : gpio_dir0);
-
- return 0;
-}
-
-static struct ar7_gpio_chip ar7_gpio_chip = {
- .chip = {
- .label = "ar7-gpio",
- .direction_input = ar7_gpio_direction_input,
- .direction_output = ar7_gpio_direction_output,
- .set = ar7_gpio_set_value,
- .get = ar7_gpio_get_value,
- .base = 0,
- .ngpio = AR7_GPIO_MAX,
- }
-};
-
-static struct ar7_gpio_chip titan_gpio_chip = {
- .chip = {
- .label = "titan-gpio",
- .direction_input = titan_gpio_direction_input,
- .direction_output = titan_gpio_direction_output,
- .set = titan_gpio_set_value,
- .get = titan_gpio_get_value,
- .base = 0,
- .ngpio = TITAN_GPIO_MAX,
- }
-};
-
-static inline int ar7_gpio_enable_ar7(unsigned gpio)
-{
- void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
-
- writel(readl(gpio_en) | (1 << gpio), gpio_en);
-
- return 0;
-}
-
-static inline int ar7_gpio_enable_titan(unsigned gpio)
-{
- void __iomem *gpio_en0 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_0;
- void __iomem *gpio_en1 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_1;
-
- writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) | (1 << (gpio & 0x1f)),
- gpio >> 5 ? gpio_en1 : gpio_en0);
-
- return 0;
-}
-
-int ar7_gpio_enable(unsigned gpio)
-{
- return ar7_is_titan() ? ar7_gpio_enable_titan(gpio) :
- ar7_gpio_enable_ar7(gpio);
-}
-EXPORT_SYMBOL(ar7_gpio_enable);
-
-static inline int ar7_gpio_disable_ar7(unsigned gpio)
-{
- void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
-
- writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
-
- return 0;
-}
-
-static inline int ar7_gpio_disable_titan(unsigned gpio)
-{
- void __iomem *gpio_en0 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_0;
- void __iomem *gpio_en1 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_1;
-
- writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) & ~(1 << (gpio & 0x1f)),
- gpio >> 5 ? gpio_en1 : gpio_en0);
-
- return 0;
-}
-
-int ar7_gpio_disable(unsigned gpio)
-{
- return ar7_is_titan() ? ar7_gpio_disable_titan(gpio) :
- ar7_gpio_disable_ar7(gpio);
-}
-EXPORT_SYMBOL(ar7_gpio_disable);
-
-struct titan_gpio_cfg {
- u32 reg;
- u32 shift;
- u32 func;
-};
-
-static const struct titan_gpio_cfg titan_gpio_table[] = {
- /* reg, start bit, mux value */
- {4, 24, 1},
- {4, 26, 1},
- {4, 28, 1},
- {4, 30, 1},
- {5, 6, 1},
- {5, 8, 1},
- {5, 10, 1},
- {5, 12, 1},
- {7, 14, 3},
- {7, 16, 3},
- {7, 18, 3},
- {7, 20, 3},
- {7, 22, 3},
- {7, 26, 3},
- {7, 28, 3},
- {7, 30, 3},
- {8, 0, 3},
- {8, 2, 3},
- {8, 4, 3},
- {8, 10, 3},
- {8, 14, 3},
- {8, 16, 3},
- {8, 18, 3},
- {8, 20, 3},
- {9, 8, 3},
- {9, 10, 3},
- {9, 12, 3},
- {9, 14, 3},
- {9, 18, 3},
- {9, 20, 3},
- {9, 24, 3},
- {9, 26, 3},
- {9, 28, 3},
- {9, 30, 3},
- {10, 0, 3},
- {10, 2, 3},
- {10, 8, 3},
- {10, 10, 3},
- {10, 12, 3},
- {10, 14, 3},
- {13, 12, 3},
- {13, 14, 3},
- {13, 16, 3},
- {13, 18, 3},
- {13, 24, 3},
- {13, 26, 3},
- {13, 28, 3},
- {13, 30, 3},
- {14, 2, 3},
- {14, 6, 3},
- {14, 8, 3},
- {14, 12, 3}
-};
-
-static int titan_gpio_pinsel(unsigned gpio)
-{
- struct titan_gpio_cfg gpio_cfg;
- u32 mux_status, pin_sel_reg, tmp;
- void __iomem *pin_sel = (void __iomem *)KSEG1ADDR(AR7_REGS_PINSEL);
-
- if (gpio >= ARRAY_SIZE(titan_gpio_table))
- return -EINVAL;
-
- gpio_cfg = titan_gpio_table[gpio];
- pin_sel_reg = gpio_cfg.reg - 1;
-
- mux_status = (readl(pin_sel + pin_sel_reg) >> gpio_cfg.shift) & 0x3;
-
- /* Check the mux status */
- if (!((mux_status == 0) || (mux_status == gpio_cfg.func)))
- return 0;
-
- /* Set the pin sel value */
- tmp = readl(pin_sel + pin_sel_reg);
- tmp |= ((gpio_cfg.func & 0x3) << gpio_cfg.shift);
- writel(tmp, pin_sel + pin_sel_reg);
-
- return 0;
-}
-
-/* Perform minimal Titan GPIO configuration */
-static void titan_gpio_init(void)
-{
- unsigned i;
-
- for (i = 44; i < 48; i++) {
- titan_gpio_pinsel(i);
- ar7_gpio_enable_titan(i);
- titan_gpio_direction_input(&titan_gpio_chip.chip, i);
- }
-}
-
-int __init ar7_gpio_init(void)
-{
- int ret;
- struct ar7_gpio_chip *gpch;
- unsigned size;
-
- if (!ar7_is_titan()) {
- gpch = &ar7_gpio_chip;
- size = 0x10;
- } else {
- gpch = &titan_gpio_chip;
- size = 0x1f;
- }
-
- gpch->regs = ioremap(AR7_REGS_GPIO, size);
- if (!gpch->regs) {
- printk(KERN_ERR "%s: failed to ioremap regs\n",
- gpch->chip.label);
- return -ENOMEM;
- }
-
- ret = gpiochip_add_data(&gpch->chip, gpch);
- if (ret) {
- printk(KERN_ERR "%s: failed to add gpiochip\n",
- gpch->chip.label);
- iounmap(gpch->regs);
- return ret;
- }
- printk(KERN_INFO "%s: registered %d GPIOs\n",
- gpch->chip.label, gpch->chip.ngpio);
-
- if (ar7_is_titan())
- titan_gpio_init();
-
- return ret;
-}
diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c
deleted file mode 100644
index f0a7942d393e..000000000000
--- a/arch/mips/ar7/irq.c
+++ /dev/null
@@ -1,165 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
- */
-
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/mach-ar7/ar7.h>
-
-#define EXCEPT_OFFSET 0x80
-#define PACE_OFFSET 0xA0
-#define CHNLS_OFFSET 0x200
-
-#define REG_OFFSET(irq, reg) ((irq) / 32 * 0x4 + reg * 0x10)
-#define SEC_REG_OFFSET(reg) (EXCEPT_OFFSET + reg * 0x8)
-#define SEC_SR_OFFSET (SEC_REG_OFFSET(0)) /* 0x80 */
-#define CR_OFFSET(irq) (REG_OFFSET(irq, 1)) /* 0x10 */
-#define SEC_CR_OFFSET (SEC_REG_OFFSET(1)) /* 0x88 */
-#define ESR_OFFSET(irq) (REG_OFFSET(irq, 2)) /* 0x20 */
-#define SEC_ESR_OFFSET (SEC_REG_OFFSET(2)) /* 0x90 */
-#define ECR_OFFSET(irq) (REG_OFFSET(irq, 3)) /* 0x30 */
-#define SEC_ECR_OFFSET (SEC_REG_OFFSET(3)) /* 0x98 */
-#define PIR_OFFSET (0x40)
-#define MSR_OFFSET (0x44)
-#define PM_OFFSET(irq) (REG_OFFSET(irq, 5)) /* 0x50 */
-#define TM_OFFSET(irq) (REG_OFFSET(irq, 6)) /* 0x60 */
-
-#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr))
-
-#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4))
-
-static int ar7_irq_base;
-
-static void ar7_unmask_irq(struct irq_data *d)
-{
- writel(1 << ((d->irq - ar7_irq_base) % 32),
- REG(ESR_OFFSET(d->irq - ar7_irq_base)));
-}
-
-static void ar7_mask_irq(struct irq_data *d)
-{
- writel(1 << ((d->irq - ar7_irq_base) % 32),
- REG(ECR_OFFSET(d->irq - ar7_irq_base)));
-}
-
-static void ar7_ack_irq(struct irq_data *d)
-{
- writel(1 << ((d->irq - ar7_irq_base) % 32),
- REG(CR_OFFSET(d->irq - ar7_irq_base)));
-}
-
-static void ar7_unmask_sec_irq(struct irq_data *d)
-{
- writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
-}
-
-static void ar7_mask_sec_irq(struct irq_data *d)
-{
- writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
-}
-
-static void ar7_ack_sec_irq(struct irq_data *d)
-{
- writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET));
-}
-
-static struct irq_chip ar7_irq_type = {
- .name = "AR7",
- .irq_unmask = ar7_unmask_irq,
- .irq_mask = ar7_mask_irq,
- .irq_ack = ar7_ack_irq
-};
-
-static struct irq_chip ar7_sec_irq_type = {
- .name = "AR7",
- .irq_unmask = ar7_unmask_sec_irq,
- .irq_mask = ar7_mask_sec_irq,
- .irq_ack = ar7_ack_sec_irq,
-};
-
-static void __init ar7_irq_init(int base)
-{
- int i;
- /*
- * Disable interrupts and clear pending
- */
- writel(0xffffffff, REG(ECR_OFFSET(0)));
- writel(0xff, REG(ECR_OFFSET(32)));
- writel(0xffffffff, REG(SEC_ECR_OFFSET));
- writel(0xffffffff, REG(CR_OFFSET(0)));
- writel(0xff, REG(CR_OFFSET(32)));
- writel(0xffffffff, REG(SEC_CR_OFFSET));
-
- ar7_irq_base = base;
-
- for (i = 0; i < 40; i++) {
- writel(i, REG(CHNL_OFFSET(i)));
- /* Primary IRQ's */
- irq_set_chip_and_handler(base + i, &ar7_irq_type,
- handle_level_irq);
- /* Secondary IRQ's */
- if (i < 32)
- irq_set_chip_and_handler(base + i + 40,
- &ar7_sec_irq_type,
- handle_level_irq);
- }
-
- if (request_irq(2, no_action, IRQF_NO_THREAD, "AR7 cascade interrupt",
- NULL))
- pr_err("Failed to request irq 2 (AR7 cascade interrupt)\n");
- if (request_irq(ar7_irq_base, no_action, IRQF_NO_THREAD,
- "AR7 cascade interrupt", NULL)) {
- pr_err("Failed to request irq %d (AR7 cascade interrupt)\n",
- ar7_irq_base);
- }
- set_c0_status(IE_IRQ0);
-}
-
-void __init arch_init_irq(void)
-{
- mips_cpu_irq_init();
- ar7_irq_init(8);
-}
-
-static void ar7_cascade(void)
-{
- u32 status;
- int i, irq;
-
- /* Primary IRQ's */
- irq = readl(REG(PIR_OFFSET)) & 0x3f;
- if (irq) {
- do_IRQ(ar7_irq_base + irq);
- return;
- }
-
- /* Secondary IRQ's are cascaded through primary '0' */
- writel(1, REG(CR_OFFSET(irq)));
- status = readl(REG(SEC_SR_OFFSET));
- for (i = 0; i < 32; i++) {
- if (status & 1) {
- do_IRQ(ar7_irq_base + i + 40);
- return;
- }
- status >>= 1;
- }
-
- spurious_interrupt();
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
- if (pending & STATUSF_IP7) /* cpu timer */
- do_IRQ(7);
- else if (pending & STATUSF_IP2) /* int0 hardware line */
- ar7_cascade();
- else
- spurious_interrupt();
-}
diff --git a/arch/mips/ar7/memory.c b/arch/mips/ar7/memory.c
deleted file mode 100644
index ce8024c1a54e..000000000000
--- a/arch/mips/ar7/memory.c
+++ /dev/null
@@ -1,51 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
- */
-#include <linux/memblock.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/pfn.h>
-#include <linux/proc_fs.h>
-#include <linux/string.h>
-#include <linux/swap.h>
-
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/sections.h>
-
-#include <asm/mach-ar7/ar7.h>
-
-static int __init memsize(void)
-{
- u32 size = (64 << 20);
- u32 *addr = (u32 *)KSEG1ADDR(AR7_SDRAM_BASE + size - 4);
- u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end));
- u32 *tmpaddr = addr;
-
- while (tmpaddr > kernel_end) {
- *tmpaddr = (u32)tmpaddr;
- size >>= 1;
- tmpaddr -= size >> 2;
- }
-
- do {
- tmpaddr += size >> 2;
- if (*tmpaddr != (u32)tmpaddr)
- break;
- size <<= 1;
- } while (size < (64 << 20));
-
- writel((u32)tmpaddr, &addr);
-
- return size;
-}
-
-void __init prom_meminit(void)
-{
- unsigned long pages;
-
- pages = memsize() >> PAGE_SHIFT;
- memblock_add(PHYS_OFFSET, pages << PAGE_SHIFT);
-}
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
deleted file mode 100644
index 215149a85d83..000000000000
--- a/arch/mips/ar7/platform.c
+++ /dev/null
@@ -1,722 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
- */
-
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/vlynq.h>
-#include <linux/leds.h>
-#include <linux/string.h>
-#include <linux/etherdevice.h>
-#include <linux/phy.h>
-#include <linux/phy_fixed.h>
-#include <linux/gpio.h>
-#include <linux/clk.h>
-
-#include <asm/addrspace.h>
-#include <asm/mach-ar7/ar7.h>
-#include <asm/mach-ar7/prom.h>
-
-/*****************************************************************************
- * VLYNQ Bus
- ****************************************************************************/
-struct plat_vlynq_data {
- struct plat_vlynq_ops ops;
- int gpio_bit;
- int reset_bit;
-};
-
-static int vlynq_on(struct vlynq_device *dev)
-{
- int ret;
- struct plat_vlynq_data *pdata = dev->dev.platform_data;
-
- ret = gpio_request(pdata->gpio_bit, "vlynq");
- if (ret)
- goto out;
-
- ar7_device_reset(pdata->reset_bit);
-
- ret = ar7_gpio_disable(pdata->gpio_bit);
- if (ret)
- goto out_enabled;
-
- ret = ar7_gpio_enable(pdata->gpio_bit);
- if (ret)
- goto out_enabled;
-
- ret = gpio_direction_output(pdata->gpio_bit, 0);
- if (ret)
- goto out_gpio_enabled;
-
- msleep(50);
-
- gpio_set_value(pdata->gpio_bit, 1);
-
- msleep(50);
-
- return 0;
-
-out_gpio_enabled:
- ar7_gpio_disable(pdata->gpio_bit);
-out_enabled:
- ar7_device_disable(pdata->reset_bit);
- gpio_free(pdata->gpio_bit);
-out:
- return ret;
-}
-
-static void vlynq_off(struct vlynq_device *dev)
-{
- struct plat_vlynq_data *pdata = dev->dev.platform_data;
-
- ar7_gpio_disable(pdata->gpio_bit);
- gpio_free(pdata->gpio_bit);
- ar7_device_disable(pdata->reset_bit);
-}
-
-static struct resource vlynq_low_res[] = {
- {
- .name = "regs",
- .flags = IORESOURCE_MEM,
- .start = AR7_REGS_VLYNQ0,
- .end = AR7_REGS_VLYNQ0 + 0xff,
- },
- {
- .name = "irq",
- .flags = IORESOURCE_IRQ,
- .start = 29,
- .end = 29,
- },
- {
- .name = "mem",
- .flags = IORESOURCE_MEM,
- .start = 0x04000000,
- .end = 0x04ffffff,
- },
- {
- .name = "devirq",
- .flags = IORESOURCE_IRQ,
- .start = 80,
- .end = 111,
- },
-};
-
-static struct resource vlynq_high_res[] = {
- {
- .name = "regs",
- .flags = IORESOURCE_MEM,
- .start = AR7_REGS_VLYNQ1,
- .end = AR7_REGS_VLYNQ1 + 0xff,
- },
- {
- .name = "irq",
- .flags = IORESOURCE_IRQ,
- .start = 33,
- .end = 33,
- },
- {
- .name = "mem",
- .flags = IORESOURCE_MEM,
- .start = 0x0c000000,
- .end = 0x0cffffff,
- },
- {
- .name = "devirq",
- .flags = IORESOURCE_IRQ,
- .start = 112,
- .end = 143,
- },
-};
-
-static struct plat_vlynq_data vlynq_low_data = {
- .ops = {
- .on = vlynq_on,
- .off = vlynq_off,
- },
- .reset_bit = 20,
- .gpio_bit = 18,
-};
-
-static struct plat_vlynq_data vlynq_high_data = {
- .ops = {
- .on = vlynq_on,
- .off = vlynq_off,
- },
- .reset_bit = 16,
- .gpio_bit = 19,
-};
-
-static struct platform_device vlynq_low = {
- .id = 0,
- .name = "vlynq",
- .dev = {
- .platform_data = &vlynq_low_data,
- },
- .resource = vlynq_low_res,
- .num_resources = ARRAY_SIZE(vlynq_low_res),
-};
-
-static struct platform_device vlynq_high = {
- .id = 1,
- .name = "vlynq",
- .dev = {
- .platform_data = &vlynq_high_data,
- },
- .resource = vlynq_high_res,
- .num_resources = ARRAY_SIZE(vlynq_high_res),
-};
-
-/*****************************************************************************
- * Flash
- ****************************************************************************/
-static struct resource physmap_flash_resource = {
- .name = "mem",
- .flags = IORESOURCE_MEM,
- .start = 0x10000000,
- .end = 0x107fffff,
-};
-
-static const char *ar7_probe_types[] = { "ar7part", NULL };
-
-static struct physmap_flash_data physmap_flash_data = {
- .width = 2,
- .part_probe_types = ar7_probe_types,
-};
-
-static struct platform_device physmap_flash = {
- .name = "physmap-flash",
- .dev = {
- .platform_data = &physmap_flash_data,
- },
- .resource = &physmap_flash_resource,
- .num_resources = 1,
-};
-
-/*****************************************************************************
- * Ethernet
- ****************************************************************************/
-static struct resource cpmac_low_res[] = {
- {
- .name = "regs",
- .flags = IORESOURCE_MEM,
- .start = AR7_REGS_MAC0,
- .end = AR7_REGS_MAC0 + 0x7ff,
- },
- {
- .name = "irq",
- .flags = IORESOURCE_IRQ,
- .start = 27,
- .end = 27,
- },
-};
-
-static struct resource cpmac_high_res[] = {
- {
- .name = "regs",
- .flags = IORESOURCE_MEM,
- .start = AR7_REGS_MAC1,
- .end = AR7_REGS_MAC1 + 0x7ff,
- },
- {
- .name = "irq",
- .flags = IORESOURCE_IRQ,
- .start = 41,
- .end = 41,
- },
-};
-
-static struct fixed_phy_status fixed_phy_status __initdata = {
- .link = 1,
- .speed = 100,
- .duplex = 1,
-};
-
-static struct plat_cpmac_data cpmac_low_data = {
- .reset_bit = 17,
- .power_bit = 20,
- .phy_mask = 0x80000000,
-};
-
-static struct plat_cpmac_data cpmac_high_data = {
- .reset_bit = 21,
- .power_bit = 22,
- .phy_mask = 0x7fffffff,
-};
-
-static u64 cpmac_dma_mask = DMA_BIT_MASK(32);
-
-static struct platform_device cpmac_low = {
- .id = 0,
- .name = "cpmac",
- .dev = {
- .dma_mask = &cpmac_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &cpmac_low_data,
- },
- .resource = cpmac_low_res,
- .num_resources = ARRAY_SIZE(cpmac_low_res),
-};
-
-static struct platform_device cpmac_high = {
- .id = 1,
- .name = "cpmac",
- .dev = {
- .dma_mask = &cpmac_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &cpmac_high_data,
- },
- .resource = cpmac_high_res,
- .num_resources = ARRAY_SIZE(cpmac_high_res),
-};
-
-static void __init cpmac_get_mac(int instance, unsigned char *dev_addr)
-{
- char name[5], *mac;
-
- sprintf(name, "mac%c", 'a' + instance);
- mac = prom_getenv(name);
- if (!mac && instance) {
- sprintf(name, "mac%c", 'a');
- mac = prom_getenv(name);
- }
-
- if (mac) {
- if (!mac_pton(mac, dev_addr)) {
- pr_warn("cannot parse mac address, using random address\n");
- eth_random_addr(dev_addr);
- }
- } else
- eth_random_addr(dev_addr);
-}
-
-/*****************************************************************************
- * USB
- ****************************************************************************/
-static struct resource usb_res[] = {
- {
- .name = "regs",
- .flags = IORESOURCE_MEM,
- .start = AR7_REGS_USB,
- .end = AR7_REGS_USB + 0xff,
- },
- {
- .name = "irq",
- .flags = IORESOURCE_IRQ,
- .start = 32,
- .end = 32,
- },
- {
- .name = "mem",
- .flags = IORESOURCE_MEM,
- .start = 0x03400000,
- .end = 0x03401fff,
- },
-};
-
-static struct platform_device ar7_udc = {
- .name = "ar7_udc",
- .resource = usb_res,
- .num_resources = ARRAY_SIZE(usb_res),
-};
-
-/*****************************************************************************
- * LEDs
- ****************************************************************************/
-static const struct gpio_led default_leds[] = {
- {
- .name = "status",
- .gpio = 8,
- .active_low = 1,
- },
-};
-
-static const struct gpio_led titan_leds[] = {
- { .name = "status", .gpio = 8, .active_low = 1, },
- { .name = "wifi", .gpio = 13, .active_low = 1, },
-};
-
-static const struct gpio_led dsl502t_leds[] = {
- {
- .name = "status",
- .gpio = 9,
- .active_low = 1,
- },
- {
- .name = "ethernet",
- .gpio = 7,
- .active_low = 1,
- },
- {
- .name = "usb",
- .gpio = 12,
- .active_low = 1,
- },
-};
-
-static const struct gpio_led dg834g_leds[] = {
- {
- .name = "ppp",
- .gpio = 6,
- .active_low = 1,
- },
- {
- .name = "status",
- .gpio = 7,
- .active_low = 1,
- },
- {
- .name = "adsl",
- .gpio = 8,
- .active_low = 1,
- },
- {
- .name = "wifi",
- .gpio = 12,
- .active_low = 1,
- },
- {
- .name = "power",
- .gpio = 14,
- .active_low = 1,
- .default_trigger = "default-on",
- },
-};
-
-static const struct gpio_led fb_sl_leds[] = {
- {
- .name = "1",
- .gpio = 7,
- },
- {
- .name = "2",
- .gpio = 13,
- .active_low = 1,
- },
- {
- .name = "3",
- .gpio = 10,
- .active_low = 1,
- },
- {
- .name = "4",
- .gpio = 12,
- .active_low = 1,
- },
- {
- .name = "5",
- .gpio = 9,
- .active_low = 1,
- },
-};
-
-static const struct gpio_led fb_fon_leds[] = {
- {
- .name = "1",
- .gpio = 8,
- },
- {
- .name = "2",
- .gpio = 3,
- .active_low = 1,
- },
- {
- .name = "3",
- .gpio = 5,
- },
- {
- .name = "4",
- .gpio = 4,
- .active_low = 1,
- },
- {
- .name = "5",
- .gpio = 11,
- .active_low = 1,
- },
-};
-
-static const struct gpio_led gt701_leds[] = {
- {
- .name = "inet:green",
- .gpio = 13,
- .active_low = 1,
- },
- {
- .name = "usb",
- .gpio = 12,
- .active_low = 1,
- },
- {
- .name = "inet:red",
- .gpio = 9,
- .active_low = 1,
- },
- {
- .name = "power:red",
- .gpio = 7,
- .active_low = 1,
- },
- {
- .name = "power:green",
- .gpio = 8,
- .active_low = 1,
- .default_trigger = "default-on",
- },
- {
- .name = "ethernet",
- .gpio = 10,
- .active_low = 1,
- },
-};
-
-static struct gpio_led_platform_data ar7_led_data;
-
-static struct platform_device ar7_gpio_leds = {
- .name = "leds-gpio",
- .dev = {
- .platform_data = &ar7_led_data,
- }
-};
-
-static void __init detect_leds(void)
-{
- char *prid, *usb_prod;
-
- /* Default LEDs */
- ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
- ar7_led_data.leds = default_leds;
-
- /* FIXME: the whole thing is unreliable */
- prid = prom_getenv("ProductID");
- usb_prod = prom_getenv("usb_prod");
-
- /* If we can't get the product id from PROM, use the default LEDs */
- if (!prid)
- return;
-
- if (strstr(prid, "Fritz_Box_FON")) {
- ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds);
- ar7_led_data.leds = fb_fon_leds;
- } else if (strstr(prid, "Fritz_Box_")) {
- ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds);
- ar7_led_data.leds = fb_sl_leds;
- } else if ((!strcmp(prid, "AR7RD") || !strcmp(prid, "AR7DB"))
- && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) {
- ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds);
- ar7_led_data.leds = dsl502t_leds;
- } else if (strstr(prid, "DG834")) {
- ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds);
- ar7_led_data.leds = dg834g_leds;
- } else if (strstr(prid, "CYWM") || strstr(prid, "CYWL")) {
- ar7_led_data.num_leds = ARRAY_SIZE(titan_leds);
- ar7_led_data.leds = titan_leds;
- } else if (strstr(prid, "GT701")) {
- ar7_led_data.num_leds = ARRAY_SIZE(gt701_leds);
- ar7_led_data.leds = gt701_leds;
- }
-}
-
-/*****************************************************************************
- * Watchdog
- ****************************************************************************/
-static struct resource ar7_wdt_res = {
- .name = "regs",
- .flags = IORESOURCE_MEM,
- .start = -1, /* Filled at runtime */
- .end = -1, /* Filled at runtime */
-};
-
-static struct platform_device ar7_wdt = {
- .name = "ar7_wdt",
- .resource = &ar7_wdt_res,
- .num_resources = 1,
-};
-
-/*****************************************************************************
- * Init
- ****************************************************************************/
-static int __init ar7_register_uarts(void)
-{
-#ifdef CONFIG_SERIAL_8250
- static struct uart_port uart_port __initdata;
- struct clk *bus_clk;
- int res;
-
- memset(&uart_port, 0, sizeof(struct uart_port));
-
- bus_clk = clk_get(NULL, "bus");
- if (IS_ERR(bus_clk))
- panic("unable to get bus clk");
-
- uart_port.type = PORT_AR7;
- uart_port.uartclk = clk_get_rate(bus_clk) / 2;
- uart_port.iotype = UPIO_MEM32;
- uart_port.flags = UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF;
- uart_port.regshift = 2;
-
- uart_port.line = 0;
- uart_port.irq = AR7_IRQ_UART0;
- uart_port.mapbase = AR7_REGS_UART0;
- uart_port.membase = ioremap(uart_port.mapbase, 256);
-
- res = early_serial_setup(&uart_port);
- if (res)
- return res;
-
- /* Only TNETD73xx have a second serial port */
- if (ar7_has_second_uart()) {
- uart_port.line = 1;
- uart_port.irq = AR7_IRQ_UART1;
- uart_port.mapbase = UR8_REGS_UART1;
- uart_port.membase = ioremap(uart_port.mapbase, 256);
-
- res = early_serial_setup(&uart_port);
- if (res)
- return res;
- }
-#endif
-
- return 0;
-}
-
-static void __init titan_fixup_devices(void)
-{
- /* Set vlynq0 data */
- vlynq_low_data.reset_bit = 15;
- vlynq_low_data.gpio_bit = 14;
-
- /* Set vlynq1 data */
- vlynq_high_data.reset_bit = 16;
- vlynq_high_data.gpio_bit = 7;
-
- /* Set vlynq0 resources */
- vlynq_low_res[0].start = TITAN_REGS_VLYNQ0;
- vlynq_low_res[0].end = TITAN_REGS_VLYNQ0 + 0xff;
- vlynq_low_res[1].start = 33;
- vlynq_low_res[1].end = 33;
- vlynq_low_res[2].start = 0x0c000000;
- vlynq_low_res[2].end = 0x0fffffff;
- vlynq_low_res[3].start = 80;
- vlynq_low_res[3].end = 111;
-
- /* Set vlynq1 resources */
- vlynq_high_res[0].start = TITAN_REGS_VLYNQ1;
- vlynq_high_res[0].end = TITAN_REGS_VLYNQ1 + 0xff;
- vlynq_high_res[1].start = 34;
- vlynq_high_res[1].end = 34;
- vlynq_high_res[2].start = 0x40000000;
- vlynq_high_res[2].end = 0x43ffffff;
- vlynq_high_res[3].start = 112;
- vlynq_high_res[3].end = 143;
-
- /* Set cpmac0 data */
- cpmac_low_data.phy_mask = 0x40000000;
-
- /* Set cpmac1 data */
- cpmac_high_data.phy_mask = 0x80000000;
-
- /* Set cpmac0 resources */
- cpmac_low_res[0].start = TITAN_REGS_MAC0;
- cpmac_low_res[0].end = TITAN_REGS_MAC0 + 0x7ff;
-
- /* Set cpmac1 resources */
- cpmac_high_res[0].start = TITAN_REGS_MAC1;
- cpmac_high_res[0].end = TITAN_REGS_MAC1 + 0x7ff;
-}
-
-static int __init ar7_register_devices(void)
-{
- void __iomem *bootcr;
- u32 val;
- int res;
-
- res = ar7_gpio_init();
- if (res)
- pr_warn("unable to register gpios: %d\n", res);
-
- res = ar7_register_uarts();
- if (res)
- pr_err("unable to setup uart(s): %d\n", res);
-
- res = platform_device_register(&physmap_flash);
- if (res)
- pr_warn("unable to register physmap-flash: %d\n", res);
-
- if (ar7_is_titan())
- titan_fixup_devices();
-
- ar7_device_disable(vlynq_low_data.reset_bit);
- res = platform_device_register(&vlynq_low);
- if (res)
- pr_warn("unable to register vlynq-low: %d\n", res);
-
- if (ar7_has_high_vlynq()) {
- ar7_device_disable(vlynq_high_data.reset_bit);
- res = platform_device_register(&vlynq_high);
- if (res)
- pr_warn("unable to register vlynq-high: %d\n", res);
- }
-
- if (ar7_has_high_cpmac()) {
- res = fixed_phy_add(PHY_POLL, cpmac_high.id,
- &fixed_phy_status);
- if (!res) {
- cpmac_get_mac(1, cpmac_high_data.dev_addr);
-
- res = platform_device_register(&cpmac_high);
- if (res)
- pr_warn("unable to register cpmac-high: %d\n",
- res);
- } else
- pr_warn("unable to add cpmac-high phy: %d\n", res);
- } else
- cpmac_low_data.phy_mask = 0xffffffff;
-
- res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status);
- if (!res) {
- cpmac_get_mac(0, cpmac_low_data.dev_addr);
- res = platform_device_register(&cpmac_low);
- if (res)
- pr_warn("unable to register cpmac-low: %d\n", res);
- } else
- pr_warn("unable to add cpmac-low phy: %d\n", res);
-
- detect_leds();
- res = platform_device_register(&ar7_gpio_leds);
- if (res)
- pr_warn("unable to register leds: %d\n", res);
-
- res = platform_device_register(&ar7_udc);
- if (res)
- pr_warn("unable to register usb slave: %d\n", res);
-
- /* Register watchdog only if enabled in hardware */
- bootcr = ioremap(AR7_REGS_DCL, 4);
- val = readl(bootcr);
- iounmap(bootcr);
- if (val & AR7_WDT_HW_ENA) {
- if (ar7_has_high_vlynq())
- ar7_wdt_res.start = UR8_REGS_WDT;
- else
- ar7_wdt_res.start = AR7_REGS_WDT;
-
- ar7_wdt_res.end = ar7_wdt_res.start + 0x20;
- res = platform_device_register(&ar7_wdt);
- if (res)
- pr_warn("unable to register watchdog: %d\n", res);
- }
-
- return 0;
-}
-device_initcall(ar7_register_devices);
diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c
deleted file mode 100644
index 5810d3993fc6..000000000000
--- a/arch/mips/ar7/prom.c
+++ /dev/null
@@ -1,256 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * Putting things on the screen/serial line using YAMONs facilities.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/serial_reg.h>
-#include <linux/spinlock.h>
-#include <linux/export.h>
-#include <linux/string.h>
-#include <linux/io.h>
-#include <asm/bootinfo.h>
-#include <asm/setup.h>
-
-#include <asm/mach-ar7/ar7.h>
-#include <asm/mach-ar7/prom.h>
-
-#define MAX_ENTRY 80
-
-struct env_var {
- char *name;
- char *value;
-};
-
-static struct env_var adam2_env[MAX_ENTRY];
-
-char *prom_getenv(const char *name)
-{
- int i;
-
- for (i = 0; (i < MAX_ENTRY) && adam2_env[i].name; i++)
- if (!strcmp(name, adam2_env[i].name))
- return adam2_env[i].value;
-
- return NULL;
-}
-EXPORT_SYMBOL(prom_getenv);
-
-static void __init ar7_init_cmdline(int argc, char *argv[])
-{
- int i;
-
- for (i = 1; i < argc; i++) {
- strlcat(arcs_cmdline, argv[i], COMMAND_LINE_SIZE);
- if (i < (argc - 1))
- strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
- }
-}
-
-struct psbl_rec {
- u32 psbl_size;
- u32 env_base;
- u32 env_size;
- u32 ffs_base;
- u32 ffs_size;
-};
-
-static const char psp_env_version[] __initconst = "TIENV0.8";
-
-struct psp_env_chunk {
- u8 num;
- u8 ctrl;
- u16 csum;
- u8 len;
- char data[11];
-} __packed;
-
-struct psp_var_map_entry {
- u8 num;
- char *value;
-};
-
-static const struct psp_var_map_entry psp_var_map[] = {
- { 1, "cpufrequency" },
- { 2, "memsize" },
- { 3, "flashsize" },
- { 4, "modetty0" },
- { 5, "modetty1" },
- { 8, "maca" },
- { 9, "macb" },
- { 28, "sysfrequency" },
- { 38, "mipsfrequency" },
-};
-
-/*
-
-Well-known variable (num is looked up in table above for matching variable name)
-Example: cpufrequency=211968000
-+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
-| 01 |CTRL|CHECKSUM | 01 | _2 | _1 | _1 | _9 | _6 | _8 | _0 | _0 | _0 | \0 | FF
-+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
-
-Name=Value pair in a single chunk
-Example: NAME=VALUE
-+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
-| 00 |CTRL|CHECKSUM | 01 | _N | _A | _M | _E | _0 | _V | _A | _L | _U | _E | \0
-+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
-
-Name=Value pair in 2 chunks (len is the number of chunks)
-Example: bootloaderVersion=1.3.7.15
-+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
-| 00 |CTRL|CHECKSUM | 02 | _b | _o | _o | _t | _l | _o | _a | _d | _e | _r | _V
-+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
-| _e | _r | _s | _i | _o | _n | \0 | _1 | _. | _3 | _. | _7 | _. | _1 | _5 | \0
-+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
-
-Data is padded with 0xFF
-
-*/
-
-#define PSP_ENV_SIZE 4096
-
-static char psp_env_data[PSP_ENV_SIZE] = { 0, };
-
-static char * __init lookup_psp_var_map(u8 num)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(psp_var_map); i++)
- if (psp_var_map[i].num == num)
- return psp_var_map[i].value;
-
- return NULL;
-}
-
-static void __init add_adam2_var(char *name, char *value)
-{
- int i;
-
- for (i = 0; i < MAX_ENTRY; i++) {
- if (!adam2_env[i].name) {
- adam2_env[i].name = name;
- adam2_env[i].value = value;
- return;
- } else if (!strcmp(adam2_env[i].name, name)) {
- adam2_env[i].value = value;
- return;
- }
- }
-}
-
-static int __init parse_psp_env(void *psp_env_base)
-{
- int i, n;
- char *name, *value;
- struct psp_env_chunk *chunks = (struct psp_env_chunk *)psp_env_data;
-
- memcpy_fromio(chunks, psp_env_base, PSP_ENV_SIZE);
-
- i = 1;
- n = PSP_ENV_SIZE / sizeof(struct psp_env_chunk);
- while (i < n) {
- if ((chunks[i].num == 0xff) || ((i + chunks[i].len) > n))
- break;
- value = chunks[i].data;
- if (chunks[i].num) {
- name = lookup_psp_var_map(chunks[i].num);
- } else {
- name = value;
- value += strlen(name) + 1;
- }
- if (name)
- add_adam2_var(name, value);
- i += chunks[i].len;
- }
- return 0;
-}
-
-static void __init ar7_init_env(struct env_var *env)
-{
- int i;
- struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300));
- void *psp_env = (void *)KSEG1ADDR(psbl->env_base);
-
- if (strcmp(psp_env, psp_env_version) == 0) {
- parse_psp_env(psp_env);
- } else {
- for (i = 0; i < MAX_ENTRY; i++, env++)
- if (env->name)
- add_adam2_var(env->name, env->value);
- }
-}
-
-static void __init console_config(void)
-{
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- char console_string[40];
- int baud = 0;
- char parity = '\0', bits = '\0', flow = '\0';
- char *s, *p;
-
- if (strstr(arcs_cmdline, "console="))
- return;
-
- s = prom_getenv("modetty0");
- if (s) {
- baud = simple_strtoul(s, &p, 10);
- s = p;
- if (*s == ',')
- s++;
- if (*s)
- parity = *s++;
- if (*s == ',')
- s++;
- if (*s)
- bits = *s++;
- if (*s == ',')
- s++;
- if (*s == 'h')
- flow = 'r';
- }
-
- if (baud == 0)
- baud = 38400;
- if (parity != 'n' && parity != 'o' && parity != 'e')
- parity = 'n';
- if (bits != '7' && bits != '8')
- bits = '8';
-
- if (flow == 'r')
- sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
- parity, bits, flow);
- else
- sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity,
- bits);
- strlcat(arcs_cmdline, console_string, COMMAND_LINE_SIZE);
-#endif
-}
-
-void __init prom_init(void)
-{
- ar7_init_cmdline(fw_arg0, (char **)fw_arg1);
- ar7_init_env((struct env_var *)fw_arg2);
- console_config();
-}
-
-#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4)))
-static inline unsigned int serial_in(int offset)
-{
- return readl((void *)PORT(offset));
-}
-
-static inline void serial_out(int offset, int value)
-{
- writel(value, (void *)PORT(offset));
-}
-
-void prom_putchar(char c)
-{
- while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0)
- ;
- serial_out(UART_TX, c);
-}
diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
deleted file mode 100644
index 352d5dbc777c..000000000000
--- a/arch/mips/ar7/setup.c
+++ /dev/null
@@ -1,93 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
- */
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/pm.h>
-#include <linux/time.h>
-
-#include <asm/reboot.h>
-#include <asm/mach-ar7/ar7.h>
-#include <asm/mach-ar7/prom.h>
-
-static void ar7_machine_restart(char *command)
-{
- u32 *softres_reg = ioremap(AR7_REGS_RESET + AR7_RESET_SOFTWARE, 1);
-
- writel(1, softres_reg);
-}
-
-static void ar7_machine_halt(void)
-{
- while (1)
- ;
-}
-
-static void ar7_machine_power_off(void)
-{
- u32 *power_reg = (u32 *)ioremap(AR7_REGS_POWER, 1);
- u32 power_state = readl(power_reg) | (3 << 30);
-
- writel(power_state, power_reg);
- ar7_machine_halt();
-}
-
-const char *get_system_type(void)
-{
- u16 chip_id = ar7_chip_id();
- u16 titan_variant_id = titan_chip_id();
-
- switch (chip_id) {
- case AR7_CHIP_7100:
- return "TI AR7 (TNETD7100)";
- case AR7_CHIP_7200:
- return "TI AR7 (TNETD7200)";
- case AR7_CHIP_7300:
- return "TI AR7 (TNETD7300)";
- case AR7_CHIP_TITAN:
- switch (titan_variant_id) {
- case TITAN_CHIP_1050:
- return "TI AR7 (TNETV1050)";
- case TITAN_CHIP_1055:
- return "TI AR7 (TNETV1055)";
- case TITAN_CHIP_1056:
- return "TI AR7 (TNETV1056)";
- case TITAN_CHIP_1060:
- return "TI AR7 (TNETV1060)";
- }
- fallthrough;
- default:
- return "TI AR7 (unknown)";
- }
-}
-
-static int __init ar7_init_console(void)
-{
- return 0;
-}
-console_initcall(ar7_init_console);
-
-/*
- * Initializes basic routines and structures pointers, memory size (as
- * given by the bios and saves the command line.
- */
-void __init plat_mem_setup(void)
-{
- unsigned long io_base;
-
- _machine_restart = ar7_machine_restart;
- _machine_halt = ar7_machine_halt;
- pm_power_off = ar7_machine_power_off;
-
- io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000);
- if (!io_base)
- panic("Can't remap IO base!");
- set_io_port_base(io_base);
-
- prom_meminit();
-
- printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n",
- get_system_type(), ar7_chip_id(), ar7_chip_rev());
-}
diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c
deleted file mode 100644
index 72aa77d7087b..000000000000
--- a/arch/mips/ar7/time.c
+++ /dev/null
@@ -1,31 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * Setting up the clock on the MIPS boards.
- */
-
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-
-#include <asm/time.h>
-#include <asm/mach-ar7/ar7.h>
-
-void __init plat_time_init(void)
-{
- struct clk *cpu_clk;
-
- /* Initialize ar7 clocks so the CPU clock frequency is correct */
- ar7_init_clocks();
-
- cpu_clk = clk_get(NULL, "cpu");
- if (IS_ERR(cpu_clk)) {
- printk(KERN_ERR "unable to get cpu clock\n");
- return;
- }
-
- mips_hpt_frequency = clk_get_rate(cpu_clk) / 2;
-}
diff --git a/arch/mips/boot/compressed/uart-16550.c b/arch/mips/boot/compressed/uart-16550.c
index 96d28f211121..09dcd2c561d9 100644
--- a/arch/mips/boot/compressed/uart-16550.c
+++ b/arch/mips/boot/compressed/uart-16550.c
@@ -13,11 +13,6 @@
#define PORT(offset) (CKSEG1ADDR(UART_BASE) + (offset))
#endif
-#ifdef CONFIG_AR7
-#include <ar7.h>
-#define PORT(offset) (CKSEG1ADDR(AR7_REGS_UART0) + (4 * offset))
-#endif
-
#ifdef CONFIG_MACH_INGENIC
#define INGENIC_UART_BASE_ADDR (0x10030000 + 0x1000 * CONFIG_ZBOOT_INGENIC_UART)
#define PORT(offset) (CKSEG1ADDR(INGENIC_UART_BASE_ADDR) + (4 * offset))
diff --git a/arch/mips/boot/dts/ingenic/jz4725b.dtsi b/arch/mips/boot/dts/ingenic/jz4725b.dtsi
index acbbe8c4664c..c5c5a094c37d 100644
--- a/arch/mips/boot/dts/ingenic/jz4725b.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4725b.dtsi
@@ -366,7 +366,6 @@
rom: memory@1fc00000 {
compatible = "mtd-rom";
- probe-type = "map_rom";
reg = <0x1fc00000 0x2000>;
bank-width = <4>;
diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi b/arch/mips/boot/dts/ingenic/jz4770.dtsi
index 9c0099919db7..504e895e916e 100644
--- a/arch/mips/boot/dts/ingenic/jz4770.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi
@@ -461,7 +461,6 @@
rom: memory@1fc00000 {
compatible = "mtd-rom";
- probe-type = "map_rom";
reg = <0x1fc00000 0x2000>;
bank-width = <4>;
diff --git a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
index f878f47e4501..ee3e2153dd13 100644
--- a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+++ b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
@@ -130,8 +130,7 @@
compatible = "pci0014,7a03.0",
"pci0014,7a03",
"pciclass0c0320",
- "pciclass0c03",
- "loongson, pci-gmac";
+ "pciclass0c03";
reg = <0x1800 0x0 0x0 0x0 0x0>;
interrupts = <12 IRQ_TYPE_LEVEL_LOW>,
diff --git a/arch/mips/boot/dts/loongson/ls7a-pch.dtsi b/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
index 7c69e8245c2f..cce9428afc41 100644
--- a/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
+++ b/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
@@ -193,8 +193,7 @@
compatible = "pci0014,7a03.0",
"pci0014,7a03",
"pciclass020000",
- "pciclass0200",
- "loongson, pci-gmac";
+ "pciclass0200";
reg = <0x1800 0x0 0x0 0x0 0x0>;
interrupts = <12 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc1.dts b/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc1.dts
index 129b6710b699..f9c262cc2e96 100644
--- a/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc1.dts
+++ b/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc1.dts
@@ -8,7 +8,7 @@
/ {
compatible = "gnubee,gb-pc1", "mediatek,mt7621-soc";
- model = "GB-PC1";
+ model = "GnuBee GB-PC1";
memory@0 {
device_type = "memory";
diff --git a/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts b/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts
index f810cd10f4f4..b281e13f22ed 100644
--- a/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts
+++ b/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts
@@ -8,7 +8,7 @@
/ {
compatible = "gnubee,gb-pc2", "mediatek,mt7621-soc";
- model = "GB-PC2";
+ model = "GnuBee GB-PC2";
memory@0 {
device_type = "memory";
diff --git a/arch/mips/boot/dts/ralink/mt7621.dtsi b/arch/mips/boot/dts/ralink/mt7621.dtsi
index 7caed0d14f11..35a10258f235 100644
--- a/arch/mips/boot/dts/ralink/mt7621.dtsi
+++ b/arch/mips/boot/dts/ralink/mt7621.dtsi
@@ -300,14 +300,13 @@
compatible = "mediatek,mt7621-eth";
reg = <0x1e100000 0x10000>;
- clocks = <&sysc MT7621_CLK_FE>,
- <&sysc MT7621_CLK_ETH>;
+ clocks = <&sysc MT7621_CLK_FE>, <&sysc MT7621_CLK_ETH>;
clock-names = "fe", "ethif";
#address-cells = <1>;
#size-cells = <0>;
- resets = <&sysc MT7621_RST_FE &sysc MT7621_RST_ETH>;
+ resets = <&sysc MT7621_RST_FE>, <&sysc MT7621_RST_ETH>;
reset-names = "fe", "eth";
interrupt-parent = <&gic>;
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
index 33c09688210f..08ea2cde1eb5 100644
--- a/arch/mips/cavium-octeon/smp.c
+++ b/arch/mips/cavium-octeon/smp.c
@@ -422,7 +422,7 @@ static const struct plat_smp_ops octeon_smp_ops = {
.cpu_disable = octeon_cpu_disable,
.cpu_die = octeon_cpu_die,
#endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
.kexec_nonboot_cpu = kexec_nonboot_cpu_jump,
#endif
};
@@ -502,7 +502,7 @@ static const struct plat_smp_ops octeon_78xx_smp_ops = {
.cpu_disable = octeon_cpu_disable,
.cpu_die = octeon_cpu_die,
#endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
.kexec_nonboot_cpu = kexec_nonboot_cpu_jump,
#endif
};
diff --git a/arch/mips/configs/ar7_defconfig b/arch/mips/configs/ar7_defconfig
deleted file mode 100644
index 329c60aa570a..000000000000
--- a/arch/mips/configs/ar7_defconfig
+++ /dev/null
@@ -1,119 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_KERNEL_LZMA=y
-CONFIG_SYSVIPC=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-# CONFIG_ELF_CORE is not set
-# CONFIG_KALLSYMS is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_COMPAT_BRK is not set
-CONFIG_AR7=y
-CONFIG_HZ_100=y
-CONFIG_KEXEC=y
-# CONFIG_SECCOMP is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_MROUTE=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_DIAG is not set
-CONFIG_TCP_CONG_ADVANCED=y
-# CONFIG_TCP_CONG_BIC is not set
-# CONFIG_TCP_CONG_CUBIC is not set
-CONFIG_TCP_CONG_WESTWOOD=y
-# CONFIG_TCP_CONG_HTCP is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_BRIDGE_NETFILTER is not set
-CONFIG_NF_CONNTRACK=m
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_IRC=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_RAW=m
-CONFIG_ATM=m
-CONFIG_ATM_BR2684=m
-CONFIG_ATM_BR2684_IPFILTER=y
-CONFIG_BRIDGE=y
-CONFIG_VLAN_8021Q=y
-CONFIG_NET_SCHED=y
-CONFIG_NET_CLS_ACT=y
-CONFIG_NET_ACT_POLICE=y
-CONFIG_HAMRADIO=y
-CONFIG_CFG80211=m
-CONFIG_MAC80211=m
-CONFIG_MTD=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_STAA=y
-CONFIG_MTD_COMPLEX_MAPPINGS=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_NETDEVICES=y
-CONFIG_CPMAC=y
-CONFIG_FIXED_PHY=y
-CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPPOATM=m
-CONFIG_PPPOE=m
-CONFIG_PPP_ASYNC=m
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_HW_RANDOM=y
-CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_AR7_WDT=y
-# CONFIG_USB_SUPPORT is not set
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-# CONFIG_DNOTIFY is not set
-CONFIG_PROC_KCORE=y
-# CONFIG_PROC_PAGE_MONITOR is not set
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_SQUASHFS=y
-# CONFIG_CRYPTO_HW is not set
-CONFIG_STRIP_ASM_SYMS=y
-CONFIG_DEBUG_FS=y
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="rootfstype=squashfs,jffs2"
diff --git a/arch/mips/configs/fuloong2e_defconfig b/arch/mips/configs/fuloong2e_defconfig
index 1843468f84a3..00329bb5de5a 100644
--- a/arch/mips/configs/fuloong2e_defconfig
+++ b/arch/mips/configs/fuloong2e_defconfig
@@ -177,7 +177,6 @@ CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
-CONFIG_REISERFS_FS=m
CONFIG_AUTOFS_FS=y
CONFIG_FUSE_FS=y
CONFIG_ISO9660_FS=m
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
index fdf374574105..65adb538030d 100644
--- a/arch/mips/configs/jazz_defconfig
+++ b/arch/mips/configs/jazz_defconfig
@@ -70,10 +70,6 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_HWMON is not set
CONFIG_EXT2_FS=m
CONFIG_EXT3_FS=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
CONFIG_XFS_FS=m
CONFIG_XFS_QUOTA=y
CONFIG_AUTOFS_FS=m
diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig
index 83d9a8ff4270..38f17b658421 100644
--- a/arch/mips/configs/lemote2f_defconfig
+++ b/arch/mips/configs/lemote2f_defconfig
@@ -229,9 +229,6 @@ CONFIG_EXT2_FS=m
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_PROC_INFO=y
-CONFIG_REISERFS_FS_XATTR=y
CONFIG_JFS_FS=m
CONFIG_JFS_POSIX_ACL=y
CONFIG_XFS_FS=m
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index ae1a7793e810..6f8046024557 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -317,11 +317,6 @@ CONFIG_UIO=m
CONFIG_UIO_CIF=m
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_PROC_INFO=y
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
CONFIG_JFS_FS=m
CONFIG_JFS_POSIX_ACL=y
CONFIG_JFS_SECURITY=y
diff --git a/arch/mips/configs/malta_kvm_defconfig b/arch/mips/configs/malta_kvm_defconfig
index c07e30f63d8b..16a91eeff67f 100644
--- a/arch/mips/configs/malta_kvm_defconfig
+++ b/arch/mips/configs/malta_kvm_defconfig
@@ -323,11 +323,6 @@ CONFIG_UIO=m
CONFIG_UIO_CIF=m
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_PROC_INFO=y
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
CONFIG_JFS_FS=m
CONFIG_JFS_POSIX_ACL=y
CONFIG_JFS_SECURITY=y
diff --git a/arch/mips/configs/maltaup_xpa_defconfig b/arch/mips/configs/maltaup_xpa_defconfig
index 0a5701020d3f..264aba29ea4f 100644
--- a/arch/mips/configs/maltaup_xpa_defconfig
+++ b/arch/mips/configs/maltaup_xpa_defconfig
@@ -323,11 +323,6 @@ CONFIG_UIO=m
CONFIG_UIO_CIF=m
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_PROC_INFO=y
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
CONFIG_JFS_FS=m
CONFIG_JFS_POSIX_ACL=y
CONFIG_JFS_SECURITY=y
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 5c5e2186210c..08e1c1f2f4de 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -310,10 +310,6 @@ CONFIG_USB_LD=m
CONFIG_USB_TEST=m
CONFIG_EXT2_FS=m
CONFIG_EXT3_FS=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
CONFIG_XFS_FS=m
CONFIG_XFS_QUOTA=y
CONFIG_AUTOFS_FS=m
diff --git a/arch/mips/crypto/crc32-mips.c b/arch/mips/crypto/crc32-mips.c
index 3e4f5ba104f8..ec6d58008f8e 100644
--- a/arch/mips/crypto/crc32-mips.c
+++ b/arch/mips/crypto/crc32-mips.c
@@ -290,7 +290,6 @@ static struct shash_alg crc32_alg = {
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
.cra_blocksize = CHKSUM_BLOCK_SIZE,
- .cra_alignmask = 0,
.cra_ctxsize = sizeof(struct chksum_ctx),
.cra_module = THIS_MODULE,
.cra_init = chksum_cra_init,
@@ -312,7 +311,6 @@ static struct shash_alg crc32c_alg = {
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
.cra_blocksize = CHKSUM_BLOCK_SIZE,
- .cra_alignmask = 0,
.cra_ctxsize = sizeof(struct chksum_ctx),
.cra_module = THIS_MODULE,
.cra_init = chksum_cra_init,
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index b4bf754f7db3..89f73d1a4ea4 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -73,7 +73,8 @@ int __mips_test_and_clear_bit(unsigned long nr,
volatile unsigned long *addr);
int __mips_test_and_change_bit(unsigned long nr,
volatile unsigned long *addr);
-
+bool __mips_xor_is_negative_byte(unsigned long mask,
+ volatile unsigned long *addr);
/*
* set_bit - Atomically set a bit in memory
@@ -279,6 +280,28 @@ static inline int test_and_change_bit(unsigned long nr,
return res;
}
+static inline bool xor_unlock_is_negative_byte(unsigned long mask,
+ volatile unsigned long *p)
+{
+ unsigned long orig;
+ bool res;
+
+ smp_mb__before_atomic();
+
+ if (!kernel_uses_llsc) {
+ res = __mips_xor_is_negative_byte(mask, p);
+ } else {
+ orig = __test_bit_op(*p, "%0",
+ "xor\t%1, %0, %3",
+ "ir"(mask));
+ res = (orig & BIT(7)) != 0;
+ }
+
+ smp_llsc_mb();
+
+ return res;
+}
+
#undef __bit_op
#undef __test_bit_op
diff --git a/arch/mips/include/asm/fb.h b/arch/mips/include/asm/fb.h
index 18b7226403ba..d98d6681d64e 100644
--- a/arch/mips/include/asm/fb.h
+++ b/arch/mips/include/asm/fb.h
@@ -3,14 +3,13 @@
#include <asm/page.h>
-struct file;
-
-static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
- unsigned long off)
+static inline pgprot_t pgprot_framebuffer(pgprot_t prot,
+ unsigned long vm_start, unsigned long vm_end,
+ unsigned long offset)
{
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ return pgprot_noncached(prot);
}
-#define fb_pgprotect fb_pgprotect
+#define pgprot_framebuffer pgprot_framebuffer
/*
* MIPS doesn't define __raw_ I/O macros, so the helpers
diff --git a/arch/mips/include/asm/kexec.h b/arch/mips/include/asm/kexec.h
index d6d5fa5cc31d..69e579e41e66 100644
--- a/arch/mips/include/asm/kexec.h
+++ b/arch/mips/include/asm/kexec.h
@@ -31,7 +31,7 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
prepare_frametrace(newregs);
}
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
struct kimage;
extern unsigned long kexec_args[4];
extern int (*_machine_kexec_prepare)(struct kimage *);
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index 68b1e5d458cf..bc27d99c9436 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -71,8 +71,6 @@ struct kprobe_ctlblk {
struct prev_kprobe prev_kprobe;
};
-extern int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
#endif /* CONFIG_KPROBES */
#endif /* _ASM_KPROBES_H */
diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h
index e6ae3df0349d..86fc24022242 100644
--- a/arch/mips/include/asm/local.h
+++ b/arch/mips/include/asm/local.h
@@ -108,22 +108,27 @@ static __inline__ bool local_try_cmpxchg(local_t *l, long *old, long new)
#define local_xchg(l, n) (atomic_long_xchg((&(l)->a), (n)))
/**
- * local_add_unless - add unless the number is a given value
+ * local_add_unless - add unless the number is already a given value
* @l: pointer of type local_t
* @a: the amount to add to l...
* @u: ...unless l is equal to u.
*
- * Atomically adds @a to @l, so long as it was not @u.
- * Returns non-zero if @l was not @u, and zero otherwise.
+ * Atomically adds @a to @l, if @v was not already @u.
+ * Returns true if the addition was done.
*/
-#define local_add_unless(l, a, u) \
-({ \
- long c, old; \
- c = local_read(l); \
- while (c != (u) && (old = local_cmpxchg((l), c, c + (a))) != c) \
- c = old; \
- c != (u); \
-})
+static __inline__ bool
+local_add_unless(local_t *l, long a, long u)
+{
+ long c = local_read(l);
+
+ do {
+ if (unlikely(c == u))
+ return false;
+ } while (!local_try_cmpxchg(l, &c, c + a));
+
+ return true;
+}
+
#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
#define local_dec_return(l) local_sub_return(1, (l))
diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h
deleted file mode 100644
index 1e8621a6afa3..000000000000
--- a/arch/mips/include/asm/mach-ar7/ar7.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
- */
-
-#ifndef __AR7_H__
-#define __AR7_H__
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/errno.h>
-
-#include <asm/addrspace.h>
-
-#define AR7_SDRAM_BASE 0x14000000
-
-#define AR7_REGS_BASE 0x08610000
-
-#define AR7_REGS_MAC0 (AR7_REGS_BASE + 0x0000)
-#define AR7_REGS_GPIO (AR7_REGS_BASE + 0x0900)
-/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */
-#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00)
-#define AR7_REGS_CLOCKS (AR7_REGS_POWER + 0x80)
-#define UR8_REGS_CLOCKS (AR7_REGS_POWER + 0x20)
-#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00)
-#define AR7_REGS_USB (AR7_REGS_BASE + 0x1200)
-#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600)
-#define AR7_REGS_PINSEL (AR7_REGS_BASE + 0x160C)
-#define AR7_REGS_VLYNQ0 (AR7_REGS_BASE + 0x1800)
-#define AR7_REGS_DCL (AR7_REGS_BASE + 0x1a00)
-#define AR7_REGS_VLYNQ1 (AR7_REGS_BASE + 0x1c00)
-#define AR7_REGS_MDIO (AR7_REGS_BASE + 0x1e00)
-#define AR7_REGS_IRQ (AR7_REGS_BASE + 0x2400)
-#define AR7_REGS_MAC1 (AR7_REGS_BASE + 0x2800)
-
-#define AR7_REGS_WDT (AR7_REGS_BASE + 0x1f00)
-#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00)
-#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00)
-
-/* Titan registers */
-#define TITAN_REGS_ESWITCH_BASE (0x08640000)
-#define TITAN_REGS_MAC0 (TITAN_REGS_ESWITCH_BASE)
-#define TITAN_REGS_MAC1 (TITAN_REGS_ESWITCH_BASE + 0x0800)
-#define TITAN_REGS_MDIO (TITAN_REGS_ESWITCH_BASE + 0x02000)
-#define TITAN_REGS_VLYNQ0 (AR7_REGS_BASE + 0x1c00)
-#define TITAN_REGS_VLYNQ1 (AR7_REGS_BASE + 0x1300)
-
-#define AR7_RESET_PERIPHERAL 0x0
-#define AR7_RESET_SOFTWARE 0x4
-#define AR7_RESET_STATUS 0x8
-
-#define AR7_RESET_BIT_CPMAC_LO 17
-#define AR7_RESET_BIT_CPMAC_HI 21
-#define AR7_RESET_BIT_MDIO 22
-#define AR7_RESET_BIT_EPHY 26
-
-#define TITAN_RESET_BIT_EPHY1 28
-
-/* GPIO control registers */
-#define AR7_GPIO_INPUT 0x0
-#define AR7_GPIO_OUTPUT 0x4
-#define AR7_GPIO_DIR 0x8
-#define AR7_GPIO_ENABLE 0xc
-#define TITAN_GPIO_INPUT_0 0x0
-#define TITAN_GPIO_INPUT_1 0x4
-#define TITAN_GPIO_OUTPUT_0 0x8
-#define TITAN_GPIO_OUTPUT_1 0xc
-#define TITAN_GPIO_DIR_0 0x10
-#define TITAN_GPIO_DIR_1 0x14
-#define TITAN_GPIO_ENBL_0 0x18
-#define TITAN_GPIO_ENBL_1 0x1c
-
-#define AR7_CHIP_7100 0x18
-#define AR7_CHIP_7200 0x2b
-#define AR7_CHIP_7300 0x05
-#define AR7_CHIP_TITAN 0x07
-#define TITAN_CHIP_1050 0x0f
-#define TITAN_CHIP_1055 0x0e
-#define TITAN_CHIP_1056 0x0d
-#define TITAN_CHIP_1060 0x07
-
-/* Interrupts */
-#define AR7_IRQ_UART0 15
-#define AR7_IRQ_UART1 16
-
-/* Clocks */
-#define AR7_AFE_CLOCK 35328000
-#define AR7_REF_CLOCK 25000000
-#define AR7_XTAL_CLOCK 24000000
-
-/* DCL */
-#define AR7_WDT_HW_ENA 0x10
-
-struct plat_cpmac_data {
- int reset_bit;
- int power_bit;
- u32 phy_mask;
- char dev_addr[6];
-};
-
-struct plat_dsl_data {
- int reset_bit_dsl;
- int reset_bit_sar;
-};
-
-static inline int ar7_is_titan(void)
-{
- return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x24)) & 0xffff) ==
- AR7_CHIP_TITAN;
-}
-
-static inline u16 ar7_chip_id(void)
-{
- return ar7_is_titan() ? AR7_CHIP_TITAN : (readl((void *)
- KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff);
-}
-
-static inline u16 titan_chip_id(void)
-{
- unsigned int val = readl((void *)KSEG1ADDR(AR7_REGS_GPIO +
- TITAN_GPIO_INPUT_1));
- return ((val >> 12) & 0x0f);
-}
-
-static inline u8 ar7_chip_rev(void)
-{
- return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + (ar7_is_titan() ? 0x24 :
- 0x14))) >> 16) & 0xff;
-}
-
-static inline int ar7_has_high_cpmac(void)
-{
- u16 chip_id = ar7_chip_id();
- switch (chip_id) {
- case AR7_CHIP_7100:
- case AR7_CHIP_7200:
- return 0;
- case AR7_CHIP_7300:
- return 1;
- default:
- return -ENXIO;
- }
-}
-#define ar7_has_high_vlynq ar7_has_high_cpmac
-#define ar7_has_second_uart ar7_has_high_cpmac
-
-static inline void ar7_device_enable(u32 bit)
-{
- void *reset_reg =
- (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PERIPHERAL);
- writel(readl(reset_reg) | (1 << bit), reset_reg);
- msleep(20);
-}
-
-static inline void ar7_device_disable(u32 bit)
-{
- void *reset_reg =
- (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PERIPHERAL);
- writel(readl(reset_reg) & ~(1 << bit), reset_reg);
- msleep(20);
-}
-
-static inline void ar7_device_reset(u32 bit)
-{
- ar7_device_disable(bit);
- ar7_device_enable(bit);
-}
-
-static inline void ar7_device_on(u32 bit)
-{
- void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
- writel(readl(power_reg) | (1 << bit), power_reg);
- msleep(20);
-}
-
-static inline void ar7_device_off(u32 bit)
-{
- void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
- writel(readl(power_reg) & ~(1 << bit), power_reg);
- msleep(20);
-}
-
-int __init ar7_gpio_init(void);
-void __init ar7_init_clocks(void);
-
-/* Board specific GPIO functions */
-int ar7_gpio_enable(unsigned gpio);
-int ar7_gpio_disable(unsigned gpio);
-
-#endif /* __AR7_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/irq.h b/arch/mips/include/asm/mach-ar7/irq.h
deleted file mode 100644
index 46bb730ea970..000000000000
--- a/arch/mips/include/asm/mach-ar7/irq.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Shamelessly copied from asm-mips/mach-emma2rh/
- * Copyright (C) 2003 by Ralf Baechle
- */
-#ifndef __ASM_AR7_IRQ_H
-#define __ASM_AR7_IRQ_H
-
-#define NR_IRQS 256
-
-#include <asm/mach-generic/irq.h>
-
-#endif /* __ASM_AR7_IRQ_H */
diff --git a/arch/mips/include/asm/mach-ar7/prom.h b/arch/mips/include/asm/mach-ar7/prom.h
deleted file mode 100644
index 9e1d20b06f57..000000000000
--- a/arch/mips/include/asm/mach-ar7/prom.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2006, 2007 Florian Fainelli <florian@openwrt.org>
- */
-
-#ifndef __PROM_H__
-#define __PROM_H__
-
-extern char *prom_getenv(const char *name);
-extern void prom_meminit(void);
-
-#endif /* __PROM_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/spaces.h b/arch/mips/include/asm/mach-ar7/spaces.h
deleted file mode 100644
index a004d94dfbdd..000000000000
--- a/arch/mips/include/asm/mach-ar7/spaces.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
- * Copyright (C) 2000, 2002 Maciej W. Rozycki
- * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
- */
-#ifndef _ASM_AR7_SPACES_H
-#define _ASM_AR7_SPACES_H
-
-/*
- * This handles the memory map.
- * We handle pages at KSEG0 for kernels with 32 bit address space.
- */
-#define PAGE_OFFSET _AC(0x94000000, UL)
-#define PHYS_OFFSET _AC(0x14000000, UL)
-
-#include <asm/mach-generic/spaces.h>
-
-#endif /* __ASM_AR7_SPACES_H */
diff --git a/arch/mips/include/asm/mach-loongson32/dma.h b/arch/mips/include/asm/mach-loongson32/dma.h
deleted file mode 100644
index e917b3ccb2c2..000000000000
--- a/arch/mips/include/asm/mach-loongson32/dma.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (c) 2015 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * Loongson 1 NAND platform support.
- */
-
-#ifndef __ASM_MACH_LOONGSON32_DMA_H
-#define __ASM_MACH_LOONGSON32_DMA_H
-
-#define LS1X_DMA_CHANNEL0 0
-#define LS1X_DMA_CHANNEL1 1
-#define LS1X_DMA_CHANNEL2 2
-
-struct plat_ls1x_dma {
- int nr_channels;
-};
-
-extern struct plat_ls1x_dma ls1b_dma_pdata;
-
-#endif /* __ASM_MACH_LOONGSON32_DMA_H */
diff --git a/arch/mips/include/asm/mach-loongson32/nand.h b/arch/mips/include/asm/mach-loongson32/nand.h
deleted file mode 100644
index aaf5ed19d78d..000000000000
--- a/arch/mips/include/asm/mach-loongson32/nand.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (c) 2015 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * Loongson 1 NAND platform support.
- */
-
-#ifndef __ASM_MACH_LOONGSON32_NAND_H
-#define __ASM_MACH_LOONGSON32_NAND_H
-
-#include <linux/dmaengine.h>
-#include <linux/mtd/partitions.h>
-
-struct plat_ls1x_nand {
- struct mtd_partition *parts;
- unsigned int nr_parts;
-
- int hold_cycle;
- int wait_cycle;
-};
-
-extern struct plat_ls1x_nand ls1b_nand_pdata;
-
-bool ls1x_dma_filter_fn(struct dma_chan *chan, void *param);
-
-#endif /* __ASM_MACH_LOONGSON32_NAND_H */
diff --git a/arch/mips/include/asm/mach-loongson32/platform.h b/arch/mips/include/asm/mach-loongson32/platform.h
index 2cdcfb5f6012..f74292b13bc3 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -8,9 +8,6 @@
#include <linux/platform_device.h>
-#include <dma.h>
-#include <nand.h>
-
extern struct platform_device ls1x_uart_pdev;
extern struct platform_device ls1x_eth0_pdev;
extern struct platform_device ls1x_eth1_pdev;
diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h
index 035b1a69e2d0..e007edd6b60a 100644
--- a/arch/mips/include/asm/mach-loongson64/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
@@ -14,7 +14,11 @@
#define ADAPTER_ROM 8
#define ACPI_TABLE 9
#define SMBIOS_TABLE 10
-#define MAX_MEMORY_TYPE 11
+#define UMA_VIDEO_RAM 11
+#define VUMA_VIDEO_RAM 12
+#define MAX_MEMORY_TYPE 13
+
+#define MEM_SIZE_IS_IN_BYTES (1 << 31)
#define LOONGSON3_BOOT_MEM_MAP_MAX 128
struct efi_memory_map_loongson {
@@ -117,7 +121,8 @@ struct irq_source_routing_table {
u64 pci_io_start_addr;
u64 pci_io_end_addr;
u64 pci_config_addr;
- u32 dma_mask_bits;
+ u16 dma_mask_bits;
+ u16 dma_noncoherent;
} __packed;
struct interface_info {
diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h
index 40e40a7eb94a..f4440edcd8fe 100644
--- a/arch/mips/include/asm/pgalloc.h
+++ b/arch/mips/include/asm/pgalloc.h
@@ -95,6 +95,7 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
if (!ptdesc)
return NULL;
+ pagetable_pud_ctor(ptdesc);
pud = ptdesc_address(ptdesc);
pud_init(pud);
diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h
index 5719ff49eff1..0c59e168f800 100644
--- a/arch/mips/include/asm/smp-ops.h
+++ b/arch/mips/include/asm/smp-ops.h
@@ -35,7 +35,7 @@ struct plat_smp_ops {
void (*cpu_die)(unsigned int cpu);
void (*cleanup_dead_cpu)(unsigned cpu);
#endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
void (*kexec_nonboot_cpu)(void);
#endif
};
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index a40d8c0e4b87..901bc61fa7ae 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -93,7 +93,7 @@ static inline void __cpu_die(unsigned int cpu)
extern void __noreturn play_dead(void);
#endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
static inline void kexec_nonboot_cpu(void)
{
extern const struct plat_smp_ops *mp_ops; /* private */
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
index 04aab419a0fc..e318ea11c858 100644
--- a/arch/mips/jazz/setup.c
+++ b/arch/mips/jazz/setup.c
@@ -13,7 +13,6 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/console.h>
-#include <linux/screen_info.h>
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
#include <linux/dma-mapping.h>
@@ -76,14 +75,6 @@ void __init plat_mem_setup(void)
_machine_restart = jazz_machine_restart;
-#ifdef CONFIG_VT
- screen_info = (struct screen_info) {
- .orig_video_cols = 160,
- .orig_video_lines = 64,
- .orig_video_points = 16,
- };
-#endif
-
add_preferred_console("ttyS", 0, "9600");
}
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 853a43ee4b44..ecf3278a32f7 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -90,7 +90,7 @@ obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
obj-$(CONFIG_RELOCATABLE) += relocate.o
-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
+obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o crash.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_EARLY_PRINTK_8250) += early_printk_8250.o
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 5387ed0a5186..b630604c577f 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -121,6 +121,19 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
/* Put the stack after the struct pt_regs. */
childksp = (unsigned long) childregs;
p->thread.cp0_status = (read_c0_status() & ~(ST0_CU2|ST0_CU1)) | ST0_KERNEL_CUMASK;
+
+ /*
+ * New tasks lose permission to use the fpu. This accelerates context
+ * switching for most programs since they don't use the fpu.
+ */
+ clear_tsk_thread_flag(p, TIF_USEDFPU);
+ clear_tsk_thread_flag(p, TIF_USEDMSA);
+ clear_tsk_thread_flag(p, TIF_MSA_CTX_LIVE);
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+ clear_tsk_thread_flag(p, TIF_FPUBOUND);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
if (unlikely(args->fn)) {
/* kernel thread */
unsigned long status = p->thread.cp0_status;
@@ -149,20 +162,8 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
p->thread.reg29 = (unsigned long) childregs;
p->thread.reg31 = (unsigned long) ret_from_fork;
- /*
- * New tasks lose permission to use the fpu. This accelerates context
- * switching for most programs since they don't use the fpu.
- */
childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
- clear_tsk_thread_flag(p, TIF_USEDFPU);
- clear_tsk_thread_flag(p, TIF_USEDMSA);
- clear_tsk_thread_flag(p, TIF_MSA_CTX_LIVE);
-
-#ifdef CONFIG_MIPS_MT_FPAFF
- clear_tsk_thread_flag(p, TIF_FPUBOUND);
-#endif /* CONFIG_MIPS_MT_FPAFF */
-
#ifdef CONFIG_MIPS_FP_SUPPORT
atomic_set(&p->thread.bd_emu_frame, BD_EMUFRAME_NONE);
#endif
diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S
index f5b2ef979b43..8f0a7263a9d6 100644
--- a/arch/mips/kernel/relocate_kernel.S
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -66,7 +66,6 @@ copy_word:
LONG_ADDIU s6, s6, -1
beq s6, zero, process_entry
b copy_word
- b process_entry
done:
#ifdef CONFIG_SMP
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index cb871eb784a7..2d2ca024bd47 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -15,7 +15,6 @@
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/export.h>
-#include <linux/screen_info.h>
#include <linux/memblock.h>
#include <linux/initrd.h>
#include <linux/root_dev.h>
@@ -54,10 +53,6 @@ struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_data);
-#ifdef CONFIG_VT
-struct screen_info screen_info;
-#endif
-
/*
* Setup information
*
@@ -460,7 +455,8 @@ static void __init mips_parse_crashkernel(void)
total_mem = memblock_phys_mem_size();
ret = parse_crashkernel(boot_command_line, total_mem,
- &crash_size, &crash_base);
+ &crash_size, &crash_base,
+ NULL, NULL);
if (ret != 0 || crash_size <= 0)
return;
@@ -792,12 +788,6 @@ void __init setup_arch(char **cmdline_p)
if (IS_ENABLED(CONFIG_CPU_R4X00_BUGS64))
check_bugs64_early();
-#if defined(CONFIG_VT)
-#if defined(CONFIG_VGA_CONSOLE)
- conswitchp = &vga_con;
-#endif
-#endif
-
arch_mem_init(cmdline_p);
dmi_setup();
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index c074ecce3fbf..b3dbf9ecb0d6 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -434,7 +434,7 @@ const struct plat_smp_ops bmips43xx_smp_ops = {
.cpu_disable = bmips_cpu_disable,
.cpu_die = bmips_cpu_die,
#endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
.kexec_nonboot_cpu = kexec_nonboot_cpu_jump,
#endif
};
@@ -451,7 +451,7 @@ const struct plat_smp_ops bmips5000_smp_ops = {
.cpu_disable = bmips_cpu_disable,
.cpu_die = bmips_cpu_die,
#endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
.kexec_nonboot_cpu = kexec_nonboot_cpu_jump,
#endif
};
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index dd55d59b88db..f6c37d407f36 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -392,7 +392,7 @@ static void cps_smp_finish(void)
local_irq_enable();
}
-#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC_CORE)
enum cpu_death {
CPU_DEATH_HALT,
@@ -429,7 +429,7 @@ static void cps_shutdown_this_cpu(enum cpu_death death)
}
}
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
static void cps_kexec_nonboot_cpu(void)
{
@@ -439,9 +439,9 @@ static void cps_kexec_nonboot_cpu(void)
cps_shutdown_this_cpu(CPU_DEATH_POWER);
}
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
-#endif /* CONFIG_HOTPLUG_CPU || CONFIG_KEXEC */
+#endif /* CONFIG_HOTPLUG_CPU || CONFIG_KEXEC_CORE */
#ifdef CONFIG_HOTPLUG_CPU
@@ -610,7 +610,7 @@ static const struct plat_smp_ops cps_smp_ops = {
.cpu_die = cps_cpu_die,
.cleanup_dead_cpu = cps_cleanup_dead_cpu,
#endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
.kexec_nonboot_cpu = cps_kexec_nonboot_cpu,
#endif
};
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 8fbef537fb88..82e2e051b416 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -351,10 +351,11 @@ early_initcall(mips_smp_ipi_init);
*/
asmlinkage void start_secondary(void)
{
- unsigned int cpu;
+ unsigned int cpu = raw_smp_processor_id();
cpu_probe();
per_cpu_trap_init(false);
+ rcutree_report_cpu_starting(cpu);
mips_clockevent_init();
mp_ops->init_secondary();
cpu_report();
@@ -366,7 +367,6 @@ asmlinkage void start_secondary(void)
*/
calibrate_delay();
- cpu = smp_processor_id();
cpu_data[cpu].udelay_val = loops_per_jiffy;
set_cpu_sibling_map(cpu);
diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
index 152034b8e0a0..a842b41c8e06 100644
--- a/arch/mips/kernel/syscalls/syscall_n32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
@@ -214,7 +214,7 @@
203 n32 io_submit compat_sys_io_submit
204 n32 io_cancel sys_io_cancel
205 n32 exit_group sys_exit_group
-206 n32 lookup_dcookie sys_lookup_dcookie
+206 n32 lookup_dcookie sys_ni_syscall
207 n32 epoll_create sys_epoll_create
208 n32 epoll_ctl sys_epoll_ctl
209 n32 epoll_wait sys_epoll_wait
@@ -391,3 +391,7 @@
450 n32 set_mempolicy_home_node sys_set_mempolicy_home_node
451 n32 cachestat sys_cachestat
452 n32 fchmodat2 sys_fchmodat2
+453 n32 map_shadow_stack sys_map_shadow_stack
+454 n32 futex_wake sys_futex_wake
+455 n32 futex_wait sys_futex_wait
+456 n32 futex_requeue sys_futex_requeue
diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
index cb5e757f6621..116ff501bf92 100644
--- a/arch/mips/kernel/syscalls/syscall_n64.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
@@ -214,7 +214,7 @@
203 n64 io_submit sys_io_submit
204 n64 io_cancel sys_io_cancel
205 n64 exit_group sys_exit_group
-206 n64 lookup_dcookie sys_lookup_dcookie
+206 n64 lookup_dcookie sys_ni_syscall
207 n64 epoll_create sys_epoll_create
208 n64 epoll_ctl sys_epoll_ctl
209 n64 epoll_wait sys_epoll_wait
@@ -367,3 +367,7 @@
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
451 n64 cachestat sys_cachestat
452 n64 fchmodat2 sys_fchmodat2
+453 n64 map_shadow_stack sys_map_shadow_stack
+454 n64 futex_wake sys_futex_wake
+455 n64 futex_wait sys_futex_wait
+456 n64 futex_requeue sys_futex_requeue
diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
index 1a646813afdc..525cc54bc63b 100644
--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
@@ -258,7 +258,7 @@
244 o32 io_submit sys_io_submit compat_sys_io_submit
245 o32 io_cancel sys_io_cancel
246 o32 exit_group sys_exit_group
-247 o32 lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie
+247 o32 lookup_dcookie sys_ni_syscall
248 o32 epoll_create sys_epoll_create
249 o32 epoll_ctl sys_epoll_ctl
250 o32 epoll_wait sys_epoll_wait
@@ -440,3 +440,7 @@
450 o32 set_mempolicy_home_node sys_set_mempolicy_home_node
451 o32 cachestat sys_cachestat
452 o32 fchmodat2 sys_fchmodat2
+453 o32 map_shadow_stack sys_map_shadow_stack
+454 o32 futex_wake sys_futex_wake
+455 o32 futex_wait sys_futex_wait
+456 o32 futex_requeue sys_futex_requeue
diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c
index 7b2ac1319d70..467ee6b95ae1 100644
--- a/arch/mips/kvm/mmu.c
+++ b/arch/mips/kvm/mmu.c
@@ -592,7 +592,7 @@ static int kvm_mips_map_page(struct kvm_vcpu *vcpu, unsigned long gpa,
gfn_t gfn = gpa >> PAGE_SHIFT;
int srcu_idx, err;
kvm_pfn_t pfn;
- pte_t *ptep, entry, old_pte;
+ pte_t *ptep, entry;
bool writeable;
unsigned long prot_bits;
unsigned long mmu_seq;
@@ -664,7 +664,6 @@ retry:
entry = pfn_pte(pfn, __pgprot(prot_bits));
/* Write the PTE */
- old_pte = *ptep;
set_pte(ptep, entry);
err = 0;
diff --git a/arch/mips/lib/bitops.c b/arch/mips/lib/bitops.c
index 116d0bd8b2ae..00aee98e9d54 100644
--- a/arch/mips/lib/bitops.c
+++ b/arch/mips/lib/bitops.c
@@ -146,3 +146,17 @@ int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
return res;
}
EXPORT_SYMBOL(__mips_test_and_change_bit);
+
+bool __mips_xor_is_negative_byte(unsigned long mask,
+ volatile unsigned long *addr)
+{
+ unsigned long flags;
+ unsigned long data;
+
+ raw_local_irq_save(flags);
+ data = *addr;
+ *addr = data ^ mask;
+ raw_local_irq_restore(flags);
+
+ return (data & BIT(7)) != 0;
+}
diff --git a/arch/mips/loongson32/common/platform.c b/arch/mips/loongson32/common/platform.c
index 8075590a9f83..623eb4bc7b41 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -15,8 +15,6 @@
#include <platform.h>
#include <loongson1.h>
-#include <dma.h>
-#include <nand.h>
/* 8250/16550 compatible UART */
#define LS1X_UART(_id) \
diff --git a/arch/mips/loongson32/ls1b/board.c b/arch/mips/loongson32/ls1b/board.c
index fed8d432ef20..fe115bdcb22c 100644
--- a/arch/mips/loongson32/ls1b/board.c
+++ b/arch/mips/loongson32/ls1b/board.c
@@ -8,8 +8,6 @@
#include <linux/sizes.h>
#include <loongson1.h>
-#include <dma.h>
-#include <nand.h>
#include <platform.h>
static const struct gpio_led ls1x_gpio_leds[] __initconst = {
diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c
index c961e2999f15..ef3750a6ffac 100644
--- a/arch/mips/loongson64/env.c
+++ b/arch/mips/loongson64/env.c
@@ -13,6 +13,8 @@
* Copyright (C) 2009 Lemote Inc.
* Author: Wu Zhangjin, wuzhangjin@gmail.com
*/
+
+#include <linux/dma-map-ops.h>
#include <linux/export.h>
#include <linux/pci_ids.h>
#include <asm/bootinfo.h>
@@ -147,8 +149,14 @@ void __init prom_lefi_init_env(void)
loongson_sysconf.dma_mask_bits = eirq_source->dma_mask_bits;
if (loongson_sysconf.dma_mask_bits < 32 ||
- loongson_sysconf.dma_mask_bits > 64)
+ loongson_sysconf.dma_mask_bits > 64) {
loongson_sysconf.dma_mask_bits = 32;
+ dma_default_coherent = true;
+ } else {
+ dma_default_coherent = !eirq_source->dma_noncoherent;
+ }
+
+ pr_info("Firmware: Coherent DMA: %s\n", dma_default_coherent ? "on" : "off");
loongson_sysconf.restart_addr = boot_p->reset_system.ResetWarm;
loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
diff --git a/arch/mips/loongson64/init.c b/arch/mips/loongson64/init.c
index ee8de1735b7c..f25caa6aa9d3 100644
--- a/arch/mips/loongson64/init.c
+++ b/arch/mips/loongson64/init.c
@@ -49,8 +49,7 @@ void virtual_early_config(void)
void __init szmem(unsigned int node)
{
u32 i, mem_type;
- static unsigned long num_physpages;
- u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size;
+ phys_addr_t node_id, mem_start, mem_size;
/* Otherwise come from DTB */
if (loongson_sysconf.fw_interface != LOONGSON_LEFI)
@@ -64,30 +63,46 @@ void __init szmem(unsigned int node)
mem_type = loongson_memmap->map[i].mem_type;
mem_size = loongson_memmap->map[i].mem_size;
- mem_start = loongson_memmap->map[i].mem_start;
+
+ /* Memory size comes in MB if MEM_SIZE_IS_IN_BYTES not set */
+ if (mem_size & MEM_SIZE_IS_IN_BYTES)
+ mem_size &= ~MEM_SIZE_IS_IN_BYTES;
+ else
+ mem_size = mem_size << 20;
+
+ mem_start = (node_id << 44) | loongson_memmap->map[i].mem_start;
switch (mem_type) {
case SYSTEM_RAM_LOW:
case SYSTEM_RAM_HIGH:
- start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
- node_psize = (mem_size << 20) >> PAGE_SHIFT;
- end_pfn = start_pfn + node_psize;
- num_physpages += node_psize;
- pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
- (u32)node_id, mem_type, mem_start, mem_size);
- pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
- start_pfn, end_pfn, num_physpages);
- memblock_add_node(PFN_PHYS(start_pfn),
- PFN_PHYS(node_psize), node,
+ case UMA_VIDEO_RAM:
+ pr_info("Node %d, mem_type:%d\t[%pa], %pa bytes usable\n",
+ (u32)node_id, mem_type, &mem_start, &mem_size);
+ memblock_add_node(mem_start, mem_size, node,
MEMBLOCK_NONE);
break;
case SYSTEM_RAM_RESERVED:
- pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
- (u32)node_id, mem_type, mem_start, mem_size);
- memblock_reserve(((node_id << 44) + mem_start), mem_size << 20);
+ case VIDEO_ROM:
+ case ADAPTER_ROM:
+ case ACPI_TABLE:
+ case SMBIOS_TABLE:
+ pr_info("Node %d, mem_type:%d\t[%pa], %pa bytes reserved\n",
+ (u32)node_id, mem_type, &mem_start, &mem_size);
+ memblock_reserve(mem_start, mem_size);
+ break;
+ /* We should not reserve VUMA_VIDEO_RAM as it overlaps with MMIO */
+ case VUMA_VIDEO_RAM:
+ default:
+ pr_info("Node %d, mem_type:%d\t[%pa], %pa bytes unhandled\n",
+ (u32)node_id, mem_type, &mem_start, &mem_size);
break;
}
}
+
+ /* Reserve vgabios if it comes from firmware */
+ if (loongson_sysconf.vgabios_addr)
+ memblock_reserve(virt_to_phys((void *)loongson_sysconf.vgabios_addr),
+ SZ_256K);
}
#ifndef CONFIG_NUMA
diff --git a/arch/mips/loongson64/reset.c b/arch/mips/loongson64/reset.c
index e420800043b0..e01c8d4a805a 100644
--- a/arch/mips/loongson64/reset.c
+++ b/arch/mips/loongson64/reset.c
@@ -53,7 +53,7 @@ static void loongson_halt(void)
}
}
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
/* 0X80000000~0X80200000 is safe */
#define MAX_ARGS 64
@@ -158,7 +158,7 @@ static int __init mips_reboot_setup(void)
_machine_halt = loongson_halt;
pm_power_off = loongson_poweroff;
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
kexec_argv = kmalloc(KEXEC_ARGV_SIZE, GFP_KERNEL);
if (WARN_ON(!kexec_argv))
return -ENOMEM;
diff --git a/arch/mips/loongson64/smp.c b/arch/mips/loongson64/smp.c
index e015a26a40f7..498bdc1bb0ed 100644
--- a/arch/mips/loongson64/smp.c
+++ b/arch/mips/loongson64/smp.c
@@ -864,7 +864,7 @@ const struct plat_smp_ops loongson3_smp_ops = {
.cpu_disable = loongson3_cpu_disable,
.cpu_die = loongson3_cpu_die,
#endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
.kexec_nonboot_cpu = kexec_nonboot_cpu_jump,
#endif
};
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 02042100e267..7f830634dbe7 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -117,7 +117,7 @@ void __flush_dcache_pages(struct page *page, unsigned int nr)
* get faulted into the tlb (and thus flushed) anyways.
*/
for (i = 0; i < nr; i++) {
- addr = (unsigned long)kmap_local_page(page + i);
+ addr = (unsigned long)kmap_local_page(nth_page(page, i));
flush_data_cache_page(addr);
kunmap_local((void *)addr);
}
diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c
index 21cb3ac1237b..3a2836e9d856 100644
--- a/arch/mips/mti-malta/malta-setup.c
+++ b/arch/mips/mti-malta/malta-setup.c
@@ -161,7 +161,7 @@ static void __init pci_clock_check(void)
#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
static void __init screen_info_setup(void)
{
- screen_info = (struct screen_info) {
+ static struct screen_info si = {
.orig_x = 0,
.orig_y = 25,
.ext_mem_k = 0,
@@ -175,6 +175,8 @@ static void __init screen_info_setup(void)
.orig_video_isVGA = VIDEO_TYPE_VGAC,
.orig_video_points = 16
};
+
+ vgacon_register_screen(&si);
}
#endif
diff --git a/arch/mips/pci/fixup-lantiq.c b/arch/mips/pci/fixup-lantiq.c
index 105569c1b712..13009666204f 100644
--- a/arch/mips/pci/fixup-lantiq.c
+++ b/arch/mips/pci/fixup-lantiq.c
@@ -4,8 +4,8 @@
* Copyright (C) 2012 John Crispin <john@phrozen.org>
*/
-#include <linux/of_irq.h>
#include <linux/of_pci.h>
+#include <linux/pci.h>
int (*ltq_pci_plat_arch_init)(struct pci_dev *dev) = NULL;
int (*ltq_pci_plat_dev_init)(struct pci_dev *dev) = NULL;
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index 76683993cdd3..38c90b5e8754 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -13,6 +13,7 @@
#include <linux/memblock.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/console.h>
#include <linux/screen_info.h>
#include <linux/initrd.h>
@@ -112,6 +113,19 @@ int update_persistent_clock64(struct timespec64 now)
}
}
+#ifdef CONFIG_VGA_CONSOLE
+static struct screen_info vgacon_screen_info = {
+ .orig_video_page = 52,
+ .orig_video_mode = 3,
+ .orig_video_cols = 80,
+ .flags = 12,
+ .orig_video_ega_bx = 3,
+ .orig_video_lines = 25,
+ .orig_video_isVGA = 0x22,
+ .orig_video_points = 16,
+};
+#endif
+
void __init plat_mem_setup(void)
{
#ifdef CONFIG_SIBYTE_BCM1x80
@@ -129,17 +143,8 @@ void __init plat_mem_setup(void)
if (m41t81_probe())
swarm_rtc_type = RTC_M41T81;
-#ifdef CONFIG_VT
- screen_info = (struct screen_info) {
- .orig_video_page = 52,
- .orig_video_mode = 3,
- .orig_video_cols = 80,
- .flags = 12,
- .orig_video_ega_bx = 3,
- .orig_video_lines = 25,
- .orig_video_isVGA = 0x22,
- .orig_video_points = 16,
- };
+#ifdef CONFIG_VGA_CONSOLE
+ vgacon_register_screen(&vgacon_screen_info);
/* XXXKW for CFE, get lines/cols from environment */
#endif
}
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index efad85c8c823..42fdb939c88d 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -38,19 +38,21 @@ extern void sni_machine_power_off(void);
static void __init sni_display_setup(void)
{
-#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_FW_ARC)
- struct screen_info *si = &screen_info;
+#if defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_FW_ARC)
+ static struct screen_info si;
DISPLAY_STATUS *di;
di = ArcGetDisplayStatus(1);
if (di) {
- si->orig_x = di->CursorXPosition;
- si->orig_y = di->CursorYPosition;
- si->orig_video_cols = di->CursorMaxXPosition;
- si->orig_video_lines = di->CursorMaxYPosition;
- si->orig_video_isVGA = VIDEO_TYPE_VGAC;
- si->orig_video_points = 16;
+ si.orig_x = di->CursorXPosition;
+ si.orig_y = di->CursorYPosition;
+ si.orig_video_cols = di->CursorMaxXPosition;
+ si.orig_video_lines = di->CursorMaxYPosition;
+ si.orig_video_isVGA = VIDEO_TYPE_VGAC;
+ si.orig_video_points = 16;
+
+ vgacon_register_screen(&si);
}
#endif
}
diff --git a/arch/nios2/kernel/setup.c b/arch/nios2/kernel/setup.c
index 8582ed965844..da122a5fa43b 100644
--- a/arch/nios2/kernel/setup.c
+++ b/arch/nios2/kernel/setup.c
@@ -19,7 +19,6 @@
#include <linux/memblock.h>
#include <linux/initrd.h>
#include <linux/of_fdt.h>
-#include <linux/screen_info.h>
#include <asm/mmu_context.h>
#include <asm/sections.h>
@@ -36,10 +35,6 @@ static struct pt_regs fake_regs = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0};
-#ifdef CONFIG_VT
-struct screen_info screen_info;
-#endif
-
/* Copy a short hook instruction sequence to the exception address */
static inline void copy_exception_handler(unsigned int addr)
{
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index a15ab147af2e..d14ccc948a29 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -8,6 +8,7 @@ config PARISC
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_SYSCALL_TRACEPOINTS
select ARCH_WANT_FRAME_POINTERS
+ select ARCH_HAS_DMA_ALLOC if PA11
select ARCH_HAS_ELF_RANDOMIZE
select ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_HAS_STRICT_MODULE_RWX
@@ -25,6 +26,7 @@ config PARISC
select INIT_ALL_POSSIBLE
select BUG
select BUILDTIME_TABLE_SORT
+ select HAVE_KERNEL_UNCOMPRESSED
select HAVE_PCI
select HAVE_PERF_EVENTS
select HAVE_KERNEL_BZIP2
@@ -113,9 +115,12 @@ config ARCH_HAS_ILOG2_U64
default n
config GENERIC_BUG
- bool
- default y
+ def_bool y
depends on BUG
+ select GENERIC_BUG_RELATIVE_POINTERS if 64BIT
+
+config GENERIC_BUG_RELATIVE_POINTERS
+ bool
config GENERIC_HWEIGHT
bool
@@ -138,11 +143,11 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
default 8
config ARCH_MMAP_RND_BITS_MAX
- default 24 if 64BIT
- default 17
+ default 18 if 64BIT
+ default 13
config ARCH_MMAP_RND_COMPAT_BITS_MAX
- default 17
+ default 13
# unless you want to implement ACPI on PA-RISC ... ;-)
config PM
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index 968ebe17494c..920db57b6b4c 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -177,12 +177,8 @@ vdso_prepare: prepare0
$(Q)$(MAKE) $(build)=arch/parisc/kernel/vdso32 include/generated/vdso32-offsets.h
endif
-PHONY += vdso_install
-
-vdso_install:
- $(Q)$(MAKE) $(build)=arch/parisc/kernel/vdso $@
- $(if $(CONFIG_COMPAT_VDSO), \
- $(Q)$(MAKE) $(build)=arch/parisc/kernel/vdso32 $@)
+vdso-install-y += arch/parisc/kernel/vdso32/vdso32.so
+vdso-install-$(CONFIG_64BIT) += arch/parisc/kernel/vdso64/vdso64.so
install: KBUILD_IMAGE := vmlinux
zinstall: KBUILD_IMAGE := vmlinuz
diff --git a/arch/parisc/boot/Makefile b/arch/parisc/boot/Makefile
index b873ee4720ca..657f967240ee 100644
--- a/arch/parisc/boot/Makefile
+++ b/arch/parisc/boot/Makefile
@@ -10,7 +10,7 @@ subdir- := compressed
$(obj)/image: vmlinux FORCE
$(call if_changed,objcopy)
-$(obj)/bzImage: $(obj)/compressed/vmlinux FORCE
+$(obj)/bzImage: $(if $(CONFIG_KERNEL_UNCOMPRESSED),$(objtree)/vmlinux,$(obj)/compressed/vmlinux) FORCE
$(call if_changed,objcopy)
$(obj)/compressed/vmlinux: FORCE
diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig
index f6ded7147b4d..19a804860ed5 100644
--- a/arch/parisc/configs/generic-64bit_defconfig
+++ b/arch/parisc/configs/generic-64bit_defconfig
@@ -248,7 +248,6 @@ CONFIG_UIO_AEC=m
CONFIG_UIO_SERCOS3=m
CONFIG_UIO_PCI_GENERIC=m
CONFIG_STAGING=y
-CONFIG_QLGE=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_SECURITY=y
diff --git a/arch/parisc/include/asm/alternative.h b/arch/parisc/include/asm/alternative.h
index 1ed45fd085d3..1eb488f25b83 100644
--- a/arch/parisc/include/asm/alternative.h
+++ b/arch/parisc/include/asm/alternative.h
@@ -34,7 +34,8 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
/* Alternative SMP implementation. */
#define ALTERNATIVE(cond, replacement) "!0:" \
- ".section .altinstructions, \"aw\" !" \
+ ".section .altinstructions, \"a\" !" \
+ ".align 4 !" \
".word (0b-4-.) !" \
".hword 1, " __stringify(cond) " !" \
".word " __stringify(replacement) " !" \
@@ -44,7 +45,8 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
/* to replace one single instructions by a new instruction */
#define ALTERNATIVE(from, to, cond, replacement)\
- .section .altinstructions, "aw" ! \
+ .section .altinstructions, "a" ! \
+ .align 4 ! \
.word (from - .) ! \
.hword (to - from)/4, cond ! \
.word replacement ! \
@@ -52,7 +54,8 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
/* to replace multiple instructions by new code */
#define ALTERNATIVE_CODE(from, num_instructions, cond, new_instr_ptr)\
- .section .altinstructions, "aw" ! \
+ .section .altinstructions, "a" ! \
+ .align 4 ! \
.word (from - .) ! \
.hword -num_instructions, cond ! \
.word (new_instr_ptr - .) ! \
diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h
index 75677b526b2b..74d17d7e759d 100644
--- a/arch/parisc/include/asm/assembly.h
+++ b/arch/parisc/include/asm/assembly.h
@@ -574,6 +574,7 @@
*/
#define ASM_EXCEPTIONTABLE_ENTRY(fault_addr, except_addr) \
.section __ex_table,"aw" ! \
+ .align 4 ! \
.word (fault_addr - .), (except_addr - .) ! \
.previous
diff --git a/arch/parisc/include/asm/bug.h b/arch/parisc/include/asm/bug.h
index 4b6d60b94124..833555f74ffa 100644
--- a/arch/parisc/include/asm/bug.h
+++ b/arch/parisc/include/asm/bug.h
@@ -17,24 +17,27 @@
#define PARISC_BUG_BREAK_ASM "break 0x1f, 0x1fff"
#define PARISC_BUG_BREAK_INSN 0x03ffe01f /* PARISC_BUG_BREAK_ASM */
-#if defined(CONFIG_64BIT)
-#define ASM_WORD_INSN ".dword\t"
+#ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
+# define __BUG_REL(val) ".word " __stringify(val) " - ."
#else
-#define ASM_WORD_INSN ".word\t"
+# define __BUG_REL(val) ".word " __stringify(val)
#endif
+
#ifdef CONFIG_DEBUG_BUGVERBOSE
#define BUG() \
do { \
asm volatile("\n" \
"1:\t" PARISC_BUG_BREAK_ASM "\n" \
- "\t.pushsection __bug_table,\"aw\"\n" \
- "2:\t" ASM_WORD_INSN "1b, %c0\n" \
- "\t.short %c1, %c2\n" \
- "\t.org 2b+%c3\n" \
+ "\t.pushsection __bug_table,\"a\"\n" \
+ "\t.align 4\n" \
+ "2:\t" __BUG_REL(1b) "\n" \
+ "\t" __BUG_REL(%c0) "\n" \
+ "\t.short %1, %2\n" \
+ "\t.blockz %3-2*4-2*2\n" \
"\t.popsection" \
: : "i" (__FILE__), "i" (__LINE__), \
- "i" (0), "i" (sizeof(struct bug_entry)) ); \
+ "i" (0), "i" (sizeof(struct bug_entry)) ); \
unreachable(); \
} while(0)
@@ -51,10 +54,12 @@
do { \
asm volatile("\n" \
"1:\t" PARISC_BUG_BREAK_ASM "\n" \
- "\t.pushsection __bug_table,\"aw\"\n" \
- "2:\t" ASM_WORD_INSN "1b, %c0\n" \
- "\t.short %c1, %c2\n" \
- "\t.org 2b+%c3\n" \
+ "\t.pushsection __bug_table,\"a\"\n" \
+ "\t.align 4\n" \
+ "2:\t" __BUG_REL(1b) "\n" \
+ "\t" __BUG_REL(%c0) "\n" \
+ "\t.short %1, %2\n" \
+ "\t.blockz %3-2*4-2*2\n" \
"\t.popsection" \
: : "i" (__FILE__), "i" (__LINE__), \
"i" (BUGFLAG_WARNING|(flags)), \
@@ -65,10 +70,11 @@
do { \
asm volatile("\n" \
"1:\t" PARISC_BUG_BREAK_ASM "\n" \
- "\t.pushsection __bug_table,\"aw\"\n" \
- "2:\t" ASM_WORD_INSN "1b\n" \
- "\t.short %c0\n" \
- "\t.org 2b+%c1\n" \
+ "\t.pushsection __bug_table,\"a\"\n" \
+ "\t.align 4\n" \
+ "2:\t" __BUG_REL(1b) "\n" \
+ "\t.short %0\n" \
+ "\t.blockz %1-4-2\n" \
"\t.popsection" \
: : "i" (BUGFLAG_WARNING|(flags)), \
"i" (sizeof(struct bug_entry)) ); \
diff --git a/arch/parisc/include/asm/elf.h b/arch/parisc/include/asm/elf.h
index 140eaa97bf21..2d73d3c3cd37 100644
--- a/arch/parisc/include/asm/elf.h
+++ b/arch/parisc/include/asm/elf.h
@@ -349,15 +349,7 @@ struct pt_regs; /* forward declaration... */
#define ELF_HWCAP 0
-/* Masks for stack and mmap randomization */
-#define BRK_RND_MASK (is_32bit_task() ? 0x07ffUL : 0x3ffffUL)
-#define MMAP_RND_MASK (is_32bit_task() ? 0x1fffUL : 0x3ffffUL)
-#define STACK_RND_MASK MMAP_RND_MASK
-
-struct mm_struct;
-extern unsigned long arch_randomize_brk(struct mm_struct *);
-#define arch_randomize_brk arch_randomize_brk
-
+#define STACK_RND_MASK 0x7ff /* 8MB of VA */
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
struct linux_binprm;
diff --git a/arch/parisc/include/asm/jump_label.h b/arch/parisc/include/asm/jump_label.h
index af2a598bc0f8..94428798b6aa 100644
--- a/arch/parisc/include/asm/jump_label.h
+++ b/arch/parisc/include/asm/jump_label.h
@@ -15,10 +15,12 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
asm_volatile_goto("1:\n\t"
"nop\n\t"
".pushsection __jump_table, \"aw\"\n\t"
+ ".align %1\n\t"
".word 1b - ., %l[l_yes] - .\n\t"
__stringify(ASM_ULONG_INSN) " %c0 - .\n\t"
".popsection\n\t"
- : : "i" (&((char *)key)[branch]) : : l_yes);
+ : : "i" (&((char *)key)[branch]), "i" (sizeof(long))
+ : : l_yes);
return false;
l_yes:
@@ -30,10 +32,12 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
asm_volatile_goto("1:\n\t"
"b,n %l[l_yes]\n\t"
".pushsection __jump_table, \"aw\"\n\t"
+ ".align %1\n\t"
".word 1b - ., %l[l_yes] - .\n\t"
__stringify(ASM_ULONG_INSN) " %c0 - .\n\t"
".popsection\n\t"
- : : "i" (&((char *)key)[branch]) : : l_yes);
+ : : "i" (&((char *)key)[branch]), "i" (sizeof(long))
+ : : l_yes);
return false;
l_yes:
diff --git a/arch/parisc/include/asm/ldcw.h b/arch/parisc/include/asm/ldcw.h
index ee9e071859b2..47ebc4c91eaf 100644
--- a/arch/parisc/include/asm/ldcw.h
+++ b/arch/parisc/include/asm/ldcw.h
@@ -55,7 +55,7 @@
})
#ifdef CONFIG_SMP
-# define __lock_aligned __section(".data..lock_aligned")
+# define __lock_aligned __section(".data..lock_aligned") __aligned(16)
#endif
#endif /* __PARISC_LDCW_H */
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index ff6cbdb6903b..982aca20f56f 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -47,6 +47,8 @@
#ifndef __ASSEMBLY__
+struct rlimit;
+unsigned long mmap_upper_limit(struct rlimit *rlim_stack);
unsigned long calc_max_stack_size(unsigned long stack_max);
/*
@@ -287,6 +289,7 @@ extern int _parisc_requires_coherency;
#endif
extern int running_on_qemu;
+extern int parisc_narrow_firmware;
extern void __noreturn toc_intr(struct pt_regs *regs);
extern void toc_handler(void);
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h
index 2bf660eabe42..4165079898d9 100644
--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -41,6 +41,7 @@ struct exception_table_entry {
#define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr )\
".section __ex_table,\"aw\"\n" \
+ ".align 4\n" \
".word (" #fault_addr " - .), (" #except_addr " - .)\n\t" \
".previous\n"
diff --git a/arch/parisc/include/uapi/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h
index 87245c584784..8d94739d75c6 100644
--- a/arch/parisc/include/uapi/asm/errno.h
+++ b/arch/parisc/include/uapi/asm/errno.h
@@ -75,7 +75,6 @@
/* We now return you to your regularly scheduled HPUX. */
-#define ENOSYM 215 /* symbol does not exist in executable */
#define ENOTSOCK 216 /* Socket operation on non-socket */
#define EDESTADDRREQ 217 /* Destination address required */
#define EMSGSIZE 218 /* Message too long */
@@ -101,7 +100,6 @@
#define ETIMEDOUT 238 /* Connection timed out */
#define ECONNREFUSED 239 /* Connection refused */
#define EREFUSED ECONNREFUSED /* for HP's NFS apparently */
-#define EREMOTERELEASE 240 /* Remote peer released connection */
#define EHOSTDOWN 241 /* Host is down */
#define EHOSTUNREACH 242 /* No route to host */
diff --git a/arch/parisc/include/uapi/asm/pdc.h b/arch/parisc/include/uapi/asm/pdc.h
index 7a90070136e8..fef4f2e96160 100644
--- a/arch/parisc/include/uapi/asm/pdc.h
+++ b/arch/parisc/include/uapi/asm/pdc.h
@@ -58,8 +58,8 @@
#define PDC_MODEL_NVA_SUPPORTED (0 << 4)
#define PDC_MODEL_NVA_SLOW (1 << 4)
#define PDC_MODEL_NVA_UNSUPPORTED (3 << 4)
-#define PDC_MODEL_GET_BOOT__OP 8 /* returns boot test options */
-#define PDC_MODEL_SET_BOOT__OP 9 /* set boot test options */
+#define PDC_MODEL_FIRM_TEST_GET 8 /* returns boot test options */
+#define PDC_MODEL_FIRM_TEST_SET 9 /* set boot test options */
#define PDC_MODEL_GET_PLATFORM_INFO 10 /* returns platform info */
#define PDC_MODEL_GET_INSTALL_KERNEL 11 /* returns kernel for installation */
@@ -472,6 +472,7 @@ struct pdc_model { /* for PDC_MODEL */
unsigned long arch_rev;
unsigned long pot_key;
unsigned long curr_key;
+ unsigned long width; /* default of PSW_W bit (1=enabled) */
};
struct pdc_cache_cf { /* for PDC_CACHE (I/D-caches) */
@@ -609,6 +610,12 @@ struct pdc_system_map_addr_info { /* PDC_SYSTEM_MAP/FIND_ADDRESS */
unsigned long mod_pgs;
};
+struct pdc_relocate_info_block { /* PDC_RELOCATE_INFO */
+ unsigned long pdc_size;
+ unsigned long pdc_alignment;
+ unsigned long pdc_address;
+};
+
struct pdc_initiator { /* PDC_INITIATOR */
int host_id;
int factor;
@@ -717,6 +724,23 @@ struct pdc_toc_pim_20 {
struct pim_cpu_state_cf cpu_state;
};
+/* for SpeedyBoot/firm_ctl funtionality */
+struct pdc_firm_test_get_rtn_block { /* PDC_MODEL/PDC_FIRM_TEST_GET */
+ unsigned long current_tests; /* u_R_addr Raddr_ints[0] */
+ unsigned long tests_supported; /* u_R_addr Raddr_ints[1] */
+ unsigned long default_tests; /* u_R_addr Raddr_ints[2] */
+};
+
+#define TORNADO_CPU_ID 0xB
+#define PCXL_CPU_ID 0xD
+#define PCXU_CPU_ID 0xE /* U and U+ for all but C-class with bug */
+#define VR_CPU_ID 0xF
+#define PCXU_PLUS_CPU_ID 0x10 /* U+ only on C-class with bug */
+#define PCXW_CPU_ID 0x11
+#define PCXW_PLUS_CPU_ID 0x12
+#define PIRANHA_CPU_ID 0x13
+#define MAKO_CPU_ID 0x14
+
#endif /* !defined(__ASSEMBLY__) */
#endif /* _UAPI_PARISC_PDC_H */
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index ed8b75948061..25f9b9e9d6df 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -927,8 +927,8 @@ static __init void qemu_header(void)
#define p ((unsigned long *)&boot_cpu_data.pdc.model)
pr_info("#define PARISC_PDC_MODEL 0x%lx, 0x%lx, 0x%lx, "
- "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx\n\n",
- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
+ "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx\n\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
#undef p
pr_info("#define PARISC_PDC_VERSION 0x%04lx\n\n",
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index ae03b8679696..ab23e61a6f01 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -36,6 +36,24 @@
.level 2.0
#endif
+/*
+ * We need seven instructions after a TLB insert for it to take effect.
+ * The PA8800/PA8900 processors are an exception and need 12 instructions.
+ * The RFI changes both IAOQ_Back and IAOQ_Front, so it counts as one.
+ */
+#ifdef CONFIG_64BIT
+#define NUM_PIPELINE_INSNS 12
+#else
+#define NUM_PIPELINE_INSNS 7
+#endif
+
+ /* Insert num nops */
+ .macro insert_nops num
+ .rept \num
+ nop
+ .endr
+ .endm
+
/* Get aligned page_table_lock address for this mm from cr28/tr4 */
.macro get_ptl reg
mfctl %cr28,\reg
@@ -415,24 +433,20 @@
3:
.endm
- /* Release page_table_lock without reloading lock address.
- We use an ordered store to ensure all prior accesses are
- performed prior to releasing the lock. */
- .macro ptl_unlock0 spc,tmp,tmp2
+ /* Release page_table_lock if for user space. We use an ordered
+ store to ensure all prior accesses are performed prior to
+ releasing the lock. Note stw may not be executed, so we
+ provide one extra nop when CONFIG_TLB_PTLOCK is defined. */
+ .macro ptl_unlock spc,tmp,tmp2
#ifdef CONFIG_TLB_PTLOCK
-98: ldi __ARCH_SPIN_LOCK_UNLOCKED_VAL, \tmp2
+98: get_ptl \tmp
+ ldi __ARCH_SPIN_LOCK_UNLOCKED_VAL, \tmp2
or,COND(=) %r0,\spc,%r0
stw,ma \tmp2,0(\tmp)
99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
-#endif
- .endm
-
- /* Release page_table_lock. */
- .macro ptl_unlock1 spc,tmp,tmp2
-#ifdef CONFIG_TLB_PTLOCK
-98: get_ptl \tmp
- ptl_unlock0 \spc,\tmp,\tmp2
-99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
+ insert_nops NUM_PIPELINE_INSNS - 4
+#else
+ insert_nops NUM_PIPELINE_INSNS - 1
#endif
.endm
@@ -461,13 +475,13 @@
* to a CPU TLB 4k PFN (4k => 12 bits to shift) */
#define PAGE_ADD_SHIFT (PAGE_SHIFT-12)
#define PAGE_ADD_HUGE_SHIFT (REAL_HPAGE_SHIFT-12)
+ #define PFN_START_BIT (63-ASM_PFN_PTE_SHIFT+(63-58)-PAGE_ADD_SHIFT)
/* Drop prot bits and convert to page addr for iitlbt and idtlbt */
.macro convert_for_tlb_insert20 pte,tmp
#ifdef CONFIG_HUGETLB_PAGE
copy \pte,\tmp
- extrd,u \tmp,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
- 64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
+ extrd,u \tmp,PFN_START_BIT,PFN_START_BIT+1,\pte
depdi _PAGE_SIZE_ENCODING_DEFAULT,63,\
(63-58)+PAGE_ADD_SHIFT,\pte
@@ -475,8 +489,7 @@
depdi _HUGE_PAGE_SIZE_ENCODING_DEFAULT,63,\
(63-58)+PAGE_ADD_HUGE_SHIFT,\pte
#else /* Huge pages disabled */
- extrd,u \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
- 64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
+ extrd,u \pte,PFN_START_BIT,PFN_START_BIT+1,\pte
depdi _PAGE_SIZE_ENCODING_DEFAULT,63,\
(63-58)+PAGE_ADD_SHIFT,\pte
#endif
@@ -1124,7 +1137,7 @@ dtlb_miss_20w:
idtlbt pte,prot
- ptl_unlock1 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1133,6 +1146,7 @@ dtlb_check_alias_20w:
idtlbt pte,prot
+ insert_nops NUM_PIPELINE_INSNS - 1
rfir
nop
@@ -1150,7 +1164,7 @@ nadtlb_miss_20w:
idtlbt pte,prot
- ptl_unlock1 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1159,6 +1173,7 @@ nadtlb_check_alias_20w:
idtlbt pte,prot
+ insert_nops NUM_PIPELINE_INSNS - 1
rfir
nop
@@ -1184,7 +1199,7 @@ dtlb_miss_11:
mtsp t1, %sr1 /* Restore sr1 */
- ptl_unlock1 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1194,6 +1209,7 @@ dtlb_check_alias_11:
idtlba pte,(va)
idtlbp prot,(va)
+ insert_nops NUM_PIPELINE_INSNS - 1
rfir
nop
@@ -1217,7 +1233,7 @@ nadtlb_miss_11:
mtsp t1, %sr1 /* Restore sr1 */
- ptl_unlock1 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1227,6 +1243,7 @@ nadtlb_check_alias_11:
idtlba pte,(va)
idtlbp prot,(va)
+ insert_nops NUM_PIPELINE_INSNS - 1
rfir
nop
@@ -1246,7 +1263,7 @@ dtlb_miss_20:
idtlbt pte,prot
- ptl_unlock1 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1255,6 +1272,7 @@ dtlb_check_alias_20:
idtlbt pte,prot
+ insert_nops NUM_PIPELINE_INSNS - 1
rfir
nop
@@ -1274,7 +1292,7 @@ nadtlb_miss_20:
idtlbt pte,prot
- ptl_unlock1 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1283,6 +1301,7 @@ nadtlb_check_alias_20:
idtlbt pte,prot
+ insert_nops NUM_PIPELINE_INSNS - 1
rfir
nop
@@ -1319,7 +1338,7 @@ itlb_miss_20w:
iitlbt pte,prot
- ptl_unlock1 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1343,7 +1362,7 @@ naitlb_miss_20w:
iitlbt pte,prot
- ptl_unlock1 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1352,6 +1371,7 @@ naitlb_check_alias_20w:
iitlbt pte,prot
+ insert_nops NUM_PIPELINE_INSNS - 1
rfir
nop
@@ -1377,7 +1397,7 @@ itlb_miss_11:
mtsp t1, %sr1 /* Restore sr1 */
- ptl_unlock1 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1401,7 +1421,7 @@ naitlb_miss_11:
mtsp t1, %sr1 /* Restore sr1 */
- ptl_unlock1 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1411,6 +1431,7 @@ naitlb_check_alias_11:
iitlba pte,(%sr0, va)
iitlbp prot,(%sr0, va)
+ insert_nops NUM_PIPELINE_INSNS - 1
rfir
nop
@@ -1431,7 +1452,7 @@ itlb_miss_20:
iitlbt pte,prot
- ptl_unlock1 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1451,7 +1472,7 @@ naitlb_miss_20:
iitlbt pte,prot
- ptl_unlock1 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1460,6 +1481,7 @@ naitlb_check_alias_20:
iitlbt pte,prot
+ insert_nops NUM_PIPELINE_INSNS - 1
rfir
nop
@@ -1481,7 +1503,7 @@ dbit_trap_20w:
idtlbt pte,prot
- ptl_unlock0 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
#else
@@ -1507,7 +1529,7 @@ dbit_trap_11:
mtsp t1, %sr1 /* Restore sr1 */
- ptl_unlock0 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
@@ -1527,7 +1549,7 @@ dbit_trap_20:
idtlbt pte,prot
- ptl_unlock0 spc,t0,t1
+ ptl_unlock spc,t0,t1
rfir
nop
#endif
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 81078abec521..904ca3b9e7a7 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -78,12 +78,12 @@ static unsigned long pdc_result[NUM_PDC_RESULT] __aligned(8);
static unsigned long pdc_result2[NUM_PDC_RESULT] __aligned(8);
#ifdef CONFIG_64BIT
-#define WIDE_FIRMWARE 0x1
-#define NARROW_FIRMWARE 0x2
+#define WIDE_FIRMWARE PDC_MODEL_OS64
+#define NARROW_FIRMWARE PDC_MODEL_OS32
-/* Firmware needs to be initially set to narrow to determine the
+/* Firmware needs to be initially set to narrow to determine the
* actual firmware width. */
-int parisc_narrow_firmware __ro_after_init = 2;
+int parisc_narrow_firmware __ro_after_init = NARROW_FIRMWARE;
#endif
/* On most currently-supported platforms, IODC I/O calls are 32-bit calls
@@ -166,10 +166,10 @@ void set_firmware_width_unlocked(void)
if (pdc_result[0] != NARROW_FIRMWARE)
parisc_narrow_firmware = 0;
}
-
+
/**
* set_firmware_width - Determine if the firmware is wide or narrow.
- *
+ *
* This function must be called before any pdc_* function that uses the
* convert_to_wide function.
*/
@@ -178,7 +178,7 @@ void set_firmware_width(void)
unsigned long flags;
/* already initialized? */
- if (parisc_narrow_firmware != 2)
+ if (parisc_narrow_firmware != NARROW_FIRMWARE)
return;
spin_lock_irqsave(&pdc_lock, flags);
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index a171bf3c6b31..96e0264ac961 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -70,9 +70,8 @@ $bss_loop:
stw,ma %arg2,4(%r1)
stw,ma %arg3,4(%r1)
-#if !defined(CONFIG_64BIT) && defined(CONFIG_PA20)
- /* This 32-bit kernel was compiled for PA2.0 CPUs. Check current CPU
- * and halt kernel if we detect a PA1.x CPU. */
+#if defined(CONFIG_PA20)
+ /* check for 64-bit capable CPU as required by current kernel */
ldi 32,%r10
mtctl %r10,%cr11
.level 2.0
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index 1fc89fa2c2d2..e95a977ba5f3 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -242,9 +242,9 @@ void __init collect_boot_cpu_data(void)
/* get CPU-Model Information... */
#define p ((unsigned long *)&boot_cpu_data.pdc.model)
if (pdc_model_info(&boot_cpu_data.pdc.model) == PDC_OK) {
- printk(KERN_INFO
- "model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
+ printk(KERN_INFO
+ "model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
add_device_randomness(&boot_cpu_data.pdc.model,
sizeof(boot_cpu_data.pdc.model));
@@ -383,7 +383,7 @@ show_cpuinfo (struct seq_file *m, void *v)
char cpu_name[60], *p;
/* strip PA path from CPU name to not confuse lscpu */
- strlcpy(cpu_name, per_cpu(cpu_data, 0).dev->name, sizeof(cpu_name));
+ strscpy(cpu_name, per_cpu(cpu_data, 0).dev->name, sizeof(cpu_name));
p = strrchr(cpu_name, '[');
if (p)
*(--p) = 0;
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index 2f434f2da185..ace483b6f19a 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -100,9 +100,6 @@ static void __init dma_ops_init(void)
void __init setup_arch(char **cmdline_p)
{
-#ifdef CONFIG_64BIT
- extern int parisc_narrow_firmware;
-#endif
unwind_init();
init_per_cpu(smp_processor_id()); /* Set Modes & Enable FP */
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 2019c1f04bd0..444154271f23 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -404,13 +404,7 @@ alive:
void __init smp_prepare_boot_cpu(void)
{
- int bootstrap_processor = per_cpu(cpu_data, 0).cpuid;
-
- /* Setup BSP mappings */
- printk(KERN_INFO "SMP: bootstrap CPU ID is %d\n", bootstrap_processor);
-
- set_cpu_online(bootstrap_processor, true);
- set_cpu_present(bootstrap_processor, true);
+ pr_info("SMP: bootstrap CPU ID is 0\n");
}
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index ab896eff7a1d..98af719d5f85 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -77,7 +77,7 @@ unsigned long calc_max_stack_size(unsigned long stack_max)
* indicating that "current" should be used instead of a passed-in
* value from the exec bprm as done with arch_pick_mmap_layout().
*/
-static unsigned long mmap_upper_limit(struct rlimit *rlim_stack)
+unsigned long mmap_upper_limit(struct rlimit *rlim_stack)
{
unsigned long stack_base;
diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
index e97c175b56f9..a47798fed54e 100644
--- a/arch/parisc/kernel/syscalls/syscall.tbl
+++ b/arch/parisc/kernel/syscalls/syscall.tbl
@@ -245,7 +245,7 @@
# 220 was alloc_hugepages
# 221 was free_hugepages
222 common exit_group sys_exit_group
-223 common lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie
+223 common lookup_dcookie sys_ni_syscall
224 common epoll_create sys_epoll_create
225 common epoll_ctl sys_epoll_ctl
226 common epoll_wait sys_epoll_wait
@@ -451,3 +451,7 @@
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
451 common cachestat sys_cachestat
452 common fchmodat2 sys_fchmodat2
+453 common map_shadow_stack sys_map_shadow_stack
+454 common futex_wake sys_futex_wake
+455 common futex_wait sys_futex_wait
+456 common futex_requeue sys_futex_requeue
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 58694d1989c2..548051b0b4af 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -130,6 +130,7 @@ SECTIONS
RO_DATA(8)
/* unwind info */
+ . = ALIGN(4);
.PARISC.unwind : {
__start___unwind = .;
*(.PARISC.unwind)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 3aaadfd2c8eb..6f105ee4f3cf 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -237,6 +237,7 @@ config PPC
select HAVE_EFFICIENT_UNALIGNED_ACCESS
select HAVE_FAST_GUP
select HAVE_FTRACE_MCOUNT_RECORD
+ select HAVE_FUNCTION_ARG_ACCESS_API
select HAVE_FUNCTION_DESCRIPTORS if PPC64_ELF_ABI_V1
select HAVE_FUNCTION_ERROR_INJECTION
select HAVE_FUNCTION_GRAPH_TRACER
@@ -910,7 +911,7 @@ config ARCH_FORCE_MAX_ORDER
default "6" if PPC32 && PPC_64K_PAGES
range 4 10 if PPC32 && PPC_256K_PAGES
default "4" if PPC32 && PPC_256K_PAGES
- range 10 10
+ range 10 12
default "10"
help
The kernel page allocator limits the size of maximal physically
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 2a54fadbeaf5..ea4033abc07d 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -82,6 +82,18 @@ config MSI_BITMAP_SELFTEST
bool "Run self-tests of the MSI bitmap code"
depends on DEBUG_KERNEL
+config GUEST_STATE_BUFFER_TEST
+ def_tristate n
+ prompt "Enable Guest State Buffer unit tests"
+ depends on KUNIT
+ depends on KVM_BOOK3S_HV_POSSIBLE
+ default KUNIT_ALL_TESTS
+ help
+ The Guest State Buffer is a data format specified in the PAPR.
+ It is by hcalls to communicate the state of L2 guests between
+ the L1 and L0 hypervisors. Enable unit tests for the library
+ used to create and use guest state buffers.
+
config PPC_IRQ_SOFT_MASK_DEBUG
bool "Include extra checks for powerpc irq soft masking"
depends on PPC64
@@ -147,6 +159,8 @@ config BDI_SWITCH
config BOOTX_TEXT
bool "Support for early boot text console (BootX or OpenFirmware only)"
depends on PPC_BOOK3S
+ select FONT_SUN8x16
+ select FONT_SUPPORT
help
Say Y here to see progress messages from the boot firmware in text
mode. Requires either BootX or Open Firmware.
diff --git a/arch/powerpc/Makefile.postlink b/arch/powerpc/Makefile.postlink
index 1f860b3c9bec..ae5a4256b03d 100644
--- a/arch/powerpc/Makefile.postlink
+++ b/arch/powerpc/Makefile.postlink
@@ -35,9 +35,6 @@ ifdef CONFIG_RELOCATABLE
$(call if_changed,relocs_check)
endif
-%.ko: FORCE
- @true
-
clean:
rm -f .tmp_symbols.txt
diff --git a/arch/powerpc/boot/install.sh b/arch/powerpc/boot/install.sh
index 461902c8a46d..101fcb397a0f 100755
--- a/arch/powerpc/boot/install.sh
+++ b/arch/powerpc/boot/install.sh
@@ -21,13 +21,17 @@ set -e
# this should work for both the pSeries zImage and the iSeries vmlinux.sm
image_name=`basename $2`
-if [ -f $4/$image_name ]; then
- mv $4/$image_name $4/$image_name.old
+
+echo "Warning: '${INSTALLKERNEL}' command not available... Copying" \
+ "directly to $4/$image_name-$1" >&2
+
+if [ -f $4/$image_name-$1 ]; then
+ mv $4/$image_name-$1 $4/$image_name-$1.old
fi
-if [ -f $4/System.map ]; then
- mv $4/System.map $4/System.old
+if [ -f $4/System.map-$1 ]; then
+ mv $4/System.map-$1 $4/System-$1.old
fi
-cat $2 > $4/$image_name
-cp $3 $4/System.map
+cat $2 > $4/$image_name-$1
+cp $3 $4/System.map-$1
diff --git a/arch/powerpc/configs/44x/sam440ep_defconfig b/arch/powerpc/configs/44x/sam440ep_defconfig
index 51499ee6366b..2479ab62d12f 100644
--- a/arch/powerpc/configs/44x/sam440ep_defconfig
+++ b/arch/powerpc/configs/44x/sam440ep_defconfig
@@ -78,7 +78,6 @@ CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS=y
CONFIG_AUTOFS_FS=y
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
diff --git a/arch/powerpc/configs/debug.config b/arch/powerpc/configs/debug.config
index a14ae1f20d60..bcc1fcf25e10 100644
--- a/arch/powerpc/configs/debug.config
+++ b/arch/powerpc/configs/debug.config
@@ -1 +1,5 @@
+CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG=y
+CONFIG_PPC_IRQ_SOFT_MASK_DEBUG=y
+CONFIG_PPC_KUAP_DEBUG=y
+CONFIG_PPC_RFI_SRR_DEBUG=y
CONFIG_SCOM_DEBUGFS=y
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 71d9d112c0b6..9215bed53291 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -202,10 +202,6 @@ CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
-CONFIG_REISERFS_FS=y
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
CONFIG_XFS_FS=m
CONFIG_XFS_POSIX_ACL=y
CONFIG_FS_DAX=y
diff --git a/arch/powerpc/configs/hardening.config b/arch/powerpc/configs/hardening.config
new file mode 100644
index 000000000000..4e9bba327e8f
--- /dev/null
+++ b/arch/powerpc/configs/hardening.config
@@ -0,0 +1,10 @@
+# PowerPC specific hardening options
+
+# Block kernel from unexpectedly reading userspace memory.
+CONFIG_PPC_KUAP=y
+
+# Attack surface reduction.
+# CONFIG_SCOM_DEBUGFS is not set
+
+# Disable internal kernel debugger.
+# CONFIG_XMON is not set
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index a205da9ee5f2..57ded82c2840 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -138,7 +138,6 @@ CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
CONFIG_ADB=y
-CONFIG_ADB_CUDA=y
CONFIG_ADB_PMU=y
CONFIG_ADB_PMU_LED=y
CONFIG_ADB_PMU_LED_DISK=y
@@ -181,6 +180,7 @@ CONFIG_SERIAL_PMACZILOG_TTYS=y
CONFIG_SERIAL_PMACZILOG_CONSOLE=y
CONFIG_NVRAM=y
CONFIG_I2C_CHARDEV=m
+CONFIG_POWER_RESET=y
CONFIG_APM_POWER=y
CONFIG_BATTERY_PMU=y
CONFIG_HWMON=m
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig
index 624c371ffcc3..4c05f4e4d505 100644
--- a/arch/powerpc/configs/ppc64e_defconfig
+++ b/arch/powerpc/configs/ppc64e_defconfig
@@ -175,10 +175,6 @@ CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
-CONFIG_REISERFS_FS=y
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
CONFIG_JFS_FS=y
CONFIG_JFS_POSIX_ACL=y
CONFIG_JFS_SECURITY=y
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index eaf3273372a9..f279703425d4 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -954,11 +954,6 @@ CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_JBD2_DEBUG=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_PROC_INFO=y
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
CONFIG_JFS_FS=m
CONFIG_JFS_POSIX_ACL=y
CONFIG_JFS_SECURITY=y
diff --git a/arch/powerpc/configs/skiroot_defconfig b/arch/powerpc/configs/skiroot_defconfig
index 8d3eacb50d56..9d44e6630908 100644
--- a/arch/powerpc/configs/skiroot_defconfig
+++ b/arch/powerpc/configs/skiroot_defconfig
@@ -301,7 +301,6 @@ CONFIG_WQ_WATCHDOG=y
CONFIG_DEBUG_SG=y
CONFIG_DEBUG_NOTIFIERS=y
CONFIG_BUG_ON_DATA_CORRUPTION=y
-CONFIG_DEBUG_CREDENTIALS=y
# CONFIG_FTRACE is not set
CONFIG_XMON=y
# CONFIG_RUNTIME_TESTING_MENU is not set
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
index 7e0f0322912b..671ecc6711e3 100644
--- a/arch/powerpc/include/asm/bitops.h
+++ b/arch/powerpc/include/asm/bitops.h
@@ -233,35 +233,24 @@ static inline int arch_test_and_change_bit(unsigned long nr,
return test_and_change_bits(BIT_MASK(nr), addr + BIT_WORD(nr)) != 0;
}
-#ifdef CONFIG_PPC64
-static inline unsigned long
-clear_bit_unlock_return_word(int nr, volatile unsigned long *addr)
+static inline bool arch_xor_unlock_is_negative_byte(unsigned long mask,
+ volatile unsigned long *p)
{
unsigned long old, t;
- unsigned long *p = (unsigned long *)addr + BIT_WORD(nr);
- unsigned long mask = BIT_MASK(nr);
__asm__ __volatile__ (
PPC_RELEASE_BARRIER
"1:" PPC_LLARX "%0,0,%3,0\n"
- "andc %1,%0,%2\n"
+ "xor %1,%0,%2\n"
PPC_STLCX "%1,0,%3\n"
"bne- 1b\n"
: "=&r" (old), "=&r" (t)
: "r" (mask), "r" (p)
: "cc", "memory");
- return old;
+ return (old & BIT_MASK(7)) != 0;
}
-
-/*
- * This is a special function for mm/filemap.c
- * Bit 7 corresponds to PG_waiters.
- */
-#define arch_clear_bit_unlock_is_negative_byte(nr, addr) \
- (clear_bit_unlock_return_word(nr, addr) & BIT_MASK(7))
-
-#endif /* CONFIG_PPC64 */
+#define arch_xor_unlock_is_negative_byte arch_xor_unlock_is_negative_byte
#include <asm-generic/bitops/non-atomic.h>
diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h
index 9b13eb14e21b..52971ee30717 100644
--- a/arch/powerpc/include/asm/book3s/32/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/32/pgtable.h
@@ -20,7 +20,7 @@
#define _PAGE_PRESENT 0x001 /* software: pte contains a translation */
#define _PAGE_HASHPTE 0x002 /* hash_page has made an HPTE for this pte */
-#define _PAGE_USER 0x004 /* usermode access allowed */
+#define _PAGE_READ 0x004 /* software: read access allowed */
#define _PAGE_GUARDED 0x008 /* G: prohibit speculative access */
#define _PAGE_COHERENT 0x010 /* M: enforce memory coherence (SMP systems) */
#define _PAGE_NO_CACHE 0x020 /* I: cache inhibit */
@@ -28,7 +28,7 @@
#define _PAGE_DIRTY 0x080 /* C: page changed */
#define _PAGE_ACCESSED 0x100 /* R: page referenced */
#define _PAGE_EXEC 0x200 /* software: exec allowed */
-#define _PAGE_RW 0x400 /* software: user write access allowed */
+#define _PAGE_WRITE 0x400 /* software: user write access allowed */
#define _PAGE_SPECIAL 0x800 /* software: Special page */
#ifdef CONFIG_PTE_64BIT
@@ -42,26 +42,13 @@
#define _PMD_PRESENT_MASK (PAGE_MASK)
#define _PMD_BAD (~PAGE_MASK)
-/* We borrow the _PAGE_USER bit to store the exclusive marker in swap PTEs. */
-#define _PAGE_SWP_EXCLUSIVE _PAGE_USER
+/* We borrow the _PAGE_READ bit to store the exclusive marker in swap PTEs. */
+#define _PAGE_SWP_EXCLUSIVE _PAGE_READ
/* And here we include common definitions */
-#define _PAGE_KERNEL_RO 0
-#define _PAGE_KERNEL_ROX (_PAGE_EXEC)
-#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW)
-#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC)
-
#define _PAGE_HPTEFLAGS _PAGE_HASHPTE
-#ifndef __ASSEMBLY__
-
-static inline bool pte_user(pte_t pte)
-{
- return pte_val(pte) & _PAGE_USER;
-}
-#endif /* __ASSEMBLY__ */
-
/*
* Location of the PFN in the PTE. Most 32-bit platforms use the same
* as _PAGE_SHIFT here (ie, naturally aligned).
@@ -97,20 +84,7 @@ static inline bool pte_user(pte_t pte)
#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED)
#define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT)
-/*
- * Permission masks used to generate the __P and __S table.
- *
- * Note:__pgprot is defined in arch/powerpc/include/asm/page.h
- *
- * Write permissions imply read permissions for now.
- */
-#define PAGE_NONE __pgprot(_PAGE_BASE)
-#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
-#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
-#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#include <asm/pgtable-masks.h>
/* Permission masks used for kernel mappings */
#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)
@@ -170,7 +144,14 @@ void unmap_kernel_page(unsigned long va);
* value (for now) on others, from where we can start layout kernel
* virtual space that goes below PKMAP and FIXMAP
*/
-#include <asm/fixmap.h>
+
+#define FIXADDR_SIZE 0
+#ifdef CONFIG_KASAN
+#include <asm/kasan.h>
+#define FIXADDR_TOP (KASAN_SHADOW_START - PAGE_SIZE)
+#else
+#define FIXADDR_TOP ((unsigned long)(-PAGE_SIZE))
+#endif
/*
* ioremap_bot starts at that address. Early ioremaps move down from there,
@@ -224,9 +205,6 @@ void unmap_kernel_page(unsigned long va);
/* Bits to mask out from a PGD to get to the PUD page */
#define PGD_MASKED_BITS 0
-#define pte_ERROR(e) \
- pr_err("%s:%d: bad pte %llx.\n", __FILE__, __LINE__, \
- (unsigned long long)pte_val(e))
#define pgd_ERROR(e) \
pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
/*
@@ -343,7 +321,7 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
{
- pte_update(mm, addr, ptep, _PAGE_RW, 0, 0);
+ pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 0);
}
static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
@@ -402,8 +380,16 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
}
/* Generic accessors to PTE bits */
-static inline int pte_write(pte_t pte) { return !!(pte_val(pte) & _PAGE_RW);}
-static inline int pte_read(pte_t pte) { return 1; }
+static inline bool pte_read(pte_t pte)
+{
+ return !!(pte_val(pte) & _PAGE_READ);
+}
+
+static inline bool pte_write(pte_t pte)
+{
+ return !!(pte_val(pte) & _PAGE_WRITE);
+}
+
static inline int pte_dirty(pte_t pte) { return !!(pte_val(pte) & _PAGE_DIRTY); }
static inline int pte_young(pte_t pte) { return !!(pte_val(pte) & _PAGE_ACCESSED); }
static inline int pte_special(pte_t pte) { return !!(pte_val(pte) & _PAGE_SPECIAL); }
@@ -438,10 +424,10 @@ static inline bool pte_ci(pte_t pte)
static inline bool pte_access_permitted(pte_t pte, bool write)
{
/*
- * A read-only access is controlled by _PAGE_USER bit.
- * We have _PAGE_READ set for WRITE and EXECUTE
+ * A read-only access is controlled by _PAGE_READ bit.
+ * We have _PAGE_READ set for WRITE
*/
- if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte))
+ if (!pte_present(pte) || !pte_read(pte))
return false;
if (write && !pte_write(pte))
@@ -465,7 +451,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
/* Generic modifiers for PTE bits */
static inline pte_t pte_wrprotect(pte_t pte)
{
- return __pte(pte_val(pte) & ~_PAGE_RW);
+ return __pte(pte_val(pte) & ~_PAGE_WRITE);
}
static inline pte_t pte_exprotect(pte_t pte)
@@ -495,6 +481,9 @@ static inline pte_t pte_mkpte(pte_t pte)
static inline pte_t pte_mkwrite_novma(pte_t pte)
{
+ /*
+ * write implies read, hence set both
+ */
return __pte(pte_val(pte) | _PAGE_RW);
}
@@ -518,16 +507,6 @@ static inline pte_t pte_mkhuge(pte_t pte)
return pte;
}
-static inline pte_t pte_mkprivileged(pte_t pte)
-{
- return __pte(pte_val(pte) & ~_PAGE_USER);
-}
-
-static inline pte_t pte_mkuser(pte_t pte)
-{
- return __pte(pte_val(pte) | _PAGE_USER);
-}
-
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
diff --git a/arch/powerpc/include/asm/book3s/32/tlbflush.h b/arch/powerpc/include/asm/book3s/32/tlbflush.h
index 4be572908124..e43534da5207 100644
--- a/arch/powerpc/include/asm/book3s/32/tlbflush.h
+++ b/arch/powerpc/include/asm/book3s/32/tlbflush.h
@@ -80,7 +80,7 @@ static inline void local_flush_tlb_page(struct vm_area_struct *vma,
static inline void local_flush_tlb_page_psize(struct mm_struct *mm,
unsigned long vmaddr, int psize)
{
- BUILD_BUG();
+ flush_range(mm, vmaddr, vmaddr);
}
static inline void local_flush_tlb_mm(struct mm_struct *mm)
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
index 5c497c862d75..cb77eddca54b 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -17,6 +17,10 @@
#define _PAGE_EXEC 0x00001 /* execute permission */
#define _PAGE_WRITE 0x00002 /* write access allowed */
#define _PAGE_READ 0x00004 /* read access allowed */
+#define _PAGE_NA _PAGE_PRIVILEGED
+#define _PAGE_NAX _PAGE_EXEC
+#define _PAGE_RO _PAGE_READ
+#define _PAGE_ROX (_PAGE_READ | _PAGE_EXEC)
#define _PAGE_RW (_PAGE_READ | _PAGE_WRITE)
#define _PAGE_RWX (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)
#define _PAGE_PRIVILEGED 0x00008 /* kernel access only */
@@ -136,23 +140,7 @@
#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED)
#define _PAGE_BASE (_PAGE_BASE_NC)
-/* Permission masks used to generate the __P and __S table,
- *
- * Note:__pgprot is defined in arch/powerpc/include/asm/page.h
- *
- * Write permissions imply read permissions for now (we could make write-only
- * pages on BookE but we don't bother for now). Execute permission control is
- * possible on platforms that define _PAGE_EXEC
- */
-#define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_PRIVILEGED)
-#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_RW)
-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_EXEC)
-#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_READ)
-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC)
-#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_READ)
-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC)
-/* Radix only, Hash uses PAGE_READONLY_X + execute-only pkey instead */
-#define PAGE_EXECONLY __pgprot(_PAGE_BASE | _PAGE_EXEC)
+#include <asm/pgtable-masks.h>
/* Permission masks used for kernel mappings */
#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)
@@ -316,6 +304,7 @@ extern unsigned long pci_io_base;
#define IOREMAP_START (ioremap_bot)
#define IOREMAP_END (KERN_IO_END - FIXADDR_SIZE)
#define FIXADDR_SIZE SZ_32M
+#define FIXADDR_TOP (IOREMAP_END + FIXADDR_SIZE)
#ifndef __ASSEMBLY__
@@ -629,16 +618,6 @@ static inline pte_t pte_mkdevmap(pte_t pte)
return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SPECIAL | _PAGE_DEVMAP));
}
-static inline pte_t pte_mkprivileged(pte_t pte)
-{
- return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PRIVILEGED));
-}
-
-static inline pte_t pte_mkuser(pte_t pte)
-{
- return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_PRIVILEGED));
-}
-
/*
* This is potentially called with a pmd as the argument, in which case it's not
* safe to check _PAGE_DEVMAP unless we also confirm that _PAGE_PTE is set.
@@ -647,7 +626,7 @@ static inline pte_t pte_mkuser(pte_t pte)
*/
static inline int pte_devmap(pte_t pte)
{
- u64 mask = cpu_to_be64(_PAGE_DEVMAP | _PAGE_PTE);
+ __be64 mask = cpu_to_be64(_PAGE_DEVMAP | _PAGE_PTE);
return (pte_raw(pte) & mask) == mask;
}
@@ -1014,8 +993,6 @@ static inline pmd_t *pud_pgtable(pud_t pud)
return (pmd_t *)__va(pud_val(pud) & ~PUD_MASKED_BITS);
}
-#define pte_ERROR(e) \
- pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
#define pmd_ERROR(e) \
pr_err("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
#define pud_ERROR(e) \
diff --git a/arch/powerpc/include/asm/book3s/pgtable.h b/arch/powerpc/include/asm/book3s/pgtable.h
index 3b7bd36a2321..f42d68c6b314 100644
--- a/arch/powerpc/include/asm/book3s/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/pgtable.h
@@ -8,37 +8,4 @@
#include <asm/book3s/32/pgtable.h>
#endif
-#ifndef __ASSEMBLY__
-#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
- pte_t *ptep, pte_t entry, int dirty);
-
-struct file;
-extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
- unsigned long size, pgprot_t vma_prot);
-#define __HAVE_PHYS_MEM_ACCESS_PROT
-
-void __update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep);
-
-/*
- * This gets called at the end of handling a page fault, when
- * the kernel has put a new PTE into the page table for the process.
- * We use it to ensure coherency between the i-cache and d-cache
- * for the page which has just been mapped in.
- * On machines which use an MMU hash table, we use this to put a
- * corresponding HPTE into the hash table ahead of time, instead of
- * waiting for the inevitable extra hash-table miss exception.
- */
-static inline void update_mmu_cache_range(struct vm_fault *vmf,
- struct vm_area_struct *vma, unsigned long address,
- pte_t *ptep, unsigned int nr)
-{
- if (IS_ENABLED(CONFIG_PPC32) && !mmu_has_feature(MMU_FTR_HPTE_TABLE))
- return;
- if (radix_enabled())
- return;
- __update_mmu_cache(vma, address, ptep);
-}
-
-#endif /* __ASSEMBLY__ */
#endif
diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index 3f881548fb61..0e29ccf903d0 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -74,6 +74,7 @@ int create_cond_branch(ppc_inst_t *instr, const u32 *addr,
int patch_branch(u32 *addr, unsigned long target, int flags);
int patch_instruction(u32 *addr, ppc_inst_t instr);
int raw_patch_instruction(u32 *addr, ppc_inst_t instr);
+int patch_instructions(u32 *addr, u32 *code, size_t len, bool repeat_instr);
static inline unsigned long patch_site_addr(s32 *site)
{
diff --git a/arch/powerpc/include/asm/cpm1.h b/arch/powerpc/include/asm/cpm1.h
index 3bdd74739cb8..e3c6969853ef 100644
--- a/arch/powerpc/include/asm/cpm1.h
+++ b/arch/powerpc/include/asm/cpm1.h
@@ -49,11 +49,6 @@
*/
extern cpm8xx_t __iomem *cpmp; /* Pointer to comm processor */
-#define cpm_dpalloc cpm_muram_alloc
-#define cpm_dpfree cpm_muram_free
-#define cpm_dpram_addr cpm_muram_addr
-#define cpm_dpram_phys cpm_muram_dma
-
extern void cpm_setbrg(uint brg, uint rate);
extern void __init cpm_load_patch(cpm8xx_t *cp);
diff --git a/arch/powerpc/include/asm/cpm2.h b/arch/powerpc/include/asm/cpm2.h
index 249d43cc6427..a22acc36eb9b 100644
--- a/arch/powerpc/include/asm/cpm2.h
+++ b/arch/powerpc/include/asm/cpm2.h
@@ -87,10 +87,6 @@
*/
extern cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor */
-#define cpm_dpalloc cpm_muram_alloc
-#define cpm_dpfree cpm_muram_free
-#define cpm_dpram_addr cpm_muram_addr
-
extern void cpm2_reset(void);
/* Baud rate generators.
diff --git a/arch/powerpc/include/asm/fb.h b/arch/powerpc/include/asm/fb.h
index 5f1a2e5f7654..c0c5d1df7ad1 100644
--- a/arch/powerpc/include/asm/fb.h
+++ b/arch/powerpc/include/asm/fb.h
@@ -2,18 +2,15 @@
#ifndef _ASM_FB_H_
#define _ASM_FB_H_
-#include <linux/fs.h>
-
#include <asm/page.h>
-static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
- unsigned long off)
+static inline pgprot_t pgprot_framebuffer(pgprot_t prot,
+ unsigned long vm_start, unsigned long vm_end,
+ unsigned long offset)
{
- vma->vm_page_prot = phys_mem_access_prot(file, off >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot);
+ return __phys_mem_access_prot(PHYS_PFN(offset), vm_end - vm_start, prot);
}
-#define fb_pgprotect fb_pgprotect
+#define pgprot_framebuffer pgprot_framebuffer
#include <asm-generic/fb.h>
diff --git a/arch/powerpc/include/asm/fixmap.h b/arch/powerpc/include/asm/fixmap.h
index a832aeafe560..f9068dd8dfce 100644
--- a/arch/powerpc/include/asm/fixmap.h
+++ b/arch/powerpc/include/asm/fixmap.h
@@ -23,18 +23,6 @@
#include <asm/kmap_size.h>
#endif
-#ifdef CONFIG_PPC64
-#define FIXADDR_TOP (IOREMAP_END + FIXADDR_SIZE)
-#else
-#define FIXADDR_SIZE 0
-#ifdef CONFIG_KASAN
-#include <asm/kasan.h>
-#define FIXADDR_TOP (KASAN_SHADOW_START - PAGE_SIZE)
-#else
-#define FIXADDR_TOP ((unsigned long)(-PAGE_SIZE))
-#endif
-#endif
-
/*
* Here we define all the compile-time 'special' virtual
* addresses. The point is to have a constant address at
@@ -119,5 +107,9 @@ static inline void __set_fixmap(enum fixed_addresses idx,
#define __early_set_fixmap __set_fixmap
+#ifdef CONFIG_PPC_8xx
+#define VIRT_IMMR_BASE (__fix_to_virt(FIX_IMMR_BASE))
+#endif
+
#endif /* !__ASSEMBLY__ */
#endif
diff --git a/arch/powerpc/include/asm/guest-state-buffer.h b/arch/powerpc/include/asm/guest-state-buffer.h
new file mode 100644
index 000000000000..808149f31576
--- /dev/null
+++ b/arch/powerpc/include/asm/guest-state-buffer.h
@@ -0,0 +1,995 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Interface based on include/net/netlink.h
+ */
+#ifndef _ASM_POWERPC_GUEST_STATE_BUFFER_H
+#define _ASM_POWERPC_GUEST_STATE_BUFFER_H
+
+#include "asm/hvcall.h"
+#include <linux/gfp.h>
+#include <linux/bitmap.h>
+#include <asm/plpar_wrappers.h>
+
+/**************************************************************************
+ * Guest State Buffer Constants
+ **************************************************************************/
+/* Element without a value and any length */
+#define KVMPPC_GSID_BLANK 0x0000
+/* Size required for the L0's internal VCPU representation */
+#define KVMPPC_GSID_HOST_STATE_SIZE 0x0001
+ /* Minimum size for the H_GUEST_RUN_VCPU output buffer */
+#define KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE 0x0002
+ /* "Logical" PVR value as defined in the PAPR */
+#define KVMPPC_GSID_LOGICAL_PVR 0x0003
+ /* L0 relative timebase offset */
+#define KVMPPC_GSID_TB_OFFSET 0x0004
+ /* Partition Scoped Page Table Info */
+#define KVMPPC_GSID_PARTITION_TABLE 0x0005
+ /* Process Table Info */
+#define KVMPPC_GSID_PROCESS_TABLE 0x0006
+
+/* H_GUEST_RUN_VCPU input buffer Info */
+#define KVMPPC_GSID_RUN_INPUT 0x0C00
+/* H_GUEST_RUN_VCPU output buffer Info */
+#define KVMPPC_GSID_RUN_OUTPUT 0x0C01
+#define KVMPPC_GSID_VPA 0x0C02
+
+#define KVMPPC_GSID_GPR(x) (0x1000 + (x))
+#define KVMPPC_GSID_HDEC_EXPIRY_TB 0x1020
+#define KVMPPC_GSID_NIA 0x1021
+#define KVMPPC_GSID_MSR 0x1022
+#define KVMPPC_GSID_LR 0x1023
+#define KVMPPC_GSID_XER 0x1024
+#define KVMPPC_GSID_CTR 0x1025
+#define KVMPPC_GSID_CFAR 0x1026
+#define KVMPPC_GSID_SRR0 0x1027
+#define KVMPPC_GSID_SRR1 0x1028
+#define KVMPPC_GSID_DAR 0x1029
+#define KVMPPC_GSID_DEC_EXPIRY_TB 0x102A
+#define KVMPPC_GSID_VTB 0x102B
+#define KVMPPC_GSID_LPCR 0x102C
+#define KVMPPC_GSID_HFSCR 0x102D
+#define KVMPPC_GSID_FSCR 0x102E
+#define KVMPPC_GSID_FPSCR 0x102F
+#define KVMPPC_GSID_DAWR0 0x1030
+#define KVMPPC_GSID_DAWR1 0x1031
+#define KVMPPC_GSID_CIABR 0x1032
+#define KVMPPC_GSID_PURR 0x1033
+#define KVMPPC_GSID_SPURR 0x1034
+#define KVMPPC_GSID_IC 0x1035
+#define KVMPPC_GSID_SPRG0 0x1036
+#define KVMPPC_GSID_SPRG1 0x1037
+#define KVMPPC_GSID_SPRG2 0x1038
+#define KVMPPC_GSID_SPRG3 0x1039
+#define KVMPPC_GSID_PPR 0x103A
+#define KVMPPC_GSID_MMCR(x) (0x103B + (x))
+#define KVMPPC_GSID_MMCRA 0x103F
+#define KVMPPC_GSID_SIER(x) (0x1040 + (x))
+#define KVMPPC_GSID_BESCR 0x1043
+#define KVMPPC_GSID_EBBHR 0x1044
+#define KVMPPC_GSID_EBBRR 0x1045
+#define KVMPPC_GSID_AMR 0x1046
+#define KVMPPC_GSID_IAMR 0x1047
+#define KVMPPC_GSID_AMOR 0x1048
+#define KVMPPC_GSID_UAMOR 0x1049
+#define KVMPPC_GSID_SDAR 0x104A
+#define KVMPPC_GSID_SIAR 0x104B
+#define KVMPPC_GSID_DSCR 0x104C
+#define KVMPPC_GSID_TAR 0x104D
+#define KVMPPC_GSID_DEXCR 0x104E
+#define KVMPPC_GSID_HDEXCR 0x104F
+#define KVMPPC_GSID_HASHKEYR 0x1050
+#define KVMPPC_GSID_HASHPKEYR 0x1051
+#define KVMPPC_GSID_CTRL 0x1052
+
+#define KVMPPC_GSID_CR 0x2000
+#define KVMPPC_GSID_PIDR 0x2001
+#define KVMPPC_GSID_DSISR 0x2002
+#define KVMPPC_GSID_VSCR 0x2003
+#define KVMPPC_GSID_VRSAVE 0x2004
+#define KVMPPC_GSID_DAWRX0 0x2005
+#define KVMPPC_GSID_DAWRX1 0x2006
+#define KVMPPC_GSID_PMC(x) (0x2007 + (x))
+#define KVMPPC_GSID_WORT 0x200D
+#define KVMPPC_GSID_PSPB 0x200E
+
+#define KVMPPC_GSID_VSRS(x) (0x3000 + (x))
+
+#define KVMPPC_GSID_HDAR 0xF000
+#define KVMPPC_GSID_HDSISR 0xF001
+#define KVMPPC_GSID_HEIR 0xF002
+#define KVMPPC_GSID_ASDR 0xF003
+
+#define KVMPPC_GSE_GUESTWIDE_START KVMPPC_GSID_BLANK
+#define KVMPPC_GSE_GUESTWIDE_END KVMPPC_GSID_PROCESS_TABLE
+#define KVMPPC_GSE_GUESTWIDE_COUNT \
+ (KVMPPC_GSE_GUESTWIDE_END - KVMPPC_GSE_GUESTWIDE_START + 1)
+
+#define KVMPPC_GSE_META_START KVMPPC_GSID_RUN_INPUT
+#define KVMPPC_GSE_META_END KVMPPC_GSID_VPA
+#define KVMPPC_GSE_META_COUNT (KVMPPC_GSE_META_END - KVMPPC_GSE_META_START + 1)
+
+#define KVMPPC_GSE_DW_REGS_START KVMPPC_GSID_GPR(0)
+#define KVMPPC_GSE_DW_REGS_END KVMPPC_GSID_CTRL
+#define KVMPPC_GSE_DW_REGS_COUNT \
+ (KVMPPC_GSE_DW_REGS_END - KVMPPC_GSE_DW_REGS_START + 1)
+
+#define KVMPPC_GSE_W_REGS_START KVMPPC_GSID_CR
+#define KVMPPC_GSE_W_REGS_END KVMPPC_GSID_PSPB
+#define KVMPPC_GSE_W_REGS_COUNT \
+ (KVMPPC_GSE_W_REGS_END - KVMPPC_GSE_W_REGS_START + 1)
+
+#define KVMPPC_GSE_VSRS_START KVMPPC_GSID_VSRS(0)
+#define KVMPPC_GSE_VSRS_END KVMPPC_GSID_VSRS(63)
+#define KVMPPC_GSE_VSRS_COUNT (KVMPPC_GSE_VSRS_END - KVMPPC_GSE_VSRS_START + 1)
+
+#define KVMPPC_GSE_INTR_REGS_START KVMPPC_GSID_HDAR
+#define KVMPPC_GSE_INTR_REGS_END KVMPPC_GSID_ASDR
+#define KVMPPC_GSE_INTR_REGS_COUNT \
+ (KVMPPC_GSE_INTR_REGS_END - KVMPPC_GSE_INTR_REGS_START + 1)
+
+#define KVMPPC_GSE_IDEN_COUNT \
+ (KVMPPC_GSE_GUESTWIDE_COUNT + KVMPPC_GSE_META_COUNT + \
+ KVMPPC_GSE_DW_REGS_COUNT + KVMPPC_GSE_W_REGS_COUNT + \
+ KVMPPC_GSE_VSRS_COUNT + KVMPPC_GSE_INTR_REGS_COUNT)
+
+/**
+ * Ranges of guest state buffer elements
+ */
+enum {
+ KVMPPC_GS_CLASS_GUESTWIDE = 0x01,
+ KVMPPC_GS_CLASS_META = 0x02,
+ KVMPPC_GS_CLASS_DWORD_REG = 0x04,
+ KVMPPC_GS_CLASS_WORD_REG = 0x08,
+ KVMPPC_GS_CLASS_VECTOR = 0x10,
+ KVMPPC_GS_CLASS_INTR = 0x20,
+};
+
+/**
+ * Types of guest state buffer elements
+ */
+enum {
+ KVMPPC_GSE_BE32,
+ KVMPPC_GSE_BE64,
+ KVMPPC_GSE_VEC128,
+ KVMPPC_GSE_PARTITION_TABLE,
+ KVMPPC_GSE_PROCESS_TABLE,
+ KVMPPC_GSE_BUFFER,
+ __KVMPPC_GSE_TYPE_MAX,
+};
+
+/**
+ * Flags for guest state elements
+ */
+enum {
+ KVMPPC_GS_FLAGS_WIDE = 0x01,
+};
+
+/**
+ * struct kvmppc_gs_part_table - deserialized partition table information
+ * element
+ * @address: start of the partition table
+ * @ea_bits: number of bits in the effective address
+ * @gpd_size: root page directory size
+ */
+struct kvmppc_gs_part_table {
+ u64 address;
+ u64 ea_bits;
+ u64 gpd_size;
+};
+
+/**
+ * struct kvmppc_gs_proc_table - deserialized process table information element
+ * @address: start of the process table
+ * @gpd_size: process table size
+ */
+struct kvmppc_gs_proc_table {
+ u64 address;
+ u64 gpd_size;
+};
+
+/**
+ * struct kvmppc_gs_buff_info - deserialized meta guest state buffer information
+ * @address: start of the guest state buffer
+ * @size: size of the guest state buffer
+ */
+struct kvmppc_gs_buff_info {
+ u64 address;
+ u64 size;
+};
+
+/**
+ * struct kvmppc_gs_header - serialized guest state buffer header
+ * @nelem: count of guest state elements in the buffer
+ * @data: start of the stream of elements in the buffer
+ */
+struct kvmppc_gs_header {
+ __be32 nelems;
+ char data[];
+} __packed;
+
+/**
+ * struct kvmppc_gs_elem - serialized guest state buffer element
+ * @iden: Guest State ID
+ * @len: length of data
+ * @data: the guest state buffer element's value
+ */
+struct kvmppc_gs_elem {
+ __be16 iden;
+ __be16 len;
+ char data[];
+} __packed;
+
+/**
+ * struct kvmppc_gs_buff - a guest state buffer with metadata.
+ * @capacity: total length of the buffer
+ * @len: current length of the elements and header
+ * @guest_id: guest id associated with the buffer
+ * @vcpu_id: vcpu_id associated with the buffer
+ * @hdr: the serialised guest state buffer
+ */
+struct kvmppc_gs_buff {
+ size_t capacity;
+ size_t len;
+ unsigned long guest_id;
+ unsigned long vcpu_id;
+ struct kvmppc_gs_header *hdr;
+};
+
+/**
+ * struct kvmppc_gs_bitmap - a bitmap for element ids
+ * @bitmap: a bitmap large enough for all Guest State IDs
+ */
+struct kvmppc_gs_bitmap {
+ /* private: */
+ DECLARE_BITMAP(bitmap, KVMPPC_GSE_IDEN_COUNT);
+};
+
+/**
+ * struct kvmppc_gs_parser - a map of element ids to locations in a buffer
+ * @iterator: bitmap used for iterating
+ * @gses: contains the pointers to elements
+ *
+ * A guest state parser is used for deserialising a guest state buffer.
+ * Given a buffer, it then allows looking up guest state elements using
+ * a guest state id.
+ */
+struct kvmppc_gs_parser {
+ /* private: */
+ struct kvmppc_gs_bitmap iterator;
+ struct kvmppc_gs_elem *gses[KVMPPC_GSE_IDEN_COUNT];
+};
+
+enum {
+ GSM_GUEST_WIDE = 0x1,
+ GSM_SEND = 0x2,
+ GSM_RECEIVE = 0x4,
+ GSM_GSB_OWNER = 0x8,
+};
+
+struct kvmppc_gs_msg;
+
+/**
+ * struct kvmppc_gs_msg_ops - guest state message behavior
+ * @get_size: maximum size required for the message data
+ * @fill_info: serializes to the guest state buffer format
+ * @refresh_info: dserializes from the guest state buffer format
+ */
+struct kvmppc_gs_msg_ops {
+ size_t (*get_size)(struct kvmppc_gs_msg *gsm);
+ int (*fill_info)(struct kvmppc_gs_buff *gsb, struct kvmppc_gs_msg *gsm);
+ int (*refresh_info)(struct kvmppc_gs_msg *gsm,
+ struct kvmppc_gs_buff *gsb);
+};
+
+/**
+ * struct kvmppc_gs_msg - a guest state message
+ * @bitmap: the guest state ids that should be included
+ * @ops: modify message behavior for reading and writing to buffers
+ * @flags: guest wide or thread wide
+ * @data: location where buffer data will be written to or from.
+ *
+ * A guest state message is allows flexibility in sending in receiving data
+ * in a guest state buffer format.
+ */
+struct kvmppc_gs_msg {
+ struct kvmppc_gs_bitmap bitmap;
+ struct kvmppc_gs_msg_ops *ops;
+ unsigned long flags;
+ void *data;
+};
+
+/**************************************************************************
+ * Guest State IDs
+ **************************************************************************/
+
+u16 kvmppc_gsid_size(u16 iden);
+unsigned long kvmppc_gsid_flags(u16 iden);
+u64 kvmppc_gsid_mask(u16 iden);
+
+/**************************************************************************
+ * Guest State Buffers
+ **************************************************************************/
+struct kvmppc_gs_buff *kvmppc_gsb_new(size_t size, unsigned long guest_id,
+ unsigned long vcpu_id, gfp_t flags);
+void kvmppc_gsb_free(struct kvmppc_gs_buff *gsb);
+void *kvmppc_gsb_put(struct kvmppc_gs_buff *gsb, size_t size);
+int kvmppc_gsb_send(struct kvmppc_gs_buff *gsb, unsigned long flags);
+int kvmppc_gsb_recv(struct kvmppc_gs_buff *gsb, unsigned long flags);
+
+/**
+ * kvmppc_gsb_header() - the header of a guest state buffer
+ * @gsb: guest state buffer
+ *
+ * Returns a pointer to the buffer header.
+ */
+static inline struct kvmppc_gs_header *
+kvmppc_gsb_header(struct kvmppc_gs_buff *gsb)
+{
+ return gsb->hdr;
+}
+
+/**
+ * kvmppc_gsb_data() - the elements of a guest state buffer
+ * @gsb: guest state buffer
+ *
+ * Returns a pointer to the first element of the buffer data.
+ */
+static inline struct kvmppc_gs_elem *kvmppc_gsb_data(struct kvmppc_gs_buff *gsb)
+{
+ return (struct kvmppc_gs_elem *)kvmppc_gsb_header(gsb)->data;
+}
+
+/**
+ * kvmppc_gsb_len() - the current length of a guest state buffer
+ * @gsb: guest state buffer
+ *
+ * Returns the length including the header of a buffer.
+ */
+static inline size_t kvmppc_gsb_len(struct kvmppc_gs_buff *gsb)
+{
+ return gsb->len;
+}
+
+/**
+ * kvmppc_gsb_capacity() - the capacity of a guest state buffer
+ * @gsb: guest state buffer
+ *
+ * Returns the capacity of a buffer.
+ */
+static inline size_t kvmppc_gsb_capacity(struct kvmppc_gs_buff *gsb)
+{
+ return gsb->capacity;
+}
+
+/**
+ * kvmppc_gsb_paddress() - the physical address of buffer
+ * @gsb: guest state buffer
+ *
+ * Returns the physical address of the buffer.
+ */
+static inline u64 kvmppc_gsb_paddress(struct kvmppc_gs_buff *gsb)
+{
+ return __pa(kvmppc_gsb_header(gsb));
+}
+
+/**
+ * kvmppc_gsb_nelems() - the number of elements in a buffer
+ * @gsb: guest state buffer
+ *
+ * Returns the number of elements in a buffer
+ */
+static inline u32 kvmppc_gsb_nelems(struct kvmppc_gs_buff *gsb)
+{
+ return be32_to_cpu(kvmppc_gsb_header(gsb)->nelems);
+}
+
+/**
+ * kvmppc_gsb_reset() - empty a guest state buffer
+ * @gsb: guest state buffer
+ *
+ * Reset the number of elements and length of buffer to empty.
+ */
+static inline void kvmppc_gsb_reset(struct kvmppc_gs_buff *gsb)
+{
+ kvmppc_gsb_header(gsb)->nelems = cpu_to_be32(0);
+ gsb->len = sizeof(struct kvmppc_gs_header);
+}
+
+/**
+ * kvmppc_gsb_data_len() - the length of a buffer excluding the header
+ * @gsb: guest state buffer
+ *
+ * Returns the length of a buffer excluding the header
+ */
+static inline size_t kvmppc_gsb_data_len(struct kvmppc_gs_buff *gsb)
+{
+ return gsb->len - sizeof(struct kvmppc_gs_header);
+}
+
+/**
+ * kvmppc_gsb_data_cap() - the capacity of a buffer excluding the header
+ * @gsb: guest state buffer
+ *
+ * Returns the capacity of a buffer excluding the header
+ */
+static inline size_t kvmppc_gsb_data_cap(struct kvmppc_gs_buff *gsb)
+{
+ return gsb->capacity - sizeof(struct kvmppc_gs_header);
+}
+
+/**
+ * kvmppc_gsb_for_each_elem - iterate over the elements in a buffer
+ * @i: loop counter
+ * @pos: set to current element
+ * @gsb: guest state buffer
+ * @rem: initialized to buffer capacity, holds bytes currently remaining in
+ * stream
+ */
+#define kvmppc_gsb_for_each_elem(i, pos, gsb, rem) \
+ kvmppc_gse_for_each_elem(i, kvmppc_gsb_nelems(gsb), pos, \
+ kvmppc_gsb_data(gsb), \
+ kvmppc_gsb_data_cap(gsb), rem)
+
+/**************************************************************************
+ * Guest State Elements
+ **************************************************************************/
+
+/**
+ * kvmppc_gse_iden() - guest state ID of element
+ * @gse: guest state element
+ *
+ * Return the guest state ID in host endianness.
+ */
+static inline u16 kvmppc_gse_iden(const struct kvmppc_gs_elem *gse)
+{
+ return be16_to_cpu(gse->iden);
+}
+
+/**
+ * kvmppc_gse_len() - length of guest state element data
+ * @gse: guest state element
+ *
+ * Returns the length of guest state element data
+ */
+static inline u16 kvmppc_gse_len(const struct kvmppc_gs_elem *gse)
+{
+ return be16_to_cpu(gse->len);
+}
+
+/**
+ * kvmppc_gse_total_len() - total length of guest state element
+ * @gse: guest state element
+ *
+ * Returns the length of the data plus the ID and size header.
+ */
+static inline u16 kvmppc_gse_total_len(const struct kvmppc_gs_elem *gse)
+{
+ return be16_to_cpu(gse->len) + sizeof(*gse);
+}
+
+/**
+ * kvmppc_gse_total_size() - space needed for a given data length
+ * @size: data length
+ *
+ * Returns size plus the space needed for the ID and size header.
+ */
+static inline u16 kvmppc_gse_total_size(u16 size)
+{
+ return sizeof(struct kvmppc_gs_elem) + size;
+}
+
+/**
+ * kvmppc_gse_data() - pointer to data of a guest state element
+ * @gse: guest state element
+ *
+ * Returns a pointer to the beginning of guest state element data.
+ */
+static inline void *kvmppc_gse_data(const struct kvmppc_gs_elem *gse)
+{
+ return (void *)gse->data;
+}
+
+/**
+ * kvmppc_gse_ok() - checks space exists for guest state element
+ * @gse: guest state element
+ * @remaining: bytes of space remaining
+ *
+ * Returns true if the guest state element can fit in remaining space.
+ */
+static inline bool kvmppc_gse_ok(const struct kvmppc_gs_elem *gse,
+ int remaining)
+{
+ return remaining >= kvmppc_gse_total_len(gse);
+}
+
+/**
+ * kvmppc_gse_next() - iterate to the next guest state element in a stream
+ * @gse: stream of guest state elements
+ * @remaining: length of the guest element stream
+ *
+ * Returns the next guest state element in a stream of elements. The length of
+ * the stream is updated in remaining.
+ */
+static inline struct kvmppc_gs_elem *
+kvmppc_gse_next(const struct kvmppc_gs_elem *gse, int *remaining)
+{
+ int len = sizeof(*gse) + kvmppc_gse_len(gse);
+
+ *remaining -= len;
+ return (struct kvmppc_gs_elem *)(gse->data + kvmppc_gse_len(gse));
+}
+
+/**
+ * kvmppc_gse_for_each_elem - iterate over a stream of guest state elements
+ * @i: loop counter
+ * @max: number of elements
+ * @pos: set to current element
+ * @head: head of elements
+ * @len: length of the stream
+ * @rem: initialized to len, holds bytes currently remaining elements
+ */
+#define kvmppc_gse_for_each_elem(i, max, pos, head, len, rem) \
+ for (i = 0, pos = head, rem = len; kvmppc_gse_ok(pos, rem) && i < max; \
+ pos = kvmppc_gse_next(pos, &(rem)), i++)
+
+int __kvmppc_gse_put(struct kvmppc_gs_buff *gsb, u16 iden, u16 size,
+ const void *data);
+int kvmppc_gse_parse(struct kvmppc_gs_parser *gsp, struct kvmppc_gs_buff *gsb);
+
+/**
+ * kvmppc_gse_put_be32() - add a be32 guest state element to a buffer
+ * @gsb: guest state buffer to add element to
+ * @iden: guest state ID
+ * @val: big endian value
+ */
+static inline int kvmppc_gse_put_be32(struct kvmppc_gs_buff *gsb, u16 iden,
+ __be32 val)
+{
+ __be32 tmp;
+
+ tmp = val;
+ return __kvmppc_gse_put(gsb, iden, sizeof(__be32), &tmp);
+}
+
+/**
+ * kvmppc_gse_put_u32() - add a host endian 32bit int guest state element to a
+ * buffer
+ * @gsb: guest state buffer to add element to
+ * @iden: guest state ID
+ * @val: host endian value
+ */
+static inline int kvmppc_gse_put_u32(struct kvmppc_gs_buff *gsb, u16 iden,
+ u32 val)
+{
+ __be32 tmp;
+
+ val &= kvmppc_gsid_mask(iden);
+ tmp = cpu_to_be32(val);
+ return kvmppc_gse_put_be32(gsb, iden, tmp);
+}
+
+/**
+ * kvmppc_gse_put_be64() - add a be64 guest state element to a buffer
+ * @gsb: guest state buffer to add element to
+ * @iden: guest state ID
+ * @val: big endian value
+ */
+static inline int kvmppc_gse_put_be64(struct kvmppc_gs_buff *gsb, u16 iden,
+ __be64 val)
+{
+ __be64 tmp;
+
+ tmp = val;
+ return __kvmppc_gse_put(gsb, iden, sizeof(__be64), &tmp);
+}
+
+/**
+ * kvmppc_gse_put_u64() - add a host endian 64bit guest state element to a
+ * buffer
+ * @gsb: guest state buffer to add element to
+ * @iden: guest state ID
+ * @val: host endian value
+ */
+static inline int kvmppc_gse_put_u64(struct kvmppc_gs_buff *gsb, u16 iden,
+ u64 val)
+{
+ __be64 tmp;
+
+ val &= kvmppc_gsid_mask(iden);
+ tmp = cpu_to_be64(val);
+ return kvmppc_gse_put_be64(gsb, iden, tmp);
+}
+
+/**
+ * __kvmppc_gse_put_reg() - add a register type guest state element to a buffer
+ * @gsb: guest state buffer to add element to
+ * @iden: guest state ID
+ * @val: host endian value
+ *
+ * Adds a register type guest state element. Uses the guest state ID for
+ * determining the length of the guest element. If the guest state ID has
+ * bits that can not be set they will be cleared.
+ */
+static inline int __kvmppc_gse_put_reg(struct kvmppc_gs_buff *gsb, u16 iden,
+ u64 val)
+{
+ val &= kvmppc_gsid_mask(iden);
+ if (kvmppc_gsid_size(iden) == sizeof(u64))
+ return kvmppc_gse_put_u64(gsb, iden, val);
+
+ if (kvmppc_gsid_size(iden) == sizeof(u32)) {
+ u32 tmp;
+
+ tmp = (u32)val;
+ if (tmp != val)
+ return -EINVAL;
+
+ return kvmppc_gse_put_u32(gsb, iden, tmp);
+ }
+ return -EINVAL;
+}
+
+/**
+ * kvmppc_gse_put_vector128() - add a vector guest state element to a buffer
+ * @gsb: guest state buffer to add element to
+ * @iden: guest state ID
+ * @val: 16 byte vector value
+ */
+static inline int kvmppc_gse_put_vector128(struct kvmppc_gs_buff *gsb, u16 iden,
+ vector128 *val)
+{
+ __be64 tmp[2] = { 0 };
+ union {
+ __vector128 v;
+ u64 dw[2];
+ } u;
+
+ u.v = *val;
+ tmp[0] = cpu_to_be64(u.dw[TS_FPROFFSET]);
+#ifdef CONFIG_VSX
+ tmp[1] = cpu_to_be64(u.dw[TS_VSRLOWOFFSET]);
+#endif
+ return __kvmppc_gse_put(gsb, iden, sizeof(tmp), &tmp);
+}
+
+/**
+ * kvmppc_gse_put_part_table() - add a partition table guest state element to a
+ * buffer
+ * @gsb: guest state buffer to add element to
+ * @iden: guest state ID
+ * @val: partition table value
+ */
+static inline int kvmppc_gse_put_part_table(struct kvmppc_gs_buff *gsb,
+ u16 iden,
+ struct kvmppc_gs_part_table val)
+{
+ __be64 tmp[3];
+
+ tmp[0] = cpu_to_be64(val.address);
+ tmp[1] = cpu_to_be64(val.ea_bits);
+ tmp[2] = cpu_to_be64(val.gpd_size);
+ return __kvmppc_gse_put(gsb, KVMPPC_GSID_PARTITION_TABLE, sizeof(tmp),
+ &tmp);
+}
+
+/**
+ * kvmppc_gse_put_proc_table() - add a process table guest state element to a
+ * buffer
+ * @gsb: guest state buffer to add element to
+ * @iden: guest state ID
+ * @val: process table value
+ */
+static inline int kvmppc_gse_put_proc_table(struct kvmppc_gs_buff *gsb,
+ u16 iden,
+ struct kvmppc_gs_proc_table val)
+{
+ __be64 tmp[2];
+
+ tmp[0] = cpu_to_be64(val.address);
+ tmp[1] = cpu_to_be64(val.gpd_size);
+ return __kvmppc_gse_put(gsb, KVMPPC_GSID_PROCESS_TABLE, sizeof(tmp),
+ &tmp);
+}
+
+/**
+ * kvmppc_gse_put_buff_info() - adds a GSB description guest state element to a
+ * buffer
+ * @gsb: guest state buffer to add element to
+ * @iden: guest state ID
+ * @val: guest state buffer description value
+ */
+static inline int kvmppc_gse_put_buff_info(struct kvmppc_gs_buff *gsb, u16 iden,
+ struct kvmppc_gs_buff_info val)
+{
+ __be64 tmp[2];
+
+ tmp[0] = cpu_to_be64(val.address);
+ tmp[1] = cpu_to_be64(val.size);
+ return __kvmppc_gse_put(gsb, iden, sizeof(tmp), &tmp);
+}
+
+int __kvmppc_gse_put(struct kvmppc_gs_buff *gsb, u16 iden, u16 size,
+ const void *data);
+
+/**
+ * kvmppc_gse_get_be32() - return the data of a be32 element
+ * @gse: guest state element
+ */
+static inline __be32 kvmppc_gse_get_be32(const struct kvmppc_gs_elem *gse)
+{
+ if (WARN_ON(kvmppc_gse_len(gse) != sizeof(__be32)))
+ return 0;
+ return *(__be32 *)kvmppc_gse_data(gse);
+}
+
+/**
+ * kvmppc_gse_get_u32() - return the data of a be32 element in host endianness
+ * @gse: guest state element
+ */
+static inline u32 kvmppc_gse_get_u32(const struct kvmppc_gs_elem *gse)
+{
+ return be32_to_cpu(kvmppc_gse_get_be32(gse));
+}
+
+/**
+ * kvmppc_gse_get_be64() - return the data of a be64 element
+ * @gse: guest state element
+ */
+static inline __be64 kvmppc_gse_get_be64(const struct kvmppc_gs_elem *gse)
+{
+ if (WARN_ON(kvmppc_gse_len(gse) != sizeof(__be64)))
+ return 0;
+ return *(__be64 *)kvmppc_gse_data(gse);
+}
+
+/**
+ * kvmppc_gse_get_u64() - return the data of a be64 element in host endianness
+ * @gse: guest state element
+ */
+static inline u64 kvmppc_gse_get_u64(const struct kvmppc_gs_elem *gse)
+{
+ return be64_to_cpu(kvmppc_gse_get_be64(gse));
+}
+
+/**
+ * kvmppc_gse_get_vector128() - return the data of a vector element
+ * @gse: guest state element
+ */
+static inline void kvmppc_gse_get_vector128(const struct kvmppc_gs_elem *gse,
+ vector128 *v)
+{
+ union {
+ __vector128 v;
+ u64 dw[2];
+ } u = { 0 };
+ __be64 *src;
+
+ if (WARN_ON(kvmppc_gse_len(gse) != sizeof(__vector128)))
+ *v = u.v;
+
+ src = (__be64 *)kvmppc_gse_data(gse);
+ u.dw[TS_FPROFFSET] = be64_to_cpu(src[0]);
+#ifdef CONFIG_VSX
+ u.dw[TS_VSRLOWOFFSET] = be64_to_cpu(src[1]);
+#endif
+ *v = u.v;
+}
+
+/**************************************************************************
+ * Guest State Bitmap
+ **************************************************************************/
+
+bool kvmppc_gsbm_test(struct kvmppc_gs_bitmap *gsbm, u16 iden);
+void kvmppc_gsbm_set(struct kvmppc_gs_bitmap *gsbm, u16 iden);
+void kvmppc_gsbm_clear(struct kvmppc_gs_bitmap *gsbm, u16 iden);
+u16 kvmppc_gsbm_next(struct kvmppc_gs_bitmap *gsbm, u16 prev);
+
+/**
+ * kvmppc_gsbm_zero - zero the entire bitmap
+ * @gsbm: guest state buffer bitmap
+ */
+static inline void kvmppc_gsbm_zero(struct kvmppc_gs_bitmap *gsbm)
+{
+ bitmap_zero(gsbm->bitmap, KVMPPC_GSE_IDEN_COUNT);
+}
+
+/**
+ * kvmppc_gsbm_fill - fill the entire bitmap
+ * @gsbm: guest state buffer bitmap
+ */
+static inline void kvmppc_gsbm_fill(struct kvmppc_gs_bitmap *gsbm)
+{
+ bitmap_fill(gsbm->bitmap, KVMPPC_GSE_IDEN_COUNT);
+ clear_bit(0, gsbm->bitmap);
+}
+
+/**
+ * kvmppc_gsbm_for_each - iterate the present guest state IDs
+ * @gsbm: guest state buffer bitmap
+ * @iden: current guest state ID
+ */
+#define kvmppc_gsbm_for_each(gsbm, iden) \
+ for (iden = kvmppc_gsbm_next(gsbm, 0); iden != 0; \
+ iden = kvmppc_gsbm_next(gsbm, iden))
+
+/**************************************************************************
+ * Guest State Parser
+ **************************************************************************/
+
+void kvmppc_gsp_insert(struct kvmppc_gs_parser *gsp, u16 iden,
+ struct kvmppc_gs_elem *gse);
+struct kvmppc_gs_elem *kvmppc_gsp_lookup(struct kvmppc_gs_parser *gsp,
+ u16 iden);
+
+/**
+ * kvmppc_gsp_for_each - iterate the <guest state IDs, guest state element>
+ * pairs
+ * @gsp: guest state buffer bitmap
+ * @iden: current guest state ID
+ * @gse: guest state element
+ */
+#define kvmppc_gsp_for_each(gsp, iden, gse) \
+ for (iden = kvmppc_gsbm_next(&(gsp)->iterator, 0), \
+ gse = kvmppc_gsp_lookup((gsp), iden); \
+ iden != 0; iden = kvmppc_gsbm_next(&(gsp)->iterator, iden), \
+ gse = kvmppc_gsp_lookup((gsp), iden))
+
+/**************************************************************************
+ * Guest State Message
+ **************************************************************************/
+
+/**
+ * kvmppc_gsm_for_each - iterate the guest state IDs included in a guest state
+ * message
+ * @gsp: guest state buffer bitmap
+ * @iden: current guest state ID
+ * @gse: guest state element
+ */
+#define kvmppc_gsm_for_each(gsm, iden) \
+ for (iden = kvmppc_gsbm_next(&gsm->bitmap, 0); iden != 0; \
+ iden = kvmppc_gsbm_next(&gsm->bitmap, iden))
+
+int kvmppc_gsm_init(struct kvmppc_gs_msg *mgs, struct kvmppc_gs_msg_ops *ops,
+ void *data, unsigned long flags);
+
+struct kvmppc_gs_msg *kvmppc_gsm_new(struct kvmppc_gs_msg_ops *ops, void *data,
+ unsigned long flags, gfp_t gfp_flags);
+void kvmppc_gsm_free(struct kvmppc_gs_msg *gsm);
+size_t kvmppc_gsm_size(struct kvmppc_gs_msg *gsm);
+int kvmppc_gsm_fill_info(struct kvmppc_gs_msg *gsm, struct kvmppc_gs_buff *gsb);
+int kvmppc_gsm_refresh_info(struct kvmppc_gs_msg *gsm,
+ struct kvmppc_gs_buff *gsb);
+
+/**
+ * kvmppc_gsm_include - indicate a guest state ID should be included when
+ * serializing
+ * @gsm: guest state message
+ * @iden: guest state ID
+ */
+static inline void kvmppc_gsm_include(struct kvmppc_gs_msg *gsm, u16 iden)
+{
+ kvmppc_gsbm_set(&gsm->bitmap, iden);
+}
+
+/**
+ * kvmppc_gsm_includes - check if a guest state ID will be included when
+ * serializing
+ * @gsm: guest state message
+ * @iden: guest state ID
+ */
+static inline bool kvmppc_gsm_includes(struct kvmppc_gs_msg *gsm, u16 iden)
+{
+ return kvmppc_gsbm_test(&gsm->bitmap, iden);
+}
+
+/**
+ * kvmppc_gsm_includes - indicate all guest state IDs should be included when
+ * serializing
+ * @gsm: guest state message
+ * @iden: guest state ID
+ */
+static inline void kvmppc_gsm_include_all(struct kvmppc_gs_msg *gsm)
+{
+ kvmppc_gsbm_fill(&gsm->bitmap);
+}
+
+/**
+ * kvmppc_gsm_include - clear the guest state IDs that should be included when
+ * serializing
+ * @gsm: guest state message
+ */
+static inline void kvmppc_gsm_reset(struct kvmppc_gs_msg *gsm)
+{
+ kvmppc_gsbm_zero(&gsm->bitmap);
+}
+
+/**
+ * kvmppc_gsb_receive_data - flexibly update values from a guest state buffer
+ * @gsb: guest state buffer
+ * @gsm: guest state message
+ *
+ * Requests updated values for the guest state values included in the guest
+ * state message. The guest state message will then deserialize the guest state
+ * buffer.
+ */
+static inline int kvmppc_gsb_receive_data(struct kvmppc_gs_buff *gsb,
+ struct kvmppc_gs_msg *gsm)
+{
+ int rc;
+
+ kvmppc_gsb_reset(gsb);
+ rc = kvmppc_gsm_fill_info(gsm, gsb);
+ if (rc < 0)
+ return rc;
+
+ rc = kvmppc_gsb_recv(gsb, gsm->flags);
+ if (rc < 0)
+ return rc;
+
+ rc = kvmppc_gsm_refresh_info(gsm, gsb);
+ if (rc < 0)
+ return rc;
+ return 0;
+}
+
+/**
+ * kvmppc_gsb_recv - receive a single guest state ID
+ * @gsb: guest state buffer
+ * @gsm: guest state message
+ * @iden: guest state identity
+ */
+static inline int kvmppc_gsb_receive_datum(struct kvmppc_gs_buff *gsb,
+ struct kvmppc_gs_msg *gsm, u16 iden)
+{
+ int rc;
+
+ kvmppc_gsm_include(gsm, iden);
+ rc = kvmppc_gsb_receive_data(gsb, gsm);
+ if (rc < 0)
+ return rc;
+ kvmppc_gsm_reset(gsm);
+ return 0;
+}
+
+/**
+ * kvmppc_gsb_send_data - flexibly send values from a guest state buffer
+ * @gsb: guest state buffer
+ * @gsm: guest state message
+ *
+ * Sends the guest state values included in the guest state message.
+ */
+static inline int kvmppc_gsb_send_data(struct kvmppc_gs_buff *gsb,
+ struct kvmppc_gs_msg *gsm)
+{
+ int rc;
+
+ kvmppc_gsb_reset(gsb);
+ rc = kvmppc_gsm_fill_info(gsm, gsb);
+ if (rc < 0)
+ return rc;
+ rc = kvmppc_gsb_send(gsb, gsm->flags);
+
+ return rc;
+}
+
+/**
+ * kvmppc_gsb_recv - send a single guest state ID
+ * @gsb: guest state buffer
+ * @gsm: guest state message
+ * @iden: guest state identity
+ */
+static inline int kvmppc_gsb_send_datum(struct kvmppc_gs_buff *gsb,
+ struct kvmppc_gs_msg *gsm, u16 iden)
+{
+ int rc;
+
+ kvmppc_gsm_include(gsm, iden);
+ rc = kvmppc_gsb_send_data(gsb, gsm);
+ if (rc < 0)
+ return rc;
+ kvmppc_gsm_reset(gsm);
+ return 0;
+}
+
+#endif /* _ASM_POWERPC_GUEST_STATE_BUFFER_H */
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index c099780385dd..ddb99e982917 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -100,6 +100,18 @@
#define H_COP_HW -74
#define H_STATE -75
#define H_IN_USE -77
+
+#define H_INVALID_ELEMENT_ID -79
+#define H_INVALID_ELEMENT_SIZE -80
+#define H_INVALID_ELEMENT_VALUE -81
+#define H_INPUT_BUFFER_NOT_DEFINED -82
+#define H_INPUT_BUFFER_TOO_SMALL -83
+#define H_OUTPUT_BUFFER_NOT_DEFINED -84
+#define H_OUTPUT_BUFFER_TOO_SMALL -85
+#define H_PARTITION_PAGE_TABLE_NOT_DEFINED -86
+#define H_GUEST_VCPU_STATE_NOT_HV_OWNED -87
+
+
#define H_UNSUPPORTED_FLAG_START -256
#define H_UNSUPPORTED_FLAG_END -511
#define H_MULTI_THREADS_ACTIVE -9005
@@ -381,6 +393,15 @@
#define H_ENTER_NESTED 0xF804
#define H_TLB_INVALIDATE 0xF808
#define H_COPY_TOFROM_GUEST 0xF80C
+#define H_GUEST_GET_CAPABILITIES 0x460
+#define H_GUEST_SET_CAPABILITIES 0x464
+#define H_GUEST_CREATE 0x470
+#define H_GUEST_CREATE_VCPU 0x474
+#define H_GUEST_GET_STATE 0x478
+#define H_GUEST_SET_STATE 0x47C
+#define H_GUEST_RUN_VCPU 0x480
+#define H_GUEST_COPY_MEMORY 0x484
+#define H_GUEST_DELETE 0x488
/* Flags for H_SVM_PAGE_IN */
#define H_PAGE_IN_SHARED 0x1
@@ -467,6 +488,15 @@
#define H_RPTI_PAGE_1G 0x08
#define H_RPTI_PAGE_ALL (-1UL)
+/* Flags for H_GUEST_{S,G}_STATE */
+#define H_GUEST_FLAGS_WIDE (1UL<<(63-0))
+
+/* Flag values used for H_{S,G}SET_GUEST_CAPABILITIES */
+#define H_GUEST_CAP_COPY_MEM (1UL<<(63-0))
+#define H_GUEST_CAP_POWER9 (1UL<<(63-1))
+#define H_GUEST_CAP_POWER10 (1UL<<(63-2))
+#define H_GUEST_CAP_BITMAP2 (1UL<<(63-63))
+
#ifndef __ASSEMBLY__
#include <linux/types.h>
diff --git a/arch/powerpc/include/asm/imc-pmu.h b/arch/powerpc/include/asm/imc-pmu.h
index 699a88584ae1..a656635df386 100644
--- a/arch/powerpc/include/asm/imc-pmu.h
+++ b/arch/powerpc/include/asm/imc-pmu.h
@@ -74,14 +74,14 @@ struct imc_events {
* The following is the data structure to hold trace imc data.
*/
struct trace_imc_data {
- u64 tb1;
- u64 ip;
- u64 val;
- u64 cpmc1;
- u64 cpmc2;
- u64 cpmc3;
- u64 cpmc4;
- u64 tb2;
+ __be64 tb1;
+ __be64 ip;
+ __be64 val;
+ __be64 cpmc1;
+ __be64 cpmc2;
+ __be64 cpmc3;
+ __be64 cpmc4;
+ __be64 tb2;
};
/* Event attribute array index */
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index 0732b743e099..5220274a6277 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -950,7 +950,7 @@ extern void __iomem *__ioremap_caller(phys_addr_t, unsigned long size,
* almost all conceivable cases a device driver should not be using
* this function
*/
-static inline unsigned long virt_to_phys(volatile void * address)
+static inline unsigned long virt_to_phys(const volatile void * address)
{
WARN_ON(IS_ENABLED(CONFIG_DEBUG_VIRTUAL) && !virt_addr_valid(address));
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index a1ddba01e7d1..e1b43aa12175 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -99,10 +99,14 @@ void relocate_new_kernel(unsigned long indirection_page, unsigned long reboot_co
void kexec_copy_flush(struct kimage *image);
-#if defined(CONFIG_CRASH_DUMP) && defined(CONFIG_PPC_RTAS)
+#if defined(CONFIG_CRASH_DUMP)
+bool is_kdump_kernel(void);
+#define is_kdump_kernel is_kdump_kernel
+#if defined(CONFIG_PPC_RTAS)
void crash_free_reserved_phys_range(unsigned long begin, unsigned long end);
#define crash_free_reserved_phys_range crash_free_reserved_phys_range
-#endif
+#endif /* CONFIG_PPC_RTAS */
+#endif /* CONFIG_CRASH_DUMP */
#ifdef CONFIG_KEXEC_FILE
extern const struct kexec_file_ops kexec_elf64_ops;
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index c8e4b4fd4e33..4525a9c68260 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -84,8 +84,6 @@ struct arch_optimized_insn {
kprobe_opcode_t *insn;
};
-extern int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
extern int kprobe_handler(struct pt_regs *regs);
extern int kprobe_post_handler(struct pt_regs *regs);
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index bbf5e2c5fe09..4f527d09c92b 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -12,6 +12,7 @@
#include <linux/types.h>
#include <linux/kvm_host.h>
#include <asm/kvm_book3s_asm.h>
+#include <asm/guest-state-buffer.h>
struct kvmppc_bat {
u64 raw;
@@ -191,14 +192,14 @@ extern int kvmppc_mmu_radix_translate_table(struct kvm_vcpu *vcpu, gva_t eaddr,
extern int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
struct kvmppc_pte *gpte, bool data, bool iswrite);
extern void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr,
- unsigned int pshift, unsigned int lpid);
+ unsigned int pshift, u64 lpid);
extern void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, unsigned long gpa,
unsigned int shift,
const struct kvm_memory_slot *memslot,
- unsigned int lpid);
+ u64 lpid);
extern bool kvmppc_hv_handle_set_rc(struct kvm *kvm, bool nested,
bool writing, unsigned long gpa,
- unsigned int lpid);
+ u64 lpid);
extern int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
unsigned long gpa,
struct kvm_memory_slot *memslot,
@@ -207,7 +208,7 @@ extern int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
extern int kvmppc_init_vm_radix(struct kvm *kvm);
extern void kvmppc_free_radix(struct kvm *kvm);
extern void kvmppc_free_pgtable_radix(struct kvm *kvm, pgd_t *pgd,
- unsigned int lpid);
+ u64 lpid);
extern int kvmppc_radix_init(void);
extern void kvmppc_radix_exit(void);
extern void kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
@@ -295,12 +296,13 @@ static inline void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu) {}
static inline void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu) {}
#endif
+extern unsigned long nested_capabilities;
long kvmhv_nested_init(void);
void kvmhv_nested_exit(void);
void kvmhv_vm_nested_init(struct kvm *kvm);
long kvmhv_set_partition_table(struct kvm_vcpu *vcpu);
long kvmhv_copy_tofrom_guest_nested(struct kvm_vcpu *vcpu);
-void kvmhv_set_ptbl_entry(unsigned int lpid, u64 dw0, u64 dw1);
+void kvmhv_set_ptbl_entry(u64 lpid, u64 dw0, u64 dw1);
void kvmhv_release_all_nested(struct kvm *kvm);
long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu);
long kvmhv_do_nested_tlbie(struct kvm_vcpu *vcpu);
@@ -316,6 +318,69 @@ long int kvmhv_nested_page_fault(struct kvm_vcpu *vcpu);
void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac);
+
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+
+extern struct static_key_false __kvmhv_is_nestedv2;
+
+static inline bool kvmhv_is_nestedv2(void)
+{
+ return static_branch_unlikely(&__kvmhv_is_nestedv2);
+}
+
+static inline bool kvmhv_is_nestedv1(void)
+{
+ return !static_branch_likely(&__kvmhv_is_nestedv2);
+}
+
+#else
+
+static inline bool kvmhv_is_nestedv2(void)
+{
+ return false;
+}
+
+static inline bool kvmhv_is_nestedv1(void)
+{
+ return false;
+}
+
+#endif
+
+int __kvmhv_nestedv2_reload_ptregs(struct kvm_vcpu *vcpu, struct pt_regs *regs);
+int __kvmhv_nestedv2_mark_dirty_ptregs(struct kvm_vcpu *vcpu, struct pt_regs *regs);
+int __kvmhv_nestedv2_mark_dirty(struct kvm_vcpu *vcpu, u16 iden);
+int __kvmhv_nestedv2_cached_reload(struct kvm_vcpu *vcpu, u16 iden);
+
+static inline int kvmhv_nestedv2_reload_ptregs(struct kvm_vcpu *vcpu,
+ struct pt_regs *regs)
+{
+ if (kvmhv_is_nestedv2())
+ return __kvmhv_nestedv2_reload_ptregs(vcpu, regs);
+ return 0;
+}
+static inline int kvmhv_nestedv2_mark_dirty_ptregs(struct kvm_vcpu *vcpu,
+ struct pt_regs *regs)
+{
+ if (kvmhv_is_nestedv2())
+ return __kvmhv_nestedv2_mark_dirty_ptregs(vcpu, regs);
+ return 0;
+}
+
+static inline int kvmhv_nestedv2_mark_dirty(struct kvm_vcpu *vcpu, u16 iden)
+{
+ if (kvmhv_is_nestedv2())
+ return __kvmhv_nestedv2_mark_dirty(vcpu, iden);
+ return 0;
+}
+
+static inline int kvmhv_nestedv2_cached_reload(struct kvm_vcpu *vcpu, u16 iden)
+{
+ if (kvmhv_is_nestedv2())
+ return __kvmhv_nestedv2_cached_reload(vcpu, iden);
+ return 0;
+}
+
extern int kvm_irq_bypass;
static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
@@ -335,60 +400,72 @@ static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
{
vcpu->arch.regs.gpr[num] = val;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_GPR(num));
}
static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num)
{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_GPR(num)) < 0);
return vcpu->arch.regs.gpr[num];
}
static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val)
{
vcpu->arch.regs.ccr = val;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_CR);
}
static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu)
{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_CR) < 0);
return vcpu->arch.regs.ccr;
}
static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, ulong val)
{
vcpu->arch.regs.xer = val;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_XER);
}
static inline ulong kvmppc_get_xer(struct kvm_vcpu *vcpu)
{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_XER) < 0);
return vcpu->arch.regs.xer;
}
static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val)
{
vcpu->arch.regs.ctr = val;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_CTR);
}
static inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu)
{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_CTR) < 0);
return vcpu->arch.regs.ctr;
}
static inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val)
{
vcpu->arch.regs.link = val;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LR);
}
static inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu)
{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_LR) < 0);
return vcpu->arch.regs.link;
}
static inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val)
{
vcpu->arch.regs.nip = val;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_NIA);
}
static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu)
{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_NIA) < 0);
return vcpu->arch.regs.nip;
}
@@ -403,10 +480,141 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
return vcpu->arch.fault_dar;
}
+static inline u64 kvmppc_get_fpr(struct kvm_vcpu *vcpu, int i)
+{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_VSRS(i)) < 0);
+ return vcpu->arch.fp.fpr[i][TS_FPROFFSET];
+}
+
+static inline void kvmppc_set_fpr(struct kvm_vcpu *vcpu, int i, u64 val)
+{
+ vcpu->arch.fp.fpr[i][TS_FPROFFSET] = val;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_VSRS(i));
+}
+
+static inline u64 kvmppc_get_fpscr(struct kvm_vcpu *vcpu)
+{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_FPSCR) < 0);
+ return vcpu->arch.fp.fpscr;
+}
+
+static inline void kvmppc_set_fpscr(struct kvm_vcpu *vcpu, u64 val)
+{
+ vcpu->arch.fp.fpscr = val;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_FPSCR);
+}
+
+
+static inline u64 kvmppc_get_vsx_fpr(struct kvm_vcpu *vcpu, int i, int j)
+{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_VSRS(i)) < 0);
+ return vcpu->arch.fp.fpr[i][j];
+}
+
+static inline void kvmppc_set_vsx_fpr(struct kvm_vcpu *vcpu, int i, int j,
+ u64 val)
+{
+ vcpu->arch.fp.fpr[i][j] = val;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_VSRS(i));
+}
+
+#ifdef CONFIG_ALTIVEC
+static inline void kvmppc_get_vsx_vr(struct kvm_vcpu *vcpu, int i, vector128 *v)
+{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_VSRS(32 + i)) < 0);
+ *v = vcpu->arch.vr.vr[i];
+}
+
+static inline void kvmppc_set_vsx_vr(struct kvm_vcpu *vcpu, int i,
+ vector128 *val)
+{
+ vcpu->arch.vr.vr[i] = *val;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_VSRS(32 + i));
+}
+
+static inline u32 kvmppc_get_vscr(struct kvm_vcpu *vcpu)
+{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_VSCR) < 0);
+ return vcpu->arch.vr.vscr.u[3];
+}
+
+static inline void kvmppc_set_vscr(struct kvm_vcpu *vcpu, u32 val)
+{
+ vcpu->arch.vr.vscr.u[3] = val;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_VSCR);
+}
+#endif
+
+#define KVMPPC_BOOK3S_VCPU_ACCESSOR_SET(reg, size, iden) \
+static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val) \
+{ \
+ \
+ vcpu->arch.reg = val; \
+ kvmhv_nestedv2_mark_dirty(vcpu, iden); \
+}
+
+#define KVMPPC_BOOK3S_VCPU_ACCESSOR_GET(reg, size, iden) \
+static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu) \
+{ \
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, iden) < 0); \
+ return vcpu->arch.reg; \
+}
+
+#define KVMPPC_BOOK3S_VCPU_ACCESSOR(reg, size, iden) \
+ KVMPPC_BOOK3S_VCPU_ACCESSOR_SET(reg, size, iden) \
+ KVMPPC_BOOK3S_VCPU_ACCESSOR_GET(reg, size, iden) \
+
+KVMPPC_BOOK3S_VCPU_ACCESSOR(pid, 32, KVMPPC_GSID_PIDR)
+KVMPPC_BOOK3S_VCPU_ACCESSOR(tar, 64, KVMPPC_GSID_TAR)
+KVMPPC_BOOK3S_VCPU_ACCESSOR(ebbhr, 64, KVMPPC_GSID_EBBHR)
+KVMPPC_BOOK3S_VCPU_ACCESSOR(ebbrr, 64, KVMPPC_GSID_EBBRR)
+KVMPPC_BOOK3S_VCPU_ACCESSOR(bescr, 64, KVMPPC_GSID_BESCR)
+KVMPPC_BOOK3S_VCPU_ACCESSOR(ic, 64, KVMPPC_GSID_IC)
+KVMPPC_BOOK3S_VCPU_ACCESSOR(vrsave, 64, KVMPPC_GSID_VRSAVE)
+
+
+#define KVMPPC_BOOK3S_VCORE_ACCESSOR_SET(reg, size, iden) \
+static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val) \
+{ \
+ vcpu->arch.vcore->reg = val; \
+ kvmhv_nestedv2_mark_dirty(vcpu, iden); \
+}
+
+#define KVMPPC_BOOK3S_VCORE_ACCESSOR_GET(reg, size, iden) \
+static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu) \
+{ \
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, iden) < 0); \
+ return vcpu->arch.vcore->reg; \
+}
+
+#define KVMPPC_BOOK3S_VCORE_ACCESSOR(reg, size, iden) \
+ KVMPPC_BOOK3S_VCORE_ACCESSOR_SET(reg, size, iden) \
+ KVMPPC_BOOK3S_VCORE_ACCESSOR_GET(reg, size, iden) \
+
+
+KVMPPC_BOOK3S_VCORE_ACCESSOR(vtb, 64, KVMPPC_GSID_VTB)
+KVMPPC_BOOK3S_VCORE_ACCESSOR(tb_offset, 64, KVMPPC_GSID_TB_OFFSET)
+KVMPPC_BOOK3S_VCORE_ACCESSOR_GET(arch_compat, 32, KVMPPC_GSID_LOGICAL_PVR)
+KVMPPC_BOOK3S_VCORE_ACCESSOR_GET(lpcr, 64, KVMPPC_GSID_LPCR)
+
+static inline u64 kvmppc_get_dec_expires(struct kvm_vcpu *vcpu)
+{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_TB_OFFSET) < 0);
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_DEC_EXPIRY_TB) < 0);
+ return vcpu->arch.dec_expires;
+}
+
+static inline void kvmppc_set_dec_expires(struct kvm_vcpu *vcpu, u64 val)
+{
+ vcpu->arch.dec_expires = val;
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_TB_OFFSET) < 0);
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_DEC_EXPIRY_TB);
+}
+
/* Expiry time of vcpu DEC relative to host TB */
static inline u64 kvmppc_dec_expires_host_tb(struct kvm_vcpu *vcpu)
{
- return vcpu->arch.dec_expires - vcpu->arch.vcore->tb_offset;
+ return kvmppc_get_dec_expires(vcpu) - kvmppc_get_tb_offset(vcpu);
}
static inline bool is_kvmppc_resume_guest(int r)
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index d49065af08e9..2477021bff54 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -624,7 +624,7 @@ static inline void copy_to_checkpoint(struct kvm_vcpu *vcpu)
extern int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte,
unsigned long gpa, unsigned int level,
- unsigned long mmu_seq, unsigned int lpid,
+ unsigned long mmu_seq, u64 lpid,
unsigned long *rmapp, struct rmap_nested **n_rmap);
extern void kvmhv_insert_nest_rmap(struct kvm *kvm, unsigned long *rmapp,
struct rmap_nested **n_rmap);
@@ -677,6 +677,12 @@ static inline pte_t *find_kvm_host_pte(struct kvm *kvm, unsigned long mmu_seq,
extern pte_t *find_kvm_nested_guest_pte(struct kvm *kvm, unsigned long lpid,
unsigned long ea, unsigned *hshift);
+int kvmhv_nestedv2_vcpu_create(struct kvm_vcpu *vcpu, struct kvmhv_nestedv2_io *io);
+void kvmhv_nestedv2_vcpu_free(struct kvm_vcpu *vcpu, struct kvmhv_nestedv2_io *io);
+int kvmhv_nestedv2_flush_vcpu(struct kvm_vcpu *vcpu, u64 time_limit);
+int kvmhv_nestedv2_set_ptbl_entry(unsigned long lpid, u64 dw0, u64 dw1);
+int kvmhv_nestedv2_parse_output(struct kvm_vcpu *vcpu);
+
#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
#endif /* __ASM_KVM_BOOK3S_64_H__ */
diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h
index 0c3401b2e19e..7c3291aa8922 100644
--- a/arch/powerpc/include/asm/kvm_booke.h
+++ b/arch/powerpc/include/asm/kvm_booke.h
@@ -89,6 +89,16 @@ static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu)
return vcpu->arch.regs.nip;
}
+static inline void kvmppc_set_fpr(struct kvm_vcpu *vcpu, int i, u64 val)
+{
+ vcpu->arch.fp.fpr[i][TS_FPROFFSET] = val;
+}
+
+static inline u64 kvmppc_get_fpr(struct kvm_vcpu *vcpu, int i)
+{
+ return vcpu->arch.fp.fpr[i][TS_FPROFFSET];
+}
+
#ifdef CONFIG_BOOKE
static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
{
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 14ee0dece853..8799b37be295 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -25,6 +25,7 @@
#include <asm/cacheflush.h>
#include <asm/hvcall.h>
#include <asm/mce.h>
+#include <asm/guest-state-buffer.h>
#define __KVM_HAVE_ARCH_VCPU_DEBUGFS
@@ -276,7 +277,7 @@ struct kvm_resize_hpt;
#define KVMPPC_SECURE_INIT_ABORT 0x4 /* H_SVM_INIT_ABORT issued */
struct kvm_arch {
- unsigned int lpid;
+ u64 lpid;
unsigned int smt_mode; /* # vcpus per virtual core */
unsigned int emul_smt_mode; /* emualted SMT mode, on P9 */
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
@@ -509,6 +510,23 @@ union xive_tma_w01 {
__be64 w01;
};
+ /* Nestedv2 H_GUEST_RUN_VCPU configuration */
+struct kvmhv_nestedv2_config {
+ struct kvmppc_gs_buff_info vcpu_run_output_cfg;
+ struct kvmppc_gs_buff_info vcpu_run_input_cfg;
+ u64 vcpu_run_output_size;
+};
+
+ /* Nestedv2 L1<->L0 communication state */
+struct kvmhv_nestedv2_io {
+ struct kvmhv_nestedv2_config cfg;
+ struct kvmppc_gs_buff *vcpu_run_output;
+ struct kvmppc_gs_buff *vcpu_run_input;
+ struct kvmppc_gs_msg *vcpu_message;
+ struct kvmppc_gs_msg *vcore_message;
+ struct kvmppc_gs_bitmap valids;
+};
+
struct kvm_vcpu_arch {
ulong host_stack;
u32 host_pid;
@@ -829,6 +847,8 @@ struct kvm_vcpu_arch {
u64 nested_hfscr; /* HFSCR that the L1 requested for the nested guest */
u32 nested_vcpu_id;
gpa_t nested_io_gpr;
+ /* For nested APIv2 guests*/
+ struct kvmhv_nestedv2_io nestedv2_io;
#endif
#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index b4da8514af43..3281215097cc 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -615,6 +615,42 @@ static inline bool kvmhv_on_pseries(void)
{
return false;
}
+
+#endif
+
+#ifndef CONFIG_PPC_BOOK3S
+
+static inline bool kvmhv_is_nestedv2(void)
+{
+ return false;
+}
+
+static inline bool kvmhv_is_nestedv1(void)
+{
+ return false;
+}
+
+static inline int kvmhv_nestedv2_reload_ptregs(struct kvm_vcpu *vcpu,
+ struct pt_regs *regs)
+{
+ return 0;
+}
+static inline int kvmhv_nestedv2_mark_dirty_ptregs(struct kvm_vcpu *vcpu,
+ struct pt_regs *regs)
+{
+ return 0;
+}
+
+static inline int kvmhv_nestedv2_mark_dirty(struct kvm_vcpu *vcpu, u16 iden)
+{
+ return 0;
+}
+
+static inline int kvmhv_nestedv2_cached_reload(struct kvm_vcpu *vcpu, u16 iden)
+{
+ return 0;
+}
+
#endif
#ifdef CONFIG_KVM_XICS
@@ -927,79 +963,85 @@ static inline bool kvmppc_shared_big_endian(struct kvm_vcpu *vcpu)
#endif
}
-#define SPRNG_WRAPPER_GET(reg, bookehv_spr) \
+#define KVMPPC_BOOKE_HV_SPRNG_ACCESSOR_GET(reg, bookehv_spr) \
static inline ulong kvmppc_get_##reg(struct kvm_vcpu *vcpu) \
{ \
return mfspr(bookehv_spr); \
} \
-#define SPRNG_WRAPPER_SET(reg, bookehv_spr) \
+#define KVMPPC_BOOKE_HV_SPRNG_ACCESSOR_SET(reg, bookehv_spr) \
static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, ulong val) \
{ \
mtspr(bookehv_spr, val); \
} \
-#define SHARED_WRAPPER_GET(reg, size) \
+#define KVMPPC_VCPU_SHARED_REGS_ACCESSOR_GET(reg, size, iden) \
static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu) \
{ \
+ if (iden) \
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, iden) < 0); \
if (kvmppc_shared_big_endian(vcpu)) \
- return be##size##_to_cpu(vcpu->arch.shared->reg); \
+ return be##size##_to_cpu((__be##size __force)vcpu->arch.shared->reg); \
else \
- return le##size##_to_cpu(vcpu->arch.shared->reg); \
+ return le##size##_to_cpu((__le##size __force)vcpu->arch.shared->reg); \
} \
-#define SHARED_WRAPPER_SET(reg, size) \
+#define KVMPPC_VCPU_SHARED_REGS_ACCESSOR_SET(reg, size, iden) \
static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val) \
{ \
if (kvmppc_shared_big_endian(vcpu)) \
- vcpu->arch.shared->reg = cpu_to_be##size(val); \
+ vcpu->arch.shared->reg = (u##size __force)cpu_to_be##size(val); \
else \
- vcpu->arch.shared->reg = cpu_to_le##size(val); \
+ vcpu->arch.shared->reg = (u##size __force)cpu_to_le##size(val); \
+ \
+ if (iden) \
+ kvmhv_nestedv2_mark_dirty(vcpu, iden); \
} \
-#define SHARED_WRAPPER(reg, size) \
- SHARED_WRAPPER_GET(reg, size) \
- SHARED_WRAPPER_SET(reg, size) \
+#define KVMPPC_VCPU_SHARED_REGS_ACCESSOR(reg, size, iden) \
+ KVMPPC_VCPU_SHARED_REGS_ACCESSOR_GET(reg, size, iden) \
+ KVMPPC_VCPU_SHARED_REGS_ACCESSOR_SET(reg, size, iden) \
-#define SPRNG_WRAPPER(reg, bookehv_spr) \
- SPRNG_WRAPPER_GET(reg, bookehv_spr) \
- SPRNG_WRAPPER_SET(reg, bookehv_spr) \
+#define KVMPPC_BOOKE_HV_SPRNG_ACCESSOR(reg, bookehv_spr) \
+ KVMPPC_BOOKE_HV_SPRNG_ACCESSOR_GET(reg, bookehv_spr) \
+ KVMPPC_BOOKE_HV_SPRNG_ACCESSOR_SET(reg, bookehv_spr) \
#ifdef CONFIG_KVM_BOOKE_HV
-#define SHARED_SPRNG_WRAPPER(reg, size, bookehv_spr) \
- SPRNG_WRAPPER(reg, bookehv_spr) \
+#define KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(reg, size, bookehv_spr, iden) \
+ KVMPPC_BOOKE_HV_SPRNG_ACCESSOR(reg, bookehv_spr) \
#else
-#define SHARED_SPRNG_WRAPPER(reg, size, bookehv_spr) \
- SHARED_WRAPPER(reg, size) \
+#define KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(reg, size, bookehv_spr, iden) \
+ KVMPPC_VCPU_SHARED_REGS_ACCESSOR(reg, size, iden) \
#endif
-SHARED_WRAPPER(critical, 64)
-SHARED_SPRNG_WRAPPER(sprg0, 64, SPRN_GSPRG0)
-SHARED_SPRNG_WRAPPER(sprg1, 64, SPRN_GSPRG1)
-SHARED_SPRNG_WRAPPER(sprg2, 64, SPRN_GSPRG2)
-SHARED_SPRNG_WRAPPER(sprg3, 64, SPRN_GSPRG3)
-SHARED_SPRNG_WRAPPER(srr0, 64, SPRN_GSRR0)
-SHARED_SPRNG_WRAPPER(srr1, 64, SPRN_GSRR1)
-SHARED_SPRNG_WRAPPER(dar, 64, SPRN_GDEAR)
-SHARED_SPRNG_WRAPPER(esr, 64, SPRN_GESR)
-SHARED_WRAPPER_GET(msr, 64)
+KVMPPC_VCPU_SHARED_REGS_ACCESSOR(critical, 64, 0)
+KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(sprg0, 64, SPRN_GSPRG0, KVMPPC_GSID_SPRG0)
+KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(sprg1, 64, SPRN_GSPRG1, KVMPPC_GSID_SPRG1)
+KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(sprg2, 64, SPRN_GSPRG2, KVMPPC_GSID_SPRG2)
+KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(sprg3, 64, SPRN_GSPRG3, KVMPPC_GSID_SPRG3)
+KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(srr0, 64, SPRN_GSRR0, KVMPPC_GSID_SRR0)
+KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(srr1, 64, SPRN_GSRR1, KVMPPC_GSID_SRR1)
+KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(dar, 64, SPRN_GDEAR, KVMPPC_GSID_DAR)
+KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(esr, 64, SPRN_GESR, 0)
+KVMPPC_VCPU_SHARED_REGS_ACCESSOR_GET(msr, 64, KVMPPC_GSID_MSR)
static inline void kvmppc_set_msr_fast(struct kvm_vcpu *vcpu, u64 val)
{
if (kvmppc_shared_big_endian(vcpu))
vcpu->arch.shared->msr = cpu_to_be64(val);
else
vcpu->arch.shared->msr = cpu_to_le64(val);
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_MSR);
}
-SHARED_WRAPPER(dsisr, 32)
-SHARED_WRAPPER(int_pending, 32)
-SHARED_WRAPPER(sprg4, 64)
-SHARED_WRAPPER(sprg5, 64)
-SHARED_WRAPPER(sprg6, 64)
-SHARED_WRAPPER(sprg7, 64)
+KVMPPC_VCPU_SHARED_REGS_ACCESSOR(dsisr, 32, KVMPPC_GSID_DSISR)
+KVMPPC_VCPU_SHARED_REGS_ACCESSOR(int_pending, 32, 0)
+KVMPPC_VCPU_SHARED_REGS_ACCESSOR(sprg4, 64, 0)
+KVMPPC_VCPU_SHARED_REGS_ACCESSOR(sprg5, 64, 0)
+KVMPPC_VCPU_SHARED_REGS_ACCESSOR(sprg6, 64, 0)
+KVMPPC_VCPU_SHARED_REGS_ACCESSOR(sprg7, 64, 0)
static inline u32 kvmppc_get_sr(struct kvm_vcpu *vcpu, int nr)
{
diff --git a/arch/powerpc/include/asm/local.h b/arch/powerpc/include/asm/local.h
index 45492fb5bf22..ec6ced6d7ced 100644
--- a/arch/powerpc/include/asm/local.h
+++ b/arch/powerpc/include/asm/local.h
@@ -115,23 +115,23 @@ static __inline__ long local_xchg(local_t *l, long n)
}
/**
- * local_add_unless - add unless the number is a given value
+ * local_add_unless - add unless the number is already a given value
* @l: pointer of type local_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
- * Atomically adds @a to @l, so long as it was not @u.
- * Returns non-zero if @l was not @u, and zero otherwise.
+ * Atomically adds @a to @l, if @v was not already @u.
+ * Returns true if the addition was done.
*/
-static __inline__ int local_add_unless(local_t *l, long a, long u)
+static __inline__ bool local_add_unless(local_t *l, long a, long u)
{
unsigned long flags;
- int ret = 0;
+ bool ret = false;
powerpc_local_irq_pmu_save(flags);
if (l->v != u) {
l->v += a;
- ret = 1;
+ ret = true;
}
powerpc_local_irq_pmu_restore(flags);
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 4f6e7d7ee388..d31a5ec1550d 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -10,7 +10,7 @@
#include <linux/export.h>
struct pt_regs;
-struct pci_bus;
+struct pci_bus;
struct device_node;
struct iommu_table;
struct rtc_time;
@@ -78,8 +78,8 @@ struct machdep_calls {
unsigned char (*nvram_read_val)(int addr);
void (*nvram_write_val)(int addr, unsigned char val);
ssize_t (*nvram_write)(char *buf, size_t count, loff_t *index);
- ssize_t (*nvram_read)(char *buf, size_t count, loff_t *index);
- ssize_t (*nvram_size)(void);
+ ssize_t (*nvram_read)(char *buf, size_t count, loff_t *index);
+ ssize_t (*nvram_size)(void);
void (*nvram_sync)(void);
/* Exception handlers */
@@ -102,12 +102,11 @@ struct machdep_calls {
*/
long (*feature_call)(unsigned int feature, ...);
- /* Get legacy PCI/IDE interrupt mapping */
+ /* Get legacy PCI/IDE interrupt mapping */
int (*pci_get_legacy_ide_irq)(struct pci_dev *dev, int channel);
-
+
/* Get access protection for /dev/mem */
- pgprot_t (*phys_mem_access_prot)(struct file *file,
- unsigned long pfn,
+ pgprot_t (*phys_mem_access_prot)(unsigned long pfn,
unsigned long size,
pgprot_t vma_prot);
diff --git a/arch/powerpc/include/asm/nohash/32/mmu-8xx.h b/arch/powerpc/include/asm/nohash/32/mmu-8xx.h
index 0e93a4728c9e..141d82e249a8 100644
--- a/arch/powerpc/include/asm/nohash/32/mmu-8xx.h
+++ b/arch/powerpc/include/asm/nohash/32/mmu-8xx.h
@@ -188,7 +188,6 @@ typedef struct {
} mm_context_t;
#define PHYS_IMMR_BASE (mfspr(SPRN_IMMR) & 0xfff80000)
-#define VIRT_IMMR_BASE (__fix_to_virt(FIX_IMMR_BASE))
/* Page size definitions, common between 32 and 64-bit
*
diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h
index f99c53a5f184..9164a9e41b02 100644
--- a/arch/powerpc/include/asm/nohash/32/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/32/pgtable.h
@@ -9,10 +9,6 @@
#include <linux/threads.h>
#include <asm/mmu.h> /* For sub-arch specific PPC_PIN_SIZE */
-#ifdef CONFIG_44x
-extern int icache_44x_need_flush;
-#endif
-
#endif /* __ASSEMBLY__ */
#define PTE_INDEX_SIZE PTE_SHIFT
@@ -55,26 +51,22 @@ extern int icache_44x_need_flush;
#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
-#define pte_ERROR(e) \
- pr_err("%s:%d: bad pte %llx.\n", __FILE__, __LINE__, \
- (unsigned long long)pte_val(e))
#define pgd_ERROR(e) \
pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
-#ifndef __ASSEMBLY__
-
-int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot);
-void unmap_kernel_page(unsigned long va);
-
-#endif /* !__ASSEMBLY__ */
-
-
/*
* This is the bottom of the PKMAP area with HIGHMEM or an arbitrary
* value (for now) on others, from where we can start layout kernel
* virtual space that goes below PKMAP and FIXMAP
*/
-#include <asm/fixmap.h>
+
+#define FIXADDR_SIZE 0
+#ifdef CONFIG_KASAN
+#include <asm/kasan.h>
+#define FIXADDR_TOP (KASAN_SHADOW_START - PAGE_SIZE)
+#else
+#define FIXADDR_TOP ((unsigned long)(-PAGE_SIZE))
+#endif
/*
* ioremap_bot starts at that address. Early ioremaps move down from there,
@@ -151,7 +143,7 @@ void unmap_kernel_page(unsigned long va);
* The mask covered by the RPN must be a ULL on 32-bit platforms with
* 64-bit PTEs.
*/
-#if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT)
+#ifdef CONFIG_PTE_64BIT
#define PTE_RPN_MASK (~((1ULL << PTE_RPN_SHIFT) - 1))
#define MAX_POSSIBLE_PHYSMEM_BITS 36
#else
@@ -159,48 +151,8 @@ void unmap_kernel_page(unsigned long va);
#define MAX_POSSIBLE_PHYSMEM_BITS 32
#endif
-/*
- * _PAGE_CHG_MASK masks of bits that are to be preserved across
- * pgprot changes.
- */
-#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPECIAL)
-
#ifndef __ASSEMBLY__
-#define pte_clear(mm, addr, ptep) \
- do { pte_update(mm, addr, ptep, ~0, 0, 0); } while (0)
-
-#ifndef pte_mkwrite_novma
-static inline pte_t pte_mkwrite_novma(pte_t pte)
-{
- return __pte(pte_val(pte) | _PAGE_RW);
-}
-#endif
-
-static inline pte_t pte_mkdirty(pte_t pte)
-{
- return __pte(pte_val(pte) | _PAGE_DIRTY);
-}
-
-static inline pte_t pte_mkyoung(pte_t pte)
-{
- return __pte(pte_val(pte) | _PAGE_ACCESSED);
-}
-
-#ifndef pte_wrprotect
-static inline pte_t pte_wrprotect(pte_t pte)
-{
- return __pte(pte_val(pte) & ~_PAGE_RW);
-}
-#endif
-
-#ifndef pte_mkexec
-static inline pte_t pte_mkexec(pte_t pte)
-{
- return __pte(pte_val(pte) | _PAGE_EXEC);
-}
-#endif
-
#define pmd_none(pmd) (!pmd_val(pmd))
#define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD)
#define pmd_present(pmd) (pmd_val(pmd) & _PMD_PRESENT_MASK)
@@ -210,141 +162,6 @@ static inline void pmd_clear(pmd_t *pmdp)
}
/*
- * PTE updates. This function is called whenever an existing
- * valid PTE is updated. This does -not- include set_pte_at()
- * which nowadays only sets a new PTE.
- *
- * Depending on the type of MMU, we may need to use atomic updates
- * and the PTE may be either 32 or 64 bit wide. In the later case,
- * when using atomic updates, only the low part of the PTE is
- * accessed atomically.
- *
- * In addition, on 44x, we also maintain a global flag indicating
- * that an executable user mapping was modified, which is needed
- * to properly flush the virtually tagged instruction cache of
- * those implementations.
- *
- * On the 8xx, the page tables are a bit special. For 16k pages, we have
- * 4 identical entries. For 512k pages, we have 128 entries as if it was
- * 4k pages, but they are flagged as 512k pages for the hardware.
- * For other page sizes, we have a single entry in the table.
- */
-#ifdef CONFIG_PPC_8xx
-static pmd_t *pmd_off(struct mm_struct *mm, unsigned long addr);
-static int hugepd_ok(hugepd_t hpd);
-
-static int number_of_cells_per_pte(pmd_t *pmd, pte_basic_t val, int huge)
-{
- if (!huge)
- return PAGE_SIZE / SZ_4K;
- else if (hugepd_ok(*((hugepd_t *)pmd)))
- return 1;
- else if (IS_ENABLED(CONFIG_PPC_4K_PAGES) && !(val & _PAGE_HUGE))
- return SZ_16K / SZ_4K;
- else
- return SZ_512K / SZ_4K;
-}
-
-static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p,
- unsigned long clr, unsigned long set, int huge)
-{
- pte_basic_t *entry = (pte_basic_t *)p;
- pte_basic_t old = pte_val(*p);
- pte_basic_t new = (old & ~(pte_basic_t)clr) | set;
- int num, i;
- pmd_t *pmd = pmd_off(mm, addr);
-
- num = number_of_cells_per_pte(pmd, new, huge);
-
- for (i = 0; i < num; i += PAGE_SIZE / SZ_4K, new += PAGE_SIZE) {
- *entry++ = new;
- if (IS_ENABLED(CONFIG_PPC_16K_PAGES) && num != 1) {
- *entry++ = new;
- *entry++ = new;
- *entry++ = new;
- }
- }
-
- return old;
-}
-
-#ifdef CONFIG_PPC_16K_PAGES
-#define ptep_get ptep_get
-static inline pte_t ptep_get(pte_t *ptep)
-{
- pte_basic_t val = READ_ONCE(ptep->pte);
- pte_t pte = {val, val, val, val};
-
- return pte;
-}
-#endif /* CONFIG_PPC_16K_PAGES */
-
-#else
-static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p,
- unsigned long clr, unsigned long set, int huge)
-{
- pte_basic_t old = pte_val(*p);
- pte_basic_t new = (old & ~(pte_basic_t)clr) | set;
-
- *p = __pte(new);
-
-#ifdef CONFIG_44x
- if ((old & _PAGE_USER) && (old & _PAGE_EXEC))
- icache_44x_need_flush = 1;
-#endif
- return old;
-}
-#endif
-
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
- unsigned long addr, pte_t *ptep)
-{
- unsigned long old;
- old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
- return (old & _PAGE_ACCESSED) != 0;
-}
-#define ptep_test_and_clear_young(__vma, __addr, __ptep) \
- __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep)
-
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep)
-{
- return __pte(pte_update(mm, addr, ptep, ~0, 0, 0));
-}
-
-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#ifndef ptep_set_wrprotect
-static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep)
-{
- pte_update(mm, addr, ptep, _PAGE_RW, 0, 0);
-}
-#endif
-
-#ifndef __ptep_set_access_flags
-static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
- pte_t *ptep, pte_t entry,
- unsigned long address,
- int psize)
-{
- unsigned long set = pte_val(entry) &
- (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
- int huge = psize > mmu_virtual_psize ? 1 : 0;
-
- pte_update(vma->vm_mm, address, ptep, 0, set, huge);
-
- flush_tlb_page(vma, address);
-}
-#endif
-
-static inline int pte_young(pte_t pte)
-{
- return pte_val(pte) & _PAGE_ACCESSED;
-}
-
-/*
* Note that on Book E processors, the pmd contains the kernel virtual
* (lowmem) address of the pte page. The physical address is less useful
* because everything runs with translation enabled (even the TLB miss
diff --git a/arch/powerpc/include/asm/nohash/32/pte-40x.h b/arch/powerpc/include/asm/nohash/32/pte-40x.h
index 6fe46e754556..d759cfd74754 100644
--- a/arch/powerpc/include/asm/nohash/32/pte-40x.h
+++ b/arch/powerpc/include/asm/nohash/32/pte-40x.h
@@ -42,10 +42,10 @@
#define _PAGE_PRESENT 0x002 /* software: PTE contains a translation */
#define _PAGE_NO_CACHE 0x004 /* I: caching is inhibited */
#define _PAGE_WRITETHRU 0x008 /* W: caching is write-through */
-#define _PAGE_USER 0x010 /* matches one of the zone permission bits */
+#define _PAGE_READ 0x010 /* software: read permission */
#define _PAGE_SPECIAL 0x020 /* software: Special page */
#define _PAGE_DIRTY 0x080 /* software: dirty page */
-#define _PAGE_RW 0x100 /* hardware: WR, anded with dirty in exception */
+#define _PAGE_WRITE 0x100 /* hardware: WR, anded with dirty in exception */
#define _PAGE_EXEC 0x200 /* hardware: EX permission */
#define _PAGE_ACCESSED 0x400 /* software: R: page referenced */
@@ -55,11 +55,6 @@
/* cache related flags non existing on 40x */
#define _PAGE_COHERENT 0
-#define _PAGE_KERNEL_RO 0
-#define _PAGE_KERNEL_ROX _PAGE_EXEC
-#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW)
-#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC)
-
#define _PMD_PRESENT 0x400 /* PMD points to page of PTEs */
#define _PMD_PRESENT_MASK _PMD_PRESENT
#define _PMD_BAD 0x802
@@ -69,20 +64,10 @@
#define _PTE_NONE_MASK 0
-/* Until my rework is finished, 40x still needs atomic PTE updates */
-#define PTE_ATOMIC_UPDATES 1
-
#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED)
#define _PAGE_BASE (_PAGE_BASE_NC)
-/* Permission masks used to generate the __P and __S table */
-#define PAGE_NONE __pgprot(_PAGE_BASE)
-#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
-#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
-#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#include <asm/pgtable-masks.h>
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_NOHASH_32_PTE_40x_H */
diff --git a/arch/powerpc/include/asm/nohash/32/pte-44x.h b/arch/powerpc/include/asm/nohash/32/pte-44x.h
index b7ed13cee137..851813725237 100644
--- a/arch/powerpc/include/asm/nohash/32/pte-44x.h
+++ b/arch/powerpc/include/asm/nohash/32/pte-44x.h
@@ -63,12 +63,12 @@
*/
#define _PAGE_PRESENT 0x00000001 /* S: PTE valid */
-#define _PAGE_RW 0x00000002 /* S: Write permission */
+#define _PAGE_WRITE 0x00000002 /* S: Write permission */
#define _PAGE_EXEC 0x00000004 /* H: Execute permission */
-#define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */
+#define _PAGE_READ 0x00000008 /* S: Read permission */
#define _PAGE_DIRTY 0x00000010 /* S: Page dirty */
#define _PAGE_SPECIAL 0x00000020 /* S: Special page */
-#define _PAGE_USER 0x00000040 /* S: User page */
+#define _PAGE_ACCESSED 0x00000040 /* S: Page referenced */
#define _PAGE_ENDIAN 0x00000080 /* H: E bit */
#define _PAGE_GUARDED 0x00000100 /* H: G bit */
#define _PAGE_COHERENT 0x00000200 /* H: M bit */
@@ -78,11 +78,6 @@
/* No page size encoding in the linux PTE */
#define _PAGE_PSIZE 0
-#define _PAGE_KERNEL_RO 0
-#define _PAGE_KERNEL_ROX _PAGE_EXEC
-#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW)
-#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC)
-
/* TODO: Add large page lowmem mapping support */
#define _PMD_PRESENT 0
#define _PMD_PRESENT_MASK (PAGE_MASK)
@@ -105,14 +100,7 @@
#define _PAGE_BASE (_PAGE_BASE_NC)
#endif
-/* Permission masks used to generate the __P and __S table */
-#define PAGE_NONE __pgprot(_PAGE_BASE)
-#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
-#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
-#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#include <asm/pgtable-masks.h>
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_NOHASH_32_PTE_44x_H */
diff --git a/arch/powerpc/include/asm/nohash/32/pte-85xx.h b/arch/powerpc/include/asm/nohash/32/pte-85xx.h
index 16451df5ddb0..653a342d3b25 100644
--- a/arch/powerpc/include/asm/nohash/32/pte-85xx.h
+++ b/arch/powerpc/include/asm/nohash/32/pte-85xx.h
@@ -17,9 +17,9 @@
*/
/* Definitions for FSL Book-E Cores */
-#define _PAGE_PRESENT 0x00001 /* S: PTE contains a translation */
-#define _PAGE_USER 0x00002 /* S: User page (maps to UR) */
-#define _PAGE_RW 0x00004 /* S: Write permission (SW) */
+#define _PAGE_READ 0x00001 /* H: Read permission (SR) */
+#define _PAGE_PRESENT 0x00002 /* S: PTE contains a translation */
+#define _PAGE_WRITE 0x00004 /* S: Write permission (SW) */
#define _PAGE_DIRTY 0x00008 /* S: Page dirty */
#define _PAGE_EXEC 0x00010 /* H: SX permission */
#define _PAGE_ACCESSED 0x00020 /* S: Page referenced */
@@ -31,11 +31,6 @@
#define _PAGE_WRITETHRU 0x00400 /* H: W bit */
#define _PAGE_SPECIAL 0x00800 /* S: Special page */
-#define _PAGE_KERNEL_RO 0
-#define _PAGE_KERNEL_ROX _PAGE_EXEC
-#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW)
-#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC)
-
/* No page size encoding in the linux PTE */
#define _PAGE_PSIZE 0
@@ -61,14 +56,7 @@
#define _PAGE_BASE (_PAGE_BASE_NC)
#endif
-/* Permission masks used to generate the __P and __S table */
-#define PAGE_NONE __pgprot(_PAGE_BASE)
-#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
-#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
-#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#include <asm/pgtable-masks.h>
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_NOHASH_32_PTE_FSL_85xx_H */
diff --git a/arch/powerpc/include/asm/nohash/32/pte-8xx.h b/arch/powerpc/include/asm/nohash/32/pte-8xx.h
index 21f681ee535a..137dc3c84e45 100644
--- a/arch/powerpc/include/asm/nohash/32/pte-8xx.h
+++ b/arch/powerpc/include/asm/nohash/32/pte-8xx.h
@@ -48,6 +48,11 @@
#define _PAGE_HUGE 0x0800 /* Copied to L1 PS bit 29 */
+#define _PAGE_NAX (_PAGE_NA | _PAGE_EXEC)
+#define _PAGE_ROX (_PAGE_RO | _PAGE_EXEC)
+#define _PAGE_RW 0
+#define _PAGE_RWX _PAGE_EXEC
+
/* cache related flags non existing on 8xx */
#define _PAGE_COHERENT 0
#define _PAGE_WRITETHRU 0
@@ -77,14 +82,7 @@
#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE)
#define _PAGE_BASE (_PAGE_BASE_NC)
-/* Permission masks used to generate the __P and __S table */
-#define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_NA)
-#define PAGE_SHARED __pgprot(_PAGE_BASE)
-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_EXEC)
-#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_RO)
-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_RO | _PAGE_EXEC)
-#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_RO)
-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_RO | _PAGE_EXEC)
+#include <asm/pgtable-masks.h>
#ifndef __ASSEMBLY__
static inline pte_t pte_wrprotect(pte_t pte)
@@ -94,6 +92,13 @@ static inline pte_t pte_wrprotect(pte_t pte)
#define pte_wrprotect pte_wrprotect
+static inline int pte_read(pte_t pte)
+{
+ return (pte_val(pte) & _PAGE_RO) != _PAGE_NA;
+}
+
+#define pte_read pte_read
+
static inline int pte_write(pte_t pte)
{
return !(pte_val(pte) & _PAGE_RO);
@@ -108,27 +113,6 @@ static inline pte_t pte_mkwrite_novma(pte_t pte)
#define pte_mkwrite_novma pte_mkwrite_novma
-static inline bool pte_user(pte_t pte)
-{
- return !(pte_val(pte) & _PAGE_SH);
-}
-
-#define pte_user pte_user
-
-static inline pte_t pte_mkprivileged(pte_t pte)
-{
- return __pte(pte_val(pte) | _PAGE_SH);
-}
-
-#define pte_mkprivileged pte_mkprivileged
-
-static inline pte_t pte_mkuser(pte_t pte)
-{
- return __pte(pte_val(pte) & ~_PAGE_SH);
-}
-
-#define pte_mkuser pte_mkuser
-
static inline pte_t pte_mkhuge(pte_t pte)
{
return __pte(pte_val(pte) | _PAGE_SPS | _PAGE_HUGE);
@@ -180,6 +164,63 @@ static inline unsigned long pte_leaf_size(pte_t pte)
#define pte_leaf_size pte_leaf_size
+/*
+ * On the 8xx, the page tables are a bit special. For 16k pages, we have
+ * 4 identical entries. For 512k pages, we have 128 entries as if it was
+ * 4k pages, but they are flagged as 512k pages for the hardware.
+ * For other page sizes, we have a single entry in the table.
+ */
+static pmd_t *pmd_off(struct mm_struct *mm, unsigned long addr);
+static int hugepd_ok(hugepd_t hpd);
+
+static inline int number_of_cells_per_pte(pmd_t *pmd, pte_basic_t val, int huge)
+{
+ if (!huge)
+ return PAGE_SIZE / SZ_4K;
+ else if (hugepd_ok(*((hugepd_t *)pmd)))
+ return 1;
+ else if (IS_ENABLED(CONFIG_PPC_4K_PAGES) && !(val & _PAGE_HUGE))
+ return SZ_16K / SZ_4K;
+ else
+ return SZ_512K / SZ_4K;
+}
+
+static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p,
+ unsigned long clr, unsigned long set, int huge)
+{
+ pte_basic_t *entry = (pte_basic_t *)p;
+ pte_basic_t old = pte_val(*p);
+ pte_basic_t new = (old & ~(pte_basic_t)clr) | set;
+ int num, i;
+ pmd_t *pmd = pmd_off(mm, addr);
+
+ num = number_of_cells_per_pte(pmd, new, huge);
+
+ for (i = 0; i < num; i += PAGE_SIZE / SZ_4K, new += PAGE_SIZE) {
+ *entry++ = new;
+ if (IS_ENABLED(CONFIG_PPC_16K_PAGES) && num != 1) {
+ *entry++ = new;
+ *entry++ = new;
+ *entry++ = new;
+ }
+ }
+
+ return old;
+}
+
+#define pte_update pte_update
+
+#ifdef CONFIG_PPC_16K_PAGES
+#define ptep_get ptep_get
+static inline pte_t ptep_get(pte_t *ptep)
+{
+ pte_basic_t val = READ_ONCE(ptep->pte);
+ pte_t pte = {val, val, val, val};
+
+ return pte;
+}
+#endif /* CONFIG_PPC_16K_PAGES */
+
#endif
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h b/arch/powerpc/include/asm/nohash/64/pgtable.h
index 5cd9acf58a7d..2202c78730e8 100644
--- a/arch/powerpc/include/asm/nohash/64/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/64/pgtable.h
@@ -57,6 +57,7 @@
#define IOREMAP_START (ioremap_bot)
#define IOREMAP_END (KERN_IO_START + KERN_IO_SIZE - FIXADDR_SIZE)
#define FIXADDR_SIZE SZ_32M
+#define FIXADDR_TOP (IOREMAP_END + FIXADDR_SIZE)
/*
* Defines the address of the vmemap area, in its own region on
@@ -74,37 +75,11 @@
#define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1))
-/*
- * _PAGE_CHG_MASK masks of bits that are to be preserved across
- * pgprot changes.
- */
-#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPECIAL)
-
#define H_PAGE_4K_PFN 0
#ifndef __ASSEMBLY__
/* pte_clear moved to later in this file */
-static inline pte_t pte_mkwrite_novma(pte_t pte)
-{
- return __pte(pte_val(pte) | _PAGE_RW);
-}
-
-static inline pte_t pte_mkdirty(pte_t pte)
-{
- return __pte(pte_val(pte) | _PAGE_DIRTY);
-}
-
-static inline pte_t pte_mkyoung(pte_t pte)
-{
- return __pte(pte_val(pte) | _PAGE_ACCESSED);
-}
-
-static inline pte_t pte_wrprotect(pte_t pte)
-{
- return __pte(pte_val(pte) & ~_PAGE_RW);
-}
-
#define PMD_BAD_BITS (PTE_TABLE_SIZE-1)
#define PUD_BAD_BITS (PMD_TABLE_SIZE-1)
@@ -170,107 +145,20 @@ static inline void p4d_set(p4d_t *p4dp, unsigned long val)
*p4dp = __p4d(val);
}
-/* Atomic PTE updates */
-static inline unsigned long pte_update(struct mm_struct *mm,
- unsigned long addr,
- pte_t *ptep, unsigned long clr,
- unsigned long set,
- int huge)
-{
- unsigned long old = pte_val(*ptep);
- *ptep = __pte((old & ~clr) | set);
-
- /* huge pages use the old page table lock */
- if (!huge)
- assert_pte_locked(mm, addr);
-
- return old;
-}
-
-static inline int pte_young(pte_t pte)
-{
- return pte_val(pte) & _PAGE_ACCESSED;
-}
-
-static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
- unsigned long addr, pte_t *ptep)
-{
- unsigned long old;
-
- if (pte_young(*ptep))
- return 0;
- old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
- return (old & _PAGE_ACCESSED) != 0;
-}
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define ptep_test_and_clear_young(__vma, __addr, __ptep) \
-({ \
- int __r; \
- __r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \
- __r; \
-})
-
-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep)
-{
-
- if ((pte_val(*ptep) & _PAGE_RW) == 0)
- return;
-
- pte_update(mm, addr, ptep, _PAGE_RW, 0, 0);
-}
-
#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
{
- if ((pte_val(*ptep) & _PAGE_RW) == 0)
- return;
-
- pte_update(mm, addr, ptep, _PAGE_RW, 0, 1);
+ pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 1);
}
#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
#define ptep_clear_flush_young(__vma, __address, __ptep) \
({ \
- int __young = __ptep_test_and_clear_young((__vma)->vm_mm, __address, \
- __ptep); \
+ int __young = ptep_test_and_clear_young(__vma, __address, __ptep);\
__young; \
})
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
- unsigned long addr, pte_t *ptep)
-{
- unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0);
- return __pte(old);
-}
-
-static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
- pte_t * ptep)
-{
- pte_update(mm, addr, ptep, ~0UL, 0, 0);
-}
-
-
-/* Set the dirty and/or accessed bits atomically in a linux PTE */
-static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
- pte_t *ptep, pte_t entry,
- unsigned long address,
- int psize)
-{
- unsigned long bits = pte_val(entry) &
- (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
-
- unsigned long old = pte_val(*ptep);
- *ptep = __pte(old | bits);
-
- flush_tlb_page(vma, address);
-}
-
-#define pte_ERROR(e) \
- pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
#define pmd_ERROR(e) \
pr_err("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
#define pgd_ERROR(e) \
@@ -310,8 +198,6 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
/* We borrow MSB 56 (LSB 7) to store the exclusive marker in swap PTEs. */
#define _PAGE_SWP_EXCLUSIVE 0x80
-int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot);
-void unmap_kernel_page(unsigned long va);
extern int __meminit vmemmap_create_mapping(unsigned long start,
unsigned long page_size,
unsigned long phys);
diff --git a/arch/powerpc/include/asm/nohash/pgtable.h b/arch/powerpc/include/asm/nohash/pgtable.h
index 56ea48276356..427db14292c9 100644
--- a/arch/powerpc/include/asm/nohash/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/pgtable.h
@@ -2,12 +2,23 @@
#ifndef _ASM_POWERPC_NOHASH_PGTABLE_H
#define _ASM_POWERPC_NOHASH_PGTABLE_H
+#ifndef __ASSEMBLY__
+static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p,
+ unsigned long clr, unsigned long set, int huge);
+#endif
+
#if defined(CONFIG_PPC64)
#include <asm/nohash/64/pgtable.h>
#else
#include <asm/nohash/32/pgtable.h>
#endif
+/*
+ * _PAGE_CHG_MASK masks of bits that are to be preserved across
+ * pgprot changes.
+ */
+#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPECIAL)
+
/* Permission masks used for kernel mappings */
#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)
#define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | _PAGE_NO_CACHE)
@@ -18,14 +29,136 @@
#ifndef __ASSEMBLY__
+extern int icache_44x_need_flush;
+
+/*
+ * PTE updates. This function is called whenever an existing
+ * valid PTE is updated. This does -not- include set_pte_at()
+ * which nowadays only sets a new PTE.
+ *
+ * Depending on the type of MMU, we may need to use atomic updates
+ * and the PTE may be either 32 or 64 bit wide. In the later case,
+ * when using atomic updates, only the low part of the PTE is
+ * accessed atomically.
+ *
+ * In addition, on 44x, we also maintain a global flag indicating
+ * that an executable user mapping was modified, which is needed
+ * to properly flush the virtually tagged instruction cache of
+ * those implementations.
+ */
+#ifndef pte_update
+static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p,
+ unsigned long clr, unsigned long set, int huge)
+{
+ pte_basic_t old = pte_val(*p);
+ pte_basic_t new = (old & ~(pte_basic_t)clr) | set;
+
+ if (new == old)
+ return old;
+
+ *p = __pte(new);
+
+ if (IS_ENABLED(CONFIG_44x) && !is_kernel_addr(addr) && (old & _PAGE_EXEC))
+ icache_44x_need_flush = 1;
+
+ /* huge pages use the old page table lock */
+ if (!huge)
+ assert_pte_locked(mm, addr);
+
+ return old;
+}
+#endif
+
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
+{
+ unsigned long old;
+
+ old = pte_update(vma->vm_mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
+
+ return (old & _PAGE_ACCESSED) != 0;
+}
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+
+#ifndef ptep_set_wrprotect
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
+{
+ pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 0);
+}
+#endif
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
+{
+ return __pte(pte_update(mm, addr, ptep, ~0UL, 0, 0));
+}
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ pte_update(mm, addr, ptep, ~0UL, 0, 0);
+}
+
+/* Set the dirty and/or accessed bits atomically in a linux PTE */
+#ifndef __ptep_set_access_flags
+static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
+ pte_t *ptep, pte_t entry,
+ unsigned long address,
+ int psize)
+{
+ unsigned long set = pte_val(entry) &
+ (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
+ int huge = psize > mmu_virtual_psize ? 1 : 0;
+
+ pte_update(vma->vm_mm, address, ptep, 0, set, huge);
+
+ flush_tlb_page(vma, address);
+}
+#endif
+
/* Generic accessors to PTE bits */
+#ifndef pte_mkwrite_novma
+static inline pte_t pte_mkwrite_novma(pte_t pte)
+{
+ /*
+ * write implies read, hence set both
+ */
+ return __pte(pte_val(pte) | _PAGE_RW);
+}
+#endif
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+ return __pte(pte_val(pte) | _PAGE_DIRTY);
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+ return __pte(pte_val(pte) | _PAGE_ACCESSED);
+}
+
+#ifndef pte_wrprotect
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+ return __pte(pte_val(pte) & ~_PAGE_WRITE);
+}
+#endif
+
+#ifndef pte_mkexec
+static inline pte_t pte_mkexec(pte_t pte)
+{
+ return __pte(pte_val(pte) | _PAGE_EXEC);
+}
+#endif
+
#ifndef pte_write
static inline int pte_write(pte_t pte)
{
- return pte_val(pte) & _PAGE_RW;
+ return pte_val(pte) & _PAGE_WRITE;
}
#endif
-static inline int pte_read(pte_t pte) { return 1; }
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; }
@@ -33,23 +166,6 @@ static inline bool pte_hashpte(pte_t pte) { return false; }
static inline bool pte_ci(pte_t pte) { return pte_val(pte) & _PAGE_NO_CACHE; }
static inline bool pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; }
-#ifdef CONFIG_NUMA_BALANCING
-/*
- * These work without NUMA balancing but the kernel does not care. See the
- * comment in include/linux/pgtable.h . On powerpc, this will only
- * work for user pages and always return true for kernel pages.
- */
-static inline int pte_protnone(pte_t pte)
-{
- return pte_present(pte) && !pte_user(pte);
-}
-
-static inline int pmd_protnone(pmd_t pmd)
-{
- return pte_protnone(pmd_pte(pmd));
-}
-#endif /* CONFIG_NUMA_BALANCING */
-
static inline int pte_present(pte_t pte)
{
return pte_val(pte) & _PAGE_PRESENT;
@@ -60,15 +176,20 @@ static inline bool pte_hw_valid(pte_t pte)
return pte_val(pte) & _PAGE_PRESENT;
}
+static inline int pte_young(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_ACCESSED;
+}
+
/*
- * Don't just check for any non zero bits in __PAGE_USER, since for book3e
+ * Don't just check for any non zero bits in __PAGE_READ, since for book3e
* and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in
- * _PAGE_USER. Need to explicitly match _PAGE_BAP_UR bit in that case too.
+ * _PAGE_READ. Need to explicitly match _PAGE_BAP_UR bit in that case too.
*/
-#ifndef pte_user
-static inline bool pte_user(pte_t pte)
+#ifndef pte_read
+static inline bool pte_read(pte_t pte)
{
- return (pte_val(pte) & _PAGE_USER) == _PAGE_USER;
+ return (pte_val(pte) & _PAGE_READ) == _PAGE_READ;
}
#endif
@@ -80,10 +201,10 @@ static inline bool pte_user(pte_t pte)
static inline bool pte_access_permitted(pte_t pte, bool write)
{
/*
- * A read-only access is controlled by _PAGE_USER bit.
- * We have _PAGE_READ set for WRITE and EXECUTE
+ * A read-only access is controlled by _PAGE_READ bit.
+ * We have _PAGE_READ set for WRITE
*/
- if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte))
+ if (!pte_present(pte) || !pte_read(pte))
return false;
if (write && !pte_write(pte))
@@ -130,20 +251,6 @@ static inline pte_t pte_mkhuge(pte_t pte)
}
#endif
-#ifndef pte_mkprivileged
-static inline pte_t pte_mkprivileged(pte_t pte)
-{
- return __pte(pte_val(pte) & ~_PAGE_USER);
-}
-#endif
-
-#ifndef pte_mkuser
-static inline pte_t pte_mkuser(pte_t pte)
-{
- return __pte(pte_val(pte) | _PAGE_USER);
-}
-#endif
-
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
@@ -205,11 +312,6 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
mb();
}
-
-#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
- pte_t *ptep, pte_t entry, int dirty);
-
/*
* Macro to mark a page protection value as "uncacheable".
*/
@@ -238,11 +340,6 @@ extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addre
#define pgprot_writecombine pgprot_noncached_wc
-struct file;
-extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
- unsigned long size, pgprot_t vma_prot);
-#define __HAVE_PHYS_MEM_ACCESS_PROT
-
#ifdef CONFIG_HUGETLB_PAGE
static inline int hugepd_ok(hugepd_t hpd)
{
@@ -267,20 +364,8 @@ static inline int pud_huge(pud_t pud)
#define is_hugepd(hpd) (hugepd_ok(hpd))
#endif
-/*
- * This gets called at the end of handling a page fault, when
- * the kernel has put a new PTE into the page table for the process.
- * We use it to ensure coherency between the i-cache and d-cache
- * for the page which has just been mapped in.
- */
-#if defined(CONFIG_PPC_E500) && defined(CONFIG_HUGETLB_PAGE)
-void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma,
- unsigned long address, pte_t *ptep, unsigned int nr);
-#else
-static inline void update_mmu_cache_range(struct vm_fault *vmf,
- struct vm_area_struct *vma, unsigned long address,
- pte_t *ptep, unsigned int nr) {}
-#endif
+int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot);
+void unmap_kernel_page(unsigned long va);
#endif /* __ASSEMBLY__ */
#endif
diff --git a/arch/powerpc/include/asm/nohash/pte-e500.h b/arch/powerpc/include/asm/nohash/pte-e500.h
index d8924cbd61e4..f516f0b5b7a8 100644
--- a/arch/powerpc/include/asm/nohash/pte-e500.h
+++ b/arch/powerpc/include/asm/nohash/pte-e500.h
@@ -48,13 +48,20 @@
/* "Higher level" linux bit combinations */
#define _PAGE_EXEC (_PAGE_BAP_SX | _PAGE_BAP_UX) /* .. and was cache cleaned */
-#define _PAGE_RW (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write permission */
+#define _PAGE_READ (_PAGE_BAP_SR | _PAGE_BAP_UR) /* User read permission */
+#define _PAGE_WRITE (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write permission */
+
#define _PAGE_KERNEL_RW (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY)
#define _PAGE_KERNEL_RO (_PAGE_BAP_SR)
#define _PAGE_KERNEL_RWX (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY | _PAGE_BAP_SX)
#define _PAGE_KERNEL_ROX (_PAGE_BAP_SR | _PAGE_BAP_SX)
-#define _PAGE_USER (_PAGE_BAP_UR | _PAGE_BAP_SR) /* Can be read */
-#define _PAGE_PRIVILEGED (_PAGE_BAP_SR)
+
+#define _PAGE_NA 0
+#define _PAGE_NAX _PAGE_BAP_UX
+#define _PAGE_RO _PAGE_READ
+#define _PAGE_ROX (_PAGE_READ | _PAGE_BAP_UX)
+#define _PAGE_RW (_PAGE_READ | _PAGE_WRITE)
+#define _PAGE_RWX (_PAGE_READ | _PAGE_WRITE | _PAGE_BAP_UX)
#define _PAGE_SPECIAL _PAGE_SW0
@@ -89,36 +96,12 @@
#define _PAGE_BASE (_PAGE_BASE_NC)
#endif
-/* Permission masks used to generate the __P and __S table */
-#define PAGE_NONE __pgprot(_PAGE_BASE)
-#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_BAP_UX)
-#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX)
-#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX)
+#include <asm/pgtable-masks.h>
#ifndef __ASSEMBLY__
-static inline pte_t pte_mkprivileged(pte_t pte)
-{
- return __pte((pte_val(pte) & ~_PAGE_USER) | _PAGE_PRIVILEGED);
-}
-
-#define pte_mkprivileged pte_mkprivileged
-
-static inline pte_t pte_mkuser(pte_t pte)
-{
- return __pte((pte_val(pte) & ~_PAGE_PRIVILEGED) | _PAGE_USER);
-}
-
-#define pte_mkuser pte_mkuser
-
static inline pte_t pte_mkexec(pte_t pte)
{
- if (pte_val(pte) & _PAGE_BAP_UR)
- return __pte((pte_val(pte) & ~_PAGE_BAP_SX) | _PAGE_BAP_UX);
- else
- return __pte((pte_val(pte) & ~_PAGE_BAP_UX) | _PAGE_BAP_SX);
+ return __pte((pte_val(pte) & ~_PAGE_BAP_SX) | _PAGE_BAP_UX);
}
#define pte_mkexec pte_mkexec
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index a9b31cc258fc..b66b0c615f4f 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -227,7 +227,7 @@ int64_t opal_pci_set_power_state(uint64_t async_token, uint64_t id,
uint64_t data);
int64_t opal_pci_poll2(uint64_t id, uint64_t data);
-int64_t opal_int_get_xirr(uint32_t *out_xirr, bool just_poll);
+int64_t opal_int_get_xirr(__be32 *out_xirr, bool just_poll);
int64_t opal_int_set_cppr(uint8_t cppr);
int64_t opal_int_eoi(uint32_t xirr);
int64_t opal_int_set_mfrr(uint32_t cpu, uint8_t mfrr);
diff --git a/arch/powerpc/include/asm/paravirt.h b/arch/powerpc/include/asm/paravirt.h
index e08513d73119..ac4279208d63 100644
--- a/arch/powerpc/include/asm/paravirt.h
+++ b/arch/powerpc/include/asm/paravirt.h
@@ -71,6 +71,11 @@ static inline void yield_to_any(void)
{
plpar_hcall_norets_notrace(H_CONFER, -1, 0);
}
+
+static inline bool is_vcpu_idle(int vcpu)
+{
+ return lppaca_of(vcpu).idle;
+}
#else
static inline bool is_shared_processor(void)
{
@@ -100,6 +105,10 @@ static inline void prod_cpu(int cpu)
___bad_prod_cpu(); /* This would be a bug */
}
+static inline bool is_vcpu_idle(int vcpu)
+{
+ return false;
+}
#endif
#define vcpu_is_preempted vcpu_is_preempted
@@ -121,9 +130,23 @@ static inline bool vcpu_is_preempted(int cpu)
if (!is_shared_processor())
return false;
+ /*
+ * If the hypervisor has dispatched the target CPU on a physical
+ * processor, then the target CPU is definitely not preempted.
+ */
+ if (!(yield_count_of(cpu) & 1))
+ return false;
+
+ /*
+ * If the target CPU has yielded to Hypervisor but OS has not
+ * requested idle then the target CPU is definitely preempted.
+ */
+ if (!is_vcpu_idle(cpu))
+ return true;
+
#ifdef CONFIG_PPC_SPLPAR
if (!is_kvm_guest()) {
- int first_cpu;
+ int first_cpu, i;
/*
* The result of vcpu_is_preempted() is used in a
@@ -149,11 +172,29 @@ static inline bool vcpu_is_preempted(int cpu)
*/
if (cpu_first_thread_sibling(cpu) == first_cpu)
return false;
+
+ /*
+ * If any of the threads of the target CPU's core are not
+ * preempted or ceded, then consider target CPU to be
+ * non-preempted.
+ */
+ first_cpu = cpu_first_thread_sibling(cpu);
+ for (i = first_cpu; i < first_cpu + threads_per_core; i++) {
+ if (i == cpu)
+ continue;
+ if (!(yield_count_of(i) & 1))
+ return false;
+ if (!is_vcpu_idle(i))
+ return true;
+ }
}
#endif
- if (yield_count_of(cpu) & 1)
- return true;
+ /*
+ * None of the threads in target CPU's core are running but none of
+ * them were preempted too. Hence assume the target CPU to be
+ * non-preempted.
+ */
return false;
}
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index f5078a7dd85a..46a9c4491ed0 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -105,9 +105,7 @@ extern void of_scan_pci_bridge(struct pci_dev *dev);
extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
extern void of_rescan_bus(struct device_node *node, struct pci_bus *bus);
-struct file;
-extern pgprot_t pci_phys_mem_access_prot(struct file *file,
- unsigned long pfn,
+extern pgprot_t pci_phys_mem_access_prot(unsigned long pfn,
unsigned long size,
pgprot_t prot);
diff --git a/arch/powerpc/include/asm/pgtable-masks.h b/arch/powerpc/include/asm/pgtable-masks.h
new file mode 100644
index 000000000000..6e8e2db26a5a
--- /dev/null
+++ b/arch/powerpc/include/asm/pgtable-masks.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_PGTABLE_MASKS_H
+#define _ASM_POWERPC_PGTABLE_MASKS_H
+
+#ifndef _PAGE_NA
+#define _PAGE_NA 0
+#define _PAGE_NAX _PAGE_EXEC
+#define _PAGE_RO _PAGE_READ
+#define _PAGE_ROX (_PAGE_READ | _PAGE_EXEC)
+#define _PAGE_RW (_PAGE_READ | _PAGE_WRITE)
+#define _PAGE_RWX (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)
+#endif
+
+/* Permission flags for kernel mappings */
+#ifndef _PAGE_KERNEL_RO
+#define _PAGE_KERNEL_RO _PAGE_RO
+#define _PAGE_KERNEL_ROX _PAGE_ROX
+#define _PAGE_KERNEL_RW (_PAGE_RW | _PAGE_DIRTY)
+#define _PAGE_KERNEL_RWX (_PAGE_RWX | _PAGE_DIRTY)
+#endif
+
+/* Permission masks used to generate the __P and __S table */
+#define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_NA)
+#define PAGE_EXECONLY_X __pgprot(_PAGE_BASE | _PAGE_NAX)
+#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_RW)
+#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_RWX)
+#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_RO)
+#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_ROX)
+#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_RO)
+#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_ROX)
+
+#endif /* _ASM_POWERPC_PGTABLE_MASKS_H */
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
index d0ee46de248e..9224f23065ff 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -71,6 +71,12 @@ static inline pgprot_t pte_pgprot(pte_t pte)
return __pgprot(pte_flags);
}
+static inline pgprot_t pgprot_nx(pgprot_t prot)
+{
+ return pte_pgprot(pte_exprotect(__pte(pgprot_val(prot))));
+}
+#define pgprot_nx pgprot_nx
+
#ifndef pmd_page_vaddr
static inline const void *pmd_page_vaddr(pmd_t pmd)
{
@@ -110,6 +116,41 @@ void mark_initmem_nx(void);
static inline void mark_initmem_nx(void) { }
#endif
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
+ pte_t *ptep, pte_t entry, int dirty);
+
+pgprot_t __phys_mem_access_prot(unsigned long pfn, unsigned long size,
+ pgprot_t vma_prot);
+
+struct file;
+static inline pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+ unsigned long size, pgprot_t vma_prot)
+{
+ return __phys_mem_access_prot(pfn, size, vma_prot);
+}
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+
+void __update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep);
+
+/*
+ * This gets called at the end of handling a page fault, when
+ * the kernel has put a new PTE into the page table for the process.
+ * We use it to ensure coherency between the i-cache and d-cache
+ * for the page which has just been mapped in.
+ * On machines which use an MMU hash table, we use this to put a
+ * corresponding HPTE into the hash table ahead of time, instead of
+ * waiting for the inevitable extra hash-table miss exception.
+ */
+static inline void update_mmu_cache_range(struct vm_fault *vmf,
+ struct vm_area_struct *vma, unsigned long address,
+ pte_t *ptep, unsigned int nr)
+{
+ if ((mmu_has_feature(MMU_FTR_HPTE_TABLE) && !radix_enabled()) ||
+ (IS_ENABLED(CONFIG_PPC_E500) && IS_ENABLED(CONFIG_HUGETLB_PAGE)))
+ __update_mmu_cache(vma, address, ptep);
+}
+
/*
* When used, PTE_FRAG_NR is defined in subarch pgtable.h
* so we are sure it is included when arriving here.
diff --git a/arch/powerpc/include/asm/plpar_wrappers.h b/arch/powerpc/include/asm/plpar_wrappers.h
index fe3d0ea0058a..b3ee44a40c2f 100644
--- a/arch/powerpc/include/asm/plpar_wrappers.h
+++ b/arch/powerpc/include/asm/plpar_wrappers.h
@@ -6,6 +6,7 @@
#include <linux/string.h>
#include <linux/irqflags.h>
+#include <linux/delay.h>
#include <asm/hvcall.h>
#include <asm/paca.h>
@@ -343,6 +344,212 @@ static inline long plpar_get_cpu_characteristics(struct h_cpu_char_result *p)
return rc;
}
+static inline long plpar_guest_create(unsigned long flags, unsigned long *guest_id)
+{
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+ unsigned long token;
+ long rc;
+
+ token = -1UL;
+ do {
+ rc = plpar_hcall(H_GUEST_CREATE, retbuf, flags, token);
+ if (rc == H_SUCCESS)
+ *guest_id = retbuf[0];
+
+ if (rc == H_BUSY) {
+ token = retbuf[0];
+ cond_resched();
+ }
+
+ if (H_IS_LONG_BUSY(rc)) {
+ token = retbuf[0];
+ msleep(get_longbusy_msecs(rc));
+ rc = H_BUSY;
+ }
+
+ } while (rc == H_BUSY);
+
+ return rc;
+}
+
+static inline long plpar_guest_create_vcpu(unsigned long flags,
+ unsigned long guest_id,
+ unsigned long vcpu_id)
+{
+ long rc;
+
+ do {
+ rc = plpar_hcall_norets(H_GUEST_CREATE_VCPU, 0, guest_id, vcpu_id);
+
+ if (rc == H_BUSY)
+ cond_resched();
+
+ if (H_IS_LONG_BUSY(rc)) {
+ msleep(get_longbusy_msecs(rc));
+ rc = H_BUSY;
+ }
+
+ } while (rc == H_BUSY);
+
+ return rc;
+}
+
+static inline long plpar_guest_set_state(unsigned long flags,
+ unsigned long guest_id,
+ unsigned long vcpu_id,
+ unsigned long data_buffer,
+ unsigned long data_size,
+ unsigned long *failed_index)
+{
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+ long rc;
+
+ while (true) {
+ rc = plpar_hcall(H_GUEST_SET_STATE, retbuf, flags, guest_id,
+ vcpu_id, data_buffer, data_size);
+
+ if (rc == H_BUSY) {
+ cpu_relax();
+ continue;
+ }
+
+ if (H_IS_LONG_BUSY(rc)) {
+ mdelay(get_longbusy_msecs(rc));
+ continue;
+ }
+
+ if (rc == H_INVALID_ELEMENT_ID)
+ *failed_index = retbuf[0];
+ else if (rc == H_INVALID_ELEMENT_SIZE)
+ *failed_index = retbuf[0];
+ else if (rc == H_INVALID_ELEMENT_VALUE)
+ *failed_index = retbuf[0];
+
+ break;
+ }
+
+ return rc;
+}
+
+static inline long plpar_guest_get_state(unsigned long flags,
+ unsigned long guest_id,
+ unsigned long vcpu_id,
+ unsigned long data_buffer,
+ unsigned long data_size,
+ unsigned long *failed_index)
+{
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+ long rc;
+
+ while (true) {
+ rc = plpar_hcall(H_GUEST_GET_STATE, retbuf, flags, guest_id,
+ vcpu_id, data_buffer, data_size);
+
+ if (rc == H_BUSY) {
+ cpu_relax();
+ continue;
+ }
+
+ if (H_IS_LONG_BUSY(rc)) {
+ mdelay(get_longbusy_msecs(rc));
+ continue;
+ }
+
+ if (rc == H_INVALID_ELEMENT_ID)
+ *failed_index = retbuf[0];
+ else if (rc == H_INVALID_ELEMENT_SIZE)
+ *failed_index = retbuf[0];
+ else if (rc == H_INVALID_ELEMENT_VALUE)
+ *failed_index = retbuf[0];
+
+ break;
+ }
+
+ return rc;
+}
+
+static inline long plpar_guest_run_vcpu(unsigned long flags, unsigned long guest_id,
+ unsigned long vcpu_id, int *trap,
+ unsigned long *failed_index)
+{
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+ long rc;
+
+ rc = plpar_hcall(H_GUEST_RUN_VCPU, retbuf, flags, guest_id, vcpu_id);
+ if (rc == H_SUCCESS)
+ *trap = retbuf[0];
+ else if (rc == H_INVALID_ELEMENT_ID)
+ *failed_index = retbuf[0];
+ else if (rc == H_INVALID_ELEMENT_SIZE)
+ *failed_index = retbuf[0];
+ else if (rc == H_INVALID_ELEMENT_VALUE)
+ *failed_index = retbuf[0];
+
+ return rc;
+}
+
+static inline long plpar_guest_delete(unsigned long flags, u64 guest_id)
+{
+ long rc;
+
+ do {
+ rc = plpar_hcall_norets(H_GUEST_DELETE, flags, guest_id);
+ if (rc == H_BUSY)
+ cond_resched();
+
+ if (H_IS_LONG_BUSY(rc)) {
+ msleep(get_longbusy_msecs(rc));
+ rc = H_BUSY;
+ }
+
+ } while (rc == H_BUSY);
+
+ return rc;
+}
+
+static inline long plpar_guest_set_capabilities(unsigned long flags,
+ unsigned long capabilities)
+{
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+ long rc;
+
+ do {
+ rc = plpar_hcall(H_GUEST_SET_CAPABILITIES, retbuf, flags, capabilities);
+ if (rc == H_BUSY)
+ cond_resched();
+
+ if (H_IS_LONG_BUSY(rc)) {
+ msleep(get_longbusy_msecs(rc));
+ rc = H_BUSY;
+ }
+ } while (rc == H_BUSY);
+
+ return rc;
+}
+
+static inline long plpar_guest_get_capabilities(unsigned long flags,
+ unsigned long *capabilities)
+{
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+ long rc;
+
+ do {
+ rc = plpar_hcall(H_GUEST_GET_CAPABILITIES, retbuf, flags);
+ if (rc == H_BUSY)
+ cond_resched();
+
+ if (H_IS_LONG_BUSY(rc)) {
+ msleep(get_longbusy_msecs(rc));
+ rc = H_BUSY;
+ }
+ } while (rc == H_BUSY);
+
+ if (rc == H_SUCCESS)
+ *capabilities = retbuf[0];
+
+ return rc;
+}
+
/*
* Wrapper to H_RPT_INVALIDATE hcall that handles return values appropriately
*
@@ -355,7 +562,7 @@ static inline long plpar_get_cpu_characteristics(struct h_cpu_char_result *p)
* error recovery of killing the process/guest will be eventually
* needed.
*/
-static inline long pseries_rpt_invalidate(u32 pid, u64 target, u64 type,
+static inline long pseries_rpt_invalidate(u64 pid, u64 target, u64 type,
u64 page_sizes, u64 start, u64 end)
{
long rc;
@@ -401,12 +608,68 @@ static inline long plpar_pte_read_4(unsigned long flags, unsigned long ptex,
return 0;
}
-static inline long pseries_rpt_invalidate(u32 pid, u64 target, u64 type,
+static inline long pseries_rpt_invalidate(u64 pid, u64 target, u64 type,
u64 page_sizes, u64 start, u64 end)
{
return 0;
}
+static inline long plpar_guest_create_vcpu(unsigned long flags,
+ unsigned long guest_id,
+ unsigned long vcpu_id)
+{
+ return 0;
+}
+
+static inline long plpar_guest_get_state(unsigned long flags,
+ unsigned long guest_id,
+ unsigned long vcpu_id,
+ unsigned long data_buffer,
+ unsigned long data_size,
+ unsigned long *failed_index)
+{
+ return 0;
+}
+
+static inline long plpar_guest_set_state(unsigned long flags,
+ unsigned long guest_id,
+ unsigned long vcpu_id,
+ unsigned long data_buffer,
+ unsigned long data_size,
+ unsigned long *failed_index)
+{
+ return 0;
+}
+
+static inline long plpar_guest_run_vcpu(unsigned long flags, unsigned long guest_id,
+ unsigned long vcpu_id, int *trap,
+ unsigned long *failed_index)
+{
+ return 0;
+}
+
+static inline long plpar_guest_create(unsigned long flags, unsigned long *guest_id)
+{
+ return 0;
+}
+
+static inline long plpar_guest_delete(unsigned long flags, u64 guest_id)
+{
+ return 0;
+}
+
+static inline long plpar_guest_get_capabilities(unsigned long flags,
+ unsigned long *capabilities)
+{
+ return 0;
+}
+
+static inline long plpar_guest_set_capabilities(unsigned long flags,
+ unsigned long capabilities)
+{
+ return 0;
+}
+
#endif /* CONFIG_PPC_PSERIES */
#endif /* _ASM_POWERPC_PLPAR_WRAPPERS_H */
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 9db8b16567e2..ea8f91fbc62f 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -397,6 +397,23 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
return 0;
}
+/**
+ * regs_get_kernel_argument() - get Nth function argument in kernel
+ * @regs: pt_regs of that context
+ * @n: function argument number (start from 0)
+ *
+ * We support up to 8 arguments and assume they are sent in through the GPRs.
+ * This will fail for fp/vector arguments, but those aren't usually found in
+ * kernel code. This is expected to be called from kprobes or ftrace with regs.
+ */
+static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs, unsigned int n)
+{
+#define NR_REG_ARGUMENTS 8
+ if (n < NR_REG_ARGUMENTS)
+ return regs_get_register(regs, offsetof(struct pt_regs, gpr[3 + n]));
+ return 0;
+}
+
#endif /* __ASSEMBLY__ */
#ifndef __powerpc64__
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index fb725ec77926..f1f9890f50d3 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -374,7 +374,7 @@ copy_mc_to_user(void __user *to, const void *from, unsigned long n)
if (check_copy_size(from, n, true)) {
if (access_ok(to, n)) {
allow_write_to_user(to, n);
- n = copy_mc_generic((void *)to, from, n);
+ n = copy_mc_generic((void __force *)to, from, n);
prevent_write_to_user(to, n);
}
}
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index 19e46fd623b0..7f63f1cdc6c3 100644
--- a/arch/powerpc/kernel/btext.c
+++ b/arch/powerpc/kernel/btext.c
@@ -8,6 +8,7 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/export.h>
+#include <linux/font.h>
#include <linux/memblock.h>
#include <linux/pgtable.h>
#include <linux/of.h>
@@ -41,10 +42,6 @@ static unsigned char *logicalDisplayBase __force_data;
unsigned long disp_BAT[2] __initdata = {0, 0};
-#define cmapsz (16*256)
-
-static unsigned char vga_font[cmapsz];
-
static int boot_text_mapped __force_data;
extern void rmci_on(void);
@@ -407,7 +404,7 @@ static unsigned int expand_bits_16[4] = {
};
-static void draw_byte_32(unsigned char *font, unsigned int *base, int rb)
+static void draw_byte_32(const unsigned char *font, unsigned int *base, int rb)
{
int l, bits;
int fg = 0xFFFFFFFFUL;
@@ -428,7 +425,7 @@ static void draw_byte_32(unsigned char *font, unsigned int *base, int rb)
}
}
-static inline void draw_byte_16(unsigned char *font, unsigned int *base, int rb)
+static inline void draw_byte_16(const unsigned char *font, unsigned int *base, int rb)
{
int l, bits;
int fg = 0xFFFFFFFFUL;
@@ -446,7 +443,7 @@ static inline void draw_byte_16(unsigned char *font, unsigned int *base, int rb)
}
}
-static inline void draw_byte_8(unsigned char *font, unsigned int *base, int rb)
+static inline void draw_byte_8(const unsigned char *font, unsigned int *base, int rb)
{
int l, bits;
int fg = 0x0F0F0F0FUL;
@@ -465,7 +462,8 @@ static inline void draw_byte_8(unsigned char *font, unsigned int *base, int rb)
static noinline void draw_byte(unsigned char c, long locX, long locY)
{
unsigned char *base = calc_base(locX << 3, locY << 4);
- unsigned char *font = &vga_font[((unsigned int)c) * 16];
+ unsigned int font_index = c * 16;
+ const unsigned char *font = font_sun_8x16.data + font_index;
int rb = dispDeviceRowBytes;
rmci_maybe_on();
@@ -583,349 +581,3 @@ void __init udbg_init_btext(void)
*/
udbg_putc = btext_drawchar;
}
-
-static unsigned char vga_font[cmapsz] = {
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd,
-0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff,
-0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe,
-0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
-0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
-0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
-0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e,
-0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30,
-0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63,
-0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8,
-0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e,
-0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
-0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb,
-0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6,
-0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
-0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
-0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c,
-0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c,
-0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c,
-0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18,
-0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
-0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
-0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18,
-0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
-0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
-0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe,
-0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
-0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
-0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
-0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
-0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
-0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde,
-0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38,
-0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
-0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c,
-0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
-0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
-0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c,
-0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60,
-0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7,
-0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66,
-0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c,
-0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c,
-0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
-0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
-0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18,
-0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
-0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
-0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c,
-0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
-0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c,
-0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60,
-0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc,
-0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
-0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60,
-0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06,
-0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60,
-0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb,
-0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
-0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60,
-0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30,
-0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3,
-0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
-0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
-0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18,
-0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6,
-0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
-0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
-0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe,
-0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
-0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c,
-0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38,
-0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06,
-0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe,
-0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
-0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66,
-0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6,
-0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00,
-0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b,
-0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c,
-0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
-0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18,
-0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc,
-0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
-0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
-0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
-0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18,
-0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66,
-0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18,
-0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c,
-0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
-0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc,
-0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc,
-0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
-0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
-0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
-0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06,
-0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
-0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
-0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
-0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44,
-0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
-0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
-0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
-0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
-0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36,
-0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8,
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
-0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6,
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
-0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
-0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36,
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
-0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
-0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
-0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0,
-0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8,
-0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66,
-0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
-0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66,
-0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60,
-0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
-0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
-0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
-0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
-0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
-0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c,
-0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00,
-};
-
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 9a3b85bfc83f..2086fa6cdc25 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -19,6 +19,7 @@
#include <linux/uio.h>
#include <asm/rtas.h>
#include <asm/inst.h>
+#include <asm/fadump.h>
#ifdef DEBUG
#include <asm/udbg.h>
@@ -92,6 +93,17 @@ ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn,
return csize;
}
+/*
+ * Return true only when kexec based kernel dump capturing method is used.
+ * This ensures all restritions applied for kdump case are not automatically
+ * applied for fadump case.
+ */
+bool is_kdump_kernel(void)
+{
+ return !is_fadump_active() && elfcorehdr_addr != ELFCORE_ADDR_MAX;
+}
+EXPORT_SYMBOL_GPL(is_kdump_kernel);
+
#ifdef CONFIG_PPC_RTAS
/*
* The crashkernel region will almost always overlap the RTAS region, so
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 438568a472d0..48773d2d9be3 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -39,7 +39,7 @@ static int eeh_result_priority(enum pci_ers_result result)
case PCI_ERS_RESULT_NEED_RESET:
return 6;
default:
- WARN_ONCE(1, "Unknown pci_ers_result value: %d\n", (int)result);
+ WARN_ONCE(1, "Unknown pci_ers_result value: %d\n", result);
return 0;
}
};
@@ -60,7 +60,7 @@ static const char *pci_ers_result_name(enum pci_ers_result result)
case PCI_ERS_RESULT_NO_AER_DRIVER:
return "no AER driver";
default:
- WARN_ONCE(1, "Unknown result type: %d\n", (int)result);
+ WARN_ONCE(1, "Unknown result type: %d\n", result);
return "unknown";
}
};
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 9692acb0361f..7eda33a24bb4 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -137,8 +137,9 @@ ret_from_syscall:
lis r4,icache_44x_need_flush@ha
lwz r5,icache_44x_need_flush@l(r4)
cmplwi cr0,r5,0
- bne- 2f
+ bne- .L44x_icache_flush
#endif /* CONFIG_PPC_47x */
+.L44x_icache_flush_return:
kuep_unlock
lwz r4,_LINK(r1)
lwz r5,_CCR(r1)
@@ -172,10 +173,11 @@ syscall_exit_finish:
b 1b
#ifdef CONFIG_44x
-2: li r7,0
+.L44x_icache_flush:
+ li r7,0
iccci r0,r0
stw r7,icache_44x_need_flush@l(r4)
- b 1b
+ b .L44x_icache_flush_return
#endif /* CONFIG_44x */
.globl ret_from_fork
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index c33c8ebf8641..eaf2f167c342 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -893,7 +893,7 @@ __start_interrupts:
*
* Call convention:
*
- * syscall register convention is in Documentation/powerpc/syscall64-abi.rst
+ * syscall register convention is in Documentation/arch/powerpc/syscall64-abi.rst
*/
EXC_VIRT_BEGIN(system_call_vectored, 0x3000, 0x1000)
/* SCV 0 */
@@ -1952,8 +1952,8 @@ EXC_VIRT_NONE(0x4b00, 0x100)
* Call convention:
*
* syscall and hypercalls register conventions are documented in
- * Documentation/powerpc/syscall64-abi.rst and
- * Documentation/powerpc/papr_hcalls.rst respectively.
+ * Documentation/arch/powerpc/syscall64-abi.rst and
+ * Documentation/arch/powerpc/papr_hcalls.rst respectively.
*
* The intersection of volatile registers that don't contain possible
* inputs is: cr0, xer, ctr. We may use these as scratch regs upon entry
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 3ff2da7b120b..d14eda1e8589 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -313,7 +313,7 @@ static __init u64 fadump_calculate_reserve_size(void)
* memory at a predefined offset.
*/
ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
- &size, &base);
+ &size, &base, NULL, NULL);
if (ret == 0 && size > 0) {
unsigned long max_size;
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index 6a9acfb690c9..2f8f3f93cbb6 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -23,6 +23,15 @@
#include <asm/feature-fixups.h>
#ifdef CONFIG_VSX
+#define __REST_1FPVSR(n,c,base) \
+BEGIN_FTR_SECTION \
+ b 2f; \
+END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
+ REST_FPR(n,base); \
+ b 3f; \
+2: REST_VSR(n,c,base); \
+3:
+
#define __REST_32FPVSRS(n,c,base) \
BEGIN_FTR_SECTION \
b 2f; \
@@ -41,9 +50,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
2: SAVE_32VSRS(n,c,base); \
3:
#else
+#define __REST_1FPVSR(n,b,base) REST_FPR(n, base)
#define __REST_32FPVSRS(n,b,base) REST_32FPRS(n, base)
#define __SAVE_32FPVSRS(n,b,base) SAVE_32FPRS(n, base)
#endif
+#define REST_1FPVSR(n,c,base) __REST_1FPVSR(n,__REG_##c,__REG_##base)
#define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base)
#define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base)
@@ -67,6 +78,7 @@ _GLOBAL(store_fp_state)
SAVE_32FPVSRS(0, R4, R3)
mffs fr0
stfd fr0,FPSTATE_FPSCR(r3)
+ REST_1FPVSR(0, R4, R3)
blr
EXPORT_SYMBOL(store_fp_state)
@@ -138,4 +150,5 @@ _GLOBAL(save_fpu)
2: SAVE_32FPVSRS(0, R4, R6)
mffs fr0
stfd fr0,FPSTATE_FPSCR(r6)
+ REST_1FPVSR(0, R4, R6)
blr
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S
index b32e7b2ebdcf..9fc90410b385 100644
--- a/arch/powerpc/kernel/head_40x.S
+++ b/arch/powerpc/kernel/head_40x.S
@@ -312,13 +312,13 @@ _ASM_NOKPROBE_SYMBOL(\name\()_virt)
rlwimi r11, r10, 22, 20, 29 /* Compute PTE address */
lwz r11, 0(r11) /* Get Linux PTE */
- li r9, _PAGE_PRESENT | _PAGE_ACCESSED
+ li r9, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_READ
andc. r9, r9, r11 /* Check permission */
bne 5f
- rlwinm r9, r11, 1, _PAGE_RW /* dirty => rw */
- and r9, r9, r11 /* hwwrite = dirty & rw */
- rlwimi r11, r9, 0, _PAGE_RW /* replace rw by hwwrite */
+ rlwinm r9, r11, 1, _PAGE_WRITE /* dirty => w */
+ and r9, r9, r11 /* hwwrite = dirty & w */
+ rlwimi r11, r9, 0, _PAGE_WRITE /* replace w by hwwrite */
/* Create TLB tag. This is the faulting address plus a static
* set of bits. These are size, valid, E, U0.
@@ -400,9 +400,9 @@ _ASM_NOKPROBE_SYMBOL(\name\()_virt)
andc. r9, r9, r11 /* Check permission */
bne 5f
- rlwinm r9, r11, 1, _PAGE_RW /* dirty => rw */
- and r9, r9, r11 /* hwwrite = dirty & rw */
- rlwimi r11, r9, 0, _PAGE_RW /* replace rw by hwwrite */
+ rlwinm r9, r11, 1, _PAGE_WRITE /* dirty => w */
+ and r9, r9, r11 /* hwwrite = dirty & w */
+ rlwimi r11, r9, 0, _PAGE_WRITE /* replace w by hwwrite */
/* Create TLB tag. This is the faulting address plus a static
* set of bits. These are size, valid, E, U0.
@@ -561,10 +561,11 @@ finish_tlb_load:
/*
* Clear out the software-only bits in the PTE to generate the
* TLB_DATA value. These are the bottom 2 bits of the RPM, the
- * top 3 bits of the zone field, and M.
+ * 4 bits of the zone field, and M.
*/
- li r9, 0x0ce2
+ li r9, 0x0cf2
andc r11, r11, r9
+ rlwimi r11, r10, 8, 24, 27 /* Copy 4 upper address bit into zone */
/* load the next available TLB index. */
lwz r9, tlb_4xx_index@l(0)
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index a3197c9f721c..25642e802ed3 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -314,8 +314,8 @@ interrupt_base:
* kernel page tables.
*/
lis r11, PAGE_OFFSET@h
- cmplw r10, r11
- blt+ 3f
+ cmplw cr7, r10, r11
+ blt+ cr7, 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
@@ -342,7 +342,7 @@ interrupt_base:
mtspr SPRN_MMUCR,r12
/* Mask of required permission bits. Note that while we
- * do copy ESR:ST to _PAGE_RW position as trying to write
+ * do copy ESR:ST to _PAGE_WRITE position as trying to write
* to an RO page is pretty common, we don't do it with
* _PAGE_DIRTY. We could do it, but it's a fairly rare
* event so I'd rather take the overhead when it happens
@@ -355,7 +355,7 @@ interrupt_base:
* place or can we save a couple of instructions here ?
*/
mfspr r12,SPRN_ESR
- li r13,_PAGE_PRESENT|_PAGE_ACCESSED
+ li r13,_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_READ
rlwimi r13,r12,10,30,30
/* Load the PTE */
@@ -428,8 +428,8 @@ interrupt_base:
* kernel page tables.
*/
lis r11, PAGE_OFFSET@h
- cmplw r10, r11
- blt+ 3f
+ cmplw cr7, r10, r11
+ blt+ cr7, 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
@@ -515,6 +515,7 @@ interrupt_base:
* r11 - PTE high word value
* r12 - PTE low word value
* r13 - TLB index
+ * cr7 - Result of comparison with PAGE_OFFSET
* MMUCR - loaded with proper value when we get here
* Upon exit, we reload everything and RFI.
*/
@@ -533,11 +534,10 @@ finish_tlb_load_44x:
tlbwe r10,r13,PPC44x_TLB_PAGEID /* Write PAGEID */
/* And WS 2 */
- li r10,0xf85 /* Mask to apply from PTE */
- rlwimi r10,r12,29,30,30 /* DIRTY -> SW position */
+ li r10,0xf84 /* Mask to apply from PTE */
+ rlwimi r10,r12,29,30,31 /* DIRTY,READ -> SW,SR position */
and r11,r12,r10 /* Mask PTE bits to keep */
- andi. r10,r12,_PAGE_USER /* User page ? */
- beq 1f /* nope, leave U bits empty */
+ bge cr7,1f /* User page ? no, leave U bits empty */
rlwimi r11,r11,3,26,28 /* yes, copy S bits to U */
rlwinm r11,r11,0,~PPC44x_TLB_SX /* Clear SX if User page */
1: tlbwe r11,r13,PPC44x_TLB_ATTRIB /* Write ATTRIB */
@@ -568,8 +568,8 @@ finish_tlb_load_44x:
* kernel page tables.
*/
lis r11,PAGE_OFFSET@h
- cmplw cr0,r10,r11
- blt+ 3f
+ cmplw cr7,r10,r11
+ blt+ cr7,3f
lis r11,swapper_pg_dir@h
ori r11,r11, swapper_pg_dir@l
li r12,0 /* MMUCR = 0 */
@@ -586,7 +586,7 @@ finish_tlb_load_44x:
4: mtspr SPRN_MMUCR,r12 /* Set MMUCR */
/* Mask of required permission bits. Note that while we
- * do copy ESR:ST to _PAGE_RW position as trying to write
+ * do copy ESR:ST to _PAGE_WRITE position as trying to write
* to an RO page is pretty common, we don't do it with
* _PAGE_DIRTY. We could do it, but it's a fairly rare
* event so I'd rather take the overhead when it happens
@@ -599,7 +599,7 @@ finish_tlb_load_44x:
* place or can we save a couple of instructions here ?
*/
mfspr r12,SPRN_ESR
- li r13,_PAGE_PRESENT|_PAGE_ACCESSED
+ li r13,_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_READ
rlwimi r13,r12,10,30,30
/* Load the PTE */
@@ -669,8 +669,8 @@ finish_tlb_load_44x:
* kernel page tables.
*/
lis r11,PAGE_OFFSET@h
- cmplw cr0,r10,r11
- blt+ 3f
+ cmplw cr7,r10,r11
+ blt+ cr7,3f
lis r11,swapper_pg_dir@h
ori r11,r11, swapper_pg_dir@l
li r12,0 /* MMUCR = 0 */
@@ -744,6 +744,7 @@ finish_tlb_load_44x:
* r11 - PTE high word value
* r12 - PTE low word value
* r13 - free to use
+ * cr7 - Result of comparison with PAGE_OFFSET
* MMUCR - loaded with proper value when we get here
* Upon exit, we reload everything and RFI.
*/
@@ -753,11 +754,10 @@ finish_tlb_load_47x:
tlbwe r11,r13,1
/* And make up word 2 */
- li r10,0xf85 /* Mask to apply from PTE */
- rlwimi r10,r12,29,30,30 /* DIRTY -> SW position */
+ li r10,0xf84 /* Mask to apply from PTE */
+ rlwimi r10,r12,29,30,31 /* DIRTY,READ -> SW,SR position */
and r11,r12,r10 /* Mask PTE bits to keep */
- andi. r10,r12,_PAGE_USER /* User page ? */
- beq 1f /* nope, leave U bits empty */
+ bge cr7,1f /* User page ? no, leave U bits empty */
rlwimi r11,r11,3,26,28 /* yes, copy S bits to U */
rlwinm r11,r11,0,~PPC47x_TLB2_SX /* Clear SX if User page */
1: tlbwe r11,r13,2
diff --git a/arch/powerpc/kernel/head_85xx.S b/arch/powerpc/kernel/head_85xx.S
index 97e9ea0c7297..39724ff5ae1f 100644
--- a/arch/powerpc/kernel/head_85xx.S
+++ b/arch/powerpc/kernel/head_85xx.S
@@ -395,7 +395,7 @@ interrupt_base:
#ifdef CONFIG_PPC_FPU
FP_UNAVAILABLE_EXCEPTION
#else
- EXCEPTION(0x0800, FP_UNAVAIL, FloatingPointUnavailable, unknown_exception)
+ EXCEPTION(0x0800, FP_UNAVAIL, FloatingPointUnavailable, emulation_assist_interrupt)
#endif
/* System Call Interrupt */
@@ -471,7 +471,7 @@ END_BTB_FLUSH_SECTION
4:
/* Mask of required permission bits. Note that while we
- * do copy ESR:ST to _PAGE_RW position as trying to write
+ * do copy ESR:ST to _PAGE_WRITE position as trying to write
* to an RO page is pretty common, we don't do it with
* _PAGE_DIRTY. We could do it, but it's a fairly rare
* event so I'd rather take the overhead when it happens
@@ -485,10 +485,10 @@ END_BTB_FLUSH_SECTION
*/
mfspr r12,SPRN_ESR
#ifdef CONFIG_PTE_64BIT
- li r13,_PAGE_PRESENT
+ li r13,_PAGE_PRESENT|_PAGE_BAP_SR
oris r13,r13,_PAGE_ACCESSED@h
#else
- li r13,_PAGE_PRESENT|_PAGE_ACCESSED
+ li r13,_PAGE_PRESENT|_PAGE_READ|_PAGE_ACCESSED
#endif
rlwimi r13,r12,11,29,29
@@ -783,15 +783,15 @@ BEGIN_MMU_FTR_SECTION
mtspr SPRN_MAS7, r10
END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
#else
- li r10, (_PAGE_EXEC | _PAGE_PRESENT)
+ li r10, (_PAGE_EXEC | _PAGE_READ)
mr r13, r11
rlwimi r10, r11, 31, 29, 29 /* extract _PAGE_DIRTY into SW */
and r12, r11, r10
- andi. r10, r11, _PAGE_USER /* Test for _PAGE_USER */
+ mcrf cr0, cr5 /* Test for user page */
slwi r10, r12, 1
or r10, r10, r12
rlwinm r10, r10, 0, ~_PAGE_EXEC /* Clear SX on user pages */
- iseleq r12, r12, r10
+ isellt r12, r10, r12
rlwimi r13, r12, 0, 20, 31 /* Get RPN from PTE, merge w/ perms */
mtspr SPRN_MAS3, r13
#endif
diff --git a/arch/powerpc/kernel/head_book3s_32.S b/arch/powerpc/kernel/head_book3s_32.S
index 6764b98ca360..c1d89764dd22 100644
--- a/arch/powerpc/kernel/head_book3s_32.S
+++ b/arch/powerpc/kernel/head_book3s_32.S
@@ -412,10 +412,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE)
. = INTERRUPT_INST_TLB_MISS_603
InstructionTLBMiss:
/*
- * r0: scratch
+ * r0: userspace flag (later scratch)
* r1: linux style pte ( later becomes ppc hardware pte )
* r2: ptr to linux-style pte
- * r3: scratch
+ * r3: fault address
*/
/* Get PTE (linux-style) and check access */
mfspr r3,SPRN_IMISS
@@ -424,12 +424,13 @@ InstructionTLBMiss:
cmplw 0,r1,r3
#endif
mfspr r2, SPRN_SDR1
- li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC | _PAGE_USER
+ li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
rlwinm r2, r2, 28, 0xfffff000
#ifdef CONFIG_MODULES
+ li r0, 3
bgt- 112f
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
- li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
+ li r0, 0
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
#endif
112: rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
@@ -437,13 +438,15 @@ InstructionTLBMiss:
rlwinm. r2,r2,0,0,19 /* extract address of pte page */
beq- InstructionAddressInvalid /* return if no mapping */
rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
- lwz r0,0(r2) /* get linux-style pte */
- andc. r1,r1,r0 /* check access & ~permission */
+ lwz r2,0(r2) /* get linux-style pte */
+ andc. r1,r1,r2 /* check access & ~permission */
bne- InstructionAddressInvalid /* return if access not permitted */
/* Convert linux-style PTE to low word of PPC-style PTE */
- rlwimi r0,r0,32-2,31,31 /* _PAGE_USER -> PP lsb */
+#ifdef CONFIG_MODULES
+ rlwimi r2, r0, 0, 31, 31 /* userspace ? -> PP lsb */
+#endif
ori r1, r1, 0xe06 /* clear out reserved bits */
- andc r1, r0, r1 /* PP = user? 1 : 0 */
+ andc r1, r2, r1 /* PP = user? 1 : 0 */
BEGIN_FTR_SECTION
rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */
END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
@@ -478,38 +481,38 @@ InstructionAddressInvalid:
. = INTERRUPT_DATA_LOAD_TLB_MISS_603
DataLoadTLBMiss:
/*
- * r0: scratch
+ * r0: userspace flag (later scratch)
* r1: linux style pte ( later becomes ppc hardware pte )
* r2: ptr to linux-style pte
- * r3: scratch
+ * r3: fault address
*/
/* Get PTE (linux-style) and check access */
mfspr r3,SPRN_DMISS
lis r1, TASK_SIZE@h /* check if kernel address */
cmplw 0,r1,r3
mfspr r2, SPRN_SDR1
- li r1, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER
+ li r1, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_READ
rlwinm r2, r2, 28, 0xfffff000
+ li r0, 3
bgt- 112f
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
- li r1, _PAGE_PRESENT | _PAGE_ACCESSED
+ li r0, 0
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
112: rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
lwz r2,0(r2) /* get pmd entry */
rlwinm. r2,r2,0,0,19 /* extract address of pte page */
beq- DataAddressInvalid /* return if no mapping */
rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
- lwz r0,0(r2) /* get linux-style pte */
- andc. r1,r1,r0 /* check access & ~permission */
+ lwz r2,0(r2) /* get linux-style pte */
+ andc. r1,r1,r2 /* check access & ~permission */
bne- DataAddressInvalid /* return if access not permitted */
/* Convert linux-style PTE to low word of PPC-style PTE */
- rlwinm r1,r0,32-9,30,30 /* _PAGE_RW -> PP msb */
- rlwimi r0,r0,32-1,30,30 /* _PAGE_USER -> PP msb */
- rlwimi r1,r0,32-3,24,24 /* _PAGE_RW -> _PAGE_DIRTY */
- rlwimi r0,r0,32-1,31,31 /* _PAGE_USER -> PP lsb */
+ rlwinm r1,r2,32-9,30,30 /* _PAGE_WRITE -> PP msb */
+ rlwimi r2,r0,0,30,31 /* userspace ? -> PP */
+ rlwimi r1,r2,32-3,24,24 /* _PAGE_WRITE -> _PAGE_DIRTY */
xori r1,r1,_PAGE_DIRTY /* clear dirty when not rw */
ori r1,r1,0xe04 /* clear out reserved bits */
- andc r1,r0,r1 /* PP = user? rw? 1: 3: 0 */
+ andc r1,r2,r1 /* PP = user? rw? 1: 3: 0 */
BEGIN_FTR_SECTION
rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */
END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
@@ -558,34 +561,35 @@ DataAddressInvalid:
. = INTERRUPT_DATA_STORE_TLB_MISS_603
DataStoreTLBMiss:
/*
- * r0: scratch
+ * r0: userspace flag (later scratch)
* r1: linux style pte ( later becomes ppc hardware pte )
* r2: ptr to linux-style pte
- * r3: scratch
+ * r3: fault address
*/
/* Get PTE (linux-style) and check access */
mfspr r3,SPRN_DMISS
lis r1, TASK_SIZE@h /* check if kernel address */
cmplw 0,r1,r3
mfspr r2, SPRN_SDR1
- li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER
+ li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
rlwinm r2, r2, 28, 0xfffff000
+ li r0, 3
bgt- 112f
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
- li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
+ li r0, 0
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
112: rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
lwz r2,0(r2) /* get pmd entry */
rlwinm. r2,r2,0,0,19 /* extract address of pte page */
beq- DataAddressInvalid /* return if no mapping */
rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
- lwz r0,0(r2) /* get linux-style pte */
- andc. r1,r1,r0 /* check access & ~permission */
+ lwz r2,0(r2) /* get linux-style pte */
+ andc. r1,r1,r2 /* check access & ~permission */
bne- DataAddressInvalid /* return if access not permitted */
/* Convert linux-style PTE to low word of PPC-style PTE */
- rlwimi r0,r0,32-2,31,31 /* _PAGE_USER -> PP lsb */
+ rlwimi r2,r0,0,31,31 /* userspace ? -> PP lsb */
li r1,0xe06 /* clear out reserved bits & PP msb */
- andc r1,r0,r1 /* PP = user? 1: 0 */
+ andc r1,r2,r1 /* PP = user? 1: 0 */
BEGIN_FTR_SECTION
rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */
END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
@@ -689,7 +693,8 @@ hash_page_dsi:
mfdar r4
mfsrr0 r5
mfsrr1 r9
- rlwinm r3, r3, 32 - 15, _PAGE_RW /* DSISR_STORE -> _PAGE_RW */
+ rlwinm r3, r3, 32 - 15, _PAGE_WRITE /* DSISR_STORE -> _PAGE_WRITE */
+ ori r3, r3, _PAGE_PRESENT | _PAGE_READ
bl hash_page
mfspr r10, SPRN_SPRG_THREAD
restore_regs_thread r10
@@ -699,7 +704,7 @@ hash_page_isi:
mr r11, r10
mfspr r10, SPRN_SPRG_THREAD
save_regs_thread r10
- li r3, 0
+ li r3, _PAGE_PRESENT | _PAGE_EXEC
lwz r4, SRR0(r10)
lwz r9, SRR1(r10)
bl hash_page
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index b1c0418b25c8..30b56c67fa61 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -105,7 +105,6 @@ static struct ctl_table powersave_nap_ctl_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
- {}
};
static int __init
diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c
index 2f29b7d432de..6af535905984 100644
--- a/arch/powerpc/kernel/io.c
+++ b/arch/powerpc/kernel/io.c
@@ -33,7 +33,7 @@ void _insb(const volatile u8 __iomem *port, void *buf, long count)
return;
asm volatile("sync");
do {
- tmp = *port;
+ tmp = *(const volatile u8 __force *)port;
eieio();
*tbuf++ = tmp;
} while (--count != 0);
@@ -49,7 +49,7 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count)
return;
asm volatile("sync");
do {
- *port = *tbuf++;
+ *(volatile u8 __force *)port = *tbuf++;
} while (--count != 0);
asm volatile("sync");
}
@@ -64,7 +64,7 @@ void _insw_ns(const volatile u16 __iomem *port, void *buf, long count)
return;
asm volatile("sync");
do {
- tmp = *port;
+ tmp = *(const volatile u16 __force *)port;
eieio();
*tbuf++ = tmp;
} while (--count != 0);
@@ -80,7 +80,7 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count)
return;
asm volatile("sync");
do {
- *port = *tbuf++;
+ *(volatile u16 __force *)port = *tbuf++;
} while (--count != 0);
asm volatile("sync");
}
@@ -95,7 +95,7 @@ void _insl_ns(const volatile u32 __iomem *port, void *buf, long count)
return;
asm volatile("sync");
do {
- tmp = *port;
+ tmp = *(const volatile u32 __force *)port;
eieio();
*tbuf++ = tmp;
} while (--count != 0);
@@ -111,7 +111,7 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count)
return;
asm volatile("sync");
do {
- *port = *tbuf++;
+ *(volatile u32 __force *)port = *tbuf++;
} while (--count != 0);
asm volatile("sync");
}
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 14251bc5219e..ebe259bdd462 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -1074,10 +1074,10 @@ int iommu_tce_check_gpa(unsigned long page_shift, unsigned long gpa)
}
EXPORT_SYMBOL_GPL(iommu_tce_check_gpa);
-extern long iommu_tce_xchg_no_kill(struct mm_struct *mm,
- struct iommu_table *tbl,
- unsigned long entry, unsigned long *hpa,
- enum dma_data_direction *direction)
+long iommu_tce_xchg_no_kill(struct mm_struct *mm,
+ struct iommu_table *tbl,
+ unsigned long entry, unsigned long *hpa,
+ enum dma_data_direction *direction)
{
long ret;
unsigned long size = 0;
@@ -1280,13 +1280,19 @@ struct iommu_table_group_ops spapr_tce_table_group_ops = {
/*
* A simple iommu_ops to allow less cruft in generic VFIO code.
*/
-static int spapr_tce_blocking_iommu_attach_dev(struct iommu_domain *dom,
- struct device *dev)
+static int
+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;
int ret = -EINVAL;
+ /* At first attach the ownership is already set */
+ if (!domain)
+ return 0;
+
if (!grp)
return -ENODEV;
@@ -1297,17 +1303,22 @@ static int spapr_tce_blocking_iommu_attach_dev(struct iommu_domain *dom,
return ret;
}
-static void spapr_tce_blocking_iommu_set_platform_dma(struct device *dev)
-{
- struct iommu_group *grp = iommu_group_get(dev);
- struct iommu_table_group *table_group;
+static const struct iommu_domain_ops spapr_tce_platform_domain_ops = {
+ .attach_dev = spapr_tce_platform_iommu_attach_dev,
+};
- table_group = iommu_group_get_iommudata(grp);
- table_group->ops->release_ownership(table_group);
-}
+static struct iommu_domain spapr_tce_platform_domain = {
+ .type = IOMMU_DOMAIN_PLATFORM,
+ .ops = &spapr_tce_platform_domain_ops,
+};
-static const struct iommu_domain_ops spapr_tce_blocking_domain_ops = {
- .attach_dev = spapr_tce_blocking_iommu_attach_dev,
+static struct iommu_domain spapr_tce_blocked_domain = {
+ .type = IOMMU_DOMAIN_BLOCKED,
+ /*
+ * FIXME: SPAPR mixes blocked and platform behaviors, the blocked domain
+ * also sets the dma_api ops
+ */
+ .ops = &spapr_tce_platform_domain_ops,
};
static bool spapr_tce_iommu_capable(struct device *dev, enum iommu_cap cap)
@@ -1322,22 +1333,6 @@ static bool spapr_tce_iommu_capable(struct device *dev, enum iommu_cap cap)
return false;
}
-static struct iommu_domain *spapr_tce_iommu_domain_alloc(unsigned int type)
-{
- struct iommu_domain *dom;
-
- if (type != IOMMU_DOMAIN_BLOCKED)
- return NULL;
-
- dom = kzalloc(sizeof(*dom), GFP_KERNEL);
- if (!dom)
- return NULL;
-
- dom->ops = &spapr_tce_blocking_domain_ops;
-
- return dom;
-}
-
static struct iommu_device *spapr_tce_iommu_probe_device(struct device *dev)
{
struct pci_dev *pdev;
@@ -1371,12 +1366,12 @@ static struct iommu_group *spapr_tce_iommu_device_group(struct device *dev)
}
static const struct iommu_ops spapr_tce_iommu_ops = {
+ .default_domain = &spapr_tce_platform_domain,
+ .blocked_domain = &spapr_tce_blocked_domain,
.capable = spapr_tce_iommu_capable,
- .domain_alloc = spapr_tce_iommu_domain_alloc,
.probe_device = spapr_tce_iommu_probe_device,
.release_device = spapr_tce_iommu_release_device,
.device_group = spapr_tce_iommu_device_group,
- .set_platform_dma_ops = spapr_tce_blocking_iommu_set_platform_dma,
};
static struct attribute *spapr_tce_iommu_attrs[] = {
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index cda4e00b67c1..7502066c3c53 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -68,7 +68,7 @@ static void *__init alloc_shared_lppaca(unsigned long size, unsigned long limit,
memblock_set_bottom_up(true);
/*
- * See Documentation/powerpc/ultravisor.rst for more details.
+ * See Documentation/arch/powerpc/ultravisor.rst for more details.
*
* UV/HV data sharing is in PAGE_SIZE granularity. In order to
* minimize the number of pages shared, align the allocation to
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 040255ddb569..d95a48eff412 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -521,8 +521,7 @@ int pci_iobar_pfn(struct pci_dev *pdev, int bar, struct vm_area_struct *vma)
* PCI device, it tries to find the PCI device first and calls the
* above routine
*/
-pgprot_t pci_phys_mem_access_prot(struct file *file,
- unsigned long pfn,
+pgprot_t pci_phys_mem_access_prot(unsigned long pfn,
unsigned long size,
pgprot_t prot)
{
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index b68898ac07e1..9452a54d356c 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1198,11 +1198,11 @@ void kvmppc_save_user_regs(void)
usermsr = current->thread.regs->msr;
+ /* Caller has enabled FP/VEC/VSX/TM in MSR */
if (usermsr & MSR_FP)
- save_fpu(current);
-
+ __giveup_fpu(current);
if (usermsr & MSR_VEC)
- save_altivec(current);
+ __giveup_altivec(current);
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
if (usermsr & MSR_TM) {
@@ -2258,6 +2258,22 @@ unsigned long __get_wchan(struct task_struct *p)
return ret;
}
+static bool empty_user_regs(struct pt_regs *regs, struct task_struct *tsk)
+{
+ unsigned long stack_page;
+
+ // A non-empty pt_regs should never have a zero MSR or TRAP value.
+ if (regs->msr || regs->trap)
+ return false;
+
+ // Check it sits at the very base of the stack
+ stack_page = (unsigned long)task_stack_page(tsk);
+ if ((unsigned long)(regs + 1) != stack_page + THREAD_SIZE)
+ return false;
+
+ return true;
+}
+
static int kstack_depth_to_print = CONFIG_PRINT_STACK_DEPTH;
void __no_sanitize_address show_stack(struct task_struct *tsk,
@@ -2322,9 +2338,13 @@ void __no_sanitize_address show_stack(struct task_struct *tsk,
lr = regs->link;
printk("%s--- interrupt: %lx at %pS\n",
loglvl, regs->trap, (void *)regs->nip);
- __show_regs(regs);
- printk("%s--- interrupt: %lx\n",
- loglvl, regs->trap);
+
+ // Detect the case of an empty pt_regs at the very base
+ // of the stack and suppress showing it in full.
+ if (!empty_user_regs(regs, tsk)) {
+ __show_regs(regs);
+ printk("%s--- interrupt: %lx\n", loglvl, regs->trap);
+ }
firstframe = 1;
}
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index d464ba412084..e67effdba85c 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -947,7 +947,7 @@ struct option_vector7 {
} __packed;
struct ibm_arch_vec {
- struct { u32 mask, val; } pvrs[14];
+ struct { __be32 mask, val; } pvrs[14];
u8 num_vectors;
diff --git a/arch/powerpc/kernel/ptrace/ptrace.c b/arch/powerpc/kernel/ptrace/ptrace.c
index 5d7a72b41ae7..727ed4a14545 100644
--- a/arch/powerpc/kernel/ptrace/ptrace.c
+++ b/arch/powerpc/kernel/ptrace/ptrace.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -9,10 +10,6 @@
*
* Modified by Cort Dougan (cort@hq.fsmlabs.com)
* and Paul Mackerras (paulus@samba.org).
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file README.legal in the main directory of
- * this archive for more details.
*/
#include <linux/regset.h>
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index 9454b8395b6a..f38df72e64b8 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -752,6 +752,8 @@ static int ppc_rtas_tone_volume_show(struct seq_file *m, void *v)
/**
* ppc_rtas_rmo_buf_show() - Describe RTAS-addressable region for user space.
+ * @m: seq_file output target.
+ * @v: Unused.
*
* Base + size description of a range of RTAS-addressable memory set
* aside for user space to use as work area(s) for certain RTAS
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 2f1026fba00d..9b142b9d5187 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -22,7 +22,6 @@
#include <linux/seq_file.h>
#include <linux/ioport.h>
#include <linux/console.h>
-#include <linux/screen_info.h>
#include <linux/root_dev.h>
#include <linux/cpu.h>
#include <linux/unistd.h>
@@ -98,21 +97,6 @@ int boot_cpu_hwid = -1;
int dcache_bsize;
int icache_bsize;
-/*
- * This still seems to be needed... -- paulus
- */
-struct screen_info screen_info = {
- .orig_x = 0,
- .orig_y = 25,
- .orig_video_cols = 80,
- .orig_video_lines = 25,
- .orig_video_isVGA = 1,
- .orig_video_points = 16
-};
-#if defined(CONFIG_FB_VGA16_MODULE)
-EXPORT_SYMBOL(screen_info);
-#endif
-
/* Variables required to store legacy IO irq routing */
int of_i8042_kbd_irq;
EXPORT_SYMBOL_GPL(of_i8042_kbd_irq);
@@ -601,7 +585,6 @@ struct seq_buf ppc_hw_desc __initdata = {
.buffer = ppc_hw_desc_buf,
.size = sizeof(ppc_hw_desc_buf),
.len = 0,
- .readpos = 0,
};
static __init void probe_machine(void)
@@ -948,6 +931,8 @@ void __init setup_arch(char **cmdline_p)
/* Parse memory topology */
mem_topology_setup();
+ /* Set max_mapnr before paging_init() */
+ set_max_mapnr(max_pfn);
/*
* Release secondary cpus out of their spinloops at 0x60 now that
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 246201d0d879..2f19d5e94485 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -364,7 +364,7 @@ void __init early_setup(unsigned long dt_ptr)
*/
initialise_paca(&boot_paca, 0);
fixup_boot_paca(&boot_paca);
- WARN_ON(local_paca != 0);
+ WARN_ON(local_paca);
setup_paca(&boot_paca); /* install the paca into registers */
/* -------- printk is now safe to use ------- */
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index 68a91e553e14..aa17e62f3754 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Common signal handling code for both 32 and 64 bits
*
* Copyright (c) 2007 Benjamin Herrenschmidt, IBM Corporation
* Extracted from signal_32.c and signal_64.c
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file README.legal in the main directory of
- * this archive for more details.
*/
#include <linux/resume_user_mode.h>
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h
index a429c57ed433..58ecea1cdc27 100644
--- a/arch/powerpc/kernel/signal.h
+++ b/arch/powerpc/kernel/signal.h
@@ -1,10 +1,7 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ *
* Copyright (c) 2007 Benjamin Herrenschmidt, IBM Corporation
* Extracted from signal_32.c and signal_64.c
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file README.legal in the main directory of
- * this archive for more details.
*/
#ifndef _POWERPC_ARCH_SIGNAL_H
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 5826f5108a12..ab691c89d787 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -1051,7 +1051,7 @@ static struct sched_domain_topology_level powerpc_topology[] = {
#endif
{ shared_cache_mask, powerpc_shared_cache_flags, SD_INIT_NAME(CACHE) },
{ cpu_mc_mask, SD_INIT_NAME(MC) },
- { cpu_cpu_mask, SD_INIT_NAME(DIE) },
+ { cpu_cpu_mask, SD_INIT_NAME(PKG) },
{ NULL, },
};
@@ -1595,7 +1595,7 @@ static void add_cpu_to_masks(int cpu)
/* Skip all CPUs already part of current CPU core mask */
cpumask_andnot(mask, cpu_online_mask, cpu_core_mask(cpu));
- /* If chip_id is -1; limit the cpu_core_mask to within DIE*/
+ /* If chip_id is -1; limit the cpu_core_mask to within PKG */
if (chip_id == -1)
cpumask_and(mask, mask, cpu_cpu_mask(cpu));
@@ -1629,7 +1629,7 @@ void start_secondary(void *unused)
smp_store_cpu_info(cpu);
set_dec(tb_ticks_per_jiffy);
- rcu_cpu_starting(cpu);
+ rcutree_report_cpu_starting(cpu);
cpu_callin_map[cpu] = 1;
if (smp_ops->setup_cpu)
diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl
index 20e50586e8a2..7fab411378f2 100644
--- a/arch/powerpc/kernel/syscalls/syscall.tbl
+++ b/arch/powerpc/kernel/syscalls/syscall.tbl
@@ -294,7 +294,7 @@
233 32 fadvise64 sys_ppc32_fadvise64 compat_sys_ppc32_fadvise64
233 64 fadvise64 sys_fadvise64
234 nospu exit_group sys_exit_group
-235 nospu lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie
+235 nospu lookup_dcookie sys_ni_syscall
236 common epoll_create sys_epoll_create
237 common epoll_ctl sys_epoll_ctl
238 common epoll_wait sys_epoll_wait
@@ -539,3 +539,7 @@
450 nospu set_mempolicy_home_node sys_set_mempolicy_home_node
451 common cachestat sys_cachestat
452 common fchmodat2 sys_fchmodat2
+453 common map_shadow_stack sys_ni_syscall
+454 common futex_wake sys_futex_wake
+455 common futex_wait sys_futex_wait
+456 common futex_requeue sys_futex_requeue
diff --git a/arch/powerpc/kernel/trace/ftrace_entry.S b/arch/powerpc/kernel/trace/ftrace_entry.S
index 90701885762c..40677416d7b2 100644
--- a/arch/powerpc/kernel/trace/ftrace_entry.S
+++ b/arch/powerpc/kernel/trace/ftrace_entry.S
@@ -62,7 +62,7 @@
.endif
/* Save previous stack pointer (r1) */
- addi r8, r1, SWITCH_FRAME_SIZE
+ addi r8, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
PPC_STL r8, GPR1(r1)
.if \allregs == 1
@@ -182,7 +182,7 @@ ftrace_no_trace:
mflr r3
mtctr r3
REST_GPR(3, r1)
- addi r1, r1, SWITCH_FRAME_SIZE
+ addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
mtlr r0
bctr
#endif
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 64ff37721fd0..5ea2014aff90 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -157,7 +157,7 @@ static int die_owner = -1;
static unsigned int die_nest_count;
static int die_counter;
-extern void panic_flush_kmsg_start(void)
+void panic_flush_kmsg_start(void)
{
/*
* These are mostly taken from kernel/panic.c, but tries to do
@@ -170,7 +170,7 @@ extern void panic_flush_kmsg_start(void)
bust_spinlocks(1);
}
-extern void panic_flush_kmsg_end(void)
+void panic_flush_kmsg_end(void)
{
kmsg_dump(KMSG_DUMP_PANIC);
bust_spinlocks(0);
@@ -1164,6 +1164,7 @@ void emulate_single_step(struct pt_regs *regs)
__single_step_exception(regs);
}
+#ifdef CONFIG_PPC_FPU_REGS
static inline int __parse_fpscr(unsigned long fpscr)
{
int ret = FPE_FLTUNK;
@@ -1190,6 +1191,7 @@ static inline int __parse_fpscr(unsigned long fpscr)
return ret;
}
+#endif
static void parse_fpe(struct pt_regs *regs)
{
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S
index 4094e4c4c77a..80b3f6e476b6 100644
--- a/arch/powerpc/kernel/vector.S
+++ b/arch/powerpc/kernel/vector.S
@@ -33,6 +33,7 @@ _GLOBAL(store_vr_state)
mfvscr v0
li r4, VRSTATE_VSCR
stvx v0, r4, r3
+ lvx v0, 0, r3
blr
EXPORT_SYMBOL(store_vr_state)
@@ -109,6 +110,7 @@ _GLOBAL(save_altivec)
mfvscr v0
li r4,VRSTATE_VSCR
stvx v0,r4,r7
+ lvx v0,0,r7
blr
#ifdef CONFIG_VSX
diff --git a/arch/powerpc/kexec/core.c b/arch/powerpc/kexec/core.c
index de64c7962991..85846cadb9b5 100644
--- a/arch/powerpc/kexec/core.c
+++ b/arch/powerpc/kexec/core.c
@@ -74,6 +74,9 @@ void arch_crash_save_vmcoreinfo(void)
VMCOREINFO_STRUCT_SIZE(mmu_psize_def);
VMCOREINFO_OFFSET(mmu_psize_def, shift);
#endif
+ VMCOREINFO_SYMBOL(cur_cpu_spec);
+ VMCOREINFO_OFFSET(cpu_spec, mmu_features);
+ vmcoreinfo_append_str("NUMBER(RADIX_MMU)=%d\n", early_radix_enabled());
vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset());
}
@@ -109,7 +112,7 @@ void __init reserve_crashkernel(void)
total_mem_sz = memory_limit ? memory_limit : memblock_phys_mem_size();
/* use common parsing */
ret = parse_crashkernel(boot_command_line, total_mem_sz,
- &crash_size, &crash_base);
+ &crash_size, &crash_base, NULL, NULL);
if (ret == 0 && crash_size > 0) {
crashk_res.start = crash_base;
crashk_res.end = crash_base + crash_size - 1;
diff --git a/arch/powerpc/kexec/core_64.c b/arch/powerpc/kexec/core_64.c
index a79e28c91e2b..0bee7ca9a77c 100644
--- a/arch/powerpc/kexec/core_64.c
+++ b/arch/powerpc/kexec/core_64.c
@@ -379,8 +379,8 @@ void default_machine_kexec(struct kimage *image)
#ifdef CONFIG_PPC_64S_HASH_MMU
/* Values we need to export to the second kernel via the device tree. */
-static unsigned long htab_base;
-static unsigned long htab_size;
+static __be64 htab_base;
+static __be64 htab_size;
static struct property htab_base_prop = {
.name = "linux,htab-base",
diff --git a/arch/powerpc/kexec/file_load_64.c b/arch/powerpc/kexec/file_load_64.c
index a3de5369d22c..961a6dd67365 100644
--- a/arch/powerpc/kexec/file_load_64.c
+++ b/arch/powerpc/kexec/file_load_64.c
@@ -32,7 +32,7 @@
#include <asm/plpks.h>
struct umem_info {
- u64 *buf; /* data buffer for usable-memory property */
+ __be64 *buf; /* data buffer for usable-memory property */
u32 size; /* size allocated for the data buffer */
u32 max_entries; /* maximum no. of entries */
u32 idx; /* index of current entry */
@@ -443,10 +443,10 @@ static int locate_mem_hole_bottom_up_ppc64(struct kexec_buf *kbuf,
*
* Returns buffer on success, NULL on error.
*/
-static u64 *check_realloc_usable_mem(struct umem_info *um_info, int cnt)
+static __be64 *check_realloc_usable_mem(struct umem_info *um_info, int cnt)
{
u32 new_size;
- u64 *tbuf;
+ __be64 *tbuf;
if ((um_info->idx + cnt) <= um_info->max_entries)
return um_info->buf;
@@ -1138,11 +1138,15 @@ static int update_pci_dma_nodes(void *fdt, const char *dmapropname)
continue;
ret = copy_property(fdt, pci_offset, dn, "ibm,dma-window");
- if (ret < 0)
+ if (ret < 0) {
+ of_node_put(dn);
break;
+ }
ret = copy_property(fdt, pci_offset, dn, dmapropname);
- if (ret < 0)
+ if (ret < 0) {
+ of_node_put(dn);
break;
+ }
}
return ret;
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 5319d889b184..4bd9d1230869 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -87,8 +87,12 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \
book3s_hv_ras.o \
book3s_hv_builtin.o \
book3s_hv_p9_perf.o \
+ book3s_hv_nestedv2.o \
+ guest-state-buffer.o \
$(kvm-book3s_64-builtin-tm-objs-y) \
$(kvm-book3s_64-builtin-xics-objs-y)
+
+obj-$(CONFIG_GUEST_STATE_BUFFER_TEST) += test-guest-state-buffer.o
endif
kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 686d8d9eda3e..6cd20ab9e94e 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -565,7 +565,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
regs->msr = kvmppc_get_msr(vcpu);
regs->srr0 = kvmppc_get_srr0(vcpu);
regs->srr1 = kvmppc_get_srr1(vcpu);
- regs->pid = vcpu->arch.pid;
+ regs->pid = kvmppc_get_pid(vcpu);
regs->sprg0 = kvmppc_get_sprg0(vcpu);
regs->sprg1 = kvmppc_get_sprg1(vcpu);
regs->sprg2 = kvmppc_get_sprg2(vcpu);
@@ -636,17 +636,17 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
break;
case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
i = id - KVM_REG_PPC_FPR0;
- *val = get_reg_val(id, VCPU_FPR(vcpu, i));
+ *val = get_reg_val(id, kvmppc_get_fpr(vcpu, i));
break;
case KVM_REG_PPC_FPSCR:
- *val = get_reg_val(id, vcpu->arch.fp.fpscr);
+ *val = get_reg_val(id, kvmppc_get_fpscr(vcpu));
break;
#ifdef CONFIG_VSX
case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
if (cpu_has_feature(CPU_FTR_VSX)) {
i = id - KVM_REG_PPC_VSR0;
- val->vsxval[0] = vcpu->arch.fp.fpr[i][0];
- val->vsxval[1] = vcpu->arch.fp.fpr[i][1];
+ val->vsxval[0] = kvmppc_get_vsx_fpr(vcpu, i, 0);
+ val->vsxval[1] = kvmppc_get_vsx_fpr(vcpu, i, 1);
} else {
r = -ENXIO;
}
@@ -683,19 +683,19 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
*val = get_reg_val(id, vcpu->arch.fscr);
break;
case KVM_REG_PPC_TAR:
- *val = get_reg_val(id, vcpu->arch.tar);
+ *val = get_reg_val(id, kvmppc_get_tar(vcpu));
break;
case KVM_REG_PPC_EBBHR:
- *val = get_reg_val(id, vcpu->arch.ebbhr);
+ *val = get_reg_val(id, kvmppc_get_ebbhr(vcpu));
break;
case KVM_REG_PPC_EBBRR:
- *val = get_reg_val(id, vcpu->arch.ebbrr);
+ *val = get_reg_val(id, kvmppc_get_ebbrr(vcpu));
break;
case KVM_REG_PPC_BESCR:
- *val = get_reg_val(id, vcpu->arch.bescr);
+ *val = get_reg_val(id, kvmppc_get_bescr(vcpu));
break;
case KVM_REG_PPC_IC:
- *val = get_reg_val(id, vcpu->arch.ic);
+ *val = get_reg_val(id, kvmppc_get_ic(vcpu));
break;
default:
r = -EINVAL;
@@ -724,7 +724,7 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
break;
case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
i = id - KVM_REG_PPC_FPR0;
- VCPU_FPR(vcpu, i) = set_reg_val(id, *val);
+ kvmppc_set_fpr(vcpu, i, set_reg_val(id, *val));
break;
case KVM_REG_PPC_FPSCR:
vcpu->arch.fp.fpscr = set_reg_val(id, *val);
@@ -733,8 +733,8 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
if (cpu_has_feature(CPU_FTR_VSX)) {
i = id - KVM_REG_PPC_VSR0;
- vcpu->arch.fp.fpr[i][0] = val->vsxval[0];
- vcpu->arch.fp.fpr[i][1] = val->vsxval[1];
+ kvmppc_set_vsx_fpr(vcpu, i, 0, val->vsxval[0]);
+ kvmppc_set_vsx_fpr(vcpu, i, 1, val->vsxval[1]);
} else {
r = -ENXIO;
}
@@ -765,22 +765,22 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
break;
#endif /* CONFIG_KVM_XIVE */
case KVM_REG_PPC_FSCR:
- vcpu->arch.fscr = set_reg_val(id, *val);
+ kvmppc_set_fpscr(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_TAR:
- vcpu->arch.tar = set_reg_val(id, *val);
+ kvmppc_set_tar(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_EBBHR:
- vcpu->arch.ebbhr = set_reg_val(id, *val);
+ kvmppc_set_ebbhr(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_EBBRR:
- vcpu->arch.ebbrr = set_reg_val(id, *val);
+ kvmppc_set_ebbrr(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_BESCR:
- vcpu->arch.bescr = set_reg_val(id, *val);
+ kvmppc_set_bescr(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_IC:
- vcpu->arch.ic = set_reg_val(id, *val);
+ kvmppc_set_ic(vcpu, set_reg_val(id, *val));
break;
default:
r = -EINVAL;
diff --git a/arch/powerpc/kvm/book3s_64_entry.S b/arch/powerpc/kvm/book3s_64_entry.S
index 3b361af87313..a9ab92abffe8 100644
--- a/arch/powerpc/kvm/book3s_64_entry.S
+++ b/arch/powerpc/kvm/book3s_64_entry.S
@@ -19,7 +19,7 @@
/*
* This is a hcall, so register convention is as
- * Documentation/powerpc/papr_hcalls.rst.
+ * Documentation/arch/powerpc/papr_hcalls.rst.
*
* This may also be a syscall from PR-KVM userspace that is to be
* reflected to the PR guest kernel, so registers may be set up for
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index efd0ebf70a5e..2b1f0cdd8c18 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -28,6 +28,7 @@
#include <asm/pte-walk.h>
#include "book3s.h"
+#include "book3s_hv.h"
#include "trace_hv.h"
//#define DEBUG_RESIZE_HPT 1
@@ -120,7 +121,7 @@ void kvmppc_set_hpt(struct kvm *kvm, struct kvm_hpt_info *info)
kvm->arch.hpt = *info;
kvm->arch.sdr1 = __pa(info->virt) | (info->order - 18);
- pr_debug("KVM guest htab at %lx (order %ld), LPID %x\n",
+ pr_debug("KVM guest htab at %lx (order %ld), LPID %llx\n",
info->virt, (long)info->order, kvm->arch.lpid);
}
@@ -347,7 +348,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
unsigned long v, orig_v, gr;
__be64 *hptep;
long int index;
- int virtmode = vcpu->arch.shregs.msr & (data ? MSR_DR : MSR_IR);
+ int virtmode = __kvmppc_get_msr_hv(vcpu) & (data ? MSR_DR : MSR_IR);
if (kvm_is_radix(vcpu->kvm))
return kvmppc_mmu_radix_xlate(vcpu, eaddr, gpte, data, iswrite);
@@ -385,7 +386,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
/* Get PP bits and key for permission check */
pp = gr & (HPTE_R_PP0 | HPTE_R_PP);
- key = (vcpu->arch.shregs.msr & MSR_PR) ? SLB_VSID_KP : SLB_VSID_KS;
+ key = (__kvmppc_get_msr_hv(vcpu) & MSR_PR) ? SLB_VSID_KP : SLB_VSID_KS;
key &= slb_v;
/* Calculate permissions */
diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c
index 572707858d65..175a8eb2681f 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_radix.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c
@@ -15,6 +15,7 @@
#include <asm/kvm_ppc.h>
#include <asm/kvm_book3s.h>
+#include "book3s_hv.h"
#include <asm/page.h>
#include <asm/mmu.h>
#include <asm/pgalloc.h>
@@ -96,7 +97,7 @@ static long kvmhv_copy_tofrom_guest_radix(struct kvm_vcpu *vcpu, gva_t eaddr,
void *to, void *from, unsigned long n)
{
int lpid = vcpu->kvm->arch.lpid;
- int pid = vcpu->arch.pid;
+ int pid = kvmppc_get_pid(vcpu);
/* This would cause a data segment intr so don't allow the access */
if (eaddr & (0x3FFUL << 52))
@@ -270,7 +271,7 @@ int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
/* Work out effective PID */
switch (eaddr >> 62) {
case 0:
- pid = vcpu->arch.pid;
+ pid = kvmppc_get_pid(vcpu);
break;
case 3:
pid = 0;
@@ -294,9 +295,9 @@ int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
} else {
if (!(pte & _PAGE_PRIVILEGED)) {
/* Check AMR/IAMR to see if strict mode is in force */
- if (vcpu->arch.amr & (1ul << 62))
+ if (kvmppc_get_amr_hv(vcpu) & (1ul << 62))
gpte->may_read = 0;
- if (vcpu->arch.amr & (1ul << 63))
+ if (kvmppc_get_amr_hv(vcpu) & (1ul << 63))
gpte->may_write = 0;
if (vcpu->arch.iamr & (1ul << 62))
gpte->may_execute = 0;
@@ -307,7 +308,7 @@ int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
}
void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr,
- unsigned int pshift, unsigned int lpid)
+ unsigned int pshift, u64 lpid)
{
unsigned long psize = PAGE_SIZE;
int psi;
@@ -344,7 +345,7 @@ void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr,
pr_err("KVM: TLB page invalidation hcall failed, rc=%ld\n", rc);
}
-static void kvmppc_radix_flush_pwc(struct kvm *kvm, unsigned int lpid)
+static void kvmppc_radix_flush_pwc(struct kvm *kvm, u64 lpid)
{
long rc;
@@ -417,7 +418,7 @@ static void kvmppc_pmd_free(pmd_t *pmdp)
void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, unsigned long gpa,
unsigned int shift,
const struct kvm_memory_slot *memslot,
- unsigned int lpid)
+ u64 lpid)
{
unsigned long old;
@@ -468,7 +469,7 @@ void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, unsigned long gpa,
* (or 4kB) mappings (of sub-pages of the same 2MB page).
*/
static void kvmppc_unmap_free_pte(struct kvm *kvm, pte_t *pte, bool full,
- unsigned int lpid)
+ u64 lpid)
{
if (full) {
memset(pte, 0, sizeof(long) << RADIX_PTE_INDEX_SIZE);
@@ -489,7 +490,7 @@ static void kvmppc_unmap_free_pte(struct kvm *kvm, pte_t *pte, bool full,
}
static void kvmppc_unmap_free_pmd(struct kvm *kvm, pmd_t *pmd, bool full,
- unsigned int lpid)
+ u64 lpid)
{
unsigned long im;
pmd_t *p = pmd;
@@ -518,7 +519,7 @@ static void kvmppc_unmap_free_pmd(struct kvm *kvm, pmd_t *pmd, bool full,
}
static void kvmppc_unmap_free_pud(struct kvm *kvm, pud_t *pud,
- unsigned int lpid)
+ u64 lpid)
{
unsigned long iu;
pud_t *p = pud;
@@ -539,7 +540,7 @@ static void kvmppc_unmap_free_pud(struct kvm *kvm, pud_t *pud,
pud_free(kvm->mm, pud);
}
-void kvmppc_free_pgtable_radix(struct kvm *kvm, pgd_t *pgd, unsigned int lpid)
+void kvmppc_free_pgtable_radix(struct kvm *kvm, pgd_t *pgd, u64 lpid)
{
unsigned long ig;
@@ -566,7 +567,7 @@ void kvmppc_free_radix(struct kvm *kvm)
}
static void kvmppc_unmap_free_pmd_entry_table(struct kvm *kvm, pmd_t *pmd,
- unsigned long gpa, unsigned int lpid)
+ unsigned long gpa, u64 lpid)
{
pte_t *pte = pte_offset_kernel(pmd, 0);
@@ -582,7 +583,7 @@ static void kvmppc_unmap_free_pmd_entry_table(struct kvm *kvm, pmd_t *pmd,
}
static void kvmppc_unmap_free_pud_entry_table(struct kvm *kvm, pud_t *pud,
- unsigned long gpa, unsigned int lpid)
+ unsigned long gpa, u64 lpid)
{
pmd_t *pmd = pmd_offset(pud, 0);
@@ -608,7 +609,7 @@ static void kvmppc_unmap_free_pud_entry_table(struct kvm *kvm, pud_t *pud,
int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte,
unsigned long gpa, unsigned int level,
- unsigned long mmu_seq, unsigned int lpid,
+ unsigned long mmu_seq, u64 lpid,
unsigned long *rmapp, struct rmap_nested **n_rmap)
{
pgd_t *pgd;
@@ -785,7 +786,7 @@ int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte,
}
bool kvmppc_hv_handle_set_rc(struct kvm *kvm, bool nested, bool writing,
- unsigned long gpa, unsigned int lpid)
+ unsigned long gpa, u64 lpid)
{
unsigned long pgflags;
unsigned int shift;
diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c
index 93b695b289e9..14c6d7e318da 100644
--- a/arch/powerpc/kvm/book3s_64_vio.c
+++ b/arch/powerpc/kvm/book3s_64_vio.c
@@ -77,8 +77,8 @@ static void kvm_spapr_tce_liobn_put(struct kref *kref)
call_rcu(&stit->rcu, kvm_spapr_tce_iommu_table_free);
}
-extern void kvm_spapr_tce_release_iommu_group(struct kvm *kvm,
- struct iommu_group *grp)
+void kvm_spapr_tce_release_iommu_group(struct kvm *kvm,
+ struct iommu_group *grp)
{
int i;
struct kvmppc_spapr_tce_table *stt;
@@ -105,8 +105,8 @@ extern void kvm_spapr_tce_release_iommu_group(struct kvm *kvm,
rcu_read_unlock();
}
-extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
- struct iommu_group *grp)
+long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
+ struct iommu_group *grp)
{
struct kvmppc_spapr_tce_table *stt = NULL;
bool found = false;
@@ -786,12 +786,12 @@ long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
idx = (ioba >> stt->page_shift) - stt->offset;
page = stt->pages[idx / TCES_PER_PAGE];
if (!page) {
- vcpu->arch.regs.gpr[4] = 0;
+ kvmppc_set_gpr(vcpu, 4, 0);
return H_SUCCESS;
}
tbl = (u64 *)page_address(page);
- vcpu->arch.regs.gpr[4] = tbl[idx % TCES_PER_PAGE];
+ kvmppc_set_gpr(vcpu, 4, tbl[idx % TCES_PER_PAGE]);
return H_SUCCESS;
}
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 130bafdb1430..1ed6ec140701 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -393,7 +393,7 @@ static void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 pvr)
static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
{
- unsigned long host_pcr_bit = 0, guest_pcr_bit = 0;
+ unsigned long host_pcr_bit = 0, guest_pcr_bit = 0, cap = 0;
struct kvmppc_vcore *vc = vcpu->arch.vcore;
/* We can (emulate) our own architecture version and anything older */
@@ -424,9 +424,11 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
break;
case PVR_ARCH_300:
guest_pcr_bit = PCR_ARCH_300;
+ cap = H_GUEST_CAP_POWER9;
break;
case PVR_ARCH_31:
guest_pcr_bit = PCR_ARCH_31;
+ cap = H_GUEST_CAP_POWER10;
break;
default:
return -EINVAL;
@@ -437,8 +439,14 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
if (guest_pcr_bit > host_pcr_bit)
return -EINVAL;
+ if (kvmhv_on_pseries() && kvmhv_is_nestedv2()) {
+ if (!(cap & nested_capabilities))
+ return -EINVAL;
+ }
+
spin_lock(&vc->lock);
vc->arch_compat = arch_compat;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LOGICAL_PVR);
/*
* Set all PCR bits for which guest_pcr_bit <= bit < host_pcr_bit
* Also set all reserved PCR bits
@@ -794,7 +802,7 @@ static void kvmppc_update_vpa_dispatch(struct kvm_vcpu *vcpu,
vpa->enqueue_dispatch_tb = cpu_to_be64(be64_to_cpu(vpa->enqueue_dispatch_tb) + stolen);
- __kvmppc_create_dtl_entry(vcpu, vpa, vc->pcpu, now + vc->tb_offset, stolen);
+ __kvmppc_create_dtl_entry(vcpu, vpa, vc->pcpu, now + kvmppc_get_tb_offset(vcpu), stolen);
vcpu->arch.vpa.dirty = true;
}
@@ -845,9 +853,9 @@ static bool kvmppc_doorbell_pending(struct kvm_vcpu *vcpu)
static bool kvmppc_power8_compatible(struct kvm_vcpu *vcpu)
{
- if (vcpu->arch.vcore->arch_compat >= PVR_ARCH_207)
+ if (kvmppc_get_arch_compat(vcpu) >= PVR_ARCH_207)
return true;
- if ((!vcpu->arch.vcore->arch_compat) &&
+ if ((!kvmppc_get_arch_compat(vcpu)) &&
cpu_has_feature(CPU_FTR_ARCH_207S))
return true;
return false;
@@ -868,7 +876,7 @@ static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags,
/* Guests can't breakpoint the hypervisor */
if ((value1 & CIABR_PRIV) == CIABR_PRIV_HYPER)
return H_P3;
- vcpu->arch.ciabr = value1;
+ kvmppc_set_ciabr_hv(vcpu, value1);
return H_SUCCESS;
case H_SET_MODE_RESOURCE_SET_DAWR0:
if (!kvmppc_power8_compatible(vcpu))
@@ -879,8 +887,8 @@ static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags,
return H_UNSUPPORTED_FLAG_START;
if (value2 & DABRX_HYP)
return H_P4;
- vcpu->arch.dawr0 = value1;
- vcpu->arch.dawrx0 = value2;
+ kvmppc_set_dawr0_hv(vcpu, value1);
+ kvmppc_set_dawrx0_hv(vcpu, value2);
return H_SUCCESS;
case H_SET_MODE_RESOURCE_SET_DAWR1:
if (!kvmppc_power8_compatible(vcpu))
@@ -895,8 +903,8 @@ static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags,
return H_UNSUPPORTED_FLAG_START;
if (value2 & DABRX_HYP)
return H_P4;
- vcpu->arch.dawr1 = value1;
- vcpu->arch.dawrx1 = value2;
+ kvmppc_set_dawr1_hv(vcpu, value1);
+ kvmppc_set_dawrx1_hv(vcpu, value2);
return H_SUCCESS;
case H_SET_MODE_RESOURCE_ADDR_TRANS_MODE:
/*
@@ -1267,10 +1275,14 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
return RESUME_HOST;
break;
#endif
- case H_RANDOM:
- if (!arch_get_random_seed_longs(&vcpu->arch.regs.gpr[4], 1))
+ case H_RANDOM: {
+ unsigned long rand;
+
+ if (!arch_get_random_seed_longs(&rand, 1))
ret = H_HARDWARE;
+ kvmppc_set_gpr(vcpu, 4, rand);
break;
+ }
case H_RPT_INVALIDATE:
ret = kvmppc_h_rpt_invalidate(vcpu, kvmppc_get_gpr(vcpu, 4),
kvmppc_get_gpr(vcpu, 5),
@@ -1370,7 +1382,7 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
*/
static void kvmppc_cede(struct kvm_vcpu *vcpu)
{
- vcpu->arch.shregs.msr |= MSR_EE;
+ __kvmppc_set_msr_hv(vcpu, __kvmppc_get_msr_hv(vcpu) | MSR_EE);
vcpu->arch.ceded = 1;
smp_mb();
if (vcpu->arch.prodded) {
@@ -1544,7 +1556,7 @@ static int kvmppc_pmu_unavailable(struct kvm_vcpu *vcpu)
if (!(vcpu->arch.hfscr_permitted & HFSCR_PM))
return EMULATE_FAIL;
- vcpu->arch.hfscr |= HFSCR_PM;
+ kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) | HFSCR_PM);
return RESUME_GUEST;
}
@@ -1554,7 +1566,7 @@ static int kvmppc_ebb_unavailable(struct kvm_vcpu *vcpu)
if (!(vcpu->arch.hfscr_permitted & HFSCR_EBB))
return EMULATE_FAIL;
- vcpu->arch.hfscr |= HFSCR_EBB;
+ kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) | HFSCR_EBB);
return RESUME_GUEST;
}
@@ -1564,7 +1576,7 @@ static int kvmppc_tm_unavailable(struct kvm_vcpu *vcpu)
if (!(vcpu->arch.hfscr_permitted & HFSCR_TM))
return EMULATE_FAIL;
- vcpu->arch.hfscr |= HFSCR_TM;
+ kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) | HFSCR_TM);
return RESUME_GUEST;
}
@@ -1585,7 +1597,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
* That can happen due to a bug, or due to a machine check
* occurring at just the wrong time.
*/
- if (vcpu->arch.shregs.msr & MSR_HV) {
+ if (__kvmppc_get_msr_hv(vcpu) & MSR_HV) {
printk(KERN_EMERG "KVM trap in HV mode!\n");
printk(KERN_EMERG "trap=0x%x | pc=0x%lx | msr=0x%llx\n",
vcpu->arch.trap, kvmppc_get_pc(vcpu),
@@ -1636,7 +1648,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
* so that it knows that the machine check occurred.
*/
if (!vcpu->kvm->arch.fwnmi_enabled) {
- ulong flags = (vcpu->arch.shregs.msr & 0x083c0000) |
+ ulong flags = (__kvmppc_get_msr_hv(vcpu) & 0x083c0000) |
(kvmppc_get_msr(vcpu) & SRR1_PREFIXED);
kvmppc_core_queue_machine_check(vcpu, flags);
r = RESUME_GUEST;
@@ -1666,7 +1678,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
* as a result of a hypervisor emulation interrupt
* (e40) getting turned into a 700 by BML RTAS.
*/
- flags = (vcpu->arch.shregs.msr & 0x1f0000ull) |
+ flags = (__kvmppc_get_msr_hv(vcpu) & 0x1f0000ull) |
(kvmppc_get_msr(vcpu) & SRR1_PREFIXED);
kvmppc_core_queue_program(vcpu, flags);
r = RESUME_GUEST;
@@ -1676,7 +1688,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
{
int i;
- if (unlikely(vcpu->arch.shregs.msr & MSR_PR)) {
+ if (unlikely(__kvmppc_get_msr_hv(vcpu) & MSR_PR)) {
/*
* Guest userspace executed sc 1. This can only be
* reached by the P9 path because the old path
@@ -1754,7 +1766,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
break;
}
- if (!(vcpu->arch.shregs.msr & MSR_DR))
+ if (!(__kvmppc_get_msr_hv(vcpu) & MSR_DR))
vsid = vcpu->kvm->arch.vrma_slb_v;
else
vsid = vcpu->arch.fault_gpa;
@@ -1778,7 +1790,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
long err;
vcpu->arch.fault_dar = kvmppc_get_pc(vcpu);
- vcpu->arch.fault_dsisr = vcpu->arch.shregs.msr &
+ vcpu->arch.fault_dsisr = __kvmppc_get_msr_hv(vcpu) &
DSISR_SRR1_MATCH_64S;
if (kvm_is_radix(vcpu->kvm) || !cpu_has_feature(CPU_FTR_ARCH_300)) {
/*
@@ -1787,7 +1799,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
* hash fault handling below is v3 only (it uses ASDR
* via fault_gpa).
*/
- if (vcpu->arch.shregs.msr & HSRR1_HISI_WRITE)
+ if (__kvmppc_get_msr_hv(vcpu) & HSRR1_HISI_WRITE)
vcpu->arch.fault_dsisr |= DSISR_ISSTORE;
r = RESUME_PAGE_FAULT;
break;
@@ -1801,7 +1813,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
break;
}
- if (!(vcpu->arch.shregs.msr & MSR_IR))
+ if (!(__kvmppc_get_msr_hv(vcpu) & MSR_IR))
vsid = vcpu->kvm->arch.vrma_slb_v;
else
vsid = vcpu->arch.fault_gpa;
@@ -1863,7 +1875,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
* Otherwise, we just generate a program interrupt to the guest.
*/
case BOOK3S_INTERRUPT_H_FAC_UNAVAIL: {
- u64 cause = vcpu->arch.hfscr >> 56;
+ u64 cause = kvmppc_get_hfscr_hv(vcpu) >> 56;
r = EMULATE_FAIL;
if (cpu_has_feature(CPU_FTR_ARCH_300)) {
@@ -1891,7 +1903,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
kvmppc_dump_regs(vcpu);
printk(KERN_EMERG "trap=0x%x | pc=0x%lx | msr=0x%llx\n",
vcpu->arch.trap, kvmppc_get_pc(vcpu),
- vcpu->arch.shregs.msr);
+ __kvmppc_get_msr_hv(vcpu));
run->hw.hardware_exit_reason = vcpu->arch.trap;
r = RESUME_HOST;
break;
@@ -1915,11 +1927,11 @@ static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu)
* That can happen due to a bug, or due to a machine check
* occurring at just the wrong time.
*/
- if (vcpu->arch.shregs.msr & MSR_HV) {
+ if (__kvmppc_get_msr_hv(vcpu) & MSR_HV) {
pr_emerg("KVM trap in HV mode while nested!\n");
pr_emerg("trap=0x%x | pc=0x%lx | msr=0x%llx\n",
vcpu->arch.trap, kvmppc_get_pc(vcpu),
- vcpu->arch.shregs.msr);
+ __kvmppc_get_msr_hv(vcpu));
kvmppc_dump_regs(vcpu);
return RESUME_HOST;
}
@@ -1976,7 +1988,7 @@ static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu)
vcpu->arch.fault_dar = kvmppc_get_pc(vcpu);
vcpu->arch.fault_dsisr = kvmppc_get_msr(vcpu) &
DSISR_SRR1_MATCH_64S;
- if (vcpu->arch.shregs.msr & HSRR1_HISI_WRITE)
+ if (__kvmppc_get_msr_hv(vcpu) & HSRR1_HISI_WRITE)
vcpu->arch.fault_dsisr |= DSISR_ISSTORE;
srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
r = kvmhv_nested_page_fault(vcpu);
@@ -2183,6 +2195,7 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr,
}
vc->lpcr = new_lpcr;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LPCR);
spin_unlock(&vc->lock);
}
@@ -2207,64 +2220,64 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
*val = get_reg_val(id, vcpu->arch.dabrx);
break;
case KVM_REG_PPC_DSCR:
- *val = get_reg_val(id, vcpu->arch.dscr);
+ *val = get_reg_val(id, kvmppc_get_dscr_hv(vcpu));
break;
case KVM_REG_PPC_PURR:
- *val = get_reg_val(id, vcpu->arch.purr);
+ *val = get_reg_val(id, kvmppc_get_purr_hv(vcpu));
break;
case KVM_REG_PPC_SPURR:
- *val = get_reg_val(id, vcpu->arch.spurr);
+ *val = get_reg_val(id, kvmppc_get_spurr_hv(vcpu));
break;
case KVM_REG_PPC_AMR:
- *val = get_reg_val(id, vcpu->arch.amr);
+ *val = get_reg_val(id, kvmppc_get_amr_hv(vcpu));
break;
case KVM_REG_PPC_UAMOR:
- *val = get_reg_val(id, vcpu->arch.uamor);
+ *val = get_reg_val(id, kvmppc_get_uamor_hv(vcpu));
break;
case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCR1:
i = id - KVM_REG_PPC_MMCR0;
- *val = get_reg_val(id, vcpu->arch.mmcr[i]);
+ *val = get_reg_val(id, kvmppc_get_mmcr_hv(vcpu, i));
break;
case KVM_REG_PPC_MMCR2:
- *val = get_reg_val(id, vcpu->arch.mmcr[2]);
+ *val = get_reg_val(id, kvmppc_get_mmcr_hv(vcpu, 2));
break;
case KVM_REG_PPC_MMCRA:
- *val = get_reg_val(id, vcpu->arch.mmcra);
+ *val = get_reg_val(id, kvmppc_get_mmcra_hv(vcpu));
break;
case KVM_REG_PPC_MMCRS:
*val = get_reg_val(id, vcpu->arch.mmcrs);
break;
case KVM_REG_PPC_MMCR3:
- *val = get_reg_val(id, vcpu->arch.mmcr[3]);
+ *val = get_reg_val(id, kvmppc_get_mmcr_hv(vcpu, 3));
break;
case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8:
i = id - KVM_REG_PPC_PMC1;
- *val = get_reg_val(id, vcpu->arch.pmc[i]);
+ *val = get_reg_val(id, kvmppc_get_pmc_hv(vcpu, i));
break;
case KVM_REG_PPC_SPMC1 ... KVM_REG_PPC_SPMC2:
i = id - KVM_REG_PPC_SPMC1;
*val = get_reg_val(id, vcpu->arch.spmc[i]);
break;
case KVM_REG_PPC_SIAR:
- *val = get_reg_val(id, vcpu->arch.siar);
+ *val = get_reg_val(id, kvmppc_get_siar_hv(vcpu));
break;
case KVM_REG_PPC_SDAR:
- *val = get_reg_val(id, vcpu->arch.sdar);
+ *val = get_reg_val(id, kvmppc_get_siar_hv(vcpu));
break;
case KVM_REG_PPC_SIER:
- *val = get_reg_val(id, vcpu->arch.sier[0]);
+ *val = get_reg_val(id, kvmppc_get_sier_hv(vcpu, 0));
break;
case KVM_REG_PPC_SIER2:
- *val = get_reg_val(id, vcpu->arch.sier[1]);
+ *val = get_reg_val(id, kvmppc_get_sier_hv(vcpu, 1));
break;
case KVM_REG_PPC_SIER3:
- *val = get_reg_val(id, vcpu->arch.sier[2]);
+ *val = get_reg_val(id, kvmppc_get_sier_hv(vcpu, 2));
break;
case KVM_REG_PPC_IAMR:
- *val = get_reg_val(id, vcpu->arch.iamr);
+ *val = get_reg_val(id, kvmppc_get_iamr_hv(vcpu));
break;
case KVM_REG_PPC_PSPB:
- *val = get_reg_val(id, vcpu->arch.pspb);
+ *val = get_reg_val(id, kvmppc_get_pspb_hv(vcpu));
break;
case KVM_REG_PPC_DPDES:
/*
@@ -2279,22 +2292,22 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
*val = get_reg_val(id, vcpu->arch.vcore->dpdes);
break;
case KVM_REG_PPC_VTB:
- *val = get_reg_val(id, vcpu->arch.vcore->vtb);
+ *val = get_reg_val(id, kvmppc_get_vtb(vcpu));
break;
case KVM_REG_PPC_DAWR:
- *val = get_reg_val(id, vcpu->arch.dawr0);
+ *val = get_reg_val(id, kvmppc_get_dawr0_hv(vcpu));
break;
case KVM_REG_PPC_DAWRX:
- *val = get_reg_val(id, vcpu->arch.dawrx0);
+ *val = get_reg_val(id, kvmppc_get_dawrx0_hv(vcpu));
break;
case KVM_REG_PPC_DAWR1:
- *val = get_reg_val(id, vcpu->arch.dawr1);
+ *val = get_reg_val(id, kvmppc_get_dawr1_hv(vcpu));
break;
case KVM_REG_PPC_DAWRX1:
- *val = get_reg_val(id, vcpu->arch.dawrx1);
+ *val = get_reg_val(id, kvmppc_get_dawrx1_hv(vcpu));
break;
case KVM_REG_PPC_CIABR:
- *val = get_reg_val(id, vcpu->arch.ciabr);
+ *val = get_reg_val(id, kvmppc_get_ciabr_hv(vcpu));
break;
case KVM_REG_PPC_CSIGR:
*val = get_reg_val(id, vcpu->arch.csigr);
@@ -2306,13 +2319,13 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
*val = get_reg_val(id, vcpu->arch.tcscr);
break;
case KVM_REG_PPC_PID:
- *val = get_reg_val(id, vcpu->arch.pid);
+ *val = get_reg_val(id, kvmppc_get_pid(vcpu));
break;
case KVM_REG_PPC_ACOP:
*val = get_reg_val(id, vcpu->arch.acop);
break;
case KVM_REG_PPC_WORT:
- *val = get_reg_val(id, vcpu->arch.wort);
+ *val = get_reg_val(id, kvmppc_get_wort_hv(vcpu));
break;
case KVM_REG_PPC_TIDR:
*val = get_reg_val(id, vcpu->arch.tid);
@@ -2338,14 +2351,14 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
spin_unlock(&vcpu->arch.vpa_update_lock);
break;
case KVM_REG_PPC_TB_OFFSET:
- *val = get_reg_val(id, vcpu->arch.vcore->tb_offset);
+ *val = get_reg_val(id, kvmppc_get_tb_offset(vcpu));
break;
case KVM_REG_PPC_LPCR:
case KVM_REG_PPC_LPCR_64:
- *val = get_reg_val(id, vcpu->arch.vcore->lpcr);
+ *val = get_reg_val(id, kvmppc_get_lpcr(vcpu));
break;
case KVM_REG_PPC_PPR:
- *val = get_reg_val(id, vcpu->arch.ppr);
+ *val = get_reg_val(id, kvmppc_get_ppr_hv(vcpu));
break;
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
case KVM_REG_PPC_TFHAR:
@@ -2414,10 +2427,10 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
break;
#endif
case KVM_REG_PPC_ARCH_COMPAT:
- *val = get_reg_val(id, vcpu->arch.vcore->arch_compat);
+ *val = get_reg_val(id, kvmppc_get_arch_compat(vcpu));
break;
case KVM_REG_PPC_DEC_EXPIRY:
- *val = get_reg_val(id, vcpu->arch.dec_expires);
+ *val = get_reg_val(id, kvmppc_get_dec_expires(vcpu));
break;
case KVM_REG_PPC_ONLINE:
*val = get_reg_val(id, vcpu->arch.online);
@@ -2425,6 +2438,9 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_PTCR:
*val = get_reg_val(id, vcpu->kvm->arch.l1_ptcr);
break;
+ case KVM_REG_PPC_FSCR:
+ *val = get_reg_val(id, kvmppc_get_fscr_hv(vcpu));
+ break;
default:
r = -EINVAL;
break;
@@ -2453,29 +2469,29 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
vcpu->arch.dabrx = set_reg_val(id, *val) & ~DABRX_HYP;
break;
case KVM_REG_PPC_DSCR:
- vcpu->arch.dscr = set_reg_val(id, *val);
+ kvmppc_set_dscr_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_PURR:
- vcpu->arch.purr = set_reg_val(id, *val);
+ kvmppc_set_purr_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_SPURR:
- vcpu->arch.spurr = set_reg_val(id, *val);
+ kvmppc_set_spurr_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_AMR:
- vcpu->arch.amr = set_reg_val(id, *val);
+ kvmppc_set_amr_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_UAMOR:
- vcpu->arch.uamor = set_reg_val(id, *val);
+ kvmppc_set_uamor_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCR1:
i = id - KVM_REG_PPC_MMCR0;
- vcpu->arch.mmcr[i] = set_reg_val(id, *val);
+ kvmppc_set_mmcr_hv(vcpu, i, set_reg_val(id, *val));
break;
case KVM_REG_PPC_MMCR2:
- vcpu->arch.mmcr[2] = set_reg_val(id, *val);
+ kvmppc_set_mmcr_hv(vcpu, 2, set_reg_val(id, *val));
break;
case KVM_REG_PPC_MMCRA:
- vcpu->arch.mmcra = set_reg_val(id, *val);
+ kvmppc_set_mmcra_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_MMCRS:
vcpu->arch.mmcrs = set_reg_val(id, *val);
@@ -2485,32 +2501,32 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
break;
case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8:
i = id - KVM_REG_PPC_PMC1;
- vcpu->arch.pmc[i] = set_reg_val(id, *val);
+ kvmppc_set_pmc_hv(vcpu, i, set_reg_val(id, *val));
break;
case KVM_REG_PPC_SPMC1 ... KVM_REG_PPC_SPMC2:
i = id - KVM_REG_PPC_SPMC1;
vcpu->arch.spmc[i] = set_reg_val(id, *val);
break;
case KVM_REG_PPC_SIAR:
- vcpu->arch.siar = set_reg_val(id, *val);
+ kvmppc_set_siar_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_SDAR:
- vcpu->arch.sdar = set_reg_val(id, *val);
+ kvmppc_set_sdar_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_SIER:
- vcpu->arch.sier[0] = set_reg_val(id, *val);
+ kvmppc_set_sier_hv(vcpu, 0, set_reg_val(id, *val));
break;
case KVM_REG_PPC_SIER2:
- vcpu->arch.sier[1] = set_reg_val(id, *val);
+ kvmppc_set_sier_hv(vcpu, 1, set_reg_val(id, *val));
break;
case KVM_REG_PPC_SIER3:
- vcpu->arch.sier[2] = set_reg_val(id, *val);
+ kvmppc_set_sier_hv(vcpu, 2, set_reg_val(id, *val));
break;
case KVM_REG_PPC_IAMR:
- vcpu->arch.iamr = set_reg_val(id, *val);
+ kvmppc_set_iamr_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_PSPB:
- vcpu->arch.pspb = set_reg_val(id, *val);
+ kvmppc_set_pspb_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_DPDES:
if (cpu_has_feature(CPU_FTR_ARCH_300))
@@ -2519,25 +2535,25 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
vcpu->arch.vcore->dpdes = set_reg_val(id, *val);
break;
case KVM_REG_PPC_VTB:
- vcpu->arch.vcore->vtb = set_reg_val(id, *val);
+ kvmppc_set_vtb(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_DAWR:
- vcpu->arch.dawr0 = set_reg_val(id, *val);
+ kvmppc_set_dawr0_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_DAWRX:
- vcpu->arch.dawrx0 = set_reg_val(id, *val) & ~DAWRX_HYP;
+ kvmppc_set_dawrx0_hv(vcpu, set_reg_val(id, *val) & ~DAWRX_HYP);
break;
case KVM_REG_PPC_DAWR1:
- vcpu->arch.dawr1 = set_reg_val(id, *val);
+ kvmppc_set_dawr1_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_DAWRX1:
- vcpu->arch.dawrx1 = set_reg_val(id, *val) & ~DAWRX_HYP;
+ kvmppc_set_dawrx1_hv(vcpu, set_reg_val(id, *val) & ~DAWRX_HYP);
break;
case KVM_REG_PPC_CIABR:
- vcpu->arch.ciabr = set_reg_val(id, *val);
+ kvmppc_set_ciabr_hv(vcpu, set_reg_val(id, *val));
/* Don't allow setting breakpoints in hypervisor code */
- if ((vcpu->arch.ciabr & CIABR_PRIV) == CIABR_PRIV_HYPER)
- vcpu->arch.ciabr &= ~CIABR_PRIV; /* disable */
+ if ((kvmppc_get_ciabr_hv(vcpu) & CIABR_PRIV) == CIABR_PRIV_HYPER)
+ kvmppc_set_ciabr_hv(vcpu, kvmppc_get_ciabr_hv(vcpu) & ~CIABR_PRIV);
break;
case KVM_REG_PPC_CSIGR:
vcpu->arch.csigr = set_reg_val(id, *val);
@@ -2549,13 +2565,13 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
vcpu->arch.tcscr = set_reg_val(id, *val);
break;
case KVM_REG_PPC_PID:
- vcpu->arch.pid = set_reg_val(id, *val);
+ kvmppc_set_pid(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_ACOP:
vcpu->arch.acop = set_reg_val(id, *val);
break;
case KVM_REG_PPC_WORT:
- vcpu->arch.wort = set_reg_val(id, *val);
+ kvmppc_set_wort_hv(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_TIDR:
vcpu->arch.tid = set_reg_val(id, *val);
@@ -2602,10 +2618,11 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
* decrementer, which is better than a large one that
* causes a hang.
*/
- if (!vcpu->arch.dec_expires && tb_offset)
- vcpu->arch.dec_expires = get_tb() + tb_offset;
+ kvmppc_set_tb_offset(vcpu, tb_offset);
+ if (!kvmppc_get_dec_expires(vcpu) && tb_offset)
+ kvmppc_set_dec_expires(vcpu, get_tb() + tb_offset);
- vcpu->arch.vcore->tb_offset = tb_offset;
+ kvmppc_set_tb_offset(vcpu, tb_offset);
break;
}
case KVM_REG_PPC_LPCR:
@@ -2615,7 +2632,7 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), false);
break;
case KVM_REG_PPC_PPR:
- vcpu->arch.ppr = set_reg_val(id, *val);
+ kvmppc_set_ppr_hv(vcpu, set_reg_val(id, *val));
break;
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
case KVM_REG_PPC_TFHAR:
@@ -2686,7 +2703,7 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
r = kvmppc_set_arch_compat(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_DEC_EXPIRY:
- vcpu->arch.dec_expires = set_reg_val(id, *val);
+ kvmppc_set_dec_expires(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_ONLINE:
i = set_reg_val(id, *val);
@@ -2699,6 +2716,9 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_PTCR:
vcpu->kvm->arch.l1_ptcr = set_reg_val(id, *val);
break;
+ case KVM_REG_PPC_FSCR:
+ kvmppc_set_fscr_hv(vcpu, set_reg_val(id, *val));
+ break;
default:
r = -EINVAL;
break;
@@ -2916,19 +2936,26 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu)
vcpu->arch.shared_big_endian = false;
#endif
#endif
- vcpu->arch.mmcr[0] = MMCR0_FC;
+
+ if (kvmhv_is_nestedv2()) {
+ err = kvmhv_nestedv2_vcpu_create(vcpu, &vcpu->arch.nestedv2_io);
+ if (err < 0)
+ return err;
+ }
+
+ kvmppc_set_mmcr_hv(vcpu, 0, MMCR0_FC);
if (cpu_has_feature(CPU_FTR_ARCH_31)) {
- vcpu->arch.mmcr[0] |= MMCR0_PMCCEXT;
- vcpu->arch.mmcra = MMCRA_BHRB_DISABLE;
+ kvmppc_set_mmcr_hv(vcpu, 0, kvmppc_get_mmcr_hv(vcpu, 0) | MMCR0_PMCCEXT);
+ kvmppc_set_mmcra_hv(vcpu, MMCRA_BHRB_DISABLE);
}
- vcpu->arch.ctrl = CTRL_RUNLATCH;
+ kvmppc_set_ctrl_hv(vcpu, CTRL_RUNLATCH);
/* default to host PVR, since we can't spoof it */
kvmppc_set_pvr_hv(vcpu, mfspr(SPRN_PVR));
spin_lock_init(&vcpu->arch.vpa_update_lock);
spin_lock_init(&vcpu->arch.tbacct_lock);
vcpu->arch.busy_preempt = TB_NIL;
- vcpu->arch.shregs.msr = MSR_ME;
+ __kvmppc_set_msr_hv(vcpu, MSR_ME);
vcpu->arch.intr_msr = MSR_SF | MSR_ME;
/*
@@ -2938,29 +2965,30 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu)
* don't set the HFSCR_MSGP bit, and that causes those instructions
* to trap and then we emulate them.
*/
- vcpu->arch.hfscr = HFSCR_TAR | HFSCR_EBB | HFSCR_PM | HFSCR_BHRB |
- HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP;
+ kvmppc_set_hfscr_hv(vcpu, HFSCR_TAR | HFSCR_EBB | HFSCR_PM | HFSCR_BHRB |
+ HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP);
/* On POWER10 and later, allow prefixed instructions */
if (cpu_has_feature(CPU_FTR_ARCH_31))
- vcpu->arch.hfscr |= HFSCR_PREFIX;
+ kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) | HFSCR_PREFIX);
if (cpu_has_feature(CPU_FTR_HVMODE)) {
- vcpu->arch.hfscr &= mfspr(SPRN_HFSCR);
+ kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) & mfspr(SPRN_HFSCR));
+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
if (cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST))
- vcpu->arch.hfscr |= HFSCR_TM;
+ kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) | HFSCR_TM);
#endif
}
if (cpu_has_feature(CPU_FTR_TM_COMP))
vcpu->arch.hfscr |= HFSCR_TM;
- vcpu->arch.hfscr_permitted = vcpu->arch.hfscr;
+ vcpu->arch.hfscr_permitted = kvmppc_get_hfscr_hv(vcpu);
/*
* PM, EBB, TM are demand-faulted so start with it clear.
*/
- vcpu->arch.hfscr &= ~(HFSCR_PM | HFSCR_EBB | HFSCR_TM);
+ kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) & ~(HFSCR_PM | HFSCR_EBB | HFSCR_TM));
kvmppc_mmu_book3s_hv_init(vcpu);
@@ -3071,6 +3099,8 @@ static void kvmppc_core_vcpu_free_hv(struct kvm_vcpu *vcpu)
unpin_vpa(vcpu->kvm, &vcpu->arch.slb_shadow);
unpin_vpa(vcpu->kvm, &vcpu->arch.vpa);
spin_unlock(&vcpu->arch.vpa_update_lock);
+ if (kvmhv_is_nestedv2())
+ kvmhv_nestedv2_vcpu_free(vcpu, &vcpu->arch.nestedv2_io);
}
static int kvmppc_core_check_requests_hv(struct kvm_vcpu *vcpu)
@@ -4035,10 +4065,58 @@ static void vcpu_vpa_increment_dispatch(struct kvm_vcpu *vcpu)
}
}
+static int kvmhv_vcpu_entry_nestedv2(struct kvm_vcpu *vcpu, u64 time_limit,
+ unsigned long lpcr, u64 *tb)
+{
+ struct kvmhv_nestedv2_io *io;
+ unsigned long msr, i;
+ int trap;
+ long rc;
+
+ io = &vcpu->arch.nestedv2_io;
+
+ msr = mfmsr();
+ kvmppc_msr_hard_disable_set_facilities(vcpu, msr);
+ if (lazy_irq_pending())
+ return 0;
+
+ rc = kvmhv_nestedv2_flush_vcpu(vcpu, time_limit);
+ if (rc < 0)
+ return -EINVAL;
+
+ accumulate_time(vcpu, &vcpu->arch.in_guest);
+ rc = plpar_guest_run_vcpu(0, vcpu->kvm->arch.lpid, vcpu->vcpu_id,
+ &trap, &i);
+
+ if (rc != H_SUCCESS) {
+ pr_err("KVM Guest Run VCPU hcall failed\n");
+ if (rc == H_INVALID_ELEMENT_ID)
+ pr_err("KVM: Guest Run VCPU invalid element id at %ld\n", i);
+ else if (rc == H_INVALID_ELEMENT_SIZE)
+ pr_err("KVM: Guest Run VCPU invalid element size at %ld\n", i);
+ else if (rc == H_INVALID_ELEMENT_VALUE)
+ pr_err("KVM: Guest Run VCPU invalid element value at %ld\n", i);
+ return -EINVAL;
+ }
+ accumulate_time(vcpu, &vcpu->arch.guest_exit);
+
+ *tb = mftb();
+ kvmppc_gsm_reset(io->vcpu_message);
+ kvmppc_gsm_reset(io->vcore_message);
+ kvmppc_gsbm_zero(&io->valids);
+
+ rc = kvmhv_nestedv2_parse_output(vcpu);
+ if (rc < 0)
+ return -EINVAL;
+
+ timer_rearm_host_dec(*tb);
+
+ return trap;
+}
+
/* call our hypervisor to load up HV regs and go */
static int kvmhv_vcpu_entry_p9_nested(struct kvm_vcpu *vcpu, u64 time_limit, unsigned long lpcr, u64 *tb)
{
- struct kvmppc_vcore *vc = vcpu->arch.vcore;
unsigned long host_psscr;
unsigned long msr;
struct hv_guest_state hvregs;
@@ -4118,7 +4196,7 @@ static int kvmhv_vcpu_entry_p9_nested(struct kvm_vcpu *vcpu, u64 time_limit, uns
if (!(lpcr & LPCR_LD)) /* Sign extend if not using large decrementer */
dec = (s32) dec;
*tb = mftb();
- vcpu->arch.dec_expires = dec + (*tb + vc->tb_offset);
+ vcpu->arch.dec_expires = dec + (*tb + kvmppc_get_tb_offset(vcpu));
timer_rearm_host_dec(*tb);
@@ -4153,7 +4231,10 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
vcpu_vpa_increment_dispatch(vcpu);
if (kvmhv_on_pseries()) {
- trap = kvmhv_vcpu_entry_p9_nested(vcpu, time_limit, lpcr, tb);
+ if (kvmhv_is_nestedv1())
+ trap = kvmhv_vcpu_entry_p9_nested(vcpu, time_limit, lpcr, tb);
+ else
+ trap = kvmhv_vcpu_entry_nestedv2(vcpu, time_limit, lpcr, tb);
/* H_CEDE has to be handled now, not later */
if (trap == BOOK3S_INTERRUPT_SYSCALL && !nested &&
@@ -4176,7 +4257,7 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
__this_cpu_write(cpu_in_guest, NULL);
if (trap == BOOK3S_INTERRUPT_SYSCALL &&
- !(vcpu->arch.shregs.msr & MSR_PR)) {
+ !(__kvmppc_get_msr_hv(vcpu) & MSR_PR)) {
unsigned long req = kvmppc_get_gpr(vcpu, 3);
/*
@@ -4655,7 +4736,7 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
if (!nested) {
kvmppc_core_prepare_to_enter(vcpu);
- if (vcpu->arch.shregs.msr & MSR_EE) {
+ if (__kvmppc_get_msr_hv(vcpu) & MSR_EE) {
if (xive_interrupt_pending(vcpu))
kvmppc_inject_interrupt_hv(vcpu,
BOOK3S_INTERRUPT_EXTERNAL, 0);
@@ -4677,7 +4758,7 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
tb = mftb();
- kvmppc_update_vpa_dispatch_p9(vcpu, vc, tb + vc->tb_offset);
+ kvmppc_update_vpa_dispatch_p9(vcpu, vc, tb + kvmppc_get_tb_offset(vcpu));
trace_kvm_guest_enter(vcpu);
@@ -4844,7 +4925,7 @@ static int kvmppc_vcpu_run_hv(struct kvm_vcpu *vcpu)
msr |= MSR_VSX;
if ((cpu_has_feature(CPU_FTR_TM) ||
cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) &&
- (vcpu->arch.hfscr & HFSCR_TM))
+ (kvmppc_get_hfscr_hv(vcpu) & HFSCR_TM))
msr |= MSR_TM;
msr = msr_check_and_set(msr);
@@ -4868,7 +4949,7 @@ static int kvmppc_vcpu_run_hv(struct kvm_vcpu *vcpu)
if (run->exit_reason == KVM_EXIT_PAPR_HCALL) {
accumulate_time(vcpu, &vcpu->arch.hcall);
- if (WARN_ON_ONCE(vcpu->arch.shregs.msr & MSR_PR)) {
+ if (WARN_ON_ONCE(__kvmppc_get_msr_hv(vcpu) & MSR_PR)) {
/*
* These should have been caught reflected
* into the guest by now. Final sanity check:
@@ -5133,6 +5214,14 @@ void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, unsigned long mask)
if (++cores_done >= kvm->arch.online_vcores)
break;
}
+
+ if (kvmhv_is_nestedv2()) {
+ struct kvm_vcpu *vcpu;
+
+ kvm_for_each_vcpu(i, vcpu, kvm) {
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LPCR);
+ }
+ }
}
void kvmppc_setup_partition_table(struct kvm *kvm)
@@ -5399,15 +5488,43 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
/* Allocate the guest's logical partition ID */
- lpid = kvmppc_alloc_lpid();
- if ((long)lpid < 0)
- return -ENOMEM;
- kvm->arch.lpid = lpid;
+ if (!kvmhv_is_nestedv2()) {
+ lpid = kvmppc_alloc_lpid();
+ if ((long)lpid < 0)
+ return -ENOMEM;
+ kvm->arch.lpid = lpid;
+ }
kvmppc_alloc_host_rm_ops();
kvmhv_vm_nested_init(kvm);
+ if (kvmhv_is_nestedv2()) {
+ long rc;
+ unsigned long guest_id;
+
+ rc = plpar_guest_create(0, &guest_id);
+
+ if (rc != H_SUCCESS)
+ pr_err("KVM: Create Guest hcall failed, rc=%ld\n", rc);
+
+ switch (rc) {
+ case H_PARAMETER:
+ case H_FUNCTION:
+ case H_STATE:
+ return -EINVAL;
+ case H_NOT_ENOUGH_RESOURCES:
+ case H_ABORTED:
+ return -ENOMEM;
+ case H_AUTHORITY:
+ return -EPERM;
+ case H_NOT_AVAILABLE:
+ return -EBUSY;
+ }
+ kvm->arch.lpid = guest_id;
+ }
+
+
/*
* Since we don't flush the TLB when tearing down a VM,
* and this lpid might have previously been used,
@@ -5477,7 +5594,10 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
lpcr |= LPCR_HAIL;
ret = kvmppc_init_vm_radix(kvm);
if (ret) {
- kvmppc_free_lpid(kvm->arch.lpid);
+ if (kvmhv_is_nestedv2())
+ plpar_guest_delete(0, kvm->arch.lpid);
+ else
+ kvmppc_free_lpid(kvm->arch.lpid);
return ret;
}
kvmppc_setup_partition_table(kvm);
@@ -5567,10 +5687,14 @@ static void kvmppc_core_destroy_vm_hv(struct kvm *kvm)
kvm->arch.process_table = 0;
if (kvm->arch.secure_guest)
uv_svm_terminate(kvm->arch.lpid);
- kvmhv_set_ptbl_entry(kvm->arch.lpid, 0, 0);
+ if (!kvmhv_is_nestedv2())
+ kvmhv_set_ptbl_entry(kvm->arch.lpid, 0, 0);
}
- kvmppc_free_lpid(kvm->arch.lpid);
+ if (kvmhv_is_nestedv2())
+ plpar_guest_delete(0, kvm->arch.lpid);
+ else
+ kvmppc_free_lpid(kvm->arch.lpid);
kvmppc_free_pimap(kvm);
}
@@ -5982,6 +6106,8 @@ static int kvmhv_enable_nested(struct kvm *kvm)
return -ENODEV;
if (!radix_enabled())
return -ENODEV;
+ if (kvmhv_is_nestedv2())
+ return -ENODEV;
/* kvm == NULL means the caller is testing if the capability exists */
if (kvm)
diff --git a/arch/powerpc/kvm/book3s_hv.h b/arch/powerpc/kvm/book3s_hv.h
index 2f2e59d7d433..47b2c815641e 100644
--- a/arch/powerpc/kvm/book3s_hv.h
+++ b/arch/powerpc/kvm/book3s_hv.h
@@ -3,6 +3,8 @@
/*
* Privileged (non-hypervisor) host registers to save.
*/
+#include "asm/guest-state-buffer.h"
+
struct p9_host_os_sprs {
unsigned long iamr;
unsigned long amr;
@@ -50,3 +52,77 @@ void accumulate_time(struct kvm_vcpu *vcpu, struct kvmhv_tb_accumulator *next);
#define start_timing(vcpu, next) do {} while (0)
#define end_timing(vcpu) do {} while (0)
#endif
+
+static inline void __kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 val)
+{
+ vcpu->arch.shregs.msr = val;
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_MSR);
+}
+
+static inline u64 __kvmppc_get_msr_hv(struct kvm_vcpu *vcpu)
+{
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_MSR) < 0);
+ return vcpu->arch.shregs.msr;
+}
+
+#define KVMPPC_BOOK3S_HV_VCPU_ACCESSOR_SET(reg, size, iden) \
+static inline void kvmppc_set_##reg ##_hv(struct kvm_vcpu *vcpu, u##size val) \
+{ \
+ vcpu->arch.reg = val; \
+ kvmhv_nestedv2_mark_dirty(vcpu, iden); \
+}
+
+#define KVMPPC_BOOK3S_HV_VCPU_ACCESSOR_GET(reg, size, iden) \
+static inline u##size kvmppc_get_##reg ##_hv(struct kvm_vcpu *vcpu) \
+{ \
+ kvmhv_nestedv2_cached_reload(vcpu, iden); \
+ return vcpu->arch.reg; \
+}
+
+#define KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(reg, size, iden) \
+ KVMPPC_BOOK3S_HV_VCPU_ACCESSOR_SET(reg, size, iden) \
+ KVMPPC_BOOK3S_HV_VCPU_ACCESSOR_GET(reg, size, iden) \
+
+#define KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR_SET(reg, size, iden) \
+static inline void kvmppc_set_##reg ##_hv(struct kvm_vcpu *vcpu, int i, u##size val) \
+{ \
+ vcpu->arch.reg[i] = val; \
+ kvmhv_nestedv2_mark_dirty(vcpu, iden(i)); \
+}
+
+#define KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR_GET(reg, size, iden) \
+static inline u##size kvmppc_get_##reg ##_hv(struct kvm_vcpu *vcpu, int i) \
+{ \
+ WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, iden(i)) < 0); \
+ return vcpu->arch.reg[i]; \
+}
+
+#define KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR(reg, size, iden) \
+ KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR_SET(reg, size, iden) \
+ KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR_GET(reg, size, iden) \
+
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(mmcra, 64, KVMPPC_GSID_MMCRA)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(hfscr, 64, KVMPPC_GSID_HFSCR)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(fscr, 64, KVMPPC_GSID_FSCR)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dscr, 64, KVMPPC_GSID_DSCR)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(purr, 64, KVMPPC_GSID_PURR)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(spurr, 64, KVMPPC_GSID_SPURR)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(amr, 64, KVMPPC_GSID_AMR)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(uamor, 64, KVMPPC_GSID_UAMOR)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(siar, 64, KVMPPC_GSID_SIAR)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(sdar, 64, KVMPPC_GSID_SDAR)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(iamr, 64, KVMPPC_GSID_IAMR)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dawr0, 64, KVMPPC_GSID_DAWR0)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dawr1, 64, KVMPPC_GSID_DAWR1)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dawrx0, 64, KVMPPC_GSID_DAWRX0)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dawrx1, 64, KVMPPC_GSID_DAWRX1)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(ciabr, 64, KVMPPC_GSID_CIABR)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(wort, 64, KVMPPC_GSID_WORT)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(ppr, 64, KVMPPC_GSID_PPR)
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(ctrl, 64, KVMPPC_GSID_CTRL);
+
+KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR(mmcr, 64, KVMPPC_GSID_MMCR)
+KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR(sier, 64, KVMPPC_GSID_SIER)
+KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR(pmc, 32, KVMPPC_GSID_PMC)
+
+KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(pspb, 32, KVMPPC_GSID_PSPB)
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index 0f5b021fa559..fa0e3a22cac0 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -32,6 +32,7 @@
#include "book3s_xics.h"
#include "book3s_xive.h"
+#include "book3s_hv.h"
/*
* Hash page table alignment on newer cpus(CPU_FTR_ARCH_206)
@@ -182,9 +183,13 @@ EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);
long kvmppc_rm_h_random(struct kvm_vcpu *vcpu)
{
+ unsigned long rand;
+
if (ppc_md.get_random_seed &&
- ppc_md.get_random_seed(&vcpu->arch.regs.gpr[4]))
+ ppc_md.get_random_seed(&rand)) {
+ kvmppc_set_gpr(vcpu, 4, rand);
return H_SUCCESS;
+ }
return H_HARDWARE;
}
@@ -510,7 +515,7 @@ void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr)
*/
if ((msr & MSR_TS_MASK) == MSR_TS_MASK)
msr &= ~MSR_TS_MASK;
- vcpu->arch.shregs.msr = msr;
+ __kvmppc_set_msr_hv(vcpu, msr);
kvmppc_end_cede(vcpu);
}
EXPORT_SYMBOL_GPL(kvmppc_set_msr_hv);
@@ -548,7 +553,7 @@ static void inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 srr1_flags)
kvmppc_set_srr0(vcpu, pc);
kvmppc_set_srr1(vcpu, (msr & SRR1_MSR_BITS) | srr1_flags);
kvmppc_set_pc(vcpu, new_pc);
- vcpu->arch.shregs.msr = new_msr;
+ __kvmppc_set_msr_hv(vcpu, new_msr);
}
void kvmppc_inject_interrupt_hv(struct kvm_vcpu *vcpu, int vec, u64 srr1_flags)
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
index 377d0b4a05ee..3b658b8696bc 100644
--- a/arch/powerpc/kvm/book3s_hv_nested.c
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
@@ -428,10 +428,12 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
return vcpu->arch.trap;
}
+unsigned long nested_capabilities;
+
long kvmhv_nested_init(void)
{
long int ptb_order;
- unsigned long ptcr;
+ unsigned long ptcr, host_capabilities;
long rc;
if (!kvmhv_on_pseries())
@@ -439,6 +441,29 @@ long kvmhv_nested_init(void)
if (!radix_enabled())
return -ENODEV;
+ rc = plpar_guest_get_capabilities(0, &host_capabilities);
+ if (rc == H_SUCCESS) {
+ unsigned long capabilities = 0;
+
+ if (cpu_has_feature(CPU_FTR_ARCH_31))
+ capabilities |= H_GUEST_CAP_POWER10;
+ if (cpu_has_feature(CPU_FTR_ARCH_300))
+ capabilities |= H_GUEST_CAP_POWER9;
+
+ nested_capabilities = capabilities & host_capabilities;
+ rc = plpar_guest_set_capabilities(0, nested_capabilities);
+ if (rc != H_SUCCESS) {
+ pr_err("kvm-hv: Could not configure parent hypervisor capabilities (rc=%ld)",
+ rc);
+ return -ENODEV;
+ }
+
+ static_branch_enable(&__kvmhv_is_nestedv2);
+ return 0;
+ }
+
+ pr_info("kvm-hv: nestedv2 get capabilities hcall failed, falling back to nestedv1 (rc=%ld)\n",
+ rc);
/* Partition table entry is 1<<4 bytes in size, hence the 4. */
ptb_order = KVM_MAX_NESTED_GUESTS_SHIFT + 4;
/* Minimum partition table size is 1<<12 bytes */
@@ -478,7 +503,7 @@ void kvmhv_nested_exit(void)
}
}
-static void kvmhv_flush_lpid(unsigned int lpid)
+static void kvmhv_flush_lpid(u64 lpid)
{
long rc;
@@ -500,17 +525,22 @@ static void kvmhv_flush_lpid(unsigned int lpid)
pr_err("KVM: TLB LPID invalidation hcall failed, rc=%ld\n", rc);
}
-void kvmhv_set_ptbl_entry(unsigned int lpid, u64 dw0, u64 dw1)
+void kvmhv_set_ptbl_entry(u64 lpid, u64 dw0, u64 dw1)
{
if (!kvmhv_on_pseries()) {
mmu_partition_table_set_entry(lpid, dw0, dw1, true);
return;
}
- pseries_partition_tb[lpid].patb0 = cpu_to_be64(dw0);
- pseries_partition_tb[lpid].patb1 = cpu_to_be64(dw1);
- /* L0 will do the necessary barriers */
- kvmhv_flush_lpid(lpid);
+ if (kvmhv_is_nestedv1()) {
+ pseries_partition_tb[lpid].patb0 = cpu_to_be64(dw0);
+ pseries_partition_tb[lpid].patb1 = cpu_to_be64(dw1);
+ /* L0 will do the necessary barriers */
+ kvmhv_flush_lpid(lpid);
+ }
+
+ if (kvmhv_is_nestedv2())
+ kvmhv_nestedv2_set_ptbl_entry(lpid, dw0, dw1);
}
static void kvmhv_set_nested_ptbl(struct kvm_nested_guest *gp)
diff --git a/arch/powerpc/kvm/book3s_hv_nestedv2.c b/arch/powerpc/kvm/book3s_hv_nestedv2.c
new file mode 100644
index 000000000000..fd3c4f2d9480
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_nestedv2.c
@@ -0,0 +1,994 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2023 Jordan Niethe, IBM Corp. <jniethe5@gmail.com>
+ *
+ * Authors:
+ * Jordan Niethe <jniethe5@gmail.com>
+ *
+ * Description: KVM functions specific to running on Book 3S
+ * processors as a NESTEDv2 guest.
+ *
+ */
+
+#include "linux/blk-mq.h"
+#include "linux/console.h"
+#include "linux/gfp_types.h"
+#include "linux/signal.h"
+#include <linux/kernel.h>
+#include <linux/kvm_host.h>
+#include <linux/pgtable.h>
+
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+#include <asm/hvcall.h>
+#include <asm/pgalloc.h>
+#include <asm/reg.h>
+#include <asm/plpar_wrappers.h>
+#include <asm/guest-state-buffer.h>
+#include "trace_hv.h"
+
+struct static_key_false __kvmhv_is_nestedv2 __read_mostly;
+EXPORT_SYMBOL_GPL(__kvmhv_is_nestedv2);
+
+
+static size_t
+gs_msg_ops_kvmhv_nestedv2_config_get_size(struct kvmppc_gs_msg *gsm)
+{
+ u16 ids[] = {
+ KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE,
+ KVMPPC_GSID_RUN_INPUT,
+ KVMPPC_GSID_RUN_OUTPUT,
+
+ };
+ size_t size = 0;
+
+ for (int i = 0; i < ARRAY_SIZE(ids); i++)
+ size += kvmppc_gse_total_size(kvmppc_gsid_size(ids[i]));
+ return size;
+}
+
+static int
+gs_msg_ops_kvmhv_nestedv2_config_fill_info(struct kvmppc_gs_buff *gsb,
+ struct kvmppc_gs_msg *gsm)
+{
+ struct kvmhv_nestedv2_config *cfg;
+ int rc;
+
+ cfg = gsm->data;
+
+ if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE)) {
+ rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE,
+ cfg->vcpu_run_output_size);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_INPUT)) {
+ rc = kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_INPUT,
+ cfg->vcpu_run_input_cfg);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_OUTPUT)) {
+ kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_OUTPUT,
+ cfg->vcpu_run_output_cfg);
+ if (rc < 0)
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+gs_msg_ops_kvmhv_nestedv2_config_refresh_info(struct kvmppc_gs_msg *gsm,
+ struct kvmppc_gs_buff *gsb)
+{
+ struct kvmhv_nestedv2_config *cfg;
+ struct kvmppc_gs_parser gsp = { 0 };
+ struct kvmppc_gs_elem *gse;
+ int rc;
+
+ cfg = gsm->data;
+
+ rc = kvmppc_gse_parse(&gsp, gsb);
+ if (rc < 0)
+ return rc;
+
+ gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE);
+ if (gse)
+ cfg->vcpu_run_output_size = kvmppc_gse_get_u64(gse);
+ return 0;
+}
+
+static struct kvmppc_gs_msg_ops config_msg_ops = {
+ .get_size = gs_msg_ops_kvmhv_nestedv2_config_get_size,
+ .fill_info = gs_msg_ops_kvmhv_nestedv2_config_fill_info,
+ .refresh_info = gs_msg_ops_kvmhv_nestedv2_config_refresh_info,
+};
+
+static size_t gs_msg_ops_vcpu_get_size(struct kvmppc_gs_msg *gsm)
+{
+ struct kvmppc_gs_bitmap gsbm = { 0 };
+ size_t size = 0;
+ u16 iden;
+
+ kvmppc_gsbm_fill(&gsbm);
+ kvmppc_gsbm_for_each(&gsbm, iden)
+ {
+ switch (iden) {
+ case KVMPPC_GSID_HOST_STATE_SIZE:
+ case KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE:
+ case KVMPPC_GSID_PARTITION_TABLE:
+ case KVMPPC_GSID_PROCESS_TABLE:
+ case KVMPPC_GSID_RUN_INPUT:
+ case KVMPPC_GSID_RUN_OUTPUT:
+ break;
+ default:
+ size += kvmppc_gse_total_size(kvmppc_gsid_size(iden));
+ }
+ }
+ return size;
+}
+
+static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb,
+ struct kvmppc_gs_msg *gsm)
+{
+ struct kvm_vcpu *vcpu;
+ vector128 v;
+ int rc, i;
+ u16 iden;
+
+ vcpu = gsm->data;
+
+ kvmppc_gsm_for_each(gsm, iden)
+ {
+ rc = 0;
+
+ if ((gsm->flags & KVMPPC_GS_FLAGS_WIDE) !=
+ (kvmppc_gsid_flags(iden) & KVMPPC_GS_FLAGS_WIDE))
+ continue;
+
+ switch (iden) {
+ case KVMPPC_GSID_DSCR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dscr);
+ break;
+ case KVMPPC_GSID_MMCRA:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.mmcra);
+ break;
+ case KVMPPC_GSID_HFSCR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.hfscr);
+ break;
+ case KVMPPC_GSID_PURR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.purr);
+ break;
+ case KVMPPC_GSID_SPURR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.spurr);
+ break;
+ case KVMPPC_GSID_AMR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.amr);
+ break;
+ case KVMPPC_GSID_UAMOR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.uamor);
+ break;
+ case KVMPPC_GSID_SIAR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.siar);
+ break;
+ case KVMPPC_GSID_SDAR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.sdar);
+ break;
+ case KVMPPC_GSID_IAMR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.iamr);
+ break;
+ case KVMPPC_GSID_DAWR0:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dawr0);
+ break;
+ case KVMPPC_GSID_DAWR1:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dawr1);
+ break;
+ case KVMPPC_GSID_DAWRX0:
+ rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.dawrx0);
+ break;
+ case KVMPPC_GSID_DAWRX1:
+ rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.dawrx1);
+ break;
+ case KVMPPC_GSID_CIABR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ciabr);
+ break;
+ case KVMPPC_GSID_WORT:
+ rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.wort);
+ break;
+ case KVMPPC_GSID_PPR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ppr);
+ break;
+ case KVMPPC_GSID_PSPB:
+ rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.pspb);
+ break;
+ case KVMPPC_GSID_TAR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.tar);
+ break;
+ case KVMPPC_GSID_FSCR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.fscr);
+ break;
+ case KVMPPC_GSID_EBBHR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ebbhr);
+ break;
+ case KVMPPC_GSID_EBBRR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ebbrr);
+ break;
+ case KVMPPC_GSID_BESCR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.bescr);
+ break;
+ case KVMPPC_GSID_IC:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ic);
+ break;
+ case KVMPPC_GSID_CTRL:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ctrl);
+ break;
+ case KVMPPC_GSID_PIDR:
+ rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.pid);
+ break;
+ case KVMPPC_GSID_AMOR: {
+ u64 amor = ~0;
+
+ rc = kvmppc_gse_put_u64(gsb, iden, amor);
+ break;
+ }
+ case KVMPPC_GSID_VRSAVE:
+ rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.vrsave);
+ break;
+ case KVMPPC_GSID_MMCR(0)... KVMPPC_GSID_MMCR(3):
+ i = iden - KVMPPC_GSID_MMCR(0);
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.mmcr[i]);
+ break;
+ case KVMPPC_GSID_SIER(0)... KVMPPC_GSID_SIER(2):
+ i = iden - KVMPPC_GSID_SIER(0);
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.sier[i]);
+ break;
+ case KVMPPC_GSID_PMC(0)... KVMPPC_GSID_PMC(5):
+ i = iden - KVMPPC_GSID_PMC(0);
+ rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.pmc[i]);
+ break;
+ case KVMPPC_GSID_GPR(0)... KVMPPC_GSID_GPR(31):
+ i = iden - KVMPPC_GSID_GPR(0);
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.regs.gpr[i]);
+ break;
+ case KVMPPC_GSID_CR:
+ rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.regs.ccr);
+ break;
+ case KVMPPC_GSID_XER:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.regs.xer);
+ break;
+ case KVMPPC_GSID_CTR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.regs.ctr);
+ break;
+ case KVMPPC_GSID_LR:
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.regs.link);
+ break;
+ case KVMPPC_GSID_NIA:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.regs.nip);
+ break;
+ case KVMPPC_GSID_SRR0:
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.shregs.srr0);
+ break;
+ case KVMPPC_GSID_SRR1:
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.shregs.srr1);
+ break;
+ case KVMPPC_GSID_SPRG0:
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.shregs.sprg0);
+ break;
+ case KVMPPC_GSID_SPRG1:
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.shregs.sprg1);
+ break;
+ case KVMPPC_GSID_SPRG2:
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.shregs.sprg2);
+ break;
+ case KVMPPC_GSID_SPRG3:
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.shregs.sprg3);
+ break;
+ case KVMPPC_GSID_DAR:
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.shregs.dar);
+ break;
+ case KVMPPC_GSID_DSISR:
+ rc = kvmppc_gse_put_u32(gsb, iden,
+ vcpu->arch.shregs.dsisr);
+ break;
+ case KVMPPC_GSID_MSR:
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.shregs.msr);
+ break;
+ case KVMPPC_GSID_VTB:
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.vcore->vtb);
+ break;
+ case KVMPPC_GSID_LPCR:
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.vcore->lpcr);
+ break;
+ case KVMPPC_GSID_TB_OFFSET:
+ rc = kvmppc_gse_put_u64(gsb, iden,
+ vcpu->arch.vcore->tb_offset);
+ break;
+ case KVMPPC_GSID_FPSCR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.fp.fpscr);
+ break;
+ case KVMPPC_GSID_VSRS(0)... KVMPPC_GSID_VSRS(31):
+ i = iden - KVMPPC_GSID_VSRS(0);
+ memcpy(&v, &vcpu->arch.fp.fpr[i],
+ sizeof(vcpu->arch.fp.fpr[i]));
+ rc = kvmppc_gse_put_vector128(gsb, iden, &v);
+ break;
+#ifdef CONFIG_VSX
+ case KVMPPC_GSID_VSCR:
+ rc = kvmppc_gse_put_u32(gsb, iden,
+ vcpu->arch.vr.vscr.u[3]);
+ break;
+ case KVMPPC_GSID_VSRS(32)... KVMPPC_GSID_VSRS(63):
+ i = iden - KVMPPC_GSID_VSRS(32);
+ rc = kvmppc_gse_put_vector128(gsb, iden,
+ &vcpu->arch.vr.vr[i]);
+ break;
+#endif
+ case KVMPPC_GSID_DEC_EXPIRY_TB: {
+ u64 dw;
+
+ dw = vcpu->arch.dec_expires -
+ vcpu->arch.vcore->tb_offset;
+ rc = kvmppc_gse_put_u64(gsb, iden, dw);
+ break;
+ }
+ case KVMPPC_GSID_LOGICAL_PVR:
+ rc = kvmppc_gse_put_u32(gsb, iden,
+ vcpu->arch.vcore->arch_compat);
+ break;
+ }
+
+ if (rc < 0)
+ return rc;
+ }
+
+ return 0;
+}
+
+static int gs_msg_ops_vcpu_refresh_info(struct kvmppc_gs_msg *gsm,
+ struct kvmppc_gs_buff *gsb)
+{
+ struct kvmppc_gs_parser gsp = { 0 };
+ struct kvmhv_nestedv2_io *io;
+ struct kvmppc_gs_bitmap *valids;
+ struct kvm_vcpu *vcpu;
+ struct kvmppc_gs_elem *gse;
+ vector128 v;
+ int rc, i;
+ u16 iden;
+
+ vcpu = gsm->data;
+
+ rc = kvmppc_gse_parse(&gsp, gsb);
+ if (rc < 0)
+ return rc;
+
+ io = &vcpu->arch.nestedv2_io;
+ valids = &io->valids;
+
+ kvmppc_gsp_for_each(&gsp, iden, gse)
+ {
+ switch (iden) {
+ case KVMPPC_GSID_DSCR:
+ vcpu->arch.dscr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_MMCRA:
+ vcpu->arch.mmcra = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_HFSCR:
+ vcpu->arch.hfscr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_PURR:
+ vcpu->arch.purr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_SPURR:
+ vcpu->arch.spurr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_AMR:
+ vcpu->arch.amr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_UAMOR:
+ vcpu->arch.uamor = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_SIAR:
+ vcpu->arch.siar = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_SDAR:
+ vcpu->arch.sdar = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_IAMR:
+ vcpu->arch.iamr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_DAWR0:
+ vcpu->arch.dawr0 = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_DAWR1:
+ vcpu->arch.dawr1 = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_DAWRX0:
+ vcpu->arch.dawrx0 = kvmppc_gse_get_u32(gse);
+ break;
+ case KVMPPC_GSID_DAWRX1:
+ vcpu->arch.dawrx1 = kvmppc_gse_get_u32(gse);
+ break;
+ case KVMPPC_GSID_CIABR:
+ vcpu->arch.ciabr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_WORT:
+ vcpu->arch.wort = kvmppc_gse_get_u32(gse);
+ break;
+ case KVMPPC_GSID_PPR:
+ vcpu->arch.ppr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_PSPB:
+ vcpu->arch.pspb = kvmppc_gse_get_u32(gse);
+ break;
+ case KVMPPC_GSID_TAR:
+ vcpu->arch.tar = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_FSCR:
+ vcpu->arch.fscr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_EBBHR:
+ vcpu->arch.ebbhr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_EBBRR:
+ vcpu->arch.ebbrr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_BESCR:
+ vcpu->arch.bescr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_IC:
+ vcpu->arch.ic = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_CTRL:
+ vcpu->arch.ctrl = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_PIDR:
+ vcpu->arch.pid = kvmppc_gse_get_u32(gse);
+ break;
+ case KVMPPC_GSID_AMOR:
+ break;
+ case KVMPPC_GSID_VRSAVE:
+ vcpu->arch.vrsave = kvmppc_gse_get_u32(gse);
+ break;
+ case KVMPPC_GSID_MMCR(0)... KVMPPC_GSID_MMCR(3):
+ i = iden - KVMPPC_GSID_MMCR(0);
+ vcpu->arch.mmcr[i] = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_SIER(0)... KVMPPC_GSID_SIER(2):
+ i = iden - KVMPPC_GSID_SIER(0);
+ vcpu->arch.sier[i] = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_PMC(0)... KVMPPC_GSID_PMC(5):
+ i = iden - KVMPPC_GSID_PMC(0);
+ vcpu->arch.pmc[i] = kvmppc_gse_get_u32(gse);
+ break;
+ case KVMPPC_GSID_GPR(0)... KVMPPC_GSID_GPR(31):
+ i = iden - KVMPPC_GSID_GPR(0);
+ vcpu->arch.regs.gpr[i] = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_CR:
+ vcpu->arch.regs.ccr = kvmppc_gse_get_u32(gse);
+ break;
+ case KVMPPC_GSID_XER:
+ vcpu->arch.regs.xer = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_CTR:
+ vcpu->arch.regs.ctr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_LR:
+ vcpu->arch.regs.link = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_NIA:
+ vcpu->arch.regs.nip = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_SRR0:
+ vcpu->arch.shregs.srr0 = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_SRR1:
+ vcpu->arch.shregs.srr1 = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_SPRG0:
+ vcpu->arch.shregs.sprg0 = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_SPRG1:
+ vcpu->arch.shregs.sprg1 = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_SPRG2:
+ vcpu->arch.shregs.sprg2 = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_SPRG3:
+ vcpu->arch.shregs.sprg3 = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_DAR:
+ vcpu->arch.shregs.dar = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_DSISR:
+ vcpu->arch.shregs.dsisr = kvmppc_gse_get_u32(gse);
+ break;
+ case KVMPPC_GSID_MSR:
+ vcpu->arch.shregs.msr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_VTB:
+ vcpu->arch.vcore->vtb = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_LPCR:
+ vcpu->arch.vcore->lpcr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_TB_OFFSET:
+ vcpu->arch.vcore->tb_offset = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_FPSCR:
+ vcpu->arch.fp.fpscr = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_VSRS(0)... KVMPPC_GSID_VSRS(31):
+ kvmppc_gse_get_vector128(gse, &v);
+ i = iden - KVMPPC_GSID_VSRS(0);
+ memcpy(&vcpu->arch.fp.fpr[i], &v,
+ sizeof(vcpu->arch.fp.fpr[i]));
+ break;
+#ifdef CONFIG_VSX
+ case KVMPPC_GSID_VSCR:
+ vcpu->arch.vr.vscr.u[3] = kvmppc_gse_get_u32(gse);
+ break;
+ case KVMPPC_GSID_VSRS(32)... KVMPPC_GSID_VSRS(63):
+ i = iden - KVMPPC_GSID_VSRS(32);
+ kvmppc_gse_get_vector128(gse, &vcpu->arch.vr.vr[i]);
+ break;
+#endif
+ case KVMPPC_GSID_HDAR:
+ vcpu->arch.fault_dar = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_HDSISR:
+ vcpu->arch.fault_dsisr = kvmppc_gse_get_u32(gse);
+ break;
+ case KVMPPC_GSID_ASDR:
+ vcpu->arch.fault_gpa = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_HEIR:
+ vcpu->arch.emul_inst = kvmppc_gse_get_u64(gse);
+ break;
+ case KVMPPC_GSID_DEC_EXPIRY_TB: {
+ u64 dw;
+
+ dw = kvmppc_gse_get_u64(gse);
+ vcpu->arch.dec_expires =
+ dw + vcpu->arch.vcore->tb_offset;
+ break;
+ }
+ case KVMPPC_GSID_LOGICAL_PVR:
+ vcpu->arch.vcore->arch_compat = kvmppc_gse_get_u32(gse);
+ break;
+ default:
+ continue;
+ }
+ kvmppc_gsbm_set(valids, iden);
+ }
+
+ return 0;
+}
+
+static struct kvmppc_gs_msg_ops vcpu_message_ops = {
+ .get_size = gs_msg_ops_vcpu_get_size,
+ .fill_info = gs_msg_ops_vcpu_fill_info,
+ .refresh_info = gs_msg_ops_vcpu_refresh_info,
+};
+
+static int kvmhv_nestedv2_host_create(struct kvm_vcpu *vcpu,
+ struct kvmhv_nestedv2_io *io)
+{
+ struct kvmhv_nestedv2_config *cfg;
+ struct kvmppc_gs_buff *gsb, *vcpu_run_output, *vcpu_run_input;
+ unsigned long guest_id, vcpu_id;
+ struct kvmppc_gs_msg *gsm, *vcpu_message, *vcore_message;
+ int rc;
+
+ cfg = &io->cfg;
+ guest_id = vcpu->kvm->arch.lpid;
+ vcpu_id = vcpu->vcpu_id;
+
+ gsm = kvmppc_gsm_new(&config_msg_ops, cfg, KVMPPC_GS_FLAGS_WIDE,
+ GFP_KERNEL);
+ if (!gsm) {
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ gsb = kvmppc_gsb_new(kvmppc_gsm_size(gsm), guest_id, vcpu_id,
+ GFP_KERNEL);
+ if (!gsb) {
+ rc = -ENOMEM;
+ goto free_gsm;
+ }
+
+ rc = kvmppc_gsb_receive_datum(gsb, gsm,
+ KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE);
+ if (rc < 0) {
+ pr_err("KVM-NESTEDv2: couldn't get vcpu run output buffer minimum size\n");
+ goto free_gsb;
+ }
+
+ vcpu_run_output = kvmppc_gsb_new(cfg->vcpu_run_output_size, guest_id,
+ vcpu_id, GFP_KERNEL);
+ if (!vcpu_run_output) {
+ rc = -ENOMEM;
+ goto free_gsb;
+ }
+
+ cfg->vcpu_run_output_cfg.address = kvmppc_gsb_paddress(vcpu_run_output);
+ cfg->vcpu_run_output_cfg.size = kvmppc_gsb_capacity(vcpu_run_output);
+ io->vcpu_run_output = vcpu_run_output;
+
+ gsm->flags = 0;
+ rc = kvmppc_gsb_send_datum(gsb, gsm, KVMPPC_GSID_RUN_OUTPUT);
+ if (rc < 0) {
+ pr_err("KVM-NESTEDv2: couldn't set vcpu run output buffer\n");
+ goto free_gs_out;
+ }
+
+ vcpu_message = kvmppc_gsm_new(&vcpu_message_ops, vcpu, 0, GFP_KERNEL);
+ if (!vcpu_message) {
+ rc = -ENOMEM;
+ goto free_gs_out;
+ }
+ kvmppc_gsm_include_all(vcpu_message);
+
+ io->vcpu_message = vcpu_message;
+
+ vcpu_run_input = kvmppc_gsb_new(kvmppc_gsm_size(vcpu_message), guest_id,
+ vcpu_id, GFP_KERNEL);
+ if (!vcpu_run_input) {
+ rc = -ENOMEM;
+ goto free_vcpu_message;
+ }
+
+ io->vcpu_run_input = vcpu_run_input;
+ cfg->vcpu_run_input_cfg.address = kvmppc_gsb_paddress(vcpu_run_input);
+ cfg->vcpu_run_input_cfg.size = kvmppc_gsb_capacity(vcpu_run_input);
+ rc = kvmppc_gsb_send_datum(gsb, gsm, KVMPPC_GSID_RUN_INPUT);
+ if (rc < 0) {
+ pr_err("KVM-NESTEDv2: couldn't set vcpu run input buffer\n");
+ goto free_vcpu_run_input;
+ }
+
+ vcore_message = kvmppc_gsm_new(&vcpu_message_ops, vcpu,
+ KVMPPC_GS_FLAGS_WIDE, GFP_KERNEL);
+ if (!vcore_message) {
+ rc = -ENOMEM;
+ goto free_vcpu_run_input;
+ }
+
+ kvmppc_gsm_include_all(vcore_message);
+ kvmppc_gsbm_clear(&vcore_message->bitmap, KVMPPC_GSID_LOGICAL_PVR);
+ io->vcore_message = vcore_message;
+
+ kvmppc_gsbm_fill(&io->valids);
+ kvmppc_gsm_free(gsm);
+ kvmppc_gsb_free(gsb);
+ return 0;
+
+free_vcpu_run_input:
+ kvmppc_gsb_free(vcpu_run_input);
+free_vcpu_message:
+ kvmppc_gsm_free(vcpu_message);
+free_gs_out:
+ kvmppc_gsb_free(vcpu_run_output);
+free_gsb:
+ kvmppc_gsb_free(gsb);
+free_gsm:
+ kvmppc_gsm_free(gsm);
+err:
+ return rc;
+}
+
+/**
+ * __kvmhv_nestedv2_mark_dirty() - mark a Guest State ID to be sent to the host
+ * @vcpu: vcpu
+ * @iden: guest state ID
+ *
+ * Mark a guest state ID as having been changed by the L1 host and thus
+ * the new value must be sent to the L0 hypervisor. See kvmhv_nestedv2_flush_vcpu()
+ */
+int __kvmhv_nestedv2_mark_dirty(struct kvm_vcpu *vcpu, u16 iden)
+{
+ struct kvmhv_nestedv2_io *io;
+ struct kvmppc_gs_bitmap *valids;
+ struct kvmppc_gs_msg *gsm;
+
+ if (!iden)
+ return 0;
+
+ io = &vcpu->arch.nestedv2_io;
+ valids = &io->valids;
+ gsm = io->vcpu_message;
+ kvmppc_gsm_include(gsm, iden);
+ gsm = io->vcore_message;
+ kvmppc_gsm_include(gsm, iden);
+ kvmppc_gsbm_set(valids, iden);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_mark_dirty);
+
+/**
+ * __kvmhv_nestedv2_cached_reload() - reload a Guest State ID from the host
+ * @vcpu: vcpu
+ * @iden: guest state ID
+ *
+ * Reload the value for the guest state ID from the L0 host into the L1 host.
+ * This is cached so that going out to the L0 host only happens if necessary.
+ */
+int __kvmhv_nestedv2_cached_reload(struct kvm_vcpu *vcpu, u16 iden)
+{
+ struct kvmhv_nestedv2_io *io;
+ struct kvmppc_gs_bitmap *valids;
+ struct kvmppc_gs_buff *gsb;
+ struct kvmppc_gs_msg gsm;
+ int rc;
+
+ if (!iden)
+ return 0;
+
+ io = &vcpu->arch.nestedv2_io;
+ valids = &io->valids;
+ if (kvmppc_gsbm_test(valids, iden))
+ return 0;
+
+ gsb = io->vcpu_run_input;
+ kvmppc_gsm_init(&gsm, &vcpu_message_ops, vcpu, kvmppc_gsid_flags(iden));
+ rc = kvmppc_gsb_receive_datum(gsb, &gsm, iden);
+ if (rc < 0) {
+ pr_err("KVM-NESTEDv2: couldn't get GSID: 0x%x\n", iden);
+ return rc;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_cached_reload);
+
+/**
+ * kvmhv_nestedv2_flush_vcpu() - send modified Guest State IDs to the host
+ * @vcpu: vcpu
+ * @time_limit: hdec expiry tb
+ *
+ * Send the values marked by __kvmhv_nestedv2_mark_dirty() to the L0 host.
+ * Thread wide values are copied to the H_GUEST_RUN_VCPU input buffer. Guest
+ * wide values need to be sent with H_GUEST_SET first.
+ *
+ * The hdec tb offset is always sent to L0 host.
+ */
+int kvmhv_nestedv2_flush_vcpu(struct kvm_vcpu *vcpu, u64 time_limit)
+{
+ struct kvmhv_nestedv2_io *io;
+ struct kvmppc_gs_buff *gsb;
+ struct kvmppc_gs_msg *gsm;
+ int rc;
+
+ io = &vcpu->arch.nestedv2_io;
+ gsb = io->vcpu_run_input;
+ gsm = io->vcore_message;
+ rc = kvmppc_gsb_send_data(gsb, gsm);
+ if (rc < 0) {
+ pr_err("KVM-NESTEDv2: couldn't set guest wide elements\n");
+ return rc;
+ }
+
+ gsm = io->vcpu_message;
+ kvmppc_gsb_reset(gsb);
+ rc = kvmppc_gsm_fill_info(gsm, gsb);
+ if (rc < 0) {
+ pr_err("KVM-NESTEDv2: couldn't fill vcpu run input buffer\n");
+ return rc;
+ }
+
+ rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_HDEC_EXPIRY_TB, time_limit);
+ if (rc < 0)
+ return rc;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kvmhv_nestedv2_flush_vcpu);
+
+/**
+ * kvmhv_nestedv2_set_ptbl_entry() - send partition and process table state to
+ * L0 host
+ * @lpid: guest id
+ * @dw0: partition table double word
+ * @dw1: process table double word
+ */
+int kvmhv_nestedv2_set_ptbl_entry(unsigned long lpid, u64 dw0, u64 dw1)
+{
+ struct kvmppc_gs_part_table patbl;
+ struct kvmppc_gs_proc_table prtbl;
+ struct kvmppc_gs_buff *gsb;
+ size_t size;
+ int rc;
+
+ size = kvmppc_gse_total_size(
+ kvmppc_gsid_size(KVMPPC_GSID_PARTITION_TABLE)) +
+ kvmppc_gse_total_size(
+ kvmppc_gsid_size(KVMPPC_GSID_PROCESS_TABLE)) +
+ sizeof(struct kvmppc_gs_header);
+ gsb = kvmppc_gsb_new(size, lpid, 0, GFP_KERNEL);
+ if (!gsb)
+ return -ENOMEM;
+
+ patbl.address = dw0 & RPDB_MASK;
+ patbl.ea_bits = ((((dw0 & RTS1_MASK) >> (RTS1_SHIFT - 3)) |
+ ((dw0 & RTS2_MASK) >> RTS2_SHIFT)) +
+ 31);
+ patbl.gpd_size = 1ul << ((dw0 & RPDS_MASK) + 3);
+ rc = kvmppc_gse_put_part_table(gsb, KVMPPC_GSID_PARTITION_TABLE, patbl);
+ if (rc < 0)
+ goto free_gsb;
+
+ prtbl.address = dw1 & PRTB_MASK;
+ prtbl.gpd_size = 1ul << ((dw1 & PRTS_MASK) + 12);
+ rc = kvmppc_gse_put_proc_table(gsb, KVMPPC_GSID_PROCESS_TABLE, prtbl);
+ if (rc < 0)
+ goto free_gsb;
+
+ rc = kvmppc_gsb_send(gsb, KVMPPC_GS_FLAGS_WIDE);
+ if (rc < 0) {
+ pr_err("KVM-NESTEDv2: couldn't set the PATE\n");
+ goto free_gsb;
+ }
+
+ kvmppc_gsb_free(gsb);
+ return 0;
+
+free_gsb:
+ kvmppc_gsb_free(gsb);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(kvmhv_nestedv2_set_ptbl_entry);
+
+/**
+ * kvmhv_nestedv2_parse_output() - receive values from H_GUEST_RUN_VCPU output
+ * @vcpu: vcpu
+ *
+ * Parse the output buffer from H_GUEST_RUN_VCPU to update vcpu.
+ */
+int kvmhv_nestedv2_parse_output(struct kvm_vcpu *vcpu)
+{
+ struct kvmhv_nestedv2_io *io;
+ struct kvmppc_gs_buff *gsb;
+ struct kvmppc_gs_msg gsm;
+
+ io = &vcpu->arch.nestedv2_io;
+ gsb = io->vcpu_run_output;
+
+ vcpu->arch.fault_dar = 0;
+ vcpu->arch.fault_dsisr = 0;
+ vcpu->arch.fault_gpa = 0;
+ vcpu->arch.emul_inst = KVM_INST_FETCH_FAILED;
+
+ kvmppc_gsm_init(&gsm, &vcpu_message_ops, vcpu, 0);
+ return kvmppc_gsm_refresh_info(&gsm, gsb);
+}
+EXPORT_SYMBOL_GPL(kvmhv_nestedv2_parse_output);
+
+static void kvmhv_nestedv2_host_free(struct kvm_vcpu *vcpu,
+ struct kvmhv_nestedv2_io *io)
+{
+ kvmppc_gsm_free(io->vcpu_message);
+ kvmppc_gsm_free(io->vcore_message);
+ kvmppc_gsb_free(io->vcpu_run_input);
+ kvmppc_gsb_free(io->vcpu_run_output);
+}
+
+int __kvmhv_nestedv2_reload_ptregs(struct kvm_vcpu *vcpu, struct pt_regs *regs)
+{
+ struct kvmhv_nestedv2_io *io;
+ struct kvmppc_gs_bitmap *valids;
+ struct kvmppc_gs_buff *gsb;
+ struct kvmppc_gs_msg gsm;
+ int rc = 0;
+
+
+ io = &vcpu->arch.nestedv2_io;
+ valids = &io->valids;
+
+ gsb = io->vcpu_run_input;
+ kvmppc_gsm_init(&gsm, &vcpu_message_ops, vcpu, 0);
+
+ for (int i = 0; i < 32; i++) {
+ if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_GPR(i)))
+ kvmppc_gsm_include(&gsm, KVMPPC_GSID_GPR(i));
+ }
+
+ if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_CR))
+ kvmppc_gsm_include(&gsm, KVMPPC_GSID_CR);
+
+ if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_XER))
+ kvmppc_gsm_include(&gsm, KVMPPC_GSID_XER);
+
+ if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_CTR))
+ kvmppc_gsm_include(&gsm, KVMPPC_GSID_CTR);
+
+ if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_LR))
+ kvmppc_gsm_include(&gsm, KVMPPC_GSID_LR);
+
+ if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_NIA))
+ kvmppc_gsm_include(&gsm, KVMPPC_GSID_NIA);
+
+ rc = kvmppc_gsb_receive_data(gsb, &gsm);
+ if (rc < 0)
+ pr_err("KVM-NESTEDv2: couldn't reload ptregs\n");
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_reload_ptregs);
+
+int __kvmhv_nestedv2_mark_dirty_ptregs(struct kvm_vcpu *vcpu,
+ struct pt_regs *regs)
+{
+ for (int i = 0; i < 32; i++)
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_GPR(i));
+
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_CR);
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_XER);
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_CTR);
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LR);
+ kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_NIA);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_mark_dirty_ptregs);
+
+/**
+ * kvmhv_nestedv2_vcpu_create() - create nested vcpu for the NESTEDv2 API
+ * @vcpu: vcpu
+ * @io: NESTEDv2 nested io state
+ *
+ * Parse the output buffer from H_GUEST_RUN_VCPU to update vcpu.
+ */
+int kvmhv_nestedv2_vcpu_create(struct kvm_vcpu *vcpu,
+ struct kvmhv_nestedv2_io *io)
+{
+ long rc;
+
+ rc = plpar_guest_create_vcpu(0, vcpu->kvm->arch.lpid, vcpu->vcpu_id);
+
+ if (rc != H_SUCCESS) {
+ pr_err("KVM: Create Guest vcpu hcall failed, rc=%ld\n", rc);
+ switch (rc) {
+ case H_NOT_ENOUGH_RESOURCES:
+ case H_ABORTED:
+ return -ENOMEM;
+ case H_AUTHORITY:
+ return -EPERM;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ rc = kvmhv_nestedv2_host_create(vcpu, io);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(kvmhv_nestedv2_vcpu_create);
+
+/**
+ * kvmhv_nestedv2_vcpu_free() - free the NESTEDv2 state
+ * @vcpu: vcpu
+ * @io: NESTEDv2 nested io state
+ */
+void kvmhv_nestedv2_vcpu_free(struct kvm_vcpu *vcpu,
+ struct kvmhv_nestedv2_io *io)
+{
+ kvmhv_nestedv2_host_free(vcpu, io);
+}
+EXPORT_SYMBOL_GPL(kvmhv_nestedv2_vcpu_free);
diff --git a/arch/powerpc/kvm/book3s_hv_p9_entry.c b/arch/powerpc/kvm/book3s_hv_p9_entry.c
index 34f1db212824..34bc0a8a1288 100644
--- a/arch/powerpc/kvm/book3s_hv_p9_entry.c
+++ b/arch/powerpc/kvm/book3s_hv_p9_entry.c
@@ -305,7 +305,7 @@ static void switch_mmu_to_guest_radix(struct kvm *kvm, struct kvm_vcpu *vcpu, u6
u32 pid;
lpid = nested ? nested->shadow_lpid : kvm->arch.lpid;
- pid = vcpu->arch.pid;
+ pid = kvmppc_get_pid(vcpu);
/*
* Prior memory accesses to host PID Q3 must be completed before we
@@ -330,7 +330,7 @@ static void switch_mmu_to_guest_hpt(struct kvm *kvm, struct kvm_vcpu *vcpu, u64
int i;
lpid = kvm->arch.lpid;
- pid = vcpu->arch.pid;
+ pid = kvmppc_get_pid(vcpu);
/*
* See switch_mmu_to_guest_radix. ptesync should not be required here
diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c
index 82be6d87514b..9012acadbca8 100644
--- a/arch/powerpc/kvm/book3s_hv_ras.c
+++ b/arch/powerpc/kvm/book3s_hv_ras.c
@@ -174,14 +174,14 @@ long kvmppc_p9_realmode_hmi_handler(struct kvm_vcpu *vcpu)
ppc_md.hmi_exception_early(NULL);
out:
- if (vc->tb_offset) {
+ if (kvmppc_get_tb_offset(vcpu)) {
u64 new_tb = mftb() + vc->tb_offset;
mtspr(SPRN_TBU40, new_tb);
if ((mftb() & 0xffffff) < (new_tb & 0xffffff)) {
new_tb += 0x1000000;
mtspr(SPRN_TBU40, new_tb);
}
- vc->tb_offset_applied = vc->tb_offset;
+ vc->tb_offset_applied = kvmppc_get_tb_offset(vcpu);
}
return ret;
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 9182324dbef9..17cb75a127b0 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -776,8 +776,8 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
r = rev[i].guest_rpte | (r & (HPTE_R_R | HPTE_R_C));
r &= ~HPTE_GR_RESERVED;
}
- vcpu->arch.regs.gpr[4 + i * 2] = v;
- vcpu->arch.regs.gpr[5 + i * 2] = r;
+ kvmppc_set_gpr(vcpu, 4 + i * 2, v);
+ kvmppc_set_gpr(vcpu, 5 + i * 2, r);
}
return H_SUCCESS;
}
@@ -824,7 +824,7 @@ long kvmppc_h_clear_ref(struct kvm_vcpu *vcpu, unsigned long flags,
}
}
}
- vcpu->arch.regs.gpr[4] = gr;
+ kvmppc_set_gpr(vcpu, 4, gr);
ret = H_SUCCESS;
out:
unlock_hpte(hpte, v & ~HPTE_V_HVLOCK);
@@ -872,7 +872,7 @@ long kvmppc_h_clear_mod(struct kvm_vcpu *vcpu, unsigned long flags,
kvmppc_set_dirty_from_hpte(kvm, v, gr);
}
}
- vcpu->arch.regs.gpr[4] = gr;
+ kvmppc_set_gpr(vcpu, 4, gr);
ret = H_SUCCESS;
out:
unlock_hpte(hpte, v & ~HPTE_V_HVLOCK);
diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c
index e165bfa842bf..e42984878503 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_xics.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c
@@ -481,7 +481,7 @@ static void icp_rm_down_cppr(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
unsigned long xics_rm_h_xirr_x(struct kvm_vcpu *vcpu)
{
- vcpu->arch.regs.gpr[5] = get_tb();
+ kvmppc_set_gpr(vcpu, 5, get_tb());
return xics_rm_h_xirr(vcpu);
}
@@ -518,7 +518,7 @@ unsigned long xics_rm_h_xirr(struct kvm_vcpu *vcpu)
} while (!icp_rm_try_update(icp, old_state, new_state));
/* Return the result in GPR4 */
- vcpu->arch.regs.gpr[4] = xirr;
+ kvmppc_set_gpr(vcpu, 4, xirr);
return check_too_hard(xics, icp);
}
diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c b/arch/powerpc/kvm/book3s_hv_uvmem.c
index e2d6f9327f77..92f33115144b 100644
--- a/arch/powerpc/kvm/book3s_hv_uvmem.c
+++ b/arch/powerpc/kvm/book3s_hv_uvmem.c
@@ -858,7 +858,7 @@ unsigned long kvmppc_h_svm_init_done(struct kvm *kvm)
}
kvm->arch.secure_guest |= KVMPPC_SECURE_INIT_DONE;
- pr_info("LPID %d went secure\n", kvm->arch.lpid);
+ pr_info("LPID %lld went secure\n", kvm->arch.lpid);
out:
srcu_read_unlock(&kvm->srcu, srcu_idx);
diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c
index f4115819e738..29a382249770 100644
--- a/arch/powerpc/kvm/book3s_xive.c
+++ b/arch/powerpc/kvm/book3s_xive.c
@@ -328,7 +328,7 @@ static unsigned long xive_vm_h_xirr(struct kvm_vcpu *vcpu)
*/
/* Return interrupt and old CPPR in GPR4 */
- vcpu->arch.regs.gpr[4] = hirq | (old_cppr << 24);
+ kvmppc_set_gpr(vcpu, 4, hirq | (old_cppr << 24));
return H_SUCCESS;
}
@@ -364,7 +364,7 @@ static unsigned long xive_vm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server
hirq = xive_vm_scan_interrupts(xc, pending, scan_poll);
/* Return interrupt and old CPPR in GPR4 */
- vcpu->arch.regs.gpr[4] = hirq | (xc->cppr << 24);
+ kvmppc_set_gpr(vcpu, 4, hirq | (xc->cppr << 24));
return H_SUCCESS;
}
@@ -884,10 +884,10 @@ int kvmppc_xive_attach_escalation(struct kvm_vcpu *vcpu, u8 prio,
}
if (single_escalation)
- name = kasprintf(GFP_KERNEL, "kvm-%d-%d",
+ name = kasprintf(GFP_KERNEL, "kvm-%lld-%d",
vcpu->kvm->arch.lpid, xc->server_num);
else
- name = kasprintf(GFP_KERNEL, "kvm-%d-%d-%d",
+ name = kasprintf(GFP_KERNEL, "kvm-%lld-%d-%d",
vcpu->kvm->arch.lpid, xc->server_num, prio);
if (!name) {
pr_err("Failed to allocate escalation irq name for queue %d of VCPU %d\n",
@@ -2779,8 +2779,6 @@ static int kvmppc_xive_create(struct kvm_device *dev, u32 type)
int kvmppc_xive_xics_hcall(struct kvm_vcpu *vcpu, u32 req)
{
- struct kvmppc_vcore *vc = vcpu->arch.vcore;
-
/* The VM should have configured XICS mode before doing XICS hcalls. */
if (!kvmppc_xics_enabled(vcpu))
return H_TOO_HARD;
@@ -2799,7 +2797,7 @@ int kvmppc_xive_xics_hcall(struct kvm_vcpu *vcpu, u32 req)
return xive_vm_h_ipoll(vcpu, kvmppc_get_gpr(vcpu, 4));
case H_XIRR_X:
xive_vm_h_xirr(vcpu);
- kvmppc_set_gpr(vcpu, 5, get_tb() + vc->tb_offset);
+ kvmppc_set_gpr(vcpu, 5, get_tb() + kvmppc_get_tb_offset(vcpu));
return H_SUCCESS;
}
diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c
index 712ab91ced39..6e2ebbd8aaac 100644
--- a/arch/powerpc/kvm/book3s_xive_native.c
+++ b/arch/powerpc/kvm/book3s_xive_native.c
@@ -567,7 +567,7 @@ static int kvmppc_xive_native_set_queue_config(struct kvmppc_xive *xive,
u8 priority;
struct kvm_ppc_xive_eq kvm_eq;
int rc;
- __be32 *qaddr = 0;
+ __be32 *qaddr = NULL;
struct page *page;
struct xive_q *q;
gfn_t gfn;
diff --git a/arch/powerpc/kvm/emulate_loadstore.c b/arch/powerpc/kvm/emulate_loadstore.c
index 059c08ae0340..077fd88a0b68 100644
--- a/arch/powerpc/kvm/emulate_loadstore.c
+++ b/arch/powerpc/kvm/emulate_loadstore.c
@@ -92,7 +92,8 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
vcpu->arch.mmio_host_swabbed = 0;
emulated = EMULATE_FAIL;
- vcpu->arch.regs.msr = vcpu->arch.shared->msr;
+ vcpu->arch.regs.msr = kvmppc_get_msr(vcpu);
+ kvmhv_nestedv2_reload_ptregs(vcpu, &vcpu->arch.regs);
if (analyse_instr(&op, &vcpu->arch.regs, inst) == 0) {
int type = op.type & INSTR_TYPE_MASK;
int size = GETSIZE(op.type);
@@ -250,7 +251,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
vcpu->arch.mmio_sp64_extend = 1;
emulated = kvmppc_handle_store(vcpu,
- VCPU_FPR(vcpu, op.reg), size, 1);
+ kvmppc_get_fpr(vcpu, op.reg), size, 1);
if ((op.type & UPDATE) && (emulated != EMULATE_FAIL))
kvmppc_set_gpr(vcpu, op.update_reg, op.ea);
@@ -357,6 +358,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
}
trace_kvm_ppc_instr(ppc_inst_val(inst), kvmppc_get_pc(vcpu), emulated);
+ kvmhv_nestedv2_mark_dirty_ptregs(vcpu, &vcpu->arch.regs);
/* Advance past emulated instruction. */
if (emulated != EMULATE_FAIL)
diff --git a/arch/powerpc/kvm/guest-state-buffer.c b/arch/powerpc/kvm/guest-state-buffer.c
new file mode 100644
index 000000000000..b80dbc58621f
--- /dev/null
+++ b/arch/powerpc/kvm/guest-state-buffer.c
@@ -0,0 +1,621 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "asm/hvcall.h"
+#include <linux/log2.h>
+#include <asm/pgalloc.h>
+#include <asm/guest-state-buffer.h>
+
+static const u16 kvmppc_gse_iden_len[__KVMPPC_GSE_TYPE_MAX] = {
+ [KVMPPC_GSE_BE32] = sizeof(__be32),
+ [KVMPPC_GSE_BE64] = sizeof(__be64),
+ [KVMPPC_GSE_VEC128] = sizeof(vector128),
+ [KVMPPC_GSE_PARTITION_TABLE] = sizeof(struct kvmppc_gs_part_table),
+ [KVMPPC_GSE_PROCESS_TABLE] = sizeof(struct kvmppc_gs_proc_table),
+ [KVMPPC_GSE_BUFFER] = sizeof(struct kvmppc_gs_buff_info),
+};
+
+/**
+ * kvmppc_gsb_new() - create a new guest state buffer
+ * @size: total size of the guest state buffer (includes header)
+ * @guest_id: guest_id
+ * @vcpu_id: vcpu_id
+ * @flags: GFP flags
+ *
+ * Returns a guest state buffer.
+ */
+struct kvmppc_gs_buff *kvmppc_gsb_new(size_t size, unsigned long guest_id,
+ unsigned long vcpu_id, gfp_t flags)
+{
+ struct kvmppc_gs_buff *gsb;
+
+ gsb = kzalloc(sizeof(*gsb), flags);
+ if (!gsb)
+ return NULL;
+
+ size = roundup_pow_of_two(size);
+ gsb->hdr = kzalloc(size, GFP_KERNEL);
+ if (!gsb->hdr)
+ goto free;
+
+ gsb->capacity = size;
+ gsb->len = sizeof(struct kvmppc_gs_header);
+ gsb->vcpu_id = vcpu_id;
+ gsb->guest_id = guest_id;
+
+ gsb->hdr->nelems = cpu_to_be32(0);
+
+ return gsb;
+
+free:
+ kfree(gsb);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsb_new);
+
+/**
+ * kvmppc_gsb_free() - free a guest state buffer
+ * @gsb: guest state buffer
+ */
+void kvmppc_gsb_free(struct kvmppc_gs_buff *gsb)
+{
+ kfree(gsb->hdr);
+ kfree(gsb);
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsb_free);
+
+/**
+ * kvmppc_gsb_put() - allocate space in a guest state buffer
+ * @gsb: buffer to allocate in
+ * @size: amount of space to allocate
+ *
+ * Returns a pointer to the amount of space requested within the buffer and
+ * increments the count of elements in the buffer.
+ *
+ * Does not check if there is enough space in the buffer.
+ */
+void *kvmppc_gsb_put(struct kvmppc_gs_buff *gsb, size_t size)
+{
+ u32 nelems = kvmppc_gsb_nelems(gsb);
+ void *p;
+
+ p = (void *)kvmppc_gsb_header(gsb) + kvmppc_gsb_len(gsb);
+ gsb->len += size;
+
+ kvmppc_gsb_header(gsb)->nelems = cpu_to_be32(nelems + 1);
+ return p;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsb_put);
+
+static int kvmppc_gsid_class(u16 iden)
+{
+ if ((iden >= KVMPPC_GSE_GUESTWIDE_START) &&
+ (iden <= KVMPPC_GSE_GUESTWIDE_END))
+ return KVMPPC_GS_CLASS_GUESTWIDE;
+
+ if ((iden >= KVMPPC_GSE_META_START) && (iden <= KVMPPC_GSE_META_END))
+ return KVMPPC_GS_CLASS_META;
+
+ if ((iden >= KVMPPC_GSE_DW_REGS_START) &&
+ (iden <= KVMPPC_GSE_DW_REGS_END))
+ return KVMPPC_GS_CLASS_DWORD_REG;
+
+ if ((iden >= KVMPPC_GSE_W_REGS_START) &&
+ (iden <= KVMPPC_GSE_W_REGS_END))
+ return KVMPPC_GS_CLASS_WORD_REG;
+
+ if ((iden >= KVMPPC_GSE_VSRS_START) && (iden <= KVMPPC_GSE_VSRS_END))
+ return KVMPPC_GS_CLASS_VECTOR;
+
+ if ((iden >= KVMPPC_GSE_INTR_REGS_START) &&
+ (iden <= KVMPPC_GSE_INTR_REGS_END))
+ return KVMPPC_GS_CLASS_INTR;
+
+ return -1;
+}
+
+static int kvmppc_gsid_type(u16 iden)
+{
+ int type = -1;
+
+ switch (kvmppc_gsid_class(iden)) {
+ case KVMPPC_GS_CLASS_GUESTWIDE:
+ switch (iden) {
+ case KVMPPC_GSID_HOST_STATE_SIZE:
+ case KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE:
+ case KVMPPC_GSID_TB_OFFSET:
+ type = KVMPPC_GSE_BE64;
+ break;
+ case KVMPPC_GSID_PARTITION_TABLE:
+ type = KVMPPC_GSE_PARTITION_TABLE;
+ break;
+ case KVMPPC_GSID_PROCESS_TABLE:
+ type = KVMPPC_GSE_PROCESS_TABLE;
+ break;
+ case KVMPPC_GSID_LOGICAL_PVR:
+ type = KVMPPC_GSE_BE32;
+ break;
+ }
+ break;
+ case KVMPPC_GS_CLASS_META:
+ switch (iden) {
+ case KVMPPC_GSID_RUN_INPUT:
+ case KVMPPC_GSID_RUN_OUTPUT:
+ type = KVMPPC_GSE_BUFFER;
+ break;
+ case KVMPPC_GSID_VPA:
+ type = KVMPPC_GSE_BE64;
+ break;
+ }
+ break;
+ case KVMPPC_GS_CLASS_DWORD_REG:
+ type = KVMPPC_GSE_BE64;
+ break;
+ case KVMPPC_GS_CLASS_WORD_REG:
+ type = KVMPPC_GSE_BE32;
+ break;
+ case KVMPPC_GS_CLASS_VECTOR:
+ type = KVMPPC_GSE_VEC128;
+ break;
+ case KVMPPC_GS_CLASS_INTR:
+ switch (iden) {
+ case KVMPPC_GSID_HDAR:
+ case KVMPPC_GSID_ASDR:
+ case KVMPPC_GSID_HEIR:
+ type = KVMPPC_GSE_BE64;
+ break;
+ case KVMPPC_GSID_HDSISR:
+ type = KVMPPC_GSE_BE32;
+ break;
+ }
+ break;
+ }
+
+ return type;
+}
+
+/**
+ * kvmppc_gsid_flags() - the flags for a guest state ID
+ * @iden: guest state ID
+ *
+ * Returns any flags for the guest state ID.
+ */
+unsigned long kvmppc_gsid_flags(u16 iden)
+{
+ unsigned long flags = 0;
+
+ switch (kvmppc_gsid_class(iden)) {
+ case KVMPPC_GS_CLASS_GUESTWIDE:
+ flags = KVMPPC_GS_FLAGS_WIDE;
+ break;
+ case KVMPPC_GS_CLASS_META:
+ case KVMPPC_GS_CLASS_DWORD_REG:
+ case KVMPPC_GS_CLASS_WORD_REG:
+ case KVMPPC_GS_CLASS_VECTOR:
+ case KVMPPC_GS_CLASS_INTR:
+ break;
+ }
+
+ return flags;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsid_flags);
+
+/**
+ * kvmppc_gsid_size() - the size of a guest state ID
+ * @iden: guest state ID
+ *
+ * Returns the size of guest state ID.
+ */
+u16 kvmppc_gsid_size(u16 iden)
+{
+ int type;
+
+ type = kvmppc_gsid_type(iden);
+ if (type == -1)
+ return 0;
+
+ if (type >= __KVMPPC_GSE_TYPE_MAX)
+ return 0;
+
+ return kvmppc_gse_iden_len[type];
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsid_size);
+
+/**
+ * kvmppc_gsid_mask() - the settable bits of a guest state ID
+ * @iden: guest state ID
+ *
+ * Returns a mask of settable bits for a guest state ID.
+ */
+u64 kvmppc_gsid_mask(u16 iden)
+{
+ u64 mask = ~0ull;
+
+ switch (iden) {
+ case KVMPPC_GSID_LPCR:
+ mask = LPCR_DPFD | LPCR_ILE | LPCR_AIL | LPCR_LD | LPCR_MER |
+ LPCR_GTSE;
+ break;
+ case KVMPPC_GSID_MSR:
+ mask = ~(MSR_HV | MSR_S | MSR_ME);
+ break;
+ }
+
+ return mask;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsid_mask);
+
+/**
+ * __kvmppc_gse_put() - add a guest state element to a buffer
+ * @gsb: buffer to the element to
+ * @iden: guest state ID
+ * @size: length of data
+ * @data: pointer to data
+ */
+int __kvmppc_gse_put(struct kvmppc_gs_buff *gsb, u16 iden, u16 size,
+ const void *data)
+{
+ struct kvmppc_gs_elem *gse;
+ u16 total_size;
+
+ total_size = sizeof(*gse) + size;
+ if (total_size + kvmppc_gsb_len(gsb) > kvmppc_gsb_capacity(gsb))
+ return -ENOMEM;
+
+ if (kvmppc_gsid_size(iden) != size)
+ return -EINVAL;
+
+ gse = kvmppc_gsb_put(gsb, total_size);
+ gse->iden = cpu_to_be16(iden);
+ gse->len = cpu_to_be16(size);
+ memcpy(gse->data, data, size);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__kvmppc_gse_put);
+
+/**
+ * kvmppc_gse_parse() - create a parse map from a guest state buffer
+ * @gsp: guest state parser
+ * @gsb: guest state buffer
+ */
+int kvmppc_gse_parse(struct kvmppc_gs_parser *gsp, struct kvmppc_gs_buff *gsb)
+{
+ struct kvmppc_gs_elem *curr;
+ int rem, i;
+
+ kvmppc_gsb_for_each_elem(i, curr, gsb, rem) {
+ if (kvmppc_gse_len(curr) !=
+ kvmppc_gsid_size(kvmppc_gse_iden(curr)))
+ return -EINVAL;
+ kvmppc_gsp_insert(gsp, kvmppc_gse_iden(curr), curr);
+ }
+
+ if (kvmppc_gsb_nelems(gsb) != i)
+ return -EINVAL;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gse_parse);
+
+static inline int kvmppc_gse_flatten_iden(u16 iden)
+{
+ int bit = 0;
+ int class;
+
+ class = kvmppc_gsid_class(iden);
+
+ if (class == KVMPPC_GS_CLASS_GUESTWIDE) {
+ bit += iden - KVMPPC_GSE_GUESTWIDE_START;
+ return bit;
+ }
+
+ bit += KVMPPC_GSE_GUESTWIDE_COUNT;
+
+ if (class == KVMPPC_GS_CLASS_META) {
+ bit += iden - KVMPPC_GSE_META_START;
+ return bit;
+ }
+
+ bit += KVMPPC_GSE_META_COUNT;
+
+ if (class == KVMPPC_GS_CLASS_DWORD_REG) {
+ bit += iden - KVMPPC_GSE_DW_REGS_START;
+ return bit;
+ }
+
+ bit += KVMPPC_GSE_DW_REGS_COUNT;
+
+ if (class == KVMPPC_GS_CLASS_WORD_REG) {
+ bit += iden - KVMPPC_GSE_W_REGS_START;
+ return bit;
+ }
+
+ bit += KVMPPC_GSE_W_REGS_COUNT;
+
+ if (class == KVMPPC_GS_CLASS_VECTOR) {
+ bit += iden - KVMPPC_GSE_VSRS_START;
+ return bit;
+ }
+
+ bit += KVMPPC_GSE_VSRS_COUNT;
+
+ if (class == KVMPPC_GS_CLASS_INTR) {
+ bit += iden - KVMPPC_GSE_INTR_REGS_START;
+ return bit;
+ }
+
+ return 0;
+}
+
+static inline u16 kvmppc_gse_unflatten_iden(int bit)
+{
+ u16 iden;
+
+ if (bit < KVMPPC_GSE_GUESTWIDE_COUNT) {
+ iden = KVMPPC_GSE_GUESTWIDE_START + bit;
+ return iden;
+ }
+ bit -= KVMPPC_GSE_GUESTWIDE_COUNT;
+
+ if (bit < KVMPPC_GSE_META_COUNT) {
+ iden = KVMPPC_GSE_META_START + bit;
+ return iden;
+ }
+ bit -= KVMPPC_GSE_META_COUNT;
+
+ if (bit < KVMPPC_GSE_DW_REGS_COUNT) {
+ iden = KVMPPC_GSE_DW_REGS_START + bit;
+ return iden;
+ }
+ bit -= KVMPPC_GSE_DW_REGS_COUNT;
+
+ if (bit < KVMPPC_GSE_W_REGS_COUNT) {
+ iden = KVMPPC_GSE_W_REGS_START + bit;
+ return iden;
+ }
+ bit -= KVMPPC_GSE_W_REGS_COUNT;
+
+ if (bit < KVMPPC_GSE_VSRS_COUNT) {
+ iden = KVMPPC_GSE_VSRS_START + bit;
+ return iden;
+ }
+ bit -= KVMPPC_GSE_VSRS_COUNT;
+
+ if (bit < KVMPPC_GSE_IDEN_COUNT) {
+ iden = KVMPPC_GSE_INTR_REGS_START + bit;
+ return iden;
+ }
+
+ return 0;
+}
+
+/**
+ * kvmppc_gsp_insert() - add a mapping from an guest state ID to an element
+ * @gsp: guest state parser
+ * @iden: guest state id (key)
+ * @gse: guest state element (value)
+ */
+void kvmppc_gsp_insert(struct kvmppc_gs_parser *gsp, u16 iden,
+ struct kvmppc_gs_elem *gse)
+{
+ int i;
+
+ i = kvmppc_gse_flatten_iden(iden);
+ kvmppc_gsbm_set(&gsp->iterator, iden);
+ gsp->gses[i] = gse;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsp_insert);
+
+/**
+ * kvmppc_gsp_lookup() - lookup an element from a guest state ID
+ * @gsp: guest state parser
+ * @iden: guest state ID (key)
+ *
+ * Returns the guest state element if present.
+ */
+struct kvmppc_gs_elem *kvmppc_gsp_lookup(struct kvmppc_gs_parser *gsp, u16 iden)
+{
+ int i;
+
+ i = kvmppc_gse_flatten_iden(iden);
+ return gsp->gses[i];
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsp_lookup);
+
+/**
+ * kvmppc_gsbm_set() - set the guest state ID
+ * @gsbm: guest state bitmap
+ * @iden: guest state ID
+ */
+void kvmppc_gsbm_set(struct kvmppc_gs_bitmap *gsbm, u16 iden)
+{
+ set_bit(kvmppc_gse_flatten_iden(iden), gsbm->bitmap);
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsbm_set);
+
+/**
+ * kvmppc_gsbm_clear() - clear the guest state ID
+ * @gsbm: guest state bitmap
+ * @iden: guest state ID
+ */
+void kvmppc_gsbm_clear(struct kvmppc_gs_bitmap *gsbm, u16 iden)
+{
+ clear_bit(kvmppc_gse_flatten_iden(iden), gsbm->bitmap);
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsbm_clear);
+
+/**
+ * kvmppc_gsbm_test() - test the guest state ID
+ * @gsbm: guest state bitmap
+ * @iden: guest state ID
+ */
+bool kvmppc_gsbm_test(struct kvmppc_gs_bitmap *gsbm, u16 iden)
+{
+ return test_bit(kvmppc_gse_flatten_iden(iden), gsbm->bitmap);
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsbm_test);
+
+/**
+ * kvmppc_gsbm_next() - return the next set guest state ID
+ * @gsbm: guest state bitmap
+ * @prev: last guest state ID
+ */
+u16 kvmppc_gsbm_next(struct kvmppc_gs_bitmap *gsbm, u16 prev)
+{
+ int bit, pbit;
+
+ pbit = prev ? kvmppc_gse_flatten_iden(prev) + 1 : 0;
+ bit = find_next_bit(gsbm->bitmap, KVMPPC_GSE_IDEN_COUNT, pbit);
+
+ if (bit < KVMPPC_GSE_IDEN_COUNT)
+ return kvmppc_gse_unflatten_iden(bit);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsbm_next);
+
+/**
+ * kvmppc_gsm_init() - initialize a guest state message
+ * @gsm: guest state message
+ * @ops: callbacks
+ * @data: private data
+ * @flags: guest wide or thread wide
+ */
+int kvmppc_gsm_init(struct kvmppc_gs_msg *gsm, struct kvmppc_gs_msg_ops *ops,
+ void *data, unsigned long flags)
+{
+ memset(gsm, 0, sizeof(*gsm));
+ gsm->ops = ops;
+ gsm->data = data;
+ gsm->flags = flags;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsm_init);
+
+/**
+ * kvmppc_gsm_new() - creates a new guest state message
+ * @ops: callbacks
+ * @data: private data
+ * @flags: guest wide or thread wide
+ * @gfp_flags: GFP allocation flags
+ *
+ * Returns an initialized guest state message.
+ */
+struct kvmppc_gs_msg *kvmppc_gsm_new(struct kvmppc_gs_msg_ops *ops, void *data,
+ unsigned long flags, gfp_t gfp_flags)
+{
+ struct kvmppc_gs_msg *gsm;
+
+ gsm = kzalloc(sizeof(*gsm), gfp_flags);
+ if (!gsm)
+ return NULL;
+
+ kvmppc_gsm_init(gsm, ops, data, flags);
+
+ return gsm;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsm_new);
+
+/**
+ * kvmppc_gsm_size() - creates a new guest state message
+ * @gsm: self
+ *
+ * Returns the size required for the message.
+ */
+size_t kvmppc_gsm_size(struct kvmppc_gs_msg *gsm)
+{
+ if (gsm->ops->get_size)
+ return gsm->ops->get_size(gsm);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsm_size);
+
+/**
+ * kvmppc_gsm_free() - free guest state message
+ * @gsm: guest state message
+ *
+ * Returns the size required for the message.
+ */
+void kvmppc_gsm_free(struct kvmppc_gs_msg *gsm)
+{
+ kfree(gsm);
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsm_free);
+
+/**
+ * kvmppc_gsm_fill_info() - serialises message to guest state buffer format
+ * @gsm: self
+ * @gsb: buffer to serialise into
+ */
+int kvmppc_gsm_fill_info(struct kvmppc_gs_msg *gsm, struct kvmppc_gs_buff *gsb)
+{
+ if (!gsm->ops->fill_info)
+ return -EINVAL;
+
+ return gsm->ops->fill_info(gsb, gsm);
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsm_fill_info);
+
+/**
+ * kvmppc_gsm_refresh_info() - deserialises from guest state buffer
+ * @gsm: self
+ * @gsb: buffer to serialise from
+ */
+int kvmppc_gsm_refresh_info(struct kvmppc_gs_msg *gsm,
+ struct kvmppc_gs_buff *gsb)
+{
+ if (!gsm->ops->fill_info)
+ return -EINVAL;
+
+ return gsm->ops->refresh_info(gsm, gsb);
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsm_refresh_info);
+
+/**
+ * kvmppc_gsb_send - send all elements in the buffer to the hypervisor.
+ * @gsb: guest state buffer
+ * @flags: guest wide or thread wide
+ *
+ * Performs the H_GUEST_SET_STATE hcall for the guest state buffer.
+ */
+int kvmppc_gsb_send(struct kvmppc_gs_buff *gsb, unsigned long flags)
+{
+ unsigned long hflags = 0;
+ unsigned long i;
+ int rc;
+
+ if (kvmppc_gsb_nelems(gsb) == 0)
+ return 0;
+
+ if (flags & KVMPPC_GS_FLAGS_WIDE)
+ hflags |= H_GUEST_FLAGS_WIDE;
+
+ rc = plpar_guest_set_state(hflags, gsb->guest_id, gsb->vcpu_id,
+ __pa(gsb->hdr), gsb->capacity, &i);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsb_send);
+
+/**
+ * kvmppc_gsb_recv - request all elements in the buffer have their value
+ * updated.
+ * @gsb: guest state buffer
+ * @flags: guest wide or thread wide
+ *
+ * Performs the H_GUEST_GET_STATE hcall for the guest state buffer.
+ * After returning from the hcall the guest state elements that were
+ * present in the buffer will have updated values from the hypervisor.
+ */
+int kvmppc_gsb_recv(struct kvmppc_gs_buff *gsb, unsigned long flags)
+{
+ unsigned long hflags = 0;
+ unsigned long i;
+ int rc;
+
+ if (flags & KVMPPC_GS_FLAGS_WIDE)
+ hflags |= H_GUEST_FLAGS_WIDE;
+
+ rc = plpar_guest_get_state(hflags, gsb->guest_id, gsb->vcpu_id,
+ __pa(gsb->hdr), gsb->capacity, &i);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gsb_recv);
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 7197c8256668..f6af752698d0 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -934,11 +934,11 @@ static inline void kvmppc_set_vsr_dword(struct kvm_vcpu *vcpu,
return;
if (index >= 32) {
- val.vval = VCPU_VSX_VR(vcpu, index - 32);
+ kvmppc_get_vsx_vr(vcpu, index - 32, &val.vval);
val.vsxval[offset] = gpr;
- VCPU_VSX_VR(vcpu, index - 32) = val.vval;
+ kvmppc_set_vsx_vr(vcpu, index - 32, &val.vval);
} else {
- VCPU_VSX_FPR(vcpu, index, offset) = gpr;
+ kvmppc_set_vsx_fpr(vcpu, index, offset, gpr);
}
}
@@ -949,13 +949,13 @@ static inline void kvmppc_set_vsr_dword_dump(struct kvm_vcpu *vcpu,
int index = vcpu->arch.io_gpr & KVM_MMIO_REG_MASK;
if (index >= 32) {
- val.vval = VCPU_VSX_VR(vcpu, index - 32);
+ kvmppc_get_vsx_vr(vcpu, index - 32, &val.vval);
val.vsxval[0] = gpr;
val.vsxval[1] = gpr;
- VCPU_VSX_VR(vcpu, index - 32) = val.vval;
+ kvmppc_set_vsx_vr(vcpu, index - 32, &val.vval);
} else {
- VCPU_VSX_FPR(vcpu, index, 0) = gpr;
- VCPU_VSX_FPR(vcpu, index, 1) = gpr;
+ kvmppc_set_vsx_fpr(vcpu, index, 0, gpr);
+ kvmppc_set_vsx_fpr(vcpu, index, 1, gpr);
}
}
@@ -970,12 +970,12 @@ static inline void kvmppc_set_vsr_word_dump(struct kvm_vcpu *vcpu,
val.vsx32val[1] = gpr;
val.vsx32val[2] = gpr;
val.vsx32val[3] = gpr;
- VCPU_VSX_VR(vcpu, index - 32) = val.vval;
+ kvmppc_set_vsx_vr(vcpu, index - 32, &val.vval);
} else {
val.vsx32val[0] = gpr;
val.vsx32val[1] = gpr;
- VCPU_VSX_FPR(vcpu, index, 0) = val.vsxval[0];
- VCPU_VSX_FPR(vcpu, index, 1) = val.vsxval[0];
+ kvmppc_set_vsx_fpr(vcpu, index, 0, val.vsxval[0]);
+ kvmppc_set_vsx_fpr(vcpu, index, 1, val.vsxval[0]);
}
}
@@ -991,15 +991,15 @@ static inline void kvmppc_set_vsr_word(struct kvm_vcpu *vcpu,
return;
if (index >= 32) {
- val.vval = VCPU_VSX_VR(vcpu, index - 32);
+ kvmppc_get_vsx_vr(vcpu, index - 32, &val.vval);
val.vsx32val[offset] = gpr32;
- VCPU_VSX_VR(vcpu, index - 32) = val.vval;
+ kvmppc_set_vsx_vr(vcpu, index - 32, &val.vval);
} else {
dword_offset = offset / 2;
word_offset = offset % 2;
- val.vsxval[0] = VCPU_VSX_FPR(vcpu, index, dword_offset);
+ val.vsxval[0] = kvmppc_get_vsx_fpr(vcpu, index, dword_offset);
val.vsx32val[word_offset] = gpr32;
- VCPU_VSX_FPR(vcpu, index, dword_offset) = val.vsxval[0];
+ kvmppc_set_vsx_fpr(vcpu, index, dword_offset, val.vsxval[0]);
}
}
#endif /* CONFIG_VSX */
@@ -1058,9 +1058,9 @@ static inline void kvmppc_set_vmx_dword(struct kvm_vcpu *vcpu,
if (offset == -1)
return;
- val.vval = VCPU_VSX_VR(vcpu, index);
+ kvmppc_get_vsx_vr(vcpu, index, &val.vval);
val.vsxval[offset] = gpr;
- VCPU_VSX_VR(vcpu, index) = val.vval;
+ kvmppc_set_vsx_vr(vcpu, index, &val.vval);
}
static inline void kvmppc_set_vmx_word(struct kvm_vcpu *vcpu,
@@ -1074,9 +1074,9 @@ static inline void kvmppc_set_vmx_word(struct kvm_vcpu *vcpu,
if (offset == -1)
return;
- val.vval = VCPU_VSX_VR(vcpu, index);
+ kvmppc_get_vsx_vr(vcpu, index, &val.vval);
val.vsx32val[offset] = gpr32;
- VCPU_VSX_VR(vcpu, index) = val.vval;
+ kvmppc_set_vsx_vr(vcpu, index, &val.vval);
}
static inline void kvmppc_set_vmx_hword(struct kvm_vcpu *vcpu,
@@ -1090,9 +1090,9 @@ static inline void kvmppc_set_vmx_hword(struct kvm_vcpu *vcpu,
if (offset == -1)
return;
- val.vval = VCPU_VSX_VR(vcpu, index);
+ kvmppc_get_vsx_vr(vcpu, index, &val.vval);
val.vsx16val[offset] = gpr16;
- VCPU_VSX_VR(vcpu, index) = val.vval;
+ kvmppc_set_vsx_vr(vcpu, index, &val.vval);
}
static inline void kvmppc_set_vmx_byte(struct kvm_vcpu *vcpu,
@@ -1106,9 +1106,9 @@ static inline void kvmppc_set_vmx_byte(struct kvm_vcpu *vcpu,
if (offset == -1)
return;
- val.vval = VCPU_VSX_VR(vcpu, index);
+ kvmppc_get_vsx_vr(vcpu, index, &val.vval);
val.vsx8val[offset] = gpr8;
- VCPU_VSX_VR(vcpu, index) = val.vval;
+ kvmppc_set_vsx_vr(vcpu, index, &val.vval);
}
#endif /* CONFIG_ALTIVEC */
@@ -1194,14 +1194,14 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu)
if (vcpu->kvm->arch.kvm_ops->giveup_ext)
vcpu->kvm->arch.kvm_ops->giveup_ext(vcpu, MSR_FP);
- VCPU_FPR(vcpu, vcpu->arch.io_gpr & KVM_MMIO_REG_MASK) = gpr;
+ kvmppc_set_fpr(vcpu, vcpu->arch.io_gpr & KVM_MMIO_REG_MASK, gpr);
break;
#ifdef CONFIG_PPC_BOOK3S
case KVM_MMIO_REG_QPR:
vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr;
break;
case KVM_MMIO_REG_FQPR:
- VCPU_FPR(vcpu, vcpu->arch.io_gpr & KVM_MMIO_REG_MASK) = gpr;
+ kvmppc_set_fpr(vcpu, vcpu->arch.io_gpr & KVM_MMIO_REG_MASK, gpr);
vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr;
break;
#endif
@@ -1419,9 +1419,9 @@ static inline int kvmppc_get_vsr_data(struct kvm_vcpu *vcpu, int rs, u64 *val)
}
if (rs < 32) {
- *val = VCPU_VSX_FPR(vcpu, rs, vsx_offset);
+ *val = kvmppc_get_vsx_fpr(vcpu, rs, vsx_offset);
} else {
- reg.vval = VCPU_VSX_VR(vcpu, rs - 32);
+ kvmppc_get_vsx_vr(vcpu, rs - 32, &reg.vval);
*val = reg.vsxval[vsx_offset];
}
break;
@@ -1438,10 +1438,10 @@ static inline int kvmppc_get_vsr_data(struct kvm_vcpu *vcpu, int rs, u64 *val)
if (rs < 32) {
dword_offset = vsx_offset / 2;
word_offset = vsx_offset % 2;
- reg.vsxval[0] = VCPU_VSX_FPR(vcpu, rs, dword_offset);
+ reg.vsxval[0] = kvmppc_get_vsx_fpr(vcpu, rs, dword_offset);
*val = reg.vsx32val[word_offset];
} else {
- reg.vval = VCPU_VSX_VR(vcpu, rs - 32);
+ kvmppc_get_vsx_vr(vcpu, rs - 32, &reg.vval);
*val = reg.vsx32val[vsx_offset];
}
break;
@@ -1556,7 +1556,7 @@ static int kvmppc_get_vmx_dword(struct kvm_vcpu *vcpu, int index, u64 *val)
if (vmx_offset == -1)
return -1;
- reg.vval = VCPU_VSX_VR(vcpu, index);
+ kvmppc_get_vsx_vr(vcpu, index, &reg.vval);
*val = reg.vsxval[vmx_offset];
return result;
@@ -1574,7 +1574,7 @@ static int kvmppc_get_vmx_word(struct kvm_vcpu *vcpu, int index, u64 *val)
if (vmx_offset == -1)
return -1;
- reg.vval = VCPU_VSX_VR(vcpu, index);
+ kvmppc_get_vsx_vr(vcpu, index, &reg.vval);
*val = reg.vsx32val[vmx_offset];
return result;
@@ -1592,7 +1592,7 @@ static int kvmppc_get_vmx_hword(struct kvm_vcpu *vcpu, int index, u64 *val)
if (vmx_offset == -1)
return -1;
- reg.vval = VCPU_VSX_VR(vcpu, index);
+ kvmppc_get_vsx_vr(vcpu, index, &reg.vval);
*val = reg.vsx16val[vmx_offset];
return result;
@@ -1610,7 +1610,7 @@ static int kvmppc_get_vmx_byte(struct kvm_vcpu *vcpu, int index, u64 *val)
if (vmx_offset == -1)
return -1;
- reg.vval = VCPU_VSX_VR(vcpu, index);
+ kvmppc_get_vsx_vr(vcpu, index, &reg.vval);
*val = reg.vsx8val[vmx_offset];
return result;
@@ -1719,17 +1719,17 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
r = -ENXIO;
break;
}
- val.vval = vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0];
+ kvmppc_get_vsx_vr(vcpu, reg->id - KVM_REG_PPC_VR0, &val.vval);
break;
case KVM_REG_PPC_VSCR:
if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
r = -ENXIO;
break;
}
- val = get_reg_val(reg->id, vcpu->arch.vr.vscr.u[3]);
+ val = get_reg_val(reg->id, kvmppc_get_vscr(vcpu));
break;
case KVM_REG_PPC_VRSAVE:
- val = get_reg_val(reg->id, vcpu->arch.vrsave);
+ val = get_reg_val(reg->id, kvmppc_get_vrsave(vcpu));
break;
#endif /* CONFIG_ALTIVEC */
default:
@@ -1770,21 +1770,21 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
r = -ENXIO;
break;
}
- vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
+ kvmppc_set_vsx_vr(vcpu, reg->id - KVM_REG_PPC_VR0, &val.vval);
break;
case KVM_REG_PPC_VSCR:
if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
r = -ENXIO;
break;
}
- vcpu->arch.vr.vscr.u[3] = set_reg_val(reg->id, val);
+ kvmppc_set_vscr(vcpu, set_reg_val(reg->id, val));
break;
case KVM_REG_PPC_VRSAVE:
if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
r = -ENXIO;
break;
}
- vcpu->arch.vrsave = set_reg_val(reg->id, val);
+ kvmppc_set_vrsave(vcpu, set_reg_val(reg->id, val));
break;
#endif /* CONFIG_ALTIVEC */
default:
diff --git a/arch/powerpc/kvm/test-guest-state-buffer.c b/arch/powerpc/kvm/test-guest-state-buffer.c
new file mode 100644
index 000000000000..4720b8dc8837
--- /dev/null
+++ b/arch/powerpc/kvm/test-guest-state-buffer.c
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/init.h>
+#include <linux/log2.h>
+#include <kunit/test.h>
+
+#include <asm/guest-state-buffer.h>
+
+static void test_creating_buffer(struct kunit *test)
+{
+ struct kvmppc_gs_buff *gsb;
+ size_t size = 0x100;
+
+ gsb = kvmppc_gsb_new(size, 0, 0, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb);
+
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb->hdr);
+
+ KUNIT_EXPECT_EQ(test, gsb->capacity, roundup_pow_of_two(size));
+ KUNIT_EXPECT_EQ(test, gsb->len, sizeof(__be32));
+
+ kvmppc_gsb_free(gsb);
+}
+
+static void test_adding_element(struct kunit *test)
+{
+ const struct kvmppc_gs_elem *head, *curr;
+ union {
+ __vector128 v;
+ u64 dw[2];
+ } u;
+ int rem;
+ struct kvmppc_gs_buff *gsb;
+ size_t size = 0x1000;
+ int i, rc;
+ u64 data;
+
+ gsb = kvmppc_gsb_new(size, 0, 0, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb);
+
+ /* Single elements, direct use of __kvmppc_gse_put() */
+ data = 0xdeadbeef;
+ rc = __kvmppc_gse_put(gsb, KVMPPC_GSID_GPR(0), 8, &data);
+ KUNIT_EXPECT_GE(test, rc, 0);
+
+ head = kvmppc_gsb_data(gsb);
+ KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(head), KVMPPC_GSID_GPR(0));
+ KUNIT_EXPECT_EQ(test, kvmppc_gse_len(head), 8);
+ data = 0;
+ memcpy(&data, kvmppc_gse_data(head), 8);
+ KUNIT_EXPECT_EQ(test, data, 0xdeadbeef);
+
+ /* Multiple elements, simple wrapper */
+ rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_GPR(1), 0xcafef00d);
+ KUNIT_EXPECT_GE(test, rc, 0);
+
+ u.dw[0] = 0x1;
+ u.dw[1] = 0x2;
+ rc = kvmppc_gse_put_vector128(gsb, KVMPPC_GSID_VSRS(0), &u.v);
+ KUNIT_EXPECT_GE(test, rc, 0);
+ u.dw[0] = 0x0;
+ u.dw[1] = 0x0;
+
+ kvmppc_gsb_for_each_elem(i, curr, gsb, rem) {
+ switch (i) {
+ case 0:
+ KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(curr),
+ KVMPPC_GSID_GPR(0));
+ KUNIT_EXPECT_EQ(test, kvmppc_gse_len(curr), 8);
+ KUNIT_EXPECT_EQ(test, kvmppc_gse_get_be64(curr),
+ 0xdeadbeef);
+ break;
+ case 1:
+ KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(curr),
+ KVMPPC_GSID_GPR(1));
+ KUNIT_EXPECT_EQ(test, kvmppc_gse_len(curr), 8);
+ KUNIT_EXPECT_EQ(test, kvmppc_gse_get_u64(curr),
+ 0xcafef00d);
+ break;
+ case 2:
+ KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(curr),
+ KVMPPC_GSID_VSRS(0));
+ KUNIT_EXPECT_EQ(test, kvmppc_gse_len(curr), 16);
+ kvmppc_gse_get_vector128(curr, &u.v);
+ KUNIT_EXPECT_EQ(test, u.dw[0], 0x1);
+ KUNIT_EXPECT_EQ(test, u.dw[1], 0x2);
+ break;
+ }
+ }
+ KUNIT_EXPECT_EQ(test, i, 3);
+
+ kvmppc_gsb_reset(gsb);
+ KUNIT_EXPECT_EQ(test, kvmppc_gsb_nelems(gsb), 0);
+ KUNIT_EXPECT_EQ(test, kvmppc_gsb_len(gsb),
+ sizeof(struct kvmppc_gs_header));
+
+ kvmppc_gsb_free(gsb);
+}
+
+static void test_gs_parsing(struct kunit *test)
+{
+ struct kvmppc_gs_elem *gse;
+ struct kvmppc_gs_parser gsp = { 0 };
+ struct kvmppc_gs_buff *gsb;
+ size_t size = 0x1000;
+ u64 tmp1, tmp2;
+
+ gsb = kvmppc_gsb_new(size, 0, 0, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb);
+
+ tmp1 = 0xdeadbeefull;
+ kvmppc_gse_put_u64(gsb, KVMPPC_GSID_GPR(0), tmp1);
+
+ KUNIT_EXPECT_GE(test, kvmppc_gse_parse(&gsp, gsb), 0);
+
+ gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_GPR(0));
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gse);
+
+ tmp2 = kvmppc_gse_get_u64(gse);
+ KUNIT_EXPECT_EQ(test, tmp2, 0xdeadbeefull);
+
+ kvmppc_gsb_free(gsb);
+}
+
+static void test_gs_bitmap(struct kunit *test)
+{
+ struct kvmppc_gs_bitmap gsbm = { 0 };
+ struct kvmppc_gs_bitmap gsbm1 = { 0 };
+ struct kvmppc_gs_bitmap gsbm2 = { 0 };
+ u16 iden;
+ int i, j;
+
+ i = 0;
+ for (u16 iden = KVMPPC_GSID_HOST_STATE_SIZE;
+ iden <= KVMPPC_GSID_PROCESS_TABLE; iden++) {
+ kvmppc_gsbm_set(&gsbm, iden);
+ kvmppc_gsbm_set(&gsbm1, iden);
+ KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
+ kvmppc_gsbm_clear(&gsbm, iden);
+ KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
+ i++;
+ }
+
+ for (u16 iden = KVMPPC_GSID_RUN_INPUT; iden <= KVMPPC_GSID_VPA;
+ iden++) {
+ kvmppc_gsbm_set(&gsbm, iden);
+ kvmppc_gsbm_set(&gsbm1, iden);
+ KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
+ kvmppc_gsbm_clear(&gsbm, iden);
+ KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
+ i++;
+ }
+
+ for (u16 iden = KVMPPC_GSID_GPR(0); iden <= KVMPPC_GSID_CTRL; iden++) {
+ kvmppc_gsbm_set(&gsbm, iden);
+ kvmppc_gsbm_set(&gsbm1, iden);
+ KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
+ kvmppc_gsbm_clear(&gsbm, iden);
+ KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
+ i++;
+ }
+
+ for (u16 iden = KVMPPC_GSID_CR; iden <= KVMPPC_GSID_PSPB; iden++) {
+ kvmppc_gsbm_set(&gsbm, iden);
+ kvmppc_gsbm_set(&gsbm1, iden);
+ KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
+ kvmppc_gsbm_clear(&gsbm, iden);
+ KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
+ i++;
+ }
+
+ for (u16 iden = KVMPPC_GSID_VSRS(0); iden <= KVMPPC_GSID_VSRS(63);
+ iden++) {
+ kvmppc_gsbm_set(&gsbm, iden);
+ kvmppc_gsbm_set(&gsbm1, iden);
+ KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
+ kvmppc_gsbm_clear(&gsbm, iden);
+ KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
+ i++;
+ }
+
+ for (u16 iden = KVMPPC_GSID_HDAR; iden <= KVMPPC_GSID_ASDR; iden++) {
+ kvmppc_gsbm_set(&gsbm, iden);
+ kvmppc_gsbm_set(&gsbm1, iden);
+ KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
+ kvmppc_gsbm_clear(&gsbm, iden);
+ KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
+ i++;
+ }
+
+ j = 0;
+ kvmppc_gsbm_for_each(&gsbm1, iden)
+ {
+ kvmppc_gsbm_set(&gsbm2, iden);
+ j++;
+ }
+ KUNIT_EXPECT_EQ(test, i, j);
+ KUNIT_EXPECT_MEMEQ(test, &gsbm1, &gsbm2, sizeof(gsbm1));
+}
+
+struct kvmppc_gs_msg_test1_data {
+ u64 a;
+ u32 b;
+ struct kvmppc_gs_part_table c;
+ struct kvmppc_gs_proc_table d;
+ struct kvmppc_gs_buff_info e;
+};
+
+static size_t test1_get_size(struct kvmppc_gs_msg *gsm)
+{
+ size_t size = 0;
+ u16 ids[] = {
+ KVMPPC_GSID_PARTITION_TABLE,
+ KVMPPC_GSID_PROCESS_TABLE,
+ KVMPPC_GSID_RUN_INPUT,
+ KVMPPC_GSID_GPR(0),
+ KVMPPC_GSID_CR,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(ids); i++)
+ size += kvmppc_gse_total_size(kvmppc_gsid_size(ids[i]));
+ return size;
+}
+
+static int test1_fill_info(struct kvmppc_gs_buff *gsb,
+ struct kvmppc_gs_msg *gsm)
+{
+ struct kvmppc_gs_msg_test1_data *data = gsm->data;
+
+ if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_GPR(0)))
+ kvmppc_gse_put_u64(gsb, KVMPPC_GSID_GPR(0), data->a);
+
+ if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_CR))
+ kvmppc_gse_put_u32(gsb, KVMPPC_GSID_CR, data->b);
+
+ if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_PARTITION_TABLE))
+ kvmppc_gse_put_part_table(gsb, KVMPPC_GSID_PARTITION_TABLE,
+ data->c);
+
+ if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_PROCESS_TABLE))
+ kvmppc_gse_put_proc_table(gsb, KVMPPC_GSID_PARTITION_TABLE,
+ data->d);
+
+ if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_INPUT))
+ kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_INPUT, data->e);
+
+ return 0;
+}
+
+static int test1_refresh_info(struct kvmppc_gs_msg *gsm,
+ struct kvmppc_gs_buff *gsb)
+{
+ struct kvmppc_gs_parser gsp = { 0 };
+ struct kvmppc_gs_msg_test1_data *data = gsm->data;
+ struct kvmppc_gs_elem *gse;
+ int rc;
+
+ rc = kvmppc_gse_parse(&gsp, gsb);
+ if (rc < 0)
+ return rc;
+
+ gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_GPR(0));
+ if (gse)
+ data->a = kvmppc_gse_get_u64(gse);
+
+ gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_CR);
+ if (gse)
+ data->b = kvmppc_gse_get_u32(gse);
+
+ return 0;
+}
+
+static struct kvmppc_gs_msg_ops gs_msg_test1_ops = {
+ .get_size = test1_get_size,
+ .fill_info = test1_fill_info,
+ .refresh_info = test1_refresh_info,
+};
+
+static void test_gs_msg(struct kunit *test)
+{
+ struct kvmppc_gs_msg_test1_data test1_data = {
+ .a = 0xdeadbeef,
+ .b = 0x1,
+ };
+ struct kvmppc_gs_msg *gsm;
+ struct kvmppc_gs_buff *gsb;
+
+ gsm = kvmppc_gsm_new(&gs_msg_test1_ops, &test1_data, GSM_SEND,
+ GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsm);
+
+ gsb = kvmppc_gsb_new(kvmppc_gsm_size(gsm), 0, 0, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb);
+
+ kvmppc_gsm_include(gsm, KVMPPC_GSID_PARTITION_TABLE);
+ kvmppc_gsm_include(gsm, KVMPPC_GSID_PROCESS_TABLE);
+ kvmppc_gsm_include(gsm, KVMPPC_GSID_RUN_INPUT);
+ kvmppc_gsm_include(gsm, KVMPPC_GSID_GPR(0));
+ kvmppc_gsm_include(gsm, KVMPPC_GSID_CR);
+
+ kvmppc_gsm_fill_info(gsm, gsb);
+
+ memset(&test1_data, 0, sizeof(test1_data));
+
+ kvmppc_gsm_refresh_info(gsm, gsb);
+ KUNIT_EXPECT_EQ(test, test1_data.a, 0xdeadbeef);
+ KUNIT_EXPECT_EQ(test, test1_data.b, 0x1);
+
+ kvmppc_gsm_free(gsm);
+}
+
+static struct kunit_case guest_state_buffer_testcases[] = {
+ KUNIT_CASE(test_creating_buffer),
+ KUNIT_CASE(test_adding_element),
+ KUNIT_CASE(test_gs_bitmap),
+ KUNIT_CASE(test_gs_parsing),
+ KUNIT_CASE(test_gs_msg),
+ {}
+};
+
+static struct kunit_suite guest_state_buffer_test_suite = {
+ .name = "guest_state_buffer_test",
+ .test_cases = guest_state_buffer_testcases,
+};
+
+kunit_test_suites(&guest_state_buffer_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index b00112d7ad46..c6ab46156cda 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -38,6 +38,7 @@ static int __patch_instruction(u32 *exec_addr, ppc_inst_t instr, u32 *patch_addr
return 0;
failed:
+ mb(); /* sync */
return -EPERM;
}
@@ -204,9 +205,6 @@ void __init poking_init(void)
{
int ret;
- if (!IS_ENABLED(CONFIG_STRICT_KERNEL_RWX))
- return;
-
if (mm_patch_enabled())
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
"powerpc/text_poke_mm:online",
@@ -309,10 +307,6 @@ static int __do_patch_instruction_mm(u32 *addr, ppc_inst_t instr)
err = __patch_instruction(addr, instr, patch_addr);
- /* hwsync performed by __patch_instruction (sync) if successful */
- if (err)
- mb(); /* sync */
-
/* context synchronisation performed by __patch_instruction (isync or exception) */
stop_using_temp_mm(patching_mm, orig_mm);
@@ -378,6 +372,144 @@ int patch_instruction(u32 *addr, ppc_inst_t instr)
}
NOKPROBE_SYMBOL(patch_instruction);
+static int __patch_instructions(u32 *patch_addr, u32 *code, size_t len, bool repeat_instr)
+{
+ unsigned long start = (unsigned long)patch_addr;
+
+ /* Repeat instruction */
+ if (repeat_instr) {
+ ppc_inst_t instr = ppc_inst_read(code);
+
+ if (ppc_inst_prefixed(instr)) {
+ u64 val = ppc_inst_as_ulong(instr);
+
+ memset64((u64 *)patch_addr, val, len / 8);
+ } else {
+ u32 val = ppc_inst_val(instr);
+
+ memset32(patch_addr, val, len / 4);
+ }
+ } else {
+ memcpy(patch_addr, code, len);
+ }
+
+ smp_wmb(); /* smp write barrier */
+ flush_icache_range(start, start + len);
+ return 0;
+}
+
+/*
+ * A page is mapped and instructions that fit the page are patched.
+ * Assumes 'len' to be (PAGE_SIZE - offset_in_page(addr)) or below.
+ */
+static int __do_patch_instructions_mm(u32 *addr, u32 *code, size_t len, bool repeat_instr)
+{
+ struct mm_struct *patching_mm, *orig_mm;
+ unsigned long pfn = get_patch_pfn(addr);
+ unsigned long text_poke_addr;
+ spinlock_t *ptl;
+ u32 *patch_addr;
+ pte_t *pte;
+ int err;
+
+ patching_mm = __this_cpu_read(cpu_patching_context.mm);
+ text_poke_addr = __this_cpu_read(cpu_patching_context.addr);
+ patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr));
+
+ pte = get_locked_pte(patching_mm, text_poke_addr, &ptl);
+ if (!pte)
+ return -ENOMEM;
+
+ __set_pte_at(patching_mm, text_poke_addr, pte, pfn_pte(pfn, PAGE_KERNEL), 0);
+
+ /* order PTE update before use, also serves as the hwsync */
+ asm volatile("ptesync" ::: "memory");
+
+ /* order context switch after arbitrary prior code */
+ isync();
+
+ orig_mm = start_using_temp_mm(patching_mm);
+
+ err = __patch_instructions(patch_addr, code, len, repeat_instr);
+
+ /* context synchronisation performed by __patch_instructions */
+ stop_using_temp_mm(patching_mm, orig_mm);
+
+ pte_clear(patching_mm, text_poke_addr, pte);
+ /*
+ * ptesync to order PTE update before TLB invalidation done
+ * by radix__local_flush_tlb_page_psize (in _tlbiel_va)
+ */
+ local_flush_tlb_page_psize(patching_mm, text_poke_addr, mmu_virtual_psize);
+
+ pte_unmap_unlock(pte, ptl);
+
+ return err;
+}
+
+/*
+ * A page is mapped and instructions that fit the page are patched.
+ * Assumes 'len' to be (PAGE_SIZE - offset_in_page(addr)) or below.
+ */
+static int __do_patch_instructions(u32 *addr, u32 *code, size_t len, bool repeat_instr)
+{
+ unsigned long pfn = get_patch_pfn(addr);
+ unsigned long text_poke_addr;
+ u32 *patch_addr;
+ pte_t *pte;
+ int err;
+
+ text_poke_addr = (unsigned long)__this_cpu_read(cpu_patching_context.addr) & PAGE_MASK;
+ patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr));
+
+ pte = __this_cpu_read(cpu_patching_context.pte);
+ __set_pte_at(&init_mm, text_poke_addr, pte, pfn_pte(pfn, PAGE_KERNEL), 0);
+ /* See ptesync comment in radix__set_pte_at() */
+ if (radix_enabled())
+ asm volatile("ptesync" ::: "memory");
+
+ err = __patch_instructions(patch_addr, code, len, repeat_instr);
+
+ pte_clear(&init_mm, text_poke_addr, pte);
+ flush_tlb_kernel_range(text_poke_addr, text_poke_addr + PAGE_SIZE);
+
+ return err;
+}
+
+/*
+ * Patch 'addr' with 'len' bytes of instructions from 'code'.
+ *
+ * If repeat_instr is true, the same instruction is filled for
+ * 'len' bytes.
+ */
+int patch_instructions(u32 *addr, u32 *code, size_t len, bool repeat_instr)
+{
+ while (len > 0) {
+ unsigned long flags;
+ size_t plen;
+ int err;
+
+ plen = min_t(size_t, PAGE_SIZE - offset_in_page(addr), len);
+
+ local_irq_save(flags);
+ if (mm_patch_enabled())
+ err = __do_patch_instructions_mm(addr, code, plen, repeat_instr);
+ else
+ err = __do_patch_instructions(addr, code, plen, repeat_instr);
+ local_irq_restore(flags);
+ if (err)
+ return err;
+
+ len -= plen;
+ addr = (u32 *)((unsigned long)addr + plen);
+ if (!repeat_instr)
+ code = (u32 *)((unsigned long)code + plen);
+ }
+
+ return 0;
+}
+NOKPROBE_SYMBOL(patch_instructions);
+
int patch_branch(u32 *addr, unsigned long target, int flags)
{
ppc_inst_t instr;
diff --git a/arch/powerpc/lib/qspinlock.c b/arch/powerpc/lib/qspinlock.c
index 253620979d0c..5de4dd549f6e 100644
--- a/arch/powerpc/lib/qspinlock.c
+++ b/arch/powerpc/lib/qspinlock.c
@@ -16,7 +16,8 @@ struct qnode {
struct qnode *next;
struct qspinlock *lock;
int cpu;
- int yield_cpu;
+ u8 sleepy; /* 1 if the previous vCPU was preempted or
+ * if the previous node was sleepy */
u8 locked; /* 1 if lock acquired */
};
@@ -43,7 +44,7 @@ static bool pv_sleepy_lock_sticky __read_mostly = false;
static u64 pv_sleepy_lock_interval_ns __read_mostly = 0;
static int pv_sleepy_lock_factor __read_mostly = 256;
static bool pv_yield_prev __read_mostly = true;
-static bool pv_yield_propagate_owner __read_mostly = true;
+static bool pv_yield_sleepy_owner __read_mostly = true;
static bool pv_prod_head __read_mostly = false;
static DEFINE_PER_CPU_ALIGNED(struct qnodes, qnodes);
@@ -247,22 +248,18 @@ static __always_inline void seen_sleepy_lock(void)
this_cpu_write(sleepy_lock_seen_clock, sched_clock());
}
-static __always_inline void seen_sleepy_node(struct qspinlock *lock, u32 val)
+static __always_inline void seen_sleepy_node(void)
{
if (pv_sleepy_lock) {
if (pv_sleepy_lock_interval_ns)
this_cpu_write(sleepy_lock_seen_clock, sched_clock());
- if (val & _Q_LOCKED_VAL) {
- if (!(val & _Q_SLEEPY_VAL))
- try_set_sleepy(lock, val);
- }
+ /* Don't set sleepy because we likely have a stale val */
}
}
-static struct qnode *get_tail_qnode(struct qspinlock *lock, u32 val)
+static struct qnode *get_tail_qnode(struct qspinlock *lock, int prev_cpu)
{
- int cpu = decode_tail_cpu(val);
- struct qnodes *qnodesp = per_cpu_ptr(&qnodes, cpu);
+ struct qnodes *qnodesp = per_cpu_ptr(&qnodes, prev_cpu);
int idx;
/*
@@ -353,74 +350,66 @@ static __always_inline bool yield_head_to_locked_owner(struct qspinlock *lock, u
return __yield_to_locked_owner(lock, val, paravirt, mustq);
}
-static __always_inline void propagate_yield_cpu(struct qnode *node, u32 val, int *set_yield_cpu, bool paravirt)
+static __always_inline void propagate_sleepy(struct qnode *node, u32 val, bool paravirt)
{
struct qnode *next;
int owner;
if (!paravirt)
return;
- if (!pv_yield_propagate_owner)
- return;
-
- owner = get_owner_cpu(val);
- if (*set_yield_cpu == owner)
+ if (!pv_yield_sleepy_owner)
return;
next = READ_ONCE(node->next);
if (!next)
return;
- if (vcpu_is_preempted(owner)) {
- next->yield_cpu = owner;
- *set_yield_cpu = owner;
- } else if (*set_yield_cpu != -1) {
- next->yield_cpu = owner;
- *set_yield_cpu = owner;
- }
+ if (next->sleepy)
+ return;
+
+ owner = get_owner_cpu(val);
+ if (vcpu_is_preempted(owner))
+ next->sleepy = 1;
}
/* Called inside spin_begin() */
-static __always_inline bool yield_to_prev(struct qspinlock *lock, struct qnode *node, u32 val, bool paravirt)
+static __always_inline bool yield_to_prev(struct qspinlock *lock, struct qnode *node, int prev_cpu, bool paravirt)
{
- int prev_cpu = decode_tail_cpu(val);
u32 yield_count;
- int yield_cpu;
bool preempted = false;
if (!paravirt)
goto relax;
- if (!pv_yield_propagate_owner)
- goto yield_prev;
-
- yield_cpu = READ_ONCE(node->yield_cpu);
- if (yield_cpu == -1) {
- /* Propagate back the -1 CPU */
- if (node->next && node->next->yield_cpu != -1)
- node->next->yield_cpu = yield_cpu;
+ if (!pv_yield_sleepy_owner)
goto yield_prev;
- }
-
- yield_count = yield_count_of(yield_cpu);
- if ((yield_count & 1) == 0)
- goto yield_prev; /* owner vcpu is running */
- spin_end();
-
- preempted = true;
- seen_sleepy_node(lock, val);
+ /*
+ * If the previous waiter was preempted it might not be able to
+ * propagate sleepy to us, so check the lock in that case too.
+ */
+ if (node->sleepy || vcpu_is_preempted(prev_cpu)) {
+ u32 val = READ_ONCE(lock->val);
- smp_rmb();
+ if (val & _Q_LOCKED_VAL) {
+ if (node->next && !node->next->sleepy) {
+ /*
+ * Propagate sleepy to next waiter. Only if
+ * owner is preempted, which allows the queue
+ * to become "non-sleepy" if vCPU preemption
+ * ceases to occur, even if the lock remains
+ * highly contended.
+ */
+ if (vcpu_is_preempted(get_owner_cpu(val)))
+ node->next->sleepy = 1;
+ }
- if (yield_cpu == node->yield_cpu) {
- if (node->next && node->next->yield_cpu != yield_cpu)
- node->next->yield_cpu = yield_cpu;
- yield_to_preempted(yield_cpu, yield_count);
- spin_begin();
- return preempted;
+ preempted = yield_to_locked_owner(lock, val, paravirt);
+ if (preempted)
+ return preempted;
+ }
+ node->sleepy = false;
}
- spin_begin();
yield_prev:
if (!pv_yield_prev)
@@ -433,7 +422,7 @@ yield_prev:
spin_end();
preempted = true;
- seen_sleepy_node(lock, val);
+ seen_sleepy_node();
smp_rmb(); /* See __yield_to_locked_owner comment */
@@ -543,7 +532,6 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b
bool sleepy = false;
bool mustq = false;
int idx;
- int set_yield_cpu = -1;
int iters = 0;
BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
@@ -567,7 +555,7 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b
node->next = NULL;
node->lock = lock;
node->cpu = smp_processor_id();
- node->yield_cpu = -1;
+ node->sleepy = 0;
node->locked = 0;
tail = encode_tail_cpu(node->cpu);
@@ -584,7 +572,8 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b
* head of the waitqueue.
*/
if (old & _Q_TAIL_CPU_MASK) {
- struct qnode *prev = get_tail_qnode(lock, old);
+ int prev_cpu = decode_tail_cpu(old);
+ struct qnode *prev = get_tail_qnode(lock, prev_cpu);
/* Link @node into the waitqueue. */
WRITE_ONCE(prev->next, node);
@@ -594,16 +583,12 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b
while (!READ_ONCE(node->locked)) {
spec_barrier();
- if (yield_to_prev(lock, node, old, paravirt))
+ if (yield_to_prev(lock, node, prev_cpu, paravirt))
seen_preempted = true;
}
spec_barrier();
spin_end();
- /* Clear out stale propagated yield_cpu */
- if (paravirt && pv_yield_propagate_owner && node->yield_cpu != -1)
- node->yield_cpu = -1;
-
smp_rmb(); /* acquire barrier for the mcs lock */
/*
@@ -645,7 +630,7 @@ again:
}
}
- propagate_yield_cpu(node, val, &set_yield_cpu, paravirt);
+ propagate_sleepy(node, val, paravirt);
preempted = yield_head_to_locked_owner(lock, val, paravirt);
if (!maybe_stealers)
continue;
@@ -949,21 +934,21 @@ static int pv_yield_prev_get(void *data, u64 *val)
DEFINE_SIMPLE_ATTRIBUTE(fops_pv_yield_prev, pv_yield_prev_get, pv_yield_prev_set, "%llu\n");
-static int pv_yield_propagate_owner_set(void *data, u64 val)
+static int pv_yield_sleepy_owner_set(void *data, u64 val)
{
- pv_yield_propagate_owner = !!val;
+ pv_yield_sleepy_owner = !!val;
return 0;
}
-static int pv_yield_propagate_owner_get(void *data, u64 *val)
+static int pv_yield_sleepy_owner_get(void *data, u64 *val)
{
- *val = pv_yield_propagate_owner;
+ *val = pv_yield_sleepy_owner;
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(fops_pv_yield_propagate_owner, pv_yield_propagate_owner_get, pv_yield_propagate_owner_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(fops_pv_yield_sleepy_owner, pv_yield_sleepy_owner_get, pv_yield_sleepy_owner_set, "%llu\n");
static int pv_prod_head_set(void *data, u64 val)
{
@@ -995,7 +980,7 @@ static __init int spinlock_debugfs_init(void)
debugfs_create_file("qspl_pv_sleepy_lock_interval_ns", 0600, arch_debugfs_dir, NULL, &fops_pv_sleepy_lock_interval_ns);
debugfs_create_file("qspl_pv_sleepy_lock_factor", 0600, arch_debugfs_dir, NULL, &fops_pv_sleepy_lock_factor);
debugfs_create_file("qspl_pv_yield_prev", 0600, arch_debugfs_dir, NULL, &fops_pv_yield_prev);
- debugfs_create_file("qspl_pv_yield_propagate_owner", 0600, arch_debugfs_dir, NULL, &fops_pv_yield_propagate_owner);
+ debugfs_create_file("qspl_pv_yield_sleepy_owner", 0600, arch_debugfs_dir, NULL, &fops_pv_yield_sleepy_owner);
debugfs_create_file("qspl_pv_prod_head", 0600, arch_debugfs_dir, NULL, &fops_pv_prod_head);
}
diff --git a/arch/powerpc/mm/book3s32/hash_low.S b/arch/powerpc/mm/book3s32/hash_low.S
index 8b804e1a9fa4..4ed0efd03db5 100644
--- a/arch/powerpc/mm/book3s32/hash_low.S
+++ b/arch/powerpc/mm/book3s32/hash_low.S
@@ -36,8 +36,9 @@
/*
* Load a PTE into the hash table, if possible.
- * The address is in r4, and r3 contains an access flag:
- * _PAGE_RW (0x400) if a write.
+ * The address is in r4, and r3 contains required access flags:
+ * - For ISI: _PAGE_PRESENT | _PAGE_EXEC
+ * - For DSI: _PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE if a write.
* r9 contains the SRR1 value, from which we use the MSR_PR bit.
* SPRG_THREAD contains the physical address of the current task's thread.
*
@@ -67,12 +68,16 @@ _GLOBAL(hash_page)
lis r0, TASK_SIZE@h /* check if kernel address */
cmplw 0,r4,r0
mfspr r8,SPRN_SPRG_THREAD /* current task's THREAD (phys) */
- ori r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
lwz r5,PGDIR(r8) /* virt page-table root */
blt+ 112f /* assume user more likely */
lis r5,swapper_pg_dir@ha /* if kernel address, use */
+ andi. r0,r9,MSR_PR /* Check usermode */
addi r5,r5,swapper_pg_dir@l /* kernel page table */
- rlwimi r3,r9,32-12,29,29 /* MSR_PR -> _PAGE_USER */
+#ifdef CONFIG_SMP
+ bne- .Lhash_page_out /* return if usermode */
+#else
+ bnelr-
+#endif
112: tophys(r5, r5)
#ifndef CONFIG_PTE_64BIT
rlwimi r5,r4,12,20,29 /* insert top 10 bits of address */
@@ -113,15 +118,15 @@ _GLOBAL(hash_page)
lwarx r6,0,r8 /* get linux-style pte, flag word */
#ifdef CONFIG_PPC_KUAP
mfsrin r5,r4
- rlwinm r0,r9,28,_PAGE_RW /* MSR[PR] => _PAGE_RW */
- rlwinm r5,r5,12,_PAGE_RW /* Ks => _PAGE_RW */
+ rlwinm r0,r9,28,_PAGE_WRITE /* MSR[PR] => _PAGE_WRITE */
+ rlwinm r5,r5,12,_PAGE_WRITE /* Ks => _PAGE_WRITE */
andc r5,r5,r0 /* Ks & ~MSR[PR] */
- andc r5,r6,r5 /* Clear _PAGE_RW when Ks = 1 && MSR[PR] = 0 */
+ andc r5,r6,r5 /* Clear _PAGE_WRITE when Ks = 1 && MSR[PR] = 0 */
andc. r5,r3,r5 /* check access & ~permission */
#else
andc. r5,r3,r6 /* check access & ~permission */
#endif
- rlwinm r0,r3,32-3,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */
+ rlwinm r0,r3,32-3,24,24 /* _PAGE_WRITE access -> _PAGE_DIRTY */
ori r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE
#ifdef CONFIG_SMP
bne- .Lhash_page_out /* return if access not permitted */
@@ -307,12 +312,15 @@ Hash_msk = (((1 << Hash_bits) - 1) * 64)
__REF
_GLOBAL(create_hpte)
/* Convert linux-style PTE (r5) to low word of PPC-style PTE (r8) */
- rlwinm r8,r5,32-9,30,30 /* _PAGE_RW -> PP msb */
+ lis r0, TASK_SIZE@h
+ rlwinm r5,r5,0,~3 /* Clear PP bits */
+ cmplw r4,r0
+ rlwinm r8,r5,32-9,30,30 /* _PAGE_WRITE -> PP msb */
rlwinm r0,r5,32-6,30,30 /* _PAGE_DIRTY -> PP msb */
and r8,r8,r0 /* writable if _RW & _DIRTY */
- rlwimi r5,r5,32-1,30,30 /* _PAGE_USER -> PP msb */
- rlwimi r5,r5,32-2,31,31 /* _PAGE_USER -> PP lsb */
- ori r8,r8,0xe04 /* clear out reserved bits */
+ bge- 1f /* Kernelspace ? Skip */
+ ori r5,r5,3 /* Userspace ? PP = 3 */
+1: ori r8,r8,0xe04 /* clear out reserved bits */
andc r8,r5,r8 /* PP = user? (rw&dirty? 1: 3): 0 */
BEGIN_FTR_SECTION
rlwinm r8,r8,0,~_PAGE_COHERENT /* clear M (coherence not required) */
diff --git a/arch/powerpc/mm/book3s32/mmu.c b/arch/powerpc/mm/book3s32/mmu.c
index 850783cfa9c7..5445587bfe84 100644
--- a/arch/powerpc/mm/book3s32/mmu.c
+++ b/arch/powerpc/mm/book3s32/mmu.c
@@ -127,7 +127,7 @@ static void setibat(int index, unsigned long virt, phys_addr_t phys,
wimgxpp = (flags & _PAGE_COHERENT) | (_PAGE_EXEC ? BPP_RX : BPP_XX);
bat[0].batu = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */
bat[0].batl = BAT_PHYS_ADDR(phys) | wimgxpp;
- if (flags & _PAGE_USER)
+ if (!is_kernel_addr(virt))
bat[0].batu |= 1; /* Vp = 1 */
}
@@ -277,10 +277,10 @@ void __init setbat(int index, unsigned long virt, phys_addr_t phys,
/* Do DBAT first */
wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE
| _PAGE_COHERENT | _PAGE_GUARDED);
- wimgxpp |= (flags & _PAGE_RW)? BPP_RW: BPP_RX;
+ wimgxpp |= (flags & _PAGE_WRITE) ? BPP_RW : BPP_RX;
bat[1].batu = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */
bat[1].batl = BAT_PHYS_ADDR(phys) | wimgxpp;
- if (flags & _PAGE_USER)
+ if (!is_kernel_addr(virt))
bat[1].batu |= 1; /* Vp = 1 */
if (flags & _PAGE_GUARDED) {
/* G bit must be zero in IBATs */
diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c
index 8f8a62d3ff4d..be229290a6a7 100644
--- a/arch/powerpc/mm/book3s64/pgtable.c
+++ b/arch/powerpc/mm/book3s64/pgtable.c
@@ -635,12 +635,10 @@ pgprot_t vm_get_page_prot(unsigned long vm_flags)
unsigned long prot;
/* Radix supports execute-only, but protection_map maps X -> RX */
- if (radix_enabled() && ((vm_flags & VM_ACCESS_FLAGS) == VM_EXEC)) {
- prot = pgprot_val(PAGE_EXECONLY);
- } else {
- prot = pgprot_val(protection_map[vm_flags &
- (VM_ACCESS_FLAGS | VM_SHARED)]);
- }
+ if (!radix_enabled() && ((vm_flags & VM_ACCESS_FLAGS) == VM_EXEC))
+ vm_flags |= VM_READ;
+
+ prot = pgprot_val(protection_map[vm_flags & (VM_ACCESS_FLAGS | VM_SHARED)]);
if (vm_flags & VM_SAO)
prot |= _PAGE_SAO;
diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
index 39acc2cbab4c..9e1f6558d026 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -1212,14 +1212,7 @@ void radix__tlb_flush(struct mmu_gather *tlb)
smp_mb(); /* see radix__flush_tlb_mm */
exit_flush_lazy_tlbs(mm);
- _tlbiel_pid(mm->context.id, RIC_FLUSH_ALL);
-
- /*
- * It should not be possible to have coprocessors still
- * attached here.
- */
- if (WARN_ON_ONCE(atomic_read(&mm->context.copros) > 0))
- __flush_all_mm(mm, true);
+ __flush_all_mm(mm, true);
preempt_enable();
} else {
diff --git a/arch/powerpc/mm/drmem.c b/arch/powerpc/mm/drmem.c
index 2369d1bf2411..fde7790277f7 100644
--- a/arch/powerpc/mm/drmem.c
+++ b/arch/powerpc/mm/drmem.c
@@ -67,7 +67,7 @@ static int drmem_update_dt_v1(struct device_node *memory,
struct property *new_prop;
struct of_drconf_cell_v1 *dr_cell;
struct drmem_lmb *lmb;
- u32 *p;
+ __be32 *p;
new_prop = clone_property(prop, prop->length);
if (!new_prop)
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index b1723094d464..9e49ede2bc1c 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -266,14 +266,15 @@ static bool access_error(bool is_write, bool is_exec, struct vm_area_struct *vma
}
/*
- * VM_READ, VM_WRITE and VM_EXEC all imply read permissions, as
- * defined in protection_map[]. Read faults can only be caused by
- * a PROT_NONE mapping, or with a PROT_EXEC-only mapping on Radix.
+ * VM_READ, VM_WRITE and VM_EXEC may imply read permissions, as
+ * defined in protection_map[]. In that case Read faults can only be
+ * caused by a PROT_NONE mapping. However a non exec access on a
+ * VM_EXEC only mapping is invalid anyway, so report it as such.
*/
if (unlikely(!vma_is_accessible(vma)))
return true;
- if (unlikely(radix_enabled() && ((vma->vm_flags & VM_ACCESS_FLAGS) == VM_EXEC)))
+ if ((vma->vm_flags & VM_ACCESS_FLAGS) == VM_EXEC)
return true;
/*
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index d8adc452f431..4e71dfe7d026 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -39,6 +39,7 @@
#include <asm/hugetlb.h>
#include <asm/kup.h>
#include <asm/kasan.h>
+#include <asm/fixmap.h>
#include <mm/mmu_decl.h>
diff --git a/arch/powerpc/mm/ioremap.c b/arch/powerpc/mm/ioremap.c
index 705e8e8ffde4..7b0afcabd89f 100644
--- a/arch/powerpc/mm/ioremap.c
+++ b/arch/powerpc/mm/ioremap.c
@@ -50,10 +50,6 @@ void __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long flags)
if (pte_write(pte))
pte = pte_mkdirty(pte);
- /* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
- pte = pte_exprotect(pte);
- pte = pte_mkprivileged(pte);
-
if (iowa_is_active())
return iowa_ioremap(addr, size, pte_pgprot(pte), caller);
return __ioremap_caller(addr, size, pte_pgprot(pte), caller);
@@ -66,7 +62,7 @@ int early_ioremap_range(unsigned long ea, phys_addr_t pa,
unsigned long i;
for (i = 0; i < size; i += PAGE_SIZE) {
- int err = map_kernel_page(ea + i, pa + i, prot);
+ int err = map_kernel_page(ea + i, pa + i, pgprot_nx(prot));
if (WARN_ON_ONCE(err)) /* Should clean up */
return err;
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 8b121df7b08f..3a440004b97d 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -26,6 +26,7 @@
#include <asm/ftrace.h>
#include <asm/code-patching.h>
#include <asm/setup.h>
+#include <asm/fixmap.h>
#include <mm/mmu_decl.h>
@@ -34,18 +35,18 @@ unsigned long long memory_limit;
unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss;
EXPORT_SYMBOL(empty_zero_page);
-pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
- unsigned long size, pgprot_t vma_prot)
+pgprot_t __phys_mem_access_prot(unsigned long pfn, unsigned long size,
+ pgprot_t vma_prot)
{
if (ppc_md.phys_mem_access_prot)
- return ppc_md.phys_mem_access_prot(file, pfn, size, vma_prot);
+ return ppc_md.phys_mem_access_prot(pfn, size, vma_prot);
if (!page_is_ram(pfn))
vma_prot = pgprot_noncached(vma_prot);
return vma_prot;
}
-EXPORT_SYMBOL(phys_mem_access_prot);
+EXPORT_SYMBOL(__phys_mem_access_prot);
#ifdef CONFIG_MEMORY_HOTPLUG
static DEFINE_MUTEX(linear_mapping_mutex);
@@ -288,7 +289,6 @@ void __init mem_init(void)
#endif
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
- set_max_mapnr(max_pfn);
kasan_late_init();
diff --git a/arch/powerpc/mm/nohash/40x.c b/arch/powerpc/mm/nohash/40x.c
index 3684d6e570fb..e835e80c09db 100644
--- a/arch/powerpc/mm/nohash/40x.c
+++ b/arch/powerpc/mm/nohash/40x.c
@@ -48,20 +48,25 @@
*/
void __init MMU_init_hw(void)
{
+ int i;
+ unsigned long zpr;
+
/*
* The Zone Protection Register (ZPR) defines how protection will
- * be applied to every page which is a member of a given zone. At
- * present, we utilize only two of the 4xx's zones.
+ * be applied to every page which is a member of a given zone.
* The zone index bits (of ZSEL) in the PTE are used for software
- * indicators, except the LSB. For user access, zone 1 is used,
- * for kernel access, zone 0 is used. We set all but zone 1
- * to zero, allowing only kernel access as indicated in the PTE.
- * For zone 1, we set a 01 binary (a value of 10 will not work)
+ * indicators. We use the 4 upper bits of virtual address to select
+ * the zone. We set all zones above TASK_SIZE to zero, allowing
+ * only kernel access as indicated in the PTE. For zones below
+ * TASK_SIZE, we set a 01 binary (a value of 10 will not work)
* to allow user access as indicated in the PTE. This also allows
* kernel access as indicated in the PTE.
*/
- mtspr(SPRN_ZPR, 0x10000000);
+ for (i = 0, zpr = 0; i < TASK_SIZE >> 28; i++)
+ zpr |= 1 << (30 - i * 2);
+
+ mtspr(SPRN_ZPR, zpr);
flush_instruction_cache();
diff --git a/arch/powerpc/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c
index a642a7929892..6be6421086ed 100644
--- a/arch/powerpc/mm/nohash/8xx.c
+++ b/arch/powerpc/mm/nohash/8xx.c
@@ -10,6 +10,8 @@
#include <linux/memblock.h>
#include <linux/hugetlb.h>
+#include <asm/fixmap.h>
+
#include <mm/mmu_decl.h>
#define IMMR_SIZE (FIX_IMMR_SIZE << PAGE_SHIFT)
diff --git a/arch/powerpc/mm/nohash/book3e_pgtable.c b/arch/powerpc/mm/nohash/book3e_pgtable.c
index b80fc4a91a53..1c5e4ecbebeb 100644
--- a/arch/powerpc/mm/nohash/book3e_pgtable.c
+++ b/arch/powerpc/mm/nohash/book3e_pgtable.c
@@ -71,7 +71,7 @@ static void __init *early_alloc_pgtable(unsigned long size)
* map_kernel_page adds an entry to the ioremap page table
* and adds an entry to the HPT, possibly bolting it
*/
-int __ref map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot)
+int __ref map_kernel_page(unsigned long ea, phys_addr_t pa, pgprot_t prot)
{
pgd_t *pgdp;
p4d_t *p4dp;
diff --git a/arch/powerpc/mm/nohash/e500.c b/arch/powerpc/mm/nohash/e500.c
index 40a4e69ae1a9..921c3521ec11 100644
--- a/arch/powerpc/mm/nohash/e500.c
+++ b/arch/powerpc/mm/nohash/e500.c
@@ -117,15 +117,15 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
TLBCAM[index].MAS2 |= (flags & _PAGE_ENDIAN) ? MAS2_E : 0;
TLBCAM[index].MAS3 = (phys & MAS3_RPN) | MAS3_SR;
- TLBCAM[index].MAS3 |= (flags & _PAGE_RW) ? MAS3_SW : 0;
+ TLBCAM[index].MAS3 |= (flags & _PAGE_WRITE) ? MAS3_SW : 0;
if (mmu_has_feature(MMU_FTR_BIG_PHYS))
TLBCAM[index].MAS7 = (u64)phys >> 32;
/* Below is unlikely -- only for large user pages or similar */
- if (pte_user(__pte(flags))) {
+ if (!is_kernel_addr(virt)) {
TLBCAM[index].MAS3 |= MAS3_UR;
TLBCAM[index].MAS3 |= (flags & _PAGE_EXEC) ? MAS3_UX : 0;
- TLBCAM[index].MAS3 |= (flags & _PAGE_RW) ? MAS3_UW : 0;
+ TLBCAM[index].MAS3 |= (flags & _PAGE_WRITE) ? MAS3_UW : 0;
} else {
TLBCAM[index].MAS3 |= (flags & _PAGE_EXEC) ? MAS3_SX : 0;
}
diff --git a/arch/powerpc/mm/nohash/e500_hugetlbpage.c b/arch/powerpc/mm/nohash/e500_hugetlbpage.c
index 6b30e40d4590..a134d28a0e4d 100644
--- a/arch/powerpc/mm/nohash/e500_hugetlbpage.c
+++ b/arch/powerpc/mm/nohash/e500_hugetlbpage.c
@@ -178,8 +178,7 @@ book3e_hugetlb_preload(struct vm_area_struct *vma, unsigned long ea, pte_t pte)
*
* This must always be called with the pte lock held.
*/
-void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma,
- unsigned long address, pte_t *ptep, unsigned int nr)
+void __update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
{
if (is_vm_hugetlb_page(vma))
book3e_hugetlb_preload(vma, address, *ptep);
diff --git a/arch/powerpc/mm/nohash/kaslr_booke.c b/arch/powerpc/mm/nohash/kaslr_booke.c
index 2fb3edafe9ab..b4f2786a7d2b 100644
--- a/arch/powerpc/mm/nohash/kaslr_booke.c
+++ b/arch/powerpc/mm/nohash/kaslr_booke.c
@@ -178,7 +178,7 @@ static void __init get_crash_kernel(void *fdt, unsigned long size)
int ret;
ret = parse_crashkernel(boot_command_line, size, &crash_size,
- &crash_base);
+ &crash_base, NULL, NULL);
if (ret != 0 || crash_size == 0)
return;
if (crash_base == 0)
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index 3ba9fe411604..a04ae4449a02 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -46,13 +46,13 @@ static inline int is_exec_fault(void)
* and we avoid _PAGE_SPECIAL and cache inhibited pte. We also only do that
* on userspace PTEs
*/
-static inline int pte_looks_normal(pte_t pte)
+static inline int pte_looks_normal(pte_t pte, unsigned long addr)
{
if (pte_present(pte) && !pte_special(pte)) {
if (pte_ci(pte))
return 0;
- if (pte_user(pte))
+ if (!is_kernel_addr(addr))
return 1;
}
return 0;
@@ -79,11 +79,11 @@ static struct folio *maybe_pte_to_folio(pte_t pte)
* support falls into the same category.
*/
-static pte_t set_pte_filter_hash(pte_t pte)
+static pte_t set_pte_filter_hash(pte_t pte, unsigned long addr)
{
pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
- if (pte_looks_normal(pte) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) ||
- cpu_has_feature(CPU_FTR_NOEXECUTE))) {
+ if (pte_looks_normal(pte, addr) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) ||
+ cpu_has_feature(CPU_FTR_NOEXECUTE))) {
struct folio *folio = maybe_pte_to_folio(pte);
if (!folio)
return pte;
@@ -97,15 +97,17 @@ static pte_t set_pte_filter_hash(pte_t pte)
#else /* CONFIG_PPC_BOOK3S */
-static pte_t set_pte_filter_hash(pte_t pte) { return pte; }
+static pte_t set_pte_filter_hash(pte_t pte, unsigned long addr) { return pte; }
#endif /* CONFIG_PPC_BOOK3S */
/* Embedded type MMU with HW exec support. This is a bit more complicated
* as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so
* instead we "filter out" the exec permission for non clean pages.
+ *
+ * This is also called once for the folio. So only work with folio->flags here.
*/
-static inline pte_t set_pte_filter(pte_t pte)
+static inline pte_t set_pte_filter(pte_t pte, unsigned long addr)
{
struct folio *folio;
@@ -113,10 +115,10 @@ static inline pte_t set_pte_filter(pte_t pte)
return pte;
if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
- return set_pte_filter_hash(pte);
+ return set_pte_filter_hash(pte, addr);
/* No exec permission in the first place, move on */
- if (!pte_exec(pte) || !pte_looks_normal(pte))
+ if (!pte_exec(pte) || !pte_looks_normal(pte, addr))
return pte;
/* If you set _PAGE_EXEC on weird pages you're on your own */
@@ -190,29 +192,39 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma,
void set_ptes(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
pte_t pte, unsigned int nr)
{
- /*
- * Make sure hardware valid bit is not set. We don't do
- * tlb flush for this update.
- */
- VM_WARN_ON(pte_hw_valid(*ptep) && !pte_protnone(*ptep));
/* Note: mm->context.id might not yet have been assigned as
* this context might not have been activated yet when this
- * is called.
+ * is called. Filter the pte value and use the filtered value
+ * to setup all the ptes in the range.
*/
- pte = set_pte_filter(pte);
+ pte = set_pte_filter(pte, addr);
- /* Perform the setting of the PTE */
- arch_enter_lazy_mmu_mode();
+ /*
+ * We don't need to call arch_enter/leave_lazy_mmu_mode()
+ * because we expect set_ptes to be only be used on not present
+ * and not hw_valid ptes. Hence there is no translation cache flush
+ * involved that need to be batched.
+ */
for (;;) {
+
+ /*
+ * Make sure hardware valid bit is not set. We don't do
+ * tlb flush for this update.
+ */
+ VM_WARN_ON(pte_hw_valid(*ptep) && !pte_protnone(*ptep));
+
+ /* Perform the setting of the PTE */
__set_pte_at(mm, addr, ptep, pte, 0);
if (--nr == 0)
break;
ptep++;
- pte = __pte(pte_val(pte) + (1UL << PTE_RPN_SHIFT));
addr += PAGE_SIZE;
+ /*
+ * increment the pfn.
+ */
+ pte = pfn_pte(pte_pfn(pte) + 1, pte_pgprot((pte)));
}
- arch_leave_lazy_mmu_mode();
}
void unmap_kernel_page(unsigned long va)
@@ -302,7 +314,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
*/
VM_WARN_ON(pte_hw_valid(*ptep) && !pte_protnone(*ptep));
- pte = set_pte_filter(pte);
+ pte = set_pte_filter(pte, addr);
val = pte_val(pte);
@@ -493,7 +505,7 @@ const pgprot_t protection_map[16] = {
[VM_READ] = PAGE_READONLY,
[VM_WRITE] = PAGE_COPY,
[VM_WRITE | VM_READ] = PAGE_COPY,
- [VM_EXEC] = PAGE_READONLY_X,
+ [VM_EXEC] = PAGE_EXECONLY_X,
[VM_EXEC | VM_READ] = PAGE_READONLY_X,
[VM_EXEC | VM_WRITE] = PAGE_COPY_X,
[VM_EXEC | VM_WRITE | VM_READ] = PAGE_COPY_X,
@@ -501,7 +513,7 @@ const pgprot_t protection_map[16] = {
[VM_SHARED | VM_READ] = PAGE_READONLY,
[VM_SHARED | VM_WRITE] = PAGE_SHARED,
[VM_SHARED | VM_WRITE | VM_READ] = PAGE_SHARED,
- [VM_SHARED | VM_EXEC] = PAGE_READONLY_X,
+ [VM_SHARED | VM_EXEC] = PAGE_EXECONLY_X,
[VM_SHARED | VM_EXEC | VM_READ] = PAGE_READONLY_X,
[VM_SHARED | VM_EXEC | VM_WRITE] = PAGE_SHARED_X,
[VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = PAGE_SHARED_X
diff --git a/arch/powerpc/mm/ptdump/8xx.c b/arch/powerpc/mm/ptdump/8xx.c
index fac932eb8f9a..b5c79b11ea3c 100644
--- a/arch/powerpc/mm/ptdump/8xx.c
+++ b/arch/powerpc/mm/ptdump/8xx.c
@@ -21,11 +21,6 @@ static const struct flag_info flag_array[] = {
.set = "huge",
.clear = " ",
}, {
- .mask = _PAGE_SH,
- .val = 0,
- .set = "user",
- .clear = " ",
- }, {
.mask = _PAGE_RO | _PAGE_NA,
.val = 0,
.set = "rw",
diff --git a/arch/powerpc/mm/ptdump/shared.c b/arch/powerpc/mm/ptdump/shared.c
index f884760ca5cf..39c30c62b7ea 100644
--- a/arch/powerpc/mm/ptdump/shared.c
+++ b/arch/powerpc/mm/ptdump/shared.c
@@ -11,15 +11,15 @@
static const struct flag_info flag_array[] = {
{
- .mask = _PAGE_USER,
- .val = _PAGE_USER,
- .set = "user",
- .clear = " ",
+ .mask = _PAGE_READ,
+ .val = 0,
+ .set = " ",
+ .clear = "r",
}, {
- .mask = _PAGE_RW,
+ .mask = _PAGE_WRITE,
.val = 0,
- .set = "r ",
- .clear = "rw",
+ .set = " ",
+ .clear = "w",
}, {
.mask = _PAGE_EXEC,
.val = _PAGE_EXEC,
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 72b7bb34fade..cdea5dccaefe 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -36,9 +36,6 @@
EMIT(PPC_RAW_BRANCH(offset)); \
} while (0)
-/* bl (unconditional 'branch' with link) */
-#define PPC_BL(dest) EMIT(PPC_RAW_BL((dest) - (unsigned long)(image + ctx->idx)))
-
/* "cond" here covers BO:BI fields. */
#define PPC_BCC_SHORT(cond, dest) \
do { \
@@ -147,12 +144,6 @@ struct codegen_context {
#define BPF_FIXUP_LEN 2 /* Two instructions => 8 bytes */
#endif
-static inline void bpf_flush_icache(void *start, void *end)
-{
- smp_wmb(); /* smp write barrier */
- flush_icache_range((unsigned long)start, (unsigned long)end);
-}
-
static inline bool bpf_is_seen_register(struct codegen_context *ctx, int i)
{
return ctx->seen & (1 << (31 - i));
@@ -169,16 +160,17 @@ static inline void bpf_clear_seen_register(struct codegen_context *ctx, int i)
}
void bpf_jit_init_reg_mapping(struct codegen_context *ctx);
-int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func);
-int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
+int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func);
+int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx,
u32 *addrs, int pass, bool extra_pass);
void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx);
void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx);
void bpf_jit_realloc_regs(struct codegen_context *ctx);
int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr);
-int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct codegen_context *ctx,
- int insn_idx, int jmp_off, int dst_reg);
+int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, u32 *fimage, int pass,
+ struct codegen_context *ctx, int insn_idx,
+ int jmp_off, int dst_reg);
#endif
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 37043dfc1add..0f9a21783329 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -13,9 +13,13 @@
#include <linux/netdevice.h>
#include <linux/filter.h>
#include <linux/if_vlan.h>
-#include <asm/kprobes.h>
+#include <linux/kernel.h>
+#include <linux/memory.h>
#include <linux/bpf.h>
+#include <asm/kprobes.h>
+#include <asm/code-patching.h>
+
#include "bpf_jit.h"
static void bpf_jit_fill_ill_insns(void *area, unsigned int size)
@@ -39,10 +43,13 @@ int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg,
return 0;
}
-struct powerpc64_jit_data {
- struct bpf_binary_header *header;
+struct powerpc_jit_data {
+ /* address of rw header */
+ struct bpf_binary_header *hdr;
+ /* address of ro final header */
+ struct bpf_binary_header *fhdr;
u32 *addrs;
- u8 *image;
+ u8 *fimage;
u32 proglen;
struct codegen_context ctx;
};
@@ -59,15 +66,18 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
u8 *image = NULL;
u32 *code_base;
u32 *addrs;
- struct powerpc64_jit_data *jit_data;
+ struct powerpc_jit_data *jit_data;
struct codegen_context cgctx;
int pass;
int flen;
- struct bpf_binary_header *bpf_hdr;
+ struct bpf_binary_header *fhdr = NULL;
+ struct bpf_binary_header *hdr = NULL;
struct bpf_prog *org_fp = fp;
struct bpf_prog *tmp_fp;
bool bpf_blinded = false;
bool extra_pass = false;
+ u8 *fimage = NULL;
+ u32 *fcode_base;
u32 extable_len;
u32 fixup_len;
@@ -97,9 +107,16 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
addrs = jit_data->addrs;
if (addrs) {
cgctx = jit_data->ctx;
- image = jit_data->image;
- bpf_hdr = jit_data->header;
+ /*
+ * JIT compiled to a writable location (image/code_base) first.
+ * It is then moved to the readonly final location (fimage/fcode_base)
+ * using instruction patching.
+ */
+ fimage = jit_data->fimage;
+ fhdr = jit_data->fhdr;
proglen = jit_data->proglen;
+ hdr = jit_data->hdr;
+ image = (void *)hdr + ((void *)fimage - (void *)fhdr);
extra_pass = true;
/* During extra pass, ensure index is reset before repopulating extable entries */
cgctx.exentry_idx = 0;
@@ -119,7 +136,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
cgctx.stack_size = round_up(fp->aux->stack_depth, 16);
/* Scouting faux-generate pass 0 */
- if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0, false)) {
+ if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false)) {
/* We hit something illegal or unsupported. */
fp = org_fp;
goto out_addrs;
@@ -134,7 +151,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
*/
if (cgctx.seen & SEEN_TAILCALL || !is_offset_in_branch_range((long)cgctx.idx * 4)) {
cgctx.idx = 0;
- if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0, false)) {
+ if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false)) {
fp = org_fp;
goto out_addrs;
}
@@ -146,9 +163,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
* update ctgtx.idx as it pretends to output instructions, then we can
* calculate total size from idx.
*/
- bpf_jit_build_prologue(0, &cgctx);
+ bpf_jit_build_prologue(NULL, &cgctx);
addrs[fp->len] = cgctx.idx * 4;
- bpf_jit_build_epilogue(0, &cgctx);
+ bpf_jit_build_epilogue(NULL, &cgctx);
fixup_len = fp->aux->num_exentries * BPF_FIXUP_LEN * 4;
extable_len = fp->aux->num_exentries * sizeof(struct exception_table_entry);
@@ -156,17 +173,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
proglen = cgctx.idx * 4;
alloclen = proglen + FUNCTION_DESCR_SIZE + fixup_len + extable_len;
- bpf_hdr = bpf_jit_binary_alloc(alloclen, &image, 4, bpf_jit_fill_ill_insns);
- if (!bpf_hdr) {
+ fhdr = bpf_jit_binary_pack_alloc(alloclen, &fimage, 4, &hdr, &image,
+ bpf_jit_fill_ill_insns);
+ if (!fhdr) {
fp = org_fp;
goto out_addrs;
}
if (extable_len)
- fp->aux->extable = (void *)image + FUNCTION_DESCR_SIZE + proglen + fixup_len;
+ fp->aux->extable = (void *)fimage + FUNCTION_DESCR_SIZE + proglen + fixup_len;
skip_init_ctx:
code_base = (u32 *)(image + FUNCTION_DESCR_SIZE);
+ fcode_base = (u32 *)(fimage + FUNCTION_DESCR_SIZE);
/* Code generation passes 1-2 */
for (pass = 1; pass < 3; pass++) {
@@ -174,8 +193,10 @@ skip_init_ctx:
cgctx.idx = 0;
cgctx.alt_exit_addr = 0;
bpf_jit_build_prologue(code_base, &cgctx);
- if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, pass, extra_pass)) {
- bpf_jit_binary_free(bpf_hdr);
+ if (bpf_jit_build_body(fp, code_base, fcode_base, &cgctx, addrs, pass,
+ extra_pass)) {
+ bpf_arch_text_copy(&fhdr->size, &hdr->size, sizeof(hdr->size));
+ bpf_jit_binary_pack_free(fhdr, hdr);
fp = org_fp;
goto out_addrs;
}
@@ -195,17 +216,19 @@ skip_init_ctx:
#ifdef CONFIG_PPC64_ELF_ABI_V1
/* Function descriptor nastiness: Address + TOC */
- ((u64 *)image)[0] = (u64)code_base;
+ ((u64 *)image)[0] = (u64)fcode_base;
((u64 *)image)[1] = local_paca->kernel_toc;
#endif
- fp->bpf_func = (void *)image;
+ fp->bpf_func = (void *)fimage;
fp->jited = 1;
fp->jited_len = proglen + FUNCTION_DESCR_SIZE;
- bpf_flush_icache(bpf_hdr, (u8 *)bpf_hdr + bpf_hdr->size);
if (!fp->is_func || extra_pass) {
- bpf_jit_binary_lock_ro(bpf_hdr);
+ if (bpf_jit_binary_pack_finalize(fp, fhdr, hdr)) {
+ fp = org_fp;
+ goto out_addrs;
+ }
bpf_prog_fill_jited_linfo(fp, addrs);
out_addrs:
kfree(addrs);
@@ -215,8 +238,9 @@ out_addrs:
jit_data->addrs = addrs;
jit_data->ctx = cgctx;
jit_data->proglen = proglen;
- jit_data->image = image;
- jit_data->header = bpf_hdr;
+ jit_data->fimage = fimage;
+ jit_data->fhdr = fhdr;
+ jit_data->hdr = hdr;
}
out:
@@ -230,12 +254,13 @@ out:
* The caller should check for (BPF_MODE(code) == BPF_PROBE_MEM) before calling
* this function, as this only applies to BPF_PROBE_MEM, for now.
*/
-int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct codegen_context *ctx,
- int insn_idx, int jmp_off, int dst_reg)
+int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, u32 *fimage, int pass,
+ struct codegen_context *ctx, int insn_idx, int jmp_off,
+ int dst_reg)
{
off_t offset;
unsigned long pc;
- struct exception_table_entry *ex;
+ struct exception_table_entry *ex, *ex_entry;
u32 *fixup;
/* Populate extable entries only in the last pass */
@@ -246,9 +271,16 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code
WARN_ON_ONCE(ctx->exentry_idx >= fp->aux->num_exentries))
return -EINVAL;
+ /*
+ * Program is first written to image before copying to the
+ * final location (fimage). Accordingly, update in the image first.
+ * As all offsets used are relative, copying as is to the
+ * final location should be alright.
+ */
pc = (unsigned long)&image[insn_idx];
+ ex = (void *)fp->aux->extable - (void *)fimage + (void *)image;
- fixup = (void *)fp->aux->extable -
+ fixup = (void *)ex -
(fp->aux->num_exentries * BPF_FIXUP_LEN * 4) +
(ctx->exentry_idx * BPF_FIXUP_LEN * 4);
@@ -259,18 +291,71 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code
fixup[BPF_FIXUP_LEN - 1] =
PPC_RAW_BRANCH((long)(pc + jmp_off) - (long)&fixup[BPF_FIXUP_LEN - 1]);
- ex = &fp->aux->extable[ctx->exentry_idx];
+ ex_entry = &ex[ctx->exentry_idx];
- offset = pc - (long)&ex->insn;
+ offset = pc - (long)&ex_entry->insn;
if (WARN_ON_ONCE(offset >= 0 || offset < INT_MIN))
return -ERANGE;
- ex->insn = offset;
+ ex_entry->insn = offset;
- offset = (long)fixup - (long)&ex->fixup;
+ offset = (long)fixup - (long)&ex_entry->fixup;
if (WARN_ON_ONCE(offset >= 0 || offset < INT_MIN))
return -ERANGE;
- ex->fixup = offset;
+ ex_entry->fixup = offset;
ctx->exentry_idx++;
return 0;
}
+
+void *bpf_arch_text_copy(void *dst, void *src, size_t len)
+{
+ int err;
+
+ if (WARN_ON_ONCE(core_kernel_text((unsigned long)dst)))
+ return ERR_PTR(-EINVAL);
+
+ mutex_lock(&text_mutex);
+ err = patch_instructions(dst, src, len, false);
+ mutex_unlock(&text_mutex);
+
+ return err ? ERR_PTR(err) : dst;
+}
+
+int bpf_arch_text_invalidate(void *dst, size_t len)
+{
+ u32 insn = BREAKPOINT_INSTRUCTION;
+ int ret;
+
+ if (WARN_ON_ONCE(core_kernel_text((unsigned long)dst)))
+ return -EINVAL;
+
+ mutex_lock(&text_mutex);
+ ret = patch_instructions(dst, &insn, len, true);
+ mutex_unlock(&text_mutex);
+
+ return ret;
+}
+
+void bpf_jit_free(struct bpf_prog *fp)
+{
+ if (fp->jited) {
+ struct powerpc_jit_data *jit_data = fp->aux->jit_data;
+ struct bpf_binary_header *hdr;
+
+ /*
+ * If we fail the final pass of JIT (from jit_subprogs),
+ * the program may not be finalized yet. Call finalize here
+ * before freeing it.
+ */
+ if (jit_data) {
+ bpf_jit_binary_pack_finalize(fp, jit_data->fhdr, jit_data->hdr);
+ kvfree(jit_data->addrs);
+ kfree(jit_data);
+ }
+ hdr = bpf_jit_binary_pack_hdr(fp);
+ bpf_jit_binary_pack_free(hdr, NULL);
+ WARN_ON_ONCE(!bpf_prog_kallsyms_verify_off(fp));
+ }
+
+ bpf_prog_unlock_free(fp);
+}
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 7f91ea064c08..2f39c50ca729 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -200,12 +200,13 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
EMIT(PPC_RAW_BLR());
}
-int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func)
+/* Relative offset needs to be calculated based on final image location */
+int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
{
- s32 rel = (s32)func - (s32)(image + ctx->idx);
+ s32 rel = (s32)func - (s32)(fimage + ctx->idx);
if (image && rel < 0x2000000 && rel >= -0x2000000) {
- PPC_BL(func);
+ EMIT(PPC_RAW_BL(rel));
} else {
/* Load function address into r0 */
EMIT(PPC_RAW_LIS(_R0, IMM_H(func)));
@@ -278,7 +279,7 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o
}
/* Assemble the body code between the prologue & epilogue */
-int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
+int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx,
u32 *addrs, int pass, bool extra_pass)
{
const struct bpf_insn *insn = fp->insnsi;
@@ -940,7 +941,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
* !fp->aux->verifier_zext. Emit NOP otherwise.
*
* Note that "li reg_h,0" is emitted for BPF_B/H/W case,
- * if necessary. So, jump there insted of emitting an
+ * if necessary. So, jump there instead of emitting an
* additional "li reg_h,0" instruction.
*/
if (size == BPF_DW && !fp->aux->verifier_zext)
@@ -997,7 +998,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
jmp_off += 4;
}
- ret = bpf_add_extable_entry(fp, image, pass, ctx, insn_idx,
+ ret = bpf_add_extable_entry(fp, image, fimage, pass, ctx, insn_idx,
jmp_off, dst_reg);
if (ret)
return ret;
@@ -1053,7 +1054,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
EMIT(PPC_RAW_STW(bpf_to_ppc(BPF_REG_5), _R1, 12));
}
- ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr);
+ ret = bpf_jit_emit_func_call_rel(image, fimage, ctx, func_addr);
if (ret)
return ret;
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index 0f8048f6dad6..79f23974a320 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -240,7 +240,7 @@ static int bpf_jit_emit_func_call_hlp(u32 *image, struct codegen_context *ctx, u
return 0;
}
-int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func)
+int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
{
unsigned int i, ctx_idx = ctx->idx;
@@ -361,7 +361,7 @@ asm (
);
/* Assemble the body code between the prologue & epilogue */
-int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
+int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx,
u32 *addrs, int pass, bool extra_pass)
{
enum stf_barrier_type stf_barrier = stf_barrier_type_get();
@@ -940,8 +940,8 @@ emit_clear:
addrs[++i] = ctx->idx * 4;
if (BPF_MODE(code) == BPF_PROBE_MEM) {
- ret = bpf_add_extable_entry(fp, image, pass, ctx, ctx->idx - 1,
- 4, dst_reg);
+ ret = bpf_add_extable_entry(fp, image, fimage, pass, ctx,
+ ctx->idx - 1, 4, dst_reg);
if (ret)
return ret;
}
@@ -995,7 +995,7 @@ emit_clear:
if (func_addr_fixed)
ret = bpf_jit_emit_func_call_hlp(image, ctx, func_addr);
else
- ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr);
+ ret = bpf_jit_emit_func_call_rel(image, fimage, ctx, func_addr);
if (ret)
return ret;
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 8c1f7def596e..10b946e9c6e7 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -1371,8 +1371,7 @@ static void power_pmu_disable(struct pmu *pmu)
/*
* Disable instruction sampling if it was enabled
*/
- if (cpuhw->mmcr.mmcra & MMCRA_SAMPLE_ENABLE)
- val &= ~MMCRA_SAMPLE_ENABLE;
+ val &= ~MMCRA_SAMPLE_ENABLE;
/* Disable BHRB via mmcra (BHRBRD) for p10 */
if (ppmu->flags & PPMU_ARCH_31)
@@ -1383,7 +1382,7 @@ static void power_pmu_disable(struct pmu *pmu)
* instruction sampling or BHRB.
*/
if (val != mmcra) {
- mtspr(SPRN_MMCRA, mmcra);
+ mtspr(SPRN_MMCRA, val);
mb();
isync();
}
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
index 3449be7c0d51..057ec2e3451d 100644
--- a/arch/powerpc/perf/hv-24x7.c
+++ b/arch/powerpc/perf/hv-24x7.c
@@ -1338,7 +1338,7 @@ static int get_count_from_result(struct perf_event *event,
for (i = count = 0, element_data = res->elements + data_offset;
i < num_elements;
i++, element_data += data_size + data_offset)
- count += be64_to_cpu(*((u64 *) element_data));
+ count += be64_to_cpu(*((__be64 *)element_data));
*countp = count;
diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c
index 9d229ef7f86e..5d12ca386c1f 100644
--- a/arch/powerpc/perf/imc-pmu.c
+++ b/arch/powerpc/perf/imc-pmu.c
@@ -51,7 +51,7 @@ static int trace_imc_mem_size;
* core and trace-imc
*/
static struct imc_pmu_ref imc_global_refc = {
- .lock = __SPIN_LOCK_INITIALIZER(imc_global_refc.lock),
+ .lock = __SPIN_LOCK_UNLOCKED(imc_global_refc.lock),
.id = 0,
.refc = 0,
};
@@ -544,7 +544,7 @@ static int nest_imc_event_init(struct perf_event *event)
break;
}
pcni++;
- } while (pcni->vbase != 0);
+ } while (pcni->vbase);
if (!flag)
return -ENODEV;
@@ -1025,16 +1025,16 @@ static bool is_thread_imc_pmu(struct perf_event *event)
return false;
}
-static u64 * get_event_base_addr(struct perf_event *event)
+static __be64 *get_event_base_addr(struct perf_event *event)
{
u64 addr;
if (is_thread_imc_pmu(event)) {
addr = (u64)per_cpu(thread_imc_mem, smp_processor_id());
- return (u64 *)(addr + (event->attr.config & IMC_EVENT_OFFSET_MASK));
+ return (__be64 *)(addr + (event->attr.config & IMC_EVENT_OFFSET_MASK));
}
- return (u64 *)event->hw.event_base;
+ return (__be64 *)event->hw.event_base;
}
static void thread_imc_pmu_start_txn(struct pmu *pmu,
@@ -1058,7 +1058,8 @@ static int thread_imc_pmu_commit_txn(struct pmu *pmu)
static u64 imc_read_counter(struct perf_event *event)
{
- u64 *addr, data;
+ __be64 *addr;
+ u64 data;
/*
* In-Memory Collection (IMC) counters are free flowing counters.
diff --git a/arch/powerpc/perf/power6-pmu.c b/arch/powerpc/perf/power6-pmu.c
index 5729b6e059de..9f720b522e17 100644
--- a/arch/powerpc/perf/power6-pmu.c
+++ b/arch/powerpc/perf/power6-pmu.c
@@ -335,26 +335,38 @@ static const unsigned int event_alternatives[][MAX_ALT] = {
{ 0x3000fe, 0x400056 }, /* PM_DATA_FROM_L3MISS */
};
-/*
- * This could be made more efficient with a binary search on
- * a presorted list, if necessary
- */
static int find_alternatives_list(u64 event)
{
- int i, j;
- unsigned int alt;
-
- for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
- if (event < event_alternatives[i][0])
- return -1;
- for (j = 0; j < MAX_ALT; ++j) {
- alt = event_alternatives[i][j];
- if (!alt || event < alt)
- break;
- if (event == alt)
- return i;
- }
+ const unsigned int presorted_event_table[] = {
+ 0x0130e8, 0x080080, 0x080088, 0x10000a, 0x10000b, 0x10000d, 0x10000e,
+ 0x100010, 0x10001a, 0x100026, 0x100054, 0x100056, 0x1000f0, 0x1000f8,
+ 0x1000fc, 0x200008, 0x20000e, 0x200010, 0x200012, 0x200054, 0x2000f0,
+ 0x2000f2, 0x2000f4, 0x2000f5, 0x2000f6, 0x2000f8, 0x2000fc, 0x2000fe,
+ 0x2d0030, 0x30000a, 0x30000c, 0x300010, 0x300012, 0x30001a, 0x300056,
+ 0x3000f0, 0x3000f2, 0x3000f6, 0x3000f8, 0x3000fc, 0x3000fe, 0x400006,
+ 0x400007, 0x40000a, 0x40000e, 0x400010, 0x400018, 0x400056, 0x4000f0,
+ 0x4000f8, 0x600005
+ };
+ const unsigned int event_index_table[] = {
+ 0, 1, 2, 3, 4, 1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 12, 14,
+ 7, 15, 2, 9, 16, 3, 4, 0, 17, 10, 18, 19, 20, 1, 17, 15, 19,
+ 18, 2, 16, 21, 8, 0, 22, 13, 14, 11, 21, 5, 20, 22, 1, 6, 3
+ };
+ int hi = ARRAY_SIZE(presorted_event_table) - 1;
+ int lo = 0;
+
+ while (lo <= hi) {
+ int mid = lo + (hi - lo) / 2;
+ unsigned int alt = presorted_event_table[mid];
+
+ if (alt < event)
+ lo = mid + 1;
+ else if (alt > event)
+ hi = mid - 1;
+ else
+ return event_index_table[mid];
}
+
return -1;
}
diff --git a/arch/powerpc/platforms/4xx/soc.c b/arch/powerpc/platforms/4xx/soc.c
index b2d940437a66..5412e6b21e10 100644
--- a/arch/powerpc/platforms/4xx/soc.c
+++ b/arch/powerpc/platforms/4xx/soc.c
@@ -112,7 +112,7 @@ static int __init ppc4xx_l2c_probe(void)
}
/* Install error handler */
- if (request_irq(irq, l2c_error_handler, 0, "L2C", 0) < 0) {
+ if (request_irq(irq, l2c_error_handler, 0, "L2C", NULL) < 0) {
printk(KERN_ERR "Cannot install L2C error handler"
", cache is not enabled\n");
of_node_put(np);
diff --git a/arch/powerpc/platforms/83xx/misc.c b/arch/powerpc/platforms/83xx/misc.c
index 2fb2a85d131f..1135c1ab923c 100644
--- a/arch/powerpc/platforms/83xx/misc.c
+++ b/arch/powerpc/platforms/83xx/misc.c
@@ -14,6 +14,8 @@
#include <asm/io.h>
#include <asm/hw_irq.h>
#include <asm/ipic.h>
+#include <asm/fixmap.h>
+
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
diff --git a/arch/powerpc/platforms/8xx/cpm1.c b/arch/powerpc/platforms/8xx/cpm1.c
index ebb5f6a27dbf..b24d4102fbf6 100644
--- a/arch/powerpc/platforms/8xx/cpm1.c
+++ b/arch/powerpc/platforms/8xx/cpm1.c
@@ -40,6 +40,7 @@
#include <asm/io.h>
#include <asm/rheap.h>
#include <asm/cpm.h>
+#include <asm/fixmap.h>
#include <sysdev/fsl_soc.h>
diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
index 77ea9335fd04..f381b177ea06 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -4,6 +4,8 @@
* Copyright (C) 2019 Haren Myneni, IBM Corp
*/
+#define pr_fmt(fmt) "vas-api: " fmt
+
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/cdev.h>
@@ -78,7 +80,7 @@ int get_vas_user_win_ref(struct vas_user_win_ref *task_ref)
task_ref->mm = get_task_mm(current);
if (!task_ref->mm) {
put_pid(task_ref->pid);
- pr_err("VAS: pid(%d): mm_struct is not found\n",
+ pr_err("pid(%d): mm_struct is not found\n",
current->pid);
return -EPERM;
}
@@ -235,8 +237,7 @@ void vas_update_csb(struct coprocessor_request_block *crb,
rc = kill_pid_info(SIGSEGV, &info, pid);
rcu_read_unlock();
- pr_devel("%s(): pid %d kill_proc_info() rc %d\n", __func__,
- pid_vnr(pid), rc);
+ pr_devel("pid %d kill_proc_info() rc %d\n", pid_vnr(pid), rc);
}
void vas_dump_crb(struct coprocessor_request_block *crb)
@@ -294,7 +295,7 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
rc = copy_from_user(&uattr, uptr, sizeof(uattr));
if (rc) {
- pr_err("%s(): copy_from_user() returns %d\n", __func__, rc);
+ pr_err("copy_from_user() returns %d\n", rc);
return -EFAULT;
}
@@ -311,7 +312,7 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
txwin = cp_inst->coproc->vops->open_win(uattr.vas_id, uattr.flags,
cp_inst->coproc->cop_type);
if (IS_ERR(txwin)) {
- pr_err("%s() VAS window open failed, %ld\n", __func__,
+ pr_err_ratelimited("VAS window open failed rc=%ld\n",
PTR_ERR(txwin));
return PTR_ERR(txwin);
}
@@ -405,8 +406,7 @@ static vm_fault_t vas_mmap_fault(struct vm_fault *vmf)
* window is not opened. Shouldn't expect this error.
*/
if (!cp_inst || !cp_inst->txwin) {
- pr_err("%s(): Unexpected fault on paste address with TX window closed\n",
- __func__);
+ pr_err("Unexpected fault on paste address with TX window closed\n");
return VM_FAULT_SIGBUS;
}
@@ -421,8 +421,7 @@ static vm_fault_t vas_mmap_fault(struct vm_fault *vmf)
* issue NX request.
*/
if (txwin->task_ref.vma != vmf->vma) {
- pr_err("%s(): No previous mapping with paste address\n",
- __func__);
+ pr_err("No previous mapping with paste address\n");
return VM_FAULT_SIGBUS;
}
@@ -481,19 +480,19 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma)
txwin = cp_inst->txwin;
if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) {
- pr_debug("%s(): size 0x%zx, PAGE_SIZE 0x%zx\n", __func__,
+ pr_debug("size 0x%zx, PAGE_SIZE 0x%zx\n",
(vma->vm_end - vma->vm_start), PAGE_SIZE);
return -EINVAL;
}
/* Ensure instance has an open send window */
if (!txwin) {
- pr_err("%s(): No send window open?\n", __func__);
+ pr_err("No send window open?\n");
return -EINVAL;
}
if (!cp_inst->coproc->vops || !cp_inst->coproc->vops->paste_addr) {
- pr_err("%s(): VAS API is not registered\n", __func__);
+ pr_err("VAS API is not registered\n");
return -EACCES;
}
@@ -510,14 +509,14 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma)
*/
mutex_lock(&txwin->task_ref.mmap_mutex);
if (txwin->status != VAS_WIN_ACTIVE) {
- pr_err("%s(): Window is not active\n", __func__);
+ pr_err("Window is not active\n");
rc = -EACCES;
goto out;
}
paste_addr = cp_inst->coproc->vops->paste_addr(txwin);
if (!paste_addr) {
- pr_err("%s(): Window paste address failed\n", __func__);
+ pr_err("Window paste address failed\n");
rc = -EINVAL;
goto out;
}
@@ -533,8 +532,8 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma)
rc = remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
vma->vm_end - vma->vm_start, prot);
- pr_devel("%s(): paste addr %llx at %lx, rc %d\n", __func__,
- paste_addr, vma->vm_start, rc);
+ pr_devel("paste addr %llx at %lx, rc %d\n", paste_addr,
+ vma->vm_start, rc);
txwin->task_ref.vma = vma;
vma->vm_ops = &vas_vm_ops;
@@ -609,8 +608,7 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
goto err;
}
- pr_devel("%s: Added dev [%d,%d]\n", __func__, MAJOR(devno),
- MINOR(devno));
+ pr_devel("Added dev [%d,%d]\n", MAJOR(devno), MINOR(devno));
return 0;
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 1a587618015c..18daafbe2e65 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -66,7 +66,7 @@ static int match_context(const void *v, struct file *file, unsigned fd)
*/
static struct spu_context *coredump_next_context(int *fd)
{
- struct spu_context *ctx;
+ struct spu_context *ctx = NULL;
struct file *file;
int n = iterate_fd(current->files, *fd, match_context, NULL);
if (!n)
@@ -74,10 +74,13 @@ static struct spu_context *coredump_next_context(int *fd)
*fd = n - 1;
rcu_read_lock();
- file = lookup_fd_rcu(*fd);
- ctx = SPUFS_I(file_inode(file))->i_ctx;
- get_spu_context(ctx);
+ file = lookup_fdget_rcu(*fd);
rcu_read_unlock();
+ if (file) {
+ ctx = SPUFS_I(file_inode(file))->i_ctx;
+ get_spu_context(ctx);
+ fput(file);
+ }
return ctx;
}
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 38c5be34c895..10c1320adfd0 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -86,7 +86,7 @@ spufs_new_inode(struct super_block *sb, umode_t mode)
inode->i_mode = mode;
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
- inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode);
+ simple_inode_init_ts(inode);
out:
return inode;
}
diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig
index 130707ec9f99..8bdae0caf21e 100644
--- a/arch/powerpc/platforms/powermac/Kconfig
+++ b/arch/powerpc/platforms/powermac/Kconfig
@@ -2,6 +2,7 @@
config PPC_PMAC
bool "Apple PowerMac based machines"
depends on PPC_BOOK3S && CPU_BIG_ENDIAN
+ select ADB_CUDA if POWER_RESET && PPC32
select MPIC
select FORCE_PCI
select PPC_INDIRECT_PCI if PPC32
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index ae62d432db8b..81c9fbae88b1 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -2614,7 +2614,8 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
struct device_node* node;
int i;
volatile u32 __iomem *base;
- const u32 *addrp, *revp;
+ const __be32 *addrp;
+ const u32 *revp;
phys_addr_t addr;
u64 size;
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 40f3aa432fba..c097d591670e 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -925,8 +925,10 @@ static void __init smu_i2c_probe(void)
sz = sizeof(struct pmac_i2c_bus) + sizeof(struct smu_i2c_cmd);
bus = kzalloc(sz, GFP_KERNEL);
- if (bus == NULL)
+ if (bus == NULL) {
+ of_node_put(busnode);
return;
+ }
bus->controller = controller;
bus->busnode = of_node_get(busnode);
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 8be71920e63c..c83d1e14077e 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -598,8 +598,10 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus)
name = "Pulsar";
break;
}
- if (pmac_tb_freeze != NULL)
+ if (pmac_tb_freeze != NULL) {
+ of_node_put(cc);
break;
+ }
}
if (pmac_tb_freeze != NULL) {
/* Open i2c bus for synchronous access */
diff --git a/arch/powerpc/platforms/powernv/opal-fadump.h b/arch/powerpc/platforms/powernv/opal-fadump.h
index 3f715efb0aa6..5eeb794b5eb1 100644
--- a/arch/powerpc/platforms/powernv/opal-fadump.h
+++ b/arch/powerpc/platforms/powernv/opal-fadump.h
@@ -135,7 +135,7 @@ static inline void opal_fadump_read_regs(char *bufp, unsigned int regs_cnt,
for (i = 0; i < regs_cnt; i++, bufp += reg_entry_size) {
reg_entry = (struct hdat_fadump_reg_entry *)bufp;
val = (cpu_endian ? be64_to_cpu(reg_entry->reg_val) :
- (u64)(reg_entry->reg_val));
+ (u64 __force)(reg_entry->reg_val));
opal_fadump_set_regval_regnum(regs,
be32_to_cpu(reg_entry->reg_type),
be32_to_cpu(reg_entry->reg_num),
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 4ebf2ef2845d..afc0f6a61337 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -164,6 +164,12 @@ config PSERIES_PLPKS
# This option is selected by in-kernel consumers that require
# access to the PKS.
+config PSERIES_PLPKS_SED
+ depends on PPC_PSERIES
+ bool
+ # This option is selected by in-kernel consumers that require
+ # access to the SED PKS keystore.
+
config PAPR_SCM
depends on PPC_PSERIES && MEMORY_HOTPLUG && LIBNVDIMM
tristate "Support for the PAPR Storage Class Memory interface"
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 53c3b91af2f7..1476c5e4433c 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_PPC_SVM) += svm.o
obj-$(CONFIG_FA_DUMP) += rtas-fadump.o
obj-$(CONFIG_PSERIES_PLPKS) += plpks.o
obj-$(CONFIG_PPC_SECURE_BOOT) += plpks-secvar.o
+obj-$(CONFIG_PSERIES_PLPKS_SED) += plpks_sed_ops.o
obj-$(CONFIG_SUSPEND) += suspend.o
obj-$(CONFIG_PPC_VAS) += vas.o vas-sysfs.o
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index aa4042dcd6d4..a43bfb01720a 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -55,7 +55,8 @@ static bool find_aa_index(struct device_node *dr_node,
struct property *ala_prop,
const u32 *lmb_assoc, u32 *aa_index)
{
- u32 *assoc_arrays, new_prop_size;
+ __be32 *assoc_arrays;
+ u32 new_prop_size;
struct property *new_prop;
int aa_arrays, aa_array_entries, aa_array_sz;
int i, index;
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S
index bae45b358a09..2b0cac6fb61f 100644
--- a/arch/powerpc/platforms/pseries/hvCall.S
+++ b/arch/powerpc/platforms/pseries/hvCall.S
@@ -184,9 +184,6 @@ _GLOBAL_TOC(plpar_hcall)
plpar_hcall_trace:
HCALL_INST_PRECALL(R5)
- std r4,STK_PARAM(R4)(r1)
- mr r0,r4
-
mr r4,r5
mr r5,r6
mr r6,r7
@@ -196,7 +193,7 @@ plpar_hcall_trace:
HVSC
- ld r12,STK_PARAM(R4)(r1)
+ ld r12,STACK_FRAME_MIN_SIZE+STK_PARAM(R4)(r1)
std r4,0(r12)
std r5,8(r12)
std r6,16(r12)
@@ -296,9 +293,6 @@ _GLOBAL_TOC(plpar_hcall9)
plpar_hcall9_trace:
HCALL_INST_PRECALL(R5)
- std r4,STK_PARAM(R4)(r1)
- mr r0,r4
-
mr r4,r5
mr r5,r6
mr r6,r7
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 16d93b580f61..496e16c588aa 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -914,7 +914,8 @@ static int remove_ddw(struct device_node *np, bool remove_prop, const char *win_
return 0;
}
-static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *window_shift)
+static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *window_shift,
+ bool *direct_mapping)
{
struct dma_win *window;
const struct dynamic_dma_window_prop *dma64;
@@ -927,6 +928,7 @@ static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *windo
dma64 = window->prop;
*dma_addr = be64_to_cpu(dma64->dma_base);
*window_shift = be32_to_cpu(dma64->window_shift);
+ *direct_mapping = window->direct;
found = true;
break;
}
@@ -1270,10 +1272,8 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
mutex_lock(&dma_win_init_mutex);
- if (find_existing_ddw(pdn, &dev->dev.archdata.dma_offset, &len)) {
- direct_mapping = (len >= max_ram_len);
+ if (find_existing_ddw(pdn, &dev->dev.archdata.dma_offset, &len, &direct_mapping))
goto out_unlock;
- }
/*
* If we already went through this for a previous function of
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index f2cb62148f36..4561667832ed 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -192,9 +192,9 @@ static void free_dtl_buffers(unsigned long *time_limit)
continue;
kmem_cache_free(dtl_cache, pp->dispatch_log);
pp->dtl_ridx = 0;
- pp->dispatch_log = 0;
- pp->dispatch_log_end = 0;
- pp->dtl_curr = 0;
+ pp->dispatch_log = NULL;
+ pp->dispatch_log_end = NULL;
+ pp->dtl_curr = NULL;
if (time_limit && time_after(jiffies, *time_limit)) {
cond_resched();
@@ -223,7 +223,7 @@ static void destroy_cpu_associativity(void)
{
kfree(vcpu_associativity);
kfree(pcpu_associativity);
- vcpu_associativity = pcpu_associativity = 0;
+ vcpu_associativity = pcpu_associativity = NULL;
}
static __be32 *__get_cpu_associativity(int cpu, __be32 *cpu_assoc, int flag)
@@ -526,8 +526,10 @@ static ssize_t vcpudispatch_stats_write(struct file *file, const char __user *p,
if (cmd) {
rc = init_cpu_associativity();
- if (rc)
+ if (rc) {
+ destroy_cpu_associativity();
goto out;
+ }
for_each_possible_cpu(cpu) {
disp = per_cpu_ptr(&vcpu_disp_data, cpu);
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
index 0161226d8fec..1798f0f14d58 100644
--- a/arch/powerpc/platforms/pseries/mobility.c
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -61,7 +61,6 @@ static struct ctl_table nmi_wd_lpm_factor_ctl_table[] = {
.mode = 0644,
.proc_handler = proc_douintvec_minmax,
},
- {}
};
static int __init register_nmi_wd_lpm_factor_sysctl(void)
diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c
index 2d40304eb6c1..febe18f251d0 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -150,7 +150,7 @@ static int plpks_gen_password(void)
ospasswordlength = maxpwsize;
ospassword = kzalloc(maxpwsize, GFP_KERNEL);
if (!ospassword) {
- kfree(password);
+ kfree_sensitive(password);
return -ENOMEM;
}
memcpy(ospassword, password, ospasswordlength);
@@ -163,7 +163,7 @@ static int plpks_gen_password(void)
}
}
out:
- kfree(password);
+ kfree_sensitive(password);
return pseries_status_to_err(rc);
}
diff --git a/arch/powerpc/platforms/pseries/plpks_sed_ops.c b/arch/powerpc/platforms/pseries/plpks_sed_ops.c
new file mode 100644
index 000000000000..7c873c9589ef
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/plpks_sed_ops.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * POWER Platform specific code for non-volatile SED key access
+ * Copyright (C) 2022 IBM Corporation
+ *
+ * Define operations for SED Opal to read/write keys
+ * from POWER LPAR Platform KeyStore(PLPKS).
+ *
+ * Self Encrypting Drives(SED) key storage using PLPKS
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/ioctl.h>
+#include <linux/sed-opal-key.h>
+#include <asm/plpks.h>
+
+static bool plpks_sed_initialized = false;
+static bool plpks_sed_available = false;
+
+/*
+ * structure that contains all SED data
+ */
+struct plpks_sed_object_data {
+ u_char version;
+ u_char pad1[7];
+ u_long authority;
+ u_long range;
+ u_int key_len;
+ u_char key[32];
+};
+
+#define PLPKS_SED_OBJECT_DATA_V0 0
+#define PLPKS_SED_MANGLED_LABEL "/default/pri"
+#define PLPKS_SED_COMPONENT "sed-opal"
+#define PLPKS_SED_KEY "opal-boot-pin"
+
+/*
+ * authority is admin1 and range is global
+ */
+#define PLPKS_SED_AUTHORITY 0x0000000900010001
+#define PLPKS_SED_RANGE 0x0000080200000001
+
+static void plpks_init_var(struct plpks_var *var, char *keyname)
+{
+ if (!plpks_sed_initialized) {
+ plpks_sed_initialized = true;
+ plpks_sed_available = plpks_is_available();
+ if (!plpks_sed_available)
+ pr_err("SED: plpks not available\n");
+ }
+
+ var->name = keyname;
+ var->namelen = strlen(keyname);
+ if (strcmp(PLPKS_SED_KEY, keyname) == 0) {
+ var->name = PLPKS_SED_MANGLED_LABEL;
+ var->namelen = strlen(keyname);
+ }
+ var->policy = PLPKS_WORLDREADABLE;
+ var->os = PLPKS_VAR_COMMON;
+ var->data = NULL;
+ var->datalen = 0;
+ var->component = PLPKS_SED_COMPONENT;
+}
+
+/*
+ * Read the SED Opal key from PLPKS given the label
+ */
+int sed_read_key(char *keyname, char *key, u_int *keylen)
+{
+ struct plpks_var var;
+ struct plpks_sed_object_data data;
+ int ret;
+ u_int len;
+
+ plpks_init_var(&var, keyname);
+
+ if (!plpks_sed_available)
+ return -EOPNOTSUPP;
+
+ var.data = (u8 *)&data;
+ var.datalen = sizeof(data);
+
+ ret = plpks_read_os_var(&var);
+ if (ret != 0)
+ return ret;
+
+ len = min_t(u16, be32_to_cpu(data.key_len), var.datalen);
+ memcpy(key, data.key, len);
+ key[len] = '\0';
+ *keylen = len;
+
+ return 0;
+}
+
+/*
+ * Write the SED Opal key to PLPKS given the label
+ */
+int sed_write_key(char *keyname, char *key, u_int keylen)
+{
+ struct plpks_var var;
+ struct plpks_sed_object_data data;
+ struct plpks_var_name vname;
+
+ plpks_init_var(&var, keyname);
+
+ if (!plpks_sed_available)
+ return -EOPNOTSUPP;
+
+ var.datalen = sizeof(struct plpks_sed_object_data);
+ var.data = (u8 *)&data;
+
+ /* initialize SED object */
+ data.version = PLPKS_SED_OBJECT_DATA_V0;
+ data.authority = cpu_to_be64(PLPKS_SED_AUTHORITY);
+ data.range = cpu_to_be64(PLPKS_SED_RANGE);
+ memset(&data.pad1, '\0', sizeof(data.pad1));
+ data.key_len = cpu_to_be32(keylen);
+ memcpy(data.key, (char *)key, keylen);
+
+ /*
+ * Key update requires remove first. The return value
+ * is ignored since it's okay if the key doesn't exist.
+ */
+ vname.namelen = var.namelen;
+ vname.name = var.name;
+ plpks_remove_var(var.component, var.os, vname);
+
+ return plpks_write_var(var);
+}
diff --git a/arch/powerpc/platforms/pseries/rtas-work-area.c b/arch/powerpc/platforms/pseries/rtas-work-area.c
index b37d52f40360..7fe34bee84d8 100644
--- a/arch/powerpc/platforms/pseries/rtas-work-area.c
+++ b/arch/powerpc/platforms/pseries/rtas-work-area.c
@@ -184,6 +184,7 @@ machine_arch_initcall(pseries, rtas_work_area_allocator_init);
/**
* rtas_work_area_reserve_arena() - Reserve memory suitable for RTAS work areas.
+ * @limit: Upper limit for memblock allocation.
*/
void __init rtas_work_area_reserve_arena(const phys_addr_t limit)
{
diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
index e25ac52acf50..71d52a670d95 100644
--- a/arch/powerpc/platforms/pseries/vas.c
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -341,7 +341,7 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags,
if (atomic_inc_return(&cop_feat_caps->nr_used_credits) >
atomic_read(&cop_feat_caps->nr_total_credits)) {
- pr_err("Credits are not available to allocate window\n");
+ pr_err_ratelimited("Credits are not available to allocate window\n");
rc = -EINVAL;
goto out;
}
@@ -385,11 +385,15 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags,
* same fault IRQ is not freed by the OS before.
*/
mutex_lock(&vas_pseries_mutex);
- if (migration_in_progress)
+ if (migration_in_progress) {
rc = -EBUSY;
- else
+ } else {
rc = allocate_setup_window(txwin, (u64 *)&domain[0],
cop_feat_caps->win_type);
+ if (!rc)
+ caps->nr_open_wins_progress++;
+ }
+
mutex_unlock(&vas_pseries_mutex);
if (rc)
goto out;
@@ -404,8 +408,17 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags,
goto out_free;
txwin->win_type = cop_feat_caps->win_type;
- mutex_lock(&vas_pseries_mutex);
+
/*
+ * The migration SUSPEND thread sets migration_in_progress and
+ * closes all open windows from the list. But the window is
+ * added to the list after open and modify HCALLs. So possible
+ * that migration_in_progress is set before modify HCALL which
+ * may cause some windows are still open when the hypervisor
+ * initiates the migration.
+ * So checks the migration_in_progress flag again and close all
+ * open windows.
+ *
* Possible to lose the acquired credit with DLPAR core
* removal after the window is opened. So if there are any
* closed windows (means with lost credits), do not give new
@@ -413,9 +426,11 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags,
* after the existing windows are reopened when credits are
* available.
*/
- if (!caps->nr_close_wins) {
+ mutex_lock(&vas_pseries_mutex);
+ if (!caps->nr_close_wins && !migration_in_progress) {
list_add(&txwin->win_list, &caps->list);
caps->nr_open_windows++;
+ caps->nr_open_wins_progress--;
mutex_unlock(&vas_pseries_mutex);
vas_user_win_add_mm_context(&txwin->vas_win.task_ref);
return &txwin->vas_win;
@@ -424,7 +439,7 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags,
put_vas_user_win_ref(&txwin->vas_win.task_ref);
rc = -EBUSY;
- pr_err("No credit is available to allocate window\n");
+ pr_err_ratelimited("No credit is available to allocate window\n");
out_free:
/*
@@ -433,6 +448,12 @@ out_free:
*/
free_irq_setup(txwin);
h_deallocate_vas_window(txwin->vas_win.winid);
+ /*
+ * Hold mutex and reduce nr_open_wins_progress counter.
+ */
+ mutex_lock(&vas_pseries_mutex);
+ caps->nr_open_wins_progress--;
+ mutex_unlock(&vas_pseries_mutex);
out:
atomic_dec(&cop_feat_caps->nr_used_credits);
kfree(txwin);
@@ -937,14 +958,14 @@ int vas_migration_handler(int action)
struct vas_caps *vcaps;
int i, rc = 0;
+ pr_info("VAS migration event %d\n", action);
+
/*
* NX-GZIP is not enabled. Nothing to do for migration.
*/
if (!copypaste_feat)
return rc;
- mutex_lock(&vas_pseries_mutex);
-
if (action == VAS_SUSPEND)
migration_in_progress = true;
else
@@ -990,12 +1011,27 @@ int vas_migration_handler(int action)
switch (action) {
case VAS_SUSPEND:
+ mutex_lock(&vas_pseries_mutex);
rc = reconfig_close_windows(vcaps, vcaps->nr_open_windows,
true);
+ /*
+ * Windows are included in the list after successful
+ * open. So wait for closing these in-progress open
+ * windows in vas_allocate_window() which will be
+ * done if the migration_in_progress is set.
+ */
+ while (vcaps->nr_open_wins_progress) {
+ mutex_unlock(&vas_pseries_mutex);
+ msleep(10);
+ mutex_lock(&vas_pseries_mutex);
+ }
+ mutex_unlock(&vas_pseries_mutex);
break;
case VAS_RESUME:
+ mutex_lock(&vas_pseries_mutex);
atomic_set(&caps->nr_total_credits, new_nr_creds);
rc = reconfig_open_windows(vcaps, new_nr_creds, true);
+ mutex_unlock(&vas_pseries_mutex);
break;
default:
/* should not happen */
@@ -1011,8 +1047,9 @@ int vas_migration_handler(int action)
goto out;
}
+ pr_info("VAS migration event (%d) successful\n", action);
+
out:
- mutex_unlock(&vas_pseries_mutex);
return rc;
}
diff --git a/arch/powerpc/platforms/pseries/vas.h b/arch/powerpc/platforms/pseries/vas.h
index 7115043ec488..45567cd13178 100644
--- a/arch/powerpc/platforms/pseries/vas.h
+++ b/arch/powerpc/platforms/pseries/vas.h
@@ -91,6 +91,8 @@ struct vas_cop_feat_caps {
struct vas_caps {
struct vas_cop_feat_caps caps;
struct list_head list; /* List of open windows */
+ int nr_open_wins_progress; /* Number of open windows in */
+ /* progress. Used in migration */
int nr_close_wins; /* closed windows in the hypervisor for DLPAR */
int nr_open_windows; /* Number of successful open windows */
u8 feat; /* Feature type */
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 57978a44d55b..558ec68d768e 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -11,9 +11,11 @@
#include <linux/msi.h>
#include <linux/pci.h>
#include <linux/slab.h>
+#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/seq_file.h>
@@ -392,7 +394,6 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev,
static const struct of_device_id fsl_of_msi_ids[];
static int fsl_of_msi_probe(struct platform_device *dev)
{
- const struct of_device_id *match;
struct fsl_msi *msi;
struct resource res, msiir;
int err, i, j, irq_index, count;
@@ -402,10 +403,7 @@ static int fsl_of_msi_probe(struct platform_device *dev)
u32 offset;
struct pci_controller *phb;
- match = of_match_device(fsl_of_msi_ids, &dev->dev);
- if (!match)
- return -EINVAL;
- features = match->data;
+ features = device_get_match_data(&dev->dev);
printk(KERN_DEBUG "Setting up Freescale MSI support\n");
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index ba287abcb008..dabbdd356664 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -355,7 +355,7 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic)
mpic_write(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0), MPIC_VECPRI_MASK);
r = mpic_read(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0));
- if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
+ if (r == swab32(MPIC_VECPRI_MASK)) {
printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
mpic->flags |= MPIC_BROKEN_IPI;
}
diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c
index 9f0af4d795d8..f1c0fa6ece21 100644
--- a/arch/powerpc/sysdev/xive/native.c
+++ b/arch/powerpc/sysdev/xive/native.c
@@ -802,7 +802,7 @@ int xive_native_get_queue_info(u32 vp_id, u32 prio,
if (out_qpage)
*out_qpage = be64_to_cpu(qpage);
if (out_qsize)
- *out_qsize = be32_to_cpu(qsize);
+ *out_qsize = be64_to_cpu(qsize);
if (out_qeoi_page)
*out_qeoi_page = be64_to_cpu(qeoi_page);
if (out_escalate_irq)
diff --git a/arch/powerpc/tools/gcc-check-mprofile-kernel.sh b/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
index a31a56016c09..73e331e7660e 100755
--- a/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
+++ b/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
@@ -7,21 +7,20 @@ set -o pipefail
# To debug, uncomment the following line
# set -x
-# -mprofile-kernel is only supported on 64-bit, so this should not be invoked
-# for 32-bit. We pass in -m64 explicitly, and -mbig-endian and -mlittle-endian
-# are passed in from Kconfig, which takes care of toolchains defaulting to
-# other targets.
+# -mprofile-kernel is only supported on 64-bit with ELFv2, so this should not
+# be invoked for other targets. Therefore we can pass in -m64 and -mabi
+# explicitly, to take care of toolchains defaulting to other targets.
# Test whether the compile option -mprofile-kernel exists and generates
# profiling code (ie. a call to _mcount()).
echo "int func() { return 0; }" | \
- $* -m64 -S -x c -O2 -p -mprofile-kernel - -o - \
+ $* -m64 -mabi=elfv2 -S -x c -O2 -p -mprofile-kernel - -o - \
2> /dev/null | grep -q "_mcount"
# Test whether the notrace attribute correctly suppresses calls to _mcount().
echo -e "#include <linux/compiler.h>\nnotrace int func() { return 0; }" | \
- $* -m64 -S -x c -O2 -p -mprofile-kernel - -o - \
+ $* -m64 -mabi=elfv2 -S -x c -O2 -p -mprofile-kernel - -o - \
2> /dev/null | grep -q "_mcount" && \
exit 1
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index d607ab0f7c6d..24c1799e2ec4 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -39,6 +39,7 @@ config RISCV
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAS_UBSAN_SANITIZE_ALL
select ARCH_HAS_VDSO_DATA
+ select ARCH_KEEP_MEMBLOCK if ACPI
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
select ARCH_STACKWALK
@@ -48,6 +49,7 @@ config RISCV
select ARCH_SUPPORTS_HUGETLBFS if MMU
select ARCH_SUPPORTS_PAGE_TABLE_CHECK if MMU
select ARCH_SUPPORTS_PER_VMA_LOCK if MMU
+ select ARCH_SUPPORTS_SHADOW_CALL_STACK if HAVE_SHADOW_CALL_STACK
select ARCH_USE_MEMTEST
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USES_CFI_TRAPS if CFI_CLANG
@@ -174,6 +176,11 @@ config GCC_SUPPORTS_DYNAMIC_FTRACE
def_bool CC_IS_GCC
depends on $(cc-option,-fpatchable-function-entry=8)
+config HAVE_SHADOW_CALL_STACK
+ def_bool $(cc-option,-fsanitize=shadow-call-stack)
+ # https://github.com/riscv-non-isa/riscv-elf-psabi-doc/commit/a484e843e6eeb51f0cb7b8819e50da6d2444d769
+ depends on $(ld-option,--no-relax-gp)
+
config ARCH_MMAP_RND_BITS_MIN
default 18 if 64BIT
default 8
@@ -273,11 +280,9 @@ config RISCV_DMA_NONCOHERENT
select ARCH_HAS_SYNC_DMA_FOR_CPU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select DMA_BOUNCE_UNALIGNED_KMALLOC if SWIOTLB
- select DMA_DIRECT_REMAP if MMU
config RISCV_NONSTANDARD_CACHE_OPS
bool
- depends on RISCV_DMA_NONCOHERENT
help
This enables function pointer support for non-standard noncoherent
systems to handle cache management.
@@ -550,6 +555,7 @@ config RISCV_ISA_ZICBOM
depends on RISCV_ALTERNATIVE
default y
select RISCV_DMA_NONCOHERENT
+ select DMA_DIRECT_REMAP
help
Adds support to dynamically detect the presence of the ZICBOM
extension (Cache Block Management Operations) and enable its
@@ -636,6 +642,15 @@ config THREAD_SIZE_ORDER
Specify the Pages of thread stack size (from 4KB to 64KB), which also
affects irq stack size, which is equal to thread stack size.
+config RISCV_MISALIGNED
+ bool "Support misaligned load/store traps for kernel and userspace"
+ select SYSCTL_ARCH_UNALIGN_ALLOW
+ default y
+ help
+ Say Y here if you want the kernel to embed support for misaligned
+ load/store for both kernel and userspace. When disable, misaligned
+ accesses will generate SIGBUS in userspace and panic in kernel.
+
endmenu # "Platform type"
menu "Kernel features"
@@ -670,7 +685,7 @@ config RISCV_BOOT_SPINWAIT
If unsure what to do here, say N.
config ARCH_SUPPORTS_KEXEC
- def_bool MMU
+ def_bool y
config ARCH_SELECTS_KEXEC
def_bool y
@@ -678,7 +693,7 @@ config ARCH_SELECTS_KEXEC
select HOTPLUG_CPU if SMP
config ARCH_SUPPORTS_KEXEC_FILE
- def_bool 64BIT && MMU
+ def_bool 64BIT
config ARCH_SELECTS_KEXEC_FILE
def_bool y
@@ -694,6 +709,9 @@ config ARCH_SUPPORTS_KEXEC_PURGATORY
config ARCH_SUPPORTS_CRASH_DUMP
def_bool y
+config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
+ def_bool CRASH_CORE
+
config COMPAT
bool "Kernel support for 32-bit U-mode"
default 64BIT
@@ -900,6 +918,9 @@ config PORTABLE
select MMU
select OF
+config ARCH_PROC_KCORE_TEXT
+ def_bool y
+
menu "Power management options"
source "kernel/power/Kconfig"
diff --git a/arch/riscv/Kconfig.debug b/arch/riscv/Kconfig.debug
index e69de29bb2d1..eafe17ebf710 100644
--- a/arch/riscv/Kconfig.debug
+++ b/arch/riscv/Kconfig.debug
@@ -0,0 +1 @@
+source "arch/riscv/kernel/tests/Kconfig.debug"
diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
index 566bcefeab50..e2c731cfed8c 100644
--- a/arch/riscv/Kconfig.errata
+++ b/arch/riscv/Kconfig.errata
@@ -77,6 +77,7 @@ config ERRATA_THEAD_PBMT
config ERRATA_THEAD_CMO
bool "Apply T-Head cache management errata"
depends on ERRATA_THEAD && MMU
+ select DMA_DIRECT_REMAP
select RISCV_DMA_NONCOHERENT
default y
help
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 6833d01e2e70..e08e91c49abe 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -22,6 +22,11 @@ config SOC_SIFIVE
help
This enables support for SiFive SoC platform hardware.
+config ARCH_SOPHGO
+ bool "Sophgo SoCs"
+ help
+ This enables support for Sophgo SoC platform hardware.
+
config ARCH_STARFIVE
def_bool SOC_STARFIVE
@@ -29,6 +34,7 @@ config SOC_STARFIVE
bool "StarFive SoCs"
select PINCTRL
select RESET_CONTROLLER
+ select ARM_AMBA
help
This enables support for StarFive SoC platform hardware.
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 1329e060c548..a74be78678eb 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -6,7 +6,6 @@
# for more details.
#
-OBJCOPYFLAGS := -O binary
LDFLAGS_vmlinux := -z norelro
ifeq ($(CONFIG_RELOCATABLE),y)
LDFLAGS_vmlinux += -shared -Bsymbolic -z notext --emit-relocs
@@ -55,6 +54,10 @@ endif
endif
endif
+ifeq ($(CONFIG_SHADOW_CALL_STACK),y)
+ KBUILD_LDFLAGS += --no-relax-gp
+endif
+
# ISA string setting
riscv-march-$(CONFIG_ARCH_RV32I) := rv32ima
riscv-march-$(CONFIG_ARCH_RV64I) := rv64ima
@@ -131,12 +134,6 @@ endif
libs-y += arch/riscv/lib/
libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
-PHONY += vdso_install
-vdso_install:
- $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@
- $(if $(CONFIG_COMPAT),$(Q)$(MAKE) \
- $(build)=arch/riscv/kernel/compat_vdso compat_$@)
-
ifeq ($(KBUILD_EXTMOD),)
ifeq ($(CONFIG_MMU),y)
prepare: vdso_prepare
@@ -148,6 +145,9 @@ vdso_prepare: prepare0
endif
endif
+vdso-install-y += arch/riscv/kernel/vdso/vdso.so.dbg
+vdso-install-$(CONFIG_COMPAT) += arch/riscv/kernel/compat_vdso/compat_vdso.so.dbg:../compat_vdso/compat_vdso.so
+
ifneq ($(CONFIG_XIP_KERNEL),y)
ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_ARCH_CANAAN),yy)
KBUILD_IMAGE := $(boot)/loader.bin
diff --git a/arch/riscv/Makefile.postlink b/arch/riscv/Makefile.postlink
index a46fc578b30b..829b9abc91f6 100644
--- a/arch/riscv/Makefile.postlink
+++ b/arch/riscv/Makefile.postlink
@@ -36,9 +36,6 @@ ifdef CONFIG_RELOCATABLE
$(call if_changed,relocs_strip)
endif
-%.ko: FORCE
- @true
-
clean:
@true
diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile
index 22b13947bd13..8e7fc0edf21d 100644
--- a/arch/riscv/boot/Makefile
+++ b/arch/riscv/boot/Makefile
@@ -17,6 +17,7 @@
KCOV_INSTRUMENT := n
OBJCOPYFLAGS_Image :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
+OBJCOPYFLAGS_loader.bin :=-O binary
OBJCOPYFLAGS_xipImage :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
targets := Image Image.* loader loader.o loader.lds loader.bin
diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile
index f60a280abb15..72030fd727af 100644
--- a/arch/riscv/boot/dts/Makefile
+++ b/arch/riscv/boot/dts/Makefile
@@ -4,6 +4,7 @@ subdir-y += canaan
subdir-y += microchip
subdir-y += renesas
subdir-y += sifive
+subdir-y += sophgo
subdir-y += starfive
subdir-y += thead
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-common-regulators.dtsi b/arch/riscv/boot/dts/allwinner/sun20i-common-regulators.dtsi
index 9b03fca2444c..ed7b12e65a10 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-common-regulators.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-common-regulators.dtsi
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
/ {
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-dongshan-nezha-stu.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-dongshan-nezha-stu.dts
index 8785de3c9224..3a2c3281eb88 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-dongshan-nezha-stu.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-dongshan-nezha-stu.dts
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
#include <dt-bindings/gpio/gpio.h>
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-480p.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-480p.dts
index 4df8ffb71561..711450ffb602 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-480p.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-480p.dts
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
#include "sun20i-d1-lichee-rv-86-panel.dtsi"
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-720p.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-720p.dts
index 1874fc05359f..b217799e6166 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-720p.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-720p.dts
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
#include "sun20i-d1-lichee-rv-86-panel.dtsi"
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel.dtsi b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel.dtsi
index 6cc7dd0c1ae2..10116fb3935a 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel.dtsi
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
#include "sun20i-d1-lichee-rv.dts"
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts
index 52b91e1affed..08cf716328a0 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2022 Jisheng Zhang <jszhang@kernel.org>
// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv.dts
index d60a0562a8b1..204da82a5dc6 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv.dts
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2022 Jisheng Zhang <jszhang@kernel.org>
// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-mangopi-mq-pro.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-mangopi-mq-pro.dts
index f2e07043afb3..e2bb6bc16c13 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-mangopi-mq-pro.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-mangopi-mq-pro.dts
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
#include <dt-bindings/gpio/gpio.h>
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
index 4ed33c1e7c9c..8dbe717c79ce 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
/*
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
index 97e7cbb32597..b18f368e06e0 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
#include "sun20i-d1s.dtsi"
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1s-mangopi-mq.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1s-mangopi-mq.dts
index e6d924f671fd..1a7d6ef33f17 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1s-mangopi-mq.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1s-mangopi-mq.dts
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
#include <dt-bindings/gpio/gpio.h>
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1s.dtsi b/arch/riscv/boot/dts/allwinner/sun20i-d1s.dtsi
index 8275630af977..64c3c2e6cbe0 100644
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1s.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1s.dtsi
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
#define SOC_PERIPHERAL_IRQ(nr) (nr + 16)
@@ -25,12 +25,14 @@
mmu-type = "riscv,sv39";
operating-points-v2 = <&opp_table_cpu>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
#cooling-cells = <2>;
cpu0_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
interrupt-controller;
- #address-cells = <0>;
#interrupt-cells = <1>;
};
};
@@ -73,4 +75,43 @@
#interrupt-cells = <2>;
};
};
+
+ pmu {
+ compatible = "riscv,pmu";
+ riscv,event-to-mhpmcounters =
+ <0x00003 0x00003 0x00000008>,
+ <0x00004 0x00004 0x00000010>,
+ <0x00005 0x00005 0x00000200>,
+ <0x00006 0x00006 0x00000100>,
+ <0x10000 0x10000 0x00004000>,
+ <0x10001 0x10001 0x00008000>,
+ <0x10002 0x10002 0x00010000>,
+ <0x10003 0x10003 0x00020000>,
+ <0x10019 0x10019 0x00000040>,
+ <0x10021 0x10021 0x00000020>;
+ riscv,event-to-mhpmevent =
+ <0x00003 0x00000000 0x00000001>,
+ <0x00004 0x00000000 0x00000002>,
+ <0x00005 0x00000000 0x00000007>,
+ <0x00006 0x00000000 0x00000006>,
+ <0x10000 0x00000000 0x0000000c>,
+ <0x10001 0x00000000 0x0000000d>,
+ <0x10002 0x00000000 0x0000000e>,
+ <0x10003 0x00000000 0x0000000f>,
+ <0x10019 0x00000000 0x00000004>,
+ <0x10021 0x00000000 0x00000003>;
+ riscv,raw-event-to-mhpmcounters =
+ <0x00000000 0x00000001 0xffffffff 0xffffffff 0x00000008>,
+ <0x00000000 0x00000002 0xffffffff 0xffffffff 0x00000010>,
+ <0x00000000 0x00000003 0xffffffff 0xffffffff 0x00000020>,
+ <0x00000000 0x00000004 0xffffffff 0xffffffff 0x00000040>,
+ <0x00000000 0x00000005 0xffffffff 0xffffffff 0x00000080>,
+ <0x00000000 0x00000006 0xffffffff 0xffffffff 0x00000100>,
+ <0x00000000 0x00000007 0xffffffff 0xffffffff 0x00000200>,
+ <0x00000000 0x0000000b 0xffffffff 0xffffffff 0x00002000>,
+ <0x00000000 0x0000000c 0xffffffff 0xffffffff 0x00004000>,
+ <0x00000000 0x0000000d 0xffffffff 0xffffffff 0x00008000>,
+ <0x00000000 0x0000000e 0xffffffff 0xffffffff 0x00010000>,
+ <0x00000000 0x0000000f 0xffffffff 0xffffffff 0x00020000>;
+ };
};
diff --git a/arch/riscv/boot/dts/allwinner/sunxi-d1-t113.dtsi b/arch/riscv/boot/dts/allwinner/sunxi-d1-t113.dtsi
index b7156123df54..3b077dc086ab 100644
--- a/arch/riscv/boot/dts/allwinner/sunxi-d1-t113.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sunxi-d1-t113.dtsi
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
/ {
diff --git a/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi b/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi
index 822f022eec2d..5a9d7f5a75b4 100644
--- a/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
#include <dt-bindings/clock/sun6i-rtc.h>
diff --git a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts
index 90b261114763..dce96f27cc89 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts
+++ b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts
@@ -8,9 +8,6 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
-/* Clock frequency (in Hz) of the rtcclk */
-#define RTCCLK_FREQ 1000000
-
/ {
model = "Microchip PolarFire-SoC Icicle Kit";
compatible = "microchip,mpfs-icicle-reference-rtlv2210", "microchip,mpfs-icicle-kit",
@@ -29,10 +26,6 @@
stdout-path = "serial1:115200n8";
};
- cpus {
- timebase-frequency = <RTCCLK_FREQ>;
- };
-
leds {
compatible = "gpio-leds";
diff --git a/arch/riscv/boot/dts/microchip/mpfs-m100pfsevp.dts b/arch/riscv/boot/dts/microchip/mpfs-m100pfsevp.dts
index 184cb36a175e..a8d623ee9fa4 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-m100pfsevp.dts
+++ b/arch/riscv/boot/dts/microchip/mpfs-m100pfsevp.dts
@@ -10,9 +10,6 @@
#include "mpfs.dtsi"
#include "mpfs-m100pfs-fabric.dtsi"
-/* Clock frequency (in Hz) of the rtcclk */
-#define MTIMER_FREQ 1000000
-
/ {
model = "Aries Embedded M100PFEVPS";
compatible = "aries,m100pfsevp", "microchip,mpfs";
@@ -33,10 +30,6 @@
stdout-path = "serial1:115200n8";
};
- cpus {
- timebase-frequency = <MTIMER_FREQ>;
- };
-
ddrc_cache_lo: memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x40000000>;
diff --git a/arch/riscv/boot/dts/microchip/mpfs-polarberry.dts b/arch/riscv/boot/dts/microchip/mpfs-polarberry.dts
index c87cc2d8fe29..ea0808ab1042 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-polarberry.dts
+++ b/arch/riscv/boot/dts/microchip/mpfs-polarberry.dts
@@ -6,9 +6,6 @@
#include "mpfs.dtsi"
#include "mpfs-polarberry-fabric.dtsi"
-/* Clock frequency (in Hz) of the rtcclk */
-#define MTIMER_FREQ 1000000
-
/ {
model = "Sundance PolarBerry";
compatible = "sundance,polarberry", "microchip,mpfs";
@@ -22,10 +19,6 @@
stdout-path = "serial0:115200n8";
};
- cpus {
- timebase-frequency = <MTIMER_FREQ>;
- };
-
ddrc_cache_lo: memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x2e000000>;
diff --git a/arch/riscv/boot/dts/microchip/mpfs-sev-kit.dts b/arch/riscv/boot/dts/microchip/mpfs-sev-kit.dts
index 013cb666c72d..f9a890579438 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-sev-kit.dts
+++ b/arch/riscv/boot/dts/microchip/mpfs-sev-kit.dts
@@ -6,9 +6,6 @@
#include "mpfs.dtsi"
#include "mpfs-sev-kit-fabric.dtsi"
-/* Clock frequency (in Hz) of the rtcclk */
-#define MTIMER_FREQ 1000000
-
/ {
#address-cells = <2>;
#size-cells = <2>;
@@ -28,10 +25,6 @@
stdout-path = "serial1:115200n8";
};
- cpus {
- timebase-frequency = <MTIMER_FREQ>;
- };
-
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
diff --git a/arch/riscv/boot/dts/microchip/mpfs-tysom-m.dts b/arch/riscv/boot/dts/microchip/mpfs-tysom-m.dts
index e0797c7e1b35..d1120f5f2c01 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-tysom-m.dts
+++ b/arch/riscv/boot/dts/microchip/mpfs-tysom-m.dts
@@ -11,9 +11,6 @@
#include "mpfs.dtsi"
#include "mpfs-tysom-m-fabric.dtsi"
-/* Clock frequency (in Hz) of the rtcclk */
-#define MTIMER_FREQ 1000000
-
/ {
model = "Aldec TySOM-M-MPFS250T-REV2";
compatible = "aldec,tysom-m-mpfs250t-rev2", "microchip,mpfs";
@@ -34,10 +31,6 @@
stdout-path = "serial1:115200n8";
};
- cpus {
- timebase-frequency = <MTIMER_FREQ>;
- };
-
ddrc_cache_lo: memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x30000000>;
diff --git a/arch/riscv/boot/dts/microchip/mpfs.dtsi b/arch/riscv/boot/dts/microchip/mpfs.dtsi
index 104504352e99..266489d43912 100644
--- a/arch/riscv/boot/dts/microchip/mpfs.dtsi
+++ b/arch/riscv/boot/dts/microchip/mpfs.dtsi
@@ -13,6 +13,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ timebase-frequency = <1000000>;
cpu0: cpu@0 {
compatible = "sifive,e51", "sifive,rocket0", "riscv";
@@ -22,6 +23,9 @@
i-cache-size = <16384>;
reg = <0>;
riscv,isa = "rv64imac";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "c", "zicntr", "zicsr", "zifencei",
+ "zihpm";
clocks = <&clkcfg CLK_CPU>;
status = "disabled";
@@ -48,6 +52,9 @@
mmu-type = "riscv,sv39";
reg = <1>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
clocks = <&clkcfg CLK_CPU>;
tlb-split;
next-level-cache = <&cctrllr>;
@@ -76,6 +83,9 @@
mmu-type = "riscv,sv39";
reg = <2>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
clocks = <&clkcfg CLK_CPU>;
tlb-split;
next-level-cache = <&cctrllr>;
@@ -104,6 +114,9 @@
mmu-type = "riscv,sv39";
reg = <3>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
clocks = <&clkcfg CLK_CPU>;
tlb-split;
next-level-cache = <&cctrllr>;
@@ -132,6 +145,9 @@
mmu-type = "riscv,sv39";
reg = <4>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
clocks = <&clkcfg CLK_CPU>;
tlb-split;
next-level-cache = <&cctrllr>;
diff --git a/arch/riscv/boot/dts/renesas/r9a07g043f.dtsi b/arch/riscv/boot/dts/renesas/r9a07g043f.dtsi
index 6ec1c6f9a403..b0796015e36b 100644
--- a/arch/riscv/boot/dts/renesas/r9a07g043f.dtsi
+++ b/arch/riscv/boot/dts/renesas/r9a07g043f.dtsi
@@ -29,6 +29,7 @@
i-cache-line-size = <0x40>;
d-cache-size = <0x8000>;
d-cache-line-size = <0x40>;
+ next-level-cache = <&l2cache>;
clocks = <&cpg CPG_CORE R9A07G043_CLK_I>;
operating-points-v2 = <&cluster0_opp>;
@@ -42,6 +43,7 @@
};
&soc {
+ dma-noncoherent;
interrupt-parent = <&plic>;
plic: interrupt-controller@12c00000 {
@@ -56,4 +58,15 @@
resets = <&cpg R9A07G043_NCEPLIC_ARESETN>;
interrupts-extended = <&cpu0_intc 11 &cpu0_intc 9>;
};
+
+ l2cache: cache-controller@13400000 {
+ compatible = "andestech,ax45mp-cache", "cache";
+ reg = <0x0 0x13400000 0x0 0x100000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(476) IRQ_TYPE_LEVEL_HIGH>;
+ cache-size = <0x40000>;
+ cache-line-size = <64>;
+ cache-sets = <1024>;
+ cache-unified;
+ cache-level = <2>;
+ };
};
diff --git a/arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi b/arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi
index c62debc7ca7e..433ab5c6a626 100644
--- a/arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi
+++ b/arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi
@@ -7,25 +7,8 @@
#include <arm64/renesas/rzg2ul-smarc-som.dtsi>
-/ {
- aliases {
- /delete-property/ ethernet0;
- /delete-property/ ethernet1;
- };
-
- chosen {
- bootargs = "ignore_loglevel";
- };
-};
-
-&dmac {
- status = "disabled";
-};
-
#if (!SW_ET0_EN_N)
&eth0 {
- status = "disabled";
-
phy0: ethernet-phy@7 {
/delete-property/ interrupt-parent;
/delete-property/ interrupts;
@@ -34,14 +17,8 @@
#endif
&eth1 {
- status = "disabled";
-
phy1: ethernet-phy@7 {
/delete-property/ interrupt-parent;
/delete-property/ interrupts;
};
};
-
-&sdhi0 {
- status = "disabled";
-};
diff --git a/arch/riscv/boot/dts/renesas/rzfive-smarc.dtsi b/arch/riscv/boot/dts/renesas/rzfive-smarc.dtsi
index c07a487c4e5a..a8573fdfd8b1 100644
--- a/arch/riscv/boot/dts/renesas/rzfive-smarc.dtsi
+++ b/arch/riscv/boot/dts/renesas/rzfive-smarc.dtsi
@@ -6,59 +6,3 @@
*/
#include <arm64/renesas/rzg2ul-smarc.dtsi>
-
-&ehci0 {
- status = "disabled";
-};
-
-&ehci1 {
- status = "disabled";
-};
-
-&hsusb {
- status = "disabled";
-};
-
-&ohci0 {
- status = "disabled";
-};
-
-&ohci1 {
- status = "disabled";
-};
-
-&phyrst {
- status = "disabled";
-};
-
-&sdhi1 {
- status = "disabled";
-};
-
-&snd_rzg2l {
- status = "disabled";
-};
-
-&spi1 {
- status = "disabled";
-};
-
-&ssi1 {
- status = "disabled";
-};
-
-&usb0_vbus_otg {
- status = "disabled";
-};
-
-&usb2_phy0 {
- status = "disabled";
-};
-
-&usb2_phy1 {
- status = "disabled";
-};
-
-&vccq_sdhi1 {
- status = "disabled";
-};
diff --git a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
index 24bba83bec77..156330a9bbf3 100644
--- a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
+++ b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
@@ -30,6 +30,9 @@
i-cache-size = <16384>;
reg = <0>;
riscv,isa = "rv64imac";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "c", "zicntr", "zicsr", "zifencei",
+ "zihpm";
status = "disabled";
cpu0_intc: interrupt-controller {
#interrupt-cells = <1>;
@@ -53,6 +56,9 @@
mmu-type = "riscv,sv39";
reg = <1>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
tlb-split;
next-level-cache = <&l2cache>;
cpu1_intc: interrupt-controller {
@@ -77,6 +83,9 @@
mmu-type = "riscv,sv39";
reg = <2>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
tlb-split;
next-level-cache = <&l2cache>;
cpu2_intc: interrupt-controller {
@@ -101,6 +110,9 @@
mmu-type = "riscv,sv39";
reg = <3>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
tlb-split;
next-level-cache = <&l2cache>;
cpu3_intc: interrupt-controller {
@@ -125,6 +137,9 @@
mmu-type = "riscv,sv39";
reg = <4>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
tlb-split;
next-level-cache = <&l2cache>;
cpu4_intc: interrupt-controller {
diff --git a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
index 5235fd1c9cb6..6150f3397bff 100644
--- a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
+++ b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
@@ -31,6 +31,9 @@
next-level-cache = <&ccache>;
reg = <0x0>;
riscv,isa = "rv64imac";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "c", "zicntr", "zicsr", "zifencei",
+ "zihpm";
status = "disabled";
cpu0_intc: interrupt-controller {
#interrupt-cells = <1>;
@@ -55,6 +58,9 @@
next-level-cache = <&ccache>;
reg = <0x1>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
tlb-split;
cpu1_intc: interrupt-controller {
#interrupt-cells = <1>;
@@ -79,6 +85,9 @@
next-level-cache = <&ccache>;
reg = <0x2>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
tlb-split;
cpu2_intc: interrupt-controller {
#interrupt-cells = <1>;
@@ -103,6 +112,9 @@
next-level-cache = <&ccache>;
reg = <0x3>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
tlb-split;
cpu3_intc: interrupt-controller {
#interrupt-cells = <1>;
@@ -127,6 +139,9 @@
next-level-cache = <&ccache>;
reg = <0x4>;
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
tlb-split;
cpu4_intc: interrupt-controller {
#interrupt-cells = <1>;
diff --git a/arch/riscv/boot/dts/sophgo/Makefile b/arch/riscv/boot/dts/sophgo/Makefile
new file mode 100644
index 000000000000..3fb65512c631
--- /dev/null
+++ b/arch/riscv/boot/dts/sophgo/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_SOPHGO) += cv1800b-milkv-duo.dtb
+dtb-$(CONFIG_ARCH_SOPHGO) += sg2042-milkv-pioneer.dtb
diff --git a/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts b/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
new file mode 100644
index 000000000000..3af9e34b3bc7
--- /dev/null
+++ b/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "cv1800b.dtsi"
+
+/ {
+ model = "Milk-V Duo";
+ compatible = "milkv,duo", "sophgo,cv1800b";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x3f40000>;
+ };
+};
+
+&osc {
+ clock-frequency = <25000000>;
+};
+
+&uart0 {
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/sophgo/cv1800b.dtsi b/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
new file mode 100644
index 000000000000..aec6401a467b
--- /dev/null
+++ b/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ compatible = "sophgo,cv1800b";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus: cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ timebase-frequency = <25000000>;
+
+ cpu0: cpu@0 {
+ compatible = "thead,c906", "riscv";
+ device_type = "cpu";
+ reg = <0>;
+ d-cache-block-size = <64>;
+ d-cache-sets = <512>;
+ d-cache-size = <65536>;
+ i-cache-block-size = <64>;
+ i-cache-sets = <128>;
+ i-cache-size = <32768>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
+
+ cpu0_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
+ osc: oscillator {
+ compatible = "fixed-clock";
+ clock-output-names = "osc_25m";
+ #clock-cells = <0>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ interrupt-parent = <&plic>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ dma-noncoherent;
+ ranges;
+
+ uart0: serial@4140000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x04140000 0x100>;
+ interrupts = <44 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ uart1: serial@4150000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x04150000 0x100>;
+ interrupts = <45 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ uart2: serial@4160000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x04160000 0x100>;
+ interrupts = <46 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ uart3: serial@4170000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x04170000 0x100>;
+ interrupts = <47 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ uart4: serial@41c0000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x041c0000 0x100>;
+ interrupts = <48 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ plic: interrupt-controller@70000000 {
+ compatible = "sophgo,cv1800b-plic", "thead,c900-plic";
+ reg = <0x70000000 0x4000000>;
+ interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>;
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ riscv,ndev = <101>;
+ };
+
+ clint: timer@74000000 {
+ compatible = "sophgo,cv1800b-clint", "thead,c900-clint";
+ reg = <0x74000000 0x10000>;
+ interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>;
+ };
+ };
+};
diff --git a/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi b/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi
new file mode 100644
index 000000000000..b136b6c4128c
--- /dev/null
+++ b/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi
@@ -0,0 +1,2000 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2022 Sophgo Technology Inc. All rights reserved.
+ */
+
+/ {
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ timebase-frequency = <50000000>;
+
+ cpu-map {
+ socket0 {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ core2 {
+ cpu = <&cpu2>;
+ };
+ core3 {
+ cpu = <&cpu3>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&cpu4>;
+ };
+ core1 {
+ cpu = <&cpu5>;
+ };
+ core2 {
+ cpu = <&cpu6>;
+ };
+ core3 {
+ cpu = <&cpu7>;
+ };
+ };
+
+ cluster2 {
+ core0 {
+ cpu = <&cpu16>;
+ };
+ core1 {
+ cpu = <&cpu17>;
+ };
+ core2 {
+ cpu = <&cpu18>;
+ };
+ core3 {
+ cpu = <&cpu19>;
+ };
+ };
+
+ cluster3 {
+ core0 {
+ cpu = <&cpu20>;
+ };
+ core1 {
+ cpu = <&cpu21>;
+ };
+ core2 {
+ cpu = <&cpu22>;
+ };
+ core3 {
+ cpu = <&cpu23>;
+ };
+ };
+
+ cluster4 {
+ core0 {
+ cpu = <&cpu8>;
+ };
+ core1 {
+ cpu = <&cpu9>;
+ };
+ core2 {
+ cpu = <&cpu10>;
+ };
+ core3 {
+ cpu = <&cpu11>;
+ };
+ };
+
+ cluster5 {
+ core0 {
+ cpu = <&cpu12>;
+ };
+ core1 {
+ cpu = <&cpu13>;
+ };
+ core2 {
+ cpu = <&cpu14>;
+ };
+ core3 {
+ cpu = <&cpu15>;
+ };
+ };
+
+ cluster6 {
+ core0 {
+ cpu = <&cpu24>;
+ };
+ core1 {
+ cpu = <&cpu25>;
+ };
+ core2 {
+ cpu = <&cpu26>;
+ };
+ core3 {
+ cpu = <&cpu27>;
+ };
+ };
+
+ cluster7 {
+ core0 {
+ cpu = <&cpu28>;
+ };
+ core1 {
+ cpu = <&cpu29>;
+ };
+ core2 {
+ cpu = <&cpu30>;
+ };
+ core3 {
+ cpu = <&cpu31>;
+ };
+ };
+
+ cluster8 {
+ core0 {
+ cpu = <&cpu32>;
+ };
+ core1 {
+ cpu = <&cpu33>;
+ };
+ core2 {
+ cpu = <&cpu34>;
+ };
+ core3 {
+ cpu = <&cpu35>;
+ };
+ };
+
+ cluster9 {
+ core0 {
+ cpu = <&cpu36>;
+ };
+ core1 {
+ cpu = <&cpu37>;
+ };
+ core2 {
+ cpu = <&cpu38>;
+ };
+ core3 {
+ cpu = <&cpu39>;
+ };
+ };
+
+ cluster10 {
+ core0 {
+ cpu = <&cpu48>;
+ };
+ core1 {
+ cpu = <&cpu49>;
+ };
+ core2 {
+ cpu = <&cpu50>;
+ };
+ core3 {
+ cpu = <&cpu51>;
+ };
+ };
+
+ cluster11 {
+ core0 {
+ cpu = <&cpu52>;
+ };
+ core1 {
+ cpu = <&cpu53>;
+ };
+ core2 {
+ cpu = <&cpu54>;
+ };
+ core3 {
+ cpu = <&cpu55>;
+ };
+ };
+
+ cluster12 {
+ core0 {
+ cpu = <&cpu40>;
+ };
+ core1 {
+ cpu = <&cpu41>;
+ };
+ core2 {
+ cpu = <&cpu42>;
+ };
+ core3 {
+ cpu = <&cpu43>;
+ };
+ };
+
+ cluster13 {
+ core0 {
+ cpu = <&cpu44>;
+ };
+ core1 {
+ cpu = <&cpu45>;
+ };
+ core2 {
+ cpu = <&cpu46>;
+ };
+ core3 {
+ cpu = <&cpu47>;
+ };
+ };
+
+ cluster14 {
+ core0 {
+ cpu = <&cpu56>;
+ };
+ core1 {
+ cpu = <&cpu57>;
+ };
+ core2 {
+ cpu = <&cpu58>;
+ };
+ core3 {
+ cpu = <&cpu59>;
+ };
+ };
+
+ cluster15 {
+ core0 {
+ cpu = <&cpu60>;
+ };
+ core1 {
+ cpu = <&cpu61>;
+ };
+ core2 {
+ cpu = <&cpu62>;
+ };
+ core3 {
+ cpu = <&cpu63>;
+ };
+ };
+ };
+ };
+
+ cpu0: cpu@0 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <0>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache0>;
+ mmu-type = "riscv,sv39";
+
+ cpu0_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu1: cpu@1 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <1>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache0>;
+ mmu-type = "riscv,sv39";
+
+ cpu1_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu2: cpu@2 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <2>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache0>;
+ mmu-type = "riscv,sv39";
+
+ cpu2_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu3: cpu@3 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <3>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache0>;
+ mmu-type = "riscv,sv39";
+
+ cpu3_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu4: cpu@4 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <4>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache1>;
+ mmu-type = "riscv,sv39";
+
+ cpu4_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu5: cpu@5 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <5>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache1>;
+ mmu-type = "riscv,sv39";
+
+ cpu5_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu6: cpu@6 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <6>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache1>;
+ mmu-type = "riscv,sv39";
+
+ cpu6_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu7: cpu@7 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <7>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache1>;
+ mmu-type = "riscv,sv39";
+
+ cpu7_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu8: cpu@8 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <8>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache4>;
+ mmu-type = "riscv,sv39";
+
+ cpu8_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu9: cpu@9 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <9>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache4>;
+ mmu-type = "riscv,sv39";
+
+ cpu9_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu10: cpu@10 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <10>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache4>;
+ mmu-type = "riscv,sv39";
+
+ cpu10_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu11: cpu@11 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <11>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache4>;
+ mmu-type = "riscv,sv39";
+
+ cpu11_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu12: cpu@12 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <12>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache5>;
+ mmu-type = "riscv,sv39";
+
+ cpu12_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu13: cpu@13 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <13>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache5>;
+ mmu-type = "riscv,sv39";
+
+ cpu13_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu14: cpu@14 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <14>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache5>;
+ mmu-type = "riscv,sv39";
+
+ cpu14_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu15: cpu@15 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <15>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache5>;
+ mmu-type = "riscv,sv39";
+
+ cpu15_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu16: cpu@16 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <16>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache2>;
+ mmu-type = "riscv,sv39";
+
+ cpu16_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu17: cpu@17 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <17>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache2>;
+ mmu-type = "riscv,sv39";
+
+ cpu17_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu18: cpu@18 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <18>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache2>;
+ mmu-type = "riscv,sv39";
+
+ cpu18_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu19: cpu@19 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <19>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache2>;
+ mmu-type = "riscv,sv39";
+
+ cpu19_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu20: cpu@20 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <20>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache3>;
+ mmu-type = "riscv,sv39";
+
+ cpu20_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu21: cpu@21 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <21>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache3>;
+ mmu-type = "riscv,sv39";
+
+ cpu21_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu22: cpu@22 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <22>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache3>;
+ mmu-type = "riscv,sv39";
+
+ cpu22_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu23: cpu@23 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <23>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache3>;
+ mmu-type = "riscv,sv39";
+
+ cpu23_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu24: cpu@24 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <24>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache6>;
+ mmu-type = "riscv,sv39";
+
+ cpu24_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu25: cpu@25 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <25>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache6>;
+ mmu-type = "riscv,sv39";
+
+ cpu25_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu26: cpu@26 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <26>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache6>;
+ mmu-type = "riscv,sv39";
+
+ cpu26_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu27: cpu@27 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <27>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache6>;
+ mmu-type = "riscv,sv39";
+
+ cpu27_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu28: cpu@28 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <28>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache7>;
+ mmu-type = "riscv,sv39";
+
+ cpu28_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu29: cpu@29 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <29>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache7>;
+ mmu-type = "riscv,sv39";
+
+ cpu29_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu30: cpu@30 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <30>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache7>;
+ mmu-type = "riscv,sv39";
+
+ cpu30_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu31: cpu@31 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <31>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache7>;
+ mmu-type = "riscv,sv39";
+
+ cpu31_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu32: cpu@32 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <32>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache8>;
+ mmu-type = "riscv,sv39";
+
+ cpu32_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu33: cpu@33 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <33>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache8>;
+ mmu-type = "riscv,sv39";
+
+ cpu33_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu34: cpu@34 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <34>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache8>;
+ mmu-type = "riscv,sv39";
+
+ cpu34_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu35: cpu@35 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <35>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache8>;
+ mmu-type = "riscv,sv39";
+
+ cpu35_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu36: cpu@36 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <36>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache9>;
+ mmu-type = "riscv,sv39";
+
+ cpu36_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu37: cpu@37 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <37>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache9>;
+ mmu-type = "riscv,sv39";
+
+ cpu37_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu38: cpu@38 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <38>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache9>;
+ mmu-type = "riscv,sv39";
+
+ cpu38_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu39: cpu@39 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <39>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache9>;
+ mmu-type = "riscv,sv39";
+
+ cpu39_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu40: cpu@40 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <40>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache12>;
+ mmu-type = "riscv,sv39";
+
+ cpu40_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu41: cpu@41 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <41>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache12>;
+ mmu-type = "riscv,sv39";
+
+ cpu41_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu42: cpu@42 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <42>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache12>;
+ mmu-type = "riscv,sv39";
+
+ cpu42_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu43: cpu@43 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <43>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache12>;
+ mmu-type = "riscv,sv39";
+
+ cpu43_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu44: cpu@44 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <44>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache13>;
+ mmu-type = "riscv,sv39";
+
+ cpu44_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu45: cpu@45 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <45>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache13>;
+ mmu-type = "riscv,sv39";
+
+ cpu45_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu46: cpu@46 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <46>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache13>;
+ mmu-type = "riscv,sv39";
+
+ cpu46_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu47: cpu@47 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <47>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache13>;
+ mmu-type = "riscv,sv39";
+
+ cpu47_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu48: cpu@48 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <48>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache10>;
+ mmu-type = "riscv,sv39";
+
+ cpu48_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu49: cpu@49 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <49>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache10>;
+ mmu-type = "riscv,sv39";
+
+ cpu49_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu50: cpu@50 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <50>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache10>;
+ mmu-type = "riscv,sv39";
+
+ cpu50_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu51: cpu@51 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <51>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache10>;
+ mmu-type = "riscv,sv39";
+
+ cpu51_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu52: cpu@52 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <52>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache11>;
+ mmu-type = "riscv,sv39";
+
+ cpu52_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu53: cpu@53 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <53>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache11>;
+ mmu-type = "riscv,sv39";
+
+ cpu53_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu54: cpu@54 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <54>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache11>;
+ mmu-type = "riscv,sv39";
+
+ cpu54_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu55: cpu@55 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <55>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache11>;
+ mmu-type = "riscv,sv39";
+
+ cpu55_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu56: cpu@56 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <56>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache14>;
+ mmu-type = "riscv,sv39";
+
+ cpu56_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu57: cpu@57 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <57>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache14>;
+ mmu-type = "riscv,sv39";
+
+ cpu57_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu58: cpu@58 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <58>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache14>;
+ mmu-type = "riscv,sv39";
+
+ cpu58_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu59: cpu@59 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <59>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache14>;
+ mmu-type = "riscv,sv39";
+
+ cpu59_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu60: cpu@60 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <60>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache15>;
+ mmu-type = "riscv,sv39";
+
+ cpu60_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu61: cpu@61 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <61>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache15>;
+ mmu-type = "riscv,sv39";
+
+ cpu61_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu62: cpu@62 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <62>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache15>;
+ mmu-type = "riscv,sv39";
+
+ cpu62_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu63: cpu@63 {
+ compatible = "thead,c920", "riscv";
+ device_type = "cpu";
+ riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+ "zicntr", "zicsr", "zifencei",
+ "zihpm";
+ reg = <63>;
+ i-cache-block-size = <64>;
+ i-cache-size = <65536>;
+ i-cache-sets = <512>;
+ d-cache-block-size = <64>;
+ d-cache-size = <65536>;
+ d-cache-sets = <512>;
+ next-level-cache = <&l2_cache15>;
+ mmu-type = "riscv,sv39";
+
+ cpu63_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ l2_cache0: cache-controller-0 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache1: cache-controller-1 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache2: cache-controller-2 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache3: cache-controller-3 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache4: cache-controller-4 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache5: cache-controller-5 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache6: cache-controller-6 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache7: cache-controller-7 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache8: cache-controller-8 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache9: cache-controller-9 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache10: cache-controller-10 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache11: cache-controller-11 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache12: cache-controller-12 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache13: cache-controller-13 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache14: cache-controller-14 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+
+ l2_cache15: cache-controller-15 {
+ compatible = "cache";
+ cache-block-size = <64>;
+ cache-level = <2>;
+ cache-size = <1048576>;
+ cache-sets = <1024>;
+ cache-unified;
+ };
+ };
+};
diff --git a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts
new file mode 100644
index 000000000000..49b4b9c2c101
--- /dev/null
+++ b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 Sophgo Technology Inc. All rights reserved.
+ */
+
+#include "sg2042.dtsi"
+
+/ {
+ model = "Milk-V Pioneer";
+ compatible = "milkv,pioneer", "sophgo,sg2042";
+
+ chosen {
+ stdout-path = "serial0";
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi
new file mode 100644
index 000000000000..93256540d078
--- /dev/null
+++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi
@@ -0,0 +1,325 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2022 Sophgo Technology Inc. All rights reserved.
+ */
+
+/dts-v1/;
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "sg2042-cpus.dtsi"
+
+/ {
+ compatible = "sophgo,sg2042";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dma-noncoherent;
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ soc: soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ clint_mswi: interrupt-controller@7094000000 {
+ compatible = "sophgo,sg2042-aclint-mswi", "thead,c900-aclint-mswi";
+ reg = <0x00000070 0x94000000 0x00000000 0x00004000>;
+ interrupts-extended = <&cpu0_intc 3>,
+ <&cpu1_intc 3>,
+ <&cpu2_intc 3>,
+ <&cpu3_intc 3>,
+ <&cpu4_intc 3>,
+ <&cpu5_intc 3>,
+ <&cpu6_intc 3>,
+ <&cpu7_intc 3>,
+ <&cpu8_intc 3>,
+ <&cpu9_intc 3>,
+ <&cpu10_intc 3>,
+ <&cpu11_intc 3>,
+ <&cpu12_intc 3>,
+ <&cpu13_intc 3>,
+ <&cpu14_intc 3>,
+ <&cpu15_intc 3>,
+ <&cpu16_intc 3>,
+ <&cpu17_intc 3>,
+ <&cpu18_intc 3>,
+ <&cpu19_intc 3>,
+ <&cpu20_intc 3>,
+ <&cpu21_intc 3>,
+ <&cpu22_intc 3>,
+ <&cpu23_intc 3>,
+ <&cpu24_intc 3>,
+ <&cpu25_intc 3>,
+ <&cpu26_intc 3>,
+ <&cpu27_intc 3>,
+ <&cpu28_intc 3>,
+ <&cpu29_intc 3>,
+ <&cpu30_intc 3>,
+ <&cpu31_intc 3>,
+ <&cpu32_intc 3>,
+ <&cpu33_intc 3>,
+ <&cpu34_intc 3>,
+ <&cpu35_intc 3>,
+ <&cpu36_intc 3>,
+ <&cpu37_intc 3>,
+ <&cpu38_intc 3>,
+ <&cpu39_intc 3>,
+ <&cpu40_intc 3>,
+ <&cpu41_intc 3>,
+ <&cpu42_intc 3>,
+ <&cpu43_intc 3>,
+ <&cpu44_intc 3>,
+ <&cpu45_intc 3>,
+ <&cpu46_intc 3>,
+ <&cpu47_intc 3>,
+ <&cpu48_intc 3>,
+ <&cpu49_intc 3>,
+ <&cpu50_intc 3>,
+ <&cpu51_intc 3>,
+ <&cpu52_intc 3>,
+ <&cpu53_intc 3>,
+ <&cpu54_intc 3>,
+ <&cpu55_intc 3>,
+ <&cpu56_intc 3>,
+ <&cpu57_intc 3>,
+ <&cpu58_intc 3>,
+ <&cpu59_intc 3>,
+ <&cpu60_intc 3>,
+ <&cpu61_intc 3>,
+ <&cpu62_intc 3>,
+ <&cpu63_intc 3>;
+ };
+
+ clint_mtimer0: timer@70ac000000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac000000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu0_intc 7>,
+ <&cpu1_intc 7>,
+ <&cpu2_intc 7>,
+ <&cpu3_intc 7>;
+ };
+
+ clint_mtimer1: timer@70ac010000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac010000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu4_intc 7>,
+ <&cpu5_intc 7>,
+ <&cpu6_intc 7>,
+ <&cpu7_intc 7>;
+ };
+
+ clint_mtimer2: timer@70ac020000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac020000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu8_intc 7>,
+ <&cpu9_intc 7>,
+ <&cpu10_intc 7>,
+ <&cpu11_intc 7>;
+ };
+
+ clint_mtimer3: timer@70ac030000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac030000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu12_intc 7>,
+ <&cpu13_intc 7>,
+ <&cpu14_intc 7>,
+ <&cpu15_intc 7>;
+ };
+
+ clint_mtimer4: timer@70ac040000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac040000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu16_intc 7>,
+ <&cpu17_intc 7>,
+ <&cpu18_intc 7>,
+ <&cpu19_intc 7>;
+ };
+
+ clint_mtimer5: timer@70ac050000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac050000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu20_intc 7>,
+ <&cpu21_intc 7>,
+ <&cpu22_intc 7>,
+ <&cpu23_intc 7>;
+ };
+
+ clint_mtimer6: timer@70ac060000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac060000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu24_intc 7>,
+ <&cpu25_intc 7>,
+ <&cpu26_intc 7>,
+ <&cpu27_intc 7>;
+ };
+
+ clint_mtimer7: timer@70ac070000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac070000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu28_intc 7>,
+ <&cpu29_intc 7>,
+ <&cpu30_intc 7>,
+ <&cpu31_intc 7>;
+ };
+
+ clint_mtimer8: timer@70ac080000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac080000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu32_intc 7>,
+ <&cpu33_intc 7>,
+ <&cpu34_intc 7>,
+ <&cpu35_intc 7>;
+ };
+
+ clint_mtimer9: timer@70ac090000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac090000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu36_intc 7>,
+ <&cpu37_intc 7>,
+ <&cpu38_intc 7>,
+ <&cpu39_intc 7>;
+ };
+
+ clint_mtimer10: timer@70ac0a0000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac0a0000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu40_intc 7>,
+ <&cpu41_intc 7>,
+ <&cpu42_intc 7>,
+ <&cpu43_intc 7>;
+ };
+
+ clint_mtimer11: timer@70ac0b0000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac0b0000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu44_intc 7>,
+ <&cpu45_intc 7>,
+ <&cpu46_intc 7>,
+ <&cpu47_intc 7>;
+ };
+
+ clint_mtimer12: timer@70ac0c0000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac0c0000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu48_intc 7>,
+ <&cpu49_intc 7>,
+ <&cpu50_intc 7>,
+ <&cpu51_intc 7>;
+ };
+
+ clint_mtimer13: timer@70ac0d0000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac0d0000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu52_intc 7>,
+ <&cpu53_intc 7>,
+ <&cpu54_intc 7>,
+ <&cpu55_intc 7>;
+ };
+
+ clint_mtimer14: timer@70ac0e0000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac0e0000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu56_intc 7>,
+ <&cpu57_intc 7>,
+ <&cpu58_intc 7>,
+ <&cpu59_intc 7>;
+ };
+
+ clint_mtimer15: timer@70ac0f0000 {
+ compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
+ reg = <0x00000070 0xac0f0000 0x00000000 0x00007ff8>;
+ interrupts-extended = <&cpu60_intc 7>,
+ <&cpu61_intc 7>,
+ <&cpu62_intc 7>,
+ <&cpu63_intc 7>;
+ };
+
+ intc: interrupt-controller@7090000000 {
+ compatible = "sophgo,sg2042-plic", "thead,c900-plic";
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x00000070 0x90000000 0x00000000 0x04000000>;
+ interrupt-controller;
+ interrupts-extended =
+ <&cpu0_intc 11>, <&cpu0_intc 9>,
+ <&cpu1_intc 11>, <&cpu1_intc 9>,
+ <&cpu2_intc 11>, <&cpu2_intc 9>,
+ <&cpu3_intc 11>, <&cpu3_intc 9>,
+ <&cpu4_intc 11>, <&cpu4_intc 9>,
+ <&cpu5_intc 11>, <&cpu5_intc 9>,
+ <&cpu6_intc 11>, <&cpu6_intc 9>,
+ <&cpu7_intc 11>, <&cpu7_intc 9>,
+ <&cpu8_intc 11>, <&cpu8_intc 9>,
+ <&cpu9_intc 11>, <&cpu9_intc 9>,
+ <&cpu10_intc 11>, <&cpu10_intc 9>,
+ <&cpu11_intc 11>, <&cpu11_intc 9>,
+ <&cpu12_intc 11>, <&cpu12_intc 9>,
+ <&cpu13_intc 11>, <&cpu13_intc 9>,
+ <&cpu14_intc 11>, <&cpu14_intc 9>,
+ <&cpu15_intc 11>, <&cpu15_intc 9>,
+ <&cpu16_intc 11>, <&cpu16_intc 9>,
+ <&cpu17_intc 11>, <&cpu17_intc 9>,
+ <&cpu18_intc 11>, <&cpu18_intc 9>,
+ <&cpu19_intc 11>, <&cpu19_intc 9>,
+ <&cpu20_intc 11>, <&cpu20_intc 9>,
+ <&cpu21_intc 11>, <&cpu21_intc 9>,
+ <&cpu22_intc 11>, <&cpu22_intc 9>,
+ <&cpu23_intc 11>, <&cpu23_intc 9>,
+ <&cpu24_intc 11>, <&cpu24_intc 9>,
+ <&cpu25_intc 11>, <&cpu25_intc 9>,
+ <&cpu26_intc 11>, <&cpu26_intc 9>,
+ <&cpu27_intc 11>, <&cpu27_intc 9>,
+ <&cpu28_intc 11>, <&cpu28_intc 9>,
+ <&cpu29_intc 11>, <&cpu29_intc 9>,
+ <&cpu30_intc 11>, <&cpu30_intc 9>,
+ <&cpu31_intc 11>, <&cpu31_intc 9>,
+ <&cpu32_intc 11>, <&cpu32_intc 9>,
+ <&cpu33_intc 11>, <&cpu33_intc 9>,
+ <&cpu34_intc 11>, <&cpu34_intc 9>,
+ <&cpu35_intc 11>, <&cpu35_intc 9>,
+ <&cpu36_intc 11>, <&cpu36_intc 9>,
+ <&cpu37_intc 11>, <&cpu37_intc 9>,
+ <&cpu38_intc 11>, <&cpu38_intc 9>,
+ <&cpu39_intc 11>, <&cpu39_intc 9>,
+ <&cpu40_intc 11>, <&cpu40_intc 9>,
+ <&cpu41_intc 11>, <&cpu41_intc 9>,
+ <&cpu42_intc 11>, <&cpu42_intc 9>,
+ <&cpu43_intc 11>, <&cpu43_intc 9>,
+ <&cpu44_intc 11>, <&cpu44_intc 9>,
+ <&cpu45_intc 11>, <&cpu45_intc 9>,
+ <&cpu46_intc 11>, <&cpu46_intc 9>,
+ <&cpu47_intc 11>, <&cpu47_intc 9>,
+ <&cpu48_intc 11>, <&cpu48_intc 9>,
+ <&cpu49_intc 11>, <&cpu49_intc 9>,
+ <&cpu50_intc 11>, <&cpu50_intc 9>,
+ <&cpu51_intc 11>, <&cpu51_intc 9>,
+ <&cpu52_intc 11>, <&cpu52_intc 9>,
+ <&cpu53_intc 11>, <&cpu53_intc 9>,
+ <&cpu54_intc 11>, <&cpu54_intc 9>,
+ <&cpu55_intc 11>, <&cpu55_intc 9>,
+ <&cpu56_intc 11>, <&cpu56_intc 9>,
+ <&cpu57_intc 11>, <&cpu57_intc 9>,
+ <&cpu58_intc 11>, <&cpu58_intc 9>,
+ <&cpu59_intc 11>, <&cpu59_intc 9>,
+ <&cpu60_intc 11>, <&cpu60_intc 9>,
+ <&cpu61_intc 11>, <&cpu61_intc 9>,
+ <&cpu62_intc 11>, <&cpu62_intc 9>,
+ <&cpu63_intc 11>, <&cpu63_intc 9>;
+ riscv,ndev = <224>;
+ };
+
+ uart0: serial@7040000000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x00000070 0x40000000 0x00000000 0x00001000>;
+ interrupt-parent = <&intc>;
+ interrupts = <112 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <500000000>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7100.dtsi b/arch/riscv/boot/dts/starfive/jh7100.dtsi
index 35ab54fb235f..e68cafe7545f 100644
--- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
@@ -33,6 +33,9 @@
i-tlb-size = <32>;
mmu-type = "riscv,sv39";
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
tlb-split;
cpu0_intc: interrupt-controller {
@@ -58,6 +61,9 @@
i-tlb-size = <32>;
mmu-type = "riscv,sv39";
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
tlb-split;
cpu1_intc: interrupt-controller {
diff --git a/arch/riscv/boot/dts/starfive/jh7110-pinfunc.h b/arch/riscv/boot/dts/starfive/jh7110-pinfunc.h
index fb0139b56723..256de17f5261 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-pinfunc.h
+++ b/arch/riscv/boot/dts/starfive/jh7110-pinfunc.h
@@ -240,8 +240,8 @@
#define GPI_SYS_MCLK_EXT 30
#define GPI_SYS_I2SRX_BCLK 31
#define GPI_SYS_I2SRX_LRCK 32
-#define GPI_SYS_I2STX0_BCLK 33
-#define GPI_SYS_I2STX0_LRCK 34
+#define GPI_SYS_I2STX1_BCLK 33
+#define GPI_SYS_I2STX1_LRCK 34
#define GPI_SYS_TDM_CLK 35
#define GPI_SYS_TDM_RXD 36
#define GPI_SYS_TDM_SYNC 37
diff --git a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
index 12ebe9792356..b89e9791efa7 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
@@ -40,6 +40,33 @@
gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
priority = <224>;
};
+
+ pwmdac_codec: pwmdac-codec {
+ compatible = "linux,spdif-dit";
+ #sound-dai-cells = <0>;
+ };
+
+ sound-pwmdac {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "StarFive-PWMDAC-Sound-Card";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,dai-link@0 {
+ reg = <0>;
+ format = "left_j";
+ bitclock-master = <&sndcpu0>;
+ frame-master = <&sndcpu0>;
+
+ sndcpu0: cpu {
+ sound-dai = <&pwmdac>;
+ };
+
+ codec {
+ sound-dai = <&pwmdac_codec>;
+ };
+ };
+ };
};
&dvp_clk {
@@ -203,8 +230,28 @@
status = "okay";
};
+&i2srx {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2srx_pins>;
+ status = "okay";
+};
+
+&i2stx0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mclk_ext_pins>;
+ status = "okay";
+};
+
+&i2stx1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2stx1_pins>;
+ status = "okay";
+};
+
&mmc0 {
max-frequency = <100000000>;
+ assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
+ assigned-clock-rates = <50000000>;
bus-width = <8>;
cap-mmc-highspeed;
mmc-ddr-1_8v;
@@ -221,6 +268,8 @@
&mmc1 {
max-frequency = <100000000>;
+ assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO1_SDCARD>;
+ assigned-clock-rates = <50000000>;
bus-width = <4>;
no-sdio;
no-mmc;
@@ -232,6 +281,12 @@
status = "okay";
};
+&pwmdac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwmdac_pins>;
+ status = "okay";
+};
+
&qspi {
#address-cells = <1>;
#size-cells = <0>;
@@ -337,6 +392,46 @@
};
};
+ i2srx_pins: i2srx-0 {
+ clk-sd-pins {
+ pinmux = <GPIOMUX(38, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_I2SRX_BCLK)>,
+ <GPIOMUX(63, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_I2SRX_LRCK)>,
+ <GPIOMUX(38, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_I2STX1_BCLK)>,
+ <GPIOMUX(63, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_I2STX1_LRCK)>,
+ <GPIOMUX(61, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_I2SRX_SDIN0)>;
+ input-enable;
+ };
+ };
+
+ i2stx1_pins: i2stx1-0 {
+ sd-pins {
+ pinmux = <GPIOMUX(44, GPOUT_SYS_I2STX1_SDO0,
+ GPOEN_ENABLE,
+ GPI_NONE)>;
+ bias-disable;
+ input-disable;
+ };
+ };
+
+ mclk_ext_pins: mclk-ext-0 {
+ mclk-ext-pins {
+ pinmux = <GPIOMUX(4, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_MCLK_EXT)>;
+ input-enable;
+ };
+ };
+
mmc0_pins: mmc0-0 {
rst-pins {
pinmux = <GPIOMUX(62, GPOUT_SYS_SDIO0_RST,
@@ -402,6 +497,22 @@
};
};
+ pwmdac_pins: pwmdac-0 {
+ pwmdac-pins {
+ pinmux = <GPIOMUX(33, GPOUT_SYS_PWMDAC_LEFT,
+ GPOEN_ENABLE,
+ GPI_NONE)>,
+ <GPIOMUX(34, GPOUT_SYS_PWMDAC_RIGHT,
+ GPOEN_ENABLE,
+ GPI_NONE)>;
+ bias-disable;
+ drive-strength = <2>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+
spi0_pins: spi0-0 {
mosi-pins {
pinmux = <GPIOMUX(52, GPOUT_SYS_SPI0_TXD,
@@ -431,7 +542,7 @@
};
ss-pins {
- pinmux = <GPIOMUX(48, GPOUT_SYS_SPI0_FSS,
+ pinmux = <GPIOMUX(49, GPOUT_SYS_SPI0_FSS,
GPOEN_ENABLE,
GPI_SYS_SPI0_FSS)>;
bias-disable;
diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
index e85464c328d0..45213cdf50dc 100644
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -28,6 +28,9 @@
i-cache-size = <16384>;
next-level-cache = <&ccache>;
riscv,isa = "rv64imac_zba_zbb";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "c", "zba", "zbb", "zicntr", "zicsr",
+ "zifencei", "zihpm";
status = "disabled";
cpu0_intc: interrupt-controller {
@@ -54,6 +57,9 @@
mmu-type = "riscv,sv39";
next-level-cache = <&ccache>;
riscv,isa = "rv64imafdc_zba_zbb";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zba", "zbb", "zicntr",
+ "zicsr", "zifencei", "zihpm";
tlb-split;
operating-points-v2 = <&cpu_opp>;
clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>;
@@ -84,6 +90,9 @@
mmu-type = "riscv,sv39";
next-level-cache = <&ccache>;
riscv,isa = "rv64imafdc_zba_zbb";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zba", "zbb", "zicntr",
+ "zicsr", "zifencei", "zihpm";
tlb-split;
operating-points-v2 = <&cpu_opp>;
clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>;
@@ -114,6 +123,9 @@
mmu-type = "riscv,sv39";
next-level-cache = <&ccache>;
riscv,isa = "rv64imafdc_zba_zbb";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zba", "zbb", "zicntr",
+ "zicsr", "zifencei", "zihpm";
tlb-split;
operating-points-v2 = <&cpu_opp>;
clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>;
@@ -144,6 +156,9 @@
mmu-type = "riscv,sv39";
next-level-cache = <&ccache>;
riscv,isa = "rv64imafdc_zba_zbb";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zba", "zbb", "zicntr",
+ "zicsr", "zifencei", "zihpm";
tlb-split;
operating-points-v2 = <&cpu_opp>;
clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>;
@@ -512,6 +527,43 @@
status = "disabled";
};
+ i2srx: i2s@100e0000 {
+ compatible = "starfive,jh7110-i2srx";
+ reg = <0x0 0x100e0000 0x0 0x1000>;
+ clocks = <&syscrg JH7110_SYSCLK_I2SRX_BCLK_MST>,
+ <&syscrg JH7110_SYSCLK_I2SRX_APB>,
+ <&syscrg JH7110_SYSCLK_MCLK>,
+ <&syscrg JH7110_SYSCLK_MCLK_INNER>,
+ <&mclk_ext>,
+ <&syscrg JH7110_SYSCLK_I2SRX_BCLK>,
+ <&syscrg JH7110_SYSCLK_I2SRX_LRCK>,
+ <&i2srx_bclk_ext>,
+ <&i2srx_lrck_ext>;
+ clock-names = "i2sclk", "apb", "mclk",
+ "mclk_inner", "mclk_ext", "bclk",
+ "lrck", "bclk_ext", "lrck_ext";
+ resets = <&syscrg JH7110_SYSRST_I2SRX_APB>,
+ <&syscrg JH7110_SYSRST_I2SRX_BCLK>;
+ dmas = <0>, <&dma 24>;
+ dma-names = "tx", "rx";
+ starfive,syscon = <&sys_syscon 0x18 0x2>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ pwmdac: pwmdac@100b0000 {
+ compatible = "starfive,jh7110-pwmdac";
+ reg = <0x0 0x100b0000 0x0 0x1000>;
+ clocks = <&syscrg JH7110_SYSCLK_PWMDAC_APB>,
+ <&syscrg JH7110_SYSCLK_PWMDAC_CORE>;
+ clock-names = "apb", "core";
+ resets = <&syscrg JH7110_SYSRST_PWMDAC_APB>;
+ dmas = <&dma 22>;
+ dma-names = "tx";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
usb0: usb@10100000 {
compatible = "starfive,jh7110-usb";
ranges = <0x0 0x0 0x10100000 0x100000>;
@@ -736,6 +788,47 @@
status = "disabled";
};
+ i2stx0: i2s@120b0000 {
+ compatible = "starfive,jh7110-i2stx0";
+ reg = <0x0 0x120b0000 0x0 0x1000>;
+ clocks = <&syscrg JH7110_SYSCLK_I2STX0_BCLK_MST>,
+ <&syscrg JH7110_SYSCLK_I2STX0_APB>,
+ <&syscrg JH7110_SYSCLK_MCLK>,
+ <&syscrg JH7110_SYSCLK_MCLK_INNER>,
+ <&mclk_ext>;
+ clock-names = "i2sclk", "apb", "mclk",
+ "mclk_inner","mclk_ext";
+ resets = <&syscrg JH7110_SYSRST_I2STX0_APB>,
+ <&syscrg JH7110_SYSRST_I2STX0_BCLK>;
+ dmas = <&dma 47>;
+ dma-names = "tx";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ i2stx1: i2s@120c0000 {
+ compatible = "starfive,jh7110-i2stx1";
+ reg = <0x0 0x120c0000 0x0 0x1000>;
+ clocks = <&syscrg JH7110_SYSCLK_I2STX1_BCLK_MST>,
+ <&syscrg JH7110_SYSCLK_I2STX1_APB>,
+ <&syscrg JH7110_SYSCLK_MCLK>,
+ <&syscrg JH7110_SYSCLK_MCLK_INNER>,
+ <&mclk_ext>,
+ <&syscrg JH7110_SYSCLK_I2STX1_BCLK>,
+ <&syscrg JH7110_SYSCLK_I2STX1_LRCK>,
+ <&i2stx_bclk_ext>,
+ <&i2stx_lrck_ext>;
+ clock-names = "i2sclk", "apb", "mclk",
+ "mclk_inner", "mclk_ext", "bclk",
+ "lrck", "bclk_ext", "lrck_ext";
+ resets = <&syscrg JH7110_SYSRST_I2STX1_APB>,
+ <&syscrg JH7110_SYSRST_I2STX1_BCLK>;
+ dmas = <&dma 48>;
+ dma-names = "tx";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
sfctemp: temperature-sensor@120e0000 {
compatible = "starfive,jh7110-temp";
reg = <0x0 0x120e0000 0x0 0x10000>;
diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/thead/th1520.dtsi
index ce708183b6f6..ba4d2c673ac8 100644
--- a/arch/riscv/boot/dts/thead/th1520.dtsi
+++ b/arch/riscv/boot/dts/thead/th1520.dtsi
@@ -20,6 +20,9 @@
compatible = "thead,c910", "riscv";
device_type = "cpu";
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
reg = <0>;
i-cache-block-size = <64>;
i-cache-size = <65536>;
@@ -41,6 +44,9 @@
compatible = "thead,c910", "riscv";
device_type = "cpu";
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
reg = <1>;
i-cache-block-size = <64>;
i-cache-size = <65536>;
@@ -62,6 +68,9 @@
compatible = "thead,c910", "riscv";
device_type = "cpu";
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
reg = <2>;
i-cache-block-size = <64>;
i-cache-size = <65536>;
@@ -83,6 +92,9 @@
compatible = "thead,c910", "riscv";
device_type = "cpu";
riscv,isa = "rv64imafdc";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+ "zifencei", "zihpm";
reg = <3>;
i-cache-block-size = <64>;
i-cache-size = <65536>;
@@ -139,6 +151,7 @@
interrupt-parent = <&plic>;
#address-cells = <2>;
#size-cells = <2>;
+ dma-noncoherent;
ranges;
plic: interrupt-controller@ffd8000000 {
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index ab86ec3b9eab..905881282a7c 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -27,15 +27,23 @@ CONFIG_EXPERT=y
CONFIG_PROFILING=y
CONFIG_SOC_MICROCHIP_POLARFIRE=y
CONFIG_ARCH_RENESAS=y
-CONFIG_ARCH_THEAD=y
CONFIG_SOC_SIFIVE=y
+CONFIG_ARCH_SOPHGO=y
CONFIG_SOC_STARFIVE=y
CONFIG_ARCH_SUNXI=y
+CONFIG_ARCH_THEAD=y
CONFIG_SOC_VIRT=y
CONFIG_SMP=y
CONFIG_HOTPLUG_CPU=y
CONFIG_PM=y
CONFIG_CPU_IDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_CPUFREQ_DT=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
CONFIG_ACPI=y
@@ -94,6 +102,7 @@ CONFIG_NETLINK_DIAG=y
CONFIG_CGROUP_NET_PRIO=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
+CONFIG_CAN=m
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCI_HOST_GENERIC=y
@@ -101,6 +110,11 @@ CONFIG_PCIE_XILINX=y
CONFIG_PCIE_FU740=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_SPI_NOR=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_NVME=m
@@ -123,8 +137,11 @@ CONFIG_VIRTIO_NET=y
CONFIG_MACB=y
CONFIG_E1000E=y
CONFIG_R8169=y
+CONFIG_RAVB=y
CONFIG_STMMAC_ETH=m
+CONFIG_MICREL_PHY=y
CONFIG_MICROSEMI_PHY=y
+CONFIG_CAN_RCAR_CANFD=m
CONFIG_INPUT_MOUSEDEV=y
CONFIG_KEYBOARD_SUN4I_LRADC=m
CONFIG_SERIAL_8250=y
@@ -135,16 +152,24 @@ CONFIG_SERIAL_SH_SCI=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
+CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MV64XXX=m
+CONFIG_I2C_RIIC=y
CONFIG_SPI=y
+CONFIG_SPI_RSPI=m
CONFIG_SPI_SIFIVE=y
CONFIG_SPI_SUN6I=y
# CONFIG_PTP_1588_CLOCK is not set
CONFIG_GPIO_SIFIVE=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
+CONFIG_RZG2L_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_SUNXI_WATCHDOG=y
+CONFIG_RENESAS_RZG2LWDT=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_GPIO=y
CONFIG_DRM=m
CONFIG_DRM_RADEON=m
CONFIG_DRM_NOUVEAU=m
@@ -152,39 +177,69 @@ CONFIG_DRM_SUN4I=m
CONFIG_DRM_VIRTIO_GPU=m
CONFIG_FB=y
CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_RZ=m
+CONFIG_SND_SOC_WM8978=m
+CONFIG_SND_SIMPLE_CARD=m
CONFIG_USB=y
+CONFIG_USB_OTG=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_PLATFORM=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_RENESAS_USBHS=m
CONFIG_USB_STORAGE=y
CONFIG_USB_UAS=y
CONFIG_USB_MUSB_HDRC=m
CONFIG_USB_MUSB_SUNXI=m
CONFIG_NOP_USB_XCEIV=m
+CONFIG_USB_GADGET=y
+CONFIG_USB_RENESAS_USBHS_UDC=m
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_CADENCE=y
CONFIG_MMC_SPI=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_STARFIVE=y
+CONFIG_MMC_SDHI=y
CONFIG_MMC_SUNXI=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_SUN6I=y
CONFIG_DMADEVICES=y
CONFIG_DMA_SUN6I=m
+CONFIG_RZ_DMAC=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_INPUT=y
CONFIG_VIRTIO_MMIO=y
+CONFIG_RENESAS_OSTM=y
CONFIG_SUN8I_DE2_CCU=m
CONFIG_SUN50I_IOMMU=y
CONFIG_RPMSG_CHAR=y
CONFIG_RPMSG_CTRL=y
CONFIG_RPMSG_VIRTIO=y
CONFIG_ARCH_R9A07G043=y
+CONFIG_IIO=y
+CONFIG_RZG2L_ADC=m
+CONFIG_RESET_RZG2L_USBPHY_CTRL=y
CONFIG_PHY_SUN4I_USB=m
+CONFIG_PHY_RCAR_GEN3_USB2=y
CONFIG_LIBNVDIMM=y
CONFIG_NVMEM_SUNXI_SID=y
CONFIG_EXT4_FS=y
diff --git a/arch/riscv/errata/andes/Makefile b/arch/riscv/errata/andes/Makefile
index 2d644e19caef..6278c389b801 100644
--- a/arch/riscv/errata/andes/Makefile
+++ b/arch/riscv/errata/andes/Makefile
@@ -1 +1,5 @@
+ifdef CONFIG_RISCV_ALTERNATIVE_EARLY
+CFLAGS_errata.o := -mcmodel=medany
+endif
+
obj-y += errata.o
diff --git a/arch/riscv/errata/andes/errata.c b/arch/riscv/errata/andes/errata.c
index 197db68cc8da..17a904869724 100644
--- a/arch/riscv/errata/andes/errata.c
+++ b/arch/riscv/errata/andes/errata.c
@@ -38,29 +38,35 @@ static long ax45mp_iocp_sw_workaround(void)
return ret.error ? 0 : ret.value;
}
-static bool errata_probe_iocp(unsigned int stage, unsigned long arch_id, unsigned long impid)
+static void errata_probe_iocp(unsigned int stage, unsigned long arch_id, unsigned long impid)
{
+ static bool done;
+
if (!IS_ENABLED(CONFIG_ERRATA_ANDES_CMO))
- return false;
+ return;
+
+ if (done)
+ return;
+
+ done = true;
if (arch_id != ANDESTECH_AX45MP_MARCHID || impid != ANDESTECH_AX45MP_MIMPID)
- return false;
+ return;
if (!ax45mp_iocp_sw_workaround())
- return false;
+ return;
/* Set this just to make core cbo code happy */
riscv_cbom_block_size = 1;
riscv_noncoherent_supported();
-
- return true;
}
void __init_or_module andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned long archid, unsigned long impid,
unsigned int stage)
{
- errata_probe_iocp(stage, archid, impid);
+ if (stage == RISCV_ALTERNATIVES_BOOT)
+ errata_probe_iocp(stage, archid, impid);
/* we have nothing to patch here ATM so just return back */
}
diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h
index d5604d2073bc..7dad0cf9d701 100644
--- a/arch/riscv/include/asm/acpi.h
+++ b/arch/riscv/include/asm/acpi.h
@@ -66,6 +66,8 @@ int acpi_get_riscv_isa(struct acpi_table_header *table,
unsigned int cpu, const char **isa);
static inline int acpi_numa_get_nid(unsigned int cpu) { return NUMA_NO_NODE; }
+void acpi_get_cbo_block_size(struct acpi_table_header *table, u32 *cbom_size,
+ u32 *cboz_size, u32 *cbop_size);
#else
static inline void acpi_init_rintc_map(void) { }
static inline struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu)
@@ -79,6 +81,10 @@ static inline int acpi_get_riscv_isa(struct acpi_table_header *table,
return -EINVAL;
}
+static inline void acpi_get_cbo_block_size(struct acpi_table_header *table,
+ u32 *cbom_size, u32 *cboz_size,
+ u32 *cbop_size) { }
+
#endif /* CONFIG_ACPI */
#endif /*_ASM_ACPI_H*/
diff --git a/arch/riscv/include/asm/asm-prototypes.h b/arch/riscv/include/asm/asm-prototypes.h
index 61ba8ed43d8f..36b955c762ba 100644
--- a/arch/riscv/include/asm/asm-prototypes.h
+++ b/arch/riscv/include/asm/asm-prototypes.h
@@ -25,7 +25,6 @@ DECLARE_DO_ERROR_INFO(do_trap_ecall_s);
DECLARE_DO_ERROR_INFO(do_trap_ecall_m);
DECLARE_DO_ERROR_INFO(do_trap_break);
-asmlinkage unsigned long get_overflow_stack(void);
asmlinkage void handle_bad_stack(struct pt_regs *regs);
asmlinkage void do_page_fault(struct pt_regs *regs);
asmlinkage void do_irq(struct pt_regs *regs);
diff --git a/arch/riscv/include/asm/asm.h b/arch/riscv/include/asm/asm.h
index 114bbadaef41..b0487b39e674 100644
--- a/arch/riscv/include/asm/asm.h
+++ b/arch/riscv/include/asm/asm.h
@@ -82,6 +82,47 @@
.endr
.endm
+#ifdef CONFIG_SMP
+#ifdef CONFIG_32BIT
+#define PER_CPU_OFFSET_SHIFT 2
+#else
+#define PER_CPU_OFFSET_SHIFT 3
+#endif
+
+.macro asm_per_cpu dst sym tmp
+ REG_L \tmp, TASK_TI_CPU_NUM(tp)
+ slli \tmp, \tmp, PER_CPU_OFFSET_SHIFT
+ la \dst, __per_cpu_offset
+ add \dst, \dst, \tmp
+ REG_L \tmp, 0(\dst)
+ la \dst, \sym
+ add \dst, \dst, \tmp
+.endm
+#else /* CONFIG_SMP */
+.macro asm_per_cpu dst sym tmp
+ la \dst, \sym
+.endm
+#endif /* CONFIG_SMP */
+
+.macro load_per_cpu dst ptr tmp
+ asm_per_cpu \dst \ptr \tmp
+ REG_L \dst, 0(\dst)
+.endm
+
+#ifdef CONFIG_SHADOW_CALL_STACK
+/* gp is used as the shadow call stack pointer instead */
+.macro load_global_pointer
+.endm
+#else
+/* load __global_pointer to gp */
+.macro load_global_pointer
+.option push
+.option norelax
+ la gp, __global_pointer$
+.option pop
+.endm
+#endif /* CONFIG_SHADOW_CALL_STACK */
+
/* save all GPs except x1 ~ x5 */
.macro save_from_x6_to_x31
REG_S x6, PT_T1(sp)
diff --git a/arch/riscv/include/asm/bitops.h b/arch/riscv/include/asm/bitops.h
index 3540b690944b..224b4dc02b50 100644
--- a/arch/riscv/include/asm/bitops.h
+++ b/arch/riscv/include/asm/bitops.h
@@ -15,13 +15,261 @@
#include <asm/barrier.h>
#include <asm/bitsperlong.h>
+#if !defined(CONFIG_RISCV_ISA_ZBB) || defined(NO_ALTERNATIVE)
#include <asm-generic/bitops/__ffs.h>
-#include <asm-generic/bitops/ffz.h>
-#include <asm-generic/bitops/fls.h>
#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/fls.h>
+
+#else
+#include <asm/alternative-macros.h>
+#include <asm/hwcap.h>
+
+#if (BITS_PER_LONG == 64)
+#define CTZW "ctzw "
+#define CLZW "clzw "
+#elif (BITS_PER_LONG == 32)
+#define CTZW "ctz "
+#define CLZW "clz "
+#else
+#error "Unexpected BITS_PER_LONG"
+#endif
+
+static __always_inline unsigned long variable__ffs(unsigned long word)
+{
+ int num;
+
+ asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
+ RISCV_ISA_EXT_ZBB, 1)
+ : : : : legacy);
+
+ asm volatile (".option push\n"
+ ".option arch,+zbb\n"
+ "ctz %0, %1\n"
+ ".option pop\n"
+ : "=r" (word) : "r" (word) :);
+
+ return word;
+
+legacy:
+ num = 0;
+#if BITS_PER_LONG == 64
+ if ((word & 0xffffffff) == 0) {
+ num += 32;
+ word >>= 32;
+ }
+#endif
+ if ((word & 0xffff) == 0) {
+ num += 16;
+ word >>= 16;
+ }
+ if ((word & 0xff) == 0) {
+ num += 8;
+ word >>= 8;
+ }
+ if ((word & 0xf) == 0) {
+ num += 4;
+ word >>= 4;
+ }
+ if ((word & 0x3) == 0) {
+ num += 2;
+ word >>= 2;
+ }
+ if ((word & 0x1) == 0)
+ num += 1;
+ return num;
+}
+
+/**
+ * __ffs - find first set bit in a long word
+ * @word: The word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ */
+#define __ffs(word) \
+ (__builtin_constant_p(word) ? \
+ (unsigned long)__builtin_ctzl(word) : \
+ variable__ffs(word))
+
+static __always_inline unsigned long variable__fls(unsigned long word)
+{
+ int num;
+
+ asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
+ RISCV_ISA_EXT_ZBB, 1)
+ : : : : legacy);
+
+ asm volatile (".option push\n"
+ ".option arch,+zbb\n"
+ "clz %0, %1\n"
+ ".option pop\n"
+ : "=r" (word) : "r" (word) :);
+
+ return BITS_PER_LONG - 1 - word;
+
+legacy:
+ num = BITS_PER_LONG - 1;
+#if BITS_PER_LONG == 64
+ if (!(word & (~0ul << 32))) {
+ num -= 32;
+ word <<= 32;
+ }
+#endif
+ if (!(word & (~0ul << (BITS_PER_LONG - 16)))) {
+ num -= 16;
+ word <<= 16;
+ }
+ if (!(word & (~0ul << (BITS_PER_LONG - 8)))) {
+ num -= 8;
+ word <<= 8;
+ }
+ if (!(word & (~0ul << (BITS_PER_LONG - 4)))) {
+ num -= 4;
+ word <<= 4;
+ }
+ if (!(word & (~0ul << (BITS_PER_LONG - 2)))) {
+ num -= 2;
+ word <<= 2;
+ }
+ if (!(word & (~0ul << (BITS_PER_LONG - 1))))
+ num -= 1;
+ return num;
+}
+
+/**
+ * __fls - find last set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ */
+#define __fls(word) \
+ (__builtin_constant_p(word) ? \
+ (unsigned long)(BITS_PER_LONG - 1 - __builtin_clzl(word)) : \
+ variable__fls(word))
+
+static __always_inline int variable_ffs(int x)
+{
+ int r;
+
+ if (!x)
+ return 0;
+
+ asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
+ RISCV_ISA_EXT_ZBB, 1)
+ : : : : legacy);
+
+ asm volatile (".option push\n"
+ ".option arch,+zbb\n"
+ CTZW "%0, %1\n"
+ ".option pop\n"
+ : "=r" (r) : "r" (x) :);
+
+ return r + 1;
+
+legacy:
+ r = 1;
+ if (!(x & 0xffff)) {
+ x >>= 16;
+ r += 16;
+ }
+ if (!(x & 0xff)) {
+ x >>= 8;
+ r += 8;
+ }
+ if (!(x & 0xf)) {
+ x >>= 4;
+ r += 4;
+ }
+ if (!(x & 3)) {
+ x >>= 2;
+ r += 2;
+ }
+ if (!(x & 1)) {
+ x >>= 1;
+ r += 1;
+ }
+ return r;
+}
+
+/**
+ * ffs - find first set bit in a word
+ * @x: the word to search
+ *
+ * This is defined the same way as the libc and compiler builtin ffs routines.
+ *
+ * ffs(value) returns 0 if value is 0 or the position of the first set bit if
+ * value is nonzero. The first (least significant) bit is at position 1.
+ */
+#define ffs(x) (__builtin_constant_p(x) ? __builtin_ffs(x) : variable_ffs(x))
+
+static __always_inline int variable_fls(unsigned int x)
+{
+ int r;
+
+ if (!x)
+ return 0;
+
+ asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
+ RISCV_ISA_EXT_ZBB, 1)
+ : : : : legacy);
+
+ asm volatile (".option push\n"
+ ".option arch,+zbb\n"
+ CLZW "%0, %1\n"
+ ".option pop\n"
+ : "=r" (r) : "r" (x) :);
+
+ return 32 - r;
+
+legacy:
+ r = 32;
+ if (!(x & 0xffff0000u)) {
+ x <<= 16;
+ r -= 16;
+ }
+ if (!(x & 0xff000000u)) {
+ x <<= 8;
+ r -= 8;
+ }
+ if (!(x & 0xf0000000u)) {
+ x <<= 4;
+ r -= 4;
+ }
+ if (!(x & 0xc0000000u)) {
+ x <<= 2;
+ r -= 2;
+ }
+ if (!(x & 0x80000000u)) {
+ x <<= 1;
+ r -= 1;
+ }
+ return r;
+}
+
+/**
+ * fls - find last set bit in a word
+ * @x: the word to search
+ *
+ * This is defined in a similar way as ffs, but returns the position of the most
+ * significant set bit.
+ *
+ * fls(value) returns 0 if value is 0 or the position of the last set bit if
+ * value is nonzero. The last (most significant) bit is at position 32.
+ */
+#define fls(x) \
+({ \
+ typeof(x) x_ = (x); \
+ __builtin_constant_p(x_) ? \
+ (int)((x_ != 0) ? (32 - __builtin_clz(x_)) : 0) \
+ : \
+ variable_fls(x_); \
+})
+
+#endif /* !defined(CONFIG_RISCV_ISA_ZBB) || defined(NO_ALTERNATIVE) */
+
+#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
@@ -191,6 +439,18 @@ static inline void __clear_bit_unlock(
clear_bit_unlock(nr, addr);
}
+static inline bool xor_unlock_is_negative_byte(unsigned long mask,
+ volatile unsigned long *addr)
+{
+ unsigned long res;
+ __asm__ __volatile__ (
+ __AMO(xor) ".rl %0, %2, %1"
+ : "=r" (res), "+A" (*addr)
+ : "r" (__NOP(mask))
+ : "memory");
+ return (res & BIT(7)) != 0;
+}
+
#undef __test_and_op_bit
#undef __op_bit
#undef __NOP
diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h
index d0345bd659c9..a418c3112cd6 100644
--- a/arch/riscv/include/asm/cpufeature.h
+++ b/arch/riscv/include/asm/cpufeature.h
@@ -7,7 +7,10 @@
#define _ASM_CPUFEATURE_H
#include <linux/bitmap.h>
+#include <linux/jump_label.h>
#include <asm/hwcap.h>
+#include <asm/alternative-macros.h>
+#include <asm/errno.h>
/*
* These are probed via a device_initcall(), via either the SBI or directly
@@ -30,6 +33,104 @@ DECLARE_PER_CPU(long, misaligned_access_speed);
/* Per-cpu ISA extensions. */
extern struct riscv_isainfo hart_isa[NR_CPUS];
-void check_unaligned_access(int cpu);
+void riscv_user_isa_enable(void);
+
+#ifdef CONFIG_RISCV_MISALIGNED
+bool unaligned_ctl_available(void);
+bool check_unaligned_access_emulated(int cpu);
+void unaligned_emulation_finish(void);
+#else
+static inline bool unaligned_ctl_available(void)
+{
+ return false;
+}
+
+static inline bool check_unaligned_access_emulated(int cpu)
+{
+ return false;
+}
+
+static inline void unaligned_emulation_finish(void) {}
+#endif
+
+unsigned long riscv_get_elf_hwcap(void);
+
+struct riscv_isa_ext_data {
+ const unsigned int id;
+ const char *name;
+ const char *property;
+};
+
+extern const struct riscv_isa_ext_data riscv_isa_ext[];
+extern const size_t riscv_isa_ext_count;
+extern bool riscv_isa_fallback;
+
+unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
+
+bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
+#define riscv_isa_extension_available(isa_bitmap, ext) \
+ __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
+
+static __always_inline bool
+riscv_has_extension_likely(const unsigned long ext)
+{
+ compiletime_assert(ext < RISCV_ISA_EXT_MAX,
+ "ext must be < RISCV_ISA_EXT_MAX");
+
+ if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
+ asm_volatile_goto(
+ ALTERNATIVE("j %l[l_no]", "nop", 0, %[ext], 1)
+ :
+ : [ext] "i" (ext)
+ :
+ : l_no);
+ } else {
+ if (!__riscv_isa_extension_available(NULL, ext))
+ goto l_no;
+ }
+
+ return true;
+l_no:
+ return false;
+}
+
+static __always_inline bool
+riscv_has_extension_unlikely(const unsigned long ext)
+{
+ compiletime_assert(ext < RISCV_ISA_EXT_MAX,
+ "ext must be < RISCV_ISA_EXT_MAX");
+
+ if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
+ asm_volatile_goto(
+ ALTERNATIVE("nop", "j %l[l_yes]", 0, %[ext], 1)
+ :
+ : [ext] "i" (ext)
+ :
+ : l_yes);
+ } else {
+ if (__riscv_isa_extension_available(NULL, ext))
+ goto l_yes;
+ }
+
+ return false;
+l_yes:
+ return true;
+}
+
+static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsigned long ext)
+{
+ if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_likely(ext))
+ return true;
+
+ return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
+}
+
+static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsigned long ext)
+{
+ if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_unlikely(ext))
+ return true;
+
+ return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
+}
#endif
diff --git a/arch/riscv/include/asm/crash_core.h b/arch/riscv/include/asm/crash_core.h
new file mode 100644
index 000000000000..e1874b23feaf
--- /dev/null
+++ b/arch/riscv/include/asm/crash_core.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _RISCV_CRASH_CORE_H
+#define _RISCV_CRASH_CORE_H
+
+#define CRASH_ALIGN PMD_SIZE
+
+#define CRASH_ADDR_LOW_MAX dma32_phys_limit
+#define CRASH_ADDR_HIGH_MAX memblock_end_of_DRAM()
+
+extern phys_addr_t memblock_end_of_DRAM(void);
+#endif
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 777cb8299551..306a19a5509c 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -203,6 +203,18 @@
#define ENVCFG_CBIE_INV _AC(0x3, UL)
#define ENVCFG_FIOM _AC(0x1, UL)
+/* Smstateen bits */
+#define SMSTATEEN0_AIA_IMSIC_SHIFT 58
+#define SMSTATEEN0_AIA_IMSIC (_ULL(1) << SMSTATEEN0_AIA_IMSIC_SHIFT)
+#define SMSTATEEN0_AIA_SHIFT 59
+#define SMSTATEEN0_AIA (_ULL(1) << SMSTATEEN0_AIA_SHIFT)
+#define SMSTATEEN0_AIA_ISEL_SHIFT 60
+#define SMSTATEEN0_AIA_ISEL (_ULL(1) << SMSTATEEN0_AIA_ISEL_SHIFT)
+#define SMSTATEEN0_HSENVCFG_SHIFT 62
+#define SMSTATEEN0_HSENVCFG (_ULL(1) << SMSTATEEN0_HSENVCFG_SHIFT)
+#define SMSTATEEN0_SSTATEEN0_SHIFT 63
+#define SMSTATEEN0_SSTATEEN0 (_ULL(1) << SMSTATEEN0_SSTATEEN0_SHIFT)
+
/* symbolic CSR names: */
#define CSR_CYCLE 0xc00
#define CSR_TIME 0xc01
@@ -275,6 +287,8 @@
#define CSR_SIE 0x104
#define CSR_STVEC 0x105
#define CSR_SCOUNTEREN 0x106
+#define CSR_SENVCFG 0x10a
+#define CSR_SSTATEEN0 0x10c
#define CSR_SSCRATCH 0x140
#define CSR_SEPC 0x141
#define CSR_SCAUSE 0x142
@@ -349,6 +363,10 @@
#define CSR_VSIEH 0x214
#define CSR_VSIPH 0x254
+/* Hypervisor stateen CSRs */
+#define CSR_HSTATEEN0 0x60c
+#define CSR_HSTATEEN0H 0x61c
+
#define CSR_MSTATUS 0x300
#define CSR_MISA 0x301
#define CSR_MIDELEG 0x303
diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h
index b3b2dfbdf945..06c236bfab53 100644
--- a/arch/riscv/include/asm/elf.h
+++ b/arch/riscv/include/asm/elf.h
@@ -14,7 +14,7 @@
#include <asm/auxvec.h>
#include <asm/byteorder.h>
#include <asm/cacheinfo.h>
-#include <asm/hwcap.h>
+#include <asm/cpufeature.h>
/*
* These are used to set parameters in the core dumps.
diff --git a/arch/riscv/include/asm/entry-common.h b/arch/riscv/include/asm/entry-common.h
index 6e4dee49d84b..7ab5e34318c8 100644
--- a/arch/riscv/include/asm/entry-common.h
+++ b/arch/riscv/include/asm/entry-common.h
@@ -8,4 +8,18 @@
void handle_page_fault(struct pt_regs *regs);
void handle_break(struct pt_regs *regs);
+#ifdef CONFIG_RISCV_MISALIGNED
+int handle_misaligned_load(struct pt_regs *regs);
+int handle_misaligned_store(struct pt_regs *regs);
+#else
+static inline int handle_misaligned_load(struct pt_regs *regs)
+{
+ return -1;
+}
+static inline int handle_misaligned_store(struct pt_regs *regs)
+{
+ return -1;
+}
+#endif
+
#endif /* _ASM_RISCV_ENTRY_COMMON_H */
diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
index b55b434f0059..83ed25e43553 100644
--- a/arch/riscv/include/asm/errata_list.h
+++ b/arch/riscv/include/asm/errata_list.h
@@ -95,31 +95,31 @@ asm volatile(ALTERNATIVE( \
#endif
/*
- * dcache.ipa rs1 (invalidate, physical address)
+ * th.dcache.ipa rs1 (invalidate, physical address)
* | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
* 0000001 01010 rs1 000 00000 0001011
- * dache.iva rs1 (invalida, virtual address)
+ * th.dache.iva rs1 (invalida, virtual address)
* 0000001 00110 rs1 000 00000 0001011
*
- * dcache.cpa rs1 (clean, physical address)
+ * th.dcache.cpa rs1 (clean, physical address)
* | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
* 0000001 01001 rs1 000 00000 0001011
- * dcache.cva rs1 (clean, virtual address)
+ * th.dcache.cva rs1 (clean, virtual address)
* 0000001 00101 rs1 000 00000 0001011
*
- * dcache.cipa rs1 (clean then invalidate, physical address)
+ * th.dcache.cipa rs1 (clean then invalidate, physical address)
* | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
* 0000001 01011 rs1 000 00000 0001011
- * dcache.civa rs1 (... virtual address)
+ * th.dcache.civa rs1 (... virtual address)
* 0000001 00111 rs1 000 00000 0001011
*
- * sync.s (make sure all cache operations finished)
+ * th.sync.s (make sure all cache operations finished)
* | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
* 0000000 11001 00000 000 00000 0001011
*/
-#define THEAD_inval_A0 ".long 0x0265000b"
-#define THEAD_clean_A0 ".long 0x0255000b"
-#define THEAD_flush_A0 ".long 0x0275000b"
+#define THEAD_INVAL_A0 ".long 0x0265000b"
+#define THEAD_CLEAN_A0 ".long 0x0255000b"
+#define THEAD_FLUSH_A0 ".long 0x0275000b"
#define THEAD_SYNC_S ".long 0x0190000b"
#define ALT_CMO_OP(_op, _start, _size, _cachesize) \
diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h
index 740a979171e5..2b2f5df7ef2c 100644
--- a/arch/riscv/include/asm/ftrace.h
+++ b/arch/riscv/include/asm/ftrace.h
@@ -31,6 +31,27 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
return addr;
}
+/*
+ * Let's do like x86/arm64 and ignore the compat syscalls.
+ */
+#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
+static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
+{
+ return is_compat_task();
+}
+
+#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
+static inline bool arch_syscall_match_sym_name(const char *sym,
+ const char *name)
+{
+ /*
+ * Since all syscall functions have __riscv_ prefix, we must skip it.
+ * However, as we described above, we decided to ignore compat
+ * syscalls, so we don't care about __riscv_compat_ prefix here.
+ */
+ return !strcmp(sym + 8, name);
+}
+
struct dyn_arch_ftrace {
};
#endif
diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index b7b58258f6c7..06d30526ef3b 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -8,9 +8,6 @@
#ifndef _ASM_RISCV_HWCAP_H
#define _ASM_RISCV_HWCAP_H
-#include <asm/alternative-macros.h>
-#include <asm/errno.h>
-#include <linux/bits.h>
#include <uapi/asm/hwcap.h>
#define RISCV_ISA_EXT_a ('a' - 'a')
@@ -58,6 +55,8 @@
#define RISCV_ISA_EXT_ZICSR 40
#define RISCV_ISA_EXT_ZIFENCEI 41
#define RISCV_ISA_EXT_ZIHPM 42
+#define RISCV_ISA_EXT_SMSTATEEN 43
+#define RISCV_ISA_EXT_ZICOND 44
#define RISCV_ISA_EXT_MAX 64
@@ -67,76 +66,4 @@
#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SSAIA
#endif
-#ifndef __ASSEMBLY__
-
-#include <linux/jump_label.h>
-
-unsigned long riscv_get_elf_hwcap(void);
-
-struct riscv_isa_ext_data {
- const unsigned int id;
- const char *name;
- const char *property;
-};
-
-extern const struct riscv_isa_ext_data riscv_isa_ext[];
-extern const size_t riscv_isa_ext_count;
-extern bool riscv_isa_fallback;
-
-unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
-
-#define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
-
-bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
-#define riscv_isa_extension_available(isa_bitmap, ext) \
- __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
-
-static __always_inline bool
-riscv_has_extension_likely(const unsigned long ext)
-{
- compiletime_assert(ext < RISCV_ISA_EXT_MAX,
- "ext must be < RISCV_ISA_EXT_MAX");
-
- if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
- asm_volatile_goto(
- ALTERNATIVE("j %l[l_no]", "nop", 0, %[ext], 1)
- :
- : [ext] "i" (ext)
- :
- : l_no);
- } else {
- if (!__riscv_isa_extension_available(NULL, ext))
- goto l_no;
- }
-
- return true;
-l_no:
- return false;
-}
-
-static __always_inline bool
-riscv_has_extension_unlikely(const unsigned long ext)
-{
- compiletime_assert(ext < RISCV_ISA_EXT_MAX,
- "ext must be < RISCV_ISA_EXT_MAX");
-
- if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
- asm_volatile_goto(
- ALTERNATIVE("nop", "j %l[l_yes]", 0, %[ext], 1)
- :
- : [ext] "i" (ext)
- :
- : l_yes);
- } else {
- if (__riscv_isa_extension_available(NULL, ext))
- goto l_yes;
- }
-
- return false;
-l_yes:
- return true;
-}
-
-#endif
-
#endif /* _ASM_RISCV_HWCAP_H */
diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
index 78936f4ff513..5c48f48e79a6 100644
--- a/arch/riscv/include/asm/hwprobe.h
+++ b/arch/riscv/include/asm/hwprobe.h
@@ -8,6 +8,11 @@
#include <uapi/asm/hwprobe.h>
-#define RISCV_HWPROBE_MAX_KEY 5
+#define RISCV_HWPROBE_MAX_KEY 6
+
+static inline bool riscv_hwprobe_key_is_valid(__s64 key)
+{
+ return key >= 0 && key <= RISCV_HWPROBE_MAX_KEY;
+}
#endif
diff --git a/arch/riscv/include/asm/insn-def.h b/arch/riscv/include/asm/insn-def.h
index 6960beb75f32..e27179b26086 100644
--- a/arch/riscv/include/asm/insn-def.h
+++ b/arch/riscv/include/asm/insn-def.h
@@ -180,19 +180,19 @@
INSN_R(OPCODE_SYSTEM, FUNC3(0), FUNC7(51), \
__RD(0), RS1(gaddr), RS2(vmid))
-#define CBO_inval(base) \
+#define CBO_INVAL(base) \
INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
RS1(base), SIMM12(0))
-#define CBO_clean(base) \
+#define CBO_CLEAN(base) \
INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
RS1(base), SIMM12(1))
-#define CBO_flush(base) \
+#define CBO_FLUSH(base) \
INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
RS1(base), SIMM12(2))
-#define CBO_zero(base) \
+#define CBO_ZERO(base) \
INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
RS1(base), SIMM12(4))
diff --git a/arch/riscv/include/asm/irq_stack.h b/arch/riscv/include/asm/irq_stack.h
index e4042d297580..6441ded3b0cf 100644
--- a/arch/riscv/include/asm/irq_stack.h
+++ b/arch/riscv/include/asm/irq_stack.h
@@ -12,6 +12,9 @@
DECLARE_PER_CPU(ulong *, irq_stack_ptr);
+asmlinkage void call_on_irq_stack(struct pt_regs *regs,
+ void (*func)(struct pt_regs *));
+
#ifdef CONFIG_VMAP_STACK
/*
* To ensure that VMAP'd stack overflow detection works correctly, all VMAP'd
diff --git a/arch/riscv/include/asm/kprobes.h b/arch/riscv/include/asm/kprobes.h
index e7882ccb0fd4..78ea44f76718 100644
--- a/arch/riscv/include/asm/kprobes.h
+++ b/arch/riscv/include/asm/kprobes.h
@@ -40,6 +40,15 @@ void arch_remove_kprobe(struct kprobe *p);
int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr);
bool kprobe_breakpoint_handler(struct pt_regs *regs);
bool kprobe_single_step_handler(struct pt_regs *regs);
-
+#else
+static inline bool kprobe_breakpoint_handler(struct pt_regs *regs)
+{
+ return false;
+}
+
+static inline bool kprobe_single_step_handler(struct pt_regs *regs)
+{
+ return false;
+}
#endif /* CONFIG_KPROBES */
#endif /* _ASM_RISCV_KPROBES_H */
diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
index 1ebf20dfbaa6..0eefd9c991ae 100644
--- a/arch/riscv/include/asm/kvm_host.h
+++ b/arch/riscv/include/asm/kvm_host.h
@@ -162,6 +162,16 @@ struct kvm_vcpu_csr {
unsigned long hvip;
unsigned long vsatp;
unsigned long scounteren;
+ unsigned long senvcfg;
+};
+
+struct kvm_vcpu_config {
+ u64 henvcfg;
+ u64 hstateen0;
+};
+
+struct kvm_vcpu_smstateen_csr {
+ unsigned long sstateen0;
};
struct kvm_vcpu_arch {
@@ -183,6 +193,8 @@ struct kvm_vcpu_arch {
unsigned long host_sscratch;
unsigned long host_stvec;
unsigned long host_scounteren;
+ unsigned long host_senvcfg;
+ unsigned long host_sstateen0;
/* CPU context of Host */
struct kvm_cpu_context host_context;
@@ -193,6 +205,9 @@ struct kvm_vcpu_arch {
/* CPU CSR context of Guest VCPU */
struct kvm_vcpu_csr guest_csr;
+ /* CPU Smstateen CSR context of Guest VCPU */
+ struct kvm_vcpu_smstateen_csr smstateen_csr;
+
/* CPU context upon Guest VCPU reset */
struct kvm_cpu_context guest_reset_context;
@@ -244,6 +259,9 @@ struct kvm_vcpu_arch {
/* Performance monitoring context */
struct kvm_pmu pmu_context;
+
+ /* 'static' configurations which are set only once */
+ struct kvm_vcpu_config cfg;
};
static inline void kvm_arch_sync_events(struct kvm *kvm) {}
diff --git a/arch/riscv/include/asm/kvm_vcpu_sbi.h b/arch/riscv/include/asm/kvm_vcpu_sbi.h
index cdcf0ff07be7..6a453f7f8b56 100644
--- a/arch/riscv/include/asm/kvm_vcpu_sbi.h
+++ b/arch/riscv/include/asm/kvm_vcpu_sbi.h
@@ -11,7 +11,7 @@
#define KVM_SBI_IMPID 3
-#define KVM_SBI_VERSION_MAJOR 1
+#define KVM_SBI_VERSION_MAJOR 2
#define KVM_SBI_VERSION_MINOR 0
enum kvm_riscv_sbi_ext_status {
@@ -35,6 +35,9 @@ struct kvm_vcpu_sbi_return {
struct kvm_vcpu_sbi_extension {
unsigned long extid_start;
unsigned long extid_end;
+
+ bool default_unavail;
+
/**
* SBI extension handler. It can be defined for a given extension or group of
* extension. But it should always return linux error codes rather than SBI
@@ -59,6 +62,7 @@ int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu,
const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
struct kvm_vcpu *vcpu, unsigned long extid);
int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run);
+void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu);
#ifdef CONFIG_RISCV_SBI_V01
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01;
@@ -69,6 +73,7 @@ extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_ipi;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_rfence;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_srst;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm;
+extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_dbcn;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor;
diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h
index 5488ecc337b6..57e887bfa34c 100644
--- a/arch/riscv/include/asm/page.h
+++ b/arch/riscv/include/asm/page.h
@@ -33,8 +33,8 @@
#define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL)
#endif
/*
- * By default, CONFIG_PAGE_OFFSET value corresponds to SV48 address space so
- * define the PAGE_OFFSET value for SV39.
+ * By default, CONFIG_PAGE_OFFSET value corresponds to SV57 address space so
+ * define the PAGE_OFFSET value for SV48 and SV39.
*/
#define PAGE_OFFSET_L4 _AC(0xffffaf8000000000, UL)
#define PAGE_OFFSET_L3 _AC(0xffffffd800000000, UL)
diff --git a/arch/riscv/include/asm/pgtable-32.h b/arch/riscv/include/asm/pgtable-32.h
index 59ba1fbaf784..00f3369570a8 100644
--- a/arch/riscv/include/asm/pgtable-32.h
+++ b/arch/riscv/include/asm/pgtable-32.h
@@ -33,4 +33,7 @@
_PAGE_WRITE | _PAGE_EXEC | \
_PAGE_USER | _PAGE_GLOBAL))
+static const __maybe_unused int pgtable_l4_enabled;
+static const __maybe_unused int pgtable_l5_enabled;
+
#endif /* _ASM_RISCV_PGTABLE_32_H */
diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
index 7a5097202e15..9a2c780a11e9 100644
--- a/arch/riscv/include/asm/pgtable-64.h
+++ b/arch/riscv/include/asm/pgtable-64.h
@@ -126,14 +126,18 @@ enum napot_cont_order {
/*
* [63:59] T-Head Memory Type definitions:
- *
- * 00000 - NC Weakly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
+ * bit[63] SO - Strong Order
+ * bit[62] C - Cacheable
+ * bit[61] B - Bufferable
+ * bit[60] SH - Shareable
+ * bit[59] Sec - Trustable
+ * 00110 - NC Weakly-ordered, Non-cacheable, Bufferable, Shareable, Non-trustable
* 01110 - PMA Weakly-ordered, Cacheable, Bufferable, Shareable, Non-trustable
- * 10000 - IO Strongly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
+ * 10010 - IO Strongly-ordered, Non-cacheable, Non-bufferable, Shareable, Non-trustable
*/
#define _PAGE_PMA_THEAD ((1UL << 62) | (1UL << 61) | (1UL << 60))
-#define _PAGE_NOCACHE_THEAD 0UL
-#define _PAGE_IO_THEAD (1UL << 63)
+#define _PAGE_NOCACHE_THEAD ((1UL < 61) | (1UL << 60))
+#define _PAGE_IO_THEAD ((1UL << 63) | (1UL << 60))
#define _PAGE_MTMASK_THEAD (_PAGE_PMA_THEAD | _PAGE_IO_THEAD | (1UL << 59))
static inline u64 riscv_page_mtmask(void)
diff --git a/arch/riscv/include/asm/pgtable-bits.h b/arch/riscv/include/asm/pgtable-bits.h
index f896708e8331..179bd4afece4 100644
--- a/arch/riscv/include/asm/pgtable-bits.h
+++ b/arch/riscv/include/asm/pgtable-bits.h
@@ -16,9 +16,9 @@
#define _PAGE_GLOBAL (1 << 5) /* Global */
#define _PAGE_ACCESSED (1 << 6) /* Set by hardware on any access */
#define _PAGE_DIRTY (1 << 7) /* Set by hardware on any write */
-#define _PAGE_SOFT (1 << 8) /* Reserved for software */
+#define _PAGE_SOFT (3 << 8) /* Reserved for software */
-#define _PAGE_SPECIAL _PAGE_SOFT
+#define _PAGE_SPECIAL (1 << 8) /* RSW: 0x1 */
#define _PAGE_TABLE _PAGE_PRESENT
/*
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index b2ba3f79cfe9..ab00235b018f 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -291,6 +291,7 @@ static inline pte_t pud_pte(pud_t pud)
}
#ifdef CONFIG_RISCV_ISA_SVNAPOT
+#include <asm/cpufeature.h>
static __always_inline bool has_svnapot(void)
{
@@ -811,7 +812,7 @@ extern pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
* bit 5: _PAGE_PROT_NONE (zero)
* bit 6: exclusive marker
* bits 7 to 11: swap type
- * bits 11 to XLEN-1: swap offset
+ * bits 12 to XLEN-1: swap offset
*/
#define __SWP_TYPE_SHIFT 7
#define __SWP_TYPE_BITS 5
@@ -898,7 +899,7 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
#define PAGE_KERNEL __pgprot(0)
#define swapper_pg_dir NULL
#define TASK_SIZE 0xffffffffUL
-#define VMALLOC_START 0
+#define VMALLOC_START _AC(0, UL)
#define VMALLOC_END TASK_SIZE
#endif /* !CONFIG_MMU */
@@ -914,7 +915,6 @@ extern uintptr_t _dtb_early_pa;
#define dtb_early_pa _dtb_early_pa
#endif /* CONFIG_XIP_KERNEL */
extern u64 satp_mode;
-extern bool pgtable_l4_enabled;
void paging_init(void);
void misc_mem_init(void);
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index 3e23e1786d05..f19f861cda54 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -8,6 +8,7 @@
#include <linux/const.h>
#include <linux/cache.h>
+#include <linux/prctl.h>
#include <vdso/processor.h>
@@ -82,6 +83,7 @@ struct thread_struct {
unsigned long bad_cause;
unsigned long vstate_ctrl;
struct __riscv_v_ext_state vstate;
+ unsigned long align_ctl;
};
/* Whitelist the fstate from the task_struct for hardened usercopy */
@@ -94,6 +96,7 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
#define INIT_THREAD { \
.sp = sizeof(init_stack) + (long)&init_stack, \
+ .align_ctl = PR_UNALIGN_NOPRINT, \
}
#define task_pt_regs(tsk) \
@@ -116,6 +119,8 @@ static inline void wait_for_interrupt(void)
__asm__ __volatile__ ("wfi");
}
+extern phys_addr_t dma32_phys_limit;
+
struct device_node;
int riscv_of_processor_hartid(struct device_node *node, unsigned long *hartid);
int riscv_early_of_processor_hartid(struct device_node *node, unsigned long *hartid);
@@ -134,6 +139,12 @@ extern long riscv_v_vstate_ctrl_set_current(unsigned long arg);
extern long riscv_v_vstate_ctrl_get_current(void);
#endif /* CONFIG_RISCV_ISA_V */
+extern int get_unalign_ctl(struct task_struct *tsk, unsigned long addr);
+extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
+
+#define GET_UNALIGN_CTL(tsk, addr) get_unalign_ctl((tsk), (addr))
+#define SET_UNALIGN_CTL(tsk, val) set_unalign_ctl((tsk), (val))
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_RISCV_PROCESSOR_H */
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
index 5b4a1bf5f439..0892f4421bc4 100644
--- a/arch/riscv/include/asm/sbi.h
+++ b/arch/riscv/include/asm/sbi.h
@@ -30,6 +30,7 @@ enum sbi_ext_id {
SBI_EXT_HSM = 0x48534D,
SBI_EXT_SRST = 0x53525354,
SBI_EXT_PMU = 0x504D55,
+ SBI_EXT_DBCN = 0x4442434E,
/* Experimentals extensions must lie within this range */
SBI_EXT_EXPERIMENTAL_START = 0x08000000,
@@ -236,6 +237,12 @@ enum sbi_pmu_ctr_type {
/* Flags defined for counter stop function */
#define SBI_PMU_STOP_FLAG_RESET (1 << 0)
+enum sbi_ext_dbcn_fid {
+ SBI_EXT_DBCN_CONSOLE_WRITE = 0,
+ SBI_EXT_DBCN_CONSOLE_READ = 1,
+ SBI_EXT_DBCN_CONSOLE_WRITE_BYTE = 2,
+};
+
#define SBI_SPEC_VERSION_DEFAULT 0x1
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
@@ -273,9 +280,6 @@ void sbi_set_timer(uint64_t stime_value);
void sbi_shutdown(void);
void sbi_send_ipi(unsigned int cpu);
int sbi_remote_fence_i(const struct cpumask *cpu_mask);
-int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
- unsigned long start,
- unsigned long size);
int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask,
unsigned long start,
diff --git a/arch/riscv/include/asm/scs.h b/arch/riscv/include/asm/scs.h
new file mode 100644
index 000000000000..0e45db78b24b
--- /dev/null
+++ b/arch/riscv/include/asm/scs.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_SCS_H
+#define _ASM_SCS_H
+
+#ifdef __ASSEMBLY__
+#include <asm/asm-offsets.h>
+
+#ifdef CONFIG_SHADOW_CALL_STACK
+
+/* Load init_shadow_call_stack to gp. */
+.macro scs_load_init_stack
+ la gp, init_shadow_call_stack
+ XIP_FIXUP_OFFSET gp
+.endm
+
+/* Load the per-CPU IRQ shadow call stack to gp. */
+.macro scs_load_irq_stack tmp
+ load_per_cpu gp, irq_shadow_call_stack_ptr, \tmp
+.endm
+
+/* Load task_scs_sp(current) to gp. */
+.macro scs_load_current
+ REG_L gp, TASK_TI_SCS_SP(tp)
+.endm
+
+/* Load task_scs_sp(current) to gp, but only if tp has changed. */
+.macro scs_load_current_if_task_changed prev
+ beq \prev, tp, _skip_scs
+ scs_load_current
+_skip_scs:
+.endm
+
+/* Save gp to task_scs_sp(current). */
+.macro scs_save_current
+ REG_S gp, TASK_TI_SCS_SP(tp)
+.endm
+
+#else /* CONFIG_SHADOW_CALL_STACK */
+
+.macro scs_load_init_stack
+.endm
+.macro scs_load_irq_stack tmp
+.endm
+.macro scs_load_current
+.endm
+.macro scs_load_current_if_task_changed prev
+.endm
+.macro scs_save_current
+.endm
+
+#endif /* CONFIG_SHADOW_CALL_STACK */
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_SCS_H */
diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h
index a727be723c56..f90d8e42f3c7 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -9,7 +9,7 @@
#include <linux/jump_label.h>
#include <linux/sched/task_stack.h>
#include <asm/vector.h>
-#include <asm/hwcap.h>
+#include <asm/cpufeature.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/csr.h>
diff --git a/arch/riscv/include/asm/thread_info.h b/arch/riscv/include/asm/thread_info.h
index 1833beb00489..574779900bfb 100644
--- a/arch/riscv/include/asm/thread_info.h
+++ b/arch/riscv/include/asm/thread_info.h
@@ -34,9 +34,6 @@
#ifndef __ASSEMBLY__
-extern long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE / sizeof(long)];
-extern unsigned long spin_shadow_stack;
-
#include <asm/processor.h>
#include <asm/csr.h>
@@ -60,8 +57,20 @@ struct thread_info {
long user_sp; /* User stack pointer */
int cpu;
unsigned long syscall_work; /* SYSCALL_WORK_ flags */
+#ifdef CONFIG_SHADOW_CALL_STACK
+ void *scs_base;
+ void *scs_sp;
+#endif
};
+#ifdef CONFIG_SHADOW_CALL_STACK
+#define INIT_SCS \
+ .scs_base = init_shadow_call_stack, \
+ .scs_sp = init_shadow_call_stack,
+#else
+#define INIT_SCS
+#endif
+
/*
* macros/functions for gaining access to the thread information structure
*
@@ -71,6 +80,7 @@ struct thread_info {
{ \
.flags = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
+ INIT_SCS \
}
void arch_release_task_struct(struct task_struct *tsk);
diff --git a/arch/riscv/include/asm/tlb.h b/arch/riscv/include/asm/tlb.h
index 120bcf2ed8a8..1eb5682b2af6 100644
--- a/arch/riscv/include/asm/tlb.h
+++ b/arch/riscv/include/asm/tlb.h
@@ -15,7 +15,13 @@ static void tlb_flush(struct mmu_gather *tlb);
static inline void tlb_flush(struct mmu_gather *tlb)
{
- flush_tlb_mm(tlb->mm);
+#ifdef CONFIG_MMU
+ if (tlb->fullmm || tlb->need_flush_all)
+ flush_tlb_mm(tlb->mm);
+ else
+ flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end,
+ tlb_get_unmap_size(tlb));
+#endif
}
#endif /* _ASM_RISCV_TLB_H */
diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
index a09196f8de68..8f3418c5f172 100644
--- a/arch/riscv/include/asm/tlbflush.h
+++ b/arch/riscv/include/asm/tlbflush.h
@@ -11,6 +11,9 @@
#include <asm/smp.h>
#include <asm/errata_list.h>
+#define FLUSH_TLB_MAX_SIZE ((unsigned long)-1)
+#define FLUSH_TLB_NO_ASID ((unsigned long)-1)
+
#ifdef CONFIG_MMU
extern unsigned long asid_mask;
@@ -32,9 +35,12 @@ static inline void local_flush_tlb_page(unsigned long addr)
#if defined(CONFIG_SMP) && defined(CONFIG_MMU)
void flush_tlb_all(void);
void flush_tlb_mm(struct mm_struct *mm);
+void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end, unsigned int page_size);
void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
+void flush_tlb_kernel_range(unsigned long start, unsigned long end);
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
@@ -51,14 +57,15 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
local_flush_tlb_all();
}
-#define flush_tlb_mm(mm) flush_tlb_all()
-#endif /* !CONFIG_SMP || !CONFIG_MMU */
-
/* Flush a range of kernel pages */
static inline void flush_tlb_kernel_range(unsigned long start,
unsigned long end)
{
- flush_tlb_all();
+ local_flush_tlb_all();
}
+#define flush_tlb_mm(mm) flush_tlb_all()
+#define flush_tlb_mm_range(mm, start, end, page_size) flush_tlb_all()
+#endif /* !CONFIG_SMP || !CONFIG_MMU */
+
#endif /* _ASM_RISCV_TLBFLUSH_H */
diff --git a/arch/riscv/include/asm/uprobes.h b/arch/riscv/include/asm/uprobes.h
index f2183e00fdd2..3fc7deda9190 100644
--- a/arch/riscv/include/asm/uprobes.h
+++ b/arch/riscv/include/asm/uprobes.h
@@ -34,7 +34,18 @@ struct arch_uprobe {
bool simulate;
};
+#ifdef CONFIG_UPROBES
bool uprobe_breakpoint_handler(struct pt_regs *regs);
bool uprobe_single_step_handler(struct pt_regs *regs);
-
+#else
+static inline bool uprobe_breakpoint_handler(struct pt_regs *regs)
+{
+ return false;
+}
+
+static inline bool uprobe_single_step_handler(struct pt_regs *regs)
+{
+ return false;
+}
+#endif /* CONFIG_UPROBES */
#endif /* _ASM_RISCV_UPROBES_H */
diff --git a/arch/riscv/include/asm/vdso/processor.h b/arch/riscv/include/asm/vdso/processor.h
index 14f5d27783b8..96b65a5396df 100644
--- a/arch/riscv/include/asm/vdso/processor.h
+++ b/arch/riscv/include/asm/vdso/processor.h
@@ -14,7 +14,7 @@ static inline void cpu_relax(void)
__asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy));
#endif
-#ifdef __riscv_zihintpause
+#ifdef CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE
/*
* Reduce instruction retirement.
* This assumes the PC changes.
diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h
index c5ee07b3df07..87aaef656257 100644
--- a/arch/riscv/include/asm/vector.h
+++ b/arch/riscv/include/asm/vector.h
@@ -15,7 +15,7 @@
#include <linux/sched.h>
#include <linux/sched/task_stack.h>
#include <asm/ptrace.h>
-#include <asm/hwcap.h>
+#include <asm/cpufeature.h>
#include <asm/csr.h>
#include <asm/asm.h>
diff --git a/arch/riscv/include/uapi/asm/elf.h b/arch/riscv/include/uapi/asm/elf.h
index d696d6610231..11a71b8533d5 100644
--- a/arch/riscv/include/uapi/asm/elf.h
+++ b/arch/riscv/include/uapi/asm/elf.h
@@ -49,6 +49,7 @@ typedef union __riscv_fp_state elf_fpregset_t;
#define R_RISCV_TLS_DTPREL64 9
#define R_RISCV_TLS_TPREL32 10
#define R_RISCV_TLS_TPREL64 11
+#define R_RISCV_IRELATIVE 58
/* Relocation types not used by the dynamic linker */
#define R_RISCV_BRANCH 16
@@ -81,7 +82,6 @@ typedef union __riscv_fp_state elf_fpregset_t;
#define R_RISCV_ALIGN 43
#define R_RISCV_RVC_BRANCH 44
#define R_RISCV_RVC_JUMP 45
-#define R_RISCV_LUI 46
#define R_RISCV_GPREL_I 47
#define R_RISCV_GPREL_S 48
#define R_RISCV_TPREL_I 49
@@ -93,6 +93,9 @@ typedef union __riscv_fp_state elf_fpregset_t;
#define R_RISCV_SET16 55
#define R_RISCV_SET32 56
#define R_RISCV_32_PCREL 57
+#define R_RISCV_PLT32 59
+#define R_RISCV_SET_ULEB128 60
+#define R_RISCV_SUB_ULEB128 61
#endif /* _UAPI_ASM_RISCV_ELF_H */
diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
index 006bfb48343d..b659ffcfcdb4 100644
--- a/arch/riscv/include/uapi/asm/hwprobe.h
+++ b/arch/riscv/include/uapi/asm/hwprobe.h
@@ -10,7 +10,7 @@
/*
* Interface for probing hardware capabilities from userspace, see
- * Documentation/riscv/hwprobe.rst for more information.
+ * Documentation/arch/riscv/hwprobe.rst for more information.
*/
struct riscv_hwprobe {
__s64 key;
@@ -29,6 +29,7 @@ struct riscv_hwprobe {
#define RISCV_HWPROBE_EXT_ZBA (1 << 3)
#define RISCV_HWPROBE_EXT_ZBB (1 << 4)
#define RISCV_HWPROBE_EXT_ZBS (1 << 5)
+#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6)
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
@@ -36,6 +37,7 @@ struct riscv_hwprobe {
#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0)
#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)
#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
+#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6
/* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
#endif
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
index 992c5e407104..60d3b21dead7 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -80,6 +80,7 @@ struct kvm_riscv_csr {
unsigned long sip;
unsigned long satp;
unsigned long scounteren;
+ unsigned long senvcfg;
};
/* AIA CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
@@ -93,6 +94,11 @@ struct kvm_riscv_aia_csr {
unsigned long iprio2h;
};
+/* Smstateen CSR for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
+struct kvm_riscv_smstateen_csr {
+ unsigned long sstateen0;
+};
+
/* TIMER registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
struct kvm_riscv_timer {
__u64 frequency;
@@ -131,6 +137,8 @@ enum KVM_RISCV_ISA_EXT_ID {
KVM_RISCV_ISA_EXT_ZICSR,
KVM_RISCV_ISA_EXT_ZIFENCEI,
KVM_RISCV_ISA_EXT_ZIHPM,
+ KVM_RISCV_ISA_EXT_SMSTATEEN,
+ KVM_RISCV_ISA_EXT_ZICOND,
KVM_RISCV_ISA_EXT_MAX,
};
@@ -148,6 +156,7 @@ enum KVM_RISCV_SBI_EXT_ID {
KVM_RISCV_SBI_EXT_PMU,
KVM_RISCV_SBI_EXT_EXPERIMENTAL,
KVM_RISCV_SBI_EXT_VENDOR,
+ KVM_RISCV_SBI_EXT_DBCN,
KVM_RISCV_SBI_EXT_MAX,
};
@@ -178,10 +187,13 @@ enum KVM_RISCV_SBI_EXT_ID {
#define KVM_REG_RISCV_CSR (0x03 << KVM_REG_RISCV_TYPE_SHIFT)
#define KVM_REG_RISCV_CSR_GENERAL (0x0 << KVM_REG_RISCV_SUBTYPE_SHIFT)
#define KVM_REG_RISCV_CSR_AIA (0x1 << KVM_REG_RISCV_SUBTYPE_SHIFT)
+#define KVM_REG_RISCV_CSR_SMSTATEEN (0x2 << KVM_REG_RISCV_SUBTYPE_SHIFT)
#define KVM_REG_RISCV_CSR_REG(name) \
(offsetof(struct kvm_riscv_csr, name) / sizeof(unsigned long))
#define KVM_REG_RISCV_CSR_AIA_REG(name) \
(offsetof(struct kvm_riscv_aia_csr, name) / sizeof(unsigned long))
+#define KVM_REG_RISCV_CSR_SMSTATEEN_REG(name) \
+ (offsetof(struct kvm_riscv_smstateen_csr, name) / sizeof(unsigned long))
/* Timer registers are mapped as type 4 */
#define KVM_REG_RISCV_TIMER (0x04 << KVM_REG_RISCV_TYPE_SHIFT)
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index 95cf25d48405..fee22a3d1b53 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -57,9 +57,10 @@ obj-y += stacktrace.o
obj-y += cacheinfo.o
obj-y += patch.o
obj-y += probes/
+obj-y += tests/
obj-$(CONFIG_MMU) += vdso.o vdso/
-obj-$(CONFIG_RISCV_M_MODE) += traps_misaligned.o
+obj-$(CONFIG_RISCV_MISALIGNED) += traps_misaligned.o
obj-$(CONFIG_FPU) += fpu.o
obj-$(CONFIG_RISCV_ISA_V) += vector.o
obj-$(CONFIG_SMP) += smpboot.o
diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c
index 56cb2c986c48..e619edc8b0cc 100644
--- a/arch/riscv/kernel/acpi.c
+++ b/arch/riscv/kernel/acpi.c
@@ -14,9 +14,10 @@
*/
#include <linux/acpi.h>
+#include <linux/efi.h>
#include <linux/io.h>
+#include <linux/memblock.h>
#include <linux/pci.h>
-#include <linux/efi.h>
int acpi_noirq = 1; /* skip ACPI IRQ initialization */
int acpi_disabled = 1;
@@ -217,7 +218,89 @@ void __init __acpi_unmap_table(void __iomem *map, unsigned long size)
void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
{
- return (void __iomem *)memremap(phys, size, MEMREMAP_WB);
+ efi_memory_desc_t *md, *region = NULL;
+ pgprot_t prot;
+
+ if (WARN_ON_ONCE(!efi_enabled(EFI_MEMMAP)))
+ return NULL;
+
+ for_each_efi_memory_desc(md) {
+ u64 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+
+ if (phys < md->phys_addr || phys >= end)
+ continue;
+
+ if (phys + size > end) {
+ pr_warn(FW_BUG "requested region covers multiple EFI memory regions\n");
+ return NULL;
+ }
+ region = md;
+ break;
+ }
+
+ /*
+ * It is fine for AML to remap regions that are not represented in the
+ * EFI memory map at all, as it only describes normal memory, and MMIO
+ * regions that require a virtual mapping to make them accessible to
+ * the EFI runtime services.
+ */
+ prot = PAGE_KERNEL_IO;
+ if (region) {
+ switch (region->type) {
+ case EFI_LOADER_CODE:
+ case EFI_LOADER_DATA:
+ case EFI_BOOT_SERVICES_CODE:
+ case EFI_BOOT_SERVICES_DATA:
+ case EFI_CONVENTIONAL_MEMORY:
+ case EFI_PERSISTENT_MEMORY:
+ if (memblock_is_map_memory(phys) ||
+ !memblock_is_region_memory(phys, size)) {
+ pr_warn(FW_BUG "requested region covers kernel memory\n");
+ return NULL;
+ }
+
+ /*
+ * Mapping kernel memory is permitted if the region in
+ * question is covered by a single memblock with the
+ * NOMAP attribute set: this enables the use of ACPI
+ * table overrides passed via initramfs.
+ * This particular use case only requires read access.
+ */
+ fallthrough;
+
+ case EFI_RUNTIME_SERVICES_CODE:
+ /*
+ * This would be unusual, but not problematic per se,
+ * as long as we take care not to create a writable
+ * mapping for executable code.
+ */
+ prot = PAGE_KERNEL_RO;
+ break;
+
+ case EFI_ACPI_RECLAIM_MEMORY:
+ /*
+ * ACPI reclaim memory is used to pass firmware tables
+ * and other data that is intended for consumption by
+ * the OS only, which may decide it wants to reclaim
+ * that memory and use it for something else. We never
+ * do that, but we usually add it to the linear map
+ * anyway, in which case we should use the existing
+ * mapping.
+ */
+ if (memblock_is_map_memory(phys))
+ return (void __iomem *)__va(phys);
+ fallthrough;
+
+ default:
+ if (region->attribute & EFI_MEMORY_WB)
+ prot = PAGE_KERNEL;
+ else if ((region->attribute & EFI_MEMORY_WC) ||
+ (region->attribute & EFI_MEMORY_WT))
+ prot = pgprot_writecombine(PAGE_KERNEL);
+ }
+ }
+
+ return ioremap_prot(phys, size, pgprot_val(prot));
}
#ifdef CONFIG_PCI
diff --git a/arch/riscv/kernel/asm-offsets.c b/arch/riscv/kernel/asm-offsets.c
index d6a75aac1d27..a03129f40c46 100644
--- a/arch/riscv/kernel/asm-offsets.c
+++ b/arch/riscv/kernel/asm-offsets.c
@@ -14,6 +14,7 @@
#include <asm/thread_info.h>
#include <asm/ptrace.h>
#include <asm/cpu_ops_sbi.h>
+#include <asm/stacktrace.h>
#include <asm/suspend.h>
void asm_offsets(void);
@@ -38,7 +39,11 @@ void asm_offsets(void)
OFFSET(TASK_TI_PREEMPT_COUNT, task_struct, thread_info.preempt_count);
OFFSET(TASK_TI_KERNEL_SP, task_struct, thread_info.kernel_sp);
OFFSET(TASK_TI_USER_SP, task_struct, thread_info.user_sp);
+#ifdef CONFIG_SHADOW_CALL_STACK
+ OFFSET(TASK_TI_SCS_SP, task_struct, thread_info.scs_sp);
+#endif
+ OFFSET(TASK_TI_CPU_NUM, task_struct, thread_info.cpu);
OFFSET(TASK_THREAD_F0, task_struct, thread.fstate.f[0]);
OFFSET(TASK_THREAD_F1, task_struct, thread.fstate.f[1]);
OFFSET(TASK_THREAD_F2, task_struct, thread.fstate.f[2]);
@@ -479,4 +484,8 @@ void asm_offsets(void)
OFFSET(KERNEL_MAP_VIRT_ADDR, kernel_mapping, virt_addr);
OFFSET(SBI_HART_BOOT_TASK_PTR_OFFSET, sbi_hart_boot_data, task_ptr);
OFFSET(SBI_HART_BOOT_STACK_PTR_OFFSET, sbi_hart_boot_data, stack_ptr);
+
+ DEFINE(STACKFRAME_SIZE_ON_STACK, ALIGN(sizeof(struct stackframe), STACK_ALIGN));
+ OFFSET(STACKFRAME_FP, stackframe, fp);
+ OFFSET(STACKFRAME_RA, stackframe, ra);
}
diff --git a/arch/riscv/kernel/compat_vdso/Makefile b/arch/riscv/kernel/compat_vdso/Makefile
index b86e5e2c3aea..62fa393b2eb2 100644
--- a/arch/riscv/kernel/compat_vdso/Makefile
+++ b/arch/riscv/kernel/compat_vdso/Makefile
@@ -76,13 +76,3 @@ quiet_cmd_compat_vdsold = VDSOLD $@
# actual build commands
quiet_cmd_compat_vdsoas = VDSOAS $@
cmd_compat_vdsoas = $(COMPAT_CC) $(a_flags) $(COMPAT_CC_FLAGS) -c -o $@ $<
-
-# install commands for the unstripped file
-quiet_cmd_compat_vdso_install = INSTALL $@
- cmd_compat_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/compat_vdso/$@
-
-compat_vdso.so: $(obj)/compat_vdso.so.dbg
- @mkdir -p $(MODLIB)/compat_vdso
- $(call cmd,compat_vdso_install)
-
-compat_vdso_install: compat_vdso.so
diff --git a/arch/riscv/kernel/copy-unaligned.S b/arch/riscv/kernel/copy-unaligned.S
index cfdecfbaad62..2b3d9398c113 100644
--- a/arch/riscv/kernel/copy-unaligned.S
+++ b/arch/riscv/kernel/copy-unaligned.S
@@ -9,7 +9,7 @@
/* void __riscv_copy_words_unaligned(void *, const void *, size_t) */
/* Performs a memcpy without aligning buffers, using word loads and stores. */
/* Note: The size is truncated to a multiple of 8 * SZREG */
-ENTRY(__riscv_copy_words_unaligned)
+SYM_FUNC_START(__riscv_copy_words_unaligned)
andi a4, a2, ~((8*SZREG)-1)
beqz a4, 2f
add a3, a1, a4
@@ -36,12 +36,12 @@ ENTRY(__riscv_copy_words_unaligned)
2:
ret
-END(__riscv_copy_words_unaligned)
+SYM_FUNC_END(__riscv_copy_words_unaligned)
/* void __riscv_copy_bytes_unaligned(void *, const void *, size_t) */
/* Performs a memcpy without aligning buffers, using only byte accesses. */
/* Note: The size is truncated to a multiple of 8 */
-ENTRY(__riscv_copy_bytes_unaligned)
+SYM_FUNC_START(__riscv_copy_bytes_unaligned)
andi a4, a2, ~(8-1)
beqz a4, 2f
add a3, a1, a4
@@ -68,4 +68,4 @@ ENTRY(__riscv_copy_bytes_unaligned)
2:
ret
-END(__riscv_copy_bytes_unaligned)
+SYM_FUNC_END(__riscv_copy_bytes_unaligned)
diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c
index c17dacb1141c..d11d6320fb0d 100644
--- a/arch/riscv/kernel/cpu.c
+++ b/arch/riscv/kernel/cpu.c
@@ -125,13 +125,14 @@ old_interface:
*/
int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid)
{
- int rc;
-
for (; node; node = node->parent) {
if (of_device_is_compatible(node, "riscv")) {
- rc = riscv_of_processor_hartid(node, hartid);
- if (!rc)
- return 0;
+ *hartid = (unsigned long)of_get_cpu_hwid(node, 0);
+ if (*hartid == ~0UL) {
+ pr_warn("Found CPU without hart ID\n");
+ return -ENODEV;
+ }
+ return 0;
}
}
@@ -202,9 +203,8 @@ arch_initcall(riscv_cpuinfo_init);
#ifdef CONFIG_PROC_FS
-static void print_isa(struct seq_file *f)
+static void print_isa(struct seq_file *f, const unsigned long *isa_bitmap)
{
- seq_puts(f, "isa\t\t: ");
if (IS_ENABLED(CONFIG_32BIT))
seq_write(f, "rv32", 4);
@@ -212,7 +212,7 @@ static void print_isa(struct seq_file *f)
seq_write(f, "rv64", 4);
for (int i = 0; i < riscv_isa_ext_count; i++) {
- if (!__riscv_isa_extension_available(NULL, riscv_isa_ext[i].id))
+ if (!__riscv_isa_extension_available(isa_bitmap, riscv_isa_ext[i].id))
continue;
/* Only multi-letter extensions are split by underscores */
@@ -276,7 +276,15 @@ static int c_show(struct seq_file *m, void *v)
seq_printf(m, "processor\t: %lu\n", cpu_id);
seq_printf(m, "hart\t\t: %lu\n", cpuid_to_hartid_map(cpu_id));
- print_isa(m);
+
+ /*
+ * For historical raisins, the isa: line is limited to the lowest common
+ * denominator of extensions supported across all harts. A true list of
+ * extensions supported on this hart is printed later in the hart isa:
+ * line.
+ */
+ seq_puts(m, "isa\t\t: ");
+ print_isa(m, NULL);
print_mmu(m);
if (acpi_disabled) {
@@ -292,6 +300,13 @@ static int c_show(struct seq_file *m, void *v)
seq_printf(m, "mvendorid\t: 0x%lx\n", ci->mvendorid);
seq_printf(m, "marchid\t\t: 0x%lx\n", ci->marchid);
seq_printf(m, "mimpid\t\t: 0x%lx\n", ci->mimpid);
+
+ /*
+ * Print the ISA extensions specific to this hart, which may show
+ * additional extensions not present across all harts.
+ */
+ seq_puts(m, "hart isa\t: ");
+ print_isa(m, hart_isa[cpu_id].isa);
seq_puts(m, "\n");
return 0;
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 1cfbba65d11a..b3785ffc1570 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -8,6 +8,7 @@
#include <linux/acpi.h>
#include <linux/bitmap.h>
+#include <linux/cpuhotplug.h>
#include <linux/ctype.h>
#include <linux/log2.h>
#include <linux/memory.h>
@@ -29,6 +30,7 @@
#define MISALIGNED_ACCESS_JIFFIES_LG2 1
#define MISALIGNED_BUFFER_SIZE 0x4000
+#define MISALIGNED_BUFFER_ORDER get_order(MISALIGNED_BUFFER_SIZE)
#define MISALIGNED_COPY_SIZE ((MISALIGNED_BUFFER_SIZE / 2) - 0x80)
unsigned long elf_hwcap __read_mostly;
@@ -93,10 +95,10 @@ static bool riscv_isa_extension_check(int id)
return true;
case RISCV_ISA_EXT_ZICBOZ:
if (!riscv_cboz_block_size) {
- pr_err("Zicboz detected in ISA string, but no cboz-block-size found\n");
+ pr_err("Zicboz detected in ISA string, disabling as no cboz-block-size found\n");
return false;
} else if (!is_power_of_2(riscv_cboz_block_size)) {
- pr_err("cboz-block-size present, but is not a power-of-2\n");
+ pr_err("Zicboz disabled as cboz-block-size present, but is not a power-of-2\n");
return false;
}
return true;
@@ -167,6 +169,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM),
__RISCV_ISA_EXT_DATA(zicboz, RISCV_ISA_EXT_ZICBOZ),
__RISCV_ISA_EXT_DATA(zicntr, RISCV_ISA_EXT_ZICNTR),
+ __RISCV_ISA_EXT_DATA(zicond, RISCV_ISA_EXT_ZICOND),
__RISCV_ISA_EXT_DATA(zicsr, RISCV_ISA_EXT_ZICSR),
__RISCV_ISA_EXT_DATA(zifencei, RISCV_ISA_EXT_ZIFENCEI),
__RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE),
@@ -175,6 +178,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(zbb, RISCV_ISA_EXT_ZBB),
__RISCV_ISA_EXT_DATA(zbs, RISCV_ISA_EXT_ZBS),
__RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA),
+ __RISCV_ISA_EXT_DATA(smstateen, RISCV_ISA_EXT_SMSTATEEN),
__RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA),
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
__RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
@@ -204,10 +208,11 @@ static void __init riscv_parse_isa_string(unsigned long *this_hwcap, struct risc
switch (*ext) {
case 's':
/*
- * Workaround for invalid single-letter 's' & 'u'(QEMU).
+ * Workaround for invalid single-letter 's' & 'u' (QEMU).
* No need to set the bit in riscv_isa as 's' & 'u' are
- * not valid ISA extensions. It works until multi-letter
- * extension starting with "Su" appears.
+ * not valid ISA extensions. It works unless the first
+ * multi-letter extension in the ISA string begins with
+ * "Su" and is not prefixed with an underscore.
*/
if (ext[-1] != '_' && ext[1] == 'u') {
++isa;
@@ -556,23 +561,21 @@ unsigned long riscv_get_elf_hwcap(void)
return hwcap;
}
-void check_unaligned_access(int cpu)
+static int check_unaligned_access(void *param)
{
+ int cpu = smp_processor_id();
u64 start_cycles, end_cycles;
u64 word_cycles;
u64 byte_cycles;
int ratio;
unsigned long start_jiffies, now;
- struct page *page;
+ struct page *page = param;
void *dst;
void *src;
long speed = RISCV_HWPROBE_MISALIGNED_SLOW;
- page = alloc_pages(GFP_NOWAIT, get_order(MISALIGNED_BUFFER_SIZE));
- if (!page) {
- pr_warn("Can't alloc pages to measure memcpy performance");
- return;
- }
+ if (check_unaligned_access_emulated(cpu))
+ return 0;
/* Make an unaligned destination buffer. */
dst = (void *)((unsigned long)page_address(page) | 0x1);
@@ -626,7 +629,7 @@ void check_unaligned_access(int cpu)
pr_warn("cpu%d: rdtime lacks granularity needed to measure unaligned access speed\n",
cpu);
- goto out;
+ return 0;
}
if (word_cycles < byte_cycles)
@@ -640,18 +643,90 @@ void check_unaligned_access(int cpu)
(speed == RISCV_HWPROBE_MISALIGNED_FAST) ? "fast" : "slow");
per_cpu(misaligned_access_speed, cpu) = speed;
+ return 0;
+}
-out:
- __free_pages(page, get_order(MISALIGNED_BUFFER_SIZE));
+static void check_unaligned_access_nonboot_cpu(void *param)
+{
+ unsigned int cpu = smp_processor_id();
+ struct page **pages = param;
+
+ if (smp_processor_id() != 0)
+ check_unaligned_access(pages[cpu]);
}
-static int check_unaligned_access_boot_cpu(void)
+static int riscv_online_cpu(unsigned int cpu)
{
- check_unaligned_access(0);
+ static struct page *buf;
+
+ /* We are already set since the last check */
+ if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_UNKNOWN)
+ return 0;
+
+ buf = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER);
+ if (!buf) {
+ pr_warn("Allocation failure, not measuring misaligned performance\n");
+ return -ENOMEM;
+ }
+
+ check_unaligned_access(buf);
+ __free_pages(buf, MISALIGNED_BUFFER_ORDER);
return 0;
}
-arch_initcall(check_unaligned_access_boot_cpu);
+/* Measure unaligned access on all CPUs present at boot in parallel. */
+static int check_unaligned_access_all_cpus(void)
+{
+ unsigned int cpu;
+ unsigned int cpu_count = num_possible_cpus();
+ struct page **bufs = kzalloc(cpu_count * sizeof(struct page *),
+ GFP_KERNEL);
+
+ if (!bufs) {
+ pr_warn("Allocation failure, not measuring misaligned performance\n");
+ return 0;
+ }
+
+ /*
+ * Allocate separate buffers for each CPU so there's no fighting over
+ * cache lines.
+ */
+ for_each_cpu(cpu, cpu_online_mask) {
+ bufs[cpu] = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER);
+ if (!bufs[cpu]) {
+ pr_warn("Allocation failure, not measuring misaligned performance\n");
+ goto out;
+ }
+ }
+
+ /* Check everybody except 0, who stays behind to tend jiffies. */
+ on_each_cpu(check_unaligned_access_nonboot_cpu, bufs, 1);
+
+ /* Check core 0. */
+ smp_call_on_cpu(0, check_unaligned_access, bufs[0], true);
+
+ /* Setup hotplug callback for any new CPUs that come online. */
+ cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online",
+ riscv_online_cpu, NULL);
+
+out:
+ unaligned_emulation_finish();
+ for_each_cpu(cpu, cpu_online_mask) {
+ if (bufs[cpu])
+ __free_pages(bufs[cpu], MISALIGNED_BUFFER_ORDER);
+ }
+
+ kfree(bufs);
+ return 0;
+}
+
+arch_initcall(check_unaligned_access_all_cpus);
+
+void riscv_user_isa_enable(void)
+{
+ if (riscv_cpu_has_extension_unlikely(smp_processor_id(), RISCV_ISA_EXT_ZICBOZ))
+ csr_set(CSR_SENVCFG, ENVCFG_CBZE);
+}
#ifdef CONFIG_RISCV_ALTERNATIVE
/*
diff --git a/arch/riscv/kernel/crash_core.c b/arch/riscv/kernel/crash_core.c
index 55f1d7856b54..8706736fd4e2 100644
--- a/arch/riscv/kernel/crash_core.c
+++ b/arch/riscv/kernel/crash_core.c
@@ -5,18 +5,20 @@
void arch_crash_save_vmcoreinfo(void)
{
- VMCOREINFO_NUMBER(VA_BITS);
VMCOREINFO_NUMBER(phys_ram_base);
vmcoreinfo_append_str("NUMBER(PAGE_OFFSET)=0x%lx\n", PAGE_OFFSET);
vmcoreinfo_append_str("NUMBER(VMALLOC_START)=0x%lx\n", VMALLOC_START);
vmcoreinfo_append_str("NUMBER(VMALLOC_END)=0x%lx\n", VMALLOC_END);
+#ifdef CONFIG_MMU
+ VMCOREINFO_NUMBER(VA_BITS);
vmcoreinfo_append_str("NUMBER(VMEMMAP_START)=0x%lx\n", VMEMMAP_START);
vmcoreinfo_append_str("NUMBER(VMEMMAP_END)=0x%lx\n", VMEMMAP_END);
#ifdef CONFIG_64BIT
vmcoreinfo_append_str("NUMBER(MODULES_VADDR)=0x%lx\n", MODULES_VADDR);
vmcoreinfo_append_str("NUMBER(MODULES_END)=0x%lx\n", MODULES_END);
#endif
+#endif
vmcoreinfo_append_str("NUMBER(KERNEL_LINK_ADDR)=0x%lx\n", KERNEL_LINK_ADDR);
vmcoreinfo_append_str("NUMBER(va_kernel_pa_offset)=0x%lx\n",
kernel_map.va_kernel_pa_offset);
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 143a2bb3e697..54ca4564a926 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -9,10 +9,15 @@
#include <asm/asm.h>
#include <asm/csr.h>
+#include <asm/scs.h>
#include <asm/unistd.h>
+#include <asm/page.h>
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
#include <asm/errata_list.h>
+#include <linux/sizes.h>
+
+ .section .irqentry.text, "ax"
SYM_CODE_START(handle_exception)
/*
@@ -21,9 +26,9 @@ SYM_CODE_START(handle_exception)
* register will contain 0, and we should continue on the current TP.
*/
csrrw tp, CSR_SCRATCH, tp
- bnez tp, _save_context
+ bnez tp, .Lsave_context
-_restore_kernel_tpsp:
+.Lrestore_kernel_tpsp:
csrr tp, CSR_SCRATCH
REG_S sp, TASK_TI_KERNEL_SP(tp)
@@ -35,7 +40,7 @@ _restore_kernel_tpsp:
REG_L sp, TASK_TI_KERNEL_SP(tp)
#endif
-_save_context:
+.Lsave_context:
REG_S sp, TASK_TI_USER_SP(tp)
REG_L sp, TASK_TI_KERNEL_SP(tp)
addi sp, sp, -(PT_SIZE_ON_STACK)
@@ -73,10 +78,11 @@ _save_context:
csrw CSR_SCRATCH, x0
/* Load the global pointer */
-.option push
-.option norelax
- la gp, __global_pointer$
-.option pop
+ load_global_pointer
+
+ /* Load the kernel shadow call stack pointer if coming from userspace */
+ scs_load_current_if_task_changed s5
+
move a0, sp /* pt_regs */
la ra, ret_from_exception
@@ -123,6 +129,9 @@ SYM_CODE_START_NOALIGN(ret_from_exception)
addi s0, sp, PT_SIZE_ON_STACK
REG_S s0, TASK_TI_KERNEL_SP(tp)
+ /* Save the kernel shadow call stack pointer */
+ scs_save_current
+
/*
* Save TP into the scratch register , so we can find the kernel data
* structures again.
@@ -170,67 +179,15 @@ SYM_CODE_END(ret_from_exception)
#ifdef CONFIG_VMAP_STACK
SYM_CODE_START_LOCAL(handle_kernel_stack_overflow)
- /*
- * Takes the psuedo-spinlock for the shadow stack, in case multiple
- * harts are concurrently overflowing their kernel stacks. We could
- * store any value here, but since we're overflowing the kernel stack
- * already we only have SP to use as a scratch register. So we just
- * swap in the address of the spinlock, as that's definately non-zero.
- *
- * Pairs with a store_release in handle_bad_stack().
- */
-1: la sp, spin_shadow_stack
- REG_AMOSWAP_AQ sp, sp, (sp)
- bnez sp, 1b
-
- la sp, shadow_stack
- addi sp, sp, SHADOW_OVERFLOW_STACK_SIZE
+ /* we reach here from kernel context, sscratch must be 0 */
+ csrrw x31, CSR_SCRATCH, x31
+ asm_per_cpu sp, overflow_stack, x31
+ li x31, OVERFLOW_STACK_SIZE
+ add sp, sp, x31
+ /* zero out x31 again and restore x31 */
+ xor x31, x31, x31
+ csrrw x31, CSR_SCRATCH, x31
- //save caller register to shadow stack
- addi sp, sp, -(PT_SIZE_ON_STACK)
- REG_S x1, PT_RA(sp)
- REG_S x5, PT_T0(sp)
- REG_S x6, PT_T1(sp)
- REG_S x7, PT_T2(sp)
- REG_S x10, PT_A0(sp)
- REG_S x11, PT_A1(sp)
- REG_S x12, PT_A2(sp)
- REG_S x13, PT_A3(sp)
- REG_S x14, PT_A4(sp)
- REG_S x15, PT_A5(sp)
- REG_S x16, PT_A6(sp)
- REG_S x17, PT_A7(sp)
- REG_S x28, PT_T3(sp)
- REG_S x29, PT_T4(sp)
- REG_S x30, PT_T5(sp)
- REG_S x31, PT_T6(sp)
-
- la ra, restore_caller_reg
- tail get_overflow_stack
-
-restore_caller_reg:
- //save per-cpu overflow stack
- REG_S a0, -8(sp)
- //restore caller register from shadow_stack
- REG_L x1, PT_RA(sp)
- REG_L x5, PT_T0(sp)
- REG_L x6, PT_T1(sp)
- REG_L x7, PT_T2(sp)
- REG_L x10, PT_A0(sp)
- REG_L x11, PT_A1(sp)
- REG_L x12, PT_A2(sp)
- REG_L x13, PT_A3(sp)
- REG_L x14, PT_A4(sp)
- REG_L x15, PT_A5(sp)
- REG_L x16, PT_A6(sp)
- REG_L x17, PT_A7(sp)
- REG_L x28, PT_T3(sp)
- REG_L x29, PT_T4(sp)
- REG_L x30, PT_T5(sp)
- REG_L x31, PT_T6(sp)
-
- //load per-cpu overflow stack
- REG_L sp, -8(sp)
addi sp, sp, -(PT_SIZE_ON_STACK)
//save context to overflow stack
@@ -268,6 +225,43 @@ SYM_CODE_START(ret_from_fork)
tail syscall_exit_to_user_mode
SYM_CODE_END(ret_from_fork)
+#ifdef CONFIG_IRQ_STACKS
+/*
+ * void call_on_irq_stack(struct pt_regs *regs,
+ * void (*func)(struct pt_regs *));
+ *
+ * Calls func(regs) using the per-CPU IRQ stack.
+ */
+SYM_FUNC_START(call_on_irq_stack)
+ /* Create a frame record to save ra and s0 (fp) */
+ addi sp, sp, -STACKFRAME_SIZE_ON_STACK
+ REG_S ra, STACKFRAME_RA(sp)
+ REG_S s0, STACKFRAME_FP(sp)
+ addi s0, sp, STACKFRAME_SIZE_ON_STACK
+
+ /* Switch to the per-CPU shadow call stack */
+ scs_save_current
+ scs_load_irq_stack t0
+
+ /* Switch to the per-CPU IRQ stack and call the handler */
+ load_per_cpu t0, irq_stack_ptr, t1
+ li t1, IRQ_STACK_SIZE
+ add sp, t0, t1
+ jalr a1
+
+ /* Switch back to the thread shadow call stack */
+ scs_load_current
+
+ /* Switch back to the thread stack and restore ra and s0 */
+ addi sp, s0, -STACKFRAME_SIZE_ON_STACK
+ REG_L ra, STACKFRAME_RA(sp)
+ REG_L s0, STACKFRAME_FP(sp)
+ addi sp, sp, STACKFRAME_SIZE_ON_STACK
+
+ ret
+SYM_FUNC_END(call_on_irq_stack)
+#endif /* CONFIG_IRQ_STACKS */
+
/*
* Integer register context switch
* The callee-saved registers must be saved and restored.
@@ -297,6 +291,8 @@ SYM_FUNC_START(__switch_to)
REG_S s9, TASK_THREAD_S9_RA(a3)
REG_S s10, TASK_THREAD_S10_RA(a3)
REG_S s11, TASK_THREAD_S11_RA(a3)
+ /* Save the kernel shadow call stack pointer */
+ scs_save_current
/* Restore context from next->thread */
REG_L ra, TASK_THREAD_RA_RA(a4)
REG_L sp, TASK_THREAD_SP_RA(a4)
@@ -314,6 +310,8 @@ SYM_FUNC_START(__switch_to)
REG_L s11, TASK_THREAD_S11_RA(a4)
/* The offset of thread_info in task_struct is zero. */
move tp, a1
+ /* Switch to the next shadow call stack */
+ scs_load_current
ret
SYM_FUNC_END(__switch_to)
@@ -324,7 +322,7 @@ SYM_FUNC_END(__switch_to)
.section ".rodata"
.align LGREG
/* Exception vector table */
-SYM_CODE_START(excp_vect_table)
+SYM_DATA_START_LOCAL(excp_vect_table)
RISCV_PTR do_trap_insn_misaligned
ALT_INSN_FAULT(RISCV_PTR do_trap_insn_fault)
RISCV_PTR do_trap_insn_illegal
@@ -342,12 +340,11 @@ SYM_CODE_START(excp_vect_table)
RISCV_PTR do_page_fault /* load page fault */
RISCV_PTR do_trap_unknown
RISCV_PTR do_page_fault /* store page fault */
-excp_vect_table_end:
-SYM_CODE_END(excp_vect_table)
+SYM_DATA_END_LABEL(excp_vect_table, SYM_L_LOCAL, excp_vect_table_end)
#ifndef CONFIG_MMU
-SYM_CODE_START(__user_rt_sigreturn)
+SYM_DATA_START(__user_rt_sigreturn)
li a7, __NR_rt_sigreturn
ecall
-SYM_CODE_END(__user_rt_sigreturn)
+SYM_DATA_END(__user_rt_sigreturn)
#endif
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
index dd2205473de7..2c543f130f93 100644
--- a/arch/riscv/kernel/fpu.S
+++ b/arch/riscv/kernel/fpu.S
@@ -19,7 +19,7 @@
#include <asm/csr.h>
#include <asm/asm-offsets.h>
-ENTRY(__fstate_save)
+SYM_FUNC_START(__fstate_save)
li a2, TASK_THREAD_F0
add a0, a0, a2
li t1, SR_FS
@@ -60,9 +60,9 @@ ENTRY(__fstate_save)
sw t0, TASK_THREAD_FCSR_F0(a0)
csrc CSR_STATUS, t1
ret
-ENDPROC(__fstate_save)
+SYM_FUNC_END(__fstate_save)
-ENTRY(__fstate_restore)
+SYM_FUNC_START(__fstate_restore)
li a2, TASK_THREAD_F0
add a0, a0, a2
li t1, SR_FS
@@ -103,4 +103,125 @@ ENTRY(__fstate_restore)
fscsr t0
csrc CSR_STATUS, t1
ret
-ENDPROC(__fstate_restore)
+SYM_FUNC_END(__fstate_restore)
+
+#define get_f32(which) fmv.x.s a0, which; j 2f
+#define put_f32(which) fmv.s.x which, a1; j 2f
+#if __riscv_xlen == 64
+# define get_f64(which) fmv.x.d a0, which; j 2f
+# define put_f64(which) fmv.d.x which, a1; j 2f
+#else
+# define get_f64(which) fsd which, 0(a1); j 2f
+# define put_f64(which) fld which, 0(a1); j 2f
+#endif
+
+.macro fp_access_prologue
+ /*
+ * Compute jump offset to store the correct FP register since we don't
+ * have indirect FP register access
+ */
+ sll t0, a0, 3
+ la t2, 1f
+ add t0, t0, t2
+ li t1, SR_FS
+ csrs CSR_STATUS, t1
+ jr t0
+1:
+.endm
+
+.macro fp_access_epilogue
+2:
+ csrc CSR_STATUS, t1
+ ret
+.endm
+
+#define fp_access_body(__access_func) \
+ __access_func(f0); \
+ __access_func(f1); \
+ __access_func(f2); \
+ __access_func(f3); \
+ __access_func(f4); \
+ __access_func(f5); \
+ __access_func(f6); \
+ __access_func(f7); \
+ __access_func(f8); \
+ __access_func(f9); \
+ __access_func(f10); \
+ __access_func(f11); \
+ __access_func(f12); \
+ __access_func(f13); \
+ __access_func(f14); \
+ __access_func(f15); \
+ __access_func(f16); \
+ __access_func(f17); \
+ __access_func(f18); \
+ __access_func(f19); \
+ __access_func(f20); \
+ __access_func(f21); \
+ __access_func(f22); \
+ __access_func(f23); \
+ __access_func(f24); \
+ __access_func(f25); \
+ __access_func(f26); \
+ __access_func(f27); \
+ __access_func(f28); \
+ __access_func(f29); \
+ __access_func(f30); \
+ __access_func(f31)
+
+
+#ifdef CONFIG_RISCV_MISALIGNED
+
+/*
+ * Disable compressed instructions set to keep a constant offset between FP
+ * load/store/move instructions
+ */
+.option norvc
+/*
+ * put_f32_reg - Set a FP register from a register containing the value
+ * a0 = FP register index to be set
+ * a1 = value to be loaded in the FP register
+ */
+SYM_FUNC_START(put_f32_reg)
+ fp_access_prologue
+ fp_access_body(put_f32)
+ fp_access_epilogue
+SYM_FUNC_END(put_f32_reg)
+
+/*
+ * get_f32_reg - Get a FP register value and return it
+ * a0 = FP register index to be retrieved
+ */
+SYM_FUNC_START(get_f32_reg)
+ fp_access_prologue
+ fp_access_body(get_f32)
+ fp_access_epilogue
+SYM_FUNC_END(get_f32_reg)
+
+/*
+ * put_f64_reg - Set a 64 bits FP register from a value or a pointer.
+ * a0 = FP register index to be set
+ * a1 = value/pointer to be loaded in the FP register (when xlen == 32 bits, we
+ * load the value to a pointer).
+ */
+SYM_FUNC_START(put_f64_reg)
+ fp_access_prologue
+ fp_access_body(put_f64)
+ fp_access_epilogue
+SYM_FUNC_END(put_f64_reg)
+
+/*
+ * put_f64_reg - Get a 64 bits FP register value and returned it or store it to
+ * a pointer.
+ * a0 = FP register index to be retrieved
+ * a1 = If xlen == 32, pointer which should be loaded with the FP register value
+ * or unused if xlen == 64. In which case the FP register value is returned
+ * through a0
+ */
+SYM_FUNC_START(get_f64_reg)
+ fp_access_prologue
+ fp_access_body(get_f64)
+ fp_access_epilogue
+SYM_FUNC_END(get_f64_reg)
+
+#endif /* CONFIG_RISCV_MISALIGNED */
diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
index 3710ea5d160f..76ace1e0b46f 100644
--- a/arch/riscv/kernel/head.S
+++ b/arch/riscv/kernel/head.S
@@ -14,11 +14,12 @@
#include <asm/cpu_ops_sbi.h>
#include <asm/hwcap.h>
#include <asm/image.h>
+#include <asm/scs.h>
#include <asm/xip_fixup.h>
#include "efi-header.S"
__HEAD
-ENTRY(_start)
+SYM_CODE_START(_start)
/*
* Image header expected by Linux boot-loaders. The image header data
* structure is described in asm/image.h.
@@ -110,10 +111,7 @@ relocate_enable_mmu:
csrw CSR_TVEC, a0
/* Reload the global pointer */
-.option push
-.option norelax
- la gp, __global_pointer$
-.option pop
+ load_global_pointer
/*
* Switch to kernel page tables. A full fence is necessary in order to
@@ -134,10 +132,7 @@ secondary_start_sbi:
csrw CSR_IP, zero
/* Load the global pointer */
- .option push
- .option norelax
- la gp, __global_pointer$
- .option pop
+ load_global_pointer
/*
* Disable FPU & VECTOR to detect illegal usage of
@@ -168,12 +163,13 @@ secondary_start_sbi:
XIP_FIXUP_OFFSET a0
call relocate_enable_mmu
#endif
- call setup_trap_vector
+ call .Lsetup_trap_vector
+ scs_load_current
tail smp_callin
#endif /* CONFIG_SMP */
.align 2
-setup_trap_vector:
+.Lsetup_trap_vector:
/* Set trap vector to exception handler */
la a0, handle_exception
csrw CSR_TVEC, a0
@@ -191,9 +187,9 @@ setup_trap_vector:
wfi
j .Lsecondary_park
-END(_start)
+SYM_CODE_END(_start)
-ENTRY(_start_kernel)
+SYM_CODE_START(_start_kernel)
/* Mask all interrupts */
csrw CSR_IE, zero
csrw CSR_IP, zero
@@ -210,7 +206,7 @@ ENTRY(_start_kernel)
* not implement PMPs, so we set up a quick trap handler to just skip
* touching the PMPs on any trap.
*/
- la a0, pmp_done
+ la a0, .Lpmp_done
csrw CSR_TVEC, a0
li a0, -1
@@ -218,7 +214,7 @@ ENTRY(_start_kernel)
li a0, (PMP_A_NAPOT | PMP_R | PMP_W | PMP_X)
csrw CSR_PMPCFG0, a0
.align 2
-pmp_done:
+.Lpmp_done:
/*
* The hartid in a0 is expected later on, and we have no firmware
@@ -228,10 +224,7 @@ pmp_done:
#endif /* CONFIG_RISCV_M_MODE */
/* Load the global pointer */
-.option push
-.option norelax
- la gp, __global_pointer$
-.option pop
+ load_global_pointer
/*
* Disable FPU & VECTOR to detect illegal usage of
@@ -282,12 +275,12 @@ pmp_done:
/* Clear BSS for flat non-ELF images */
la a3, __bss_start
la a4, __bss_stop
- ble a4, a3, clear_bss_done
-clear_bss:
+ ble a4, a3, .Lclear_bss_done
+.Lclear_bss:
REG_S zero, (a3)
add a3, a3, RISCV_SZPTR
- blt a3, a4, clear_bss
-clear_bss_done:
+ blt a3, a4, .Lclear_bss
+.Lclear_bss_done:
#endif
la a2, boot_cpu_hartid
XIP_FIXUP_OFFSET a2
@@ -298,6 +291,7 @@ clear_bss_done:
la sp, init_thread_union + THREAD_SIZE
XIP_FIXUP_OFFSET sp
addi sp, sp, -PT_SIZE_ON_STACK
+ scs_load_init_stack
#ifdef CONFIG_BUILTIN_DTB
la a0, __dtb_start
XIP_FIXUP_OFFSET a0
@@ -311,11 +305,12 @@ clear_bss_done:
call relocate_enable_mmu
#endif /* CONFIG_MMU */
- call setup_trap_vector
+ call .Lsetup_trap_vector
/* Restore C environment */
la tp, init_task
la sp, init_thread_union + THREAD_SIZE
addi sp, sp, -PT_SIZE_ON_STACK
+ scs_load_current
#ifdef CONFIG_KASAN
call kasan_early_init
@@ -353,10 +348,10 @@ clear_bss_done:
tail .Lsecondary_start_common
#endif /* CONFIG_RISCV_BOOT_SPINWAIT */
-END(_start_kernel)
+SYM_CODE_END(_start_kernel)
#ifdef CONFIG_RISCV_M_MODE
-ENTRY(reset_regs)
+SYM_CODE_START_LOCAL(reset_regs)
li sp, 0
li gp, 0
li tp, 0
@@ -454,5 +449,5 @@ ENTRY(reset_regs)
.Lreset_regs_done_vector:
#endif /* CONFIG_RISCV_ISA_V */
ret
-END(reset_regs)
+SYM_CODE_END(reset_regs)
#endif /* CONFIG_RISCV_M_MODE */
diff --git a/arch/riscv/kernel/hibernate-asm.S b/arch/riscv/kernel/hibernate-asm.S
index d698dd7df637..d040dcf4add4 100644
--- a/arch/riscv/kernel/hibernate-asm.S
+++ b/arch/riscv/kernel/hibernate-asm.S
@@ -21,7 +21,7 @@
*
* Always returns 0
*/
-ENTRY(__hibernate_cpu_resume)
+SYM_FUNC_START(__hibernate_cpu_resume)
/* switch to hibernated image's page table. */
csrw CSR_SATP, s0
sfence.vma
@@ -34,7 +34,7 @@ ENTRY(__hibernate_cpu_resume)
mv a0, zero
ret
-END(__hibernate_cpu_resume)
+SYM_FUNC_END(__hibernate_cpu_resume)
/*
* Prepare to restore the image.
@@ -42,7 +42,7 @@ END(__hibernate_cpu_resume)
* a1: satp of temporary page tables.
* a2: cpu_resume.
*/
-ENTRY(hibernate_restore_image)
+SYM_FUNC_START(hibernate_restore_image)
mv s0, a0
mv s1, a1
mv s2, a2
@@ -50,7 +50,7 @@ ENTRY(hibernate_restore_image)
REG_L a1, relocated_restore_code
jr a1
-END(hibernate_restore_image)
+SYM_FUNC_END(hibernate_restore_image)
/*
* The below code will be executed from a 'safe' page.
@@ -58,7 +58,7 @@ END(hibernate_restore_image)
* back to the original memory location. Finally, it jumps to __hibernate_cpu_resume()
* to restore the CPU context.
*/
-ENTRY(hibernate_core_restore_code)
+SYM_FUNC_START(hibernate_core_restore_code)
/* switch to temp page table. */
csrw satp, s1
sfence.vma
@@ -73,4 +73,4 @@ ENTRY(hibernate_core_restore_code)
bnez s4, .Lcopy
jr s2
-END(hibernate_core_restore_code)
+SYM_FUNC_END(hibernate_core_restore_code)
diff --git a/arch/riscv/kernel/image-vars.h b/arch/riscv/kernel/image-vars.h
index ea1a10355ce9..3df30dd1c458 100644
--- a/arch/riscv/kernel/image-vars.h
+++ b/arch/riscv/kernel/image-vars.h
@@ -28,7 +28,9 @@ __efistub__start_kernel = _start_kernel;
__efistub__end = _end;
__efistub__edata = _edata;
__efistub___init_text_end = __init_text_end;
+#if defined(CONFIG_EFI_EARLYCON) || defined(CONFIG_SYSFB)
__efistub_screen_info = screen_info;
+#endif
#endif
diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c
index a8efa053c4a5..9ceda02507ca 100644
--- a/arch/riscv/kernel/irq.c
+++ b/arch/riscv/kernel/irq.c
@@ -9,6 +9,7 @@
#include <linux/irqchip.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
+#include <linux/scs.h>
#include <linux/seq_file.h>
#include <asm/sbi.h>
#include <asm/smp.h>
@@ -34,6 +35,24 @@ EXPORT_SYMBOL_GPL(riscv_get_intc_hwnode);
#ifdef CONFIG_IRQ_STACKS
#include <asm/irq_stack.h>
+DECLARE_PER_CPU(ulong *, irq_shadow_call_stack_ptr);
+
+#ifdef CONFIG_SHADOW_CALL_STACK
+DEFINE_PER_CPU(ulong *, irq_shadow_call_stack_ptr);
+#endif
+
+static void init_irq_scs(void)
+{
+ int cpu;
+
+ if (!scs_is_enabled())
+ return;
+
+ for_each_possible_cpu(cpu)
+ per_cpu(irq_shadow_call_stack_ptr, cpu) =
+ scs_alloc(cpu_to_node(cpu));
+}
+
DEFINE_PER_CPU(ulong *, irq_stack_ptr);
#ifdef CONFIG_VMAP_STACK
@@ -60,41 +79,23 @@ static void init_irq_stacks(void)
}
#endif /* CONFIG_VMAP_STACK */
-#ifdef CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK
+#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
+static void ___do_softirq(struct pt_regs *regs)
+{
+ __do_softirq();
+}
+
void do_softirq_own_stack(void)
{
-#ifdef CONFIG_IRQ_STACKS
- if (on_thread_stack()) {
- ulong *sp = per_cpu(irq_stack_ptr, smp_processor_id())
- + IRQ_STACK_SIZE/sizeof(ulong);
- __asm__ __volatile(
- "addi sp, sp, -"RISCV_SZPTR "\n"
- REG_S" ra, (sp) \n"
- "addi sp, sp, -"RISCV_SZPTR "\n"
- REG_S" s0, (sp) \n"
- "addi s0, sp, 2*"RISCV_SZPTR "\n"
- "move sp, %[sp] \n"
- "call __do_softirq \n"
- "addi sp, s0, -2*"RISCV_SZPTR"\n"
- REG_L" s0, (sp) \n"
- "addi sp, sp, "RISCV_SZPTR "\n"
- REG_L" ra, (sp) \n"
- "addi sp, sp, "RISCV_SZPTR "\n"
- :
- : [sp] "r" (sp)
- : "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
- "t0", "t1", "t2", "t3", "t4", "t5", "t6",
-#ifndef CONFIG_FRAME_POINTER
- "s0",
-#endif
- "memory");
- } else
-#endif
+ if (on_thread_stack())
+ call_on_irq_stack(NULL, ___do_softirq);
+ else
__do_softirq();
}
-#endif /* CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK */
+#endif /* CONFIG_SOFTIRQ_ON_OWN_STACK */
#else
+static void init_irq_scs(void) {}
static void init_irq_stacks(void) {}
#endif /* CONFIG_IRQ_STACKS */
@@ -106,6 +107,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
void __init init_IRQ(void)
{
+ init_irq_scs();
init_irq_stacks();
irqchip_init();
if (!handle_arch_irq)
diff --git a/arch/riscv/kernel/kexec_relocate.S b/arch/riscv/kernel/kexec_relocate.S
index 059c5e216ae7..de0a4b35d01e 100644
--- a/arch/riscv/kernel/kexec_relocate.S
+++ b/arch/riscv/kernel/kexec_relocate.S
@@ -17,27 +17,17 @@ SYM_CODE_START(riscv_kexec_relocate)
* s1: (const) Phys address to jump to after relocation
* s2: (const) Phys address of the FDT image
* s3: (const) The hartid of the current hart
- * s4: Pointer to the destination address for the relocation
- * s5: (const) Number of words per page
- * s6: (const) 1, used for subtraction
- * s7: (const) kernel_map.va_pa_offset, used when switching MMU off
- * s8: (const) Physical address of the main loop
- * s9: (debug) indirection page counter
- * s10: (debug) entry counter
- * s11: (debug) copied words counter
+ * s4: (const) kernel_map.va_pa_offset, used when switching MMU off
+ * s5: Pointer to the destination address for the relocation
+ * s6: (const) Physical address of the main loop
*/
mv s0, a0
mv s1, a1
mv s2, a2
mv s3, a3
- mv s4, zero
- li s5, (PAGE_SIZE / RISCV_SZPTR)
- li s6, 1
- mv s7, a4
- mv s8, zero
- mv s9, zero
- mv s10, zero
- mv s11, zero
+ mv s4, a4
+ mv s5, zero
+ mv s6, zero
/* Disable / cleanup interrupts */
csrw CSR_SIE, zero
@@ -52,21 +42,27 @@ SYM_CODE_START(riscv_kexec_relocate)
* the start of the loop below so that we jump there in
* any case.
*/
- la s8, 1f
- sub s8, s8, s7
- csrw CSR_STVEC, s8
+ la s6, 1f
+ sub s6, s6, s4
+ csrw CSR_STVEC, s6
+
+ /*
+ * With C-extension, here we get 42 Bytes and the next
+ * .align directive would pad zeros here up to 44 Bytes.
+ * So manually put a nop here to avoid zeros padding.
+ */
+ nop
/* Process entries in a loop */
.align 2
1:
- addi s10, s10, 1
REG_L t0, 0(s0) /* t0 = *image->entry */
addi s0, s0, RISCV_SZPTR /* image->entry++ */
/* IND_DESTINATION entry ? -> save destination address */
andi t1, t0, 0x1
beqz t1, 2f
- andi s4, t0, ~0x1
+ andi s5, t0, ~0x1
j 1b
2:
@@ -74,9 +70,8 @@ SYM_CODE_START(riscv_kexec_relocate)
andi t1, t0, 0x2
beqz t1, 2f
andi s0, t0, ~0x2
- addi s9, s9, 1
csrw CSR_SATP, zero
- jalr zero, s8, 0
+ jr s6
2:
/* IND_DONE entry ? -> jump to done label */
@@ -92,14 +87,13 @@ SYM_CODE_START(riscv_kexec_relocate)
andi t1, t0, 0x8
beqz t1, 1b /* Unknown entry type, ignore it */
andi t0, t0, ~0x8
- mv t3, s5 /* i = num words per page */
+ li t3, (PAGE_SIZE / RISCV_SZPTR) /* i = num words per page */
3: /* copy loop */
REG_L t1, (t0) /* t1 = *src_ptr */
- REG_S t1, (s4) /* *dst_ptr = *src_ptr */
+ REG_S t1, (s5) /* *dst_ptr = *src_ptr */
addi t0, t0, RISCV_SZPTR /* stc_ptr++ */
- addi s4, s4, RISCV_SZPTR /* dst_ptr++ */
- sub t3, t3, s6 /* i-- */
- addi s11, s11, 1 /* c++ */
+ addi s5, s5, RISCV_SZPTR /* dst_ptr++ */
+ addi t3, t3, -0x1 /* i-- */
beqz t3, 1b /* copy done ? */
j 3b
@@ -146,7 +140,7 @@ SYM_CODE_START(riscv_kexec_relocate)
*/
fence.i
- jalr zero, a2, 0
+ jr a2
SYM_CODE_END(riscv_kexec_relocate)
riscv_kexec_relocate_end:
diff --git a/arch/riscv/kernel/mcount-dyn.S b/arch/riscv/kernel/mcount-dyn.S
index 669b8697aa38..58dd96a2a153 100644
--- a/arch/riscv/kernel/mcount-dyn.S
+++ b/arch/riscv/kernel/mcount-dyn.S
@@ -82,7 +82,7 @@
.endm
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
-ENTRY(ftrace_caller)
+SYM_FUNC_START(ftrace_caller)
SAVE_ABI
addi a0, t0, -FENTRY_RA_OFFSET
@@ -91,8 +91,7 @@ ENTRY(ftrace_caller)
mv a1, ra
mv a3, sp
-ftrace_call:
- .global ftrace_call
+SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
call ftrace_stub
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -102,16 +101,15 @@ ftrace_call:
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
mv a2, s0
#endif
-ftrace_graph_call:
- .global ftrace_graph_call
+SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)
call ftrace_stub
#endif
RESTORE_ABI
jr t0
-ENDPROC(ftrace_caller)
+SYM_FUNC_END(ftrace_caller)
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
-ENTRY(ftrace_regs_caller)
+SYM_FUNC_START(ftrace_regs_caller)
SAVE_ALL
addi a0, t0, -FENTRY_RA_OFFSET
@@ -120,8 +118,7 @@ ENTRY(ftrace_regs_caller)
mv a1, ra
mv a3, sp
-ftrace_regs_call:
- .global ftrace_regs_call
+SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL)
call ftrace_stub
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -131,12 +128,11 @@ ftrace_regs_call:
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
mv a2, s0
#endif
-ftrace_graph_regs_call:
- .global ftrace_graph_regs_call
+SYM_INNER_LABEL(ftrace_graph_regs_call, SYM_L_GLOBAL)
call ftrace_stub
#endif
RESTORE_ALL
jr t0
-ENDPROC(ftrace_regs_caller)
+SYM_FUNC_END(ftrace_regs_caller)
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S
index 8818a8fa9ff3..b4dd9ed6849e 100644
--- a/arch/riscv/kernel/mcount.S
+++ b/arch/riscv/kernel/mcount.S
@@ -61,7 +61,7 @@ SYM_TYPED_FUNC_START(ftrace_stub_graph)
ret
SYM_FUNC_END(ftrace_stub_graph)
-ENTRY(return_to_handler)
+SYM_FUNC_START(return_to_handler)
/*
* On implementing the frame point test, the ideal way is to compare the
* s0 (frame pointer, if enabled) on entry and the sp (stack pointer) on return.
@@ -76,25 +76,25 @@ ENTRY(return_to_handler)
mv a2, a0
RESTORE_RET_ABI_STATE
jalr a2
-ENDPROC(return_to_handler)
+SYM_FUNC_END(return_to_handler)
#endif
#ifndef CONFIG_DYNAMIC_FTRACE
-ENTRY(MCOUNT_NAME)
+SYM_FUNC_START(MCOUNT_NAME)
la t4, ftrace_stub
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
la t0, ftrace_graph_return
REG_L t1, 0(t0)
- bne t1, t4, do_ftrace_graph_caller
+ bne t1, t4, .Ldo_ftrace_graph_caller
la t3, ftrace_graph_entry
REG_L t2, 0(t3)
la t6, ftrace_graph_entry_stub
- bne t2, t6, do_ftrace_graph_caller
+ bne t2, t6, .Ldo_ftrace_graph_caller
#endif
la t3, ftrace_trace_function
REG_L t5, 0(t3)
- bne t5, t4, do_trace
+ bne t5, t4, .Ldo_trace
ret
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -102,7 +102,7 @@ ENTRY(MCOUNT_NAME)
* A pseudo representation for the function graph tracer:
* prepare_to_return(&ra_to_caller_of_caller, ra_to_caller)
*/
-do_ftrace_graph_caller:
+.Ldo_ftrace_graph_caller:
addi a0, s0, -SZREG
mv a1, ra
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
@@ -118,7 +118,7 @@ do_ftrace_graph_caller:
* A pseudo representation for the function tracer:
* (*ftrace_trace_function)(ra_to_caller, ra_to_caller_of_caller)
*/
-do_trace:
+.Ldo_trace:
REG_L a1, -SZREG(s0)
mv a0, ra
@@ -126,6 +126,6 @@ do_trace:
jalr t5
RESTORE_ABI_STATE
ret
-ENDPROC(MCOUNT_NAME)
+SYM_FUNC_END(MCOUNT_NAME)
#endif
EXPORT_SYMBOL(MCOUNT_NAME)
diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
index 7c651d55fcbd..aac019ed63b1 100644
--- a/arch/riscv/kernel/module.c
+++ b/arch/riscv/kernel/module.c
@@ -7,6 +7,9 @@
#include <linux/elf.h>
#include <linux/err.h>
#include <linux/errno.h>
+#include <linux/hashtable.h>
+#include <linux/kernel.h>
+#include <linux/log2.h>
#include <linux/moduleloader.h>
#include <linux/vmalloc.h>
#include <linux/sizes.h>
@@ -14,6 +17,29 @@
#include <asm/alternative.h>
#include <asm/sections.h>
+struct used_bucket {
+ struct list_head head;
+ struct hlist_head *bucket;
+};
+
+struct relocation_head {
+ struct hlist_node node;
+ struct list_head *rel_entry;
+ void *location;
+};
+
+struct relocation_entry {
+ struct list_head head;
+ Elf_Addr value;
+ unsigned int type;
+};
+
+struct relocation_handlers {
+ int (*reloc_handler)(struct module *me, void *location, Elf_Addr v);
+ int (*accumulate_handler)(struct module *me, void *location,
+ long buffer);
+};
+
/*
* The auipc+jalr instruction pair can reach any PC-relative offset
* in the range [-2^31 - 2^11, 2^31 - 2^11)
@@ -27,68 +53,90 @@ static bool riscv_insn_valid_32bit_offset(ptrdiff_t val)
#endif
}
-static int apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v)
+static int riscv_insn_rmw(void *location, u32 keep, u32 set)
+{
+ __le16 *parcel = location;
+ u32 insn = (u32)le16_to_cpu(parcel[0]) | (u32)le16_to_cpu(parcel[1]) << 16;
+
+ insn &= keep;
+ insn |= set;
+
+ parcel[0] = cpu_to_le16(insn);
+ parcel[1] = cpu_to_le16(insn >> 16);
+ return 0;
+}
+
+static int riscv_insn_rvc_rmw(void *location, u16 keep, u16 set)
+{
+ __le16 *parcel = location;
+ u16 insn = le16_to_cpu(*parcel);
+
+ insn &= keep;
+ insn |= set;
+
+ *parcel = cpu_to_le16(insn);
+ return 0;
+}
+
+static int apply_r_riscv_32_rela(struct module *me, void *location, Elf_Addr v)
{
if (v != (u32)v) {
pr_err("%s: value %016llx out of range for 32-bit field\n",
me->name, (long long)v);
return -EINVAL;
}
- *location = v;
+ *(u32 *)location = v;
return 0;
}
-static int apply_r_riscv_64_rela(struct module *me, u32 *location, Elf_Addr v)
+static int apply_r_riscv_64_rela(struct module *me, void *location, Elf_Addr v)
{
*(u64 *)location = v;
return 0;
}
-static int apply_r_riscv_branch_rela(struct module *me, u32 *location,
+static int apply_r_riscv_branch_rela(struct module *me, void *location,
Elf_Addr v)
{
- ptrdiff_t offset = (void *)v - (void *)location;
+ ptrdiff_t offset = (void *)v - location;
u32 imm12 = (offset & 0x1000) << (31 - 12);
u32 imm11 = (offset & 0x800) >> (11 - 7);
u32 imm10_5 = (offset & 0x7e0) << (30 - 10);
u32 imm4_1 = (offset & 0x1e) << (11 - 4);
- *location = (*location & 0x1fff07f) | imm12 | imm11 | imm10_5 | imm4_1;
- return 0;
+ return riscv_insn_rmw(location, 0x1fff07f, imm12 | imm11 | imm10_5 | imm4_1);
}
-static int apply_r_riscv_jal_rela(struct module *me, u32 *location,
+static int apply_r_riscv_jal_rela(struct module *me, void *location,
Elf_Addr v)
{
- ptrdiff_t offset = (void *)v - (void *)location;
+ ptrdiff_t offset = (void *)v - location;
u32 imm20 = (offset & 0x100000) << (31 - 20);
u32 imm19_12 = (offset & 0xff000);
u32 imm11 = (offset & 0x800) << (20 - 11);
u32 imm10_1 = (offset & 0x7fe) << (30 - 10);
- *location = (*location & 0xfff) | imm20 | imm19_12 | imm11 | imm10_1;
- return 0;
+ return riscv_insn_rmw(location, 0xfff, imm20 | imm19_12 | imm11 | imm10_1);
}
-static int apply_r_riscv_rvc_branch_rela(struct module *me, u32 *location,
+static int apply_r_riscv_rvc_branch_rela(struct module *me, void *location,
Elf_Addr v)
{
- ptrdiff_t offset = (void *)v - (void *)location;
+ ptrdiff_t offset = (void *)v - location;
u16 imm8 = (offset & 0x100) << (12 - 8);
u16 imm7_6 = (offset & 0xc0) >> (6 - 5);
u16 imm5 = (offset & 0x20) >> (5 - 2);
u16 imm4_3 = (offset & 0x18) << (12 - 5);
u16 imm2_1 = (offset & 0x6) << (12 - 10);
- *(u16 *)location = (*(u16 *)location & 0xe383) |
- imm8 | imm7_6 | imm5 | imm4_3 | imm2_1;
- return 0;
+ return riscv_insn_rvc_rmw(location, 0xe383,
+ imm8 | imm7_6 | imm5 | imm4_3 | imm2_1);
}
-static int apply_r_riscv_rvc_jump_rela(struct module *me, u32 *location,
+static int apply_r_riscv_rvc_jump_rela(struct module *me, void *location,
Elf_Addr v)
{
- ptrdiff_t offset = (void *)v - (void *)location;
+ ptrdiff_t offset = (void *)v - location;
u16 imm11 = (offset & 0x800) << (12 - 11);
u16 imm10 = (offset & 0x400) >> (10 - 8);
u16 imm9_8 = (offset & 0x300) << (12 - 11);
@@ -98,16 +146,14 @@ static int apply_r_riscv_rvc_jump_rela(struct module *me, u32 *location,
u16 imm4 = (offset & 0x10) << (12 - 5);
u16 imm3_1 = (offset & 0xe) << (12 - 10);
- *(u16 *)location = (*(u16 *)location & 0xe003) |
- imm11 | imm10 | imm9_8 | imm7 | imm6 | imm5 | imm4 | imm3_1;
- return 0;
+ return riscv_insn_rvc_rmw(location, 0xe003,
+ imm11 | imm10 | imm9_8 | imm7 | imm6 | imm5 | imm4 | imm3_1);
}
-static int apply_r_riscv_pcrel_hi20_rela(struct module *me, u32 *location,
+static int apply_r_riscv_pcrel_hi20_rela(struct module *me, void *location,
Elf_Addr v)
{
- ptrdiff_t offset = (void *)v - (void *)location;
- s32 hi20;
+ ptrdiff_t offset = (void *)v - location;
if (!riscv_insn_valid_32bit_offset(offset)) {
pr_err(
@@ -116,23 +162,20 @@ static int apply_r_riscv_pcrel_hi20_rela(struct module *me, u32 *location,
return -EINVAL;
}
- hi20 = (offset + 0x800) & 0xfffff000;
- *location = (*location & 0xfff) | hi20;
- return 0;
+ return riscv_insn_rmw(location, 0xfff, (offset + 0x800) & 0xfffff000);
}
-static int apply_r_riscv_pcrel_lo12_i_rela(struct module *me, u32 *location,
+static int apply_r_riscv_pcrel_lo12_i_rela(struct module *me, void *location,
Elf_Addr v)
{
/*
* v is the lo12 value to fill. It is calculated before calling this
* handler.
*/
- *location = (*location & 0xfffff) | ((v & 0xfff) << 20);
- return 0;
+ return riscv_insn_rmw(location, 0xfffff, (v & 0xfff) << 20);
}
-static int apply_r_riscv_pcrel_lo12_s_rela(struct module *me, u32 *location,
+static int apply_r_riscv_pcrel_lo12_s_rela(struct module *me, void *location,
Elf_Addr v)
{
/*
@@ -142,15 +185,12 @@ static int apply_r_riscv_pcrel_lo12_s_rela(struct module *me, u32 *location,
u32 imm11_5 = (v & 0xfe0) << (31 - 11);
u32 imm4_0 = (v & 0x1f) << (11 - 4);
- *location = (*location & 0x1fff07f) | imm11_5 | imm4_0;
- return 0;
+ return riscv_insn_rmw(location, 0x1fff07f, imm11_5 | imm4_0);
}
-static int apply_r_riscv_hi20_rela(struct module *me, u32 *location,
+static int apply_r_riscv_hi20_rela(struct module *me, void *location,
Elf_Addr v)
{
- s32 hi20;
-
if (IS_ENABLED(CONFIG_CMODEL_MEDLOW)) {
pr_err(
"%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
@@ -158,22 +198,20 @@ static int apply_r_riscv_hi20_rela(struct module *me, u32 *location,
return -EINVAL;
}
- hi20 = ((s32)v + 0x800) & 0xfffff000;
- *location = (*location & 0xfff) | hi20;
- return 0;
+ return riscv_insn_rmw(location, 0xfff, ((s32)v + 0x800) & 0xfffff000);
}
-static int apply_r_riscv_lo12_i_rela(struct module *me, u32 *location,
+static int apply_r_riscv_lo12_i_rela(struct module *me, void *location,
Elf_Addr v)
{
/* Skip medlow checking because of filtering by HI20 already */
s32 hi20 = ((s32)v + 0x800) & 0xfffff000;
s32 lo12 = ((s32)v - hi20);
- *location = (*location & 0xfffff) | ((lo12 & 0xfff) << 20);
- return 0;
+
+ return riscv_insn_rmw(location, 0xfffff, (lo12 & 0xfff) << 20);
}
-static int apply_r_riscv_lo12_s_rela(struct module *me, u32 *location,
+static int apply_r_riscv_lo12_s_rela(struct module *me, void *location,
Elf_Addr v)
{
/* Skip medlow checking because of filtering by HI20 already */
@@ -181,20 +219,18 @@ static int apply_r_riscv_lo12_s_rela(struct module *me, u32 *location,
s32 lo12 = ((s32)v - hi20);
u32 imm11_5 = (lo12 & 0xfe0) << (31 - 11);
u32 imm4_0 = (lo12 & 0x1f) << (11 - 4);
- *location = (*location & 0x1fff07f) | imm11_5 | imm4_0;
- return 0;
+
+ return riscv_insn_rmw(location, 0x1fff07f, imm11_5 | imm4_0);
}
-static int apply_r_riscv_got_hi20_rela(struct module *me, u32 *location,
+static int apply_r_riscv_got_hi20_rela(struct module *me, void *location,
Elf_Addr v)
{
- ptrdiff_t offset = (void *)v - (void *)location;
- s32 hi20;
+ ptrdiff_t offset = (void *)v - location;
/* Always emit the got entry */
if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) {
- offset = module_emit_got_entry(me, v);
- offset = (void *)offset - (void *)location;
+ offset = (void *)module_emit_got_entry(me, v) - location;
} else {
pr_err(
"%s: can not generate the GOT entry for symbol = %016llx from PC = %p\n",
@@ -202,22 +238,19 @@ static int apply_r_riscv_got_hi20_rela(struct module *me, u32 *location,
return -EINVAL;
}
- hi20 = (offset + 0x800) & 0xfffff000;
- *location = (*location & 0xfff) | hi20;
- return 0;
+ return riscv_insn_rmw(location, 0xfff, (offset + 0x800) & 0xfffff000);
}
-static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location,
+static int apply_r_riscv_call_plt_rela(struct module *me, void *location,
Elf_Addr v)
{
- ptrdiff_t offset = (void *)v - (void *)location;
+ ptrdiff_t offset = (void *)v - location;
u32 hi20, lo12;
if (!riscv_insn_valid_32bit_offset(offset)) {
/* Only emit the plt entry if offset over 32-bit range */
if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) {
- offset = module_emit_plt_entry(me, v);
- offset = (void *)offset - (void *)location;
+ offset = (void *)module_emit_plt_entry(me, v) - location;
} else {
pr_err(
"%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
@@ -228,15 +261,14 @@ static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location,
hi20 = (offset + 0x800) & 0xfffff000;
lo12 = (offset - hi20) & 0xfff;
- *location = (*location & 0xfff) | hi20;
- *(location + 1) = (*(location + 1) & 0xfffff) | (lo12 << 20);
- return 0;
+ riscv_insn_rmw(location, 0xfff, hi20);
+ return riscv_insn_rmw(location + 4, 0xfffff, lo12 << 20);
}
-static int apply_r_riscv_call_rela(struct module *me, u32 *location,
+static int apply_r_riscv_call_rela(struct module *me, void *location,
Elf_Addr v)
{
- ptrdiff_t offset = (void *)v - (void *)location;
+ ptrdiff_t offset = (void *)v - location;
u32 hi20, lo12;
if (!riscv_insn_valid_32bit_offset(offset)) {
@@ -248,18 +280,17 @@ static int apply_r_riscv_call_rela(struct module *me, u32 *location,
hi20 = (offset + 0x800) & 0xfffff000;
lo12 = (offset - hi20) & 0xfff;
- *location = (*location & 0xfff) | hi20;
- *(location + 1) = (*(location + 1) & 0xfffff) | (lo12 << 20);
- return 0;
+ riscv_insn_rmw(location, 0xfff, hi20);
+ return riscv_insn_rmw(location + 4, 0xfffff, lo12 << 20);
}
-static int apply_r_riscv_relax_rela(struct module *me, u32 *location,
+static int apply_r_riscv_relax_rela(struct module *me, void *location,
Elf_Addr v)
{
return 0;
}
-static int apply_r_riscv_align_rela(struct module *me, u32 *location,
+static int apply_r_riscv_align_rela(struct module *me, void *location,
Elf_Addr v)
{
pr_err(
@@ -268,91 +299,505 @@ static int apply_r_riscv_align_rela(struct module *me, u32 *location,
return -EINVAL;
}
-static int apply_r_riscv_add16_rela(struct module *me, u32 *location,
+static int apply_r_riscv_add8_rela(struct module *me, void *location, Elf_Addr v)
+{
+ *(u8 *)location += (u8)v;
+ return 0;
+}
+
+static int apply_r_riscv_add16_rela(struct module *me, void *location,
Elf_Addr v)
{
*(u16 *)location += (u16)v;
return 0;
}
-static int apply_r_riscv_add32_rela(struct module *me, u32 *location,
+static int apply_r_riscv_add32_rela(struct module *me, void *location,
Elf_Addr v)
{
*(u32 *)location += (u32)v;
return 0;
}
-static int apply_r_riscv_add64_rela(struct module *me, u32 *location,
+static int apply_r_riscv_add64_rela(struct module *me, void *location,
Elf_Addr v)
{
*(u64 *)location += (u64)v;
return 0;
}
-static int apply_r_riscv_sub16_rela(struct module *me, u32 *location,
+static int apply_r_riscv_sub8_rela(struct module *me, void *location, Elf_Addr v)
+{
+ *(u8 *)location -= (u8)v;
+ return 0;
+}
+
+static int apply_r_riscv_sub16_rela(struct module *me, void *location,
Elf_Addr v)
{
*(u16 *)location -= (u16)v;
return 0;
}
-static int apply_r_riscv_sub32_rela(struct module *me, u32 *location,
+static int apply_r_riscv_sub32_rela(struct module *me, void *location,
Elf_Addr v)
{
*(u32 *)location -= (u32)v;
return 0;
}
-static int apply_r_riscv_sub64_rela(struct module *me, u32 *location,
+static int apply_r_riscv_sub64_rela(struct module *me, void *location,
Elf_Addr v)
{
*(u64 *)location -= (u64)v;
return 0;
}
-static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
- Elf_Addr v) = {
- [R_RISCV_32] = apply_r_riscv_32_rela,
- [R_RISCV_64] = apply_r_riscv_64_rela,
- [R_RISCV_BRANCH] = apply_r_riscv_branch_rela,
- [R_RISCV_JAL] = apply_r_riscv_jal_rela,
- [R_RISCV_RVC_BRANCH] = apply_r_riscv_rvc_branch_rela,
- [R_RISCV_RVC_JUMP] = apply_r_riscv_rvc_jump_rela,
- [R_RISCV_PCREL_HI20] = apply_r_riscv_pcrel_hi20_rela,
- [R_RISCV_PCREL_LO12_I] = apply_r_riscv_pcrel_lo12_i_rela,
- [R_RISCV_PCREL_LO12_S] = apply_r_riscv_pcrel_lo12_s_rela,
- [R_RISCV_HI20] = apply_r_riscv_hi20_rela,
- [R_RISCV_LO12_I] = apply_r_riscv_lo12_i_rela,
- [R_RISCV_LO12_S] = apply_r_riscv_lo12_s_rela,
- [R_RISCV_GOT_HI20] = apply_r_riscv_got_hi20_rela,
- [R_RISCV_CALL_PLT] = apply_r_riscv_call_plt_rela,
- [R_RISCV_CALL] = apply_r_riscv_call_rela,
- [R_RISCV_RELAX] = apply_r_riscv_relax_rela,
- [R_RISCV_ALIGN] = apply_r_riscv_align_rela,
- [R_RISCV_ADD16] = apply_r_riscv_add16_rela,
- [R_RISCV_ADD32] = apply_r_riscv_add32_rela,
- [R_RISCV_ADD64] = apply_r_riscv_add64_rela,
- [R_RISCV_SUB16] = apply_r_riscv_sub16_rela,
- [R_RISCV_SUB32] = apply_r_riscv_sub32_rela,
- [R_RISCV_SUB64] = apply_r_riscv_sub64_rela,
+static int dynamic_linking_not_supported(struct module *me, void *location,
+ Elf_Addr v)
+{
+ pr_err("%s: Dynamic linking not supported in kernel modules PC = %p\n",
+ me->name, location);
+ return -EINVAL;
+}
+
+static int tls_not_supported(struct module *me, void *location, Elf_Addr v)
+{
+ pr_err("%s: Thread local storage not supported in kernel modules PC = %p\n",
+ me->name, location);
+ return -EINVAL;
+}
+
+static int apply_r_riscv_sub6_rela(struct module *me, void *location, Elf_Addr v)
+{
+ u8 *byte = location;
+ u8 value = v;
+
+ *byte = (*byte - (value & 0x3f)) & 0x3f;
+ return 0;
+}
+
+static int apply_r_riscv_set6_rela(struct module *me, void *location, Elf_Addr v)
+{
+ u8 *byte = location;
+ u8 value = v;
+
+ *byte = (*byte & 0xc0) | (value & 0x3f);
+ return 0;
+}
+
+static int apply_r_riscv_set8_rela(struct module *me, void *location, Elf_Addr v)
+{
+ *(u8 *)location = (u8)v;
+ return 0;
+}
+
+static int apply_r_riscv_set16_rela(struct module *me, void *location,
+ Elf_Addr v)
+{
+ *(u16 *)location = (u16)v;
+ return 0;
+}
+
+static int apply_r_riscv_set32_rela(struct module *me, void *location,
+ Elf_Addr v)
+{
+ *(u32 *)location = (u32)v;
+ return 0;
+}
+
+static int apply_r_riscv_32_pcrel_rela(struct module *me, void *location,
+ Elf_Addr v)
+{
+ *(u32 *)location = v - (uintptr_t)location;
+ return 0;
+}
+
+static int apply_r_riscv_plt32_rela(struct module *me, void *location,
+ Elf_Addr v)
+{
+ ptrdiff_t offset = (void *)v - location;
+
+ if (!riscv_insn_valid_32bit_offset(offset)) {
+ /* Only emit the plt entry if offset over 32-bit range */
+ if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) {
+ offset = (void *)module_emit_plt_entry(me, v) - location;
+ } else {
+ pr_err("%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
+ me->name, (long long)v, location);
+ return -EINVAL;
+ }
+ }
+
+ *(u32 *)location = (u32)offset;
+ return 0;
+}
+
+static int apply_r_riscv_set_uleb128(struct module *me, void *location, Elf_Addr v)
+{
+ *(long *)location = v;
+ return 0;
+}
+
+static int apply_r_riscv_sub_uleb128(struct module *me, void *location, Elf_Addr v)
+{
+ *(long *)location -= v;
+ return 0;
+}
+
+static int apply_6_bit_accumulation(struct module *me, void *location, long buffer)
+{
+ u8 *byte = location;
+ u8 value = buffer;
+
+ if (buffer > 0x3f) {
+ pr_err("%s: value %ld out of range for 6-bit relocation.\n",
+ me->name, buffer);
+ return -EINVAL;
+ }
+
+ *byte = (*byte & 0xc0) | (value & 0x3f);
+ return 0;
+}
+
+static int apply_8_bit_accumulation(struct module *me, void *location, long buffer)
+{
+ if (buffer > U8_MAX) {
+ pr_err("%s: value %ld out of range for 8-bit relocation.\n",
+ me->name, buffer);
+ return -EINVAL;
+ }
+ *(u8 *)location = (u8)buffer;
+ return 0;
+}
+
+static int apply_16_bit_accumulation(struct module *me, void *location, long buffer)
+{
+ if (buffer > U16_MAX) {
+ pr_err("%s: value %ld out of range for 16-bit relocation.\n",
+ me->name, buffer);
+ return -EINVAL;
+ }
+ *(u16 *)location = (u16)buffer;
+ return 0;
+}
+
+static int apply_32_bit_accumulation(struct module *me, void *location, long buffer)
+{
+ if (buffer > U32_MAX) {
+ pr_err("%s: value %ld out of range for 32-bit relocation.\n",
+ me->name, buffer);
+ return -EINVAL;
+ }
+ *(u32 *)location = (u32)buffer;
+ return 0;
+}
+
+static int apply_64_bit_accumulation(struct module *me, void *location, long buffer)
+{
+ *(u64 *)location = (u64)buffer;
+ return 0;
+}
+
+static int apply_uleb128_accumulation(struct module *me, void *location, long buffer)
+{
+ /*
+ * ULEB128 is a variable length encoding. Encode the buffer into
+ * the ULEB128 data format.
+ */
+ u8 *p = location;
+
+ while (buffer != 0) {
+ u8 value = buffer & 0x7f;
+
+ buffer >>= 7;
+ value |= (!!buffer) << 7;
+
+ *p++ = value;
+ }
+ return 0;
+}
+
+/*
+ * Relocations defined in the riscv-elf-psabi-doc.
+ * This handles static linking only.
+ */
+static const struct relocation_handlers reloc_handlers[] = {
+ [R_RISCV_32] = { .reloc_handler = apply_r_riscv_32_rela },
+ [R_RISCV_64] = { .reloc_handler = apply_r_riscv_64_rela },
+ [R_RISCV_RELATIVE] = { .reloc_handler = dynamic_linking_not_supported },
+ [R_RISCV_COPY] = { .reloc_handler = dynamic_linking_not_supported },
+ [R_RISCV_JUMP_SLOT] = { .reloc_handler = dynamic_linking_not_supported },
+ [R_RISCV_TLS_DTPMOD32] = { .reloc_handler = dynamic_linking_not_supported },
+ [R_RISCV_TLS_DTPMOD64] = { .reloc_handler = dynamic_linking_not_supported },
+ [R_RISCV_TLS_DTPREL32] = { .reloc_handler = dynamic_linking_not_supported },
+ [R_RISCV_TLS_DTPREL64] = { .reloc_handler = dynamic_linking_not_supported },
+ [R_RISCV_TLS_TPREL32] = { .reloc_handler = dynamic_linking_not_supported },
+ [R_RISCV_TLS_TPREL64] = { .reloc_handler = dynamic_linking_not_supported },
+ /* 12-15 undefined */
+ [R_RISCV_BRANCH] = { .reloc_handler = apply_r_riscv_branch_rela },
+ [R_RISCV_JAL] = { .reloc_handler = apply_r_riscv_jal_rela },
+ [R_RISCV_CALL] = { .reloc_handler = apply_r_riscv_call_rela },
+ [R_RISCV_CALL_PLT] = { .reloc_handler = apply_r_riscv_call_plt_rela },
+ [R_RISCV_GOT_HI20] = { .reloc_handler = apply_r_riscv_got_hi20_rela },
+ [R_RISCV_TLS_GOT_HI20] = { .reloc_handler = tls_not_supported },
+ [R_RISCV_TLS_GD_HI20] = { .reloc_handler = tls_not_supported },
+ [R_RISCV_PCREL_HI20] = { .reloc_handler = apply_r_riscv_pcrel_hi20_rela },
+ [R_RISCV_PCREL_LO12_I] = { .reloc_handler = apply_r_riscv_pcrel_lo12_i_rela },
+ [R_RISCV_PCREL_LO12_S] = { .reloc_handler = apply_r_riscv_pcrel_lo12_s_rela },
+ [R_RISCV_HI20] = { .reloc_handler = apply_r_riscv_hi20_rela },
+ [R_RISCV_LO12_I] = { .reloc_handler = apply_r_riscv_lo12_i_rela },
+ [R_RISCV_LO12_S] = { .reloc_handler = apply_r_riscv_lo12_s_rela },
+ [R_RISCV_TPREL_HI20] = { .reloc_handler = tls_not_supported },
+ [R_RISCV_TPREL_LO12_I] = { .reloc_handler = tls_not_supported },
+ [R_RISCV_TPREL_LO12_S] = { .reloc_handler = tls_not_supported },
+ [R_RISCV_TPREL_ADD] = { .reloc_handler = tls_not_supported },
+ [R_RISCV_ADD8] = { .reloc_handler = apply_r_riscv_add8_rela,
+ .accumulate_handler = apply_8_bit_accumulation },
+ [R_RISCV_ADD16] = { .reloc_handler = apply_r_riscv_add16_rela,
+ .accumulate_handler = apply_16_bit_accumulation },
+ [R_RISCV_ADD32] = { .reloc_handler = apply_r_riscv_add32_rela,
+ .accumulate_handler = apply_32_bit_accumulation },
+ [R_RISCV_ADD64] = { .reloc_handler = apply_r_riscv_add64_rela,
+ .accumulate_handler = apply_64_bit_accumulation },
+ [R_RISCV_SUB8] = { .reloc_handler = apply_r_riscv_sub8_rela,
+ .accumulate_handler = apply_8_bit_accumulation },
+ [R_RISCV_SUB16] = { .reloc_handler = apply_r_riscv_sub16_rela,
+ .accumulate_handler = apply_16_bit_accumulation },
+ [R_RISCV_SUB32] = { .reloc_handler = apply_r_riscv_sub32_rela,
+ .accumulate_handler = apply_32_bit_accumulation },
+ [R_RISCV_SUB64] = { .reloc_handler = apply_r_riscv_sub64_rela,
+ .accumulate_handler = apply_64_bit_accumulation },
+ /* 41-42 reserved for future standard use */
+ [R_RISCV_ALIGN] = { .reloc_handler = apply_r_riscv_align_rela },
+ [R_RISCV_RVC_BRANCH] = { .reloc_handler = apply_r_riscv_rvc_branch_rela },
+ [R_RISCV_RVC_JUMP] = { .reloc_handler = apply_r_riscv_rvc_jump_rela },
+ /* 46-50 reserved for future standard use */
+ [R_RISCV_RELAX] = { .reloc_handler = apply_r_riscv_relax_rela },
+ [R_RISCV_SUB6] = { .reloc_handler = apply_r_riscv_sub6_rela,
+ .accumulate_handler = apply_6_bit_accumulation },
+ [R_RISCV_SET6] = { .reloc_handler = apply_r_riscv_set6_rela,
+ .accumulate_handler = apply_6_bit_accumulation },
+ [R_RISCV_SET8] = { .reloc_handler = apply_r_riscv_set8_rela,
+ .accumulate_handler = apply_8_bit_accumulation },
+ [R_RISCV_SET16] = { .reloc_handler = apply_r_riscv_set16_rela,
+ .accumulate_handler = apply_16_bit_accumulation },
+ [R_RISCV_SET32] = { .reloc_handler = apply_r_riscv_set32_rela,
+ .accumulate_handler = apply_32_bit_accumulation },
+ [R_RISCV_32_PCREL] = { .reloc_handler = apply_r_riscv_32_pcrel_rela },
+ [R_RISCV_IRELATIVE] = { .reloc_handler = dynamic_linking_not_supported },
+ [R_RISCV_PLT32] = { .reloc_handler = apply_r_riscv_plt32_rela },
+ [R_RISCV_SET_ULEB128] = { .reloc_handler = apply_r_riscv_set_uleb128,
+ .accumulate_handler = apply_uleb128_accumulation },
+ [R_RISCV_SUB_ULEB128] = { .reloc_handler = apply_r_riscv_sub_uleb128,
+ .accumulate_handler = apply_uleb128_accumulation },
+ /* 62-191 reserved for future standard use */
+ /* 192-255 nonstandard ABI extensions */
};
+static void
+process_accumulated_relocations(struct module *me,
+ struct hlist_head **relocation_hashtable,
+ struct list_head *used_buckets_list)
+{
+ /*
+ * Only ADD/SUB/SET/ULEB128 should end up here.
+ *
+ * Each bucket may have more than one relocation location. All
+ * relocations for a location are stored in a list in a bucket.
+ *
+ * Relocations are applied to a temp variable before being stored to the
+ * provided location to check for overflow. This also allows ULEB128 to
+ * properly decide how many entries are needed before storing to
+ * location. The final value is stored into location using the handler
+ * for the last relocation to an address.
+ *
+ * Three layers of indexing:
+ * - Each of the buckets in use
+ * - Groups of relocations in each bucket by location address
+ * - Each relocation entry for a location address
+ */
+ struct used_bucket *bucket_iter;
+ struct used_bucket *bucket_iter_tmp;
+ struct relocation_head *rel_head_iter;
+ struct hlist_node *rel_head_iter_tmp;
+ struct relocation_entry *rel_entry_iter;
+ struct relocation_entry *rel_entry_iter_tmp;
+ int curr_type;
+ void *location;
+ long buffer;
+
+ list_for_each_entry_safe(bucket_iter, bucket_iter_tmp,
+ used_buckets_list, head) {
+ hlist_for_each_entry_safe(rel_head_iter, rel_head_iter_tmp,
+ bucket_iter->bucket, node) {
+ buffer = 0;
+ location = rel_head_iter->location;
+ list_for_each_entry_safe(rel_entry_iter,
+ rel_entry_iter_tmp,
+ rel_head_iter->rel_entry,
+ head) {
+ curr_type = rel_entry_iter->type;
+ reloc_handlers[curr_type].reloc_handler(
+ me, &buffer, rel_entry_iter->value);
+ kfree(rel_entry_iter);
+ }
+ reloc_handlers[curr_type].accumulate_handler(
+ me, location, buffer);
+ kfree(rel_head_iter);
+ }
+ kfree(bucket_iter);
+ }
+
+ kfree(*relocation_hashtable);
+}
+
+static int add_relocation_to_accumulate(struct module *me, int type,
+ void *location,
+ unsigned int hashtable_bits, Elf_Addr v,
+ struct hlist_head *relocation_hashtable,
+ struct list_head *used_buckets_list)
+{
+ struct relocation_entry *entry;
+ struct relocation_head *rel_head;
+ struct hlist_head *current_head;
+ struct used_bucket *bucket;
+ unsigned long hash;
+
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+
+ if (!entry)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&entry->head);
+ entry->type = type;
+ entry->value = v;
+
+ hash = hash_min((uintptr_t)location, hashtable_bits);
+
+ current_head = &relocation_hashtable[hash];
+
+ /*
+ * Search for the relocation_head for the relocations that happen at the
+ * provided location
+ */
+ bool found = false;
+ struct relocation_head *rel_head_iter;
+
+ hlist_for_each_entry(rel_head_iter, current_head, node) {
+ if (rel_head_iter->location == location) {
+ found = true;
+ rel_head = rel_head_iter;
+ break;
+ }
+ }
+
+ /*
+ * If there has not yet been any relocations at the provided location,
+ * create a relocation_head for that location and populate it with this
+ * relocation_entry.
+ */
+ if (!found) {
+ rel_head = kmalloc(sizeof(*rel_head), GFP_KERNEL);
+
+ if (!rel_head) {
+ kfree(entry);
+ return -ENOMEM;
+ }
+
+ rel_head->rel_entry =
+ kmalloc(sizeof(struct list_head), GFP_KERNEL);
+
+ if (!rel_head->rel_entry) {
+ kfree(entry);
+ kfree(rel_head);
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(rel_head->rel_entry);
+ rel_head->location = location;
+ INIT_HLIST_NODE(&rel_head->node);
+ if (!current_head->first) {
+ bucket =
+ kmalloc(sizeof(struct used_bucket), GFP_KERNEL);
+
+ if (!bucket) {
+ kfree(entry);
+ kfree(rel_head);
+ kfree(rel_head->rel_entry);
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&bucket->head);
+ bucket->bucket = current_head;
+ list_add(&bucket->head, used_buckets_list);
+ }
+ hlist_add_head(&rel_head->node, current_head);
+ }
+
+ /* Add relocation to head of discovered rel_head */
+ list_add_tail(&entry->head, rel_head->rel_entry);
+
+ return 0;
+}
+
+static unsigned int
+initialize_relocation_hashtable(unsigned int num_relocations,
+ struct hlist_head **relocation_hashtable)
+{
+ /* Can safely assume that bits is not greater than sizeof(long) */
+ unsigned long hashtable_size = roundup_pow_of_two(num_relocations);
+ unsigned int hashtable_bits = ilog2(hashtable_size);
+
+ /*
+ * Double size of hashtable if num_relocations * 1.25 is greater than
+ * hashtable_size.
+ */
+ int should_double_size = ((num_relocations + (num_relocations >> 2)) > (hashtable_size));
+
+ hashtable_bits += should_double_size;
+
+ hashtable_size <<= should_double_size;
+
+ *relocation_hashtable = kmalloc_array(hashtable_size,
+ sizeof(*relocation_hashtable),
+ GFP_KERNEL);
+ if (!*relocation_hashtable)
+ return -ENOMEM;
+
+ __hash_init(*relocation_hashtable, hashtable_size);
+
+ return hashtable_bits;
+}
+
int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
unsigned int symindex, unsigned int relsec,
struct module *me)
{
Elf_Rela *rel = (void *) sechdrs[relsec].sh_addr;
- int (*handler)(struct module *me, u32 *location, Elf_Addr v);
+ int (*handler)(struct module *me, void *location, Elf_Addr v);
Elf_Sym *sym;
- u32 *location;
+ void *location;
unsigned int i, type;
Elf_Addr v;
int res;
+ unsigned int num_relocations = sechdrs[relsec].sh_size / sizeof(*rel);
+ struct hlist_head *relocation_hashtable;
+ struct list_head used_buckets_list;
+ unsigned int hashtable_bits;
+
+ hashtable_bits = initialize_relocation_hashtable(num_relocations,
+ &relocation_hashtable);
+
+ if (hashtable_bits < 0)
+ return hashtable_bits;
+
+ INIT_LIST_HEAD(&used_buckets_list);
pr_debug("Applying relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info);
- for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ for (i = 0; i < num_relocations; i++) {
/* This is where to make the change */
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ rel[i].r_offset;
@@ -370,8 +815,8 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
type = ELF_RISCV_R_TYPE(rel[i].r_info);
- if (type < ARRAY_SIZE(reloc_handlers_rela))
- handler = reloc_handlers_rela[type];
+ if (type < ARRAY_SIZE(reloc_handlers))
+ handler = reloc_handlers[type].reloc_handler;
else
handler = NULL;
@@ -427,11 +872,20 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
}
}
- res = handler(me, location, v);
+ if (reloc_handlers[type].accumulate_handler)
+ res = add_relocation_to_accumulate(me, type, location,
+ hashtable_bits, v,
+ relocation_hashtable,
+ &used_buckets_list);
+ else
+ res = handler(me, location, v);
if (res)
return res;
}
+ process_accumulated_relocations(me, &relocation_hashtable,
+ &used_buckets_list);
+
return 0;
}
diff --git a/arch/riscv/kernel/probes/rethook_trampoline.S b/arch/riscv/kernel/probes/rethook_trampoline.S
index 21bac92a170a..f2cd83d9b0f0 100644
--- a/arch/riscv/kernel/probes/rethook_trampoline.S
+++ b/arch/riscv/kernel/probes/rethook_trampoline.S
@@ -75,7 +75,7 @@
REG_L x31, PT_T6(sp)
.endm
-ENTRY(arch_rethook_trampoline)
+SYM_CODE_START(arch_rethook_trampoline)
addi sp, sp, -(PT_SIZE_ON_STACK)
save_all_base_regs
@@ -90,4 +90,4 @@ ENTRY(arch_rethook_trampoline)
addi sp, sp, PT_SIZE_ON_STACK
ret
-ENDPROC(arch_rethook_trampoline)
+SYM_CODE_END(arch_rethook_trampoline)
diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
index d3099d67816d..6c166029079c 100644
--- a/arch/riscv/kernel/probes/simulate-insn.c
+++ b/arch/riscv/kernel/probes/simulate-insn.c
@@ -24,7 +24,7 @@ static inline bool rv_insn_reg_set_val(struct pt_regs *regs, u32 index,
unsigned long val)
{
if (index == 0)
- return false;
+ return true;
else if (index <= 31)
*((unsigned long *)regs + index) = val;
else
diff --git a/arch/riscv/kernel/probes/uprobes.c b/arch/riscv/kernel/probes/uprobes.c
index 194f166b2cc4..4b3dc8beaf77 100644
--- a/arch/riscv/kernel/probes/uprobes.c
+++ b/arch/riscv/kernel/probes/uprobes.c
@@ -3,6 +3,7 @@
#include <linux/highmem.h>
#include <linux/ptrace.h>
#include <linux/uprobes.h>
+#include <asm/insn.h>
#include "decode-insn.h"
@@ -17,6 +18,11 @@ bool is_swbp_insn(uprobe_opcode_t *insn)
#endif
}
+bool is_trap_insn(uprobe_opcode_t *insn)
+{
+ return riscv_insn_is_ebreak(*insn) || riscv_insn_is_c_ebreak(*insn);
+}
+
unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
{
return instruction_pointer(regs);
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index e32d737e039f..4f21d970a129 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -25,6 +25,7 @@
#include <asm/thread_info.h>
#include <asm/cpuidle.h>
#include <asm/vector.h>
+#include <asm/cpufeature.h>
register unsigned long gp_in_global __asm__("gp");
@@ -41,6 +42,23 @@ void arch_cpu_idle(void)
cpu_do_idle();
}
+int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
+{
+ if (!unaligned_ctl_available())
+ return -EINVAL;
+
+ tsk->thread.align_ctl = val;
+ return 0;
+}
+
+int get_unalign_ctl(struct task_struct *tsk, unsigned long adr)
+{
+ if (!unaligned_ctl_available())
+ return -EINVAL;
+
+ return put_user(tsk->thread.align_ctl, (unsigned long __user *)adr);
+}
+
void __show_regs(struct pt_regs *regs)
{
show_regs_print_info(KERN_DEFAULT);
diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
index c672c8ba9a2a..5a62ed1da453 100644
--- a/arch/riscv/kernel/sbi.c
+++ b/arch/riscv/kernel/sbi.c
@@ -11,6 +11,7 @@
#include <linux/reboot.h>
#include <asm/sbi.h>
#include <asm/smp.h>
+#include <asm/tlbflush.h>
/* default SBI version is 0.1 */
unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
@@ -377,31 +378,14 @@ int sbi_remote_fence_i(const struct cpumask *cpu_mask)
EXPORT_SYMBOL(sbi_remote_fence_i);
/**
- * sbi_remote_sfence_vma() - Execute SFENCE.VMA instructions on given remote
- * harts for the specified virtual address range.
- * @cpu_mask: A cpu mask containing all the target harts.
- * @start: Start of the virtual address
- * @size: Total size of the virtual address range.
- *
- * Return: 0 on success, appropriate linux error code otherwise.
- */
-int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
- unsigned long start,
- unsigned long size)
-{
- return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
- cpu_mask, start, size, 0, 0);
-}
-EXPORT_SYMBOL(sbi_remote_sfence_vma);
-
-/**
* sbi_remote_sfence_vma_asid() - Execute SFENCE.VMA instructions on given
- * remote harts for a virtual address range belonging to a specific ASID.
+ * remote harts for a virtual address range belonging to a specific ASID or not.
*
* @cpu_mask: A cpu mask containing all the target harts.
* @start: Start of the virtual address
* @size: Total size of the virtual address range.
- * @asid: The value of address space identifier (ASID).
+ * @asid: The value of address space identifier (ASID), or FLUSH_TLB_NO_ASID
+ * for flushing all address spaces.
*
* Return: 0 on success, appropriate linux error code otherwise.
*/
@@ -410,8 +394,12 @@ int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask,
unsigned long size,
unsigned long asid)
{
- return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
- cpu_mask, start, size, asid, 0);
+ if (asid == FLUSH_TLB_NO_ASID)
+ return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
+ cpu_mask, start, size, 0, 0);
+ else
+ return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
+ cpu_mask, start, size, asid, 0);
}
EXPORT_SYMBOL(sbi_remote_sfence_vma_asid);
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index e600aab116a4..535a837de55d 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -15,7 +15,6 @@
#include <linux/memblock.h>
#include <linux/sched.h>
#include <linux/console.h>
-#include <linux/screen_info.h>
#include <linux/of_fdt.h>
#include <linux/sched/task.h>
#include <linux/smp.h>
@@ -26,6 +25,7 @@
#include <asm/acpi.h>
#include <asm/alternative.h>
#include <asm/cacheflush.h>
+#include <asm/cpufeature.h>
#include <asm/cpu_ops.h>
#include <asm/early_ioremap.h>
#include <asm/pgtable.h>
@@ -40,17 +40,6 @@
#include "head.h"
-#if defined(CONFIG_DUMMY_CONSOLE) || defined(CONFIG_EFI)
-struct screen_info screen_info __section(".data") = {
- .orig_video_lines = 30,
- .orig_video_cols = 80,
- .orig_video_mode = 0,
- .orig_video_ega_bx = 0,
- .orig_video_isVGA = 1,
- .orig_video_points = 8
-};
-#endif
-
/*
* The lucky hart to first increment this variable will boot the other cores.
* This is used before the kernel initializes the BSS so it can't be in the
@@ -173,19 +162,6 @@ static void __init init_resources(void)
if (ret < 0)
goto error;
-#ifdef CONFIG_KEXEC_CORE
- if (crashk_res.start != crashk_res.end) {
- ret = add_resource(&iomem_resource, &crashk_res);
- if (ret < 0)
- goto error;
- }
- if (crashk_low_res.start != crashk_low_res.end) {
- ret = add_resource(&iomem_resource, &crashk_low_res);
- if (ret < 0)
- goto error;
- }
-#endif
-
#ifdef CONFIG_CRASH_DUMP
if (elfcorehdr_size > 0) {
elfcorehdr_res.start = elfcorehdr_addr;
@@ -314,10 +290,13 @@ void __init setup_arch(char **cmdline_p)
riscv_fill_hwcap();
init_rt_signal_env();
apply_boot_alternatives();
+
if (IS_ENABLED(CONFIG_RISCV_ISA_ZICBOM) &&
riscv_isa_extension_available(NULL, ZICBOM))
riscv_noncoherent_supported();
riscv_set_dma_cache_alignment();
+
+ riscv_user_isa_enable();
}
static int __init topology_init(void)
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 180d951d3624..88b6220b2608 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -311,13 +311,6 @@ static inline void __user *get_sigframe(struct ksignal *ksig,
/* Align the stack frame. */
sp &= ~0xfUL;
- /*
- * Fail if the size of the altstack is not large enough for the
- * sigframe construction.
- */
- if (current->sas_ss_size && sp < current->sas_ss_sp)
- return (void __user __force *)-1UL;
-
return (void __user *)sp;
}
@@ -391,30 +384,6 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
sigset_t *oldset = sigmask_to_save();
int ret;
- /* Are we from a system call? */
- if (regs->cause == EXC_SYSCALL) {
- /* Avoid additional syscall restarting via ret_from_exception */
- regs->cause = -1UL;
- /* If so, check system call restarting.. */
- switch (regs->a0) {
- case -ERESTART_RESTARTBLOCK:
- case -ERESTARTNOHAND:
- regs->a0 = -EINTR;
- break;
-
- case -ERESTARTSYS:
- if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
- regs->a0 = -EINTR;
- break;
- }
- fallthrough;
- case -ERESTARTNOINTR:
- regs->a0 = regs->orig_a0;
- regs->epc -= 0x4;
- break;
- }
- }
-
rseq_signal_deliver(ksig, regs);
/* Set up the stack frame */
@@ -428,36 +397,67 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
void arch_do_signal_or_restart(struct pt_regs *regs)
{
+ unsigned long continue_addr = 0, restart_addr = 0;
+ int retval = 0;
struct ksignal ksig;
+ bool syscall = (regs->cause == EXC_SYSCALL);
- if (get_signal(&ksig)) {
- /* Actually deliver the signal */
- handle_signal(&ksig, regs);
- return;
- }
+ /* If we were from a system call, check for system call restarting */
+ if (syscall) {
+ continue_addr = regs->epc;
+ restart_addr = continue_addr - 4;
+ retval = regs->a0;
- /* Did we come from a system call? */
- if (regs->cause == EXC_SYSCALL) {
/* Avoid additional syscall restarting via ret_from_exception */
regs->cause = -1UL;
- /* Restart the system call - no handlers present */
- switch (regs->a0) {
+ /*
+ * Prepare for system call restart. We do this here so that a
+ * debugger will see the already changed PC.
+ */
+ switch (retval) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
- regs->a0 = regs->orig_a0;
- regs->epc -= 0x4;
- break;
case -ERESTART_RESTARTBLOCK:
- regs->a0 = regs->orig_a0;
- regs->a7 = __NR_restart_syscall;
- regs->epc -= 0x4;
+ regs->a0 = regs->orig_a0;
+ regs->epc = restart_addr;
break;
}
}
/*
+ * Get the signal to deliver. When running under ptrace, at this point
+ * the debugger may change all of our registers.
+ */
+ if (get_signal(&ksig)) {
+ /*
+ * Depending on the signal settings, we may need to revert the
+ * decision to restart the system call, but skip this if a
+ * debugger has chosen to restart at a different PC.
+ */
+ if (regs->epc == restart_addr &&
+ (retval == -ERESTARTNOHAND ||
+ retval == -ERESTART_RESTARTBLOCK ||
+ (retval == -ERESTARTSYS &&
+ !(ksig.ka.sa.sa_flags & SA_RESTART)))) {
+ regs->a0 = -EINTR;
+ regs->epc = continue_addr;
+ }
+
+ /* Actually deliver the signal */
+ handle_signal(&ksig, regs);
+ return;
+ }
+
+ /*
+ * Handle restarting a different system call. As above, if a debugger
+ * has chosen to restart at a different PC, ignore the restart.
+ */
+ if (syscall && regs->epc == restart_addr && retval == -ERESTART_RESTARTBLOCK)
+ regs->a7 = __NR_restart_syscall;
+
+ /*
* If there is no signal to deliver, we just put the saved
* sigmask back.
*/
diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c
index 1b8da4e40a4d..d162bf339beb 100644
--- a/arch/riscv/kernel/smpboot.c
+++ b/arch/riscv/kernel/smpboot.c
@@ -25,6 +25,8 @@
#include <linux/of.h>
#include <linux/sched/task_stack.h>
#include <linux/sched/mm.h>
+
+#include <asm/cpufeature.h>
#include <asm/cpu_ops.h>
#include <asm/cpufeature.h>
#include <asm/irq.h>
@@ -246,13 +248,14 @@ asmlinkage __visible void smp_callin(void)
numa_add_cpu(curr_cpuid);
set_cpu_online(curr_cpuid, 1);
- check_unaligned_access(curr_cpuid);
if (has_vector()) {
if (riscv_v_setup_vsize())
elf_hwcap &= ~COMPAT_HWCAP_ISA_V;
}
+ riscv_user_isa_enable();
+
/*
* Remote TLB flushes are ignored while the CPU is offline, so emit
* a local TLB flush right now just in case.
diff --git a/arch/riscv/kernel/suspend_entry.S b/arch/riscv/kernel/suspend_entry.S
index f7960c7c5f9e..2d54f309c140 100644
--- a/arch/riscv/kernel/suspend_entry.S
+++ b/arch/riscv/kernel/suspend_entry.S
@@ -16,7 +16,7 @@
.altmacro
.option norelax
-ENTRY(__cpu_suspend_enter)
+SYM_FUNC_START(__cpu_suspend_enter)
/* Save registers (except A0 and T0-T6) */
REG_S ra, (SUSPEND_CONTEXT_REGS + PT_RA)(a0)
REG_S sp, (SUSPEND_CONTEXT_REGS + PT_SP)(a0)
@@ -57,14 +57,11 @@ ENTRY(__cpu_suspend_enter)
/* Return to C code */
ret
-END(__cpu_suspend_enter)
+SYM_FUNC_END(__cpu_suspend_enter)
SYM_TYPED_FUNC_START(__cpu_resume_enter)
/* Load the global pointer */
- .option push
- .option norelax
- la gp, __global_pointer$
- .option pop
+ load_global_pointer
#ifdef CONFIG_MMU
/* Save A0 and A1 */
diff --git a/arch/riscv/kernel/sys_riscv.c b/arch/riscv/kernel/sys_riscv.c
index 473159b5f303..a2ca5b7756a5 100644
--- a/arch/riscv/kernel/sys_riscv.c
+++ b/arch/riscv/kernel/sys_riscv.c
@@ -79,7 +79,7 @@ SYSCALL_DEFINE3(riscv_flush_icache, uintptr_t, start, uintptr_t, end,
/*
* The hwprobe interface, for allowing userspace to probe to see which features
- * are supported by the hardware. See Documentation/riscv/hwprobe.rst for more
+ * are supported by the hardware. See Documentation/arch/riscv/hwprobe.rst for more
* details.
*/
static void hwprobe_arch_id(struct riscv_hwprobe *pair,
@@ -145,26 +145,38 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
for_each_cpu(cpu, cpus) {
struct riscv_isainfo *isainfo = &hart_isa[cpu];
- if (riscv_isa_extension_available(isainfo->isa, ZBA))
- pair->value |= RISCV_HWPROBE_EXT_ZBA;
- else
- missing |= RISCV_HWPROBE_EXT_ZBA;
+#define EXT_KEY(ext) \
+ do { \
+ if (__riscv_isa_extension_available(isainfo->isa, RISCV_ISA_EXT_##ext)) \
+ pair->value |= RISCV_HWPROBE_EXT_##ext; \
+ else \
+ missing |= RISCV_HWPROBE_EXT_##ext; \
+ } while (false)
- if (riscv_isa_extension_available(isainfo->isa, ZBB))
- pair->value |= RISCV_HWPROBE_EXT_ZBB;
- else
- missing |= RISCV_HWPROBE_EXT_ZBB;
-
- if (riscv_isa_extension_available(isainfo->isa, ZBS))
- pair->value |= RISCV_HWPROBE_EXT_ZBS;
- else
- missing |= RISCV_HWPROBE_EXT_ZBS;
+ /*
+ * Only use EXT_KEY() for extensions which can be exposed to userspace,
+ * regardless of the kernel's configuration, as no other checks, besides
+ * presence in the hart_isa bitmap, are made.
+ */
+ EXT_KEY(ZBA);
+ EXT_KEY(ZBB);
+ EXT_KEY(ZBS);
+ EXT_KEY(ZICBOZ);
+#undef EXT_KEY
}
/* Now turn off reporting features if any CPU is missing it. */
pair->value &= ~missing;
}
+static bool hwprobe_ext0_has(const struct cpumask *cpus, u64 ext)
+{
+ struct riscv_hwprobe pair;
+
+ hwprobe_isa_ext0(&pair, cpus);
+ return (pair.value & ext);
+}
+
static u64 hwprobe_misaligned(const struct cpumask *cpus)
{
int cpu;
@@ -215,6 +227,12 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
pair->value = hwprobe_misaligned(cpus);
break;
+ case RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE:
+ pair->value = 0;
+ if (hwprobe_ext0_has(cpus, RISCV_HWPROBE_EXT_ZICBOZ))
+ pair->value = riscv_cboz_block_size;
+ break;
+
/*
* For forward compatibility, unknown keys don't fail the whole
* call, but get their element key set to -1 and value set to 0
diff --git a/arch/riscv/kernel/tests/Kconfig.debug b/arch/riscv/kernel/tests/Kconfig.debug
new file mode 100644
index 000000000000..5dba64e8e977
--- /dev/null
+++ b/arch/riscv/kernel/tests/Kconfig.debug
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: GPL-2.0-only
+menu "arch/riscv/kernel Testing and Coverage"
+
+config AS_HAS_ULEB128
+ def_bool $(as-instr,.reloc label$(comma) R_RISCV_SET_ULEB128$(comma) 127\n.reloc label$(comma) R_RISCV_SUB_ULEB128$(comma) 127\nlabel:\n.word 0)
+
+menuconfig RUNTIME_KERNEL_TESTING_MENU
+ bool "arch/riscv/kernel runtime Testing"
+ def_bool y
+ help
+ Enable riscv kernel runtime testing.
+
+if RUNTIME_KERNEL_TESTING_MENU
+
+config RISCV_MODULE_LINKING_KUNIT
+ bool "KUnit test riscv module linking at runtime" if !KUNIT_ALL_TESTS
+ depends on KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ Enable this option to test riscv module linking at boot. This will
+ enable a module called "test_module_linking".
+
+ KUnit tests run during boot and output the results to the debug log
+ in TAP format (http://testanything.org/). Only useful for kernel devs
+ running the KUnit test harness, and not intended for inclusion into a
+ production build.
+
+ For more information on KUnit and unit tests in general please refer
+ to the KUnit documentation in Documentation/dev-tools/kunit/.
+
+ If unsure, say N.
+
+endif # RUNTIME_TESTING_MENU
+
+endmenu # "arch/riscv/kernel runtime Testing"
diff --git a/arch/riscv/kernel/tests/Makefile b/arch/riscv/kernel/tests/Makefile
new file mode 100644
index 000000000000..7d6c76cffe20
--- /dev/null
+++ b/arch/riscv/kernel/tests/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_RISCV_MODULE_LINKING_KUNIT) += module_test/
diff --git a/arch/riscv/kernel/tests/module_test/Makefile b/arch/riscv/kernel/tests/module_test/Makefile
new file mode 100644
index 000000000000..d7a6fd8943de
--- /dev/null
+++ b/arch/riscv/kernel/tests/module_test/Makefile
@@ -0,0 +1,15 @@
+obj-m += test_module_linking.o
+
+test_sub := test_sub6.o test_sub8.o test_sub16.o test_sub32.o test_sub64.o
+
+test_set := test_set6.o test_set8.o test_set16.o test_set32.o
+
+test_module_linking-objs += $(test_sub)
+
+test_module_linking-objs += $(test_set)
+
+ifeq ($(CONFIG_AS_HAS_ULEB128),y)
+test_module_linking-objs += test_uleb128.o
+endif
+
+test_module_linking-objs += test_module_linking_main.o
diff --git a/arch/riscv/kernel/tests/module_test/test_module_linking_main.c b/arch/riscv/kernel/tests/module_test/test_module_linking_main.c
new file mode 100644
index 000000000000..8df5fa5b834e
--- /dev/null
+++ b/arch/riscv/kernel/tests/module_test/test_module_linking_main.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Rivos Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <kunit/test.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Test module linking");
+
+extern int test_set32(void);
+extern int test_set16(void);
+extern int test_set8(void);
+extern int test_set6(void);
+extern long test_sub64(void);
+extern int test_sub32(void);
+extern int test_sub16(void);
+extern int test_sub8(void);
+extern int test_sub6(void);
+
+#ifdef CONFIG_AS_HAS_ULEB128
+extern int test_uleb_basic(void);
+extern int test_uleb_large(void);
+#endif
+
+#define CHECK_EQ(lhs, rhs) KUNIT_ASSERT_EQ(test, lhs, rhs)
+
+void run_test_set(struct kunit *test);
+void run_test_sub(struct kunit *test);
+void run_test_uleb(struct kunit *test);
+
+void run_test_set(struct kunit *test)
+{
+ int val32 = test_set32();
+ int val16 = test_set16();
+ int val8 = test_set8();
+ int val6 = test_set6();
+
+ CHECK_EQ(val32, 0);
+ CHECK_EQ(val16, 0);
+ CHECK_EQ(val8, 0);
+ CHECK_EQ(val6, 0);
+}
+
+void run_test_sub(struct kunit *test)
+{
+ int val64 = test_sub64();
+ int val32 = test_sub32();
+ int val16 = test_sub16();
+ int val8 = test_sub8();
+ int val6 = test_sub6();
+
+ CHECK_EQ(val64, 0);
+ CHECK_EQ(val32, 0);
+ CHECK_EQ(val16, 0);
+ CHECK_EQ(val8, 0);
+ CHECK_EQ(val6, 0);
+}
+
+#ifdef CONFIG_AS_HAS_ULEB128
+void run_test_uleb(struct kunit *test)
+{
+ int val_uleb = test_uleb_basic();
+ int val_uleb2 = test_uleb_large();
+
+ CHECK_EQ(val_uleb, 0);
+ CHECK_EQ(val_uleb2, 0);
+}
+#endif
+
+static struct kunit_case __refdata riscv_module_linking_test_cases[] = {
+ KUNIT_CASE(run_test_set),
+ KUNIT_CASE(run_test_sub),
+#ifdef CONFIG_AS_HAS_ULEB128
+ KUNIT_CASE(run_test_uleb),
+#endif
+ {}
+};
+
+static struct kunit_suite riscv_module_linking_test_suite = {
+ .name = "riscv_checksum",
+ .test_cases = riscv_module_linking_test_cases,
+};
+
+kunit_test_suites(&riscv_module_linking_test_suite);
diff --git a/arch/riscv/kernel/tests/module_test/test_set16.S b/arch/riscv/kernel/tests/module_test/test_set16.S
new file mode 100644
index 000000000000..2be0e441a12e
--- /dev/null
+++ b/arch/riscv/kernel/tests/module_test/test_set16.S
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Rivos Inc.
+ */
+
+.text
+.global test_set16
+test_set16:
+ lw a0, set16
+ la t0, set16
+#ifdef CONFIG_32BIT
+ slli t0, t0, 16
+ srli t0, t0, 16
+#else
+ slli t0, t0, 48
+ srli t0, t0, 48
+#endif
+ sub a0, a0, t0
+ ret
+.data
+set16:
+ .reloc set16, R_RISCV_SET16, set16
+ .word 0
diff --git a/arch/riscv/kernel/tests/module_test/test_set32.S b/arch/riscv/kernel/tests/module_test/test_set32.S
new file mode 100644
index 000000000000..de0444537e67
--- /dev/null
+++ b/arch/riscv/kernel/tests/module_test/test_set32.S
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Rivos Inc.
+ */
+
+.text
+.global test_set32
+test_set32:
+ lw a0, set32
+ la t0, set32
+#ifndef CONFIG_32BIT
+ slli t0, t0, 32
+ srli t0, t0, 32
+#endif
+ sub a0, a0, t0
+ ret
+.data
+set32:
+ .reloc set32, R_RISCV_SET32, set32
+ .word 0
diff --git a/arch/riscv/kernel/tests/module_test/test_set6.S b/arch/riscv/kernel/tests/module_test/test_set6.S
new file mode 100644
index 000000000000..c39ce4c219eb
--- /dev/null
+++ b/arch/riscv/kernel/tests/module_test/test_set6.S
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Rivos Inc.
+ */
+
+.text
+.global test_set6
+test_set6:
+ lw a0, set6
+ la t0, set6
+#ifdef CONFIG_32BIT
+ slli t0, t0, 26
+ srli t0, t0, 26
+#else
+ slli t0, t0, 58
+ srli t0, t0, 58
+#endif
+ sub a0, a0, t0
+ ret
+.data
+set6:
+ .reloc set6, R_RISCV_SET6, set6
+ .word 0
diff --git a/arch/riscv/kernel/tests/module_test/test_set8.S b/arch/riscv/kernel/tests/module_test/test_set8.S
new file mode 100644
index 000000000000..a656173f6f99
--- /dev/null
+++ b/arch/riscv/kernel/tests/module_test/test_set8.S
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Rivos Inc.
+ */
+
+.text
+.global test_set8
+test_set8:
+ lw a0, set8
+ la t0, set8
+#ifdef CONFIG_32BIT
+ slli t0, t0, 24
+ srli t0, t0, 24
+#else
+ slli t0, t0, 56
+ srli t0, t0, 56
+#endif
+ sub a0, a0, t0
+ ret
+.data
+set8:
+ .reloc set8, R_RISCV_SET8, set8
+ .word 0
diff --git a/arch/riscv/kernel/tests/module_test/test_sub16.S b/arch/riscv/kernel/tests/module_test/test_sub16.S
new file mode 100644
index 000000000000..80f731d599ba
--- /dev/null
+++ b/arch/riscv/kernel/tests/module_test/test_sub16.S
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Rivos Inc.
+ */
+
+.text
+.global test_sub16
+test_sub16:
+ lh a0, sub16
+ addi a0, a0, -32
+ ret
+first:
+ .space 32
+second:
+
+.data
+sub16:
+ .reloc sub16, R_RISCV_ADD16, second
+ .reloc sub16, R_RISCV_SUB16, first
+ .half 0
diff --git a/arch/riscv/kernel/tests/module_test/test_sub32.S b/arch/riscv/kernel/tests/module_test/test_sub32.S
new file mode 100644
index 000000000000..a341686e12df
--- /dev/null
+++ b/arch/riscv/kernel/tests/module_test/test_sub32.S
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Rivos Inc.
+ */
+
+.text
+.global test_sub32
+test_sub32:
+ lw a0, sub32
+ addi a0, a0, -32
+ ret
+first:
+ .space 32
+second:
+
+.data
+sub32:
+ .reloc sub32, R_RISCV_ADD32, second
+ .reloc sub32, R_RISCV_SUB32, first
+ .word 0
diff --git a/arch/riscv/kernel/tests/module_test/test_sub6.S b/arch/riscv/kernel/tests/module_test/test_sub6.S
new file mode 100644
index 000000000000..e8b61c1ec527
--- /dev/null
+++ b/arch/riscv/kernel/tests/module_test/test_sub6.S
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Rivos Inc.
+ */
+
+.text
+.global test_sub6
+test_sub6:
+ lb a0, sub6
+ addi a0, a0, -32
+ ret
+first:
+ .space 32
+second:
+
+.data
+sub6:
+ .reloc sub6, R_RISCV_SET6, second
+ .reloc sub6, R_RISCV_SUB6, first
+ .byte 0
diff --git a/arch/riscv/kernel/tests/module_test/test_sub64.S b/arch/riscv/kernel/tests/module_test/test_sub64.S
new file mode 100644
index 000000000000..a59e8afa88fd
--- /dev/null
+++ b/arch/riscv/kernel/tests/module_test/test_sub64.S
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Rivos Inc.
+ */
+
+.text
+.global test_sub64
+test_sub64:
+#ifdef CONFIG_32BIT
+ lw a0, sub64
+#else
+ ld a0, sub64
+#endif
+ addi a0, a0, -32
+ ret
+first:
+ .space 32
+second:
+
+.data
+sub64:
+ .reloc sub64, R_RISCV_ADD64, second
+ .reloc sub64, R_RISCV_SUB64, first
+ .word 0
+ .word 0
diff --git a/arch/riscv/kernel/tests/module_test/test_sub8.S b/arch/riscv/kernel/tests/module_test/test_sub8.S
new file mode 100644
index 000000000000..ac5d0ec98de3
--- /dev/null
+++ b/arch/riscv/kernel/tests/module_test/test_sub8.S
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Rivos Inc.
+ */
+
+.text
+.global test_sub8
+test_sub8:
+ lb a0, sub8
+ addi a0, a0, -32
+ ret
+first:
+ .space 32
+second:
+
+.data
+sub8:
+ .reloc sub8, R_RISCV_ADD8, second
+ .reloc sub8, R_RISCV_SUB8, first
+ .byte 0
diff --git a/arch/riscv/kernel/tests/module_test/test_uleb128.S b/arch/riscv/kernel/tests/module_test/test_uleb128.S
new file mode 100644
index 000000000000..8515ed7cd8c1
--- /dev/null
+++ b/arch/riscv/kernel/tests/module_test/test_uleb128.S
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Rivos Inc.
+ */
+
+.text
+.global test_uleb_basic
+test_uleb_basic:
+ lw a0, second
+ addi a0, a0, -127
+ ret
+
+.global test_uleb_large
+test_uleb_large:
+ lw a0, fourth
+ addi a0, a0, -0x07e8
+ ret
+
+.data
+first:
+ .space 127
+second:
+ .reloc second, R_RISCV_SET_ULEB128, second
+ .reloc second, R_RISCV_SUB_ULEB128, first
+ .word 0
+third:
+ .space 1000
+fourth:
+ .reloc fourth, R_RISCV_SET_ULEB128, fourth
+ .reloc fourth, R_RISCV_SUB_ULEB128, third
+ .word 0
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 19807c4d3805..a1b9be3c4332 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -13,6 +13,8 @@
#include <linux/kdebug.h>
#include <linux/uaccess.h>
#include <linux/kprobes.h>
+#include <linux/uprobes.h>
+#include <asm/uprobes.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/irq.h>
@@ -34,7 +36,21 @@ int show_unhandled_signals = 1;
static DEFINE_SPINLOCK(die_lock);
-static void dump_kernel_instr(const char *loglvl, struct pt_regs *regs)
+static int copy_code(struct pt_regs *regs, u16 *val, const u16 *insns)
+{
+ const void __user *uaddr = (__force const void __user *)insns;
+
+ if (!user_mode(regs))
+ return get_kernel_nofault(*val, insns);
+
+ /* The user space code from other tasks cannot be accessed. */
+ if (regs != task_pt_regs(current))
+ return -EPERM;
+
+ return copy_from_user_nofault(val, uaddr, sizeof(*val));
+}
+
+static void dump_instr(const char *loglvl, struct pt_regs *regs)
{
char str[sizeof("0000 ") * 12 + 2 + 1], *p = str;
const u16 *insns = (u16 *)instruction_pointer(regs);
@@ -43,7 +59,7 @@ static void dump_kernel_instr(const char *loglvl, struct pt_regs *regs)
int i;
for (i = -10; i < 2; i++) {
- bad = get_kernel_nofault(val, &insns[i]);
+ bad = copy_code(regs, &val, &insns[i]);
if (!bad) {
p += sprintf(p, i == 0 ? "(%04hx) " : "%04hx ", val);
} else {
@@ -72,7 +88,7 @@ void die(struct pt_regs *regs, const char *str)
print_modules();
if (regs) {
show_regs(regs);
- dump_kernel_instr(KERN_EMERG, regs);
+ dump_instr(KERN_EMERG, regs);
}
cause = regs ? regs->cause : -1;
@@ -105,6 +121,7 @@ void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr)
print_vma_addr(KERN_CONT " in ", instruction_pointer(regs));
pr_cont("\n");
__show_regs(regs);
+ dump_instr(KERN_EMERG, regs);
}
force_sig_fault(signo, code, (void __user *)addr);
@@ -179,14 +196,6 @@ asmlinkage __visible __trap_section void do_trap_insn_illegal(struct pt_regs *re
DO_ERROR_INFO(do_trap_load_fault,
SIGSEGV, SEGV_ACCERR, "load access fault");
-#ifndef CONFIG_RISCV_M_MODE
-DO_ERROR_INFO(do_trap_load_misaligned,
- SIGBUS, BUS_ADRALN, "Oops - load address misaligned");
-DO_ERROR_INFO(do_trap_store_misaligned,
- SIGBUS, BUS_ADRALN, "Oops - store (or AMO) address misaligned");
-#else
-int handle_misaligned_load(struct pt_regs *regs);
-int handle_misaligned_store(struct pt_regs *regs);
asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs)
{
@@ -229,7 +238,6 @@ asmlinkage __visible __trap_section void do_trap_store_misaligned(struct pt_regs
irqentry_nmi_exit(regs, state);
}
}
-#endif
DO_ERROR_INFO(do_trap_store_fault,
SIGSEGV, SEGV_ACCERR, "store (or AMO) access fault");
DO_ERROR_INFO(do_trap_ecall_s,
@@ -247,22 +255,28 @@ static inline unsigned long get_break_insn_length(unsigned long pc)
return GET_INSN_LENGTH(insn);
}
+static bool probe_single_step_handler(struct pt_regs *regs)
+{
+ bool user = user_mode(regs);
+
+ return user ? uprobe_single_step_handler(regs) : kprobe_single_step_handler(regs);
+}
+
+static bool probe_breakpoint_handler(struct pt_regs *regs)
+{
+ bool user = user_mode(regs);
+
+ return user ? uprobe_breakpoint_handler(regs) : kprobe_breakpoint_handler(regs);
+}
+
void handle_break(struct pt_regs *regs)
{
-#ifdef CONFIG_KPROBES
- if (kprobe_single_step_handler(regs))
+ if (probe_single_step_handler(regs))
return;
- if (kprobe_breakpoint_handler(regs))
- return;
-#endif
-#ifdef CONFIG_UPROBES
- if (uprobe_single_step_handler(regs))
+ if (probe_breakpoint_handler(regs))
return;
- if (uprobe_breakpoint_handler(regs))
- return;
-#endif
current->thread.bad_cause = regs->cause;
if (user_mode(regs))
@@ -352,34 +366,10 @@ static void noinstr handle_riscv_irq(struct pt_regs *regs)
asmlinkage void noinstr do_irq(struct pt_regs *regs)
{
irqentry_state_t state = irqentry_enter(regs);
-#ifdef CONFIG_IRQ_STACKS
- if (on_thread_stack()) {
- ulong *sp = per_cpu(irq_stack_ptr, smp_processor_id())
- + IRQ_STACK_SIZE/sizeof(ulong);
- __asm__ __volatile(
- "addi sp, sp, -"RISCV_SZPTR "\n"
- REG_S" ra, (sp) \n"
- "addi sp, sp, -"RISCV_SZPTR "\n"
- REG_S" s0, (sp) \n"
- "addi s0, sp, 2*"RISCV_SZPTR "\n"
- "move sp, %[sp] \n"
- "move a0, %[regs] \n"
- "call handle_riscv_irq \n"
- "addi sp, s0, -2*"RISCV_SZPTR"\n"
- REG_L" s0, (sp) \n"
- "addi sp, sp, "RISCV_SZPTR "\n"
- REG_L" ra, (sp) \n"
- "addi sp, sp, "RISCV_SZPTR "\n"
- :
- : [sp] "r" (sp), [regs] "r" (regs)
- : "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
- "t0", "t1", "t2", "t3", "t4", "t5", "t6",
-#ifndef CONFIG_FRAME_POINTER
- "s0",
-#endif
- "memory");
- } else
-#endif
+
+ if (IS_ENABLED(CONFIG_IRQ_STACKS) && on_thread_stack())
+ call_on_irq_stack(regs, handle_riscv_irq);
+ else
handle_riscv_irq(regs);
irqentry_exit(regs, state);
@@ -402,48 +392,14 @@ int is_valid_bugaddr(unsigned long pc)
#endif /* CONFIG_GENERIC_BUG */
#ifdef CONFIG_VMAP_STACK
-/*
- * Extra stack space that allows us to provide panic messages when the kernel
- * has overflowed its stack.
- */
-static DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)],
+DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)],
overflow_stack)__aligned(16);
-/*
- * A temporary stack for use by handle_kernel_stack_overflow. This is used so
- * we can call into C code to get the per-hart overflow stack. Usage of this
- * stack must be protected by spin_shadow_stack.
- */
-long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE/sizeof(long)] __aligned(16);
-
-/*
- * A pseudo spinlock to protect the shadow stack from being used by multiple
- * harts concurrently. This isn't a real spinlock because the lock side must
- * be taken without a valid stack and only a single register, it's only taken
- * while in the process of panicing anyway so the performance and error
- * checking a proper spinlock gives us doesn't matter.
- */
-unsigned long spin_shadow_stack;
-
-asmlinkage unsigned long get_overflow_stack(void)
-{
- return (unsigned long)this_cpu_ptr(overflow_stack) +
- OVERFLOW_STACK_SIZE;
-}
asmlinkage void handle_bad_stack(struct pt_regs *regs)
{
unsigned long tsk_stk = (unsigned long)current->stack;
unsigned long ovf_stk = (unsigned long)this_cpu_ptr(overflow_stack);
- /*
- * We're done with the shadow stack by this point, as we're on the
- * overflow stack. Tell any other concurrent overflowing harts that
- * they can proceed with panicing by releasing the pseudo-spinlock.
- *
- * This pairs with an amoswap.aq in handle_kernel_stack_overflow.
- */
- smp_store_release(&spin_shadow_stack, 0);
-
console_verbose();
pr_emerg("Insufficient stack space to handle exception!\n");
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index 378f5b151443..5255f8134aef 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -6,12 +6,16 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
+#include <linux/perf_event.h>
#include <linux/irq.h>
#include <linux/stringify.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/csr.h>
+#include <asm/entry-common.h>
+#include <asm/hwprobe.h>
+#include <asm/cpufeature.h>
#define INSN_MATCH_LB 0x3
#define INSN_MASK_LB 0x707f
@@ -151,53 +155,134 @@
#define PRECISION_S 0
#define PRECISION_D 1
-#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type, insn) \
-static inline type load_##type(const type *addr) \
-{ \
- type val; \
- asm (#insn " %0, %1" \
- : "=&r" (val) : "m" (*addr)); \
- return val; \
+#ifdef CONFIG_FPU
+
+#define FP_GET_RD(insn) (insn >> 7 & 0x1F)
+
+extern void put_f32_reg(unsigned long fp_reg, unsigned long value);
+
+static int set_f32_rd(unsigned long insn, struct pt_regs *regs,
+ unsigned long val)
+{
+ unsigned long fp_reg = FP_GET_RD(insn);
+
+ put_f32_reg(fp_reg, val);
+ regs->status |= SR_FS_DIRTY;
+
+ return 0;
}
-#define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type, insn) \
-static inline void store_##type(type *addr, type val) \
-{ \
- asm volatile (#insn " %0, %1\n" \
- : : "r" (val), "m" (*addr)); \
+extern void put_f64_reg(unsigned long fp_reg, unsigned long value);
+
+static int set_f64_rd(unsigned long insn, struct pt_regs *regs, u64 val)
+{
+ unsigned long fp_reg = FP_GET_RD(insn);
+ unsigned long value;
+
+#if __riscv_xlen == 32
+ value = (unsigned long) &val;
+#else
+ value = val;
+#endif
+ put_f64_reg(fp_reg, value);
+ regs->status |= SR_FS_DIRTY;
+
+ return 0;
}
-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u8, lbu)
-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u16, lhu)
-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s8, lb)
-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s16, lh)
-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s32, lw)
-DECLARE_UNPRIVILEGED_STORE_FUNCTION(u8, sb)
-DECLARE_UNPRIVILEGED_STORE_FUNCTION(u16, sh)
-DECLARE_UNPRIVILEGED_STORE_FUNCTION(u32, sw)
-#if defined(CONFIG_64BIT)
-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u32, lwu)
-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u64, ld)
-DECLARE_UNPRIVILEGED_STORE_FUNCTION(u64, sd)
-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong, ld)
+#if __riscv_xlen == 32
+extern void get_f64_reg(unsigned long fp_reg, u64 *value);
+
+static u64 get_f64_rs(unsigned long insn, u8 fp_reg_offset,
+ struct pt_regs *regs)
+{
+ unsigned long fp_reg = (insn >> fp_reg_offset) & 0x1F;
+ u64 val;
+
+ get_f64_reg(fp_reg, &val);
+ regs->status |= SR_FS_DIRTY;
+
+ return val;
+}
#else
-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u32, lw)
-DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong, lw)
-static inline u64 load_u64(const u64 *addr)
+extern unsigned long get_f64_reg(unsigned long fp_reg);
+
+static unsigned long get_f64_rs(unsigned long insn, u8 fp_reg_offset,
+ struct pt_regs *regs)
+{
+ unsigned long fp_reg = (insn >> fp_reg_offset) & 0x1F;
+ unsigned long val;
+
+ val = get_f64_reg(fp_reg);
+ regs->status |= SR_FS_DIRTY;
+
+ return val;
+}
+
+#endif
+
+extern unsigned long get_f32_reg(unsigned long fp_reg);
+
+static unsigned long get_f32_rs(unsigned long insn, u8 fp_reg_offset,
+ struct pt_regs *regs)
{
- return load_u32((u32 *)addr)
- + ((u64)load_u32((u32 *)addr + 1) << 32);
+ unsigned long fp_reg = (insn >> fp_reg_offset) & 0x1F;
+ unsigned long val;
+
+ val = get_f32_reg(fp_reg);
+ regs->status |= SR_FS_DIRTY;
+
+ return val;
+}
+
+#else /* CONFIG_FPU */
+static void set_f32_rd(unsigned long insn, struct pt_regs *regs,
+ unsigned long val) {}
+
+static void set_f64_rd(unsigned long insn, struct pt_regs *regs, u64 val) {}
+
+static unsigned long get_f64_rs(unsigned long insn, u8 fp_reg_offset,
+ struct pt_regs *regs)
+{
+ return 0;
}
-static inline void store_u64(u64 *addr, u64 val)
+static unsigned long get_f32_rs(unsigned long insn, u8 fp_reg_offset,
+ struct pt_regs *regs)
{
- store_u32((u32 *)addr, val);
- store_u32((u32 *)addr + 1, val >> 32);
+ return 0;
}
+
#endif
-static inline ulong get_insn(ulong mepc)
+#define GET_F64_RS2(insn, regs) (get_f64_rs(insn, 20, regs))
+#define GET_F64_RS2C(insn, regs) (get_f64_rs(insn, 2, regs))
+#define GET_F64_RS2S(insn, regs) (get_f64_rs(RVC_RS2S(insn), 0, regs))
+
+#define GET_F32_RS2(insn, regs) (get_f32_rs(insn, 20, regs))
+#define GET_F32_RS2C(insn, regs) (get_f32_rs(insn, 2, regs))
+#define GET_F32_RS2S(insn, regs) (get_f32_rs(RVC_RS2S(insn), 0, regs))
+
+#ifdef CONFIG_RISCV_M_MODE
+static inline int load_u8(struct pt_regs *regs, const u8 *addr, u8 *r_val)
+{
+ u8 val;
+
+ asm volatile("lbu %0, %1" : "=&r" (val) : "m" (*addr));
+ *r_val = val;
+
+ return 0;
+}
+
+static inline int store_u8(struct pt_regs *regs, u8 *addr, u8 val)
+{
+ asm volatile ("sb %0, %1\n" : : "r" (val), "m" (*addr));
+
+ return 0;
+}
+
+static inline int get_insn(struct pt_regs *regs, ulong mepc, ulong *r_insn)
{
register ulong __mepc asm ("a2") = mepc;
ulong val, rvc_mask = 3, tmp;
@@ -226,8 +311,86 @@ static inline ulong get_insn(ulong mepc)
: [addr] "r" (__mepc), [rvc_mask] "r" (rvc_mask),
[xlen_minus_16] "i" (XLEN_MINUS_16));
- return val;
+ *r_insn = val;
+
+ return 0;
}
+#else
+static inline int load_u8(struct pt_regs *regs, const u8 *addr, u8 *r_val)
+{
+ if (user_mode(regs)) {
+ return __get_user(*r_val, addr);
+ } else {
+ *r_val = *addr;
+ return 0;
+ }
+}
+
+static inline int store_u8(struct pt_regs *regs, u8 *addr, u8 val)
+{
+ if (user_mode(regs)) {
+ return __put_user(val, addr);
+ } else {
+ *addr = val;
+ return 0;
+ }
+}
+
+#define __read_insn(regs, insn, insn_addr) \
+({ \
+ int __ret; \
+ \
+ if (user_mode(regs)) { \
+ __ret = __get_user(insn, insn_addr); \
+ } else { \
+ insn = *insn_addr; \
+ __ret = 0; \
+ } \
+ \
+ __ret; \
+})
+
+static inline int get_insn(struct pt_regs *regs, ulong epc, ulong *r_insn)
+{
+ ulong insn = 0;
+
+ if (epc & 0x2) {
+ ulong tmp = 0;
+ u16 __user *insn_addr = (u16 __user *)epc;
+
+ if (__read_insn(regs, insn, insn_addr))
+ return -EFAULT;
+ /* __get_user() uses regular "lw" which sign extend the loaded
+ * value make sure to clear higher order bits in case we "or" it
+ * below with the upper 16 bits half.
+ */
+ insn &= GENMASK(15, 0);
+ if ((insn & __INSN_LENGTH_MASK) != __INSN_LENGTH_32) {
+ *r_insn = insn;
+ return 0;
+ }
+ insn_addr++;
+ if (__read_insn(regs, tmp, insn_addr))
+ return -EFAULT;
+ *r_insn = (tmp << 16) | insn;
+
+ return 0;
+ } else {
+ u32 __user *insn_addr = (u32 __user *)epc;
+
+ if (__read_insn(regs, insn, insn_addr))
+ return -EFAULT;
+ if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32) {
+ *r_insn = insn;
+ return 0;
+ }
+ insn &= GENMASK(15, 0);
+ *r_insn = insn;
+
+ return 0;
+ }
+}
+#endif
union reg_data {
u8 data_bytes[8];
@@ -235,14 +398,32 @@ union reg_data {
u64 data_u64;
};
+static bool unaligned_ctl __read_mostly;
+
+/* sysctl hooks */
+int unaligned_enabled __read_mostly = 1; /* Enabled by default */
+
int handle_misaligned_load(struct pt_regs *regs)
{
union reg_data val;
unsigned long epc = regs->epc;
- unsigned long insn = get_insn(epc);
- unsigned long addr = csr_read(mtval);
+ unsigned long insn;
+ unsigned long addr = regs->badaddr;
int i, fp = 0, shift = 0, len = 0;
+ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
+
+ *this_cpu_ptr(&misaligned_access_speed) = RISCV_HWPROBE_MISALIGNED_EMULATED;
+
+ if (!unaligned_enabled)
+ return -1;
+
+ if (user_mode(regs) && (current->thread.align_ctl & PR_UNALIGN_SIGBUS))
+ return -1;
+
+ if (get_insn(regs, epc, &insn))
+ return -1;
+
regs->epc = 0;
if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) {
@@ -305,13 +486,21 @@ int handle_misaligned_load(struct pt_regs *regs)
return -1;
}
+ if (!IS_ENABLED(CONFIG_FPU) && fp)
+ return -EOPNOTSUPP;
+
val.data_u64 = 0;
- for (i = 0; i < len; i++)
- val.data_bytes[i] = load_u8((void *)(addr + i));
+ for (i = 0; i < len; i++) {
+ if (load_u8(regs, (void *)(addr + i), &val.data_bytes[i]))
+ return -1;
+ }
- if (fp)
- return -1;
- SET_RD(insn, regs, val.data_ulong << shift >> shift);
+ if (!fp)
+ SET_RD(insn, regs, val.data_ulong << shift >> shift);
+ else if (len == 8)
+ set_f64_rd(insn, regs, val.data_u64);
+ else
+ set_f32_rd(insn, regs, val.data_ulong);
regs->epc = epc + INSN_LEN(insn);
@@ -322,9 +511,20 @@ int handle_misaligned_store(struct pt_regs *regs)
{
union reg_data val;
unsigned long epc = regs->epc;
- unsigned long insn = get_insn(epc);
- unsigned long addr = csr_read(mtval);
- int i, len = 0;
+ unsigned long insn;
+ unsigned long addr = regs->badaddr;
+ int i, len = 0, fp = 0;
+
+ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
+
+ if (!unaligned_enabled)
+ return -1;
+
+ if (user_mode(regs) && (current->thread.align_ctl & PR_UNALIGN_SIGBUS))
+ return -1;
+
+ if (get_insn(regs, epc, &insn))
+ return -1;
regs->epc = 0;
@@ -336,33 +536,112 @@ int handle_misaligned_store(struct pt_regs *regs)
} else if ((insn & INSN_MASK_SD) == INSN_MATCH_SD) {
len = 8;
#endif
+ } else if ((insn & INSN_MASK_FSD) == INSN_MATCH_FSD) {
+ fp = 1;
+ len = 8;
+ val.data_u64 = GET_F64_RS2(insn, regs);
+ } else if ((insn & INSN_MASK_FSW) == INSN_MATCH_FSW) {
+ fp = 1;
+ len = 4;
+ val.data_ulong = GET_F32_RS2(insn, regs);
} else if ((insn & INSN_MASK_SH) == INSN_MATCH_SH) {
len = 2;
#if defined(CONFIG_64BIT)
} else if ((insn & INSN_MASK_C_SD) == INSN_MATCH_C_SD) {
len = 8;
val.data_ulong = GET_RS2S(insn, regs);
- } else if ((insn & INSN_MASK_C_SDSP) == INSN_MATCH_C_SDSP &&
- ((insn >> SH_RD) & 0x1f)) {
+ } else if ((insn & INSN_MASK_C_SDSP) == INSN_MATCH_C_SDSP) {
len = 8;
val.data_ulong = GET_RS2C(insn, regs);
#endif
} else if ((insn & INSN_MASK_C_SW) == INSN_MATCH_C_SW) {
len = 4;
val.data_ulong = GET_RS2S(insn, regs);
- } else if ((insn & INSN_MASK_C_SWSP) == INSN_MATCH_C_SWSP &&
- ((insn >> SH_RD) & 0x1f)) {
+ } else if ((insn & INSN_MASK_C_SWSP) == INSN_MATCH_C_SWSP) {
len = 4;
val.data_ulong = GET_RS2C(insn, regs);
+ } else if ((insn & INSN_MASK_C_FSD) == INSN_MATCH_C_FSD) {
+ fp = 1;
+ len = 8;
+ val.data_u64 = GET_F64_RS2S(insn, regs);
+ } else if ((insn & INSN_MASK_C_FSDSP) == INSN_MATCH_C_FSDSP) {
+ fp = 1;
+ len = 8;
+ val.data_u64 = GET_F64_RS2C(insn, regs);
+#if !defined(CONFIG_64BIT)
+ } else if ((insn & INSN_MASK_C_FSW) == INSN_MATCH_C_FSW) {
+ fp = 1;
+ len = 4;
+ val.data_ulong = GET_F32_RS2S(insn, regs);
+ } else if ((insn & INSN_MASK_C_FSWSP) == INSN_MATCH_C_FSWSP) {
+ fp = 1;
+ len = 4;
+ val.data_ulong = GET_F32_RS2C(insn, regs);
+#endif
} else {
regs->epc = epc;
return -1;
}
- for (i = 0; i < len; i++)
- store_u8((void *)(addr + i), val.data_bytes[i]);
+ if (!IS_ENABLED(CONFIG_FPU) && fp)
+ return -EOPNOTSUPP;
+
+ for (i = 0; i < len; i++) {
+ if (store_u8(regs, (void *)(addr + i), val.data_bytes[i]))
+ return -1;
+ }
regs->epc = epc + INSN_LEN(insn);
return 0;
}
+
+bool check_unaligned_access_emulated(int cpu)
+{
+ long *mas_ptr = per_cpu_ptr(&misaligned_access_speed, cpu);
+ unsigned long tmp_var, tmp_val;
+ bool misaligned_emu_detected;
+
+ *mas_ptr = RISCV_HWPROBE_MISALIGNED_UNKNOWN;
+
+ __asm__ __volatile__ (
+ " "REG_L" %[tmp], 1(%[ptr])\n"
+ : [tmp] "=r" (tmp_val) : [ptr] "r" (&tmp_var) : "memory");
+
+ misaligned_emu_detected = (*mas_ptr == RISCV_HWPROBE_MISALIGNED_EMULATED);
+ /*
+ * If unaligned_ctl is already set, this means that we detected that all
+ * CPUS uses emulated misaligned access at boot time. If that changed
+ * when hotplugging the new cpu, this is something we don't handle.
+ */
+ if (unlikely(unaligned_ctl && !misaligned_emu_detected)) {
+ pr_crit("CPU misaligned accesses non homogeneous (expected all emulated)\n");
+ while (true)
+ cpu_relax();
+ }
+
+ return misaligned_emu_detected;
+}
+
+void unaligned_emulation_finish(void)
+{
+ int cpu;
+
+ /*
+ * We can only support PR_UNALIGN controls if all CPUs have misaligned
+ * accesses emulated since tasks requesting such control can run on any
+ * CPU.
+ */
+ for_each_present_cpu(cpu) {
+ if (per_cpu(misaligned_access_speed, cpu) !=
+ RISCV_HWPROBE_MISALIGNED_EMULATED) {
+ return;
+ }
+ }
+ unaligned_ctl = true;
+}
+
+bool unaligned_ctl_available(void)
+{
+ return unaligned_ctl;
+}
diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile
index 6b1dba11bf6d..9b517fe1b8a8 100644
--- a/arch/riscv/kernel/vdso/Makefile
+++ b/arch/riscv/kernel/vdso/Makefile
@@ -36,7 +36,7 @@ CPPFLAGS_vdso.lds += -DHAS_VGETTIMEOFDAY
endif
# Disable -pg to prevent insert call site
-CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS)
# Disable profiling and instrumentation for VDSO code
GCOV_PROFILE := n
@@ -73,13 +73,3 @@ quiet_cmd_vdsold = VDSOLD $@
cmd_vdsold = $(LD) $(ld_flags) -T $(filter-out FORCE,$^) -o $@.tmp && \
$(OBJCOPY) $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \
rm $@.tmp
-
-# install commands for the unstripped file
-quiet_cmd_vdso_install = INSTALL $@
- cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
-
-vdso.so: $(obj)/vdso.so.dbg
- @mkdir -p $(MODLIB)/vdso
- $(call cmd,vdso_install)
-
-vdso_install: vdso.so
diff --git a/arch/riscv/kernel/vdso/flush_icache.S b/arch/riscv/kernel/vdso/flush_icache.S
index 82f97d67c23e..8f884227e8bc 100644
--- a/arch/riscv/kernel/vdso/flush_icache.S
+++ b/arch/riscv/kernel/vdso/flush_icache.S
@@ -8,7 +8,7 @@
.text
/* int __vdso_flush_icache(void *start, void *end, unsigned long flags); */
-ENTRY(__vdso_flush_icache)
+SYM_FUNC_START(__vdso_flush_icache)
.cfi_startproc
#ifdef CONFIG_SMP
li a7, __NR_riscv_flush_icache
@@ -19,4 +19,4 @@ ENTRY(__vdso_flush_icache)
#endif
ret
.cfi_endproc
-ENDPROC(__vdso_flush_icache)
+SYM_FUNC_END(__vdso_flush_icache)
diff --git a/arch/riscv/kernel/vdso/getcpu.S b/arch/riscv/kernel/vdso/getcpu.S
index bb0c05e2ffba..9c1bd531907f 100644
--- a/arch/riscv/kernel/vdso/getcpu.S
+++ b/arch/riscv/kernel/vdso/getcpu.S
@@ -8,11 +8,11 @@
.text
/* int __vdso_getcpu(unsigned *cpu, unsigned *node, void *unused); */
-ENTRY(__vdso_getcpu)
+SYM_FUNC_START(__vdso_getcpu)
.cfi_startproc
/* For now, just do the syscall. */
li a7, __NR_getcpu
ecall
ret
.cfi_endproc
-ENDPROC(__vdso_getcpu)
+SYM_FUNC_END(__vdso_getcpu)
diff --git a/arch/riscv/kernel/vdso/hwprobe.c b/arch/riscv/kernel/vdso/hwprobe.c
index d40bec6ac078..cadf725ef798 100644
--- a/arch/riscv/kernel/vdso/hwprobe.c
+++ b/arch/riscv/kernel/vdso/hwprobe.c
@@ -37,7 +37,7 @@ int __vdso_riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
/* This is something we can handle, fill out the pairs. */
while (p < end) {
- if (p->key <= RISCV_HWPROBE_MAX_KEY) {
+ if (riscv_hwprobe_key_is_valid(p->key)) {
p->value = avd->all_cpu_hwprobe_values[p->key];
} else {
diff --git a/arch/riscv/kernel/vdso/rt_sigreturn.S b/arch/riscv/kernel/vdso/rt_sigreturn.S
index 10438c7c626a..3dc022aa8931 100644
--- a/arch/riscv/kernel/vdso/rt_sigreturn.S
+++ b/arch/riscv/kernel/vdso/rt_sigreturn.S
@@ -7,10 +7,10 @@
#include <asm/unistd.h>
.text
-ENTRY(__vdso_rt_sigreturn)
+SYM_FUNC_START(__vdso_rt_sigreturn)
.cfi_startproc
.cfi_signal_frame
li a7, __NR_rt_sigreturn
ecall
.cfi_endproc
-ENDPROC(__vdso_rt_sigreturn)
+SYM_FUNC_END(__vdso_rt_sigreturn)
diff --git a/arch/riscv/kernel/vdso/sys_hwprobe.S b/arch/riscv/kernel/vdso/sys_hwprobe.S
index 4e704146c77a..77e57f830521 100644
--- a/arch/riscv/kernel/vdso/sys_hwprobe.S
+++ b/arch/riscv/kernel/vdso/sys_hwprobe.S
@@ -5,11 +5,11 @@
#include <asm/unistd.h>
.text
-ENTRY(riscv_hwprobe)
+SYM_FUNC_START(riscv_hwprobe)
.cfi_startproc
li a7, __NR_riscv_hwprobe
ecall
ret
.cfi_endproc
-ENDPROC(riscv_hwprobe)
+SYM_FUNC_END(riscv_hwprobe)
diff --git a/arch/riscv/kernel/vdso/vdso.lds.S b/arch/riscv/kernel/vdso/vdso.lds.S
index 82ce64900f3d..cbe2a179331d 100644
--- a/arch/riscv/kernel/vdso/vdso.lds.S
+++ b/arch/riscv/kernel/vdso/vdso.lds.S
@@ -23,35 +23,31 @@ SECTIONS
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
- .note : { *(.note.*) } :text :note
.dynamic : { *(.dynamic) } :text :dynamic
+ .rodata : {
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.got.plt) *(.got)
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ }
+
+ .note : { *(.note.*) } :text :note
+
.eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
.eh_frame : { KEEP (*(.eh_frame)) } :text
- .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
-
/*
- * This linker script is used both with -r and with -shared.
- * For the layouts to match, we need to skip more than enough
- * space for the dynamic symbol table, etc. If this amount is
- * insufficient, ld -shared will error; simply increase it here.
+ * Text is well-separated from actual data: there's plenty of
+ * stuff that isn't used at runtime in between.
*/
- . = 0x800;
+ . = ALIGN(16);
.text : { *(.text .text.*) } :text
. = ALIGN(4);
.alternative : {
- __alt_start = .;
*(.alternative)
- __alt_end = .;
- }
-
- .data : {
- *(.got.plt) *(.got)
- *(.data .data.* .gnu.linkonce.d.*)
- *(.dynbss)
- *(.bss .bss.* .gnu.linkonce.b.*)
}
}
diff --git a/arch/riscv/kernel/vector.c b/arch/riscv/kernel/vector.c
index 8d92fb6c522c..578b6292487e 100644
--- a/arch/riscv/kernel/vector.c
+++ b/arch/riscv/kernel/vector.c
@@ -255,7 +255,6 @@ static struct ctl_table riscv_v_default_vstate_table[] = {
.mode = 0644,
.proc_handler = proc_dobool,
},
- { }
};
static int __init riscv_v_sysctl_init(void)
diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c
index 74bb27440527..a944294f6f23 100644
--- a/arch/riscv/kvm/aia.c
+++ b/arch/riscv/kvm/aia.c
@@ -14,7 +14,7 @@
#include <linux/kvm_host.h>
#include <linux/percpu.h>
#include <linux/spinlock.h>
-#include <asm/hwcap.h>
+#include <asm/cpufeature.h>
#include <asm/kvm_aia_imsic.h>
struct aia_hgei_control {
diff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c
index 48ae0d4b3932..225a435d9c9a 100644
--- a/arch/riscv/kvm/main.c
+++ b/arch/riscv/kvm/main.c
@@ -11,7 +11,7 @@
#include <linux/module.h>
#include <linux/kvm_host.h>
#include <asm/csr.h>
-#include <asm/hwcap.h>
+#include <asm/cpufeature.h>
#include <asm/sbi.h>
long kvm_arch_dev_ioctl(struct file *filp,
diff --git a/arch/riscv/kvm/tlb.c b/arch/riscv/kvm/tlb.c
index 44bc324aeeb0..23c0e82b5103 100644
--- a/arch/riscv/kvm/tlb.c
+++ b/arch/riscv/kvm/tlb.c
@@ -12,7 +12,7 @@
#include <linux/kvm_host.h>
#include <asm/cacheflush.h>
#include <asm/csr.h>
-#include <asm/hwcap.h>
+#include <asm/cpufeature.h>
#include <asm/insn-def.h>
#define has_svinval() riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index 82229db1ce73..e087c809073c 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -141,6 +141,12 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
if (rc)
return rc;
+ /*
+ * Setup SBI extensions
+ * NOTE: This must be the last thing to be initialized.
+ */
+ kvm_riscv_vcpu_sbi_init(vcpu);
+
/* Reset VCPU */
kvm_riscv_reset_vcpu(vcpu);
@@ -471,31 +477,38 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
return -EINVAL;
}
-static void kvm_riscv_vcpu_update_config(const unsigned long *isa)
+static void kvm_riscv_vcpu_setup_config(struct kvm_vcpu *vcpu)
{
- u64 henvcfg = 0;
+ const unsigned long *isa = vcpu->arch.isa;
+ struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
if (riscv_isa_extension_available(isa, SVPBMT))
- henvcfg |= ENVCFG_PBMTE;
+ cfg->henvcfg |= ENVCFG_PBMTE;
if (riscv_isa_extension_available(isa, SSTC))
- henvcfg |= ENVCFG_STCE;
+ cfg->henvcfg |= ENVCFG_STCE;
if (riscv_isa_extension_available(isa, ZICBOM))
- henvcfg |= (ENVCFG_CBIE | ENVCFG_CBCFE);
+ cfg->henvcfg |= (ENVCFG_CBIE | ENVCFG_CBCFE);
if (riscv_isa_extension_available(isa, ZICBOZ))
- henvcfg |= ENVCFG_CBZE;
-
- csr_write(CSR_HENVCFG, henvcfg);
-#ifdef CONFIG_32BIT
- csr_write(CSR_HENVCFGH, henvcfg >> 32);
-#endif
+ cfg->henvcfg |= ENVCFG_CBZE;
+
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
+ cfg->hstateen0 |= SMSTATEEN0_HSENVCFG;
+ if (riscv_isa_extension_available(isa, SSAIA))
+ cfg->hstateen0 |= SMSTATEEN0_AIA_IMSIC |
+ SMSTATEEN0_AIA |
+ SMSTATEEN0_AIA_ISEL;
+ if (riscv_isa_extension_available(isa, SMSTATEEN))
+ cfg->hstateen0 |= SMSTATEEN0_SSTATEEN0;
+ }
}
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+ struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
csr_write(CSR_VSSTATUS, csr->vsstatus);
csr_write(CSR_VSIE, csr->vsie);
@@ -506,8 +519,14 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
csr_write(CSR_VSTVAL, csr->vstval);
csr_write(CSR_HVIP, csr->hvip);
csr_write(CSR_VSATP, csr->vsatp);
-
- kvm_riscv_vcpu_update_config(vcpu->arch.isa);
+ csr_write(CSR_HENVCFG, cfg->henvcfg);
+ if (IS_ENABLED(CONFIG_32BIT))
+ csr_write(CSR_HENVCFGH, cfg->henvcfg >> 32);
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
+ csr_write(CSR_HSTATEEN0, cfg->hstateen0);
+ if (IS_ENABLED(CONFIG_32BIT))
+ csr_write(CSR_HSTATEEN0H, cfg->hstateen0 >> 32);
+ }
kvm_riscv_gstage_update_hgatp(vcpu);
@@ -606,6 +625,32 @@ static void kvm_riscv_update_hvip(struct kvm_vcpu *vcpu)
kvm_riscv_vcpu_aia_update_hvip(vcpu);
}
+static __always_inline void kvm_riscv_vcpu_swap_in_guest_state(struct kvm_vcpu *vcpu)
+{
+ struct kvm_vcpu_smstateen_csr *smcsr = &vcpu->arch.smstateen_csr;
+ struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+ struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
+
+ vcpu->arch.host_senvcfg = csr_swap(CSR_SENVCFG, csr->senvcfg);
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN) &&
+ (cfg->hstateen0 & SMSTATEEN0_SSTATEEN0))
+ vcpu->arch.host_sstateen0 = csr_swap(CSR_SSTATEEN0,
+ smcsr->sstateen0);
+}
+
+static __always_inline void kvm_riscv_vcpu_swap_in_host_state(struct kvm_vcpu *vcpu)
+{
+ struct kvm_vcpu_smstateen_csr *smcsr = &vcpu->arch.smstateen_csr;
+ struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+ struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
+
+ csr->senvcfg = csr_swap(CSR_SENVCFG, vcpu->arch.host_senvcfg);
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN) &&
+ (cfg->hstateen0 & SMSTATEEN0_SSTATEEN0))
+ smcsr->sstateen0 = csr_swap(CSR_SSTATEEN0,
+ vcpu->arch.host_sstateen0);
+}
+
/*
* Actually run the vCPU, entering an RCU extended quiescent state (EQS) while
* the vCPU is running.
@@ -615,10 +660,12 @@ static void kvm_riscv_update_hvip(struct kvm_vcpu *vcpu)
*/
static void noinstr kvm_riscv_vcpu_enter_exit(struct kvm_vcpu *vcpu)
{
+ kvm_riscv_vcpu_swap_in_guest_state(vcpu);
guest_state_enter_irqoff();
__kvm_riscv_switch_to(&vcpu->arch);
vcpu->arch.last_exit_cpu = vcpu->cpu;
guest_state_exit_irqoff();
+ kvm_riscv_vcpu_swap_in_host_state(vcpu);
}
int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
@@ -627,6 +674,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
struct kvm_cpu_trap trap;
struct kvm_run *run = vcpu->run;
+ if (!vcpu->arch.ran_atleast_once)
+ kvm_riscv_vcpu_setup_config(vcpu);
+
/* Mark this VCPU ran at least once */
vcpu->arch.ran_atleast_once = true;
diff --git a/arch/riscv/kvm/vcpu_fp.c b/arch/riscv/kvm/vcpu_fp.c
index 08ba48a395aa..030904d82b58 100644
--- a/arch/riscv/kvm/vcpu_fp.c
+++ b/arch/riscv/kvm/vcpu_fp.c
@@ -11,7 +11,7 @@
#include <linux/err.h>
#include <linux/kvm_host.h>
#include <linux/uaccess.h>
-#include <asm/hwcap.h>
+#include <asm/cpufeature.h>
#ifdef CONFIG_FPU
void kvm_riscv_vcpu_fp_reset(struct kvm_vcpu *vcpu)
diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index b7e0e03c69b1..f8c9fa0c03c5 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -13,7 +13,7 @@
#include <linux/uaccess.h>
#include <linux/kvm_host.h>
#include <asm/cacheflush.h>
-#include <asm/hwcap.h>
+#include <asm/cpufeature.h>
#include <asm/kvm_vcpu_vector.h>
#include <asm/vector.h>
@@ -34,6 +34,7 @@ static const unsigned long kvm_isa_ext_arr[] = {
[KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m,
[KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v,
/* Multi letter extensions (alphabetically sorted) */
+ KVM_ISA_EXT_ARR(SMSTATEEN),
KVM_ISA_EXT_ARR(SSAIA),
KVM_ISA_EXT_ARR(SSTC),
KVM_ISA_EXT_ARR(SVINVAL),
@@ -45,6 +46,7 @@ static const unsigned long kvm_isa_ext_arr[] = {
KVM_ISA_EXT_ARR(ZICBOM),
KVM_ISA_EXT_ARR(ZICBOZ),
KVM_ISA_EXT_ARR(ZICNTR),
+ KVM_ISA_EXT_ARR(ZICOND),
KVM_ISA_EXT_ARR(ZICSR),
KVM_ISA_EXT_ARR(ZIFENCEI),
KVM_ISA_EXT_ARR(ZIHINTPAUSE),
@@ -80,11 +82,11 @@ static bool kvm_riscv_vcpu_isa_enable_allowed(unsigned long ext)
static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext)
{
switch (ext) {
+ /* Extensions which don't have any mechanism to disable */
case KVM_RISCV_ISA_EXT_A:
case KVM_RISCV_ISA_EXT_C:
case KVM_RISCV_ISA_EXT_I:
case KVM_RISCV_ISA_EXT_M:
- case KVM_RISCV_ISA_EXT_SSAIA:
case KVM_RISCV_ISA_EXT_SSTC:
case KVM_RISCV_ISA_EXT_SVINVAL:
case KVM_RISCV_ISA_EXT_SVNAPOT:
@@ -92,11 +94,15 @@ static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext)
case KVM_RISCV_ISA_EXT_ZBB:
case KVM_RISCV_ISA_EXT_ZBS:
case KVM_RISCV_ISA_EXT_ZICNTR:
+ case KVM_RISCV_ISA_EXT_ZICOND:
case KVM_RISCV_ISA_EXT_ZICSR:
case KVM_RISCV_ISA_EXT_ZIFENCEI:
case KVM_RISCV_ISA_EXT_ZIHINTPAUSE:
case KVM_RISCV_ISA_EXT_ZIHPM:
return false;
+ /* Extensions which can be disabled using Smstateen */
+ case KVM_RISCV_ISA_EXT_SSAIA:
+ return riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN);
default:
break;
}
@@ -378,6 +384,34 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
return 0;
}
+static inline int kvm_riscv_vcpu_smstateen_set_csr(struct kvm_vcpu *vcpu,
+ unsigned long reg_num,
+ unsigned long reg_val)
+{
+ struct kvm_vcpu_smstateen_csr *csr = &vcpu->arch.smstateen_csr;
+
+ if (reg_num >= sizeof(struct kvm_riscv_smstateen_csr) /
+ sizeof(unsigned long))
+ return -EINVAL;
+
+ ((unsigned long *)csr)[reg_num] = reg_val;
+ return 0;
+}
+
+static int kvm_riscv_vcpu_smstateen_get_csr(struct kvm_vcpu *vcpu,
+ unsigned long reg_num,
+ unsigned long *out_val)
+{
+ struct kvm_vcpu_smstateen_csr *csr = &vcpu->arch.smstateen_csr;
+
+ if (reg_num >= sizeof(struct kvm_riscv_smstateen_csr) /
+ sizeof(unsigned long))
+ return -EINVAL;
+
+ *out_val = ((unsigned long *)csr)[reg_num];
+ return 0;
+}
+
static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg)
{
@@ -401,6 +435,12 @@ static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu,
case KVM_REG_RISCV_CSR_AIA:
rc = kvm_riscv_vcpu_aia_get_csr(vcpu, reg_num, &reg_val);
break;
+ case KVM_REG_RISCV_CSR_SMSTATEEN:
+ rc = -EINVAL;
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN))
+ rc = kvm_riscv_vcpu_smstateen_get_csr(vcpu, reg_num,
+ &reg_val);
+ break;
default:
rc = -ENOENT;
break;
@@ -440,6 +480,12 @@ static int kvm_riscv_vcpu_set_reg_csr(struct kvm_vcpu *vcpu,
case KVM_REG_RISCV_CSR_AIA:
rc = kvm_riscv_vcpu_aia_set_csr(vcpu, reg_num, reg_val);
break;
+ case KVM_REG_RISCV_CSR_SMSTATEEN:
+ rc = -EINVAL;
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN))
+ rc = kvm_riscv_vcpu_smstateen_set_csr(vcpu, reg_num,
+ reg_val);
+break;
default:
rc = -ENOENT;
break;
@@ -696,6 +742,8 @@ static inline unsigned long num_csr_regs(const struct kvm_vcpu *vcpu)
if (riscv_isa_extension_available(vcpu->arch.isa, SSAIA))
n += sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long);
+ if (riscv_isa_extension_available(vcpu->arch.isa, SMSTATEEN))
+ n += sizeof(struct kvm_riscv_smstateen_csr) / sizeof(unsigned long);
return n;
}
@@ -704,7 +752,7 @@ static int copy_csr_reg_indices(const struct kvm_vcpu *vcpu,
u64 __user *uindices)
{
int n1 = sizeof(struct kvm_riscv_csr) / sizeof(unsigned long);
- int n2 = 0;
+ int n2 = 0, n3 = 0;
/* copy general csr regs */
for (int i = 0; i < n1; i++) {
@@ -738,7 +786,25 @@ static int copy_csr_reg_indices(const struct kvm_vcpu *vcpu,
}
}
- return n1 + n2;
+ /* copy Smstateen csr regs */
+ if (riscv_isa_extension_available(vcpu->arch.isa, SMSTATEEN)) {
+ n3 = sizeof(struct kvm_riscv_smstateen_csr) / sizeof(unsigned long);
+
+ for (int i = 0; i < n3; i++) {
+ u64 size = IS_ENABLED(CONFIG_32BIT) ?
+ KVM_REG_SIZE_U32 : KVM_REG_SIZE_U64;
+ u64 reg = KVM_REG_RISCV | size | KVM_REG_RISCV_CSR |
+ KVM_REG_RISCV_CSR_SMSTATEEN | i;
+
+ if (uindices) {
+ if (put_user(reg, uindices))
+ return -EFAULT;
+ uindices++;
+ }
+ }
+ }
+
+ return n1 + n2 + n3;
}
static inline unsigned long num_timer_regs(void)
diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c
index 9cd97091c723..a04ff98085d9 100644
--- a/arch/riscv/kvm/vcpu_sbi.c
+++ b/arch/riscv/kvm/vcpu_sbi.c
@@ -67,6 +67,10 @@ static const struct kvm_riscv_sbi_extension_entry sbi_ext[] = {
.ext_ptr = &vcpu_sbi_ext_pmu,
},
{
+ .ext_idx = KVM_RISCV_SBI_EXT_DBCN,
+ .ext_ptr = &vcpu_sbi_ext_dbcn,
+ },
+ {
.ext_idx = KVM_RISCV_SBI_EXT_EXPERIMENTAL,
.ext_ptr = &vcpu_sbi_ext_experimental,
},
@@ -155,14 +159,8 @@ static int riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu *vcpu,
if (!sext)
return -ENOENT;
- /*
- * We can't set the extension status to available here, since it may
- * have a probe() function which needs to confirm availability first,
- * but it may be too early to call that here. We can set the status to
- * unavailable, though.
- */
- if (!reg_val)
- scontext->ext_status[sext->ext_idx] =
+ scontext->ext_status[sext->ext_idx] = (reg_val) ?
+ KVM_RISCV_SBI_EXT_AVAILABLE :
KVM_RISCV_SBI_EXT_UNAVAILABLE;
return 0;
@@ -188,16 +186,8 @@ static int riscv_vcpu_get_sbi_ext_single(struct kvm_vcpu *vcpu,
if (!sext)
return -ENOENT;
- /*
- * If the extension status is still uninitialized, then we should probe
- * to determine if it's available, but it may be too early to do that
- * here. The best we can do is report that the extension has not been
- * disabled, i.e. we return 1 when the extension is available and also
- * when it only may be available.
- */
- *reg_val = scontext->ext_status[sext->ext_idx] !=
- KVM_RISCV_SBI_EXT_UNAVAILABLE;
-
+ *reg_val = scontext->ext_status[sext->ext_idx] ==
+ KVM_RISCV_SBI_EXT_AVAILABLE;
return 0;
}
@@ -337,18 +327,8 @@ const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
scontext->ext_status[entry->ext_idx] ==
KVM_RISCV_SBI_EXT_AVAILABLE)
return ext;
- if (scontext->ext_status[entry->ext_idx] ==
- KVM_RISCV_SBI_EXT_UNAVAILABLE)
- return NULL;
- if (ext->probe && !ext->probe(vcpu)) {
- scontext->ext_status[entry->ext_idx] =
- KVM_RISCV_SBI_EXT_UNAVAILABLE;
- return NULL;
- }
- scontext->ext_status[entry->ext_idx] =
- KVM_RISCV_SBI_EXT_AVAILABLE;
- return ext;
+ return NULL;
}
}
@@ -419,3 +399,26 @@ ecall_done:
return ret;
}
+
+void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu)
+{
+ struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
+ const struct kvm_riscv_sbi_extension_entry *entry;
+ const struct kvm_vcpu_sbi_extension *ext;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
+ entry = &sbi_ext[i];
+ ext = entry->ext_ptr;
+
+ if (ext->probe && !ext->probe(vcpu)) {
+ scontext->ext_status[entry->ext_idx] =
+ KVM_RISCV_SBI_EXT_UNAVAILABLE;
+ continue;
+ }
+
+ scontext->ext_status[entry->ext_idx] = ext->default_unavail ?
+ KVM_RISCV_SBI_EXT_UNAVAILABLE :
+ KVM_RISCV_SBI_EXT_AVAILABLE;
+ }
+}
diff --git a/arch/riscv/kvm/vcpu_sbi_replace.c b/arch/riscv/kvm/vcpu_sbi_replace.c
index 7c4d5d38a339..23b57c931b15 100644
--- a/arch/riscv/kvm/vcpu_sbi_replace.c
+++ b/arch/riscv/kvm/vcpu_sbi_replace.c
@@ -175,3 +175,35 @@ const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_srst = {
.extid_end = SBI_EXT_SRST,
.handler = kvm_sbi_ext_srst_handler,
};
+
+static int kvm_sbi_ext_dbcn_handler(struct kvm_vcpu *vcpu,
+ struct kvm_run *run,
+ struct kvm_vcpu_sbi_return *retdata)
+{
+ struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
+ unsigned long funcid = cp->a6;
+
+ switch (funcid) {
+ case SBI_EXT_DBCN_CONSOLE_WRITE:
+ case SBI_EXT_DBCN_CONSOLE_READ:
+ case SBI_EXT_DBCN_CONSOLE_WRITE_BYTE:
+ /*
+ * The SBI debug console functions are unconditionally
+ * forwarded to the userspace.
+ */
+ kvm_riscv_vcpu_sbi_forward(vcpu, run);
+ retdata->uexit = true;
+ break;
+ default:
+ retdata->err_val = SBI_ERR_NOT_SUPPORTED;
+ }
+
+ return 0;
+}
+
+const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_dbcn = {
+ .extid_start = SBI_EXT_DBCN,
+ .extid_end = SBI_EXT_DBCN,
+ .default_unavail = true,
+ .handler = kvm_sbi_ext_dbcn_handler,
+};
diff --git a/arch/riscv/kvm/vcpu_vector.c b/arch/riscv/kvm/vcpu_vector.c
index b430cbb69521..b339a2682f25 100644
--- a/arch/riscv/kvm/vcpu_vector.c
+++ b/arch/riscv/kvm/vcpu_vector.c
@@ -11,7 +11,7 @@
#include <linux/err.h>
#include <linux/kvm_host.h>
#include <linux/uaccess.h>
-#include <asm/hwcap.h>
+#include <asm/cpufeature.h>
#include <asm/kvm_vcpu_vector.h>
#include <asm/vector.h>
diff --git a/arch/riscv/lib/clear_page.S b/arch/riscv/lib/clear_page.S
index d7a256eb53f4..b22de1231144 100644
--- a/arch/riscv/lib/clear_page.S
+++ b/arch/riscv/lib/clear_page.S
@@ -29,41 +29,41 @@ SYM_FUNC_START(clear_page)
lw a1, riscv_cboz_block_size
add a2, a0, a2
.Lzero_loop:
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
CBOZ_ALT(11, "bltu a0, a2, .Lzero_loop; ret", "nop; nop")
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
CBOZ_ALT(10, "bltu a0, a2, .Lzero_loop; ret", "nop; nop")
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
CBOZ_ALT(9, "bltu a0, a2, .Lzero_loop; ret", "nop; nop")
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
CBOZ_ALT(8, "bltu a0, a2, .Lzero_loop; ret", "nop; nop")
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
- CBO_zero(a0)
+ CBO_ZERO(a0)
add a0, a0, a1
bltu a0, a2, .Lzero_loop
ret
diff --git a/arch/riscv/lib/memcpy.S b/arch/riscv/lib/memcpy.S
index 1a40d01a9543..44e009ec5fef 100644
--- a/arch/riscv/lib/memcpy.S
+++ b/arch/riscv/lib/memcpy.S
@@ -7,8 +7,7 @@
#include <asm/asm.h>
/* void *memcpy(void *, const void *, size_t) */
-ENTRY(__memcpy)
-WEAK(memcpy)
+SYM_FUNC_START(__memcpy)
move t6, a0 /* Preserve return value */
/* Defer to byte-oriented copy for small sizes */
@@ -105,6 +104,7 @@ WEAK(memcpy)
bltu a1, a3, 5b
6:
ret
-END(__memcpy)
+SYM_FUNC_END(__memcpy)
+SYM_FUNC_ALIAS_WEAK(memcpy, __memcpy)
SYM_FUNC_ALIAS(__pi_memcpy, __memcpy)
SYM_FUNC_ALIAS(__pi___memcpy, __memcpy)
diff --git a/arch/riscv/lib/memmove.S b/arch/riscv/lib/memmove.S
index 838ff2022fe3..cb3e2e7ef0ba 100644
--- a/arch/riscv/lib/memmove.S
+++ b/arch/riscv/lib/memmove.S
@@ -7,7 +7,6 @@
#include <asm/asm.h>
SYM_FUNC_START(__memmove)
-SYM_FUNC_START_WEAK(memmove)
/*
* Returns
* a0 - dest
@@ -26,8 +25,8 @@ SYM_FUNC_START_WEAK(memmove)
*/
/* Return if nothing to do */
- beq a0, a1, return_from_memmove
- beqz a2, return_from_memmove
+ beq a0, a1, .Lreturn_from_memmove
+ beqz a2, .Lreturn_from_memmove
/*
* Register Uses
@@ -60,7 +59,7 @@ SYM_FUNC_START_WEAK(memmove)
* small enough not to bother.
*/
andi t0, a2, -(2 * SZREG)
- beqz t0, byte_copy
+ beqz t0, .Lbyte_copy
/*
* Now solve for t5 and t6.
@@ -87,14 +86,14 @@ SYM_FUNC_START_WEAK(memmove)
*/
xor t0, a0, a1
andi t1, t0, (SZREG - 1)
- beqz t1, coaligned_copy
+ beqz t1, .Lcoaligned_copy
/* Fall through to misaligned fixup copy */
-misaligned_fixup_copy:
- bltu a1, a0, misaligned_fixup_copy_reverse
+.Lmisaligned_fixup_copy:
+ bltu a1, a0, .Lmisaligned_fixup_copy_reverse
-misaligned_fixup_copy_forward:
- jal t0, byte_copy_until_aligned_forward
+.Lmisaligned_fixup_copy_forward:
+ jal t0, .Lbyte_copy_until_aligned_forward
andi a5, a1, (SZREG - 1) /* Find the alignment offset of src (a1) */
slli a6, a5, 3 /* Multiply by 8 to convert that to bits to shift */
@@ -153,10 +152,10 @@ misaligned_fixup_copy_forward:
mv t3, t6 /* Fix the dest pointer in case the loop was broken */
add a1, t3, a5 /* Restore the src pointer */
- j byte_copy_forward /* Copy any remaining bytes */
+ j .Lbyte_copy_forward /* Copy any remaining bytes */
-misaligned_fixup_copy_reverse:
- jal t0, byte_copy_until_aligned_reverse
+.Lmisaligned_fixup_copy_reverse:
+ jal t0, .Lbyte_copy_until_aligned_reverse
andi a5, a4, (SZREG - 1) /* Find the alignment offset of src (a4) */
slli a6, a5, 3 /* Multiply by 8 to convert that to bits to shift */
@@ -215,18 +214,18 @@ misaligned_fixup_copy_reverse:
mv t4, t5 /* Fix the dest pointer in case the loop was broken */
add a4, t4, a5 /* Restore the src pointer */
- j byte_copy_reverse /* Copy any remaining bytes */
+ j .Lbyte_copy_reverse /* Copy any remaining bytes */
/*
* Simple copy loops for SZREG co-aligned memory locations.
* These also make calls to do byte copies for any unaligned
* data at their terminations.
*/
-coaligned_copy:
- bltu a1, a0, coaligned_copy_reverse
+.Lcoaligned_copy:
+ bltu a1, a0, .Lcoaligned_copy_reverse
-coaligned_copy_forward:
- jal t0, byte_copy_until_aligned_forward
+.Lcoaligned_copy_forward:
+ jal t0, .Lbyte_copy_until_aligned_forward
1:
REG_L t1, ( 0 * SZREG)(a1)
@@ -235,10 +234,10 @@ coaligned_copy_forward:
REG_S t1, (-1 * SZREG)(t3)
bne t3, t6, 1b
- j byte_copy_forward /* Copy any remaining bytes */
+ j .Lbyte_copy_forward /* Copy any remaining bytes */
-coaligned_copy_reverse:
- jal t0, byte_copy_until_aligned_reverse
+.Lcoaligned_copy_reverse:
+ jal t0, .Lbyte_copy_until_aligned_reverse
1:
REG_L t1, (-1 * SZREG)(a4)
@@ -247,7 +246,7 @@ coaligned_copy_reverse:
REG_S t1, ( 0 * SZREG)(t4)
bne t4, t5, 1b
- j byte_copy_reverse /* Copy any remaining bytes */
+ j .Lbyte_copy_reverse /* Copy any remaining bytes */
/*
* These are basically sub-functions within the function. They
@@ -258,7 +257,7 @@ coaligned_copy_reverse:
* up from where they were left and we avoid code duplication
* without any overhead except the call in and return jumps.
*/
-byte_copy_until_aligned_forward:
+.Lbyte_copy_until_aligned_forward:
beq t3, t5, 2f
1:
lb t1, 0(a1)
@@ -269,7 +268,7 @@ byte_copy_until_aligned_forward:
2:
jalr zero, 0x0(t0) /* Return to multibyte copy loop */
-byte_copy_until_aligned_reverse:
+.Lbyte_copy_until_aligned_reverse:
beq t4, t6, 2f
1:
lb t1, -1(a4)
@@ -285,10 +284,10 @@ byte_copy_until_aligned_reverse:
* These will byte copy until they reach the end of data to copy.
* At that point, they will call to return from memmove.
*/
-byte_copy:
- bltu a1, a0, byte_copy_reverse
+.Lbyte_copy:
+ bltu a1, a0, .Lbyte_copy_reverse
-byte_copy_forward:
+.Lbyte_copy_forward:
beq t3, t4, 2f
1:
lb t1, 0(a1)
@@ -299,7 +298,7 @@ byte_copy_forward:
2:
ret
-byte_copy_reverse:
+.Lbyte_copy_reverse:
beq t4, t3, 2f
1:
lb t1, -1(a4)
@@ -309,10 +308,10 @@ byte_copy_reverse:
bne t4, t3, 1b
2:
-return_from_memmove:
+.Lreturn_from_memmove:
ret
-SYM_FUNC_END(memmove)
SYM_FUNC_END(__memmove)
+SYM_FUNC_ALIAS_WEAK(memmove, __memmove)
SYM_FUNC_ALIAS(__pi_memmove, __memmove)
SYM_FUNC_ALIAS(__pi___memmove, __memmove)
diff --git a/arch/riscv/lib/memset.S b/arch/riscv/lib/memset.S
index 34c5360c6705..35f358e70bdb 100644
--- a/arch/riscv/lib/memset.S
+++ b/arch/riscv/lib/memset.S
@@ -8,8 +8,7 @@
#include <asm/asm.h>
/* void *memset(void *, int, size_t) */
-ENTRY(__memset)
-WEAK(memset)
+SYM_FUNC_START(__memset)
move t0, a0 /* Preserve return value */
/* Defer to byte-oriented fill for small sizes */
@@ -110,4 +109,5 @@ WEAK(memset)
bltu t0, a3, 5b
6:
ret
-END(__memset)
+SYM_FUNC_END(__memset)
+SYM_FUNC_ALIAS_WEAK(memset, __memset)
diff --git a/arch/riscv/lib/uaccess.S b/arch/riscv/lib/uaccess.S
index 09b47ebacf2e..3ab438f30d13 100644
--- a/arch/riscv/lib/uaccess.S
+++ b/arch/riscv/lib/uaccess.S
@@ -10,8 +10,7 @@
_asm_extable 100b, \lbl
.endm
-ENTRY(__asm_copy_to_user)
-ENTRY(__asm_copy_from_user)
+SYM_FUNC_START(__asm_copy_to_user)
/* Enable access to user memory */
li t6, SR_SUM
@@ -181,13 +180,13 @@ ENTRY(__asm_copy_from_user)
csrc CSR_STATUS, t6
sub a0, t5, a0
ret
-ENDPROC(__asm_copy_to_user)
-ENDPROC(__asm_copy_from_user)
+SYM_FUNC_END(__asm_copy_to_user)
EXPORT_SYMBOL(__asm_copy_to_user)
+SYM_FUNC_ALIAS(__asm_copy_from_user, __asm_copy_to_user)
EXPORT_SYMBOL(__asm_copy_from_user)
-ENTRY(__clear_user)
+SYM_FUNC_START(__clear_user)
/* Enable access to user memory */
li t6, SR_SUM
@@ -233,5 +232,5 @@ ENTRY(__clear_user)
csrc CSR_STATUS, t6
sub a0, a3, a0
ret
-ENDPROC(__clear_user)
+SYM_FUNC_END(__clear_user)
EXPORT_SYMBOL(__clear_user)
diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
index 9c454f90fd3d..3a4dfc8babcf 100644
--- a/arch/riscv/mm/Makefile
+++ b/arch/riscv/mm/Makefile
@@ -36,3 +36,4 @@ endif
obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
obj-$(CONFIG_RISCV_DMA_NONCOHERENT) += dma-noncoherent.o
+obj-$(CONFIG_RISCV_NONSTANDARD_CACHE_OPS) += cache-ops.o
diff --git a/arch/riscv/mm/cache-ops.c b/arch/riscv/mm/cache-ops.c
new file mode 100644
index 000000000000..a993ad11d0ec
--- /dev/null
+++ b/arch/riscv/mm/cache-ops.c
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ */
+
+#include <asm/dma-noncoherent.h>
+
+struct riscv_nonstd_cache_ops noncoherent_cache_ops __ro_after_init;
+
+void
+riscv_noncoherent_register_cache_ops(const struct riscv_nonstd_cache_ops *ops)
+{
+ if (!ops)
+ return;
+ noncoherent_cache_ops = *ops;
+}
+EXPORT_SYMBOL_GPL(riscv_noncoherent_register_cache_ops);
diff --git a/arch/riscv/mm/cacheflush.c b/arch/riscv/mm/cacheflush.c
index f1387272a551..55a34f2020a8 100644
--- a/arch/riscv/mm/cacheflush.c
+++ b/arch/riscv/mm/cacheflush.c
@@ -3,7 +3,9 @@
* Copyright (C) 2017 SiFive
*/
+#include <linux/acpi.h>
#include <linux/of.h>
+#include <asm/acpi.h>
#include <asm/cacheflush.h>
#ifdef CONFIG_SMP
@@ -124,13 +126,24 @@ void __init riscv_init_cbo_blocksizes(void)
unsigned long cbom_hartid, cboz_hartid;
u32 cbom_block_size = 0, cboz_block_size = 0;
struct device_node *node;
+ struct acpi_table_header *rhct;
+ acpi_status status;
+
+ if (acpi_disabled) {
+ for_each_of_cpu_node(node) {
+ /* set block-size for cbom and/or cboz extension if available */
+ cbo_get_block_size(node, "riscv,cbom-block-size",
+ &cbom_block_size, &cbom_hartid);
+ cbo_get_block_size(node, "riscv,cboz-block-size",
+ &cboz_block_size, &cboz_hartid);
+ }
+ } else {
+ status = acpi_get_table(ACPI_SIG_RHCT, 0, &rhct);
+ if (ACPI_FAILURE(status))
+ return;
- for_each_of_cpu_node(node) {
- /* set block-size for cbom and/or cboz extension if available */
- cbo_get_block_size(node, "riscv,cbom-block-size",
- &cbom_block_size, &cbom_hartid);
- cbo_get_block_size(node, "riscv,cboz-block-size",
- &cboz_block_size, &cboz_hartid);
+ acpi_get_cbo_block_size(rhct, &cbom_block_size, &cboz_block_size, NULL);
+ acpi_put_table((struct acpi_table_header *)rhct);
}
if (cbom_block_size)
diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
index b76e7e192eb1..4e4e469b8dd6 100644
--- a/arch/riscv/mm/dma-noncoherent.c
+++ b/arch/riscv/mm/dma-noncoherent.c
@@ -15,12 +15,6 @@ static bool noncoherent_supported __ro_after_init;
int dma_cache_alignment __ro_after_init = ARCH_DMA_MINALIGN;
EXPORT_SYMBOL_GPL(dma_cache_alignment);
-struct riscv_nonstd_cache_ops noncoherent_cache_ops __ro_after_init = {
- .wback = NULL,
- .inv = NULL,
- .wback_inv = NULL,
-};
-
static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size)
{
void *vaddr = phys_to_virt(paddr);
@@ -31,7 +25,7 @@ static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size)
return;
}
#endif
- ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size);
+ ALT_CMO_OP(CLEAN, vaddr, size, riscv_cbom_block_size);
}
static inline void arch_dma_cache_inv(phys_addr_t paddr, size_t size)
@@ -45,7 +39,7 @@ static inline void arch_dma_cache_inv(phys_addr_t paddr, size_t size)
}
#endif
- ALT_CMO_OP(inval, vaddr, size, riscv_cbom_block_size);
+ ALT_CMO_OP(INVAL, vaddr, size, riscv_cbom_block_size);
}
static inline void arch_dma_cache_wback_inv(phys_addr_t paddr, size_t size)
@@ -59,7 +53,7 @@ static inline void arch_dma_cache_wback_inv(phys_addr_t paddr, size_t size)
}
#endif
- ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size);
+ ALT_CMO_OP(FLUSH, vaddr, size, riscv_cbom_block_size);
}
static inline bool arch_sync_dma_clean_before_fromdevice(void)
@@ -131,7 +125,7 @@ void arch_dma_prep_coherent(struct page *page, size_t size)
}
#endif
- ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size);
+ ALT_CMO_OP(FLUSH, flush_addr, size, riscv_cbom_block_size);
}
void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
@@ -162,12 +156,3 @@ void __init riscv_set_dma_cache_alignment(void)
if (!noncoherent_supported)
dma_cache_alignment = 1;
}
-
-void riscv_noncoherent_register_cache_ops(const struct riscv_nonstd_cache_ops *ops)
-{
- if (!ops)
- return;
-
- noncoherent_cache_ops = *ops;
-}
-EXPORT_SYMBOL_GPL(riscv_noncoherent_register_cache_ops);
diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c
index 6115d7514972..90d4ba36d1d0 100644
--- a/arch/riscv/mm/fault.c
+++ b/arch/riscv/mm/fault.c
@@ -72,7 +72,7 @@ static inline void mm_fault_error(struct pt_regs *regs, unsigned long addr, vm_f
}
pagefault_out_of_memory();
return;
- } else if (fault & VM_FAULT_SIGBUS) {
+ } else if (fault & (VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)) {
/* Kernel mode? Handle exceptions or die */
if (!user_mode(regs)) {
no_context(regs, addr);
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index e4a2ace92dbe..b52f0210481f 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -183,15 +183,22 @@ void set_huge_pte_at(struct mm_struct *mm,
pte_t pte,
unsigned long sz)
{
+ unsigned long hugepage_shift;
int i, pte_num;
- if (!pte_napot(pte)) {
- set_pte_at(mm, addr, ptep, pte);
- return;
- }
+ if (sz >= PGDIR_SIZE)
+ hugepage_shift = PGDIR_SHIFT;
+ else if (sz >= P4D_SIZE)
+ hugepage_shift = P4D_SHIFT;
+ else if (sz >= PUD_SIZE)
+ hugepage_shift = PUD_SHIFT;
+ else if (sz >= PMD_SIZE)
+ hugepage_shift = PMD_SHIFT;
+ else
+ hugepage_shift = PAGE_SHIFT;
- pte_num = napot_pte_num(napot_cont_order(pte));
- for (i = 0; i < pte_num; i++, ptep++, addr += PAGE_SIZE)
+ pte_num = sz >> hugepage_shift;
+ for (i = 0; i < pte_num; i++, ptep++, addr += (1 << hugepage_shift))
set_pte_at(mm, addr, ptep, pte);
}
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 0798bd861dcb..2e011cbddf3a 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -49,10 +49,12 @@ u64 satp_mode __ro_after_init = SATP_MODE_32;
#endif
EXPORT_SYMBOL(satp_mode);
+#ifdef CONFIG_64BIT
bool pgtable_l4_enabled = IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_XIP_KERNEL);
bool pgtable_l5_enabled = IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_XIP_KERNEL);
EXPORT_SYMBOL(pgtable_l4_enabled);
EXPORT_SYMBOL(pgtable_l5_enabled);
+#endif
phys_addr_t phys_ram_base __ro_after_init;
EXPORT_SYMBOL(phys_ram_base);
@@ -65,7 +67,7 @@ extern char _start[];
void *_dtb_early_va __initdata;
uintptr_t _dtb_early_pa __initdata;
-static phys_addr_t dma32_phys_limit __initdata;
+phys_addr_t dma32_phys_limit __initdata;
static void __init zone_sizes_init(void)
{
@@ -664,16 +666,16 @@ void __init create_pgd_mapping(pgd_t *pgdp,
static uintptr_t __init best_map_size(phys_addr_t pa, uintptr_t va,
phys_addr_t size)
{
- if (!(pa & (PGDIR_SIZE - 1)) && !(va & (PGDIR_SIZE - 1)) && size >= PGDIR_SIZE)
- return PGDIR_SIZE;
-
- if (!(pa & (P4D_SIZE - 1)) && !(va & (P4D_SIZE - 1)) && size >= P4D_SIZE)
+ if (pgtable_l5_enabled &&
+ !(pa & (P4D_SIZE - 1)) && !(va & (P4D_SIZE - 1)) && size >= P4D_SIZE)
return P4D_SIZE;
- if (!(pa & (PUD_SIZE - 1)) && !(va & (PUD_SIZE - 1)) && size >= PUD_SIZE)
+ if (pgtable_l4_enabled &&
+ !(pa & (PUD_SIZE - 1)) && !(va & (PUD_SIZE - 1)) && size >= PUD_SIZE)
return PUD_SIZE;
- if (!(pa & (PMD_SIZE - 1)) && !(va & (PMD_SIZE - 1)) && size >= PMD_SIZE)
+ if (IS_ENABLED(CONFIG_64BIT) &&
+ !(pa & (PMD_SIZE - 1)) && !(va & (PMD_SIZE - 1)) && size >= PMD_SIZE)
return PMD_SIZE;
return PAGE_SIZE;
@@ -1333,28 +1335,6 @@ static inline void setup_vm_final(void)
}
#endif /* CONFIG_MMU */
-/* Reserve 128M low memory by default for swiotlb buffer */
-#define DEFAULT_CRASH_KERNEL_LOW_SIZE (128UL << 20)
-
-static int __init reserve_crashkernel_low(unsigned long long low_size)
-{
- unsigned long long low_base;
-
- low_base = memblock_phys_alloc_range(low_size, PMD_SIZE, 0, dma32_phys_limit);
- if (!low_base) {
- pr_err("cannot allocate crashkernel low memory (size:0x%llx).\n", low_size);
- return -ENOMEM;
- }
-
- pr_info("crashkernel low memory reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
- low_base, low_base + low_size, low_size >> 20);
-
- crashk_low_res.start = low_base;
- crashk_low_res.end = low_base + low_size - 1;
-
- return 0;
-}
-
/*
* reserve_crashkernel() - reserves memory for crash kernel
*
@@ -1362,122 +1342,25 @@ static int __init reserve_crashkernel_low(unsigned long long low_size)
* line parameter. The memory reserved is used by dump capture kernel when
* primary kernel is crashing.
*/
-static void __init reserve_crashkernel(void)
+static void __init arch_reserve_crashkernel(void)
{
- unsigned long long crash_base = 0;
- unsigned long long crash_size = 0;
- unsigned long long crash_low_size = 0;
- unsigned long search_start = memblock_start_of_DRAM();
- unsigned long search_end = (unsigned long)dma32_phys_limit;
+ unsigned long long low_size = 0;
+ unsigned long long crash_base, crash_size;
char *cmdline = boot_command_line;
- bool fixed_base = false;
bool high = false;
-
- int ret = 0;
+ int ret;
if (!IS_ENABLED(CONFIG_KEXEC_CORE))
return;
- /*
- * Don't reserve a region for a crash kernel on a crash kernel
- * since it doesn't make much sense and we have limited memory
- * resources.
- */
- if (is_kdump_kernel()) {
- pr_info("crashkernel: ignoring reservation request\n");
- return;
- }
ret = parse_crashkernel(cmdline, memblock_phys_mem_size(),
- &crash_size, &crash_base);
- if (ret == -ENOENT) {
- /* Fallback to crashkernel=X,[high,low] */
- ret = parse_crashkernel_high(cmdline, 0, &crash_size, &crash_base);
- if (ret || !crash_size)
- return;
-
- /*
- * crashkernel=Y,low is valid only when crashkernel=X,high
- * is passed.
- */
- ret = parse_crashkernel_low(cmdline, 0, &crash_low_size, &crash_base);
- if (ret == -ENOENT)
- crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
- else if (ret)
- return;
-
- search_start = (unsigned long)dma32_phys_limit;
- search_end = memblock_end_of_DRAM();
- high = true;
- } else if (ret || !crash_size) {
- /* Invalid argument value specified */
- return;
- }
-
- crash_size = PAGE_ALIGN(crash_size);
-
- if (crash_base) {
- fixed_base = true;
- search_start = crash_base;
- search_end = crash_base + crash_size;
- }
-
- /*
- * Current riscv boot protocol requires 2MB alignment for
- * RV64 and 4MB alignment for RV32 (hugepage size)
- *
- * Try to alloc from 32bit addressible physical memory so that
- * swiotlb can work on the crash kernel.
- */
- crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE,
- search_start, search_end);
- if (crash_base == 0) {
- /*
- * For crashkernel=size[KMG]@offset[KMG], print out failure
- * message if can't reserve the specified region.
- */
- if (fixed_base) {
- pr_warn("crashkernel: allocating failed with given size@offset\n");
- return;
- }
-
- if (high) {
- /*
- * For crashkernel=size[KMG],high, if the first attempt was
- * for high memory, fall back to low memory.
- */
- search_start = memblock_start_of_DRAM();
- search_end = (unsigned long)dma32_phys_limit;
- } else {
- /*
- * For crashkernel=size[KMG], if the first attempt was for
- * low memory, fall back to high memory, the minimum required
- * low memory will be reserved later.
- */
- search_start = (unsigned long)dma32_phys_limit;
- search_end = memblock_end_of_DRAM();
- crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
- }
-
- crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE,
- search_start, search_end);
- if (crash_base == 0) {
- pr_warn("crashkernel: couldn't allocate %lldKB\n",
- crash_size >> 10);
- return;
- }
- }
-
- if ((crash_base >= dma32_phys_limit) && crash_low_size &&
- reserve_crashkernel_low(crash_low_size)) {
- memblock_phys_free(crash_base, crash_size);
+ &crash_size, &crash_base,
+ &low_size, &high);
+ if (ret)
return;
- }
-
- pr_info("crashkernel: reserved 0x%016llx - 0x%016llx (%lld MB)\n",
- crash_base, crash_base + crash_size, crash_size >> 20);
- crashk_res.start = crash_base;
- crashk_res.end = crash_base + crash_size - 1;
+ reserve_crashkernel_generic(cmdline, crash_size, crash_base,
+ low_size, high);
}
void __init paging_init(void)
@@ -1495,7 +1378,7 @@ void __init misc_mem_init(void)
arch_numa_init();
sparse_init();
zone_sizes_init();
- reserve_crashkernel();
+ arch_reserve_crashkernel();
memblock_dump_all();
}
diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
index 161d0b34c2cb..fc5fc4f785c4 100644
--- a/arch/riscv/mm/pageattr.c
+++ b/arch/riscv/mm/pageattr.c
@@ -5,6 +5,7 @@
#include <linux/pagewalk.h>
#include <linux/pgtable.h>
+#include <linux/vmalloc.h>
#include <asm/tlbflush.h>
#include <asm/bitops.h>
#include <asm/set_memory.h>
@@ -25,19 +26,6 @@ static unsigned long set_pageattr_masks(unsigned long val, struct mm_walk *walk)
return new_val;
}
-static int pageattr_pgd_entry(pgd_t *pgd, unsigned long addr,
- unsigned long next, struct mm_walk *walk)
-{
- pgd_t val = READ_ONCE(*pgd);
-
- if (pgd_leaf(val)) {
- val = __pgd(set_pageattr_masks(pgd_val(val), walk));
- set_pgd(pgd, val);
- }
-
- return 0;
-}
-
static int pageattr_p4d_entry(p4d_t *p4d, unsigned long addr,
unsigned long next, struct mm_walk *walk)
{
@@ -96,7 +84,6 @@ static int pageattr_pte_hole(unsigned long addr, unsigned long next,
}
static const struct mm_walk_ops pageattr_ops = {
- .pgd_entry = pageattr_pgd_entry,
.p4d_entry = pageattr_p4d_entry,
.pud_entry = pageattr_pud_entry,
.pmd_entry = pageattr_pmd_entry,
@@ -105,12 +92,181 @@ static const struct mm_walk_ops pageattr_ops = {
.walk_lock = PGWALK_RDLOCK,
};
+#ifdef CONFIG_64BIT
+static int __split_linear_mapping_pmd(pud_t *pudp,
+ unsigned long vaddr, unsigned long end)
+{
+ pmd_t *pmdp;
+ unsigned long next;
+
+ pmdp = pmd_offset(pudp, vaddr);
+
+ do {
+ next = pmd_addr_end(vaddr, end);
+
+ if (next - vaddr >= PMD_SIZE &&
+ vaddr <= (vaddr & PMD_MASK) && end >= next)
+ continue;
+
+ if (pmd_leaf(*pmdp)) {
+ struct page *pte_page;
+ unsigned long pfn = _pmd_pfn(*pmdp);
+ pgprot_t prot = __pgprot(pmd_val(*pmdp) & ~_PAGE_PFN_MASK);
+ pte_t *ptep_new;
+ int i;
+
+ pte_page = alloc_page(GFP_KERNEL);
+ if (!pte_page)
+ return -ENOMEM;
+
+ ptep_new = (pte_t *)page_address(pte_page);
+ for (i = 0; i < PTRS_PER_PTE; ++i, ++ptep_new)
+ set_pte(ptep_new, pfn_pte(pfn + i, prot));
+
+ smp_wmb();
+
+ set_pmd(pmdp, pfn_pmd(page_to_pfn(pte_page), PAGE_TABLE));
+ }
+ } while (pmdp++, vaddr = next, vaddr != end);
+
+ return 0;
+}
+
+static int __split_linear_mapping_pud(p4d_t *p4dp,
+ unsigned long vaddr, unsigned long end)
+{
+ pud_t *pudp;
+ unsigned long next;
+ int ret;
+
+ pudp = pud_offset(p4dp, vaddr);
+
+ do {
+ next = pud_addr_end(vaddr, end);
+
+ if (next - vaddr >= PUD_SIZE &&
+ vaddr <= (vaddr & PUD_MASK) && end >= next)
+ continue;
+
+ if (pud_leaf(*pudp)) {
+ struct page *pmd_page;
+ unsigned long pfn = _pud_pfn(*pudp);
+ pgprot_t prot = __pgprot(pud_val(*pudp) & ~_PAGE_PFN_MASK);
+ pmd_t *pmdp_new;
+ int i;
+
+ pmd_page = alloc_page(GFP_KERNEL);
+ if (!pmd_page)
+ return -ENOMEM;
+
+ pmdp_new = (pmd_t *)page_address(pmd_page);
+ for (i = 0; i < PTRS_PER_PMD; ++i, ++pmdp_new)
+ set_pmd(pmdp_new,
+ pfn_pmd(pfn + ((i * PMD_SIZE) >> PAGE_SHIFT), prot));
+
+ smp_wmb();
+
+ set_pud(pudp, pfn_pud(page_to_pfn(pmd_page), PAGE_TABLE));
+ }
+
+ ret = __split_linear_mapping_pmd(pudp, vaddr, next);
+ if (ret)
+ return ret;
+ } while (pudp++, vaddr = next, vaddr != end);
+
+ return 0;
+}
+
+static int __split_linear_mapping_p4d(pgd_t *pgdp,
+ unsigned long vaddr, unsigned long end)
+{
+ p4d_t *p4dp;
+ unsigned long next;
+ int ret;
+
+ p4dp = p4d_offset(pgdp, vaddr);
+
+ do {
+ next = p4d_addr_end(vaddr, end);
+
+ /*
+ * If [vaddr; end] contains [vaddr & P4D_MASK; next], we don't
+ * need to split, we'll change the protections on the whole P4D.
+ */
+ if (next - vaddr >= P4D_SIZE &&
+ vaddr <= (vaddr & P4D_MASK) && end >= next)
+ continue;
+
+ if (p4d_leaf(*p4dp)) {
+ struct page *pud_page;
+ unsigned long pfn = _p4d_pfn(*p4dp);
+ pgprot_t prot = __pgprot(p4d_val(*p4dp) & ~_PAGE_PFN_MASK);
+ pud_t *pudp_new;
+ int i;
+
+ pud_page = alloc_page(GFP_KERNEL);
+ if (!pud_page)
+ return -ENOMEM;
+
+ /*
+ * Fill the pud level with leaf puds that have the same
+ * protections as the leaf p4d.
+ */
+ pudp_new = (pud_t *)page_address(pud_page);
+ for (i = 0; i < PTRS_PER_PUD; ++i, ++pudp_new)
+ set_pud(pudp_new,
+ pfn_pud(pfn + ((i * PUD_SIZE) >> PAGE_SHIFT), prot));
+
+ /*
+ * Make sure the pud filling is not reordered with the
+ * p4d store which could result in seeing a partially
+ * filled pud level.
+ */
+ smp_wmb();
+
+ set_p4d(p4dp, pfn_p4d(page_to_pfn(pud_page), PAGE_TABLE));
+ }
+
+ ret = __split_linear_mapping_pud(p4dp, vaddr, next);
+ if (ret)
+ return ret;
+ } while (p4dp++, vaddr = next, vaddr != end);
+
+ return 0;
+}
+
+static int __split_linear_mapping_pgd(pgd_t *pgdp,
+ unsigned long vaddr,
+ unsigned long end)
+{
+ unsigned long next;
+ int ret;
+
+ do {
+ next = pgd_addr_end(vaddr, end);
+ /* We never use PGD mappings for the linear mapping */
+ ret = __split_linear_mapping_p4d(pgdp, vaddr, next);
+ if (ret)
+ return ret;
+ } while (pgdp++, vaddr = next, vaddr != end);
+
+ return 0;
+}
+
+static int split_linear_mapping(unsigned long start, unsigned long end)
+{
+ return __split_linear_mapping_pgd(pgd_offset_k(start), start, end);
+}
+#endif /* CONFIG_64BIT */
+
static int __set_memory(unsigned long addr, int numpages, pgprot_t set_mask,
pgprot_t clear_mask)
{
int ret;
unsigned long start = addr;
unsigned long end = start + PAGE_SIZE * numpages;
+ unsigned long __maybe_unused lm_start;
+ unsigned long __maybe_unused lm_end;
struct pageattr_masks masks = {
.set_mask = set_mask,
.clear_mask = clear_mask
@@ -120,11 +276,67 @@ static int __set_memory(unsigned long addr, int numpages, pgprot_t set_mask,
return 0;
mmap_write_lock(&init_mm);
+
+#ifdef CONFIG_64BIT
+ /*
+ * We are about to change the permissions of a kernel mapping, we must
+ * apply the same changes to its linear mapping alias, which may imply
+ * splitting a huge mapping.
+ */
+
+ if (is_vmalloc_or_module_addr((void *)start)) {
+ struct vm_struct *area = NULL;
+ int i, page_start;
+
+ area = find_vm_area((void *)start);
+ page_start = (start - (unsigned long)area->addr) >> PAGE_SHIFT;
+
+ for (i = page_start; i < page_start + numpages; ++i) {
+ lm_start = (unsigned long)page_address(area->pages[i]);
+ lm_end = lm_start + PAGE_SIZE;
+
+ ret = split_linear_mapping(lm_start, lm_end);
+ if (ret)
+ goto unlock;
+
+ ret = walk_page_range_novma(&init_mm, lm_start, lm_end,
+ &pageattr_ops, NULL, &masks);
+ if (ret)
+ goto unlock;
+ }
+ } else if (is_kernel_mapping(start) || is_linear_mapping(start)) {
+ lm_start = (unsigned long)lm_alias(start);
+ lm_end = (unsigned long)lm_alias(end);
+
+ ret = split_linear_mapping(lm_start, lm_end);
+ if (ret)
+ goto unlock;
+
+ ret = walk_page_range_novma(&init_mm, lm_start, lm_end,
+ &pageattr_ops, NULL, &masks);
+ if (ret)
+ goto unlock;
+ }
+
ret = walk_page_range_novma(&init_mm, start, end, &pageattr_ops, NULL,
&masks);
+
+unlock:
+ mmap_write_unlock(&init_mm);
+
+ /*
+ * We can't use flush_tlb_kernel_range() here as we may have split a
+ * hugepage that is larger than that, so let's flush everything.
+ */
+ flush_tlb_all();
+#else
+ ret = walk_page_range_novma(&init_mm, start, end, &pageattr_ops, NULL,
+ &masks);
+
mmap_write_unlock(&init_mm);
flush_tlb_kernel_range(start, end);
+#endif
return ret;
}
@@ -159,36 +371,14 @@ int set_memory_nx(unsigned long addr, int numpages)
int set_direct_map_invalid_noflush(struct page *page)
{
- int ret;
- unsigned long start = (unsigned long)page_address(page);
- unsigned long end = start + PAGE_SIZE;
- struct pageattr_masks masks = {
- .set_mask = __pgprot(0),
- .clear_mask = __pgprot(_PAGE_PRESENT)
- };
-
- mmap_read_lock(&init_mm);
- ret = walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
- mmap_read_unlock(&init_mm);
-
- return ret;
+ return __set_memory((unsigned long)page_address(page), 1,
+ __pgprot(0), __pgprot(_PAGE_PRESENT));
}
int set_direct_map_default_noflush(struct page *page)
{
- int ret;
- unsigned long start = (unsigned long)page_address(page);
- unsigned long end = start + PAGE_SIZE;
- struct pageattr_masks masks = {
- .set_mask = PAGE_KERNEL,
- .clear_mask = __pgprot(0)
- };
-
- mmap_read_lock(&init_mm);
- ret = walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
- mmap_read_unlock(&init_mm);
-
- return ret;
+ return __set_memory((unsigned long)page_address(page), 1,
+ PAGE_KERNEL, __pgprot(0));
}
#ifdef CONFIG_DEBUG_PAGEALLOC
diff --git a/arch/riscv/mm/pmem.c b/arch/riscv/mm/pmem.c
index c5fc5ec96f6d..370a422ede11 100644
--- a/arch/riscv/mm/pmem.c
+++ b/arch/riscv/mm/pmem.c
@@ -17,7 +17,7 @@ void arch_wb_cache_pmem(void *addr, size_t size)
return;
}
#endif
- ALT_CMO_OP(clean, addr, size, riscv_cbom_block_size);
+ ALT_CMO_OP(CLEAN, addr, size, riscv_cbom_block_size);
}
EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
@@ -29,6 +29,6 @@ void arch_invalidate_pmem(void *addr, size_t size)
return;
}
#endif
- ALT_CMO_OP(inval, addr, size, riscv_cbom_block_size);
+ ALT_CMO_OP(INVAL, addr, size, riscv_cbom_block_size);
}
EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
diff --git a/arch/riscv/mm/ptdump.c b/arch/riscv/mm/ptdump.c
index 20a9f991a6d7..657c27bc07a7 100644
--- a/arch/riscv/mm/ptdump.c
+++ b/arch/riscv/mm/ptdump.c
@@ -129,55 +129,55 @@ static struct ptd_mm_info efi_ptd_info = {
/* Page Table Entry */
struct prot_bits {
u64 mask;
- u64 val;
const char *set;
const char *clear;
};
static const struct prot_bits pte_bits[] = {
{
+#ifdef CONFIG_64BIT
+ .mask = _PAGE_NAPOT,
+ .set = "N",
+ .clear = ".",
+ }, {
+ .mask = _PAGE_MTMASK_SVPBMT,
+ .set = "MT(%s)",
+ .clear = " .. ",
+ }, {
+#endif
.mask = _PAGE_SOFT,
- .val = _PAGE_SOFT,
- .set = "RSW",
- .clear = " ",
+ .set = "RSW(%d)",
+ .clear = " .. ",
}, {
.mask = _PAGE_DIRTY,
- .val = _PAGE_DIRTY,
.set = "D",
.clear = ".",
}, {
.mask = _PAGE_ACCESSED,
- .val = _PAGE_ACCESSED,
.set = "A",
.clear = ".",
}, {
.mask = _PAGE_GLOBAL,
- .val = _PAGE_GLOBAL,
.set = "G",
.clear = ".",
}, {
.mask = _PAGE_USER,
- .val = _PAGE_USER,
.set = "U",
.clear = ".",
}, {
.mask = _PAGE_EXEC,
- .val = _PAGE_EXEC,
.set = "X",
.clear = ".",
}, {
.mask = _PAGE_WRITE,
- .val = _PAGE_WRITE,
.set = "W",
.clear = ".",
}, {
.mask = _PAGE_READ,
- .val = _PAGE_READ,
.set = "R",
.clear = ".",
}, {
.mask = _PAGE_PRESENT,
- .val = _PAGE_PRESENT,
.set = "V",
.clear = ".",
}
@@ -208,15 +208,30 @@ static void dump_prot(struct pg_state *st)
unsigned int i;
for (i = 0; i < ARRAY_SIZE(pte_bits); i++) {
- const char *s;
+ char s[7];
+ unsigned long val;
- if ((st->current_prot & pte_bits[i].mask) == pte_bits[i].val)
- s = pte_bits[i].set;
- else
- s = pte_bits[i].clear;
+ val = st->current_prot & pte_bits[i].mask;
+ if (val) {
+ if (pte_bits[i].mask == _PAGE_SOFT)
+ sprintf(s, pte_bits[i].set, val >> 8);
+#ifdef CONFIG_64BIT
+ else if (pte_bits[i].mask == _PAGE_MTMASK_SVPBMT) {
+ if (val == _PAGE_NOCACHE_SVPBMT)
+ sprintf(s, pte_bits[i].set, "NC");
+ else if (val == _PAGE_IO_SVPBMT)
+ sprintf(s, pte_bits[i].set, "IO");
+ else
+ sprintf(s, pte_bits[i].set, "??");
+ }
+#endif
+ else
+ sprintf(s, "%s", pte_bits[i].set);
+ } else {
+ sprintf(s, "%s", pte_bits[i].clear);
+ }
- if (s)
- pt_dump_seq_printf(st->seq, " %s", s);
+ pt_dump_seq_printf(st->seq, " %s", s);
}
}
@@ -384,6 +399,9 @@ static int __init ptdump_init(void)
kernel_ptd_info.base_addr = KERN_VIRT_START;
+ pg_level[1].name = pgtable_l5_enabled ? "P4D" : "PGD";
+ pg_level[2].name = pgtable_l4_enabled ? "PUD" : "PGD";
+
for (i = 0; i < ARRAY_SIZE(pg_level); i++)
for (j = 0; j < ARRAY_SIZE(pte_bits); j++)
pg_level[i].mask |= pte_bits[j].mask;
diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
index 77be59aadc73..e6659d7368b3 100644
--- a/arch/riscv/mm/tlbflush.c
+++ b/arch/riscv/mm/tlbflush.c
@@ -3,33 +3,56 @@
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/sched.h>
+#include <linux/hugetlb.h>
#include <asm/sbi.h>
#include <asm/mmu_context.h>
static inline void local_flush_tlb_all_asid(unsigned long asid)
{
- __asm__ __volatile__ ("sfence.vma x0, %0"
- :
- : "r" (asid)
- : "memory");
+ if (asid != FLUSH_TLB_NO_ASID)
+ __asm__ __volatile__ ("sfence.vma x0, %0"
+ :
+ : "r" (asid)
+ : "memory");
+ else
+ local_flush_tlb_all();
}
static inline void local_flush_tlb_page_asid(unsigned long addr,
unsigned long asid)
{
- __asm__ __volatile__ ("sfence.vma %0, %1"
- :
- : "r" (addr), "r" (asid)
- : "memory");
+ if (asid != FLUSH_TLB_NO_ASID)
+ __asm__ __volatile__ ("sfence.vma %0, %1"
+ :
+ : "r" (addr), "r" (asid)
+ : "memory");
+ else
+ local_flush_tlb_page(addr);
}
-static inline void local_flush_tlb_range(unsigned long start,
- unsigned long size, unsigned long stride)
+/*
+ * Flush entire TLB if number of entries to be flushed is greater
+ * than the threshold below.
+ */
+static unsigned long tlb_flush_all_threshold __read_mostly = 64;
+
+static void local_flush_tlb_range_threshold_asid(unsigned long start,
+ unsigned long size,
+ unsigned long stride,
+ unsigned long asid)
{
- if (size <= stride)
- local_flush_tlb_page(start);
- else
- local_flush_tlb_all();
+ unsigned long nr_ptes_in_range = DIV_ROUND_UP(size, stride);
+ int i;
+
+ if (nr_ptes_in_range > tlb_flush_all_threshold) {
+ local_flush_tlb_all_asid(asid);
+ return;
+ }
+
+ for (i = 0; i < nr_ptes_in_range; ++i) {
+ local_flush_tlb_page_asid(start, asid);
+ start += stride;
+ }
}
static inline void local_flush_tlb_range_asid(unsigned long start,
@@ -37,8 +60,10 @@ static inline void local_flush_tlb_range_asid(unsigned long start,
{
if (size <= stride)
local_flush_tlb_page_asid(start, asid);
- else
+ else if (size == FLUSH_TLB_MAX_SIZE)
local_flush_tlb_all_asid(asid);
+ else
+ local_flush_tlb_range_threshold_asid(start, size, stride, asid);
}
static void __ipi_flush_tlb_all(void *info)
@@ -51,7 +76,7 @@ void flush_tlb_all(void)
if (riscv_use_ipi_for_rfence())
on_each_cpu(__ipi_flush_tlb_all, NULL, 1);
else
- sbi_remote_sfence_vma(NULL, 0, -1);
+ sbi_remote_sfence_vma_asid(NULL, 0, FLUSH_TLB_MAX_SIZE, FLUSH_TLB_NO_ASID);
}
struct flush_tlb_range_data {
@@ -68,68 +93,62 @@ static void __ipi_flush_tlb_range_asid(void *info)
local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid);
}
-static void __ipi_flush_tlb_range(void *info)
-{
- struct flush_tlb_range_data *d = info;
-
- local_flush_tlb_range(d->start, d->size, d->stride);
-}
-
static void __flush_tlb_range(struct mm_struct *mm, unsigned long start,
unsigned long size, unsigned long stride)
{
struct flush_tlb_range_data ftd;
- struct cpumask *cmask = mm_cpumask(mm);
- unsigned int cpuid;
+ const struct cpumask *cmask;
+ unsigned long asid = FLUSH_TLB_NO_ASID;
bool broadcast;
- if (cpumask_empty(cmask))
- return;
+ if (mm) {
+ unsigned int cpuid;
- cpuid = get_cpu();
- /* check if the tlbflush needs to be sent to other CPUs */
- broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids;
- if (static_branch_unlikely(&use_asid_allocator)) {
- unsigned long asid = atomic_long_read(&mm->context.id) & asid_mask;
-
- if (broadcast) {
- if (riscv_use_ipi_for_rfence()) {
- ftd.asid = asid;
- ftd.start = start;
- ftd.size = size;
- ftd.stride = stride;
- on_each_cpu_mask(cmask,
- __ipi_flush_tlb_range_asid,
- &ftd, 1);
- } else
- sbi_remote_sfence_vma_asid(cmask,
- start, size, asid);
- } else {
- local_flush_tlb_range_asid(start, size, stride, asid);
- }
+ cmask = mm_cpumask(mm);
+ if (cpumask_empty(cmask))
+ return;
+
+ cpuid = get_cpu();
+ /* check if the tlbflush needs to be sent to other CPUs */
+ broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids;
+
+ if (static_branch_unlikely(&use_asid_allocator))
+ asid = atomic_long_read(&mm->context.id) & asid_mask;
} else {
- if (broadcast) {
- if (riscv_use_ipi_for_rfence()) {
- ftd.asid = 0;
- ftd.start = start;
- ftd.size = size;
- ftd.stride = stride;
- on_each_cpu_mask(cmask,
- __ipi_flush_tlb_range,
- &ftd, 1);
- } else
- sbi_remote_sfence_vma(cmask, start, size);
- } else {
- local_flush_tlb_range(start, size, stride);
- }
+ cmask = cpu_online_mask;
+ broadcast = true;
}
- put_cpu();
+ if (broadcast) {
+ if (riscv_use_ipi_for_rfence()) {
+ ftd.asid = asid;
+ ftd.start = start;
+ ftd.size = size;
+ ftd.stride = stride;
+ on_each_cpu_mask(cmask,
+ __ipi_flush_tlb_range_asid,
+ &ftd, 1);
+ } else
+ sbi_remote_sfence_vma_asid(cmask,
+ start, size, asid);
+ } else {
+ local_flush_tlb_range_asid(start, size, stride, asid);
+ }
+
+ if (mm)
+ put_cpu();
}
void flush_tlb_mm(struct mm_struct *mm)
{
- __flush_tlb_range(mm, 0, -1, PAGE_SIZE);
+ __flush_tlb_range(mm, 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE);
+}
+
+void flush_tlb_mm_range(struct mm_struct *mm,
+ unsigned long start, unsigned long end,
+ unsigned int page_size)
+{
+ __flush_tlb_range(mm, start, end - start, page_size);
}
void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
@@ -140,8 +159,40 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
{
- __flush_tlb_range(vma->vm_mm, start, end - start, PAGE_SIZE);
+ unsigned long stride_size;
+
+ if (!is_vm_hugetlb_page(vma)) {
+ stride_size = PAGE_SIZE;
+ } else {
+ stride_size = huge_page_size(hstate_vma(vma));
+
+ /*
+ * As stated in the privileged specification, every PTE in a
+ * NAPOT region must be invalidated, so reset the stride in that
+ * case.
+ */
+ if (has_svnapot()) {
+ if (stride_size >= PGDIR_SIZE)
+ stride_size = PGDIR_SIZE;
+ else if (stride_size >= P4D_SIZE)
+ stride_size = P4D_SIZE;
+ else if (stride_size >= PUD_SIZE)
+ stride_size = PUD_SIZE;
+ else if (stride_size >= PMD_SIZE)
+ stride_size = PMD_SIZE;
+ else
+ stride_size = PAGE_SIZE;
+ }
+ }
+
+ __flush_tlb_range(vma->vm_mm, start, end - start, stride_size);
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ __flush_tlb_range(NULL, start, end - start, PAGE_SIZE);
}
+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index ecd3ae6f4116..8581693e62d3 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -245,7 +245,7 @@ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
emit_addi(RV_REG_SP, RV_REG_SP, stack_adjust, ctx);
/* Set return value. */
if (!is_tail_call)
- emit_mv(RV_REG_A0, RV_REG_A5, ctx);
+ emit_addiw(RV_REG_A0, RV_REG_A5, 0, ctx);
emit_jalr(RV_REG_ZERO, is_tail_call ? RV_REG_T3 : RV_REG_RA,
is_tail_call ? (RV_FENTRY_NINSNS + 1) * 4 : 0, /* skip reserved nops and TCC init */
ctx);
@@ -759,8 +759,10 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of
if (ret)
return ret;
- if (save_ret)
- emit_sd(RV_REG_FP, -retval_off, regmap[BPF_REG_0], ctx);
+ if (save_ret) {
+ emit_sd(RV_REG_FP, -retval_off, RV_REG_A0, ctx);
+ emit_sd(RV_REG_FP, -(retval_off - 8), regmap[BPF_REG_0], ctx);
+ }
/* update branch with beqz */
if (ctx->insns) {
@@ -853,7 +855,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET);
if (save_ret) {
- stack_size += 8;
+ stack_size += 16; /* Save both A5 (BPF R0) and A0 */
retval_off = stack_size;
}
@@ -957,6 +959,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
if (ret)
goto out;
emit_sd(RV_REG_FP, -retval_off, RV_REG_A0, ctx);
+ emit_sd(RV_REG_FP, -(retval_off - 8), regmap[BPF_REG_0], ctx);
im->ip_after_call = ctx->insns + ctx->ninsns;
/* 2 nops reserved for auipc+jalr pair */
emit(rv_nop(), ctx);
@@ -988,8 +991,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
if (flags & BPF_TRAMP_F_RESTORE_REGS)
restore_args(nregs, args_off, ctx);
- if (save_ret)
+ if (save_ret) {
emit_ld(RV_REG_A0, -retval_off, RV_REG_FP, ctx);
+ emit_ld(regmap[BPF_REG_0], -(retval_off - 8), RV_REG_FP, ctx);
+ }
emit_ld(RV_REG_S1, -sreg_off, RV_REG_FP, ctx);
@@ -1515,7 +1520,8 @@ out_be:
if (ret)
return ret;
- emit_mv(bpf_to_rv_reg(BPF_REG_0, ctx), RV_REG_A0, ctx);
+ if (insn->src_reg != BPF_PSEUDO_CALL)
+ emit_mv(bpf_to_rv_reg(BPF_REG_0, ctx), RV_REG_A0, ctx);
break;
}
/* tail call */
diff --git a/arch/riscv/purgatory/Makefile b/arch/riscv/purgatory/Makefile
index 9e6476719abb..280b0eb352b8 100644
--- a/arch/riscv/purgatory/Makefile
+++ b/arch/riscv/purgatory/Makefile
@@ -81,6 +81,14 @@ ifdef CONFIG_CFI_CLANG
PURGATORY_CFLAGS_REMOVE += $(CC_FLAGS_CFI)
endif
+ifdef CONFIG_RELOCATABLE
+PURGATORY_CFLAGS_REMOVE += -fPIE
+endif
+
+ifdef CONFIG_SHADOW_CALL_STACK
+PURGATORY_CFLAGS_REMOVE += $(CC_FLAGS_SCS)
+endif
+
CFLAGS_REMOVE_purgatory.o += $(PURGATORY_CFLAGS_REMOVE)
CFLAGS_purgatory.o += $(PURGATORY_CFLAGS)
diff --git a/arch/riscv/purgatory/entry.S b/arch/riscv/purgatory/entry.S
index 0194f4554130..5bcf3af903da 100644
--- a/arch/riscv/purgatory/entry.S
+++ b/arch/riscv/purgatory/entry.S
@@ -7,15 +7,11 @@
* Author: Li Zhengyu (lizhengyu3@huawei.com)
*
*/
-
-.macro size, sym:req
- .size \sym, . - \sym
-.endm
+#include <linux/linkage.h>
.text
-.globl purgatory_start
-purgatory_start:
+SYM_CODE_START(purgatory_start)
lla sp, .Lstack
mv s0, a0 /* The hartid of the current hart */
@@ -28,8 +24,7 @@ purgatory_start:
mv a1, s1
ld a2, riscv_kernel_entry
jr a2
-
-size purgatory_start
+SYM_CODE_END(purgatory_start)
.align 4
.rept 256
@@ -39,9 +34,6 @@ size purgatory_start
.data
-.globl riscv_kernel_entry
-riscv_kernel_entry:
- .quad 0
-size riscv_kernel_entry
+SYM_DATA(riscv_kernel_entry, .quad 0)
.end
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index ae29e4392664..3bec98d20283 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -131,6 +131,7 @@ config S390
select ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP
select BUILDTIME_TABLE_SORT
select CLONE_BACKWARDS2
+ select DCACHE_WORD_ACCESS if !KMSAN
select DMA_OPS if PCI
select DYNAMIC_FTRACE if FUNCTION_TRACER
select FUNCTION_ALIGNMENT_8B if CC_IS_GCC
@@ -235,6 +236,7 @@ config S390
select THREAD_INFO_IN_TASK
select TRACE_IRQFLAGS_SUPPORT
select TTY
+ select USER_STACKTRACE_SUPPORT
select VIRT_CPU_ACCOUNTING
select ZONE_DMA
# Note: keep the above list sorted alphabetically
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index a53a36ee0731..73873e451686 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -138,9 +138,6 @@ bzImage: vmlinux
zfcpdump:
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
-vdso_install:
- $(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso64 $@
-
archheaders:
$(Q)$(MAKE) $(build)=$(syscalls) uapi
@@ -160,6 +157,9 @@ vdso_prepare: prepare0
$(if $(CONFIG_COMPAT),$(Q)$(MAKE) \
$(build)=arch/s390/kernel/vdso32 include/generated/vdso32-offsets.h)
+vdso-install-y += arch/s390/kernel/vdso64/vdso64.so.dbg
+vdso-install-$(CONFIG_COMPAT) += arch/s390/kernel/vdso32/vdso32.so.dbg
+
ifdef CONFIG_EXPOLINE_EXTERN
modules_prepare: expoline_prepare
expoline_prepare: scripts
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 3b0994625652..c2978cb03b36 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -63,7 +63,6 @@ static struct ctl_table appldata_table[] = {
.mode = S_IRUGO | S_IWUSR,
.proc_handler = appldata_interval_handler,
},
- { },
};
/*
@@ -351,8 +350,7 @@ int appldata_register_ops(struct appldata_ops *ops)
if (ops->size > APPLDATA_MAX_REC_SIZE)
return -EINVAL;
- /* The last entry must be an empty one */
- ops->ctl_table = kcalloc(2, sizeof(struct ctl_table), GFP_KERNEL);
+ ops->ctl_table = kcalloc(1, sizeof(struct ctl_table), GFP_KERNEL);
if (!ops->ctl_table)
return -ENOMEM;
diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c
index 7b7521762633..2ab4872fbee1 100644
--- a/arch/s390/boot/ipl_parm.c
+++ b/arch/s390/boot/ipl_parm.c
@@ -3,6 +3,7 @@
#include <linux/init.h>
#include <linux/ctype.h>
#include <linux/pgtable.h>
+#include <asm/page-states.h>
#include <asm/ebcdic.h>
#include <asm/sclp.h>
#include <asm/sections.h>
@@ -24,6 +25,7 @@ unsigned int __bootdata_preserved(zlib_dfltcc_support) = ZLIB_DFLTCC_FULL;
struct ipl_parameter_block __bootdata_preserved(ipl_block);
int __bootdata_preserved(ipl_block_valid);
int __bootdata_preserved(__kaslr_enabled);
+int __bootdata_preserved(cmma_flag) = 1;
unsigned long vmalloc_size = VMALLOC_DEFAULT_SIZE;
unsigned long memory_limit;
@@ -295,6 +297,12 @@ void parse_boot_command_line(void)
if (!strcmp(param, "nokaslr"))
__kaslr_enabled = 0;
+ if (!strcmp(param, "cmma")) {
+ rc = kstrtobool(val, &enabled);
+ if (!rc && !enabled)
+ cmma_flag = 0;
+ }
+
#if IS_ENABLED(CONFIG_KVM)
if (!strcmp(param, "prot_virt")) {
rc = kstrtobool(val, &enabled);
diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
index d3e48bd9c394..8104e0e3d188 100644
--- a/arch/s390/boot/startup.c
+++ b/arch/s390/boot/startup.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/string.h>
#include <linux/elf.h>
+#include <asm/page-states.h>
#include <asm/boot_data.h>
#include <asm/sections.h>
#include <asm/maccess.h>
@@ -49,7 +50,7 @@ static void detect_facilities(void)
{
if (test_facility(8)) {
machine.has_edat1 = 1;
- __ctl_set_bit(0, 23);
+ local_ctl_set_bit(0, CR0_EDAT_BIT);
}
if (test_facility(78))
machine.has_edat2 = 1;
@@ -57,6 +58,48 @@ static void detect_facilities(void)
machine.has_nx = 1;
}
+static int cmma_test_essa(void)
+{
+ unsigned long reg1, reg2, tmp = 0;
+ int rc = 1;
+ psw_t old;
+
+ /* Test ESSA_GET_STATE */
+ asm volatile(
+ " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n"
+ " epsw %[reg1],%[reg2]\n"
+ " st %[reg1],0(%[psw_pgm])\n"
+ " st %[reg2],4(%[psw_pgm])\n"
+ " larl %[reg1],1f\n"
+ " stg %[reg1],8(%[psw_pgm])\n"
+ " .insn rrf,0xb9ab0000,%[tmp],%[tmp],%[cmd],0\n"
+ " la %[rc],0\n"
+ "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n"
+ : [reg1] "=&d" (reg1),
+ [reg2] "=&a" (reg2),
+ [rc] "+&d" (rc),
+ [tmp] "=&d" (tmp),
+ "+Q" (S390_lowcore.program_new_psw),
+ "=Q" (old)
+ : [psw_old] "a" (&old),
+ [psw_pgm] "a" (&S390_lowcore.program_new_psw),
+ [cmd] "i" (ESSA_GET_STATE)
+ : "cc", "memory");
+ return rc;
+}
+
+static void cmma_init(void)
+{
+ if (!cmma_flag)
+ return;
+ if (cmma_test_essa()) {
+ cmma_flag = 0;
+ return;
+ }
+ if (test_facility(147))
+ cmma_flag = 2;
+}
+
static void setup_lpp(void)
{
S390_lowcore.current_pid = 0;
@@ -306,6 +349,7 @@ void startup_kernel(void)
setup_boot_command_line();
parse_boot_command_line();
detect_facilities();
+ cmma_init();
sanitize_prot_virt_host();
max_physmem_end = detect_max_physmem_end();
setup_ident_map_size(max_physmem_end);
diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c
index 01257ce3b89c..e3a4500a5a75 100644
--- a/arch/s390/boot/vmem.c
+++ b/arch/s390/boot/vmem.c
@@ -2,16 +2,18 @@
#include <linux/sched/task.h>
#include <linux/pgtable.h>
#include <linux/kasan.h>
+#include <asm/page-states.h>
#include <asm/pgalloc.h>
#include <asm/facility.h>
#include <asm/sections.h>
+#include <asm/ctlreg.h>
#include <asm/physmem_info.h>
#include <asm/maccess.h>
#include <asm/abs_lowcore.h>
#include "decompressor.h"
#include "boot.h"
-unsigned long __bootdata_preserved(s390_invalid_asce);
+struct ctlreg __bootdata_preserved(s390_invalid_asce);
#ifdef CONFIG_PROC_FS
atomic_long_t __bootdata_preserved(direct_pages_count[PG_DIRECT_MAP_MAX]);
@@ -57,6 +59,7 @@ static void kasan_populate_shadow(void)
pmd_t pmd_z = __pmd(__pa(kasan_early_shadow_pte) | _SEGMENT_ENTRY);
pud_t pud_z = __pud(__pa(kasan_early_shadow_pmd) | _REGION3_ENTRY);
p4d_t p4d_z = __p4d(__pa(kasan_early_shadow_pud) | _REGION2_ENTRY);
+ unsigned long memgap_start = 0;
unsigned long untracked_end;
unsigned long start, end;
int i;
@@ -68,6 +71,10 @@ static void kasan_populate_shadow(void)
crst_table_init((unsigned long *)kasan_early_shadow_pud, pud_val(pud_z));
crst_table_init((unsigned long *)kasan_early_shadow_pmd, pmd_val(pmd_z));
memset64((u64 *)kasan_early_shadow_pte, pte_val(pte_z), PTRS_PER_PTE);
+ __arch_set_page_dat(kasan_early_shadow_p4d, 1UL << CRST_ALLOC_ORDER);
+ __arch_set_page_dat(kasan_early_shadow_pud, 1UL << CRST_ALLOC_ORDER);
+ __arch_set_page_dat(kasan_early_shadow_pmd, 1UL << CRST_ALLOC_ORDER);
+ __arch_set_page_dat(kasan_early_shadow_pte, 1);
/*
* Current memory layout:
@@ -101,8 +108,12 @@ static void kasan_populate_shadow(void)
* +- shadow end ----+---------+- shadow end ---+
*/
- for_each_physmem_usable_range(i, &start, &end)
+ for_each_physmem_usable_range(i, &start, &end) {
kasan_populate(start, end, POPULATE_KASAN_MAP_SHADOW);
+ if (memgap_start && physmem_info.info_source == MEM_DETECT_DIAG260)
+ kasan_populate(memgap_start, start, POPULATE_KASAN_ZERO_SHADOW);
+ memgap_start = end;
+ }
if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
untracked_end = VMALLOC_START;
/* shallowly populate kasan shadow for vmalloc and modules */
@@ -161,8 +172,6 @@ static bool kasan_pmd_populate_zero_shadow(pmd_t *pmd, unsigned long addr,
static bool kasan_pte_populate_zero_shadow(pte_t *pte, enum populate_mode mode)
{
- pte_t entry;
-
if (mode == POPULATE_KASAN_ZERO_SHADOW) {
set_pte(pte, pte_z);
return true;
@@ -219,6 +228,7 @@ static void *boot_crst_alloc(unsigned long val)
table = (unsigned long *)physmem_alloc_top_down(RR_VMEM, size, size);
crst_table_init(table, val);
+ __arch_set_page_dat(table, 1UL << CRST_ALLOC_ORDER);
return table;
}
@@ -234,6 +244,7 @@ static pte_t *boot_pte_alloc(void)
if (!pte_leftover) {
pte_leftover = (void *)physmem_alloc_top_down(RR_VMEM, PAGE_SIZE, PAGE_SIZE);
pte = pte_leftover + _PAGE_TABLE_SIZE;
+ __arch_set_page_dat(pte, 1);
} else {
pte = pte_leftover;
pte_leftover = NULL;
@@ -414,6 +425,14 @@ void setup_vmem(unsigned long asce_limit)
unsigned long asce_bits;
int i;
+ /*
+ * Mark whole memory as no-dat. This must be done before any
+ * page tables are allocated, or kernel image builtin pages
+ * are marked as dat tables.
+ */
+ for_each_physmem_online_range(i, &start, &end)
+ __arch_set_page_nodat((void *)start, (end - start) >> PAGE_SHIFT);
+
if (asce_limit == _REGION1_SIZE) {
asce_type = _REGION2_ENTRY_EMPTY;
asce_bits = _ASCE_TYPE_REGION2 | _ASCE_TABLE_LENGTH;
@@ -421,10 +440,12 @@ void setup_vmem(unsigned long asce_limit)
asce_type = _REGION3_ENTRY_EMPTY;
asce_bits = _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH;
}
- s390_invalid_asce = invalid_pg_dir | _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH;
+ s390_invalid_asce.val = invalid_pg_dir | _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH;
crst_table_init((unsigned long *)swapper_pg_dir, asce_type);
crst_table_init((unsigned long *)invalid_pg_dir, _REGION3_ENTRY_EMPTY);
+ __arch_set_page_dat((void *)swapper_pg_dir, 1UL << CRST_ALLOC_ORDER);
+ __arch_set_page_dat((void *)invalid_pg_dir, 1UL << CRST_ALLOC_ORDER);
/*
* To allow prefixing the lowcore must be mapped with 4KB pages.
@@ -442,12 +463,12 @@ void setup_vmem(unsigned long asce_limit)
kasan_populate_shadow();
- S390_lowcore.kernel_asce = swapper_pg_dir | asce_bits;
+ S390_lowcore.kernel_asce.val = swapper_pg_dir | asce_bits;
S390_lowcore.user_asce = s390_invalid_asce;
- __ctl_load(S390_lowcore.kernel_asce, 1, 1);
- __ctl_load(S390_lowcore.user_asce, 7, 7);
- __ctl_load(S390_lowcore.kernel_asce, 13, 13);
+ local_ctl_load(1, &S390_lowcore.kernel_asce);
+ local_ctl_load(7, &S390_lowcore.user_asce);
+ local_ctl_load(13, &S390_lowcore.kernel_asce);
- init_mm.context.asce = S390_lowcore.kernel_asce;
+ init_mm.context.asce = S390_lowcore.kernel_asce.val;
}
diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig
index 438cd92e6080..dd0608629310 100644
--- a/arch/s390/configs/debug_defconfig
+++ b/arch/s390/configs/debug_defconfig
@@ -834,7 +834,6 @@ CONFIG_DEBUG_IRQFLAGS=y
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_SG=y
CONFIG_DEBUG_NOTIFIERS=y
-CONFIG_DEBUG_CREDENTIALS=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_RCU_REF_SCALE_TEST=m
CONFIG_RCU_CPU_STALL_TIMEOUT=300
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index ada83149932f..858beaf4a8cb 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -53,7 +53,7 @@ static void hypfs_update_update(struct super_block *sb)
struct inode *inode = d_inode(sb_info->update_file);
sb_info->last_update = ktime_get_seconds();
- inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode);
+ simple_inode_init_ts(inode);
}
/* directory tree removal functions */
@@ -101,7 +101,7 @@ static struct inode *hypfs_make_inode(struct super_block *sb, umode_t mode)
ret->i_mode = mode;
ret->i_uid = hypfs_info->uid;
ret->i_gid = hypfs_info->gid;
- ret->i_atime = ret->i_mtime = inode_set_ctime_current(ret);
+ simple_inode_init_ts(ret);
if (S_ISDIR(mode))
set_nlink(ret, 2);
}
diff --git a/arch/s390/include/asm/asm-extable.h b/arch/s390/include/asm/asm-extable.h
index e6532477f126..4a6b0a8b6412 100644
--- a/arch/s390/include/asm/asm-extable.h
+++ b/arch/s390/include/asm/asm-extable.h
@@ -13,6 +13,7 @@
#define EX_TYPE_UA_LOAD_MEM 4
#define EX_TYPE_UA_LOAD_REG 5
#define EX_TYPE_UA_LOAD_REGPAIR 6
+#define EX_TYPE_ZEROPAD 7
#define EX_DATA_REG_ERR_SHIFT 0
#define EX_DATA_REG_ERR GENMASK(3, 0)
@@ -23,16 +24,7 @@
#define EX_DATA_LEN_SHIFT 8
#define EX_DATA_LEN GENMASK(11, 8)
-#define __EX_TABLE(_section, _fault, _target, _type) \
- stringify_in_c(.section _section,"a";) \
- stringify_in_c(.balign 4;) \
- stringify_in_c(.long (_fault) - .;) \
- stringify_in_c(.long (_target) - .;) \
- stringify_in_c(.short (_type);) \
- stringify_in_c(.short 0;) \
- stringify_in_c(.previous)
-
-#define __EX_TABLE_UA(_section, _fault, _target, _type, _regerr, _regaddr, _len)\
+#define __EX_TABLE(_section, _fault, _target, _type, _regerr, _regaddr, _len) \
stringify_in_c(.section _section,"a";) \
stringify_in_c(.balign 4;) \
stringify_in_c(.long (_fault) - .;) \
@@ -72,21 +64,24 @@
stringify_in_c(.previous)
#define EX_TABLE(_fault, _target) \
- __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_FIXUP)
+ __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_FIXUP, __stringify(%%r0), __stringify(%%r0), 0)
#define EX_TABLE_AMODE31(_fault, _target) \
- __EX_TABLE(.amode31.ex_table, _fault, _target, EX_TYPE_FIXUP)
+ __EX_TABLE(.amode31.ex_table, _fault, _target, EX_TYPE_FIXUP, __stringify(%%r0), __stringify(%%r0), 0)
#define EX_TABLE_UA_STORE(_fault, _target, _regerr) \
- __EX_TABLE_UA(__ex_table, _fault, _target, EX_TYPE_UA_STORE, _regerr, _regerr, 0)
+ __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_STORE, _regerr, _regerr, 0)
#define EX_TABLE_UA_LOAD_MEM(_fault, _target, _regerr, _regmem, _len) \
- __EX_TABLE_UA(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_MEM, _regerr, _regmem, _len)
+ __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_MEM, _regerr, _regmem, _len)
#define EX_TABLE_UA_LOAD_REG(_fault, _target, _regerr, _regzero) \
- __EX_TABLE_UA(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_REG, _regerr, _regzero, 0)
+ __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_REG, _regerr, _regzero, 0)
#define EX_TABLE_UA_LOAD_REGPAIR(_fault, _target, _regerr, _regzero) \
- __EX_TABLE_UA(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_REGPAIR, _regerr, _regzero, 0)
+ __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_REGPAIR, _regerr, _regzero, 0)
+
+#define EX_TABLE_ZEROPAD(_fault, _target, _regdata, _regaddr) \
+ __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_ZEROPAD, _regdata, _regaddr, 0)
#endif /* __ASM_EXTABLE_H */
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 2de74fcd0578..c467dffa8c12 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -201,6 +201,16 @@ static inline void arch___clear_bit_unlock(unsigned long nr,
arch___clear_bit(nr, ptr);
}
+static inline bool arch_xor_unlock_is_negative_byte(unsigned long mask,
+ volatile unsigned long *ptr)
+{
+ unsigned long old;
+
+ old = __atomic64_xor_barrier(mask, (long *)ptr);
+ return old & BIT(7);
+}
+#define arch_xor_unlock_is_negative_byte arch_xor_unlock_is_negative_byte
+
#include <asm-generic/bitops/instrumented-atomic.h>
#include <asm-generic/bitops/instrumented-non-atomic.h>
#include <asm-generic/bitops/instrumented-lock.h>
diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h
deleted file mode 100644
index adf7d8cdac7e..000000000000
--- a/arch/s390/include/asm/ctl_reg.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright IBM Corp. 1999, 2009
- *
- * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
- */
-
-#ifndef __ASM_CTL_REG_H
-#define __ASM_CTL_REG_H
-
-#include <linux/bits.h>
-
-#define CR0_CLOCK_COMPARATOR_SIGN BIT(63 - 10)
-#define CR0_LOW_ADDRESS_PROTECTION BIT(63 - 35)
-#define CR0_FETCH_PROTECTION_OVERRIDE BIT(63 - 38)
-#define CR0_STORAGE_PROTECTION_OVERRIDE BIT(63 - 39)
-#define CR0_EMERGENCY_SIGNAL_SUBMASK BIT(63 - 49)
-#define CR0_EXTERNAL_CALL_SUBMASK BIT(63 - 50)
-#define CR0_CLOCK_COMPARATOR_SUBMASK BIT(63 - 52)
-#define CR0_CPU_TIMER_SUBMASK BIT(63 - 53)
-#define CR0_SERVICE_SIGNAL_SUBMASK BIT(63 - 54)
-#define CR0_UNUSED_56 BIT(63 - 56)
-#define CR0_INTERRUPT_KEY_SUBMASK BIT(63 - 57)
-#define CR0_MEASUREMENT_ALERT_SUBMASK BIT(63 - 58)
-
-#define CR14_UNUSED_32 BIT(63 - 32)
-#define CR14_UNUSED_33 BIT(63 - 33)
-#define CR14_CHANNEL_REPORT_SUBMASK BIT(63 - 35)
-#define CR14_RECOVERY_SUBMASK BIT(63 - 36)
-#define CR14_DEGRADATION_SUBMASK BIT(63 - 37)
-#define CR14_EXTERNAL_DAMAGE_SUBMASK BIT(63 - 38)
-#define CR14_WARNING_SUBMASK BIT(63 - 39)
-
-#ifndef __ASSEMBLY__
-
-#include <linux/bug.h>
-
-#define __ctl_load(array, low, high) do { \
- typedef struct { char _[sizeof(array)]; } addrtype; \
- \
- BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\
- asm volatile( \
- " lctlg %1,%2,%0\n" \
- : \
- : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high) \
- : "memory"); \
-} while (0)
-
-#define __ctl_store(array, low, high) do { \
- typedef struct { char _[sizeof(array)]; } addrtype; \
- \
- BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\
- asm volatile( \
- " stctg %1,%2,%0\n" \
- : "=Q" (*(addrtype *)(&array)) \
- : "i" (low), "i" (high)); \
-} while (0)
-
-static __always_inline void __ctl_set_bit(unsigned int cr, unsigned int bit)
-{
- unsigned long reg;
-
- __ctl_store(reg, cr, cr);
- reg |= 1UL << bit;
- __ctl_load(reg, cr, cr);
-}
-
-static __always_inline void __ctl_clear_bit(unsigned int cr, unsigned int bit)
-{
- unsigned long reg;
-
- __ctl_store(reg, cr, cr);
- reg &= ~(1UL << bit);
- __ctl_load(reg, cr, cr);
-}
-
-void smp_ctl_set_clear_bit(int cr, int bit, bool set);
-
-static inline void ctl_set_bit(int cr, int bit)
-{
- smp_ctl_set_clear_bit(cr, bit, true);
-}
-
-static inline void ctl_clear_bit(int cr, int bit)
-{
- smp_ctl_set_clear_bit(cr, bit, false);
-}
-
-union ctlreg0 {
- unsigned long val;
- struct {
- unsigned long : 8;
- unsigned long tcx : 1; /* Transactional-Execution control */
- unsigned long pifo : 1; /* Transactional-Execution Program-
- Interruption-Filtering Override */
- unsigned long : 3;
- unsigned long ccc : 1; /* Cryptography counter control */
- unsigned long pec : 1; /* PAI extension control */
- unsigned long : 17;
- unsigned long : 3;
- unsigned long lap : 1; /* Low-address-protection control */
- unsigned long : 4;
- unsigned long edat : 1; /* Enhanced-DAT-enablement control */
- unsigned long : 2;
- unsigned long iep : 1; /* Instruction-Execution-Protection */
- unsigned long : 1;
- unsigned long afp : 1; /* AFP-register control */
- unsigned long vx : 1; /* Vector enablement control */
- unsigned long : 7;
- unsigned long sssm : 1; /* Service signal subclass mask */
- unsigned long : 9;
- };
-};
-
-union ctlreg2 {
- unsigned long val;
- struct {
- unsigned long : 33;
- unsigned long ducto : 25;
- unsigned long : 1;
- unsigned long gse : 1;
- unsigned long : 1;
- unsigned long tds : 1;
- unsigned long tdc : 2;
- };
-};
-
-union ctlreg5 {
- unsigned long val;
- struct {
- unsigned long : 33;
- unsigned long pasteo: 25;
- unsigned long : 6;
- };
-};
-
-union ctlreg15 {
- unsigned long val;
- struct {
- unsigned long lsea : 61;
- unsigned long : 3;
- };
-};
-
-#endif /* __ASSEMBLY__ */
-#endif /* __ASM_CTL_REG_H */
diff --git a/arch/s390/include/asm/ctlreg.h b/arch/s390/include/asm/ctlreg.h
new file mode 100644
index 000000000000..6d4b85f2b541
--- /dev/null
+++ b/arch/s390/include/asm/ctlreg.h
@@ -0,0 +1,251 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright IBM Corp. 1999, 2009
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef __ASM_S390_CTLREG_H
+#define __ASM_S390_CTLREG_H
+
+#include <linux/bits.h>
+
+#define CR0_TRANSACTIONAL_EXECUTION_BIT (63 - 8)
+#define CR0_CLOCK_COMPARATOR_SIGN_BIT (63 - 10)
+#define CR0_CRYPTOGRAPHY_COUNTER_BIT (63 - 13)
+#define CR0_PAI_EXTENSION_BIT (63 - 14)
+#define CR0_CPUMF_EXTRACTION_AUTH_BIT (63 - 15)
+#define CR0_WARNING_TRACK_BIT (63 - 30)
+#define CR0_LOW_ADDRESS_PROTECTION_BIT (63 - 35)
+#define CR0_FETCH_PROTECTION_OVERRIDE_BIT (63 - 38)
+#define CR0_STORAGE_PROTECTION_OVERRIDE_BIT (63 - 39)
+#define CR0_EDAT_BIT (63 - 40)
+#define CR0_INSTRUCTION_EXEC_PROTECTION_BIT (63 - 43)
+#define CR0_VECTOR_BIT (63 - 46)
+#define CR0_MALFUNCTION_ALERT_SUBMASK_BIT (63 - 48)
+#define CR0_EMERGENCY_SIGNAL_SUBMASK_BIT (63 - 49)
+#define CR0_EXTERNAL_CALL_SUBMASK_BIT (63 - 50)
+#define CR0_CLOCK_COMPARATOR_SUBMASK_BIT (63 - 52)
+#define CR0_CPU_TIMER_SUBMASK_BIT (63 - 53)
+#define CR0_SERVICE_SIGNAL_SUBMASK_BIT (63 - 54)
+#define CR0_UNUSED_56_BIT (63 - 56)
+#define CR0_INTERRUPT_KEY_SUBMASK_BIT (63 - 57)
+#define CR0_MEASUREMENT_ALERT_SUBMASK_BIT (63 - 58)
+#define CR0_ETR_SUBMASK_BIT (63 - 59)
+#define CR0_IUCV_BIT (63 - 62)
+
+#define CR0_TRANSACTIONAL_EXECUTION BIT(CR0_TRANSACTIONAL_EXECUTION_BIT)
+#define CR0_CLOCK_COMPARATOR_SIGN BIT(CR0_CLOCK_COMPARATOR_SIGN_BIT)
+#define CR0_CRYPTOGRAPHY_COUNTER BIT(CR0_CRYPTOGRAPHY_COUNTER_BIT)
+#define CR0_PAI_EXTENSION BIT(CR0_PAI_EXTENSION_BIT)
+#define CR0_CPUMF_EXTRACTION_AUTH BIT(CR0_CPUMF_EXTRACTION_AUTH_BIT)
+#define CR0_WARNING_TRACK BIT(CR0_WARNING_TRACK_BIT)
+#define CR0_LOW_ADDRESS_PROTECTION BIT(CR0_LOW_ADDRESS_PROTECTION_BIT)
+#define CR0_FETCH_PROTECTION_OVERRIDE BIT(CR0_FETCH_PROTECTION_OVERRIDE_BIT)
+#define CR0_STORAGE_PROTECTION_OVERRIDE BIT(CR0_STORAGE_PROTECTION_OVERRIDE_BIT)
+#define CR0_EDAT BIT(CR0_EDAT_BIT)
+#define CR0_INSTRUCTION_EXEC_PROTECTION BIT(CR0_INSTRUCTION_EXEC_PROTECTION_BIT)
+#define CR0_VECTOR BIT(CR0_VECTOR_BIT)
+#define CR0_MALFUNCTION_ALERT_SUBMASK BIT(CR0_MALFUNCTION_ALERT_SUBMASK_BIT)
+#define CR0_EMERGENCY_SIGNAL_SUBMASK BIT(CR0_EMERGENCY_SIGNAL_SUBMASK_BIT)
+#define CR0_EXTERNAL_CALL_SUBMASK BIT(CR0_EXTERNAL_CALL_SUBMASK_BIT)
+#define CR0_CLOCK_COMPARATOR_SUBMASK BIT(CR0_CLOCK_COMPARATOR_SUBMASK_BIT)
+#define CR0_CPU_TIMER_SUBMASK BIT(CR0_CPU_TIMER_SUBMASK_BIT)
+#define CR0_SERVICE_SIGNAL_SUBMASK BIT(CR0_SERVICE_SIGNAL_SUBMASK_BIT)
+#define CR0_UNUSED_56 BIT(CR0_UNUSED_56_BIT)
+#define CR0_INTERRUPT_KEY_SUBMASK BIT(CR0_INTERRUPT_KEY_SUBMASK_BIT)
+#define CR0_MEASUREMENT_ALERT_SUBMASK BIT(CR0_MEASUREMENT_ALERT_SUBMASK_BIT)
+#define CR0_ETR_SUBMASK BIT(CR0_ETR_SUBMASK_BIT)
+#define CR0_IUCV BIT(CR0_IUCV_BIT)
+
+#define CR2_MIO_ADDRESSING_BIT (63 - 58)
+#define CR2_GUARDED_STORAGE_BIT (63 - 59)
+
+#define CR2_MIO_ADDRESSING BIT(CR2_MIO_ADDRESSING_BIT)
+#define CR2_GUARDED_STORAGE BIT(CR2_GUARDED_STORAGE_BIT)
+
+#define CR14_UNUSED_32_BIT (63 - 32)
+#define CR14_UNUSED_33_BIT (63 - 33)
+#define CR14_CHANNEL_REPORT_SUBMASK_BIT (63 - 35)
+#define CR14_RECOVERY_SUBMASK_BIT (63 - 36)
+#define CR14_DEGRADATION_SUBMASK_BIT (63 - 37)
+#define CR14_EXTERNAL_DAMAGE_SUBMASK_BIT (63 - 38)
+#define CR14_WARNING_SUBMASK_BIT (63 - 39)
+
+#define CR14_UNUSED_32 BIT(CR14_UNUSED_32_BIT)
+#define CR14_UNUSED_33 BIT(CR14_UNUSED_33_BIT)
+#define CR14_CHANNEL_REPORT_SUBMASK BIT(CR14_CHANNEL_REPORT_SUBMASK_BIT)
+#define CR14_RECOVERY_SUBMASK BIT(CR14_RECOVERY_SUBMASK_BIT)
+#define CR14_DEGRADATION_SUBMASK BIT(CR14_DEGRADATION_SUBMASK_BIT)
+#define CR14_EXTERNAL_DAMAGE_SUBMASK BIT(CR14_EXTERNAL_DAMAGE_SUBMASK_BIT)
+#define CR14_WARNING_SUBMASK BIT(CR14_WARNING_SUBMASK_BIT)
+
+#ifndef __ASSEMBLY__
+
+#include <linux/bug.h>
+
+struct ctlreg {
+ unsigned long val;
+};
+
+#define __local_ctl_load(low, high, array) do { \
+ struct addrtype { \
+ char _[sizeof(array)]; \
+ }; \
+ int _high = high; \
+ int _low = low; \
+ int _esize; \
+ \
+ _esize = (_high - _low + 1) * sizeof(struct ctlreg); \
+ BUILD_BUG_ON(sizeof(struct addrtype) != _esize); \
+ typecheck(struct ctlreg, array[0]); \
+ asm volatile( \
+ " lctlg %[_low],%[_high],%[_arr]\n" \
+ : \
+ : [_arr] "Q" (*(struct addrtype *)(&array)), \
+ [_low] "i" (low), [_high] "i" (high) \
+ : "memory"); \
+} while (0)
+
+#define __local_ctl_store(low, high, array) do { \
+ struct addrtype { \
+ char _[sizeof(array)]; \
+ }; \
+ int _high = high; \
+ int _low = low; \
+ int _esize; \
+ \
+ _esize = (_high - _low + 1) * sizeof(struct ctlreg); \
+ BUILD_BUG_ON(sizeof(struct addrtype) != _esize); \
+ typecheck(struct ctlreg, array[0]); \
+ asm volatile( \
+ " stctg %[_low],%[_high],%[_arr]\n" \
+ : [_arr] "=Q" (*(struct addrtype *)(&array)) \
+ : [_low] "i" (low), [_high] "i" (high)); \
+} while (0)
+
+static __always_inline void local_ctl_load(unsigned int cr, struct ctlreg *reg)
+{
+ asm volatile(
+ " lctlg %[cr],%[cr],%[reg]\n"
+ :
+ : [reg] "Q" (*reg), [cr] "i" (cr)
+ : "memory");
+}
+
+static __always_inline void local_ctl_store(unsigned int cr, struct ctlreg *reg)
+{
+ asm volatile(
+ " stctg %[cr],%[cr],%[reg]\n"
+ : [reg] "=Q" (*reg)
+ : [cr] "i" (cr));
+}
+
+static __always_inline void local_ctl_set_bit(unsigned int cr, unsigned int bit)
+{
+ struct ctlreg reg;
+
+ local_ctl_store(cr, &reg);
+ reg.val |= 1UL << bit;
+ local_ctl_load(cr, &reg);
+}
+
+static __always_inline void local_ctl_clear_bit(unsigned int cr, unsigned int bit)
+{
+ struct ctlreg reg;
+
+ local_ctl_store(cr, &reg);
+ reg.val &= ~(1UL << bit);
+ local_ctl_load(cr, &reg);
+}
+
+struct lowcore;
+
+void system_ctlreg_lock(void);
+void system_ctlreg_unlock(void);
+void system_ctlreg_init_save_area(struct lowcore *lc);
+void system_ctlreg_modify(unsigned int cr, unsigned long data, int request);
+
+enum {
+ CTLREG_SET_BIT,
+ CTLREG_CLEAR_BIT,
+ CTLREG_LOAD,
+};
+
+static inline void system_ctl_set_bit(unsigned int cr, unsigned int bit)
+{
+ system_ctlreg_modify(cr, bit, CTLREG_SET_BIT);
+}
+
+static inline void system_ctl_clear_bit(unsigned int cr, unsigned int bit)
+{
+ system_ctlreg_modify(cr, bit, CTLREG_CLEAR_BIT);
+}
+
+static inline void system_ctl_load(unsigned int cr, struct ctlreg *reg)
+{
+ system_ctlreg_modify(cr, reg->val, CTLREG_LOAD);
+}
+
+union ctlreg0 {
+ unsigned long val;
+ struct ctlreg reg;
+ struct {
+ unsigned long : 8;
+ unsigned long tcx : 1; /* Transactional-Execution control */
+ unsigned long pifo : 1; /* Transactional-Execution Program-
+ Interruption-Filtering Override */
+ unsigned long : 3;
+ unsigned long ccc : 1; /* Cryptography counter control */
+ unsigned long pec : 1; /* PAI extension control */
+ unsigned long : 17;
+ unsigned long : 3;
+ unsigned long lap : 1; /* Low-address-protection control */
+ unsigned long : 4;
+ unsigned long edat : 1; /* Enhanced-DAT-enablement control */
+ unsigned long : 2;
+ unsigned long iep : 1; /* Instruction-Execution-Protection */
+ unsigned long : 1;
+ unsigned long afp : 1; /* AFP-register control */
+ unsigned long vx : 1; /* Vector enablement control */
+ unsigned long : 7;
+ unsigned long sssm : 1; /* Service signal subclass mask */
+ unsigned long : 9;
+ };
+};
+
+union ctlreg2 {
+ unsigned long val;
+ struct ctlreg reg;
+ struct {
+ unsigned long : 33;
+ unsigned long ducto : 25;
+ unsigned long : 1;
+ unsigned long gse : 1;
+ unsigned long : 1;
+ unsigned long tds : 1;
+ unsigned long tdc : 2;
+ };
+};
+
+union ctlreg5 {
+ unsigned long val;
+ struct ctlreg reg;
+ struct {
+ unsigned long : 33;
+ unsigned long pasteo: 25;
+ unsigned long : 6;
+ };
+};
+
+union ctlreg15 {
+ unsigned long val;
+ struct ctlreg reg;
+ struct {
+ unsigned long lsea : 61;
+ unsigned long : 3;
+ };
+};
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_S390_CTLREG_H */
diff --git a/arch/s390/include/asm/fault.h b/arch/s390/include/asm/fault.h
new file mode 100644
index 000000000000..d326f56603d6
--- /dev/null
+++ b/arch/s390/include/asm/fault.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright IBM Corp. 1999, 2023
+ */
+#ifndef _ASM_S390_FAULT_H
+#define _ASM_S390_FAULT_H
+
+union teid {
+ unsigned long val;
+ struct {
+ unsigned long addr : 52; /* Translation-exception Address */
+ unsigned long fsi : 2; /* Access Exception Fetch/Store Indication */
+ unsigned long : 2;
+ unsigned long b56 : 1;
+ unsigned long : 3;
+ unsigned long b60 : 1;
+ unsigned long b61 : 1;
+ unsigned long as : 2; /* ASCE Identifier */
+ };
+};
+
+enum {
+ TEID_FSI_UNKNOWN = 0, /* Unknown whether fetch or store */
+ TEID_FSI_STORE = 1, /* Exception was due to store operation */
+ TEID_FSI_FETCH = 2 /* Exception was due to fetch operation */
+};
+
+#endif /* _ASM_S390_FAULT_H */
diff --git a/arch/s390/include/asm/fpu/internal.h b/arch/s390/include/asm/fpu/internal.h
index bbdadb1c9efc..8634581b9011 100644
--- a/arch/s390/include/asm/fpu/internal.h
+++ b/arch/s390/include/asm/fpu/internal.h
@@ -10,7 +10,6 @@
#define _ASM_S390_FPU_INTERNAL_H
#include <linux/string.h>
-#include <asm/ctl_reg.h>
#include <asm/fpu/types.h>
static inline void save_vx_regs(__vector128 *vxrs)
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h
index 89902f754740..54b42817f70a 100644
--- a/arch/s390/include/asm/irq.h
+++ b/arch/s390/include/asm/irq.h
@@ -31,6 +31,7 @@
#include <linux/percpu.h>
#include <linux/cache.h>
#include <linux/types.h>
+#include <asm/ctlreg.h>
enum interruption_class {
IRQEXT_CLK,
@@ -101,17 +102,17 @@ enum irq_subclass {
};
#define CR0_IRQ_SUBCLASS_MASK \
- ((1UL << (63 - 30)) /* Warning Track */ | \
- (1UL << (63 - 48)) /* Malfunction Alert */ | \
- (1UL << (63 - 49)) /* Emergency Signal */ | \
- (1UL << (63 - 50)) /* External Call */ | \
- (1UL << (63 - 52)) /* Clock Comparator */ | \
- (1UL << (63 - 53)) /* CPU Timer */ | \
- (1UL << (63 - 54)) /* Service Signal */ | \
- (1UL << (63 - 57)) /* Interrupt Key */ | \
- (1UL << (63 - 58)) /* Measurement Alert */ | \
- (1UL << (63 - 59)) /* Timing Alert */ | \
- (1UL << (63 - 62))) /* IUCV */
+ (CR0_WARNING_TRACK | \
+ CR0_MALFUNCTION_ALERT_SUBMASK | \
+ CR0_EMERGENCY_SIGNAL_SUBMASK | \
+ CR0_EXTERNAL_CALL_SUBMASK | \
+ CR0_CLOCK_COMPARATOR_SUBMASK | \
+ CR0_CPU_TIMER_SUBMASK | \
+ CR0_SERVICE_SIGNAL_SUBMASK | \
+ CR0_INTERRUPT_KEY_SUBMASK | \
+ CR0_MEASUREMENT_ALERT_SUBMASK | \
+ CR0_ETR_SUBMASK | \
+ CR0_IUCV)
void irq_subclass_register(enum irq_subclass subclass);
void irq_subclass_unregister(enum irq_subclass subclass);
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 83f732ca3af4..01f1682a73b7 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -15,6 +15,7 @@
* <grundym@us.ibm.com>
*/
#include <linux/types.h>
+#include <asm/ctlreg.h>
#include <asm-generic/kprobes.h>
#define BREAKPOINT_INSTRUCTION 0x0002
@@ -65,15 +66,13 @@ struct prev_kprobe {
struct kprobe_ctlblk {
unsigned long kprobe_status;
unsigned long kprobe_saved_imask;
- unsigned long kprobe_saved_ctl[3];
+ struct ctlreg kprobe_saved_ctl[3];
struct prev_kprobe prev_kprobe;
};
void arch_remove_kprobe(struct kprobe *p);
int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
-int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
#define flush_insn_slot(p) do { } while (0)
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 427f9528a7b6..67a298b6cf6e 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -777,6 +777,13 @@ struct kvm_vm_stat {
u64 inject_service_signal;
u64 inject_virtio;
u64 aen_forward;
+ u64 gmap_shadow_create;
+ u64 gmap_shadow_reuse;
+ u64 gmap_shadow_r1_entry;
+ u64 gmap_shadow_r2_entry;
+ u64 gmap_shadow_r3_entry;
+ u64 gmap_shadow_sg_entry;
+ u64 gmap_shadow_pg_entry;
};
struct kvm_arch_memory_slot {
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index 69ccc464a430..5dc1b6345006 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -11,6 +11,7 @@
#include <linux/types.h>
#include <asm/ptrace.h>
+#include <asm/ctlreg.h>
#include <asm/cpu.h>
#include <asm/types.h>
@@ -139,8 +140,8 @@ struct lowcore {
__u32 restart_flags; /* 0x0384 */
/* Address space pointer. */
- __u64 kernel_asce; /* 0x0388 */
- __u64 user_asce; /* 0x0390 */
+ struct ctlreg kernel_asce; /* 0x0388 */
+ struct ctlreg user_asce; /* 0x0390 */
/*
* The lpp and current_pid fields form a
@@ -199,7 +200,7 @@ struct lowcore {
__u32 clock_comp_save_area[2]; /* 0x1330 */
__u64 last_break_save_area; /* 0x1338 */
__u32 access_regs_save_area[16]; /* 0x1340 */
- __u64 cregs_save_area[16]; /* 0x1380 */
+ struct ctlreg cregs_save_area[16]; /* 0x1380 */
__u8 pad_0x1400[0x1500-0x1400]; /* 0x1400 */
/* Cryptography-counter designation */
__u64 ccd; /* 0x1500 */
@@ -221,12 +222,4 @@ static inline void set_prefix(__u32 address)
asm volatile("spx %0" : : "Q" (address) : "memory");
}
-static inline __u32 store_prefix(void)
-{
- __u32 address;
-
- asm volatile("stpx %0" : "=Q" (address));
- return address;
-}
-
#endif /* _ASM_S390_LOWCORE_H */
diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h
index 829d68e2c685..bb1b4bef1878 100644
--- a/arch/s390/include/asm/mmu.h
+++ b/arch/s390/include/asm/mmu.h
@@ -11,7 +11,6 @@ typedef struct {
cpumask_t cpu_attach_mask;
atomic_t flush_count;
unsigned int flush_mm;
- struct list_head pgtable_list;
struct list_head gmap_list;
unsigned long gmap_asce;
unsigned long asce;
@@ -39,7 +38,6 @@ typedef struct {
#define INIT_MM_CONTEXT(name) \
.context.lock = __SPIN_LOCK_UNLOCKED(name.context.lock), \
- .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), \
.context.gmap_list = LIST_HEAD_INIT(name.context.gmap_list),
#endif
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
index 2a38af5a00c2..929af18b0908 100644
--- a/arch/s390/include/asm/mmu_context.h
+++ b/arch/s390/include/asm/mmu_context.h
@@ -12,7 +12,7 @@
#include <linux/uaccess.h>
#include <linux/mm_types.h>
#include <asm/tlbflush.h>
-#include <asm/ctl_reg.h>
+#include <asm/ctlreg.h>
#include <asm-generic/mm_hooks.h>
#define init_new_context init_new_context
@@ -22,7 +22,6 @@ static inline int init_new_context(struct task_struct *tsk,
unsigned long asce_type, init_entry;
spin_lock_init(&mm->context.lock);
- INIT_LIST_HEAD(&mm->context.pgtable_list);
INIT_LIST_HEAD(&mm->context.gmap_list);
cpumask_clear(&mm->context.cpu_attach_mask);
atomic_set(&mm->context.flush_count, 0);
@@ -78,10 +77,10 @@ static inline void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *
if (next == &init_mm)
S390_lowcore.user_asce = s390_invalid_asce;
else
- S390_lowcore.user_asce = next->context.asce;
+ S390_lowcore.user_asce.val = next->context.asce;
cpumask_set_cpu(cpu, &next->context.cpu_attach_mask);
/* Clear previous user-ASCE from CR7 */
- __ctl_load(s390_invalid_asce, 7, 7);
+ local_ctl_load(7, &s390_invalid_asce);
if (prev != next)
cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask);
}
@@ -111,7 +110,7 @@ static inline void finish_arch_post_lock_switch(void)
__tlb_flush_mm_lazy(mm);
preempt_enable();
}
- __ctl_load(S390_lowcore.user_asce, 7, 7);
+ local_ctl_load(7, &S390_lowcore.user_asce);
}
#define activate_mm activate_mm
@@ -120,7 +119,7 @@ static inline void activate_mm(struct mm_struct *prev,
{
switch_mm(prev, next, current);
cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
- __ctl_load(S390_lowcore.user_asce, 7, 7);
+ local_ctl_load(7, &S390_lowcore.user_asce);
}
#include <asm-generic/mmu_context.h>
diff --git a/arch/s390/include/asm/page-states.h b/arch/s390/include/asm/page-states.h
index c33c4deb545f..08fcbd628120 100644
--- a/arch/s390/include/asm/page-states.h
+++ b/arch/s390/include/asm/page-states.h
@@ -7,6 +7,9 @@
#ifndef PAGE_STATES_H
#define PAGE_STATES_H
+#include <asm/sections.h>
+#include <asm/page.h>
+
#define ESSA_GET_STATE 0
#define ESSA_SET_STABLE 1
#define ESSA_SET_UNUSED 2
@@ -18,4 +21,60 @@
#define ESSA_MAX ESSA_SET_STABLE_NODAT
+extern int __bootdata_preserved(cmma_flag);
+
+static __always_inline unsigned long essa(unsigned long paddr, unsigned char cmd)
+{
+ unsigned long rc;
+
+ asm volatile(
+ " .insn rrf,0xb9ab0000,%[rc],%[paddr],%[cmd],0"
+ : [rc] "=d" (rc)
+ : [paddr] "d" (paddr),
+ [cmd] "i" (cmd));
+ return rc;
+}
+
+static __always_inline void __set_page_state(void *addr, unsigned long num_pages, unsigned char cmd)
+{
+ unsigned long paddr = __pa(addr) & PAGE_MASK;
+
+ while (num_pages--) {
+ essa(paddr, cmd);
+ paddr += PAGE_SIZE;
+ }
+}
+
+static inline void __set_page_unused(void *addr, unsigned long num_pages)
+{
+ __set_page_state(addr, num_pages, ESSA_SET_UNUSED);
+}
+
+static inline void __set_page_stable_dat(void *addr, unsigned long num_pages)
+{
+ __set_page_state(addr, num_pages, ESSA_SET_STABLE);
+}
+
+static inline void __set_page_stable_nodat(void *addr, unsigned long num_pages)
+{
+ __set_page_state(addr, num_pages, ESSA_SET_STABLE_NODAT);
+}
+
+static inline void __arch_set_page_nodat(void *addr, unsigned long num_pages)
+{
+ if (!cmma_flag)
+ return;
+ if (cmma_flag < 2)
+ __set_page_stable_dat(addr, num_pages);
+ else
+ __set_page_stable_nodat(addr, num_pages);
+}
+
+static inline void __arch_set_page_dat(void *addr, unsigned long num_pages)
+{
+ if (!cmma_flag)
+ return;
+ __set_page_stable_dat(addr, num_pages);
+}
+
#endif
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h
index cfec0743314e..73b9c3bf377f 100644
--- a/arch/s390/include/asm/page.h
+++ b/arch/s390/include/asm/page.h
@@ -164,7 +164,6 @@ static inline int page_reset_referenced(unsigned long addr)
struct page;
void arch_free_page(struct page *page, int order);
void arch_alloc_page(struct page *page, int order);
-void arch_set_page_dat(struct page *page, int order);
static inline int devmem_is_allowed(unsigned long pfn)
{
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index b248694e0024..e91cd6bbc330 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -159,13 +159,6 @@ struct zpci_dev {
unsigned long *dma_table;
int tlb_refresh;
- spinlock_t iommu_bitmap_lock;
- unsigned long *iommu_bitmap;
- unsigned long *lazy_bitmap;
- unsigned long iommu_size;
- unsigned long iommu_pages;
- unsigned int next_bit;
-
struct iommu_device iommu_dev; /* IOMMU core handle */
char res_name[16];
@@ -180,10 +173,6 @@ struct zpci_dev {
struct zpci_fmb *fmb;
u16 fmb_update; /* update interval */
u16 fmb_length;
- /* software counters */
- atomic64_t allocated_pages;
- atomic64_t mapped_pages;
- atomic64_t unmapped_pages;
u8 version;
enum pci_bus_speed max_bus_speed;
diff --git a/arch/s390/include/asm/pci_clp.h b/arch/s390/include/asm/pci_clp.h
index d6189ed14f84..f0c677ddd270 100644
--- a/arch/s390/include/asm/pci_clp.h
+++ b/arch/s390/include/asm/pci_clp.h
@@ -50,6 +50,9 @@ struct clp_fh_list_entry {
#define CLP_UTIL_STR_LEN 64
#define CLP_PFIP_NR_SEGMENTS 4
+/* PCI function type numbers */
+#define PCI_FUNC_TYPE_ISM 0x5 /* ISM device */
+
extern bool zpci_unique_uid;
struct clp_rsp_slpc_pci {
diff --git a/arch/s390/include/asm/pci_dma.h b/arch/s390/include/asm/pci_dma.h
index 7119c04c51c5..42d7cc4262ca 100644
--- a/arch/s390/include/asm/pci_dma.h
+++ b/arch/s390/include/asm/pci_dma.h
@@ -82,117 +82,16 @@ enum zpci_ioat_dtype {
#define ZPCI_TABLE_VALID_MASK 0x20
#define ZPCI_TABLE_PROT_MASK 0x200
-static inline unsigned int calc_rtx(dma_addr_t ptr)
-{
- return ((unsigned long) ptr >> ZPCI_RT_SHIFT) & ZPCI_INDEX_MASK;
-}
-
-static inline unsigned int calc_sx(dma_addr_t ptr)
-{
- return ((unsigned long) ptr >> ZPCI_ST_SHIFT) & ZPCI_INDEX_MASK;
-}
-
-static inline unsigned int calc_px(dma_addr_t ptr)
-{
- return ((unsigned long) ptr >> PAGE_SHIFT) & ZPCI_PT_MASK;
-}
-
-static inline void set_pt_pfaa(unsigned long *entry, phys_addr_t pfaa)
-{
- *entry &= ZPCI_PTE_FLAG_MASK;
- *entry |= (pfaa & ZPCI_PTE_ADDR_MASK);
-}
-
-static inline void set_rt_sto(unsigned long *entry, phys_addr_t sto)
-{
- *entry &= ZPCI_RTE_FLAG_MASK;
- *entry |= (sto & ZPCI_RTE_ADDR_MASK);
- *entry |= ZPCI_TABLE_TYPE_RTX;
-}
-
-static inline void set_st_pto(unsigned long *entry, phys_addr_t pto)
-{
- *entry &= ZPCI_STE_FLAG_MASK;
- *entry |= (pto & ZPCI_STE_ADDR_MASK);
- *entry |= ZPCI_TABLE_TYPE_SX;
-}
-
-static inline void validate_rt_entry(unsigned long *entry)
-{
- *entry &= ~ZPCI_TABLE_VALID_MASK;
- *entry &= ~ZPCI_TABLE_OFFSET_MASK;
- *entry |= ZPCI_TABLE_VALID;
- *entry |= ZPCI_TABLE_LEN_RTX;
-}
-
-static inline void validate_st_entry(unsigned long *entry)
-{
- *entry &= ~ZPCI_TABLE_VALID_MASK;
- *entry |= ZPCI_TABLE_VALID;
-}
-
-static inline void invalidate_pt_entry(unsigned long *entry)
-{
- WARN_ON_ONCE((*entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_INVALID);
- *entry &= ~ZPCI_PTE_VALID_MASK;
- *entry |= ZPCI_PTE_INVALID;
-}
-
-static inline void validate_pt_entry(unsigned long *entry)
-{
- WARN_ON_ONCE((*entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID);
- *entry &= ~ZPCI_PTE_VALID_MASK;
- *entry |= ZPCI_PTE_VALID;
-}
-
-static inline void entry_set_protected(unsigned long *entry)
-{
- *entry &= ~ZPCI_TABLE_PROT_MASK;
- *entry |= ZPCI_TABLE_PROTECTED;
-}
-
-static inline void entry_clr_protected(unsigned long *entry)
-{
- *entry &= ~ZPCI_TABLE_PROT_MASK;
- *entry |= ZPCI_TABLE_UNPROTECTED;
-}
-
-static inline int reg_entry_isvalid(unsigned long entry)
-{
- return (entry & ZPCI_TABLE_VALID_MASK) == ZPCI_TABLE_VALID;
-}
-
-static inline int pt_entry_isvalid(unsigned long entry)
-{
- return (entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID;
-}
-
-static inline unsigned long *get_rt_sto(unsigned long entry)
-{
- if ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_RTX)
- return phys_to_virt(entry & ZPCI_RTE_ADDR_MASK);
- else
- return NULL;
-
-}
-
-static inline unsigned long *get_st_pto(unsigned long entry)
-{
- if ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_SX)
- return phys_to_virt(entry & ZPCI_STE_ADDR_MASK);
- else
- return NULL;
-}
-
-/* Prototypes */
-void dma_free_seg_table(unsigned long);
-unsigned long *dma_alloc_cpu_table(gfp_t gfp);
-void dma_cleanup_tables(unsigned long *);
-unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr,
- gfp_t gfp);
-void dma_update_cpu_trans(unsigned long *entry, phys_addr_t page_addr, int flags);
-
-extern const struct dma_map_ops s390_pci_dma_ops;
+struct zpci_iommu_ctrs {
+ atomic64_t mapped_pages;
+ atomic64_t unmapped_pages;
+ atomic64_t global_rpcits;
+ atomic64_t sync_map_rpcits;
+ atomic64_t sync_rpcits;
+};
+
+struct zpci_dev;
+struct zpci_iommu_ctrs *zpci_get_iommu_ctrs(struct zpci_dev *zdev);
#endif
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index 376b4b23bdaa..502d655fe6ae 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -25,7 +25,6 @@ void crst_table_free(struct mm_struct *, unsigned long *);
unsigned long *page_table_alloc(struct mm_struct *);
struct page *page_table_alloc_pgste(struct mm_struct *mm);
void page_table_free(struct mm_struct *, unsigned long *);
-void page_table_free_rcu(struct mmu_gather *, unsigned long *, unsigned long);
void page_table_free_pgste(struct page *page);
extern int page_table_allocate_pgste;
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index fb3ee7758b76..601e87fa8a9a 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -18,6 +18,7 @@
#include <linux/radix-tree.h>
#include <linux/atomic.h>
#include <asm/sections.h>
+#include <asm/ctlreg.h>
#include <asm/bug.h>
#include <asm/page.h>
#include <asm/uv.h>
@@ -25,7 +26,7 @@
extern pgd_t swapper_pg_dir[];
extern pgd_t invalid_pg_dir[];
extern void paging_init(void);
-extern unsigned long s390_invalid_asce;
+extern struct ctlreg s390_invalid_asce;
enum {
PG_DIRECT_MAP_4K = 0,
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index dc17896a001a..c15eadbb9983 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -228,7 +228,6 @@ typedef struct thread_struct thread_struct;
execve_tail(); \
} while (0)
-/* Forward declaration, a strange C thing */
struct task_struct;
struct mm_struct;
struct seq_file;
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index 25cadc2b9cff..df316436d2e1 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -125,9 +125,6 @@ static inline void vmcp_cma_reserve(void) { }
void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault);
-void cmma_init(void);
-void cmma_init_nodat(void);
-
extern void (*_machine_restart)(char *command);
extern void (*_machine_halt)(void);
extern void (*_machine_power_off)(void);
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h
index 73ed2781073b..6e5b1b4b19a9 100644
--- a/arch/s390/include/asm/smp.h
+++ b/arch/s390/include/asm/smp.h
@@ -59,7 +59,6 @@ static inline void smp_cpus_done(unsigned int max_cpus)
{
}
-extern int smp_reinit_ipl_cpu(void);
extern int smp_rescan_cpus(void);
extern void __noreturn cpu_die(void);
extern void __cpu_die(unsigned int cpu);
diff --git a/arch/s390/include/asm/stacktrace.h b/arch/s390/include/asm/stacktrace.h
index 78f7b729b65f..31ec4f545e03 100644
--- a/arch/s390/include/asm/stacktrace.h
+++ b/arch/s390/include/asm/stacktrace.h
@@ -6,6 +6,13 @@
#include <linux/ptrace.h>
#include <asm/switch_to.h>
+struct stack_frame_user {
+ unsigned long back_chain;
+ unsigned long empty1[5];
+ unsigned long gprs[10];
+ unsigned long empty2[4];
+};
+
enum stack_type {
STACK_TYPE_UNKNOWN,
STACK_TYPE_TASK,
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
index 383b1f91442c..d1455a601adc 100644
--- a/arch/s390/include/asm/tlb.h
+++ b/arch/s390/include/asm/tlb.h
@@ -69,12 +69,9 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
tlb->cleared_pmds = 1;
- /*
- * page_table_free_rcu takes care of the allocation bit masks
- * of the 2K table fragments in the 4K page table page,
- * then calls tlb_remove_table.
- */
- page_table_free_rcu(tlb, (unsigned long *) pte, address);
+ if (mm_alloc_pgste(tlb->mm))
+ gmap_unlink(tlb->mm, (unsigned long *)pte, address);
+ tlb_remove_ptdesc(tlb, pte);
}
/*
@@ -112,7 +109,7 @@ static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
__tlb_adjust_range(tlb, address, PAGE_SIZE);
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
- tlb_remove_table(tlb, p4d);
+ tlb_remove_ptdesc(tlb, p4d);
}
/*
@@ -130,7 +127,7 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
tlb->cleared_p4ds = 1;
- tlb_remove_table(tlb, pud);
+ tlb_remove_ptdesc(tlb, pud);
}
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index 8a8c64a678c4..81ae8a98e7ec 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -15,7 +15,6 @@
*/
#include <asm/asm-extable.h>
#include <asm/processor.h>
-#include <asm/ctl_reg.h>
#include <asm/extable.h>
#include <asm/facility.h>
#include <asm-generic/access_ok.h>
diff --git a/arch/s390/include/asm/word-at-a-time.h b/arch/s390/include/asm/word-at-a-time.h
new file mode 100644
index 000000000000..2579f1694b82
--- /dev/null
+++ b/arch/s390/include/asm/word-at-a-time.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_WORD_AT_A_TIME_H
+#define _ASM_WORD_AT_A_TIME_H
+
+#include <linux/kernel.h>
+#include <asm/asm-extable.h>
+#include <asm/bitsperlong.h>
+
+struct word_at_a_time {
+ const unsigned long bits;
+};
+
+#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x7f) }
+
+static inline unsigned long prep_zero_mask(unsigned long val, unsigned long data, const struct word_at_a_time *c)
+{
+ return data;
+}
+
+static inline unsigned long create_zero_mask(unsigned long data)
+{
+ return __fls(data);
+}
+
+static inline unsigned long find_zero(unsigned long data)
+{
+ return (data ^ (BITS_PER_LONG - 1)) >> 3;
+}
+
+static inline unsigned long has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c)
+{
+ unsigned long mask = (val & c->bits) + c->bits;
+
+ *data = ~(mask | val | c->bits);
+ return *data;
+}
+
+static inline unsigned long zero_bytemask(unsigned long data)
+{
+ return ~1UL << data;
+}
+
+/*
+ * Load an unaligned word from kernel space.
+ *
+ * In the (very unlikely) case of the word being a page-crosser
+ * and the next page not being mapped, take the exception and
+ * return zeroes in the non-existing part.
+ */
+static inline unsigned long load_unaligned_zeropad(const void *addr)
+{
+ unsigned long data;
+
+ asm volatile(
+ "0: lg %[data],0(%[addr])\n"
+ "1: nopr %%r7\n"
+ EX_TABLE_ZEROPAD(0b, 1b, %[data], %[addr])
+ EX_TABLE_ZEROPAD(1b, 1b, %[data], %[addr])
+ : [data] "=d" (data)
+ : [addr] "a" (addr), "m" (*(unsigned long *)addr));
+ return data;
+}
+
+#endif /* _ASM_WORD_AT_A_TIME_H */
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 0df2b88cc0da..353def93973b 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -37,7 +37,7 @@ CFLAGS_unwind_bc.o += -fno-optimize-sibling-calls
obj-y := head64.o traps.o time.o process.o earlypgm.o early.o setup.o idle.o vtime.o
obj-y += processor.o syscall.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o cpufeature.o
-obj-y += sysinfo.o lgr.o os_info.o
+obj-y += sysinfo.o lgr.o os_info.o ctlreg.o
obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o
obj-y += entry.o reipl.o kdebugfs.o alternative.o
obj-y += nospec-branch.o ipl_vmparm.o machine_kexec_reloc.o unwind_bc.o
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index 7af69948b290..514feadd4c58 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -498,7 +498,7 @@ static int get_mem_chunk_cnt(void)
/*
* Initialize ELF loads (new kernel)
*/
-static void loads_init(Elf64_Phdr *phdr, u64 loads_offset)
+static void loads_init(Elf64_Phdr *phdr)
{
phys_addr_t start, end;
u64 idx;
@@ -507,7 +507,7 @@ static void loads_init(Elf64_Phdr *phdr, u64 loads_offset)
phdr->p_filesz = end - start;
phdr->p_type = PT_LOAD;
phdr->p_offset = start;
- phdr->p_vaddr = start;
+ phdr->p_vaddr = (unsigned long)__va(start);
phdr->p_paddr = start;
phdr->p_memsz = end - start;
phdr->p_flags = PF_R | PF_W | PF_X;
@@ -612,7 +612,7 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off);
/* Init loads */
hdr_off = PTR_DIFF(ptr, hdr);
- loads_init(phdr_loads, hdr_off);
+ loads_init(phdr_loads);
*addr = (unsigned long long) hdr;
*size = (unsigned long long) hdr_off;
BUG_ON(elfcorehdr_size > alloc_size);
diff --git a/arch/s390/kernel/ctlreg.c b/arch/s390/kernel/ctlreg.c
new file mode 100644
index 000000000000..8cc26cf2c64a
--- /dev/null
+++ b/arch/s390/kernel/ctlreg.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright IBM Corp. 1999, 2023
+ */
+
+#include <linux/irqflags.h>
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/cache.h>
+#include <asm/abs_lowcore.h>
+#include <asm/ctlreg.h>
+
+/*
+ * ctl_lock guards access to global control register contents which
+ * are kept in the control register save area within absolute lowcore
+ * at physical address zero.
+ */
+static DEFINE_SPINLOCK(system_ctl_lock);
+
+void system_ctlreg_lock(void)
+ __acquires(&system_ctl_lock)
+{
+ spin_lock(&system_ctl_lock);
+}
+
+void system_ctlreg_unlock(void)
+ __releases(&system_ctl_lock)
+{
+ spin_unlock(&system_ctl_lock);
+}
+
+static bool system_ctlreg_area_init __ro_after_init;
+
+void __init system_ctlreg_init_save_area(struct lowcore *lc)
+{
+ struct lowcore *abs_lc;
+
+ abs_lc = get_abs_lowcore();
+ __local_ctl_store(0, 15, lc->cregs_save_area);
+ __local_ctl_store(0, 15, abs_lc->cregs_save_area);
+ put_abs_lowcore(abs_lc);
+ system_ctlreg_area_init = true;
+}
+
+struct ctlreg_parms {
+ unsigned long andval;
+ unsigned long orval;
+ unsigned long val;
+ int request;
+ int cr;
+};
+
+static void ctlreg_callback(void *info)
+{
+ struct ctlreg_parms *pp = info;
+ struct ctlreg regs[16];
+
+ __local_ctl_store(0, 15, regs);
+ if (pp->request == CTLREG_LOAD) {
+ regs[pp->cr].val = pp->val;
+ } else {
+ regs[pp->cr].val &= pp->andval;
+ regs[pp->cr].val |= pp->orval;
+ }
+ __local_ctl_load(0, 15, regs);
+}
+
+static void system_ctlreg_update(void *info)
+{
+ unsigned long flags;
+
+ if (system_state == SYSTEM_BOOTING) {
+ /*
+ * For very early calls do not call on_each_cpu()
+ * since not everything might be setup.
+ */
+ local_irq_save(flags);
+ ctlreg_callback(info);
+ local_irq_restore(flags);
+ } else {
+ on_each_cpu(ctlreg_callback, info, 1);
+ }
+}
+
+void system_ctlreg_modify(unsigned int cr, unsigned long data, int request)
+{
+ struct ctlreg_parms pp = { .cr = cr, .request = request, };
+ struct lowcore *abs_lc;
+
+ switch (request) {
+ case CTLREG_SET_BIT:
+ pp.orval = 1UL << data;
+ pp.andval = -1UL;
+ break;
+ case CTLREG_CLEAR_BIT:
+ pp.orval = 0;
+ pp.andval = ~(1UL << data);
+ break;
+ case CTLREG_LOAD:
+ pp.val = data;
+ break;
+ }
+ if (system_ctlreg_area_init) {
+ system_ctlreg_lock();
+ abs_lc = get_abs_lowcore();
+ if (request == CTLREG_LOAD) {
+ abs_lc->cregs_save_area[cr].val = pp.val;
+ } else {
+ abs_lc->cregs_save_area[cr].val &= pp.andval;
+ abs_lc->cregs_save_area[cr].val |= pp.orval;
+ }
+ put_abs_lowcore(abs_lc);
+ system_ctlreg_update(&pp);
+ system_ctlreg_unlock();
+ } else {
+ system_ctlreg_update(&pp);
+ }
+}
+EXPORT_SYMBOL(system_ctlreg_modify);
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index a85e0c3e7027..85328a0ef3b6 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -978,7 +978,6 @@ static struct ctl_table s390dbf_table[] = {
.mode = S_IRUGO | S_IWUSR,
.proc_handler = s390dbf_procactive,
},
- { }
};
static struct ctl_table_header *s390dbf_sysctl_header;
diff --git a/arch/s390/kernel/diag.c b/arch/s390/kernel/diag.c
index f9f06cd8fcee..92fdc35f028c 100644
--- a/arch/s390/kernel/diag.c
+++ b/arch/s390/kernel/diag.c
@@ -245,6 +245,7 @@ EXPORT_SYMBOL(diag8c);
int diag224(void *ptr)
{
+ unsigned long addr = __pa(ptr);
int rc = -EOPNOTSUPP;
diag_stat_inc(DIAG_STAT_X224);
@@ -253,7 +254,7 @@ int diag224(void *ptr)
"0: lhi %0,0x0\n"
"1:\n"
EX_TABLE(0b,1b)
- : "+d" (rc) :"d" (0), "d" (ptr) : "memory");
+ : "+d" (rc) :"d" (0), "d" (addr) : "memory");
return rc;
}
EXPORT_SYMBOL(diag224);
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 442ce0489e1a..eb43e5922a25 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -46,6 +46,7 @@ decompressor_handled_param(vmalloc);
decompressor_handled_param(dfltcc);
decompressor_handled_param(facilities);
decompressor_handled_param(nokaslr);
+decompressor_handled_param(cmma);
#if IS_ENABLED(CONFIG_KVM)
decompressor_handled_param(prot_virt);
#endif
@@ -216,7 +217,7 @@ static __init void detect_machine_facilities(void)
{
if (test_facility(8)) {
S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT1;
- __ctl_set_bit(0, 23);
+ system_ctl_set_bit(0, CR0_EDAT_BIT);
}
if (test_facility(78))
S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT2;
@@ -224,13 +225,13 @@ static __init void detect_machine_facilities(void)
S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE;
if (test_facility(50) && test_facility(73)) {
S390_lowcore.machine_flags |= MACHINE_FLAG_TE;
- __ctl_set_bit(0, 55);
+ system_ctl_set_bit(0, CR0_TRANSACTIONAL_EXECUTION_BIT);
}
if (test_facility(51))
S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC;
if (test_facility(129)) {
S390_lowcore.machine_flags |= MACHINE_FLAG_VX;
- __ctl_set_bit(0, 17);
+ system_ctl_set_bit(0, CR0_VECTOR_BIT);
}
if (test_facility(130))
S390_lowcore.machine_flags |= MACHINE_FLAG_NX;
@@ -240,7 +241,7 @@ static __init void detect_machine_facilities(void)
/* Enabled signed clock comparator comparisons */
S390_lowcore.machine_flags |= MACHINE_FLAG_SCC;
clock_comparator_max = -1ULL >> 1;
- __ctl_set_bit(0, 53);
+ system_ctl_set_bit(0, CR0_CLOCK_COMPARATOR_SIGN_BIT);
}
if (IS_ENABLED(CONFIG_PCI) && test_facility(153)) {
S390_lowcore.machine_flags |= MACHINE_FLAG_PCI_MIO;
@@ -258,15 +259,9 @@ static inline void save_vector_registers(void)
#endif
}
-static inline void setup_control_registers(void)
+static inline void setup_low_address_protection(void)
{
- unsigned long reg;
-
- __ctl_store(reg, 0, 0);
- reg |= CR0_LOW_ADDRESS_PROTECTION;
- reg |= CR0_EMERGENCY_SIGNAL_SUBMASK;
- reg |= CR0_EXTERNAL_CALL_SUBMASK;
- __ctl_load(reg, 0, 0);
+ system_ctl_set_bit(0, CR0_LOW_ADDRESS_PROTECTION_BIT);
}
static inline void setup_access_registers(void)
@@ -279,7 +274,7 @@ static inline void setup_access_registers(void)
static int __init disable_vector_extension(char *str)
{
S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX;
- __ctl_clear_bit(0, 17);
+ system_ctl_clear_bit(0, CR0_VECTOR_BIT);
return 0;
}
early_param("novx", disable_vector_extension);
@@ -314,7 +309,7 @@ void __init startup_init(void)
save_vector_registers();
setup_topology();
sclp_early_detect();
- setup_control_registers();
+ setup_low_address_protection();
setup_access_registers();
lockdep_on();
}
diff --git a/arch/s390/kernel/guarded_storage.c b/arch/s390/kernel/guarded_storage.c
index d14dd1c2e524..0b68168d9566 100644
--- a/arch/s390/kernel/guarded_storage.c
+++ b/arch/s390/kernel/guarded_storage.c
@@ -28,7 +28,7 @@ static int gs_enable(void)
return -ENOMEM;
gs_cb->gsd = 25;
preempt_disable();
- __ctl_set_bit(2, 4);
+ local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT);
load_gs_cb(gs_cb);
current->thread.gs_cb = gs_cb;
preempt_enable();
@@ -42,7 +42,7 @@ static int gs_disable(void)
preempt_disable();
kfree(current->thread.gs_cb);
current->thread.gs_cb = NULL;
- __ctl_clear_bit(2, 4);
+ local_ctl_clear_bit(2, CR2_GUARDED_STORAGE_BIT);
preempt_enable();
}
return 0;
@@ -84,7 +84,7 @@ void gs_load_bc_cb(struct pt_regs *regs)
if (gs_cb) {
kfree(current->thread.gs_cb);
current->thread.gs_bc_cb = NULL;
- __ctl_set_bit(2, 4);
+ local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT);
load_gs_cb(gs_cb);
current->thread.gs_cb = gs_cb;
}
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 05e51666db03..ba75f6bee774 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -666,6 +666,7 @@ static int __init ipl_init(void)
&ipl_ccw_attr_group_lpar);
break;
case IPL_TYPE_ECKD:
+ case IPL_TYPE_ECKD_DUMP:
rc = sysfs_create_group(&ipl_kset->kobj, &ipl_eckd_attr_group);
break;
case IPL_TYPE_FCP:
@@ -2381,7 +2382,7 @@ void s390_reset_system(void)
set_prefix(0);
/* Disable lowcore protection */
- __ctl_clear_bit(0, 28);
+ local_ctl_clear_bit(0, CR0_LOW_ADDRESS_PROTECTION_BIT);
diag_amode31_ops.diag308_reset();
}
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index b020ff17d206..6f71b0ce1068 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -385,7 +385,7 @@ void irq_subclass_register(enum irq_subclass subclass)
{
spin_lock(&irq_subclass_lock);
if (!irq_subclass_refcount[subclass])
- ctl_set_bit(0, subclass);
+ system_ctl_set_bit(0, subclass);
irq_subclass_refcount[subclass]++;
spin_unlock(&irq_subclass_lock);
}
@@ -396,7 +396,7 @@ void irq_subclass_unregister(enum irq_subclass subclass)
spin_lock(&irq_subclass_lock);
irq_subclass_refcount[subclass]--;
if (!irq_subclass_refcount[subclass])
- ctl_clear_bit(0, subclass);
+ system_ctl_clear_bit(0, subclass);
spin_unlock(&irq_subclass_lock);
}
EXPORT_SYMBOL(irq_subclass_unregister);
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index d4b863ed0aa7..f0cf20d4b3c5 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -224,20 +224,27 @@ static void enable_singlestep(struct kprobe_ctlblk *kcb,
struct pt_regs *regs,
unsigned long ip)
{
- struct per_regs per_kprobe;
+ union {
+ struct ctlreg regs[3];
+ struct {
+ struct ctlreg control;
+ struct ctlreg start;
+ struct ctlreg end;
+ };
+ } per_kprobe;
/* Set up the PER control registers %cr9-%cr11 */
- per_kprobe.control = PER_EVENT_IFETCH;
- per_kprobe.start = ip;
- per_kprobe.end = ip;
+ per_kprobe.control.val = PER_EVENT_IFETCH;
+ per_kprobe.start.val = ip;
+ per_kprobe.end.val = ip;
/* Save control regs and psw mask */
- __ctl_store(kcb->kprobe_saved_ctl, 9, 11);
+ __local_ctl_store(9, 11, kcb->kprobe_saved_ctl);
kcb->kprobe_saved_imask = regs->psw.mask &
(PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT);
/* Set PER control regs, turns on single step for the given address */
- __ctl_load(per_kprobe, 9, 11);
+ __local_ctl_load(9, 11, per_kprobe.regs);
regs->psw.mask |= PSW_MASK_PER;
regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT);
regs->psw.addr = ip;
@@ -249,7 +256,7 @@ static void disable_singlestep(struct kprobe_ctlblk *kcb,
unsigned long ip)
{
/* Restore control regs and psw mask, set new psw address */
- __ctl_load(kcb->kprobe_saved_ctl, 9, 11);
+ __local_ctl_load(9, 11, kcb->kprobe_saved_ctl);
regs->psw.mask &= ~PSW_MASK_PER;
regs->psw.mask |= kcb->kprobe_saved_imask;
regs->psw.addr = ip;
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index ce65fc01671f..bb0d4d68fcbe 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -94,12 +94,12 @@ static noinline void __machine_kdump(void *image)
if (MACHINE_HAS_VX)
save_vx_regs((__vector128 *) mcesa->vector_save_area);
if (MACHINE_HAS_GS) {
- __ctl_store(cr2_old.val, 2, 2);
+ local_ctl_store(2, &cr2_old.reg);
cr2_new = cr2_old;
cr2_new.gse = 1;
- __ctl_load(cr2_new.val, 2, 2);
+ local_ctl_load(2, &cr2_new.reg);
save_gs_cb((struct gs_cb *) mcesa->guarded_storage_save_area);
- __ctl_load(cr2_old.val, 2, 2);
+ local_ctl_load(2, &cr2_old.reg);
}
/*
* To create a good backchain for this CPU in the dump store_status
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c
index 38ec0487521c..0daf0f1cdfc9 100644
--- a/arch/s390/kernel/nmi.c
+++ b/arch/s390/kernel/nmi.c
@@ -22,13 +22,13 @@
#include <linux/kvm_host.h>
#include <linux/export.h>
#include <asm/lowcore.h>
+#include <asm/ctlreg.h>
#include <asm/smp.h>
#include <asm/stp.h>
#include <asm/cputime.h>
#include <asm/nmi.h>
#include <asm/crw.h>
#include <asm/switch_to.h>
-#include <asm/ctl_reg.h>
#include <asm/asm-offsets.h>
#include <asm/pai.h>
#include <asm/vx-insn.h>
@@ -131,10 +131,10 @@ static notrace void s390_handle_damage(void)
* Disable low address protection and make machine check new PSW a
* disabled wait PSW. Any additional machine check cannot be handled.
*/
- __ctl_store(cr0.val, 0, 0);
+ local_ctl_store(0, &cr0.reg);
cr0_new = cr0;
cr0_new.lap = 0;
- __ctl_load(cr0_new.val, 0, 0);
+ local_ctl_load(0, &cr0_new.reg);
psw_save = S390_lowcore.mcck_new_psw;
psw_bits(S390_lowcore.mcck_new_psw).io = 0;
psw_bits(S390_lowcore.mcck_new_psw).ext = 0;
@@ -146,7 +146,7 @@ static notrace void s390_handle_damage(void)
* values. This makes possible system dump analysis easier.
*/
S390_lowcore.mcck_new_psw = psw_save;
- __ctl_load(cr0.val, 0, 0);
+ local_ctl_load(0, &cr0.reg);
disabled_wait();
while (1);
}
@@ -185,7 +185,7 @@ void s390_handle_mcck(void)
static int mchchk_wng_posted = 0;
/* Use single cpu clear, as we cannot handle smp here. */
- __ctl_clear_bit(14, 24); /* Disable WARNING MCH */
+ local_ctl_clear_bit(14, CR14_WARNING_SUBMASK_BIT);
if (xchg(&mchchk_wng_posted, 1) == 0)
kill_cad_pid(SIGPWR, 1);
}
@@ -269,9 +269,9 @@ static int notrace s390_validate_registers(union mci mci)
*/
if (!mci.vr && !test_cpu_flag(CIF_MCCK_GUEST))
kill_task = 1;
- cr0.val = S390_lowcore.cregs_save_area[0];
+ cr0.reg = S390_lowcore.cregs_save_area[0];
cr0.afp = cr0.vx = 1;
- __ctl_load(cr0.val, 0, 0);
+ local_ctl_load(0, &cr0.reg);
asm volatile(
" la 1,%0\n"
" VLM 0,15,0,1\n"
@@ -279,7 +279,7 @@ static int notrace s390_validate_registers(union mci mci)
:
: "Q" (*(struct vx_array *)mcesa->vector_save_area)
: "1");
- __ctl_load(S390_lowcore.cregs_save_area[0], 0, 0);
+ local_ctl_load(0, &S390_lowcore.cregs_save_area[0]);
}
/* Validate access registers */
asm volatile(
@@ -290,7 +290,7 @@ static int notrace s390_validate_registers(union mci mci)
if (!mci.ar)
kill_task = 1;
/* Validate guarded storage registers */
- cr2.val = S390_lowcore.cregs_save_area[2];
+ cr2.reg = S390_lowcore.cregs_save_area[2];
if (cr2.gse) {
if (!mci.gs) {
/*
@@ -505,9 +505,9 @@ NOKPROBE_SYMBOL(s390_do_machine_check);
static int __init machine_check_init(void)
{
- ctl_set_bit(14, 25); /* enable external damage MCH */
- ctl_set_bit(14, 27); /* enable system recovery MCH */
- ctl_set_bit(14, 24); /* enable warning MCH */
+ system_ctl_set_bit(14, CR14_EXTERNAL_DAMAGE_SUBMASK_BIT);
+ system_ctl_set_bit(14, CR14_RECOVERY_SUBMASK_BIT);
+ system_ctl_set_bit(14, CR14_WARNING_SUBMASK_BIT);
return 0;
}
early_initcall(machine_check_init);
diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c
index 850c11ea631a..41ed6e0f0a2a 100644
--- a/arch/s390/kernel/perf_cpum_cf.c
+++ b/arch/s390/kernel/perf_cpum_cf.c
@@ -1193,7 +1193,7 @@ static int __init cpumf_pmu_init(void)
* Clear bit 15 of cr0 to unauthorize problem-state to
* extract measurement counters
*/
- ctl_clear_bit(0, 48);
+ system_ctl_clear_bit(0, CR0_CPUMF_EXTRACTION_AUTH_BIT);
/* register handler for measurement-alert interruptions */
rc = register_external_irq(EXT_IRQ_MEASURE_ALERT,
diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c
index c27321cb0969..dfa77da2fd2e 100644
--- a/arch/s390/kernel/perf_event.c
+++ b/arch/s390/kernel/perf_event.c
@@ -15,7 +15,10 @@
#include <linux/export.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/compat.h>
#include <linux/sysfs.h>
+#include <asm/stacktrace.h>
#include <asm/irq.h>
#include <asm/cpu_mf.h>
#include <asm/lowcore.h>
@@ -212,6 +215,44 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
}
}
+void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
+ struct pt_regs *regs)
+{
+ struct stack_frame_user __user *sf;
+ unsigned long ip, sp;
+ bool first = true;
+
+ if (is_compat_task())
+ return;
+ perf_callchain_store(entry, instruction_pointer(regs));
+ sf = (void __user *)user_stack_pointer(regs);
+ pagefault_disable();
+ while (entry->nr < entry->max_stack) {
+ if (__get_user(sp, &sf->back_chain))
+ break;
+ if (__get_user(ip, &sf->gprs[8]))
+ break;
+ if (ip & 0x1) {
+ /*
+ * If the instruction address is invalid, and this
+ * is the first stack frame, assume r14 has not
+ * been written to the stack yet. Otherwise exit.
+ */
+ if (first && !(regs->gprs[14] & 0x1))
+ ip = regs->gprs[14];
+ else
+ break;
+ }
+ perf_callchain_store(entry, ip);
+ /* Sanity check: ABI requires SP to be aligned 8 bytes. */
+ if (!sp || sp & 0x7)
+ break;
+ sf = (void __user *)sp;
+ first = false;
+ }
+ pagefault_enable();
+}
+
/* Perf definitions for PMU event attributes in sysfs */
ssize_t cpumf_events_sysfs_show(struct device *dev,
struct device_attribute *attr, char *page)
diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c
index fe7d1774ded1..39a91b00438a 100644
--- a/arch/s390/kernel/perf_pai_crypto.c
+++ b/arch/s390/kernel/perf_pai_crypto.c
@@ -16,8 +16,7 @@
#include <linux/export.h>
#include <linux/io.h>
#include <linux/perf_event.h>
-
-#include <asm/ctl_reg.h>
+#include <asm/ctlreg.h>
#include <asm/pai.h>
#include <asm/debug.h>
@@ -41,7 +40,43 @@ struct paicrypt_map {
struct perf_event *event; /* Perf event for sampling */
};
-static DEFINE_PER_CPU(struct paicrypt_map, paicrypt_map);
+struct paicrypt_mapptr {
+ struct paicrypt_map *mapptr;
+};
+
+static struct paicrypt_root { /* Anchor to per CPU data */
+ refcount_t refcnt; /* Overall active events */
+ struct paicrypt_mapptr __percpu *mapptr;
+} paicrypt_root;
+
+/* Free per CPU data when the last event is removed. */
+static void paicrypt_root_free(void)
+{
+ if (refcount_dec_and_test(&paicrypt_root.refcnt)) {
+ free_percpu(paicrypt_root.mapptr);
+ paicrypt_root.mapptr = NULL;
+ }
+ debug_sprintf_event(cfm_dbg, 5, "%s root.refcount %d\n", __func__,
+ refcount_read(&paicrypt_root.refcnt));
+}
+
+/*
+ * On initialization of first event also allocate per CPU data dynamically.
+ * Start with an array of pointers, the array size is the maximum number of
+ * CPUs possible, which might be larger than the number of CPUs currently
+ * online.
+ */
+static int paicrypt_root_alloc(void)
+{
+ if (!refcount_inc_not_zero(&paicrypt_root.refcnt)) {
+ /* The memory is already zeroed. */
+ paicrypt_root.mapptr = alloc_percpu(struct paicrypt_mapptr);
+ if (!paicrypt_root.mapptr)
+ return -ENOMEM;
+ refcount_set(&paicrypt_root.refcnt, 1);
+ }
+ return 0;
+}
/* Release the PMU if event is the last perf event */
static DEFINE_MUTEX(pai_reserve_mutex);
@@ -51,7 +86,9 @@ static DEFINE_MUTEX(pai_reserve_mutex);
*/
static void paicrypt_event_destroy(struct perf_event *event)
{
- struct paicrypt_map *cpump = per_cpu_ptr(&paicrypt_map, event->cpu);
+ struct paicrypt_mapptr *mp = per_cpu_ptr(paicrypt_root.mapptr,
+ event->cpu);
+ struct paicrypt_map *cpump = mp->mapptr;
cpump->event = NULL;
static_branch_dec(&pai_key);
@@ -66,11 +103,11 @@ static void paicrypt_event_destroy(struct perf_event *event)
__func__, (unsigned long)cpump->page,
cpump->save);
free_page((unsigned long)cpump->page);
- cpump->page = NULL;
kvfree(cpump->save);
- cpump->save = NULL;
- cpump->mode = PAI_MODE_NONE;
+ kfree(cpump);
+ mp->mapptr = NULL;
}
+ paicrypt_root_free();
mutex_unlock(&pai_reserve_mutex);
}
@@ -86,7 +123,8 @@ static u64 paicrypt_getctr(struct paicrypt_map *cpump, int nr, bool kernel)
*/
static u64 paicrypt_getdata(struct perf_event *event, bool kernel)
{
- struct paicrypt_map *cpump = this_cpu_ptr(&paicrypt_map);
+ struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr);
+ struct paicrypt_map *cpump = mp->mapptr;
u64 sum = 0;
int i;
@@ -132,11 +170,31 @@ static u64 paicrypt_getall(struct perf_event *event)
*
* Allocate the memory for the event.
*/
-static int paicrypt_busy(struct perf_event_attr *a, struct paicrypt_map *cpump)
+static struct paicrypt_map *paicrypt_busy(struct perf_event *event)
{
- int rc = 0;
+ struct perf_event_attr *a = &event->attr;
+ struct paicrypt_map *cpump = NULL;
+ struct paicrypt_mapptr *mp;
+ int rc;
mutex_lock(&pai_reserve_mutex);
+
+ /* Allocate root node */
+ rc = paicrypt_root_alloc();
+ if (rc)
+ goto unlock;
+
+ /* Allocate node for this event */
+ mp = per_cpu_ptr(paicrypt_root.mapptr, event->cpu);
+ cpump = mp->mapptr;
+ if (!cpump) { /* Paicrypt_map allocated? */
+ cpump = kzalloc(sizeof(*cpump), GFP_KERNEL);
+ if (!cpump) {
+ rc = -ENOMEM;
+ goto free_root;
+ }
+ }
+
if (a->sample_period) { /* Sampling requested */
if (cpump->mode != PAI_MODE_NONE)
rc = -EBUSY; /* ... sampling/counting active */
@@ -144,8 +202,15 @@ static int paicrypt_busy(struct perf_event_attr *a, struct paicrypt_map *cpump)
if (cpump->mode == PAI_MODE_SAMPLING)
rc = -EBUSY; /* ... and sampling active */
}
+ /*
+ * This error case triggers when there is a conflict:
+ * Either sampling requested and counting already active, or visa
+ * versa. Therefore the struct paicrypto_map for this CPU is
+ * needed or the error could not have occurred. Only adjust root
+ * node refcount.
+ */
if (rc)
- goto unlock;
+ goto free_root;
/* Allocate memory for counter page and counter extraction.
* Only the first counting event has to allocate a page.
@@ -158,30 +223,36 @@ static int paicrypt_busy(struct perf_event_attr *a, struct paicrypt_map *cpump)
rc = -ENOMEM;
cpump->page = (unsigned long *)get_zeroed_page(GFP_KERNEL);
if (!cpump->page)
- goto unlock;
+ goto free_paicrypt_map;
cpump->save = kvmalloc_array(paicrypt_cnt + 1,
sizeof(struct pai_userdata), GFP_KERNEL);
if (!cpump->save) {
free_page((unsigned long)cpump->page);
cpump->page = NULL;
- goto unlock;
+ goto free_paicrypt_map;
}
+
+ /* Set mode and reference count */
rc = 0;
refcount_set(&cpump->refcnt, 1);
-
-unlock:
- /* If rc is non-zero, do not set mode and reference count */
- if (!rc) {
- cpump->mode = a->sample_period ? PAI_MODE_SAMPLING
- : PAI_MODE_COUNTING;
- }
+ cpump->mode = a->sample_period ? PAI_MODE_SAMPLING : PAI_MODE_COUNTING;
+ mp->mapptr = cpump;
debug_sprintf_event(cfm_dbg, 5, "%s sample_period %#llx users %d"
" mode %d refcnt %u page %#lx save %p rc %d\n",
__func__, a->sample_period, cpump->active_events,
cpump->mode, refcount_read(&cpump->refcnt),
(unsigned long)cpump->page, cpump->save, rc);
+ goto unlock;
+
+free_paicrypt_map:
+ kfree(cpump);
+ mp->mapptr = NULL;
+free_root:
+ paicrypt_root_free();
+
+unlock:
mutex_unlock(&pai_reserve_mutex);
- return rc;
+ return rc ? ERR_PTR(rc) : cpump;
}
/* Might be called on different CPU than the one the event is intended for. */
@@ -189,7 +260,6 @@ static int paicrypt_event_init(struct perf_event *event)
{
struct perf_event_attr *a = &event->attr;
struct paicrypt_map *cpump;
- int rc;
/* PAI crypto PMU registered as PERF_TYPE_RAW, check event type */
if (a->type != PERF_TYPE_RAW && event->pmu->type != a->type)
@@ -199,24 +269,16 @@ static int paicrypt_event_init(struct perf_event *event)
a->config > PAI_CRYPTO_BASE + paicrypt_cnt)
return -EINVAL;
/* Allow only CPU wide operation, no process context for now. */
- if (event->hw.target || event->cpu == -1)
+ if ((event->attach_state & PERF_ATTACH_TASK) || event->cpu == -1)
return -ENOENT;
/* Allow only CRYPTO_ALL for sampling. */
if (a->sample_period && a->config != PAI_CRYPTO_BASE)
return -EINVAL;
- cpump = per_cpu_ptr(&paicrypt_map, event->cpu);
- rc = paicrypt_busy(a, cpump);
- if (rc)
- return rc;
+ cpump = paicrypt_busy(event);
+ if (IS_ERR(cpump))
+ return PTR_ERR(cpump);
- /* Event initialization sets last_tag to 0. When later on the events
- * are deleted and re-added, do not reset the event count value to zero.
- * Events are added, deleted and re-added when 2 or more events
- * are active at the same time.
- */
- event->hw.last_tag = 0;
- cpump->event = event;
event->destroy = paicrypt_event_destroy;
if (a->sample_period) {
@@ -250,23 +312,28 @@ static void paicrypt_start(struct perf_event *event, int flags)
{
u64 sum;
+ /* Event initialization sets last_tag to 0. When later on the events
+ * are deleted and re-added, do not reset the event count value to zero.
+ * Events are added, deleted and re-added when 2 or more events
+ * are active at the same time.
+ */
if (!event->hw.last_tag) {
event->hw.last_tag = 1;
sum = paicrypt_getall(event); /* Get current value */
- local64_set(&event->count, 0);
local64_set(&event->hw.prev_count, sum);
}
}
static int paicrypt_add(struct perf_event *event, int flags)
{
- struct paicrypt_map *cpump = this_cpu_ptr(&paicrypt_map);
+ struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr);
+ struct paicrypt_map *cpump = mp->mapptr;
unsigned long ccd;
if (++cpump->active_events == 1) {
ccd = virt_to_phys(cpump->page) | PAI_CRYPTO_KERNEL_OFFSET;
WRITE_ONCE(S390_lowcore.ccd, ccd);
- __ctl_set_bit(0, 50);
+ local_ctl_set_bit(0, CR0_CRYPTOGRAPHY_COUNTER_BIT);
}
cpump->event = event;
if (flags & PERF_EF_START && !event->attr.sample_period) {
@@ -287,7 +354,8 @@ static void paicrypt_stop(struct perf_event *event, int flags)
static void paicrypt_del(struct perf_event *event, int flags)
{
- struct paicrypt_map *cpump = this_cpu_ptr(&paicrypt_map);
+ struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr);
+ struct paicrypt_map *cpump = mp->mapptr;
if (event->attr.sample_period)
perf_sched_cb_dec(event->pmu);
@@ -295,7 +363,7 @@ static void paicrypt_del(struct perf_event *event, int flags)
/* Only counting needs to read counter */
paicrypt_stop(event, PERF_EF_UPDATE);
if (--cpump->active_events == 0) {
- __ctl_clear_bit(0, 50);
+ local_ctl_clear_bit(0, CR0_CRYPTOGRAPHY_COUNTER_BIT);
WRITE_ONCE(S390_lowcore.ccd, 0);
}
}
@@ -329,7 +397,8 @@ static size_t paicrypt_copy(struct pai_userdata *userdata,
static int paicrypt_push_sample(void)
{
- struct paicrypt_map *cpump = this_cpu_ptr(&paicrypt_map);
+ struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr);
+ struct paicrypt_map *cpump = mp->mapptr;
struct perf_event *event = cpump->event;
struct perf_sample_data data;
struct perf_raw_record raw;
diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c
index c57c1a203256..e7013a2e8960 100644
--- a/arch/s390/kernel/perf_pai_ext.c
+++ b/arch/s390/kernel/perf_pai_ext.c
@@ -17,8 +17,7 @@
#include <linux/export.h>
#include <linux/io.h>
#include <linux/perf_event.h>
-
-#include <asm/ctl_reg.h>
+#include <asm/ctlreg.h>
#include <asm/pai.h>
#include <asm/debug.h>
@@ -249,7 +248,7 @@ static int paiext_event_init(struct perf_event *event)
if (rc)
return rc;
/* Allow only CPU wide operation, no process context for now. */
- if (event->hw.target || event->cpu == -1)
+ if ((event->attach_state & PERF_ATTACH_TASK) || event->cpu == -1)
return -ENOENT;
/* Allow only event NNPA_ALL for sampling. */
if (a->sample_period && a->config != PAI_NNPA_BASE)
@@ -261,7 +260,6 @@ static int paiext_event_init(struct perf_event *event)
rc = paiext_alloc(a, event);
if (rc)
return rc;
- event->hw.last_tag = 0;
event->destroy = paiext_event_destroy;
if (a->sample_period) {
@@ -327,7 +325,6 @@ static void paiext_start(struct perf_event *event, int flags)
event->hw.last_tag = 1;
sum = paiext_getall(event); /* Get current value */
local64_set(&event->hw.prev_count, sum);
- local64_set(&event->count, 0);
}
static int paiext_add(struct perf_event *event, int flags)
@@ -340,7 +337,7 @@ static int paiext_add(struct perf_event *event, int flags)
S390_lowcore.aicd = virt_to_phys(cpump->paiext_cb);
pcb->acc = virt_to_phys(cpump->area) | 0x1;
/* Enable CPU instruction lookup for PAIE1 control block */
- __ctl_set_bit(0, 49);
+ local_ctl_set_bit(0, CR0_PAI_EXTENSION_BIT);
debug_sprintf_event(paiext_dbg, 4, "%s 1508 %llx acc %llx\n",
__func__, S390_lowcore.aicd, pcb->acc);
}
@@ -376,7 +373,7 @@ static void paiext_del(struct perf_event *event, int flags)
}
if (--cpump->active_events == 0) {
/* Disable CPU instruction lookup for PAIE1 control block */
- __ctl_clear_bit(0, 49);
+ local_ctl_clear_bit(0, CR0_PAI_EXTENSION_BIT);
pcb->acc = 0;
S390_lowcore.aicd = 0;
debug_sprintf_event(paiext_dbg, 4, "%s 1508 %llx acc %llx\n",
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index ea244a73efad..046403471c5d 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -41,13 +41,20 @@ void update_cr_regs(struct task_struct *task)
{
struct pt_regs *regs = task_pt_regs(task);
struct thread_struct *thread = &task->thread;
- struct per_regs old, new;
union ctlreg0 cr0_old, cr0_new;
union ctlreg2 cr2_old, cr2_new;
int cr0_changed, cr2_changed;
-
- __ctl_store(cr0_old.val, 0, 0);
- __ctl_store(cr2_old.val, 2, 2);
+ union {
+ struct ctlreg regs[3];
+ struct {
+ struct ctlreg control;
+ struct ctlreg start;
+ struct ctlreg end;
+ };
+ } old, new;
+
+ local_ctl_store(0, &cr0_old.reg);
+ local_ctl_store(2, &cr2_old.reg);
cr0_new = cr0_old;
cr2_new = cr2_old;
/* Take care of the enable/disable of transactional execution. */
@@ -75,38 +82,38 @@ void update_cr_regs(struct task_struct *task)
cr0_changed = cr0_new.val != cr0_old.val;
cr2_changed = cr2_new.val != cr2_old.val;
if (cr0_changed)
- __ctl_load(cr0_new.val, 0, 0);
+ local_ctl_load(0, &cr0_new.reg);
if (cr2_changed)
- __ctl_load(cr2_new.val, 2, 2);
+ local_ctl_load(2, &cr2_new.reg);
/* Copy user specified PER registers */
- new.control = thread->per_user.control;
- new.start = thread->per_user.start;
- new.end = thread->per_user.end;
+ new.control.val = thread->per_user.control;
+ new.start.val = thread->per_user.start;
+ new.end.val = thread->per_user.end;
/* merge TIF_SINGLE_STEP into user specified PER registers. */
if (test_tsk_thread_flag(task, TIF_SINGLE_STEP) ||
test_tsk_thread_flag(task, TIF_UPROBE_SINGLESTEP)) {
if (test_tsk_thread_flag(task, TIF_BLOCK_STEP))
- new.control |= PER_EVENT_BRANCH;
+ new.control.val |= PER_EVENT_BRANCH;
else
- new.control |= PER_EVENT_IFETCH;
- new.control |= PER_CONTROL_SUSPENSION;
- new.control |= PER_EVENT_TRANSACTION_END;
+ new.control.val |= PER_EVENT_IFETCH;
+ new.control.val |= PER_CONTROL_SUSPENSION;
+ new.control.val |= PER_EVENT_TRANSACTION_END;
if (test_tsk_thread_flag(task, TIF_UPROBE_SINGLESTEP))
- new.control |= PER_EVENT_IFETCH;
- new.start = 0;
- new.end = -1UL;
+ new.control.val |= PER_EVENT_IFETCH;
+ new.start.val = 0;
+ new.end.val = -1UL;
}
/* Take care of the PER enablement bit in the PSW. */
- if (!(new.control & PER_EVENT_MASK)) {
+ if (!(new.control.val & PER_EVENT_MASK)) {
regs->psw.mask &= ~PSW_MASK_PER;
return;
}
regs->psw.mask |= PSW_MASK_PER;
- __ctl_store(old, 9, 11);
+ __local_ctl_store(9, 11, old.regs);
if (memcmp(&new, &old, sizeof(struct per_regs)) != 0)
- __ctl_load(new, 9, 11);
+ __local_ctl_load(9, 11, new.regs);
}
void user_enable_single_step(struct task_struct *task)
@@ -1107,7 +1114,7 @@ static int s390_gs_cb_set(struct task_struct *target,
target->thread.gs_cb = data;
*target->thread.gs_cb = gs_cb;
if (target == current) {
- __ctl_set_bit(2, 4);
+ local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT);
restore_gs_cb(target->thread.gs_cb);
}
preempt_enable();
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index de6ad0fb2328..5701356f4f33 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -305,7 +305,7 @@ static void __init setup_zfcpdump(void)
return;
if (oldmem_data.start)
return;
- strcat(boot_command_line, " cio_ignore=all,!ipldev,!condev");
+ strlcat(boot_command_line, " cio_ignore=all,!ipldev,!condev", COMMAND_LINE_SIZE);
console_loglevel = 2;
}
#else
@@ -381,12 +381,6 @@ void stack_free(unsigned long stack)
#endif
}
-void __init __noreturn arch_call_rest_init(void)
-{
- smp_reinit_ipl_cpu();
- rest_init();
-}
-
static unsigned long __init stack_alloc_early(void)
{
unsigned long stack;
@@ -455,7 +449,6 @@ static void __init setup_lowcore(void)
lc->restart_fn = (unsigned long) do_restart;
lc->restart_data = 0;
lc->restart_source = -1U;
- __ctl_store(lc->cregs_save_area, 0, 15);
lc->spinlock_lockval = arch_spin_lockval(0);
lc->spinlock_index = 0;
arch_spin_lock_setup(0);
@@ -465,6 +458,7 @@ static void __init setup_lowcore(void)
lc->kernel_asce = S390_lowcore.kernel_asce;
lc->user_asce = S390_lowcore.user_asce;
+ system_ctlreg_init_save_area(lc);
abs_lc = get_abs_lowcore();
abs_lc->restart_stack = lc->restart_stack;
abs_lc->restart_fn = lc->restart_fn;
@@ -472,7 +466,6 @@ static void __init setup_lowcore(void)
abs_lc->restart_source = lc->restart_source;
abs_lc->restart_psw = lc->restart_psw;
abs_lc->restart_flags = RESTART_FLAG_CTLREGS;
- memcpy(abs_lc->cregs_save_area, lc->cregs_save_area, sizeof(abs_lc->cregs_save_area));
abs_lc->program_new_psw = lc->program_new_psw;
abs_lc->mcesad = lc->mcesad;
put_abs_lowcore(abs_lc);
@@ -625,8 +618,8 @@ static void __init reserve_crashkernel(void)
phys_addr_t low, high;
int rc;
- rc = parse_crashkernel(boot_command_line, ident_map_size, &crash_size,
- &crash_base);
+ rc = parse_crashkernel(boot_command_line, ident_map_size,
+ &crash_size, &crash_base, NULL, NULL);
crash_base = ALIGN(crash_base, KEXEC_CRASH_MEM_ALIGN);
crash_size = ALIGN(crash_size, KEXEC_CRASH_MEM_ALIGN);
@@ -797,15 +790,15 @@ static void __init setup_cr(void)
__ctl_duct[4] = (unsigned long)__ctl_duald;
/* Update control registers CR2, CR5 and CR15 */
- __ctl_store(cr2.val, 2, 2);
- __ctl_store(cr5.val, 5, 5);
- __ctl_store(cr15.val, 15, 15);
+ local_ctl_store(2, &cr2.reg);
+ local_ctl_store(5, &cr5.reg);
+ local_ctl_store(15, &cr15.reg);
cr2.ducto = (unsigned long)__ctl_duct >> 6;
cr5.pasteo = (unsigned long)__ctl_duct >> 6;
cr15.lsea = (unsigned long)__ctl_linkage_stack >> 3;
- __ctl_load(cr2.val, 2, 2);
- __ctl_load(cr5.val, 5, 5);
- __ctl_load(cr15.val, 15, 15);
+ system_ctl_load(2, &cr2.reg);
+ system_ctl_load(5, &cr5.reg);
+ system_ctl_load(15, &cr15.reg);
}
/*
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index a4edb7ea66ea..f7fcfff09acf 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -37,6 +37,7 @@
#include <linux/crash_dump.h>
#include <linux/kprobes.h>
#include <asm/asm-offsets.h>
+#include <asm/ctlreg.h>
#include <asm/pfault.h>
#include <asm/diag.h>
#include <asm/switch_to.h>
@@ -567,54 +568,6 @@ void arch_irq_work_raise(void)
}
#endif
-/*
- * parameter area for the set/clear control bit callbacks
- */
-struct ec_creg_mask_parms {
- unsigned long orval;
- unsigned long andval;
- int cr;
-};
-
-/*
- * callback for setting/clearing control bits
- */
-static void smp_ctl_bit_callback(void *info)
-{
- struct ec_creg_mask_parms *pp = info;
- unsigned long cregs[16];
-
- __ctl_store(cregs, 0, 15);
- cregs[pp->cr] = (cregs[pp->cr] & pp->andval) | pp->orval;
- __ctl_load(cregs, 0, 15);
-}
-
-static DEFINE_SPINLOCK(ctl_lock);
-
-void smp_ctl_set_clear_bit(int cr, int bit, bool set)
-{
- struct ec_creg_mask_parms parms = { .cr = cr, };
- struct lowcore *abs_lc;
- u64 ctlreg;
-
- if (set) {
- parms.orval = 1UL << bit;
- parms.andval = -1UL;
- } else {
- parms.orval = 0;
- parms.andval = ~(1UL << bit);
- }
- spin_lock(&ctl_lock);
- abs_lc = get_abs_lowcore();
- ctlreg = abs_lc->cregs_save_area[cr];
- ctlreg = (ctlreg & parms.andval) | parms.orval;
- abs_lc->cregs_save_area[cr] = ctlreg;
- put_abs_lowcore(abs_lc);
- on_each_cpu(smp_ctl_bit_callback, &parms, 1);
- spin_unlock(&ctl_lock);
-}
-EXPORT_SYMBOL(smp_ctl_set_clear_bit);
-
#ifdef CONFIG_CRASH_DUMP
int smp_store_status(int cpu)
@@ -898,7 +851,7 @@ static void smp_start_secondary(void *cpuvoid)
S390_lowcore.restart_flags = 0;
restore_access_regs(S390_lowcore.access_regs_save_area);
cpu_init();
- rcu_cpu_starting(cpu);
+ rcutree_report_cpu_starting(cpu);
init_cpu_timer();
vtime_init();
vdso_getcpu_init();
@@ -935,14 +888,14 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
* Make sure global control register contents do not change
* until new CPU has initialized control registers.
*/
- spin_lock(&ctl_lock);
+ system_ctlreg_lock();
pcpu_prepare_secondary(pcpu, cpu);
pcpu_attach_task(pcpu, tidle);
pcpu_start_fn(pcpu, smp_start_secondary, NULL);
/* Wait until cpu puts itself in the online & active maps */
while (!cpu_online(cpu))
cpu_relax();
- spin_unlock(&ctl_lock);
+ system_ctlreg_unlock();
return 0;
}
@@ -957,7 +910,7 @@ early_param("possible_cpus", _setup_possible_cpus);
int __cpu_disable(void)
{
- unsigned long cregs[16];
+ struct ctlreg cregs[16];
int cpu;
/* Handle possible pending IPIs */
@@ -969,11 +922,11 @@ int __cpu_disable(void)
/* Disable pseudo page faults on this cpu. */
pfault_fini();
/* Disable interrupt sources via control register. */
- __ctl_store(cregs, 0, 15);
- cregs[0] &= ~0x0000ee70UL; /* disable all external interrupts */
- cregs[6] &= ~0xff000000UL; /* disable all I/O interrupts */
- cregs[14] &= ~0x1f000000UL; /* disable most machine checks */
- __ctl_load(cregs, 0, 15);
+ __local_ctl_store(0, 15, cregs);
+ cregs[0].val &= ~0x0000ee70UL; /* disable all external interrupts */
+ cregs[6].val &= ~0xff000000UL; /* disable all I/O interrupts */
+ cregs[14].val &= ~0x1f000000UL; /* disable most machine checks */
+ __local_ctl_load(0, 15, cregs);
clear_cpu_flag(CIF_NOHZ_DELAY);
return 0;
}
@@ -1013,12 +966,12 @@ void __init smp_fill_possible_mask(void)
void __init smp_prepare_cpus(unsigned int max_cpus)
{
- /* request the 0x1201 emergency signal external interrupt */
if (register_external_irq(EXT_IRQ_EMERGENCY_SIG, do_ext_call_interrupt))
panic("Couldn't request external interrupt 0x1201");
- /* request the 0x1202 external call external interrupt */
+ system_ctl_set_bit(0, 14);
if (register_external_irq(EXT_IRQ_EXTERNAL_CALL, do_ext_call_interrupt))
panic("Couldn't request external interrupt 0x1202");
+ system_ctl_set_bit(0, 13);
}
void __init smp_prepare_boot_cpu(void)
@@ -1076,11 +1029,9 @@ static ssize_t cpu_configure_store(struct device *dev,
cpus_read_lock();
mutex_lock(&smp_cpu_state_mutex);
rc = -EBUSY;
- /* disallow configuration changes of online cpus and cpu 0 */
+ /* disallow configuration changes of online cpus */
cpu = dev->id;
cpu = smp_get_base_cpu(cpu);
- if (cpu == 0)
- goto out;
for (i = 0; i <= smp_cpu_mtid; i++)
if (cpu_online(cpu + i))
goto out;
@@ -1180,7 +1131,7 @@ static int smp_add_present_cpu(int cpu)
return -ENOMEM;
per_cpu(cpu_device, cpu) = c;
s = &c->dev;
- c->hotpluggable = 1;
+ c->hotpluggable = !!cpu;
rc = register_cpu(c, cpu);
if (rc)
goto out;
@@ -1258,60 +1209,3 @@ out:
return rc;
}
subsys_initcall(s390_smp_init);
-
-static __always_inline void set_new_lowcore(struct lowcore *lc)
-{
- union register_pair dst, src;
- u32 pfx;
-
- src.even = (unsigned long) &S390_lowcore;
- src.odd = sizeof(S390_lowcore);
- dst.even = (unsigned long) lc;
- dst.odd = sizeof(*lc);
- pfx = __pa(lc);
-
- asm volatile(
- " mvcl %[dst],%[src]\n"
- " spx %[pfx]\n"
- : [dst] "+&d" (dst.pair), [src] "+&d" (src.pair)
- : [pfx] "Q" (pfx)
- : "memory", "cc");
-}
-
-int __init smp_reinit_ipl_cpu(void)
-{
- unsigned long async_stack, nodat_stack, mcck_stack;
- struct lowcore *lc, *lc_ipl;
- unsigned long flags, cr0;
- u64 mcesad;
-
- lc_ipl = lowcore_ptr[0];
- lc = (struct lowcore *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER);
- nodat_stack = __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER);
- async_stack = stack_alloc();
- mcck_stack = stack_alloc();
- if (!lc || !nodat_stack || !async_stack || !mcck_stack || nmi_alloc_mcesa(&mcesad))
- panic("Couldn't allocate memory");
-
- local_irq_save(flags);
- local_mcck_disable();
- set_new_lowcore(lc);
- S390_lowcore.nodat_stack = nodat_stack + STACK_INIT_OFFSET;
- S390_lowcore.async_stack = async_stack + STACK_INIT_OFFSET;
- S390_lowcore.mcck_stack = mcck_stack + STACK_INIT_OFFSET;
- __ctl_store(cr0, 0, 0);
- __ctl_clear_bit(0, 28); /* disable lowcore protection */
- S390_lowcore.mcesad = mcesad;
- __ctl_load(cr0, 0, 0);
- if (abs_lowcore_map(0, lc, false))
- panic("Couldn't remap absolute lowcore");
- lowcore_ptr[0] = lc;
- local_mcck_enable();
- local_irq_restore(flags);
-
- memblock_free_late(__pa(lc_ipl->mcck_stack - STACK_INIT_OFFSET), THREAD_SIZE);
- memblock_free_late(__pa(lc_ipl->async_stack - STACK_INIT_OFFSET), THREAD_SIZE);
- memblock_free_late(__pa(lc_ipl->nodat_stack - STACK_INIT_OFFSET), THREAD_SIZE);
- memblock_free_late(__pa(lc_ipl), sizeof(*lc_ipl));
- return 0;
-}
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index 0787010139f7..94f440e38303 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -6,9 +6,12 @@
*/
#include <linux/stacktrace.h>
+#include <linux/uaccess.h>
+#include <linux/compat.h>
#include <asm/stacktrace.h>
#include <asm/unwind.h>
#include <asm/kprobes.h>
+#include <asm/ptrace.h>
void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
struct task_struct *task, struct pt_regs *regs)
@@ -58,3 +61,43 @@ int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
return -EINVAL;
return 0;
}
+
+void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
+ const struct pt_regs *regs)
+{
+ struct stack_frame_user __user *sf;
+ unsigned long ip, sp;
+ bool first = true;
+
+ if (is_compat_task())
+ return;
+ if (!consume_entry(cookie, instruction_pointer(regs)))
+ return;
+ sf = (void __user *)user_stack_pointer(regs);
+ pagefault_disable();
+ while (1) {
+ if (__get_user(sp, &sf->back_chain))
+ break;
+ if (__get_user(ip, &sf->gprs[8]))
+ break;
+ if (ip & 0x1) {
+ /*
+ * If the instruction address is invalid, and this
+ * is the first stack frame, assume r14 has not
+ * been written to the stack yet. Otherwise exit.
+ */
+ if (first && !(regs->gprs[14] & 0x1))
+ ip = regs->gprs[14];
+ else
+ break;
+ }
+ if (!consume_entry(cookie, ip))
+ break;
+ /* Sanity check: ABI requires SP to be aligned 8 bytes. */
+ if (!sp || sp & 0x7)
+ break;
+ sf = (void __user *)sp;
+ first = false;
+ }
+ pagefault_enable();
+}
diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl
index 0122cc156952..86fec9b080f6 100644
--- a/arch/s390/kernel/syscalls/syscall.tbl
+++ b/arch/s390/kernel/syscalls/syscall.tbl
@@ -100,7 +100,7 @@
106 common stat sys_newstat compat_sys_newstat
107 common lstat sys_newlstat compat_sys_newlstat
108 common fstat sys_newfstat compat_sys_newfstat
-110 common lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie
+110 common lookup_dcookie - -
111 common vhangup sys_vhangup sys_vhangup
112 common idle - -
114 common wait4 sys_wait4 compat_sys_wait4
@@ -455,3 +455,7 @@
450 common set_mempolicy_home_node sys_set_mempolicy_home_node sys_set_mempolicy_home_node
451 common cachestat sys_cachestat sys_cachestat
452 common fchmodat2 sys_fchmodat2 sys_fchmodat2
+453 common map_shadow_stack sys_map_shadow_stack sys_map_shadow_stack
+454 common futex_wake sys_futex_wake sys_futex_wake
+455 common futex_wait sys_futex_wait sys_futex_wait
+456 common futex_requeue sys_futex_requeue sys_futex_requeue
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index d34d3548c046..14abad953c02 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -173,10 +173,10 @@ void init_cpu_timer(void)
clockevents_register_device(cd);
/* Enable clock comparator timer interrupt. */
- __ctl_set_bit(0,11);
+ local_ctl_set_bit(0, CR0_CLOCK_COMPARATOR_SUBMASK_BIT);
/* Always allow the timing alert external interrupt. */
- __ctl_set_bit(0, 4);
+ local_ctl_set_bit(0, CR0_ETR_SUBMASK_BIT);
}
static void clock_comparator_interrupt(struct ext_code ext_code,
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 68adf1de8888..89e91b8ce842 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -522,7 +522,7 @@ static struct sched_domain_topology_level s390_topology[] = {
{ cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
{ cpu_book_mask, SD_INIT_NAME(BOOK) },
{ cpu_drawer_mask, SD_INIT_NAME(DRAWER) },
- { cpu_cpu_mask, SD_INIT_NAME(DIE) },
+ { cpu_cpu_mask, SD_INIT_NAME(PKG) },
{ NULL, },
};
@@ -636,7 +636,6 @@ static struct ctl_table topology_ctl_table[] = {
.mode = 0644,
.proc_handler = topology_ctl_handler,
},
- { },
};
static int __init topology_init(void)
diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile
index 23e868b79a6c..caec7db6f966 100644
--- a/arch/s390/kernel/vdso32/Makefile
+++ b/arch/s390/kernel/vdso32/Makefile
@@ -61,16 +61,6 @@ quiet_cmd_vdso32as = VDSO32A $@
quiet_cmd_vdso32cc = VDSO32C $@
cmd_vdso32cc = $(CC) $(c_flags) -c -o $@ $<
-# install commands for the unstripped file
-quiet_cmd_vdso_install = INSTALL $@
- cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
-
-vdso32.so: $(obj)/vdso32.so.dbg
- @mkdir -p $(MODLIB)/vdso
- $(call cmd,vdso_install)
-
-vdso_install: vdso32.so
-
# Generate VDSO offsets using helper script
gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
quiet_cmd_vdsosym = VDSOSYM $@
diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile
index fc1c6ff8178f..e3c9085f8fa7 100644
--- a/arch/s390/kernel/vdso64/Makefile
+++ b/arch/s390/kernel/vdso64/Makefile
@@ -70,16 +70,6 @@ quiet_cmd_vdso64as = VDSO64A $@
quiet_cmd_vdso64cc = VDSO64C $@
cmd_vdso64cc = $(CC) $(c_flags) -c -o $@ $<
-# install commands for the unstripped file
-quiet_cmd_vdso_install = INSTALL $@
- cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
-
-vdso64.so: $(obj)/vdso64.so.dbg
- @mkdir -p $(MODLIB)/vdso
- $(call cmd,vdso_install)
-
-vdso_install: vdso64.so
-
# Generate VDSO offsets using helper script
gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
quiet_cmd_vdsosym = VDSOSYM $@
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index 6d6bc19b37dc..5bfcc50c1a68 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -11,7 +11,7 @@
#include <linux/err.h>
#include <linux/pgtable.h>
#include <linux/bitfield.h>
-
+#include <asm/fault.h>
#include <asm/gmap.h>
#include "kvm-s390.h"
#include "gaccess.h"
@@ -466,23 +466,6 @@ static int ar_translation(struct kvm_vcpu *vcpu, union asce *asce, u8 ar,
return 0;
}
-struct trans_exc_code_bits {
- unsigned long addr : 52; /* Translation-exception Address */
- unsigned long fsi : 2; /* Access Exception Fetch/Store Indication */
- unsigned long : 2;
- unsigned long b56 : 1;
- unsigned long : 3;
- unsigned long b60 : 1;
- unsigned long b61 : 1;
- unsigned long as : 2; /* ASCE Identifier */
-};
-
-enum {
- FSI_UNKNOWN = 0, /* Unknown whether fetch or store */
- FSI_STORE = 1, /* Exception was due to store operation */
- FSI_FETCH = 2 /* Exception was due to fetch operation */
-};
-
enum prot_type {
PROT_TYPE_LA = 0,
PROT_TYPE_KEYC = 1,
@@ -497,11 +480,11 @@ static int trans_exc_ending(struct kvm_vcpu *vcpu, int code, unsigned long gva,
enum gacc_mode mode, enum prot_type prot, bool terminate)
{
struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm;
- struct trans_exc_code_bits *tec;
+ union teid *teid;
memset(pgm, 0, sizeof(*pgm));
pgm->code = code;
- tec = (struct trans_exc_code_bits *)&pgm->trans_exc_code;
+ teid = (union teid *)&pgm->trans_exc_code;
switch (code) {
case PGM_PROTECTION:
@@ -511,25 +494,25 @@ static int trans_exc_ending(struct kvm_vcpu *vcpu, int code, unsigned long gva,
WARN_ON_ONCE(1);
break;
case PROT_TYPE_IEP:
- tec->b61 = 1;
+ teid->b61 = 1;
fallthrough;
case PROT_TYPE_LA:
- tec->b56 = 1;
+ teid->b56 = 1;
break;
case PROT_TYPE_KEYC:
- tec->b60 = 1;
+ teid->b60 = 1;
break;
case PROT_TYPE_ALC:
- tec->b60 = 1;
+ teid->b60 = 1;
fallthrough;
case PROT_TYPE_DAT:
- tec->b61 = 1;
+ teid->b61 = 1;
break;
}
if (terminate) {
- tec->b56 = 0;
- tec->b60 = 0;
- tec->b61 = 0;
+ teid->b56 = 0;
+ teid->b60 = 0;
+ teid->b61 = 0;
}
fallthrough;
case PGM_ASCE_TYPE:
@@ -543,9 +526,9 @@ static int trans_exc_ending(struct kvm_vcpu *vcpu, int code, unsigned long gva,
* exc_access_id has to be set to 0 for some instructions. Both
* cases have to be handled by the caller.
*/
- tec->addr = gva >> PAGE_SHIFT;
- tec->fsi = mode == GACC_STORE ? FSI_STORE : FSI_FETCH;
- tec->as = psw_bits(vcpu->arch.sie_block->gpsw).as;
+ teid->addr = gva >> PAGE_SHIFT;
+ teid->fsi = mode == GACC_STORE ? TEID_FSI_STORE : TEID_FSI_FETCH;
+ teid->as = psw_bits(vcpu->arch.sie_block->gpsw).as;
fallthrough;
case PGM_ALEN_TRANSLATION:
case PGM_ALE_SEQUENCE:
@@ -1382,6 +1365,7 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
unsigned long *pgt, int *dat_protection,
int *fake)
{
+ struct kvm *kvm;
struct gmap *parent;
union asce asce;
union vaddress vaddr;
@@ -1390,6 +1374,7 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
*fake = 0;
*dat_protection = 0;
+ kvm = sg->private;
parent = sg->parent;
vaddr.addr = saddr;
asce.val = sg->orig_asce;
@@ -1450,6 +1435,7 @@ shadow_r2t:
rc = gmap_shadow_r2t(sg, saddr, rfte.val, *fake);
if (rc)
return rc;
+ kvm->stat.gmap_shadow_r1_entry++;
}
fallthrough;
case ASCE_TYPE_REGION2: {
@@ -1478,6 +1464,7 @@ shadow_r3t:
rc = gmap_shadow_r3t(sg, saddr, rste.val, *fake);
if (rc)
return rc;
+ kvm->stat.gmap_shadow_r2_entry++;
}
fallthrough;
case ASCE_TYPE_REGION3: {
@@ -1515,6 +1502,7 @@ shadow_sgt:
rc = gmap_shadow_sgt(sg, saddr, rtte.val, *fake);
if (rc)
return rc;
+ kvm->stat.gmap_shadow_r3_entry++;
}
fallthrough;
case ASCE_TYPE_SEGMENT: {
@@ -1548,6 +1536,7 @@ shadow_pgt:
rc = gmap_shadow_pgt(sg, saddr, ste.val, *fake);
if (rc)
return rc;
+ kvm->stat.gmap_shadow_sg_entry++;
}
}
/* Return the parent address of the page table */
@@ -1618,6 +1607,7 @@ shadow_page:
pte.p |= dat_protection;
if (!rc)
rc = gmap_shadow_page(sg, saddr, __pte(pte.val));
+ vcpu->kvm->stat.gmap_shadow_pg_entry++;
ipte_unlock(vcpu->kvm);
mmap_read_unlock(sg->mm);
return rc;
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index c1b47d608a2b..efaebba5ee19 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -303,11 +303,6 @@ static inline u8 gisa_get_ipm_or_restore_iam(struct kvm_s390_gisa_interrupt *gi)
return 0;
}
-static inline int gisa_in_alert_list(struct kvm_s390_gisa *gisa)
-{
- return READ_ONCE(gisa->next_alert) != (u32)virt_to_phys(gisa);
-}
-
static inline void gisa_set_ipm_gisc(struct kvm_s390_gisa *gisa, u32 gisc)
{
set_bit_inv(IPM_BIT_OFFSET + gisc, (unsigned long *) gisa);
@@ -3216,11 +3211,12 @@ void kvm_s390_gisa_destroy(struct kvm *kvm)
if (!gi->origin)
return;
- if (gi->alert.mask)
- KVM_EVENT(3, "vm 0x%pK has unexpected iam 0x%02x",
- kvm, gi->alert.mask);
- while (gisa_in_alert_list(gi->origin))
- cpu_relax();
+ WARN(gi->alert.mask != 0x00,
+ "unexpected non zero alert.mask 0x%02x",
+ gi->alert.mask);
+ gi->alert.mask = 0x00;
+ if (gisa_set_iam(gi->origin, gi->alert.mask))
+ process_gib_alert_list();
hrtimer_cancel(&gi->timer);
gi->origin = NULL;
VM_EVENT(kvm, 3, "gisa 0x%pK destroyed", gisa);
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index b3f17e014cab..7aa0e668488f 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -66,7 +66,14 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
STATS_DESC_COUNTER(VM, inject_pfault_done),
STATS_DESC_COUNTER(VM, inject_service_signal),
STATS_DESC_COUNTER(VM, inject_virtio),
- STATS_DESC_COUNTER(VM, aen_forward)
+ STATS_DESC_COUNTER(VM, aen_forward),
+ STATS_DESC_COUNTER(VM, gmap_shadow_reuse),
+ STATS_DESC_COUNTER(VM, gmap_shadow_create),
+ STATS_DESC_COUNTER(VM, gmap_shadow_r1_entry),
+ STATS_DESC_COUNTER(VM, gmap_shadow_r2_entry),
+ STATS_DESC_COUNTER(VM, gmap_shadow_r3_entry),
+ STATS_DESC_COUNTER(VM, gmap_shadow_sg_entry),
+ STATS_DESC_COUNTER(VM, gmap_shadow_pg_entry),
};
const struct kvm_stats_header kvm_vm_stats_header = {
@@ -4053,6 +4060,8 @@ static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start,
unsigned long prefix;
unsigned long i;
+ trace_kvm_s390_gmap_notifier(start, end, gmap_is_shadow(gmap));
+
if (gmap_is_shadow(gmap))
return;
if (start >= 1UL << 31)
@@ -4918,7 +4927,7 @@ static void sync_regs_fmt2(struct kvm_vcpu *vcpu)
}
if (MACHINE_HAS_GS) {
preempt_disable();
- __ctl_set_bit(2, 4);
+ local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT);
if (current->thread.gs_cb) {
vcpu->arch.host_gscb = current->thread.gs_cb;
save_gs_cb(vcpu->arch.host_gscb);
@@ -4995,13 +5004,13 @@ static void store_regs_fmt2(struct kvm_vcpu *vcpu)
kvm_run->s.regs.diag318 = vcpu->arch.diag318_info.val;
if (MACHINE_HAS_GS) {
preempt_disable();
- __ctl_set_bit(2, 4);
+ local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT);
if (vcpu->arch.gs_enabled)
save_gs_cb(current->thread.gs_cb);
current->thread.gs_cb = vcpu->arch.host_gscb;
restore_gs_cb(vcpu->arch.host_gscb);
if (!vcpu->arch.host_gscb)
- __ctl_clear_bit(2, 4);
+ local_ctl_clear_bit(2, CR2_GUARDED_STORAGE_BIT);
vcpu->arch.host_gscb = NULL;
preempt_enable();
}
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index dc4cfa8795c0..621a17fd1a1b 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -57,7 +57,7 @@ static int handle_gs(struct kvm_vcpu *vcpu)
if (test_kvm_facility(vcpu->kvm, 133)) {
VCPU_EVENT(vcpu, 3, "%s", "ENABLE: GS (lazy)");
preempt_disable();
- __ctl_set_bit(2, 4);
+ local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT);
current->thread.gs_cb = (struct gs_cb *)&vcpu->run->s.regs.gscb;
restore_gs_cb(current->thread.gs_cb);
preempt_enable();
diff --git a/arch/s390/kvm/trace-s390.h b/arch/s390/kvm/trace-s390.h
index 6f0209d45164..9ac92dbf680d 100644
--- a/arch/s390/kvm/trace-s390.h
+++ b/arch/s390/kvm/trace-s390.h
@@ -333,6 +333,29 @@ TRACE_EVENT(kvm_s390_airq_suppressed,
__entry->id, __entry->isc)
);
+/*
+ * Trace point for gmap notifier calls.
+ */
+TRACE_EVENT(kvm_s390_gmap_notifier,
+ TP_PROTO(unsigned long start, unsigned long end, unsigned int shadow),
+ TP_ARGS(start, end, shadow),
+
+ TP_STRUCT__entry(
+ __field(unsigned long, start)
+ __field(unsigned long, end)
+ __field(unsigned int, shadow)
+ ),
+
+ TP_fast_assign(
+ __entry->start = start;
+ __entry->end = end;
+ __entry->shadow = shadow;
+ ),
+
+ TP_printk("gmap notified (start:0x%lx end:0x%lx shadow:%d)",
+ __entry->start, __entry->end, __entry->shadow)
+ );
+
#endif /* _TRACE_KVMS390_H */
diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c
index 61499293c2ac..8207a892bbe2 100644
--- a/arch/s390/kvm/vsie.c
+++ b/arch/s390/kvm/vsie.c
@@ -587,10 +587,6 @@ void kvm_s390_vsie_gmap_notifier(struct gmap *gmap, unsigned long start,
if (!gmap_is_shadow(gmap))
return;
- if (start >= 1UL << 31)
- /* We are only interested in prefix pages */
- return;
-
/*
* Only new shadow blocks are added to the list during runtime,
* therefore we can safely reference them all the time.
@@ -1214,8 +1210,10 @@ static int acquire_gmap_shadow(struct kvm_vcpu *vcpu,
* we're holding has been unshadowed. If the gmap is still valid,
* we can safely reuse it.
*/
- if (vsie_page->gmap && gmap_shadow_valid(vsie_page->gmap, asce, edat))
+ if (vsie_page->gmap && gmap_shadow_valid(vsie_page->gmap, asce, edat)) {
+ vcpu->kvm->stat.gmap_shadow_reuse++;
return 0;
+ }
/* release the old shadow - if any, and mark the prefix as unmapped */
release_gmap_shadow(vsie_page);
@@ -1223,6 +1221,7 @@ static int acquire_gmap_shadow(struct kvm_vcpu *vcpu,
if (IS_ERR(gmap))
return PTR_ERR(gmap);
gmap->private = vcpu->kvm;
+ vcpu->kvm->stat.gmap_shadow_create++;
WRITE_ONCE(vsie_page->gmap, gmap);
return 0;
}
diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c
index e4a13d7cab6e..61d8dcd95bbc 100644
--- a/arch/s390/lib/uaccess.c
+++ b/arch/s390/lib/uaccess.c
@@ -12,21 +12,22 @@
#include <linux/export.h>
#include <linux/mm.h>
#include <asm/asm-extable.h>
+#include <asm/ctlreg.h>
#ifdef CONFIG_DEBUG_ENTRY
void debug_user_asce(int exit)
{
- unsigned long cr1, cr7;
+ struct ctlreg cr1, cr7;
- __ctl_store(cr1, 1, 1);
- __ctl_store(cr7, 7, 7);
- if (cr1 == S390_lowcore.kernel_asce && cr7 == S390_lowcore.user_asce)
+ local_ctl_store(1, &cr1);
+ local_ctl_store(7, &cr7);
+ if (cr1.val == S390_lowcore.kernel_asce.val && cr7.val == S390_lowcore.user_asce.val)
return;
panic("incorrect ASCE on kernel %s\n"
"cr1: %016lx cr7: %016lx\n"
- "kernel: %016llx user: %016llx\n",
- exit ? "exit" : "entry", cr1, cr7,
- S390_lowcore.kernel_asce, S390_lowcore.user_asce);
+ "kernel: %016lx user: %016lx\n",
+ exit ? "exit" : "entry", cr1.val, cr7.val,
+ S390_lowcore.kernel_asce.val, S390_lowcore.user_asce.val);
}
#endif /*CONFIG_DEBUG_ENTRY */
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index f47515313226..f8b13f247646 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -332,7 +332,6 @@ static struct ctl_table cmm_table[] = {
.mode = 0644,
.proc_handler = cmm_timeout_handler,
},
- { }
};
#ifdef CONFIG_CMM_IUCV
diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c
index b51666967aa1..d37a8f607b71 100644
--- a/arch/s390/mm/dump_pagetables.c
+++ b/arch/s390/mm/dump_pagetables.c
@@ -287,7 +287,7 @@ static int pt_dump_init(void)
* kernel ASCE. We need this to keep the page table walker functions
* from accessing non-existent entries.
*/
- max_addr = (S390_lowcore.kernel_asce & _REGION_ENTRY_TYPE_MASK) >> 2;
+ max_addr = (S390_lowcore.kernel_asce.val & _REGION_ENTRY_TYPE_MASK) >> 2;
max_addr = 1UL << (max_addr * 11 + 31);
address_markers[IDENTITY_AFTER_END_NR].start_address = ident_map_size;
address_markers[AMODE31_START_NR].start_address = (unsigned long)__samode31;
diff --git a/arch/s390/mm/extable.c b/arch/s390/mm/extable.c
index fe87291df95d..0a0738a473af 100644
--- a/arch/s390/mm/extable.c
+++ b/arch/s390/mm/extable.c
@@ -61,6 +61,22 @@ static bool ex_handler_ua_load_reg(const struct exception_table_entry *ex,
return true;
}
+static bool ex_handler_zeropad(const struct exception_table_entry *ex, struct pt_regs *regs)
+{
+ unsigned int reg_addr = FIELD_GET(EX_DATA_REG_ADDR, ex->data);
+ unsigned int reg_data = FIELD_GET(EX_DATA_REG_ERR, ex->data);
+ unsigned long data, addr, offset;
+
+ addr = regs->gprs[reg_addr];
+ offset = addr & (sizeof(unsigned long) - 1);
+ addr &= ~(sizeof(unsigned long) - 1);
+ data = *(unsigned long *)addr;
+ data <<= BITS_PER_BYTE * offset;
+ regs->gprs[reg_data] = data;
+ regs->psw.addr = extable_fixup(ex);
+ return true;
+}
+
bool fixup_exception(struct pt_regs *regs)
{
const struct exception_table_entry *ex;
@@ -81,6 +97,8 @@ bool fixup_exception(struct pt_regs *regs)
return ex_handler_ua_load_reg(ex, false, regs);
case EX_TYPE_UA_LOAD_REGPAIR:
return ex_handler_ua_load_reg(ex, true, regs);
+ case EX_TYPE_ZEROPAD:
+ return ex_handler_zeropad(ex, regs);
}
panic("invalid exception table entry");
}
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index b678295931c3..249aefcf7c4e 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -3,17 +3,19 @@
* S390 version
* Copyright IBM Corp. 1999
* Author(s): Hartmut Penner (hp@de.ibm.com)
- * Ulrich Weigand (uweigand@de.ibm.com)
+ * Ulrich Weigand (uweigand@de.ibm.com)
*
* Derived from "arch/i386/mm/fault.c"
* Copyright (C) 1995 Linus Torvalds
*/
#include <linux/kernel_stat.h>
+#include <linux/mmu_context.h>
#include <linux/perf_event.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/sched/debug.h>
+#include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
@@ -34,38 +36,27 @@
#include <linux/kfence.h>
#include <asm/asm-extable.h>
#include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
+#include <asm/fault.h>
#include <asm/diag.h>
#include <asm/gmap.h>
#include <asm/irq.h>
-#include <asm/mmu_context.h>
#include <asm/facility.h>
#include <asm/uv.h>
#include "../kernel/entry.h"
-#define __FAIL_ADDR_MASK -4096L
-
-/*
- * Allocate private vm_fault_reason from top. Please make sure it won't
- * collide with vm_fault_reason.
- */
-#define VM_FAULT_BADCONTEXT ((__force vm_fault_t)0x80000000)
-#define VM_FAULT_BADMAP ((__force vm_fault_t)0x40000000)
-#define VM_FAULT_BADACCESS ((__force vm_fault_t)0x20000000)
-#define VM_FAULT_SIGNAL ((__force vm_fault_t)0x10000000)
-#define VM_FAULT_PFAULT ((__force vm_fault_t)0x8000000)
-
enum fault_type {
KERNEL_FAULT,
USER_FAULT,
GMAP_FAULT,
};
-static unsigned long store_indication __read_mostly;
+static DEFINE_STATIC_KEY_FALSE(have_store_indication);
static int __init fault_init(void)
{
if (test_facility(75))
- store_indication = 0xc00;
+ static_branch_enable(&have_store_indication);
return 0;
}
early_initcall(fault_init);
@@ -75,11 +66,9 @@ early_initcall(fault_init);
*/
static enum fault_type get_fault_type(struct pt_regs *regs)
{
- unsigned long trans_exc_code;
+ union teid teid = { .val = regs->int_parm_long };
- trans_exc_code = regs->int_parm_long & 3;
- if (likely(trans_exc_code == 0)) {
- /* primary space exception */
+ if (likely(teid.as == PSW_BITS_AS_PRIMARY)) {
if (user_mode(regs))
return USER_FAULT;
if (!IS_ENABLED(CONFIG_PGSTE))
@@ -88,83 +77,77 @@ static enum fault_type get_fault_type(struct pt_regs *regs)
return GMAP_FAULT;
return KERNEL_FAULT;
}
- if (trans_exc_code == 2)
+ if (teid.as == PSW_BITS_AS_SECONDARY)
return USER_FAULT;
- if (trans_exc_code == 1) {
- /* access register mode, not used in the kernel */
+ /* Access register mode, not used in the kernel */
+ if (teid.as == PSW_BITS_AS_ACCREG)
return USER_FAULT;
- }
- /* home space exception -> access via kernel ASCE */
+ /* Home space -> access via kernel ASCE */
return KERNEL_FAULT;
}
static unsigned long get_fault_address(struct pt_regs *regs)
{
- unsigned long trans_exc_code = regs->int_parm_long;
+ union teid teid = { .val = regs->int_parm_long };
- return trans_exc_code & __FAIL_ADDR_MASK;
+ return teid.addr * PAGE_SIZE;
}
-static bool fault_is_write(struct pt_regs *regs)
+static __always_inline bool fault_is_write(struct pt_regs *regs)
{
- unsigned long trans_exc_code = regs->int_parm_long;
+ union teid teid = { .val = regs->int_parm_long };
- return (trans_exc_code & store_indication) == 0x400;
-}
-
-static int bad_address(void *p)
-{
- unsigned long dummy;
-
- return get_kernel_nofault(dummy, (unsigned long *)p);
+ if (static_branch_likely(&have_store_indication))
+ return teid.fsi == TEID_FSI_STORE;
+ return false;
}
static void dump_pagetable(unsigned long asce, unsigned long address)
{
- unsigned long *table = __va(asce & _ASCE_ORIGIN);
+ unsigned long entry, *table = __va(asce & _ASCE_ORIGIN);
pr_alert("AS:%016lx ", asce);
switch (asce & _ASCE_TYPE_MASK) {
case _ASCE_TYPE_REGION1:
table += (address & _REGION1_INDEX) >> _REGION1_SHIFT;
- if (bad_address(table))
+ if (get_kernel_nofault(entry, table))
goto bad;
- pr_cont("R1:%016lx ", *table);
- if (*table & _REGION_ENTRY_INVALID)
+ pr_cont("R1:%016lx ", entry);
+ if (entry & _REGION_ENTRY_INVALID)
goto out;
- table = __va(*table & _REGION_ENTRY_ORIGIN);
+ table = __va(entry & _REGION_ENTRY_ORIGIN);
fallthrough;
case _ASCE_TYPE_REGION2:
table += (address & _REGION2_INDEX) >> _REGION2_SHIFT;
- if (bad_address(table))
+ if (get_kernel_nofault(entry, table))
goto bad;
- pr_cont("R2:%016lx ", *table);
- if (*table & _REGION_ENTRY_INVALID)
+ pr_cont("R2:%016lx ", entry);
+ if (entry & _REGION_ENTRY_INVALID)
goto out;
- table = __va(*table & _REGION_ENTRY_ORIGIN);
+ table = __va(entry & _REGION_ENTRY_ORIGIN);
fallthrough;
case _ASCE_TYPE_REGION3:
table += (address & _REGION3_INDEX) >> _REGION3_SHIFT;
- if (bad_address(table))
+ if (get_kernel_nofault(entry, table))
goto bad;
- pr_cont("R3:%016lx ", *table);
- if (*table & (_REGION_ENTRY_INVALID | _REGION3_ENTRY_LARGE))
+ pr_cont("R3:%016lx ", entry);
+ if (entry & (_REGION_ENTRY_INVALID | _REGION3_ENTRY_LARGE))
goto out;
- table = __va(*table & _REGION_ENTRY_ORIGIN);
+ table = __va(entry & _REGION_ENTRY_ORIGIN);
fallthrough;
case _ASCE_TYPE_SEGMENT:
table += (address & _SEGMENT_INDEX) >> _SEGMENT_SHIFT;
- if (bad_address(table))
+ if (get_kernel_nofault(entry, table))
goto bad;
- pr_cont("S:%016lx ", *table);
- if (*table & (_SEGMENT_ENTRY_INVALID | _SEGMENT_ENTRY_LARGE))
+ pr_cont("S:%016lx ", entry);
+ if (entry & (_SEGMENT_ENTRY_INVALID | _SEGMENT_ENTRY_LARGE))
goto out;
- table = __va(*table & _SEGMENT_ENTRY_ORIGIN);
+ table = __va(entry & _SEGMENT_ENTRY_ORIGIN);
}
table += (address & _PAGE_INDEX) >> _PAGE_SHIFT;
- if (bad_address(table))
+ if (get_kernel_nofault(entry, table))
goto bad;
- pr_cont("P:%016lx ", *table);
+ pr_cont("P:%016lx ", entry);
out:
pr_cont("\n");
return;
@@ -174,173 +157,113 @@ bad:
static void dump_fault_info(struct pt_regs *regs)
{
+ union teid teid = { .val = regs->int_parm_long };
unsigned long asce;
pr_alert("Failing address: %016lx TEID: %016lx\n",
- regs->int_parm_long & __FAIL_ADDR_MASK, regs->int_parm_long);
+ get_fault_address(regs), teid.val);
pr_alert("Fault in ");
- switch (regs->int_parm_long & 3) {
- case 3:
+ switch (teid.as) {
+ case PSW_BITS_AS_HOME:
pr_cont("home space ");
break;
- case 2:
+ case PSW_BITS_AS_SECONDARY:
pr_cont("secondary space ");
break;
- case 1:
+ case PSW_BITS_AS_ACCREG:
pr_cont("access register ");
break;
- case 0:
+ case PSW_BITS_AS_PRIMARY:
pr_cont("primary space ");
break;
}
pr_cont("mode while using ");
switch (get_fault_type(regs)) {
case USER_FAULT:
- asce = S390_lowcore.user_asce;
+ asce = S390_lowcore.user_asce.val;
pr_cont("user ");
break;
case GMAP_FAULT:
- asce = ((struct gmap *) S390_lowcore.gmap)->asce;
+ asce = ((struct gmap *)S390_lowcore.gmap)->asce;
pr_cont("gmap ");
break;
case KERNEL_FAULT:
- asce = S390_lowcore.kernel_asce;
+ asce = S390_lowcore.kernel_asce.val;
pr_cont("kernel ");
break;
default:
unreachable();
}
pr_cont("ASCE.\n");
- dump_pagetable(asce, regs->int_parm_long & __FAIL_ADDR_MASK);
+ dump_pagetable(asce, get_fault_address(regs));
}
int show_unhandled_signals = 1;
void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault)
{
+ static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
+
if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
return;
if (!unhandled_signal(current, signr))
return;
- if (!printk_ratelimit())
+ if (!__ratelimit(&rs))
return;
- printk(KERN_ALERT "User process fault: interruption code %04x ilc:%d ",
- regs->int_code & 0xffff, regs->int_code >> 17);
+ pr_alert("User process fault: interruption code %04x ilc:%d ",
+ regs->int_code & 0xffff, regs->int_code >> 17);
print_vma_addr(KERN_CONT "in ", regs->psw.addr);
- printk(KERN_CONT "\n");
+ pr_cont("\n");
if (is_mm_fault)
dump_fault_info(regs);
show_regs(regs);
}
-/*
- * Send SIGSEGV to task. This is an external routine
- * to keep the stack usage of do_page_fault small.
- */
-static noinline void do_sigsegv(struct pt_regs *regs, int si_code)
+static void do_sigsegv(struct pt_regs *regs, int si_code)
{
report_user_fault(regs, SIGSEGV, 1);
- force_sig_fault(SIGSEGV, si_code,
- (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK));
+ force_sig_fault(SIGSEGV, si_code, (void __user *)get_fault_address(regs));
}
-static noinline void do_no_context(struct pt_regs *regs, vm_fault_t fault)
+static void handle_fault_error_nolock(struct pt_regs *regs, int si_code)
{
enum fault_type fault_type;
unsigned long address;
bool is_write;
+ if (user_mode(regs)) {
+ if (WARN_ON_ONCE(!si_code))
+ si_code = SEGV_MAPERR;
+ return do_sigsegv(regs, si_code);
+ }
if (fixup_exception(regs))
return;
fault_type = get_fault_type(regs);
- if ((fault_type == KERNEL_FAULT) && (fault == VM_FAULT_BADCONTEXT)) {
+ if (fault_type == KERNEL_FAULT) {
address = get_fault_address(regs);
is_write = fault_is_write(regs);
if (kfence_handle_page_fault(address, is_write, regs))
return;
}
- /*
- * Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
- */
if (fault_type == KERNEL_FAULT)
- printk(KERN_ALERT "Unable to handle kernel pointer dereference"
- " in virtual kernel address space\n");
+ pr_alert("Unable to handle kernel pointer dereference in virtual kernel address space\n");
else
- printk(KERN_ALERT "Unable to handle kernel paging request"
- " in virtual user address space\n");
+ pr_alert("Unable to handle kernel paging request in virtual user address space\n");
dump_fault_info(regs);
die(regs, "Oops");
}
-static noinline void do_low_address(struct pt_regs *regs)
+static void handle_fault_error(struct pt_regs *regs, int si_code)
{
- /* Low-address protection hit in kernel mode means
- NULL pointer write access in kernel mode. */
- if (regs->psw.mask & PSW_MASK_PSTATE) {
- /* Low-address protection hit in user mode 'cannot happen'. */
- die (regs, "Low-address protection");
- }
+ struct mm_struct *mm = current->mm;
- do_no_context(regs, VM_FAULT_BADACCESS);
-}
-
-static noinline void do_sigbus(struct pt_regs *regs)
-{
- /*
- * Send a sigbus, regardless of whether we were in kernel
- * or user mode.
- */
- force_sig_fault(SIGBUS, BUS_ADRERR,
- (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK));
+ mmap_read_unlock(mm);
+ handle_fault_error_nolock(regs, si_code);
}
-static noinline void do_fault_error(struct pt_regs *regs, vm_fault_t fault)
+static void do_sigbus(struct pt_regs *regs)
{
- int si_code;
-
- switch (fault) {
- case VM_FAULT_BADACCESS:
- case VM_FAULT_BADMAP:
- /* Bad memory access. Check if it is kernel or user space. */
- if (user_mode(regs)) {
- /* User mode accesses just cause a SIGSEGV */
- si_code = (fault == VM_FAULT_BADMAP) ?
- SEGV_MAPERR : SEGV_ACCERR;
- do_sigsegv(regs, si_code);
- break;
- }
- fallthrough;
- case VM_FAULT_BADCONTEXT:
- case VM_FAULT_PFAULT:
- do_no_context(regs, fault);
- break;
- case VM_FAULT_SIGNAL:
- if (!user_mode(regs))
- do_no_context(regs, fault);
- break;
- default: /* fault & VM_FAULT_ERROR */
- if (fault & VM_FAULT_OOM) {
- if (!user_mode(regs))
- do_no_context(regs, fault);
- else
- pagefault_out_of_memory();
- } else if (fault & VM_FAULT_SIGSEGV) {
- /* Kernel mode? Handle exceptions or die */
- if (!user_mode(regs))
- do_no_context(regs, fault);
- else
- do_sigsegv(regs, SEGV_MAPERR);
- } else if (fault & VM_FAULT_SIGBUS) {
- /* Kernel mode? Handle exceptions or die */
- if (!user_mode(regs))
- do_no_context(regs, fault);
- else
- do_sigbus(regs);
- } else
- BUG();
- break;
- }
+ force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)get_fault_address(regs));
}
/*
@@ -349,20 +272,20 @@ static noinline void do_fault_error(struct pt_regs *regs, vm_fault_t fault)
* routines.
*
* interruption code (int_code):
- * 04 Protection -> Write-Protection (suppression)
- * 10 Segment translation -> Not present (nullification)
- * 11 Page translation -> Not present (nullification)
- * 3b Region third trans. -> Not present (nullification)
+ * 04 Protection -> Write-Protection (suppression)
+ * 10 Segment translation -> Not present (nullification)
+ * 11 Page translation -> Not present (nullification)
+ * 3b Region third trans. -> Not present (nullification)
*/
-static inline vm_fault_t do_exception(struct pt_regs *regs, int access)
+static void do_exception(struct pt_regs *regs, int access)
{
- struct gmap *gmap;
+ struct vm_area_struct *vma;
struct task_struct *tsk;
+ unsigned long address;
struct mm_struct *mm;
- struct vm_area_struct *vma;
enum fault_type type;
- unsigned long address;
unsigned int flags;
+ struct gmap *gmap;
vm_fault_t fault;
bool is_write;
@@ -372,31 +295,21 @@ static inline vm_fault_t do_exception(struct pt_regs *regs, int access)
* been nullified. Don't signal single step via SIGTRAP.
*/
clear_thread_flag(TIF_PER_TRAP);
-
if (kprobe_page_fault(regs, 14))
- return 0;
-
+ return;
mm = tsk->mm;
address = get_fault_address(regs);
is_write = fault_is_write(regs);
-
- /*
- * Verify that the fault happened in user space, that
- * we are not in an interrupt and that there is a
- * user context.
- */
- fault = VM_FAULT_BADCONTEXT;
type = get_fault_type(regs);
switch (type) {
case KERNEL_FAULT:
- goto out;
+ return handle_fault_error_nolock(regs, 0);
case USER_FAULT:
case GMAP_FAULT:
if (faulthandler_disabled() || !mm)
- goto out;
+ return handle_fault_error_nolock(regs, 0);
break;
}
-
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
flags = FAULT_FLAG_DEFAULT;
if (user_mode(regs))
@@ -419,125 +332,117 @@ static inline vm_fault_t do_exception(struct pt_regs *regs, int access)
vma_end_read(vma);
if (!(fault & VM_FAULT_RETRY)) {
count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
- if (likely(!(fault & VM_FAULT_ERROR)))
- fault = 0;
- goto out;
+ if (unlikely(fault & VM_FAULT_ERROR))
+ goto error;
+ return;
}
count_vm_vma_lock_event(VMA_LOCK_RETRY);
/* Quick path to respond to signals */
if (fault_signal_pending(fault, regs)) {
- fault = VM_FAULT_SIGNAL;
- goto out;
+ if (!user_mode(regs))
+ handle_fault_error_nolock(regs, 0);
+ return;
}
lock_mmap:
mmap_read_lock(mm);
-
gmap = NULL;
if (IS_ENABLED(CONFIG_PGSTE) && type == GMAP_FAULT) {
- gmap = (struct gmap *) S390_lowcore.gmap;
+ gmap = (struct gmap *)S390_lowcore.gmap;
current->thread.gmap_addr = address;
current->thread.gmap_write_flag = !!(flags & FAULT_FLAG_WRITE);
current->thread.gmap_int_code = regs->int_code & 0xffff;
address = __gmap_translate(gmap, address);
- if (address == -EFAULT) {
- fault = VM_FAULT_BADMAP;
- goto out_up;
- }
+ if (address == -EFAULT)
+ return handle_fault_error(regs, SEGV_MAPERR);
if (gmap->pfault_enabled)
flags |= FAULT_FLAG_RETRY_NOWAIT;
}
-
retry:
- fault = VM_FAULT_BADMAP;
vma = find_vma(mm, address);
if (!vma)
- goto out_up;
-
+ return handle_fault_error(regs, SEGV_MAPERR);
if (unlikely(vma->vm_start > address)) {
if (!(vma->vm_flags & VM_GROWSDOWN))
- goto out_up;
+ return handle_fault_error(regs, SEGV_MAPERR);
vma = expand_stack(mm, address);
if (!vma)
- goto out;
+ return handle_fault_error_nolock(regs, SEGV_MAPERR);
}
-
- /*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
- fault = VM_FAULT_BADACCESS;
if (unlikely(!(vma->vm_flags & access)))
- goto out_up;
-
- /*
- * If for any reason at all we couldn't handle the fault,
- * make sure we exit gracefully rather than endlessly redo
- * the fault.
- */
+ return handle_fault_error(regs, SEGV_ACCERR);
fault = handle_mm_fault(vma, address, flags, regs);
if (fault_signal_pending(fault, regs)) {
- fault = VM_FAULT_SIGNAL;
if (flags & FAULT_FLAG_RETRY_NOWAIT)
- goto out_up;
- goto out;
+ mmap_read_unlock(mm);
+ if (!user_mode(regs))
+ handle_fault_error_nolock(regs, 0);
+ return;
}
-
/* The fault is fully completed (including releasing mmap lock) */
if (fault & VM_FAULT_COMPLETED) {
if (gmap) {
mmap_read_lock(mm);
- goto out_gmap;
+ goto gmap;
}
- fault = 0;
- goto out;
+ return;
+ }
+ if (unlikely(fault & VM_FAULT_ERROR)) {
+ mmap_read_unlock(mm);
+ goto error;
}
-
- if (unlikely(fault & VM_FAULT_ERROR))
- goto out_up;
-
if (fault & VM_FAULT_RETRY) {
- if (IS_ENABLED(CONFIG_PGSTE) && gmap &&
- (flags & FAULT_FLAG_RETRY_NOWAIT)) {
+ if (IS_ENABLED(CONFIG_PGSTE) && gmap && (flags & FAULT_FLAG_RETRY_NOWAIT)) {
/*
- * FAULT_FLAG_RETRY_NOWAIT has been set, mmap_lock has
- * not been released
+ * FAULT_FLAG_RETRY_NOWAIT has been set,
+ * mmap_lock has not been released
*/
current->thread.gmap_pfault = 1;
- fault = VM_FAULT_PFAULT;
- goto out_up;
+ return handle_fault_error(regs, 0);
}
flags &= ~FAULT_FLAG_RETRY_NOWAIT;
flags |= FAULT_FLAG_TRIED;
mmap_read_lock(mm);
goto retry;
}
-out_gmap:
+gmap:
if (IS_ENABLED(CONFIG_PGSTE) && gmap) {
address = __gmap_link(gmap, current->thread.gmap_addr,
address);
- if (address == -EFAULT) {
- fault = VM_FAULT_BADMAP;
- goto out_up;
- }
+ if (address == -EFAULT)
+ return handle_fault_error(regs, SEGV_MAPERR);
if (address == -ENOMEM) {
fault = VM_FAULT_OOM;
- goto out_up;
+ mmap_read_unlock(mm);
+ goto error;
}
}
- fault = 0;
-out_up:
mmap_read_unlock(mm);
-out:
- return fault;
+ return;
+error:
+ if (fault & VM_FAULT_OOM) {
+ if (!user_mode(regs))
+ handle_fault_error_nolock(regs, 0);
+ else
+ pagefault_out_of_memory();
+ } else if (fault & VM_FAULT_SIGSEGV) {
+ if (!user_mode(regs))
+ handle_fault_error_nolock(regs, 0);
+ else
+ do_sigsegv(regs, SEGV_MAPERR);
+ } else if (fault & VM_FAULT_SIGBUS) {
+ if (!user_mode(regs))
+ handle_fault_error_nolock(regs, 0);
+ else
+ do_sigbus(regs);
+ } else {
+ BUG();
+ }
}
void do_protection_exception(struct pt_regs *regs)
{
- unsigned long trans_exc_code;
- int access;
- vm_fault_t fault;
+ union teid teid = { .val = regs->int_parm_long };
- trans_exc_code = regs->int_parm_long;
/*
* Protection exceptions are suppressing, decrement psw address.
* The exception to this rule are aborted transactions, for these
@@ -550,33 +455,28 @@ void do_protection_exception(struct pt_regs *regs)
* as a special case because the translation exception code
* field is not guaranteed to contain valid data in this case.
*/
- if (unlikely(!(trans_exc_code & 4))) {
- do_low_address(regs);
- return;
+ if (unlikely(!teid.b61)) {
+ if (user_mode(regs)) {
+ /* Low-address protection in user mode: cannot happen */
+ die(regs, "Low-address protection");
+ }
+ /*
+ * Low-address protection in kernel mode means
+ * NULL pointer write access in kernel mode.
+ */
+ return handle_fault_error_nolock(regs, 0);
}
- if (unlikely(MACHINE_HAS_NX && (trans_exc_code & 0x80))) {
- regs->int_parm_long = (trans_exc_code & ~PAGE_MASK) |
- (regs->psw.addr & PAGE_MASK);
- access = VM_EXEC;
- fault = VM_FAULT_BADACCESS;
- } else {
- access = VM_WRITE;
- fault = do_exception(regs, access);
+ if (unlikely(MACHINE_HAS_NX && teid.b56)) {
+ regs->int_parm_long = (teid.addr * PAGE_SIZE) | (regs->psw.addr & PAGE_MASK);
+ return handle_fault_error_nolock(regs, SEGV_ACCERR);
}
- if (unlikely(fault))
- do_fault_error(regs, fault);
+ do_exception(regs, VM_WRITE);
}
NOKPROBE_SYMBOL(do_protection_exception);
void do_dat_exception(struct pt_regs *regs)
{
- int access;
- vm_fault_t fault;
-
- access = VM_ACCESS_FLAGS;
- fault = do_exception(regs, access);
- if (unlikely(fault))
- do_fault_error(regs, fault);
+ do_exception(regs, VM_ACCESS_FLAGS);
}
NOKPROBE_SYMBOL(do_dat_exception);
@@ -584,7 +484,8 @@ NOKPROBE_SYMBOL(do_dat_exception);
void do_secure_storage_access(struct pt_regs *regs)
{
- unsigned long addr = regs->int_parm_long & __FAIL_ADDR_MASK;
+ union teid teid = { .val = regs->int_parm_long };
+ unsigned long addr = get_fault_address(regs);
struct vm_area_struct *vma;
struct mm_struct *mm;
struct page *page;
@@ -592,14 +493,12 @@ void do_secure_storage_access(struct pt_regs *regs)
int rc;
/*
- * bit 61 tells us if the address is valid, if it's not we
- * have a major problem and should stop the kernel or send a
- * SIGSEGV to the process. Unfortunately bit 61 is not
- * reliable without the misc UV feature so we need to check
- * for that as well.
+ * Bit 61 indicates if the address is valid, if it is not the
+ * kernel should be stopped or SIGSEGV should be sent to the
+ * process. Bit 61 is not reliable without the misc UV feature,
+ * therefore this needs to be checked too.
*/
- if (uv_has_feature(BIT_UV_FEAT_MISC) &&
- !test_bit_inv(61, &regs->int_parm_long)) {
+ if (uv_has_feature(BIT_UV_FEAT_MISC) && !teid.b61) {
/*
* When this happens, userspace did something that it
* was not supposed to do, e.g. branching into secure
@@ -609,14 +508,12 @@ void do_secure_storage_access(struct pt_regs *regs)
send_sig(SIGSEGV, current, 0);
return;
}
-
/*
- * The kernel should never run into this case and we
- * have no way out of this situation.
+ * The kernel should never run into this case and
+ * there is no way out of this situation.
*/
panic("Unexpected PGM 0x3d with TEID bit 61=0");
}
-
switch (get_fault_type(regs)) {
case GMAP_FAULT:
mm = current->mm;
@@ -624,20 +521,15 @@ void do_secure_storage_access(struct pt_regs *regs)
mmap_read_lock(mm);
addr = __gmap_translate(gmap, addr);
mmap_read_unlock(mm);
- if (IS_ERR_VALUE(addr)) {
- do_fault_error(regs, VM_FAULT_BADMAP);
- break;
- }
+ if (IS_ERR_VALUE(addr))
+ return handle_fault_error_nolock(regs, SEGV_MAPERR);
fallthrough;
case USER_FAULT:
mm = current->mm;
mmap_read_lock(mm);
vma = find_vma(mm, addr);
- if (!vma) {
- mmap_read_unlock(mm);
- do_fault_error(regs, VM_FAULT_BADMAP);
- break;
- }
+ if (!vma)
+ return handle_fault_error(regs, SEGV_MAPERR);
page = follow_page(vma, addr, FOLL_WRITE | FOLL_GET);
if (IS_ERR_OR_NULL(page)) {
mmap_read_unlock(mm);
@@ -658,23 +550,18 @@ void do_secure_storage_access(struct pt_regs *regs)
BUG();
break;
default:
- do_fault_error(regs, VM_FAULT_BADMAP);
- WARN_ON_ONCE(1);
+ unreachable();
}
}
NOKPROBE_SYMBOL(do_secure_storage_access);
void do_non_secure_storage_access(struct pt_regs *regs)
{
- unsigned long gaddr = regs->int_parm_long & __FAIL_ADDR_MASK;
struct gmap *gmap = (struct gmap *)S390_lowcore.gmap;
+ unsigned long gaddr = get_fault_address(regs);
- if (get_fault_type(regs) != GMAP_FAULT) {
- do_fault_error(regs, VM_FAULT_BADMAP);
- WARN_ON_ONCE(1);
- return;
- }
-
+ if (WARN_ON_ONCE(get_fault_type(regs) != GMAP_FAULT))
+ return handle_fault_error_nolock(regs, SEGV_MAPERR);
if (gmap_convert_to_secure(gmap, gaddr) == -EINVAL)
send_sig(SIGSEGV, current, 0);
}
@@ -682,8 +569,8 @@ NOKPROBE_SYMBOL(do_non_secure_storage_access);
void do_secure_storage_violation(struct pt_regs *regs)
{
- unsigned long gaddr = regs->int_parm_long & __FAIL_ADDR_MASK;
struct gmap *gmap = (struct gmap *)S390_lowcore.gmap;
+ unsigned long gaddr = get_fault_address(regs);
/*
* If the VM has been rebooted, its address space might still contain
@@ -699,9 +586,8 @@ void do_secure_storage_violation(struct pt_regs *regs)
* This exception is only triggered when a guest 2 is running
* and can therefore never occur in kernel context.
*/
- printk_ratelimited(KERN_WARNING
- "Secure storage violation in task: %s, pid %d\n",
- current->comm, current->pid);
+ pr_warn_ratelimited("Secure storage violation in task: %s, pid %d\n",
+ current->comm, current->pid);
send_sig(SIGSEGV, current, 0);
}
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index 906a7bfc2a78..6f96b5a71c63 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -18,13 +18,25 @@
#include <linux/ksm.h>
#include <linux/mman.h>
#include <linux/pgtable.h>
-
+#include <asm/page-states.h>
#include <asm/pgalloc.h>
#include <asm/gmap.h>
+#include <asm/page.h>
#include <asm/tlb.h>
#define GMAP_SHADOW_FAKE_TABLE 1ULL
+static struct page *gmap_alloc_crst(void)
+{
+ struct page *page;
+
+ page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER);
+ if (!page)
+ return NULL;
+ __arch_set_page_dat(page_to_virt(page), 1UL << CRST_ALLOC_ORDER);
+ return page;
+}
+
/**
* gmap_alloc - allocate and initialize a guest address space
* @limit: maximum address of the gmap address space
@@ -67,7 +79,7 @@ static struct gmap *gmap_alloc(unsigned long limit)
spin_lock_init(&gmap->guest_table_lock);
spin_lock_init(&gmap->shadow_lock);
refcount_set(&gmap->ref_count, 1);
- page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER);
+ page = gmap_alloc_crst();
if (!page)
goto out_free;
page->index = 0;
@@ -308,7 +320,7 @@ static int gmap_alloc_table(struct gmap *gmap, unsigned long *table,
unsigned long *new;
/* since we dont free the gmap table until gmap_free we can unlock */
- page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER);
+ page = gmap_alloc_crst();
if (!page)
return -ENOMEM;
new = page_to_virt(page);
@@ -1759,7 +1771,7 @@ int gmap_shadow_r2t(struct gmap *sg, unsigned long saddr, unsigned long r2t,
BUG_ON(!gmap_is_shadow(sg));
/* Allocate a shadow region second table */
- page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER);
+ page = gmap_alloc_crst();
if (!page)
return -ENOMEM;
page->index = r2t & _REGION_ENTRY_ORIGIN;
@@ -1843,7 +1855,7 @@ int gmap_shadow_r3t(struct gmap *sg, unsigned long saddr, unsigned long r3t,
BUG_ON(!gmap_is_shadow(sg));
/* Allocate a shadow region second table */
- page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER);
+ page = gmap_alloc_crst();
if (!page)
return -ENOMEM;
page->index = r3t & _REGION_ENTRY_ORIGIN;
@@ -1927,7 +1939,7 @@ int gmap_shadow_sgt(struct gmap *sg, unsigned long saddr, unsigned long sgt,
BUG_ON(!gmap_is_shadow(sg) || (sgt & _REGION3_ENTRY_LARGE));
/* Allocate a shadow segment table */
- page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER);
+ page = gmap_alloc_crst();
if (!page)
return -ENOMEM;
page->index = sgt & _REGION_ENTRY_ORIGIN;
@@ -2855,7 +2867,7 @@ int s390_replace_asce(struct gmap *gmap)
if ((gmap->asce & _ASCE_TYPE_MASK) == _ASCE_TYPE_SEGMENT)
return -EINVAL;
- page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER);
+ page = gmap_alloc_crst();
if (!page)
return -ENOMEM;
page->index = 0;
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 8b94d2212d33..43e612bc2bcd 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -35,6 +35,7 @@
#include <asm/processor.h>
#include <linux/uaccess.h>
#include <asm/pgalloc.h>
+#include <asm/ctlreg.h>
#include <asm/kfence.h>
#include <asm/ptdump.h>
#include <asm/dma.h>
@@ -42,7 +43,6 @@
#include <asm/tlb.h>
#include <asm/tlbflush.h>
#include <asm/sections.h>
-#include <asm/ctl_reg.h>
#include <asm/sclp.h>
#include <asm/set_memory.h>
#include <asm/kasan.h>
@@ -54,7 +54,7 @@
pgd_t swapper_pg_dir[PTRS_PER_PGD] __section(".bss..swapper_pg_dir");
pgd_t invalid_pg_dir[PTRS_PER_PGD] __section(".bss..invalid_pg_dir");
-unsigned long __bootdata_preserved(s390_invalid_asce);
+struct ctlreg __bootdata_preserved(s390_invalid_asce);
unsigned long empty_zero_page, zero_page_mask;
EXPORT_SYMBOL(empty_zero_page);
@@ -164,14 +164,10 @@ void __init mem_init(void)
pv_init();
kfence_split_mapping();
- /* Setup guest page hinting */
- cmma_init();
/* this will put all low memory onto the freelists */
memblock_free_all();
setup_zero_pages(); /* Setup zeroed pages. */
-
- cmma_init_nodat();
}
void free_initmem(void)
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
index c805b3e2592b..632c3a55feed 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
@@ -15,10 +15,10 @@
#include <linux/uio.h>
#include <linux/io.h>
#include <asm/asm-extable.h>
-#include <asm/ctl_reg.h>
#include <asm/abs_lowcore.h>
#include <asm/stacktrace.h>
#include <asm/maccess.h>
+#include <asm/ctlreg.h>
unsigned long __bootdata_preserved(__memcpy_real_area);
pte_t *__bootdata_preserved(memcpy_real_ptep);
diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c
index 1e2ea706aa22..01f9b39e65f5 100644
--- a/arch/s390/mm/page-states.c
+++ b/arch/s390/mm/page-states.c
@@ -7,199 +7,18 @@
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
#include <linux/mm.h>
-#include <linux/memblock.h>
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <asm/asm-extable.h>
-#include <asm/facility.h>
#include <asm/page-states.h>
+#include <asm/sections.h>
+#include <asm/page.h>
-static int cmma_flag = 1;
-
-static int __init cmma(char *str)
-{
- bool enabled;
-
- if (!kstrtobool(str, &enabled))
- cmma_flag = enabled;
- return 1;
-}
-__setup("cmma=", cmma);
-
-static inline int cmma_test_essa(void)
-{
- unsigned long tmp = 0;
- int rc = -EOPNOTSUPP;
-
- /* test ESSA_GET_STATE */
- asm volatile(
- " .insn rrf,0xb9ab0000,%[tmp],%[tmp],%[cmd],0\n"
- "0: la %[rc],0\n"
- "1:\n"
- EX_TABLE(0b,1b)
- : [rc] "+&d" (rc), [tmp] "+&d" (tmp)
- : [cmd] "i" (ESSA_GET_STATE));
- return rc;
-}
-
-void __init cmma_init(void)
-{
- if (!cmma_flag)
- return;
- if (cmma_test_essa()) {
- cmma_flag = 0;
- return;
- }
- if (test_facility(147))
- cmma_flag = 2;
-}
-
-static inline void set_page_unused(struct page *page, int order)
-{
- int i, rc;
-
- for (i = 0; i < (1 << order); i++)
- asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0"
- : "=&d" (rc)
- : "a" (page_to_phys(page + i)),
- "i" (ESSA_SET_UNUSED));
-}
-
-static inline void set_page_stable_dat(struct page *page, int order)
-{
- int i, rc;
-
- for (i = 0; i < (1 << order); i++)
- asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0"
- : "=&d" (rc)
- : "a" (page_to_phys(page + i)),
- "i" (ESSA_SET_STABLE));
-}
-
-static inline void set_page_stable_nodat(struct page *page, int order)
-{
- int i, rc;
-
- for (i = 0; i < (1 << order); i++)
- asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0"
- : "=&d" (rc)
- : "a" (page_to_phys(page + i)),
- "i" (ESSA_SET_STABLE_NODAT));
-}
-
-static void mark_kernel_pmd(pud_t *pud, unsigned long addr, unsigned long end)
-{
- unsigned long next;
- struct page *page;
- pmd_t *pmd;
-
- pmd = pmd_offset(pud, addr);
- do {
- next = pmd_addr_end(addr, end);
- if (pmd_none(*pmd) || pmd_large(*pmd))
- continue;
- page = phys_to_page(pmd_val(*pmd));
- set_bit(PG_arch_1, &page->flags);
- } while (pmd++, addr = next, addr != end);
-}
-
-static void mark_kernel_pud(p4d_t *p4d, unsigned long addr, unsigned long end)
-{
- unsigned long next;
- struct page *page;
- pud_t *pud;
- int i;
-
- pud = pud_offset(p4d, addr);
- do {
- next = pud_addr_end(addr, end);
- if (pud_none(*pud) || pud_large(*pud))
- continue;
- if (!pud_folded(*pud)) {
- page = phys_to_page(pud_val(*pud));
- for (i = 0; i < 3; i++)
- set_bit(PG_arch_1, &page[i].flags);
- }
- mark_kernel_pmd(pud, addr, next);
- } while (pud++, addr = next, addr != end);
-}
-
-static void mark_kernel_p4d(pgd_t *pgd, unsigned long addr, unsigned long end)
-{
- unsigned long next;
- struct page *page;
- p4d_t *p4d;
- int i;
-
- p4d = p4d_offset(pgd, addr);
- do {
- next = p4d_addr_end(addr, end);
- if (p4d_none(*p4d))
- continue;
- if (!p4d_folded(*p4d)) {
- page = phys_to_page(p4d_val(*p4d));
- for (i = 0; i < 3; i++)
- set_bit(PG_arch_1, &page[i].flags);
- }
- mark_kernel_pud(p4d, addr, next);
- } while (p4d++, addr = next, addr != end);
-}
-
-static void mark_kernel_pgd(void)
-{
- unsigned long addr, next;
- struct page *page;
- pgd_t *pgd;
- int i;
-
- addr = 0;
- pgd = pgd_offset_k(addr);
- do {
- next = pgd_addr_end(addr, MODULES_END);
- if (pgd_none(*pgd))
- continue;
- if (!pgd_folded(*pgd)) {
- page = phys_to_page(pgd_val(*pgd));
- for (i = 0; i < 3; i++)
- set_bit(PG_arch_1, &page[i].flags);
- }
- mark_kernel_p4d(pgd, addr, next);
- } while (pgd++, addr = next, addr != MODULES_END);
-}
-
-void __init cmma_init_nodat(void)
-{
- struct page *page;
- unsigned long start, end, ix;
- int i;
-
- if (cmma_flag < 2)
- return;
- /* Mark pages used in kernel page tables */
- mark_kernel_pgd();
-
- /* Set all kernel pages not used for page tables to stable/no-dat */
- for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, NULL) {
- page = pfn_to_page(start);
- for (ix = start; ix < end; ix++, page++) {
- if (__test_and_clear_bit(PG_arch_1, &page->flags))
- continue; /* skip page table pages */
- if (!list_empty(&page->lru))
- continue; /* skip free pages */
- set_page_stable_nodat(page, 0);
- }
- }
-}
+int __bootdata_preserved(cmma_flag);
void arch_free_page(struct page *page, int order)
{
if (!cmma_flag)
return;
- set_page_unused(page, order);
+ __set_page_unused(page_to_virt(page), 1UL << order);
}
void arch_alloc_page(struct page *page, int order)
@@ -207,14 +26,7 @@ void arch_alloc_page(struct page *page, int order)
if (!cmma_flag)
return;
if (cmma_flag < 2)
- set_page_stable_dat(page, order);
+ __set_page_stable_dat(page_to_virt(page), 1UL << order);
else
- set_page_stable_nodat(page, order);
-}
-
-void arch_set_page_dat(struct page *page, int order)
-{
- if (!cmma_flag)
- return;
- set_page_stable_dat(page, order);
+ __set_page_stable_nodat(page_to_virt(page), 1UL << order);
}
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index b87e96c64b61..631e3a4ee2de 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -75,7 +75,7 @@ static void pgt_set(unsigned long *old, unsigned long new, unsigned long addr,
break;
}
table = (unsigned long *)((unsigned long)old & mask);
- crdte(*old, new, table, dtt, addr, S390_lowcore.kernel_asce);
+ crdte(*old, new, table, dtt, addr, S390_lowcore.kernel_asce.val);
} else if (MACHINE_HAS_IDTE) {
cspg(old, *old, new);
} else {
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index 07fc660a24aa..008e487c94a6 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -10,6 +10,7 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <asm/mmu_context.h>
+#include <asm/page-states.h>
#include <asm/pgalloc.h>
#include <asm/gmap.h>
#include <asm/tlb.h>
@@ -30,7 +31,6 @@ static struct ctl_table page_table_sysctl[] = {
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
- { }
};
static int __init page_table_register_sysctl(void)
@@ -44,11 +44,13 @@ __initcall(page_table_register_sysctl);
unsigned long *crst_table_alloc(struct mm_struct *mm)
{
struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, CRST_ALLOC_ORDER);
+ unsigned long *table;
if (!ptdesc)
return NULL;
- arch_set_page_dat(ptdesc_page(ptdesc), CRST_ALLOC_ORDER);
- return (unsigned long *) ptdesc_to_virt(ptdesc);
+ table = ptdesc_to_virt(ptdesc);
+ __arch_set_page_dat(table, 1UL << CRST_ALLOC_ORDER);
+ return table;
}
void crst_table_free(struct mm_struct *mm, unsigned long *table)
@@ -62,8 +64,8 @@ static void __crst_table_upgrade(void *arg)
/* change all active ASCEs to avoid the creation of new TLBs */
if (current->active_mm == mm) {
- S390_lowcore.user_asce = mm->context.asce;
- __ctl_load(S390_lowcore.user_asce, 7, 7);
+ S390_lowcore.user_asce.val = mm->context.asce;
+ local_ctl_load(7, &S390_lowcore.user_asce);
}
__tlb_flush_local();
}
@@ -131,11 +133,6 @@ err_p4d:
return -ENOMEM;
}
-static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
-{
- return atomic_fetch_xor(bits, v) ^ bits;
-}
-
#ifdef CONFIG_PGSTE
struct page *page_table_alloc_pgste(struct mm_struct *mm)
@@ -146,6 +143,7 @@ struct page *page_table_alloc_pgste(struct mm_struct *mm)
ptdesc = pagetable_alloc(GFP_KERNEL, 0);
if (ptdesc) {
table = (u64 *)ptdesc_to_virt(ptdesc);
+ __arch_set_page_dat(table, 1);
memset64(table, _PAGE_INVALID, PTRS_PER_PTE);
memset64(table + PTRS_PER_PTE, 0, PTRS_PER_PTE);
}
@@ -159,125 +157,11 @@ void page_table_free_pgste(struct page *page)
#endif /* CONFIG_PGSTE */
-/*
- * A 2KB-pgtable is either upper or lower half of a normal page.
- * The second half of the page may be unused or used as another
- * 2KB-pgtable.
- *
- * Whenever possible the parent page for a new 2KB-pgtable is picked
- * from the list of partially allocated pages mm_context_t::pgtable_list.
- * In case the list is empty a new parent page is allocated and added to
- * the list.
- *
- * When a parent page gets fully allocated it contains 2KB-pgtables in both
- * upper and lower halves and is removed from mm_context_t::pgtable_list.
- *
- * When 2KB-pgtable is freed from to fully allocated parent page that
- * page turns partially allocated and added to mm_context_t::pgtable_list.
- *
- * If 2KB-pgtable is freed from the partially allocated parent page that
- * page turns unused and gets removed from mm_context_t::pgtable_list.
- * Furthermore, the unused parent page is released.
- *
- * As follows from the above, no unallocated or fully allocated parent
- * pages are contained in mm_context_t::pgtable_list.
- *
- * The upper byte (bits 24-31) of the parent page _refcount is used
- * for tracking contained 2KB-pgtables and has the following format:
- *
- * PP AA
- * 01234567 upper byte (bits 24-31) of struct page::_refcount
- * || ||
- * || |+--- upper 2KB-pgtable is allocated
- * || +---- lower 2KB-pgtable is allocated
- * |+------- upper 2KB-pgtable is pending for removal
- * +-------- lower 2KB-pgtable is pending for removal
- *
- * (See commit 620b4e903179 ("s390: use _refcount for pgtables") on why
- * using _refcount is possible).
- *
- * When 2KB-pgtable is allocated the corresponding AA bit is set to 1.
- * The parent page is either:
- * - added to mm_context_t::pgtable_list in case the second half of the
- * parent page is still unallocated;
- * - removed from mm_context_t::pgtable_list in case both hales of the
- * parent page are allocated;
- * These operations are protected with mm_context_t::lock.
- *
- * When 2KB-pgtable is deallocated the corresponding AA bit is set to 0
- * and the corresponding PP bit is set to 1 in a single atomic operation.
- * Thus, PP and AA bits corresponding to the same 2KB-pgtable are mutually
- * exclusive and may never be both set to 1!
- * The parent page is either:
- * - added to mm_context_t::pgtable_list in case the second half of the
- * parent page is still allocated;
- * - removed from mm_context_t::pgtable_list in case the second half of
- * the parent page is unallocated;
- * These operations are protected with mm_context_t::lock.
- *
- * It is important to understand that mm_context_t::lock only protects
- * mm_context_t::pgtable_list and AA bits, but not the parent page itself
- * and PP bits.
- *
- * Releasing the parent page happens whenever the PP bit turns from 1 to 0,
- * while both AA bits and the second PP bit are already unset. Then the
- * parent page does not contain any 2KB-pgtable fragment anymore, and it has
- * also been removed from mm_context_t::pgtable_list. It is safe to release
- * the page therefore.
- *
- * PGSTE memory spaces use full 4KB-pgtables and do not need most of the
- * logic described above. Both AA bits are set to 1 to denote a 4KB-pgtable
- * while the PP bits are never used, nor such a page is added to or removed
- * from mm_context_t::pgtable_list.
- *
- * pte_free_defer() overrides those rules: it takes the page off pgtable_list,
- * and prevents both 2K fragments from being reused. pte_free_defer() has to
- * guarantee that its pgtable cannot be reused before the RCU grace period
- * has elapsed (which page_table_free_rcu() does not actually guarantee).
- * But for simplicity, because page->rcu_head overlays page->lru, and because
- * the RCU callback might not be called before the mm_context_t has been freed,
- * pte_free_defer() in this implementation prevents both fragments from being
- * reused, and delays making the call to RCU until both fragments are freed.
- */
unsigned long *page_table_alloc(struct mm_struct *mm)
{
- unsigned long *table;
struct ptdesc *ptdesc;
- unsigned int mask, bit;
-
- /* Try to get a fragment of a 4K page as a 2K page table */
- if (!mm_alloc_pgste(mm)) {
- table = NULL;
- spin_lock_bh(&mm->context.lock);
- if (!list_empty(&mm->context.pgtable_list)) {
- ptdesc = list_first_entry(&mm->context.pgtable_list,
- struct ptdesc, pt_list);
- mask = atomic_read(&ptdesc->_refcount) >> 24;
- /*
- * The pending removal bits must also be checked.
- * Failure to do so might lead to an impossible
- * value of (i.e 0x13 or 0x23) written to _refcount.
- * Such values violate the assumption that pending and
- * allocation bits are mutually exclusive, and the rest
- * of the code unrails as result. That could lead to
- * a whole bunch of races and corruptions.
- */
- mask = (mask | (mask >> 4)) & 0x03U;
- if (mask != 0x03U) {
- table = (unsigned long *) ptdesc_to_virt(ptdesc);
- bit = mask & 1; /* =1 -> second 2K */
- if (bit)
- table += PTRS_PER_PTE;
- atomic_xor_bits(&ptdesc->_refcount,
- 0x01U << (bit + 24));
- list_del_init(&ptdesc->pt_list);
- }
- }
- spin_unlock_bh(&mm->context.lock);
- if (table)
- return table;
- }
- /* Allocate a fresh page */
+ unsigned long *table;
+
ptdesc = pagetable_alloc(GFP_KERNEL, 0);
if (!ptdesc)
return NULL;
@@ -285,177 +169,57 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
pagetable_free(ptdesc);
return NULL;
}
- arch_set_page_dat(ptdesc_page(ptdesc), 0);
- /* Initialize page table */
- table = (unsigned long *) ptdesc_to_virt(ptdesc);
- if (mm_alloc_pgste(mm)) {
- /* Return 4K page table with PGSTEs */
- INIT_LIST_HEAD(&ptdesc->pt_list);
- atomic_xor_bits(&ptdesc->_refcount, 0x03U << 24);
- memset64((u64 *)table, _PAGE_INVALID, PTRS_PER_PTE);
- memset64((u64 *)table + PTRS_PER_PTE, 0, PTRS_PER_PTE);
- } else {
- /* Return the first 2K fragment of the page */
- atomic_xor_bits(&ptdesc->_refcount, 0x01U << 24);
- memset64((u64 *)table, _PAGE_INVALID, 2 * PTRS_PER_PTE);
- spin_lock_bh(&mm->context.lock);
- list_add(&ptdesc->pt_list, &mm->context.pgtable_list);
- spin_unlock_bh(&mm->context.lock);
- }
+ table = ptdesc_to_virt(ptdesc);
+ __arch_set_page_dat(table, 1);
+ /* pt_list is used by gmap only */
+ INIT_LIST_HEAD(&ptdesc->pt_list);
+ memset64((u64 *)table, _PAGE_INVALID, PTRS_PER_PTE);
+ memset64((u64 *)table + PTRS_PER_PTE, 0, PTRS_PER_PTE);
return table;
}
-static void page_table_release_check(struct page *page, void *table,
- unsigned int half, unsigned int mask)
+static void pagetable_pte_dtor_free(struct ptdesc *ptdesc)
{
- char msg[128];
-
- if (!IS_ENABLED(CONFIG_DEBUG_VM))
- return;
- if (!mask && list_empty(&page->lru))
- return;
- snprintf(msg, sizeof(msg),
- "Invalid pgtable %p release half 0x%02x mask 0x%02x",
- table, half, mask);
- dump_page(page, msg);
-}
-
-static void pte_free_now(struct rcu_head *head)
-{
- struct ptdesc *ptdesc;
-
- ptdesc = container_of(head, struct ptdesc, pt_rcu_head);
pagetable_pte_dtor(ptdesc);
pagetable_free(ptdesc);
}
void page_table_free(struct mm_struct *mm, unsigned long *table)
{
- unsigned int mask, bit, half;
struct ptdesc *ptdesc = virt_to_ptdesc(table);
- if (!mm_alloc_pgste(mm)) {
- /* Free 2K page table fragment of a 4K page */
- bit = ((unsigned long) table & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t));
- spin_lock_bh(&mm->context.lock);
- /*
- * Mark the page for delayed release. The actual release
- * will happen outside of the critical section from this
- * function or from __tlb_remove_table()
- */
- mask = atomic_xor_bits(&ptdesc->_refcount, 0x11U << (bit + 24));
- mask >>= 24;
- if ((mask & 0x03U) && !folio_test_active(ptdesc_folio(ptdesc))) {
- /*
- * Other half is allocated, and neither half has had
- * its free deferred: add page to head of list, to make
- * this freed half available for immediate reuse.
- */
- list_add(&ptdesc->pt_list, &mm->context.pgtable_list);
- } else {
- /* If page is on list, now remove it. */
- list_del_init(&ptdesc->pt_list);
- }
- spin_unlock_bh(&mm->context.lock);
- mask = atomic_xor_bits(&ptdesc->_refcount, 0x10U << (bit + 24));
- mask >>= 24;
- if (mask != 0x00U)
- return;
- half = 0x01U << bit;
- } else {
- half = 0x03U;
- mask = atomic_xor_bits(&ptdesc->_refcount, 0x03U << 24);
- mask >>= 24;
- }
-
- page_table_release_check(ptdesc_page(ptdesc), table, half, mask);
- if (folio_test_clear_active(ptdesc_folio(ptdesc)))
- call_rcu(&ptdesc->pt_rcu_head, pte_free_now);
- else
- pte_free_now(&ptdesc->pt_rcu_head);
+ pagetable_pte_dtor_free(ptdesc);
}
-void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table,
- unsigned long vmaddr)
+void __tlb_remove_table(void *table)
{
- struct mm_struct *mm;
- unsigned int bit, mask;
struct ptdesc *ptdesc = virt_to_ptdesc(table);
+ struct page *page = ptdesc_page(ptdesc);
- mm = tlb->mm;
- if (mm_alloc_pgste(mm)) {
- gmap_unlink(mm, table, vmaddr);
- table = (unsigned long *) ((unsigned long)table | 0x03U);
- tlb_remove_ptdesc(tlb, table);
+ if (compound_order(page) == CRST_ALLOC_ORDER) {
+ /* pmd, pud, or p4d */
+ pagetable_free(ptdesc);
return;
}
- bit = ((unsigned long) table & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t));
- spin_lock_bh(&mm->context.lock);
- /*
- * Mark the page for delayed release. The actual release will happen
- * outside of the critical section from __tlb_remove_table() or from
- * page_table_free()
- */
- mask = atomic_xor_bits(&ptdesc->_refcount, 0x11U << (bit + 24));
- mask >>= 24;
- if ((mask & 0x03U) && !folio_test_active(ptdesc_folio(ptdesc))) {
- /*
- * Other half is allocated, and neither half has had
- * its free deferred: add page to end of list, to make
- * this freed half available for reuse once its pending
- * bit has been cleared by __tlb_remove_table().
- */
- list_add_tail(&ptdesc->pt_list, &mm->context.pgtable_list);
- } else {
- /* If page is on list, now remove it. */
- list_del_init(&ptdesc->pt_list);
- }
- spin_unlock_bh(&mm->context.lock);
- table = (unsigned long *) ((unsigned long) table | (0x01U << bit));
- tlb_remove_table(tlb, table);
+ pagetable_pte_dtor_free(ptdesc);
}
-void __tlb_remove_table(void *_table)
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static void pte_free_now(struct rcu_head *head)
{
- unsigned int mask = (unsigned long) _table & 0x03U, half = mask;
- void *table = (void *)((unsigned long) _table ^ mask);
- struct ptdesc *ptdesc = virt_to_ptdesc(table);
-
- switch (half) {
- case 0x00U: /* pmd, pud, or p4d */
- pagetable_free(ptdesc);
- return;
- case 0x01U: /* lower 2K of a 4K page table */
- case 0x02U: /* higher 2K of a 4K page table */
- mask = atomic_xor_bits(&ptdesc->_refcount, mask << (4 + 24));
- mask >>= 24;
- if (mask != 0x00U)
- return;
- break;
- case 0x03U: /* 4K page table with pgstes */
- mask = atomic_xor_bits(&ptdesc->_refcount, 0x03U << 24);
- mask >>= 24;
- break;
- }
+ struct ptdesc *ptdesc = container_of(head, struct ptdesc, pt_rcu_head);
- page_table_release_check(ptdesc_page(ptdesc), table, half, mask);
- if (folio_test_clear_active(ptdesc_folio(ptdesc)))
- call_rcu(&ptdesc->pt_rcu_head, pte_free_now);
- else
- pte_free_now(&ptdesc->pt_rcu_head);
+ pagetable_pte_dtor_free(ptdesc);
}
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
void pte_free_defer(struct mm_struct *mm, pgtable_t pgtable)
{
- struct page *page;
+ struct ptdesc *ptdesc = virt_to_ptdesc(pgtable);
- page = virt_to_page(pgtable);
- SetPageActive(page);
- page_table_free(mm, (unsigned long *)pgtable);
+ call_rcu(&ptdesc->pt_rcu_head, pte_free_now);
/*
- * page_table_free() does not do the pgste gmap_unlink() which
- * page_table_free_rcu() does: warn us if pgste ever reaches here.
+ * THPs are not allowed for KVM guests. Warn if pgste ever reaches here.
+ * Turn to the generic pte_free_defer() version once gmap is removed.
*/
WARN_ON_ONCE(mm_has_pgste(mm));
}
@@ -488,11 +252,10 @@ static unsigned long *base_crst_alloc(unsigned long val)
unsigned long *table;
struct ptdesc *ptdesc;
- ptdesc = pagetable_alloc(GFP_KERNEL & ~__GFP_HIGHMEM, CRST_ALLOC_ORDER);
+ ptdesc = pagetable_alloc(GFP_KERNEL, CRST_ALLOC_ORDER);
if (!ptdesc)
return NULL;
table = ptdesc_address(ptdesc);
-
crst_table_init(table, val);
return table;
}
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 3bd2ab2a9a34..5cb92941540b 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -756,7 +756,7 @@ void ptep_zap_unused(struct mm_struct *mm, unsigned long addr,
pte_clear(mm, addr, ptep);
}
if (reset)
- pgste_val(pgste) &= ~_PGSTE_GPS_USAGE_MASK;
+ pgste_val(pgste) &= ~(_PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT);
pgste_set_unlock(ptep, pgste);
preempt_enable();
}
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 6957d2ed97bf..186a020857cf 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -12,8 +12,10 @@
#include <linux/hugetlb.h>
#include <linux/slab.h>
#include <linux/sort.h>
+#include <asm/page-states.h>
#include <asm/cacheflush.h>
#include <asm/nospec-branch.h>
+#include <asm/ctlreg.h>
#include <asm/pgalloc.h>
#include <asm/setup.h>
#include <asm/tlbflush.h>
@@ -45,8 +47,10 @@ void *vmem_crst_alloc(unsigned long val)
unsigned long *table;
table = vmem_alloc_pages(CRST_ALLOC_ORDER);
- if (table)
- crst_table_init(table, val);
+ if (!table)
+ return NULL;
+ crst_table_init(table, val);
+ __arch_set_page_dat(table, 1UL << CRST_ALLOC_ORDER);
return table;
}
@@ -62,6 +66,7 @@ pte_t __ref *vmem_pte_alloc(void)
if (!pte)
return NULL;
memset64((u64 *)pte, _PAGE_INVALID, PTRS_PER_PTE);
+ __arch_set_page_dat(pte, 1);
return pte;
}
@@ -498,6 +503,8 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
return ret;
}
+#ifdef CONFIG_MEMORY_HOTPLUG
+
void vmemmap_free(unsigned long start, unsigned long end,
struct vmem_altmap *altmap)
{
@@ -506,6 +513,8 @@ void vmemmap_free(unsigned long start, unsigned long end,
mutex_unlock(&vmem_mutex);
}
+#endif
+
void vmem_remove_mapping(unsigned long start, unsigned long size)
{
mutex_lock(&vmem_mutex);
@@ -659,7 +668,7 @@ void __init vmem_map_init(void)
__set_memory_4k(__va(0), RELOC_HIDE(__va(0), ident_map_size));
}
if (MACHINE_HAS_NX)
- ctl_set_bit(0, 20);
+ system_ctl_set_bit(0, CR0_INSTRUCTION_EXEC_PROTECTION_BIT);
pr_info("Write protected kernel read-only data: %luk\n",
(unsigned long)(__end_rodata - _stext) >> 10);
}
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 2861e3360aff..bf06b7283f0c 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -556,7 +556,7 @@ static void bpf_jit_prologue(struct bpf_jit *jit, struct bpf_prog *fp,
EMIT6_PCREL_RILC(0xc0040000, 0, jit->prologue_plt);
jit->prologue_plt_ret = jit->prg;
- if (fp->aux->func_idx == 0) {
+ if (!bpf_is_subprog(fp)) {
/* Initialize the tail call counter in the main program. */
/* xc STK_OFF_TCCNT(4,%r15),STK_OFF_TCCNT(%r15) */
_EMIT6(0xd703f000 | STK_OFF_TCCNT, 0xf000 | STK_OFF_TCCNT);
@@ -670,15 +670,18 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth)
static int get_probe_mem_regno(const u8 *insn)
{
/*
- * insn must point to llgc, llgh, llgf or lg, which have destination
- * register at the same position.
+ * insn must point to llgc, llgh, llgf, lg, lgb, lgh or lgf, which have
+ * destination register at the same position.
*/
- if (insn[0] != 0xe3) /* common llgc, llgh, llgf and lg prefix */
+ if (insn[0] != 0xe3) /* common prefix */
return -1;
if (insn[5] != 0x90 && /* llgc */
insn[5] != 0x91 && /* llgh */
insn[5] != 0x16 && /* llgf */
- insn[5] != 0x04) /* lg */
+ insn[5] != 0x04 && /* lg */
+ insn[5] != 0x77 && /* lgb */
+ insn[5] != 0x15 && /* lgh */
+ insn[5] != 0x14) /* lgf */
return -1;
return insn[1] >> 4;
}
@@ -776,6 +779,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
int i, bool extra_pass, u32 stack_depth)
{
struct bpf_insn *insn = &fp->insnsi[i];
+ s16 branch_oc_off = insn->off;
u32 dst_reg = insn->dst_reg;
u32 src_reg = insn->src_reg;
int last, insn_count = 1;
@@ -788,22 +792,55 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
int err;
if (BPF_CLASS(insn->code) == BPF_LDX &&
- BPF_MODE(insn->code) == BPF_PROBE_MEM)
+ (BPF_MODE(insn->code) == BPF_PROBE_MEM ||
+ BPF_MODE(insn->code) == BPF_PROBE_MEMSX))
probe_prg = jit->prg;
switch (insn->code) {
/*
* BPF_MOV
*/
- case BPF_ALU | BPF_MOV | BPF_X: /* dst = (u32) src */
- /* llgfr %dst,%src */
- EMIT4(0xb9160000, dst_reg, src_reg);
- if (insn_is_zext(&insn[1]))
- insn_count = 2;
+ case BPF_ALU | BPF_MOV | BPF_X:
+ switch (insn->off) {
+ case 0: /* DST = (u32) SRC */
+ /* llgfr %dst,%src */
+ EMIT4(0xb9160000, dst_reg, src_reg);
+ if (insn_is_zext(&insn[1]))
+ insn_count = 2;
+ break;
+ case 8: /* DST = (u32)(s8) SRC */
+ /* lbr %dst,%src */
+ EMIT4(0xb9260000, dst_reg, src_reg);
+ /* llgfr %dst,%dst */
+ EMIT4(0xb9160000, dst_reg, dst_reg);
+ break;
+ case 16: /* DST = (u32)(s16) SRC */
+ /* lhr %dst,%src */
+ EMIT4(0xb9270000, dst_reg, src_reg);
+ /* llgfr %dst,%dst */
+ EMIT4(0xb9160000, dst_reg, dst_reg);
+ break;
+ }
break;
- case BPF_ALU64 | BPF_MOV | BPF_X: /* dst = src */
- /* lgr %dst,%src */
- EMIT4(0xb9040000, dst_reg, src_reg);
+ case BPF_ALU64 | BPF_MOV | BPF_X:
+ switch (insn->off) {
+ case 0: /* DST = SRC */
+ /* lgr %dst,%src */
+ EMIT4(0xb9040000, dst_reg, src_reg);
+ break;
+ case 8: /* DST = (s8) SRC */
+ /* lgbr %dst,%src */
+ EMIT4(0xb9060000, dst_reg, src_reg);
+ break;
+ case 16: /* DST = (s16) SRC */
+ /* lghr %dst,%src */
+ EMIT4(0xb9070000, dst_reg, src_reg);
+ break;
+ case 32: /* DST = (s32) SRC */
+ /* lgfr %dst,%src */
+ EMIT4(0xb9140000, dst_reg, src_reg);
+ break;
+ }
break;
case BPF_ALU | BPF_MOV | BPF_K: /* dst = (u32) imm */
/* llilf %dst,imm */
@@ -912,66 +949,115 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
/*
* BPF_DIV / BPF_MOD
*/
- case BPF_ALU | BPF_DIV | BPF_X: /* dst = (u32) dst / (u32) src */
- case BPF_ALU | BPF_MOD | BPF_X: /* dst = (u32) dst % (u32) src */
+ case BPF_ALU | BPF_DIV | BPF_X:
+ case BPF_ALU | BPF_MOD | BPF_X:
{
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
- /* lhi %w0,0 */
- EMIT4_IMM(0xa7080000, REG_W0, 0);
- /* lr %w1,%dst */
- EMIT2(0x1800, REG_W1, dst_reg);
- /* dlr %w0,%src */
- EMIT4(0xb9970000, REG_W0, src_reg);
+ switch (off) {
+ case 0: /* dst = (u32) dst {/,%} (u32) src */
+ /* xr %w0,%w0 */
+ EMIT2(0x1700, REG_W0, REG_W0);
+ /* lr %w1,%dst */
+ EMIT2(0x1800, REG_W1, dst_reg);
+ /* dlr %w0,%src */
+ EMIT4(0xb9970000, REG_W0, src_reg);
+ break;
+ case 1: /* dst = (u32) ((s32) dst {/,%} (s32) src) */
+ /* lgfr %r1,%dst */
+ EMIT4(0xb9140000, REG_W1, dst_reg);
+ /* dsgfr %r0,%src */
+ EMIT4(0xb91d0000, REG_W0, src_reg);
+ break;
+ }
/* llgfr %dst,%rc */
EMIT4(0xb9160000, dst_reg, rc_reg);
if (insn_is_zext(&insn[1]))
insn_count = 2;
break;
}
- case BPF_ALU64 | BPF_DIV | BPF_X: /* dst = dst / src */
- case BPF_ALU64 | BPF_MOD | BPF_X: /* dst = dst % src */
+ case BPF_ALU64 | BPF_DIV | BPF_X:
+ case BPF_ALU64 | BPF_MOD | BPF_X:
{
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
- /* lghi %w0,0 */
- EMIT4_IMM(0xa7090000, REG_W0, 0);
- /* lgr %w1,%dst */
- EMIT4(0xb9040000, REG_W1, dst_reg);
- /* dlgr %w0,%dst */
- EMIT4(0xb9870000, REG_W0, src_reg);
+ switch (off) {
+ case 0: /* dst = dst {/,%} src */
+ /* lghi %w0,0 */
+ EMIT4_IMM(0xa7090000, REG_W0, 0);
+ /* lgr %w1,%dst */
+ EMIT4(0xb9040000, REG_W1, dst_reg);
+ /* dlgr %w0,%src */
+ EMIT4(0xb9870000, REG_W0, src_reg);
+ break;
+ case 1: /* dst = (s64) dst {/,%} (s64) src */
+ /* lgr %w1,%dst */
+ EMIT4(0xb9040000, REG_W1, dst_reg);
+ /* dsgr %w0,%src */
+ EMIT4(0xb90d0000, REG_W0, src_reg);
+ break;
+ }
/* lgr %dst,%rc */
EMIT4(0xb9040000, dst_reg, rc_reg);
break;
}
- case BPF_ALU | BPF_DIV | BPF_K: /* dst = (u32) dst / (u32) imm */
- case BPF_ALU | BPF_MOD | BPF_K: /* dst = (u32) dst % (u32) imm */
+ case BPF_ALU | BPF_DIV | BPF_K:
+ case BPF_ALU | BPF_MOD | BPF_K:
{
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
if (imm == 1) {
if (BPF_OP(insn->code) == BPF_MOD)
- /* lhgi %dst,0 */
+ /* lghi %dst,0 */
EMIT4_IMM(0xa7090000, dst_reg, 0);
else
EMIT_ZERO(dst_reg);
break;
}
- /* lhi %w0,0 */
- EMIT4_IMM(0xa7080000, REG_W0, 0);
- /* lr %w1,%dst */
- EMIT2(0x1800, REG_W1, dst_reg);
if (!is_first_pass(jit) && can_use_ldisp_for_lit32(jit)) {
- /* dl %w0,<d(imm)>(%l) */
- EMIT6_DISP_LH(0xe3000000, 0x0097, REG_W0, REG_0, REG_L,
- EMIT_CONST_U32(imm));
+ switch (off) {
+ case 0: /* dst = (u32) dst {/,%} (u32) imm */
+ /* xr %w0,%w0 */
+ EMIT2(0x1700, REG_W0, REG_W0);
+ /* lr %w1,%dst */
+ EMIT2(0x1800, REG_W1, dst_reg);
+ /* dl %w0,<d(imm)>(%l) */
+ EMIT6_DISP_LH(0xe3000000, 0x0097, REG_W0, REG_0,
+ REG_L, EMIT_CONST_U32(imm));
+ break;
+ case 1: /* dst = (s32) dst {/,%} (s32) imm */
+ /* lgfr %r1,%dst */
+ EMIT4(0xb9140000, REG_W1, dst_reg);
+ /* dsgf %r0,<d(imm)>(%l) */
+ EMIT6_DISP_LH(0xe3000000, 0x001d, REG_W0, REG_0,
+ REG_L, EMIT_CONST_U32(imm));
+ break;
+ }
} else {
- /* lgfrl %dst,imm */
- EMIT6_PCREL_RILB(0xc40c0000, dst_reg,
- _EMIT_CONST_U32(imm));
- jit->seen |= SEEN_LITERAL;
- /* dlr %w0,%dst */
- EMIT4(0xb9970000, REG_W0, dst_reg);
+ switch (off) {
+ case 0: /* dst = (u32) dst {/,%} (u32) imm */
+ /* xr %w0,%w0 */
+ EMIT2(0x1700, REG_W0, REG_W0);
+ /* lr %w1,%dst */
+ EMIT2(0x1800, REG_W1, dst_reg);
+ /* lrl %dst,imm */
+ EMIT6_PCREL_RILB(0xc40d0000, dst_reg,
+ _EMIT_CONST_U32(imm));
+ jit->seen |= SEEN_LITERAL;
+ /* dlr %w0,%dst */
+ EMIT4(0xb9970000, REG_W0, dst_reg);
+ break;
+ case 1: /* dst = (s32) dst {/,%} (s32) imm */
+ /* lgfr %w1,%dst */
+ EMIT4(0xb9140000, REG_W1, dst_reg);
+ /* lgfrl %dst,imm */
+ EMIT6_PCREL_RILB(0xc40c0000, dst_reg,
+ _EMIT_CONST_U32(imm));
+ jit->seen |= SEEN_LITERAL;
+ /* dsgr %w0,%dst */
+ EMIT4(0xb90d0000, REG_W0, dst_reg);
+ break;
+ }
}
/* llgfr %dst,%rc */
EMIT4(0xb9160000, dst_reg, rc_reg);
@@ -979,8 +1065,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
insn_count = 2;
break;
}
- case BPF_ALU64 | BPF_DIV | BPF_K: /* dst = dst / imm */
- case BPF_ALU64 | BPF_MOD | BPF_K: /* dst = dst % imm */
+ case BPF_ALU64 | BPF_DIV | BPF_K:
+ case BPF_ALU64 | BPF_MOD | BPF_K:
{
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
@@ -990,21 +1076,50 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
EMIT4_IMM(0xa7090000, dst_reg, 0);
break;
}
- /* lghi %w0,0 */
- EMIT4_IMM(0xa7090000, REG_W0, 0);
- /* lgr %w1,%dst */
- EMIT4(0xb9040000, REG_W1, dst_reg);
if (!is_first_pass(jit) && can_use_ldisp_for_lit64(jit)) {
- /* dlg %w0,<d(imm)>(%l) */
- EMIT6_DISP_LH(0xe3000000, 0x0087, REG_W0, REG_0, REG_L,
- EMIT_CONST_U64(imm));
+ switch (off) {
+ case 0: /* dst = dst {/,%} imm */
+ /* lghi %w0,0 */
+ EMIT4_IMM(0xa7090000, REG_W0, 0);
+ /* lgr %w1,%dst */
+ EMIT4(0xb9040000, REG_W1, dst_reg);
+ /* dlg %w0,<d(imm)>(%l) */
+ EMIT6_DISP_LH(0xe3000000, 0x0087, REG_W0, REG_0,
+ REG_L, EMIT_CONST_U64(imm));
+ break;
+ case 1: /* dst = (s64) dst {/,%} (s64) imm */
+ /* lgr %w1,%dst */
+ EMIT4(0xb9040000, REG_W1, dst_reg);
+ /* dsg %w0,<d(imm)>(%l) */
+ EMIT6_DISP_LH(0xe3000000, 0x000d, REG_W0, REG_0,
+ REG_L, EMIT_CONST_U64(imm));
+ break;
+ }
} else {
- /* lgrl %dst,imm */
- EMIT6_PCREL_RILB(0xc4080000, dst_reg,
- _EMIT_CONST_U64(imm));
- jit->seen |= SEEN_LITERAL;
- /* dlgr %w0,%dst */
- EMIT4(0xb9870000, REG_W0, dst_reg);
+ switch (off) {
+ case 0: /* dst = dst {/,%} imm */
+ /* lghi %w0,0 */
+ EMIT4_IMM(0xa7090000, REG_W0, 0);
+ /* lgr %w1,%dst */
+ EMIT4(0xb9040000, REG_W1, dst_reg);
+ /* lgrl %dst,imm */
+ EMIT6_PCREL_RILB(0xc4080000, dst_reg,
+ _EMIT_CONST_U64(imm));
+ jit->seen |= SEEN_LITERAL;
+ /* dlgr %w0,%dst */
+ EMIT4(0xb9870000, REG_W0, dst_reg);
+ break;
+ case 1: /* dst = (s64) dst {/,%} (s64) imm */
+ /* lgr %w1,%dst */
+ EMIT4(0xb9040000, REG_W1, dst_reg);
+ /* lgrl %dst,imm */
+ EMIT6_PCREL_RILB(0xc4080000, dst_reg,
+ _EMIT_CONST_U64(imm));
+ jit->seen |= SEEN_LITERAL;
+ /* dsgr %w0,%dst */
+ EMIT4(0xb90d0000, REG_W0, dst_reg);
+ break;
+ }
}
/* lgr %dst,%rc */
EMIT4(0xb9040000, dst_reg, rc_reg);
@@ -1217,6 +1332,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
}
break;
case BPF_ALU | BPF_END | BPF_FROM_LE:
+ case BPF_ALU64 | BPF_END | BPF_FROM_LE:
switch (imm) {
case 16: /* dst = (u16) cpu_to_le16(dst) */
/* lrvr %dst,%dst */
@@ -1374,6 +1490,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
if (insn_is_zext(&insn[1]))
insn_count = 2;
break;
+ case BPF_LDX | BPF_MEMSX | BPF_B: /* dst = *(s8 *)(ul) (src + off) */
+ case BPF_LDX | BPF_PROBE_MEMSX | BPF_B:
+ /* lgb %dst,0(off,%src) */
+ EMIT6_DISP_LH(0xe3000000, 0x0077, dst_reg, src_reg, REG_0, off);
+ jit->seen |= SEEN_MEM;
+ break;
case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */
case BPF_LDX | BPF_PROBE_MEM | BPF_H:
/* llgh %dst,0(off,%src) */
@@ -1382,6 +1504,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
if (insn_is_zext(&insn[1]))
insn_count = 2;
break;
+ case BPF_LDX | BPF_MEMSX | BPF_H: /* dst = *(s16 *)(ul) (src + off) */
+ case BPF_LDX | BPF_PROBE_MEMSX | BPF_H:
+ /* lgh %dst,0(off,%src) */
+ EMIT6_DISP_LH(0xe3000000, 0x0015, dst_reg, src_reg, REG_0, off);
+ jit->seen |= SEEN_MEM;
+ break;
case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */
case BPF_LDX | BPF_PROBE_MEM | BPF_W:
/* llgf %dst,off(%src) */
@@ -1390,6 +1518,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
if (insn_is_zext(&insn[1]))
insn_count = 2;
break;
+ case BPF_LDX | BPF_MEMSX | BPF_W: /* dst = *(s32 *)(ul) (src + off) */
+ case BPF_LDX | BPF_PROBE_MEMSX | BPF_W:
+ /* lgf %dst,off(%src) */
+ jit->seen |= SEEN_MEM;
+ EMIT6_DISP_LH(0xe3000000, 0x0014, dst_reg, src_reg, REG_0, off);
+ break;
case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */
case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
/* lg %dst,0(off,%src) */
@@ -1570,6 +1704,9 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
* instruction itself (loop) and for BPF with offset 0 we
* branch to the instruction behind the branch.
*/
+ case BPF_JMP32 | BPF_JA: /* if (true) */
+ branch_oc_off = imm;
+ fallthrough;
case BPF_JMP | BPF_JA: /* if (true) */
mask = 0xf000; /* j */
goto branch_oc;
@@ -1738,14 +1875,16 @@ branch_xu:
break;
branch_oc:
if (!is_first_pass(jit) &&
- can_use_rel(jit, addrs[i + off + 1])) {
+ can_use_rel(jit, addrs[i + branch_oc_off + 1])) {
/* brc mask,off */
EMIT4_PCREL_RIC(0xa7040000,
- mask >> 12, addrs[i + off + 1]);
+ mask >> 12,
+ addrs[i + branch_oc_off + 1]);
} else {
/* brcl mask,off */
EMIT6_PCREL_RILC(0xc0040000,
- mask >> 12, addrs[i + off + 1]);
+ mask >> 12,
+ addrs[i + branch_oc_off + 1]);
}
break;
}
@@ -2066,6 +2205,7 @@ struct bpf_tramp_jit {
* func_addr's original caller
*/
int stack_size; /* Trampoline stack size */
+ int backchain_off; /* Offset of backchain */
int stack_args_off; /* Offset of stack arguments for calling
* func_addr, has to be at the top
*/
@@ -2086,9 +2226,10 @@ struct bpf_tramp_jit {
* for __bpf_prog_enter() return value and
* func_addr respectively
*/
- int r14_off; /* Offset of saved %r14 */
int run_ctx_off; /* Offset of struct bpf_tramp_run_ctx */
int tccnt_off; /* Offset of saved tailcall counter */
+ int r14_off; /* Offset of saved %r14, has to be at the
+ * bottom */
int do_fexit; /* do_fexit: label */
};
@@ -2247,8 +2388,12 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
* Calculate the stack layout.
*/
- /* Reserve STACK_FRAME_OVERHEAD bytes for the callees. */
+ /*
+ * Allocate STACK_FRAME_OVERHEAD bytes for the callees. As the s390x
+ * ABI requires, put our backchain at the end of the allocated memory.
+ */
tjit->stack_size = STACK_FRAME_OVERHEAD;
+ tjit->backchain_off = tjit->stack_size - sizeof(u64);
tjit->stack_args_off = alloc_stack(tjit, nr_stack_args * sizeof(u64));
tjit->reg_args_off = alloc_stack(tjit, nr_reg_args * sizeof(u64));
tjit->ip_off = alloc_stack(tjit, sizeof(u64));
@@ -2256,16 +2401,25 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
tjit->bpf_args_off = alloc_stack(tjit, nr_bpf_args * sizeof(u64));
tjit->retval_off = alloc_stack(tjit, sizeof(u64));
tjit->r7_r8_off = alloc_stack(tjit, 2 * sizeof(u64));
- tjit->r14_off = alloc_stack(tjit, sizeof(u64));
tjit->run_ctx_off = alloc_stack(tjit,
sizeof(struct bpf_tramp_run_ctx));
tjit->tccnt_off = alloc_stack(tjit, sizeof(u64));
- /* The caller has already reserved STACK_FRAME_OVERHEAD bytes. */
- tjit->stack_size -= STACK_FRAME_OVERHEAD;
+ tjit->r14_off = alloc_stack(tjit, sizeof(u64) * 2);
+ /*
+ * In accordance with the s390x ABI, the caller has allocated
+ * STACK_FRAME_OVERHEAD bytes for us. 8 of them contain the caller's
+ * backchain, and the rest we can use.
+ */
+ tjit->stack_size -= STACK_FRAME_OVERHEAD - sizeof(u64);
tjit->orig_stack_args_off = tjit->stack_size + STACK_FRAME_OVERHEAD;
+ /* lgr %r1,%r15 */
+ EMIT4(0xb9040000, REG_1, REG_15);
/* aghi %r15,-stack_size */
EMIT4_IMM(0xa70b0000, REG_15, -tjit->stack_size);
+ /* stg %r1,backchain_off(%r15) */
+ EMIT6_DISP_LH(0xe3000000, 0x0024, REG_1, REG_0, REG_15,
+ tjit->backchain_off);
/* mvc tccnt_off(4,%r15),stack_size+STK_OFF_TCCNT(%r15) */
_EMIT6(0xd203f000 | tjit->tccnt_off,
0xf000 | (tjit->stack_size + STK_OFF_TCCNT));
diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
index 5ae31ca9dd44..0547a10406e7 100644
--- a/arch/s390/pci/Makefile
+++ b/arch/s390/pci/Makefile
@@ -3,7 +3,7 @@
# Makefile for the s390 PCI subsystem.
#
-obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_dma.o pci_clp.o pci_sysfs.o \
+obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_clp.o pci_sysfs.o \
pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
pci_bus.o pci_kvm_hook.o
obj-$(CONFIG_PCI_IOV) += pci_iov.o
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index d34d5813d006..676ac74026a8 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -124,7 +124,11 @@ int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas,
WARN_ON_ONCE(iota & 0x3fff);
fib.pba = base;
- fib.pal = limit;
+ /* Work around off by one in ISM virt device */
+ if (zdev->pft == PCI_FUNC_TYPE_ISM && limit > base)
+ fib.pal = limit + (1 << 12);
+ else
+ fib.pal = limit;
fib.iota = iota | ZPCI_IOTA_RTTO_FLAG;
fib.gd = zdev->gisa;
cc = zpci_mod_fc(req, &fib, status);
@@ -153,6 +157,7 @@ int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas)
int zpci_fmb_enable_device(struct zpci_dev *zdev)
{
u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_SET_MEASURE);
+ struct zpci_iommu_ctrs *ctrs;
struct zpci_fib fib = {0};
u8 cc, status;
@@ -165,9 +170,15 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev)
WARN_ON((u64) zdev->fmb & 0xf);
/* reset software counters */
- atomic64_set(&zdev->allocated_pages, 0);
- atomic64_set(&zdev->mapped_pages, 0);
- atomic64_set(&zdev->unmapped_pages, 0);
+ ctrs = zpci_get_iommu_ctrs(zdev);
+ if (ctrs) {
+ atomic64_set(&ctrs->mapped_pages, 0);
+ atomic64_set(&ctrs->unmapped_pages, 0);
+ atomic64_set(&ctrs->global_rpcits, 0);
+ atomic64_set(&ctrs->sync_map_rpcits, 0);
+ atomic64_set(&ctrs->sync_rpcits, 0);
+ }
+
fib.fmb_addr = virt_to_phys(zdev->fmb);
fib.gd = zdev->gisa;
@@ -582,7 +593,6 @@ int pcibios_device_add(struct pci_dev *pdev)
pdev->no_vf_scan = 1;
pdev->dev.groups = zpci_attr_groups;
- pdev->dev.dma_ops = &s390_pci_dma_ops;
zpci_map_resources(pdev);
for (i = 0; i < PCI_STD_NUM_BARS; i++) {
@@ -756,8 +766,6 @@ int zpci_hot_reset_device(struct zpci_dev *zdev)
if (zdev->dma_table)
rc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
virt_to_phys(zdev->dma_table), &status);
- else
- rc = zpci_dma_init_device(zdev);
if (rc) {
zpci_disable_device(zdev);
return rc;
@@ -865,11 +873,6 @@ int zpci_deconfigure_device(struct zpci_dev *zdev)
if (zdev->zbus->bus)
zpci_bus_remove_device(zdev, false);
- if (zdev->dma_table) {
- rc = zpci_dma_exit_device(zdev);
- if (rc)
- return rc;
- }
if (zdev_enabled(zdev)) {
rc = zpci_disable_device(zdev);
if (rc)
@@ -918,8 +921,6 @@ void zpci_release_device(struct kref *kref)
if (zdev->zbus->bus)
zpci_bus_remove_device(zdev, false);
- if (zdev->dma_table)
- zpci_dma_exit_device(zdev);
if (zdev_enabled(zdev))
zpci_disable_device(zdev);
@@ -1094,7 +1095,7 @@ static int __init pci_base_init(void)
if (MACHINE_HAS_PCI_MIO) {
static_branch_enable(&have_mio);
- ctl_set_bit(2, 5);
+ system_ctl_set_bit(2, CR2_MIO_ADDRESSING_BIT);
}
rc = zpci_debug_init();
@@ -1109,10 +1110,6 @@ static int __init pci_base_init(void)
if (rc)
goto out_irq;
- rc = zpci_dma_init();
- if (rc)
- goto out_dma;
-
rc = clp_scan_pci_devices();
if (rc)
goto out_find;
@@ -1122,8 +1119,6 @@ static int __init pci_base_init(void)
return 0;
out_find:
- zpci_dma_exit();
-out_dma:
zpci_irq_exit();
out_irq:
zpci_mem_exit();
diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c
index 32245b970a0c..daa5d7450c7d 100644
--- a/arch/s390/pci/pci_bus.c
+++ b/arch/s390/pci/pci_bus.c
@@ -47,11 +47,6 @@ static int zpci_bus_prepare_device(struct zpci_dev *zdev)
rc = zpci_enable_device(zdev);
if (rc)
return rc;
- rc = zpci_dma_init_device(zdev);
- if (rc) {
- zpci_disable_device(zdev);
- return rc;
- }
}
if (!zdev->has_resources) {
diff --git a/arch/s390/pci/pci_debug.c b/arch/s390/pci/pci_debug.c
index ca6bd98eec13..6dde2263c79d 100644
--- a/arch/s390/pci/pci_debug.c
+++ b/arch/s390/pci/pci_debug.c
@@ -53,9 +53,11 @@ static char *pci_fmt3_names[] = {
};
static char *pci_sw_names[] = {
- "Allocated pages",
"Mapped pages",
"Unmapped pages",
+ "Global RPCITs",
+ "Sync Map RPCITs",
+ "Sync RPCITs",
};
static void pci_fmb_show(struct seq_file *m, char *name[], int length,
@@ -69,10 +71,14 @@ static void pci_fmb_show(struct seq_file *m, char *name[], int length,
static void pci_sw_counter_show(struct seq_file *m)
{
- struct zpci_dev *zdev = m->private;
- atomic64_t *counter = &zdev->allocated_pages;
+ struct zpci_iommu_ctrs *ctrs = zpci_get_iommu_ctrs(m->private);
+ atomic64_t *counter;
int i;
+ if (!ctrs)
+ return;
+
+ counter = &ctrs->mapped_pages;
for (i = 0; i < ARRAY_SIZE(pci_sw_names); i++, counter++)
seq_printf(m, "%26s:\t%llu\n", pci_sw_names[i],
atomic64_read(counter));
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
deleted file mode 100644
index 2d9b01d7ca4c..000000000000
--- a/arch/s390/pci/pci_dma.c
+++ /dev/null
@@ -1,735 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright IBM Corp. 2012
- *
- * Author(s):
- * Jan Glauber <jang@linux.vnet.ibm.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <linux/iommu-helper.h>
-#include <linux/dma-map-ops.h>
-#include <linux/vmalloc.h>
-#include <linux/pci.h>
-#include <asm/pci_dma.h>
-
-static struct kmem_cache *dma_region_table_cache;
-static struct kmem_cache *dma_page_table_cache;
-static int s390_iommu_strict;
-static u64 s390_iommu_aperture;
-static u32 s390_iommu_aperture_factor = 1;
-
-static int zpci_refresh_global(struct zpci_dev *zdev)
-{
- return zpci_refresh_trans((u64) zdev->fh << 32, zdev->start_dma,
- zdev->iommu_pages * PAGE_SIZE);
-}
-
-unsigned long *dma_alloc_cpu_table(gfp_t gfp)
-{
- unsigned long *table, *entry;
-
- table = kmem_cache_alloc(dma_region_table_cache, gfp);
- if (!table)
- return NULL;
-
- for (entry = table; entry < table + ZPCI_TABLE_ENTRIES; entry++)
- *entry = ZPCI_TABLE_INVALID;
- return table;
-}
-
-static void dma_free_cpu_table(void *table)
-{
- kmem_cache_free(dma_region_table_cache, table);
-}
-
-static unsigned long *dma_alloc_page_table(gfp_t gfp)
-{
- unsigned long *table, *entry;
-
- table = kmem_cache_alloc(dma_page_table_cache, gfp);
- if (!table)
- return NULL;
-
- for (entry = table; entry < table + ZPCI_PT_ENTRIES; entry++)
- *entry = ZPCI_PTE_INVALID;
- return table;
-}
-
-static void dma_free_page_table(void *table)
-{
- kmem_cache_free(dma_page_table_cache, table);
-}
-
-static unsigned long *dma_get_seg_table_origin(unsigned long *rtep, gfp_t gfp)
-{
- unsigned long old_rte, rte;
- unsigned long *sto;
-
- rte = READ_ONCE(*rtep);
- if (reg_entry_isvalid(rte)) {
- sto = get_rt_sto(rte);
- } else {
- sto = dma_alloc_cpu_table(gfp);
- if (!sto)
- return NULL;
-
- set_rt_sto(&rte, virt_to_phys(sto));
- validate_rt_entry(&rte);
- entry_clr_protected(&rte);
-
- old_rte = cmpxchg(rtep, ZPCI_TABLE_INVALID, rte);
- if (old_rte != ZPCI_TABLE_INVALID) {
- /* Somone else was faster, use theirs */
- dma_free_cpu_table(sto);
- sto = get_rt_sto(old_rte);
- }
- }
- return sto;
-}
-
-static unsigned long *dma_get_page_table_origin(unsigned long *step, gfp_t gfp)
-{
- unsigned long old_ste, ste;
- unsigned long *pto;
-
- ste = READ_ONCE(*step);
- if (reg_entry_isvalid(ste)) {
- pto = get_st_pto(ste);
- } else {
- pto = dma_alloc_page_table(gfp);
- if (!pto)
- return NULL;
- set_st_pto(&ste, virt_to_phys(pto));
- validate_st_entry(&ste);
- entry_clr_protected(&ste);
-
- old_ste = cmpxchg(step, ZPCI_TABLE_INVALID, ste);
- if (old_ste != ZPCI_TABLE_INVALID) {
- /* Somone else was faster, use theirs */
- dma_free_page_table(pto);
- pto = get_st_pto(old_ste);
- }
- }
- return pto;
-}
-
-unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr,
- gfp_t gfp)
-{
- unsigned long *sto, *pto;
- unsigned int rtx, sx, px;
-
- rtx = calc_rtx(dma_addr);
- sto = dma_get_seg_table_origin(&rto[rtx], gfp);
- if (!sto)
- return NULL;
-
- sx = calc_sx(dma_addr);
- pto = dma_get_page_table_origin(&sto[sx], gfp);
- if (!pto)
- return NULL;
-
- px = calc_px(dma_addr);
- return &pto[px];
-}
-
-void dma_update_cpu_trans(unsigned long *ptep, phys_addr_t page_addr, int flags)
-{
- unsigned long pte;
-
- pte = READ_ONCE(*ptep);
- if (flags & ZPCI_PTE_INVALID) {
- invalidate_pt_entry(&pte);
- } else {
- set_pt_pfaa(&pte, page_addr);
- validate_pt_entry(&pte);
- }
-
- if (flags & ZPCI_TABLE_PROTECTED)
- entry_set_protected(&pte);
- else
- entry_clr_protected(&pte);
-
- xchg(ptep, pte);
-}
-
-static int __dma_update_trans(struct zpci_dev *zdev, phys_addr_t pa,
- dma_addr_t dma_addr, size_t size, int flags)
-{
- unsigned int nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
- phys_addr_t page_addr = (pa & PAGE_MASK);
- unsigned long *entry;
- int i, rc = 0;
-
- if (!nr_pages)
- return -EINVAL;
-
- if (!zdev->dma_table)
- return -EINVAL;
-
- for (i = 0; i < nr_pages; i++) {
- entry = dma_walk_cpu_trans(zdev->dma_table, dma_addr,
- GFP_ATOMIC);
- if (!entry) {
- rc = -ENOMEM;
- goto undo_cpu_trans;
- }
- dma_update_cpu_trans(entry, page_addr, flags);
- page_addr += PAGE_SIZE;
- dma_addr += PAGE_SIZE;
- }
-
-undo_cpu_trans:
- if (rc && ((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID)) {
- flags = ZPCI_PTE_INVALID;
- while (i-- > 0) {
- page_addr -= PAGE_SIZE;
- dma_addr -= PAGE_SIZE;
- entry = dma_walk_cpu_trans(zdev->dma_table, dma_addr,
- GFP_ATOMIC);
- if (!entry)
- break;
- dma_update_cpu_trans(entry, page_addr, flags);
- }
- }
- return rc;
-}
-
-static int __dma_purge_tlb(struct zpci_dev *zdev, dma_addr_t dma_addr,
- size_t size, int flags)
-{
- unsigned long irqflags;
- int ret;
-
- /*
- * With zdev->tlb_refresh == 0, rpcit is not required to establish new
- * translations when previously invalid translation-table entries are
- * validated. With lazy unmap, rpcit is skipped for previously valid
- * entries, but a global rpcit is then required before any address can
- * be re-used, i.e. after each iommu bitmap wrap-around.
- */
- if ((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID) {
- if (!zdev->tlb_refresh)
- return 0;
- } else {
- if (!s390_iommu_strict)
- return 0;
- }
-
- ret = zpci_refresh_trans((u64) zdev->fh << 32, dma_addr,
- PAGE_ALIGN(size));
- if (ret == -ENOMEM && !s390_iommu_strict) {
- /* enable the hypervisor to free some resources */
- if (zpci_refresh_global(zdev))
- goto out;
-
- spin_lock_irqsave(&zdev->iommu_bitmap_lock, irqflags);
- bitmap_andnot(zdev->iommu_bitmap, zdev->iommu_bitmap,
- zdev->lazy_bitmap, zdev->iommu_pages);
- bitmap_zero(zdev->lazy_bitmap, zdev->iommu_pages);
- spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, irqflags);
- ret = 0;
- }
-out:
- return ret;
-}
-
-static int dma_update_trans(struct zpci_dev *zdev, phys_addr_t pa,
- dma_addr_t dma_addr, size_t size, int flags)
-{
- int rc;
-
- rc = __dma_update_trans(zdev, pa, dma_addr, size, flags);
- if (rc)
- return rc;
-
- rc = __dma_purge_tlb(zdev, dma_addr, size, flags);
- if (rc && ((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID))
- __dma_update_trans(zdev, pa, dma_addr, size, ZPCI_PTE_INVALID);
-
- return rc;
-}
-
-void dma_free_seg_table(unsigned long entry)
-{
- unsigned long *sto = get_rt_sto(entry);
- int sx;
-
- for (sx = 0; sx < ZPCI_TABLE_ENTRIES; sx++)
- if (reg_entry_isvalid(sto[sx]))
- dma_free_page_table(get_st_pto(sto[sx]));
-
- dma_free_cpu_table(sto);
-}
-
-void dma_cleanup_tables(unsigned long *table)
-{
- int rtx;
-
- if (!table)
- return;
-
- for (rtx = 0; rtx < ZPCI_TABLE_ENTRIES; rtx++)
- if (reg_entry_isvalid(table[rtx]))
- dma_free_seg_table(table[rtx]);
-
- dma_free_cpu_table(table);
-}
-
-static unsigned long __dma_alloc_iommu(struct device *dev,
- unsigned long start, int size)
-{
- struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
-
- return iommu_area_alloc(zdev->iommu_bitmap, zdev->iommu_pages,
- start, size, zdev->start_dma >> PAGE_SHIFT,
- dma_get_seg_boundary_nr_pages(dev, PAGE_SHIFT),
- 0);
-}
-
-static dma_addr_t dma_alloc_address(struct device *dev, int size)
-{
- struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
- unsigned long offset, flags;
-
- spin_lock_irqsave(&zdev->iommu_bitmap_lock, flags);
- offset = __dma_alloc_iommu(dev, zdev->next_bit, size);
- if (offset == -1) {
- if (!s390_iommu_strict) {
- /* global flush before DMA addresses are reused */
- if (zpci_refresh_global(zdev))
- goto out_error;
-
- bitmap_andnot(zdev->iommu_bitmap, zdev->iommu_bitmap,
- zdev->lazy_bitmap, zdev->iommu_pages);
- bitmap_zero(zdev->lazy_bitmap, zdev->iommu_pages);
- }
- /* wrap-around */
- offset = __dma_alloc_iommu(dev, 0, size);
- if (offset == -1)
- goto out_error;
- }
- zdev->next_bit = offset + size;
- spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, flags);
-
- return zdev->start_dma + offset * PAGE_SIZE;
-
-out_error:
- spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, flags);
- return DMA_MAPPING_ERROR;
-}
-
-static void dma_free_address(struct device *dev, dma_addr_t dma_addr, int size)
-{
- struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
- unsigned long flags, offset;
-
- offset = (dma_addr - zdev->start_dma) >> PAGE_SHIFT;
-
- spin_lock_irqsave(&zdev->iommu_bitmap_lock, flags);
- if (!zdev->iommu_bitmap)
- goto out;
-
- if (s390_iommu_strict)
- bitmap_clear(zdev->iommu_bitmap, offset, size);
- else
- bitmap_set(zdev->lazy_bitmap, offset, size);
-
-out:
- spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, flags);
-}
-
-static inline void zpci_err_dma(unsigned long rc, unsigned long addr)
-{
- struct {
- unsigned long rc;
- unsigned long addr;
- } __packed data = {rc, addr};
-
- zpci_err_hex(&data, sizeof(data));
-}
-
-static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction direction,
- unsigned long attrs)
-{
- struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
- unsigned long pa = page_to_phys(page) + offset;
- int flags = ZPCI_PTE_VALID;
- unsigned long nr_pages;
- dma_addr_t dma_addr;
- int ret;
-
- /* This rounds up number of pages based on size and offset */
- nr_pages = iommu_num_pages(pa, size, PAGE_SIZE);
- dma_addr = dma_alloc_address(dev, nr_pages);
- if (dma_addr == DMA_MAPPING_ERROR) {
- ret = -ENOSPC;
- goto out_err;
- }
-
- /* Use rounded up size */
- size = nr_pages * PAGE_SIZE;
-
- if (direction == DMA_NONE || direction == DMA_TO_DEVICE)
- flags |= ZPCI_TABLE_PROTECTED;
-
- ret = dma_update_trans(zdev, pa, dma_addr, size, flags);
- if (ret)
- goto out_free;
-
- atomic64_add(nr_pages, &zdev->mapped_pages);
- return dma_addr + (offset & ~PAGE_MASK);
-
-out_free:
- dma_free_address(dev, dma_addr, nr_pages);
-out_err:
- zpci_err("map error:\n");
- zpci_err_dma(ret, pa);
- return DMA_MAPPING_ERROR;
-}
-
-static void s390_dma_unmap_pages(struct device *dev, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction direction,
- unsigned long attrs)
-{
- struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
- int npages, ret;
-
- npages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
- dma_addr = dma_addr & PAGE_MASK;
- ret = dma_update_trans(zdev, 0, dma_addr, npages * PAGE_SIZE,
- ZPCI_PTE_INVALID);
- if (ret) {
- zpci_err("unmap error:\n");
- zpci_err_dma(ret, dma_addr);
- return;
- }
-
- atomic64_add(npages, &zdev->unmapped_pages);
- dma_free_address(dev, dma_addr, npages);
-}
-
-static void *s390_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag,
- unsigned long attrs)
-{
- struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
- struct page *page;
- phys_addr_t pa;
- dma_addr_t map;
-
- size = PAGE_ALIGN(size);
- page = alloc_pages(flag | __GFP_ZERO, get_order(size));
- if (!page)
- return NULL;
-
- pa = page_to_phys(page);
- map = s390_dma_map_pages(dev, page, 0, size, DMA_BIDIRECTIONAL, 0);
- if (dma_mapping_error(dev, map)) {
- __free_pages(page, get_order(size));
- return NULL;
- }
-
- atomic64_add(size / PAGE_SIZE, &zdev->allocated_pages);
- if (dma_handle)
- *dma_handle = map;
- return phys_to_virt(pa);
-}
-
-static void s390_dma_free(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle,
- unsigned long attrs)
-{
- struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
-
- size = PAGE_ALIGN(size);
- atomic64_sub(size / PAGE_SIZE, &zdev->allocated_pages);
- s390_dma_unmap_pages(dev, dma_handle, size, DMA_BIDIRECTIONAL, 0);
- free_pages((unsigned long)vaddr, get_order(size));
-}
-
-/* Map a segment into a contiguous dma address area */
-static int __s390_dma_map_sg(struct device *dev, struct scatterlist *sg,
- size_t size, dma_addr_t *handle,
- enum dma_data_direction dir)
-{
- unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
- struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
- dma_addr_t dma_addr_base, dma_addr;
- int flags = ZPCI_PTE_VALID;
- struct scatterlist *s;
- phys_addr_t pa = 0;
- int ret;
-
- dma_addr_base = dma_alloc_address(dev, nr_pages);
- if (dma_addr_base == DMA_MAPPING_ERROR)
- return -ENOMEM;
-
- dma_addr = dma_addr_base;
- if (dir == DMA_NONE || dir == DMA_TO_DEVICE)
- flags |= ZPCI_TABLE_PROTECTED;
-
- for (s = sg; dma_addr < dma_addr_base + size; s = sg_next(s)) {
- pa = page_to_phys(sg_page(s));
- ret = __dma_update_trans(zdev, pa, dma_addr,
- s->offset + s->length, flags);
- if (ret)
- goto unmap;
-
- dma_addr += s->offset + s->length;
- }
- ret = __dma_purge_tlb(zdev, dma_addr_base, size, flags);
- if (ret)
- goto unmap;
-
- *handle = dma_addr_base;
- atomic64_add(nr_pages, &zdev->mapped_pages);
-
- return ret;
-
-unmap:
- dma_update_trans(zdev, 0, dma_addr_base, dma_addr - dma_addr_base,
- ZPCI_PTE_INVALID);
- dma_free_address(dev, dma_addr_base, nr_pages);
- zpci_err("map error:\n");
- zpci_err_dma(ret, pa);
- return ret;
-}
-
-static int s390_dma_map_sg(struct device *dev, struct scatterlist *sg,
- int nr_elements, enum dma_data_direction dir,
- unsigned long attrs)
-{
- struct scatterlist *s = sg, *start = sg, *dma = sg;
- unsigned int max = dma_get_max_seg_size(dev);
- unsigned int size = s->offset + s->length;
- unsigned int offset = s->offset;
- int count = 0, i, ret;
-
- for (i = 1; i < nr_elements; i++) {
- s = sg_next(s);
-
- s->dma_length = 0;
-
- if (s->offset || (size & ~PAGE_MASK) ||
- size + s->length > max) {
- ret = __s390_dma_map_sg(dev, start, size,
- &dma->dma_address, dir);
- if (ret)
- goto unmap;
-
- dma->dma_address += offset;
- dma->dma_length = size - offset;
-
- size = offset = s->offset;
- start = s;
- dma = sg_next(dma);
- count++;
- }
- size += s->length;
- }
- ret = __s390_dma_map_sg(dev, start, size, &dma->dma_address, dir);
- if (ret)
- goto unmap;
-
- dma->dma_address += offset;
- dma->dma_length = size - offset;
-
- return count + 1;
-unmap:
- for_each_sg(sg, s, count, i)
- s390_dma_unmap_pages(dev, sg_dma_address(s), sg_dma_len(s),
- dir, attrs);
-
- return ret;
-}
-
-static void s390_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
- int nr_elements, enum dma_data_direction dir,
- unsigned long attrs)
-{
- struct scatterlist *s;
- int i;
-
- for_each_sg(sg, s, nr_elements, i) {
- if (s->dma_length)
- s390_dma_unmap_pages(dev, s->dma_address, s->dma_length,
- dir, attrs);
- s->dma_address = 0;
- s->dma_length = 0;
- }
-}
-
-int zpci_dma_init_device(struct zpci_dev *zdev)
-{
- u8 status;
- int rc;
-
- /*
- * At this point, if the device is part of an IOMMU domain, this would
- * be a strong hint towards a bug in the IOMMU API (common) code and/or
- * simultaneous access via IOMMU and DMA API. So let's issue a warning.
- */
- WARN_ON(zdev->s390_domain);
-
- spin_lock_init(&zdev->iommu_bitmap_lock);
-
- zdev->dma_table = dma_alloc_cpu_table(GFP_KERNEL);
- if (!zdev->dma_table) {
- rc = -ENOMEM;
- goto out;
- }
-
- /*
- * Restrict the iommu bitmap size to the minimum of the following:
- * - s390_iommu_aperture which defaults to high_memory
- * - 3-level pagetable address limit minus start_dma offset
- * - DMA address range allowed by the hardware (clp query pci fn)
- *
- * Also set zdev->end_dma to the actual end address of the usable
- * range, instead of the theoretical maximum as reported by hardware.
- *
- * This limits the number of concurrently usable DMA mappings since
- * for each DMA mapped memory address we need a DMA address including
- * extra DMA addresses for multiple mappings of the same memory address.
- */
- zdev->start_dma = PAGE_ALIGN(zdev->start_dma);
- zdev->iommu_size = min3(s390_iommu_aperture,
- ZPCI_TABLE_SIZE_RT - zdev->start_dma,
- zdev->end_dma - zdev->start_dma + 1);
- zdev->end_dma = zdev->start_dma + zdev->iommu_size - 1;
- zdev->iommu_pages = zdev->iommu_size >> PAGE_SHIFT;
- zdev->iommu_bitmap = vzalloc(zdev->iommu_pages / 8);
- if (!zdev->iommu_bitmap) {
- rc = -ENOMEM;
- goto free_dma_table;
- }
- if (!s390_iommu_strict) {
- zdev->lazy_bitmap = vzalloc(zdev->iommu_pages / 8);
- if (!zdev->lazy_bitmap) {
- rc = -ENOMEM;
- goto free_bitmap;
- }
-
- }
- if (zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
- virt_to_phys(zdev->dma_table), &status)) {
- rc = -EIO;
- goto free_bitmap;
- }
-
- return 0;
-free_bitmap:
- vfree(zdev->iommu_bitmap);
- zdev->iommu_bitmap = NULL;
- vfree(zdev->lazy_bitmap);
- zdev->lazy_bitmap = NULL;
-free_dma_table:
- dma_free_cpu_table(zdev->dma_table);
- zdev->dma_table = NULL;
-out:
- return rc;
-}
-
-int zpci_dma_exit_device(struct zpci_dev *zdev)
-{
- int cc = 0;
-
- /*
- * At this point, if the device is part of an IOMMU domain, this would
- * be a strong hint towards a bug in the IOMMU API (common) code and/or
- * simultaneous access via IOMMU and DMA API. So let's issue a warning.
- */
- WARN_ON(zdev->s390_domain);
- if (zdev_enabled(zdev))
- cc = zpci_unregister_ioat(zdev, 0);
- /*
- * cc == 3 indicates the function is gone already. This can happen
- * if the function was deconfigured/disabled suddenly and we have not
- * received a new handle yet.
- */
- if (cc && cc != 3)
- return -EIO;
-
- dma_cleanup_tables(zdev->dma_table);
- zdev->dma_table = NULL;
- vfree(zdev->iommu_bitmap);
- zdev->iommu_bitmap = NULL;
- vfree(zdev->lazy_bitmap);
- zdev->lazy_bitmap = NULL;
- zdev->next_bit = 0;
- return 0;
-}
-
-static int __init dma_alloc_cpu_table_caches(void)
-{
- dma_region_table_cache = kmem_cache_create("PCI_DMA_region_tables",
- ZPCI_TABLE_SIZE, ZPCI_TABLE_ALIGN,
- 0, NULL);
- if (!dma_region_table_cache)
- return -ENOMEM;
-
- dma_page_table_cache = kmem_cache_create("PCI_DMA_page_tables",
- ZPCI_PT_SIZE, ZPCI_PT_ALIGN,
- 0, NULL);
- if (!dma_page_table_cache) {
- kmem_cache_destroy(dma_region_table_cache);
- return -ENOMEM;
- }
- return 0;
-}
-
-int __init zpci_dma_init(void)
-{
- s390_iommu_aperture = (u64)virt_to_phys(high_memory);
- if (!s390_iommu_aperture_factor)
- s390_iommu_aperture = ULONG_MAX;
- else
- s390_iommu_aperture *= s390_iommu_aperture_factor;
-
- return dma_alloc_cpu_table_caches();
-}
-
-void zpci_dma_exit(void)
-{
- kmem_cache_destroy(dma_page_table_cache);
- kmem_cache_destroy(dma_region_table_cache);
-}
-
-const struct dma_map_ops s390_pci_dma_ops = {
- .alloc = s390_dma_alloc,
- .free = s390_dma_free,
- .map_sg = s390_dma_map_sg,
- .unmap_sg = s390_dma_unmap_sg,
- .map_page = s390_dma_map_pages,
- .unmap_page = s390_dma_unmap_pages,
- .mmap = dma_common_mmap,
- .get_sgtable = dma_common_get_sgtable,
- .alloc_pages = dma_common_alloc_pages,
- .free_pages = dma_common_free_pages,
- /* dma_supported is unconditionally true without a callback */
-};
-EXPORT_SYMBOL_GPL(s390_pci_dma_ops);
-
-static int __init s390_iommu_setup(char *str)
-{
- if (!strcmp(str, "strict"))
- s390_iommu_strict = 1;
- return 1;
-}
-
-__setup("s390_iommu=", s390_iommu_setup);
-
-static int __init s390_iommu_aperture_setup(char *str)
-{
- if (kstrtou32(str, 10, &s390_iommu_aperture_factor))
- s390_iommu_aperture_factor = 1;
- return 1;
-}
-
-__setup("s390_iommu_aperture=", s390_iommu_aperture_setup);
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
index b9324ca2eb94..4d9773ef9e0a 100644
--- a/arch/s390/pci/pci_event.c
+++ b/arch/s390/pci/pci_event.c
@@ -59,9 +59,16 @@ static inline bool ers_result_indicates_abort(pci_ers_result_t ers_res)
}
}
-static bool is_passed_through(struct zpci_dev *zdev)
+static bool is_passed_through(struct pci_dev *pdev)
{
- return zdev->s390_domain;
+ struct zpci_dev *zdev = to_zpci(pdev);
+ bool ret;
+
+ mutex_lock(&zdev->kzdev_lock);
+ ret = !!zdev->kzdev;
+ mutex_unlock(&zdev->kzdev_lock);
+
+ return ret;
}
static bool is_driver_supported(struct pci_driver *driver)
@@ -176,7 +183,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
}
pdev->error_state = pci_channel_io_frozen;
- if (is_passed_through(to_zpci(pdev))) {
+ if (is_passed_through(pdev)) {
pr_info("%s: Cannot be recovered in the host because it is a pass-through device\n",
pci_name(pdev));
goto out_unlock;
@@ -239,7 +246,7 @@ static void zpci_event_io_failure(struct pci_dev *pdev, pci_channel_state_t es)
* we will inject the error event and let the guest recover the device
* itself.
*/
- if (is_passed_through(to_zpci(pdev)))
+ if (is_passed_through(pdev))
goto out;
driver = to_pci_driver(pdev->dev.driver);
if (driver && driver->err_handler && driver->err_handler->error_detected)
@@ -306,8 +313,6 @@ static void zpci_event_hard_deconfigured(struct zpci_dev *zdev, u32 fh)
/* Even though the device is already gone we still
* need to free zPCI resources as part of the disable.
*/
- if (zdev->dma_table)
- zpci_dma_exit_device(zdev);
if (zdev_enabled(zdev))
zpci_disable_device(zdev);
zdev->state = ZPCI_FN_STATE_STANDBY;
diff --git a/arch/s390/pci/pci_sysfs.c b/arch/s390/pci/pci_sysfs.c
index cae280e5c047..8a7abac51816 100644
--- a/arch/s390/pci/pci_sysfs.c
+++ b/arch/s390/pci/pci_sysfs.c
@@ -56,6 +56,7 @@ static ssize_t recover_store(struct device *dev, struct device_attribute *attr,
struct pci_dev *pdev = to_pci_dev(dev);
struct zpci_dev *zdev = to_zpci(pdev);
int ret = 0;
+ u8 status;
/* Can't use device_remove_self() here as that would lead us to lock
* the pci_rescan_remove_lock while holding the device' kernfs lock.
@@ -82,12 +83,6 @@ static ssize_t recover_store(struct device *dev, struct device_attribute *attr,
pci_lock_rescan_remove();
if (pci_dev_is_added(pdev)) {
pci_stop_and_remove_bus_device(pdev);
- if (zdev->dma_table) {
- ret = zpci_dma_exit_device(zdev);
- if (ret)
- goto out;
- }
-
if (zdev_enabled(zdev)) {
ret = zpci_disable_device(zdev);
/*
@@ -105,14 +100,16 @@ static ssize_t recover_store(struct device *dev, struct device_attribute *attr,
ret = zpci_enable_device(zdev);
if (ret)
goto out;
- ret = zpci_dma_init_device(zdev);
- if (ret) {
- zpci_disable_device(zdev);
- goto out;
+
+ if (zdev->dma_table) {
+ ret = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
+ virt_to_phys(zdev->dma_table), &status);
+ if (ret)
+ zpci_disable_device(zdev);
}
- pci_rescan_bus(zdev->zbus->bus);
}
out:
+ pci_rescan_bus(zdev->zbus->bus);
pci_unlock_rescan_remove();
if (kn)
sysfs_unbreak_active_protection(kn);
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 33530b044953..7500521b2b98 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -124,8 +124,7 @@ config ARCH_HAS_ILOG2_U64
config NO_IOPORT_MAP
def_bool !PCI
- depends on !SH_SH4202_MICRODEV && !SH_SHMIN && !SH_HP6XX && \
- !SH_SOLUTION_ENGINE
+ depends on !SH_SHMIN && !SH_HP6XX && !SH_SOLUTION_ENGINE
config IO_TRAPPED
bool
@@ -384,10 +383,6 @@ config CPU_SUBTYPE_SH7760
bool "Support SH7760 processor"
select CPU_SH4
-config CPU_SUBTYPE_SH4_202
- bool "Support SH4-202 processor"
- select CPU_SH4
-
# SH-4A Processor Support
config CPU_SUBTYPE_SH7723
@@ -518,7 +513,6 @@ config SH_PCLK_FREQ
CPU_SUBTYPE_SH7263 || \
CPU_SUBTYPE_MXG
default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R
- default "66000000" if CPU_SUBTYPE_SH4_202
default "50000000"
help
This option is used to specify the peripheral clock frequency.
@@ -743,10 +737,6 @@ endmenu
menu "Bus options"
-config SUPERHYWAY
- tristate "SuperHyway Bus support"
- depends on CPU_SUBTYPE_SH4_202
-
config MAPLE
bool "Maple Bus support"
depends on SH_DREAMCAST
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index c449e7c1b20f..8bcd6c1431a9 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -22,6 +22,17 @@ config STACK_DEBUG
every function call and will therefore incur a major
performance hit. Most users should say N.
+config EARLY_PRINTK
+ bool "Early printk"
+ depends on SH_STANDARD_BIOS
+ help
+ Say Y here to redirect kernel printk messages to the serial port
+ used by the SH-IPL bootloader, starting very early in the boot
+ process and ending when the kernel's serial console is initialised.
+ This option is only useful while porting the kernel to a new machine,
+ when the kernel may crash or hang before the serial console is
+ initialised. If unsure, say N.
+
config 4KSTACKS
bool "Use 4Kb for kernel stacks instead of 8Kb"
depends on DEBUG_KERNEL && (MMU || BROKEN) && !PAGE_SIZE_64KB
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index fafe15d3ba1d..109bec4dad94 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -289,13 +289,6 @@ config SH_EDOSK7760
Select if configuring for a Renesas EDOSK7760
evaluation board.
-config SH_SH4202_MICRODEV
- bool "SH4-202 MicroDev"
- depends on CPU_SUBTYPE_SH4_202
- help
- Select SH4-202 MicroDev if configuring for a SuperH MicroDev board
- with an SH4-202 CPU.
-
config SH_LANDISK
bool "LANDISK"
depends on CPU_SUBTYPE_SH7751R
diff --git a/arch/sh/boards/Makefile b/arch/sh/boards/Makefile
index b57219436ace..fbbc350ca854 100644
--- a/arch/sh/boards/Makefile
+++ b/arch/sh/boards/Makefile
@@ -33,7 +33,6 @@ obj-$(CONFIG_SH_SDK7780) += mach-sdk7780/
obj-$(CONFIG_SH_SDK7786) += mach-sdk7786/
obj-$(CONFIG_SH_X3PROTO) += mach-x3proto/
obj-$(CONFIG_SH_SH7763RDP) += mach-sh7763rdp/
-obj-$(CONFIG_SH_SH4202_MICRODEV)+= mach-microdev/
obj-$(CONFIG_SH_LANDISK) += mach-landisk/
obj-$(CONFIG_SH_LBOX_RE2) += mach-lboxre2/
obj-$(CONFIG_SH_RSK) += mach-rsk/
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 3be293335de5..0f279360838a 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -881,7 +881,7 @@ static struct platform_device fsi_device = {
.resource = fsi_resources,
};
-static struct asoc_simple_card_info fsi_da7210_info = {
+static struct simple_util_info fsi_da7210_info = {
.name = "DA7210",
.card = "FSIB-DA7210",
.codec = "da7210.0-001a",
diff --git a/arch/sh/boards/mach-microdev/Makefile b/arch/sh/boards/mach-microdev/Makefile
deleted file mode 100644
index 05c5698dcad0..000000000000
--- a/arch/sh/boards/mach-microdev/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the SuperH MicroDev specific parts of the kernel
-#
-
-obj-y := setup.o irq.o io.o fdc37c93xapm.o
diff --git a/arch/sh/boards/mach-microdev/fdc37c93xapm.c b/arch/sh/boards/mach-microdev/fdc37c93xapm.c
deleted file mode 100644
index 2a04f72dd145..000000000000
--- a/arch/sh/boards/mach-microdev/fdc37c93xapm.c
+++ /dev/null
@@ -1,157 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Setup for the SMSC FDC37C93xAPM
- *
- * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
- * Copyright (C) 2003, 2004 SuperH, Inc.
- * Copyright (C) 2004, 2005 Paul Mundt
- *
- * SuperH SH4-202 MicroDev board support.
- */
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <mach/microdev.h>
-
-#define SMSC_CONFIG_PORT_ADDR (0x3F0)
-#define SMSC_INDEX_PORT_ADDR SMSC_CONFIG_PORT_ADDR
-#define SMSC_DATA_PORT_ADDR (SMSC_INDEX_PORT_ADDR + 1)
-
-#define SMSC_ENTER_CONFIG_KEY 0x55
-#define SMSC_EXIT_CONFIG_KEY 0xaa
-
-#define SMCS_LOGICAL_DEV_INDEX 0x07 /* Logical Device Number */
-#define SMSC_DEVICE_ID_INDEX 0x20 /* Device ID */
-#define SMSC_DEVICE_REV_INDEX 0x21 /* Device Revision */
-#define SMSC_ACTIVATE_INDEX 0x30 /* Activate */
-#define SMSC_PRIMARY_BASE_INDEX 0x60 /* Primary Base Address */
-#define SMSC_SECONDARY_BASE_INDEX 0x62 /* Secondary Base Address */
-#define SMSC_PRIMARY_INT_INDEX 0x70 /* Primary Interrupt Select */
-#define SMSC_SECONDARY_INT_INDEX 0x72 /* Secondary Interrupt Select */
-#define SMSC_HDCS0_INDEX 0xf0 /* HDCS0 Address Decoder */
-#define SMSC_HDCS1_INDEX 0xf1 /* HDCS1 Address Decoder */
-
-#define SMSC_IDE1_DEVICE 1 /* IDE #1 logical device */
-#define SMSC_IDE2_DEVICE 2 /* IDE #2 logical device */
-#define SMSC_PARALLEL_DEVICE 3 /* Parallel Port logical device */
-#define SMSC_SERIAL1_DEVICE 4 /* Serial #1 logical device */
-#define SMSC_SERIAL2_DEVICE 5 /* Serial #2 logical device */
-#define SMSC_KEYBOARD_DEVICE 7 /* Keyboard logical device */
-#define SMSC_CONFIG_REGISTERS 8 /* Configuration Registers (Aux I/O) */
-
-#define SMSC_READ_INDEXED(index) ({ \
- outb((index), SMSC_INDEX_PORT_ADDR); \
- inb(SMSC_DATA_PORT_ADDR); })
-#define SMSC_WRITE_INDEXED(val, index) ({ \
- outb((index), SMSC_INDEX_PORT_ADDR); \
- outb((val), SMSC_DATA_PORT_ADDR); })
-
-#define IDE1_PRIMARY_BASE 0x01f0 /* Task File Registe base for IDE #1 */
-#define IDE1_SECONDARY_BASE 0x03f6 /* Miscellaneous AT registers for IDE #1 */
-#define IDE2_PRIMARY_BASE 0x0170 /* Task File Registe base for IDE #2 */
-#define IDE2_SECONDARY_BASE 0x0376 /* Miscellaneous AT registers for IDE #2 */
-
-#define SERIAL1_PRIMARY_BASE 0x03f8
-#define SERIAL2_PRIMARY_BASE 0x02f8
-
-#define MSB(x) ( (x) >> 8 )
-#define LSB(x) ( (x) & 0xff )
-
- /* General-Purpose base address on CPU-board FPGA */
-#define MICRODEV_FPGA_GP_BASE 0xa6100000ul
-
-static int __init smsc_superio_setup(void)
-{
-
- unsigned char devid, devrev;
-
- /* Initially the chip is in run state */
- /* Put it into configuration state */
- outb(SMSC_ENTER_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
-
- /* Read device ID info */
- devid = SMSC_READ_INDEXED(SMSC_DEVICE_ID_INDEX);
- devrev = SMSC_READ_INDEXED(SMSC_DEVICE_REV_INDEX);
-
- if ((devid == 0x30) && (devrev == 0x01))
- printk("SMSC FDC37C93xAPM SuperIO device detected\n");
- else
- return -ENODEV;
-
- /* Select the keyboard device */
- SMSC_WRITE_INDEXED(SMSC_KEYBOARD_DEVICE, SMCS_LOGICAL_DEV_INDEX);
- /* enable it */
- SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
- /* enable the interrupts */
- SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_KEYBOARD, SMSC_PRIMARY_INT_INDEX);
- SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_MOUSE, SMSC_SECONDARY_INT_INDEX);
-
- /* Select the Serial #1 device */
- SMSC_WRITE_INDEXED(SMSC_SERIAL1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
- /* enable it */
- SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
- /* program with port addresses */
- SMSC_WRITE_INDEXED(MSB(SERIAL1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
- SMSC_WRITE_INDEXED(LSB(SERIAL1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
- SMSC_WRITE_INDEXED(0x00, SMSC_HDCS0_INDEX);
- /* enable the interrupts */
- SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_SERIAL1, SMSC_PRIMARY_INT_INDEX);
-
- /* Select the Serial #2 device */
- SMSC_WRITE_INDEXED(SMSC_SERIAL2_DEVICE, SMCS_LOGICAL_DEV_INDEX);
- /* enable it */
- SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
- /* program with port addresses */
- SMSC_WRITE_INDEXED(MSB(SERIAL2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
- SMSC_WRITE_INDEXED(LSB(SERIAL2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
- SMSC_WRITE_INDEXED(0x00, SMSC_HDCS0_INDEX);
- /* enable the interrupts */
- SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_SERIAL2, SMSC_PRIMARY_INT_INDEX);
-
- /* Select the IDE#1 device */
- SMSC_WRITE_INDEXED(SMSC_IDE1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
- /* enable it */
- SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
- /* program with port addresses */
- SMSC_WRITE_INDEXED(MSB(IDE1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
- SMSC_WRITE_INDEXED(LSB(IDE1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
- SMSC_WRITE_INDEXED(MSB(IDE1_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+0);
- SMSC_WRITE_INDEXED(LSB(IDE1_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+1);
- SMSC_WRITE_INDEXED(0x0c, SMSC_HDCS0_INDEX);
- SMSC_WRITE_INDEXED(0x00, SMSC_HDCS1_INDEX);
- /* select the interrupt */
- SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_IDE1, SMSC_PRIMARY_INT_INDEX);
-
- /* Select the IDE#2 device */
- SMSC_WRITE_INDEXED(SMSC_IDE2_DEVICE, SMCS_LOGICAL_DEV_INDEX);
- /* enable it */
- SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
- /* program with port addresses */
- SMSC_WRITE_INDEXED(MSB(IDE2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
- SMSC_WRITE_INDEXED(LSB(IDE2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
- SMSC_WRITE_INDEXED(MSB(IDE2_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+0);
- SMSC_WRITE_INDEXED(LSB(IDE2_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+1);
- /* select the interrupt */
- SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_IDE2, SMSC_PRIMARY_INT_INDEX);
-
- /* Select the configuration registers */
- SMSC_WRITE_INDEXED(SMSC_CONFIG_REGISTERS, SMCS_LOGICAL_DEV_INDEX);
- /* enable the appropriate GPIO pins for IDE functionality:
- * bit[0] In/Out 1==input; 0==output
- * bit[1] Polarity 1==invert; 0==no invert
- * bit[2] Int Enb #1 1==Enable Combined IRQ #1; 0==disable
- * bit[3:4] Function Select 00==original; 01==Alternate Function #1
- */
- SMSC_WRITE_INDEXED(0x00, 0xc2); /* GP42 = nIDE1_OE */
- SMSC_WRITE_INDEXED(0x01, 0xc5); /* GP45 = IDE1_IRQ */
- SMSC_WRITE_INDEXED(0x00, 0xc6); /* GP46 = nIOROP */
- SMSC_WRITE_INDEXED(0x00, 0xc7); /* GP47 = nIOWOP */
- SMSC_WRITE_INDEXED(0x08, 0xe8); /* GP20 = nIDE2_OE */
-
- /* Exit the configuration state */
- outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
-
- return 0;
-}
-device_initcall(smsc_superio_setup);
diff --git a/arch/sh/boards/mach-microdev/io.c b/arch/sh/boards/mach-microdev/io.c
deleted file mode 100644
index a76c12721e63..000000000000
--- a/arch/sh/boards/mach-microdev/io.c
+++ /dev/null
@@ -1,123 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * linux/arch/sh/boards/superh/microdev/io.c
- *
- * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
- * Copyright (C) 2003, 2004 SuperH, Inc.
- * Copyright (C) 2004 Paul Mundt
- *
- * SuperH SH4-202 MicroDev board support.
- */
-
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/wait.h>
-#include <asm/io.h>
-#include <mach/microdev.h>
-
- /*
- * we need to have a 'safe' address to re-direct all I/O requests
- * that we do not explicitly wish to handle. This safe address
- * must have the following properies:
- *
- * * writes are ignored (no exception)
- * * reads are benign (no side-effects)
- * * accesses of width 1, 2 and 4-bytes are all valid.
- *
- * The Processor Version Register (PVR) has these properties.
- */
-#define PVR 0xff000030 /* Processor Version Register */
-
-
-#define IO_IDE2_BASE 0x170ul /* I/O base for SMSC FDC37C93xAPM IDE #2 */
-#define IO_IDE1_BASE 0x1f0ul /* I/O base for SMSC FDC37C93xAPM IDE #1 */
-#define IO_ISP1161_BASE 0x290ul /* I/O port for Philips ISP1161x USB chip */
-#define IO_SERIAL2_BASE 0x2f8ul /* I/O base for SMSC FDC37C93xAPM Serial #2 */
-#define IO_LAN91C111_BASE 0x300ul /* I/O base for SMSC LAN91C111 Ethernet chip */
-#define IO_IDE2_MISC 0x376ul /* I/O misc for SMSC FDC37C93xAPM IDE #2 */
-#define IO_SUPERIO_BASE 0x3f0ul /* I/O base for SMSC FDC37C93xAPM SuperIO chip */
-#define IO_IDE1_MISC 0x3f6ul /* I/O misc for SMSC FDC37C93xAPM IDE #1 */
-#define IO_SERIAL1_BASE 0x3f8ul /* I/O base for SMSC FDC37C93xAPM Serial #1 */
-
-#define IO_ISP1161_EXTENT 0x04ul /* I/O extent for Philips ISP1161x USB chip */
-#define IO_LAN91C111_EXTENT 0x10ul /* I/O extent for SMSC LAN91C111 Ethernet chip */
-#define IO_SUPERIO_EXTENT 0x02ul /* I/O extent for SMSC FDC37C93xAPM SuperIO chip */
-#define IO_IDE_EXTENT 0x08ul /* I/O extent for IDE Task Register set */
-#define IO_SERIAL_EXTENT 0x10ul
-
-#define IO_LAN91C111_PHYS 0xa7500000ul /* Physical address of SMSC LAN91C111 Ethernet chip */
-#define IO_ISP1161_PHYS 0xa7700000ul /* Physical address of Philips ISP1161x USB chip */
-#define IO_SUPERIO_PHYS 0xa7800000ul /* Physical address of SMSC FDC37C93xAPM SuperIO chip */
-
-/*
- * map I/O ports to memory-mapped addresses
- */
-void __iomem *microdev_ioport_map(unsigned long offset, unsigned int len)
-{
- unsigned long result;
-
- if ((offset >= IO_LAN91C111_BASE) &&
- (offset < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) {
- /*
- * SMSC LAN91C111 Ethernet chip
- */
- result = IO_LAN91C111_PHYS + offset - IO_LAN91C111_BASE;
- } else if ((offset >= IO_SUPERIO_BASE) &&
- (offset < IO_SUPERIO_BASE + IO_SUPERIO_EXTENT)) {
- /*
- * SMSC FDC37C93xAPM SuperIO chip
- *
- * Configuration Registers
- */
- result = IO_SUPERIO_PHYS + (offset << 1);
- } else if (((offset >= IO_IDE1_BASE) &&
- (offset < IO_IDE1_BASE + IO_IDE_EXTENT)) ||
- (offset == IO_IDE1_MISC)) {
- /*
- * SMSC FDC37C93xAPM SuperIO chip
- *
- * IDE #1
- */
- result = IO_SUPERIO_PHYS + (offset << 1);
- } else if (((offset >= IO_IDE2_BASE) &&
- (offset < IO_IDE2_BASE + IO_IDE_EXTENT)) ||
- (offset == IO_IDE2_MISC)) {
- /*
- * SMSC FDC37C93xAPM SuperIO chip
- *
- * IDE #2
- */
- result = IO_SUPERIO_PHYS + (offset << 1);
- } else if ((offset >= IO_SERIAL1_BASE) &&
- (offset < IO_SERIAL1_BASE + IO_SERIAL_EXTENT)) {
- /*
- * SMSC FDC37C93xAPM SuperIO chip
- *
- * Serial #1
- */
- result = IO_SUPERIO_PHYS + (offset << 1);
- } else if ((offset >= IO_SERIAL2_BASE) &&
- (offset < IO_SERIAL2_BASE + IO_SERIAL_EXTENT)) {
- /*
- * SMSC FDC37C93xAPM SuperIO chip
- *
- * Serial #2
- */
- result = IO_SUPERIO_PHYS + (offset << 1);
- } else if ((offset >= IO_ISP1161_BASE) &&
- (offset < IO_ISP1161_BASE + IO_ISP1161_EXTENT)) {
- /*
- * Philips USB ISP1161x chip
- */
- result = IO_ISP1161_PHYS + offset - IO_ISP1161_BASE;
- } else {
- /*
- * safe default.
- */
- printk("Warning: unexpected port in %s( offset = 0x%lx )\n",
- __func__, offset);
- result = PVR;
- }
-
- return (void __iomem *)result;
-}
diff --git a/arch/sh/boards/mach-microdev/irq.c b/arch/sh/boards/mach-microdev/irq.c
deleted file mode 100644
index dc27492c83d7..000000000000
--- a/arch/sh/boards/mach-microdev/irq.c
+++ /dev/null
@@ -1,150 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/sh/boards/superh/microdev/irq.c
- *
- * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
- *
- * SuperH SH4-202 MicroDev board support.
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-#include <mach/microdev.h>
-
-#define NUM_EXTERNAL_IRQS 16 /* IRL0 .. IRL15 */
-
-static const struct {
- unsigned char fpgaIrq;
- unsigned char mapped;
- const char *name;
-} fpgaIrqTable[NUM_EXTERNAL_IRQS] = {
- { 0, 0, "unused" }, /* IRQ #0 IRL=15 0x200 */
- { MICRODEV_FPGA_IRQ_KEYBOARD, 1, "keyboard" }, /* IRQ #1 IRL=14 0x220 */
- { MICRODEV_FPGA_IRQ_SERIAL1, 1, "Serial #1"}, /* IRQ #2 IRL=13 0x240 */
- { MICRODEV_FPGA_IRQ_ETHERNET, 1, "Ethernet" }, /* IRQ #3 IRL=12 0x260 */
- { MICRODEV_FPGA_IRQ_SERIAL2, 0, "Serial #2"}, /* IRQ #4 IRL=11 0x280 */
- { 0, 0, "unused" }, /* IRQ #5 IRL=10 0x2a0 */
- { 0, 0, "unused" }, /* IRQ #6 IRL=9 0x2c0 */
- { MICRODEV_FPGA_IRQ_USB_HC, 1, "USB" }, /* IRQ #7 IRL=8 0x2e0 */
- { MICRODEV_IRQ_PCI_INTA, 1, "PCI INTA" }, /* IRQ #8 IRL=7 0x300 */
- { MICRODEV_IRQ_PCI_INTB, 1, "PCI INTB" }, /* IRQ #9 IRL=6 0x320 */
- { MICRODEV_IRQ_PCI_INTC, 1, "PCI INTC" }, /* IRQ #10 IRL=5 0x340 */
- { MICRODEV_IRQ_PCI_INTD, 1, "PCI INTD" }, /* IRQ #11 IRL=4 0x360 */
- { MICRODEV_FPGA_IRQ_MOUSE, 1, "mouse" }, /* IRQ #12 IRL=3 0x380 */
- { MICRODEV_FPGA_IRQ_IDE2, 1, "IDE #2" }, /* IRQ #13 IRL=2 0x3a0 */
- { MICRODEV_FPGA_IRQ_IDE1, 1, "IDE #1" }, /* IRQ #14 IRL=1 0x3c0 */
- { 0, 0, "unused" }, /* IRQ #15 IRL=0 0x3e0 */
-};
-
-#if (MICRODEV_LINUX_IRQ_KEYBOARD != 1)
-# error Inconsistancy in defining the IRQ# for Keyboard!
-#endif
-
-#if (MICRODEV_LINUX_IRQ_ETHERNET != 3)
-# error Inconsistancy in defining the IRQ# for Ethernet!
-#endif
-
-#if (MICRODEV_LINUX_IRQ_USB_HC != 7)
-# error Inconsistancy in defining the IRQ# for USB!
-#endif
-
-#if (MICRODEV_LINUX_IRQ_MOUSE != 12)
-# error Inconsistancy in defining the IRQ# for PS/2 Mouse!
-#endif
-
-#if (MICRODEV_LINUX_IRQ_IDE2 != 13)
-# error Inconsistancy in defining the IRQ# for secondary IDE!
-#endif
-
-#if (MICRODEV_LINUX_IRQ_IDE1 != 14)
-# error Inconsistancy in defining the IRQ# for primary IDE!
-#endif
-
-static void disable_microdev_irq(struct irq_data *data)
-{
- unsigned int irq = data->irq;
- unsigned int fpgaIrq;
-
- if (irq >= NUM_EXTERNAL_IRQS)
- return;
- if (!fpgaIrqTable[irq].mapped)
- return;
-
- fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
-
- /* disable interrupts on the FPGA INTC register */
- __raw_writel(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTDSB_REG);
-}
-
-static void enable_microdev_irq(struct irq_data *data)
-{
- unsigned int irq = data->irq;
- unsigned long priorityReg, priorities, pri;
- unsigned int fpgaIrq;
-
- if (unlikely(irq >= NUM_EXTERNAL_IRQS))
- return;
- if (unlikely(!fpgaIrqTable[irq].mapped))
- return;
-
- pri = 15 - irq;
-
- fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
- priorityReg = MICRODEV_FPGA_INTPRI_REG(fpgaIrq);
-
- /* set priority for the interrupt */
- priorities = __raw_readl(priorityReg);
- priorities &= ~MICRODEV_FPGA_INTPRI_MASK(fpgaIrq);
- priorities |= MICRODEV_FPGA_INTPRI_LEVEL(fpgaIrq, pri);
- __raw_writel(priorities, priorityReg);
-
- /* enable interrupts on the FPGA INTC register */
- __raw_writel(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTENB_REG);
-}
-
-static struct irq_chip microdev_irq_type = {
- .name = "MicroDev-IRQ",
- .irq_unmask = enable_microdev_irq,
- .irq_mask = disable_microdev_irq,
-};
-
-/* This function sets the desired irq handler to be a MicroDev type */
-static void __init make_microdev_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- irq_set_chip_and_handler(irq, &microdev_irq_type, handle_level_irq);
- disable_microdev_irq(irq_get_irq_data(irq));
-}
-
-extern void __init init_microdev_irq(void)
-{
- int i;
-
- /* disable interrupts on the FPGA INTC register */
- __raw_writel(~0ul, MICRODEV_FPGA_INTDSB_REG);
-
- for (i = 0; i < NUM_EXTERNAL_IRQS; i++)
- make_microdev_irq(i);
-}
-
-extern void microdev_print_fpga_intc_status(void)
-{
- volatile unsigned int * const intenb = (unsigned int*)MICRODEV_FPGA_INTENB_REG;
- volatile unsigned int * const intdsb = (unsigned int*)MICRODEV_FPGA_INTDSB_REG;
- volatile unsigned int * const intpria = (unsigned int*)MICRODEV_FPGA_INTPRI_REG(0);
- volatile unsigned int * const intprib = (unsigned int*)MICRODEV_FPGA_INTPRI_REG(8);
- volatile unsigned int * const intpric = (unsigned int*)MICRODEV_FPGA_INTPRI_REG(16);
- volatile unsigned int * const intprid = (unsigned int*)MICRODEV_FPGA_INTPRI_REG(24);
- volatile unsigned int * const intsrc = (unsigned int*)MICRODEV_FPGA_INTSRC_REG;
- volatile unsigned int * const intreq = (unsigned int*)MICRODEV_FPGA_INTREQ_REG;
-
- printk("-------------------------- microdev_print_fpga_intc_status() ------------------\n");
- printk("FPGA_INTENB = 0x%08x\n", *intenb);
- printk("FPGA_INTDSB = 0x%08x\n", *intdsb);
- printk("FPGA_INTSRC = 0x%08x\n", *intsrc);
- printk("FPGA_INTREQ = 0x%08x\n", *intreq);
- printk("FPGA_INTPRI[3..0] = %08x:%08x:%08x:%08x\n", *intprid, *intpric, *intprib, *intpria);
- printk("-------------------------------------------------------------------------------\n");
-}
diff --git a/arch/sh/boards/mach-microdev/setup.c b/arch/sh/boards/mach-microdev/setup.c
deleted file mode 100644
index f4a777fe2d01..000000000000
--- a/arch/sh/boards/mach-microdev/setup.c
+++ /dev/null
@@ -1,197 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/sh/boards/superh/microdev/setup.c
- *
- * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
- * Copyright (C) 2003, 2004 SuperH, Inc.
- * Copyright (C) 2004, 2005 Paul Mundt
- *
- * SuperH SH4-202 MicroDev board support.
- */
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/ioport.h>
-#include <video/s1d13xxxfb.h>
-#include <mach/microdev.h>
-#include <asm/io.h>
-#include <asm/machvec.h>
-#include <linux/sizes.h>
-
-static struct resource smc91x_resources[] = {
- [0] = {
- .start = 0x300,
- .end = 0x300 + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = MICRODEV_LINUX_IRQ_ETHERNET,
- .end = MICRODEV_LINUX_IRQ_ETHERNET,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device smc91x_device = {
- .name = "smc91x",
- .id = -1,
- .num_resources = ARRAY_SIZE(smc91x_resources),
- .resource = smc91x_resources,
-};
-
-static struct s1d13xxxfb_regval s1d13806_initregs[] = {
- { S1DREG_MISC, 0x00 },
- { S1DREG_COM_DISP_MODE, 0x00 },
- { S1DREG_GPIO_CNF0, 0x00 },
- { S1DREG_GPIO_CNF1, 0x00 },
- { S1DREG_GPIO_CTL0, 0x00 },
- { S1DREG_GPIO_CTL1, 0x00 },
- { S1DREG_CLK_CNF, 0x02 },
- { S1DREG_LCD_CLK_CNF, 0x01 },
- { S1DREG_CRT_CLK_CNF, 0x03 },
- { S1DREG_MPLUG_CLK_CNF, 0x03 },
- { S1DREG_CPU2MEM_WST_SEL, 0x02 },
- { S1DREG_SDRAM_REF_RATE, 0x03 },
- { S1DREG_SDRAM_TC0, 0x00 },
- { S1DREG_SDRAM_TC1, 0x01 },
- { S1DREG_MEM_CNF, 0x80 },
- { S1DREG_PANEL_TYPE, 0x25 },
- { S1DREG_MOD_RATE, 0x00 },
- { S1DREG_LCD_DISP_HWIDTH, 0x63 },
- { S1DREG_LCD_NDISP_HPER, 0x1e },
- { S1DREG_TFT_FPLINE_START, 0x06 },
- { S1DREG_TFT_FPLINE_PWIDTH, 0x03 },
- { S1DREG_LCD_DISP_VHEIGHT0, 0x57 },
- { S1DREG_LCD_DISP_VHEIGHT1, 0x02 },
- { S1DREG_LCD_NDISP_VPER, 0x00 },
- { S1DREG_TFT_FPFRAME_START, 0x0a },
- { S1DREG_TFT_FPFRAME_PWIDTH, 0x81 },
- { S1DREG_LCD_DISP_MODE, 0x03 },
- { S1DREG_LCD_MISC, 0x00 },
- { S1DREG_LCD_DISP_START0, 0x00 },
- { S1DREG_LCD_DISP_START1, 0x00 },
- { S1DREG_LCD_DISP_START2, 0x00 },
- { S1DREG_LCD_MEM_OFF0, 0x90 },
- { S1DREG_LCD_MEM_OFF1, 0x01 },
- { S1DREG_LCD_PIX_PAN, 0x00 },
- { S1DREG_LCD_DISP_FIFO_HTC, 0x00 },
- { S1DREG_LCD_DISP_FIFO_LTC, 0x00 },
- { S1DREG_CRT_DISP_HWIDTH, 0x63 },
- { S1DREG_CRT_NDISP_HPER, 0x1f },
- { S1DREG_CRT_HRTC_START, 0x04 },
- { S1DREG_CRT_HRTC_PWIDTH, 0x8f },
- { S1DREG_CRT_DISP_VHEIGHT0, 0x57 },
- { S1DREG_CRT_DISP_VHEIGHT1, 0x02 },
- { S1DREG_CRT_NDISP_VPER, 0x1b },
- { S1DREG_CRT_VRTC_START, 0x00 },
- { S1DREG_CRT_VRTC_PWIDTH, 0x83 },
- { S1DREG_TV_OUT_CTL, 0x10 },
- { S1DREG_CRT_DISP_MODE, 0x05 },
- { S1DREG_CRT_DISP_START0, 0x00 },
- { S1DREG_CRT_DISP_START1, 0x00 },
- { S1DREG_CRT_DISP_START2, 0x00 },
- { S1DREG_CRT_MEM_OFF0, 0x20 },
- { S1DREG_CRT_MEM_OFF1, 0x03 },
- { S1DREG_CRT_PIX_PAN, 0x00 },
- { S1DREG_CRT_DISP_FIFO_HTC, 0x00 },
- { S1DREG_CRT_DISP_FIFO_LTC, 0x00 },
- { S1DREG_LCD_CUR_CTL, 0x00 },
- { S1DREG_LCD_CUR_START, 0x01 },
- { S1DREG_LCD_CUR_XPOS0, 0x00 },
- { S1DREG_LCD_CUR_XPOS1, 0x00 },
- { S1DREG_LCD_CUR_YPOS0, 0x00 },
- { S1DREG_LCD_CUR_YPOS1, 0x00 },
- { S1DREG_LCD_CUR_BCTL0, 0x00 },
- { S1DREG_LCD_CUR_GCTL0, 0x00 },
- { S1DREG_LCD_CUR_RCTL0, 0x00 },
- { S1DREG_LCD_CUR_BCTL1, 0x1f },
- { S1DREG_LCD_CUR_GCTL1, 0x3f },
- { S1DREG_LCD_CUR_RCTL1, 0x1f },
- { S1DREG_LCD_CUR_FIFO_HTC, 0x00 },
- { S1DREG_CRT_CUR_CTL, 0x00 },
- { S1DREG_CRT_CUR_START, 0x01 },
- { S1DREG_CRT_CUR_XPOS0, 0x00 },
- { S1DREG_CRT_CUR_XPOS1, 0x00 },
- { S1DREG_CRT_CUR_YPOS0, 0x00 },
- { S1DREG_CRT_CUR_YPOS1, 0x00 },
- { S1DREG_CRT_CUR_BCTL0, 0x00 },
- { S1DREG_CRT_CUR_GCTL0, 0x00 },
- { S1DREG_CRT_CUR_RCTL0, 0x00 },
- { S1DREG_CRT_CUR_BCTL1, 0x1f },
- { S1DREG_CRT_CUR_GCTL1, 0x3f },
- { S1DREG_CRT_CUR_RCTL1, 0x1f },
- { S1DREG_CRT_CUR_FIFO_HTC, 0x00 },
- { S1DREG_BBLT_CTL0, 0x00 },
- { S1DREG_BBLT_CTL1, 0x00 },
- { S1DREG_BBLT_CC_EXP, 0x00 },
- { S1DREG_BBLT_OP, 0x00 },
- { S1DREG_BBLT_SRC_START0, 0x00 },
- { S1DREG_BBLT_SRC_START1, 0x00 },
- { S1DREG_BBLT_SRC_START2, 0x00 },
- { S1DREG_BBLT_DST_START0, 0x00 },
- { S1DREG_BBLT_DST_START1, 0x00 },
- { S1DREG_BBLT_DST_START2, 0x00 },
- { S1DREG_BBLT_MEM_OFF0, 0x00 },
- { S1DREG_BBLT_MEM_OFF1, 0x00 },
- { S1DREG_BBLT_WIDTH0, 0x00 },
- { S1DREG_BBLT_WIDTH1, 0x00 },
- { S1DREG_BBLT_HEIGHT0, 0x00 },
- { S1DREG_BBLT_HEIGHT1, 0x00 },
- { S1DREG_BBLT_BGC0, 0x00 },
- { S1DREG_BBLT_BGC1, 0x00 },
- { S1DREG_BBLT_FGC0, 0x00 },
- { S1DREG_BBLT_FGC1, 0x00 },
- { S1DREG_LKUP_MODE, 0x00 },
- { S1DREG_LKUP_ADDR, 0x00 },
- { S1DREG_PS_CNF, 0x10 },
- { S1DREG_PS_STATUS, 0x00 },
- { S1DREG_CPU2MEM_WDOGT, 0x00 },
- { S1DREG_COM_DISP_MODE, 0x02 },
-};
-
-static struct s1d13xxxfb_pdata s1d13806_platform_data = {
- .initregs = s1d13806_initregs,
- .initregssize = ARRAY_SIZE(s1d13806_initregs),
-};
-
-static struct resource s1d13806_resources[] = {
- [0] = {
- .start = 0x07200000,
- .end = 0x07200000 + SZ_2M - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = 0x07000000,
- .end = 0x07000000 + SZ_2M - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device s1d13806_device = {
- .name = "s1d13806fb",
- .id = -1,
- .num_resources = ARRAY_SIZE(s1d13806_resources),
- .resource = s1d13806_resources,
-
- .dev = {
- .platform_data = &s1d13806_platform_data,
- },
-};
-
-static struct platform_device *microdev_devices[] __initdata = {
- &smc91x_device,
- &s1d13806_device,
-};
-
-static int __init microdev_devices_setup(void)
-{
- return platform_add_devices(microdev_devices, ARRAY_SIZE(microdev_devices));
-}
-device_initcall(microdev_devices_setup);
-
-/*
- * The Machine Vector
- */
-static struct sh_machine_vector mv_sh4202_microdev __initmv = {
- .mv_name = "SH4-202 MicroDev",
- .mv_ioport_map = microdev_ioport_map,
- .mv_init_irq = init_microdev_irq,
-};
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 6495f9354065..787ddd3c627a 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -300,7 +300,7 @@ static struct platform_device fsi_device = {
.resource = fsi_resources,
};
-static struct asoc_simple_card_info fsi_ak4642_info = {
+static struct simple_util_info fsi_ak4642_info = {
.name = "AK4642",
.card = "FSIA-AK4642",
.codec = "ak4642-codec.0-0012",
diff --git a/arch/sh/configs/microdev_defconfig b/arch/sh/configs/microdev_defconfig
deleted file mode 100644
index 39a83d832cac..000000000000
--- a/arch/sh/configs/microdev_defconfig
+++ /dev/null
@@ -1,42 +0,0 @@
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_CPU_SUBTYPE_SH4_202=y
-CONFIG_FLATMEM_MANUAL=y
-CONFIG_SH_SH4202_MICRODEV=y
-CONFIG_SH_DMA=y
-CONFIG_SH_DMA_API=y
-CONFIG_HEARTBEAT=y
-CONFIG_PREEMPT=y
-CONFIG_CMDLINE_OVERWRITE=y
-CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/hda1"
-CONFIG_SUPERHYWAY=y
-CONFIG_NET=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-# CONFIG_IPV6 is not set
-# CONFIG_FW_LOADER is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_CONSOLE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_VFAT_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_HUGETLBFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_CRYPTO_ECB=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/sh/drivers/Makefile b/arch/sh/drivers/Makefile
index 56b0acace6e7..8bd10b904bf9 100644
--- a/arch/sh/drivers/Makefile
+++ b/arch/sh/drivers/Makefile
@@ -6,6 +6,5 @@
obj-y += dma/ platform_early.o
obj-$(CONFIG_PCI) += pci/
-obj-$(CONFIG_SUPERHYWAY) += superhyway/
obj-$(CONFIG_PUSH_SWITCH) += push-switch.o
obj-$(CONFIG_HEARTBEAT) += heartbeat.o
diff --git a/arch/sh/drivers/pci/common.c b/arch/sh/drivers/pci/common.c
index 2fd2b77e12ce..ab9e791070b4 100644
--- a/arch/sh/drivers/pci/common.c
+++ b/arch/sh/drivers/pci/common.c
@@ -50,20 +50,21 @@ int __init pci_is_66mhz_capable(struct pci_channel *hose,
int top_bus, int current_bus)
{
u32 pci_devfn;
- unsigned short vid;
+ u16 vid;
int cap66 = -1;
u16 stat;
+ int ret;
pr_info("PCI: Checking 66MHz capabilities...\n");
for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
if (PCI_FUNC(pci_devfn))
continue;
- if (early_read_config_word(hose, top_bus, current_bus,
- pci_devfn, PCI_VENDOR_ID, &vid) !=
- PCIBIOS_SUCCESSFUL)
+ ret = early_read_config_word(hose, top_bus, current_bus,
+ pci_devfn, PCI_VENDOR_ID, &vid);
+ if (ret != PCIBIOS_SUCCESSFUL)
continue;
- if (vid == 0xffff)
+ if (PCI_POSSIBLE_ERROR(vid))
continue;
/* check 66MHz capability */
diff --git a/arch/sh/drivers/superhyway/Makefile b/arch/sh/drivers/superhyway/Makefile
deleted file mode 100644
index aa6e3267c055..000000000000
--- a/arch/sh/drivers/superhyway/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the SuperHyway specific kernel interface routines under Linux.
-#
-
-obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += ops-sh4-202.o
-
diff --git a/arch/sh/drivers/superhyway/ops-sh4-202.c b/arch/sh/drivers/superhyway/ops-sh4-202.c
deleted file mode 100644
index 490142274e3b..000000000000
--- a/arch/sh/drivers/superhyway/ops-sh4-202.c
+++ /dev/null
@@ -1,168 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/sh/drivers/superhyway/ops-sh4-202.c
- *
- * SuperHyway bus support for SH4-202
- *
- * Copyright (C) 2005 Paul Mundt
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/superhyway.h>
-#include <linux/string.h>
-#include <asm/addrspace.h>
-#include <asm/io.h>
-
-#define PHYS_EMI_CBLOCK P4SEGADDR(0x1ec00000)
-#define PHYS_EMI_DBLOCK P4SEGADDR(0x08000000)
-#define PHYS_FEMI_CBLOCK P4SEGADDR(0x1f800000)
-#define PHYS_FEMI_DBLOCK P4SEGADDR(0x00000000)
-
-#define PHYS_EPBR_BLOCK P4SEGADDR(0x1de00000)
-#define PHYS_DMAC_BLOCK P4SEGADDR(0x1fa00000)
-#define PHYS_PBR_BLOCK P4SEGADDR(0x1fc00000)
-
-static struct resource emi_resources[] = {
- [0] = {
- .start = PHYS_EMI_CBLOCK,
- .end = PHYS_EMI_CBLOCK + 0x00300000 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = PHYS_EMI_DBLOCK,
- .end = PHYS_EMI_DBLOCK + 0x08000000 - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct superhyway_device emi_device = {
- .name = "emi",
- .num_resources = ARRAY_SIZE(emi_resources),
- .resource = emi_resources,
-};
-
-static struct resource femi_resources[] = {
- [0] = {
- .start = PHYS_FEMI_CBLOCK,
- .end = PHYS_FEMI_CBLOCK + 0x00100000 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = PHYS_FEMI_DBLOCK,
- .end = PHYS_FEMI_DBLOCK + 0x08000000 - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct superhyway_device femi_device = {
- .name = "femi",
- .num_resources = ARRAY_SIZE(femi_resources),
- .resource = femi_resources,
-};
-
-static struct resource epbr_resources[] = {
- [0] = {
- .start = P4SEGADDR(0x1e7ffff8),
- .end = P4SEGADDR(0x1e7ffff8 + (sizeof(u32) * 2) - 1),
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = PHYS_EPBR_BLOCK,
- .end = PHYS_EPBR_BLOCK + 0x00a00000 - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct superhyway_device epbr_device = {
- .name = "epbr",
- .num_resources = ARRAY_SIZE(epbr_resources),
- .resource = epbr_resources,
-};
-
-static struct resource dmac_resource = {
- .start = PHYS_DMAC_BLOCK,
- .end = PHYS_DMAC_BLOCK + 0x00100000 - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct superhyway_device dmac_device = {
- .name = "dmac",
- .num_resources = 1,
- .resource = &dmac_resource,
-};
-
-static struct resource pbr_resources[] = {
- [0] = {
- .start = P4SEGADDR(0x1ffffff8),
- .end = P4SEGADDR(0x1ffffff8 + (sizeof(u32) * 2) - 1),
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = PHYS_PBR_BLOCK,
- .end = PHYS_PBR_BLOCK + 0x00400000 - (sizeof(u32) * 2) - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct superhyway_device pbr_device = {
- .name = "pbr",
- .num_resources = ARRAY_SIZE(pbr_resources),
- .resource = pbr_resources,
-};
-
-static struct superhyway_device *sh4202_devices[] __initdata = {
- &emi_device, &femi_device, &epbr_device, &dmac_device, &pbr_device,
-};
-
-static int sh4202_read_vcr(unsigned long base, struct superhyway_vcr_info *vcr)
-{
- u32 vcrh, vcrl;
- u64 tmp;
-
- /*
- * XXX: Even though the SH4-202 Evaluation Device documentation
- * indicates that VCRL is mapped first with VCRH at a + 0x04
- * offset, the opposite seems to be true.
- *
- * Some modules (PBR and ePBR for instance) also appear to have
- * VCRL/VCRH flipped in the documentation, but on the SH4-202
- * itself it appears that these are all consistently mapped with
- * VCRH preceding VCRL.
- *
- * Do not trust the documentation, for it is evil.
- */
- vcrh = __raw_readl(base);
- vcrl = __raw_readl(base + sizeof(u32));
-
- tmp = ((u64)vcrh << 32) | vcrl;
- memcpy(vcr, &tmp, sizeof(u64));
-
- return 0;
-}
-
-static int sh4202_write_vcr(unsigned long base, struct superhyway_vcr_info vcr)
-{
- u64 tmp = *(u64 *)&vcr;
-
- __raw_writel((tmp >> 32) & 0xffffffff, base);
- __raw_writel(tmp & 0xffffffff, base + sizeof(u32));
-
- return 0;
-}
-
-static struct superhyway_ops sh4202_superhyway_ops = {
- .read_vcr = sh4202_read_vcr,
- .write_vcr = sh4202_write_vcr,
-};
-
-struct superhyway_bus superhyway_channels[] = {
- { &sh4202_superhyway_ops, },
- { 0, },
-};
-
-int __init superhyway_scan_bus(struct superhyway_bus *bus)
-{
- return superhyway_add_devices(bus, sh4202_devices,
- ARRAY_SIZE(sh4202_devices));
-}
-
diff --git a/arch/sh/include/asm/cmpxchg.h b/arch/sh/include/asm/cmpxchg.h
index 288f6f38d98f..5d617b3ef78f 100644
--- a/arch/sh/include/asm/cmpxchg.h
+++ b/arch/sh/include/asm/cmpxchg.h
@@ -71,4 +71,13 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
(unsigned long)_n_, sizeof(*(ptr))); \
})
+#include <asm-generic/cmpxchg-local.h>
+
+#define arch_cmpxchg_local(ptr, o, n) ({ \
+ (__typeof__(*ptr))__generic_cmpxchg_local((ptr), \
+ (unsigned long)(o), \
+ (unsigned long)(n), \
+ sizeof(*(ptr))); \
+})
+
#endif /* __ASM_SH_CMPXCHG_H */
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index f2f38e9d489a..ac521f287fa5 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -181,7 +181,7 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \
{ \
volatile type *__addr; \
\
- __addr = __ioport_map(port, sizeof(type)); \
+ __addr = (void __iomem *)sh_io_port_base + port; \
*__addr = val; \
slow; \
} \
@@ -191,7 +191,7 @@ static inline type pfx##in##bwlq##p(unsigned long port) \
volatile type *__addr; \
type __val; \
\
- __addr = __ioport_map(port, sizeof(type)); \
+ __addr = (void __iomem *)sh_io_port_base + port; \
__val = *__addr; \
slow; \
\
diff --git a/arch/sh/include/asm/kexec.h b/arch/sh/include/asm/kexec.h
index 927d80ba2332..76631714673c 100644
--- a/arch/sh/include/asm/kexec.h
+++ b/arch/sh/include/asm/kexec.h
@@ -28,7 +28,7 @@
/* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_SH
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
/* arch/sh/kernel/machine_kexec.c */
void reserve_crashkernel(void);
@@ -67,6 +67,6 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
}
#else
static inline void reserve_crashkernel(void) { }
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
#endif /* __ASM_SH_KEXEC_H */
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index eeba83e0a7d2..65d4c3316a5b 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -46,8 +46,6 @@ struct kprobe_ctlblk {
};
extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
-extern int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
extern int kprobe_handle_illslot(unsigned long pc);
#else
diff --git a/arch/sh/include/asm/machvec.h b/arch/sh/include/asm/machvec.h
index 2b4b085e8f21..4e5314b921f1 100644
--- a/arch/sh/include/asm/machvec.h
+++ b/arch/sh/include/asm/machvec.h
@@ -19,11 +19,6 @@ struct sh_machine_vector {
int (*mv_irq_demux)(int irq);
void (*mv_init_irq)(void);
-#ifdef CONFIG_HAS_IOPORT_MAP
- void __iomem *(*mv_ioport_map)(unsigned long port, unsigned int size);
- void (*mv_ioport_unmap)(void __iomem *);
-#endif
-
int (*mv_clk_init)(void);
int (*mv_mode_pins)(void);
diff --git a/arch/sh/include/mach-common/mach/microdev.h b/arch/sh/include/mach-common/mach/microdev.h
deleted file mode 100644
index 0e2f9ab11976..000000000000
--- a/arch/sh/include/mach-common/mach/microdev.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
- * linux/include/asm-sh/microdev.h
- *
- * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
- *
- * Definitions for the SuperH SH4-202 MicroDev board.
- */
-#ifndef __ASM_SH_MICRODEV_H
-#define __ASM_SH_MICRODEV_H
-
-extern void init_microdev_irq(void);
-extern void microdev_print_fpga_intc_status(void);
-
-/*
- * The following are useful macros for manipulating the interrupt
- * controller (INTC) on the CPU-board FPGA. should be noted that there
- * is an INTC on the FPGA, and a separate INTC on the SH4-202 core -
- * these are two different things, both of which need to be prorammed to
- * correctly route - unfortunately, they have the same name and
- * abbreviations!
- */
-#define MICRODEV_FPGA_INTC_BASE 0xa6110000ul /* INTC base address on CPU-board FPGA */
-#define MICRODEV_FPGA_INTENB_REG (MICRODEV_FPGA_INTC_BASE+0ul) /* Interrupt Enable Register on INTC on CPU-board FPGA */
-#define MICRODEV_FPGA_INTDSB_REG (MICRODEV_FPGA_INTC_BASE+8ul) /* Interrupt Disable Register on INTC on CPU-board FPGA */
-#define MICRODEV_FPGA_INTC_MASK(n) (1ul<<(n)) /* Interrupt mask to enable/disable INTC in CPU-board FPGA */
-#define MICRODEV_FPGA_INTPRI_REG(n) (MICRODEV_FPGA_INTC_BASE+0x10+((n)/8)*8)/* Interrupt Priority Register on INTC on CPU-board FPGA */
-#define MICRODEV_FPGA_INTPRI_LEVEL(n,x) ((x)<<(((n)%8)*4)) /* MICRODEV_FPGA_INTPRI_LEVEL(int_number, int_level) */
-#define MICRODEV_FPGA_INTPRI_MASK(n) (MICRODEV_FPGA_INTPRI_LEVEL((n),0xful)) /* Interrupt Priority Mask on INTC on CPU-board FPGA */
-#define MICRODEV_FPGA_INTSRC_REG (MICRODEV_FPGA_INTC_BASE+0x30ul) /* Interrupt Source Register on INTC on CPU-board FPGA */
-#define MICRODEV_FPGA_INTREQ_REG (MICRODEV_FPGA_INTC_BASE+0x38ul) /* Interrupt Request Register on INTC on CPU-board FPGA */
-
-
-/*
- * The following are the IRQ numbers for the Linux Kernel for external
- * interrupts. i.e. the numbers seen by 'cat /proc/interrupt'.
- */
-#define MICRODEV_LINUX_IRQ_KEYBOARD 1 /* SuperIO Keyboard */
-#define MICRODEV_LINUX_IRQ_SERIAL1 2 /* SuperIO Serial #1 */
-#define MICRODEV_LINUX_IRQ_ETHERNET 3 /* on-board Ethnernet */
-#define MICRODEV_LINUX_IRQ_SERIAL2 4 /* SuperIO Serial #2 */
-#define MICRODEV_LINUX_IRQ_USB_HC 7 /* on-board USB HC */
-#define MICRODEV_LINUX_IRQ_MOUSE 12 /* SuperIO PS/2 Mouse */
-#define MICRODEV_LINUX_IRQ_IDE2 13 /* SuperIO IDE #2 */
-#define MICRODEV_LINUX_IRQ_IDE1 14 /* SuperIO IDE #1 */
-
-/*
- * The following are the IRQ numbers for the INTC on the FPGA for
- * external interrupts. i.e. the bits in the INTC registers in the
- * FPGA.
- */
-#define MICRODEV_FPGA_IRQ_KEYBOARD 1 /* SuperIO Keyboard */
-#define MICRODEV_FPGA_IRQ_SERIAL1 3 /* SuperIO Serial #1 */
-#define MICRODEV_FPGA_IRQ_SERIAL2 4 /* SuperIO Serial #2 */
-#define MICRODEV_FPGA_IRQ_MOUSE 12 /* SuperIO PS/2 Mouse */
-#define MICRODEV_FPGA_IRQ_IDE1 14 /* SuperIO IDE #1 */
-#define MICRODEV_FPGA_IRQ_IDE2 15 /* SuperIO IDE #2 */
-#define MICRODEV_FPGA_IRQ_USB_HC 16 /* on-board USB HC */
-#define MICRODEV_FPGA_IRQ_ETHERNET 18 /* on-board Ethnernet */
-
-#define MICRODEV_IRQ_PCI_INTA 8
-#define MICRODEV_IRQ_PCI_INTB 9
-#define MICRODEV_IRQ_PCI_INTC 10
-#define MICRODEV_IRQ_PCI_INTD 11
-
-#define __IO_PREFIX microdev
-#include <asm/io_generic.h>
-
-#endif /* __ASM_SH_MICRODEV_H */
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 69cd9ac4b2ab..2d7e70537de0 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -33,7 +33,7 @@ obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_MODULES) += sh_ksyms_32.o module.o
-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_IO_TRAPPED) += io_trapped.o
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 00c16331e07e..02e3ee16e15c 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -23,15 +23,11 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7091) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7760) += setup-sh7760.o
-obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += setup-sh4-202.o
# Primary on-chip clocks (common)
ifndef CONFIG_CPU_SH4A
clock-$(CONFIG_CPU_SH4) := clock-sh4.o
endif
-# Additional clocks by subtype
-clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o
-
obj-y += $(clock-y)
obj-$(CONFIG_PERF_EVENTS) += $(perf-y)
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
deleted file mode 100644
index c1cdef763cb2..000000000000
--- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
+++ /dev/null
@@ -1,174 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/sh/kernel/cpu/sh4/clock-sh4-202.c
- *
- * Additional SH4-202 support for the clock framework
- *
- * Copyright (C) 2005 Paul Mundt
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
-#include <asm/clock.h>
-#include <asm/freq.h>
-
-#define CPG2_FRQCR3 0xfe0a0018
-
-static int frqcr3_divisors[] = { 1, 2, 3, 4, 6, 8, 16 };
-static int frqcr3_values[] = { 0, 1, 2, 3, 4, 5, 6 };
-
-static unsigned long emi_clk_recalc(struct clk *clk)
-{
- int idx = __raw_readl(CPG2_FRQCR3) & 0x0007;
- return clk->parent->rate / frqcr3_divisors[idx];
-}
-
-static inline int frqcr3_lookup(struct clk *clk, unsigned long rate)
-{
- int divisor = clk->parent->rate / rate;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++)
- if (frqcr3_divisors[i] == divisor)
- return frqcr3_values[i];
-
- /* Safe fallback */
- return 5;
-}
-
-static struct sh_clk_ops sh4202_emi_clk_ops = {
- .recalc = emi_clk_recalc,
-};
-
-static struct clk sh4202_emi_clk = {
- .flags = CLK_ENABLE_ON_INIT,
- .ops = &sh4202_emi_clk_ops,
-};
-
-static unsigned long femi_clk_recalc(struct clk *clk)
-{
- int idx = (__raw_readl(CPG2_FRQCR3) >> 3) & 0x0007;
- return clk->parent->rate / frqcr3_divisors[idx];
-}
-
-static struct sh_clk_ops sh4202_femi_clk_ops = {
- .recalc = femi_clk_recalc,
-};
-
-static struct clk sh4202_femi_clk = {
- .flags = CLK_ENABLE_ON_INIT,
- .ops = &sh4202_femi_clk_ops,
-};
-
-static void shoc_clk_init(struct clk *clk)
-{
- int i;
-
- /*
- * For some reason, the shoc_clk seems to be set to some really
- * insane value at boot (values outside of the allowable frequency
- * range for instance). We deal with this by scaling it back down
- * to something sensible just in case.
- *
- * Start scaling from the high end down until we find something
- * that passes rate verification..
- */
- for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) {
- int divisor = frqcr3_divisors[i];
-
- if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0)
- break;
- }
-
- WARN_ON(i == ARRAY_SIZE(frqcr3_divisors)); /* Undefined clock */
-}
-
-static unsigned long shoc_clk_recalc(struct clk *clk)
-{
- int idx = (__raw_readl(CPG2_FRQCR3) >> 6) & 0x0007;
- return clk->parent->rate / frqcr3_divisors[idx];
-}
-
-static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *bclk = clk_get(NULL, "bus_clk");
- unsigned long bclk_rate = clk_get_rate(bclk);
-
- clk_put(bclk);
-
- if (rate > bclk_rate)
- return 1;
- if (rate > 66000000)
- return 1;
-
- return 0;
-}
-
-static int shoc_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- unsigned long frqcr3;
- unsigned int tmp;
-
- /* Make sure we have something sensible to switch to */
- if (shoc_clk_verify_rate(clk, rate) != 0)
- return -EINVAL;
-
- tmp = frqcr3_lookup(clk, rate);
-
- frqcr3 = __raw_readl(CPG2_FRQCR3);
- frqcr3 &= ~(0x0007 << 6);
- frqcr3 |= tmp << 6;
- __raw_writel(frqcr3, CPG2_FRQCR3);
-
- clk->rate = clk->parent->rate / frqcr3_divisors[tmp];
-
- return 0;
-}
-
-static struct sh_clk_ops sh4202_shoc_clk_ops = {
- .init = shoc_clk_init,
- .recalc = shoc_clk_recalc,
- .set_rate = shoc_clk_set_rate,
-};
-
-static struct clk sh4202_shoc_clk = {
- .flags = CLK_ENABLE_ON_INIT,
- .ops = &sh4202_shoc_clk_ops,
-};
-
-static struct clk *sh4202_onchip_clocks[] = {
- &sh4202_emi_clk,
- &sh4202_femi_clk,
- &sh4202_shoc_clk,
-};
-
-static struct clk_lookup lookups[] = {
- /* main clocks */
- CLKDEV_CON_ID("emi_clk", &sh4202_emi_clk),
- CLKDEV_CON_ID("femi_clk", &sh4202_femi_clk),
- CLKDEV_CON_ID("shoc_clk", &sh4202_shoc_clk),
-};
-
-int __init arch_clk_init(void)
-{
- struct clk *clk;
- int i, ret = 0;
-
- cpg_clk_init();
-
- clk = clk_get(NULL, "master_clk");
- for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) {
- struct clk *clkp = sh4202_onchip_clocks[i];
-
- clkp->parent = clk;
- ret |= clk_register(clkp);
- }
-
- clk_put(clk);
-
- clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
- return ret;
-}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
deleted file mode 100644
index e6737f3d0df2..000000000000
--- a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
+++ /dev/null
@@ -1,139 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * SH4-202 Setup
- *
- * Copyright (C) 2006 Paul Mundt
- * Copyright (C) 2009 Magnus Damm
- */
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial.h>
-#include <linux/serial_sci.h>
-#include <linux/sh_timer.h>
-#include <linux/sh_intc.h>
-#include <linux/io.h>
-#include <asm/platform_early.h>
-
-static struct plat_sci_port scif0_platform_data = {
- .scscr = SCSCR_REIE,
- .type = PORT_SCIF,
-};
-
-static struct resource scif0_resources[] = {
- DEFINE_RES_MEM(0xffe80000, 0x100),
- DEFINE_RES_IRQ(evt2irq(0x700)),
- DEFINE_RES_IRQ(evt2irq(0x720)),
- DEFINE_RES_IRQ(evt2irq(0x760)),
- DEFINE_RES_IRQ(evt2irq(0x740)),
-};
-
-static struct platform_device scif0_device = {
- .name = "sh-sci",
- .id = 0,
- .resource = scif0_resources,
- .num_resources = ARRAY_SIZE(scif0_resources),
- .dev = {
- .platform_data = &scif0_platform_data,
- },
-};
-
-static struct sh_timer_config tmu0_platform_data = {
- .channels_mask = 7,
-};
-
-static struct resource tmu0_resources[] = {
- DEFINE_RES_MEM(0xffd80000, 0x30),
- DEFINE_RES_IRQ(evt2irq(0x400)),
- DEFINE_RES_IRQ(evt2irq(0x420)),
- DEFINE_RES_IRQ(evt2irq(0x440)),
-};
-
-static struct platform_device tmu0_device = {
- .name = "sh-tmu",
- .id = 0,
- .dev = {
- .platform_data = &tmu0_platform_data,
- },
- .resource = tmu0_resources,
- .num_resources = ARRAY_SIZE(tmu0_resources),
-};
-
-static struct platform_device *sh4202_devices[] __initdata = {
- &scif0_device,
- &tmu0_device,
-};
-
-static int __init sh4202_devices_setup(void)
-{
- return platform_add_devices(sh4202_devices,
- ARRAY_SIZE(sh4202_devices));
-}
-arch_initcall(sh4202_devices_setup);
-
-static struct platform_device *sh4202_early_devices[] __initdata = {
- &scif0_device,
- &tmu0_device,
-};
-
-void __init plat_early_device_setup(void)
-{
- sh_early_platform_add_devices(sh4202_early_devices,
- ARRAY_SIZE(sh4202_early_devices));
-}
-
-enum {
- UNUSED = 0,
-
- /* interrupt sources */
- IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */
- HUDI, TMU0, TMU1, TMU2, RTC, SCIF, WDT,
-};
-
-static struct intc_vect vectors[] __initdata = {
- INTC_VECT(HUDI, 0x600),
- INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
- INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2, 0x460),
- INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
- INTC_VECT(RTC, 0x4c0),
- INTC_VECT(SCIF, 0x700), INTC_VECT(SCIF, 0x720),
- INTC_VECT(SCIF, 0x740), INTC_VECT(SCIF, 0x760),
- INTC_VECT(WDT, 0x560),
-};
-
-static struct intc_prio_reg prio_registers[] __initdata = {
- { 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
- { 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, 0, 0, 0 } },
- { 0xffd0000c, 0, 16, 4, /* IPRC */ { 0, 0, SCIF, HUDI } },
- { 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
-};
-
-static DECLARE_INTC_DESC(intc_desc, "sh4-202", vectors, NULL,
- NULL, prio_registers, NULL);
-
-static struct intc_vect vectors_irlm[] __initdata = {
- INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
- INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
-};
-
-static DECLARE_INTC_DESC(intc_desc_irlm, "sh4-202_irlm", vectors_irlm, NULL,
- NULL, prio_registers, NULL);
-
-void __init plat_irq_setup(void)
-{
- register_intc_controller(&intc_desc);
-}
-
-#define INTC_ICR 0xffd00000UL
-#define INTC_ICR_IRLM (1<<7)
-
-void __init plat_irq_setup_pins(int mode)
-{
- switch (mode) {
- case IRQ_MODE_IRQ: /* individual interrupt mode for IRL3-0 */
- __raw_writew(__raw_readw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
- register_intc_controller(&intc_desc_irlm);
- break;
- default:
- BUG();
- }
-}
diff --git a/arch/sh/kernel/ioport.c b/arch/sh/kernel/ioport.c
index f39446a658bd..c8aff8a20164 100644
--- a/arch/sh/kernel/ioport.c
+++ b/arch/sh/kernel/ioport.c
@@ -12,15 +12,6 @@
unsigned long sh_io_port_base __read_mostly = -1;
EXPORT_SYMBOL(sh_io_port_base);
-void __iomem *__ioport_map(unsigned long addr, unsigned int size)
-{
- if (sh_mv.mv_ioport_map)
- return sh_mv.mv_ioport_map(addr, size);
-
- return (void __iomem *)(addr + sh_io_port_base);
-}
-EXPORT_SYMBOL(__ioport_map);
-
void __iomem *ioport_map(unsigned long port, unsigned int nr)
{
void __iomem *ret;
@@ -29,13 +20,11 @@ void __iomem *ioport_map(unsigned long port, unsigned int nr)
if (ret)
return ret;
- return __ioport_map(port, nr);
+ return (void __iomem *)(port + sh_io_port_base);
}
EXPORT_SYMBOL(ioport_map);
void ioport_unmap(void __iomem *addr)
{
- if (sh_mv.mv_ioport_unmap)
- sh_mv.mv_ioport_unmap(addr);
}
EXPORT_SYMBOL(ioport_unmap);
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c
index 223c14f44af7..fa3a7b36190a 100644
--- a/arch/sh/kernel/machine_kexec.c
+++ b/arch/sh/kernel/machine_kexec.c
@@ -154,7 +154,7 @@ void __init reserve_crashkernel(void)
int ret;
ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
- &crash_size, &crash_base);
+ &crash_size, &crash_base, NULL, NULL);
if (ret == 0 && crash_size > 0) {
crashk_res.start = crash_base;
crashk_res.end = crash_base + crash_size - 1;
diff --git a/arch/sh/kernel/reboot.c b/arch/sh/kernel/reboot.c
index e8eeedc9b182..1de006b1c339 100644
--- a/arch/sh/kernel/reboot.c
+++ b/arch/sh/kernel/reboot.c
@@ -63,7 +63,7 @@ struct machine_ops machine_ops = {
.shutdown = native_machine_shutdown,
.restart = native_machine_restart,
.halt = native_machine_halt,
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
.crash_shutdown = native_machine_crash_shutdown,
#endif
};
@@ -88,7 +88,7 @@ void machine_halt(void)
machine_ops.halt();
}
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
void machine_crash_shutdown(struct pt_regs *regs)
{
machine_ops.crash_shutdown(regs);
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index b3da2757faaf..d3175f09b3aa 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -7,7 +7,6 @@
* Copyright (C) 1999 Niibe Yutaka
* Copyright (C) 2002 - 2010 Paul Mundt
*/
-#include <linux/screen_info.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/initrd.h>
@@ -69,10 +68,6 @@ EXPORT_SYMBOL(cpu_data);
struct sh_machine_vector sh_mv = { .mv_name = "generic", };
EXPORT_SYMBOL(sh_mv);
-#ifdef CONFIG_VT
-struct screen_info screen_info;
-#endif
-
extern int root_mountflags;
#define RAMDISK_IMAGE_START_MASK 0x07FF
@@ -225,7 +220,7 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
request_resource(res, &code_resource);
request_resource(res, &data_resource);
request_resource(res, &bss_resource);
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
request_resource(res, &crashk_res);
#endif
diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl
index e90d585c4d3e..363fae0fe9bf 100644
--- a/arch/sh/kernel/syscalls/syscall.tbl
+++ b/arch/sh/kernel/syscalls/syscall.tbl
@@ -260,7 +260,7 @@
250 common fadvise64 sys_fadvise64
# 251 is unused
252 common exit_group sys_exit_group
-253 common lookup_dcookie sys_lookup_dcookie
+253 common lookup_dcookie sys_ni_syscall
254 common epoll_create sys_epoll_create
255 common epoll_ctl sys_epoll_ctl
256 common epoll_wait sys_epoll_wait
@@ -455,3 +455,7 @@
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
451 common cachestat sys_cachestat
452 common fchmodat2 sys_fchmodat2
+453 common map_shadow_stack sys_map_shadow_stack
+454 common futex_wake sys_futex_wake
+455 common futex_wait sys_futex_wait
+456 common futex_requeue sys_futex_requeue
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 7417345c6639..5f6035936131 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -76,9 +76,8 @@ install:
archheaders:
$(Q)$(MAKE) $(build)=arch/sparc/kernel/syscalls all
-PHONY += vdso_install
-vdso_install:
- $(Q)$(MAKE) $(build)=arch/sparc/vdso $@
+vdso-install-$(CONFIG_SPARC64) += arch/sparc/vdso/vdso64.so.dbg
+vdso-install-$(CONFIG_COMPAT) += arch/sparc/vdso/vdso32.so.dbg
# This is the image used for packaging
KBUILD_IMAGE := $(boot)/zImage
diff --git a/arch/sparc/crypto/crc32c_glue.c b/arch/sparc/crypto/crc32c_glue.c
index 82efb7f81c28..688db0dcb97d 100644
--- a/arch/sparc/crypto/crc32c_glue.c
+++ b/arch/sparc/crypto/crc32c_glue.c
@@ -20,6 +20,7 @@
#include <asm/pstate.h>
#include <asm/elf.h>
+#include <asm/unaligned.h>
#include "opcodes.h"
@@ -35,7 +36,7 @@ static int crc32c_sparc64_setkey(struct crypto_shash *hash, const u8 *key,
if (keylen != sizeof(u32))
return -EINVAL;
- *mctx = le32_to_cpup((__le32 *)key);
+ *mctx = get_unaligned_le32(key);
return 0;
}
@@ -51,18 +52,26 @@ static int crc32c_sparc64_init(struct shash_desc *desc)
extern void crc32c_sparc64(u32 *crcp, const u64 *data, unsigned int len);
-static void crc32c_compute(u32 *crcp, const u64 *data, unsigned int len)
+static u32 crc32c_compute(u32 crc, const u8 *data, unsigned int len)
{
- unsigned int asm_len;
-
- asm_len = len & ~7U;
- if (asm_len) {
- crc32c_sparc64(crcp, data, asm_len);
- data += asm_len / 8;
- len -= asm_len;
+ unsigned int n = -(uintptr_t)data & 7;
+
+ if (n) {
+ /* Data isn't 8-byte aligned. Align it. */
+ n = min(n, len);
+ crc = __crc32c_le(crc, data, n);
+ data += n;
+ len -= n;
+ }
+ n = len & ~7U;
+ if (n) {
+ crc32c_sparc64(&crc, (const u64 *)data, n);
+ data += n;
+ len -= n;
}
if (len)
- *crcp = __crc32c_le(*crcp, (const unsigned char *) data, len);
+ crc = __crc32c_le(crc, data, len);
+ return crc;
}
static int crc32c_sparc64_update(struct shash_desc *desc, const u8 *data,
@@ -70,19 +79,14 @@ static int crc32c_sparc64_update(struct shash_desc *desc, const u8 *data,
{
u32 *crcp = shash_desc_ctx(desc);
- crc32c_compute(crcp, (const u64 *) data, len);
-
+ *crcp = crc32c_compute(*crcp, data, len);
return 0;
}
-static int __crc32c_sparc64_finup(u32 *crcp, const u8 *data, unsigned int len,
- u8 *out)
+static int __crc32c_sparc64_finup(const u32 *crcp, const u8 *data,
+ unsigned int len, u8 *out)
{
- u32 tmp = *crcp;
-
- crc32c_compute(&tmp, (const u64 *) data, len);
-
- *(__le32 *) out = ~cpu_to_le32(tmp);
+ put_unaligned_le32(~crc32c_compute(*crcp, data, len), out);
return 0;
}
@@ -96,7 +100,7 @@ static int crc32c_sparc64_final(struct shash_desc *desc, u8 *out)
{
u32 *crcp = shash_desc_ctx(desc);
- *(__le32 *) out = ~cpu_to_le32p(crcp);
+ put_unaligned_le32(~*crcp, out);
return 0;
}
@@ -135,7 +139,6 @@ static struct shash_alg alg = {
.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
.cra_blocksize = CHKSUM_BLOCK_SIZE,
.cra_ctxsize = sizeof(u32),
- .cra_alignmask = 7,
.cra_module = THIS_MODULE,
.cra_init = crc32c_sparc64_cra_init,
}
diff --git a/arch/sparc/include/asm/fb.h b/arch/sparc/include/asm/fb.h
index 572ecd3e1cc4..24440c0fda49 100644
--- a/arch/sparc/include/asm/fb.h
+++ b/arch/sparc/include/asm/fb.h
@@ -4,15 +4,18 @@
#include <linux/io.h>
+#include <asm/page.h>
+
struct fb_info;
-struct file;
-struct vm_area_struct;
#ifdef CONFIG_SPARC32
-static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
- unsigned long off)
-{ }
-#define fb_pgprotect fb_pgprotect
+static inline pgprot_t pgprot_framebuffer(pgprot_t prot,
+ unsigned long vm_start, unsigned long vm_end,
+ unsigned long offset)
+{
+ return prot;
+}
+#define pgprot_framebuffer pgprot_framebuffer
#endif
int fb_is_primary_device(struct fb_info *info);
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index 06c2bc767ef7..aec742cd898f 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -47,8 +47,6 @@ struct kprobe_ctlblk {
struct prev_kprobe prev_kprobe;
};
-int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
struct pt_regs *regs);
diff --git a/arch/sparc/kernel/cpumap.c b/arch/sparc/kernel/cpumap.c
index f07ea88a83af..8fcf2d8c6bd2 100644
--- a/arch/sparc/kernel/cpumap.c
+++ b/arch/sparc/kernel/cpumap.c
@@ -50,7 +50,7 @@ struct cpuinfo_tree {
/* Offsets into nodes[] for each level of the tree */
struct cpuinfo_level level[CPUINFO_LVL_MAX];
- struct cpuinfo_node nodes[];
+ struct cpuinfo_node nodes[] __counted_by(total_nodes);
};
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index 34ef7febf0d5..e3b72a7b46d3 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -17,7 +17,6 @@
#include <linux/initrd.h>
#include <asm/smp.h>
#include <linux/user.h>
-#include <linux/screen_info.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
@@ -51,18 +50,6 @@
#include "kernel.h"
-struct screen_info screen_info = {
- 0, 0, /* orig-x, orig-y */
- 0, /* unused */
- 0, /* orig-video-page */
- 0, /* orig-video-mode */
- 128, /* orig-video-cols */
- 0,0,0, /* ega_ax, ega_bx, ega_cx */
- 54, /* orig-video-lines */
- 0, /* orig-video-isVGA */
- 16 /* orig-video-points */
-};
-
/* Typing sync at the prom prompt calls the function pointed to by
* romvec->pv_synchook which I set to the following function.
* This should sync all filesystems and return, for now it just
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index 6546ca9d4d3f..6a4797dec34b 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -15,7 +15,6 @@
#include <linux/ptrace.h>
#include <asm/smp.h>
#include <linux/user.h>
-#include <linux/screen_info.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
@@ -68,18 +67,6 @@
DEFINE_SPINLOCK(ns87303_lock);
EXPORT_SYMBOL(ns87303_lock);
-struct screen_info screen_info = {
- 0, 0, /* orig-x, orig-y */
- 0, /* unused */
- 0, /* orig-video-page */
- 0, /* orig-video-mode */
- 128, /* orig-video-cols */
- 0, 0, 0, /* unused, ega_bx, unused */
- 54, /* orig-video-lines */
- 0, /* orig-video-isVGA */
- 16 /* orig-video-points */
-};
-
static void
prom_console_write(struct console *con, const char *s, unsigned int n)
{
diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl
index 4ed06c71c43f..7bcaa3d5ea44 100644
--- a/arch/sparc/kernel/syscalls/syscall.tbl
+++ b/arch/sparc/kernel/syscalls/syscall.tbl
@@ -249,7 +249,7 @@
205 common readahead sys_readahead compat_sys_readahead
206 common socketcall sys_socketcall sys32_socketcall
207 common syslog sys_syslog
-208 common lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie
+208 common lookup_dcookie sys_ni_syscall
209 common fadvise64 sys_fadvise64 compat_sys_fadvise64
210 common fadvise64_64 sys_fadvise64_64 compat_sys_fadvise64_64
211 common tgkill sys_tgkill
@@ -498,3 +498,7 @@
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
451 common cachestat sys_cachestat
452 common fchmodat2 sys_fchmodat2
+453 common map_shadow_stack sys_map_shadow_stack
+454 common futex_wake sys_futex_wake
+455 common futex_wait sys_futex_wait
+456 common futex_requeue sys_futex_requeue
diff --git a/arch/sparc/lib/checksum_32.S b/arch/sparc/lib/checksum_32.S
index 84ad709cbecb..66eda40fce36 100644
--- a/arch/sparc/lib/checksum_32.S
+++ b/arch/sparc/lib/checksum_32.S
@@ -453,5 +453,5 @@ ccslow: cmp %g1, 0
* we only bother with faults on loads... */
cc_fault:
- ret
+ retl
clr %o0
diff --git a/arch/sparc/vdso/Makefile b/arch/sparc/vdso/Makefile
index 77d7b9032158..d08c3a0443f3 100644
--- a/arch/sparc/vdso/Makefile
+++ b/arch/sparc/vdso/Makefile
@@ -116,30 +116,3 @@ quiet_cmd_vdso = VDSO $@
VDSO_LDFLAGS = -shared --hash-style=both --build-id=sha1 -Bsymbolic
GCOV_PROFILE := n
-
-#
-# Install the unstripped copies of vdso*.so. If our toolchain supports
-# build-id, install .build-id links as well.
-#
-quiet_cmd_vdso_install = INSTALL $(@:install_%=%)
-define cmd_vdso_install
- cp $< "$(MODLIB)/vdso/$(@:install_%=%)"; \
- if readelf -n $< |grep -q 'Build ID'; then \
- buildid=`readelf -n $< |grep 'Build ID' |sed -e 's/^.*Build ID: \(.*\)$$/\1/'`; \
- first=`echo $$buildid | cut -b-2`; \
- last=`echo $$buildid | cut -b3-`; \
- mkdir -p "$(MODLIB)/vdso/.build-id/$$first"; \
- ln -sf "../../$(@:install_%=%)" "$(MODLIB)/vdso/.build-id/$$first/$$last.debug"; \
- fi
-endef
-
-vdso_img_insttargets := $(vdso_img_sodbg:%.dbg=install_%)
-
-$(MODLIB)/vdso: FORCE
- @mkdir -p $(MODLIB)/vdso
-
-$(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso FORCE
- $(call cmd,vdso_install)
-
-PHONY += vdso_install $(vdso_img_insttargets)
-vdso_install: $(vdso_img_insttargets) FORCE
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 9483021d86dd..3363851a4ae8 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -105,7 +105,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
sprintf(data_fd_buf, "%d", data_remote);
sprintf(version_buf, "%d", UML_NET_VERSION);
if (gate != NULL) {
- strncpy(gate_buf, gate, 15);
+ strscpy(gate_buf, gate, sizeof(gate_buf));
args = setup_args;
}
else args = nosetup_args;
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 66bfabae8814..3762f41bb092 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -28,7 +28,6 @@ config X86_64
select ARCH_HAS_GIGANTIC_PAGE
select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
select ARCH_SUPPORTS_PER_VMA_LOCK
- select ARCH_USE_CMPXCHG_LOCKREF
select HAVE_ARCH_SOFT_DIRTY
select MODULES_USE_ELF_RELA
select NEED_DMA_MAP_STATE
@@ -118,6 +117,7 @@ config X86
select ARCH_SUPPORTS_LTO_CLANG
select ARCH_SUPPORTS_LTO_CLANG_THIN
select ARCH_USE_BUILTIN_BSWAP
+ select ARCH_USE_CMPXCHG_LOCKREF if X86_CMPXCHG64
select ARCH_USE_MEMTEST
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_QUEUED_SPINLOCKS
@@ -1313,16 +1313,41 @@ config MICROCODE
def_bool y
depends on CPU_SUP_AMD || CPU_SUP_INTEL
+config MICROCODE_INITRD32
+ def_bool y
+ depends on MICROCODE && X86_32 && BLK_DEV_INITRD
+
config MICROCODE_LATE_LOADING
bool "Late microcode loading (DANGEROUS)"
default n
- depends on MICROCODE
+ depends on MICROCODE && SMP
help
Loading microcode late, when the system is up and executing instructions
is a tricky business and should be avoided if possible. Just the sequence
of synchronizing all cores and SMT threads is one fragile dance which does
not guarantee that cores might not softlock after the loading. Therefore,
- use this at your own risk. Late loading taints the kernel too.
+ use this at your own risk. Late loading taints the kernel unless the
+ microcode header indicates that it is safe for late loading via the
+ minimal revision check. This minimal revision check can be enforced on
+ the kernel command line with "microcode.minrev=Y".
+
+config MICROCODE_LATE_FORCE_MINREV
+ bool "Enforce late microcode loading minimal revision check"
+ default n
+ depends on MICROCODE_LATE_LOADING
+ help
+ To prevent that users load microcode late which modifies already
+ in use features, newer microcode patches have a minimum revision field
+ in the microcode header, which tells the kernel which minimum
+ revision must be active in the CPU to safely load that new microcode
+ late into the running system. If disabled the check will not
+ be enforced but the kernel will be tainted when the minimal
+ revision check fails.
+
+ This minimal revision check can also be controlled via the
+ "microcode.minrev" parameter on the kernel command line.
+
+ If unsure say Y.
config X86_MSR
tristate "/dev/cpu/*/msr - Model-specific register support"
@@ -1534,6 +1559,7 @@ config NUMA
depends on X86_64 || (X86_32 && HIGHMEM64G && X86_BIGSMP)
default y if X86_BIGSMP
select USE_PERCPU_NUMA_NODE_ID
+ select OF_NUMA if OF
help
Enable NUMA (Non-Uniform Memory Access) support.
@@ -1939,6 +1965,18 @@ config X86_USER_SHADOW_STACK
If unsure, say N.
+config INTEL_TDX_HOST
+ bool "Intel Trust Domain Extensions (TDX) host support"
+ depends on CPU_SUP_INTEL
+ depends on X86_64
+ depends on KVM_INTEL
+ help
+ Intel Trust Domain Extensions (TDX) protects guest VMs from malicious
+ host and certain physical attacks. This option enables necessary TDX
+ support in the host kernel to run confidential VMs.
+
+ If unsure, say N.
+
config EFI
bool "EFI runtime service support"
depends on ACPI
@@ -2062,6 +2100,9 @@ config ARCH_SUPPORTS_CRASH_DUMP
config ARCH_SUPPORTS_CRASH_HOTPLUG
def_bool y
+config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
+ def_bool CRASH_CORE
+
config PHYSICAL_START
hex "Physical address where the kernel is loaded" if (EXPERT || CRASH_DUMP)
default "0x1000000"
@@ -2954,6 +2995,15 @@ config IA32_EMULATION
64-bit kernel. You should likely turn this on, unless you're
100% sure that you don't have any 32-bit programs left.
+config IA32_EMULATION_DEFAULT_DISABLED
+ bool "IA32 emulation disabled by default"
+ default n
+ depends on IA32_EMULATION
+ help
+ Make IA32 emulation disabled by default. This prevents loading 32-bit
+ processes and access to 32-bit syscalls. If unsure, leave it to its
+ default value.
+
config X86_X32_ABI
bool "x32 ABI for 64-bit mode"
depends on X86_64
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 5bfe5caaa444..1a068de12a56 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -43,7 +43,7 @@ endif
# How to compile the 16-bit code. Note we always compile for -march=i386;
# that way we can complain to the user if the CPU is insufficient.
-REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \
+REALMODE_CFLAGS := -std=gnu11 -m16 -g -Os -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \
-Wall -Wstrict-prototypes -march=i386 -mregparm=3 \
-fno-strict-aliasing -fomit-frame-pointer -fno-pic \
-mno-mmx -mno-sse $(call cc-option,-fcf-protection=none)
@@ -81,6 +81,7 @@ ifeq ($(CONFIG_X86_KERNEL_IBT),y)
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104816
#
KBUILD_CFLAGS += $(call cc-option,-fcf-protection=branch -fno-jump-tables)
+KBUILD_RUSTFLAGS += -Zcf-protection=branch -Zno-jump-tables
else
KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none)
endif
@@ -252,6 +253,8 @@ archheaders:
libs-y += arch/x86/lib/
+core-y += arch/x86/virt/
+
# drivers-y are linked after core-y
drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/
drivers-$(CONFIG_PCI) += arch/x86/pci/
@@ -291,9 +294,10 @@ PHONY += install
install:
$(call cmd,install)
-PHONY += vdso_install
-vdso_install:
- $(Q)$(MAKE) $(build)=arch/x86/entry/vdso $@
+vdso-install-$(CONFIG_X86_64) += arch/x86/entry/vdso/vdso64.so.dbg
+vdso-install-$(CONFIG_X86_X32_ABI) += arch/x86/entry/vdso/vdsox32.so.dbg
+vdso-install-$(CONFIG_X86_32) += arch/x86/entry/vdso/vdso32.so.dbg
+vdso-install-$(CONFIG_IA32_EMULATION) += arch/x86/entry/vdso/vdso32.so.dbg
archprepare: checkbin
checkbin:
diff --git a/arch/x86/Makefile.postlink b/arch/x86/Makefile.postlink
index 936093d29160..fef2e977cc7d 100644
--- a/arch/x86/Makefile.postlink
+++ b/arch/x86/Makefile.postlink
@@ -34,9 +34,6 @@ ifeq ($(CONFIG_X86_NEED_RELOCS),y)
$(call cmd,strip_relocs)
endif
-%.ko: FORCE
- @true
-
clean:
@rm -f $(OUT_RELOCS)/vmlinux.relocs
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index f33e45ed1437..3cece19b7473 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -89,7 +89,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [a-zA-Z] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|efi32_pe_entry\|input_data\|kernel_info\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [a-zA-Z] \(startup_32\|efi.._stub_entry\|efi\(32\)\?_pe_entry\|input_data\|kernel_info\|_end\|_ehead\|_text\|_e\?data\|z_.*\)$$/\#define ZO_\2 0x\1/p'
quiet_cmd_zoffset = ZOFFSET $@
cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
diff --git a/arch/x86/boot/compressed/acpi.c b/arch/x86/boot/compressed/acpi.c
index 9caf89063e77..18d15d1ce87d 100644
--- a/arch/x86/boot/compressed/acpi.c
+++ b/arch/x86/boot/compressed/acpi.c
@@ -30,13 +30,13 @@ __efi_get_rsdp_addr(unsigned long cfg_tbl_pa, unsigned int cfg_tbl_len)
* Search EFI system tables for RSDP. Preferred is ACPI_20_TABLE_GUID to
* ACPI_TABLE_GUID because it has more features.
*/
- rsdp_addr = efi_find_vendor_table(boot_params, cfg_tbl_pa, cfg_tbl_len,
+ rsdp_addr = efi_find_vendor_table(boot_params_ptr, cfg_tbl_pa, cfg_tbl_len,
ACPI_20_TABLE_GUID);
if (rsdp_addr)
return (acpi_physical_address)rsdp_addr;
/* No ACPI_20_TABLE_GUID found, fallback to ACPI_TABLE_GUID. */
- rsdp_addr = efi_find_vendor_table(boot_params, cfg_tbl_pa, cfg_tbl_len,
+ rsdp_addr = efi_find_vendor_table(boot_params_ptr, cfg_tbl_pa, cfg_tbl_len,
ACPI_TABLE_GUID);
if (rsdp_addr)
return (acpi_physical_address)rsdp_addr;
@@ -56,15 +56,15 @@ static acpi_physical_address efi_get_rsdp_addr(void)
enum efi_type et;
int ret;
- et = efi_get_type(boot_params);
+ et = efi_get_type(boot_params_ptr);
if (et == EFI_TYPE_NONE)
return 0;
- systab_pa = efi_get_system_table(boot_params);
+ systab_pa = efi_get_system_table(boot_params_ptr);
if (!systab_pa)
error("EFI support advertised, but unable to locate system table.");
- ret = efi_get_conf_table(boot_params, &cfg_tbl_pa, &cfg_tbl_len);
+ ret = efi_get_conf_table(boot_params_ptr, &cfg_tbl_pa, &cfg_tbl_len);
if (ret || !cfg_tbl_pa)
error("EFI config table not found.");
@@ -156,7 +156,7 @@ acpi_physical_address get_rsdp_addr(void)
{
acpi_physical_address pa;
- pa = boot_params->acpi_rsdp_addr;
+ pa = boot_params_ptr->acpi_rsdp_addr;
if (!pa)
pa = efi_get_rsdp_addr();
@@ -178,7 +178,7 @@ static unsigned long get_cmdline_acpi_rsdp(void)
{
unsigned long addr = 0;
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
char val[MAX_ADDR_LEN] = { };
int ret;
@@ -210,7 +210,7 @@ static unsigned long get_acpi_srat_table(void)
rsdp = (struct acpi_table_rsdp *)get_cmdline_acpi_rsdp();
if (!rsdp)
rsdp = (struct acpi_table_rsdp *)(long)
- boot_params->acpi_rsdp_addr;
+ boot_params_ptr->acpi_rsdp_addr;
if (!rsdp)
return 0;
diff --git a/arch/x86/boot/compressed/cmdline.c b/arch/x86/boot/compressed/cmdline.c
index f1add5d85da9..c1bb180973ea 100644
--- a/arch/x86/boot/compressed/cmdline.c
+++ b/arch/x86/boot/compressed/cmdline.c
@@ -14,9 +14,9 @@ static inline char rdfs8(addr_t addr)
#include "../cmdline.c"
unsigned long get_cmd_line_ptr(void)
{
- unsigned long cmd_line_ptr = boot_params->hdr.cmd_line_ptr;
+ unsigned long cmd_line_ptr = boot_params_ptr->hdr.cmd_line_ptr;
- cmd_line_ptr |= (u64)boot_params->ext_cmd_line_ptr << 32;
+ cmd_line_ptr |= (u64)boot_params_ptr->ext_cmd_line_ptr << 32;
return cmd_line_ptr;
}
diff --git a/arch/x86/boot/compressed/ident_map_64.c b/arch/x86/boot/compressed/ident_map_64.c
index 08f93b0401bb..473ba59b82a8 100644
--- a/arch/x86/boot/compressed/ident_map_64.c
+++ b/arch/x86/boot/compressed/ident_map_64.c
@@ -159,8 +159,9 @@ void initialize_identity_maps(void *rmode)
* or does not touch all the pages covering them.
*/
kernel_add_identity_map((unsigned long)_head, (unsigned long)_end);
- boot_params = rmode;
- kernel_add_identity_map((unsigned long)boot_params, (unsigned long)(boot_params + 1));
+ boot_params_ptr = rmode;
+ kernel_add_identity_map((unsigned long)boot_params_ptr,
+ (unsigned long)(boot_params_ptr + 1));
cmdline = get_cmd_line_ptr();
kernel_add_identity_map(cmdline, cmdline + COMMAND_LINE_SIZE);
@@ -168,7 +169,7 @@ void initialize_identity_maps(void *rmode)
* Also map the setup_data entries passed via boot_params in case they
* need to be accessed by uncompressed kernel via the identity mapping.
*/
- sd = (struct setup_data *)boot_params->hdr.setup_data;
+ sd = (struct setup_data *)boot_params_ptr->hdr.setup_data;
while (sd) {
unsigned long sd_addr = (unsigned long)sd;
diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index 9193acf0e9cd..dec961c6d16a 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -63,7 +63,7 @@ static unsigned long get_boot_seed(void)
unsigned long hash = 0;
hash = rotate_xor(hash, build_str, sizeof(build_str));
- hash = rotate_xor(hash, boot_params, sizeof(*boot_params));
+ hash = rotate_xor(hash, boot_params_ptr, sizeof(*boot_params_ptr));
return hash;
}
@@ -383,7 +383,7 @@ static void handle_mem_options(void)
static void mem_avoid_init(unsigned long input, unsigned long input_size,
unsigned long output)
{
- unsigned long init_size = boot_params->hdr.init_size;
+ unsigned long init_size = boot_params_ptr->hdr.init_size;
u64 initrd_start, initrd_size;
unsigned long cmd_line, cmd_line_size;
@@ -395,10 +395,10 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
mem_avoid[MEM_AVOID_ZO_RANGE].size = (output + init_size) - input;
/* Avoid initrd. */
- initrd_start = (u64)boot_params->ext_ramdisk_image << 32;
- initrd_start |= boot_params->hdr.ramdisk_image;
- initrd_size = (u64)boot_params->ext_ramdisk_size << 32;
- initrd_size |= boot_params->hdr.ramdisk_size;
+ initrd_start = (u64)boot_params_ptr->ext_ramdisk_image << 32;
+ initrd_start |= boot_params_ptr->hdr.ramdisk_image;
+ initrd_size = (u64)boot_params_ptr->ext_ramdisk_size << 32;
+ initrd_size |= boot_params_ptr->hdr.ramdisk_size;
mem_avoid[MEM_AVOID_INITRD].start = initrd_start;
mem_avoid[MEM_AVOID_INITRD].size = initrd_size;
/* No need to set mapping for initrd, it will be handled in VO. */
@@ -413,8 +413,8 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
}
/* Avoid boot parameters. */
- mem_avoid[MEM_AVOID_BOOTPARAMS].start = (unsigned long)boot_params;
- mem_avoid[MEM_AVOID_BOOTPARAMS].size = sizeof(*boot_params);
+ mem_avoid[MEM_AVOID_BOOTPARAMS].start = (unsigned long)boot_params_ptr;
+ mem_avoid[MEM_AVOID_BOOTPARAMS].size = sizeof(*boot_params_ptr);
/* We don't need to set a mapping for setup_data. */
@@ -447,7 +447,7 @@ static bool mem_avoid_overlap(struct mem_vector *img,
}
/* Avoid all entries in the setup_data linked list. */
- ptr = (struct setup_data *)(unsigned long)boot_params->hdr.setup_data;
+ ptr = (struct setup_data *)(unsigned long)boot_params_ptr->hdr.setup_data;
while (ptr) {
struct mem_vector avoid;
@@ -706,7 +706,7 @@ static inline bool memory_type_is_free(efi_memory_desc_t *md)
static bool
process_efi_entries(unsigned long minimum, unsigned long image_size)
{
- struct efi_info *e = &boot_params->efi_info;
+ struct efi_info *e = &boot_params_ptr->efi_info;
bool efi_mirror_found = false;
struct mem_vector region;
efi_memory_desc_t *md;
@@ -777,8 +777,8 @@ static void process_e820_entries(unsigned long minimum,
struct boot_e820_entry *entry;
/* Verify potential e820 positions, appending to slots list. */
- for (i = 0; i < boot_params->e820_entries; i++) {
- entry = &boot_params->e820_table[i];
+ for (i = 0; i < boot_params_ptr->e820_entries; i++) {
+ entry = &boot_params_ptr->e820_table[i];
/* Skip non-RAM entries. */
if (entry->type != E820_TYPE_RAM)
continue;
@@ -852,7 +852,7 @@ void choose_random_location(unsigned long input,
return;
}
- boot_params->hdr.loadflags |= KASLR_FLAG;
+ boot_params_ptr->hdr.loadflags |= KASLR_FLAG;
if (IS_ENABLED(CONFIG_X86_32))
mem_limit = KERNEL_IMAGE_SIZE;
diff --git a/arch/x86/boot/compressed/mem.c b/arch/x86/boot/compressed/mem.c
index 3c1609245f2a..b3c3a4be7471 100644
--- a/arch/x86/boot/compressed/mem.c
+++ b/arch/x86/boot/compressed/mem.c
@@ -54,17 +54,17 @@ bool init_unaccepted_memory(void)
enum efi_type et;
int ret;
- et = efi_get_type(boot_params);
+ et = efi_get_type(boot_params_ptr);
if (et == EFI_TYPE_NONE)
return false;
- ret = efi_get_conf_table(boot_params, &cfg_table_pa, &cfg_table_len);
+ ret = efi_get_conf_table(boot_params_ptr, &cfg_table_pa, &cfg_table_len);
if (ret) {
warn("EFI config table not found.");
return false;
}
- table = (void *)efi_find_vendor_table(boot_params, cfg_table_pa,
+ table = (void *)efi_find_vendor_table(boot_params_ptr, cfg_table_pa,
cfg_table_len, guid);
if (!table)
return false;
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index f711f2a85862..b99e08e6815b 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -46,7 +46,7 @@ void *memmove(void *dest, const void *src, size_t n);
/*
* This is set up by the setup-routine at boot-time
*/
-struct boot_params *boot_params;
+struct boot_params *boot_params_ptr;
struct port_io_ops pio_ops;
@@ -132,8 +132,8 @@ void __putstr(const char *s)
if (lines == 0 || cols == 0)
return;
- x = boot_params->screen_info.orig_x;
- y = boot_params->screen_info.orig_y;
+ x = boot_params_ptr->screen_info.orig_x;
+ y = boot_params_ptr->screen_info.orig_y;
while ((c = *s++) != '\0') {
if (c == '\n') {
@@ -154,8 +154,8 @@ void __putstr(const char *s)
}
}
- boot_params->screen_info.orig_x = x;
- boot_params->screen_info.orig_y = y;
+ boot_params_ptr->screen_info.orig_x = x;
+ boot_params_ptr->screen_info.orig_y = y;
pos = (x + cols * y) * 2; /* Update cursor position */
outb(14, vidport);
@@ -382,14 +382,14 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
size_t entry_offset;
/* Retain x86 boot parameters pointer passed from startup_32/64. */
- boot_params = rmode;
+ boot_params_ptr = rmode;
/* Clear flags intended for solely in-kernel use. */
- boot_params->hdr.loadflags &= ~KASLR_FLAG;
+ boot_params_ptr->hdr.loadflags &= ~KASLR_FLAG;
- sanitize_boot_params(boot_params);
+ sanitize_boot_params(boot_params_ptr);
- if (boot_params->screen_info.orig_video_mode == 7) {
+ if (boot_params_ptr->screen_info.orig_video_mode == 7) {
vidmem = (char *) 0xb0000;
vidport = 0x3b4;
} else {
@@ -397,8 +397,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
vidport = 0x3d4;
}
- lines = boot_params->screen_info.orig_video_lines;
- cols = boot_params->screen_info.orig_video_cols;
+ lines = boot_params_ptr->screen_info.orig_video_lines;
+ cols = boot_params_ptr->screen_info.orig_video_cols;
init_default_io_ops();
@@ -417,7 +417,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
* so that early debugging output from the RSDP parsing code can be
* collected.
*/
- boot_params->acpi_rsdp_addr = get_rsdp_addr();
+ boot_params_ptr->acpi_rsdp_addr = get_rsdp_addr();
debug_putstr("early console in extract_kernel\n");
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index cc70d3fb9049..c0d502bd8716 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -61,7 +61,6 @@ extern memptr free_mem_ptr;
extern memptr free_mem_end_ptr;
void *malloc(int size);
void free(void *where);
-extern struct boot_params *boot_params;
void __putstr(const char *s);
void __puthex(unsigned long value);
#define error_putstr(__x) __putstr(__x)
diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
index 7939eb6e6ce9..51f957b24ba7 100644
--- a/arch/x86/boot/compressed/pgtable_64.c
+++ b/arch/x86/boot/compressed/pgtable_64.c
@@ -28,7 +28,6 @@ static char trampoline_save[TRAMPOLINE_32BIT_SIZE];
*/
unsigned long *trampoline_32bit __section(".data");
-extern struct boot_params *boot_params;
int cmdline_find_option_bool(const char *option);
static unsigned long find_trampoline_placement(void)
@@ -49,7 +48,7 @@ static unsigned long find_trampoline_placement(void)
*
* Only look for values in the legacy ROM for non-EFI system.
*/
- signature = (char *)&boot_params->efi_info.efi_loader_signature;
+ signature = (char *)&boot_params_ptr->efi_info.efi_loader_signature;
if (strncmp(signature, EFI32_LOADER_SIGNATURE, 4) &&
strncmp(signature, EFI64_LOADER_SIGNATURE, 4)) {
ebda_start = *(unsigned short *)0x40e << 4;
@@ -65,10 +64,10 @@ static unsigned long find_trampoline_placement(void)
bios_start = round_down(bios_start, PAGE_SIZE);
/* Find the first usable memory region under bios_start. */
- for (i = boot_params->e820_entries - 1; i >= 0; i--) {
+ for (i = boot_params_ptr->e820_entries - 1; i >= 0; i--) {
unsigned long new = bios_start;
- entry = &boot_params->e820_table[i];
+ entry = &boot_params_ptr->e820_table[i];
/* Skip all entries above bios_start. */
if (bios_start <= entry->addr)
@@ -107,7 +106,7 @@ asmlinkage void configure_5level_paging(struct boot_params *bp, void *pgtable)
bool l5_required = false;
/* Initialize boot_params. Required for cmdline_find_option_bool(). */
- boot_params = bp;
+ boot_params_ptr = bp;
/*
* Check if LA57 is desired and supported.
diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
index dc8c876fbd8f..454acd7a2daf 100644
--- a/arch/x86/boot/compressed/sev.c
+++ b/arch/x86/boot/compressed/sev.c
@@ -25,7 +25,7 @@
#include "error.h"
#include "../msr.h"
-struct ghcb boot_ghcb_page __aligned(PAGE_SIZE);
+static struct ghcb boot_ghcb_page __aligned(PAGE_SIZE);
struct ghcb *boot_ghcb;
/*
@@ -103,6 +103,16 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt,
return ES_OK;
}
+static enum es_result vc_ioio_check(struct es_em_ctxt *ctxt, u16 port, size_t size)
+{
+ return ES_OK;
+}
+
+static bool fault_in_kernel_space(unsigned long address)
+{
+ return false;
+}
+
#undef __init
#define __init
@@ -605,7 +615,7 @@ void sev_prep_identity_maps(unsigned long top_level_pgt)
* accessed after switchover.
*/
if (sev_snp_enabled()) {
- unsigned long cc_info_pa = boot_params->cc_blob_address;
+ unsigned long cc_info_pa = boot_params_ptr->cc_blob_address;
struct cc_blob_sev_info *cc_info;
kernel_add_identity_map(cc_info_pa, cc_info_pa + sizeof(*cc_info));
diff --git a/arch/x86/boot/compressed/tdx.c b/arch/x86/boot/compressed/tdx.c
index 8841b945a1e2..8451d6a1030c 100644
--- a/arch/x86/boot/compressed/tdx.c
+++ b/arch/x86/boot/compressed/tdx.c
@@ -18,7 +18,7 @@ void __tdx_hypercall_failed(void)
static inline unsigned int tdx_io_in(int size, u16 port)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = hcall_func(EXIT_REASON_IO_INSTRUCTION),
.r12 = size,
@@ -26,7 +26,7 @@ static inline unsigned int tdx_io_in(int size, u16 port)
.r14 = port,
};
- if (__tdx_hypercall_ret(&args))
+ if (__tdx_hypercall(&args))
return UINT_MAX;
return args.r11;
@@ -34,7 +34,7 @@ static inline unsigned int tdx_io_in(int size, u16 port)
static inline void tdx_io_out(int size, u16 port, u32 value)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = hcall_func(EXIT_REASON_IO_INSTRUCTION),
.r12 = size,
diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
index b22f34b8684a..083ec6d7722a 100644
--- a/arch/x86/boot/compressed/vmlinux.lds.S
+++ b/arch/x86/boot/compressed/vmlinux.lds.S
@@ -43,11 +43,13 @@ SECTIONS
*(.rodata.*)
_erodata = . ;
}
- .data : {
+ .data : ALIGN(0x1000) {
_data = . ;
*(.data)
*(.data.*)
- *(.bss.efistub)
+
+ /* Add 4 bytes of extra space for a CRC-32 checksum */
+ . = ALIGN(. + 4, 0x200);
_edata = . ;
}
. = ALIGN(L1_CACHE_BYTES);
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index b04ca8e2b213..b2771710ed98 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -36,66 +36,20 @@ SYSSEG = 0x1000 /* historical load address >> 4 */
#define ROOT_RDONLY 1
#endif
+ .set salign, 0x1000
+ .set falign, 0x200
+
.code16
.section ".bstext", "ax"
-
- .global bootsect_start
-bootsect_start:
#ifdef CONFIG_EFI_STUB
# "MZ", MS-DOS header
.word MZ_MAGIC
-#endif
-
- # Normalize the start address
- ljmp $BOOTSEG, $start2
-
-start2:
- movw %cs, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %ss
- xorw %sp, %sp
- sti
- cld
-
- movw $bugger_off_msg, %si
-
-msg_loop:
- lodsb
- andb %al, %al
- jz bs_die
- movb $0xe, %ah
- movw $7, %bx
- int $0x10
- jmp msg_loop
-
-bs_die:
- # Allow the user to press a key, then reboot
- xorw %ax, %ax
- int $0x16
- int $0x19
-
- # int 0x19 should never return. In case it does anyway,
- # invoke the BIOS reset code...
- ljmp $0xf000,$0xfff0
-
-#ifdef CONFIG_EFI_STUB
.org 0x38
#
# Offset to the PE header.
#
.long LINUX_PE_MAGIC
.long pe_header
-#endif /* CONFIG_EFI_STUB */
-
- .section ".bsdata", "a"
-bugger_off_msg:
- .ascii "Use a boot loader.\r\n"
- .ascii "\n"
- .ascii "Remove disk and press any key to reboot...\r\n"
- .byte 0
-
-#ifdef CONFIG_EFI_STUB
pe_header:
.long PE_MAGIC
@@ -124,30 +78,26 @@ optional_header:
.byte 0x02 # MajorLinkerVersion
.byte 0x14 # MinorLinkerVersion
- # Filled in by build.c
- .long 0 # SizeOfCode
+ .long ZO__data # SizeOfCode
- .long 0 # SizeOfInitializedData
+ .long ZO__end - ZO__data # SizeOfInitializedData
.long 0 # SizeOfUninitializedData
- # Filled in by build.c
- .long 0x0000 # AddressOfEntryPoint
+ .long setup_size + ZO_efi_pe_entry # AddressOfEntryPoint
- .long 0x0200 # BaseOfCode
+ .long setup_size # BaseOfCode
#ifdef CONFIG_X86_32
.long 0 # data
#endif
extra_header_fields:
- # PE specification requires ImageBase to be 64k aligned
- .set image_base, (LOAD_PHYSICAL_ADDR + 0xffff) & ~0xffff
#ifdef CONFIG_X86_32
- .long image_base # ImageBase
+ .long 0 # ImageBase
#else
- .quad image_base # ImageBase
+ .quad 0 # ImageBase
#endif
- .long 0x20 # SectionAlignment
- .long 0x20 # FileAlignment
+ .long salign # SectionAlignment
+ .long falign # FileAlignment
.word 0 # MajorOperatingSystemVersion
.word 0 # MinorOperatingSystemVersion
.word LINUX_EFISTUB_MAJOR_VERSION # MajorImageVersion
@@ -156,12 +106,10 @@ extra_header_fields:
.word 0 # MinorSubsystemVersion
.long 0 # Win32VersionValue
- #
- # The size of the bzImage is written in tools/build.c
- #
- .long 0 # SizeOfImage
+ .long setup_size + ZO__end + pecompat_vsize
+ # SizeOfImage
- .long 0x200 # SizeOfHeaders
+ .long salign # SizeOfHeaders
.long 0 # CheckSum
.word IMAGE_SUBSYSTEM_EFI_APPLICATION # Subsystem (EFI application)
#ifdef CONFIG_EFI_DXE_MEM_ATTRIBUTES
@@ -192,87 +140,78 @@ extra_header_fields:
# Section table
section_table:
- #
- # The offset & size fields are filled in by build.c.
- #
.ascii ".setup"
.byte 0
.byte 0
- .long 0
- .long 0x0 # startup_{32,64}
- .long 0 # Size of initialized data
- # on disk
- .long 0x0 # startup_{32,64}
- .long 0 # PointerToRelocations
- .long 0 # PointerToLineNumbers
- .word 0 # NumberOfRelocations
- .word 0 # NumberOfLineNumbers
- .long IMAGE_SCN_CNT_CODE | \
- IMAGE_SCN_MEM_READ | \
- IMAGE_SCN_MEM_EXECUTE | \
- IMAGE_SCN_ALIGN_16BYTES # Characteristics
+ .long setup_size - salign # VirtualSize
+ .long salign # VirtualAddress
+ .long pecompat_fstart - salign # SizeOfRawData
+ .long salign # PointerToRawData
- #
- # The EFI application loader requires a relocation section
- # because EFI applications must be relocatable. The .reloc
- # offset & size fields are filled in by build.c.
- #
- .ascii ".reloc"
- .byte 0
- .byte 0
- .long 0
- .long 0
- .long 0 # SizeOfRawData
- .long 0 # PointerToRawData
- .long 0 # PointerToRelocations
- .long 0 # PointerToLineNumbers
- .word 0 # NumberOfRelocations
- .word 0 # NumberOfLineNumbers
+ .long 0, 0, 0
.long IMAGE_SCN_CNT_INITIALIZED_DATA | \
IMAGE_SCN_MEM_READ | \
- IMAGE_SCN_MEM_DISCARDABLE | \
- IMAGE_SCN_ALIGN_1BYTES # Characteristics
+ IMAGE_SCN_MEM_DISCARDABLE # Characteristics
#ifdef CONFIG_EFI_MIXED
- #
- # The offset & size fields are filled in by build.c.
- #
.asciz ".compat"
- .long 0
- .long 0x0
- .long 0 # Size of initialized data
- # on disk
- .long 0x0
- .long 0 # PointerToRelocations
- .long 0 # PointerToLineNumbers
- .word 0 # NumberOfRelocations
- .word 0 # NumberOfLineNumbers
+
+ .long 8 # VirtualSize
+ .long setup_size + ZO__end # VirtualAddress
+ .long pecompat_fsize # SizeOfRawData
+ .long pecompat_fstart # PointerToRawData
+
+ .long 0, 0, 0
.long IMAGE_SCN_CNT_INITIALIZED_DATA | \
IMAGE_SCN_MEM_READ | \
- IMAGE_SCN_MEM_DISCARDABLE | \
- IMAGE_SCN_ALIGN_1BYTES # Characteristics
+ IMAGE_SCN_MEM_DISCARDABLE # Characteristics
+
+ /*
+ * Put the IA-32 machine type and the associated entry point address in
+ * the .compat section, so loaders can figure out which other execution
+ * modes this image supports.
+ */
+ .pushsection ".pecompat", "a", @progbits
+ .balign falign
+ .set pecompat_vsize, salign
+ .globl pecompat_fstart
+pecompat_fstart:
+ .byte 0x1 # Version
+ .byte 8 # Size
+ .word IMAGE_FILE_MACHINE_I386 # PE machine type
+ .long setup_size + ZO_efi32_pe_entry # Entrypoint
+ .popsection
+#else
+ .set pecompat_vsize, 0
+ .set pecompat_fstart, setup_size
#endif
-
- #
- # The offset & size fields are filled in by build.c.
- #
.ascii ".text"
.byte 0
.byte 0
.byte 0
- .long 0
- .long 0x0 # startup_{32,64}
- .long 0 # Size of initialized data
+ .long ZO__data
+ .long setup_size
+ .long ZO__data # Size of initialized data
# on disk
- .long 0x0 # startup_{32,64}
+ .long setup_size
.long 0 # PointerToRelocations
.long 0 # PointerToLineNumbers
.word 0 # NumberOfRelocations
.word 0 # NumberOfLineNumbers
.long IMAGE_SCN_CNT_CODE | \
IMAGE_SCN_MEM_READ | \
- IMAGE_SCN_MEM_EXECUTE | \
- IMAGE_SCN_ALIGN_16BYTES # Characteristics
+ IMAGE_SCN_MEM_EXECUTE # Characteristics
+
+ .ascii ".data\0\0\0"
+ .long ZO__end - ZO__data # VirtualSize
+ .long setup_size + ZO__data # VirtualAddress
+ .long ZO__edata - ZO__data # SizeOfRawData
+ .long setup_size + ZO__data # PointerToRawData
+
+ .long 0, 0, 0
+ .long IMAGE_SCN_CNT_INITIALIZED_DATA | \
+ IMAGE_SCN_MEM_READ | \
+ IMAGE_SCN_MEM_WRITE # Characteristics
.set section_count, (. - section_table) / 40
#endif /* CONFIG_EFI_STUB */
@@ -286,12 +225,12 @@ sentinel: .byte 0xff, 0xff /* Used to detect broken loaders */
.globl hdr
hdr:
-setup_sects: .byte 0 /* Filled in by build.c */
+ .byte setup_sects - 1
root_flags: .word ROOT_RDONLY
-syssize: .long 0 /* Filled in by build.c */
+syssize: .long ZO__edata / 16
ram_size: .word 0 /* Obsolete */
vid_mode: .word SVGA_MODE
-root_dev: .word 0 /* Filled in by build.c */
+root_dev: .word 0 /* Default to major/minor 0/0 */
boot_flag: .word 0xAA55
# offset 512, entry point
@@ -579,9 +518,25 @@ pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr
# define INIT_SIZE VO_INIT_SIZE
#endif
+ .macro __handover_offset
+#ifndef CONFIG_EFI_HANDOVER_PROTOCOL
+ .long 0
+#elif !defined(CONFIG_X86_64)
+ .long ZO_efi32_stub_entry
+#else
+ /* Yes, this is really how we defined it :( */
+ .long ZO_efi64_stub_entry - 0x200
+#ifdef CONFIG_EFI_MIXED
+ .if ZO_efi32_stub_entry != ZO_efi64_stub_entry - 0x200
+ .error "32-bit and 64-bit EFI entry points do not match"
+ .endif
+#endif
+#endif
+ .endm
+
init_size: .long INIT_SIZE # kernel initialization size
-handover_offset: .long 0 # Filled in by build.c
-kernel_info_offset: .long 0 # Filled in by build.c
+handover_offset: __handover_offset
+kernel_info_offset: .long ZO_kernel_info
# End of setup header #####################################################
diff --git a/arch/x86/boot/setup.ld b/arch/x86/boot/setup.ld
index 49546c247ae2..83bb7efad8ae 100644
--- a/arch/x86/boot/setup.ld
+++ b/arch/x86/boot/setup.ld
@@ -10,10 +10,11 @@ ENTRY(_start)
SECTIONS
{
. = 0;
- .bstext : { *(.bstext) }
- .bsdata : { *(.bsdata) }
+ .bstext : {
+ *(.bstext)
+ . = 495;
+ } =0xffffffff
- . = 495;
.header : { *(.header) }
.entrytext : { *(.entrytext) }
.inittext : { *(.inittext) }
@@ -35,11 +36,16 @@ SECTIONS
. = ALIGN(16);
.data : { *(.data*) }
+ .pecompat : { *(.pecompat) }
+ PROVIDE(pecompat_fsize = setup_size - pecompat_fstart);
+
.signature : {
setup_sig = .;
LONG(0x5a5aaa55)
- }
+ setup_size = ALIGN(ABSOLUTE(.), 4096);
+ setup_sects = ABSOLUTE(setup_size / 512);
+ }
. = ALIGN(16);
.bss :
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index bd247692b701..10311d77c67f 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -40,10 +40,6 @@ typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
-#define DEFAULT_MAJOR_ROOT 0
-#define DEFAULT_MINOR_ROOT 0
-#define DEFAULT_ROOT_DEV (DEFAULT_MAJOR_ROOT << 8 | DEFAULT_MINOR_ROOT)
-
/* Minimal number of setup sectors */
#define SETUP_SECT_MIN 5
#define SETUP_SECT_MAX 64
@@ -51,22 +47,7 @@ typedef unsigned int u32;
/* This must be large enough to hold the entire setup */
u8 buf[SETUP_SECT_MAX*512];
-#define PECOFF_RELOC_RESERVE 0x20
-
-#ifdef CONFIG_EFI_MIXED
-#define PECOFF_COMPAT_RESERVE 0x20
-#else
-#define PECOFF_COMPAT_RESERVE 0x0
-#endif
-
-static unsigned long efi32_stub_entry;
-static unsigned long efi64_stub_entry;
-static unsigned long efi_pe_entry;
-static unsigned long efi32_pe_entry;
-static unsigned long kernel_info;
-static unsigned long startup_64;
-static unsigned long _ehead;
-static unsigned long _end;
+static unsigned long _edata;
/*----------------------------------------------------------------------*/
@@ -152,180 +133,6 @@ static void usage(void)
die("Usage: build setup system zoffset.h image");
}
-#ifdef CONFIG_EFI_STUB
-
-static void update_pecoff_section_header_fields(char *section_name, u32 vma, u32 size, u32 datasz, u32 offset)
-{
- unsigned int pe_header;
- unsigned short num_sections;
- u8 *section;
-
- pe_header = get_unaligned_le32(&buf[0x3c]);
- num_sections = get_unaligned_le16(&buf[pe_header + 6]);
-
-#ifdef CONFIG_X86_32
- section = &buf[pe_header + 0xa8];
-#else
- section = &buf[pe_header + 0xb8];
-#endif
-
- while (num_sections > 0) {
- if (strncmp((char*)section, section_name, 8) == 0) {
- /* section header size field */
- put_unaligned_le32(size, section + 0x8);
-
- /* section header vma field */
- put_unaligned_le32(vma, section + 0xc);
-
- /* section header 'size of initialised data' field */
- put_unaligned_le32(datasz, section + 0x10);
-
- /* section header 'file offset' field */
- put_unaligned_le32(offset, section + 0x14);
-
- break;
- }
- section += 0x28;
- num_sections--;
- }
-}
-
-static void update_pecoff_section_header(char *section_name, u32 offset, u32 size)
-{
- update_pecoff_section_header_fields(section_name, offset, size, size, offset);
-}
-
-static void update_pecoff_setup_and_reloc(unsigned int size)
-{
- u32 setup_offset = 0x200;
- u32 reloc_offset = size - PECOFF_RELOC_RESERVE - PECOFF_COMPAT_RESERVE;
-#ifdef CONFIG_EFI_MIXED
- u32 compat_offset = reloc_offset + PECOFF_RELOC_RESERVE;
-#endif
- u32 setup_size = reloc_offset - setup_offset;
-
- update_pecoff_section_header(".setup", setup_offset, setup_size);
- update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE);
-
- /*
- * Modify .reloc section contents with a single entry. The
- * relocation is applied to offset 10 of the relocation section.
- */
- put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
- put_unaligned_le32(10, &buf[reloc_offset + 4]);
-
-#ifdef CONFIG_EFI_MIXED
- update_pecoff_section_header(".compat", compat_offset, PECOFF_COMPAT_RESERVE);
-
- /*
- * Put the IA-32 machine type (0x14c) and the associated entry point
- * address in the .compat section, so loaders can figure out which other
- * execution modes this image supports.
- */
- buf[compat_offset] = 0x1;
- buf[compat_offset + 1] = 0x8;
- put_unaligned_le16(0x14c, &buf[compat_offset + 2]);
- put_unaligned_le32(efi32_pe_entry + size, &buf[compat_offset + 4]);
-#endif
-}
-
-static void update_pecoff_text(unsigned int text_start, unsigned int file_sz,
- unsigned int init_sz)
-{
- unsigned int pe_header;
- unsigned int text_sz = file_sz - text_start;
- unsigned int bss_sz = init_sz - file_sz;
-
- pe_header = get_unaligned_le32(&buf[0x3c]);
-
- /*
- * The PE/COFF loader may load the image at an address which is
- * misaligned with respect to the kernel_alignment field in the setup
- * header.
- *
- * In order to avoid relocating the kernel to correct the misalignment,
- * add slack to allow the buffer to be aligned within the declared size
- * of the image.
- */
- bss_sz += CONFIG_PHYSICAL_ALIGN;
- init_sz += CONFIG_PHYSICAL_ALIGN;
-
- /*
- * Size of code: Subtract the size of the first sector (512 bytes)
- * which includes the header.
- */
- put_unaligned_le32(file_sz - 512 + bss_sz, &buf[pe_header + 0x1c]);
-
- /* Size of image */
- put_unaligned_le32(init_sz, &buf[pe_header + 0x50]);
-
- /*
- * Address of entry point for PE/COFF executable
- */
- put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
-
- update_pecoff_section_header_fields(".text", text_start, text_sz + bss_sz,
- text_sz, text_start);
-}
-
-static int reserve_pecoff_reloc_section(int c)
-{
- /* Reserve 0x20 bytes for .reloc section */
- memset(buf+c, 0, PECOFF_RELOC_RESERVE);
- return PECOFF_RELOC_RESERVE;
-}
-
-static void efi_stub_defaults(void)
-{
- /* Defaults for old kernel */
-#ifdef CONFIG_X86_32
- efi_pe_entry = 0x10;
-#else
- efi_pe_entry = 0x210;
- startup_64 = 0x200;
-#endif
-}
-
-static void efi_stub_entry_update(void)
-{
- unsigned long addr = efi32_stub_entry;
-
-#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
-#ifdef CONFIG_X86_64
- /* Yes, this is really how we defined it :( */
- addr = efi64_stub_entry - 0x200;
-#endif
-
-#ifdef CONFIG_EFI_MIXED
- if (efi32_stub_entry != addr)
- die("32-bit and 64-bit EFI entry points do not match\n");
-#endif
-#endif
- put_unaligned_le32(addr, &buf[0x264]);
-}
-
-#else
-
-static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
-static inline void update_pecoff_text(unsigned int text_start,
- unsigned int file_sz,
- unsigned int init_sz) {}
-static inline void efi_stub_defaults(void) {}
-static inline void efi_stub_entry_update(void) {}
-
-static inline int reserve_pecoff_reloc_section(int c)
-{
- return 0;
-}
-#endif /* CONFIG_EFI_STUB */
-
-static int reserve_pecoff_compat_section(int c)
-{
- /* Reserve 0x20 bytes for .compat section */
- memset(buf+c, 0, PECOFF_COMPAT_RESERVE);
- return PECOFF_COMPAT_RESERVE;
-}
-
/*
* Parse zoffset.h and find the entry points. We could just #include zoffset.h
* but that would mean tools/build would have to be rebuilt every time. It's
@@ -354,14 +161,7 @@ static void parse_zoffset(char *fname)
p = (char *)buf;
while (p && *p) {
- PARSE_ZOFS(p, efi32_stub_entry);
- PARSE_ZOFS(p, efi64_stub_entry);
- PARSE_ZOFS(p, efi_pe_entry);
- PARSE_ZOFS(p, efi32_pe_entry);
- PARSE_ZOFS(p, kernel_info);
- PARSE_ZOFS(p, startup_64);
- PARSE_ZOFS(p, _ehead);
- PARSE_ZOFS(p, _end);
+ PARSE_ZOFS(p, _edata);
p = strchr(p, '\n');
while (p && (*p == '\r' || *p == '\n'))
@@ -371,17 +171,14 @@ static void parse_zoffset(char *fname)
int main(int argc, char ** argv)
{
- unsigned int i, sz, setup_sectors, init_sz;
+ unsigned int i, sz, setup_sectors;
int c;
- u32 sys_size;
struct stat sb;
FILE *file, *dest;
int fd;
void *kernel;
u32 crc = 0xffffffffUL;
- efi_stub_defaults();
-
if (argc != 5)
usage();
parse_zoffset(argv[3]);
@@ -403,72 +200,27 @@ int main(int argc, char ** argv)
die("Boot block hasn't got boot flag (0xAA55)");
fclose(file);
- c += reserve_pecoff_compat_section(c);
- c += reserve_pecoff_reloc_section(c);
-
/* Pad unused space with zeros */
- setup_sectors = (c + 511) / 512;
+ setup_sectors = (c + 4095) / 4096;
+ setup_sectors *= 8;
if (setup_sectors < SETUP_SECT_MIN)
setup_sectors = SETUP_SECT_MIN;
i = setup_sectors*512;
memset(buf+c, 0, i-c);
- update_pecoff_setup_and_reloc(i);
-
- /* Set the default root device */
- put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
-
/* Open and stat the kernel file */
fd = open(argv[2], O_RDONLY);
if (fd < 0)
die("Unable to open `%s': %m", argv[2]);
if (fstat(fd, &sb))
die("Unable to stat `%s': %m", argv[2]);
- sz = sb.st_size;
+ if (_edata != sb.st_size)
+ die("Unexpected file size `%s': %u != %u", argv[2], _edata,
+ sb.st_size);
+ sz = _edata - 4;
kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
if (kernel == MAP_FAILED)
die("Unable to mmap '%s': %m", argv[2]);
- /* Number of 16-byte paragraphs, including space for a 4-byte CRC */
- sys_size = (sz + 15 + 4) / 16;
-#ifdef CONFIG_EFI_STUB
- /*
- * COFF requires minimum 32-byte alignment of sections, and
- * adding a signature is problematic without that alignment.
- */
- sys_size = (sys_size + 1) & ~1;
-#endif
-
- /* Patch the setup code with the appropriate size parameters */
- buf[0x1f1] = setup_sectors-1;
- put_unaligned_le32(sys_size, &buf[0x1f4]);
-
- init_sz = get_unaligned_le32(&buf[0x260]);
-#ifdef CONFIG_EFI_STUB
- /*
- * The decompression buffer will start at ImageBase. When relocating
- * the compressed kernel to its end, we must ensure that the head
- * section does not get overwritten. The head section occupies
- * [i, i + _ehead), and the destination is [init_sz - _end, init_sz).
- *
- * At present these should never overlap, because 'i' is at most 32k
- * because of SETUP_SECT_MAX, '_ehead' is less than 1k, and the
- * calculation of INIT_SIZE in boot/header.S ensures that
- * 'init_sz - _end' is at least 64k.
- *
- * For future-proofing, increase init_sz if necessary.
- */
-
- if (init_sz - _end < i + _ehead) {
- init_sz = (i + _ehead + _end + 4095) & ~4095;
- put_unaligned_le32(init_sz, &buf[0x260]);
- }
-#endif
- update_pecoff_text(setup_sectors * 512, i + (sys_size * 16), init_sz);
-
- efi_stub_entry_update();
-
- /* Update kernel_info offset. */
- put_unaligned_le32(kernel_info, &buf[0x268]);
crc = partial_crc32(buf, i, crc);
if (fwrite(buf, 1, i, dest) != i)
@@ -479,13 +231,6 @@ int main(int argc, char ** argv)
if (fwrite(kernel, 1, sz, dest) != sz)
die("Writing kernel failed");
- /* Add padding leaving 4 bytes for the checksum */
- while (sz++ < (sys_size*16) - 4) {
- crc = partial_crc32_one('\0', crc);
- if (fwrite("\0", 1, 1, dest) != 1)
- die("Writing padding failed");
- }
-
/* Write the CRC */
put_unaligned_le32(crc, buf);
if (fwrite(buf, 1, 4, dest) != 4)
diff --git a/arch/x86/coco/tdx/tdcall.S b/arch/x86/coco/tdx/tdcall.S
index b193c0a1d8db..52d9786da308 100644
--- a/arch/x86/coco/tdx/tdcall.S
+++ b/arch/x86/coco/tdx/tdcall.S
@@ -1,239 +1,63 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <asm/asm-offsets.h>
#include <asm/asm.h>
-#include <asm/frame.h>
-#include <asm/unwind_hints.h>
#include <linux/linkage.h>
-#include <linux/bits.h>
#include <linux/errno.h>
#include "../../virt/vmx/tdx/tdxcall.S"
-/*
- * Bitmasks of exposed registers (with VMM).
- */
-#define TDX_RDX BIT(2)
-#define TDX_RBX BIT(3)
-#define TDX_RSI BIT(6)
-#define TDX_RDI BIT(7)
-#define TDX_R8 BIT(8)
-#define TDX_R9 BIT(9)
-#define TDX_R10 BIT(10)
-#define TDX_R11 BIT(11)
-#define TDX_R12 BIT(12)
-#define TDX_R13 BIT(13)
-#define TDX_R14 BIT(14)
-#define TDX_R15 BIT(15)
-
-/*
- * These registers are clobbered to hold arguments for each
- * TDVMCALL. They are safe to expose to the VMM.
- * Each bit in this mask represents a register ID. Bit field
- * details can be found in TDX GHCI specification, section
- * titled "TDCALL [TDG.VP.VMCALL] leaf".
- */
-#define TDVMCALL_EXPOSE_REGS_MASK \
- ( TDX_RDX | TDX_RBX | TDX_RSI | TDX_RDI | TDX_R8 | TDX_R9 | \
- TDX_R10 | TDX_R11 | TDX_R12 | TDX_R13 | TDX_R14 | TDX_R15 )
-
.section .noinstr.text, "ax"
/*
- * __tdx_module_call() - Used by TDX guests to request services from
- * the TDX module (does not include VMM services) using TDCALL instruction.
- *
- * Transforms function call register arguments into the TDCALL register ABI.
- * After TDCALL operation, TDX module output is saved in @out (if it is
- * provided by the user).
- *
- *-------------------------------------------------------------------------
- * TDCALL ABI:
- *-------------------------------------------------------------------------
- * Input Registers:
- *
- * RAX - TDCALL Leaf number.
- * RCX,RDX,R8-R9 - TDCALL Leaf specific input registers.
- *
- * Output Registers:
+ * __tdcall() - Used by TDX guests to request services from the TDX
+ * module (does not include VMM services) using TDCALL instruction.
*
- * RAX - TDCALL instruction error code.
- * RCX,RDX,R8-R11 - TDCALL Leaf specific output registers.
+ * __tdcall() function ABI:
*
- *-------------------------------------------------------------------------
+ * @fn (RDI) - TDCALL Leaf ID, moved to RAX
+ * @args (RSI) - struct tdx_module_args for input
*
- * __tdx_module_call() function ABI:
- *
- * @fn (RDI) - TDCALL Leaf ID, moved to RAX
- * @rcx (RSI) - Input parameter 1, moved to RCX
- * @rdx (RDX) - Input parameter 2, moved to RDX
- * @r8 (RCX) - Input parameter 3, moved to R8
- * @r9 (R8) - Input parameter 4, moved to R9
- *
- * @out (R9) - struct tdx_module_output pointer
- * stored temporarily in R12 (not
- * shared with the TDX module). It
- * can be NULL.
+ * Only RCX/RDX/R8-R11 are used as input registers.
*
* Return status of TDCALL via RAX.
*/
-SYM_FUNC_START(__tdx_module_call)
- FRAME_BEGIN
+SYM_FUNC_START(__tdcall)
TDX_MODULE_CALL host=0
- FRAME_END
- RET
-SYM_FUNC_END(__tdx_module_call)
+SYM_FUNC_END(__tdcall)
/*
- * TDX_HYPERCALL - Make hypercalls to a TDX VMM using TDVMCALL leaf of TDCALL
- * instruction
- *
- * Transforms values in function call argument struct tdx_hypercall_args @args
- * into the TDCALL register ABI. After TDCALL operation, VMM output is saved
- * back in @args, if \ret is 1.
- *
- *-------------------------------------------------------------------------
- * TD VMCALL ABI:
- *-------------------------------------------------------------------------
- *
- * Input Registers:
+ * __tdcall_ret() - Used by TDX guests to request services from the TDX
+ * module (does not include VMM services) using TDCALL instruction, with
+ * saving output registers to the 'struct tdx_module_args' used as input.
*
- * RAX - TDCALL instruction leaf number (0 - TDG.VP.VMCALL)
- * RCX - BITMAP which controls which part of TD Guest GPR
- * is passed as-is to the VMM and back.
- * R10 - Set 0 to indicate TDCALL follows standard TDX ABI
- * specification. Non zero value indicates vendor
- * specific ABI.
- * R11 - VMCALL sub function number
- * RBX, RDX, RDI, RSI - Used to pass VMCALL sub function specific arguments.
- * R8-R9, R12-R15 - Same as above.
+ * __tdcall_ret() function ABI:
*
- * Output Registers:
+ * @fn (RDI) - TDCALL Leaf ID, moved to RAX
+ * @args (RSI) - struct tdx_module_args for input and output
*
- * RAX - TDCALL instruction status (Not related to hypercall
- * output).
- * RBX, RDX, RDI, RSI - Hypercall sub function specific output values.
- * R8-R15 - Same as above.
+ * Only RCX/RDX/R8-R11 are used as input/output registers.
*
+ * Return status of TDCALL via RAX.
*/
-.macro TDX_HYPERCALL ret:req
- FRAME_BEGIN
-
- /* Save callee-saved GPRs as mandated by the x86_64 ABI */
- push %r15
- push %r14
- push %r13
- push %r12
- push %rbx
-
- /* Free RDI to be used as TDVMCALL arguments */
- movq %rdi, %rax
-
- /* Copy hypercall registers from arg struct: */
- movq TDX_HYPERCALL_r8(%rax), %r8
- movq TDX_HYPERCALL_r9(%rax), %r9
- movq TDX_HYPERCALL_r10(%rax), %r10
- movq TDX_HYPERCALL_r11(%rax), %r11
- movq TDX_HYPERCALL_r12(%rax), %r12
- movq TDX_HYPERCALL_r13(%rax), %r13
- movq TDX_HYPERCALL_r14(%rax), %r14
- movq TDX_HYPERCALL_r15(%rax), %r15
- movq TDX_HYPERCALL_rdi(%rax), %rdi
- movq TDX_HYPERCALL_rsi(%rax), %rsi
- movq TDX_HYPERCALL_rbx(%rax), %rbx
- movq TDX_HYPERCALL_rdx(%rax), %rdx
-
- push %rax
-
- /* Mangle function call ABI into TDCALL ABI: */
- /* Set TDCALL leaf ID (TDVMCALL (0)) in RAX */
- xor %eax, %eax
-
- movl $TDVMCALL_EXPOSE_REGS_MASK, %ecx
-
- tdcall
-
- /*
- * RAX!=0 indicates a failure of the TDVMCALL mechanism itself and that
- * something has gone horribly wrong with the TDX module.
- *
- * The return status of the hypercall operation is in a separate
- * register (in R10). Hypercall errors are a part of normal operation
- * and are handled by callers.
- */
- testq %rax, %rax
- jne .Lpanic\@
-
- pop %rax
-
- .if \ret
- movq %r8, TDX_HYPERCALL_r8(%rax)
- movq %r9, TDX_HYPERCALL_r9(%rax)
- movq %r10, TDX_HYPERCALL_r10(%rax)
- movq %r11, TDX_HYPERCALL_r11(%rax)
- movq %r12, TDX_HYPERCALL_r12(%rax)
- movq %r13, TDX_HYPERCALL_r13(%rax)
- movq %r14, TDX_HYPERCALL_r14(%rax)
- movq %r15, TDX_HYPERCALL_r15(%rax)
- movq %rdi, TDX_HYPERCALL_rdi(%rax)
- movq %rsi, TDX_HYPERCALL_rsi(%rax)
- movq %rbx, TDX_HYPERCALL_rbx(%rax)
- movq %rdx, TDX_HYPERCALL_rdx(%rax)
- .endif
-
- /* TDVMCALL leaf return code is in R10 */
- movq %r10, %rax
-
- /*
- * Zero out registers exposed to the VMM to avoid speculative execution
- * with VMM-controlled values. This needs to include all registers
- * present in TDVMCALL_EXPOSE_REGS_MASK, except RBX, and R12-R15 which
- * will be restored.
- */
- xor %r8d, %r8d
- xor %r9d, %r9d
- xor %r10d, %r10d
- xor %r11d, %r11d
- xor %rdi, %rdi
- xor %rdx, %rdx
-
- /* Restore callee-saved GPRs as mandated by the x86_64 ABI */
- pop %rbx
- pop %r12
- pop %r13
- pop %r14
- pop %r15
-
- FRAME_END
-
- RET
-.Lpanic\@:
- call __tdx_hypercall_failed
- /* __tdx_hypercall_failed never returns */
- REACHABLE
- jmp .Lpanic\@
-.endm
+SYM_FUNC_START(__tdcall_ret)
+ TDX_MODULE_CALL host=0 ret=1
+SYM_FUNC_END(__tdcall_ret)
/*
+ * __tdcall_saved_ret() - Used by TDX guests to request services from the
+ * TDX module (including VMM services) using TDCALL instruction, with
+ * saving output registers to the 'struct tdx_module_args' used as input.
*
- * __tdx_hypercall() function ABI:
- *
- * @args (RDI) - struct tdx_hypercall_args for input
- *
- * On successful completion, return the hypercall error code.
- */
-SYM_FUNC_START(__tdx_hypercall)
- TDX_HYPERCALL ret=0
-SYM_FUNC_END(__tdx_hypercall)
-
-/*
+ * __tdcall_saved_ret() function ABI:
*
- * __tdx_hypercall_ret() function ABI:
+ * @fn (RDI) - TDCALL leaf ID, moved to RAX
+ * @args (RSI) - struct tdx_module_args for input/output
*
- * @args (RDI) - struct tdx_hypercall_args for input and output
+ * All registers in @args are used as input/output registers.
*
* On successful completion, return the hypercall error code.
*/
-SYM_FUNC_START(__tdx_hypercall_ret)
- TDX_HYPERCALL ret=1
-SYM_FUNC_END(__tdx_hypercall_ret)
+SYM_FUNC_START(__tdcall_saved_ret)
+ TDX_MODULE_CALL host=0 ret=1 saved=1
+SYM_FUNC_END(__tdcall_saved_ret)
diff --git a/arch/x86/coco/tdx/tdx-shared.c b/arch/x86/coco/tdx/tdx-shared.c
index ef20ddc37b58..78e413269791 100644
--- a/arch/x86/coco/tdx/tdx-shared.c
+++ b/arch/x86/coco/tdx/tdx-shared.c
@@ -5,7 +5,7 @@ static unsigned long try_accept_one(phys_addr_t start, unsigned long len,
enum pg_level pg_level)
{
unsigned long accept_size = page_level_size(pg_level);
- u64 tdcall_rcx;
+ struct tdx_module_args args = {};
u8 page_size;
if (!IS_ALIGNED(start, accept_size))
@@ -34,8 +34,8 @@ static unsigned long try_accept_one(phys_addr_t start, unsigned long len,
return 0;
}
- tdcall_rcx = start | page_size;
- if (__tdx_module_call(TDX_ACCEPT_PAGE, tdcall_rcx, 0, 0, 0, NULL))
+ args.rcx = start | page_size;
+ if (__tdcall(TDG_MEM_PAGE_ACCEPT, &args))
return 0;
return accept_size;
@@ -45,7 +45,7 @@ bool tdx_accept_memory(phys_addr_t start, phys_addr_t end)
{
/*
* For shared->private conversion, accept the page using
- * TDX_ACCEPT_PAGE TDX module call.
+ * TDG_MEM_PAGE_ACCEPT TDX module call.
*/
while (start < end) {
unsigned long len = end - start;
@@ -69,3 +69,23 @@ bool tdx_accept_memory(phys_addr_t start, phys_addr_t end)
return true;
}
+
+noinstr u64 __tdx_hypercall(struct tdx_module_args *args)
+{
+ /*
+ * For TDVMCALL explicitly set RCX to the bitmap of shared registers.
+ * The caller isn't expected to set @args->rcx anyway.
+ */
+ args->rcx = TDVMCALL_EXPOSE_REGS_MASK;
+
+ /*
+ * Failure of __tdcall_saved_ret() indicates a failure of the TDVMCALL
+ * mechanism itself and that something has gone horribly wrong with
+ * the TDX module. __tdx_hypercall_failed() never returns.
+ */
+ if (__tdcall_saved_ret(TDG_VP_VMCALL, args))
+ __tdx_hypercall_failed();
+
+ /* TDVMCALL leaf return code is in R10 */
+ return args->r10;
+}
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index 1d6b863c42b0..cf1f13c82175 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -10,6 +10,7 @@
#include <asm/coco.h>
#include <asm/tdx.h>
#include <asm/vmx.h>
+#include <asm/ia32.h>
#include <asm/insn.h>
#include <asm/insn-eval.h>
#include <asm/pgtable.h>
@@ -38,7 +39,7 @@
#define TDREPORT_SUBTYPE_0 0
/* Called from __tdx_hypercall() for unrecoverable failure */
-noinstr void __tdx_hypercall_failed(void)
+noinstr void __noreturn __tdx_hypercall_failed(void)
{
instrumentation_begin();
panic("TDVMCALL failed. TDX module bug?");
@@ -48,7 +49,7 @@ noinstr void __tdx_hypercall_failed(void)
long tdx_kvm_hypercall(unsigned int nr, unsigned long p1, unsigned long p2,
unsigned long p3, unsigned long p4)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = nr,
.r11 = p1,
.r12 = p2,
@@ -66,10 +67,9 @@ EXPORT_SYMBOL_GPL(tdx_kvm_hypercall);
* should only be used for calls that have no legitimate reason to fail
* or where the kernel can not survive the call failing.
*/
-static inline void tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
- struct tdx_module_output *out)
+static inline void tdcall(u64 fn, struct tdx_module_args *args)
{
- if (__tdx_module_call(fn, rcx, rdx, r8, r9, out))
+ if (__tdcall_ret(fn, args))
panic("TDCALL %lld failed (Buggy TDX module!)\n", fn);
}
@@ -89,11 +89,14 @@ static inline void tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
*/
int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport)
{
+ struct tdx_module_args args = {
+ .rcx = virt_to_phys(tdreport),
+ .rdx = virt_to_phys(reportdata),
+ .r8 = TDREPORT_SUBTYPE_0,
+ };
u64 ret;
- ret = __tdx_module_call(TDX_GET_REPORT, virt_to_phys(tdreport),
- virt_to_phys(reportdata), TDREPORT_SUBTYPE_0,
- 0, NULL);
+ ret = __tdcall(TDG_MR_REPORT, &args);
if (ret) {
if (TDCALL_RETURN_CODE(ret) == TDCALL_INVALID_OPERAND)
return -EINVAL;
@@ -104,9 +107,30 @@ int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport)
}
EXPORT_SYMBOL_GPL(tdx_mcall_get_report0);
+/**
+ * tdx_hcall_get_quote() - Wrapper to request TD Quote using GetQuote
+ * hypercall.
+ * @buf: Address of the directly mapped shared kernel buffer which
+ * contains TDREPORT. The same buffer will be used by VMM to
+ * store the generated TD Quote output.
+ * @size: size of the tdquote buffer (4KB-aligned).
+ *
+ * Refer to section titled "TDG.VP.VMCALL<GetQuote>" in the TDX GHCI
+ * v1.0 specification for more information on GetQuote hypercall.
+ * It is used in the TDX guest driver module to get the TD Quote.
+ *
+ * Return 0 on success or error code on failure.
+ */
+u64 tdx_hcall_get_quote(u8 *buf, size_t size)
+{
+ /* Since buf is a shared memory, set the shared (decrypted) bits */
+ return _tdx_hypercall(TDVMCALL_GET_QUOTE, cc_mkdec(virt_to_phys(buf)), size, 0, 0);
+}
+EXPORT_SYMBOL_GPL(tdx_hcall_get_quote);
+
static void __noreturn tdx_panic(const char *msg)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = TDVMCALL_REPORT_FATAL_ERROR,
.r12 = 0, /* Error code: 0 is Panic */
@@ -119,7 +143,7 @@ static void __noreturn tdx_panic(const char *msg)
} message;
/* VMM assumes '\0' in byte 65, if the message took all 64 bytes */
- strncpy(message.str, msg, 64);
+ strtomem_pad(message.str, msg, '\0');
args.r8 = message.r8;
args.r9 = message.r9;
@@ -141,7 +165,7 @@ static void __noreturn tdx_panic(const char *msg)
static void tdx_parse_tdinfo(u64 *cc_mask)
{
- struct tdx_module_output out;
+ struct tdx_module_args args = {};
unsigned int gpa_width;
u64 td_attr;
@@ -152,7 +176,7 @@ static void tdx_parse_tdinfo(u64 *cc_mask)
* Guest-Host-Communication Interface (GHCI), section 2.4.2 TDCALL
* [TDG.VP.INFO].
*/
- tdx_module_call(TDX_GET_INFO, 0, 0, 0, 0, &out);
+ tdcall(TDG_VP_INFO, &args);
/*
* The highest bit of a guest physical address is the "sharing" bit.
@@ -161,7 +185,7 @@ static void tdx_parse_tdinfo(u64 *cc_mask)
* The GPA width that comes out of this call is critical. TDX guests
* can not meaningfully run without it.
*/
- gpa_width = out.rcx & GENMASK(5, 0);
+ gpa_width = args.rcx & GENMASK(5, 0);
*cc_mask = BIT_ULL(gpa_width - 1);
/*
@@ -169,7 +193,7 @@ static void tdx_parse_tdinfo(u64 *cc_mask)
* memory. Ensure that no #VE will be delivered for accesses to
* TD-private memory. Only VMM-shared memory (MMIO) will #VE.
*/
- td_attr = out.rdx;
+ td_attr = args.rdx;
if (!(td_attr & ATTR_SEPT_VE_DISABLE)) {
const char *msg = "TD misconfiguration: SEPT_VE_DISABLE attribute must be set.";
@@ -228,7 +252,7 @@ static int ve_instr_len(struct ve_info *ve)
static u64 __cpuidle __halt(const bool irq_disabled)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = hcall_func(EXIT_REASON_HLT),
.r12 = irq_disabled,
@@ -272,7 +296,7 @@ void __cpuidle tdx_safe_halt(void)
static int read_msr(struct pt_regs *regs, struct ve_info *ve)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = hcall_func(EXIT_REASON_MSR_READ),
.r12 = regs->cx,
@@ -283,7 +307,7 @@ static int read_msr(struct pt_regs *regs, struct ve_info *ve)
* can be found in TDX Guest-Host-Communication Interface
* (GHCI), section titled "TDG.VP.VMCALL<Instruction.RDMSR>".
*/
- if (__tdx_hypercall_ret(&args))
+ if (__tdx_hypercall(&args))
return -EIO;
regs->ax = lower_32_bits(args.r11);
@@ -293,7 +317,7 @@ static int read_msr(struct pt_regs *regs, struct ve_info *ve)
static int write_msr(struct pt_regs *regs, struct ve_info *ve)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = hcall_func(EXIT_REASON_MSR_WRITE),
.r12 = regs->cx,
@@ -313,7 +337,7 @@ static int write_msr(struct pt_regs *regs, struct ve_info *ve)
static int handle_cpuid(struct pt_regs *regs, struct ve_info *ve)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = hcall_func(EXIT_REASON_CPUID),
.r12 = regs->ax,
@@ -337,7 +361,7 @@ static int handle_cpuid(struct pt_regs *regs, struct ve_info *ve)
* ABI can be found in TDX Guest-Host-Communication Interface
* (GHCI), section titled "VP.VMCALL<Instruction.CPUID>".
*/
- if (__tdx_hypercall_ret(&args))
+ if (__tdx_hypercall(&args))
return -EIO;
/*
@@ -355,7 +379,7 @@ static int handle_cpuid(struct pt_regs *regs, struct ve_info *ve)
static bool mmio_read(int size, unsigned long addr, unsigned long *val)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = hcall_func(EXIT_REASON_EPT_VIOLATION),
.r12 = size,
@@ -364,8 +388,9 @@ static bool mmio_read(int size, unsigned long addr, unsigned long *val)
.r15 = *val,
};
- if (__tdx_hypercall_ret(&args))
+ if (__tdx_hypercall(&args))
return false;
+
*val = args.r11;
return true;
}
@@ -483,7 +508,7 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
static bool handle_in(struct pt_regs *regs, int size, int port)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = hcall_func(EXIT_REASON_IO_INSTRUCTION),
.r12 = size,
@@ -498,7 +523,7 @@ static bool handle_in(struct pt_regs *regs, int size, int port)
* in TDX Guest-Host-Communication Interface (GHCI) section titled
* "TDG.VP.VMCALL<Instruction.IO>".
*/
- success = !__tdx_hypercall_ret(&args);
+ success = !__tdx_hypercall(&args);
/* Update part of the register affected by the emulated instruction */
regs->ax &= ~mask;
@@ -577,7 +602,7 @@ __init bool tdx_early_handle_ve(struct pt_regs *regs)
void tdx_get_ve_info(struct ve_info *ve)
{
- struct tdx_module_output out;
+ struct tdx_module_args args = {};
/*
* Called during #VE handling to retrieve the #VE info from the
@@ -594,15 +619,15 @@ void tdx_get_ve_info(struct ve_info *ve)
* Note, the TDX module treats virtual NMIs as inhibited if the #VE
* valid flag is set. It means that NMI=>#VE will not result in a #DF.
*/
- tdx_module_call(TDX_GET_VEINFO, 0, 0, 0, 0, &out);
+ tdcall(TDG_VP_VEINFO_GET, &args);
/* Transfer the output parameters */
- ve->exit_reason = out.rcx;
- ve->exit_qual = out.rdx;
- ve->gla = out.r8;
- ve->gpa = out.r9;
- ve->instr_len = lower_32_bits(out.r10);
- ve->instr_info = upper_32_bits(out.r10);
+ ve->exit_reason = args.rcx;
+ ve->exit_qual = args.rdx;
+ ve->gla = args.r8;
+ ve->gpa = args.r9;
+ ve->instr_len = lower_32_bits(args.r10);
+ ve->instr_info = upper_32_bits(args.r10);
}
/*
@@ -703,14 +728,15 @@ static bool tdx_cache_flush_required(void)
}
/*
- * Inform the VMM of the guest's intent for this physical page: shared with
- * the VMM or private to the guest. The VMM is expected to change its mapping
- * of the page in response.
+ * Notify the VMM about page mapping conversion. More info about ABI
+ * can be found in TDX Guest-Host-Communication Interface (GHCI),
+ * section "TDG.VP.VMCALL<MapGPA>".
*/
-static bool tdx_enc_status_changed(unsigned long vaddr, int numpages, bool enc)
+static bool tdx_map_gpa(phys_addr_t start, phys_addr_t end, bool enc)
{
- phys_addr_t start = __pa(vaddr);
- phys_addr_t end = __pa(vaddr + numpages * PAGE_SIZE);
+ /* Retrying the hypercall a second time should succeed; use 3 just in case */
+ const int max_retries_per_page = 3;
+ int retry_count = 0;
if (!enc) {
/* Set the shared (decrypted) bits: */
@@ -718,12 +744,51 @@ static bool tdx_enc_status_changed(unsigned long vaddr, int numpages, bool enc)
end |= cc_mkdec(0);
}
- /*
- * Notify the VMM about page mapping conversion. More info about ABI
- * can be found in TDX Guest-Host-Communication Interface (GHCI),
- * section "TDG.VP.VMCALL<MapGPA>"
- */
- if (_tdx_hypercall(TDVMCALL_MAP_GPA, start, end - start, 0, 0))
+ while (retry_count < max_retries_per_page) {
+ struct tdx_module_args args = {
+ .r10 = TDX_HYPERCALL_STANDARD,
+ .r11 = TDVMCALL_MAP_GPA,
+ .r12 = start,
+ .r13 = end - start };
+
+ u64 map_fail_paddr;
+ u64 ret = __tdx_hypercall(&args);
+
+ if (ret != TDVMCALL_STATUS_RETRY)
+ return !ret;
+ /*
+ * The guest must retry the operation for the pages in the
+ * region starting at the GPA specified in R11. R11 comes
+ * from the untrusted VMM. Sanity check it.
+ */
+ map_fail_paddr = args.r11;
+ if (map_fail_paddr < start || map_fail_paddr >= end)
+ return false;
+
+ /* "Consume" a retry without forward progress */
+ if (map_fail_paddr == start) {
+ retry_count++;
+ continue;
+ }
+
+ start = map_fail_paddr;
+ retry_count = 0;
+ }
+
+ return false;
+}
+
+/*
+ * Inform the VMM of the guest's intent for this physical page: shared with
+ * the VMM or private to the guest. The VMM is expected to change its mapping
+ * of the page in response.
+ */
+static bool tdx_enc_status_changed(unsigned long vaddr, int numpages, bool enc)
+{
+ phys_addr_t start = __pa(vaddr);
+ phys_addr_t end = __pa(vaddr + numpages * PAGE_SIZE);
+
+ if (!tdx_map_gpa(start, end, enc))
return false;
/* shared->private conversion requires memory to be accepted before use */
@@ -759,6 +824,10 @@ static bool tdx_enc_status_change_finish(unsigned long vaddr, int numpages,
void __init tdx_early_init(void)
{
+ struct tdx_module_args args = {
+ .rdx = TDCS_NOTIFY_ENABLES,
+ .r9 = -1ULL,
+ };
u64 cc_mask;
u32 eax, sig[3];
@@ -769,12 +838,15 @@ void __init tdx_early_init(void)
setup_force_cpu_cap(X86_FEATURE_TDX_GUEST);
+ /* TSC is the only reliable clock in TDX guest */
+ setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
+
cc_vendor = CC_VENDOR_INTEL;
tdx_parse_tdinfo(&cc_mask);
cc_set_mask(cc_mask);
/* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */
- tdx_module_call(TDX_WR, 0, TDCS_NOTIFY_ENABLES, 0, -1ULL, NULL);
+ tdcall(TDG_VM_WR, &args);
/*
* All bits above GPA width are reserved and kernel treats shared bit
diff --git a/arch/x86/configs/hardening.config b/arch/x86/configs/hardening.config
new file mode 100644
index 000000000000..7b497f3b7bc3
--- /dev/null
+++ b/arch/x86/configs/hardening.config
@@ -0,0 +1,14 @@
+# Basic kernel hardening options (specific to x86)
+
+# Modern libc no longer needs a fixed-position mapping in userspace, remove
+# it as a possible target.
+CONFIG_LEGACY_VSYSCALL_NONE=y
+
+# Enable chip-specific IOMMU support.
+CONFIG_INTEL_IOMMU=y
+CONFIG_INTEL_IOMMU_DEFAULT_ON=y
+CONFIG_INTEL_IOMMU_SVM=y
+CONFIG_AMD_IOMMU=y
+
+# Enable CET Shadow Stack for userspace.
+CONFIG_X86_USER_SHADOW_STACK=y
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index 1b411bbf3cb0..73abbbdd26f8 100644
--- a/arch/x86/configs/i386_defconfig
+++ b/arch/x86/configs/i386_defconfig
@@ -281,4 +281,5 @@ CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
CONFIG_EARLY_PRINTK_DBGP=y
CONFIG_DEBUG_BOOT_PARAMS=y
CONFIG_UNWINDER_FRAME_POINTER=y
+CONFIG_DEBUG_ENTRY=y
# CONFIG_64BIT is not set
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index 409e9182bd29..61e25f6209ed 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -276,3 +276,4 @@ CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
CONFIG_EARLY_PRINTK_DBGP=y
CONFIG_DEBUG_BOOT_PARAMS=y
+CONFIG_DEBUG_ENTRY=y
diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S
index 3ac7487ecad2..187f913cc239 100644
--- a/arch/x86/crypto/aesni-intel_asm.S
+++ b/arch/x86/crypto/aesni-intel_asm.S
@@ -672,7 +672,7 @@ ALL_F: .octa 0xffffffffffffffffffffffffffffffff
add %r13, %r10
# Set r10 to be the amount of data left in CYPH_PLAIN_IN after filling
sub $16, %r10
- # Determine if if partial block is not being filled and
+ # Determine if partial block is not being filled and
# shift mask accordingly
jge .L_no_extra_mask_1_\@
sub %r10, %r12
@@ -708,7 +708,7 @@ ALL_F: .octa 0xffffffffffffffffffffffffffffffff
add %r13, %r10
# Set r10 to be the amount of data left in CYPH_PLAIN_IN after filling
sub $16, %r10
- # Determine if if partial block is not being filled and
+ # Determine if partial block is not being filled and
# shift mask accordingly
jge .L_no_extra_mask_2_\@
sub %r10, %r12
diff --git a/arch/x86/crypto/aesni-intel_avx-x86_64.S b/arch/x86/crypto/aesni-intel_avx-x86_64.S
index 46cddd78857b..74dd230973cf 100644
--- a/arch/x86/crypto/aesni-intel_avx-x86_64.S
+++ b/arch/x86/crypto/aesni-intel_avx-x86_64.S
@@ -753,7 +753,7 @@ VARIABLE_OFFSET = 16*8
add %r13, %r10
# Set r10 to be the amount of data left in CYPH_PLAIN_IN after filling
sub $16, %r10
- # Determine if if partial block is not being filled and
+ # Determine if partial block is not being filled and
# shift mask accordingly
jge .L_no_extra_mask_1_\@
sub %r10, %r12
@@ -789,7 +789,7 @@ VARIABLE_OFFSET = 16*8
add %r13, %r10
# Set r10 to be the amount of data left in CYPH_PLAIN_IN after filling
sub $16, %r10
- # Determine if if partial block is not being filled and
+ # Determine if partial block is not being filled and
# shift mask accordingly
jge .L_no_extra_mask_2_\@
sub %r10, %r12
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index 39d6a62ac627..b1d90c25975a 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -61,8 +61,8 @@ struct generic_gcmaes_ctx {
};
struct aesni_xts_ctx {
- u8 raw_tweak_ctx[sizeof(struct crypto_aes_ctx)] AESNI_ALIGN_ATTR;
- u8 raw_crypt_ctx[sizeof(struct crypto_aes_ctx)] AESNI_ALIGN_ATTR;
+ struct crypto_aes_ctx tweak_ctx AESNI_ALIGN_ATTR;
+ struct crypto_aes_ctx crypt_ctx AESNI_ALIGN_ATTR;
};
#define GCM_BLOCK_LEN 16
@@ -80,6 +80,13 @@ struct gcm_context_data {
u8 hash_keys[GCM_BLOCK_LEN * 16];
};
+static inline void *aes_align_addr(void *addr)
+{
+ if (crypto_tfm_ctx_alignment() >= AESNI_ALIGN)
+ return addr;
+ return PTR_ALIGN(addr, AESNI_ALIGN);
+}
+
asmlinkage int aesni_set_key(struct crypto_aes_ctx *ctx, const u8 *in_key,
unsigned int key_len);
asmlinkage void aesni_enc(const void *ctx, u8 *out, const u8 *in);
@@ -201,32 +208,24 @@ static __ro_after_init DEFINE_STATIC_KEY_FALSE(gcm_use_avx2);
static inline struct
aesni_rfc4106_gcm_ctx *aesni_rfc4106_gcm_ctx_get(struct crypto_aead *tfm)
{
- unsigned long align = AESNI_ALIGN;
-
- if (align <= crypto_tfm_ctx_alignment())
- align = 1;
- return PTR_ALIGN(crypto_aead_ctx(tfm), align);
+ return aes_align_addr(crypto_aead_ctx(tfm));
}
static inline struct
generic_gcmaes_ctx *generic_gcmaes_ctx_get(struct crypto_aead *tfm)
{
- unsigned long align = AESNI_ALIGN;
-
- if (align <= crypto_tfm_ctx_alignment())
- align = 1;
- return PTR_ALIGN(crypto_aead_ctx(tfm), align);
+ return aes_align_addr(crypto_aead_ctx(tfm));
}
#endif
static inline struct crypto_aes_ctx *aes_ctx(void *raw_ctx)
{
- unsigned long addr = (unsigned long)raw_ctx;
- unsigned long align = AESNI_ALIGN;
+ return aes_align_addr(raw_ctx);
+}
- if (align <= crypto_tfm_ctx_alignment())
- align = 1;
- return (struct crypto_aes_ctx *)ALIGN(addr, align);
+static inline struct aesni_xts_ctx *aes_xts_ctx(struct crypto_skcipher *tfm)
+{
+ return aes_align_addr(crypto_skcipher_ctx(tfm));
}
static int aes_set_key_common(struct crypto_aes_ctx *ctx,
@@ -881,7 +880,7 @@ static int helper_rfc4106_decrypt(struct aead_request *req)
static int xts_aesni_setkey(struct crypto_skcipher *tfm, const u8 *key,
unsigned int keylen)
{
- struct aesni_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
+ struct aesni_xts_ctx *ctx = aes_xts_ctx(tfm);
int err;
err = xts_verify_key(tfm, key, keylen);
@@ -891,19 +890,18 @@ static int xts_aesni_setkey(struct crypto_skcipher *tfm, const u8 *key,
keylen /= 2;
/* first half of xts-key is for crypt */
- err = aes_set_key_common(aes_ctx(ctx->raw_crypt_ctx), key, keylen);
+ err = aes_set_key_common(&ctx->crypt_ctx, key, keylen);
if (err)
return err;
/* second half of xts-key is for tweak */
- return aes_set_key_common(aes_ctx(ctx->raw_tweak_ctx), key + keylen,
- keylen);
+ return aes_set_key_common(&ctx->tweak_ctx, key + keylen, keylen);
}
static int xts_crypt(struct skcipher_request *req, bool encrypt)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
- struct aesni_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
+ struct aesni_xts_ctx *ctx = aes_xts_ctx(tfm);
int tail = req->cryptlen % AES_BLOCK_SIZE;
struct skcipher_request subreq;
struct skcipher_walk walk;
@@ -939,7 +937,7 @@ static int xts_crypt(struct skcipher_request *req, bool encrypt)
kernel_fpu_begin();
/* calculate first value of T */
- aesni_enc(aes_ctx(ctx->raw_tweak_ctx), walk.iv, walk.iv);
+ aesni_enc(&ctx->tweak_ctx, walk.iv, walk.iv);
while (walk.nbytes > 0) {
int nbytes = walk.nbytes;
@@ -948,11 +946,11 @@ static int xts_crypt(struct skcipher_request *req, bool encrypt)
nbytes &= ~(AES_BLOCK_SIZE - 1);
if (encrypt)
- aesni_xts_encrypt(aes_ctx(ctx->raw_crypt_ctx),
+ aesni_xts_encrypt(&ctx->crypt_ctx,
walk.dst.virt.addr, walk.src.virt.addr,
nbytes, walk.iv);
else
- aesni_xts_decrypt(aes_ctx(ctx->raw_crypt_ctx),
+ aesni_xts_decrypt(&ctx->crypt_ctx,
walk.dst.virt.addr, walk.src.virt.addr,
nbytes, walk.iv);
kernel_fpu_end();
@@ -980,11 +978,11 @@ static int xts_crypt(struct skcipher_request *req, bool encrypt)
kernel_fpu_begin();
if (encrypt)
- aesni_xts_encrypt(aes_ctx(ctx->raw_crypt_ctx),
+ aesni_xts_encrypt(&ctx->crypt_ctx,
walk.dst.virt.addr, walk.src.virt.addr,
walk.nbytes, walk.iv);
else
- aesni_xts_decrypt(aes_ctx(ctx->raw_crypt_ctx),
+ aesni_xts_decrypt(&ctx->crypt_ctx,
walk.dst.virt.addr, walk.src.virt.addr,
walk.nbytes, walk.iv);
kernel_fpu_end();
diff --git a/arch/x86/crypto/nhpoly1305-avx2-glue.c b/arch/x86/crypto/nhpoly1305-avx2-glue.c
index 46b036204ed9..c3a872f4d6a7 100644
--- a/arch/x86/crypto/nhpoly1305-avx2-glue.c
+++ b/arch/x86/crypto/nhpoly1305-avx2-glue.c
@@ -34,6 +34,14 @@ static int nhpoly1305_avx2_update(struct shash_desc *desc,
return 0;
}
+static int nhpoly1305_avx2_digest(struct shash_desc *desc,
+ const u8 *src, unsigned int srclen, u8 *out)
+{
+ return crypto_nhpoly1305_init(desc) ?:
+ nhpoly1305_avx2_update(desc, src, srclen) ?:
+ crypto_nhpoly1305_final(desc, out);
+}
+
static struct shash_alg nhpoly1305_alg = {
.base.cra_name = "nhpoly1305",
.base.cra_driver_name = "nhpoly1305-avx2",
@@ -44,6 +52,7 @@ static struct shash_alg nhpoly1305_alg = {
.init = crypto_nhpoly1305_init,
.update = nhpoly1305_avx2_update,
.final = crypto_nhpoly1305_final,
+ .digest = nhpoly1305_avx2_digest,
.setkey = crypto_nhpoly1305_setkey,
.descsize = sizeof(struct nhpoly1305_state),
};
diff --git a/arch/x86/crypto/nhpoly1305-sse2-glue.c b/arch/x86/crypto/nhpoly1305-sse2-glue.c
index 4a4970d75107..a268a8439a5c 100644
--- a/arch/x86/crypto/nhpoly1305-sse2-glue.c
+++ b/arch/x86/crypto/nhpoly1305-sse2-glue.c
@@ -34,6 +34,14 @@ static int nhpoly1305_sse2_update(struct shash_desc *desc,
return 0;
}
+static int nhpoly1305_sse2_digest(struct shash_desc *desc,
+ const u8 *src, unsigned int srclen, u8 *out)
+{
+ return crypto_nhpoly1305_init(desc) ?:
+ nhpoly1305_sse2_update(desc, src, srclen) ?:
+ crypto_nhpoly1305_final(desc, out);
+}
+
static struct shash_alg nhpoly1305_alg = {
.base.cra_name = "nhpoly1305",
.base.cra_driver_name = "nhpoly1305-sse2",
@@ -44,6 +52,7 @@ static struct shash_alg nhpoly1305_alg = {
.init = crypto_nhpoly1305_init,
.update = nhpoly1305_sse2_update,
.final = crypto_nhpoly1305_final,
+ .digest = nhpoly1305_sse2_digest,
.setkey = crypto_nhpoly1305_setkey,
.descsize = sizeof(struct nhpoly1305_state),
};
diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c
index 44340a1139e0..959afa705e95 100644
--- a/arch/x86/crypto/sha1_ssse3_glue.c
+++ b/arch/x86/crypto/sha1_ssse3_glue.c
@@ -24,8 +24,17 @@
#include <linux/types.h>
#include <crypto/sha1.h>
#include <crypto/sha1_base.h>
+#include <asm/cpu_device_id.h>
#include <asm/simd.h>
+static const struct x86_cpu_id module_cpu_ids[] = {
+ X86_MATCH_FEATURE(X86_FEATURE_AVX2, NULL),
+ X86_MATCH_FEATURE(X86_FEATURE_AVX, NULL),
+ X86_MATCH_FEATURE(X86_FEATURE_SSSE3, NULL),
+ {}
+};
+MODULE_DEVICE_TABLE(x86cpu, module_cpu_ids);
+
static int sha1_update(struct shash_desc *desc, const u8 *data,
unsigned int len, sha1_block_fn *sha1_xform)
{
@@ -301,6 +310,9 @@ static inline void unregister_sha1_ni(void) { }
static int __init sha1_ssse3_mod_init(void)
{
+ if (!x86_match_cpu(module_cpu_ids))
+ return -ENODEV;
+
if (register_sha1_ssse3())
goto fail;
diff --git a/arch/x86/crypto/sha256_ssse3_glue.c b/arch/x86/crypto/sha256_ssse3_glue.c
index 3a5f6be7dbba..4c0383a90e11 100644
--- a/arch/x86/crypto/sha256_ssse3_glue.c
+++ b/arch/x86/crypto/sha256_ssse3_glue.c
@@ -38,11 +38,20 @@
#include <crypto/sha2.h>
#include <crypto/sha256_base.h>
#include <linux/string.h>
+#include <asm/cpu_device_id.h>
#include <asm/simd.h>
asmlinkage void sha256_transform_ssse3(struct sha256_state *state,
const u8 *data, int blocks);
+static const struct x86_cpu_id module_cpu_ids[] = {
+ X86_MATCH_FEATURE(X86_FEATURE_AVX2, NULL),
+ X86_MATCH_FEATURE(X86_FEATURE_AVX, NULL),
+ X86_MATCH_FEATURE(X86_FEATURE_SSSE3, NULL),
+ {}
+};
+MODULE_DEVICE_TABLE(x86cpu, module_cpu_ids);
+
static int _sha256_update(struct shash_desc *desc, const u8 *data,
unsigned int len, sha256_block_fn *sha256_xform)
{
@@ -98,12 +107,20 @@ static int sha256_ssse3_final(struct shash_desc *desc, u8 *out)
return sha256_ssse3_finup(desc, NULL, 0, out);
}
+static int sha256_ssse3_digest(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ return sha256_base_init(desc) ?:
+ sha256_ssse3_finup(desc, data, len, out);
+}
+
static struct shash_alg sha256_ssse3_algs[] = { {
.digestsize = SHA256_DIGEST_SIZE,
.init = sha256_base_init,
.update = sha256_ssse3_update,
.final = sha256_ssse3_final,
.finup = sha256_ssse3_finup,
+ .digest = sha256_ssse3_digest,
.descsize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha256",
@@ -163,12 +180,20 @@ static int sha256_avx_final(struct shash_desc *desc, u8 *out)
return sha256_avx_finup(desc, NULL, 0, out);
}
+static int sha256_avx_digest(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ return sha256_base_init(desc) ?:
+ sha256_avx_finup(desc, data, len, out);
+}
+
static struct shash_alg sha256_avx_algs[] = { {
.digestsize = SHA256_DIGEST_SIZE,
.init = sha256_base_init,
.update = sha256_avx_update,
.final = sha256_avx_final,
.finup = sha256_avx_finup,
+ .digest = sha256_avx_digest,
.descsize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha256",
@@ -239,12 +264,20 @@ static int sha256_avx2_final(struct shash_desc *desc, u8 *out)
return sha256_avx2_finup(desc, NULL, 0, out);
}
+static int sha256_avx2_digest(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ return sha256_base_init(desc) ?:
+ sha256_avx2_finup(desc, data, len, out);
+}
+
static struct shash_alg sha256_avx2_algs[] = { {
.digestsize = SHA256_DIGEST_SIZE,
.init = sha256_base_init,
.update = sha256_avx2_update,
.final = sha256_avx2_final,
.finup = sha256_avx2_finup,
+ .digest = sha256_avx2_digest,
.descsize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha256",
@@ -314,12 +347,20 @@ static int sha256_ni_final(struct shash_desc *desc, u8 *out)
return sha256_ni_finup(desc, NULL, 0, out);
}
+static int sha256_ni_digest(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ return sha256_base_init(desc) ?:
+ sha256_ni_finup(desc, data, len, out);
+}
+
static struct shash_alg sha256_ni_algs[] = { {
.digestsize = SHA256_DIGEST_SIZE,
.init = sha256_base_init,
.update = sha256_ni_update,
.final = sha256_ni_final,
.finup = sha256_ni_finup,
+ .digest = sha256_ni_digest,
.descsize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha256",
@@ -366,6 +407,9 @@ static inline void unregister_sha256_ni(void) { }
static int __init sha256_ssse3_mod_init(void)
{
+ if (!x86_match_cpu(module_cpu_ids))
+ return -ENODEV;
+
if (register_sha256_ssse3())
goto fail;
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 93c60c0c9d4a..6356060caaf3 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -19,12 +19,14 @@
#include <linux/nospec.h>
#include <linux/syscalls.h>
#include <linux/uaccess.h>
+#include <linux/init.h>
#ifdef CONFIG_XEN_PV
#include <xen/xen-ops.h>
#include <xen/events.h>
#endif
+#include <asm/apic.h>
#include <asm/desc.h>
#include <asm/traps.h>
#include <asm/vdso.h>
@@ -70,7 +72,8 @@ static __always_inline bool do_syscall_x32(struct pt_regs *regs, int nr)
return false;
}
-__visible noinstr void do_syscall_64(struct pt_regs *regs, int nr)
+/* Returns true to return using SYSRET, or false to use IRET */
+__visible noinstr bool do_syscall_64(struct pt_regs *regs, int nr)
{
add_random_kstack_offset();
nr = syscall_enter_from_user_mode(regs, nr);
@@ -84,6 +87,46 @@ __visible noinstr void do_syscall_64(struct pt_regs *regs, int nr)
instrumentation_end();
syscall_exit_to_user_mode(regs);
+
+ /*
+ * Check that the register state is valid for using SYSRET to exit
+ * to userspace. Otherwise use the slower but fully capable IRET
+ * exit path.
+ */
+
+ /* XEN PV guests always use the IRET path */
+ if (cpu_feature_enabled(X86_FEATURE_XENPV))
+ return false;
+
+ /* SYSRET requires RCX == RIP and R11 == EFLAGS */
+ if (unlikely(regs->cx != regs->ip || regs->r11 != regs->flags))
+ return false;
+
+ /* CS and SS must match the values set in MSR_STAR */
+ if (unlikely(regs->cs != __USER_CS || regs->ss != __USER_DS))
+ return false;
+
+ /*
+ * On Intel CPUs, SYSRET with non-canonical RCX/RIP will #GP
+ * in kernel space. This essentially lets the user take over
+ * the kernel, since userspace controls RSP.
+ *
+ * TASK_SIZE_MAX covers all user-accessible addresses other than
+ * the deprecated vsyscall page.
+ */
+ if (unlikely(regs->ip >= TASK_SIZE_MAX))
+ return false;
+
+ /*
+ * SYSRET cannot restore RF. It can restore TF, but unlike IRET,
+ * restoring TF results in a trap from userspace immediately after
+ * SYSRET.
+ */
+ if (unlikely(regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF)))
+ return false;
+
+ /* Use SYSRET to exit to userspace */
+ return true;
}
#endif
@@ -96,6 +139,16 @@ static __always_inline int syscall_32_enter(struct pt_regs *regs)
return (int)regs->orig_ax;
}
+#ifdef CONFIG_IA32_EMULATION
+bool __ia32_enabled __ro_after_init = !IS_ENABLED(CONFIG_IA32_EMULATION_DEFAULT_DISABLED);
+
+static int ia32_emulation_override_cmdline(char *arg)
+{
+ return kstrtobool(arg, &__ia32_enabled);
+}
+early_param("ia32_emulation", ia32_emulation_override_cmdline);
+#endif
+
/*
* Invoke a 32-bit syscall. Called with IRQs on in CONTEXT_KERNEL.
*/
@@ -115,7 +168,96 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, int nr)
}
}
-/* Handles int $0x80 */
+#ifdef CONFIG_IA32_EMULATION
+static __always_inline bool int80_is_external(void)
+{
+ const unsigned int offs = (0x80 / 32) * 0x10;
+ const u32 bit = BIT(0x80 % 32);
+
+ /* The local APIC on XENPV guests is fake */
+ if (cpu_feature_enabled(X86_FEATURE_XENPV))
+ return false;
+
+ /*
+ * If vector 0x80 is set in the APIC ISR then this is an external
+ * interrupt. Either from broken hardware or injected by a VMM.
+ *
+ * Note: In guest mode this is only valid for secure guests where
+ * the secure module fully controls the vAPIC exposed to the guest.
+ */
+ return apic_read(APIC_ISR + offs) & bit;
+}
+
+/**
+ * int80_emulation - 32-bit legacy syscall entry
+ *
+ * This entry point can be used by 32-bit and 64-bit programs to perform
+ * 32-bit system calls. Instances of INT $0x80 can be found inline in
+ * various programs and libraries. It is also used by the vDSO's
+ * __kernel_vsyscall fallback for hardware that doesn't support a faster
+ * entry method. Restarted 32-bit system calls also fall back to INT
+ * $0x80 regardless of what instruction was originally used to do the
+ * system call.
+ *
+ * This is considered a slow path. It is not used by most libc
+ * implementations on modern hardware except during process startup.
+ *
+ * The arguments for the INT $0x80 based syscall are on stack in the
+ * pt_regs structure:
+ * eax: system call number
+ * ebx, ecx, edx, esi, edi, ebp: arg1 - arg 6
+ */
+DEFINE_IDTENTRY_RAW(int80_emulation)
+{
+ int nr;
+
+ /* Kernel does not use INT $0x80! */
+ if (unlikely(!user_mode(regs))) {
+ irqentry_enter(regs);
+ instrumentation_begin();
+ panic("Unexpected external interrupt 0x80\n");
+ }
+
+ /*
+ * Establish kernel context for instrumentation, including for
+ * int80_is_external() below which calls into the APIC driver.
+ * Identical for soft and external interrupts.
+ */
+ enter_from_user_mode(regs);
+
+ instrumentation_begin();
+ add_random_kstack_offset();
+
+ /* Validate that this is a soft interrupt to the extent possible */
+ if (unlikely(int80_is_external()))
+ panic("Unexpected external interrupt 0x80\n");
+
+ /*
+ * The low level idtentry code pushed -1 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);
+}
+#else /* CONFIG_IA32_EMULATION */
+
+/* Handles int $0x80 on a 32bit kernel */
__visible noinstr void do_int80_syscall_32(struct pt_regs *regs)
{
int nr = syscall_32_enter(regs);
@@ -134,6 +276,7 @@ __visible noinstr void do_int80_syscall_32(struct pt_regs *regs)
instrumentation_end();
syscall_exit_to_user_mode(regs);
}
+#endif /* !CONFIG_IA32_EMULATION */
static noinstr bool __do_fast_syscall_32(struct pt_regs *regs)
{
@@ -182,8 +325,8 @@ static noinstr bool __do_fast_syscall_32(struct pt_regs *regs)
return true;
}
-/* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */
-__visible noinstr long do_fast_syscall_32(struct pt_regs *regs)
+/* Returns true to return using SYSEXIT/SYSRETL, or false to use IRET */
+__visible noinstr bool do_fast_syscall_32(struct pt_regs *regs)
{
/*
* Called using the internal vDSO SYSENTER/SYSCALL32 calling
@@ -201,41 +344,36 @@ __visible noinstr long do_fast_syscall_32(struct pt_regs *regs)
/* Invoke the syscall. If it failed, keep it simple: use IRET. */
if (!__do_fast_syscall_32(regs))
- return 0;
+ return false;
-#ifdef CONFIG_X86_64
- /*
- * Opportunistic SYSRETL: if possible, try to return using SYSRETL.
- * SYSRETL is available on all 64-bit CPUs, so we don't need to
- * bother with SYSEXIT.
- *
- * Unlike 64-bit opportunistic SYSRET, we can't check that CX == IP,
- * because the ECX fixup above will ensure that this is essentially
- * never the case.
- */
- return regs->cs == __USER32_CS && regs->ss == __USER_DS &&
- regs->ip == landing_pad &&
- (regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF)) == 0;
-#else
/*
- * Opportunistic SYSEXIT: if possible, try to return using SYSEXIT.
- *
- * Unlike 64-bit opportunistic SYSRET, we can't check that CX == IP,
- * because the ECX fixup above will ensure that this is essentially
- * never the case.
- *
- * We don't allow syscalls at all from VM86 mode, but we still
- * need to check VM, because we might be returning from sys_vm86.
+ * Check that the register state is valid for using SYSRETL/SYSEXIT
+ * to exit to userspace. Otherwise use the slower but fully capable
+ * IRET exit path.
*/
- return static_cpu_has(X86_FEATURE_SEP) &&
- regs->cs == __USER_CS && regs->ss == __USER_DS &&
- regs->ip == landing_pad &&
- (regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF | X86_EFLAGS_VM)) == 0;
-#endif
+
+ /* XEN PV guests always use the IRET path */
+ if (cpu_feature_enabled(X86_FEATURE_XENPV))
+ return false;
+
+ /* EIP must point to the VDSO landing pad */
+ if (unlikely(regs->ip != landing_pad))
+ return false;
+
+ /* CS and SS must match the values set in MSR_STAR */
+ if (unlikely(regs->cs != __USER32_CS || regs->ss != __USER_DS))
+ return false;
+
+ /* If the TF, RF, or VM flags are set, use IRET */
+ if (unlikely(regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF | X86_EFLAGS_VM)))
+ return false;
+
+ /* Use SYSRETL/SYSEXIT to exit to userspace */
+ return true;
}
-/* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */
-__visible noinstr long do_SYSENTER_32(struct pt_regs *regs)
+/* Returns true to return using SYSEXIT/SYSRETL, or false to use IRET */
+__visible noinstr bool do_SYSENTER_32(struct pt_regs *regs)
{
/* SYSENTER loses RSP, but the vDSO saved it in RBP. */
regs->sp = regs->bp;
diff --git a/arch/x86/entry/entry.S b/arch/x86/entry/entry.S
index bfb7bcb362bc..8c8d38f0cb1d 100644
--- a/arch/x86/entry/entry.S
+++ b/arch/x86/entry/entry.S
@@ -3,8 +3,8 @@
* Common place for both 32- and 64-bit entry routines.
*/
+#include <linux/export.h>
#include <linux/linkage.h>
-#include <asm/export.h>
#include <asm/msr-index.h>
.pushsection .noinstr.text, "ax"
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 6e6af42e044a..c73047bf9f4b 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -837,7 +837,7 @@ SYM_FUNC_START(entry_SYSENTER_32)
movl %esp, %eax
call do_SYSENTER_32
- testl %eax, %eax
+ testb %al, %al
jz .Lsyscall_32_done
STACKLEAK_ERASE
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 43606de22511..de6469dffe3a 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -18,6 +18,7 @@
* - SYM_FUNC_START/END:Define functions in the symbol table.
* - idtentry: Define exception entry points.
*/
+#include <linux/export.h>
#include <linux/linkage.h>
#include <asm/segment.h>
#include <asm/cache.h>
@@ -34,7 +35,6 @@
#include <asm/asm.h>
#include <asm/smap.h>
#include <asm/pgtable_types.h>
-#include <asm/export.h>
#include <asm/frame.h>
#include <asm/trapnr.h>
#include <asm/nospec-branch.h>
@@ -126,70 +126,8 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL)
* In the Xen PV case we must use iret anyway.
*/
- ALTERNATIVE "", "jmp swapgs_restore_regs_and_return_to_usermode", \
- X86_FEATURE_XENPV
-
- movq RCX(%rsp), %rcx
- movq RIP(%rsp), %r11
-
- cmpq %rcx, %r11 /* SYSRET requires RCX == RIP */
- jne swapgs_restore_regs_and_return_to_usermode
-
- /*
- * On Intel CPUs, SYSRET with non-canonical RCX/RIP will #GP
- * in kernel space. This essentially lets the user take over
- * the kernel, since userspace controls RSP.
- *
- * If width of "canonical tail" ever becomes variable, this will need
- * to be updated to remain correct on both old and new CPUs.
- *
- * Change top bits to match most significant bit (47th or 56th bit
- * depending on paging mode) in the address.
- */
-#ifdef CONFIG_X86_5LEVEL
- ALTERNATIVE "shl $(64 - 48), %rcx; sar $(64 - 48), %rcx", \
- "shl $(64 - 57), %rcx; sar $(64 - 57), %rcx", X86_FEATURE_LA57
-#else
- shl $(64 - (__VIRTUAL_MASK_SHIFT+1)), %rcx
- sar $(64 - (__VIRTUAL_MASK_SHIFT+1)), %rcx
-#endif
-
- /* If this changed %rcx, it was not canonical */
- cmpq %rcx, %r11
- jne swapgs_restore_regs_and_return_to_usermode
-
- cmpq $__USER_CS, CS(%rsp) /* CS must match SYSRET */
- jne swapgs_restore_regs_and_return_to_usermode
-
- movq R11(%rsp), %r11
- cmpq %r11, EFLAGS(%rsp) /* R11 == RFLAGS */
- jne swapgs_restore_regs_and_return_to_usermode
-
- /*
- * SYSCALL clears RF when it saves RFLAGS in R11 and SYSRET cannot
- * restore RF properly. If the slowpath sets it for whatever reason, we
- * need to restore it correctly.
- *
- * SYSRET can restore TF, but unlike IRET, restoring TF results in a
- * trap from userspace immediately after SYSRET. This would cause an
- * infinite loop whenever #DB happens with register state that satisfies
- * the opportunistic SYSRET conditions. For example, single-stepping
- * this user code:
- *
- * movq $stuck_here, %rcx
- * pushfq
- * popq %r11
- * stuck_here:
- *
- * would never get past 'stuck_here'.
- */
- testq $(X86_EFLAGS_RF|X86_EFLAGS_TF), %r11
- jnz swapgs_restore_regs_and_return_to_usermode
-
- /* nothing to check for RSP */
-
- cmpq $__USER_DS, SS(%rsp) /* SS must match SYSRET */
- jne swapgs_restore_regs_and_return_to_usermode
+ ALTERNATIVE "testb %al, %al; jz swapgs_restore_regs_and_return_to_usermode", \
+ "jmp swapgs_restore_regs_and_return_to_usermode", X86_FEATURE_XENPV
/*
* We win! This label is here just for ease of understanding
@@ -1163,8 +1101,8 @@ SYM_CODE_START(asm_exc_nmi)
* anyway.
*
* To handle this case we do the following:
- * Check the a special location on the stack that contains
- * a variable that is set when NMIs are executing.
+ * Check a special location on the stack that contains a
+ * variable that is set when NMIs are executing.
* The interrupted task's stack is also checked to see if it
* is an NMI stack.
* If the variable is not set and the stack is not the NMI
@@ -1237,7 +1175,6 @@ SYM_CODE_START(asm_exc_nmi)
*/
movq %rsp, %rdi
- movq $-1, %rsi
call exc_nmi
/*
@@ -1295,8 +1232,8 @@ SYM_CODE_START(asm_exc_nmi)
* end_repeat_nmi, then we are a nested NMI. We must not
* modify the "iret" frame because it's being written by
* the outer NMI. That's okay; the outer NMI handler is
- * about to about to call exc_nmi() anyway, so we can just
- * resume the outer NMI.
+ * about to call exc_nmi() anyway, so we can just resume
+ * the outer NMI.
*/
movq $repeat_nmi, %rdx
@@ -1451,7 +1388,6 @@ end_repeat_nmi:
UNWIND_HINT_REGS
movq %rsp, %rdi
- movq $-1, %rsi
call exc_nmi
/* Always restore stashed SPEC_CTRL value (see paranoid_entry) */
@@ -1511,18 +1447,16 @@ nmi_restore:
iretq
SYM_CODE_END(asm_exc_nmi)
-#ifndef CONFIG_IA32_EMULATION
/*
* This handles SYSCALL from 32-bit code. There is no way to program
* MSRs to fully disable 32-bit SYSCALL.
*/
-SYM_CODE_START(ignore_sysret)
+SYM_CODE_START(entry_SYSCALL32_ignore)
UNWIND_HINT_END_OF_STACK
ENDBR
mov $-ENOSYS, %eax
sysretl
-SYM_CODE_END(ignore_sysret)
-#endif
+SYM_CODE_END(entry_SYSCALL32_ignore)
.pushsection .text, "ax"
__FUNC_ALIGN
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index 70150298f8bd..de94e2e84ecc 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -118,9 +118,6 @@ SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL)
movq %rsp, %rdi
call do_SYSENTER_32
- /* XEN PV guests always use IRET path */
- ALTERNATIVE "testl %eax, %eax; jz swapgs_restore_regs_and_return_to_usermode", \
- "jmp swapgs_restore_regs_and_return_to_usermode", X86_FEATURE_XENPV
jmp sysret32_from_system_call
.Lsysenter_fix_flags:
@@ -212,13 +209,15 @@ SYM_INNER_LABEL(entry_SYSCALL_compat_after_hwframe, SYM_L_GLOBAL)
movq %rsp, %rdi
call do_fast_syscall_32
+
+sysret32_from_system_call:
/* XEN PV guests always use IRET path */
- ALTERNATIVE "testl %eax, %eax; jz swapgs_restore_regs_and_return_to_usermode", \
+ ALTERNATIVE "testb %al, %al; jz swapgs_restore_regs_and_return_to_usermode", \
"jmp swapgs_restore_regs_and_return_to_usermode", X86_FEATURE_XENPV
- /* Opportunistic SYSRET */
-sysret32_from_system_call:
/*
+ * Opportunistic SYSRET
+ *
* We are not going to return to userspace from the trampoline
* stack. So let's erase the thread stack right now.
*/
@@ -276,80 +275,3 @@ SYM_INNER_LABEL(entry_SYSRETL_compat_end, SYM_L_GLOBAL)
ANNOTATE_NOENDBR
int3
SYM_CODE_END(entry_SYSCALL_compat)
-
-/*
- * 32-bit legacy system call entry.
- *
- * 32-bit x86 Linux system calls traditionally used the INT $0x80
- * instruction. INT $0x80 lands here.
- *
- * This entry point can be used by 32-bit and 64-bit programs to perform
- * 32-bit system calls. Instances of INT $0x80 can be found inline in
- * various programs and libraries. It is also used by the vDSO's
- * __kernel_vsyscall fallback for hardware that doesn't support a faster
- * entry method. Restarted 32-bit system calls also fall back to INT
- * $0x80 regardless of what instruction was originally used to do the
- * system call.
- *
- * This is considered a slow path. It is not used by most libc
- * implementations on modern hardware except during process startup.
- *
- * Arguments:
- * eax system call number
- * ebx arg1
- * ecx arg2
- * edx arg3
- * esi arg4
- * edi arg5
- * ebp arg6
- */
-SYM_CODE_START(entry_INT80_compat)
- UNWIND_HINT_ENTRY
- ENDBR
- /*
- * Interrupts are off on entry.
- */
- ASM_CLAC /* Do this early to minimize exposure */
- ALTERNATIVE "swapgs", "", X86_FEATURE_XENPV
-
- /*
- * User tracing code (ptrace or signal handlers) might assume that
- * the saved RAX contains a 32-bit number when we're invoking a 32-bit
- * syscall. Just in case the high bits are nonzero, zero-extend
- * the syscall number. (This could almost certainly be deleted
- * with no ill effects.)
- */
- movl %eax, %eax
-
- /* switch to thread stack expects orig_ax and rdi to be pushed */
- pushq %rax /* pt_regs->orig_ax */
-
- /* Need to switch before accessing the thread stack. */
- SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
-
- /* In the Xen PV case we already run on the thread stack. */
- ALTERNATIVE "", "jmp .Lint80_keep_stack", X86_FEATURE_XENPV
-
- movq %rsp, %rax
- movq PER_CPU_VAR(pcpu_hot + X86_top_of_stack), %rsp
-
- pushq 5*8(%rax) /* regs->ss */
- pushq 4*8(%rax) /* regs->rsp */
- pushq 3*8(%rax) /* regs->eflags */
- pushq 2*8(%rax) /* regs->cs */
- pushq 1*8(%rax) /* regs->ip */
- pushq 0*8(%rax) /* regs->orig_ax */
-.Lint80_keep_stack:
-
- PUSH_AND_CLEAR_REGS rax=$-ENOSYS
- UNWIND_HINT_REGS
-
- cld
-
- IBRS_ENTER
- UNTRAIN_RET
-
- movq %rsp, %rdi
- call do_int80_syscall_32
- jmp swapgs_restore_regs_and_return_to_usermode
-SYM_CODE_END(entry_INT80_compat)
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index 2d0b1bd866ea..c8fac5205803 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -264,7 +264,7 @@
250 i386 fadvise64 sys_ia32_fadvise64
# 251 is available for reuse (was briefly sys_set_zone_reclaim)
252 i386 exit_group sys_exit_group
-253 i386 lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie
+253 i386 lookup_dcookie
254 i386 epoll_create sys_epoll_create
255 i386 epoll_ctl sys_epoll_ctl
256 i386 epoll_wait sys_epoll_wait
@@ -457,3 +457,7 @@
450 i386 set_mempolicy_home_node sys_set_mempolicy_home_node
451 i386 cachestat sys_cachestat
452 i386 fchmodat2 sys_fchmodat2
+453 i386 map_shadow_stack sys_map_shadow_stack
+454 i386 futex_wake sys_futex_wake
+455 i386 futex_wait sys_futex_wait
+456 i386 futex_requeue sys_futex_requeue
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index 1d6eee30eceb..8cb8bf68721c 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -220,7 +220,7 @@
209 64 io_submit sys_io_submit
210 common io_cancel sys_io_cancel
211 64 get_thread_area
-212 common lookup_dcookie sys_lookup_dcookie
+212 common lookup_dcookie
213 common epoll_create sys_epoll_create
214 64 epoll_ctl_old
215 64 epoll_wait_old
@@ -375,6 +375,9 @@
451 common cachestat sys_cachestat
452 common fchmodat2 sys_fchmodat2
453 64 map_shadow_stack sys_map_shadow_stack
+454 common futex_wake sys_futex_wake
+455 common futex_wait sys_futex_wait
+456 common futex_requeue sys_futex_requeue
#
# Due to a historical design error, certain syscalls are numbered differently
diff --git a/arch/x86/entry/thunk_32.S b/arch/x86/entry/thunk_32.S
index ff6e7003da97..0103e103a657 100644
--- a/arch/x86/entry/thunk_32.S
+++ b/arch/x86/entry/thunk_32.S
@@ -4,9 +4,9 @@
* Copyright 2008 by Steven Rostedt, Red Hat, Inc
* (inspired by Andi Kleen's thunk_64.S)
*/
+ #include <linux/export.h>
#include <linux/linkage.h>
#include <asm/asm.h>
- #include <asm/export.h>
/* put return address in eax (arg1) */
.macro THUNK name, func, put_ret_addr_in_eax=0
diff --git a/arch/x86/entry/thunk_64.S b/arch/x86/entry/thunk_64.S
index 27b5da2111ac..416b400f39db 100644
--- a/arch/x86/entry/thunk_64.S
+++ b/arch/x86/entry/thunk_64.S
@@ -4,10 +4,10 @@
* disturbance of register allocation in some inline assembly constructs.
* Copyright 2001,2002 by Andi Kleen, SuSE Labs.
*/
+#include <linux/export.h>
#include <linux/linkage.h>
#include "calling.h"
#include <asm/asm.h>
-#include <asm/export.h>
/* rdi: arg1 ... normal C conventions. rax is saved/restored. */
.macro THUNK name, func
diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
index 6a1821bd7d5e..b1b8dd1608f7 100644
--- a/arch/x86/entry/vdso/Makefile
+++ b/arch/x86/entry/vdso/Makefile
@@ -42,7 +42,8 @@ vdso_img-$(VDSO64-y) += 64
vdso_img-$(VDSOX32-y) += x32
vdso_img-$(VDSO32-y) += 32
-obj-$(VDSO32-y) += vdso32-setup.o
+obj-$(VDSO32-y) += vdso32-setup.o
+OBJECT_FILES_NON_STANDARD_vdso32-setup.o := n
vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
vobjs32 := $(foreach F,$(vobjs32-y),$(obj)/$F)
@@ -190,31 +191,4 @@ GCOV_PROFILE := n
quiet_cmd_vdso_and_check = VDSO $@
cmd_vdso_and_check = $(cmd_vdso); $(cmd_vdso_check)
-#
-# Install the unstripped copies of vdso*.so. If our toolchain supports
-# build-id, install .build-id links as well.
-#
-quiet_cmd_vdso_install = INSTALL $(@:install_%=%)
-define cmd_vdso_install
- cp $< "$(MODLIB)/vdso/$(@:install_%=%)"; \
- if readelf -n $< |grep -q 'Build ID'; then \
- buildid=`readelf -n $< |grep 'Build ID' |sed -e 's/^.*Build ID: \(.*\)$$/\1/'`; \
- first=`echo $$buildid | cut -b-2`; \
- last=`echo $$buildid | cut -b3-`; \
- mkdir -p "$(MODLIB)/vdso/.build-id/$$first"; \
- ln -sf "../../$(@:install_%=%)" "$(MODLIB)/vdso/.build-id/$$first/$$last.debug"; \
- fi
-endef
-
-vdso_img_insttargets := $(vdso_img_sodbg:%.dbg=install_%)
-
-$(MODLIB)/vdso: FORCE
- @mkdir -p $(MODLIB)/vdso
-
-$(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso
- $(call cmd,vdso_install)
-
-PHONY += vdso_install $(vdso_img_insttargets)
-vdso_install: $(vdso_img_insttargets)
-
clean-files := vdso32.so vdso32.so.dbg vdso64* vdso-image-*.c vdsox32.so*
diff --git a/arch/x86/entry/vdso/vdso32-setup.c b/arch/x86/entry/vdso/vdso32-setup.c
index f3b3cacbcbb0..76e4e74f35b5 100644
--- a/arch/x86/entry/vdso/vdso32-setup.c
+++ b/arch/x86/entry/vdso/vdso32-setup.c
@@ -67,7 +67,6 @@ static struct ctl_table abi_table2[] = {
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
- {}
};
static __init int ia32_binfmt_init(void)
diff --git a/arch/x86/entry/vdso/vsgx.S b/arch/x86/entry/vdso/vsgx.S
index d77d278ee9dd..37a3d4c02366 100644
--- a/arch/x86/entry/vdso/vsgx.S
+++ b/arch/x86/entry/vdso/vsgx.S
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/linkage.h>
-#include <asm/export.h>
#include <asm/errno.h>
#include <asm/enclu.h>
diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c
index 83f15fe411b3..5bf03c575812 100644
--- a/arch/x86/events/amd/uncore.c
+++ b/arch/x86/events/amd/uncore.c
@@ -26,57 +26,66 @@
#define RDPMC_BASE_LLC 10
#define COUNTER_SHIFT 16
+#define UNCORE_NAME_LEN 16
+#define UNCORE_GROUP_MAX 256
#undef pr_fmt
#define pr_fmt(fmt) "amd_uncore: " fmt
static int pmu_version;
-static int num_counters_llc;
-static int num_counters_nb;
-static bool l3_mask;
-static HLIST_HEAD(uncore_unused_list);
-
-struct amd_uncore {
- int id;
+struct amd_uncore_ctx {
int refcnt;
int cpu;
+ struct perf_event **events;
+ struct hlist_node node;
+};
+
+struct amd_uncore_pmu {
+ char name[UNCORE_NAME_LEN];
int num_counters;
int rdpmc_base;
u32 msr_base;
- cpumask_t *active_mask;
- struct pmu *pmu;
- struct perf_event **events;
- struct hlist_node node;
+ int group;
+ cpumask_t active_mask;
+ struct pmu pmu;
+ struct amd_uncore_ctx * __percpu *ctx;
};
-static struct amd_uncore * __percpu *amd_uncore_nb;
-static struct amd_uncore * __percpu *amd_uncore_llc;
+enum {
+ UNCORE_TYPE_DF,
+ UNCORE_TYPE_L3,
+ UNCORE_TYPE_UMC,
-static struct pmu amd_nb_pmu;
-static struct pmu amd_llc_pmu;
+ UNCORE_TYPE_MAX
+};
-static cpumask_t amd_nb_active_mask;
-static cpumask_t amd_llc_active_mask;
+union amd_uncore_info {
+ struct {
+ u64 aux_data:32; /* auxiliary data */
+ u64 num_pmcs:8; /* number of counters */
+ u64 gid:8; /* group id */
+ u64 cid:8; /* context id */
+ } split;
+ u64 full;
+};
-static bool is_nb_event(struct perf_event *event)
-{
- return event->pmu->type == amd_nb_pmu.type;
-}
+struct amd_uncore {
+ union amd_uncore_info * __percpu info;
+ struct amd_uncore_pmu *pmus;
+ unsigned int num_pmus;
+ bool init_done;
+ void (*scan)(struct amd_uncore *uncore, unsigned int cpu);
+ int (*init)(struct amd_uncore *uncore, unsigned int cpu);
+ void (*move)(struct amd_uncore *uncore, unsigned int cpu);
+ void (*free)(struct amd_uncore *uncore, unsigned int cpu);
+};
-static bool is_llc_event(struct perf_event *event)
-{
- return event->pmu->type == amd_llc_pmu.type;
-}
+static struct amd_uncore uncores[UNCORE_TYPE_MAX];
-static struct amd_uncore *event_to_amd_uncore(struct perf_event *event)
+static struct amd_uncore_pmu *event_to_amd_uncore_pmu(struct perf_event *event)
{
- if (is_nb_event(event) && amd_uncore_nb)
- return *per_cpu_ptr(amd_uncore_nb, event->cpu);
- else if (is_llc_event(event) && amd_uncore_llc)
- return *per_cpu_ptr(amd_uncore_llc, event->cpu);
-
- return NULL;
+ return container_of(event->pmu, struct amd_uncore_pmu, pmu);
}
static void amd_uncore_read(struct perf_event *event)
@@ -91,7 +100,16 @@ static void amd_uncore_read(struct perf_event *event)
*/
prev = local64_read(&hwc->prev_count);
- rdpmcl(hwc->event_base_rdpmc, new);
+
+ /*
+ * Some uncore PMUs do not have RDPMC assignments. In such cases,
+ * read counts directly from the corresponding PERF_CTR.
+ */
+ if (hwc->event_base_rdpmc < 0)
+ rdmsrl(hwc->event_base, new);
+ else
+ rdpmcl(hwc->event_base_rdpmc, new);
+
local64_set(&hwc->prev_count, new);
delta = (new << COUNTER_SHIFT) - (prev << COUNTER_SHIFT);
delta >>= COUNTER_SHIFT;
@@ -118,7 +136,7 @@ static void amd_uncore_stop(struct perf_event *event, int flags)
hwc->state |= PERF_HES_STOPPED;
if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
- amd_uncore_read(event);
+ event->pmu->read(event);
hwc->state |= PERF_HES_UPTODATE;
}
}
@@ -126,15 +144,16 @@ static void amd_uncore_stop(struct perf_event *event, int flags)
static int amd_uncore_add(struct perf_event *event, int flags)
{
int i;
- struct amd_uncore *uncore = event_to_amd_uncore(event);
+ struct amd_uncore_pmu *pmu = event_to_amd_uncore_pmu(event);
+ struct amd_uncore_ctx *ctx = *per_cpu_ptr(pmu->ctx, event->cpu);
struct hw_perf_event *hwc = &event->hw;
/* are we already assigned? */
- if (hwc->idx != -1 && uncore->events[hwc->idx] == event)
+ if (hwc->idx != -1 && ctx->events[hwc->idx] == event)
goto out;
- for (i = 0; i < uncore->num_counters; i++) {
- if (uncore->events[i] == event) {
+ for (i = 0; i < pmu->num_counters; i++) {
+ if (ctx->events[i] == event) {
hwc->idx = i;
goto out;
}
@@ -142,8 +161,8 @@ static int amd_uncore_add(struct perf_event *event, int flags)
/* if not, take the first available counter */
hwc->idx = -1;
- for (i = 0; i < uncore->num_counters; i++) {
- if (cmpxchg(&uncore->events[i], NULL, event) == NULL) {
+ for (i = 0; i < pmu->num_counters; i++) {
+ if (cmpxchg(&ctx->events[i], NULL, event) == NULL) {
hwc->idx = i;
break;
}
@@ -153,23 +172,16 @@ out:
if (hwc->idx == -1)
return -EBUSY;
- hwc->config_base = uncore->msr_base + (2 * hwc->idx);
- hwc->event_base = uncore->msr_base + 1 + (2 * hwc->idx);
- hwc->event_base_rdpmc = uncore->rdpmc_base + hwc->idx;
+ hwc->config_base = pmu->msr_base + (2 * hwc->idx);
+ hwc->event_base = pmu->msr_base + 1 + (2 * hwc->idx);
+ hwc->event_base_rdpmc = pmu->rdpmc_base + hwc->idx;
hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
- /*
- * The first four DF counters are accessible via RDPMC index 6 to 9
- * followed by the L3 counters from index 10 to 15. For processors
- * with more than four DF counters, the DF RDPMC assignments become
- * discontiguous as the additional counters are accessible starting
- * from index 16.
- */
- if (is_nb_event(event) && hwc->idx >= NUM_COUNTERS_NB)
- hwc->event_base_rdpmc += NUM_COUNTERS_L3;
+ if (pmu->rdpmc_base < 0)
+ hwc->event_base_rdpmc = -1;
if (flags & PERF_EF_START)
- amd_uncore_start(event, PERF_EF_RELOAD);
+ event->pmu->start(event, PERF_EF_RELOAD);
return 0;
}
@@ -177,55 +189,36 @@ out:
static void amd_uncore_del(struct perf_event *event, int flags)
{
int i;
- struct amd_uncore *uncore = event_to_amd_uncore(event);
+ struct amd_uncore_pmu *pmu = event_to_amd_uncore_pmu(event);
+ struct amd_uncore_ctx *ctx = *per_cpu_ptr(pmu->ctx, event->cpu);
struct hw_perf_event *hwc = &event->hw;
- amd_uncore_stop(event, PERF_EF_UPDATE);
+ event->pmu->stop(event, PERF_EF_UPDATE);
- for (i = 0; i < uncore->num_counters; i++) {
- if (cmpxchg(&uncore->events[i], event, NULL) == event)
+ for (i = 0; i < pmu->num_counters; i++) {
+ if (cmpxchg(&ctx->events[i], event, NULL) == event)
break;
}
hwc->idx = -1;
}
-/*
- * Return a full thread and slice mask unless user
- * has provided them
- */
-static u64 l3_thread_slice_mask(u64 config)
-{
- if (boot_cpu_data.x86 <= 0x18)
- return ((config & AMD64_L3_SLICE_MASK) ? : AMD64_L3_SLICE_MASK) |
- ((config & AMD64_L3_THREAD_MASK) ? : AMD64_L3_THREAD_MASK);
-
- /*
- * If the user doesn't specify a threadmask, they're not trying to
- * count core 0, so we enable all cores & threads.
- * We'll also assume that they want to count slice 0 if they specify
- * a threadmask and leave sliceid and enallslices unpopulated.
- */
- if (!(config & AMD64_L3_F19H_THREAD_MASK))
- return AMD64_L3_F19H_THREAD_MASK | AMD64_L3_EN_ALL_SLICES |
- AMD64_L3_EN_ALL_CORES;
-
- return config & (AMD64_L3_F19H_THREAD_MASK | AMD64_L3_SLICEID_MASK |
- AMD64_L3_EN_ALL_CORES | AMD64_L3_EN_ALL_SLICES |
- AMD64_L3_COREID_MASK);
-}
-
static int amd_uncore_event_init(struct perf_event *event)
{
- struct amd_uncore *uncore;
+ struct amd_uncore_pmu *pmu;
+ struct amd_uncore_ctx *ctx;
struct hw_perf_event *hwc = &event->hw;
- u64 event_mask = AMD64_RAW_EVENT_MASK_NB;
if (event->attr.type != event->pmu->type)
return -ENOENT;
- if (pmu_version >= 2 && is_nb_event(event))
- event_mask = AMD64_PERFMON_V2_RAW_EVENT_MASK_NB;
+ if (event->cpu < 0)
+ return -EINVAL;
+
+ pmu = event_to_amd_uncore_pmu(event);
+ ctx = *per_cpu_ptr(pmu->ctx, event->cpu);
+ if (!ctx)
+ return -ENODEV;
/*
* NB and Last level cache counters (MSRs) are shared across all cores
@@ -235,28 +228,14 @@ static int amd_uncore_event_init(struct perf_event *event)
* out. So we do not support sampling and per-thread events via
* CAP_NO_INTERRUPT, and we do not enable counter overflow interrupts:
*/
- hwc->config = event->attr.config & event_mask;
+ hwc->config = event->attr.config;
hwc->idx = -1;
- if (event->cpu < 0)
- return -EINVAL;
-
- /*
- * SliceMask and ThreadMask need to be set for certain L3 events.
- * For other events, the two fields do not affect the count.
- */
- if (l3_mask && is_llc_event(event))
- hwc->config |= l3_thread_slice_mask(event->attr.config);
-
- uncore = event_to_amd_uncore(event);
- if (!uncore)
- return -ENODEV;
-
/*
* since request can come in to any of the shared cores, we will remap
* to a single common cpu.
*/
- event->cpu = uncore->cpu;
+ event->cpu = ctx->cpu;
return 0;
}
@@ -278,17 +257,10 @@ static ssize_t amd_uncore_attr_show_cpumask(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- cpumask_t *active_mask;
- struct pmu *pmu = dev_get_drvdata(dev);
+ struct pmu *ptr = dev_get_drvdata(dev);
+ struct amd_uncore_pmu *pmu = container_of(ptr, struct amd_uncore_pmu, pmu);
- if (pmu->type == amd_nb_pmu.type)
- active_mask = &amd_nb_active_mask;
- else if (pmu->type == amd_llc_pmu.type)
- active_mask = &amd_llc_active_mask;
- else
- return 0;
-
- return cpumap_print_to_pagebuf(true, buf, active_mask);
+ return cpumap_print_to_pagebuf(true, buf, &pmu->active_mask);
}
static DEVICE_ATTR(cpumask, S_IRUGO, amd_uncore_attr_show_cpumask, NULL);
@@ -315,7 +287,7 @@ static struct device_attribute format_attr_##_var = \
DEFINE_UNCORE_FORMAT_ATTR(event12, event, "config:0-7,32-35");
DEFINE_UNCORE_FORMAT_ATTR(event14, event, "config:0-7,32-35,59-60"); /* F17h+ DF */
DEFINE_UNCORE_FORMAT_ATTR(event14v2, event, "config:0-7,32-37"); /* PerfMonV2 DF */
-DEFINE_UNCORE_FORMAT_ATTR(event8, event, "config:0-7"); /* F17h+ L3 */
+DEFINE_UNCORE_FORMAT_ATTR(event8, event, "config:0-7"); /* F17h+ L3, PerfMonV2 UMC */
DEFINE_UNCORE_FORMAT_ATTR(umask8, umask, "config:8-15");
DEFINE_UNCORE_FORMAT_ATTR(umask12, umask, "config:8-15,24-27"); /* PerfMonV2 DF */
DEFINE_UNCORE_FORMAT_ATTR(coreid, coreid, "config:42-44"); /* F19h L3 */
@@ -325,6 +297,7 @@ DEFINE_UNCORE_FORMAT_ATTR(threadmask2, threadmask, "config:56-57"); /* F19h L
DEFINE_UNCORE_FORMAT_ATTR(enallslices, enallslices, "config:46"); /* F19h L3 */
DEFINE_UNCORE_FORMAT_ATTR(enallcores, enallcores, "config:47"); /* F19h L3 */
DEFINE_UNCORE_FORMAT_ATTR(sliceid, sliceid, "config:48-50"); /* F19h L3 */
+DEFINE_UNCORE_FORMAT_ATTR(rdwrmask, rdwrmask, "config:8-9"); /* PerfMonV2 UMC */
/* Common DF and NB attributes */
static struct attribute *amd_uncore_df_format_attr[] = {
@@ -341,6 +314,13 @@ static struct attribute *amd_uncore_l3_format_attr[] = {
NULL,
};
+/* Common UMC attributes */
+static struct attribute *amd_uncore_umc_format_attr[] = {
+ &format_attr_event8.attr, /* event */
+ &format_attr_rdwrmask.attr, /* rdwrmask */
+ NULL,
+};
+
/* F17h unique L3 attributes */
static struct attribute *amd_f17h_uncore_l3_format_attr[] = {
&format_attr_slicemask.attr, /* slicemask */
@@ -378,6 +358,11 @@ static struct attribute_group amd_f19h_uncore_l3_format_group = {
.is_visible = amd_f19h_uncore_is_visible,
};
+static struct attribute_group amd_uncore_umc_format_group = {
+ .name = "format",
+ .attrs = amd_uncore_umc_format_attr,
+};
+
static const struct attribute_group *amd_uncore_df_attr_groups[] = {
&amd_uncore_attr_group,
&amd_uncore_df_format_group,
@@ -396,259 +381,636 @@ static const struct attribute_group *amd_uncore_l3_attr_update[] = {
NULL,
};
-static struct pmu amd_nb_pmu = {
- .task_ctx_nr = perf_invalid_context,
- .attr_groups = amd_uncore_df_attr_groups,
- .name = "amd_nb",
- .event_init = amd_uncore_event_init,
- .add = amd_uncore_add,
- .del = amd_uncore_del,
- .start = amd_uncore_start,
- .stop = amd_uncore_stop,
- .read = amd_uncore_read,
- .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
- .module = THIS_MODULE,
+static const struct attribute_group *amd_uncore_umc_attr_groups[] = {
+ &amd_uncore_attr_group,
+ &amd_uncore_umc_format_group,
+ NULL,
};
-static struct pmu amd_llc_pmu = {
- .task_ctx_nr = perf_invalid_context,
- .attr_groups = amd_uncore_l3_attr_groups,
- .attr_update = amd_uncore_l3_attr_update,
- .name = "amd_l2",
- .event_init = amd_uncore_event_init,
- .add = amd_uncore_add,
- .del = amd_uncore_del,
- .start = amd_uncore_start,
- .stop = amd_uncore_stop,
- .read = amd_uncore_read,
- .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
- .module = THIS_MODULE,
-};
+static __always_inline
+int amd_uncore_ctx_cid(struct amd_uncore *uncore, unsigned int cpu)
+{
+ union amd_uncore_info *info = per_cpu_ptr(uncore->info, cpu);
+ return info->split.cid;
+}
-static struct amd_uncore *amd_uncore_alloc(unsigned int cpu)
+static __always_inline
+int amd_uncore_ctx_gid(struct amd_uncore *uncore, unsigned int cpu)
{
- return kzalloc_node(sizeof(struct amd_uncore), GFP_KERNEL,
- cpu_to_node(cpu));
+ union amd_uncore_info *info = per_cpu_ptr(uncore->info, cpu);
+ return info->split.gid;
}
-static inline struct perf_event **
-amd_uncore_events_alloc(unsigned int num, unsigned int cpu)
+static __always_inline
+int amd_uncore_ctx_num_pmcs(struct amd_uncore *uncore, unsigned int cpu)
{
- return kzalloc_node(sizeof(struct perf_event *) * num, GFP_KERNEL,
- cpu_to_node(cpu));
+ union amd_uncore_info *info = per_cpu_ptr(uncore->info, cpu);
+ return info->split.num_pmcs;
}
-static int amd_uncore_cpu_up_prepare(unsigned int cpu)
+static void amd_uncore_ctx_free(struct amd_uncore *uncore, unsigned int cpu)
{
- struct amd_uncore *uncore_nb = NULL, *uncore_llc = NULL;
+ struct amd_uncore_pmu *pmu;
+ struct amd_uncore_ctx *ctx;
+ int i;
- if (amd_uncore_nb) {
- *per_cpu_ptr(amd_uncore_nb, cpu) = NULL;
- uncore_nb = amd_uncore_alloc(cpu);
- if (!uncore_nb)
- goto fail;
- uncore_nb->cpu = cpu;
- uncore_nb->num_counters = num_counters_nb;
- uncore_nb->rdpmc_base = RDPMC_BASE_NB;
- uncore_nb->msr_base = MSR_F15H_NB_PERF_CTL;
- uncore_nb->active_mask = &amd_nb_active_mask;
- uncore_nb->pmu = &amd_nb_pmu;
- uncore_nb->events = amd_uncore_events_alloc(num_counters_nb, cpu);
- if (!uncore_nb->events)
- goto fail;
- uncore_nb->id = -1;
- *per_cpu_ptr(amd_uncore_nb, cpu) = uncore_nb;
+ if (!uncore->init_done)
+ return;
+
+ for (i = 0; i < uncore->num_pmus; i++) {
+ pmu = &uncore->pmus[i];
+ ctx = *per_cpu_ptr(pmu->ctx, cpu);
+ if (!ctx)
+ continue;
+
+ if (cpu == ctx->cpu)
+ cpumask_clear_cpu(cpu, &pmu->active_mask);
+
+ if (!--ctx->refcnt) {
+ kfree(ctx->events);
+ kfree(ctx);
+ }
+
+ *per_cpu_ptr(pmu->ctx, cpu) = NULL;
}
+}
- if (amd_uncore_llc) {
- *per_cpu_ptr(amd_uncore_llc, cpu) = NULL;
- uncore_llc = amd_uncore_alloc(cpu);
- if (!uncore_llc)
- goto fail;
- uncore_llc->cpu = cpu;
- uncore_llc->num_counters = num_counters_llc;
- uncore_llc->rdpmc_base = RDPMC_BASE_LLC;
- uncore_llc->msr_base = MSR_F16H_L2I_PERF_CTL;
- uncore_llc->active_mask = &amd_llc_active_mask;
- uncore_llc->pmu = &amd_llc_pmu;
- uncore_llc->events = amd_uncore_events_alloc(num_counters_llc, cpu);
- if (!uncore_llc->events)
- goto fail;
- uncore_llc->id = -1;
- *per_cpu_ptr(amd_uncore_llc, cpu) = uncore_llc;
+static int amd_uncore_ctx_init(struct amd_uncore *uncore, unsigned int cpu)
+{
+ struct amd_uncore_ctx *curr, *prev;
+ struct amd_uncore_pmu *pmu;
+ int node, cid, gid, i, j;
+
+ if (!uncore->init_done || !uncore->num_pmus)
+ return 0;
+
+ cid = amd_uncore_ctx_cid(uncore, cpu);
+ gid = amd_uncore_ctx_gid(uncore, cpu);
+
+ for (i = 0; i < uncore->num_pmus; i++) {
+ pmu = &uncore->pmus[i];
+ *per_cpu_ptr(pmu->ctx, cpu) = NULL;
+ curr = NULL;
+
+ /* Check for group exclusivity */
+ if (gid != pmu->group)
+ continue;
+
+ /* Find a sibling context */
+ for_each_online_cpu(j) {
+ if (cpu == j)
+ continue;
+
+ prev = *per_cpu_ptr(pmu->ctx, j);
+ if (!prev)
+ continue;
+
+ if (cid == amd_uncore_ctx_cid(uncore, j)) {
+ curr = prev;
+ break;
+ }
+ }
+
+ /* Allocate context if sibling does not exist */
+ if (!curr) {
+ node = cpu_to_node(cpu);
+ curr = kzalloc_node(sizeof(*curr), GFP_KERNEL, node);
+ if (!curr)
+ goto fail;
+
+ curr->cpu = cpu;
+ curr->events = kzalloc_node(sizeof(*curr->events) *
+ pmu->num_counters,
+ GFP_KERNEL, node);
+ if (!curr->events) {
+ kfree(curr);
+ goto fail;
+ }
+
+ cpumask_set_cpu(cpu, &pmu->active_mask);
+ }
+
+ curr->refcnt++;
+ *per_cpu_ptr(pmu->ctx, cpu) = curr;
}
return 0;
fail:
- if (uncore_nb) {
- kfree(uncore_nb->events);
- kfree(uncore_nb);
- }
-
- if (uncore_llc) {
- kfree(uncore_llc->events);
- kfree(uncore_llc);
- }
+ amd_uncore_ctx_free(uncore, cpu);
return -ENOMEM;
}
-static struct amd_uncore *
-amd_uncore_find_online_sibling(struct amd_uncore *this,
- struct amd_uncore * __percpu *uncores)
+static void amd_uncore_ctx_move(struct amd_uncore *uncore, unsigned int cpu)
{
- unsigned int cpu;
- struct amd_uncore *that;
-
- for_each_online_cpu(cpu) {
- that = *per_cpu_ptr(uncores, cpu);
+ struct amd_uncore_ctx *curr, *next;
+ struct amd_uncore_pmu *pmu;
+ int i, j;
- if (!that)
- continue;
+ if (!uncore->init_done)
+ return;
- if (this == that)
+ for (i = 0; i < uncore->num_pmus; i++) {
+ pmu = &uncore->pmus[i];
+ curr = *per_cpu_ptr(pmu->ctx, cpu);
+ if (!curr)
continue;
- if (this->id == that->id) {
- hlist_add_head(&this->node, &uncore_unused_list);
- this = that;
- break;
+ /* Migrate to a shared sibling if possible */
+ for_each_online_cpu(j) {
+ next = *per_cpu_ptr(pmu->ctx, j);
+ if (!next || cpu == j)
+ continue;
+
+ if (curr == next) {
+ perf_pmu_migrate_context(&pmu->pmu, cpu, j);
+ cpumask_clear_cpu(cpu, &pmu->active_mask);
+ cpumask_set_cpu(j, &pmu->active_mask);
+ next->cpu = j;
+ break;
+ }
}
}
-
- this->refcnt++;
- return this;
}
static int amd_uncore_cpu_starting(unsigned int cpu)
{
- unsigned int eax, ebx, ecx, edx;
struct amd_uncore *uncore;
+ int i;
+
+ for (i = 0; i < UNCORE_TYPE_MAX; i++) {
+ uncore = &uncores[i];
+ uncore->scan(uncore, cpu);
+ }
+
+ return 0;
+}
- if (amd_uncore_nb) {
- uncore = *per_cpu_ptr(amd_uncore_nb, cpu);
- cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
- uncore->id = ecx & 0xff;
+static int amd_uncore_cpu_online(unsigned int cpu)
+{
+ struct amd_uncore *uncore;
+ int i;
- uncore = amd_uncore_find_online_sibling(uncore, amd_uncore_nb);
- *per_cpu_ptr(amd_uncore_nb, cpu) = uncore;
+ for (i = 0; i < UNCORE_TYPE_MAX; i++) {
+ uncore = &uncores[i];
+ if (uncore->init(uncore, cpu))
+ break;
}
- if (amd_uncore_llc) {
- uncore = *per_cpu_ptr(amd_uncore_llc, cpu);
- uncore->id = get_llc_id(cpu);
+ return 0;
+}
- uncore = amd_uncore_find_online_sibling(uncore, amd_uncore_llc);
- *per_cpu_ptr(amd_uncore_llc, cpu) = uncore;
+static int amd_uncore_cpu_down_prepare(unsigned int cpu)
+{
+ struct amd_uncore *uncore;
+ int i;
+
+ for (i = 0; i < UNCORE_TYPE_MAX; i++) {
+ uncore = &uncores[i];
+ uncore->move(uncore, cpu);
}
return 0;
}
-static void uncore_clean_online(void)
+static int amd_uncore_cpu_dead(unsigned int cpu)
{
struct amd_uncore *uncore;
- struct hlist_node *n;
+ int i;
- hlist_for_each_entry_safe(uncore, n, &uncore_unused_list, node) {
- hlist_del(&uncore->node);
- kfree(uncore->events);
- kfree(uncore);
+ for (i = 0; i < UNCORE_TYPE_MAX; i++) {
+ uncore = &uncores[i];
+ uncore->free(uncore, cpu);
}
+
+ return 0;
}
-static void uncore_online(unsigned int cpu,
- struct amd_uncore * __percpu *uncores)
+static int amd_uncore_df_event_init(struct perf_event *event)
{
- struct amd_uncore *uncore = *per_cpu_ptr(uncores, cpu);
+ struct hw_perf_event *hwc = &event->hw;
+ int ret = amd_uncore_event_init(event);
- uncore_clean_online();
+ if (ret || pmu_version < 2)
+ return ret;
- if (cpu == uncore->cpu)
- cpumask_set_cpu(cpu, uncore->active_mask);
+ hwc->config = event->attr.config &
+ (pmu_version >= 2 ? AMD64_PERFMON_V2_RAW_EVENT_MASK_NB :
+ AMD64_RAW_EVENT_MASK_NB);
+
+ return 0;
}
-static int amd_uncore_cpu_online(unsigned int cpu)
+static int amd_uncore_df_add(struct perf_event *event, int flags)
{
- if (amd_uncore_nb)
- uncore_online(cpu, amd_uncore_nb);
+ int ret = amd_uncore_add(event, flags & ~PERF_EF_START);
+ struct hw_perf_event *hwc = &event->hw;
+
+ if (ret)
+ return ret;
+
+ /*
+ * The first four DF counters are accessible via RDPMC index 6 to 9
+ * followed by the L3 counters from index 10 to 15. For processors
+ * with more than four DF counters, the DF RDPMC assignments become
+ * discontiguous as the additional counters are accessible starting
+ * from index 16.
+ */
+ if (hwc->idx >= NUM_COUNTERS_NB)
+ hwc->event_base_rdpmc += NUM_COUNTERS_L3;
- if (amd_uncore_llc)
- uncore_online(cpu, amd_uncore_llc);
+ /* Delayed start after rdpmc base update */
+ if (flags & PERF_EF_START)
+ amd_uncore_start(event, PERF_EF_RELOAD);
return 0;
}
-static void uncore_down_prepare(unsigned int cpu,
- struct amd_uncore * __percpu *uncores)
+static
+void amd_uncore_df_ctx_scan(struct amd_uncore *uncore, unsigned int cpu)
{
- unsigned int i;
- struct amd_uncore *this = *per_cpu_ptr(uncores, cpu);
+ union cpuid_0x80000022_ebx ebx;
+ union amd_uncore_info info;
- if (this->cpu != cpu)
+ if (!boot_cpu_has(X86_FEATURE_PERFCTR_NB))
return;
- /* this cpu is going down, migrate to a shared sibling if possible */
- for_each_online_cpu(i) {
- struct amd_uncore *that = *per_cpu_ptr(uncores, i);
+ info.split.aux_data = 0;
+ info.split.num_pmcs = NUM_COUNTERS_NB;
+ info.split.gid = 0;
+ info.split.cid = topology_die_id(cpu);
- if (cpu == i)
- continue;
+ if (pmu_version >= 2) {
+ ebx.full = cpuid_ebx(EXT_PERFMON_DEBUG_FEATURES);
+ info.split.num_pmcs = ebx.split.num_df_pmc;
+ }
- if (this == that) {
- perf_pmu_migrate_context(this->pmu, cpu, i);
- cpumask_clear_cpu(cpu, that->active_mask);
- cpumask_set_cpu(i, that->active_mask);
- that->cpu = i;
- break;
- }
+ *per_cpu_ptr(uncore->info, cpu) = info;
+}
+
+static
+int amd_uncore_df_ctx_init(struct amd_uncore *uncore, unsigned int cpu)
+{
+ struct attribute **df_attr = amd_uncore_df_format_attr;
+ struct amd_uncore_pmu *pmu;
+
+ /* Run just once */
+ if (uncore->init_done)
+ return amd_uncore_ctx_init(uncore, cpu);
+
+ /* No grouping, single instance for a system */
+ uncore->pmus = kzalloc(sizeof(*uncore->pmus), GFP_KERNEL);
+ if (!uncore->pmus) {
+ uncore->num_pmus = 0;
+ goto done;
}
+
+ /*
+ * For Family 17h and above, the Northbridge counters are repurposed
+ * as Data Fabric counters. The PMUs are exported based on family as
+ * either NB or DF.
+ */
+ pmu = &uncore->pmus[0];
+ strscpy(pmu->name, boot_cpu_data.x86 >= 0x17 ? "amd_df" : "amd_nb",
+ sizeof(pmu->name));
+ pmu->num_counters = amd_uncore_ctx_num_pmcs(uncore, cpu);
+ pmu->msr_base = MSR_F15H_NB_PERF_CTL;
+ pmu->rdpmc_base = RDPMC_BASE_NB;
+ pmu->group = amd_uncore_ctx_gid(uncore, cpu);
+
+ if (pmu_version >= 2) {
+ *df_attr++ = &format_attr_event14v2.attr;
+ *df_attr++ = &format_attr_umask12.attr;
+ } else if (boot_cpu_data.x86 >= 0x17) {
+ *df_attr = &format_attr_event14.attr;
+ }
+
+ pmu->ctx = alloc_percpu(struct amd_uncore_ctx *);
+ if (!pmu->ctx)
+ goto done;
+
+ pmu->pmu = (struct pmu) {
+ .task_ctx_nr = perf_invalid_context,
+ .attr_groups = amd_uncore_df_attr_groups,
+ .name = pmu->name,
+ .event_init = amd_uncore_df_event_init,
+ .add = amd_uncore_df_add,
+ .del = amd_uncore_del,
+ .start = amd_uncore_start,
+ .stop = amd_uncore_stop,
+ .read = amd_uncore_read,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
+ .module = THIS_MODULE,
+ };
+
+ if (perf_pmu_register(&pmu->pmu, pmu->pmu.name, -1)) {
+ free_percpu(pmu->ctx);
+ pmu->ctx = NULL;
+ goto done;
+ }
+
+ pr_info("%d %s%s counters detected\n", pmu->num_counters,
+ boot_cpu_data.x86_vendor == X86_VENDOR_HYGON ? "HYGON " : "",
+ pmu->pmu.name);
+
+ uncore->num_pmus = 1;
+
+done:
+ uncore->init_done = true;
+
+ return amd_uncore_ctx_init(uncore, cpu);
}
-static int amd_uncore_cpu_down_prepare(unsigned int cpu)
+static int amd_uncore_l3_event_init(struct perf_event *event)
{
- if (amd_uncore_nb)
- uncore_down_prepare(cpu, amd_uncore_nb);
+ int ret = amd_uncore_event_init(event);
+ struct hw_perf_event *hwc = &event->hw;
+ u64 config = event->attr.config;
+ u64 mask;
- if (amd_uncore_llc)
- uncore_down_prepare(cpu, amd_uncore_llc);
+ hwc->config = config & AMD64_RAW_EVENT_MASK_NB;
+
+ /*
+ * SliceMask and ThreadMask need to be set for certain L3 events.
+ * For other events, the two fields do not affect the count.
+ */
+ if (ret || boot_cpu_data.x86 < 0x17)
+ return ret;
+
+ mask = config & (AMD64_L3_F19H_THREAD_MASK | AMD64_L3_SLICEID_MASK |
+ AMD64_L3_EN_ALL_CORES | AMD64_L3_EN_ALL_SLICES |
+ AMD64_L3_COREID_MASK);
+
+ if (boot_cpu_data.x86 <= 0x18)
+ mask = ((config & AMD64_L3_SLICE_MASK) ? : AMD64_L3_SLICE_MASK) |
+ ((config & AMD64_L3_THREAD_MASK) ? : AMD64_L3_THREAD_MASK);
+
+ /*
+ * If the user doesn't specify a ThreadMask, they're not trying to
+ * count core 0, so we enable all cores & threads.
+ * We'll also assume that they want to count slice 0 if they specify
+ * a ThreadMask and leave SliceId and EnAllSlices unpopulated.
+ */
+ else if (!(config & AMD64_L3_F19H_THREAD_MASK))
+ mask = AMD64_L3_F19H_THREAD_MASK | AMD64_L3_EN_ALL_SLICES |
+ AMD64_L3_EN_ALL_CORES;
+
+ hwc->config |= mask;
return 0;
}
-static void uncore_dead(unsigned int cpu, struct amd_uncore * __percpu *uncores)
+static
+void amd_uncore_l3_ctx_scan(struct amd_uncore *uncore, unsigned int cpu)
{
- struct amd_uncore *uncore = *per_cpu_ptr(uncores, cpu);
+ union amd_uncore_info info;
- if (cpu == uncore->cpu)
- cpumask_clear_cpu(cpu, uncore->active_mask);
+ if (!boot_cpu_has(X86_FEATURE_PERFCTR_LLC))
+ return;
+
+ info.split.aux_data = 0;
+ info.split.num_pmcs = NUM_COUNTERS_L2;
+ info.split.gid = 0;
+ info.split.cid = per_cpu_llc_id(cpu);
- if (!--uncore->refcnt) {
- kfree(uncore->events);
- kfree(uncore);
+ if (boot_cpu_data.x86 >= 0x17)
+ info.split.num_pmcs = NUM_COUNTERS_L3;
+
+ *per_cpu_ptr(uncore->info, cpu) = info;
+}
+
+static
+int amd_uncore_l3_ctx_init(struct amd_uncore *uncore, unsigned int cpu)
+{
+ struct attribute **l3_attr = amd_uncore_l3_format_attr;
+ struct amd_uncore_pmu *pmu;
+
+ /* Run just once */
+ if (uncore->init_done)
+ return amd_uncore_ctx_init(uncore, cpu);
+
+ /* No grouping, single instance for a system */
+ uncore->pmus = kzalloc(sizeof(*uncore->pmus), GFP_KERNEL);
+ if (!uncore->pmus) {
+ uncore->num_pmus = 0;
+ goto done;
}
- *per_cpu_ptr(uncores, cpu) = NULL;
+ /*
+ * For Family 17h and above, L3 cache counters are available instead
+ * of L2 cache counters. The PMUs are exported based on family as
+ * either L2 or L3.
+ */
+ pmu = &uncore->pmus[0];
+ strscpy(pmu->name, boot_cpu_data.x86 >= 0x17 ? "amd_l3" : "amd_l2",
+ sizeof(pmu->name));
+ pmu->num_counters = amd_uncore_ctx_num_pmcs(uncore, cpu);
+ pmu->msr_base = MSR_F16H_L2I_PERF_CTL;
+ pmu->rdpmc_base = RDPMC_BASE_LLC;
+ pmu->group = amd_uncore_ctx_gid(uncore, cpu);
+
+ if (boot_cpu_data.x86 >= 0x17) {
+ *l3_attr++ = &format_attr_event8.attr;
+ *l3_attr++ = &format_attr_umask8.attr;
+ *l3_attr++ = boot_cpu_data.x86 >= 0x19 ?
+ &format_attr_threadmask2.attr :
+ &format_attr_threadmask8.attr;
+ }
+
+ pmu->ctx = alloc_percpu(struct amd_uncore_ctx *);
+ if (!pmu->ctx)
+ goto done;
+
+ pmu->pmu = (struct pmu) {
+ .task_ctx_nr = perf_invalid_context,
+ .attr_groups = amd_uncore_l3_attr_groups,
+ .attr_update = amd_uncore_l3_attr_update,
+ .name = pmu->name,
+ .event_init = amd_uncore_l3_event_init,
+ .add = amd_uncore_add,
+ .del = amd_uncore_del,
+ .start = amd_uncore_start,
+ .stop = amd_uncore_stop,
+ .read = amd_uncore_read,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
+ .module = THIS_MODULE,
+ };
+
+ if (perf_pmu_register(&pmu->pmu, pmu->pmu.name, -1)) {
+ free_percpu(pmu->ctx);
+ pmu->ctx = NULL;
+ goto done;
+ }
+
+ pr_info("%d %s%s counters detected\n", pmu->num_counters,
+ boot_cpu_data.x86_vendor == X86_VENDOR_HYGON ? "HYGON " : "",
+ pmu->pmu.name);
+
+ uncore->num_pmus = 1;
+
+done:
+ uncore->init_done = true;
+
+ return amd_uncore_ctx_init(uncore, cpu);
}
-static int amd_uncore_cpu_dead(unsigned int cpu)
+static int amd_uncore_umc_event_init(struct perf_event *event)
{
- if (amd_uncore_nb)
- uncore_dead(cpu, amd_uncore_nb);
+ struct hw_perf_event *hwc = &event->hw;
+ int ret = amd_uncore_event_init(event);
+
+ if (ret)
+ return ret;
- if (amd_uncore_llc)
- uncore_dead(cpu, amd_uncore_llc);
+ hwc->config = event->attr.config & AMD64_PERFMON_V2_RAW_EVENT_MASK_UMC;
return 0;
}
-static int __init amd_uncore_init(void)
+static void amd_uncore_umc_start(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ if (flags & PERF_EF_RELOAD)
+ wrmsrl(hwc->event_base, (u64)local64_read(&hwc->prev_count));
+
+ hwc->state = 0;
+ wrmsrl(hwc->config_base, (hwc->config | AMD64_PERFMON_V2_ENABLE_UMC));
+ perf_event_update_userpage(event);
+}
+
+static
+void amd_uncore_umc_ctx_scan(struct amd_uncore *uncore, unsigned int cpu)
{
- struct attribute **df_attr = amd_uncore_df_format_attr;
- struct attribute **l3_attr = amd_uncore_l3_format_attr;
union cpuid_0x80000022_ebx ebx;
+ union amd_uncore_info info;
+ unsigned int eax, ecx, edx;
+
+ if (pmu_version < 2)
+ return;
+
+ cpuid(EXT_PERFMON_DEBUG_FEATURES, &eax, &ebx.full, &ecx, &edx);
+ info.split.aux_data = ecx; /* stash active mask */
+ info.split.num_pmcs = ebx.split.num_umc_pmc;
+ info.split.gid = topology_die_id(cpu);
+ info.split.cid = topology_die_id(cpu);
+ *per_cpu_ptr(uncore->info, cpu) = info;
+}
+
+static
+int amd_uncore_umc_ctx_init(struct amd_uncore *uncore, unsigned int cpu)
+{
+ DECLARE_BITMAP(gmask, UNCORE_GROUP_MAX) = { 0 };
+ u8 group_num_pmus[UNCORE_GROUP_MAX] = { 0 };
+ u8 group_num_pmcs[UNCORE_GROUP_MAX] = { 0 };
+ union amd_uncore_info info;
+ struct amd_uncore_pmu *pmu;
+ int index = 0, gid, i;
+
+ if (pmu_version < 2)
+ return 0;
+
+ /* Run just once */
+ if (uncore->init_done)
+ return amd_uncore_ctx_init(uncore, cpu);
+
+ /* Find unique groups */
+ for_each_online_cpu(i) {
+ info = *per_cpu_ptr(uncore->info, i);
+ gid = info.split.gid;
+ if (test_bit(gid, gmask))
+ continue;
+
+ __set_bit(gid, gmask);
+ group_num_pmus[gid] = hweight32(info.split.aux_data);
+ group_num_pmcs[gid] = info.split.num_pmcs;
+ uncore->num_pmus += group_num_pmus[gid];
+ }
+
+ uncore->pmus = kzalloc(sizeof(*uncore->pmus) * uncore->num_pmus,
+ GFP_KERNEL);
+ if (!uncore->pmus) {
+ uncore->num_pmus = 0;
+ goto done;
+ }
+
+ for_each_set_bit(gid, gmask, UNCORE_GROUP_MAX) {
+ for (i = 0; i < group_num_pmus[gid]; i++) {
+ pmu = &uncore->pmus[index];
+ snprintf(pmu->name, sizeof(pmu->name), "amd_umc_%d", index);
+ pmu->num_counters = group_num_pmcs[gid] / group_num_pmus[gid];
+ pmu->msr_base = MSR_F19H_UMC_PERF_CTL + i * pmu->num_counters * 2;
+ pmu->rdpmc_base = -1;
+ pmu->group = gid;
+
+ pmu->ctx = alloc_percpu(struct amd_uncore_ctx *);
+ if (!pmu->ctx)
+ goto done;
+
+ pmu->pmu = (struct pmu) {
+ .task_ctx_nr = perf_invalid_context,
+ .attr_groups = amd_uncore_umc_attr_groups,
+ .name = pmu->name,
+ .event_init = amd_uncore_umc_event_init,
+ .add = amd_uncore_add,
+ .del = amd_uncore_del,
+ .start = amd_uncore_umc_start,
+ .stop = amd_uncore_stop,
+ .read = amd_uncore_read,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
+ .module = THIS_MODULE,
+ };
+
+ if (perf_pmu_register(&pmu->pmu, pmu->pmu.name, -1)) {
+ free_percpu(pmu->ctx);
+ pmu->ctx = NULL;
+ goto done;
+ }
+
+ pr_info("%d %s counters detected\n", pmu->num_counters,
+ pmu->pmu.name);
+
+ index++;
+ }
+ }
+
+done:
+ uncore->num_pmus = index;
+ uncore->init_done = true;
+
+ return amd_uncore_ctx_init(uncore, cpu);
+}
+
+static struct amd_uncore uncores[UNCORE_TYPE_MAX] = {
+ /* UNCORE_TYPE_DF */
+ {
+ .scan = amd_uncore_df_ctx_scan,
+ .init = amd_uncore_df_ctx_init,
+ .move = amd_uncore_ctx_move,
+ .free = amd_uncore_ctx_free,
+ },
+ /* UNCORE_TYPE_L3 */
+ {
+ .scan = amd_uncore_l3_ctx_scan,
+ .init = amd_uncore_l3_ctx_init,
+ .move = amd_uncore_ctx_move,
+ .free = amd_uncore_ctx_free,
+ },
+ /* UNCORE_TYPE_UMC */
+ {
+ .scan = amd_uncore_umc_ctx_scan,
+ .init = amd_uncore_umc_ctx_init,
+ .move = amd_uncore_ctx_move,
+ .free = amd_uncore_ctx_free,
+ },
+};
+
+static int __init amd_uncore_init(void)
+{
+ struct amd_uncore *uncore;
int ret = -ENODEV;
+ int i;
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
@@ -660,125 +1022,91 @@ static int __init amd_uncore_init(void)
if (boot_cpu_has(X86_FEATURE_PERFMON_V2))
pmu_version = 2;
- num_counters_nb = NUM_COUNTERS_NB;
- num_counters_llc = NUM_COUNTERS_L2;
- if (boot_cpu_data.x86 >= 0x17) {
- /*
- * For F17h and above, the Northbridge counters are
- * repurposed as Data Fabric counters. Also, L3
- * counters are supported too. The PMUs are exported
- * based on family as either L2 or L3 and NB or DF.
- */
- num_counters_llc = NUM_COUNTERS_L3;
- amd_nb_pmu.name = "amd_df";
- amd_llc_pmu.name = "amd_l3";
- l3_mask = true;
- }
+ for (i = 0; i < UNCORE_TYPE_MAX; i++) {
+ uncore = &uncores[i];
- if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) {
- if (pmu_version >= 2) {
- *df_attr++ = &format_attr_event14v2.attr;
- *df_attr++ = &format_attr_umask12.attr;
- } else if (boot_cpu_data.x86 >= 0x17) {
- *df_attr = &format_attr_event14.attr;
- }
+ BUG_ON(!uncore->scan);
+ BUG_ON(!uncore->init);
+ BUG_ON(!uncore->move);
+ BUG_ON(!uncore->free);
- amd_uncore_nb = alloc_percpu(struct amd_uncore *);
- if (!amd_uncore_nb) {
+ uncore->info = alloc_percpu(union amd_uncore_info);
+ if (!uncore->info) {
ret = -ENOMEM;
- goto fail_nb;
- }
- ret = perf_pmu_register(&amd_nb_pmu, amd_nb_pmu.name, -1);
- if (ret)
- goto fail_nb;
-
- if (pmu_version >= 2) {
- ebx.full = cpuid_ebx(EXT_PERFMON_DEBUG_FEATURES);
- num_counters_nb = ebx.split.num_df_pmc;
- }
-
- pr_info("%d %s %s counters detected\n", num_counters_nb,
- boot_cpu_data.x86_vendor == X86_VENDOR_HYGON ? "HYGON" : "",
- amd_nb_pmu.name);
-
- ret = 0;
- }
-
- if (boot_cpu_has(X86_FEATURE_PERFCTR_LLC)) {
- if (boot_cpu_data.x86 >= 0x19) {
- *l3_attr++ = &format_attr_event8.attr;
- *l3_attr++ = &format_attr_umask8.attr;
- *l3_attr++ = &format_attr_threadmask2.attr;
- } else if (boot_cpu_data.x86 >= 0x17) {
- *l3_attr++ = &format_attr_event8.attr;
- *l3_attr++ = &format_attr_umask8.attr;
- *l3_attr++ = &format_attr_threadmask8.attr;
- }
-
- amd_uncore_llc = alloc_percpu(struct amd_uncore *);
- if (!amd_uncore_llc) {
- ret = -ENOMEM;
- goto fail_llc;
+ goto fail;
}
- ret = perf_pmu_register(&amd_llc_pmu, amd_llc_pmu.name, -1);
- if (ret)
- goto fail_llc;
-
- pr_info("%d %s %s counters detected\n", num_counters_llc,
- boot_cpu_data.x86_vendor == X86_VENDOR_HYGON ? "HYGON" : "",
- amd_llc_pmu.name);
- ret = 0;
- }
+ };
/*
* Install callbacks. Core will call them for each online cpu.
*/
- if (cpuhp_setup_state(CPUHP_PERF_X86_AMD_UNCORE_PREP,
- "perf/x86/amd/uncore:prepare",
- amd_uncore_cpu_up_prepare, amd_uncore_cpu_dead))
- goto fail_llc;
-
- if (cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING,
- "perf/x86/amd/uncore:starting",
- amd_uncore_cpu_starting, NULL))
+ ret = cpuhp_setup_state(CPUHP_PERF_X86_AMD_UNCORE_PREP,
+ "perf/x86/amd/uncore:prepare",
+ NULL, amd_uncore_cpu_dead);
+ if (ret)
+ goto fail;
+
+ ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING,
+ "perf/x86/amd/uncore:starting",
+ amd_uncore_cpu_starting, NULL);
+ if (ret)
goto fail_prep;
- if (cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_UNCORE_ONLINE,
- "perf/x86/amd/uncore:online",
- amd_uncore_cpu_online,
- amd_uncore_cpu_down_prepare))
+
+ ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_UNCORE_ONLINE,
+ "perf/x86/amd/uncore:online",
+ amd_uncore_cpu_online,
+ amd_uncore_cpu_down_prepare);
+ if (ret)
goto fail_start;
+
return 0;
fail_start:
cpuhp_remove_state(CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING);
fail_prep:
cpuhp_remove_state(CPUHP_PERF_X86_AMD_UNCORE_PREP);
-fail_llc:
- if (boot_cpu_has(X86_FEATURE_PERFCTR_NB))
- perf_pmu_unregister(&amd_nb_pmu);
- free_percpu(amd_uncore_llc);
-fail_nb:
- free_percpu(amd_uncore_nb);
+fail:
+ for (i = 0; i < UNCORE_TYPE_MAX; i++) {
+ uncore = &uncores[i];
+ if (uncore->info) {
+ free_percpu(uncore->info);
+ uncore->info = NULL;
+ }
+ }
return ret;
}
static void __exit amd_uncore_exit(void)
{
+ struct amd_uncore *uncore;
+ struct amd_uncore_pmu *pmu;
+ int i, j;
+
cpuhp_remove_state(CPUHP_AP_PERF_X86_AMD_UNCORE_ONLINE);
cpuhp_remove_state(CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING);
cpuhp_remove_state(CPUHP_PERF_X86_AMD_UNCORE_PREP);
- if (boot_cpu_has(X86_FEATURE_PERFCTR_LLC)) {
- perf_pmu_unregister(&amd_llc_pmu);
- free_percpu(amd_uncore_llc);
- amd_uncore_llc = NULL;
- }
+ for (i = 0; i < UNCORE_TYPE_MAX; i++) {
+ uncore = &uncores[i];
+ if (!uncore->info)
+ continue;
+
+ free_percpu(uncore->info);
+ uncore->info = NULL;
+
+ for (j = 0; j < uncore->num_pmus; j++) {
+ pmu = &uncore->pmus[j];
+ if (!pmu->ctx)
+ continue;
+
+ perf_pmu_unregister(&pmu->pmu);
+ free_percpu(pmu->ctx);
+ pmu->ctx = NULL;
+ }
- if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) {
- perf_pmu_unregister(&amd_nb_pmu);
- free_percpu(amd_uncore_nb);
- amd_uncore_nb = NULL;
+ kfree(uncore->pmus);
+ uncore->pmus = NULL;
}
}
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 185f902e5f28..40ad1425ffa2 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -1887,9 +1887,9 @@ ssize_t events_hybrid_sysfs_show(struct device *dev,
str = pmu_attr->event_str;
for (i = 0; i < x86_pmu.num_hybrid_pmus; i++) {
- if (!(x86_pmu.hybrid_pmu[i].cpu_type & pmu_attr->pmu_type))
+ if (!(x86_pmu.hybrid_pmu[i].pmu_type & pmu_attr->pmu_type))
continue;
- if (x86_pmu.hybrid_pmu[i].cpu_type & pmu->cpu_type) {
+ if (x86_pmu.hybrid_pmu[i].pmu_type & pmu->pmu_type) {
next_str = strchr(str, ';');
if (next_str)
return snprintf(page, next_str - str + 1, "%s", str);
@@ -2169,7 +2169,7 @@ static int __init init_hw_perf_events(void)
hybrid_pmu->pmu.capabilities |= PERF_PMU_CAP_EXTENDED_HW_TYPE;
err = perf_pmu_register(&hybrid_pmu->pmu, hybrid_pmu->name,
- (hybrid_pmu->cpu_type == hybrid_big) ? PERF_TYPE_RAW : -1);
+ (hybrid_pmu->pmu_type == hybrid_big) ? PERF_TYPE_RAW : -1);
if (err)
break;
}
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index fa355d3658a6..ce1c777227b4 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -211,6 +211,14 @@ static struct event_constraint intel_slm_event_constraints[] __read_mostly =
EVENT_CONSTRAINT_END
};
+static struct event_constraint intel_grt_event_constraints[] __read_mostly = {
+ FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+ FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+ FIXED_EVENT_CONSTRAINT(0x0300, 2), /* pseudo CPU_CLK_UNHALTED.REF */
+ FIXED_EVENT_CONSTRAINT(0x013c, 2), /* CPU_CLK_UNHALTED.REF_TSC_P */
+ EVENT_CONSTRAINT_END
+};
+
static struct event_constraint intel_skl_event_constraints[] = {
FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
@@ -299,7 +307,7 @@ static struct extra_reg intel_icl_extra_regs[] __read_mostly = {
EVENT_EXTRA_END
};
-static struct extra_reg intel_spr_extra_regs[] __read_mostly = {
+static struct extra_reg intel_glc_extra_regs[] __read_mostly = {
INTEL_UEVENT_EXTRA_REG(0x012a, MSR_OFFCORE_RSP_0, 0x3fffffffffull, RSP_0),
INTEL_UEVENT_EXTRA_REG(0x012b, MSR_OFFCORE_RSP_1, 0x3fffffffffull, RSP_1),
INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
@@ -309,11 +317,12 @@ static struct extra_reg intel_spr_extra_regs[] __read_mostly = {
EVENT_EXTRA_END
};
-static struct event_constraint intel_spr_event_constraints[] = {
+static struct event_constraint intel_glc_event_constraints[] = {
FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
FIXED_EVENT_CONSTRAINT(0x0100, 0), /* INST_RETIRED.PREC_DIST */
FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
+ FIXED_EVENT_CONSTRAINT(0x013c, 2), /* CPU_CLK_UNHALTED.REF_TSC_P */
FIXED_EVENT_CONSTRAINT(0x0400, 3), /* SLOTS */
METRIC_EVENT_CONSTRAINT(INTEL_TD_METRIC_RETIRING, 0),
METRIC_EVENT_CONSTRAINT(INTEL_TD_METRIC_BAD_SPEC, 1),
@@ -349,7 +358,7 @@ static struct event_constraint intel_spr_event_constraints[] = {
EVENT_CONSTRAINT_END
};
-static struct extra_reg intel_gnr_extra_regs[] __read_mostly = {
+static struct extra_reg intel_rwc_extra_regs[] __read_mostly = {
INTEL_UEVENT_EXTRA_REG(0x012a, MSR_OFFCORE_RSP_0, 0x3fffffffffull, RSP_0),
INTEL_UEVENT_EXTRA_REG(0x012b, MSR_OFFCORE_RSP_1, 0x3fffffffffull, RSP_1),
INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
@@ -473,7 +482,7 @@ static u64 intel_pmu_event_map(int hw_event)
return intel_perfmon_event_map[hw_event];
}
-static __initconst const u64 spr_hw_cache_event_ids
+static __initconst const u64 glc_hw_cache_event_ids
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] =
@@ -552,7 +561,7 @@ static __initconst const u64 spr_hw_cache_event_ids
},
};
-static __initconst const u64 spr_hw_cache_extra_regs
+static __initconst const u64 glc_hw_cache_extra_regs
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] =
@@ -2556,16 +2565,6 @@ static int icl_set_topdown_event_period(struct perf_event *event)
return 0;
}
-static int adl_set_topdown_event_period(struct perf_event *event)
-{
- struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu);
-
- if (pmu->cpu_type != hybrid_big)
- return 0;
-
- return icl_set_topdown_event_period(event);
-}
-
DEFINE_STATIC_CALL(intel_pmu_set_topdown_event_period, x86_perf_event_set_period);
static inline u64 icl_get_metrics_event_value(u64 metric, u64 slots, int idx)
@@ -2708,16 +2707,6 @@ static u64 icl_update_topdown_event(struct perf_event *event)
x86_pmu.num_topdown_events - 1);
}
-static u64 adl_update_topdown_event(struct perf_event *event)
-{
- struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu);
-
- if (pmu->cpu_type != hybrid_big)
- return 0;
-
- return icl_update_topdown_event(event);
-}
-
DEFINE_STATIC_CALL(intel_pmu_update_topdown_event, x86_perf_event_update);
static void intel_pmu_read_topdown_event(struct perf_event *event)
@@ -3869,7 +3858,7 @@ static inline bool require_mem_loads_aux_event(struct perf_event *event)
return false;
if (is_hybrid())
- return hybrid_pmu(event->pmu)->cpu_type == hybrid_big;
+ return hybrid_pmu(event->pmu)->pmu_type == hybrid_big;
return true;
}
@@ -4273,7 +4262,7 @@ icl_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
}
static struct event_constraint *
-spr_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+glc_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
struct perf_event *event)
{
struct event_constraint *c;
@@ -4361,9 +4350,9 @@ adl_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
{
struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu);
- if (pmu->cpu_type == hybrid_big)
- return spr_get_event_constraints(cpuc, idx, event);
- else if (pmu->cpu_type == hybrid_small)
+ if (pmu->pmu_type == hybrid_big)
+ return glc_get_event_constraints(cpuc, idx, event);
+ else if (pmu->pmu_type == hybrid_small)
return tnt_get_event_constraints(cpuc, idx, event);
WARN_ON(1);
@@ -4409,7 +4398,7 @@ rwc_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
{
struct event_constraint *c;
- c = spr_get_event_constraints(cpuc, idx, event);
+ c = glc_get_event_constraints(cpuc, idx, event);
/* The Retire Latency is not supported by the fixed counter 0. */
if (event->attr.precise_ip &&
@@ -4433,9 +4422,9 @@ mtl_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
{
struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu);
- if (pmu->cpu_type == hybrid_big)
+ if (pmu->pmu_type == hybrid_big)
return rwc_get_event_constraints(cpuc, idx, event);
- if (pmu->cpu_type == hybrid_small)
+ if (pmu->pmu_type == hybrid_small)
return cmt_get_event_constraints(cpuc, idx, event);
WARN_ON(1);
@@ -4446,18 +4435,18 @@ static int adl_hw_config(struct perf_event *event)
{
struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu);
- if (pmu->cpu_type == hybrid_big)
+ if (pmu->pmu_type == hybrid_big)
return hsw_hw_config(event);
- else if (pmu->cpu_type == hybrid_small)
+ else if (pmu->pmu_type == hybrid_small)
return intel_pmu_hw_config(event);
WARN_ON(1);
return -EOPNOTSUPP;
}
-static u8 adl_get_hybrid_cpu_type(void)
+static enum hybrid_cpu_type adl_get_hybrid_cpu_type(void)
{
- return hybrid_big;
+ return HYBRID_INTEL_CORE;
}
/*
@@ -4490,7 +4479,7 @@ static void nhm_limit_period(struct perf_event *event, s64 *left)
*left = max(*left, 32LL);
}
-static void spr_limit_period(struct perf_event *event, s64 *left)
+static void glc_limit_period(struct perf_event *event, s64 *left)
{
if (event->attr.precise_ip == 3)
*left = max(*left, 128LL);
@@ -4618,6 +4607,23 @@ static void intel_pmu_check_num_counters(int *num_counters,
int *num_counters_fixed,
u64 *intel_ctrl, u64 fixed_mask);
+static void intel_pmu_check_event_constraints(struct event_constraint *event_constraints,
+ int num_counters,
+ int num_counters_fixed,
+ u64 intel_ctrl);
+
+static void intel_pmu_check_extra_regs(struct extra_reg *extra_regs);
+
+static inline bool intel_pmu_broken_perf_cap(void)
+{
+ /* The Perf Metric (Bit 15) is always cleared */
+ if ((boot_cpu_data.x86_model == INTEL_FAM6_METEORLAKE) ||
+ (boot_cpu_data.x86_model == INTEL_FAM6_METEORLAKE_L))
+ return true;
+
+ return false;
+}
+
static void update_pmu_cap(struct x86_hybrid_pmu *pmu)
{
unsigned int sub_bitmaps = cpuid_eax(ARCH_PERFMON_EXT_LEAF);
@@ -4628,27 +4634,83 @@ static void update_pmu_cap(struct x86_hybrid_pmu *pmu)
&eax, &ebx, &ecx, &edx);
pmu->num_counters = fls(eax);
pmu->num_counters_fixed = fls(ebx);
- intel_pmu_check_num_counters(&pmu->num_counters, &pmu->num_counters_fixed,
- &pmu->intel_ctrl, ebx);
+ }
+
+
+ if (!intel_pmu_broken_perf_cap()) {
+ /* Perf Metric (Bit 15) and PEBS via PT (Bit 16) are hybrid enumeration */
+ rdmsrl(MSR_IA32_PERF_CAPABILITIES, pmu->intel_cap.capabilities);
}
}
-static bool init_hybrid_pmu(int cpu)
+static void intel_pmu_check_hybrid_pmus(struct x86_hybrid_pmu *pmu)
+{
+ intel_pmu_check_num_counters(&pmu->num_counters, &pmu->num_counters_fixed,
+ &pmu->intel_ctrl, (1ULL << pmu->num_counters_fixed) - 1);
+ pmu->max_pebs_events = min_t(unsigned, MAX_PEBS_EVENTS, pmu->num_counters);
+ pmu->unconstrained = (struct event_constraint)
+ __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+ 0, pmu->num_counters, 0, 0);
+
+ if (pmu->intel_cap.perf_metrics)
+ pmu->intel_ctrl |= 1ULL << GLOBAL_CTRL_EN_PERF_METRICS;
+ else
+ pmu->intel_ctrl &= ~(1ULL << GLOBAL_CTRL_EN_PERF_METRICS);
+
+ if (pmu->intel_cap.pebs_output_pt_available)
+ pmu->pmu.capabilities |= PERF_PMU_CAP_AUX_OUTPUT;
+ else
+ pmu->pmu.capabilities &= ~PERF_PMU_CAP_AUX_OUTPUT;
+
+ intel_pmu_check_event_constraints(pmu->event_constraints,
+ pmu->num_counters,
+ pmu->num_counters_fixed,
+ pmu->intel_ctrl);
+
+ intel_pmu_check_extra_regs(pmu->extra_regs);
+}
+
+static struct x86_hybrid_pmu *find_hybrid_pmu_for_cpu(void)
{
- struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
u8 cpu_type = get_this_hybrid_cpu_type();
- struct x86_hybrid_pmu *pmu = NULL;
int i;
- if (!cpu_type && x86_pmu.get_hybrid_cpu_type)
- cpu_type = x86_pmu.get_hybrid_cpu_type();
+ /*
+ * This is running on a CPU model that is known to have hybrid
+ * configurations. But the CPU told us it is not hybrid, shame
+ * on it. There should be a fixup function provided for these
+ * troublesome CPUs (->get_hybrid_cpu_type).
+ */
+ if (cpu_type == HYBRID_INTEL_NONE) {
+ if (x86_pmu.get_hybrid_cpu_type)
+ cpu_type = x86_pmu.get_hybrid_cpu_type();
+ else
+ return NULL;
+ }
+ /*
+ * This essentially just maps between the 'hybrid_cpu_type'
+ * and 'hybrid_pmu_type' enums:
+ */
for (i = 0; i < x86_pmu.num_hybrid_pmus; i++) {
- if (x86_pmu.hybrid_pmu[i].cpu_type == cpu_type) {
- pmu = &x86_pmu.hybrid_pmu[i];
- break;
- }
+ enum hybrid_pmu_type pmu_type = x86_pmu.hybrid_pmu[i].pmu_type;
+
+ if (cpu_type == HYBRID_INTEL_CORE &&
+ pmu_type == hybrid_big)
+ return &x86_pmu.hybrid_pmu[i];
+ if (cpu_type == HYBRID_INTEL_ATOM &&
+ pmu_type == hybrid_small)
+ return &x86_pmu.hybrid_pmu[i];
}
+
+ return NULL;
+}
+
+static bool init_hybrid_pmu(int cpu)
+{
+ struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+ struct x86_hybrid_pmu *pmu = find_hybrid_pmu_for_cpu();
+
if (WARN_ON_ONCE(!pmu || (pmu->pmu.type == -1))) {
cpuc->pmu = NULL;
return false;
@@ -4661,6 +4723,8 @@ static bool init_hybrid_pmu(int cpu)
if (this_cpu_has(X86_FEATURE_ARCH_PERFMON_EXT))
update_pmu_cap(pmu);
+ intel_pmu_check_hybrid_pmus(pmu);
+
if (!check_hw_exists(&pmu->pmu, pmu->num_counters, pmu->num_counters_fixed))
return false;
@@ -5337,14 +5401,14 @@ static struct attribute *icl_tsx_events_attrs[] = {
EVENT_ATTR_STR(mem-stores, mem_st_spr, "event=0xcd,umask=0x2");
EVENT_ATTR_STR(mem-loads-aux, mem_ld_aux, "event=0x03,umask=0x82");
-static struct attribute *spr_events_attrs[] = {
+static struct attribute *glc_events_attrs[] = {
EVENT_PTR(mem_ld_hsw),
EVENT_PTR(mem_st_spr),
EVENT_PTR(mem_ld_aux),
NULL,
};
-static struct attribute *spr_td_events_attrs[] = {
+static struct attribute *glc_td_events_attrs[] = {
EVENT_PTR(slots),
EVENT_PTR(td_retiring),
EVENT_PTR(td_bad_spec),
@@ -5357,7 +5421,7 @@ static struct attribute *spr_td_events_attrs[] = {
NULL,
};
-static struct attribute *spr_tsx_events_attrs[] = {
+static struct attribute *glc_tsx_events_attrs[] = {
EVENT_PTR(tx_start),
EVENT_PTR(tx_abort),
EVENT_PTR(tx_commit),
@@ -5699,7 +5763,7 @@ static bool is_attr_for_this_pmu(struct kobject *kobj, struct attribute *attr)
struct perf_pmu_events_hybrid_attr *pmu_attr =
container_of(attr, struct perf_pmu_events_hybrid_attr, attr.attr);
- return pmu->cpu_type & pmu_attr->pmu_type;
+ return pmu->pmu_type & pmu_attr->pmu_type;
}
static umode_t hybrid_events_is_visible(struct kobject *kobj,
@@ -5736,7 +5800,7 @@ static umode_t hybrid_format_is_visible(struct kobject *kobj,
container_of(attr, struct perf_pmu_format_hybrid_attr, attr.attr);
int cpu = hybrid_find_supported_cpu(pmu);
- return (cpu >= 0) && (pmu->cpu_type & pmu_attr->pmu_type) ? attr->mode : 0;
+ return (cpu >= 0) && (pmu->pmu_type & pmu_attr->pmu_type) ? attr->mode : 0;
}
static struct attribute_group hybrid_group_events_td = {
@@ -5880,40 +5944,105 @@ static void intel_pmu_check_extra_regs(struct extra_reg *extra_regs)
}
}
-static void intel_pmu_check_hybrid_pmus(u64 fixed_mask)
+static const struct { enum hybrid_pmu_type id; char *name; } intel_hybrid_pmu_type_map[] __initconst = {
+ { hybrid_small, "cpu_atom" },
+ { hybrid_big, "cpu_core" },
+};
+
+static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus)
{
+ unsigned long pmus_mask = pmus;
struct x86_hybrid_pmu *pmu;
- int i;
+ int idx = 0, bit;
- for (i = 0; i < x86_pmu.num_hybrid_pmus; i++) {
- pmu = &x86_pmu.hybrid_pmu[i];
+ x86_pmu.num_hybrid_pmus = hweight_long(pmus_mask);
+ x86_pmu.hybrid_pmu = kcalloc(x86_pmu.num_hybrid_pmus,
+ sizeof(struct x86_hybrid_pmu),
+ GFP_KERNEL);
+ if (!x86_pmu.hybrid_pmu)
+ return -ENOMEM;
- intel_pmu_check_num_counters(&pmu->num_counters,
- &pmu->num_counters_fixed,
- &pmu->intel_ctrl,
- fixed_mask);
+ static_branch_enable(&perf_is_hybrid);
+ x86_pmu.filter = intel_pmu_filter;
- if (pmu->intel_cap.perf_metrics) {
- pmu->intel_ctrl |= 1ULL << GLOBAL_CTRL_EN_PERF_METRICS;
- pmu->intel_ctrl |= INTEL_PMC_MSK_FIXED_SLOTS;
+ for_each_set_bit(bit, &pmus_mask, ARRAY_SIZE(intel_hybrid_pmu_type_map)) {
+ pmu = &x86_pmu.hybrid_pmu[idx++];
+ pmu->pmu_type = intel_hybrid_pmu_type_map[bit].id;
+ pmu->name = intel_hybrid_pmu_type_map[bit].name;
+
+ pmu->num_counters = x86_pmu.num_counters;
+ pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
+ pmu->max_pebs_events = min_t(unsigned, MAX_PEBS_EVENTS, pmu->num_counters);
+ pmu->unconstrained = (struct event_constraint)
+ __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+ 0, pmu->num_counters, 0, 0);
+
+ pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities;
+ if (pmu->pmu_type & hybrid_small) {
+ pmu->intel_cap.perf_metrics = 0;
+ pmu->intel_cap.pebs_output_pt_available = 1;
+ pmu->mid_ack = true;
+ } else if (pmu->pmu_type & hybrid_big) {
+ pmu->intel_cap.perf_metrics = 1;
+ pmu->intel_cap.pebs_output_pt_available = 0;
+ pmu->late_ack = true;
}
+ }
- if (pmu->intel_cap.pebs_output_pt_available)
- pmu->pmu.capabilities |= PERF_PMU_CAP_AUX_OUTPUT;
+ return 0;
+}
- intel_pmu_check_event_constraints(pmu->event_constraints,
- pmu->num_counters,
- pmu->num_counters_fixed,
- pmu->intel_ctrl);
+static __always_inline void intel_pmu_ref_cycles_ext(void)
+{
+ if (!(x86_pmu.events_maskl & (INTEL_PMC_MSK_FIXED_REF_CYCLES >> INTEL_PMC_IDX_FIXED)))
+ intel_perfmon_event_map[PERF_COUNT_HW_REF_CPU_CYCLES] = 0x013c;
+}
- intel_pmu_check_extra_regs(pmu->extra_regs);
- }
+static __always_inline void intel_pmu_init_glc(struct pmu *pmu)
+{
+ x86_pmu.late_ack = true;
+ x86_pmu.limit_period = glc_limit_period;
+ x86_pmu.pebs_aliases = NULL;
+ x86_pmu.pebs_prec_dist = true;
+ x86_pmu.pebs_block = true;
+ x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+ x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
+ x86_pmu.flags |= PMU_FL_INSTR_LATENCY;
+ x86_pmu.rtm_abort_event = X86_CONFIG(.event=0xc9, .umask=0x04);
+ x86_pmu.lbr_pt_coexist = true;
+ x86_pmu.num_topdown_events = 8;
+ static_call_update(intel_pmu_update_topdown_event,
+ &icl_update_topdown_event);
+ static_call_update(intel_pmu_set_topdown_event_period,
+ &icl_set_topdown_event_period);
+
+ memcpy(hybrid_var(pmu, hw_cache_event_ids), glc_hw_cache_event_ids, sizeof(hw_cache_event_ids));
+ memcpy(hybrid_var(pmu, hw_cache_extra_regs), glc_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
+ hybrid(pmu, event_constraints) = intel_glc_event_constraints;
+ hybrid(pmu, pebs_constraints) = intel_glc_pebs_event_constraints;
+
+ intel_pmu_ref_cycles_ext();
}
-static __always_inline bool is_mtl(u8 x86_model)
+static __always_inline void intel_pmu_init_grt(struct pmu *pmu)
{
- return (x86_model == INTEL_FAM6_METEORLAKE) ||
- (x86_model == INTEL_FAM6_METEORLAKE_L);
+ x86_pmu.mid_ack = true;
+ x86_pmu.limit_period = glc_limit_period;
+ x86_pmu.pebs_aliases = NULL;
+ x86_pmu.pebs_prec_dist = true;
+ x86_pmu.pebs_block = true;
+ x86_pmu.lbr_pt_coexist = true;
+ x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+ x86_pmu.flags |= PMU_FL_INSTR_LATENCY;
+
+ memcpy(hybrid_var(pmu, hw_cache_event_ids), glp_hw_cache_event_ids, sizeof(hw_cache_event_ids));
+ memcpy(hybrid_var(pmu, hw_cache_extra_regs), tnt_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
+ hybrid_var(pmu, hw_cache_event_ids)[C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)] = -1;
+ hybrid(pmu, event_constraints) = intel_grt_event_constraints;
+ hybrid(pmu, pebs_constraints) = intel_grt_pebs_event_constraints;
+ hybrid(pmu, extra_regs) = intel_grt_extra_regs;
+
+ intel_pmu_ref_cycles_ext();
}
__init int intel_pmu_init(void)
@@ -6194,28 +6323,10 @@ __init int intel_pmu_init(void)
break;
case INTEL_FAM6_ATOM_GRACEMONT:
- x86_pmu.mid_ack = true;
- memcpy(hw_cache_event_ids, glp_hw_cache_event_ids,
- sizeof(hw_cache_event_ids));
- memcpy(hw_cache_extra_regs, tnt_hw_cache_extra_regs,
- sizeof(hw_cache_extra_regs));
- hw_cache_event_ids[C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)] = -1;
-
- x86_pmu.event_constraints = intel_slm_event_constraints;
- x86_pmu.pebs_constraints = intel_grt_pebs_event_constraints;
- x86_pmu.extra_regs = intel_grt_extra_regs;
-
- x86_pmu.pebs_aliases = NULL;
- x86_pmu.pebs_prec_dist = true;
- x86_pmu.pebs_block = true;
- x86_pmu.lbr_pt_coexist = true;
- x86_pmu.flags |= PMU_FL_HAS_RSP_1;
- x86_pmu.flags |= PMU_FL_INSTR_LATENCY;
-
+ intel_pmu_init_grt(NULL);
intel_pmu_pebs_data_source_grt();
x86_pmu.pebs_latency_data = adl_latency_data_small;
x86_pmu.get_event_constraints = tnt_get_event_constraints;
- x86_pmu.limit_period = spr_limit_period;
td_attr = tnt_events_attrs;
mem_attr = grt_mem_attrs;
extra_attr = nhm_format_attr;
@@ -6225,28 +6336,11 @@ __init int intel_pmu_init(void)
case INTEL_FAM6_ATOM_CRESTMONT:
case INTEL_FAM6_ATOM_CRESTMONT_X:
- x86_pmu.mid_ack = true;
- memcpy(hw_cache_event_ids, glp_hw_cache_event_ids,
- sizeof(hw_cache_event_ids));
- memcpy(hw_cache_extra_regs, tnt_hw_cache_extra_regs,
- sizeof(hw_cache_extra_regs));
- hw_cache_event_ids[C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)] = -1;
-
- x86_pmu.event_constraints = intel_slm_event_constraints;
- x86_pmu.pebs_constraints = intel_grt_pebs_event_constraints;
+ intel_pmu_init_grt(NULL);
x86_pmu.extra_regs = intel_cmt_extra_regs;
-
- x86_pmu.pebs_aliases = NULL;
- x86_pmu.pebs_prec_dist = true;
- x86_pmu.lbr_pt_coexist = true;
- x86_pmu.pebs_block = true;
- x86_pmu.flags |= PMU_FL_HAS_RSP_1;
- x86_pmu.flags |= PMU_FL_INSTR_LATENCY;
-
intel_pmu_pebs_data_source_cmt();
x86_pmu.pebs_latency_data = mtl_latency_data_small;
x86_pmu.get_event_constraints = cmt_get_event_constraints;
- x86_pmu.limit_period = spr_limit_period;
td_attr = cmt_events_attrs;
mem_attr = grt_mem_attrs;
extra_attr = cmt_format_attr;
@@ -6563,44 +6657,23 @@ __init int intel_pmu_init(void)
case INTEL_FAM6_SAPPHIRERAPIDS_X:
case INTEL_FAM6_EMERALDRAPIDS_X:
x86_pmu.flags |= PMU_FL_MEM_LOADS_AUX;
- x86_pmu.extra_regs = intel_spr_extra_regs;
+ x86_pmu.extra_regs = intel_glc_extra_regs;
fallthrough;
case INTEL_FAM6_GRANITERAPIDS_X:
case INTEL_FAM6_GRANITERAPIDS_D:
- pmem = true;
- x86_pmu.late_ack = true;
- memcpy(hw_cache_event_ids, spr_hw_cache_event_ids, sizeof(hw_cache_event_ids));
- memcpy(hw_cache_extra_regs, spr_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
-
- x86_pmu.event_constraints = intel_spr_event_constraints;
- x86_pmu.pebs_constraints = intel_spr_pebs_event_constraints;
+ intel_pmu_init_glc(NULL);
if (!x86_pmu.extra_regs)
- x86_pmu.extra_regs = intel_gnr_extra_regs;
- x86_pmu.limit_period = spr_limit_period;
+ x86_pmu.extra_regs = intel_rwc_extra_regs;
x86_pmu.pebs_ept = 1;
- x86_pmu.pebs_aliases = NULL;
- x86_pmu.pebs_prec_dist = true;
- x86_pmu.pebs_block = true;
- x86_pmu.flags |= PMU_FL_HAS_RSP_1;
- x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
- x86_pmu.flags |= PMU_FL_INSTR_LATENCY;
-
x86_pmu.hw_config = hsw_hw_config;
- x86_pmu.get_event_constraints = spr_get_event_constraints;
+ x86_pmu.get_event_constraints = glc_get_event_constraints;
extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
hsw_format_attr : nhm_format_attr;
extra_skl_attr = skl_format_attr;
- mem_attr = spr_events_attrs;
- td_attr = spr_td_events_attrs;
- tsx_attr = spr_tsx_events_attrs;
- x86_pmu.rtm_abort_event = X86_CONFIG(.event=0xc9, .umask=0x04);
- x86_pmu.lbr_pt_coexist = true;
- intel_pmu_pebs_data_source_skl(pmem);
- x86_pmu.num_topdown_events = 8;
- static_call_update(intel_pmu_update_topdown_event,
- &icl_update_topdown_event);
- static_call_update(intel_pmu_set_topdown_event_period,
- &icl_set_topdown_event_period);
+ mem_attr = glc_events_attrs;
+ td_attr = glc_td_events_attrs;
+ tsx_attr = glc_tsx_events_attrs;
+ intel_pmu_pebs_data_source_skl(true);
pr_cont("Sapphire Rapids events, ");
name = "sapphire_rapids";
break;
@@ -6610,47 +6683,17 @@ __init int intel_pmu_init(void)
case INTEL_FAM6_RAPTORLAKE:
case INTEL_FAM6_RAPTORLAKE_P:
case INTEL_FAM6_RAPTORLAKE_S:
- case INTEL_FAM6_METEORLAKE:
- case INTEL_FAM6_METEORLAKE_L:
/*
* Alder Lake has 2 types of CPU, core and atom.
*
* Initialize the common PerfMon capabilities here.
*/
- x86_pmu.hybrid_pmu = kcalloc(X86_HYBRID_NUM_PMUS,
- sizeof(struct x86_hybrid_pmu),
- GFP_KERNEL);
- if (!x86_pmu.hybrid_pmu)
- return -ENOMEM;
- static_branch_enable(&perf_is_hybrid);
- x86_pmu.num_hybrid_pmus = X86_HYBRID_NUM_PMUS;
+ intel_pmu_init_hybrid(hybrid_big_small);
- x86_pmu.pebs_aliases = NULL;
- x86_pmu.pebs_prec_dist = true;
- x86_pmu.pebs_block = true;
- x86_pmu.flags |= PMU_FL_HAS_RSP_1;
- x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
- x86_pmu.flags |= PMU_FL_INSTR_LATENCY;
- x86_pmu.lbr_pt_coexist = true;
x86_pmu.pebs_latency_data = adl_latency_data_small;
- x86_pmu.num_topdown_events = 8;
- static_call_update(intel_pmu_update_topdown_event,
- &adl_update_topdown_event);
- static_call_update(intel_pmu_set_topdown_event_period,
- &adl_set_topdown_event_period);
-
- x86_pmu.filter = intel_pmu_filter;
x86_pmu.get_event_constraints = adl_get_event_constraints;
x86_pmu.hw_config = adl_hw_config;
- x86_pmu.limit_period = spr_limit_period;
x86_pmu.get_hybrid_cpu_type = adl_get_hybrid_cpu_type;
- /*
- * The rtm_abort_event is used to check whether to enable GPRs
- * for the RTM abort event. Atom doesn't have the RTM abort
- * event. There is no harmful to set it in the common
- * x86_pmu.rtm_abort_event.
- */
- x86_pmu.rtm_abort_event = X86_CONFIG(.event=0xc9, .umask=0x04);
td_attr = adl_hybrid_events_attrs;
mem_attr = adl_hybrid_mem_attrs;
@@ -6660,9 +6703,7 @@ __init int intel_pmu_init(void)
/* Initialize big core specific PerfMon capabilities.*/
pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_CORE_IDX];
- pmu->name = "cpu_core";
- pmu->cpu_type = hybrid_big;
- pmu->late_ack = true;
+ intel_pmu_init_glc(&pmu->pmu);
if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) {
pmu->num_counters = x86_pmu.num_counters + 2;
pmu->num_counters_fixed = x86_pmu.num_counters_fixed + 1;
@@ -6687,54 +6728,45 @@ __init int intel_pmu_init(void)
pmu->unconstrained = (struct event_constraint)
__EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
0, pmu->num_counters, 0, 0);
- pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities;
- pmu->intel_cap.perf_metrics = 1;
- pmu->intel_cap.pebs_output_pt_available = 0;
+ pmu->extra_regs = intel_glc_extra_regs;
+
+ /* Initialize Atom core specific PerfMon capabilities.*/
+ pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_ATOM_IDX];
+ intel_pmu_init_grt(&pmu->pmu);
+
+ x86_pmu.flags |= PMU_FL_MEM_LOADS_AUX;
+ intel_pmu_pebs_data_source_adl();
+ pr_cont("Alderlake Hybrid events, ");
+ name = "alderlake_hybrid";
+ break;
+
+ case INTEL_FAM6_METEORLAKE:
+ case INTEL_FAM6_METEORLAKE_L:
+ intel_pmu_init_hybrid(hybrid_big_small);
- memcpy(pmu->hw_cache_event_ids, spr_hw_cache_event_ids, sizeof(pmu->hw_cache_event_ids));
- memcpy(pmu->hw_cache_extra_regs, spr_hw_cache_extra_regs, sizeof(pmu->hw_cache_extra_regs));
- pmu->event_constraints = intel_spr_event_constraints;
- pmu->pebs_constraints = intel_spr_pebs_event_constraints;
- pmu->extra_regs = intel_spr_extra_regs;
+ x86_pmu.pebs_latency_data = mtl_latency_data_small;
+ x86_pmu.get_event_constraints = mtl_get_event_constraints;
+ x86_pmu.hw_config = adl_hw_config;
+
+ td_attr = adl_hybrid_events_attrs;
+ mem_attr = mtl_hybrid_mem_attrs;
+ tsx_attr = adl_hybrid_tsx_attrs;
+ extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
+ mtl_hybrid_extra_attr_rtm : mtl_hybrid_extra_attr;
+
+ /* Initialize big core specific PerfMon capabilities.*/
+ pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_CORE_IDX];
+ intel_pmu_init_glc(&pmu->pmu);
+ pmu->extra_regs = intel_rwc_extra_regs;
/* Initialize Atom core specific PerfMon capabilities.*/
pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_ATOM_IDX];
- pmu->name = "cpu_atom";
- pmu->cpu_type = hybrid_small;
- pmu->mid_ack = true;
- pmu->num_counters = x86_pmu.num_counters;
- pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
- pmu->max_pebs_events = x86_pmu.max_pebs_events;
- pmu->unconstrained = (struct event_constraint)
- __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
- 0, pmu->num_counters, 0, 0);
- pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities;
- pmu->intel_cap.perf_metrics = 0;
- pmu->intel_cap.pebs_output_pt_available = 1;
-
- memcpy(pmu->hw_cache_event_ids, glp_hw_cache_event_ids, sizeof(pmu->hw_cache_event_ids));
- memcpy(pmu->hw_cache_extra_regs, tnt_hw_cache_extra_regs, sizeof(pmu->hw_cache_extra_regs));
- pmu->hw_cache_event_ids[C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)] = -1;
- pmu->event_constraints = intel_slm_event_constraints;
- pmu->pebs_constraints = intel_grt_pebs_event_constraints;
- pmu->extra_regs = intel_grt_extra_regs;
- if (is_mtl(boot_cpu_data.x86_model)) {
- x86_pmu.hybrid_pmu[X86_HYBRID_PMU_CORE_IDX].extra_regs = intel_gnr_extra_regs;
- x86_pmu.pebs_latency_data = mtl_latency_data_small;
- extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
- mtl_hybrid_extra_attr_rtm : mtl_hybrid_extra_attr;
- mem_attr = mtl_hybrid_mem_attrs;
- intel_pmu_pebs_data_source_mtl();
- x86_pmu.get_event_constraints = mtl_get_event_constraints;
- pmu->extra_regs = intel_cmt_extra_regs;
- pr_cont("Meteorlake Hybrid events, ");
- name = "meteorlake_hybrid";
- } else {
- x86_pmu.flags |= PMU_FL_MEM_LOADS_AUX;
- intel_pmu_pebs_data_source_adl();
- pr_cont("Alderlake Hybrid events, ");
- name = "alderlake_hybrid";
- }
+ intel_pmu_init_grt(&pmu->pmu);
+ pmu->extra_regs = intel_cmt_extra_regs;
+
+ intel_pmu_pebs_data_source_mtl();
+ pr_cont("Meteorlake Hybrid events, ");
+ name = "meteorlake_hybrid";
break;
default:
@@ -6846,9 +6878,6 @@ __init int intel_pmu_init(void)
if (!is_hybrid() && x86_pmu.intel_cap.perf_metrics)
x86_pmu.intel_ctrl |= 1ULL << GLOBAL_CTRL_EN_PERF_METRICS;
- if (is_hybrid())
- intel_pmu_check_hybrid_pmus((u64)fixed_mask);
-
if (x86_pmu.intel_cap.pebs_timing_info)
x86_pmu.flags |= PMU_FL_RETIRE_LATENCY;
diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c
index 96fffb2d521d..cbeb6d2bf5b4 100644
--- a/arch/x86/events/intel/cstate.c
+++ b/arch/x86/events/intel/cstate.c
@@ -336,6 +336,9 @@ static int cstate_pmu_event_init(struct perf_event *event)
cfg = array_index_nospec((unsigned long)cfg, PERF_CSTATE_PKG_EVENT_MAX);
if (!(pkg_msr_mask & (1 << cfg)))
return -EINVAL;
+
+ event->event_caps |= PERF_EV_CAP_READ_ACTIVE_PKG;
+
event->hw.event_base = pkg_msr[cfg].msr;
cpu = cpumask_any_and(&cstate_pkg_cpu_mask,
topology_die_cpumask(event->cpu));
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
index eb8dd8b8a1e8..bf97ab904d40 100644
--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -261,7 +261,7 @@ static u64 __adl_latency_data_small(struct perf_event *event, u64 status,
{
u64 val;
- WARN_ON_ONCE(hybrid_pmu(event->pmu)->cpu_type == hybrid_big);
+ WARN_ON_ONCE(hybrid_pmu(event->pmu)->pmu_type == hybrid_big);
dse &= PERF_PEBS_DATA_SOURCE_MASK;
val = hybrid_var(event->pmu, pebs_data_source)[dse];
@@ -1058,7 +1058,7 @@ struct event_constraint intel_icl_pebs_event_constraints[] = {
EVENT_CONSTRAINT_END
};
-struct event_constraint intel_spr_pebs_event_constraints[] = {
+struct event_constraint intel_glc_pebs_event_constraints[] = {
INTEL_FLAGS_UEVENT_CONSTRAINT(0x100, 0x100000000ULL), /* INST_RETIRED.PREC_DIST */
INTEL_FLAGS_UEVENT_CONSTRAINT(0x0400, 0x800000000ULL),
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index 42a55794004a..8e2a12235e62 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -736,6 +736,7 @@ static bool topa_table_full(struct topa *topa)
/**
* topa_insert_pages() - create a list of ToPA tables
* @buf: PT buffer being initialized.
+ * @cpu: CPU on which to allocate.
* @gfp: Allocation flags.
*
* This initializes a list of ToPA tables with entries from
@@ -1207,8 +1208,11 @@ static void pt_buffer_fini_topa(struct pt_buffer *buf)
/**
* pt_buffer_init_topa() - initialize ToPA table for pt buffer
* @buf: PT buffer.
- * @size: Total size of all regions within this ToPA.
+ * @cpu: CPU on which to allocate.
+ * @nr_pages: No. of pages to allocate.
* @gfp: Allocation flags.
+ *
+ * Return: 0 on success or error code.
*/
static int pt_buffer_init_topa(struct pt_buffer *buf, int cpu,
unsigned long nr_pages, gfp_t gfp)
@@ -1281,7 +1285,7 @@ out:
/**
* pt_buffer_setup_aux() - set up topa tables for a PT buffer
- * @cpu: Cpu on which to allocate, -1 means current.
+ * @event: Performance event
* @pages: Array of pointers to buffer pages passed from perf core.
* @nr_pages: Number of pages in the buffer.
* @snapshot: If this is a snapshot/overwrite counter.
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
index 69043e02e8a7..01023aa5125b 100644
--- a/arch/x86/events/intel/uncore.c
+++ b/arch/x86/events/intel/uncore.c
@@ -74,7 +74,7 @@ int uncore_device_to_die(struct pci_dev *dev)
struct cpuinfo_x86 *c = &cpu_data(cpu);
if (c->initialized && cpu_to_node(cpu) == node)
- return c->logical_die_id;
+ return c->topo.logical_die_id;
}
return -1;
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index c8ba2be7585d..53dd5d495ba6 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -652,10 +652,29 @@ enum {
#define PERF_PEBS_DATA_SOURCE_MAX 0x10
#define PERF_PEBS_DATA_SOURCE_MASK (PERF_PEBS_DATA_SOURCE_MAX - 1)
+enum hybrid_cpu_type {
+ HYBRID_INTEL_NONE,
+ HYBRID_INTEL_ATOM = 0x20,
+ HYBRID_INTEL_CORE = 0x40,
+};
+
+enum hybrid_pmu_type {
+ not_hybrid,
+ hybrid_small = BIT(0),
+ hybrid_big = BIT(1),
+
+ hybrid_big_small = hybrid_big | hybrid_small, /* only used for matching */
+};
+
+#define X86_HYBRID_PMU_ATOM_IDX 0
+#define X86_HYBRID_PMU_CORE_IDX 1
+
+#define X86_HYBRID_NUM_PMUS 2
+
struct x86_hybrid_pmu {
struct pmu pmu;
const char *name;
- u8 cpu_type;
+ enum hybrid_pmu_type pmu_type;
cpumask_t supported_cpus;
union perf_capabilities intel_cap;
u64 intel_ctrl;
@@ -721,18 +740,6 @@ extern struct static_key_false perf_is_hybrid;
__Fp; \
})
-enum hybrid_pmu_type {
- hybrid_big = 0x40,
- hybrid_small = 0x20,
-
- hybrid_big_small = hybrid_big | hybrid_small,
-};
-
-#define X86_HYBRID_PMU_ATOM_IDX 0
-#define X86_HYBRID_PMU_CORE_IDX 1
-
-#define X86_HYBRID_NUM_PMUS 2
-
/*
* struct x86_pmu - generic x86 pmu
*/
@@ -940,7 +947,7 @@ struct x86_pmu {
*/
int num_hybrid_pmus;
struct x86_hybrid_pmu *hybrid_pmu;
- u8 (*get_hybrid_cpu_type) (void);
+ enum hybrid_cpu_type (*get_hybrid_cpu_type) (void);
};
struct x86_perf_task_context_opt {
@@ -1521,7 +1528,7 @@ extern struct event_constraint intel_skl_pebs_event_constraints[];
extern struct event_constraint intel_icl_pebs_event_constraints[];
-extern struct event_constraint intel_spr_pebs_event_constraints[];
+extern struct event_constraint intel_glc_pebs_event_constraints[];
struct event_constraint *intel_pebs_constraints(struct perf_event *event);
diff --git a/arch/x86/events/rapl.c b/arch/x86/events/rapl.c
index 1579429846cc..8d98d468b976 100644
--- a/arch/x86/events/rapl.c
+++ b/arch/x86/events/rapl.c
@@ -115,7 +115,7 @@ struct rapl_pmu {
struct rapl_pmus {
struct pmu pmu;
unsigned int maxdie;
- struct rapl_pmu *pmus[];
+ struct rapl_pmu *pmus[] __counted_by(maxdie);
};
enum rapl_unit_quirk {
@@ -179,15 +179,11 @@ static u64 rapl_event_update(struct perf_event *event)
s64 delta, sdelta;
int shift = RAPL_CNTR_WIDTH;
-again:
prev_raw_count = local64_read(&hwc->prev_count);
- rdmsrl(event->hw.event_base, new_raw_count);
-
- if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
- new_raw_count) != prev_raw_count) {
- cpu_relax();
- goto again;
- }
+ do {
+ rdmsrl(event->hw.event_base, new_raw_count);
+ } while (!local64_try_cmpxchg(&hwc->prev_count,
+ &prev_raw_count, new_raw_count));
/*
* Now we have the new raw value and have updated the prev
@@ -537,11 +533,11 @@ static struct perf_msr intel_rapl_spr_msrs[] = {
* - want to use same event codes across both architectures
*/
static struct perf_msr amd_rapl_msrs[] = {
- [PERF_RAPL_PP0] = { 0, &rapl_events_cores_group, 0, false, 0 },
+ [PERF_RAPL_PP0] = { 0, &rapl_events_cores_group, NULL, false, 0 },
[PERF_RAPL_PKG] = { MSR_AMD_PKG_ENERGY_STATUS, &rapl_events_pkg_group, test_msr, false, RAPL_MSR_MASK },
- [PERF_RAPL_RAM] = { 0, &rapl_events_ram_group, 0, false, 0 },
- [PERF_RAPL_PP1] = { 0, &rapl_events_gpu_group, 0, false, 0 },
- [PERF_RAPL_PSYS] = { 0, &rapl_events_psys_group, 0, false, 0 },
+ [PERF_RAPL_RAM] = { 0, &rapl_events_ram_group, NULL, false, 0 },
+ [PERF_RAPL_PP1] = { 0, &rapl_events_gpu_group, NULL, false, 0 },
+ [PERF_RAPL_PSYS] = { 0, &rapl_events_psys_group, NULL, false, 0 },
};
static int rapl_cpu_offline(unsigned int cpu)
diff --git a/arch/x86/events/utils.c b/arch/x86/events/utils.c
index 76b1f8bb0fd5..dab4ed199227 100644
--- a/arch/x86/events/utils.c
+++ b/arch/x86/events/utils.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <asm/insn.h>
+#include <linux/mm.h>
#include "perf_event.h"
@@ -132,9 +133,9 @@ static int get_branch_type(unsigned long from, unsigned long to, int abort,
* The LBR logs any address in the IP, even if the IP just
* faulted. This means userspace can control the from address.
* Ensure we don't blindly read any address by validating it is
- * a known text address.
+ * a known text address and not a vsyscall address.
*/
- if (kernel_text_address(from)) {
+ if (kernel_text_address(from) && !in_gate_area_no_mm(from)) {
addr = (void *)from;
/*
* Assume we can get the maximum possible size
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 21556ad87f4b..8f3a4d16bb79 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <asm/apic.h>
#include <asm/desc.h>
+#include <asm/e820/api.h>
#include <asm/sev.h>
#include <asm/ibt.h>
#include <asm/hypervisor.h>
@@ -286,15 +287,31 @@ static int hv_cpu_die(unsigned int cpu)
static int __init hv_pci_init(void)
{
- int gen2vm = efi_enabled(EFI_BOOT);
+ bool gen2vm = efi_enabled(EFI_BOOT);
/*
- * For Generation-2 VM, we exit from pci_arch_init() by returning 0.
- * The purpose is to suppress the harmless warning:
+ * A Generation-2 VM doesn't support legacy PCI/PCIe, so both
+ * raw_pci_ops and raw_pci_ext_ops are NULL, and pci_subsys_init() ->
+ * pcibios_init() doesn't call pcibios_resource_survey() ->
+ * e820__reserve_resources_late(); as a result, any emulated persistent
+ * memory of E820_TYPE_PRAM (12) via the kernel parameter
+ * memmap=nn[KMG]!ss is not added into iomem_resource and hence can't be
+ * detected by register_e820_pmem(). Fix this by directly calling
+ * e820__reserve_resources_late() here: e820__reserve_resources_late()
+ * depends on e820__reserve_resources(), which has been called earlier
+ * from setup_arch(). Note: e820__reserve_resources_late() also adds
+ * any memory of E820_TYPE_PMEM (7) into iomem_resource, and
+ * acpi_nfit_register_region() -> acpi_nfit_insert_resource() ->
+ * region_intersects() returns REGION_INTERSECTS, so the memory of
+ * E820_TYPE_PMEM won't get added twice.
+ *
+ * We return 0 here so that pci_arch_init() won't print the warning:
* "PCI: Fatal: No config space access function found"
*/
- if (gen2vm)
+ if (gen2vm) {
+ e820__reserve_resources_late();
return 0;
+ }
/* For Generation-1 VM, we'll proceed in pci_arch_init(). */
return 1;
diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c
index 999f5ac82fe9..96e6c51515f5 100644
--- a/arch/x86/hyperv/hv_vtl.c
+++ b/arch/x86/hyperv/hv_vtl.c
@@ -196,7 +196,7 @@ static int hv_vtl_apicid_to_vp_id(u32 apic_id)
return ret;
}
-static int hv_vtl_wakeup_secondary_cpu(int apicid, unsigned long start_eip)
+static int hv_vtl_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip)
{
int vp_id;
diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
index 8c6bf07f7d2b..02e55237d919 100644
--- a/arch/x86/hyperv/ivm.c
+++ b/arch/x86/hyperv/ivm.c
@@ -288,7 +288,7 @@ static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa)
free_page((unsigned long)vmsa);
}
-int hv_snp_boot_ap(int cpu, unsigned long start_ip)
+int hv_snp_boot_ap(u32 cpu, unsigned long start_ip)
{
struct sev_es_save_area *vmsa = (struct sev_es_save_area *)
__get_free_page(GFP_KERNEL | __GFP_ZERO);
@@ -384,7 +384,7 @@ static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {}
#ifdef CONFIG_INTEL_TDX_GUEST
static void hv_tdx_msr_write(u64 msr, u64 val)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = EXIT_REASON_MSR_WRITE,
.r12 = msr,
@@ -398,13 +398,13 @@ static void hv_tdx_msr_write(u64 msr, u64 val)
static void hv_tdx_msr_read(u64 msr, u64 *val)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = EXIT_REASON_MSR_READ,
.r12 = msr,
};
- u64 ret = __tdx_hypercall_ret(&args);
+ u64 ret = __tdx_hypercall(&args);
if (WARN_ONCE(ret, "Failed to emulate MSR read: %lld\n", ret))
*val = 0;
@@ -414,13 +414,13 @@ static void hv_tdx_msr_read(u64 msr, u64 *val)
u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2)
{
- struct tdx_hypercall_args args = { };
+ struct tdx_module_args args = { };
args.r10 = control;
args.rdx = param1;
args.r8 = param2;
- (void)__tdx_hypercall_ret(&args);
+ (void)__tdx_hypercall(&args);
return args.r11;
}
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 4f1ce5fc4e19..a192bdea69e2 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -10,5 +10,4 @@ generated-y += unistd_64_x32.h
generated-y += xen-hypercalls.h
generic-y += early_ioremap.h
-generic-y += export.h
generic-y += mcs_spinlock.h
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index c8a7fc23f63c..f896eed4516c 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -16,6 +16,9 @@
#include <asm/x86_init.h>
#include <asm/cpufeature.h>
#include <asm/irq_vectors.h>
+#include <asm/xen/hypervisor.h>
+
+#include <xen/xen.h>
#ifdef CONFIG_ACPI_APEI
# include <asm/pgtable_types.h>
@@ -127,6 +130,17 @@ static inline void arch_acpi_set_proc_cap_bits(u32 *cap)
if (!cpu_has(c, X86_FEATURE_MWAIT) ||
boot_option_idle_override == IDLE_NOMWAIT)
*cap &= ~(ACPI_PROC_CAP_C_C1_FFH | ACPI_PROC_CAP_C_C2C3_FFH);
+
+ if (xen_initial_domain()) {
+ /*
+ * When Linux is running as Xen dom0, the hypervisor is the
+ * entity in charge of the processor power management, and so
+ * Xen needs to check the OS capabilities reported in the
+ * processor capabilities buffer matches what the hypervisor
+ * driver supports.
+ */
+ xen_sanitize_proc_cap_bits(cap);
+ }
}
static inline bool acpi_has_cpu_in_madt(void)
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 9c4da699e11a..65f79092c9d9 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -58,7 +58,7 @@
#define ANNOTATE_IGNORE_ALTERNATIVE \
"999:\n\t" \
".pushsection .discard.ignore_alts\n\t" \
- ".long 999b - .\n\t" \
+ ".long 999b\n\t" \
".popsection\n\t"
/*
@@ -352,7 +352,7 @@ static inline int alternatives_text_reserved(void *start, void *end)
.macro ANNOTATE_IGNORE_ALTERNATIVE
.Lannotate_\@:
.pushsection .discard.ignore_alts
- .long .Lannotate_\@ - .
+ .long .Lannotate_\@
.popsection
.endm
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 5af4ec1a0f71..d21f48f1c242 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -54,7 +54,7 @@ extern int local_apic_timer_c2_ok;
extern bool apic_is_disabled;
extern unsigned int lapic_timer_period;
-extern int cpuid_to_apicid[];
+extern u32 cpuid_to_apicid[];
extern enum apic_intr_mode_id apic_intr_mode;
enum apic_intr_mode_id {
@@ -276,7 +276,8 @@ struct apic {
u32 disable_esr : 1,
dest_mode_logical : 1,
- x2apic_set_max_apicid : 1;
+ x2apic_set_max_apicid : 1,
+ nmi_to_offline_cpu : 1;
u32 (*calc_dest_apicid)(unsigned int cpu);
@@ -292,19 +293,19 @@ struct apic {
int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
bool (*apic_id_registered)(void);
- bool (*check_apicid_used)(physid_mask_t *map, int apicid);
+ bool (*check_apicid_used)(physid_mask_t *map, u32 apicid);
void (*init_apic_ldr)(void);
void (*ioapic_phys_id_map)(physid_mask_t *phys_map, physid_mask_t *retmap);
- int (*cpu_present_to_apicid)(int mps_cpu);
- int (*phys_pkg_id)(int cpuid_apic, int index_msb);
+ u32 (*cpu_present_to_apicid)(int mps_cpu);
+ u32 (*phys_pkg_id)(u32 cpuid_apic, int index_msb);
- u32 (*get_apic_id)(unsigned long x);
- u32 (*set_apic_id)(unsigned int id);
+ u32 (*get_apic_id)(u32 id);
+ u32 (*set_apic_id)(u32 apicid);
/* wakeup_secondary_cpu */
- int (*wakeup_secondary_cpu)(int apicid, unsigned long start_eip);
+ int (*wakeup_secondary_cpu)(u32 apicid, unsigned long start_eip);
/* wakeup secondary CPU using 64-bit wakeup point */
- int (*wakeup_secondary_cpu_64)(int apicid, unsigned long start_eip);
+ int (*wakeup_secondary_cpu_64)(u32 apicid, unsigned long start_eip);
char *name;
};
@@ -322,8 +323,8 @@ struct apic_override {
void (*send_IPI_self)(int vector);
u64 (*icr_read)(void);
void (*icr_write)(u32 low, u32 high);
- int (*wakeup_secondary_cpu)(int apicid, unsigned long start_eip);
- int (*wakeup_secondary_cpu_64)(int apicid, unsigned long start_eip);
+ int (*wakeup_secondary_cpu)(u32 apicid, unsigned long start_eip);
+ int (*wakeup_secondary_cpu_64)(u32 apicid, unsigned long start_eip);
};
/*
@@ -493,16 +494,6 @@ static inline bool lapic_vector_set_in_irr(unsigned int vector)
return !!(irr & (1U << (vector % 32)));
}
-static inline unsigned default_get_apic_id(unsigned long x)
-{
- unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
-
- if (APIC_XAPIC(ver) || boot_cpu_has(X86_FEATURE_EXTD_APICID))
- return (x >> 24) & 0xFF;
- else
- return (x >> 24) & 0x0F;
-}
-
/*
* Warm reset vector position:
*/
@@ -517,9 +508,9 @@ extern void generic_bigsmp_probe(void);
extern struct apic apic_noop;
-static inline unsigned int read_apic_id(void)
+static inline u32 read_apic_id(void)
{
- unsigned int reg = apic_read(APIC_ID);
+ u32 reg = apic_read(APIC_ID);
return apic->get_apic_id(reg);
}
@@ -538,13 +529,14 @@ extern int default_apic_id_valid(u32 apicid);
extern u32 apic_default_calc_apicid(unsigned int cpu);
extern u32 apic_flat_calc_apicid(unsigned int cpu);
-extern bool default_check_apicid_used(physid_mask_t *map, int apicid);
extern void default_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap);
-extern int default_cpu_present_to_apicid(int mps_cpu);
+extern u32 default_cpu_present_to_apicid(int mps_cpu);
+
+void apic_send_nmi_to_offline_cpu(unsigned int cpu);
#else /* CONFIG_X86_LOCAL_APIC */
-static inline unsigned int read_apic_id(void) { return 0; }
+static inline u32 read_apic_id(void) { return 0; }
#endif /* !CONFIG_X86_LOCAL_APIC */
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index 2edf68475fec..990eb686ca67 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -94,18 +94,17 @@ arch___clear_bit(unsigned long nr, volatile unsigned long *addr)
asm volatile(__ASM_SIZE(btr) " %1,%0" : : ADDR, "Ir" (nr) : "memory");
}
-static __always_inline bool
-arch_clear_bit_unlock_is_negative_byte(long nr, volatile unsigned long *addr)
+static __always_inline bool arch_xor_unlock_is_negative_byte(unsigned long mask,
+ volatile unsigned long *addr)
{
bool negative;
- asm volatile(LOCK_PREFIX "andb %2,%1"
+ asm volatile(LOCK_PREFIX "xorb %2,%1"
CC_SET(s)
: CC_OUT(s) (negative), WBYTE_ADDR(addr)
- : "ir" ((char) ~(1 << nr)) : "memory");
+ : "iq" ((char)mask) : "memory");
return negative;
}
-#define arch_clear_bit_unlock_is_negative_byte \
- arch_clear_bit_unlock_is_negative_byte
+#define arch_xor_unlock_is_negative_byte arch_xor_unlock_is_negative_byte
static __always_inline void
arch___clear_bit_unlock(long nr, volatile unsigned long *addr)
@@ -293,6 +292,9 @@ static __always_inline unsigned long variable_ffz(unsigned long word)
*/
static __always_inline unsigned long __fls(unsigned long word)
{
+ if (__builtin_constant_p(word))
+ return BITS_PER_LONG - 1 - __builtin_clzl(word);
+
asm("bsr %1,%0"
: "=r" (word)
: "rm" (word));
@@ -360,6 +362,9 @@ static __always_inline int fls(unsigned int x)
{
int r;
+ if (__builtin_constant_p(x))
+ return x ? 32 - __builtin_clz(x) : 0;
+
#ifdef CONFIG_X86_64
/*
* AMD64 says BSRL won't clobber the dest reg if x==0; Intel64 says the
@@ -401,6 +406,9 @@ static __always_inline int fls(unsigned int x)
static __always_inline int fls64(__u64 x)
{
int bitpos = -1;
+
+ if (__builtin_constant_p(x))
+ return x ? 64 - __builtin_clzll(x) : 0;
/*
* AMD64 says BSRQ won't clobber the dest reg if x==0; Intel64 says the
* dest reg is undefined if x==0, but their CPU architect says its
diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h
index b3a7cfb0d99e..a38cc0afc90a 100644
--- a/arch/x86/include/asm/boot.h
+++ b/arch/x86/include/asm/boot.h
@@ -85,6 +85,8 @@ extern const unsigned long kernel_total_size;
unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr,
void (*error)(char *x));
+
+extern struct boot_params *boot_params_ptr;
#endif
#endif /* _ASM_X86_BOOT_H */
diff --git a/arch/x86/include/asm/cacheinfo.h b/arch/x86/include/asm/cacheinfo.h
index ce9685fc78d8..5aa061199866 100644
--- a/arch/x86/include/asm/cacheinfo.h
+++ b/arch/x86/include/asm/cacheinfo.h
@@ -7,9 +7,6 @@ extern unsigned int memory_caching_control;
#define CACHE_MTRR 0x01
#define CACHE_PAT 0x02
-void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu);
-void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu);
-
void cache_disable(void);
void cache_enable(void);
void set_cache_aps_delayed_init(bool val);
diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h
index d53636506134..5612648b0202 100644
--- a/arch/x86/include/asm/cmpxchg.h
+++ b/arch/x86/include/asm/cmpxchg.h
@@ -221,12 +221,18 @@ extern void __add_wrong_size(void)
#define __try_cmpxchg(ptr, pold, new, size) \
__raw_try_cmpxchg((ptr), (pold), (new), (size), LOCK_PREFIX)
+#define __sync_try_cmpxchg(ptr, pold, new, size) \
+ __raw_try_cmpxchg((ptr), (pold), (new), (size), "lock; ")
+
#define __try_cmpxchg_local(ptr, pold, new, size) \
__raw_try_cmpxchg((ptr), (pold), (new), (size), "")
#define arch_try_cmpxchg(ptr, pold, new) \
__try_cmpxchg((ptr), (pold), (new), sizeof(*(ptr)))
+#define arch_sync_try_cmpxchg(ptr, pold, new) \
+ __sync_try_cmpxchg((ptr), (pold), (new), sizeof(*(ptr)))
+
#define arch_try_cmpxchg_local(ptr, pold, new) \
__try_cmpxchg_local((ptr), (pold), (new), sizeof(*(ptr)))
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 3a233ebff712..fecc4fe1d68a 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -28,8 +28,6 @@ struct x86_cpu {
};
#ifdef CONFIG_HOTPLUG_CPU
-extern int arch_register_cpu(int num);
-extern void arch_unregister_cpu(int);
extern void soft_restart_cpu(void);
#endif
@@ -73,26 +71,12 @@ static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {}
extern __noendbr void cet_disable(void);
-struct ucode_cpu_info;
+struct cpu_signature;
-int intel_cpu_collect_info(struct ucode_cpu_info *uci);
-
-static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
- unsigned int s2, unsigned int p2)
-{
- if (s1 != s2)
- return false;
-
- /* Processor flags are either both 0 ... */
- if (!p1 && !p2)
- return true;
-
- /* ... or they intersect. */
- return p1 & p2;
-}
+void intel_collect_cpu_info(struct cpu_signature *sig);
extern u64 x86_read_arch_cap_msr(void);
-int intel_find_matching_signature(void *mc, unsigned int csig, int cpf);
+bool intel_find_matching_signature(void *mc, struct cpu_signature *sig);
int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type);
extern struct cpumask cpus_stop_mask;
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 58cb9495e40f..4af140cf5719 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -443,6 +443,7 @@
/* AMD-defined Extended Feature 2 EAX, CPUID level 0x80000021 (EAX), word 20 */
#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* "" No Nested Data Breakpoints */
+#define X86_FEATURE_WRMSR_XX_BASE_NS (20*32+ 1) /* "" WRMSR to {FS,GS,KERNEL_GS}_BASE is non-serializing */
#define X86_FEATURE_LFENCE_RDTSC (20*32+ 2) /* "" LFENCE always serializing / synchronizes RDTSC */
#define X86_FEATURE_NULL_SEL_CLR_BASE (20*32+ 6) /* "" Null Selector Clears Base */
#define X86_FEATURE_AUTOIBRS (20*32+ 8) /* "" Automatic IBRS */
diff --git a/arch/x86/include/asm/crash_core.h b/arch/x86/include/asm/crash_core.h
new file mode 100644
index 000000000000..76af98f4e801
--- /dev/null
+++ b/arch/x86/include/asm/crash_core.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _X86_CRASH_CORE_H
+#define _X86_CRASH_CORE_H
+
+/* 16M alignment for crash kernel regions */
+#define CRASH_ALIGN SZ_16M
+
+/*
+ * Keep the crash kernel below this limit.
+ *
+ * Earlier 32-bits kernels would limit the kernel to the low 512 MB range
+ * due to mapping restrictions.
+ *
+ * 64-bit kdump kernels need to be restricted to be under 64 TB, which is
+ * the upper limit of system RAM in 4-level paging mode. Since the kdump
+ * jump could be from 5-level paging to 4-level paging, the jump will fail if
+ * the kernel is put above 64 TB, and during the 1st kernel bootup there's
+ * no good way to detect the paging mode of the target kernel which will be
+ * loaded for dumping.
+ */
+extern unsigned long swiotlb_size_or_default(void);
+
+#ifdef CONFIG_X86_32
+# define CRASH_ADDR_LOW_MAX SZ_512M
+# define CRASH_ADDR_HIGH_MAX SZ_512M
+#else
+# define CRASH_ADDR_LOW_MAX SZ_4G
+# define CRASH_ADDR_HIGH_MAX SZ_64T
+#endif
+
+# define DEFAULT_CRASH_KERNEL_LOW_SIZE crash_low_size_default()
+
+static inline unsigned long crash_low_size_default(void)
+{
+#ifdef CONFIG_X86_64
+ return max(swiotlb_size_or_default() + (8UL << 20), 256UL << 20);
+#else
+ return 0;
+#endif
+}
+
+#endif /* _X86_CRASH_CORE_H */
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 18fd06f7936a..a0234dfd1031 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -7,6 +7,7 @@
*/
#include <linux/thread_info.h>
+#include <asm/ia32.h>
#include <asm/ptrace.h>
#include <asm/user.h>
#include <asm/auxvec.h>
@@ -149,7 +150,7 @@ do { \
((x)->e_machine == EM_X86_64)
#define compat_elf_check_arch(x) \
- (elf_check_arch_ia32(x) || \
+ ((elf_check_arch_ia32(x) && ia32_enabled()) || \
(IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64))
static inline void elf_common_init(struct thread_struct *t,
diff --git a/arch/x86/include/asm/fb.h b/arch/x86/include/asm/fb.h
index 23873da8fb77..c3b9582de7ef 100644
--- a/arch/x86/include/asm/fb.h
+++ b/arch/x86/include/asm/fb.h
@@ -2,12 +2,14 @@
#ifndef _ASM_X86_FB_H
#define _ASM_X86_FB_H
+#include <asm/page.h>
+
struct fb_info;
-struct file;
-struct vm_area_struct;
-void fb_pgprotect(struct file *file, struct vm_area_struct *vma, unsigned long off);
-#define fb_pgprotect fb_pgprotect
+pgprot_t pgprot_framebuffer(pgprot_t prot,
+ unsigned long vm_start, unsigned long vm_end,
+ unsigned long offset);
+#define pgprot_framebuffer pgprot_framebuffer
int fb_is_primary_device(struct fb_info *info);
#define fb_is_primary_device fb_is_primary_device
diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h
index 31089b851c4f..a2be3aefff9f 100644
--- a/arch/x86/include/asm/fpu/api.h
+++ b/arch/x86/include/asm/fpu/api.h
@@ -157,7 +157,8 @@ static inline void fpu_update_guest_xfd(struct fpu_guest *guest_fpu, u64 xfd) {
static inline void fpu_sync_guest_vmexit_xfd_state(void) { }
#endif
-extern void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf, unsigned int size, u32 pkru);
+extern void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf,
+ unsigned int size, u64 xfeatures, u32 pkru);
extern int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf, u64 xcr0, u32 *vpkru);
static inline void fpstate_set_confidential(struct fpu_guest *gfpu)
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index 551829884734..b02c3cd3c0f6 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -28,7 +28,7 @@
#include <asm/irq.h>
#include <asm/sections.h>
-#ifdef CONFIG_X86_LOCAL_APIC
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
struct irq_data;
struct pci_dev;
struct msi_desc;
@@ -105,10 +105,10 @@ static inline void irq_complete_move(struct irq_cfg *c) { }
#endif
extern void apic_ack_edge(struct irq_data *data);
-#else /* CONFIG_X86_LOCAL_APIC */
+#else /* CONFIG_IRQ_DOMAIN_HIERARCHY */
static inline void lock_vector_lock(void) {}
static inline void unlock_vector_lock(void) {}
-#endif /* CONFIG_X86_LOCAL_APIC */
+#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */
/* Statistics */
extern atomic_t irq_err_count;
diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index 637fa1df3512..c715097e92fd 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -69,6 +69,8 @@ struct legacy_pic {
void (*make_irq)(unsigned int irq);
};
+void legacy_pic_pcat_compat(void);
+
extern struct legacy_pic *legacy_pic;
extern struct legacy_pic null_legacy_pic;
diff --git a/arch/x86/include/asm/ia32.h b/arch/x86/include/asm/ia32.h
index fada857f0a1e..9805629479d9 100644
--- a/arch/x86/include/asm/ia32.h
+++ b/arch/x86/include/asm/ia32.h
@@ -68,6 +68,27 @@ extern void ia32_pick_mmap_layout(struct mm_struct *mm);
#endif
-#endif /* CONFIG_IA32_EMULATION */
+extern bool __ia32_enabled;
+
+static inline bool ia32_enabled(void)
+{
+ return __ia32_enabled;
+}
+
+static inline void ia32_disable(void)
+{
+ __ia32_enabled = false;
+}
+
+#else /* !CONFIG_IA32_EMULATION */
+
+static inline bool ia32_enabled(void)
+{
+ return IS_ENABLED(CONFIG_X86_32);
+}
+
+static inline void ia32_disable(void) {}
+
+#endif
#endif /* _ASM_X86_IA32_H */
diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h
index 05fd175cec7d..13639e57e1f8 100644
--- a/arch/x86/include/asm/idtentry.h
+++ b/arch/x86/include/asm/idtentry.h
@@ -569,6 +569,10 @@ DECLARE_IDTENTRY_RAW(X86_TRAP_UD, exc_invalid_op);
DECLARE_IDTENTRY_RAW(X86_TRAP_BP, exc_int3);
DECLARE_IDTENTRY_RAW_ERRORCODE(X86_TRAP_PF, exc_page_fault);
+#if defined(CONFIG_IA32_EMULATION)
+DECLARE_IDTENTRY_RAW(IA32_SYSCALL_VECTOR, int80_emulation);
+#endif
+
#ifdef CONFIG_X86_MCE
#ifdef CONFIG_X86_64
DECLARE_IDTENTRY_MCE(X86_TRAP_MC, exc_machine_check);
diff --git a/arch/x86/include/asm/init.h b/arch/x86/include/asm/init.h
index 5f1d3c421f68..cc9ccf61b6bd 100644
--- a/arch/x86/include/asm/init.h
+++ b/arch/x86/include/asm/init.h
@@ -2,6 +2,8 @@
#ifndef _ASM_X86_INIT_H
#define _ASM_X86_INIT_H
+#define __head __section(".head.text")
+
struct x86_mapping_info {
void *(*alloc_pgt_page)(void *); /* allocate buf for page table */
void *context; /* context for alloc_pgt_page */
diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h
index 5fcd85fd64fd..197316121f04 100644
--- a/arch/x86/include/asm/intel-family.h
+++ b/arch/x86/include/asm/intel-family.h
@@ -27,6 +27,7 @@
* _X - regular server parts
* _D - micro server parts
* _N,_P - other mobile parts
+ * _H - premium mobile parts
* _S - other client parts
*
* Historical OPTDIFFs:
@@ -124,6 +125,7 @@
#define INTEL_FAM6_METEORLAKE 0xAC
#define INTEL_FAM6_METEORLAKE_L 0xAA
+#define INTEL_FAM6_ARROWLAKE_H 0xC5
#define INTEL_FAM6_ARROWLAKE 0xC6
#define INTEL_FAM6_LUNARLAKE_M 0xBD
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index a2e9317aad49..5939694dfb28 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -113,8 +113,6 @@ struct kprobe_ctlblk {
};
extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
-extern int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
extern int kprobe_int3_handler(struct pt_regs *regs);
#else
diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h
index e3054e3e46d5..26b628d84594 100644
--- a/arch/x86/include/asm/kvm-x86-ops.h
+++ b/arch/x86/include/asm/kvm-x86-ops.h
@@ -108,6 +108,7 @@ KVM_X86_OP_OPTIONAL(vcpu_blocking)
KVM_X86_OP_OPTIONAL(vcpu_unblocking)
KVM_X86_OP_OPTIONAL(pi_update_irte)
KVM_X86_OP_OPTIONAL(pi_start_assignment)
+KVM_X86_OP_OPTIONAL(apicv_pre_state_restore)
KVM_X86_OP_OPTIONAL(apicv_post_state_restore)
KVM_X86_OP_OPTIONAL_RET0(dy_apicv_has_pending_interrupt)
KVM_X86_OP_OPTIONAL(set_hv_timer)
@@ -126,7 +127,7 @@ KVM_X86_OP_OPTIONAL(vm_copy_enc_context_from)
KVM_X86_OP_OPTIONAL(vm_move_enc_context_from)
KVM_X86_OP_OPTIONAL(guest_memory_reclaimed)
KVM_X86_OP(get_msr_feature)
-KVM_X86_OP(can_emulate_instruction)
+KVM_X86_OP(check_emulate_instruction)
KVM_X86_OP(apic_init_signal_blocked)
KVM_X86_OP_OPTIONAL(enable_l2_tlb_flush)
KVM_X86_OP_OPTIONAL(migrate_timers)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 17715cb8731d..d7036982332e 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -39,7 +39,15 @@
#define __KVM_HAVE_ARCH_VCPU_DEBUGFS
+/*
+ * CONFIG_KVM_MAX_NR_VCPUS is defined iff CONFIG_KVM!=n, provide a dummy max if
+ * KVM is disabled (arbitrarily use the default from CONFIG_KVM_MAX_NR_VCPUS).
+ */
+#ifdef CONFIG_KVM_MAX_NR_VCPUS
+#define KVM_MAX_VCPUS CONFIG_KVM_MAX_NR_VCPUS
+#else
#define KVM_MAX_VCPUS 1024
+#endif
/*
* In x86, the VCPU ID corresponds to the APIC ID, and APIC IDs
@@ -528,7 +536,6 @@ struct kvm_pmu {
u64 raw_event_mask;
struct kvm_pmc gp_counters[KVM_INTEL_PMC_MAX_GENERIC];
struct kvm_pmc fixed_counters[KVM_PMC_MAX_FIXED];
- struct irq_work irq_work;
/*
* Overlay the bitmap with a 64-bit atomic so that all bits can be
@@ -680,6 +687,7 @@ struct kvm_hypervisor_cpuid {
u32 limit;
};
+#ifdef CONFIG_KVM_XEN
/* Xen HVM per vcpu emulation context */
struct kvm_vcpu_xen {
u64 hypercall_rip;
@@ -702,6 +710,7 @@ struct kvm_vcpu_xen {
struct timer_list poll_timer;
struct kvm_hypervisor_cpuid cpuid;
};
+#endif
struct kvm_queued_exception {
bool pending;
@@ -930,8 +939,9 @@ struct kvm_vcpu_arch {
bool hyperv_enabled;
struct kvm_vcpu_hv *hyperv;
+#ifdef CONFIG_KVM_XEN
struct kvm_vcpu_xen xen;
-
+#endif
cpumask_var_t wbinvd_dirty_mask;
unsigned long last_retry_eip;
@@ -1276,7 +1286,6 @@ struct kvm_arch {
*/
spinlock_t mmu_unsync_pages_lock;
- struct list_head assigned_dev_head;
struct iommu_domain *iommu_domain;
bool iommu_noncoherent;
#define __KVM_HAVE_ARCH_NONCOHERENT_DMA
@@ -1324,6 +1333,7 @@ struct kvm_arch {
int nr_vcpus_matched_tsc;
u32 default_tsc_khz;
+ bool user_set_tsc;
seqcount_raw_spinlock_t pvclock_sc;
bool use_master_clock;
@@ -1692,7 +1702,7 @@ struct kvm_x86_ops {
void (*request_immediate_exit)(struct kvm_vcpu *vcpu);
- void (*sched_in)(struct kvm_vcpu *kvm, int cpu);
+ void (*sched_in)(struct kvm_vcpu *vcpu, int cpu);
/*
* Size of the CPU's dirty log buffer, i.e. VMX's PML buffer. A zero
@@ -1709,6 +1719,7 @@ struct kvm_x86_ops {
int (*pi_update_irte)(struct kvm *kvm, unsigned int host_irq,
uint32_t guest_irq, bool set);
void (*pi_start_assignment)(struct kvm *kvm);
+ void (*apicv_pre_state_restore)(struct kvm_vcpu *vcpu);
void (*apicv_post_state_restore)(struct kvm_vcpu *vcpu);
bool (*dy_apicv_has_pending_interrupt)(struct kvm_vcpu *vcpu);
@@ -1734,8 +1745,8 @@ struct kvm_x86_ops {
int (*get_msr_feature)(struct kvm_msr_entry *entry);
- bool (*can_emulate_instruction)(struct kvm_vcpu *vcpu, int emul_type,
- void *insn, int insn_len);
+ int (*check_emulate_instruction)(struct kvm_vcpu *vcpu, int emul_type,
+ void *insn, int insn_len);
bool (*apic_init_signal_blocked)(struct kvm_vcpu *vcpu);
int (*enable_l2_tlb_flush)(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/include/asm/local.h b/arch/x86/include/asm/local.h
index 635132a12778..73dba8b94443 100644
--- a/arch/x86/include/asm/local.h
+++ b/arch/x86/include/asm/local.h
@@ -135,28 +135,27 @@ static inline bool local_try_cmpxchg(local_t *l, long *old, long new)
#define local_xchg(l, n) (xchg(&((l)->a.counter), (n)))
/**
- * local_add_unless - add unless the number is a given value
+ * local_add_unless - add unless the number is already a given value
* @l: pointer of type local_t
* @a: the amount to add to l...
* @u: ...unless l is equal to u.
*
- * Atomically adds @a to @l, so long as it was not @u.
- * Returns non-zero if @l was not @u, and zero otherwise.
+ * Atomically adds @a to @l, if @v was not already @u.
+ * Returns true if the addition was done.
*/
-#define local_add_unless(l, a, u) \
-({ \
- long c, old; \
- c = local_read((l)); \
- for (;;) { \
- if (unlikely(c == (u))) \
- break; \
- old = local_cmpxchg((l), c, c + (a)); \
- if (likely(old == c)) \
- break; \
- c = old; \
- } \
- c != (u); \
-})
+static __always_inline bool
+local_add_unless(local_t *l, long a, long u)
+{
+ long c = local_read(l);
+
+ do {
+ if (unlikely(c == u))
+ return false;
+ } while (!local_try_cmpxchg(l, &c, c + a));
+
+ return true;
+}
+
#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
/* On x86_32, these are no better than the atomic variants.
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 180b1cbfcc4e..6de6e1d95952 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -245,7 +245,7 @@ static inline void cmci_recheck(void) {}
int mce_available(struct cpuinfo_x86 *c);
bool mce_is_memory_error(struct mce *m);
bool mce_is_correctable(struct mce *m);
-int mce_usable_address(struct mce *m);
+bool mce_usable_address(struct mce *m);
DECLARE_PER_CPU(unsigned, mce_exception_count);
DECLARE_PER_CPU(unsigned, mce_poll_count);
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 473b16d73b47..359ada486fa9 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -19,8 +19,10 @@
#ifdef CONFIG_X86_MEM_ENCRYPT
void __init mem_encrypt_init(void);
+void __init mem_encrypt_setup_arch(void);
#else
static inline void mem_encrypt_init(void) { }
+static inline void __init mem_encrypt_setup_arch(void) { }
#endif
#ifdef CONFIG_AMD_MEM_ENCRYPT
@@ -43,7 +45,6 @@ void __init sme_map_bootdata(char *real_mode_data);
void __init sme_unmap_bootdata(char *real_mode_data);
void __init sme_early_init(void);
-void __init sev_setup_arch(void);
void __init sme_encrypt_kernel(struct boot_params *bp);
void __init sme_enable(struct boot_params *bp);
@@ -73,7 +74,6 @@ static inline void __init sme_map_bootdata(char *real_mode_data) { }
static inline void __init sme_unmap_bootdata(char *real_mode_data) { }
static inline void __init sme_early_init(void) { }
-static inline void __init sev_setup_arch(void) { }
static inline void __init sme_encrypt_kernel(struct boot_params *bp) { }
static inline void __init sme_enable(struct boot_params *bp) { }
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index bbbe9d744977..695e569159c1 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -23,6 +23,8 @@ static inline void load_ucode_ap(void) { }
static inline void microcode_bsp_resume(void) { }
#endif
+extern unsigned long initrd_start_early;
+
#ifdef CONFIG_CPU_SUP_INTEL
/* Intel specific microcode defines. Public for IFS */
struct microcode_header_intel {
@@ -36,7 +38,8 @@ struct microcode_header_intel {
unsigned int datasize;
unsigned int totalsize;
unsigned int metasize;
- unsigned int reserved[2];
+ unsigned int min_req_ver;
+ unsigned int reserved;
};
struct microcode_intel {
@@ -68,11 +71,19 @@ static inline u32 intel_get_microcode_revision(void)
return rev;
}
+#endif /* !CONFIG_CPU_SUP_INTEL */
-void show_ucode_info_early(void);
+bool microcode_nmi_handler(void);
+void microcode_offline_nmi_handler(void);
-#else /* CONFIG_CPU_SUP_INTEL */
-static inline void show_ucode_info_early(void) { }
-#endif /* !CONFIG_CPU_SUP_INTEL */
+#ifdef CONFIG_MICROCODE_LATE_LOADING
+DECLARE_STATIC_KEY_FALSE(microcode_nmi_handler_enable);
+static __always_inline bool microcode_nmi_handler_enabled(void)
+{
+ return static_branch_unlikely(&microcode_nmi_handler_enable);
+}
+#else
+static __always_inline bool microcode_nmi_handler_enabled(void) { return false; }
+#endif
#endif /* _ASM_X86_MICROCODE_H */
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index f46df8349e86..4b0f98a8d338 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -37,7 +37,7 @@ extern int mp_bus_id_to_type[MAX_MP_BUSSES];
extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
-extern unsigned int boot_cpu_physical_apicid;
+extern u32 boot_cpu_physical_apicid;
extern u8 boot_cpu_apic_version;
#ifdef CONFIG_X86_LOCAL_APIC
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 896445edc6a8..ce4ce8720d55 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -276,11 +276,11 @@ int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);
#ifdef CONFIG_AMD_MEM_ENCRYPT
bool hv_ghcb_negotiate_protocol(void);
void __noreturn hv_ghcb_terminate(unsigned int set, unsigned int reason);
-int hv_snp_boot_ap(int cpu, unsigned long start_ip);
+int hv_snp_boot_ap(u32 cpu, unsigned long start_ip);
#else
static inline bool hv_ghcb_negotiate_protocol(void) { return false; }
static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {}
-static inline int hv_snp_boot_ap(int cpu, unsigned long start_ip) { return 0; }
+static inline int hv_snp_boot_ap(u32 cpu, unsigned long start_ip) { return 0; }
#endif
#if defined(CONFIG_AMD_MEM_ENCRYPT) || defined(CONFIG_INTEL_TDX_GUEST)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 1d111350197f..1d51e1850ed0 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -222,6 +222,7 @@
#define MSR_INTEGRITY_CAPS_ARRAY_BIST BIT(MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT)
#define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT 4
#define MSR_INTEGRITY_CAPS_PERIODIC_BIST BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT)
+#define MSR_INTEGRITY_CAPS_SAF_GEN_MASK GENMASK_ULL(10, 9)
#define MSR_LBR_NHM_FROM 0x00000680
#define MSR_LBR_NHM_TO 0x000006c0
@@ -553,6 +554,7 @@
#define MSR_AMD64_CPUID_FN_1 0xc0011004
#define MSR_AMD64_LS_CFG 0xc0011020
#define MSR_AMD64_DC_CFG 0xc0011022
+#define MSR_AMD64_TW_CFG 0xc0011023
#define MSR_AMD64_DE_CFG 0xc0011029
#define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT 1
@@ -637,12 +639,21 @@
/* AMD Last Branch Record MSRs */
#define MSR_AMD64_LBR_SELECT 0xc000010e
+/* Zen4 */
+#define MSR_ZEN4_BP_CFG 0xc001102e
+#define MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT 5
+
+/* Fam 19h MSRs */
+#define MSR_F19H_UMC_PERF_CTL 0xc0010800
+#define MSR_F19H_UMC_PERF_CTR 0xc0010801
+
+/* Zen 2 */
+#define MSR_ZEN2_SPECTRAL_CHICKEN 0xc00110e3
+#define MSR_ZEN2_SPECTRAL_CHICKEN_BIT BIT_ULL(1)
+
/* Fam 17h MSRs */
#define MSR_F17H_IRPERF 0xc00000e9
-#define MSR_ZEN2_SPECTRAL_CHICKEN 0xc00110e3
-#define MSR_ZEN2_SPECTRAL_CHICKEN_BIT BIT_ULL(1)
-
/* Fam 16h MSRs */
#define MSR_F16H_L2I_PERF_CTL 0xc0010230
#define MSR_F16H_L2I_PERF_CTR 0xc0010231
@@ -1112,12 +1123,16 @@
#define MSR_IA32_VMX_MISC_INTEL_PT (1ULL << 14)
#define MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS (1ULL << 29)
#define MSR_IA32_VMX_MISC_PREEMPTION_TIMER_SCALE 0x1F
-/* AMD-V MSRs */
+/* AMD-V MSRs */
#define MSR_VM_CR 0xc0010114
#define MSR_VM_IGNNE 0xc0010115
#define MSR_VM_HSAVE_PA 0xc0010117
+#define SVM_VM_CR_VALID_MASK 0x001fULL
+#define SVM_VM_CR_SVM_LOCK_MASK 0x0008ULL
+#define SVM_VM_CR_SVM_DIS_MASK 0x0010ULL
+
/* Hardware Feedback Interface */
#define MSR_IA32_HW_FEEDBACK_PTR 0x17d0
#define MSR_IA32_HW_FEEDBACK_CONFIG 0x17d1
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index c55cc243592e..f93e9b96927a 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -196,7 +196,7 @@
.macro ANNOTATE_RETPOLINE_SAFE
.Lhere_\@:
.pushsection .discard.retpoline_safe
- .long .Lhere_\@ - .
+ .long .Lhere_\@
.popsection
.endm
@@ -271,7 +271,7 @@
.Lskip_rsb_\@:
.endm
-#ifdef CONFIG_CPU_UNRET_ENTRY
+#if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_SRSO)
#define CALL_UNTRAIN_RET "call entry_untrain_ret"
#else
#define CALL_UNTRAIN_RET ""
@@ -288,38 +288,24 @@
* As such, this must be placed after every *SWITCH_TO_KERNEL_CR3 at a point
* where we have a stack but before any RET instruction.
*/
-.macro UNTRAIN_RET
-#if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_IBPB_ENTRY) || \
- defined(CONFIG_CALL_DEPTH_TRACKING) || defined(CONFIG_CPU_SRSO)
+.macro __UNTRAIN_RET ibpb_feature, call_depth_insns
+#if defined(CONFIG_RETHUNK) || defined(CONFIG_CPU_IBPB_ENTRY)
VALIDATE_UNRET_END
ALTERNATIVE_3 "", \
CALL_UNTRAIN_RET, X86_FEATURE_UNRET, \
- "call entry_ibpb", X86_FEATURE_ENTRY_IBPB, \
- __stringify(RESET_CALL_DEPTH), X86_FEATURE_CALL_DEPTH
+ "call entry_ibpb", \ibpb_feature, \
+ __stringify(\call_depth_insns), X86_FEATURE_CALL_DEPTH
#endif
.endm
-.macro UNTRAIN_RET_VM
-#if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_IBPB_ENTRY) || \
- defined(CONFIG_CALL_DEPTH_TRACKING) || defined(CONFIG_CPU_SRSO)
- VALIDATE_UNRET_END
- ALTERNATIVE_3 "", \
- CALL_UNTRAIN_RET, X86_FEATURE_UNRET, \
- "call entry_ibpb", X86_FEATURE_IBPB_ON_VMEXIT, \
- __stringify(RESET_CALL_DEPTH), X86_FEATURE_CALL_DEPTH
-#endif
-.endm
+#define UNTRAIN_RET \
+ __UNTRAIN_RET X86_FEATURE_ENTRY_IBPB, __stringify(RESET_CALL_DEPTH)
-.macro UNTRAIN_RET_FROM_CALL
-#if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_IBPB_ENTRY) || \
- defined(CONFIG_CALL_DEPTH_TRACKING)
- VALIDATE_UNRET_END
- ALTERNATIVE_3 "", \
- CALL_UNTRAIN_RET, X86_FEATURE_UNRET, \
- "call entry_ibpb", X86_FEATURE_ENTRY_IBPB, \
- __stringify(RESET_CALL_DEPTH_FROM_CALL), X86_FEATURE_CALL_DEPTH
-#endif
-.endm
+#define UNTRAIN_RET_VM \
+ __UNTRAIN_RET X86_FEATURE_IBPB_ON_VMEXIT, __stringify(RESET_CALL_DEPTH)
+
+#define UNTRAIN_RET_FROM_CALL \
+ __UNTRAIN_RET X86_FEATURE_ENTRY_IBPB, __stringify(RESET_CALL_DEPTH_FROM_CALL)
.macro CALL_DEPTH_ACCOUNT
@@ -334,7 +320,7 @@
#define ANNOTATE_RETPOLINE_SAFE \
"999:\n\t" \
".pushsection .discard.retpoline_safe\n\t" \
- ".long 999b - .\n\t" \
+ ".long 999b\n\t" \
".popsection\n\t"
typedef u8 retpoline_thunk_t[RETPOLINE_THUNK_SIZE];
@@ -348,13 +334,23 @@ extern void __x86_return_thunk(void);
static inline void __x86_return_thunk(void) {}
#endif
+#ifdef CONFIG_CPU_UNRET_ENTRY
extern void retbleed_return_thunk(void);
+#else
+static inline void retbleed_return_thunk(void) {}
+#endif
+
+#ifdef CONFIG_CPU_SRSO
extern void srso_return_thunk(void);
extern void srso_alias_return_thunk(void);
+#else
+static inline void srso_return_thunk(void) {}
+static inline void srso_alias_return_thunk(void) {}
+#endif
-extern void retbleed_untrain_ret(void);
-extern void srso_untrain_ret(void);
-extern void srso_alias_untrain_ret(void);
+extern void retbleed_return_thunk(void);
+extern void srso_return_thunk(void);
+extern void srso_alias_return_thunk(void);
extern void entry_untrain_ret(void);
extern void entry_ibpb(void);
@@ -362,12 +358,7 @@ extern void entry_ibpb(void);
extern void (*x86_return_thunk)(void);
#ifdef CONFIG_CALL_DEPTH_TRACKING
-extern void __x86_return_skl(void);
-
-static inline void x86_set_skl_return_thunk(void)
-{
- x86_return_thunk = &__x86_return_skl;
-}
+extern void call_depth_return_thunk(void);
#define CALL_DEPTH_ACCOUNT \
ALTERNATIVE("", \
@@ -380,12 +371,12 @@ DECLARE_PER_CPU(u64, __x86_ret_count);
DECLARE_PER_CPU(u64, __x86_stuffs_count);
DECLARE_PER_CPU(u64, __x86_ctxsw_count);
#endif
-#else
-static inline void x86_set_skl_return_thunk(void) {}
+#else /* !CONFIG_CALL_DEPTH_TRACKING */
+static inline void call_depth_return_thunk(void) {}
#define CALL_DEPTH_ACCOUNT ""
-#endif
+#endif /* CONFIG_CALL_DEPTH_TRACKING */
#ifdef CONFIG_RETPOLINE
diff --git a/arch/x86/include/asm/numa.h b/arch/x86/include/asm/numa.h
index e3bae2b60a0d..ef2844d69173 100644
--- a/arch/x86/include/asm/numa.h
+++ b/arch/x86/include/asm/numa.h
@@ -12,13 +12,6 @@
#define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
-/*
- * Too small node sizes may confuse the VM badly. Usually they
- * result from BIOS bugs. So dont recognize nodes as standalone
- * NUMA entities that have less than this amount of RAM listed:
- */
-#define NODE_MIN_SIZE (4*1024*1024)
-
extern int numa_off;
/*
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index 34734d730463..20624b80f890 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -210,6 +210,25 @@ do { \
(typeof(_var))(unsigned long) pco_old__; \
})
+#define percpu_try_cmpxchg_op(size, qual, _var, _ovalp, _nval) \
+({ \
+ bool success; \
+ __pcpu_type_##size *pco_oval__ = (__pcpu_type_##size *)(_ovalp); \
+ __pcpu_type_##size pco_old__ = *pco_oval__; \
+ __pcpu_type_##size pco_new__ = __pcpu_cast_##size(_nval); \
+ asm qual (__pcpu_op2_##size("cmpxchg", "%[nval]", \
+ __percpu_arg([var])) \
+ CC_SET(z) \
+ : CC_OUT(z) (success), \
+ [oval] "+a" (pco_old__), \
+ [var] "+m" (_var) \
+ : [nval] __pcpu_reg_##size(, pco_new__) \
+ : "memory"); \
+ if (unlikely(!success)) \
+ *pco_oval__ = pco_old__; \
+ likely(success); \
+})
+
#if defined(CONFIG_X86_32) && !defined(CONFIG_UML)
#define percpu_cmpxchg64_op(size, qual, _var, _oval, _nval) \
({ \
@@ -223,26 +242,63 @@ do { \
old__.var = _oval; \
new__.var = _nval; \
\
- asm qual (ALTERNATIVE("leal %P[var], %%esi; call this_cpu_cmpxchg8b_emu", \
+ asm qual (ALTERNATIVE("call this_cpu_cmpxchg8b_emu", \
"cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \
: [var] "+m" (_var), \
"+a" (old__.low), \
"+d" (old__.high) \
: "b" (new__.low), \
- "c" (new__.high) \
- : "memory", "esi"); \
+ "c" (new__.high), \
+ "S" (&(_var)) \
+ : "memory"); \
\
old__.var; \
})
#define raw_cpu_cmpxchg64(pcp, oval, nval) percpu_cmpxchg64_op(8, , pcp, oval, nval)
#define this_cpu_cmpxchg64(pcp, oval, nval) percpu_cmpxchg64_op(8, volatile, pcp, oval, nval)
+
+#define percpu_try_cmpxchg64_op(size, qual, _var, _ovalp, _nval) \
+({ \
+ bool success; \
+ u64 *_oval = (u64 *)(_ovalp); \
+ union { \
+ u64 var; \
+ struct { \
+ u32 low, high; \
+ }; \
+ } old__, new__; \
+ \
+ old__.var = *_oval; \
+ new__.var = _nval; \
+ \
+ asm qual (ALTERNATIVE("call this_cpu_cmpxchg8b_emu", \
+ "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \
+ CC_SET(z) \
+ : CC_OUT(z) (success), \
+ [var] "+m" (_var), \
+ "+a" (old__.low), \
+ "+d" (old__.high) \
+ : "b" (new__.low), \
+ "c" (new__.high), \
+ "S" (&(_var)) \
+ : "memory"); \
+ if (unlikely(!success)) \
+ *_oval = old__.var; \
+ likely(success); \
+})
+
+#define raw_cpu_try_cmpxchg64(pcp, ovalp, nval) percpu_try_cmpxchg64_op(8, , pcp, ovalp, nval)
+#define this_cpu_try_cmpxchg64(pcp, ovalp, nval) percpu_try_cmpxchg64_op(8, volatile, pcp, ovalp, nval)
#endif
#ifdef CONFIG_X86_64
#define raw_cpu_cmpxchg64(pcp, oval, nval) percpu_cmpxchg_op(8, , pcp, oval, nval);
#define this_cpu_cmpxchg64(pcp, oval, nval) percpu_cmpxchg_op(8, volatile, pcp, oval, nval);
+#define raw_cpu_try_cmpxchg64(pcp, ovalp, nval) percpu_try_cmpxchg_op(8, , pcp, ovalp, nval);
+#define this_cpu_try_cmpxchg64(pcp, ovalp, nval) percpu_try_cmpxchg_op(8, volatile, pcp, ovalp, nval);
+
#define percpu_cmpxchg128_op(size, qual, _var, _oval, _nval) \
({ \
union { \
@@ -255,20 +311,54 @@ do { \
old__.var = _oval; \
new__.var = _nval; \
\
- asm qual (ALTERNATIVE("leaq %P[var], %%rsi; call this_cpu_cmpxchg16b_emu", \
+ asm qual (ALTERNATIVE("call this_cpu_cmpxchg16b_emu", \
"cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \
: [var] "+m" (_var), \
"+a" (old__.low), \
"+d" (old__.high) \
: "b" (new__.low), \
- "c" (new__.high) \
- : "memory", "rsi"); \
+ "c" (new__.high), \
+ "S" (&(_var)) \
+ : "memory"); \
\
old__.var; \
})
#define raw_cpu_cmpxchg128(pcp, oval, nval) percpu_cmpxchg128_op(16, , pcp, oval, nval)
#define this_cpu_cmpxchg128(pcp, oval, nval) percpu_cmpxchg128_op(16, volatile, pcp, oval, nval)
+
+#define percpu_try_cmpxchg128_op(size, qual, _var, _ovalp, _nval) \
+({ \
+ bool success; \
+ u128 *_oval = (u128 *)(_ovalp); \
+ union { \
+ u128 var; \
+ struct { \
+ u64 low, high; \
+ }; \
+ } old__, new__; \
+ \
+ old__.var = *_oval; \
+ new__.var = _nval; \
+ \
+ asm qual (ALTERNATIVE("call this_cpu_cmpxchg16b_emu", \
+ "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \
+ CC_SET(z) \
+ : CC_OUT(z) (success), \
+ [var] "+m" (_var), \
+ "+a" (old__.low), \
+ "+d" (old__.high) \
+ : "b" (new__.low), \
+ "c" (new__.high), \
+ "S" (&(_var)) \
+ : "memory"); \
+ if (unlikely(!success)) \
+ *_oval = old__.var; \
+ likely(success); \
+})
+
+#define raw_cpu_try_cmpxchg128(pcp, ovalp, nval) percpu_try_cmpxchg128_op(16, , pcp, ovalp, nval)
+#define this_cpu_try_cmpxchg128(pcp, ovalp, nval) percpu_try_cmpxchg128_op(16, volatile, pcp, ovalp, nval)
#endif
/*
@@ -343,6 +433,9 @@ do { \
#define raw_cpu_cmpxchg_1(pcp, oval, nval) percpu_cmpxchg_op(1, , pcp, oval, nval)
#define raw_cpu_cmpxchg_2(pcp, oval, nval) percpu_cmpxchg_op(2, , pcp, oval, nval)
#define raw_cpu_cmpxchg_4(pcp, oval, nval) percpu_cmpxchg_op(4, , pcp, oval, nval)
+#define raw_cpu_try_cmpxchg_1(pcp, ovalp, nval) percpu_try_cmpxchg_op(1, , pcp, ovalp, nval)
+#define raw_cpu_try_cmpxchg_2(pcp, ovalp, nval) percpu_try_cmpxchg_op(2, , pcp, ovalp, nval)
+#define raw_cpu_try_cmpxchg_4(pcp, ovalp, nval) percpu_try_cmpxchg_op(4, , pcp, ovalp, nval)
#define this_cpu_add_return_1(pcp, val) percpu_add_return_op(1, volatile, pcp, val)
#define this_cpu_add_return_2(pcp, val) percpu_add_return_op(2, volatile, pcp, val)
@@ -350,6 +443,9 @@ do { \
#define this_cpu_cmpxchg_1(pcp, oval, nval) percpu_cmpxchg_op(1, volatile, pcp, oval, nval)
#define this_cpu_cmpxchg_2(pcp, oval, nval) percpu_cmpxchg_op(2, volatile, pcp, oval, nval)
#define this_cpu_cmpxchg_4(pcp, oval, nval) percpu_cmpxchg_op(4, volatile, pcp, oval, nval)
+#define this_cpu_try_cmpxchg_1(pcp, ovalp, nval) percpu_try_cmpxchg_op(1, volatile, pcp, ovalp, nval)
+#define this_cpu_try_cmpxchg_2(pcp, ovalp, nval) percpu_try_cmpxchg_op(2, volatile, pcp, ovalp, nval)
+#define this_cpu_try_cmpxchg_4(pcp, ovalp, nval) percpu_try_cmpxchg_op(4, volatile, pcp, ovalp, nval)
/*
* Per cpu atomic 64 bit operations are only available under 64 bit.
@@ -364,6 +460,7 @@ do { \
#define raw_cpu_add_return_8(pcp, val) percpu_add_return_op(8, , pcp, val)
#define raw_cpu_xchg_8(pcp, nval) raw_percpu_xchg_op(pcp, nval)
#define raw_cpu_cmpxchg_8(pcp, oval, nval) percpu_cmpxchg_op(8, , pcp, oval, nval)
+#define raw_cpu_try_cmpxchg_8(pcp, ovalp, nval) percpu_try_cmpxchg_op(8, , pcp, ovalp, nval)
#define this_cpu_read_8(pcp) percpu_from_op(8, volatile, "mov", pcp)
#define this_cpu_write_8(pcp, val) percpu_to_op(8, volatile, "mov", (pcp), val)
@@ -373,6 +470,7 @@ do { \
#define this_cpu_add_return_8(pcp, val) percpu_add_return_op(8, volatile, pcp, val)
#define this_cpu_xchg_8(pcp, nval) percpu_xchg_op(8, volatile, pcp, nval)
#define this_cpu_cmpxchg_8(pcp, oval, nval) percpu_cmpxchg_op(8, volatile, pcp, oval, nval)
+#define this_cpu_try_cmpxchg_8(pcp, ovalp, nval) percpu_try_cmpxchg_op(8, volatile, pcp, ovalp, nval)
#endif
static __always_inline bool x86_this_cpu_constant_test_bit(unsigned int nr,
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 85a9fd5a3ec3..2618ec7c3d1d 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -112,6 +112,13 @@
(AMD64_PERFMON_V2_EVENTSEL_EVENT_NB | \
AMD64_PERFMON_V2_EVENTSEL_UMASK_NB)
+#define AMD64_PERFMON_V2_ENABLE_UMC BIT_ULL(31)
+#define AMD64_PERFMON_V2_EVENTSEL_EVENT_UMC GENMASK_ULL(7, 0)
+#define AMD64_PERFMON_V2_EVENTSEL_RDWRMASK_UMC GENMASK_ULL(9, 8)
+#define AMD64_PERFMON_V2_RAW_EVENT_MASK_UMC \
+ (AMD64_PERFMON_V2_EVENTSEL_EVENT_UMC | \
+ AMD64_PERFMON_V2_EVENTSEL_RDWRMASK_UMC)
+
#define AMD64_NUM_COUNTERS 4
#define AMD64_NUM_COUNTERS_CORE 6
#define AMD64_NUM_COUNTERS_NB 4
@@ -232,6 +239,8 @@ union cpuid_0x80000022_ebx {
unsigned int lbr_v2_stack_sz:6;
/* Number of Data Fabric Counters */
unsigned int num_df_pmc:6;
+ /* Number of Unified Memory Controller Counters */
+ unsigned int num_umc_pmc:6;
} split;
unsigned int full;
};
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index e02b179ec659..57bab91bbf50 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -1716,6 +1716,14 @@ static inline bool pud_user_accessible_page(pud_t pud)
}
#endif
+#ifdef CONFIG_X86_SGX
+int arch_memory_failure(unsigned long pfn, int flags);
+#define arch_memory_failure arch_memory_failure
+
+bool arch_is_platform_page(u64 paddr);
+#define arch_is_platform_page arch_is_platform_page
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_X86_PGTABLE_H */
diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h
index 2d13f25b1bd8..4527e1430c6d 100644
--- a/arch/x86/include/asm/preempt.h
+++ b/arch/x86/include/asm/preempt.h
@@ -31,11 +31,11 @@ static __always_inline void preempt_count_set(int pc)
{
int old, new;
+ old = raw_cpu_read_4(pcpu_hot.preempt_count);
do {
- old = raw_cpu_read_4(pcpu_hot.preempt_count);
new = (old & PREEMPT_NEED_RESCHED) |
(pc & ~PREEMPT_NEED_RESCHED);
- } while (raw_cpu_cmpxchg_4(pcpu_hot.preempt_count, old, new) != old);
+ } while (!raw_cpu_try_cmpxchg_4(pcpu_hot.preempt_count, &old, new));
}
/*
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index a3669a7774ed..ae81a7191c1c 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -75,11 +75,36 @@ extern u16 __read_mostly tlb_lld_4m[NR_INFO];
extern u16 __read_mostly tlb_lld_1g[NR_INFO];
/*
- * CPU type and hardware bug flags. Kept separately for each CPU.
- * Members of this structure are referenced in head_32.S, so think twice
- * before touching them. [mj]
+ * CPU type and hardware bug flags. Kept separately for each CPU.
*/
+struct cpuinfo_topology {
+ // Real APIC ID read from the local APIC
+ u32 apicid;
+ // The initial APIC ID provided by CPUID
+ u32 initial_apicid;
+
+ // Physical package ID
+ u32 pkg_id;
+
+ // Physical die ID on AMD, Relative on Intel
+ u32 die_id;
+
+ // Compute unit ID - AMD specific
+ u32 cu_id;
+
+ // Core ID relative to the package
+ u32 core_id;
+
+ // Logical ID mappings
+ u32 logical_pkg_id;
+ u32 logical_die_id;
+
+ // Cache level topology IDs
+ u32 llc_id;
+ u32 l2c_id;
+};
+
struct cpuinfo_x86 {
__u8 x86; /* CPU family */
__u8 x86_vendor; /* CPU vendor */
@@ -96,7 +121,6 @@ struct cpuinfo_x86 {
__u8 x86_phys_bits;
/* CPUID returned core id bits: */
__u8 x86_coreid_bits;
- __u8 cu_id;
/* Max extended CPUID function supported: */
__u32 extended_cpuid_level;
/* Maximum supported CPUID level, -1=no CPUID: */
@@ -112,6 +136,7 @@ struct cpuinfo_x86 {
};
char x86_vendor_id[16];
char x86_model_id[64];
+ struct cpuinfo_topology topo;
/* in KB - valid for CPUS which support this call: */
unsigned int x86_cache_size;
int x86_cache_alignment; /* In bytes */
@@ -125,19 +150,9 @@ struct cpuinfo_x86 {
u64 ppin;
/* cpuid returned max cores value: */
u16 x86_max_cores;
- u16 apicid;
- u16 initial_apicid;
u16 x86_clflush_size;
/* number of cores as seen by the OS: */
u16 booted_cores;
- /* Physical processor id: */
- u16 phys_proc_id;
- /* Logical processor id: */
- u16 logical_proc_id;
- /* Core id: */
- u16 cpu_core_id;
- u16 cpu_die_id;
- u16 logical_die_id;
/* Index into per_cpu list: */
u16 cpu_index;
/* Is SMT active on this core? */
@@ -399,7 +414,7 @@ static inline unsigned long cpu_kernelmode_gs_base(int cpu)
return (unsigned long)per_cpu(fixed_percpu_data.gs_base, cpu);
}
-extern asmlinkage void ignore_sysret(void);
+extern asmlinkage void entry_SYSCALL32_ignore(void);
/* Save actual FS/GS selectors and bases to current->thread */
void current_save_fsgs(void);
@@ -678,7 +693,15 @@ extern int set_tsc_mode(unsigned int val);
DECLARE_PER_CPU(u64, msr_misc_features_shadow);
-extern u16 get_llc_id(unsigned int cpu);
+static inline u32 per_cpu_llc_id(unsigned int cpu)
+{
+ return per_cpu(cpu_info.topo.llc_id, cpu);
+}
+
+static inline u32 per_cpu_l2c_id(unsigned int cpu)
+{
+ return per_cpu(cpu_info.topo.l2c_id, cpu);
+}
#ifdef CONFIG_CPU_SUP_AMD
extern u32 amd_get_nodes_per_socket(void);
@@ -724,14 +747,6 @@ enum mds_mitigations {
MDS_MITIGATION_VMWERV,
};
-#ifdef CONFIG_X86_SGX
-int arch_memory_failure(unsigned long pfn, int flags);
-#define arch_memory_failure arch_memory_failure
-
-bool arch_is_platform_page(u64 paddr);
-#define arch_is_platform_page arch_is_platform_page
-#endif
-
extern bool gds_ucode_mitigated(void);
#endif /* _ASM_X86_PROCESSOR_H */
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index b716d291d0d4..65dee2420624 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -31,6 +31,11 @@ static inline void x86_dtb_init(void) { }
#define of_ioapic 0
#endif
+#ifdef CONFIG_OF_EARLY_FLATTREE
+void x86_flattree_get_config(void);
+#else
+static inline void x86_flattree_get_config(void) { }
+#endif
extern char cmd_line[COMMAND_LINE_SIZE];
#endif /* __ASSEMBLY__ */
diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h
index 12ef86b19910..484f4f0131a5 100644
--- a/arch/x86/include/asm/proto.h
+++ b/arch/x86/include/asm/proto.h
@@ -32,10 +32,9 @@ void entry_SYSCALL_compat(void);
void entry_SYSCALL_compat_safe_stack(void);
void entry_SYSRETL_compat_unsafe_stack(void);
void entry_SYSRETL_compat_end(void);
-void entry_INT80_compat(void);
-#ifdef CONFIG_XEN_PV
-void xen_entry_INT80_compat(void);
-#endif
+#else /* !CONFIG_IA32_EMULATION */
+#define entry_SYSCALL_compat NULL
+#define entry_SYSENTER_compat NULL
#endif
void x86_configure_nx(void);
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index f3495623ac99..bf483fcb4e57 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -126,6 +126,7 @@ void clear_bss(void);
#ifdef __i386__
asmlinkage void __init __noreturn i386_start_kernel(void);
+void __init mk_early_pgtbl_32(void);
#else
asmlinkage void __init __noreturn x86_64_start_kernel(char *real_mode);
diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h
index 7513b3bb69b7..ccce7ebd8677 100644
--- a/arch/x86/include/asm/shared/tdx.h
+++ b/arch/x86/include/asm/shared/tdx.h
@@ -11,45 +11,85 @@
#define TDX_IDENT "IntelTDX "
/* TDX module Call Leaf IDs */
-#define TDX_GET_INFO 1
-#define TDX_GET_VEINFO 3
-#define TDX_GET_REPORT 4
-#define TDX_ACCEPT_PAGE 6
-#define TDX_WR 8
+#define TDG_VP_VMCALL 0
+#define TDG_VP_INFO 1
+#define TDG_VP_VEINFO_GET 3
+#define TDG_MR_REPORT 4
+#define TDG_MEM_PAGE_ACCEPT 6
+#define TDG_VM_WR 8
/* TDCS fields. To be used by TDG.VM.WR and TDG.VM.RD module calls */
#define TDCS_NOTIFY_ENABLES 0x9100000000000010
/* TDX hypercall Leaf IDs */
#define TDVMCALL_MAP_GPA 0x10001
+#define TDVMCALL_GET_QUOTE 0x10002
#define TDVMCALL_REPORT_FATAL_ERROR 0x10003
+#define TDVMCALL_STATUS_RETRY 1
+
+/*
+ * Bitmasks of exposed registers (with VMM).
+ */
+#define TDX_RDX BIT(2)
+#define TDX_RBX BIT(3)
+#define TDX_RSI BIT(6)
+#define TDX_RDI BIT(7)
+#define TDX_R8 BIT(8)
+#define TDX_R9 BIT(9)
+#define TDX_R10 BIT(10)
+#define TDX_R11 BIT(11)
+#define TDX_R12 BIT(12)
+#define TDX_R13 BIT(13)
+#define TDX_R14 BIT(14)
+#define TDX_R15 BIT(15)
+
+/*
+ * These registers are clobbered to hold arguments for each
+ * TDVMCALL. They are safe to expose to the VMM.
+ * Each bit in this mask represents a register ID. Bit field
+ * details can be found in TDX GHCI specification, section
+ * titled "TDCALL [TDG.VP.VMCALL] leaf".
+ */
+#define TDVMCALL_EXPOSE_REGS_MASK \
+ (TDX_RDX | TDX_RBX | TDX_RSI | TDX_RDI | TDX_R8 | TDX_R9 | \
+ TDX_R10 | TDX_R11 | TDX_R12 | TDX_R13 | TDX_R14 | TDX_R15)
+
#ifndef __ASSEMBLY__
+#include <linux/compiler_attributes.h>
+
/*
- * Used in __tdx_hypercall() to pass down and get back registers' values of
- * the TDCALL instruction when requesting services from the VMM.
- *
- * This is a software only structure and not part of the TDX module/VMM ABI.
+ * Used in __tdcall*() to gather the input/output registers' values of the
+ * TDCALL instruction when requesting services from the TDX module. This is a
+ * software only structure and not part of the TDX module/VMM ABI
*/
-struct tdx_hypercall_args {
+struct tdx_module_args {
+ /* callee-clobbered */
+ u64 rcx;
+ u64 rdx;
u64 r8;
u64 r9;
+ /* extra callee-clobbered */
u64 r10;
u64 r11;
+ /* callee-saved + rdi/rsi */
u64 r12;
u64 r13;
u64 r14;
u64 r15;
+ u64 rbx;
u64 rdi;
u64 rsi;
- u64 rbx;
- u64 rdx;
};
+/* Used to communicate with the TDX module */
+u64 __tdcall(u64 fn, struct tdx_module_args *args);
+u64 __tdcall_ret(u64 fn, struct tdx_module_args *args);
+u64 __tdcall_saved_ret(u64 fn, struct tdx_module_args *args);
+
/* Used to request services from the VMM */
-u64 __tdx_hypercall(struct tdx_hypercall_args *args);
-u64 __tdx_hypercall_ret(struct tdx_hypercall_args *args);
+u64 __tdx_hypercall(struct tdx_module_args *args);
/*
* Wrapper for standard use of __tdx_hypercall with no output aside from
@@ -57,7 +97,7 @@ u64 __tdx_hypercall_ret(struct tdx_hypercall_args *args);
*/
static inline u64 _tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15)
{
- struct tdx_hypercall_args args = {
+ struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = fn,
.r12 = r12,
@@ -71,25 +111,7 @@ static inline u64 _tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15)
/* Called from __tdx_hypercall() for unrecoverable failure */
-void __tdx_hypercall_failed(void);
-
-/*
- * Used in __tdx_module_call() to gather the output registers' values of the
- * TDCALL instruction when requesting services from the TDX module. This is a
- * software only structure and not part of the TDX module/VMM ABI
- */
-struct tdx_module_output {
- u64 rcx;
- u64 rdx;
- u64 r8;
- u64 r9;
- u64 r10;
- u64 r11;
-};
-
-/* Used to communicate with the TDX module */
-u64 __tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
- struct tdx_module_output *out);
+void __noreturn __tdx_hypercall_failed(void);
bool tdx_accept_memory(phys_addr_t start, phys_addr_t end);
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index ad98dd1d9cfb..4fab2ed454f3 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -17,10 +17,8 @@ DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_die_map);
/* cpus sharing the last level cache: */
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_l2c_shared_map);
-DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id);
-DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_l2c_id);
-DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid);
+DECLARE_EARLY_PER_CPU_READ_MOSTLY(u32, x86_cpu_to_apicid);
DECLARE_EARLY_PER_CPU_READ_MOSTLY(u32, x86_cpu_to_acpiid);
struct task_struct;
@@ -129,7 +127,6 @@ void native_smp_send_reschedule(int cpu);
void native_send_call_func_ipi(const struct cpumask *mask);
void native_send_call_func_single_ipi(int cpu);
-bool smp_park_other_cpus_in_init(void);
void smp_store_cpu_info(int id);
asmlinkage __visible void smp_reboot_interrupt(void);
diff --git a/arch/x86/include/asm/sparsemem.h b/arch/x86/include/asm/sparsemem.h
index 64df897c0ee3..1be13b2dfe8b 100644
--- a/arch/x86/include/asm/sparsemem.h
+++ b/arch/x86/include/asm/sparsemem.h
@@ -37,6 +37,8 @@ extern int phys_to_target_node(phys_addr_t start);
#define phys_to_target_node phys_to_target_node
extern int memory_add_physaddr_to_nid(u64 start);
#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid
+extern int numa_fill_memblks(u64 start, u64 end);
+#define numa_fill_memblks numa_fill_memblks
#endif
#endif /* __ASSEMBLY__ */
diff --git a/arch/x86/include/asm/spec-ctrl.h b/arch/x86/include/asm/spec-ctrl.h
index cb0386fc4dc3..c648502e4535 100644
--- a/arch/x86/include/asm/spec-ctrl.h
+++ b/arch/x86/include/asm/spec-ctrl.h
@@ -4,6 +4,7 @@
#include <linux/thread_info.h>
#include <asm/nospec-branch.h>
+#include <asm/msr.h>
/*
* On VMENTER we must preserve whatever view of the SPEC_CTRL MSR
@@ -76,6 +77,16 @@ static inline u64 ssbd_tif_to_amd_ls_cfg(u64 tifn)
return (tifn & _TIF_SSBD) ? x86_amd_ls_cfg_ssbd_mask : 0ULL;
}
+/*
+ * This can be used in noinstr functions & should only be called in bare
+ * metal context.
+ */
+static __always_inline void __update_spec_ctrl(u64 val)
+{
+ __this_cpu_write(x86_spec_ctrl_current, val);
+ native_wrmsrl(MSR_IA32_SPEC_CTRL, val);
+}
+
#ifdef CONFIG_SMP
extern void speculative_store_bypass_ht_init(void);
#else
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 19bf955b67e0..87a7b917d30e 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -229,10 +229,6 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
#define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT)
#define SVM_IOIO_ASIZE_MASK (7 << SVM_IOIO_ASIZE_SHIFT)
-#define SVM_VM_CR_VALID_MASK 0x001fULL
-#define SVM_VM_CR_SVM_LOCK_MASK 0x0008ULL
-#define SVM_VM_CR_SVM_DIS_MASK 0x0010ULL
-
#define SVM_NESTED_CTL_NP_ENABLE BIT(0)
#define SVM_NESTED_CTL_SEV_ENABLE BIT(1)
#define SVM_NESTED_CTL_SEV_ES_ENABLE BIT(2)
@@ -268,6 +264,7 @@ enum avic_ipi_failure_cause {
AVIC_IPI_FAILURE_TARGET_NOT_RUNNING,
AVIC_IPI_FAILURE_INVALID_TARGET,
AVIC_IPI_FAILURE_INVALID_BACKING_PAGE,
+ AVIC_IPI_FAILURE_INVALID_IPI_VECTOR,
};
#define AVIC_PHYSICAL_MAX_INDEX_MASK GENMASK_ULL(8, 0)
@@ -571,8 +568,6 @@ struct vmcb {
#define SVM_CPUID_FUNC 0x8000000a
-#define SVM_VM_CR_SVM_DISABLE 4
-
#define SVM_SELECTOR_S_SHIFT 4
#define SVM_SELECTOR_DPL_SHIFT 5
#define SVM_SELECTOR_P_SHIFT 7
diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h
index 4fb36fba4b5a..f44e2f9ab65d 100644
--- a/arch/x86/include/asm/syscall.h
+++ b/arch/x86/include/asm/syscall.h
@@ -126,12 +126,12 @@ static inline int syscall_get_arch(struct task_struct *task)
? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
}
-void do_syscall_64(struct pt_regs *regs, int nr);
+bool do_syscall_64(struct pt_regs *regs, int nr);
#endif /* CONFIG_X86_32 */
void do_int80_syscall_32(struct pt_regs *regs);
-long do_fast_syscall_32(struct pt_regs *regs);
-long do_SYSENTER_32(struct pt_regs *regs);
+bool do_fast_syscall_32(struct pt_regs *regs);
+bool do_SYSENTER_32(struct pt_regs *regs);
#endif /* _ASM_X86_SYSCALL_H */
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 603e6d1e9d4a..f3d5305a60fc 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -8,6 +8,7 @@
#include <asm/errno.h>
#include <asm/ptrace.h>
+#include <asm/trapnr.h>
#include <asm/shared/tdx.h>
/*
@@ -20,6 +21,9 @@
#define TDX_SW_ERROR (TDX_ERROR | GENMASK_ULL(47, 40))
#define TDX_SEAMCALL_VMFAILINVALID (TDX_SW_ERROR | _UL(0xFFFF0000))
+#define TDX_SEAMCALL_GP (TDX_SW_ERROR | X86_TRAP_GP)
+#define TDX_SEAMCALL_UD (TDX_SW_ERROR | X86_TRAP_UD)
+
#ifndef __ASSEMBLY__
/*
@@ -52,6 +56,8 @@ bool tdx_early_handle_ve(struct pt_regs *regs);
int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport);
+u64 tdx_hcall_get_quote(u8 *buf, size_t size);
+
#else
static inline void tdx_early_init(void) { };
@@ -72,5 +78,12 @@ static inline long tdx_kvm_hypercall(unsigned int nr, unsigned long p1,
return -ENODEV;
}
#endif /* CONFIG_INTEL_TDX_GUEST && CONFIG_KVM_GUEST */
+
+#ifdef CONFIG_INTEL_TDX_HOST
+u64 __seamcall(u64 fn, struct tdx_module_args *args);
+u64 __seamcall_ret(u64 fn, struct tdx_module_args *args);
+u64 __seamcall_saved_ret(u64 fn, struct tdx_module_args *args);
+#endif /* CONFIG_INTEL_TDX_HOST */
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_X86_TDX_H */
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index 3235ba1e5b06..5f87f6b9b09e 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -105,17 +105,17 @@ static inline void setup_node_to_cpumask_map(void) { }
extern const struct cpumask *cpu_coregroup_mask(int cpu);
extern const struct cpumask *cpu_clustergroup_mask(int cpu);
-#define topology_logical_package_id(cpu) (cpu_data(cpu).logical_proc_id)
-#define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id)
-#define topology_logical_die_id(cpu) (cpu_data(cpu).logical_die_id)
-#define topology_die_id(cpu) (cpu_data(cpu).cpu_die_id)
-#define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id)
+#define topology_logical_package_id(cpu) (cpu_data(cpu).topo.logical_pkg_id)
+#define topology_physical_package_id(cpu) (cpu_data(cpu).topo.pkg_id)
+#define topology_logical_die_id(cpu) (cpu_data(cpu).topo.logical_die_id)
+#define topology_die_id(cpu) (cpu_data(cpu).topo.die_id)
+#define topology_core_id(cpu) (cpu_data(cpu).topo.core_id)
#define topology_ppin(cpu) (cpu_data(cpu).ppin)
extern unsigned int __max_die_per_package;
#ifdef CONFIG_SMP
-#define topology_cluster_id(cpu) (per_cpu(cpu_l2c_id, cpu))
+#define topology_cluster_id(cpu) (cpu_data(cpu).topo.l2c_id)
#define topology_die_cpumask(cpu) (per_cpu(cpu_die_map, cpu))
#define topology_cluster_cpumask(cpu) (cpu_clustergroup_mask(cpu))
#define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu))
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 8bae40a66282..5c367c1290c3 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -496,7 +496,7 @@ copy_mc_to_kernel(void *to, const void *from, unsigned len);
#define copy_mc_to_kernel copy_mc_to_kernel
unsigned long __must_check
-copy_mc_to_user(void *to, const void *from, unsigned len);
+copy_mc_to_user(void __user *to, const void *from, unsigned len);
#endif
/*
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 5240d88db52a..c878616a18b8 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -177,7 +177,7 @@ struct x86_init_ops {
* struct x86_cpuinit_ops - platform specific cpu hotplug setups
* @setup_percpu_clockev: set up the per cpu clock event device
* @early_percpu_clock_init: early init of the per cpu clock event device
- * @fixup_cpu_id: fixup function for cpuinfo_x86::phys_proc_id
+ * @fixup_cpu_id: fixup function for cpuinfo_x86::topo.pkg_id
* @parallel_bringup: Parallel bringup control
*/
struct x86_cpuinit_ops {
diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h
index 7048dfacc04b..a9088250770f 100644
--- a/arch/x86/include/asm/xen/hypervisor.h
+++ b/arch/x86/include/asm/xen/hypervisor.h
@@ -100,4 +100,13 @@ static inline void leave_lazy(enum xen_lazy_mode mode)
enum xen_lazy_mode xen_get_lazy_mode(void);
+#if defined(CONFIG_XEN_DOM0) && defined(CONFIG_ACPI)
+void xen_sanitize_proc_cap_bits(uint32_t *buf);
+#else
+static inline void xen_sanitize_proc_cap_bits(uint32_t *buf)
+{
+ BUG();
+}
+#endif
+
#endif /* _ASM_X86_XEN_HYPERVISOR_H */
diff --git a/arch/x86/include/uapi/asm/amd_hsmp.h b/arch/x86/include/uapi/asm/amd_hsmp.h
index 769b939444ae..fce22686c834 100644
--- a/arch/x86/include/uapi/asm/amd_hsmp.h
+++ b/arch/x86/include/uapi/asm/amd_hsmp.h
@@ -47,6 +47,9 @@ enum hsmp_message_ids {
HSMP_SET_PCI_RATE, /* 20h Control link rate on PCIe devices */
HSMP_SET_POWER_MODE, /* 21h Select power efficiency profile policy */
HSMP_SET_PSTATE_MAX_MIN, /* 22h Set the max and min DF P-State */
+ HSMP_GET_METRIC_TABLE_VER, /* 23h Get metrics table version */
+ HSMP_GET_METRIC_TABLE, /* 24h Get metrics table */
+ HSMP_GET_METRIC_TABLE_DRAM_ADDR,/* 25h Get metrics table dram address */
HSMP_MSG_ID_MAX,
};
@@ -64,6 +67,14 @@ enum hsmp_msg_type {
HSMP_GET = 1,
};
+enum hsmp_proto_versions {
+ HSMP_PROTO_VER2 = 2,
+ HSMP_PROTO_VER3,
+ HSMP_PROTO_VER4,
+ HSMP_PROTO_VER5,
+ HSMP_PROTO_VER6
+};
+
struct hsmp_msg_desc {
int num_args;
int response_sz;
@@ -295,6 +306,104 @@ static const struct hsmp_msg_desc hsmp_msg_desc_table[] = {
* input: args[0] = min df pstate[15:8] + max df pstate[7:0]
*/
{1, 0, HSMP_SET},
+
+ /*
+ * HSMP_GET_METRIC_TABLE_VER, num_args = 0, response_sz = 1
+ * output: args[0] = metrics table version
+ */
+ {0, 1, HSMP_GET},
+
+ /*
+ * HSMP_GET_METRIC_TABLE, num_args = 0, response_sz = 0
+ */
+ {0, 0, HSMP_GET},
+
+ /*
+ * HSMP_GET_METRIC_TABLE_DRAM_ADDR, num_args = 0, response_sz = 2
+ * output: args[0] = lower 32 bits of the address
+ * output: args[1] = upper 32 bits of the address
+ */
+ {0, 2, HSMP_GET},
+};
+
+/* Metrics table (supported only with proto version 6) */
+struct hsmp_metric_table {
+ __u32 accumulation_counter;
+
+ /* TEMPERATURE */
+ __u32 max_socket_temperature;
+ __u32 max_vr_temperature;
+ __u32 max_hbm_temperature;
+ __u64 max_socket_temperature_acc;
+ __u64 max_vr_temperature_acc;
+ __u64 max_hbm_temperature_acc;
+
+ /* POWER */
+ __u32 socket_power_limit;
+ __u32 max_socket_power_limit;
+ __u32 socket_power;
+
+ /* ENERGY */
+ __u64 timestamp;
+ __u64 socket_energy_acc;
+ __u64 ccd_energy_acc;
+ __u64 xcd_energy_acc;
+ __u64 aid_energy_acc;
+ __u64 hbm_energy_acc;
+
+ /* FREQUENCY */
+ __u32 cclk_frequency_limit;
+ __u32 gfxclk_frequency_limit;
+ __u32 fclk_frequency;
+ __u32 uclk_frequency;
+ __u32 socclk_frequency[4];
+ __u32 vclk_frequency[4];
+ __u32 dclk_frequency[4];
+ __u32 lclk_frequency[4];
+ __u64 gfxclk_frequency_acc[8];
+ __u64 cclk_frequency_acc[96];
+
+ /* FREQUENCY RANGE */
+ __u32 max_cclk_frequency;
+ __u32 min_cclk_frequency;
+ __u32 max_gfxclk_frequency;
+ __u32 min_gfxclk_frequency;
+ __u32 fclk_frequency_table[4];
+ __u32 uclk_frequency_table[4];
+ __u32 socclk_frequency_table[4];
+ __u32 vclk_frequency_table[4];
+ __u32 dclk_frequency_table[4];
+ __u32 lclk_frequency_table[4];
+ __u32 max_lclk_dpm_range;
+ __u32 min_lclk_dpm_range;
+
+ /* XGMI */
+ __u32 xgmi_width;
+ __u32 xgmi_bitrate;
+ __u64 xgmi_read_bandwidth_acc[8];
+ __u64 xgmi_write_bandwidth_acc[8];
+
+ /* ACTIVITY */
+ __u32 socket_c0_residency;
+ __u32 socket_gfx_busy;
+ __u32 dram_bandwidth_utilization;
+ __u64 socket_c0_residency_acc;
+ __u64 socket_gfx_busy_acc;
+ __u64 dram_bandwidth_acc;
+ __u32 max_dram_bandwidth;
+ __u64 dram_bandwidth_utilization_acc;
+ __u64 pcie_bandwidth_acc[4];
+
+ /* THROTTLERS */
+ __u32 prochot_residency_acc;
+ __u32 ppt_residency_acc;
+ __u32 socket_thm_residency_acc;
+ __u32 vr_thm_residency_acc;
+ __u32 hbm_thm_residency_acc;
+ __u32 spare;
+
+ /* New items at the end to maintain driver compatibility */
+ __u32 gfxclk_frequency[8];
};
/* Reset to default packing */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 3269a0e23d3a..0000325ab98f 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -16,6 +16,7 @@ CFLAGS_REMOVE_kvmclock.o = -pg
CFLAGS_REMOVE_ftrace.o = -pg
CFLAGS_REMOVE_early_printk.o = -pg
CFLAGS_REMOVE_head64.o = -pg
+CFLAGS_REMOVE_head32.o = -pg
CFLAGS_REMOVE_sev.o = -pg
CFLAGS_REMOVE_rethook.o = -pg
endif
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 2a0ea38955df..1a0dd80d81ac 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -63,6 +63,7 @@ int acpi_fix_pin2_polarity __initdata;
#ifdef CONFIG_X86_LOCAL_APIC
static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
+static bool has_lapic_cpus __initdata;
static bool acpi_support_online_capable;
#endif
@@ -148,6 +149,9 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
pr_debug("Local APIC address 0x%08x\n", madt->address);
}
+ if (madt->flags & ACPI_MADT_PCAT_COMPAT)
+ legacy_pic_pcat_compat();
+
/* ACPI 6.3 and newer support the online capable bit. */
if (acpi_gbl_FADT.header.revision > 6 ||
(acpi_gbl_FADT.header.revision == 6 &&
@@ -230,6 +234,14 @@ acpi_parse_x2apic(union acpi_subtable_headers *header, const unsigned long end)
return 0;
/*
+ * According to https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html#processor-local-x2apic-structure
+ * when MADT provides both valid LAPIC and x2APIC entries, the APIC ID
+ * in x2APIC must be equal or greater than 0xff.
+ */
+ if (has_lapic_cpus && apic_id < 0xff)
+ return 0;
+
+ /*
* We need to register disabled CPU as well to permit
* counting disabled CPUs. This allows us to size
* cpus_possible_map more accurately, to permit
@@ -359,7 +371,7 @@ acpi_parse_lapic_nmi(union acpi_subtable_headers * header, const unsigned long e
}
#ifdef CONFIG_X86_64
-static int acpi_wakeup_cpu(int apicid, unsigned long start_ip)
+static int acpi_wakeup_cpu(u32 apicid, unsigned long start_ip)
{
/*
* Remap mailbox memory only for the first call to acpi_wakeup_cpu().
@@ -856,7 +868,7 @@ int acpi_unmap_cpu(int cpu)
set_apicid_to_node(per_cpu(x86_cpu_to_apicid, cpu), NUMA_NO_NODE);
#endif
- per_cpu(x86_cpu_to_apicid, cpu) = -1;
+ per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID;
set_cpu_present(cpu, false);
num_processors--;
@@ -1111,10 +1123,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
static int __init acpi_parse_madt_lapic_entries(void)
{
- int count;
- int x2count = 0;
- int ret;
- struct acpi_subtable_proc madt_proc[2];
+ int count, x2count = 0;
if (!boot_cpu_has(X86_FEATURE_APIC))
return -ENODEV;
@@ -1123,21 +1132,11 @@ static int __init acpi_parse_madt_lapic_entries(void)
acpi_parse_sapic, MAX_LOCAL_APIC);
if (!count) {
- memset(madt_proc, 0, sizeof(madt_proc));
- madt_proc[0].id = ACPI_MADT_TYPE_LOCAL_APIC;
- madt_proc[0].handler = acpi_parse_lapic;
- madt_proc[1].id = ACPI_MADT_TYPE_LOCAL_X2APIC;
- madt_proc[1].handler = acpi_parse_x2apic;
- ret = acpi_table_parse_entries_array(ACPI_SIG_MADT,
- sizeof(struct acpi_table_madt),
- madt_proc, ARRAY_SIZE(madt_proc), MAX_LOCAL_APIC);
- if (ret < 0) {
- pr_err("Error parsing LAPIC/X2APIC entries\n");
- return ret;
- }
-
- count = madt_proc[0].count;
- x2count = madt_proc[1].count;
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
+ acpi_parse_lapic, MAX_LOCAL_APIC);
+ has_lapic_cpus = count > 0;
+ x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC,
+ acpi_parse_x2apic, MAX_LOCAL_APIC);
}
if (!count && !x2count) {
pr_err("No LAPIC entries present\n");
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 517ee01503be..73be3931e4f0 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -403,6 +403,17 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
u8 insn_buff[MAX_PATCH_LEN];
DPRINTK(ALT, "alt table %px, -> %px", start, end);
+
+ /*
+ * In the case CONFIG_X86_5LEVEL=y, KASAN_SHADOW_START is defined using
+ * cpu_feature_enabled(X86_FEATURE_LA57) and is therefore patched here.
+ * During the process, KASAN becomes confused seeing partial LA57
+ * conversion and triggers a false-positive out-of-bound report.
+ *
+ * Disable KASAN until the patching is complete.
+ */
+ kasan_disable_current();
+
/*
* The scan order should be from start to end. A later scanned
* alternative code can overwrite previously scanned alternative code.
@@ -452,6 +463,8 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
text_poke_early(instr, insn_buff, insn_buff_sz);
}
+
+ kasan_enable_current();
}
static inline bool is_jcc32(struct insn *insn)
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index 356de955e78d..053f6dcc6b2c 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -27,6 +27,7 @@
#define PCI_DEVICE_ID_AMD_1AH_M00H_ROOT 0x153a
#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507
#define PCI_DEVICE_ID_AMD_MI200_ROOT 0x14bb
+#define PCI_DEVICE_ID_AMD_MI300_ROOT 0x14f8
#define PCI_DEVICE_ID_AMD_17H_DF_F4 0x1464
#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F4 0x15ec
@@ -43,6 +44,7 @@
#define PCI_DEVICE_ID_AMD_19H_M78H_DF_F4 0x12fc
#define PCI_DEVICE_ID_AMD_1AH_M00H_DF_F4 0x12c4
#define PCI_DEVICE_ID_AMD_MI200_DF_F4 0x14d4
+#define PCI_DEVICE_ID_AMD_MI300_DF_F4 0x152c
/* Protect the PCI config register pairs used for SMN. */
static DEFINE_MUTEX(smn_mutex);
@@ -62,6 +64,7 @@ static const struct pci_device_id amd_root_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M00H_ROOT) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_ROOT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI300_ROOT) },
{}
};
@@ -93,6 +96,7 @@ static const struct pci_device_id amd_nb_misc_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M00H_DF_F3) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_DF_F3) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_DF_F3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI300_DF_F3) },
{}
};
@@ -112,9 +116,13 @@ static const struct pci_device_id amd_nb_link_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M10H_DF_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M40H_DF_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M60H_DF_F4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M70H_DF_F4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M78H_DF_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M00H_DF_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_DF_F4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI300_DF_F4) },
{}
};
@@ -386,7 +394,7 @@ int amd_get_subcaches(int cpu)
pci_read_config_dword(link, 0x1d4, &mask);
- return (mask >> (4 * cpu_data(cpu).cpu_core_id)) & 0xf;
+ return (mask >> (4 * cpu_data(cpu).topo.core_id)) & 0xf;
}
int amd_set_subcaches(int cpu, unsigned long mask)
@@ -412,7 +420,7 @@ int amd_set_subcaches(int cpu, unsigned long mask)
pci_write_config_dword(nb->misc, 0x1b8, reg & ~0x180000);
}
- cuid = cpu_data(cpu).cpu_core_id;
+ cuid = cpu_data(cpu).topo.core_id;
mask <<= 4 * cuid;
mask |= (0xf ^ (1 << cuid)) << 26;
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 760adac3d1a8..41093cf20acd 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -36,6 +36,8 @@
#include <linux/smp.h>
#include <linux/mm.h>
+#include <xen/xen.h>
+
#include <asm/trace/irq_vectors.h>
#include <asm/irq_remapping.h>
#include <asm/pc-conf-reg.h>
@@ -70,7 +72,7 @@ unsigned int num_processors;
unsigned disabled_cpus;
/* Processor that is doing the boot up */
-unsigned int boot_cpu_physical_apicid __ro_after_init = -1U;
+u32 boot_cpu_physical_apicid __ro_after_init = BAD_APICID;
EXPORT_SYMBOL_GPL(boot_cpu_physical_apicid);
u8 boot_cpu_apic_version __ro_after_init;
@@ -85,7 +87,7 @@ physid_mask_t phys_cpu_present_map;
* disable_cpu_apicid=<int>, mostly used for the kdump 2nd kernel to
* avoid undefined behaviour caused by sending INIT from AP to BSP.
*/
-static unsigned int disabled_cpu_apicid __ro_after_init = BAD_APICID;
+static u32 disabled_cpu_apicid __ro_after_init = BAD_APICID;
/*
* This variable controls which CPUs receive external NMIs. By default,
@@ -109,7 +111,7 @@ static inline bool apic_accessible(void)
/*
* Map cpu index to physical APIC ID
*/
-DEFINE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid, BAD_APICID);
+DEFINE_EARLY_PER_CPU_READ_MOSTLY(u32, x86_cpu_to_apicid, BAD_APICID);
DEFINE_EARLY_PER_CPU_READ_MOSTLY(u32, x86_cpu_to_acpiid, U32_MAX);
EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid);
EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_acpiid);
@@ -1763,7 +1765,7 @@ static void __x2apic_enable(void)
static int __init setup_nox2apic(char *str)
{
if (x2apic_enabled()) {
- int apicid = native_apic_msr_read(APIC_ID);
+ u32 apicid = native_apic_msr_read(APIC_ID);
if (apicid >= 255) {
pr_warn("Apicid: %08x, cannot enforce nox2apic\n",
@@ -2316,13 +2318,11 @@ static int nr_logical_cpuids = 1;
/*
* Used to store mapping between logical CPU IDs and APIC IDs.
*/
-int cpuid_to_apicid[] = {
- [0 ... NR_CPUS - 1] = -1,
-};
+u32 cpuid_to_apicid[] = { [0 ... NR_CPUS - 1] = BAD_APICID, };
bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
{
- return phys_id == cpuid_to_apicid[cpu];
+ return phys_id == (u64)cpuid_to_apicid[cpu];
}
#ifdef CONFIG_SMP
@@ -2344,6 +2344,15 @@ static int __init smp_init_primary_thread_mask(void)
{
unsigned int cpu;
+ /*
+ * XEN/PV provides either none or useless topology information.
+ * Pretend that all vCPUs are primary threads.
+ */
+ if (xen_pv_domain()) {
+ cpumask_copy(&__cpu_primary_thread_mask, cpu_possible_mask);
+ return 0;
+ }
+
for (cpu = 0; cpu < nr_logical_cpuids; cpu++)
cpu_mark_primary_thread(cpu, cpuid_to_apicid[cpu]);
return 0;
@@ -2382,7 +2391,7 @@ static int allocate_logical_cpuid(int apicid)
return nr_logical_cpuids++;
}
-static void cpu_update_apic(int cpu, int apicid)
+static void cpu_update_apic(int cpu, u32 apicid)
{
#if defined(CONFIG_SMP) || defined(CONFIG_X86_64)
early_per_cpu(x86_cpu_to_apicid, cpu) = apicid;
@@ -2535,7 +2544,7 @@ static struct {
*/
int active;
/* r/w apic fields */
- unsigned int apic_id;
+ u32 apic_id;
unsigned int apic_taskpri;
unsigned int apic_ldr;
unsigned int apic_dfr;
diff --git a/arch/x86/kernel/apic/apic_common.c b/arch/x86/kernel/apic/apic_common.c
index 7bc5d9bf59cd..8a00141073ea 100644
--- a/arch/x86/kernel/apic/apic_common.c
+++ b/arch/x86/kernel/apic/apic_common.c
@@ -18,7 +18,7 @@ u32 apic_flat_calc_apicid(unsigned int cpu)
return 1U << cpu;
}
-bool default_check_apicid_used(physid_mask_t *map, int apicid)
+bool default_check_apicid_used(physid_mask_t *map, u32 apicid)
{
return physid_isset(apicid, *map);
}
@@ -28,7 +28,7 @@ void default_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
*retmap = *phys_map;
}
-int default_cpu_present_to_apicid(int mps_cpu)
+u32 default_cpu_present_to_apicid(int mps_cpu)
{
if (mps_cpu < nr_cpu_ids && cpu_present(mps_cpu))
return (int)per_cpu(x86_cpu_to_apicid, mps_cpu);
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c
index 032a84e2c3cc..7139867d69cd 100644
--- a/arch/x86/kernel/apic/apic_flat_64.c
+++ b/arch/x86/kernel/apic/apic_flat_64.c
@@ -56,17 +56,17 @@ flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
_flat_send_IPI_mask(mask, vector);
}
-static unsigned int flat_get_apic_id(unsigned long x)
+static u32 flat_get_apic_id(u32 x)
{
return (x >> 24) & 0xFF;
}
-static u32 set_apic_id(unsigned int id)
+static u32 set_apic_id(u32 id)
{
return (id & 0xFF) << 24;
}
-static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
+static u32 flat_phys_pkg_id(u32 initial_apic_id, int index_msb)
{
return initial_apic_id >> index_msb;
}
@@ -103,6 +103,7 @@ static struct apic apic_flat __ro_after_init = {
.send_IPI_allbutself = default_send_IPI_allbutself,
.send_IPI_all = default_send_IPI_all,
.send_IPI_self = default_send_IPI_self,
+ .nmi_to_offline_cpu = true,
.read = native_apic_mem_read,
.write = native_apic_mem_write,
@@ -158,8 +159,6 @@ static struct apic apic_physflat __ro_after_init = {
.disable_esr = 0,
- .check_apicid_used = NULL,
- .ioapic_phys_id_map = NULL,
.cpu_present_to_apicid = default_cpu_present_to_apicid,
.phys_pkg_id = flat_phys_pkg_id,
@@ -175,6 +174,7 @@ static struct apic apic_physflat __ro_after_init = {
.send_IPI_allbutself = default_send_IPI_allbutself,
.send_IPI_all = default_send_IPI_all,
.send_IPI_self = default_send_IPI_self,
+ .nmi_to_offline_cpu = true,
.read = native_apic_mem_read,
.write = native_apic_mem_write,
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c
index 966d7cf10b95..b00d52ae84fa 100644
--- a/arch/x86/kernel/apic/apic_noop.c
+++ b/arch/x86/kernel/apic/apic_noop.c
@@ -18,6 +18,8 @@
#include <asm/apic.h>
+#include "local.h"
+
static void noop_send_IPI(int cpu, int vector) { }
static void noop_send_IPI_mask(const struct cpumask *cpumask, int vector) { }
static void noop_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) { }
@@ -25,10 +27,10 @@ static void noop_send_IPI_allbutself(int vector) { }
static void noop_send_IPI_all(int vector) { }
static void noop_send_IPI_self(int vector) { }
static void noop_apic_icr_write(u32 low, u32 id) { }
-static int noop_wakeup_secondary_cpu(int apicid, unsigned long start_eip) { return -1; }
+static int noop_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip) { return -1; }
static u64 noop_apic_icr_read(void) { return 0; }
-static int noop_phys_pkg_id(int cpuid_apic, int index_msb) { return 0; }
-static unsigned int noop_get_apic_id(unsigned long x) { return 0; }
+static u32 noop_phys_pkg_id(u32 cpuid_apic, int index_msb) { return 0; }
+static u32 noop_get_apic_id(u32 apicid) { return 0; }
static void noop_apic_eoi(void) { }
static u32 noop_apic_read(u32 reg)
diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c
index 63f3d7be9dc7..456a14c44f67 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -25,7 +25,7 @@ static const struct apic apic_numachip1;
static const struct apic apic_numachip2;
static void (*numachip_apic_icr_write)(int apicid, unsigned int val) __read_mostly;
-static unsigned int numachip1_get_apic_id(unsigned long x)
+static u32 numachip1_get_apic_id(u32 x)
{
unsigned long value;
unsigned int id = (x >> 24) & 0xff;
@@ -38,12 +38,12 @@ static unsigned int numachip1_get_apic_id(unsigned long x)
return id;
}
-static u32 numachip1_set_apic_id(unsigned int id)
+static u32 numachip1_set_apic_id(u32 id)
{
return (id & 0xff) << 24;
}
-static unsigned int numachip2_get_apic_id(unsigned long x)
+static u32 numachip2_get_apic_id(u32 x)
{
u64 mcfg;
@@ -51,12 +51,12 @@ static unsigned int numachip2_get_apic_id(unsigned long x)
return ((mcfg >> (28 - 8)) & 0xfff00) | (x >> 24);
}
-static u32 numachip2_set_apic_id(unsigned int id)
+static u32 numachip2_set_apic_id(u32 id)
{
return id << 24;
}
-static int numachip_phys_pkg_id(int initial_apic_id, int index_msb)
+static u32 numachip_phys_pkg_id(u32 initial_apic_id, int index_msb)
{
return initial_apic_id >> index_msb;
}
@@ -71,7 +71,7 @@ static void numachip2_apic_icr_write(int apicid, unsigned int val)
numachip2_write32_lcsr(NUMACHIP2_APIC_ICR, (apicid << 12) | val);
}
-static int numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip)
+static int numachip_wakeup_secondary(u32 phys_apicid, unsigned long start_rip)
{
numachip_apic_icr_write(phys_apicid, APIC_DM_INIT);
numachip_apic_icr_write(phys_apicid, APIC_DM_STARTUP |
@@ -161,7 +161,7 @@ static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)
u64 val;
u32 nodes = 1;
- this_cpu_write(cpu_llc_id, node);
+ c->topo.llc_id = node;
/* Account for nodes per socket in multi-core-module processors */
if (boot_cpu_has(X86_FEATURE_NODEID_MSR)) {
@@ -169,7 +169,7 @@ static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)
nodes = ((val >> 3) & 7) + 1;
}
- c->phys_proc_id = node / nodes;
+ c->topo.pkg_id = node / nodes;
}
static int __init numachip_system_init(void)
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c
index 0e5535add4b5..7ee3c486cb33 100644
--- a/arch/x86/kernel/apic/bigsmp_32.c
+++ b/arch/x86/kernel/apic/bigsmp_32.c
@@ -13,12 +13,12 @@
#include "local.h"
-static unsigned bigsmp_get_apic_id(unsigned long x)
+static u32 bigsmp_get_apic_id(u32 x)
{
return (x >> 24) & 0xFF;
}
-static bool bigsmp_check_apicid_used(physid_mask_t *map, int apicid)
+static bool bigsmp_check_apicid_used(physid_mask_t *map, u32 apicid)
{
return false;
}
@@ -29,7 +29,7 @@ static void bigsmp_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *re
physids_promote(0xFFL, retmap);
}
-static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb)
+static u32 bigsmp_phys_pkg_id(u32 cpuid_apic, int index_msb)
{
return cpuid_apic >> index_msb;
}
diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c
index a44ba7209ef3..5da693d633b7 100644
--- a/arch/x86/kernel/apic/ipi.c
+++ b/arch/x86/kernel/apic/ipi.c
@@ -97,6 +97,14 @@ sendmask:
__apic_send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
}
+void apic_send_nmi_to_offline_cpu(unsigned int cpu)
+{
+ if (WARN_ON_ONCE(!apic->nmi_to_offline_cpu))
+ return;
+ if (WARN_ON_ONCE(!cpumask_test_cpu(cpu, &cpus_booted_once_mask)))
+ return;
+ apic->send_IPI(cpu, NMI_VECTOR);
+}
#endif /* CONFIG_SMP */
static inline int __prepare_ICR2(unsigned int mask)
@@ -281,7 +289,7 @@ void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector)
}
#ifdef CONFIG_SMP
-static int convert_apicid_to_cpu(int apic_id)
+static int convert_apicid_to_cpu(u32 apic_id)
{
int i;
@@ -294,7 +302,8 @@ static int convert_apicid_to_cpu(int apic_id)
int safe_smp_processor_id(void)
{
- int apicid, cpuid;
+ u32 apicid;
+ int cpuid;
if (!boot_cpu_has(X86_FEATURE_APIC))
return 0;
diff --git a/arch/x86/kernel/apic/local.h b/arch/x86/kernel/apic/local.h
index ec219c659c7d..9ea6186ea88c 100644
--- a/arch/x86/kernel/apic/local.h
+++ b/arch/x86/kernel/apic/local.h
@@ -15,9 +15,9 @@
/* X2APIC */
void __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest);
-unsigned int x2apic_get_apic_id(unsigned long id);
-u32 x2apic_set_apic_id(unsigned int id);
-int x2apic_phys_pkg_id(int initial_apicid, int index_msb);
+u32 x2apic_get_apic_id(u32 id);
+u32 x2apic_set_apic_id(u32 id);
+u32 x2apic_phys_pkg_id(u32 initial_apicid, int index_msb);
void x2apic_send_IPI_all(int vector);
void x2apic_send_IPI_allbutself(int vector);
@@ -64,6 +64,7 @@ void default_send_IPI_all(int vector);
void default_send_IPI_self(int vector);
bool default_apic_id_registered(void);
+bool default_check_apicid_used(physid_mask_t *map, u32 apicid);
#ifdef CONFIG_X86_32
void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, int vector);
diff --git a/arch/x86/kernel/apic/msi.c b/arch/x86/kernel/apic/msi.c
index 6b6b711678fe..d9651f15ae4f 100644
--- a/arch/x86/kernel/apic/msi.c
+++ b/arch/x86/kernel/apic/msi.c
@@ -55,14 +55,14 @@ msi_set_affinity(struct irq_data *irqd, const struct cpumask *mask, bool force)
* caused by the non-atomic update of the address/data pair.
*
* Direct update is possible when:
- * - The MSI is maskable (remapped MSI does not use this code path)).
- * The quirk bit is not set in this case.
+ * - The MSI is maskable (remapped MSI does not use this code path).
+ * The reservation mode bit is set in this case.
* - The new vector is the same as the old vector
* - The old vector is MANAGED_IRQ_SHUTDOWN_VECTOR (interrupt starts up)
* - The interrupt is not yet started up
* - The new destination CPU is the same as the old destination CPU
*/
- if (!irqd_msi_nomask_quirk(irqd) ||
+ if (!irqd_can_reserve(irqd) ||
cfg->vector == old_cfg.vector ||
old_cfg.vector == MANAGED_IRQ_SHUTDOWN_VECTOR ||
!irqd_is_started(irqd) ||
@@ -215,8 +215,6 @@ static bool x86_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
if (WARN_ON_ONCE(domain != real_parent))
return false;
info->chip->irq_set_affinity = msi_set_affinity;
- /* See msi_set_affinity() for the gory details */
- info->flags |= MSI_FLAG_NOMASK_QUIRK;
break;
case DOMAIN_BUS_DMAR:
case DOMAIN_BUS_AMDVI:
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index 9a06df6cdd68..5eb3fbe472da 100644
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -18,11 +18,21 @@
#include "local.h"
-static int default_phys_pkg_id(int cpuid_apic, int index_msb)
+static u32 default_phys_pkg_id(u32 cpuid_apic, int index_msb)
{
return cpuid_apic >> index_msb;
}
+static u32 default_get_apic_id(u32 x)
+{
+ unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
+
+ if (APIC_XAPIC(ver) || boot_cpu_has(X86_FEATURE_EXTD_APICID))
+ return (x >> 24) & 0xFF;
+ else
+ return (x >> 24) & 0x0F;
+}
+
/* should be called last. */
static int probe_default(void)
{
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c
index affbff65e497..a8306089c91b 100644
--- a/arch/x86/kernel/apic/x2apic_cluster.c
+++ b/arch/x86/kernel/apic/x2apic_cluster.c
@@ -251,6 +251,7 @@ static struct apic apic_x2apic_cluster __ro_after_init = {
.send_IPI_allbutself = x2apic_send_IPI_allbutself,
.send_IPI_all = x2apic_send_IPI_all,
.send_IPI_self = x2apic_send_IPI_self,
+ .nmi_to_offline_cpu = true,
.read = native_apic_msr_read,
.write = native_apic_msr_write,
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 788cdb4ee394..558a4a8824f4 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -124,17 +124,17 @@ static int x2apic_phys_probe(void)
return apic == &apic_x2apic_phys;
}
-unsigned int x2apic_get_apic_id(unsigned long id)
+u32 x2apic_get_apic_id(u32 id)
{
return id;
}
-u32 x2apic_set_apic_id(unsigned int id)
+u32 x2apic_set_apic_id(u32 id)
{
return id;
}
-int x2apic_phys_pkg_id(int initial_apicid, int index_msb)
+u32 x2apic_phys_pkg_id(u32 initial_apicid, int index_msb)
{
return initial_apicid >> index_msb;
}
@@ -166,6 +166,7 @@ static struct apic apic_x2apic_phys __ro_after_init = {
.send_IPI_allbutself = x2apic_send_IPI_allbutself,
.send_IPI_all = x2apic_send_IPI_all,
.send_IPI_self = x2apic_send_IPI_self,
+ .nmi_to_offline_cpu = true,
.read = native_apic_msr_read,
.write = native_apic_msr_write,
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 205cee567629..1b0d7336a28f 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -110,7 +110,7 @@ static void __init early_get_pnodeid(void)
} else if (UVH_RH_GAM_ADDR_MAP_CONFIG) {
union uvh_rh_gam_addr_map_config_u m_n_config;
- m_n_config.v = uv_early_read_mmr(UVH_RH_GAM_ADDR_MAP_CONFIG);
+ m_n_config.v = uv_early_read_mmr(UVH_RH_GAM_ADDR_MAP_CONFIG);
uv_cpuid.n_skt = m_n_config.s.n_skt;
if (is_uv(UV3))
uv_cpuid.m_skt = m_n_config.s3.m_skt;
@@ -701,7 +701,7 @@ static __init void build_uv_gr_table(void)
}
}
-static int uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
+static int uv_wakeup_secondary(u32 phys_apicid, unsigned long start_rip)
{
unsigned long val;
int pnode;
@@ -779,7 +779,7 @@ static void uv_send_IPI_all(int vector)
uv_send_IPI_mask(cpu_online_mask, vector);
}
-static u32 set_apic_id(unsigned int id)
+static u32 set_apic_id(u32 id)
{
return id;
}
@@ -789,7 +789,7 @@ static unsigned int uv_read_apic_id(void)
return x2apic_get_apic_id(apic_read(APIC_ID));
}
-static int uv_phys_pkg_id(int initial_apicid, int index_msb)
+static u32 uv_phys_pkg_id(u32 initial_apicid, int index_msb)
{
return uv_read_apic_id() >> index_msb;
}
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index dc3576303f1a..6913b372ccf7 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -68,26 +68,19 @@ static void __used common(void)
#endif
BLANK();
- OFFSET(TDX_MODULE_rcx, tdx_module_output, rcx);
- OFFSET(TDX_MODULE_rdx, tdx_module_output, rdx);
- OFFSET(TDX_MODULE_r8, tdx_module_output, r8);
- OFFSET(TDX_MODULE_r9, tdx_module_output, r9);
- OFFSET(TDX_MODULE_r10, tdx_module_output, r10);
- OFFSET(TDX_MODULE_r11, tdx_module_output, r11);
-
- BLANK();
- OFFSET(TDX_HYPERCALL_r8, tdx_hypercall_args, r8);
- OFFSET(TDX_HYPERCALL_r9, tdx_hypercall_args, r9);
- OFFSET(TDX_HYPERCALL_r10, tdx_hypercall_args, r10);
- OFFSET(TDX_HYPERCALL_r11, tdx_hypercall_args, r11);
- OFFSET(TDX_HYPERCALL_r12, tdx_hypercall_args, r12);
- OFFSET(TDX_HYPERCALL_r13, tdx_hypercall_args, r13);
- OFFSET(TDX_HYPERCALL_r14, tdx_hypercall_args, r14);
- OFFSET(TDX_HYPERCALL_r15, tdx_hypercall_args, r15);
- OFFSET(TDX_HYPERCALL_rdi, tdx_hypercall_args, rdi);
- OFFSET(TDX_HYPERCALL_rsi, tdx_hypercall_args, rsi);
- OFFSET(TDX_HYPERCALL_rbx, tdx_hypercall_args, rbx);
- OFFSET(TDX_HYPERCALL_rdx, tdx_hypercall_args, rdx);
+ OFFSET(TDX_MODULE_rcx, tdx_module_args, rcx);
+ OFFSET(TDX_MODULE_rdx, tdx_module_args, rdx);
+ OFFSET(TDX_MODULE_r8, tdx_module_args, r8);
+ OFFSET(TDX_MODULE_r9, tdx_module_args, r9);
+ OFFSET(TDX_MODULE_r10, tdx_module_args, r10);
+ OFFSET(TDX_MODULE_r11, tdx_module_args, r11);
+ OFFSET(TDX_MODULE_r12, tdx_module_args, r12);
+ OFFSET(TDX_MODULE_r13, tdx_module_args, r13);
+ OFFSET(TDX_MODULE_r14, tdx_module_args, r14);
+ OFFSET(TDX_MODULE_r15, tdx_module_args, r15);
+ OFFSET(TDX_MODULE_rbx, tdx_module_args, rbx);
+ OFFSET(TDX_MODULE_rdi, tdx_module_args, rdi);
+ OFFSET(TDX_MODULE_rsi, tdx_module_args, rsi);
BLANK();
OFFSET(BP_scratch, boot_params, scratch);
diff --git a/arch/x86/kernel/callthunks.c b/arch/x86/kernel/callthunks.c
index faa9f2299848..e9ad518a5003 100644
--- a/arch/x86/kernel/callthunks.c
+++ b/arch/x86/kernel/callthunks.c
@@ -48,11 +48,6 @@ EXPORT_SYMBOL_GPL(__x86_call_count);
extern s32 __call_sites[], __call_sites_end[];
-struct thunk_desc {
- void *template;
- unsigned int template_size;
-};
-
struct core_text {
unsigned long base;
unsigned long end;
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 4350f6bfc064..93eabf544031 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -54,6 +54,8 @@ obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o
obj-$(CONFIG_HYPERVISOR_GUEST) += vmware.o hypervisor.o mshyperv.o
obj-$(CONFIG_ACRN_GUEST) += acrn.o
+obj-$(CONFIG_DEBUG_FS) += debugfs.o
+
quiet_cmd_mkcapflags = MKCAP $@
cmd_mkcapflags = $(CONFIG_SHELL) $(srctree)/$(src)/mkcapflags.sh $@ $^
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 03ef962a6992..f322ebd053a9 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -80,6 +80,10 @@ static const int amd_div0[] =
AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x00, 0x0, 0x2f, 0xf),
AMD_MODEL_RANGE(0x17, 0x50, 0x0, 0x5f, 0xf));
+static const int amd_erratum_1485[] =
+ AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x19, 0x10, 0x0, 0x1f, 0xf),
+ AMD_MODEL_RANGE(0x19, 0x60, 0x0, 0xaf, 0xf));
+
static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
{
int osvw_id = *erratum++;
@@ -378,7 +382,7 @@ static int nearby_node(int apicid)
#endif
/*
- * Fix up cpu_core_id for pre-F17h systems to be in the
+ * Fix up topo::core_id for pre-F17h systems to be in the
* [0 .. cores_per_node - 1] range. Not really needed but
* kept so as not to break existing setups.
*/
@@ -390,7 +394,7 @@ static void legacy_fixup_core_id(struct cpuinfo_x86 *c)
return;
cus_per_node = c->x86_max_cores / nodes_per_socket;
- c->cpu_core_id %= cus_per_node;
+ c->topo.core_id %= cus_per_node;
}
/*
@@ -401,8 +405,6 @@ static void legacy_fixup_core_id(struct cpuinfo_x86 *c)
*/
static void amd_get_topology(struct cpuinfo_x86 *c)
{
- int cpu = smp_processor_id();
-
/* get information required for multi-node processors */
if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
int err;
@@ -410,13 +412,13 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
- c->cpu_die_id = ecx & 0xff;
+ c->topo.die_id = ecx & 0xff;
if (c->x86 == 0x15)
- c->cu_id = ebx & 0xff;
+ c->topo.cu_id = ebx & 0xff;
if (c->x86 >= 0x17) {
- c->cpu_core_id = ebx & 0xff;
+ c->topo.core_id = ebx & 0xff;
if (smp_num_siblings > 1)
c->x86_max_cores /= smp_num_siblings;
@@ -430,15 +432,14 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
if (!err)
c->x86_coreid_bits = get_count_order(c->x86_max_cores);
- cacheinfo_amd_init_llc_id(c, cpu);
+ cacheinfo_amd_init_llc_id(c);
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
u64 value;
rdmsrl(MSR_FAM10H_NODE_ID, value);
- c->cpu_die_id = value & 7;
-
- per_cpu(cpu_llc_id, cpu) = c->cpu_die_id;
+ c->topo.die_id = value & 7;
+ c->topo.llc_id = c->topo.die_id;
} else
return;
@@ -455,15 +456,14 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
static void amd_detect_cmp(struct cpuinfo_x86 *c)
{
unsigned bits;
- int cpu = smp_processor_id();
bits = c->x86_coreid_bits;
/* Low order bits define the core id (index of core in socket) */
- c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
+ c->topo.core_id = c->topo.initial_apicid & ((1 << bits)-1);
/* Convert the initial APIC ID into the socket ID */
- c->phys_proc_id = c->initial_apicid >> bits;
+ c->topo.pkg_id = c->topo.initial_apicid >> bits;
/* use socket ID also for last level cache */
- per_cpu(cpu_llc_id, cpu) = c->cpu_die_id = c->phys_proc_id;
+ c->topo.llc_id = c->topo.die_id = c->topo.pkg_id;
}
u32 amd_get_nodes_per_socket(void)
@@ -477,11 +477,11 @@ static void srat_detect_node(struct cpuinfo_x86 *c)
#ifdef CONFIG_NUMA
int cpu = smp_processor_id();
int node;
- unsigned apicid = c->apicid;
+ unsigned apicid = c->topo.apicid;
node = numa_cpu_node(cpu);
if (node == NUMA_NO_NODE)
- node = get_llc_id(cpu);
+ node = per_cpu_llc_id(cpu);
/*
* On multi-fabric platform (e.g. Numascale NumaChip) a
@@ -511,7 +511,7 @@ static void srat_detect_node(struct cpuinfo_x86 *c)
* through CPU mapping may alter the outcome, directly
* access __apicid_to_node[].
*/
- int ht_nodeid = c->initial_apicid;
+ int ht_nodeid = c->topo.initial_apicid;
if (__apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
node = __apicid_to_node[ht_nodeid];
@@ -1010,7 +1010,6 @@ static bool cpu_has_zenbleed_microcode(void)
default:
return false;
- break;
}
if (boot_cpu_data.microcode < good_rev)
@@ -1040,6 +1039,8 @@ static void zenbleed_check(struct cpuinfo_x86 *c)
static void init_amd(struct cpuinfo_x86 *c)
{
+ u64 vm_cr;
+
early_init_amd(c);
/*
@@ -1056,7 +1057,7 @@ static void init_amd(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_FSRS);
/* get apicid instead of initial apic id from cpuid */
- c->apicid = read_apic_id();
+ c->topo.apicid = read_apic_id();
/* K6s reports MCEs but don't actually have all the MSRs */
if (c->x86 < 6)
@@ -1091,6 +1092,14 @@ static void init_amd(struct cpuinfo_x86 *c)
init_amd_cacheinfo(c);
+ if (cpu_has(c, X86_FEATURE_SVM)) {
+ rdmsrl(MSR_VM_CR, vm_cr);
+ if (vm_cr & SVM_VM_CR_SVM_DIS_MASK) {
+ pr_notice_once("SVM disabled (by BIOS) in MSR_VM_CR\n");
+ clear_cpu_cap(c, X86_FEATURE_SVM);
+ }
+ }
+
if (!cpu_has(c, X86_FEATURE_LFENCE_RDTSC) && cpu_has(c, X86_FEATURE_XMM2)) {
/*
* Use LFENCE for execution serialization. On families which
@@ -1149,6 +1158,10 @@ static void init_amd(struct cpuinfo_x86 *c)
pr_notice_once("AMD Zen1 DIV0 bug detected. Disable SMT for full protection.\n");
setup_force_cpu_bug(X86_BUG_DIV0);
}
+
+ if (!cpu_has(c, X86_FEATURE_HYPERVISOR) &&
+ cpu_has_amd_erratum(c, amd_erratum_1485))
+ msr_set_bit(MSR_ZEN4_BP_CFG, MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT);
}
#ifdef CONFIG_X86_32
@@ -1307,6 +1320,9 @@ static void zenbleed_check_cpu(void *unused)
void amd_check_microcode(void)
{
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+ return;
+
on_each_cpu(zenbleed_check_cpu, NULL, 1);
}
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 10499bcd4e39..bb0ab8466b91 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -63,7 +63,7 @@ EXPORT_SYMBOL_GPL(x86_pred_cmd);
static DEFINE_MUTEX(spec_ctrl_mutex);
-void (*x86_return_thunk)(void) __ro_after_init = &__x86_return_thunk;
+void (*x86_return_thunk)(void) __ro_after_init = __x86_return_thunk;
/* Update SPEC_CTRL MSR and its cached copy unconditionally */
static void update_spec_ctrl(u64 val)
@@ -717,7 +717,7 @@ void update_gds_msr(void)
case GDS_MITIGATION_UCODE_NEEDED:
case GDS_MITIGATION_HYPERVISOR:
return;
- };
+ }
wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
@@ -1019,7 +1019,6 @@ static void __init retbleed_select_mitigation(void)
do_cmd_auto:
case RETBLEED_CMD_AUTO:
- default:
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
if (IS_ENABLED(CONFIG_CPU_UNRET_ENTRY))
@@ -1042,8 +1041,7 @@ do_cmd_auto:
setup_force_cpu_cap(X86_FEATURE_RETHUNK);
setup_force_cpu_cap(X86_FEATURE_UNRET);
- if (IS_ENABLED(CONFIG_RETHUNK))
- x86_return_thunk = retbleed_return_thunk;
+ x86_return_thunk = retbleed_return_thunk;
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
@@ -1061,7 +1059,8 @@ do_cmd_auto:
case RETBLEED_MITIGATION_STUFF:
setup_force_cpu_cap(X86_FEATURE_RETHUNK);
setup_force_cpu_cap(X86_FEATURE_CALL_DEPTH);
- x86_set_skl_return_thunk();
+
+ x86_return_thunk = call_depth_return_thunk;
break;
default:
@@ -1290,6 +1289,8 @@ spectre_v2_user_select_mitigation(void)
spectre_v2_user_ibpb = mode;
switch (cmd) {
+ case SPECTRE_V2_USER_CMD_NONE:
+ break;
case SPECTRE_V2_USER_CMD_FORCE:
case SPECTRE_V2_USER_CMD_PRCTL_IBPB:
case SPECTRE_V2_USER_CMD_SECCOMP_IBPB:
@@ -1301,8 +1302,6 @@ spectre_v2_user_select_mitigation(void)
case SPECTRE_V2_USER_CMD_SECCOMP:
static_branch_enable(&switch_mm_cond_ibpb);
break;
- default:
- break;
}
pr_info("mitigation: Enabling %s Indirect Branch Prediction Barrier\n",
@@ -2160,6 +2159,10 @@ static int l1d_flush_prctl_get(struct task_struct *task)
static int ssb_prctl_get(struct task_struct *task)
{
switch (ssb_mode) {
+ case SPEC_STORE_BYPASS_NONE:
+ if (boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS))
+ return PR_SPEC_ENABLE;
+ return PR_SPEC_NOT_AFFECTED;
case SPEC_STORE_BYPASS_DISABLE:
return PR_SPEC_DISABLE;
case SPEC_STORE_BYPASS_SECCOMP:
@@ -2171,11 +2174,8 @@ static int ssb_prctl_get(struct task_struct *task)
if (task_spec_ssb_disable(task))
return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
- default:
- if (boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS))
- return PR_SPEC_ENABLE;
- return PR_SPEC_NOT_AFFECTED;
}
+ BUG();
}
static int ib_prctl_get(struct task_struct *task)
@@ -2353,6 +2353,8 @@ early_param("l1tf", l1tf_cmdline);
enum srso_mitigation {
SRSO_MITIGATION_NONE,
+ SRSO_MITIGATION_UCODE_NEEDED,
+ SRSO_MITIGATION_SAFE_RET_UCODE_NEEDED,
SRSO_MITIGATION_MICROCODE,
SRSO_MITIGATION_SAFE_RET,
SRSO_MITIGATION_IBPB,
@@ -2368,11 +2370,13 @@ enum srso_mitigation_cmd {
};
static const char * const srso_strings[] = {
- [SRSO_MITIGATION_NONE] = "Vulnerable",
- [SRSO_MITIGATION_MICROCODE] = "Mitigation: microcode",
- [SRSO_MITIGATION_SAFE_RET] = "Mitigation: safe RET",
- [SRSO_MITIGATION_IBPB] = "Mitigation: IBPB",
- [SRSO_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT only"
+ [SRSO_MITIGATION_NONE] = "Vulnerable",
+ [SRSO_MITIGATION_UCODE_NEEDED] = "Vulnerable: No microcode",
+ [SRSO_MITIGATION_SAFE_RET_UCODE_NEEDED] = "Vulnerable: Safe RET, no microcode",
+ [SRSO_MITIGATION_MICROCODE] = "Vulnerable: Microcode, no safe RET",
+ [SRSO_MITIGATION_SAFE_RET] = "Mitigation: Safe RET",
+ [SRSO_MITIGATION_IBPB] = "Mitigation: IBPB",
+ [SRSO_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT only"
};
static enum srso_mitigation srso_mitigation __ro_after_init = SRSO_MITIGATION_NONE;
@@ -2406,34 +2410,44 @@ static void __init srso_select_mitigation(void)
{
bool has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE);
- if (!boot_cpu_has_bug(X86_BUG_SRSO) || cpu_mitigations_off())
- goto pred_cmd;
+ if (cpu_mitigations_off())
+ return;
- if (!has_microcode) {
- pr_warn("IBPB-extending microcode not applied!\n");
- pr_warn(SRSO_NOTICE);
- } else {
+ if (!boot_cpu_has_bug(X86_BUG_SRSO)) {
+ if (boot_cpu_has(X86_FEATURE_SBPB))
+ x86_pred_cmd = PRED_CMD_SBPB;
+ return;
+ }
+
+ if (has_microcode) {
/*
* Zen1/2 with SMT off aren't vulnerable after the right
* IBPB microcode has been applied.
+ *
+ * Zen1/2 don't have SBPB, no need to try to enable it here.
*/
if (boot_cpu_data.x86 < 0x19 && !cpu_smt_possible()) {
setup_force_cpu_cap(X86_FEATURE_SRSO_NO);
return;
}
- }
- if (retbleed_mitigation == RETBLEED_MITIGATION_IBPB) {
- if (has_microcode) {
- pr_err("Retbleed IBPB mitigation enabled, using same for SRSO\n");
+ if (retbleed_mitigation == RETBLEED_MITIGATION_IBPB) {
srso_mitigation = SRSO_MITIGATION_IBPB;
- goto pred_cmd;
+ goto out;
}
+ } else {
+ pr_warn("IBPB-extending microcode not applied!\n");
+ pr_warn(SRSO_NOTICE);
+
+ /* may be overwritten by SRSO_CMD_SAFE_RET below */
+ srso_mitigation = SRSO_MITIGATION_UCODE_NEEDED;
}
switch (srso_cmd) {
case SRSO_CMD_OFF:
- goto pred_cmd;
+ if (boot_cpu_has(X86_FEATURE_SBPB))
+ x86_pred_cmd = PRED_CMD_SBPB;
+ return;
case SRSO_CMD_MICROCODE:
if (has_microcode) {
@@ -2458,10 +2472,12 @@ static void __init srso_select_mitigation(void)
setup_force_cpu_cap(X86_FEATURE_SRSO);
x86_return_thunk = srso_return_thunk;
}
- srso_mitigation = SRSO_MITIGATION_SAFE_RET;
+ if (has_microcode)
+ srso_mitigation = SRSO_MITIGATION_SAFE_RET;
+ else
+ srso_mitigation = SRSO_MITIGATION_SAFE_RET_UCODE_NEEDED;
} else {
pr_err("WARNING: kernel not compiled with CPU_SRSO.\n");
- goto pred_cmd;
}
break;
@@ -2473,7 +2489,6 @@ static void __init srso_select_mitigation(void)
}
} else {
pr_err("WARNING: kernel not compiled with CPU_IBPB_ENTRY.\n");
- goto pred_cmd;
}
break;
@@ -2485,20 +2500,12 @@ static void __init srso_select_mitigation(void)
}
} else {
pr_err("WARNING: kernel not compiled with CPU_SRSO.\n");
- goto pred_cmd;
}
break;
-
- default:
- break;
}
- pr_info("%s%s\n", srso_strings[srso_mitigation], (has_microcode ? "" : ", no microcode"));
-
-pred_cmd:
- if ((boot_cpu_has(X86_FEATURE_SRSO_NO) || srso_cmd == SRSO_CMD_OFF) &&
- boot_cpu_has(X86_FEATURE_SBPB))
- x86_pred_cmd = PRED_CMD_SBPB;
+out:
+ pr_info("%s\n", srso_strings[srso_mitigation]);
}
#undef pr_fmt
@@ -2704,9 +2711,7 @@ static ssize_t srso_show_state(char *buf)
if (boot_cpu_has(X86_FEATURE_SRSO_NO))
return sysfs_emit(buf, "Mitigation: SMT disabled\n");
- return sysfs_emit(buf, "%s%s\n",
- srso_strings[srso_mitigation],
- boot_cpu_has(X86_FEATURE_IBPB_BRTYPE) ? "" : ", no microcode");
+ return sysfs_emit(buf, "%s\n", srso_strings[srso_mitigation]);
}
static ssize_t gds_show_state(char *buf)
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 8f86eacf69f7..c131c412db89 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -661,7 +661,7 @@ static int find_num_cache_leaves(struct cpuinfo_x86 *c)
return i;
}
-void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu)
+void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c)
{
/*
* We may have multiple LLCs if L3 caches exist, so check if we
@@ -672,13 +672,13 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu)
if (c->x86 < 0x17) {
/* LLC is at the node level. */
- per_cpu(cpu_llc_id, cpu) = c->cpu_die_id;
+ c->topo.llc_id = c->topo.die_id;
} else if (c->x86 == 0x17 && c->x86_model <= 0x1F) {
/*
* LLC is at the core complex level.
* Core complex ID is ApicId[3] for these processors.
*/
- per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
+ c->topo.llc_id = c->topo.apicid >> 3;
} else {
/*
* LLC ID is calculated from the number of threads sharing the
@@ -694,12 +694,12 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu)
if (num_sharing_cache) {
int bits = get_count_order(num_sharing_cache);
- per_cpu(cpu_llc_id, cpu) = c->apicid >> bits;
+ c->topo.llc_id = c->topo.apicid >> bits;
}
}
}
-void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu)
+void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c)
{
/*
* We may have multiple LLCs if L3 caches exist, so check if we
@@ -712,7 +712,7 @@ void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu)
* LLC is at the core complex level.
* Core complex ID is ApicId[3] for these processors.
*/
- per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
+ c->topo.llc_id = c->topo.apicid >> 3;
}
void init_amd_cacheinfo(struct cpuinfo_x86 *c)
@@ -740,9 +740,6 @@ void init_intel_cacheinfo(struct cpuinfo_x86 *c)
unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
-#ifdef CONFIG_SMP
- unsigned int cpu = c->cpu_index;
-#endif
if (c->cpuid_level > 3) {
static int is_initialized;
@@ -776,13 +773,13 @@ void init_intel_cacheinfo(struct cpuinfo_x86 *c)
new_l2 = this_leaf.size/1024;
num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
index_msb = get_count_order(num_threads_sharing);
- l2_id = c->apicid & ~((1 << index_msb) - 1);
+ l2_id = c->topo.apicid & ~((1 << index_msb) - 1);
break;
case 3:
new_l3 = this_leaf.size/1024;
num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
index_msb = get_count_order(num_threads_sharing);
- l3_id = c->apicid & ~((1 << index_msb) - 1);
+ l3_id = c->topo.apicid & ~((1 << index_msb) - 1);
break;
default:
break;
@@ -856,30 +853,24 @@ void init_intel_cacheinfo(struct cpuinfo_x86 *c)
if (new_l2) {
l2 = new_l2;
-#ifdef CONFIG_SMP
- per_cpu(cpu_llc_id, cpu) = l2_id;
- per_cpu(cpu_l2c_id, cpu) = l2_id;
-#endif
+ c->topo.llc_id = l2_id;
+ c->topo.l2c_id = l2_id;
}
if (new_l3) {
l3 = new_l3;
-#ifdef CONFIG_SMP
- per_cpu(cpu_llc_id, cpu) = l3_id;
-#endif
+ c->topo.llc_id = l3_id;
}
-#ifdef CONFIG_SMP
/*
- * If cpu_llc_id is not yet set, this means cpuid_level < 4 which in
+ * If llc_id is not yet set, this means cpuid_level < 4 which in
* turns means that the only possibility is SMT (as indicated in
* cpuid1). Since cpuid2 doesn't specify shared caches, and we know
* that SMT shares all caches, we can unconditionally set cpu_llc_id to
- * c->phys_proc_id.
+ * c->topo.pkg_id.
*/
- if (per_cpu(cpu_llc_id, cpu) == BAD_APICID)
- per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
-#endif
+ if (c->topo.llc_id == BAD_APICID)
+ c->topo.llc_id = c->topo.pkg_id;
c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d));
@@ -915,7 +906,7 @@ static int __cache_amd_cpumap_setup(unsigned int cpu, int index,
unsigned int apicid, nshared, first, last;
nshared = base->eax.split.num_threads_sharing + 1;
- apicid = cpu_data(cpu).apicid;
+ apicid = cpu_data(cpu).topo.apicid;
first = apicid - (apicid % nshared);
last = first + nshared - 1;
@@ -924,14 +915,14 @@ static int __cache_amd_cpumap_setup(unsigned int cpu, int index,
if (!this_cpu_ci->info_list)
continue;
- apicid = cpu_data(i).apicid;
+ apicid = cpu_data(i).topo.apicid;
if ((apicid < first) || (apicid > last))
continue;
this_leaf = this_cpu_ci->info_list + index;
for_each_online_cpu(sibling) {
- apicid = cpu_data(sibling).apicid;
+ apicid = cpu_data(sibling).topo.apicid;
if ((apicid < first) || (apicid > last))
continue;
cpumask_set_cpu(sibling,
@@ -969,7 +960,7 @@ static void __cache_cpumap_setup(unsigned int cpu, int index,
index_msb = get_count_order(num_threads_sharing);
for_each_online_cpu(i)
- if (cpu_data(i).apicid >> index_msb == c->apicid >> index_msb) {
+ if (cpu_data(i).topo.apicid >> index_msb == c->topo.apicid >> index_msb) {
struct cpu_cacheinfo *sib_cpu_ci = get_cpu_cacheinfo(i);
if (i == cpu || !sib_cpu_ci->info_list)
@@ -1024,7 +1015,7 @@ static void get_cache_id(int cpu, struct _cpuid4_info_regs *id4_regs)
num_threads_sharing = 1 + id4_regs->eax.split.num_threads_sharing;
index_msb = get_count_order(num_threads_sharing);
- id4_regs->id = c->apicid >> index_msb;
+ id4_regs->id = c->topo.apicid >> index_msb;
}
int populate_cache_leaves(unsigned int cpu)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 4e5ffc8b0e46..b14fc8c1c953 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -62,6 +62,7 @@
#include <asm/intel-family.h>
#include <asm/cpu_device_id.h>
#include <asm/uv/uv.h>
+#include <asm/ia32.h>
#include <asm/set_memory.h>
#include <asm/traps.h>
#include <asm/sev.h>
@@ -74,18 +75,6 @@ u32 elf_hwcap2 __read_mostly;
int smp_num_siblings = 1;
EXPORT_SYMBOL(smp_num_siblings);
-/* Last level cache ID of each logical CPU */
-DEFINE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id) = BAD_APICID;
-
-u16 get_llc_id(unsigned int cpu)
-{
- return per_cpu(cpu_llc_id, cpu);
-}
-EXPORT_SYMBOL_GPL(get_llc_id);
-
-/* L2 cache ID of each logical CPU */
-DEFINE_PER_CPU_READ_MOSTLY(u16, cpu_l2c_id) = BAD_APICID;
-
static struct ppin_info {
int feature;
int msr_ppin_ctl;
@@ -914,7 +903,7 @@ void detect_ht(struct cpuinfo_x86 *c)
return;
index_msb = get_count_order(smp_num_siblings);
- c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb);
+ c->topo.pkg_id = apic->phys_pkg_id(c->topo.initial_apicid, index_msb);
smp_num_siblings = smp_num_siblings / c->x86_max_cores;
@@ -922,8 +911,8 @@ void detect_ht(struct cpuinfo_x86 *c)
core_bits = get_count_order(c->x86_max_cores);
- c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, index_msb) &
- ((1 << core_bits) - 1);
+ c->topo.core_id = apic->phys_pkg_id(c->topo.initial_apicid, index_msb) &
+ ((1 << core_bits) - 1);
#endif
}
@@ -1114,18 +1103,34 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
void get_cpu_address_sizes(struct cpuinfo_x86 *c)
{
u32 eax, ebx, ecx, edx;
+ bool vp_bits_from_cpuid = true;
- if (c->extended_cpuid_level >= 0x80000008) {
+ if (!cpu_has(c, X86_FEATURE_CPUID) ||
+ (c->extended_cpuid_level < 0x80000008))
+ vp_bits_from_cpuid = false;
+
+ if (vp_bits_from_cpuid) {
cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
c->x86_virt_bits = (eax >> 8) & 0xff;
c->x86_phys_bits = eax & 0xff;
+ } else {
+ if (IS_ENABLED(CONFIG_X86_64)) {
+ c->x86_clflush_size = 64;
+ c->x86_phys_bits = 36;
+ c->x86_virt_bits = 48;
+ } else {
+ c->x86_clflush_size = 32;
+ c->x86_virt_bits = 32;
+ c->x86_phys_bits = 32;
+
+ if (cpu_has(c, X86_FEATURE_PAE) ||
+ cpu_has(c, X86_FEATURE_PSE36))
+ c->x86_phys_bits = 36;
+ }
}
-#ifdef CONFIG_X86_32
- else if (cpu_has(c, X86_FEATURE_PAE) || cpu_has(c, X86_FEATURE_PSE36))
- c->x86_phys_bits = 36;
-#endif
c->x86_cache_bits = c->x86_phys_bits;
+ c->x86_cache_alignment = c->x86_clflush_size;
}
static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
@@ -1579,17 +1584,6 @@ static void __init cpu_parse_early_param(void)
*/
static void __init early_identify_cpu(struct cpuinfo_x86 *c)
{
-#ifdef CONFIG_X86_64
- c->x86_clflush_size = 64;
- c->x86_phys_bits = 36;
- c->x86_virt_bits = 48;
-#else
- c->x86_clflush_size = 32;
- c->x86_phys_bits = 32;
- c->x86_virt_bits = 32;
-#endif
- c->x86_cache_alignment = c->x86_clflush_size;
-
memset(&c->x86_capability, 0, sizeof(c->x86_capability));
c->extended_cpuid_level = 0;
@@ -1601,7 +1595,6 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
cpu_detect(c);
get_cpu_vendor(c);
get_cpu_cap(c);
- get_cpu_address_sizes(c);
setup_force_cpu_cap(X86_FEATURE_CPUID);
cpu_parse_early_param();
@@ -1617,6 +1610,8 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
setup_clear_cpu_cap(X86_FEATURE_CPUID);
}
+ get_cpu_address_sizes(c);
+
setup_force_cpu_cap(X86_FEATURE_ALWAYS);
cpu_set_bug_bits(c);
@@ -1761,15 +1756,15 @@ static void generic_identify(struct cpuinfo_x86 *c)
get_cpu_address_sizes(c);
if (c->cpuid_level >= 0x00000001) {
- c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF;
+ c->topo.initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF;
#ifdef CONFIG_X86_32
# ifdef CONFIG_SMP
- c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
+ c->topo.apicid = apic->phys_pkg_id(c->topo.initial_apicid, 0);
# else
- c->apicid = c->initial_apicid;
+ c->topo.apicid = c->topo.initial_apicid;
# endif
#endif
- c->phys_proc_id = c->initial_apicid;
+ c->topo.pkg_id = c->topo.initial_apicid;
}
get_model_name(c); /* Default name */
@@ -1799,18 +1794,19 @@ static void generic_identify(struct cpuinfo_x86 *c)
static void validate_apic_and_package_id(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
- unsigned int apicid, cpu = smp_processor_id();
+ unsigned int cpu = smp_processor_id();
+ u32 apicid;
apicid = apic->cpu_present_to_apicid(cpu);
- if (apicid != c->apicid) {
+ if (apicid != c->topo.apicid) {
pr_err(FW_BUG "CPU%u: APIC id mismatch. Firmware: %x APIC: %x\n",
- cpu, apicid, c->initial_apicid);
+ cpu, apicid, c->topo.initial_apicid);
}
- BUG_ON(topology_update_package_map(c->phys_proc_id, cpu));
- BUG_ON(topology_update_die_map(c->cpu_die_id, cpu));
+ BUG_ON(topology_update_package_map(c->topo.pkg_id, cpu));
+ BUG_ON(topology_update_die_map(c->topo.die_id, cpu));
#else
- c->logical_proc_id = 0;
+ c->topo.logical_pkg_id = 0;
#endif
}
@@ -1829,7 +1825,9 @@ static void identify_cpu(struct cpuinfo_x86 *c)
c->x86_model_id[0] = '\0'; /* Unset */
c->x86_max_cores = 1;
c->x86_coreid_bits = 0;
- c->cu_id = 0xff;
+ c->topo.cu_id = 0xff;
+ c->topo.llc_id = BAD_APICID;
+ c->topo.l2c_id = BAD_APICID;
#ifdef CONFIG_X86_64
c->x86_clflush_size = 64;
c->x86_phys_bits = 36;
@@ -1855,7 +1853,7 @@ static void identify_cpu(struct cpuinfo_x86 *c)
apply_forced_caps(c);
#ifdef CONFIG_X86_64
- c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
+ c->topo.apicid = apic->phys_pkg_id(c->topo.initial_apicid, 0);
#endif
/*
@@ -2074,24 +2072,24 @@ void syscall_init(void)
wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
-#ifdef CONFIG_IA32_EMULATION
- wrmsrl_cstar((unsigned long)entry_SYSCALL_compat);
- /*
- * This only works on Intel CPUs.
- * On AMD CPUs these MSRs are 32-bit, CPU truncates MSR_IA32_SYSENTER_EIP.
- * This does not cause SYSENTER to jump to the wrong location, because
- * AMD doesn't allow SYSENTER in long mode (either 32- or 64-bit).
- */
- wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
- wrmsrl_safe(MSR_IA32_SYSENTER_ESP,
- (unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));
- wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);
-#else
- wrmsrl_cstar((unsigned long)ignore_sysret);
- wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
- wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
- wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
-#endif
+ if (ia32_enabled()) {
+ wrmsrl_cstar((unsigned long)entry_SYSCALL_compat);
+ /*
+ * This only works on Intel CPUs.
+ * On AMD CPUs these MSRs are 32-bit, CPU truncates MSR_IA32_SYSENTER_EIP.
+ * This does not cause SYSENTER to jump to the wrong location, because
+ * AMD doesn't allow SYSENTER in long mode (either 32- or 64-bit).
+ */
+ wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
+ wrmsrl_safe(MSR_IA32_SYSENTER_ESP,
+ (unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));
+ wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);
+ } else {
+ wrmsrl_cstar((unsigned long)entry_SYSCALL32_ignore);
+ wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
+ wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
+ wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
+ }
/*
* Flags to clear on syscall; clear as much as possible
@@ -2166,8 +2164,6 @@ static inline void setup_getcpu(int cpu)
}
#ifdef CONFIG_X86_64
-static inline void ucode_cpu_init(int cpu) { }
-
static inline void tss_setup_ist(struct tss_struct *tss)
{
/* Set up the per-CPU TSS IST stacks */
@@ -2178,16 +2174,8 @@ static inline void tss_setup_ist(struct tss_struct *tss)
/* Only mapped when SEV-ES is active */
tss->x86_tss.ist[IST_INDEX_VC] = __this_cpu_ist_top_va(VC);
}
-
#else /* CONFIG_X86_64 */
-
-static inline void ucode_cpu_init(int cpu)
-{
- show_ucode_info_early();
-}
-
static inline void tss_setup_ist(struct tss_struct *tss) { }
-
#endif /* !CONFIG_X86_64 */
static inline void tss_setup_io_bitmap(struct tss_struct *tss)
@@ -2243,8 +2231,6 @@ void cpu_init(void)
struct task_struct *cur = current;
int cpu = raw_smp_processor_id();
- ucode_cpu_init(cpu);
-
#ifdef CONFIG_NUMA
if (this_cpu_read(numa_node) == 0 &&
early_cpu_to_node(cpu) != NUMA_NO_NODE)
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index 1dcd7d4e38ef..885281ae79a5 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -78,6 +78,9 @@ extern int detect_ht_early(struct cpuinfo_x86 *c);
extern void detect_ht(struct cpuinfo_x86 *c);
extern void check_null_seg_clears_base(struct cpuinfo_x86 *c);
+void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c);
+void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c);
+
unsigned int aperfmperf_get_khz(int cpu);
void cpu_select_mitigations(void);
diff --git a/arch/x86/kernel/cpu/debugfs.c b/arch/x86/kernel/cpu/debugfs.c
new file mode 100644
index 000000000000..0c179d684b3b
--- /dev/null
+++ b/arch/x86/kernel/cpu/debugfs.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/debugfs.h>
+
+#include <asm/apic.h>
+#include <asm/processor.h>
+
+static int cpu_debug_show(struct seq_file *m, void *p)
+{
+ unsigned long cpu = (unsigned long)m->private;
+ struct cpuinfo_x86 *c = per_cpu_ptr(&cpu_info, cpu);
+
+ seq_printf(m, "online: %d\n", cpu_online(cpu));
+ if (!c->initialized)
+ return 0;
+
+ seq_printf(m, "initial_apicid: %x\n", c->topo.initial_apicid);
+ seq_printf(m, "apicid: %x\n", c->topo.apicid);
+ seq_printf(m, "pkg_id: %u\n", c->topo.pkg_id);
+ seq_printf(m, "die_id: %u\n", c->topo.die_id);
+ seq_printf(m, "cu_id: %u\n", c->topo.cu_id);
+ seq_printf(m, "core_id: %u\n", c->topo.core_id);
+ seq_printf(m, "logical_pkg_id: %u\n", c->topo.logical_pkg_id);
+ seq_printf(m, "logical_die_id: %u\n", c->topo.logical_die_id);
+ seq_printf(m, "llc_id: %u\n", c->topo.llc_id);
+ seq_printf(m, "l2c_id: %u\n", c->topo.l2c_id);
+ seq_printf(m, "max_cores: %u\n", c->x86_max_cores);
+ seq_printf(m, "max_die_per_pkg: %u\n", __max_die_per_package);
+ seq_printf(m, "smp_num_siblings: %u\n", smp_num_siblings);
+ return 0;
+}
+
+static int cpu_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cpu_debug_show, inode->i_private);
+}
+
+static const struct file_operations dfs_cpu_ops = {
+ .open = cpu_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static __init int cpu_init_debugfs(void)
+{
+ struct dentry *dir, *base = debugfs_create_dir("topo", arch_debugfs_dir);
+ unsigned long id;
+ char name[24];
+
+ dir = debugfs_create_dir("cpus", base);
+ for_each_possible_cpu(id) {
+ sprintf(name, "%lu", id);
+ debugfs_create_file(name, 0444, dir, (void *)id, &dfs_cpu_ops);
+ }
+ return 0;
+}
+late_initcall(cpu_init_debugfs);
diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c
index defdc594be14..6f247d66758d 100644
--- a/arch/x86/kernel/cpu/hygon.c
+++ b/arch/x86/kernel/cpu/hygon.c
@@ -63,8 +63,6 @@ static void hygon_get_topology_early(struct cpuinfo_x86 *c)
*/
static void hygon_get_topology(struct cpuinfo_x86 *c)
{
- int cpu = smp_processor_id();
-
/* get information required for multi-node processors */
if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
int err;
@@ -72,9 +70,9 @@ static void hygon_get_topology(struct cpuinfo_x86 *c)
cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
- c->cpu_die_id = ecx & 0xff;
+ c->topo.die_id = ecx & 0xff;
- c->cpu_core_id = ebx & 0xff;
+ c->topo.core_id = ebx & 0xff;
if (smp_num_siblings > 1)
c->x86_max_cores /= smp_num_siblings;
@@ -87,17 +85,20 @@ static void hygon_get_topology(struct cpuinfo_x86 *c)
if (!err)
c->x86_coreid_bits = get_count_order(c->x86_max_cores);
- /* Socket ID is ApicId[6] for these processors. */
- c->phys_proc_id = c->apicid >> APICID_SOCKET_ID_BIT;
+ /*
+ * Socket ID is ApicId[6] for the processors with model <= 0x3
+ * when running on host.
+ */
+ if (!boot_cpu_has(X86_FEATURE_HYPERVISOR) && c->x86_model <= 0x3)
+ c->topo.pkg_id = c->topo.apicid >> APICID_SOCKET_ID_BIT;
- cacheinfo_hygon_init_llc_id(c, cpu);
+ cacheinfo_hygon_init_llc_id(c);
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
u64 value;
rdmsrl(MSR_FAM10H_NODE_ID, value);
- c->cpu_die_id = value & 7;
-
- per_cpu(cpu_llc_id, cpu) = c->cpu_die_id;
+ c->topo.die_id = value & 7;
+ c->topo.llc_id = c->topo.die_id;
} else
return;
@@ -112,15 +113,14 @@ static void hygon_get_topology(struct cpuinfo_x86 *c)
static void hygon_detect_cmp(struct cpuinfo_x86 *c)
{
unsigned int bits;
- int cpu = smp_processor_id();
bits = c->x86_coreid_bits;
/* Low order bits define the core id (index of core in socket) */
- c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
+ c->topo.core_id = c->topo.initial_apicid & ((1 << bits)-1);
/* Convert the initial APIC ID into the socket ID */
- c->phys_proc_id = c->initial_apicid >> bits;
- /* use socket ID also for last level cache */
- per_cpu(cpu_llc_id, cpu) = c->cpu_die_id = c->phys_proc_id;
+ c->topo.pkg_id = c->topo.initial_apicid >> bits;
+ /* Use package ID also for last level cache */
+ c->topo.llc_id = c->topo.die_id = c->topo.pkg_id;
}
static void srat_detect_node(struct cpuinfo_x86 *c)
@@ -128,11 +128,11 @@ static void srat_detect_node(struct cpuinfo_x86 *c)
#ifdef CONFIG_NUMA
int cpu = smp_processor_id();
int node;
- unsigned int apicid = c->apicid;
+ unsigned int apicid = c->topo.apicid;
node = numa_cpu_node(cpu);
if (node == NUMA_NO_NODE)
- node = per_cpu(cpu_llc_id, cpu);
+ node = c->topo.llc_id;
/*
* On multi-fabric platform (e.g. Numascale NumaChip) a
@@ -161,7 +161,7 @@ static void srat_detect_node(struct cpuinfo_x86 *c)
* through CPU mapping may alter the outcome, directly
* access __apicid_to_node[].
*/
- int ht_nodeid = c->initial_apicid;
+ int ht_nodeid = c->topo.initial_apicid;
if (__apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
node = __apicid_to_node[ht_nodeid];
@@ -290,6 +290,8 @@ static void early_init_hygon(struct cpuinfo_x86 *c)
static void init_hygon(struct cpuinfo_x86 *c)
{
+ u64 vm_cr;
+
early_init_hygon(c);
/*
@@ -301,7 +303,7 @@ static void init_hygon(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_REP_GOOD);
/* get apicid instead of initial apic id from cpuid */
- c->apicid = read_apic_id();
+ c->topo.apicid = read_apic_id();
/*
* XXX someone from Hygon needs to confirm this DTRT
@@ -320,6 +322,14 @@ static void init_hygon(struct cpuinfo_x86 *c)
init_hygon_cacheinfo(c);
+ if (cpu_has(c, X86_FEATURE_SVM)) {
+ rdmsrl(MSR_VM_CR, vm_cr);
+ if (vm_cr & SVM_VM_CR_SVM_DIS_MASK) {
+ pr_notice_once("SVM disabled (by BIOS) in MSR_VM_CR\n");
+ clear_cpu_cap(c, X86_FEATURE_SVM);
+ }
+ }
+
if (cpu_has(c, X86_FEATURE_XMM2)) {
/*
* Use LFENCE for execution serialization. On families which
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index be4045628fd3..a927a8fc9624 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -314,19 +314,6 @@ static void early_init_intel(struct cpuinfo_x86 *c)
setup_clear_cpu_cap(X86_FEATURE_PGE);
}
- if (c->cpuid_level >= 0x00000001) {
- u32 eax, ebx, ecx, edx;
-
- cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
- /*
- * If HTT (EDX[28]) is set EBX[16:23] contain the number of
- * apicids which are reserved per package. Store the resulting
- * shift value for the package management code.
- */
- if (edx & (1U << 28))
- c->x86_coreid_bits = get_count_order((ebx >> 16) & 0xff);
- }
-
check_memory_type_self_snoop_errata(c);
/*
@@ -1016,7 +1003,6 @@ static struct ctl_table sld_sysctls[] = {
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
- {}
};
static int __init sld_mitigate_sysctl_init(void)
diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c
index c267f43de39e..f3517b8a8e91 100644
--- a/arch/x86/kernel/cpu/mce/amd.c
+++ b/arch/x86/kernel/cpu/mce/amd.c
@@ -713,17 +713,75 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
deferred_error_interrupt_enable(c);
}
-bool amd_mce_is_memory_error(struct mce *m)
+/*
+ * DRAM ECC errors are reported in the Northbridge (bank 4) with
+ * Extended Error Code 8.
+ */
+static bool legacy_mce_is_memory_error(struct mce *m)
+{
+ return m->bank == 4 && XEC(m->status, 0x1f) == 8;
+}
+
+/*
+ * DRAM ECC errors are reported in Unified Memory Controllers with
+ * Extended Error Code 0.
+ */
+static bool smca_mce_is_memory_error(struct mce *m)
{
enum smca_bank_types bank_type;
- /* ErrCodeExt[20:16] */
- u8 xec = (m->status >> 16) & 0x1f;
+
+ if (XEC(m->status, 0x3f))
+ return false;
bank_type = smca_get_bank_type(m->extcpu, m->bank);
+
+ return bank_type == SMCA_UMC || bank_type == SMCA_UMC_V2;
+}
+
+bool amd_mce_is_memory_error(struct mce *m)
+{
if (mce_flags.smca)
- return (bank_type == SMCA_UMC || bank_type == SMCA_UMC_V2) && xec == 0x0;
+ return smca_mce_is_memory_error(m);
+ else
+ return legacy_mce_is_memory_error(m);
+}
+
+/*
+ * AMD systems do not have an explicit indicator that the value in MCA_ADDR is
+ * a system physical address. Therefore, individual cases need to be detected.
+ * Future cases and checks will be added as needed.
+ *
+ * 1) General case
+ * a) Assume address is not usable.
+ * 2) Poison errors
+ * a) Indicated by MCA_STATUS[43]: poison. Defined for all banks except legacy
+ * northbridge (bank 4).
+ * b) Refers to poison consumption in the core. Does not include "no action",
+ * "action optional", or "deferred" error severities.
+ * c) Will include a usable address so that immediate action can be taken.
+ * 3) Northbridge DRAM ECC errors
+ * a) Reported in legacy bank 4 with extended error code (XEC) 8.
+ * b) MCA_STATUS[43] is *not* defined as poison in legacy bank 4. Therefore,
+ * this bit should not be checked.
+ *
+ * NOTE: SMCA UMC memory errors fall into case #1.
+ */
+bool amd_mce_usable_address(struct mce *m)
+{
+ /* Check special northbridge case 3) first. */
+ if (!mce_flags.smca) {
+ if (legacy_mce_is_memory_error(m))
+ return true;
+ else if (m->bank == 4)
+ return false;
+ }
- return m->bank == 4 && xec == 0x8;
+ /* Check poison bit for all other bank types. */
+ if (m->status & MCI_STATUS_POISON)
+ return true;
+
+ /* Assume address is not usable for all others. */
+ return false;
}
static void __log_error(unsigned int bank, u64 status, u64 addr, u64 misc)
diff --git a/arch/x86/kernel/cpu/mce/apei.c b/arch/x86/kernel/cpu/mce/apei.c
index 8ed341714686..7f7309ff67d0 100644
--- a/arch/x86/kernel/cpu/mce/apei.c
+++ b/arch/x86/kernel/cpu/mce/apei.c
@@ -103,9 +103,9 @@ int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info, u64 lapic_id)
m.socketid = -1;
for_each_possible_cpu(cpu) {
- if (cpu_data(cpu).initial_apicid == lapic_id) {
+ if (cpu_data(cpu).topo.initial_apicid == lapic_id) {
m.extcpu = cpu;
- m.socketid = cpu_data(m.extcpu).phys_proc_id;
+ m.socketid = cpu_data(m.extcpu).topo.pkg_id;
break;
}
}
diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
index 6f35f724cc14..7b397370b4d6 100644
--- a/arch/x86/kernel/cpu/mce/core.c
+++ b/arch/x86/kernel/cpu/mce/core.c
@@ -123,8 +123,8 @@ void mce_setup(struct mce *m)
m->time = __ktime_get_real_seconds();
m->cpuvendor = boot_cpu_data.x86_vendor;
m->cpuid = cpuid_eax(1);
- m->socketid = cpu_data(m->extcpu).phys_proc_id;
- m->apicid = cpu_data(m->extcpu).initial_apicid;
+ m->socketid = cpu_data(m->extcpu).topo.pkg_id;
+ m->apicid = cpu_data(m->extcpu).topo.initial_apicid;
m->mcgcap = __rdmsr(MSR_IA32_MCG_CAP);
m->ppin = cpu_data(m->extcpu).ppin;
m->microcode = boot_cpu_data.microcode;
@@ -453,32 +453,22 @@ static void mce_irq_work_cb(struct irq_work *entry)
mce_schedule_work();
}
-/*
- * Check if the address reported by the CPU is in a format we can parse.
- * It would be possible to add code for most other cases, but all would
- * be somewhat complicated (e.g. segment offset would require an instruction
- * parser). So only support physical addresses up to page granularity for now.
- */
-int mce_usable_address(struct mce *m)
+bool mce_usable_address(struct mce *m)
{
if (!(m->status & MCI_STATUS_ADDRV))
- return 0;
-
- /* Checks after this one are Intel/Zhaoxin-specific: */
- if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL &&
- boot_cpu_data.x86_vendor != X86_VENDOR_ZHAOXIN)
- return 1;
-
- if (!(m->status & MCI_STATUS_MISCV))
- return 0;
+ return false;
- if (MCI_MISC_ADDR_LSB(m->misc) > PAGE_SHIFT)
- return 0;
+ switch (m->cpuvendor) {
+ case X86_VENDOR_AMD:
+ return amd_mce_usable_address(m);
- if (MCI_MISC_ADDR_MODE(m->misc) != MCI_MISC_ADDR_PHYS)
- return 0;
+ case X86_VENDOR_INTEL:
+ case X86_VENDOR_ZHAOXIN:
+ return intel_mce_usable_address(m);
- return 1;
+ default:
+ return true;
+ }
}
EXPORT_SYMBOL_GPL(mce_usable_address);
diff --git a/arch/x86/kernel/cpu/mce/intel.c b/arch/x86/kernel/cpu/mce/intel.c
index f5323551c1a9..52bce533ddcc 100644
--- a/arch/x86/kernel/cpu/mce/intel.c
+++ b/arch/x86/kernel/cpu/mce/intel.c
@@ -536,3 +536,23 @@ bool intel_filter_mce(struct mce *m)
return false;
}
+
+/*
+ * Check if the address reported by the CPU is in a format we can parse.
+ * It would be possible to add code for most other cases, but all would
+ * be somewhat complicated (e.g. segment offset would require an instruction
+ * parser). So only support physical addresses up to page granularity for now.
+ */
+bool intel_mce_usable_address(struct mce *m)
+{
+ if (!(m->status & MCI_STATUS_MISCV))
+ return false;
+
+ if (MCI_MISC_ADDR_LSB(m->misc) > PAGE_SHIFT)
+ return false;
+
+ if (MCI_MISC_ADDR_MODE(m->misc) != MCI_MISC_ADDR_PHYS)
+ return false;
+
+ return true;
+}
diff --git a/arch/x86/kernel/cpu/mce/internal.h b/arch/x86/kernel/cpu/mce/internal.h
index bcf1b3c66c9c..e13a26c9c0ac 100644
--- a/arch/x86/kernel/cpu/mce/internal.h
+++ b/arch/x86/kernel/cpu/mce/internal.h
@@ -49,6 +49,7 @@ void intel_init_cmci(void);
void intel_init_lmce(void);
void intel_clear_lmce(void);
bool intel_filter_mce(struct mce *m);
+bool intel_mce_usable_address(struct mce *m);
#else
# define cmci_intel_adjust_timer mce_adjust_timer_default
static inline bool mce_intel_cmci_poll(void) { return false; }
@@ -58,6 +59,7 @@ static inline void intel_init_cmci(void) { }
static inline void intel_init_lmce(void) { }
static inline void intel_clear_lmce(void) { }
static inline bool intel_filter_mce(struct mce *m) { return false; }
+static inline bool intel_mce_usable_address(struct mce *m) { return false; }
#endif
void mce_timer_kick(unsigned long interval);
@@ -210,6 +212,7 @@ extern bool filter_mce(struct mce *m);
#ifdef CONFIG_X86_MCE_AMD
extern bool amd_filter_mce(struct mce *m);
+bool amd_mce_usable_address(struct mce *m);
/*
* If MCA_CONFIG[McaLsbInStatusSupported] is set, extract ErrAddr in bits
@@ -237,6 +240,7 @@ static __always_inline void smca_extract_err_addr(struct mce *m)
#else
static inline bool amd_filter_mce(struct mce *m) { return false; }
+static inline bool amd_mce_usable_address(struct mce *m) { return false; }
static inline void smca_extract_err_addr(struct mce *m) { }
#endif
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index bbd1dc38ea03..13b45b9c806d 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -37,6 +37,16 @@
#include "internal.h"
+struct ucode_patch {
+ struct list_head plist;
+ void *data;
+ unsigned int size;
+ u32 patch_id;
+ u16 equiv_cpu;
+};
+
+static LIST_HEAD(microcode_cache);
+
#define UCODE_MAGIC 0x00414d44
#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
#define UCODE_UCODE_TYPE 0x00000001
@@ -94,8 +104,6 @@ struct cont_desc {
size_t size;
};
-static u32 ucode_new_rev;
-
/*
* Microcode patch container file is prepended to the initrd in cpio
* format. See Documentation/arch/x86/microcode.rst
@@ -121,24 +129,20 @@ static u16 find_equiv_id(struct equiv_cpu_table *et, u32 sig)
/*
* Check whether there is a valid microcode container file at the beginning
- * of @buf of size @buf_size. Set @early to use this function in the early path.
+ * of @buf of size @buf_size.
*/
-static bool verify_container(const u8 *buf, size_t buf_size, bool early)
+static bool verify_container(const u8 *buf, size_t buf_size)
{
u32 cont_magic;
if (buf_size <= CONTAINER_HDR_SZ) {
- if (!early)
- pr_debug("Truncated microcode container header.\n");
-
+ pr_debug("Truncated microcode container header.\n");
return false;
}
cont_magic = *(const u32 *)buf;
if (cont_magic != UCODE_MAGIC) {
- if (!early)
- pr_debug("Invalid magic value (0x%08x).\n", cont_magic);
-
+ pr_debug("Invalid magic value (0x%08x).\n", cont_magic);
return false;
}
@@ -147,23 +151,20 @@ static bool verify_container(const u8 *buf, size_t buf_size, bool early)
/*
* Check whether there is a valid, non-truncated CPU equivalence table at the
- * beginning of @buf of size @buf_size. Set @early to use this function in the
- * early path.
+ * beginning of @buf of size @buf_size.
*/
-static bool verify_equivalence_table(const u8 *buf, size_t buf_size, bool early)
+static bool verify_equivalence_table(const u8 *buf, size_t buf_size)
{
const u32 *hdr = (const u32 *)buf;
u32 cont_type, equiv_tbl_len;
- if (!verify_container(buf, buf_size, early))
+ if (!verify_container(buf, buf_size))
return false;
cont_type = hdr[1];
if (cont_type != UCODE_EQUIV_CPU_TABLE_TYPE) {
- if (!early)
- pr_debug("Wrong microcode container equivalence table type: %u.\n",
- cont_type);
-
+ pr_debug("Wrong microcode container equivalence table type: %u.\n",
+ cont_type);
return false;
}
@@ -172,9 +173,7 @@ static bool verify_equivalence_table(const u8 *buf, size_t buf_size, bool early)
equiv_tbl_len = hdr[2];
if (equiv_tbl_len < sizeof(struct equiv_cpu_entry) ||
buf_size < equiv_tbl_len) {
- if (!early)
- pr_debug("Truncated equivalence table.\n");
-
+ pr_debug("Truncated equivalence table.\n");
return false;
}
@@ -183,22 +182,19 @@ static bool verify_equivalence_table(const u8 *buf, size_t buf_size, bool early)
/*
* Check whether there is a valid, non-truncated microcode patch section at the
- * beginning of @buf of size @buf_size. Set @early to use this function in the
- * early path.
+ * beginning of @buf of size @buf_size.
*
* On success, @sh_psize returns the patch size according to the section header,
* to the caller.
*/
static bool
-__verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize, bool early)
+__verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize)
{
u32 p_type, p_size;
const u32 *hdr;
if (buf_size < SECTION_HDR_SIZE) {
- if (!early)
- pr_debug("Truncated patch section.\n");
-
+ pr_debug("Truncated patch section.\n");
return false;
}
@@ -207,17 +203,13 @@ __verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize, bool early
p_size = hdr[1];
if (p_type != UCODE_UCODE_TYPE) {
- if (!early)
- pr_debug("Invalid type field (0x%x) in container file section header.\n",
- p_type);
-
+ pr_debug("Invalid type field (0x%x) in container file section header.\n",
+ p_type);
return false;
}
if (p_size < sizeof(struct microcode_header_amd)) {
- if (!early)
- pr_debug("Patch of size %u too short.\n", p_size);
-
+ pr_debug("Patch of size %u too short.\n", p_size);
return false;
}
@@ -269,7 +261,7 @@ static unsigned int __verify_patch_size(u8 family, u32 sh_psize, size_t buf_size
* 0: success
*/
static int
-verify_patch(u8 family, const u8 *buf, size_t buf_size, u32 *patch_size, bool early)
+verify_patch(u8 family, const u8 *buf, size_t buf_size, u32 *patch_size)
{
struct microcode_header_amd *mc_hdr;
unsigned int ret;
@@ -277,7 +269,7 @@ verify_patch(u8 family, const u8 *buf, size_t buf_size, u32 *patch_size, bool ea
u16 proc_id;
u8 patch_fam;
- if (!__verify_patch_section(buf, buf_size, &sh_psize, early))
+ if (!__verify_patch_section(buf, buf_size, &sh_psize))
return -1;
/*
@@ -292,16 +284,13 @@ verify_patch(u8 family, const u8 *buf, size_t buf_size, u32 *patch_size, bool ea
* size sh_psize, as the section claims.
*/
if (buf_size < sh_psize) {
- if (!early)
- pr_debug("Patch of size %u truncated.\n", sh_psize);
-
+ pr_debug("Patch of size %u truncated.\n", sh_psize);
return -1;
}
ret = __verify_patch_size(family, sh_psize, buf_size);
if (!ret) {
- if (!early)
- pr_debug("Per-family patch size mismatch.\n");
+ pr_debug("Per-family patch size mismatch.\n");
return -1;
}
@@ -309,8 +298,7 @@ verify_patch(u8 family, const u8 *buf, size_t buf_size, u32 *patch_size, bool ea
mc_hdr = (struct microcode_header_amd *)(buf + SECTION_HDR_SIZE);
if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
- if (!early)
- pr_err("Patch-ID 0x%08x: chipset-specific code unsupported.\n", mc_hdr->patch_id);
+ pr_err("Patch-ID 0x%08x: chipset-specific code unsupported.\n", mc_hdr->patch_id);
return -1;
}
@@ -337,7 +325,7 @@ static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc)
u16 eq_id;
u8 *buf;
- if (!verify_equivalence_table(ucode, size, true))
+ if (!verify_equivalence_table(ucode, size))
return 0;
buf = ucode;
@@ -364,7 +352,7 @@ static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc)
u32 patch_size;
int ret;
- ret = verify_patch(x86_family(desc->cpuid_1_eax), buf, size, &patch_size, true);
+ ret = verify_patch(x86_family(desc->cpuid_1_eax), buf, size, &patch_size);
if (ret < 0) {
/*
* Patch verification failed, skip to the next container, if
@@ -452,19 +440,12 @@ static int __apply_microcode_amd(struct microcode_amd *mc)
*
* Returns true if container found (sets @desc), false otherwise.
*/
-static bool early_apply_microcode(u32 cpuid_1_eax, void *ucode, size_t size)
+static bool early_apply_microcode(u32 cpuid_1_eax, u32 old_rev, void *ucode, size_t size)
{
struct cont_desc desc = { 0 };
struct microcode_amd *mc;
- u32 rev, dummy, *new_rev;
bool ret = false;
-#ifdef CONFIG_X86_32
- new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
-#else
- new_rev = &ucode_new_rev;
-#endif
-
desc.cpuid_1_eax = cpuid_1_eax;
scan_containers(ucode, size, &desc);
@@ -473,22 +454,15 @@ static bool early_apply_microcode(u32 cpuid_1_eax, void *ucode, size_t size)
if (!mc)
return ret;
- native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
-
/*
* Allow application of the same revision to pick up SMT-specific
* changes even if the revision of the other SMT thread is already
* up-to-date.
*/
- if (rev > mc->hdr.patch_id)
+ if (old_rev > mc->hdr.patch_id)
return ret;
- if (!__apply_microcode_amd(mc)) {
- *new_rev = mc->hdr.patch_id;
- ret = true;
- }
-
- return ret;
+ return !__apply_microcode_amd(mc);
}
static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family)
@@ -501,7 +475,7 @@ static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family)
if (family >= 0x15)
snprintf(fw_name, sizeof(fw_name),
- "amd-ucode/microcode_amd_fam%.2xh.bin", family);
+ "amd-ucode/microcode_amd_fam%02hhxh.bin", family);
if (firmware_request_builtin(&fw, fw_name)) {
cp->size = fw.size;
@@ -512,57 +486,48 @@ static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family)
return false;
}
-static void find_blobs_in_containers(unsigned int cpuid_1_eax, struct cpio_data *ret)
+static void __init find_blobs_in_containers(unsigned int cpuid_1_eax, struct cpio_data *ret)
{
- struct ucode_cpu_info *uci;
struct cpio_data cp;
- const char *path;
- bool use_pa;
-
- if (IS_ENABLED(CONFIG_X86_32)) {
- uci = (struct ucode_cpu_info *)__pa_nodebug(ucode_cpu_info);
- path = (const char *)__pa_nodebug(ucode_path);
- use_pa = true;
- } else {
- uci = ucode_cpu_info;
- path = ucode_path;
- use_pa = false;
- }
if (!get_builtin_microcode(&cp, x86_family(cpuid_1_eax)))
- cp = find_microcode_in_initrd(path, use_pa);
-
- /* Needed in load_microcode_amd() */
- uci->cpu_sig.sig = cpuid_1_eax;
+ cp = find_microcode_in_initrd(ucode_path);
*ret = cp;
}
-static void apply_ucode_from_containers(unsigned int cpuid_1_eax)
+void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_eax)
{
struct cpio_data cp = { };
+ u32 dummy;
+
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->old_rev, dummy);
+
+ /* Needed in load_microcode_amd() */
+ ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax;
find_blobs_in_containers(cpuid_1_eax, &cp);
if (!(cp.data && cp.size))
return;
- early_apply_microcode(cpuid_1_eax, cp.data, cp.size);
-}
-
-void load_ucode_amd_early(unsigned int cpuid_1_eax)
-{
- return apply_ucode_from_containers(cpuid_1_eax);
+ if (early_apply_microcode(cpuid_1_eax, ed->old_rev, cp.data, cp.size))
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy);
}
static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
-int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
+static int __init save_microcode_in_initrd(void)
{
+ unsigned int cpuid_1_eax = native_cpuid_eax(1);
+ struct cpuinfo_x86 *c = &boot_cpu_data;
struct cont_desc desc = { 0 };
enum ucode_state ret;
struct cpio_data cp;
- cp = find_microcode_in_initrd(ucode_path, false);
+ if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10)
+ return 0;
+
+ find_blobs_in_containers(cpuid_1_eax, &cp);
if (!(cp.data && cp.size))
return -EINVAL;
@@ -578,6 +543,7 @@ int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
return 0;
}
+early_initcall(save_microcode_in_initrd);
/*
* a small, trivial cache of per-family ucode patches
@@ -631,7 +597,6 @@ static struct ucode_patch *find_patch(unsigned int cpu)
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
u16 equiv_id;
-
equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig);
if (!equiv_id)
return NULL;
@@ -654,10 +619,8 @@ void reload_ucode_amd(unsigned int cpu)
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
if (rev < mc->hdr.patch_id) {
- if (!__apply_microcode_amd(mc)) {
- ucode_new_rev = mc->hdr.patch_id;
- pr_info("reload patch_level=0x%08x\n", ucode_new_rev);
- }
+ if (!__apply_microcode_amd(mc))
+ pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id);
}
}
@@ -678,8 +641,6 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
if (p && (p->patch_id == csig->rev))
uci->mc = p->data;
- pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
-
return 0;
}
@@ -720,8 +681,6 @@ static enum ucode_state apply_microcode_amd(int cpu)
rev = mc_amd->hdr.patch_id;
ret = UCODE_UPDATED;
- pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev);
-
out:
uci->cpu_sig.rev = rev;
c->microcode = rev;
@@ -733,12 +692,20 @@ out:
return ret;
}
+void load_ucode_amd_ap(unsigned int cpuid_1_eax)
+{
+ unsigned int cpu = smp_processor_id();
+
+ ucode_cpu_info[cpu].cpu_sig.sig = cpuid_1_eax;
+ apply_microcode_amd(cpu);
+}
+
static size_t install_equiv_cpu_table(const u8 *buf, size_t buf_size)
{
u32 equiv_tbl_len;
const u32 *hdr;
- if (!verify_equivalence_table(buf, buf_size, false))
+ if (!verify_equivalence_table(buf, buf_size))
return 0;
hdr = (const u32 *)buf;
@@ -784,7 +751,7 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover,
u16 proc_id;
int ret;
- ret = verify_patch(family, fw, leftover, patch_size, false);
+ ret = verify_patch(family, fw, leftover, patch_size);
if (ret)
return ret;
@@ -909,6 +876,9 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device)
enum ucode_state ret = UCODE_NFOUND;
const struct firmware *fw;
+ if (force_minrev)
+ return UCODE_NFOUND;
+
if (c->x86 >= 0x15)
snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
@@ -918,7 +888,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device)
}
ret = UCODE_ERROR;
- if (!verify_container(fw->data, fw->size, false))
+ if (!verify_container(fw->data, fw->size))
goto fw_release;
ret = load_microcode_amd(c->x86, fw->data, fw->size);
@@ -938,10 +908,11 @@ static void microcode_fini_cpu_amd(int cpu)
}
static struct microcode_ops microcode_amd_ops = {
- .request_microcode_fw = request_microcode_amd,
- .collect_cpu_info = collect_cpu_info_amd,
- .apply_microcode = apply_microcode_amd,
- .microcode_fini_cpu = microcode_fini_cpu_amd,
+ .request_microcode_fw = request_microcode_amd,
+ .collect_cpu_info = collect_cpu_info_amd,
+ .apply_microcode = apply_microcode_amd,
+ .microcode_fini_cpu = microcode_fini_cpu_amd,
+ .nmi_safe = true,
};
struct microcode_ops * __init init_amd_microcode(void)
@@ -952,11 +923,6 @@ struct microcode_ops * __init init_amd_microcode(void)
pr_warn("AMD CPU family 0x%x not supported\n", c->x86);
return NULL;
}
-
- if (ucode_new_rev)
- pr_info_once("microcode updated early to new patch_level=0x%08x\n",
- ucode_new_rev);
-
return &microcode_amd_ops;
}
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 6cc7a2c181da..232026a239a6 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -23,6 +23,7 @@
#include <linux/miscdevice.h>
#include <linux/capability.h>
#include <linux/firmware.h>
+#include <linux/cpumask.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/mutex.h>
@@ -31,6 +32,7 @@
#include <linux/fs.h>
#include <linux/mm.h>
+#include <asm/apic.h>
#include <asm/cpu_device_id.h>
#include <asm/perf_event.h>
#include <asm/processor.h>
@@ -39,14 +41,11 @@
#include "internal.h"
-#define DRIVER_VERSION "2.2"
-
static struct microcode_ops *microcode_ops;
-static bool dis_ucode_ldr = true;
-
-bool initrd_gone;
+bool dis_ucode_ldr = true;
-LIST_HEAD(microcode_cache);
+bool force_minrev = IS_ENABLED(CONFIG_MICROCODE_LATE_FORCE_MINREV);
+module_param(force_minrev, bool, S_IRUSR | S_IWUSR);
/*
* Synchronization.
@@ -76,6 +75,8 @@ static u32 final_levels[] = {
0, /* T-101 terminator */
};
+struct early_load_data early_data;
+
/*
* Check the current patch level on this CPU.
*
@@ -90,10 +91,7 @@ static bool amd_check_current_patch_level(void)
native_rdmsr(MSR_AMD64_PATCH_LEVEL, lvl, dummy);
- if (IS_ENABLED(CONFIG_X86_32))
- levels = (u32 *)__pa_nodebug(&final_levels);
- else
- levels = final_levels;
+ levels = final_levels;
for (i = 0; levels[i]; i++) {
if (lvl == levels[i])
@@ -105,17 +103,8 @@ static bool amd_check_current_patch_level(void)
static bool __init check_loader_disabled_bsp(void)
{
static const char *__dis_opt_str = "dis_ucode_ldr";
-
-#ifdef CONFIG_X86_32
- const char *cmdline = (const char *)__pa_nodebug(boot_command_line);
- const char *option = (const char *)__pa_nodebug(__dis_opt_str);
- bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr);
-
-#else /* CONFIG_X86_64 */
const char *cmdline = boot_command_line;
const char *option = __dis_opt_str;
- bool *res = &dis_ucode_ldr;
-#endif
/*
* CPUID(1).ECX[31]: reserved for hypervisor use. This is still not
@@ -123,17 +112,17 @@ static bool __init check_loader_disabled_bsp(void)
* that's good enough as they don't land on the BSP path anyway.
*/
if (native_cpuid_ecx(1) & BIT(31))
- return *res;
+ return true;
if (x86_cpuid_vendor() == X86_VENDOR_AMD) {
if (amd_check_current_patch_level())
- return *res;
+ return true;
}
if (cmdline_find_option_bool(cmdline, option) <= 0)
- *res = false;
+ dis_ucode_ldr = false;
- return *res;
+ return dis_ucode_ldr;
}
void __init load_ucode_bsp(void)
@@ -166,25 +155,16 @@ void __init load_ucode_bsp(void)
return;
if (intel)
- load_ucode_intel_bsp();
+ load_ucode_intel_bsp(&early_data);
else
- load_ucode_amd_early(cpuid_1_eax);
-}
-
-static bool check_loader_disabled_ap(void)
-{
-#ifdef CONFIG_X86_32
- return *((bool *)__pa_nodebug(&dis_ucode_ldr));
-#else
- return dis_ucode_ldr;
-#endif
+ load_ucode_amd_bsp(&early_data, cpuid_1_eax);
}
void load_ucode_ap(void)
{
unsigned int cpuid_1_eax;
- if (check_loader_disabled_ap())
+ if (dis_ucode_ldr)
return;
cpuid_1_eax = native_cpuid_eax(1);
@@ -196,97 +176,44 @@ void load_ucode_ap(void)
break;
case X86_VENDOR_AMD:
if (x86_family(cpuid_1_eax) >= 0x10)
- load_ucode_amd_early(cpuid_1_eax);
+ load_ucode_amd_ap(cpuid_1_eax);
break;
default:
break;
}
}
-static int __init save_microcode_in_initrd(void)
-{
- struct cpuinfo_x86 *c = &boot_cpu_data;
- int ret = -EINVAL;
-
- switch (c->x86_vendor) {
- case X86_VENDOR_INTEL:
- if (c->x86 >= 6)
- ret = save_microcode_in_initrd_intel();
- break;
- case X86_VENDOR_AMD:
- if (c->x86 >= 0x10)
- ret = save_microcode_in_initrd_amd(cpuid_eax(1));
- break;
- default:
- break;
- }
-
- initrd_gone = true;
-
- return ret;
-}
-
-struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
+struct cpio_data __init find_microcode_in_initrd(const char *path)
{
#ifdef CONFIG_BLK_DEV_INITRD
unsigned long start = 0;
size_t size;
#ifdef CONFIG_X86_32
- struct boot_params *params;
-
- if (use_pa)
- params = (struct boot_params *)__pa_nodebug(&boot_params);
- else
- params = &boot_params;
-
- size = params->hdr.ramdisk_size;
-
- /*
- * Set start only if we have an initrd image. We cannot use initrd_start
- * because it is not set that early yet.
- */
+ size = boot_params.hdr.ramdisk_size;
+ /* Early load on BSP has a temporary mapping. */
if (size)
- start = params->hdr.ramdisk_image;
+ start = initrd_start_early;
-# else /* CONFIG_X86_64 */
+#else /* CONFIG_X86_64 */
size = (unsigned long)boot_params.ext_ramdisk_size << 32;
size |= boot_params.hdr.ramdisk_size;
if (size) {
start = (unsigned long)boot_params.ext_ramdisk_image << 32;
start |= boot_params.hdr.ramdisk_image;
-
start += PAGE_OFFSET;
}
-# endif
+#endif
/*
* Fixup the start address: after reserve_initrd() runs, initrd_start
* has the virtual address of the beginning of the initrd. It also
* possibly relocates the ramdisk. In either case, initrd_start contains
* the updated address so use that instead.
- *
- * initrd_gone is for the hotplug case where we've thrown out initrd
- * already.
*/
- if (!use_pa) {
- if (initrd_gone)
- return (struct cpio_data){ NULL, 0, "" };
- if (initrd_start)
- start = initrd_start;
- } else {
- /*
- * The picture with physical addresses is a bit different: we
- * need to get the *physical* address to which the ramdisk was
- * relocated, i.e., relocated_ramdisk (not initrd_start) and
- * since we're running from physical addresses, we need to access
- * relocated_ramdisk through its *physical* address too.
- */
- u64 *rr = (u64 *)__pa_nodebug(&relocated_ramdisk);
- if (*rr)
- start = *rr;
- }
+ if (initrd_start)
+ start = initrd_start;
return find_cpio_data(path, (void *)start, size, NULL);
#else /* !CONFIG_BLK_DEV_INITRD */
@@ -330,117 +257,298 @@ static struct platform_device *microcode_pdev;
* requirement can be relaxed in the future. Right now, this is conservative
* and good.
*/
-#define SPINUNIT 100 /* 100 nsec */
+enum sibling_ctrl {
+ /* Spinwait with timeout */
+ SCTRL_WAIT,
+ /* Invoke the microcode_apply() callback */
+ SCTRL_APPLY,
+ /* Proceed without invoking the microcode_apply() callback */
+ SCTRL_DONE,
+};
-static int check_online_cpus(void)
+struct microcode_ctrl {
+ enum sibling_ctrl ctrl;
+ enum ucode_state result;
+ unsigned int ctrl_cpu;
+ bool nmi_enabled;
+};
+
+DEFINE_STATIC_KEY_FALSE(microcode_nmi_handler_enable);
+static DEFINE_PER_CPU(struct microcode_ctrl, ucode_ctrl);
+static atomic_t late_cpus_in, offline_in_nmi;
+static unsigned int loops_per_usec;
+static cpumask_t cpu_offline_mask;
+
+static noinstr bool wait_for_cpus(atomic_t *cnt)
{
- unsigned int cpu;
+ unsigned int timeout, loops;
- /*
- * Make sure all CPUs are online. It's fine for SMT to be disabled if
- * all the primary threads are still online.
- */
- for_each_present_cpu(cpu) {
- if (topology_is_primary_thread(cpu) && !cpu_online(cpu)) {
- pr_err("Not all CPUs online, aborting microcode update.\n");
- return -EINVAL;
+ WARN_ON_ONCE(raw_atomic_dec_return(cnt) < 0);
+
+ for (timeout = 0; timeout < USEC_PER_SEC; timeout++) {
+ if (!raw_atomic_read(cnt))
+ return true;
+
+ for (loops = 0; loops < loops_per_usec; loops++)
+ cpu_relax();
+
+ /* If invoked directly, tickle the NMI watchdog */
+ if (!microcode_ops->use_nmi && !(timeout % USEC_PER_MSEC)) {
+ instrumentation_begin();
+ touch_nmi_watchdog();
+ instrumentation_end();
}
}
-
- return 0;
+ /* Prevent the late comers from making progress and let them time out */
+ raw_atomic_inc(cnt);
+ return false;
}
-static atomic_t late_cpus_in;
-static atomic_t late_cpus_out;
-
-static int __wait_for_cpus(atomic_t *t, long long timeout)
+static noinstr bool wait_for_ctrl(void)
{
- int all_cpus = num_online_cpus();
+ unsigned int timeout, loops;
- atomic_inc(t);
-
- while (atomic_read(t) < all_cpus) {
- if (timeout < SPINUNIT) {
- pr_err("Timeout while waiting for CPUs rendezvous, remaining: %d\n",
- all_cpus - atomic_read(t));
- return 1;
- }
+ for (timeout = 0; timeout < USEC_PER_SEC; timeout++) {
+ if (raw_cpu_read(ucode_ctrl.ctrl) != SCTRL_WAIT)
+ return true;
- ndelay(SPINUNIT);
- timeout -= SPINUNIT;
+ for (loops = 0; loops < loops_per_usec; loops++)
+ cpu_relax();
- touch_nmi_watchdog();
+ /* If invoked directly, tickle the NMI watchdog */
+ if (!microcode_ops->use_nmi && !(timeout % USEC_PER_MSEC)) {
+ instrumentation_begin();
+ touch_nmi_watchdog();
+ instrumentation_end();
+ }
}
- return 0;
+ return false;
}
/*
- * Returns:
- * < 0 - on error
- * 0 - success (no update done or microcode was updated)
+ * Protected against instrumentation up to the point where the primary
+ * thread completed the update. See microcode_nmi_handler() for details.
*/
-static int __reload_late(void *info)
+static noinstr bool load_secondary_wait(unsigned int ctrl_cpu)
{
- int cpu = smp_processor_id();
- enum ucode_state err;
- int ret = 0;
+ /* Initial rendezvous to ensure that all CPUs have arrived */
+ if (!wait_for_cpus(&late_cpus_in)) {
+ raw_cpu_write(ucode_ctrl.result, UCODE_TIMEOUT);
+ return false;
+ }
/*
- * Wait for all CPUs to arrive. A load will not be attempted unless all
- * CPUs show up.
- * */
- if (__wait_for_cpus(&late_cpus_in, NSEC_PER_SEC))
- return -1;
+ * Wait for primary threads to complete. If one of them hangs due
+ * to the update, there is no way out. This is non-recoverable
+ * because the CPU might hold locks or resources and confuse the
+ * scheduler, watchdogs etc. There is no way to safely evacuate the
+ * machine.
+ */
+ if (wait_for_ctrl())
+ return true;
+ instrumentation_begin();
+ panic("Microcode load: Primary CPU %d timed out\n", ctrl_cpu);
+ instrumentation_end();
+}
+
+/*
+ * Protected against instrumentation up to the point where the primary
+ * thread completed the update. See microcode_nmi_handler() for details.
+ */
+static noinstr void load_secondary(unsigned int cpu)
+{
+ unsigned int ctrl_cpu = raw_cpu_read(ucode_ctrl.ctrl_cpu);
+ enum ucode_state ret;
+
+ if (!load_secondary_wait(ctrl_cpu)) {
+ instrumentation_begin();
+ pr_err_once("load: %d CPUs timed out\n",
+ atomic_read(&late_cpus_in) - 1);
+ instrumentation_end();
+ return;
+ }
+
+ /* Primary thread completed. Allow to invoke instrumentable code */
+ instrumentation_begin();
/*
- * On an SMT system, it suffices to load the microcode on one sibling of
- * the core because the microcode engine is shared between the threads.
- * Synchronization still needs to take place so that no concurrent
- * loading attempts happen on multiple threads of an SMT core. See
- * below.
+ * If the primary succeeded then invoke the apply() callback,
+ * otherwise copy the state from the primary thread.
*/
- if (cpumask_first(topology_sibling_cpumask(cpu)) == cpu)
- err = microcode_ops->apply_microcode(cpu);
+ if (this_cpu_read(ucode_ctrl.ctrl) == SCTRL_APPLY)
+ ret = microcode_ops->apply_microcode(cpu);
else
- goto wait_for_siblings;
+ ret = per_cpu(ucode_ctrl.result, ctrl_cpu);
- if (err >= UCODE_NFOUND) {
- if (err == UCODE_ERROR) {
- pr_warn("Error reloading microcode on CPU %d\n", cpu);
- ret = -1;
- }
+ this_cpu_write(ucode_ctrl.result, ret);
+ this_cpu_write(ucode_ctrl.ctrl, SCTRL_DONE);
+ instrumentation_end();
+}
+
+static void __load_primary(unsigned int cpu)
+{
+ struct cpumask *secondaries = topology_sibling_cpumask(cpu);
+ enum sibling_ctrl ctrl;
+ enum ucode_state ret;
+ unsigned int sibling;
+
+ /* Initial rendezvous to ensure that all CPUs have arrived */
+ if (!wait_for_cpus(&late_cpus_in)) {
+ this_cpu_write(ucode_ctrl.result, UCODE_TIMEOUT);
+ pr_err_once("load: %d CPUs timed out\n", atomic_read(&late_cpus_in) - 1);
+ return;
}
-wait_for_siblings:
- if (__wait_for_cpus(&late_cpus_out, NSEC_PER_SEC))
- panic("Timeout during microcode update!\n");
+ ret = microcode_ops->apply_microcode(cpu);
+ this_cpu_write(ucode_ctrl.result, ret);
+ this_cpu_write(ucode_ctrl.ctrl, SCTRL_DONE);
/*
- * At least one thread has completed update on each core.
- * For others, simply call the update to make sure the
- * per-cpu cpuinfo can be updated with right microcode
- * revision.
+ * If the update was successful, let the siblings run the apply()
+ * callback. If not, tell them it's done. This also covers the
+ * case where the CPU has uniform loading at package or system
+ * scope implemented but does not advertise it.
*/
- if (cpumask_first(topology_sibling_cpumask(cpu)) != cpu)
- err = microcode_ops->apply_microcode(cpu);
+ if (ret == UCODE_UPDATED || ret == UCODE_OK)
+ ctrl = SCTRL_APPLY;
+ else
+ ctrl = SCTRL_DONE;
+
+ for_each_cpu(sibling, secondaries) {
+ if (sibling != cpu)
+ per_cpu(ucode_ctrl.ctrl, sibling) = ctrl;
+ }
+}
+
+static bool kick_offline_cpus(unsigned int nr_offl)
+{
+ unsigned int cpu, timeout;
+
+ for_each_cpu(cpu, &cpu_offline_mask) {
+ /* Enable the rendezvous handler and send NMI */
+ per_cpu(ucode_ctrl.nmi_enabled, cpu) = true;
+ apic_send_nmi_to_offline_cpu(cpu);
+ }
+
+ /* Wait for them to arrive */
+ for (timeout = 0; timeout < (USEC_PER_SEC / 2); timeout++) {
+ if (atomic_read(&offline_in_nmi) == nr_offl)
+ return true;
+ udelay(1);
+ }
+ /* Let the others time out */
+ return false;
+}
+
+static void release_offline_cpus(void)
+{
+ unsigned int cpu;
+
+ for_each_cpu(cpu, &cpu_offline_mask)
+ per_cpu(ucode_ctrl.ctrl, cpu) = SCTRL_DONE;
+}
+
+static void load_primary(unsigned int cpu)
+{
+ unsigned int nr_offl = cpumask_weight(&cpu_offline_mask);
+ bool proceed = true;
+
+ /* Kick soft-offlined SMT siblings if required */
+ if (!cpu && nr_offl)
+ proceed = kick_offline_cpus(nr_offl);
+
+ /* If the soft-offlined CPUs did not respond, abort */
+ if (proceed)
+ __load_primary(cpu);
- return ret;
+ /* Unconditionally release soft-offlined SMT siblings if required */
+ if (!cpu && nr_offl)
+ release_offline_cpus();
}
/*
- * Reload microcode late on all CPUs. Wait for a sec until they
- * all gather together.
+ * Minimal stub rendezvous handler for soft-offlined CPUs which participate
+ * in the NMI rendezvous to protect against a concurrent NMI on affected
+ * CPUs.
*/
-static int microcode_reload_late(void)
+void noinstr microcode_offline_nmi_handler(void)
{
- int old = boot_cpu_data.microcode, ret;
+ if (!raw_cpu_read(ucode_ctrl.nmi_enabled))
+ return;
+ raw_cpu_write(ucode_ctrl.nmi_enabled, false);
+ raw_cpu_write(ucode_ctrl.result, UCODE_OFFLINE);
+ raw_atomic_inc(&offline_in_nmi);
+ wait_for_ctrl();
+}
+
+static noinstr bool microcode_update_handler(void)
+{
+ unsigned int cpu = raw_smp_processor_id();
+
+ if (raw_cpu_read(ucode_ctrl.ctrl_cpu) == cpu) {
+ instrumentation_begin();
+ load_primary(cpu);
+ instrumentation_end();
+ } else {
+ load_secondary(cpu);
+ }
+
+ instrumentation_begin();
+ touch_nmi_watchdog();
+ instrumentation_end();
+
+ return true;
+}
+
+/*
+ * Protection against instrumentation is required for CPUs which are not
+ * safe against an NMI which is delivered to the secondary SMT sibling
+ * while the primary thread updates the microcode. Instrumentation can end
+ * up in #INT3, #DB and #PF. The IRET from those exceptions reenables NMI
+ * which is the opposite of what the NMI rendezvous is trying to achieve.
+ *
+ * The primary thread is safe versus instrumentation as the actual
+ * microcode update handles this correctly. It's only the sibling code
+ * path which must be NMI safe until the primary thread completed the
+ * update.
+ */
+bool noinstr microcode_nmi_handler(void)
+{
+ if (!raw_cpu_read(ucode_ctrl.nmi_enabled))
+ return false;
+
+ raw_cpu_write(ucode_ctrl.nmi_enabled, false);
+ return microcode_update_handler();
+}
+
+static int load_cpus_stopped(void *unused)
+{
+ if (microcode_ops->use_nmi) {
+ /* Enable the NMI handler and raise NMI */
+ this_cpu_write(ucode_ctrl.nmi_enabled, true);
+ apic->send_IPI(smp_processor_id(), NMI_VECTOR);
+ } else {
+ /* Just invoke the handler directly */
+ microcode_update_handler();
+ }
+ return 0;
+}
+
+static int load_late_stop_cpus(bool is_safe)
+{
+ unsigned int cpu, updated = 0, failed = 0, timedout = 0, siblings = 0;
+ unsigned int nr_offl, offline = 0;
+ int old_rev = boot_cpu_data.microcode;
struct cpuinfo_x86 prev_info;
- pr_err("Attempting late microcode loading - it is dangerous and taints the kernel.\n");
- pr_err("You should switch to early loading, if possible.\n");
+ if (!is_safe) {
+ pr_err("Late microcode loading without minimal revision check.\n");
+ pr_err("You should switch to early loading, if possible.\n");
+ }
- atomic_set(&late_cpus_in, 0);
- atomic_set(&late_cpus_out, 0);
+ atomic_set(&late_cpus_in, num_online_cpus());
+ atomic_set(&offline_in_nmi, 0);
+ loops_per_usec = loops_per_jiffy / (TICK_NSEC / 1000);
/*
* Take a snapshot before the microcode update in order to compare and
@@ -448,52 +556,162 @@ static int microcode_reload_late(void)
*/
store_cpu_caps(&prev_info);
- ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask);
- if (!ret) {
- pr_info("Reload succeeded, microcode revision: 0x%x -> 0x%x\n",
- old, boot_cpu_data.microcode);
- microcode_check(&prev_info);
- } else {
- pr_info("Reload failed, current microcode revision: 0x%x\n",
- boot_cpu_data.microcode);
+ if (microcode_ops->use_nmi)
+ static_branch_enable_cpuslocked(&microcode_nmi_handler_enable);
+
+ stop_machine_cpuslocked(load_cpus_stopped, NULL, cpu_online_mask);
+
+ if (microcode_ops->use_nmi)
+ static_branch_disable_cpuslocked(&microcode_nmi_handler_enable);
+
+ /* Analyze the results */
+ for_each_cpu_and(cpu, cpu_present_mask, &cpus_booted_once_mask) {
+ switch (per_cpu(ucode_ctrl.result, cpu)) {
+ case UCODE_UPDATED: updated++; break;
+ case UCODE_TIMEOUT: timedout++; break;
+ case UCODE_OK: siblings++; break;
+ case UCODE_OFFLINE: offline++; break;
+ default: failed++; break;
+ }
}
- return ret;
+ if (microcode_ops->finalize_late_load)
+ microcode_ops->finalize_late_load(!updated);
+
+ if (!updated) {
+ /* Nothing changed. */
+ if (!failed && !timedout)
+ return 0;
+
+ nr_offl = cpumask_weight(&cpu_offline_mask);
+ if (offline < nr_offl) {
+ pr_warn("%u offline siblings did not respond.\n",
+ nr_offl - atomic_read(&offline_in_nmi));
+ return -EIO;
+ }
+ pr_err("update failed: %u CPUs failed %u CPUs timed out\n",
+ failed, timedout);
+ return -EIO;
+ }
+
+ if (!is_safe || failed || timedout)
+ add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
+
+ pr_info("load: updated on %u primary CPUs with %u siblings\n", updated, siblings);
+ if (failed || timedout) {
+ pr_err("load incomplete. %u CPUs timed out or failed\n",
+ num_online_cpus() - (updated + siblings));
+ }
+ pr_info("revision: 0x%x -> 0x%x\n", old_rev, boot_cpu_data.microcode);
+ microcode_check(&prev_info);
+
+ return updated + siblings == num_online_cpus() ? 0 : -EIO;
+}
+
+/*
+ * This function does two things:
+ *
+ * 1) Ensure that all required CPUs which are present and have been booted
+ * once are online.
+ *
+ * To pass this check, all primary threads must be online.
+ *
+ * If the microcode load is not safe against NMI then all SMT threads
+ * must be online as well because they still react to NMIs when they are
+ * soft-offlined and parked in one of the play_dead() variants. So if a
+ * NMI hits while the primary thread updates the microcode the resulting
+ * behaviour is undefined. The default play_dead() implementation on
+ * modern CPUs uses MWAIT, which is also not guaranteed to be safe
+ * against a microcode update which affects MWAIT.
+ *
+ * As soft-offlined CPUs still react on NMIs, the SMT sibling
+ * restriction can be lifted when the vendor driver signals to use NMI
+ * for rendezvous and the APIC provides a mechanism to send an NMI to a
+ * soft-offlined CPU. The soft-offlined CPUs are then able to
+ * participate in the rendezvous in a trivial stub handler.
+ *
+ * 2) Initialize the per CPU control structure and create a cpumask
+ * which contains "offline"; secondary threads, so they can be handled
+ * correctly by a control CPU.
+ */
+static bool setup_cpus(void)
+{
+ struct microcode_ctrl ctrl = { .ctrl = SCTRL_WAIT, .result = -1, };
+ bool allow_smt_offline;
+ unsigned int cpu;
+
+ allow_smt_offline = microcode_ops->nmi_safe ||
+ (microcode_ops->use_nmi && apic->nmi_to_offline_cpu);
+
+ cpumask_clear(&cpu_offline_mask);
+
+ for_each_cpu_and(cpu, cpu_present_mask, &cpus_booted_once_mask) {
+ /*
+ * Offline CPUs sit in one of the play_dead() functions
+ * with interrupts disabled, but they still react on NMIs
+ * and execute arbitrary code. Also MWAIT being updated
+ * while the offline CPU sits there is not necessarily safe
+ * on all CPU variants.
+ *
+ * Mark them in the offline_cpus mask which will be handled
+ * by CPU0 later in the update process.
+ *
+ * Ensure that the primary thread is online so that it is
+ * guaranteed that all cores are updated.
+ */
+ if (!cpu_online(cpu)) {
+ if (topology_is_primary_thread(cpu) || !allow_smt_offline) {
+ pr_err("CPU %u not online, loading aborted\n", cpu);
+ return false;
+ }
+ cpumask_set_cpu(cpu, &cpu_offline_mask);
+ per_cpu(ucode_ctrl, cpu) = ctrl;
+ continue;
+ }
+
+ /*
+ * Initialize the per CPU state. This is core scope for now,
+ * but prepared to take package or system scope into account.
+ */
+ ctrl.ctrl_cpu = cpumask_first(topology_sibling_cpumask(cpu));
+ per_cpu(ucode_ctrl, cpu) = ctrl;
+ }
+ return true;
+}
+
+static int load_late_locked(void)
+{
+ if (!setup_cpus())
+ return -EBUSY;
+
+ switch (microcode_ops->request_microcode_fw(0, &microcode_pdev->dev)) {
+ case UCODE_NEW:
+ return load_late_stop_cpus(false);
+ case UCODE_NEW_SAFE:
+ return load_late_stop_cpus(true);
+ case UCODE_NFOUND:
+ return -ENOENT;
+ default:
+ return -EBADFD;
+ }
}
static ssize_t reload_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
- enum ucode_state tmp_ret = UCODE_OK;
- int bsp = boot_cpu_data.cpu_index;
unsigned long val;
- ssize_t ret = 0;
+ ssize_t ret;
ret = kstrtoul(buf, 0, &val);
if (ret || val != 1)
return -EINVAL;
cpus_read_lock();
-
- ret = check_online_cpus();
- if (ret)
- goto put;
-
- tmp_ret = microcode_ops->request_microcode_fw(bsp, &microcode_pdev->dev);
- if (tmp_ret != UCODE_NEW)
- goto put;
-
- ret = microcode_reload_late();
-put:
+ ret = load_late_locked();
cpus_read_unlock();
- if (ret == 0)
- ret = size;
-
- add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
-
- return ret;
+ return ret ? : size;
}
static DEVICE_ATTR_WO(reload);
@@ -535,17 +753,6 @@ static void microcode_fini_cpu(int cpu)
microcode_ops->microcode_fini_cpu(cpu);
}
-static enum ucode_state microcode_init_cpu(int cpu)
-{
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
- memset(uci, 0, sizeof(*uci));
-
- microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
-
- return microcode_ops->apply_microcode(cpu);
-}
-
/**
* microcode_bsp_resume - Update boot CPU microcode during resume.
*/
@@ -564,19 +771,18 @@ static struct syscore_ops mc_syscore_ops = {
.resume = microcode_bsp_resume,
};
-static int mc_cpu_starting(unsigned int cpu)
-{
- enum ucode_state err = microcode_ops->apply_microcode(cpu);
-
- pr_debug("%s: CPU%d, err: %d\n", __func__, cpu, err);
-
- return err == UCODE_ERROR;
-}
-
static int mc_cpu_online(unsigned int cpu)
{
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
struct device *dev = get_cpu_device(cpu);
+ memset(uci, 0, sizeof(*uci));
+
+ microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
+ cpu_data(cpu).microcode = uci->cpu_sig.rev;
+ if (!cpu)
+ boot_cpu_data.microcode = uci->cpu_sig.rev;
+
if (sysfs_create_group(&dev->kobj, &mc_attr_group))
pr_err("Failed to create group for CPU%d\n", cpu);
return 0;
@@ -584,33 +790,13 @@ static int mc_cpu_online(unsigned int cpu)
static int mc_cpu_down_prep(unsigned int cpu)
{
- struct device *dev;
-
- dev = get_cpu_device(cpu);
+ struct device *dev = get_cpu_device(cpu);
microcode_fini_cpu(cpu);
-
- /* Suspend is in progress, only remove the interface */
sysfs_remove_group(&dev->kobj, &mc_attr_group);
- pr_debug("%s: CPU%d\n", __func__, cpu);
-
return 0;
}
-static void setup_online_cpu(struct work_struct *work)
-{
- int cpu = smp_processor_id();
- enum ucode_state err;
-
- err = microcode_init_cpu(cpu);
- if (err == UCODE_ERROR) {
- pr_err("Error applying microcode on CPU%d\n", cpu);
- return;
- }
-
- mc_cpu_online(cpu);
-}
-
static struct attribute *cpu_root_microcode_attrs[] = {
#ifdef CONFIG_MICROCODE_LATE_LOADING
&dev_attr_reload.attr,
@@ -642,6 +828,11 @@ static int __init microcode_init(void)
if (!microcode_ops)
return -ENODEV;
+ pr_info_once("Current revision: 0x%08x\n", (early_data.new_rev ?: early_data.old_rev));
+
+ if (early_data.new_rev)
+ pr_info_once("Updated early from: 0x%08x\n", early_data.old_rev);
+
microcode_pdev = platform_device_register_simple("microcode", -1, NULL, 0);
if (IS_ERR(microcode_pdev))
return PTR_ERR(microcode_pdev);
@@ -656,16 +847,9 @@ static int __init microcode_init(void)
}
}
- /* Do per-CPU setup */
- schedule_on_each_cpu(setup_online_cpu);
-
register_syscore_ops(&mc_syscore_ops);
- cpuhp_setup_state_nocalls(CPUHP_AP_MICROCODE_LOADER, "x86/microcode:starting",
- mc_cpu_starting, NULL);
- cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "x86/microcode:online",
- mc_cpu_online, mc_cpu_down_prep);
-
- pr_info("Microcode Update Driver: v%s.", DRIVER_VERSION);
+ cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/microcode:online",
+ mc_cpu_online, mc_cpu_down_prep);
return 0;
@@ -674,5 +858,4 @@ static int __init microcode_init(void)
return error;
}
-fs_initcall(save_microcode_in_initrd);
late_initcall(microcode_init);
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 94dd6af9c963..070426b9895f 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -14,7 +14,6 @@
#include <linux/earlycpio.h>
#include <linux/firmware.h>
#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
#include <linux/initrd.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -32,11 +31,14 @@
static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";
+#define UCODE_BSP_LOADED ((struct microcode_intel *)0x1UL)
+
/* Current microcode patch used in early patching on the APs. */
-static struct microcode_intel *intel_ucode_patch;
+static struct microcode_intel *ucode_patch_va __read_mostly;
+static struct microcode_intel *ucode_patch_late __read_mostly;
/* last level cache size per core */
-static int llc_size_per_core;
+static unsigned int llc_size_per_core __ro_after_init;
/* microcode format is extended from prescott processors */
struct extended_signature {
@@ -66,60 +68,52 @@ static inline unsigned int exttable_size(struct extended_sigtable *et)
return et->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE;
}
-int intel_cpu_collect_info(struct ucode_cpu_info *uci)
+void intel_collect_cpu_info(struct cpu_signature *sig)
{
- unsigned int val[2];
- unsigned int family, model;
- struct cpu_signature csig = { 0 };
- unsigned int eax, ebx, ecx, edx;
-
- memset(uci, 0, sizeof(*uci));
-
- eax = 0x00000001;
- ecx = 0;
- native_cpuid(&eax, &ebx, &ecx, &edx);
- csig.sig = eax;
+ sig->sig = cpuid_eax(1);
+ sig->pf = 0;
+ sig->rev = intel_get_microcode_revision();
- family = x86_family(eax);
- model = x86_model(eax);
+ if (x86_model(sig->sig) >= 5 || x86_family(sig->sig) > 6) {
+ unsigned int val[2];
- if (model >= 5 || family > 6) {
/* get processor flags from MSR 0x17 */
native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
- csig.pf = 1 << ((val[1] >> 18) & 7);
+ sig->pf = 1 << ((val[1] >> 18) & 7);
}
+}
+EXPORT_SYMBOL_GPL(intel_collect_cpu_info);
- csig.rev = intel_get_microcode_revision();
-
- uci->cpu_sig = csig;
+static inline bool cpu_signatures_match(struct cpu_signature *s1, unsigned int sig2,
+ unsigned int pf2)
+{
+ if (s1->sig != sig2)
+ return false;
- return 0;
+ /* Processor flags are either both 0 or they intersect. */
+ return ((!s1->pf && !pf2) || (s1->pf & pf2));
}
-EXPORT_SYMBOL_GPL(intel_cpu_collect_info);
-/*
- * Returns 1 if update has been found, 0 otherwise.
- */
-int intel_find_matching_signature(void *mc, unsigned int csig, int cpf)
+bool intel_find_matching_signature(void *mc, struct cpu_signature *sig)
{
struct microcode_header_intel *mc_hdr = mc;
- struct extended_sigtable *ext_hdr;
struct extended_signature *ext_sig;
+ struct extended_sigtable *ext_hdr;
int i;
- if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
- return 1;
+ if (cpu_signatures_match(sig, mc_hdr->sig, mc_hdr->pf))
+ return true;
/* Look for ext. headers: */
if (get_totalsize(mc_hdr) <= intel_microcode_get_datasize(mc_hdr) + MC_HEADER_SIZE)
- return 0;
+ return false;
ext_hdr = mc + intel_microcode_get_datasize(mc_hdr) + MC_HEADER_SIZE;
ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
for (i = 0; i < ext_hdr->count; i++) {
- if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
- return 1;
+ if (cpu_signatures_match(sig, ext_sig->sig, ext_sig->pf))
+ return true;
ext_sig++;
}
return 0;
@@ -240,264 +234,91 @@ int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type)
}
EXPORT_SYMBOL_GPL(intel_microcode_sanity_check);
-/*
- * Returns 1 if update has been found, 0 otherwise.
- */
-static int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev)
+static void update_ucode_pointer(struct microcode_intel *mc)
{
- struct microcode_header_intel *mc_hdr = mc;
-
- if (mc_hdr->rev <= new_rev)
- return 0;
-
- return intel_find_matching_signature(mc, csig, cpf);
-}
-
-static struct ucode_patch *memdup_patch(void *data, unsigned int size)
-{
- struct ucode_patch *p;
-
- p = kzalloc(sizeof(struct ucode_patch), GFP_KERNEL);
- if (!p)
- return NULL;
-
- p->data = kmemdup(data, size, GFP_KERNEL);
- if (!p->data) {
- kfree(p);
- return NULL;
- }
-
- return p;
-}
-
-static void save_microcode_patch(struct ucode_cpu_info *uci, void *data, unsigned int size)
-{
- struct microcode_header_intel *mc_hdr, *mc_saved_hdr;
- struct ucode_patch *iter, *tmp, *p = NULL;
- bool prev_found = false;
- unsigned int sig, pf;
-
- mc_hdr = (struct microcode_header_intel *)data;
-
- list_for_each_entry_safe(iter, tmp, &microcode_cache, plist) {
- mc_saved_hdr = (struct microcode_header_intel *)iter->data;
- sig = mc_saved_hdr->sig;
- pf = mc_saved_hdr->pf;
-
- if (intel_find_matching_signature(data, sig, pf)) {
- prev_found = true;
-
- if (mc_hdr->rev <= mc_saved_hdr->rev)
- continue;
-
- p = memdup_patch(data, size);
- if (!p)
- pr_err("Error allocating buffer %p\n", data);
- else {
- list_replace(&iter->plist, &p->plist);
- kfree(iter->data);
- kfree(iter);
- }
- }
- }
+ kvfree(ucode_patch_va);
/*
- * There weren't any previous patches found in the list cache; save the
- * newly found.
+ * Save the virtual address for early loading and for eventual free
+ * on late loading.
*/
- if (!prev_found) {
- p = memdup_patch(data, size);
- if (!p)
- pr_err("Error allocating buffer for %p\n", data);
- else
- list_add_tail(&p->plist, &microcode_cache);
- }
-
- if (!p)
- return;
+ ucode_patch_va = mc;
+}
- if (!intel_find_matching_signature(p->data, uci->cpu_sig.sig, uci->cpu_sig.pf))
- return;
+static void save_microcode_patch(struct microcode_intel *patch)
+{
+ unsigned int size = get_totalsize(&patch->hdr);
+ struct microcode_intel *mc;
- /*
- * Save for early loading. On 32-bit, that needs to be a physical
- * address as the APs are running from physical addresses, before
- * paging has been enabled.
- */
- if (IS_ENABLED(CONFIG_X86_32))
- intel_ucode_patch = (struct microcode_intel *)__pa_nodebug(p->data);
+ mc = kvmemdup(patch, size, GFP_KERNEL);
+ if (mc)
+ update_ucode_pointer(mc);
else
- intel_ucode_patch = p->data;
+ pr_err("Unable to allocate microcode memory size: %u\n", size);
}
-/*
- * Get microcode matching with BSP's model. Only CPUs with the same model as
- * BSP can stay in the platform.
- */
-static struct microcode_intel *
-scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
+/* Scan blob for microcode matching the boot CPUs family, model, stepping */
+static __init struct microcode_intel *scan_microcode(void *data, size_t size,
+ struct ucode_cpu_info *uci,
+ bool save)
{
struct microcode_header_intel *mc_header;
struct microcode_intel *patch = NULL;
+ u32 cur_rev = uci->cpu_sig.rev;
unsigned int mc_size;
- while (size) {
- if (size < sizeof(struct microcode_header_intel))
- break;
-
+ for (; size >= sizeof(struct microcode_header_intel); size -= mc_size, data += mc_size) {
mc_header = (struct microcode_header_intel *)data;
mc_size = get_totalsize(mc_header);
- if (!mc_size ||
- mc_size > size ||
+ if (!mc_size || mc_size > size ||
intel_microcode_sanity_check(data, false, MC_HEADER_TYPE_MICROCODE) < 0)
break;
- size -= mc_size;
-
- if (!intel_find_matching_signature(data, uci->cpu_sig.sig,
- uci->cpu_sig.pf)) {
- data += mc_size;
+ if (!intel_find_matching_signature(data, &uci->cpu_sig))
continue;
- }
+ /*
+ * For saving the early microcode, find the matching revision which
+ * was loaded on the BSP.
+ *
+ * On the BSP during early boot, find a newer revision than
+ * actually loaded in the CPU.
+ */
if (save) {
- save_microcode_patch(uci, data, mc_size);
- goto next;
- }
-
-
- if (!patch) {
- if (!has_newer_microcode(data,
- uci->cpu_sig.sig,
- uci->cpu_sig.pf,
- uci->cpu_sig.rev))
- goto next;
-
- } else {
- struct microcode_header_intel *phdr = &patch->hdr;
-
- if (!has_newer_microcode(data,
- phdr->sig,
- phdr->pf,
- phdr->rev))
- goto next;
+ if (cur_rev != mc_header->rev)
+ continue;
+ } else if (cur_rev >= mc_header->rev) {
+ continue;
}
- /* We have a newer patch, save it. */
patch = data;
-
-next:
- data += mc_size;
- }
-
- if (size)
- return NULL;
-
- return patch;
-}
-
-static bool load_builtin_intel_microcode(struct cpio_data *cp)
-{
- unsigned int eax = 1, ebx, ecx = 0, edx;
- struct firmware fw;
- char name[30];
-
- if (IS_ENABLED(CONFIG_X86_32))
- return false;
-
- native_cpuid(&eax, &ebx, &ecx, &edx);
-
- sprintf(name, "intel-ucode/%02x-%02x-%02x",
- x86_family(eax), x86_model(eax), x86_stepping(eax));
-
- if (firmware_request_builtin(&fw, name)) {
- cp->size = fw.size;
- cp->data = (void *)fw.data;
- return true;
+ cur_rev = mc_header->rev;
}
- return false;
+ return size ? NULL : patch;
}
-static void print_ucode_info(int old_rev, int new_rev, unsigned int date)
+static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci,
+ struct microcode_intel *mc,
+ u32 *cur_rev)
{
- pr_info_once("updated early: 0x%x -> 0x%x, date = %04x-%02x-%02x\n",
- old_rev,
- new_rev,
- date & 0xffff,
- date >> 24,
- (date >> 16) & 0xff);
-}
-
-#ifdef CONFIG_X86_32
-
-static int delay_ucode_info;
-static int current_mc_date;
-static int early_old_rev;
-
-/*
- * Print early updated ucode info after printk works. This is delayed info dump.
- */
-void show_ucode_info_early(void)
-{
- struct ucode_cpu_info uci;
-
- if (delay_ucode_info) {
- intel_cpu_collect_info(&uci);
- print_ucode_info(early_old_rev, uci.cpu_sig.rev, current_mc_date);
- delay_ucode_info = 0;
- }
-}
-
-/*
- * At this point, we can not call printk() yet. Delay printing microcode info in
- * show_ucode_info_early() until printk() works.
- */
-static void print_ucode(int old_rev, int new_rev, int date)
-{
- int *delay_ucode_info_p;
- int *current_mc_date_p;
- int *early_old_rev_p;
-
- delay_ucode_info_p = (int *)__pa_nodebug(&delay_ucode_info);
- current_mc_date_p = (int *)__pa_nodebug(&current_mc_date);
- early_old_rev_p = (int *)__pa_nodebug(&early_old_rev);
-
- *delay_ucode_info_p = 1;
- *current_mc_date_p = date;
- *early_old_rev_p = old_rev;
-}
-#else
-
-static inline void print_ucode(int old_rev, int new_rev, int date)
-{
- print_ucode_info(old_rev, new_rev, date);
-}
-#endif
-
-static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
-{
- struct microcode_intel *mc;
- u32 rev, old_rev;
+ u32 rev;
- mc = uci->mc;
if (!mc)
- return 0;
+ return UCODE_NFOUND;
/*
* Save us the MSR write below - which is a particular expensive
* operation - when the other hyperthread has updated the microcode
* already.
*/
- rev = intel_get_microcode_revision();
- if (rev >= mc->hdr.rev) {
- uci->cpu_sig.rev = rev;
+ *cur_rev = intel_get_microcode_revision();
+ if (*cur_rev >= mc->hdr.rev) {
+ uci->cpu_sig.rev = *cur_rev;
return UCODE_OK;
}
- old_rev = rev;
-
/*
* Writeback and invalidate caches before updating microcode to avoid
* internal issues depending on what the microcode is updating.
@@ -509,247 +330,179 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
rev = intel_get_microcode_revision();
if (rev != mc->hdr.rev)
- return -1;
+ return UCODE_ERROR;
uci->cpu_sig.rev = rev;
+ return UCODE_UPDATED;
+}
- if (early)
- print_ucode(old_rev, uci->cpu_sig.rev, mc->hdr.date);
- else
- print_ucode_info(old_rev, uci->cpu_sig.rev, mc->hdr.date);
+static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci)
+{
+ struct microcode_intel *mc = uci->mc;
+ u32 cur_rev;
- return 0;
+ return __apply_microcode(uci, mc, &cur_rev);
}
-int __init save_microcode_in_initrd_intel(void)
+static __init bool load_builtin_intel_microcode(struct cpio_data *cp)
{
- struct ucode_cpu_info uci;
- struct cpio_data cp;
-
- /*
- * initrd is going away, clear patch ptr. We will scan the microcode one
- * last time before jettisoning and save a patch, if found. Then we will
- * update that pointer too, with a stable patch address to use when
- * resuming the cores.
- */
- intel_ucode_patch = NULL;
+ unsigned int eax = 1, ebx, ecx = 0, edx;
+ struct firmware fw;
+ char name[30];
- if (!load_builtin_intel_microcode(&cp))
- cp = find_microcode_in_initrd(ucode_path, false);
+ if (IS_ENABLED(CONFIG_X86_32))
+ return false;
- if (!(cp.data && cp.size))
- return 0;
+ native_cpuid(&eax, &ebx, &ecx, &edx);
- intel_cpu_collect_info(&uci);
+ sprintf(name, "intel-ucode/%02x-%02x-%02x",
+ x86_family(eax), x86_model(eax), x86_stepping(eax));
- scan_microcode(cp.data, cp.size, &uci, true);
- return 0;
+ if (firmware_request_builtin(&fw, name)) {
+ cp->size = fw.size;
+ cp->data = (void *)fw.data;
+ return true;
+ }
+ return false;
}
-/*
- * @res_patch, output: a pointer to the patch we found.
- */
-static struct microcode_intel *__load_ucode_intel(struct ucode_cpu_info *uci)
+static __init struct microcode_intel *get_microcode_blob(struct ucode_cpu_info *uci, bool save)
{
- static const char *path;
struct cpio_data cp;
- bool use_pa;
-
- if (IS_ENABLED(CONFIG_X86_32)) {
- path = (const char *)__pa_nodebug(ucode_path);
- use_pa = true;
- } else {
- path = ucode_path;
- use_pa = false;
- }
- /* try built-in microcode first */
if (!load_builtin_intel_microcode(&cp))
- cp = find_microcode_in_initrd(path, use_pa);
+ cp = find_microcode_in_initrd(ucode_path);
if (!(cp.data && cp.size))
return NULL;
- intel_cpu_collect_info(uci);
+ intel_collect_cpu_info(&uci->cpu_sig);
- return scan_microcode(cp.data, cp.size, uci, false);
+ return scan_microcode(cp.data, cp.size, uci, save);
}
-void __init load_ucode_intel_bsp(void)
+/*
+ * Invoked from an early init call to save the microcode blob which was
+ * selected during early boot when mm was not usable. The microcode must be
+ * saved because initrd is going away. It's an early init call so the APs
+ * just can use the pointer and do not have to scan initrd/builtin firmware
+ * again.
+ */
+static int __init save_builtin_microcode(void)
{
- struct microcode_intel *patch;
struct ucode_cpu_info uci;
- patch = __load_ucode_intel(&uci);
- if (!patch)
- return;
+ if (xchg(&ucode_patch_va, NULL) != UCODE_BSP_LOADED)
+ return 0;
- uci.mc = patch;
+ if (dis_ucode_ldr || boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+ return 0;
- apply_microcode_early(&uci, true);
+ uci.mc = get_microcode_blob(&uci, true);
+ if (uci.mc)
+ save_microcode_patch(uci.mc);
+ return 0;
}
+early_initcall(save_builtin_microcode);
-void load_ucode_intel_ap(void)
+/* Load microcode on BSP from initrd or builtin blobs */
+void __init load_ucode_intel_bsp(struct early_load_data *ed)
{
- struct microcode_intel *patch, **iup;
struct ucode_cpu_info uci;
- if (IS_ENABLED(CONFIG_X86_32))
- iup = (struct microcode_intel **) __pa_nodebug(&intel_ucode_patch);
- else
- iup = &intel_ucode_patch;
+ ed->old_rev = intel_get_microcode_revision();
- if (!*iup) {
- patch = __load_ucode_intel(&uci);
- if (!patch)
- return;
+ uci.mc = get_microcode_blob(&uci, false);
+ if (uci.mc && apply_microcode_early(&uci) == UCODE_UPDATED)
+ ucode_patch_va = UCODE_BSP_LOADED;
- *iup = patch;
- }
-
- uci.mc = *iup;
-
- apply_microcode_early(&uci, true);
+ ed->new_rev = uci.cpu_sig.rev;
}
-static struct microcode_intel *find_patch(struct ucode_cpu_info *uci)
+void load_ucode_intel_ap(void)
{
- struct microcode_header_intel *phdr;
- struct ucode_patch *iter, *tmp;
-
- list_for_each_entry_safe(iter, tmp, &microcode_cache, plist) {
-
- phdr = (struct microcode_header_intel *)iter->data;
-
- if (phdr->rev <= uci->cpu_sig.rev)
- continue;
-
- if (!intel_find_matching_signature(phdr,
- uci->cpu_sig.sig,
- uci->cpu_sig.pf))
- continue;
+ struct ucode_cpu_info uci;
- return iter->data;
- }
- return NULL;
+ uci.mc = ucode_patch_va;
+ if (uci.mc)
+ apply_microcode_early(&uci);
}
+/* Reload microcode on resume */
void reload_ucode_intel(void)
{
- struct microcode_intel *p;
- struct ucode_cpu_info uci;
-
- intel_cpu_collect_info(&uci);
+ struct ucode_cpu_info uci = { .mc = ucode_patch_va, };
- p = find_patch(&uci);
- if (!p)
- return;
-
- uci.mc = p;
-
- apply_microcode_early(&uci, false);
+ if (uci.mc)
+ apply_microcode_early(&uci);
}
static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
{
- struct cpuinfo_x86 *c = &cpu_data(cpu_num);
- unsigned int val[2];
-
- memset(csig, 0, sizeof(*csig));
-
- csig->sig = cpuid_eax(0x00000001);
-
- if ((c->x86_model >= 5) || (c->x86 > 6)) {
- /* get processor flags from MSR 0x17 */
- rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
- csig->pf = 1 << ((val[1] >> 18) & 7);
- }
-
- csig->rev = c->microcode;
-
+ intel_collect_cpu_info(csig);
return 0;
}
-static enum ucode_state apply_microcode_intel(int cpu)
+static enum ucode_state apply_microcode_late(int cpu)
{
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
- struct cpuinfo_x86 *c = &cpu_data(cpu);
- bool bsp = c->cpu_index == boot_cpu_data.cpu_index;
- struct microcode_intel *mc;
+ struct microcode_intel *mc = ucode_patch_late;
enum ucode_state ret;
- static int prev_rev;
- u32 rev;
+ u32 cur_rev;
- /* We should bind the task to the CPU */
- if (WARN_ON(raw_smp_processor_id() != cpu))
+ if (WARN_ON_ONCE(smp_processor_id() != cpu))
return UCODE_ERROR;
- /* Look for a newer patch in our cache: */
- mc = find_patch(uci);
- if (!mc) {
- mc = uci->mc;
- if (!mc)
- return UCODE_NFOUND;
- }
+ ret = __apply_microcode(uci, mc, &cur_rev);
+ if (ret != UCODE_UPDATED && ret != UCODE_OK)
+ return ret;
- /*
- * Save us the MSR write below - which is a particular expensive
- * operation - when the other hyperthread has updated the microcode
- * already.
- */
- rev = intel_get_microcode_revision();
- if (rev >= mc->hdr.rev) {
- ret = UCODE_OK;
- goto out;
+ if (!cpu && uci->cpu_sig.rev != cur_rev) {
+ pr_info("Updated to revision 0x%x, date = %04x-%02x-%02x\n",
+ uci->cpu_sig.rev, mc->hdr.date & 0xffff, mc->hdr.date >> 24,
+ (mc->hdr.date >> 16) & 0xff);
}
- /*
- * Writeback and invalidate caches before updating microcode to avoid
- * internal issues depending on what the microcode is updating.
- */
- native_wbinvd();
+ cpu_data(cpu).microcode = uci->cpu_sig.rev;
+ if (!cpu)
+ boot_cpu_data.microcode = uci->cpu_sig.rev;
- /* write microcode via MSR 0x79 */
- wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
+ return ret;
+}
- rev = intel_get_microcode_revision();
+static bool ucode_validate_minrev(struct microcode_header_intel *mc_header)
+{
+ int cur_rev = boot_cpu_data.microcode;
- if (rev != mc->hdr.rev) {
- pr_err("CPU%d update to revision 0x%x failed\n",
- cpu, mc->hdr.rev);
- return UCODE_ERROR;
+ /*
+ * When late-loading, ensure the header declares a minimum revision
+ * required to perform a late-load. The previously reserved field
+ * is 0 in older microcode blobs.
+ */
+ if (!mc_header->min_req_ver) {
+ pr_info("Unsafe microcode update: Microcode header does not specify a required min version\n");
+ return false;
}
- if (bsp && rev != prev_rev) {
- pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",
- rev,
- mc->hdr.date & 0xffff,
- mc->hdr.date >> 24,
- (mc->hdr.date >> 16) & 0xff);
- prev_rev = rev;
+ /*
+ * Check whether the current revision is either greater or equal to
+ * to the minimum revision specified in the header.
+ */
+ if (cur_rev < mc_header->min_req_ver) {
+ pr_info("Unsafe microcode update: Current revision 0x%x too old\n", cur_rev);
+ pr_info("Current should be at 0x%x or higher. Use early loading instead\n", mc_header->min_req_ver);
+ return false;
}
-
- ret = UCODE_UPDATED;
-
-out:
- uci->cpu_sig.rev = rev;
- c->microcode = rev;
-
- /* Update boot_cpu_data's revision too, if we're on the BSP: */
- if (bsp)
- boot_cpu_data.microcode = rev;
-
- return ret;
+ return true;
}
-static enum ucode_state generic_load_microcode(int cpu, struct iov_iter *iter)
+static enum ucode_state parse_microcode_blobs(int cpu, struct iov_iter *iter)
{
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
- unsigned int curr_mc_size = 0, new_mc_size = 0;
- enum ucode_state ret = UCODE_OK;
- int new_rev = uci->cpu_sig.rev;
+ bool is_safe, new_is_safe = false;
+ int cur_rev = uci->cpu_sig.rev;
+ unsigned int curr_mc_size = 0;
u8 *new_mc = NULL, *mc = NULL;
- unsigned int csig, cpf;
while (iov_iter_count(iter)) {
struct microcode_header_intel mc_header;
@@ -758,68 +511,66 @@ static enum ucode_state generic_load_microcode(int cpu, struct iov_iter *iter)
if (!copy_from_iter_full(&mc_header, sizeof(mc_header), iter)) {
pr_err("error! Truncated or inaccessible header in microcode data file\n");
- break;
+ goto fail;
}
mc_size = get_totalsize(&mc_header);
if (mc_size < sizeof(mc_header)) {
pr_err("error! Bad data in microcode data file (totalsize too small)\n");
- break;
+ goto fail;
}
data_size = mc_size - sizeof(mc_header);
if (data_size > iov_iter_count(iter)) {
pr_err("error! Bad data in microcode data file (truncated file?)\n");
- break;
+ goto fail;
}
/* For performance reasons, reuse mc area when possible */
if (!mc || mc_size > curr_mc_size) {
- vfree(mc);
- mc = vmalloc(mc_size);
+ kvfree(mc);
+ mc = kvmalloc(mc_size, GFP_KERNEL);
if (!mc)
- break;
+ goto fail;
curr_mc_size = mc_size;
}
memcpy(mc, &mc_header, sizeof(mc_header));
data = mc + sizeof(mc_header);
if (!copy_from_iter_full(data, data_size, iter) ||
- intel_microcode_sanity_check(mc, true, MC_HEADER_TYPE_MICROCODE) < 0) {
- break;
- }
+ intel_microcode_sanity_check(mc, true, MC_HEADER_TYPE_MICROCODE) < 0)
+ goto fail;
- csig = uci->cpu_sig.sig;
- cpf = uci->cpu_sig.pf;
- if (has_newer_microcode(mc, csig, cpf, new_rev)) {
- vfree(new_mc);
- new_rev = mc_header.rev;
- new_mc = mc;
- new_mc_size = mc_size;
- mc = NULL; /* trigger new vmalloc */
- ret = UCODE_NEW;
- }
- }
+ if (cur_rev >= mc_header.rev)
+ continue;
- vfree(mc);
+ if (!intel_find_matching_signature(mc, &uci->cpu_sig))
+ continue;
- if (iov_iter_count(iter)) {
- vfree(new_mc);
- return UCODE_ERROR;
+ is_safe = ucode_validate_minrev(&mc_header);
+ if (force_minrev && !is_safe)
+ continue;
+
+ kvfree(new_mc);
+ cur_rev = mc_header.rev;
+ new_mc = mc;
+ new_is_safe = is_safe;
+ mc = NULL;
}
+ if (iov_iter_count(iter))
+ goto fail;
+
+ kvfree(mc);
if (!new_mc)
return UCODE_NFOUND;
- vfree(uci->mc);
- uci->mc = (struct microcode_intel *)new_mc;
-
- /* Save for CPU hotplug */
- save_microcode_patch(uci, new_mc, new_mc_size);
+ ucode_patch_late = (struct microcode_intel *)new_mc;
+ return new_is_safe ? UCODE_NEW_SAFE : UCODE_NEW;
- pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
- cpu, new_rev, uci->cpu_sig.rev);
-
- return ret;
+fail:
+ kvfree(mc);
+ kvfree(new_mc);
+ return UCODE_ERROR;
}
static bool is_blacklisted(unsigned int cpu)
@@ -868,26 +619,36 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device)
kvec.iov_base = (void *)firmware->data;
kvec.iov_len = firmware->size;
iov_iter_kvec(&iter, ITER_SOURCE, &kvec, 1, firmware->size);
- ret = generic_load_microcode(cpu, &iter);
+ ret = parse_microcode_blobs(cpu, &iter);
release_firmware(firmware);
return ret;
}
+static void finalize_late_load(int result)
+{
+ if (!result)
+ update_ucode_pointer(ucode_patch_late);
+ else
+ kvfree(ucode_patch_late);
+ ucode_patch_late = NULL;
+}
+
static struct microcode_ops microcode_intel_ops = {
- .request_microcode_fw = request_microcode_fw,
- .collect_cpu_info = collect_cpu_info,
- .apply_microcode = apply_microcode_intel,
+ .request_microcode_fw = request_microcode_fw,
+ .collect_cpu_info = collect_cpu_info,
+ .apply_microcode = apply_microcode_late,
+ .finalize_late_load = finalize_late_load,
+ .use_nmi = IS_ENABLED(CONFIG_X86_64),
};
-static int __init calc_llc_size_per_core(struct cpuinfo_x86 *c)
+static __init void calc_llc_size_per_core(struct cpuinfo_x86 *c)
{
u64 llc_size = c->x86_cache_size * 1024ULL;
do_div(llc_size, c->x86_max_cores);
-
- return (int)llc_size;
+ llc_size_per_core = (unsigned int)llc_size;
}
struct microcode_ops * __init init_intel_microcode(void)
@@ -900,7 +661,7 @@ struct microcode_ops * __init init_intel_microcode(void)
return NULL;
}
- llc_size_per_core = calc_llc_size_per_core(c);
+ calc_llc_size_per_core(c);
return &microcode_intel_ops;
}
diff --git a/arch/x86/kernel/cpu/microcode/internal.h b/arch/x86/kernel/cpu/microcode/internal.h
index bf883aa71233..21776c529fa9 100644
--- a/arch/x86/kernel/cpu/microcode/internal.h
+++ b/arch/x86/kernel/cpu/microcode/internal.h
@@ -8,43 +8,43 @@
#include <asm/cpu.h>
#include <asm/microcode.h>
-struct ucode_patch {
- struct list_head plist;
- void *data; /* Intel uses only this one */
- unsigned int size;
- u32 patch_id;
- u16 equiv_cpu;
-};
-
-extern struct list_head microcode_cache;
-
struct device;
enum ucode_state {
UCODE_OK = 0,
UCODE_NEW,
+ UCODE_NEW_SAFE,
UCODE_UPDATED,
UCODE_NFOUND,
UCODE_ERROR,
+ UCODE_TIMEOUT,
+ UCODE_OFFLINE,
};
struct microcode_ops {
enum ucode_state (*request_microcode_fw)(int cpu, struct device *dev);
-
void (*microcode_fini_cpu)(int cpu);
/*
- * The generic 'microcode_core' part guarantees that
- * the callbacks below run on a target cpu when they
- * are being called.
+ * The generic 'microcode_core' part guarantees that the callbacks
+ * below run on a target CPU when they are being called.
* See also the "Synchronization" section in microcode_core.c.
*/
- enum ucode_state (*apply_microcode)(int cpu);
- int (*collect_cpu_info)(int cpu, struct cpu_signature *csig);
+ enum ucode_state (*apply_microcode)(int cpu);
+ int (*collect_cpu_info)(int cpu, struct cpu_signature *csig);
+ void (*finalize_late_load)(int result);
+ unsigned int nmi_safe : 1,
+ use_nmi : 1;
+};
+
+struct early_load_data {
+ u32 old_rev;
+ u32 new_rev;
};
+extern struct early_load_data early_data;
extern struct ucode_cpu_info ucode_cpu_info[];
-struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa);
+struct cpio_data find_microcode_in_initrd(const char *path);
#define MAX_UCODE_COUNT 128
@@ -94,20 +94,19 @@ static inline unsigned int x86_cpuid_family(void)
return x86_family(eax);
}
-extern bool initrd_gone;
+extern bool dis_ucode_ldr;
+extern bool force_minrev;
#ifdef CONFIG_CPU_SUP_AMD
-void load_ucode_amd_bsp(unsigned int family);
+void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family);
void load_ucode_amd_ap(unsigned int family);
-void load_ucode_amd_early(unsigned int cpuid_1_eax);
int save_microcode_in_initrd_amd(unsigned int family);
void reload_ucode_amd(unsigned int cpu);
struct microcode_ops *init_amd_microcode(void);
void exit_amd_microcode(void);
#else /* CONFIG_CPU_SUP_AMD */
-static inline void load_ucode_amd_bsp(unsigned int family) { }
+static inline void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family) { }
static inline void load_ucode_amd_ap(unsigned int family) { }
-static inline void load_ucode_amd_early(unsigned int family) { }
static inline int save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
static inline void reload_ucode_amd(unsigned int cpu) { }
static inline struct microcode_ops *init_amd_microcode(void) { return NULL; }
@@ -115,15 +114,13 @@ static inline void exit_amd_microcode(void) { }
#endif /* !CONFIG_CPU_SUP_AMD */
#ifdef CONFIG_CPU_SUP_INTEL
-void load_ucode_intel_bsp(void);
+void load_ucode_intel_bsp(struct early_load_data *ed);
void load_ucode_intel_ap(void);
-int save_microcode_in_initrd_intel(void);
void reload_ucode_intel(void);
struct microcode_ops *init_intel_microcode(void);
#else /* CONFIG_CPU_SUP_INTEL */
-static inline void load_ucode_intel_bsp(void) { }
+static inline void load_ucode_intel_bsp(struct early_load_data *ed) { }
static inline void load_ucode_intel_ap(void) { }
-static inline int save_microcode_in_initrd_intel(void) { return -EINVAL; }
static inline void reload_ucode_intel(void) { }
static inline struct microcode_ops *init_intel_microcode(void) { return NULL; }
#endif /* !CONFIG_CPU_SUP_INTEL */
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index e6bba12c759c..01fa06dd06b6 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -262,11 +262,14 @@ static uint32_t __init ms_hyperv_platform(void)
static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
{
static atomic_t nmi_cpu = ATOMIC_INIT(-1);
+ unsigned int old_cpu, this_cpu;
if (!unknown_nmi_panic)
return NMI_DONE;
- if (atomic_cmpxchg(&nmi_cpu, -1, raw_smp_processor_id()) != -1)
+ old_cpu = -1;
+ this_cpu = raw_smp_processor_id();
+ if (!atomic_try_cmpxchg(&nmi_cpu, &old_cpu, this_cpu))
return NMI_HANDLED;
return NMI_DONE;
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 31c0e68f6227..e65fae63660e 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -20,13 +20,13 @@ static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c,
unsigned int cpu)
{
#ifdef CONFIG_SMP
- seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
+ seq_printf(m, "physical id\t: %d\n", c->topo.pkg_id);
seq_printf(m, "siblings\t: %d\n",
cpumask_weight(topology_core_cpumask(cpu)));
- seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
+ seq_printf(m, "core id\t\t: %d\n", c->topo.core_id);
seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
- seq_printf(m, "apicid\t\t: %d\n", c->apicid);
- seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid);
+ seq_printf(m, "apicid\t\t: %d\n", c->topo.apicid);
+ seq_printf(m, "initial apicid\t: %d\n", c->topo.initial_apicid);
#endif
}
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index 030d3b409768..19e0681f0435 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -152,6 +152,7 @@ static inline void cache_alloc_hsw_probe(void)
r->cache.cbm_len = 20;
r->cache.shareable_bits = 0xc0000;
r->cache.min_cbm_bits = 2;
+ r->cache.arch_has_sparse_bitmasks = false;
r->alloc_capable = true;
rdt_alloc_capable = true;
@@ -267,15 +268,18 @@ static void rdt_get_cache_alloc_cfg(int idx, struct rdt_resource *r)
{
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
union cpuid_0x10_1_eax eax;
+ union cpuid_0x10_x_ecx ecx;
union cpuid_0x10_x_edx edx;
- u32 ebx, ecx;
+ u32 ebx;
- cpuid_count(0x00000010, idx, &eax.full, &ebx, &ecx, &edx.full);
+ cpuid_count(0x00000010, idx, &eax.full, &ebx, &ecx.full, &edx.full);
hw_res->num_closid = edx.split.cos_max + 1;
r->cache.cbm_len = eax.split.cbm_len + 1;
r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1;
r->cache.shareable_bits = ebx & r->default_ctrl;
r->data_width = (r->cache.cbm_len + 3) / 4;
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+ r->cache.arch_has_sparse_bitmasks = ecx.split.noncont;
r->alloc_capable = true;
}
@@ -872,7 +876,6 @@ static __init void rdt_init_res_defs_intel(void)
if (r->rid == RDT_RESOURCE_L3 ||
r->rid == RDT_RESOURCE_L2) {
- r->cache.arch_has_sparse_bitmaps = false;
r->cache.arch_has_per_cpu_cfg = false;
r->cache.min_cbm_bits = 1;
} else if (r->rid == RDT_RESOURCE_MBA) {
@@ -892,7 +895,7 @@ static __init void rdt_init_res_defs_amd(void)
if (r->rid == RDT_RESOURCE_L3 ||
r->rid == RDT_RESOURCE_L2) {
- r->cache.arch_has_sparse_bitmaps = true;
+ r->cache.arch_has_sparse_bitmasks = true;
r->cache.arch_has_per_cpu_cfg = true;
r->cache.min_cbm_bits = 0;
} else if (r->rid == RDT_RESOURCE_MBA) {
diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
index b44c487727d4..beccb0e87ba7 100644
--- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
+++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
@@ -87,10 +87,12 @@ int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s,
/*
* Check whether a cache bit mask is valid.
- * For Intel the SDM says:
- * Please note that all (and only) contiguous '1' combinations
- * are allowed (e.g. FFFFH, 0FF0H, 003CH, etc.).
- * Additionally Haswell requires at least two bits set.
+ * On Intel CPUs, non-contiguous 1s value support is indicated by CPUID:
+ * - CPUID.0x10.1:ECX[3]: L3 non-contiguous 1s value supported if 1
+ * - CPUID.0x10.2:ECX[3]: L2 non-contiguous 1s value supported if 1
+ *
+ * Haswell does not support a non-contiguous 1s value and additionally
+ * requires at least two bits set.
* AMD allows non-contiguous bitmasks.
*/
static bool cbm_validate(char *buf, u32 *data, struct rdt_resource *r)
@@ -113,8 +115,8 @@ static bool cbm_validate(char *buf, u32 *data, struct rdt_resource *r)
first_bit = find_first_bit(&val, cbm_len);
zero_bit = find_next_zero_bit(&val, cbm_len, first_bit);
- /* Are non-contiguous bitmaps allowed? */
- if (!r->cache.arch_has_sparse_bitmaps &&
+ /* Are non-contiguous bitmasks allowed? */
+ if (!r->cache.arch_has_sparse_bitmasks &&
(find_next_bit(&val, cbm_len, zero_bit) < cbm_len)) {
rdt_last_cmd_printf("The mask %lx has non-consecutive 1-bits\n", val);
return false;
diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
index 85ceaf9a31ac..a4f1aa15f0a2 100644
--- a/arch/x86/kernel/cpu/resctrl/internal.h
+++ b/arch/x86/kernel/cpu/resctrl/internal.h
@@ -59,6 +59,7 @@ struct rdt_fs_context {
bool enable_cdpl2;
bool enable_cdpl3;
bool enable_mba_mbps;
+ bool enable_debug;
};
static inline struct rdt_fs_context *rdt_fc2context(struct fs_context *fc)
@@ -243,18 +244,17 @@ struct rdtgroup {
*/
#define RFTYPE_INFO BIT(0)
#define RFTYPE_BASE BIT(1)
-#define RF_CTRLSHIFT 4
-#define RF_MONSHIFT 5
-#define RF_TOPSHIFT 6
-#define RFTYPE_CTRL BIT(RF_CTRLSHIFT)
-#define RFTYPE_MON BIT(RF_MONSHIFT)
-#define RFTYPE_TOP BIT(RF_TOPSHIFT)
+#define RFTYPE_CTRL BIT(4)
+#define RFTYPE_MON BIT(5)
+#define RFTYPE_TOP BIT(6)
#define RFTYPE_RES_CACHE BIT(8)
#define RFTYPE_RES_MB BIT(9)
-#define RF_CTRL_INFO (RFTYPE_INFO | RFTYPE_CTRL)
-#define RF_MON_INFO (RFTYPE_INFO | RFTYPE_MON)
-#define RF_TOP_INFO (RFTYPE_INFO | RFTYPE_TOP)
-#define RF_CTRL_BASE (RFTYPE_BASE | RFTYPE_CTRL)
+#define RFTYPE_DEBUG BIT(10)
+#define RFTYPE_CTRL_INFO (RFTYPE_INFO | RFTYPE_CTRL)
+#define RFTYPE_MON_INFO (RFTYPE_INFO | RFTYPE_MON)
+#define RFTYPE_TOP_INFO (RFTYPE_INFO | RFTYPE_TOP)
+#define RFTYPE_CTRL_BASE (RFTYPE_BASE | RFTYPE_CTRL)
+#define RFTYPE_MON_BASE (RFTYPE_BASE | RFTYPE_MON)
/* List of all resource groups */
extern struct list_head rdt_all_groups;
@@ -270,7 +270,7 @@ void __exit rdtgroup_exit(void);
* @mode: Access mode
* @kf_ops: File operations
* @flags: File specific RFTYPE_FLAGS_* flags
- * @fflags: File specific RF_* or RFTYPE_* flags
+ * @fflags: File specific RFTYPE_* flags
* @seq_show: Show content of the file
* @write: Write to the file
*/
@@ -492,6 +492,15 @@ union cpuid_0x10_3_eax {
unsigned int full;
};
+/* CPUID.(EAX=10H, ECX=ResID).ECX */
+union cpuid_0x10_x_ecx {
+ struct {
+ unsigned int reserved:3;
+ unsigned int noncont:1;
+ } split;
+ unsigned int full;
+};
+
/* CPUID.(EAX=10H, ECX=ResID).EDX */
union cpuid_0x10_x_edx {
struct {
diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
index ded1fc7cb7cb..f136ac046851 100644
--- a/arch/x86/kernel/cpu/resctrl/monitor.c
+++ b/arch/x86/kernel/cpu/resctrl/monitor.c
@@ -30,15 +30,15 @@ struct rmid_entry {
struct list_head list;
};
-/**
- * @rmid_free_lru A least recently used list of free RMIDs
+/*
+ * @rmid_free_lru - A least recently used list of free RMIDs
* These RMIDs are guaranteed to have an occupancy less than the
* threshold occupancy
*/
static LIST_HEAD(rmid_free_lru);
-/**
- * @rmid_limbo_count count of currently unused but (potentially)
+/*
+ * @rmid_limbo_count - count of currently unused but (potentially)
* dirty RMIDs.
* This counts RMIDs that no one is currently using but that
* may have a occupancy value > resctrl_rmid_realloc_threshold. User can
@@ -46,7 +46,7 @@ static LIST_HEAD(rmid_free_lru);
*/
static unsigned int rmid_limbo_count;
-/**
+/*
* @rmid_entry - The entry in the limbo and free lists.
*/
static struct rmid_entry *rmid_ptrs;
diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
index 725344048f85..69a1de92384a 100644
--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
@@ -54,8 +54,13 @@ static struct kernfs_node *kn_mondata;
static struct seq_buf last_cmd_status;
static char last_cmd_status_buf[512];
+static int rdtgroup_setup_root(struct rdt_fs_context *ctx);
+static void rdtgroup_destroy_root(void);
+
struct dentry *debugfs_resctrl;
+static bool resctrl_debug;
+
void rdt_last_cmd_clear(void)
{
lockdep_assert_held(&rdtgroup_mutex);
@@ -696,11 +701,10 @@ static ssize_t rdtgroup_tasks_write(struct kernfs_open_file *of,
char *buf, size_t nbytes, loff_t off)
{
struct rdtgroup *rdtgrp;
+ char *pid_str;
int ret = 0;
pid_t pid;
- if (kstrtoint(strstrip(buf), 0, &pid) || pid < 0)
- return -EINVAL;
rdtgrp = rdtgroup_kn_lock_live(of->kn);
if (!rdtgrp) {
rdtgroup_kn_unlock(of->kn);
@@ -715,7 +719,27 @@ static ssize_t rdtgroup_tasks_write(struct kernfs_open_file *of,
goto unlock;
}
- ret = rdtgroup_move_task(pid, rdtgrp, of);
+ while (buf && buf[0] != '\0' && buf[0] != '\n') {
+ pid_str = strim(strsep(&buf, ","));
+
+ if (kstrtoint(pid_str, 0, &pid)) {
+ rdt_last_cmd_printf("Task list parsing error pid %s\n", pid_str);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (pid < 0) {
+ rdt_last_cmd_printf("Invalid pid %d\n", pid);
+ ret = -EINVAL;
+ break;
+ }
+
+ ret = rdtgroup_move_task(pid, rdtgrp, of);
+ if (ret) {
+ rdt_last_cmd_printf("Error while processing task %d\n", pid);
+ break;
+ }
+ }
unlock:
rdtgroup_kn_unlock(of->kn);
@@ -755,6 +779,38 @@ static int rdtgroup_tasks_show(struct kernfs_open_file *of,
return ret;
}
+static int rdtgroup_closid_show(struct kernfs_open_file *of,
+ struct seq_file *s, void *v)
+{
+ struct rdtgroup *rdtgrp;
+ int ret = 0;
+
+ rdtgrp = rdtgroup_kn_lock_live(of->kn);
+ if (rdtgrp)
+ seq_printf(s, "%u\n", rdtgrp->closid);
+ else
+ ret = -ENOENT;
+ rdtgroup_kn_unlock(of->kn);
+
+ return ret;
+}
+
+static int rdtgroup_rmid_show(struct kernfs_open_file *of,
+ struct seq_file *s, void *v)
+{
+ struct rdtgroup *rdtgrp;
+ int ret = 0;
+
+ rdtgrp = rdtgroup_kn_lock_live(of->kn);
+ if (rdtgrp)
+ seq_printf(s, "%u\n", rdtgrp->mon.rmid);
+ else
+ ret = -ENOENT;
+ rdtgroup_kn_unlock(of->kn);
+
+ return ret;
+}
+
#ifdef CONFIG_PROC_CPU_RESCTRL
/*
@@ -895,7 +951,7 @@ static int rdt_shareable_bits_show(struct kernfs_open_file *of,
return 0;
}
-/**
+/*
* rdt_bit_usage_show - Display current usage of resources
*
* A domain is a shared resource that can now be allocated differently. Here
@@ -1117,12 +1173,24 @@ static enum resctrl_conf_type resctrl_peer_type(enum resctrl_conf_type my_type)
}
}
+static int rdt_has_sparse_bitmasks_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+{
+ struct resctrl_schema *s = of->kn->parent->priv;
+ struct rdt_resource *r = s->res;
+
+ seq_printf(seq, "%u\n", r->cache.arch_has_sparse_bitmasks);
+
+ return 0;
+}
+
/**
* __rdtgroup_cbm_overlaps - Does CBM for intended closid overlap with other
* @r: Resource to which domain instance @d belongs.
* @d: The domain instance for which @closid is being tested.
* @cbm: Capacity bitmask being tested.
* @closid: Intended closid for @cbm.
+ * @type: CDP type of @r.
* @exclusive: Only check if overlaps with exclusive resource groups
*
* Checks if provided @cbm intended to be used for @closid on domain
@@ -1209,6 +1277,7 @@ bool rdtgroup_cbm_overlaps(struct resctrl_schema *s, struct rdt_domain *d,
/**
* rdtgroup_mode_test_exclusive - Test if this resource group can be exclusive
+ * @rdtgrp: Resource group identified through its closid.
*
* An exclusive resource group implies that there should be no sharing of
* its allocated resources. At the time this group is considered to be
@@ -1251,9 +1320,8 @@ static bool rdtgroup_mode_test_exclusive(struct rdtgroup *rdtgrp)
return true;
}
-/**
+/*
* rdtgroup_mode_write - Modify the resource group's mode
- *
*/
static ssize_t rdtgroup_mode_write(struct kernfs_open_file *of,
char *buf, size_t nbytes, loff_t off)
@@ -1357,12 +1425,11 @@ unsigned int rdtgroup_cbm_to_size(struct rdt_resource *r,
return size;
}
-/**
+/*
* rdtgroup_size_show - Display size in bytes of allocated regions
*
* The "size" file mirrors the layout of the "schemata" file, printing the
* size in bytes of each region instead of the capacity bitmask.
- *
*/
static int rdtgroup_size_show(struct kernfs_open_file *of,
struct seq_file *s, void *v)
@@ -1686,77 +1753,77 @@ static struct rftype res_common_files[] = {
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_last_cmd_status_show,
- .fflags = RF_TOP_INFO,
+ .fflags = RFTYPE_TOP_INFO,
},
{
.name = "num_closids",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_num_closids_show,
- .fflags = RF_CTRL_INFO,
+ .fflags = RFTYPE_CTRL_INFO,
},
{
.name = "mon_features",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_mon_features_show,
- .fflags = RF_MON_INFO,
+ .fflags = RFTYPE_MON_INFO,
},
{
.name = "num_rmids",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_num_rmids_show,
- .fflags = RF_MON_INFO,
+ .fflags = RFTYPE_MON_INFO,
},
{
.name = "cbm_mask",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_default_ctrl_show,
- .fflags = RF_CTRL_INFO | RFTYPE_RES_CACHE,
+ .fflags = RFTYPE_CTRL_INFO | RFTYPE_RES_CACHE,
},
{
.name = "min_cbm_bits",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_min_cbm_bits_show,
- .fflags = RF_CTRL_INFO | RFTYPE_RES_CACHE,
+ .fflags = RFTYPE_CTRL_INFO | RFTYPE_RES_CACHE,
},
{
.name = "shareable_bits",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_shareable_bits_show,
- .fflags = RF_CTRL_INFO | RFTYPE_RES_CACHE,
+ .fflags = RFTYPE_CTRL_INFO | RFTYPE_RES_CACHE,
},
{
.name = "bit_usage",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_bit_usage_show,
- .fflags = RF_CTRL_INFO | RFTYPE_RES_CACHE,
+ .fflags = RFTYPE_CTRL_INFO | RFTYPE_RES_CACHE,
},
{
.name = "min_bandwidth",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_min_bw_show,
- .fflags = RF_CTRL_INFO | RFTYPE_RES_MB,
+ .fflags = RFTYPE_CTRL_INFO | RFTYPE_RES_MB,
},
{
.name = "bandwidth_gran",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_bw_gran_show,
- .fflags = RF_CTRL_INFO | RFTYPE_RES_MB,
+ .fflags = RFTYPE_CTRL_INFO | RFTYPE_RES_MB,
},
{
.name = "delay_linear",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdt_delay_linear_show,
- .fflags = RF_CTRL_INFO | RFTYPE_RES_MB,
+ .fflags = RFTYPE_CTRL_INFO | RFTYPE_RES_MB,
},
/*
* Platform specific which (if any) capabilities are provided by
@@ -1775,7 +1842,7 @@ static struct rftype res_common_files[] = {
.kf_ops = &rdtgroup_kf_single_ops,
.write = max_threshold_occ_write,
.seq_show = max_threshold_occ_show,
- .fflags = RF_MON_INFO | RFTYPE_RES_CACHE,
+ .fflags = RFTYPE_MON_INFO | RFTYPE_RES_CACHE,
},
{
.name = "mbm_total_bytes_config",
@@ -1817,12 +1884,19 @@ static struct rftype res_common_files[] = {
.fflags = RFTYPE_BASE,
},
{
+ .name = "mon_hw_id",
+ .mode = 0444,
+ .kf_ops = &rdtgroup_kf_single_ops,
+ .seq_show = rdtgroup_rmid_show,
+ .fflags = RFTYPE_MON_BASE | RFTYPE_DEBUG,
+ },
+ {
.name = "schemata",
.mode = 0644,
.kf_ops = &rdtgroup_kf_single_ops,
.write = rdtgroup_schemata_write,
.seq_show = rdtgroup_schemata_show,
- .fflags = RF_CTRL_BASE,
+ .fflags = RFTYPE_CTRL_BASE,
},
{
.name = "mode",
@@ -1830,14 +1904,28 @@ static struct rftype res_common_files[] = {
.kf_ops = &rdtgroup_kf_single_ops,
.write = rdtgroup_mode_write,
.seq_show = rdtgroup_mode_show,
- .fflags = RF_CTRL_BASE,
+ .fflags = RFTYPE_CTRL_BASE,
},
{
.name = "size",
.mode = 0444,
.kf_ops = &rdtgroup_kf_single_ops,
.seq_show = rdtgroup_size_show,
- .fflags = RF_CTRL_BASE,
+ .fflags = RFTYPE_CTRL_BASE,
+ },
+ {
+ .name = "sparse_masks",
+ .mode = 0444,
+ .kf_ops = &rdtgroup_kf_single_ops,
+ .seq_show = rdt_has_sparse_bitmasks_show,
+ .fflags = RFTYPE_CTRL_INFO | RFTYPE_RES_CACHE,
+ },
+ {
+ .name = "ctrl_hw_id",
+ .mode = 0444,
+ .kf_ops = &rdtgroup_kf_single_ops,
+ .seq_show = rdtgroup_closid_show,
+ .fflags = RFTYPE_CTRL_BASE | RFTYPE_DEBUG,
},
};
@@ -1852,6 +1940,9 @@ static int rdtgroup_add_files(struct kernfs_node *kn, unsigned long fflags)
lockdep_assert_held(&rdtgroup_mutex);
+ if (resctrl_debug)
+ fflags |= RFTYPE_DEBUG;
+
for (rft = rfts; rft < rfts + len; rft++) {
if (rft->fflags && ((fflags & rft->fflags) == rft->fflags)) {
ret = rdtgroup_add_file(kn, rft);
@@ -1894,7 +1985,7 @@ void __init thread_throttle_mode_init(void)
if (!rft)
return;
- rft->fflags = RF_CTRL_INFO | RFTYPE_RES_MB;
+ rft->fflags = RFTYPE_CTRL_INFO | RFTYPE_RES_MB;
}
void __init mbm_config_rftype_init(const char *config)
@@ -1903,7 +1994,7 @@ void __init mbm_config_rftype_init(const char *config)
rft = rdtgroup_get_rftype_by_name(config);
if (rft)
- rft->fflags = RF_MON_INFO | RFTYPE_RES_CACHE;
+ rft->fflags = RFTYPE_MON_INFO | RFTYPE_RES_CACHE;
}
/**
@@ -2038,21 +2129,21 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
if (IS_ERR(kn_info))
return PTR_ERR(kn_info);
- ret = rdtgroup_add_files(kn_info, RF_TOP_INFO);
+ ret = rdtgroup_add_files(kn_info, RFTYPE_TOP_INFO);
if (ret)
goto out_destroy;
/* loop over enabled controls, these are all alloc_capable */
list_for_each_entry(s, &resctrl_schema_all, list) {
r = s->res;
- fflags = r->fflags | RF_CTRL_INFO;
+ fflags = r->fflags | RFTYPE_CTRL_INFO;
ret = rdtgroup_mkdir_info_resdir(s, s->name, fflags);
if (ret)
goto out_destroy;
}
for_each_mon_capable_rdt_resource(r) {
- fflags = r->fflags | RF_MON_INFO;
+ fflags = r->fflags | RFTYPE_MON_INFO;
sprintf(name, "%s_MON", r->name);
ret = rdtgroup_mkdir_info_resdir(r, name, fflags);
if (ret)
@@ -2271,14 +2362,6 @@ int resctrl_arch_set_cdp_enabled(enum resctrl_res_level l, bool enable)
return 0;
}
-static void cdp_disable_all(void)
-{
- if (resctrl_arch_get_cdp_enabled(RDT_RESOURCE_L3))
- resctrl_arch_set_cdp_enabled(RDT_RESOURCE_L3, false);
- if (resctrl_arch_get_cdp_enabled(RDT_RESOURCE_L2))
- resctrl_arch_set_cdp_enabled(RDT_RESOURCE_L2, false);
-}
-
/*
* We don't allow rdtgroup directories to be created anywhere
* except the root directory. Thus when looking for the rdtgroup
@@ -2358,19 +2441,47 @@ static int mkdir_mondata_all(struct kernfs_node *parent_kn,
struct rdtgroup *prgrp,
struct kernfs_node **mon_data_kn);
+static void rdt_disable_ctx(void)
+{
+ resctrl_arch_set_cdp_enabled(RDT_RESOURCE_L3, false);
+ resctrl_arch_set_cdp_enabled(RDT_RESOURCE_L2, false);
+ set_mba_sc(false);
+
+ resctrl_debug = false;
+}
+
static int rdt_enable_ctx(struct rdt_fs_context *ctx)
{
int ret = 0;
- if (ctx->enable_cdpl2)
+ if (ctx->enable_cdpl2) {
ret = resctrl_arch_set_cdp_enabled(RDT_RESOURCE_L2, true);
+ if (ret)
+ goto out_done;
+ }
- if (!ret && ctx->enable_cdpl3)
+ if (ctx->enable_cdpl3) {
ret = resctrl_arch_set_cdp_enabled(RDT_RESOURCE_L3, true);
+ if (ret)
+ goto out_cdpl2;
+ }
- if (!ret && ctx->enable_mba_mbps)
+ if (ctx->enable_mba_mbps) {
ret = set_mba_sc(true);
+ if (ret)
+ goto out_cdpl3;
+ }
+
+ if (ctx->enable_debug)
+ resctrl_debug = true;
+ return 0;
+
+out_cdpl3:
+ resctrl_arch_set_cdp_enabled(RDT_RESOURCE_L3, false);
+out_cdpl2:
+ resctrl_arch_set_cdp_enabled(RDT_RESOURCE_L2, false);
+out_done:
return ret;
}
@@ -2463,6 +2574,7 @@ static void schemata_list_destroy(void)
static int rdt_get_tree(struct fs_context *fc)
{
struct rdt_fs_context *ctx = rdt_fc2context(fc);
+ unsigned long flags = RFTYPE_CTRL_BASE;
struct rdt_domain *dom;
struct rdt_resource *r;
int ret;
@@ -2477,18 +2589,31 @@ static int rdt_get_tree(struct fs_context *fc)
goto out;
}
+ ret = rdtgroup_setup_root(ctx);
+ if (ret)
+ goto out;
+
ret = rdt_enable_ctx(ctx);
- if (ret < 0)
- goto out_cdp;
+ if (ret)
+ goto out_root;
ret = schemata_list_create();
if (ret) {
schemata_list_destroy();
- goto out_mba;
+ goto out_ctx;
}
closid_init();
+ if (rdt_mon_capable)
+ flags |= RFTYPE_MON;
+
+ ret = rdtgroup_add_files(rdtgroup_default.kn, flags);
+ if (ret)
+ goto out_schemata_free;
+
+ kernfs_activate(rdtgroup_default.kn);
+
ret = rdtgroup_create_info_dir(rdtgroup_default.kn);
if (ret < 0)
goto out_schemata_free;
@@ -2543,11 +2668,10 @@ out_info:
kernfs_remove(kn_info);
out_schemata_free:
schemata_list_destroy();
-out_mba:
- if (ctx->enable_mba_mbps)
- set_mba_sc(false);
-out_cdp:
- cdp_disable_all();
+out_ctx:
+ rdt_disable_ctx();
+out_root:
+ rdtgroup_destroy_root();
out:
rdt_last_cmd_clear();
mutex_unlock(&rdtgroup_mutex);
@@ -2559,6 +2683,7 @@ enum rdt_param {
Opt_cdp,
Opt_cdpl2,
Opt_mba_mbps,
+ Opt_debug,
nr__rdt_params
};
@@ -2566,6 +2691,7 @@ static const struct fs_parameter_spec rdt_fs_parameters[] = {
fsparam_flag("cdp", Opt_cdp),
fsparam_flag("cdpl2", Opt_cdpl2),
fsparam_flag("mba_MBps", Opt_mba_mbps),
+ fsparam_flag("debug", Opt_debug),
{}
};
@@ -2591,6 +2717,9 @@ static int rdt_parse_param(struct fs_context *fc, struct fs_parameter *param)
return -EINVAL;
ctx->enable_mba_mbps = true;
return 0;
+ case Opt_debug:
+ ctx->enable_debug = true;
+ return 0;
}
return -EINVAL;
@@ -2618,7 +2747,6 @@ static int rdt_init_fs_context(struct fs_context *fc)
if (!ctx)
return -ENOMEM;
- ctx->kfc.root = rdt_root;
ctx->kfc.magic = RDTGROUP_SUPER_MAGIC;
fc->fs_private = &ctx->kfc;
fc->ops = &rdt_fs_context_ops;
@@ -2779,16 +2907,16 @@ static void rdt_kill_sb(struct super_block *sb)
cpus_read_lock();
mutex_lock(&rdtgroup_mutex);
- set_mba_sc(false);
+ rdt_disable_ctx();
/*Put everything back to default values. */
for_each_alloc_capable_rdt_resource(r)
reset_all_ctrls(r);
- cdp_disable_all();
rmdir_all_sub();
rdt_pseudo_lock_release();
rdtgroup_default.mode = RDT_MODE_SHAREABLE;
schemata_list_destroy();
+ rdtgroup_destroy_root();
static_branch_disable_cpuslocked(&rdt_alloc_enable_key);
static_branch_disable_cpuslocked(&rdt_mon_enable_key);
static_branch_disable_cpuslocked(&rdt_enable_key);
@@ -3170,8 +3298,8 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
enum rdt_group_type rtype, struct rdtgroup **r)
{
struct rdtgroup *prdtgrp, *rdtgrp;
+ unsigned long files = 0;
struct kernfs_node *kn;
- uint files = 0;
int ret;
prdtgrp = rdtgroup_kn_lock_live(parent_kn);
@@ -3223,7 +3351,14 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
goto out_destroy;
}
- files = RFTYPE_BASE | BIT(RF_CTRLSHIFT + rtype);
+ if (rtype == RDTCTRL_GROUP) {
+ files = RFTYPE_BASE | RFTYPE_CTRL;
+ if (rdt_mon_capable)
+ files |= RFTYPE_MON;
+ } else {
+ files = RFTYPE_BASE | RFTYPE_MON;
+ }
+
ret = rdtgroup_add_files(kn, files);
if (ret) {
rdt_last_cmd_puts("kernfs fill error\n");
@@ -3656,6 +3791,9 @@ static int rdtgroup_show_options(struct seq_file *seq, struct kernfs_root *kf)
if (is_mba_sc(&rdt_resources_all[RDT_RESOURCE_MBA].r_resctrl))
seq_puts(seq, ",mba_MBps");
+ if (resctrl_debug)
+ seq_puts(seq, ",debug");
+
return 0;
}
@@ -3666,10 +3804,8 @@ static struct kernfs_syscall_ops rdtgroup_kf_syscall_ops = {
.show_options = rdtgroup_show_options,
};
-static int __init rdtgroup_setup_root(void)
+static int rdtgroup_setup_root(struct rdt_fs_context *ctx)
{
- int ret;
-
rdt_root = kernfs_create_root(&rdtgroup_kf_syscall_ops,
KERNFS_ROOT_CREATE_DEACTIVATED |
KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK,
@@ -3677,6 +3813,20 @@ static int __init rdtgroup_setup_root(void)
if (IS_ERR(rdt_root))
return PTR_ERR(rdt_root);
+ ctx->kfc.root = rdt_root;
+ rdtgroup_default.kn = kernfs_root_to_node(rdt_root);
+
+ return 0;
+}
+
+static void rdtgroup_destroy_root(void)
+{
+ kernfs_destroy_root(rdt_root);
+ rdtgroup_default.kn = NULL;
+}
+
+static void __init rdtgroup_setup_default(void)
+{
mutex_lock(&rdtgroup_mutex);
rdtgroup_default.closid = 0;
@@ -3686,19 +3836,7 @@ static int __init rdtgroup_setup_root(void)
list_add(&rdtgroup_default.rdtgroup_list, &rdt_all_groups);
- ret = rdtgroup_add_files(kernfs_root_to_node(rdt_root), RF_CTRL_BASE);
- if (ret) {
- kernfs_destroy_root(rdt_root);
- goto out;
- }
-
- rdtgroup_default.kn = kernfs_root_to_node(rdt_root);
- kernfs_activate(rdtgroup_default.kn);
-
-out:
mutex_unlock(&rdtgroup_mutex);
-
- return ret;
}
static void domain_destroy_mon_state(struct rdt_domain *d)
@@ -3820,13 +3958,11 @@ int __init rdtgroup_init(void)
seq_buf_init(&last_cmd_status, last_cmd_status_buf,
sizeof(last_cmd_status_buf));
- ret = rdtgroup_setup_root();
- if (ret)
- return ret;
+ rdtgroup_setup_default();
ret = sysfs_create_mount_point(fs_kobj, "resctrl");
if (ret)
- goto cleanup_root;
+ return ret;
ret = register_filesystem(&rdt_fs_type);
if (ret)
@@ -3859,8 +3995,6 @@ int __init rdtgroup_init(void)
cleanup_mountpoint:
sysfs_remove_mount_point(fs_kobj, "resctrl");
-cleanup_root:
- kernfs_destroy_root(rdt_root);
return ret;
}
@@ -3870,5 +4004,4 @@ void __exit rdtgroup_exit(void)
debugfs_remove_recursive(debugfs_resctrl);
unregister_filesystem(&rdt_fs_type);
sysfs_remove_mount_point(fs_kobj, "resctrl");
- kernfs_destroy_root(rdt_root);
}
diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c
index 0270925fe013..dc136703566f 100644
--- a/arch/x86/kernel/cpu/topology.c
+++ b/arch/x86/kernel/cpu/topology.c
@@ -78,7 +78,7 @@ int detect_extended_topology_early(struct cpuinfo_x86 *c)
/*
* initial apic id, which also represents 32-bit extended x2apic id.
*/
- c->initial_apicid = edx;
+ c->topo.initial_apicid = edx;
smp_num_siblings = max_t(int, smp_num_siblings, LEVEL_MAX_SIBLINGS(ebx));
#endif
return 0;
@@ -108,7 +108,7 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
* Populate HT related information from sub-leaf level 0.
*/
cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
- c->initial_apicid = edx;
+ c->topo.initial_apicid = edx;
core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
smp_num_siblings = max_t(int, smp_num_siblings, LEVEL_MAX_SIBLINGS(ebx));
core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
@@ -146,20 +146,19 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
die_select_mask = (~(-1 << die_plus_mask_width)) >>
core_plus_mask_width;
- c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid,
+ c->topo.core_id = apic->phys_pkg_id(c->topo.initial_apicid,
ht_mask_width) & core_select_mask;
if (die_level_present) {
- c->cpu_die_id = apic->phys_pkg_id(c->initial_apicid,
+ c->topo.die_id = apic->phys_pkg_id(c->topo.initial_apicid,
core_plus_mask_width) & die_select_mask;
}
- c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid,
- pkg_mask_width);
+ c->topo.pkg_id = apic->phys_pkg_id(c->topo.initial_apicid, pkg_mask_width);
/*
* Reinit the apicid, now that we have extended initial_apicid.
*/
- c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
+ c->topo.apicid = apic->phys_pkg_id(c->topo.initial_apicid, 0);
c->x86_max_cores = (core_level_siblings / smp_num_siblings);
__max_die_per_package = (die_level_siblings / core_level_siblings);
diff --git a/arch/x86/kernel/cpu/zhaoxin.c b/arch/x86/kernel/cpu/zhaoxin.c
index 05fa4ef63490..415564a6523b 100644
--- a/arch/x86/kernel/cpu/zhaoxin.c
+++ b/arch/x86/kernel/cpu/zhaoxin.c
@@ -65,20 +65,6 @@ static void early_init_zhaoxin(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
}
-
- if (c->cpuid_level >= 0x00000001) {
- u32 eax, ebx, ecx, edx;
-
- cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
- /*
- * If HTT (EDX[28]) is set EBX[16:23] contain the number of
- * apicids which are reserved per package. Store the resulting
- * shift value for the package management code.
- */
- if (edx & (1U << 28))
- c->x86_coreid_bits = get_count_order((ebx >> 16) & 0xff);
- }
-
}
static void init_zhaoxin(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 87d38f17ff5c..afd09924094e 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -278,7 +278,7 @@ static void __init dtb_apic_setup(void)
}
#ifdef CONFIG_OF_EARLY_FLATTREE
-static void __init x86_flattree_get_config(void)
+void __init x86_flattree_get_config(void)
{
u32 size, map_len;
void *dt;
@@ -300,14 +300,10 @@ static void __init x86_flattree_get_config(void)
unflatten_and_copy_device_tree();
early_memunmap(dt, map_len);
}
-#else
-static inline void x86_flattree_get_config(void) { }
#endif
void __init x86_dtb_init(void)
{
- x86_flattree_get_config();
-
if (!of_have_populated_dt())
return;
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index a86d37052a64..a21a4d0ecc34 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -369,14 +369,15 @@ int fpu_swap_kvm_fpstate(struct fpu_guest *guest_fpu, bool enter_guest)
EXPORT_SYMBOL_GPL(fpu_swap_kvm_fpstate);
void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf,
- unsigned int size, u32 pkru)
+ unsigned int size, u64 xfeatures, u32 pkru)
{
struct fpstate *kstate = gfpu->fpstate;
union fpregs_state *ustate = buf;
struct membuf mb = { .p = buf, .left = size };
if (cpu_feature_enabled(X86_FEATURE_XSAVE)) {
- __copy_xstate_to_uabi_buf(mb, kstate, pkru, XSTATE_COPY_XSAVE);
+ __copy_xstate_to_uabi_buf(mb, kstate, xfeatures, pkru,
+ XSTATE_COPY_XSAVE);
} else {
memcpy(&ustate->fxsave, &kstate->regs.fxsave,
sizeof(ustate->fxsave));
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index cadf68737e6b..117e74c44e75 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -1049,6 +1049,7 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate,
* __copy_xstate_to_uabi_buf - Copy kernel saved xstate to a UABI buffer
* @to: membuf descriptor
* @fpstate: The fpstate buffer from which to copy
+ * @xfeatures: The mask of xfeatures to save (XSAVE mode only)
* @pkru_val: The PKRU value to store in the PKRU component
* @copy_mode: The requested copy mode
*
@@ -1059,7 +1060,8 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate,
* It supports partial copy but @to.pos always starts from zero.
*/
void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
- u32 pkru_val, enum xstate_copy_mode copy_mode)
+ u64 xfeatures, u32 pkru_val,
+ enum xstate_copy_mode copy_mode)
{
const unsigned int off_mxcsr = offsetof(struct fxregs_state, mxcsr);
struct xregs_state *xinit = &init_fpstate.regs.xsave;
@@ -1083,7 +1085,7 @@ void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
break;
case XSTATE_COPY_XSAVE:
- header.xfeatures &= fpstate->user_xfeatures;
+ header.xfeatures &= fpstate->user_xfeatures & xfeatures;
break;
}
@@ -1185,6 +1187,7 @@ void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
enum xstate_copy_mode copy_mode)
{
__copy_xstate_to_uabi_buf(to, tsk->thread.fpu.fpstate,
+ tsk->thread.fpu.fpstate->user_xfeatures,
tsk->thread.pkru, copy_mode);
}
@@ -1536,10 +1539,7 @@ static int fpstate_realloc(u64 xfeatures, unsigned int ksize,
fpregs_restore_userregs();
newfps->xfeatures = curfps->xfeatures | xfeatures;
-
- if (!guest_fpu)
- newfps->user_xfeatures = curfps->user_xfeatures | xfeatures;
-
+ newfps->user_xfeatures = curfps->user_xfeatures | xfeatures;
newfps->xfd = curfps->xfd & ~xfeatures;
/* Do the final updates within the locked region */
@@ -1736,7 +1736,6 @@ EXPORT_SYMBOL_GPL(xstate_get_guest_group_perm);
/**
* fpu_xstate_prctl - xstate permission operations
- * @tsk: Redundant pointer to current
* @option: A subfunction of arch_prctl()
* @arg2: option argument
* Return: 0 if successful; otherwise, an error code
diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h
index a4ecb04d8d64..3518fb26d06b 100644
--- a/arch/x86/kernel/fpu/xstate.h
+++ b/arch/x86/kernel/fpu/xstate.h
@@ -43,7 +43,8 @@ enum xstate_copy_mode {
struct membuf;
extern void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
- u32 pkru_val, enum xstate_copy_mode copy_mode);
+ u64 xfeatures, u32 pkru_val,
+ enum xstate_copy_mode copy_mode);
extern void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
enum xstate_copy_mode mode);
extern int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf, u32 *pkru);
diff --git a/arch/x86/kernel/ftrace_32.S b/arch/x86/kernel/ftrace_32.S
index 24c1175a47e2..58d9ed50fe61 100644
--- a/arch/x86/kernel/ftrace_32.S
+++ b/arch/x86/kernel/ftrace_32.S
@@ -3,10 +3,10 @@
* Copyright (C) 2017 Steven Rostedt, VMware Inc.
*/
+#include <linux/export.h>
#include <linux/linkage.h>
#include <asm/page_types.h>
#include <asm/segment.h>
-#include <asm/export.h>
#include <asm/ftrace.h>
#include <asm/nospec-branch.h>
#include <asm/frame.h>
diff --git a/arch/x86/kernel/ftrace_64.S b/arch/x86/kernel/ftrace_64.S
index 945cfa5f7239..214f30e9f0c0 100644
--- a/arch/x86/kernel/ftrace_64.S
+++ b/arch/x86/kernel/ftrace_64.S
@@ -3,12 +3,12 @@
* Copyright (C) 2014 Steven Rostedt, Red Hat Inc
*/
+#include <linux/export.h>
#include <linux/cfi_types.h>
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
#include <asm/ftrace.h>
-#include <asm/export.h>
#include <asm/nospec-branch.h>
#include <asm/unwind_hints.h>
#include <asm/frame.h>
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 246a609f889b..de001b2146ab 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -19,6 +19,7 @@
#include <asm/apic.h>
#include <asm/io_apic.h>
#include <asm/bios_ebda.h>
+#include <asm/microcode.h>
#include <asm/tlbflush.h>
#include <asm/bootparam_utils.h>
@@ -29,11 +30,33 @@ static void __init i386_default_early_setup(void)
x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc;
}
+#ifdef CONFIG_MICROCODE_INITRD32
+unsigned long __initdata initrd_start_early;
+static pte_t __initdata *initrd_pl2p_start, *initrd_pl2p_end;
+
+static void zap_early_initrd_mapping(void)
+{
+ pte_t *pl2p = initrd_pl2p_start;
+
+ for (; pl2p < initrd_pl2p_end; pl2p++) {
+ *pl2p = (pte_t){ .pte = 0 };
+
+ if (!IS_ENABLED(CONFIG_X86_PAE))
+ *(pl2p + ((PAGE_OFFSET >> PGDIR_SHIFT))) = (pte_t) {.pte = 0};
+ }
+}
+#else
+static inline void zap_early_initrd_mapping(void) { }
+#endif
+
asmlinkage __visible void __init __noreturn i386_start_kernel(void)
{
/* Make sure IDT is set up before any exception happens */
idt_setup_early_handler();
+ load_ucode_bsp();
+ zap_early_initrd_mapping();
+
cr4_init_shadow();
sanitize_boot_params(&boot_params);
@@ -69,52 +92,83 @@ asmlinkage __visible void __init __noreturn i386_start_kernel(void)
* to the first kernel PMD. Note the upper half of each PMD or PTE are
* always zero at this stage.
*/
-void __init mk_early_pgtbl_32(void);
-void __init mk_early_pgtbl_32(void)
-{
-#ifdef __pa
-#undef __pa
-#endif
-#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
- pte_t pte, *ptep;
- int i;
- unsigned long *ptr;
- /* Enough space to fit pagetables for the low memory linear map */
- const unsigned long limit = __pa(_end) +
- (PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT);
#ifdef CONFIG_X86_PAE
- pmd_t pl2, *pl2p = (pmd_t *)__pa(initial_pg_pmd);
-#define SET_PL2(pl2, val) { (pl2).pmd = (val); }
+typedef pmd_t pl2_t;
+#define pl2_base initial_pg_pmd
+#define SET_PL2(val) { .pmd = (val), }
#else
- pgd_t pl2, *pl2p = (pgd_t *)__pa(initial_page_table);
-#define SET_PL2(pl2, val) { (pl2).pgd = (val); }
+typedef pgd_t pl2_t;
+#define pl2_base initial_page_table
+#define SET_PL2(val) { .pgd = (val), }
#endif
- ptep = (pte_t *)__pa(__brk_base);
- pte.pte = PTE_IDENT_ATTR;
-
+static __init __no_stack_protector pte_t init_map(pte_t pte, pte_t **ptep, pl2_t **pl2p,
+ const unsigned long limit)
+{
while ((pte.pte & PTE_PFN_MASK) < limit) {
+ pl2_t pl2 = SET_PL2((unsigned long)*ptep | PDE_IDENT_ATTR);
+ int i;
+
+ **pl2p = pl2;
+ if (!IS_ENABLED(CONFIG_X86_PAE)) {
+ /* Kernel PDE entry */
+ *(*pl2p + ((PAGE_OFFSET >> PGDIR_SHIFT))) = pl2;
+ }
- SET_PL2(pl2, (unsigned long)ptep | PDE_IDENT_ATTR);
- *pl2p = pl2;
-#ifndef CONFIG_X86_PAE
- /* Kernel PDE entry */
- *(pl2p + ((PAGE_OFFSET >> PGDIR_SHIFT))) = pl2;
-#endif
for (i = 0; i < PTRS_PER_PTE; i++) {
- *ptep = pte;
+ **ptep = pte;
pte.pte += PAGE_SIZE;
- ptep++;
+ (*ptep)++;
}
-
- pl2p++;
+ (*pl2p)++;
}
+ return pte;
+}
+
+void __init __no_stack_protector mk_early_pgtbl_32(void)
+{
+ /* Enough space to fit pagetables for the low memory linear map */
+ unsigned long limit = __pa_nodebug(_end) + (PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT);
+ pte_t pte, *ptep = (pte_t *)__pa_nodebug(__brk_base);
+ struct boot_params __maybe_unused *params;
+ pl2_t *pl2p = (pl2_t *)__pa_nodebug(pl2_base);
+ unsigned long *ptr;
+
+ pte.pte = PTE_IDENT_ATTR;
+ pte = init_map(pte, &ptep, &pl2p, limit);
- ptr = (unsigned long *)__pa(&max_pfn_mapped);
+ ptr = (unsigned long *)__pa_nodebug(&max_pfn_mapped);
/* Can't use pte_pfn() since it's a call with CONFIG_PARAVIRT */
*ptr = (pte.pte & PTE_PFN_MASK) >> PAGE_SHIFT;
- ptr = (unsigned long *)__pa(&_brk_end);
+ ptr = (unsigned long *)__pa_nodebug(&_brk_end);
*ptr = (unsigned long)ptep + PAGE_OFFSET;
-}
+#ifdef CONFIG_MICROCODE_INITRD32
+ /* Running on a hypervisor? */
+ if (native_cpuid_ecx(1) & BIT(31))
+ return;
+
+ params = (struct boot_params *)__pa_nodebug(&boot_params);
+ if (!params->hdr.ramdisk_size || !params->hdr.ramdisk_image)
+ return;
+
+ /* Save the virtual start address */
+ ptr = (unsigned long *)__pa_nodebug(&initrd_start_early);
+ *ptr = (pte.pte & PTE_PFN_MASK) + PAGE_OFFSET;
+ *ptr += ((unsigned long)params->hdr.ramdisk_image) & ~PAGE_MASK;
+
+ /* Save PLP2 for cleanup */
+ ptr = (unsigned long *)__pa_nodebug(&initrd_pl2p_start);
+ *ptr = (unsigned long)pl2p + PAGE_OFFSET;
+
+ limit = (unsigned long)params->hdr.ramdisk_image;
+ pte.pte = PTE_IDENT_ATTR | PFN_ALIGN(limit);
+ limit = (unsigned long)params->hdr.ramdisk_image + params->hdr.ramdisk_size;
+
+ init_map(pte, &ptep, &pl2p, limit);
+
+ ptr = (unsigned long *)__pa_nodebug(&initrd_pl2p_end);
+ *ptr = (unsigned long)pl2p + PAGE_OFFSET;
+#endif
+}
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 49f7629b17f7..05a110c97111 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -41,6 +41,7 @@
#include <asm/trapnr.h>
#include <asm/sev.h>
#include <asm/tdx.h>
+#include <asm/init.h>
/*
* Manage page tables very early on.
@@ -69,7 +70,7 @@ EXPORT_SYMBOL(vmemmap_base);
/*
* GDT used on the boot CPU before switching to virtual addresses.
*/
-static struct desc_struct startup_gdt[GDT_ENTRIES] = {
+static struct desc_struct startup_gdt[GDT_ENTRIES] __initdata = {
[GDT_ENTRY_KERNEL32_CS] = GDT_ENTRY_INIT(0xc09b, 0, 0xfffff),
[GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xa09b, 0, 0xfffff),
[GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc093, 0, 0xfffff),
@@ -79,13 +80,11 @@ static struct desc_struct startup_gdt[GDT_ENTRIES] = {
* Address needs to be set at runtime because it references the startup_gdt
* while the kernel still uses a direct mapping.
*/
-static struct desc_ptr startup_gdt_descr = {
- .size = sizeof(startup_gdt),
+static struct desc_ptr startup_gdt_descr __initdata = {
+ .size = sizeof(startup_gdt)-1,
.address = 0,
};
-#define __head __section(".head.text")
-
static void __head *fixup_pointer(void *ptr, unsigned long physaddr)
{
return ptr - (void *)_text + (void *)physaddr;
@@ -211,7 +210,7 @@ unsigned long __head __startup_64(unsigned long physaddr,
/* Fixup the physical addresses in the page table */
- pgd = fixup_pointer(&early_top_pgt, physaddr);
+ pgd = fixup_pointer(early_top_pgt, physaddr);
p = pgd + pgd_index(__START_KERNEL_map);
if (la57)
*p = (unsigned long)level4_kernel_pgt;
@@ -220,11 +219,11 @@ unsigned long __head __startup_64(unsigned long physaddr,
*p += _PAGE_TABLE_NOENC - __START_KERNEL_map + load_delta;
if (la57) {
- p4d = fixup_pointer(&level4_kernel_pgt, physaddr);
+ p4d = fixup_pointer(level4_kernel_pgt, physaddr);
p4d[511] += load_delta;
}
- pud = fixup_pointer(&level3_kernel_pgt, physaddr);
+ pud = fixup_pointer(level3_kernel_pgt, physaddr);
pud[510] += load_delta;
pud[511] += load_delta;
@@ -588,7 +587,7 @@ static void set_bringup_idt_handler(gate_desc *idt, int n, void *handler)
}
/* This runs while still in the direct mapping */
-static void startup_64_load_idt(unsigned long physbase)
+static void __head startup_64_load_idt(unsigned long physbase)
{
struct desc_ptr *desc = fixup_pointer(&bringup_idt_descr, physbase);
gate_desc *idt = fixup_pointer(bringup_idt_table, physbase);
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index c9318993f959..487ac57e2c81 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -8,6 +8,7 @@
*/
.text
+#include <linux/export.h>
#include <linux/threads.h>
#include <linux/init.h>
#include <linux/linkage.h>
@@ -25,7 +26,6 @@
#include <asm/nops.h>
#include <asm/nospec-branch.h>
#include <asm/bootparam.h>
-#include <asm/export.h>
#include <asm/pgtable_32.h>
/* Physical address */
@@ -118,11 +118,6 @@ SYM_CODE_START(startup_32)
movl %eax, pa(olpc_ofw_pgd)
#endif
-#ifdef CONFIG_MICROCODE
- /* Early load ucode on BSP. */
- call load_ucode_bsp
-#endif
-
/* Create early pagetables. */
call mk_early_pgtbl_32
@@ -157,11 +152,6 @@ SYM_FUNC_START(startup_32_smp)
movl %eax,%ss
leal -__PAGE_OFFSET(%ecx),%esp
-#ifdef CONFIG_MICROCODE
- /* Early load ucode on AP. */
- call load_ucode_ap
-#endif
-
.Ldefault_entry:
movl $(CR0_STATE & ~X86_CR0_PG),%eax
movl %eax,%cr0
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index ea6995920b7a..086a2c3aaaa0 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -9,7 +9,7 @@
* Copyright (C) 2005 Eric Biederman <ebiederm@xmission.com>
*/
-
+#include <linux/export.h>
#include <linux/linkage.h>
#include <linux/threads.h>
#include <linux/init.h>
@@ -22,7 +22,6 @@
#include <asm/percpu.h>
#include <asm/nops.h>
#include "../entry/calling.h"
-#include <asm/export.h>
#include <asm/nospec-branch.h>
#include <asm/apicdef.h>
#include <asm/fixmap.h>
@@ -180,8 +179,8 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
movl $0, %ecx
#endif
- /* Enable PAE mode, PGE and LA57 */
- orl $(X86_CR4_PAE | X86_CR4_PGE), %ecx
+ /* Enable PAE mode, PSE, PGE and LA57 */
+ orl $(X86_CR4_PAE | X86_CR4_PSE | X86_CR4_PGE), %ecx
#ifdef CONFIG_X86_5LEVEL
testl $1, __pgtable_l5_enabled(%rip)
jz 1f
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 1648aa0204d9..41eecf180b7f 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -52,7 +52,7 @@ unsigned long hpet_address;
u8 hpet_blockid; /* OS timer block num */
bool hpet_msi_disable;
-#ifdef CONFIG_GENERIC_MSI_IRQ
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_GENERIC_MSI_IRQ)
static DEFINE_PER_CPU(struct hpet_channel *, cpu_hpet_channel);
static struct irq_domain *hpet_domain;
#endif
@@ -469,7 +469,7 @@ static void __init hpet_legacy_clockevent_register(struct hpet_channel *hc)
/*
* HPET MSI Support
*/
-#ifdef CONFIG_GENERIC_MSI_IRQ
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_GENERIC_MSI_IRQ)
static void hpet_msi_unmask(struct irq_data *data)
{
struct hpet_channel *hc = irq_data_get_irq_handler_data(data);
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 30a55207c000..c20d1832c481 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -32,6 +32,7 @@
*/
static void init_8259A(int auto_eoi);
+static bool pcat_compat __ro_after_init;
static int i8259A_auto_eoi;
DEFINE_RAW_SPINLOCK(i8259A_lock);
@@ -299,15 +300,32 @@ static void unmask_8259A(void)
static int probe_8259A(void)
{
+ unsigned char new_val, probe_val = ~(1 << PIC_CASCADE_IR);
unsigned long flags;
- unsigned char probe_val = ~(1 << PIC_CASCADE_IR);
- unsigned char new_val;
+
+ /*
+ * If MADT has the PCAT_COMPAT flag set, then do not bother probing
+ * for the PIC. Some BIOSes leave the PIC uninitialized and probing
+ * fails.
+ *
+ * Right now this causes problems as quite some code depends on
+ * nr_legacy_irqs() > 0 or has_legacy_pic() == true. This is silly
+ * when the system has an IO/APIC because then PIC is not required
+ * at all, except for really old machines where the timer interrupt
+ * must be routed through the PIC. So just pretend that the PIC is
+ * there and let legacy_pic->init() initialize it for nothing.
+ *
+ * Alternatively this could just try to initialize the PIC and
+ * repeat the probe, but for cases where there is no PIC that's
+ * just pointless.
+ */
+ if (pcat_compat)
+ return nr_legacy_irqs();
+
/*
- * Check to see if we have a PIC.
- * Mask all except the cascade and read
- * back the value we just wrote. If we don't
- * have a PIC, we will read 0xff as opposed to the
- * value we wrote.
+ * Check to see if we have a PIC. Mask all except the cascade and
+ * read back the value we just wrote. If we don't have a PIC, we
+ * will read 0xff as opposed to the value we wrote.
*/
raw_spin_lock_irqsave(&i8259A_lock, flags);
@@ -429,5 +447,9 @@ static int __init i8259A_init_ops(void)
return 0;
}
-
device_initcall(i8259A_init_ops);
+
+void __init legacy_pic_pcat_compat(void)
+{
+ pcat_compat = true;
+}
diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c
index b786d48f5a0f..660b601f1d6c 100644
--- a/arch/x86/kernel/idt.c
+++ b/arch/x86/kernel/idt.c
@@ -10,6 +10,7 @@
#include <asm/proto.h>
#include <asm/desc.h>
#include <asm/hw_irq.h>
+#include <asm/ia32.h>
#include <asm/idtentry.h>
#define DPL0 0x0
@@ -116,8 +117,11 @@ static const __initconst struct idt_data def_idts[] = {
#endif
SYSG(X86_TRAP_OF, asm_exc_overflow),
+};
+
+static const struct idt_data ia32_idt[] __initconst = {
#if defined(CONFIG_IA32_EMULATION)
- SYSG(IA32_SYSCALL_VECTOR, entry_INT80_compat),
+ SYSG(IA32_SYSCALL_VECTOR, asm_int80_emulation),
#elif defined(CONFIG_X86_32)
SYSG(IA32_SYSCALL_VECTOR, entry_INT80_32),
#endif
@@ -225,6 +229,9 @@ void __init idt_setup_early_traps(void)
void __init idt_setup_traps(void)
{
idt_setup_from_table(idt_table, def_idts, ARRAY_SIZE(def_idts), true);
+
+ if (ia32_enabled())
+ idt_setup_from_table(idt_table, ia32_idt, ARRAY_SIZE(ia32_idt), true);
}
#ifdef CONFIG_X86_64
diff --git a/arch/x86/kernel/irqflags.S b/arch/x86/kernel/irqflags.S
index aaf9e776f323..7f542a7799cb 100644
--- a/arch/x86/kernel/irqflags.S
+++ b/arch/x86/kernel/irqflags.S
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <asm/asm.h>
-#include <asm/export.h>
+#include <linux/export.h>
#include <linux/linkage.h>
/*
diff --git a/arch/x86/kernel/itmt.c b/arch/x86/kernel/itmt.c
index ee4fe8cdb857..9a7c03d47861 100644
--- a/arch/x86/kernel/itmt.c
+++ b/arch/x86/kernel/itmt.c
@@ -74,7 +74,6 @@ static struct ctl_table itmt_kern_table[] = {
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
- {}
};
static struct ctl_table_header *itmt_sysctl_header;
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index b8ab9ee5896c..0ddb3bd0f1aa 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -500,13 +500,13 @@ static bool pv_sched_yield_supported(void)
static void __send_ipi_mask(const struct cpumask *mask, int vector)
{
unsigned long flags;
- int cpu, apic_id, icr;
- int min = 0, max = 0;
+ int cpu, min = 0, max = 0;
#ifdef CONFIG_X86_64
__uint128_t ipi_bitmap = 0;
#else
u64 ipi_bitmap = 0;
#endif
+ u32 apic_id, icr;
long ret;
if (cpumask_empty(mask))
@@ -1028,8 +1028,8 @@ arch_initcall(activate_jump_labels);
/* Kick a cpu by its apicid. Used to wake up a halted vcpu */
static void kvm_kick_cpu(int cpu)
{
- int apicid;
unsigned long flags = 0;
+ u32 apicid;
apicid = per_cpu(x86_cpu_to_apicid, cpu);
kvm_hypercall2(KVM_HC_KICK_CPU, flags, apicid);
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
index a0c551846b35..17e955ab69fe 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -33,6 +33,7 @@
#include <asm/reboot.h>
#include <asm/cache.h>
#include <asm/nospec-branch.h>
+#include <asm/microcode.h>
#include <asm/sev.h>
#define CREATE_TRACE_POINTS
@@ -343,6 +344,9 @@ static noinstr void default_do_nmi(struct pt_regs *regs)
instrumentation_begin();
+ if (microcode_nmi_handler_enabled() && microcode_nmi_handler())
+ goto out;
+
handled = nmi_handle(NMI_LOCAL, regs);
__this_cpu_add(nmi_stats.normal, handled);
if (handled) {
@@ -498,8 +502,11 @@ DEFINE_IDTENTRY_RAW(exc_nmi)
if (IS_ENABLED(CONFIG_NMI_CHECK_CPU))
raw_atomic_long_inc(&nsp->idt_calls);
- if (IS_ENABLED(CONFIG_SMP) && arch_cpu_is_offline(smp_processor_id()))
+ if (IS_ENABLED(CONFIG_SMP) && arch_cpu_is_offline(smp_processor_id())) {
+ if (microcode_nmi_handler_enabled())
+ microcode_offline_nmi_handler();
return;
+ }
if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) {
this_cpu_write(nmi_state, NMI_LATCHED);
@@ -507,12 +514,13 @@ DEFINE_IDTENTRY_RAW(exc_nmi)
}
this_cpu_write(nmi_state, NMI_EXECUTING);
this_cpu_write(nmi_cr2, read_cr2());
+
+nmi_restart:
if (IS_ENABLED(CONFIG_NMI_CHECK_CPU)) {
WRITE_ONCE(nsp->idt_seq, nsp->idt_seq + 1);
WARN_ON_ONCE(!(nsp->idt_seq & 0x1));
WRITE_ONCE(nsp->recv_jiffies, jiffies);
}
-nmi_restart:
/*
* Needs to happen before DR7 is accessed, because the hypervisor can
@@ -548,16 +556,16 @@ nmi_restart:
if (unlikely(this_cpu_read(nmi_cr2) != read_cr2()))
write_cr2(this_cpu_read(nmi_cr2));
- if (this_cpu_dec_return(nmi_state))
- goto nmi_restart;
-
- if (user_mode(regs))
- mds_user_clear_cpu_buffers();
if (IS_ENABLED(CONFIG_NMI_CHECK_CPU)) {
WRITE_ONCE(nsp->idt_seq, nsp->idt_seq + 1);
WARN_ON_ONCE(nsp->idt_seq & 0x1);
WRITE_ONCE(nsp->recv_jiffies, jiffies);
}
+ if (this_cpu_dec_return(nmi_state))
+ goto nmi_restart;
+
+ if (user_mode(regs))
+ mds_user_clear_cpu_buffers();
}
#if IS_ENABLED(CONFIG_KVM_INTEL)
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index b098b1fa2470..1526747bedf2 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -466,154 +466,29 @@ static void __init memblock_x86_reserve_range_setup_data(void)
}
}
-/*
- * --------- Crashkernel reservation ------------------------------
- */
-
-/* 16M alignment for crash kernel regions */
-#define CRASH_ALIGN SZ_16M
-
-/*
- * Keep the crash kernel below this limit.
- *
- * Earlier 32-bits kernels would limit the kernel to the low 512 MB range
- * due to mapping restrictions.
- *
- * 64-bit kdump kernels need to be restricted to be under 64 TB, which is
- * the upper limit of system RAM in 4-level paging mode. Since the kdump
- * jump could be from 5-level paging to 4-level paging, the jump will fail if
- * the kernel is put above 64 TB, and during the 1st kernel bootup there's
- * no good way to detect the paging mode of the target kernel which will be
- * loaded for dumping.
- */
-#ifdef CONFIG_X86_32
-# define CRASH_ADDR_LOW_MAX SZ_512M
-# define CRASH_ADDR_HIGH_MAX SZ_512M
-#else
-# define CRASH_ADDR_LOW_MAX SZ_4G
-# define CRASH_ADDR_HIGH_MAX SZ_64T
-#endif
-
-static int __init reserve_crashkernel_low(void)
-{
-#ifdef CONFIG_X86_64
- unsigned long long base, low_base = 0, low_size = 0;
- unsigned long low_mem_limit;
- int ret;
-
- low_mem_limit = min(memblock_phys_mem_size(), CRASH_ADDR_LOW_MAX);
-
- /* crashkernel=Y,low */
- ret = parse_crashkernel_low(boot_command_line, low_mem_limit, &low_size, &base);
- if (ret) {
- /*
- * two parts from kernel/dma/swiotlb.c:
- * -swiotlb size: user-specified with swiotlb= or default.
- *
- * -swiotlb overflow buffer: now hardcoded to 32k. We round it
- * to 8M for other buffers that may need to stay low too. Also
- * make sure we allocate enough extra low memory so that we
- * don't run out of DMA buffers for 32-bit devices.
- */
- low_size = max(swiotlb_size_or_default() + (8UL << 20), 256UL << 20);
- } else {
- /* passed with crashkernel=0,low ? */
- if (!low_size)
- return 0;
- }
-
- low_base = memblock_phys_alloc_range(low_size, CRASH_ALIGN, 0, CRASH_ADDR_LOW_MAX);
- if (!low_base) {
- pr_err("Cannot reserve %ldMB crashkernel low memory, please try smaller size.\n",
- (unsigned long)(low_size >> 20));
- return -ENOMEM;
- }
-
- pr_info("Reserving %ldMB of low memory at %ldMB for crashkernel (low RAM limit: %ldMB)\n",
- (unsigned long)(low_size >> 20),
- (unsigned long)(low_base >> 20),
- (unsigned long)(low_mem_limit >> 20));
-
- crashk_low_res.start = low_base;
- crashk_low_res.end = low_base + low_size - 1;
- insert_resource(&iomem_resource, &crashk_low_res);
-#endif
- return 0;
-}
-
-static void __init reserve_crashkernel(void)
+static void __init arch_reserve_crashkernel(void)
{
- unsigned long long crash_size, crash_base, total_mem;
+ unsigned long long crash_base, crash_size, low_size = 0;
+ char *cmdline = boot_command_line;
bool high = false;
int ret;
if (!IS_ENABLED(CONFIG_KEXEC_CORE))
return;
- total_mem = memblock_phys_mem_size();
-
- /* crashkernel=XM */
- ret = parse_crashkernel(boot_command_line, total_mem, &crash_size, &crash_base);
- if (ret != 0 || crash_size <= 0) {
- /* crashkernel=X,high */
- ret = parse_crashkernel_high(boot_command_line, total_mem,
- &crash_size, &crash_base);
- if (ret != 0 || crash_size <= 0)
- return;
- high = true;
- }
+ ret = parse_crashkernel(cmdline, memblock_phys_mem_size(),
+ &crash_size, &crash_base,
+ &low_size, &high);
+ if (ret)
+ return;
if (xen_pv_domain()) {
pr_info("Ignoring crashkernel for a Xen PV domain\n");
return;
}
- /* 0 means: find the address automatically */
- if (!crash_base) {
- /*
- * Set CRASH_ADDR_LOW_MAX upper bound for crash memory,
- * crashkernel=x,high reserves memory over 4G, also allocates
- * 256M extra low memory for DMA buffers and swiotlb.
- * But the extra memory is not required for all machines.
- * So try low memory first and fall back to high memory
- * unless "crashkernel=size[KMG],high" is specified.
- */
- if (!high)
- crash_base = memblock_phys_alloc_range(crash_size,
- CRASH_ALIGN, CRASH_ALIGN,
- CRASH_ADDR_LOW_MAX);
- if (!crash_base)
- crash_base = memblock_phys_alloc_range(crash_size,
- CRASH_ALIGN, CRASH_ALIGN,
- CRASH_ADDR_HIGH_MAX);
- if (!crash_base) {
- pr_info("crashkernel reservation failed - No suitable area found.\n");
- return;
- }
- } else {
- unsigned long long start;
-
- start = memblock_phys_alloc_range(crash_size, SZ_1M, crash_base,
- crash_base + crash_size);
- if (start != crash_base) {
- pr_info("crashkernel reservation failed - memory is in use.\n");
- return;
- }
- }
-
- if (crash_base >= (1ULL << 32) && reserve_crashkernel_low()) {
- memblock_phys_free(crash_base, crash_size);
- return;
- }
-
- pr_info("Reserving %ldMB of memory at %ldMB for crashkernel (System RAM: %ldMB)\n",
- (unsigned long)(crash_size >> 20),
- (unsigned long)(crash_base >> 20),
- (unsigned long)(total_mem >> 20));
-
- crashk_res.start = crash_base;
- crashk_res.end = crash_base + crash_size - 1;
- insert_resource(&iomem_resource, &crashk_res);
+ reserve_crashkernel_generic(cmdline, crash_size, crash_base,
+ low_size, high);
}
static struct resource standard_io_resources[] = {
@@ -1120,7 +995,7 @@ void __init setup_arch(char **cmdline_p)
* Needs to run after memblock setup because it needs the physical
* memory size.
*/
- sev_setup_arch();
+ mem_encrypt_setup_arch();
efi_fake_memmap();
efi_find_mirror();
@@ -1217,6 +1092,8 @@ void __init setup_arch(char **cmdline_p)
early_acpi_boot_init();
+ x86_flattree_get_config();
+
initmem_init();
dma_contiguous_reserve(max_pfn_mapped << PAGE_SHIFT);
@@ -1227,7 +1104,7 @@ void __init setup_arch(char **cmdline_p)
* Reserve memory for crash kernel after SRAT is parsed so that it
* won't consume hotpluggable memory.
*/
- reserve_crashkernel();
+ arch_reserve_crashkernel();
memblock_find_dma_reserve();
@@ -1290,7 +1167,7 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
if (!efi_enabled(EFI_BOOT) || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
- conswitchp = &vga_con;
+ vgacon_register_screen(&screen_info);
#endif
#endif
x86_init.oem.banner();
diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
index dcf325b7b022..ccb0915e84e1 100644
--- a/arch/x86/kernel/sev-shared.c
+++ b/arch/x86/kernel/sev-shared.c
@@ -632,6 +632,23 @@ fail:
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
}
+static enum es_result vc_insn_string_check(struct es_em_ctxt *ctxt,
+ unsigned long address,
+ bool write)
+{
+ if (user_mode(ctxt->regs) && fault_in_kernel_space(address)) {
+ ctxt->fi.vector = X86_TRAP_PF;
+ ctxt->fi.error_code = X86_PF_USER;
+ ctxt->fi.cr2 = address;
+ if (write)
+ ctxt->fi.error_code |= X86_PF_WRITE;
+
+ return ES_EXCEPTION;
+ }
+
+ return ES_OK;
+}
+
static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt,
void *src, char *buf,
unsigned int data_size,
@@ -639,7 +656,12 @@ static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt,
bool backwards)
{
int i, b = backwards ? -1 : 1;
- enum es_result ret = ES_OK;
+ unsigned long address = (unsigned long)src;
+ enum es_result ret;
+
+ ret = vc_insn_string_check(ctxt, address, false);
+ if (ret != ES_OK)
+ return ret;
for (i = 0; i < count; i++) {
void *s = src + (i * data_size * b);
@@ -660,7 +682,12 @@ static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt,
bool backwards)
{
int i, s = backwards ? -1 : 1;
- enum es_result ret = ES_OK;
+ unsigned long address = (unsigned long)dst;
+ enum es_result ret;
+
+ ret = vc_insn_string_check(ctxt, address, true);
+ if (ret != ES_OK)
+ return ret;
for (i = 0; i < count; i++) {
void *d = dst + (i * data_size * s);
@@ -696,6 +723,9 @@ static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt,
static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
{
struct insn *insn = &ctxt->insn;
+ size_t size;
+ u64 port;
+
*exitinfo = 0;
switch (insn->opcode.bytes[0]) {
@@ -704,7 +734,7 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
case 0x6d:
*exitinfo |= IOIO_TYPE_INS;
*exitinfo |= IOIO_SEG_ES;
- *exitinfo |= (ctxt->regs->dx & 0xffff) << 16;
+ port = ctxt->regs->dx & 0xffff;
break;
/* OUTS opcodes */
@@ -712,41 +742,43 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
case 0x6f:
*exitinfo |= IOIO_TYPE_OUTS;
*exitinfo |= IOIO_SEG_DS;
- *exitinfo |= (ctxt->regs->dx & 0xffff) << 16;
+ port = ctxt->regs->dx & 0xffff;
break;
/* IN immediate opcodes */
case 0xe4:
case 0xe5:
*exitinfo |= IOIO_TYPE_IN;
- *exitinfo |= (u8)insn->immediate.value << 16;
+ port = (u8)insn->immediate.value & 0xffff;
break;
/* OUT immediate opcodes */
case 0xe6:
case 0xe7:
*exitinfo |= IOIO_TYPE_OUT;
- *exitinfo |= (u8)insn->immediate.value << 16;
+ port = (u8)insn->immediate.value & 0xffff;
break;
/* IN register opcodes */
case 0xec:
case 0xed:
*exitinfo |= IOIO_TYPE_IN;
- *exitinfo |= (ctxt->regs->dx & 0xffff) << 16;
+ port = ctxt->regs->dx & 0xffff;
break;
/* OUT register opcodes */
case 0xee:
case 0xef:
*exitinfo |= IOIO_TYPE_OUT;
- *exitinfo |= (ctxt->regs->dx & 0xffff) << 16;
+ port = ctxt->regs->dx & 0xffff;
break;
default:
return ES_DECODE_FAILED;
}
+ *exitinfo |= port << 16;
+
switch (insn->opcode.bytes[0]) {
case 0x6c:
case 0x6e:
@@ -756,12 +788,15 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
case 0xee:
/* Single byte opcodes */
*exitinfo |= IOIO_DATA_8;
+ size = 1;
break;
default:
/* Length determined by instruction parsing */
*exitinfo |= (insn->opnd_bytes == 2) ? IOIO_DATA_16
: IOIO_DATA_32;
+ size = (insn->opnd_bytes == 2) ? 2 : 4;
}
+
switch (insn->addr_bytes) {
case 2:
*exitinfo |= IOIO_ADDR_16;
@@ -777,7 +812,7 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
if (insn_has_rep_prefix(insn))
*exitinfo |= IOIO_REP;
- return ES_OK;
+ return vc_ioio_check(ctxt, (u16)port, size);
}
static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index d8c1e3be74c0..c67285824e82 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -524,6 +524,33 @@ static enum es_result vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt
return ES_OK;
}
+static enum es_result vc_ioio_check(struct es_em_ctxt *ctxt, u16 port, size_t size)
+{
+ BUG_ON(size > 4);
+
+ if (user_mode(ctxt->regs)) {
+ struct thread_struct *t = &current->thread;
+ struct io_bitmap *iobm = t->io_bitmap;
+ size_t idx;
+
+ if (!iobm)
+ goto fault;
+
+ for (idx = port; idx < port + size; ++idx) {
+ if (test_bit(idx, iobm->bitmap))
+ goto fault;
+ }
+ }
+
+ return ES_OK;
+
+fault:
+ ctxt->fi.vector = X86_TRAP_GP;
+ ctxt->fi.error_code = 0;
+
+ return ES_EXCEPTION;
+}
+
/* Include code shared with pre-decompression boot stage */
#include "sev-shared.c"
@@ -939,7 +966,7 @@ static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa)
free_page((unsigned long)vmsa);
}
-static int wakeup_cpu_via_vmgexit(int apic_id, unsigned long start_ip)
+static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
{
struct sev_es_save_area *cur_vmsa, *vmsa;
struct ghcb_state state;
@@ -1207,10 +1234,6 @@ void setup_ghcb(void)
if (!cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT))
return;
- /* First make sure the hypervisor talks a supported protocol. */
- if (!sev_es_negotiate_protocol())
- sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
-
/*
* Check whether the runtime #VC exception handler is active. It uses
* the per-CPU GHCB page which is set up by sev_es_init_vc_handling().
@@ -1228,6 +1251,13 @@ void setup_ghcb(void)
}
/*
+ * Make sure the hypervisor talks a supported protocol.
+ * This gets called only in the BSP boot phase.
+ */
+ if (!sev_es_negotiate_protocol())
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
+
+ /*
* Clear the boot_ghcb. The first exception comes in before the bss
* section is cleared.
*/
@@ -1508,6 +1538,9 @@ static enum es_result vc_handle_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
return ES_DECODE_FAILED;
}
+ if (user_mode(ctxt->regs))
+ return ES_UNSUPPORTED;
+
switch (mmio) {
case INSN_MMIO_WRITE:
memcpy(ghcb->shared_buffer, reg_data, bytes);
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index cacf2ede6217..23d8aaf8d9fd 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -175,9 +175,6 @@ int x64_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
frame = get_sigframe(ksig, regs, sizeof(struct rt_sigframe), &fp);
uc_flags = frame_uc_flags(regs);
- if (setup_signal_shadow_stack(ksig))
- return -EFAULT;
-
if (!user_access_begin(frame, sizeof(*frame)))
return -EFAULT;
@@ -198,6 +195,9 @@ int x64_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
return -EFAULT;
}
+ if (setup_signal_shadow_stack(ksig))
+ return -EFAULT;
+
/* Set up registers for signal handler */
regs->di = ksig->sig;
/* In case the signal handler was declared without prototypes */
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index 6eb06d001bcc..96a771f9f930 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -131,7 +131,7 @@ static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs)
}
/*
- * Disable virtualization, APIC etc. and park the CPU in a HLT loop
+ * this function calls the 'stop' function on all other CPUs in the system.
*/
DEFINE_IDTENTRY_SYSVEC(sysvec_reboot)
{
@@ -172,17 +172,13 @@ static void native_stop_other_cpus(int wait)
* 2) Wait for all other CPUs to report that they reached the
* HLT loop in stop_this_cpu()
*
- * 3) If the system uses INIT/STARTUP for CPU bringup, then
- * send all present CPUs an INIT vector, which brings them
- * completely out of the way.
+ * 3) If #2 timed out send an NMI to the CPUs which did not
+ * yet report
*
- * 4) If #3 is not possible and #2 timed out send an NMI to the
- * CPUs which did not yet report
- *
- * 5) Wait for all other CPUs to report that they reached the
+ * 4) Wait for all other CPUs to report that they reached the
* HLT loop in stop_this_cpu()
*
- * #4 can obviously race against a CPU reaching the HLT loop late.
+ * #3 can obviously race against a CPU reaching the HLT loop late.
* That CPU will have reported already and the "have all CPUs
* reached HLT" condition will be true despite the fact that the
* other CPU is still handling the NMI. Again, there is no
@@ -198,7 +194,7 @@ static void native_stop_other_cpus(int wait)
/*
* Don't wait longer than a second for IPI completion. The
* wait request is not checked here because that would
- * prevent an NMI/INIT shutdown in case that not all
+ * prevent an NMI shutdown attempt in case that not all
* CPUs reach shutdown state.
*/
timeout = USEC_PER_SEC;
@@ -206,27 +202,7 @@ static void native_stop_other_cpus(int wait)
udelay(1);
}
- /*
- * Park all other CPUs in INIT including "offline" CPUs, if
- * possible. That's a safe place where they can't resume execution
- * of HLT and then execute the HLT loop from overwritten text or
- * page tables.
- *
- * The only downside is a broadcast MCE, but up to the point where
- * the kexec() kernel brought all APs online again an MCE will just
- * make HLT resume and handle the MCE. The machine crashes and burns
- * due to overwritten text, page tables and data. So there is a
- * choice between fire and frying pan. The result is pretty much
- * the same. Chose frying pan until x86 provides a sane mechanism
- * to park a CPU.
- */
- if (smp_park_other_cpus_in_init())
- goto done;
-
- /*
- * If park with INIT was not possible and the REBOOT_VECTOR didn't
- * take all secondary CPUs offline, try with the NMI.
- */
+ /* if the REBOOT_VECTOR didn't work, try with the NMI */
if (!cpumask_empty(&cpus_stop_mask)) {
/*
* If NMI IPI is enabled, try to register the stop handler
@@ -249,7 +225,6 @@ static void native_stop_other_cpus(int wait)
udelay(1);
}
-done:
local_irq_save(flags);
disable_local_APIC();
mcheck_cpu_clear(this_cpu_ptr(&cpu_info));
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 48e040618731..2cc2aa120b4b 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -87,6 +87,7 @@
#include <asm/hw_irq.h>
#include <asm/stackprotector.h>
#include <asm/sev.h>
+#include <asm/spec-ctrl.h>
/* representing HT siblings of each logical CPU */
DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map);
@@ -124,7 +125,20 @@ struct mwait_cpu_dead {
*/
static DEFINE_PER_CPU_ALIGNED(struct mwait_cpu_dead, mwait_cpu_dead);
-/* Logical package management. We might want to allocate that dynamically */
+/* Logical package management. */
+struct logical_maps {
+ u32 phys_pkg_id;
+ u32 phys_die_id;
+ u32 logical_pkg_id;
+ u32 logical_die_id;
+};
+
+/* Temporary workaround until the full topology mechanics is in place */
+static DEFINE_PER_CPU_READ_MOSTLY(struct logical_maps, logical_maps) = {
+ .phys_pkg_id = U32_MAX,
+ .phys_die_id = U32_MAX,
+};
+
unsigned int __max_logical_packages __read_mostly;
EXPORT_SYMBOL(__max_logical_packages);
static unsigned int logical_packages __read_mostly;
@@ -258,12 +272,9 @@ static void notrace start_secondary(void *unused)
cpu_init_exception_handling();
/*
- * 32-bit systems load the microcode from the ASM startup code for
- * historical reasons.
- *
- * On 64-bit systems load it before reaching the AP alive
- * synchronization point below so it is not part of the full per
- * CPU serialized bringup part when "parallel" bringup is enabled.
+ * Load the microcode before reaching the AP alive synchronization
+ * point below so it is not part of the full per CPU serialized
+ * bringup part when "parallel" bringup is enabled.
*
* That's even safe when hyperthreading is enabled in the CPU as
* the core code starts the primary threads first and leaves the
@@ -276,8 +287,7 @@ static void notrace start_secondary(void *unused)
* CPUID, MSRs etc. must be strictly serialized to maintain
* software state correctness.
*/
- if (IS_ENABLED(CONFIG_X86_64))
- load_ucode_ap();
+ load_ucode_ap();
/*
* Synchronization point with the hotplug core. Sets this CPUs
@@ -288,7 +298,7 @@ static void notrace start_secondary(void *unused)
cpu_init();
fpu__init_cpu();
- rcu_cpu_starting(raw_smp_processor_id());
+ rcutree_report_cpu_starting(raw_smp_processor_id());
x86_cpuinit.early_percpu_clock_init();
ap_starting();
@@ -337,10 +347,8 @@ int topology_phys_to_logical_pkg(unsigned int phys_pkg)
int cpu;
for_each_possible_cpu(cpu) {
- struct cpuinfo_x86 *c = &cpu_data(cpu);
-
- if (c->initialized && c->phys_proc_id == phys_pkg)
- return c->logical_proc_id;
+ if (per_cpu(logical_maps.phys_pkg_id, cpu) == phys_pkg)
+ return per_cpu(logical_maps.logical_pkg_id, cpu);
}
return -1;
}
@@ -355,14 +363,12 @@ EXPORT_SYMBOL(topology_phys_to_logical_pkg);
*/
static int topology_phys_to_logical_die(unsigned int die_id, unsigned int cur_cpu)
{
- int cpu, proc_id = cpu_data(cur_cpu).phys_proc_id;
+ int cpu, proc_id = cpu_data(cur_cpu).topo.pkg_id;
for_each_possible_cpu(cpu) {
- struct cpuinfo_x86 *c = &cpu_data(cpu);
-
- if (c->initialized && c->cpu_die_id == die_id &&
- c->phys_proc_id == proc_id)
- return c->logical_die_id;
+ if (per_cpu(logical_maps.phys_pkg_id, cpu) == proc_id &&
+ per_cpu(logical_maps.phys_die_id, cpu) == die_id)
+ return per_cpu(logical_maps.logical_die_id, cpu);
}
return -1;
}
@@ -387,7 +393,9 @@ int topology_update_package_map(unsigned int pkg, unsigned int cpu)
cpu, pkg, new);
}
found:
- cpu_data(cpu).logical_proc_id = new;
+ per_cpu(logical_maps.phys_pkg_id, cpu) = pkg;
+ per_cpu(logical_maps.logical_pkg_id, cpu) = new;
+ cpu_data(cpu).topo.logical_pkg_id = new;
return 0;
}
/**
@@ -410,7 +418,9 @@ int topology_update_die_map(unsigned int die, unsigned int cpu)
cpu, die, new);
}
found:
- cpu_data(cpu).logical_die_id = new;
+ per_cpu(logical_maps.phys_die_id, cpu) = die;
+ per_cpu(logical_maps.logical_die_id, cpu) = new;
+ cpu_data(cpu).topo.logical_die_id = new;
return 0;
}
@@ -421,8 +431,8 @@ static void __init smp_store_boot_cpu_info(void)
*c = boot_cpu_data;
c->cpu_index = id;
- topology_update_package_map(c->phys_proc_id, id);
- topology_update_die_map(c->cpu_die_id, id);
+ topology_update_package_map(c->topo.pkg_id, id);
+ topology_update_die_map(c->topo.die_id, id);
c->initialized = true;
}
@@ -476,21 +486,21 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
- if (c->phys_proc_id == o->phys_proc_id &&
- c->cpu_die_id == o->cpu_die_id &&
- per_cpu(cpu_llc_id, cpu1) == per_cpu(cpu_llc_id, cpu2)) {
- if (c->cpu_core_id == o->cpu_core_id)
+ if (c->topo.pkg_id == o->topo.pkg_id &&
+ c->topo.die_id == o->topo.die_id &&
+ per_cpu_llc_id(cpu1) == per_cpu_llc_id(cpu2)) {
+ if (c->topo.core_id == o->topo.core_id)
return topology_sane(c, o, "smt");
- if ((c->cu_id != 0xff) &&
- (o->cu_id != 0xff) &&
- (c->cu_id == o->cu_id))
+ if ((c->topo.cu_id != 0xff) &&
+ (o->topo.cu_id != 0xff) &&
+ (c->topo.cu_id == o->topo.cu_id))
return topology_sane(c, o, "smt");
}
- } else if (c->phys_proc_id == o->phys_proc_id &&
- c->cpu_die_id == o->cpu_die_id &&
- c->cpu_core_id == o->cpu_core_id) {
+ } else if (c->topo.pkg_id == o->topo.pkg_id &&
+ c->topo.die_id == o->topo.die_id &&
+ c->topo.core_id == o->topo.core_id) {
return topology_sane(c, o, "smt");
}
@@ -499,8 +509,8 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
static bool match_die(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
{
- if (c->phys_proc_id == o->phys_proc_id &&
- c->cpu_die_id == o->cpu_die_id)
+ if (c->topo.pkg_id == o->topo.pkg_id &&
+ c->topo.die_id == o->topo.die_id)
return true;
return false;
}
@@ -510,11 +520,11 @@ static bool match_l2c(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
/* If the arch didn't set up l2c_id, fall back to SMT */
- if (per_cpu(cpu_l2c_id, cpu1) == BAD_APICID)
+ if (per_cpu_l2c_id(cpu1) == BAD_APICID)
return match_smt(c, o);
/* Do not match if L2 cache id does not match: */
- if (per_cpu(cpu_l2c_id, cpu1) != per_cpu(cpu_l2c_id, cpu2))
+ if (per_cpu_l2c_id(cpu1) != per_cpu_l2c_id(cpu2))
return false;
return topology_sane(c, o, "l2c");
@@ -527,7 +537,7 @@ static bool match_l2c(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
*/
static bool match_pkg(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
{
- if (c->phys_proc_id == o->phys_proc_id)
+ if (c->topo.pkg_id == o->topo.pkg_id)
return true;
return false;
}
@@ -560,11 +570,11 @@ static bool match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
bool intel_snc = id && id->driver_data;
/* Do not match if we do not have a valid APICID for cpu: */
- if (per_cpu(cpu_llc_id, cpu1) == BAD_APICID)
+ if (per_cpu_llc_id(cpu1) == BAD_APICID)
return false;
/* Do not match if LLC id does not match: */
- if (per_cpu(cpu_llc_id, cpu1) != per_cpu(cpu_llc_id, cpu2))
+ if (per_cpu_llc_id(cpu1) != per_cpu_llc_id(cpu2))
return false;
/*
@@ -640,13 +650,13 @@ static void __init build_sched_topology(void)
};
#endif
/*
- * When there is NUMA topology inside the package skip the DIE domain
+ * When there is NUMA topology inside the package skip the PKG domain
* since the NUMA domains will auto-magically create the right spanning
* domains based on the SLIT.
*/
if (!x86_has_numa_in_package) {
x86_topology[i++] = (struct sched_domain_topology_level){
- cpu_cpu_mask, x86_die_flags, SD_INIT_NAME(DIE)
+ cpu_cpu_mask, x86_die_flags, SD_INIT_NAME(PKG)
};
}
@@ -809,7 +819,7 @@ static void __init smp_quirk_init_udelay(void)
/*
* Wake up AP by INIT, INIT, STARTUP sequence.
*/
-static void send_init_sequence(int phys_apicid)
+static void send_init_sequence(u32 phys_apicid)
{
int maxlvt = lapic_get_maxlvt();
@@ -835,7 +845,7 @@ static void send_init_sequence(int phys_apicid)
/*
* Wake up AP by INIT, INIT, STARTUP sequence.
*/
-static int wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
+static int wakeup_secondary_cpu_via_init(u32 phys_apicid, unsigned long start_eip)
{
unsigned long send_status = 0, accept_status = 0;
int num_starts, j, maxlvt;
@@ -982,7 +992,7 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
* Returns zero if startup was successfully sent, else error code from
* ->wakeup_secondary_cpu.
*/
-static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
+static int do_boot_cpu(u32 apicid, int cpu, struct task_struct *idle)
{
unsigned long start_ip = real_mode_header->trampoline_start;
int ret;
@@ -1050,7 +1060,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
int native_kick_ap(unsigned int cpu, struct task_struct *tidle)
{
- int apicid = apic->cpu_present_to_apicid(cpu);
+ u32 apicid = apic->cpu_present_to_apicid(cpu);
int err;
lockdep_assert_irqs_enabled();
@@ -1240,33 +1250,6 @@ void arch_thaw_secondary_cpus_end(void)
cache_aps_init();
}
-bool smp_park_other_cpus_in_init(void)
-{
- unsigned int cpu, this_cpu = smp_processor_id();
- unsigned int apicid;
-
- if (apic->wakeup_secondary_cpu_64 || apic->wakeup_secondary_cpu)
- return false;
-
- /*
- * If this is a crash stop which does not execute on the boot CPU,
- * then this cannot use the INIT mechanism because INIT to the boot
- * CPU will reset the machine.
- */
- if (this_cpu)
- return false;
-
- for_each_cpu_and(cpu, &cpus_booted_once_mask, cpu_present_mask) {
- if (cpu == this_cpu)
- continue;
- apicid = apic->cpu_present_to_apicid(cpu);
- if (apicid == BAD_APICID)
- continue;
- send_init_sequence(apicid);
- }
- return true;
-}
-
/*
* Early setup to make printk work.
*/
@@ -1432,7 +1415,7 @@ static void remove_siblinginfo(int cpu)
cpumask_clear(topology_sibling_cpumask(cpu));
cpumask_clear(topology_core_cpumask(cpu));
cpumask_clear(topology_die_cpumask(cpu));
- c->cpu_core_id = 0;
+ c->topo.core_id = 0;
c->booted_cores = 0;
cpumask_clear_cpu(cpu, cpu_sibling_setup_mask);
recompute_smt_state();
@@ -1623,8 +1606,15 @@ void __noreturn hlt_play_dead(void)
native_halt();
}
+/*
+ * native_play_dead() is essentially a __noreturn function, but it can't
+ * be marked as such as the compiler may complain about it.
+ */
void native_play_dead(void)
{
+ if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS))
+ __update_spec_ctrl(0);
+
play_dead_common();
tboot_shutdown(TB_SHUTDOWN_WFS);
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c
index ca004e2e4469..0bab03130033 100644
--- a/arch/x86/kernel/topology.c
+++ b/arch/x86/kernel/topology.c
@@ -54,7 +54,7 @@ void arch_unregister_cpu(int num)
EXPORT_SYMBOL(arch_unregister_cpu);
#else /* CONFIG_HOTPLUG_CPU */
-static int __init arch_register_cpu(int num)
+int __init arch_register_cpu(int num)
{
return register_cpu(&per_cpu(cpu_devices, num).cpu, num);
}
diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c
index bbc440c93e08..1123ef3ccf90 100644
--- a/arch/x86/kernel/tsc_sync.c
+++ b/arch/x86/kernel/tsc_sync.c
@@ -15,6 +15,7 @@
* ( The serial nature of the boot logic and the CPU hotplug lock
* protects against more than 2 CPUs entering this code. )
*/
+#include <linux/workqueue.h>
#include <linux/topology.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
@@ -342,6 +343,13 @@ static inline unsigned int loop_timeout(int cpu)
return (cpumask_weight(topology_core_cpumask(cpu)) > 1) ? 2 : 20;
}
+static void tsc_sync_mark_tsc_unstable(struct work_struct *work)
+{
+ mark_tsc_unstable("check_tsc_sync_source failed");
+}
+
+static DECLARE_WORK(tsc_sync_work, tsc_sync_mark_tsc_unstable);
+
/*
* The freshly booted CPU initiates this via an async SMP function call.
*/
@@ -395,7 +403,7 @@ retry:
"turning off TSC clock.\n", max_warp);
if (random_warps)
pr_warn("TSC warped randomly between CPUs\n");
- mark_tsc_unstable("check_tsc_sync_source failed");
+ schedule_work(&tsc_sync_work);
}
/*
diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c
index 7e574cf3bf8a..d00c28aaa5be 100644
--- a/arch/x86/kernel/unwind_orc.c
+++ b/arch/x86/kernel/unwind_orc.c
@@ -85,7 +85,7 @@ static struct orc_entry *__orc_find(int *ip_table, struct orc_entry *u_table,
{
int *first = ip_table;
int *last = ip_table + num_entries - 1;
- int *mid = first, *found = first;
+ int *mid, *found = first;
if (!num_entries)
return NULL;
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index f15fb71f280e..54a5596adaa6 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -139,10 +139,7 @@ SECTIONS
STATIC_CALL_TEXT
ALIGN_ENTRY_TEXT_BEGIN
-#ifdef CONFIG_CPU_SRSO
*(.text..__x86.rethunk_untrain)
-#endif
-
ENTRY_TEXT
#ifdef CONFIG_CPU_SRSO
@@ -520,12 +517,12 @@ INIT_PER_CPU(irq_stack_backing_store);
"fixed_percpu_data is not at start of per-cpu area");
#endif
-#ifdef CONFIG_RETHUNK
+#ifdef CONFIG_CPU_UNRET_ENTRY
. = ASSERT((retbleed_return_thunk & 0x3f) == 0, "retbleed_return_thunk not cacheline-aligned");
-. = ASSERT((srso_safe_ret & 0x3f) == 0, "srso_safe_ret not cacheline-aligned");
#endif
#ifdef CONFIG_CPU_SRSO
+. = ASSERT((srso_safe_ret & 0x3f) == 0, "srso_safe_ret not cacheline-aligned");
/*
* GNU ld cannot do XOR until 2.41.
* https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=f6f78318fca803c4907fb8d7f6ded8295f1947b1
diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c
index 65e96b76c423..d3fc01770558 100644
--- a/arch/x86/kernel/vsmp_64.c
+++ b/arch/x86/kernel/vsmp_64.c
@@ -127,7 +127,7 @@ static void __init vsmp_cap_cpus(void)
#endif
}
-static int apicid_phys_pkg_id(int initial_apic_id, int index_msb)
+static u32 apicid_phys_pkg_id(u32 initial_apic_id, int index_msb)
{
return read_apic_id() >> index_msb;
}
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index ed90f148140d..950c12868d30 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -154,4 +154,15 @@ config KVM_PROVE_MMU
config KVM_EXTERNAL_WRITE_TRACKING
bool
+config KVM_MAX_NR_VCPUS
+ int "Maximum number of vCPUs per KVM guest"
+ depends on KVM
+ range 1024 4096
+ default 4096 if MAXSMP
+ default 1024
+ help
+ Set the maximum number of vCPUs per KVM guest. Larger values will increase
+ the memory footprint of each KVM guest, regardless of how many vCPUs are
+ created for a given VM.
+
endif # VIRTUALIZATION
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 0544e30b4946..dda6fc4cfae8 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -360,14 +360,6 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
vcpu->arch.guest_supported_xcr0 =
cpuid_get_supported_xcr0(vcpu->arch.cpuid_entries, vcpu->arch.cpuid_nent);
- /*
- * FP+SSE can always be saved/restored via KVM_{G,S}ET_XSAVE, even if
- * XSAVE/XCRO are not exposed to the guest, and even if XSAVE isn't
- * supported by the host.
- */
- vcpu->arch.guest_fpu.fpstate->user_xfeatures = vcpu->arch.guest_supported_xcr0 |
- XFEATURE_MASK_FPSSE;
-
kvm_update_pv_runtime(vcpu);
vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
@@ -456,7 +448,9 @@ static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2,
vcpu->arch.cpuid_nent = nent;
vcpu->arch.kvm_cpuid = kvm_get_hypervisor_cpuid(vcpu, KVM_SIGNATURE);
+#ifdef CONFIG_KVM_XEN
vcpu->arch.xen.cpuid = kvm_get_hypervisor_cpuid(vcpu, XEN_SIGNATURE);
+#endif
kvm_vcpu_after_set_cpuid(vcpu);
return 0;
@@ -761,11 +755,13 @@ void kvm_set_cpu_caps(void)
kvm_cpu_cap_mask(CPUID_8000_0021_EAX,
F(NO_NESTED_DATA_BP) | F(LFENCE_RDTSC) | 0 /* SmmPgCfgLock */ |
- F(NULL_SEL_CLR_BASE) | F(AUTOIBRS) | 0 /* PrefetchCtlMsr */
+ F(NULL_SEL_CLR_BASE) | F(AUTOIBRS) | 0 /* PrefetchCtlMsr */ |
+ F(WRMSR_XX_BASE_NS)
);
- if (cpu_feature_enabled(X86_FEATURE_SRSO_NO))
- kvm_cpu_cap_set(X86_FEATURE_SRSO_NO);
+ kvm_cpu_cap_check_and_set(X86_FEATURE_SBPB);
+ kvm_cpu_cap_check_and_set(X86_FEATURE_IBPB_BRTYPE);
+ kvm_cpu_cap_check_and_set(X86_FEATURE_SRSO_NO);
kvm_cpu_cap_init_kvm_defined(CPUID_8000_0022_EAX,
F(PERFMON_V2)
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index 284fa4704553..0b90532b6e26 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -174,7 +174,8 @@ static inline bool guest_has_spec_ctrl_msr(struct kvm_vcpu *vcpu)
static inline bool guest_has_pred_cmd_msr(struct kvm_vcpu *vcpu)
{
return (guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) ||
- guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBPB));
+ guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBPB) ||
+ guest_cpuid_has(vcpu, X86_FEATURE_SBPB));
}
static inline bool supports_cpuid_fault(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/debugfs.c b/arch/x86/kvm/debugfs.c
index ee8c4c3496ed..eea6ea7f14af 100644
--- a/arch/x86/kvm/debugfs.c
+++ b/arch/x86/kvm/debugfs.c
@@ -182,6 +182,7 @@ static int kvm_mmu_rmaps_stat_release(struct inode *inode, struct file *file)
}
static const struct file_operations mmu_rmaps_stat_fops = {
+ .owner = THIS_MODULE,
.open = kvm_mmu_rmaps_stat_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 7c2dac6824e2..238afd7335e4 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -727,10 +727,12 @@ static int stimer_set_count(struct kvm_vcpu_hv_stimer *stimer, u64 count,
stimer_cleanup(stimer);
stimer->count = count;
- if (stimer->count == 0)
- stimer->config.enable = 0;
- else if (stimer->config.auto_enable)
- stimer->config.enable = 1;
+ if (!host) {
+ if (stimer->count == 0)
+ stimer->config.enable = 0;
+ else if (stimer->config.auto_enable)
+ stimer->config.enable = 1;
+ }
if (stimer->config.enable)
stimer_mark_pending(stimer, false);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index dcd60b39e794..245b20973cae 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2444,22 +2444,22 @@ EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset)
{
struct kvm_lapic *apic = vcpu->arch.apic;
- u64 val;
/*
- * ICR is a single 64-bit register when x2APIC is enabled. For legacy
- * xAPIC, ICR writes need to go down the common (slightly slower) path
- * to get the upper half from ICR2.
+ * ICR is a single 64-bit register when x2APIC is enabled, all others
+ * registers hold 32-bit values. For legacy xAPIC, ICR writes need to
+ * go down the common path to get the upper half from ICR2.
+ *
+ * Note, using the write helpers may incur an unnecessary write to the
+ * virtual APIC state, but KVM needs to conditionally modify the value
+ * in certain cases, e.g. to clear the ICR busy bit. The cost of extra
+ * conditional branches is likely a wash relative to the cost of the
+ * maybe-unecessary write, and both are in the noise anyways.
*/
- if (apic_x2apic_mode(apic) && offset == APIC_ICR) {
- val = kvm_lapic_get_reg64(apic, APIC_ICR);
- kvm_apic_send_ipi(apic, (u32)val, (u32)(val >> 32));
- trace_kvm_apic_write(APIC_ICR, val);
- } else {
- /* TODO: optimize to just emulate side effect w/o one more write */
- val = kvm_lapic_get_reg(apic, offset);
- kvm_lapic_reg_write(apic, offset, (u32)val);
- }
+ if (apic_x2apic_mode(apic) && offset == APIC_ICR)
+ kvm_x2apic_icr_write(apic, kvm_lapic_get_reg64(apic, APIC_ICR));
+ else
+ kvm_lapic_reg_write(apic, offset, kvm_lapic_get_reg(apic, offset));
}
EXPORT_SYMBOL_GPL(kvm_apic_write_nodecode);
@@ -2670,6 +2670,8 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
u64 msr_val;
int i;
+ static_call_cond(kvm_x86_apicv_pre_state_restore)(vcpu);
+
if (!init_event) {
msr_val = APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE;
if (kvm_vcpu_is_reset_bsp(vcpu))
@@ -2759,13 +2761,17 @@ int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type)
{
u32 reg = kvm_lapic_get_reg(apic, lvt_type);
int vector, mode, trig_mode;
+ int r;
if (kvm_apic_hw_enabled(apic) && !(reg & APIC_LVT_MASKED)) {
vector = reg & APIC_VECTOR_MASK;
mode = reg & APIC_MODE_MASK;
trig_mode = reg & APIC_LVT_LEVEL_TRIGGER;
- return __apic_accept_irq(apic, mode, vector, 1, trig_mode,
- NULL);
+
+ r = __apic_accept_irq(apic, mode, vector, 1, trig_mode, NULL);
+ if (r && lvt_type == APIC_LVTPC)
+ kvm_lapic_set_reg(apic, APIC_LVTPC, reg | APIC_LVT_MASKED);
+ return r;
}
return 0;
}
@@ -2977,6 +2983,8 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
struct kvm_lapic *apic = vcpu->arch.apic;
int r;
+ static_call_cond(kvm_x86_apicv_pre_state_restore)(vcpu);
+
kvm_lapic_set_base(vcpu, vcpu->arch.apic_base);
/* set SPIV separately to get count of SW disabled APICs right */
apic_set_spiv(apic, *((u32 *)(s->regs + APIC_SPIV)));
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 253fb2093d5d..bb8c86eefac0 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -237,6 +237,13 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
return -(u32)fault & errcode;
}
+bool __kvm_mmu_honors_guest_mtrrs(bool vm_has_noncoherent_dma);
+
+static inline bool kvm_mmu_honors_guest_mtrrs(struct kvm *kvm)
+{
+ return __kvm_mmu_honors_guest_mtrrs(kvm_arch_has_noncoherent_dma(kvm));
+}
+
void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end);
int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index f7901cb4d2fa..c57e181bba21 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -3425,8 +3425,8 @@ static int fast_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
{
struct kvm_mmu_page *sp;
int ret = RET_PF_INVALID;
- u64 spte = 0ull;
- u64 *sptep = NULL;
+ u64 spte;
+ u64 *sptep;
uint retry_count = 0;
if (!page_fault_can_be_fast(fault))
@@ -3442,6 +3442,14 @@ static int fast_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
else
sptep = fast_pf_get_last_sptep(vcpu, fault->addr, &spte);
+ /*
+ * It's entirely possible for the mapping to have been zapped
+ * by a different task, but the root page should always be
+ * available as the vCPU holds a reference to its root(s).
+ */
+ if (WARN_ON_ONCE(!sptep))
+ spte = REMOVED_SPTE;
+
if (!is_shadow_present_pte(spte))
break;
@@ -4479,21 +4487,28 @@ out_unlock:
}
#endif
-int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
+bool __kvm_mmu_honors_guest_mtrrs(bool vm_has_noncoherent_dma)
{
/*
- * If the guest's MTRRs may be used to compute the "real" memtype,
- * restrict the mapping level to ensure KVM uses a consistent memtype
- * across the entire mapping. If the host MTRRs are ignored by TDP
- * (shadow_memtype_mask is non-zero), and the VM has non-coherent DMA
- * (DMA doesn't snoop CPU caches), KVM's ABI is to honor the memtype
- * from the guest's MTRRs so that guest accesses to memory that is
- * DMA'd aren't cached against the guest's wishes.
+ * If host MTRRs are ignored (shadow_memtype_mask is non-zero), and the
+ * VM has non-coherent DMA (DMA doesn't snoop CPU caches), KVM's ABI is
+ * to honor the memtype from the guest's MTRRs so that guest accesses
+ * to memory that is DMA'd aren't cached against the guest's wishes.
*
* Note, KVM may still ultimately ignore guest MTRRs for certain PFNs,
* e.g. KVM will force UC memtype for host MMIO.
*/
- if (shadow_memtype_mask && kvm_arch_has_noncoherent_dma(vcpu->kvm)) {
+ return vm_has_noncoherent_dma && shadow_memtype_mask;
+}
+
+int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
+{
+ /*
+ * If the guest's MTRRs may be used to compute the "real" memtype,
+ * restrict the mapping level to ensure KVM uses a consistent memtype
+ * across the entire mapping.
+ */
+ if (kvm_mmu_honors_guest_mtrrs(vcpu->kvm)) {
for ( ; fault->max_level > PG_LEVEL_4K; --fault->max_level) {
int page_num = KVM_PAGES_PER_HPAGE(fault->max_level);
gfn_t base = gfn_round_for_level(fault->gfn,
@@ -6785,11 +6800,7 @@ static unsigned long mmu_shrink_count(struct shrinker *shrink,
return percpu_counter_read_positive(&kvm_total_used_mmu_pages);
}
-static struct shrinker mmu_shrinker = {
- .count_objects = mmu_shrink_count,
- .scan_objects = mmu_shrink_scan,
- .seeks = DEFAULT_SEEKS * 10,
-};
+static struct shrinker *mmu_shrinker;
static void mmu_destroy_caches(void)
{
@@ -6922,10 +6933,16 @@ int kvm_mmu_vendor_module_init(void)
if (percpu_counter_init(&kvm_total_used_mmu_pages, 0, GFP_KERNEL))
goto out;
- ret = register_shrinker(&mmu_shrinker, "x86-mmu");
- if (ret)
+ mmu_shrinker = shrinker_alloc(0, "x86-mmu");
+ if (!mmu_shrinker)
goto out_shrinker;
+ mmu_shrinker->count_objects = mmu_shrink_count;
+ mmu_shrinker->scan_objects = mmu_shrink_scan;
+ mmu_shrinker->seeks = DEFAULT_SEEKS * 10;
+
+ shrinker_register(mmu_shrinker);
+
return 0;
out_shrinker:
@@ -6947,7 +6964,7 @@ void kvm_mmu_vendor_module_exit(void)
{
mmu_destroy_caches();
percpu_counter_destroy(&kvm_total_used_mmu_pages);
- unregister_shrinker(&mmu_shrinker);
+ shrinker_free(mmu_shrinker);
}
/*
diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c
index 3eb6e7f47e96..a67c28a56417 100644
--- a/arch/x86/kvm/mtrr.c
+++ b/arch/x86/kvm/mtrr.c
@@ -320,7 +320,7 @@ static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr)
struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state;
gfn_t start, end;
- if (!tdp_enabled || !kvm_arch_has_noncoherent_dma(vcpu->kvm))
+ if (!kvm_mmu_honors_guest_mtrrs(vcpu->kvm))
return;
if (!mtrr_is_enabled(mtrr_state) && msr != MSR_MTRRdefType)
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index edb89b51b383..9ae07db6f0f6 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -93,14 +93,6 @@ void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_ops)
#undef __KVM_X86_PMU_OP
}
-static void kvm_pmi_trigger_fn(struct irq_work *irq_work)
-{
- struct kvm_pmu *pmu = container_of(irq_work, struct kvm_pmu, irq_work);
- struct kvm_vcpu *vcpu = pmu_to_vcpu(pmu);
-
- kvm_pmu_deliver_pmi(vcpu);
-}
-
static inline void __kvm_perf_overflow(struct kvm_pmc *pmc, bool in_pmi)
{
struct kvm_pmu *pmu = pmc_to_pmu(pmc);
@@ -124,20 +116,7 @@ static inline void __kvm_perf_overflow(struct kvm_pmc *pmc, bool in_pmi)
__set_bit(pmc->idx, (unsigned long *)&pmu->global_status);
}
- if (!pmc->intr || skip_pmi)
- return;
-
- /*
- * Inject PMI. If vcpu was in a guest mode during NMI PMI
- * can be ejected on a guest mode re-entry. Otherwise we can't
- * be sure that vcpu wasn't executing hlt instruction at the
- * time of vmexit and is not going to re-enter guest mode until
- * woken up. So we should wake it, but this is impossible from
- * NMI context. Do it from irq work instead.
- */
- if (in_pmi && !kvm_handling_nmi_from_guest(pmc->vcpu))
- irq_work_queue(&pmc_to_pmu(pmc)->irq_work);
- else
+ if (pmc->intr && !skip_pmi)
kvm_make_request(KVM_REQ_PMI, pmc->vcpu);
}
@@ -675,9 +654,6 @@ void kvm_pmu_refresh(struct kvm_vcpu *vcpu)
void kvm_pmu_reset(struct kvm_vcpu *vcpu)
{
- struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
-
- irq_work_sync(&pmu->irq_work);
static_call(kvm_x86_pmu_reset)(vcpu);
}
@@ -687,7 +663,6 @@ void kvm_pmu_init(struct kvm_vcpu *vcpu)
memset(pmu, 0, sizeof(*pmu));
static_call(kvm_x86_pmu_init)(vcpu);
- init_irq_work(&pmu->irq_work, kvm_pmi_trigger_fn);
pmu->event_count = 0;
pmu->need_cleanup = false;
kvm_pmu_refresh(vcpu);
diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
index 7d9ba301c090..1d64113de488 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -74,6 +74,12 @@ static inline u64 pmc_read_counter(struct kvm_pmc *pmc)
return counter & pmc_bitmask(pmc);
}
+static inline void pmc_write_counter(struct kvm_pmc *pmc, u64 val)
+{
+ pmc->counter += val - pmc_read_counter(pmc);
+ pmc->counter &= pmc_bitmask(pmc);
+}
+
static inline void pmc_release_perf_event(struct kvm_pmc *pmc)
{
if (pmc->perf_event) {
diff --git a/arch/x86/kvm/smm.c b/arch/x86/kvm/smm.c
index b42111a24cc2..dc3d95fdca7d 100644
--- a/arch/x86/kvm/smm.c
+++ b/arch/x86/kvm/smm.c
@@ -324,7 +324,6 @@ void enter_smm(struct kvm_vcpu *vcpu)
cr0 = vcpu->arch.cr0 & ~(X86_CR0_PE | X86_CR0_EM | X86_CR0_TS | X86_CR0_PG);
static_call(kvm_x86_set_cr0)(vcpu, cr0);
- vcpu->arch.cr0 = cr0;
static_call(kvm_x86_set_cr4)(vcpu, 0);
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index 2092db892d7d..4b74ea91f4e6 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -529,8 +529,11 @@ int avic_incomplete_ipi_interception(struct kvm_vcpu *vcpu)
case AVIC_IPI_FAILURE_INVALID_BACKING_PAGE:
WARN_ONCE(1, "Invalid backing page\n");
break;
+ case AVIC_IPI_FAILURE_INVALID_IPI_VECTOR:
+ /* Invalid IPI with vector < 16 */
+ break;
default:
- pr_err("Unknown IPI interception\n");
+ vcpu_unimpl(vcpu, "Unknown avic incomplete IPI interception\n");
}
return 1;
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index dd496c9e5f91..3fea8c47679e 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -1253,6 +1253,9 @@ void svm_leave_nested(struct kvm_vcpu *vcpu)
nested_svm_uninit_mmu_context(vcpu);
vmcb_mark_all_dirty(svm->vmcb);
+
+ if (kvm_apicv_activated(vcpu->kvm))
+ kvm_make_request(KVM_REQ_APICV_UPDATE, vcpu);
}
kvm_clear_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu);
diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c
index cef5a3d0abd0..373ff6a6687b 100644
--- a/arch/x86/kvm/svm/pmu.c
+++ b/arch/x86/kvm/svm/pmu.c
@@ -160,7 +160,7 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
/* MSR_PERFCTRn */
pmc = get_gp_pmc_amd(pmu, msr, PMU_TYPE_COUNTER);
if (pmc) {
- pmc->counter += data - pmc_read_counter(pmc);
+ pmc_write_counter(pmc, data);
pmc_update_sample_period(pmc);
return 0;
}
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 9507df93f410..f3bb30b40876 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -199,7 +199,7 @@ module_param_named(npt, npt_enabled, bool, 0444);
/* allow nested virtualization in KVM/SVM */
static int nested = true;
-module_param(nested, int, S_IRUGO);
+module_param(nested, int, 0444);
/* enable/disable Next RIP Save */
int nrips = true;
@@ -364,8 +364,6 @@ static void svm_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
svm->vmcb->control.int_state |= SVM_INTERRUPT_SHADOW_MASK;
}
-static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
- void *insn, int insn_len);
static int __svm_skip_emulated_instruction(struct kvm_vcpu *vcpu,
bool commit_side_effects)
@@ -386,14 +384,6 @@ static int __svm_skip_emulated_instruction(struct kvm_vcpu *vcpu,
}
if (!svm->next_rip) {
- /*
- * FIXME: Drop this when kvm_emulate_instruction() does the
- * right thing and treats "can't emulate" as outright failure
- * for EMULTYPE_SKIP.
- */
- if (!svm_can_emulate_instruction(vcpu, EMULTYPE_SKIP, NULL, 0))
- return 0;
-
if (unlikely(!commit_side_effects))
old_rflags = svm->vmcb->save.rflags;
@@ -531,8 +521,6 @@ static bool __kvm_is_svm_supported(void)
int cpu = smp_processor_id();
struct cpuinfo_x86 *c = &cpu_data(cpu);
- u64 vm_cr;
-
if (c->x86_vendor != X86_VENDOR_AMD &&
c->x86_vendor != X86_VENDOR_HYGON) {
pr_err("CPU %d isn't AMD or Hygon\n", cpu);
@@ -549,12 +537,6 @@ static bool __kvm_is_svm_supported(void)
return false;
}
- rdmsrl(MSR_VM_CR, vm_cr);
- if (vm_cr & (1 << SVM_VM_CR_SVM_DISABLE)) {
- pr_err("SVM disabled (by BIOS) in MSR_VM_CR on CPU %d\n", cpu);
- return false;
- }
-
return true;
}
@@ -691,7 +673,7 @@ static int svm_hardware_enable(void)
*/
if (boot_cpu_has(X86_FEATURE_V_TSC_AUX)) {
struct sev_es_save_area *hostsa;
- u32 msr_hi;
+ u32 __maybe_unused msr_hi;
hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400);
@@ -913,8 +895,7 @@ void svm_set_x2apic_msr_interception(struct vcpu_svm *svm, bool intercept)
if (intercept == svm->x2avic_msrs_intercepted)
return;
- if (!x2avic_enabled ||
- !apic_x2apic_mode(svm->vcpu.arch.apic))
+ if (!x2avic_enabled)
return;
for (i = 0; i < MAX_DIRECT_ACCESS_MSRS; i++) {
@@ -1874,15 +1855,17 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
bool old_paging = is_paging(vcpu);
#ifdef CONFIG_X86_64
- if (vcpu->arch.efer & EFER_LME && !vcpu->arch.guest_state_protected) {
+ if (vcpu->arch.efer & EFER_LME) {
if (!is_paging(vcpu) && (cr0 & X86_CR0_PG)) {
vcpu->arch.efer |= EFER_LMA;
- svm->vmcb->save.efer |= EFER_LMA | EFER_LME;
+ if (!vcpu->arch.guest_state_protected)
+ svm->vmcb->save.efer |= EFER_LMA | EFER_LME;
}
if (is_paging(vcpu) && !(cr0 & X86_CR0_PG)) {
vcpu->arch.efer &= ~EFER_LMA;
- svm->vmcb->save.efer &= ~(EFER_LMA | EFER_LME);
+ if (!vcpu->arch.guest_state_protected)
+ svm->vmcb->save.efer &= ~(EFER_LMA | EFER_LME);
}
}
#endif
@@ -2203,12 +2186,6 @@ static int shutdown_interception(struct kvm_vcpu *vcpu)
struct kvm_run *kvm_run = vcpu->run;
struct vcpu_svm *svm = to_svm(vcpu);
- /*
- * The VM save area has already been encrypted so it
- * cannot be reinitialized - just terminate.
- */
- if (sev_es_guest(vcpu->kvm))
- return -EINVAL;
/*
* VMCB is undefined after a SHUTDOWN intercept. INIT the vCPU to put
@@ -2217,9 +2194,14 @@ static int shutdown_interception(struct kvm_vcpu *vcpu)
* userspace. At a platform view, INIT is acceptable behavior as
* there exist bare metal platforms that automatically INIT the CPU
* in response to shutdown.
+ *
+ * The VM save area for SEV-ES guests has already been encrypted so it
+ * cannot be reinitialized, i.e. synthesizing INIT is futile.
*/
- clear_page(svm->vmcb);
- kvm_vcpu_reset(vcpu, true);
+ if (!sev_es_guest(vcpu->kvm)) {
+ clear_page(svm->vmcb);
+ kvm_vcpu_reset(vcpu, true);
+ }
kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
return 0;
@@ -4728,15 +4710,15 @@ static void svm_enable_smi_window(struct kvm_vcpu *vcpu)
}
#endif
-static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
- void *insn, int insn_len)
+static int svm_check_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
+ void *insn, int insn_len)
{
bool smep, smap, is_user;
u64 error_code;
/* Emulation is always possible when KVM has access to all guest state. */
if (!sev_guest(vcpu->kvm))
- return true;
+ return X86EMUL_CONTINUE;
/* #UD and #GP should never be intercepted for SEV guests. */
WARN_ON_ONCE(emul_type & (EMULTYPE_TRAP_UD |
@@ -4748,14 +4730,14 @@ static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
* to guest register state.
*/
if (sev_es_guest(vcpu->kvm))
- return false;
+ return X86EMUL_RETRY_INSTR;
/*
* Emulation is possible if the instruction is already decoded, e.g.
* when completing I/O after returning from userspace.
*/
if (emul_type & EMULTYPE_NO_DECODE)
- return true;
+ return X86EMUL_CONTINUE;
/*
* Emulation is possible for SEV guests if and only if a prefilled
@@ -4781,9 +4763,11 @@ static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
* success (and in practice it will work the vast majority of the time).
*/
if (unlikely(!insn)) {
- if (!(emul_type & EMULTYPE_SKIP))
- kvm_queue_exception(vcpu, UD_VECTOR);
- return false;
+ if (emul_type & EMULTYPE_SKIP)
+ return X86EMUL_UNHANDLEABLE;
+
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return X86EMUL_PROPAGATE_FAULT;
}
/*
@@ -4794,7 +4778,7 @@ static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
* table used to translate CS:RIP resides in emulated MMIO.
*/
if (likely(insn_len))
- return true;
+ return X86EMUL_CONTINUE;
/*
* Detect and workaround Errata 1096 Fam_17h_00_0Fh.
@@ -4852,6 +4836,7 @@ static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
kvm_inject_gp(vcpu, 0);
else
kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+ return X86EMUL_PROPAGATE_FAULT;
}
resume_guest:
@@ -4869,7 +4854,7 @@ resume_guest:
* doesn't explicitly define "ignored", i.e. doing nothing and letting
* the guest spin is technically "ignoring" the access.
*/
- return false;
+ return X86EMUL_RETRY_INSTR;
}
static bool svm_apic_init_signal_blocked(struct kvm_vcpu *vcpu)
@@ -5029,7 +5014,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
.vm_copy_enc_context_from = sev_vm_copy_enc_context_from,
.vm_move_enc_context_from = sev_vm_move_enc_context_from,
- .can_emulate_instruction = svm_can_emulate_instruction,
+ .check_emulate_instruction = svm_check_emulate_instruction,
.apic_init_signal_blocked = svm_apic_init_signal_blocked,
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index f2efa0bf7ae8..820d3e1f6b4f 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -436,11 +436,11 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if (!msr_info->host_initiated &&
!(msr & MSR_PMC_FULL_WIDTH_BIT))
data = (s64)(s32)data;
- pmc->counter += data - pmc_read_counter(pmc);
+ pmc_write_counter(pmc, data);
pmc_update_sample_period(pmc);
break;
} else if ((pmc = get_fixed_pmc(pmu, msr))) {
- pmc->counter += data - pmc_read_counter(pmc);
+ pmc_write_counter(pmc, data);
pmc_update_sample_period(pmc);
break;
} else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) {
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 72e3943f3693..be20a60047b1 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -82,28 +82,28 @@ bool __read_mostly enable_vpid = 1;
module_param_named(vpid, enable_vpid, bool, 0444);
static bool __read_mostly enable_vnmi = 1;
-module_param_named(vnmi, enable_vnmi, bool, S_IRUGO);
+module_param_named(vnmi, enable_vnmi, bool, 0444);
bool __read_mostly flexpriority_enabled = 1;
-module_param_named(flexpriority, flexpriority_enabled, bool, S_IRUGO);
+module_param_named(flexpriority, flexpriority_enabled, bool, 0444);
bool __read_mostly enable_ept = 1;
-module_param_named(ept, enable_ept, bool, S_IRUGO);
+module_param_named(ept, enable_ept, bool, 0444);
bool __read_mostly enable_unrestricted_guest = 1;
module_param_named(unrestricted_guest,
- enable_unrestricted_guest, bool, S_IRUGO);
+ enable_unrestricted_guest, bool, 0444);
bool __read_mostly enable_ept_ad_bits = 1;
-module_param_named(eptad, enable_ept_ad_bits, bool, S_IRUGO);
+module_param_named(eptad, enable_ept_ad_bits, bool, 0444);
static bool __read_mostly emulate_invalid_guest_state = true;
-module_param(emulate_invalid_guest_state, bool, S_IRUGO);
+module_param(emulate_invalid_guest_state, bool, 0444);
static bool __read_mostly fasteoi = 1;
-module_param(fasteoi, bool, S_IRUGO);
+module_param(fasteoi, bool, 0444);
-module_param(enable_apicv, bool, S_IRUGO);
+module_param(enable_apicv, bool, 0444);
bool __read_mostly enable_ipiv = true;
module_param(enable_ipiv, bool, 0444);
@@ -114,10 +114,10 @@ module_param(enable_ipiv, bool, 0444);
* use VMX instructions.
*/
static bool __read_mostly nested = 1;
-module_param(nested, bool, S_IRUGO);
+module_param(nested, bool, 0444);
bool __read_mostly enable_pml = 1;
-module_param_named(pml, enable_pml, bool, S_IRUGO);
+module_param_named(pml, enable_pml, bool, 0444);
static bool __read_mostly error_on_inconsistent_vmcs_config = true;
module_param(error_on_inconsistent_vmcs_config, bool, 0444);
@@ -1657,8 +1657,8 @@ static int vmx_rtit_ctl_check(struct kvm_vcpu *vcpu, u64 data)
return 0;
}
-static bool vmx_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
- void *insn, int insn_len)
+static int vmx_check_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
+ void *insn, int insn_len)
{
/*
* Emulation of instructions in SGX enclaves is impossible as RIP does
@@ -1669,9 +1669,9 @@ static bool vmx_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
*/
if (to_vmx(vcpu)->exit_reason.enclave_mode) {
kvm_queue_exception(vcpu, UD_VECTOR);
- return false;
+ return X86EMUL_PROPAGATE_FAULT;
}
- return true;
+ return X86EMUL_CONTINUE;
}
static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
@@ -5792,7 +5792,7 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
{
gpa_t gpa;
- if (!vmx_can_emulate_instruction(vcpu, EMULTYPE_PF, NULL, 0))
+ if (vmx_check_emulate_instruction(vcpu, EMULTYPE_PF, NULL, 0))
return 1;
/*
@@ -6912,7 +6912,7 @@ static void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
vmcs_write64(EOI_EXIT_BITMAP3, eoi_exit_bitmap[3]);
}
-static void vmx_apicv_post_state_restore(struct kvm_vcpu *vcpu)
+static void vmx_apicv_pre_state_restore(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -7579,8 +7579,6 @@ static int vmx_vm_init(struct kvm *kvm)
static u8 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
{
- u8 cache;
-
/* We wanted to honor guest CD/MTRR/PAT, but doing so could result in
* memory aliases with conflicting memory types and sometimes MCEs.
* We have to be careful as to what are honored and when.
@@ -7607,11 +7605,10 @@ static u8 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
if (kvm_read_cr0_bits(vcpu, X86_CR0_CD)) {
if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED))
- cache = MTRR_TYPE_WRBACK;
+ return MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT;
else
- cache = MTRR_TYPE_UNCACHABLE;
-
- return (cache << VMX_EPT_MT_EPTE_SHIFT) | VMX_EPT_IPAT_BIT;
+ return (MTRR_TYPE_UNCACHABLE << VMX_EPT_MT_EPTE_SHIFT) |
+ VMX_EPT_IPAT_BIT;
}
return kvm_mtrr_get_guest_memory_type(vcpu, gfn) << VMX_EPT_MT_EPTE_SHIFT;
@@ -8286,7 +8283,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
.set_apic_access_page_addr = vmx_set_apic_access_page_addr,
.refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl,
.load_eoi_exitmap = vmx_load_eoi_exitmap,
- .apicv_post_state_restore = vmx_apicv_post_state_restore,
+ .apicv_pre_state_restore = vmx_apicv_pre_state_restore,
.required_apicv_inhibits = VMX_REQUIRED_APICV_INHIBITS,
.hwapic_irr_update = vmx_hwapic_irr_update,
.hwapic_isr_update = vmx_hwapic_isr_update,
@@ -8341,7 +8338,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
.enable_smi_window = vmx_enable_smi_window,
#endif
- .can_emulate_instruction = vmx_can_emulate_instruction,
+ .check_emulate_instruction = vmx_check_emulate_instruction,
.apic_init_signal_blocked = vmx_apic_init_signal_blocked,
.migrate_timers = vmx_migrate_timers,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 9f18b06bbda6..1a3aaa7dafae 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -145,21 +145,21 @@ EXPORT_STATIC_CALL_GPL(kvm_x86_get_cs_db_l_bits);
EXPORT_STATIC_CALL_GPL(kvm_x86_cache_reg);
static bool __read_mostly ignore_msrs = 0;
-module_param(ignore_msrs, bool, S_IRUGO | S_IWUSR);
+module_param(ignore_msrs, bool, 0644);
bool __read_mostly report_ignored_msrs = true;
-module_param(report_ignored_msrs, bool, S_IRUGO | S_IWUSR);
+module_param(report_ignored_msrs, bool, 0644);
EXPORT_SYMBOL_GPL(report_ignored_msrs);
unsigned int min_timer_period_us = 200;
-module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR);
+module_param(min_timer_period_us, uint, 0644);
static bool __read_mostly kvmclock_periodic_sync = true;
-module_param(kvmclock_periodic_sync, bool, S_IRUGO);
+module_param(kvmclock_periodic_sync, bool, 0444);
/* tsc tolerance in parts per million - default to 1/2 of the NTP threshold */
static u32 __read_mostly tsc_tolerance_ppm = 250;
-module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR);
+module_param(tsc_tolerance_ppm, uint, 0644);
/*
* lapic timer advance (tscdeadline mode only) in nanoseconds. '-1' enables
@@ -168,13 +168,13 @@ module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR);
* tuning, i.e. allows privileged userspace to set an exact advancement time.
*/
static int __read_mostly lapic_timer_advance_ns = -1;
-module_param(lapic_timer_advance_ns, int, S_IRUGO | S_IWUSR);
+module_param(lapic_timer_advance_ns, int, 0644);
static bool __read_mostly vector_hashing = true;
-module_param(vector_hashing, bool, S_IRUGO);
+module_param(vector_hashing, bool, 0444);
bool __read_mostly enable_vmware_backdoor = false;
-module_param(enable_vmware_backdoor, bool, S_IRUGO);
+module_param(enable_vmware_backdoor, bool, 0444);
EXPORT_SYMBOL_GPL(enable_vmware_backdoor);
/*
@@ -186,7 +186,7 @@ static int __read_mostly force_emulation_prefix;
module_param(force_emulation_prefix, int, 0644);
int __read_mostly pi_inject_timer = -1;
-module_param(pi_inject_timer, bint, S_IRUGO | S_IWUSR);
+module_param(pi_inject_timer, bint, 0644);
/* Enable/disable PMU virtualization */
bool __read_mostly enable_pmu = true;
@@ -962,7 +962,7 @@ void kvm_post_set_cr0(struct kvm_vcpu *vcpu, unsigned long old_cr0, unsigned lon
kvm_mmu_reset_context(vcpu);
if (((cr0 ^ old_cr0) & X86_CR0_CD) &&
- kvm_arch_has_noncoherent_dma(vcpu->kvm) &&
+ kvm_mmu_honors_guest_mtrrs(vcpu->kvm) &&
!kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED))
kvm_zap_gfn_range(vcpu->kvm, 0, ~0ULL);
}
@@ -2331,14 +2331,9 @@ static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock, int sec_hi_o
if (kvm_write_guest(kvm, wall_clock, &version, sizeof(version)))
return;
- /*
- * The guest calculates current wall clock time by adding
- * system time (updated by kvm_guest_time_update below) to the
- * wall clock specified here. We do the reverse here.
- */
- wall_nsec = ktime_get_real_ns() - get_kvmclock_ns(kvm);
+ wall_nsec = kvm_get_wall_clock_epoch(kvm);
- wc.nsec = do_div(wall_nsec, 1000000000);
+ wc.nsec = do_div(wall_nsec, NSEC_PER_SEC);
wc.sec = (u32)wall_nsec; /* overflow in 2106 guest time */
wc.version = version;
@@ -2714,8 +2709,9 @@ static void __kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 offset, u64 tsc,
kvm_track_tsc_matching(vcpu);
}
-static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 data)
+static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 *user_value)
{
+ u64 data = user_value ? *user_value : 0;
struct kvm *kvm = vcpu->kvm;
u64 offset, ns, elapsed;
unsigned long flags;
@@ -2730,25 +2726,37 @@ static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 data)
if (vcpu->arch.virtual_tsc_khz) {
if (data == 0) {
/*
- * detection of vcpu initialization -- need to sync
- * with other vCPUs. This particularly helps to keep
- * kvm_clock stable after CPU hotplug
+ * Force synchronization when creating a vCPU, or when
+ * userspace explicitly writes a zero value.
*/
synchronizing = true;
- } else {
+ } else if (kvm->arch.user_set_tsc) {
u64 tsc_exp = kvm->arch.last_tsc_write +
nsec_to_cycles(vcpu, elapsed);
u64 tsc_hz = vcpu->arch.virtual_tsc_khz * 1000LL;
/*
- * Special case: TSC write with a small delta (1 second)
- * of virtual cycle time against real time is
- * interpreted as an attempt to synchronize the CPU.
+ * Here lies UAPI baggage: when a user-initiated TSC write has
+ * a small delta (1 second) of virtual cycle time against the
+ * previously set vCPU, we assume that they were intended to be
+ * in sync and the delta was only due to the racy nature of the
+ * legacy API.
+ *
+ * This trick falls down when restoring a guest which genuinely
+ * has been running for less time than the 1 second of imprecision
+ * which we allow for in the legacy API. In this case, the first
+ * value written by userspace (on any vCPU) should not be subject
+ * to this 'correction' to make it sync up with values that only
+ * come from the kernel's default vCPU creation. Make the 1-second
+ * slop hack only trigger if the user_set_tsc flag is already set.
*/
synchronizing = data < tsc_exp + tsc_hz &&
data + tsc_hz > tsc_exp;
}
}
+ if (user_value)
+ kvm->arch.user_set_tsc = true;
+
/*
* For a reliable TSC, we can match TSC offsets, and for an unstable
* TSC, we add elapsed time in this computation. We could let the
@@ -3232,16 +3240,94 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
if (vcpu->pv_time.active)
kvm_setup_guest_pvclock(v, &vcpu->pv_time, 0);
+#ifdef CONFIG_KVM_XEN
if (vcpu->xen.vcpu_info_cache.active)
kvm_setup_guest_pvclock(v, &vcpu->xen.vcpu_info_cache,
offsetof(struct compat_vcpu_info, time));
if (vcpu->xen.vcpu_time_info_cache.active)
kvm_setup_guest_pvclock(v, &vcpu->xen.vcpu_time_info_cache, 0);
+#endif
kvm_hv_setup_tsc_page(v->kvm, &vcpu->hv_clock);
return 0;
}
/*
+ * The pvclock_wall_clock ABI tells the guest the wall clock time at
+ * which it started (i.e. its epoch, when its kvmclock was zero).
+ *
+ * In fact those clocks are subtly different; wall clock frequency is
+ * adjusted by NTP and has leap seconds, while the kvmclock is a
+ * simple function of the TSC without any such adjustment.
+ *
+ * Perhaps the ABI should have exposed CLOCK_TAI and a ratio between
+ * that and kvmclock, but even that would be subject to change over
+ * time.
+ *
+ * Attempt to calculate the epoch at a given moment using the *same*
+ * TSC reading via kvm_get_walltime_and_clockread() to obtain both
+ * wallclock and kvmclock times, and subtracting one from the other.
+ *
+ * Fall back to using their values at slightly different moments by
+ * calling ktime_get_real_ns() and get_kvmclock_ns() separately.
+ */
+uint64_t kvm_get_wall_clock_epoch(struct kvm *kvm)
+{
+#ifdef CONFIG_X86_64
+ struct pvclock_vcpu_time_info hv_clock;
+ struct kvm_arch *ka = &kvm->arch;
+ unsigned long seq, local_tsc_khz;
+ struct timespec64 ts;
+ uint64_t host_tsc;
+
+ do {
+ seq = read_seqcount_begin(&ka->pvclock_sc);
+
+ local_tsc_khz = 0;
+ if (!ka->use_master_clock)
+ break;
+
+ /*
+ * The TSC read and the call to get_cpu_tsc_khz() must happen
+ * on the same CPU.
+ */
+ get_cpu();
+
+ local_tsc_khz = get_cpu_tsc_khz();
+
+ if (local_tsc_khz &&
+ !kvm_get_walltime_and_clockread(&ts, &host_tsc))
+ local_tsc_khz = 0; /* Fall back to old method */
+
+ put_cpu();
+
+ /*
+ * These values must be snapshotted within the seqcount loop.
+ * After that, it's just mathematics which can happen on any
+ * CPU at any time.
+ */
+ hv_clock.tsc_timestamp = ka->master_cycle_now;
+ hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset;
+
+ } while (read_seqcount_retry(&ka->pvclock_sc, seq));
+
+ /*
+ * If the conditions were right, and obtaining the wallclock+TSC was
+ * successful, calculate the KVM clock at the corresponding time and
+ * subtract one from the other to get the guest's epoch in nanoseconds
+ * since 1970-01-01.
+ */
+ if (local_tsc_khz) {
+ kvm_get_time_scale(NSEC_PER_SEC, local_tsc_khz * NSEC_PER_USEC,
+ &hv_clock.tsc_shift,
+ &hv_clock.tsc_to_system_mul);
+ return ts.tv_nsec + NSEC_PER_SEC * ts.tv_sec -
+ __pvclock_read_cycles(&hv_clock, host_tsc);
+ }
+#endif
+ return ktime_get_real_ns() - get_kvmclock_ns(kvm);
+}
+
+/*
* kvmclock updates which are isolated to a given vcpu, such as
* vcpu->cpu migration, should not allow system_timestamp from
* the rest of the vcpus to remain static. Otherwise ntp frequency
@@ -3290,9 +3376,6 @@ static void kvmclock_sync_fn(struct work_struct *work)
kvmclock_sync_work);
struct kvm *kvm = container_of(ka, struct kvm, arch);
- if (!kvmclock_periodic_sync)
- return;
-
schedule_delayed_work(&kvm->arch.kvmclock_update_work, 0);
schedule_delayed_work(&kvm->arch.kvmclock_sync_work,
KVMCLOCK_SYNC_PERIOD);
@@ -3641,6 +3724,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_AMD64_PATCH_LOADER:
case MSR_AMD64_BU_CFG2:
case MSR_AMD64_DC_CFG:
+ case MSR_AMD64_TW_CFG:
case MSR_F15H_EX_CFG:
break;
@@ -3670,17 +3754,36 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
vcpu->arch.perf_capabilities = data;
kvm_pmu_refresh(vcpu);
break;
- case MSR_IA32_PRED_CMD:
- if (!msr_info->host_initiated && !guest_has_pred_cmd_msr(vcpu))
- return 1;
+ case MSR_IA32_PRED_CMD: {
+ u64 reserved_bits = ~(PRED_CMD_IBPB | PRED_CMD_SBPB);
+
+ if (!msr_info->host_initiated) {
+ if ((!guest_has_pred_cmd_msr(vcpu)))
+ return 1;
+
+ if (!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) &&
+ !guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBPB))
+ reserved_bits |= PRED_CMD_IBPB;
+
+ if (!guest_cpuid_has(vcpu, X86_FEATURE_SBPB))
+ reserved_bits |= PRED_CMD_SBPB;
+ }
+
+ if (!boot_cpu_has(X86_FEATURE_IBPB))
+ reserved_bits |= PRED_CMD_IBPB;
- if (!boot_cpu_has(X86_FEATURE_IBPB) || (data & ~PRED_CMD_IBPB))
+ if (!boot_cpu_has(X86_FEATURE_SBPB))
+ reserved_bits |= PRED_CMD_SBPB;
+
+ if (data & reserved_bits)
return 1;
+
if (!data)
break;
- wrmsrl(MSR_IA32_PRED_CMD, PRED_CMD_IBPB);
+ wrmsrl(MSR_IA32_PRED_CMD, data);
break;
+ }
case MSR_IA32_FLUSH_CMD:
if (!msr_info->host_initiated &&
!guest_cpuid_has(vcpu, X86_FEATURE_FLUSH_L1D))
@@ -3700,13 +3803,16 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
data &= ~(u64)0x100; /* ignore ignne emulation enable */
data &= ~(u64)0x8; /* ignore TLB cache disable */
- /* Handle McStatusWrEn */
- if (data == BIT_ULL(18)) {
- vcpu->arch.msr_hwcr = data;
- } else if (data != 0) {
+ /*
+ * Allow McStatusWrEn and TscFreqSel. (Linux guests from v3.2
+ * through at least v6.6 whine if TscFreqSel is clear,
+ * depending on F/M/S.
+ */
+ if (data & ~(BIT_ULL(18) | BIT_ULL(24))) {
kvm_pr_unimpl_wrmsr(vcpu, msr, data);
return 1;
}
+ vcpu->arch.msr_hwcr = data;
break;
case MSR_FAM10H_MMIO_CONF_BASE:
if (data != 0) {
@@ -3777,7 +3883,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
break;
case MSR_IA32_TSC:
if (msr_info->host_initiated) {
- kvm_synchronize_tsc(vcpu, data);
+ kvm_synchronize_tsc(vcpu, &data);
} else {
u64 adj = kvm_compute_l1_tsc_offset(vcpu, data) - vcpu->arch.l1_tsc_offset;
adjust_tsc_offset_guest(vcpu, adj);
@@ -4065,6 +4171,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_AMD64_BU_CFG2:
case MSR_IA32_PERF_CTL:
case MSR_AMD64_DC_CFG:
+ case MSR_AMD64_TW_CFG:
case MSR_F15H_EX_CFG:
/*
* Intel Sandy Bridge CPUs must support the RAPL (running average power
@@ -5382,26 +5489,37 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
return 0;
}
-static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
- struct kvm_xsave *guest_xsave)
-{
- if (fpstate_is_confidential(&vcpu->arch.guest_fpu))
- return;
-
- fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu,
- guest_xsave->region,
- sizeof(guest_xsave->region),
- vcpu->arch.pkru);
-}
static void kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_vcpu *vcpu,
u8 *state, unsigned int size)
{
+ /*
+ * Only copy state for features that are enabled for the guest. The
+ * state itself isn't problematic, but setting bits in the header for
+ * features that are supported in *this* host but not exposed to the
+ * guest can result in KVM_SET_XSAVE failing when live migrating to a
+ * compatible host without the features that are NOT exposed to the
+ * guest.
+ *
+ * FP+SSE can always be saved/restored via KVM_{G,S}ET_XSAVE, even if
+ * XSAVE/XCRO are not exposed to the guest, and even if XSAVE isn't
+ * supported by the host.
+ */
+ u64 supported_xcr0 = vcpu->arch.guest_supported_xcr0 |
+ XFEATURE_MASK_FPSSE;
+
if (fpstate_is_confidential(&vcpu->arch.guest_fpu))
return;
- fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu,
- state, size, vcpu->arch.pkru);
+ fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu, state, size,
+ supported_xcr0, vcpu->arch.pkru);
+}
+
+static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
+ struct kvm_xsave *guest_xsave)
+{
+ kvm_vcpu_ioctl_x86_get_xsave2(vcpu, (void *)guest_xsave->region,
+ sizeof(guest_xsave->region));
}
static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,
@@ -5536,6 +5654,7 @@ static int kvm_arch_tsc_set_attr(struct kvm_vcpu *vcpu,
tsc = kvm_scale_tsc(rdtsc(), vcpu->arch.l1_tsc_scaling_ratio) + offset;
ns = get_kvmclock_base_ns();
+ kvm->arch.user_set_tsc = true;
__kvm_synchronize_tsc(vcpu, offset, tsc, ns, matched);
raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
@@ -6248,6 +6367,9 @@ void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
struct kvm_vcpu *vcpu;
unsigned long i;
+ if (!kvm_x86_ops.cpu_dirty_log_size)
+ return;
+
kvm_for_each_vcpu(i, vcpu, kvm)
kvm_vcpu_kick(vcpu);
}
@@ -7474,11 +7596,11 @@ int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val,
}
EXPORT_SYMBOL_GPL(kvm_write_guest_virt_system);
-static int kvm_can_emulate_insn(struct kvm_vcpu *vcpu, int emul_type,
- void *insn, int insn_len)
+static int kvm_check_emulate_insn(struct kvm_vcpu *vcpu, int emul_type,
+ void *insn, int insn_len)
{
- return static_call(kvm_x86_can_emulate_instruction)(vcpu, emul_type,
- insn, insn_len);
+ return static_call(kvm_x86_check_emulate_instruction)(vcpu, emul_type,
+ insn, insn_len);
}
int handle_ud(struct kvm_vcpu *vcpu)
@@ -7488,8 +7610,10 @@ int handle_ud(struct kvm_vcpu *vcpu)
int emul_type = EMULTYPE_TRAP_UD;
char sig[5]; /* ud2; .ascii "kvm" */
struct x86_exception e;
+ int r;
- if (unlikely(!kvm_can_emulate_insn(vcpu, emul_type, NULL, 0)))
+ r = kvm_check_emulate_insn(vcpu, emul_type, NULL, 0);
+ if (r != X86EMUL_CONTINUE)
return 1;
if (fep_flags &&
@@ -8871,8 +8995,14 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
struct x86_emulate_ctxt *ctxt = vcpu->arch.emulate_ctxt;
bool writeback = true;
- if (unlikely(!kvm_can_emulate_insn(vcpu, emulation_type, insn, insn_len)))
- return 1;
+ r = kvm_check_emulate_insn(vcpu, emulation_type, insn, insn_len);
+ if (r != X86EMUL_CONTINUE) {
+ if (r == X86EMUL_RETRY_INSTR || r == X86EMUL_PROPAGATE_FAULT)
+ return 1;
+
+ WARN_ON_ONCE(r != X86EMUL_UNHANDLEABLE);
+ return handle_emulation_failure(vcpu, emulation_type);
+ }
vcpu->arch.l1tf_flush_l1d = true;
@@ -10576,16 +10706,16 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
}
if (kvm_check_request(KVM_REQ_STEAL_UPDATE, vcpu))
record_steal_time(vcpu);
+ if (kvm_check_request(KVM_REQ_PMU, vcpu))
+ kvm_pmu_handle_event(vcpu);
+ if (kvm_check_request(KVM_REQ_PMI, vcpu))
+ kvm_pmu_deliver_pmi(vcpu);
#ifdef CONFIG_KVM_SMM
if (kvm_check_request(KVM_REQ_SMI, vcpu))
process_smi(vcpu);
#endif
if (kvm_check_request(KVM_REQ_NMI, vcpu))
process_nmi(vcpu);
- if (kvm_check_request(KVM_REQ_PMU, vcpu))
- kvm_pmu_handle_event(vcpu);
- if (kvm_check_request(KVM_REQ_PMI, vcpu))
- kvm_pmu_deliver_pmi(vcpu);
if (kvm_check_request(KVM_REQ_IOAPIC_EOI_EXIT, vcpu)) {
BUG_ON(vcpu->arch.pending_ioapic_eoi > 255);
if (test_bit(vcpu->arch.pending_ioapic_eoi,
@@ -11521,7 +11651,6 @@ static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs,
*mmu_reset_needed |= kvm_read_cr0(vcpu) != sregs->cr0;
static_call(kvm_x86_set_cr0)(vcpu, sregs->cr0);
- vcpu->arch.cr0 = sregs->cr0;
*mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4;
static_call(kvm_x86_set_cr4)(vcpu, sregs->cr4);
@@ -11565,8 +11694,10 @@ static int __set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
if (ret)
return ret;
- if (mmu_reset_needed)
+ if (mmu_reset_needed) {
kvm_mmu_reset_context(vcpu);
+ kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu);
+ }
max_bits = KVM_NR_INTERRUPTS;
pending_vec = find_first_bit(
@@ -11607,8 +11738,10 @@ static int __set_sregs2(struct kvm_vcpu *vcpu, struct kvm_sregs2 *sregs2)
mmu_reset_needed = 1;
vcpu->arch.pdptrs_from_userspace = true;
}
- if (mmu_reset_needed)
+ if (mmu_reset_needed) {
kvm_mmu_reset_context(vcpu);
+ kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu);
+ }
return 0;
}
@@ -11959,7 +12092,7 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
if (mutex_lock_killable(&vcpu->mutex))
return;
vcpu_load(vcpu);
- kvm_synchronize_tsc(vcpu, 0);
+ kvm_synchronize_tsc(vcpu, NULL);
vcpu_put(vcpu);
/* poll control enabled by default */
@@ -12315,7 +12448,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
goto out_uninit_mmu;
INIT_HLIST_HEAD(&kvm->arch.mask_notifier_list);
- INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
atomic_set(&kvm->arch.noncoherent_dma_count, 0);
/* Reserve bit 0 of irq_sources_bitmap for userspace irq source */
@@ -12843,6 +12975,9 @@ static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
return true;
#endif
+ if (kvm_test_request(KVM_REQ_PMI, vcpu))
+ return true;
+
if (kvm_arch_interrupt_allowed(vcpu) &&
(kvm_cpu_has_interrupt(vcpu) ||
kvm_guest_apic_has_interrupt(vcpu)))
@@ -12896,7 +13031,10 @@ bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
if (vcpu->arch.guest_state_protected)
return true;
- return vcpu->arch.preempted_in_kernel;
+ if (vcpu != kvm_get_running_vcpu())
+ return vcpu->arch.preempted_in_kernel;
+
+ return static_call(kvm_x86_get_cpl)(vcpu) == 0;
}
unsigned long kvm_arch_vcpu_get_ip(struct kvm_vcpu *vcpu)
@@ -13188,15 +13326,30 @@ bool noinstr kvm_arch_has_assigned_device(struct kvm *kvm)
}
EXPORT_SYMBOL_GPL(kvm_arch_has_assigned_device);
+static void kvm_noncoherent_dma_assignment_start_or_stop(struct kvm *kvm)
+{
+ /*
+ * Non-coherent DMA assignment and de-assignment will affect
+ * whether KVM honors guest MTRRs and cause changes in memtypes
+ * in TDP.
+ * So, pass %true unconditionally to indicate non-coherent DMA was,
+ * or will be involved, and that zapping SPTEs might be necessary.
+ */
+ if (__kvm_mmu_honors_guest_mtrrs(true))
+ kvm_zap_gfn_range(kvm, gpa_to_gfn(0), gpa_to_gfn(~0ULL));
+}
+
void kvm_arch_register_noncoherent_dma(struct kvm *kvm)
{
- atomic_inc(&kvm->arch.noncoherent_dma_count);
+ if (atomic_inc_return(&kvm->arch.noncoherent_dma_count) == 1)
+ kvm_noncoherent_dma_assignment_start_or_stop(kvm);
}
EXPORT_SYMBOL_GPL(kvm_arch_register_noncoherent_dma);
void kvm_arch_unregister_noncoherent_dma(struct kvm *kvm)
{
- atomic_dec(&kvm->arch.noncoherent_dma_count);
+ if (!atomic_dec_return(&kvm->arch.noncoherent_dma_count))
+ kvm_noncoherent_dma_assignment_start_or_stop(kvm);
}
EXPORT_SYMBOL_GPL(kvm_arch_unregister_noncoherent_dma);
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 1e7be1f6ab29..5184fde1dc54 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -293,6 +293,7 @@ static inline bool kvm_check_has_quirk(struct kvm *kvm, u64 quirk)
void kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);
u64 get_kvmclock_ns(struct kvm *kvm);
+uint64_t kvm_get_wall_clock_epoch(struct kvm *kvm);
int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
gva_t addr, void *val, unsigned int bytes,
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 40edf4d1974c..e53fad915a62 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -59,7 +59,7 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
* This code mirrors kvm_write_wall_clock() except that it writes
* directly through the pfn cache and doesn't mark the page dirty.
*/
- wall_nsec = ktime_get_real_ns() - get_kvmclock_ns(kvm);
+ wall_nsec = kvm_get_wall_clock_epoch(kvm);
/* It could be invalid again already, so we need to check */
read_lock_irq(&gpc->lock);
@@ -98,7 +98,7 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
wc_version = wc->version = (wc->version + 1) | 1;
smp_wmb();
- wc->nsec = do_div(wall_nsec, 1000000000);
+ wc->nsec = do_div(wall_nsec, NSEC_PER_SEC);
wc->sec = (u32)wall_nsec;
*wc_sec_hi = wall_nsec >> 32;
smp_wmb();
@@ -134,9 +134,23 @@ static enum hrtimer_restart xen_timer_callback(struct hrtimer *timer)
{
struct kvm_vcpu *vcpu = container_of(timer, struct kvm_vcpu,
arch.xen.timer);
+ struct kvm_xen_evtchn e;
+ int rc;
+
if (atomic_read(&vcpu->arch.xen.timer_pending))
return HRTIMER_NORESTART;
+ e.vcpu_id = vcpu->vcpu_id;
+ e.vcpu_idx = vcpu->vcpu_idx;
+ e.port = vcpu->arch.xen.timer_virq;
+ e.priority = KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL;
+
+ rc = kvm_xen_set_evtchn_fast(&e, vcpu->kvm);
+ if (rc != -EWOULDBLOCK) {
+ vcpu->arch.xen.timer_expires = 0;
+ return HRTIMER_NORESTART;
+ }
+
atomic_inc(&vcpu->arch.xen.timer_pending);
kvm_make_request(KVM_REQ_UNBLOCK, vcpu);
kvm_vcpu_kick(vcpu);
@@ -146,6 +160,14 @@ static enum hrtimer_restart xen_timer_callback(struct hrtimer *timer)
static void kvm_xen_start_timer(struct kvm_vcpu *vcpu, u64 guest_abs, s64 delta_ns)
{
+ /*
+ * Avoid races with the old timer firing. Checking timer_expires
+ * to avoid calling hrtimer_cancel() will only have false positives
+ * so is fine.
+ */
+ if (vcpu->arch.xen.timer_expires)
+ hrtimer_cancel(&vcpu->arch.xen.timer);
+
atomic_set(&vcpu->arch.xen.timer_pending, 0);
vcpu->arch.xen.timer_expires = guest_abs;
@@ -1019,9 +1041,36 @@ int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
break;
case KVM_XEN_VCPU_ATTR_TYPE_TIMER:
+ /*
+ * Ensure a consistent snapshot of state is captured, with a
+ * timer either being pending, or the event channel delivered
+ * to the corresponding bit in the shared_info. Not still
+ * lurking in the timer_pending flag for deferred delivery.
+ * Purely as an optimisation, if the timer_expires field is
+ * zero, that means the timer isn't active (or even in the
+ * timer_pending flag) and there is no need to cancel it.
+ */
+ if (vcpu->arch.xen.timer_expires) {
+ hrtimer_cancel(&vcpu->arch.xen.timer);
+ kvm_xen_inject_timer_irqs(vcpu);
+ }
+
data->u.timer.port = vcpu->arch.xen.timer_virq;
data->u.timer.priority = KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL;
data->u.timer.expires_ns = vcpu->arch.xen.timer_expires;
+
+ /*
+ * The hrtimer may trigger and raise the IRQ immediately,
+ * while the returned state causes it to be set up and
+ * raised again on the destination system after migration.
+ * That's fine, as the guest won't even have had a chance
+ * to run and handle the interrupt. Asserting an already
+ * pending event channel is idempotent.
+ */
+ if (vcpu->arch.xen.timer_expires)
+ hrtimer_start_expires(&vcpu->arch.xen.timer,
+ HRTIMER_MODE_ABS_HARD);
+
r = 0;
break;
@@ -1374,12 +1423,8 @@ static bool kvm_xen_hcall_vcpu_op(struct kvm_vcpu *vcpu, bool longmode, int cmd,
return true;
}
+ /* A delta <= 0 results in an immediate callback, which is what we want */
delta = oneshot.timeout_abs_ns - get_kvmclock_ns(vcpu->kvm);
- if ((oneshot.flags & VCPU_SSHOTTMR_future) && delta < 0) {
- *r = -ETIME;
- return true;
- }
-
kvm_xen_start_timer(vcpu, oneshot.timeout_abs_ns, delta);
*r = 0;
return true;
diff --git a/arch/x86/lib/checksum_32.S b/arch/x86/lib/checksum_32.S
index 23318c338db0..68f7fa3e1322 100644
--- a/arch/x86/lib/checksum_32.S
+++ b/arch/x86/lib/checksum_32.S
@@ -21,10 +21,10 @@
* converted to pure assembler
*/
+#include <linux/export.h>
#include <linux/linkage.h>
#include <asm/errno.h>
#include <asm/asm.h>
-#include <asm/export.h>
#include <asm/nospec-branch.h>
/*
diff --git a/arch/x86/lib/clear_page_64.S b/arch/x86/lib/clear_page_64.S
index f74a3e704a1c..2760a15fbc00 100644
--- a/arch/x86/lib/clear_page_64.S
+++ b/arch/x86/lib/clear_page_64.S
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
+#include <linux/export.h>
#include <linux/linkage.h>
#include <asm/asm.h>
-#include <asm/export.h>
/*
* Most CPUs support enhanced REP MOVSB/STOSB instructions. It is
diff --git a/arch/x86/lib/cmpxchg8b_emu.S b/arch/x86/lib/cmpxchg8b_emu.S
index 49805257b125..873e4ef23e49 100644
--- a/arch/x86/lib/cmpxchg8b_emu.S
+++ b/arch/x86/lib/cmpxchg8b_emu.S
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
+#include <linux/export.h>
#include <linux/linkage.h>
-#include <asm/export.h>
#include <asm/percpu.h>
#include <asm/processor-flags.h>
diff --git a/arch/x86/lib/copy_mc.c b/arch/x86/lib/copy_mc.c
index 80efd45a7761..6e8b7e600def 100644
--- a/arch/x86/lib/copy_mc.c
+++ b/arch/x86/lib/copy_mc.c
@@ -70,23 +70,23 @@ unsigned long __must_check copy_mc_to_kernel(void *dst, const void *src, unsigne
}
EXPORT_SYMBOL_GPL(copy_mc_to_kernel);
-unsigned long __must_check copy_mc_to_user(void *dst, const void *src, unsigned len)
+unsigned long __must_check copy_mc_to_user(void __user *dst, const void *src, unsigned len)
{
unsigned long ret;
if (copy_mc_fragile_enabled) {
__uaccess_begin();
- ret = copy_mc_fragile(dst, src, len);
+ ret = copy_mc_fragile((__force void *)dst, src, len);
__uaccess_end();
return ret;
}
if (static_cpu_has(X86_FEATURE_ERMS)) {
__uaccess_begin();
- ret = copy_mc_enhanced_fast_string(dst, src, len);
+ ret = copy_mc_enhanced_fast_string((__force void *)dst, src, len);
__uaccess_end();
return ret;
}
- return copy_user_generic(dst, src, len);
+ return copy_user_generic((__force void *)dst, src, len);
}
diff --git a/arch/x86/lib/copy_page_64.S b/arch/x86/lib/copy_page_64.S
index 30ea644bf446..d6ae793d08fa 100644
--- a/arch/x86/lib/copy_page_64.S
+++ b/arch/x86/lib/copy_page_64.S
@@ -1,10 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Written 2003 by Andi Kleen, based on a kernel by Evandro Menezes */
+#include <linux/export.h>
#include <linux/linkage.h>
#include <asm/cpufeatures.h>
#include <asm/alternative.h>
-#include <asm/export.h>
/*
* Some CPUs run faster using the string copy instructions (sane microcode).
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
index 0a81aafed7f8..fc9fb5d06174 100644
--- a/arch/x86/lib/copy_user_64.S
+++ b/arch/x86/lib/copy_user_64.S
@@ -6,11 +6,11 @@
* Functions to copy from and to user space.
*/
+#include <linux/export.h>
#include <linux/linkage.h>
#include <asm/cpufeatures.h>
#include <asm/alternative.h>
#include <asm/asm.h>
-#include <asm/export.h>
/*
* rep_movs_alternative - memory copy with exception handling.
diff --git a/arch/x86/lib/copy_user_uncached_64.S b/arch/x86/lib/copy_user_uncached_64.S
index 5c5f38d32672..2918e36eece2 100644
--- a/arch/x86/lib/copy_user_uncached_64.S
+++ b/arch/x86/lib/copy_user_uncached_64.S
@@ -3,9 +3,9 @@
* Copyright 2023 Linus Torvalds <torvalds@linux-foundation.org>
*/
+#include <linux/export.h>
#include <linux/linkage.h>
#include <asm/asm.h>
-#include <asm/export.h>
/*
* copy_user_nocache - Uncached memory copy with exception handling
diff --git a/arch/x86/lib/csum-wrappers_64.c b/arch/x86/lib/csum-wrappers_64.c
index 145f9a0bde29..f4df4d241526 100644
--- a/arch/x86/lib/csum-wrappers_64.c
+++ b/arch/x86/lib/csum-wrappers_64.c
@@ -14,8 +14,6 @@
* @src: source address (user space)
* @dst: destination address
* @len: number of bytes to be copied.
- * @isum: initial sum that is added into the result (32bit unfolded)
- * @errp: set to -EFAULT for an bad source address.
*
* Returns an 32bit unfolded checksum of the buffer.
* src and dst are best aligned to 64bits.
@@ -38,8 +36,6 @@ csum_and_copy_from_user(const void __user *src, void *dst, int len)
* @src: source address
* @dst: destination address (user space)
* @len: number of bytes to be copied.
- * @isum: initial sum that is added into the result (32bit unfolded)
- * @errp: set to -EFAULT for an bad destination address.
*
* Returns an 32bit unfolded checksum of the buffer.
* src and dst are best aligned to 64bits.
@@ -62,7 +58,6 @@ csum_and_copy_to_user(const void *src, void __user *dst, int len)
* @src: source address
* @dst: destination address
* @len: number of bytes to be copied.
- * @sum: initial sum that is added into the result (32bit unfolded)
*
* Returns an 32bit unfolded checksum of the buffer.
*/
diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
index 9c63713477bb..20ef350a60fb 100644
--- a/arch/x86/lib/getuser.S
+++ b/arch/x86/lib/getuser.S
@@ -26,6 +26,7 @@
* as they get called from within inline assembly.
*/
+#include <linux/export.h>
#include <linux/linkage.h>
#include <asm/page_types.h>
#include <asm/errno.h>
@@ -33,7 +34,6 @@
#include <asm/thread_info.h>
#include <asm/asm.h>
#include <asm/smap.h>
-#include <asm/export.h>
#define ASM_BARRIER_NOSPEC ALTERNATIVE "", "lfence", X86_FEATURE_LFENCE_RDTSC
diff --git a/arch/x86/lib/hweight.S b/arch/x86/lib/hweight.S
index 12c16c6aa44a..774bdf3e6f0a 100644
--- a/arch/x86/lib/hweight.S
+++ b/arch/x86/lib/hweight.S
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/export.h>
#include <linux/linkage.h>
-#include <asm/export.h>
#include <asm/asm.h>
@@ -36,8 +36,12 @@ SYM_FUNC_START(__sw_hweight32)
SYM_FUNC_END(__sw_hweight32)
EXPORT_SYMBOL(__sw_hweight32)
-SYM_FUNC_START(__sw_hweight64)
+/*
+ * No 32-bit variant, because it's implemented as an inline wrapper
+ * on top of __arch_hweight32():
+ */
#ifdef CONFIG_X86_64
+SYM_FUNC_START(__sw_hweight64)
pushq %rdi
pushq %rdx
@@ -66,18 +70,6 @@ SYM_FUNC_START(__sw_hweight64)
popq %rdx
popq %rdi
RET
-#else /* CONFIG_X86_32 */
- /* We're getting an u64 arg in (%eax,%edx): unsigned long hweight64(__u64 w) */
- pushl %ecx
-
- call __sw_hweight32
- movl %eax, %ecx # stash away result
- movl %edx, %eax # second part of input
- call __sw_hweight32
- addl %ecx, %eax # result
-
- popl %ecx
- RET
-#endif
SYM_FUNC_END(__sw_hweight64)
EXPORT_SYMBOL(__sw_hweight64)
+#endif
diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S
index 76697df8dfd5..0ae2e1712e2e 100644
--- a/arch/x86/lib/memcpy_64.S
+++ b/arch/x86/lib/memcpy_64.S
@@ -1,12 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright 2002 Andi Kleen */
+#include <linux/export.h>
#include <linux/linkage.h>
#include <linux/cfi_types.h>
#include <asm/errno.h>
#include <asm/cpufeatures.h>
#include <asm/alternative.h>
-#include <asm/export.h>
.section .noinstr.text, "ax"
diff --git a/arch/x86/lib/memmove_32.S b/arch/x86/lib/memmove_32.S
index 0588b2c0fc95..35010ba3dd6f 100644
--- a/arch/x86/lib/memmove_32.S
+++ b/arch/x86/lib/memmove_32.S
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/export.h>
#include <linux/linkage.h>
-#include <asm/export.h>
SYM_FUNC_START(memmove)
/*
diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S
index ccdf3a597045..1b60ae81ecd8 100644
--- a/arch/x86/lib/memmove_64.S
+++ b/arch/x86/lib/memmove_64.S
@@ -6,10 +6,10 @@
* This assembly file is re-written from memmove_64.c file.
* - Copyright 2011 Fenghua Yu <fenghua.yu@intel.com>
*/
+#include <linux/export.h>
#include <linux/linkage.h>
#include <asm/cpufeatures.h>
#include <asm/alternative.h>
-#include <asm/export.h>
#undef memmove
diff --git a/arch/x86/lib/memset_64.S b/arch/x86/lib/memset_64.S
index 3d818b849ec6..0199d56cb479 100644
--- a/arch/x86/lib/memset_64.S
+++ b/arch/x86/lib/memset_64.S
@@ -1,10 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright 2002 Andi Kleen, SuSE Labs */
+#include <linux/export.h>
#include <linux/linkage.h>
#include <asm/cpufeatures.h>
#include <asm/alternative.h>
-#include <asm/export.h>
.section .noinstr.text, "ax"
diff --git a/arch/x86/lib/putuser.S b/arch/x86/lib/putuser.S
index 235bbda6fc82..2877f5934177 100644
--- a/arch/x86/lib/putuser.S
+++ b/arch/x86/lib/putuser.S
@@ -11,13 +11,12 @@
* return an error value in addition to the "real"
* return value.
*/
+#include <linux/export.h>
#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/errno.h>
#include <asm/asm.h>
#include <asm/smap.h>
-#include <asm/export.h>
-
/*
* __put_user_X
diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S
index cd86aeb5fdd3..7b2589877d06 100644
--- a/arch/x86/lib/retpoline.S
+++ b/arch/x86/lib/retpoline.S
@@ -1,12 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/export.h>
#include <linux/stringify.h>
#include <linux/linkage.h>
#include <asm/dwarf2.h>
#include <asm/cpufeatures.h>
#include <asm/alternative.h>
#include <asm/asm-offsets.h>
-#include <asm/export.h>
#include <asm/nospec-branch.h>
#include <asm/unwind_hints.h>
#include <asm/percpu.h>
@@ -126,11 +126,19 @@ SYM_CODE_END(__x86_indirect_jump_thunk_array)
#include <asm/GEN-for-each-reg.h>
#undef GEN
#endif
+
+#ifdef CONFIG_RETHUNK
+
/*
- * This function name is magical and is used by -mfunction-return=thunk-extern
- * for the compiler to generate JMPs to it.
+ * Be careful here: that label cannot really be removed because in
+ * some configurations and toolchains, the JMP __x86_return_thunk the
+ * compiler issues is either a short one or the compiler doesn't use
+ * relocations for same-section JMPs and that breaks the returns
+ * detection logic in apply_returns() and in objtool.
*/
-#ifdef CONFIG_RETHUNK
+ .section .text..__x86.return_thunk
+
+#ifdef CONFIG_CPU_SRSO
/*
* srso_alias_untrain_ret() and srso_alias_safe_ret() are placed at
@@ -147,29 +155,18 @@ SYM_CODE_END(__x86_indirect_jump_thunk_array)
*
* As a result, srso_alias_safe_ret() becomes a safe return.
*/
-#ifdef CONFIG_CPU_SRSO
- .section .text..__x86.rethunk_untrain
-
-SYM_START(srso_alias_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE)
+ .pushsection .text..__x86.rethunk_untrain
+SYM_CODE_START_NOALIGN(srso_alias_untrain_ret)
UNWIND_HINT_FUNC
ANNOTATE_NOENDBR
ASM_NOP2
lfence
jmp srso_alias_return_thunk
SYM_FUNC_END(srso_alias_untrain_ret)
-__EXPORT_THUNK(srso_alias_untrain_ret)
-
- .section .text..__x86.rethunk_safe
-#else
-/* dummy definition for alternatives */
-SYM_START(srso_alias_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE)
- ANNOTATE_UNRET_SAFE
- ret
- int3
-SYM_FUNC_END(srso_alias_untrain_ret)
-#endif
+ .popsection
-SYM_START(srso_alias_safe_ret, SYM_L_GLOBAL, SYM_A_NONE)
+ .pushsection .text..__x86.rethunk_safe
+SYM_CODE_START_NOALIGN(srso_alias_safe_ret)
lea 8(%_ASM_SP), %_ASM_SP
UNWIND_HINT_FUNC
ANNOTATE_UNRET_SAFE
@@ -177,14 +174,63 @@ SYM_START(srso_alias_safe_ret, SYM_L_GLOBAL, SYM_A_NONE)
int3
SYM_FUNC_END(srso_alias_safe_ret)
- .section .text..__x86.return_thunk
-
-SYM_CODE_START(srso_alias_return_thunk)
+SYM_CODE_START_NOALIGN(srso_alias_return_thunk)
UNWIND_HINT_FUNC
ANNOTATE_NOENDBR
call srso_alias_safe_ret
ud2
SYM_CODE_END(srso_alias_return_thunk)
+ .popsection
+
+/*
+ * SRSO untraining sequence for Zen1/2, similar to retbleed_untrain_ret()
+ * above. On kernel entry, srso_untrain_ret() is executed which is a
+ *
+ * movabs $0xccccc30824648d48,%rax
+ *
+ * and when the return thunk executes the inner label srso_safe_ret()
+ * later, it is a stack manipulation and a RET which is mispredicted and
+ * thus a "safe" one to use.
+ */
+ .align 64
+ .skip 64 - (srso_safe_ret - srso_untrain_ret), 0xcc
+SYM_CODE_START_LOCAL_NOALIGN(srso_untrain_ret)
+ ANNOTATE_NOENDBR
+ .byte 0x48, 0xb8
+
+/*
+ * This forces the function return instruction to speculate into a trap
+ * (UD2 in srso_return_thunk() below). This RET will then mispredict
+ * and execution will continue at the return site read from the top of
+ * the stack.
+ */
+SYM_INNER_LABEL(srso_safe_ret, SYM_L_GLOBAL)
+ lea 8(%_ASM_SP), %_ASM_SP
+ ret
+ int3
+ int3
+ /* end of movabs */
+ lfence
+ call srso_safe_ret
+ ud2
+SYM_CODE_END(srso_safe_ret)
+SYM_FUNC_END(srso_untrain_ret)
+
+SYM_CODE_START(srso_return_thunk)
+ UNWIND_HINT_FUNC
+ ANNOTATE_NOENDBR
+ call srso_safe_ret
+ ud2
+SYM_CODE_END(srso_return_thunk)
+
+#define JMP_SRSO_UNTRAIN_RET "jmp srso_untrain_ret"
+#define JMP_SRSO_ALIAS_UNTRAIN_RET "jmp srso_alias_untrain_ret"
+#else /* !CONFIG_CPU_SRSO */
+#define JMP_SRSO_UNTRAIN_RET "ud2"
+#define JMP_SRSO_ALIAS_UNTRAIN_RET "ud2"
+#endif /* CONFIG_CPU_SRSO */
+
+#ifdef CONFIG_CPU_UNRET_ENTRY
/*
* Some generic notes on the untraining sequences:
@@ -216,7 +262,7 @@ SYM_CODE_END(srso_alias_return_thunk)
*/
.align 64
.skip 64 - (retbleed_return_thunk - retbleed_untrain_ret), 0xcc
-SYM_START(retbleed_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE)
+SYM_CODE_START_LOCAL_NOALIGN(retbleed_untrain_ret)
ANNOTATE_NOENDBR
/*
* As executed from retbleed_untrain_ret, this is:
@@ -264,72 +310,27 @@ SYM_CODE_END(retbleed_return_thunk)
jmp retbleed_return_thunk
int3
SYM_FUNC_END(retbleed_untrain_ret)
-__EXPORT_THUNK(retbleed_untrain_ret)
-/*
- * SRSO untraining sequence for Zen1/2, similar to retbleed_untrain_ret()
- * above. On kernel entry, srso_untrain_ret() is executed which is a
- *
- * movabs $0xccccc30824648d48,%rax
- *
- * and when the return thunk executes the inner label srso_safe_ret()
- * later, it is a stack manipulation and a RET which is mispredicted and
- * thus a "safe" one to use.
- */
- .align 64
- .skip 64 - (srso_safe_ret - srso_untrain_ret), 0xcc
-SYM_START(srso_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE)
- ANNOTATE_NOENDBR
- .byte 0x48, 0xb8
+#define JMP_RETBLEED_UNTRAIN_RET "jmp retbleed_untrain_ret"
+#else /* !CONFIG_CPU_UNRET_ENTRY */
+#define JMP_RETBLEED_UNTRAIN_RET "ud2"
+#endif /* CONFIG_CPU_UNRET_ENTRY */
-/*
- * This forces the function return instruction to speculate into a trap
- * (UD2 in srso_return_thunk() below). This RET will then mispredict
- * and execution will continue at the return site read from the top of
- * the stack.
- */
-SYM_INNER_LABEL(srso_safe_ret, SYM_L_GLOBAL)
- lea 8(%_ASM_SP), %_ASM_SP
- ret
- int3
- int3
- /* end of movabs */
- lfence
- call srso_safe_ret
- ud2
-SYM_CODE_END(srso_safe_ret)
-SYM_FUNC_END(srso_untrain_ret)
-__EXPORT_THUNK(srso_untrain_ret)
-
-SYM_CODE_START(srso_return_thunk)
- UNWIND_HINT_FUNC
- ANNOTATE_NOENDBR
- call srso_safe_ret
- ud2
-SYM_CODE_END(srso_return_thunk)
+#if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_SRSO)
SYM_FUNC_START(entry_untrain_ret)
- ALTERNATIVE_2 "jmp retbleed_untrain_ret", \
- "jmp srso_untrain_ret", X86_FEATURE_SRSO, \
- "jmp srso_alias_untrain_ret", X86_FEATURE_SRSO_ALIAS
+ ALTERNATIVE_2 JMP_RETBLEED_UNTRAIN_RET, \
+ JMP_SRSO_UNTRAIN_RET, X86_FEATURE_SRSO, \
+ JMP_SRSO_ALIAS_UNTRAIN_RET, X86_FEATURE_SRSO_ALIAS
SYM_FUNC_END(entry_untrain_ret)
__EXPORT_THUNK(entry_untrain_ret)
-SYM_CODE_START(__x86_return_thunk)
- UNWIND_HINT_FUNC
- ANNOTATE_NOENDBR
- ANNOTATE_UNRET_SAFE
- ret
- int3
-SYM_CODE_END(__x86_return_thunk)
-EXPORT_SYMBOL(__x86_return_thunk)
-
-#endif /* CONFIG_RETHUNK */
+#endif /* CONFIG_CPU_UNRET_ENTRY || CONFIG_CPU_SRSO */
#ifdef CONFIG_CALL_DEPTH_TRACKING
.align 64
-SYM_FUNC_START(__x86_return_skl)
+SYM_FUNC_START(call_depth_return_thunk)
ANNOTATE_NOENDBR
/*
* Keep the hotpath in a 16byte I-fetch for the non-debug
@@ -356,6 +357,33 @@ SYM_FUNC_START(__x86_return_skl)
ANNOTATE_UNRET_SAFE
ret
int3
-SYM_FUNC_END(__x86_return_skl)
+SYM_FUNC_END(call_depth_return_thunk)
#endif /* CONFIG_CALL_DEPTH_TRACKING */
+
+/*
+ * This function name is magical and is used by -mfunction-return=thunk-extern
+ * for the compiler to generate JMPs to it.
+ *
+ * This code is only used during kernel boot or module init. All
+ * 'JMP __x86_return_thunk' sites are changed to something else by
+ * apply_returns().
+ *
+ * This should be converted eventually to call a warning function which
+ * should scream loudly when the default return thunk is called after
+ * alternatives have been applied.
+ *
+ * That warning function cannot BUG() because the bug splat cannot be
+ * displayed in all possible configurations, leading to users not really
+ * knowing why the machine froze.
+ */
+SYM_CODE_START(__x86_return_thunk)
+ UNWIND_HINT_FUNC
+ ANNOTATE_NOENDBR
+ ANNOTATE_UNRET_SAFE
+ ret
+ int3
+SYM_CODE_END(__x86_return_thunk)
+EXPORT_SYMBOL(__x86_return_thunk)
+
+#endif /* CONFIG_RETHUNK */
diff --git a/arch/x86/mm/maccess.c b/arch/x86/mm/maccess.c
index 5a53c2cc169c..6993f026adec 100644
--- a/arch/x86/mm/maccess.c
+++ b/arch/x86/mm/maccess.c
@@ -9,12 +9,21 @@ bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
unsigned long vaddr = (unsigned long)unsafe_src;
/*
- * Range covering the highest possible canonical userspace address
- * as well as non-canonical address range. For the canonical range
- * we also need to include the userspace guard page.
+ * Do not allow userspace addresses. This disallows
+ * normal userspace and the userspace guard page:
*/
- return vaddr >= TASK_SIZE_MAX + PAGE_SIZE &&
- __is_canonical_address(vaddr, boot_cpu_data.x86_virt_bits);
+ if (vaddr < TASK_SIZE_MAX + PAGE_SIZE)
+ return false;
+
+ /*
+ * Allow everything during early boot before 'x86_virt_bits'
+ * is initialized. Needed for instruction decoding in early
+ * exception handlers.
+ */
+ if (!boot_cpu_data.x86_virt_bits)
+ return true;
+
+ return __is_canonical_address(vaddr, boot_cpu_data.x86_virt_bits);
}
#else
bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 9f27e14e185f..c290c55b632b 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -12,6 +12,7 @@
#include <linux/swiotlb.h>
#include <linux/cc_platform.h>
#include <linux/mem_encrypt.h>
+#include <linux/virtio_anchor.h>
/* Override for DMA direct allocation check - ARCH_HAS_FORCE_DMA_UNENCRYPTED */
bool force_dma_unencrypted(struct device *dev)
@@ -86,3 +87,36 @@ void __init mem_encrypt_init(void)
print_mem_encrypt_feature_info();
}
+
+void __init mem_encrypt_setup_arch(void)
+{
+ phys_addr_t total_mem = memblock_phys_mem_size();
+ unsigned long size;
+
+ if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
+ return;
+
+ /*
+ * For SEV and TDX, all DMA has to occur via shared/unencrypted pages.
+ * Kernel uses SWIOTLB to make this happen without changing device
+ * drivers. However, depending on the workload being run, the
+ * default 64MB of SWIOTLB may not be enough and SWIOTLB may
+ * run out of buffers for DMA, resulting in I/O errors and/or
+ * performance degradation especially with high I/O workloads.
+ *
+ * Adjust the default size of SWIOTLB using a percentage of guest
+ * memory for SWIOTLB buffers. Also, as the SWIOTLB bounce buffer
+ * memory is allocated from low memory, ensure that the adjusted size
+ * is within the limits of low available memory.
+ *
+ * The percentage of guest memory used here for SWIOTLB buffers
+ * is more of an approximation of the static adjustment which
+ * 64MB for <1G, and ~128M to 256M for 1G-to-4G, i.e., the 6%
+ */
+ size = total_mem * 6 / 100;
+ size = clamp_val(size, IO_TLB_DEFAULT_SIZE, SZ_1G);
+ swiotlb_adjust_size(size);
+
+ /* Set restricted memory access for virtio. */
+ virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc);
+}
diff --git a/arch/x86/mm/mem_encrypt_amd.c b/arch/x86/mm/mem_encrypt_amd.c
index 6faea41e99b6..70b91de2e053 100644
--- a/arch/x86/mm/mem_encrypt_amd.c
+++ b/arch/x86/mm/mem_encrypt_amd.c
@@ -19,8 +19,6 @@
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <linux/dma-mapping.h>
-#include <linux/virtio_config.h>
-#include <linux/virtio_anchor.h>
#include <linux/cc_platform.h>
#include <asm/tlbflush.h>
@@ -34,6 +32,7 @@
#include <asm/msr.h>
#include <asm/cmdline.h>
#include <asm/sev.h>
+#include <asm/ia32.h>
#include "mm_internal.h"
@@ -215,40 +214,6 @@ void __init sme_map_bootdata(char *real_mode_data)
__sme_early_map_unmap_mem(__va(cmdline_paddr), COMMAND_LINE_SIZE, true);
}
-void __init sev_setup_arch(void)
-{
- phys_addr_t total_mem = memblock_phys_mem_size();
- unsigned long size;
-
- if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
- return;
-
- /*
- * For SEV, all DMA has to occur via shared/unencrypted pages.
- * SEV uses SWIOTLB to make this happen without changing device
- * drivers. However, depending on the workload being run, the
- * default 64MB of SWIOTLB may not be enough and SWIOTLB may
- * run out of buffers for DMA, resulting in I/O errors and/or
- * performance degradation especially with high I/O workloads.
- *
- * Adjust the default size of SWIOTLB for SEV guests using
- * a percentage of guest memory for SWIOTLB buffers.
- * Also, as the SWIOTLB bounce buffer memory is allocated
- * from low memory, ensure that the adjusted size is within
- * the limits of low available memory.
- *
- * The percentage of guest memory used here for SWIOTLB buffers
- * is more of an approximation of the static adjustment which
- * 64MB for <1G, and ~128M to 256M for 1G-to-4G, i.e., the 6%
- */
- size = total_mem * 6 / 100;
- size = clamp_val(size, IO_TLB_DEFAULT_SIZE, SZ_1G);
- swiotlb_adjust_size(size);
-
- /* Set restricted memory access for virtio. */
- virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc);
-}
-
static unsigned long pg_level_to_pfn(int level, pte_t *kpte, pgprot_t *ret_prot)
{
unsigned long pfn = 0;
@@ -517,6 +482,16 @@ void __init sme_early_init(void)
*/
if (sev_status & MSR_AMD64_SEV_ES_ENABLED)
x86_cpuinit.parallel_bringup = false;
+
+ /*
+ * The VMM is capable of injecting interrupt 0x80 and triggering the
+ * compatibility syscall path.
+ *
+ * By default, the 32-bit emulation is disabled in order to ensure
+ * the safety of the VM.
+ */
+ if (sev_status & MSR_AMD64_SEV_ENABLED)
+ ia32_disable();
}
void __init mem_encrypt_free_decrypted_mem(void)
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index 2aadb2019b4f..b29ceb19e46e 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -3,6 +3,7 @@
#include <linux/acpi.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/of.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/memblock.h>
@@ -11,6 +12,7 @@
#include <linux/nodemask.h>
#include <linux/sched.h>
#include <linux/topology.h>
+#include <linux/sort.h>
#include <asm/e820/api.h>
#include <asm/proto.h>
@@ -56,7 +58,7 @@ s16 __apicid_to_node[MAX_LOCAL_APIC] = {
int numa_cpu_node(int cpu)
{
- int apicid = early_per_cpu(x86_cpu_to_apicid, cpu);
+ u32 apicid = early_per_cpu(x86_cpu_to_apicid, cpu);
if (apicid != BAD_APICID)
return __apicid_to_node[apicid];
@@ -601,13 +603,6 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
if (start >= end)
continue;
- /*
- * Don't confuse VM with a node that doesn't have the
- * minimum amount of memory:
- */
- if (end && (end - start) < NODE_MIN_SIZE)
- continue;
-
alloc_node_data(nid);
}
@@ -733,6 +728,8 @@ void __init x86_numa_init(void)
if (!numa_init(amd_numa_init))
return;
#endif
+ if (acpi_disabled && !numa_init(of_numa_init))
+ return;
}
numa_init(dummy_numa_init);
@@ -786,7 +783,7 @@ void __init init_gi_nodes(void)
void __init init_cpu_to_node(void)
{
int cpu;
- u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid);
+ u32 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid);
BUG_ON(cpu_to_apicid == NULL);
@@ -961,4 +958,83 @@ int memory_add_physaddr_to_nid(u64 start)
return nid;
}
EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+
+static int __init cmp_memblk(const void *a, const void *b)
+{
+ const struct numa_memblk *ma = *(const struct numa_memblk **)a;
+ const struct numa_memblk *mb = *(const struct numa_memblk **)b;
+
+ return ma->start - mb->start;
+}
+
+static struct numa_memblk *numa_memblk_list[NR_NODE_MEMBLKS] __initdata;
+
+/**
+ * numa_fill_memblks - Fill gaps in numa_meminfo memblks
+ * @start: address to begin fill
+ * @end: address to end fill
+ *
+ * Find and extend numa_meminfo memblks to cover the @start-@end
+ * physical address range, such that the first memblk includes
+ * @start, the last memblk includes @end, and any gaps in between
+ * are filled.
+ *
+ * RETURNS:
+ * 0 : Success
+ * NUMA_NO_MEMBLK : No memblk exists in @start-@end range
+ */
+
+int __init numa_fill_memblks(u64 start, u64 end)
+{
+ struct numa_memblk **blk = &numa_memblk_list[0];
+ struct numa_meminfo *mi = &numa_meminfo;
+ int count = 0;
+ u64 prev_end;
+
+ /*
+ * Create a list of pointers to numa_meminfo memblks that
+ * overlap start, end. Exclude (start == bi->end) since
+ * end addresses in both a CFMWS range and a memblk range
+ * are exclusive.
+ *
+ * This list of pointers is used to make in-place changes
+ * that fill out the numa_meminfo memblks.
+ */
+ for (int i = 0; i < mi->nr_blks; i++) {
+ struct numa_memblk *bi = &mi->blk[i];
+
+ if (start < bi->end && end >= bi->start) {
+ blk[count] = &mi->blk[i];
+ count++;
+ }
+ }
+ if (!count)
+ return NUMA_NO_MEMBLK;
+
+ /* Sort the list of pointers in memblk->start order */
+ sort(&blk[0], count, sizeof(blk[0]), cmp_memblk, NULL);
+
+ /* Make sure the first/last memblks include start/end */
+ blk[0]->start = min(blk[0]->start, start);
+ blk[count - 1]->end = max(blk[count - 1]->end, end);
+
+ /*
+ * Fill any gaps by tracking the previous memblks
+ * end address and backfilling to it if needed.
+ */
+ prev_end = blk[0]->end;
+ for (int i = 1; i < count; i++) {
+ struct numa_memblk *curr = blk[i];
+
+ if (prev_end >= curr->start) {
+ if (prev_end < curr->end)
+ prev_end = curr->end;
+ } else {
+ curr->start = prev_end;
+ prev_end = curr->end;
+ }
+ }
+ return 0;
+}
+
#endif
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index 9deadf517f14..0cbc1b8e8e3d 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -76,6 +76,9 @@ void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
#if CONFIG_PGTABLE_LEVELS > 3
void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
{
+ struct ptdesc *ptdesc = virt_to_ptdesc(pud);
+
+ pagetable_pud_dtor(ptdesc);
paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
paravirt_tlb_remove_table(tlb, virt_to_page(pud));
}
diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
index 78414c6d1b5e..5dd733944629 100644
--- a/arch/x86/mm/pti.c
+++ b/arch/x86/mm/pti.c
@@ -69,6 +69,7 @@ static void __init pti_print_if_secure(const char *reason)
pr_info("%s\n", reason);
}
+/* Assume mode is auto unless overridden via cmdline below. */
static enum pti_mode {
PTI_AUTO = 0,
PTI_FORCE_OFF,
@@ -77,50 +78,49 @@ static enum pti_mode {
void __init pti_check_boottime_disable(void)
{
- char arg[5];
- int ret;
-
- /* Assume mode is auto unless overridden. */
- pti_mode = PTI_AUTO;
-
if (hypervisor_is_type(X86_HYPER_XEN_PV)) {
pti_mode = PTI_FORCE_OFF;
pti_print_if_insecure("disabled on XEN PV.");
return;
}
- ret = cmdline_find_option(boot_command_line, "pti", arg, sizeof(arg));
- if (ret > 0) {
- if (ret == 3 && !strncmp(arg, "off", 3)) {
- pti_mode = PTI_FORCE_OFF;
- pti_print_if_insecure("disabled on command line.");
- return;
- }
- if (ret == 2 && !strncmp(arg, "on", 2)) {
- pti_mode = PTI_FORCE_ON;
- pti_print_if_secure("force enabled on command line.");
- goto enable;
- }
- if (ret == 4 && !strncmp(arg, "auto", 4)) {
- pti_mode = PTI_AUTO;
- goto autosel;
- }
- }
-
- if (cmdline_find_option_bool(boot_command_line, "nopti") ||
- cpu_mitigations_off()) {
+ if (cpu_mitigations_off())
pti_mode = PTI_FORCE_OFF;
+ if (pti_mode == PTI_FORCE_OFF) {
pti_print_if_insecure("disabled on command line.");
return;
}
-autosel:
- if (!boot_cpu_has_bug(X86_BUG_CPU_MELTDOWN))
+ if (pti_mode == PTI_FORCE_ON)
+ pti_print_if_secure("force enabled on command line.");
+
+ if (pti_mode == PTI_AUTO && !boot_cpu_has_bug(X86_BUG_CPU_MELTDOWN))
return;
-enable:
+
setup_force_cpu_cap(X86_FEATURE_PTI);
}
+static int __init pti_parse_cmdline(char *arg)
+{
+ if (!strcmp(arg, "off"))
+ pti_mode = PTI_FORCE_OFF;
+ else if (!strcmp(arg, "on"))
+ pti_mode = PTI_FORCE_ON;
+ else if (!strcmp(arg, "auto"))
+ pti_mode = PTI_AUTO;
+ else
+ return -EINVAL;
+ return 0;
+}
+early_param("pti", pti_parse_cmdline);
+
+static int __init pti_parse_cmdline_nopti(char *arg)
+{
+ pti_mode = PTI_FORCE_OFF;
+ return 0;
+}
+early_param("nopti", pti_parse_cmdline_nopti);
+
pgd_t __pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd)
{
/*
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index a5930042139d..e89e415aa743 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -16,6 +16,9 @@
#include <asm/set_memory.h>
#include <asm/nospec-branch.h>
#include <asm/text-patching.h>
+#include <asm/unwind.h>
+
+static bool all_callee_regs_used[4] = {true, true, true, true};
static u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len)
{
@@ -255,6 +258,14 @@ struct jit_context {
/* Number of bytes that will be skipped on tailcall */
#define X86_TAIL_CALL_OFFSET (11 + ENDBR_INSN_SIZE)
+static void push_r12(u8 **pprog)
+{
+ u8 *prog = *pprog;
+
+ EMIT2(0x41, 0x54); /* push r12 */
+ *pprog = prog;
+}
+
static void push_callee_regs(u8 **pprog, bool *callee_regs_used)
{
u8 *prog = *pprog;
@@ -270,6 +281,14 @@ static void push_callee_regs(u8 **pprog, bool *callee_regs_used)
*pprog = prog;
}
+static void pop_r12(u8 **pprog)
+{
+ u8 *prog = *pprog;
+
+ EMIT2(0x41, 0x5C); /* pop r12 */
+ *pprog = prog;
+}
+
static void pop_callee_regs(u8 **pprog, bool *callee_regs_used)
{
u8 *prog = *pprog;
@@ -291,7 +310,8 @@ static void pop_callee_regs(u8 **pprog, bool *callee_regs_used)
* while jumping to another program
*/
static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf,
- bool tail_call_reachable, bool is_subprog)
+ bool tail_call_reachable, bool is_subprog,
+ bool is_exception_cb)
{
u8 *prog = *pprog;
@@ -303,12 +323,30 @@ static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf,
prog += X86_PATCH_SIZE;
if (!ebpf_from_cbpf) {
if (tail_call_reachable && !is_subprog)
+ /* When it's the entry of the whole tailcall context,
+ * zeroing rax means initialising tail_call_cnt.
+ */
EMIT2(0x31, 0xC0); /* xor eax, eax */
else
+ /* Keep the same instruction layout. */
EMIT2(0x66, 0x90); /* nop2 */
}
- EMIT1(0x55); /* push rbp */
- EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */
+ /* Exception callback receives FP as third parameter */
+ if (is_exception_cb) {
+ EMIT3(0x48, 0x89, 0xF4); /* mov rsp, rsi */
+ EMIT3(0x48, 0x89, 0xD5); /* mov rbp, rdx */
+ /* The main frame must have exception_boundary as true, so we
+ * first restore those callee-saved regs from stack, before
+ * reusing the stack frame.
+ */
+ pop_callee_regs(&prog, all_callee_regs_used);
+ pop_r12(&prog);
+ /* Reset the stack frame. */
+ EMIT3(0x48, 0x89, 0xEC); /* mov rsp, rbp */
+ } else {
+ EMIT1(0x55); /* push rbp */
+ EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */
+ }
/* X86_TAIL_CALL_OFFSET is here */
EMIT_ENDBR();
@@ -467,7 +505,8 @@ static void emit_return(u8 **pprog, u8 *ip)
* goto *(prog->bpf_func + prologue_size);
* out:
*/
-static void emit_bpf_tail_call_indirect(u8 **pprog, bool *callee_regs_used,
+static void emit_bpf_tail_call_indirect(struct bpf_prog *bpf_prog,
+ u8 **pprog, bool *callee_regs_used,
u32 stack_depth, u8 *ip,
struct jit_context *ctx)
{
@@ -517,7 +556,12 @@ static void emit_bpf_tail_call_indirect(u8 **pprog, bool *callee_regs_used,
offset = ctx->tail_call_indirect_label - (prog + 2 - start);
EMIT2(X86_JE, offset); /* je out */
- pop_callee_regs(&prog, callee_regs_used);
+ if (bpf_prog->aux->exception_boundary) {
+ pop_callee_regs(&prog, all_callee_regs_used);
+ pop_r12(&prog);
+ } else {
+ pop_callee_regs(&prog, callee_regs_used);
+ }
EMIT1(0x58); /* pop rax */
if (stack_depth)
@@ -541,7 +585,8 @@ static void emit_bpf_tail_call_indirect(u8 **pprog, bool *callee_regs_used,
*pprog = prog;
}
-static void emit_bpf_tail_call_direct(struct bpf_jit_poke_descriptor *poke,
+static void emit_bpf_tail_call_direct(struct bpf_prog *bpf_prog,
+ struct bpf_jit_poke_descriptor *poke,
u8 **pprog, u8 *ip,
bool *callee_regs_used, u32 stack_depth,
struct jit_context *ctx)
@@ -570,7 +615,13 @@ static void emit_bpf_tail_call_direct(struct bpf_jit_poke_descriptor *poke,
emit_jump(&prog, (u8 *)poke->tailcall_target + X86_PATCH_SIZE,
poke->tailcall_bypass);
- pop_callee_regs(&prog, callee_regs_used);
+ if (bpf_prog->aux->exception_boundary) {
+ pop_callee_regs(&prog, all_callee_regs_used);
+ pop_r12(&prog);
+ } else {
+ pop_callee_regs(&prog, callee_regs_used);
+ }
+
EMIT1(0x58); /* pop rax */
if (stack_depth)
EMIT3_off32(0x48, 0x81, 0xC4, round_up(stack_depth, 8));
@@ -1018,6 +1069,10 @@ static void emit_shiftx(u8 **pprog, u32 dst_reg, u8 src_reg, bool is64, u8 op)
#define INSN_SZ_DIFF (((addrs[i] - addrs[i - 1]) - (prog - temp)))
+/* mov rax, qword ptr [rbp - rounded_stack_depth - 8] */
+#define RESTORE_TAIL_CALL_CNT(stack) \
+ EMIT3_off32(0x48, 0x8B, 0x85, -round_up(stack, 8) - 8)
+
static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image,
int oldproglen, struct jit_context *ctx, bool jmp_padding)
{
@@ -1041,8 +1096,20 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
emit_prologue(&prog, bpf_prog->aux->stack_depth,
bpf_prog_was_classic(bpf_prog), tail_call_reachable,
- bpf_prog->aux->func_idx != 0);
- push_callee_regs(&prog, callee_regs_used);
+ bpf_is_subprog(bpf_prog), bpf_prog->aux->exception_cb);
+ /* Exception callback will clobber callee regs for its own use, and
+ * restore the original callee regs from main prog's stack frame.
+ */
+ if (bpf_prog->aux->exception_boundary) {
+ /* We also need to save r12, which is not mapped to any BPF
+ * register, as we throw after entry into the kernel, which may
+ * overwrite r12.
+ */
+ push_r12(&prog);
+ push_callee_regs(&prog, all_callee_regs_used);
+ } else {
+ push_callee_regs(&prog, callee_regs_used);
+ }
ilen = prog - temp;
if (rw_image)
@@ -1623,9 +1690,7 @@ st: if (is_imm8(insn->off))
func = (u8 *) __bpf_call_base + imm32;
if (tail_call_reachable) {
- /* mov rax, qword ptr [rbp - rounded_stack_depth - 8] */
- EMIT3_off32(0x48, 0x8B, 0x85,
- -round_up(bpf_prog->aux->stack_depth, 8) - 8);
+ RESTORE_TAIL_CALL_CNT(bpf_prog->aux->stack_depth);
if (!imm32)
return -EINVAL;
offs = 7 + x86_call_depth_emit_accounting(&prog, func);
@@ -1641,13 +1706,15 @@ st: if (is_imm8(insn->off))
case BPF_JMP | BPF_TAIL_CALL:
if (imm32)
- emit_bpf_tail_call_direct(&bpf_prog->aux->poke_tab[imm32 - 1],
+ emit_bpf_tail_call_direct(bpf_prog,
+ &bpf_prog->aux->poke_tab[imm32 - 1],
&prog, image + addrs[i - 1],
callee_regs_used,
bpf_prog->aux->stack_depth,
ctx);
else
- emit_bpf_tail_call_indirect(&prog,
+ emit_bpf_tail_call_indirect(bpf_prog,
+ &prog,
callee_regs_used,
bpf_prog->aux->stack_depth,
image + addrs[i - 1],
@@ -1900,7 +1967,12 @@ emit_jmp:
seen_exit = true;
/* Update cleanup_addr */
ctx->cleanup_addr = proglen;
- pop_callee_regs(&prog, callee_regs_used);
+ if (bpf_prog->aux->exception_boundary) {
+ pop_callee_regs(&prog, all_callee_regs_used);
+ pop_r12(&prog);
+ } else {
+ pop_callee_regs(&prog, callee_regs_used);
+ }
EMIT1(0xC9); /* leave */
emit_return(&prog, image + addrs[i - 1] + (prog - temp));
break;
@@ -2400,6 +2472,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
* [ ... ]
* [ stack_arg2 ]
* RBP - arg_stack_off [ stack_arg1 ]
+ * RSP [ tail_call_cnt ] BPF_TRAMP_F_TAIL_CALL_CTX
*/
/* room for return value of orig_call or fentry prog */
@@ -2464,6 +2537,8 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
else
/* sub rsp, stack_size */
EMIT4(0x48, 0x83, 0xEC, stack_size);
+ if (flags & BPF_TRAMP_F_TAIL_CALL_CTX)
+ EMIT1(0x50); /* push rax */
/* mov QWORD PTR [rbp - rbx_off], rbx */
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_6, -rbx_off);
@@ -2516,9 +2591,15 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
restore_regs(m, &prog, regs_off);
save_args(m, &prog, arg_stack_off, true);
+ if (flags & BPF_TRAMP_F_TAIL_CALL_CTX)
+ /* Before calling the original function, restore the
+ * tail_call_cnt from stack to rax.
+ */
+ RESTORE_TAIL_CALL_CNT(stack_size);
+
if (flags & BPF_TRAMP_F_ORIG_STACK) {
- emit_ldx(&prog, BPF_DW, BPF_REG_0, BPF_REG_FP, 8);
- EMIT2(0xff, 0xd0); /* call *rax */
+ emit_ldx(&prog, BPF_DW, BPF_REG_6, BPF_REG_FP, 8);
+ EMIT2(0xff, 0xd3); /* call *rbx */
} else {
/* call original function */
if (emit_rsb_call(&prog, orig_call, prog)) {
@@ -2569,7 +2650,12 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
ret = -EINVAL;
goto cleanup;
}
- }
+ } else if (flags & BPF_TRAMP_F_TAIL_CALL_CTX)
+ /* Before running the original function, restore the
+ * tail_call_cnt from stack to rax.
+ */
+ RESTORE_TAIL_CALL_CNT(stack_size);
+
/* restore return value of orig_call or fentry prog back into RAX */
if (save_ret)
emit_ldx(&prog, BPF_DW, BPF_REG_0, BPF_REG_FP, -8);
@@ -2913,3 +2999,75 @@ void bpf_jit_free(struct bpf_prog *prog)
bpf_prog_unlock_free(prog);
}
+
+bool bpf_jit_supports_exceptions(void)
+{
+ /* We unwind through both kernel frames (starting from within bpf_throw
+ * call) and BPF frames. Therefore we require ORC unwinder to be enabled
+ * to walk kernel frames and reach BPF frames in the stack trace.
+ */
+ return IS_ENABLED(CONFIG_UNWINDER_ORC);
+}
+
+void arch_bpf_stack_walk(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp), void *cookie)
+{
+#if defined(CONFIG_UNWINDER_ORC)
+ struct unwind_state state;
+ unsigned long addr;
+
+ for (unwind_start(&state, current, NULL, NULL); !unwind_done(&state);
+ unwind_next_frame(&state)) {
+ addr = unwind_get_return_address(&state);
+ if (!addr || !consume_fn(cookie, (u64)addr, (u64)state.sp, (u64)state.bp))
+ break;
+ }
+ return;
+#endif
+ WARN(1, "verification of programs using bpf_throw should have failed\n");
+}
+
+void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke,
+ struct bpf_prog *new, struct bpf_prog *old)
+{
+ u8 *old_addr, *new_addr, *old_bypass_addr;
+ int ret;
+
+ old_bypass_addr = old ? NULL : poke->bypass_addr;
+ old_addr = old ? (u8 *)old->bpf_func + poke->adj_off : NULL;
+ new_addr = new ? (u8 *)new->bpf_func + poke->adj_off : NULL;
+
+ /*
+ * On program loading or teardown, the program's kallsym entry
+ * might not be in place, so we use __bpf_arch_text_poke to skip
+ * the kallsyms check.
+ */
+ if (new) {
+ ret = __bpf_arch_text_poke(poke->tailcall_target,
+ BPF_MOD_JUMP,
+ old_addr, new_addr);
+ BUG_ON(ret < 0);
+ if (!old) {
+ ret = __bpf_arch_text_poke(poke->tailcall_bypass,
+ BPF_MOD_JUMP,
+ poke->bypass_addr,
+ NULL);
+ BUG_ON(ret < 0);
+ }
+ } else {
+ ret = __bpf_arch_text_poke(poke->tailcall_bypass,
+ BPF_MOD_JUMP,
+ old_bypass_addr,
+ poke->bypass_addr);
+ BUG_ON(ret < 0);
+ /* let other CPUs finish the execution of program
+ * so that it will not possible to expose them
+ * to invalid nop, stack unwind, nop state
+ */
+ if (!ret)
+ synchronize_rcu();
+ ret = __bpf_arch_text_poke(poke->tailcall_target,
+ BPF_MOD_JUMP,
+ old_addr, NULL);
+ BUG_ON(ret < 0);
+ }
+}
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index e3ec02e6ac9f..f347c20247d3 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -3,9 +3,11 @@
* Exceptions for specific devices. Usually work-arounds for fatal design flaws.
*/
+#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/pci.h>
+#include <linux/suspend.h>
#include <linux/vgaarb.h>
#include <asm/amd_nb.h>
#include <asm/hpet.h>
@@ -904,3 +906,60 @@ static void chromeos_fixup_apl_pci_l1ss_capability(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x5ad6, chromeos_save_apl_pci_l1ss_capability);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, 0x5ad6, chromeos_fixup_apl_pci_l1ss_capability);
+
+#ifdef CONFIG_SUSPEND
+/*
+ * Root Ports on some AMD SoCs advertise PME_Support for D3hot and D3cold, but
+ * if the SoC is put into a hardware sleep state by the amd-pmc driver, the
+ * Root Ports don't generate wakeup interrupts for USB devices.
+ *
+ * When suspending, remove D3hot and D3cold from the PME_Support advertised
+ * by the Root Port so we don't use those states if we're expecting wakeup
+ * interrupts. Restore the advertised PME_Support when resuming.
+ */
+static void amd_rp_pme_suspend(struct pci_dev *dev)
+{
+ struct pci_dev *rp;
+
+ /*
+ * PM_SUSPEND_ON means we're doing runtime suspend, which means
+ * amd-pmc will not be involved so PMEs during D3 work as advertised.
+ *
+ * The PMEs *do* work if amd-pmc doesn't put the SoC in the hardware
+ * sleep state, but we assume amd-pmc is always present.
+ */
+ if (pm_suspend_target_state == PM_SUSPEND_ON)
+ return;
+
+ rp = pcie_find_root_port(dev);
+ if (!rp->pm_cap)
+ return;
+
+ rp->pme_support &= ~((PCI_PM_CAP_PME_D3hot|PCI_PM_CAP_PME_D3cold) >>
+ PCI_PM_CAP_PME_SHIFT);
+ dev_info_once(&rp->dev, "quirk: disabling D3cold for suspend\n");
+}
+
+static void amd_rp_pme_resume(struct pci_dev *dev)
+{
+ struct pci_dev *rp;
+ u16 pmc;
+
+ rp = pcie_find_root_port(dev);
+ if (!rp->pm_cap)
+ return;
+
+ pci_read_config_word(rp, rp->pm_cap + PCI_PM_PMC, &pmc);
+ rp->pme_support = FIELD_GET(PCI_PM_CAP_PME_MASK, pmc);
+}
+/* Rembrandt (yellow_carp) */
+DECLARE_PCI_FIXUP_SUSPEND(PCI_VENDOR_ID_AMD, 0x162e, amd_rp_pme_suspend);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x162e, amd_rp_pme_resume);
+DECLARE_PCI_FIXUP_SUSPEND(PCI_VENDOR_ID_AMD, 0x162f, amd_rp_pme_suspend);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x162f, amd_rp_pme_resume);
+/* Phoenix (pink_sardine) */
+DECLARE_PCI_FIXUP_SUSPEND(PCI_VENDOR_ID_AMD, 0x1668, amd_rp_pme_suspend);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x1668, amd_rp_pme_resume);
+DECLARE_PCI_FIXUP_SUSPEND(PCI_VENDOR_ID_AMD, 0x1669, amd_rp_pme_suspend);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x1669, amd_rp_pme_resume);
+#endif /* CONFIG_SUSPEND */
diff --git a/arch/x86/platform/uv/uv_nmi.c b/arch/x86/platform/uv/uv_nmi.c
index 45d0c17ce77c..e03207de2880 100644
--- a/arch/x86/platform/uv/uv_nmi.c
+++ b/arch/x86/platform/uv/uv_nmi.c
@@ -17,6 +17,7 @@
#include <linux/sched.h>
#include <linux/sched/debug.h>
#include <linux/slab.h>
+#include <linux/string.h>
#include <linux/clocksource.h>
#include <asm/apic.h>
@@ -178,49 +179,56 @@ module_param_named(debug, uv_nmi_debug, int, 0644);
} while (0)
/* Valid NMI Actions */
-#define ACTION_LEN 16
-static struct nmi_action {
- char *action;
- char *desc;
-} valid_acts[] = {
- { "kdump", "do kernel crash dump" },
- { "dump", "dump process stack for each cpu" },
- { "ips", "dump Inst Ptr info for each cpu" },
- { "kdb", "enter KDB (needs kgdboc= assignment)" },
- { "kgdb", "enter KGDB (needs gdb target remote)" },
- { "health", "check if CPUs respond to NMI" },
+enum action_t {
+ nmi_act_kdump,
+ nmi_act_dump,
+ nmi_act_ips,
+ nmi_act_kdb,
+ nmi_act_kgdb,
+ nmi_act_health,
+ nmi_act_max
};
-typedef char action_t[ACTION_LEN];
-static action_t uv_nmi_action = { "dump" };
+
+static const char * const actions[nmi_act_max] = {
+ [nmi_act_kdump] = "kdump",
+ [nmi_act_dump] = "dump",
+ [nmi_act_ips] = "ips",
+ [nmi_act_kdb] = "kdb",
+ [nmi_act_kgdb] = "kgdb",
+ [nmi_act_health] = "health",
+};
+
+static const char * const actions_desc[nmi_act_max] = {
+ [nmi_act_kdump] = "do kernel crash dump",
+ [nmi_act_dump] = "dump process stack for each cpu",
+ [nmi_act_ips] = "dump Inst Ptr info for each cpu",
+ [nmi_act_kdb] = "enter KDB (needs kgdboc= assignment)",
+ [nmi_act_kgdb] = "enter KGDB (needs gdb target remote)",
+ [nmi_act_health] = "check if CPUs respond to NMI",
+};
+
+static enum action_t uv_nmi_action = nmi_act_dump;
static int param_get_action(char *buffer, const struct kernel_param *kp)
{
- return sprintf(buffer, "%s\n", uv_nmi_action);
+ return sprintf(buffer, "%s\n", actions[uv_nmi_action]);
}
static int param_set_action(const char *val, const struct kernel_param *kp)
{
- int i;
- int n = ARRAY_SIZE(valid_acts);
- char arg[ACTION_LEN];
-
- /* (remove possible '\n') */
- strscpy(arg, val, strnchrnul(val, sizeof(arg)-1, '\n') - val + 1);
-
- for (i = 0; i < n; i++)
- if (!strcmp(arg, valid_acts[i].action))
- break;
+ int i, n = ARRAY_SIZE(actions);
- if (i < n) {
- strscpy(uv_nmi_action, arg, sizeof(uv_nmi_action));
- pr_info("UV: New NMI action:%s\n", uv_nmi_action);
+ i = sysfs_match_string(actions, val);
+ if (i >= 0) {
+ uv_nmi_action = i;
+ pr_info("UV: New NMI action:%s\n", actions[i]);
return 0;
}
- pr_err("UV: Invalid NMI action:%s, valid actions are:\n", arg);
+ pr_err("UV: Invalid NMI action. Valid actions are:\n");
for (i = 0; i < n; i++)
- pr_err("UV: %-8s - %s\n",
- valid_acts[i].action, valid_acts[i].desc);
+ pr_err("UV: %-8s - %s\n", actions[i], actions_desc[i]);
+
return -EINVAL;
}
@@ -228,15 +236,10 @@ static const struct kernel_param_ops param_ops_action = {
.get = param_get_action,
.set = param_set_action,
};
-#define param_check_action(name, p) __param_check(name, p, action_t)
+#define param_check_action(name, p) __param_check(name, p, enum action_t)
module_param_named(action, uv_nmi_action, action, 0644);
-static inline bool uv_nmi_action_is(const char *action)
-{
- return (strncmp(uv_nmi_action, action, strlen(action)) == 0);
-}
-
/* Setup which NMI support is present in system */
static void uv_nmi_setup_mmrs(void)
{
@@ -727,10 +730,10 @@ static void uv_nmi_dump_state_cpu(int cpu, struct pt_regs *regs)
if (cpu == 0)
uv_nmi_dump_cpu_ip_hdr();
- if (current->pid != 0 || !uv_nmi_action_is("ips"))
+ if (current->pid != 0 || uv_nmi_action != nmi_act_ips)
uv_nmi_dump_cpu_ip(cpu, regs);
- if (uv_nmi_action_is("dump")) {
+ if (uv_nmi_action == nmi_act_dump) {
pr_info("UV:%sNMI process trace for CPU %d\n", dots, cpu);
show_regs(regs);
}
@@ -798,7 +801,7 @@ static void uv_nmi_dump_state(int cpu, struct pt_regs *regs, int master)
int saved_console_loglevel = console_loglevel;
pr_alert("UV: tracing %s for %d CPUs from CPU %d\n",
- uv_nmi_action_is("ips") ? "IPs" : "processes",
+ uv_nmi_action == nmi_act_ips ? "IPs" : "processes",
atomic_read(&uv_nmi_cpus_in_nmi), cpu);
console_loglevel = uv_nmi_loglevel;
@@ -874,7 +877,7 @@ static inline int uv_nmi_kdb_reason(void)
static inline int uv_nmi_kdb_reason(void)
{
/* Ensure user is expecting to attach gdb remote */
- if (uv_nmi_action_is("kgdb"))
+ if (uv_nmi_action == nmi_act_kgdb)
return 0;
pr_err("UV: NMI error: KDB is not enabled in this kernel\n");
@@ -950,28 +953,35 @@ static int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
master = (atomic_read(&uv_nmi_cpu) == cpu);
/* If NMI action is "kdump", then attempt to do it */
- if (uv_nmi_action_is("kdump")) {
+ if (uv_nmi_action == nmi_act_kdump) {
uv_nmi_kdump(cpu, master, regs);
/* Unexpected return, revert action to "dump" */
if (master)
- strscpy(uv_nmi_action, "dump", sizeof(uv_nmi_action));
+ uv_nmi_action = nmi_act_dump;
}
/* Pause as all CPU's enter the NMI handler */
uv_nmi_wait(master);
/* Process actions other than "kdump": */
- if (uv_nmi_action_is("health")) {
+ switch (uv_nmi_action) {
+ case nmi_act_health:
uv_nmi_action_health(cpu, regs, master);
- } else if (uv_nmi_action_is("ips") || uv_nmi_action_is("dump")) {
+ break;
+ case nmi_act_ips:
+ case nmi_act_dump:
uv_nmi_dump_state(cpu, regs, master);
- } else if (uv_nmi_action_is("kdb") || uv_nmi_action_is("kgdb")) {
+ break;
+ case nmi_act_kdb:
+ case nmi_act_kgdb:
uv_call_kgdb_kdb(cpu, regs, master);
- } else {
+ break;
+ default:
if (master)
- pr_alert("UV: unknown NMI action: %s\n", uv_nmi_action);
+ pr_alert("UV: unknown NMI action: %d\n", uv_nmi_action);
uv_nmi_sync_exit(master);
+ break;
}
/* Clear per_cpu "in_nmi" flag */
diff --git a/arch/x86/platform/uv/uv_time.c b/arch/x86/platform/uv/uv_time.c
index 54663f3e00cb..ff5afc8a5a41 100644
--- a/arch/x86/platform/uv/uv_time.c
+++ b/arch/x86/platform/uv/uv_time.c
@@ -53,7 +53,7 @@ struct uv_rtc_timer_head {
struct {
int lcpu; /* systemwide logical cpu number */
u64 expires; /* next timer expiration for this cpu */
- } cpu[];
+ } cpu[] __counted_by(ncpus);
};
/*
diff --git a/arch/x86/um/vdso/Makefile b/arch/x86/um/vdso/Makefile
index 6825e146a62f..b86d634730b2 100644
--- a/arch/x86/um/vdso/Makefile
+++ b/arch/x86/um/vdso/Makefile
@@ -67,15 +67,3 @@ quiet_cmd_vdso = VDSO $@
VDSO_LDFLAGS = -fPIC -shared -Wl,--hash-style=sysv -z noexecstack
GCOV_PROFILE := n
-
-#
-# Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
-#
-quiet_cmd_vdso_install = INSTALL $@
- cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
-$(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE
- @mkdir -p $(MODLIB)/vdso
- $(call cmd,vdso_install)
-
-PHONY += vdso_install $(vdso-install-y)
-vdso_install: $(vdso-install-y)
diff --git a/arch/x86/video/fbdev.c b/arch/x86/video/fbdev.c
index 49a0452402e9..1dd6528cc947 100644
--- a/arch/x86/video/fbdev.c
+++ b/arch/x86/video/fbdev.c
@@ -13,16 +13,17 @@
#include <linux/vgaarb.h>
#include <asm/fb.h>
-void fb_pgprotect(struct file *file, struct vm_area_struct *vma, unsigned long off)
+pgprot_t pgprot_framebuffer(pgprot_t prot,
+ unsigned long vm_start, unsigned long vm_end,
+ unsigned long offset)
{
- unsigned long prot;
-
- prot = pgprot_val(vma->vm_page_prot) & ~_PAGE_CACHE_MASK;
+ pgprot_val(prot) &= ~_PAGE_CACHE_MASK;
if (boot_cpu_data.x86 > 3)
- pgprot_val(vma->vm_page_prot) =
- prot | cachemode2protval(_PAGE_CACHE_MODE_UC_MINUS);
+ pgprot_val(prot) |= cachemode2protval(_PAGE_CACHE_MODE_UC_MINUS);
+
+ return prot;
}
-EXPORT_SYMBOL(fb_pgprotect);
+EXPORT_SYMBOL(pgprot_framebuffer);
int fb_is_primary_device(struct fb_info *info)
{
diff --git a/arch/ia64/kernel/.gitignore b/arch/x86/virt/Makefile
index 0374827206e7..1e36502cd738 100644
--- a/arch/ia64/kernel/.gitignore
+++ b/arch/x86/virt/Makefile
@@ -1,3 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
-gate.lds
-vmlinux.lds
+obj-y += vmx/
diff --git a/arch/x86/virt/vmx/Makefile b/arch/x86/virt/vmx/Makefile
new file mode 100644
index 000000000000..feebda21d793
--- /dev/null
+++ b/arch/x86/virt/vmx/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_INTEL_TDX_HOST) += tdx/
diff --git a/arch/x86/virt/vmx/tdx/Makefile b/arch/x86/virt/vmx/tdx/Makefile
new file mode 100644
index 000000000000..46ef8f73aebb
--- /dev/null
+++ b/arch/x86/virt/vmx/tdx/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += seamcall.o
diff --git a/arch/x86/virt/vmx/tdx/seamcall.S b/arch/x86/virt/vmx/tdx/seamcall.S
new file mode 100644
index 000000000000..5b1f2286aea9
--- /dev/null
+++ b/arch/x86/virt/vmx/tdx/seamcall.S
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/linkage.h>
+#include <asm/frame.h>
+
+#include "tdxcall.S"
+
+/*
+ * __seamcall() - Host-side interface functions to SEAM software
+ * (the P-SEAMLDR or the TDX module).
+ *
+ * __seamcall() function ABI:
+ *
+ * @fn (RDI) - SEAMCALL Leaf number, moved to RAX
+ * @args (RSI) - struct tdx_module_args for input
+ *
+ * Only RCX/RDX/R8-R11 are used as input registers.
+ *
+ * Return (via RAX) TDX_SEAMCALL_VMFAILINVALID if the SEAMCALL itself
+ * fails, or the completion status of the SEAMCALL leaf function.
+ */
+SYM_FUNC_START(__seamcall)
+ TDX_MODULE_CALL host=1
+SYM_FUNC_END(__seamcall)
+
+/*
+ * __seamcall_ret() - Host-side interface functions to SEAM software
+ * (the P-SEAMLDR or the TDX module), with saving output registers to
+ * the 'struct tdx_module_args' used as input.
+ *
+ * __seamcall_ret() function ABI:
+ *
+ * @fn (RDI) - SEAMCALL Leaf number, moved to RAX
+ * @args (RSI) - struct tdx_module_args for input and output
+ *
+ * Only RCX/RDX/R8-R11 are used as input/output registers.
+ *
+ * Return (via RAX) TDX_SEAMCALL_VMFAILINVALID if the SEAMCALL itself
+ * fails, or the completion status of the SEAMCALL leaf function.
+ */
+SYM_FUNC_START(__seamcall_ret)
+ TDX_MODULE_CALL host=1 ret=1
+SYM_FUNC_END(__seamcall_ret)
+
+/*
+ * __seamcall_saved_ret() - Host-side interface functions to SEAM software
+ * (the P-SEAMLDR or the TDX module), with saving output registers to the
+ * 'struct tdx_module_args' used as input.
+ *
+ * __seamcall_saved_ret() function ABI:
+ *
+ * @fn (RDI) - SEAMCALL Leaf number, moved to RAX
+ * @args (RSI) - struct tdx_module_args for input and output
+ *
+ * All registers in @args are used as input/output registers.
+ *
+ * Return (via RAX) TDX_SEAMCALL_VMFAILINVALID if the SEAMCALL itself
+ * fails, or the completion status of the SEAMCALL leaf function.
+ */
+SYM_FUNC_START(__seamcall_saved_ret)
+ TDX_MODULE_CALL host=1 ret=1 saved=1
+SYM_FUNC_END(__seamcall_saved_ret)
diff --git a/arch/x86/virt/vmx/tdx/tdxcall.S b/arch/x86/virt/vmx/tdx/tdxcall.S
index 49a54356ae99..016a2a1ec1d6 100644
--- a/arch/x86/virt/vmx/tdx/tdxcall.S
+++ b/arch/x86/virt/vmx/tdx/tdxcall.S
@@ -1,5 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <asm/asm-offsets.h>
+#include <asm/frame.h>
+#include <asm/asm.h>
#include <asm/tdx.h>
/*
@@ -16,35 +18,75 @@
* TDX module and hypercalls to the VMM.
* SEAMCALL - used by TDX hosts to make requests to the
* TDX module.
+ *
+ *-------------------------------------------------------------------------
+ * TDCALL/SEAMCALL ABI:
+ *-------------------------------------------------------------------------
+ * Input Registers:
+ *
+ * RAX - TDCALL/SEAMCALL Leaf number.
+ * RCX,RDX,RDI,RSI,RBX,R8-R15 - TDCALL/SEAMCALL Leaf specific input registers.
+ *
+ * Output Registers:
+ *
+ * RAX - TDCALL/SEAMCALL instruction error code.
+ * RCX,RDX,RDI,RSI,RBX,R8-R15 - TDCALL/SEAMCALL Leaf specific output registers.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * So while the common core (RAX,RCX,RDX,R8-R11) fits nicely in the
+ * callee-clobbered registers and even leaves RDI,RSI free to act as a
+ * base pointer, some leafs (e.g., VP.ENTER) make a giant mess of things.
+ *
+ * For simplicity, assume that anything that needs the callee-saved regs
+ * also tramples on RDI,RSI. This isn't strictly true, see for example
+ * TDH.EXPORT.MEM.
*/
-.macro TDX_MODULE_CALL host:req
- /*
- * R12 will be used as temporary storage for struct tdx_module_output
- * pointer. Since R12-R15 registers are not used by TDCALL/SEAMCALL
- * services supported by this function, it can be reused.
- */
+.macro TDX_MODULE_CALL host:req ret=0 saved=0
+ FRAME_BEGIN
- /* Callee saved, so preserve it */
- push %r12
+ /* Move Leaf ID to RAX */
+ mov %rdi, %rax
+
+ /* Move other input regs from 'struct tdx_module_args' */
+ movq TDX_MODULE_rcx(%rsi), %rcx
+ movq TDX_MODULE_rdx(%rsi), %rdx
+ movq TDX_MODULE_r8(%rsi), %r8
+ movq TDX_MODULE_r9(%rsi), %r9
+ movq TDX_MODULE_r10(%rsi), %r10
+ movq TDX_MODULE_r11(%rsi), %r11
+.if \saved
/*
- * Push output pointer to stack.
- * After the operation, it will be fetched into R12 register.
+ * Move additional input regs from the structure. For simplicity
+ * assume that anything needs the callee-saved regs also tramples
+ * on RDI/RSI (see VP.ENTER).
*/
- push %r9
+ /* Save those callee-saved GPRs as mandated by the x86_64 ABI */
+ pushq %rbx
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
- /* Mangle function call ABI into TDCALL/SEAMCALL ABI: */
- /* Move Leaf ID to RAX */
- mov %rdi, %rax
- /* Move input 4 to R9 */
- mov %r8, %r9
- /* Move input 3 to R8 */
- mov %rcx, %r8
- /* Move input 1 to RCX */
- mov %rsi, %rcx
- /* Leave input param 2 in RDX */
-
- .if \host
+ movq TDX_MODULE_r12(%rsi), %r12
+ movq TDX_MODULE_r13(%rsi), %r13
+ movq TDX_MODULE_r14(%rsi), %r14
+ movq TDX_MODULE_r15(%rsi), %r15
+ movq TDX_MODULE_rbx(%rsi), %rbx
+
+.if \ret
+ /* Save the structure pointer as RSI is about to be clobbered */
+ pushq %rsi
+.endif
+
+ movq TDX_MODULE_rdi(%rsi), %rdi
+ /* RSI needs to be done at last */
+ movq TDX_MODULE_rsi(%rsi), %rsi
+.endif /* \saved */
+
+.if \host
+.Lseamcall\@:
seamcall
/*
* SEAMCALL instruction is essentially a VMExit from VMX root
@@ -57,40 +99,122 @@
* This value will never be used as actual SEAMCALL error code as
* it is from the Reserved status code class.
*/
- jnc .Lno_vmfailinvalid
- mov $TDX_SEAMCALL_VMFAILINVALID, %rax
-.Lno_vmfailinvalid:
-
- .else
+ jc .Lseamcall_vmfailinvalid\@
+.else
tdcall
- .endif
+.endif
+.if \ret
+.if \saved
/*
- * Fetch output pointer from stack to R12 (It is used
- * as temporary storage)
+ * Restore the structure from stack to save the output registers
+ *
+ * In case of VP.ENTER returns due to TDVMCALL, all registers are
+ * valid thus no register can be used as spare to restore the
+ * structure from the stack (see "TDH.VP.ENTER Output Operands
+ * Definition on TDCALL(TDG.VP.VMCALL) Following a TD Entry").
+ * For this case, need to make one register as spare by saving it
+ * to the stack and then manually load the structure pointer to
+ * the spare register.
+ *
+ * Note for other TDCALLs/SEAMCALLs there are spare registers
+ * thus no need for such hack but just use this for all.
*/
- pop %r12
+ pushq %rax /* save the TDCALL/SEAMCALL return code */
+ movq 8(%rsp), %rax /* restore the structure pointer */
+ movq %rsi, TDX_MODULE_rsi(%rax) /* save RSI */
+ popq %rax /* restore the return code */
+ popq %rsi /* pop the structure pointer */
+
+ /* Copy additional output regs to the structure */
+ movq %r12, TDX_MODULE_r12(%rsi)
+ movq %r13, TDX_MODULE_r13(%rsi)
+ movq %r14, TDX_MODULE_r14(%rsi)
+ movq %r15, TDX_MODULE_r15(%rsi)
+ movq %rbx, TDX_MODULE_rbx(%rsi)
+ movq %rdi, TDX_MODULE_rdi(%rsi)
+.endif /* \saved */
+ /* Copy output registers to the structure */
+ movq %rcx, TDX_MODULE_rcx(%rsi)
+ movq %rdx, TDX_MODULE_rdx(%rsi)
+ movq %r8, TDX_MODULE_r8(%rsi)
+ movq %r9, TDX_MODULE_r9(%rsi)
+ movq %r10, TDX_MODULE_r10(%rsi)
+ movq %r11, TDX_MODULE_r11(%rsi)
+.endif /* \ret */
+
+.if \saved && \ret
/*
- * Since this macro can be invoked with NULL as an output pointer,
- * check if caller provided an output struct before storing output
- * registers.
+ * Clear registers shared by guest for VP.VMCALL/VP.ENTER to prevent
+ * speculative use of guest's/VMM's values, including those are
+ * restored from the stack.
+ *
+ * See arch/x86/kvm/vmx/vmenter.S:
*
- * Update output registers, even if the call failed (RAX != 0).
- * Other registers may contain details of the failure.
+ * In theory, a L1 cache miss when restoring register from stack
+ * could lead to speculative execution with guest's values.
+ *
+ * Note: RBP/RSP are not used as shared register. RSI has been
+ * restored already.
+ *
+ * XOR is cheap, thus unconditionally do for all leafs.
*/
- test %r12, %r12
- jz .Lno_output_struct
-
- /* Copy result registers to output struct: */
- movq %rcx, TDX_MODULE_rcx(%r12)
- movq %rdx, TDX_MODULE_rdx(%r12)
- movq %r8, TDX_MODULE_r8(%r12)
- movq %r9, TDX_MODULE_r9(%r12)
- movq %r10, TDX_MODULE_r10(%r12)
- movq %r11, TDX_MODULE_r11(%r12)
-
-.Lno_output_struct:
- /* Restore the state of R12 register */
- pop %r12
+ xorl %ecx, %ecx
+ xorl %edx, %edx
+ xorl %r8d, %r8d
+ xorl %r9d, %r9d
+ xorl %r10d, %r10d
+ xorl %r11d, %r11d
+ xorl %r12d, %r12d
+ xorl %r13d, %r13d
+ xorl %r14d, %r14d
+ xorl %r15d, %r15d
+ xorl %ebx, %ebx
+ xorl %edi, %edi
+.endif /* \ret && \host */
+
+.if \host
+.Lout\@:
+.endif
+
+.if \saved
+ /* Restore callee-saved GPRs as mandated by the x86_64 ABI */
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %rbx
+.endif /* \saved */
+
+ FRAME_END
+ RET
+
+.if \host
+.Lseamcall_vmfailinvalid\@:
+ mov $TDX_SEAMCALL_VMFAILINVALID, %rax
+ jmp .Lseamcall_fail\@
+
+.Lseamcall_trap\@:
+ /*
+ * SEAMCALL caused #GP or #UD. By reaching here RAX contains
+ * the trap number. Convert the trap number to the TDX error
+ * code by setting TDX_SW_ERROR to the high 32-bits of RAX.
+ *
+ * Note cannot OR TDX_SW_ERROR directly to RAX as OR instruction
+ * only accepts 32-bit immediate at most.
+ */
+ movq $TDX_SW_ERROR, %rdi
+ orq %rdi, %rax
+
+.Lseamcall_fail\@:
+.if \ret && \saved
+ /* pop the unused structure pointer back to RSI */
+ popq %rsi
+.endif
+ jmp .Lout\@
+
+ _ASM_EXTABLE_FAULT(.Lseamcall\@, .Lseamcall_trap\@)
+.endif /* \host */
+
.endm
diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c
index 7ad91225fdf4..9dd5490b3318 100644
--- a/arch/x86/xen/apic.c
+++ b/arch/x86/xen/apic.c
@@ -33,13 +33,13 @@ static unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
return 0xfd;
}
-static u32 xen_set_apic_id(unsigned int x)
+static u32 xen_set_apic_id(u32 x)
{
WARN_ON(1);
return x;
}
-static unsigned int xen_get_apic_id(unsigned long x)
+static u32 xen_get_apic_id(u32 x)
{
return ((x)>>24) & 0xFFu;
}
@@ -110,15 +110,15 @@ static int xen_madt_oem_check(char *oem_id, char *oem_table_id)
return xen_pv_domain();
}
-static int xen_phys_pkg_id(int initial_apic_id, int index_msb)
+static u32 xen_phys_pkg_id(u32 initial_apic_id, int index_msb)
{
return initial_apic_id >> index_msb;
}
-static int xen_cpu_present_to_apicid(int cpu)
+static u32 xen_cpu_present_to_apicid(int cpu)
{
if (cpu_present(cpu))
- return cpu_data(cpu).apicid;
+ return cpu_data(cpu).topo.apicid;
else
return BAD_APICID;
}
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 0337392a3121..3c61bb98c10e 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -33,9 +33,12 @@ EXPORT_SYMBOL_GPL(hypercall_page);
* and xen_vcpu_setup for details. By default it points to share_info->vcpu_info
* but during boot it is switched to point to xen_vcpu_info.
* The pointer is used in xen_evtchn_do_upcall to acknowledge pending events.
+ * Make sure that xen_vcpu_info doesn't cross a page boundary by making it
+ * cache-line aligned (the struct is guaranteed to have a size of 64 bytes,
+ * which matches the cache line size of 64-bit x86 processors).
*/
DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
-DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
+DEFINE_PER_CPU_ALIGNED(struct vcpu_info, xen_vcpu_info);
/* Linux <-> Xen vCPU id mapping */
DEFINE_PER_CPU(uint32_t, xen_vcpu_id);
@@ -160,6 +163,7 @@ void xen_vcpu_setup(int cpu)
int err;
struct vcpu_info *vcpup;
+ BUILD_BUG_ON(sizeof(*vcpup) > SMP_CACHE_BYTES);
BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
/*
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index bbbfdd495ebd..aeb33e0a3f76 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -704,7 +704,7 @@ static struct trap_array_entry trap_array[] = {
TRAP_ENTRY(exc_int3, false ),
TRAP_ENTRY(exc_overflow, false ),
#ifdef CONFIG_IA32_EMULATION
- { entry_INT80_compat, xen_entry_INT80_compat, false },
+ TRAP_ENTRY(int80_emulation, false ),
#endif
TRAP_ENTRY(exc_page_fault, false ),
TRAP_ENTRY(exc_divide_error, false ),
diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S
index 9e5e68008785..1a9cd18dfbd3 100644
--- a/arch/x86/xen/xen-asm.S
+++ b/arch/x86/xen/xen-asm.S
@@ -156,7 +156,7 @@ xen_pv_trap asm_xenpv_exc_machine_check
#endif /* CONFIG_X86_MCE */
xen_pv_trap asm_exc_simd_coprocessor_error
#ifdef CONFIG_IA32_EMULATION
-xen_pv_trap entry_INT80_compat
+xen_pv_trap asm_int80_emulation
#endif
xen_pv_trap asm_exc_xen_unknown_trap
xen_pv_trap asm_exc_xen_hypervisor_callback
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 408a2aa66c69..a87ab36889e7 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -21,7 +21,7 @@ extern void *xen_initial_gdt;
struct trap_info;
void xen_copy_trap_info(struct trap_info *traps);
-DECLARE_PER_CPU(struct vcpu_info, xen_vcpu_info);
+DECLARE_PER_CPU_ALIGNED(struct vcpu_info, xen_vcpu_info);
DECLARE_PER_CPU(unsigned long, xen_cr3);
DECLARE_PER_CPU(unsigned long, xen_current_cr3);
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 52d6e4870a04..bdec4a773af0 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -19,7 +19,6 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
-#include <linux/screen_info.h>
#include <linux/kernel.h>
#include <linux/percpu.h>
#include <linux/reboot.h>
@@ -49,17 +48,6 @@
#include <asm/timex.h>
#include <asm/traps.h>
-#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
-struct screen_info screen_info = {
- .orig_x = 0,
- .orig_y = 24,
- .orig_video_cols = 80,
- .orig_video_lines = 24,
- .orig_video_isVGA = 1,
- .orig_video_points = 16,
-};
-#endif
-
#ifdef CONFIG_BLK_DEV_INITRD
extern unsigned long initrd_start;
extern unsigned long initrd_end;
diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl
index fc1a4f3c81d9..06eefa9c1458 100644
--- a/arch/xtensa/kernel/syscalls/syscall.tbl
+++ b/arch/xtensa/kernel/syscalls/syscall.tbl
@@ -273,7 +273,7 @@
252 common timer_getoverrun sys_timer_getoverrun
# System
253 common reserved253 sys_ni_syscall
-254 common lookup_dcookie sys_lookup_dcookie
+254 common lookup_dcookie sys_ni_syscall
255 common available255 sys_ni_syscall
256 common add_key sys_add_key
257 common request_key sys_request_key
@@ -423,3 +423,7 @@
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
451 common cachestat sys_cachestat
452 common fchmodat2 sys_fchmodat2
+453 common map_shadow_stack sys_map_shadow_stack
+454 common futex_wake sys_futex_wake
+455 common futex_wait sys_futex_wait
+456 common futex_requeue sys_futex_requeue
diff --git a/block/Kconfig b/block/Kconfig
index f1364d1c0d93..55ae2286a4de 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -186,6 +186,7 @@ config BLK_SED_OPAL
bool "Logic for interfacing with Opal enabled SEDs"
depends on KEYS
select PSERIES_PLPKS if PPC_PSERIES
+ select PSERIES_PLPKS_SED if PPC_PSERIES
help
Builds Logic for interfacing with Opal enabled controllers.
Enabling this option enables users to setup/unlock/lock
diff --git a/block/badblocks.c b/block/badblocks.c
index 3afb550c0f7b..fc92d4e18aa3 100644
--- a/block/badblocks.c
+++ b/block/badblocks.c
@@ -16,119 +16,830 @@
#include <linux/types.h>
#include <linux/slab.h>
-/**
- * badblocks_check() - check a given range for bad sectors
- * @bb: the badblocks structure that holds all badblock information
- * @s: sector (start) at which to check for badblocks
- * @sectors: number of sectors to check for badblocks
- * @first_bad: pointer to store location of the first badblock
- * @bad_sectors: pointer to store number of badblocks after @first_bad
+/*
+ * The purpose of badblocks set/clear is to manage bad blocks ranges which are
+ * identified by LBA addresses.
*
- * We can record which blocks on each device are 'bad' and so just
- * fail those blocks, or that stripe, rather than the whole device.
- * Entries in the bad-block table are 64bits wide. This comprises:
- * Length of bad-range, in sectors: 0-511 for lengths 1-512
- * Start of bad-range, sector offset, 54 bits (allows 8 exbibytes)
- * A 'shift' can be set so that larger blocks are tracked and
- * consequently larger devices can be covered.
- * 'Acknowledged' flag - 1 bit. - the most significant bit.
+ * When the caller of badblocks_set() wants to set a range of bad blocks, the
+ * setting range can be acked or unacked. And the setting range may merge,
+ * overwrite, skip the overlapped already set range, depends on who they are
+ * overlapped or adjacent, and the acknowledgment type of the ranges. It can be
+ * more complicated when the setting range covers multiple already set bad block
+ * ranges, with restrictions of maximum length of each bad range and the bad
+ * table space limitation.
*
- * Locking of the bad-block table uses a seqlock so badblocks_check
- * might need to retry if it is very unlucky.
- * We will sometimes want to check for bad blocks in a bi_end_io function,
- * so we use the write_seqlock_irq variant.
+ * It is difficult and unnecessary to take care of all the possible situations,
+ * for setting a large range of bad blocks, we can handle it by dividing the
+ * large range into smaller ones when encounter overlap, max range length or
+ * bad table full conditions. Every time only a smaller piece of the bad range
+ * is handled with a limited number of conditions how it is interacted with
+ * possible overlapped or adjacent already set bad block ranges. Then the hard
+ * complicated problem can be much simpler to handle in proper way.
*
- * When looking for a bad block we specify a range and want to
- * know if any block in the range is bad. So we binary-search
- * to the last range that starts at-or-before the given endpoint,
- * (or "before the sector after the target range")
- * then see if it ends after the given start.
+ * When setting a range of bad blocks to the bad table, the simplified situations
+ * to be considered are, (The already set bad blocks ranges are naming with
+ * prefix E, and the setting bad blocks range is naming with prefix S)
*
- * Return:
- * 0: there are no known bad blocks in the range
- * 1: there are known bad block which are all acknowledged
- * -1: there are bad blocks which have not yet been acknowledged in metadata.
- * plus the start/length of the first bad section we overlap.
+ * 1) A setting range is not overlapped or adjacent to any other already set bad
+ * block range.
+ * +--------+
+ * | S |
+ * +--------+
+ * +-------------+ +-------------+
+ * | E1 | | E2 |
+ * +-------------+ +-------------+
+ * For this situation if the bad blocks table is not full, just allocate a
+ * free slot from the bad blocks table to mark the setting range S. The
+ * result is,
+ * +-------------+ +--------+ +-------------+
+ * | E1 | | S | | E2 |
+ * +-------------+ +--------+ +-------------+
+ * 2) A setting range starts exactly at a start LBA of an already set bad blocks
+ * range.
+ * 2.1) The setting range size < already set range size
+ * +--------+
+ * | S |
+ * +--------+
+ * +-------------+
+ * | E |
+ * +-------------+
+ * 2.1.1) If S and E are both acked or unacked range, the setting range S can
+ * be merged into existing bad range E. The result is,
+ * +-------------+
+ * | S |
+ * +-------------+
+ * 2.1.2) If S is unacked setting and E is acked, the setting will be denied, and
+ * the result is,
+ * +-------------+
+ * | E |
+ * +-------------+
+ * 2.1.3) If S is acked setting and E is unacked, range S can overwrite on E.
+ * An extra slot from the bad blocks table will be allocated for S, and head
+ * of E will move to end of the inserted range S. The result is,
+ * +--------+----+
+ * | S | E |
+ * +--------+----+
+ * 2.2) The setting range size == already set range size
+ * 2.2.1) If S and E are both acked or unacked range, the setting range S can
+ * be merged into existing bad range E. The result is,
+ * +-------------+
+ * | S |
+ * +-------------+
+ * 2.2.2) If S is unacked setting and E is acked, the setting will be denied, and
+ * the result is,
+ * +-------------+
+ * | E |
+ * +-------------+
+ * 2.2.3) If S is acked setting and E is unacked, range S can overwrite all of
+ bad blocks range E. The result is,
+ * +-------------+
+ * | S |
+ * +-------------+
+ * 2.3) The setting range size > already set range size
+ * +-------------------+
+ * | S |
+ * +-------------------+
+ * +-------------+
+ * | E |
+ * +-------------+
+ * For such situation, the setting range S can be treated as two parts, the
+ * first part (S1) is as same size as the already set range E, the second
+ * part (S2) is the rest of setting range.
+ * +-------------+-----+ +-------------+ +-----+
+ * | S1 | S2 | | S1 | | S2 |
+ * +-------------+-----+ ===> +-------------+ +-----+
+ * +-------------+ +-------------+
+ * | E | | E |
+ * +-------------+ +-------------+
+ * Now we only focus on how to handle the setting range S1 and already set
+ * range E, which are already explained in 2.2), for the rest S2 it will be
+ * handled later in next loop.
+ * 3) A setting range starts before the start LBA of an already set bad blocks
+ * range.
+ * +-------------+
+ * | S |
+ * +-------------+
+ * +-------------+
+ * | E |
+ * +-------------+
+ * For this situation, the setting range S can be divided into two parts, the
+ * first (S1) ends at the start LBA of already set range E, the second part
+ * (S2) starts exactly at a start LBA of the already set range E.
+ * +----+---------+ +----+ +---------+
+ * | S1 | S2 | | S1 | | S2 |
+ * +----+---------+ ===> +----+ +---------+
+ * +-------------+ +-------------+
+ * | E | | E |
+ * +-------------+ +-------------+
+ * Now only the first part S1 should be handled in this loop, which is in
+ * similar condition as 1). The rest part S2 has exact same start LBA address
+ * of the already set range E, they will be handled in next loop in one of
+ * situations in 2).
+ * 4) A setting range starts after the start LBA of an already set bad blocks
+ * range.
+ * 4.1) If the setting range S exactly matches the tail part of already set bad
+ * blocks range E, like the following chart shows,
+ * +---------+
+ * | S |
+ * +---------+
+ * +-------------+
+ * | E |
+ * +-------------+
+ * 4.1.1) If range S and E have same acknowledge value (both acked or unacked),
+ * they will be merged into one, the result is,
+ * +-------------+
+ * | S |
+ * +-------------+
+ * 4.1.2) If range E is acked and the setting range S is unacked, the setting
+ * request of S will be rejected, the result is,
+ * +-------------+
+ * | E |
+ * +-------------+
+ * 4.1.3) If range E is unacked, and the setting range S is acked, then S may
+ * overwrite the overlapped range of E, the result is,
+ * +---+---------+
+ * | E | S |
+ * +---+---------+
+ * 4.2) If the setting range S stays in middle of an already set range E, like
+ * the following chart shows,
+ * +----+
+ * | S |
+ * +----+
+ * +--------------+
+ * | E |
+ * +--------------+
+ * 4.2.1) If range S and E have same acknowledge value (both acked or unacked),
+ * they will be merged into one, the result is,
+ * +--------------+
+ * | S |
+ * +--------------+
+ * 4.2.2) If range E is acked and the setting range S is unacked, the setting
+ * request of S will be rejected, the result is also,
+ * +--------------+
+ * | E |
+ * +--------------+
+ * 4.2.3) If range E is unacked, and the setting range S is acked, then S will
+ * inserted into middle of E and split previous range E into two parts (E1
+ * and E2), the result is,
+ * +----+----+----+
+ * | E1 | S | E2 |
+ * +----+----+----+
+ * 4.3) If the setting bad blocks range S is overlapped with an already set bad
+ * blocks range E. The range S starts after the start LBA of range E, and
+ * ends after the end LBA of range E, as the following chart shows,
+ * +-------------------+
+ * | S |
+ * +-------------------+
+ * +-------------+
+ * | E |
+ * +-------------+
+ * For this situation the range S can be divided into two parts, the first
+ * part (S1) ends at end range E, and the second part (S2) has rest range of
+ * origin S.
+ * +---------+---------+ +---------+ +---------+
+ * | S1 | S2 | | S1 | | S2 |
+ * +---------+---------+ ===> +---------+ +---------+
+ * +-------------+ +-------------+
+ * | E | | E |
+ * +-------------+ +-------------+
+ * Now in this loop the setting range S1 and already set range E can be
+ * handled as the situations 4.1), the rest range S2 will be handled in next
+ * loop and ignored in this loop.
+ * 5) A setting bad blocks range S is adjacent to one or more already set bad
+ * blocks range(s), and they are all acked or unacked range.
+ * 5.1) Front merge: If the already set bad blocks range E is before setting
+ * range S and they are adjacent,
+ * +------+
+ * | S |
+ * +------+
+ * +-------+
+ * | E |
+ * +-------+
+ * 5.1.1) When total size of range S and E <= BB_MAX_LEN, and their acknowledge
+ * values are same, the setting range S can front merges into range E. The
+ * result is,
+ * +--------------+
+ * | S |
+ * +--------------+
+ * 5.1.2) Otherwise these two ranges cannot merge, just insert the setting
+ * range S right after already set range E into the bad blocks table. The
+ * result is,
+ * +--------+------+
+ * | E | S |
+ * +--------+------+
+ * 6) Special cases which above conditions cannot handle
+ * 6.1) Multiple already set ranges may merge into less ones in a full bad table
+ * +-------------------------------------------------------+
+ * | S |
+ * +-------------------------------------------------------+
+ * |<----- BB_MAX_LEN ----->|
+ * +-----+ +-----+ +-----+
+ * | E1 | | E2 | | E3 |
+ * +-----+ +-----+ +-----+
+ * In the above example, when the bad blocks table is full, inserting the
+ * first part of setting range S will fail because no more available slot
+ * can be allocated from bad blocks table. In this situation a proper
+ * setting method should be go though all the setting bad blocks range and
+ * look for chance to merge already set ranges into less ones. When there
+ * is available slot from bad blocks table, re-try again to handle more
+ * setting bad blocks ranges as many as possible.
+ * +------------------------+
+ * | S3 |
+ * +------------------------+
+ * |<----- BB_MAX_LEN ----->|
+ * +-----+-----+-----+---+-----+--+
+ * | S1 | S2 |
+ * +-----+-----+-----+---+-----+--+
+ * The above chart shows although the first part (S3) cannot be inserted due
+ * to no-space in bad blocks table, but the following E1, E2 and E3 ranges
+ * can be merged with rest part of S into less range S1 and S2. Now there is
+ * 1 free slot in bad blocks table.
+ * +------------------------+-----+-----+-----+---+-----+--+
+ * | S3 | S1 | S2 |
+ * +------------------------+-----+-----+-----+---+-----+--+
+ * Since the bad blocks table is not full anymore, re-try again for the
+ * origin setting range S. Now the setting range S3 can be inserted into the
+ * bad blocks table with previous freed slot from multiple ranges merge.
+ * 6.2) Front merge after overwrite
+ * In the following example, in bad blocks table, E1 is an acked bad blocks
+ * range and E2 is an unacked bad blocks range, therefore they are not able
+ * to merge into a larger range. The setting bad blocks range S is acked,
+ * therefore part of E2 can be overwritten by S.
+ * +--------+
+ * | S | acknowledged
+ * +--------+ S: 1
+ * +-------+-------------+ E1: 1
+ * | E1 | E2 | E2: 0
+ * +-------+-------------+
+ * With previous simplified routines, after overwriting part of E2 with S,
+ * the bad blocks table should be (E3 is remaining part of E2 which is not
+ * overwritten by S),
+ * acknowledged
+ * +-------+--------+----+ S: 1
+ * | E1 | S | E3 | E1: 1
+ * +-------+--------+----+ E3: 0
+ * The above result is correct but not perfect. Range E1 and S in the bad
+ * blocks table are all acked, merging them into a larger one range may
+ * occupy less bad blocks table space and make badblocks_check() faster.
+ * Therefore in such situation, after overwriting range S, the previous range
+ * E1 should be checked for possible front combination. Then the ideal
+ * result can be,
+ * +----------------+----+ acknowledged
+ * | E1 | E3 | E1: 1
+ * +----------------+----+ E3: 0
+ * 6.3) Behind merge: If the already set bad blocks range E is behind the setting
+ * range S and they are adjacent. Normally we don't need to care about this
+ * because front merge handles this while going though range S from head to
+ * tail, except for the tail part of range S. When the setting range S are
+ * fully handled, all the above simplified routine doesn't check whether the
+ * tail LBA of range S is adjacent to the next already set range and not
+ * merge them even it is possible.
+ * +------+
+ * | S |
+ * +------+
+ * +-------+
+ * | E |
+ * +-------+
+ * For the above special situation, when the setting range S are all handled
+ * and the loop ends, an extra check is necessary for whether next already
+ * set range E is right after S and mergeable.
+ * 6.3.1) When total size of range E and S <= BB_MAX_LEN, and their acknowledge
+ * values are same, the setting range S can behind merges into range E. The
+ * result is,
+ * +--------------+
+ * | S |
+ * +--------------+
+ * 6.3.2) Otherwise these two ranges cannot merge, just insert the setting range
+ * S in front of the already set range E in the bad blocks table. The result
+ * is,
+ * +------+-------+
+ * | S | E |
+ * +------+-------+
+ *
+ * All the above 5 simplified situations and 3 special cases may cover 99%+ of
+ * the bad block range setting conditions. Maybe there is some rare corner case
+ * is not considered and optimized, it won't hurt if badblocks_set() fails due
+ * to no space, or some ranges are not merged to save bad blocks table space.
+ *
+ * Inside badblocks_set() each loop starts by jumping to re_insert label, every
+ * time for the new loop prev_badblocks() is called to find an already set range
+ * which starts before or at current setting range. Since the setting bad blocks
+ * range is handled from head to tail, most of the cases it is unnecessary to do
+ * the binary search inside prev_badblocks(), it is possible to provide a hint
+ * to prev_badblocks() for a fast path, then the expensive binary search can be
+ * avoided. In my test with the hint to prev_badblocks(), except for the first
+ * loop, all rested calls to prev_badblocks() can go into the fast path and
+ * return correct bad blocks table index immediately.
+ *
+ *
+ * Clearing a bad blocks range from the bad block table has similar idea as
+ * setting does, but much more simpler. The only thing needs to be noticed is
+ * when the clearing range hits middle of a bad block range, the existing bad
+ * block range will split into two, and one more item should be added into the
+ * bad block table. The simplified situations to be considered are, (The already
+ * set bad blocks ranges in bad block table are naming with prefix E, and the
+ * clearing bad blocks range is naming with prefix C)
+ *
+ * 1) A clearing range is not overlapped to any already set ranges in bad block
+ * table.
+ * +-----+ | +-----+ | +-----+
+ * | C | | | C | | | C |
+ * +-----+ or +-----+ or +-----+
+ * +---+ | +----+ +----+ | +---+
+ * | E | | | E1 | | E2 | | | E |
+ * +---+ | +----+ +----+ | +---+
+ * For the above situations, no bad block to be cleared and no failure
+ * happens, simply returns 0.
+ * 2) The clearing range hits middle of an already setting bad blocks range in
+ * the bad block table.
+ * +---+
+ * | C |
+ * +---+
+ * +-----------------+
+ * | E |
+ * +-----------------+
+ * In this situation if the bad block table is not full, the range E will be
+ * split into two ranges E1 and E2. The result is,
+ * +------+ +------+
+ * | E1 | | E2 |
+ * +------+ +------+
+ * 3) The clearing range starts exactly at same LBA as an already set bad block range
+ * from the bad block table.
+ * 3.1) Partially covered at head part
+ * +------------+
+ * | C |
+ * +------------+
+ * +-----------------+
+ * | E |
+ * +-----------------+
+ * For this situation, the overlapped already set range will update the
+ * start LBA to end of C and shrink the range to BB_LEN(E) - BB_LEN(C). No
+ * item deleted from bad block table. The result is,
+ * +----+
+ * | E1 |
+ * +----+
+ * 3.2) Exact fully covered
+ * +-----------------+
+ * | C |
+ * +-----------------+
+ * +-----------------+
+ * | E |
+ * +-----------------+
+ * For this situation the whole bad blocks range E will be cleared and its
+ * corresponded item is deleted from the bad block table.
+ * 4) The clearing range exactly ends at same LBA as an already set bad block
+ * range.
+ * +-------+
+ * | C |
+ * +-------+
+ * +-----------------+
+ * | E |
+ * +-----------------+
+ * For the above situation, the already set range E is updated to shrink its
+ * end to the start of C, and reduce its length to BB_LEN(E) - BB_LEN(C).
+ * The result is,
+ * +---------+
+ * | E |
+ * +---------+
+ * 5) The clearing range is partially overlapped with an already set bad block
+ * range from the bad block table.
+ * 5.1) The already set bad block range is front overlapped with the clearing
+ * range.
+ * +----------+
+ * | C |
+ * +----------+
+ * +------------+
+ * | E |
+ * +------------+
+ * For such situation, the clearing range C can be treated as two parts. The
+ * first part ends at the start LBA of range E, and the second part starts at
+ * same LBA of range E.
+ * +----+-----+ +----+ +-----+
+ * | C1 | C2 | | C1 | | C2 |
+ * +----+-----+ ===> +----+ +-----+
+ * +------------+ +------------+
+ * | E | | E |
+ * +------------+ +------------+
+ * Now the first part C1 can be handled as condition 1), and the second part C2 can be
+ * handled as condition 3.1) in next loop.
+ * 5.2) The already set bad block range is behind overlaopped with the clearing
+ * range.
+ * +----------+
+ * | C |
+ * +----------+
+ * +------------+
+ * | E |
+ * +------------+
+ * For such situation, the clearing range C can be treated as two parts. The
+ * first part C1 ends at same end LBA of range E, and the second part starts
+ * at end LBA of range E.
+ * +----+-----+ +----+ +-----+
+ * | C1 | C2 | | C1 | | C2 |
+ * +----+-----+ ===> +----+ +-----+
+ * +------------+ +------------+
+ * | E | | E |
+ * +------------+ +------------+
+ * Now the first part clearing range C1 can be handled as condition 4), and
+ * the second part clearing range C2 can be handled as condition 1) in next
+ * loop.
+ *
+ * All bad blocks range clearing can be simplified into the above 5 situations
+ * by only handling the head part of the clearing range in each run of the
+ * while-loop. The idea is similar to bad blocks range setting but much
+ * simpler.
*/
-int badblocks_check(struct badblocks *bb, sector_t s, int sectors,
- sector_t *first_bad, int *bad_sectors)
+
+/*
+ * Find the range starts at-or-before 's' from bad table. The search
+ * starts from index 'hint' and stops at index 'hint_end' from the bad
+ * table.
+ */
+static int prev_by_hint(struct badblocks *bb, sector_t s, int hint)
{
- int hi;
- int lo;
+ int hint_end = hint + 2;
u64 *p = bb->page;
- int rv;
- sector_t target = s + sectors;
- unsigned seq;
+ int ret = -1;
- if (bb->shift > 0) {
- /* round the start down, and the end up */
- s >>= bb->shift;
- target += (1<<bb->shift) - 1;
- target >>= bb->shift;
+ while ((hint < hint_end) && ((hint + 1) <= bb->count) &&
+ (BB_OFFSET(p[hint]) <= s)) {
+ if ((hint + 1) == bb->count || BB_OFFSET(p[hint + 1]) > s) {
+ ret = hint;
+ break;
+ }
+ hint++;
+ }
+
+ return ret;
+}
+
+/*
+ * Find the range starts at-or-before bad->start. If 'hint' is provided
+ * (hint >= 0) then search in the bad table from hint firstly. It is
+ * very probably the wanted bad range can be found from the hint index,
+ * then the unnecessary while-loop iteration can be avoided.
+ */
+static int prev_badblocks(struct badblocks *bb, struct badblocks_context *bad,
+ int hint)
+{
+ sector_t s = bad->start;
+ int ret = -1;
+ int lo, hi;
+ u64 *p;
+
+ if (!bb->count)
+ goto out;
+
+ if (hint >= 0) {
+ ret = prev_by_hint(bb, s, hint);
+ if (ret >= 0)
+ goto out;
}
- /* 'target' is now the first block after the bad range */
-retry:
- seq = read_seqbegin(&bb->lock);
lo = 0;
- rv = 0;
hi = bb->count;
+ p = bb->page;
- /* Binary search between lo and hi for 'target'
- * i.e. for the last range that starts before 'target'
- */
- /* INVARIANT: ranges before 'lo' and at-or-after 'hi'
- * are known not to be the last range before target.
- * VARIANT: hi-lo is the number of possible
- * ranges, and decreases until it reaches 1
- */
+ /* The following bisect search might be unnecessary */
+ if (BB_OFFSET(p[lo]) > s)
+ return -1;
+ if (BB_OFFSET(p[hi - 1]) <= s)
+ return hi - 1;
+
+ /* Do bisect search in bad table */
while (hi - lo > 1) {
- int mid = (lo + hi) / 2;
+ int mid = (lo + hi)/2;
sector_t a = BB_OFFSET(p[mid]);
- if (a < target)
- /* This could still be the one, earlier ranges
- * could not.
- */
+ if (a == s) {
+ ret = mid;
+ goto out;
+ }
+
+ if (a < s)
lo = mid;
else
- /* This and later ranges are definitely out. */
hi = mid;
}
- /* 'lo' might be the last that started before target, but 'hi' isn't */
- if (hi > lo) {
- /* need to check all range that end after 's' to see if
- * any are unacknowledged.
+
+ if (BB_OFFSET(p[lo]) <= s)
+ ret = lo;
+out:
+ return ret;
+}
+
+/*
+ * Return 'true' if the range indicated by 'bad' can be backward merged
+ * with the bad range (from the bad table) index by 'behind'.
+ */
+static bool can_merge_behind(struct badblocks *bb,
+ struct badblocks_context *bad, int behind)
+{
+ sector_t sectors = bad->len;
+ sector_t s = bad->start;
+ u64 *p = bb->page;
+
+ if ((s < BB_OFFSET(p[behind])) &&
+ ((s + sectors) >= BB_OFFSET(p[behind])) &&
+ ((BB_END(p[behind]) - s) <= BB_MAX_LEN) &&
+ BB_ACK(p[behind]) == bad->ack)
+ return true;
+ return false;
+}
+
+/*
+ * Do backward merge for range indicated by 'bad' and the bad range
+ * (from the bad table) indexed by 'behind'. The return value is merged
+ * sectors from bad->len.
+ */
+static int behind_merge(struct badblocks *bb, struct badblocks_context *bad,
+ int behind)
+{
+ sector_t sectors = bad->len;
+ sector_t s = bad->start;
+ u64 *p = bb->page;
+ int merged = 0;
+
+ WARN_ON(s >= BB_OFFSET(p[behind]));
+ WARN_ON((s + sectors) < BB_OFFSET(p[behind]));
+
+ if (s < BB_OFFSET(p[behind])) {
+ merged = BB_OFFSET(p[behind]) - s;
+ p[behind] = BB_MAKE(s, BB_LEN(p[behind]) + merged, bad->ack);
+
+ WARN_ON((BB_LEN(p[behind]) + merged) >= BB_MAX_LEN);
+ }
+
+ return merged;
+}
+
+/*
+ * Return 'true' if the range indicated by 'bad' can be forward
+ * merged with the bad range (from the bad table) indexed by 'prev'.
+ */
+static bool can_merge_front(struct badblocks *bb, int prev,
+ struct badblocks_context *bad)
+{
+ sector_t s = bad->start;
+ u64 *p = bb->page;
+
+ if (BB_ACK(p[prev]) == bad->ack &&
+ (s < BB_END(p[prev]) ||
+ (s == BB_END(p[prev]) && (BB_LEN(p[prev]) < BB_MAX_LEN))))
+ return true;
+ return false;
+}
+
+/*
+ * Do forward merge for range indicated by 'bad' and the bad range
+ * (from bad table) indexed by 'prev'. The return value is sectors
+ * merged from bad->len.
+ */
+static int front_merge(struct badblocks *bb, int prev, struct badblocks_context *bad)
+{
+ sector_t sectors = bad->len;
+ sector_t s = bad->start;
+ u64 *p = bb->page;
+ int merged = 0;
+
+ WARN_ON(s > BB_END(p[prev]));
+
+ if (s < BB_END(p[prev])) {
+ merged = min_t(sector_t, sectors, BB_END(p[prev]) - s);
+ } else {
+ merged = min_t(sector_t, sectors, BB_MAX_LEN - BB_LEN(p[prev]));
+ if ((prev + 1) < bb->count &&
+ merged > (BB_OFFSET(p[prev + 1]) - BB_END(p[prev]))) {
+ merged = BB_OFFSET(p[prev + 1]) - BB_END(p[prev]);
+ }
+
+ p[prev] = BB_MAKE(BB_OFFSET(p[prev]),
+ BB_LEN(p[prev]) + merged, bad->ack);
+ }
+
+ return merged;
+}
+
+/*
+ * 'Combine' is a special case which can_merge_front() is not able to
+ * handle: If a bad range (indexed by 'prev' from bad table) exactly
+ * starts as bad->start, and the bad range ahead of 'prev' (indexed by
+ * 'prev - 1' from bad table) exactly ends at where 'prev' starts, and
+ * the sum of their lengths does not exceed BB_MAX_LEN limitation, then
+ * these two bad range (from bad table) can be combined.
+ *
+ * Return 'true' if bad ranges indexed by 'prev' and 'prev - 1' from bad
+ * table can be combined.
+ */
+static bool can_combine_front(struct badblocks *bb, int prev,
+ struct badblocks_context *bad)
+{
+ u64 *p = bb->page;
+
+ if ((prev > 0) &&
+ (BB_OFFSET(p[prev]) == bad->start) &&
+ (BB_END(p[prev - 1]) == BB_OFFSET(p[prev])) &&
+ (BB_LEN(p[prev - 1]) + BB_LEN(p[prev]) <= BB_MAX_LEN) &&
+ (BB_ACK(p[prev - 1]) == BB_ACK(p[prev])))
+ return true;
+ return false;
+}
+
+/*
+ * Combine the bad ranges indexed by 'prev' and 'prev - 1' (from bad
+ * table) into one larger bad range, and the new range is indexed by
+ * 'prev - 1'.
+ * The caller of front_combine() will decrease bb->count, therefore
+ * it is unnecessary to clear p[perv] after front merge.
+ */
+static void front_combine(struct badblocks *bb, int prev)
+{
+ u64 *p = bb->page;
+
+ p[prev - 1] = BB_MAKE(BB_OFFSET(p[prev - 1]),
+ BB_LEN(p[prev - 1]) + BB_LEN(p[prev]),
+ BB_ACK(p[prev]));
+ if ((prev + 1) < bb->count)
+ memmove(p + prev, p + prev + 1, (bb->count - prev - 1) * 8);
+}
+
+/*
+ * Return 'true' if the range indicated by 'bad' is exactly forward
+ * overlapped with the bad range (from bad table) indexed by 'front'.
+ * Exactly forward overlap means the bad range (from bad table) indexed
+ * by 'prev' does not cover the whole range indicated by 'bad'.
+ */
+static bool overlap_front(struct badblocks *bb, int front,
+ struct badblocks_context *bad)
+{
+ u64 *p = bb->page;
+
+ if (bad->start >= BB_OFFSET(p[front]) &&
+ bad->start < BB_END(p[front]))
+ return true;
+ return false;
+}
+
+/*
+ * Return 'true' if the range indicated by 'bad' is exactly backward
+ * overlapped with the bad range (from bad table) indexed by 'behind'.
+ */
+static bool overlap_behind(struct badblocks *bb, struct badblocks_context *bad,
+ int behind)
+{
+ u64 *p = bb->page;
+
+ if (bad->start < BB_OFFSET(p[behind]) &&
+ (bad->start + bad->len) > BB_OFFSET(p[behind]))
+ return true;
+ return false;
+}
+
+/*
+ * Return 'true' if the range indicated by 'bad' can overwrite the bad
+ * range (from bad table) indexed by 'prev'.
+ *
+ * The range indicated by 'bad' can overwrite the bad range indexed by
+ * 'prev' when,
+ * 1) The whole range indicated by 'bad' can cover partial or whole bad
+ * range (from bad table) indexed by 'prev'.
+ * 2) The ack value of 'bad' is larger or equal to the ack value of bad
+ * range 'prev'.
+ *
+ * If the overwriting doesn't cover the whole bad range (from bad table)
+ * indexed by 'prev', new range might be split from existing bad range,
+ * 1) The overwrite covers head or tail part of existing bad range, 1
+ * extra bad range will be split and added into the bad table.
+ * 2) The overwrite covers middle of existing bad range, 2 extra bad
+ * ranges will be split (ahead and after the overwritten range) and
+ * added into the bad table.
+ * The number of extra split ranges of the overwriting is stored in
+ * 'extra' and returned for the caller.
+ */
+static bool can_front_overwrite(struct badblocks *bb, int prev,
+ struct badblocks_context *bad, int *extra)
+{
+ u64 *p = bb->page;
+ int len;
+
+ WARN_ON(!overlap_front(bb, prev, bad));
+
+ if (BB_ACK(p[prev]) >= bad->ack)
+ return false;
+
+ if (BB_END(p[prev]) <= (bad->start + bad->len)) {
+ len = BB_END(p[prev]) - bad->start;
+ if (BB_OFFSET(p[prev]) == bad->start)
+ *extra = 0;
+ else
+ *extra = 1;
+
+ bad->len = len;
+ } else {
+ if (BB_OFFSET(p[prev]) == bad->start)
+ *extra = 1;
+ else
+ /*
+ * prev range will be split into two, beside the overwritten
+ * one, an extra slot needed from bad table.
*/
- while (lo >= 0 &&
- BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > s) {
- if (BB_OFFSET(p[lo]) < target) {
- /* starts before the end, and finishes after
- * the start, so they must overlap
- */
- if (rv != -1 && BB_ACK(p[lo]))
- rv = 1;
- else
- rv = -1;
- *first_bad = BB_OFFSET(p[lo]);
- *bad_sectors = BB_LEN(p[lo]);
- }
- lo--;
+ *extra = 2;
+ }
+
+ if ((bb->count + (*extra)) >= MAX_BADBLOCKS)
+ return false;
+
+ return true;
+}
+
+/*
+ * Do the overwrite from the range indicated by 'bad' to the bad range
+ * (from bad table) indexed by 'prev'.
+ * The previously called can_front_overwrite() will provide how many
+ * extra bad range(s) might be split and added into the bad table. All
+ * the splitting cases in the bad table will be handled here.
+ */
+static int front_overwrite(struct badblocks *bb, int prev,
+ struct badblocks_context *bad, int extra)
+{
+ u64 *p = bb->page;
+ sector_t orig_end = BB_END(p[prev]);
+ int orig_ack = BB_ACK(p[prev]);
+
+ switch (extra) {
+ case 0:
+ p[prev] = BB_MAKE(BB_OFFSET(p[prev]), BB_LEN(p[prev]),
+ bad->ack);
+ break;
+ case 1:
+ if (BB_OFFSET(p[prev]) == bad->start) {
+ p[prev] = BB_MAKE(BB_OFFSET(p[prev]),
+ bad->len, bad->ack);
+ memmove(p + prev + 2, p + prev + 1,
+ (bb->count - prev - 1) * 8);
+ p[prev + 1] = BB_MAKE(bad->start + bad->len,
+ orig_end - BB_END(p[prev]),
+ orig_ack);
+ } else {
+ p[prev] = BB_MAKE(BB_OFFSET(p[prev]),
+ bad->start - BB_OFFSET(p[prev]),
+ orig_ack);
+ /*
+ * prev +2 -> prev + 1 + 1, which is for,
+ * 1) prev + 1: the slot index of the previous one
+ * 2) + 1: one more slot for extra being 1.
+ */
+ memmove(p + prev + 2, p + prev + 1,
+ (bb->count - prev - 1) * 8);
+ p[prev + 1] = BB_MAKE(bad->start, bad->len, bad->ack);
}
+ break;
+ case 2:
+ p[prev] = BB_MAKE(BB_OFFSET(p[prev]),
+ bad->start - BB_OFFSET(p[prev]),
+ orig_ack);
+ /*
+ * prev + 3 -> prev + 1 + 2, which is for,
+ * 1) prev + 1: the slot index of the previous one
+ * 2) + 2: two more slots for extra being 2.
+ */
+ memmove(p + prev + 3, p + prev + 1,
+ (bb->count - prev - 1) * 8);
+ p[prev + 1] = BB_MAKE(bad->start, bad->len, bad->ack);
+ p[prev + 2] = BB_MAKE(BB_END(p[prev + 1]),
+ orig_end - BB_END(p[prev + 1]),
+ orig_ack);
+ break;
+ default:
+ break;
}
- if (read_seqretry(&bb->lock, seq))
- goto retry;
+ return bad->len;
+}
- return rv;
+/*
+ * Explicitly insert a range indicated by 'bad' to the bad table, where
+ * the location is indexed by 'at'.
+ */
+static int insert_at(struct badblocks *bb, int at, struct badblocks_context *bad)
+{
+ u64 *p = bb->page;
+ int len;
+
+ WARN_ON(badblocks_full(bb));
+
+ len = min_t(sector_t, bad->len, BB_MAX_LEN);
+ if (at < bb->count)
+ memmove(p + at + 1, p + at, (bb->count - at) * 8);
+ p[at] = BB_MAKE(bad->start, len, bad->ack);
+
+ return len;
}
-EXPORT_SYMBOL_GPL(badblocks_check);
static void badblocks_update_acked(struct badblocks *bb)
{
+ bool unacked = false;
u64 *p = bb->page;
int i;
- bool unacked = false;
if (!bb->unacked_exist)
return;
@@ -144,281 +855,600 @@ static void badblocks_update_acked(struct badblocks *bb)
bb->unacked_exist = 0;
}
-/**
- * badblocks_set() - Add a range of bad blocks to the table.
- * @bb: the badblocks structure that holds all badblock information
- * @s: first sector to mark as bad
- * @sectors: number of sectors to mark as bad
- * @acknowledged: weather to mark the bad sectors as acknowledged
- *
- * This might extend the table, or might contract it if two adjacent ranges
- * can be merged. We binary-search to find the 'insertion' point, then
- * decide how best to handle it.
- *
- * Return:
- * 0: success
- * 1: failed to set badblocks (out of space)
- */
-int badblocks_set(struct badblocks *bb, sector_t s, int sectors,
- int acknowledged)
+/* Do exact work to set bad block range into the bad block table */
+static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors,
+ int acknowledged)
{
- u64 *p;
- int lo, hi;
- int rv = 0;
+ int retried = 0, space_desired = 0;
+ int orig_len, len = 0, added = 0;
+ struct badblocks_context bad;
+ int prev = -1, hint = -1;
+ sector_t orig_start;
unsigned long flags;
+ int rv = 0;
+ u64 *p;
if (bb->shift < 0)
/* badblocks are disabled */
return 1;
+ if (sectors == 0)
+ /* Invalid sectors number */
+ return 1;
+
if (bb->shift) {
/* round the start down, and the end up */
sector_t next = s + sectors;
- s >>= bb->shift;
- next += (1<<bb->shift) - 1;
- next >>= bb->shift;
+ rounddown(s, bb->shift);
+ roundup(next, bb->shift);
sectors = next - s;
}
write_seqlock_irqsave(&bb->lock, flags);
+ orig_start = s;
+ orig_len = sectors;
+ bad.ack = acknowledged;
p = bb->page;
- lo = 0;
- hi = bb->count;
- /* Find the last range that starts at-or-before 's' */
- while (hi - lo > 1) {
- int mid = (lo + hi) / 2;
- sector_t a = BB_OFFSET(p[mid]);
- if (a <= s)
- lo = mid;
- else
- hi = mid;
+re_insert:
+ bad.start = s;
+ bad.len = sectors;
+ len = 0;
+
+ if (badblocks_empty(bb)) {
+ len = insert_at(bb, 0, &bad);
+ bb->count++;
+ added++;
+ goto update_sectors;
}
- if (hi > lo && BB_OFFSET(p[lo]) > s)
- hi = lo;
- if (hi > lo) {
- /* we found a range that might merge with the start
- * of our new range
- */
- sector_t a = BB_OFFSET(p[lo]);
- sector_t e = a + BB_LEN(p[lo]);
- int ack = BB_ACK(p[lo]);
-
- if (e >= s) {
- /* Yes, we can merge with a previous range */
- if (s == a && s + sectors >= e)
- /* new range covers old */
- ack = acknowledged;
- else
- ack = ack && acknowledged;
-
- if (e < s + sectors)
- e = s + sectors;
- if (e - a <= BB_MAX_LEN) {
- p[lo] = BB_MAKE(a, e-a, ack);
- s = e;
+ prev = prev_badblocks(bb, &bad, hint);
+
+ /* start before all badblocks */
+ if (prev < 0) {
+ if (!badblocks_full(bb)) {
+ /* insert on the first */
+ if (bad.len > (BB_OFFSET(p[0]) - bad.start))
+ bad.len = BB_OFFSET(p[0]) - bad.start;
+ len = insert_at(bb, 0, &bad);
+ bb->count++;
+ added++;
+ hint = 0;
+ goto update_sectors;
+ }
+
+ /* No sapce, try to merge */
+ if (overlap_behind(bb, &bad, 0)) {
+ if (can_merge_behind(bb, &bad, 0)) {
+ len = behind_merge(bb, &bad, 0);
+ added++;
} else {
- /* does not all fit in one range,
- * make p[lo] maximal
- */
- if (BB_LEN(p[lo]) != BB_MAX_LEN)
- p[lo] = BB_MAKE(a, BB_MAX_LEN, ack);
- s = a + BB_MAX_LEN;
+ len = BB_OFFSET(p[0]) - s;
+ space_desired = 1;
}
- sectors = e - s;
+ hint = 0;
+ goto update_sectors;
}
+
+ /* no table space and give up */
+ goto out;
}
- if (sectors && hi < bb->count) {
- /* 'hi' points to the first range that starts after 's'.
- * Maybe we can merge with the start of that range
- */
- sector_t a = BB_OFFSET(p[hi]);
- sector_t e = a + BB_LEN(p[hi]);
- int ack = BB_ACK(p[hi]);
-
- if (a <= s + sectors) {
- /* merging is possible */
- if (e <= s + sectors) {
- /* full overlap */
- e = s + sectors;
- ack = acknowledged;
- } else
- ack = ack && acknowledged;
-
- a = s;
- if (e - a <= BB_MAX_LEN) {
- p[hi] = BB_MAKE(a, e-a, ack);
- s = e;
- } else {
- p[hi] = BB_MAKE(a, BB_MAX_LEN, ack);
- s = a + BB_MAX_LEN;
+
+ /* in case p[prev-1] can be merged with p[prev] */
+ if (can_combine_front(bb, prev, &bad)) {
+ front_combine(bb, prev);
+ bb->count--;
+ added++;
+ hint = prev;
+ goto update_sectors;
+ }
+
+ if (overlap_front(bb, prev, &bad)) {
+ if (can_merge_front(bb, prev, &bad)) {
+ len = front_merge(bb, prev, &bad);
+ added++;
+ } else {
+ int extra = 0;
+
+ if (!can_front_overwrite(bb, prev, &bad, &extra)) {
+ len = min_t(sector_t,
+ BB_END(p[prev]) - s, sectors);
+ hint = prev;
+ goto update_sectors;
+ }
+
+ len = front_overwrite(bb, prev, &bad, extra);
+ added++;
+ bb->count += extra;
+
+ if (can_combine_front(bb, prev, &bad)) {
+ front_combine(bb, prev);
+ bb->count--;
}
- sectors = e - s;
- lo = hi;
- hi++;
}
+ hint = prev;
+ goto update_sectors;
+ }
+
+ if (can_merge_front(bb, prev, &bad)) {
+ len = front_merge(bb, prev, &bad);
+ added++;
+ hint = prev;
+ goto update_sectors;
}
- if (sectors == 0 && hi < bb->count) {
- /* we might be able to combine lo and hi */
- /* Note: 's' is at the end of 'lo' */
- sector_t a = BB_OFFSET(p[hi]);
- int lolen = BB_LEN(p[lo]);
- int hilen = BB_LEN(p[hi]);
- int newlen = lolen + hilen - (s - a);
-
- if (s >= a && newlen < BB_MAX_LEN) {
- /* yes, we can combine them */
- int ack = BB_ACK(p[lo]) && BB_ACK(p[hi]);
-
- p[lo] = BB_MAKE(BB_OFFSET(p[lo]), newlen, ack);
- memmove(p + hi, p + hi + 1,
- (bb->count - hi - 1) * 8);
- bb->count--;
+
+ /* if no space in table, still try to merge in the covered range */
+ if (badblocks_full(bb)) {
+ /* skip the cannot-merge range */
+ if (((prev + 1) < bb->count) &&
+ overlap_behind(bb, &bad, prev + 1) &&
+ ((s + sectors) >= BB_END(p[prev + 1]))) {
+ len = BB_END(p[prev + 1]) - s;
+ hint = prev + 1;
+ goto update_sectors;
}
+
+ /* no retry any more */
+ len = sectors;
+ space_desired = 1;
+ hint = -1;
+ goto update_sectors;
}
- while (sectors) {
- /* didn't merge (it all).
- * Need to add a range just before 'hi'
- */
- if (bb->count >= MAX_BADBLOCKS) {
- /* No room for more */
- rv = 1;
- break;
- } else {
- int this_sectors = sectors;
- memmove(p + hi + 1, p + hi,
- (bb->count - hi) * 8);
- bb->count++;
+ /* cannot merge and there is space in bad table */
+ if ((prev + 1) < bb->count &&
+ overlap_behind(bb, &bad, prev + 1))
+ bad.len = min_t(sector_t,
+ bad.len, BB_OFFSET(p[prev + 1]) - bad.start);
- if (this_sectors > BB_MAX_LEN)
- this_sectors = BB_MAX_LEN;
- p[hi] = BB_MAKE(s, this_sectors, acknowledged);
- sectors -= this_sectors;
- s += this_sectors;
- }
+ len = insert_at(bb, prev + 1, &bad);
+ bb->count++;
+ added++;
+ hint = prev + 1;
+
+update_sectors:
+ s += len;
+ sectors -= len;
+
+ if (sectors > 0)
+ goto re_insert;
+
+ WARN_ON(sectors < 0);
+
+ /*
+ * Check whether the following already set range can be
+ * merged. (prev < 0) condition is not handled here,
+ * because it's already complicated enough.
+ */
+ if (prev >= 0 &&
+ (prev + 1) < bb->count &&
+ BB_END(p[prev]) == BB_OFFSET(p[prev + 1]) &&
+ (BB_LEN(p[prev]) + BB_LEN(p[prev + 1])) <= BB_MAX_LEN &&
+ BB_ACK(p[prev]) == BB_ACK(p[prev + 1])) {
+ p[prev] = BB_MAKE(BB_OFFSET(p[prev]),
+ BB_LEN(p[prev]) + BB_LEN(p[prev + 1]),
+ BB_ACK(p[prev]));
+
+ if ((prev + 2) < bb->count)
+ memmove(p + prev + 1, p + prev + 2,
+ (bb->count - (prev + 2)) * 8);
+ bb->count--;
+ }
+
+ if (space_desired && !badblocks_full(bb)) {
+ s = orig_start;
+ sectors = orig_len;
+ space_desired = 0;
+ if (retried++ < 3)
+ goto re_insert;
+ }
+
+out:
+ if (added) {
+ set_changed(bb);
+
+ if (!acknowledged)
+ bb->unacked_exist = 1;
+ else
+ badblocks_update_acked(bb);
}
- bb->changed = 1;
- if (!acknowledged)
- bb->unacked_exist = 1;
- else
- badblocks_update_acked(bb);
write_sequnlock_irqrestore(&bb->lock, flags);
+ if (!added)
+ rv = 1;
+
return rv;
}
-EXPORT_SYMBOL_GPL(badblocks_set);
-/**
- * badblocks_clear() - Remove a range of bad blocks to the table.
- * @bb: the badblocks structure that holds all badblock information
- * @s: first sector to mark as bad
- * @sectors: number of sectors to mark as bad
- *
- * This may involve extending the table if we spilt a region,
- * but it must not fail. So if the table becomes full, we just
- * drop the remove request.
- *
- * Return:
- * 0: success
- * 1: failed to clear badblocks
+/*
+ * Clear the bad block range from bad block table which is front overlapped
+ * with the clearing range. The return value is how many sectors from an
+ * already set bad block range are cleared. If the whole bad block range is
+ * covered by the clearing range and fully cleared, 'delete' is set as 1 for
+ * the caller to reduce bb->count.
*/
-int badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
+static int front_clear(struct badblocks *bb, int prev,
+ struct badblocks_context *bad, int *deleted)
{
- u64 *p;
- int lo, hi;
- sector_t target = s + sectors;
+ sector_t sectors = bad->len;
+ sector_t s = bad->start;
+ u64 *p = bb->page;
+ int cleared = 0;
+
+ *deleted = 0;
+ if (s == BB_OFFSET(p[prev])) {
+ if (BB_LEN(p[prev]) > sectors) {
+ p[prev] = BB_MAKE(BB_OFFSET(p[prev]) + sectors,
+ BB_LEN(p[prev]) - sectors,
+ BB_ACK(p[prev]));
+ cleared = sectors;
+ } else {
+ /* BB_LEN(p[prev]) <= sectors */
+ cleared = BB_LEN(p[prev]);
+ if ((prev + 1) < bb->count)
+ memmove(p + prev, p + prev + 1,
+ (bb->count - prev - 1) * 8);
+ *deleted = 1;
+ }
+ } else if (s > BB_OFFSET(p[prev])) {
+ if (BB_END(p[prev]) <= (s + sectors)) {
+ cleared = BB_END(p[prev]) - s;
+ p[prev] = BB_MAKE(BB_OFFSET(p[prev]),
+ s - BB_OFFSET(p[prev]),
+ BB_ACK(p[prev]));
+ } else {
+ /* Splitting is handled in front_splitting_clear() */
+ BUG();
+ }
+ }
+
+ return cleared;
+}
+
+/*
+ * Handle the condition that the clearing range hits middle of an already set
+ * bad block range from bad block table. In this condition the existing bad
+ * block range is split into two after the middle part is cleared.
+ */
+static int front_splitting_clear(struct badblocks *bb, int prev,
+ struct badblocks_context *bad)
+{
+ u64 *p = bb->page;
+ u64 end = BB_END(p[prev]);
+ int ack = BB_ACK(p[prev]);
+ sector_t sectors = bad->len;
+ sector_t s = bad->start;
+
+ p[prev] = BB_MAKE(BB_OFFSET(p[prev]),
+ s - BB_OFFSET(p[prev]),
+ ack);
+ memmove(p + prev + 2, p + prev + 1, (bb->count - prev - 1) * 8);
+ p[prev + 1] = BB_MAKE(s + sectors, end - s - sectors, ack);
+ return sectors;
+}
+
+/* Do the exact work to clear bad block range from the bad block table */
+static int _badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
+{
+ struct badblocks_context bad;
+ int prev = -1, hint = -1;
+ int len = 0, cleared = 0;
int rv = 0;
+ u64 *p;
+
+ if (bb->shift < 0)
+ /* badblocks are disabled */
+ return 1;
+
+ if (sectors == 0)
+ /* Invalid sectors number */
+ return 1;
+
+ if (bb->shift) {
+ sector_t target;
- if (bb->shift > 0) {
/* When clearing we round the start up and the end down.
* This should not matter as the shift should align with
* the block size and no rounding should ever be needed.
* However it is better the think a block is bad when it
* isn't than to think a block is not bad when it is.
*/
- s += (1<<bb->shift) - 1;
- s >>= bb->shift;
- target >>= bb->shift;
+ target = s + sectors;
+ roundup(s, bb->shift);
+ rounddown(target, bb->shift);
+ sectors = target - s;
}
write_seqlock_irq(&bb->lock);
+ bad.ack = true;
p = bb->page;
- lo = 0;
- hi = bb->count;
- /* Find the last range that starts before 'target' */
- while (hi - lo > 1) {
- int mid = (lo + hi) / 2;
- sector_t a = BB_OFFSET(p[mid]);
- if (a < target)
- lo = mid;
- else
- hi = mid;
+re_clear:
+ bad.start = s;
+ bad.len = sectors;
+
+ if (badblocks_empty(bb)) {
+ len = sectors;
+ cleared++;
+ goto update_sectors;
}
- if (hi > lo) {
- /* p[lo] is the last range that could overlap the
- * current range. Earlier ranges could also overlap,
- * but only this one can overlap the end of the range.
- */
- if ((BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > target) &&
- (BB_OFFSET(p[lo]) < target)) {
- /* Partial overlap, leave the tail of this range */
- int ack = BB_ACK(p[lo]);
- sector_t a = BB_OFFSET(p[lo]);
- sector_t end = a + BB_LEN(p[lo]);
-
- if (a < s) {
- /* we need to split this range */
- if (bb->count >= MAX_BADBLOCKS) {
- rv = -ENOSPC;
- goto out;
- }
- memmove(p+lo+1, p+lo, (bb->count - lo) * 8);
- bb->count++;
- p[lo] = BB_MAKE(a, s-a, ack);
- lo++;
- }
- p[lo] = BB_MAKE(target, end - target, ack);
- /* there is no longer an overlap */
- hi = lo;
- lo--;
- }
- while (lo >= 0 &&
- (BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > s) &&
- (BB_OFFSET(p[lo]) < target)) {
- /* This range does overlap */
- if (BB_OFFSET(p[lo]) < s) {
- /* Keep the early parts of this range. */
- int ack = BB_ACK(p[lo]);
- sector_t start = BB_OFFSET(p[lo]);
-
- p[lo] = BB_MAKE(start, s - start, ack);
- /* now low doesn't overlap, so.. */
- break;
- }
- lo--;
+
+
+ prev = prev_badblocks(bb, &bad, hint);
+
+ /* Start before all badblocks */
+ if (prev < 0) {
+ if (overlap_behind(bb, &bad, 0)) {
+ len = BB_OFFSET(p[0]) - s;
+ hint = 0;
+ } else {
+ len = sectors;
}
- /* 'lo' is strictly before, 'hi' is strictly after,
- * anything between needs to be discarded
+ /*
+ * Both situations are to clear non-bad range,
+ * should be treated as successful
*/
- if (hi - lo > 1) {
- memmove(p+lo+1, p+hi, (bb->count - hi) * 8);
- bb->count -= (hi - lo - 1);
+ cleared++;
+ goto update_sectors;
+ }
+
+ /* Start after all badblocks */
+ if ((prev + 1) >= bb->count && !overlap_front(bb, prev, &bad)) {
+ len = sectors;
+ cleared++;
+ goto update_sectors;
+ }
+
+ /* Clear will split a bad record but the table is full */
+ if (badblocks_full(bb) && (BB_OFFSET(p[prev]) < bad.start) &&
+ (BB_END(p[prev]) > (bad.start + sectors))) {
+ len = sectors;
+ goto update_sectors;
+ }
+
+ if (overlap_front(bb, prev, &bad)) {
+ if ((BB_OFFSET(p[prev]) < bad.start) &&
+ (BB_END(p[prev]) > (bad.start + bad.len))) {
+ /* Splitting */
+ if ((bb->count + 1) < MAX_BADBLOCKS) {
+ len = front_splitting_clear(bb, prev, &bad);
+ bb->count += 1;
+ cleared++;
+ } else {
+ /* No space to split, give up */
+ len = sectors;
+ }
+ } else {
+ int deleted = 0;
+
+ len = front_clear(bb, prev, &bad, &deleted);
+ bb->count -= deleted;
+ cleared++;
+ hint = prev;
}
+
+ goto update_sectors;
+ }
+
+ /* Not front overlap, but behind overlap */
+ if ((prev + 1) < bb->count && overlap_behind(bb, &bad, prev + 1)) {
+ len = BB_OFFSET(p[prev + 1]) - bad.start;
+ hint = prev + 1;
+ /* Clear non-bad range should be treated as successful */
+ cleared++;
+ goto update_sectors;
+ }
+
+ /* Not cover any badblocks range in the table */
+ len = sectors;
+ /* Clear non-bad range should be treated as successful */
+ cleared++;
+
+update_sectors:
+ s += len;
+ sectors -= len;
+
+ if (sectors > 0)
+ goto re_clear;
+
+ WARN_ON(sectors < 0);
+
+ if (cleared) {
+ badblocks_update_acked(bb);
+ set_changed(bb);
}
- badblocks_update_acked(bb);
- bb->changed = 1;
-out:
write_sequnlock_irq(&bb->lock);
+
+ if (!cleared)
+ rv = 1;
+
return rv;
}
+
+/* Do the exact work to check bad blocks range from the bad block table */
+static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
+ sector_t *first_bad, int *bad_sectors)
+{
+ int unacked_badblocks, acked_badblocks;
+ int prev = -1, hint = -1, set = 0;
+ struct badblocks_context bad;
+ unsigned int seq;
+ int len, rv;
+ u64 *p;
+
+ WARN_ON(bb->shift < 0 || sectors == 0);
+
+ if (bb->shift > 0) {
+ sector_t target;
+
+ /* round the start down, and the end up */
+ target = s + sectors;
+ rounddown(s, bb->shift);
+ roundup(target, bb->shift);
+ sectors = target - s;
+ }
+
+retry:
+ seq = read_seqbegin(&bb->lock);
+
+ p = bb->page;
+ unacked_badblocks = 0;
+ acked_badblocks = 0;
+
+re_check:
+ bad.start = s;
+ bad.len = sectors;
+
+ if (badblocks_empty(bb)) {
+ len = sectors;
+ goto update_sectors;
+ }
+
+ prev = prev_badblocks(bb, &bad, hint);
+
+ /* start after all badblocks */
+ if ((prev + 1) >= bb->count && !overlap_front(bb, prev, &bad)) {
+ len = sectors;
+ goto update_sectors;
+ }
+
+ if (overlap_front(bb, prev, &bad)) {
+ if (BB_ACK(p[prev]))
+ acked_badblocks++;
+ else
+ unacked_badblocks++;
+
+ if (BB_END(p[prev]) >= (s + sectors))
+ len = sectors;
+ else
+ len = BB_END(p[prev]) - s;
+
+ if (set == 0) {
+ *first_bad = BB_OFFSET(p[prev]);
+ *bad_sectors = BB_LEN(p[prev]);
+ set = 1;
+ }
+ goto update_sectors;
+ }
+
+ /* Not front overlap, but behind overlap */
+ if ((prev + 1) < bb->count && overlap_behind(bb, &bad, prev + 1)) {
+ len = BB_OFFSET(p[prev + 1]) - bad.start;
+ hint = prev + 1;
+ goto update_sectors;
+ }
+
+ /* not cover any badblocks range in the table */
+ len = sectors;
+
+update_sectors:
+ s += len;
+ sectors -= len;
+
+ if (sectors > 0)
+ goto re_check;
+
+ WARN_ON(sectors < 0);
+
+ if (unacked_badblocks > 0)
+ rv = -1;
+ else if (acked_badblocks > 0)
+ rv = 1;
+ else
+ rv = 0;
+
+ if (read_seqretry(&bb->lock, seq))
+ goto retry;
+
+ return rv;
+}
+
+/**
+ * badblocks_check() - check a given range for bad sectors
+ * @bb: the badblocks structure that holds all badblock information
+ * @s: sector (start) at which to check for badblocks
+ * @sectors: number of sectors to check for badblocks
+ * @first_bad: pointer to store location of the first badblock
+ * @bad_sectors: pointer to store number of badblocks after @first_bad
+ *
+ * We can record which blocks on each device are 'bad' and so just
+ * fail those blocks, or that stripe, rather than the whole device.
+ * Entries in the bad-block table are 64bits wide. This comprises:
+ * Length of bad-range, in sectors: 0-511 for lengths 1-512
+ * Start of bad-range, sector offset, 54 bits (allows 8 exbibytes)
+ * A 'shift' can be set so that larger blocks are tracked and
+ * consequently larger devices can be covered.
+ * 'Acknowledged' flag - 1 bit. - the most significant bit.
+ *
+ * Locking of the bad-block table uses a seqlock so badblocks_check
+ * might need to retry if it is very unlucky.
+ * We will sometimes want to check for bad blocks in a bi_end_io function,
+ * so we use the write_seqlock_irq variant.
+ *
+ * When looking for a bad block we specify a range and want to
+ * know if any block in the range is bad. So we binary-search
+ * to the last range that starts at-or-before the given endpoint,
+ * (or "before the sector after the target range")
+ * then see if it ends after the given start.
+ *
+ * Return:
+ * 0: there are no known bad blocks in the range
+ * 1: there are known bad block which are all acknowledged
+ * -1: there are bad blocks which have not yet been acknowledged in metadata.
+ * plus the start/length of the first bad section we overlap.
+ */
+int badblocks_check(struct badblocks *bb, sector_t s, int sectors,
+ sector_t *first_bad, int *bad_sectors)
+{
+ return _badblocks_check(bb, s, sectors, first_bad, bad_sectors);
+}
+EXPORT_SYMBOL_GPL(badblocks_check);
+
+/**
+ * badblocks_set() - Add a range of bad blocks to the table.
+ * @bb: the badblocks structure that holds all badblock information
+ * @s: first sector to mark as bad
+ * @sectors: number of sectors to mark as bad
+ * @acknowledged: weather to mark the bad sectors as acknowledged
+ *
+ * This might extend the table, or might contract it if two adjacent ranges
+ * can be merged. We binary-search to find the 'insertion' point, then
+ * decide how best to handle it.
+ *
+ * Return:
+ * 0: success
+ * 1: failed to set badblocks (out of space)
+ */
+int badblocks_set(struct badblocks *bb, sector_t s, int sectors,
+ int acknowledged)
+{
+ return _badblocks_set(bb, s, sectors, acknowledged);
+}
+EXPORT_SYMBOL_GPL(badblocks_set);
+
+/**
+ * badblocks_clear() - Remove a range of bad blocks to the table.
+ * @bb: the badblocks structure that holds all badblock information
+ * @s: first sector to mark as bad
+ * @sectors: number of sectors to mark as bad
+ *
+ * This may involve extending the table if we spilt a region,
+ * but it must not fail. So if the table becomes full, we just
+ * drop the remove request.
+ *
+ * Return:
+ * 0: success
+ * 1: failed to clear badblocks
+ */
+int badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
+{
+ return _badblocks_clear(bb, s, sectors);
+}
EXPORT_SYMBOL_GPL(badblocks_clear);
/**
diff --git a/block/bdev.c b/block/bdev.c
index f3b13aa1b7d4..750aec178b6a 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -292,7 +292,7 @@ EXPORT_SYMBOL(thaw_bdev);
*/
static __cacheline_aligned_in_smp DEFINE_MUTEX(bdev_lock);
-static struct kmem_cache * bdev_cachep __read_mostly;
+static struct kmem_cache *bdev_cachep __ro_after_init;
static struct inode *bdev_alloc_inode(struct super_block *sb)
{
@@ -361,13 +361,13 @@ static struct file_system_type bd_type = {
.kill_sb = kill_anon_super,
};
-struct super_block *blockdev_superblock __read_mostly;
+struct super_block *blockdev_superblock __ro_after_init;
EXPORT_SYMBOL_GPL(blockdev_superblock);
void __init bdev_cache_init(void)
{
int err;
- static struct vfsmount *bd_mnt;
+ static struct vfsmount *bd_mnt __ro_after_init;
bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),
0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
@@ -425,6 +425,8 @@ void bdev_set_nr_sectors(struct block_device *bdev, sector_t sectors)
void bdev_add(struct block_device *bdev, dev_t dev)
{
+ if (bdev_stable_writes(bdev))
+ mapping_set_stable_writes(bdev->bd_inode->i_mapping);
bdev->bd_dev = dev;
bdev->bd_inode->i_rdev = dev;
bdev->bd_inode->i_ino = dev;
@@ -829,6 +831,28 @@ put_blkdev:
}
EXPORT_SYMBOL(blkdev_get_by_dev);
+struct bdev_handle *bdev_open_by_dev(dev_t dev, blk_mode_t mode, void *holder,
+ const struct blk_holder_ops *hops)
+{
+ struct bdev_handle *handle = kmalloc(sizeof(*handle), GFP_KERNEL);
+ struct block_device *bdev;
+
+ if (!handle)
+ return ERR_PTR(-ENOMEM);
+ bdev = blkdev_get_by_dev(dev, mode, holder, hops);
+ if (IS_ERR(bdev)) {
+ kfree(handle);
+ return ERR_CAST(bdev);
+ }
+ handle->bdev = bdev;
+ handle->holder = holder;
+ if (holder)
+ mode |= BLK_OPEN_EXCL;
+ handle->mode = mode;
+ return handle;
+}
+EXPORT_SYMBOL(bdev_open_by_dev);
+
/**
* blkdev_get_by_path - open a block device by name
* @path: path to the block device to open
@@ -867,6 +891,28 @@ struct block_device *blkdev_get_by_path(const char *path, blk_mode_t mode,
}
EXPORT_SYMBOL(blkdev_get_by_path);
+struct bdev_handle *bdev_open_by_path(const char *path, blk_mode_t mode,
+ void *holder, const struct blk_holder_ops *hops)
+{
+ struct bdev_handle *handle;
+ dev_t dev;
+ int error;
+
+ error = lookup_bdev(path, &dev);
+ if (error)
+ return ERR_PTR(error);
+
+ handle = bdev_open_by_dev(dev, mode, holder, hops);
+ if (!IS_ERR(handle) && (mode & BLK_OPEN_WRITE) &&
+ bdev_read_only(handle->bdev)) {
+ bdev_release(handle);
+ return ERR_PTR(-EACCES);
+ }
+
+ return handle;
+}
+EXPORT_SYMBOL(bdev_open_by_path);
+
void blkdev_put(struct block_device *bdev, void *holder)
{
struct gendisk *disk = bdev->bd_disk;
@@ -903,6 +949,13 @@ void blkdev_put(struct block_device *bdev, void *holder)
}
EXPORT_SYMBOL(blkdev_put);
+void bdev_release(struct bdev_handle *handle)
+{
+ blkdev_put(handle->bdev, handle->holder);
+ kfree(handle);
+}
+EXPORT_SYMBOL(bdev_release);
+
/**
* lookup_bdev() - Look up a struct block_device by name.
* @pathname: Name of the block device in the filesystem.
@@ -961,20 +1014,20 @@ void bdev_mark_dead(struct block_device *bdev, bool surprise)
mutex_lock(&bdev->bd_holder_lock);
if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead)
bdev->bd_holder_ops->mark_dead(bdev, surprise);
- else
+ else {
+ mutex_unlock(&bdev->bd_holder_lock);
sync_blockdev(bdev);
- mutex_unlock(&bdev->bd_holder_lock);
+ }
invalidate_bdev(bdev);
}
-#ifdef CONFIG_DASD_MODULE
/*
- * Drivers should not use this directly, but the DASD driver has historically
- * had a shutdown to offline mode that doesn't actually remove the gendisk
- * that otherwise looks a lot like a safe device removal.
+ * New drivers should not use this directly. There are some drivers however
+ * that needs this for historical reasons. For example, the DASD driver has
+ * historically had a shutdown to offline mode that doesn't actually remove the
+ * gendisk that otherwise looks a lot like a safe device removal.
*/
EXPORT_SYMBOL_GPL(bdev_mark_dead);
-#endif
void sync_bdevs(bool wait)
{
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 4a42ea2972ad..4b48c2c44098 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -577,6 +577,7 @@ static void blkg_destroy_all(struct gendisk *disk)
struct request_queue *q = disk->queue;
struct blkcg_gq *blkg, *n;
int count = BLKG_DESTROY_BATCH_SIZE;
+ int i;
restart:
spin_lock_irq(&q->queue_lock);
@@ -602,6 +603,18 @@ restart:
}
}
+ /*
+ * Mark policy deactivated since policy offline has been done, and
+ * the free is scheduled, so future blkcg_deactivate_policy() can
+ * be bypassed
+ */
+ for (i = 0; i < BLKCG_MAX_POLS; i++) {
+ struct blkcg_policy *pol = blkcg_policy[i];
+
+ if (pol)
+ __clear_bit(pol->plid, q->blkcg_pols);
+ }
+
q->root_blkg = NULL;
spin_unlock_irq(&q->queue_lock);
}
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index 624c03c8fe64..fd482439afbc 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -249,8 +249,6 @@ static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg,
{
struct blkcg_gq *blkg;
- WARN_ON_ONCE(!rcu_read_lock_held());
-
if (blkcg == &blkcg_root)
return q->root_blkg;
diff --git a/block/blk-core.c b/block/blk-core.c
index 9d51e9894ece..2eca76ccf4ee 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -501,9 +501,17 @@ static inline void bio_check_ro(struct bio *bio)
if (op_is_write(bio_op(bio)) && bdev_read_only(bio->bi_bdev)) {
if (op_is_flush(bio->bi_opf) && !bio_sectors(bio))
return;
+
+ if (bio->bi_bdev->bd_ro_warned)
+ return;
+
+ bio->bi_bdev->bd_ro_warned = true;
+ /*
+ * Use ioctl to set underlying disk of raid/dm to read-only
+ * will trigger this.
+ */
pr_warn("Trying to write to read-only block-device %pg\n",
bio->bi_bdev);
- /* Older lvm-tools actually trigger this */
}
}
diff --git a/block/blk-flush.c b/block/blk-flush.c
index e73dc22d05c1..3f4d41952ef2 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -323,16 +323,9 @@ static void blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq,
flush_rq->mq_ctx = first_rq->mq_ctx;
flush_rq->mq_hctx = first_rq->mq_hctx;
- if (!q->elevator) {
+ if (!q->elevator)
flush_rq->tag = first_rq->tag;
-
- /*
- * We borrow data request's driver tag, so have to mark
- * this flush request as INFLIGHT for avoiding double
- * account of this driver tag
- */
- flush_rq->rq_flags |= RQF_MQ_INFLIGHT;
- } else
+ else
flush_rq->internal_tag = first_rq->internal_tag;
flush_rq->cmd_flags = REQ_OP_FLUSH | REQ_PREFLUSH;
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index c3b5930106b2..5cbeb9344f2f 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -246,7 +246,6 @@ static const char *const rqf_name[] = {
RQF_NAME(STARTED),
RQF_NAME(FLUSH_SEQ),
RQF_NAME(MIXED_MERGE),
- RQF_NAME(MQ_INFLIGHT),
RQF_NAME(DONTPREP),
RQF_NAME(SCHED_TAGS),
RQF_NAME(USE_SCHED),
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 1fafd54dce3c..ac18f802c027 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -426,6 +426,8 @@ __blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data)
rq_list_add(data->cached_rq, rq);
nr++;
}
+ if (!(data->rq_flags & RQF_SCHED_TAGS))
+ blk_mq_add_active_requests(data->hctx, nr);
/* caller already holds a reference, add for remainder */
percpu_ref_get_many(&data->q->q_usage_counter, nr - 1);
data->nr_tags -= nr;
@@ -510,6 +512,8 @@ retry:
goto retry;
}
+ if (!(data->rq_flags & RQF_SCHED_TAGS))
+ blk_mq_inc_active_requests(data->hctx);
rq = blk_mq_rq_ctx_init(data, blk_mq_tags_from_data(data), tag);
blk_mq_rq_time_init(rq, alloc_time_ns);
return rq;
@@ -669,6 +673,8 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q,
tag = blk_mq_get_tag(&data);
if (tag == BLK_MQ_NO_TAG)
goto out_queue_exit;
+ if (!(data.rq_flags & RQF_SCHED_TAGS))
+ blk_mq_inc_active_requests(data.hctx);
rq = blk_mq_rq_ctx_init(&data, blk_mq_tags_from_data(&data), tag);
blk_mq_rq_time_init(rq, alloc_time_ns);
rq->__data_len = 0;
@@ -708,11 +714,10 @@ static void __blk_mq_free_request(struct request *rq)
blk_pm_mark_last_busy(rq);
rq->mq_hctx = NULL;
- if (rq->rq_flags & RQF_MQ_INFLIGHT)
- __blk_mq_dec_active_requests(hctx);
-
- if (rq->tag != BLK_MQ_NO_TAG)
+ if (rq->tag != BLK_MQ_NO_TAG) {
+ blk_mq_dec_active_requests(hctx);
blk_mq_put_tag(hctx->tags, ctx, rq->tag);
+ }
if (sched_tag != BLK_MQ_NO_TAG)
blk_mq_put_tag(hctx->sched_tags, ctx, sched_tag);
blk_mq_sched_restart(hctx);
@@ -1061,12 +1066,7 @@ static inline void blk_mq_flush_tag_batch(struct blk_mq_hw_ctx *hctx,
{
struct request_queue *q = hctx->queue;
- /*
- * All requests should have been marked as RQF_MQ_INFLIGHT, so
- * update hctx->nr_active in batch
- */
- if (hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)
- __blk_mq_sub_active_requests(hctx, nr_tags);
+ blk_mq_sub_active_requests(hctx, nr_tags);
blk_mq_put_tags(hctx->tags, tag_array, nr_tags);
percpu_ref_put_many(&q->q_usage_counter, nr_tags);
@@ -1259,6 +1259,7 @@ void blk_mq_start_request(struct request *rq)
blk_add_timer(rq);
WRITE_ONCE(rq->state, MQ_RQ_IN_FLIGHT);
+ rq->mq_hctx->tags->rqs[rq->tag] = rq;
#ifdef CONFIG_BLK_DEV_INTEGRITY
if (blk_integrity_rq(rq) && req_op(rq) == REQ_OP_WRITE)
@@ -1511,14 +1512,26 @@ void blk_mq_delay_kick_requeue_list(struct request_queue *q,
}
EXPORT_SYMBOL(blk_mq_delay_kick_requeue_list);
+static bool blk_is_flush_data_rq(struct request *rq)
+{
+ return (rq->rq_flags & RQF_FLUSH_SEQ) && !is_flush_rq(rq);
+}
+
static bool blk_mq_rq_inflight(struct request *rq, void *priv)
{
/*
* If we find a request that isn't idle we know the queue is busy
* as it's checked in the iter.
* Return false to stop the iteration.
+ *
+ * In case of queue quiesce, if one flush data request is completed,
+ * don't count it as inflight given the flush sequence is suspended,
+ * and the original flush data request is invisible to driver, just
+ * like other pending requests because of quiesce
*/
- if (blk_mq_request_started(rq)) {
+ if (blk_mq_request_started(rq) && !(blk_queue_quiesced(rq->q) &&
+ blk_is_flush_data_rq(rq) &&
+ blk_mq_request_completed(rq))) {
bool *busy = priv;
*busy = true;
@@ -1748,7 +1761,7 @@ struct request *blk_mq_dequeue_from_ctx(struct blk_mq_hw_ctx *hctx,
return data.rq;
}
-static bool __blk_mq_alloc_driver_tag(struct request *rq)
+bool __blk_mq_alloc_driver_tag(struct request *rq)
{
struct sbitmap_queue *bt = &rq->mq_hctx->tags->bitmap_tags;
unsigned int tag_offset = rq->mq_hctx->tags->nr_reserved_tags;
@@ -1769,20 +1782,7 @@ static bool __blk_mq_alloc_driver_tag(struct request *rq)
return false;
rq->tag = tag + tag_offset;
- return true;
-}
-
-bool __blk_mq_get_driver_tag(struct blk_mq_hw_ctx *hctx, struct request *rq)
-{
- if (rq->tag == BLK_MQ_NO_TAG && !__blk_mq_alloc_driver_tag(rq))
- return false;
-
- if ((hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED) &&
- !(rq->rq_flags & RQF_MQ_INFLIGHT)) {
- rq->rq_flags |= RQF_MQ_INFLIGHT;
- __blk_mq_inc_active_requests(hctx);
- }
- hctx->tags->rqs[rq->tag] = rq;
+ blk_mq_inc_active_requests(rq->mq_hctx);
return true;
}
@@ -2794,13 +2794,8 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
* If we do, we can dispatch the whole plug list in one go. We
* already know at this point that all requests belong to the
* same queue, caller must ensure that's the case.
- *
- * Since we pass off the full list to the driver at this point,
- * we do not increment the active request count for the queue.
- * Bypass shared tags for now because of that.
*/
- if (q->mq_ops->queue_rqs &&
- !(rq->mq_hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) {
+ if (q->mq_ops->queue_rqs) {
blk_mq_run_dispatch_ops(q,
__blk_mq_flush_plug_list(q, plug));
if (rq_list_empty(plug->mq_list))
@@ -2875,11 +2870,8 @@ static struct request *blk_mq_get_new_requests(struct request_queue *q,
};
struct request *rq;
- if (unlikely(bio_queue_enter(bio)))
- return NULL;
-
if (blk_mq_attempt_bio_merge(q, bio, nsegs))
- goto queue_exit;
+ return NULL;
rq_qos_throttle(q, bio);
@@ -2895,35 +2887,23 @@ static struct request *blk_mq_get_new_requests(struct request_queue *q,
rq_qos_cleanup(q, bio);
if (bio->bi_opf & REQ_NOWAIT)
bio_wouldblock_error(bio);
-queue_exit:
- blk_queue_exit(q);
return NULL;
}
-static inline struct request *blk_mq_get_cached_request(struct request_queue *q,
- struct blk_plug *plug, struct bio **bio, unsigned int nsegs)
+/* return true if this @rq can be used for @bio */
+static bool blk_mq_can_use_cached_rq(struct request *rq, struct blk_plug *plug,
+ struct bio *bio)
{
- struct request *rq;
- enum hctx_type type, hctx_type;
+ enum hctx_type type = blk_mq_get_hctx_type(bio->bi_opf);
+ enum hctx_type hctx_type = rq->mq_hctx->type;
- if (!plug)
- return NULL;
- rq = rq_list_peek(&plug->cached_rq);
- if (!rq || rq->q != q)
- return NULL;
+ WARN_ON_ONCE(rq_list_peek(&plug->cached_rq) != rq);
- if (blk_mq_attempt_bio_merge(q, *bio, nsegs)) {
- *bio = NULL;
- return NULL;
- }
-
- type = blk_mq_get_hctx_type((*bio)->bi_opf);
- hctx_type = rq->mq_hctx->type;
if (type != hctx_type &&
!(type == HCTX_TYPE_READ && hctx_type == HCTX_TYPE_DEFAULT))
- return NULL;
- if (op_is_flush(rq->cmd_flags) != op_is_flush((*bio)->bi_opf))
- return NULL;
+ return false;
+ if (op_is_flush(rq->cmd_flags) != op_is_flush(bio->bi_opf))
+ return false;
/*
* If any qos ->throttle() end up blocking, we will have flushed the
@@ -2931,12 +2911,12 @@ static inline struct request *blk_mq_get_cached_request(struct request_queue *q,
* before we throttle.
*/
plug->cached_rq = rq_list_next(rq);
- rq_qos_throttle(q, *bio);
+ rq_qos_throttle(rq->q, bio);
blk_mq_rq_time_init(rq, 0);
- rq->cmd_flags = (*bio)->bi_opf;
+ rq->cmd_flags = bio->bi_opf;
INIT_LIST_HEAD(&rq->queuelist);
- return rq;
+ return true;
}
static void bio_set_ioprio(struct bio *bio)
@@ -2966,7 +2946,7 @@ void blk_mq_submit_bio(struct bio *bio)
struct blk_plug *plug = blk_mq_plug(bio);
const int is_sync = op_is_sync(bio->bi_opf);
struct blk_mq_hw_ctx *hctx;
- struct request *rq;
+ struct request *rq = NULL;
unsigned int nr_segs = 1;
blk_status_t ret;
@@ -2977,20 +2957,36 @@ void blk_mq_submit_bio(struct bio *bio)
return;
}
- if (!bio_integrity_prep(bio))
- return;
-
bio_set_ioprio(bio);
- rq = blk_mq_get_cached_request(q, plug, &bio, nr_segs);
- if (!rq) {
- if (!bio)
+ if (plug) {
+ rq = rq_list_peek(&plug->cached_rq);
+ if (rq && rq->q != q)
+ rq = NULL;
+ }
+ if (rq) {
+ if (!bio_integrity_prep(bio))
return;
- rq = blk_mq_get_new_requests(q, plug, bio, nr_segs);
- if (unlikely(!rq))
+ if (blk_mq_attempt_bio_merge(q, bio, nr_segs))
return;
+ if (blk_mq_can_use_cached_rq(rq, plug, bio))
+ goto done;
+ percpu_ref_get(&q->q_usage_counter);
+ } else {
+ if (unlikely(bio_queue_enter(bio)))
+ return;
+ if (!bio_integrity_prep(bio))
+ goto fail;
}
+ rq = blk_mq_get_new_requests(q, plug, bio, nr_segs);
+ if (unlikely(!rq)) {
+fail:
+ blk_queue_exit(q);
+ return;
+ }
+
+done:
trace_block_getrq(bio);
rq_qos_track(q, rq, bio);
diff --git a/block/blk-mq.h b/block/blk-mq.h
index 1743857e0b01..f75a9ecfebde 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -271,12 +271,18 @@ static inline int blk_mq_get_rq_budget_token(struct request *rq)
return -1;
}
-static inline void __blk_mq_inc_active_requests(struct blk_mq_hw_ctx *hctx)
+static inline void __blk_mq_add_active_requests(struct blk_mq_hw_ctx *hctx,
+ int val)
{
if (blk_mq_is_shared_tags(hctx->flags))
- atomic_inc(&hctx->queue->nr_active_requests_shared_tags);
+ atomic_add(val, &hctx->queue->nr_active_requests_shared_tags);
else
- atomic_inc(&hctx->nr_active);
+ atomic_add(val, &hctx->nr_active);
+}
+
+static inline void __blk_mq_inc_active_requests(struct blk_mq_hw_ctx *hctx)
+{
+ __blk_mq_add_active_requests(hctx, 1);
}
static inline void __blk_mq_sub_active_requests(struct blk_mq_hw_ctx *hctx,
@@ -293,6 +299,32 @@ static inline void __blk_mq_dec_active_requests(struct blk_mq_hw_ctx *hctx)
__blk_mq_sub_active_requests(hctx, 1);
}
+static inline void blk_mq_add_active_requests(struct blk_mq_hw_ctx *hctx,
+ int val)
+{
+ if (hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)
+ __blk_mq_add_active_requests(hctx, val);
+}
+
+static inline void blk_mq_inc_active_requests(struct blk_mq_hw_ctx *hctx)
+{
+ if (hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)
+ __blk_mq_inc_active_requests(hctx);
+}
+
+static inline void blk_mq_sub_active_requests(struct blk_mq_hw_ctx *hctx,
+ int val)
+{
+ if (hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)
+ __blk_mq_sub_active_requests(hctx, val);
+}
+
+static inline void blk_mq_dec_active_requests(struct blk_mq_hw_ctx *hctx)
+{
+ if (hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)
+ __blk_mq_dec_active_requests(hctx);
+}
+
static inline int __blk_mq_active_requests(struct blk_mq_hw_ctx *hctx)
{
if (blk_mq_is_shared_tags(hctx->flags))
@@ -302,13 +334,9 @@ static inline int __blk_mq_active_requests(struct blk_mq_hw_ctx *hctx)
static inline void __blk_mq_put_driver_tag(struct blk_mq_hw_ctx *hctx,
struct request *rq)
{
+ blk_mq_dec_active_requests(hctx);
blk_mq_put_tag(hctx->tags, rq->mq_ctx, rq->tag);
rq->tag = BLK_MQ_NO_TAG;
-
- if (rq->rq_flags & RQF_MQ_INFLIGHT) {
- rq->rq_flags &= ~RQF_MQ_INFLIGHT;
- __blk_mq_dec_active_requests(hctx);
- }
}
static inline void blk_mq_put_driver_tag(struct request *rq)
@@ -319,19 +347,14 @@ static inline void blk_mq_put_driver_tag(struct request *rq)
__blk_mq_put_driver_tag(rq->mq_hctx, rq);
}
-bool __blk_mq_get_driver_tag(struct blk_mq_hw_ctx *hctx, struct request *rq);
+bool __blk_mq_alloc_driver_tag(struct request *rq);
static inline bool blk_mq_get_driver_tag(struct request *rq)
{
- struct blk_mq_hw_ctx *hctx = rq->mq_hctx;
-
- if (rq->tag != BLK_MQ_NO_TAG &&
- !(hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)) {
- hctx->tags->rqs[rq->tag] = rq;
- return true;
- }
+ if (rq->tag == BLK_MQ_NO_TAG && !__blk_mq_alloc_driver_tag(rq))
+ return false;
- return __blk_mq_get_driver_tag(hctx, rq);
+ return true;
}
static inline void blk_mq_clear_mq_map(struct blk_mq_queue_map *qmap)
diff --git a/block/blk-pm.c b/block/blk-pm.c
index 6b72b2e03fc8..42e842074715 100644
--- a/block/blk-pm.c
+++ b/block/blk-pm.c
@@ -163,39 +163,16 @@ EXPORT_SYMBOL(blk_pre_runtime_resume);
* @q: the queue of the device
*
* Description:
- * For historical reasons, this routine merely calls blk_set_runtime_active()
- * to do the real work of restarting the queue. It does this regardless of
- * whether the device's runtime-resume succeeded; even if it failed the
+ * Restart the queue of a runtime suspended device. It does this regardless
+ * of whether the device's runtime-resume succeeded; even if it failed the
* driver or error handler will need to communicate with the device.
*
* This function should be called near the end of the device's
- * runtime_resume callback.
+ * runtime_resume callback to correct queue runtime PM status and re-enable
+ * peeking requests from the queue.
*/
void blk_post_runtime_resume(struct request_queue *q)
{
- blk_set_runtime_active(q);
-}
-EXPORT_SYMBOL(blk_post_runtime_resume);
-
-/**
- * blk_set_runtime_active - Force runtime status of the queue to be active
- * @q: the queue of the device
- *
- * If the device is left runtime suspended during system suspend the resume
- * hook typically resumes the device and corrects runtime status
- * accordingly. However, that does not affect the queue runtime PM status
- * which is still "suspended". This prevents processing requests from the
- * queue.
- *
- * This function can be used in driver's resume hook to correct queue
- * runtime PM status and re-enable peeking requests from the queue. It
- * should be called before first request is added to the queue.
- *
- * This function is also called by blk_post_runtime_resume() for
- * runtime resumes. It does everything necessary to restart the queue.
- */
-void blk_set_runtime_active(struct request_queue *q)
-{
int old_status;
if (!q->dev)
@@ -211,4 +188,4 @@ void blk_set_runtime_active(struct request_queue *q)
if (old_status != RPM_ACTIVE)
blk_clear_pm_only(q);
}
-EXPORT_SYMBOL(blk_set_runtime_active);
+EXPORT_SYMBOL(blk_post_runtime_resume);
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 63e481262336..0b2d04766324 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -615,6 +615,7 @@ static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page,
QUEUE_RW_ENTRY(queue_wb_lat, "wbt_lat_usec");
#endif
+/* Common attributes for bio-based and request-based queues. */
static struct attribute *queue_attrs[] = {
&queue_ra_entry.attr,
&queue_max_hw_sectors_entry.attr,
@@ -659,6 +660,7 @@ static struct attribute *queue_attrs[] = {
NULL,
};
+/* Request-based queue attributes that are not relevant for bio-based queues. */
static struct attribute *blk_mq_queue_attrs[] = {
&queue_requests_entry.attr,
&elv_iosched_entry.attr,
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 38a881cf97d0..16f5766620a4 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -723,6 +723,12 @@ static unsigned int calculate_io_allowed(u32 iops_limit,
static u64 calculate_bytes_allowed(u64 bps_limit, unsigned long jiffy_elapsed)
{
+ /*
+ * Can result be wider than 64 bits?
+ * We check against 62, not 64, due to ilog2 truncation.
+ */
+ if (ilog2(bps_limit) + ilog2(jiffy_elapsed) - ilog2(HZ) > 62)
+ return U64_MAX;
return mul_u64_u64_div_u64(bps_limit, (u64)jiffy_elapsed, (u64)HZ);
}
@@ -1314,6 +1320,7 @@ static void tg_conf_updated(struct throtl_grp *tg, bool global)
tg_bps_limit(tg, READ), tg_bps_limit(tg, WRITE),
tg_iops_limit(tg, READ), tg_iops_limit(tg, WRITE));
+ rcu_read_lock();
/*
* Update has_rules[] flags for the updated tg's subtree. A tg is
* considered to have rules if either the tg itself or any of its
@@ -1341,6 +1348,7 @@ static void tg_conf_updated(struct throtl_grp *tg, bool global)
this_tg->latency_target = max(this_tg->latency_target,
parent_tg->latency_target);
}
+ rcu_read_unlock();
/*
* We're already holding queue_lock and know @tg is valid. Let's
diff --git a/block/disk-events.c b/block/disk-events.c
index 13c3372c465a..2f697224386a 100644
--- a/block/disk-events.c
+++ b/block/disk-events.c
@@ -266,11 +266,8 @@ static unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
* disk_check_media_change - check if a removable media has been changed
* @disk: gendisk to check
*
- * Check whether a removable media has been changed, and attempt to free all
- * dentries and inodes and invalidates all block device page cache entries in
- * that case.
- *
- * Returns %true if the media has changed, or %false if not.
+ * Returns %true and marks the disk for a partition rescan whether a removable
+ * media has been changed, and %false if the media did not change.
*/
bool disk_check_media_change(struct gendisk *disk)
{
@@ -278,12 +275,11 @@ bool disk_check_media_change(struct gendisk *disk)
events = disk_clear_events(disk, DISK_EVENT_MEDIA_CHANGE |
DISK_EVENT_EJECT_REQUEST);
- if (!(events & DISK_EVENT_MEDIA_CHANGE))
- return false;
-
- bdev_mark_dead(disk->part0, true);
- set_bit(GD_NEED_PART_SCAN, &disk->state);
- return true;
+ if (events & DISK_EVENT_MEDIA_CHANGE) {
+ set_bit(GD_NEED_PART_SCAN, &disk->state);
+ return true;
+ }
+ return false;
}
EXPORT_SYMBOL(disk_check_media_change);
diff --git a/block/fops.c b/block/fops.c
index acff3d5d22d4..0abaac705daf 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -542,15 +542,31 @@ static int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
return error;
}
+/**
+ * file_to_blk_mode - get block open flags from file flags
+ * @file: file whose open flags should be converted
+ *
+ * Look at file open flags and generate corresponding block open flags from
+ * them. The function works both for file just being open (e.g. during ->open
+ * callback) and for file that is already open. This is actually non-trivial
+ * (see comment in the function).
+ */
blk_mode_t file_to_blk_mode(struct file *file)
{
blk_mode_t mode = 0;
+ struct bdev_handle *handle = file->private_data;
if (file->f_mode & FMODE_READ)
mode |= BLK_OPEN_READ;
if (file->f_mode & FMODE_WRITE)
mode |= BLK_OPEN_WRITE;
- if (file->private_data)
+ /*
+ * do_dentry_open() clears O_EXCL from f_flags, use handle->mode to
+ * determine whether the open was exclusive for already open files.
+ */
+ if (handle)
+ mode |= handle->mode & BLK_OPEN_EXCL;
+ else if (file->f_flags & O_EXCL)
mode |= BLK_OPEN_EXCL;
if (file->f_flags & O_NDELAY)
mode |= BLK_OPEN_NDELAY;
@@ -568,7 +584,8 @@ blk_mode_t file_to_blk_mode(struct file *file)
static int blkdev_open(struct inode *inode, struct file *filp)
{
- struct block_device *bdev;
+ struct bdev_handle *handle;
+ blk_mode_t mode;
/*
* Preserve backwards compatibility and allow large file access
@@ -579,29 +596,24 @@ static int blkdev_open(struct inode *inode, struct file *filp)
filp->f_flags |= O_LARGEFILE;
filp->f_mode |= FMODE_BUF_RASYNC | FMODE_CAN_ODIRECT;
- /*
- * Use the file private data to store the holder for exclusive openes.
- * file_to_blk_mode relies on it being present to set BLK_OPEN_EXCL.
- */
- if (filp->f_flags & O_EXCL)
- filp->private_data = filp;
-
- bdev = blkdev_get_by_dev(inode->i_rdev, file_to_blk_mode(filp),
- filp->private_data, NULL);
- if (IS_ERR(bdev))
- return PTR_ERR(bdev);
+ mode = file_to_blk_mode(filp);
+ handle = bdev_open_by_dev(inode->i_rdev, mode,
+ mode & BLK_OPEN_EXCL ? filp : NULL, NULL);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
- if (bdev_nowait(bdev))
+ if (bdev_nowait(handle->bdev))
filp->f_mode |= FMODE_NOWAIT;
- filp->f_mapping = bdev->bd_inode->i_mapping;
+ filp->f_mapping = handle->bdev->bd_inode->i_mapping;
filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping);
+ filp->private_data = handle;
return 0;
}
static int blkdev_release(struct inode *inode, struct file *filp)
{
- blkdev_put(I_BDEV(filp->f_mapping->host), filp->private_data);
+ bdev_release(filp->private_data);
return 0;
}
@@ -772,24 +784,35 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start,
filemap_invalidate_lock(inode->i_mapping);
- /* Invalidate the page cache, including dirty pages. */
- error = truncate_bdev_range(bdev, file_to_blk_mode(file), start, end);
- if (error)
- goto fail;
-
+ /*
+ * Invalidate the page cache, including dirty pages, for valid
+ * de-allocate mode calls to fallocate().
+ */
switch (mode) {
case FALLOC_FL_ZERO_RANGE:
case FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE:
+ error = truncate_bdev_range(bdev, file_to_blk_mode(file), start, end);
+ if (error)
+ goto fail;
+
error = blkdev_issue_zeroout(bdev, start >> SECTOR_SHIFT,
len >> SECTOR_SHIFT, GFP_KERNEL,
BLKDEV_ZERO_NOUNMAP);
break;
case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE:
+ error = truncate_bdev_range(bdev, file_to_blk_mode(file), start, end);
+ if (error)
+ goto fail;
+
error = blkdev_issue_zeroout(bdev, start >> SECTOR_SHIFT,
len >> SECTOR_SHIFT, GFP_KERNEL,
BLKDEV_ZERO_NOFALLBACK);
break;
case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE | FALLOC_FL_NO_HIDE_STALE:
+ error = truncate_bdev_range(bdev, file_to_blk_mode(file), start, end);
+ if (error)
+ goto fail;
+
error = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT,
len >> SECTOR_SHIFT, GFP_KERNEL);
break;
diff --git a/block/genhd.c b/block/genhd.c
index cc32a0c704eb..c9d06f72c587 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -342,7 +342,7 @@ EXPORT_SYMBOL_GPL(disk_uevent);
int disk_scan_partitions(struct gendisk *disk, blk_mode_t mode)
{
- struct block_device *bdev;
+ struct bdev_handle *handle;
int ret = 0;
if (disk->flags & (GENHD_FL_NO_PART | GENHD_FL_HIDDEN))
@@ -366,12 +366,12 @@ int disk_scan_partitions(struct gendisk *disk, blk_mode_t mode)
}
set_bit(GD_NEED_PART_SCAN, &disk->state);
- bdev = blkdev_get_by_dev(disk_devt(disk), mode & ~BLK_OPEN_EXCL, NULL,
- NULL);
- if (IS_ERR(bdev))
- ret = PTR_ERR(bdev);
+ handle = bdev_open_by_dev(disk_devt(disk), mode & ~BLK_OPEN_EXCL, NULL,
+ NULL);
+ if (IS_ERR(handle))
+ ret = PTR_ERR(handle);
else
- blkdev_put(bdev, NULL);
+ bdev_release(handle);
/*
* If blkdev_get_by_dev() failed early, GD_NEED_PART_SCAN is still set,
@@ -559,6 +559,13 @@ static void blk_report_disk_dead(struct gendisk *disk, bool surprise)
struct block_device *bdev;
unsigned long idx;
+ /*
+ * On surprise disk removal, bdev_mark_dead() may call into file
+ * systems below. Make it clear that we're expecting to not hold
+ * disk->open_mutex.
+ */
+ lockdep_assert_not_held(&disk->open_mutex);
+
rcu_read_lock();
xa_for_each(&disk->part_tbl, idx, bdev) {
if (!kobject_get_unless_zero(&bdev->bd_device.kobj))
diff --git a/block/ioctl.c b/block/ioctl.c
index d5f5cd61efd7..4160f4e6bd5b 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -370,9 +370,10 @@ static int blkdev_flushbuf(struct block_device *bdev, unsigned cmd,
mutex_lock(&bdev->bd_holder_lock);
if (bdev->bd_holder_ops && bdev->bd_holder_ops->sync)
bdev->bd_holder_ops->sync(bdev);
- else
+ else {
+ mutex_unlock(&bdev->bd_holder_lock);
sync_blockdev(bdev);
- mutex_unlock(&bdev->bd_holder_lock);
+ }
invalidate_bdev(bdev);
return 0;
@@ -467,6 +468,7 @@ static int blkdev_bszset(struct block_device *bdev, blk_mode_t mode,
int __user *argp)
{
int ret, n;
+ struct bdev_handle *handle;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -478,10 +480,11 @@ static int blkdev_bszset(struct block_device *bdev, blk_mode_t mode,
if (mode & BLK_OPEN_EXCL)
return set_blocksize(bdev, n);
- if (IS_ERR(blkdev_get_by_dev(bdev->bd_dev, mode, &bdev, NULL)))
+ handle = bdev_open_by_dev(bdev->bd_dev, mode, &bdev, NULL);
+ if (IS_ERR(handle))
return -EBUSY;
ret = set_blocksize(bdev, n);
- blkdev_put(bdev, &bdev);
+ bdev_release(handle);
return ret;
}
diff --git a/block/partitions/core.c b/block/partitions/core.c
index e137a87f4db0..f47ffcfdfcec 100644
--- a/block/partitions/core.c
+++ b/block/partitions/core.c
@@ -274,17 +274,6 @@ void drop_partition(struct block_device *part)
put_device(&part->bd_device);
}
-static void delete_partition(struct block_device *part)
-{
- /*
- * Remove the block device from the inode hash, so that it cannot be
- * looked up any more even when openers still hold references.
- */
- remove_inode_hash(part->bd_inode);
- bdev_mark_dead(part, false);
- drop_partition(part);
-}
-
static ssize_t whole_disk_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -485,7 +474,18 @@ int bdev_del_partition(struct gendisk *disk, int partno)
if (atomic_read(&part->bd_openers))
goto out_unlock;
- delete_partition(part);
+ /*
+ * We verified that @part->bd_openers is zero above and so
+ * @part->bd_holder{_ops} can't be set. And since we hold
+ * @disk->open_mutex the device can't be claimed by anyone.
+ *
+ * So no need to call @part->bd_holder_ops->mark_dead() here.
+ * Just delete the partition and invalidate it.
+ */
+
+ remove_inode_hash(part->bd_inode);
+ invalidate_bdev(part);
+ drop_partition(part);
ret = 0;
out_unlock:
mutex_unlock(&disk->open_mutex);
@@ -663,8 +663,23 @@ rescan:
sync_blockdev(disk->part0);
invalidate_bdev(disk->part0);
- xa_for_each_start(&disk->part_tbl, idx, part, 1)
- delete_partition(part);
+ xa_for_each_start(&disk->part_tbl, idx, part, 1) {
+ /*
+ * Remove the block device from the inode hash, so that
+ * it cannot be looked up any more even when openers
+ * still hold references.
+ */
+ remove_inode_hash(part->bd_inode);
+
+ /*
+ * If @disk->open_partitions isn't elevated but there's
+ * still an active holder of that block device things
+ * are broken.
+ */
+ WARN_ON_ONCE(atomic_read(&part->bd_openers));
+ invalidate_bdev(part);
+ drop_partition(part);
+ }
clear_bit(GD_NEED_PART_SCAN, &disk->state);
/*
diff --git a/block/partitions/ibm.c b/block/partitions/ibm.c
index 403756dbd50d..82d9c4c3fb41 100644
--- a/block/partitions/ibm.c
+++ b/block/partitions/ibm.c
@@ -61,6 +61,47 @@ static sector_t cchhb2blk(struct vtoc_cchhb *ptr, struct hd_geometry *geo)
ptr->b;
}
+/* Volume Label Type/ID Length */
+#define DASD_VOL_TYPE_LEN 4
+#define DASD_VOL_ID_LEN 6
+
+/* Volume Label Types */
+#define DASD_VOLLBL_TYPE_VOL1 0
+#define DASD_VOLLBL_TYPE_LNX1 1
+#define DASD_VOLLBL_TYPE_CMS1 2
+
+struct dasd_vollabel {
+ char *type;
+ int idx;
+};
+
+static struct dasd_vollabel dasd_vollabels[] = {
+ [DASD_VOLLBL_TYPE_VOL1] = {
+ .type = "VOL1",
+ .idx = DASD_VOLLBL_TYPE_VOL1,
+ },
+ [DASD_VOLLBL_TYPE_LNX1] = {
+ .type = "LNX1",
+ .idx = DASD_VOLLBL_TYPE_LNX1,
+ },
+ [DASD_VOLLBL_TYPE_CMS1] = {
+ .type = "CMS1",
+ .idx = DASD_VOLLBL_TYPE_CMS1,
+ },
+};
+
+static int get_label_by_type(const char *type)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dasd_vollabels); i++) {
+ if (!memcmp(type, dasd_vollabels[i].type, DASD_VOL_TYPE_LEN))
+ return dasd_vollabels[i].idx;
+ }
+
+ return -1;
+}
+
static int find_label(struct parsed_partitions *state,
dasd_information2_t *info,
struct hd_geometry *geo,
@@ -70,12 +111,10 @@ static int find_label(struct parsed_partitions *state,
char type[],
union label_t *label)
{
- Sector sect;
- unsigned char *data;
sector_t testsect[3];
- unsigned char temp[5];
- int found = 0;
int i, testcount;
+ Sector sect;
+ void *data;
/* There a three places where we may find a valid label:
* - on an ECKD disk it's block 2
@@ -103,31 +142,27 @@ static int find_label(struct parsed_partitions *state,
if (data == NULL)
continue;
memcpy(label, data, sizeof(*label));
- memcpy(temp, data, 4);
- temp[4] = 0;
- EBCASC(temp, 4);
+ memcpy(type, data, DASD_VOL_TYPE_LEN);
+ EBCASC(type, DASD_VOL_TYPE_LEN);
put_dev_sector(sect);
- if (!strcmp(temp, "VOL1") ||
- !strcmp(temp, "LNX1") ||
- !strcmp(temp, "CMS1")) {
- if (!strcmp(temp, "VOL1")) {
- strncpy(type, label->vol.vollbl, 4);
- strncpy(name, label->vol.volid, 6);
- } else {
- strncpy(type, label->lnx.vollbl, 4);
- strncpy(name, label->lnx.volid, 6);
- }
- EBCASC(type, 4);
- EBCASC(name, 6);
+ switch (get_label_by_type(type)) {
+ case DASD_VOLLBL_TYPE_VOL1:
+ memcpy(name, label->vol.volid, DASD_VOL_ID_LEN);
+ EBCASC(name, DASD_VOL_ID_LEN);
+ *labelsect = testsect[i];
+ return 1;
+ case DASD_VOLLBL_TYPE_LNX1:
+ case DASD_VOLLBL_TYPE_CMS1:
+ memcpy(name, label->lnx.volid, DASD_VOL_ID_LEN);
+ EBCASC(name, DASD_VOL_ID_LEN);
*labelsect = testsect[i];
- found = 1;
+ return 1;
+ default:
break;
}
}
- if (!found)
- memset(label, 0, sizeof(*label));
- return found;
+ return 0;
}
static int find_vol1_partitions(struct parsed_partitions *state,
@@ -297,8 +332,8 @@ int ibm_partition(struct parsed_partitions *state)
sector_t nr_sectors;
dasd_information2_t *info;
struct hd_geometry *geo;
- char type[5] = {0,};
- char name[7] = {0,};
+ char type[DASD_VOL_TYPE_LEN + 1] = "";
+ char name[DASD_VOL_ID_LEN + 1] = "";
sector_t labelsect;
union label_t *label;
@@ -330,18 +365,21 @@ int ibm_partition(struct parsed_partitions *state)
info = NULL;
}
- if (find_label(state, info, geo, blocksize, &labelsect, name, type,
- label)) {
- if (!strncmp(type, "VOL1", 4)) {
+ if (find_label(state, info, geo, blocksize, &labelsect, name, type, label)) {
+ switch (get_label_by_type(type)) {
+ case DASD_VOLLBL_TYPE_VOL1:
res = find_vol1_partitions(state, geo, blocksize, name,
label);
- } else if (!strncmp(type, "LNX1", 4)) {
+ break;
+ case DASD_VOLLBL_TYPE_LNX1:
res = find_lnx1_partitions(state, geo, blocksize, name,
label, labelsect, nr_sectors,
info);
- } else if (!strncmp(type, "CMS1", 4)) {
+ break;
+ case DASD_VOLLBL_TYPE_CMS1:
res = find_cms1_partitions(state, geo, blocksize, name,
label, labelsect);
+ break;
}
} else if (info) {
/*
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 6d7f25d1711b..3d9e9cd250bd 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -18,6 +18,7 @@
#include <linux/uaccess.h>
#include <uapi/linux/sed-opal.h>
#include <linux/sed-opal.h>
+#include <linux/sed-opal-key.h>
#include <linux/string.h>
#include <linux/kdev_t.h>
#include <linux/key.h>
@@ -2888,12 +2889,11 @@ static int opal_lock_unlock(struct opal_dev *dev,
if (lk_unlk->session.who > OPAL_USER9)
return -EINVAL;
- ret = opal_get_key(dev, &lk_unlk->session.opal_key);
- if (ret)
- return ret;
mutex_lock(&dev->dev_lock);
opal_lock_check_for_saved_key(dev, lk_unlk);
- ret = __opal_lock_unlock(dev, lk_unlk);
+ ret = opal_get_key(dev, &lk_unlk->session.opal_key);
+ if (!ret)
+ ret = __opal_lock_unlock(dev, lk_unlk);
mutex_unlock(&dev->dev_lock);
return ret;
@@ -3019,7 +3019,13 @@ static int opal_set_new_pw(struct opal_dev *dev, struct opal_new_pw *opal_pw)
if (ret)
return ret;
- /* update keyring with new password */
+ /* update keyring and key store with new password */
+ ret = sed_write_key(OPAL_AUTH_KEY,
+ opal_pw->new_user_pw.opal_key.key,
+ opal_pw->new_user_pw.opal_key.key_len);
+ if (ret != -EOPNOTSUPP)
+ pr_warn("error updating SED key: %d\n", ret);
+
ret = update_sed_opal_key(OPAL_AUTH_KEY,
opal_pw->new_user_pw.opal_key.key,
opal_pw->new_user_pw.opal_key.key_len);
@@ -3292,6 +3298,8 @@ EXPORT_SYMBOL_GPL(sed_ioctl);
static int __init sed_opal_init(void)
{
struct key *kr;
+ char init_sed_key[OPAL_KEY_MAX];
+ int keylen = OPAL_KEY_MAX - 1;
kr = keyring_alloc(".sed_opal",
GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(),
@@ -3304,6 +3312,11 @@ static int __init sed_opal_init(void)
sed_opal_keyring = kr;
- return 0;
+ if (sed_read_key(OPAL_AUTH_KEY, init_sed_key, &keylen) < 0) {
+ memset(init_sed_key, '\0', sizeof(init_sed_key));
+ keylen = OPAL_KEY_MAX - 1;
+ }
+
+ return update_sed_opal_key(OPAL_AUTH_KEY, init_sed_key, keylen);
}
late_initcall(sed_opal_init);
diff --git a/certs/Kconfig b/certs/Kconfig
index 1f109b070877..78307dc25559 100644
--- a/certs/Kconfig
+++ b/certs/Kconfig
@@ -30,9 +30,11 @@ config MODULE_SIG_KEY_TYPE_RSA
config MODULE_SIG_KEY_TYPE_ECDSA
bool "ECDSA"
select CRYPTO_ECDSA
+ depends on !(MODULE_SIG_SHA256 || MODULE_SIG_SHA3_256)
help
- Use an elliptic curve key (NIST P384) for module signing. Consider
- using a strong hash like sha256 or sha384 for hashing modules.
+ Use an elliptic curve key (NIST P384) for module signing. Use
+ a strong hash of same or higher bit length, i.e. sha384 or
+ sha512 for hashing modules.
Note: Remove all ECDSA signing keys, e.g. certs/signing_key.pem,
when falling back to building Linux 5.14 and older kernels.
@@ -88,7 +90,21 @@ config SECONDARY_TRUSTED_KEYRING
help
If set, provide a keyring to which extra keys may be added, provided
those keys are not blacklisted and are vouched for by a key built
- into the kernel or already in the secondary trusted keyring.
+ into the kernel, machine keyring (if configured), or already in the
+ secondary trusted keyring.
+
+config SECONDARY_TRUSTED_KEYRING_SIGNED_BY_BUILTIN
+ bool "Only allow additional certs signed by keys on the builtin trusted keyring"
+ depends on SECONDARY_TRUSTED_KEYRING
+ help
+ If set, only certificates signed by keys on the builtin trusted
+ keyring may be loaded onto the secondary trusted keyring.
+
+ Note: The machine keyring, if configured, will be linked to the
+ secondary keyring. When enabling this option, it is recommended
+ to also configure INTEGRITY_CA_MACHINE_KEYRING_MAX to prevent
+ linking code signing keys with imputed trust to the secondary
+ trusted keyring.
config SYSTEM_BLACKLIST_KEYRING
bool "Provide system-wide ring of blacklisted keys"
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 650b1b3620d8..70661f58ee41 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -85,6 +85,7 @@ config CRYPTO_SKCIPHER
tristate
select CRYPTO_SKCIPHER2
select CRYPTO_ALGAPI
+ select CRYPTO_ECB
config CRYPTO_SKCIPHER2
tristate
@@ -689,7 +690,7 @@ config CRYPTO_CTS
config CRYPTO_ECB
tristate "ECB (Electronic Codebook)"
- select CRYPTO_SKCIPHER
+ select CRYPTO_SKCIPHER2
select CRYPTO_MANAGER
help
ECB (Electronic Codebook) mode (NIST SP800-38A)
@@ -1296,9 +1297,69 @@ config CRYPTO_JITTERENTROPY
See https://www.chronox.de/jent.html
+if CRYPTO_JITTERENTROPY
+if CRYPTO_FIPS && EXPERT
+
+choice
+ prompt "CPU Jitter RNG Memory Size"
+ default CRYPTO_JITTERENTROPY_MEMSIZE_2
+ help
+ The Jitter RNG measures the execution time of memory accesses.
+ Multiple consecutive memory accesses are performed. If the memory
+ size fits into a cache (e.g. L1), only the memory access timing
+ to that cache is measured. The closer the cache is to the CPU
+ the less variations are measured and thus the less entropy is
+ obtained. Thus, if the memory size fits into the L1 cache, the
+ obtained entropy is less than if the memory size fits within
+ L1 + L2, which in turn is less if the memory fits into
+ L1 + L2 + L3. Thus, by selecting a different memory size,
+ the entropy rate produced by the Jitter RNG can be modified.
+
+ config CRYPTO_JITTERENTROPY_MEMSIZE_2
+ bool "2048 Bytes (default)"
+
+ config CRYPTO_JITTERENTROPY_MEMSIZE_128
+ bool "128 kBytes"
+
+ config CRYPTO_JITTERENTROPY_MEMSIZE_1024
+ bool "1024 kBytes"
+
+ config CRYPTO_JITTERENTROPY_MEMSIZE_8192
+ bool "8192 kBytes"
+endchoice
+
+config CRYPTO_JITTERENTROPY_MEMORY_BLOCKS
+ int
+ default 64 if CRYPTO_JITTERENTROPY_MEMSIZE_2
+ default 512 if CRYPTO_JITTERENTROPY_MEMSIZE_128
+ default 1024 if CRYPTO_JITTERENTROPY_MEMSIZE_1024
+ default 4096 if CRYPTO_JITTERENTROPY_MEMSIZE_8192
+
+config CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE
+ int
+ default 32 if CRYPTO_JITTERENTROPY_MEMSIZE_2
+ default 256 if CRYPTO_JITTERENTROPY_MEMSIZE_128
+ default 1024 if CRYPTO_JITTERENTROPY_MEMSIZE_1024
+ default 2048 if CRYPTO_JITTERENTROPY_MEMSIZE_8192
+
+config CRYPTO_JITTERENTROPY_OSR
+ int "CPU Jitter RNG Oversampling Rate"
+ range 1 15
+ default 1
+ help
+ The Jitter RNG allows the specification of an oversampling rate (OSR).
+ The Jitter RNG operation requires a fixed amount of timing
+ measurements to produce one output block of random numbers. The
+ OSR value is multiplied with the amount of timing measurements to
+ generate one output block. Thus, the timing measurement is oversampled
+ by the OSR factor. The oversampling allows the Jitter RNG to operate
+ on hardware whose timers deliver limited amount of entropy (e.g.
+ the timer is coarse) by setting the OSR to a higher value. The
+ trade-off, however, is that the Jitter RNG now requires more time
+ to generate random numbers.
+
config CRYPTO_JITTERENTROPY_TESTINTERFACE
bool "CPU Jitter RNG Test Interface"
- depends on CRYPTO_JITTERENTROPY
help
The test interface allows a privileged process to capture
the raw unconditioned high resolution time stamp noise that
@@ -1316,6 +1377,28 @@ config CRYPTO_JITTERENTROPY_TESTINTERFACE
If unsure, select N.
+endif # if CRYPTO_FIPS && EXPERT
+
+if !(CRYPTO_FIPS && EXPERT)
+
+config CRYPTO_JITTERENTROPY_MEMORY_BLOCKS
+ int
+ default 64
+
+config CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE
+ int
+ default 32
+
+config CRYPTO_JITTERENTROPY_OSR
+ int
+ default 1
+
+config CRYPTO_JITTERENTROPY_TESTINTERFACE
+ bool
+
+endif # if !(CRYPTO_FIPS && EXPERT)
+endif # if CRYPTO_JITTERENTROPY
+
config CRYPTO_KDF800108_CTR
tristate
select CRYPTO_HMAC
diff --git a/crypto/Makefile b/crypto/Makefile
index 953a7e105e58..5ac6876f935a 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -16,7 +16,11 @@ obj-$(CONFIG_CRYPTO_ALGAPI2) += crypto_algapi.o
obj-$(CONFIG_CRYPTO_AEAD2) += aead.o
obj-$(CONFIG_CRYPTO_GENIV) += geniv.o
-obj-$(CONFIG_CRYPTO_SKCIPHER2) += skcipher.o
+crypto_skcipher-y += lskcipher.o
+crypto_skcipher-y += skcipher.o
+
+obj-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
+
obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
obj-$(CONFIG_CRYPTO_ECHAINIV) += echainiv.o
diff --git a/crypto/adiantum.c b/crypto/adiantum.c
index c33ba22a6638..60f3883b736a 100644
--- a/crypto/adiantum.c
+++ b/crypto/adiantum.c
@@ -245,10 +245,9 @@ static void adiantum_hash_header(struct skcipher_request *req)
/* Hash the left-hand part (the "bulk") of the message using NHPoly1305 */
static int adiantum_hash_message(struct skcipher_request *req,
- struct scatterlist *sgl, le128 *digest)
+ struct scatterlist *sgl, unsigned int nents,
+ le128 *digest)
{
- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
- const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
struct adiantum_request_ctx *rctx = skcipher_request_ctx(req);
const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE;
struct shash_desc *hash_desc = &rctx->u.hash_desc;
@@ -256,14 +255,11 @@ static int adiantum_hash_message(struct skcipher_request *req,
unsigned int i, n;
int err;
- hash_desc->tfm = tctx->hash;
-
err = crypto_shash_init(hash_desc);
if (err)
return err;
- sg_miter_start(&miter, sgl, sg_nents(sgl),
- SG_MITER_FROM_SG | SG_MITER_ATOMIC);
+ sg_miter_start(&miter, sgl, nents, SG_MITER_FROM_SG | SG_MITER_ATOMIC);
for (i = 0; i < bulk_len; i += n) {
sg_miter_next(&miter);
n = min_t(unsigned int, miter.length, bulk_len - i);
@@ -285,6 +281,8 @@ static int adiantum_finish(struct skcipher_request *req)
const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
struct adiantum_request_ctx *rctx = skcipher_request_ctx(req);
const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE;
+ struct scatterlist *dst = req->dst;
+ const unsigned int dst_nents = sg_nents(dst);
le128 digest;
int err;
@@ -298,13 +296,32 @@ static int adiantum_finish(struct skcipher_request *req)
* enc: C_R = C_M - H_{K_H}(T, C_L)
* dec: P_R = P_M - H_{K_H}(T, P_L)
*/
- err = adiantum_hash_message(req, req->dst, &digest);
- if (err)
- return err;
- le128_add(&digest, &digest, &rctx->header_hash);
- le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest);
- scatterwalk_map_and_copy(&rctx->rbuf.bignum, req->dst,
- bulk_len, BLOCKCIPHER_BLOCK_SIZE, 1);
+ rctx->u.hash_desc.tfm = tctx->hash;
+ le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash);
+ if (dst_nents == 1 && dst->offset + req->cryptlen <= PAGE_SIZE) {
+ /* Fast path for single-page destination */
+ struct page *page = sg_page(dst);
+ void *virt = kmap_local_page(page) + dst->offset;
+
+ err = crypto_shash_digest(&rctx->u.hash_desc, virt, bulk_len,
+ (u8 *)&digest);
+ if (err) {
+ kunmap_local(virt);
+ return err;
+ }
+ le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest);
+ memcpy(virt + bulk_len, &rctx->rbuf.bignum, sizeof(le128));
+ flush_dcache_page(page);
+ kunmap_local(virt);
+ } else {
+ /* Slow path that works for any destination scatterlist */
+ err = adiantum_hash_message(req, dst, dst_nents, &digest);
+ if (err)
+ return err;
+ le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest);
+ scatterwalk_map_and_copy(&rctx->rbuf.bignum, dst,
+ bulk_len, sizeof(le128), 1);
+ }
return 0;
}
@@ -324,6 +341,8 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc)
const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
struct adiantum_request_ctx *rctx = skcipher_request_ctx(req);
const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE;
+ struct scatterlist *src = req->src;
+ const unsigned int src_nents = sg_nents(src);
unsigned int stream_len;
le128 digest;
int err;
@@ -339,12 +358,24 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc)
* dec: C_M = C_R + H_{K_H}(T, C_L)
*/
adiantum_hash_header(req);
- err = adiantum_hash_message(req, req->src, &digest);
+ rctx->u.hash_desc.tfm = tctx->hash;
+ if (src_nents == 1 && src->offset + req->cryptlen <= PAGE_SIZE) {
+ /* Fast path for single-page source */
+ void *virt = kmap_local_page(sg_page(src)) + src->offset;
+
+ err = crypto_shash_digest(&rctx->u.hash_desc, virt, bulk_len,
+ (u8 *)&digest);
+ memcpy(&rctx->rbuf.bignum, virt + bulk_len, sizeof(le128));
+ kunmap_local(virt);
+ } else {
+ /* Slow path that works for any source scatterlist */
+ err = adiantum_hash_message(req, src, src_nents, &digest);
+ scatterwalk_map_and_copy(&rctx->rbuf.bignum, src,
+ bulk_len, sizeof(le128), 0);
+ }
if (err)
return err;
- le128_add(&digest, &digest, &rctx->header_hash);
- scatterwalk_map_and_copy(&rctx->rbuf.bignum, req->src,
- bulk_len, BLOCKCIPHER_BLOCK_SIZE, 0);
+ le128_add(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash);
le128_add(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest);
/* If encrypting, encrypt P_M with the block cipher to get C_M */
@@ -468,7 +499,7 @@ static void adiantum_free_instance(struct skcipher_instance *inst)
* Check for a supported set of inner algorithms.
* See the comment at the beginning of this file.
*/
-static bool adiantum_supported_algorithms(struct skcipher_alg *streamcipher_alg,
+static bool adiantum_supported_algorithms(struct skcipher_alg_common *streamcipher_alg,
struct crypto_alg *blockcipher_alg,
struct shash_alg *hash_alg)
{
@@ -494,7 +525,7 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
const char *nhpoly1305_name;
struct skcipher_instance *inst;
struct adiantum_instance_ctx *ictx;
- struct skcipher_alg *streamcipher_alg;
+ struct skcipher_alg_common *streamcipher_alg;
struct crypto_alg *blockcipher_alg;
struct shash_alg *hash_alg;
int err;
@@ -514,7 +545,7 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
crypto_attr_alg_name(tb[1]), 0, mask);
if (err)
goto err_free_inst;
- streamcipher_alg = crypto_spawn_skcipher_alg(&ictx->streamcipher_spawn);
+ streamcipher_alg = crypto_spawn_skcipher_alg_common(&ictx->streamcipher_spawn);
/* Block cipher, e.g. "aes" */
err = crypto_grab_cipher(&ictx->blockcipher_spawn,
@@ -561,8 +592,7 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
inst->alg.base.cra_blocksize = BLOCKCIPHER_BLOCK_SIZE;
inst->alg.base.cra_ctxsize = sizeof(struct adiantum_tfm_ctx);
- inst->alg.base.cra_alignmask = streamcipher_alg->base.cra_alignmask |
- hash_alg->base.cra_alignmask;
+ inst->alg.base.cra_alignmask = streamcipher_alg->base.cra_alignmask;
/*
* The block cipher is only invoked once per message, so for long
* messages (e.g. sectors for disk encryption) its performance doesn't
@@ -578,8 +608,8 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
inst->alg.decrypt = adiantum_decrypt;
inst->alg.init = adiantum_init_tfm;
inst->alg.exit = adiantum_exit_tfm;
- inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(streamcipher_alg);
- inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(streamcipher_alg);
+ inst->alg.min_keysize = streamcipher_alg->min_keysize;
+ inst->alg.max_keysize = streamcipher_alg->max_keysize;
inst->alg.ivsize = TWEAK_SIZE;
inst->free = adiantum_free_instance;
diff --git a/crypto/aead.c b/crypto/aead.c
index d5ba204ebdbf..54906633566a 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -269,6 +269,12 @@ struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)
}
EXPORT_SYMBOL_GPL(crypto_alloc_aead);
+int crypto_has_aead(const char *alg_name, u32 type, u32 mask)
+{
+ return crypto_type_has_alg(alg_name, &crypto_aead_type, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_has_aead);
+
static int aead_prepare_alg(struct aead_alg *alg)
{
struct crypto_istat_aead *istat = aead_get_stat(alg);
diff --git a/crypto/ahash.c b/crypto/ahash.c
index 709ef0940799..80c3e5354711 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -2,8 +2,12 @@
/*
* Asynchronous Cryptographic Hash operations.
*
- * This is the asynchronous version of hash.c with notification of
- * completion via a callback.
+ * This is the implementation of the ahash (asynchronous hash) API. It differs
+ * from shash (synchronous hash) in that ahash supports asynchronous operations,
+ * and it hashes data from scatterlists instead of virtually addressed buffers.
+ *
+ * The ahash API provides access to both ahash and shash algorithms. The shash
+ * API only provides access to shash algorithms.
*
* Copyright (c) 2008 Loc Ho <lho@amcc.com>
*/
@@ -21,33 +25,142 @@
#include "hash.h"
-static const struct crypto_type crypto_ahash_type;
+#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000e
-struct ahash_request_priv {
- crypto_completion_t complete;
- void *data;
- u8 *result;
- u32 flags;
- void *ubuf[] CRYPTO_MINALIGN_ATTR;
-};
+static inline struct crypto_istat_hash *ahash_get_stat(struct ahash_alg *alg)
+{
+ return hash_get_stat(&alg->halg);
+}
+
+static inline int crypto_ahash_errstat(struct ahash_alg *alg, int err)
+{
+ if (!IS_ENABLED(CONFIG_CRYPTO_STATS))
+ return err;
+
+ if (err && err != -EINPROGRESS && err != -EBUSY)
+ atomic64_inc(&ahash_get_stat(alg)->err_cnt);
+
+ return err;
+}
+
+/*
+ * For an ahash tfm that is using an shash algorithm (instead of an ahash
+ * algorithm), this returns the underlying shash tfm.
+ */
+static inline struct crypto_shash *ahash_to_shash(struct crypto_ahash *tfm)
+{
+ return *(struct crypto_shash **)crypto_ahash_ctx(tfm);
+}
+
+static inline struct shash_desc *prepare_shash_desc(struct ahash_request *req,
+ struct crypto_ahash *tfm)
+{
+ struct shash_desc *desc = ahash_request_ctx(req);
+
+ desc->tfm = ahash_to_shash(tfm);
+ return desc;
+}
+
+int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc)
+{
+ struct crypto_hash_walk walk;
+ int nbytes;
+
+ for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0;
+ nbytes = crypto_hash_walk_done(&walk, nbytes))
+ nbytes = crypto_shash_update(desc, walk.data, nbytes);
+
+ return nbytes;
+}
+EXPORT_SYMBOL_GPL(shash_ahash_update);
+
+int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc)
+{
+ struct crypto_hash_walk walk;
+ int nbytes;
+
+ nbytes = crypto_hash_walk_first(req, &walk);
+ if (!nbytes)
+ return crypto_shash_final(desc, req->result);
+
+ do {
+ nbytes = crypto_hash_walk_last(&walk) ?
+ crypto_shash_finup(desc, walk.data, nbytes,
+ req->result) :
+ crypto_shash_update(desc, walk.data, nbytes);
+ nbytes = crypto_hash_walk_done(&walk, nbytes);
+ } while (nbytes > 0);
+
+ return nbytes;
+}
+EXPORT_SYMBOL_GPL(shash_ahash_finup);
+
+int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc)
+{
+ unsigned int nbytes = req->nbytes;
+ struct scatterlist *sg;
+ unsigned int offset;
+ int err;
+
+ if (nbytes &&
+ (sg = req->src, offset = sg->offset,
+ nbytes <= min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) {
+ void *data;
+
+ data = kmap_local_page(sg_page(sg));
+ err = crypto_shash_digest(desc, data + offset, nbytes,
+ req->result);
+ kunmap_local(data);
+ } else
+ err = crypto_shash_init(desc) ?:
+ shash_ahash_finup(req, desc);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(shash_ahash_digest);
+
+static void crypto_exit_ahash_using_shash(struct crypto_tfm *tfm)
+{
+ struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_shash(*ctx);
+}
+
+static int crypto_init_ahash_using_shash(struct crypto_tfm *tfm)
+{
+ struct crypto_alg *calg = tfm->__crt_alg;
+ struct crypto_ahash *crt = __crypto_ahash_cast(tfm);
+ struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
+ struct crypto_shash *shash;
+
+ if (!crypto_mod_get(calg))
+ return -EAGAIN;
+
+ shash = crypto_create_tfm(calg, &crypto_shash_type);
+ if (IS_ERR(shash)) {
+ crypto_mod_put(calg);
+ return PTR_ERR(shash);
+ }
+
+ crt->using_shash = true;
+ *ctx = shash;
+ tfm->exit = crypto_exit_ahash_using_shash;
+
+ crypto_ahash_set_flags(crt, crypto_shash_get_flags(shash) &
+ CRYPTO_TFM_NEED_KEY);
+ crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash);
+
+ return 0;
+}
static int hash_walk_next(struct crypto_hash_walk *walk)
{
- unsigned int alignmask = walk->alignmask;
unsigned int offset = walk->offset;
unsigned int nbytes = min(walk->entrylen,
((unsigned int)(PAGE_SIZE)) - offset);
walk->data = kmap_local_page(walk->pg);
walk->data += offset;
-
- if (offset & alignmask) {
- unsigned int unaligned = alignmask + 1 - (offset & alignmask);
-
- if (nbytes > unaligned)
- nbytes = unaligned;
- }
-
walk->entrylen -= nbytes;
return nbytes;
}
@@ -71,23 +184,8 @@ static int hash_walk_new_entry(struct crypto_hash_walk *walk)
int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
{
- unsigned int alignmask = walk->alignmask;
-
walk->data -= walk->offset;
- if (walk->entrylen && (walk->offset & alignmask) && !err) {
- unsigned int nbytes;
-
- walk->offset = ALIGN(walk->offset, alignmask + 1);
- nbytes = min(walk->entrylen,
- (unsigned int)(PAGE_SIZE - walk->offset));
- if (nbytes) {
- walk->entrylen -= nbytes;
- walk->data += walk->offset;
- return nbytes;
- }
- }
-
kunmap_local(walk->data);
crypto_yield(walk->flags);
@@ -119,7 +217,6 @@ int crypto_hash_walk_first(struct ahash_request *req,
return 0;
}
- walk->alignmask = crypto_ahash_alignmask(crypto_ahash_reqtfm(req));
walk->sg = req->src;
walk->flags = req->base.flags;
@@ -127,67 +224,64 @@ int crypto_hash_walk_first(struct ahash_request *req,
}
EXPORT_SYMBOL_GPL(crypto_hash_walk_first);
-static int ahash_setkey_unaligned(struct crypto_ahash *tfm, const u8 *key,
- unsigned int keylen)
-{
- unsigned long alignmask = crypto_ahash_alignmask(tfm);
- int ret;
- u8 *buffer, *alignbuffer;
- unsigned long absize;
-
- absize = keylen + alignmask;
- buffer = kmalloc(absize, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
- memcpy(alignbuffer, key, keylen);
- ret = tfm->setkey(tfm, alignbuffer, keylen);
- kfree_sensitive(buffer);
- return ret;
-}
-
static int ahash_nosetkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen)
{
return -ENOSYS;
}
-static void ahash_set_needkey(struct crypto_ahash *tfm)
+static void ahash_set_needkey(struct crypto_ahash *tfm, struct ahash_alg *alg)
{
- const struct hash_alg_common *alg = crypto_hash_alg_common(tfm);
-
- if (tfm->setkey != ahash_nosetkey &&
- !(alg->base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY))
+ if (alg->setkey != ahash_nosetkey &&
+ !(alg->halg.base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY))
crypto_ahash_set_flags(tfm, CRYPTO_TFM_NEED_KEY);
}
int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen)
{
- unsigned long alignmask = crypto_ahash_alignmask(tfm);
- int err;
+ if (likely(tfm->using_shash)) {
+ struct crypto_shash *shash = ahash_to_shash(tfm);
+ int err;
- if ((unsigned long)key & alignmask)
- err = ahash_setkey_unaligned(tfm, key, keylen);
- else
- err = tfm->setkey(tfm, key, keylen);
-
- if (unlikely(err)) {
- ahash_set_needkey(tfm);
- return err;
+ err = crypto_shash_setkey(shash, key, keylen);
+ if (unlikely(err)) {
+ crypto_ahash_set_flags(tfm,
+ crypto_shash_get_flags(shash) &
+ CRYPTO_TFM_NEED_KEY);
+ return err;
+ }
+ } else {
+ struct ahash_alg *alg = crypto_ahash_alg(tfm);
+ int err;
+
+ err = alg->setkey(tfm, key, keylen);
+ if (unlikely(err)) {
+ ahash_set_needkey(tfm, alg);
+ return err;
+ }
}
-
crypto_ahash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
return 0;
}
EXPORT_SYMBOL_GPL(crypto_ahash_setkey);
+int crypto_ahash_init(struct ahash_request *req)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+
+ if (likely(tfm->using_shash))
+ return crypto_shash_init(prepare_shash_desc(req, tfm));
+ if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
+ return -ENOKEY;
+ return crypto_ahash_alg(tfm)->init(req);
+}
+EXPORT_SYMBOL_GPL(crypto_ahash_init);
+
static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt,
bool has_state)
{
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- unsigned long alignmask = crypto_ahash_alignmask(tfm);
unsigned int ds = crypto_ahash_digestsize(tfm);
struct ahash_request *subreq;
unsigned int subreq_size;
@@ -201,7 +295,6 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt,
reqsize = ALIGN(reqsize, crypto_tfm_ctx_alignment());
subreq_size += reqsize;
subreq_size += ds;
- subreq_size += alignmask & ~(crypto_tfm_ctx_alignment() - 1);
flags = ahash_request_flags(req);
gfp = (flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC;
@@ -213,7 +306,6 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt,
ahash_request_set_callback(subreq, flags, cplt, req);
result = (u8 *)(subreq + 1) + reqsize;
- result = PTR_ALIGN(result, alignmask + 1);
ahash_request_set_crypt(subreq, req->src, result, req->nbytes);
@@ -249,100 +341,78 @@ static void ahash_restore_req(struct ahash_request *req, int err)
kfree_sensitive(subreq);
}
-static void ahash_op_unaligned_done(void *data, int err)
-{
- struct ahash_request *areq = data;
-
- if (err == -EINPROGRESS)
- goto out;
-
- /* First copy req->result into req->priv.result */
- ahash_restore_req(areq, err);
-
-out:
- /* Complete the ORIGINAL request. */
- ahash_request_complete(areq, err);
-}
-
-static int ahash_op_unaligned(struct ahash_request *req,
- int (*op)(struct ahash_request *),
- bool has_state)
-{
- int err;
-
- err = ahash_save_req(req, ahash_op_unaligned_done, has_state);
- if (err)
- return err;
-
- err = op(req->priv);
- if (err == -EINPROGRESS || err == -EBUSY)
- return err;
-
- ahash_restore_req(req, err);
-
- return err;
-}
-
-static int crypto_ahash_op(struct ahash_request *req,
- int (*op)(struct ahash_request *),
- bool has_state)
+int crypto_ahash_update(struct ahash_request *req)
{
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- unsigned long alignmask = crypto_ahash_alignmask(tfm);
- int err;
+ struct ahash_alg *alg;
- if ((unsigned long)req->result & alignmask)
- err = ahash_op_unaligned(req, op, has_state);
- else
- err = op(req);
+ if (likely(tfm->using_shash))
+ return shash_ahash_update(req, ahash_request_ctx(req));
- return crypto_hash_errstat(crypto_hash_alg_common(tfm), err);
+ alg = crypto_ahash_alg(tfm);
+ if (IS_ENABLED(CONFIG_CRYPTO_STATS))
+ atomic64_add(req->nbytes, &ahash_get_stat(alg)->hash_tlen);
+ return crypto_ahash_errstat(alg, alg->update(req));
}
+EXPORT_SYMBOL_GPL(crypto_ahash_update);
int crypto_ahash_final(struct ahash_request *req)
{
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- struct hash_alg_common *alg = crypto_hash_alg_common(tfm);
+ struct ahash_alg *alg;
- if (IS_ENABLED(CONFIG_CRYPTO_STATS))
- atomic64_inc(&hash_get_stat(alg)->hash_cnt);
+ if (likely(tfm->using_shash))
+ return crypto_shash_final(ahash_request_ctx(req), req->result);
- return crypto_ahash_op(req, tfm->final, true);
+ alg = crypto_ahash_alg(tfm);
+ if (IS_ENABLED(CONFIG_CRYPTO_STATS))
+ atomic64_inc(&ahash_get_stat(alg)->hash_cnt);
+ return crypto_ahash_errstat(alg, alg->final(req));
}
EXPORT_SYMBOL_GPL(crypto_ahash_final);
int crypto_ahash_finup(struct ahash_request *req)
{
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- struct hash_alg_common *alg = crypto_hash_alg_common(tfm);
+ struct ahash_alg *alg;
+
+ if (likely(tfm->using_shash))
+ return shash_ahash_finup(req, ahash_request_ctx(req));
+ alg = crypto_ahash_alg(tfm);
if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
- struct crypto_istat_hash *istat = hash_get_stat(alg);
+ struct crypto_istat_hash *istat = ahash_get_stat(alg);
atomic64_inc(&istat->hash_cnt);
atomic64_add(req->nbytes, &istat->hash_tlen);
}
-
- return crypto_ahash_op(req, tfm->finup, true);
+ return crypto_ahash_errstat(alg, alg->finup(req));
}
EXPORT_SYMBOL_GPL(crypto_ahash_finup);
int crypto_ahash_digest(struct ahash_request *req)
{
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- struct hash_alg_common *alg = crypto_hash_alg_common(tfm);
+ struct ahash_alg *alg;
+ int err;
+
+ if (likely(tfm->using_shash))
+ return shash_ahash_digest(req, prepare_shash_desc(req, tfm));
+ alg = crypto_ahash_alg(tfm);
if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
- struct crypto_istat_hash *istat = hash_get_stat(alg);
+ struct crypto_istat_hash *istat = ahash_get_stat(alg);
atomic64_inc(&istat->hash_cnt);
atomic64_add(req->nbytes, &istat->hash_tlen);
}
if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
- return crypto_hash_errstat(alg, -ENOKEY);
+ err = -ENOKEY;
+ else
+ err = alg->digest(req);
- return crypto_ahash_op(req, tfm->digest, false);
+ return crypto_ahash_errstat(alg, err);
}
EXPORT_SYMBOL_GPL(crypto_ahash_digest);
@@ -367,7 +437,7 @@ static int ahash_def_finup_finish1(struct ahash_request *req, int err)
subreq->base.complete = ahash_def_finup_done2;
- err = crypto_ahash_reqtfm(req)->final(subreq);
+ err = crypto_ahash_alg(crypto_ahash_reqtfm(req))->final(subreq);
if (err == -EINPROGRESS || err == -EBUSY)
return err;
@@ -404,13 +474,35 @@ static int ahash_def_finup(struct ahash_request *req)
if (err)
return err;
- err = tfm->update(req->priv);
+ err = crypto_ahash_alg(tfm)->update(req->priv);
if (err == -EINPROGRESS || err == -EBUSY)
return err;
return ahash_def_finup_finish1(req, err);
}
+int crypto_ahash_export(struct ahash_request *req, void *out)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+
+ if (likely(tfm->using_shash))
+ return crypto_shash_export(ahash_request_ctx(req), out);
+ return crypto_ahash_alg(tfm)->export(req, out);
+}
+EXPORT_SYMBOL_GPL(crypto_ahash_export);
+
+int crypto_ahash_import(struct ahash_request *req, const void *in)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+
+ if (likely(tfm->using_shash))
+ return crypto_shash_import(prepare_shash_desc(req, tfm), in);
+ if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
+ return -ENOKEY;
+ return crypto_ahash_alg(tfm)->import(req, in);
+}
+EXPORT_SYMBOL_GPL(crypto_ahash_import);
+
static void crypto_ahash_exit_tfm(struct crypto_tfm *tfm)
{
struct crypto_ahash *hash = __crypto_ahash_cast(tfm);
@@ -424,25 +516,12 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm)
struct crypto_ahash *hash = __crypto_ahash_cast(tfm);
struct ahash_alg *alg = crypto_ahash_alg(hash);
- hash->setkey = ahash_nosetkey;
-
crypto_ahash_set_statesize(hash, alg->halg.statesize);
- if (tfm->__crt_alg->cra_type != &crypto_ahash_type)
- return crypto_init_shash_ops_async(tfm);
+ if (tfm->__crt_alg->cra_type == &crypto_shash_type)
+ return crypto_init_ahash_using_shash(tfm);
- hash->init = alg->init;
- hash->update = alg->update;
- hash->final = alg->final;
- hash->finup = alg->finup ?: ahash_def_finup;
- hash->digest = alg->digest;
- hash->export = alg->export;
- hash->import = alg->import;
-
- if (alg->setkey) {
- hash->setkey = alg->setkey;
- ahash_set_needkey(hash);
- }
+ ahash_set_needkey(hash, alg);
if (alg->exit_tfm)
tfm->exit = crypto_ahash_exit_tfm;
@@ -452,7 +531,7 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm)
static unsigned int crypto_ahash_extsize(struct crypto_alg *alg)
{
- if (alg->cra_type != &crypto_ahash_type)
+ if (alg->cra_type == &crypto_shash_type)
return sizeof(struct crypto_shash *);
return crypto_alg_extsize(alg);
@@ -560,19 +639,22 @@ struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *hash)
if (IS_ERR(nhash))
return nhash;
- nhash->init = hash->init;
- nhash->update = hash->update;
- nhash->final = hash->final;
- nhash->finup = hash->finup;
- nhash->digest = hash->digest;
- nhash->export = hash->export;
- nhash->import = hash->import;
- nhash->setkey = hash->setkey;
nhash->reqsize = hash->reqsize;
nhash->statesize = hash->statesize;
- if (tfm->__crt_alg->cra_type != &crypto_ahash_type)
- return crypto_clone_shash_ops_async(nhash, hash);
+ if (likely(hash->using_shash)) {
+ struct crypto_shash **nctx = crypto_ahash_ctx(nhash);
+ struct crypto_shash *shash;
+
+ shash = crypto_clone_shash(ahash_to_shash(hash));
+ if (IS_ERR(shash)) {
+ err = PTR_ERR(shash);
+ goto out_free_nhash;
+ }
+ nhash->using_shash = true;
+ *nctx = shash;
+ return nhash;
+ }
err = -ENOSYS;
alg = crypto_ahash_alg(hash);
@@ -606,6 +688,11 @@ static int ahash_prepare_alg(struct ahash_alg *alg)
base->cra_type = &crypto_ahash_type;
base->cra_flags |= CRYPTO_ALG_TYPE_AHASH;
+ if (!alg->finup)
+ alg->finup = ahash_def_finup;
+ if (!alg->setkey)
+ alg->setkey = ahash_nosetkey;
+
return 0;
}
@@ -677,10 +764,10 @@ bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg)
{
struct crypto_alg *alg = &halg->base;
- if (alg->cra_type != &crypto_ahash_type)
+ if (alg->cra_type == &crypto_shash_type)
return crypto_shash_alg_has_setkey(__crypto_shash_alg(alg));
- return __crypto_ahash_alg(alg)->setkey != NULL;
+ return __crypto_ahash_alg(alg)->setkey != ahash_nosetkey;
}
EXPORT_SYMBOL_GPL(crypto_hash_alg_has_setkey);
diff --git a/crypto/api.c b/crypto/api.c
index b9cc0c906efe..7f402107f0cc 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -389,7 +389,7 @@ EXPORT_SYMBOL_GPL(crypto_shoot_alg);
struct crypto_tfm *__crypto_alloc_tfmgfp(struct crypto_alg *alg, u32 type,
u32 mask, gfp_t gfp)
{
- struct crypto_tfm *tfm = NULL;
+ struct crypto_tfm *tfm;
unsigned int tfm_size;
int err = -ENOMEM;
diff --git a/crypto/arc4.c b/crypto/arc4.c
index 3254dcc34368..eb3590dc9282 100644
--- a/crypto/arc4.c
+++ b/crypto/arc4.c
@@ -7,7 +7,6 @@
* Jon Oberheide <jon@oberheide.org>
*/
-#include <crypto/algapi.h>
#include <crypto/arc4.h>
#include <crypto/internal/skcipher.h>
#include <linux/init.h>
@@ -15,33 +14,24 @@
#include <linux/module.h>
#include <linux/sched.h>
-static int crypto_arc4_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
+static int crypto_arc4_setkey(struct crypto_lskcipher *tfm, const u8 *in_key,
unsigned int key_len)
{
- struct arc4_ctx *ctx = crypto_skcipher_ctx(tfm);
+ struct arc4_ctx *ctx = crypto_lskcipher_ctx(tfm);
return arc4_setkey(ctx, in_key, key_len);
}
-static int crypto_arc4_crypt(struct skcipher_request *req)
+static int crypto_arc4_crypt(struct crypto_lskcipher *tfm, const u8 *src,
+ u8 *dst, unsigned nbytes, u8 *iv, bool final)
{
- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
- struct arc4_ctx *ctx = crypto_skcipher_ctx(tfm);
- struct skcipher_walk walk;
- int err;
+ struct arc4_ctx *ctx = crypto_lskcipher_ctx(tfm);
- err = skcipher_walk_virt(&walk, req, false);
-
- while (walk.nbytes > 0) {
- arc4_crypt(ctx, walk.dst.virt.addr, walk.src.virt.addr,
- walk.nbytes);
- err = skcipher_walk_done(&walk, 0);
- }
-
- return err;
+ arc4_crypt(ctx, dst, src, nbytes);
+ return 0;
}
-static int crypto_arc4_init(struct crypto_skcipher *tfm)
+static int crypto_arc4_init(struct crypto_lskcipher *tfm)
{
pr_warn_ratelimited("\"%s\" (%ld) uses obsolete ecb(arc4) skcipher\n",
current->comm, (unsigned long)current->pid);
@@ -49,33 +39,29 @@ static int crypto_arc4_init(struct crypto_skcipher *tfm)
return 0;
}
-static struct skcipher_alg arc4_alg = {
- /*
- * For legacy reasons, this is named "ecb(arc4)", not "arc4".
- * Nevertheless it's actually a stream cipher, not a block cipher.
- */
- .base.cra_name = "ecb(arc4)",
- .base.cra_driver_name = "ecb(arc4)-generic",
- .base.cra_priority = 100,
- .base.cra_blocksize = ARC4_BLOCK_SIZE,
- .base.cra_ctxsize = sizeof(struct arc4_ctx),
- .base.cra_module = THIS_MODULE,
- .min_keysize = ARC4_MIN_KEY_SIZE,
- .max_keysize = ARC4_MAX_KEY_SIZE,
- .setkey = crypto_arc4_setkey,
- .encrypt = crypto_arc4_crypt,
- .decrypt = crypto_arc4_crypt,
- .init = crypto_arc4_init,
+static struct lskcipher_alg arc4_alg = {
+ .co.base.cra_name = "arc4",
+ .co.base.cra_driver_name = "arc4-generic",
+ .co.base.cra_priority = 100,
+ .co.base.cra_blocksize = ARC4_BLOCK_SIZE,
+ .co.base.cra_ctxsize = sizeof(struct arc4_ctx),
+ .co.base.cra_module = THIS_MODULE,
+ .co.min_keysize = ARC4_MIN_KEY_SIZE,
+ .co.max_keysize = ARC4_MAX_KEY_SIZE,
+ .setkey = crypto_arc4_setkey,
+ .encrypt = crypto_arc4_crypt,
+ .decrypt = crypto_arc4_crypt,
+ .init = crypto_arc4_init,
};
static int __init arc4_init(void)
{
- return crypto_register_skcipher(&arc4_alg);
+ return crypto_register_lskcipher(&arc4_alg);
}
static void __exit arc4_exit(void)
{
- crypto_unregister_skcipher(&arc4_alg);
+ crypto_unregister_lskcipher(&arc4_alg);
}
subsys_initcall(arc4_init);
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 1ef3b46d6f6e..59ec726b7c77 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -76,7 +76,7 @@ config SIGNED_PE_FILE_VERIFICATION
signed PE binary.
config FIPS_SIGNATURE_SELFTEST
- bool "Run FIPS selftests on the X.509+PKCS7 signature verification"
+ tristate "Run FIPS selftests on the X.509+PKCS7 signature verification"
help
This option causes some selftests to be run on the signature
verification code, using some built in data. This is required
@@ -84,5 +84,6 @@ config FIPS_SIGNATURE_SELFTEST
depends on KEYS
depends on ASYMMETRIC_KEY_TYPE
depends on PKCS7_MESSAGE_PARSER=X509_CERTIFICATE_PARSER
+ depends on X509_CERTIFICATE_PARSER
endif # ASYMMETRIC_KEY_TYPE
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index 0d1fa1b692c6..1a273d6df3eb 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -22,7 +22,8 @@ x509_key_parser-y := \
x509_cert_parser.o \
x509_loader.o \
x509_public_key.o
-x509_key_parser-$(CONFIG_FIPS_SIGNATURE_SELFTEST) += selftest.o
+obj-$(CONFIG_FIPS_SIGNATURE_SELFTEST) += x509_selftest.o
+x509_selftest-y += selftest.o
$(obj)/x509_cert_parser.o: \
$(obj)/x509.asn1.h \
diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c
index 839591ad21ac..05402ef8964e 100644
--- a/crypto/asymmetric_keys/mscode_parser.c
+++ b/crypto/asymmetric_keys/mscode_parser.c
@@ -75,15 +75,6 @@ int mscode_note_digest_algo(void *context, size_t hdrlen,
oid = look_up_OID(value, vlen);
switch (oid) {
- case OID_md4:
- ctx->digest_algo = "md4";
- break;
- case OID_md5:
- ctx->digest_algo = "md5";
- break;
- case OID_sha1:
- ctx->digest_algo = "sha1";
- break;
case OID_sha256:
ctx->digest_algo = "sha256";
break;
@@ -93,8 +84,14 @@ int mscode_note_digest_algo(void *context, size_t hdrlen,
case OID_sha512:
ctx->digest_algo = "sha512";
break;
- case OID_sha224:
- ctx->digest_algo = "sha224";
+ case OID_sha3_256:
+ ctx->digest_algo = "sha3-256";
+ break;
+ case OID_sha3_384:
+ ctx->digest_algo = "sha3-384";
+ break;
+ case OID_sha3_512:
+ ctx->digest_algo = "sha3-512";
break;
case OID__NR:
diff --git a/crypto/asymmetric_keys/pkcs7.asn1 b/crypto/asymmetric_keys/pkcs7.asn1
index 1eca740b816a..28e1f4a41c14 100644
--- a/crypto/asymmetric_keys/pkcs7.asn1
+++ b/crypto/asymmetric_keys/pkcs7.asn1
@@ -1,3 +1,10 @@
+-- SPDX-License-Identifier: BSD-3-Clause
+--
+-- Copyright (C) 2009 IETF Trust and the persons identified as authors
+-- of the code
+--
+-- https://www.rfc-editor.org/rfc/rfc5652#section-3
+
PKCS7ContentInfo ::= SEQUENCE {
contentType ContentType ({ pkcs7_check_content_type }),
content [0] EXPLICIT SignedData OPTIONAL
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index 277482bb1777..5b08c50722d0 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -227,15 +227,6 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
struct pkcs7_parse_context *ctx = context;
switch (ctx->last_oid) {
- case OID_md4:
- ctx->sinfo->sig->hash_algo = "md4";
- break;
- case OID_md5:
- ctx->sinfo->sig->hash_algo = "md5";
- break;
- case OID_sha1:
- ctx->sinfo->sig->hash_algo = "sha1";
- break;
case OID_sha256:
ctx->sinfo->sig->hash_algo = "sha256";
break;
@@ -257,6 +248,15 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
case OID_gost2012Digest512:
ctx->sinfo->sig->hash_algo = "streebog512";
break;
+ case OID_sha3_256:
+ ctx->sinfo->sig->hash_algo = "sha3-256";
+ break;
+ case OID_sha3_384:
+ ctx->sinfo->sig->hash_algo = "sha3-384";
+ break;
+ case OID_sha3_512:
+ ctx->sinfo->sig->hash_algo = "sha3-512";
+ break;
default:
printk("Unsupported digest algo: %u\n", ctx->last_oid);
return -ENOPKG;
@@ -278,11 +278,13 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
ctx->sinfo->sig->pkey_algo = "rsa";
ctx->sinfo->sig->encoding = "pkcs1";
break;
- case OID_id_ecdsa_with_sha1:
case OID_id_ecdsa_with_sha224:
case OID_id_ecdsa_with_sha256:
case OID_id_ecdsa_with_sha384:
case OID_id_ecdsa_with_sha512:
+ case OID_id_ecdsa_with_sha3_256:
+ case OID_id_ecdsa_with_sha3_384:
+ case OID_id_ecdsa_with_sha3_512:
ctx->sinfo->sig->pkey_algo = "ecdsa";
ctx->sinfo->sig->encoding = "x962";
break;
diff --git a/crypto/asymmetric_keys/pkcs8.asn1 b/crypto/asymmetric_keys/pkcs8.asn1
index 702c41a3c713..a2a8af2633d8 100644
--- a/crypto/asymmetric_keys/pkcs8.asn1
+++ b/crypto/asymmetric_keys/pkcs8.asn1
@@ -1,3 +1,9 @@
+-- SPDX-License-Identifier: BSD-3-Clause
+--
+-- Copyright (C) 2010 IETF Trust and the persons identified as authors
+-- of the code
+--
+-- https://www.rfc-editor.org/rfc/rfc5958#section-2
--
-- This is the unencrypted variant
--
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index abeecb8329b3..e5f22691febd 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -81,14 +81,13 @@ software_key_determine_akcipher(const struct public_key *pkey,
* RSA signatures usually use EMSA-PKCS1-1_5 [RFC3447 sec 8.2].
*/
if (strcmp(encoding, "pkcs1") == 0) {
+ *sig = op == kernel_pkey_sign ||
+ op == kernel_pkey_verify;
if (!hash_algo) {
- *sig = false;
n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
"pkcs1pad(%s)",
pkey->pkey_algo);
} else {
- *sig = op == kernel_pkey_sign ||
- op == kernel_pkey_verify;
n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
"pkcs1pad(%s,%s)",
pkey->pkey_algo, hash_algo);
@@ -116,11 +115,13 @@ software_key_determine_akcipher(const struct public_key *pkey,
*/
if (!hash_algo)
return -EINVAL;
- if (strcmp(hash_algo, "sha1") != 0 &&
- strcmp(hash_algo, "sha224") != 0 &&
+ if (strcmp(hash_algo, "sha224") != 0 &&
strcmp(hash_algo, "sha256") != 0 &&
strcmp(hash_algo, "sha384") != 0 &&
- strcmp(hash_algo, "sha512") != 0)
+ strcmp(hash_algo, "sha512") != 0 &&
+ strcmp(hash_algo, "sha3-256") != 0 &&
+ strcmp(hash_algo, "sha3-384") != 0 &&
+ strcmp(hash_algo, "sha3-512") != 0)
return -EINVAL;
} else if (strcmp(pkey->pkey_algo, "sm2") == 0) {
if (strcmp(encoding, "raw") != 0)
diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c
index 6b69ea40da23..afcd4d101ac5 100644
--- a/crypto/asymmetric_keys/restrict.c
+++ b/crypto/asymmetric_keys/restrict.c
@@ -102,6 +102,10 @@ int restrict_link_by_signature(struct key *dest_keyring,
if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags))
ret = -ENOKEY;
+ else if (IS_BUILTIN(CONFIG_SECONDARY_TRUSTED_KEYRING_SIGNED_BY_BUILTIN) &&
+ !strcmp(dest_keyring->description, ".secondary_trusted_keys") &&
+ !test_bit(KEY_FLAG_BUILTIN, &key->flags))
+ ret = -ENOKEY;
else
ret = verify_signature(key, sig);
key_put(key);
diff --git a/crypto/asymmetric_keys/selftest.c b/crypto/asymmetric_keys/selftest.c
index fa0bf7f24284..c50da7ef90ae 100644
--- a/crypto/asymmetric_keys/selftest.c
+++ b/crypto/asymmetric_keys/selftest.c
@@ -4,10 +4,11 @@
* Written by David Howells (dhowells@redhat.com)
*/
-#include <linux/kernel.h>
+#include <crypto/pkcs7.h>
#include <linux/cred.h>
+#include <linux/kernel.h>
#include <linux/key.h>
-#include <crypto/pkcs7.h>
+#include <linux/module.h>
#include "x509_parser.h"
struct certs_test {
@@ -175,7 +176,7 @@ static const struct certs_test certs_tests[] __initconst = {
TEST(certs_selftest_1_data, certs_selftest_1_pkcs7),
};
-int __init fips_signature_selftest(void)
+static int __init fips_signature_selftest(void)
{
struct key *keyring;
int ret, i;
@@ -222,3 +223,9 @@ int __init fips_signature_selftest(void)
key_put(keyring);
return 0;
}
+
+late_initcall(fips_signature_selftest);
+
+MODULE_DESCRIPTION("X.509 self tests");
+MODULE_AUTHOR("Red Hat, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c
index 2deff81f8af5..398983be77e8 100644
--- a/crypto/asymmetric_keys/signature.c
+++ b/crypto/asymmetric_keys/signature.c
@@ -115,7 +115,7 @@ EXPORT_SYMBOL_GPL(decrypt_blob);
* Sign the specified data blob using the private key specified by params->key.
* The signature is wrapped in an encoding if params->encoding is specified
* (eg. "pkcs1"). If the encoding needs to know the digest type, this can be
- * passed through params->hash_algo (eg. "sha1").
+ * passed through params->hash_algo (eg. "sha512").
*
* Returns the length of the data placed in the signature buffer or an error.
*/
diff --git a/crypto/asymmetric_keys/x509.asn1 b/crypto/asymmetric_keys/x509.asn1
index 92d59c32f96a..feb9573cacce 100644
--- a/crypto/asymmetric_keys/x509.asn1
+++ b/crypto/asymmetric_keys/x509.asn1
@@ -1,3 +1,10 @@
+-- SPDX-License-Identifier: BSD-3-Clause
+--
+-- Copyright (C) 2008 IETF Trust and the persons identified as authors
+-- of the code
+--
+-- https://www.rfc-editor.org/rfc/rfc5280#section-4
+
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate ({ x509_note_tbs_certificate }),
signatureAlgorithm AlgorithmIdentifier,
diff --git a/crypto/asymmetric_keys/x509_akid.asn1 b/crypto/asymmetric_keys/x509_akid.asn1
index 1a33231a75a8..0f8355cf1907 100644
--- a/crypto/asymmetric_keys/x509_akid.asn1
+++ b/crypto/asymmetric_keys/x509_akid.asn1
@@ -1,3 +1,8 @@
+-- SPDX-License-Identifier: BSD-3-Clause
+--
+-- Copyright (C) 2008 IETF Trust and the persons identified as authors
+-- of the code
+--
-- X.509 AuthorityKeyIdentifier
-- rfc5280 section 4.2.1.1
@@ -14,15 +19,15 @@ CertificateSerialNumber ::= INTEGER ({ x509_akid_note_serial })
GeneralNames ::= SEQUENCE OF GeneralName
GeneralName ::= CHOICE {
- otherName [0] ANY,
- rfc822Name [1] IA5String,
- dNSName [2] IA5String,
+ otherName [0] IMPLICIT OtherName,
+ rfc822Name [1] IMPLICIT IA5String,
+ dNSName [2] IMPLICIT IA5String,
x400Address [3] ANY,
directoryName [4] Name ({ x509_akid_note_name }),
- ediPartyName [5] ANY,
- uniformResourceIdentifier [6] IA5String,
- iPAddress [7] OCTET STRING,
- registeredID [8] OBJECT IDENTIFIER
+ ediPartyName [5] IMPLICIT EDIPartyName,
+ uniformResourceIdentifier [6] IMPLICIT IA5String,
+ iPAddress [7] IMPLICIT OCTET STRING,
+ registeredID [8] IMPLICIT OBJECT IDENTIFIER
}
Name ::= SEQUENCE OF RelativeDistinguishedName
@@ -33,3 +38,13 @@ AttributeValueAssertion ::= SEQUENCE {
attributeType OBJECT IDENTIFIER ({ x509_note_OID }),
attributeValue ANY ({ x509_extract_name_segment })
}
+
+OtherName ::= SEQUENCE {
+ type-id OBJECT IDENTIFIER,
+ value [0] ANY
+ }
+
+EDIPartyName ::= SEQUENCE {
+ nameAssigner [0] ANY OPTIONAL,
+ partyName [1] ANY
+ }
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index 0a7049b470c1..487204d39426 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -195,19 +195,9 @@ int x509_note_sig_algo(void *context, size_t hdrlen, unsigned char tag,
pr_debug("PubKey Algo: %u\n", ctx->last_oid);
switch (ctx->last_oid) {
- case OID_md2WithRSAEncryption:
- case OID_md3WithRSAEncryption:
default:
return -ENOPKG; /* Unsupported combination */
- case OID_md4WithRSAEncryption:
- ctx->cert->sig->hash_algo = "md4";
- goto rsa_pkcs1;
-
- case OID_sha1WithRSAEncryption:
- ctx->cert->sig->hash_algo = "sha1";
- goto rsa_pkcs1;
-
case OID_sha256WithRSAEncryption:
ctx->cert->sig->hash_algo = "sha256";
goto rsa_pkcs1;
@@ -224,9 +214,17 @@ int x509_note_sig_algo(void *context, size_t hdrlen, unsigned char tag,
ctx->cert->sig->hash_algo = "sha224";
goto rsa_pkcs1;
- case OID_id_ecdsa_with_sha1:
- ctx->cert->sig->hash_algo = "sha1";
- goto ecdsa;
+ case OID_id_rsassa_pkcs1_v1_5_with_sha3_256:
+ ctx->cert->sig->hash_algo = "sha3-256";
+ goto rsa_pkcs1;
+
+ case OID_id_rsassa_pkcs1_v1_5_with_sha3_384:
+ ctx->cert->sig->hash_algo = "sha3-384";
+ goto rsa_pkcs1;
+
+ case OID_id_rsassa_pkcs1_v1_5_with_sha3_512:
+ ctx->cert->sig->hash_algo = "sha3-512";
+ goto rsa_pkcs1;
case OID_id_ecdsa_with_sha224:
ctx->cert->sig->hash_algo = "sha224";
@@ -244,6 +242,18 @@ int x509_note_sig_algo(void *context, size_t hdrlen, unsigned char tag,
ctx->cert->sig->hash_algo = "sha512";
goto ecdsa;
+ case OID_id_ecdsa_with_sha3_256:
+ ctx->cert->sig->hash_algo = "sha3-256";
+ goto ecdsa;
+
+ case OID_id_ecdsa_with_sha3_384:
+ ctx->cert->sig->hash_algo = "sha3-384";
+ goto ecdsa;
+
+ case OID_id_ecdsa_with_sha3_512:
+ ctx->cert->sig->hash_algo = "sha3-512";
+ goto ecdsa;
+
case OID_gost2012Signature256:
ctx->cert->sig->hash_algo = "streebog256";
goto ecrdsa;
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
index a299c9c56f40..97a886cbe01c 100644
--- a/crypto/asymmetric_keys/x509_parser.h
+++ b/crypto/asymmetric_keys/x509_parser.h
@@ -41,15 +41,6 @@ struct x509_certificate {
};
/*
- * selftest.c
- */
-#ifdef CONFIG_FIPS_SIGNATURE_SELFTEST
-extern int __init fips_signature_selftest(void);
-#else
-static inline int fips_signature_selftest(void) { return 0; }
-#endif
-
-/*
* x509_cert_parser.c
*/
extern void x509_free_certificate(struct x509_certificate *cert);
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 7c71db3ac23d..6a4f00be22fc 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -262,15 +262,9 @@ static struct asymmetric_key_parser x509_key_parser = {
/*
* Module stuff
*/
-extern int __init certs_selftest(void);
static int __init x509_key_init(void)
{
- int ret;
-
- ret = register_asymmetric_key_parser(&x509_key_parser);
- if (ret < 0)
- return ret;
- return fips_signature_selftest();
+ return register_asymmetric_key_parser(&x509_key_parser);
}
static void __exit x509_key_exit(void)
diff --git a/crypto/authenc.c b/crypto/authenc.c
index 3326c7343e86..3aaf3ab4e360 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -141,9 +141,6 @@ static int crypto_authenc_genicv(struct aead_request *req, unsigned int flags)
u8 *hash = areq_ctx->tail;
int err;
- hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
- crypto_ahash_alignmask(auth) + 1);
-
ahash_request_set_tfm(ahreq, auth);
ahash_request_set_crypt(ahreq, req->dst, hash,
req->assoclen + req->cryptlen);
@@ -286,9 +283,6 @@ static int crypto_authenc_decrypt(struct aead_request *req)
u8 *hash = areq_ctx->tail;
int err;
- hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
- crypto_ahash_alignmask(auth) + 1);
-
ahash_request_set_tfm(ahreq, auth);
ahash_request_set_crypt(ahreq, req->src, hash,
req->assoclen + req->cryptlen - authsize);
@@ -373,9 +367,9 @@ static int crypto_authenc_create(struct crypto_template *tmpl,
u32 mask;
struct aead_instance *inst;
struct authenc_instance_ctx *ctx;
+ struct skcipher_alg_common *enc;
struct hash_alg_common *auth;
struct crypto_alg *auth_base;
- struct skcipher_alg *enc;
int err;
err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
@@ -398,10 +392,9 @@ static int crypto_authenc_create(struct crypto_template *tmpl,
crypto_attr_alg_name(tb[2]), 0, mask);
if (err)
goto err_free_inst;
- enc = crypto_spawn_skcipher_alg(&ctx->enc);
+ enc = crypto_spawn_skcipher_alg_common(&ctx->enc);
- ctx->reqoff = ALIGN(2 * auth->digestsize + auth_base->cra_alignmask,
- auth_base->cra_alignmask + 1);
+ ctx->reqoff = 2 * auth->digestsize;
err = -ENAMETOOLONG;
if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
@@ -418,12 +411,11 @@ static int crypto_authenc_create(struct crypto_template *tmpl,
inst->alg.base.cra_priority = enc->base.cra_priority * 10 +
auth_base->cra_priority;
inst->alg.base.cra_blocksize = enc->base.cra_blocksize;
- inst->alg.base.cra_alignmask = auth_base->cra_alignmask |
- enc->base.cra_alignmask;
+ inst->alg.base.cra_alignmask = enc->base.cra_alignmask;
inst->alg.base.cra_ctxsize = sizeof(struct crypto_authenc_ctx);
- inst->alg.ivsize = crypto_skcipher_alg_ivsize(enc);
- inst->alg.chunksize = crypto_skcipher_alg_chunksize(enc);
+ inst->alg.ivsize = enc->ivsize;
+ inst->alg.chunksize = enc->chunksize;
inst->alg.maxauthsize = auth->digestsize;
inst->alg.init = crypto_authenc_init_tfm;
diff --git a/crypto/authencesn.c b/crypto/authencesn.c
index 91424e791d5c..2cc933e2f790 100644
--- a/crypto/authencesn.c
+++ b/crypto/authencesn.c
@@ -87,11 +87,8 @@ static int crypto_authenc_esn_genicv_tail(struct aead_request *req,
unsigned int flags)
{
struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
- struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
- struct crypto_ahash *auth = ctx->auth;
- u8 *hash = PTR_ALIGN((u8 *)areq_ctx->tail,
- crypto_ahash_alignmask(auth) + 1);
+ u8 *hash = areq_ctx->tail;
unsigned int authsize = crypto_aead_authsize(authenc_esn);
unsigned int assoclen = req->assoclen;
unsigned int cryptlen = req->cryptlen;
@@ -122,8 +119,7 @@ static int crypto_authenc_esn_genicv(struct aead_request *req,
struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
struct crypto_ahash *auth = ctx->auth;
- u8 *hash = PTR_ALIGN((u8 *)areq_ctx->tail,
- crypto_ahash_alignmask(auth) + 1);
+ u8 *hash = areq_ctx->tail;
struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
unsigned int authsize = crypto_aead_authsize(authenc_esn);
unsigned int assoclen = req->assoclen;
@@ -224,8 +220,7 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
struct skcipher_request *skreq = (void *)(areq_ctx->tail +
ctx->reqoff);
struct crypto_ahash *auth = ctx->auth;
- u8 *ohash = PTR_ALIGN((u8 *)areq_ctx->tail,
- crypto_ahash_alignmask(auth) + 1);
+ u8 *ohash = areq_ctx->tail;
unsigned int cryptlen = req->cryptlen - authsize;
unsigned int assoclen = req->assoclen;
struct scatterlist *dst = req->dst;
@@ -272,8 +267,7 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req)
struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
unsigned int authsize = crypto_aead_authsize(authenc_esn);
struct crypto_ahash *auth = ctx->auth;
- u8 *ohash = PTR_ALIGN((u8 *)areq_ctx->tail,
- crypto_ahash_alignmask(auth) + 1);
+ u8 *ohash = areq_ctx->tail;
unsigned int assoclen = req->assoclen;
unsigned int cryptlen = req->cryptlen;
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
@@ -344,8 +338,7 @@ static int crypto_authenc_esn_init_tfm(struct crypto_aead *tfm)
ctx->enc = enc;
ctx->null = null;
- ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth),
- crypto_ahash_alignmask(auth) + 1);
+ ctx->reqoff = 2 * crypto_ahash_digestsize(auth);
crypto_aead_set_reqsize(
tfm,
@@ -390,9 +383,9 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl,
u32 mask;
struct aead_instance *inst;
struct authenc_esn_instance_ctx *ctx;
+ struct skcipher_alg_common *enc;
struct hash_alg_common *auth;
struct crypto_alg *auth_base;
- struct skcipher_alg *enc;
int err;
err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
@@ -415,7 +408,7 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl,
crypto_attr_alg_name(tb[2]), 0, mask);
if (err)
goto err_free_inst;
- enc = crypto_spawn_skcipher_alg(&ctx->enc);
+ enc = crypto_spawn_skcipher_alg_common(&ctx->enc);
err = -ENAMETOOLONG;
if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
@@ -431,12 +424,11 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl,
inst->alg.base.cra_priority = enc->base.cra_priority * 10 +
auth_base->cra_priority;
inst->alg.base.cra_blocksize = enc->base.cra_blocksize;
- inst->alg.base.cra_alignmask = auth_base->cra_alignmask |
- enc->base.cra_alignmask;
+ inst->alg.base.cra_alignmask = enc->base.cra_alignmask;
inst->alg.base.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx);
- inst->alg.ivsize = crypto_skcipher_alg_ivsize(enc);
- inst->alg.chunksize = crypto_skcipher_alg_chunksize(enc);
+ inst->alg.ivsize = enc->ivsize;
+ inst->alg.chunksize = enc->chunksize;
inst->alg.maxauthsize = auth->digestsize;
inst->alg.init = crypto_authenc_esn_init_tfm;
diff --git a/crypto/cbc.c b/crypto/cbc.c
index 6c03e96b945f..28345b8d921c 100644
--- a/crypto/cbc.c
+++ b/crypto/cbc.c
@@ -5,8 +5,6 @@
* Copyright (c) 2006-2016 Herbert Xu <herbert@gondor.apana.org.au>
*/
-#include <crypto/algapi.h>
-#include <crypto/internal/cipher.h>
#include <crypto/internal/skcipher.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -14,99 +12,71 @@
#include <linux/log2.h>
#include <linux/module.h>
-static int crypto_cbc_encrypt_segment(struct skcipher_walk *walk,
- struct crypto_skcipher *skcipher)
+static int crypto_cbc_encrypt_segment(struct crypto_lskcipher *tfm,
+ const u8 *src, u8 *dst, unsigned nbytes,
+ u8 *iv)
{
- unsigned int bsize = crypto_skcipher_blocksize(skcipher);
- void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
- unsigned int nbytes = walk->nbytes;
- u8 *src = walk->src.virt.addr;
- u8 *dst = walk->dst.virt.addr;
- struct crypto_cipher *cipher;
- struct crypto_tfm *tfm;
- u8 *iv = walk->iv;
-
- cipher = skcipher_cipher_simple(skcipher);
- tfm = crypto_cipher_tfm(cipher);
- fn = crypto_cipher_alg(cipher)->cia_encrypt;
+ unsigned int bsize = crypto_lskcipher_blocksize(tfm);
- do {
+ for (; nbytes >= bsize; src += bsize, dst += bsize, nbytes -= bsize) {
crypto_xor(iv, src, bsize);
- fn(tfm, dst, iv);
+ crypto_lskcipher_encrypt(tfm, iv, dst, bsize, NULL);
memcpy(iv, dst, bsize);
-
- src += bsize;
- dst += bsize;
- } while ((nbytes -= bsize) >= bsize);
+ }
return nbytes;
}
-static int crypto_cbc_encrypt_inplace(struct skcipher_walk *walk,
- struct crypto_skcipher *skcipher)
+static int crypto_cbc_encrypt_inplace(struct crypto_lskcipher *tfm,
+ u8 *src, unsigned nbytes, u8 *oiv)
{
- unsigned int bsize = crypto_skcipher_blocksize(skcipher);
- void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
- unsigned int nbytes = walk->nbytes;
- u8 *src = walk->src.virt.addr;
- struct crypto_cipher *cipher;
- struct crypto_tfm *tfm;
- u8 *iv = walk->iv;
-
- cipher = skcipher_cipher_simple(skcipher);
- tfm = crypto_cipher_tfm(cipher);
- fn = crypto_cipher_alg(cipher)->cia_encrypt;
+ unsigned int bsize = crypto_lskcipher_blocksize(tfm);
+ u8 *iv = oiv;
+
+ if (nbytes < bsize)
+ goto out;
do {
crypto_xor(src, iv, bsize);
- fn(tfm, src, src);
+ crypto_lskcipher_encrypt(tfm, src, src, bsize, NULL);
iv = src;
src += bsize;
} while ((nbytes -= bsize) >= bsize);
- memcpy(walk->iv, iv, bsize);
+ memcpy(oiv, iv, bsize);
+out:
return nbytes;
}
-static int crypto_cbc_encrypt(struct skcipher_request *req)
+static int crypto_cbc_encrypt(struct crypto_lskcipher *tfm, const u8 *src,
+ u8 *dst, unsigned len, u8 *iv, bool final)
{
- struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
- struct skcipher_walk walk;
- int err;
+ struct crypto_lskcipher **ctx = crypto_lskcipher_ctx(tfm);
+ struct crypto_lskcipher *cipher = *ctx;
+ int rem;
- err = skcipher_walk_virt(&walk, req, false);
+ if (src == dst)
+ rem = crypto_cbc_encrypt_inplace(cipher, dst, len, iv);
+ else
+ rem = crypto_cbc_encrypt_segment(cipher, src, dst, len, iv);
- while (walk.nbytes) {
- if (walk.src.virt.addr == walk.dst.virt.addr)
- err = crypto_cbc_encrypt_inplace(&walk, skcipher);
- else
- err = crypto_cbc_encrypt_segment(&walk, skcipher);
- err = skcipher_walk_done(&walk, err);
- }
-
- return err;
+ return rem && final ? -EINVAL : rem;
}
-static int crypto_cbc_decrypt_segment(struct skcipher_walk *walk,
- struct crypto_skcipher *skcipher)
+static int crypto_cbc_decrypt_segment(struct crypto_lskcipher *tfm,
+ const u8 *src, u8 *dst, unsigned nbytes,
+ u8 *oiv)
{
- unsigned int bsize = crypto_skcipher_blocksize(skcipher);
- void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
- unsigned int nbytes = walk->nbytes;
- u8 *src = walk->src.virt.addr;
- u8 *dst = walk->dst.virt.addr;
- struct crypto_cipher *cipher;
- struct crypto_tfm *tfm;
- u8 *iv = walk->iv;
-
- cipher = skcipher_cipher_simple(skcipher);
- tfm = crypto_cipher_tfm(cipher);
- fn = crypto_cipher_alg(cipher)->cia_decrypt;
+ unsigned int bsize = crypto_lskcipher_blocksize(tfm);
+ const u8 *iv = oiv;
+
+ if (nbytes < bsize)
+ goto out;
do {
- fn(tfm, dst, src);
+ crypto_lskcipher_decrypt(tfm, src, dst, bsize, NULL);
crypto_xor(dst, iv, bsize);
iv = src;
@@ -114,83 +84,72 @@ static int crypto_cbc_decrypt_segment(struct skcipher_walk *walk,
dst += bsize;
} while ((nbytes -= bsize) >= bsize);
- memcpy(walk->iv, iv, bsize);
+ memcpy(oiv, iv, bsize);
+out:
return nbytes;
}
-static int crypto_cbc_decrypt_inplace(struct skcipher_walk *walk,
- struct crypto_skcipher *skcipher)
+static int crypto_cbc_decrypt_inplace(struct crypto_lskcipher *tfm,
+ u8 *src, unsigned nbytes, u8 *iv)
{
- unsigned int bsize = crypto_skcipher_blocksize(skcipher);
- void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
- unsigned int nbytes = walk->nbytes;
- u8 *src = walk->src.virt.addr;
+ unsigned int bsize = crypto_lskcipher_blocksize(tfm);
u8 last_iv[MAX_CIPHER_BLOCKSIZE];
- struct crypto_cipher *cipher;
- struct crypto_tfm *tfm;
- cipher = skcipher_cipher_simple(skcipher);
- tfm = crypto_cipher_tfm(cipher);
- fn = crypto_cipher_alg(cipher)->cia_decrypt;
+ if (nbytes < bsize)
+ goto out;
/* Start of the last block. */
src += nbytes - (nbytes & (bsize - 1)) - bsize;
memcpy(last_iv, src, bsize);
for (;;) {
- fn(tfm, src, src);
+ crypto_lskcipher_decrypt(tfm, src, src, bsize, NULL);
if ((nbytes -= bsize) < bsize)
break;
crypto_xor(src, src - bsize, bsize);
src -= bsize;
}
- crypto_xor(src, walk->iv, bsize);
- memcpy(walk->iv, last_iv, bsize);
+ crypto_xor(src, iv, bsize);
+ memcpy(iv, last_iv, bsize);
+out:
return nbytes;
}
-static int crypto_cbc_decrypt(struct skcipher_request *req)
+static int crypto_cbc_decrypt(struct crypto_lskcipher *tfm, const u8 *src,
+ u8 *dst, unsigned len, u8 *iv, bool final)
{
- struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
- struct skcipher_walk walk;
- int err;
+ struct crypto_lskcipher **ctx = crypto_lskcipher_ctx(tfm);
+ struct crypto_lskcipher *cipher = *ctx;
+ int rem;
- err = skcipher_walk_virt(&walk, req, false);
+ if (src == dst)
+ rem = crypto_cbc_decrypt_inplace(cipher, dst, len, iv);
+ else
+ rem = crypto_cbc_decrypt_segment(cipher, src, dst, len, iv);
- while (walk.nbytes) {
- if (walk.src.virt.addr == walk.dst.virt.addr)
- err = crypto_cbc_decrypt_inplace(&walk, skcipher);
- else
- err = crypto_cbc_decrypt_segment(&walk, skcipher);
- err = skcipher_walk_done(&walk, err);
- }
-
- return err;
+ return rem && final ? -EINVAL : rem;
}
static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb)
{
- struct skcipher_instance *inst;
- struct crypto_alg *alg;
+ struct lskcipher_instance *inst;
int err;
- inst = skcipher_alloc_instance_simple(tmpl, tb);
+ inst = lskcipher_alloc_instance_simple(tmpl, tb);
if (IS_ERR(inst))
return PTR_ERR(inst);
- alg = skcipher_ialg_simple(inst);
-
err = -EINVAL;
- if (!is_power_of_2(alg->cra_blocksize))
+ if (!is_power_of_2(inst->alg.co.base.cra_blocksize))
goto out_free_inst;
inst->alg.encrypt = crypto_cbc_encrypt;
inst->alg.decrypt = crypto_cbc_decrypt;
- err = skcipher_register_instance(tmpl, inst);
+ err = lskcipher_register_instance(tmpl, inst);
if (err) {
out_free_inst:
inst->free(inst);
diff --git a/crypto/ccm.c b/crypto/ccm.c
index a9453129c51c..36f0acec32e1 100644
--- a/crypto/ccm.c
+++ b/crypto/ccm.c
@@ -56,6 +56,7 @@ struct cbcmac_tfm_ctx {
struct cbcmac_desc_ctx {
unsigned int len;
+ u8 dg[];
};
static inline struct crypto_ccm_req_priv_ctx *crypto_ccm_reqctx(
@@ -447,10 +448,10 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl,
const char *ctr_name,
const char *mac_name)
{
+ struct skcipher_alg_common *ctr;
u32 mask;
struct aead_instance *inst;
struct ccm_instance_ctx *ictx;
- struct skcipher_alg *ctr;
struct hash_alg_common *mac;
int err;
@@ -478,13 +479,12 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl,
ctr_name, 0, mask);
if (err)
goto err_free_inst;
- ctr = crypto_spawn_skcipher_alg(&ictx->ctr);
+ ctr = crypto_spawn_skcipher_alg_common(&ictx->ctr);
/* The skcipher algorithm must be CTR mode, using 16-byte blocks. */
err = -EINVAL;
if (strncmp(ctr->base.cra_name, "ctr(", 4) != 0 ||
- crypto_skcipher_alg_ivsize(ctr) != 16 ||
- ctr->base.cra_blocksize != 1)
+ ctr->ivsize != 16 || ctr->base.cra_blocksize != 1)
goto err_free_inst;
/* ctr and cbcmac must use the same underlying block cipher. */
@@ -504,10 +504,9 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl,
inst->alg.base.cra_priority = (mac->base.cra_priority +
ctr->base.cra_priority) / 2;
inst->alg.base.cra_blocksize = 1;
- inst->alg.base.cra_alignmask = mac->base.cra_alignmask |
- ctr->base.cra_alignmask;
+ inst->alg.base.cra_alignmask = ctr->base.cra_alignmask;
inst->alg.ivsize = 16;
- inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr);
+ inst->alg.chunksize = ctr->chunksize;
inst->alg.maxauthsize = 16;
inst->alg.base.cra_ctxsize = sizeof(struct crypto_ccm_ctx);
inst->alg.init = crypto_ccm_init_tfm;
@@ -786,10 +785,9 @@ static int crypto_cbcmac_digest_init(struct shash_desc *pdesc)
{
struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
int bs = crypto_shash_digestsize(pdesc->tfm);
- u8 *dg = (u8 *)ctx + crypto_shash_descsize(pdesc->tfm) - bs;
ctx->len = 0;
- memset(dg, 0, bs);
+ memset(ctx->dg, 0, bs);
return 0;
}
@@ -802,18 +800,17 @@ static int crypto_cbcmac_digest_update(struct shash_desc *pdesc, const u8 *p,
struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
struct crypto_cipher *tfm = tctx->child;
int bs = crypto_shash_digestsize(parent);
- u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
while (len > 0) {
unsigned int l = min(len, bs - ctx->len);
- crypto_xor(dg + ctx->len, p, l);
+ crypto_xor(&ctx->dg[ctx->len], p, l);
ctx->len +=l;
len -= l;
p += l;
if (ctx->len == bs) {
- crypto_cipher_encrypt_one(tfm, dg, dg);
+ crypto_cipher_encrypt_one(tfm, ctx->dg, ctx->dg);
ctx->len = 0;
}
}
@@ -828,12 +825,11 @@ static int crypto_cbcmac_digest_final(struct shash_desc *pdesc, u8 *out)
struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
struct crypto_cipher *tfm = tctx->child;
int bs = crypto_shash_digestsize(parent);
- u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
if (ctx->len)
- crypto_cipher_encrypt_one(tfm, dg, dg);
+ crypto_cipher_encrypt_one(tfm, ctx->dg, ctx->dg);
- memcpy(out, dg, bs);
+ memcpy(out, ctx->dg, bs);
return 0;
}
@@ -890,8 +886,7 @@ static int cbcmac_create(struct crypto_template *tmpl, struct rtattr **tb)
inst->alg.base.cra_blocksize = 1;
inst->alg.digestsize = alg->cra_blocksize;
- inst->alg.descsize = ALIGN(sizeof(struct cbcmac_desc_ctx),
- alg->cra_alignmask + 1) +
+ inst->alg.descsize = sizeof(struct cbcmac_desc_ctx) +
alg->cra_blocksize;
inst->alg.base.cra_ctxsize = sizeof(struct cbcmac_tfm_ctx);
diff --git a/crypto/chacha20poly1305.c b/crypto/chacha20poly1305.c
index 3a905c5d8f53..9e4651330852 100644
--- a/crypto/chacha20poly1305.c
+++ b/crypto/chacha20poly1305.c
@@ -558,7 +558,7 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,
u32 mask;
struct aead_instance *inst;
struct chachapoly_instance_ctx *ctx;
- struct skcipher_alg *chacha;
+ struct skcipher_alg_common *chacha;
struct hash_alg_common *poly;
int err;
@@ -579,7 +579,7 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,
crypto_attr_alg_name(tb[1]), 0, mask);
if (err)
goto err_free_inst;
- chacha = crypto_spawn_skcipher_alg(&ctx->chacha);
+ chacha = crypto_spawn_skcipher_alg_common(&ctx->chacha);
err = crypto_grab_ahash(&ctx->poly, aead_crypto_instance(inst),
crypto_attr_alg_name(tb[2]), 0, mask);
@@ -591,7 +591,7 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,
if (poly->digestsize != POLY1305_DIGEST_SIZE)
goto err_free_inst;
/* Need 16-byte IV size, including Initial Block Counter value */
- if (crypto_skcipher_alg_ivsize(chacha) != CHACHA_IV_SIZE)
+ if (chacha->ivsize != CHACHA_IV_SIZE)
goto err_free_inst;
/* Not a stream cipher? */
if (chacha->base.cra_blocksize != 1)
@@ -610,12 +610,11 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,
inst->alg.base.cra_priority = (chacha->base.cra_priority +
poly->base.cra_priority) / 2;
inst->alg.base.cra_blocksize = 1;
- inst->alg.base.cra_alignmask = chacha->base.cra_alignmask |
- poly->base.cra_alignmask;
+ inst->alg.base.cra_alignmask = chacha->base.cra_alignmask;
inst->alg.base.cra_ctxsize = sizeof(struct chachapoly_ctx) +
ctx->saltlen;
inst->alg.ivsize = ivsize;
- inst->alg.chunksize = crypto_skcipher_alg_chunksize(chacha);
+ inst->alg.chunksize = chacha->chunksize;
inst->alg.maxauthsize = POLY1305_DIGEST_SIZE;
inst->alg.init = chachapoly_init;
inst->alg.exit = chachapoly_exit;
diff --git a/crypto/cmac.c b/crypto/cmac.c
index fce6b0f58e88..c7aa3665b076 100644
--- a/crypto/cmac.c
+++ b/crypto/cmac.c
@@ -28,7 +28,7 @@
*/
struct cmac_tfm_ctx {
struct crypto_cipher *child;
- u8 ctx[];
+ __be64 consts[];
};
/*
@@ -44,17 +44,15 @@ struct cmac_tfm_ctx {
*/
struct cmac_desc_ctx {
unsigned int len;
- u8 ctx[];
+ u8 odds[];
};
static int crypto_cmac_digest_setkey(struct crypto_shash *parent,
const u8 *inkey, unsigned int keylen)
{
- unsigned long alignmask = crypto_shash_alignmask(parent);
struct cmac_tfm_ctx *ctx = crypto_shash_ctx(parent);
unsigned int bs = crypto_shash_blocksize(parent);
- __be64 *consts = PTR_ALIGN((void *)ctx->ctx,
- (alignmask | (__alignof__(__be64) - 1)) + 1);
+ __be64 *consts = ctx->consts;
u64 _const[2];
int i, err = 0;
u8 msb_mask, gfmask;
@@ -104,10 +102,9 @@ static int crypto_cmac_digest_setkey(struct crypto_shash *parent,
static int crypto_cmac_digest_init(struct shash_desc *pdesc)
{
- unsigned long alignmask = crypto_shash_alignmask(pdesc->tfm);
struct cmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
int bs = crypto_shash_blocksize(pdesc->tfm);
- u8 *prev = PTR_ALIGN((void *)ctx->ctx, alignmask + 1) + bs;
+ u8 *prev = &ctx->odds[bs];
ctx->len = 0;
memset(prev, 0, bs);
@@ -119,12 +116,11 @@ static int crypto_cmac_digest_update(struct shash_desc *pdesc, const u8 *p,
unsigned int len)
{
struct crypto_shash *parent = pdesc->tfm;
- unsigned long alignmask = crypto_shash_alignmask(parent);
struct cmac_tfm_ctx *tctx = crypto_shash_ctx(parent);
struct cmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
struct crypto_cipher *tfm = tctx->child;
int bs = crypto_shash_blocksize(parent);
- u8 *odds = PTR_ALIGN((void *)ctx->ctx, alignmask + 1);
+ u8 *odds = ctx->odds;
u8 *prev = odds + bs;
/* checking the data can fill the block */
@@ -165,14 +161,11 @@ static int crypto_cmac_digest_update(struct shash_desc *pdesc, const u8 *p,
static int crypto_cmac_digest_final(struct shash_desc *pdesc, u8 *out)
{
struct crypto_shash *parent = pdesc->tfm;
- unsigned long alignmask = crypto_shash_alignmask(parent);
struct cmac_tfm_ctx *tctx = crypto_shash_ctx(parent);
struct cmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
struct crypto_cipher *tfm = tctx->child;
int bs = crypto_shash_blocksize(parent);
- u8 *consts = PTR_ALIGN((void *)tctx->ctx,
- (alignmask | (__alignof__(__be64) - 1)) + 1);
- u8 *odds = PTR_ALIGN((void *)ctx->ctx, alignmask + 1);
+ u8 *odds = ctx->odds;
u8 *prev = odds + bs;
unsigned int offset = 0;
@@ -191,7 +184,7 @@ static int crypto_cmac_digest_final(struct shash_desc *pdesc, u8 *out)
}
crypto_xor(prev, odds, bs);
- crypto_xor(prev, consts + offset, bs);
+ crypto_xor(prev, (const u8 *)tctx->consts + offset, bs);
crypto_cipher_encrypt_one(tfm, out, prev);
@@ -241,7 +234,6 @@ static int cmac_create(struct crypto_template *tmpl, struct rtattr **tb)
struct shash_instance *inst;
struct crypto_cipher_spawn *spawn;
struct crypto_alg *alg;
- unsigned long alignmask;
u32 mask;
int err;
@@ -273,23 +265,14 @@ static int cmac_create(struct crypto_template *tmpl, struct rtattr **tb)
if (err)
goto err_free_inst;
- alignmask = alg->cra_alignmask;
- inst->alg.base.cra_alignmask = alignmask;
inst->alg.base.cra_priority = alg->cra_priority;
inst->alg.base.cra_blocksize = alg->cra_blocksize;
+ inst->alg.base.cra_ctxsize = sizeof(struct cmac_tfm_ctx) +
+ alg->cra_blocksize * 2;
inst->alg.digestsize = alg->cra_blocksize;
- inst->alg.descsize =
- ALIGN(sizeof(struct cmac_desc_ctx), crypto_tfm_ctx_alignment())
- + (alignmask & ~(crypto_tfm_ctx_alignment() - 1))
- + alg->cra_blocksize * 2;
-
- inst->alg.base.cra_ctxsize =
- ALIGN(sizeof(struct cmac_tfm_ctx), crypto_tfm_ctx_alignment())
- + ((alignmask | (__alignof__(__be64) - 1)) &
- ~(crypto_tfm_ctx_alignment() - 1))
- + alg->cra_blocksize * 2;
-
+ inst->alg.descsize = sizeof(struct cmac_desc_ctx) +
+ alg->cra_blocksize * 2;
inst->alg.init = crypto_cmac_digest_init;
inst->alg.update = crypto_cmac_digest_update;
inst->alg.final = crypto_cmac_digest_final;
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index bbcc368b6a55..31d022d47f7a 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -377,7 +377,7 @@ static int cryptd_create_skcipher(struct crypto_template *tmpl,
{
struct skcipherd_instance_ctx *ctx;
struct skcipher_instance *inst;
- struct skcipher_alg *alg;
+ struct skcipher_alg_common *alg;
u32 type;
u32 mask;
int err;
@@ -396,17 +396,17 @@ static int cryptd_create_skcipher(struct crypto_template *tmpl,
if (err)
goto err_free_inst;
- alg = crypto_spawn_skcipher_alg(&ctx->spawn);
+ alg = crypto_spawn_skcipher_alg_common(&ctx->spawn);
err = cryptd_init_instance(skcipher_crypto_instance(inst), &alg->base);
if (err)
goto err_free_inst;
inst->alg.base.cra_flags |= CRYPTO_ALG_ASYNC |
(alg->base.cra_flags & CRYPTO_ALG_INTERNAL);
- inst->alg.ivsize = crypto_skcipher_alg_ivsize(alg);
- inst->alg.chunksize = crypto_skcipher_alg_chunksize(alg);
- inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg);
- inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg);
+ inst->alg.ivsize = alg->ivsize;
+ inst->alg.chunksize = alg->chunksize;
+ inst->alg.min_keysize = alg->min_keysize;
+ inst->alg.max_keysize = alg->max_keysize;
inst->alg.base.cra_ctxsize = sizeof(struct cryptd_skcipher_ctx);
@@ -929,7 +929,7 @@ static int cryptd_create(struct crypto_template *tmpl, struct rtattr **tb)
return PTR_ERR(algt);
switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) {
- case CRYPTO_ALG_TYPE_SKCIPHER:
+ case CRYPTO_ALG_TYPE_LSKCIPHER:
return cryptd_create_skcipher(tmpl, tb, algt, &queue);
case CRYPTO_ALG_TYPE_HASH:
return cryptd_create_hash(tmpl, tb, algt, &queue);
diff --git a/crypto/crypto_engine.c b/crypto/crypto_engine.c
index 108d9d55c509..e60a0eb628e8 100644
--- a/crypto/crypto_engine.c
+++ b/crypto/crypto_engine.c
@@ -552,20 +552,16 @@ EXPORT_SYMBOL_GPL(crypto_engine_alloc_init);
/**
* crypto_engine_exit - free the resources of hardware engine when exit
* @engine: the hardware engine need to be freed
- *
- * Return 0 for success.
*/
-int crypto_engine_exit(struct crypto_engine *engine)
+void crypto_engine_exit(struct crypto_engine *engine)
{
int ret;
ret = crypto_engine_stop(engine);
if (ret)
- return ret;
+ return;
kthread_destroy_worker(engine->kworker);
-
- return 0;
}
EXPORT_SYMBOL_GPL(crypto_engine_exit);
diff --git a/crypto/ctr.c b/crypto/ctr.c
index 23c698b22013..1420496062d5 100644
--- a/crypto/ctr.c
+++ b/crypto/ctr.c
@@ -258,8 +258,8 @@ static int crypto_rfc3686_create(struct crypto_template *tmpl,
struct rtattr **tb)
{
struct skcipher_instance *inst;
- struct skcipher_alg *alg;
struct crypto_skcipher_spawn *spawn;
+ struct skcipher_alg_common *alg;
u32 mask;
int err;
@@ -278,11 +278,11 @@ static int crypto_rfc3686_create(struct crypto_template *tmpl,
if (err)
goto err_free_inst;
- alg = crypto_spawn_skcipher_alg(spawn);
+ alg = crypto_spawn_skcipher_alg_common(spawn);
/* We only support 16-byte blocks. */
err = -EINVAL;
- if (crypto_skcipher_alg_ivsize(alg) != CTR_RFC3686_BLOCK_SIZE)
+ if (alg->ivsize != CTR_RFC3686_BLOCK_SIZE)
goto err_free_inst;
/* Not a stream cipher? */
@@ -303,11 +303,9 @@ static int crypto_rfc3686_create(struct crypto_template *tmpl,
inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
inst->alg.ivsize = CTR_RFC3686_IV_SIZE;
- inst->alg.chunksize = crypto_skcipher_alg_chunksize(alg);
- inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg) +
- CTR_RFC3686_NONCE_SIZE;
- inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg) +
- CTR_RFC3686_NONCE_SIZE;
+ inst->alg.chunksize = alg->chunksize;
+ inst->alg.min_keysize = alg->min_keysize + CTR_RFC3686_NONCE_SIZE;
+ inst->alg.max_keysize = alg->max_keysize + CTR_RFC3686_NONCE_SIZE;
inst->alg.setkey = crypto_rfc3686_setkey;
inst->alg.encrypt = crypto_rfc3686_crypt;
diff --git a/crypto/cts.c b/crypto/cts.c
index 8f604f6554b1..f5b42156b6c7 100644
--- a/crypto/cts.c
+++ b/crypto/cts.c
@@ -324,8 +324,8 @@ static void crypto_cts_free(struct skcipher_instance *inst)
static int crypto_cts_create(struct crypto_template *tmpl, struct rtattr **tb)
{
struct crypto_skcipher_spawn *spawn;
+ struct skcipher_alg_common *alg;
struct skcipher_instance *inst;
- struct skcipher_alg *alg;
u32 mask;
int err;
@@ -344,10 +344,10 @@ static int crypto_cts_create(struct crypto_template *tmpl, struct rtattr **tb)
if (err)
goto err_free_inst;
- alg = crypto_spawn_skcipher_alg(spawn);
+ alg = crypto_spawn_skcipher_alg_common(spawn);
err = -EINVAL;
- if (crypto_skcipher_alg_ivsize(alg) != alg->base.cra_blocksize)
+ if (alg->ivsize != alg->base.cra_blocksize)
goto err_free_inst;
if (strncmp(alg->base.cra_name, "cbc(", 4))
@@ -363,9 +363,9 @@ static int crypto_cts_create(struct crypto_template *tmpl, struct rtattr **tb)
inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
inst->alg.ivsize = alg->base.cra_blocksize;
- inst->alg.chunksize = crypto_skcipher_alg_chunksize(alg);
- inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg);
- inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg);
+ inst->alg.chunksize = alg->chunksize;
+ inst->alg.min_keysize = alg->min_keysize;
+ inst->alg.max_keysize = alg->max_keysize;
inst->alg.base.cra_ctxsize = sizeof(struct crypto_cts_ctx);
diff --git a/crypto/deflate.c b/crypto/deflate.c
index b2a46f6dc961..6e31e0db0e86 100644
--- a/crypto/deflate.c
+++ b/crypto/deflate.c
@@ -39,24 +39,20 @@ struct deflate_ctx {
struct z_stream_s decomp_stream;
};
-static int deflate_comp_init(struct deflate_ctx *ctx, int format)
+static int deflate_comp_init(struct deflate_ctx *ctx)
{
int ret = 0;
struct z_stream_s *stream = &ctx->comp_stream;
stream->workspace = vzalloc(zlib_deflate_workspacesize(
- MAX_WBITS, MAX_MEM_LEVEL));
+ -DEFLATE_DEF_WINBITS, MAX_MEM_LEVEL));
if (!stream->workspace) {
ret = -ENOMEM;
goto out;
}
- if (format)
- ret = zlib_deflateInit(stream, 3);
- else
- ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
- -DEFLATE_DEF_WINBITS,
- DEFLATE_DEF_MEMLEVEL,
- Z_DEFAULT_STRATEGY);
+ ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
+ -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
+ Z_DEFAULT_STRATEGY);
if (ret != Z_OK) {
ret = -EINVAL;
goto out_free;
@@ -68,7 +64,7 @@ out_free:
goto out;
}
-static int deflate_decomp_init(struct deflate_ctx *ctx, int format)
+static int deflate_decomp_init(struct deflate_ctx *ctx)
{
int ret = 0;
struct z_stream_s *stream = &ctx->decomp_stream;
@@ -78,10 +74,7 @@ static int deflate_decomp_init(struct deflate_ctx *ctx, int format)
ret = -ENOMEM;
goto out;
}
- if (format)
- ret = zlib_inflateInit(stream);
- else
- ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS);
+ ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS);
if (ret != Z_OK) {
ret = -EINVAL;
goto out_free;
@@ -105,21 +98,21 @@ static void deflate_decomp_exit(struct deflate_ctx *ctx)
vfree(ctx->decomp_stream.workspace);
}
-static int __deflate_init(void *ctx, int format)
+static int __deflate_init(void *ctx)
{
int ret;
- ret = deflate_comp_init(ctx, format);
+ ret = deflate_comp_init(ctx);
if (ret)
goto out;
- ret = deflate_decomp_init(ctx, format);
+ ret = deflate_decomp_init(ctx);
if (ret)
deflate_comp_exit(ctx);
out:
return ret;
}
-static void *gen_deflate_alloc_ctx(struct crypto_scomp *tfm, int format)
+static void *deflate_alloc_ctx(struct crypto_scomp *tfm)
{
struct deflate_ctx *ctx;
int ret;
@@ -128,7 +121,7 @@ static void *gen_deflate_alloc_ctx(struct crypto_scomp *tfm, int format)
if (!ctx)
return ERR_PTR(-ENOMEM);
- ret = __deflate_init(ctx, format);
+ ret = __deflate_init(ctx);
if (ret) {
kfree(ctx);
return ERR_PTR(ret);
@@ -137,21 +130,11 @@ static void *gen_deflate_alloc_ctx(struct crypto_scomp *tfm, int format)
return ctx;
}
-static void *deflate_alloc_ctx(struct crypto_scomp *tfm)
-{
- return gen_deflate_alloc_ctx(tfm, 0);
-}
-
-static void *zlib_deflate_alloc_ctx(struct crypto_scomp *tfm)
-{
- return gen_deflate_alloc_ctx(tfm, 1);
-}
-
static int deflate_init(struct crypto_tfm *tfm)
{
struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
- return __deflate_init(ctx, 0);
+ return __deflate_init(ctx);
}
static void __deflate_exit(void *ctx)
@@ -286,7 +269,7 @@ static struct crypto_alg alg = {
.coa_decompress = deflate_decompress } }
};
-static struct scomp_alg scomp[] = { {
+static struct scomp_alg scomp = {
.alloc_ctx = deflate_alloc_ctx,
.free_ctx = deflate_free_ctx,
.compress = deflate_scompress,
@@ -296,17 +279,7 @@ static struct scomp_alg scomp[] = { {
.cra_driver_name = "deflate-scomp",
.cra_module = THIS_MODULE,
}
-}, {
- .alloc_ctx = zlib_deflate_alloc_ctx,
- .free_ctx = deflate_free_ctx,
- .compress = deflate_scompress,
- .decompress = deflate_sdecompress,
- .base = {
- .cra_name = "zlib-deflate",
- .cra_driver_name = "zlib-deflate-scomp",
- .cra_module = THIS_MODULE,
- }
-} };
+};
static int __init deflate_mod_init(void)
{
@@ -316,7 +289,7 @@ static int __init deflate_mod_init(void)
if (ret)
return ret;
- ret = crypto_register_scomps(scomp, ARRAY_SIZE(scomp));
+ ret = crypto_register_scomp(&scomp);
if (ret) {
crypto_unregister_alg(&alg);
return ret;
@@ -328,7 +301,7 @@ static int __init deflate_mod_init(void)
static void __exit deflate_mod_fini(void)
{
crypto_unregister_alg(&alg);
- crypto_unregister_scomps(scomp, ARRAY_SIZE(scomp));
+ crypto_unregister_scomp(&scomp);
}
subsys_initcall(deflate_mod_init);
diff --git a/crypto/drbg.c b/crypto/drbg.c
index ff4ebbc68efa..e01f8c7769d0 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1698,7 +1698,7 @@ static int drbg_init_hash_kernel(struct drbg_state *drbg)
sdesc->shash.tfm = tfm;
drbg->priv_data = sdesc;
- return crypto_shash_alignmask(tfm);
+ return 0;
}
static int drbg_fini_hash_kernel(struct drbg_state *drbg)
diff --git a/crypto/ecb.c b/crypto/ecb.c
index 71fbb0543d64..cc7625d1a475 100644
--- a/crypto/ecb.c
+++ b/crypto/ecb.c
@@ -5,75 +5,196 @@
* Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
*/
-#include <crypto/algapi.h>
#include <crypto/internal/cipher.h>
#include <crypto/internal/skcipher.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/slab.h>
-static int crypto_ecb_crypt(struct skcipher_request *req,
- struct crypto_cipher *cipher,
+static int crypto_ecb_crypt(struct crypto_cipher *cipher, const u8 *src,
+ u8 *dst, unsigned nbytes, bool final,
void (*fn)(struct crypto_tfm *, u8 *, const u8 *))
{
const unsigned int bsize = crypto_cipher_blocksize(cipher);
- struct skcipher_walk walk;
- unsigned int nbytes;
- int err;
-
- err = skcipher_walk_virt(&walk, req, false);
- while ((nbytes = walk.nbytes) != 0) {
- const u8 *src = walk.src.virt.addr;
- u8 *dst = walk.dst.virt.addr;
+ while (nbytes >= bsize) {
+ fn(crypto_cipher_tfm(cipher), dst, src);
- do {
- fn(crypto_cipher_tfm(cipher), dst, src);
+ src += bsize;
+ dst += bsize;
- src += bsize;
- dst += bsize;
- } while ((nbytes -= bsize) >= bsize);
-
- err = skcipher_walk_done(&walk, nbytes);
+ nbytes -= bsize;
}
- return err;
+ return nbytes && final ? -EINVAL : nbytes;
}
-static int crypto_ecb_encrypt(struct skcipher_request *req)
+static int crypto_ecb_encrypt2(struct crypto_lskcipher *tfm, const u8 *src,
+ u8 *dst, unsigned len, u8 *iv, bool final)
{
- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
- struct crypto_cipher *cipher = skcipher_cipher_simple(tfm);
+ struct crypto_cipher **ctx = crypto_lskcipher_ctx(tfm);
+ struct crypto_cipher *cipher = *ctx;
- return crypto_ecb_crypt(req, cipher,
+ return crypto_ecb_crypt(cipher, src, dst, len, final,
crypto_cipher_alg(cipher)->cia_encrypt);
}
-static int crypto_ecb_decrypt(struct skcipher_request *req)
+static int crypto_ecb_decrypt2(struct crypto_lskcipher *tfm, const u8 *src,
+ u8 *dst, unsigned len, u8 *iv, bool final)
{
- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
- struct crypto_cipher *cipher = skcipher_cipher_simple(tfm);
+ struct crypto_cipher **ctx = crypto_lskcipher_ctx(tfm);
+ struct crypto_cipher *cipher = *ctx;
- return crypto_ecb_crypt(req, cipher,
+ return crypto_ecb_crypt(cipher, src, dst, len, final,
crypto_cipher_alg(cipher)->cia_decrypt);
}
-static int crypto_ecb_create(struct crypto_template *tmpl, struct rtattr **tb)
+static int lskcipher_setkey_simple2(struct crypto_lskcipher *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ struct crypto_cipher **ctx = crypto_lskcipher_ctx(tfm);
+ struct crypto_cipher *cipher = *ctx;
+
+ crypto_cipher_clear_flags(cipher, CRYPTO_TFM_REQ_MASK);
+ crypto_cipher_set_flags(cipher, crypto_lskcipher_get_flags(tfm) &
+ CRYPTO_TFM_REQ_MASK);
+ return crypto_cipher_setkey(cipher, key, keylen);
+}
+
+static int lskcipher_init_tfm_simple2(struct crypto_lskcipher *tfm)
+{
+ struct lskcipher_instance *inst = lskcipher_alg_instance(tfm);
+ struct crypto_cipher **ctx = crypto_lskcipher_ctx(tfm);
+ struct crypto_cipher_spawn *spawn;
+ struct crypto_cipher *cipher;
+
+ spawn = lskcipher_instance_ctx(inst);
+ cipher = crypto_spawn_cipher(spawn);
+ if (IS_ERR(cipher))
+ return PTR_ERR(cipher);
+
+ *ctx = cipher;
+ return 0;
+}
+
+static void lskcipher_exit_tfm_simple2(struct crypto_lskcipher *tfm)
+{
+ struct crypto_cipher **ctx = crypto_lskcipher_ctx(tfm);
+
+ crypto_free_cipher(*ctx);
+}
+
+static void lskcipher_free_instance_simple2(struct lskcipher_instance *inst)
+{
+ crypto_drop_cipher(lskcipher_instance_ctx(inst));
+ kfree(inst);
+}
+
+static struct lskcipher_instance *lskcipher_alloc_instance_simple2(
+ struct crypto_template *tmpl, struct rtattr **tb)
+{
+ struct crypto_cipher_spawn *spawn;
+ struct lskcipher_instance *inst;
+ struct crypto_alg *cipher_alg;
+ u32 mask;
+ int err;
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_LSKCIPHER, &mask);
+ if (err)
+ return ERR_PTR(err);
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+ if (!inst)
+ return ERR_PTR(-ENOMEM);
+ spawn = lskcipher_instance_ctx(inst);
+
+ err = crypto_grab_cipher(spawn, lskcipher_crypto_instance(inst),
+ crypto_attr_alg_name(tb[1]), 0, mask);
+ if (err)
+ goto err_free_inst;
+ cipher_alg = crypto_spawn_cipher_alg(spawn);
+
+ err = crypto_inst_setname(lskcipher_crypto_instance(inst), tmpl->name,
+ cipher_alg);
+ if (err)
+ goto err_free_inst;
+
+ inst->free = lskcipher_free_instance_simple2;
+
+ /* Default algorithm properties, can be overridden */
+ inst->alg.co.base.cra_blocksize = cipher_alg->cra_blocksize;
+ inst->alg.co.base.cra_alignmask = cipher_alg->cra_alignmask;
+ inst->alg.co.base.cra_priority = cipher_alg->cra_priority;
+ inst->alg.co.min_keysize = cipher_alg->cra_cipher.cia_min_keysize;
+ inst->alg.co.max_keysize = cipher_alg->cra_cipher.cia_max_keysize;
+ inst->alg.co.ivsize = cipher_alg->cra_blocksize;
+
+ /* Use struct crypto_cipher * by default, can be overridden */
+ inst->alg.co.base.cra_ctxsize = sizeof(struct crypto_cipher *);
+ inst->alg.setkey = lskcipher_setkey_simple2;
+ inst->alg.init = lskcipher_init_tfm_simple2;
+ inst->alg.exit = lskcipher_exit_tfm_simple2;
+
+ return inst;
+
+err_free_inst:
+ lskcipher_free_instance_simple2(inst);
+ return ERR_PTR(err);
+}
+
+static int crypto_ecb_create2(struct crypto_template *tmpl, struct rtattr **tb)
{
- struct skcipher_instance *inst;
+ struct lskcipher_instance *inst;
int err;
- inst = skcipher_alloc_instance_simple(tmpl, tb);
+ inst = lskcipher_alloc_instance_simple2(tmpl, tb);
if (IS_ERR(inst))
return PTR_ERR(inst);
- inst->alg.ivsize = 0; /* ECB mode doesn't take an IV */
+ /* ECB mode doesn't take an IV */
+ inst->alg.co.ivsize = 0;
+
+ inst->alg.encrypt = crypto_ecb_encrypt2;
+ inst->alg.decrypt = crypto_ecb_decrypt2;
+
+ err = lskcipher_register_instance(tmpl, inst);
+ if (err)
+ inst->free(inst);
+
+ return err;
+}
+
+static int crypto_ecb_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+ struct crypto_lskcipher_spawn *spawn;
+ struct lskcipher_alg *cipher_alg;
+ struct lskcipher_instance *inst;
+ int err;
+
+ inst = lskcipher_alloc_instance_simple(tmpl, tb);
+ if (IS_ERR(inst)) {
+ err = crypto_ecb_create2(tmpl, tb);
+ return err;
+ }
+
+ spawn = lskcipher_instance_ctx(inst);
+ cipher_alg = crypto_lskcipher_spawn_alg(spawn);
+
+ /* ECB mode doesn't take an IV */
+ inst->alg.co.ivsize = 0;
+ if (cipher_alg->co.ivsize)
+ return -EINVAL;
- inst->alg.encrypt = crypto_ecb_encrypt;
- inst->alg.decrypt = crypto_ecb_decrypt;
+ inst->alg.co.base.cra_ctxsize = cipher_alg->co.base.cra_ctxsize;
+ inst->alg.setkey = cipher_alg->setkey;
+ inst->alg.encrypt = cipher_alg->encrypt;
+ inst->alg.decrypt = cipher_alg->decrypt;
+ inst->alg.init = cipher_alg->init;
+ inst->alg.exit = cipher_alg->exit;
- err = skcipher_register_instance(tmpl, inst);
+ err = lskcipher_register_instance(tmpl, inst);
if (err)
inst->free(inst);
@@ -102,3 +223,4 @@ module_exit(crypto_ecb_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ECB block cipher mode of operation");
MODULE_ALIAS_CRYPTO("ecb");
+MODULE_IMPORT_NS(CRYPTO_INTERNAL);
diff --git a/crypto/essiv.c b/crypto/essiv.c
index f7d4ef4837e5..e63fc6442e32 100644
--- a/crypto/essiv.c
+++ b/crypto/essiv.c
@@ -442,6 +442,7 @@ out:
static int essiv_create(struct crypto_template *tmpl, struct rtattr **tb)
{
+ struct skcipher_alg_common *skcipher_alg = NULL;
struct crypto_attr_type *algt;
const char *inner_cipher_name;
const char *shash_name;
@@ -450,7 +451,6 @@ static int essiv_create(struct crypto_template *tmpl, struct rtattr **tb)
struct crypto_instance *inst;
struct crypto_alg *base, *block_base;
struct essiv_instance_ctx *ictx;
- struct skcipher_alg *skcipher_alg = NULL;
struct aead_alg *aead_alg = NULL;
struct crypto_alg *_hash_alg;
struct shash_alg *hash_alg;
@@ -475,7 +475,7 @@ static int essiv_create(struct crypto_template *tmpl, struct rtattr **tb)
mask = crypto_algt_inherited_mask(algt);
switch (type) {
- case CRYPTO_ALG_TYPE_SKCIPHER:
+ case CRYPTO_ALG_TYPE_LSKCIPHER:
skcipher_inst = kzalloc(sizeof(*skcipher_inst) +
sizeof(*ictx), GFP_KERNEL);
if (!skcipher_inst)
@@ -489,9 +489,10 @@ static int essiv_create(struct crypto_template *tmpl, struct rtattr **tb)
inner_cipher_name, 0, mask);
if (err)
goto out_free_inst;
- skcipher_alg = crypto_spawn_skcipher_alg(&ictx->u.skcipher_spawn);
+ skcipher_alg = crypto_spawn_skcipher_alg_common(
+ &ictx->u.skcipher_spawn);
block_base = &skcipher_alg->base;
- ivsize = crypto_skcipher_alg_ivsize(skcipher_alg);
+ ivsize = skcipher_alg->ivsize;
break;
case CRYPTO_ALG_TYPE_AEAD:
@@ -574,18 +575,17 @@ static int essiv_create(struct crypto_template *tmpl, struct rtattr **tb)
base->cra_alignmask = block_base->cra_alignmask;
base->cra_priority = block_base->cra_priority;
- if (type == CRYPTO_ALG_TYPE_SKCIPHER) {
+ if (type == CRYPTO_ALG_TYPE_LSKCIPHER) {
skcipher_inst->alg.setkey = essiv_skcipher_setkey;
skcipher_inst->alg.encrypt = essiv_skcipher_encrypt;
skcipher_inst->alg.decrypt = essiv_skcipher_decrypt;
skcipher_inst->alg.init = essiv_skcipher_init_tfm;
skcipher_inst->alg.exit = essiv_skcipher_exit_tfm;
- skcipher_inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(skcipher_alg);
- skcipher_inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(skcipher_alg);
+ skcipher_inst->alg.min_keysize = skcipher_alg->min_keysize;
+ skcipher_inst->alg.max_keysize = skcipher_alg->max_keysize;
skcipher_inst->alg.ivsize = ivsize;
- skcipher_inst->alg.chunksize = crypto_skcipher_alg_chunksize(skcipher_alg);
- skcipher_inst->alg.walksize = crypto_skcipher_alg_walksize(skcipher_alg);
+ skcipher_inst->alg.chunksize = skcipher_alg->chunksize;
skcipher_inst->free = essiv_skcipher_free_instance;
@@ -616,7 +616,7 @@ static int essiv_create(struct crypto_template *tmpl, struct rtattr **tb)
out_free_hash:
crypto_mod_put(_hash_alg);
out_drop_skcipher:
- if (type == CRYPTO_ALG_TYPE_SKCIPHER)
+ if (type == CRYPTO_ALG_TYPE_LSKCIPHER)
crypto_drop_skcipher(&ictx->u.skcipher_spawn);
else
crypto_drop_aead(&ictx->u.aead_spawn);
diff --git a/crypto/gcm.c b/crypto/gcm.c
index 4ba624450c3f..84f7c23d14e4 100644
--- a/crypto/gcm.c
+++ b/crypto/gcm.c
@@ -576,10 +576,10 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl,
const char *ctr_name,
const char *ghash_name)
{
+ struct skcipher_alg_common *ctr;
u32 mask;
struct aead_instance *inst;
struct gcm_instance_ctx *ctx;
- struct skcipher_alg *ctr;
struct hash_alg_common *ghash;
int err;
@@ -607,13 +607,12 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl,
ctr_name, 0, mask);
if (err)
goto err_free_inst;
- ctr = crypto_spawn_skcipher_alg(&ctx->ctr);
+ ctr = crypto_spawn_skcipher_alg_common(&ctx->ctr);
/* The skcipher algorithm must be CTR mode, using 16-byte blocks. */
err = -EINVAL;
if (strncmp(ctr->base.cra_name, "ctr(", 4) != 0 ||
- crypto_skcipher_alg_ivsize(ctr) != 16 ||
- ctr->base.cra_blocksize != 1)
+ ctr->ivsize != 16 || ctr->base.cra_blocksize != 1)
goto err_free_inst;
err = -ENAMETOOLONG;
@@ -630,11 +629,10 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl,
inst->alg.base.cra_priority = (ghash->base.cra_priority +
ctr->base.cra_priority) / 2;
inst->alg.base.cra_blocksize = 1;
- inst->alg.base.cra_alignmask = ghash->base.cra_alignmask |
- ctr->base.cra_alignmask;
+ inst->alg.base.cra_alignmask = ctr->base.cra_alignmask;
inst->alg.base.cra_ctxsize = sizeof(struct crypto_gcm_ctx);
inst->alg.ivsize = GCM_AES_IV_SIZE;
- inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr);
+ inst->alg.chunksize = ctr->chunksize;
inst->alg.maxauthsize = 16;
inst->alg.init = crypto_gcm_init_tfm;
inst->alg.exit = crypto_gcm_exit_tfm;
diff --git a/crypto/hash.h b/crypto/hash.h
index 7e6c1a948692..93f6ba0df263 100644
--- a/crypto/hash.h
+++ b/crypto/hash.h
@@ -12,6 +12,16 @@
#include "internal.h"
+static inline struct crypto_istat_hash *hash_get_stat(
+ struct hash_alg_common *alg)
+{
+#ifdef CONFIG_CRYPTO_STATS
+ return &alg->stat;
+#else
+ return NULL;
+#endif
+}
+
static inline int crypto_hash_report_stat(struct sk_buff *skb,
struct crypto_alg *alg,
const char *type)
@@ -31,9 +41,7 @@ static inline int crypto_hash_report_stat(struct sk_buff *skb,
return nla_put(skb, CRYPTOCFGA_STAT_HASH, sizeof(rhash), &rhash);
}
-int crypto_init_shash_ops_async(struct crypto_tfm *tfm);
-struct crypto_ahash *crypto_clone_shash_ops_async(struct crypto_ahash *nhash,
- struct crypto_ahash *hash);
+extern const struct crypto_type crypto_shash_type;
int hash_prepare_alg(struct hash_alg_common *alg);
diff --git a/crypto/hash_info.c b/crypto/hash_info.c
index a49ff96bde77..9a467638c971 100644
--- a/crypto/hash_info.c
+++ b/crypto/hash_info.c
@@ -29,6 +29,9 @@ const char *const hash_algo_name[HASH_ALGO__LAST] = {
[HASH_ALGO_SM3_256] = "sm3",
[HASH_ALGO_STREEBOG_256] = "streebog256",
[HASH_ALGO_STREEBOG_512] = "streebog512",
+ [HASH_ALGO_SHA3_256] = "sha3-256",
+ [HASH_ALGO_SHA3_384] = "sha3-384",
+ [HASH_ALGO_SHA3_512] = "sha3-512",
};
EXPORT_SYMBOL_GPL(hash_algo_name);
@@ -53,5 +56,8 @@ const int hash_digest_size[HASH_ALGO__LAST] = {
[HASH_ALGO_SM3_256] = SM3256_DIGEST_SIZE,
[HASH_ALGO_STREEBOG_256] = STREEBOG256_DIGEST_SIZE,
[HASH_ALGO_STREEBOG_512] = STREEBOG512_DIGEST_SIZE,
+ [HASH_ALGO_SHA3_256] = SHA3_256_DIGEST_SIZE,
+ [HASH_ALGO_SHA3_384] = SHA3_384_DIGEST_SIZE,
+ [HASH_ALGO_SHA3_512] = SHA3_512_DIGEST_SIZE,
};
EXPORT_SYMBOL_GPL(hash_digest_size);
diff --git a/crypto/hctr2.c b/crypto/hctr2.c
index 6f4c1884d0e9..87e7547ad186 100644
--- a/crypto/hctr2.c
+++ b/crypto/hctr2.c
@@ -406,10 +406,10 @@ static int hctr2_create_common(struct crypto_template *tmpl,
const char *xctr_name,
const char *polyval_name)
{
+ struct skcipher_alg_common *xctr_alg;
u32 mask;
struct skcipher_instance *inst;
struct hctr2_instance_ctx *ictx;
- struct skcipher_alg *xctr_alg;
struct crypto_alg *blockcipher_alg;
struct shash_alg *polyval_alg;
char blockcipher_name[CRYPTO_MAX_ALG_NAME];
@@ -431,7 +431,7 @@ static int hctr2_create_common(struct crypto_template *tmpl,
xctr_name, 0, mask);
if (err)
goto err_free_inst;
- xctr_alg = crypto_spawn_skcipher_alg(&ictx->xctr_spawn);
+ xctr_alg = crypto_spawn_skcipher_alg_common(&ictx->xctr_spawn);
err = -EINVAL;
if (strncmp(xctr_alg->base.cra_name, "xctr(", 5))
@@ -485,8 +485,7 @@ static int hctr2_create_common(struct crypto_template *tmpl,
inst->alg.base.cra_blocksize = BLOCKCIPHER_BLOCK_SIZE;
inst->alg.base.cra_ctxsize = sizeof(struct hctr2_tfm_ctx) +
polyval_alg->statesize * 2;
- inst->alg.base.cra_alignmask = xctr_alg->base.cra_alignmask |
- polyval_alg->base.cra_alignmask;
+ inst->alg.base.cra_alignmask = xctr_alg->base.cra_alignmask;
/*
* The hash function is called twice, so it is weighted higher than the
* xctr and blockcipher.
@@ -500,8 +499,8 @@ static int hctr2_create_common(struct crypto_template *tmpl,
inst->alg.decrypt = hctr2_decrypt;
inst->alg.init = hctr2_init_tfm;
inst->alg.exit = hctr2_exit_tfm;
- inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(xctr_alg);
- inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(xctr_alg);
+ inst->alg.min_keysize = xctr_alg->min_keysize;
+ inst->alg.max_keysize = xctr_alg->max_keysize;
inst->alg.ivsize = TWEAK_SIZE;
inst->free = hctr2_free_instance;
diff --git a/crypto/hmac.c b/crypto/hmac.c
index ea93f4c55f25..7cec25ff9889 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -24,31 +24,20 @@
struct hmac_ctx {
struct crypto_shash *hash;
+ /* Contains 'u8 ipad[statesize];', then 'u8 opad[statesize];' */
+ u8 pads[];
};
-static inline void *align_ptr(void *p, unsigned int align)
-{
- return (void *)ALIGN((unsigned long)p, align);
-}
-
-static inline struct hmac_ctx *hmac_ctx(struct crypto_shash *tfm)
-{
- return align_ptr(crypto_shash_ctx_aligned(tfm) +
- crypto_shash_statesize(tfm) * 2,
- crypto_tfm_ctx_alignment());
-}
-
static int hmac_setkey(struct crypto_shash *parent,
const u8 *inkey, unsigned int keylen)
{
int bs = crypto_shash_blocksize(parent);
int ds = crypto_shash_digestsize(parent);
int ss = crypto_shash_statesize(parent);
- char *ipad = crypto_shash_ctx_aligned(parent);
- char *opad = ipad + ss;
- struct hmac_ctx *ctx = align_ptr(opad + ss,
- crypto_tfm_ctx_alignment());
- struct crypto_shash *hash = ctx->hash;
+ struct hmac_ctx *tctx = crypto_shash_ctx(parent);
+ struct crypto_shash *hash = tctx->hash;
+ u8 *ipad = &tctx->pads[0];
+ u8 *opad = &tctx->pads[ss];
SHASH_DESC_ON_STACK(shash, hash);
unsigned int i;
@@ -94,16 +83,18 @@ static int hmac_export(struct shash_desc *pdesc, void *out)
static int hmac_import(struct shash_desc *pdesc, const void *in)
{
struct shash_desc *desc = shash_desc_ctx(pdesc);
- struct hmac_ctx *ctx = hmac_ctx(pdesc->tfm);
+ const struct hmac_ctx *tctx = crypto_shash_ctx(pdesc->tfm);
- desc->tfm = ctx->hash;
+ desc->tfm = tctx->hash;
return crypto_shash_import(desc, in);
}
static int hmac_init(struct shash_desc *pdesc)
{
- return hmac_import(pdesc, crypto_shash_ctx_aligned(pdesc->tfm));
+ const struct hmac_ctx *tctx = crypto_shash_ctx(pdesc->tfm);
+
+ return hmac_import(pdesc, &tctx->pads[0]);
}
static int hmac_update(struct shash_desc *pdesc,
@@ -119,7 +110,8 @@ static int hmac_final(struct shash_desc *pdesc, u8 *out)
struct crypto_shash *parent = pdesc->tfm;
int ds = crypto_shash_digestsize(parent);
int ss = crypto_shash_statesize(parent);
- char *opad = crypto_shash_ctx_aligned(parent) + ss;
+ const struct hmac_ctx *tctx = crypto_shash_ctx(parent);
+ const u8 *opad = &tctx->pads[ss];
struct shash_desc *desc = shash_desc_ctx(pdesc);
return crypto_shash_final(desc, out) ?:
@@ -134,7 +126,8 @@ static int hmac_finup(struct shash_desc *pdesc, const u8 *data,
struct crypto_shash *parent = pdesc->tfm;
int ds = crypto_shash_digestsize(parent);
int ss = crypto_shash_statesize(parent);
- char *opad = crypto_shash_ctx_aligned(parent) + ss;
+ const struct hmac_ctx *tctx = crypto_shash_ctx(parent);
+ const u8 *opad = &tctx->pads[ss];
struct shash_desc *desc = shash_desc_ctx(pdesc);
return crypto_shash_finup(desc, data, nbytes, out) ?:
@@ -147,7 +140,7 @@ static int hmac_init_tfm(struct crypto_shash *parent)
struct crypto_shash *hash;
struct shash_instance *inst = shash_alg_instance(parent);
struct crypto_shash_spawn *spawn = shash_instance_ctx(inst);
- struct hmac_ctx *ctx = hmac_ctx(parent);
+ struct hmac_ctx *tctx = crypto_shash_ctx(parent);
hash = crypto_spawn_shash(spawn);
if (IS_ERR(hash))
@@ -156,14 +149,14 @@ static int hmac_init_tfm(struct crypto_shash *parent)
parent->descsize = sizeof(struct shash_desc) +
crypto_shash_descsize(hash);
- ctx->hash = hash;
+ tctx->hash = hash;
return 0;
}
static int hmac_clone_tfm(struct crypto_shash *dst, struct crypto_shash *src)
{
- struct hmac_ctx *sctx = hmac_ctx(src);
- struct hmac_ctx *dctx = hmac_ctx(dst);
+ struct hmac_ctx *sctx = crypto_shash_ctx(src);
+ struct hmac_ctx *dctx = crypto_shash_ctx(dst);
struct crypto_shash *hash;
hash = crypto_clone_shash(sctx->hash);
@@ -176,9 +169,9 @@ static int hmac_clone_tfm(struct crypto_shash *dst, struct crypto_shash *src)
static void hmac_exit_tfm(struct crypto_shash *parent)
{
- struct hmac_ctx *ctx = hmac_ctx(parent);
+ struct hmac_ctx *tctx = crypto_shash_ctx(parent);
- crypto_free_shash(ctx->hash);
+ crypto_free_shash(tctx->hash);
}
static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
@@ -225,15 +218,10 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
inst->alg.base.cra_priority = alg->cra_priority;
inst->alg.base.cra_blocksize = alg->cra_blocksize;
- inst->alg.base.cra_alignmask = alg->cra_alignmask;
+ inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) + (ss * 2);
- ss = ALIGN(ss, alg->cra_alignmask + 1);
inst->alg.digestsize = ds;
inst->alg.statesize = ss;
-
- inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) +
- ALIGN(ss * 2, crypto_tfm_ctx_alignment());
-
inst->alg.init = hmac_init;
inst->alg.update = hmac_update;
inst->alg.final = hmac_final;
diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c
index 7d1463a1562a..76edbf8af0ac 100644
--- a/crypto/jitterentropy-kcapi.c
+++ b/crypto/jitterentropy-kcapi.c
@@ -54,6 +54,17 @@
* Helper function
***************************************************************************/
+void *jent_kvzalloc(unsigned int len)
+{
+ return kvzalloc(len, GFP_KERNEL);
+}
+
+void jent_kvzfree(void *ptr, unsigned int len)
+{
+ memzero_explicit(ptr, len);
+ kvfree(ptr);
+}
+
void *jent_zalloc(unsigned int len)
{
return kzalloc(len, GFP_KERNEL);
@@ -245,7 +256,9 @@ static int jent_kcapi_init(struct crypto_tfm *tfm)
crypto_shash_init(sdesc);
rng->sdesc = sdesc;
- rng->entropy_collector = jent_entropy_collector_alloc(1, 0, sdesc);
+ rng->entropy_collector =
+ jent_entropy_collector_alloc(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0,
+ sdesc);
if (!rng->entropy_collector) {
ret = -ENOMEM;
goto err;
@@ -334,7 +347,7 @@ static int __init jent_mod_init(void)
desc->tfm = tfm;
crypto_shash_init(desc);
- ret = jent_entropy_init(desc);
+ ret = jent_entropy_init(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0, desc, NULL);
shash_desc_zero(desc);
crypto_free_shash(tfm);
if (ret) {
diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c
index fe9c233ec769..26a9048bc893 100644
--- a/crypto/jitterentropy.c
+++ b/crypto/jitterentropy.c
@@ -72,11 +72,13 @@ struct rand_data {
__u64 prev_time; /* SENSITIVE Previous time stamp */
__u64 last_delta; /* SENSITIVE stuck test */
__s64 last_delta2; /* SENSITIVE stuck test */
+
+ unsigned int flags; /* Flags used to initialize */
unsigned int osr; /* Oversample rate */
-#define JENT_MEMORY_BLOCKS 64
-#define JENT_MEMORY_BLOCKSIZE 32
#define JENT_MEMORY_ACCESSLOOPS 128
-#define JENT_MEMORY_SIZE (JENT_MEMORY_BLOCKS*JENT_MEMORY_BLOCKSIZE)
+#define JENT_MEMORY_SIZE \
+ (CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS * \
+ CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE)
unsigned char *mem; /* Memory access location with size of
* memblocks * memblocksize */
unsigned int memlocation; /* Pointer to byte in *mem */
@@ -88,16 +90,9 @@ struct rand_data {
/* Repetition Count Test */
unsigned int rct_count; /* Number of stuck values */
- /* Intermittent health test failure threshold of 2^-30 */
- /* From an SP800-90B perspective, this RCT cutoff value is equal to 31. */
- /* However, our RCT implementation starts at 1, so we subtract 1 here. */
-#define JENT_RCT_CUTOFF (31 - 1) /* Taken from SP800-90B sec 4.4.1 */
-#define JENT_APT_CUTOFF 325 /* Taken from SP800-90B sec 4.4.2 */
- /* Permanent health test failure threshold of 2^-60 */
- /* From an SP800-90B perspective, this RCT cutoff value is equal to 61. */
- /* However, our RCT implementation starts at 1, so we subtract 1 here. */
-#define JENT_RCT_CUTOFF_PERMANENT (61 - 1)
-#define JENT_APT_CUTOFF_PERMANENT 355
+ /* Adaptive Proportion Test cutoff values */
+ unsigned int apt_cutoff; /* Intermittent health test failure */
+ unsigned int apt_cutoff_permanent; /* Permanent health test failure */
#define JENT_APT_WINDOW_SIZE 512 /* Data window size */
/* LSB of time stamp to process */
#define JENT_APT_LSB 16
@@ -105,6 +100,8 @@ struct rand_data {
unsigned int apt_observations; /* Number of collected observations */
unsigned int apt_count; /* APT counter */
unsigned int apt_base; /* APT base reference */
+ unsigned int health_failure; /* Record health failure */
+
unsigned int apt_base_set:1; /* APT base reference set? */
};
@@ -122,6 +119,16 @@ struct rand_data {
* zero). */
#define JENT_ESTUCK 8 /* Too many stuck results during init. */
#define JENT_EHEALTH 9 /* Health test failed during initialization */
+#define JENT_ERCT 10 /* RCT failed during initialization */
+#define JENT_EHASH 11 /* Hash self test failed */
+#define JENT_EMEM 12 /* Can't allocate memory for initialization */
+
+#define JENT_RCT_FAILURE 1 /* Failure in RCT health test. */
+#define JENT_APT_FAILURE 2 /* Failure in APT health test. */
+#define JENT_PERMANENT_FAILURE_SHIFT 16
+#define JENT_PERMANENT_FAILURE(x) (x << JENT_PERMANENT_FAILURE_SHIFT)
+#define JENT_RCT_FAILURE_PERMANENT JENT_PERMANENT_FAILURE(JENT_RCT_FAILURE)
+#define JENT_APT_FAILURE_PERMANENT JENT_PERMANENT_FAILURE(JENT_APT_FAILURE)
/*
* The output n bits can receive more than n bits of min entropy, of course,
@@ -148,6 +155,48 @@ struct rand_data {
***************************************************************************/
/*
+ * See the SP 800-90B comment #10b for the corrected cutoff for the SP 800-90B
+ * APT.
+ * http://www.untruth.org/~josh/sp80090b/UL%20SP800-90B-final%20comments%20v1.9%2020191212.pdf
+ * In in the syntax of R, this is C = 2 + qbinom(1 − 2^(−30), 511, 2^(-1/osr)).
+ * (The original formula wasn't correct because the first symbol must
+ * necessarily have been observed, so there is no chance of observing 0 of these
+ * symbols.)
+ *
+ * For the alpha < 2^-53, R cannot be used as it uses a float data type without
+ * arbitrary precision. A SageMath script is used to calculate those cutoff
+ * values.
+ *
+ * For any value above 14, this yields the maximal allowable value of 512
+ * (by FIPS 140-2 IG 7.19 Resolution # 16, we cannot choose a cutoff value that
+ * renders the test unable to fail).
+ */
+static const unsigned int jent_apt_cutoff_lookup[15] = {
+ 325, 422, 459, 477, 488, 494, 499, 502,
+ 505, 507, 508, 509, 510, 511, 512 };
+static const unsigned int jent_apt_cutoff_permanent_lookup[15] = {
+ 355, 447, 479, 494, 502, 507, 510, 512,
+ 512, 512, 512, 512, 512, 512, 512 };
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static void jent_apt_init(struct rand_data *ec, unsigned int osr)
+{
+ /*
+ * Establish the apt_cutoff based on the presumed entropy rate of
+ * 1/osr.
+ */
+ if (osr >= ARRAY_SIZE(jent_apt_cutoff_lookup)) {
+ ec->apt_cutoff = jent_apt_cutoff_lookup[
+ ARRAY_SIZE(jent_apt_cutoff_lookup) - 1];
+ ec->apt_cutoff_permanent = jent_apt_cutoff_permanent_lookup[
+ ARRAY_SIZE(jent_apt_cutoff_permanent_lookup) - 1];
+ } else {
+ ec->apt_cutoff = jent_apt_cutoff_lookup[osr - 1];
+ ec->apt_cutoff_permanent =
+ jent_apt_cutoff_permanent_lookup[osr - 1];
+ }
+}
+/*
* Reset the APT counter
*
* @ec [in] Reference to entropy collector
@@ -175,26 +224,22 @@ static void jent_apt_insert(struct rand_data *ec, unsigned int delta_masked)
return;
}
- if (delta_masked == ec->apt_base)
+ if (delta_masked == ec->apt_base) {
ec->apt_count++;
+ /* Note, ec->apt_count starts with one. */
+ if (ec->apt_count >= ec->apt_cutoff_permanent)
+ ec->health_failure |= JENT_APT_FAILURE_PERMANENT;
+ else if (ec->apt_count >= ec->apt_cutoff)
+ ec->health_failure |= JENT_APT_FAILURE;
+ }
+
ec->apt_observations++;
if (ec->apt_observations >= JENT_APT_WINDOW_SIZE)
jent_apt_reset(ec, delta_masked);
}
-/* APT health test failure detection */
-static int jent_apt_permanent_failure(struct rand_data *ec)
-{
- return (ec->apt_count >= JENT_APT_CUTOFF_PERMANENT) ? 1 : 0;
-}
-
-static int jent_apt_failure(struct rand_data *ec)
-{
- return (ec->apt_count >= JENT_APT_CUTOFF) ? 1 : 0;
-}
-
/***************************************************************************
* Stuck Test and its use as Repetition Count Test
*
@@ -221,6 +266,30 @@ static void jent_rct_insert(struct rand_data *ec, int stuck)
{
if (stuck) {
ec->rct_count++;
+
+ /*
+ * The cutoff value is based on the following consideration:
+ * alpha = 2^-30 or 2^-60 as recommended in SP800-90B.
+ * In addition, we require an entropy value H of 1/osr as this
+ * is the minimum entropy required to provide full entropy.
+ * Note, we collect (DATA_SIZE_BITS + ENTROPY_SAFETY_FACTOR)*osr
+ * deltas for inserting them into the entropy pool which should
+ * then have (close to) DATA_SIZE_BITS bits of entropy in the
+ * conditioned output.
+ *
+ * Note, ec->rct_count (which equals to value B in the pseudo
+ * code of SP800-90B section 4.4.1) starts with zero. Hence
+ * we need to subtract one from the cutoff value as calculated
+ * following SP800-90B. Thus C = ceil(-log_2(alpha)/H) = 30*osr
+ * or 60*osr.
+ */
+ if ((unsigned int)ec->rct_count >= (60 * ec->osr)) {
+ ec->rct_count = -1;
+ ec->health_failure |= JENT_RCT_FAILURE_PERMANENT;
+ } else if ((unsigned int)ec->rct_count >= (30 * ec->osr)) {
+ ec->rct_count = -1;
+ ec->health_failure |= JENT_RCT_FAILURE;
+ }
} else {
/* Reset RCT */
ec->rct_count = 0;
@@ -275,26 +344,25 @@ static int jent_stuck(struct rand_data *ec, __u64 current_delta)
return 0;
}
-/* RCT health test failure detection */
-static int jent_rct_permanent_failure(struct rand_data *ec)
-{
- return (ec->rct_count >= JENT_RCT_CUTOFF_PERMANENT) ? 1 : 0;
-}
-
-static int jent_rct_failure(struct rand_data *ec)
-{
- return (ec->rct_count >= JENT_RCT_CUTOFF) ? 1 : 0;
-}
-
-/* Report of health test failures */
-static int jent_health_failure(struct rand_data *ec)
+/*
+ * Report any health test failures
+ *
+ * @ec [in] Reference to entropy collector
+ *
+ * @return a bitmask indicating which tests failed
+ * 0 No health test failure
+ * 1 RCT failure
+ * 2 APT failure
+ * 1<<JENT_PERMANENT_FAILURE_SHIFT RCT permanent failure
+ * 2<<JENT_PERMANENT_FAILURE_SHIFT APT permanent failure
+ */
+static unsigned int jent_health_failure(struct rand_data *ec)
{
- return jent_rct_failure(ec) | jent_apt_failure(ec);
-}
+ /* Test is only enabled in FIPS mode */
+ if (!fips_enabled)
+ return 0;
-static int jent_permanent_health_failure(struct rand_data *ec)
-{
- return jent_rct_permanent_failure(ec) | jent_apt_permanent_failure(ec);
+ return ec->health_failure;
}
/***************************************************************************
@@ -448,7 +516,7 @@ static void jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
*
* @return result of stuck test
*/
-static int jent_measure_jitter(struct rand_data *ec)
+static int jent_measure_jitter(struct rand_data *ec, __u64 *ret_current_delta)
{
__u64 time = 0;
__u64 current_delta = 0;
@@ -472,6 +540,10 @@ static int jent_measure_jitter(struct rand_data *ec)
if (jent_condition_data(ec, current_delta, stuck))
stuck = 1;
+ /* return the raw entropy value */
+ if (ret_current_delta)
+ *ret_current_delta = current_delta;
+
return stuck;
}
@@ -489,11 +561,11 @@ static void jent_gen_entropy(struct rand_data *ec)
safety_factor = JENT_ENTROPY_SAFETY_FACTOR;
/* priming of the ->prev_time value */
- jent_measure_jitter(ec);
+ jent_measure_jitter(ec, NULL);
while (!jent_health_failure(ec)) {
/* If a stuck measurement is received, repeat measurement */
- if (jent_measure_jitter(ec))
+ if (jent_measure_jitter(ec, NULL))
continue;
/*
@@ -537,11 +609,12 @@ int jent_read_entropy(struct rand_data *ec, unsigned char *data,
return -1;
while (len > 0) {
- unsigned int tocopy;
+ unsigned int tocopy, health_test_result;
jent_gen_entropy(ec);
- if (jent_permanent_health_failure(ec)) {
+ health_test_result = jent_health_failure(ec);
+ if (health_test_result > JENT_PERMANENT_FAILURE_SHIFT) {
/*
* At this point, the Jitter RNG instance is considered
* as a failed instance. There is no rerun of the
@@ -549,13 +622,18 @@ int jent_read_entropy(struct rand_data *ec, unsigned char *data,
* is assumed to not further use this instance.
*/
return -3;
- } else if (jent_health_failure(ec)) {
+ } else if (health_test_result) {
/*
* Perform startup health tests and return permanent
* error if it fails.
*/
- if (jent_entropy_init(ec->hash_state))
+ if (jent_entropy_init(0, 0, NULL, ec)) {
+ /* Mark the permanent error */
+ ec->health_failure &=
+ JENT_RCT_FAILURE_PERMANENT |
+ JENT_APT_FAILURE_PERMANENT;
return -3;
+ }
return -2;
}
@@ -592,23 +670,29 @@ struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
/* Allocate memory for adding variations based on memory
* access
*/
- entropy_collector->mem = jent_zalloc(JENT_MEMORY_SIZE);
+ entropy_collector->mem = jent_kvzalloc(JENT_MEMORY_SIZE);
if (!entropy_collector->mem) {
jent_zfree(entropy_collector);
return NULL;
}
- entropy_collector->memblocksize = JENT_MEMORY_BLOCKSIZE;
- entropy_collector->memblocks = JENT_MEMORY_BLOCKS;
+ entropy_collector->memblocksize =
+ CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE;
+ entropy_collector->memblocks =
+ CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS;
entropy_collector->memaccessloops = JENT_MEMORY_ACCESSLOOPS;
}
/* verify and set the oversampling rate */
if (osr == 0)
- osr = 1; /* minimum sampling rate is 1 */
+ osr = 1; /* H_submitter = 1 / osr */
entropy_collector->osr = osr;
+ entropy_collector->flags = flags;
entropy_collector->hash_state = hash_state;
+ /* Initialize the APT */
+ jent_apt_init(entropy_collector, osr);
+
/* fill the data pad with non-zero values */
jent_gen_entropy(entropy_collector);
@@ -617,25 +701,39 @@ struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
void jent_entropy_collector_free(struct rand_data *entropy_collector)
{
- jent_zfree(entropy_collector->mem);
+ jent_kvzfree(entropy_collector->mem, JENT_MEMORY_SIZE);
entropy_collector->mem = NULL;
jent_zfree(entropy_collector);
}
-int jent_entropy_init(void *hash_state)
+int jent_entropy_init(unsigned int osr, unsigned int flags, void *hash_state,
+ struct rand_data *p_ec)
{
- int i;
- __u64 delta_sum = 0;
- __u64 old_delta = 0;
- unsigned int nonstuck = 0;
- int time_backwards = 0;
- int count_mod = 0;
- int count_stuck = 0;
- struct rand_data ec = { 0 };
-
- /* Required for RCT */
- ec.osr = 1;
- ec.hash_state = hash_state;
+ /*
+ * If caller provides an allocated ec, reuse it which implies that the
+ * health test entropy data is used to further still the available
+ * entropy pool.
+ */
+ struct rand_data *ec = p_ec;
+ int i, time_backwards = 0, ret = 0, ec_free = 0;
+ unsigned int health_test_result;
+
+ if (!ec) {
+ ec = jent_entropy_collector_alloc(osr, flags, hash_state);
+ if (!ec)
+ return JENT_EMEM;
+ ec_free = 1;
+ } else {
+ /* Reset the APT */
+ jent_apt_reset(ec, 0);
+ /* Ensure that a new APT base is obtained */
+ ec->apt_base_set = 0;
+ /* Reset the RCT */
+ ec->rct_count = 0;
+ /* Reset intermittent, leave permanent health test result */
+ ec->health_failure &= (~JENT_RCT_FAILURE);
+ ec->health_failure &= (~JENT_APT_FAILURE);
+ }
/* We could perform statistical tests here, but the problem is
* that we only have a few loop counts to do testing. These
@@ -664,31 +762,28 @@ int jent_entropy_init(void *hash_state)
#define TESTLOOPCOUNT 1024
#define CLEARCACHE 100
for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) {
- __u64 time = 0;
- __u64 time2 = 0;
- __u64 delta = 0;
- unsigned int lowdelta = 0;
- int stuck;
+ __u64 start_time = 0, end_time = 0, delta = 0;
/* Invoke core entropy collection logic */
- jent_get_nstime(&time);
- ec.prev_time = time;
- jent_condition_data(&ec, time, 0);
- jent_get_nstime(&time2);
+ jent_measure_jitter(ec, &delta);
+ end_time = ec->prev_time;
+ start_time = ec->prev_time - delta;
/* test whether timer works */
- if (!time || !time2)
- return JENT_ENOTIME;
- delta = jent_delta(time, time2);
+ if (!start_time || !end_time) {
+ ret = JENT_ENOTIME;
+ goto out;
+ }
+
/*
* test whether timer is fine grained enough to provide
* delta even when called shortly after each other -- this
* implies that we also have a high resolution timer
*/
- if (!delta)
- return JENT_ECOARSETIME;
-
- stuck = jent_stuck(&ec, delta);
+ if (!delta || (end_time == start_time)) {
+ ret = JENT_ECOARSETIME;
+ goto out;
+ }
/*
* up to here we did not modify any variable that will be
@@ -700,49 +795,9 @@ int jent_entropy_init(void *hash_state)
if (i < CLEARCACHE)
continue;
- if (stuck)
- count_stuck++;
- else {
- nonstuck++;
-
- /*
- * Ensure that the APT succeeded.
- *
- * With the check below that count_stuck must be less
- * than 10% of the overall generated raw entropy values
- * it is guaranteed that the APT is invoked at
- * floor((TESTLOOPCOUNT * 0.9) / 64) == 14 times.
- */
- if ((nonstuck % JENT_APT_WINDOW_SIZE) == 0) {
- jent_apt_reset(&ec,
- delta & JENT_APT_WORD_MASK);
- }
- }
-
- /* Validate health test result */
- if (jent_health_failure(&ec))
- return JENT_EHEALTH;
-
/* test whether we have an increasing timer */
- if (!(time2 > time))
+ if (!(end_time > start_time))
time_backwards++;
-
- /* use 32 bit value to ensure compilation on 32 bit arches */
- lowdelta = time2 - time;
- if (!(lowdelta % 100))
- count_mod++;
-
- /*
- * ensure that we have a varying delta timer which is necessary
- * for the calculation of entropy -- perform this check
- * only after the first loop is executed as we need to prime
- * the old_data value
- */
- if (delta > old_delta)
- delta_sum += (delta - old_delta);
- else
- delta_sum += (old_delta - delta);
- old_delta = delta;
}
/*
@@ -752,31 +807,22 @@ int jent_entropy_init(void *hash_state)
* should not fail. The value of 3 should cover the NTP case being
* performed during our test run.
*/
- if (time_backwards > 3)
- return JENT_ENOMONOTONIC;
-
- /*
- * Variations of deltas of time must on average be larger
- * than 1 to ensure the entropy estimation
- * implied with 1 is preserved
- */
- if ((delta_sum) <= 1)
- return JENT_EVARVAR;
+ if (time_backwards > 3) {
+ ret = JENT_ENOMONOTONIC;
+ goto out;
+ }
- /*
- * Ensure that we have variations in the time stamp below 10 for at
- * least 10% of all checks -- on some platforms, the counter increments
- * in multiples of 100, but not always
- */
- if ((TESTLOOPCOUNT/10 * 9) < count_mod)
- return JENT_ECOARSETIME;
+ /* Did we encounter a health test failure? */
+ health_test_result = jent_health_failure(ec);
+ if (health_test_result) {
+ ret = (health_test_result & JENT_RCT_FAILURE) ? JENT_ERCT :
+ JENT_EHEALTH;
+ goto out;
+ }
- /*
- * If we have more than 90% stuck results, then this Jitter RNG is
- * likely to not work well.
- */
- if ((TESTLOOPCOUNT/10 * 9) < count_stuck)
- return JENT_ESTUCK;
+out:
+ if (ec_free)
+ jent_entropy_collector_free(ec);
- return 0;
+ return ret;
}
diff --git a/crypto/jitterentropy.h b/crypto/jitterentropy.h
index 4c92176ea2b1..aa4728675ae2 100644
--- a/crypto/jitterentropy.h
+++ b/crypto/jitterentropy.h
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
+extern void *jent_kvzalloc(unsigned int len);
+extern void jent_kvzfree(void *ptr, unsigned int len);
extern void *jent_zalloc(unsigned int len);
extern void jent_zfree(void *ptr);
extern void jent_get_nstime(__u64 *out);
@@ -9,7 +11,8 @@ extern int jent_hash_time(void *hash_state, __u64 time, u8 *addtl,
int jent_read_random_block(void *hash_state, char *dst, unsigned int dst_len);
struct rand_data;
-extern int jent_entropy_init(void *hash_state);
+extern int jent_entropy_init(unsigned int osr, unsigned int flags,
+ void *hash_state, struct rand_data *p_ec);
extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
unsigned int len);
diff --git a/crypto/lrw.c b/crypto/lrw.c
index 59260aefed28..e216fbf2b786 100644
--- a/crypto/lrw.c
+++ b/crypto/lrw.c
@@ -299,8 +299,8 @@ static void lrw_free_instance(struct skcipher_instance *inst)
static int lrw_create(struct crypto_template *tmpl, struct rtattr **tb)
{
struct crypto_skcipher_spawn *spawn;
+ struct skcipher_alg_common *alg;
struct skcipher_instance *inst;
- struct skcipher_alg *alg;
const char *cipher_name;
char ecb_name[CRYPTO_MAX_ALG_NAME];
u32 mask;
@@ -336,13 +336,13 @@ static int lrw_create(struct crypto_template *tmpl, struct rtattr **tb)
if (err)
goto err_free_inst;
- alg = crypto_skcipher_spawn_alg(spawn);
+ alg = crypto_spawn_skcipher_alg_common(spawn);
err = -EINVAL;
if (alg->base.cra_blocksize != LRW_BLOCK_SIZE)
goto err_free_inst;
- if (crypto_skcipher_alg_ivsize(alg))
+ if (alg->ivsize)
goto err_free_inst;
err = crypto_inst_setname(skcipher_crypto_instance(inst), "lrw",
@@ -382,10 +382,8 @@ static int lrw_create(struct crypto_template *tmpl, struct rtattr **tb)
(__alignof__(be128) - 1);
inst->alg.ivsize = LRW_BLOCK_SIZE;
- inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg) +
- LRW_BLOCK_SIZE;
- inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg) +
- LRW_BLOCK_SIZE;
+ inst->alg.min_keysize = alg->min_keysize + LRW_BLOCK_SIZE;
+ inst->alg.max_keysize = alg->max_keysize + LRW_BLOCK_SIZE;
inst->alg.base.cra_ctxsize = sizeof(struct lrw_tfm_ctx);
diff --git a/crypto/lskcipher.c b/crypto/lskcipher.c
new file mode 100644
index 000000000000..9edc89730951
--- /dev/null
+++ b/crypto/lskcipher.c
@@ -0,0 +1,634 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Linear symmetric key cipher operations.
+ *
+ * Generic encrypt/decrypt wrapper for ciphers.
+ *
+ * Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/cryptouser.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <net/netlink.h>
+#include "skcipher.h"
+
+static inline struct crypto_lskcipher *__crypto_lskcipher_cast(
+ struct crypto_tfm *tfm)
+{
+ return container_of(tfm, struct crypto_lskcipher, base);
+}
+
+static inline struct lskcipher_alg *__crypto_lskcipher_alg(
+ struct crypto_alg *alg)
+{
+ return container_of(alg, struct lskcipher_alg, co.base);
+}
+
+static inline struct crypto_istat_cipher *lskcipher_get_stat(
+ struct lskcipher_alg *alg)
+{
+ return skcipher_get_stat_common(&alg->co);
+}
+
+static inline int crypto_lskcipher_errstat(struct lskcipher_alg *alg, int err)
+{
+ struct crypto_istat_cipher *istat = lskcipher_get_stat(alg);
+
+ if (!IS_ENABLED(CONFIG_CRYPTO_STATS))
+ return err;
+
+ if (err)
+ atomic64_inc(&istat->err_cnt);
+
+ return err;
+}
+
+static int lskcipher_setkey_unaligned(struct crypto_lskcipher *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ unsigned long alignmask = crypto_lskcipher_alignmask(tfm);
+ struct lskcipher_alg *cipher = crypto_lskcipher_alg(tfm);
+ u8 *buffer, *alignbuffer;
+ unsigned long absize;
+ int ret;
+
+ absize = keylen + alignmask;
+ buffer = kmalloc(absize, GFP_ATOMIC);
+ if (!buffer)
+ return -ENOMEM;
+
+ alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+ memcpy(alignbuffer, key, keylen);
+ ret = cipher->setkey(tfm, alignbuffer, keylen);
+ kfree_sensitive(buffer);
+ return ret;
+}
+
+int crypto_lskcipher_setkey(struct crypto_lskcipher *tfm, const u8 *key,
+ unsigned int keylen)
+{
+ unsigned long alignmask = crypto_lskcipher_alignmask(tfm);
+ struct lskcipher_alg *cipher = crypto_lskcipher_alg(tfm);
+
+ if (keylen < cipher->co.min_keysize || keylen > cipher->co.max_keysize)
+ return -EINVAL;
+
+ if ((unsigned long)key & alignmask)
+ return lskcipher_setkey_unaligned(tfm, key, keylen);
+ else
+ return cipher->setkey(tfm, key, keylen);
+}
+EXPORT_SYMBOL_GPL(crypto_lskcipher_setkey);
+
+static int crypto_lskcipher_crypt_unaligned(
+ struct crypto_lskcipher *tfm, const u8 *src, u8 *dst, unsigned len,
+ u8 *iv, int (*crypt)(struct crypto_lskcipher *tfm, const u8 *src,
+ u8 *dst, unsigned len, u8 *iv, bool final))
+{
+ unsigned ivsize = crypto_lskcipher_ivsize(tfm);
+ unsigned bs = crypto_lskcipher_blocksize(tfm);
+ unsigned cs = crypto_lskcipher_chunksize(tfm);
+ int err;
+ u8 *tiv;
+ u8 *p;
+
+ BUILD_BUG_ON(MAX_CIPHER_BLOCKSIZE > PAGE_SIZE ||
+ MAX_CIPHER_ALIGNMASK >= PAGE_SIZE);
+
+ tiv = kmalloc(PAGE_SIZE, GFP_ATOMIC);
+ if (!tiv)
+ return -ENOMEM;
+
+ memcpy(tiv, iv, ivsize);
+
+ p = kmalloc(PAGE_SIZE, GFP_ATOMIC);
+ err = -ENOMEM;
+ if (!p)
+ goto out;
+
+ while (len >= bs) {
+ unsigned chunk = min((unsigned)PAGE_SIZE, len);
+ int err;
+
+ if (chunk > cs)
+ chunk &= ~(cs - 1);
+
+ memcpy(p, src, chunk);
+ err = crypt(tfm, p, p, chunk, tiv, true);
+ if (err)
+ goto out;
+
+ memcpy(dst, p, chunk);
+ src += chunk;
+ dst += chunk;
+ len -= chunk;
+ }
+
+ err = len ? -EINVAL : 0;
+
+out:
+ memcpy(iv, tiv, ivsize);
+ kfree_sensitive(p);
+ kfree_sensitive(tiv);
+ return err;
+}
+
+static int crypto_lskcipher_crypt(struct crypto_lskcipher *tfm, const u8 *src,
+ u8 *dst, unsigned len, u8 *iv,
+ int (*crypt)(struct crypto_lskcipher *tfm,
+ const u8 *src, u8 *dst,
+ unsigned len, u8 *iv,
+ bool final))
+{
+ unsigned long alignmask = crypto_lskcipher_alignmask(tfm);
+ struct lskcipher_alg *alg = crypto_lskcipher_alg(tfm);
+ int ret;
+
+ if (((unsigned long)src | (unsigned long)dst | (unsigned long)iv) &
+ alignmask) {
+ ret = crypto_lskcipher_crypt_unaligned(tfm, src, dst, len, iv,
+ crypt);
+ goto out;
+ }
+
+ ret = crypt(tfm, src, dst, len, iv, true);
+
+out:
+ return crypto_lskcipher_errstat(alg, ret);
+}
+
+int crypto_lskcipher_encrypt(struct crypto_lskcipher *tfm, const u8 *src,
+ u8 *dst, unsigned len, u8 *iv)
+{
+ struct lskcipher_alg *alg = crypto_lskcipher_alg(tfm);
+
+ if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
+ struct crypto_istat_cipher *istat = lskcipher_get_stat(alg);
+
+ atomic64_inc(&istat->encrypt_cnt);
+ atomic64_add(len, &istat->encrypt_tlen);
+ }
+
+ return crypto_lskcipher_crypt(tfm, src, dst, len, iv, alg->encrypt);
+}
+EXPORT_SYMBOL_GPL(crypto_lskcipher_encrypt);
+
+int crypto_lskcipher_decrypt(struct crypto_lskcipher *tfm, const u8 *src,
+ u8 *dst, unsigned len, u8 *iv)
+{
+ struct lskcipher_alg *alg = crypto_lskcipher_alg(tfm);
+
+ if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
+ struct crypto_istat_cipher *istat = lskcipher_get_stat(alg);
+
+ atomic64_inc(&istat->decrypt_cnt);
+ atomic64_add(len, &istat->decrypt_tlen);
+ }
+
+ return crypto_lskcipher_crypt(tfm, src, dst, len, iv, alg->decrypt);
+}
+EXPORT_SYMBOL_GPL(crypto_lskcipher_decrypt);
+
+static int crypto_lskcipher_crypt_sg(struct skcipher_request *req,
+ int (*crypt)(struct crypto_lskcipher *tfm,
+ const u8 *src, u8 *dst,
+ unsigned len, u8 *iv,
+ bool final))
+{
+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
+ struct crypto_lskcipher **ctx = crypto_skcipher_ctx(skcipher);
+ struct crypto_lskcipher *tfm = *ctx;
+ struct skcipher_walk walk;
+ int err;
+
+ err = skcipher_walk_virt(&walk, req, false);
+
+ while (walk.nbytes) {
+ err = crypt(tfm, walk.src.virt.addr, walk.dst.virt.addr,
+ walk.nbytes, walk.iv, walk.nbytes == walk.total);
+ err = skcipher_walk_done(&walk, err);
+ }
+
+ return err;
+}
+
+int crypto_lskcipher_encrypt_sg(struct skcipher_request *req)
+{
+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
+ struct crypto_lskcipher **ctx = crypto_skcipher_ctx(skcipher);
+ struct lskcipher_alg *alg = crypto_lskcipher_alg(*ctx);
+
+ return crypto_lskcipher_crypt_sg(req, alg->encrypt);
+}
+
+int crypto_lskcipher_decrypt_sg(struct skcipher_request *req)
+{
+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
+ struct crypto_lskcipher **ctx = crypto_skcipher_ctx(skcipher);
+ struct lskcipher_alg *alg = crypto_lskcipher_alg(*ctx);
+
+ return crypto_lskcipher_crypt_sg(req, alg->decrypt);
+}
+
+static void crypto_lskcipher_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_lskcipher *skcipher = __crypto_lskcipher_cast(tfm);
+ struct lskcipher_alg *alg = crypto_lskcipher_alg(skcipher);
+
+ alg->exit(skcipher);
+}
+
+static int crypto_lskcipher_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_lskcipher *skcipher = __crypto_lskcipher_cast(tfm);
+ struct lskcipher_alg *alg = crypto_lskcipher_alg(skcipher);
+
+ if (alg->exit)
+ skcipher->base.exit = crypto_lskcipher_exit_tfm;
+
+ if (alg->init)
+ return alg->init(skcipher);
+
+ return 0;
+}
+
+static void crypto_lskcipher_free_instance(struct crypto_instance *inst)
+{
+ struct lskcipher_instance *skcipher =
+ container_of(inst, struct lskcipher_instance, s.base);
+
+ skcipher->free(skcipher);
+}
+
+static void __maybe_unused crypto_lskcipher_show(
+ struct seq_file *m, struct crypto_alg *alg)
+{
+ struct lskcipher_alg *skcipher = __crypto_lskcipher_alg(alg);
+
+ seq_printf(m, "type : lskcipher\n");
+ seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
+ seq_printf(m, "min keysize : %u\n", skcipher->co.min_keysize);
+ seq_printf(m, "max keysize : %u\n", skcipher->co.max_keysize);
+ seq_printf(m, "ivsize : %u\n", skcipher->co.ivsize);
+ seq_printf(m, "chunksize : %u\n", skcipher->co.chunksize);
+}
+
+static int __maybe_unused crypto_lskcipher_report(
+ struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct lskcipher_alg *skcipher = __crypto_lskcipher_alg(alg);
+ struct crypto_report_blkcipher rblkcipher;
+
+ memset(&rblkcipher, 0, sizeof(rblkcipher));
+
+ strscpy(rblkcipher.type, "lskcipher", sizeof(rblkcipher.type));
+ strscpy(rblkcipher.geniv, "<none>", sizeof(rblkcipher.geniv));
+
+ rblkcipher.blocksize = alg->cra_blocksize;
+ rblkcipher.min_keysize = skcipher->co.min_keysize;
+ rblkcipher.max_keysize = skcipher->co.max_keysize;
+ rblkcipher.ivsize = skcipher->co.ivsize;
+
+ return nla_put(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+ sizeof(rblkcipher), &rblkcipher);
+}
+
+static int __maybe_unused crypto_lskcipher_report_stat(
+ struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct lskcipher_alg *skcipher = __crypto_lskcipher_alg(alg);
+ struct crypto_istat_cipher *istat;
+ struct crypto_stat_cipher rcipher;
+
+ istat = lskcipher_get_stat(skcipher);
+
+ memset(&rcipher, 0, sizeof(rcipher));
+
+ strscpy(rcipher.type, "cipher", sizeof(rcipher.type));
+
+ rcipher.stat_encrypt_cnt = atomic64_read(&istat->encrypt_cnt);
+ rcipher.stat_encrypt_tlen = atomic64_read(&istat->encrypt_tlen);
+ rcipher.stat_decrypt_cnt = atomic64_read(&istat->decrypt_cnt);
+ rcipher.stat_decrypt_tlen = atomic64_read(&istat->decrypt_tlen);
+ rcipher.stat_err_cnt = atomic64_read(&istat->err_cnt);
+
+ return nla_put(skb, CRYPTOCFGA_STAT_CIPHER, sizeof(rcipher), &rcipher);
+}
+
+static const struct crypto_type crypto_lskcipher_type = {
+ .extsize = crypto_alg_extsize,
+ .init_tfm = crypto_lskcipher_init_tfm,
+ .free = crypto_lskcipher_free_instance,
+#ifdef CONFIG_PROC_FS
+ .show = crypto_lskcipher_show,
+#endif
+#if IS_ENABLED(CONFIG_CRYPTO_USER)
+ .report = crypto_lskcipher_report,
+#endif
+#ifdef CONFIG_CRYPTO_STATS
+ .report_stat = crypto_lskcipher_report_stat,
+#endif
+ .maskclear = ~CRYPTO_ALG_TYPE_MASK,
+ .maskset = CRYPTO_ALG_TYPE_MASK,
+ .type = CRYPTO_ALG_TYPE_LSKCIPHER,
+ .tfmsize = offsetof(struct crypto_lskcipher, base),
+};
+
+static void crypto_lskcipher_exit_tfm_sg(struct crypto_tfm *tfm)
+{
+ struct crypto_lskcipher **ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_lskcipher(*ctx);
+}
+
+int crypto_init_lskcipher_ops_sg(struct crypto_tfm *tfm)
+{
+ struct crypto_lskcipher **ctx = crypto_tfm_ctx(tfm);
+ struct crypto_alg *calg = tfm->__crt_alg;
+ struct crypto_lskcipher *skcipher;
+
+ if (!crypto_mod_get(calg))
+ return -EAGAIN;
+
+ skcipher = crypto_create_tfm(calg, &crypto_lskcipher_type);
+ if (IS_ERR(skcipher)) {
+ crypto_mod_put(calg);
+ return PTR_ERR(skcipher);
+ }
+
+ *ctx = skcipher;
+ tfm->exit = crypto_lskcipher_exit_tfm_sg;
+
+ return 0;
+}
+
+int crypto_grab_lskcipher(struct crypto_lskcipher_spawn *spawn,
+ struct crypto_instance *inst,
+ const char *name, u32 type, u32 mask)
+{
+ spawn->base.frontend = &crypto_lskcipher_type;
+ return crypto_grab_spawn(&spawn->base, inst, name, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_grab_lskcipher);
+
+struct crypto_lskcipher *crypto_alloc_lskcipher(const char *alg_name,
+ u32 type, u32 mask)
+{
+ return crypto_alloc_tfm(alg_name, &crypto_lskcipher_type, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_lskcipher);
+
+static int lskcipher_prepare_alg(struct lskcipher_alg *alg)
+{
+ struct crypto_alg *base = &alg->co.base;
+ int err;
+
+ err = skcipher_prepare_alg_common(&alg->co);
+ if (err)
+ return err;
+
+ if (alg->co.chunksize & (alg->co.chunksize - 1))
+ return -EINVAL;
+
+ base->cra_type = &crypto_lskcipher_type;
+ base->cra_flags |= CRYPTO_ALG_TYPE_LSKCIPHER;
+
+ return 0;
+}
+
+int crypto_register_lskcipher(struct lskcipher_alg *alg)
+{
+ struct crypto_alg *base = &alg->co.base;
+ int err;
+
+ err = lskcipher_prepare_alg(alg);
+ if (err)
+ return err;
+
+ return crypto_register_alg(base);
+}
+EXPORT_SYMBOL_GPL(crypto_register_lskcipher);
+
+void crypto_unregister_lskcipher(struct lskcipher_alg *alg)
+{
+ crypto_unregister_alg(&alg->co.base);
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_lskcipher);
+
+int crypto_register_lskciphers(struct lskcipher_alg *algs, int count)
+{
+ int i, ret;
+
+ for (i = 0; i < count; i++) {
+ ret = crypto_register_lskcipher(&algs[i]);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ for (--i; i >= 0; --i)
+ crypto_unregister_lskcipher(&algs[i]);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(crypto_register_lskciphers);
+
+void crypto_unregister_lskciphers(struct lskcipher_alg *algs, int count)
+{
+ int i;
+
+ for (i = count - 1; i >= 0; --i)
+ crypto_unregister_lskcipher(&algs[i]);
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_lskciphers);
+
+int lskcipher_register_instance(struct crypto_template *tmpl,
+ struct lskcipher_instance *inst)
+{
+ int err;
+
+ if (WARN_ON(!inst->free))
+ return -EINVAL;
+
+ err = lskcipher_prepare_alg(&inst->alg);
+ if (err)
+ return err;
+
+ return crypto_register_instance(tmpl, lskcipher_crypto_instance(inst));
+}
+EXPORT_SYMBOL_GPL(lskcipher_register_instance);
+
+static int lskcipher_setkey_simple(struct crypto_lskcipher *tfm, const u8 *key,
+ unsigned int keylen)
+{
+ struct crypto_lskcipher *cipher = lskcipher_cipher_simple(tfm);
+
+ crypto_lskcipher_clear_flags(cipher, CRYPTO_TFM_REQ_MASK);
+ crypto_lskcipher_set_flags(cipher, crypto_lskcipher_get_flags(tfm) &
+ CRYPTO_TFM_REQ_MASK);
+ return crypto_lskcipher_setkey(cipher, key, keylen);
+}
+
+static int lskcipher_init_tfm_simple(struct crypto_lskcipher *tfm)
+{
+ struct lskcipher_instance *inst = lskcipher_alg_instance(tfm);
+ struct crypto_lskcipher **ctx = crypto_lskcipher_ctx(tfm);
+ struct crypto_lskcipher_spawn *spawn;
+ struct crypto_lskcipher *cipher;
+
+ spawn = lskcipher_instance_ctx(inst);
+ cipher = crypto_spawn_lskcipher(spawn);
+ if (IS_ERR(cipher))
+ return PTR_ERR(cipher);
+
+ *ctx = cipher;
+ return 0;
+}
+
+static void lskcipher_exit_tfm_simple(struct crypto_lskcipher *tfm)
+{
+ struct crypto_lskcipher **ctx = crypto_lskcipher_ctx(tfm);
+
+ crypto_free_lskcipher(*ctx);
+}
+
+static void lskcipher_free_instance_simple(struct lskcipher_instance *inst)
+{
+ crypto_drop_lskcipher(lskcipher_instance_ctx(inst));
+ kfree(inst);
+}
+
+/**
+ * lskcipher_alloc_instance_simple - allocate instance of simple block cipher
+ *
+ * Allocate an lskcipher_instance for a simple block cipher mode of operation,
+ * e.g. cbc or ecb. The instance context will have just a single crypto_spawn,
+ * that for the underlying cipher. The {min,max}_keysize, ivsize, blocksize,
+ * alignmask, and priority are set from the underlying cipher but can be
+ * overridden if needed. The tfm context defaults to
+ * struct crypto_lskcipher *, and default ->setkey(), ->init(), and
+ * ->exit() methods are installed.
+ *
+ * @tmpl: the template being instantiated
+ * @tb: the template parameters
+ *
+ * Return: a pointer to the new instance, or an ERR_PTR(). The caller still
+ * needs to register the instance.
+ */
+struct lskcipher_instance *lskcipher_alloc_instance_simple(
+ struct crypto_template *tmpl, struct rtattr **tb)
+{
+ u32 mask;
+ struct lskcipher_instance *inst;
+ struct crypto_lskcipher_spawn *spawn;
+ char ecb_name[CRYPTO_MAX_ALG_NAME];
+ struct lskcipher_alg *cipher_alg;
+ const char *cipher_name;
+ int err;
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_LSKCIPHER, &mask);
+ if (err)
+ return ERR_PTR(err);
+
+ cipher_name = crypto_attr_alg_name(tb[1]);
+ if (IS_ERR(cipher_name))
+ return ERR_CAST(cipher_name);
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+ if (!inst)
+ return ERR_PTR(-ENOMEM);
+
+ spawn = lskcipher_instance_ctx(inst);
+ err = crypto_grab_lskcipher(spawn,
+ lskcipher_crypto_instance(inst),
+ cipher_name, 0, mask);
+
+ ecb_name[0] = 0;
+ if (err == -ENOENT && !!memcmp(tmpl->name, "ecb", 4)) {
+ err = -ENAMETOOLONG;
+ if (snprintf(ecb_name, CRYPTO_MAX_ALG_NAME, "ecb(%s)",
+ cipher_name) >= CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+
+ err = crypto_grab_lskcipher(spawn,
+ lskcipher_crypto_instance(inst),
+ ecb_name, 0, mask);
+ }
+
+ if (err)
+ goto err_free_inst;
+
+ cipher_alg = crypto_lskcipher_spawn_alg(spawn);
+
+ err = crypto_inst_setname(lskcipher_crypto_instance(inst), tmpl->name,
+ &cipher_alg->co.base);
+ if (err)
+ goto err_free_inst;
+
+ if (ecb_name[0]) {
+ int len;
+
+ err = -EINVAL;
+ len = strscpy(ecb_name, &cipher_alg->co.base.cra_name[4],
+ sizeof(ecb_name));
+ if (len < 2)
+ goto err_free_inst;
+
+ if (ecb_name[len - 1] != ')')
+ goto err_free_inst;
+
+ ecb_name[len - 1] = 0;
+
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.co.base.cra_name, CRYPTO_MAX_ALG_NAME,
+ "%s(%s)", tmpl->name, ecb_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+
+ if (strcmp(ecb_name, cipher_name) &&
+ snprintf(inst->alg.co.base.cra_driver_name,
+ CRYPTO_MAX_ALG_NAME,
+ "%s(%s)", tmpl->name, cipher_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+ } else {
+ /* Don't allow nesting. */
+ err = -ELOOP;
+ if ((cipher_alg->co.base.cra_flags & CRYPTO_ALG_INSTANCE))
+ goto err_free_inst;
+ }
+
+ err = -EINVAL;
+ if (cipher_alg->co.ivsize)
+ goto err_free_inst;
+
+ inst->free = lskcipher_free_instance_simple;
+
+ /* Default algorithm properties, can be overridden */
+ inst->alg.co.base.cra_blocksize = cipher_alg->co.base.cra_blocksize;
+ inst->alg.co.base.cra_alignmask = cipher_alg->co.base.cra_alignmask;
+ inst->alg.co.base.cra_priority = cipher_alg->co.base.cra_priority;
+ inst->alg.co.min_keysize = cipher_alg->co.min_keysize;
+ inst->alg.co.max_keysize = cipher_alg->co.max_keysize;
+ inst->alg.co.ivsize = cipher_alg->co.base.cra_blocksize;
+
+ /* Use struct crypto_lskcipher * by default, can be overridden */
+ inst->alg.co.base.cra_ctxsize = sizeof(struct crypto_lskcipher *);
+ inst->alg.setkey = lskcipher_setkey_simple;
+ inst->alg.init = lskcipher_init_tfm_simple;
+ inst->alg.exit = lskcipher_exit_tfm_simple;
+
+ return inst;
+
+err_free_inst:
+ lskcipher_free_instance_simple(inst);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(lskcipher_alloc_instance_simple);
diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c
index 8c1d0ca41213..d0d954fe9d54 100644
--- a/crypto/pcrypt.c
+++ b/crypto/pcrypt.c
@@ -117,6 +117,8 @@ static int pcrypt_aead_encrypt(struct aead_request *req)
err = padata_do_parallel(ictx->psenc, padata, &ctx->cb_cpu);
if (!err)
return -EINPROGRESS;
+ if (err == -EBUSY)
+ return -EAGAIN;
return err;
}
@@ -164,6 +166,8 @@ static int pcrypt_aead_decrypt(struct aead_request *req)
err = padata_do_parallel(ictx->psdec, padata, &ctx->cb_cpu);
if (!err)
return -EINPROGRESS;
+ if (err == -EBUSY)
+ return -EAGAIN;
return err;
}
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index d2e5e104f8cf..cd501195f34a 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -61,6 +61,24 @@ static const u8 rsa_digest_info_sha512[] = {
0x05, 0x00, 0x04, 0x40
};
+static const u8 rsa_digest_info_sha3_256[] = {
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08,
+ 0x05, 0x00, 0x04, 0x20
+};
+
+static const u8 rsa_digest_info_sha3_384[] = {
+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09,
+ 0x05, 0x00, 0x04, 0x30
+};
+
+static const u8 rsa_digest_info_sha3_512[] = {
+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0A,
+ 0x05, 0x00, 0x04, 0x40
+};
+
static const struct rsa_asn1_template {
const char *name;
const u8 *data;
@@ -74,8 +92,13 @@ static const struct rsa_asn1_template {
_(sha384),
_(sha512),
_(sha224),
- { NULL }
#undef _
+#define _(X) { "sha3-" #X, rsa_digest_info_sha3_##X, sizeof(rsa_digest_info_sha3_##X) }
+ _(256),
+ _(384),
+ _(512),
+#undef _
+ { NULL }
};
static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
@@ -687,3 +710,5 @@ struct crypto_template rsa_pkcs1pad_tmpl = {
.create = pkcs1pad_create,
.module = THIS_MODULE,
};
+
+MODULE_ALIAS_CRYPTO("pkcs1pad");
diff --git a/crypto/rsaprivkey.asn1 b/crypto/rsaprivkey.asn1
index 4ce06758e8af..76865124a9c7 100644
--- a/crypto/rsaprivkey.asn1
+++ b/crypto/rsaprivkey.asn1
@@ -1,3 +1,10 @@
+-- SPDX-License-Identifier: BSD-3-Clause
+--
+-- Copyright (C) 2016 IETF Trust and the persons identified as authors
+-- of the code
+--
+-- https://www.rfc-editor.org/rfc/rfc8017#appendix-A.1.2
+
RsaPrivKey ::= SEQUENCE {
version INTEGER,
n INTEGER ({ rsa_get_n }),
diff --git a/crypto/rsapubkey.asn1 b/crypto/rsapubkey.asn1
index 725498e461d2..0d32b1ca6270 100644
--- a/crypto/rsapubkey.asn1
+++ b/crypto/rsapubkey.asn1
@@ -1,3 +1,10 @@
+-- SPDX-License-Identifier: BSD-3-Clause
+--
+-- Copyright (C) 2016 IETF Trust and the persons identified as authors
+-- of the code
+--
+-- https://www.rfc-editor.org/rfc/rfc8017#appendix-A.1.1
+
RsaPubKey ::= SEQUENCE {
n INTEGER ({ rsa_get_n }),
e INTEGER ({ rsa_get_e })
diff --git a/crypto/shash.c b/crypto/shash.c
index 1fadb6b59bdc..d5194221c88c 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -10,17 +10,12 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
#include <linux/seq_file.h>
#include <linux/string.h>
#include <net/netlink.h>
#include "hash.h"
-#define MAX_SHASH_ALIGNMASK 63
-
-static const struct crypto_type crypto_shash_type;
-
static inline struct crypto_istat_hash *shash_get_stat(struct shash_alg *alg)
{
return hash_get_stat(&alg->halg);
@@ -28,7 +23,13 @@ static inline struct crypto_istat_hash *shash_get_stat(struct shash_alg *alg)
static inline int crypto_shash_errstat(struct shash_alg *alg, int err)
{
- return crypto_hash_errstat(&alg->halg, err);
+ if (!IS_ENABLED(CONFIG_CRYPTO_STATS))
+ return err;
+
+ if (err && err != -EINPROGRESS && err != -EBUSY)
+ atomic64_inc(&shash_get_stat(alg)->err_cnt);
+
+ return err;
}
int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
@@ -38,27 +39,6 @@ int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
}
EXPORT_SYMBOL_GPL(shash_no_setkey);
-static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
- unsigned int keylen)
-{
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
- unsigned long absize;
- u8 *buffer, *alignbuffer;
- int err;
-
- absize = keylen + (alignmask & ~(crypto_tfm_ctx_alignment() - 1));
- buffer = kmalloc(absize, GFP_ATOMIC);
- if (!buffer)
- return -ENOMEM;
-
- alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
- memcpy(alignbuffer, key, keylen);
- err = shash->setkey(tfm, alignbuffer, keylen);
- kfree_sensitive(buffer);
- return err;
-}
-
static void shash_set_needkey(struct crypto_shash *tfm, struct shash_alg *alg)
{
if (crypto_shash_alg_needs_key(alg))
@@ -69,14 +49,9 @@ int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
unsigned int keylen)
{
struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
int err;
- if ((unsigned long)key & alignmask)
- err = shash_setkey_unaligned(tfm, key, keylen);
- else
- err = shash->setkey(tfm, key, keylen);
-
+ err = shash->setkey(tfm, key, keylen);
if (unlikely(err)) {
shash_set_needkey(tfm, shash);
return err;
@@ -87,108 +62,42 @@ int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
}
EXPORT_SYMBOL_GPL(crypto_shash_setkey);
-static int shash_update_unaligned(struct shash_desc *desc, const u8 *data,
- unsigned int len)
-{
- struct crypto_shash *tfm = desc->tfm;
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
- unsigned int unaligned_len = alignmask + 1 -
- ((unsigned long)data & alignmask);
- /*
- * We cannot count on __aligned() working for large values:
- * https://patchwork.kernel.org/patch/9507697/
- */
- u8 ubuf[MAX_SHASH_ALIGNMASK * 2];
- u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
- int err;
-
- if (WARN_ON(buf + unaligned_len > ubuf + sizeof(ubuf)))
- return -EINVAL;
-
- if (unaligned_len > len)
- unaligned_len = len;
-
- memcpy(buf, data, unaligned_len);
- err = shash->update(desc, buf, unaligned_len);
- memset(buf, 0, unaligned_len);
-
- return err ?:
- shash->update(desc, data + unaligned_len, len - unaligned_len);
-}
-
int crypto_shash_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
- struct crypto_shash *tfm = desc->tfm;
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
+ struct shash_alg *shash = crypto_shash_alg(desc->tfm);
int err;
if (IS_ENABLED(CONFIG_CRYPTO_STATS))
atomic64_add(len, &shash_get_stat(shash)->hash_tlen);
- if ((unsigned long)data & alignmask)
- err = shash_update_unaligned(desc, data, len);
- else
- err = shash->update(desc, data, len);
+ err = shash->update(desc, data, len);
return crypto_shash_errstat(shash, err);
}
EXPORT_SYMBOL_GPL(crypto_shash_update);
-static int shash_final_unaligned(struct shash_desc *desc, u8 *out)
-{
- struct crypto_shash *tfm = desc->tfm;
- unsigned long alignmask = crypto_shash_alignmask(tfm);
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned int ds = crypto_shash_digestsize(tfm);
- /*
- * We cannot count on __aligned() working for large values:
- * https://patchwork.kernel.org/patch/9507697/
- */
- u8 ubuf[MAX_SHASH_ALIGNMASK + HASH_MAX_DIGESTSIZE];
- u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
- int err;
-
- if (WARN_ON(buf + ds > ubuf + sizeof(ubuf)))
- return -EINVAL;
-
- err = shash->final(desc, buf);
- if (err)
- goto out;
-
- memcpy(out, buf, ds);
-
-out:
- memset(buf, 0, ds);
- return err;
-}
-
int crypto_shash_final(struct shash_desc *desc, u8 *out)
{
- struct crypto_shash *tfm = desc->tfm;
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
+ struct shash_alg *shash = crypto_shash_alg(desc->tfm);
int err;
if (IS_ENABLED(CONFIG_CRYPTO_STATS))
atomic64_inc(&shash_get_stat(shash)->hash_cnt);
- if ((unsigned long)out & alignmask)
- err = shash_final_unaligned(desc, out);
- else
- err = shash->final(desc, out);
+ err = shash->final(desc, out);
return crypto_shash_errstat(shash, err);
}
EXPORT_SYMBOL_GPL(crypto_shash_final);
-static int shash_finup_unaligned(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
+static int shash_default_finup(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
{
- return shash_update_unaligned(desc, data, len) ?:
- shash_final_unaligned(desc, out);
+ struct shash_alg *shash = crypto_shash_alg(desc->tfm);
+
+ return shash->update(desc, data, len) ?:
+ shash->final(desc, out);
}
int crypto_shash_finup(struct shash_desc *desc, const u8 *data,
@@ -196,7 +105,6 @@ int crypto_shash_finup(struct shash_desc *desc, const u8 *data,
{
struct crypto_shash *tfm = desc->tfm;
struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
int err;
if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
@@ -206,22 +114,19 @@ int crypto_shash_finup(struct shash_desc *desc, const u8 *data,
atomic64_add(len, &istat->hash_tlen);
}
- if (((unsigned long)data | (unsigned long)out) & alignmask)
- err = shash_finup_unaligned(desc, data, len, out);
- else
- err = shash->finup(desc, data, len, out);
-
+ err = shash->finup(desc, data, len, out);
return crypto_shash_errstat(shash, err);
}
EXPORT_SYMBOL_GPL(crypto_shash_finup);
-static int shash_digest_unaligned(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
+static int shash_default_digest(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
{
- return crypto_shash_init(desc) ?:
- shash_update_unaligned(desc, data, len) ?:
- shash_final_unaligned(desc, out);
+ struct shash_alg *shash = crypto_shash_alg(desc->tfm);
+
+ return shash->init(desc) ?:
+ shash->finup(desc, data, len, out);
}
int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
@@ -229,7 +134,6 @@ int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
{
struct crypto_shash *tfm = desc->tfm;
struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
int err;
if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
@@ -241,8 +145,6 @@ int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
err = -ENOKEY;
- else if (((unsigned long)data | (unsigned long)out) & alignmask)
- err = shash_digest_unaligned(desc, data, len, out);
else
err = shash->digest(desc, data, len, out);
@@ -266,202 +168,34 @@ int crypto_shash_tfm_digest(struct crypto_shash *tfm, const u8 *data,
}
EXPORT_SYMBOL_GPL(crypto_shash_tfm_digest);
-static int shash_default_export(struct shash_desc *desc, void *out)
-{
- memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(desc->tfm));
- return 0;
-}
-
-static int shash_default_import(struct shash_desc *desc, const void *in)
-{
- memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(desc->tfm));
- return 0;
-}
-
-static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
- unsigned int keylen)
-{
- struct crypto_shash **ctx = crypto_ahash_ctx(tfm);
-
- return crypto_shash_setkey(*ctx, key, keylen);
-}
-
-static int shash_async_init(struct ahash_request *req)
-{
- struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
- struct shash_desc *desc = ahash_request_ctx(req);
-
- desc->tfm = *ctx;
-
- return crypto_shash_init(desc);
-}
-
-int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc)
-{
- struct crypto_hash_walk walk;
- int nbytes;
-
- for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0;
- nbytes = crypto_hash_walk_done(&walk, nbytes))
- nbytes = crypto_shash_update(desc, walk.data, nbytes);
-
- return nbytes;
-}
-EXPORT_SYMBOL_GPL(shash_ahash_update);
-
-static int shash_async_update(struct ahash_request *req)
-{
- return shash_ahash_update(req, ahash_request_ctx(req));
-}
-
-static int shash_async_final(struct ahash_request *req)
-{
- return crypto_shash_final(ahash_request_ctx(req), req->result);
-}
-
-int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc)
-{
- struct crypto_hash_walk walk;
- int nbytes;
-
- nbytes = crypto_hash_walk_first(req, &walk);
- if (!nbytes)
- return crypto_shash_final(desc, req->result);
-
- do {
- nbytes = crypto_hash_walk_last(&walk) ?
- crypto_shash_finup(desc, walk.data, nbytes,
- req->result) :
- crypto_shash_update(desc, walk.data, nbytes);
- nbytes = crypto_hash_walk_done(&walk, nbytes);
- } while (nbytes > 0);
-
- return nbytes;
-}
-EXPORT_SYMBOL_GPL(shash_ahash_finup);
-
-static int shash_async_finup(struct ahash_request *req)
-{
- struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
- struct shash_desc *desc = ahash_request_ctx(req);
-
- desc->tfm = *ctx;
-
- return shash_ahash_finup(req, desc);
-}
-
-int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc)
-{
- unsigned int nbytes = req->nbytes;
- struct scatterlist *sg;
- unsigned int offset;
- int err;
-
- if (nbytes &&
- (sg = req->src, offset = sg->offset,
- nbytes <= min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) {
- void *data;
-
- data = kmap_local_page(sg_page(sg));
- err = crypto_shash_digest(desc, data + offset, nbytes,
- req->result);
- kunmap_local(data);
- } else
- err = crypto_shash_init(desc) ?:
- shash_ahash_finup(req, desc);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(shash_ahash_digest);
-
-static int shash_async_digest(struct ahash_request *req)
-{
- struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
- struct shash_desc *desc = ahash_request_ctx(req);
-
- desc->tfm = *ctx;
-
- return shash_ahash_digest(req, desc);
-}
-
-static int shash_async_export(struct ahash_request *req, void *out)
-{
- return crypto_shash_export(ahash_request_ctx(req), out);
-}
-
-static int shash_async_import(struct ahash_request *req, const void *in)
-{
- struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
- struct shash_desc *desc = ahash_request_ctx(req);
-
- desc->tfm = *ctx;
-
- return crypto_shash_import(desc, in);
-}
-
-static void crypto_exit_shash_ops_async(struct crypto_tfm *tfm)
+int crypto_shash_export(struct shash_desc *desc, void *out)
{
- struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
-
- crypto_free_shash(*ctx);
-}
-
-int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
-{
- struct crypto_alg *calg = tfm->__crt_alg;
- struct shash_alg *alg = __crypto_shash_alg(calg);
- struct crypto_ahash *crt = __crypto_ahash_cast(tfm);
- struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
- struct crypto_shash *shash;
-
- if (!crypto_mod_get(calg))
- return -EAGAIN;
-
- shash = crypto_create_tfm(calg, &crypto_shash_type);
- if (IS_ERR(shash)) {
- crypto_mod_put(calg);
- return PTR_ERR(shash);
- }
-
- *ctx = shash;
- tfm->exit = crypto_exit_shash_ops_async;
-
- crt->init = shash_async_init;
- crt->update = shash_async_update;
- crt->final = shash_async_final;
- crt->finup = shash_async_finup;
- crt->digest = shash_async_digest;
- if (crypto_shash_alg_has_setkey(alg))
- crt->setkey = shash_async_setkey;
-
- crypto_ahash_set_flags(crt, crypto_shash_get_flags(shash) &
- CRYPTO_TFM_NEED_KEY);
-
- crt->export = shash_async_export;
- crt->import = shash_async_import;
+ struct crypto_shash *tfm = desc->tfm;
+ struct shash_alg *shash = crypto_shash_alg(tfm);
- crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash);
+ if (shash->export)
+ return shash->export(desc, out);
+ memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(tfm));
return 0;
}
+EXPORT_SYMBOL_GPL(crypto_shash_export);
-struct crypto_ahash *crypto_clone_shash_ops_async(struct crypto_ahash *nhash,
- struct crypto_ahash *hash)
+int crypto_shash_import(struct shash_desc *desc, const void *in)
{
- struct crypto_shash **nctx = crypto_ahash_ctx(nhash);
- struct crypto_shash **ctx = crypto_ahash_ctx(hash);
- struct crypto_shash *shash;
+ struct crypto_shash *tfm = desc->tfm;
+ struct shash_alg *shash = crypto_shash_alg(tfm);
- shash = crypto_clone_shash(*ctx);
- if (IS_ERR(shash)) {
- crypto_free_ahash(nhash);
- return ERR_CAST(shash);
- }
+ if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
+ return -ENOKEY;
- *nctx = shash;
+ if (shash->import)
+ return shash->import(desc, in);
- return nhash;
+ memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(tfm));
+ return 0;
}
+EXPORT_SYMBOL_GPL(crypto_shash_import);
static void crypto_shash_exit_tfm(struct crypto_tfm *tfm)
{
@@ -541,7 +275,7 @@ static int __maybe_unused crypto_shash_report_stat(
return crypto_hash_report_stat(skb, alg, "shash");
}
-static const struct crypto_type crypto_shash_type = {
+const struct crypto_type crypto_shash_type = {
.extsize = crypto_alg_extsize,
.init_tfm = crypto_shash_init_tfm,
.free = crypto_shash_free_instance,
@@ -626,6 +360,10 @@ int hash_prepare_alg(struct hash_alg_common *alg)
if (alg->digestsize > HASH_MAX_DIGESTSIZE)
return -EINVAL;
+ /* alignmask is not useful for hashes, so it is not supported. */
+ if (base->cra_alignmask)
+ return -EINVAL;
+
base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
if (IS_ENABLED(CONFIG_CRYPTO_STATS))
@@ -642,9 +380,6 @@ static int shash_prepare_alg(struct shash_alg *alg)
if (alg->descsize > HASH_MAX_DESCSIZE)
return -EINVAL;
- if (base->cra_alignmask > MAX_SHASH_ALIGNMASK)
- return -EINVAL;
-
if ((alg->export && !alg->import) || (alg->import && !alg->export))
return -EINVAL;
@@ -655,15 +390,23 @@ static int shash_prepare_alg(struct shash_alg *alg)
base->cra_type = &crypto_shash_type;
base->cra_flags |= CRYPTO_ALG_TYPE_SHASH;
+ /*
+ * Handle missing optional functions. For each one we can either
+ * install a default here, or we can leave the pointer as NULL and check
+ * the pointer for NULL in crypto_shash_*(), avoiding an indirect call
+ * when the default behavior is desired. For ->finup and ->digest we
+ * install defaults, since for optimal performance algorithms should
+ * implement these anyway. On the other hand, for ->import and
+ * ->export the common case and best performance comes from the simple
+ * memcpy of the shash_desc_ctx, so when those pointers are NULL we
+ * leave them NULL and provide the memcpy with no indirect call.
+ */
if (!alg->finup)
- alg->finup = shash_finup_unaligned;
+ alg->finup = shash_default_finup;
if (!alg->digest)
- alg->digest = shash_digest_unaligned;
- if (!alg->export) {
- alg->export = shash_default_export;
- alg->import = shash_default_import;
+ alg->digest = shash_default_digest;
+ if (!alg->export)
alg->halg.statesize = alg->descsize;
- }
if (!alg->setkey)
alg->setkey = shash_no_setkey;
diff --git a/crypto/skcipher.c b/crypto/skcipher.c
index 7b275716cf4e..ac8b8c042654 100644
--- a/crypto/skcipher.c
+++ b/crypto/skcipher.c
@@ -24,8 +24,9 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <net/netlink.h>
+#include "skcipher.h"
-#include "internal.h"
+#define CRYPTO_ALG_TYPE_SKCIPHER_MASK 0x0000000e
enum {
SKCIPHER_WALK_PHYS = 1 << 0,
@@ -43,6 +44,8 @@ struct skcipher_walk_buffer {
u8 buffer[];
};
+static const struct crypto_type crypto_skcipher_type;
+
static int skcipher_walk_next(struct skcipher_walk *walk);
static inline void skcipher_map_src(struct skcipher_walk *walk)
@@ -89,11 +92,7 @@ static inline struct skcipher_alg *__crypto_skcipher_alg(
static inline struct crypto_istat_cipher *skcipher_get_stat(
struct skcipher_alg *alg)
{
-#ifdef CONFIG_CRYPTO_STATS
- return &alg->stat;
-#else
- return NULL;
-#endif
+ return skcipher_get_stat_common(&alg->co);
}
static inline int crypto_skcipher_errstat(struct skcipher_alg *alg, int err)
@@ -468,6 +467,7 @@ static int skcipher_walk_skcipher(struct skcipher_walk *walk,
struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+ struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
walk->total = req->cryptlen;
walk->nbytes = 0;
@@ -485,10 +485,14 @@ static int skcipher_walk_skcipher(struct skcipher_walk *walk,
SKCIPHER_WALK_SLEEP : 0;
walk->blocksize = crypto_skcipher_blocksize(tfm);
- walk->stride = crypto_skcipher_walksize(tfm);
walk->ivsize = crypto_skcipher_ivsize(tfm);
walk->alignmask = crypto_skcipher_alignmask(tfm);
+ if (alg->co.base.cra_type != &crypto_skcipher_type)
+ walk->stride = alg->co.chunksize;
+ else
+ walk->stride = alg->walksize;
+
return skcipher_walk_first(walk);
}
@@ -616,6 +620,17 @@ int crypto_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
unsigned long alignmask = crypto_skcipher_alignmask(tfm);
int err;
+ if (cipher->co.base.cra_type != &crypto_skcipher_type) {
+ struct crypto_lskcipher **ctx = crypto_skcipher_ctx(tfm);
+
+ crypto_lskcipher_clear_flags(*ctx, CRYPTO_TFM_REQ_MASK);
+ crypto_lskcipher_set_flags(*ctx,
+ crypto_skcipher_get_flags(tfm) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_lskcipher_setkey(*ctx, key, keylen);
+ goto out;
+ }
+
if (keylen < cipher->min_keysize || keylen > cipher->max_keysize)
return -EINVAL;
@@ -624,6 +639,7 @@ int crypto_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
else
err = cipher->setkey(tfm, key, keylen);
+out:
if (unlikely(err)) {
skcipher_set_needkey(tfm);
return err;
@@ -649,6 +665,8 @@ int crypto_skcipher_encrypt(struct skcipher_request *req)
if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
ret = -ENOKEY;
+ else if (alg->co.base.cra_type != &crypto_skcipher_type)
+ ret = crypto_lskcipher_encrypt_sg(req);
else
ret = alg->encrypt(req);
@@ -671,6 +689,8 @@ int crypto_skcipher_decrypt(struct skcipher_request *req)
if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
ret = -ENOKEY;
+ else if (alg->co.base.cra_type != &crypto_skcipher_type)
+ ret = crypto_lskcipher_decrypt_sg(req);
else
ret = alg->decrypt(req);
@@ -693,6 +713,9 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm)
skcipher_set_needkey(skcipher);
+ if (tfm->__crt_alg->cra_type != &crypto_skcipher_type)
+ return crypto_init_lskcipher_ops_sg(tfm);
+
if (alg->exit)
skcipher->base.exit = crypto_skcipher_exit_tfm;
@@ -702,6 +725,14 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm)
return 0;
}
+static unsigned int crypto_skcipher_extsize(struct crypto_alg *alg)
+{
+ if (alg->cra_type != &crypto_skcipher_type)
+ return sizeof(struct crypto_lskcipher *);
+
+ return crypto_alg_extsize(alg);
+}
+
static void crypto_skcipher_free_instance(struct crypto_instance *inst)
{
struct skcipher_instance *skcipher =
@@ -770,7 +801,7 @@ static int __maybe_unused crypto_skcipher_report_stat(
}
static const struct crypto_type crypto_skcipher_type = {
- .extsize = crypto_alg_extsize,
+ .extsize = crypto_skcipher_extsize,
.init_tfm = crypto_skcipher_init_tfm,
.free = crypto_skcipher_free_instance,
#ifdef CONFIG_PROC_FS
@@ -783,7 +814,7 @@ static const struct crypto_type crypto_skcipher_type = {
.report_stat = crypto_skcipher_report_stat,
#endif
.maskclear = ~CRYPTO_ALG_TYPE_MASK,
- .maskset = CRYPTO_ALG_TYPE_MASK,
+ .maskset = CRYPTO_ALG_TYPE_SKCIPHER_MASK,
.type = CRYPTO_ALG_TYPE_SKCIPHER,
.tfmsize = offsetof(struct crypto_skcipher, base),
};
@@ -834,23 +865,18 @@ int crypto_has_skcipher(const char *alg_name, u32 type, u32 mask)
}
EXPORT_SYMBOL_GPL(crypto_has_skcipher);
-static int skcipher_prepare_alg(struct skcipher_alg *alg)
+int skcipher_prepare_alg_common(struct skcipher_alg_common *alg)
{
- struct crypto_istat_cipher *istat = skcipher_get_stat(alg);
+ struct crypto_istat_cipher *istat = skcipher_get_stat_common(alg);
struct crypto_alg *base = &alg->base;
- if (alg->ivsize > PAGE_SIZE / 8 || alg->chunksize > PAGE_SIZE / 8 ||
- alg->walksize > PAGE_SIZE / 8)
+ if (alg->ivsize > PAGE_SIZE / 8 || alg->chunksize > PAGE_SIZE / 8)
return -EINVAL;
if (!alg->chunksize)
alg->chunksize = base->cra_blocksize;
- if (!alg->walksize)
- alg->walksize = alg->chunksize;
- base->cra_type = &crypto_skcipher_type;
base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
- base->cra_flags |= CRYPTO_ALG_TYPE_SKCIPHER;
if (IS_ENABLED(CONFIG_CRYPTO_STATS))
memset(istat, 0, sizeof(*istat));
@@ -858,6 +884,27 @@ static int skcipher_prepare_alg(struct skcipher_alg *alg)
return 0;
}
+static int skcipher_prepare_alg(struct skcipher_alg *alg)
+{
+ struct crypto_alg *base = &alg->base;
+ int err;
+
+ err = skcipher_prepare_alg_common(&alg->co);
+ if (err)
+ return err;
+
+ if (alg->walksize > PAGE_SIZE / 8)
+ return -EINVAL;
+
+ if (!alg->walksize)
+ alg->walksize = alg->chunksize;
+
+ base->cra_type = &crypto_skcipher_type;
+ base->cra_flags |= CRYPTO_ALG_TYPE_SKCIPHER;
+
+ return 0;
+}
+
int crypto_register_skcipher(struct skcipher_alg *alg)
{
struct crypto_alg *base = &alg->base;
diff --git a/crypto/skcipher.h b/crypto/skcipher.h
new file mode 100644
index 000000000000..16c9484360da
--- /dev/null
+++ b/crypto/skcipher.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+#ifndef _LOCAL_CRYPTO_SKCIPHER_H
+#define _LOCAL_CRYPTO_SKCIPHER_H
+
+#include <crypto/internal/skcipher.h>
+#include "internal.h"
+
+static inline struct crypto_istat_cipher *skcipher_get_stat_common(
+ struct skcipher_alg_common *alg)
+{
+#ifdef CONFIG_CRYPTO_STATS
+ return &alg->stat;
+#else
+ return NULL;
+#endif
+}
+
+int crypto_lskcipher_encrypt_sg(struct skcipher_request *req);
+int crypto_lskcipher_decrypt_sg(struct skcipher_request *req);
+int crypto_init_lskcipher_ops_sg(struct crypto_tfm *tfm);
+int skcipher_prepare_alg_common(struct skcipher_alg_common *alg);
+
+#endif /* _LOCAL_CRYPTO_SKCIPHER_H */
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 216878c8bc3d..15c7a3011269 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -408,17 +408,15 @@ static const struct testvec_config default_hash_testvec_configs[] = {
.finalization_type = FINALIZATION_TYPE_FINAL,
.key_offset = 1,
}, {
- .name = "digest buffer aligned only to alignmask",
+ .name = "digest misaligned buffer",
.src_divs = {
{
.proportion_of_total = 10000,
.offset = 1,
- .offset_relative_to_alignmask = true,
},
},
.finalization_type = FINALIZATION_TYPE_DIGEST,
.key_offset = 1,
- .key_offset_relative_to_alignmask = true,
}, {
.name = "init+update+update+final two even splits",
.src_divs = {
@@ -1275,7 +1273,6 @@ static int test_shash_vec_cfg(const struct hash_testvec *vec,
u8 *hashstate)
{
struct crypto_shash *tfm = desc->tfm;
- const unsigned int alignmask = crypto_shash_alignmask(tfm);
const unsigned int digestsize = crypto_shash_digestsize(tfm);
const unsigned int statesize = crypto_shash_statesize(tfm);
const char *driver = crypto_shash_driver_name(tfm);
@@ -1287,7 +1284,7 @@ static int test_shash_vec_cfg(const struct hash_testvec *vec,
/* Set the key, if specified */
if (vec->ksize) {
err = do_setkey(crypto_shash_setkey, tfm, vec->key, vec->ksize,
- cfg, alignmask);
+ cfg, 0);
if (err) {
if (err == vec->setkey_error)
return 0;
@@ -1304,7 +1301,7 @@ static int test_shash_vec_cfg(const struct hash_testvec *vec,
}
/* Build the scatterlist for the source data */
- err = build_hash_sglist(tsgl, vec, cfg, alignmask, divs);
+ err = build_hash_sglist(tsgl, vec, cfg, 0, divs);
if (err) {
pr_err("alg: shash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n",
driver, vec_name, cfg->name);
@@ -1459,7 +1456,6 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec,
u8 *hashstate)
{
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- const unsigned int alignmask = crypto_ahash_alignmask(tfm);
const unsigned int digestsize = crypto_ahash_digestsize(tfm);
const unsigned int statesize = crypto_ahash_statesize(tfm);
const char *driver = crypto_ahash_driver_name(tfm);
@@ -1475,7 +1471,7 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec,
/* Set the key, if specified */
if (vec->ksize) {
err = do_setkey(crypto_ahash_setkey, tfm, vec->key, vec->ksize,
- cfg, alignmask);
+ cfg, 0);
if (err) {
if (err == vec->setkey_error)
return 0;
@@ -1492,7 +1488,7 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec,
}
/* Build the scatterlist for the source data */
- err = build_hash_sglist(tsgl, vec, cfg, alignmask, divs);
+ err = build_hash_sglist(tsgl, vec, cfg, 0, divs);
if (err) {
pr_err("alg: ahash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n",
driver, vec_name, cfg->name);
@@ -4963,7 +4959,7 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}, {
.alg = "ecb(arc4)",
- .generic_driver = "ecb(arc4)-generic",
+ .generic_driver = "arc4-generic",
.test = alg_test_skcipher,
.suite = {
.cipher = __VECS(arc4_tv_template)
@@ -5461,6 +5457,18 @@ static const struct alg_test_desc alg_test_descs[] = {
.akcipher = __VECS(pkcs1pad_rsa_tv_template)
}
}, {
+ .alg = "pkcs1pad(rsa,sha3-256)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "pkcs1pad(rsa,sha3-384)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "pkcs1pad(rsa,sha3-512)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
.alg = "pkcs1pad(rsa,sha384)",
.test = alg_test_null,
.fips_allowed = 1,
@@ -5773,16 +5781,6 @@ static const struct alg_test_desc alg_test_descs[] = {
.hash = __VECS(xxhash64_tv_template)
}
}, {
- .alg = "zlib-deflate",
- .test = alg_test_comp,
- .fips_allowed = 1,
- .suite = {
- .comp = {
- .comp = __VECS(zlib_deflate_comp_tv_template),
- .decomp = __VECS(zlib_deflate_decomp_tv_template)
- }
- }
- }, {
.alg = "zstd",
.test = alg_test_comp,
.fips_allowed = 1,
@@ -5945,6 +5943,25 @@ test_done:
return rc;
notest:
+ if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_LSKCIPHER) {
+ char nalg[CRYPTO_MAX_ALG_NAME];
+
+ if (snprintf(nalg, sizeof(nalg), "ecb(%s)", alg) >=
+ sizeof(nalg))
+ goto notest2;
+
+ i = alg_find_test(nalg);
+ if (i < 0)
+ goto notest2;
+
+ if (fips_enabled && !alg_test_descs[i].fips_allowed)
+ goto non_fips_alg;
+
+ rc = alg_test_skcipher(alg_test_descs + i, driver, type, mask);
+ goto test_done;
+ }
+
+notest2:
printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver);
if (type & CRYPTO_ALG_FIPS_INTERNAL)
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 5ca7a412508f..d7e98397549b 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -653,30 +653,6 @@ static const struct akcipher_testvec rsa_tv_template[] = {
static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
{
.key =
- "\x04\xf7\x46\xf8\x2f\x15\xf6\x22\x8e\xd7\x57\x4f\xcc\xe7\xbb\xc1"
- "\xd4\x09\x73\xcf\xea\xd0\x15\x07\x3d\xa5\x8a\x8a\x95\x43\xe4\x68"
- "\xea\xc6\x25\xc1\xc1\x01\x25\x4c\x7e\xc3\x3c\xa6\x04\x0a\xe7\x08"
- "\x98",
- .key_len = 49,
- .params =
- "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
- "\xce\x3d\x03\x01\x01",
- .param_len = 21,
- .m =
- "\xcd\xb9\xd2\x1c\xb7\x6f\xcd\x44\xb3\xfd\x63\xea\xa3\x66\x7f\xae"
- "\x63\x85\xe7\x82",
- .m_size = 20,
- .algo = OID_id_ecdsa_with_sha1,
- .c =
- "\x30\x35\x02\x19\x00\xba\xe5\x93\x83\x6e\xb6\x3b\x63\xa0\x27\x91"
- "\xc6\xf6\x7f\xc3\x09\xad\x59\xad\x88\x27\xd6\x92\x6b\x02\x18\x10"
- "\x68\x01\x9d\xba\xce\x83\x08\xef\x95\x52\x7b\xa0\x0f\xe4\x18\x86"
- "\x80\x6f\xa5\x79\x77\xda\xd0",
- .c_size = 55,
- .public_key_vec = true,
- .siggen_sigver_test = true,
- }, {
- .key =
"\x04\xb6\x4b\xb1\xd1\xac\xba\x24\x8f\x65\xb2\x60\x00\x90\xbf\xbd"
"\x78\x05\x73\xe9\x79\x1d\x6f\x7c\x0b\xd2\xc3\x93\xa7\x28\xe1\x75"
"\xf7\xd5\x95\x1d\x28\x10\xc0\x75\x50\x5c\x1a\x4f\x3f\x8f\xa5\xee"
@@ -780,32 +756,6 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
{
.key =
- "\x04\xb9\x7b\xbb\xd7\x17\x64\xd2\x7e\xfc\x81\x5d\x87\x06\x83\x41"
- "\x22\xd6\x9a\xaa\x87\x17\xec\x4f\x63\x55\x2f\x94\xba\xdd\x83\xe9"
- "\x34\x4b\xf3\xe9\x91\x13\x50\xb6\xcb\xca\x62\x08\xe7\x3b\x09\xdc"
- "\xc3\x63\x4b\x2d\xb9\x73\x53\xe4\x45\xe6\x7c\xad\xe7\x6b\xb0\xe8"
- "\xaf",
- .key_len = 65,
- .params =
- "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
- "\xce\x3d\x03\x01\x07",
- .param_len = 21,
- .m =
- "\xc2\x2b\x5f\x91\x78\x34\x26\x09\x42\x8d\x6f\x51\xb2\xc5\xaf\x4c"
- "\x0b\xde\x6a\x42",
- .m_size = 20,
- .algo = OID_id_ecdsa_with_sha1,
- .c =
- "\x30\x46\x02\x21\x00\xf9\x25\xce\x9f\x3a\xa6\x35\x81\xcf\xd4\xe7"
- "\xb7\xf0\x82\x56\x41\xf7\xd4\xad\x8d\x94\x5a\x69\x89\xee\xca\x6a"
- "\x52\x0e\x48\x4d\xcc\x02\x21\x00\xd7\xe4\xef\x52\x66\xd3\x5b\x9d"
- "\x8a\xfa\x54\x93\x29\xa7\x70\x86\xf1\x03\x03\xf3\x3b\xe2\x73\xf7"
- "\xfb\x9d\x8b\xde\xd4\x8d\x6f\xad",
- .c_size = 72,
- .public_key_vec = true,
- .siggen_sigver_test = true,
- }, {
- .key =
"\x04\x8b\x6d\xc0\x33\x8e\x2d\x8b\x67\xf5\xeb\xc4\x7f\xa0\xf5\xd9"
"\x7b\x03\xa5\x78\x9a\xb5\xea\x14\xe4\x23\xd0\xaf\xd7\x0e\x2e\xa0"
"\xc9\x8b\xdb\x95\xf8\xb3\xaf\xac\x00\x2c\x2c\x1f\x7a\xfd\x95\x88"
@@ -916,36 +866,6 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
{
- .key = /* secp384r1(sha1) */
- "\x04\x89\x25\xf3\x97\x88\xcb\xb0\x78\xc5\x72\x9a\x14\x6e\x7a\xb1"
- "\x5a\xa5\x24\xf1\x95\x06\x9e\x28\xfb\xc4\xb9\xbe\x5a\x0d\xd9\x9f"
- "\xf3\xd1\x4d\x2d\x07\x99\xbd\xda\xa7\x66\xec\xbb\xea\xba\x79\x42"
- "\xc9\x34\x89\x6a\xe7\x0b\xc3\xf2\xfe\x32\x30\xbe\xba\xf9\xdf\x7e"
- "\x4b\x6a\x07\x8e\x26\x66\x3f\x1d\xec\xa2\x57\x91\x51\xdd\x17\x0e"
- "\x0b\x25\xd6\x80\x5c\x3b\xe6\x1a\x98\x48\x91\x45\x7a\x73\xb0\xc3"
- "\xf1",
- .key_len = 97,
- .params =
- "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
- "\x00\x22",
- .param_len = 18,
- .m =
- "\x12\x55\x28\xf0\x77\xd5\xb6\x21\x71\x32\x48\xcd\x28\xa8\x25\x22"
- "\x3a\x69\xc1\x93",
- .m_size = 20,
- .algo = OID_id_ecdsa_with_sha1,
- .c =
- "\x30\x66\x02\x31\x00\xf5\x0f\x24\x4c\x07\x93\x6f\x21\x57\x55\x07"
- "\x20\x43\x30\xde\xa0\x8d\x26\x8e\xae\x63\x3f\xbc\x20\x3a\xc6\xf1"
- "\x32\x3c\xce\x70\x2b\x78\xf1\x4c\x26\xe6\x5b\x86\xcf\xec\x7c\x7e"
- "\xd0\x87\xd7\xd7\x6e\x02\x31\x00\xcd\xbb\x7e\x81\x5d\x8f\x63\xc0"
- "\x5f\x63\xb1\xbe\x5e\x4c\x0e\xa1\xdf\x28\x8c\x1b\xfa\xf9\x95\x88"
- "\x74\xa0\x0f\xbf\xaf\xc3\x36\x76\x4a\xa1\x59\xf1\x1c\xa4\x58\x26"
- "\x79\x12\x2a\xb7\xc5\x15\x92\xc5",
- .c_size = 104,
- .public_key_vec = true,
- .siggen_sigver_test = true,
- }, {
.key = /* secp384r1(sha224) */
"\x04\x69\x6c\xcf\x62\xee\xd0\x0d\xe5\xb5\x2f\x70\x54\xcf\x26\xa0"
"\xd9\x98\x8d\x92\x2a\xab\x9b\x11\xcb\x48\x18\xa1\xa9\x0d\xd5\x18"
@@ -35754,81 +35674,6 @@ static const struct comp_testvec deflate_decomp_tv_template[] = {
},
};
-static const struct comp_testvec zlib_deflate_comp_tv_template[] = {
- {
- .inlen = 70,
- .outlen = 44,
- .input = "Join us now and share the software "
- "Join us now and share the software ",
- .output = "\x78\x5e\xf3\xca\xcf\xcc\x53\x28"
- "\x2d\x56\xc8\xcb\x2f\x57\x48\xcc"
- "\x4b\x51\x28\xce\x48\x2c\x4a\x55"
- "\x28\xc9\x48\x55\x28\xce\x4f\x2b"
- "\x29\x07\x71\xbc\x08\x2b\x01\x00"
- "\x7c\x65\x19\x3d",
- }, {
- .inlen = 191,
- .outlen = 129,
- .input = "This document describes a compression method based on the DEFLATE"
- "compression algorithm. This document defines the application of "
- "the DEFLATE algorithm to the IP Payload Compression Protocol.",
- .output = "\x78\x5e\x5d\xce\x41\x0a\xc3\x30"
- "\x0c\x04\xc0\xaf\xec\x0b\xf2\x87"
- "\xd2\xa6\x50\xe8\xc1\x07\x7f\x40"
- "\xb1\x95\x5a\x60\x5b\xc6\x56\x0f"
- "\xfd\x7d\x93\x1e\x42\xe8\x51\xec"
- "\xee\x20\x9f\x64\x20\x6a\x78\x17"
- "\xae\x86\xc8\x23\x74\x59\x78\x80"
- "\x10\xb4\xb4\xce\x63\x88\x56\x14"
- "\xb6\xa4\x11\x0b\x0d\x8e\xd8\x6e"
- "\x4b\x8c\xdb\x7c\x7f\x5e\xfc\x7c"
- "\xae\x51\x7e\x69\x17\x4b\x65\x02"
- "\xfc\x1f\xbc\x4a\xdd\xd8\x7d\x48"
- "\xad\x65\x09\x64\x3b\xac\xeb\xd9"
- "\xc2\x01\xc0\xf4\x17\x3c\x1c\x1c"
- "\x7d\xb2\x52\xc4\xf5\xf4\x8f\xeb"
- "\x6a\x1a\x34\x4f\x5f\x2e\x32\x45"
- "\x4e",
- },
-};
-
-static const struct comp_testvec zlib_deflate_decomp_tv_template[] = {
- {
- .inlen = 128,
- .outlen = 191,
- .input = "\x78\x9c\x5d\x8d\x31\x0e\xc2\x30"
- "\x10\x04\xbf\xb2\x2f\xc8\x1f\x10"
- "\x04\x09\x89\xc2\x85\x3f\x70\xb1"
- "\x2f\xf8\x24\xdb\x67\xd9\x47\xc1"
- "\xef\x49\x68\x12\x51\xae\x76\x67"
- "\xd6\x27\x19\x88\x1a\xde\x85\xab"
- "\x21\xf2\x08\x5d\x16\x1e\x20\x04"
- "\x2d\xad\xf3\x18\xa2\x15\x85\x2d"
- "\x69\xc4\x42\x83\x23\xb6\x6c\x89"
- "\x71\x9b\xef\xcf\x8b\x9f\xcf\x33"
- "\xca\x2f\xed\x62\xa9\x4c\x80\xff"
- "\x13\xaf\x52\x37\xed\x0e\x52\x6b"
- "\x59\x02\xd9\x4e\xe8\x7a\x76\x1d"
- "\x02\x98\xfe\x8a\x87\x83\xa3\x4f"
- "\x56\x8a\xb8\x9e\x8e\x5c\x57\xd3"
- "\xa0\x79\xfa\x02\x2e\x32\x45\x4e",
- .output = "This document describes a compression method based on the DEFLATE"
- "compression algorithm. This document defines the application of "
- "the DEFLATE algorithm to the IP Payload Compression Protocol.",
- }, {
- .inlen = 44,
- .outlen = 70,
- .input = "\x78\x9c\xf3\xca\xcf\xcc\x53\x28"
- "\x2d\x56\xc8\xcb\x2f\x57\x48\xcc"
- "\x4b\x51\x28\xce\x48\x2c\x4a\x55"
- "\x28\xc9\x48\x55\x28\xce\x4f\x2b"
- "\x29\x07\x71\xbc\x08\x2b\x01\x00"
- "\x7c\x65\x19\x3d",
- .output = "Join us now and share the software "
- "Join us now and share the software ",
- },
-};
-
/*
* LZO test vectors (null-terminated strings).
*/
diff --git a/crypto/vmac.c b/crypto/vmac.c
index 4633b2dda1e0..0a1d8efa6c1a 100644
--- a/crypto/vmac.c
+++ b/crypto/vmac.c
@@ -649,7 +649,6 @@ static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb)
inst->alg.base.cra_priority = alg->cra_priority;
inst->alg.base.cra_blocksize = alg->cra_blocksize;
- inst->alg.base.cra_alignmask = alg->cra_alignmask;
inst->alg.base.cra_ctxsize = sizeof(struct vmac_tfm_ctx);
inst->alg.base.cra_init = vmac_init_tfm;
diff --git a/crypto/xcbc.c b/crypto/xcbc.c
index 6074c5c1da49..a9e8ee9c1949 100644
--- a/crypto/xcbc.c
+++ b/crypto/xcbc.c
@@ -27,7 +27,7 @@ static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
*/
struct xcbc_tfm_ctx {
struct crypto_cipher *child;
- u8 ctx[];
+ u8 consts[];
};
/*
@@ -43,7 +43,7 @@ struct xcbc_tfm_ctx {
*/
struct xcbc_desc_ctx {
unsigned int len;
- u8 ctx[];
+ u8 odds[];
};
#define XCBC_BLOCKSIZE 16
@@ -51,9 +51,8 @@ struct xcbc_desc_ctx {
static int crypto_xcbc_digest_setkey(struct crypto_shash *parent,
const u8 *inkey, unsigned int keylen)
{
- unsigned long alignmask = crypto_shash_alignmask(parent);
struct xcbc_tfm_ctx *ctx = crypto_shash_ctx(parent);
- u8 *consts = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
+ u8 *consts = ctx->consts;
int err = 0;
u8 key1[XCBC_BLOCKSIZE];
int bs = sizeof(key1);
@@ -71,10 +70,9 @@ static int crypto_xcbc_digest_setkey(struct crypto_shash *parent,
static int crypto_xcbc_digest_init(struct shash_desc *pdesc)
{
- unsigned long alignmask = crypto_shash_alignmask(pdesc->tfm);
struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
int bs = crypto_shash_blocksize(pdesc->tfm);
- u8 *prev = PTR_ALIGN(&ctx->ctx[0], alignmask + 1) + bs;
+ u8 *prev = &ctx->odds[bs];
ctx->len = 0;
memset(prev, 0, bs);
@@ -86,12 +84,11 @@ static int crypto_xcbc_digest_update(struct shash_desc *pdesc, const u8 *p,
unsigned int len)
{
struct crypto_shash *parent = pdesc->tfm;
- unsigned long alignmask = crypto_shash_alignmask(parent);
struct xcbc_tfm_ctx *tctx = crypto_shash_ctx(parent);
struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
struct crypto_cipher *tfm = tctx->child;
int bs = crypto_shash_blocksize(parent);
- u8 *odds = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
+ u8 *odds = ctx->odds;
u8 *prev = odds + bs;
/* checking the data can fill the block */
@@ -132,13 +129,11 @@ static int crypto_xcbc_digest_update(struct shash_desc *pdesc, const u8 *p,
static int crypto_xcbc_digest_final(struct shash_desc *pdesc, u8 *out)
{
struct crypto_shash *parent = pdesc->tfm;
- unsigned long alignmask = crypto_shash_alignmask(parent);
struct xcbc_tfm_ctx *tctx = crypto_shash_ctx(parent);
struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
struct crypto_cipher *tfm = tctx->child;
int bs = crypto_shash_blocksize(parent);
- u8 *consts = PTR_ALIGN(&tctx->ctx[0], alignmask + 1);
- u8 *odds = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
+ u8 *odds = ctx->odds;
u8 *prev = odds + bs;
unsigned int offset = 0;
@@ -157,7 +152,7 @@ static int crypto_xcbc_digest_final(struct shash_desc *pdesc, u8 *out)
}
crypto_xor(prev, odds, bs);
- crypto_xor(prev, consts + offset, bs);
+ crypto_xor(prev, &tctx->consts[offset], bs);
crypto_cipher_encrypt_one(tfm, out, prev);
@@ -191,7 +186,6 @@ static int xcbc_create(struct crypto_template *tmpl, struct rtattr **tb)
struct shash_instance *inst;
struct crypto_cipher_spawn *spawn;
struct crypto_alg *alg;
- unsigned long alignmask;
u32 mask;
int err;
@@ -218,21 +212,15 @@ static int xcbc_create(struct crypto_template *tmpl, struct rtattr **tb)
if (err)
goto err_free_inst;
- alignmask = alg->cra_alignmask | 3;
- inst->alg.base.cra_alignmask = alignmask;
inst->alg.base.cra_priority = alg->cra_priority;
inst->alg.base.cra_blocksize = alg->cra_blocksize;
+ inst->alg.base.cra_ctxsize = sizeof(struct xcbc_tfm_ctx) +
+ alg->cra_blocksize * 2;
inst->alg.digestsize = alg->cra_blocksize;
- inst->alg.descsize = ALIGN(sizeof(struct xcbc_desc_ctx),
- crypto_tfm_ctx_alignment()) +
- (alignmask &
- ~(crypto_tfm_ctx_alignment() - 1)) +
+ inst->alg.descsize = sizeof(struct xcbc_desc_ctx) +
alg->cra_blocksize * 2;
- inst->alg.base.cra_ctxsize = ALIGN(sizeof(struct xcbc_tfm_ctx),
- alignmask + 1) +
- alg->cra_blocksize * 2;
inst->alg.base.cra_init = xcbc_init_tfm;
inst->alg.base.cra_exit = xcbc_exit_tfm;
diff --git a/crypto/xts.c b/crypto/xts.c
index 548b302c6c6a..672e1a3f0b0c 100644
--- a/crypto/xts.c
+++ b/crypto/xts.c
@@ -28,7 +28,7 @@ struct xts_tfm_ctx {
struct xts_instance_ctx {
struct crypto_skcipher_spawn spawn;
- char name[CRYPTO_MAX_ALG_NAME];
+ struct crypto_cipher_spawn tweak_spawn;
};
struct xts_request_ctx {
@@ -306,7 +306,7 @@ static int xts_init_tfm(struct crypto_skcipher *tfm)
ctx->child = child;
- tweak = crypto_alloc_cipher(ictx->name, 0, 0);
+ tweak = crypto_spawn_cipher(&ictx->tweak_spawn);
if (IS_ERR(tweak)) {
crypto_free_skcipher(ctx->child);
return PTR_ERR(tweak);
@@ -333,14 +333,16 @@ static void xts_free_instance(struct skcipher_instance *inst)
struct xts_instance_ctx *ictx = skcipher_instance_ctx(inst);
crypto_drop_skcipher(&ictx->spawn);
+ crypto_drop_cipher(&ictx->tweak_spawn);
kfree(inst);
}
static int xts_create(struct crypto_template *tmpl, struct rtattr **tb)
{
+ struct skcipher_alg_common *alg;
+ char name[CRYPTO_MAX_ALG_NAME];
struct skcipher_instance *inst;
struct xts_instance_ctx *ctx;
- struct skcipher_alg *alg;
const char *cipher_name;
u32 mask;
int err;
@@ -363,25 +365,25 @@ static int xts_create(struct crypto_template *tmpl, struct rtattr **tb)
cipher_name, 0, mask);
if (err == -ENOENT) {
err = -ENAMETOOLONG;
- if (snprintf(ctx->name, CRYPTO_MAX_ALG_NAME, "ecb(%s)",
+ if (snprintf(name, CRYPTO_MAX_ALG_NAME, "ecb(%s)",
cipher_name) >= CRYPTO_MAX_ALG_NAME)
goto err_free_inst;
err = crypto_grab_skcipher(&ctx->spawn,
skcipher_crypto_instance(inst),
- ctx->name, 0, mask);
+ name, 0, mask);
}
if (err)
goto err_free_inst;
- alg = crypto_skcipher_spawn_alg(&ctx->spawn);
+ alg = crypto_spawn_skcipher_alg_common(&ctx->spawn);
err = -EINVAL;
if (alg->base.cra_blocksize != XTS_BLOCK_SIZE)
goto err_free_inst;
- if (crypto_skcipher_alg_ivsize(alg))
+ if (alg->ivsize)
goto err_free_inst;
err = crypto_inst_setname(skcipher_crypto_instance(inst), "xts",
@@ -398,31 +400,36 @@ static int xts_create(struct crypto_template *tmpl, struct rtattr **tb)
if (!strncmp(cipher_name, "ecb(", 4)) {
int len;
- len = strscpy(ctx->name, cipher_name + 4, sizeof(ctx->name));
+ len = strscpy(name, cipher_name + 4, sizeof(name));
if (len < 2)
goto err_free_inst;
- if (ctx->name[len - 1] != ')')
+ if (name[len - 1] != ')')
goto err_free_inst;
- ctx->name[len - 1] = 0;
+ name[len - 1] = 0;
if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
- "xts(%s)", ctx->name) >= CRYPTO_MAX_ALG_NAME) {
+ "xts(%s)", name) >= CRYPTO_MAX_ALG_NAME) {
err = -ENAMETOOLONG;
goto err_free_inst;
}
} else
goto err_free_inst;
+ err = crypto_grab_cipher(&ctx->tweak_spawn,
+ skcipher_crypto_instance(inst), name, 0, mask);
+ if (err)
+ goto err_free_inst;
+
inst->alg.base.cra_priority = alg->base.cra_priority;
inst->alg.base.cra_blocksize = XTS_BLOCK_SIZE;
inst->alg.base.cra_alignmask = alg->base.cra_alignmask |
(__alignof__(u64) - 1);
inst->alg.ivsize = XTS_BLOCK_SIZE;
- inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg) * 2;
- inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg) * 2;
+ inst->alg.min_keysize = alg->min_keysize * 2;
+ inst->alg.max_keysize = alg->max_keysize * 2;
inst->alg.base.cra_ctxsize = sizeof(struct xts_tfm_ctx);
diff --git a/drivers/Kconfig b/drivers/Kconfig
index efb66e25fa2d..7bdad836fc62 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -135,8 +135,6 @@ source "drivers/uio/Kconfig"
source "drivers/vfio/Kconfig"
-source "drivers/vlynq/Kconfig"
-
source "drivers/virt/Kconfig"
source "drivers/virtio/Kconfig"
@@ -175,6 +173,8 @@ source "drivers/soundwire/Kconfig"
source "drivers/soc/Kconfig"
+source "drivers/pmdomain/Kconfig"
+
source "drivers/devfreq/Kconfig"
source "drivers/extcon/Kconfig"
@@ -243,4 +243,6 @@ source "drivers/hte/Kconfig"
source "drivers/cdx/Kconfig"
+source "drivers/dpll/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 1bec7819a837..d828329c268d 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -151,7 +151,6 @@ obj-$(CONFIG_BCMA) += bcma/
obj-$(CONFIG_VHOST_RING) += vhost/
obj-$(CONFIG_VHOST_IOTLB) += vhost/
obj-$(CONFIG_VHOST) += vhost/
-obj-$(CONFIG_VLYNQ) += vlynq/
obj-$(CONFIG_GREYBUS) += greybus/
obj-$(CONFIG_COMEDI) += comedi/
obj-$(CONFIG_STAGING) += staging/
@@ -197,5 +196,6 @@ obj-$(CONFIG_PECI) += peci/
obj-$(CONFIG_HTE) += hte/
obj-$(CONFIG_DRM_ACCEL) += accel/
obj-$(CONFIG_CDX_BUS) += cdx/
+obj-$(CONFIG_DPLL) += dpll/
obj-$(CONFIG_S390) += s390/
diff --git a/drivers/accel/drm_accel.c b/drivers/accel/drm_accel.c
index 4a9baf02439e..294b572a9c33 100644
--- a/drivers/accel/drm_accel.c
+++ b/drivers/accel/drm_accel.c
@@ -21,7 +21,6 @@ static DEFINE_SPINLOCK(accel_minor_lock);
static struct idr accel_minors_idr;
static struct dentry *accel_debugfs_root;
-static struct class *accel_class;
static struct device_type accel_sysfs_device_minor = {
.name = "accel_minor"
@@ -32,23 +31,19 @@ static char *accel_devnode(const struct device *dev, umode_t *mode)
return kasprintf(GFP_KERNEL, "accel/%s", dev_name(dev));
}
+static const struct class accel_class = {
+ .name = "accel",
+ .devnode = accel_devnode,
+};
+
static int accel_sysfs_init(void)
{
- accel_class = class_create("accel");
- if (IS_ERR(accel_class))
- return PTR_ERR(accel_class);
-
- accel_class->devnode = accel_devnode;
-
- return 0;
+ return class_register(&accel_class);
}
static void accel_sysfs_destroy(void)
{
- if (IS_ERR_OR_NULL(accel_class))
- return;
- class_destroy(accel_class);
- accel_class = NULL;
+ class_unregister(&accel_class);
}
static int accel_name_info(struct seq_file *m, void *data)
@@ -79,29 +74,30 @@ static const struct drm_info_list accel_debugfs_list[] = {
#define ACCEL_DEBUGFS_ENTRIES ARRAY_SIZE(accel_debugfs_list)
/**
- * accel_debugfs_init() - Initialize debugfs for accel minor
- * @minor: Pointer to the drm_minor instance.
- * @minor_id: The minor's id
+ * accel_debugfs_init() - Initialize debugfs for device
+ * @dev: Pointer to the device instance.
*
- * This function initializes the drm minor's debugfs members and creates
- * a root directory for the minor in debugfs. It also creates common files
- * for accelerators and calls the driver's debugfs init callback.
+ * This function creates a root directory for the device in debugfs.
*/
-void accel_debugfs_init(struct drm_minor *minor, int minor_id)
+void accel_debugfs_init(struct drm_device *dev)
{
- struct drm_device *dev = minor->dev;
- char name[64];
+ drm_debugfs_dev_init(dev, accel_debugfs_root);
+}
- INIT_LIST_HEAD(&minor->debugfs_list);
- mutex_init(&minor->debugfs_lock);
- sprintf(name, "%d", minor_id);
- minor->debugfs_root = debugfs_create_dir(name, accel_debugfs_root);
+/**
+ * accel_debugfs_register() - Register debugfs for device
+ * @dev: Pointer to the device instance.
+ *
+ * Creates common files for accelerators.
+ */
+void accel_debugfs_register(struct drm_device *dev)
+{
+ struct drm_minor *minor = dev->accel;
- drm_debugfs_create_files(accel_debugfs_list, ACCEL_DEBUGFS_ENTRIES,
- minor->debugfs_root, minor);
+ minor->debugfs_root = dev->debugfs_root;
- if (dev->driver->debugfs_init)
- dev->driver->debugfs_init(minor);
+ drm_debugfs_create_files(accel_debugfs_list, ACCEL_DEBUGFS_ENTRIES,
+ dev->debugfs_root, minor);
}
/**
@@ -116,7 +112,7 @@ void accel_debugfs_init(struct drm_minor *minor, int minor_id)
void accel_set_device_instance_params(struct device *kdev, int index)
{
kdev->devt = MKDEV(ACCEL_MAJOR, index);
- kdev->class = accel_class;
+ kdev->class = &accel_class;
kdev->type = &accel_sysfs_device_minor;
}
diff --git a/drivers/accel/habanalabs/common/command_buffer.c b/drivers/accel/habanalabs/common/command_buffer.c
index 08f7aee42624..0f0d295116e7 100644
--- a/drivers/accel/habanalabs/common/command_buffer.c
+++ b/drivers/accel/habanalabs/common/command_buffer.c
@@ -361,10 +361,11 @@ out:
return rc;
}
-int hl_cb_ioctl(struct hl_fpriv *hpriv, void *data)
+int hl_cb_ioctl(struct drm_device *ddev, void *data, struct drm_file *file_priv)
{
- union hl_cb_args *args = data;
+ struct hl_fpriv *hpriv = file_priv->driver_priv;
struct hl_device *hdev = hpriv->hdev;
+ union hl_cb_args *args = data;
u64 handle = 0, device_va = 0;
enum hl_device_status status;
u32 usage_cnt = 0;
diff --git a/drivers/accel/habanalabs/common/command_submission.c b/drivers/accel/habanalabs/common/command_submission.c
index c23829dab97a..3aa6eeef443b 100644
--- a/drivers/accel/habanalabs/common/command_submission.c
+++ b/drivers/accel/habanalabs/common/command_submission.c
@@ -31,6 +31,24 @@ enum hl_cs_wait_status {
CS_WAIT_STATUS_GONE
};
+/*
+ * Data used while handling wait/timestamp nodes.
+ * The purpose of this struct is to store the needed data for both operations
+ * in one variable instead of passing large number of arguments to functions.
+ */
+struct wait_interrupt_data {
+ struct hl_user_interrupt *interrupt;
+ struct hl_mmap_mem_buf *buf;
+ struct hl_mem_mgr *mmg;
+ struct hl_cb *cq_cb;
+ u64 ts_handle;
+ u64 ts_offset;
+ u64 cq_handle;
+ u64 cq_offset;
+ u64 target_value;
+ u64 intr_timeout_us;
+};
+
static void job_wq_completion(struct work_struct *work);
static int _hl_cs_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, u64 timeout_us, u64 seq,
enum hl_cs_wait_status *status, s64 *timestamp);
@@ -1079,19 +1097,22 @@ static void
wake_pending_user_interrupt_threads(struct hl_user_interrupt *interrupt)
{
struct hl_user_pending_interrupt *pend, *temp;
+ unsigned long flags;
- spin_lock(&interrupt->wait_list_lock);
- list_for_each_entry_safe(pend, temp, &interrupt->wait_list_head, wait_list_node) {
- if (pend->ts_reg_info.buf) {
- list_del(&pend->wait_list_node);
- hl_mmap_mem_buf_put(pend->ts_reg_info.buf);
- hl_cb_put(pend->ts_reg_info.cq_cb);
- } else {
- pend->fence.error = -EIO;
- complete_all(&pend->fence.completion);
- }
+ spin_lock_irqsave(&interrupt->wait_list_lock, flags);
+ list_for_each_entry_safe(pend, temp, &interrupt->wait_list_head, list_node) {
+ pend->fence.error = -EIO;
+ complete_all(&pend->fence.completion);
}
- spin_unlock(&interrupt->wait_list_lock);
+ spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
+
+ spin_lock_irqsave(&interrupt->ts_list_lock, flags);
+ list_for_each_entry_safe(pend, temp, &interrupt->ts_list_head, list_node) {
+ list_del(&pend->list_node);
+ hl_mmap_mem_buf_put(pend->ts_reg_info.buf);
+ hl_cb_put(pend->ts_reg_info.cq_cb);
+ }
+ spin_unlock_irqrestore(&interrupt->ts_list_lock, flags);
}
void hl_release_pending_user_interrupts(struct hl_device *hdev)
@@ -1730,16 +1751,11 @@ static int hl_cs_ctx_switch(struct hl_fpriv *hpriv, union hl_cs_args *args,
/* Need to wait for restore completion before execution phase */
if (num_chunks) {
enum hl_cs_wait_status status;
-wait_again:
+
ret = _hl_cs_wait_ioctl(hdev, ctx,
jiffies_to_usecs(hdev->timeout_jiffies),
*cs_seq, &status, NULL);
if (ret) {
- if (ret == -ERESTARTSYS) {
- usleep_range(100, 200);
- goto wait_again;
- }
-
dev_err(hdev->dev,
"Restore CS for context %d failed to complete %d\n",
ctx->asid, ret);
@@ -2539,8 +2555,9 @@ static int cs_ioctl_flush_pci_hbw_writes(struct hl_fpriv *hpriv)
return 0;
}
-int hl_cs_ioctl(struct hl_fpriv *hpriv, void *data)
+int hl_cs_ioctl(struct drm_device *ddev, void *data, struct drm_file *file_priv)
{
+ struct hl_fpriv *hpriv = file_priv->driver_priv;
union hl_cs_args *args = data;
enum hl_cs_type cs_type = 0;
u64 cs_seq = ULONG_MAX;
@@ -3197,166 +3214,241 @@ static int hl_cs_wait_ioctl(struct hl_fpriv *hpriv, void *data)
return 0;
}
-static int ts_buff_get_kernel_ts_record(struct hl_mmap_mem_buf *buf,
- struct hl_cb *cq_cb,
- u64 ts_offset, u64 cq_offset, u64 target_value,
- spinlock_t *wait_list_lock,
- struct hl_user_pending_interrupt **pend)
+static inline void set_record_cq_info(struct hl_user_pending_interrupt *record,
+ struct hl_cb *cq_cb, u32 cq_offset, u32 target_value)
{
- struct hl_ts_buff *ts_buff = buf->private;
- struct hl_user_pending_interrupt *requested_offset_record =
- (struct hl_user_pending_interrupt *)ts_buff->kernel_buff_address +
- ts_offset;
- struct hl_user_pending_interrupt *cb_last =
- (struct hl_user_pending_interrupt *)ts_buff->kernel_buff_address +
+ record->ts_reg_info.cq_cb = cq_cb;
+ record->cq_kernel_addr = (u64 *) cq_cb->kernel_address + cq_offset;
+ record->cq_target_value = target_value;
+}
+
+static int validate_and_get_ts_record(struct device *dev,
+ struct hl_ts_buff *ts_buff, u64 ts_offset,
+ struct hl_user_pending_interrupt **req_event_record)
+{
+ struct hl_user_pending_interrupt *ts_cb_last;
+
+ *req_event_record = (struct hl_user_pending_interrupt *)ts_buff->kernel_buff_address +
+ ts_offset;
+ ts_cb_last = (struct hl_user_pending_interrupt *)ts_buff->kernel_buff_address +
(ts_buff->kernel_buff_size / sizeof(struct hl_user_pending_interrupt));
- unsigned long iter_counter = 0;
- u64 current_cq_counter;
- ktime_t timestamp;
/* Validate ts_offset not exceeding last max */
- if (requested_offset_record >= cb_last) {
- dev_err(buf->mmg->dev, "Ts offset exceeds max CB offset(0x%llx)\n",
- (u64)(uintptr_t)cb_last);
+ if (*req_event_record >= ts_cb_last) {
+ dev_err(dev, "Ts offset(%llu) exceeds max CB offset(0x%llx)\n",
+ ts_offset, (u64)(uintptr_t)ts_cb_last);
return -EINVAL;
}
- timestamp = ktime_get();
+ return 0;
+}
-start_over:
- spin_lock(wait_list_lock);
+static void unregister_timestamp_node(struct hl_device *hdev,
+ struct hl_user_pending_interrupt *record, bool need_lock)
+{
+ struct hl_user_interrupt *interrupt = record->ts_reg_info.interrupt;
+ bool ts_rec_found = false;
+ unsigned long flags;
- /* Unregister only if we didn't reach the target value
- * since in this case there will be no handling in irq context
- * and then it's safe to delete the node out of the interrupt list
- * then re-use it on other interrupt
- */
- if (requested_offset_record->ts_reg_info.in_use) {
- current_cq_counter = *requested_offset_record->cq_kernel_addr;
- if (current_cq_counter < requested_offset_record->cq_target_value) {
- list_del(&requested_offset_record->wait_list_node);
- spin_unlock(wait_list_lock);
+ if (need_lock)
+ spin_lock_irqsave(&interrupt->ts_list_lock, flags);
- hl_mmap_mem_buf_put(requested_offset_record->ts_reg_info.buf);
- hl_cb_put(requested_offset_record->ts_reg_info.cq_cb);
+ if (record->ts_reg_info.in_use) {
+ record->ts_reg_info.in_use = false;
+ list_del(&record->list_node);
+ ts_rec_found = true;
+ }
- dev_dbg(buf->mmg->dev,
- "ts node removed from interrupt list now can re-use\n");
- } else {
- dev_dbg(buf->mmg->dev,
- "ts node in middle of irq handling\n");
-
- /* irq thread handling in the middle give it time to finish */
- spin_unlock(wait_list_lock);
- usleep_range(100, 1000);
- if (++iter_counter == MAX_TS_ITER_NUM) {
- dev_err(buf->mmg->dev,
- "Timestamp offset processing reached timeout of %lld ms\n",
- ktime_ms_delta(ktime_get(), timestamp));
- return -EAGAIN;
- }
+ if (need_lock)
+ spin_unlock_irqrestore(&interrupt->ts_list_lock, flags);
- goto start_over;
+ /* Put refcounts that were taken when we registered the event */
+ if (ts_rec_found) {
+ hl_mmap_mem_buf_put(record->ts_reg_info.buf);
+ hl_cb_put(record->ts_reg_info.cq_cb);
+ }
+}
+
+static int ts_get_and_handle_kernel_record(struct hl_device *hdev, struct hl_ctx *ctx,
+ struct wait_interrupt_data *data, unsigned long *flags,
+ struct hl_user_pending_interrupt **pend)
+{
+ struct hl_user_pending_interrupt *req_offset_record;
+ struct hl_ts_buff *ts_buff = data->buf->private;
+ bool need_lock = false;
+ int rc;
+
+ rc = validate_and_get_ts_record(data->buf->mmg->dev, ts_buff, data->ts_offset,
+ &req_offset_record);
+ if (rc)
+ return rc;
+
+ /* In case the node already registered, need to unregister first then re-use */
+ if (req_offset_record->ts_reg_info.in_use) {
+ dev_dbg(data->buf->mmg->dev,
+ "Requested record %p is in use on irq: %u ts addr: %p, unregister first then put on irq: %u\n",
+ req_offset_record,
+ req_offset_record->ts_reg_info.interrupt->interrupt_id,
+ req_offset_record->ts_reg_info.timestamp_kernel_addr,
+ data->interrupt->interrupt_id);
+ /*
+ * Since interrupt here can be different than the one the node currently registered
+ * on, and we don't want to lock two lists while we're doing unregister, so
+ * unlock the new interrupt wait list here and acquire the lock again after you done
+ */
+ if (data->interrupt->interrupt_id !=
+ req_offset_record->ts_reg_info.interrupt->interrupt_id) {
+
+ need_lock = true;
+ spin_unlock_irqrestore(&data->interrupt->ts_list_lock, *flags);
}
- } else {
- /* Fill up the new registration node info */
- requested_offset_record->ts_reg_info.buf = buf;
- requested_offset_record->ts_reg_info.cq_cb = cq_cb;
- requested_offset_record->ts_reg_info.timestamp_kernel_addr =
- (u64 *) ts_buff->user_buff_address + ts_offset;
- requested_offset_record->cq_kernel_addr =
- (u64 *) cq_cb->kernel_address + cq_offset;
- requested_offset_record->cq_target_value = target_value;
- spin_unlock(wait_list_lock);
+ unregister_timestamp_node(hdev, req_offset_record, need_lock);
+
+ if (need_lock)
+ spin_lock_irqsave(&data->interrupt->ts_list_lock, *flags);
}
- *pend = requested_offset_record;
+ /* Fill up the new registration node info and add it to the list */
+ req_offset_record->ts_reg_info.in_use = true;
+ req_offset_record->ts_reg_info.buf = data->buf;
+ req_offset_record->ts_reg_info.timestamp_kernel_addr =
+ (u64 *) ts_buff->user_buff_address + data->ts_offset;
+ req_offset_record->ts_reg_info.interrupt = data->interrupt;
+ set_record_cq_info(req_offset_record, data->cq_cb, data->cq_offset,
+ data->target_value);
- dev_dbg(buf->mmg->dev, "Found available node in TS kernel CB %p\n",
- requested_offset_record);
- return 0;
+ *pend = req_offset_record;
+
+ return rc;
+}
+
+static int _hl_interrupt_ts_reg_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,
+ struct wait_interrupt_data *data,
+ u32 *status, u64 *timestamp)
+{
+ struct hl_user_pending_interrupt *pend;
+ unsigned long flags;
+ int rc = 0;
+
+ hl_ctx_get(ctx);
+
+ data->cq_cb = hl_cb_get(data->mmg, data->cq_handle);
+ if (!data->cq_cb) {
+ rc = -EINVAL;
+ goto put_ctx;
+ }
+
+ /* Validate the cq offset */
+ if (((u64 *) data->cq_cb->kernel_address + data->cq_offset) >=
+ ((u64 *) data->cq_cb->kernel_address + (data->cq_cb->size / sizeof(u64)))) {
+ rc = -EINVAL;
+ goto put_cq_cb;
+ }
+
+ dev_dbg(hdev->dev, "Timestamp registration: interrupt id: %u, handle: 0x%llx, ts offset: %llu, cq_offset: %llu\n",
+ data->interrupt->interrupt_id, data->ts_handle,
+ data->ts_offset, data->cq_offset);
+
+ data->buf = hl_mmap_mem_buf_get(data->mmg, data->ts_handle);
+ if (!data->buf) {
+ rc = -EINVAL;
+ goto put_cq_cb;
+ }
+
+ spin_lock_irqsave(&data->interrupt->ts_list_lock, flags);
+
+ /* get ts buffer record */
+ rc = ts_get_and_handle_kernel_record(hdev, ctx, data, &flags, &pend);
+ if (rc) {
+ spin_unlock_irqrestore(&data->interrupt->ts_list_lock, flags);
+ goto put_ts_buff;
+ }
+
+ /* We check for completion value as interrupt could have been received
+ * before we add the timestamp node to the ts list.
+ */
+ if (*pend->cq_kernel_addr >= data->target_value) {
+ spin_unlock_irqrestore(&data->interrupt->ts_list_lock, flags);
+
+ dev_dbg(hdev->dev, "Target value already reached release ts record: pend: %p, offset: %llu, interrupt: %u\n",
+ pend, data->ts_offset, data->interrupt->interrupt_id);
+
+ pend->ts_reg_info.in_use = 0;
+ *status = HL_WAIT_CS_STATUS_COMPLETED;
+ *pend->ts_reg_info.timestamp_kernel_addr = ktime_get_ns();
+
+ goto put_ts_buff;
+ }
+
+ list_add_tail(&pend->list_node, &data->interrupt->ts_list_head);
+ spin_unlock_irqrestore(&data->interrupt->ts_list_lock, flags);
+
+ rc = *status = HL_WAIT_CS_STATUS_COMPLETED;
+
+ hl_ctx_put(ctx);
+
+ return rc;
+
+put_ts_buff:
+ hl_mmap_mem_buf_put(data->buf);
+put_cq_cb:
+ hl_cb_put(data->cq_cb);
+put_ctx:
+ hl_ctx_put(ctx);
+
+ return rc;
}
static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,
- struct hl_mem_mgr *cb_mmg, struct hl_mem_mgr *mmg,
- u64 timeout_us, u64 cq_counters_handle, u64 cq_counters_offset,
- u64 target_value, struct hl_user_interrupt *interrupt,
- bool register_ts_record, u64 ts_handle, u64 ts_offset,
+ struct wait_interrupt_data *data,
u32 *status, u64 *timestamp)
{
struct hl_user_pending_interrupt *pend;
- struct hl_mmap_mem_buf *buf;
- struct hl_cb *cq_cb;
- unsigned long timeout;
+ unsigned long timeout, flags;
long completion_rc;
int rc = 0;
- timeout = hl_usecs64_to_jiffies(timeout_us);
+ timeout = hl_usecs64_to_jiffies(data->intr_timeout_us);
hl_ctx_get(ctx);
- cq_cb = hl_cb_get(cb_mmg, cq_counters_handle);
- if (!cq_cb) {
+ data->cq_cb = hl_cb_get(data->mmg, data->cq_handle);
+ if (!data->cq_cb) {
rc = -EINVAL;
goto put_ctx;
}
/* Validate the cq offset */
- if (((u64 *) cq_cb->kernel_address + cq_counters_offset) >=
- ((u64 *) cq_cb->kernel_address + (cq_cb->size / sizeof(u64)))) {
+ if (((u64 *) data->cq_cb->kernel_address + data->cq_offset) >=
+ ((u64 *) data->cq_cb->kernel_address + (data->cq_cb->size / sizeof(u64)))) {
rc = -EINVAL;
goto put_cq_cb;
}
- if (register_ts_record) {
- dev_dbg(hdev->dev, "Timestamp registration: interrupt id: %u, ts offset: %llu, cq_offset: %llu\n",
- interrupt->interrupt_id, ts_offset, cq_counters_offset);
- buf = hl_mmap_mem_buf_get(mmg, ts_handle);
- if (!buf) {
- rc = -EINVAL;
- goto put_cq_cb;
- }
-
- /* get ts buffer record */
- rc = ts_buff_get_kernel_ts_record(buf, cq_cb, ts_offset,
- cq_counters_offset, target_value,
- &interrupt->wait_list_lock, &pend);
- if (rc)
- goto put_ts_buff;
- } else {
- pend = kzalloc(sizeof(*pend), GFP_KERNEL);
- if (!pend) {
- rc = -ENOMEM;
- goto put_cq_cb;
- }
- hl_fence_init(&pend->fence, ULONG_MAX);
- pend->cq_kernel_addr = (u64 *) cq_cb->kernel_address + cq_counters_offset;
- pend->cq_target_value = target_value;
+ pend = kzalloc(sizeof(*pend), GFP_KERNEL);
+ if (!pend) {
+ rc = -ENOMEM;
+ goto put_cq_cb;
}
- spin_lock(&interrupt->wait_list_lock);
+ hl_fence_init(&pend->fence, ULONG_MAX);
+ pend->cq_kernel_addr = (u64 *) data->cq_cb->kernel_address + data->cq_offset;
+ pend->cq_target_value = data->target_value;
+ spin_lock_irqsave(&data->interrupt->wait_list_lock, flags);
+
/* We check for completion value as interrupt could have been received
- * before we added the node to the wait list
+ * before we add the wait node to the wait list.
*/
- if (*pend->cq_kernel_addr >= target_value) {
- if (register_ts_record)
- pend->ts_reg_info.in_use = 0;
- spin_unlock(&interrupt->wait_list_lock);
+ if (*pend->cq_kernel_addr >= data->target_value || (!data->intr_timeout_us)) {
+ spin_unlock_irqrestore(&data->interrupt->wait_list_lock, flags);
- *status = HL_WAIT_CS_STATUS_COMPLETED;
+ if (*pend->cq_kernel_addr >= data->target_value)
+ *status = HL_WAIT_CS_STATUS_COMPLETED;
+ else
+ *status = HL_WAIT_CS_STATUS_BUSY;
- if (register_ts_record) {
- *pend->ts_reg_info.timestamp_kernel_addr = ktime_get_ns();
- goto put_ts_buff;
- } else {
- pend->fence.timestamp = ktime_get();
- goto set_timestamp;
- }
- } else if (!timeout_us) {
- spin_unlock(&interrupt->wait_list_lock);
- *status = HL_WAIT_CS_STATUS_BUSY;
pend->fence.timestamp = ktime_get();
goto set_timestamp;
}
@@ -3366,55 +3458,38 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,
* Note that we cannot have sorted list by target value,
* in order to shorten the list pass loop, since
* same list could have nodes for different cq counter handle.
- * Note:
- * Mark ts buff offset as in use here in the spinlock protection area
- * to avoid getting in the re-use section in ts_buff_get_kernel_ts_record
- * before adding the node to the list. this scenario might happen when
- * multiple threads are racing on same offset and one thread could
- * set the ts buff in ts_buff_get_kernel_ts_record then the other thread
- * takes over and get to ts_buff_get_kernel_ts_record and then we will try
- * to re-use the same ts buff offset, and will try to delete a non existing
- * node from the list.
*/
- if (register_ts_record)
- pend->ts_reg_info.in_use = 1;
-
- list_add_tail(&pend->wait_list_node, &interrupt->wait_list_head);
- spin_unlock(&interrupt->wait_list_lock);
-
- if (register_ts_record) {
- rc = *status = HL_WAIT_CS_STATUS_COMPLETED;
- goto ts_registration_exit;
- }
+ list_add_tail(&pend->list_node, &data->interrupt->wait_list_head);
+ spin_unlock_irqrestore(&data->interrupt->wait_list_lock, flags);
/* Wait for interrupt handler to signal completion */
completion_rc = wait_for_completion_interruptible_timeout(&pend->fence.completion,
timeout);
if (completion_rc > 0) {
- *status = HL_WAIT_CS_STATUS_COMPLETED;
+ if (pend->fence.error == -EIO) {
+ dev_err_ratelimited(hdev->dev,
+ "interrupt based wait ioctl aborted(error:%d) due to a reset cycle initiated\n",
+ pend->fence.error);
+ rc = -EIO;
+ *status = HL_WAIT_CS_STATUS_ABORTED;
+ } else {
+ *status = HL_WAIT_CS_STATUS_COMPLETED;
+ }
} else {
if (completion_rc == -ERESTARTSYS) {
dev_err_ratelimited(hdev->dev,
"user process got signal while waiting for interrupt ID %d\n",
- interrupt->interrupt_id);
+ data->interrupt->interrupt_id);
rc = -EINTR;
*status = HL_WAIT_CS_STATUS_ABORTED;
} else {
- if (pend->fence.error == -EIO) {
- dev_err_ratelimited(hdev->dev,
- "interrupt based wait ioctl aborted(error:%d) due to a reset cycle initiated\n",
- pend->fence.error);
- rc = -EIO;
- *status = HL_WAIT_CS_STATUS_ABORTED;
- } else {
- /* The wait has timed-out. We don't know anything beyond that
- * because the workload wasn't submitted through the driver.
- * Therefore, from driver's perspective, the workload is still
- * executing.
- */
- rc = 0;
- *status = HL_WAIT_CS_STATUS_BUSY;
- }
+ /* The wait has timed-out. We don't know anything beyond that
+ * because the workload was not submitted through the driver.
+ * Therefore, from driver's perspective, the workload is still
+ * executing.
+ */
+ rc = 0;
+ *status = HL_WAIT_CS_STATUS_BUSY;
}
}
@@ -3424,23 +3499,20 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,
* for ts record, the node will be deleted in the irq handler after
* we reach the target value.
*/
- spin_lock(&interrupt->wait_list_lock);
- list_del(&pend->wait_list_node);
- spin_unlock(&interrupt->wait_list_lock);
+ spin_lock_irqsave(&data->interrupt->wait_list_lock, flags);
+ list_del(&pend->list_node);
+ spin_unlock_irqrestore(&data->interrupt->wait_list_lock, flags);
set_timestamp:
*timestamp = ktime_to_ns(pend->fence.timestamp);
kfree(pend);
- hl_cb_put(cq_cb);
-ts_registration_exit:
+ hl_cb_put(data->cq_cb);
hl_ctx_put(ctx);
return rc;
-put_ts_buff:
- hl_mmap_mem_buf_put(buf);
put_cq_cb:
- hl_cb_put(cq_cb);
+ hl_cb_put(data->cq_cb);
put_ctx:
hl_ctx_put(ctx);
@@ -3454,7 +3526,7 @@ static int _hl_interrupt_wait_ioctl_user_addr(struct hl_device *hdev, struct hl_
u64 *timestamp)
{
struct hl_user_pending_interrupt *pend;
- unsigned long timeout;
+ unsigned long timeout, flags;
u64 completion_value;
long completion_rc;
int rc = 0;
@@ -3474,9 +3546,9 @@ static int _hl_interrupt_wait_ioctl_user_addr(struct hl_device *hdev, struct hl_
/* Add pending user interrupt to relevant list for the interrupt
* handler to monitor
*/
- spin_lock(&interrupt->wait_list_lock);
- list_add_tail(&pend->wait_list_node, &interrupt->wait_list_head);
- spin_unlock(&interrupt->wait_list_lock);
+ spin_lock_irqsave(&interrupt->wait_list_lock, flags);
+ list_add_tail(&pend->list_node, &interrupt->wait_list_head);
+ spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
/* We check for completion value as interrupt could have been received
* before we added the node to the wait list
@@ -3507,14 +3579,14 @@ wait_again:
* If comparison fails, keep waiting until timeout expires
*/
if (completion_rc > 0) {
- spin_lock(&interrupt->wait_list_lock);
+ spin_lock_irqsave(&interrupt->wait_list_lock, flags);
/* reinit_completion must be called before we check for user
* completion value, otherwise, if interrupt is received after
* the comparison and before the next wait_for_completion,
* we will reach timeout and fail
*/
reinit_completion(&pend->fence.completion);
- spin_unlock(&interrupt->wait_list_lock);
+ spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
if (copy_from_user(&completion_value, u64_to_user_ptr(user_address), 8)) {
dev_err(hdev->dev, "Failed to copy completion value from user\n");
@@ -3551,9 +3623,9 @@ wait_again:
}
remove_pending_user_interrupt:
- spin_lock(&interrupt->wait_list_lock);
- list_del(&pend->wait_list_node);
- spin_unlock(&interrupt->wait_list_lock);
+ spin_lock_irqsave(&interrupt->wait_list_lock, flags);
+ list_del(&pend->list_node);
+ spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
*timestamp = ktime_to_ns(pend->fence.timestamp);
@@ -3611,19 +3683,42 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data)
return -EINVAL;
}
- if (args->in.flags & HL_WAIT_CS_FLAGS_INTERRUPT_KERNEL_CQ)
- rc = _hl_interrupt_wait_ioctl(hdev, hpriv->ctx, &hpriv->mem_mgr, &hpriv->mem_mgr,
- args->in.interrupt_timeout_us, args->in.cq_counters_handle,
- args->in.cq_counters_offset,
- args->in.target, interrupt,
- !!(args->in.flags & HL_WAIT_CS_FLAGS_REGISTER_INTERRUPT),
- args->in.timestamp_handle, args->in.timestamp_offset,
- &status, &timestamp);
- else
+ if (args->in.flags & HL_WAIT_CS_FLAGS_INTERRUPT_KERNEL_CQ) {
+ struct wait_interrupt_data wait_intr_data = {0};
+
+ wait_intr_data.interrupt = interrupt;
+ wait_intr_data.mmg = &hpriv->mem_mgr;
+ wait_intr_data.cq_handle = args->in.cq_counters_handle;
+ wait_intr_data.cq_offset = args->in.cq_counters_offset;
+ wait_intr_data.ts_handle = args->in.timestamp_handle;
+ wait_intr_data.ts_offset = args->in.timestamp_offset;
+ wait_intr_data.target_value = args->in.target;
+ wait_intr_data.intr_timeout_us = args->in.interrupt_timeout_us;
+
+ if (args->in.flags & HL_WAIT_CS_FLAGS_REGISTER_INTERRUPT) {
+ /*
+ * Allow only one registration at a time. this is needed in order to prevent
+ * issues while handling the flow of re-use of the same offset.
+ * Since the registration flow is protected only by the interrupt lock,
+ * re-use flow might request to move ts node to another interrupt list,
+ * and in such case we're not protected.
+ */
+ mutex_lock(&hpriv->ctx->ts_reg_lock);
+
+ rc = _hl_interrupt_ts_reg_ioctl(hdev, hpriv->ctx, &wait_intr_data,
+ &status, &timestamp);
+
+ mutex_unlock(&hpriv->ctx->ts_reg_lock);
+ } else
+ rc = _hl_interrupt_wait_ioctl(hdev, hpriv->ctx, &wait_intr_data,
+ &status, &timestamp);
+ } else {
rc = _hl_interrupt_wait_ioctl_user_addr(hdev, hpriv->ctx,
args->in.interrupt_timeout_us, args->in.addr,
args->in.target, interrupt, &status,
&timestamp);
+ }
+
if (rc)
return rc;
@@ -3638,8 +3733,9 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data)
return 0;
}
-int hl_wait_ioctl(struct hl_fpriv *hpriv, void *data)
+int hl_wait_ioctl(struct drm_device *ddev, void *data, struct drm_file *file_priv)
{
+ struct hl_fpriv *hpriv = file_priv->driver_priv;
struct hl_device *hdev = hpriv->hdev;
union hl_wait_cs_args *args = data;
u32 flags = args->in.flags;
diff --git a/drivers/accel/habanalabs/common/context.c b/drivers/accel/habanalabs/common/context.c
index 9c8b1b37b510..b83141f58319 100644
--- a/drivers/accel/habanalabs/common/context.c
+++ b/drivers/accel/habanalabs/common/context.c
@@ -102,7 +102,7 @@ static void hl_ctx_fini(struct hl_ctx *ctx)
kfree(ctx->cs_pending);
if (ctx->asid != HL_KERNEL_ASID_ID) {
- dev_dbg(hdev->dev, "closing user context %d\n", ctx->asid);
+ dev_dbg(hdev->dev, "closing user context, asid=%u\n", ctx->asid);
/* The engines are stopped as there is no executing CS, but the
* Coresight might be still working by accessing addresses
@@ -119,6 +119,7 @@ static void hl_ctx_fini(struct hl_ctx *ctx)
hl_vm_ctx_fini(ctx);
hl_asid_free(hdev, ctx->asid);
hl_encaps_sig_mgr_fini(hdev, &ctx->sig_mgr);
+ mutex_destroy(&ctx->ts_reg_lock);
} else {
dev_dbg(hdev->dev, "closing kernel context\n");
hdev->asic_funcs->ctx_fini(ctx);
@@ -198,6 +199,7 @@ out_err:
int hl_ctx_init(struct hl_device *hdev, struct hl_ctx *ctx, bool is_kernel_ctx)
{
+ char task_comm[TASK_COMM_LEN];
int rc = 0, i;
ctx->hdev = hdev;
@@ -267,7 +269,10 @@ int hl_ctx_init(struct hl_device *hdev, struct hl_ctx *ctx, bool is_kernel_ctx)
hl_encaps_sig_mgr_init(&ctx->sig_mgr);
- dev_dbg(hdev->dev, "create user context %d\n", ctx->asid);
+ mutex_init(&ctx->ts_reg_lock);
+
+ dev_dbg(hdev->dev, "create user context, comm=\"%s\", asid=%u\n",
+ get_task_comm(task_comm, current), ctx->asid);
}
return 0;
diff --git a/drivers/accel/habanalabs/common/debugfs.c b/drivers/accel/habanalabs/common/debugfs.c
index 9e84a47a21dc..01f071d52570 100644
--- a/drivers/accel/habanalabs/common/debugfs.c
+++ b/drivers/accel/habanalabs/common/debugfs.c
@@ -18,8 +18,6 @@
#define MMU_KBUF_SIZE (MMU_ADDR_BUF_SIZE + MMU_ASID_BUF_SIZE)
#define I2C_MAX_TRANSACTION_LEN 8
-static struct dentry *hl_debug_root;
-
static int hl_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,
u8 i2c_reg, u8 i2c_len, u64 *val)
{
@@ -1788,20 +1786,14 @@ void hl_debugfs_add_device(struct hl_device *hdev)
{
struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
- dev_entry->root = debugfs_create_dir(dev_name(hdev->dev), hl_debug_root);
+ dev_entry->root = hdev->drm.accel->debugfs_root;
add_files_to_device(hdev, dev_entry, dev_entry->root);
+
if (!hdev->asic_prop.fw_security_enabled)
add_secured_nodes(dev_entry, dev_entry->root);
}
-void hl_debugfs_remove_device(struct hl_device *hdev)
-{
- struct hl_dbg_device_entry *entry = &hdev->hl_debugfs;
-
- debugfs_remove_recursive(entry->root);
-}
-
void hl_debugfs_add_file(struct hl_fpriv *hpriv)
{
struct hl_dbg_device_entry *dev_entry = &hpriv->hdev->hl_debugfs;
@@ -1932,13 +1924,3 @@ void hl_debugfs_set_state_dump(struct hl_device *hdev, char *data,
up_write(&dev_entry->state_dump_sem);
}
-
-void __init hl_debugfs_init(void)
-{
- hl_debug_root = debugfs_create_dir("habanalabs", NULL);
-}
-
-void hl_debugfs_fini(void)
-{
- debugfs_remove_recursive(hl_debug_root);
-}
diff --git a/drivers/accel/habanalabs/common/device.c b/drivers/accel/habanalabs/common/device.c
index b97339d1f7c6..9711e8fc979d 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -14,11 +14,14 @@
#include <linux/hwmon.h>
#include <linux/vmalloc.h>
+#include <drm/drm_accel.h>
+#include <drm/drm_drv.h>
+
#include <trace/events/habanalabs.h>
#define HL_RESET_DELAY_USEC 10000 /* 10ms */
-#define HL_DEVICE_RELEASE_WATCHDOG_TIMEOUT_SEC 5
+#define HL_DEVICE_RELEASE_WATCHDOG_TIMEOUT_SEC 30
enum dma_alloc_type {
DMA_ALLOC_COHERENT,
@@ -185,7 +188,36 @@ void hl_cpu_accessible_dma_pool_free(struct hl_device *hdev, size_t size, void *
hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev, size, vaddr);
}
-int hl_dma_map_sgtable(struct hl_device *hdev, struct sg_table *sgt, enum dma_data_direction dir)
+int hl_dma_map_sgtable_caller(struct hl_device *hdev, struct sg_table *sgt,
+ enum dma_data_direction dir, const char *caller)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ struct scatterlist *sg;
+ int rc, i;
+
+ rc = hdev->asic_funcs->dma_map_sgtable(hdev, sgt, dir);
+ if (rc)
+ return rc;
+
+ if (!trace_habanalabs_dma_map_page_enabled())
+ return 0;
+
+ for_each_sgtable_dma_sg(sgt, sg, i)
+ trace_habanalabs_dma_map_page(hdev->dev,
+ page_to_phys(sg_page(sg)),
+ sg->dma_address - prop->device_dma_offset_for_host_access,
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+ sg->dma_length,
+#else
+ sg->length,
+#endif
+ dir, caller);
+
+ return 0;
+}
+
+int hl_asic_dma_map_sgtable(struct hl_device *hdev, struct sg_table *sgt,
+ enum dma_data_direction dir)
{
struct asic_fixed_properties *prop = &hdev->asic_prop;
struct scatterlist *sg;
@@ -203,7 +235,30 @@ int hl_dma_map_sgtable(struct hl_device *hdev, struct sg_table *sgt, enum dma_da
return 0;
}
-void hl_dma_unmap_sgtable(struct hl_device *hdev, struct sg_table *sgt, enum dma_data_direction dir)
+void hl_dma_unmap_sgtable_caller(struct hl_device *hdev, struct sg_table *sgt,
+ enum dma_data_direction dir, const char *caller)
+{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ struct scatterlist *sg;
+ int i;
+
+ hdev->asic_funcs->dma_unmap_sgtable(hdev, sgt, dir);
+
+ if (trace_habanalabs_dma_unmap_page_enabled()) {
+ for_each_sgtable_dma_sg(sgt, sg, i)
+ trace_habanalabs_dma_unmap_page(hdev->dev, page_to_phys(sg_page(sg)),
+ sg->dma_address - prop->device_dma_offset_for_host_access,
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+ sg->dma_length,
+#else
+ sg->length,
+#endif
+ dir, caller);
+ }
+}
+
+void hl_asic_dma_unmap_sgtable(struct hl_device *hdev, struct sg_table *sgt,
+ enum dma_data_direction dir)
{
struct asic_fixed_properties *prop = &hdev->asic_prop;
struct scatterlist *sg;
@@ -315,7 +370,9 @@ enum hl_device_status hl_device_status(struct hl_device *hdev)
{
enum hl_device_status status;
- if (hdev->reset_info.in_reset) {
+ if (hdev->device_fini_pending) {
+ status = HL_DEVICE_STATUS_MALFUNCTION;
+ } else if (hdev->reset_info.in_reset) {
if (hdev->reset_info.in_compute_reset)
status = HL_DEVICE_STATUS_IN_RESET_AFTER_DEVICE_RELEASE;
else
@@ -343,9 +400,9 @@ bool hl_device_operational(struct hl_device *hdev,
*status = current_status;
switch (current_status) {
+ case HL_DEVICE_STATUS_MALFUNCTION:
case HL_DEVICE_STATUS_IN_RESET:
case HL_DEVICE_STATUS_IN_RESET_AFTER_DEVICE_RELEASE:
- case HL_DEVICE_STATUS_MALFUNCTION:
case HL_DEVICE_STATUS_NEEDS_RESET:
return false;
case HL_DEVICE_STATUS_OPERATIONAL:
@@ -406,8 +463,6 @@ static void hpriv_release(struct kref *ref)
hdev->asic_funcs->send_device_activity(hdev, false);
- put_pid(hpriv->taskpid);
-
hl_debugfs_remove_file(hpriv);
mutex_destroy(&hpriv->ctx_lock);
@@ -424,7 +479,7 @@ static void hpriv_release(struct kref *ref)
/* Check the device idle status and reset if not idle.
* Skip it if already in reset, or if device is going to be reset in any case.
*/
- if (!hdev->reset_info.in_reset && !reset_device && hdev->pdev && !hdev->pldm)
+ if (!hdev->reset_info.in_reset && !reset_device && !hdev->pldm)
device_is_idle = hdev->asic_funcs->is_device_idle(hdev, idle_mask,
HL_BUSY_ENGINES_MASK_EXT_SIZE, NULL);
if (!device_is_idle) {
@@ -446,14 +501,18 @@ static void hpriv_release(struct kref *ref)
list_del(&hpriv->dev_node);
mutex_unlock(&hdev->fpriv_list_lock);
+ put_pid(hpriv->taskpid);
+
if (reset_device) {
hl_device_reset(hdev, HL_DRV_RESET_DEV_RELEASE);
} else {
/* Scrubbing is handled within hl_device_reset(), so here need to do it directly */
int rc = hdev->asic_funcs->scrub_device_mem(hdev);
- if (rc)
+ if (rc) {
dev_err(hdev->dev, "failed to scrub memory from hpriv release (%d)\n", rc);
+ hl_device_reset(hdev, HL_DRV_RESET_HARD);
+ }
}
/* Now we can mark the compute_ctx as not active. Even if a reset is running in a different
@@ -516,24 +575,20 @@ static void print_device_in_use_info(struct hl_device *hdev, const char *message
}
/*
- * hl_device_release - release function for habanalabs device
- *
- * @inode: pointer to inode structure
- * @filp: pointer to file structure
+ * hl_device_release() - release function for habanalabs device.
+ * @ddev: pointer to DRM device structure.
+ * @file: pointer to DRM file private data structure.
*
* Called when process closes an habanalabs device
*/
-static int hl_device_release(struct inode *inode, struct file *filp)
+void hl_device_release(struct drm_device *ddev, struct drm_file *file_priv)
{
- struct hl_fpriv *hpriv = filp->private_data;
- struct hl_device *hdev = hpriv->hdev;
-
- filp->private_data = NULL;
+ struct hl_fpriv *hpriv = file_priv->driver_priv;
+ struct hl_device *hdev = to_hl_device(ddev);
if (!hdev) {
pr_crit("Closing FD after device was removed. Memory leak will occur and it is advised to reboot.\n");
put_pid(hpriv->taskpid);
- return 0;
}
hl_ctx_mgr_fini(hdev, &hpriv->ctx_mgr);
@@ -551,8 +606,6 @@ static int hl_device_release(struct inode *inode, struct file *filp)
}
hdev->last_open_session_duration_jif = jiffies - hdev->last_successful_open_jif;
-
- return 0;
}
static int hl_device_release_ctrl(struct inode *inode, struct file *filp)
@@ -571,11 +624,6 @@ static int hl_device_release_ctrl(struct inode *inode, struct file *filp)
list_del(&hpriv->dev_node);
mutex_unlock(&hdev->fpriv_ctrl_list_lock);
out:
- /* release the eventfd */
- if (hpriv->notifier_event.eventfd)
- eventfd_ctx_put(hpriv->notifier_event.eventfd);
-
- mutex_destroy(&hpriv->notifier_event.lock);
put_pid(hpriv->taskpid);
kfree(hpriv);
@@ -583,18 +631,8 @@ out:
return 0;
}
-/*
- * hl_mmap - mmap function for habanalabs device
- *
- * @*filp: pointer to file structure
- * @*vma: pointer to vm_area_struct of the process
- *
- * Called when process does an mmap on habanalabs device. Call the relevant mmap
- * function at the end of the common code.
- */
-static int hl_mmap(struct file *filp, struct vm_area_struct *vma)
+static int __hl_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
{
- struct hl_fpriv *hpriv = filp->private_data;
struct hl_device *hdev = hpriv->hdev;
unsigned long vm_pgoff;
@@ -617,14 +655,22 @@ static int hl_mmap(struct file *filp, struct vm_area_struct *vma)
return -EINVAL;
}
-static const struct file_operations hl_ops = {
- .owner = THIS_MODULE,
- .open = hl_device_open,
- .release = hl_device_release,
- .mmap = hl_mmap,
- .unlocked_ioctl = hl_ioctl,
- .compat_ioctl = hl_ioctl
-};
+/*
+ * hl_mmap - mmap function for habanalabs device
+ *
+ * @*filp: pointer to file structure
+ * @*vma: pointer to vm_area_struct of the process
+ *
+ * Called when process does an mmap on habanalabs device. Call the relevant mmap
+ * function at the end of the common code.
+ */
+int hl_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct drm_file *file_priv = filp->private_data;
+ struct hl_fpriv *hpriv = file_priv->driver_priv;
+
+ return __hl_mmap(hpriv, vma);
+}
static const struct file_operations hl_ctrl_ops = {
.owner = THIS_MODULE,
@@ -645,14 +691,14 @@ static void device_release_func(struct device *dev)
* @hdev: pointer to habanalabs device structure
* @class: pointer to the class object of the device
* @minor: minor number of the specific device
- * @fpos: file operations to install for this device
+ * @fops: file operations to install for this device
* @name: name of the device as it will appear in the filesystem
* @cdev: pointer to the char device object that will be initialized
* @dev: pointer to the device object that will be initialized
*
* Initialize a cdev and a Linux device for habanalabs's device.
*/
-static int device_init_cdev(struct hl_device *hdev, struct class *class,
+static int device_init_cdev(struct hl_device *hdev, const struct class *class,
int minor, const struct file_operations *fops,
char *name, struct cdev *cdev,
struct device **dev)
@@ -676,23 +722,26 @@ static int device_init_cdev(struct hl_device *hdev, struct class *class,
static int cdev_sysfs_debugfs_add(struct hl_device *hdev)
{
+ const struct class *accel_class = hdev->drm.accel->kdev->class;
+ char name[32];
int rc;
- rc = cdev_device_add(&hdev->cdev, hdev->dev);
- if (rc) {
- dev_err(hdev->dev,
- "failed to add a char device to the system\n");
+ hdev->cdev_idx = hdev->drm.accel->index;
+
+ /* Initialize cdev and device structures for the control device */
+ snprintf(name, sizeof(name), "accel_controlD%d", hdev->cdev_idx);
+ rc = device_init_cdev(hdev, accel_class, hdev->cdev_idx, &hl_ctrl_ops, name,
+ &hdev->cdev_ctrl, &hdev->dev_ctrl);
+ if (rc)
return rc;
- }
rc = cdev_device_add(&hdev->cdev_ctrl, hdev->dev_ctrl);
if (rc) {
- dev_err(hdev->dev,
- "failed to add a control char device to the system\n");
- goto delete_cdev_device;
+ dev_err(hdev->dev_ctrl,
+ "failed to add an accel control char device to the system\n");
+ goto free_ctrl_device;
}
- /* hl_sysfs_init() must be done after adding the device to the system */
rc = hl_sysfs_init(hdev);
if (rc) {
dev_err(hdev->dev, "failed to initialize sysfs\n");
@@ -707,23 +756,19 @@ static int cdev_sysfs_debugfs_add(struct hl_device *hdev)
delete_ctrl_cdev_device:
cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl);
-delete_cdev_device:
- cdev_device_del(&hdev->cdev, hdev->dev);
+free_ctrl_device:
+ put_device(hdev->dev_ctrl);
return rc;
}
static void cdev_sysfs_debugfs_remove(struct hl_device *hdev)
{
if (!hdev->cdev_sysfs_debugfs_created)
- goto put_devices;
+ return;
- hl_debugfs_remove_device(hdev);
hl_sysfs_fini(hdev);
- cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl);
- cdev_device_del(&hdev->cdev, hdev->dev);
-put_devices:
- put_device(hdev->dev);
+ cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl);
put_device(hdev->dev_ctrl);
}
@@ -996,6 +1041,20 @@ static bool is_pci_link_healthy(struct hl_device *hdev)
return (vendor_id == PCI_VENDOR_ID_HABANALABS);
}
+static void hl_device_eq_heartbeat(struct hl_device *hdev)
+{
+ u64 event_mask = HL_NOTIFIER_EVENT_DEVICE_RESET | HL_NOTIFIER_EVENT_DEVICE_UNAVAILABLE;
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+
+ if (!prop->cpucp_info.eq_health_check_supported)
+ return;
+
+ if (hdev->eq_heartbeat_received)
+ hdev->eq_heartbeat_received = false;
+ else
+ hl_device_cond_reset(hdev, HL_DRV_RESET_HARD, event_mask);
+}
+
static void hl_device_heartbeat(struct work_struct *work)
{
struct hl_device *hdev = container_of(work, struct hl_device,
@@ -1003,9 +1062,16 @@ static void hl_device_heartbeat(struct work_struct *work)
struct hl_info_fw_err_info info = {0};
u64 event_mask = HL_NOTIFIER_EVENT_DEVICE_RESET | HL_NOTIFIER_EVENT_DEVICE_UNAVAILABLE;
- if (!hl_device_operational(hdev, NULL))
+ /* Start heartbeat checks only after driver has enabled events from FW */
+ if (!hl_device_operational(hdev, NULL) || !hdev->init_done)
goto reschedule;
+ /*
+ * For EQ health check need to check if driver received the heartbeat eq event
+ * in order to validate the eq is working.
+ */
+ hl_device_eq_heartbeat(hdev);
+
if (!hdev->asic_funcs->send_heartbeat(hdev))
goto reschedule;
@@ -1062,7 +1128,15 @@ static int device_late_init(struct hl_device *hdev)
hdev->high_pll = hdev->asic_prop.high_pll;
if (hdev->heartbeat) {
+ /*
+ * Before scheduling the heartbeat driver will check if eq event has received.
+ * for the first schedule we need to set the indication as true then for the next
+ * one this indication will be true only if eq event was sent by FW.
+ */
+ hdev->eq_heartbeat_received = true;
+
INIT_DELAYED_WORK(&hdev->work_heartbeat, hl_device_heartbeat);
+
schedule_delayed_work(&hdev->work_heartbeat,
usecs_to_jiffies(HL_HEARTBEAT_PER_USEC));
}
@@ -1302,18 +1376,18 @@ disable_device:
static int device_kill_open_processes(struct hl_device *hdev, u32 timeout, bool control_dev)
{
struct task_struct *task = NULL;
- struct list_head *fd_list;
- struct hl_fpriv *hpriv;
- struct mutex *fd_lock;
+ struct list_head *hpriv_list;
+ struct hl_fpriv *hpriv;
+ struct mutex *hpriv_lock;
u32 pending_cnt;
- fd_lock = control_dev ? &hdev->fpriv_ctrl_list_lock : &hdev->fpriv_list_lock;
- fd_list = control_dev ? &hdev->fpriv_ctrl_list : &hdev->fpriv_list;
+ hpriv_lock = control_dev ? &hdev->fpriv_ctrl_list_lock : &hdev->fpriv_list_lock;
+ hpriv_list = control_dev ? &hdev->fpriv_ctrl_list : &hdev->fpriv_list;
/* Giving time for user to close FD, and for processes that are inside
* hl_device_open to finish
*/
- if (!list_empty(fd_list))
+ if (!list_empty(hpriv_list))
ssleep(1);
if (timeout) {
@@ -1329,12 +1403,12 @@ static int device_kill_open_processes(struct hl_device *hdev, u32 timeout, bool
}
}
- mutex_lock(fd_lock);
+ mutex_lock(hpriv_lock);
/* This section must be protected because we are dereferencing
* pointers that are freed if the process exits
*/
- list_for_each_entry(hpriv, fd_list, dev_node) {
+ list_for_each_entry(hpriv, hpriv_list, dev_node) {
task = get_pid_task(hpriv->taskpid, PIDTYPE_PID);
if (task) {
dev_info(hdev->dev, "Killing user process pid=%d\n",
@@ -1344,17 +1418,13 @@ static int device_kill_open_processes(struct hl_device *hdev, u32 timeout, bool
put_task_struct(task);
} else {
- /*
- * If we got here, it means that process was killed from outside the driver
- * right after it started looping on fd_list and before get_pid_task, thus
- * we don't need to kill it.
- */
dev_dbg(hdev->dev,
- "Can't get task struct for user process, assuming process was killed from outside the driver\n");
+ "Can't get task struct for user process %d, process was killed from outside the driver\n",
+ pid_nr(hpriv->taskpid));
}
}
- mutex_unlock(fd_lock);
+ mutex_unlock(hpriv_lock);
/*
* We killed the open users, but that doesn't mean they are closed.
@@ -1366,7 +1436,7 @@ static int device_kill_open_processes(struct hl_device *hdev, u32 timeout, bool
*/
wait_for_processes:
- while ((!list_empty(fd_list)) && (pending_cnt)) {
+ while ((!list_empty(hpriv_list)) && (pending_cnt)) {
dev_dbg(hdev->dev,
"Waiting for all unmap operations to finish before hard reset\n");
@@ -1376,7 +1446,7 @@ wait_for_processes:
}
/* All processes exited successfully */
- if (list_empty(fd_list))
+ if (list_empty(hpriv_list))
return 0;
/* Give up waiting for processes to exit */
@@ -1390,17 +1460,17 @@ wait_for_processes:
static void device_disable_open_processes(struct hl_device *hdev, bool control_dev)
{
- struct list_head *fd_list;
+ struct list_head *hpriv_list;
struct hl_fpriv *hpriv;
- struct mutex *fd_lock;
+ struct mutex *hpriv_lock;
- fd_lock = control_dev ? &hdev->fpriv_ctrl_list_lock : &hdev->fpriv_list_lock;
- fd_list = control_dev ? &hdev->fpriv_ctrl_list : &hdev->fpriv_list;
+ hpriv_lock = control_dev ? &hdev->fpriv_ctrl_list_lock : &hdev->fpriv_list_lock;
+ hpriv_list = control_dev ? &hdev->fpriv_ctrl_list : &hdev->fpriv_list;
- mutex_lock(fd_lock);
- list_for_each_entry(hpriv, fd_list, dev_node)
+ mutex_lock(hpriv_lock);
+ list_for_each_entry(hpriv, hpriv_list, dev_node)
hpriv->hdev = NULL;
- mutex_unlock(fd_lock);
+ mutex_unlock(hpriv_lock);
}
static void send_disable_pci_access(struct hl_device *hdev, u32 flags)
@@ -1916,7 +1986,16 @@ int hl_device_cond_reset(struct hl_device *hdev, u32 flags, u64 event_mask)
}
ctx = hl_get_compute_ctx(hdev);
- if (!ctx || !ctx->hpriv->notifier_event.eventfd)
+ if (!ctx)
+ goto device_reset;
+
+ /*
+ * There is no point in postponing the reset if user is not registered for events.
+ * However if no eventfd_ctx exists but the device release watchdog is already scheduled, it
+ * just implies that user has unregistered as part of handling a previous event. In this
+ * case an immediate reset is not required.
+ */
+ if (!ctx->hpriv->notifier_event.eventfd && !hdev->reset_info.watchdog_active)
goto device_reset;
/* Schedule the device release watchdog work unless reset is already in progress or if the
@@ -1928,8 +2007,10 @@ int hl_device_cond_reset(struct hl_device *hdev, u32 flags, u64 event_mask)
goto device_reset;
}
- if (hdev->reset_info.watchdog_active)
+ if (hdev->reset_info.watchdog_active) {
+ hdev->device_release_watchdog_work.flags |= flags;
goto out;
+ }
hdev->device_release_watchdog_work.flags = flags;
dev_dbg(hdev->dev, "Device is going to be hard-reset in %u sec unless being released\n",
@@ -1990,59 +2071,6 @@ void hl_notifier_event_send_all(struct hl_device *hdev, u64 event_mask)
hl_notifier_event_send(&hpriv->notifier_event, event_mask);
mutex_unlock(&hdev->fpriv_list_lock);
-
- /* control device */
- mutex_lock(&hdev->fpriv_ctrl_list_lock);
-
- list_for_each_entry(hpriv, &hdev->fpriv_ctrl_list, dev_node)
- hl_notifier_event_send(&hpriv->notifier_event, event_mask);
-
- mutex_unlock(&hdev->fpriv_ctrl_list_lock);
-}
-
-static int create_cdev(struct hl_device *hdev)
-{
- char *name;
- int rc;
-
- hdev->cdev_idx = hdev->id / 2;
-
- name = kasprintf(GFP_KERNEL, "hl%d", hdev->cdev_idx);
- if (!name) {
- rc = -ENOMEM;
- goto out_err;
- }
-
- /* Initialize cdev and device structures */
- rc = device_init_cdev(hdev, hdev->hclass, hdev->id, &hl_ops, name,
- &hdev->cdev, &hdev->dev);
-
- kfree(name);
-
- if (rc)
- goto out_err;
-
- name = kasprintf(GFP_KERNEL, "hl_controlD%d", hdev->cdev_idx);
- if (!name) {
- rc = -ENOMEM;
- goto free_dev;
- }
-
- /* Initialize cdev and device structures for control device */
- rc = device_init_cdev(hdev, hdev->hclass, hdev->id_control, &hl_ctrl_ops,
- name, &hdev->cdev_ctrl, &hdev->dev_ctrl);
-
- kfree(name);
-
- if (rc)
- goto free_dev;
-
- return 0;
-
-free_dev:
- put_device(hdev->dev);
-out_err:
- return rc;
}
/*
@@ -2057,16 +2085,14 @@ out_err:
int hl_device_init(struct hl_device *hdev)
{
int i, rc, cq_cnt, user_interrupt_cnt, cq_ready_cnt;
+ struct hl_ts_free_jobs *free_jobs_data;
bool expose_interfaces_on_err = false;
-
- rc = create_cdev(hdev);
- if (rc)
- goto out_disabled;
+ void *p;
/* Initialize ASIC function pointers and perform early init */
rc = device_early_init(hdev);
if (rc)
- goto free_dev;
+ goto out_disabled;
user_interrupt_cnt = hdev->asic_prop.user_dec_intr_count +
hdev->asic_prop.user_interrupt_count;
@@ -2078,15 +2104,43 @@ int hl_device_init(struct hl_device *hdev)
rc = -ENOMEM;
goto early_fini;
}
+
+ /* Timestamp records supported only if CQ supported in device */
+ if (hdev->asic_prop.first_available_cq[0] != USHRT_MAX) {
+ for (i = 0 ; i < user_interrupt_cnt ; i++) {
+ p = vzalloc(TIMESTAMP_FREE_NODES_NUM *
+ sizeof(struct timestamp_reg_free_node));
+ if (!p) {
+ rc = -ENOMEM;
+ goto free_usr_intr_mem;
+ }
+ free_jobs_data = &hdev->user_interrupt[i].ts_free_jobs_data;
+ free_jobs_data->free_nodes_pool = p;
+ free_jobs_data->free_nodes_length = TIMESTAMP_FREE_NODES_NUM;
+ free_jobs_data->next_avail_free_node_idx = 0;
+ }
+ }
+ }
+
+ free_jobs_data = &hdev->common_user_cq_interrupt.ts_free_jobs_data;
+ p = vzalloc(TIMESTAMP_FREE_NODES_NUM *
+ sizeof(struct timestamp_reg_free_node));
+ if (!p) {
+ rc = -ENOMEM;
+ goto free_usr_intr_mem;
}
+ free_jobs_data->free_nodes_pool = p;
+ free_jobs_data->free_nodes_length = TIMESTAMP_FREE_NODES_NUM;
+ free_jobs_data->next_avail_free_node_idx = 0;
+
/*
* Start calling ASIC initialization. First S/W then H/W and finally
* late init
*/
rc = hdev->asic_funcs->sw_init(hdev);
if (rc)
- goto free_usr_intr_mem;
+ goto free_common_usr_intr_mem;
/* initialize completion structure for multi CS wait */
@@ -2253,6 +2307,14 @@ int hl_device_init(struct hl_device *hdev)
* From here there is no need to expose them in case of an error.
*/
expose_interfaces_on_err = false;
+
+ rc = drm_dev_register(&hdev->drm, 0);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to register DRM device, rc %d\n", rc);
+ rc = 0;
+ goto out_disabled;
+ }
+
rc = cdev_sysfs_debugfs_add(hdev);
if (rc) {
dev_err(hdev->dev, "Failed to add char devices and sysfs/debugfs files\n");
@@ -2284,8 +2346,6 @@ int hl_device_init(struct hl_device *hdev)
"Successfully added device %s to habanalabs driver\n",
dev_name(&(hdev)->pdev->dev));
- hdev->init_done = true;
-
/* After initialization is done, we are ready to receive events from
* the F/W. We can't do it before because we will ignore events and if
* those events are fatal, we won't know about it and the device will
@@ -2293,6 +2353,8 @@ int hl_device_init(struct hl_device *hdev)
*/
hdev->asic_funcs->enable_events_from_fw(hdev);
+ hdev->init_done = true;
+
return 0;
cb_pool_fini:
@@ -2317,19 +2379,27 @@ hw_queues_destroy:
hl_hw_queues_destroy(hdev);
sw_fini:
hdev->asic_funcs->sw_fini(hdev);
+free_common_usr_intr_mem:
+ vfree(hdev->common_user_cq_interrupt.ts_free_jobs_data.free_nodes_pool);
free_usr_intr_mem:
- kfree(hdev->user_interrupt);
+ if (user_interrupt_cnt) {
+ for (i = 0 ; i < user_interrupt_cnt ; i++) {
+ if (!hdev->user_interrupt[i].ts_free_jobs_data.free_nodes_pool)
+ break;
+ vfree(hdev->user_interrupt[i].ts_free_jobs_data.free_nodes_pool);
+ }
+ kfree(hdev->user_interrupt);
+ }
early_fini:
device_early_fini(hdev);
-free_dev:
- put_device(hdev->dev_ctrl);
- put_device(hdev->dev);
out_disabled:
hdev->disabled = true;
- if (expose_interfaces_on_err)
+ if (expose_interfaces_on_err) {
+ drm_dev_register(&hdev->drm, 0);
cdev_sysfs_debugfs_add(hdev);
- dev_err(&hdev->pdev->dev,
- "Failed to initialize hl%d. Device %s is NOT usable !\n",
+ }
+
+ pr_err("Failed to initialize accel%d. Device %s is NOT usable!\n",
hdev->cdev_idx, dev_name(&hdev->pdev->dev));
return rc;
@@ -2344,12 +2414,13 @@ out_disabled:
*/
void hl_device_fini(struct hl_device *hdev)
{
+ u32 user_interrupt_cnt;
bool device_in_reset;
ktime_t timeout;
u64 reset_sec;
int i, rc;
- dev_info(hdev->dev, "Removing device\n");
+ dev_info(hdev->dev, "Removing device %s\n", dev_name(&(hdev)->pdev->dev));
hdev->device_fini_pending = 1;
flush_delayed_work(&hdev->device_reset_work.reset_work);
@@ -2425,14 +2496,14 @@ void hl_device_fini(struct hl_device *hdev)
hdev->process_kill_trial_cnt = 0;
rc = device_kill_open_processes(hdev, HL_WAIT_PROCESS_KILL_ON_DEVICE_FINI, false);
if (rc) {
- dev_crit(hdev->dev, "Failed to kill all open processes\n");
+ dev_crit(hdev->dev, "Failed to kill all open processes (%d)\n", rc);
device_disable_open_processes(hdev, false);
}
hdev->process_kill_trial_cnt = 0;
rc = device_kill_open_processes(hdev, 0, true);
if (rc) {
- dev_crit(hdev->dev, "Failed to kill all control device open processes\n");
+ dev_crit(hdev->dev, "Failed to kill all control device open processes (%d)\n", rc);
device_disable_open_processes(hdev, true);
}
@@ -2464,7 +2535,20 @@ void hl_device_fini(struct hl_device *hdev)
for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++)
hl_cq_fini(hdev, &hdev->completion_queue[i]);
kfree(hdev->completion_queue);
- kfree(hdev->user_interrupt);
+
+ user_interrupt_cnt = hdev->asic_prop.user_dec_intr_count +
+ hdev->asic_prop.user_interrupt_count;
+
+ if (user_interrupt_cnt) {
+ if (hdev->asic_prop.first_available_cq[0] != USHRT_MAX) {
+ for (i = 0 ; i < user_interrupt_cnt ; i++)
+ vfree(hdev->user_interrupt[i].ts_free_jobs_data.free_nodes_pool);
+ }
+
+ kfree(hdev->user_interrupt);
+ }
+
+ vfree(hdev->common_user_cq_interrupt.ts_free_jobs_data.free_nodes_pool);
hl_hw_queues_destroy(hdev);
@@ -2475,6 +2559,7 @@ void hl_device_fini(struct hl_device *hdev)
/* Hide devices and sysfs/debugfs files from user */
cdev_sysfs_debugfs_remove(hdev);
+ drm_dev_unregister(&hdev->drm);
hl_debugfs_device_fini(hdev);
@@ -2690,6 +2775,20 @@ void hl_handle_fw_err(struct hl_device *hdev, struct hl_info_fw_err_info *info)
*info->event_mask |= HL_NOTIFIER_EVENT_CRITICL_FW_ERR;
}
+void hl_capture_engine_err(struct hl_device *hdev, u16 engine_id, u16 error_count)
+{
+ struct engine_err_info *info = &hdev->captured_err_info.engine_err;
+
+ /* Capture only the first engine error */
+ if (atomic_cmpxchg(&info->event_detected, 0, 1))
+ return;
+
+ info->event.timestamp = ktime_to_ns(ktime_get());
+ info->event.engine_id = engine_id;
+ info->event.error_count = error_count;
+ info->event_info_available = true;
+}
+
void hl_enable_err_info_capture(struct hl_error_info *captured_err_info)
{
vfree(captured_err_info->page_fault_info.user_mappings);
diff --git a/drivers/accel/habanalabs/common/firmware_if.c b/drivers/accel/habanalabs/common/firmware_if.c
index acbc1a6b5cb1..47e8384134aa 100644
--- a/drivers/accel/habanalabs/common/firmware_if.c
+++ b/drivers/accel/habanalabs/common/firmware_if.c
@@ -6,7 +6,7 @@
*/
#include "habanalabs.h"
-#include "../include/common/hl_boot_if.h"
+#include <linux/habanalabs/hl_boot_if.h>
#include <linux/firmware.h>
#include <linux/crc32.h>
@@ -724,6 +724,11 @@ static bool fw_report_boot_dev0(struct hl_device *hdev, u32 err_val,
err_exists = true;
}
+ if (err_val & CPU_BOOT_ERR0_TMP_THRESH_INIT_FAIL) {
+ dev_err(hdev->dev, "Device boot error - Failed to set threshold for temperature sensor\n");
+ err_exists = true;
+ }
+
if (err_val & CPU_BOOT_ERR0_DEVICE_UNUSABLE_FAIL) {
/* Ignore this bit, don't prevent driver loading */
dev_dbg(hdev->dev, "device unusable status is set\n");
@@ -1459,6 +1464,10 @@ static void detect_cpu_boot_status(struct hl_device *hdev, u32 status)
dev_err(hdev->dev,
"Device boot progress - Stuck in preboot after security initialization\n");
break;
+ case CPU_BOOT_STATUS_FW_SHUTDOWN_PREP:
+ dev_err(hdev->dev,
+ "Device boot progress - Stuck in preparation for shutdown\n");
+ break;
default:
dev_err(hdev->dev,
"Device boot progress - Invalid or unexpected status code %d\n", status);
@@ -1469,8 +1478,9 @@ static void detect_cpu_boot_status(struct hl_device *hdev, u32 status)
int hl_fw_wait_preboot_ready(struct hl_device *hdev)
{
struct pre_fw_load_props *pre_fw_load = &hdev->fw_loader.pre_fw_load;
- u32 status;
- int rc;
+ u32 status = 0, timeout;
+ int rc, tries = 1;
+ bool preboot_still_runs;
/* Need to check two possible scenarios:
*
@@ -1480,6 +1490,8 @@ int hl_fw_wait_preboot_ready(struct hl_device *hdev)
* All other status values - for older firmwares where the uboot was
* loaded from the FLASH
*/
+ timeout = pre_fw_load->wait_for_preboot_timeout;
+retry:
rc = hl_poll_timeout(
hdev,
pre_fw_load->cpu_boot_status_reg,
@@ -1488,7 +1500,24 @@ int hl_fw_wait_preboot_ready(struct hl_device *hdev)
(status == CPU_BOOT_STATUS_READY_TO_BOOT) ||
(status == CPU_BOOT_STATUS_WAITING_FOR_BOOT_FIT),
hdev->fw_poll_interval_usec,
- pre_fw_load->wait_for_preboot_timeout);
+ timeout);
+ /*
+ * if F/W reports "security-ready" it means preboot might take longer.
+ * If the field 'wait_for_preboot_extended_timeout' is non 0 we wait again
+ * with that timeout
+ */
+ preboot_still_runs = (status == CPU_BOOT_STATUS_SECURITY_READY ||
+ status == CPU_BOOT_STATUS_IN_PREBOOT ||
+ status == CPU_BOOT_STATUS_FW_SHUTDOWN_PREP ||
+ status == CPU_BOOT_STATUS_DRAM_RDY);
+
+ if (rc && tries && preboot_still_runs) {
+ tries--;
+ if (pre_fw_load->wait_for_preboot_extended_timeout) {
+ timeout = pre_fw_load->wait_for_preboot_extended_timeout;
+ goto retry;
+ }
+ }
if (rc) {
detect_cpu_boot_status(hdev, status);
@@ -2743,7 +2772,8 @@ static int hl_fw_dynamic_init_cpu(struct hl_device *hdev,
if (!(hdev->fw_components & FW_TYPE_BOOT_CPU)) {
struct lkd_fw_binning_info *binning_info;
- rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader, 0);
+ rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader,
+ sizeof(struct lkd_msg_comms));
if (rc)
goto protocol_err;
@@ -2777,6 +2807,11 @@ static int hl_fw_dynamic_init_cpu(struct hl_device *hdev,
hdev->decoder_binning, hdev->rotator_binning);
}
+ if (hdev->asic_prop.support_dynamic_resereved_fw_size) {
+ hdev->asic_prop.reserved_fw_mem_size =
+ le32_to_cpu(fw_loader->dynamic_loader.comm_desc.rsvd_mem_size_mb);
+ }
+
return 0;
}
diff --git a/drivers/accel/habanalabs/common/habanalabs.h b/drivers/accel/habanalabs/common/habanalabs.h
index 2f027d5a8206..1655c101c705 100644
--- a/drivers/accel/habanalabs/common/habanalabs.h
+++ b/drivers/accel/habanalabs/common/habanalabs.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright 2016-2022 HabanaLabs, Ltd.
+ * Copyright 2016-2023 HabanaLabs, Ltd.
* All Rights Reserved.
*
*/
@@ -8,7 +8,7 @@
#ifndef HABANALABSP_H_
#define HABANALABSP_H_
-#include "../include/common/cpucp_if.h"
+#include <linux/habanalabs/cpucp_if.h>
#include "../include/common/qman_if.h"
#include "../include/hw_ip/mmu/mmu_general.h"
#include <uapi/drm/habanalabs_accel.h>
@@ -29,6 +29,9 @@
#include <linux/coresight.h>
#include <linux/dma-buf.h>
+#include <drm/drm_device.h>
+#include <drm/drm_file.h>
+
#include "security.h"
#define HL_NAME "habanalabs"
@@ -82,8 +85,6 @@ struct hl_fpriv;
#define HL_PCI_ELBI_TIMEOUT_MSEC 10 /* 10ms */
-#define HL_SIM_MAX_TIMEOUT_US 100000000 /* 100s */
-
#define HL_INVALID_QUEUE UINT_MAX
#define HL_COMMON_USER_CQ_INTERRUPT_ID 0xFFF
@@ -103,6 +104,8 @@ struct hl_fpriv;
/* MMU */
#define MMU_HASH_TABLE_BITS 7 /* 1 << 7 buckets */
+#define TIMESTAMP_FREE_NODES_NUM 512
+
/**
* enum hl_mmu_page_table_location - mmu page table location
* @MMU_DR_PGT: page-table is located on device DRAM.
@@ -154,6 +157,11 @@ enum hl_mmu_page_table_location {
#define hl_asic_dma_pool_free(hdev, vaddr, dma_addr) \
hl_asic_dma_pool_free_caller(hdev, vaddr, dma_addr, __func__)
+#define hl_dma_map_sgtable(hdev, sgt, dir) \
+ hl_dma_map_sgtable_caller(hdev, sgt, dir, __func__)
+#define hl_dma_unmap_sgtable(hdev, sgt, dir) \
+ hl_dma_unmap_sgtable_caller(hdev, sgt, dir, __func__)
+
/*
* Reset Flags
*
@@ -545,8 +553,7 @@ struct hl_hints_range {
* allocated with huge pages.
* @hints_dram_reserved_va_range: dram hint addresses reserved range.
* @hints_host_reserved_va_range: host hint addresses reserved range.
- * @hints_host_hpage_reserved_va_range: host huge page hint addresses reserved
- * range.
+ * @hints_host_hpage_reserved_va_range: host huge page hint addresses reserved range.
* @sram_base_address: SRAM physical start address.
* @sram_end_address: SRAM physical end address.
* @sram_user_base_address - SRAM physical start address for user access.
@@ -585,7 +592,7 @@ struct hl_hints_range {
* @mmu_pte_size: PTE size in MMU page tables.
* @mmu_hop_table_size: MMU hop table size.
* @mmu_hop0_tables_total_size: total size of MMU hop0 tables.
- * @dram_page_size: page size for MMU DRAM allocation.
+ * @dram_page_size: The DRAM physical page size.
* @cfg_size: configuration space size on SRAM.
* @sram_size: total size of SRAM.
* @max_asid: maximum number of open contexts (ASIDs).
@@ -641,6 +648,7 @@ struct hl_hints_range {
* @glbl_err_cause_num: global err cause number.
* @hbw_flush_reg: register to read to generate HBW flush. value of 0 means HBW flush is
* not supported.
+ * @reserved_fw_mem_size: size in MB of dram memory reserved for FW.
* @collective_first_sob: first sync object available for collective use
* @collective_first_mon: first monitor available for collective use
* @sync_stream_first_sob: first sync object available for sync stream use
@@ -686,9 +694,10 @@ struct hl_hints_range {
* @configurable_stop_on_err: is stop-on-error option configurable via debugfs.
* @set_max_power_on_device_init: true if need to set max power in F/W on device init.
* @supports_user_set_page_size: true if user can set the allocation page size.
- * @dma_mask: the dma mask to be set for this device
+ * @dma_mask: the dma mask to be set for this device.
* @supports_advanced_cpucp_rc: true if new cpucp opcodes are supported.
* @supports_engine_modes: true if changing engines/engine_cores modes is supported.
+ * @support_dynamic_resereved_fw_size: true if we support dynamic reserved size for fw.
*/
struct asic_fixed_properties {
struct hw_queue_properties *hw_queues_props;
@@ -772,6 +781,7 @@ struct asic_fixed_properties {
u32 num_of_special_blocks;
u32 glbl_err_cause_num;
u32 hbw_flush_reg;
+ u32 reserved_fw_mem_size;
u16 collective_first_sob;
u16 collective_first_mon;
u16 sync_stream_first_sob;
@@ -808,6 +818,7 @@ struct asic_fixed_properties {
u8 dma_mask;
u8 supports_advanced_cpucp_rc;
u8 supports_engine_modes;
+ u8 support_dynamic_resereved_fw_size;
};
/**
@@ -1098,19 +1109,41 @@ enum hl_user_interrupt_type {
};
/**
+ * struct hl_ts_free_jobs - holds user interrupt ts free nodes related data
+ * @free_nodes_pool: pool of nodes to be used for free timestamp jobs
+ * @free_nodes_length: number of nodes in free_nodes_pool
+ * @next_avail_free_node_idx: index of the next free node in the pool
+ *
+ * the free nodes pool must be protected by the user interrupt lock
+ * to avoid race between different interrupts which are using the same
+ * ts buffer with different offsets.
+ */
+struct hl_ts_free_jobs {
+ struct timestamp_reg_free_node *free_nodes_pool;
+ u32 free_nodes_length;
+ u32 next_avail_free_node_idx;
+};
+
+/**
* struct hl_user_interrupt - holds user interrupt information
* @hdev: pointer to the device structure
+ * @ts_free_jobs_data: timestamp free jobs related data
* @type: user interrupt type
* @wait_list_head: head to the list of user threads pending on this interrupt
+ * @ts_list_head: head to the list of timestamp records
* @wait_list_lock: protects wait_list_head
+ * @ts_list_lock: protects ts_list_head
* @timestamp: last timestamp taken upon interrupt
* @interrupt_id: msix interrupt id
*/
struct hl_user_interrupt {
struct hl_device *hdev;
+ struct hl_ts_free_jobs ts_free_jobs_data;
enum hl_user_interrupt_type type;
struct list_head wait_list_head;
+ struct list_head ts_list_head;
spinlock_t wait_list_lock;
+ spinlock_t ts_list_lock;
ktime_t timestamp;
u32 interrupt_id;
};
@@ -1120,11 +1153,15 @@ struct hl_user_interrupt {
* @free_objects_node: node in the list free_obj_jobs
* @cq_cb: pointer to cq command buffer to be freed
* @buf: pointer to timestamp buffer to be freed
+ * @in_use: indicates whether the node still in use in workqueue thread.
+ * @dynamic_alloc: indicates whether the node was allocated dynamically in the interrupt handler
*/
struct timestamp_reg_free_node {
struct list_head free_objects_node;
struct hl_cb *cq_cb;
struct hl_mmap_mem_buf *buf;
+ atomic_t in_use;
+ u8 dynamic_alloc;
};
/* struct timestamp_reg_work_obj - holds the timestamp registration free objects job
@@ -1133,17 +1170,21 @@ struct timestamp_reg_free_node {
* @free_obj: workqueue object to free timestamp registration node objects
* @hdev: pointer to the device structure
* @free_obj_head: list of free jobs nodes (node type timestamp_reg_free_node)
+ * @dynamic_alloc_free_obj_head: list of free jobs nodes which were dynamically allocated in the
+ * interrupt handler.
*/
struct timestamp_reg_work_obj {
struct work_struct free_obj;
struct hl_device *hdev;
struct list_head *free_obj_head;
+ struct list_head *dynamic_alloc_free_obj_head;
};
/* struct timestamp_reg_info - holds the timestamp registration related data.
* @buf: pointer to the timestamp buffer which include both user/kernel buffers.
* relevant only when doing timestamps records registration.
* @cq_cb: pointer to CQ counter CB.
+ * @interrupt: interrupt that the node hanged on it's wait list.
* @timestamp_kernel_addr: timestamp handle address, where to set timestamp
* relevant only when doing timestamps records
* registration.
@@ -1153,17 +1194,18 @@ struct timestamp_reg_work_obj {
* allocating records dynamically.
*/
struct timestamp_reg_info {
- struct hl_mmap_mem_buf *buf;
- struct hl_cb *cq_cb;
- u64 *timestamp_kernel_addr;
- u8 in_use;
+ struct hl_mmap_mem_buf *buf;
+ struct hl_cb *cq_cb;
+ struct hl_user_interrupt *interrupt;
+ u64 *timestamp_kernel_addr;
+ bool in_use;
};
/**
* struct hl_user_pending_interrupt - holds a context to a user thread
* pending on an interrupt
* @ts_reg_info: holds the timestamps registration nodes info
- * @wait_list_node: node in the list of user threads pending on an interrupt
+ * @list_node: node in the list of user threads pending on an interrupt or timestamp
* @fence: hl fence object for interrupt completion
* @cq_target_value: CQ target value
* @cq_kernel_addr: CQ kernel address, to be used in the cq interrupt
@@ -1171,7 +1213,7 @@ struct timestamp_reg_info {
*/
struct hl_user_pending_interrupt {
struct timestamp_reg_info ts_reg_info;
- struct list_head wait_list_node;
+ struct list_head list_node;
struct hl_fence fence;
u64 cq_target_value;
u64 *cq_kernel_addr;
@@ -1370,6 +1412,8 @@ struct dynamic_fw_load_mgr {
* @boot_err0_reg: boot_err0 register address
* @boot_err1_reg: boot_err1 register address
* @wait_for_preboot_timeout: timeout to poll for preboot ready
+ * @wait_for_preboot_extended_timeout: timeout to pull for preboot ready in case where we know
+ * preboot needs longer time.
*/
struct pre_fw_load_props {
u32 cpu_boot_status_reg;
@@ -1378,6 +1422,7 @@ struct pre_fw_load_props {
u32 boot_err0_reg;
u32 boot_err1_reg;
u32 wait_for_preboot_timeout;
+ u32 wait_for_preboot_extended_timeout;
};
/**
@@ -1477,11 +1522,9 @@ struct engines_data {
* @asic_dma_pool_free: free small DMA allocation from pool.
* @cpu_accessible_dma_pool_alloc: allocate CPU PQ packet from DMA pool.
* @cpu_accessible_dma_pool_free: free CPU PQ packet from DMA pool.
- * @asic_dma_unmap_single: unmap a single DMA buffer
- * @asic_dma_map_single: map a single buffer to a DMA
- * @hl_dma_unmap_sgtable: DMA unmap scatter-gather table.
+ * @dma_unmap_sgtable: DMA unmap scatter-gather table.
+ * @dma_map_sgtable: DMA map scatter-gather table.
* @cs_parser: parse Command Submission.
- * @asic_dma_map_sgtable: DMA map scatter-gather table.
* @add_end_of_cb_packets: Add packets to the end of CB, if device requires it.
* @update_eq_ci: update event queue CI.
* @context_switch: called upon ASID context switch.
@@ -1602,18 +1645,11 @@ struct hl_asic_funcs {
size_t size, dma_addr_t *dma_handle);
void (*cpu_accessible_dma_pool_free)(struct hl_device *hdev,
size_t size, void *vaddr);
- void (*asic_dma_unmap_single)(struct hl_device *hdev,
- dma_addr_t dma_addr, int len,
- enum dma_data_direction dir);
- dma_addr_t (*asic_dma_map_single)(struct hl_device *hdev,
- void *addr, int len,
+ void (*dma_unmap_sgtable)(struct hl_device *hdev, struct sg_table *sgt,
enum dma_data_direction dir);
- void (*hl_dma_unmap_sgtable)(struct hl_device *hdev,
- struct sg_table *sgt,
+ int (*dma_map_sgtable)(struct hl_device *hdev, struct sg_table *sgt,
enum dma_data_direction dir);
int (*cs_parser)(struct hl_device *hdev, struct hl_cs_parser *parser);
- int (*asic_dma_map_sgtable)(struct hl_device *hdev, struct sg_table *sgt,
- enum dma_data_direction dir);
void (*add_end_of_cb_packets)(struct hl_device *hdev,
void *kernel_address, u32 len,
u32 original_len,
@@ -1771,16 +1807,19 @@ struct hl_cs_counters_atomic {
* @phys_pg_pack: pointer to physical page pack if the dma-buf was exported
* where virtual memory is supported.
* @memhash_hnode: pointer to the memhash node. this object holds the export count.
- * @device_address: physical address of the device's memory. Relevant only
- * if phys_pg_pack is NULL (dma-buf was exported from address).
- * The total size can be taken from the dmabuf object.
+ * @offset: the offset into the buffer from which the memory is exported.
+ * Relevant only if virtual memory is supported and phys_pg_pack is being used.
+ * device_phys_addr: physical address of the device's memory. Relevant only
+ * if phys_pg_pack is NULL (dma-buf was exported from address).
+ * The total size can be taken from the dmabuf object.
*/
struct hl_dmabuf_priv {
struct dma_buf *dmabuf;
struct hl_ctx *ctx;
struct hl_vm_phys_pg_pack *phys_pg_pack;
struct hl_vm_hash_node *memhash_hnode;
- uint64_t device_address;
+ u64 offset;
+ u64 device_phys_addr;
};
#define HL_CS_OUTCOME_HISTORY_LEN 256
@@ -1835,6 +1874,7 @@ struct hl_cs_outcome_store {
* @va_range: holds available virtual addresses for host and dram mappings.
* @mem_hash_lock: protects the mem_hash.
* @hw_block_list_lock: protects the HW block memory list.
+ * @ts_reg_lock: timestamp registration ioctls lock.
* @debugfs_list: node in debugfs list of contexts.
* @hw_block_mem_list: list of HW block virtual mapped addresses.
* @cs_counters: context command submission counters.
@@ -1871,6 +1911,7 @@ struct hl_ctx {
struct hl_va_range *va_range[HL_VA_RANGE_TYPE_MAX];
struct mutex mem_hash_lock;
struct mutex hw_block_list_lock;
+ struct mutex ts_reg_lock;
struct list_head debugfs_list;
struct list_head hw_block_mem_list;
struct hl_cs_counters_atomic cs_counters;
@@ -1917,17 +1958,17 @@ struct hl_ctx_mgr {
* @dma_mapped: true if the SG was mapped to DMA addresses, false otherwise.
*/
struct hl_userptr {
- enum vm_type vm_type; /* must be first */
- struct list_head job_node;
- struct page **pages;
- unsigned int npages;
- struct sg_table *sgt;
- enum dma_data_direction dir;
- struct list_head debugfs_list;
- pid_t pid;
- u64 addr;
- u64 size;
- u8 dma_mapped;
+ enum vm_type vm_type; /* must be first */
+ struct list_head job_node;
+ struct page **pages;
+ unsigned int npages;
+ struct sg_table *sgt;
+ enum dma_data_direction dir;
+ struct list_head debugfs_list;
+ pid_t pid;
+ u64 addr;
+ u64 size;
+ u8 dma_mapped;
};
/**
@@ -2148,7 +2189,6 @@ struct hl_vm_hw_block_list_node {
* @pages: the physical page array.
* @npages: num physical pages in the pack.
* @total_size: total size of all the pages in this list.
- * @exported_size: buffer exported size.
* @node: used to attach to deletion list that is used when all the allocations are cleared
* at the teardown of the context.
* @mapping_cnt: number of shared mappings.
@@ -2165,7 +2205,6 @@ struct hl_vm_phys_pg_pack {
u64 *pages;
u64 npages;
u64 total_size;
- u64 exported_size;
struct list_head node;
atomic_t mapping_cnt;
u32 asid;
@@ -2250,7 +2289,7 @@ struct hl_notifier_event {
/**
* struct hl_fpriv - process information stored in FD private data.
* @hdev: habanalabs device structure.
- * @filp: pointer to the given file structure.
+ * @file_priv: pointer to the DRM file private data structure.
* @taskpid: current process ID.
* @ctx: current executing context. TODO: remove for multiple ctx per process
* @ctx_mgr: context manager to handle multiple context for this FD.
@@ -2265,7 +2304,7 @@ struct hl_notifier_event {
*/
struct hl_fpriv {
struct hl_device *hdev;
- struct file *filp;
+ struct drm_file *file_priv;
struct pid *taskpid;
struct hl_ctx *ctx;
struct hl_ctx_mgr ctx_mgr;
@@ -2706,6 +2745,8 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
usr_intr.type = intr_type; \
INIT_LIST_HEAD(&usr_intr.wait_list_head); \
spin_lock_init(&usr_intr.wait_list_lock); \
+ INIT_LIST_HEAD(&usr_intr.ts_list_head); \
+ spin_lock_init(&usr_intr.ts_list_lock); \
})
struct hwmon_chip_info;
@@ -3055,6 +3096,20 @@ struct fw_err_info {
};
/**
+ * struct engine_err_info - engine error information.
+ * @event: holds information on the event.
+ * @event_detected: if set as 1, then an engine event was discovered for the
+ * first time after the driver has finished booting-up.
+ * @event_info_available: indicates that an engine event info is now available.
+ */
+struct engine_err_info {
+ struct hl_info_engine_err_event event;
+ atomic_t event_detected;
+ bool event_info_available;
+};
+
+
+/**
* struct hl_error_info - holds information collected during an error.
* @cs_timeout: CS timeout error information.
* @razwi_info: RAZWI information.
@@ -3062,6 +3117,7 @@ struct fw_err_info {
* @page_fault_info: page fault information.
* @hw_err: (fatal) hardware error information.
* @fw_err: firmware error information.
+ * @engine_err: engine error information.
*/
struct hl_error_info {
struct cs_timeout_info cs_timeout;
@@ -3070,6 +3126,7 @@ struct hl_error_info {
struct page_fault_info page_fault_info;
struct hw_err_info hw_err;
struct fw_err_info fw_err;
+ struct engine_err_info engine_err;
};
/**
@@ -3117,8 +3174,7 @@ struct hl_reset_info {
* (required only for PCI address match mode)
* @pcie_bar: array of available PCIe bars virtual addresses.
* @rmmio: configuration area address on SRAM.
- * @hclass: pointer to the habanalabs class.
- * @cdev: related char device.
+ * @drm: related DRM device.
* @cdev_ctrl: char device for control operations only (INFO IOCTL)
* @dev: related kernel basic device structure.
* @dev_ctrl: related kernel device structure for the control device
@@ -3245,8 +3301,7 @@ struct hl_reset_info {
* @rotator_binning: contains mask of rotators engines that is received from the f/w
* which indicates which rotator engines are binned-out(Gaudi3 and above).
* @id: device minor.
- * @id_control: minor of the control device.
- * @cdev_idx: char device index. Used for setting its name.
+ * @cdev_idx: char device index.
* @cpu_pci_msb_addr: 50-bit extension bits for the device CPU's 40-bit
* addresses.
* @is_in_dram_scrub: true if dram scrub operation is on going.
@@ -3289,6 +3344,7 @@ struct hl_reset_info {
* device.
* @supports_ctx_switch: true if a ctx switch is required upon first submission.
* @support_preboot_binning: true if we support read binning info from preboot.
+ * @eq_heartbeat_received: indication that eq heartbeat event has received from FW.
* @nic_ports_mask: Controls which NIC ports are enabled. Used only for testing.
* @fw_components: Controls which f/w components to load to the device. There are multiple f/w
* stages and sometimes we want to stop at a certain stage. Used only for testing.
@@ -3308,8 +3364,7 @@ struct hl_device {
u64 pcie_bar_phys[HL_PCI_NUM_BARS];
void __iomem *pcie_bar[HL_PCI_NUM_BARS];
void __iomem *rmmio;
- struct class *hclass;
- struct cdev cdev;
+ struct drm_device drm;
struct cdev cdev_ctrl;
struct device *dev;
struct device *dev_ctrl;
@@ -3418,7 +3473,6 @@ struct hl_device {
u32 device_release_watchdog_timeout_sec;
u32 rotator_binning;
u16 id;
- u16 id_control;
u16 cdev_idx;
u16 cpu_pci_msb_addr;
u8 is_in_dram_scrub;
@@ -3451,6 +3505,7 @@ struct hl_device {
u8 reset_upon_device_release;
u8 supports_ctx_switch;
u8 support_preboot_binning;
+ u8 eq_heartbeat_received;
/* Parameters for bring-up to be upstreamed */
u64 nic_ports_mask;
@@ -3582,6 +3637,11 @@ static inline bool hl_mem_area_inside_range(u64 address, u64 size,
return false;
}
+static inline struct hl_device *to_hl_device(struct drm_device *ddev)
+{
+ return container_of(ddev, struct hl_device, drm);
+}
+
/**
* hl_mem_area_crosses_range() - Checks whether address+size crossing a range.
* @address: The start address of the area we want to validate.
@@ -3611,8 +3671,13 @@ void *hl_asic_dma_pool_zalloc_caller(struct hl_device *hdev, size_t size, gfp_t
dma_addr_t *dma_handle, const char *caller);
void hl_asic_dma_pool_free_caller(struct hl_device *hdev, void *vaddr, dma_addr_t dma_addr,
const char *caller);
-int hl_dma_map_sgtable(struct hl_device *hdev, struct sg_table *sgt, enum dma_data_direction dir);
-void hl_dma_unmap_sgtable(struct hl_device *hdev, struct sg_table *sgt,
+int hl_dma_map_sgtable_caller(struct hl_device *hdev, struct sg_table *sgt,
+ enum dma_data_direction dir, const char *caller);
+void hl_dma_unmap_sgtable_caller(struct hl_device *hdev, struct sg_table *sgt,
+ enum dma_data_direction dir, const char *caller);
+int hl_asic_dma_map_sgtable(struct hl_device *hdev, struct sg_table *sgt,
+ enum dma_data_direction dir);
+void hl_asic_dma_unmap_sgtable(struct hl_device *hdev, struct sg_table *sgt,
enum dma_data_direction dir);
int hl_access_sram_dram_region(struct hl_device *hdev, u64 addr, u64 *val,
enum debugfs_access_type acc_type, enum pci_region region_type, bool set_dram_bar);
@@ -3620,7 +3685,12 @@ int hl_access_cfg_region(struct hl_device *hdev, u64 addr, u64 *val,
enum debugfs_access_type acc_type);
int hl_access_dev_mem(struct hl_device *hdev, enum pci_region region_type,
u64 addr, u64 *val, enum debugfs_access_type acc_type);
-int hl_device_open(struct inode *inode, struct file *filp);
+
+int hl_mmap(struct file *filp, struct vm_area_struct *vma);
+
+int hl_device_open(struct drm_device *drm, struct drm_file *file_priv);
+void hl_device_release(struct drm_device *ddev, struct drm_file *file_priv);
+
int hl_device_open_ctrl(struct inode *inode, struct file *filp);
bool hl_device_operational(struct hl_device *hdev,
enum hl_device_status *status);
@@ -3652,8 +3722,9 @@ void hl_eq_reset(struct hl_device *hdev, struct hl_eq *q);
irqreturn_t hl_irq_handler_cq(int irq, void *arg);
irqreturn_t hl_irq_handler_eq(int irq, void *arg);
irqreturn_t hl_irq_handler_dec_abnrm(int irq, void *arg);
-irqreturn_t hl_irq_handler_user_interrupt(int irq, void *arg);
+irqreturn_t hl_irq_user_interrupt_handler(int irq, void *arg);
irqreturn_t hl_irq_user_interrupt_thread_handler(int irq, void *arg);
+irqreturn_t hl_irq_eq_error_interrupt_thread_handler(int irq, void *arg);
u32 hl_cq_inc_ptr(u32 ptr);
int hl_asid_init(struct hl_device *hdev);
@@ -3944,16 +4015,14 @@ void hl_handle_page_fault(struct hl_device *hdev, u64 addr, u16 eng_id, bool is_
u64 *event_mask);
void hl_handle_critical_hw_err(struct hl_device *hdev, u16 event_id, u64 *event_mask);
void hl_handle_fw_err(struct hl_device *hdev, struct hl_info_fw_err_info *info);
+void hl_capture_engine_err(struct hl_device *hdev, u16 engine_id, u16 error_count);
void hl_enable_err_info_capture(struct hl_error_info *captured_err_info);
#ifdef CONFIG_DEBUG_FS
-void hl_debugfs_init(void);
-void hl_debugfs_fini(void);
int hl_debugfs_device_init(struct hl_device *hdev);
void hl_debugfs_device_fini(struct hl_device *hdev);
void hl_debugfs_add_device(struct hl_device *hdev);
-void hl_debugfs_remove_device(struct hl_device *hdev);
void hl_debugfs_add_file(struct hl_fpriv *hpriv);
void hl_debugfs_remove_file(struct hl_fpriv *hpriv);
void hl_debugfs_add_cb(struct hl_cb *cb);
@@ -3972,14 +4041,6 @@ void hl_debugfs_set_state_dump(struct hl_device *hdev, char *data,
#else
-static inline void __init hl_debugfs_init(void)
-{
-}
-
-static inline void hl_debugfs_fini(void)
-{
-}
-
static inline int hl_debugfs_device_init(struct hl_device *hdev)
{
return 0;
@@ -3993,10 +4054,6 @@ static inline void hl_debugfs_add_device(struct hl_device *hdev)
{
}
-static inline void hl_debugfs_remove_device(struct hl_device *hdev)
-{
-}
-
static inline void hl_debugfs_add_file(struct hl_fpriv *hpriv)
{
}
@@ -4108,11 +4165,12 @@ void hl_ack_pb_single_dcore(struct hl_device *hdev, u32 dcore_offset,
const u32 pb_blocks[], u32 blocks_array_size);
/* IOCTLs */
-long hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
long hl_ioctl_control(struct file *filep, unsigned int cmd, unsigned long arg);
-int hl_cb_ioctl(struct hl_fpriv *hpriv, void *data);
-int hl_cs_ioctl(struct hl_fpriv *hpriv, void *data);
-int hl_wait_ioctl(struct hl_fpriv *hpriv, void *data);
-int hl_mem_ioctl(struct hl_fpriv *hpriv, void *data);
+int hl_info_ioctl(struct drm_device *ddev, void *data, struct drm_file *file_priv);
+int hl_cb_ioctl(struct drm_device *ddev, void *data, struct drm_file *file_priv);
+int hl_cs_ioctl(struct drm_device *ddev, void *data, struct drm_file *file_priv);
+int hl_wait_ioctl(struct drm_device *ddev, void *data, struct drm_file *file_priv);
+int hl_mem_ioctl(struct drm_device *ddev, void *data, struct drm_file *file_priv);
+int hl_debug_ioctl(struct drm_device *ddev, void *data, struct drm_file *file_priv);
#endif /* HABANALABSP_H_ */
diff --git a/drivers/accel/habanalabs/common/habanalabs_drv.c b/drivers/accel/habanalabs/common/habanalabs_drv.c
index 7263e84c1a4d..306a5bc9bf89 100644
--- a/drivers/accel/habanalabs/common/habanalabs_drv.c
+++ b/drivers/accel/habanalabs/common/habanalabs_drv.c
@@ -14,6 +14,11 @@
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
+#include <linux/version.h>
+
+#include <drm/drm_accel.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_ioctl.h>
#define CREATE_TRACE_POINTS
#include <trace/events/habanalabs.h>
@@ -27,7 +32,6 @@ MODULE_DESCRIPTION(HL_DRIVER_DESC);
MODULE_LICENSE("GPL v2");
static int hl_major;
-static struct class *hl_class;
static DEFINE_IDR(hl_devs_idr);
static DEFINE_MUTEX(hl_devs_idr_lock);
@@ -70,6 +74,42 @@ static const struct pci_device_id ids[] = {
};
MODULE_DEVICE_TABLE(pci, ids);
+static const struct drm_ioctl_desc hl_drm_ioctls[] = {
+ DRM_IOCTL_DEF_DRV(HL_INFO, hl_info_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(HL_CB, hl_cb_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(HL_CS, hl_cs_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(HL_WAIT_CS, hl_wait_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(HL_MEMORY, hl_mem_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(HL_DEBUG, hl_debug_ioctl, 0),
+};
+
+static const struct file_operations hl_fops = {
+ .owner = THIS_MODULE,
+ .open = accel_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+ .compat_ioctl = drm_compat_ioctl,
+ .llseek = noop_llseek,
+ .mmap = hl_mmap
+};
+
+static const struct drm_driver hl_driver = {
+ .driver_features = DRIVER_COMPUTE_ACCEL,
+
+ .name = HL_NAME,
+ .desc = HL_DRIVER_DESC,
+ .major = LINUX_VERSION_MAJOR,
+ .minor = LINUX_VERSION_PATCHLEVEL,
+ .patchlevel = LINUX_VERSION_SUBLEVEL,
+ .date = "20190505",
+
+ .fops = &hl_fops,
+ .open = hl_device_open,
+ .postclose = hl_device_release,
+ .ioctls = hl_drm_ioctls,
+ .num_ioctls = ARRAY_SIZE(hl_drm_ioctls)
+};
+
/*
* get_asic_type - translate device id to asic type
*
@@ -123,43 +163,28 @@ static bool is_asic_secured(enum hl_asic_type asic_type)
}
/*
- * hl_device_open - open function for habanalabs device
- *
- * @inode: pointer to inode structure
- * @filp: pointer to file structure
+ * hl_device_open() - open function for habanalabs device.
+ * @ddev: pointer to DRM device structure.
+ * @file: pointer to DRM file private data structure.
*
* Called when process opens an habanalabs device.
*/
-int hl_device_open(struct inode *inode, struct file *filp)
+int hl_device_open(struct drm_device *ddev, struct drm_file *file_priv)
{
+ struct hl_device *hdev = to_hl_device(ddev);
enum hl_device_status status;
- struct hl_device *hdev;
struct hl_fpriv *hpriv;
int rc;
- mutex_lock(&hl_devs_idr_lock);
- hdev = idr_find(&hl_devs_idr, iminor(inode));
- mutex_unlock(&hl_devs_idr_lock);
-
- if (!hdev) {
- pr_err("Couldn't find device %d:%d\n",
- imajor(inode), iminor(inode));
- return -ENXIO;
- }
-
hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
if (!hpriv)
return -ENOMEM;
hpriv->hdev = hdev;
- filp->private_data = hpriv;
- hpriv->filp = filp;
-
mutex_init(&hpriv->notifier_event.lock);
mutex_init(&hpriv->restore_phase_mutex);
mutex_init(&hpriv->ctx_lock);
kref_init(&hpriv->refcount);
- nonseekable_open(inode, filp);
hl_ctx_mgr_init(&hpriv->ctx_mgr);
hl_mem_mgr_init(hpriv->hdev->dev, &hpriv->mem_mgr);
@@ -225,6 +250,9 @@ int hl_device_open(struct inode *inode, struct file *filp)
hdev->last_successful_open_jif = jiffies;
hdev->last_successful_open_ktime = ktime_get();
+ file_priv->driver_priv = hpriv;
+ hpriv->file_priv = file_priv;
+
return 0;
out_err:
@@ -232,7 +260,6 @@ out_err:
hl_mem_mgr_fini(&hpriv->mem_mgr);
hl_mem_mgr_idr_destroy(&hpriv->mem_mgr);
hl_ctx_mgr_fini(hpriv->hdev, &hpriv->ctx_mgr);
- filp->private_data = NULL;
mutex_destroy(&hpriv->ctx_lock);
mutex_destroy(&hpriv->restore_phase_mutex);
mutex_destroy(&hpriv->notifier_event.lock);
@@ -268,9 +295,7 @@ int hl_device_open_ctrl(struct inode *inode, struct file *filp)
*/
hpriv->hdev = hdev;
filp->private_data = hpriv;
- hpriv->filp = filp;
- mutex_init(&hpriv->notifier_event.lock);
nonseekable_open(inode, filp);
hpriv->taskpid = get_task_pid(current, PIDTYPE_PID);
@@ -317,7 +342,6 @@ static void copy_kernel_module_params_to_device(struct hl_device *hdev)
hdev->asic_prop.fw_security_enabled = is_asic_secured(hdev->asic_type);
hdev->major = hl_major;
- hdev->hclass = hl_class;
hdev->memory_scrub = memory_scrub;
hdev->reset_on_lockup = reset_on_lockup;
hdev->boot_error_status_mask = boot_error_status_mask;
@@ -383,6 +407,31 @@ static int fixup_device_params(struct hl_device *hdev)
return 0;
}
+static int allocate_device_id(struct hl_device *hdev)
+{
+ int id;
+
+ mutex_lock(&hl_devs_idr_lock);
+ id = idr_alloc(&hl_devs_idr, hdev, 0, HL_MAX_MINORS, GFP_KERNEL);
+ mutex_unlock(&hl_devs_idr_lock);
+
+ if (id < 0) {
+ if (id == -ENOSPC)
+ pr_err("too many devices in the system\n");
+ return -EBUSY;
+ }
+
+ hdev->id = id;
+
+ /*
+ * Firstly initialized with the internal device ID.
+ * Will be updated later after the DRM device registration to hold the minor ID.
+ */
+ hdev->cdev_idx = hdev->id;
+
+ return 0;
+}
+
/**
* create_hdev - create habanalabs device instance
*
@@ -395,27 +444,29 @@ static int fixup_device_params(struct hl_device *hdev)
*/
static int create_hdev(struct hl_device **dev, struct pci_dev *pdev)
{
- int main_id, ctrl_id = 0, rc = 0;
struct hl_device *hdev;
+ int rc;
*dev = NULL;
- hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
- if (!hdev)
- return -ENOMEM;
+ hdev = devm_drm_dev_alloc(&pdev->dev, &hl_driver, struct hl_device, drm);
+ if (IS_ERR(hdev))
+ return PTR_ERR(hdev);
+
+ hdev->dev = hdev->drm.dev;
/* Will be NULL in case of simulator device */
hdev->pdev = pdev;
/* Assign status description string */
- strncpy(hdev->status[HL_DEVICE_STATUS_OPERATIONAL], "operational", HL_STR_MAX);
- strncpy(hdev->status[HL_DEVICE_STATUS_IN_RESET], "in reset", HL_STR_MAX);
- strncpy(hdev->status[HL_DEVICE_STATUS_MALFUNCTION], "disabled", HL_STR_MAX);
- strncpy(hdev->status[HL_DEVICE_STATUS_NEEDS_RESET], "needs reset", HL_STR_MAX);
- strncpy(hdev->status[HL_DEVICE_STATUS_IN_DEVICE_CREATION],
- "in device creation", HL_STR_MAX);
- strncpy(hdev->status[HL_DEVICE_STATUS_IN_RESET_AFTER_DEVICE_RELEASE],
- "in reset after device release", HL_STR_MAX);
+ strscpy(hdev->status[HL_DEVICE_STATUS_OPERATIONAL], "operational", HL_STR_MAX);
+ strscpy(hdev->status[HL_DEVICE_STATUS_IN_RESET], "in reset", HL_STR_MAX);
+ strscpy(hdev->status[HL_DEVICE_STATUS_MALFUNCTION], "disabled", HL_STR_MAX);
+ strscpy(hdev->status[HL_DEVICE_STATUS_NEEDS_RESET], "needs reset", HL_STR_MAX);
+ strscpy(hdev->status[HL_DEVICE_STATUS_IN_DEVICE_CREATION],
+ "in device creation", HL_STR_MAX);
+ strscpy(hdev->status[HL_DEVICE_STATUS_IN_RESET_AFTER_DEVICE_RELEASE],
+ "in reset after device release", HL_STR_MAX);
/* First, we must find out which ASIC are we handling. This is needed
@@ -425,7 +476,7 @@ static int create_hdev(struct hl_device **dev, struct pci_dev *pdev)
if (hdev->asic_type == ASIC_INVALID) {
dev_err(&pdev->dev, "Unsupported ASIC\n");
rc = -ENODEV;
- goto free_hdev;
+ goto out_err;
}
copy_kernel_module_params_to_device(hdev);
@@ -434,42 +485,15 @@ static int create_hdev(struct hl_device **dev, struct pci_dev *pdev)
fixup_device_params(hdev);
- mutex_lock(&hl_devs_idr_lock);
-
- /* Always save 2 numbers, 1 for main device and 1 for control.
- * They must be consecutive
- */
- main_id = idr_alloc(&hl_devs_idr, hdev, 0, HL_MAX_MINORS, GFP_KERNEL);
-
- if (main_id >= 0)
- ctrl_id = idr_alloc(&hl_devs_idr, hdev, main_id + 1,
- main_id + 2, GFP_KERNEL);
-
- mutex_unlock(&hl_devs_idr_lock);
-
- if ((main_id < 0) || (ctrl_id < 0)) {
- if ((main_id == -ENOSPC) || (ctrl_id == -ENOSPC))
- pr_err("too many devices in the system\n");
-
- if (main_id >= 0) {
- mutex_lock(&hl_devs_idr_lock);
- idr_remove(&hl_devs_idr, main_id);
- mutex_unlock(&hl_devs_idr_lock);
- }
-
- rc = -EBUSY;
- goto free_hdev;
- }
-
- hdev->id = main_id;
- hdev->id_control = ctrl_id;
+ rc = allocate_device_id(hdev);
+ if (rc)
+ goto out_err;
*dev = hdev;
return 0;
-free_hdev:
- kfree(hdev);
+out_err:
return rc;
}
@@ -484,10 +508,8 @@ static void destroy_hdev(struct hl_device *hdev)
/* Remove device from the device list */
mutex_lock(&hl_devs_idr_lock);
idr_remove(&hl_devs_idr, hdev->id);
- idr_remove(&hl_devs_idr, hdev->id_control);
mutex_unlock(&hl_devs_idr_lock);
- kfree(hdev);
}
static int hl_pmops_suspend(struct device *dev)
@@ -691,28 +713,16 @@ static int __init hl_init(void)
hl_major = MAJOR(dev);
- hl_class = class_create(HL_NAME);
- if (IS_ERR(hl_class)) {
- pr_err("failed to allocate class\n");
- rc = PTR_ERR(hl_class);
- goto remove_major;
- }
-
- hl_debugfs_init();
-
rc = pci_register_driver(&hl_pci_driver);
if (rc) {
pr_err("failed to register pci device\n");
- goto remove_debugfs;
+ goto remove_major;
}
pr_debug("driver loaded\n");
return 0;
-remove_debugfs:
- hl_debugfs_fini();
- class_destroy(hl_class);
remove_major:
unregister_chrdev_region(MKDEV(hl_major, 0), HL_MAX_MINORS);
return rc;
@@ -725,14 +735,6 @@ static void __exit hl_exit(void)
{
pci_unregister_driver(&hl_pci_driver);
- /*
- * Removing debugfs must be after all devices or simulator devices
- * have been removed because otherwise we get a bug in the
- * debugfs module for referencing NULL objects
- */
- hl_debugfs_fini();
-
- class_destroy(hl_class);
unregister_chrdev_region(MKDEV(hl_major, 0), HL_MAX_MINORS);
idr_destroy(&hl_devs_idr);
diff --git a/drivers/accel/habanalabs/common/habanalabs_ioctl.c b/drivers/accel/habanalabs/common/habanalabs_ioctl.c
index 6a45a92344e9..8ef36effb95b 100644
--- a/drivers/accel/habanalabs/common/habanalabs_ioctl.c
+++ b/drivers/accel/habanalabs/common/habanalabs_ioctl.c
@@ -17,6 +17,8 @@
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
+#include <asm/msr.h>
+
static u32 hl_debug_struct_size[HL_DEBUG_OP_TIMESTAMP + 1] = {
[HL_DEBUG_OP_ETR] = sizeof(struct hl_debug_params_etr),
[HL_DEBUG_OP_ETF] = sizeof(struct hl_debug_params_etf),
@@ -320,6 +322,7 @@ static int time_sync_info(struct hl_device *hdev, struct hl_info_args *args)
time_sync.device_time = hdev->asic_funcs->get_device_time(hdev);
time_sync.host_time = ktime_get_raw_ns();
+ time_sync.tsc_time = rdtsc();
return copy_to_user(out, &time_sync,
min((size_t) max_size, sizeof(time_sync))) ? -EFAULT : 0;
@@ -875,6 +878,28 @@ static int fw_err_info(struct hl_fpriv *hpriv, struct hl_info_args *args)
return rc ? -EFAULT : 0;
}
+static int engine_err_info(struct hl_fpriv *hpriv, struct hl_info_args *args)
+{
+ void __user *user_buf = (void __user *) (uintptr_t) args->return_pointer;
+ struct hl_device *hdev = hpriv->hdev;
+ u32 user_buf_size = args->return_size;
+ struct engine_err_info *info;
+ int rc;
+
+ if (!user_buf)
+ return -EINVAL;
+
+ info = &hdev->captured_err_info.engine_err;
+ if (!info->event_info_available)
+ return 0;
+
+ if (user_buf_size < sizeof(struct hl_info_engine_err_event))
+ return -ENOMEM;
+
+ rc = copy_to_user(user_buf, &info->event, sizeof(struct hl_info_engine_err_event));
+ return rc ? -EFAULT : 0;
+}
+
static int send_fw_generic_request(struct hl_device *hdev, struct hl_info_args *info_args)
{
void __user *buff = (void __user *) (uintptr_t) info_args->return_pointer;
@@ -1001,6 +1026,9 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data,
case HL_INFO_FW_ERR_EVENT:
return fw_err_info(hpriv, args);
+ case HL_INFO_USER_ENGINE_ERR_EVENT:
+ return engine_err_info(hpriv, args);
+
case HL_INFO_DRAM_USAGE:
return dram_usage_info(hpriv, args);
default:
@@ -1070,20 +1098,34 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data,
return rc;
}
-static int hl_info_ioctl(struct hl_fpriv *hpriv, void *data)
+int hl_info_ioctl(struct drm_device *ddev, void *data, struct drm_file *file_priv)
{
+ struct hl_fpriv *hpriv = file_priv->driver_priv;
+
return _hl_info_ioctl(hpriv, data, hpriv->hdev->dev);
}
static int hl_info_ioctl_control(struct hl_fpriv *hpriv, void *data)
{
+ struct hl_info_args *args = data;
+
+ switch (args->op) {
+ case HL_INFO_GET_EVENTS:
+ case HL_INFO_UNREGISTER_EVENTFD:
+ case HL_INFO_REGISTER_EVENTFD:
+ return -EOPNOTSUPP;
+ default:
+ break;
+ }
+
return _hl_info_ioctl(hpriv, data, hpriv->hdev->dev_ctrl);
}
-static int hl_debug_ioctl(struct hl_fpriv *hpriv, void *data)
+int hl_debug_ioctl(struct drm_device *ddev, void *data, struct drm_file *file_priv)
{
- struct hl_debug_args *args = data;
+ struct hl_fpriv *hpriv = file_priv->driver_priv;
struct hl_device *hdev = hpriv->hdev;
+ struct hl_debug_args *args = data;
enum hl_device_status status;
int rc = 0;
@@ -1126,25 +1168,15 @@ static int hl_debug_ioctl(struct hl_fpriv *hpriv, void *data)
}
#define HL_IOCTL_DEF(ioctl, _func) \
- [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func}
-
-static const struct hl_ioctl_desc hl_ioctls[] = {
- HL_IOCTL_DEF(HL_IOCTL_INFO, hl_info_ioctl),
- HL_IOCTL_DEF(HL_IOCTL_CB, hl_cb_ioctl),
- HL_IOCTL_DEF(HL_IOCTL_CS, hl_cs_ioctl),
- HL_IOCTL_DEF(HL_IOCTL_WAIT_CS, hl_wait_ioctl),
- HL_IOCTL_DEF(HL_IOCTL_MEMORY, hl_mem_ioctl),
- HL_IOCTL_DEF(HL_IOCTL_DEBUG, hl_debug_ioctl)
-};
+ [_IOC_NR(ioctl) - HL_COMMAND_START] = {.cmd = ioctl, .func = _func}
static const struct hl_ioctl_desc hl_ioctls_control[] = {
- HL_IOCTL_DEF(HL_IOCTL_INFO, hl_info_ioctl_control)
+ HL_IOCTL_DEF(DRM_IOCTL_HL_INFO, hl_info_ioctl_control)
};
-static long _hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg,
- const struct hl_ioctl_desc *ioctl, struct device *dev)
+static long _hl_ioctl(struct hl_fpriv *hpriv, unsigned int cmd, unsigned long arg,
+ const struct hl_ioctl_desc *ioctl, struct device *dev)
{
- struct hl_fpriv *hpriv = filep->private_data;
unsigned int nr = _IOC_NR(cmd);
char stack_kdata[128] = {0};
char *kdata = NULL;
@@ -1194,9 +1226,13 @@ static long _hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg,
retcode = -EFAULT;
out_err:
- if (retcode)
- dev_dbg_ratelimited(dev, "error in ioctl: pid=%d, cmd=0x%02x, nr=0x%02x\n",
- task_pid_nr(current), cmd, nr);
+ if (retcode) {
+ char task_comm[TASK_COMM_LEN];
+
+ dev_dbg_ratelimited(dev,
+ "error in ioctl: pid=%d, comm=\"%s\", cmd=%#010x, nr=%#04x\n",
+ task_pid_nr(current), get_task_comm(task_comm, current), cmd, nr);
+ }
if (kdata != stack_kdata)
kfree(kdata);
@@ -1204,29 +1240,6 @@ out_err:
return retcode;
}
-long hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
-{
- struct hl_fpriv *hpriv = filep->private_data;
- struct hl_device *hdev = hpriv->hdev;
- const struct hl_ioctl_desc *ioctl = NULL;
- unsigned int nr = _IOC_NR(cmd);
-
- if (!hdev) {
- pr_err_ratelimited("Sending ioctl after device was removed! Please close FD\n");
- return -ENODEV;
- }
-
- if ((nr >= HL_COMMAND_START) && (nr < HL_COMMAND_END)) {
- ioctl = &hl_ioctls[nr];
- } else {
- dev_dbg_ratelimited(hdev->dev, "invalid ioctl: pid=%d, nr=0x%02x\n",
- task_pid_nr(current), nr);
- return -ENOTTY;
- }
-
- return _hl_ioctl(filep, cmd, arg, ioctl, hdev->dev);
-}
-
long hl_ioctl_control(struct file *filep, unsigned int cmd, unsigned long arg)
{
struct hl_fpriv *hpriv = filep->private_data;
@@ -1239,13 +1252,16 @@ long hl_ioctl_control(struct file *filep, unsigned int cmd, unsigned long arg)
return -ENODEV;
}
- if (nr == _IOC_NR(HL_IOCTL_INFO)) {
- ioctl = &hl_ioctls_control[nr];
+ if (nr == _IOC_NR(DRM_IOCTL_HL_INFO)) {
+ ioctl = &hl_ioctls_control[nr - HL_COMMAND_START];
} else {
- dev_dbg_ratelimited(hdev->dev_ctrl, "invalid ioctl: pid=%d, nr=0x%02x\n",
- task_pid_nr(current), nr);
+ char task_comm[TASK_COMM_LEN];
+
+ dev_dbg_ratelimited(hdev->dev_ctrl,
+ "invalid ioctl: pid=%d, comm=\"%s\", cmd=%#010x, nr=%#04x\n",
+ task_pid_nr(current), get_task_comm(task_comm, current), cmd, nr);
return -ENOTTY;
}
- return _hl_ioctl(filep, cmd, arg, ioctl, hdev->dev_ctrl);
+ return _hl_ioctl(hpriv, cmd, arg, ioctl, hdev->dev_ctrl);
}
diff --git a/drivers/accel/habanalabs/common/irq.c b/drivers/accel/habanalabs/common/irq.c
index b1010d206c2e..978b7f4d5eeb 100644
--- a/drivers/accel/habanalabs/common/irq.c
+++ b/drivers/accel/habanalabs/common/irq.c
@@ -204,8 +204,10 @@ static void hl_ts_free_objects(struct work_struct *work)
{
struct timestamp_reg_work_obj *job =
container_of(work, struct timestamp_reg_work_obj, free_obj);
+ struct list_head *dynamic_alloc_free_list_head = job->dynamic_alloc_free_obj_head;
struct timestamp_reg_free_node *free_obj, *temp_free_obj;
struct list_head *free_list_head = job->free_obj_head;
+
struct hl_device *hdev = job->hdev;
list_for_each_entry_safe(free_obj, temp_free_obj, free_list_head, free_objects_node) {
@@ -215,10 +217,28 @@ static void hl_ts_free_objects(struct work_struct *work)
hl_mmap_mem_buf_put(free_obj->buf);
hl_cb_put(free_obj->cq_cb);
- kfree(free_obj);
+ atomic_set(&free_obj->in_use, 0);
}
kfree(free_list_head);
+
+ if (dynamic_alloc_free_list_head) {
+ list_for_each_entry_safe(free_obj, temp_free_obj, dynamic_alloc_free_list_head,
+ free_objects_node) {
+ dev_dbg(hdev->dev,
+ "Dynamic_Alloc list: About to put refcount to buf (%p) cq_cb(%p)\n",
+ free_obj->buf,
+ free_obj->cq_cb);
+
+ hl_mmap_mem_buf_put(free_obj->buf);
+ hl_cb_put(free_obj->cq_cb);
+ list_del(&free_obj->free_objects_node);
+ kfree(free_obj);
+ }
+
+ kfree(dynamic_alloc_free_list_head);
+ }
+
kfree(job);
}
@@ -233,11 +253,18 @@ static void hl_ts_free_objects(struct work_struct *work)
* list to a dedicated workqueue to do the actual put.
*/
static int handle_registration_node(struct hl_device *hdev, struct hl_user_pending_interrupt *pend,
- struct list_head **free_list, ktime_t now)
+ struct list_head **free_list,
+ struct list_head **dynamic_alloc_list,
+ struct hl_user_interrupt *intr)
{
+ struct hl_ts_free_jobs *ts_free_jobs_data;
struct timestamp_reg_free_node *free_node;
+ u32 free_node_index;
u64 timestamp;
+ ts_free_jobs_data = &intr->ts_free_jobs_data;
+ free_node_index = ts_free_jobs_data->next_avail_free_node_idx;
+
if (!(*free_list)) {
/* Alloc/Init the timestamp registration free objects list */
*free_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
@@ -247,39 +274,65 @@ static int handle_registration_node(struct hl_device *hdev, struct hl_user_pendi
INIT_LIST_HEAD(*free_list);
}
- free_node = kmalloc(sizeof(*free_node), GFP_ATOMIC);
- if (!free_node)
- return -ENOMEM;
+ free_node = &ts_free_jobs_data->free_nodes_pool[free_node_index];
+ if (atomic_cmpxchg(&free_node->in_use, 0, 1)) {
+ dev_dbg(hdev->dev,
+ "Timestamp free node pool is full, buff: %p, record: %p, irq: %u\n",
+ pend->ts_reg_info.buf,
+ pend,
+ intr->interrupt_id);
- timestamp = ktime_to_ns(now);
+ if (!(*dynamic_alloc_list)) {
+ *dynamic_alloc_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
+ if (!(*dynamic_alloc_list))
+ return -ENOMEM;
- *pend->ts_reg_info.timestamp_kernel_addr = timestamp;
+ INIT_LIST_HEAD(*dynamic_alloc_list);
+ }
+
+ free_node = kmalloc(sizeof(struct timestamp_reg_free_node), GFP_ATOMIC);
+ if (!free_node)
+ return -ENOMEM;
+
+ free_node->dynamic_alloc = 1;
+ }
- dev_dbg(hdev->dev, "Timestamp is set to ts cb address (%p), ts: 0x%llx\n",
- pend->ts_reg_info.timestamp_kernel_addr,
- *(u64 *)pend->ts_reg_info.timestamp_kernel_addr);
+ timestamp = ktime_to_ns(intr->timestamp);
- list_del(&pend->wait_list_node);
+ *pend->ts_reg_info.timestamp_kernel_addr = timestamp;
+
+ dev_dbg(hdev->dev, "Irq handle: Timestamp record (%p) ts cb address (%p), interrupt_id: %u\n",
+ pend, pend->ts_reg_info.timestamp_kernel_addr, intr->interrupt_id);
- /* Mark kernel CB node as free */
- pend->ts_reg_info.in_use = 0;
+ list_del(&pend->list_node);
/* Putting the refcount for ts_buff and cq_cb objects will be handled
* in workqueue context, just add job to free_list.
*/
free_node->buf = pend->ts_reg_info.buf;
free_node->cq_cb = pend->ts_reg_info.cq_cb;
- list_add(&free_node->free_objects_node, *free_list);
+
+ if (free_node->dynamic_alloc) {
+ list_add(&free_node->free_objects_node, *dynamic_alloc_list);
+ } else {
+ ts_free_jobs_data->next_avail_free_node_idx =
+ (++free_node_index) % ts_free_jobs_data->free_nodes_length;
+ list_add(&free_node->free_objects_node, *free_list);
+ }
+
+ /* Mark TS record as free */
+ pend->ts_reg_info.in_use = false;
return 0;
}
-static void handle_user_interrupt(struct hl_device *hdev, struct hl_user_interrupt *intr)
+static void handle_user_interrupt_ts_list(struct hl_device *hdev, struct hl_user_interrupt *intr)
{
+ struct list_head *ts_reg_free_list_head = NULL, *dynamic_alloc_list_head = NULL;
struct hl_user_pending_interrupt *pend, *temp_pend;
- struct list_head *ts_reg_free_list_head = NULL;
struct timestamp_reg_work_obj *job;
bool reg_node_handle_fail = false;
+ unsigned long flags;
int rc;
/* For registration nodes:
@@ -288,36 +341,32 @@ static void handle_user_interrupt(struct hl_device *hdev, struct hl_user_interru
* or in irq handler context at all (since release functions are long and
* might sleep), so we will need to handle that part in workqueue context.
* To avoid handling kmalloc failure which compels us rolling back actions
- * and move nodes hanged on the free list back to the interrupt wait list
+ * and move nodes hanged on the free list back to the interrupt ts list
* we always alloc the job of the WQ at the beginning.
*/
job = kmalloc(sizeof(*job), GFP_ATOMIC);
if (!job)
return;
- spin_lock(&intr->wait_list_lock);
- list_for_each_entry_safe(pend, temp_pend, &intr->wait_list_head, wait_list_node) {
+ spin_lock_irqsave(&intr->ts_list_lock, flags);
+ list_for_each_entry_safe(pend, temp_pend, &intr->ts_list_head, list_node) {
if ((pend->cq_kernel_addr && *(pend->cq_kernel_addr) >= pend->cq_target_value) ||
!pend->cq_kernel_addr) {
- if (pend->ts_reg_info.buf) {
- if (!reg_node_handle_fail) {
- rc = handle_registration_node(hdev, pend,
- &ts_reg_free_list_head, intr->timestamp);
- if (rc)
- reg_node_handle_fail = true;
- }
- } else {
- /* Handle wait target value node */
- pend->fence.timestamp = intr->timestamp;
- complete_all(&pend->fence.completion);
+ if (!reg_node_handle_fail) {
+ rc = handle_registration_node(hdev, pend,
+ &ts_reg_free_list_head,
+ &dynamic_alloc_list_head, intr);
+ if (rc)
+ reg_node_handle_fail = true;
}
}
}
- spin_unlock(&intr->wait_list_lock);
+ spin_unlock_irqrestore(&intr->ts_list_lock, flags);
if (ts_reg_free_list_head) {
INIT_WORK(&job->free_obj, hl_ts_free_objects);
job->free_obj_head = ts_reg_free_list_head;
+ job->dynamic_alloc_free_obj_head = dynamic_alloc_list_head;
job->hdev = hdev;
queue_work(hdev->ts_free_obj_wq, &job->free_obj);
} else {
@@ -325,6 +374,23 @@ static void handle_user_interrupt(struct hl_device *hdev, struct hl_user_interru
}
}
+static void handle_user_interrupt_wait_list(struct hl_device *hdev, struct hl_user_interrupt *intr)
+{
+ struct hl_user_pending_interrupt *pend, *temp_pend;
+ unsigned long flags;
+
+ spin_lock_irqsave(&intr->wait_list_lock, flags);
+ list_for_each_entry_safe(pend, temp_pend, &intr->wait_list_head, list_node) {
+ if ((pend->cq_kernel_addr && *(pend->cq_kernel_addr) >= pend->cq_target_value) ||
+ !pend->cq_kernel_addr) {
+ /* Handle wait target value node */
+ pend->fence.timestamp = intr->timestamp;
+ complete_all(&pend->fence.completion);
+ }
+ }
+ spin_unlock_irqrestore(&intr->wait_list_lock, flags);
+}
+
static void handle_tpc_interrupt(struct hl_device *hdev)
{
u64 event_mask;
@@ -346,19 +412,38 @@ static void handle_unexpected_user_interrupt(struct hl_device *hdev)
}
/**
- * hl_irq_handler_user_interrupt - irq handler for user interrupts
+ * hl_irq_user_interrupt_handler - irq handler for user interrupts.
*
* @irq: irq number
* @arg: pointer to user interrupt structure
- *
*/
-irqreturn_t hl_irq_handler_user_interrupt(int irq, void *arg)
+irqreturn_t hl_irq_user_interrupt_handler(int irq, void *arg)
{
struct hl_user_interrupt *user_int = arg;
+ struct hl_device *hdev = user_int->hdev;
user_int->timestamp = ktime_get();
+ switch (user_int->type) {
+ case HL_USR_INTERRUPT_CQ:
+ /* First handle user waiters threads */
+ handle_user_interrupt_wait_list(hdev, &hdev->common_user_cq_interrupt);
+ handle_user_interrupt_wait_list(hdev, user_int);
- return IRQ_WAKE_THREAD;
+ /* Second handle user timestamp registrations */
+ handle_user_interrupt_ts_list(hdev, &hdev->common_user_cq_interrupt);
+ handle_user_interrupt_ts_list(hdev, user_int);
+ break;
+ case HL_USR_INTERRUPT_DECODER:
+ handle_user_interrupt_wait_list(hdev, &hdev->common_decoder_interrupt);
+
+ /* Handle decoder interrupt registered on this specific irq */
+ handle_user_interrupt_wait_list(hdev, user_int);
+ break;
+ default:
+ break;
+ }
+
+ return IRQ_HANDLED;
}
/**
@@ -374,19 +459,8 @@ irqreturn_t hl_irq_user_interrupt_thread_handler(int irq, void *arg)
struct hl_user_interrupt *user_int = arg;
struct hl_device *hdev = user_int->hdev;
+ user_int->timestamp = ktime_get();
switch (user_int->type) {
- case HL_USR_INTERRUPT_CQ:
- handle_user_interrupt(hdev, &hdev->common_user_cq_interrupt);
-
- /* Handle user cq interrupt registered on this specific irq */
- handle_user_interrupt(hdev, user_int);
- break;
- case HL_USR_INTERRUPT_DECODER:
- handle_user_interrupt(hdev, &hdev->common_decoder_interrupt);
-
- /* Handle decoder interrupt registered on this specific irq */
- handle_user_interrupt(hdev, user_int);
- break;
case HL_USR_INTERRUPT_TPC:
handle_tpc_interrupt(hdev);
break;
@@ -400,6 +474,18 @@ irqreturn_t hl_irq_user_interrupt_thread_handler(int irq, void *arg)
return IRQ_HANDLED;
}
+irqreturn_t hl_irq_eq_error_interrupt_thread_handler(int irq, void *arg)
+{
+ u64 event_mask = HL_NOTIFIER_EVENT_DEVICE_RESET | HL_NOTIFIER_EVENT_DEVICE_UNAVAILABLE;
+ struct hl_device *hdev = arg;
+
+ dev_err(hdev->dev, "EQ error interrupt received\n");
+
+ hl_device_cond_reset(hdev, HL_DRV_RESET_HARD, event_mask);
+
+ return IRQ_HANDLED;
+}
+
/**
* hl_irq_handler_eq - irq handler for event queue
*
diff --git a/drivers/accel/habanalabs/common/memory.c b/drivers/accel/habanalabs/common/memory.c
index 4fc72a07d2f5..0b8689fe0b64 100644
--- a/drivers/accel/habanalabs/common/memory.c
+++ b/drivers/accel/habanalabs/common/memory.c
@@ -244,7 +244,7 @@ static int dma_map_host_va(struct hl_device *hdev, u64 addr, u64 size,
*p_userptr = userptr;
- rc = hdev->asic_funcs->asic_dma_map_sgtable(hdev, userptr->sgt, DMA_BIDIRECTIONAL);
+ rc = hl_dma_map_sgtable(hdev, userptr->sgt, DMA_BIDIRECTIONAL);
if (rc) {
dev_err(hdev->dev, "failed to map sgt with DMA region\n");
goto dma_map_err;
@@ -832,7 +832,6 @@ int hl_unreserve_va_block(struct hl_device *hdev, struct hl_ctx *ctx,
* physical pages
*
* This function does the following:
- * - Pin the physical pages related to the given virtual block.
* - Create a physical page pack from the physical pages related to the given
* virtual block.
*/
@@ -1532,24 +1531,20 @@ static int set_dma_sg(struct scatterlist *sg, u64 bar_address, u64 chunk_size,
}
static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64 *pages, u64 npages,
- u64 page_size, u64 exported_size,
+ u64 page_size, u64 exported_size, u64 offset,
struct device *dev, enum dma_data_direction dir)
{
- u64 chunk_size, bar_address, dma_max_seg_size, cur_size_to_export, cur_npages;
- struct asic_fixed_properties *prop;
- int rc, i, j, nents, cur_page;
+ u64 dma_max_seg_size, curr_page, size, chunk_size, left_size_to_export, left_size_in_page,
+ left_size_in_dma_seg, device_address, bar_address, start_page;
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
struct scatterlist *sg;
+ unsigned int nents, i;
struct sg_table *sgt;
+ bool next_sg_entry;
+ int rc;
- prop = &hdev->asic_prop;
-
- dma_max_seg_size = dma_get_max_seg_size(dev);
-
- /* We would like to align the max segment size to PAGE_SIZE, so the
- * SGL will contain aligned addresses that can be easily mapped to
- * an MMU
- */
- dma_max_seg_size = ALIGN_DOWN(dma_max_seg_size, PAGE_SIZE);
+ /* Align max segment size to PAGE_SIZE to fit the minimal IOMMU mapping granularity */
+ dma_max_seg_size = ALIGN_DOWN(dma_get_max_seg_size(dev), PAGE_SIZE);
if (dma_max_seg_size < PAGE_SIZE) {
dev_err_ratelimited(hdev->dev,
"dma_max_seg_size %llu can't be smaller than PAGE_SIZE\n",
@@ -1561,121 +1556,149 @@ static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64
if (!sgt)
return ERR_PTR(-ENOMEM);
- /* remove export size restrictions in case not explicitly defined */
- cur_size_to_export = exported_size ? exported_size : (npages * page_size);
-
- /* If the size of each page is larger than the dma max segment size,
- * then we can't combine pages and the number of entries in the SGL
- * will just be the
- * <number of pages> * <chunks of max segment size in each page>
- */
- if (page_size > dma_max_seg_size) {
- /* we should limit number of pages according to the exported size */
- cur_npages = DIV_ROUND_UP_SECTOR_T(cur_size_to_export, page_size);
- nents = cur_npages * DIV_ROUND_UP_SECTOR_T(page_size, dma_max_seg_size);
- } else {
- cur_npages = npages;
-
- /* Get number of non-contiguous chunks */
- for (i = 1, nents = 1, chunk_size = page_size ; i < cur_npages ; i++) {
- if (pages[i - 1] + page_size != pages[i] ||
- chunk_size + page_size > dma_max_seg_size) {
- nents++;
- chunk_size = page_size;
- continue;
- }
+ /* Use the offset to move to the actual first page that is exported */
+ for (start_page = 0 ; start_page < npages ; ++start_page) {
+ if (offset < page_size)
+ break;
- chunk_size += page_size;
- }
+ /* The offset value was validated so there can't be an underflow */
+ offset -= page_size;
}
- rc = sg_alloc_table(sgt, nents, GFP_KERNEL | __GFP_ZERO);
- if (rc)
- goto error_free;
+ /* Calculate the required number of entries for the SG table */
+ curr_page = start_page;
+ nents = 1;
+ left_size_to_export = exported_size;
+ left_size_in_page = page_size - offset;
+ left_size_in_dma_seg = dma_max_seg_size;
+ next_sg_entry = false;
- cur_page = 0;
+ while (true) {
+ size = min3(left_size_to_export, left_size_in_page, left_size_in_dma_seg);
+ left_size_to_export -= size;
+ left_size_in_page -= size;
+ left_size_in_dma_seg -= size;
- if (page_size > dma_max_seg_size) {
- u64 size_left, cur_device_address = 0;
+ if (!left_size_to_export)
+ break;
- size_left = page_size;
+ if (!left_size_in_page) {
+ /* left_size_to_export is not zero so there must be another page */
+ if (pages[curr_page] + page_size != pages[curr_page + 1])
+ next_sg_entry = true;
- /* Need to split each page into the number of chunks of
- * dma_max_seg_size
- */
- for_each_sgtable_dma_sg(sgt, sg, i) {
- if (size_left == page_size)
- cur_device_address =
- pages[cur_page] - prop->dram_base_address;
- else
- cur_device_address += dma_max_seg_size;
+ ++curr_page;
+ left_size_in_page = page_size;
+ }
- /* make sure not to export over exported size */
- chunk_size = min3(size_left, dma_max_seg_size, cur_size_to_export);
+ if (!left_size_in_dma_seg) {
+ next_sg_entry = true;
+ left_size_in_dma_seg = dma_max_seg_size;
+ }
- bar_address = hdev->dram_pci_bar_start + cur_device_address;
+ if (next_sg_entry) {
+ ++nents;
+ next_sg_entry = false;
+ }
+ }
- rc = set_dma_sg(sg, bar_address, chunk_size, dev, dir);
- if (rc)
- goto error_unmap;
+ rc = sg_alloc_table(sgt, nents, GFP_KERNEL | __GFP_ZERO);
+ if (rc)
+ goto err_free_sgt;
- cur_size_to_export -= chunk_size;
+ /* Prepare the SG table entries */
+ curr_page = start_page;
+ device_address = pages[curr_page] + offset;
+ left_size_to_export = exported_size;
+ left_size_in_page = page_size - offset;
+ left_size_in_dma_seg = dma_max_seg_size;
+ next_sg_entry = false;
- if (size_left > dma_max_seg_size) {
- size_left -= dma_max_seg_size;
- } else {
- cur_page++;
- size_left = page_size;
+ for_each_sgtable_dma_sg(sgt, sg, i) {
+ bar_address = hdev->dram_pci_bar_start + (device_address - prop->dram_base_address);
+ chunk_size = 0;
+
+ for ( ; curr_page < npages ; ++curr_page) {
+ size = min3(left_size_to_export, left_size_in_page, left_size_in_dma_seg);
+ chunk_size += size;
+ left_size_to_export -= size;
+ left_size_in_page -= size;
+ left_size_in_dma_seg -= size;
+
+ if (!left_size_to_export)
+ break;
+
+ if (!left_size_in_page) {
+ /* left_size_to_export is not zero so there must be another page */
+ if (pages[curr_page] + page_size != pages[curr_page + 1]) {
+ device_address = pages[curr_page + 1];
+ next_sg_entry = true;
+ }
+
+ left_size_in_page = page_size;
}
- }
- } else {
- /* Merge pages and put them into the scatterlist */
- for_each_sgtable_dma_sg(sgt, sg, i) {
- chunk_size = page_size;
- for (j = cur_page + 1 ; j < cur_npages ; j++) {
- if (pages[j - 1] + page_size != pages[j] ||
- chunk_size + page_size > dma_max_seg_size)
- break;
-
- chunk_size += page_size;
+
+ if (!left_size_in_dma_seg) {
+ /*
+ * Skip setting a new device address if already moving to a page
+ * which is not contiguous with the current page.
+ */
+ if (!next_sg_entry) {
+ device_address += chunk_size;
+ next_sg_entry = true;
+ }
+
+ left_size_in_dma_seg = dma_max_seg_size;
}
- bar_address = hdev->dram_pci_bar_start +
- (pages[cur_page] - prop->dram_base_address);
+ if (next_sg_entry) {
+ next_sg_entry = false;
+ break;
+ }
+ }
- /* make sure not to export over exported size */
- chunk_size = min(chunk_size, cur_size_to_export);
- rc = set_dma_sg(sg, bar_address, chunk_size, dev, dir);
- if (rc)
- goto error_unmap;
+ rc = set_dma_sg(sg, bar_address, chunk_size, dev, dir);
+ if (rc)
+ goto err_unmap;
+ }
- cur_size_to_export -= chunk_size;
- cur_page = j;
- }
+ /* There should be nothing left to export exactly after looping over all SG elements */
+ if (left_size_to_export) {
+ dev_err(hdev->dev,
+ "left size to export %#llx after initializing %u SG elements\n",
+ left_size_to_export, sgt->nents);
+ rc = -ENOMEM;
+ goto err_unmap;
}
- /* Because we are not going to include a CPU list we want to have some
- * chance that other users will detect this by setting the orig_nents
- * to 0 and using only nents (length of DMA list) when going over the
- * sgl
+ /*
+ * Because we are not going to include a CPU list, we want to have some chance that other
+ * users will detect this when going over SG table, by setting the orig_nents to 0 and using
+ * only nents (length of DMA list).
*/
sgt->orig_nents = 0;
+ dev_dbg(hdev->dev, "prepared SG table with %u entries for importer %s\n",
+ nents, dev_name(dev));
+ for_each_sgtable_dma_sg(sgt, sg, i)
+ dev_dbg(hdev->dev,
+ "SG entry %d: address %#llx, length %#x\n",
+ i, sg_dma_address(sg), sg_dma_len(sg));
+
return sgt;
-error_unmap:
+err_unmap:
for_each_sgtable_dma_sg(sgt, sg, i) {
if (!sg_dma_len(sg))
continue;
- dma_unmap_resource(dev, sg_dma_address(sg),
- sg_dma_len(sg), dir,
+ dma_unmap_resource(dev, sg_dma_address(sg), sg_dma_len(sg), dir,
DMA_ATTR_SKIP_CPU_SYNC);
}
sg_free_table(sgt);
-error_free:
+err_free_sgt:
kfree(sgt);
return ERR_PTR(rc);
}
@@ -1700,6 +1723,7 @@ static int hl_dmabuf_attach(struct dma_buf *dmabuf,
static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment,
enum dma_data_direction dir)
{
+ u64 *pages, npages, page_size, exported_size, offset;
struct dma_buf *dma_buf = attachment->dmabuf;
struct hl_vm_phys_pg_pack *phys_pg_pack;
struct hl_dmabuf_priv *hl_dmabuf;
@@ -1708,30 +1732,28 @@ static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment,
hl_dmabuf = dma_buf->priv;
hdev = hl_dmabuf->ctx->hdev;
- phys_pg_pack = hl_dmabuf->phys_pg_pack;
if (!attachment->peer2peer) {
dev_dbg(hdev->dev, "Failed to map dmabuf because p2p is disabled\n");
return ERR_PTR(-EPERM);
}
- if (phys_pg_pack)
- sgt = alloc_sgt_from_device_pages(hdev,
- phys_pg_pack->pages,
- phys_pg_pack->npages,
- phys_pg_pack->page_size,
- phys_pg_pack->exported_size,
- attachment->dev,
- dir);
- else
- sgt = alloc_sgt_from_device_pages(hdev,
- &hl_dmabuf->device_address,
- 1,
- hl_dmabuf->dmabuf->size,
- 0,
- attachment->dev,
- dir);
+ exported_size = hl_dmabuf->dmabuf->size;
+ offset = hl_dmabuf->offset;
+ phys_pg_pack = hl_dmabuf->phys_pg_pack;
+ if (phys_pg_pack) {
+ pages = phys_pg_pack->pages;
+ npages = phys_pg_pack->npages;
+ page_size = phys_pg_pack->page_size;
+ } else {
+ pages = &hl_dmabuf->device_phys_addr;
+ npages = 1;
+ page_size = hl_dmabuf->dmabuf->size;
+ }
+
+ sgt = alloc_sgt_from_device_pages(hdev, pages, npages, page_size, exported_size, offset,
+ attachment->dev, dir);
if (IS_ERR(sgt))
dev_err(hdev->dev, "failed (%ld) to initialize sgt for dmabuf\n", PTR_ERR(sgt));
@@ -1818,7 +1840,7 @@ static void hl_release_dmabuf(struct dma_buf *dmabuf)
hl_ctx_put(ctx);
/* Paired with get_file() in export_dmabuf() */
- fput(ctx->hpriv->filp);
+ fput(ctx->hpriv->file_priv->filp);
kfree(hl_dmabuf);
}
@@ -1864,7 +1886,7 @@ static int export_dmabuf(struct hl_ctx *ctx,
* released first and only then the compute device.
* Paired with fput() in hl_release_dmabuf().
*/
- get_file(ctx->hpriv->filp);
+ get_file(ctx->hpriv->file_priv->filp);
*dmabuf_fd = fd;
@@ -1876,22 +1898,29 @@ err_dma_buf_put:
return rc;
}
-static int validate_export_params_common(struct hl_device *hdev, u64 device_addr, u64 size)
+static int validate_export_params_common(struct hl_device *hdev, u64 addr, u64 size, u64 offset)
{
- if (!IS_ALIGNED(device_addr, PAGE_SIZE)) {
+ if (!PAGE_ALIGNED(addr)) {
dev_dbg(hdev->dev,
- "exported device memory address 0x%llx should be aligned to 0x%lx\n",
- device_addr, PAGE_SIZE);
+ "exported device memory address 0x%llx should be aligned to PAGE_SIZE 0x%lx\n",
+ addr, PAGE_SIZE);
return -EINVAL;
}
- if (size < PAGE_SIZE) {
+ if (!size || !PAGE_ALIGNED(size)) {
dev_dbg(hdev->dev,
- "exported device memory size %llu should be equal to or greater than %lu\n",
+ "exported device memory size %llu should be a multiple of PAGE_SIZE %lu\n",
size, PAGE_SIZE);
return -EINVAL;
}
+ if (!PAGE_ALIGNED(offset)) {
+ dev_dbg(hdev->dev,
+ "exported device memory offset %llu should be a multiple of PAGE_SIZE %lu\n",
+ offset, PAGE_SIZE);
+ return -EINVAL;
+ }
+
return 0;
}
@@ -1901,13 +1930,13 @@ static int validate_export_params_no_mmu(struct hl_device *hdev, u64 device_addr
u64 bar_address;
int rc;
- rc = validate_export_params_common(hdev, device_addr, size);
+ rc = validate_export_params_common(hdev, device_addr, size, 0);
if (rc)
return rc;
if (device_addr < prop->dram_user_base_address ||
- (device_addr + size) > prop->dram_end_address ||
- (device_addr + size) < device_addr) {
+ (device_addr + size) > prop->dram_end_address ||
+ (device_addr + size) < device_addr) {
dev_dbg(hdev->dev,
"DRAM memory range 0x%llx (+0x%llx) is outside of DRAM boundaries\n",
device_addr, size);
@@ -1934,29 +1963,26 @@ static int validate_export_params(struct hl_device *hdev, u64 device_addr, u64 s
u64 bar_address;
int i, rc;
- rc = validate_export_params_common(hdev, device_addr, size);
+ rc = validate_export_params_common(hdev, device_addr, size, offset);
if (rc)
return rc;
if ((offset + size) > phys_pg_pack->total_size) {
dev_dbg(hdev->dev, "offset %#llx and size %#llx exceed total map size %#llx\n",
- offset, size, phys_pg_pack->total_size);
+ offset, size, phys_pg_pack->total_size);
return -EINVAL;
}
for (i = 0 ; i < phys_pg_pack->npages ; i++) {
-
bar_address = hdev->dram_pci_bar_start +
- (phys_pg_pack->pages[i] - prop->dram_base_address);
+ (phys_pg_pack->pages[i] - prop->dram_base_address);
if ((bar_address + phys_pg_pack->page_size) >
(hdev->dram_pci_bar_start + prop->dram_pci_bar_size) ||
(bar_address + phys_pg_pack->page_size) < bar_address) {
dev_dbg(hdev->dev,
"DRAM memory range 0x%llx (+0x%x) is outside of PCI BAR boundaries\n",
- phys_pg_pack->pages[i],
- phys_pg_pack->page_size);
-
+ phys_pg_pack->pages[i], phys_pg_pack->page_size);
return -EINVAL;
}
}
@@ -2012,7 +2038,6 @@ static int export_dmabuf_from_addr(struct hl_ctx *ctx, u64 addr, u64 size, u64 o
struct asic_fixed_properties *prop;
struct hl_dmabuf_priv *hl_dmabuf;
struct hl_device *hdev;
- u64 export_addr;
int rc;
hdev = ctx->hdev;
@@ -2024,8 +2049,6 @@ static int export_dmabuf_from_addr(struct hl_ctx *ctx, u64 addr, u64 size, u64 o
return -EINVAL;
}
- export_addr = addr + offset;
-
hl_dmabuf = kzalloc(sizeof(*hl_dmabuf), GFP_KERNEL);
if (!hl_dmabuf)
return -ENOMEM;
@@ -2041,20 +2064,20 @@ static int export_dmabuf_from_addr(struct hl_ctx *ctx, u64 addr, u64 size, u64 o
rc = PTR_ERR(phys_pg_pack);
goto dec_memhash_export_cnt;
}
- rc = validate_export_params(hdev, export_addr, size, offset, phys_pg_pack);
+ rc = validate_export_params(hdev, addr, size, offset, phys_pg_pack);
if (rc)
goto dec_memhash_export_cnt;
- phys_pg_pack->exported_size = size;
hl_dmabuf->phys_pg_pack = phys_pg_pack;
hl_dmabuf->memhash_hnode = hnode;
+ hl_dmabuf->offset = offset;
} else {
- rc = validate_export_params_no_mmu(hdev, export_addr, size);
+ rc = validate_export_params_no_mmu(hdev, addr, size);
if (rc)
goto err_free_dmabuf_wrapper;
- }
- hl_dmabuf->device_address = export_addr;
+ hl_dmabuf->device_phys_addr = addr;
+ }
rc = export_dmabuf(ctx, hl_dmabuf, size, flags, dmabuf_fd);
if (rc)
@@ -2171,8 +2194,9 @@ static int allocate_timestamps_buffers(struct hl_fpriv *hpriv, struct hl_mem_in
return 0;
}
-int hl_mem_ioctl(struct hl_fpriv *hpriv, void *data)
+int hl_mem_ioctl(struct drm_device *ddev, void *data, struct drm_file *file_priv)
{
+ struct hl_fpriv *hpriv = file_priv->driver_priv;
enum hl_device_status status;
union hl_mem_args *args = data;
struct hl_device *hdev = hpriv->hdev;
@@ -2420,7 +2444,7 @@ void hl_unpin_host_memory(struct hl_device *hdev, struct hl_userptr *userptr)
hl_debugfs_remove_userptr(hdev, userptr);
if (userptr->dma_mapped)
- hdev->asic_funcs->hl_dma_unmap_sgtable(hdev, userptr->sgt, userptr->dir);
+ hl_dma_unmap_sgtable(hdev, userptr->sgt, userptr->dir);
unpin_user_pages_dirty_lock(userptr->pages, userptr->npages, true);
kvfree(userptr->pages);
diff --git a/drivers/accel/habanalabs/gaudi/gaudi.c b/drivers/accel/habanalabs/gaudi/gaudi.c
index 056e2ef44afb..53292d4c15c8 100644
--- a/drivers/accel/habanalabs/gaudi/gaudi.c
+++ b/drivers/accel/habanalabs/gaudi/gaudi.c
@@ -63,6 +63,10 @@
#define GAUDI_LINUX_FW_FILE "habanalabs/gaudi/gaudi-fit.itb"
#define GAUDI_TPC_FW_FILE "habanalabs/gaudi/gaudi_tpc.bin"
+MODULE_FIRMWARE(GAUDI_BOOT_FIT_FILE);
+MODULE_FIRMWARE(GAUDI_LINUX_FW_FILE);
+MODULE_FIRMWARE(GAUDI_TPC_FW_FILE);
+
#define GAUDI_DMA_POOL_BLK_SIZE 0x100 /* 256 bytes */
#define GAUDI_RESET_TIMEOUT_MSEC 2000 /* 2000ms */
@@ -660,7 +664,7 @@ static int gaudi_set_fixed_properties(struct hl_device *hdev)
prop->pcie_dbi_base_address = mmPCIE_DBI_BASE;
prop->pcie_aux_dbi_reg_addr = CFG_BASE + mmPCIE_AUX_DBI;
- strncpy(prop->cpucp_info.card_name, GAUDI_DEFAULT_CARD_NAME,
+ strscpy_pad(prop->cpucp_info.card_name, GAUDI_DEFAULT_CARD_NAME,
CARD_NAME_MAX_LEN);
prop->max_pending_cs = GAUDI_MAX_PENDING_CS;
@@ -4619,8 +4623,7 @@ static int gaudi_scrub_device_dram(struct hl_device *hdev, u64 val)
static int gaudi_scrub_device_mem(struct hl_device *hdev)
{
struct asic_fixed_properties *prop = &hdev->asic_prop;
- u64 wait_to_idle_time = hdev->pdev ? HBM_SCRUBBING_TIMEOUT_US :
- min_t(u64, HBM_SCRUBBING_TIMEOUT_US * 10, HL_SIM_MAX_TIMEOUT_US);
+ u64 wait_to_idle_time = HBM_SCRUBBING_TIMEOUT_US;
u64 addr, size, val = hdev->memory_scrub_val;
ktime_t timeout;
int rc = 0;
@@ -4904,7 +4907,7 @@ static int gaudi_pin_memory_before_cs(struct hl_device *hdev,
list_add_tail(&userptr->job_node, parser->job_userptr_list);
- rc = hdev->asic_funcs->asic_dma_map_sgtable(hdev, userptr->sgt, dir);
+ rc = hl_dma_map_sgtable(hdev, userptr->sgt, dir);
if (rc) {
dev_err(hdev->dev, "failed to map sgt with DMA region\n");
goto unpin_memory;
@@ -8000,7 +8003,7 @@ static int gaudi_cpucp_info_get(struct hl_device *hdev)
return rc;
if (!strlen(prop->cpucp_info.card_name))
- strncpy(prop->cpucp_info.card_name, GAUDI_DEFAULT_CARD_NAME,
+ strscpy_pad(prop->cpucp_info.card_name, GAUDI_DEFAULT_CARD_NAME,
CARD_NAME_MAX_LEN);
hdev->card_type = le32_to_cpu(hdev->asic_prop.cpucp_info.card_type);
@@ -9140,9 +9143,9 @@ static const struct hl_asic_funcs gaudi_funcs = {
.asic_dma_pool_free = gaudi_dma_pool_free,
.cpu_accessible_dma_pool_alloc = gaudi_cpu_accessible_dma_pool_alloc,
.cpu_accessible_dma_pool_free = gaudi_cpu_accessible_dma_pool_free,
- .hl_dma_unmap_sgtable = hl_dma_unmap_sgtable,
+ .dma_unmap_sgtable = hl_asic_dma_unmap_sgtable,
.cs_parser = gaudi_cs_parser,
- .asic_dma_map_sgtable = hl_dma_map_sgtable,
+ .dma_map_sgtable = hl_asic_dma_map_sgtable,
.add_end_of_cb_packets = gaudi_add_end_of_cb_packets,
.update_eq_ci = gaudi_update_eq_ci,
.context_switch = gaudi_context_switch,
diff --git a/drivers/accel/habanalabs/gaudi/gaudiP.h b/drivers/accel/habanalabs/gaudi/gaudiP.h
index b8fa724be5a1..831be53bb9d7 100644
--- a/drivers/accel/habanalabs/gaudi/gaudiP.h
+++ b/drivers/accel/habanalabs/gaudi/gaudiP.h
@@ -10,7 +10,7 @@
#include <uapi/drm/habanalabs_accel.h>
#include "../common/habanalabs.h"
-#include "../include/common/hl_boot_if.h"
+#include <linux/habanalabs/hl_boot_if.h>
#include "../include/gaudi/gaudi_packets.h"
#include "../include/gaudi/gaudi.h"
#include "../include/gaudi/gaudi_async_events.h"
diff --git a/drivers/accel/habanalabs/gaudi/gaudi_coresight.c b/drivers/accel/habanalabs/gaudi/gaudi_coresight.c
index 3455b14554c6..1168fefa33f4 100644
--- a/drivers/accel/habanalabs/gaudi/gaudi_coresight.c
+++ b/drivers/accel/habanalabs/gaudi/gaudi_coresight.c
@@ -482,6 +482,11 @@ static int gaudi_config_etf(struct hl_device *hdev,
WREG32(base_reg + 0xFB0, CORESIGHT_UNLOCK);
+ val = RREG32(base_reg + 0x20);
+
+ if ((!params->enable && val == 0x0) || (params->enable && val != 0x0))
+ return 0;
+
val = RREG32(base_reg + 0x304);
val |= 0x1000;
WREG32(base_reg + 0x304, val);
@@ -580,6 +585,13 @@ static int gaudi_config_etr(struct hl_device *hdev,
WREG32(mmPSOC_ETR_LAR, CORESIGHT_UNLOCK);
+ val = RREG32(mmPSOC_ETR_CTL);
+
+ if ((!params->enable && val == 0x0) || (params->enable && val != 0x0))
+ return 0;
+
+
+
val = RREG32(mmPSOC_ETR_FFCR);
val |= 0x1000;
WREG32(mmPSOC_ETR_FFCR, val);
diff --git a/drivers/accel/habanalabs/gaudi2/gaudi2.c b/drivers/accel/habanalabs/gaudi2/gaudi2.c
index 20c4583f12b0..819660c684cf 100644
--- a/drivers/accel/habanalabs/gaudi2/gaudi2.c
+++ b/drivers/accel/habanalabs/gaudi2/gaudi2.c
@@ -66,7 +66,6 @@
#define GAUDI2_NUM_OF_TPC_INTR_CAUSE 31
#define GAUDI2_NUM_OF_DEC_ERR_CAUSE 25
#define GAUDI2_NUM_OF_MME_ERR_CAUSE 16
-#define GAUDI2_NUM_OF_MME_SBTE_ERR_CAUSE 5
#define GAUDI2_NUM_OF_MME_WAP_ERR_CAUSE 7
#define GAUDI2_NUM_OF_DMA_CORE_INTR_CAUSE 8
#define GAUDI2_NUM_OF_MMU_SPI_SEI_CAUSE 19
@@ -916,14 +915,6 @@ static const char * const guadi2_mme_error_cause[GAUDI2_NUM_OF_MME_ERR_CAUSE] =
"sbte_prtn_intr_4",
};
-static const char * const guadi2_mme_sbte_error_cause[GAUDI2_NUM_OF_MME_SBTE_ERR_CAUSE] = {
- "i0",
- "i1",
- "i2",
- "i3",
- "i4",
-};
-
static const char * const guadi2_mme_wap_error_cause[GAUDI2_NUM_OF_MME_WAP_ERR_CAUSE] = {
"WBC ERR RESP_0",
"WBC ERR RESP_1",
@@ -993,6 +984,111 @@ gaudi2_pcie_addr_dec_error_cause[GAUDI2_NUM_OF_PCIE_ADDR_DEC_ERR_CAUSE] = {
"TLP is blocked by RR"
};
+static const int gaudi2_queue_id_to_engine_id[] = {
+ [GAUDI2_QUEUE_ID_PDMA_0_0...GAUDI2_QUEUE_ID_PDMA_0_3] = GAUDI2_ENGINE_ID_PDMA_0,
+ [GAUDI2_QUEUE_ID_PDMA_1_0...GAUDI2_QUEUE_ID_PDMA_1_3] = GAUDI2_ENGINE_ID_PDMA_1,
+ [GAUDI2_QUEUE_ID_DCORE0_EDMA_0_0...GAUDI2_QUEUE_ID_DCORE0_EDMA_0_3] =
+ GAUDI2_DCORE0_ENGINE_ID_EDMA_0,
+ [GAUDI2_QUEUE_ID_DCORE0_EDMA_1_0...GAUDI2_QUEUE_ID_DCORE0_EDMA_1_3] =
+ GAUDI2_DCORE0_ENGINE_ID_EDMA_1,
+ [GAUDI2_QUEUE_ID_DCORE1_EDMA_0_0...GAUDI2_QUEUE_ID_DCORE1_EDMA_0_3] =
+ GAUDI2_DCORE1_ENGINE_ID_EDMA_0,
+ [GAUDI2_QUEUE_ID_DCORE1_EDMA_1_0...GAUDI2_QUEUE_ID_DCORE1_EDMA_1_3] =
+ GAUDI2_DCORE1_ENGINE_ID_EDMA_1,
+ [GAUDI2_QUEUE_ID_DCORE2_EDMA_0_0...GAUDI2_QUEUE_ID_DCORE2_EDMA_0_3] =
+ GAUDI2_DCORE2_ENGINE_ID_EDMA_0,
+ [GAUDI2_QUEUE_ID_DCORE2_EDMA_1_0...GAUDI2_QUEUE_ID_DCORE2_EDMA_1_3] =
+ GAUDI2_DCORE2_ENGINE_ID_EDMA_1,
+ [GAUDI2_QUEUE_ID_DCORE3_EDMA_0_0...GAUDI2_QUEUE_ID_DCORE3_EDMA_0_3] =
+ GAUDI2_DCORE3_ENGINE_ID_EDMA_0,
+ [GAUDI2_QUEUE_ID_DCORE3_EDMA_1_0...GAUDI2_QUEUE_ID_DCORE3_EDMA_1_3] =
+ GAUDI2_DCORE3_ENGINE_ID_EDMA_1,
+ [GAUDI2_QUEUE_ID_DCORE0_MME_0_0...GAUDI2_QUEUE_ID_DCORE0_MME_0_3] =
+ GAUDI2_DCORE0_ENGINE_ID_MME,
+ [GAUDI2_QUEUE_ID_DCORE1_MME_0_0...GAUDI2_QUEUE_ID_DCORE1_MME_0_3] =
+ GAUDI2_DCORE1_ENGINE_ID_MME,
+ [GAUDI2_QUEUE_ID_DCORE2_MME_0_0...GAUDI2_QUEUE_ID_DCORE2_MME_0_3] =
+ GAUDI2_DCORE2_ENGINE_ID_MME,
+ [GAUDI2_QUEUE_ID_DCORE3_MME_0_0...GAUDI2_QUEUE_ID_DCORE3_MME_0_3] =
+ GAUDI2_DCORE3_ENGINE_ID_MME,
+ [GAUDI2_QUEUE_ID_DCORE0_TPC_0_0...GAUDI2_QUEUE_ID_DCORE0_TPC_0_3] =
+ GAUDI2_DCORE0_ENGINE_ID_TPC_0,
+ [GAUDI2_QUEUE_ID_DCORE0_TPC_1_0...GAUDI2_QUEUE_ID_DCORE0_TPC_1_3] =
+ GAUDI2_DCORE0_ENGINE_ID_TPC_1,
+ [GAUDI2_QUEUE_ID_DCORE0_TPC_2_0...GAUDI2_QUEUE_ID_DCORE0_TPC_2_3] =
+ GAUDI2_DCORE0_ENGINE_ID_TPC_2,
+ [GAUDI2_QUEUE_ID_DCORE0_TPC_3_0...GAUDI2_QUEUE_ID_DCORE0_TPC_3_3] =
+ GAUDI2_DCORE0_ENGINE_ID_TPC_3,
+ [GAUDI2_QUEUE_ID_DCORE0_TPC_4_0...GAUDI2_QUEUE_ID_DCORE0_TPC_4_3] =
+ GAUDI2_DCORE0_ENGINE_ID_TPC_4,
+ [GAUDI2_QUEUE_ID_DCORE0_TPC_5_0...GAUDI2_QUEUE_ID_DCORE0_TPC_5_3] =
+ GAUDI2_DCORE0_ENGINE_ID_TPC_5,
+ [GAUDI2_QUEUE_ID_DCORE0_TPC_6_0...GAUDI2_QUEUE_ID_DCORE0_TPC_6_3] =
+ GAUDI2_DCORE0_ENGINE_ID_TPC_6,
+ [GAUDI2_QUEUE_ID_DCORE1_TPC_0_0...GAUDI2_QUEUE_ID_DCORE1_TPC_0_3] =
+ GAUDI2_DCORE1_ENGINE_ID_TPC_0,
+ [GAUDI2_QUEUE_ID_DCORE1_TPC_1_0...GAUDI2_QUEUE_ID_DCORE1_TPC_1_3] =
+ GAUDI2_DCORE1_ENGINE_ID_TPC_1,
+ [GAUDI2_QUEUE_ID_DCORE1_TPC_2_0...GAUDI2_QUEUE_ID_DCORE1_TPC_2_3] =
+ GAUDI2_DCORE1_ENGINE_ID_TPC_2,
+ [GAUDI2_QUEUE_ID_DCORE1_TPC_3_0...GAUDI2_QUEUE_ID_DCORE1_TPC_3_3] =
+ GAUDI2_DCORE1_ENGINE_ID_TPC_3,
+ [GAUDI2_QUEUE_ID_DCORE1_TPC_4_0...GAUDI2_QUEUE_ID_DCORE1_TPC_4_3] =
+ GAUDI2_DCORE1_ENGINE_ID_TPC_4,
+ [GAUDI2_QUEUE_ID_DCORE1_TPC_5_0...GAUDI2_QUEUE_ID_DCORE1_TPC_5_3] =
+ GAUDI2_DCORE1_ENGINE_ID_TPC_5,
+ [GAUDI2_QUEUE_ID_DCORE2_TPC_0_0...GAUDI2_QUEUE_ID_DCORE2_TPC_0_3] =
+ GAUDI2_DCORE2_ENGINE_ID_TPC_0,
+ [GAUDI2_QUEUE_ID_DCORE2_TPC_1_0...GAUDI2_QUEUE_ID_DCORE2_TPC_1_3] =
+ GAUDI2_DCORE2_ENGINE_ID_TPC_1,
+ [GAUDI2_QUEUE_ID_DCORE2_TPC_2_0...GAUDI2_QUEUE_ID_DCORE2_TPC_2_3] =
+ GAUDI2_DCORE2_ENGINE_ID_TPC_2,
+ [GAUDI2_QUEUE_ID_DCORE2_TPC_3_0...GAUDI2_QUEUE_ID_DCORE2_TPC_3_3] =
+ GAUDI2_DCORE2_ENGINE_ID_TPC_3,
+ [GAUDI2_QUEUE_ID_DCORE2_TPC_4_0...GAUDI2_QUEUE_ID_DCORE2_TPC_4_3] =
+ GAUDI2_DCORE2_ENGINE_ID_TPC_4,
+ [GAUDI2_QUEUE_ID_DCORE2_TPC_5_0...GAUDI2_QUEUE_ID_DCORE2_TPC_5_3] =
+ GAUDI2_DCORE2_ENGINE_ID_TPC_5,
+ [GAUDI2_QUEUE_ID_DCORE3_TPC_0_0...GAUDI2_QUEUE_ID_DCORE3_TPC_0_3] =
+ GAUDI2_DCORE3_ENGINE_ID_TPC_0,
+ [GAUDI2_QUEUE_ID_DCORE3_TPC_1_0...GAUDI2_QUEUE_ID_DCORE3_TPC_1_3] =
+ GAUDI2_DCORE3_ENGINE_ID_TPC_1,
+ [GAUDI2_QUEUE_ID_DCORE3_TPC_2_0...GAUDI2_QUEUE_ID_DCORE3_TPC_2_3] =
+ GAUDI2_DCORE3_ENGINE_ID_TPC_2,
+ [GAUDI2_QUEUE_ID_DCORE3_TPC_3_0...GAUDI2_QUEUE_ID_DCORE3_TPC_3_3] =
+ GAUDI2_DCORE3_ENGINE_ID_TPC_3,
+ [GAUDI2_QUEUE_ID_DCORE3_TPC_4_0...GAUDI2_QUEUE_ID_DCORE3_TPC_4_3] =
+ GAUDI2_DCORE3_ENGINE_ID_TPC_4,
+ [GAUDI2_QUEUE_ID_DCORE3_TPC_5_0...GAUDI2_QUEUE_ID_DCORE3_TPC_5_3] =
+ GAUDI2_DCORE3_ENGINE_ID_TPC_5,
+ [GAUDI2_QUEUE_ID_NIC_0_0...GAUDI2_QUEUE_ID_NIC_0_3] = GAUDI2_ENGINE_ID_NIC0_0,
+ [GAUDI2_QUEUE_ID_NIC_1_0...GAUDI2_QUEUE_ID_NIC_1_3] = GAUDI2_ENGINE_ID_NIC0_1,
+ [GAUDI2_QUEUE_ID_NIC_2_0...GAUDI2_QUEUE_ID_NIC_2_3] = GAUDI2_ENGINE_ID_NIC1_0,
+ [GAUDI2_QUEUE_ID_NIC_3_0...GAUDI2_QUEUE_ID_NIC_3_3] = GAUDI2_ENGINE_ID_NIC1_1,
+ [GAUDI2_QUEUE_ID_NIC_4_0...GAUDI2_QUEUE_ID_NIC_4_3] = GAUDI2_ENGINE_ID_NIC2_0,
+ [GAUDI2_QUEUE_ID_NIC_5_0...GAUDI2_QUEUE_ID_NIC_5_3] = GAUDI2_ENGINE_ID_NIC2_1,
+ [GAUDI2_QUEUE_ID_NIC_6_0...GAUDI2_QUEUE_ID_NIC_6_3] = GAUDI2_ENGINE_ID_NIC3_0,
+ [GAUDI2_QUEUE_ID_NIC_7_0...GAUDI2_QUEUE_ID_NIC_7_3] = GAUDI2_ENGINE_ID_NIC3_1,
+ [GAUDI2_QUEUE_ID_NIC_8_0...GAUDI2_QUEUE_ID_NIC_8_3] = GAUDI2_ENGINE_ID_NIC4_0,
+ [GAUDI2_QUEUE_ID_NIC_9_0...GAUDI2_QUEUE_ID_NIC_9_3] = GAUDI2_ENGINE_ID_NIC4_1,
+ [GAUDI2_QUEUE_ID_NIC_10_0...GAUDI2_QUEUE_ID_NIC_10_3] = GAUDI2_ENGINE_ID_NIC5_0,
+ [GAUDI2_QUEUE_ID_NIC_11_0...GAUDI2_QUEUE_ID_NIC_11_3] = GAUDI2_ENGINE_ID_NIC5_1,
+ [GAUDI2_QUEUE_ID_NIC_12_0...GAUDI2_QUEUE_ID_NIC_12_3] = GAUDI2_ENGINE_ID_NIC6_0,
+ [GAUDI2_QUEUE_ID_NIC_13_0...GAUDI2_QUEUE_ID_NIC_13_3] = GAUDI2_ENGINE_ID_NIC6_1,
+ [GAUDI2_QUEUE_ID_NIC_14_0...GAUDI2_QUEUE_ID_NIC_14_3] = GAUDI2_ENGINE_ID_NIC7_0,
+ [GAUDI2_QUEUE_ID_NIC_15_0...GAUDI2_QUEUE_ID_NIC_15_3] = GAUDI2_ENGINE_ID_NIC7_1,
+ [GAUDI2_QUEUE_ID_NIC_16_0...GAUDI2_QUEUE_ID_NIC_16_3] = GAUDI2_ENGINE_ID_NIC8_0,
+ [GAUDI2_QUEUE_ID_NIC_17_0...GAUDI2_QUEUE_ID_NIC_17_3] = GAUDI2_ENGINE_ID_NIC8_1,
+ [GAUDI2_QUEUE_ID_NIC_18_0...GAUDI2_QUEUE_ID_NIC_18_3] = GAUDI2_ENGINE_ID_NIC9_0,
+ [GAUDI2_QUEUE_ID_NIC_19_0...GAUDI2_QUEUE_ID_NIC_19_3] = GAUDI2_ENGINE_ID_NIC9_1,
+ [GAUDI2_QUEUE_ID_NIC_20_0...GAUDI2_QUEUE_ID_NIC_20_3] = GAUDI2_ENGINE_ID_NIC10_0,
+ [GAUDI2_QUEUE_ID_NIC_21_0...GAUDI2_QUEUE_ID_NIC_21_3] = GAUDI2_ENGINE_ID_NIC10_1,
+ [GAUDI2_QUEUE_ID_NIC_22_0...GAUDI2_QUEUE_ID_NIC_22_3] = GAUDI2_ENGINE_ID_NIC11_0,
+ [GAUDI2_QUEUE_ID_NIC_23_0...GAUDI2_QUEUE_ID_NIC_23_3] = GAUDI2_ENGINE_ID_NIC11_1,
+ [GAUDI2_QUEUE_ID_ROT_0_0...GAUDI2_QUEUE_ID_ROT_0_3] = GAUDI2_ENGINE_ID_ROT_0,
+ [GAUDI2_QUEUE_ID_ROT_1_0...GAUDI2_QUEUE_ID_ROT_1_3] = GAUDI2_ENGINE_ID_ROT_1,
+};
+
const u32 gaudi2_qm_blocks_bases[GAUDI2_QUEUE_ID_SIZE] = {
[GAUDI2_QUEUE_ID_PDMA_0_0] = mmPDMA0_QM_BASE,
[GAUDI2_QUEUE_ID_PDMA_0_1] = mmPDMA0_QM_BASE,
@@ -2001,7 +2097,8 @@ enum razwi_event_sources {
RAZWI_PDMA,
RAZWI_NIC,
RAZWI_DEC,
- RAZWI_ROT
+ RAZWI_ROT,
+ RAZWI_ARC_FARM
};
struct hbm_mc_error_causes {
@@ -2431,7 +2528,7 @@ static int gaudi2_set_fixed_properties(struct hl_device *hdev)
prop->pcie_dbi_base_address = CFG_BASE + mmPCIE_DBI_BASE;
prop->pcie_aux_dbi_reg_addr = CFG_BASE + mmPCIE_AUX_DBI;
- strncpy(prop->cpucp_info.card_name, GAUDI2_DEFAULT_CARD_NAME, CARD_NAME_MAX_LEN);
+ strscpy_pad(prop->cpucp_info.card_name, GAUDI2_DEFAULT_CARD_NAME, CARD_NAME_MAX_LEN);
prop->mme_master_slave_mode = 1;
@@ -2884,7 +2981,8 @@ static int gaudi2_cpucp_info_get(struct hl_device *hdev)
}
if (!strlen(prop->cpucp_info.card_name))
- strncpy(prop->cpucp_info.card_name, GAUDI2_DEFAULT_CARD_NAME, CARD_NAME_MAX_LEN);
+ strscpy_pad(prop->cpucp_info.card_name, GAUDI2_DEFAULT_CARD_NAME,
+ CARD_NAME_MAX_LEN);
/* Overwrite binning masks with the actual binning values from F/W */
hdev->dram_binning = prop->cpucp_info.dram_binning_mask;
@@ -4077,6 +4175,8 @@ static const char *gaudi2_irq_name(u16 irq_number)
return "gaudi2 unexpected error";
case GAUDI2_IRQ_NUM_USER_FIRST ... GAUDI2_IRQ_NUM_USER_LAST:
return "gaudi2 user completion";
+ case GAUDI2_IRQ_NUM_EQ_ERROR:
+ return "gaudi2 eq error";
default:
return "invalid";
}
@@ -4127,9 +4227,7 @@ static int gaudi2_dec_enable_msix(struct hl_device *hdev)
rc = request_irq(irq, hl_irq_handler_dec_abnrm, 0,
gaudi2_irq_name(i), (void *) dec);
} else {
- rc = request_threaded_irq(irq, hl_irq_handler_user_interrupt,
- hl_irq_user_interrupt_thread_handler, IRQF_ONESHOT,
- gaudi2_irq_name(i),
+ rc = request_irq(irq, hl_irq_user_interrupt_handler, 0, gaudi2_irq_name(i),
(void *) &hdev->user_interrupt[dec->core_id]);
}
@@ -4187,17 +4285,17 @@ static int gaudi2_enable_msix(struct hl_device *hdev)
}
irq = pci_irq_vector(hdev->pdev, GAUDI2_IRQ_NUM_TPC_ASSERT);
- rc = request_threaded_irq(irq, hl_irq_handler_user_interrupt,
- hl_irq_user_interrupt_thread_handler, IRQF_ONESHOT,
- gaudi2_irq_name(GAUDI2_IRQ_NUM_TPC_ASSERT), &hdev->tpc_interrupt);
+ rc = request_threaded_irq(irq, NULL, hl_irq_user_interrupt_thread_handler, IRQF_ONESHOT,
+ gaudi2_irq_name(GAUDI2_IRQ_NUM_TPC_ASSERT),
+ &hdev->tpc_interrupt);
if (rc) {
dev_err(hdev->dev, "Failed to request IRQ %d", irq);
goto free_dec_irq;
}
irq = pci_irq_vector(hdev->pdev, GAUDI2_IRQ_NUM_UNEXPECTED_ERROR);
- rc = request_irq(irq, hl_irq_handler_user_interrupt, 0,
- gaudi2_irq_name(GAUDI2_IRQ_NUM_UNEXPECTED_ERROR),
+ rc = request_threaded_irq(irq, NULL, hl_irq_user_interrupt_thread_handler, IRQF_ONESHOT,
+ gaudi2_irq_name(GAUDI2_IRQ_NUM_UNEXPECTED_ERROR),
&hdev->unexpected_error_interrupt);
if (rc) {
dev_err(hdev->dev, "Failed to request IRQ %d", irq);
@@ -4209,16 +4307,23 @@ static int gaudi2_enable_msix(struct hl_device *hdev)
i++, j++, user_irq_init_cnt++) {
irq = pci_irq_vector(hdev->pdev, i);
- rc = request_threaded_irq(irq, hl_irq_handler_user_interrupt,
- hl_irq_user_interrupt_thread_handler, IRQF_ONESHOT,
- gaudi2_irq_name(i), &hdev->user_interrupt[j]);
-
+ rc = request_irq(irq, hl_irq_user_interrupt_handler, 0, gaudi2_irq_name(i),
+ &hdev->user_interrupt[j]);
if (rc) {
dev_err(hdev->dev, "Failed to request IRQ %d", irq);
goto free_user_irq;
}
}
+ irq = pci_irq_vector(hdev->pdev, GAUDI2_IRQ_NUM_EQ_ERROR);
+ rc = request_threaded_irq(irq, NULL, hl_irq_eq_error_interrupt_thread_handler,
+ IRQF_ONESHOT, gaudi2_irq_name(GAUDI2_IRQ_NUM_EQ_ERROR),
+ hdev);
+ if (rc) {
+ dev_err(hdev->dev, "Failed to request IRQ %d", irq);
+ goto free_user_irq;
+ }
+
gaudi2->hw_cap_initialized |= HW_CAP_MSIX;
return 0;
@@ -4278,6 +4383,7 @@ static void gaudi2_sync_irqs(struct hl_device *hdev)
}
synchronize_irq(pci_irq_vector(hdev->pdev, GAUDI2_IRQ_NUM_EVENT_QUEUE));
+ synchronize_irq(pci_irq_vector(hdev->pdev, GAUDI2_IRQ_NUM_EQ_ERROR));
}
static void gaudi2_disable_msix(struct hl_device *hdev)
@@ -4314,6 +4420,9 @@ static void gaudi2_disable_msix(struct hl_device *hdev)
cq = &hdev->completion_queue[GAUDI2_RESERVED_CQ_CS_COMPLETION];
free_irq(irq, cq);
+ irq = pci_irq_vector(hdev->pdev, GAUDI2_IRQ_NUM_EQ_ERROR);
+ free_irq(irq, hdev);
+
pci_free_irq_vectors(hdev->pdev);
gaudi2->hw_cap_initialized &= ~HW_CAP_MSIX;
@@ -4716,6 +4825,8 @@ static void gaudi2_init_firmware_preload_params(struct hl_device *hdev)
pre_fw_load->boot_err0_reg = mmCPU_BOOT_ERR0;
pre_fw_load->boot_err1_reg = mmCPU_BOOT_ERR1;
pre_fw_load->wait_for_preboot_timeout = GAUDI2_PREBOOT_REQ_TIMEOUT_USEC;
+ pre_fw_load->wait_for_preboot_extended_timeout =
+ GAUDI2_PREBOOT_EXTENDED_REQ_TIMEOUT_USEC;
}
static void gaudi2_init_firmware_loader(struct hl_device *hdev)
@@ -6157,17 +6268,14 @@ static int gaudi2_get_soft_rst_done_indication(struct hl_device *hdev, u32 poll_
static int gaudi2_execute_soft_reset(struct hl_device *hdev, bool driver_performs_reset,
u32 poll_timeout_us)
{
- struct cpu_dyn_regs *dyn_regs = &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs;
- int rc = 0;
+ int rc;
if (!driver_performs_reset) {
if (hl_is_fw_sw_ver_below(hdev, 1, 10)) {
/* set SP to indicate reset request sent to FW */
- if (dyn_regs->cpu_rst_status)
- WREG32(le32_to_cpu(dyn_regs->cpu_rst_status), CPU_RST_STATUS_NA);
- else
- WREG32(mmCPU_RST_STATUS_TO_HOST, CPU_RST_STATUS_NA);
- WREG32(le32_to_cpu(dyn_regs->gic_host_soft_rst_irq),
+ WREG32(mmCPU_RST_STATUS_TO_HOST, CPU_RST_STATUS_NA);
+
+ WREG32(mmGIC_HOST_SOFT_RST_IRQ_POLL_REG,
gaudi2_irq_map_table[GAUDI2_EVENT_CPU_SOFT_RESET].cpu_id);
/* wait for f/w response */
@@ -6623,24 +6731,6 @@ static void gaudi2_cpu_accessible_dma_pool_free(struct hl_device *hdev, size_t s
hl_fw_cpu_accessible_dma_pool_free(hdev, size, vaddr);
}
-static dma_addr_t gaudi2_dma_map_single(struct hl_device *hdev, void *addr, int len,
- enum dma_data_direction dir)
-{
- dma_addr_t dma_addr;
-
- dma_addr = dma_map_single(&hdev->pdev->dev, addr, len, dir);
- if (unlikely(dma_mapping_error(&hdev->pdev->dev, dma_addr)))
- return 0;
-
- return dma_addr;
-}
-
-static void gaudi2_dma_unmap_single(struct hl_device *hdev, dma_addr_t addr, int len,
- enum dma_data_direction dir)
-{
- dma_unmap_single(&hdev->pdev->dev, addr, len, dir);
-}
-
static int gaudi2_validate_cb_address(struct hl_device *hdev, struct hl_cs_parser *parser)
{
struct asic_fixed_properties *asic_prop = &hdev->asic_prop;
@@ -7703,11 +7793,13 @@ static inline bool is_info_event(u32 event)
switch (event) {
case GAUDI2_EVENT_CPU_CPLD_SHUTDOWN_CAUSE:
case GAUDI2_EVENT_CPU_FIX_POWER_ENV_S ... GAUDI2_EVENT_CPU_FIX_THERMAL_ENV_E:
+ case GAUDI2_EVENT_ARC_PWR_BRK_ENTRY ... GAUDI2_EVENT_ARC_PWR_RD_MODE3:
/* return in case of NIC status event - these events are received periodically and not as
* an indication to an error.
*/
case GAUDI2_EVENT_CPU0_STATUS_NIC0_ENG0 ... GAUDI2_EVENT_CPU11_STATUS_NIC11_ENG1:
+ case GAUDI2_EVENT_ARC_EQ_HEARTBEAT:
return true;
default:
return false;
@@ -7739,21 +7831,34 @@ static void gaudi2_print_event(struct hl_device *hdev, u16 event_type,
static bool gaudi2_handle_ecc_event(struct hl_device *hdev, u16 event_type,
struct hl_eq_ecc_data *ecc_data)
{
- u64 ecc_address = 0, ecc_syndrom = 0;
+ u64 ecc_address = 0, ecc_syndrome = 0;
u8 memory_wrapper_idx = 0;
+ bool has_block_id = false;
+ u16 block_id;
+
+ if (!hl_is_fw_sw_ver_below(hdev, 1, 12))
+ has_block_id = true;
ecc_address = le64_to_cpu(ecc_data->ecc_address);
- ecc_syndrom = le64_to_cpu(ecc_data->ecc_syndrom);
+ ecc_syndrome = le64_to_cpu(ecc_data->ecc_syndrom);
memory_wrapper_idx = ecc_data->memory_wrapper_idx;
- gaudi2_print_event(hdev, event_type, !ecc_data->is_critical,
- "ECC error detected. address: %#llx. Syndrom: %#llx. block id %u. critical %u.",
- ecc_address, ecc_syndrom, memory_wrapper_idx, ecc_data->is_critical);
+ if (has_block_id) {
+ block_id = le16_to_cpu(ecc_data->block_id);
+ gaudi2_print_event(hdev, event_type, !ecc_data->is_critical,
+ "ECC error detected. address: %#llx. Syndrome: %#llx. wrapper id %u. block id %#x. critical %u.",
+ ecc_address, ecc_syndrome, memory_wrapper_idx, block_id,
+ ecc_data->is_critical);
+ } else {
+ gaudi2_print_event(hdev, event_type, !ecc_data->is_critical,
+ "ECC error detected. address: %#llx. Syndrome: %#llx. wrapper id %u. critical %u.",
+ ecc_address, ecc_syndrome, memory_wrapper_idx, ecc_data->is_critical);
+ }
return !!ecc_data->is_critical;
}
-static void print_lower_qman_data_on_err(struct hl_device *hdev, u64 qman_base)
+static void handle_lower_qman_data_on_err(struct hl_device *hdev, u64 qman_base, u64 event_mask)
{
u32 lo, hi, cq_ptr_size, arc_cq_ptr_size;
u64 cq_ptr, arc_cq_ptr, cp_current_inst;
@@ -7775,10 +7880,22 @@ static void print_lower_qman_data_on_err(struct hl_device *hdev, u64 qman_base)
dev_info(hdev->dev,
"LowerQM. CQ: {ptr %#llx, size %u}, ARC_CQ: {ptr %#llx, size %u}, CP: {instruction %#llx}\n",
cq_ptr, cq_ptr_size, arc_cq_ptr, arc_cq_ptr_size, cp_current_inst);
+
+ if (event_mask & HL_NOTIFIER_EVENT_UNDEFINED_OPCODE) {
+ if (arc_cq_ptr) {
+ hdev->captured_err_info.undef_opcode.cq_addr = arc_cq_ptr;
+ hdev->captured_err_info.undef_opcode.cq_size = arc_cq_ptr_size;
+ } else {
+ hdev->captured_err_info.undef_opcode.cq_addr = cq_ptr;
+ hdev->captured_err_info.undef_opcode.cq_size = cq_ptr_size;
+ }
+
+ hdev->captured_err_info.undef_opcode.stream_id = QMAN_STREAMS;
+ }
}
static int gaudi2_handle_qman_err_generic(struct hl_device *hdev, u16 event_type,
- u64 qman_base, u32 qid_base)
+ u64 qman_base, u32 qid_base, u64 *event_mask)
{
u32 i, j, glbl_sts_val, arb_err_val, num_error_causes, error_count = 0;
u64 glbl_sts_addr, arb_err_addr;
@@ -7812,8 +7929,22 @@ static int gaudi2_handle_qman_err_generic(struct hl_device *hdev, u16 event_type
error_count++;
}
- if (i == QMAN_STREAMS)
- print_lower_qman_data_on_err(hdev, qman_base);
+ if (i == QMAN_STREAMS && error_count) {
+ /* check for undefined opcode */
+ if (glbl_sts_val & PDMA0_QM_GLBL_ERR_STS_CP_UNDEF_CMD_ERR_MASK &&
+ hdev->captured_err_info.undef_opcode.write_enable) {
+ memset(&hdev->captured_err_info.undef_opcode, 0,
+ sizeof(hdev->captured_err_info.undef_opcode));
+
+ hdev->captured_err_info.undef_opcode.write_enable = false;
+ hdev->captured_err_info.undef_opcode.timestamp = ktime_get();
+ hdev->captured_err_info.undef_opcode.engine_id =
+ gaudi2_queue_id_to_engine_id[qid_base];
+ *event_mask |= HL_NOTIFIER_EVENT_UNDEFINED_OPCODE;
+ }
+
+ handle_lower_qman_data_on_err(hdev, qman_base, *event_mask);
+ }
}
arb_err_val = RREG32(arb_err_addr);
@@ -7927,6 +8058,9 @@ static enum gaudi2_engine_id gaudi2_razwi_calc_engine_id(struct hl_device *hdev,
case RAZWI_ROT:
return GAUDI2_ENGINE_ID_ROT_0 + module_idx;
+ case RAZWI_ARC_FARM:
+ return GAUDI2_ENGINE_ID_ARC_FARM;
+
default:
return GAUDI2_ENGINE_ID_SIZE;
}
@@ -8036,6 +8170,11 @@ static void gaudi2_ack_module_razwi_event_handler(struct hl_device *hdev,
lbw_rtr_id = gaudi2_rot_initiator_lbw_rtr_id[module_idx];
sprintf(initiator_name, "ROT_%u", module_idx);
break;
+ case RAZWI_ARC_FARM:
+ lbw_rtr_id = DCORE1_RTR5;
+ hbw_rtr_id = DCORE1_RTR7;
+ sprintf(initiator_name, "ARC_FARM_%u", module_idx);
+ break;
default:
return;
}
@@ -8149,11 +8288,11 @@ static int gaudi2_psoc_razwi_get_engines(struct gaudi2_razwi_info *razwi_info, u
eng_id[num_of_eng] = razwi_info[i].eng_id;
base[num_of_eng] = razwi_info[i].rtr_ctrl;
if (!num_of_eng)
- str_size += snprintf(eng_name + str_size,
+ str_size += scnprintf(eng_name + str_size,
PSOC_RAZWI_ENG_STR_SIZE - str_size, "%s",
razwi_info[i].eng_name);
else
- str_size += snprintf(eng_name + str_size,
+ str_size += scnprintf(eng_name + str_size,
PSOC_RAZWI_ENG_STR_SIZE - str_size, " or %s",
razwi_info[i].eng_name);
num_of_eng++;
@@ -8475,7 +8614,8 @@ static int gaudi2_handle_qman_err(struct hl_device *hdev, u16 event_type, u64 *e
return 0;
}
- error_count = gaudi2_handle_qman_err_generic(hdev, event_type, qman_base, qid_base);
+ error_count = gaudi2_handle_qman_err_generic(hdev, event_type, qman_base,
+ qid_base, event_mask);
/* Handle EDMA QM SEI here because there is no AXI error response event for EDMA */
if (event_type >= GAUDI2_EVENT_HDMA2_QM && event_type <= GAUDI2_EVENT_HDMA5_QM) {
@@ -8488,7 +8628,7 @@ static int gaudi2_handle_qman_err(struct hl_device *hdev, u16 event_type, u64 *e
return error_count;
}
-static int gaudi2_handle_arc_farm_sei_err(struct hl_device *hdev, u16 event_type)
+static int gaudi2_handle_arc_farm_sei_err(struct hl_device *hdev, u16 event_type, u64 *event_mask)
{
u32 i, sts_val, sts_clr_val, error_count = 0, arc_farm;
@@ -8510,6 +8650,7 @@ static int gaudi2_handle_arc_farm_sei_err(struct hl_device *hdev, u16 event_type
sts_clr_val);
}
+ gaudi2_ack_module_razwi_event_handler(hdev, RAZWI_ARC_FARM, 0, 0, event_mask);
hl_check_for_glbl_errors(hdev);
return error_count;
@@ -8649,21 +8790,16 @@ static int gaudi2_handle_mme_err(struct hl_device *hdev, u8 mme_index, u16 event
return error_count;
}
-static int gaudi2_handle_mme_sbte_err(struct hl_device *hdev, u16 event_type,
- u64 intr_cause_data)
+static int gaudi2_handle_mme_sbte_err(struct hl_device *hdev, u16 event_type)
{
- int i, error_count = 0;
-
- for (i = 0 ; i < GAUDI2_NUM_OF_MME_SBTE_ERR_CAUSE ; i++)
- if (intr_cause_data & BIT(i)) {
- gaudi2_print_event(hdev, event_type, true,
- "err cause: %s", guadi2_mme_sbte_error_cause[i]);
- error_count++;
- }
-
+ /*
+ * We have a single error cause here but the report mechanism is
+ * buggy. Hence there is no good reason to fetch the cause so we
+ * just check for glbl_errors and exit.
+ */
hl_check_for_glbl_errors(hdev);
- return error_count;
+ return GAUDI2_NA_EVENT_CAUSE;
}
static int gaudi2_handle_mme_wap_err(struct hl_device *hdev, u8 mme_index, u16 event_type,
@@ -9460,6 +9596,176 @@ static int hl_arc_event_handle(struct hl_device *hdev, u16 event_type,
}
}
+static u16 event_id_to_engine_id(struct hl_device *hdev, u16 event_type)
+{
+ enum gaudi2_block_types type = GAUDI2_BLOCK_TYPE_MAX;
+ u16 index;
+
+ switch (event_type) {
+ case GAUDI2_EVENT_TPC0_AXI_ERR_RSP ... GAUDI2_EVENT_TPC24_AXI_ERR_RSP:
+ index = event_type - GAUDI2_EVENT_TPC0_AXI_ERR_RSP;
+ type = GAUDI2_BLOCK_TYPE_TPC;
+ break;
+ case GAUDI2_EVENT_TPC0_QM ... GAUDI2_EVENT_TPC24_QM:
+ index = event_type - GAUDI2_EVENT_TPC0_QM;
+ type = GAUDI2_BLOCK_TYPE_TPC;
+ break;
+ case GAUDI2_EVENT_MME0_SBTE0_AXI_ERR_RSP ... GAUDI2_EVENT_MME0_CTRL_AXI_ERROR_RESPONSE:
+ case GAUDI2_EVENT_MME0_SPI_BASE ... GAUDI2_EVENT_MME0_WAP_SOURCE_RESULT_INVALID:
+ case GAUDI2_EVENT_MME0_QM:
+ index = 0;
+ type = GAUDI2_BLOCK_TYPE_MME;
+ break;
+ case GAUDI2_EVENT_MME1_SBTE0_AXI_ERR_RSP ... GAUDI2_EVENT_MME1_CTRL_AXI_ERROR_RESPONSE:
+ case GAUDI2_EVENT_MME1_SPI_BASE ... GAUDI2_EVENT_MME1_WAP_SOURCE_RESULT_INVALID:
+ case GAUDI2_EVENT_MME1_QM:
+ index = 1;
+ type = GAUDI2_BLOCK_TYPE_MME;
+ break;
+ case GAUDI2_EVENT_MME2_SBTE0_AXI_ERR_RSP ... GAUDI2_EVENT_MME2_CTRL_AXI_ERROR_RESPONSE:
+ case GAUDI2_EVENT_MME2_SPI_BASE ... GAUDI2_EVENT_MME2_WAP_SOURCE_RESULT_INVALID:
+ case GAUDI2_EVENT_MME2_QM:
+ index = 2;
+ type = GAUDI2_BLOCK_TYPE_MME;
+ break;
+ case GAUDI2_EVENT_MME3_SBTE0_AXI_ERR_RSP ... GAUDI2_EVENT_MME3_CTRL_AXI_ERROR_RESPONSE:
+ case GAUDI2_EVENT_MME3_SPI_BASE ... GAUDI2_EVENT_MME3_WAP_SOURCE_RESULT_INVALID:
+ case GAUDI2_EVENT_MME3_QM:
+ index = 3;
+ type = GAUDI2_BLOCK_TYPE_MME;
+ break;
+ case GAUDI2_EVENT_KDMA_CH0_AXI_ERR_RSP:
+ case GAUDI2_EVENT_KDMA_BM_SPMU:
+ case GAUDI2_EVENT_KDMA0_CORE:
+ return GAUDI2_ENGINE_ID_KDMA;
+ case GAUDI2_EVENT_PDMA_CH0_AXI_ERR_RSP:
+ case GAUDI2_EVENT_PDMA0_CORE:
+ case GAUDI2_EVENT_PDMA0_BM_SPMU:
+ case GAUDI2_EVENT_PDMA0_QM:
+ return GAUDI2_ENGINE_ID_PDMA_0;
+ case GAUDI2_EVENT_PDMA_CH1_AXI_ERR_RSP:
+ case GAUDI2_EVENT_PDMA1_CORE:
+ case GAUDI2_EVENT_PDMA1_BM_SPMU:
+ case GAUDI2_EVENT_PDMA1_QM:
+ return GAUDI2_ENGINE_ID_PDMA_1;
+ case GAUDI2_EVENT_DEC0_AXI_ERR_RSPONSE ... GAUDI2_EVENT_DEC9_AXI_ERR_RSPONSE:
+ index = event_type - GAUDI2_EVENT_DEC0_AXI_ERR_RSPONSE;
+ type = GAUDI2_BLOCK_TYPE_DEC;
+ break;
+ case GAUDI2_EVENT_DEC0_SPI ... GAUDI2_EVENT_DEC9_BMON_SPMU:
+ index = (event_type - GAUDI2_EVENT_DEC0_SPI) >> 1;
+ type = GAUDI2_BLOCK_TYPE_DEC;
+ break;
+ case GAUDI2_EVENT_NIC0_AXI_ERROR_RESPONSE ... GAUDI2_EVENT_NIC11_AXI_ERROR_RESPONSE:
+ index = event_type - GAUDI2_EVENT_NIC0_AXI_ERROR_RESPONSE;
+ return GAUDI2_ENGINE_ID_NIC0_0 + (index * 2);
+ case GAUDI2_EVENT_NIC0_QM0 ... GAUDI2_EVENT_NIC11_QM1:
+ index = event_type - GAUDI2_EVENT_NIC0_QM0;
+ return GAUDI2_ENGINE_ID_NIC0_0 + index;
+ case GAUDI2_EVENT_NIC0_BMON_SPMU ... GAUDI2_EVENT_NIC11_SW_ERROR:
+ index = event_type - GAUDI2_EVENT_NIC0_BMON_SPMU;
+ return GAUDI2_ENGINE_ID_NIC0_0 + (index * 2);
+ case GAUDI2_EVENT_TPC0_BMON_SPMU ... GAUDI2_EVENT_TPC24_KERNEL_ERR:
+ index = (event_type - GAUDI2_EVENT_TPC0_BMON_SPMU) >> 1;
+ type = GAUDI2_BLOCK_TYPE_TPC;
+ break;
+ case GAUDI2_EVENT_ROTATOR0_AXI_ERROR_RESPONSE:
+ case GAUDI2_EVENT_ROTATOR0_BMON_SPMU:
+ case GAUDI2_EVENT_ROTATOR0_ROT0_QM:
+ return GAUDI2_ENGINE_ID_ROT_0;
+ case GAUDI2_EVENT_ROTATOR1_AXI_ERROR_RESPONSE:
+ case GAUDI2_EVENT_ROTATOR1_BMON_SPMU:
+ case GAUDI2_EVENT_ROTATOR1_ROT1_QM:
+ return GAUDI2_ENGINE_ID_ROT_1;
+ case GAUDI2_EVENT_HDMA0_BM_SPMU:
+ case GAUDI2_EVENT_HDMA0_QM:
+ case GAUDI2_EVENT_HDMA0_CORE:
+ return GAUDI2_DCORE0_ENGINE_ID_EDMA_0;
+ case GAUDI2_EVENT_HDMA1_BM_SPMU:
+ case GAUDI2_EVENT_HDMA1_QM:
+ case GAUDI2_EVENT_HDMA1_CORE:
+ return GAUDI2_DCORE0_ENGINE_ID_EDMA_1;
+ case GAUDI2_EVENT_HDMA2_BM_SPMU:
+ case GAUDI2_EVENT_HDMA2_QM:
+ case GAUDI2_EVENT_HDMA2_CORE:
+ return GAUDI2_DCORE1_ENGINE_ID_EDMA_0;
+ case GAUDI2_EVENT_HDMA3_BM_SPMU:
+ case GAUDI2_EVENT_HDMA3_QM:
+ case GAUDI2_EVENT_HDMA3_CORE:
+ return GAUDI2_DCORE1_ENGINE_ID_EDMA_1;
+ case GAUDI2_EVENT_HDMA4_BM_SPMU:
+ case GAUDI2_EVENT_HDMA4_QM:
+ case GAUDI2_EVENT_HDMA4_CORE:
+ return GAUDI2_DCORE2_ENGINE_ID_EDMA_0;
+ case GAUDI2_EVENT_HDMA5_BM_SPMU:
+ case GAUDI2_EVENT_HDMA5_QM:
+ case GAUDI2_EVENT_HDMA5_CORE:
+ return GAUDI2_DCORE2_ENGINE_ID_EDMA_1;
+ case GAUDI2_EVENT_HDMA6_BM_SPMU:
+ case GAUDI2_EVENT_HDMA6_QM:
+ case GAUDI2_EVENT_HDMA6_CORE:
+ return GAUDI2_DCORE3_ENGINE_ID_EDMA_0;
+ case GAUDI2_EVENT_HDMA7_BM_SPMU:
+ case GAUDI2_EVENT_HDMA7_QM:
+ case GAUDI2_EVENT_HDMA7_CORE:
+ return GAUDI2_DCORE3_ENGINE_ID_EDMA_1;
+ default:
+ break;
+ }
+
+ switch (type) {
+ case GAUDI2_BLOCK_TYPE_TPC:
+ switch (index) {
+ case TPC_ID_DCORE0_TPC0 ... TPC_ID_DCORE0_TPC5:
+ return GAUDI2_DCORE0_ENGINE_ID_TPC_0 + index;
+ case TPC_ID_DCORE1_TPC0 ... TPC_ID_DCORE1_TPC5:
+ return GAUDI2_DCORE1_ENGINE_ID_TPC_0 + index - TPC_ID_DCORE1_TPC0;
+ case TPC_ID_DCORE2_TPC0 ... TPC_ID_DCORE2_TPC5:
+ return GAUDI2_DCORE2_ENGINE_ID_TPC_0 + index - TPC_ID_DCORE2_TPC0;
+ case TPC_ID_DCORE3_TPC0 ... TPC_ID_DCORE3_TPC5:
+ return GAUDI2_DCORE3_ENGINE_ID_TPC_0 + index - TPC_ID_DCORE3_TPC0;
+ default:
+ break;
+ }
+ break;
+ case GAUDI2_BLOCK_TYPE_MME:
+ switch (index) {
+ case MME_ID_DCORE0: return GAUDI2_DCORE0_ENGINE_ID_MME;
+ case MME_ID_DCORE1: return GAUDI2_DCORE1_ENGINE_ID_MME;
+ case MME_ID_DCORE2: return GAUDI2_DCORE2_ENGINE_ID_MME;
+ case MME_ID_DCORE3: return GAUDI2_DCORE3_ENGINE_ID_MME;
+ default:
+ break;
+ }
+ break;
+ case GAUDI2_BLOCK_TYPE_DEC:
+ switch (index) {
+ case DEC_ID_DCORE0_DEC0: return GAUDI2_DCORE0_ENGINE_ID_DEC_0;
+ case DEC_ID_DCORE0_DEC1: return GAUDI2_DCORE0_ENGINE_ID_DEC_1;
+ case DEC_ID_DCORE1_DEC0: return GAUDI2_DCORE1_ENGINE_ID_DEC_0;
+ case DEC_ID_DCORE1_DEC1: return GAUDI2_DCORE1_ENGINE_ID_DEC_1;
+ case DEC_ID_DCORE2_DEC0: return GAUDI2_DCORE2_ENGINE_ID_DEC_0;
+ case DEC_ID_DCORE2_DEC1: return GAUDI2_DCORE2_ENGINE_ID_DEC_1;
+ case DEC_ID_DCORE3_DEC0: return GAUDI2_DCORE3_ENGINE_ID_DEC_0;
+ case DEC_ID_DCORE3_DEC1: return GAUDI2_DCORE3_ENGINE_ID_DEC_1;
+ case DEC_ID_PCIE_VDEC0: return GAUDI2_PCIE_ENGINE_ID_DEC_0;
+ case DEC_ID_PCIE_VDEC1: return GAUDI2_PCIE_ENGINE_ID_DEC_1;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return U16_MAX;
+}
+
+static void hl_eq_heartbeat_event_handle(struct hl_device *hdev)
+{
+ hdev->eq_heartbeat_received = true;
+}
+
static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_entry)
{
struct gaudi2_device *gaudi2 = hdev->asic_specific;
@@ -9501,7 +9807,7 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent
break;
case GAUDI2_EVENT_ARC_AXI_ERROR_RESPONSE_0:
- error_count = gaudi2_handle_arc_farm_sei_err(hdev, event_type);
+ error_count = gaudi2_handle_arc_farm_sei_err(hdev, event_type, &event_mask);
event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR;
break;
@@ -9724,8 +10030,7 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent
case GAUDI2_EVENT_MME1_SBTE0_AXI_ERR_RSP ... GAUDI2_EVENT_MME1_SBTE4_AXI_ERR_RSP:
case GAUDI2_EVENT_MME2_SBTE0_AXI_ERR_RSP ... GAUDI2_EVENT_MME2_SBTE4_AXI_ERR_RSP:
case GAUDI2_EVENT_MME3_SBTE0_AXI_ERR_RSP ... GAUDI2_EVENT_MME3_SBTE4_AXI_ERR_RSP:
- error_count = gaudi2_handle_mme_sbte_err(hdev, event_type,
- le64_to_cpu(eq_entry->intr_cause.intr_cause_data));
+ error_count = gaudi2_handle_mme_sbte_err(hdev, event_type);
event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR;
break;
case GAUDI2_EVENT_VM0_ALARM_A ... GAUDI2_EVENT_VM3_ALARM_B:
@@ -9875,6 +10180,21 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent
is_critical = true;
break;
+ case GAUDI2_EVENT_ARC_PWR_BRK_ENTRY:
+ case GAUDI2_EVENT_ARC_PWR_BRK_EXT:
+ case GAUDI2_EVENT_ARC_PWR_RD_MODE0:
+ case GAUDI2_EVENT_ARC_PWR_RD_MODE1:
+ case GAUDI2_EVENT_ARC_PWR_RD_MODE2:
+ case GAUDI2_EVENT_ARC_PWR_RD_MODE3:
+ error_count = GAUDI2_NA_EVENT_CAUSE;
+ dev_info_ratelimited(hdev->dev, "%s event received\n",
+ gaudi2_irq_map_table[event_type].name);
+ break;
+
+ case GAUDI2_EVENT_ARC_EQ_HEARTBEAT:
+ hl_eq_heartbeat_event_handle(hdev);
+ error_count = GAUDI2_NA_EVENT_CAUSE;
+ break;
default:
if (gaudi2_irq_map_table[event_type].valid) {
dev_err_ratelimited(hdev->dev, "Cannot find handler for event %d\n",
@@ -9883,6 +10203,9 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent
}
}
+ if (event_mask & HL_NOTIFIER_EVENT_USER_ENGINE_ERR)
+ hl_capture_engine_err(hdev, event_id_to_engine_id(hdev, event_type), error_count);
+
/* Make sure to dump an error in case no error cause was printed so far.
* Note that although we have counted the errors, we use this number as
* a boolean.
@@ -10523,6 +10846,9 @@ static int gaudi2_ctx_init(struct hl_ctx *ctx)
{
int rc;
+ if (ctx->asid == HL_KERNEL_ASID_ID)
+ return 0;
+
rc = gaudi2_mmu_prepare(ctx->hdev, ctx->asid);
if (rc)
return rc;
@@ -11014,6 +11340,7 @@ static int gaudi2_ack_mmu_page_fault_or_access_error(struct hl_device *hdev, u64
static void gaudi2_get_msi_info(__le32 *table)
{
table[CPUCP_EVENT_QUEUE_MSI_TYPE] = cpu_to_le32(GAUDI2_EVENT_QUEUE_MSIX_IDX);
+ table[CPUCP_EVENT_QUEUE_ERR_MSI_TYPE] = cpu_to_le32(GAUDI2_IRQ_NUM_EQ_ERROR);
}
static int gaudi2_map_pll_idx_to_fw_idx(u32 pll_idx)
@@ -11170,11 +11497,9 @@ static const struct hl_asic_funcs gaudi2_funcs = {
.asic_dma_pool_free = gaudi2_dma_pool_free,
.cpu_accessible_dma_pool_alloc = gaudi2_cpu_accessible_dma_pool_alloc,
.cpu_accessible_dma_pool_free = gaudi2_cpu_accessible_dma_pool_free,
- .asic_dma_unmap_single = gaudi2_dma_unmap_single,
- .asic_dma_map_single = gaudi2_dma_map_single,
- .hl_dma_unmap_sgtable = hl_dma_unmap_sgtable,
+ .dma_unmap_sgtable = hl_asic_dma_unmap_sgtable,
.cs_parser = gaudi2_cs_parser,
- .asic_dma_map_sgtable = hl_dma_map_sgtable,
+ .dma_map_sgtable = hl_asic_dma_map_sgtable,
.add_end_of_cb_packets = NULL,
.update_eq_ci = gaudi2_update_eq_ci,
.context_switch = gaudi2_context_switch,
diff --git a/drivers/accel/habanalabs/gaudi2/gaudi2P.h b/drivers/accel/habanalabs/gaudi2/gaudi2P.h
index 5f3ce086928e..9b9eef0d97d6 100644
--- a/drivers/accel/habanalabs/gaudi2/gaudi2P.h
+++ b/drivers/accel/habanalabs/gaudi2/gaudi2P.h
@@ -10,7 +10,7 @@
#include <uapi/drm/habanalabs_accel.h>
#include "../common/habanalabs.h"
-#include "../include/common/hl_boot_if.h"
+#include <linux/habanalabs/hl_boot_if.h>
#include "../include/gaudi2/gaudi2.h"
#include "../include/gaudi2/gaudi2_packets.h"
#include "../include/gaudi2/gaudi2_fw_if.h"
@@ -84,6 +84,7 @@
#define CORESIGHT_TIMEOUT_USEC 100000 /* 100 ms */
#define GAUDI2_PREBOOT_REQ_TIMEOUT_USEC 25000000 /* 25s */
+#define GAUDI2_PREBOOT_EXTENDED_REQ_TIMEOUT_USEC 85000000 /* 85s */
#define GAUDI2_BOOT_FIT_REQ_TIMEOUT_USEC 10000000 /* 10s */
@@ -419,6 +420,7 @@ enum gaudi2_irq_num {
GAUDI2_IRQ_NUM_NIC_PORT_FIRST,
GAUDI2_IRQ_NUM_NIC_PORT_LAST = (GAUDI2_IRQ_NUM_NIC_PORT_FIRST + NIC_NUMBER_OF_PORTS - 1),
GAUDI2_IRQ_NUM_TPC_ASSERT,
+ GAUDI2_IRQ_NUM_EQ_ERROR,
GAUDI2_IRQ_NUM_RESERVED_FIRST,
GAUDI2_IRQ_NUM_RESERVED_LAST = (GAUDI2_MSIX_ENTRIES - GAUDI2_TOTAL_USER_INTERRUPTS - 1),
GAUDI2_IRQ_NUM_UNEXPECTED_ERROR = RESERVED_MSIX_UNEXPECTED_USER_ERROR_INTERRUPT,
diff --git a/drivers/accel/habanalabs/gaudi2/gaudi2_coresight.c b/drivers/accel/habanalabs/gaudi2/gaudi2_coresight.c
index 25b5368f37dd..2423620ff358 100644
--- a/drivers/accel/habanalabs/gaudi2/gaudi2_coresight.c
+++ b/drivers/accel/habanalabs/gaudi2/gaudi2_coresight.c
@@ -151,8 +151,8 @@ static u64 debug_stm_regs[GAUDI2_STM_LAST + 1] = {
[GAUDI2_STM_DCORE3_VDEC1_CS] = mmDCORE3_VDEC1_CS_STM_BASE,
[GAUDI2_STM_PCIE] = mmPCIE_STM_BASE,
[GAUDI2_STM_PSOC] = mmPSOC_STM_BASE,
- [GAUDI2_STM_PSOC_ARC0_CS] = mmPSOC_ARC0_CS_STM_BASE,
- [GAUDI2_STM_PSOC_ARC1_CS] = mmPSOC_ARC1_CS_STM_BASE,
+ [GAUDI2_STM_PSOC_ARC0_CS] = 0,
+ [GAUDI2_STM_PSOC_ARC1_CS] = 0,
[GAUDI2_STM_PDMA0_CS] = mmPDMA0_CS_STM_BASE,
[GAUDI2_STM_PDMA1_CS] = mmPDMA1_CS_STM_BASE,
[GAUDI2_STM_CPU] = mmCPU_STM_BASE,
@@ -293,8 +293,8 @@ static u64 debug_etf_regs[GAUDI2_ETF_LAST + 1] = {
[GAUDI2_ETF_DCORE3_VDEC1_CS] = mmDCORE3_VDEC1_CS_ETF_BASE,
[GAUDI2_ETF_PCIE] = mmPCIE_ETF_BASE,
[GAUDI2_ETF_PSOC] = mmPSOC_ETF_BASE,
- [GAUDI2_ETF_PSOC_ARC0_CS] = mmPSOC_ARC0_CS_ETF_BASE,
- [GAUDI2_ETF_PSOC_ARC1_CS] = mmPSOC_ARC1_CS_ETF_BASE,
+ [GAUDI2_ETF_PSOC_ARC0_CS] = 0,
+ [GAUDI2_ETF_PSOC_ARC1_CS] = 0,
[GAUDI2_ETF_PDMA0_CS] = mmPDMA0_CS_ETF_BASE,
[GAUDI2_ETF_PDMA1_CS] = mmPDMA1_CS_ETF_BASE,
[GAUDI2_ETF_CPU_0] = mmCPU_ETF_0_BASE,
@@ -436,8 +436,8 @@ static u64 debug_funnel_regs[GAUDI2_FUNNEL_LAST + 1] = {
[GAUDI2_FUNNEL_DCORE3_RTR6] = mmDCORE3_RTR6_FUNNEL_BASE,
[GAUDI2_FUNNEL_DCORE3_RTR7] = mmDCORE3_RTR7_FUNNEL_BASE,
[GAUDI2_FUNNEL_PSOC] = mmPSOC_FUNNEL_BASE,
- [GAUDI2_FUNNEL_PSOC_ARC0] = mmPSOC_ARC0_FUNNEL_BASE,
- [GAUDI2_FUNNEL_PSOC_ARC1] = mmPSOC_ARC1_FUNNEL_BASE,
+ [GAUDI2_FUNNEL_PSOC_ARC0] = 0,
+ [GAUDI2_FUNNEL_PSOC_ARC1] = 0,
[GAUDI2_FUNNEL_XDMA] = mmXDMA_FUNNEL_BASE,
[GAUDI2_FUNNEL_CPU] = mmCPU_FUNNEL_BASE,
[GAUDI2_FUNNEL_PMMU] = mmPMMU_FUNNEL_BASE,
@@ -766,10 +766,10 @@ static u64 debug_bmon_regs[GAUDI2_BMON_LAST + 1] = {
[GAUDI2_BMON_PCIE_MSTR_RD] = mmPCIE_BMON_MSTR_RD_BASE,
[GAUDI2_BMON_PCIE_SLV_WR] = mmPCIE_BMON_SLV_WR_BASE,
[GAUDI2_BMON_PCIE_SLV_RD] = mmPCIE_BMON_SLV_RD_BASE,
- [GAUDI2_BMON_PSOC_ARC0_0] = mmPSOC_ARC0_BMON_0_BASE,
- [GAUDI2_BMON_PSOC_ARC0_1] = mmPSOC_ARC0_BMON_1_BASE,
- [GAUDI2_BMON_PSOC_ARC1_0] = mmPSOC_ARC1_BMON_0_BASE,
- [GAUDI2_BMON_PSOC_ARC1_1] = mmPSOC_ARC1_BMON_1_BASE,
+ [GAUDI2_BMON_PSOC_ARC0_0] = 0,
+ [GAUDI2_BMON_PSOC_ARC0_1] = 0,
+ [GAUDI2_BMON_PSOC_ARC1_0] = 0,
+ [GAUDI2_BMON_PSOC_ARC1_1] = 0,
[GAUDI2_BMON_PDMA0_0] = mmPDMA0_BMON_0_BASE,
[GAUDI2_BMON_PDMA0_1] = mmPDMA0_BMON_1_BASE,
[GAUDI2_BMON_PDMA1_0] = mmPDMA1_BMON_0_BASE,
@@ -968,8 +968,8 @@ static u64 debug_spmu_regs[GAUDI2_SPMU_LAST + 1] = {
[GAUDI2_SPMU_DCORE3_VDEC0_CS] = mmDCORE3_VDEC0_CS_SPMU_BASE,
[GAUDI2_SPMU_DCORE3_VDEC1_CS] = mmDCORE3_VDEC1_CS_SPMU_BASE,
[GAUDI2_SPMU_PCIE] = mmPCIE_SPMU_BASE,
- [GAUDI2_SPMU_PSOC_ARC0_CS] = mmPSOC_ARC0_CS_SPMU_BASE,
- [GAUDI2_SPMU_PSOC_ARC1_CS] = mmPSOC_ARC1_CS_SPMU_BASE,
+ [GAUDI2_SPMU_PSOC_ARC0_CS] = 0,
+ [GAUDI2_SPMU_PSOC_ARC1_CS] = 0,
[GAUDI2_SPMU_PDMA0_CS] = mmPDMA0_CS_SPMU_BASE,
[GAUDI2_SPMU_PDMA1_CS] = mmPDMA1_CS_SPMU_BASE,
[GAUDI2_SPMU_PMMU_CS] = mmPMMU_CS_SPMU_BASE,
@@ -2092,6 +2092,11 @@ static int gaudi2_config_etf(struct hl_device *hdev, struct hl_debug_params *par
if (rc)
return -EIO;
+ val = RREG32(base_reg + mmETF_CTL_OFFSET);
+
+ if ((!params->enable && val == 0x0) || (params->enable && val != 0x0))
+ return 0;
+
val = RREG32(base_reg + mmETF_FFCR_OFFSET);
val |= 0x1000;
WREG32(base_reg + mmETF_FFCR_OFFSET, val);
@@ -2120,10 +2125,17 @@ static int gaudi2_config_etf(struct hl_device *hdev, struct hl_debug_params *par
if (!input)
return -EINVAL;
+ val = RREG32(base_reg + mmETF_RSZ_OFFSET) << 2;
+ if (val) {
+ val = ffs(val);
+ WREG32(base_reg + mmETF_PSCR_OFFSET, val);
+ } else {
+ WREG32(base_reg + mmETF_PSCR_OFFSET, 0x10);
+ }
+
WREG32(base_reg + mmETF_BUFWM_OFFSET, 0x3FFC);
WREG32(base_reg + mmETF_MODE_OFFSET, input->sink_mode);
WREG32(base_reg + mmETF_FFCR_OFFSET, 0x4001);
- WREG32(base_reg + mmETF_PSCR_OFFSET, 0x10);
WREG32(base_reg + mmETF_CTL_OFFSET, 1);
} else {
WREG32(base_reg + mmETF_BUFWM_OFFSET, 0);
@@ -2189,6 +2201,11 @@ static int gaudi2_config_etr(struct hl_device *hdev, struct hl_ctx *ctx,
if (rc)
return -EIO;
+ val = RREG32(mmPSOC_ETR_CTL);
+
+ if ((!params->enable && val == 0x0) || (params->enable && val != 0x0))
+ return 0;
+
val = RREG32(mmPSOC_ETR_FFCR);
val |= 0x1000;
WREG32(mmPSOC_ETR_FFCR, val);
@@ -2483,7 +2500,8 @@ static int gaudi2_config_spmu(struct hl_device *hdev, struct hl_debug_params *pa
* set enabled events mask based on input->event_types_num
*/
event_mask = 0x80000000;
- event_mask |= GENMASK(input->event_types_num, 0);
+ if (input->event_types_num)
+ event_mask |= GENMASK(input->event_types_num - 1, 0);
WREG32(base_reg + mmSPMU_PMCNTENSET_EL0_OFFSET, event_mask);
} else {
diff --git a/drivers/accel/habanalabs/gaudi2/gaudi2_security.c b/drivers/accel/habanalabs/gaudi2/gaudi2_security.c
index 2742b1f801eb..34bf80c5a44b 100644
--- a/drivers/accel/habanalabs/gaudi2/gaudi2_security.c
+++ b/drivers/accel/habanalabs/gaudi2/gaudi2_security.c
@@ -1601,6 +1601,7 @@ static const u32 gaudi2_pb_dcr0_tpc0_unsecured_regs[] = {
mmDCORE0_TPC0_CFG_KERNEL_SRF_30,
mmDCORE0_TPC0_CFG_KERNEL_SRF_31,
mmDCORE0_TPC0_CFG_TPC_SB_L0CD,
+ mmDCORE0_TPC0_CFG_TPC_COUNT,
mmDCORE0_TPC0_CFG_TPC_ID,
mmDCORE0_TPC0_CFG_QM_KERNEL_ID_INC,
mmDCORE0_TPC0_CFG_QM_TID_BASE_SIZE_HIGH_DIM_0,
@@ -2907,7 +2908,7 @@ static void gaudi2_init_lbw_range_registers_secure(struct hl_device *hdev)
* - range 11: NIC11_CFG + *_DBG (not including TPC_DBG)
*
* If F/W security is not enabled:
- * - ranges 12,13: PSOC_CFG (excluding PSOC_TIMESTAMP)
+ * - ranges 12,13: PSOC_CFG (excluding PSOC_TIMESTAMP, PSOC_EFUSE and PSOC_GLOBAL_CONF)
*/
u64 lbw_range_min_short[] = {
mmNIC0_TX_AXUSER_BASE,
@@ -2923,7 +2924,7 @@ static void gaudi2_init_lbw_range_registers_secure(struct hl_device *hdev)
mmNIC10_TX_AXUSER_BASE,
mmNIC11_TX_AXUSER_BASE,
mmPSOC_I2C_M0_BASE,
- mmPSOC_EFUSE_BASE
+ mmPSOC_GPIO0_BASE
};
u64 lbw_range_max_short[] = {
mmNIC0_MAC_CH3_MAC_PCS_BASE + HL_BLOCK_SIZE,
@@ -3219,6 +3220,7 @@ static void gaudi2_init_range_registers(struct hl_device *hdev)
*/
static int gaudi2_init_protection_bits(struct hl_device *hdev)
{
+ u32 *user_regs_array = NULL, user_regs_array_size = 0, engine_core_intr_reg;
struct asic_fixed_properties *prop = &hdev->asic_prop;
u32 instance_offset;
int rc = 0;
@@ -3389,11 +3391,24 @@ static int gaudi2_init_protection_bits(struct hl_device *hdev)
/* PSOC.
* Except for PSOC_GLOBAL_CONF, skip when security is enabled in F/W, because the blocks are
* protected by privileged RR.
+ * For PSOC_GLOBAL_CONF, need to un-secure the scratchpad register which is used for engine
+ * cores to raise events towards F/W.
*/
+ engine_core_intr_reg = (u32) (hdev->asic_prop.engine_core_interrupt_reg_addr - CFG_BASE);
+ if (engine_core_intr_reg >= mmPSOC_GLOBAL_CONF_SCRATCHPAD_0 &&
+ engine_core_intr_reg <= mmPSOC_GLOBAL_CONF_SCRATCHPAD_31) {
+ user_regs_array = &engine_core_intr_reg;
+ user_regs_array_size = 1;
+ } else {
+ dev_err(hdev->dev,
+ "Engine cores register for interrupts (%#x) is not a PSOC scratchpad register\n",
+ engine_core_intr_reg);
+ }
+
rc |= hl_init_pb(hdev, HL_PB_SHARED, HL_PB_NA,
HL_PB_SINGLE_INSTANCE, HL_PB_NA,
gaudi2_pb_psoc_global_conf, ARRAY_SIZE(gaudi2_pb_psoc_global_conf),
- NULL, HL_PB_NA);
+ user_regs_array, user_regs_array_size);
if (!hdev->asic_prop.fw_security_enabled)
rc |= hl_init_pb(hdev, HL_PB_SHARED, HL_PB_NA,
diff --git a/drivers/accel/habanalabs/goya/goya.c b/drivers/accel/habanalabs/goya/goya.c
index 7c685e6075f6..1322cb330c57 100644
--- a/drivers/accel/habanalabs/goya/goya.c
+++ b/drivers/accel/habanalabs/goya/goya.c
@@ -466,7 +466,7 @@ int goya_set_fixed_properties(struct hl_device *hdev)
prop->pcie_dbi_base_address = mmPCIE_DBI_BASE;
prop->pcie_aux_dbi_reg_addr = CFG_BASE + mmPCIE_AUX_DBI;
- strncpy(prop->cpucp_info.card_name, GOYA_DEFAULT_CARD_NAME,
+ strscpy_pad(prop->cpucp_info.card_name, GOYA_DEFAULT_CARD_NAME,
CARD_NAME_MAX_LEN);
prop->max_pending_cs = GOYA_MAX_PENDING_CS;
@@ -3358,7 +3358,7 @@ static int goya_pin_memory_before_cs(struct hl_device *hdev,
list_add_tail(&userptr->job_node, parser->job_userptr_list);
- rc = hdev->asic_funcs->asic_dma_map_sgtable(hdev, userptr->sgt, dir);
+ rc = hl_dma_map_sgtable(hdev, userptr->sgt, dir);
if (rc) {
dev_err(hdev->dev, "failed to map sgt with DMA region\n");
goto unpin_memory;
@@ -5122,7 +5122,7 @@ int goya_cpucp_info_get(struct hl_device *hdev)
}
if (!strlen(prop->cpucp_info.card_name))
- strncpy(prop->cpucp_info.card_name, GOYA_DEFAULT_CARD_NAME,
+ strscpy_pad(prop->cpucp_info.card_name, GOYA_DEFAULT_CARD_NAME,
CARD_NAME_MAX_LEN);
return 0;
@@ -5465,9 +5465,9 @@ static const struct hl_asic_funcs goya_funcs = {
.asic_dma_pool_free = goya_dma_pool_free,
.cpu_accessible_dma_pool_alloc = goya_cpu_accessible_dma_pool_alloc,
.cpu_accessible_dma_pool_free = goya_cpu_accessible_dma_pool_free,
- .hl_dma_unmap_sgtable = hl_dma_unmap_sgtable,
+ .dma_unmap_sgtable = hl_asic_dma_unmap_sgtable,
.cs_parser = goya_cs_parser,
- .asic_dma_map_sgtable = hl_dma_map_sgtable,
+ .dma_map_sgtable = hl_asic_dma_map_sgtable,
.add_end_of_cb_packets = goya_add_end_of_cb_packets,
.update_eq_ci = goya_update_eq_ci,
.context_switch = goya_context_switch,
diff --git a/drivers/accel/habanalabs/goya/goyaP.h b/drivers/accel/habanalabs/goya/goyaP.h
index 5df3d30b91fd..194c2ae157cd 100644
--- a/drivers/accel/habanalabs/goya/goyaP.h
+++ b/drivers/accel/habanalabs/goya/goyaP.h
@@ -9,8 +9,8 @@
#define GOYAP_H_
#include <uapi/drm/habanalabs_accel.h>
+#include <linux/habanalabs/hl_boot_if.h>
#include "../common/habanalabs.h"
-#include "../include/common/hl_boot_if.h"
#include "../include/goya/goya_packets.h"
#include "../include/goya/goya.h"
#include "../include/goya/goya_async_events.h"
diff --git a/drivers/accel/habanalabs/goya/goya_coresight.c b/drivers/accel/habanalabs/goya/goya_coresight.c
index a6d6cc38bcd8..41cae5fd843b 100644
--- a/drivers/accel/habanalabs/goya/goya_coresight.c
+++ b/drivers/accel/habanalabs/goya/goya_coresight.c
@@ -315,6 +315,11 @@ static int goya_config_etf(struct hl_device *hdev,
WREG32(base_reg + 0xFB0, CORESIGHT_UNLOCK);
+ val = RREG32(base_reg + 0x20);
+
+ if ((!params->enable && val == 0x0) || (params->enable && val != 0x0))
+ return 0;
+
val = RREG32(base_reg + 0x304);
val |= 0x1000;
WREG32(base_reg + 0x304, val);
@@ -386,6 +391,11 @@ static int goya_config_etr(struct hl_device *hdev,
WREG32(mmPSOC_ETR_LAR, CORESIGHT_UNLOCK);
+ val = RREG32(mmPSOC_ETR_CTL);
+
+ if ((!params->enable && val == 0x0) || (params->enable && val != 0x0))
+ return 0;
+
val = RREG32(mmPSOC_ETR_FFCR);
val |= 0x1000;
WREG32(mmPSOC_ETR_FFCR, val);
diff --git a/drivers/accel/habanalabs/include/gaudi/gaudi_fw_if.h b/drivers/accel/habanalabs/include/gaudi/gaudi_fw_if.h
index 2dba02757d37..a2547f306750 100644
--- a/drivers/accel/habanalabs/include/gaudi/gaudi_fw_if.h
+++ b/drivers/accel/habanalabs/include/gaudi/gaudi_fw_if.h
@@ -44,38 +44,6 @@ struct eq_nic_sei_event {
__u8 pad[6];
};
-/*
- * struct gaudi_nic_status - describes the status of a NIC port.
- * @port: NIC port index.
- * @bad_format_cnt: e.g. CRC.
- * @responder_out_of_sequence_psn_cnt: e.g NAK.
- * @high_ber_reinit_cnt: link reinit due to high BER.
- * @correctable_err_cnt: e.g. bit-flip.
- * @uncorrectable_err_cnt: e.g. MAC errors.
- * @retraining_cnt: re-training counter.
- * @up: is port up.
- * @pcs_link: has PCS link.
- * @phy_ready: is PHY ready.
- * @auto_neg: is Autoneg enabled.
- * @timeout_retransmission_cnt: timeout retransmission events
- * @high_ber_cnt: high ber events
- */
-struct gaudi_nic_status {
- __u32 port;
- __u32 bad_format_cnt;
- __u32 responder_out_of_sequence_psn_cnt;
- __u32 high_ber_reinit;
- __u32 correctable_err_cnt;
- __u32 uncorrectable_err_cnt;
- __u32 retraining_cnt;
- __u8 up;
- __u8 pcs_link;
- __u8 phy_ready;
- __u8 auto_neg;
- __u32 timeout_retransmission_cnt;
- __u32 high_ber_cnt;
-};
-
struct gaudi_cold_rst_data {
union {
struct {
diff --git a/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_events.h b/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_events.h
index f661068d0c5f..a426410139af 100644
--- a/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_events.h
+++ b/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_events.h
@@ -959,6 +959,13 @@ enum gaudi2_async_event_id {
GAUDI2_EVENT_ARC_DCCM_FULL = 1319,
GAUDI2_EVENT_CPU_FP32_NOT_SUPPORTED = 1320,
GAUDI2_EVENT_CPU_DEV_RESET_REQ = 1321,
+ GAUDI2_EVENT_ARC_PWR_BRK_ENTRY = 1322,
+ GAUDI2_EVENT_ARC_PWR_BRK_EXT = 1323,
+ GAUDI2_EVENT_ARC_PWR_RD_MODE0 = 1324,
+ GAUDI2_EVENT_ARC_PWR_RD_MODE1 = 1325,
+ GAUDI2_EVENT_ARC_PWR_RD_MODE2 = 1326,
+ GAUDI2_EVENT_ARC_PWR_RD_MODE3 = 1327,
+ GAUDI2_EVENT_ARC_EQ_HEARTBEAT = 1328,
GAUDI2_EVENT_SIZE,
};
diff --git a/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h b/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h
index ad01fc4e9940..b2dbe1f64430 100644
--- a/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h
+++ b/drivers/accel/habanalabs/include/gaudi2/gaudi2_async_ids_map_extended.h
@@ -1293,7 +1293,7 @@ static struct gaudi2_async_events_ids_map gaudi2_irq_map_table[] = {
.name = "" },
{ .fc_id = 631, .cpu_id = 128, .valid = 1, .msg = 0, .reset = EVENT_RESET_TYPE_NONE,
.name = "PCIE_P2P_MSIX" },
- { .fc_id = 632, .cpu_id = 129, .valid = 1, .msg = 0, .reset = EVENT_RESET_TYPE_NONE,
+ { .fc_id = 632, .cpu_id = 129, .valid = 1, .msg = 0, .reset = EVENT_RESET_TYPE_HARD,
.name = "PCIE_DRAIN_COMPLETE" },
{ .fc_id = 633, .cpu_id = 130, .valid = 1, .msg = 0, .reset = EVENT_RESET_TYPE_NONE,
.name = "TPC0_BMON_SPMU" },
@@ -2673,6 +2673,20 @@ static struct gaudi2_async_events_ids_map gaudi2_irq_map_table[] = {
.name = "FP32_NOT_SUPPORTED" },
{ .fc_id = 1321, .cpu_id = 627, .valid = 1, .msg = 1, .reset = EVENT_RESET_TYPE_HARD,
.name = "DEV_RESET_REQ" },
+ { .fc_id = 1322, .cpu_id = 628, .valid = 1, .msg = 1, .reset = EVENT_RESET_TYPE_NONE,
+ .name = "ARC_PWR_BRK_ENTRY" },
+ { .fc_id = 1323, .cpu_id = 629, .valid = 1, .msg = 1, .reset = EVENT_RESET_TYPE_NONE,
+ .name = "ARC_PWR_BRK_EXT" },
+ { .fc_id = 1324, .cpu_id = 630, .valid = 1, .msg = 1, .reset = EVENT_RESET_TYPE_NONE,
+ .name = "ARC_PWR_RD_MODE0" },
+ { .fc_id = 1325, .cpu_id = 631, .valid = 1, .msg = 1, .reset = EVENT_RESET_TYPE_NONE,
+ .name = "ARC_PWR_RD_MODE1" },
+ { .fc_id = 1326, .cpu_id = 632, .valid = 1, .msg = 1, .reset = EVENT_RESET_TYPE_NONE,
+ .name = "ARC_PWR_RD_MODE2" },
+ { .fc_id = 1327, .cpu_id = 633, .valid = 1, .msg = 1, .reset = EVENT_RESET_TYPE_NONE,
+ .name = "ARC_PWR_RD_MODE3" },
+ { .fc_id = 1328, .cpu_id = 634, .valid = 1, .msg = 1, .reset = EVENT_RESET_TYPE_NONE,
+ .name = "ARC_EQ_HEARTBEAT" },
};
#endif /* __GAUDI2_ASYNC_IDS_MAP_EVENTS_EXT_H_ */
diff --git a/drivers/accel/ivpu/Makefile b/drivers/accel/ivpu/Makefile
index e4328b430564..95ff7ad16338 100644
--- a/drivers/accel/ivpu/Makefile
+++ b/drivers/accel/ivpu/Makefile
@@ -2,7 +2,6 @@
# Copyright (C) 2023 Intel Corporation
intel_vpu-y := \
- ivpu_debugfs.o \
ivpu_drv.o \
ivpu_fw.o \
ivpu_fw_log.o \
@@ -16,4 +15,6 @@ intel_vpu-y := \
ivpu_mmu_context.o \
ivpu_pm.o
+intel_vpu-$(CONFIG_DEBUG_FS) += ivpu_debugfs.o
+
obj-$(CONFIG_DRM_ACCEL_IVPU) += intel_vpu.o
diff --git a/drivers/accel/ivpu/TODO b/drivers/accel/ivpu/TODO
deleted file mode 100644
index 9077217ae10f..000000000000
--- a/drivers/accel/ivpu/TODO
+++ /dev/null
@@ -1,11 +0,0 @@
-- Move to threaded_irqs to mitigate potential infinite loop in ivpu_ipc_irq_handler()
-- Implement support for BLOB IDs
-- Add debugfs support to improve debugging and testing
-- Add tracing events for performance debugging
-- Implement HW based scheduling support
-- Use syncobjs for submit/sync
-- Refactor IPC protocol to improve message latency
-- Implement BO cache and MADVISE IOCTL
-- Add support for user allocated buffers using prime import and dma-buf heaps
-- Refactor struct ivpu_bo to use struct drm_gem_shmem_object
-- Add driver/device documentation
diff --git a/drivers/accel/ivpu/ivpu_debugfs.c b/drivers/accel/ivpu/ivpu_debugfs.c
index 5e5996fd4f9f..ea453b985b49 100644
--- a/drivers/accel/ivpu/ivpu_debugfs.c
+++ b/drivers/accel/ivpu/ivpu_debugfs.c
@@ -17,20 +17,26 @@
#include "ivpu_jsm_msg.h"
#include "ivpu_pm.h"
+static inline struct ivpu_device *seq_to_ivpu(struct seq_file *s)
+{
+ struct drm_debugfs_entry *entry = s->private;
+
+ return to_ivpu_device(entry->dev);
+}
+
static int bo_list_show(struct seq_file *s, void *v)
{
- struct drm_info_node *node = (struct drm_info_node *)s->private;
struct drm_printer p = drm_seq_file_printer(s);
+ struct ivpu_device *vdev = seq_to_ivpu(s);
- ivpu_bo_list(node->minor->dev, &p);
+ ivpu_bo_list(&vdev->drm, &p);
return 0;
}
static int fw_name_show(struct seq_file *s, void *v)
{
- struct drm_info_node *node = (struct drm_info_node *)s->private;
- struct ivpu_device *vdev = to_ivpu_device(node->minor->dev);
+ struct ivpu_device *vdev = seq_to_ivpu(s);
seq_printf(s, "%s\n", vdev->fw->name);
return 0;
@@ -38,8 +44,7 @@ static int fw_name_show(struct seq_file *s, void *v)
static int fw_trace_capability_show(struct seq_file *s, void *v)
{
- struct drm_info_node *node = (struct drm_info_node *)s->private;
- struct ivpu_device *vdev = to_ivpu_device(node->minor->dev);
+ struct ivpu_device *vdev = seq_to_ivpu(s);
u64 trace_hw_component_mask;
u32 trace_destination_mask;
int ret;
@@ -57,8 +62,7 @@ static int fw_trace_capability_show(struct seq_file *s, void *v)
static int fw_trace_config_show(struct seq_file *s, void *v)
{
- struct drm_info_node *node = (struct drm_info_node *)s->private;
- struct ivpu_device *vdev = to_ivpu_device(node->minor->dev);
+ struct ivpu_device *vdev = seq_to_ivpu(s);
/**
* WA: VPU_JSM_MSG_TRACE_GET_CONFIG command is not working yet,
* so we use values from vdev->fw instead of calling ivpu_jsm_trace_get_config()
@@ -78,8 +82,7 @@ static int fw_trace_config_show(struct seq_file *s, void *v)
static int last_bootmode_show(struct seq_file *s, void *v)
{
- struct drm_info_node *node = (struct drm_info_node *)s->private;
- struct ivpu_device *vdev = to_ivpu_device(node->minor->dev);
+ struct ivpu_device *vdev = seq_to_ivpu(s);
seq_printf(s, "%s\n", (vdev->pm->is_warmboot) ? "warmboot" : "coldboot");
@@ -88,8 +91,7 @@ static int last_bootmode_show(struct seq_file *s, void *v)
static int reset_counter_show(struct seq_file *s, void *v)
{
- struct drm_info_node *node = (struct drm_info_node *)s->private;
- struct ivpu_device *vdev = to_ivpu_device(node->minor->dev);
+ struct ivpu_device *vdev = seq_to_ivpu(s);
seq_printf(s, "%d\n", atomic_read(&vdev->pm->reset_counter));
return 0;
@@ -97,14 +99,13 @@ static int reset_counter_show(struct seq_file *s, void *v)
static int reset_pending_show(struct seq_file *s, void *v)
{
- struct drm_info_node *node = (struct drm_info_node *)s->private;
- struct ivpu_device *vdev = to_ivpu_device(node->minor->dev);
+ struct ivpu_device *vdev = seq_to_ivpu(s);
seq_printf(s, "%d\n", atomic_read(&vdev->pm->in_reset));
return 0;
}
-static const struct drm_info_list vdev_debugfs_list[] = {
+static const struct drm_debugfs_info vdev_debugfs_list[] = {
{"bo_list", bo_list_show, 0},
{"fw_name", fw_name_show, 0},
{"fw_trace_capability", fw_trace_capability_show, 0},
@@ -270,25 +271,24 @@ static const struct file_operations ivpu_reset_engine_fops = {
.write = ivpu_reset_engine_fn,
};
-void ivpu_debugfs_init(struct drm_minor *minor)
+void ivpu_debugfs_init(struct ivpu_device *vdev)
{
- struct ivpu_device *vdev = to_ivpu_device(minor->dev);
+ struct dentry *debugfs_root = vdev->drm.debugfs_root;
- drm_debugfs_create_files(vdev_debugfs_list, ARRAY_SIZE(vdev_debugfs_list),
- minor->debugfs_root, minor);
+ drm_debugfs_add_files(&vdev->drm, vdev_debugfs_list, ARRAY_SIZE(vdev_debugfs_list));
- debugfs_create_file("force_recovery", 0200, minor->debugfs_root, vdev,
+ debugfs_create_file("force_recovery", 0200, debugfs_root, vdev,
&ivpu_force_recovery_fops);
- debugfs_create_file("fw_log", 0644, minor->debugfs_root, vdev,
+ debugfs_create_file("fw_log", 0644, debugfs_root, vdev,
&fw_log_fops);
- debugfs_create_file("fw_trace_destination_mask", 0200, minor->debugfs_root, vdev,
+ debugfs_create_file("fw_trace_destination_mask", 0200, debugfs_root, vdev,
&fw_trace_destination_mask_fops);
- debugfs_create_file("fw_trace_hw_comp_mask", 0200, minor->debugfs_root, vdev,
+ debugfs_create_file("fw_trace_hw_comp_mask", 0200, debugfs_root, vdev,
&fw_trace_hw_comp_mask_fops);
- debugfs_create_file("fw_trace_level", 0200, minor->debugfs_root, vdev,
+ debugfs_create_file("fw_trace_level", 0200, debugfs_root, vdev,
&fw_trace_level_fops);
- debugfs_create_file("reset_engine", 0200, minor->debugfs_root, vdev,
+ debugfs_create_file("reset_engine", 0200, debugfs_root, vdev,
&ivpu_reset_engine_fops);
}
diff --git a/drivers/accel/ivpu/ivpu_debugfs.h b/drivers/accel/ivpu/ivpu_debugfs.h
index 78f80c1e00e4..49ae9ea78287 100644
--- a/drivers/accel/ivpu/ivpu_debugfs.h
+++ b/drivers/accel/ivpu/ivpu_debugfs.h
@@ -6,8 +6,12 @@
#ifndef __IVPU_DEBUGFS_H__
#define __IVPU_DEBUGFS_H__
-struct drm_minor;
+struct ivpu_device;
-void ivpu_debugfs_init(struct drm_minor *minor);
+#if defined(CONFIG_DEBUG_FS)
+void ivpu_debugfs_init(struct ivpu_device *vdev);
+#else
+static inline void ivpu_debugfs_init(struct ivpu_device *vdev) { }
+#endif
#endif /* __IVPU_DEBUGFS_H__ */
diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c
index 467a60235370..790603017653 100644
--- a/drivers/accel/ivpu/ivpu_drv.c
+++ b/drivers/accel/ivpu/ivpu_drv.c
@@ -131,6 +131,22 @@ static int ivpu_get_capabilities(struct ivpu_device *vdev, struct drm_ivpu_param
return 0;
}
+static int ivpu_get_core_clock_rate(struct ivpu_device *vdev, u64 *clk_rate)
+{
+ int ret;
+
+ ret = ivpu_rpm_get_if_active(vdev);
+ if (ret < 0)
+ return ret;
+
+ *clk_rate = ret ? ivpu_hw_reg_pll_freq_get(vdev) : 0;
+
+ if (ret)
+ ivpu_rpm_put(vdev);
+
+ return 0;
+}
+
static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
{
struct ivpu_file_priv *file_priv = file->driver_priv;
@@ -154,7 +170,7 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f
args->value = vdev->platform;
break;
case DRM_IVPU_PARAM_CORE_CLOCK_RATE:
- args->value = ivpu_hw_reg_pll_freq_get(vdev);
+ ret = ivpu_get_core_clock_rate(vdev, &args->value);
break;
case DRM_IVPU_PARAM_NUM_CONTEXTS:
args->value = ivpu_get_context_count(vdev);
@@ -367,14 +383,19 @@ int ivpu_boot(struct ivpu_device *vdev)
return 0;
}
-int ivpu_shutdown(struct ivpu_device *vdev)
+void ivpu_prepare_for_reset(struct ivpu_device *vdev)
{
- int ret;
-
ivpu_hw_irq_disable(vdev);
disable_irq(vdev->irq);
ivpu_ipc_disable(vdev);
ivpu_mmu_disable(vdev);
+}
+
+int ivpu_shutdown(struct ivpu_device *vdev)
+{
+ int ret;
+
+ ivpu_prepare_for_reset(vdev);
ret = ivpu_hw_power_down(vdev);
if (ret)
@@ -395,10 +416,6 @@ static const struct drm_driver driver = {
.postclose = ivpu_postclose,
.gem_prime_import = ivpu_gem_prime_import,
-#if defined(CONFIG_DEBUG_FS)
- .debugfs_init = ivpu_debugfs_init,
-#endif
-
.ioctls = ivpu_drm_ioctls,
.num_ioctls = ARRAY_SIZE(ivpu_drm_ioctls),
.fops = &ivpu_fops,
@@ -518,78 +535,52 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
lockdep_set_class(&vdev->submitted_jobs_xa.xa_lock, &submitted_jobs_xa_lock_class_key);
ret = ivpu_pci_init(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to initialize PCI device: %d\n", ret);
+ if (ret)
goto err_xa_destroy;
- }
ret = ivpu_irq_init(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to initialize IRQs: %d\n", ret);
+ if (ret)
goto err_xa_destroy;
- }
/* Init basic HW info based on buttress registers which are accessible before power up */
ret = ivpu_hw_info_init(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to initialize HW info: %d\n", ret);
+ if (ret)
goto err_xa_destroy;
- }
/* Power up early so the rest of init code can access VPU registers */
ret = ivpu_hw_power_up(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to power up HW: %d\n", ret);
+ if (ret)
goto err_xa_destroy;
- }
ret = ivpu_mmu_global_context_init(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to initialize global MMU context: %d\n", ret);
+ if (ret)
goto err_power_down;
- }
ret = ivpu_mmu_init(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to initialize MMU device: %d\n", ret);
+ if (ret)
goto err_mmu_gctx_fini;
- }
- ret = ivpu_fw_init(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to initialize firmware: %d\n", ret);
+ ret = ivpu_mmu_reserved_context_init(vdev);
+ if (ret)
goto err_mmu_gctx_fini;
- }
+
+ ret = ivpu_fw_init(vdev);
+ if (ret)
+ goto err_mmu_rctx_fini;
ret = ivpu_ipc_init(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to initialize IPC: %d\n", ret);
+ if (ret)
goto err_fw_fini;
- }
- ret = ivpu_pm_init(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to initialize PM: %d\n", ret);
- goto err_ipc_fini;
- }
+ ivpu_pm_init(vdev);
ret = ivpu_job_done_thread_init(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to initialize job done thread: %d\n", ret);
+ if (ret)
goto err_ipc_fini;
- }
-
- ret = ivpu_fw_load(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to load firmware: %d\n", ret);
- goto err_job_done_thread_fini;
- }
ret = ivpu_boot(vdev);
- if (ret) {
- ivpu_err(vdev, "Failed to boot: %d\n", ret);
+ if (ret)
goto err_job_done_thread_fini;
- }
ivpu_pm_enable(vdev);
@@ -601,6 +592,8 @@ err_ipc_fini:
ivpu_ipc_fini(vdev);
err_fw_fini:
ivpu_fw_fini(vdev);
+err_mmu_rctx_fini:
+ ivpu_mmu_reserved_context_fini(vdev);
err_mmu_gctx_fini:
ivpu_mmu_global_context_fini(vdev);
err_power_down:
@@ -624,6 +617,7 @@ static void ivpu_dev_fini(struct ivpu_device *vdev)
ivpu_ipc_fini(vdev);
ivpu_fw_fini(vdev);
+ ivpu_mmu_reserved_context_fini(vdev);
ivpu_mmu_global_context_fini(vdev);
drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->submitted_jobs_xa));
@@ -652,10 +646,10 @@ static int ivpu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, vdev);
ret = ivpu_dev_init(vdev);
- if (ret) {
- dev_err(&pdev->dev, "Failed to initialize VPU device: %d\n", ret);
+ if (ret)
return ret;
- }
+
+ ivpu_debugfs_init(vdev);
ret = drm_dev_register(&vdev->drm, 0);
if (ret) {
diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h
index 03b3d6532fb6..417ddeca8517 100644
--- a/drivers/accel/ivpu/ivpu_drv.h
+++ b/drivers/accel/ivpu/ivpu_drv.h
@@ -29,12 +29,13 @@
#define IVPU_HW_37XX 37
#define IVPU_HW_40XX 40
-#define IVPU_GLOBAL_CONTEXT_MMU_SSID 0
-/* SSID 1 is used by the VPU to represent invalid context */
-#define IVPU_USER_CONTEXT_MIN_SSID 2
-#define IVPU_USER_CONTEXT_MAX_SSID (IVPU_USER_CONTEXT_MIN_SSID + 63)
+#define IVPU_GLOBAL_CONTEXT_MMU_SSID 0
+/* SSID 1 is used by the VPU to represent reserved context */
+#define IVPU_RESERVED_CONTEXT_MMU_SSID 1
+#define IVPU_USER_CONTEXT_MIN_SSID 2
+#define IVPU_USER_CONTEXT_MAX_SSID (IVPU_USER_CONTEXT_MIN_SSID + 63)
-#define IVPU_NUM_ENGINES 2
+#define IVPU_NUM_ENGINES 2
#define IVPU_PLATFORM_SILICON 0
#define IVPU_PLATFORM_SIMICS 2
@@ -76,6 +77,11 @@
#define IVPU_WA(wa_name) (vdev->wa.wa_name)
+#define IVPU_PRINT_WA(wa_name) do { \
+ if (IVPU_WA(wa_name)) \
+ ivpu_dbg(vdev, MISC, "Using WA: " #wa_name "\n"); \
+} while (0)
+
struct ivpu_wa_table {
bool punit_disabled;
bool clear_runtime_mem;
@@ -105,6 +111,7 @@ struct ivpu_device {
struct ivpu_pm_info *pm;
struct ivpu_mmu_context gctx;
+ struct ivpu_mmu_context rctx;
struct xarray context_xa;
struct xa_limit context_xa_limit;
@@ -118,6 +125,7 @@ struct ivpu_device {
int jsm;
int tdr;
int reschedule_suspend;
+ int autosuspend;
} timeout;
};
@@ -151,6 +159,7 @@ void ivpu_file_priv_put(struct ivpu_file_priv **link);
int ivpu_boot(struct ivpu_device *vdev);
int ivpu_shutdown(struct ivpu_device *vdev);
+void ivpu_prepare_for_reset(struct ivpu_device *vdev);
static inline u8 ivpu_revision(struct ivpu_device *vdev)
{
diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c
index 0191cf8e5964..691da521dde5 100644
--- a/drivers/accel/ivpu/ivpu_fw.c
+++ b/drivers/accel/ivpu/ivpu_fw.c
@@ -220,8 +220,7 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev)
if (ret)
return ret;
- fw->mem = ivpu_bo_alloc_internal(vdev, fw->runtime_addr, fw->runtime_size,
- DRM_IVPU_BO_CACHED | DRM_IVPU_BO_NOSNOOP);
+ fw->mem = ivpu_bo_alloc_internal(vdev, fw->runtime_addr, fw->runtime_size, DRM_IVPU_BO_WC);
if (!fw->mem) {
ivpu_err(vdev, "Failed to allocate firmware runtime memory\n");
return -ENOMEM;
@@ -302,6 +301,8 @@ int ivpu_fw_init(struct ivpu_device *vdev)
if (ret)
goto err_fw_release;
+ ivpu_fw_load(vdev);
+
return 0;
err_fw_release:
@@ -315,25 +316,23 @@ void ivpu_fw_fini(struct ivpu_device *vdev)
ivpu_fw_release(vdev);
}
-int ivpu_fw_load(struct ivpu_device *vdev)
+void ivpu_fw_load(struct ivpu_device *vdev)
{
struct ivpu_fw_info *fw = vdev->fw;
u64 image_end_offset = fw->image_load_offset + fw->image_size;
- memset(fw->mem->kvaddr, 0, fw->image_load_offset);
- memcpy(fw->mem->kvaddr + fw->image_load_offset,
+ memset(ivpu_bo_vaddr(fw->mem), 0, fw->image_load_offset);
+ memcpy(ivpu_bo_vaddr(fw->mem) + fw->image_load_offset,
fw->file->data + FW_FILE_IMAGE_OFFSET, fw->image_size);
if (IVPU_WA(clear_runtime_mem)) {
- u8 *start = fw->mem->kvaddr + image_end_offset;
- u64 size = fw->mem->base.size - image_end_offset;
+ u8 *start = ivpu_bo_vaddr(fw->mem) + image_end_offset;
+ u64 size = ivpu_bo_size(fw->mem) - image_end_offset;
memset(start, 0, size);
}
- clflush_cache_range(fw->mem->kvaddr, fw->mem->base.size);
-
- return 0;
+ wmb(); /* Flush WC buffers after writing fw->mem */
}
static void ivpu_fw_boot_params_print(struct ivpu_device *vdev, struct vpu_boot_params *boot_params)
@@ -433,7 +432,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
if (!ivpu_fw_is_cold_boot(vdev)) {
boot_params->save_restore_ret_address = 0;
vdev->pm->is_warmboot = true;
- clflush_cache_range(vdev->fw->mem->kvaddr, SZ_4K);
+ wmb(); /* Flush WC buffers after writing save_restore_ret_address */
return;
}
@@ -452,10 +451,10 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
vdev->hw->ranges.global.start;
boot_params->ipc_header_area_start = ipc_mem_rx->vpu_addr;
- boot_params->ipc_header_area_size = ipc_mem_rx->base.size / 2;
+ boot_params->ipc_header_area_size = ivpu_bo_size(ipc_mem_rx) / 2;
- boot_params->ipc_payload_area_start = ipc_mem_rx->vpu_addr + ipc_mem_rx->base.size / 2;
- boot_params->ipc_payload_area_size = ipc_mem_rx->base.size / 2;
+ boot_params->ipc_payload_area_start = ipc_mem_rx->vpu_addr + ivpu_bo_size(ipc_mem_rx) / 2;
+ boot_params->ipc_payload_area_size = ivpu_bo_size(ipc_mem_rx) / 2;
boot_params->global_aliased_pio_base = vdev->hw->ranges.user.start;
boot_params->global_aliased_pio_size = ivpu_hw_range_size(&vdev->hw->ranges.user);
@@ -487,15 +486,15 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
boot_params->trace_destination_mask = vdev->fw->trace_destination_mask;
boot_params->trace_hw_component_mask = vdev->fw->trace_hw_component_mask;
boot_params->crit_tracing_buff_addr = vdev->fw->mem_log_crit->vpu_addr;
- boot_params->crit_tracing_buff_size = vdev->fw->mem_log_crit->base.size;
+ boot_params->crit_tracing_buff_size = ivpu_bo_size(vdev->fw->mem_log_crit);
boot_params->verbose_tracing_buff_addr = vdev->fw->mem_log_verb->vpu_addr;
- boot_params->verbose_tracing_buff_size = vdev->fw->mem_log_verb->base.size;
+ boot_params->verbose_tracing_buff_size = ivpu_bo_size(vdev->fw->mem_log_verb);
boot_params->punit_telemetry_sram_base = ivpu_hw_reg_telemetry_offset_get(vdev);
boot_params->punit_telemetry_sram_size = ivpu_hw_reg_telemetry_size_get(vdev);
boot_params->vpu_telemetry_enable = ivpu_hw_reg_telemetry_enable_get(vdev);
- clflush_cache_range(vdev->fw->mem->kvaddr, SZ_4K);
+ wmb(); /* Flush WC buffers after writing bootparams */
ivpu_fw_boot_params_print(vdev, boot_params);
}
diff --git a/drivers/accel/ivpu/ivpu_fw.h b/drivers/accel/ivpu/ivpu_fw.h
index 8567fdf925fe..10ae2847f0ef 100644
--- a/drivers/accel/ivpu/ivpu_fw.h
+++ b/drivers/accel/ivpu/ivpu_fw.h
@@ -31,7 +31,7 @@ struct ivpu_fw_info {
int ivpu_fw_init(struct ivpu_device *vdev);
void ivpu_fw_fini(struct ivpu_device *vdev);
-int ivpu_fw_load(struct ivpu_device *vdev);
+void ivpu_fw_load(struct ivpu_device *vdev);
void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params *bp);
static inline bool ivpu_fw_is_cold_boot(struct ivpu_device *vdev)
diff --git a/drivers/accel/ivpu/ivpu_fw_log.c b/drivers/accel/ivpu/ivpu_fw_log.c
index 95065cac9fbd..f6770f5e82a2 100644
--- a/drivers/accel/ivpu/ivpu_fw_log.c
+++ b/drivers/accel/ivpu/ivpu_fw_log.c
@@ -31,10 +31,10 @@ static int fw_log_ptr(struct ivpu_device *vdev, struct ivpu_bo *bo, u32 *offset,
{
struct vpu_tracing_buffer_header *log;
- if ((*offset + sizeof(*log)) > bo->base.size)
+ if ((*offset + sizeof(*log)) > ivpu_bo_size(bo))
return -EINVAL;
- log = bo->kvaddr + *offset;
+ log = ivpu_bo_vaddr(bo) + *offset;
if (log->vpu_canary_start != VPU_TRACING_BUFFER_CANARY)
return -EINVAL;
@@ -43,7 +43,7 @@ static int fw_log_ptr(struct ivpu_device *vdev, struct ivpu_bo *bo, u32 *offset,
ivpu_dbg(vdev, FW_BOOT, "Invalid header size 0x%x\n", log->header_size);
return -EINVAL;
}
- if ((char *)log + log->size > (char *)bo->kvaddr + bo->base.size) {
+ if ((char *)log + log->size > (char *)ivpu_bo_vaddr(bo) + ivpu_bo_size(bo)) {
ivpu_dbg(vdev, FW_BOOT, "Invalid log size 0x%x\n", log->size);
return -EINVAL;
}
diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c
index d09f13b35902..c91852f2edc8 100644
--- a/drivers/accel/ivpu/ivpu_gem.c
+++ b/drivers/accel/ivpu/ivpu_gem.c
@@ -69,7 +69,7 @@ static const struct ivpu_bo_ops prime_ops = {
static int __must_check shmem_alloc_pages_locked(struct ivpu_bo *bo)
{
- int npages = bo->base.size >> PAGE_SHIFT;
+ int npages = ivpu_bo_size(bo) >> PAGE_SHIFT;
struct page **pages;
pages = drm_gem_get_pages(&bo->base);
@@ -88,7 +88,7 @@ static int __must_check shmem_alloc_pages_locked(struct ivpu_bo *bo)
static void shmem_free_pages_locked(struct ivpu_bo *bo)
{
if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED)
- set_pages_array_wb(bo->pages, bo->base.size >> PAGE_SHIFT);
+ set_pages_array_wb(bo->pages, ivpu_bo_size(bo) >> PAGE_SHIFT);
drm_gem_put_pages(&bo->base, bo->pages, true, false);
bo->pages = NULL;
@@ -96,7 +96,7 @@ static void shmem_free_pages_locked(struct ivpu_bo *bo)
static int ivpu_bo_map_pages_locked(struct ivpu_bo *bo)
{
- int npages = bo->base.size >> PAGE_SHIFT;
+ int npages = ivpu_bo_size(bo) >> PAGE_SHIFT;
struct ivpu_device *vdev = ivpu_bo_to_vdev(bo);
struct sg_table *sgt;
int ret;
@@ -142,7 +142,7 @@ static const struct ivpu_bo_ops shmem_ops = {
static int __must_check internal_alloc_pages_locked(struct ivpu_bo *bo)
{
- unsigned int i, npages = bo->base.size >> PAGE_SHIFT;
+ unsigned int i, npages = ivpu_bo_size(bo) >> PAGE_SHIFT;
struct page **pages;
int ret;
@@ -171,10 +171,10 @@ err_free_pages:
static void internal_free_pages_locked(struct ivpu_bo *bo)
{
- unsigned int i, npages = bo->base.size >> PAGE_SHIFT;
+ unsigned int i, npages = ivpu_bo_size(bo) >> PAGE_SHIFT;
if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED)
- set_pages_array_wb(bo->pages, bo->base.size >> PAGE_SHIFT);
+ set_pages_array_wb(bo->pages, ivpu_bo_size(bo) >> PAGE_SHIFT);
for (i = 0; i < npages; i++)
put_page(bo->pages[i]);
@@ -291,7 +291,7 @@ ivpu_bo_alloc_vpu_addr(struct ivpu_bo *bo, struct ivpu_mmu_context *ctx,
}
mutex_lock(&ctx->lock);
- ret = ivpu_mmu_context_insert_node_locked(ctx, range, bo->base.size, &bo->mm_node);
+ ret = ivpu_mmu_context_insert_node_locked(ctx, range, ivpu_bo_size(bo), &bo->mm_node);
if (!ret) {
bo->ctx = ctx;
bo->vpu_addr = bo->mm_node.start;
@@ -438,7 +438,7 @@ static int ivpu_bo_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
struct ivpu_device *vdev = ivpu_bo_to_vdev(bo);
ivpu_dbg(vdev, BO, "mmap: ctx %u handle %u vpu_addr 0x%llx size %zu type %s",
- bo->ctx->id, bo->handle, bo->vpu_addr, bo->base.size, bo->ops->name);
+ bo->ctx->id, bo->handle, bo->vpu_addr, ivpu_bo_size(bo), bo->ops->name);
if (obj->import_attach) {
/* Drop the reference drm_gem_mmap_obj() acquired.*/
@@ -553,7 +553,7 @@ ivpu_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
drm_gem_object_put(&bo->base);
ivpu_dbg(vdev, BO, "alloc shmem: ctx %u vpu_addr 0x%llx size %zu flags 0x%x\n",
- file_priv->ctx.id, bo->vpu_addr, bo->base.size, bo->flags);
+ file_priv->ctx.id, bo->vpu_addr, ivpu_bo_size(bo), bo->flags);
return ret;
}
@@ -590,22 +590,22 @@ ivpu_bo_alloc_internal(struct ivpu_device *vdev, u64 vpu_addr, u64 size, u32 fla
goto err_put;
if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED)
- drm_clflush_pages(bo->pages, bo->base.size >> PAGE_SHIFT);
+ drm_clflush_pages(bo->pages, ivpu_bo_size(bo) >> PAGE_SHIFT);
if (bo->flags & DRM_IVPU_BO_WC)
- set_pages_array_wc(bo->pages, bo->base.size >> PAGE_SHIFT);
+ set_pages_array_wc(bo->pages, ivpu_bo_size(bo) >> PAGE_SHIFT);
else if (bo->flags & DRM_IVPU_BO_UNCACHED)
- set_pages_array_uc(bo->pages, bo->base.size >> PAGE_SHIFT);
+ set_pages_array_uc(bo->pages, ivpu_bo_size(bo) >> PAGE_SHIFT);
prot = ivpu_bo_pgprot(bo, PAGE_KERNEL);
- bo->kvaddr = vmap(bo->pages, bo->base.size >> PAGE_SHIFT, VM_MAP, prot);
+ bo->kvaddr = vmap(bo->pages, ivpu_bo_size(bo) >> PAGE_SHIFT, VM_MAP, prot);
if (!bo->kvaddr) {
ivpu_err(vdev, "Failed to map BO into kernel virtual memory\n");
goto err_put;
}
ivpu_dbg(vdev, BO, "alloc internal: ctx 0 vpu_addr 0x%llx size %zu flags 0x%x\n",
- bo->vpu_addr, bo->base.size, flags);
+ bo->vpu_addr, ivpu_bo_size(bo), flags);
return bo;
@@ -718,7 +718,7 @@ static void ivpu_bo_print_info(struct ivpu_bo *bo, struct drm_printer *p)
dma_refcount = atomic_long_read(&bo->base.dma_buf->file->f_count);
drm_printf(p, "%5u %6d %16llx %10lu %10u %12lu %14s\n",
- bo->ctx->id, bo->handle, bo->vpu_addr, bo->base.size,
+ bo->ctx->id, bo->handle, bo->vpu_addr, ivpu_bo_size(bo),
kref_read(&bo->base.refcount), dma_refcount, bo->ops->name);
}
diff --git a/drivers/accel/ivpu/ivpu_gem.h b/drivers/accel/ivpu/ivpu_gem.h
index f4130586ff1b..a0b4d4a32b3b 100644
--- a/drivers/accel/ivpu/ivpu_gem.h
+++ b/drivers/accel/ivpu/ivpu_gem.h
@@ -8,8 +8,6 @@
#include <drm/drm_gem.h>
#include <drm/drm_mm.h>
-#define DRM_IVPU_BO_NOSNOOP 0x10000000
-
struct dma_buf;
struct ivpu_bo_ops;
struct ivpu_file_priv;
@@ -70,9 +68,19 @@ static inline struct ivpu_bo *to_ivpu_bo(struct drm_gem_object *obj)
return container_of(obj, struct ivpu_bo, base);
}
+static inline void *ivpu_bo_vaddr(struct ivpu_bo *bo)
+{
+ return bo->kvaddr;
+}
+
+static inline size_t ivpu_bo_size(struct ivpu_bo *bo)
+{
+ return bo->base.size;
+}
+
static inline struct page *ivpu_bo_get_page(struct ivpu_bo *bo, u64 offset)
{
- if (offset > bo->base.size || !bo->pages)
+ if (offset > ivpu_bo_size(bo) || !bo->pages)
return NULL;
return bo->pages[offset / PAGE_SIZE];
@@ -85,9 +93,6 @@ static inline u32 ivpu_bo_cache_mode(struct ivpu_bo *bo)
static inline bool ivpu_bo_is_snooped(struct ivpu_bo *bo)
{
- if (bo->flags & DRM_IVPU_BO_NOSNOOP)
- return false;
-
return ivpu_bo_cache_mode(bo) == DRM_IVPU_BO_CACHED;
}
@@ -112,21 +117,21 @@ static inline void *ivpu_to_cpu_addr(struct ivpu_bo *bo, u32 vpu_addr)
if (vpu_addr < bo->vpu_addr)
return NULL;
- if (vpu_addr >= (bo->vpu_addr + bo->base.size))
+ if (vpu_addr >= (bo->vpu_addr + ivpu_bo_size(bo)))
return NULL;
- return bo->kvaddr + (vpu_addr - bo->vpu_addr);
+ return ivpu_bo_vaddr(bo) + (vpu_addr - bo->vpu_addr);
}
static inline u32 cpu_to_vpu_addr(struct ivpu_bo *bo, void *cpu_addr)
{
- if (cpu_addr < bo->kvaddr)
+ if (cpu_addr < ivpu_bo_vaddr(bo))
return 0;
- if (cpu_addr >= (bo->kvaddr + bo->base.size))
+ if (cpu_addr >= (ivpu_bo_vaddr(bo) + ivpu_bo_size(bo)))
return 0;
- return bo->vpu_addr + (cpu_addr - bo->kvaddr);
+ return bo->vpu_addr + (cpu_addr - ivpu_bo_vaddr(bo));
}
#endif /* __IVPU_GEM_H__ */
diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h
index ab341237bcf9..1079e06255ba 100644
--- a/drivers/accel/ivpu/ivpu_hw.h
+++ b/drivers/accel/ivpu/ivpu_hw.h
@@ -13,6 +13,7 @@ struct ivpu_hw_ops {
int (*power_up)(struct ivpu_device *vdev);
int (*boot_fw)(struct ivpu_device *vdev);
int (*power_down)(struct ivpu_device *vdev);
+ int (*reset)(struct ivpu_device *vdev);
bool (*is_idle)(struct ivpu_device *vdev);
void (*wdt_disable)(struct ivpu_device *vdev);
void (*diagnose_failure)(struct ivpu_device *vdev);
@@ -91,6 +92,13 @@ static inline int ivpu_hw_power_down(struct ivpu_device *vdev)
return vdev->hw->ops->power_down(vdev);
};
+static inline int ivpu_hw_reset(struct ivpu_device *vdev)
+{
+ ivpu_dbg(vdev, PM, "HW reset\n");
+
+ return vdev->hw->ops->reset(vdev);
+};
+
static inline void ivpu_hw_wdt_disable(struct ivpu_device *vdev)
{
vdev->hw->ops->wdt_disable(vdev);
diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c
index 9eae1c241bc0..d530384f8d60 100644
--- a/drivers/accel/ivpu/ivpu_hw_37xx.c
+++ b/drivers/accel/ivpu/ivpu_hw_37xx.c
@@ -53,10 +53,12 @@
#define ICB_0_1_IRQ_MASK ((((u64)ICB_1_IRQ_MASK) << 32) | ICB_0_IRQ_MASK)
-#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE)) | \
- (REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \
+#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \
(REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, UFI_ERR)))
+#define BUTTRESS_ALL_IRQ_MASK (BUTTRESS_IRQ_MASK | \
+ (REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE)))
+
#define BUTTRESS_IRQ_ENABLE_MASK ((u32)~BUTTRESS_IRQ_MASK)
#define BUTTRESS_IRQ_DISABLE_MASK ((u32)-1)
@@ -68,57 +70,32 @@
(REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI)) | \
(REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI_CMX)))
-static char *ivpu_platform_to_str(u32 platform)
-{
- switch (platform) {
- case IVPU_PLATFORM_SILICON:
- return "IVPU_PLATFORM_SILICON";
- case IVPU_PLATFORM_SIMICS:
- return "IVPU_PLATFORM_SIMICS";
- case IVPU_PLATFORM_FPGA:
- return "IVPU_PLATFORM_FPGA";
- default:
- return "Invalid platform";
- }
-}
-
-static void ivpu_hw_read_platform(struct ivpu_device *vdev)
-{
- u32 gen_ctrl = REGV_RD32(VPU_37XX_HOST_SS_GEN_CTRL);
- u32 platform = REG_GET_FLD(VPU_37XX_HOST_SS_GEN_CTRL, PS, gen_ctrl);
-
- if (platform == IVPU_PLATFORM_SIMICS || platform == IVPU_PLATFORM_FPGA)
- vdev->platform = platform;
- else
- vdev->platform = IVPU_PLATFORM_SILICON;
-
- ivpu_dbg(vdev, MISC, "Platform type: %s (%d)\n",
- ivpu_platform_to_str(vdev->platform), vdev->platform);
-}
-
static void ivpu_hw_wa_init(struct ivpu_device *vdev)
{
- vdev->wa.punit_disabled = ivpu_is_fpga(vdev);
+ vdev->wa.punit_disabled = false;
vdev->wa.clear_runtime_mem = false;
vdev->wa.d3hot_after_power_off = true;
- if (ivpu_device_id(vdev) == PCI_DEVICE_ID_MTL && ivpu_revision(vdev) < 4)
+ REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, BUTTRESS_ALL_IRQ_MASK);
+ if (REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) == BUTTRESS_ALL_IRQ_MASK) {
+ /* Writing 1s does not clear the interrupt status register */
vdev->wa.interrupt_clear_with_0 = true;
+ REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, 0x0);
+ }
+
+ IVPU_PRINT_WA(punit_disabled);
+ IVPU_PRINT_WA(clear_runtime_mem);
+ IVPU_PRINT_WA(d3hot_after_power_off);
+ IVPU_PRINT_WA(interrupt_clear_with_0);
}
static void ivpu_hw_timeouts_init(struct ivpu_device *vdev)
{
- if (ivpu_is_simics(vdev) || ivpu_is_fpga(vdev)) {
- vdev->timeout.boot = 100000;
- vdev->timeout.jsm = 50000;
- vdev->timeout.tdr = 2000000;
- vdev->timeout.reschedule_suspend = 1000;
- } else {
- vdev->timeout.boot = 1000;
- vdev->timeout.jsm = 500;
- vdev->timeout.tdr = 2000;
- vdev->timeout.reschedule_suspend = 10;
- }
+ vdev->timeout.boot = 1000;
+ vdev->timeout.jsm = 500;
+ vdev->timeout.tdr = 2000;
+ vdev->timeout.reschedule_suspend = 10;
+ vdev->timeout.autosuspend = 10;
}
static int ivpu_pll_wait_for_cmd_send(struct ivpu_device *vdev)
@@ -213,8 +190,7 @@ static int ivpu_pll_drive(struct ivpu_device *vdev, bool enable)
int ret;
if (IVPU_WA(punit_disabled)) {
- ivpu_dbg(vdev, PM, "Skipping PLL request on %s\n",
- ivpu_platform_to_str(vdev->platform));
+ ivpu_dbg(vdev, PM, "Skipping PLL request\n");
return 0;
}
@@ -345,10 +321,10 @@ static int ivpu_boot_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val)
static int ivpu_boot_top_noc_qrenqn_check(struct ivpu_device *vdev, u32 exp_val)
{
- u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QREQN);
+ u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN);
- if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) ||
- !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val))
+ if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) ||
+ !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val))
return -EIO;
return 0;
@@ -356,10 +332,10 @@ static int ivpu_boot_top_noc_qrenqn_check(struct ivpu_device *vdev, u32 exp_val)
static int ivpu_boot_top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val)
{
- u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QACCEPTN);
+ u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QACCEPTN);
- if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) ||
- !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val))
+ if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) ||
+ !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val))
return -EIO;
return 0;
@@ -367,10 +343,10 @@ static int ivpu_boot_top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_va
static int ivpu_boot_top_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val)
{
- u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QDENY);
+ u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QDENY);
- if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) ||
- !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val))
+ if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) ||
+ !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val))
return -EIO;
return 0;
@@ -423,15 +399,15 @@ static int ivpu_boot_host_ss_top_noc_drive(struct ivpu_device *vdev, bool enable
int ret;
u32 val;
- val = REGV_RD32(MTL_VPU_TOP_NOC_QREQN);
+ val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN);
if (enable) {
- val = REG_SET_FLD(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, val);
- val = REG_SET_FLD(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, val);
+ val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val);
+ val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val);
} else {
- val = REG_CLR_FLD(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, val);
- val = REG_CLR_FLD(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, val);
+ val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val);
+ val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val);
}
- REGV_WR32(MTL_VPU_TOP_NOC_QREQN, val);
+ REGV_WR32(VPU_37XX_TOP_NOC_QREQN, val);
ret = ivpu_boot_top_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0);
if (ret) {
@@ -477,10 +453,6 @@ static void ivpu_boot_pwr_island_drive(struct ivpu_device *vdev, bool enable)
static int ivpu_boot_wait_for_pwr_island_status(struct ivpu_device *vdev, u32 exp_val)
{
- /* FPGA model (UPF) is not power aware, skipped Power Island polling */
- if (ivpu_is_fpga(vdev))
- return 0;
-
return REGV_POLL_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_STATUS0, MSS_CPU,
exp_val, PWR_ISLAND_STATUS_TIMEOUT_US);
}
@@ -536,6 +508,16 @@ static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev)
return ret;
}
+static int ivpu_boot_pwr_domain_disable(struct ivpu_device *vdev)
+{
+ ivpu_boot_dpu_active_drive(vdev, false);
+ ivpu_boot_pwr_island_isolation_drive(vdev, true);
+ ivpu_boot_pwr_island_trickle_drive(vdev, false);
+ ivpu_boot_pwr_island_drive(vdev, false);
+
+ return ivpu_boot_wait_for_pwr_island_status(vdev, 0x0);
+}
+
static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev)
{
u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES);
@@ -563,17 +545,17 @@ static void ivpu_boot_soc_cpu_boot(struct ivpu_device *vdev)
{
u32 val;
- val = REGV_RD32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC);
- val = REG_SET_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTRUN0, val);
+ val = REGV_RD32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC);
+ val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTRUN0, val);
- val = REG_CLR_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTVEC, val);
- REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
+ val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTVEC, val);
+ REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
- val = REG_SET_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val);
- REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
+ val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val);
+ REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
- val = REG_CLR_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val);
- REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
+ val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val);
+ REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
val = vdev->fw->entry_point >> 9;
REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val);
@@ -625,30 +607,26 @@ static int ivpu_hw_37xx_info_init(struct ivpu_device *vdev)
ivpu_hw_init_range(&hw->ranges.shave, 0x180000000, SZ_2G);
ivpu_hw_init_range(&hw->ranges.dma, 0x200000000, SZ_8G);
+ vdev->platform = IVPU_PLATFORM_SILICON;
+ ivpu_hw_wa_init(vdev);
+ ivpu_hw_timeouts_init(vdev);
+
return 0;
}
static int ivpu_hw_37xx_reset(struct ivpu_device *vdev)
{
- int ret;
- u32 val;
-
- if (IVPU_WA(punit_disabled))
- return 0;
+ int ret = 0;
- ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
- if (ret) {
- ivpu_err(vdev, "Timed out waiting for TRIGGER bit\n");
- return ret;
+ if (ivpu_boot_pwr_domain_disable(vdev)) {
+ ivpu_err(vdev, "Failed to disable power domain\n");
+ ret = -EIO;
}
- val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_IP_RESET);
- val = REG_SET_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, val);
- REGB_WR32(VPU_37XX_BUTTRESS_VPU_IP_RESET, val);
-
- ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
- if (ret)
- ivpu_err(vdev, "Timed out waiting for RESET completion\n");
+ if (ivpu_pll_disable(vdev)) {
+ ivpu_err(vdev, "Failed to disable PLL\n");
+ ret = -EIO;
+ }
return ret;
}
@@ -681,14 +659,6 @@ static int ivpu_hw_37xx_power_up(struct ivpu_device *vdev)
{
int ret;
- ivpu_hw_read_platform(vdev);
- ivpu_hw_wa_init(vdev);
- ivpu_hw_timeouts_init(vdev);
-
- ret = ivpu_hw_37xx_reset(vdev);
- if (ret)
- ivpu_warn(vdev, "Failed to reset HW: %d\n", ret);
-
ret = ivpu_hw_37xx_d0i3_disable(vdev);
if (ret)
ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret);
@@ -756,11 +726,11 @@ static int ivpu_hw_37xx_power_down(struct ivpu_device *vdev)
{
int ret = 0;
- if (!ivpu_hw_37xx_is_idle(vdev) && ivpu_hw_37xx_reset(vdev))
- ivpu_err(vdev, "Failed to reset the VPU\n");
+ if (!ivpu_hw_37xx_is_idle(vdev))
+ ivpu_warn(vdev, "VPU not idle during power down\n");
- if (ivpu_pll_disable(vdev)) {
- ivpu_err(vdev, "Failed to disable PLL\n");
+ if (ivpu_hw_37xx_reset(vdev)) {
+ ivpu_err(vdev, "Failed to reset VPU\n");
ret = -EIO;
}
@@ -777,17 +747,17 @@ static void ivpu_hw_37xx_wdt_disable(struct ivpu_device *vdev)
u32 val;
/* Enable writing and set non-zero WDT value */
- REGV_WR32(MTL_VPU_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE);
- REGV_WR32(MTL_VPU_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE);
+ REGV_WR32(VPU_37XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE);
+ REGV_WR32(VPU_37XX_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE);
/* Enable writing and disable watchdog timer */
- REGV_WR32(MTL_VPU_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE);
- REGV_WR32(MTL_VPU_CPU_SS_TIM_WDOG_EN, 0);
+ REGV_WR32(VPU_37XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE);
+ REGV_WR32(VPU_37XX_CPU_SS_TIM_WDOG_EN, 0);
/* Now clear the timeout interrupt */
- val = REGV_RD32(MTL_VPU_CPU_SS_TIM_GEN_CONFIG);
- val = REG_CLR_FLD(MTL_VPU_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val);
- REGV_WR32(MTL_VPU_CPU_SS_TIM_GEN_CONFIG, val);
+ val = REGV_RD32(VPU_37XX_CPU_SS_TIM_GEN_CONFIG);
+ val = REG_CLR_FLD(VPU_37XX_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val);
+ REGV_WR32(VPU_37XX_CPU_SS_TIM_GEN_CONFIG, val);
}
static u32 ivpu_hw_37xx_pll_to_freq(u32 ratio, u32 config)
@@ -834,10 +804,10 @@ static u32 ivpu_hw_37xx_reg_telemetry_enable_get(struct ivpu_device *vdev)
static void ivpu_hw_37xx_reg_db_set(struct ivpu_device *vdev, u32 db_id)
{
- u32 reg_stride = MTL_VPU_CPU_SS_DOORBELL_1 - MTL_VPU_CPU_SS_DOORBELL_0;
- u32 val = REG_FLD(MTL_VPU_CPU_SS_DOORBELL_0, SET);
+ u32 reg_stride = VPU_37XX_CPU_SS_DOORBELL_1 - VPU_37XX_CPU_SS_DOORBELL_0;
+ u32 val = REG_FLD(VPU_37XX_CPU_SS_DOORBELL_0, SET);
- REGV_WR32I(MTL_VPU_CPU_SS_DOORBELL_0, reg_stride, db_id, val);
+ REGV_WR32I(VPU_37XX_CPU_SS_DOORBELL_0, reg_stride, db_id, val);
}
static u32 ivpu_hw_37xx_reg_ipc_rx_addr_get(struct ivpu_device *vdev)
@@ -854,7 +824,7 @@ static u32 ivpu_hw_37xx_reg_ipc_rx_count_get(struct ivpu_device *vdev)
static void ivpu_hw_37xx_reg_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr)
{
- REGV_WR32(MTL_VPU_CPU_SS_TIM_IPC_FIFO, vpu_addr);
+ REGV_WR32(VPU_37XX_CPU_SS_TIM_IPC_FIFO, vpu_addr);
}
static void ivpu_hw_37xx_irq_clear(struct ivpu_device *vdev)
@@ -940,9 +910,6 @@ static u32 ivpu_hw_37xx_irqb_handler(struct ivpu_device *vdev, int irq)
if (status == 0)
return 0;
- /* Disable global interrupt before handling local buttress interrupts */
- REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x1);
-
if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE, status))
ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x",
REGB_RD32(VPU_37XX_BUTTRESS_CURRENT_PLL));
@@ -974,9 +941,6 @@ static u32 ivpu_hw_37xx_irqb_handler(struct ivpu_device *vdev, int irq)
else
REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, status);
- /* Re-enable global interrupt */
- REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x0);
-
if (schedule_recovery)
ivpu_pm_schedule_recovery(vdev);
@@ -988,9 +952,14 @@ static irqreturn_t ivpu_hw_37xx_irq_handler(int irq, void *ptr)
struct ivpu_device *vdev = ptr;
u32 ret_irqv, ret_irqb;
+ REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x1);
+
ret_irqv = ivpu_hw_37xx_irqv_handler(vdev, irq);
ret_irqb = ivpu_hw_37xx_irqb_handler(vdev, irq);
+ /* Re-enable global interrupts to re-trigger MSI for pending interrupts */
+ REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x0);
+
return IRQ_RETVAL(ret_irqb | ret_irqv);
}
@@ -1029,6 +998,7 @@ const struct ivpu_hw_ops ivpu_hw_37xx_ops = {
.power_up = ivpu_hw_37xx_power_up,
.is_idle = ivpu_hw_37xx_is_idle,
.power_down = ivpu_hw_37xx_power_down,
+ .reset = ivpu_hw_37xx_reset,
.boot_fw = ivpu_hw_37xx_boot_fw,
.wdt_disable = ivpu_hw_37xx_wdt_disable,
.diagnose_failure = ivpu_hw_37xx_diagnose_failure,
diff --git a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h
index 6e4e915948f9..4083beb5e9db 100644
--- a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h
+++ b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h
@@ -3,70 +3,70 @@
* Copyright (C) 2020-2023 Intel Corporation
*/
-#ifndef __IVPU_HW_MTL_REG_H__
-#define __IVPU_HW_MTL_REG_H__
+#ifndef __IVPU_HW_37XX_REG_H__
+#define __IVPU_HW_37XX_REG_H__
#include <linux/bits.h>
-#define VPU_37XX_BUTTRESS_INTERRUPT_TYPE 0x00000000u
+#define VPU_37XX_BUTTRESS_INTERRUPT_TYPE 0x00000000u
-#define VPU_37XX_BUTTRESS_INTERRUPT_STAT 0x00000004u
-#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0)
+#define VPU_37XX_BUTTRESS_INTERRUPT_STAT 0x00000004u
+#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0)
#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_ATS_ERR_MASK BIT_MASK(1)
#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_UFI_ERR_MASK BIT_MASK(2)
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0 0x00000008u
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0)
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16)
+#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0 0x00000008u
+#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0)
+#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16)
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1 0x0000000cu
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0)
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16)
+#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1 0x0000000cu
+#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0)
+#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16)
-#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2 0x00000010u
+#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2 0x00000010u
#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2_CONFIG_MASK GENMASK(15, 0)
-#define VPU_37XX_BUTTRESS_WP_REQ_CMD 0x00000014u
+#define VPU_37XX_BUTTRESS_WP_REQ_CMD 0x00000014u
#define VPU_37XX_BUTTRESS_WP_REQ_CMD_SEND_MASK BIT_MASK(0)
#define VPU_37XX_BUTTRESS_WP_DOWNLOAD 0x00000018u
#define VPU_37XX_BUTTRESS_WP_DOWNLOAD_TARGET_RATIO_MASK GENMASK(15, 0)
#define VPU_37XX_BUTTRESS_CURRENT_PLL 0x0000001cu
-#define VPU_37XX_BUTTRESS_CURRENT_PLL_RATIO_MASK GENMASK(15, 0)
+#define VPU_37XX_BUTTRESS_CURRENT_PLL_RATIO_MASK GENMASK(15, 0)
-#define VPU_37XX_BUTTRESS_PLL_ENABLE 0x00000020u
+#define VPU_37XX_BUTTRESS_PLL_ENABLE 0x00000020u
-#define VPU_37XX_BUTTRESS_FMIN_FUSE 0x00000024u
-#define VPU_37XX_BUTTRESS_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0)
-#define VPU_37XX_BUTTRESS_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8)
+#define VPU_37XX_BUTTRESS_FMIN_FUSE 0x00000024u
+#define VPU_37XX_BUTTRESS_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0)
+#define VPU_37XX_BUTTRESS_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8)
-#define VPU_37XX_BUTTRESS_FMAX_FUSE 0x00000028u
-#define VPU_37XX_BUTTRESS_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0)
+#define VPU_37XX_BUTTRESS_FMAX_FUSE 0x00000028u
+#define VPU_37XX_BUTTRESS_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0)
-#define VPU_37XX_BUTTRESS_TILE_FUSE 0x0000002cu
+#define VPU_37XX_BUTTRESS_TILE_FUSE 0x0000002cu
#define VPU_37XX_BUTTRESS_TILE_FUSE_VALID_MASK BIT_MASK(0)
-#define VPU_37XX_BUTTRESS_TILE_FUSE_SKU_MASK GENMASK(3, 2)
+#define VPU_37XX_BUTTRESS_TILE_FUSE_SKU_MASK GENMASK(3, 2)
-#define VPU_37XX_BUTTRESS_LOCAL_INT_MASK 0x00000030u
-#define VPU_37XX_BUTTRESS_GLOBAL_INT_MASK 0x00000034u
+#define VPU_37XX_BUTTRESS_LOCAL_INT_MASK 0x00000030u
+#define VPU_37XX_BUTTRESS_GLOBAL_INT_MASK 0x00000034u
-#define VPU_37XX_BUTTRESS_PLL_STATUS 0x00000040u
+#define VPU_37XX_BUTTRESS_PLL_STATUS 0x00000040u
#define VPU_37XX_BUTTRESS_PLL_STATUS_LOCK_MASK BIT_MASK(1)
-#define VPU_37XX_BUTTRESS_VPU_STATUS 0x00000044u
+#define VPU_37XX_BUTTRESS_VPU_STATUS 0x00000044u
#define VPU_37XX_BUTTRESS_VPU_STATUS_READY_MASK BIT_MASK(0)
#define VPU_37XX_BUTTRESS_VPU_STATUS_IDLE_MASK BIT_MASK(1)
-#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL 0x00000060u
-#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0)
-#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL_I3_MASK BIT_MASK(2)
+#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL 0x00000060u
+#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0)
+#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL_I3_MASK BIT_MASK(2)
#define VPU_37XX_BUTTRESS_VPU_IP_RESET 0x00000050u
-#define VPU_37XX_BUTTRESS_VPU_IP_RESET_TRIGGER_MASK BIT_MASK(0)
+#define VPU_37XX_BUTTRESS_VPU_IP_RESET_TRIGGER_MASK BIT_MASK(0)
#define VPU_37XX_BUTTRESS_VPU_TELEMETRY_OFFSET 0x00000080u
-#define VPU_37XX_BUTTRESS_VPU_TELEMETRY_SIZE 0x00000084u
+#define VPU_37XX_BUTTRESS_VPU_TELEMETRY_SIZE 0x00000084u
#define VPU_37XX_BUTTRESS_VPU_TELEMETRY_ENABLE 0x00000088u
#define VPU_37XX_BUTTRESS_ATS_ERR_LOG_0 0x000000a0u
@@ -74,9 +74,9 @@
#define VPU_37XX_BUTTRESS_ATS_ERR_CLEAR 0x000000a8u
#define VPU_37XX_BUTTRESS_UFI_ERR_LOG 0x000000b0u
-#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_CQ_ID_MASK GENMASK(11, 0)
-#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_AXI_ID_MASK GENMASK(19, 12)
-#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_OPCODE_MASK GENMASK(24, 20)
+#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_CQ_ID_MASK GENMASK(11, 0)
+#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_AXI_ID_MASK GENMASK(19, 12)
+#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_OPCODE_MASK GENMASK(24, 20)
#define VPU_37XX_BUTTRESS_UFI_ERR_CLEAR 0x000000b4u
@@ -113,17 +113,17 @@
#define VPU_37XX_HOST_SS_NOC_QDENY 0x0000015cu
#define VPU_37XX_HOST_SS_NOC_QDENY_TOP_SOCMMIO_MASK BIT_MASK(0)
-#define MTL_VPU_TOP_NOC_QREQN 0x00000160u
-#define MTL_VPU_TOP_NOC_QREQN_CPU_CTRL_MASK BIT_MASK(0)
-#define MTL_VPU_TOP_NOC_QREQN_HOSTIF_L2CACHE_MASK BIT_MASK(1)
+#define VPU_37XX_TOP_NOC_QREQN 0x00000160u
+#define VPU_37XX_TOP_NOC_QREQN_CPU_CTRL_MASK BIT_MASK(0)
+#define VPU_37XX_TOP_NOC_QREQN_HOSTIF_L2CACHE_MASK BIT_MASK(1)
-#define MTL_VPU_TOP_NOC_QACCEPTN 0x00000164u
-#define MTL_VPU_TOP_NOC_QACCEPTN_CPU_CTRL_MASK BIT_MASK(0)
-#define MTL_VPU_TOP_NOC_QACCEPTN_HOSTIF_L2CACHE_MASK BIT_MASK(1)
+#define VPU_37XX_TOP_NOC_QACCEPTN 0x00000164u
+#define VPU_37XX_TOP_NOC_QACCEPTN_CPU_CTRL_MASK BIT_MASK(0)
+#define VPU_37XX_TOP_NOC_QACCEPTN_HOSTIF_L2CACHE_MASK BIT_MASK(1)
-#define MTL_VPU_TOP_NOC_QDENY 0x00000168u
-#define MTL_VPU_TOP_NOC_QDENY_CPU_CTRL_MASK BIT_MASK(0)
-#define MTL_VPU_TOP_NOC_QDENY_HOSTIF_L2CACHE_MASK BIT_MASK(1)
+#define VPU_37XX_TOP_NOC_QDENY 0x00000168u
+#define VPU_37XX_TOP_NOC_QDENY_CPU_CTRL_MASK BIT_MASK(0)
+#define VPU_37XX_TOP_NOC_QDENY_HOSTIF_L2CACHE_MASK BIT_MASK(1)
#define VPU_37XX_HOST_SS_FW_SOC_IRQ_EN 0x00000170u
#define VPU_37XX_HOST_SS_FW_SOC_IRQ_EN_CSS_ROM_CMX_MASK BIT_MASK(0)
@@ -140,9 +140,9 @@
#define VPU_37XX_HOST_SS_ICB_STATUS_0_TIMER_2_INT_MASK BIT_MASK(2)
#define VPU_37XX_HOST_SS_ICB_STATUS_0_TIMER_3_INT_MASK BIT_MASK(3)
#define VPU_37XX_HOST_SS_ICB_STATUS_0_HOST_IPC_FIFO_INT_MASK BIT_MASK(4)
-#define VPU_37XX_HOST_SS_ICB_STATUS_0_MMU_IRQ_0_INT_MASK BIT_MASK(5)
-#define VPU_37XX_HOST_SS_ICB_STATUS_0_MMU_IRQ_1_INT_MASK BIT_MASK(6)
-#define VPU_37XX_HOST_SS_ICB_STATUS_0_MMU_IRQ_2_INT_MASK BIT_MASK(7)
+#define VPU_37XX_HOST_SS_ICB_STATUS_0_MMU_IRQ_0_INT_MASK BIT_MASK(5)
+#define VPU_37XX_HOST_SS_ICB_STATUS_0_MMU_IRQ_1_INT_MASK BIT_MASK(6)
+#define VPU_37XX_HOST_SS_ICB_STATUS_0_MMU_IRQ_2_INT_MASK BIT_MASK(7)
#define VPU_37XX_HOST_SS_ICB_STATUS_0_NOC_FIREWALL_INT_MASK BIT_MASK(8)
#define VPU_37XX_HOST_SS_ICB_STATUS_0_CPU_INT_REDIRECT_0_INT_MASK BIT_MASK(30)
#define VPU_37XX_HOST_SS_ICB_STATUS_0_CPU_INT_REDIRECT_1_INT_MASK BIT_MASK(31)
@@ -164,14 +164,14 @@
#define VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT_FILL_LEVEL_MASK GENMASK(23, 16)
#define VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT_RSVD0_MASK GENMASK(31, 24)
-#define VPU_37XX_HOST_SS_AON_PWR_ISO_EN0 0x00030020u
+#define VPU_37XX_HOST_SS_AON_PWR_ISO_EN0 0x00030020u
#define VPU_37XX_HOST_SS_AON_PWR_ISO_EN0_MSS_CPU_MASK BIT_MASK(3)
#define VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0 0x00030024u
-#define VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0_MSS_CPU_MASK BIT_MASK(3)
+#define VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0_MSS_CPU_MASK BIT_MASK(3)
#define VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0 0x00030028u
-#define VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0_MSS_CPU_MASK BIT_MASK(3)
+#define VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0_MSS_CPU_MASK BIT_MASK(3)
#define VPU_37XX_HOST_SS_AON_PWR_ISLAND_STATUS0 0x0003002cu
#define VPU_37XX_HOST_SS_AON_PWR_ISLAND_STATUS0_MSS_CPU_MASK BIT_MASK(3)
@@ -187,47 +187,14 @@
#define VPU_37XX_HOST_SS_LOADING_ADDRESS_LO_IOSF_RS_ID_MASK GENMASK(2, 1)
#define VPU_37XX_HOST_SS_LOADING_ADDRESS_LO_IMAGE_LOCATION_MASK GENMASK(31, 3)
-#define VPU_37XX_HOST_SS_WORKPOINT_CONFIG_MIRROR 0x00082020u
+#define VPU_37XX_HOST_SS_WORKPOINT_CONFIG_MIRROR 0x00082020u
#define VPU_37XX_HOST_SS_WORKPOINT_CONFIG_MIRROR_FINAL_PLL_FREQ_MASK GENMASK(15, 0)
#define VPU_37XX_HOST_SS_WORKPOINT_CONFIG_MIRROR_CONFIG_ID_MASK GENMASK(31, 16)
-#define VPU_37XX_HOST_MMU_IDR0 0x00200000u
-#define VPU_37XX_HOST_MMU_IDR1 0x00200004u
-#define VPU_37XX_HOST_MMU_IDR3 0x0020000cu
-#define VPU_37XX_HOST_MMU_IDR5 0x00200014u
-#define VPU_37XX_HOST_MMU_CR0 0x00200020u
-#define VPU_37XX_HOST_MMU_CR0ACK 0x00200024u
-#define VPU_37XX_HOST_MMU_CR1 0x00200028u
-#define VPU_37XX_HOST_MMU_CR2 0x0020002cu
-#define VPU_37XX_HOST_MMU_IRQ_CTRL 0x00200050u
-#define VPU_37XX_HOST_MMU_IRQ_CTRLACK 0x00200054u
-
-#define VPU_37XX_HOST_MMU_GERROR 0x00200060u
-#define VPU_37XX_HOST_MMU_GERROR_CMDQ_MASK BIT_MASK(0)
-#define VPU_37XX_HOST_MMU_GERROR_EVTQ_ABT_MASK BIT_MASK(2)
-#define VPU_37XX_HOST_MMU_GERROR_PRIQ_ABT_MASK BIT_MASK(3)
-#define VPU_37XX_HOST_MMU_GERROR_MSI_CMDQ_ABT_MASK BIT_MASK(4)
-#define VPU_37XX_HOST_MMU_GERROR_MSI_EVTQ_ABT_MASK BIT_MASK(5)
-#define VPU_37XX_HOST_MMU_GERROR_MSI_PRIQ_ABT_MASK BIT_MASK(6)
-#define VPU_37XX_HOST_MMU_GERROR_MSI_ABT_MASK BIT_MASK(7)
-
-#define VPU_37XX_HOST_MMU_GERRORN 0x00200064u
-
-#define VPU_37XX_HOST_MMU_STRTAB_BASE 0x00200080u
-#define VPU_37XX_HOST_MMU_STRTAB_BASE_CFG 0x00200088u
-#define VPU_37XX_HOST_MMU_CMDQ_BASE 0x00200090u
-#define VPU_37XX_HOST_MMU_CMDQ_PROD 0x00200098u
-#define VPU_37XX_HOST_MMU_CMDQ_CONS 0x0020009cu
-#define VPU_37XX_HOST_MMU_EVTQ_BASE 0x002000a0u
-#define VPU_37XX_HOST_MMU_EVTQ_PROD 0x002000a8u
-#define VPU_37XX_HOST_MMU_EVTQ_CONS 0x002000acu
-#define VPU_37XX_HOST_MMU_EVTQ_PROD_SEC (0x002000a8u + SZ_64K)
-#define VPU_37XX_HOST_MMU_EVTQ_CONS_SEC (0x002000acu + SZ_64K)
-
#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES 0x00360000u
#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_CACHE_OVERRIDE_EN_MASK BIT_MASK(0)
-#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_AWCACHE_OVERRIDE_MASK BIT_MASK(1)
-#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_ARCACHE_OVERRIDE_MASK BIT_MASK(2)
+#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_AWCACHE_OVERRIDE_MASK BIT_MASK(1)
+#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_ARCACHE_OVERRIDE_MASK BIT_MASK(2)
#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_NOSNOOP_OVERRIDE_EN_MASK BIT_MASK(3)
#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_AW_NOSNOOP_OVERRIDE_MASK BIT_MASK(4)
#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_AR_NOSNOOP_OVERRIDE_MASK BIT_MASK(5)
@@ -246,36 +213,36 @@
#define VPU_37XX_HOST_IF_TBU_MMUSSIDV_TBU4_AWMMUSSIDV_MASK BIT_MASK(8)
#define VPU_37XX_HOST_IF_TBU_MMUSSIDV_TBU4_ARMMUSSIDV_MASK BIT_MASK(9)
-#define MTL_VPU_CPU_SS_DSU_LEON_RT_BASE 0x04000000u
-#define MTL_VPU_CPU_SS_DSU_LEON_RT_DSU_CTRL 0x04000000u
-#define MTL_VPU_CPU_SS_DSU_LEON_RT_PC_REG 0x04400010u
-#define MTL_VPU_CPU_SS_DSU_LEON_RT_NPC_REG 0x04400014u
-#define MTL_VPU_CPU_SS_DSU_LEON_RT_DSU_TRAP_REG 0x04400020u
+#define VPU_37XX_CPU_SS_DSU_LEON_RT_BASE 0x04000000u
+#define VPU_37XX_CPU_SS_DSU_LEON_RT_DSU_CTRL 0x04000000u
+#define VPU_37XX_CPU_SS_DSU_LEON_RT_PC_REG 0x04400010u
+#define VPU_37XX_CPU_SS_DSU_LEON_RT_NPC_REG 0x04400014u
+#define VPU_37XX_CPU_SS_DSU_LEON_RT_DSU_TRAP_REG 0x04400020u
-#define MTL_VPU_CPU_SS_MSSCPU_CPR_CLK_SET 0x06010004u
-#define MTL_VPU_CPU_SS_MSSCPU_CPR_CLK_SET_CPU_DSU_MASK BIT_MASK(1)
+#define VPU_37XX_CPU_SS_MSSCPU_CPR_CLK_SET 0x06010004u
+#define VPU_37XX_CPU_SS_MSSCPU_CPR_CLK_SET_CPU_DSU_MASK BIT_MASK(1)
-#define MTL_VPU_CPU_SS_MSSCPU_CPR_RST_CLR 0x06010018u
-#define MTL_VPU_CPU_SS_MSSCPU_CPR_RST_CLR_CPU_DSU_MASK BIT_MASK(1)
+#define VPU_37XX_CPU_SS_MSSCPU_CPR_RST_CLR 0x06010018u
+#define VPU_37XX_CPU_SS_MSSCPU_CPR_RST_CLR_CPU_DSU_MASK BIT_MASK(1)
-#define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC 0x06010040u
-#define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTRUN0_MASK BIT_MASK(0)
-#define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RESUME0_MASK BIT_MASK(1)
-#define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTRUN1_MASK BIT_MASK(2)
-#define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RESUME1_MASK BIT_MASK(3)
-#define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTVEC_MASK GENMASK(31, 4)
+#define VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC 0x06010040u
+#define VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTRUN0_MASK BIT_MASK(0)
+#define VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RESUME0_MASK BIT_MASK(1)
+#define VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTRUN1_MASK BIT_MASK(2)
+#define VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RESUME1_MASK BIT_MASK(3)
+#define VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTVEC_MASK GENMASK(31, 4)
-#define MTL_VPU_CPU_SS_TIM_WATCHDOG 0x0602009cu
-#define MTL_VPU_CPU_SS_TIM_WDOG_EN 0x060200a4u
-#define MTL_VPU_CPU_SS_TIM_SAFE 0x060200a8u
-#define MTL_VPU_CPU_SS_TIM_IPC_FIFO 0x060200f0u
+#define VPU_37XX_CPU_SS_TIM_WATCHDOG 0x0602009cu
+#define VPU_37XX_CPU_SS_TIM_WDOG_EN 0x060200a4u
+#define VPU_37XX_CPU_SS_TIM_SAFE 0x060200a8u
+#define VPU_37XX_CPU_SS_TIM_IPC_FIFO 0x060200f0u
-#define MTL_VPU_CPU_SS_TIM_GEN_CONFIG 0x06021008u
-#define MTL_VPU_CPU_SS_TIM_GEN_CONFIG_WDOG_TO_INT_CLR_MASK BIT_MASK(9)
+#define VPU_37XX_CPU_SS_TIM_GEN_CONFIG 0x06021008u
+#define VPU_37XX_CPU_SS_TIM_GEN_CONFIG_WDOG_TO_INT_CLR_MASK BIT_MASK(9)
-#define MTL_VPU_CPU_SS_DOORBELL_0 0x06300000u
-#define MTL_VPU_CPU_SS_DOORBELL_0_SET_MASK BIT_MASK(0)
+#define VPU_37XX_CPU_SS_DOORBELL_0 0x06300000u
+#define VPU_37XX_CPU_SS_DOORBELL_0_SET_MASK BIT_MASK(0)
-#define MTL_VPU_CPU_SS_DOORBELL_1 0x06301000u
+#define VPU_37XX_CPU_SS_DOORBELL_1 0x06301000u
-#endif /* __IVPU_HW_MTL_REG_H__ */
+#endif /* __IVPU_HW_37XX_REG_H__ */
diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c
index 8bdb59a45da6..e691c49c9841 100644
--- a/drivers/accel/ivpu/ivpu_hw_40xx.c
+++ b/drivers/accel/ivpu/ivpu_hw_40xx.c
@@ -125,6 +125,10 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev)
if (ivpu_hw_gen(vdev) == IVPU_HW_40XX)
vdev->wa.disable_clock_relinquish = true;
+
+ IVPU_PRINT_WA(punit_disabled);
+ IVPU_PRINT_WA(clear_runtime_mem);
+ IVPU_PRINT_WA(disable_clock_relinquish);
}
static void ivpu_hw_timeouts_init(struct ivpu_device *vdev)
@@ -134,16 +138,19 @@ static void ivpu_hw_timeouts_init(struct ivpu_device *vdev)
vdev->timeout.jsm = 50000;
vdev->timeout.tdr = 2000000;
vdev->timeout.reschedule_suspend = 1000;
+ vdev->timeout.autosuspend = -1;
} else if (ivpu_is_simics(vdev)) {
vdev->timeout.boot = 50;
vdev->timeout.jsm = 500;
vdev->timeout.tdr = 10000;
vdev->timeout.reschedule_suspend = 10;
+ vdev->timeout.autosuspend = -1;
} else {
vdev->timeout.boot = 1000;
vdev->timeout.jsm = 500;
vdev->timeout.tdr = 2000;
vdev->timeout.reschedule_suspend = 10;
+ vdev->timeout.autosuspend = 10;
}
}
@@ -728,6 +735,10 @@ static int ivpu_hw_40xx_info_init(struct ivpu_device *vdev)
ivpu_hw_init_range(&vdev->hw->ranges.shave, 0x80000000 + SZ_256M, SZ_2G - SZ_256M);
ivpu_hw_init_range(&vdev->hw->ranges.dma, 0x200000000, SZ_8G);
+ ivpu_hw_read_platform(vdev);
+ ivpu_hw_wa_init(vdev);
+ ivpu_hw_timeouts_init(vdev);
+
return 0;
}
@@ -819,10 +830,6 @@ static int ivpu_hw_40xx_power_up(struct ivpu_device *vdev)
return ret;
}
- ivpu_hw_read_platform(vdev);
- ivpu_hw_wa_init(vdev);
- ivpu_hw_timeouts_init(vdev);
-
ret = ivpu_hw_40xx_d0i3_disable(vdev);
if (ret)
ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret);
@@ -1179,6 +1186,7 @@ const struct ivpu_hw_ops ivpu_hw_40xx_ops = {
.power_up = ivpu_hw_40xx_power_up,
.is_idle = ivpu_hw_40xx_is_idle,
.power_down = ivpu_hw_40xx_power_down,
+ .reset = ivpu_hw_40xx_reset,
.boot_fw = ivpu_hw_40xx_boot_fw,
.wdt_disable = ivpu_hw_40xx_wdt_disable,
.diagnose_failure = ivpu_hw_40xx_diagnose_failure,
diff --git a/drivers/accel/ivpu/ivpu_hw_reg_io.h b/drivers/accel/ivpu/ivpu_hw_reg_io.h
index 43c2c0c2d050..79b3f441eac4 100644
--- a/drivers/accel/ivpu/ivpu_hw_reg_io.h
+++ b/drivers/accel/ivpu/ivpu_hw_reg_io.h
@@ -47,22 +47,30 @@
#define REG_TEST_FLD_NUM(REG, FLD, num, val) \
((num) == FIELD_GET(REG##_##FLD##_MASK, val))
-#define REGB_POLL(reg, var, cond, timeout_us) \
- read_poll_timeout(REGB_RD32_SILENT, var, cond, REG_POLL_SLEEP_US, timeout_us, false, reg)
-
-#define REGV_POLL(reg, var, cond, timeout_us) \
- read_poll_timeout(REGV_RD32_SILENT, var, cond, REG_POLL_SLEEP_US, timeout_us, false, reg)
-
#define REGB_POLL_FLD(reg, fld, val, timeout_us) \
({ \
u32 var; \
- REGB_POLL(reg, var, (FIELD_GET(reg##_##fld##_MASK, var) == (val)), timeout_us); \
+ int r; \
+ ivpu_dbg(vdev, REG, "%s : %s (0x%08x) Polling field %s started (expected 0x%x)\n", \
+ __func__, #reg, reg, #fld, val); \
+ r = read_poll_timeout(REGB_RD32_SILENT, var, (FIELD_GET(reg##_##fld##_MASK, var) == (val)),\
+ REG_POLL_SLEEP_US, timeout_us, false, (reg)); \
+ ivpu_dbg(vdev, REG, "%s : %s (0x%08x) Polling field %s %s (reg val 0x%08x)\n", \
+ __func__, #reg, reg, #fld, r ? "ETIMEDOUT" : "OK", var); \
+ r; \
})
#define REGV_POLL_FLD(reg, fld, val, timeout_us) \
({ \
u32 var; \
- REGV_POLL(reg, var, (FIELD_GET(reg##_##fld##_MASK, var) == (val)), timeout_us); \
+ int r; \
+ ivpu_dbg(vdev, REG, "%s : %s (0x%08x) Polling field %s started (expected 0x%x)\n", \
+ __func__, #reg, reg, #fld, val); \
+ r = read_poll_timeout(REGV_RD32_SILENT, var, (FIELD_GET(reg##_##fld##_MASK, var) == (val)),\
+ REG_POLL_SLEEP_US, timeout_us, false, (reg)); \
+ ivpu_dbg(vdev, REG, "%s : %s (0x%08x) Polling field %s %s (reg val 0x%08x)\n", \
+ __func__, #reg, reg, #fld, r ? "ETIMEDOUT" : "OK", var); \
+ r; \
})
static inline u32
@@ -71,7 +79,7 @@ ivpu_hw_reg_rd32(struct ivpu_device *vdev, void __iomem *base, u32 reg,
{
u32 val = readl(base + reg);
- ivpu_dbg(vdev, REG, "%s RD: %s (0x%08x) => 0x%08x\n", func, name, reg, val);
+ ivpu_dbg(vdev, REG, "%s : %s (0x%08x) RD: 0x%08x\n", func, name, reg, val);
return val;
}
@@ -81,7 +89,7 @@ ivpu_hw_reg_rd64(struct ivpu_device *vdev, void __iomem *base, u32 reg,
{
u64 val = readq(base + reg);
- ivpu_dbg(vdev, REG, "%s RD: %s (0x%08x) => 0x%016llx\n", func, name, reg, val);
+ ivpu_dbg(vdev, REG, "%s : %s (0x%08x) RD: 0x%016llx\n", func, name, reg, val);
return val;
}
@@ -89,7 +97,7 @@ static inline void
ivpu_hw_reg_wr32(struct ivpu_device *vdev, void __iomem *base, u32 reg, u32 val,
const char *name, const char *func)
{
- ivpu_dbg(vdev, REG, "%s WR: %s (0x%08x) <= 0x%08x\n", func, name, reg, val);
+ ivpu_dbg(vdev, REG, "%s : %s (0x%08x) WR: 0x%08x\n", func, name, reg, val);
writel(val, base + reg);
}
@@ -97,7 +105,7 @@ static inline void
ivpu_hw_reg_wr64(struct ivpu_device *vdev, void __iomem *base, u32 reg, u64 val,
const char *name, const char *func)
{
- ivpu_dbg(vdev, REG, "%s WR: %s (0x%08x) <= 0x%016llx\n", func, name, reg, val);
+ ivpu_dbg(vdev, REG, "%s : %s (0x%08x) WR: 0x%016llx\n", func, name, reg, val);
writeq(val, base + reg);
}
diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c
index 295c0d7b5039..a4ca40b184d4 100644
--- a/drivers/accel/ivpu/ivpu_ipc.c
+++ b/drivers/accel/ivpu/ivpu_ipc.c
@@ -45,8 +45,9 @@ static void ivpu_jsm_msg_dump(struct ivpu_device *vdev, char *c,
u32 *payload = (u32 *)&jsm_msg->payload;
ivpu_dbg(vdev, JSM,
- "%s: vpu:0x%08x (type:0x%x, status:0x%x, id: 0x%x, result: 0x%x, payload:0x%x 0x%x 0x%x 0x%x 0x%x)\n",
- c, vpu_addr, jsm_msg->type, jsm_msg->status, jsm_msg->request_id, jsm_msg->result,
+ "%s: vpu:0x%08x (type:%s, status:0x%x, id: 0x%x, result: 0x%x, payload:0x%x 0x%x 0x%x 0x%x 0x%x)\n",
+ c, vpu_addr, ivpu_jsm_msg_type_to_str(jsm_msg->type),
+ jsm_msg->status, jsm_msg->request_id, jsm_msg->result,
payload[0], payload[1], payload[2], payload[3], payload[4]);
}
@@ -79,8 +80,8 @@ ivpu_ipc_tx_prepare(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
tx_buf_vpu_addr = gen_pool_alloc(ipc->mm_tx, sizeof(*tx_buf));
if (!tx_buf_vpu_addr) {
- ivpu_err(vdev, "Failed to reserve IPC buffer, size %ld\n",
- sizeof(*tx_buf));
+ ivpu_err_ratelimited(vdev, "Failed to reserve IPC buffer, size %ld\n",
+ sizeof(*tx_buf));
return -ENOMEM;
}
@@ -93,12 +94,12 @@ ivpu_ipc_tx_prepare(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
jsm_vpu_addr = tx_buf_vpu_addr + offsetof(struct ivpu_ipc_tx_buf, jsm);
if (tx_buf->ipc.status != IVPU_IPC_HDR_FREE)
- ivpu_warn(vdev, "IPC message vpu:0x%x not released by firmware\n",
- tx_buf_vpu_addr);
+ ivpu_warn_ratelimited(vdev, "IPC message vpu:0x%x not released by firmware\n",
+ tx_buf_vpu_addr);
if (tx_buf->jsm.status != VPU_JSM_MSG_FREE)
- ivpu_warn(vdev, "JSM message vpu:0x%x not released by firmware\n",
- jsm_vpu_addr);
+ ivpu_warn_ratelimited(vdev, "JSM message vpu:0x%x not released by firmware\n",
+ jsm_vpu_addr);
memset(tx_buf, 0, sizeof(*tx_buf));
tx_buf->ipc.data_addr = jsm_vpu_addr;
@@ -263,18 +264,19 @@ ivpu_ipc_send_receive_internal(struct ivpu_device *vdev, struct vpu_jsm_msg *req
ret = ivpu_ipc_send(vdev, &cons, req);
if (ret) {
- ivpu_warn(vdev, "IPC send failed: %d\n", ret);
+ ivpu_warn_ratelimited(vdev, "IPC send failed: %d\n", ret);
goto consumer_del;
}
ret = ivpu_ipc_receive(vdev, &cons, NULL, resp, timeout_ms);
if (ret) {
- ivpu_warn(vdev, "IPC receive failed: type 0x%x, ret %d\n", req->type, ret);
+ ivpu_warn_ratelimited(vdev, "IPC receive failed: type %s, ret %d\n",
+ ivpu_jsm_msg_type_to_str(req->type), ret);
goto consumer_del;
}
if (resp->type != expected_resp_type) {
- ivpu_warn(vdev, "Invalid JSM response type: 0x%x\n", resp->type);
+ ivpu_warn_ratelimited(vdev, "Invalid JSM response type: 0x%x\n", resp->type);
ret = -EBADE;
}
@@ -372,13 +374,13 @@ int ivpu_ipc_irq_handler(struct ivpu_device *vdev)
while (ivpu_hw_reg_ipc_rx_count_get(vdev)) {
vpu_addr = ivpu_hw_reg_ipc_rx_addr_get(vdev);
if (vpu_addr == REG_IO_ERROR) {
- ivpu_err(vdev, "Failed to read IPC rx addr register\n");
+ ivpu_err_ratelimited(vdev, "Failed to read IPC rx addr register\n");
return -EIO;
}
ipc_hdr = ivpu_to_cpu_addr(ipc->mem_rx, vpu_addr);
if (!ipc_hdr) {
- ivpu_warn(vdev, "IPC msg 0x%x out of range\n", vpu_addr);
+ ivpu_warn_ratelimited(vdev, "IPC msg 0x%x out of range\n", vpu_addr);
continue;
}
ivpu_ipc_msg_dump(vdev, "RX", ipc_hdr, vpu_addr);
@@ -387,7 +389,8 @@ int ivpu_ipc_irq_handler(struct ivpu_device *vdev)
if (ipc_hdr->channel != IVPU_IPC_CHAN_BOOT_MSG) {
jsm_msg = ivpu_to_cpu_addr(ipc->mem_rx, ipc_hdr->data_addr);
if (!jsm_msg) {
- ivpu_warn(vdev, "JSM msg 0x%x out of range\n", ipc_hdr->data_addr);
+ ivpu_warn_ratelimited(vdev, "JSM msg 0x%x out of range\n",
+ ipc_hdr->data_addr);
ivpu_ipc_rx_mark_free(vdev, ipc_hdr, NULL);
continue;
}
@@ -395,7 +398,8 @@ int ivpu_ipc_irq_handler(struct ivpu_device *vdev)
}
if (atomic_read(&ipc->rx_msg_count) > IPC_MAX_RX_MSG) {
- ivpu_warn(vdev, "IPC RX msg dropped, msg count %d\n", IPC_MAX_RX_MSG);
+ ivpu_warn_ratelimited(vdev, "IPC RX msg dropped, msg count %d\n",
+ IPC_MAX_RX_MSG);
ivpu_ipc_rx_mark_free(vdev, ipc_hdr, jsm_msg);
continue;
}
@@ -423,15 +427,20 @@ int ivpu_ipc_irq_handler(struct ivpu_device *vdev)
int ivpu_ipc_init(struct ivpu_device *vdev)
{
struct ivpu_ipc_info *ipc = vdev->ipc;
- int ret = -ENOMEM;
+ int ret;
ipc->mem_tx = ivpu_bo_alloc_internal(vdev, 0, SZ_16K, DRM_IVPU_BO_WC);
- if (!ipc->mem_tx)
- return ret;
+ if (!ipc->mem_tx) {
+ ivpu_err(vdev, "Failed to allocate mem_tx\n");
+ return -ENOMEM;
+ }
ipc->mem_rx = ivpu_bo_alloc_internal(vdev, 0, SZ_16K, DRM_IVPU_BO_WC);
- if (!ipc->mem_rx)
+ if (!ipc->mem_rx) {
+ ivpu_err(vdev, "Failed to allocate mem_rx\n");
+ ret = -ENOMEM;
goto err_free_tx;
+ }
ipc->mm_tx = devm_gen_pool_create(vdev->drm.dev, __ffs(IVPU_IPC_ALIGNMENT),
-1, "TX_IPC_JSM");
@@ -441,7 +450,7 @@ int ivpu_ipc_init(struct ivpu_device *vdev)
goto err_free_rx;
}
- ret = gen_pool_add(ipc->mm_tx, ipc->mem_tx->vpu_addr, ipc->mem_tx->base.size, -1);
+ ret = gen_pool_add(ipc->mm_tx, ipc->mem_tx->vpu_addr, ivpu_bo_size(ipc->mem_tx), -1);
if (ret) {
ivpu_err(vdev, "gen_pool_add failed, ret %d\n", ret);
goto err_free_rx;
@@ -497,8 +506,8 @@ void ivpu_ipc_reset(struct ivpu_device *vdev)
mutex_lock(&ipc->lock);
- memset(ipc->mem_tx->kvaddr, 0, ipc->mem_tx->base.size);
- memset(ipc->mem_rx->kvaddr, 0, ipc->mem_rx->base.size);
+ memset(ivpu_bo_vaddr(ipc->mem_tx), 0, ivpu_bo_size(ipc->mem_tx));
+ memset(ivpu_bo_vaddr(ipc->mem_rx), 0, ivpu_bo_size(ipc->mem_rx));
wmb(); /* Flush WC buffers for TX and RX rings */
mutex_unlock(&ipc->lock);
diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c
index de9e69f70af7..8983e3a4fdf9 100644
--- a/drivers/accel/ivpu/ivpu_job.c
+++ b/drivers/accel/ivpu/ivpu_job.c
@@ -48,10 +48,10 @@ static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv *file_priv, u16 e
goto cmdq_free;
cmdq->db_id = file_priv->ctx.id + engine * ivpu_get_context_count(vdev);
- cmdq->entry_count = (u32)((cmdq->mem->base.size - sizeof(struct vpu_job_queue_header)) /
+ cmdq->entry_count = (u32)((ivpu_bo_size(cmdq->mem) - sizeof(struct vpu_job_queue_header)) /
sizeof(struct vpu_job_queue_entry));
- cmdq->jobq = (struct vpu_job_queue *)cmdq->mem->kvaddr;
+ cmdq->jobq = (struct vpu_job_queue *)ivpu_bo_vaddr(cmdq->mem);
jobq_header = &cmdq->jobq->header;
jobq_header->engine_idx = engine;
jobq_header->head = 0;
@@ -93,7 +93,7 @@ static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u16
return cmdq;
ret = ivpu_jsm_register_db(vdev, file_priv->ctx.id, cmdq->db_id,
- cmdq->mem->vpu_addr, cmdq->mem->base.size);
+ cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem));
if (ret)
return NULL;
@@ -453,7 +453,7 @@ ivpu_job_prepare_bos_for_submit(struct drm_file *file, struct ivpu_job *job, u32
return -EBUSY;
}
- if (commands_offset >= bo->base.size) {
+ if (commands_offset >= ivpu_bo_size(bo)) {
ivpu_warn(vdev, "Invalid command buffer offset %u\n", commands_offset);
return -EINVAL;
}
@@ -618,6 +618,5 @@ int ivpu_job_done_thread_init(struct ivpu_device *vdev)
void ivpu_job_done_thread_fini(struct ivpu_device *vdev)
{
- kthread_stop(vdev->job_done_thread);
- put_task_struct(vdev->job_done_thread);
+ kthread_stop_put(vdev->job_done_thread);
}
diff --git a/drivers/accel/ivpu/ivpu_job.h b/drivers/accel/ivpu/ivpu_job.h
index aa1f0b9479b0..5514c2d8a609 100644
--- a/drivers/accel/ivpu/ivpu_job.h
+++ b/drivers/accel/ivpu/ivpu_job.h
@@ -51,7 +51,7 @@ struct ivpu_job {
u32 job_id;
u32 engine_idx;
size_t bo_count;
- struct ivpu_bo *bos[];
+ struct ivpu_bo *bos[] __counted_by(bo_count);
};
int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file);
diff --git a/drivers/accel/ivpu/ivpu_jsm_msg.c b/drivers/accel/ivpu/ivpu_jsm_msg.c
index bdddef2c59ee..0c2fe7142024 100644
--- a/drivers/accel/ivpu/ivpu_jsm_msg.c
+++ b/drivers/accel/ivpu/ivpu_jsm_msg.c
@@ -7,6 +7,70 @@
#include "ivpu_ipc.h"
#include "ivpu_jsm_msg.h"
+const char *ivpu_jsm_msg_type_to_str(enum vpu_ipc_msg_type type)
+{
+ #define IVPU_CASE_TO_STR(x) case x: return #x
+ switch (type) {
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_UNKNOWN);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_ENGINE_RESET);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_ENGINE_PREEMPT);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_REGISTER_DB);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_UNREGISTER_DB);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_QUERY_ENGINE_HB);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_GET_POWER_LEVEL_COUNT);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_GET_POWER_LEVEL);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_SET_POWER_LEVEL);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_OPEN);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_CLOSE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_TRACE_SET_CONFIG);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_TRACE_GET_CONFIG);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_TRACE_GET_CAPABILITY);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_TRACE_GET_NAME);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_SSID_RELEASE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_START);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_STOP);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_UPDATE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_INFO);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_SET_PRIORITY_BAND_SETUP);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_CREATE_CMD_QUEUE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_DESTROY_CMD_QUEUE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_SET_CONTEXT_SCHED_PROPERTIES);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_HWS_REGISTER_DB);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_BLOB_DEINIT);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_DYNDBG_CONTROL);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_JOB_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_ENGINE_RESET_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_ENGINE_PREEMPT_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_REGISTER_DB_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_UNREGISTER_DB_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_QUERY_ENGINE_HB_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_GET_POWER_LEVEL_COUNT_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_GET_POWER_LEVEL_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_SET_POWER_LEVEL_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_OPEN_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_CLOSE_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_TRACE_SET_CONFIG_RSP);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_TRACE_GET_CONFIG_RSP);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_TRACE_GET_CAPABILITY_RSP);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_TRACE_GET_NAME_RSP);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_SSID_RELEASE_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_START_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_STOP_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_UPDATE_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_INFO_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_METRIC_STREAMER_NOTIFICATION);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_SET_PRIORITY_BAND_SETUP_RSP);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_CREATE_CMD_QUEUE_RSP);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_DESTROY_CMD_QUEUE_RSP);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_SET_CONTEXT_SCHED_PROPERTIES_RSP);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_BLOB_DEINIT_DONE);
+ IVPU_CASE_TO_STR(VPU_JSM_MSG_DYNDBG_CONTROL_RSP);
+ }
+ #undef IVPU_CASE_TO_STR
+
+ return "Unknown JSM message type";
+}
+
int ivpu_jsm_register_db(struct ivpu_device *vdev, u32 ctx_id, u32 db_id,
u64 jobq_base, u32 jobq_size)
{
@@ -22,7 +86,7 @@ int ivpu_jsm_register_db(struct ivpu_device *vdev, u32 ctx_id, u32 db_id,
ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_REGISTER_DB_DONE, &resp,
VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
if (ret) {
- ivpu_err(vdev, "Failed to register doorbell %d: %d\n", db_id, ret);
+ ivpu_err_ratelimited(vdev, "Failed to register doorbell %d: %d\n", db_id, ret);
return ret;
}
@@ -42,7 +106,7 @@ int ivpu_jsm_unregister_db(struct ivpu_device *vdev, u32 db_id)
ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_UNREGISTER_DB_DONE, &resp,
VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
if (ret) {
- ivpu_warn(vdev, "Failed to unregister doorbell %d: %d\n", db_id, ret);
+ ivpu_warn_ratelimited(vdev, "Failed to unregister doorbell %d: %d\n", db_id, ret);
return ret;
}
@@ -65,7 +129,8 @@ int ivpu_jsm_get_heartbeat(struct ivpu_device *vdev, u32 engine, u64 *heartbeat)
ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_QUERY_ENGINE_HB_DONE, &resp,
VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
if (ret) {
- ivpu_err(vdev, "Failed to get heartbeat from engine %d: %d\n", engine, ret);
+ ivpu_err_ratelimited(vdev, "Failed to get heartbeat from engine %d: %d\n",
+ engine, ret);
return ret;
}
@@ -87,7 +152,7 @@ int ivpu_jsm_reset_engine(struct ivpu_device *vdev, u32 engine)
ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_ENGINE_RESET_DONE, &resp,
VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
if (ret)
- ivpu_err(vdev, "Failed to reset engine %d: %d\n", engine, ret);
+ ivpu_err_ratelimited(vdev, "Failed to reset engine %d: %d\n", engine, ret);
return ret;
}
@@ -107,7 +172,7 @@ int ivpu_jsm_preempt_engine(struct ivpu_device *vdev, u32 engine, u32 preempt_id
ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_ENGINE_PREEMPT_DONE, &resp,
VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
if (ret)
- ivpu_err(vdev, "Failed to preempt engine %d: %d\n", engine, ret);
+ ivpu_err_ratelimited(vdev, "Failed to preempt engine %d: %d\n", engine, ret);
return ret;
}
@@ -123,7 +188,8 @@ int ivpu_jsm_dyndbg_control(struct ivpu_device *vdev, char *command, size_t size
ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_DYNDBG_CONTROL_RSP, &resp,
VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
if (ret)
- ivpu_warn(vdev, "Failed to send command \"%s\": ret %d\n", command, ret);
+ ivpu_warn_ratelimited(vdev, "Failed to send command \"%s\": ret %d\n",
+ command, ret);
return ret;
}
@@ -138,7 +204,7 @@ int ivpu_jsm_trace_get_capability(struct ivpu_device *vdev, u32 *trace_destinati
ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_TRACE_GET_CAPABILITY_RSP, &resp,
VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
if (ret) {
- ivpu_warn(vdev, "Failed to get trace capability: %d\n", ret);
+ ivpu_warn_ratelimited(vdev, "Failed to get trace capability: %d\n", ret);
return ret;
}
@@ -162,7 +228,7 @@ int ivpu_jsm_trace_set_config(struct ivpu_device *vdev, u32 trace_level, u32 tra
ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_TRACE_SET_CONFIG_RSP, &resp,
VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
if (ret)
- ivpu_warn(vdev, "Failed to set config: %d\n", ret);
+ ivpu_warn_ratelimited(vdev, "Failed to set config: %d\n", ret);
return ret;
}
diff --git a/drivers/accel/ivpu/ivpu_jsm_msg.h b/drivers/accel/ivpu/ivpu_jsm_msg.h
index ab50d7b017c1..66979a948c7c 100644
--- a/drivers/accel/ivpu/ivpu_jsm_msg.h
+++ b/drivers/accel/ivpu/ivpu_jsm_msg.h
@@ -8,6 +8,8 @@
#include "vpu_jsm_api.h"
+const char *ivpu_jsm_msg_type_to_str(enum vpu_ipc_msg_type type);
+
int ivpu_jsm_register_db(struct ivpu_device *vdev, u32 ctx_id, u32 db_id,
u64 jobq_base, u32 jobq_size);
int ivpu_jsm_unregister_db(struct ivpu_device *vdev, u32 db_id);
diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c
index baefaf7bb3cb..2538c78fbebe 100644
--- a/drivers/accel/ivpu/ivpu_mmu.c
+++ b/drivers/accel/ivpu/ivpu_mmu.c
@@ -7,12 +7,48 @@
#include <linux/highmem.h>
#include "ivpu_drv.h"
-#include "ivpu_hw_37xx_reg.h"
#include "ivpu_hw_reg_io.h"
#include "ivpu_mmu.h"
#include "ivpu_mmu_context.h"
#include "ivpu_pm.h"
+#define IVPU_MMU_REG_IDR0 0x00200000u
+#define IVPU_MMU_REG_IDR1 0x00200004u
+#define IVPU_MMU_REG_IDR3 0x0020000cu
+#define IVPU_MMU_REG_IDR5 0x00200014u
+#define IVPU_MMU_REG_CR0 0x00200020u
+#define IVPU_MMU_REG_CR0ACK 0x00200024u
+#define IVPU_MMU_REG_CR0ACK_VAL_MASK GENMASK(31, 0)
+#define IVPU_MMU_REG_CR1 0x00200028u
+#define IVPU_MMU_REG_CR2 0x0020002cu
+#define IVPU_MMU_REG_IRQ_CTRL 0x00200050u
+#define IVPU_MMU_REG_IRQ_CTRLACK 0x00200054u
+#define IVPU_MMU_REG_IRQ_CTRLACK_VAL_MASK GENMASK(31, 0)
+
+#define IVPU_MMU_REG_GERROR 0x00200060u
+#define IVPU_MMU_REG_GERROR_CMDQ_MASK BIT_MASK(0)
+#define IVPU_MMU_REG_GERROR_EVTQ_ABT_MASK BIT_MASK(2)
+#define IVPU_MMU_REG_GERROR_PRIQ_ABT_MASK BIT_MASK(3)
+#define IVPU_MMU_REG_GERROR_MSI_CMDQ_ABT_MASK BIT_MASK(4)
+#define IVPU_MMU_REG_GERROR_MSI_EVTQ_ABT_MASK BIT_MASK(5)
+#define IVPU_MMU_REG_GERROR_MSI_PRIQ_ABT_MASK BIT_MASK(6)
+#define IVPU_MMU_REG_GERROR_MSI_ABT_MASK BIT_MASK(7)
+
+#define IVPU_MMU_REG_GERRORN 0x00200064u
+
+#define IVPU_MMU_REG_STRTAB_BASE 0x00200080u
+#define IVPU_MMU_REG_STRTAB_BASE_CFG 0x00200088u
+#define IVPU_MMU_REG_CMDQ_BASE 0x00200090u
+#define IVPU_MMU_REG_CMDQ_PROD 0x00200098u
+#define IVPU_MMU_REG_CMDQ_CONS 0x0020009cu
+#define IVPU_MMU_REG_CMDQ_CONS_VAL_MASK GENMASK(23, 0)
+#define IVPU_MMU_REG_CMDQ_CONS_ERR_MASK GENMASK(30, 24)
+#define IVPU_MMU_REG_EVTQ_BASE 0x002000a0u
+#define IVPU_MMU_REG_EVTQ_PROD 0x002000a8u
+#define IVPU_MMU_REG_EVTQ_CONS 0x002000acu
+#define IVPU_MMU_REG_EVTQ_PROD_SEC (0x002000a8u + SZ_64K)
+#define IVPU_MMU_REG_EVTQ_CONS_SEC (0x002000acu + SZ_64K)
+
#define IVPU_MMU_IDR0_REF 0x080f3e0f
#define IVPU_MMU_IDR0_REF_SIMICS 0x080f3e1f
#define IVPU_MMU_IDR1_REF 0x0e739d18
@@ -186,13 +222,13 @@
#define IVPU_MMU_REG_TIMEOUT_US (10 * USEC_PER_MSEC)
#define IVPU_MMU_QUEUE_TIMEOUT_US (100 * USEC_PER_MSEC)
-#define IVPU_MMU_GERROR_ERR_MASK ((REG_FLD(VPU_37XX_HOST_MMU_GERROR, CMDQ)) | \
- (REG_FLD(VPU_37XX_HOST_MMU_GERROR, EVTQ_ABT)) | \
- (REG_FLD(VPU_37XX_HOST_MMU_GERROR, PRIQ_ABT)) | \
- (REG_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_CMDQ_ABT)) | \
- (REG_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_EVTQ_ABT)) | \
- (REG_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_PRIQ_ABT)) | \
- (REG_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_ABT)))
+#define IVPU_MMU_GERROR_ERR_MASK ((REG_FLD(IVPU_MMU_REG_GERROR, CMDQ)) | \
+ (REG_FLD(IVPU_MMU_REG_GERROR, EVTQ_ABT)) | \
+ (REG_FLD(IVPU_MMU_REG_GERROR, PRIQ_ABT)) | \
+ (REG_FLD(IVPU_MMU_REG_GERROR, MSI_CMDQ_ABT)) | \
+ (REG_FLD(IVPU_MMU_REG_GERROR, MSI_EVTQ_ABT)) | \
+ (REG_FLD(IVPU_MMU_REG_GERROR, MSI_PRIQ_ABT)) | \
+ (REG_FLD(IVPU_MMU_REG_GERROR, MSI_ABT)))
static char *ivpu_mmu_event_to_str(u32 cmd)
{
@@ -250,15 +286,15 @@ static void ivpu_mmu_config_check(struct ivpu_device *vdev)
else
val_ref = IVPU_MMU_IDR0_REF;
- val = REGV_RD32(VPU_37XX_HOST_MMU_IDR0);
+ val = REGV_RD32(IVPU_MMU_REG_IDR0);
if (val != val_ref)
ivpu_dbg(vdev, MMU, "IDR0 0x%x != IDR0_REF 0x%x\n", val, val_ref);
- val = REGV_RD32(VPU_37XX_HOST_MMU_IDR1);
+ val = REGV_RD32(IVPU_MMU_REG_IDR1);
if (val != IVPU_MMU_IDR1_REF)
ivpu_dbg(vdev, MMU, "IDR1 0x%x != IDR1_REF 0x%x\n", val, IVPU_MMU_IDR1_REF);
- val = REGV_RD32(VPU_37XX_HOST_MMU_IDR3);
+ val = REGV_RD32(IVPU_MMU_REG_IDR3);
if (val != IVPU_MMU_IDR3_REF)
ivpu_dbg(vdev, MMU, "IDR3 0x%x != IDR3_REF 0x%x\n", val, IVPU_MMU_IDR3_REF);
@@ -269,7 +305,7 @@ static void ivpu_mmu_config_check(struct ivpu_device *vdev)
else
val_ref = IVPU_MMU_IDR5_REF;
- val = REGV_RD32(VPU_37XX_HOST_MMU_IDR5);
+ val = REGV_RD32(IVPU_MMU_REG_IDR5);
if (val != val_ref)
ivpu_dbg(vdev, MMU, "IDR5 0x%x != IDR5_REF 0x%x\n", val, val_ref);
}
@@ -376,19 +412,18 @@ static int ivpu_mmu_structs_alloc(struct ivpu_device *vdev)
return ret;
}
-static int ivpu_mmu_reg_write(struct ivpu_device *vdev, u32 reg, u32 val)
+static int ivpu_mmu_reg_write_cr0(struct ivpu_device *vdev, u32 val)
{
- u32 reg_ack = reg + 4; /* ACK register is 4B after base register */
- u32 val_ack;
- int ret;
+ REGV_WR32(IVPU_MMU_REG_CR0, val);
- REGV_WR32(reg, val);
+ return REGV_POLL_FLD(IVPU_MMU_REG_CR0ACK, VAL, val, IVPU_MMU_REG_TIMEOUT_US);
+}
- ret = REGV_POLL(reg_ack, val_ack, (val == val_ack), IVPU_MMU_REG_TIMEOUT_US);
- if (ret)
- ivpu_err(vdev, "Failed to write register 0x%x\n", reg);
+static int ivpu_mmu_reg_write_irq_ctrl(struct ivpu_device *vdev, u32 val)
+{
+ REGV_WR32(IVPU_MMU_REG_IRQ_CTRL, val);
- return ret;
+ return REGV_POLL_FLD(IVPU_MMU_REG_IRQ_CTRLACK, VAL, val, IVPU_MMU_REG_TIMEOUT_US);
}
static int ivpu_mmu_irqs_setup(struct ivpu_device *vdev)
@@ -396,19 +431,26 @@ static int ivpu_mmu_irqs_setup(struct ivpu_device *vdev)
u32 irq_ctrl = IVPU_MMU_IRQ_EVTQ_EN | IVPU_MMU_IRQ_GERROR_EN;
int ret;
- ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_IRQ_CTRL, 0);
+ ret = ivpu_mmu_reg_write_irq_ctrl(vdev, 0);
if (ret)
return ret;
- return ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_IRQ_CTRL, irq_ctrl);
+ return ivpu_mmu_reg_write_irq_ctrl(vdev, irq_ctrl);
}
static int ivpu_mmu_cmdq_wait_for_cons(struct ivpu_device *vdev)
{
struct ivpu_mmu_queue *cmdq = &vdev->mmu->cmdq;
+ int ret;
+
+ ret = REGV_POLL_FLD(IVPU_MMU_REG_CMDQ_CONS, VAL, cmdq->prod,
+ IVPU_MMU_QUEUE_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ cmdq->cons = cmdq->prod;
- return REGV_POLL(VPU_37XX_HOST_MMU_CMDQ_CONS, cmdq->cons, (cmdq->prod == cmdq->cons),
- IVPU_MMU_QUEUE_TIMEOUT_US);
+ return 0;
}
static int ivpu_mmu_cmdq_cmd_write(struct ivpu_device *vdev, const char *name, u64 data0, u64 data1)
@@ -447,7 +489,7 @@ static int ivpu_mmu_cmdq_sync(struct ivpu_device *vdev)
return ret;
clflush_cache_range(q->base, IVPU_MMU_CMDQ_SIZE);
- REGV_WR32(VPU_37XX_HOST_MMU_CMDQ_PROD, q->prod);
+ REGV_WR32(IVPU_MMU_REG_CMDQ_PROD, q->prod);
ret = ivpu_mmu_cmdq_wait_for_cons(vdev);
if (ret)
@@ -495,7 +537,7 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev)
mmu->evtq.prod = 0;
mmu->evtq.cons = 0;
- ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, 0);
+ ret = ivpu_mmu_reg_write_cr0(vdev, 0);
if (ret)
return ret;
@@ -505,17 +547,17 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev)
FIELD_PREP(IVPU_MMU_CR1_QUEUE_SH, IVPU_MMU_SH_ISH) |
FIELD_PREP(IVPU_MMU_CR1_QUEUE_OC, IVPU_MMU_CACHE_WB) |
FIELD_PREP(IVPU_MMU_CR1_QUEUE_IC, IVPU_MMU_CACHE_WB);
- REGV_WR32(VPU_37XX_HOST_MMU_CR1, val);
+ REGV_WR32(IVPU_MMU_REG_CR1, val);
- REGV_WR64(VPU_37XX_HOST_MMU_STRTAB_BASE, mmu->strtab.dma_q);
- REGV_WR32(VPU_37XX_HOST_MMU_STRTAB_BASE_CFG, mmu->strtab.base_cfg);
+ REGV_WR64(IVPU_MMU_REG_STRTAB_BASE, mmu->strtab.dma_q);
+ REGV_WR32(IVPU_MMU_REG_STRTAB_BASE_CFG, mmu->strtab.base_cfg);
- REGV_WR64(VPU_37XX_HOST_MMU_CMDQ_BASE, mmu->cmdq.dma_q);
- REGV_WR32(VPU_37XX_HOST_MMU_CMDQ_PROD, 0);
- REGV_WR32(VPU_37XX_HOST_MMU_CMDQ_CONS, 0);
+ REGV_WR64(IVPU_MMU_REG_CMDQ_BASE, mmu->cmdq.dma_q);
+ REGV_WR32(IVPU_MMU_REG_CMDQ_PROD, 0);
+ REGV_WR32(IVPU_MMU_REG_CMDQ_CONS, 0);
val = IVPU_MMU_CR0_CMDQEN;
- ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, val);
+ ret = ivpu_mmu_reg_write_cr0(vdev, val);
if (ret)
return ret;
@@ -531,17 +573,17 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev)
if (ret)
return ret;
- REGV_WR64(VPU_37XX_HOST_MMU_EVTQ_BASE, mmu->evtq.dma_q);
- REGV_WR32(VPU_37XX_HOST_MMU_EVTQ_PROD_SEC, 0);
- REGV_WR32(VPU_37XX_HOST_MMU_EVTQ_CONS_SEC, 0);
+ REGV_WR64(IVPU_MMU_REG_EVTQ_BASE, mmu->evtq.dma_q);
+ REGV_WR32(IVPU_MMU_REG_EVTQ_PROD_SEC, 0);
+ REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, 0);
val |= IVPU_MMU_CR0_EVTQEN;
- ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, val);
+ ret = ivpu_mmu_reg_write_cr0(vdev, val);
if (ret)
return ret;
val |= IVPU_MMU_CR0_ATSCHK;
- ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, val);
+ ret = ivpu_mmu_reg_write_cr0(vdev, val);
if (ret)
return ret;
@@ -550,7 +592,7 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev)
return ret;
val |= IVPU_MMU_CR0_SMMUEN;
- return ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, val);
+ return ivpu_mmu_reg_write_cr0(vdev, val);
}
static void ivpu_mmu_strtab_link_cd(struct ivpu_device *vdev, u32 sid)
@@ -801,14 +843,14 @@ static u32 *ivpu_mmu_get_event(struct ivpu_device *vdev)
u32 idx = IVPU_MMU_Q_IDX(evtq->cons);
u32 *evt = evtq->base + (idx * IVPU_MMU_EVTQ_CMD_SIZE);
- evtq->prod = REGV_RD32(VPU_37XX_HOST_MMU_EVTQ_PROD_SEC);
+ evtq->prod = REGV_RD32(IVPU_MMU_REG_EVTQ_PROD_SEC);
if (!CIRC_CNT(IVPU_MMU_Q_IDX(evtq->prod), IVPU_MMU_Q_IDX(evtq->cons), IVPU_MMU_Q_COUNT))
return NULL;
clflush_cache_range(evt, IVPU_MMU_EVTQ_CMD_SIZE);
evtq->cons = (evtq->cons + 1) & IVPU_MMU_Q_WRAP_MASK;
- REGV_WR32(VPU_37XX_HOST_MMU_EVTQ_CONS_SEC, evtq->cons);
+ REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, evtq->cons);
return evt;
}
@@ -841,35 +883,35 @@ void ivpu_mmu_irq_gerr_handler(struct ivpu_device *vdev)
ivpu_dbg(vdev, IRQ, "MMU error\n");
- gerror_val = REGV_RD32(VPU_37XX_HOST_MMU_GERROR);
- gerrorn_val = REGV_RD32(VPU_37XX_HOST_MMU_GERRORN);
+ gerror_val = REGV_RD32(IVPU_MMU_REG_GERROR);
+ gerrorn_val = REGV_RD32(IVPU_MMU_REG_GERRORN);
active = gerror_val ^ gerrorn_val;
if (!(active & IVPU_MMU_GERROR_ERR_MASK))
return;
- if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_ABT, active))
+ if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, MSI_ABT, active))
ivpu_warn_ratelimited(vdev, "MMU MSI ABT write aborted\n");
- if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_PRIQ_ABT, active))
+ if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, MSI_PRIQ_ABT, active))
ivpu_warn_ratelimited(vdev, "MMU PRIQ MSI ABT write aborted\n");
- if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_EVTQ_ABT, active))
+ if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, MSI_EVTQ_ABT, active))
ivpu_warn_ratelimited(vdev, "MMU EVTQ MSI ABT write aborted\n");
- if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_CMDQ_ABT, active))
+ if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, MSI_CMDQ_ABT, active))
ivpu_warn_ratelimited(vdev, "MMU CMDQ MSI ABT write aborted\n");
- if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, PRIQ_ABT, active))
+ if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, PRIQ_ABT, active))
ivpu_err_ratelimited(vdev, "MMU PRIQ write aborted\n");
- if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, EVTQ_ABT, active))
+ if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, EVTQ_ABT, active))
ivpu_err_ratelimited(vdev, "MMU EVTQ write aborted\n");
- if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, CMDQ, active))
+ if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, CMDQ, active))
ivpu_err_ratelimited(vdev, "MMU CMDQ write aborted\n");
- REGV_WR32(VPU_37XX_HOST_MMU_GERRORN, gerror_val);
+ REGV_WR32(IVPU_MMU_REG_GERRORN, gerror_val);
}
int ivpu_mmu_set_pgtable(struct ivpu_device *vdev, int ssid, struct ivpu_mmu_pgtable *pgtable)
diff --git a/drivers/accel/ivpu/ivpu_mmu_context.c b/drivers/accel/ivpu/ivpu_mmu_context.c
index 1d2e554e2c4a..c1050a2df954 100644
--- a/drivers/accel/ivpu/ivpu_mmu_context.c
+++ b/drivers/accel/ivpu/ivpu_mmu_context.c
@@ -11,6 +11,7 @@
#include "ivpu_mmu.h"
#include "ivpu_mmu_context.h"
+#define IVPU_MMU_VPU_ADDRESS_MASK GENMASK(47, 12)
#define IVPU_MMU_PGD_INDEX_MASK GENMASK(47, 39)
#define IVPU_MMU_PUD_INDEX_MASK GENMASK(38, 30)
#define IVPU_MMU_PMD_INDEX_MASK GENMASK(29, 21)
@@ -328,12 +329,8 @@ ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
if (!IS_ALIGNED(vpu_addr, IVPU_MMU_PAGE_SIZE))
return -EINVAL;
- /*
- * VPU is only 32 bit, but DMA engine is 38 bit
- * Ranges < 2 GB are reserved for VPU internal registers
- * Limit range to 8 GB
- */
- if (vpu_addr < SZ_2G || vpu_addr > SZ_8G)
+
+ if (vpu_addr & ~IVPU_MMU_VPU_ADDRESS_MASK)
return -EINVAL;
prot = IVPU_MMU_ENTRY_MAPPED;
@@ -427,8 +424,10 @@ ivpu_mmu_context_init(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u3
INIT_LIST_HEAD(&ctx->bo_list);
ret = ivpu_mmu_pgtable_init(vdev, &ctx->pgtable);
- if (ret)
+ if (ret) {
+ ivpu_err(vdev, "Failed to initialize pgtable for ctx %u: %d\n", context_id, ret);
return ret;
+ }
if (!context_id) {
start = vdev->hw->ranges.global.start;
@@ -467,6 +466,16 @@ void ivpu_mmu_global_context_fini(struct ivpu_device *vdev)
return ivpu_mmu_context_fini(vdev, &vdev->gctx);
}
+int ivpu_mmu_reserved_context_init(struct ivpu_device *vdev)
+{
+ return ivpu_mmu_user_context_init(vdev, &vdev->rctx, IVPU_RESERVED_CONTEXT_MMU_SSID);
+}
+
+void ivpu_mmu_reserved_context_fini(struct ivpu_device *vdev)
+{
+ return ivpu_mmu_user_context_fini(vdev, &vdev->rctx);
+}
+
void ivpu_mmu_user_context_mark_invalid(struct ivpu_device *vdev, u32 ssid)
{
struct ivpu_file_priv *file_priv;
@@ -488,13 +497,13 @@ int ivpu_mmu_user_context_init(struct ivpu_device *vdev, struct ivpu_mmu_context
ret = ivpu_mmu_context_init(vdev, ctx, ctx_id);
if (ret) {
- ivpu_err(vdev, "Failed to initialize context: %d\n", ret);
+ ivpu_err(vdev, "Failed to initialize context %u: %d\n", ctx_id, ret);
return ret;
}
ret = ivpu_mmu_set_pgtable(vdev, ctx_id, &ctx->pgtable);
if (ret) {
- ivpu_err(vdev, "Failed to set page table: %d\n", ret);
+ ivpu_err(vdev, "Failed to set page table for context %u: %d\n", ctx_id, ret);
goto err_context_fini;
}
diff --git a/drivers/accel/ivpu/ivpu_mmu_context.h b/drivers/accel/ivpu/ivpu_mmu_context.h
index 961a0d6a6c7f..f15d8c630d8a 100644
--- a/drivers/accel/ivpu/ivpu_mmu_context.h
+++ b/drivers/accel/ivpu/ivpu_mmu_context.h
@@ -32,6 +32,8 @@ struct ivpu_mmu_context {
int ivpu_mmu_global_context_init(struct ivpu_device *vdev);
void ivpu_mmu_global_context_fini(struct ivpu_device *vdev);
+int ivpu_mmu_reserved_context_init(struct ivpu_device *vdev);
+void ivpu_mmu_reserved_context_fini(struct ivpu_device *vdev);
int ivpu_mmu_user_context_init(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u32 ctx_id);
void ivpu_mmu_user_context_fini(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx);
diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c
index e6f27daf5560..e9b16cbc26f4 100644
--- a/drivers/accel/ivpu/ivpu_pm.c
+++ b/drivers/accel/ivpu/ivpu_pm.c
@@ -37,7 +37,7 @@ static void ivpu_pm_prepare_cold_boot(struct ivpu_device *vdev)
static void ivpu_pm_prepare_warm_boot(struct ivpu_device *vdev)
{
struct ivpu_fw_info *fw = vdev->fw;
- struct vpu_boot_params *bp = fw->mem->kvaddr;
+ struct vpu_boot_params *bp = ivpu_bo_vaddr(fw->mem);
if (!bp->save_restore_ret_address) {
ivpu_pm_prepare_cold_boot(vdev);
@@ -246,6 +246,16 @@ int ivpu_rpm_get(struct ivpu_device *vdev)
return ret;
}
+int ivpu_rpm_get_if_active(struct ivpu_device *vdev)
+{
+ int ret;
+
+ ret = pm_runtime_get_if_active(vdev->drm.dev, false);
+ drm_WARN_ON(&vdev->drm, ret < 0);
+
+ return ret;
+}
+
void ivpu_rpm_put(struct ivpu_device *vdev)
{
pm_runtime_mark_last_busy(vdev->drm.dev);
@@ -261,7 +271,8 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev)
ivpu_dbg(vdev, PM, "Pre-reset..\n");
atomic_inc(&vdev->pm->reset_counter);
atomic_set(&vdev->pm->in_reset, 1);
- ivpu_shutdown(vdev);
+ ivpu_prepare_for_reset(vdev);
+ ivpu_hw_reset(vdev);
ivpu_pm_prepare_cold_boot(vdev);
ivpu_jobs_abort_all(vdev);
ivpu_dbg(vdev, PM, "Pre-reset done.\n");
@@ -282,10 +293,11 @@ void ivpu_pm_reset_done_cb(struct pci_dev *pdev)
pm_runtime_put_autosuspend(vdev->drm.dev);
}
-int ivpu_pm_init(struct ivpu_device *vdev)
+void ivpu_pm_init(struct ivpu_device *vdev)
{
struct device *dev = vdev->drm.dev;
struct ivpu_pm_info *pm = vdev->pm;
+ int delay;
pm->vdev = vdev;
pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT;
@@ -293,16 +305,15 @@ int ivpu_pm_init(struct ivpu_device *vdev)
atomic_set(&pm->in_reset, 0);
INIT_WORK(&pm->recovery_work, ivpu_pm_recovery_work);
- pm_runtime_use_autosuspend(dev);
-
if (ivpu_disable_recovery)
- pm_runtime_set_autosuspend_delay(dev, -1);
- else if (ivpu_is_silicon(vdev))
- pm_runtime_set_autosuspend_delay(dev, 100);
+ delay = -1;
else
- pm_runtime_set_autosuspend_delay(dev, 60000);
+ delay = vdev->timeout.autosuspend;
- return 0;
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_autosuspend_delay(dev, delay);
+
+ ivpu_dbg(vdev, PM, "Autosuspend delay = %d\n", delay);
}
void ivpu_pm_cancel_recovery(struct ivpu_device *vdev)
diff --git a/drivers/accel/ivpu/ivpu_pm.h b/drivers/accel/ivpu/ivpu_pm.h
index fd4eada1290f..044db150be07 100644
--- a/drivers/accel/ivpu/ivpu_pm.h
+++ b/drivers/accel/ivpu/ivpu_pm.h
@@ -19,7 +19,7 @@ struct ivpu_pm_info {
u32 suspend_reschedule_counter;
};
-int ivpu_pm_init(struct ivpu_device *vdev);
+void ivpu_pm_init(struct ivpu_device *vdev);
void ivpu_pm_enable(struct ivpu_device *vdev);
void ivpu_pm_disable(struct ivpu_device *vdev);
void ivpu_pm_cancel_recovery(struct ivpu_device *vdev);
@@ -33,6 +33,7 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev);
void ivpu_pm_reset_done_cb(struct pci_dev *pdev);
int __must_check ivpu_rpm_get(struct ivpu_device *vdev);
+int __must_check ivpu_rpm_get_if_active(struct ivpu_device *vdev);
void ivpu_rpm_put(struct ivpu_device *vdev);
void ivpu_pm_schedule_recovery(struct ivpu_device *vdev);
diff --git a/drivers/accel/qaic/qaic.h b/drivers/accel/qaic/qaic.h
index f2bd637a0d4e..e3f4c30f3ffd 100644
--- a/drivers/accel/qaic/qaic.h
+++ b/drivers/accel/qaic/qaic.h
@@ -27,6 +27,9 @@
#define QAIC_DBC_OFF(i) ((i) * QAIC_DBC_SIZE + QAIC_DBC_BASE)
#define to_qaic_bo(obj) container_of(obj, struct qaic_bo, base)
+#define to_qaic_drm_device(dev) container_of(dev, struct qaic_drm_device, drm)
+#define to_drm(qddev) (&(qddev)->drm)
+#define to_accel_kdev(qddev) (to_drm(qddev)->accel->kdev) /* Return Linux device of accel node */
extern bool datapath_polling;
@@ -137,6 +140,8 @@ struct qaic_device {
};
struct qaic_drm_device {
+ /* The drm device struct of this drm device */
+ struct drm_device drm;
/* Pointer to the root device struct driven by this driver */
struct qaic_device *qdev;
/*
@@ -146,8 +151,6 @@ struct qaic_drm_device {
* device is the actual physical device
*/
s32 partition_id;
- /* Pointer to the drm device struct of this drm device */
- struct drm_device *ddev;
/* Head in list of users who have opened this drm device */
struct list_head users;
/* Synchronizes access to users list */
@@ -158,8 +161,6 @@ struct qaic_bo {
struct drm_gem_object base;
/* Scatter/gather table for allocate/imported BO */
struct sg_table *sgt;
- /* BO size requested by user. GEM object might be bigger in size. */
- u64 size;
/* Head in list of slices of this BO */
struct list_head slices;
/* Total nents, for all slices of this BO */
@@ -221,7 +222,8 @@ struct qaic_bo {
*/
u32 queue_level_before;
} perf_stats;
-
+ /* Synchronizes BO operations */
+ struct mutex lock;
};
struct bo_slice {
@@ -277,6 +279,7 @@ int qaic_execute_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *f
int qaic_partial_execute_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
int qaic_wait_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
int qaic_perf_stats_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+int qaic_detach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
void irq_polling_work(struct work_struct *work);
#endif /* _QAIC_H_ */
diff --git a/drivers/accel/qaic/qaic_data.c b/drivers/accel/qaic/qaic_data.c
index f4b06792c6f1..4a8e43a7a6a4 100644
--- a/drivers/accel/qaic/qaic_data.c
+++ b/drivers/accel/qaic/qaic_data.c
@@ -154,6 +154,7 @@ static void free_slice(struct kref *kref)
{
struct bo_slice *slice = container_of(kref, struct bo_slice, ref_count);
+ slice->bo->total_slice_nents -= slice->nents;
list_del(&slice->slice);
drm_gem_object_put(&slice->bo->base);
sg_free_table(slice->sgt);
@@ -579,7 +580,7 @@ static void qaic_gem_print_info(struct drm_printer *p, unsigned int indent,
{
struct qaic_bo *bo = to_qaic_bo(obj);
- drm_printf_indent(p, indent, "user requested size=%llu\n", bo->size);
+ drm_printf_indent(p, indent, "BO DMA direction %d\n", bo->dir);
}
static const struct vm_operations_struct drm_vm_ops = {
@@ -623,6 +624,7 @@ static void qaic_free_object(struct drm_gem_object *obj)
qaic_free_sgt(bo->sgt);
}
+ mutex_destroy(&bo->lock);
drm_gem_object_release(obj);
kfree(bo);
}
@@ -634,6 +636,19 @@ static const struct drm_gem_object_funcs qaic_gem_funcs = {
.vm_ops = &drm_vm_ops,
};
+static void qaic_init_bo(struct qaic_bo *bo, bool reinit)
+{
+ if (reinit) {
+ bo->sliced = false;
+ reinit_completion(&bo->xfer_done);
+ } else {
+ mutex_init(&bo->lock);
+ init_completion(&bo->xfer_done);
+ }
+ complete_all(&bo->xfer_done);
+ INIT_LIST_HEAD(&bo->slices);
+}
+
static struct qaic_bo *qaic_alloc_init_bo(void)
{
struct qaic_bo *bo;
@@ -642,9 +657,7 @@ static struct qaic_bo *qaic_alloc_init_bo(void)
if (!bo)
return ERR_PTR(-ENOMEM);
- INIT_LIST_HEAD(&bo->slices);
- init_completion(&bo->xfer_done);
- complete_all(&bo->xfer_done);
+ qaic_init_bo(bo, false);
return bo;
}
@@ -695,8 +708,6 @@ int qaic_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
if (ret)
goto free_bo;
- bo->size = args->size;
-
ret = drm_gem_handle_create(file_priv, obj, &args->handle);
if (ret)
goto free_sgt;
@@ -828,7 +839,6 @@ static int qaic_prepare_import_bo(struct qaic_bo *bo, struct qaic_attach_slice_h
}
bo->sgt = sgt;
- bo->size = hdr->size;
return 0;
}
@@ -838,7 +848,7 @@ static int qaic_prepare_export_bo(struct qaic_device *qdev, struct qaic_bo *bo,
{
int ret;
- if (bo->size != hdr->size)
+ if (bo->base.size < hdr->size)
return -EINVAL;
ret = dma_map_sgtable(&qdev->pdev->dev, bo->sgt, hdr->dir, 0);
@@ -857,9 +867,9 @@ static int qaic_prepare_bo(struct qaic_device *qdev, struct qaic_bo *bo,
ret = qaic_prepare_import_bo(bo, hdr);
else
ret = qaic_prepare_export_bo(qdev, bo, hdr);
-
- if (ret == 0)
- bo->dir = hdr->dir;
+ bo->dir = hdr->dir;
+ bo->dbc = &qdev->dbc[hdr->dbc_id];
+ bo->nr_slice = hdr->count;
return ret;
}
@@ -868,7 +878,6 @@ static void qaic_unprepare_import_bo(struct qaic_bo *bo)
{
dma_buf_unmap_attachment(bo->base.import_attach, bo->sgt, bo->dir);
bo->sgt = NULL;
- bo->size = 0;
}
static void qaic_unprepare_export_bo(struct qaic_device *qdev, struct qaic_bo *bo)
@@ -884,6 +893,8 @@ static void qaic_unprepare_bo(struct qaic_device *qdev, struct qaic_bo *bo)
qaic_unprepare_export_bo(qdev, bo);
bo->dir = 0;
+ bo->dbc = NULL;
+ bo->nr_slice = 0;
}
static void qaic_free_slices_bo(struct qaic_bo *bo)
@@ -892,6 +903,9 @@ static void qaic_free_slices_bo(struct qaic_bo *bo)
list_for_each_entry_safe(slice, temp, &bo->slices, slice)
kref_put(&slice->ref_count, free_slice);
+ if (WARN_ON_ONCE(bo->total_slice_nents != 0))
+ bo->total_slice_nents = 0;
+ bo->nr_slice = 0;
}
static int qaic_attach_slicing_bo(struct qaic_device *qdev, struct qaic_bo *bo,
@@ -908,15 +922,11 @@ static int qaic_attach_slicing_bo(struct qaic_device *qdev, struct qaic_bo *bo,
}
}
- if (bo->total_slice_nents > qdev->dbc[hdr->dbc_id].nelem) {
+ if (bo->total_slice_nents > bo->dbc->nelem) {
qaic_free_slices_bo(bo);
return -ENOSPC;
}
- bo->sliced = true;
- bo->nr_slice = hdr->count;
- list_add_tail(&bo->bo_list, &qdev->dbc[hdr->dbc_id].bo_lists);
-
return 0;
}
@@ -994,10 +1004,13 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
}
bo = to_qaic_bo(obj);
+ ret = mutex_lock_interruptible(&bo->lock);
+ if (ret)
+ goto put_bo;
if (bo->sliced) {
ret = -EINVAL;
- goto put_bo;
+ goto unlock_bo;
}
dbc = &qdev->dbc[args->hdr.dbc_id];
@@ -1018,9 +1031,10 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
if (args->hdr.dir == DMA_TO_DEVICE)
dma_sync_sgtable_for_cpu(&qdev->pdev->dev, bo->sgt, args->hdr.dir);
- bo->dbc = dbc;
+ bo->sliced = true;
+ list_add_tail(&bo->bo_list, &bo->dbc->bo_lists);
srcu_read_unlock(&dbc->ch_lock, rcu_id);
- drm_gem_object_put(obj);
+ mutex_unlock(&bo->lock);
kfree(slice_ent);
srcu_read_unlock(&qdev->dev_lock, qdev_rcu_id);
srcu_read_unlock(&usr->qddev_lock, usr_rcu_id);
@@ -1031,6 +1045,8 @@ unprepare_bo:
qaic_unprepare_bo(qdev, bo);
unlock_ch_srcu:
srcu_read_unlock(&dbc->ch_lock, rcu_id);
+unlock_bo:
+ mutex_unlock(&bo->lock);
put_bo:
drm_gem_object_put(obj);
free_slice_ent:
@@ -1185,15 +1201,18 @@ static int send_bo_list_to_device(struct qaic_device *qdev, struct drm_file *fil
}
bo = to_qaic_bo(obj);
+ ret = mutex_lock_interruptible(&bo->lock);
+ if (ret)
+ goto failed_to_send_bo;
if (!bo->sliced) {
ret = -EINVAL;
- goto failed_to_send_bo;
+ goto unlock_bo;
}
- if (is_partial && pexec[i].resize > bo->size) {
+ if (is_partial && pexec[i].resize > bo->base.size) {
ret = -EINVAL;
- goto failed_to_send_bo;
+ goto unlock_bo;
}
spin_lock_irqsave(&dbc->xfer_lock, flags);
@@ -1202,7 +1221,7 @@ static int send_bo_list_to_device(struct qaic_device *qdev, struct drm_file *fil
if (queued) {
spin_unlock_irqrestore(&dbc->xfer_lock, flags);
ret = -EINVAL;
- goto failed_to_send_bo;
+ goto unlock_bo;
}
bo->req_id = dbc->next_req_id++;
@@ -1233,17 +1252,20 @@ static int send_bo_list_to_device(struct qaic_device *qdev, struct drm_file *fil
if (ret) {
bo->queued = false;
spin_unlock_irqrestore(&dbc->xfer_lock, flags);
- goto failed_to_send_bo;
+ goto unlock_bo;
}
}
reinit_completion(&bo->xfer_done);
list_add_tail(&bo->xfer_list, &dbc->xfer_list);
spin_unlock_irqrestore(&dbc->xfer_lock, flags);
dma_sync_sgtable_for_device(&qdev->pdev->dev, bo->sgt, bo->dir);
+ mutex_unlock(&bo->lock);
}
return 0;
+unlock_bo:
+ mutex_unlock(&bo->lock);
failed_to_send_bo:
if (likely(obj))
drm_gem_object_put(obj);
@@ -1799,6 +1821,91 @@ unlock_usr_srcu:
return ret;
}
+static void detach_slice_bo(struct qaic_device *qdev, struct qaic_bo *bo)
+{
+ qaic_free_slices_bo(bo);
+ qaic_unprepare_bo(qdev, bo);
+ qaic_init_bo(bo, true);
+ list_del(&bo->bo_list);
+ drm_gem_object_put(&bo->base);
+}
+
+int qaic_detach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+ struct qaic_detach_slice *args = data;
+ int rcu_id, usr_rcu_id, qdev_rcu_id;
+ struct dma_bridge_chan *dbc;
+ struct drm_gem_object *obj;
+ struct qaic_device *qdev;
+ struct qaic_user *usr;
+ unsigned long flags;
+ struct qaic_bo *bo;
+ int ret;
+
+ if (args->pad != 0)
+ return -EINVAL;
+
+ usr = file_priv->driver_priv;
+ usr_rcu_id = srcu_read_lock(&usr->qddev_lock);
+ if (!usr->qddev) {
+ ret = -ENODEV;
+ goto unlock_usr_srcu;
+ }
+
+ qdev = usr->qddev->qdev;
+ qdev_rcu_id = srcu_read_lock(&qdev->dev_lock);
+ if (qdev->in_reset) {
+ ret = -ENODEV;
+ goto unlock_dev_srcu;
+ }
+
+ obj = drm_gem_object_lookup(file_priv, args->handle);
+ if (!obj) {
+ ret = -ENOENT;
+ goto unlock_dev_srcu;
+ }
+
+ bo = to_qaic_bo(obj);
+ ret = mutex_lock_interruptible(&bo->lock);
+ if (ret)
+ goto put_bo;
+
+ if (!bo->sliced) {
+ ret = -EINVAL;
+ goto unlock_bo;
+ }
+
+ dbc = bo->dbc;
+ rcu_id = srcu_read_lock(&dbc->ch_lock);
+ if (dbc->usr != usr) {
+ ret = -EINVAL;
+ goto unlock_ch_srcu;
+ }
+
+ /* Check if BO is committed to H/W for DMA */
+ spin_lock_irqsave(&dbc->xfer_lock, flags);
+ if (bo->queued) {
+ spin_unlock_irqrestore(&dbc->xfer_lock, flags);
+ ret = -EBUSY;
+ goto unlock_ch_srcu;
+ }
+ spin_unlock_irqrestore(&dbc->xfer_lock, flags);
+
+ detach_slice_bo(qdev, bo);
+
+unlock_ch_srcu:
+ srcu_read_unlock(&dbc->ch_lock, rcu_id);
+unlock_bo:
+ mutex_unlock(&bo->lock);
+put_bo:
+ drm_gem_object_put(obj);
+unlock_dev_srcu:
+ srcu_read_unlock(&qdev->dev_lock, qdev_rcu_id);
+unlock_usr_srcu:
+ srcu_read_unlock(&usr->qddev_lock, usr_rcu_id);
+ return ret;
+}
+
static void empty_xfer_list(struct qaic_device *qdev, struct dma_bridge_chan *dbc)
{
unsigned long flags;
@@ -1810,6 +1917,12 @@ static void empty_xfer_list(struct qaic_device *qdev, struct dma_bridge_chan *db
bo->queued = false;
list_del(&bo->xfer_list);
spin_unlock_irqrestore(&dbc->xfer_lock, flags);
+ bo->nr_slice_xfer_done = 0;
+ bo->req_id = 0;
+ bo->perf_stats.req_received_ts = 0;
+ bo->perf_stats.req_submit_ts = 0;
+ bo->perf_stats.req_processed_ts = 0;
+ bo->perf_stats.queue_level_before = 0;
dma_sync_sgtable_for_cpu(&qdev->pdev->dev, bo->sgt, bo->dir);
complete_all(&bo->xfer_done);
drm_gem_object_put(&bo->base);
@@ -1857,7 +1970,6 @@ void wakeup_dbc(struct qaic_device *qdev, u32 dbc_id)
void release_dbc(struct qaic_device *qdev, u32 dbc_id)
{
- struct bo_slice *slice, *slice_temp;
struct qaic_bo *bo, *bo_temp;
struct dma_bridge_chan *dbc;
@@ -1875,24 +1987,11 @@ void release_dbc(struct qaic_device *qdev, u32 dbc_id)
dbc->usr = NULL;
list_for_each_entry_safe(bo, bo_temp, &dbc->bo_lists, bo_list) {
- list_for_each_entry_safe(slice, slice_temp, &bo->slices, slice)
- kref_put(&slice->ref_count, free_slice);
- bo->sliced = false;
- INIT_LIST_HEAD(&bo->slices);
- bo->total_slice_nents = 0;
- bo->dir = 0;
- bo->dbc = NULL;
- bo->nr_slice = 0;
- bo->nr_slice_xfer_done = 0;
- bo->queued = false;
- bo->req_id = 0;
- init_completion(&bo->xfer_done);
- complete_all(&bo->xfer_done);
- list_del(&bo->bo_list);
- bo->perf_stats.req_received_ts = 0;
- bo->perf_stats.req_submit_ts = 0;
- bo->perf_stats.req_processed_ts = 0;
- bo->perf_stats.queue_level_before = 0;
+ drm_gem_object_get(&bo->base);
+ mutex_lock(&bo->lock);
+ detach_slice_bo(qdev, bo);
+ mutex_unlock(&bo->lock);
+ drm_gem_object_put(&bo->base);
}
dbc->in_use = false;
diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c
index b5de82e6eb4d..6f58095767df 100644
--- a/drivers/accel/qaic/qaic_drv.c
+++ b/drivers/accel/qaic/qaic_drv.c
@@ -22,6 +22,7 @@
#include <drm/drm_file.h>
#include <drm/drm_gem.h>
#include <drm/drm_ioctl.h>
+#include <drm/drm_managed.h>
#include <uapi/drm/qaic_accel.h>
#include "mhi_controller.h"
@@ -55,7 +56,7 @@ static void free_usr(struct kref *kref)
static int qaic_open(struct drm_device *dev, struct drm_file *file)
{
- struct qaic_drm_device *qddev = dev->dev_private;
+ struct qaic_drm_device *qddev = to_qaic_drm_device(dev);
struct qaic_device *qdev = qddev->qdev;
struct qaic_user *usr;
int rcu_id;
@@ -150,6 +151,7 @@ static const struct drm_ioctl_desc qaic_drm_ioctls[] = {
DRM_IOCTL_DEF_DRV(QAIC_PARTIAL_EXECUTE_BO, qaic_partial_execute_bo_ioctl, 0),
DRM_IOCTL_DEF_DRV(QAIC_WAIT_BO, qaic_wait_bo_ioctl, 0),
DRM_IOCTL_DEF_DRV(QAIC_PERF_STATS_BO, qaic_perf_stats_bo_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(QAIC_DETACH_SLICE_BO, qaic_detach_slice_bo_ioctl, 0),
};
static const struct drm_driver qaic_accel_driver = {
@@ -170,64 +172,39 @@ static const struct drm_driver qaic_accel_driver = {
static int qaic_create_drm_device(struct qaic_device *qdev, s32 partition_id)
{
- struct qaic_drm_device *qddev;
- struct drm_device *ddev;
- struct device *pdev;
+ struct qaic_drm_device *qddev = qdev->qddev;
+ struct drm_device *drm = to_drm(qddev);
int ret;
/* Hold off implementing partitions until the uapi is determined */
if (partition_id != QAIC_NO_PARTITION)
return -EINVAL;
- pdev = &qdev->pdev->dev;
-
- qddev = kzalloc(sizeof(*qddev), GFP_KERNEL);
- if (!qddev)
- return -ENOMEM;
-
- ddev = drm_dev_alloc(&qaic_accel_driver, pdev);
- if (IS_ERR(ddev)) {
- ret = PTR_ERR(ddev);
- goto ddev_fail;
- }
-
- ddev->dev_private = qddev;
- qddev->ddev = ddev;
-
- qddev->qdev = qdev;
qddev->partition_id = partition_id;
- INIT_LIST_HEAD(&qddev->users);
- mutex_init(&qddev->users_mutex);
-
- qdev->qddev = qddev;
-
- ret = drm_dev_register(ddev, 0);
- if (ret) {
- pci_dbg(qdev->pdev, "%s: drm_dev_register failed %d\n", __func__, ret);
- goto drm_reg_fail;
- }
- return 0;
+ /*
+ * drm_dev_unregister() sets the driver data to NULL and
+ * drm_dev_register() does not update the driver data. During a SOC
+ * reset drm dev is unregistered and registered again leaving the
+ * driver data to NULL.
+ */
+ dev_set_drvdata(to_accel_kdev(qddev), drm->accel);
+ ret = drm_dev_register(drm, 0);
+ if (ret)
+ pci_dbg(qdev->pdev, "drm_dev_register failed %d\n", ret);
-drm_reg_fail:
- mutex_destroy(&qddev->users_mutex);
- qdev->qddev = NULL;
- drm_dev_put(ddev);
-ddev_fail:
- kfree(qddev);
return ret;
}
static void qaic_destroy_drm_device(struct qaic_device *qdev, s32 partition_id)
{
- struct qaic_drm_device *qddev;
+ struct qaic_drm_device *qddev = qdev->qddev;
+ struct drm_device *drm = to_drm(qddev);
struct qaic_user *usr;
- qddev = qdev->qddev;
- qdev->qddev = NULL;
- if (!qddev)
- return;
-
+ drm_dev_get(drm);
+ drm_dev_unregister(drm);
+ qddev->partition_id = 0;
/*
* Existing users get unresolvable errors till they close FDs.
* Need to sync carefully with users calling close(). The
@@ -254,13 +231,7 @@ static void qaic_destroy_drm_device(struct qaic_device *qdev, s32 partition_id)
mutex_lock(&qddev->users_mutex);
}
mutex_unlock(&qddev->users_mutex);
-
- if (qddev->ddev) {
- drm_dev_unregister(qddev->ddev);
- drm_dev_put(qddev->ddev);
- }
-
- kfree(qddev);
+ drm_dev_put(drm);
}
static int qaic_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id)
@@ -344,8 +315,20 @@ void qaic_dev_reset_clean_local_state(struct qaic_device *qdev, bool exit_reset)
qdev->in_reset = false;
}
+static void cleanup_qdev(struct qaic_device *qdev)
+{
+ int i;
+
+ for (i = 0; i < qdev->num_dbc; ++i)
+ cleanup_srcu_struct(&qdev->dbc[i].ch_lock);
+ cleanup_srcu_struct(&qdev->dev_lock);
+ pci_set_drvdata(qdev->pdev, NULL);
+ destroy_workqueue(qdev->cntl_wq);
+}
+
static struct qaic_device *create_qdev(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ struct qaic_drm_device *qddev;
struct qaic_device *qdev;
int i;
@@ -381,18 +364,18 @@ static struct qaic_device *create_qdev(struct pci_dev *pdev, const struct pci_de
INIT_LIST_HEAD(&qdev->dbc[i].bo_lists);
}
- return qdev;
-}
+ qddev = devm_drm_dev_alloc(&pdev->dev, &qaic_accel_driver, struct qaic_drm_device, drm);
+ if (IS_ERR(qddev)) {
+ cleanup_qdev(qdev);
+ return NULL;
+ }
-static void cleanup_qdev(struct qaic_device *qdev)
-{
- int i;
+ drmm_mutex_init(to_drm(qddev), &qddev->users_mutex);
+ INIT_LIST_HEAD(&qddev->users);
+ qddev->qdev = qdev;
+ qdev->qddev = qddev;
- for (i = 0; i < qdev->num_dbc; ++i)
- cleanup_srcu_struct(&qdev->dbc[i].ch_lock);
- cleanup_srcu_struct(&qdev->dev_lock);
- pci_set_drvdata(qdev->pdev, NULL);
- destroy_workqueue(qdev->cntl_wq);
+ return qdev;
}
static int init_pci(struct qaic_device *qdev, struct pci_dev *pdev)
@@ -591,22 +574,22 @@ static int __init qaic_init(void)
{
int ret;
- ret = mhi_driver_register(&qaic_mhi_driver);
+ ret = pci_register_driver(&qaic_pci_driver);
if (ret) {
- pr_debug("qaic: mhi_driver_register failed %d\n", ret);
+ pr_debug("qaic: pci_register_driver failed %d\n", ret);
return ret;
}
- ret = pci_register_driver(&qaic_pci_driver);
+ ret = mhi_driver_register(&qaic_mhi_driver);
if (ret) {
- pr_debug("qaic: pci_register_driver failed %d\n", ret);
- goto free_mhi;
+ pr_debug("qaic: mhi_driver_register failed %d\n", ret);
+ goto free_pci;
}
return 0;
-free_mhi:
- mhi_driver_unregister(&qaic_mhi_driver);
+free_pci:
+ pci_unregister_driver(&qaic_pci_driver);
return ret;
}
@@ -628,8 +611,8 @@ static void __exit qaic_exit(void)
* reinitializing the link_up state after the cleanup is done.
*/
link_up = true;
- pci_unregister_driver(&qaic_pci_driver);
mhi_driver_unregister(&qaic_mhi_driver);
+ pci_unregister_driver(&qaic_pci_driver);
}
module_init(qaic_init);
diff --git a/drivers/accessibility/speakup/kobjects.c b/drivers/accessibility/speakup/kobjects.c
index a7522d409802..0dfdb6608e02 100644
--- a/drivers/accessibility/speakup/kobjects.c
+++ b/drivers/accessibility/speakup/kobjects.c
@@ -413,27 +413,24 @@ static ssize_t synth_direct_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
- u_char tmp[256];
- int len;
- int bytes;
- const char *ptr = buf;
+ char *unescaped;
unsigned long flags;
if (!synth)
return -EPERM;
- len = strlen(buf);
+ unescaped = kstrdup(buf, GFP_KERNEL);
+ if (!unescaped)
+ return -ENOMEM;
+
+ string_unescape_any_inplace(unescaped);
+
spin_lock_irqsave(&speakup_info.spinlock, flags);
- while (len > 0) {
- bytes = min_t(size_t, len, 250);
- strncpy(tmp, ptr, bytes);
- tmp[bytes] = '\0';
- string_unescape_any_inplace(tmp);
- synth_printf("%s", tmp);
- ptr += bytes;
- len -= bytes;
- }
+ synth_write(unescaped, strlen(unescaped));
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
+
+ kfree(unescaped);
+
return count;
}
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index cee82b473dc5..f819e760ff19 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -12,6 +12,7 @@ menuconfig ACPI
select PNP
select NLS
select CRC32
+ select FIRMWARE_TABLE
default y if X86
help
Advanced Configuration and Power Interface (ACPI) support for
@@ -257,7 +258,7 @@ config ACPI_CPU_FREQ_PSS
config ACPI_PROCESSOR_CSTATE
def_bool y
depends on ACPI_PROCESSOR
- depends on IA64 || X86
+ depends on X86
config ACPI_PROCESSOR_IDLE
bool
@@ -281,9 +282,9 @@ config ACPI_CPPC_LIB
config ACPI_PROCESSOR
tristate "Processor"
- depends on X86 || IA64 || ARM64 || LOONGARCH
+ depends on X86 || ARM64 || LOONGARCH
select ACPI_PROCESSOR_IDLE
- select ACPI_CPU_FREQ_PSS if X86 || IA64 || LOONGARCH
+ select ACPI_CPU_FREQ_PSS if X86 || LOONGARCH
select THERMAL
default y
help
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 225dc6818751..2d4a35e6dd18 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
+#include <linux/string_choices.h>
#include <linux/acpi.h>
#include <acpi/battery.h>
@@ -32,8 +33,9 @@ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION("ACPI AC Adapter Driver");
MODULE_LICENSE("GPL");
-static int acpi_ac_add(struct acpi_device *device);
-static void acpi_ac_remove(struct acpi_device *device);
+static int acpi_ac_probe(struct platform_device *pdev);
+static void acpi_ac_remove(struct platform_device *pdev);
+
static void acpi_ac_notify(acpi_handle handle, u32 event, void *data);
static const struct acpi_device_id ac_device_ids[] = {
@@ -50,17 +52,6 @@ static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
static int ac_sleep_before_get_state_ms;
static int ac_only;
-static struct acpi_driver acpi_ac_driver = {
- .name = "ac",
- .class = ACPI_AC_CLASS,
- .ids = ac_device_ids,
- .ops = {
- .add = acpi_ac_add,
- .remove = acpi_ac_remove,
- },
- .drv.pm = &acpi_ac_pm,
-};
-
struct acpi_ac {
struct power_supply *charger;
struct power_supply_desc charger_desc;
@@ -128,15 +119,12 @@ static enum power_supply_property ac_props[] = {
/* Driver Model */
static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_device *device = data;
- struct acpi_ac *ac = acpi_driver_data(device);
-
- if (!ac)
- return;
+ struct acpi_ac *ac = data;
+ struct acpi_device *adev = ac->device;
switch (event) {
default:
- acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n",
+ acpi_handle_debug(adev->handle, "Unsupported event [0x%x]\n",
event);
fallthrough;
case ACPI_AC_NOTIFY_STATUS:
@@ -153,10 +141,10 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
msleep(ac_sleep_before_get_state_ms);
acpi_ac_get_state(ac);
- acpi_bus_generate_netlink_event(device->pnp.device_class,
- dev_name(&device->dev), event,
+ acpi_bus_generate_netlink_event(adev->pnp.device_class,
+ dev_name(&adev->dev), event,
(u32) ac->state);
- acpi_notifier_call_chain(device, event, (u32) ac->state);
+ acpi_notifier_call_chain(adev, event, (u32) ac->state);
kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE);
}
}
@@ -213,24 +201,22 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = {
{},
};
-static int acpi_ac_add(struct acpi_device *device)
+static int acpi_ac_probe(struct platform_device *pdev)
{
+ struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
struct power_supply_config psy_cfg = {};
- int result = 0;
- struct acpi_ac *ac = NULL;
-
-
- if (!device)
- return -EINVAL;
+ struct acpi_ac *ac;
+ int result;
ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
if (!ac)
return -ENOMEM;
- ac->device = device;
- strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
- strcpy(acpi_device_class(device), ACPI_AC_CLASS);
- device->driver_data = ac;
+ ac->device = adev;
+ strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME);
+ strcpy(acpi_device_class(adev), ACPI_AC_CLASS);
+
+ platform_set_drvdata(pdev, ac);
result = acpi_ac_get_state(ac);
if (result)
@@ -238,26 +224,26 @@ static int acpi_ac_add(struct acpi_device *device)
psy_cfg.drv_data = ac;
- ac->charger_desc.name = acpi_device_bid(device);
+ ac->charger_desc.name = acpi_device_bid(adev);
ac->charger_desc.type = POWER_SUPPLY_TYPE_MAINS;
ac->charger_desc.properties = ac_props;
ac->charger_desc.num_properties = ARRAY_SIZE(ac_props);
ac->charger_desc.get_property = get_ac_property;
- ac->charger = power_supply_register(&ac->device->dev,
+ ac->charger = power_supply_register(&pdev->dev,
&ac->charger_desc, &psy_cfg);
if (IS_ERR(ac->charger)) {
result = PTR_ERR(ac->charger);
goto err_release_ac;
}
- pr_info("%s [%s] (%s)\n", acpi_device_name(device),
- acpi_device_bid(device), ac->state ? "on-line" : "off-line");
+ pr_info("%s [%s] (%s-line)\n", acpi_device_name(adev),
+ acpi_device_bid(adev), str_on_off(ac->state));
ac->battery_nb.notifier_call = acpi_ac_battery_notify;
register_acpi_notifier(&ac->battery_nb);
- result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY,
- acpi_ac_notify);
+ result = acpi_dev_install_notify_handler(adev, ACPI_ALL_NOTIFY,
+ acpi_ac_notify, ac);
if (result)
goto err_unregister;
@@ -275,16 +261,9 @@ err_release_ac:
#ifdef CONFIG_PM_SLEEP
static int acpi_ac_resume(struct device *dev)
{
- struct acpi_ac *ac;
+ struct acpi_ac *ac = dev_get_drvdata(dev);
unsigned int old_state;
- if (!dev)
- return -EINVAL;
-
- ac = acpi_driver_data(to_acpi_device(dev));
- if (!ac)
- return -EINVAL;
-
old_state = ac->state;
if (acpi_ac_get_state(ac))
return 0;
@@ -297,16 +276,11 @@ static int acpi_ac_resume(struct device *dev)
#define acpi_ac_resume NULL
#endif
-static void acpi_ac_remove(struct acpi_device *device)
+static void acpi_ac_remove(struct platform_device *pdev)
{
- struct acpi_ac *ac = NULL;
+ struct acpi_ac *ac = platform_get_drvdata(pdev);
- if (!device || !acpi_driver_data(device))
- return;
-
- ac = acpi_driver_data(device);
-
- acpi_dev_remove_notify_handler(device, ACPI_ALL_NOTIFY,
+ acpi_dev_remove_notify_handler(ac->device, ACPI_ALL_NOTIFY,
acpi_ac_notify);
power_supply_unregister(ac->charger);
unregister_acpi_notifier(&ac->battery_nb);
@@ -314,6 +288,16 @@ static void acpi_ac_remove(struct acpi_device *device)
kfree(ac);
}
+static struct platform_driver acpi_ac_driver = {
+ .probe = acpi_ac_probe,
+ .remove_new = acpi_ac_remove,
+ .driver = {
+ .name = "ac",
+ .acpi_match_table = ac_device_ids,
+ .pm = &acpi_ac_pm,
+ },
+};
+
static int __init acpi_ac_init(void)
{
int result;
@@ -326,7 +310,7 @@ static int __init acpi_ac_init(void)
dmi_check_system(ac_dmi_table);
- result = acpi_bus_register_driver(&acpi_ac_driver);
+ result = platform_driver_register(&acpi_ac_driver);
if (result < 0)
return -ENODEV;
@@ -335,7 +319,7 @@ static int __init acpi_ac_init(void)
static void __exit acpi_ac_exit(void)
{
- acpi_bus_unregister_driver(&acpi_ac_driver);
+ platform_driver_unregister(&acpi_ac_driver);
}
module_init(acpi_ac_init);
module_exit(acpi_ac_exit);
diff --git a/drivers/acpi/acpi_fpdt.c b/drivers/acpi/acpi_fpdt.c
index a2056c4c8cb7..271092f2700a 100644
--- a/drivers/acpi/acpi_fpdt.c
+++ b/drivers/acpi/acpi_fpdt.c
@@ -194,12 +194,19 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
record_header = (void *)subtable_header + offset;
offset += record_header->length;
+ if (!record_header->length) {
+ pr_err(FW_BUG "Zero-length record found in FPTD.\n");
+ result = -EINVAL;
+ goto err;
+ }
+
switch (record_header->type) {
case RECORD_S3_RESUME:
if (subtable_type != SUBTABLE_S3PT) {
pr_err(FW_BUG "Invalid record %d for subtable %s\n",
record_header->type, signature);
- return -EINVAL;
+ result = -EINVAL;
+ goto err;
}
if (record_resume) {
pr_err("Duplicate resume performance record found.\n");
@@ -208,7 +215,7 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
record_resume = (struct resume_performance_record *)record_header;
result = sysfs_create_group(fpdt_kobj, &resume_attr_group);
if (result)
- return result;
+ goto err;
break;
case RECORD_S3_SUSPEND:
if (subtable_type != SUBTABLE_S3PT) {
@@ -223,13 +230,14 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
record_suspend = (struct suspend_performance_record *)record_header;
result = sysfs_create_group(fpdt_kobj, &suspend_attr_group);
if (result)
- return result;
+ goto err;
break;
case RECORD_BOOT:
if (subtable_type != SUBTABLE_FBPT) {
pr_err(FW_BUG "Invalid %d for subtable %s\n",
record_header->type, signature);
- return -EINVAL;
+ result = -EINVAL;
+ goto err;
}
if (record_boot) {
pr_err("Duplicate boot performance record found.\n");
@@ -238,7 +246,7 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
record_boot = (struct boot_performance_record *)record_header;
result = sysfs_create_group(fpdt_kobj, &boot_attr_group);
if (result)
- return result;
+ goto err;
break;
default:
@@ -247,6 +255,18 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
}
}
return 0;
+
+err:
+ if (record_boot)
+ sysfs_remove_group(fpdt_kobj, &boot_attr_group);
+
+ if (record_suspend)
+ sysfs_remove_group(fpdt_kobj, &suspend_attr_group);
+
+ if (record_resume)
+ sysfs_remove_group(fpdt_kobj, &resume_attr_group);
+
+ return result;
}
static int __init acpi_init_fpdt(void)
@@ -255,6 +275,7 @@ static int __init acpi_init_fpdt(void)
struct acpi_table_header *header;
struct fpdt_subtable_entry *subtable;
u32 offset = sizeof(*header);
+ int result;
status = acpi_get_table(ACPI_SIG_FPDT, 0, &header);
@@ -263,8 +284,8 @@ static int __init acpi_init_fpdt(void)
fpdt_kobj = kobject_create_and_add("fpdt", acpi_kobj);
if (!fpdt_kobj) {
- acpi_put_table(header);
- return -ENOMEM;
+ result = -ENOMEM;
+ goto err_nomem;
}
while (offset < header->length) {
@@ -272,8 +293,10 @@ static int __init acpi_init_fpdt(void)
switch (subtable->type) {
case SUBTABLE_FBPT:
case SUBTABLE_S3PT:
- fpdt_process_subtable(subtable->address,
+ result = fpdt_process_subtable(subtable->address,
subtable->type);
+ if (result)
+ goto err_subtable;
break;
default:
/* Other types are reserved in ACPI 6.4 spec. */
@@ -282,6 +305,12 @@ static int __init acpi_init_fpdt(void)
offset += sizeof(*subtable);
}
return 0;
+err_subtable:
+ kobject_put(fpdt_kobj);
+
+err_nomem:
+ acpi_put_table(header);
+ return result;
}
fs_initcall(acpi_init_fpdt);
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 539e700de4d2..875de44961bf 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -368,7 +368,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
{ "INT33C4", LPSS_ADDR(lpt_uart_dev_desc) },
{ "INT33C5", LPSS_ADDR(lpt_uart_dev_desc) },
{ "INT33C6", LPSS_ADDR(lpt_sdio_dev_desc) },
- { "INT33C7", },
/* BayTrail LPSS devices */
{ "80860F09", LPSS_ADDR(byt_pwm_dev_desc) },
@@ -376,8 +375,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
{ "80860F0E", LPSS_ADDR(byt_spi_dev_desc) },
{ "80860F14", LPSS_ADDR(byt_sdio_dev_desc) },
{ "80860F41", LPSS_ADDR(byt_i2c_dev_desc) },
- { "INT33B2", },
- { "INT33FC", },
/* Braswell LPSS devices */
{ "80862286", LPSS_ADDR(lpss_dma_desc) },
@@ -396,7 +393,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
{ "INT3434", LPSS_ADDR(lpt_uart_dev_desc) },
{ "INT3435", LPSS_ADDR(lpt_uart_dev_desc) },
{ "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) },
- { "INT3437", },
/* Wildcat Point LPSS devices */
{ "INT3438", LPSS_ADDR(lpt_spi_dev_desc) },
@@ -578,6 +574,7 @@ static bool acpi_lpss_dep(struct acpi_device *adev, acpi_handle handle)
{
struct acpi_handle_list dep_devices;
acpi_status status;
+ bool ret = false;
int i;
if (!acpi_has_method(adev->handle, "_DEP"))
@@ -591,11 +588,14 @@ static bool acpi_lpss_dep(struct acpi_device *adev, acpi_handle handle)
}
for (i = 0; i < dep_devices.count; i++) {
- if (dep_devices.handles[i] == handle)
- return true;
+ if (dep_devices.handles[i] == handle) {
+ ret = true;
+ break;
+ }
}
- return false;
+ acpi_handle_list_free(&dep_devices);
+ return ret;
}
static void acpi_lpss_link_consumer(struct device *dev1,
@@ -657,10 +657,9 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
int ret;
dev_desc = (const struct lpss_device_desc *)id->driver_data;
- if (!dev_desc) {
- pdev = acpi_create_platform_device(adev, NULL);
- return IS_ERR_OR_NULL(pdev) ? PTR_ERR(pdev) : 1;
- }
+ if (!dev_desc)
+ return -EINVAL;
+
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 7a453c5ff303..bd1ad07f0290 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/perf_event.h>
+#include <linux/platform_device.h>
#include <asm/mwait.h>
#include <xen/xen.h>
@@ -100,7 +101,7 @@ static void round_robin_cpu(unsigned int tsk_index)
for_each_cpu(cpu, pad_busy_cpus)
cpumask_or(tmp, tmp, topology_sibling_cpumask(cpu));
cpumask_andnot(tmp, cpu_online_mask, tmp);
- /* avoid HT sibilings if possible */
+ /* avoid HT siblings if possible */
if (cpumask_empty(tmp))
cpumask_andnot(tmp, cpu_online_mask, pad_busy_cpus);
if (cpumask_empty(tmp)) {
@@ -336,33 +337,14 @@ static ssize_t idlecpus_show(struct device *dev,
static DEVICE_ATTR_RW(idlecpus);
-static int acpi_pad_add_sysfs(struct acpi_device *device)
-{
- int result;
-
- result = device_create_file(&device->dev, &dev_attr_idlecpus);
- if (result)
- return -ENODEV;
- result = device_create_file(&device->dev, &dev_attr_idlepct);
- if (result) {
- device_remove_file(&device->dev, &dev_attr_idlecpus);
- return -ENODEV;
- }
- result = device_create_file(&device->dev, &dev_attr_rrtime);
- if (result) {
- device_remove_file(&device->dev, &dev_attr_idlecpus);
- device_remove_file(&device->dev, &dev_attr_idlepct);
- return -ENODEV;
- }
- return 0;
-}
+static struct attribute *acpi_pad_attrs[] = {
+ &dev_attr_idlecpus.attr,
+ &dev_attr_idlepct.attr,
+ &dev_attr_rrtime.attr,
+ NULL
+};
-static void acpi_pad_remove_sysfs(struct acpi_device *device)
-{
- device_remove_file(&device->dev, &dev_attr_idlecpus);
- device_remove_file(&device->dev, &dev_attr_idlepct);
- device_remove_file(&device->dev, &dev_attr_rrtime);
-}
+ATTRIBUTE_GROUPS(acpi_pad);
/*
* Query firmware how many CPUs should be idle
@@ -416,13 +398,13 @@ static void acpi_pad_handle_notify(acpi_handle handle)
static void acpi_pad_notify(acpi_handle handle, u32 event,
void *data)
{
- struct acpi_device *device = data;
+ struct acpi_device *adev = data;
switch (event) {
case ACPI_PROCESSOR_AGGREGATOR_NOTIFY:
acpi_pad_handle_notify(handle);
- acpi_bus_generate_netlink_event(device->pnp.device_class,
- dev_name(&device->dev), event, 0);
+ acpi_bus_generate_netlink_event(adev->pnp.device_class,
+ dev_name(&adev->dev), event, 0);
break;
default:
pr_warn("Unsupported event [0x%x]\n", event);
@@ -430,35 +412,33 @@ static void acpi_pad_notify(acpi_handle handle, u32 event,
}
}
-static int acpi_pad_add(struct acpi_device *device)
+static int acpi_pad_probe(struct platform_device *pdev)
{
+ struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
acpi_status status;
- strcpy(acpi_device_name(device), ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME);
- strcpy(acpi_device_class(device), ACPI_PROCESSOR_AGGREGATOR_CLASS);
+ strcpy(acpi_device_name(adev), ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME);
+ strcpy(acpi_device_class(adev), ACPI_PROCESSOR_AGGREGATOR_CLASS);
- if (acpi_pad_add_sysfs(device))
- return -ENODEV;
+ status = acpi_install_notify_handler(adev->handle,
+ ACPI_DEVICE_NOTIFY, acpi_pad_notify, adev);
- status = acpi_install_notify_handler(device->handle,
- ACPI_DEVICE_NOTIFY, acpi_pad_notify, device);
- if (ACPI_FAILURE(status)) {
- acpi_pad_remove_sysfs(device);
+ if (ACPI_FAILURE(status))
return -ENODEV;
- }
return 0;
}
-static void acpi_pad_remove(struct acpi_device *device)
+static void acpi_pad_remove(struct platform_device *pdev)
{
+ struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
+
mutex_lock(&isolated_cpus_lock);
acpi_pad_idle_cpus(0);
mutex_unlock(&isolated_cpus_lock);
- acpi_remove_notify_handler(device->handle,
+ acpi_remove_notify_handler(adev->handle,
ACPI_DEVICE_NOTIFY, acpi_pad_notify);
- acpi_pad_remove_sysfs(device);
}
static const struct acpi_device_id pad_device_ids[] = {
@@ -467,13 +447,13 @@ static const struct acpi_device_id pad_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, pad_device_ids);
-static struct acpi_driver acpi_pad_driver = {
- .name = "processor_aggregator",
- .class = ACPI_PROCESSOR_AGGREGATOR_CLASS,
- .ids = pad_device_ids,
- .ops = {
- .add = acpi_pad_add,
- .remove = acpi_pad_remove,
+static struct platform_driver acpi_pad_driver = {
+ .probe = acpi_pad_probe,
+ .remove_new = acpi_pad_remove,
+ .driver = {
+ .dev_groups = acpi_pad_groups,
+ .name = "processor_aggregator",
+ .acpi_match_table = pad_device_ids,
},
};
@@ -487,12 +467,12 @@ static int __init acpi_pad_init(void)
if (power_saving_mwait_eax == 0)
return -EINVAL;
- return acpi_bus_register_driver(&acpi_pad_driver);
+ return platform_driver_register(&acpi_pad_driver);
}
static void __exit acpi_pad_exit(void)
{
- acpi_bus_unregister_driver(&acpi_pad_driver);
+ platform_driver_unregister(&acpi_pad_driver);
}
module_init(acpi_pad_init);
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index c711db8a9c33..0f5218e361df 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -12,6 +12,7 @@
#define pr_fmt(fmt) "ACPI: " fmt
#include <linux/acpi.h>
+#include <linux/cpu.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/kernel.h>
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index b411948594ff..6cee536c229a 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -253,8 +253,7 @@ static const struct backlight_ops acpi_backlight_ops = {
static int video_get_max_state(struct thermal_cooling_device *cooling_dev,
unsigned long *state)
{
- struct acpi_device *device = cooling_dev->devdata;
- struct acpi_video_device *video = acpi_driver_data(device);
+ struct acpi_video_device *video = cooling_dev->devdata;
*state = video->brightness->count - ACPI_VIDEO_FIRST_LEVEL - 1;
return 0;
@@ -263,8 +262,7 @@ static int video_get_max_state(struct thermal_cooling_device *cooling_dev,
static int video_get_cur_state(struct thermal_cooling_device *cooling_dev,
unsigned long *state)
{
- struct acpi_device *device = cooling_dev->devdata;
- struct acpi_video_device *video = acpi_driver_data(device);
+ struct acpi_video_device *video = cooling_dev->devdata;
unsigned long long level;
int offset;
@@ -283,8 +281,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cooling_dev,
static int
video_set_cur_state(struct thermal_cooling_device *cooling_dev, unsigned long state)
{
- struct acpi_device *device = cooling_dev->devdata;
- struct acpi_video_device *video = acpi_driver_data(device);
+ struct acpi_video_device *video = cooling_dev->devdata;
int level;
if (state >= video->brightness->count - ACPI_VIDEO_FIRST_LEVEL)
@@ -1125,7 +1122,6 @@ static int acpi_video_bus_get_one_device(struct acpi_device *device, void *arg)
strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
- device->driver_data = data;
data->device_id = device_id;
data->video = video;
@@ -1747,8 +1743,8 @@ static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
device->backlight->props.brightness =
acpi_video_get_brightness(device->backlight);
- device->cooling_dev = thermal_cooling_device_register("LCD",
- device->dev, &video_cooling_ops);
+ device->cooling_dev = thermal_cooling_device_register("LCD", device,
+ &video_cooling_ops);
if (IS_ERR(device->cooling_dev)) {
/*
* Set cooling_dev to NULL so we don't crash trying to free it.
@@ -2031,7 +2027,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
* HP ZBook Fury 16 G10 requires ACPI video's child devices have _PS0
* evaluated to have functional panel brightness control.
*/
- acpi_device_fix_up_power_extended(device);
+ acpi_device_fix_up_power_children(device);
pr_info("%s [%s] (multi-head: %s rom: %s post: %s)\n",
ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
@@ -2062,7 +2058,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
goto err_del;
error = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
- acpi_video_bus_notify);
+ acpi_video_bus_notify, device);
if (error)
goto err_remove;
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 247989060e29..bf65e3461531 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -59,6 +59,10 @@ static struct acpi_table_erst *erst_tab;
#define ERST_RANGE_NVRAM 0x0002
#define ERST_RANGE_SLOW 0x0004
+/* ERST Exec max timings */
+#define ERST_EXEC_TIMING_MAX_MASK 0xFFFFFFFF00000000
+#define ERST_EXEC_TIMING_MAX_SHIFT 32
+
/*
* ERST Error Log Address Range, used as buffer for reading/writing
* error records.
@@ -68,6 +72,7 @@ static struct erst_erange {
u64 size;
void __iomem *vaddr;
u32 attr;
+ u64 timings;
} erst_erange;
/*
@@ -97,6 +102,19 @@ static inline int erst_errno(int command_status)
}
}
+static inline u64 erst_get_timeout(void)
+{
+ u64 timeout = FIRMWARE_TIMEOUT;
+
+ if (erst_erange.attr & ERST_RANGE_SLOW) {
+ timeout = ((erst_erange.timings & ERST_EXEC_TIMING_MAX_MASK) >>
+ ERST_EXEC_TIMING_MAX_SHIFT) * NSEC_PER_MSEC;
+ if (timeout < FIRMWARE_TIMEOUT)
+ timeout = FIRMWARE_TIMEOUT;
+ }
+ return timeout;
+}
+
static int erst_timedout(u64 *t, u64 spin_unit)
{
if ((s64)*t < spin_unit) {
@@ -191,9 +209,11 @@ static int erst_exec_stall_while_true(struct apei_exec_context *ctx,
{
int rc;
u64 val;
- u64 timeout = FIRMWARE_TIMEOUT;
+ u64 timeout;
u64 stall_time;
+ timeout = erst_get_timeout();
+
if (ctx->var1 > FIRMWARE_MAX_STALL) {
if (!in_nmi())
pr_warn(FW_WARN
@@ -389,6 +409,13 @@ static int erst_get_erange(struct erst_erange *range)
if (rc)
return rc;
range->attr = apei_exec_ctx_get_output(&ctx);
+ rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_TIMINGS);
+ if (rc == 0)
+ range->timings = apei_exec_ctx_get_output(&ctx);
+ else if (rc == -ENOENT)
+ range->timings = 0;
+ else
+ return rc;
return 0;
}
@@ -621,10 +648,12 @@ EXPORT_SYMBOL_GPL(erst_get_record_id_end);
static int __erst_write_to_storage(u64 offset)
{
struct apei_exec_context ctx;
- u64 timeout = FIRMWARE_TIMEOUT;
+ u64 timeout;
u64 val;
int rc;
+ timeout = erst_get_timeout();
+
erst_exec_ctx_init(&ctx);
rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_WRITE);
if (rc)
@@ -660,10 +689,12 @@ static int __erst_write_to_storage(u64 offset)
static int __erst_read_from_storage(u64 record_id, u64 offset)
{
struct apei_exec_context ctx;
- u64 timeout = FIRMWARE_TIMEOUT;
+ u64 timeout;
u64 val;
int rc;
+ timeout = erst_get_timeout();
+
erst_exec_ctx_init(&ctx);
rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_READ);
if (rc)
@@ -703,10 +734,12 @@ static int __erst_read_from_storage(u64 record_id, u64 offset)
static int __erst_clear_from_storage(u64 record_id)
{
struct apei_exec_context ctx;
- u64 timeout = FIRMWARE_TIMEOUT;
+ u64 timeout;
u64 val;
int rc;
+ timeout = erst_get_timeout();
+
erst_exec_ctx_init(&ctx);
rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_CLEAR);
if (rc)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index ef59d6ea16da..63ad0541db38 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -209,6 +209,20 @@ err_pool_alloc:
return -ENOMEM;
}
+/**
+ * ghes_estatus_pool_region_free - free previously allocated memory
+ * from the ghes_estatus_pool.
+ * @addr: address of memory to free.
+ * @size: size of memory to free.
+ *
+ * Returns none.
+ */
+void ghes_estatus_pool_region_free(unsigned long addr, u32 size)
+{
+ gen_pool_free(ghes_estatus_pool, addr, size);
+}
+EXPORT_SYMBOL_GPL(ghes_estatus_pool_region_free);
+
static int map_gen_v2(struct ghes *ghes)
{
return apei_map_generic_address(&ghes->generic_v2->read_ack_register);
@@ -564,6 +578,7 @@ static void ghes_handle_aer(struct acpi_hest_generic_data *gdata)
pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO) {
unsigned int devfn;
int aer_severity;
+ u8 *aer_info;
devfn = PCI_DEVFN(pcie_err->device_id.device,
pcie_err->device_id.function);
@@ -577,11 +592,17 @@ static void ghes_handle_aer(struct acpi_hest_generic_data *gdata)
if (gdata->flags & CPER_SEC_RESET)
aer_severity = AER_FATAL;
+ aer_info = (void *)gen_pool_alloc(ghes_estatus_pool,
+ sizeof(struct aer_capability_regs));
+ if (!aer_info)
+ return;
+ memcpy(aer_info, pcie_err->aer_info, sizeof(struct aer_capability_regs));
+
aer_recover_queue(pcie_err->device_id.segment,
pcie_err->device_id.bus,
devfn, aer_severity,
(struct aer_capability_regs *)
- pcie_err->aer_info);
+ aer_info);
}
#endif
}
diff --git a/drivers/acpi/arm64/amba.c b/drivers/acpi/arm64/amba.c
index 60be8ee1dbdc..171b5c2c7edd 100644
--- a/drivers/acpi/arm64/amba.c
+++ b/drivers/acpi/arm64/amba.c
@@ -101,7 +101,7 @@ static int amba_handler_attach(struct acpi_device *adev,
if (parent)
dev->dev.parent = acpi_get_first_physical_node(parent);
- ACPI_COMPANION_SET(&dev->dev, adev);
+ device_set_node(&dev->dev, acpi_fwnode_handle(adev));
ret = amba_device_add(dev, &iomem_resource);
if (ret) {
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 969bf81e8d54..b379401ff1c2 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -1214,7 +1214,7 @@ static int acpi_battery_add(struct acpi_device *device)
device_init_wakeup(&device->dev, 1);
result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY,
- acpi_battery_notify);
+ acpi_battery_notify, device);
if (result)
goto fail_pm;
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index f41dda2d3493..72e64c0718c9 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -556,12 +556,12 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device,
int acpi_dev_install_notify_handler(struct acpi_device *adev,
u32 handler_type,
- acpi_notify_handler handler)
+ acpi_notify_handler handler, void *context)
{
acpi_status status;
status = acpi_install_notify_handler(adev->handle, handler_type,
- handler, adev);
+ handler, context);
if (ACPI_FAILURE(status))
return -ENODEV;
@@ -1410,10 +1410,10 @@ static int __init acpi_init(void)
acpi_init_ffh();
pci_mmcfg_late_init();
- acpi_arm_init();
acpi_viot_early_init();
acpi_hest_init();
acpi_ghes_init();
+ acpi_arm_init();
acpi_scan_init();
acpi_ec_init();
acpi_debugfs_init();
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index f007116a8427..3b4d048c4941 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -397,6 +397,19 @@ void acpi_device_fix_up_power_extended(struct acpi_device *adev)
}
EXPORT_SYMBOL_GPL(acpi_device_fix_up_power_extended);
+/**
+ * acpi_device_fix_up_power_children - Force a device's children into D0.
+ * @adev: Parent device object whose children's power state is to be fixed up.
+ *
+ * Call acpi_device_fix_up_power() for @adev's children so long as they
+ * are reported as present and enabled.
+ */
+void acpi_device_fix_up_power_children(struct acpi_device *adev)
+{
+ acpi_dev_for_each_child(adev, fix_up_power_if_applicable, NULL);
+}
+EXPORT_SYMBOL_GPL(acpi_device_fix_up_power_children);
+
int acpi_device_update_power(struct acpi_device *device, int *state_p)
{
int state;
diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c
index b9bbf0746199..23373faa35ec 100644
--- a/drivers/acpi/device_sysfs.c
+++ b/drivers/acpi/device_sysfs.c
@@ -158,8 +158,8 @@ static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalia
return 0;
len = snprintf(modalias, size, "acpi:");
- if (len <= 0)
- return len;
+ if (len >= size)
+ return -ENOMEM;
size -= len;
@@ -168,8 +168,6 @@ static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalia
continue;
count = snprintf(&modalias[len], size, "%s:", id->id);
- if (count < 0)
- return -EINVAL;
if (count >= size)
return -ENOMEM;
@@ -177,7 +175,7 @@ static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalia
len += count;
size -= count;
}
- modalias[len] = '\0';
+
return len;
}
@@ -212,8 +210,10 @@ static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias
len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
ACPI_FREE(buf.pointer);
- if (len <= 0)
- return len;
+ if (len >= size)
+ return -ENOMEM;
+
+ size -= len;
of_compatible = acpi_dev->data.of_compatible;
if (of_compatible->type == ACPI_TYPE_PACKAGE) {
@@ -226,8 +226,6 @@ static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias
for (i = 0; i < nval; i++, obj++) {
count = snprintf(&modalias[len], size, "C%s",
obj->string.pointer);
- if (count < 0)
- return -EINVAL;
if (count >= size)
return -ENOMEM;
@@ -235,7 +233,7 @@ static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias
len += count;
size -= count;
}
- modalias[len] = '\0';
+
return len;
}
@@ -410,7 +408,7 @@ static ssize_t uid_show(struct device *dev,
{
struct acpi_device *acpi_dev = to_acpi_device(dev);
- return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
+ return sprintf(buf, "%s\n", acpi_device_uid(acpi_dev));
}
static DEVICE_ATTR_RO(uid);
@@ -554,7 +552,7 @@ int acpi_device_setup_files(struct acpi_device *dev)
if (dev->pnp.type.bus_address)
result = device_create_file(&dev->dev, &dev_attr_adr);
- if (dev->pnp.unique_id)
+ if (acpi_device_uid(dev))
result = device_create_file(&dev->dev, &dev_attr_uid);
if (acpi_has_method(dev->handle, "_SUN")) {
@@ -635,7 +633,7 @@ void acpi_device_remove_files(struct acpi_device *dev)
if (acpi_has_method(dev->handle, "_HRV"))
device_remove_file(&dev->dev, &dev_attr_hrv);
- if (dev->pnp.unique_id)
+ if (acpi_device_uid(dev))
device_remove_file(&dev->dev, &dev_attr_uid);
if (dev->pnp.type.bus_address)
device_remove_file(&dev->dev, &dev_attr_adr);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 660834a49c1f..a59c11df7375 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -1915,6 +1915,27 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = {
},
{
/*
+ * HP Pavilion Gaming Laptop 15-dk1xxx
+ * https://github.com/systemd/systemd/issues/28942
+ */
+ .callback = ec_honor_dsdt_gpe,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Gaming Laptop 15-dk1xxx"),
+ },
+ },
+ {
+ /*
+ * HP 250 G7 Notebook PC
+ */
+ .callback = ec_honor_dsdt_gpe,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP 250 G7 Notebook PC"),
+ },
+ },
+ {
+ /*
* Samsung hardware
* https://bugzilla.kernel.org/show_bug.cgi?id=44161
*/
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
index 46c6f8c35b43..7652515a6be1 100644
--- a/drivers/acpi/hed.c
+++ b/drivers/acpi/hed.c
@@ -57,7 +57,7 @@ static int acpi_hed_add(struct acpi_device *device)
hed_handle = device->handle;
err = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
- acpi_hed_notify);
+ acpi_hed_notify, device);
if (err)
hed_handle = NULL;
diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index c2c786eb95ab..1687483ff319 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -57,6 +57,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity)
{
struct irq_fwspec fwspec;
+ unsigned int irq;
fwspec.fwnode = acpi_get_gsi_domain_id(gsi);
if (WARN_ON(!fwspec.fwnode)) {
@@ -68,7 +69,11 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
fwspec.param_count = 2;
- return irq_create_fwspec_mapping(&fwspec);
+ irq = irq_create_fwspec_mapping(&fwspec);
+ if (!irq)
+ return -EINVAL;
+
+ return irq;
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index f96bf32cd368..992385537757 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -3339,6 +3339,16 @@ static int acpi_nfit_add(struct acpi_device *adev)
acpi_size sz;
int rc = 0;
+ rc = acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY,
+ acpi_nfit_notify, adev);
+ if (rc)
+ return rc;
+
+ rc = devm_add_action_or_reset(dev, acpi_nfit_remove_notify_handler,
+ adev);
+ if (rc)
+ return rc;
+
status = acpi_get_table(ACPI_SIG_NFIT, 0, &tbl);
if (ACPI_FAILURE(status)) {
/* The NVDIMM root device allows OS to trigger enumeration of
@@ -3386,17 +3396,7 @@ static int acpi_nfit_add(struct acpi_device *adev)
if (rc)
return rc;
- rc = devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc);
- if (rc)
- return rc;
-
- rc = acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY,
- acpi_nfit_notify);
- if (rc)
- return rc;
-
- return devm_add_action_or_reset(dev, acpi_nfit_remove_notify_handler,
- adev);
+ return devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc);
}
static void acpi_nfit_update_notify(struct device *dev, acpi_handle handle)
diff --git a/drivers/acpi/numa/Kconfig b/drivers/acpi/numa/Kconfig
index 39b1f34c21df..849c2bd820b9 100644
--- a/drivers/acpi/numa/Kconfig
+++ b/drivers/acpi/numa/Kconfig
@@ -2,8 +2,8 @@
config ACPI_NUMA
bool "NUMA support"
depends on NUMA
- depends on (X86 || IA64 || ARM64 || LOONGARCH)
- default y if IA64 || ARM64
+ depends on (X86 || ARM64 || LOONGARCH)
+ default y if ARM64
config ACPI_HMAT
bool "ACPI Heterogeneous Memory Attribute Table Support"
diff --git a/drivers/acpi/numa/hmat.c b/drivers/acpi/numa/hmat.c
index bba268ecd802..9ef5f1bdcfdb 100644
--- a/drivers/acpi/numa/hmat.c
+++ b/drivers/acpi/numa/hmat.c
@@ -24,6 +24,7 @@
#include <linux/node.h>
#include <linux/sysfs.h>
#include <linux/dax.h>
+#include <linux/memory-tiers.h>
static u8 hmat_revision;
static int hmat_disable __initdata;
@@ -582,28 +583,25 @@ static int initiators_to_nodemask(unsigned long *p_nodes)
return 0;
}
-static void hmat_register_target_initiators(struct memory_target *target)
+static void hmat_update_target_attrs(struct memory_target *target,
+ unsigned long *p_nodes, int access)
{
- static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
struct memory_initiator *initiator;
- unsigned int mem_nid, cpu_nid;
+ unsigned int cpu_nid;
struct memory_locality *loc = NULL;
u32 best = 0;
- bool access0done = false;
int i;
- mem_nid = pxm_to_node(target->memory_pxm);
+ bitmap_zero(p_nodes, MAX_NUMNODES);
/*
- * If the Address Range Structure provides a local processor pxm, link
+ * If the Address Range Structure provides a local processor pxm, set
* only that one. Otherwise, find the best performance attributes and
- * register all initiators that match.
+ * collect all initiators that match.
*/
if (target->processor_pxm != PXM_INVAL) {
cpu_nid = pxm_to_node(target->processor_pxm);
- register_memory_node_under_compute_node(mem_nid, cpu_nid, 0);
- access0done = true;
- if (node_state(cpu_nid, N_CPU)) {
- register_memory_node_under_compute_node(mem_nid, cpu_nid, 1);
+ if (access == 0 || node_state(cpu_nid, N_CPU)) {
+ set_bit(target->processor_pxm, p_nodes);
return;
}
}
@@ -617,47 +615,10 @@ static void hmat_register_target_initiators(struct memory_target *target)
* We'll also use the sorting to prime the candidate nodes with known
* initiators.
*/
- bitmap_zero(p_nodes, MAX_NUMNODES);
list_sort(NULL, &initiators, initiator_cmp);
if (initiators_to_nodemask(p_nodes) < 0)
return;
- if (!access0done) {
- for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) {
- loc = localities_types[i];
- if (!loc)
- continue;
-
- best = 0;
- list_for_each_entry(initiator, &initiators, node) {
- u32 value;
-
- if (!test_bit(initiator->processor_pxm, p_nodes))
- continue;
-
- value = hmat_initiator_perf(target, initiator,
- loc->hmat_loc);
- if (hmat_update_best(loc->hmat_loc->data_type, value, &best))
- bitmap_clear(p_nodes, 0, initiator->processor_pxm);
- if (value != best)
- clear_bit(initiator->processor_pxm, p_nodes);
- }
- if (best)
- hmat_update_target_access(target, loc->hmat_loc->data_type,
- best, 0);
- }
-
- for_each_set_bit(i, p_nodes, MAX_NUMNODES) {
- cpu_nid = pxm_to_node(i);
- register_memory_node_under_compute_node(mem_nid, cpu_nid, 0);
- }
- }
-
- /* Access 1 ignores Generic Initiators */
- bitmap_zero(p_nodes, MAX_NUMNODES);
- if (initiators_to_nodemask(p_nodes) < 0)
- return;
-
for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) {
loc = localities_types[i];
if (!loc)
@@ -667,7 +628,7 @@ static void hmat_register_target_initiators(struct memory_target *target)
list_for_each_entry(initiator, &initiators, node) {
u32 value;
- if (!initiator->has_cpu) {
+ if (access == 1 && !initiator->has_cpu) {
clear_bit(initiator->processor_pxm, p_nodes);
continue;
}
@@ -681,14 +642,33 @@ static void hmat_register_target_initiators(struct memory_target *target)
clear_bit(initiator->processor_pxm, p_nodes);
}
if (best)
- hmat_update_target_access(target, loc->hmat_loc->data_type, best, 1);
+ hmat_update_target_access(target, loc->hmat_loc->data_type, best, access);
}
+}
+
+static void __hmat_register_target_initiators(struct memory_target *target,
+ unsigned long *p_nodes,
+ int access)
+{
+ unsigned int mem_nid, cpu_nid;
+ int i;
+
+ mem_nid = pxm_to_node(target->memory_pxm);
+ hmat_update_target_attrs(target, p_nodes, access);
for_each_set_bit(i, p_nodes, MAX_NUMNODES) {
cpu_nid = pxm_to_node(i);
- register_memory_node_under_compute_node(mem_nid, cpu_nid, 1);
+ register_memory_node_under_compute_node(mem_nid, cpu_nid, access);
}
}
+static void hmat_register_target_initiators(struct memory_target *target)
+{
+ static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
+
+ __hmat_register_target_initiators(target, p_nodes, 0);
+ __hmat_register_target_initiators(target, p_nodes, 1);
+}
+
static void hmat_register_target_cache(struct memory_target *target)
{
unsigned mem_nid = pxm_to_node(target->memory_pxm);
@@ -780,6 +760,61 @@ static int hmat_callback(struct notifier_block *self,
return NOTIFY_OK;
}
+static int hmat_set_default_dram_perf(void)
+{
+ int rc;
+ int nid, pxm;
+ struct memory_target *target;
+ struct node_hmem_attrs *attrs;
+
+ if (!default_dram_type)
+ return -EIO;
+
+ for_each_node_mask(nid, default_dram_type->nodes) {
+ pxm = node_to_pxm(nid);
+ target = find_mem_target(pxm);
+ if (!target)
+ continue;
+ attrs = &target->hmem_attrs[1];
+ rc = mt_set_default_dram_perf(nid, attrs, "ACPI HMAT");
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
+static int hmat_calculate_adistance(struct notifier_block *self,
+ unsigned long nid, void *data)
+{
+ static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
+ struct memory_target *target;
+ struct node_hmem_attrs *perf;
+ int *adist = data;
+ int pxm;
+
+ pxm = node_to_pxm(nid);
+ target = find_mem_target(pxm);
+ if (!target)
+ return NOTIFY_OK;
+
+ mutex_lock(&target_lock);
+ hmat_update_target_attrs(target, p_nodes, 1);
+ mutex_unlock(&target_lock);
+
+ perf = &target->hmem_attrs[1];
+
+ if (mt_perf_to_adistance(perf, adist))
+ return NOTIFY_OK;
+
+ return NOTIFY_STOP;
+}
+
+static struct notifier_block hmat_adist_nb __meminitdata = {
+ .notifier_call = hmat_calculate_adistance,
+ .priority = 100,
+};
+
static __init void hmat_free_structures(void)
{
struct memory_target *target, *tnext;
@@ -862,8 +897,13 @@ static __init int hmat_init(void)
hmat_register_targets();
/* Keep the table and structures if the notifier may use them */
- if (!hotplug_memory_notifier(hmat_callback, HMAT_CALLBACK_PRI))
- return 0;
+ if (hotplug_memory_notifier(hmat_callback, HMAT_CALLBACK_PRI))
+ goto out_put;
+
+ if (!hmat_set_default_dram_perf())
+ register_mt_adistance_algorithm(&hmat_adist_nb);
+
+ return 0;
out_put:
hmat_free_structures();
acpi_put_table(tbl);
diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c
index 1f4fc5f8a819..12f330b0eac0 100644
--- a/drivers/acpi/numa/srat.c
+++ b/drivers/acpi/numa/srat.c
@@ -310,11 +310,16 @@ static int __init acpi_parse_cfmws(union acpi_subtable_headers *header,
start = cfmws->base_hpa;
end = cfmws->base_hpa + cfmws->window_size;
- /* Skip if the SRAT already described the NUMA details for this HPA */
- node = phys_to_target_node(start);
- if (node != NUMA_NO_NODE)
+ /*
+ * The SRAT may have already described NUMA details for all,
+ * or a portion of, this CFMWS HPA range. Extend the memblks
+ * found for any portion of the window to cover the entire
+ * window.
+ */
+ if (!numa_fill_memblks(start, end))
return 0;
+ /* No SRAT description. Create a new node. */
node = acpi_map_pxm_to_node(*fake_pxm);
if (node == NUMA_NO_NODE) {
diff --git a/drivers/acpi/osi.c b/drivers/acpi/osi.c
index d4405e1ca9b9..df9328c850bd 100644
--- a/drivers/acpi/osi.c
+++ b/drivers/acpi/osi.c
@@ -110,7 +110,7 @@ void __init acpi_osi_setup(char *str)
break;
} else if (osi->string[0] == '\0') {
osi->enable = enable;
- strncpy(osi->string, str, OSI_STRING_LENGTH_MAX);
+ strscpy(osi->string, str, OSI_STRING_LENGTH_MAX);
break;
}
}
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index f725813d0cce..c09cc3c68633 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -149,7 +149,7 @@ void acpi_os_printf(const char *fmt, ...)
}
EXPORT_SYMBOL(acpi_os_printf);
-void acpi_os_vprintf(const char *fmt, va_list args)
+void __printf(1, 0) acpi_os_vprintf(const char *fmt, va_list args)
{
static char buffer[512];
@@ -276,7 +276,7 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
return NULL;
}
-#if defined(CONFIG_IA64) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
+#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
/* ioremap will take care of cache attributes */
#define should_use_kmap(pfn) 0
#else
@@ -493,7 +493,7 @@ EXPORT_SYMBOL(acpi_os_unmap_generic_address);
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
+acpi_os_get_physical_address(void *virt, acpi_physical_address *phys)
{
if (!phys || !virt)
return AE_BAD_PARAMETER;
@@ -784,7 +784,7 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width)
#ifdef CONFIG_PCI
acpi_status
-acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
+acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id, u32 reg,
u64 *value, u32 width)
{
int result, size;
@@ -816,7 +816,7 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
}
acpi_status
-acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
+acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id, u32 reg,
u64 value, u32 width)
{
int result, size;
@@ -1067,6 +1067,7 @@ acpi_status acpi_os_execute(acpi_execute_type type,
struct acpi_os_dpc *dpc;
struct workqueue_struct *queue;
int ret;
+
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Scheduling function [%p(%p)] for deferred execution.\n",
function, context));
@@ -1197,7 +1198,7 @@ bool acpi_queue_hotplug_work(struct work_struct *work)
}
acpi_status
-acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
+acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle *handle)
{
struct semaphore *sem = NULL;
@@ -1522,6 +1523,7 @@ acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp)
__acquires(lockp)
{
acpi_cpu_flags flags;
+
spin_lock_irqsave(lockp, flags);
return flags;
}
@@ -1554,7 +1556,7 @@ void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags)
******************************************************************************/
acpi_status
-acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
+acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t **cache)
{
*cache = kmem_cache_create(name, size, 0, 0, NULL);
if (*cache == NULL)
@@ -1575,10 +1577,10 @@ acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
*
******************************************************************************/
-acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
+acpi_status acpi_os_purge_cache(acpi_cache_t *cache)
{
kmem_cache_shrink(cache);
- return (AE_OK);
+ return AE_OK;
}
/*******************************************************************************
@@ -1594,10 +1596,10 @@ acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
*
******************************************************************************/
-acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
+acpi_status acpi_os_delete_cache(acpi_cache_t *cache)
{
kmem_cache_destroy(cache);
- return (AE_OK);
+ return AE_OK;
}
/*******************************************************************************
@@ -1614,10 +1616,10 @@ acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
*
******************************************************************************/
-acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
+acpi_status acpi_os_release_object(acpi_cache_t *cache, void *object)
{
kmem_cache_free(cache, object);
- return (AE_OK);
+ return AE_OK;
}
#endif
@@ -1708,6 +1710,7 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state, u32 pm1a_control,
u32 pm1b_control)
{
int rc = 0;
+
if (__acpi_os_prepare_sleep)
rc = __acpi_os_prepare_sleep(sleep_state,
pm1a_control, pm1b_control);
@@ -1730,6 +1733,7 @@ acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a,
u32 val_b)
{
int rc = 0;
+
if (__acpi_os_prepare_extended_sleep)
rc = __acpi_os_prepare_extended_sleep(sleep_state,
val_a, val_b);
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 84030804a763..58b89b8d950e 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -1055,9 +1055,9 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
* exists and returns 0, we must preserve any PCI resource
* assignments made by firmware for this host bridge.
*/
- obj = acpi_evaluate_dsm(ACPI_HANDLE(bus->bridge), &pci_acpi_dsm_guid, 1,
- DSM_PCI_PRESERVE_BOOT_CONFIG, NULL);
- if (obj && obj->type == ACPI_TYPE_INTEGER && obj->integer.value == 0)
+ obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(bus->bridge), &pci_acpi_dsm_guid, 1,
+ DSM_PCI_PRESERVE_BOOT_CONFIG, NULL, ACPI_TYPE_INTEGER);
+ if (obj && obj->integer.value == 0)
host_bridge->preserve_config = 1;
ACPI_FREE(obj);
diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c
index 7020584096bf..c78453c74ef5 100644
--- a/drivers/acpi/prmt.c
+++ b/drivers/acpi/prmt.c
@@ -69,7 +69,7 @@ struct prm_module_info {
bool updatable;
struct list_head module_list;
- struct prm_handler_info handlers[];
+ struct prm_handler_info handlers[] __counted_by(handler_count);
};
static u64 efi_pa_va_lookup(u64 pa)
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 7dd6dbaa98c3..b203cfe28550 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -90,7 +90,7 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry,
struct acpi_madt_generic_interrupt *gicc =
container_of(entry, struct acpi_madt_generic_interrupt, header);
- if (!(gicc->flags & ACPI_MADT_ENABLED))
+ if (!acpi_gicc_is_usable(gicc))
return -ENODEV;
/* device_declaration means Device object in DSDT, in the
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 3a34a8c425fe..55437f5e0c3a 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -592,7 +592,7 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
while (1) {
if (cx->entry_method == ACPI_CSTATE_HALT)
- safe_halt();
+ raw_safe_halt();
else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
io_idle(cx->address);
} else
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 413e4fcadcaf..6979a3f9f90a 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -55,6 +55,7 @@ static const guid_t ads_guid =
GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b);
+/* ACPI _DSD data buffer GUID: edb12dd0-363d-4085-a3d2-49522ca160c4 */
static const guid_t buffer_prop_guid =
GUID_INIT(0xedb12dd0, 0x363d, 0x4085,
0xa3, 0xd2, 0x49, 0x52, 0x2c, 0xa1, 0x60, 0xc4);
@@ -1102,25 +1103,26 @@ static int acpi_data_prop_read(const struct acpi_device_data *data,
switch (proptype) {
case DEV_PROP_STRING:
break;
- case DEV_PROP_U8 ... DEV_PROP_U64:
+ default:
if (obj->type == ACPI_TYPE_BUFFER) {
if (nval > obj->buffer.length)
return -EOVERFLOW;
- break;
+ } else {
+ if (nval > obj->package.count)
+ return -EOVERFLOW;
}
- fallthrough;
- default:
- if (nval > obj->package.count)
- return -EOVERFLOW;
break;
}
if (nval == 0)
return -EINVAL;
- if (obj->type != ACPI_TYPE_BUFFER)
- items = obj->package.elements;
- else
+ if (obj->type == ACPI_TYPE_BUFFER) {
+ if (proptype != DEV_PROP_U8)
+ return -EPROTO;
items = obj;
+ } else {
+ items = obj->package.elements;
+ }
switch (proptype) {
case DEV_PROP_U8:
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 32cfa3f4efd3..9bd9f79cd409 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -385,140 +385,167 @@ unsigned int acpi_dev_get_irq_type(int triggering, int polarity)
}
EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type);
-static const struct dmi_system_id medion_laptop[] = {
+/*
+ * DMI matches for boards where the DSDT specifies the kbd IRQ as
+ * level active-low and using the override changes this to rising edge,
+ * stopping the keyboard from working.
+ */
+static const struct dmi_system_id irq1_level_low_skip_override[] = {
{
- .ident = "MEDION P15651",
+ /* MEDION P15651 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
DMI_MATCH(DMI_BOARD_NAME, "M15T"),
},
},
{
- .ident = "MEDION S17405",
+ /* MEDION S17405 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
DMI_MATCH(DMI_BOARD_NAME, "M17T"),
},
},
{
- .ident = "MEDION S17413",
+ /* MEDION S17413 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
DMI_MATCH(DMI_BOARD_NAME, "M1xA"),
},
},
- { }
-};
-
-static const struct dmi_system_id asus_laptop[] = {
{
- .ident = "Asus Vivobook K3402ZA",
+ /* Asus Vivobook K3402ZA */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_BOARD_NAME, "K3402ZA"),
},
},
{
- .ident = "Asus Vivobook K3502ZA",
+ /* Asus Vivobook K3502ZA */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_BOARD_NAME, "K3502ZA"),
},
},
{
- .ident = "Asus Vivobook S5402ZA",
+ /* Asus Vivobook S5402ZA */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_BOARD_NAME, "S5402ZA"),
},
},
{
- .ident = "Asus Vivobook S5602ZA",
+ /* Asus Vivobook S5602ZA */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"),
},
},
{
- .ident = "Asus ExpertBook B1502CBA",
+ /* Asus ExpertBook B1402CBA */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "B1402CBA"),
+ },
+ },
+ {
+ /* Asus ExpertBook B1402CVA */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "B1402CVA"),
+ },
+ },
+ {
+ /* Asus ExpertBook B1502CBA */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_BOARD_NAME, "B1502CBA"),
},
},
{
- .ident = "Asus ExpertBook B2402CBA",
+ /* Asus ExpertBook B2402CBA */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_BOARD_NAME, "B2402CBA"),
},
},
{
- .ident = "Asus ExpertBook B2402FBA",
+ /* Asus ExpertBook B2402FBA */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_BOARD_NAME, "B2402FBA"),
},
},
{
- .ident = "Asus ExpertBook B2502",
+ /* Asus ExpertBook B2502 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_BOARD_NAME, "B2502CBA"),
},
},
+ {
+ /* LG Electronics 17U70P */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
+ DMI_MATCH(DMI_BOARD_NAME, "17U70P"),
+ },
+ },
{ }
};
-static const struct dmi_system_id tongfang_gm_rg[] = {
+/*
+ * DMI matches for AMD Zen boards where the DSDT specifies the kbd IRQ
+ * as falling edge and this must be overridden to rising edge,
+ * to have a working keyboard.
+ */
+static const struct dmi_system_id irq1_edge_low_force_override[] = {
{
- .ident = "TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD",
+ /* TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD */
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
},
},
- { }
-};
-
-static const struct dmi_system_id maingear_laptop[] = {
{
- .ident = "MAINGEAR Vector Pro 2 15",
+ /* TongFang GMxXGxx/TUXEDO Polaris 15 Gen5 AMD */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
+ },
+ },
+ {
+ /* TongFang GM6XGxX/TUXEDO Stellaris 16 Gen5 AMD */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"),
+ },
+ },
+ {
+ /* MAINGEAR Vector Pro 2 15 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),
DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"),
}
},
{
- .ident = "MAINGEAR Vector Pro 2 17",
+ /* MAINGEAR Vector Pro 2 17 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),
DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-17A3070T"),
},
},
- { }
-};
-
-static const struct dmi_system_id pcspecialist_laptop[] = {
{
- .ident = "PCSpecialist Elimina Pro 16 M",
- /*
- * Some models have product-name "Elimina Pro 16 M",
- * others "GM6BGEQ". Match on board-name to match both.
- */
+ /* TongFang GM6BGEQ / PCSpecialist Elimina Pro 16 M, RTX 3050 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "PCSpecialist"),
DMI_MATCH(DMI_BOARD_NAME, "GM6BGEQ"),
},
},
- { }
-};
-
-static const struct dmi_system_id lg_laptop[] = {
{
- .ident = "LG Electronics 17U70P",
+ /* TongFang GM6BG5Q, RTX 4050 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
- DMI_MATCH(DMI_BOARD_NAME, "17U70P"),
+ DMI_MATCH(DMI_BOARD_NAME, "GM6BG5Q"),
+ },
+ },
+ {
+ /* TongFang GM6BG0Q / PCSpecialist Elimina Pro 16 M, RTX 4060 */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GM6BG0Q"),
},
},
{ }
@@ -534,12 +561,8 @@ struct irq_override_cmp {
};
static const struct irq_override_cmp override_table[] = {
- { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
- { asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
- { tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
- { maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
- { pcspecialist_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
- { lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
+ { irq1_level_low_skip_override, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
+ { irq1_edge_low_force_override, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
};
static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
diff --git a/drivers/acpi/riscv/rhct.c b/drivers/acpi/riscv/rhct.c
index b280b3e9c7d9..caa2c16e1697 100644
--- a/drivers/acpi/riscv/rhct.c
+++ b/drivers/acpi/riscv/rhct.c
@@ -8,8 +8,9 @@
#define pr_fmt(fmt) "ACPI: RHCT: " fmt
#include <linux/acpi.h>
+#include <linux/bits.h>
-static struct acpi_table_header *acpi_get_rhct(void)
+static struct acpi_table_rhct *acpi_get_rhct(void)
{
static struct acpi_table_header *rhct;
acpi_status status;
@@ -26,7 +27,7 @@ static struct acpi_table_header *acpi_get_rhct(void)
}
}
- return rhct;
+ return (struct acpi_table_rhct *)rhct;
}
/*
@@ -48,7 +49,7 @@ int acpi_get_riscv_isa(struct acpi_table_header *table, unsigned int cpu, const
BUG_ON(acpi_disabled);
if (!table) {
- rhct = (struct acpi_table_rhct *)acpi_get_rhct();
+ rhct = acpi_get_rhct();
if (!rhct)
return -ENOENT;
} else {
@@ -81,3 +82,89 @@ int acpi_get_riscv_isa(struct acpi_table_header *table, unsigned int cpu, const
return -1;
}
+
+static void acpi_parse_hart_info_cmo_node(struct acpi_table_rhct *rhct,
+ struct acpi_rhct_hart_info *hart_info,
+ u32 *cbom_size, u32 *cboz_size, u32 *cbop_size)
+{
+ u32 size_hartinfo = sizeof(struct acpi_rhct_hart_info);
+ u32 size_hdr = sizeof(struct acpi_rhct_node_header);
+ struct acpi_rhct_node_header *ref_node;
+ struct acpi_rhct_cmo_node *cmo_node;
+ u32 *hart_info_node_offset;
+
+ hart_info_node_offset = ACPI_ADD_PTR(u32, hart_info, size_hartinfo);
+ for (int i = 0; i < hart_info->num_offsets; i++) {
+ ref_node = ACPI_ADD_PTR(struct acpi_rhct_node_header,
+ rhct, hart_info_node_offset[i]);
+ if (ref_node->type == ACPI_RHCT_NODE_TYPE_CMO) {
+ cmo_node = ACPI_ADD_PTR(struct acpi_rhct_cmo_node,
+ ref_node, size_hdr);
+ if (cbom_size && cmo_node->cbom_size <= 30) {
+ if (!*cbom_size)
+ *cbom_size = BIT(cmo_node->cbom_size);
+ else if (*cbom_size != BIT(cmo_node->cbom_size))
+ pr_warn("CBOM size is not the same across harts\n");
+ }
+
+ if (cboz_size && cmo_node->cboz_size <= 30) {
+ if (!*cboz_size)
+ *cboz_size = BIT(cmo_node->cboz_size);
+ else if (*cboz_size != BIT(cmo_node->cboz_size))
+ pr_warn("CBOZ size is not the same across harts\n");
+ }
+
+ if (cbop_size && cmo_node->cbop_size <= 30) {
+ if (!*cbop_size)
+ *cbop_size = BIT(cmo_node->cbop_size);
+ else if (*cbop_size != BIT(cmo_node->cbop_size))
+ pr_warn("CBOP size is not the same across harts\n");
+ }
+ }
+ }
+}
+
+/*
+ * During early boot, the caller should call acpi_get_table() and pass its pointer to
+ * these functions (and free up later). At run time, since this table can be used
+ * multiple times, pass NULL so that the table remains in memory.
+ */
+void acpi_get_cbo_block_size(struct acpi_table_header *table, u32 *cbom_size,
+ u32 *cboz_size, u32 *cbop_size)
+{
+ u32 size_hdr = sizeof(struct acpi_rhct_node_header);
+ struct acpi_rhct_node_header *node, *end;
+ struct acpi_rhct_hart_info *hart_info;
+ struct acpi_table_rhct *rhct;
+
+ if (acpi_disabled)
+ return;
+
+ if (table) {
+ rhct = (struct acpi_table_rhct *)table;
+ } else {
+ rhct = acpi_get_rhct();
+ if (!rhct)
+ return;
+ }
+
+ if (cbom_size)
+ *cbom_size = 0;
+
+ if (cboz_size)
+ *cboz_size = 0;
+
+ if (cbop_size)
+ *cbop_size = 0;
+
+ end = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->header.length);
+ for (node = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->node_offset);
+ node < end;
+ node = ACPI_ADD_PTR(struct acpi_rhct_node_header, node, node->length)) {
+ if (node->type == ACPI_RHCT_NODE_TYPE_HART_INFO) {
+ hart_info = ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, size_hdr);
+ acpi_parse_hart_info_cmo_node(rhct, hart_info, cbom_size,
+ cboz_size, cbop_size);
+ }
+ }
+}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 691d4b7686ee..02bb2cce423f 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -289,10 +289,10 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
return 0;
}
-static int acpi_scan_device_not_present(struct acpi_device *adev)
+static int acpi_scan_device_not_enumerated(struct acpi_device *adev)
{
if (!acpi_device_enumerated(adev)) {
- dev_warn(&adev->dev, "Still not present\n");
+ dev_warn(&adev->dev, "Still not enumerated\n");
return -EALREADY;
}
acpi_bus_trim(adev);
@@ -304,7 +304,7 @@ static int acpi_scan_device_check(struct acpi_device *adev)
int error;
acpi_bus_get_status(adev);
- if (adev->status.present || adev->status.functional) {
+ if (acpi_device_is_present(adev)) {
/*
* This function is only called for device objects for which
* matching scan handlers exist. The only situation in which
@@ -327,7 +327,7 @@ static int acpi_scan_device_check(struct acpi_device *adev)
error = -ENODEV;
}
} else {
- error = acpi_scan_device_not_present(adev);
+ error = acpi_scan_device_not_enumerated(adev);
}
return error;
}
@@ -338,8 +338,8 @@ static int acpi_scan_bus_check(struct acpi_device *adev, void *not_used)
int error;
acpi_bus_get_status(adev);
- if (!(adev->status.present || adev->status.functional)) {
- acpi_scan_device_not_present(adev);
+ if (!acpi_device_is_present(adev)) {
+ acpi_scan_device_not_enumerated(adev);
return 0;
}
if (handler && handler->hotplug.scan_dependent)
@@ -1568,17 +1568,22 @@ static const struct iommu_ops *acpi_iommu_configure_id(struct device *dev,
int err;
const struct iommu_ops *ops;
+ /* Serialise to make dev->iommu stable under our potential fwspec */
+ mutex_lock(&iommu_probe_device_lock);
/*
* If we already translated the fwspec there is nothing left to do,
* return the iommu_ops.
*/
ops = acpi_iommu_fwspec_ops(dev);
- if (ops)
+ if (ops) {
+ mutex_unlock(&iommu_probe_device_lock);
return ops;
+ }
err = iort_iommu_configure_id(dev, id_in);
if (err && err != -EPROBE_DEFER)
err = viot_iommu_configure(dev);
+ mutex_unlock(&iommu_probe_device_lock);
/*
* If we have reason to believe the IOMMU driver missed the initial
@@ -2032,6 +2037,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
mutex_unlock(&acpi_dep_list_lock);
}
+ acpi_handle_list_free(&dep_devices);
return count;
}
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 8ab0a82b4da4..c1516337f668 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -37,18 +37,6 @@ static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata;
static int acpi_apic_instance __initdata_or_acpilib;
-enum acpi_subtable_type {
- ACPI_SUBTABLE_COMMON,
- ACPI_SUBTABLE_HMAT,
- ACPI_SUBTABLE_PRMT,
- ACPI_SUBTABLE_CEDT,
-};
-
-struct acpi_subtable_entry {
- union acpi_subtable_headers *hdr;
- enum acpi_subtable_type type;
-};
-
/*
* Disable table checksum verification for the early stage due to the size
* limitation of the current x86 early mapping implementation.
@@ -237,167 +225,6 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
}
}
-static unsigned long __init_or_acpilib
-acpi_get_entry_type(struct acpi_subtable_entry *entry)
-{
- switch (entry->type) {
- case ACPI_SUBTABLE_COMMON:
- return entry->hdr->common.type;
- case ACPI_SUBTABLE_HMAT:
- return entry->hdr->hmat.type;
- case ACPI_SUBTABLE_PRMT:
- return 0;
- case ACPI_SUBTABLE_CEDT:
- return entry->hdr->cedt.type;
- }
- return 0;
-}
-
-static unsigned long __init_or_acpilib
-acpi_get_entry_length(struct acpi_subtable_entry *entry)
-{
- switch (entry->type) {
- case ACPI_SUBTABLE_COMMON:
- return entry->hdr->common.length;
- case ACPI_SUBTABLE_HMAT:
- return entry->hdr->hmat.length;
- case ACPI_SUBTABLE_PRMT:
- return entry->hdr->prmt.length;
- case ACPI_SUBTABLE_CEDT:
- return entry->hdr->cedt.length;
- }
- return 0;
-}
-
-static unsigned long __init_or_acpilib
-acpi_get_subtable_header_length(struct acpi_subtable_entry *entry)
-{
- switch (entry->type) {
- case ACPI_SUBTABLE_COMMON:
- return sizeof(entry->hdr->common);
- case ACPI_SUBTABLE_HMAT:
- return sizeof(entry->hdr->hmat);
- case ACPI_SUBTABLE_PRMT:
- return sizeof(entry->hdr->prmt);
- case ACPI_SUBTABLE_CEDT:
- return sizeof(entry->hdr->cedt);
- }
- return 0;
-}
-
-static enum acpi_subtable_type __init_or_acpilib
-acpi_get_subtable_type(char *id)
-{
- if (strncmp(id, ACPI_SIG_HMAT, 4) == 0)
- return ACPI_SUBTABLE_HMAT;
- if (strncmp(id, ACPI_SIG_PRMT, 4) == 0)
- return ACPI_SUBTABLE_PRMT;
- if (strncmp(id, ACPI_SIG_CEDT, 4) == 0)
- return ACPI_SUBTABLE_CEDT;
- return ACPI_SUBTABLE_COMMON;
-}
-
-static __init_or_acpilib bool has_handler(struct acpi_subtable_proc *proc)
-{
- return proc->handler || proc->handler_arg;
-}
-
-static __init_or_acpilib int call_handler(struct acpi_subtable_proc *proc,
- union acpi_subtable_headers *hdr,
- unsigned long end)
-{
- if (proc->handler)
- return proc->handler(hdr, end);
- if (proc->handler_arg)
- return proc->handler_arg(hdr, proc->arg, end);
- return -EINVAL;
-}
-
-/**
- * acpi_parse_entries_array - for each proc_num find a suitable subtable
- *
- * @id: table id (for debugging purposes)
- * @table_size: size of the root table
- * @table_header: where does the table start?
- * @proc: array of acpi_subtable_proc struct containing entry id
- * and associated handler with it
- * @proc_num: how big proc is?
- * @max_entries: how many entries can we process?
- *
- * For each proc_num find a subtable with proc->id and run proc->handler
- * on it. Assumption is that there's only single handler for particular
- * entry id.
- *
- * The table_size is not the size of the complete ACPI table (the length
- * field in the header struct), but only the size of the root table; i.e.,
- * the offset from the very first byte of the complete ACPI table, to the
- * first byte of the very first subtable.
- *
- * On success returns sum of all matching entries for all proc handlers.
- * Otherwise, -ENODEV or -EINVAL is returned.
- */
-static int __init_or_acpilib acpi_parse_entries_array(
- char *id, unsigned long table_size,
- struct acpi_table_header *table_header, struct acpi_subtable_proc *proc,
- int proc_num, unsigned int max_entries)
-{
- struct acpi_subtable_entry entry;
- unsigned long table_end, subtable_len, entry_len;
- int count = 0;
- int errs = 0;
- int i;
-
- table_end = (unsigned long)table_header + table_header->length;
-
- /* Parse all entries looking for a match. */
-
- entry.type = acpi_get_subtable_type(id);
- entry.hdr = (union acpi_subtable_headers *)
- ((unsigned long)table_header + table_size);
- subtable_len = acpi_get_subtable_header_length(&entry);
-
- while (((unsigned long)entry.hdr) + subtable_len < table_end) {
- if (max_entries && count >= max_entries)
- break;
-
- for (i = 0; i < proc_num; i++) {
- if (acpi_get_entry_type(&entry) != proc[i].id)
- continue;
- if (!has_handler(&proc[i]) ||
- (!errs &&
- call_handler(&proc[i], entry.hdr, table_end))) {
- errs++;
- continue;
- }
-
- proc[i].count++;
- break;
- }
- if (i != proc_num)
- count++;
-
- /*
- * If entry->length is 0, break from this loop to avoid
- * infinite loop.
- */
- entry_len = acpi_get_entry_length(&entry);
- if (entry_len == 0) {
- pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id);
- return -EINVAL;
- }
-
- entry.hdr = (union acpi_subtable_headers *)
- ((unsigned long)entry.hdr + entry_len);
- }
-
- if (max_entries && count > max_entries) {
- pr_warn("[%4.4s:0x%02x] found the maximum %i entries\n",
- id, proc->id, count);
- }
-
- return errs ? -EINVAL : count;
-}
-
int __init_or_acpilib acpi_table_parse_entries_array(
char *id, unsigned long table_size, struct acpi_subtable_proc *proc,
int proc_num, unsigned int max_entries)
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 312730f8272e..f74d81abdbfc 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -43,17 +43,7 @@
#define ACPI_THERMAL_MAX_ACTIVE 10
#define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
-#define ACPI_TRIPS_CRITICAL BIT(0)
-#define ACPI_TRIPS_HOT BIT(1)
-#define ACPI_TRIPS_PASSIVE BIT(2)
-#define ACPI_TRIPS_ACTIVE BIT(3)
-#define ACPI_TRIPS_DEVICES BIT(4)
-
-#define ACPI_TRIPS_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
-
-#define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \
- ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \
- ACPI_TRIPS_DEVICES)
+#define ACPI_THERMAL_TRIP_PASSIVE (-1)
/*
* This exception is thrown out in two cases:
@@ -62,12 +52,11 @@
* 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
* We need to re-bind the cooling devices of a thermal zone when this occurs.
*/
-#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, tz, str) \
+#define ACPI_THERMAL_TRIPS_EXCEPTION(tz, str) \
do { \
- if (flags != ACPI_TRIPS_INIT) \
- acpi_handle_info(tz->device->handle, \
- "ACPI thermal trip point %s changed\n" \
- "Please report to linux-acpi@vger.kernel.org\n", str); \
+ acpi_handle_info(tz->device->handle, \
+ "ACPI thermal trip point %s changed\n" \
+ "Please report to linux-acpi@vger.kernel.org\n", str); \
} while (0)
static int act;
@@ -93,13 +82,12 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
static struct workqueue_struct *acpi_thermal_pm_queue;
struct acpi_thermal_trip {
- unsigned long temperature;
- bool valid;
+ unsigned long temp_dk;
+ struct acpi_handle_list devices;
};
struct acpi_thermal_passive {
struct acpi_thermal_trip trip;
- struct acpi_handle_list devices;
unsigned long tc1;
unsigned long tc2;
unsigned long tsp;
@@ -107,12 +95,9 @@ struct acpi_thermal_passive {
struct acpi_thermal_active {
struct acpi_thermal_trip trip;
- struct acpi_handle_list devices;
};
struct acpi_thermal_trips {
- struct acpi_thermal_trip critical;
- struct acpi_thermal_trip hot;
struct acpi_thermal_passive passive;
struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
};
@@ -120,13 +105,12 @@ struct acpi_thermal_trips {
struct acpi_thermal {
struct acpi_device *device;
acpi_bus_id name;
- unsigned long temperature;
- unsigned long last_temperature;
+ unsigned long temp_dk;
+ unsigned long last_temp_dk;
unsigned long polling_frequency;
volatile u8 zombie;
struct acpi_thermal_trips trips;
struct thermal_trip *trip_table;
- struct acpi_handle_list devices;
struct thermal_zone_device *thermal_zone;
int kelvin_offset; /* in millidegrees */
struct work_struct thermal_check_work;
@@ -146,16 +130,16 @@ static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
if (!tz)
return -EINVAL;
- tz->last_temperature = tz->temperature;
+ tz->last_temp_dk = tz->temp_dk;
status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp);
if (ACPI_FAILURE(status))
return -ENODEV;
- tz->temperature = tmp;
+ tz->temp_dk = tmp;
acpi_handle_debug(tz->device->handle, "Temperature is %lu dK\n",
- tz->temperature);
+ tz->temp_dk);
return 0;
}
@@ -188,245 +172,148 @@ static int acpi_thermal_temp(struct acpi_thermal *tz, int temp_deci_k)
tz->kelvin_offset);
}
-static void __acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
+static bool acpi_thermal_trip_valid(struct acpi_thermal_trip *acpi_trip)
+{
+ return acpi_trip->temp_dk != THERMAL_TEMP_INVALID;
+}
+
+static int active_trip_index(struct acpi_thermal *tz,
+ struct acpi_thermal_trip *acpi_trip)
+{
+ struct acpi_thermal_active *active;
+
+ active = container_of(acpi_trip, struct acpi_thermal_active, trip);
+ return active - tz->trips.active;
+}
+
+static long get_passive_temp(struct acpi_thermal *tz)
{
+ unsigned long long tmp;
acpi_status status;
+
+ status = acpi_evaluate_integer(tz->device->handle, "_PSV", NULL, &tmp);
+ if (ACPI_FAILURE(status))
+ return THERMAL_TEMP_INVALID;
+
+ return tmp;
+}
+
+static long get_active_temp(struct acpi_thermal *tz, int index)
+{
+ char method[] = { '_', 'A', 'C', '0' + index, '\0' };
unsigned long long tmp;
- struct acpi_handle_list devices;
- bool valid = false;
- int i;
+ acpi_status status;
- /* Critical Shutdown */
- if (flag & ACPI_TRIPS_CRITICAL) {
- status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp);
- tz->trips.critical.temperature = tmp;
- /*
- * Treat freezing temperatures as invalid as well; some
- * BIOSes return really low values and cause reboots at startup.
- * Below zero (Celsius) values clearly aren't right for sure..
- * ... so lets discard those as invalid.
- */
- if (ACPI_FAILURE(status)) {
- tz->trips.critical.valid = false;
- acpi_handle_debug(tz->device->handle,
- "No critical threshold\n");
- } else if (tmp <= 2732) {
- pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp);
- tz->trips.critical.valid = false;
- } else {
- tz->trips.critical.valid = true;
- acpi_handle_debug(tz->device->handle,
- "Found critical threshold [%lu]\n",
- tz->trips.critical.temperature);
- }
- if (tz->trips.critical.valid) {
- if (crt == -1) {
- tz->trips.critical.valid = false;
- } else if (crt > 0) {
- unsigned long crt_k = celsius_to_deci_kelvin(crt);
-
- /*
- * Allow override critical threshold
- */
- if (crt_k > tz->trips.critical.temperature)
- pr_info("Critical threshold %d C\n", crt);
-
- tz->trips.critical.temperature = crt_k;
- }
- }
+ status = acpi_evaluate_integer(tz->device->handle, method, NULL, &tmp);
+ if (ACPI_FAILURE(status))
+ return THERMAL_TEMP_INVALID;
+
+ /*
+ * If an override has been provided, apply it so there are no active
+ * trips with thresholds greater than the override.
+ */
+ if (act > 0) {
+ unsigned long long override = celsius_to_deci_kelvin(act);
+
+ if (tmp > override)
+ tmp = override;
}
+ return tmp;
+}
- /* Critical Sleep (optional) */
- if (flag & ACPI_TRIPS_HOT) {
- status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp);
- if (ACPI_FAILURE(status)) {
- tz->trips.hot.valid = false;
- acpi_handle_debug(tz->device->handle,
- "No hot threshold\n");
- } else {
- tz->trips.hot.temperature = tmp;
- tz->trips.hot.valid = true;
- acpi_handle_debug(tz->device->handle,
- "Found hot threshold [%lu]\n",
- tz->trips.hot.temperature);
- }
+static void acpi_thermal_update_trip(struct acpi_thermal *tz,
+ const struct thermal_trip *trip)
+{
+ struct acpi_thermal_trip *acpi_trip = trip->priv;
+
+ if (trip->type == THERMAL_TRIP_PASSIVE) {
+ if (psv > 0)
+ return;
+
+ acpi_trip->temp_dk = get_passive_temp(tz);
+ } else {
+ int index = active_trip_index(tz, acpi_trip);
+
+ acpi_trip->temp_dk = get_active_temp(tz, index);
}
- /* Passive (optional) */
- if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.trip.valid) ||
- flag == ACPI_TRIPS_INIT) {
- valid = tz->trips.passive.trip.valid;
- if (psv == -1) {
- status = AE_SUPPORT;
- } else if (psv > 0) {
- tmp = celsius_to_deci_kelvin(psv);
- status = AE_OK;
- } else {
- status = acpi_evaluate_integer(tz->device->handle,
- "_PSV", NULL, &tmp);
- }
+ if (!acpi_thermal_trip_valid(acpi_trip))
+ ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state");
+}
- if (ACPI_FAILURE(status)) {
- tz->trips.passive.trip.valid = false;
- } else {
- tz->trips.passive.trip.temperature = tmp;
- tz->trips.passive.trip.valid = true;
- if (flag == ACPI_TRIPS_INIT) {
- status = acpi_evaluate_integer(tz->device->handle,
- "_TC1", NULL, &tmp);
- if (ACPI_FAILURE(status))
- tz->trips.passive.trip.valid = false;
- else
- tz->trips.passive.tc1 = tmp;
-
- status = acpi_evaluate_integer(tz->device->handle,
- "_TC2", NULL, &tmp);
- if (ACPI_FAILURE(status))
- tz->trips.passive.trip.valid = false;
- else
- tz->trips.passive.tc2 = tmp;
-
- status = acpi_evaluate_integer(tz->device->handle,
- "_TSP", NULL, &tmp);
- if (ACPI_FAILURE(status))
- tz->trips.passive.trip.valid = false;
- else
- tz->trips.passive.tsp = tmp;
- }
- }
+static bool update_trip_devices(struct acpi_thermal *tz,
+ struct acpi_thermal_trip *acpi_trip,
+ int index, bool compare)
+{
+ struct acpi_handle_list devices = { 0 };
+ char method[] = "_PSL";
+ acpi_status status;
+
+ if (index != ACPI_THERMAL_TRIP_PASSIVE) {
+ method[1] = 'A';
+ method[2] = 'L';
+ method[3] = '0' + index;
}
- if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.trip.valid) {
- memset(&devices, 0, sizeof(struct acpi_handle_list));
- status = acpi_evaluate_reference(tz->device->handle, "_PSL",
- NULL, &devices);
- if (ACPI_FAILURE(status)) {
- acpi_handle_info(tz->device->handle,
- "Invalid passive threshold\n");
- tz->trips.passive.trip.valid = false;
- } else {
- tz->trips.passive.trip.valid = true;
- }
- if (memcmp(&tz->trips.passive.devices, &devices,
- sizeof(struct acpi_handle_list))) {
- memcpy(&tz->trips.passive.devices, &devices,
- sizeof(struct acpi_handle_list));
- ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
- }
+ status = acpi_evaluate_reference(tz->device->handle, method, NULL, &devices);
+ if (ACPI_FAILURE(status)) {
+ acpi_handle_info(tz->device->handle, "%s evaluation failure\n", method);
+ return false;
}
- if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
- if (valid != tz->trips.passive.trip.valid)
- ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state");
+
+ if (acpi_handle_list_equal(&acpi_trip->devices, &devices)) {
+ acpi_handle_list_free(&devices);
+ return true;
}
- /* Active (optional) */
- for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
- char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
- valid = tz->trips.active[i].trip.valid;
+ if (compare)
+ ACPI_THERMAL_TRIPS_EXCEPTION(tz, "device");
- if (act == -1)
- break; /* disable all active trip points */
-
- if (flag == ACPI_TRIPS_INIT || ((flag & ACPI_TRIPS_ACTIVE) &&
- tz->trips.active[i].trip.valid)) {
- status = acpi_evaluate_integer(tz->device->handle,
- name, NULL, &tmp);
- if (ACPI_FAILURE(status)) {
- tz->trips.active[i].trip.valid = false;
- if (i == 0)
- break;
-
- if (act <= 0)
- break;
-
- if (i == 1)
- tz->trips.active[0].trip.temperature =
- celsius_to_deci_kelvin(act);
- else
- /*
- * Don't allow override higher than
- * the next higher trip point
- */
- tz->trips.active[i-1].trip.temperature =
- min_t(unsigned long,
- tz->trips.active[i-2].trip.temperature,
- celsius_to_deci_kelvin(act));
-
- break;
- } else {
- tz->trips.active[i].trip.temperature = tmp;
- tz->trips.active[i].trip.valid = true;
- }
- }
+ acpi_handle_list_replace(&acpi_trip->devices, &devices);
+ return true;
+}
- name[2] = 'L';
- if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].trip.valid) {
- memset(&devices, 0, sizeof(struct acpi_handle_list));
- status = acpi_evaluate_reference(tz->device->handle,
- name, NULL, &devices);
- if (ACPI_FAILURE(status)) {
- acpi_handle_info(tz->device->handle,
- "Invalid active%d threshold\n", i);
- tz->trips.active[i].trip.valid = false;
- } else {
- tz->trips.active[i].trip.valid = true;
- }
-
- if (memcmp(&tz->trips.active[i].devices, &devices,
- sizeof(struct acpi_handle_list))) {
- memcpy(&tz->trips.active[i].devices, &devices,
- sizeof(struct acpi_handle_list));
- ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
- }
- }
- if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
- if (valid != tz->trips.active[i].trip.valid)
- ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state");
+static void acpi_thermal_update_trip_devices(struct acpi_thermal *tz,
+ const struct thermal_trip *trip)
+{
+ struct acpi_thermal_trip *acpi_trip = trip->priv;
+ int index = trip->type == THERMAL_TRIP_PASSIVE ?
+ ACPI_THERMAL_TRIP_PASSIVE : active_trip_index(tz, acpi_trip);
- if (!tz->trips.active[i].trip.valid)
- break;
- }
+ if (update_trip_devices(tz, acpi_trip, index, true))
+ return;
- if (flag & ACPI_TRIPS_DEVICES) {
- memset(&devices, 0, sizeof(devices));
- status = acpi_evaluate_reference(tz->device->handle, "_TZD",
- NULL, &devices);
- if (ACPI_SUCCESS(status) &&
- memcmp(&tz->devices, &devices, sizeof(devices))) {
- tz->devices = devices;
- ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
- }
- }
+ acpi_trip->temp_dk = THERMAL_TEMP_INVALID;
+ ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state");
}
+struct adjust_trip_data {
+ struct acpi_thermal *tz;
+ u32 event;
+};
+
static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data)
{
struct acpi_thermal_trip *acpi_trip = trip->priv;
- struct acpi_thermal *tz = data;
+ struct adjust_trip_data *atd = data;
+ struct acpi_thermal *tz = atd->tz;
- if (!acpi_trip)
+ if (!acpi_trip || !acpi_thermal_trip_valid(acpi_trip))
return 0;
- if (acpi_trip->valid)
- trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature);
+ if (atd->event == ACPI_THERMAL_NOTIFY_THRESHOLDS)
+ acpi_thermal_update_trip(tz, trip);
+ else
+ acpi_thermal_update_trip_devices(tz, trip);
+
+ if (acpi_thermal_trip_valid(acpi_trip))
+ trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk);
else
trip->temperature = THERMAL_TEMP_INVALID;
return 0;
}
-static void acpi_thermal_adjust_thermal_zone(struct thermal_zone_device *thermal,
- unsigned long data)
-{
- struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
- int flag = data == ACPI_THERMAL_NOTIFY_THRESHOLDS ?
- ACPI_TRIPS_THRESHOLDS : ACPI_TRIPS_DEVICES;
-
- __acpi_thermal_trips_update(tz, flag);
-
- for_each_thermal_trip(tz->thermal_zone, acpi_thermal_adjust_trip, tz);
-}
-
static void acpi_queue_thermal_check(struct acpi_thermal *tz)
{
if (!work_pending(&tz->thermal_check_work))
@@ -435,41 +322,156 @@ static void acpi_queue_thermal_check(struct acpi_thermal *tz)
static void acpi_thermal_trips_update(struct acpi_thermal *tz, u32 event)
{
+ struct adjust_trip_data atd = { .tz = tz, .event = event };
struct acpi_device *adev = tz->device;
/*
- * Use thermal_zone_device_exec() to carry out the trip points
+ * Use thermal_zone_for_each_trip() to carry out the trip points
* update, so as to protect thermal_get_trend() from getting stale
* trip point temperatures and to prevent thermal_zone_device_update()
* invoked from acpi_thermal_check_fn() from producing inconsistent
* results.
*/
- thermal_zone_device_exec(tz->thermal_zone,
- acpi_thermal_adjust_thermal_zone, event);
+ thermal_zone_for_each_trip(tz->thermal_zone,
+ acpi_thermal_adjust_trip, &atd);
acpi_queue_thermal_check(tz);
acpi_bus_generate_netlink_event(adev->pnp.device_class,
dev_name(&adev->dev), event, 0);
}
+static long acpi_thermal_get_critical_trip(struct acpi_thermal *tz)
+{
+ unsigned long long tmp;
+ acpi_status status;
+
+ if (crt > 0) {
+ tmp = celsius_to_deci_kelvin(crt);
+ goto set;
+ }
+ if (crt == -1) {
+ acpi_handle_debug(tz->device->handle, "Critical threshold disabled\n");
+ return THERMAL_TEMP_INVALID;
+ }
+
+ status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp);
+ if (ACPI_FAILURE(status)) {
+ acpi_handle_debug(tz->device->handle, "No critical threshold\n");
+ return THERMAL_TEMP_INVALID;
+ }
+ if (tmp <= 2732) {
+ /*
+ * Below zero (Celsius) values clearly aren't right for sure,
+ * so discard them as invalid.
+ */
+ pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp);
+ return THERMAL_TEMP_INVALID;
+ }
+
+set:
+ acpi_handle_debug(tz->device->handle, "Critical threshold [%llu]\n", tmp);
+ return tmp;
+}
+
+static long acpi_thermal_get_hot_trip(struct acpi_thermal *tz)
+{
+ unsigned long long tmp;
+ acpi_status status;
+
+ status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp);
+ if (ACPI_FAILURE(status)) {
+ acpi_handle_debug(tz->device->handle, "No hot threshold\n");
+ return THERMAL_TEMP_INVALID;
+ }
+
+ acpi_handle_debug(tz->device->handle, "Hot threshold [%llu]\n", tmp);
+ return tmp;
+}
+
+static bool passive_trip_params_init(struct acpi_thermal *tz)
+{
+ unsigned long long tmp;
+ acpi_status status;
+
+ status = acpi_evaluate_integer(tz->device->handle, "_TC1", NULL, &tmp);
+ if (ACPI_FAILURE(status))
+ return false;
+
+ tz->trips.passive.tc1 = tmp;
+
+ status = acpi_evaluate_integer(tz->device->handle, "_TC2", NULL, &tmp);
+ if (ACPI_FAILURE(status))
+ return false;
+
+ tz->trips.passive.tc2 = tmp;
+
+ status = acpi_evaluate_integer(tz->device->handle, "_TSP", NULL, &tmp);
+ if (ACPI_FAILURE(status))
+ return false;
+
+ tz->trips.passive.tsp = tmp;
+
+ return true;
+}
+
+static bool acpi_thermal_init_trip(struct acpi_thermal *tz, int index)
+{
+ struct acpi_thermal_trip *acpi_trip;
+ long temp;
+
+ if (index == ACPI_THERMAL_TRIP_PASSIVE) {
+ acpi_trip = &tz->trips.passive.trip;
+
+ if (psv == -1)
+ goto fail;
+
+ if (!passive_trip_params_init(tz))
+ goto fail;
+
+ temp = psv > 0 ? celsius_to_deci_kelvin(psv) :
+ get_passive_temp(tz);
+ } else {
+ acpi_trip = &tz->trips.active[index].trip;
+
+ if (act == -1)
+ goto fail;
+
+ temp = get_active_temp(tz, index);
+ }
+
+ if (temp == THERMAL_TEMP_INVALID)
+ goto fail;
+
+ if (!update_trip_devices(tz, acpi_trip, index, false))
+ goto fail;
+
+ acpi_trip->temp_dk = temp;
+ return true;
+
+fail:
+ acpi_trip->temp_dk = THERMAL_TEMP_INVALID;
+ return false;
+}
+
static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
{
- bool valid;
+ unsigned int count = 0;
int i;
- __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
-
- valid = tz->trips.critical.valid |
- tz->trips.hot.valid |
- tz->trips.passive.trip.valid;
+ if (acpi_thermal_init_trip(tz, ACPI_THERMAL_TRIP_PASSIVE))
+ count++;
- for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
- valid = valid || tz->trips.active[i].trip.valid;
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+ if (acpi_thermal_init_trip(tz, i))
+ count++;
+ else
+ break;
- if (!valid) {
- pr_warn(FW_BUG "No valid trip found\n");
- return -ENODEV;
}
- return 0;
+
+ while (++i < ACPI_THERMAL_MAX_ACTIVE)
+ tz->trips.active[i].trip.temp_dk = THERMAL_TEMP_INVALID;
+
+ return count;
}
/* sys I/F for generic thermal sysfs support */
@@ -486,7 +488,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
if (result)
return result;
- *temp = deci_kelvin_to_millicelsius_with_offset(tz->temperature,
+ *temp = deci_kelvin_to_millicelsius_with_offset(tz->temp_dk,
tz->kelvin_offset);
return 0;
}
@@ -503,15 +505,15 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
return -EINVAL;
acpi_trip = trip->priv;
- if (!acpi_trip || !acpi_trip->valid)
+ if (!acpi_trip || !acpi_thermal_trip_valid(acpi_trip))
return -EINVAL;
switch (trip->type) {
case THERMAL_TRIP_PASSIVE:
- t = tz->trips.passive.tc1 * (tz->temperature -
- tz->last_temperature) +
- tz->trips.passive.tc2 * (tz->temperature -
- acpi_trip->temperature);
+ t = tz->trips.passive.tc1 * (tz->temp_dk -
+ tz->last_temp_dk) +
+ tz->trips.passive.tc2 * (tz->temp_dk -
+ acpi_trip->temp_dk);
if (t > 0)
*trend = THERMAL_TREND_RAISING;
else if (t < 0)
@@ -522,7 +524,7 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
return 0;
case THERMAL_TRIP_ACTIVE:
- t = acpi_thermal_temp(tz, tz->temperature);
+ t = acpi_thermal_temp(tz, tz->temp_dk);
if (t <= trip->temperature)
break;
@@ -557,91 +559,72 @@ static void acpi_thermal_zone_device_critical(struct thermal_zone_device *therma
thermal_zone_device_critical(thermal);
}
-static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
- struct thermal_cooling_device *cdev,
- bool bind)
+struct acpi_thermal_bind_data {
+ struct thermal_zone_device *thermal;
+ struct thermal_cooling_device *cdev;
+ bool bind;
+};
+
+static int bind_unbind_cdev_cb(struct thermal_trip *trip, void *arg)
{
- struct acpi_device *device = cdev->devdata;
- struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
- struct acpi_device *dev;
- acpi_handle handle;
+ struct acpi_thermal_trip *acpi_trip = trip->priv;
+ struct acpi_thermal_bind_data *bd = arg;
+ struct thermal_zone_device *thermal = bd->thermal;
+ struct thermal_cooling_device *cdev = bd->cdev;
+ struct acpi_device *cdev_adev = cdev->devdata;
int i;
- int j;
- int trip = -1;
- int result = 0;
- if (tz->trips.critical.valid)
- trip++;
+ /* Skip critical and hot trips. */
+ if (!acpi_trip)
+ return 0;
- if (tz->trips.hot.valid)
- trip++;
+ for (i = 0; i < acpi_trip->devices.count; i++) {
+ acpi_handle handle = acpi_trip->devices.handles[i];
+ struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
- if (tz->trips.passive.trip.valid) {
- trip++;
- for (i = 0; i < tz->trips.passive.devices.count; i++) {
- handle = tz->trips.passive.devices.handles[i];
- dev = acpi_fetch_acpi_dev(handle);
- if (dev != device)
- continue;
-
- if (bind)
- result = thermal_zone_bind_cooling_device(
- thermal, trip, cdev,
- THERMAL_NO_LIMIT,
- THERMAL_NO_LIMIT,
- THERMAL_WEIGHT_DEFAULT);
- else
- result =
- thermal_zone_unbind_cooling_device(
- thermal, trip, cdev);
-
- if (result)
- goto failed;
- }
- }
+ if (adev != cdev_adev)
+ continue;
- for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
- if (!tz->trips.active[i].trip.valid)
- break;
+ if (bd->bind) {
+ int ret;
- trip++;
- for (j = 0; j < tz->trips.active[i].devices.count; j++) {
- handle = tz->trips.active[i].devices.handles[j];
- dev = acpi_fetch_acpi_dev(handle);
- if (dev != device)
- continue;
-
- if (bind)
- result = thermal_zone_bind_cooling_device(
- thermal, trip, cdev,
- THERMAL_NO_LIMIT,
- THERMAL_NO_LIMIT,
- THERMAL_WEIGHT_DEFAULT);
- else
- result = thermal_zone_unbind_cooling_device(
- thermal, trip, cdev);
-
- if (result)
- goto failed;
+ ret = thermal_bind_cdev_to_trip(thermal, trip, cdev,
+ THERMAL_NO_LIMIT,
+ THERMAL_NO_LIMIT,
+ THERMAL_WEIGHT_DEFAULT);
+ if (ret)
+ return ret;
+ } else {
+ thermal_unbind_cdev_from_trip(thermal, trip, cdev);
}
}
-failed:
- return result;
+ return 0;
+}
+
+static int acpi_thermal_bind_unbind_cdev(struct thermal_zone_device *thermal,
+ struct thermal_cooling_device *cdev,
+ bool bind)
+{
+ struct acpi_thermal_bind_data bd = {
+ .thermal = thermal, .cdev = cdev, .bind = bind
+ };
+
+ return for_each_thermal_trip(thermal, bind_unbind_cdev_cb, &bd);
}
static int
acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
struct thermal_cooling_device *cdev)
{
- return acpi_thermal_cooling_device_cb(thermal, cdev, true);
+ return acpi_thermal_bind_unbind_cdev(thermal, cdev, true);
}
static int
acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
struct thermal_cooling_device *cdev)
{
- return acpi_thermal_cooling_device_cb(thermal, cdev, false);
+ return acpi_thermal_bind_unbind_cdev(thermal, cdev, false);
}
static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
@@ -679,66 +662,11 @@ static void acpi_thermal_zone_sysfs_remove(struct acpi_thermal *tz)
sysfs_remove_link(&tzdev->kobj, "device");
}
-static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
+static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz,
+ unsigned int trip_count,
+ int passive_delay)
{
- struct acpi_thermal_trip *acpi_trip;
- struct thermal_trip *trip;
- int passive_delay = 0;
- int trip_count = 0;
int result;
- int i;
-
- if (tz->trips.critical.valid)
- trip_count++;
-
- if (tz->trips.hot.valid)
- trip_count++;
-
- if (tz->trips.passive.trip.valid) {
- trip_count++;
- passive_delay = tz->trips.passive.tsp * 100;
- }
-
- for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].trip.valid; i++)
- trip_count++;
-
- trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL);
- if (!trip)
- return -ENOMEM;
-
- tz->trip_table = trip;
-
- if (tz->trips.critical.valid) {
- trip->type = THERMAL_TRIP_CRITICAL;
- trip->temperature = acpi_thermal_temp(tz, tz->trips.critical.temperature);
- trip++;
- }
-
- if (tz->trips.hot.valid) {
- trip->type = THERMAL_TRIP_HOT;
- trip->temperature = acpi_thermal_temp(tz, tz->trips.hot.temperature);
- trip++;
- }
-
- acpi_trip = &tz->trips.passive.trip;
- if (acpi_trip->valid) {
- trip->type = THERMAL_TRIP_PASSIVE;
- trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature);
- trip->priv = acpi_trip;
- trip++;
- }
-
- for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
- acpi_trip = &tz->trips.active[i].trip;
-
- if (!acpi_trip->valid)
- break;
-
- trip->type = THERMAL_TRIP_ACTIVE;
- trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature);
- trip->priv = acpi_trip;
- trip++;
- }
tz->thermal_zone = thermal_zone_device_register_with_trips("acpitz",
tz->trip_table,
@@ -748,10 +676,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
NULL,
passive_delay,
tz->polling_frequency * 100);
- if (IS_ERR(tz->thermal_zone)) {
- result = PTR_ERR(tz->thermal_zone);
- goto free_trip_table;
- }
+ if (IS_ERR(tz->thermal_zone))
+ return PTR_ERR(tz->thermal_zone);
result = acpi_thermal_zone_sysfs_add(tz);
if (result)
@@ -770,17 +696,15 @@ remove_links:
acpi_thermal_zone_sysfs_remove(tz);
unregister_tzd:
thermal_zone_device_unregister(tz->thermal_zone);
-free_trip_table:
- kfree(tz->trip_table);
return result;
}
static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
{
+ thermal_zone_device_disable(tz->thermal_zone);
acpi_thermal_zone_sysfs_remove(tz);
thermal_zone_device_unregister(tz->thermal_zone);
- kfree(tz->trip_table);
tz->thermal_zone = NULL;
}
@@ -844,38 +768,6 @@ static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz)
acpi_evaluate_integer(handle, "_TMP", NULL, &value);
}
-static int acpi_thermal_get_info(struct acpi_thermal *tz)
-{
- int result;
-
- if (!tz)
- return -EINVAL;
-
- acpi_thermal_aml_dependency_fix(tz);
-
- /* Get trip points [_CRT, _PSV, etc.] (required) */
- result = acpi_thermal_get_trip_points(tz);
- if (result)
- return result;
-
- /* Get temperature [_TMP] (required) */
- result = acpi_thermal_get_temperature(tz);
- if (result)
- return result;
-
- /* Set the cooling mode [_SCP] to active cooling (default) */
- acpi_execute_simple_method(tz->device->handle, "_SCP",
- ACPI_THERMAL_MODE_ACTIVE);
-
- /* Get default polling frequency [_TZP] (optional) */
- if (tzp)
- tz->polling_frequency = tzp;
- else
- acpi_thermal_get_polling_frequency(tz);
-
- return 0;
-}
-
/*
* The exact offset between Kelvin and degree Celsius is 273.15. However ACPI
* handles temperature values with a single decimal place. As a consequence,
@@ -886,10 +778,9 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
* The heuristic below should work for all ACPI thermal zones which have a
* critical trip point with a value being a multiple of 0.5 degree Celsius.
*/
-static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
+static void acpi_thermal_guess_offset(struct acpi_thermal *tz, long crit_temp)
{
- if (tz->trips.critical.valid &&
- (tz->trips.critical.temperature % 5) == 1)
+ if (crit_temp != THERMAL_TEMP_INVALID && crit_temp % 5 == 1)
tz->kelvin_offset = 273100;
else
tz->kelvin_offset = 273200;
@@ -920,10 +811,27 @@ static void acpi_thermal_check_fn(struct work_struct *work)
mutex_unlock(&tz->thermal_check_lock);
}
+static void acpi_thermal_free_thermal_zone(struct acpi_thermal *tz)
+{
+ int i;
+
+ acpi_handle_list_free(&tz->trips.passive.trip.devices);
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
+ acpi_handle_list_free(&tz->trips.active[i].trip.devices);
+
+ kfree(tz);
+}
+
static int acpi_thermal_add(struct acpi_device *device)
{
+ struct acpi_thermal_trip *acpi_trip;
+ struct thermal_trip *trip;
struct acpi_thermal *tz;
+ unsigned int trip_count;
+ int crit_temp, hot_temp;
+ int passive_delay = 0;
int result;
+ int i;
if (!device)
return -EINVAL;
@@ -938,25 +846,97 @@ static int acpi_thermal_add(struct acpi_device *device)
strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
device->driver_data = tz;
- result = acpi_thermal_get_info(tz);
+ acpi_thermal_aml_dependency_fix(tz);
+
+ /* Get trip points [_CRT, _PSV, etc.] (required). */
+ trip_count = acpi_thermal_get_trip_points(tz);
+
+ crit_temp = acpi_thermal_get_critical_trip(tz);
+ if (crit_temp != THERMAL_TEMP_INVALID)
+ trip_count++;
+
+ hot_temp = acpi_thermal_get_hot_trip(tz);
+ if (hot_temp != THERMAL_TEMP_INVALID)
+ trip_count++;
+
+ if (!trip_count) {
+ pr_warn(FW_BUG "No valid trip points!\n");
+ result = -ENODEV;
+ goto free_memory;
+ }
+
+ /* Get temperature [_TMP] (required). */
+ result = acpi_thermal_get_temperature(tz);
if (result)
goto free_memory;
- acpi_thermal_guess_offset(tz);
+ /* Set the cooling mode [_SCP] to active cooling. */
+ acpi_execute_simple_method(tz->device->handle, "_SCP",
+ ACPI_THERMAL_MODE_ACTIVE);
- result = acpi_thermal_register_thermal_zone(tz);
- if (result)
+ /* Determine the default polling frequency [_TZP]. */
+ if (tzp)
+ tz->polling_frequency = tzp;
+ else
+ acpi_thermal_get_polling_frequency(tz);
+
+ acpi_thermal_guess_offset(tz, crit_temp);
+
+ trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL);
+ if (!trip) {
+ result = -ENOMEM;
goto free_memory;
+ }
+
+ tz->trip_table = trip;
+
+ if (crit_temp != THERMAL_TEMP_INVALID) {
+ trip->type = THERMAL_TRIP_CRITICAL;
+ trip->temperature = acpi_thermal_temp(tz, crit_temp);
+ trip++;
+ }
+
+ if (hot_temp != THERMAL_TEMP_INVALID) {
+ trip->type = THERMAL_TRIP_HOT;
+ trip->temperature = acpi_thermal_temp(tz, hot_temp);
+ trip++;
+ }
+
+ acpi_trip = &tz->trips.passive.trip;
+ if (acpi_thermal_trip_valid(acpi_trip)) {
+ passive_delay = tz->trips.passive.tsp * 100;
+
+ trip->type = THERMAL_TRIP_PASSIVE;
+ trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk);
+ trip->priv = acpi_trip;
+ trip++;
+ }
+
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+ acpi_trip = &tz->trips.active[i].trip;
+
+ if (!acpi_thermal_trip_valid(acpi_trip))
+ break;
+
+ trip->type = THERMAL_TRIP_ACTIVE;
+ trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk);
+ trip->priv = acpi_trip;
+ trip++;
+ }
+
+ result = acpi_thermal_register_thermal_zone(tz, trip_count, passive_delay);
+ if (result)
+ goto free_trips;
refcount_set(&tz->thermal_check_count, 3);
mutex_init(&tz->thermal_check_lock);
INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn);
pr_info("%s [%s] (%ld C)\n", acpi_device_name(device),
- acpi_device_bid(device), deci_kelvin_to_celsius(tz->temperature));
+ acpi_device_bid(device), deci_kelvin_to_celsius(tz->temp_dk));
result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
- acpi_thermal_notify);
+ acpi_thermal_notify, device);
if (result)
goto flush_wq;
@@ -965,8 +945,10 @@ static int acpi_thermal_add(struct acpi_device *device)
flush_wq:
flush_workqueue(acpi_thermal_pm_queue);
acpi_thermal_unregister_thermal_zone(tz);
+free_trips:
+ kfree(tz->trip_table);
free_memory:
- kfree(tz);
+ acpi_thermal_free_thermal_zone(tz);
return result;
}
@@ -985,8 +967,8 @@ static void acpi_thermal_remove(struct acpi_device *device)
flush_workqueue(acpi_thermal_pm_queue);
acpi_thermal_unregister_thermal_zone(tz);
-
- kfree(tz);
+ kfree(tz->trip_table);
+ acpi_thermal_free_thermal_zone(tz);
}
#ifdef CONFIG_PM_SLEEP
@@ -1010,11 +992,13 @@ static int acpi_thermal_resume(struct device *dev)
return -EINVAL;
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
- if (!tz->trips.active[i].trip.valid)
+ struct acpi_thermal_trip *acpi_trip = &tz->trips.active[i].trip;
+
+ if (!acpi_thermal_trip_valid(acpi_trip))
break;
- for (j = 0; j < tz->trips.active[i].devices.count; j++) {
- acpi_bus_update_power(tz->trips.active[i].devices.handles[j],
+ for (j = 0; j < acpi_trip->devices.count; j++) {
+ acpi_bus_update_power(acpi_trip->devices.handles[j],
&power_state);
}
}
@@ -1046,7 +1030,8 @@ static struct acpi_driver acpi_thermal_driver = {
.drv.pm = &acpi_thermal_pm,
};
-static int thermal_act(const struct dmi_system_id *d) {
+static int thermal_act(const struct dmi_system_id *d)
+{
if (act == 0) {
pr_notice("%s detected: disabling all active thermal trip points\n",
d->ident);
@@ -1054,13 +1039,17 @@ static int thermal_act(const struct dmi_system_id *d) {
}
return 0;
}
-static int thermal_nocrt(const struct dmi_system_id *d) {
+
+static int thermal_nocrt(const struct dmi_system_id *d)
+{
pr_notice("%s detected: disabling all critical thermal trip point actions.\n",
d->ident);
crt = -1;
return 0;
}
-static int thermal_tzp(const struct dmi_system_id *d) {
+
+static int thermal_tzp(const struct dmi_system_id *d)
+{
if (tzp == 0) {
pr_notice("%s detected: enabling thermal zone polling\n",
d->ident);
@@ -1068,7 +1057,9 @@ static int thermal_tzp(const struct dmi_system_id *d) {
}
return 0;
}
-static int thermal_psv(const struct dmi_system_id *d) {
+
+static int thermal_psv(const struct dmi_system_id *d)
+{
if (psv == 0) {
pr_notice("%s detected: disabling all passive thermal trip points\n",
d->ident);
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 2ea14648a661..62944e35fcee 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -342,9 +342,8 @@ acpi_evaluate_reference(acpi_handle handle,
u32 i = 0;
- if (!list) {
+ if (!list)
return AE_BAD_PARAMETER;
- }
/* Evaluate object. */
@@ -370,7 +369,8 @@ acpi_evaluate_reference(acpi_handle handle,
goto end;
}
- if (package->package.count > ACPI_MAX_HANDLES) {
+ list->handles = kcalloc(package->package.count, sizeof(*list->handles), GFP_KERNEL);
+ if (!list->handles) {
kfree(package);
return AE_NO_MEMORY;
}
@@ -399,12 +399,13 @@ acpi_evaluate_reference(acpi_handle handle,
acpi_handle_debug(list->handles[i], "Found in reference list\n");
}
- end:
if (ACPI_FAILURE(status)) {
list->count = 0;
- //kfree(list->handles);
+ kfree(list->handles);
+ list->handles = NULL;
}
+end:
kfree(buffer.pointer);
return status;
@@ -412,6 +413,61 @@ acpi_evaluate_reference(acpi_handle handle,
EXPORT_SYMBOL(acpi_evaluate_reference);
+/**
+ * acpi_handle_list_equal - Check if two ACPI handle lists are the same
+ * @list1: First list to compare.
+ * @list2: Second list to compare.
+ *
+ * Return true if the given ACPI handle lists are of the same size and
+ * contain the same ACPI handles in the same order. Otherwise, return false.
+ */
+bool acpi_handle_list_equal(struct acpi_handle_list *list1,
+ struct acpi_handle_list *list2)
+{
+ return list1->count == list2->count &&
+ !memcmp(list1->handles, list2->handles,
+ list1->count * sizeof(acpi_handle));
+}
+EXPORT_SYMBOL_GPL(acpi_handle_list_equal);
+
+/**
+ * acpi_handle_list_replace - Replace one ACPI handle list with another
+ * @dst: ACPI handle list to replace.
+ * @src: Source ACPI handle list.
+ *
+ * Free the handles table in @dst, move the handles table from @src to @dst,
+ * copy count from @src to @dst and clear @src.
+ */
+void acpi_handle_list_replace(struct acpi_handle_list *dst,
+ struct acpi_handle_list *src)
+{
+ if (dst->count)
+ kfree(dst->handles);
+
+ dst->count = src->count;
+ dst->handles = src->handles;
+
+ src->handles = NULL;
+ src->count = 0;
+}
+EXPORT_SYMBOL_GPL(acpi_handle_list_replace);
+
+/**
+ * acpi_handle_list_free - Free the handles table in an ACPI handle list
+ * @list: ACPI handle list to free.
+ *
+ * Free the handles table in @list and clear its count field.
+ */
+void acpi_handle_list_free(struct acpi_handle_list *list)
+{
+ if (!list->count)
+ return;
+
+ kfree(list->handles);
+ list->count = 0;
+}
+EXPORT_SYMBOL_GPL(acpi_handle_list_free);
+
acpi_status
acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld)
{
@@ -523,7 +579,7 @@ acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...)
vaf.va = &args;
path = acpi_handle_path(handle);
- printk("%sACPI: %s: %pV", level, path ? path : "<n/a>" , &vaf);
+ printk("%sACPI: %s: %pV", level, path ? path : "<n/a>", &vaf);
va_end(args);
kfree(path);
@@ -769,19 +825,42 @@ bool acpi_check_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 funcs)
EXPORT_SYMBOL(acpi_check_dsm);
/**
+ * acpi_dev_uid_match - Match device by supplied UID
+ * @adev: ACPI device to match.
+ * @uid2: Unique ID of the device.
+ *
+ * Matches UID in @adev with given @uid2.
+ *
+ * Returns:
+ * - %true if matches.
+ * - %false otherwise.
+ */
+bool acpi_dev_uid_match(struct acpi_device *adev, const char *uid2)
+{
+ const char *uid1 = acpi_device_uid(adev);
+
+ return uid1 && uid2 && !strcmp(uid1, uid2);
+}
+EXPORT_SYMBOL_GPL(acpi_dev_uid_match);
+
+/**
* acpi_dev_hid_uid_match - Match device by supplied HID and UID
* @adev: ACPI device to match.
* @hid2: Hardware ID of the device.
* @uid2: Unique ID of the device, pass NULL to not check _UID.
*
- * Matches HID and UID in @adev with given @hid2 and @uid2.
- * Returns true if matches.
+ * Matches HID and UID in @adev with given @hid2 and @uid2. Absence of @uid2
+ * will be treated as a match. If user wants to validate @uid2, it should be
+ * done before calling this function.
+ *
+ * Returns:
+ * - %true if matches or @uid2 is NULL.
+ * - %false otherwise.
*/
bool acpi_dev_hid_uid_match(struct acpi_device *adev,
const char *hid2, const char *uid2)
{
const char *hid1 = acpi_device_hid(adev);
- const char *uid1 = acpi_device_uid(adev);
if (strcmp(hid1, hid2))
return false;
@@ -789,7 +868,7 @@ bool acpi_dev_hid_uid_match(struct acpi_device *adev,
if (!uid2)
return true;
- return uid1 && !strcmp(uid1, uid2);
+ return acpi_dev_uid_match(adev, uid2);
}
EXPORT_SYMBOL(acpi_dev_hid_uid_match);
@@ -863,8 +942,7 @@ static int acpi_dev_match_cb(struct device *dev, const void *data)
if (acpi_match_device_ids(adev, match->hid))
return 0;
- if (match->uid && (!adev->pnp.unique_id ||
- strcmp(adev->pnp.unique_id, match->uid)))
+ if (match->uid && !acpi_dev_uid_match(adev, match->uid))
return 0;
if (match->hrv == -1)
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 442396f6ed1f..9fdcc620c652 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -130,6 +130,16 @@ static int video_detect_force_native(const struct dmi_system_id *d)
return 0;
}
+static int video_detect_portege_r100(const struct dmi_system_id *d)
+{
+ struct pci_dev *dev;
+ /* Search for Trident CyberBlade XP4m32 to confirm Portégé R100 */
+ dev = pci_get_device(PCI_VENDOR_ID_TRIDENT, 0x2100, NULL);
+ if (dev)
+ acpi_backlight_dmi = acpi_backlight_vendor;
+ return 0;
+}
+
static const struct dmi_system_id video_detect_dmi_table[] = {
/*
* Models which should use the vendor backlight interface,
@@ -229,14 +239,6 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
},
},
- {
- .callback = video_detect_force_vendor,
- /* Xiaomi Mi Pad 2 */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
- },
- },
/*
* Models which should use the vendor backlight interface,
@@ -271,6 +273,22 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
/*
+ * Toshiba Portégé R100 has working both acpi_video and toshiba_acpi
+ * vendor driver. But none of them gets activated as it has a VGA with
+ * no kernel driver (Trident CyberBlade XP4m32).
+ * The DMI strings are generic so check for the VGA chip in callback.
+ */
+ {
+ .callback = video_detect_portege_r100,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"),
+ DMI_MATCH(DMI_BOARD_NAME, "Portable PC")
+ },
+ },
+
+ /*
* Models which need acpi_video backlight control where the GPU drivers
* do not call acpi_video_register_backlight() because no internal panel
* is detected. Typically these are all-in-ones (monitors with builtin
@@ -799,6 +817,56 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 15 3535"),
},
},
+
+ /*
+ * x86 android tablets which directly control the backlight through
+ * an external backlight controller, typically TI's LP8557.
+ * The backlight is directly controlled by the lp855x driver on these.
+ * This setup means that neither i915's native nor acpi_video backlight
+ * control works. Add a "vendor" quirk to disable both. Note these
+ * devices do not use vendor control in the typical meaning of
+ * vendor specific SMBIOS or ACPI calls being used.
+ */
+ {
+ .callback = video_detect_force_vendor,
+ /* Lenovo Yoga Book X90F / X90L */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+ },
+ },
+ {
+ .callback = video_detect_force_vendor,
+ /*
+ * Lenovo Yoga Tablet 2 830F/L or 1050F/L (The 8" and 10"
+ * Lenovo Yoga Tablet 2 use the same mainboard)
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
+ DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
+ /* Partial match on beginning of BIOS version */
+ DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
+ },
+ },
+ {
+ .callback = video_detect_force_vendor,
+ /* Lenovo Yoga Tab 3 Pro YT3-X90F */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
+ },
+ },
+ {
+ .callback = video_detect_force_vendor,
+ /* Xiaomi Mi Pad 2 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
+ },
+ },
{ },
};
diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
index 08f7c6708206..7d64e655f1b8 100644
--- a/drivers/acpi/x86/s2idle.c
+++ b/drivers/acpi/x86/s2idle.c
@@ -417,11 +417,10 @@ static int validate_dsm(acpi_handle handle, const char *uuid, int rev, guid_t *d
int ret = -EINVAL;
guid_parse(uuid, dsm_guid);
- obj = acpi_evaluate_dsm(handle, dsm_guid, rev, 0, NULL);
/* Check if the _DSM is present and as expected. */
- if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length == 0 ||
- obj->buffer.length > sizeof(u32)) {
+ obj = acpi_evaluate_dsm_typed(handle, dsm_guid, rev, 0, NULL, ACPI_TYPE_BUFFER);
+ if (!obj || obj->buffer.length == 0 || obj->buffer.length > sizeof(u32)) {
acpi_handle_debug(handle,
"_DSM UUID %s rev %d function 0 evaluation failed\n", uuid, rev);
goto out;
diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
index 63d834dd3811..bc65ebfcdf76 100644
--- a/drivers/acpi/x86/utils.c
+++ b/drivers/acpi/x86/utils.c
@@ -184,8 +184,7 @@ bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *s
if (acpi_match_device_ids(adev, override_status_ids[i].hid))
continue;
- if (!adev->pnp.unique_id ||
- strcmp(adev->pnp.unique_id, override_status_ids[i].uid))
+ if (!acpi_dev_uid_match(adev, override_status_ids[i].uid))
continue;
}
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 09e72967b8ab..a24c152bfaac 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -18,6 +18,7 @@
#include <linux/limits.h>
#include <linux/clk/clk-conf.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/reset.h>
#include <linux/of_irq.h>
#include <linux/of_device.h>
@@ -528,7 +529,7 @@ static void amba_device_release(struct device *dev)
{
struct amba_device *d = to_amba_device(dev);
- of_node_put(d->dev.of_node);
+ fwnode_handle_put(dev_fwnode(&d->dev));
if (d->res.parent)
release_resource(&d->res);
mutex_destroy(&d->periphid_lock);
@@ -548,6 +549,8 @@ int amba_device_add(struct amba_device *dev, struct resource *parent)
{
int ret;
+ fwnode_handle_get(dev_fwnode(&dev->dev));
+
ret = request_resource(parent, &dev->res);
if (ret)
return ret;
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 367afac5f1bf..92128aae2d06 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -4812,6 +4812,8 @@ static void binder_release_work(struct binder_proc *proc,
"undelivered TRANSACTION_ERROR: %u\n",
e->cmd);
} break;
+ case BINDER_WORK_TRANSACTION_PENDING:
+ case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT:
case BINDER_WORK_TRANSACTION_COMPLETE: {
binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
"undelivered TRANSACTION_COMPLETE\n");
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index e3db8297095a..138f6d43d13b 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -1053,11 +1053,7 @@ binder_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
NULL, sc->nr_to_scan);
}
-static struct shrinker binder_shrinker = {
- .count_objects = binder_shrink_count,
- .scan_objects = binder_shrink_scan,
- .seeks = DEFAULT_SEEKS,
-};
+static struct shrinker *binder_shrinker;
/**
* binder_alloc_init() - called by binder_open() for per-proc initialization
@@ -1077,19 +1073,29 @@ void binder_alloc_init(struct binder_alloc *alloc)
int binder_alloc_shrinker_init(void)
{
- int ret = list_lru_init(&binder_alloc_lru);
+ int ret;
- if (ret == 0) {
- ret = register_shrinker(&binder_shrinker, "android-binder");
- if (ret)
- list_lru_destroy(&binder_alloc_lru);
+ ret = list_lru_init(&binder_alloc_lru);
+ if (ret)
+ return ret;
+
+ binder_shrinker = shrinker_alloc(0, "android-binder");
+ if (!binder_shrinker) {
+ list_lru_destroy(&binder_alloc_lru);
+ return -ENOMEM;
}
- return ret;
+
+ binder_shrinker->count_objects = binder_shrink_count;
+ binder_shrinker->scan_objects = binder_shrink_scan;
+
+ shrinker_register(binder_shrinker);
+
+ return 0;
}
void binder_alloc_shrinker_exit(void)
{
- unregister_shrinker(&binder_shrinker);
+ shrinker_free(binder_shrinker);
list_lru_destroy(&binder_alloc_lru);
}
diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c
index 81effec17b3d..1224ab7aa070 100644
--- a/drivers/android/binderfs.c
+++ b/drivers/android/binderfs.c
@@ -93,7 +93,7 @@ bool is_binderfs_device(const struct inode *inode)
/**
* binderfs_binder_device_create - allocate inode from super block of a
* binderfs mount
- * @ref_inode: inode from wich the super block will be taken
+ * @ref_inode: inode from which the super block will be taken
* @userp: buffer to copy information about new device for userspace to
* @req: struct binderfs_device as copied from userspace
*
@@ -152,7 +152,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
goto err;
inode->i_ino = minor + INODE_OFFSET;
- inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode);
+ simple_inode_init_ts(inode);
init_special_inode(inode, S_IFCHR | 0600,
MKDEV(MAJOR(binderfs_dev), minor));
inode->i_fop = &binder_fops;
@@ -431,7 +431,7 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
}
inode->i_ino = SECOND_INODE;
- inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode);
+ simple_inode_init_ts(inode);
init_special_inode(inode, S_IFCHR | 0600,
MKDEV(MAJOR(binderfs_dev), minor));
inode->i_fop = &binder_ctl_fops;
@@ -473,7 +473,7 @@ static struct inode *binderfs_make_inode(struct super_block *sb, int mode)
if (ret) {
ret->i_ino = iunique(sb, BINDERFS_MAX_MINOR + INODE_OFFSET);
ret->i_mode = mode;
- ret->i_atime = ret->i_mtime = inode_set_ctime_current(ret);
+ simple_inode_init_ts(ret);
}
return ret;
}
@@ -702,7 +702,7 @@ static int binderfs_fill_super(struct super_block *sb, struct fs_context *fc)
inode->i_ino = FIRST_INODE;
inode->i_fop = &simple_dir_operations;
inode->i_mode = S_IFDIR | 0755;
- inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode);
+ simple_inode_init_ts(inode);
inode->i_op = &binderfs_dir_inode_operations;
set_nlink(inode, 2);
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 08745e7db820..3a5f3255f51b 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -423,6 +423,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x02d7), board_ahci_low_power }, /* Comet Lake PCH RAID */
/* Elkhart Lake IDs 0x4b60 & 0x4b62 https://sata-io.org/product/8803 not tested yet */
{ PCI_VDEVICE(INTEL, 0x4b63), board_ahci_low_power }, /* Elkhart Lake AHCI */
+ { PCI_VDEVICE(INTEL, 0x7ae2), board_ahci_low_power }, /* Alder Lake-P AHCI */
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -604,6 +605,11 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */
{ PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */
{ PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci }, /* ASM1062+JMB575 */
+ { PCI_VDEVICE(ASMEDIA, 0x1062), board_ahci }, /* ASM1062A */
+ { PCI_VDEVICE(ASMEDIA, 0x1064), board_ahci }, /* ASM1064 */
+ { PCI_VDEVICE(ASMEDIA, 0x1164), board_ahci }, /* ASM1164 */
+ { PCI_VDEVICE(ASMEDIA, 0x1165), board_ahci }, /* ASM1165 */
+ { PCI_VDEVICE(ASMEDIA, 0x1166), board_ahci }, /* ASM1166 */
/*
* Samsung SSDs found on some macbooks. NCQ times out if MSI is
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 9fa005965f3b..cb768f66f0a7 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -9,10 +9,11 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/ahci_platform.h>
#include <linux/gpio/consumer.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <linux/libata.h>
@@ -1050,16 +1051,11 @@ static int imx8_sata_probe(struct device *dev, struct imx_ahci_priv *imxpriv)
static int imx_ahci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- const struct of_device_id *of_id;
struct ahci_host_priv *hpriv;
struct imx_ahci_priv *imxpriv;
unsigned int reg_val;
int ret;
- of_id = of_match_device(imx_ahci_of_match, dev);
- if (!of_id)
- return -EINVAL;
-
imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL);
if (!imxpriv)
return -ENOMEM;
@@ -1067,7 +1063,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
imxpriv->ahci_pdev = pdev;
imxpriv->no_device = false;
imxpriv->first_time = true;
- imxpriv->type = (unsigned long)of_id->data;
+ imxpriv->type = (enum ahci_imx_type)device_get_match_data(dev);
imxpriv->sata_clk = devm_clk_get(dev, "sata");
if (IS_ERR(imxpriv->sata_clk)) {
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index ccef5e63bdf9..81a1d838c0fc 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -13,9 +13,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/ahci_platform.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_irq.h>
+#include <linux/of.h>
#include <linux/phy/phy.h>
#include "ahci.h"
@@ -735,7 +733,6 @@ static int xgene_ahci_probe(struct platform_device *pdev)
struct ahci_host_priv *hpriv;
struct xgene_ahci_context *ctx;
struct resource *res;
- const struct of_device_id *of_devid;
enum xgene_ahci_version version = XGENE_AHCI_V1;
const struct ata_port_info *ppi[] = { &xgene_ahci_v1_port_info,
&xgene_ahci_v2_port_info };
@@ -778,10 +775,8 @@ static int xgene_ahci_probe(struct platform_device *pdev)
ctx->csr_mux = csr;
}
- of_devid = of_match_device(xgene_ahci_of_match, dev);
- if (of_devid) {
- if (of_devid->data)
- version = (unsigned long) of_devid->data;
+ if (dev->of_node) {
+ version = (enum xgene_ahci_version)of_device_get_match_data(dev);
}
#ifdef CONFIG_ACPI
else {
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index f1263364fa97..1a63200ea437 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -2730,7 +2730,7 @@ static int ahci_host_activate_multi_irqs(struct ata_host *host,
if (rc)
return rc;
- ata_port_desc(host->ports[i], "irq %d", irq);
+ ata_port_desc_misc(host->ports[i], irq);
}
return ata_host_register(host, sht);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index d8cc1e27a125..09ed67772fae 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1972,6 +1972,35 @@ retry:
return rc;
}
+bool ata_dev_power_init_tf(struct ata_device *dev, struct ata_taskfile *tf,
+ bool set_active)
+{
+ /* Only applies to ATA and ZAC devices */
+ if (dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC)
+ return false;
+
+ ata_tf_init(dev, tf);
+ tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
+ tf->protocol = ATA_PROT_NODATA;
+
+ if (set_active) {
+ /* VERIFY for 1 sector at lba=0 */
+ tf->command = ATA_CMD_VERIFY;
+ tf->nsect = 1;
+ if (dev->flags & ATA_DFLAG_LBA) {
+ tf->flags |= ATA_TFLAG_LBA;
+ tf->device |= ATA_LBA;
+ } else {
+ /* CHS */
+ tf->lbal = 0x1; /* sect */
+ }
+ } else {
+ tf->command = ATA_CMD_STANDBYNOW1;
+ }
+
+ return true;
+}
+
/**
* ata_dev_power_set_standby - Set a device power mode to standby
* @dev: target device
@@ -1988,10 +2017,6 @@ void ata_dev_power_set_standby(struct ata_device *dev)
struct ata_taskfile tf;
unsigned int err_mask;
- /* Issue STANDBY IMMEDIATE command only if supported by the device */
- if (dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC)
- return;
-
/*
* Some odd clown BIOSes issue spindown on power off (ACPI S4 or S5)
* causing some drives to spin up and down again. For these, do nothing
@@ -2005,10 +2030,9 @@ void ata_dev_power_set_standby(struct ata_device *dev)
system_entering_hibernation())
return;
- ata_tf_init(dev, &tf);
- tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
- tf.protocol = ATA_PROT_NODATA;
- tf.command = ATA_CMD_STANDBYNOW1;
+ /* Issue STANDBY IMMEDIATE command only if supported by the device */
+ if (!ata_dev_power_init_tf(dev, &tf, false))
+ return;
ata_dev_notice(dev, "Entering standby power mode\n");
@@ -2018,6 +2042,33 @@ void ata_dev_power_set_standby(struct ata_device *dev)
err_mask);
}
+static bool ata_dev_power_is_active(struct ata_device *dev)
+{
+ struct ata_taskfile tf;
+ unsigned int err_mask;
+
+ ata_tf_init(dev, &tf);
+ tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
+ tf.protocol = ATA_PROT_NODATA;
+ tf.command = ATA_CMD_CHK_POWER;
+
+ err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
+ if (err_mask) {
+ ata_dev_err(dev, "Check power mode failed (err_mask=0x%x)\n",
+ err_mask);
+ /*
+ * Assume we are in standby mode so that we always force a
+ * spinup in ata_dev_power_set_active().
+ */
+ return false;
+ }
+
+ ata_dev_dbg(dev, "Power mode: 0x%02x\n", tf.nsect);
+
+ /* Active or idle */
+ return tf.nsect == 0xff;
+}
+
/**
* ata_dev_power_set_active - Set a device power mode to active
* @dev: target device
@@ -2038,21 +2089,15 @@ void ata_dev_power_set_active(struct ata_device *dev)
* Issue READ VERIFY SECTORS command for 1 sector at lba=0 only
* if supported by the device.
*/
- if (dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC)
+ if (!ata_dev_power_init_tf(dev, &tf, true))
return;
- ata_tf_init(dev, &tf);
- tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
- tf.protocol = ATA_PROT_NODATA;
- tf.command = ATA_CMD_VERIFY;
- tf.nsect = 1;
- if (dev->flags & ATA_DFLAG_LBA) {
- tf.flags |= ATA_TFLAG_LBA;
- tf.device |= ATA_LBA;
- } else {
- /* CHS */
- tf.lbal = 0x1; /* sect */
- }
+ /*
+ * Check the device power state & condition and force a spinup with
+ * VERIFY command only if the drive is not already ACTIVE or IDLE.
+ */
+ if (ata_dev_power_is_active(dev))
+ return;
ata_dev_notice(dev, "Entering active power mode\n");
@@ -5155,18 +5200,8 @@ static void ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
ata_port_wait_eh(ap);
}
-/*
- * On some hardware, device fails to respond after spun down for suspend. As
- * the device won't be used before being resumed, we don't need to touch the
- * device. Ask EH to skip the usual stuff and proceed directly to suspend.
- *
- * http://thread.gmane.org/gmane.linux.ide/46764
- */
-static const unsigned int ata_port_suspend_ehi = ATA_EHI_QUIET
- | ATA_EHI_NO_AUTOPSY
- | ATA_EHI_NO_RECOVERY;
-
-static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg)
+static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg,
+ bool async)
{
/*
* We are about to suspend the port, so we do not care about
@@ -5176,20 +5211,18 @@ static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg)
*/
cancel_delayed_work_sync(&ap->scsi_rescan_task);
- ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, false);
-}
-
-static void ata_port_suspend_async(struct ata_port *ap, pm_message_t mesg)
-{
/*
- * We are about to suspend the port, so we do not care about
- * scsi_rescan_device() calls scheduled by previous resume operations.
- * The next resume will schedule the rescan again. So cancel any rescan
- * that is not done yet.
+ * On some hardware, device fails to respond after spun down for
+ * suspend. As the device will not be used until being resumed, we
+ * do not need to touch the device. Ask EH to skip the usual stuff
+ * and proceed directly to suspend.
+ *
+ * http://thread.gmane.org/gmane.linux.ide/46764
*/
- cancel_delayed_work_sync(&ap->scsi_rescan_task);
-
- ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, true);
+ ata_port_request_pm(ap, mesg, 0,
+ ATA_EHI_QUIET | ATA_EHI_NO_AUTOPSY |
+ ATA_EHI_NO_RECOVERY,
+ async);
}
static int ata_port_pm_suspend(struct device *dev)
@@ -5199,7 +5232,7 @@ static int ata_port_pm_suspend(struct device *dev)
if (pm_runtime_suspended(dev))
return 0;
- ata_port_suspend(ap, PMSG_SUSPEND);
+ ata_port_suspend(ap, PMSG_SUSPEND, false);
return 0;
}
@@ -5210,35 +5243,29 @@ static int ata_port_pm_freeze(struct device *dev)
if (pm_runtime_suspended(dev))
return 0;
- ata_port_suspend(ap, PMSG_FREEZE);
+ ata_port_suspend(ap, PMSG_FREEZE, false);
return 0;
}
static int ata_port_pm_poweroff(struct device *dev)
{
- ata_port_suspend(to_ata_port(dev), PMSG_HIBERNATE);
+ if (!pm_runtime_suspended(dev))
+ ata_port_suspend(to_ata_port(dev), PMSG_HIBERNATE, false);
return 0;
}
-static const unsigned int ata_port_resume_ehi = ATA_EHI_NO_AUTOPSY
- | ATA_EHI_QUIET;
-
-static void ata_port_resume(struct ata_port *ap, pm_message_t mesg)
-{
- ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, false);
-}
-
-static void ata_port_resume_async(struct ata_port *ap, pm_message_t mesg)
+static void ata_port_resume(struct ata_port *ap, pm_message_t mesg,
+ bool async)
{
- ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, true);
+ ata_port_request_pm(ap, mesg, ATA_EH_RESET,
+ ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET,
+ async);
}
static int ata_port_pm_resume(struct device *dev)
{
- ata_port_resume_async(to_ata_port(dev), PMSG_RESUME);
- pm_runtime_disable(dev);
- pm_runtime_set_active(dev);
- pm_runtime_enable(dev);
+ if (!pm_runtime_suspended(dev))
+ ata_port_resume(to_ata_port(dev), PMSG_RESUME, true);
return 0;
}
@@ -5268,13 +5295,13 @@ static int ata_port_runtime_idle(struct device *dev)
static int ata_port_runtime_suspend(struct device *dev)
{
- ata_port_suspend(to_ata_port(dev), PMSG_AUTO_SUSPEND);
+ ata_port_suspend(to_ata_port(dev), PMSG_AUTO_SUSPEND, false);
return 0;
}
static int ata_port_runtime_resume(struct device *dev)
{
- ata_port_resume(to_ata_port(dev), PMSG_AUTO_RESUME);
+ ata_port_resume(to_ata_port(dev), PMSG_AUTO_RESUME, false);
return 0;
}
@@ -5298,13 +5325,13 @@ static const struct dev_pm_ops ata_port_pm_ops = {
*/
void ata_sas_port_suspend(struct ata_port *ap)
{
- ata_port_suspend_async(ap, PMSG_SUSPEND);
+ ata_port_suspend(ap, PMSG_SUSPEND, true);
}
EXPORT_SYMBOL_GPL(ata_sas_port_suspend);
void ata_sas_port_resume(struct ata_port *ap)
{
- ata_port_resume_async(ap, PMSG_RESUME);
+ ata_port_resume(ap, PMSG_RESUME, true);
}
EXPORT_SYMBOL_GPL(ata_sas_port_resume);
@@ -6026,7 +6053,7 @@ int ata_host_activate(struct ata_host *host, int irq,
return rc;
for (i = 0; i < host->n_ports; i++)
- ata_port_desc(host->ports[i], "irq %d", irq);
+ ata_port_desc_misc(host->ports[i], irq);
rc = ata_host_register(host, sht);
/* if failed, just free the IRQ and leave ports alone */
@@ -6054,6 +6081,9 @@ static void ata_port_detach(struct ata_port *ap)
struct ata_link *link;
struct ata_device *dev;
+ /* Ensure ata_port probe has completed */
+ async_synchronize_cookie(ap->cookie + 1);
+
/* Wait for any ongoing EH */
ata_port_wait_eh(ap);
@@ -6118,11 +6148,8 @@ void ata_host_detach(struct ata_host *host)
{
int i;
- for (i = 0; i < host->n_ports; i++) {
- /* Ensure ata_port probe has completed */
- async_synchronize_cookie(host->ports[i]->cookie + 1);
+ for (i = 0; i < host->n_ports; i++)
ata_port_detach(host->ports[i]);
- }
/* the host is dead now, dissociate ACPI */
ata_acpi_dissociate(host);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 5686353e442c..b0d6e69c4a5b 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -494,6 +494,18 @@ void ata_eh_release(struct ata_port *ap)
mutex_unlock(&ap->host->eh_mutex);
}
+static void ata_eh_dev_disable(struct ata_device *dev)
+{
+ ata_acpi_on_disable(dev);
+ ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET);
+ dev->class++;
+
+ /* From now till the next successful probe, ering is used to
+ * track probe failures. Clear accumulated device error info.
+ */
+ ata_ering_clear(&dev->ering);
+}
+
static void ata_eh_unload(struct ata_port *ap)
{
struct ata_link *link;
@@ -517,8 +529,8 @@ static void ata_eh_unload(struct ata_port *ap)
*/
ata_for_each_link(link, ap, PMP_FIRST) {
sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0);
- ata_for_each_dev(dev, link, ALL)
- ata_dev_disable(dev);
+ ata_for_each_dev(dev, link, ENABLED)
+ ata_eh_dev_disable(dev);
}
/* freeze and set UNLOADED */
@@ -1211,14 +1223,8 @@ void ata_dev_disable(struct ata_device *dev)
return;
ata_dev_warn(dev, "disable device\n");
- ata_acpi_on_disable(dev);
- ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET);
- dev->class++;
- /* From now till the next successful probe, ering is used to
- * track probe failures. Clear accumulated device error info.
- */
- ata_ering_clear(&dev->ering);
+ ata_eh_dev_disable(dev);
}
EXPORT_SYMBOL_GPL(ata_dev_disable);
@@ -1240,12 +1246,12 @@ void ata_eh_detach_dev(struct ata_device *dev)
/*
* If the device is still enabled, transition it to standby power mode
- * (i.e. spin down HDDs).
+ * (i.e. spin down HDDs) and disable it.
*/
- if (ata_dev_enabled(dev))
+ if (ata_dev_enabled(dev)) {
ata_dev_power_set_standby(dev);
-
- ata_dev_disable(dev);
+ ata_eh_dev_disable(dev);
+ }
spin_lock_irqsave(ap->lock, flags);
@@ -2909,6 +2915,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
*/
if (ata_is_host_link(link))
ata_eh_thaw_port(ap);
+ ata_link_warn(link, "%s failed\n",
+ reset == hardreset ? "hardreset" : "softreset");
goto out;
}
@@ -3043,15 +3051,6 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
if (ehc->i.flags & ATA_EHI_DID_RESET)
readid_flags |= ATA_READID_POSTRESET;
- /*
- * When resuming, before executing any command, make sure to
- * transition the device to the active power mode.
- */
- if ((action & ATA_EH_SET_ACTIVE) && ata_dev_enabled(dev)) {
- ata_dev_power_set_active(dev);
- ata_eh_done(link, dev, ATA_EH_SET_ACTIVE);
- }
-
if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) {
WARN_ON(dev->class == ATA_DEV_PMP);
@@ -3848,6 +3847,17 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
}
}
+ /*
+ * Make sure to transition devices to the active power mode
+ * if needed (e.g. if we were scheduled on system resume).
+ */
+ ata_for_each_dev(dev, link, ENABLED) {
+ if (ehc->i.dev_action[dev->devno] & ATA_EH_SET_ACTIVE) {
+ ata_dev_power_set_active(dev);
+ ata_eh_done(link, dev, ATA_EH_SET_ACTIVE);
+ }
+ }
+
/* retry flush if necessary */
ata_for_each_dev(dev, link, ALL) {
if (dev->class != ATA_DEV_ATA &&
diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c
index a701e1538482..b6656c287175 100644
--- a/drivers/ata/libata-sata.c
+++ b/drivers/ata/libata-sata.c
@@ -621,7 +621,6 @@ int sata_link_hardreset(struct ata_link *link, const unsigned int *timing,
/* online is set iff link is online && reset succeeded */
if (online)
*online = false;
- ata_link_err(link, "COMRESET failed (errno=%d)\n", rc);
}
return rc;
}
@@ -1182,8 +1181,8 @@ EXPORT_SYMBOL_GPL(ata_sas_tport_delete);
int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap)
{
ata_scsi_sdev_config(sdev);
- ata_scsi_dev_config(sdev, ap->link.device);
- return 0;
+
+ return ata_scsi_dev_config(sdev, ap->link.device);
}
EXPORT_SYMBOL_GPL(ata_sas_slave_configure);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index a371b497035e..0a0f483124c3 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1053,10 +1053,16 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev)
/*
* Ask the sd driver to issue START STOP UNIT on runtime suspend
- * and resume only. For system level suspend/resume, devices
- * power state is handled directly by libata EH.
+ * and resume and shutdown only. For system level suspend/resume,
+ * devices power state is handled directly by libata EH.
+ * Given that disks are always spun up on system resume, also
+ * make sure that the sd driver forces runtime suspended disks
+ * to be resumed to correctly reflect the power state of the
+ * device.
*/
- sdev->manage_runtime_start_stop = true;
+ sdev->manage_runtime_start_stop = 1;
+ sdev->manage_shutdown = 1;
+ sdev->force_runtime_start_on_system_start = 1;
}
/*
@@ -1202,7 +1208,6 @@ EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *scmd = qc->scsicmd;
- struct ata_taskfile *tf = &qc->tf;
const u8 *cdb = scmd->cmnd;
u16 fp;
u8 bp = 0xff;
@@ -1212,54 +1217,24 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
goto invalid_fld;
}
- tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
- tf->protocol = ATA_PROT_NODATA;
- if (cdb[1] & 0x1) {
- ; /* ignore IMMED bit, violates sat-r05 */
- }
+ /* LOEJ bit set not supported */
if (cdb[4] & 0x2) {
fp = 4;
bp = 1;
- goto invalid_fld; /* LOEJ bit set not supported */
+ goto invalid_fld;
}
+
+ /* Power conditions not supported */
if (((cdb[4] >> 4) & 0xf) != 0) {
fp = 4;
bp = 3;
- goto invalid_fld; /* power conditions not supported */
+ goto invalid_fld;
}
- if (cdb[4] & 0x1) {
- tf->nsect = 1; /* 1 sector, lba=0 */
-
- if (qc->dev->flags & ATA_DFLAG_LBA) {
- tf->flags |= ATA_TFLAG_LBA;
-
- tf->lbah = 0x0;
- tf->lbam = 0x0;
- tf->lbal = 0x0;
- tf->device |= ATA_LBA;
- } else {
- /* CHS */
- tf->lbal = 0x1; /* sect */
- tf->lbam = 0x0; /* cyl low */
- tf->lbah = 0x0; /* cyl high */
- }
-
- tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
- } else {
- /* Some odd clown BIOSen issue spindown on power off (ACPI S4
- * or S5) causing some drives to spin up and down again.
- */
- if ((qc->ap->flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
- system_state == SYSTEM_POWER_OFF)
- goto skip;
-
- if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
- system_entering_hibernation())
- goto skip;
-
- /* Issue ATA STANDBY IMMEDIATE command */
- tf->command = ATA_CMD_STANDBYNOW1;
+ /* Ignore IMMED bit (cdb[1] & 0x1), violates sat-r05 */
+ if (!ata_dev_power_init_tf(qc->dev, &qc->tf, cdb[4] & 0x1)) {
+ ata_scsi_set_sense(qc->dev, scmd, ABORTED_COMMAND, 0, 0);
+ return 1;
}
/*
@@ -1274,12 +1249,8 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
invalid_fld:
ata_scsi_set_invalid_field(qc->dev, scmd, fp, bp);
return 1;
- skip:
- scmd->result = SAM_STAT_GOOD;
- return 1;
}
-
/**
* ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
* @qc: Storage for translated ATA taskfile
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 8fcc622fcb3d..95a19c4ef2a1 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -2316,7 +2316,7 @@ int ata_pci_sff_activate_host(struct ata_host *host,
for (i = 0; i < 2; i++) {
if (ata_port_is_dummy(host->ports[i]))
continue;
- ata_port_desc(host->ports[i], "irq %d", pdev->irq);
+ ata_port_desc_misc(host->ports[i], pdev->irq);
}
} else if (legacy_mode) {
if (!ata_port_is_dummy(host->ports[0])) {
@@ -2326,8 +2326,8 @@ int ata_pci_sff_activate_host(struct ata_host *host,
if (rc)
goto out;
- ata_port_desc(host->ports[0], "irq %d",
- ATA_PRIMARY_IRQ(pdev));
+ ata_port_desc_misc(host->ports[0],
+ ATA_PRIMARY_IRQ(pdev));
}
if (!ata_port_is_dummy(host->ports[1])) {
@@ -2337,8 +2337,8 @@ int ata_pci_sff_activate_host(struct ata_host *host,
if (rc)
goto out;
- ata_port_desc(host->ports[1], "irq %d",
- ATA_SECONDARY_IRQ(pdev));
+ ata_port_desc_misc(host->ports[1],
+ ATA_SECONDARY_IRQ(pdev));
}
}
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 05ac80da8ebc..5c685bb1939e 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -62,6 +62,8 @@ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags);
extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
unsigned int readid_flags);
extern int ata_dev_configure(struct ata_device *dev);
+extern bool ata_dev_power_init_tf(struct ata_device *dev,
+ struct ata_taskfile *tf, bool set_active);
extern void ata_dev_power_set_standby(struct ata_device *dev);
extern void ata_dev_power_set_active(struct ata_device *dev);
extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit);
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 422d42761a1d..38795508c2e9 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -212,7 +212,7 @@ static int cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;
- ata_port_desc(ap, "irq %d", irq[i]);
+ ata_port_desc_misc(ap, irq[i]);
}
return ata_host_register(host, &cs5520_sht);
diff --git a/drivers/ata/pata_falcon.c b/drivers/ata/pata_falcon.c
index 0c2ae430f5aa..18ceefd176df 100644
--- a/drivers/ata/pata_falcon.c
+++ b/drivers/ata/pata_falcon.c
@@ -121,7 +121,7 @@ static struct ata_port_operations pata_falcon_ops = {
.set_mode = pata_falcon_set_mode,
};
-static int __init pata_falcon_init_one(struct platform_device *pdev)
+static int pata_falcon_init_one(struct platform_device *pdev)
{
struct resource *base_mem_res, *ctl_mem_res;
struct resource *base_res, *ctl_res, *irq_res;
@@ -216,23 +216,22 @@ static int __init pata_falcon_init_one(struct platform_device *pdev)
IRQF_SHARED, &pata_falcon_sht);
}
-static int __exit pata_falcon_remove_one(struct platform_device *pdev)
+static void pata_falcon_remove_one(struct platform_device *pdev)
{
struct ata_host *host = platform_get_drvdata(pdev);
ata_host_detach(host);
-
- return 0;
}
static struct platform_driver pata_falcon_driver = {
- .remove = __exit_p(pata_falcon_remove_one),
+ .probe = pata_falcon_init_one,
+ .remove_new = pata_falcon_remove_one,
.driver = {
.name = "atari-falcon-ide",
},
};
-module_platform_driver_probe(pata_falcon_driver, pata_falcon_init_one);
+module_platform_driver(pata_falcon_driver);
MODULE_AUTHOR("Bartlomiej Zolnierkiewicz");
MODULE_DESCRIPTION("low-level driver for Atari Falcon PATA");
diff --git a/drivers/ata/pata_gayle.c b/drivers/ata/pata_gayle.c
index 3bdbe2b65a2b..94df60ac2307 100644
--- a/drivers/ata/pata_gayle.c
+++ b/drivers/ata/pata_gayle.c
@@ -124,7 +124,7 @@ static struct ata_port_operations pata_gayle_a4000_ops = {
.set_mode = pata_gayle_set_mode,
};
-static int __init pata_gayle_init_one(struct platform_device *pdev)
+static int pata_gayle_init_one(struct platform_device *pdev)
{
struct resource *res;
struct gayle_ide_platform_data *pdata;
@@ -193,23 +193,22 @@ static int __init pata_gayle_init_one(struct platform_device *pdev)
return 0;
}
-static int __exit pata_gayle_remove_one(struct platform_device *pdev)
+static void pata_gayle_remove_one(struct platform_device *pdev)
{
struct ata_host *host = platform_get_drvdata(pdev);
ata_host_detach(host);
-
- return 0;
}
static struct platform_driver pata_gayle_driver = {
- .remove = __exit_p(pata_gayle_remove_one),
+ .probe = pata_gayle_init_one,
+ .remove_new = pata_gayle_remove_one,
.driver = {
.name = "amiga-gayle-ide",
},
};
-module_platform_driver_probe(pata_gayle_driver, pata_gayle_init_one);
+module_platform_driver(pata_gayle_driver);
MODULE_AUTHOR("Bartlomiej Zolnierkiewicz");
MODULE_DESCRIPTION("low-level driver for Amiga Gayle PATA");
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 25a63d043c8e..0f77e0424066 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -82,6 +82,9 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
if (pnp_port_valid(idev, 1)) {
ctl_addr = devm_ioport_map(&idev->dev,
pnp_port_start(idev, 1), 1);
+ if (!ctl_addr)
+ return -ENOMEM;
+
ap->ioaddr.altstatus_addr = ctl_addr;
ap->ioaddr.ctl_addr = ctl_addr;
ap->ops = &isapnp_port_ops;
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 45e48d653c60..e82786c63fbd 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -4123,10 +4123,13 @@ static int mv_platform_probe(struct platform_device *pdev)
hpriv->base -= SATAHC0_REG_BASE;
hpriv->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(hpriv->clk))
+ if (IS_ERR(hpriv->clk)) {
dev_notice(&pdev->dev, "cannot get optional clkdev\n");
- else
- clk_prepare_enable(hpriv->clk);
+ } else {
+ rc = clk_prepare_enable(hpriv->clk);
+ if (rc)
+ goto err;
+ }
for (port = 0; port < n_ports; port++) {
char port_number[16];
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index fb2be3574c26..50d8ce20ae5b 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -36,7 +36,7 @@
#ifdef CONFIG_SBUS
#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/platform_device.h>
#include <asm/idprom.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
@@ -2520,18 +2520,12 @@ static int fore200e_init(struct fore200e *fore200e, struct device *parent)
}
#ifdef CONFIG_SBUS
-static const struct of_device_id fore200e_sba_match[];
static int fore200e_sba_probe(struct platform_device *op)
{
- const struct of_device_id *match;
struct fore200e *fore200e;
static int index = 0;
int err;
- match = of_match_device(fore200e_sba_match, &op->dev);
- if (!match)
- return -EINVAL;
-
fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL);
if (!fore200e)
return -ENOMEM;
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index 324148686953..9bba8f280a4d 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -2291,19 +2291,21 @@ static int get_esi(struct atm_dev *dev)
static int reset_sar(struct atm_dev *dev)
{
IADEV *iadev;
- int i, error = 1;
+ int i, error;
unsigned int pci[64];
iadev = INPH_IA_DEV(dev);
- for(i=0; i<64; i++)
- if ((error = pci_read_config_dword(iadev->pci,
- i*4, &pci[i])) != PCIBIOS_SUCCESSFUL)
- return error;
+ for (i = 0; i < 64; i++) {
+ error = pci_read_config_dword(iadev->pci, i * 4, &pci[i]);
+ if (error != PCIBIOS_SUCCESSFUL)
+ return error;
+ }
writel(0, iadev->reg+IPHASE5575_EXT_RESET);
- for(i=0; i<64; i++)
- if ((error = pci_write_config_dword(iadev->pci,
- i*4, pci[i])) != PCIBIOS_SUCCESSFUL)
- return error;
+ for (i = 0; i < 64; i++) {
+ error = pci_write_config_dword(iadev->pci, i * 4, pci[i]);
+ if (error != PCIBIOS_SUCCESSFUL)
+ return error;
+ }
udelay(5);
return 0;
}
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 94fbc3abe60e..d3c30a28c410 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -449,9 +449,9 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr,
struct sk_buff *skb;
unsigned int len;
- spin_lock(&card->cli_queue_lock);
+ spin_lock_bh(&card->cli_queue_lock);
skb = skb_dequeue(&card->cli_queue[SOLOS_CHAN(atmdev)]);
- spin_unlock(&card->cli_queue_lock);
+ spin_unlock_bh(&card->cli_queue_lock);
if(skb == NULL)
return sprintf(buf, "No data.\n");
@@ -956,14 +956,14 @@ static void pclose(struct atm_vcc *vcc)
struct pkt_hdr *header;
/* Remove any yet-to-be-transmitted packets from the pending queue */
- spin_lock(&card->tx_queue_lock);
+ spin_lock_bh(&card->tx_queue_lock);
skb_queue_walk_safe(&card->tx_queue[port], skb, tmpskb) {
if (SKB_CB(skb)->vcc == vcc) {
skb_unlink(skb, &card->tx_queue[port]);
solos_pop(vcc, skb);
}
}
- spin_unlock(&card->tx_queue_lock);
+ spin_unlock_bh(&card->tx_queue_lock);
skb = alloc_skb(sizeof(*header), GFP_KERNEL);
if (!skb) {
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index eba04c0de7eb..e20d35bdf5fe 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -1449,10 +1449,9 @@ static struct logical_input *panel_bind_key(const char *name, const char *press,
key->rise_time = 1;
key->fall_time = 1;
- strncpy(key->u.kbd.press_str, press, sizeof(key->u.kbd.press_str));
- strncpy(key->u.kbd.repeat_str, repeat, sizeof(key->u.kbd.repeat_str));
- strncpy(key->u.kbd.release_str, release,
- sizeof(key->u.kbd.release_str));
+ strtomem_pad(key->u.kbd.press_str, press, '\0');
+ strtomem_pad(key->u.kbd.repeat_str, repeat, '\0');
+ strtomem_pad(key->u.kbd.release_str, release, '\0');
list_add(&key->list, &logical_inputs);
return key;
}
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index cbae8be1fe52..f1e79263fe61 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -898,6 +898,48 @@ err:
return rc;
}
+/*
+ * Calculate the size of the per-CPU data cache slice. This can be
+ * used to estimate the size of the data cache slice that can be used
+ * by one CPU under ideal circumstances. UNIFIED caches are counted
+ * in addition to DATA caches. So, please consider code cache usage
+ * when use the result.
+ *
+ * Because the cache inclusive/non-inclusive information isn't
+ * available, we just use the size of the per-CPU slice of LLC to make
+ * the result more predictable across architectures.
+ */
+static void update_per_cpu_data_slice_size_cpu(unsigned int cpu)
+{
+ struct cpu_cacheinfo *ci;
+ struct cacheinfo *llc;
+ unsigned int nr_shared;
+
+ if (!last_level_cache_is_valid(cpu))
+ return;
+
+ ci = ci_cacheinfo(cpu);
+ llc = per_cpu_cacheinfo_idx(cpu, cache_leaves(cpu) - 1);
+
+ if (llc->type != CACHE_TYPE_DATA && llc->type != CACHE_TYPE_UNIFIED)
+ return;
+
+ nr_shared = cpumask_weight(&llc->shared_cpu_map);
+ if (nr_shared)
+ ci->per_cpu_data_slice_size = llc->size / nr_shared;
+}
+
+static void update_per_cpu_data_slice_size(bool cpu_online, unsigned int cpu)
+{
+ unsigned int icpu;
+
+ for_each_online_cpu(icpu) {
+ if (!cpu_online && icpu == cpu)
+ continue;
+ update_per_cpu_data_slice_size_cpu(icpu);
+ }
+}
+
static int cacheinfo_cpu_online(unsigned int cpu)
{
int rc = detect_cache_attributes(cpu);
@@ -906,7 +948,12 @@ static int cacheinfo_cpu_online(unsigned int cpu)
return rc;
rc = cache_add_dev(cpu);
if (rc)
- free_cache_attributes(cpu);
+ goto err;
+ update_per_cpu_data_slice_size(true, cpu);
+ setup_pcp_cacheinfo();
+ return 0;
+err:
+ free_cache_attributes(cpu);
return rc;
}
@@ -916,6 +963,8 @@ static int cacheinfo_cpu_pre_down(unsigned int cpu)
cpu_cache_sysfs_exit(cpu);
free_cache_attributes(cpu);
+ update_per_cpu_data_slice_size(false, cpu);
+ setup_pcp_cacheinfo();
return 0;
}
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 05d9df90f621..7e78aee0fd6c 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -193,10 +193,8 @@ int class_register(const struct class *cls)
lockdep_register_key(key);
__mutex_init(&cp->mutex, "subsys mutex", key);
error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
- if (error) {
- kfree(cp);
- return error;
- }
+ if (error)
+ goto err_out;
cp->subsys.kobj.kset = class_kset;
cp->subsys.kobj.ktype = &class_ktype;
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 4d8b315c48a1..67ba592afc77 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -49,6 +49,7 @@ static bool fw_devlink_best_effort;
* __fwnode_link_add - Create a link between two fwnode_handles.
* @con: Consumer end of the link.
* @sup: Supplier end of the link.
+ * @flags: Link flags.
*
* Create a fwnode link between fwnode handles @con and @sup. The fwnode link
* represents the detail that the firmware lists @sup fwnode as supplying a
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 9ea22e165acd..548491de818e 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -144,7 +144,7 @@ static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store);
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
#endif /* CONFIG_HOTPLUG_CPU */
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
#include <linux/kexec.h>
static ssize_t crash_notes_show(struct device *dev,
@@ -189,14 +189,14 @@ static const struct attribute_group crash_note_cpu_attr_group = {
#endif
static const struct attribute_group *common_cpu_attr_groups[] = {
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
&crash_note_cpu_attr_group,
#endif
NULL
};
static const struct attribute_group *hotplugable_cpu_attr_groups[] = {
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
&crash_note_cpu_attr_group,
#endif
NULL
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index a528cec24264..0c3725c3eefa 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -1274,8 +1274,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
if (dev->bus && dev->bus->dma_cleanup)
dev->bus->dma_cleanup(dev);
- device_links_driver_cleanup(dev);
device_unbind_cleanup(dev);
+ device_links_driver_cleanup(dev);
klist_remove(&dev->p->knode_driver);
device_pm_check_callbacks(dev);
diff --git a/drivers/base/devcoredump.c b/drivers/base/devcoredump.c
index 91536ee05f14..7e2d1f0d903a 100644
--- a/drivers/base/devcoredump.c
+++ b/drivers/base/devcoredump.c
@@ -362,6 +362,7 @@ void dev_coredumpm(struct device *dev, struct module *owner,
devcd->devcd_dev.class = &devcd_class;
mutex_lock(&devcd->mutex);
+ dev_set_uevent_suppress(&devcd->devcd_dev, true);
if (device_add(&devcd->devcd_dev))
goto put_device;
@@ -376,6 +377,8 @@ void dev_coredumpm(struct device *dev, struct module *owner,
"devcoredump"))
dev_warn(dev, "devcoredump create_link failed\n");
+ dev_set_uevent_suppress(&devcd->devcd_dev, false);
+ kobject_uevent(&devcd->devcd_dev.kobj, KOBJ_ADD);
INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT);
mutex_unlock(&devcd->mutex);
diff --git a/drivers/base/firmware_loader/fallback.c b/drivers/base/firmware_loader/fallback.c
index bf68e3947814..3ef0b312ae71 100644
--- a/drivers/base/firmware_loader/fallback.c
+++ b/drivers/base/firmware_loader/fallback.c
@@ -46,7 +46,7 @@ static inline int fw_sysfs_wait_timeout(struct fw_priv *fw_priv, long timeout)
static LIST_HEAD(pending_fw_head);
-void kill_pending_fw_fallback_reqs(bool only_kill_custom)
+void kill_pending_fw_fallback_reqs(bool kill_all)
{
struct fw_priv *fw_priv;
struct fw_priv *next;
@@ -54,9 +54,13 @@ void kill_pending_fw_fallback_reqs(bool only_kill_custom)
mutex_lock(&fw_lock);
list_for_each_entry_safe(fw_priv, next, &pending_fw_head,
pending_list) {
- if (!fw_priv->need_uevent || !only_kill_custom)
+ if (kill_all || !fw_priv->need_uevent)
__fw_load_abort(fw_priv);
}
+
+ if (kill_all)
+ fw_load_abort_all = true;
+
mutex_unlock(&fw_lock);
}
@@ -86,7 +90,7 @@ static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, long timeout)
}
mutex_lock(&fw_lock);
- if (fw_state_is_aborted(fw_priv)) {
+ if (fw_load_abort_all || fw_state_is_aborted(fw_priv)) {
mutex_unlock(&fw_lock);
retval = -EINTR;
goto out;
diff --git a/drivers/base/firmware_loader/fallback.h b/drivers/base/firmware_loader/fallback.h
index 144148595660..ccf912bef6ca 100644
--- a/drivers/base/firmware_loader/fallback.h
+++ b/drivers/base/firmware_loader/fallback.h
@@ -13,7 +13,7 @@ int firmware_fallback_sysfs(struct firmware *fw, const char *name,
struct device *device,
u32 opt_flags,
int ret);
-void kill_pending_fw_fallback_reqs(bool only_kill_custom);
+void kill_pending_fw_fallback_reqs(bool kill_all);
void fw_fallback_set_cache_timeout(void);
void fw_fallback_set_default_timeout(void);
@@ -28,7 +28,7 @@ static inline int firmware_fallback_sysfs(struct firmware *fw, const char *name,
return ret;
}
-static inline void kill_pending_fw_fallback_reqs(bool only_kill_custom) { }
+static inline void kill_pending_fw_fallback_reqs(bool kill_all) { }
static inline void fw_fallback_set_cache_timeout(void) { }
static inline void fw_fallback_set_default_timeout(void) { }
#endif /* CONFIG_FW_LOADER_USER_HELPER */
diff --git a/drivers/base/firmware_loader/fallback_table.c b/drivers/base/firmware_loader/fallback_table.c
index e5ac098d0742..8432ab2c3b3c 100644
--- a/drivers/base/firmware_loader/fallback_table.c
+++ b/drivers/base/firmware_loader/fallback_table.c
@@ -44,7 +44,6 @@ static struct ctl_table firmware_config_table[] = {
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
- { }
};
static struct ctl_table_header *firmware_config_sysct_table_header;
diff --git a/drivers/base/firmware_loader/firmware.h b/drivers/base/firmware_loader/firmware.h
index bf549d6500d7..e891742ba264 100644
--- a/drivers/base/firmware_loader/firmware.h
+++ b/drivers/base/firmware_loader/firmware.h
@@ -86,6 +86,7 @@ struct fw_priv {
extern struct mutex fw_lock;
extern struct firmware_cache fw_cache;
+extern bool fw_load_abort_all;
static inline bool __fw_state_check(struct fw_priv *fw_priv,
enum fw_status status)
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index b58c42f1b1ce..ea28102d421e 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -93,6 +93,7 @@ static inline struct fw_priv *to_fw_priv(struct kref *ref)
DEFINE_MUTEX(fw_lock);
struct firmware_cache fw_cache;
+bool fw_load_abort_all;
void fw_state_init(struct fw_priv *fw_priv)
{
@@ -1524,10 +1525,10 @@ static int fw_pm_notify(struct notifier_block *notify_block,
case PM_SUSPEND_PREPARE:
case PM_RESTORE_PREPARE:
/*
- * kill pending fallback requests with a custom fallback
- * to avoid stalling suspend.
+ * Here, kill pending fallback requests will only kill
+ * non-uevent firmware request to avoid stalling suspend.
*/
- kill_pending_fw_fallback_reqs(true);
+ kill_pending_fw_fallback_reqs(false);
device_cache_fw_images();
break;
@@ -1612,7 +1613,7 @@ static int fw_shutdown_notify(struct notifier_block *unused1,
* Kill all pending fallback requests to avoid both stalling shutdown,
* and avoid a deadlock with the usermode_lock.
*/
- kill_pending_fw_fallback_reqs(false);
+ kill_pending_fw_fallback_reqs(true);
return NOTIFY_DONE;
}
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index f3b9a4d0fa3b..8a13babd826c 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -180,6 +180,9 @@ static inline unsigned long memblk_nr_poison(struct memory_block *mem)
}
#endif
+/*
+ * Must acquire mem_hotplug_lock in write mode.
+ */
static int memory_block_online(struct memory_block *mem)
{
unsigned long start_pfn = section_nr_to_pfn(mem->start_section_nr);
@@ -204,10 +207,11 @@ static int memory_block_online(struct memory_block *mem)
if (mem->altmap)
nr_vmemmap_pages = mem->altmap->free;
+ mem_hotplug_begin();
if (nr_vmemmap_pages) {
ret = mhp_init_memmap_on_memory(start_pfn, nr_vmemmap_pages, zone);
if (ret)
- return ret;
+ goto out;
}
ret = online_pages(start_pfn + nr_vmemmap_pages,
@@ -215,7 +219,7 @@ static int memory_block_online(struct memory_block *mem)
if (ret) {
if (nr_vmemmap_pages)
mhp_deinit_memmap_on_memory(start_pfn, nr_vmemmap_pages);
- return ret;
+ goto out;
}
/*
@@ -227,9 +231,14 @@ static int memory_block_online(struct memory_block *mem)
nr_vmemmap_pages);
mem->zone = zone;
+out:
+ mem_hotplug_done();
return ret;
}
+/*
+ * Must acquire mem_hotplug_lock in write mode.
+ */
static int memory_block_offline(struct memory_block *mem)
{
unsigned long start_pfn = section_nr_to_pfn(mem->start_section_nr);
@@ -247,6 +256,7 @@ static int memory_block_offline(struct memory_block *mem)
if (mem->altmap)
nr_vmemmap_pages = mem->altmap->free;
+ mem_hotplug_begin();
if (nr_vmemmap_pages)
adjust_present_page_count(pfn_to_page(start_pfn), mem->group,
-nr_vmemmap_pages);
@@ -258,13 +268,15 @@ static int memory_block_offline(struct memory_block *mem)
if (nr_vmemmap_pages)
adjust_present_page_count(pfn_to_page(start_pfn),
mem->group, nr_vmemmap_pages);
- return ret;
+ goto out;
}
if (nr_vmemmap_pages)
mhp_deinit_memmap_on_memory(start_pfn, nr_vmemmap_pages);
mem->zone = NULL;
+out:
+ mem_hotplug_done();
return ret;
}
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 76bfcba25003..10c577963418 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -178,18 +178,19 @@ int platform_get_irq_optional(struct platform_device *dev, unsigned int num)
ret = dev->archdata.irqs[num];
goto out;
#else
+ struct fwnode_handle *fwnode = dev_fwnode(&dev->dev);
struct resource *r;
- if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) {
- ret = of_irq_get(dev->dev.of_node, num);
+ if (is_of_node(fwnode)) {
+ ret = of_irq_get(to_of_node(fwnode), num);
if (ret > 0 || ret == -EPROBE_DEFER)
goto out;
}
r = platform_get_resource(dev, IORESOURCE_IRQ, num);
- if (has_acpi_companion(&dev->dev)) {
+ if (is_acpi_device_node(fwnode)) {
if (r && r->flags & IORESOURCE_DISABLED) {
- ret = acpi_irq_get(ACPI_HANDLE(&dev->dev), num, r);
+ ret = acpi_irq_get(ACPI_HANDLE_FWNODE(fwnode), num, r);
if (ret)
goto out;
}
@@ -222,8 +223,8 @@ int platform_get_irq_optional(struct platform_device *dev, unsigned int num)
* the device will only expose one IRQ, and this fallback
* allows a common code path across either kind of resource.
*/
- if (num == 0 && has_acpi_companion(&dev->dev)) {
- ret = acpi_dev_gpio_irq_get(ACPI_COMPANION(&dev->dev), num);
+ if (num == 0 && is_acpi_device_node(fwnode)) {
+ ret = acpi_dev_gpio_irq_get(to_acpi_device_node(fwnode), num);
/* Our callers expect -ENXIO for missing IRQs. */
if (ret >= 0 || ret == -EPROBE_DEFER)
goto out;
@@ -291,7 +292,7 @@ EXPORT_SYMBOL_GPL(platform_irq_count);
struct irq_affinity_devres {
unsigned int count;
- unsigned int irq[];
+ unsigned int irq[] __counted_by(count);
};
static void platform_disable_acpi_irq(struct platform_device *pdev, int index)
@@ -312,7 +313,7 @@ static void devm_platform_get_irqs_affinity_release(struct device *dev,
for (i = 0; i < ptr->count; i++) {
irq_dispose_mapping(ptr->irq[i]);
- if (has_acpi_companion(dev))
+ if (is_acpi_device_node(dev_fwnode(dev)))
platform_disable_acpi_irq(to_platform_device(dev), i);
}
}
@@ -655,23 +656,21 @@ EXPORT_SYMBOL_GPL(platform_device_add_data);
*/
int platform_device_add(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
u32 i;
int ret;
- if (!pdev)
- return -EINVAL;
-
- if (!pdev->dev.parent)
- pdev->dev.parent = &platform_bus;
+ if (!dev->parent)
+ dev->parent = &platform_bus;
- pdev->dev.bus = &platform_bus_type;
+ dev->bus = &platform_bus_type;
switch (pdev->id) {
default:
- dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
+ dev_set_name(dev, "%s.%d", pdev->name, pdev->id);
break;
case PLATFORM_DEVID_NONE:
- dev_set_name(&pdev->dev, "%s", pdev->name);
+ dev_set_name(dev, "%s", pdev->name);
break;
case PLATFORM_DEVID_AUTO:
/*
@@ -681,10 +680,10 @@ int platform_device_add(struct platform_device *pdev)
*/
ret = ida_alloc(&platform_devid_ida, GFP_KERNEL);
if (ret < 0)
- goto err_out;
+ return ret;
pdev->id = ret;
pdev->id_auto = true;
- dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, pdev->id);
+ dev_set_name(dev, "%s.%d.auto", pdev->name, pdev->id);
break;
}
@@ -692,7 +691,7 @@ int platform_device_add(struct platform_device *pdev)
struct resource *p, *r = &pdev->resource[i];
if (r->name == NULL)
- r->name = dev_name(&pdev->dev);
+ r->name = dev_name(dev);
p = r->parent;
if (!p) {
@@ -705,18 +704,20 @@ int platform_device_add(struct platform_device *pdev)
if (p) {
ret = insert_resource(p, r);
if (ret) {
- dev_err(&pdev->dev, "failed to claim resource %d: %pR\n", i, r);
+ dev_err(dev, "failed to claim resource %d: %pR\n", i, r);
goto failed;
}
}
}
- pr_debug("Registering platform device '%s'. Parent at %s\n",
- dev_name(&pdev->dev), dev_name(pdev->dev.parent));
+ pr_debug("Registering platform device '%s'. Parent at %s\n", dev_name(dev),
+ dev_name(dev->parent));
- ret = device_add(&pdev->dev);
- if (ret == 0)
- return ret;
+ ret = device_add(dev);
+ if (ret)
+ goto failed;
+
+ return 0;
failed:
if (pdev->id_auto) {
@@ -730,7 +731,6 @@ int platform_device_add(struct platform_device *pdev)
release_resource(r);
}
- err_out:
return ret;
}
EXPORT_SYMBOL_GPL(platform_device_add);
@@ -1447,21 +1447,22 @@ static void platform_shutdown(struct device *_dev)
static int platform_dma_configure(struct device *dev)
{
struct platform_driver *drv = to_platform_driver(dev->driver);
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
enum dev_dma_attr attr;
int ret = 0;
- if (dev->of_node) {
- ret = of_dma_configure(dev, dev->of_node, true);
- } else if (has_acpi_companion(dev)) {
- attr = acpi_get_dma_attr(to_acpi_device_node(dev->fwnode));
+ if (is_of_node(fwnode)) {
+ ret = of_dma_configure(dev, to_of_node(fwnode), true);
+ } else if (is_acpi_device_node(fwnode)) {
+ attr = acpi_get_dma_attr(to_acpi_device_node(fwnode));
ret = acpi_dma_configure(dev, attr);
}
+ if (ret || drv->driver_managed_dma)
+ return ret;
- if (!ret && !drv->driver_managed_dma) {
- ret = iommu_device_use_default_domain(dev);
- if (ret)
- arch_teardown_dma_ops(dev);
- }
+ ret = iommu_device_use_default_domain(dev);
+ if (ret)
+ arch_teardown_dma_ops(dev);
return ret;
}
diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
index 72115917e0bd..44ec20918a4d 100644
--- a/drivers/base/power/common.c
+++ b/drivers/base/power/common.c
@@ -228,3 +228,24 @@ void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd)
device_pm_check_callbacks(dev);
}
EXPORT_SYMBOL_GPL(dev_pm_domain_set);
+
+/**
+ * dev_pm_domain_set_performance_state - Request a new performance state.
+ * @dev: The device to make the request for.
+ * @state: Target performance state for the device.
+ *
+ * This function should be called when a new performance state needs to be
+ * requested for a device that is attached to a PM domain. Note that, the
+ * support for performance scaling for PM domains is optional.
+ *
+ * Returns 0 on success and when performance scaling isn't supported, negative
+ * error code on failure.
+ */
+int dev_pm_domain_set_performance_state(struct device *dev, unsigned int state)
+{
+ if (dev->pm_domain && dev->pm_domain->set_performance_state)
+ return dev->pm_domain->set_performance_state(dev, state);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_set_performance_state);
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 5cb2023581d4..da1777e39eaa 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -130,6 +130,7 @@ static const struct genpd_lock_ops genpd_spin_ops = {
#define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP)
#define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
#define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)
+#define genpd_is_opp_table_fw(genpd) (genpd->flags & GENPD_FLAG_OPP_TABLE_FW)
static inline bool irq_safe_dev_in_sleep_domain(struct device *dev,
const struct generic_pm_domain *genpd)
@@ -419,6 +420,25 @@ static void genpd_restore_performance_state(struct device *dev,
genpd_set_performance_state(dev, state);
}
+static int genpd_dev_pm_set_performance_state(struct device *dev,
+ unsigned int state)
+{
+ struct generic_pm_domain *genpd = dev_to_genpd(dev);
+ int ret = 0;
+
+ genpd_lock(genpd);
+ if (pm_runtime_suspended(dev)) {
+ dev_gpd_data(dev)->rpm_pstate = state;
+ } else {
+ ret = genpd_set_performance_state(dev, state);
+ if (!ret)
+ dev_gpd_data(dev)->rpm_pstate = 0;
+ }
+ genpd_unlock(genpd);
+
+ return ret;
+}
+
/**
* dev_pm_genpd_set_performance_state- Set performance state of device's power
* domain.
@@ -437,7 +457,6 @@ static void genpd_restore_performance_state(struct device *dev,
int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state)
{
struct generic_pm_domain *genpd;
- int ret = 0;
genpd = dev_to_genpd_safe(dev);
if (!genpd)
@@ -447,17 +466,7 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state)
!dev->power.subsys_data->domain_data))
return -EINVAL;
- genpd_lock(genpd);
- if (pm_runtime_suspended(dev)) {
- dev_gpd_data(dev)->rpm_pstate = state;
- } else {
- ret = genpd_set_performance_state(dev, state);
- if (!ret)
- dev_gpd_data(dev)->rpm_pstate = 0;
- }
- genpd_unlock(genpd);
-
- return ret;
+ return genpd_dev_pm_set_performance_state(dev, state);
}
EXPORT_SYMBOL_GPL(dev_pm_genpd_set_performance_state);
@@ -2079,6 +2088,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
genpd->domain.ops.restore_noirq = genpd_restore_noirq;
genpd->domain.ops.complete = genpd_complete;
genpd->domain.start = genpd_dev_pm_start;
+ genpd->domain.set_performance_state = genpd_dev_pm_set_performance_state;
if (genpd->flags & GENPD_FLAG_PM_CLK) {
genpd->dev_ops.stop = pm_clk_suspend;
@@ -2328,7 +2338,7 @@ int of_genpd_add_provider_simple(struct device_node *np,
genpd->dev.of_node = np;
/* Parse genpd OPP table */
- if (genpd->set_performance_state) {
+ if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
ret = dev_pm_opp_of_add_table(&genpd->dev);
if (ret)
return dev_err_probe(&genpd->dev, ret, "Failed to add OPP table\n");
@@ -2343,7 +2353,7 @@ int of_genpd_add_provider_simple(struct device_node *np,
ret = genpd_add_provider(np, genpd_xlate_simple, genpd);
if (ret) {
- if (genpd->set_performance_state) {
+ if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
dev_pm_opp_put_opp_table(genpd->opp_table);
dev_pm_opp_of_remove_table(&genpd->dev);
}
@@ -2387,7 +2397,7 @@ int of_genpd_add_provider_onecell(struct device_node *np,
genpd->dev.of_node = np;
/* Parse genpd OPP table */
- if (genpd->set_performance_state) {
+ if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
ret = dev_pm_opp_of_add_table_indexed(&genpd->dev, i);
if (ret) {
dev_err_probe(&genpd->dev, ret,
@@ -2423,7 +2433,7 @@ error:
genpd->provider = NULL;
genpd->has_provider = false;
- if (genpd->set_performance_state) {
+ if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
dev_pm_opp_put_opp_table(genpd->opp_table);
dev_pm_opp_of_remove_table(&genpd->dev);
}
@@ -2455,7 +2465,7 @@ void of_genpd_del_provider(struct device_node *np)
if (gpd->provider == &np->fwnode) {
gpd->has_provider = false;
- if (!gpd->set_performance_state)
+ if (genpd_is_opp_table_fw(gpd) || !gpd->set_performance_state)
continue;
dev_pm_opp_put_opp_table(gpd->opp_table);
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index c5d151e9c481..ac63a73ccdaa 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -334,6 +334,11 @@ static int regcache_default_sync(struct regmap *map, unsigned int min,
return 0;
}
+static int rbtree_all(const void *key, const struct rb_node *node)
+{
+ return 0;
+}
+
/**
* regcache_sync - Sync the register cache with the hardware.
*
@@ -351,6 +356,7 @@ int regcache_sync(struct regmap *map)
unsigned int i;
const char *name;
bool bypass;
+ struct rb_node *node;
if (WARN_ON(map->cache_type == REGCACHE_NONE))
return -EINVAL;
@@ -392,6 +398,29 @@ out:
/* Restore the bypass state */
map->cache_bypass = bypass;
map->no_sync_defaults = false;
+
+ /*
+ * If we did any paging with cache bypassed and a cached
+ * paging register then the register and cache state might
+ * have gone out of sync, force writes of all the paging
+ * registers.
+ */
+ rb_for_each(node, 0, &map->range_tree, rbtree_all) {
+ struct regmap_range_node *this =
+ rb_entry(node, struct regmap_range_node, node);
+
+ /* If there's nothing in the cache there's nothing to sync */
+ if (regcache_read(map, this->selector_reg, &i) != 0)
+ continue;
+
+ ret = _regmap_write(map, this->selector_reg, i);
+ if (ret != 0) {
+ dev_err(map->dev, "Failed to write %x = %x: %d\n",
+ this->selector_reg, i, ret);
+ break;
+ }
+ }
+
map->unlock(map->lock_arg);
regmap_async_complete(map);
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index f36027591e1a..bdd80b73c3e6 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -48,7 +48,7 @@ static ssize_t regmap_name_read_file(struct file *file,
name = map->dev->driver->name;
ret = snprintf(buf, PAGE_SIZE, "%s\n", name);
- if (ret < 0) {
+ if (ret >= PAGE_SIZE) {
kfree(buf);
return ret;
}
diff --git a/drivers/base/regmap/regmap-kunit.c b/drivers/base/regmap/regmap-kunit.c
index 264d29b3fced..e14cc03a17f6 100644
--- a/drivers/base/regmap/regmap-kunit.c
+++ b/drivers/base/regmap/regmap-kunit.c
@@ -442,10 +442,18 @@ static struct regmap_range_cfg test_range = {
.range_max = 40,
};
-static bool test_range_volatile(struct device *dev, unsigned int reg)
+static bool test_range_window_volatile(struct device *dev, unsigned int reg)
{
if (reg >= test_range.window_start &&
- reg <= test_range.selector_reg + test_range.window_len)
+ reg <= test_range.window_start + test_range.window_len)
+ return true;
+
+ return false;
+}
+
+static bool test_range_all_volatile(struct device *dev, unsigned int reg)
+{
+ if (test_range_window_volatile(dev, reg))
return true;
if (reg >= test_range.range_min && reg <= test_range.range_max)
@@ -465,7 +473,7 @@ static void basic_ranges(struct kunit *test)
config = test_regmap_config;
config.cache_type = t->type;
- config.volatile_reg = test_range_volatile;
+ config.volatile_reg = test_range_all_volatile;
config.ranges = &test_range;
config.num_ranges = 1;
config.max_register = test_range.range_max;
@@ -875,6 +883,59 @@ static void cache_present(struct kunit *test)
regmap_exit(map);
}
+/* Check that caching the window register works with sync */
+static void cache_range_window_reg(struct kunit *test)
+{
+ struct regcache_types *t = (struct regcache_types *)test->param_value;
+ struct regmap *map;
+ struct regmap_config config;
+ struct regmap_ram_data *data;
+ unsigned int val;
+ int i;
+
+ config = test_regmap_config;
+ config.cache_type = t->type;
+ config.volatile_reg = test_range_window_volatile;
+ config.ranges = &test_range;
+ config.num_ranges = 1;
+ config.max_register = test_range.range_max;
+
+ map = gen_regmap(&config, &data);
+ KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+ if (IS_ERR(map))
+ return;
+
+ /* Write new values to the entire range */
+ for (i = test_range.range_min; i <= test_range.range_max; i++)
+ KUNIT_ASSERT_EQ(test, 0, regmap_write(map, i, 0));
+
+ val = data->vals[test_range.selector_reg] & test_range.selector_mask;
+ KUNIT_ASSERT_EQ(test, val, 2);
+
+ /* Write to the first register in the range to reset the page */
+ KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
+ val = data->vals[test_range.selector_reg] & test_range.selector_mask;
+ KUNIT_ASSERT_EQ(test, val, 0);
+
+ /* Trigger a cache sync */
+ regcache_mark_dirty(map);
+ KUNIT_ASSERT_EQ(test, 0, regcache_sync(map));
+
+ /* Write to the first register again, the page should be reset */
+ KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
+ val = data->vals[test_range.selector_reg] & test_range.selector_mask;
+ KUNIT_ASSERT_EQ(test, val, 0);
+
+ /* Trigger another cache sync */
+ regcache_mark_dirty(map);
+ KUNIT_ASSERT_EQ(test, 0, regcache_sync(map));
+
+ /* Write to the last register again, the page should be reset */
+ KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_max, 0));
+ val = data->vals[test_range.selector_reg] & test_range.selector_mask;
+ KUNIT_ASSERT_EQ(test, val, 2);
+}
+
struct raw_test_types {
const char *name;
@@ -1217,6 +1278,7 @@ static struct kunit_case regmap_test_cases[] = {
KUNIT_CASE_PARAM(cache_sync_patch, real_cache_types_gen_params),
KUNIT_CASE_PARAM(cache_drop, sparse_cache_types_gen_params),
KUNIT_CASE_PARAM(cache_present, sparse_cache_types_gen_params),
+ KUNIT_CASE_PARAM(cache_range_window_reg, real_cache_types_gen_params),
KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params),
KUNIT_CASE_PARAM(raw_read_defaults, raw_test_types_gen_params),
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 884cb51c8f67..ea6157747199 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1478,7 +1478,7 @@ static int dev_get_regmap_match(struct device *dev, void *res, void *data)
/* If the user didn't specify a name match any */
if (data)
- return !strcmp((*r)->name, data);
+ return (*r)->name && !strcmp((*r)->name, data);
else
return 1;
}
@@ -1620,17 +1620,19 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
}
if (!map->cache_bypass && map->format.parse_val) {
- unsigned int ival;
+ unsigned int ival, offset;
int val_bytes = map->format.val_bytes;
- for (i = 0; i < val_len / val_bytes; i++) {
- ival = map->format.parse_val(val + (i * val_bytes));
- ret = regcache_write(map,
- reg + regmap_get_offset(map, i),
- ival);
+
+ /* Cache the last written value for noinc writes */
+ i = noinc ? val_len - val_bytes : 0;
+ for (; i < val_len; i += val_bytes) {
+ ival = map->format.parse_val(val + i);
+ offset = noinc ? 0 : regmap_get_offset(map, i / val_bytes);
+ ret = regcache_write(map, reg + offset, ival);
if (ret) {
dev_err(map->dev,
"Error in caching of register: %x ret: %d\n",
- reg + regmap_get_offset(map, i), ret);
+ reg + offset, ret);
return ret;
}
}
diff --git a/drivers/base/test/Kconfig b/drivers/base/test/Kconfig
index 9d42051f8f8e..5c7fac80611c 100644
--- a/drivers/base/test/Kconfig
+++ b/drivers/base/test/Kconfig
@@ -14,6 +14,6 @@ config DM_KUNIT_TEST
depends on KUNIT
config DRIVER_PE_KUNIT_TEST
- bool "KUnit Tests for property entry API" if !KUNIT_ALL_TESTS
- depends on KUNIT=y
+ tristate "KUnit Tests for property entry API" if !KUNIT_ALL_TESTS
+ depends on KUNIT
default KUNIT_ALL_TESTS
diff --git a/drivers/base/test/property-entry-test.c b/drivers/base/test/property-entry-test.c
index dd2b606d76a3..a8657eb06f94 100644
--- a/drivers/base/test/property-entry-test.c
+++ b/drivers/base/test/property-entry-test.c
@@ -506,3 +506,7 @@ static struct kunit_suite property_entry_test_suite = {
};
kunit_test_suite(property_entry_test_suite);
+
+MODULE_DESCRIPTION("Test module for the property entry API");
+MODULE_AUTHOR("Dmitry Torokhov <dtor@chromium.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index 63773a90581d..c51ea95bc2ce 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -39,8 +39,7 @@ static struct ktstate kts;
#ifndef MODULE
static int __init aoe_iflist_setup(char *str)
{
- strncpy(aoe_iflist, str, IFLISTSZ);
- aoe_iflist[IFLISTSZ - 1] = '\0';
+ strscpy(aoe_iflist, str, IFLISTSZ);
return 1;
}
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index cd738cab725f..50949207798d 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1760,8 +1760,10 @@ static int fd_locked_ioctl(struct block_device *bdev, blk_mode_t mode,
/* invalidate the buffer track to force a reread */
BufferDrive = -1;
set_bit(drive, &fake_change);
- if (disk_check_media_change(disk))
+ if (disk_check_media_change(disk)) {
+ bdev_mark_dead(disk->part0, true);
floppy_revalidate(disk);
+ }
return 0;
default:
return -EINVAL;
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index a30a5ed811be..c21e3732759e 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -524,7 +524,9 @@ struct drbd_md {
struct drbd_backing_dev {
struct block_device *backing_bdev;
+ struct bdev_handle *backing_bdev_handle;
struct block_device *md_bdev;
+ struct bdev_handle *md_bdev_handle;
struct drbd_md md;
struct disk_conf *disk_conf; /* RCU, for updates: resource->conf_update */
sector_t known_size; /* last known size of that backing device */
@@ -553,7 +555,7 @@ struct fifo_buffer {
unsigned int head_index;
unsigned int size;
int total; /* sum of all values */
- int values[];
+ int values[] __counted_by(size);
};
extern struct fifo_buffer *fifo_alloc(unsigned int fifo_size);
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index d3538bd83fb3..43747a1aae43 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -82,7 +82,7 @@ static atomic_t notify_genl_seq = ATOMIC_INIT(2); /* two. */
DEFINE_MUTEX(notification_mutex);
-/* used blkdev_get_by_path, to claim our meta data device(s) */
+/* used bdev_open_by_path, to claim our meta data device(s) */
static char *drbd_m_holder = "Hands off! this is DRBD's meta data device.";
static void drbd_adm_send_reply(struct sk_buff *skb, struct genl_info *info)
@@ -1635,43 +1635,45 @@ success:
return 0;
}
-static struct block_device *open_backing_dev(struct drbd_device *device,
+static struct bdev_handle *open_backing_dev(struct drbd_device *device,
const char *bdev_path, void *claim_ptr, bool do_bd_link)
{
- struct block_device *bdev;
+ struct bdev_handle *handle;
int err = 0;
- bdev = blkdev_get_by_path(bdev_path, BLK_OPEN_READ | BLK_OPEN_WRITE,
- claim_ptr, NULL);
- if (IS_ERR(bdev)) {
+ handle = bdev_open_by_path(bdev_path, BLK_OPEN_READ | BLK_OPEN_WRITE,
+ claim_ptr, NULL);
+ if (IS_ERR(handle)) {
drbd_err(device, "open(\"%s\") failed with %ld\n",
- bdev_path, PTR_ERR(bdev));
- return bdev;
+ bdev_path, PTR_ERR(handle));
+ return handle;
}
if (!do_bd_link)
- return bdev;
+ return handle;
- err = bd_link_disk_holder(bdev, device->vdisk);
+ err = bd_link_disk_holder(handle->bdev, device->vdisk);
if (err) {
- blkdev_put(bdev, claim_ptr);
+ bdev_release(handle);
drbd_err(device, "bd_link_disk_holder(\"%s\", ...) failed with %d\n",
bdev_path, err);
- bdev = ERR_PTR(err);
+ handle = ERR_PTR(err);
}
- return bdev;
+ return handle;
}
static int open_backing_devices(struct drbd_device *device,
struct disk_conf *new_disk_conf,
struct drbd_backing_dev *nbc)
{
- struct block_device *bdev;
+ struct bdev_handle *handle;
- bdev = open_backing_dev(device, new_disk_conf->backing_dev, device, true);
- if (IS_ERR(bdev))
+ handle = open_backing_dev(device, new_disk_conf->backing_dev, device,
+ true);
+ if (IS_ERR(handle))
return ERR_OPEN_DISK;
- nbc->backing_bdev = bdev;
+ nbc->backing_bdev = handle->bdev;
+ nbc->backing_bdev_handle = handle;
/*
* meta_dev_idx >= 0: external fixed size, possibly multiple
@@ -1681,7 +1683,7 @@ static int open_backing_devices(struct drbd_device *device,
* should check it for you already; but if you don't, or
* someone fooled it, we need to double check here)
*/
- bdev = open_backing_dev(device, new_disk_conf->meta_dev,
+ handle = open_backing_dev(device, new_disk_conf->meta_dev,
/* claim ptr: device, if claimed exclusively; shared drbd_m_holder,
* if potentially shared with other drbd minors */
(new_disk_conf->meta_dev_idx < 0) ? (void*)device : (void*)drbd_m_holder,
@@ -1689,20 +1691,21 @@ static int open_backing_devices(struct drbd_device *device,
* as would happen with internal metadata. */
(new_disk_conf->meta_dev_idx != DRBD_MD_INDEX_FLEX_INT &&
new_disk_conf->meta_dev_idx != DRBD_MD_INDEX_INTERNAL));
- if (IS_ERR(bdev))
+ if (IS_ERR(handle))
return ERR_OPEN_MD_DISK;
- nbc->md_bdev = bdev;
+ nbc->md_bdev = handle->bdev;
+ nbc->md_bdev_handle = handle;
return NO_ERROR;
}
-static void close_backing_dev(struct drbd_device *device, struct block_device *bdev,
- void *claim_ptr, bool do_bd_unlink)
+static void close_backing_dev(struct drbd_device *device,
+ struct bdev_handle *handle, bool do_bd_unlink)
{
- if (!bdev)
+ if (!handle)
return;
if (do_bd_unlink)
- bd_unlink_disk_holder(bdev, device->vdisk);
- blkdev_put(bdev, claim_ptr);
+ bd_unlink_disk_holder(handle->bdev, device->vdisk);
+ bdev_release(handle);
}
void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev *ldev)
@@ -1710,11 +1713,9 @@ void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev *
if (ldev == NULL)
return;
- close_backing_dev(device, ldev->md_bdev,
- ldev->md.meta_dev_idx < 0 ?
- (void *)device : (void *)drbd_m_holder,
+ close_backing_dev(device, ldev->md_bdev_handle,
ldev->md_bdev != ldev->backing_bdev);
- close_backing_dev(device, ldev->backing_bdev, device, true);
+ close_backing_dev(device, ldev->backing_bdev_handle, true);
kfree(ldev->disk_conf);
kfree(ldev);
@@ -2130,11 +2131,9 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
fail:
conn_reconfig_done(connection);
if (nbc) {
- close_backing_dev(device, nbc->md_bdev,
- nbc->disk_conf->meta_dev_idx < 0 ?
- (void *)device : (void *)drbd_m_holder,
+ close_backing_dev(device, nbc->md_bdev_handle,
nbc->md_bdev != nbc->backing_bdev);
- close_backing_dev(device, nbc->backing_bdev, device, true);
+ close_backing_dev(device, nbc->backing_bdev_handle, true);
kfree(nbc);
}
kfree(new_disk_conf);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index ea4eb88a2e45..11114a5d9e5c 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3215,8 +3215,10 @@ static int invalidate_drive(struct gendisk *disk)
/* invalidate the buffer track to force a reread */
set_bit((long)disk->private_data, &fake_change);
process_fd_request();
- if (disk_check_media_change(disk))
+ if (disk_check_media_change(disk)) {
+ bdev_mark_dead(disk->part0, true);
floppy_revalidate(disk);
+ }
return 0;
}
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 800f131222fc..b6414e1e645b 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -67,6 +67,7 @@ struct nbd_sock {
struct recv_thread_args {
struct work_struct work;
struct nbd_device *nbd;
+ struct nbd_sock *nsock;
int index;
};
@@ -250,7 +251,6 @@ static void nbd_dev_remove(struct nbd_device *nbd)
struct gendisk *disk = nbd->disk;
del_gendisk(disk);
- put_disk(disk);
blk_mq_free_tag_set(&nbd->tag_set);
/*
@@ -261,7 +261,7 @@ static void nbd_dev_remove(struct nbd_device *nbd)
idr_remove(&nbd_index_idr, nbd->index);
mutex_unlock(&nbd_index_mutex);
destroy_workqueue(nbd->recv_workq);
- kfree(nbd);
+ put_disk(disk);
}
static void nbd_dev_remove_work(struct work_struct *work)
@@ -396,6 +396,22 @@ static u32 req_to_nbd_cmd_type(struct request *req)
}
}
+static struct nbd_config *nbd_get_config_unlocked(struct nbd_device *nbd)
+{
+ if (refcount_inc_not_zero(&nbd->config_refs)) {
+ /*
+ * Add smp_mb__after_atomic to ensure that reading nbd->config_refs
+ * and reading nbd->config is ordered. The pair is the barrier in
+ * nbd_alloc_and_init_config(), avoid nbd->config_refs is set
+ * before nbd->config.
+ */
+ smp_mb__after_atomic();
+ return nbd->config;
+ }
+
+ return NULL;
+}
+
static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req)
{
struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
@@ -410,13 +426,13 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req)
return BLK_EH_DONE;
}
- if (!refcount_inc_not_zero(&nbd->config_refs)) {
+ config = nbd_get_config_unlocked(nbd);
+ if (!config) {
cmd->status = BLK_STS_TIMEOUT;
__clear_bit(NBD_CMD_INFLIGHT, &cmd->flags);
mutex_unlock(&cmd->lock);
goto done;
}
- config = nbd->config;
if (config->num_connections > 1 ||
(config->num_connections == 1 && nbd->tag_set.timeout)) {
@@ -490,15 +506,9 @@ done:
return BLK_EH_DONE;
}
-/*
- * Send or receive packet. Return a positive value on success and
- * negtive value on failue, and never return 0.
- */
-static int sock_xmit(struct nbd_device *nbd, int index, int send,
- struct iov_iter *iter, int msg_flags, int *sent)
+static int __sock_xmit(struct nbd_device *nbd, struct socket *sock, int send,
+ struct iov_iter *iter, int msg_flags, int *sent)
{
- struct nbd_config *config = nbd->config;
- struct socket *sock = config->socks[index]->sock;
int result;
struct msghdr msg;
unsigned int noreclaim_flag;
@@ -542,6 +552,19 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send,
}
/*
+ * Send or receive packet. Return a positive value on success and
+ * negtive value on failure, and never return 0.
+ */
+static int sock_xmit(struct nbd_device *nbd, int index, int send,
+ struct iov_iter *iter, int msg_flags, int *sent)
+{
+ struct nbd_config *config = nbd->config;
+ struct socket *sock = config->socks[index]->sock;
+
+ return __sock_xmit(nbd, sock, send, iter, msg_flags, sent);
+}
+
+/*
* Different settings for sk->sk_sndtimeo can result in different return values
* if there is a signal pending when we enter sendmsg, because reasons?
*/
@@ -697,7 +720,7 @@ out:
return 0;
}
-static int nbd_read_reply(struct nbd_device *nbd, int index,
+static int nbd_read_reply(struct nbd_device *nbd, struct socket *sock,
struct nbd_reply *reply)
{
struct kvec iov = {.iov_base = reply, .iov_len = sizeof(*reply)};
@@ -706,7 +729,7 @@ static int nbd_read_reply(struct nbd_device *nbd, int index,
reply->magic = 0;
iov_iter_kvec(&to, ITER_DEST, &iov, 1, sizeof(*reply));
- result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL);
+ result = __sock_xmit(nbd, sock, 0, &to, MSG_WAITALL, NULL);
if (result < 0) {
if (!nbd_disconnected(nbd->config))
dev_err(disk_to_dev(nbd->disk),
@@ -830,14 +853,14 @@ static void recv_work(struct work_struct *work)
struct nbd_device *nbd = args->nbd;
struct nbd_config *config = nbd->config;
struct request_queue *q = nbd->disk->queue;
- struct nbd_sock *nsock;
+ struct nbd_sock *nsock = args->nsock;
struct nbd_cmd *cmd;
struct request *rq;
while (1) {
struct nbd_reply reply;
- if (nbd_read_reply(nbd, args->index, &reply))
+ if (nbd_read_reply(nbd, nsock->sock, &reply))
break;
/*
@@ -872,7 +895,6 @@ static void recv_work(struct work_struct *work)
percpu_ref_put(&q->q_usage_counter);
}
- nsock = config->socks[args->index];
mutex_lock(&nsock->tx_lock);
nbd_mark_nsock_dead(nbd, nsock, 1);
mutex_unlock(&nsock->tx_lock);
@@ -978,12 +1000,12 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
struct nbd_sock *nsock;
int ret;
- if (!refcount_inc_not_zero(&nbd->config_refs)) {
+ config = nbd_get_config_unlocked(nbd);
+ if (!config) {
dev_err_ratelimited(disk_to_dev(nbd->disk),
"Socks array is empty\n");
return -EINVAL;
}
- config = nbd->config;
if (index >= config->num_connections) {
dev_err_ratelimited(disk_to_dev(nbd->disk),
@@ -1216,6 +1238,7 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
INIT_WORK(&args->work, recv_work);
args->index = i;
args->nbd = nbd;
+ args->nsock = nsock;
nsock->cookie++;
mutex_unlock(&nsock->tx_lock);
sockfd_put(old);
@@ -1398,6 +1421,7 @@ static int nbd_start_device(struct nbd_device *nbd)
refcount_inc(&nbd->config_refs);
INIT_WORK(&args->work, recv_work);
args->nbd = nbd;
+ args->nsock = config->socks[i];
args->index = i;
queue_work(nbd->recv_workq, &args->work);
}
@@ -1531,17 +1555,20 @@ static int nbd_ioctl(struct block_device *bdev, blk_mode_t mode,
return error;
}
-static struct nbd_config *nbd_alloc_config(void)
+static int nbd_alloc_and_init_config(struct nbd_device *nbd)
{
struct nbd_config *config;
+ if (WARN_ON(nbd->config))
+ return -EINVAL;
+
if (!try_module_get(THIS_MODULE))
- return ERR_PTR(-ENODEV);
+ return -ENODEV;
config = kzalloc(sizeof(struct nbd_config), GFP_NOFS);
if (!config) {
module_put(THIS_MODULE);
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
}
atomic_set(&config->recv_threads, 0);
@@ -1549,12 +1576,24 @@ static struct nbd_config *nbd_alloc_config(void)
init_waitqueue_head(&config->conn_wait);
config->blksize_bits = NBD_DEF_BLKSIZE_BITS;
atomic_set(&config->live_connections, 0);
- return config;
+
+ nbd->config = config;
+ /*
+ * Order refcount_set(&nbd->config_refs, 1) and nbd->config assignment,
+ * its pair is the barrier in nbd_get_config_unlocked().
+ * So nbd_get_config_unlocked() won't see nbd->config as null after
+ * refcount_inc_not_zero() succeed.
+ */
+ smp_mb__before_atomic();
+ refcount_set(&nbd->config_refs, 1);
+
+ return 0;
}
static int nbd_open(struct gendisk *disk, blk_mode_t mode)
{
struct nbd_device *nbd;
+ struct nbd_config *config;
int ret = 0;
mutex_lock(&nbd_index_mutex);
@@ -1567,27 +1606,25 @@ static int nbd_open(struct gendisk *disk, blk_mode_t mode)
ret = -ENXIO;
goto out;
}
- if (!refcount_inc_not_zero(&nbd->config_refs)) {
- struct nbd_config *config;
+ config = nbd_get_config_unlocked(nbd);
+ if (!config) {
mutex_lock(&nbd->config_lock);
if (refcount_inc_not_zero(&nbd->config_refs)) {
mutex_unlock(&nbd->config_lock);
goto out;
}
- config = nbd_alloc_config();
- if (IS_ERR(config)) {
- ret = PTR_ERR(config);
+ ret = nbd_alloc_and_init_config(nbd);
+ if (ret) {
mutex_unlock(&nbd->config_lock);
goto out;
}
- nbd->config = config;
- refcount_set(&nbd->config_refs, 1);
+
refcount_inc(&nbd->refs);
mutex_unlock(&nbd->config_lock);
if (max_part)
set_bit(GD_NEED_PART_SCAN, &disk->state);
- } else if (nbd_disconnected(nbd->config)) {
+ } else if (nbd_disconnected(config)) {
if (max_part)
set_bit(GD_NEED_PART_SCAN, &disk->state);
}
@@ -1608,6 +1645,13 @@ static void nbd_release(struct gendisk *disk)
nbd_put(nbd);
}
+static void nbd_free_disk(struct gendisk *disk)
+{
+ struct nbd_device *nbd = disk->private_data;
+
+ kfree(nbd);
+}
+
static const struct block_device_operations nbd_fops =
{
.owner = THIS_MODULE,
@@ -1615,6 +1659,7 @@ static const struct block_device_operations nbd_fops =
.release = nbd_release,
.ioctl = nbd_ioctl,
.compat_ioctl = nbd_ioctl,
+ .free_disk = nbd_free_disk,
};
#if IS_ENABLED(CONFIG_DEBUG_FS)
@@ -1983,22 +2028,17 @@ again:
pr_err("nbd%d already in use\n", index);
return -EBUSY;
}
- if (WARN_ON(nbd->config)) {
- mutex_unlock(&nbd->config_lock);
- nbd_put(nbd);
- return -EINVAL;
- }
- config = nbd_alloc_config();
- if (IS_ERR(config)) {
+
+ ret = nbd_alloc_and_init_config(nbd);
+ if (ret) {
mutex_unlock(&nbd->config_lock);
nbd_put(nbd);
pr_err("couldn't allocate config\n");
- return PTR_ERR(config);
+ return ret;
}
- nbd->config = config;
- refcount_set(&nbd->config_refs, 1);
- set_bit(NBD_RT_BOUND, &config->runtime_flags);
+ config = nbd->config;
+ set_bit(NBD_RT_BOUND, &config->runtime_flags);
ret = nbd_genl_size_set(info, nbd);
if (ret)
goto out;
@@ -2201,7 +2241,8 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
}
mutex_unlock(&nbd_index_mutex);
- if (!refcount_inc_not_zero(&nbd->config_refs)) {
+ config = nbd_get_config_unlocked(nbd);
+ if (!config) {
dev_err(nbd_to_dev(nbd),
"not configured, cannot reconfigure\n");
nbd_put(nbd);
@@ -2209,7 +2250,6 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
}
mutex_lock(&nbd->config_lock);
- config = nbd->config;
if (!test_bit(NBD_RT_BOUND, &config->runtime_flags) ||
!nbd->pid) {
dev_err(nbd_to_dev(nbd),
diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
index 968090935eb2..3021d58ca51c 100644
--- a/drivers/block/null_blk/main.c
+++ b/drivers/block/null_blk/main.c
@@ -1464,19 +1464,13 @@ blk_status_t null_process_cmd(struct nullb_cmd *cmd, enum req_op op,
return BLK_STS_OK;
}
-static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
- sector_t nr_sectors, enum req_op op)
+static void null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
+ sector_t nr_sectors, enum req_op op)
{
struct nullb_device *dev = cmd->nq->dev;
struct nullb *nullb = dev->nullb;
blk_status_t sts;
- if (test_bit(NULLB_DEV_FL_THROTTLED, &dev->flags)) {
- sts = null_handle_throttled(cmd);
- if (sts != BLK_STS_OK)
- return sts;
- }
-
if (op == REQ_OP_FLUSH) {
cmd->error = errno_to_blk_status(null_handle_flush(nullb));
goto out;
@@ -1493,7 +1487,6 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
out:
nullb_complete_cmd(cmd);
- return BLK_STS_OK;
}
static enum hrtimer_restart nullb_bwtimer_fn(struct hrtimer *timer)
@@ -1724,8 +1717,6 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
cmd->fake_timeout = should_timeout_request(rq) ||
blk_should_fake_timeout(rq->q);
- blk_mq_start_request(rq);
-
if (should_requeue_request(rq)) {
/*
* Alternate between hitting the core BUSY path, and the
@@ -1738,6 +1729,15 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
return BLK_STS_OK;
}
+ if (test_bit(NULLB_DEV_FL_THROTTLED, &nq->dev->flags)) {
+ blk_status_t sts = null_handle_throttled(cmd);
+
+ if (sts != BLK_STS_OK)
+ return sts;
+ }
+
+ blk_mq_start_request(rq);
+
if (is_poll) {
spin_lock(&nq->poll_lock);
list_add_tail(&rq->queuelist, &nq->poll_list);
@@ -1747,7 +1747,27 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
if (cmd->fake_timeout)
return BLK_STS_OK;
- return null_handle_cmd(cmd, sector, nr_sectors, req_op(rq));
+ null_handle_cmd(cmd, sector, nr_sectors, req_op(rq));
+ return BLK_STS_OK;
+}
+
+static void null_queue_rqs(struct request **rqlist)
+{
+ struct request *requeue_list = NULL;
+ struct request **requeue_lastp = &requeue_list;
+ struct blk_mq_queue_data bd = { };
+ blk_status_t ret;
+
+ do {
+ struct request *rq = rq_list_pop(rqlist);
+
+ bd.rq = rq;
+ ret = null_queue_rq(rq->mq_hctx, &bd);
+ if (ret != BLK_STS_OK)
+ rq_list_add_tail(&requeue_lastp, rq);
+ } while (!rq_list_empty(*rqlist));
+
+ *rqlist = requeue_list;
}
static void cleanup_queue(struct nullb_queue *nq)
@@ -1802,6 +1822,7 @@ static int null_init_hctx(struct blk_mq_hw_ctx *hctx, void *driver_data,
static const struct blk_mq_ops null_mq_ops = {
.queue_rq = null_queue_rq,
+ .queue_rqs = null_queue_rqs,
.complete = null_complete_rq,
.timeout = null_timeout_rq,
.poll = null_poll,
@@ -1946,7 +1967,7 @@ static int null_gendisk_register(struct nullb *nullb)
else
disk->fops = &null_bio_ops;
disk->private_data = nullb;
- strncpy(disk->disk_name, nullb->disk_name, DISK_NAME_LEN);
+ strscpy_pad(disk->disk_name, nullb->disk_name, DISK_NAME_LEN);
if (nullb->dev->zoned) {
int ret = null_register_zoned_dev(nullb);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index a1428538bda5..d56d972aadb3 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -340,8 +340,8 @@ static ssize_t device_map_show(const struct class *c, const struct class_attribu
n += sysfs_emit_at(data, n, "%s %u:%u %u:%u\n",
pd->disk->disk_name,
MAJOR(pd->pkt_dev), MINOR(pd->pkt_dev),
- MAJOR(pd->bdev->bd_dev),
- MINOR(pd->bdev->bd_dev));
+ MAJOR(pd->bdev_handle->bdev->bd_dev),
+ MINOR(pd->bdev_handle->bdev->bd_dev));
}
mutex_unlock(&ctl_mutex);
return n;
@@ -437,7 +437,8 @@ static int pkt_seq_show(struct seq_file *m, void *p)
char *msg;
int states[PACKET_NUM_STATES];
- seq_printf(m, "Writer %s mapped to %pg:\n", pd->disk->disk_name, pd->bdev);
+ seq_printf(m, "Writer %s mapped to %pg:\n", pd->disk->disk_name,
+ pd->bdev_handle->bdev);
seq_printf(m, "\nSettings:\n");
seq_printf(m, "\tpacket size:\t\t%dkB\n", pd->settings.size / 2);
@@ -714,7 +715,7 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod
*/
static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *cgc)
{
- struct request_queue *q = bdev_get_queue(pd->bdev);
+ struct request_queue *q = bdev_get_queue(pd->bdev_handle->bdev);
struct scsi_cmnd *scmd;
struct request *rq;
int ret = 0;
@@ -1047,7 +1048,8 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
continue;
bio = pkt->r_bios[f];
- bio_init(bio, pd->bdev, bio->bi_inline_vecs, 1, REQ_OP_READ);
+ bio_init(bio, pd->bdev_handle->bdev, bio->bi_inline_vecs, 1,
+ REQ_OP_READ);
bio->bi_iter.bi_sector = pkt->sector + f * (CD_FRAMESIZE >> 9);
bio->bi_end_io = pkt_end_io_read;
bio->bi_private = pkt;
@@ -1262,8 +1264,8 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
struct device *ddev = disk_to_dev(pd->disk);
int f;
- bio_init(pkt->w_bio, pd->bdev, pkt->w_bio->bi_inline_vecs, pkt->frames,
- REQ_OP_WRITE);
+ bio_init(pkt->w_bio, pd->bdev_handle->bdev, pkt->w_bio->bi_inline_vecs,
+ pkt->frames, REQ_OP_WRITE);
pkt->w_bio->bi_iter.bi_sector = pkt->sector;
pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
pkt->w_bio->bi_private = pkt;
@@ -2160,18 +2162,20 @@ static int pkt_open_dev(struct pktcdvd_device *pd, bool write)
int ret;
long lba;
struct request_queue *q;
- struct block_device *bdev;
+ struct bdev_handle *bdev_handle;
/*
* We need to re-open the cdrom device without O_NONBLOCK to be able
* to read/write from/to it. It is already opened in O_NONBLOCK mode
* so open should not fail.
*/
- bdev = blkdev_get_by_dev(pd->bdev->bd_dev, BLK_OPEN_READ, pd, NULL);
- if (IS_ERR(bdev)) {
- ret = PTR_ERR(bdev);
+ bdev_handle = bdev_open_by_dev(pd->bdev_handle->bdev->bd_dev,
+ BLK_OPEN_READ, pd, NULL);
+ if (IS_ERR(bdev_handle)) {
+ ret = PTR_ERR(bdev_handle);
goto out;
}
+ pd->open_bdev_handle = bdev_handle;
ret = pkt_get_last_written(pd, &lba);
if (ret) {
@@ -2180,9 +2184,9 @@ static int pkt_open_dev(struct pktcdvd_device *pd, bool write)
}
set_capacity(pd->disk, lba << 2);
- set_capacity_and_notify(pd->bdev->bd_disk, lba << 2);
+ set_capacity_and_notify(pd->bdev_handle->bdev->bd_disk, lba << 2);
- q = bdev_get_queue(pd->bdev);
+ q = bdev_get_queue(pd->bdev_handle->bdev);
if (write) {
ret = pkt_open_write(pd);
if (ret)
@@ -2214,7 +2218,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, bool write)
return 0;
out_putdev:
- blkdev_put(bdev, pd);
+ bdev_release(bdev_handle);
out:
return ret;
}
@@ -2233,7 +2237,8 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
pkt_lock_door(pd, 0);
pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
- blkdev_put(pd->bdev, pd);
+ bdev_release(pd->open_bdev_handle);
+ pd->open_bdev_handle = NULL;
pkt_shrink_pktlist(pd);
}
@@ -2321,8 +2326,8 @@ static void pkt_end_io_read_cloned(struct bio *bio)
static void pkt_make_request_read(struct pktcdvd_device *pd, struct bio *bio)
{
- struct bio *cloned_bio =
- bio_alloc_clone(pd->bdev, bio, GFP_NOIO, &pkt_bio_set);
+ struct bio *cloned_bio = bio_alloc_clone(pd->bdev_handle->bdev, bio,
+ GFP_NOIO, &pkt_bio_set);
struct packet_stacked_data *psd = mempool_alloc(&psd_pool, GFP_NOIO);
psd->pd = pd;
@@ -2492,7 +2497,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
{
struct device *ddev = disk_to_dev(pd->disk);
int i;
- struct block_device *bdev;
+ struct bdev_handle *bdev_handle;
struct scsi_device *sdev;
if (pd->pkt_dev == dev) {
@@ -2503,8 +2508,9 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
struct pktcdvd_device *pd2 = pkt_devs[i];
if (!pd2)
continue;
- if (pd2->bdev->bd_dev == dev) {
- dev_err(ddev, "%pg already setup\n", pd2->bdev);
+ if (pd2->bdev_handle->bdev->bd_dev == dev) {
+ dev_err(ddev, "%pg already setup\n",
+ pd2->bdev_handle->bdev);
return -EBUSY;
}
if (pd2->pkt_dev == dev) {
@@ -2513,13 +2519,13 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
}
}
- bdev = blkdev_get_by_dev(dev, BLK_OPEN_READ | BLK_OPEN_NDELAY, NULL,
- NULL);
- if (IS_ERR(bdev))
- return PTR_ERR(bdev);
- sdev = scsi_device_from_queue(bdev->bd_disk->queue);
+ bdev_handle = bdev_open_by_dev(dev, BLK_OPEN_READ | BLK_OPEN_NDELAY,
+ NULL, NULL);
+ if (IS_ERR(bdev_handle))
+ return PTR_ERR(bdev_handle);
+ sdev = scsi_device_from_queue(bdev_handle->bdev->bd_disk->queue);
if (!sdev) {
- blkdev_put(bdev, NULL);
+ bdev_release(bdev_handle);
return -EINVAL;
}
put_device(&sdev->sdev_gendev);
@@ -2527,8 +2533,8 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
/* This is safe, since we have a reference from open(). */
__module_get(THIS_MODULE);
- pd->bdev = bdev;
- set_blocksize(bdev, CD_FRAMESIZE);
+ pd->bdev_handle = bdev_handle;
+ set_blocksize(bdev_handle->bdev, CD_FRAMESIZE);
pkt_init_queue(pd);
@@ -2540,11 +2546,11 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
}
proc_create_single_data(pd->disk->disk_name, 0, pkt_proc, pkt_seq_show, pd);
- dev_notice(ddev, "writer mapped to %pg\n", bdev);
+ dev_notice(ddev, "writer mapped to %pg\n", bdev_handle->bdev);
return 0;
out_mem:
- blkdev_put(bdev, NULL);
+ bdev_release(bdev_handle);
/* This is safe: open() is still holding a reference. */
module_put(THIS_MODULE);
return -ENOMEM;
@@ -2599,9 +2605,9 @@ static unsigned int pkt_check_events(struct gendisk *disk,
if (!pd)
return 0;
- if (!pd->bdev)
+ if (!pd->bdev_handle)
return 0;
- attached_disk = pd->bdev->bd_disk;
+ attached_disk = pd->bdev_handle->bdev->bd_disk;
if (!attached_disk || !attached_disk->fops->check_events)
return 0;
return attached_disk->fops->check_events(attached_disk, clearing);
@@ -2686,7 +2692,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
goto out_mem2;
/* inherit events of the host device */
- disk->events = pd->bdev->bd_disk->events;
+ disk->events = pd->bdev_handle->bdev->bd_disk->events;
ret = add_disk(disk);
if (ret)
@@ -2751,7 +2757,7 @@ static int pkt_remove_dev(dev_t pkt_dev)
pkt_debugfs_dev_remove(pd);
pkt_sysfs_dev_remove(pd);
- blkdev_put(pd->bdev, NULL);
+ bdev_release(pd->bdev_handle);
remove_proc_entry(pd->disk->disk_name, pkt_proc);
dev_notice(ddev, "writer unmapped\n");
@@ -2778,7 +2784,7 @@ static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd)
pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index);
if (pd) {
- ctrl_cmd->dev = new_encode_dev(pd->bdev->bd_dev);
+ ctrl_cmd->dev = new_encode_dev(pd->bdev_handle->bdev->bd_dev);
ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev);
} else {
ctrl_cmd->dev = 0;
diff --git a/drivers/block/rnbd/rnbd-srv.c b/drivers/block/rnbd/rnbd-srv.c
index c186df0ec641..65de51f3dfd9 100644
--- a/drivers/block/rnbd/rnbd-srv.c
+++ b/drivers/block/rnbd/rnbd-srv.c
@@ -145,7 +145,7 @@ static int process_rdma(struct rnbd_srv_session *srv_sess,
priv->sess_dev = sess_dev;
priv->id = id;
- bio = bio_alloc(sess_dev->bdev, 1,
+ bio = bio_alloc(sess_dev->bdev_handle->bdev, 1,
rnbd_to_bio_flags(le32_to_cpu(msg->rw)), GFP_KERNEL);
if (bio_add_page(bio, virt_to_page(data), datalen,
offset_in_page(data)) != datalen) {
@@ -219,7 +219,7 @@ void rnbd_destroy_sess_dev(struct rnbd_srv_sess_dev *sess_dev, bool keep_id)
rnbd_put_sess_dev(sess_dev);
wait_for_completion(&dc); /* wait for inflights to drop to zero */
- blkdev_put(sess_dev->bdev, NULL);
+ bdev_release(sess_dev->bdev_handle);
mutex_lock(&sess_dev->dev->lock);
list_del(&sess_dev->dev_list);
if (!sess_dev->readonly)
@@ -534,7 +534,7 @@ rnbd_srv_get_or_create_srv_dev(struct block_device *bdev,
static void rnbd_srv_fill_msg_open_rsp(struct rnbd_msg_open_rsp *rsp,
struct rnbd_srv_sess_dev *sess_dev)
{
- struct block_device *bdev = sess_dev->bdev;
+ struct block_device *bdev = sess_dev->bdev_handle->bdev;
rsp->hdr.type = cpu_to_le16(RNBD_MSG_OPEN_RSP);
rsp->device_id = cpu_to_le32(sess_dev->device_id);
@@ -559,7 +559,7 @@ static void rnbd_srv_fill_msg_open_rsp(struct rnbd_msg_open_rsp *rsp,
static struct rnbd_srv_sess_dev *
rnbd_srv_create_set_sess_dev(struct rnbd_srv_session *srv_sess,
const struct rnbd_msg_open *open_msg,
- struct block_device *bdev, bool readonly,
+ struct bdev_handle *handle, bool readonly,
struct rnbd_srv_dev *srv_dev)
{
struct rnbd_srv_sess_dev *sdev = rnbd_sess_dev_alloc(srv_sess);
@@ -571,7 +571,7 @@ rnbd_srv_create_set_sess_dev(struct rnbd_srv_session *srv_sess,
strscpy(sdev->pathname, open_msg->dev_name, sizeof(sdev->pathname));
- sdev->bdev = bdev;
+ sdev->bdev_handle = handle;
sdev->sess = srv_sess;
sdev->dev = srv_dev;
sdev->readonly = readonly;
@@ -676,7 +676,7 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess,
struct rnbd_srv_dev *srv_dev;
struct rnbd_srv_sess_dev *srv_sess_dev;
const struct rnbd_msg_open *open_msg = msg;
- struct block_device *bdev;
+ struct bdev_handle *bdev_handle;
blk_mode_t open_flags = BLK_OPEN_READ;
char *full_path;
struct rnbd_msg_open_rsp *rsp = data;
@@ -714,15 +714,15 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess,
goto reject;
}
- bdev = blkdev_get_by_path(full_path, open_flags, NULL, NULL);
- if (IS_ERR(bdev)) {
- ret = PTR_ERR(bdev);
+ bdev_handle = bdev_open_by_path(full_path, open_flags, NULL, NULL);
+ if (IS_ERR(bdev_handle)) {
+ ret = PTR_ERR(bdev_handle);
pr_err("Opening device '%s' on session %s failed, failed to open the block device, err: %d\n",
full_path, srv_sess->sessname, ret);
goto free_path;
}
- srv_dev = rnbd_srv_get_or_create_srv_dev(bdev, srv_sess,
+ srv_dev = rnbd_srv_get_or_create_srv_dev(bdev_handle->bdev, srv_sess,
open_msg->access_mode);
if (IS_ERR(srv_dev)) {
pr_err("Opening device '%s' on session %s failed, creating srv_dev failed, err: %ld\n",
@@ -731,7 +731,8 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess,
goto blkdev_put;
}
- srv_sess_dev = rnbd_srv_create_set_sess_dev(srv_sess, open_msg, bdev,
+ srv_sess_dev = rnbd_srv_create_set_sess_dev(srv_sess, open_msg,
+ bdev_handle,
open_msg->access_mode == RNBD_ACCESS_RO,
srv_dev);
if (IS_ERR(srv_sess_dev)) {
@@ -747,7 +748,7 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess,
*/
mutex_lock(&srv_dev->lock);
if (!srv_dev->dev_kobj.state_in_sysfs) {
- ret = rnbd_srv_create_dev_sysfs(srv_dev, bdev);
+ ret = rnbd_srv_create_dev_sysfs(srv_dev, bdev_handle->bdev);
if (ret) {
mutex_unlock(&srv_dev->lock);
rnbd_srv_err(srv_sess_dev,
@@ -790,7 +791,7 @@ srv_dev_put:
}
rnbd_put_srv_dev(srv_dev);
blkdev_put:
- blkdev_put(bdev, NULL);
+ bdev_release(bdev_handle);
free_path:
kfree(full_path);
reject:
diff --git a/drivers/block/rnbd/rnbd-srv.h b/drivers/block/rnbd/rnbd-srv.h
index 1027656dedb0..343cc682b617 100644
--- a/drivers/block/rnbd/rnbd-srv.h
+++ b/drivers/block/rnbd/rnbd-srv.h
@@ -46,7 +46,7 @@ struct rnbd_srv_dev {
struct rnbd_srv_sess_dev {
/* Entry inside rnbd_srv_dev struct */
struct list_head dev_list;
- struct block_device *bdev;
+ struct bdev_handle *bdev_handle;
struct rnbd_srv_session *sess;
struct rnbd_srv_dev *dev;
struct kobject kobj;
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 630ddfe6657b..83600b45e12a 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -75,6 +75,7 @@ struct ublk_rq_data {
struct ublk_uring_cmd_pdu {
struct ublk_queue *ubq;
+ u16 tag;
};
/*
@@ -115,6 +116,9 @@ struct ublk_uring_cmd_pdu {
*/
#define UBLK_IO_FLAG_NEED_GET_DATA 0x08
+/* atomic RW with ubq->cancel_lock */
+#define UBLK_IO_FLAG_CANCELED 0x80000000
+
struct ublk_io {
/* userspace buffer address from io cmd */
__u64 addr;
@@ -138,13 +142,13 @@ struct ublk_queue {
unsigned int max_io_sz;
bool force_abort;
bool timeout;
+ bool canceling;
unsigned short nr_io_ready; /* how many ios setup */
+ spinlock_t cancel_lock;
struct ublk_device *dev;
struct ublk_io ios[];
};
-#define UBLK_DAEMON_MONITOR_PERIOD (5 * HZ)
-
struct ublk_device {
struct gendisk *ub_disk;
@@ -166,7 +170,7 @@ struct ublk_device {
struct mutex mutex;
- spinlock_t mm_lock;
+ spinlock_t lock;
struct mm_struct *mm;
struct ublk_params params;
@@ -175,11 +179,6 @@ struct ublk_device {
unsigned int nr_queues_ready;
unsigned int nr_privileged_daemon;
- /*
- * Our ubq->daemon may be killed without any notification, so
- * monitor each queue's daemon periodically
- */
- struct delayed_work monitor_work;
struct work_struct quiesce_work;
struct work_struct stop_work;
};
@@ -190,10 +189,11 @@ struct ublk_params_header {
__u32 types;
};
+static bool ublk_abort_requests(struct ublk_device *ub, struct ublk_queue *ubq);
+
static inline unsigned int ublk_req_build_flags(struct request *req);
static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq,
int tag);
-
static inline bool ublk_dev_is_user_copy(const struct ublk_device *ub)
{
return ub->dev_info.flags & UBLK_F_USER_COPY;
@@ -470,6 +470,7 @@ static DEFINE_MUTEX(ublk_ctl_mutex);
* It can be extended to one per-user limit in future or even controlled
* by cgroup.
*/
+#define UBLK_MAX_UBLKS UBLK_MINORS
static unsigned int ublks_max = 64;
static unsigned int ublks_added; /* protected by ublk_ctl_mutex */
@@ -1083,13 +1084,10 @@ static void __ublk_fail_req(struct ublk_queue *ubq, struct ublk_io *io,
{
WARN_ON_ONCE(io->flags & UBLK_IO_FLAG_ACTIVE);
- if (!(io->flags & UBLK_IO_FLAG_ABORTED)) {
- io->flags |= UBLK_IO_FLAG_ABORTED;
- if (ublk_queue_can_use_recovery_reissue(ubq))
- blk_mq_requeue_request(req, false);
- else
- ublk_put_req_ref(ubq, req);
- }
+ if (ublk_queue_can_use_recovery_reissue(ubq))
+ blk_mq_requeue_request(req, false);
+ else
+ ublk_put_req_ref(ubq, req);
}
static void ubq_complete_io_cmd(struct ublk_io *io, int res,
@@ -1118,8 +1116,6 @@ static inline void __ublk_abort_rq(struct ublk_queue *ubq,
blk_mq_requeue_request(rq, false);
else
blk_mq_end_request(rq, BLK_STS_IOERR);
-
- mod_delayed_work(system_wq, &ubq->dev->monitor_work, 0);
}
static inline void __ublk_rq_task_work(struct request *req,
@@ -1212,15 +1208,6 @@ static inline void ublk_forward_io_cmds(struct ublk_queue *ubq,
__ublk_rq_task_work(blk_mq_rq_from_pdu(data), issue_flags);
}
-static inline void ublk_abort_io_cmds(struct ublk_queue *ubq)
-{
- struct llist_node *io_cmds = llist_del_all(&ubq->io_cmds);
- struct ublk_rq_data *data, *tmp;
-
- llist_for_each_entry_safe(data, tmp, io_cmds, node)
- __ublk_abort_rq(ubq, blk_mq_rq_from_pdu(data));
-}
-
static void ublk_rq_task_work_cb(struct io_uring_cmd *cmd, unsigned issue_flags)
{
struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
@@ -1232,38 +1219,19 @@ static void ublk_rq_task_work_cb(struct io_uring_cmd *cmd, unsigned issue_flags)
static void ublk_queue_cmd(struct ublk_queue *ubq, struct request *rq)
{
struct ublk_rq_data *data = blk_mq_rq_to_pdu(rq);
- struct ublk_io *io;
- if (!llist_add(&data->node, &ubq->io_cmds))
- return;
+ if (llist_add(&data->node, &ubq->io_cmds)) {
+ struct ublk_io *io = &ubq->ios[rq->tag];
- io = &ubq->ios[rq->tag];
- /*
- * If the check pass, we know that this is a re-issued request aborted
- * previously in monitor_work because the ubq_daemon(cmd's task) is
- * PF_EXITING. We cannot call io_uring_cmd_complete_in_task() anymore
- * because this ioucmd's io_uring context may be freed now if no inflight
- * ioucmd exists. Otherwise we may cause null-deref in ctx->fallback_work.
- *
- * Note: monitor_work sets UBLK_IO_FLAG_ABORTED and ends this request(releasing
- * the tag). Then the request is re-started(allocating the tag) and we are here.
- * Since releasing/allocating a tag implies smp_mb(), finding UBLK_IO_FLAG_ABORTED
- * guarantees that here is a re-issued request aborted previously.
- */
- if (unlikely(io->flags & UBLK_IO_FLAG_ABORTED)) {
- ublk_abort_io_cmds(ubq);
- } else {
- struct io_uring_cmd *cmd = io->cmd;
- struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
-
- pdu->ubq = ubq;
- io_uring_cmd_complete_in_task(cmd, ublk_rq_task_work_cb);
+ io_uring_cmd_complete_in_task(io->cmd, ublk_rq_task_work_cb);
}
}
static enum blk_eh_timer_return ublk_timeout(struct request *rq)
{
struct ublk_queue *ubq = rq->mq_hctx->driver_data;
+ unsigned int nr_inflight = 0;
+ int i;
if (ubq->flags & UBLK_F_UNPRIVILEGED_DEV) {
if (!ubq->timeout) {
@@ -1274,6 +1242,29 @@ static enum blk_eh_timer_return ublk_timeout(struct request *rq)
return BLK_EH_DONE;
}
+ if (!ubq_daemon_is_dying(ubq))
+ return BLK_EH_RESET_TIMER;
+
+ for (i = 0; i < ubq->q_depth; i++) {
+ struct ublk_io *io = &ubq->ios[i];
+
+ if (!(io->flags & UBLK_IO_FLAG_ACTIVE))
+ nr_inflight++;
+ }
+
+ /* cancelable uring_cmd can't help us if all commands are in-flight */
+ if (nr_inflight == ubq->q_depth) {
+ struct ublk_device *ub = ubq->dev;
+
+ if (ublk_abort_requests(ub, ubq)) {
+ if (ublk_can_use_recovery(ub))
+ schedule_work(&ub->quiesce_work);
+ else
+ schedule_work(&ub->stop_work);
+ }
+ return BLK_EH_DONE;
+ }
+
return BLK_EH_RESET_TIMER;
}
@@ -1301,13 +1292,12 @@ static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx,
if (ublk_queue_can_use_recovery(ubq) && unlikely(ubq->force_abort))
return BLK_STS_IOERR;
- blk_mq_start_request(bd->rq);
-
- if (unlikely(ubq_daemon_is_dying(ubq))) {
+ if (unlikely(ubq->canceling)) {
__ublk_abort_rq(ubq, rq);
return BLK_STS_OK;
}
+ blk_mq_start_request(bd->rq);
ublk_queue_cmd(ubq, rq);
return BLK_STS_OK;
@@ -1357,12 +1347,12 @@ static int ublk_ch_mmap(struct file *filp, struct vm_area_struct *vma)
unsigned long pfn, end, phys_off = vma->vm_pgoff << PAGE_SHIFT;
int q_id, ret = 0;
- spin_lock(&ub->mm_lock);
+ spin_lock(&ub->lock);
if (!ub->mm)
ub->mm = current->mm;
if (current->mm != ub->mm)
ret = -EINVAL;
- spin_unlock(&ub->mm_lock);
+ spin_unlock(&ub->lock);
if (ret)
return ret;
@@ -1411,17 +1401,14 @@ static void ublk_commit_completion(struct ublk_device *ub,
}
/*
- * When ->ubq_daemon is exiting, either new request is ended immediately,
- * or any queued io command is drained, so it is safe to abort queue
- * lockless
+ * Called from ubq_daemon context via cancel fn, meantime quiesce ublk
+ * blk-mq queue, so we are called exclusively with blk-mq and ubq_daemon
+ * context, so everything is serialized.
*/
static void ublk_abort_queue(struct ublk_device *ub, struct ublk_queue *ubq)
{
int i;
- if (!ublk_get_device(ub))
- return;
-
for (i = 0; i < ubq->q_depth; i++) {
struct ublk_io *io = &ubq->ios[i];
@@ -1433,72 +1420,114 @@ static void ublk_abort_queue(struct ublk_device *ub, struct ublk_queue *ubq)
* will do it
*/
rq = blk_mq_tag_to_rq(ub->tag_set.tags[ubq->q_id], i);
- if (rq)
+ if (rq && blk_mq_request_started(rq)) {
+ io->flags |= UBLK_IO_FLAG_ABORTED;
__ublk_fail_req(ubq, io, rq);
+ }
}
}
- ublk_put_device(ub);
}
-static void ublk_daemon_monitor_work(struct work_struct *work)
+static bool ublk_abort_requests(struct ublk_device *ub, struct ublk_queue *ubq)
{
- struct ublk_device *ub =
- container_of(work, struct ublk_device, monitor_work.work);
- int i;
+ struct gendisk *disk;
- for (i = 0; i < ub->dev_info.nr_hw_queues; i++) {
- struct ublk_queue *ubq = ublk_get_queue(ub, i);
+ spin_lock(&ubq->cancel_lock);
+ if (ubq->canceling) {
+ spin_unlock(&ubq->cancel_lock);
+ return false;
+ }
+ ubq->canceling = true;
+ spin_unlock(&ubq->cancel_lock);
- if (ubq_daemon_is_dying(ubq)) {
- if (ublk_queue_can_use_recovery(ubq))
- schedule_work(&ub->quiesce_work);
- else
- schedule_work(&ub->stop_work);
+ spin_lock(&ub->lock);
+ disk = ub->ub_disk;
+ if (disk)
+ get_device(disk_to_dev(disk));
+ spin_unlock(&ub->lock);
- /* abort queue is for making forward progress */
- ublk_abort_queue(ub, ubq);
- }
- }
+ /* Our disk has been dead */
+ if (!disk)
+ return false;
- /*
- * We can't schedule monitor work after ub's state is not UBLK_S_DEV_LIVE.
- * after ublk_remove() or __ublk_quiesce_dev() is started.
- *
- * No need ub->mutex, monitor work are canceled after state is marked
- * as not LIVE, so new state is observed reliably.
- */
- if (ub->dev_info.state == UBLK_S_DEV_LIVE)
- schedule_delayed_work(&ub->monitor_work,
- UBLK_DAEMON_MONITOR_PERIOD);
-}
+ /* Now we are serialized with ublk_queue_rq() */
+ blk_mq_quiesce_queue(disk->queue);
+ /* abort queue is for making forward progress */
+ ublk_abort_queue(ub, ubq);
+ blk_mq_unquiesce_queue(disk->queue);
+ put_device(disk_to_dev(disk));
-static inline bool ublk_queue_ready(struct ublk_queue *ubq)
-{
- return ubq->nr_io_ready == ubq->q_depth;
+ return true;
}
-static void ublk_cmd_cancel_cb(struct io_uring_cmd *cmd, unsigned issue_flags)
+static void ublk_cancel_cmd(struct ublk_queue *ubq, struct ublk_io *io,
+ unsigned int issue_flags)
{
- io_uring_cmd_done(cmd, UBLK_IO_RES_ABORT, 0, issue_flags);
+ bool done;
+
+ if (!(io->flags & UBLK_IO_FLAG_ACTIVE))
+ return;
+
+ spin_lock(&ubq->cancel_lock);
+ done = !!(io->flags & UBLK_IO_FLAG_CANCELED);
+ if (!done)
+ io->flags |= UBLK_IO_FLAG_CANCELED;
+ spin_unlock(&ubq->cancel_lock);
+
+ if (!done)
+ io_uring_cmd_done(io->cmd, UBLK_IO_RES_ABORT, 0, issue_flags);
}
-static void ublk_cancel_queue(struct ublk_queue *ubq)
+/*
+ * The ublk char device won't be closed when calling cancel fn, so both
+ * ublk device and queue are guaranteed to be live
+ */
+static void ublk_uring_cmd_cancel_fn(struct io_uring_cmd *cmd,
+ unsigned int issue_flags)
{
- int i;
+ struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
+ struct ublk_queue *ubq = pdu->ubq;
+ struct task_struct *task;
+ struct ublk_device *ub;
+ bool need_schedule;
+ struct ublk_io *io;
- if (!ublk_queue_ready(ubq))
+ if (WARN_ON_ONCE(!ubq))
return;
- for (i = 0; i < ubq->q_depth; i++) {
- struct ublk_io *io = &ubq->ios[i];
+ if (WARN_ON_ONCE(pdu->tag >= ubq->q_depth))
+ return;
+
+ task = io_uring_cmd_get_task(cmd);
+ if (WARN_ON_ONCE(task && task != ubq->ubq_daemon))
+ return;
+
+ ub = ubq->dev;
+ need_schedule = ublk_abort_requests(ub, ubq);
+
+ io = &ubq->ios[pdu->tag];
+ WARN_ON_ONCE(io->cmd != cmd);
+ ublk_cancel_cmd(ubq, io, issue_flags);
- if (io->flags & UBLK_IO_FLAG_ACTIVE)
- io_uring_cmd_complete_in_task(io->cmd,
- ublk_cmd_cancel_cb);
+ if (need_schedule) {
+ if (ublk_can_use_recovery(ub))
+ schedule_work(&ub->quiesce_work);
+ else
+ schedule_work(&ub->stop_work);
}
+}
- /* all io commands are canceled */
- ubq->nr_io_ready = 0;
+static inline bool ublk_queue_ready(struct ublk_queue *ubq)
+{
+ return ubq->nr_io_ready == ubq->q_depth;
+}
+
+static void ublk_cancel_queue(struct ublk_queue *ubq)
+{
+ int i;
+
+ for (i = 0; i < ubq->q_depth; i++)
+ ublk_cancel_cmd(ubq, &ubq->ios[i], IO_URING_F_UNLOCKED);
}
/* Cancel all pending commands, must be called after del_gendisk() returns */
@@ -1545,16 +1574,6 @@ static void __ublk_quiesce_dev(struct ublk_device *ub)
blk_mq_quiesce_queue(ub->ub_disk->queue);
ublk_wait_tagset_rqs_idle(ub);
ub->dev_info.state = UBLK_S_DEV_QUIESCED;
- ublk_cancel_dev(ub);
- /* we are going to release task_struct of ubq_daemon and resets
- * ->ubq_daemon to NULL. So in monitor_work, check on ubq_daemon causes UAF.
- * Besides, monitor_work is not necessary in QUIESCED state since we have
- * already scheduled quiesce_work and quiesced all ubqs.
- *
- * Do not let monitor_work schedule itself if state it QUIESCED. And we cancel
- * it here and re-schedule it in END_USER_RECOVERY to avoid UAF.
- */
- cancel_delayed_work_sync(&ub->monitor_work);
}
static void ublk_quiesce_work_fn(struct work_struct *work)
@@ -1568,6 +1587,7 @@ static void ublk_quiesce_work_fn(struct work_struct *work)
__ublk_quiesce_dev(ub);
unlock:
mutex_unlock(&ub->mutex);
+ ublk_cancel_dev(ub);
}
static void ublk_unquiesce_dev(struct ublk_device *ub)
@@ -1593,6 +1613,8 @@ static void ublk_unquiesce_dev(struct ublk_device *ub)
static void ublk_stop_dev(struct ublk_device *ub)
{
+ struct gendisk *disk;
+
mutex_lock(&ub->mutex);
if (ub->dev_info.state == UBLK_S_DEV_DEAD)
goto unlock;
@@ -1602,14 +1624,18 @@ static void ublk_stop_dev(struct ublk_device *ub)
ublk_unquiesce_dev(ub);
}
del_gendisk(ub->ub_disk);
+
+ /* Sync with ublk_abort_queue() by holding the lock */
+ spin_lock(&ub->lock);
+ disk = ub->ub_disk;
ub->dev_info.state = UBLK_S_DEV_DEAD;
ub->dev_info.ublksrv_pid = -1;
- put_disk(ub->ub_disk);
ub->ub_disk = NULL;
+ spin_unlock(&ub->lock);
+ put_disk(disk);
unlock:
- ublk_cancel_dev(ub);
mutex_unlock(&ub->mutex);
- cancel_delayed_work_sync(&ub->monitor_work);
+ ublk_cancel_dev(ub);
}
/* device can only be started after all IOs are ready */
@@ -1660,6 +1686,21 @@ static inline void ublk_fill_io_cmd(struct ublk_io *io,
io->addr = buf_addr;
}
+static inline void ublk_prep_cancel(struct io_uring_cmd *cmd,
+ unsigned int issue_flags,
+ struct ublk_queue *ubq, unsigned int tag)
+{
+ struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
+
+ /*
+ * Safe to refer to @ubq since ublk_queue won't be died until its
+ * commands are completed
+ */
+ pdu->ubq = ubq;
+ pdu->tag = tag;
+ io_uring_cmd_mark_cancelable(cmd, issue_flags);
+}
+
static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
unsigned int issue_flags,
const struct ublksrv_io_cmd *ub_cmd)
@@ -1775,6 +1816,7 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
default:
goto out;
}
+ ublk_prep_cancel(cmd, issue_flags, ubq, tag);
return -EIOCBQUEUED;
out:
@@ -1814,7 +1856,8 @@ fail_put:
return NULL;
}
-static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
+static inline int ublk_ch_uring_cmd_local(struct io_uring_cmd *cmd,
+ unsigned int issue_flags)
{
/*
* Not necessary for async retry, but let's keep it simple and always
@@ -1828,9 +1871,33 @@ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
.addr = READ_ONCE(ub_src->addr)
};
+ WARN_ON_ONCE(issue_flags & IO_URING_F_UNLOCKED);
+
return __ublk_ch_uring_cmd(cmd, issue_flags, &ub_cmd);
}
+static void ublk_ch_uring_cmd_cb(struct io_uring_cmd *cmd,
+ unsigned int issue_flags)
+{
+ ublk_ch_uring_cmd_local(cmd, issue_flags);
+}
+
+static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
+{
+ if (unlikely(issue_flags & IO_URING_F_CANCEL)) {
+ ublk_uring_cmd_cancel_fn(cmd, issue_flags);
+ return 0;
+ }
+
+ /* well-implemented server won't run into unlocked */
+ if (unlikely(issue_flags & IO_URING_F_UNLOCKED)) {
+ io_uring_cmd_complete_in_task(cmd, ublk_ch_uring_cmd_cb);
+ return -EIOCBQUEUED;
+ }
+
+ return ublk_ch_uring_cmd_local(cmd, issue_flags);
+}
+
static inline bool ublk_check_ubuf_dir(const struct request *req,
int ubuf_dir)
{
@@ -1962,6 +2029,7 @@ static int ublk_init_queue(struct ublk_device *ub, int q_id)
void *ptr;
int size;
+ spin_lock_init(&ubq->cancel_lock);
ubq->flags = ub->dev_info.flags;
ubq->q_id = q_id;
ubq->q_depth = ub->dev_info.queue_depth;
@@ -2026,7 +2094,8 @@ static int ublk_alloc_dev_number(struct ublk_device *ub, int idx)
if (err == -ENOSPC)
err = -EEXIST;
} else {
- err = idr_alloc(&ublk_index_idr, ub, 0, 0, GFP_NOWAIT);
+ err = idr_alloc(&ublk_index_idr, ub, 0, UBLK_MAX_UBLKS,
+ GFP_NOWAIT);
}
spin_unlock(&ublk_idr_lock);
@@ -2151,8 +2220,6 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd)
if (wait_for_completion_interruptible(&ub->completion) != 0)
return -EINTR;
- schedule_delayed_work(&ub->monitor_work, UBLK_DAEMON_MONITOR_PERIOD);
-
mutex_lock(&ub->mutex);
if (ub->dev_info.state == UBLK_S_DEV_LIVE ||
test_bit(UB_STATE_USED, &ub->state)) {
@@ -2305,6 +2372,12 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
return -EINVAL;
}
+ if (header->dev_id != U32_MAX && header->dev_id >= UBLK_MAX_UBLKS) {
+ pr_warn("%s: dev id is too large. Max supported is %d\n",
+ __func__, UBLK_MAX_UBLKS - 1);
+ return -EINVAL;
+ }
+
ublk_dump_dev_info(&info);
ret = mutex_lock_killable(&ublk_ctl_mutex);
@@ -2320,10 +2393,9 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
if (!ub)
goto out_unlock;
mutex_init(&ub->mutex);
- spin_lock_init(&ub->mm_lock);
+ spin_lock_init(&ub->lock);
INIT_WORK(&ub->quiesce_work, ublk_quiesce_work_fn);
INIT_WORK(&ub->stop_work, ublk_stop_work_fn);
- INIT_DELAYED_WORK(&ub->monitor_work, ublk_daemon_monitor_work);
ret = ublk_alloc_dev_number(ub, header->dev_id);
if (ret < 0)
@@ -2569,13 +2641,15 @@ static void ublk_queue_reinit(struct ublk_device *ub, struct ublk_queue *ubq)
int i;
WARN_ON_ONCE(!(ubq->ubq_daemon && ubq_daemon_is_dying(ubq)));
+
/* All old ioucmds have to be completed */
- WARN_ON_ONCE(ubq->nr_io_ready);
+ ubq->nr_io_ready = 0;
/* old daemon is PF_EXITING, put it now */
put_task_struct(ubq->ubq_daemon);
/* We have to reset it to NULL, otherwise ub won't accept new FETCH_REQ */
ubq->ubq_daemon = NULL;
ubq->timeout = false;
+ ubq->canceling = false;
for (i = 0; i < ubq->q_depth; i++) {
struct ublk_io *io = &ubq->ios[i];
@@ -2661,7 +2735,6 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub,
__func__, header->dev_id);
blk_mq_kick_requeue_list(ub->ub_disk->queue);
ub->dev_info.state = UBLK_S_DEV_LIVE;
- schedule_delayed_work(&ub->monitor_work, UBLK_DAEMON_MONITOR_PERIOD);
ret = 0;
out_unlock:
mutex_unlock(&ub->mutex);
@@ -2932,7 +3005,22 @@ static void __exit ublk_exit(void)
module_init(ublk_init);
module_exit(ublk_exit);
-module_param(ublks_max, int, 0444);
+static int ublk_set_max_ublks(const char *buf, const struct kernel_param *kp)
+{
+ return param_set_uint_minmax(buf, kp, 0, UBLK_MAX_UBLKS);
+}
+
+static int ublk_get_max_ublks(char *buf, const struct kernel_param *kp)
+{
+ return sysfs_emit(buf, "%u\n", ublks_max);
+}
+
+static const struct kernel_param_ops ublk_max_ublks_ops = {
+ .set = ublk_set_max_ublks,
+ .get = ublk_get_max_ublks,
+};
+
+module_param_cb(ublks_max, &ublk_max_ublks_ops, &ublks_max, 0644);
MODULE_PARM_DESC(ublks_max, "max number of ublk devices allowed to add(default: 64)");
MODULE_AUTHOR("Ming Lei <ming.lei@redhat.com>");
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 1fe011676d07..d53d6aa8ee69 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -470,8 +470,6 @@ static bool virtblk_prep_rq_batch(struct request *req)
struct virtio_blk *vblk = req->mq_hctx->queue->queuedata;
struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
- req->mq_hctx->tags->rqs[req->tag] = req;
-
return virtblk_prep_rq(req->mq_hctx, vblk, req, vbr) == BLK_STS_OK;
}
@@ -1313,6 +1311,7 @@ static int virtblk_probe(struct virtio_device *vdev)
u16 min_io_size;
u8 physical_block_exp, alignment_offset;
unsigned int queue_depth;
+ size_t max_dma_size;
if (!vdev->config->get) {
dev_err(&vdev->dev, "%s failure: config access disabled\n",
@@ -1411,7 +1410,8 @@ static int virtblk_probe(struct virtio_device *vdev)
/* No real sector limit. */
blk_queue_max_hw_sectors(q, UINT_MAX);
- max_size = virtio_max_dma_size(vdev);
+ max_dma_size = virtio_max_dma_size(vdev);
+ max_size = max_dma_size > U32_MAX ? U32_MAX : max_dma_size;
/* Host can optionally specify maximum segment size and number of
* segments. */
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index c362f4ad80ab..4defd7f387c7 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -465,7 +465,7 @@ static int xen_vbd_translate(struct phys_req *req, struct xen_blkif *blkif,
}
req->dev = vbd->pdevice;
- req->bdev = vbd->bdev;
+ req->bdev = vbd->bdev_handle->bdev;
rc = 0;
out:
@@ -969,7 +969,7 @@ static int dispatch_discard_io(struct xen_blkif_ring *ring,
int err = 0;
int status = BLKIF_RSP_OKAY;
struct xen_blkif *blkif = ring->blkif;
- struct block_device *bdev = blkif->vbd.bdev;
+ struct block_device *bdev = blkif->vbd.bdev_handle->bdev;
struct phys_req preq;
xen_blkif_get(blkif);
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index 40f67bfc052d..5ff50e76cee5 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -221,7 +221,7 @@ struct xen_vbd {
unsigned char type;
/* phys device that this vbd maps to. */
u32 pdevice;
- struct block_device *bdev;
+ struct bdev_handle *bdev_handle;
/* Cached size parameter. */
sector_t size;
unsigned int flush_support:1;
@@ -360,7 +360,7 @@ struct pending_req {
};
-#define vbd_sz(_v) bdev_nr_sectors((_v)->bdev)
+#define vbd_sz(_v) bdev_nr_sectors((_v)->bdev_handle->bdev)
#define xen_blkif_get(_b) (atomic_inc(&(_b)->refcnt))
#define xen_blkif_put(_b) \
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index bb66178c432b..e34219ea2b05 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -81,7 +81,7 @@ static void xen_update_blkif_status(struct xen_blkif *blkif)
int i;
/* Not ready to connect? */
- if (!blkif->rings || !blkif->rings[0].irq || !blkif->vbd.bdev)
+ if (!blkif->rings || !blkif->rings[0].irq || !blkif->vbd.bdev_handle)
return;
/* Already connected? */
@@ -99,12 +99,13 @@ static void xen_update_blkif_status(struct xen_blkif *blkif)
return;
}
- err = sync_blockdev(blkif->vbd.bdev);
+ err = sync_blockdev(blkif->vbd.bdev_handle->bdev);
if (err) {
xenbus_dev_error(blkif->be->dev, err, "block flush");
return;
}
- invalidate_inode_pages2(blkif->vbd.bdev->bd_inode->i_mapping);
+ invalidate_inode_pages2(
+ blkif->vbd.bdev_handle->bdev->bd_inode->i_mapping);
for (i = 0; i < blkif->nr_rings; i++) {
ring = &blkif->rings[i];
@@ -472,9 +473,9 @@ static void xenvbd_sysfs_delif(struct xenbus_device *dev)
static void xen_vbd_free(struct xen_vbd *vbd)
{
- if (vbd->bdev)
- blkdev_put(vbd->bdev, NULL);
- vbd->bdev = NULL;
+ if (vbd->bdev_handle)
+ bdev_release(vbd->bdev_handle);
+ vbd->bdev_handle = NULL;
}
static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
@@ -482,7 +483,7 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
int cdrom)
{
struct xen_vbd *vbd;
- struct block_device *bdev;
+ struct bdev_handle *bdev_handle;
vbd = &blkif->vbd;
vbd->handle = handle;
@@ -491,17 +492,17 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
vbd->pdevice = MKDEV(major, minor);
- bdev = blkdev_get_by_dev(vbd->pdevice, vbd->readonly ?
+ bdev_handle = bdev_open_by_dev(vbd->pdevice, vbd->readonly ?
BLK_OPEN_READ : BLK_OPEN_WRITE, NULL, NULL);
- if (IS_ERR(bdev)) {
+ if (IS_ERR(bdev_handle)) {
pr_warn("xen_vbd_create: device %08x could not be opened\n",
vbd->pdevice);
return -ENOENT;
}
- vbd->bdev = bdev;
- if (vbd->bdev->bd_disk == NULL) {
+ vbd->bdev_handle = bdev_handle;
+ if (vbd->bdev_handle->bdev->bd_disk == NULL) {
pr_warn("xen_vbd_create: device %08x doesn't exist\n",
vbd->pdevice);
xen_vbd_free(vbd);
@@ -509,14 +510,14 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
}
vbd->size = vbd_sz(vbd);
- if (cdrom || disk_to_cdi(vbd->bdev->bd_disk))
+ if (cdrom || disk_to_cdi(vbd->bdev_handle->bdev->bd_disk))
vbd->type |= VDISK_CDROM;
- if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
+ if (vbd->bdev_handle->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
vbd->type |= VDISK_REMOVABLE;
- if (bdev_write_cache(bdev))
+ if (bdev_write_cache(bdev_handle->bdev))
vbd->flush_support = true;
- if (bdev_max_secure_erase_sectors(bdev))
+ if (bdev_max_secure_erase_sectors(bdev_handle->bdev))
vbd->discard_secure = true;
pr_debug("Successful creation of handle=%04x (dom=%u)\n",
@@ -569,7 +570,7 @@ static void xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info
struct xen_blkif *blkif = be->blkif;
int err;
int state = 0;
- struct block_device *bdev = be->blkif->vbd.bdev;
+ struct block_device *bdev = be->blkif->vbd.bdev_handle->bdev;
if (!xenbus_read_unsigned(dev->nodename, "discard-enable", 1))
return;
@@ -930,15 +931,16 @@ again:
goto abort;
}
err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu",
- (unsigned long)
- bdev_logical_block_size(be->blkif->vbd.bdev));
+ (unsigned long)bdev_logical_block_size(
+ be->blkif->vbd.bdev_handle->bdev));
if (err) {
xenbus_dev_fatal(dev, err, "writing %s/sector-size",
dev->nodename);
goto abort;
}
err = xenbus_printf(xbt, dev->nodename, "physical-sector-size", "%u",
- bdev_physical_block_size(be->blkif->vbd.bdev));
+ bdev_physical_block_size(
+ be->blkif->vbd.bdev_handle->bdev));
if (err)
xenbus_dev_error(dev, err, "writing %s/physical-sector-size",
dev->nodename);
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 06673c6ca255..d77d3664ca08 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -414,17 +414,14 @@ static ssize_t writeback_limit_show(struct device *dev,
static void reset_bdev(struct zram *zram)
{
- struct block_device *bdev;
-
if (!zram->backing_dev)
return;
- bdev = zram->bdev;
- blkdev_put(bdev, zram);
+ bdev_release(zram->bdev_handle);
/* hope filp_close flush all of IO */
filp_close(zram->backing_dev, NULL);
zram->backing_dev = NULL;
- zram->bdev = NULL;
+ zram->bdev_handle = NULL;
zram->disk->fops = &zram_devops;
kvfree(zram->bitmap);
zram->bitmap = NULL;
@@ -470,7 +467,7 @@ static ssize_t backing_dev_store(struct device *dev,
struct address_space *mapping;
unsigned int bitmap_sz;
unsigned long nr_pages, *bitmap = NULL;
- struct block_device *bdev = NULL;
+ struct bdev_handle *bdev_handle = NULL;
int err;
struct zram *zram = dev_to_zram(dev);
@@ -507,11 +504,11 @@ static ssize_t backing_dev_store(struct device *dev,
goto out;
}
- bdev = blkdev_get_by_dev(inode->i_rdev, BLK_OPEN_READ | BLK_OPEN_WRITE,
- zram, NULL);
- if (IS_ERR(bdev)) {
- err = PTR_ERR(bdev);
- bdev = NULL;
+ bdev_handle = bdev_open_by_dev(inode->i_rdev,
+ BLK_OPEN_READ | BLK_OPEN_WRITE, zram, NULL);
+ if (IS_ERR(bdev_handle)) {
+ err = PTR_ERR(bdev_handle);
+ bdev_handle = NULL;
goto out;
}
@@ -525,7 +522,7 @@ static ssize_t backing_dev_store(struct device *dev,
reset_bdev(zram);
- zram->bdev = bdev;
+ zram->bdev_handle = bdev_handle;
zram->backing_dev = backing_dev;
zram->bitmap = bitmap;
zram->nr_pages = nr_pages;
@@ -538,8 +535,8 @@ static ssize_t backing_dev_store(struct device *dev,
out:
kvfree(bitmap);
- if (bdev)
- blkdev_put(bdev, zram);
+ if (bdev_handle)
+ bdev_release(bdev_handle);
if (backing_dev)
filp_close(backing_dev, NULL);
@@ -581,7 +578,7 @@ static void read_from_bdev_async(struct zram *zram, struct page *page,
{
struct bio *bio;
- bio = bio_alloc(zram->bdev, 1, parent->bi_opf, GFP_NOIO);
+ bio = bio_alloc(zram->bdev_handle->bdev, 1, parent->bi_opf, GFP_NOIO);
bio->bi_iter.bi_sector = entry * (PAGE_SIZE >> 9);
__bio_add_page(bio, page, PAGE_SIZE, 0);
bio_chain(bio, parent);
@@ -697,7 +694,7 @@ static ssize_t writeback_store(struct device *dev,
continue;
}
- bio_init(&bio, zram->bdev, &bio_vec, 1,
+ bio_init(&bio, zram->bdev_handle->bdev, &bio_vec, 1,
REQ_OP_WRITE | REQ_SYNC);
bio.bi_iter.bi_sector = blk_idx * (PAGE_SIZE >> 9);
__bio_add_page(&bio, page, PAGE_SIZE, 0);
@@ -779,7 +776,7 @@ static void zram_sync_read(struct work_struct *work)
struct bio_vec bv;
struct bio bio;
- bio_init(&bio, zw->zram->bdev, &bv, 1, REQ_OP_READ);
+ bio_init(&bio, zw->zram->bdev_handle->bdev, &bv, 1, REQ_OP_READ);
bio.bi_iter.bi_sector = zw->entry * (PAGE_SIZE >> 9);
__bio_add_page(&bio, zw->page, PAGE_SIZE, 0);
zw->error = submit_bio_wait(&bio);
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index ca7a15bd4845..d090753f97be 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -132,7 +132,7 @@ struct zram {
spinlock_t wb_limit_lock;
bool wb_limit_enable;
u64 bd_wb_limit;
- struct block_device *bdev;
+ struct bdev_handle *bdev_handle;
unsigned long *bitmap;
unsigned long nr_pages;
#endif
diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index f9a3444753c2..ff4868c83cd8 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -118,6 +118,7 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table);
#define BTMTKSDIO_FUNC_ENABLED 3
#define BTMTKSDIO_PATCH_ENABLED 4
#define BTMTKSDIO_HW_RESET_ACTIVE 5
+#define BTMTKSDIO_BT_WAKE_ENABLED 6
struct mtkbtsdio_hdr {
__le16 len;
@@ -554,7 +555,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
sdio_claim_host(bdev->func);
/* Disable interrupt */
- sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0);
+ sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
txrx_timeout = jiffies + 5 * HZ;
@@ -576,7 +577,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
if ((int_status & FW_MAILBOX_INT) &&
bdev->data->chipid == 0x7921) {
sdio_writel(bdev->func, PH2DSM0R_DRIVER_OWN,
- MTK_REG_PH2DSM0R, 0);
+ MTK_REG_PH2DSM0R, NULL);
}
if (int_status & FW_OWN_BACK_INT)
@@ -608,7 +609,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
} while (int_status || time_is_before_jiffies(txrx_timeout));
/* Enable interrupt */
- sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, 0);
+ sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
sdio_release_host(bdev->func);
@@ -620,8 +621,14 @@ static void btmtksdio_interrupt(struct sdio_func *func)
{
struct btmtksdio_dev *bdev = sdio_get_drvdata(func);
+ if (test_bit(BTMTKSDIO_BT_WAKE_ENABLED, &bdev->tx_state)) {
+ if (bdev->hdev->suspended)
+ pm_wakeup_event(bdev->dev, 0);
+ clear_bit(BTMTKSDIO_BT_WAKE_ENABLED, &bdev->tx_state);
+ }
+
/* Disable interrupt */
- sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0);
+ sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
schedule_work(&bdev->txrx_work);
}
@@ -1454,6 +1461,23 @@ static int btmtksdio_runtime_suspend(struct device *dev)
return err;
}
+static int btmtksdio_system_suspend(struct device *dev)
+{
+ struct sdio_func *func = dev_to_sdio_func(dev);
+ struct btmtksdio_dev *bdev;
+
+ bdev = sdio_get_drvdata(func);
+ if (!bdev)
+ return 0;
+
+ if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state))
+ return 0;
+
+ set_bit(BTMTKSDIO_BT_WAKE_ENABLED, &bdev->tx_state);
+
+ return btmtksdio_runtime_suspend(dev);
+}
+
static int btmtksdio_runtime_resume(struct device *dev)
{
struct sdio_func *func = dev_to_sdio_func(dev);
@@ -1474,8 +1498,16 @@ static int btmtksdio_runtime_resume(struct device *dev)
return err;
}
-static UNIVERSAL_DEV_PM_OPS(btmtksdio_pm_ops, btmtksdio_runtime_suspend,
- btmtksdio_runtime_resume, NULL);
+static int btmtksdio_system_resume(struct device *dev)
+{
+ return btmtksdio_runtime_resume(dev);
+}
+
+static const struct dev_pm_ops btmtksdio_pm_ops = {
+ SYSTEM_SLEEP_PM_OPS(btmtksdio_system_suspend, btmtksdio_system_resume)
+ RUNTIME_PM_OPS(btmtksdio_runtime_suspend, btmtksdio_runtime_resume, NULL)
+};
+
#define BTMTKSDIO_PM_OPS (&btmtksdio_pm_ops)
#else /* CONFIG_PM */
#define BTMTKSDIO_PM_OPS NULL
diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index 5a35ac4138c6..fdb0fae88d1c 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -205,6 +205,44 @@ static int qca_send_reset(struct hci_dev *hdev)
return 0;
}
+static int qca_read_fw_board_id(struct hci_dev *hdev, u16 *bid)
+{
+ u8 cmd;
+ struct sk_buff *skb;
+ struct edl_event_hdr *edl;
+ int err = 0;
+
+ cmd = EDL_GET_BID_REQ_CMD;
+ skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN,
+ &cmd, 0, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ bt_dev_err(hdev, "Reading QCA board ID failed (%d)", err);
+ return err;
+ }
+
+ edl = skb_pull_data(skb, sizeof(*edl));
+ if (!edl) {
+ bt_dev_err(hdev, "QCA read board ID with no header");
+ err = -EILSEQ;
+ goto out;
+ }
+
+ if (edl->cresp != EDL_CMD_REQ_RES_EVT ||
+ edl->rtype != EDL_GET_BID_REQ_CMD) {
+ bt_dev_err(hdev, "QCA Wrong packet: %d %d", edl->cresp, edl->rtype);
+ err = -EIO;
+ goto out;
+ }
+
+ *bid = (edl->data[1] << 8) + edl->data[2];
+ bt_dev_dbg(hdev, "%s: bid = %x", __func__, *bid);
+
+out:
+ kfree_skb(skb);
+ return err;
+}
+
int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
{
struct sk_buff *skb;
@@ -574,6 +612,23 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
}
EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
+static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size,
+ struct qca_btsoc_version ver, u8 rom_ver, u16 bid)
+{
+ const char *variant;
+
+ /* hsp gf chip */
+ if ((le32_to_cpu(ver.soc_id) & QCA_HSP_GF_SOC_MASK) == QCA_HSP_GF_SOC_ID)
+ variant = "g";
+ else
+ variant = "";
+
+ if (bid == 0x0)
+ snprintf(fwname, max_size, "qca/hpnv%02x%s.bin", rom_ver, variant);
+ else
+ snprintf(fwname, max_size, "qca/hpnv%02x%s.%x", rom_ver, variant, bid);
+}
+
int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
const char *firmware_name)
@@ -582,6 +637,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
int err;
u8 rom_ver = 0;
u32 soc_ver;
+ u16 boardid = 0;
bt_dev_dbg(hdev, "QCA setup on UART");
@@ -615,6 +671,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
snprintf(config.fwname, sizeof(config.fwname),
"qca/apbtfw%02x.tlv", rom_ver);
break;
+ case QCA_QCA2066:
+ snprintf(config.fwname, sizeof(config.fwname),
+ "qca/hpbtfw%02x.tlv", rom_ver);
+ break;
case QCA_QCA6390:
snprintf(config.fwname, sizeof(config.fwname),
"qca/htbtfw%02x.tlv", rom_ver);
@@ -649,6 +709,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
/* Give the controller some time to get ready to receive the NVM */
msleep(10);
+ if (soc_type == QCA_QCA2066)
+ qca_read_fw_board_id(hdev, &boardid);
+
/* Download NVM configuration */
config.type = TLV_TYPE_NVM;
if (firmware_name) {
@@ -671,6 +734,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
snprintf(config.fwname, sizeof(config.fwname),
"qca/apnv%02x.bin", rom_ver);
break;
+ case QCA_QCA2066:
+ qca_generate_hsp_nvm_name(config.fwname,
+ sizeof(config.fwname), ver, rom_ver, boardid);
+ break;
case QCA_QCA6390:
snprintf(config.fwname, sizeof(config.fwname),
"qca/htnv%02x.bin", rom_ver);
@@ -702,6 +769,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
switch (soc_type) {
case QCA_WCN3991:
+ case QCA_QCA2066:
case QCA_QCA6390:
case QCA_WCN6750:
case QCA_WCN6855:
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
index 03bff5c0059d..dc31984f71dc 100644
--- a/drivers/bluetooth/btqca.h
+++ b/drivers/bluetooth/btqca.h
@@ -12,6 +12,7 @@
#define EDL_PATCH_VER_REQ_CMD (0x19)
#define EDL_PATCH_TLV_REQ_CMD (0x1E)
#define EDL_GET_BUILD_INFO_CMD (0x20)
+#define EDL_GET_BID_REQ_CMD (0x23)
#define EDL_NVM_ACCESS_SET_REQ_CMD (0x01)
#define EDL_PATCH_CONFIG_CMD (0x28)
#define MAX_SIZE_PER_TLV_SEGMENT (243)
@@ -47,7 +48,8 @@
((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver)))
#define QCA_FW_BUILD_VER_LEN 255
-
+#define QCA_HSP_GF_SOC_ID 0x1200
+#define QCA_HSP_GF_SOC_MASK 0x0000ff00
enum qca_baudrate {
QCA_BAUDRATE_115200 = 0,
@@ -146,6 +148,7 @@ enum qca_btsoc_type {
QCA_WCN3990,
QCA_WCN3998,
QCA_WCN3991,
+ QCA_QCA2066,
QCA_QCA6390,
QCA_WCN6750,
QCA_WCN6855,
diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c
index 84c2c2e1122f..277d039ecbb4 100644
--- a/drivers/bluetooth/btrtl.c
+++ b/drivers/bluetooth/btrtl.c
@@ -962,13 +962,10 @@ static void btrtl_dmp_hdr(struct hci_dev *hdev, struct sk_buff *skb)
skb_put_data(skb, buf, strlen(buf));
}
-static int btrtl_register_devcoredump_support(struct hci_dev *hdev)
+static void btrtl_register_devcoredump_support(struct hci_dev *hdev)
{
- int err;
+ hci_devcd_register(hdev, btrtl_coredump, btrtl_dmp_hdr, NULL);
- err = hci_devcd_register(hdev, btrtl_coredump, btrtl_dmp_hdr, NULL);
-
- return err;
}
void btrtl_set_driver_name(struct hci_dev *hdev, const char *driver_name)
@@ -1255,8 +1252,7 @@ int btrtl_download_firmware(struct hci_dev *hdev,
}
done:
- if (!err)
- err = btrtl_register_devcoredump_support(hdev);
+ btrtl_register_devcoredump_support(hdev);
return err;
}
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 499f4809fcdf..b8e9de887b5d 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -477,6 +477,7 @@ static const struct usb_device_id quirks_table[] = {
{ USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED },
{ USB_DEVICE(0x8087, 0x0035), .driver_info = BTUSB_INTEL_COMBINED },
{ USB_DEVICE(0x8087, 0x0036), .driver_info = BTUSB_INTEL_COMBINED },
+ { USB_DEVICE(0x8087, 0x0038), .driver_info = BTUSB_INTEL_COMBINED },
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED |
BTUSB_INTEL_NO_WBS_SUPPORT |
@@ -543,6 +544,10 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK |
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x13d3, 0x3570), .driver_info = BTUSB_REALTEK |
+ BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
@@ -644,6 +649,9 @@ static const struct usb_device_id quirks_table[] = {
{ USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
+ { USB_DEVICE(0x35f5, 0x7922), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH |
+ BTUSB_VALID_LE_STATES },
/* Additional Realtek 8723AE Bluetooth devices */
{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
@@ -2818,6 +2826,9 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
goto err_free_wc;
}
+ if (data->evt_skb == NULL)
+ goto err_free_wc;
+
/* Parse and handle the return WMT event */
wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
if (wmt_evt->whdr.op != hdr->op) {
diff --git a/drivers/bluetooth/hci_bcm4377.c b/drivers/bluetooth/hci_bcm4377.c
index 19ad0e788646..a61757835695 100644
--- a/drivers/bluetooth/hci_bcm4377.c
+++ b/drivers/bluetooth/hci_bcm4377.c
@@ -512,6 +512,7 @@ struct bcm4377_hw {
unsigned long disable_aspm : 1;
unsigned long broken_ext_scan : 1;
unsigned long broken_mws_transport_config : 1;
+ unsigned long broken_le_coded : 1;
int (*send_calibration)(struct bcm4377_data *bcm4377);
int (*send_ptb)(struct bcm4377_data *bcm4377,
@@ -2372,6 +2373,8 @@ static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id)
set_bit(HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG, &hdev->quirks);
if (bcm4377->hw->broken_ext_scan)
set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
+ if (bcm4377->hw->broken_le_coded)
+ set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks);
pci_set_drvdata(pdev, bcm4377);
hci_set_drvdata(hdev, bcm4377);
@@ -2461,6 +2464,7 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = {
.bar0_core2_window2 = 0x18107000,
.has_bar0_core2_window2 = true,
.broken_mws_transport_config = true,
+ .broken_le_coded = true,
.send_calibration = bcm4378_send_calibration,
.send_ptb = bcm4378_send_ptb,
},
@@ -2474,6 +2478,7 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = {
.has_bar0_core2_window2 = true,
.clear_pciecfg_subsystem_ctrl_bit19 = true,
.broken_mws_transport_config = true,
+ .broken_le_coded = true,
.send_calibration = bcm4387_send_calibration,
.send_ptb = bcm4378_send_ptb,
},
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 4b57e15f9c7a..067e248e3599 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -1841,6 +1841,10 @@ static int qca_setup(struct hci_uart *hu)
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
switch (soc_type) {
+ case QCA_QCA2066:
+ soc_name = "qca2066";
+ break;
+
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -2032,6 +2036,11 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = {
.num_vregs = 4,
};
+static const struct qca_device_data qca_soc_data_qca2066 __maybe_unused = {
+ .soc_type = QCA_QCA2066,
+ .num_vregs = 0,
+};
+
static const struct qca_device_data qca_soc_data_qca6390 __maybe_unused = {
.soc_type = QCA_QCA6390,
.num_vregs = 0,
@@ -2559,6 +2568,7 @@ static SIMPLE_DEV_PM_OPS(qca_pm_ops, qca_suspend, qca_resume);
#ifdef CONFIG_OF
static const struct of_device_id qca_bluetooth_of_match[] = {
+ { .compatible = "qcom,qca2066-bt", .data = &qca_soc_data_qca2066},
{ .compatible = "qcom,qca6174-bt" },
{ .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390},
{ .compatible = "qcom,qca9377-bt" },
@@ -2576,6 +2586,7 @@ MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match);
#ifdef CONFIG_ACPI
static const struct acpi_device_id qca_bluetooth_acpi_match[] = {
+ { "QCOM2066", (kernel_ulong_t)&qca_soc_data_qca2066 },
{ "QCOM6390", (kernel_ulong_t)&qca_soc_data_qca6390 },
{ "DLA16390", (kernel_ulong_t)&qca_soc_data_qca6390 },
{ "DLB16390", (kernel_ulong_t)&qca_soc_data_qca6390 },
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 40e2b9fa11a2..f3892e9ce800 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -74,7 +74,10 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
struct vhci_data *data = hci_get_drvdata(hdev);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
+
+ mutex_lock(&data->open_mutex);
skb_queue_tail(&data->readq, skb);
+ mutex_unlock(&data->open_mutex);
wake_up_interruptible(&data->read_wait);
return 0;
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index c98dd6ca2629..e6742998f372 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -31,7 +31,7 @@ config ARM_INTEGRATOR_LM
config BRCMSTB_GISB_ARB
tristate "Broadcom STB GISB bus arbiter"
- depends on ARM || ARM64 || MIPS
+ depends on ARCH_BRCMSTB || BMIPS_GENERIC
default ARCH_BRCMSTB || BMIPS_GENERIC
help
Driver for the Broadcom Set Top Box System-on-a-chip internal bus
diff --git a/drivers/bus/fsl-mc/dprc.c b/drivers/bus/fsl-mc/dprc.c
index d129338b8bc0..dd1b5c0fb7e2 100644
--- a/drivers/bus/fsl-mc/dprc.c
+++ b/drivers/bus/fsl-mc/dprc.c
@@ -450,10 +450,8 @@ int dprc_get_obj(struct fsl_mc_io *mc_io,
obj_desc->ver_major = le16_to_cpu(rsp_params->version_major);
obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor);
obj_desc->flags = le16_to_cpu(rsp_params->flags);
- strncpy(obj_desc->type, rsp_params->type, 16);
- obj_desc->type[15] = '\0';
- strncpy(obj_desc->label, rsp_params->label, 16);
- obj_desc->label[15] = '\0';
+ strscpy_pad(obj_desc->type, rsp_params->type, 16);
+ strscpy_pad(obj_desc->label, rsp_params->label, 16);
return 0;
}
EXPORT_SYMBOL_GPL(dprc_get_obj);
@@ -491,8 +489,7 @@ int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
cmd_params->obj_id = cpu_to_le32(obj_id);
- strncpy(cmd_params->obj_type, obj_type, 16);
- cmd_params->obj_type[15] = '\0';
+ strscpy_pad(cmd_params->obj_type, obj_type, 16);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
@@ -564,8 +561,7 @@ int dprc_get_obj_region(struct fsl_mc_io *mc_io,
cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params;
cmd_params->obj_id = cpu_to_le32(obj_id);
cmd_params->region_index = region_index;
- strncpy(cmd_params->obj_type, obj_type, 16);
- cmd_params->obj_type[15] = '\0';
+ strscpy_pad(cmd_params->obj_type, obj_type, 16);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
diff --git a/drivers/bus/vexpress-config.c b/drivers/bus/vexpress-config.c
index c4e1becbb2d2..d2c7ada90186 100644
--- a/drivers/bus/vexpress-config.c
+++ b/drivers/bus/vexpress-config.c
@@ -54,7 +54,7 @@ struct vexpress_syscfg_func {
struct vexpress_syscfg *syscfg;
struct regmap *regmap;
int num_templates;
- u32 template[]; /* Keep it last! */
+ u32 template[] __counted_by(num_templates); /* Keep it last! */
};
struct vexpress_config_bridge_ops {
diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig
index a57677f908f3..d6e5e3abaad8 100644
--- a/drivers/cache/Kconfig
+++ b/drivers/cache/Kconfig
@@ -3,7 +3,7 @@ menu "Cache Drivers"
config AX45MP_L2_CACHE
bool "Andes Technology AX45MP L2 Cache controller"
- depends on RISCV_DMA_NONCOHERENT
+ depends on RISCV
select RISCV_NONSTANDARD_CACHE_OPS
help
Support for the L2 cache controller on Andes Technology AX45MP platforms.
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index cc2839805983..a5e07270e0d4 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -3655,7 +3655,6 @@ static struct ctl_table cdrom_table[] = {
.mode = 0644,
.proc_handler = cdrom_sysctl_handler
},
- { }
};
static struct ctl_table_header *cdrom_sysctl_header;
diff --git a/drivers/cdx/Makefile b/drivers/cdx/Makefile
index 0324e4914f6e..5d1ea482419f 100644
--- a/drivers/cdx/Makefile
+++ b/drivers/cdx/Makefile
@@ -5,4 +5,6 @@
# Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
#
+ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=CDX_BUS
+
obj-$(CONFIG_CDX_BUS) += cdx.o controller/
diff --git a/drivers/cdx/cdx.c b/drivers/cdx/cdx.c
index d2cad4c670a0..4461c6c9313f 100644
--- a/drivers/cdx/cdx.c
+++ b/drivers/cdx/cdx.c
@@ -60,7 +60,7 @@
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/mm.h>
-#include <linux/xarray.h>
+#include <linux/idr.h>
#include <linux/cdx/cdx_bus.h>
#include <linux/iommu.h>
#include <linux/dma-map-ops.h>
@@ -70,8 +70,12 @@
#define CDX_DEFAULT_DMA_MASK (~0ULL)
#define MAX_CDX_CONTROLLERS 16
-/* CDX controllers registered with the CDX bus */
-static DEFINE_XARRAY_ALLOC(cdx_controllers);
+/* IDA for CDX controllers registered with the CDX bus */
+static DEFINE_IDA(cdx_controller_ida);
+/* Lock to protect controller ops */
+static DEFINE_MUTEX(cdx_controller_lock);
+
+static char *compat_node_name = "xlnx,versal-net-cdx";
/**
* cdx_dev_reset - Reset a CDX device
@@ -107,6 +111,20 @@ int cdx_dev_reset(struct device *dev)
EXPORT_SYMBOL_GPL(cdx_dev_reset);
/**
+ * reset_cdx_device - Reset a CDX device
+ * @dev: CDX device
+ * @data: This is always passed as NULL, and is not used in this API,
+ * but is required here as the device_for_each_child() API expects
+ * the passed function to have this as an argument.
+ *
+ * Return: -errno on failure, 0 on success.
+ */
+static int reset_cdx_device(struct device *dev, void *data)
+{
+ return cdx_dev_reset(dev);
+}
+
+/**
* cdx_unregister_device - Unregister a CDX device
* @dev: CDX device
* @data: This is always passed as NULL, and is not used in this API,
@@ -120,9 +138,17 @@ static int cdx_unregister_device(struct device *dev,
void *data)
{
struct cdx_device *cdx_dev = to_cdx_device(dev);
+ struct cdx_controller *cdx = cdx_dev->cdx;
+
+ if (cdx_dev->is_bus) {
+ device_for_each_child(dev, NULL, cdx_unregister_device);
+ if (cdx_dev->enabled && cdx->ops->bus_disable)
+ cdx->ops->bus_disable(cdx, cdx_dev->bus_num);
+ } else {
+ kfree(cdx_dev->driver_override);
+ cdx_dev->driver_override = NULL;
+ }
- kfree(cdx_dev->driver_override);
- cdx_dev->driver_override = NULL;
/*
* Do not free cdx_dev here as it would be freed in
* cdx_device_release() called from within put_device().
@@ -153,7 +179,10 @@ cdx_match_one_device(const struct cdx_device_id *id,
{
/* Use vendor ID and device ID for matching */
if ((id->vendor == CDX_ANY_ID || id->vendor == dev->vendor) &&
- (id->device == CDX_ANY_ID || id->device == dev->device))
+ (id->device == CDX_ANY_ID || id->device == dev->device) &&
+ (id->subvendor == CDX_ANY_ID || id->subvendor == dev->subsystem_vendor) &&
+ (id->subdevice == CDX_ANY_ID || id->subdevice == dev->subsystem_device) &&
+ !((id->class ^ dev->class) & id->class_mask))
return id;
return NULL;
}
@@ -182,6 +211,38 @@ cdx_match_id(const struct cdx_device_id *ids, struct cdx_device *dev)
return NULL;
}
+int cdx_set_master(struct cdx_device *cdx_dev)
+{
+ struct cdx_controller *cdx = cdx_dev->cdx;
+ struct cdx_device_config dev_config;
+ int ret = -EOPNOTSUPP;
+
+ dev_config.type = CDX_DEV_BUS_MASTER_CONF;
+ dev_config.bus_master_enable = true;
+ if (cdx->ops->dev_configure)
+ ret = cdx->ops->dev_configure(cdx, cdx_dev->bus_num,
+ cdx_dev->dev_num, &dev_config);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cdx_set_master);
+
+int cdx_clear_master(struct cdx_device *cdx_dev)
+{
+ struct cdx_controller *cdx = cdx_dev->cdx;
+ struct cdx_device_config dev_config;
+ int ret = -EOPNOTSUPP;
+
+ dev_config.type = CDX_DEV_BUS_MASTER_CONF;
+ dev_config.bus_master_enable = false;
+ if (cdx->ops->dev_configure)
+ ret = cdx->ops->dev_configure(cdx, cdx_dev->bus_num,
+ cdx_dev->dev_num, &dev_config);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cdx_clear_master);
+
/**
* cdx_bus_match - device to driver matching callback
* @dev: the cdx device to match against
@@ -197,6 +258,9 @@ static int cdx_bus_match(struct device *dev, struct device_driver *drv)
const struct cdx_device_id *found_id = NULL;
const struct cdx_device_id *ids;
+ if (cdx_dev->is_bus)
+ return false;
+
ids = cdx_drv->match_id_table;
/* When driver_override is set, only bind to the matching driver */
@@ -261,10 +325,11 @@ static int cdx_dma_configure(struct device *dev)
{
struct cdx_driver *cdx_drv = to_cdx_driver(dev->driver);
struct cdx_device *cdx_dev = to_cdx_device(dev);
+ struct cdx_controller *cdx = cdx_dev->cdx;
u32 input_id = cdx_dev->req_id;
int ret;
- ret = of_dma_configure_id(dev, dev->parent->of_node, 0, &input_id);
+ ret = of_dma_configure_id(dev, cdx->dev->of_node, 0, &input_id);
if (ret && ret != -EPROBE_DEFER) {
dev_err(dev, "of_dma_configure_id() failed\n");
return ret;
@@ -299,6 +364,10 @@ static DEVICE_ATTR_RO(field)
cdx_config_attr(vendor, "0x%04x\n");
cdx_config_attr(device, "0x%04x\n");
+cdx_config_attr(subsystem_vendor, "0x%04x\n");
+cdx_config_attr(subsystem_device, "0x%04x\n");
+cdx_config_attr(revision, "0x%02x\n");
+cdx_config_attr(class, "0x%06x\n");
static ssize_t remove_store(struct device *dev,
struct device_attribute *attr,
@@ -327,6 +396,7 @@ static DEVICE_ATTR_WO(remove);
static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
+ struct cdx_device *cdx_dev = to_cdx_device(dev);
bool val;
int ret;
@@ -336,14 +406,27 @@ static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
if (!val)
return -EINVAL;
- ret = cdx_dev_reset(dev);
- if (ret)
- return ret;
+ if (cdx_dev->is_bus)
+ /* Reset all the devices attached to cdx bus */
+ ret = device_for_each_child(dev, NULL, reset_cdx_device);
+ else
+ ret = cdx_dev_reset(dev);
- return count;
+ return ret < 0 ? ret : count;
}
static DEVICE_ATTR_WO(reset);
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct cdx_device *cdx_dev = to_cdx_device(dev);
+
+ return sprintf(buf, "cdx:v%04Xd%04Xsv%04Xsd%04Xc%06X\n", cdx_dev->vendor,
+ cdx_dev->device, cdx_dev->subsystem_vendor, cdx_dev->subsystem_device,
+ cdx_dev->class);
+}
+static DEVICE_ATTR_RO(modalias);
+
static ssize_t driver_override_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@@ -370,21 +453,107 @@ static ssize_t driver_override_show(struct device *dev,
}
static DEVICE_ATTR_RW(driver_override);
+static ssize_t enable_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cdx_device *cdx_dev = to_cdx_device(dev);
+ struct cdx_controller *cdx = cdx_dev->cdx;
+ bool enable;
+ int ret;
+
+ if (kstrtobool(buf, &enable) < 0)
+ return -EINVAL;
+
+ if (enable == cdx_dev->enabled)
+ return count;
+
+ if (enable && cdx->ops->bus_enable)
+ ret = cdx->ops->bus_enable(cdx, cdx_dev->bus_num);
+ else if (!enable && cdx->ops->bus_disable)
+ ret = cdx->ops->bus_disable(cdx, cdx_dev->bus_num);
+ else
+ ret = -EOPNOTSUPP;
+
+ if (!ret)
+ cdx_dev->enabled = enable;
+
+ return ret < 0 ? ret : count;
+}
+
+static ssize_t enable_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct cdx_device *cdx_dev = to_cdx_device(dev);
+
+ return sysfs_emit(buf, "%u\n", cdx_dev->enabled);
+}
+static DEVICE_ATTR_RW(enable);
+
+static umode_t cdx_dev_attrs_are_visible(struct kobject *kobj, struct attribute *a, int n)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct cdx_device *cdx_dev;
+
+ cdx_dev = to_cdx_device(dev);
+ if (!cdx_dev->is_bus)
+ return a->mode;
+
+ return 0;
+}
+
+static umode_t cdx_bus_attrs_are_visible(struct kobject *kobj, struct attribute *a, int n)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct cdx_device *cdx_dev;
+
+ cdx_dev = to_cdx_device(dev);
+ if (cdx_dev->is_bus)
+ return a->mode;
+
+ return 0;
+}
+
static struct attribute *cdx_dev_attrs[] = {
&dev_attr_remove.attr,
&dev_attr_reset.attr,
&dev_attr_vendor.attr,
&dev_attr_device.attr,
+ &dev_attr_subsystem_vendor.attr,
+ &dev_attr_subsystem_device.attr,
+ &dev_attr_class.attr,
+ &dev_attr_revision.attr,
+ &dev_attr_modalias.attr,
&dev_attr_driver_override.attr,
NULL,
};
-ATTRIBUTE_GROUPS(cdx_dev);
+
+static const struct attribute_group cdx_dev_group = {
+ .attrs = cdx_dev_attrs,
+ .is_visible = cdx_dev_attrs_are_visible,
+};
+
+static struct attribute *cdx_bus_dev_attrs[] = {
+ &dev_attr_enable.attr,
+ &dev_attr_reset.attr,
+ NULL,
+};
+
+static const struct attribute_group cdx_bus_dev_group = {
+ .attrs = cdx_bus_dev_attrs,
+ .is_visible = cdx_bus_attrs_are_visible,
+};
+
+static const struct attribute_group *cdx_dev_groups[] = {
+ &cdx_dev_group,
+ &cdx_bus_dev_group,
+ NULL,
+};
static ssize_t rescan_store(const struct bus_type *bus,
const char *buf, size_t count)
{
struct cdx_controller *cdx;
- unsigned long index;
+ struct platform_device *pd;
+ struct device_node *np;
bool val;
if (kstrtobool(buf, &val) < 0)
@@ -393,18 +562,29 @@ static ssize_t rescan_store(const struct bus_type *bus,
if (!val)
return -EINVAL;
+ mutex_lock(&cdx_controller_lock);
+
/* Unregister all the devices on the bus */
cdx_unregister_devices(&cdx_bus_type);
/* Rescan all the devices */
- xa_for_each(&cdx_controllers, index, cdx) {
- int ret;
+ for_each_compatible_node(np, NULL, compat_node_name) {
+ if (!np)
+ return -EINVAL;
- ret = cdx->ops->scan(cdx);
- if (ret)
- dev_err(cdx->dev, "cdx bus scanning failed\n");
+ pd = of_find_device_by_node(np);
+ if (!pd)
+ return -EINVAL;
+
+ cdx = platform_get_drvdata(pd);
+ if (cdx && cdx->controller_registered && cdx->ops->scan)
+ cdx->ops->scan(cdx);
+
+ put_device(&pd->dev);
}
+ mutex_unlock(&cdx_controller_lock);
+
return count;
}
static BUS_ATTR_WO(rescan);
@@ -463,7 +643,6 @@ static void cdx_device_release(struct device *dev)
int cdx_device_add(struct cdx_dev_params *dev_params)
{
struct cdx_controller *cdx = dev_params->cdx;
- struct device *parent = cdx->dev;
struct cdx_device *cdx_dev;
int ret;
@@ -480,6 +659,10 @@ int cdx_device_add(struct cdx_dev_params *dev_params)
cdx_dev->req_id = dev_params->req_id;
cdx_dev->vendor = dev_params->vendor;
cdx_dev->device = dev_params->device;
+ cdx_dev->subsystem_vendor = dev_params->subsys_vendor;
+ cdx_dev->subsystem_device = dev_params->subsys_device;
+ cdx_dev->class = dev_params->class;
+ cdx_dev->revision = dev_params->revision;
cdx_dev->bus_num = dev_params->bus_num;
cdx_dev->dev_num = dev_params->dev_num;
cdx_dev->cdx = dev_params->cdx;
@@ -487,7 +670,7 @@ int cdx_device_add(struct cdx_dev_params *dev_params)
/* Initialize generic device */
device_initialize(&cdx_dev->dev);
- cdx_dev->dev.parent = parent;
+ cdx_dev->dev.parent = dev_params->parent;
cdx_dev->dev.bus = &cdx_bus_type;
cdx_dev->dev.dma_mask = &cdx_dev->dma_mask;
cdx_dev->dev.release = cdx_device_release;
@@ -514,37 +697,94 @@ fail:
return ret;
}
-EXPORT_SYMBOL_GPL(cdx_device_add);
+EXPORT_SYMBOL_NS_GPL(cdx_device_add, CDX_BUS_CONTROLLER);
-int cdx_register_controller(struct cdx_controller *cdx)
+struct device *cdx_bus_add(struct cdx_controller *cdx, u8 bus_num)
{
+ struct cdx_device *cdx_dev;
int ret;
- ret = xa_alloc(&cdx_controllers, &cdx->id, cdx,
- XA_LIMIT(0, MAX_CDX_CONTROLLERS - 1), GFP_KERNEL);
+ cdx_dev = kzalloc(sizeof(*cdx_dev), GFP_KERNEL);
+ if (!cdx_dev)
+ return NULL;
+
+ device_initialize(&cdx_dev->dev);
+ cdx_dev->cdx = cdx;
+
+ cdx_dev->dev.parent = cdx->dev;
+ cdx_dev->dev.bus = &cdx_bus_type;
+ cdx_dev->dev.release = cdx_device_release;
+ cdx_dev->is_bus = true;
+ cdx_dev->bus_num = bus_num;
+
+ dev_set_name(&cdx_dev->dev, "cdx-%02x",
+ ((cdx->id << CDX_CONTROLLER_ID_SHIFT) | (bus_num & CDX_BUS_NUM_MASK)));
+
+ ret = device_add(&cdx_dev->dev);
if (ret) {
+ dev_err(&cdx_dev->dev, "cdx bus device add failed: %d\n", ret);
+ goto device_add_fail;
+ }
+
+ if (cdx->ops->bus_enable) {
+ ret = cdx->ops->bus_enable(cdx, bus_num);
+ if (ret && ret != -EALREADY) {
+ dev_err(cdx->dev, "cdx bus enable failed: %d\n", ret);
+ goto bus_enable_fail;
+ }
+ }
+
+ cdx_dev->enabled = true;
+ return &cdx_dev->dev;
+
+bus_enable_fail:
+ device_del(&cdx_dev->dev);
+device_add_fail:
+ put_device(&cdx_dev->dev);
+
+ return NULL;
+}
+EXPORT_SYMBOL_NS_GPL(cdx_bus_add, CDX_BUS_CONTROLLER);
+
+int cdx_register_controller(struct cdx_controller *cdx)
+{
+ int ret;
+
+ ret = ida_alloc_range(&cdx_controller_ida, 0, MAX_CDX_CONTROLLERS - 1, GFP_KERNEL);
+ if (ret < 0) {
dev_err(cdx->dev,
"No free index available. Maximum controllers already registered\n");
cdx->id = (u8)MAX_CDX_CONTROLLERS;
return ret;
}
+ mutex_lock(&cdx_controller_lock);
+ cdx->id = ret;
+
/* Scan all the devices */
- cdx->ops->scan(cdx);
+ if (cdx->ops->scan)
+ cdx->ops->scan(cdx);
+ cdx->controller_registered = true;
+ mutex_unlock(&cdx_controller_lock);
return 0;
}
-EXPORT_SYMBOL_GPL(cdx_register_controller);
+EXPORT_SYMBOL_NS_GPL(cdx_register_controller, CDX_BUS_CONTROLLER);
void cdx_unregister_controller(struct cdx_controller *cdx)
{
if (cdx->id >= MAX_CDX_CONTROLLERS)
return;
+ mutex_lock(&cdx_controller_lock);
+
+ cdx->controller_registered = false;
device_for_each_child(cdx->dev, NULL, cdx_unregister_device);
- xa_erase(&cdx_controllers, cdx->id);
+ ida_free(&cdx_controller_ida, cdx->id);
+
+ mutex_unlock(&cdx_controller_lock);
}
-EXPORT_SYMBOL_GPL(cdx_unregister_controller);
+EXPORT_SYMBOL_NS_GPL(cdx_unregister_controller, CDX_BUS_CONTROLLER);
static int __init cdx_bus_init(void)
{
diff --git a/drivers/cdx/cdx.h b/drivers/cdx/cdx.h
index c436ac7ac86f..300ad8be7a34 100644
--- a/drivers/cdx/cdx.h
+++ b/drivers/cdx/cdx.h
@@ -13,24 +13,33 @@
/**
* struct cdx_dev_params - CDX device parameters
* @cdx: CDX controller associated with the device
- * @parent: Associated CDX controller
+ * @parent: Associated CDX Bus device
* @vendor: Vendor ID for CDX device
* @device: Device ID for CDX device
+ * @subsys_vendor: Sub vendor ID for CDX device
+ * @subsys_device: Sub device ID for CDX device
* @bus_num: Bus number for this CDX device
* @dev_num: Device number for this device
* @res: array of MMIO region entries
* @res_count: number of valid MMIO regions
* @req_id: Requestor ID associated with CDX device
+ * @class: Class of the CDX Device
+ * @revision: Revision of the CDX device
*/
struct cdx_dev_params {
struct cdx_controller *cdx;
+ struct device *parent;
u16 vendor;
u16 device;
+ u16 subsys_vendor;
+ u16 subsys_device;
u8 bus_num;
u8 dev_num;
struct resource res[MAX_CDX_DEV_RESOURCES];
u8 res_count;
u32 req_id;
+ u32 class;
+ u8 revision;
};
/**
@@ -59,4 +68,15 @@ void cdx_unregister_controller(struct cdx_controller *cdx);
*/
int cdx_device_add(struct cdx_dev_params *dev_params);
+/**
+ * cdx_bus_add - Add a CDX bus. This function adds a bus on the CDX bus
+ * subsystem. It creates a CDX device for the corresponding bus and
+ * also registers an associated Linux generic device.
+ * @cdx: Associated CDX controller
+ * @us_num: Bus number
+ *
+ * Return: associated Linux generic device pointer on success or NULL on failure.
+ */
+struct device *cdx_bus_add(struct cdx_controller *cdx, u8 bus_num);
+
#endif /* _CDX_H_ */
diff --git a/drivers/cdx/controller/cdx_controller.c b/drivers/cdx/controller/cdx_controller.c
index bb4ae7970e21..85fe4b1c4e5e 100644
--- a/drivers/cdx/controller/cdx_controller.c
+++ b/drivers/cdx/controller/cdx_controller.c
@@ -33,6 +33,16 @@ static const struct cdx_mcdi_ops mcdi_ops = {
.mcdi_request = cdx_mcdi_request,
};
+static int cdx_bus_enable(struct cdx_controller *cdx, u8 bus_num)
+{
+ return cdx_mcdi_bus_enable(cdx->priv, bus_num);
+}
+
+static int cdx_bus_disable(struct cdx_controller *cdx, u8 bus_num)
+{
+ return cdx_mcdi_bus_disable(cdx->priv, bus_num);
+}
+
void cdx_rpmsg_post_probe(struct cdx_controller *cdx)
{
/* Register CDX controller with CDX bus driver */
@@ -56,6 +66,10 @@ static int cdx_configure_device(struct cdx_controller *cdx,
case CDX_DEV_RESET_CONF:
ret = cdx_mcdi_reset_device(cdx->priv, bus_num, dev_num);
break;
+ case CDX_DEV_BUS_MASTER_CONF:
+ ret = cdx_mcdi_bus_master_enable(cdx->priv, bus_num, dev_num,
+ dev_config->bus_master_enable);
+ break;
default:
ret = -EINVAL;
}
@@ -79,8 +93,14 @@ static int cdx_scan_devices(struct cdx_controller *cdx)
num_cdx_bus = (u8)ret;
for (bus_num = 0; bus_num < num_cdx_bus; bus_num++) {
+ struct device *bus_dev;
u8 num_cdx_dev;
+ /* Add the bus on cdx subsystem */
+ bus_dev = cdx_bus_add(cdx, bus_num);
+ if (!bus_dev)
+ continue;
+
/* MCDI FW Read: Fetch the number of devices present */
ret = cdx_mcdi_get_num_devs(cdx_mcdi, bus_num);
if (ret < 0) {
@@ -103,6 +123,7 @@ static int cdx_scan_devices(struct cdx_controller *cdx)
continue;
}
dev_params.cdx = cdx;
+ dev_params.parent = bus_dev;
/* Add the device to the cdx bus */
ret = cdx_device_add(&dev_params);
@@ -121,6 +142,8 @@ static int cdx_scan_devices(struct cdx_controller *cdx)
}
static struct cdx_ops cdx_ops = {
+ .bus_enable = cdx_bus_enable,
+ .bus_disable = cdx_bus_disable,
.scan = cdx_scan_devices,
.dev_configure = cdx_configure_device,
};
@@ -229,3 +252,4 @@ module_exit(cdx_controller_exit);
MODULE_AUTHOR("AMD Inc.");
MODULE_DESCRIPTION("CDX controller for AMD devices");
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(CDX_BUS_CONTROLLER);
diff --git a/drivers/cdx/controller/mc_cdx_pcol.h b/drivers/cdx/controller/mc_cdx_pcol.h
index 4ccb7b52951b..2de019406b57 100644
--- a/drivers/cdx/controller/mc_cdx_pcol.h
+++ b/drivers/cdx/controller/mc_cdx_pcol.h
@@ -457,6 +457,60 @@
/***********************************/
/*
+ * MC_CMD_CDX_BUS_DOWN
+ * Asserting reset on the CDX bus causes all devices on the bus to be quiesced.
+ * DMA bus mastering is disabled and any pending DMA request are flushed. Once
+ * the response is returned, the devices are guaranteed to no longer issue DMA
+ * requests or raise MSI interrupts. Further device MMIO accesses may have
+ * undefined results. While the bus reset is asserted, any of the enumeration
+ * or device configuration MCDIs will fail with EAGAIN. It is only legal to
+ * reload the relevant PL region containing CDX devices if the corresponding CDX
+ * bus is in reset. Depending on the implementation, the firmware may or may
+ * not enforce this restriction and it is up to the caller to make sure this
+ * requirement is satisfied.
+ */
+#define MC_CMD_CDX_BUS_DOWN 0x4
+#define MC_CMD_CDX_BUS_DOWN_MSGSET 0x4
+
+/* MC_CMD_CDX_BUS_DOWN_IN msgrequest */
+#define MC_CMD_CDX_BUS_DOWN_IN_LEN 4
+/* Bus number to put in reset, in range 0 to BUS_COUNT-1 */
+#define MC_CMD_CDX_BUS_DOWN_IN_BUS_OFST 0
+#define MC_CMD_CDX_BUS_DOWN_IN_BUS_LEN 4
+
+/*
+ * MC_CMD_CDX_BUS_DOWN_OUT msgresponse: The bus is quiesced, no further
+ * upstream traffic for devices on this bus.
+ */
+#define MC_CMD_CDX_BUS_DOWN_OUT_LEN 0
+
+/***********************************/
+/*
+ * MC_CMD_CDX_BUS_UP
+ * After bus reset is de-asserted, devices are in a state which is functionally
+ * equivalent to each device having been reset with MC_CMD_CDX_DEVICE_RESET. In
+ * other words, device logic is reset in a hardware-specific way, MMIO accesses
+ * are forwarded to the device, DMA bus mastering is disabled and needs to be
+ * re-enabled with MC_CMD_CDX_DEVICE_DMA_ENABLE once the driver is ready to
+ * start servicing DMA. If the underlying number of devices or device resources
+ * changed (e.g. if PL was reloaded) while the bus was in reset, the bus driver
+ * is expected to re-enumerate the bus. Returns EALREADY if the bus was already
+ * up before the call.
+ */
+#define MC_CMD_CDX_BUS_UP 0x5
+#define MC_CMD_CDX_BUS_UP_MSGSET 0x5
+
+/* MC_CMD_CDX_BUS_UP_IN msgrequest */
+#define MC_CMD_CDX_BUS_UP_IN_LEN 4
+/* Bus number to take out of reset, in range 0 to BUS_COUNT-1 */
+#define MC_CMD_CDX_BUS_UP_IN_BUS_OFST 0
+#define MC_CMD_CDX_BUS_UP_IN_BUS_LEN 4
+
+/* MC_CMD_CDX_BUS_UP_OUT msgresponse: The bus can now be enumerated. */
+#define MC_CMD_CDX_BUS_UP_OUT_LEN 0
+
+/***********************************/
+/*
* MC_CMD_CDX_DEVICE_RESET
* After this call completes, device DMA and interrupts are quiesced, devices
* logic is reset in a hardware-specific way and DMA bus mastering is disabled.
diff --git a/drivers/cdx/controller/mcdi_functions.c b/drivers/cdx/controller/mcdi_functions.c
index 0158f26533dd..b1f530946389 100644
--- a/drivers/cdx/controller/mcdi_functions.c
+++ b/drivers/cdx/controller/mcdi_functions.c
@@ -120,10 +120,41 @@ int cdx_mcdi_get_dev_config(struct cdx_mcdi *cdx,
dev_params->vendor = MCDI_WORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_VENDOR_ID);
dev_params->device = MCDI_WORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_ID);
+ dev_params->subsys_vendor = MCDI_WORD(outbuf,
+ CDX_BUS_GET_DEVICE_CONFIG_OUT_SUBSYS_VENDOR_ID);
+ dev_params->subsys_device = MCDI_WORD(outbuf,
+ CDX_BUS_GET_DEVICE_CONFIG_OUT_SUBSYS_DEVICE_ID);
+ dev_params->class = MCDI_DWORD(outbuf,
+ CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_CLASS) & 0xFFFFFF;
+ dev_params->revision = MCDI_BYTE(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_REVISION);
return 0;
}
+int cdx_mcdi_bus_enable(struct cdx_mcdi *cdx, u8 bus_num)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_BUS_UP_IN_LEN);
+ int ret;
+
+ MCDI_SET_DWORD(inbuf, CDX_BUS_UP_IN_BUS, bus_num);
+ ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_BUS_UP, inbuf, sizeof(inbuf),
+ NULL, 0, NULL);
+
+ return ret;
+}
+
+int cdx_mcdi_bus_disable(struct cdx_mcdi *cdx, u8 bus_num)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_BUS_DOWN_IN_LEN);
+ int ret;
+
+ MCDI_SET_DWORD(inbuf, CDX_BUS_DOWN_IN_BUS, bus_num);
+ ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_BUS_DOWN, inbuf, sizeof(inbuf),
+ NULL, 0, NULL);
+
+ return ret;
+}
+
int cdx_mcdi_reset_device(struct cdx_mcdi *cdx, u8 bus_num, u8 dev_num)
{
MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_RESET_IN_LEN);
@@ -137,3 +168,61 @@ int cdx_mcdi_reset_device(struct cdx_mcdi *cdx, u8 bus_num, u8 dev_num)
return ret;
}
+
+static int cdx_mcdi_ctrl_flag_get(struct cdx_mcdi *cdx, u8 bus_num,
+ u8 dev_num, u32 *flags)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_CONTROL_GET_IN_LEN);
+ MCDI_DECLARE_BUF(outbuf, MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_LEN);
+ size_t outlen;
+ int ret;
+
+ MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_GET_IN_BUS, bus_num);
+ MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_GET_IN_DEVICE, dev_num);
+ ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_DEVICE_CONTROL_GET, inbuf,
+ sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
+ if (ret)
+ return ret;
+
+ if (outlen != MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_LEN)
+ return -EIO;
+
+ *flags = MCDI_DWORD(outbuf, CDX_DEVICE_CONTROL_GET_OUT_FLAGS);
+
+ return 0;
+}
+
+static int cdx_mcdi_ctrl_flag_set(struct cdx_mcdi *cdx, u8 bus_num,
+ u8 dev_num, bool enable, int bit_pos)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_CONTROL_SET_IN_LEN);
+ u32 flags;
+ int ret;
+
+ /*
+ * Get flags and then set/reset bit at bit_pos according to
+ * the input params.
+ */
+ ret = cdx_mcdi_ctrl_flag_get(cdx, bus_num, dev_num, &flags);
+ if (ret)
+ return ret;
+
+ flags = flags & (u32)(~(BIT(bit_pos)));
+ if (enable)
+ flags |= (1 << bit_pos);
+
+ MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_SET_IN_BUS, bus_num);
+ MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_SET_IN_DEVICE, dev_num);
+ MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_SET_IN_FLAGS, flags);
+ ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_DEVICE_CONTROL_SET, inbuf,
+ sizeof(inbuf), NULL, 0, NULL);
+
+ return ret;
+}
+
+int cdx_mcdi_bus_master_enable(struct cdx_mcdi *cdx, u8 bus_num,
+ u8 dev_num, bool enable)
+{
+ return cdx_mcdi_ctrl_flag_set(cdx, bus_num, dev_num, enable,
+ MC_CMD_CDX_DEVICE_CONTROL_SET_IN_BUS_MASTER_ENABLE_LBN);
+}
diff --git a/drivers/cdx/controller/mcdi_functions.h b/drivers/cdx/controller/mcdi_functions.h
index 7440ace5539a..258a5462fbe3 100644
--- a/drivers/cdx/controller/mcdi_functions.h
+++ b/drivers/cdx/controller/mcdi_functions.h
@@ -48,6 +48,24 @@ int cdx_mcdi_get_dev_config(struct cdx_mcdi *cdx,
struct cdx_dev_params *dev_params);
/**
+ * cdx_mcdi_bus_enable - Enable CDX bus represented by bus_num
+ * @cdx: pointer to MCDI interface.
+ * @bus_num: Bus number.
+ *
+ * Return: 0 on success, <0 on failure
+ */
+int cdx_mcdi_bus_enable(struct cdx_mcdi *cdx, u8 bus_num);
+
+/**
+ * cdx_mcdi_bus_disable - Disable CDX bus represented by bus_num
+ * @cdx: pointer to MCDI interface.
+ * @bus_num: Bus number.
+ *
+ * Return: 0 on success, <0 on failure
+ */
+int cdx_mcdi_bus_disable(struct cdx_mcdi *cdx, u8 bus_num);
+
+/**
* cdx_mcdi_reset_device - Reset cdx device represented by bus_num:dev_num
* @cdx: pointer to MCDI interface.
* @bus_num: Bus number.
@@ -58,4 +76,17 @@ int cdx_mcdi_get_dev_config(struct cdx_mcdi *cdx,
int cdx_mcdi_reset_device(struct cdx_mcdi *cdx,
u8 bus_num, u8 dev_num);
+/**
+ * cdx_mcdi_bus_master_enable - Set/Reset bus mastering for cdx device
+ * represented by bus_num:dev_num
+ * @cdx: pointer to MCDI interface.
+ * @bus_num: Bus number.
+ * @dev_num: Device number.
+ * @enable: Enable bus mastering if set, disable otherwise.
+ *
+ * Return: 0 on success, <0 on failure
+ */
+int cdx_mcdi_bus_master_enable(struct cdx_mcdi *cdx, u8 bus_num,
+ u8 dev_num, bool enable);
+
#endif /* CDX_MCDI_FUNCTIONS_H */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 625af75833fc..7c8dd0abcfdf 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -348,7 +348,7 @@ config DEVPORT
device is similar to /dev/mem, but for I/O ports.
config HPET
- bool "HPET - High Precision Event Timer" if (X86 || IA64)
+ bool "HPET - High Precision Event Timer" if X86
default n
depends on ACPI
help
@@ -377,7 +377,7 @@ config HPET_MMAP_DEFAULT
config HANGCHECK_TIMER
tristate "Hangcheck timer"
- depends on X86 || IA64 || PPC64 || S390
+ depends on X86 || PPC64 || S390
help
The hangcheck-timer module detects when the system has gone
out to lunch past a certain margin. It can reboot the system
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index c5f532e412f1..e9b360cdc99a 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o
obj-y += misc.o
obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o
-obj-$(CONFIG_MSPEC) += mspec.o
obj-$(CONFIG_UV_MMTIMER) += uv_mmtimer.o
obj-$(CONFIG_IBM_BSR) += bsr.o
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 4f501e4842ab..c47eb7bf06d4 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
menuconfig AGP
tristate "/dev/agpgart (AGP Support)"
- depends on ALPHA || IA64 || PARISC || PPC || X86
+ depends on ALPHA || PARISC || PPC || X86
depends on PCI
help
AGP (Accelerated Graphics Port) is a bus system mainly used to
@@ -109,20 +109,6 @@ config AGP_VIA
This option gives you AGP support for the GLX component of
X on VIA MVP3/Apollo Pro chipsets.
-config AGP_I460
- tristate "Intel 460GX chipset support"
- depends on AGP && IA64
- help
- This option gives you AGP GART support for the Intel 460GX chipset
- for IA64 processors.
-
-config AGP_HP_ZX1
- tristate "HP ZX1 chipset AGP support"
- depends on AGP && IA64
- help
- This option gives you AGP GART support for the HP ZX1 chipset
- for IA64 processors.
-
config AGP_PARISC
tristate "HP Quicksilver AGP support"
depends on AGP && PARISC && 64BIT && IOMMU_SBA
diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile
index 90ed8c789e48..25834557e486 100644
--- a/drivers/char/agp/Makefile
+++ b/drivers/char/agp/Makefile
@@ -14,9 +14,7 @@ obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o
obj-$(CONFIG_AGP_AMD64) += amd64-agp.o
obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o
obj-$(CONFIG_AGP_EFFICEON) += efficeon-agp.o
-obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o
obj-$(CONFIG_AGP_PARISC) += parisc-agp.o
-obj-$(CONFIG_AGP_I460) += i460-agp.o
obj-$(CONFIG_AGP_INTEL) += intel-agp.o
obj-$(CONFIG_INTEL_GTT) += intel-gtt.o
obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
deleted file mode 100644
index 84d9adbb62f6..000000000000
--- a/drivers/char/agp/hp-agp.c
+++ /dev/null
@@ -1,550 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * HP zx1 AGPGART routines.
- *
- * (c) Copyright 2002, 2003 Hewlett-Packard Development Company, L.P.
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- */
-
-#include <linux/acpi.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/agp_backend.h>
-#include <linux/log2.h>
-#include <linux/slab.h>
-
-#include <asm/acpi-ext.h>
-
-#include "agp.h"
-
-#define HP_ZX1_IOC_OFFSET 0x1000 /* ACPI reports SBA, we want IOC */
-
-/* HP ZX1 IOC registers */
-#define HP_ZX1_IBASE 0x300
-#define HP_ZX1_IMASK 0x308
-#define HP_ZX1_PCOM 0x310
-#define HP_ZX1_TCNFG 0x318
-#define HP_ZX1_PDIR_BASE 0x320
-
-#define HP_ZX1_IOVA_BASE GB(1UL)
-#define HP_ZX1_IOVA_SIZE GB(1UL)
-#define HP_ZX1_GART_SIZE (HP_ZX1_IOVA_SIZE / 2)
-#define HP_ZX1_SBA_IOMMU_COOKIE 0x0000badbadc0ffeeUL
-
-#define HP_ZX1_PDIR_VALID_BIT 0x8000000000000000UL
-#define HP_ZX1_IOVA_TO_PDIR(va) ((va - hp_private.iova_base) >> hp_private.io_tlb_shift)
-
-#define AGP8X_MODE_BIT 3
-#define AGP8X_MODE (1 << AGP8X_MODE_BIT)
-
-/* AGP bridge need not be PCI device, but DRM thinks it is. */
-static struct pci_dev fake_bridge_dev;
-
-static int hp_zx1_gart_found;
-
-static struct aper_size_info_fixed hp_zx1_sizes[] =
-{
- {0, 0, 0}, /* filled in by hp_zx1_fetch_size() */
-};
-
-static struct gatt_mask hp_zx1_masks[] =
-{
- {.mask = HP_ZX1_PDIR_VALID_BIT, .type = 0}
-};
-
-static struct _hp_private {
- volatile u8 __iomem *ioc_regs;
- volatile u8 __iomem *lba_regs;
- int lba_cap_offset;
- u64 *io_pdir; // PDIR for entire IOVA
- u64 *gatt; // PDIR just for GART (subset of above)
- u64 gatt_entries;
- u64 iova_base;
- u64 gart_base;
- u64 gart_size;
- u64 io_pdir_size;
- int io_pdir_owner; // do we own it, or share it with sba_iommu?
- int io_page_size;
- int io_tlb_shift;
- int io_tlb_ps; // IOC ps config
- int io_pages_per_kpage;
-} hp_private;
-
-static int __init hp_zx1_ioc_shared(void)
-{
- struct _hp_private *hp = &hp_private;
-
- printk(KERN_INFO PFX "HP ZX1 IOC: IOPDIR shared with sba_iommu\n");
-
- /*
- * IOC already configured by sba_iommu module; just use
- * its setup. We assume:
- * - IOVA space is 1Gb in size
- * - first 512Mb is IOMMU, second 512Mb is GART
- */
- hp->io_tlb_ps = readq(hp->ioc_regs+HP_ZX1_TCNFG);
- switch (hp->io_tlb_ps) {
- case 0: hp->io_tlb_shift = 12; break;
- case 1: hp->io_tlb_shift = 13; break;
- case 2: hp->io_tlb_shift = 14; break;
- case 3: hp->io_tlb_shift = 16; break;
- default:
- printk(KERN_ERR PFX "Invalid IOTLB page size "
- "configuration 0x%x\n", hp->io_tlb_ps);
- hp->gatt = NULL;
- hp->gatt_entries = 0;
- return -ENODEV;
- }
- hp->io_page_size = 1 << hp->io_tlb_shift;
- hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size;
-
- hp->iova_base = readq(hp->ioc_regs+HP_ZX1_IBASE) & ~0x1;
- hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - HP_ZX1_GART_SIZE;
-
- hp->gart_size = HP_ZX1_GART_SIZE;
- hp->gatt_entries = hp->gart_size / hp->io_page_size;
-
- hp->io_pdir = phys_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
- hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
-
- if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
- /* Normal case when no AGP device in system */
- hp->gatt = NULL;
- hp->gatt_entries = 0;
- printk(KERN_ERR PFX "No reserved IO PDIR entry found; "
- "GART disabled\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-static int __init
-hp_zx1_ioc_owner (void)
-{
- struct _hp_private *hp = &hp_private;
-
- printk(KERN_INFO PFX "HP ZX1 IOC: IOPDIR dedicated to GART\n");
-
- /*
- * Select an IOV page size no larger than system page size.
- */
- if (PAGE_SIZE >= KB(64)) {
- hp->io_tlb_shift = 16;
- hp->io_tlb_ps = 3;
- } else if (PAGE_SIZE >= KB(16)) {
- hp->io_tlb_shift = 14;
- hp->io_tlb_ps = 2;
- } else if (PAGE_SIZE >= KB(8)) {
- hp->io_tlb_shift = 13;
- hp->io_tlb_ps = 1;
- } else {
- hp->io_tlb_shift = 12;
- hp->io_tlb_ps = 0;
- }
- hp->io_page_size = 1 << hp->io_tlb_shift;
- hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size;
-
- hp->iova_base = HP_ZX1_IOVA_BASE;
- hp->gart_size = HP_ZX1_GART_SIZE;
- hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - hp->gart_size;
-
- hp->gatt_entries = hp->gart_size / hp->io_page_size;
- hp->io_pdir_size = (HP_ZX1_IOVA_SIZE / hp->io_page_size) * sizeof(u64);
-
- return 0;
-}
-
-static int __init
-hp_zx1_ioc_init (u64 hpa)
-{
- struct _hp_private *hp = &hp_private;
-
- hp->ioc_regs = ioremap(hpa, 1024);
- if (!hp->ioc_regs)
- return -ENOMEM;
-
- /*
- * If the IOTLB is currently disabled, we can take it over.
- * Otherwise, we have to share with sba_iommu.
- */
- hp->io_pdir_owner = (readq(hp->ioc_regs+HP_ZX1_IBASE) & 0x1) == 0;
-
- if (hp->io_pdir_owner)
- return hp_zx1_ioc_owner();
-
- return hp_zx1_ioc_shared();
-}
-
-static int
-hp_zx1_lba_find_capability (volatile u8 __iomem *hpa, int cap)
-{
- u16 status;
- u8 pos, id;
- int ttl = 48;
-
- status = readw(hpa+PCI_STATUS);
- if (!(status & PCI_STATUS_CAP_LIST))
- return 0;
- pos = readb(hpa+PCI_CAPABILITY_LIST);
- while (ttl-- && pos >= 0x40) {
- pos &= ~3;
- id = readb(hpa+pos+PCI_CAP_LIST_ID);
- if (id == 0xff)
- break;
- if (id == cap)
- return pos;
- pos = readb(hpa+pos+PCI_CAP_LIST_NEXT);
- }
- return 0;
-}
-
-static int __init
-hp_zx1_lba_init (u64 hpa)
-{
- struct _hp_private *hp = &hp_private;
- int cap;
-
- hp->lba_regs = ioremap(hpa, 256);
- if (!hp->lba_regs)
- return -ENOMEM;
-
- hp->lba_cap_offset = hp_zx1_lba_find_capability(hp->lba_regs, PCI_CAP_ID_AGP);
-
- cap = readl(hp->lba_regs+hp->lba_cap_offset) & 0xff;
- if (cap != PCI_CAP_ID_AGP) {
- printk(KERN_ERR PFX "Invalid capability ID 0x%02x at 0x%x\n",
- cap, hp->lba_cap_offset);
- iounmap(hp->lba_regs);
- return -ENODEV;
- }
-
- return 0;
-}
-
-static int
-hp_zx1_fetch_size(void)
-{
- int size;
-
- size = hp_private.gart_size / MB(1);
- hp_zx1_sizes[0].size = size;
- agp_bridge->current_size = (void *) &hp_zx1_sizes[0];
- return size;
-}
-
-static int
-hp_zx1_configure (void)
-{
- struct _hp_private *hp = &hp_private;
-
- agp_bridge->gart_bus_addr = hp->gart_base;
- agp_bridge->capndx = hp->lba_cap_offset;
- agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
-
- if (hp->io_pdir_owner) {
- writel(virt_to_phys(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
- readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
- writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
- readl(hp->ioc_regs+HP_ZX1_TCNFG);
- writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK);
- readl(hp->ioc_regs+HP_ZX1_IMASK);
- writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE);
- readl(hp->ioc_regs+HP_ZX1_IBASE);
- writel(hp->iova_base|ilog2(HP_ZX1_IOVA_SIZE), hp->ioc_regs+HP_ZX1_PCOM);
- readl(hp->ioc_regs+HP_ZX1_PCOM);
- }
-
- return 0;
-}
-
-static void
-hp_zx1_cleanup (void)
-{
- struct _hp_private *hp = &hp_private;
-
- if (hp->ioc_regs) {
- if (hp->io_pdir_owner) {
- writeq(0, hp->ioc_regs+HP_ZX1_IBASE);
- readq(hp->ioc_regs+HP_ZX1_IBASE);
- }
- iounmap(hp->ioc_regs);
- }
- if (hp->lba_regs)
- iounmap(hp->lba_regs);
-}
-
-static void
-hp_zx1_tlbflush (struct agp_memory *mem)
-{
- struct _hp_private *hp = &hp_private;
-
- writeq(hp->gart_base | ilog2(hp->gart_size), hp->ioc_regs+HP_ZX1_PCOM);
- readq(hp->ioc_regs+HP_ZX1_PCOM);
-}
-
-static int
-hp_zx1_create_gatt_table (struct agp_bridge_data *bridge)
-{
- struct _hp_private *hp = &hp_private;
- int i;
-
- if (hp->io_pdir_owner) {
- hp->io_pdir = (u64 *) __get_free_pages(GFP_KERNEL,
- get_order(hp->io_pdir_size));
- if (!hp->io_pdir) {
- printk(KERN_ERR PFX "Couldn't allocate contiguous "
- "memory for I/O PDIR\n");
- hp->gatt = NULL;
- hp->gatt_entries = 0;
- return -ENOMEM;
- }
- memset(hp->io_pdir, 0, hp->io_pdir_size);
-
- hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
- }
-
- for (i = 0; i < hp->gatt_entries; i++) {
- hp->gatt[i] = (unsigned long) agp_bridge->scratch_page;
- }
-
- return 0;
-}
-
-static int
-hp_zx1_free_gatt_table (struct agp_bridge_data *bridge)
-{
- struct _hp_private *hp = &hp_private;
-
- if (hp->io_pdir_owner)
- free_pages((unsigned long) hp->io_pdir,
- get_order(hp->io_pdir_size));
- else
- hp->gatt[0] = HP_ZX1_SBA_IOMMU_COOKIE;
- return 0;
-}
-
-static int
-hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type)
-{
- struct _hp_private *hp = &hp_private;
- int i, k;
- off_t j, io_pg_start;
- int io_pg_count;
-
- if (type != mem->type ||
- agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
- return -EINVAL;
- }
-
- io_pg_start = hp->io_pages_per_kpage * pg_start;
- io_pg_count = hp->io_pages_per_kpage * mem->page_count;
- if ((io_pg_start + io_pg_count) > hp->gatt_entries) {
- return -EINVAL;
- }
-
- j = io_pg_start;
- while (j < (io_pg_start + io_pg_count)) {
- if (hp->gatt[j]) {
- return -EBUSY;
- }
- j++;
- }
-
- if (!mem->is_flushed) {
- global_cache_flush();
- mem->is_flushed = true;
- }
-
- for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
- unsigned long paddr;
-
- paddr = page_to_phys(mem->pages[i]);
- for (k = 0;
- k < hp->io_pages_per_kpage;
- k++, j++, paddr += hp->io_page_size) {
- hp->gatt[j] = HP_ZX1_PDIR_VALID_BIT | paddr;
- }
- }
-
- agp_bridge->driver->tlb_flush(mem);
- return 0;
-}
-
-static int
-hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type)
-{
- struct _hp_private *hp = &hp_private;
- int i, io_pg_start, io_pg_count;
-
- if (type != mem->type ||
- agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
- return -EINVAL;
- }
-
- io_pg_start = hp->io_pages_per_kpage * pg_start;
- io_pg_count = hp->io_pages_per_kpage * mem->page_count;
- for (i = io_pg_start; i < io_pg_count + io_pg_start; i++) {
- hp->gatt[i] = agp_bridge->scratch_page;
- }
-
- agp_bridge->driver->tlb_flush(mem);
- return 0;
-}
-
-static unsigned long
-hp_zx1_mask_memory (struct agp_bridge_data *bridge, dma_addr_t addr, int type)
-{
- return HP_ZX1_PDIR_VALID_BIT | addr;
-}
-
-static void
-hp_zx1_enable (struct agp_bridge_data *bridge, u32 mode)
-{
- struct _hp_private *hp = &hp_private;
- u32 command;
-
- command = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
- command = agp_collect_device_status(bridge, mode, command);
- command |= 0x00000100;
-
- writel(command, hp->lba_regs+hp->lba_cap_offset+PCI_AGP_COMMAND);
-
- agp_device_command(command, (mode & AGP8X_MODE) != 0);
-}
-
-const struct agp_bridge_driver hp_zx1_driver = {
- .owner = THIS_MODULE,
- .size_type = FIXED_APER_SIZE,
- .configure = hp_zx1_configure,
- .fetch_size = hp_zx1_fetch_size,
- .cleanup = hp_zx1_cleanup,
- .tlb_flush = hp_zx1_tlbflush,
- .mask_memory = hp_zx1_mask_memory,
- .masks = hp_zx1_masks,
- .agp_enable = hp_zx1_enable,
- .cache_flush = global_cache_flush,
- .create_gatt_table = hp_zx1_create_gatt_table,
- .free_gatt_table = hp_zx1_free_gatt_table,
- .insert_memory = hp_zx1_insert_memory,
- .remove_memory = hp_zx1_remove_memory,
- .alloc_by_type = agp_generic_alloc_by_type,
- .free_by_type = agp_generic_free_by_type,
- .agp_alloc_page = agp_generic_alloc_page,
- .agp_alloc_pages = agp_generic_alloc_pages,
- .agp_destroy_page = agp_generic_destroy_page,
- .agp_destroy_pages = agp_generic_destroy_pages,
- .agp_type_to_mask_type = agp_generic_type_to_mask_type,
- .cant_use_aperture = true,
-};
-
-static int __init
-hp_zx1_setup (u64 ioc_hpa, u64 lba_hpa)
-{
- struct agp_bridge_data *bridge;
- int error = 0;
-
- error = hp_zx1_ioc_init(ioc_hpa);
- if (error)
- goto fail;
-
- error = hp_zx1_lba_init(lba_hpa);
- if (error)
- goto fail;
-
- bridge = agp_alloc_bridge();
- if (!bridge) {
- error = -ENOMEM;
- goto fail;
- }
- bridge->driver = &hp_zx1_driver;
-
- fake_bridge_dev.vendor = PCI_VENDOR_ID_HP;
- fake_bridge_dev.device = PCI_DEVICE_ID_HP_PCIX_LBA;
- bridge->dev = &fake_bridge_dev;
-
- error = agp_add_bridge(bridge);
- fail:
- if (error)
- hp_zx1_cleanup();
- return error;
-}
-
-static acpi_status __init
-zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret)
-{
- acpi_handle handle, parent;
- acpi_status status;
- struct acpi_device_info *info;
- u64 lba_hpa, sba_hpa, length;
- int match;
-
- status = hp_acpi_csr_space(obj, &lba_hpa, &length);
- if (ACPI_FAILURE(status))
- return AE_OK; /* keep looking for another bridge */
-
- /* Look for an enclosing IOC scope and find its CSR space */
- handle = obj;
- do {
- status = acpi_get_object_info(handle, &info);
- if (ACPI_SUCCESS(status) && (info->valid & ACPI_VALID_HID)) {
- /* TBD check _CID also */
- match = (strcmp(info->hardware_id.string, "HWP0001") == 0);
- kfree(info);
- if (match) {
- status = hp_acpi_csr_space(handle, &sba_hpa, &length);
- if (ACPI_SUCCESS(status))
- break;
- else {
- printk(KERN_ERR PFX "Detected HP ZX1 "
- "AGP LBA but no IOC.\n");
- return AE_OK;
- }
- }
- }
-
- status = acpi_get_parent(handle, &parent);
- handle = parent;
- } while (ACPI_SUCCESS(status));
-
- if (ACPI_FAILURE(status))
- return AE_OK; /* found no enclosing IOC */
-
- if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa))
- return AE_OK;
-
- printk(KERN_INFO PFX "Detected HP ZX1 %s AGP chipset "
- "(ioc=%llx, lba=%llx)\n", (char *)context,
- sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa);
-
- hp_zx1_gart_found = 1;
- return AE_CTRL_TERMINATE; /* we only support one bridge; quit looking */
-}
-
-static int __init
-agp_hp_init (void)
-{
- if (agp_off)
- return -EINVAL;
-
- acpi_get_devices("HWP0003", zx1_gart_probe, "HWP0003", NULL);
- if (hp_zx1_gart_found)
- return 0;
-
- acpi_get_devices("HWP0007", zx1_gart_probe, "HWP0007", NULL);
- if (hp_zx1_gart_found)
- return 0;
-
- return -ENODEV;
-}
-
-static void __exit
-agp_hp_cleanup (void)
-{
-}
-
-module_init(agp_hp_init);
-module_exit(agp_hp_cleanup);
-
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
deleted file mode 100644
index 15b240ea4848..000000000000
--- a/drivers/char/agp/i460-agp.c
+++ /dev/null
@@ -1,659 +0,0 @@
-/*
- * For documentation on the i460 AGP interface, see Chapter 7 (AGP Subsystem) of
- * the "Intel 460GTX Chipset Software Developer's Manual":
- * http://www.intel.com/design/archives/itanium/downloads/248704.htm
- */
-/*
- * 460GX support by Chris Ahna <christopher.j.ahna@intel.com>
- * Clean up & simplification by David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/agp_backend.h>
-#include <linux/log2.h>
-
-#include "agp.h"
-
-#define INTEL_I460_BAPBASE 0x98
-#define INTEL_I460_GXBCTL 0xa0
-#define INTEL_I460_AGPSIZ 0xa2
-#define INTEL_I460_ATTBASE 0xfe200000
-#define INTEL_I460_GATT_VALID (1UL << 24)
-#define INTEL_I460_GATT_COHERENT (1UL << 25)
-
-/*
- * The i460 can operate with large (4MB) pages, but there is no sane way to support this
- * within the current kernel/DRM environment, so we disable the relevant code for now.
- * See also comments in ia64_alloc_page()...
- */
-#define I460_LARGE_IO_PAGES 0
-
-#if I460_LARGE_IO_PAGES
-# define I460_IO_PAGE_SHIFT i460.io_page_shift
-#else
-# define I460_IO_PAGE_SHIFT 12
-#endif
-
-#define I460_IOPAGES_PER_KPAGE (PAGE_SIZE >> I460_IO_PAGE_SHIFT)
-#define I460_KPAGES_PER_IOPAGE (1 << (I460_IO_PAGE_SHIFT - PAGE_SHIFT))
-#define I460_SRAM_IO_DISABLE (1 << 4)
-#define I460_BAPBASE_ENABLE (1 << 3)
-#define I460_AGPSIZ_MASK 0x7
-#define I460_4M_PS (1 << 1)
-
-/* Control bits for Out-Of-GART coherency and Burst Write Combining */
-#define I460_GXBCTL_OOG (1UL << 0)
-#define I460_GXBCTL_BWC (1UL << 2)
-
-/*
- * gatt_table entries are 32-bits wide on the i460; the generic code ought to declare the
- * gatt_table and gatt_table_real pointers a "void *"...
- */
-#define RD_GATT(index) readl((u32 *) i460.gatt + (index))
-#define WR_GATT(index, val) writel((val), (u32 *) i460.gatt + (index))
-/*
- * The 460 spec says we have to read the last location written to make sure that all
- * writes have taken effect
- */
-#define WR_FLUSH_GATT(index) RD_GATT(index)
-
-static unsigned long i460_mask_memory (struct agp_bridge_data *bridge,
- dma_addr_t addr, int type);
-
-static struct {
- void *gatt; /* ioremap'd GATT area */
-
- /* i460 supports multiple GART page sizes, so GART pageshift is dynamic: */
- u8 io_page_shift;
-
- /* BIOS configures chipset to one of 2 possible apbase values: */
- u8 dynamic_apbase;
-
- /* structure for tracking partial use of 4MB GART pages: */
- struct lp_desc {
- unsigned long *alloced_map; /* bitmap of kernel-pages in use */
- int refcount; /* number of kernel pages using the large page */
- u64 paddr; /* physical address of large page */
- struct page *page; /* page pointer */
- } *lp_desc;
-} i460;
-
-static const struct aper_size_info_8 i460_sizes[3] =
-{
- /*
- * The 32GB aperture is only available with a 4M GART page size. Due to the
- * dynamic GART page size, we can't figure out page_order or num_entries until
- * runtime.
- */
- {32768, 0, 0, 4},
- {1024, 0, 0, 2},
- {256, 0, 0, 1}
-};
-
-static struct gatt_mask i460_masks[] =
-{
- {
- .mask = INTEL_I460_GATT_VALID | INTEL_I460_GATT_COHERENT,
- .type = 0
- }
-};
-
-static int i460_fetch_size (void)
-{
- int i;
- u8 temp;
- struct aper_size_info_8 *values;
-
- /* Determine the GART page size */
- pci_read_config_byte(agp_bridge->dev, INTEL_I460_GXBCTL, &temp);
- i460.io_page_shift = (temp & I460_4M_PS) ? 22 : 12;
- pr_debug("i460_fetch_size: io_page_shift=%d\n", i460.io_page_shift);
-
- if (i460.io_page_shift != I460_IO_PAGE_SHIFT) {
- printk(KERN_ERR PFX
- "I/O (GART) page-size %luKB doesn't match expected "
- "size %luKB\n",
- 1UL << (i460.io_page_shift - 10),
- 1UL << (I460_IO_PAGE_SHIFT));
- return 0;
- }
-
- values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
-
- pci_read_config_byte(agp_bridge->dev, INTEL_I460_AGPSIZ, &temp);
-
- /* Exit now if the IO drivers for the GART SRAMS are turned off */
- if (temp & I460_SRAM_IO_DISABLE) {
- printk(KERN_ERR PFX "GART SRAMS disabled on 460GX chipset\n");
- printk(KERN_ERR PFX "AGPGART operation not possible\n");
- return 0;
- }
-
- /* Make sure we don't try to create an 2 ^ 23 entry GATT */
- if ((i460.io_page_shift == 0) && ((temp & I460_AGPSIZ_MASK) == 4)) {
- printk(KERN_ERR PFX "We can't have a 32GB aperture with 4KB GART pages\n");
- return 0;
- }
-
- /* Determine the proper APBASE register */
- if (temp & I460_BAPBASE_ENABLE)
- i460.dynamic_apbase = INTEL_I460_BAPBASE;
- else
- i460.dynamic_apbase = AGP_APBASE;
-
- for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
- /*
- * Dynamically calculate the proper num_entries and page_order values for
- * the define aperture sizes. Take care not to shift off the end of
- * values[i].size.
- */
- values[i].num_entries = (values[i].size << 8) >> (I460_IO_PAGE_SHIFT - 12);
- values[i].page_order = ilog2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT);
- }
-
- for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
- /* Neglect control bits when matching up size_value */
- if ((temp & I460_AGPSIZ_MASK) == values[i].size_value) {
- agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i);
- agp_bridge->aperture_size_idx = i;
- return values[i].size;
- }
- }
-
- return 0;
-}
-
-/* There isn't anything to do here since 460 has no GART TLB. */
-static void i460_tlb_flush (struct agp_memory *mem)
-{
- return;
-}
-
-/*
- * This utility function is needed to prevent corruption of the control bits
- * which are stored along with the aperture size in 460's AGPSIZ register
- */
-static void i460_write_agpsiz (u8 size_value)
-{
- u8 temp;
-
- pci_read_config_byte(agp_bridge->dev, INTEL_I460_AGPSIZ, &temp);
- pci_write_config_byte(agp_bridge->dev, INTEL_I460_AGPSIZ,
- ((temp & ~I460_AGPSIZ_MASK) | size_value));
-}
-
-static void i460_cleanup (void)
-{
- struct aper_size_info_8 *previous_size;
-
- previous_size = A_SIZE_8(agp_bridge->previous_size);
- i460_write_agpsiz(previous_size->size_value);
-
- if (I460_IO_PAGE_SHIFT > PAGE_SHIFT)
- kfree(i460.lp_desc);
-}
-
-static int i460_configure (void)
-{
- union {
- u32 small[2];
- u64 large;
- } temp;
- size_t size;
- u8 scratch;
- struct aper_size_info_8 *current_size;
-
- temp.large = 0;
-
- current_size = A_SIZE_8(agp_bridge->current_size);
- i460_write_agpsiz(current_size->size_value);
-
- /*
- * Do the necessary rigmarole to read all eight bytes of APBASE.
- * This has to be done since the AGP aperture can be above 4GB on
- * 460 based systems.
- */
- pci_read_config_dword(agp_bridge->dev, i460.dynamic_apbase, &(temp.small[0]));
- pci_read_config_dword(agp_bridge->dev, i460.dynamic_apbase + 4, &(temp.small[1]));
-
- /* Clear BAR control bits */
- agp_bridge->gart_bus_addr = temp.large & ~((1UL << 3) - 1);
-
- pci_read_config_byte(agp_bridge->dev, INTEL_I460_GXBCTL, &scratch);
- pci_write_config_byte(agp_bridge->dev, INTEL_I460_GXBCTL,
- (scratch & 0x02) | I460_GXBCTL_OOG | I460_GXBCTL_BWC);
-
- /*
- * Initialize partial allocation trackers if a GART page is bigger than a kernel
- * page.
- */
- if (I460_IO_PAGE_SHIFT > PAGE_SHIFT) {
- size = current_size->num_entries * sizeof(i460.lp_desc[0]);
- i460.lp_desc = kzalloc(size, GFP_KERNEL);
- if (!i460.lp_desc)
- return -ENOMEM;
- }
- return 0;
-}
-
-static int i460_create_gatt_table (struct agp_bridge_data *bridge)
-{
- int page_order, num_entries, i;
- void *temp;
-
- /*
- * Load up the fixed address of the GART SRAMS which hold our GATT table.
- */
- temp = agp_bridge->current_size;
- page_order = A_SIZE_8(temp)->page_order;
- num_entries = A_SIZE_8(temp)->num_entries;
-
- i460.gatt = ioremap(INTEL_I460_ATTBASE, PAGE_SIZE << page_order);
- if (!i460.gatt) {
- printk(KERN_ERR PFX "ioremap failed\n");
- return -ENOMEM;
- }
-
- /* These are no good, the should be removed from the agp_bridge strucure... */
- agp_bridge->gatt_table_real = NULL;
- agp_bridge->gatt_table = NULL;
- agp_bridge->gatt_bus_addr = 0;
-
- for (i = 0; i < num_entries; ++i)
- WR_GATT(i, 0);
- WR_FLUSH_GATT(i - 1);
- return 0;
-}
-
-static int i460_free_gatt_table (struct agp_bridge_data *bridge)
-{
- int num_entries, i;
- void *temp;
-
- temp = agp_bridge->current_size;
-
- num_entries = A_SIZE_8(temp)->num_entries;
-
- for (i = 0; i < num_entries; ++i)
- WR_GATT(i, 0);
- WR_FLUSH_GATT(num_entries - 1);
-
- iounmap(i460.gatt);
- return 0;
-}
-
-/*
- * The following functions are called when the I/O (GART) page size is smaller than
- * PAGE_SIZE.
- */
-
-static int i460_insert_memory_small_io_page (struct agp_memory *mem,
- off_t pg_start, int type)
-{
- unsigned long paddr, io_pg_start, io_page_size;
- int i, j, k, num_entries;
- void *temp;
-
- pr_debug("i460_insert_memory_small_io_page(mem=%p, pg_start=%ld, type=%d, paddr0=0x%lx)\n",
- mem, pg_start, type, page_to_phys(mem->pages[0]));
-
- if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
- return -EINVAL;
-
- io_pg_start = I460_IOPAGES_PER_KPAGE * pg_start;
-
- temp = agp_bridge->current_size;
- num_entries = A_SIZE_8(temp)->num_entries;
-
- if ((io_pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count) > num_entries) {
- printk(KERN_ERR PFX "Looks like we're out of AGP memory\n");
- return -EINVAL;
- }
-
- j = io_pg_start;
- while (j < (io_pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count)) {
- if (!PGE_EMPTY(agp_bridge, RD_GATT(j))) {
- pr_debug("i460_insert_memory_small_io_page: GATT[%d]=0x%x is busy\n",
- j, RD_GATT(j));
- return -EBUSY;
- }
- j++;
- }
-
- io_page_size = 1UL << I460_IO_PAGE_SHIFT;
- for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
- paddr = page_to_phys(mem->pages[i]);
- for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size)
- WR_GATT(j, i460_mask_memory(agp_bridge, paddr, mem->type));
- }
- WR_FLUSH_GATT(j - 1);
- return 0;
-}
-
-static int i460_remove_memory_small_io_page(struct agp_memory *mem,
- off_t pg_start, int type)
-{
- int i;
-
- pr_debug("i460_remove_memory_small_io_page(mem=%p, pg_start=%ld, type=%d)\n",
- mem, pg_start, type);
-
- pg_start = I460_IOPAGES_PER_KPAGE * pg_start;
-
- for (i = pg_start; i < (pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count); i++)
- WR_GATT(i, 0);
- WR_FLUSH_GATT(i - 1);
- return 0;
-}
-
-#if I460_LARGE_IO_PAGES
-
-/*
- * These functions are called when the I/O (GART) page size exceeds PAGE_SIZE.
- *
- * This situation is interesting since AGP memory allocations that are smaller than a
- * single GART page are possible. The i460.lp_desc array tracks partial allocation of the
- * large GART pages to work around this issue.
- *
- * i460.lp_desc[pg_num].refcount tracks the number of kernel pages in use within GART page
- * pg_num. i460.lp_desc[pg_num].paddr is the physical address of the large page and
- * i460.lp_desc[pg_num].alloced_map is a bitmap of kernel pages that are in use (allocated).
- */
-
-static int i460_alloc_large_page (struct lp_desc *lp)
-{
- unsigned long order = I460_IO_PAGE_SHIFT - PAGE_SHIFT;
- size_t map_size;
-
- lp->page = alloc_pages(GFP_KERNEL, order);
- if (!lp->page) {
- printk(KERN_ERR PFX "Couldn't alloc 4M GART page...\n");
- return -ENOMEM;
- }
-
- map_size = ((I460_KPAGES_PER_IOPAGE + BITS_PER_LONG - 1) & -BITS_PER_LONG)/8;
- lp->alloced_map = kzalloc(map_size, GFP_KERNEL);
- if (!lp->alloced_map) {
- __free_pages(lp->page, order);
- printk(KERN_ERR PFX "Out of memory, we're in trouble...\n");
- return -ENOMEM;
- }
-
- lp->paddr = page_to_phys(lp->page);
- lp->refcount = 0;
- atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
- return 0;
-}
-
-static void i460_free_large_page (struct lp_desc *lp)
-{
- kfree(lp->alloced_map);
- lp->alloced_map = NULL;
-
- __free_pages(lp->page, I460_IO_PAGE_SHIFT - PAGE_SHIFT);
- atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
-}
-
-static int i460_insert_memory_large_io_page (struct agp_memory *mem,
- off_t pg_start, int type)
-{
- int i, start_offset, end_offset, idx, pg, num_entries;
- struct lp_desc *start, *end, *lp;
- void *temp;
-
- if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
- return -EINVAL;
-
- temp = agp_bridge->current_size;
- num_entries = A_SIZE_8(temp)->num_entries;
-
- /* Figure out what pg_start means in terms of our large GART pages */
- start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
- end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
- start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
- end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;
-
- if (end > i460.lp_desc + num_entries) {
- printk(KERN_ERR PFX "Looks like we're out of AGP memory\n");
- return -EINVAL;
- }
-
- /* Check if the requested region of the aperture is free */
- for (lp = start; lp <= end; ++lp) {
- if (!lp->alloced_map)
- continue; /* OK, the entire large page is available... */
-
- for (idx = ((lp == start) ? start_offset : 0);
- idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
- idx++)
- {
- if (test_bit(idx, lp->alloced_map))
- return -EBUSY;
- }
- }
-
- for (lp = start, i = 0; lp <= end; ++lp) {
- if (!lp->alloced_map) {
- /* Allocate new GART pages... */
- if (i460_alloc_large_page(lp) < 0)
- return -ENOMEM;
- pg = lp - i460.lp_desc;
- WR_GATT(pg, i460_mask_memory(agp_bridge,
- lp->paddr, 0));
- WR_FLUSH_GATT(pg);
- }
-
- for (idx = ((lp == start) ? start_offset : 0);
- idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
- idx++, i++)
- {
- mem->pages[i] = lp->page;
- __set_bit(idx, lp->alloced_map);
- ++lp->refcount;
- }
- }
- return 0;
-}
-
-static int i460_remove_memory_large_io_page (struct agp_memory *mem,
- off_t pg_start, int type)
-{
- int i, pg, start_offset, end_offset, idx, num_entries;
- struct lp_desc *start, *end, *lp;
- void *temp;
-
- temp = agp_bridge->current_size;
- num_entries = A_SIZE_8(temp)->num_entries;
-
- /* Figure out what pg_start means in terms of our large GART pages */
- start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
- end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
- start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
- end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;
-
- for (i = 0, lp = start; lp <= end; ++lp) {
- for (idx = ((lp == start) ? start_offset : 0);
- idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
- idx++, i++)
- {
- mem->pages[i] = NULL;
- __clear_bit(idx, lp->alloced_map);
- --lp->refcount;
- }
-
- /* Free GART pages if they are unused */
- if (lp->refcount == 0) {
- pg = lp - i460.lp_desc;
- WR_GATT(pg, 0);
- WR_FLUSH_GATT(pg);
- i460_free_large_page(lp);
- }
- }
- return 0;
-}
-
-/* Wrapper routines to call the approriate {small_io_page,large_io_page} function */
-
-static int i460_insert_memory (struct agp_memory *mem,
- off_t pg_start, int type)
-{
- if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT)
- return i460_insert_memory_small_io_page(mem, pg_start, type);
- else
- return i460_insert_memory_large_io_page(mem, pg_start, type);
-}
-
-static int i460_remove_memory (struct agp_memory *mem,
- off_t pg_start, int type)
-{
- if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT)
- return i460_remove_memory_small_io_page(mem, pg_start, type);
- else
- return i460_remove_memory_large_io_page(mem, pg_start, type);
-}
-
-/*
- * If the I/O (GART) page size is bigger than the kernel page size, we don't want to
- * allocate memory until we know where it is to be bound in the aperture (a
- * multi-kernel-page alloc might fit inside of an already allocated GART page).
- *
- * Let's just hope nobody counts on the allocated AGP memory being there before bind time
- * (I don't think current drivers do)...
- */
-static struct page *i460_alloc_page (struct agp_bridge_data *bridge)
-{
- void *page;
-
- if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) {
- page = agp_generic_alloc_page(agp_bridge);
- } else
- /* Returning NULL would cause problems */
- /* AK: really dubious code. */
- page = (void *)~0UL;
- return page;
-}
-
-static void i460_destroy_page (struct page *page, int flags)
-{
- if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) {
- agp_generic_destroy_page(page, flags);
- }
-}
-
-#endif /* I460_LARGE_IO_PAGES */
-
-static unsigned long i460_mask_memory (struct agp_bridge_data *bridge,
- dma_addr_t addr, int type)
-{
- /* Make sure the returned address is a valid GATT entry */
- return bridge->driver->masks[0].mask
- | (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xfffff000) >> 12);
-}
-
-const struct agp_bridge_driver intel_i460_driver = {
- .owner = THIS_MODULE,
- .aperture_sizes = i460_sizes,
- .size_type = U8_APER_SIZE,
- .num_aperture_sizes = 3,
- .configure = i460_configure,
- .fetch_size = i460_fetch_size,
- .cleanup = i460_cleanup,
- .tlb_flush = i460_tlb_flush,
- .mask_memory = i460_mask_memory,
- .masks = i460_masks,
- .agp_enable = agp_generic_enable,
- .cache_flush = global_cache_flush,
- .create_gatt_table = i460_create_gatt_table,
- .free_gatt_table = i460_free_gatt_table,
-#if I460_LARGE_IO_PAGES
- .insert_memory = i460_insert_memory,
- .remove_memory = i460_remove_memory,
- .agp_alloc_page = i460_alloc_page,
- .agp_destroy_page = i460_destroy_page,
-#else
- .insert_memory = i460_insert_memory_small_io_page,
- .remove_memory = i460_remove_memory_small_io_page,
- .agp_alloc_page = agp_generic_alloc_page,
- .agp_alloc_pages = agp_generic_alloc_pages,
- .agp_destroy_page = agp_generic_destroy_page,
- .agp_destroy_pages = agp_generic_destroy_pages,
-#endif
- .alloc_by_type = agp_generic_alloc_by_type,
- .free_by_type = agp_generic_free_by_type,
- .agp_type_to_mask_type = agp_generic_type_to_mask_type,
- .cant_use_aperture = true,
-};
-
-static int agp_intel_i460_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- struct agp_bridge_data *bridge;
- u8 cap_ptr;
-
- cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
- if (!cap_ptr)
- return -ENODEV;
-
- bridge = agp_alloc_bridge();
- if (!bridge)
- return -ENOMEM;
-
- bridge->driver = &intel_i460_driver;
- bridge->dev = pdev;
- bridge->capndx = cap_ptr;
-
- printk(KERN_INFO PFX "Detected Intel 460GX chipset\n");
-
- pci_set_drvdata(pdev, bridge);
- return agp_add_bridge(bridge);
-}
-
-static void agp_intel_i460_remove(struct pci_dev *pdev)
-{
- struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
-
- agp_remove_bridge(bridge);
- agp_put_bridge(bridge);
-}
-
-static struct pci_device_id agp_intel_i460_pci_table[] = {
- {
- .class = (PCI_CLASS_BRIDGE_HOST << 8),
- .class_mask = ~0,
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_84460GX,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- { }
-};
-
-MODULE_DEVICE_TABLE(pci, agp_intel_i460_pci_table);
-
-static struct pci_driver agp_intel_i460_pci_driver = {
- .name = "agpgart-intel-i460",
- .id_table = agp_intel_i460_pci_table,
- .probe = agp_intel_i460_probe,
- .remove = agp_intel_i460_remove,
-};
-
-static int __init agp_intel_i460_init(void)
-{
- if (agp_off)
- return -EINVAL;
- return pci_register_driver(&agp_intel_i460_pci_driver);
-}
-
-static void __exit agp_intel_i460_cleanup(void)
-{
- pci_unregister_driver(&agp_intel_i460_pci_driver);
-}
-
-module_init(agp_intel_i460_init);
-module_exit(agp_intel_i460_cleanup);
-
-MODULE_AUTHOR("Chris Ahna <Christopher.J.Ahna@intel.com>");
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
index c6f181702b9a..edbc4d338117 100644
--- a/drivers/char/agp/parisc-agp.c
+++ b/drivers/char/agp/parisc-agp.c
@@ -38,7 +38,7 @@ static struct _parisc_agp_info {
int lba_cap_offset;
- u64 *gatt;
+ __le64 *gatt;
u64 gatt_entries;
u64 gart_base;
@@ -104,7 +104,7 @@ parisc_agp_create_gatt_table(struct agp_bridge_data *bridge)
int i;
for (i = 0; i < info->gatt_entries; i++) {
- info->gatt[i] = (unsigned long)agp_bridge->scratch_page;
+ info->gatt[i] = cpu_to_le64(agp_bridge->scratch_page);
}
return 0;
@@ -158,9 +158,9 @@ parisc_agp_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
for (k = 0;
k < info->io_pages_per_kpage;
k++, j++, paddr += info->io_page_size) {
- info->gatt[j] =
+ info->gatt[j] = cpu_to_le64(
parisc_agp_mask_memory(agp_bridge,
- paddr, type);
+ paddr, type));
asm_io_fdc(&info->gatt[j]);
}
}
@@ -184,7 +184,7 @@ parisc_agp_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
io_pg_start = info->io_pages_per_kpage * pg_start;
io_pg_count = info->io_pages_per_kpage * mem->page_count;
for (i = io_pg_start; i < io_pg_count + io_pg_start; i++) {
- info->gatt[i] = agp_bridge->scratch_page;
+ info->gatt[i] = cpu_to_le64(agp_bridge->scratch_page);
}
agp_bridge->driver->tlb_flush(mem);
@@ -204,7 +204,8 @@ parisc_agp_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr,
pa |= (ci >> PAGE_SHIFT) & 0xff;/* move CI (8 bits) into lowest byte */
pa |= SBA_PDIR_VALID_BIT; /* set "valid" bit */
- return cpu_to_le64(pa);
+ /* return native (big-endian) PDIR entry */
+ return pa;
}
static void
@@ -251,7 +252,8 @@ static int __init
agp_ioc_init(void __iomem *ioc_regs)
{
struct _parisc_agp_info *info = &parisc_agp_info;
- u64 iova_base, *io_pdir, io_tlb_ps;
+ u64 iova_base, io_tlb_ps;
+ __le64 *io_pdir;
int io_tlb_shift;
printk(KERN_INFO DRVPFX "IO PDIR shared with sba_iommu\n");
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index ee71376f174b..9c90b1d2c036 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -64,25 +64,6 @@
static DEFINE_MUTEX(hpet_mutex); /* replaces BKL */
static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
-/* This clocksource driver currently only works on ia64 */
-#ifdef CONFIG_IA64
-static void __iomem *hpet_mctr;
-
-static u64 read_hpet(struct clocksource *cs)
-{
- return (u64)read_counter((void __iomem *)hpet_mctr);
-}
-
-static struct clocksource clocksource_hpet = {
- .name = "hpet",
- .rating = 250,
- .read = read_hpet,
- .mask = CLOCKSOURCE_MASK(64),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-static struct clocksource *hpet_clocksource;
-#endif
-
/* A lock for concurrent access by app and isr hpet activity. */
static DEFINE_SPINLOCK(hpet_lock);
@@ -111,7 +92,7 @@ struct hpets {
unsigned long hp_delta;
unsigned int hp_ntimer;
unsigned int hp_which;
- struct hpet_dev hp_dev[];
+ struct hpet_dev hp_dev[] __counted_by(hp_ntimer);
};
static struct hpets *hpets;
@@ -728,7 +709,6 @@ static struct ctl_table hpet_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
- {}
};
static struct ctl_table_header *sysctl_header;
@@ -907,17 +887,6 @@ int hpet_alloc(struct hpet_data *hdp)
hpetp->hp_delta = hpet_calibrate(hpetp);
-/* This clocksource driver currently only works on ia64 */
-#ifdef CONFIG_IA64
- if (!hpet_clocksource) {
- hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc;
- clocksource_hpet.archdata.fsys_mmio = hpet_mctr;
- clocksource_register_hz(&clocksource_hpet, hpetp->hp_tick_freq);
- hpetp->hp_clocksource = &clocksource_hpet;
- hpet_clocksource = &clocksource_hpet;
- }
-#endif
-
return 0;
}
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 8de74dcfa18c..442c40efb200 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -37,7 +37,7 @@ config HW_RANDOM_TIMERIOMEM
config HW_RANDOM_INTEL
tristate "Intel HW Random Number Generator support"
- depends on (X86 || IA64 || COMPILE_TEST) && PCI
+ depends on (X86 || COMPILE_TEST) && PCI
default HW_RANDOM
help
This driver provides kernel-side support for the Random Number
diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
index e19b0f9f48b9..b03e80300627 100644
--- a/drivers/char/hw_random/bcm2835-rng.c
+++ b/drivers/char/hw_random/bcm2835-rng.c
@@ -70,7 +70,7 @@ static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
while ((rng_readl(priv, RNG_STATUS) >> 24) == 0) {
if (!wait)
return 0;
- hwrng_msleep(rng, 1000);
+ hwrng_yield(rng);
}
num_words = rng_readl(priv, RNG_STATUS) >> 24;
@@ -149,8 +149,6 @@ static int bcm2835_rng_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- platform_set_drvdata(pdev, priv);
-
/* map peripheral */
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index e3598ec9cfca..420f155d251f 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -678,6 +678,12 @@ long hwrng_msleep(struct hwrng *rng, unsigned int msecs)
}
EXPORT_SYMBOL_GPL(hwrng_msleep);
+long hwrng_yield(struct hwrng *rng)
+{
+ return wait_for_completion_interruptible_timeout(&rng->dying, 1);
+}
+EXPORT_SYMBOL_GPL(hwrng_yield);
+
static int __init hwrng_modinit(void)
{
int ret;
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
index 12fbe8091831..159baf00a867 100644
--- a/drivers/char/hw_random/geode-rng.c
+++ b/drivers/char/hw_random/geode-rng.c
@@ -58,7 +58,8 @@ struct amd_geode_priv {
static int geode_rng_data_read(struct hwrng *rng, u32 *data)
{
- void __iomem *mem = (void __iomem *)rng->priv;
+ struct amd_geode_priv *priv = (struct amd_geode_priv *)rng->priv;
+ void __iomem *mem = priv->membase;
*data = readl(mem + GEODE_RNG_DATA_REG);
@@ -67,7 +68,8 @@ static int geode_rng_data_read(struct hwrng *rng, u32 *data)
static int geode_rng_data_present(struct hwrng *rng, int wait)
{
- void __iomem *mem = (void __iomem *)rng->priv;
+ struct amd_geode_priv *priv = (struct amd_geode_priv *)rng->priv;
+ void __iomem *mem = priv->membase;
int data, i;
for (i = 0; i < 20; i++) {
diff --git a/drivers/char/hw_random/hisi-rng.c b/drivers/char/hw_random/hisi-rng.c
index 96438f85cafa..b6f27566e0ba 100644
--- a/drivers/char/hw_random/hisi-rng.c
+++ b/drivers/char/hw_random/hisi-rng.c
@@ -79,8 +79,6 @@ static int hisi_rng_probe(struct platform_device *pdev)
if (!rng)
return -ENOMEM;
- platform_set_drvdata(pdev, rng);
-
rng->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rng->base))
return PTR_ERR(rng->base);
diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c
index e4b385b01b11..118a72acb99b 100644
--- a/drivers/char/hw_random/imx-rngc.c
+++ b/drivers/char/hw_random/imx-rngc.c
@@ -51,8 +51,8 @@
#define RNGC_ERROR_STATUS_STAT_ERR 0x00000008
-#define RNGC_TIMEOUT 3000 /* 3 sec */
-
+#define RNGC_SELFTEST_TIMEOUT 2500 /* us */
+#define RNGC_SEED_TIMEOUT 200 /* ms */
static bool self_test = true;
module_param(self_test, bool, 0);
@@ -110,7 +110,8 @@ static int imx_rngc_self_test(struct imx_rngc *rngc)
cmd = readl(rngc->base + RNGC_COMMAND);
writel(cmd | RNGC_CMD_SELF_TEST, rngc->base + RNGC_COMMAND);
- ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT));
+ ret = wait_for_completion_timeout(&rngc->rng_op_done,
+ usecs_to_jiffies(RNGC_SELFTEST_TIMEOUT));
imx_rngc_irq_mask_clear(rngc);
if (!ret)
return -ETIMEDOUT;
@@ -182,7 +183,8 @@ static int imx_rngc_init(struct hwrng *rng)
cmd = readl(rngc->base + RNGC_COMMAND);
writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND);
- ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT));
+ ret = wait_for_completion_timeout(&rngc->rng_op_done,
+ msecs_to_jiffies(RNGC_SEED_TIMEOUT));
if (!ret) {
ret = -ETIMEDOUT;
goto err;
diff --git a/drivers/char/hw_random/ks-sa-rng.c b/drivers/char/hw_random/ks-sa-rng.c
index 2f2f21f1b659..dff7b9db7044 100644
--- a/drivers/char/hw_random/ks-sa-rng.c
+++ b/drivers/char/hw_random/ks-sa-rng.c
@@ -81,7 +81,6 @@ struct trng_regs {
};
struct ks_sa_rng {
- struct device *dev;
struct hwrng rng;
struct clk *clk;
struct regmap *regmap_cfg;
@@ -113,8 +112,7 @@ static unsigned int refill_delay_ns(unsigned long clk_rate)
static int ks_sa_rng_init(struct hwrng *rng)
{
u32 value;
- struct device *dev = (struct device *)rng->priv;
- struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev);
+ struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng);
unsigned long clk_rate = clk_get_rate(ks_sa_rng->clk);
/* Enable RNG module */
@@ -153,8 +151,7 @@ static int ks_sa_rng_init(struct hwrng *rng)
static void ks_sa_rng_cleanup(struct hwrng *rng)
{
- struct device *dev = (struct device *)rng->priv;
- struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev);
+ struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng);
/* Disable RNG */
writel(0, &ks_sa_rng->reg_rng->control);
@@ -164,8 +161,7 @@ static void ks_sa_rng_cleanup(struct hwrng *rng)
static int ks_sa_rng_data_read(struct hwrng *rng, u32 *data)
{
- struct device *dev = (struct device *)rng->priv;
- struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev);
+ struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng);
/* Read random data */
data[0] = readl(&ks_sa_rng->reg_rng->output_l);
@@ -179,8 +175,7 @@ static int ks_sa_rng_data_read(struct hwrng *rng, u32 *data)
static int ks_sa_rng_data_present(struct hwrng *rng, int wait)
{
- struct device *dev = (struct device *)rng->priv;
- struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev);
+ struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng);
u64 now = ktime_get_ns();
u32 ready;
@@ -217,7 +212,6 @@ static int ks_sa_rng_probe(struct platform_device *pdev)
if (!ks_sa_rng)
return -ENOMEM;
- ks_sa_rng->dev = dev;
ks_sa_rng->rng = (struct hwrng) {
.name = "ks_sa_hwrng",
.init = ks_sa_rng_init,
@@ -225,7 +219,6 @@ static int ks_sa_rng_probe(struct platform_device *pdev)
.data_present = ks_sa_rng_data_present,
.cleanup = ks_sa_rng_cleanup,
};
- ks_sa_rng->rng.priv = (unsigned long)dev;
ks_sa_rng->reg_rng = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ks_sa_rng->reg_rng))
@@ -235,21 +228,16 @@ static int ks_sa_rng_probe(struct platform_device *pdev)
syscon_regmap_lookup_by_phandle(dev->of_node,
"ti,syscon-sa-cfg");
- if (IS_ERR(ks_sa_rng->regmap_cfg)) {
- dev_err(dev, "syscon_node_to_regmap failed\n");
- return -EINVAL;
- }
+ if (IS_ERR(ks_sa_rng->regmap_cfg))
+ return dev_err_probe(dev, -EINVAL, "syscon_node_to_regmap failed\n");
pm_runtime_enable(dev);
ret = pm_runtime_resume_and_get(dev);
if (ret < 0) {
- dev_err(dev, "Failed to enable SA power-domain\n");
pm_runtime_disable(dev);
- return ret;
+ return dev_err_probe(dev, ret, "Failed to enable SA power-domain\n");
}
- platform_set_drvdata(pdev, ks_sa_rng);
-
return devm_hwrng_register(&pdev->dev, &ks_sa_rng->rng);
}
diff --git a/drivers/char/hw_random/meson-rng.c b/drivers/char/hw_random/meson-rng.c
index a4eb8e35f13d..75225eb9fef6 100644
--- a/drivers/char/hw_random/meson-rng.c
+++ b/drivers/char/hw_random/meson-rng.c
@@ -13,12 +13,23 @@
#include <linux/types.h>
#include <linux/of.h>
#include <linux/clk.h>
+#include <linux/iopoll.h>
-#define RNG_DATA 0x00
+#define RNG_DATA 0x00
+#define RNG_S4_DATA 0x08
+#define RNG_S4_CFG 0x00
+
+#define RUN_BIT BIT(0)
+#define SEED_READY_STS_BIT BIT(31)
+
+struct meson_rng_priv {
+ int (*read)(struct hwrng *rng, void *buf, size_t max, bool wait);
+};
struct meson_rng_data {
void __iomem *base;
struct hwrng rng;
+ struct device *dev;
};
static int meson_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
@@ -31,16 +42,62 @@ static int meson_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
return sizeof(u32);
}
+static int meson_rng_wait_status(void __iomem *cfg_addr, int bit)
+{
+ u32 status = 0;
+ int ret;
+
+ ret = readl_relaxed_poll_timeout_atomic(cfg_addr,
+ status, !(status & bit),
+ 10, 10000);
+ if (ret)
+ return -EBUSY;
+
+ return 0;
+}
+
+static int meson_s4_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+{
+ struct meson_rng_data *data =
+ container_of(rng, struct meson_rng_data, rng);
+
+ void __iomem *cfg_addr = data->base + RNG_S4_CFG;
+ int err;
+
+ writel_relaxed(readl_relaxed(cfg_addr) | SEED_READY_STS_BIT, cfg_addr);
+
+ err = meson_rng_wait_status(cfg_addr, SEED_READY_STS_BIT);
+ if (err) {
+ dev_err(data->dev, "Seed isn't ready, try again\n");
+ return err;
+ }
+
+ err = meson_rng_wait_status(cfg_addr, RUN_BIT);
+ if (err) {
+ dev_err(data->dev, "Can't get random number, try again\n");
+ return err;
+ }
+
+ *(u32 *)buf = readl_relaxed(data->base + RNG_S4_DATA);
+
+ return sizeof(u32);
+}
+
static int meson_rng_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct meson_rng_data *data;
struct clk *core_clk;
+ const struct meson_rng_priv *priv;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
+ priv = device_get_match_data(&pdev->dev);
+ if (!priv)
+ return -ENODEV;
+
data->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(data->base))
return PTR_ERR(data->base);
@@ -51,13 +108,30 @@ static int meson_rng_probe(struct platform_device *pdev)
"Failed to get core clock\n");
data->rng.name = pdev->name;
- data->rng.read = meson_rng_read;
+ data->rng.read = priv->read;
+
+ data->dev = &pdev->dev;
return devm_hwrng_register(dev, &data->rng);
}
+static const struct meson_rng_priv meson_rng_priv = {
+ .read = meson_rng_read,
+};
+
+static const struct meson_rng_priv meson_rng_priv_s4 = {
+ .read = meson_s4_rng_read,
+};
+
static const struct of_device_id meson_rng_of_match[] = {
- { .compatible = "amlogic,meson-rng", },
+ {
+ .compatible = "amlogic,meson-rng",
+ .data = (void *)&meson_rng_priv,
+ },
+ {
+ .compatible = "amlogic,meson-s4-rng",
+ .data = (void *)&meson_rng_priv_s4,
+ },
{},
};
MODULE_DEVICE_TABLE(of, meson_rng_of_match);
diff --git a/drivers/char/hw_random/mpfs-rng.c b/drivers/char/hw_random/mpfs-rng.c
index c6972734ae62..0994024daa70 100644
--- a/drivers/char/hw_random/mpfs-rng.c
+++ b/drivers/char/hw_random/mpfs-rng.c
@@ -79,8 +79,6 @@ static int mpfs_rng_probe(struct platform_device *pdev)
rng_priv->rng.read = mpfs_rng_read;
rng_priv->rng.name = pdev->name;
- platform_set_drvdata(pdev, rng_priv);
-
ret = devm_hwrng_register(&pdev->dev, &rng_priv->rng);
if (ret)
return dev_err_probe(&pdev->dev, ret, "Failed to register MPFS hwrng\n");
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index 73e408146420..aaae16b98475 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -14,7 +14,8 @@
#include <linux/hw_random.h>
#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
#include <asm/hypervisor.h>
@@ -695,20 +696,15 @@ static void n2rng_driver_version(void)
static const struct of_device_id n2rng_match[];
static int n2rng_probe(struct platform_device *op)
{
- const struct of_device_id *match;
int err = -ENOMEM;
struct n2rng *np;
- match = of_match_device(n2rng_match, &op->dev);
- if (!match)
- return -EINVAL;
-
n2rng_driver_version();
np = devm_kzalloc(&op->dev, sizeof(*np), GFP_KERNEL);
if (!np)
goto out;
np->op = op;
- np->data = (struct n2rng_template *)match->data;
+ np->data = (struct n2rng_template *)device_get_match_data(&op->dev);
INIT_DELAYED_WORK(&np->work, n2rng_work);
diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c
index 8c6a40d6ce3d..a2009fc4ad3c 100644
--- a/drivers/char/hw_random/nomadik-rng.c
+++ b/drivers/char/hw_random/nomadik-rng.c
@@ -88,4 +88,5 @@ static struct amba_driver nmk_rng_driver = {
module_amba_driver(nmk_rng_driver);
+MODULE_DESCRIPTION("ST-Ericsson Nomadik Random Number Generator");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c
index 8561a09b4681..412f54405036 100644
--- a/drivers/char/hw_random/octeon-rng.c
+++ b/drivers/char/hw_random/octeon-rng.c
@@ -33,7 +33,7 @@ static int octeon_rng_init(struct hwrng *rng)
ctl.u64 = 0;
ctl.s.ent_en = 1; /* Enable the entropy source. */
ctl.s.rng_en = 1; /* Enable the RNG hardware. */
- cvmx_write_csr((__force u64)p->control_status, ctl.u64);
+ cvmx_write_csr((unsigned long)p->control_status, ctl.u64);
return 0;
}
@@ -44,14 +44,14 @@ static void octeon_rng_cleanup(struct hwrng *rng)
ctl.u64 = 0;
/* Disable everything. */
- cvmx_write_csr((__force u64)p->control_status, ctl.u64);
+ cvmx_write_csr((unsigned long)p->control_status, ctl.u64);
}
static int octeon_rng_data_read(struct hwrng *rng, u32 *data)
{
struct octeon_rng *p = container_of(rng, struct octeon_rng, ops);
- *data = cvmx_read64_uint32((__force u64)p->result);
+ *data = cvmx_read64_uint32((unsigned long)p->result);
return sizeof(u32);
}
diff --git a/drivers/char/hw_random/st-rng.c b/drivers/char/hw_random/st-rng.c
index 6e9dfac9fc9f..23749817d83c 100644
--- a/drivers/char/hw_random/st-rng.c
+++ b/drivers/char/hw_random/st-rng.c
@@ -121,4 +121,5 @@ static struct platform_driver st_rng_driver = {
module_platform_driver(st_rng_driver);
MODULE_AUTHOR("Pankaj Dev <pankaj.dev@st.com>");
+MODULE_DESCRIPTION("ST Microelectronics HW Random Number Generator");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index efb6a9f9a11b..41e1dbea5d2e 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -17,60 +17,234 @@
#include <linux/reset.h>
#include <linux/slab.h>
-#define RNG_CR 0x00
-#define RNG_CR_RNGEN BIT(2)
-#define RNG_CR_CED BIT(5)
-
-#define RNG_SR 0x04
-#define RNG_SR_SEIS BIT(6)
-#define RNG_SR_CEIS BIT(5)
-#define RNG_SR_DRDY BIT(0)
+#define RNG_CR 0x00
+#define RNG_CR_RNGEN BIT(2)
+#define RNG_CR_CED BIT(5)
+#define RNG_CR_CONFIG1 GENMASK(11, 8)
+#define RNG_CR_NISTC BIT(12)
+#define RNG_CR_CONFIG2 GENMASK(15, 13)
+#define RNG_CR_CLKDIV_SHIFT 16
+#define RNG_CR_CLKDIV GENMASK(19, 16)
+#define RNG_CR_CONFIG3 GENMASK(25, 20)
+#define RNG_CR_CONDRST BIT(30)
+#define RNG_CR_CONFLOCK BIT(31)
+#define RNG_CR_ENTROPY_SRC_MASK (RNG_CR_CONFIG1 | RNG_CR_NISTC | RNG_CR_CONFIG2 | RNG_CR_CONFIG3)
+#define RNG_CR_CONFIG_MASK (RNG_CR_ENTROPY_SRC_MASK | RNG_CR_CED | RNG_CR_CLKDIV)
+
+#define RNG_SR 0x04
+#define RNG_SR_DRDY BIT(0)
+#define RNG_SR_CECS BIT(1)
+#define RNG_SR_SECS BIT(2)
+#define RNG_SR_CEIS BIT(5)
+#define RNG_SR_SEIS BIT(6)
+
+#define RNG_DR 0x08
+
+#define RNG_NSCR 0x0C
+#define RNG_NSCR_MASK GENMASK(17, 0)
+
+#define RNG_HTCR 0x10
+
+#define RNG_NB_RECOVER_TRIES 3
+
+struct stm32_rng_data {
+ uint max_clock_rate;
+ u32 cr;
+ u32 nscr;
+ u32 htcr;
+ bool has_cond_reset;
+};
-#define RNG_DR 0x08
+/**
+ * struct stm32_rng_config - RNG configuration data
+ *
+ * @cr: RNG configuration. 0 means default hardware RNG configuration
+ * @nscr: Noise sources control configuration.
+ * @htcr: Health tests configuration.
+ */
+struct stm32_rng_config {
+ u32 cr;
+ u32 nscr;
+ u32 htcr;
+};
struct stm32_rng_private {
struct hwrng rng;
void __iomem *base;
struct clk *clk;
struct reset_control *rst;
+ struct stm32_rng_config pm_conf;
+ const struct stm32_rng_data *data;
bool ced;
+ bool lock_conf;
};
+/*
+ * Extracts from the STM32 RNG specification when RNG supports CONDRST.
+ *
+ * When a noise source (or seed) error occurs, the RNG stops generating
+ * random numbers and sets to “1†both SEIS and SECS bits to indicate
+ * that a seed error occurred. (...)
+ *
+ * 1. Software reset by writing CONDRST at 1 and at 0 (see bitfield
+ * description for details). This step is needed only if SECS is set.
+ * Indeed, when SEIS is set and SECS is cleared it means RNG performed
+ * the reset automatically (auto-reset).
+ * 2. If SECS was set in step 1 (no auto-reset) wait for CONDRST
+ * to be cleared in the RNG_CR register, then confirm that SEIS is
+ * cleared in the RNG_SR register. Otherwise just clear SEIS bit in
+ * the RNG_SR register.
+ * 3. If SECS was set in step 1 (no auto-reset) wait for SECS to be
+ * cleared by RNG. The random number generation is now back to normal.
+ */
+static int stm32_rng_conceal_seed_error_cond_reset(struct stm32_rng_private *priv)
+{
+ struct device *dev = (struct device *)priv->rng.priv;
+ u32 sr = readl_relaxed(priv->base + RNG_SR);
+ u32 cr = readl_relaxed(priv->base + RNG_CR);
+ int err;
+
+ if (sr & RNG_SR_SECS) {
+ /* Conceal by resetting the subsystem (step 1.) */
+ writel_relaxed(cr | RNG_CR_CONDRST, priv->base + RNG_CR);
+ writel_relaxed(cr & ~RNG_CR_CONDRST, priv->base + RNG_CR);
+ } else {
+ /* RNG auto-reset (step 2.) */
+ writel_relaxed(sr & ~RNG_SR_SEIS, priv->base + RNG_SR);
+ goto end;
+ }
+
+ err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, cr, !(cr & RNG_CR_CONDRST), 10,
+ 100000);
+ if (err) {
+ dev_err(dev, "%s: timeout %x\n", __func__, sr);
+ return err;
+ }
+
+ /* Check SEIS is cleared (step 2.) */
+ if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS)
+ return -EINVAL;
+
+ err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_SR, sr, !(sr & RNG_SR_SECS), 10,
+ 100000);
+ if (err) {
+ dev_err(dev, "%s: timeout %x\n", __func__, sr);
+ return err;
+ }
+
+end:
+ return 0;
+}
+
+/*
+ * Extracts from the STM32 RNG specification, when CONDRST is not supported
+ *
+ * When a noise source (or seed) error occurs, the RNG stops generating
+ * random numbers and sets to “1†both SEIS and SECS bits to indicate
+ * that a seed error occurred. (...)
+ *
+ * The following sequence shall be used to fully recover from a seed
+ * error after the RNG initialization:
+ * 1. Clear the SEIS bit by writing it to “0â€.
+ * 2. Read out 12 words from the RNG_DR register, and discard each of
+ * them in order to clean the pipeline.
+ * 3. Confirm that SEIS is still cleared. Random number generation is
+ * back to normal.
+ */
+static int stm32_rng_conceal_seed_error_sw_reset(struct stm32_rng_private *priv)
+{
+ unsigned int i = 0;
+ u32 sr = readl_relaxed(priv->base + RNG_SR);
+
+ writel_relaxed(sr & ~RNG_SR_SEIS, priv->base + RNG_SR);
+
+ for (i = 12; i != 0; i--)
+ (void)readl_relaxed(priv->base + RNG_DR);
+
+ if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int stm32_rng_conceal_seed_error(struct hwrng *rng)
+{
+ struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng);
+
+ dev_dbg((struct device *)priv->rng.priv, "Concealing seed error\n");
+
+ if (priv->data->has_cond_reset)
+ return stm32_rng_conceal_seed_error_cond_reset(priv);
+ else
+ return stm32_rng_conceal_seed_error_sw_reset(priv);
+};
+
+
static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
- struct stm32_rng_private *priv =
- container_of(rng, struct stm32_rng_private, rng);
+ struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng);
+ unsigned int i = 0;
+ int retval = 0, err = 0;
u32 sr;
- int retval = 0;
pm_runtime_get_sync((struct device *) priv->rng.priv);
+ if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS)
+ stm32_rng_conceal_seed_error(rng);
+
while (max >= sizeof(u32)) {
sr = readl_relaxed(priv->base + RNG_SR);
- /* Manage timeout which is based on timer and take */
- /* care of initial delay time when enabling rng */
+ /*
+ * Manage timeout which is based on timer and take
+ * care of initial delay time when enabling the RNG.
+ */
if (!sr && wait) {
- int err;
-
err = readl_relaxed_poll_timeout_atomic(priv->base
+ RNG_SR,
sr, sr,
10, 50000);
- if (err)
+ if (err) {
dev_err((struct device *)priv->rng.priv,
"%s: timeout %x!\n", __func__, sr);
+ break;
+ }
+ } else if (!sr) {
+ /* The FIFO is being filled up */
+ break;
}
- /* If error detected or data not ready... */
if (sr != RNG_SR_DRDY) {
- if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
- "bad RNG status - %x\n", sr))
+ if (sr & RNG_SR_SEIS) {
+ err = stm32_rng_conceal_seed_error(rng);
+ i++;
+ if (err && i > RNG_NB_RECOVER_TRIES) {
+ dev_err((struct device *)priv->rng.priv,
+ "Couldn't recover from seed error\n");
+ return -ENOTRECOVERABLE;
+ }
+
+ continue;
+ }
+
+ if (WARN_ONCE((sr & RNG_SR_CEIS), "RNG clock too slow - %x\n", sr))
writel_relaxed(0, priv->base + RNG_SR);
- break;
}
+ /* Late seed error case: DR being 0 is an error status */
*(u32 *)data = readl_relaxed(priv->base + RNG_DR);
+ if (!*(u32 *)data) {
+ err = stm32_rng_conceal_seed_error(rng);
+ i++;
+ if (err && i > RNG_NB_RECOVER_TRIES) {
+ dev_err((struct device *)priv->rng.priv,
+ "Couldn't recover from seed error");
+ return -ENOTRECOVERABLE;
+ }
+ continue;
+ }
+
+ i = 0;
retval += sizeof(u32);
data += sizeof(u32);
max -= sizeof(u32);
@@ -82,54 +256,264 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
return retval || !wait ? retval : -EIO;
}
+static uint stm32_rng_clock_freq_restrain(struct hwrng *rng)
+{
+ struct stm32_rng_private *priv =
+ container_of(rng, struct stm32_rng_private, rng);
+ unsigned long clock_rate = 0;
+ uint clock_div = 0;
+
+ clock_rate = clk_get_rate(priv->clk);
+
+ /*
+ * Get the exponent to apply on the CLKDIV field in RNG_CR register
+ * No need to handle the case when clock-div > 0xF as it is physically
+ * impossible
+ */
+ while ((clock_rate >> clock_div) > priv->data->max_clock_rate)
+ clock_div++;
+
+ pr_debug("RNG clk rate : %lu\n", clk_get_rate(priv->clk) >> clock_div);
+
+ return clock_div;
+}
+
static int stm32_rng_init(struct hwrng *rng)
{
struct stm32_rng_private *priv =
container_of(rng, struct stm32_rng_private, rng);
int err;
+ u32 reg;
err = clk_prepare_enable(priv->clk);
if (err)
return err;
- if (priv->ced)
- writel_relaxed(RNG_CR_RNGEN, priv->base + RNG_CR);
- else
- writel_relaxed(RNG_CR_RNGEN | RNG_CR_CED,
- priv->base + RNG_CR);
-
/* clear error indicators */
writel_relaxed(0, priv->base + RNG_SR);
+ reg = readl_relaxed(priv->base + RNG_CR);
+
+ /*
+ * Keep default RNG configuration if none was specified.
+ * 0 is an invalid value as it disables all entropy sources.
+ */
+ if (priv->data->has_cond_reset && priv->data->cr) {
+ uint clock_div = stm32_rng_clock_freq_restrain(rng);
+
+ reg &= ~RNG_CR_CONFIG_MASK;
+ reg |= RNG_CR_CONDRST | (priv->data->cr & RNG_CR_ENTROPY_SRC_MASK) |
+ (clock_div << RNG_CR_CLKDIV_SHIFT);
+ if (priv->ced)
+ reg &= ~RNG_CR_CED;
+ else
+ reg |= RNG_CR_CED;
+ writel_relaxed(reg, priv->base + RNG_CR);
+
+ /* Health tests and noise control registers */
+ writel_relaxed(priv->data->htcr, priv->base + RNG_HTCR);
+ writel_relaxed(priv->data->nscr & RNG_NSCR_MASK, priv->base + RNG_NSCR);
+
+ reg &= ~RNG_CR_CONDRST;
+ reg |= RNG_CR_RNGEN;
+ if (priv->lock_conf)
+ reg |= RNG_CR_CONFLOCK;
+
+ writel_relaxed(reg, priv->base + RNG_CR);
+
+ err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, reg,
+ (!(reg & RNG_CR_CONDRST)),
+ 10, 50000);
+ if (err) {
+ dev_err((struct device *)priv->rng.priv,
+ "%s: timeout %x!\n", __func__, reg);
+ return -EINVAL;
+ }
+ } else {
+ /* Handle all RNG versions by checking if conditional reset should be set */
+ if (priv->data->has_cond_reset)
+ reg |= RNG_CR_CONDRST;
+
+ if (priv->ced)
+ reg &= ~RNG_CR_CED;
+ else
+ reg |= RNG_CR_CED;
+
+ writel_relaxed(reg, priv->base + RNG_CR);
+
+ if (priv->data->has_cond_reset)
+ reg &= ~RNG_CR_CONDRST;
+
+ reg |= RNG_CR_RNGEN;
+
+ writel_relaxed(reg, priv->base + RNG_CR);
+ }
+
+ err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_SR, reg,
+ reg & RNG_SR_DRDY,
+ 10, 100000);
+ if (err | (reg & ~RNG_SR_DRDY)) {
+ clk_disable_unprepare(priv->clk);
+ dev_err((struct device *)priv->rng.priv,
+ "%s: timeout:%x SR: %x!\n", __func__, err, reg);
+ return -EINVAL;
+ }
+
return 0;
}
-static void stm32_rng_cleanup(struct hwrng *rng)
+static int stm32_rng_remove(struct platform_device *ofdev)
{
- struct stm32_rng_private *priv =
- container_of(rng, struct stm32_rng_private, rng);
+ pm_runtime_disable(&ofdev->dev);
+
+ return 0;
+}
+
+static int __maybe_unused stm32_rng_runtime_suspend(struct device *dev)
+{
+ struct stm32_rng_private *priv = dev_get_drvdata(dev);
+ u32 reg;
- writel_relaxed(0, priv->base + RNG_CR);
+ reg = readl_relaxed(priv->base + RNG_CR);
+ reg &= ~RNG_CR_RNGEN;
+ writel_relaxed(reg, priv->base + RNG_CR);
clk_disable_unprepare(priv->clk);
+
+ return 0;
}
+static int __maybe_unused stm32_rng_suspend(struct device *dev)
+{
+ struct stm32_rng_private *priv = dev_get_drvdata(dev);
+
+ if (priv->data->has_cond_reset) {
+ priv->pm_conf.nscr = readl_relaxed(priv->base + RNG_NSCR);
+ priv->pm_conf.htcr = readl_relaxed(priv->base + RNG_HTCR);
+ }
+
+ /* Do not save that RNG is enabled as it will be handled at resume */
+ priv->pm_conf.cr = readl_relaxed(priv->base + RNG_CR) & ~RNG_CR_RNGEN;
+
+ writel_relaxed(priv->pm_conf.cr, priv->base + RNG_CR);
+
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static int __maybe_unused stm32_rng_runtime_resume(struct device *dev)
+{
+ struct stm32_rng_private *priv = dev_get_drvdata(dev);
+ int err;
+ u32 reg;
+
+ err = clk_prepare_enable(priv->clk);
+ if (err)
+ return err;
+
+ /* Clean error indications */
+ writel_relaxed(0, priv->base + RNG_SR);
+
+ reg = readl_relaxed(priv->base + RNG_CR);
+ reg |= RNG_CR_RNGEN;
+ writel_relaxed(reg, priv->base + RNG_CR);
+
+ return 0;
+}
+
+static int __maybe_unused stm32_rng_resume(struct device *dev)
+{
+ struct stm32_rng_private *priv = dev_get_drvdata(dev);
+ int err;
+ u32 reg;
+
+ err = clk_prepare_enable(priv->clk);
+ if (err)
+ return err;
+
+ /* Clean error indications */
+ writel_relaxed(0, priv->base + RNG_SR);
+
+ if (priv->data->has_cond_reset) {
+ /*
+ * Correct configuration in bits [29:4] must be set in the same
+ * access that set RNG_CR_CONDRST bit. Else config setting is
+ * not taken into account. CONFIGLOCK bit must also be unset but
+ * it is not handled at the moment.
+ */
+ writel_relaxed(priv->pm_conf.cr | RNG_CR_CONDRST, priv->base + RNG_CR);
+
+ writel_relaxed(priv->pm_conf.nscr, priv->base + RNG_NSCR);
+ writel_relaxed(priv->pm_conf.htcr, priv->base + RNG_HTCR);
+
+ reg = readl_relaxed(priv->base + RNG_CR);
+ reg |= RNG_CR_RNGEN;
+ reg &= ~RNG_CR_CONDRST;
+ writel_relaxed(reg, priv->base + RNG_CR);
+
+ err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, reg,
+ reg & ~RNG_CR_CONDRST, 10, 100000);
+
+ if (err) {
+ clk_disable_unprepare(priv->clk);
+ dev_err((struct device *)priv->rng.priv,
+ "%s: timeout:%x CR: %x!\n", __func__, err, reg);
+ return -EINVAL;
+ }
+ } else {
+ reg = priv->pm_conf.cr;
+ reg |= RNG_CR_RNGEN;
+ writel_relaxed(reg, priv->base + RNG_CR);
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops __maybe_unused stm32_rng_pm_ops = {
+ SET_RUNTIME_PM_OPS(stm32_rng_runtime_suspend,
+ stm32_rng_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(stm32_rng_suspend,
+ stm32_rng_resume)
+};
+
+static const struct stm32_rng_data stm32mp13_rng_data = {
+ .has_cond_reset = true,
+ .max_clock_rate = 48000000,
+ .cr = 0x00F00D00,
+ .nscr = 0x2B5BB,
+ .htcr = 0x969D,
+};
+
+static const struct stm32_rng_data stm32_rng_data = {
+ .has_cond_reset = false,
+ .max_clock_rate = 3000000,
+};
+
+static const struct of_device_id stm32_rng_match[] = {
+ {
+ .compatible = "st,stm32mp13-rng",
+ .data = &stm32mp13_rng_data,
+ },
+ {
+ .compatible = "st,stm32-rng",
+ .data = &stm32_rng_data,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, stm32_rng_match);
+
static int stm32_rng_probe(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
struct device_node *np = ofdev->dev.of_node;
struct stm32_rng_private *priv;
- struct resource res;
- int err;
+ struct resource *res;
priv = devm_kzalloc(dev, sizeof(struct stm32_rng_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- err = of_address_to_resource(np, 0, &res);
- if (err)
- return err;
-
- priv->base = devm_ioremap_resource(dev, &res);
+ priv->base = devm_platform_get_and_ioremap_resource(ofdev, 0, &res);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
@@ -145,14 +529,16 @@ static int stm32_rng_probe(struct platform_device *ofdev)
}
priv->ced = of_property_read_bool(np, "clock-error-detect");
+ priv->lock_conf = of_property_read_bool(np, "st,rng-lock-conf");
+
+ priv->data = of_device_get_match_data(dev);
+ if (!priv->data)
+ return -ENODEV;
dev_set_drvdata(dev, priv);
priv->rng.name = dev_driver_string(dev);
-#ifndef CONFIG_PM
priv->rng.init = stm32_rng_init;
- priv->rng.cleanup = stm32_rng_cleanup;
-#endif
priv->rng.read = stm32_rng_read;
priv->rng.priv = (unsigned long) dev;
priv->rng.quality = 900;
@@ -164,51 +550,10 @@ static int stm32_rng_probe(struct platform_device *ofdev)
return devm_hwrng_register(dev, &priv->rng);
}
-static int stm32_rng_remove(struct platform_device *ofdev)
-{
- pm_runtime_disable(&ofdev->dev);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int stm32_rng_runtime_suspend(struct device *dev)
-{
- struct stm32_rng_private *priv = dev_get_drvdata(dev);
-
- stm32_rng_cleanup(&priv->rng);
-
- return 0;
-}
-
-static int stm32_rng_runtime_resume(struct device *dev)
-{
- struct stm32_rng_private *priv = dev_get_drvdata(dev);
-
- return stm32_rng_init(&priv->rng);
-}
-#endif
-
-static const struct dev_pm_ops stm32_rng_pm_ops = {
- SET_RUNTIME_PM_OPS(stm32_rng_runtime_suspend,
- stm32_rng_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
-};
-
-
-static const struct of_device_id stm32_rng_match[] = {
- {
- .compatible = "st,stm32-rng",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, stm32_rng_match);
-
static struct platform_driver stm32_rng_driver = {
.driver = {
.name = "stm32-rng",
- .pm = &stm32_rng_pm_ops,
+ .pm = pm_ptr(&stm32_rng_pm_ops),
.of_match_table = stm32_rng_match,
},
.probe = stm32_rng_probe,
diff --git a/drivers/char/hw_random/xgene-rng.c b/drivers/char/hw_random/xgene-rng.c
index 99f4e86ac3e9..7382724bf501 100644
--- a/drivers/char/hw_random/xgene-rng.c
+++ b/drivers/char/hw_random/xgene-rng.c
@@ -321,7 +321,6 @@ static int xgene_rng_probe(struct platform_device *pdev)
return -ENOMEM;
ctx->dev = &pdev->dev;
- platform_set_drvdata(pdev, ctx);
ctx->csr_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ctx->csr_base))
diff --git a/drivers/char/hw_random/xiphera-trng.c b/drivers/char/hw_random/xiphera-trng.c
index 2c586d1fe8a9..4af64f76c8d6 100644
--- a/drivers/char/hw_random/xiphera-trng.c
+++ b/drivers/char/hw_random/xiphera-trng.c
@@ -121,8 +121,6 @@ static int xiphera_trng_probe(struct platform_device *pdev)
return ret;
}
- platform_set_drvdata(pdev, trng);
-
return 0;
}
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 186f1fee7534..d6f14279684d 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -5377,20 +5377,15 @@ static void send_panic_events(struct ipmi_smi *intf, char *str)
j = 0;
while (*p) {
- int size = strlen(p);
+ int size = strnlen(p, 11);
- if (size > 11)
- size = 11;
data[0] = 0;
data[1] = 0;
data[2] = 0xf0; /* OEM event without timestamp. */
data[3] = intf->addrinfo[0].address;
data[4] = j++; /* sequence # */
- /*
- * Always give 11 bytes, so strncpy will fill
- * it with zeroes for me.
- */
- strncpy(data+5, p, 11);
+
+ memcpy_and_pad(data+5, 11, p, size, '\0');
p += size;
ipmi_panic_request_and_wait(intf, &addr, &msg);
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index 870659d91db2..941d2dcc8c9d 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -656,7 +656,6 @@ static struct ctl_table ipmi_table[] = {
.maxlen = sizeof(poweroff_powercycle),
.mode = 0644,
.proc_handler = proc_dointvec },
- { }
};
static struct ctl_table_header *ipmi_table_header;
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index df8dd50b4cbe..1f7600c361e6 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -1945,7 +1945,7 @@ static int new_ssif_client(int addr, char *adapter_name,
}
}
- strncpy(addr_info->binfo.type, DEVICE_NAME,
+ strscpy(addr_info->binfo.type, DEVICE_NAME,
sizeof(addr_info->binfo.type));
addr_info->binfo.addr = addr;
addr_info->binfo.platform_data = addr_info;
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 1052b0f2d4cf..3c6670cf905f 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -31,10 +31,6 @@
#include <linux/uaccess.h>
#include <linux/security.h>
-#ifdef CONFIG_IA64
-# include <linux/efi.h>
-#endif
-
#define DEVMEM_MINOR 1
#define DEVPORT_MINOR 4
@@ -277,13 +273,6 @@ int __weak phys_mem_access_prot_allowed(struct file *file,
#ifdef pgprot_noncached
static int uncached_access(struct file *file, phys_addr_t addr)
{
-#if defined(CONFIG_IA64)
- /*
- * On ia64, we ignore O_DSYNC because we cannot tolerate memory
- * attribute aliases.
- */
- return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
-#else
/*
* Accessing memory above the top the kernel knows about or through a
* file pointer
@@ -292,7 +281,6 @@ static int uncached_access(struct file *file, phys_addr_t addr)
if (file->f_flags & O_DSYNC)
return 1;
return addr >= __pa(high_memory);
-#endif
}
#endif
@@ -640,6 +628,7 @@ static int open_port(struct inode *inode, struct file *filp)
#define full_lseek null_lseek
#define write_zero write_null
#define write_iter_zero write_iter_null
+#define splice_write_zero splice_write_null
#define open_mem open_port
static const struct file_operations __maybe_unused mem_fops = {
@@ -677,6 +666,8 @@ static const struct file_operations zero_fops = {
.read_iter = read_iter_zero,
.read = read_zero,
.write_iter = write_iter_zero,
+ .splice_read = copy_splice_read,
+ .splice_write = splice_write_zero,
.mmap = mmap_zero,
.get_unmapped_area = get_unmapped_area_zero,
#ifndef CONFIG_MMU
@@ -688,6 +679,7 @@ static const struct file_operations full_fops = {
.llseek = full_lseek,
.read_iter = read_iter_zero,
.write = write_full,
+ .splice_read = copy_splice_read,
};
static const struct memdev {
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
deleted file mode 100644
index b35f651837c8..000000000000
--- a/drivers/char/mspec.c
+++ /dev/null
@@ -1,295 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2001-2006 Silicon Graphics, Inc. All rights
- * reserved.
- */
-
-/*
- * SN Platform Special Memory (mspec) Support
- *
- * This driver exports the SN special memory (mspec) facility to user
- * processes.
- * There are two types of memory made available thru this driver:
- * uncached and cached.
- *
- * Uncached are used for memory write combining feature of the ia64
- * cpu.
- *
- * Cached are used for areas of memory that are used as cached addresses
- * on our partition and used as uncached addresses from other partitions.
- * Due to a design constraint of the SN2 Shub, you can not have processors
- * on the same FSB perform both a cached and uncached reference to the
- * same cache line. These special memory cached regions prevent the
- * kernel from ever dropping in a TLB entry and therefore prevent the
- * processor from ever speculating a cache line from this page.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/vmalloc.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/numa.h>
-#include <linux/refcount.h>
-#include <asm/page.h>
-#include <linux/atomic.h>
-#include <asm/tlbflush.h>
-#include <asm/uncached.h>
-
-
-#define CACHED_ID "Cached,"
-#define UNCACHED_ID "Uncached"
-#define REVISION "4.0"
-#define MSPEC_BASENAME "mspec"
-
-/*
- * Page types allocated by the device.
- */
-enum mspec_page_type {
- MSPEC_CACHED = 2,
- MSPEC_UNCACHED
-};
-
-/*
- * One of these structures is allocated when an mspec region is mmaped. The
- * structure is pointed to by the vma->vm_private_data field in the vma struct.
- * This structure is used to record the addresses of the mspec pages.
- * This structure is shared by all vma's that are split off from the
- * original vma when split_vma()'s are done.
- *
- * The refcnt is incremented atomically because mm->mmap_lock does not
- * protect in fork case where multiple tasks share the vma_data.
- */
-struct vma_data {
- refcount_t refcnt; /* Number of vmas sharing the data. */
- spinlock_t lock; /* Serialize access to this structure. */
- int count; /* Number of pages allocated. */
- enum mspec_page_type type; /* Type of pages allocated. */
- unsigned long vm_start; /* Original (unsplit) base. */
- unsigned long vm_end; /* Original (unsplit) end. */
- unsigned long maddr[]; /* Array of MSPEC addresses. */
-};
-
-/*
- * mspec_open
- *
- * Called when a device mapping is created by a means other than mmap
- * (via fork, munmap, etc.). Increments the reference count on the
- * underlying mspec data so it is not freed prematurely.
- */
-static void
-mspec_open(struct vm_area_struct *vma)
-{
- struct vma_data *vdata;
-
- vdata = vma->vm_private_data;
- refcount_inc(&vdata->refcnt);
-}
-
-/*
- * mspec_close
- *
- * Called when unmapping a device mapping. Frees all mspec pages
- * belonging to all the vma's sharing this vma_data structure.
- */
-static void
-mspec_close(struct vm_area_struct *vma)
-{
- struct vma_data *vdata;
- int index, last_index;
- unsigned long my_page;
-
- vdata = vma->vm_private_data;
-
- if (!refcount_dec_and_test(&vdata->refcnt))
- return;
-
- last_index = (vdata->vm_end - vdata->vm_start) >> PAGE_SHIFT;
- for (index = 0; index < last_index; index++) {
- if (vdata->maddr[index] == 0)
- continue;
- /*
- * Clear the page before sticking it back
- * into the pool.
- */
- my_page = vdata->maddr[index];
- vdata->maddr[index] = 0;
- memset((char *)my_page, 0, PAGE_SIZE);
- uncached_free_page(my_page, 1);
- }
-
- kvfree(vdata);
-}
-
-/*
- * mspec_fault
- *
- * Creates a mspec page and maps it to user space.
- */
-static vm_fault_t
-mspec_fault(struct vm_fault *vmf)
-{
- unsigned long paddr, maddr;
- unsigned long pfn;
- pgoff_t index = vmf->pgoff;
- struct vma_data *vdata = vmf->vma->vm_private_data;
-
- maddr = (volatile unsigned long) vdata->maddr[index];
- if (maddr == 0) {
- maddr = uncached_alloc_page(numa_node_id(), 1);
- if (maddr == 0)
- return VM_FAULT_OOM;
-
- spin_lock(&vdata->lock);
- if (vdata->maddr[index] == 0) {
- vdata->count++;
- vdata->maddr[index] = maddr;
- } else {
- uncached_free_page(maddr, 1);
- maddr = vdata->maddr[index];
- }
- spin_unlock(&vdata->lock);
- }
-
- paddr = maddr & ~__IA64_UNCACHED_OFFSET;
- pfn = paddr >> PAGE_SHIFT;
-
- return vmf_insert_pfn(vmf->vma, vmf->address, pfn);
-}
-
-static const struct vm_operations_struct mspec_vm_ops = {
- .open = mspec_open,
- .close = mspec_close,
- .fault = mspec_fault,
-};
-
-/*
- * mspec_mmap
- *
- * Called when mmapping the device. Initializes the vma with a fault handler
- * and private data structure necessary to allocate, track, and free the
- * underlying pages.
- */
-static int
-mspec_mmap(struct file *file, struct vm_area_struct *vma,
- enum mspec_page_type type)
-{
- struct vma_data *vdata;
- int pages, vdata_size;
-
- if (vma->vm_pgoff != 0)
- return -EINVAL;
-
- if ((vma->vm_flags & VM_SHARED) == 0)
- return -EINVAL;
-
- if ((vma->vm_flags & VM_WRITE) == 0)
- return -EPERM;
-
- pages = vma_pages(vma);
- vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
- vdata = kvzalloc(vdata_size, GFP_KERNEL);
- if (!vdata)
- return -ENOMEM;
-
- vdata->vm_start = vma->vm_start;
- vdata->vm_end = vma->vm_end;
- vdata->type = type;
- spin_lock_init(&vdata->lock);
- refcount_set(&vdata->refcnt, 1);
- vma->vm_private_data = vdata;
-
- vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP);
- if (vdata->type == MSPEC_UNCACHED)
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- vma->vm_ops = &mspec_vm_ops;
-
- return 0;
-}
-
-static int
-cached_mmap(struct file *file, struct vm_area_struct *vma)
-{
- return mspec_mmap(file, vma, MSPEC_CACHED);
-}
-
-static int
-uncached_mmap(struct file *file, struct vm_area_struct *vma)
-{
- return mspec_mmap(file, vma, MSPEC_UNCACHED);
-}
-
-static const struct file_operations cached_fops = {
- .owner = THIS_MODULE,
- .mmap = cached_mmap,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice cached_miscdev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "mspec_cached",
- .fops = &cached_fops
-};
-
-static const struct file_operations uncached_fops = {
- .owner = THIS_MODULE,
- .mmap = uncached_mmap,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice uncached_miscdev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "mspec_uncached",
- .fops = &uncached_fops
-};
-
-/*
- * mspec_init
- *
- * Called at boot time to initialize the mspec facility.
- */
-static int __init
-mspec_init(void)
-{
- int ret;
-
- ret = misc_register(&cached_miscdev);
- if (ret) {
- printk(KERN_ERR "%s: failed to register device %i\n",
- CACHED_ID, ret);
- return ret;
- }
- ret = misc_register(&uncached_miscdev);
- if (ret) {
- printk(KERN_ERR "%s: failed to register device %i\n",
- UNCACHED_ID, ret);
- misc_deregister(&cached_miscdev);
- return ret;
- }
-
- printk(KERN_INFO "%s %s initialized devices: %s %s\n",
- MSPEC_BASENAME, REVISION, CACHED_ID, UNCACHED_ID);
-
- return 0;
-}
-
-static void __exit
-mspec_exit(void)
-{
- misc_deregister(&uncached_miscdev);
- misc_deregister(&cached_miscdev);
-}
-
-module_init(mspec_init);
-module_exit(mspec_exit);
-
-MODULE_AUTHOR("Silicon Graphics, Inc. <linux-altix@sgi.com>");
-MODULE_DESCRIPTION("Driver for SGI SN special memory operations");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 3cb37760dfec..4a9c79391dee 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1683,7 +1683,6 @@ static struct ctl_table random_table[] = {
.mode = 0444,
.proc_handler = proc_do_uuid,
},
- { }
};
/*
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 9211531689b2..22d249333f53 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -920,7 +920,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
if (ret > 0) {
struct inode *inode = file_inode(file);
- inode->i_atime = current_time(inode);
+ inode_set_atime_to_ts(inode, current_time(inode));
}
return ret;
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 680d1ef2a217..431e9e5bf9c1 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -106,7 +106,7 @@ struct port_buffer {
unsigned int sgpages;
/* sg is used if spages > 0. sg must be the last in is struct */
- struct scatterlist sg[];
+ struct scatterlist sg[] __counted_by(sgpages);
};
/*
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index f60bb6151402..019cf6079cec 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -84,18 +84,13 @@
#include <linux/sysctl.h>
#include <linux/fs.h>
#include <linux/cdev.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/uaccess.h>
-#ifdef CONFIG_OF
-/* For open firmware. */
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#endif
-
#include "xilinx_hwicap.h"
#include "buffer_icap.h"
#include "fifo_icap.h"
@@ -601,14 +596,14 @@ static const struct file_operations hwicap_fops = {
.llseek = noop_llseek,
};
-static int hwicap_setup(struct device *dev, int id,
- const struct resource *regs_res,
+static int hwicap_setup(struct platform_device *pdev, int id,
const struct hwicap_driver_config *config,
const struct config_registers *config_regs)
{
dev_t devt;
struct hwicap_drvdata *drvdata = NULL;
- int retval = 0;
+ struct device *dev = &pdev->dev;
+ int retval;
dev_info(dev, "Xilinx icap port driver\n");
@@ -636,72 +631,39 @@ static int hwicap_setup(struct device *dev, int id,
devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR + id);
- drvdata = kzalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL);
+ drvdata = devm_kzalloc(dev, sizeof(struct hwicap_drvdata), GFP_KERNEL);
if (!drvdata) {
retval = -ENOMEM;
- goto failed0;
+ goto failed;
}
dev_set_drvdata(dev, (void *)drvdata);
- if (!regs_res) {
- dev_err(dev, "Couldn't get registers resource\n");
- retval = -EFAULT;
- goto failed1;
- }
-
- drvdata->mem_start = regs_res->start;
- drvdata->mem_end = regs_res->end;
- drvdata->mem_size = resource_size(regs_res);
-
- if (!request_mem_region(drvdata->mem_start,
- drvdata->mem_size, DRIVER_NAME)) {
- dev_err(dev, "Couldn't lock memory region at %Lx\n",
- (unsigned long long) regs_res->start);
- retval = -EBUSY;
- goto failed1;
+ drvdata->base_address = devm_platform_ioremap_resource(pdev, 0);
+ if (!drvdata->base_address) {
+ retval = -ENODEV;
+ goto failed;
}
drvdata->devt = devt;
drvdata->dev = dev;
- drvdata->base_address = ioremap(drvdata->mem_start, drvdata->mem_size);
- if (!drvdata->base_address) {
- dev_err(dev, "ioremap() failed\n");
- retval = -ENOMEM;
- goto failed2;
- }
-
drvdata->config = config;
drvdata->config_regs = config_regs;
mutex_init(&drvdata->sem);
drvdata->is_open = 0;
- dev_info(dev, "ioremap %llx to %p with size %llx\n",
- (unsigned long long) drvdata->mem_start,
- drvdata->base_address,
- (unsigned long long) drvdata->mem_size);
-
cdev_init(&drvdata->cdev, &hwicap_fops);
drvdata->cdev.owner = THIS_MODULE;
retval = cdev_add(&drvdata->cdev, devt, 1);
if (retval) {
dev_err(dev, "cdev_add() failed\n");
- goto failed3;
+ goto failed;
}
device_create(&icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id);
return 0; /* success */
- failed3:
- iounmap(drvdata->base_address);
-
- failed2:
- release_mem_region(regs_res->start, drvdata->mem_size);
-
- failed1:
- kfree(drvdata);
-
- failed0:
+ failed:
mutex_lock(&icap_sem);
probed_devices[id] = 0;
mutex_unlock(&icap_sem);
@@ -723,75 +685,22 @@ static struct hwicap_driver_config fifo_icap_config = {
.reset = fifo_icap_reset,
};
-#ifdef CONFIG_OF
-static int hwicap_of_probe(struct platform_device *op,
- const struct hwicap_driver_config *config)
-{
- struct resource res;
- const unsigned int *id;
- const char *family;
- int rc;
- const struct config_registers *regs;
-
-
- rc = of_address_to_resource(op->dev.of_node, 0, &res);
- if (rc) {
- dev_err(&op->dev, "invalid address\n");
- return rc;
- }
-
- id = of_get_property(op->dev.of_node, "port-number", NULL);
-
- /* It's most likely that we're using V4, if the family is not
- * specified
- */
- regs = &v4_config_registers;
- family = of_get_property(op->dev.of_node, "xlnx,family", NULL);
-
- if (family) {
- if (!strcmp(family, "virtex2p"))
- regs = &v2_config_registers;
- else if (!strcmp(family, "virtex4"))
- regs = &v4_config_registers;
- else if (!strcmp(family, "virtex5"))
- regs = &v5_config_registers;
- else if (!strcmp(family, "virtex6"))
- regs = &v6_config_registers;
- }
- return hwicap_setup(&op->dev, id ? *id : -1, &res, config,
- regs);
-}
-#else
-static inline int hwicap_of_probe(struct platform_device *op,
- const struct hwicap_driver_config *config)
-{
- return -EINVAL;
-}
-#endif /* CONFIG_OF */
-
-static const struct of_device_id hwicap_of_match[];
static int hwicap_drv_probe(struct platform_device *pdev)
{
- const struct of_device_id *match;
- struct resource *res;
const struct config_registers *regs;
+ const struct hwicap_driver_config *config;
const char *family;
+ int id = -1;
- match = of_match_device(hwicap_of_match, &pdev->dev);
- if (match)
- return hwicap_of_probe(pdev, match->data);
+ config = device_get_match_data(&pdev->dev);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
+ of_property_read_u32(pdev->dev.of_node, "port-number", &id);
/* It's most likely that we're using V4, if the family is not
* specified
*/
regs = &v4_config_registers;
- family = pdev->dev.platform_data;
-
- if (family) {
+ if (!of_property_read_string(pdev->dev.of_node, "xlnx,family", &family)) {
if (!strcmp(family, "virtex2p"))
regs = &v2_config_registers;
else if (!strcmp(family, "virtex4"))
@@ -801,9 +710,7 @@ static int hwicap_drv_probe(struct platform_device *pdev)
else if (!strcmp(family, "virtex6"))
regs = &v6_config_registers;
}
-
- return hwicap_setup(&pdev->dev, pdev->id, res,
- &buffer_icap_config, regs);
+ return hwicap_setup(pdev, id, config, regs);
}
static void hwicap_drv_remove(struct platform_device *pdev)
@@ -815,16 +722,12 @@ static void hwicap_drv_remove(struct platform_device *pdev)
device_destroy(&icap_class, drvdata->devt);
cdev_del(&drvdata->cdev);
- iounmap(drvdata->base_address);
- release_mem_region(drvdata->mem_start, drvdata->mem_size);
- kfree(drvdata);
mutex_lock(&icap_sem);
probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
mutex_unlock(&icap_sem);
}
-#ifdef CONFIG_OF
/* Match table for device tree binding */
static const struct of_device_id hwicap_of_match[] = {
{ .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
@@ -832,9 +735,6 @@ static const struct of_device_id hwicap_of_match[] = {
{},
};
MODULE_DEVICE_TABLE(of, hwicap_of_match);
-#else
-#define hwicap_of_match NULL
-#endif
static struct platform_driver hwicap_platform_driver = {
.probe = hwicap_drv_probe,
diff --git a/drivers/clk/.kunitconfig b/drivers/clk/.kunitconfig
index 2fbeb71316f8..efa12ac2b3f2 100644
--- a/drivers/clk/.kunitconfig
+++ b/drivers/clk/.kunitconfig
@@ -2,4 +2,5 @@ CONFIG_KUNIT=y
CONFIG_COMMON_CLK=y
CONFIG_CLK_KUNIT_TEST=y
CONFIG_CLK_GATE_KUNIT_TEST=y
+CONFIG_CLK_FD_KUNIT_TEST=y
CONFIG_UML_PCI_OVER_VIRTIO=n
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c30099866174..c30d0d396f7a 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -277,6 +277,15 @@ config COMMON_CLK_S2MPS11
clock. These multi-function devices have two (S2MPS14) or three
(S2MPS11, S5M8767) fixed-rate oscillators, clocked at 32KHz each.
+config CLK_TWL
+ tristate "Clock driver for the TWL PMIC family"
+ depends on TWL4030_CORE
+ help
+ Enable support for controlling the clock resources on TWL family
+ PMICs. These devices have some 32K clock outputs which can be
+ controlled by software. For now, only the TWL6032 clocks are
+ supported.
+
config CLK_TWL6040
tristate "External McPDM functional clock from twl6040"
depends on TWL6040_CORE
@@ -517,4 +526,11 @@ config CLK_GATE_KUNIT_TEST
help
Kunit test for the basic clk gate type.
+config CLK_FD_KUNIT_TEST
+ tristate "Basic fractional divider type Kunit test" if !KUNIT_ALL_TESTS
+ depends on KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ Kunit test for the clk-fractional-divider type.
+
endif
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 18969cbd4bb1..ed71f2e0ee36 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-multiplier.o
obj-$(CONFIG_COMMON_CLK) += clk-mux.o
obj-$(CONFIG_COMMON_CLK) += clk-composite.o
obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o
+obj-$(CONFIG_CLK_FD_KUNIT_TEST) += clk-fractional-divider_test.o
obj-$(CONFIG_COMMON_CLK) += clk-gpio.o
ifeq ($(CONFIG_OF), y)
obj-$(CONFIG_COMMON_CLK) += clk-conf.o
@@ -72,6 +73,7 @@ obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o
obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o
obj-$(CONFIG_COMMON_CLK_TPS68470) += clk-tps68470.o
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
+obj-$(CONFIG_CLK_TWL) += clk-twl.o
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
obj-$(CONFIG_COMMON_CLK_RS9_PCIE) += clk-renesas-pcie.o
obj-$(CONFIG_COMMON_CLK_SI521XX) += clk-si521xx.o
diff --git a/drivers/clk/analogbits/Kconfig b/drivers/clk/analogbits/Kconfig
index 1e291b185438..7d73db0fcd49 100644
--- a/drivers/clk/analogbits/Kconfig
+++ b/drivers/clk/analogbits/Kconfig
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
config CLK_ANALOGBITS_WRPLL_CLN28HPC
- bool
+ tristate
diff --git a/drivers/clk/analogbits/wrpll-cln28hpc.c b/drivers/clk/analogbits/wrpll-cln28hpc.c
index 09ca82356399..65d422a588e1 100644
--- a/drivers/clk/analogbits/wrpll-cln28hpc.c
+++ b/drivers/clk/analogbits/wrpll-cln28hpc.c
@@ -28,6 +28,7 @@
#include <linux/math64.h>
#include <linux/math.h>
#include <linux/minmax.h>
+#include <linux/module.h>
#include <linux/clk/analogbits-wrpll-cln28hpc.h>
@@ -312,6 +313,7 @@ int wrpll_configure_for_rate(struct wrpll_cfg *c, u32 target_rate,
return 0;
}
+EXPORT_SYMBOL_GPL(wrpll_configure_for_rate);
/**
* wrpll_calc_output_rate() - calculate the PLL's target output rate
@@ -349,6 +351,7 @@ unsigned long wrpll_calc_output_rate(const struct wrpll_cfg *c,
return n;
}
+EXPORT_SYMBOL_GPL(wrpll_calc_output_rate);
/**
* wrpll_calc_max_lock_us() - return the time for the PLL to lock
@@ -366,3 +369,8 @@ unsigned int wrpll_calc_max_lock_us(const struct wrpll_cfg *c)
{
return MAX_LOCK_US;
}
+EXPORT_SYMBOL_GPL(wrpll_calc_max_lock_us);
+
+MODULE_AUTHOR("Paul Walmsley <paul.walmsley@sifive.com>");
+MODULE_DESCRIPTION("Analog Bits Wide-Range PLL library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c
index 40c84f5af5e8..b991180beea1 100644
--- a/drivers/clk/at91/clk-utmi.c
+++ b/drivers/clk/at91/clk-utmi.c
@@ -161,13 +161,11 @@ at91_clk_register_utmi_internal(struct regmap *regmap_pmc,
init.name = name;
init.ops = ops;
- if (parent_hw) {
- init.parent_hws = parent_hw ? (const struct clk_hw **)&parent_hw : NULL;
- init.num_parents = parent_hw ? 1 : 0;
- } else {
- init.parent_names = parent_name ? &parent_name : NULL;
- init.num_parents = parent_name ? 1 : 0;
- }
+ if (parent_hw)
+ init.parent_hws = (const struct clk_hw **)&parent_hw;
+ else
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
init.flags = flags;
utmi->hw.init = &init;
diff --git a/drivers/clk/clk-asm9260.c b/drivers/clk/clk-asm9260.c
index 8b3c059e19a1..3432c801f1bd 100644
--- a/drivers/clk/clk-asm9260.c
+++ b/drivers/clk/clk-asm9260.c
@@ -255,7 +255,7 @@ static struct asm9260_mux_clock asm9260_mux_clks[] __initdata = {
static void __init asm9260_acc_init(struct device_node *np)
{
- struct clk_hw *hw, *pll_hw;
+ struct clk_hw *pll_hw;
struct clk_hw **hws;
const char *pll_clk = "pll";
struct clk_parent_data pll_parent_data = { .index = 0 };
@@ -283,7 +283,7 @@ static void __init asm9260_acc_init(struct device_node *np)
for (n = 0; n < ARRAY_SIZE(asm9260_mux_clks); n++) {
const struct asm9260_mux_clock *mc = &asm9260_mux_clks[n];
- hw = clk_hw_register_mux_table_parent_data(NULL, mc->name, mc->parent_data,
+ clk_hw_register_mux_table_parent_data(NULL, mc->name, mc->parent_data,
mc->num_parents, mc->flags, base + mc->offset,
0, mc->mask, 0, mc->table, &asm9260_clk_lock);
}
@@ -292,7 +292,7 @@ static void __init asm9260_acc_init(struct device_node *np)
for (n = 0; n < ARRAY_SIZE(asm9260_mux_gates); n++) {
const struct asm9260_gate_data *gd = &asm9260_mux_gates[n];
- hw = clk_hw_register_gate(NULL, gd->name,
+ clk_hw_register_gate(NULL, gd->name,
gd->parent_name, gd->flags | CLK_SET_RATE_PARENT,
base + gd->reg, gd->bit_idx, 0, &asm9260_clk_lock);
}
diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c
index cdee4958f26d..b0122093c6ff 100644
--- a/drivers/clk/clk-cdce925.c
+++ b/drivers/clk/clk-cdce925.c
@@ -25,25 +25,11 @@
* Model this as 2 PLL clocks which are parents to the outputs.
*/
-enum {
- CDCE913,
- CDCE925,
- CDCE937,
- CDCE949,
-};
-
struct clk_cdce925_chip_info {
int num_plls;
int num_outputs;
};
-static const struct clk_cdce925_chip_info clk_cdce925_chip_info_tbl[] = {
- [CDCE913] = { .num_plls = 1, .num_outputs = 3 },
- [CDCE925] = { .num_plls = 2, .num_outputs = 5 },
- [CDCE937] = { .num_plls = 3, .num_outputs = 7 },
- [CDCE949] = { .num_plls = 4, .num_outputs = 9 },
-};
-
#define MAX_NUMBER_OF_PLLS 4
#define MAX_NUMBER_OF_OUTPUTS 9
@@ -621,20 +607,10 @@ static struct regmap_bus regmap_cdce925_bus = {
.read = cdce925_regmap_i2c_read,
};
-static const struct i2c_device_id cdce925_id[] = {
- { "cdce913", CDCE913 },
- { "cdce925", CDCE925 },
- { "cdce937", CDCE937 },
- { "cdce949", CDCE949 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, cdce925_id);
-
static int cdce925_probe(struct i2c_client *client)
{
struct clk_cdce925_chip *data;
struct device_node *node = client->dev.of_node;
- const struct i2c_device_id *id = i2c_match_id(cdce925_id, client);
const char *parent_name;
const char *pll_clk_name[MAX_NUMBER_OF_PLLS] = {NULL,};
struct clk_init_data init;
@@ -647,7 +623,7 @@ static int cdce925_probe(struct i2c_client *client)
.name = "configuration0",
.reg_bits = 8,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
dev_dbg(&client->dev, "%s\n", __func__);
@@ -665,7 +641,7 @@ static int cdce925_probe(struct i2c_client *client)
return -ENOMEM;
data->i2c_client = client;
- data->chip_info = &clk_cdce925_chip_info_tbl[id->driver_data];
+ data->chip_info = i2c_get_match_data(client);
config.max_register = CDCE925_OFFSET_PLL +
data->chip_info->num_plls * 0x10 - 1;
data->regmap = devm_regmap_init(&client->dev, &regmap_cdce925_bus,
@@ -822,12 +798,41 @@ error:
return err;
}
+static const struct clk_cdce925_chip_info clk_cdce913_info = {
+ .num_plls = 1,
+ .num_outputs = 3,
+};
+
+static const struct clk_cdce925_chip_info clk_cdce925_info = {
+ .num_plls = 2,
+ .num_outputs = 5,
+};
+
+static const struct clk_cdce925_chip_info clk_cdce937_info = {
+ .num_plls = 3,
+ .num_outputs = 7,
+};
+
+static const struct clk_cdce925_chip_info clk_cdce949_info = {
+ .num_plls = 4,
+ .num_outputs = 9,
+};
+
+static const struct i2c_device_id cdce925_id[] = {
+ { "cdce913", (kernel_ulong_t)&clk_cdce913_info },
+ { "cdce925", (kernel_ulong_t)&clk_cdce925_info },
+ { "cdce937", (kernel_ulong_t)&clk_cdce937_info },
+ { "cdce949", (kernel_ulong_t)&clk_cdce949_info },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, cdce925_id);
+
static const struct of_device_id clk_cdce925_of_match[] = {
- { .compatible = "ti,cdce913" },
- { .compatible = "ti,cdce925" },
- { .compatible = "ti,cdce937" },
- { .compatible = "ti,cdce949" },
- { },
+ { .compatible = "ti,cdce913", .data = &clk_cdce913_info },
+ { .compatible = "ti,cdce925", .data = &clk_cdce925_info },
+ { .compatible = "ti,cdce937", .data = &clk_cdce937_info },
+ { .compatible = "ti,cdce949", .data = &clk_cdce949_info },
+ { }
};
MODULE_DEVICE_TABLE(of, clk_cdce925_of_match);
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
index 479297763e70..5067e067e906 100644
--- a/drivers/clk/clk-fractional-divider.c
+++ b/drivers/clk/clk-fractional-divider.c
@@ -123,6 +123,7 @@ void clk_fractional_divider_general_approximation(struct clk_hw *hw,
unsigned long *m, unsigned long *n)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
+ unsigned long max_m, max_n;
/*
* Get rate closer to *parent_rate to guarantee there is no overflow
@@ -138,10 +139,17 @@ void clk_fractional_divider_general_approximation(struct clk_hw *hw,
rate <<= scale - fd->nwidth;
}
- rational_best_approximation(rate, *parent_rate,
- GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
- m, n);
+ if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
+ max_m = 1 << fd->mwidth;
+ max_n = 1 << fd->nwidth;
+ } else {
+ max_m = GENMASK(fd->mwidth - 1, 0);
+ max_n = GENMASK(fd->nwidth - 1, 0);
+ }
+
+ rational_best_approximation(rate, *parent_rate, max_m, max_n, m, n);
}
+EXPORT_SYMBOL_GPL(clk_fractional_divider_general_approximation);
static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
@@ -169,13 +177,18 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
unsigned long flags = 0;
- unsigned long m, n;
+ unsigned long m, n, max_m, max_n;
u32 mmask, nmask;
u32 val;
- rational_best_approximation(rate, parent_rate,
- GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
- &m, &n);
+ if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
+ max_m = 1 << fd->mwidth;
+ max_n = 1 << fd->nwidth;
+ } else {
+ max_m = GENMASK(fd->mwidth - 1, 0);
+ max_n = GENMASK(fd->nwidth - 1, 0);
+ }
+ rational_best_approximation(rate, parent_rate, max_m, max_n, &m, &n);
if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
m--;
diff --git a/drivers/clk/clk-fractional-divider_test.c b/drivers/clk/clk-fractional-divider_test.c
new file mode 100644
index 000000000000..929eec927548
--- /dev/null
+++ b/drivers/clk/clk-fractional-divider_test.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Kunit test for clock fractional divider
+ */
+#include <linux/clk-provider.h>
+#include <kunit/test.h>
+
+#include "clk-fractional-divider.h"
+
+/*
+ * Test the maximum denominator case for fd clock without flags.
+ *
+ * Expect the highest possible denominator to be used in order to get as close as possible to the
+ * requested rate.
+ */
+static void clk_fd_test_approximation_max_denominator(struct kunit *test)
+{
+ struct clk_fractional_divider *fd;
+ unsigned long rate, parent_rate, parent_rate_before, m, n, max_n;
+
+ fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, fd);
+
+ fd->mwidth = 3;
+ fd->nwidth = 3;
+ max_n = 7;
+
+ rate = 240000000;
+ parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */
+ parent_rate_before = parent_rate;
+
+ clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n);
+ KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before);
+
+ KUNIT_EXPECT_EQ(test, m, 1);
+ KUNIT_EXPECT_EQ(test, n, max_n);
+}
+
+/*
+ * Test the maximum numerator case for fd clock without flags.
+ *
+ * Expect the highest possible numerator to be used in order to get as close as possible to the
+ * requested rate.
+ */
+static void clk_fd_test_approximation_max_numerator(struct kunit *test)
+{
+ struct clk_fractional_divider *fd;
+ unsigned long rate, parent_rate, parent_rate_before, m, n, max_m;
+
+ fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, fd);
+
+ fd->mwidth = 3;
+ max_m = 7;
+ fd->nwidth = 3;
+
+ rate = 240000000;
+ parent_rate = rate / (max_m + 1); /* so that it exceeds the maximum numerator */
+ parent_rate_before = parent_rate;
+
+ clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n);
+ KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before);
+
+ KUNIT_EXPECT_EQ(test, m, max_m);
+ KUNIT_EXPECT_EQ(test, n, 1);
+}
+
+/*
+ * Test the maximum denominator case for zero based fd clock.
+ *
+ * Expect the highest possible denominator to be used in order to get as close as possible to the
+ * requested rate.
+ */
+static void clk_fd_test_approximation_max_denominator_zero_based(struct kunit *test)
+{
+ struct clk_fractional_divider *fd;
+ unsigned long rate, parent_rate, parent_rate_before, m, n, max_n;
+
+ fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, fd);
+
+ fd->flags = CLK_FRAC_DIVIDER_ZERO_BASED;
+ fd->mwidth = 3;
+ fd->nwidth = 3;
+ max_n = 8;
+
+ rate = 240000000;
+ parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */
+ parent_rate_before = parent_rate;
+
+ clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n);
+ KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before);
+
+ KUNIT_EXPECT_EQ(test, m, 1);
+ KUNIT_EXPECT_EQ(test, n, max_n);
+}
+
+/*
+ * Test the maximum numerator case for zero based fd clock.
+ *
+ * Expect the highest possible numerator to be used in order to get as close as possible to the
+ * requested rate.
+ */
+static void clk_fd_test_approximation_max_numerator_zero_based(struct kunit *test)
+{
+ struct clk_fractional_divider *fd;
+ unsigned long rate, parent_rate, parent_rate_before, m, n, max_m;
+
+ fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, fd);
+
+ fd->flags = CLK_FRAC_DIVIDER_ZERO_BASED;
+ fd->mwidth = 3;
+ max_m = 8;
+ fd->nwidth = 3;
+
+ rate = 240000000;
+ parent_rate = rate / (max_m + 1); /* so that it exceeds the maximum numerator */
+ parent_rate_before = parent_rate;
+
+ clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n);
+ KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before);
+
+ KUNIT_EXPECT_EQ(test, m, max_m);
+ KUNIT_EXPECT_EQ(test, n, 1);
+}
+
+static struct kunit_case clk_fd_approximation_test_cases[] = {
+ KUNIT_CASE(clk_fd_test_approximation_max_denominator),
+ KUNIT_CASE(clk_fd_test_approximation_max_numerator),
+ KUNIT_CASE(clk_fd_test_approximation_max_denominator_zero_based),
+ KUNIT_CASE(clk_fd_test_approximation_max_numerator_zero_based),
+ {}
+};
+
+/*
+ * Test suite for clk_fractional_divider_general_approximation().
+ */
+static struct kunit_suite clk_fd_approximation_suite = {
+ .name = "clk-fd-approximation",
+ .test_cases = clk_fd_approximation_test_cases,
+};
+
+kunit_test_suites(
+ &clk_fd_approximation_suite
+);
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 64283807600b..68e585a02fd9 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -15,7 +15,7 @@
#include <linux/string.h>
/**
- * DOC: basic gatable clock which can gate and ungate it's ouput
+ * DOC: basic gatable clock which can gate and ungate its output
*
* Traits of this clock:
* prepare - clk_(un)prepare only ensures parent is (un)prepared
diff --git a/drivers/clk/clk-gate_test.c b/drivers/clk/clk-gate_test.c
index e136aaad48bf..c96d93b19ddf 100644
--- a/drivers/clk/clk-gate_test.c
+++ b/drivers/clk/clk-gate_test.c
@@ -131,7 +131,7 @@ struct clk_gate_test_context {
void __iomem *fake_mem;
struct clk_hw *hw;
struct clk_hw *parent;
- u32 fake_reg; /* Keep at end, KASAN can detect out of bounds */
+ __le32 fake_reg; /* Keep at end, KASAN can detect out of bounds */
};
static struct clk_gate_test_context *clk_gate_test_alloc_ctx(struct kunit *test)
@@ -166,7 +166,7 @@ static void clk_gate_test_enable(struct kunit *test)
KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
- KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg);
+ KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw));
KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw));
KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent));
@@ -183,10 +183,10 @@ static void clk_gate_test_disable(struct kunit *test)
u32 disable_val = 0;
KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
- KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg);
+ KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
clk_disable_unprepare(clk);
- KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg);
+ KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg));
KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw));
KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw));
KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent));
@@ -246,7 +246,7 @@ static void clk_gate_test_invert_enable(struct kunit *test)
KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
- KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg);
+ KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw));
KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw));
KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent));
@@ -263,10 +263,10 @@ static void clk_gate_test_invert_disable(struct kunit *test)
u32 disable_val = BIT(15);
KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
- KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg);
+ KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
clk_disable_unprepare(clk);
- KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg);
+ KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg));
KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw));
KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw));
KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent));
@@ -290,7 +290,7 @@ static int clk_gate_test_invert_init(struct kunit *test)
2000000);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
- ctx->fake_reg = BIT(15); /* Default to off */
+ ctx->fake_reg = cpu_to_le32(BIT(15)); /* Default to off */
hw = clk_hw_register_gate_parent_hw(NULL, "test_gate", parent, 0,
ctx->fake_mem, 15,
CLK_GATE_SET_TO_DISABLE, NULL);
@@ -319,7 +319,7 @@ static void clk_gate_test_hiword_enable(struct kunit *test)
KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
- KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg);
+ KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw));
KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw));
KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent));
@@ -336,10 +336,10 @@ static void clk_gate_test_hiword_disable(struct kunit *test)
u32 disable_val = BIT(9 + 16);
KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
- KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg);
+ KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
clk_disable_unprepare(clk);
- KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg);
+ KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg));
KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw));
KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw));
KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent));
@@ -387,7 +387,7 @@ static void clk_gate_test_is_enabled(struct kunit *test)
struct clk_gate_test_context *ctx;
ctx = clk_gate_test_alloc_ctx(test);
- ctx->fake_reg = BIT(7);
+ ctx->fake_reg = cpu_to_le32(BIT(7));
hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 7,
0, NULL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
@@ -402,7 +402,7 @@ static void clk_gate_test_is_disabled(struct kunit *test)
struct clk_gate_test_context *ctx;
ctx = clk_gate_test_alloc_ctx(test);
- ctx->fake_reg = BIT(4);
+ ctx->fake_reg = cpu_to_le32(BIT(4));
hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 7,
0, NULL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
@@ -417,7 +417,7 @@ static void clk_gate_test_is_enabled_inverted(struct kunit *test)
struct clk_gate_test_context *ctx;
ctx = clk_gate_test_alloc_ctx(test);
- ctx->fake_reg = BIT(31);
+ ctx->fake_reg = cpu_to_le32(BIT(31));
hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 2,
CLK_GATE_SET_TO_DISABLE, NULL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
@@ -432,7 +432,7 @@ static void clk_gate_test_is_disabled_inverted(struct kunit *test)
struct clk_gate_test_context *ctx;
ctx = clk_gate_test_alloc_ctx(test);
- ctx->fake_reg = BIT(29);
+ ctx->fake_reg = cpu_to_le32(BIT(29));
hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 29,
CLK_GATE_SET_TO_DISABLE, NULL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
diff --git a/drivers/clk/clk-lochnagar.c b/drivers/clk/clk-lochnagar.c
index db468a62c8d7..5561a2c66b69 100644
--- a/drivers/clk/clk-lochnagar.c
+++ b/drivers/clk/clk-lochnagar.c
@@ -12,8 +12,8 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/mfd/lochnagar1_regs.h>
@@ -242,22 +242,17 @@ static int lochnagar_clk_probe(struct platform_device *pdev)
};
struct device *dev = &pdev->dev;
struct lochnagar_clk_priv *priv;
- const struct of_device_id *of_id;
struct lochnagar_clk *lclk;
struct lochnagar_config *conf;
int ret, i;
- of_id = of_match_device(lochnagar_of_match, dev);
- if (!of_id)
- return -EINVAL;
-
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->dev = dev;
priv->regmap = dev_get_regmap(dev->parent, NULL);
- conf = (struct lochnagar_config *)of_id->data;
+ conf = (struct lochnagar_config *)device_get_match_data(dev);
memcpy(priv->lclks, conf->clks, sizeof(priv->lclks));
diff --git a/drivers/clk/clk-npcm7xx.c b/drivers/clk/clk-npcm7xx.c
index e319cfa51a8a..030186def9c6 100644
--- a/drivers/clk/clk-npcm7xx.c
+++ b/drivers/clk/clk-npcm7xx.c
@@ -510,7 +510,7 @@ static void __init npcm7xx_clk_init(struct device_node *clk_np)
return;
npcm7xx_init_fail:
- kfree(npcm7xx_clk_data->hws);
+ kfree(npcm7xx_clk_data);
npcm7xx_init_np_err:
iounmap(clk_base);
npcm7xx_init_error:
diff --git a/drivers/clk/clk-renesas-pcie.c b/drivers/clk/clk-renesas-pcie.c
index 7d7b2cb75318..380245f635d6 100644
--- a/drivers/clk/clk-renesas-pcie.c
+++ b/drivers/clk/clk-renesas-pcie.c
@@ -298,7 +298,7 @@ static int rs9_probe(struct i2c_client *client)
i2c_set_clientdata(client, rs9);
rs9->client = client;
- rs9->chip_info = device_get_match_data(&client->dev);
+ rs9->chip_info = i2c_get_match_data(client);
if (!rs9->chip_info)
return -EINVAL;
diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
index 2c7a830ce308..8cbe24789c24 100644
--- a/drivers/clk/clk-scmi.c
+++ b/drivers/clk/clk-scmi.c
@@ -13,13 +13,18 @@
#include <linux/scmi_protocol.h>
#include <asm/div64.h>
+#define NOT_ATOMIC false
+#define ATOMIC true
+
static const struct scmi_clk_proto_ops *scmi_proto_clk_ops;
struct scmi_clk {
u32 id;
+ struct device *dev;
struct clk_hw hw;
const struct scmi_clock_info *info;
const struct scmi_protocol_handle *ph;
+ struct clk_parent_data *parent_data;
};
#define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
@@ -74,38 +79,89 @@ static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
return scmi_proto_clk_ops->rate_set(clk->ph, clk->id, rate);
}
+static int scmi_clk_set_parent(struct clk_hw *hw, u8 parent_index)
+{
+ struct scmi_clk *clk = to_scmi_clk(hw);
+
+ return scmi_proto_clk_ops->parent_set(clk->ph, clk->id, parent_index);
+}
+
+static u8 scmi_clk_get_parent(struct clk_hw *hw)
+{
+ struct scmi_clk *clk = to_scmi_clk(hw);
+ u32 parent_id, p_idx;
+ int ret;
+
+ ret = scmi_proto_clk_ops->parent_get(clk->ph, clk->id, &parent_id);
+ if (ret)
+ return 0;
+
+ for (p_idx = 0; p_idx < clk->info->num_parents; p_idx++) {
+ if (clk->parent_data[p_idx].index == parent_id)
+ break;
+ }
+
+ if (p_idx == clk->info->num_parents)
+ return 0;
+
+ return p_idx;
+}
+
+static int scmi_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
+{
+ /*
+ * Suppose all the requested rates are supported, and let firmware
+ * to handle the left work.
+ */
+ return 0;
+}
+
static int scmi_clk_enable(struct clk_hw *hw)
{
struct scmi_clk *clk = to_scmi_clk(hw);
- return scmi_proto_clk_ops->enable(clk->ph, clk->id);
+ return scmi_proto_clk_ops->enable(clk->ph, clk->id, NOT_ATOMIC);
}
static void scmi_clk_disable(struct clk_hw *hw)
{
struct scmi_clk *clk = to_scmi_clk(hw);
- scmi_proto_clk_ops->disable(clk->ph, clk->id);
+ scmi_proto_clk_ops->disable(clk->ph, clk->id, NOT_ATOMIC);
}
static int scmi_clk_atomic_enable(struct clk_hw *hw)
{
struct scmi_clk *clk = to_scmi_clk(hw);
- return scmi_proto_clk_ops->enable_atomic(clk->ph, clk->id);
+ return scmi_proto_clk_ops->enable(clk->ph, clk->id, ATOMIC);
}
static void scmi_clk_atomic_disable(struct clk_hw *hw)
{
struct scmi_clk *clk = to_scmi_clk(hw);
- scmi_proto_clk_ops->disable_atomic(clk->ph, clk->id);
+ scmi_proto_clk_ops->disable(clk->ph, clk->id, ATOMIC);
+}
+
+static int scmi_clk_atomic_is_enabled(struct clk_hw *hw)
+{
+ int ret;
+ bool enabled = false;
+ struct scmi_clk *clk = to_scmi_clk(hw);
+
+ ret = scmi_proto_clk_ops->state_get(clk->ph, clk->id, &enabled, ATOMIC);
+ if (ret)
+ dev_warn(clk->dev,
+ "Failed to get state for clock ID %d\n", clk->id);
+
+ return !!enabled;
}
/*
- * We can provide enable/disable atomic callbacks only if the underlying SCMI
- * transport for an SCMI instance is configured to handle SCMI commands in an
- * atomic manner.
+ * We can provide enable/disable/is_enabled atomic callbacks only if the
+ * underlying SCMI transport for an SCMI instance is configured to handle
+ * SCMI commands in an atomic manner.
*
* When no SCMI atomic transport support is available we instead provide only
* the prepare/unprepare API, as allowed by the clock framework when atomic
@@ -121,6 +177,9 @@ static const struct clk_ops scmi_clk_ops = {
.set_rate = scmi_clk_set_rate,
.prepare = scmi_clk_enable,
.unprepare = scmi_clk_disable,
+ .set_parent = scmi_clk_set_parent,
+ .get_parent = scmi_clk_get_parent,
+ .determine_rate = scmi_clk_determine_rate,
};
static const struct clk_ops scmi_atomic_clk_ops = {
@@ -129,6 +188,10 @@ static const struct clk_ops scmi_atomic_clk_ops = {
.set_rate = scmi_clk_set_rate,
.enable = scmi_clk_atomic_enable,
.disable = scmi_clk_atomic_disable,
+ .is_enabled = scmi_clk_atomic_is_enabled,
+ .set_parent = scmi_clk_set_parent,
+ .get_parent = scmi_clk_get_parent,
+ .determine_rate = scmi_clk_determine_rate,
};
static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk,
@@ -139,9 +202,10 @@ static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk,
struct clk_init_data init = {
.flags = CLK_GET_RATE_NOCACHE,
- .num_parents = 0,
+ .num_parents = sclk->info->num_parents,
.ops = scmi_ops,
.name = sclk->info->name,
+ .parent_data = sclk->parent_data,
};
sclk->hw.init = &init;
@@ -213,11 +277,13 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
sclk->info = scmi_proto_clk_ops->info_get(ph, idx);
if (!sclk->info) {
dev_dbg(dev, "invalid clock info for idx %d\n", idx);
+ devm_kfree(dev, sclk);
continue;
}
sclk->id = idx;
sclk->ph = ph;
+ sclk->dev = dev;
/*
* Note that when transport is atomic but SCMI protocol did not
@@ -230,9 +296,23 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
else
scmi_ops = &scmi_clk_ops;
+ /* Initialize clock parent data. */
+ if (sclk->info->num_parents > 0) {
+ sclk->parent_data = devm_kcalloc(dev, sclk->info->num_parents,
+ sizeof(*sclk->parent_data), GFP_KERNEL);
+ if (!sclk->parent_data)
+ return -ENOMEM;
+
+ for (int i = 0; i < sclk->info->num_parents; i++) {
+ sclk->parent_data[i].index = sclk->info->parents[i];
+ sclk->parent_data[i].hw = hws[sclk->info->parents[i]];
+ }
+ }
+
err = scmi_clk_ops_init(dev, sclk, scmi_ops);
if (err) {
dev_err(dev, "failed to register clock %d\n", idx);
+ devm_kfree(dev, sclk->parent_data);
devm_kfree(dev, sclk);
hws[idx] = NULL;
} else {
diff --git a/drivers/clk/clk-si514.c b/drivers/clk/clk-si514.c
index e8c18afac184..6ee148e5469d 100644
--- a/drivers/clk/clk-si514.c
+++ b/drivers/clk/clk-si514.c
@@ -321,7 +321,7 @@ static bool si514_regmap_is_writeable(struct device *dev, unsigned int reg)
static const struct regmap_config si514_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = SI514_REG_CONTROL,
.writeable_reg = si514_regmap_is_writeable,
.volatile_reg = si514_regmap_is_volatile,
diff --git a/drivers/clk/clk-si521xx.c b/drivers/clk/clk-si521xx.c
index ef4ba467e747..4f7b74f889f1 100644
--- a/drivers/clk/clk-si521xx.c
+++ b/drivers/clk/clk-si521xx.c
@@ -279,10 +279,10 @@ si521xx_of_clk_get(struct of_phandle_args *clkspec, void *data)
static int si521xx_probe(struct i2c_client *client)
{
- const u16 chip_info = (u16)(uintptr_t)device_get_match_data(&client->dev);
+ const u16 chip_info = (u16)(uintptr_t)i2c_get_match_data(client);
const struct clk_parent_data clk_parent_data = { .index = 0 };
const u8 data[3] = { SI521XX_REG_BC, 1, 1 };
- unsigned char name[6] = "DIFF0";
+ unsigned char name[16] = "DIFF0";
struct clk_init_data init = {};
struct si521xx *si;
int i, ret;
@@ -316,7 +316,7 @@ static int si521xx_probe(struct i2c_client *client)
/* Register clock */
for (i = 0; i < hweight16(chip_info); i++) {
memset(&init, 0, sizeof(init));
- snprintf(name, 6, "DIFF%d", i);
+ snprintf(name, sizeof(name), "DIFF%d", i);
init.name = name;
init.ops = &si521xx_diff_clk_ops;
init.parent_data = &clk_parent_data;
diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c
index 9599857842c7..845b451511d2 100644
--- a/drivers/clk/clk-si5341.c
+++ b/drivers/clk/clk-si5341.c
@@ -1260,7 +1260,7 @@ static int si5341_wait_device_ready(struct i2c_client *client)
static const struct regmap_config si5341_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.ranges = si5341_regmap_ranges,
.num_ranges = ARRAY_SIZE(si5341_regmap_ranges),
.max_register = SI5341_REGISTER_MAX,
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c
index 00fb9b09e030..a9a0bc448a4b 100644
--- a/drivers/clk/clk-si5351.c
+++ b/drivers/clk/clk-si5351.c
@@ -206,7 +206,7 @@ static bool si5351_regmap_is_writeable(struct device *dev, unsigned int reg)
static const struct regmap_config si5351_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = 187,
.writeable_reg = si5351_regmap_is_writeable,
.volatile_reg = si5351_regmap_is_volatile,
@@ -1385,8 +1385,7 @@ MODULE_DEVICE_TABLE(i2c, si5351_i2c_ids);
static int si5351_i2c_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_match_id(si5351_i2c_ids, client);
- enum si5351_variant variant = (enum si5351_variant)id->driver_data;
+ enum si5351_variant variant;
struct si5351_platform_data *pdata;
struct si5351_driver_data *drvdata;
struct clk_init_data init;
@@ -1394,6 +1393,7 @@ static int si5351_i2c_probe(struct i2c_client *client)
u8 num_parents, num_clocks;
int ret, n;
+ variant = (enum si5351_variant)(uintptr_t)i2c_get_match_data(client);
ret = si5351_dt_parse(client, variant);
if (ret)
return ret;
diff --git a/drivers/clk/clk-si544.c b/drivers/clk/clk-si544.c
index 22925968aa35..c88650558f32 100644
--- a/drivers/clk/clk-si544.c
+++ b/drivers/clk/clk-si544.c
@@ -56,17 +56,11 @@
#define DELTA_M_FRAC_NUM 19
#define DELTA_M_FRAC_DEN 20000
-enum si544_speed_grade {
- si544a,
- si544b,
- si544c,
-};
-
struct clk_si544 {
struct clk_hw hw;
struct regmap *regmap;
struct i2c_client *i2c_client;
- enum si544_speed_grade speed_grade;
+ unsigned long max_freq;
};
#define to_clk_si544(_hw) container_of(_hw, struct clk_si544, hw)
@@ -196,24 +190,10 @@ static int si544_set_muldiv(struct clk_si544 *data,
static bool is_valid_frequency(const struct clk_si544 *data,
unsigned long frequency)
{
- unsigned long max_freq = 0;
-
if (frequency < SI544_MIN_FREQ)
return false;
- switch (data->speed_grade) {
- case si544a:
- max_freq = 1500000000;
- break;
- case si544b:
- max_freq = 800000000;
- break;
- case si544c:
- max_freq = 350000000;
- break;
- }
-
- return frequency <= max_freq;
+ return frequency <= data->max_freq;
}
/* Calculate divider settings for a given frequency */
@@ -446,24 +426,15 @@ static bool si544_regmap_is_volatile(struct device *dev, unsigned int reg)
static const struct regmap_config si544_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = SI544_REG_PAGE_SELECT,
.volatile_reg = si544_regmap_is_volatile,
};
-static const struct i2c_device_id si544_id[] = {
- { "si544a", si544a },
- { "si544b", si544b },
- { "si544c", si544c },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, si544_id);
-
static int si544_probe(struct i2c_client *client)
{
struct clk_si544 *data;
struct clk_init_data init;
- const struct i2c_device_id *id = i2c_match_id(si544_id, client);
int err;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
@@ -475,7 +446,7 @@ static int si544_probe(struct i2c_client *client)
init.num_parents = 0;
data->hw.init = &init;
data->i2c_client = client;
- data->speed_grade = id->driver_data;
+ data->max_freq = (uintptr_t)i2c_get_match_data(client);
if (of_property_read_string(client->dev.of_node, "clock-output-names",
&init.name))
@@ -507,11 +478,19 @@ static int si544_probe(struct i2c_client *client)
return 0;
}
+static const struct i2c_device_id si544_id[] = {
+ { "si544a", 1500000000 },
+ { "si544b", 800000000 },
+ { "si544c", 350000000 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, si544_id);
+
static const struct of_device_id clk_si544_of_match[] = {
- { .compatible = "silabs,si544a" },
- { .compatible = "silabs,si544b" },
- { .compatible = "silabs,si544c" },
- { },
+ { .compatible = "silabs,si544a", .data = (void *)1500000000 },
+ { .compatible = "silabs,si544b", .data = (void *)800000000 },
+ { .compatible = "silabs,si544c", .data = (void *)350000000 },
+ { }
};
MODULE_DEVICE_TABLE(of, clk_si544_of_match);
diff --git a/drivers/clk/clk-si570.c b/drivers/clk/clk-si570.c
index de0212fb5f87..a549ea13be20 100644
--- a/drivers/clk/clk-si570.c
+++ b/drivers/clk/clk-si570.c
@@ -50,11 +50,21 @@
#define SI570_FREEZE_DCO (1 << 4)
/**
+ * struct clk_si570_info:
+ * @max_freq: Maximum frequency for this device
+ * @has_temperature_stability: Device support temperature stability
+ */
+struct clk_si570_info {
+ u64 max_freq;
+ bool has_temperature_stability;
+};
+
+/**
* struct clk_si570:
* @hw: Clock hw struct
* @regmap: Device's regmap
* @div_offset: Rgister offset for dividers
- * @max_freq: Maximum frequency for this device
+ * @info: Device info
* @fxtal: Factory xtal frequency
* @n1: Clock divider N1
* @hs_div: Clock divider HSDIV
@@ -66,7 +76,7 @@ struct clk_si570 {
struct clk_hw hw;
struct regmap *regmap;
unsigned int div_offset;
- u64 max_freq;
+ const struct clk_si570_info *info;
u64 fxtal;
unsigned int n1;
unsigned int hs_div;
@@ -76,11 +86,6 @@ struct clk_si570 {
};
#define to_clk_si570(_hw) container_of(_hw, struct clk_si570, hw)
-enum clk_si570_variant {
- si57x,
- si59x
-};
-
/**
* si570_get_divs() - Read clock dividers from HW
* @data: Pointer to struct clk_si570
@@ -341,7 +346,7 @@ static int si570_set_rate(struct clk_hw *hw, unsigned long rate,
struct i2c_client *client = data->i2c_client;
int err;
- if (rate < SI570_MIN_FREQ || rate > data->max_freq) {
+ if (rate < SI570_MIN_FREQ || rate > data->info->max_freq) {
dev_err(&client->dev,
"requested frequency %lu Hz is out of range\n", rate);
return -EINVAL;
@@ -392,30 +397,19 @@ static bool si570_regmap_is_writeable(struct device *dev, unsigned int reg)
static const struct regmap_config si570_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = 137,
.writeable_reg = si570_regmap_is_writeable,
.volatile_reg = si570_regmap_is_volatile,
};
-static const struct i2c_device_id si570_id[] = {
- { "si570", si57x },
- { "si571", si57x },
- { "si598", si59x },
- { "si599", si59x },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, si570_id);
-
static int si570_probe(struct i2c_client *client)
{
struct clk_si570 *data;
struct clk_init_data init;
- const struct i2c_device_id *id = i2c_match_id(si570_id, client);
u32 initial_fout, factory_fout, stability;
bool skip_recall;
int err;
- enum clk_si570_variant variant = id->driver_data;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (!data)
@@ -427,7 +421,8 @@ static int si570_probe(struct i2c_client *client)
data->hw.init = &init;
data->i2c_client = client;
- if (variant == si57x) {
+ data->info = i2c_get_match_data(client);
+ if (data->info->has_temperature_stability) {
err = of_property_read_u32(client->dev.of_node,
"temperature-stability", &stability);
if (err) {
@@ -438,10 +433,6 @@ static int si570_probe(struct i2c_client *client)
/* adjust register offsets for 7ppm devices */
if (stability == 7)
data->div_offset = SI570_DIV_OFFSET_7PPM;
-
- data->max_freq = SI570_MAX_FREQ;
- } else {
- data->max_freq = SI598_MAX_FREQ;
}
if (of_property_read_string(client->dev.of_node, "clock-output-names",
@@ -496,12 +487,30 @@ static int si570_probe(struct i2c_client *client)
return 0;
}
+static const struct clk_si570_info clk_si570_info = {
+ .max_freq = SI570_MAX_FREQ,
+ .has_temperature_stability = true,
+};
+
+static const struct clk_si570_info clk_si590_info = {
+ .max_freq = SI598_MAX_FREQ,
+};
+
+static const struct i2c_device_id si570_id[] = {
+ { "si570", (kernel_ulong_t)&clk_si570_info },
+ { "si571", (kernel_ulong_t)&clk_si570_info },
+ { "si598", (kernel_ulong_t)&clk_si590_info },
+ { "si599", (kernel_ulong_t)&clk_si590_info },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, si570_id);
+
static const struct of_device_id clk_si570_of_match[] = {
- { .compatible = "silabs,si570" },
- { .compatible = "silabs,si571" },
- { .compatible = "silabs,si598" },
- { .compatible = "silabs,si599" },
- { },
+ { .compatible = "silabs,si570", .data = &clk_si570_info },
+ { .compatible = "silabs,si571", .data = &clk_si570_info },
+ { .compatible = "silabs,si598", .data = &clk_si590_info },
+ { .compatible = "silabs,si599", .data = &clk_si590_info },
+ { }
};
MODULE_DEVICE_TABLE(of, clk_si570_of_match);
diff --git a/drivers/clk/clk-twl.c b/drivers/clk/clk-twl.c
new file mode 100644
index 000000000000..eab9d3c8ed8a
--- /dev/null
+++ b/drivers/clk/clk-twl.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Clock driver for twl device.
+ *
+ * inspired by the driver for the Palmas device
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/mfd/twl.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define VREG_STATE 2
+#define TWL6030_CFG_STATE_OFF 0x00
+#define TWL6030_CFG_STATE_ON 0x01
+#define TWL6030_CFG_STATE_MASK 0x03
+
+struct twl_clock_info {
+ struct device *dev;
+ u8 base;
+ struct clk_hw hw;
+};
+
+static inline int
+twlclk_read(struct twl_clock_info *info, unsigned int slave_subgp,
+ unsigned int offset)
+{
+ u8 value;
+ int status;
+
+ status = twl_i2c_read_u8(slave_subgp, &value,
+ info->base + offset);
+ return (status < 0) ? status : value;
+}
+
+static inline int
+twlclk_write(struct twl_clock_info *info, unsigned int slave_subgp,
+ unsigned int offset, u8 value)
+{
+ return twl_i2c_write_u8(slave_subgp, value,
+ info->base + offset);
+}
+
+static inline struct twl_clock_info *to_twl_clks_info(struct clk_hw *hw)
+{
+ return container_of(hw, struct twl_clock_info, hw);
+}
+
+static unsigned long twl_clks_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return 32768;
+}
+
+static int twl6032_clks_prepare(struct clk_hw *hw)
+{
+ struct twl_clock_info *cinfo = to_twl_clks_info(hw);
+ int ret;
+
+ ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
+ TWL6030_CFG_STATE_ON);
+ if (ret < 0)
+ dev_err(cinfo->dev, "clk prepare failed\n");
+
+ return ret;
+}
+
+static void twl6032_clks_unprepare(struct clk_hw *hw)
+{
+ struct twl_clock_info *cinfo = to_twl_clks_info(hw);
+ int ret;
+
+ ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
+ TWL6030_CFG_STATE_OFF);
+ if (ret < 0)
+ dev_err(cinfo->dev, "clk unprepare failed\n");
+}
+
+static int twl6032_clks_is_prepared(struct clk_hw *hw)
+{
+ struct twl_clock_info *cinfo = to_twl_clks_info(hw);
+ int val;
+
+ val = twlclk_read(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE);
+ if (val < 0) {
+ dev_err(cinfo->dev, "clk read failed\n");
+ return val;
+ }
+
+ val &= TWL6030_CFG_STATE_MASK;
+
+ return val == TWL6030_CFG_STATE_ON;
+}
+
+static const struct clk_ops twl6032_clks_ops = {
+ .prepare = twl6032_clks_prepare,
+ .unprepare = twl6032_clks_unprepare,
+ .is_prepared = twl6032_clks_is_prepared,
+ .recalc_rate = twl_clks_recalc_rate,
+};
+
+struct twl_clks_data {
+ struct clk_init_data init;
+ u8 base;
+};
+
+static const struct twl_clks_data twl6032_clks[] = {
+ {
+ .init = {
+ .name = "clk32kg",
+ .ops = &twl6032_clks_ops,
+ .flags = CLK_IGNORE_UNUSED,
+ },
+ .base = 0x8C,
+ },
+ {
+ .init = {
+ .name = "clk32kaudio",
+ .ops = &twl6032_clks_ops,
+ .flags = CLK_IGNORE_UNUSED,
+ },
+ .base = 0x8F,
+ },
+ {
+ /* sentinel */
+ }
+};
+
+static int twl_clks_probe(struct platform_device *pdev)
+{
+ struct clk_hw_onecell_data *clk_data;
+ const struct twl_clks_data *hw_data;
+
+ struct twl_clock_info *cinfo;
+ int ret;
+ int i;
+ int count;
+
+ hw_data = twl6032_clks;
+ for (count = 0; hw_data[count].init.name; count++)
+ ;
+
+ clk_data = devm_kzalloc(&pdev->dev,
+ struct_size(clk_data, hws, count),
+ GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->num = count;
+ cinfo = devm_kcalloc(&pdev->dev, count, sizeof(*cinfo), GFP_KERNEL);
+ if (!cinfo)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++) {
+ cinfo[i].base = hw_data[i].base;
+ cinfo[i].dev = &pdev->dev;
+ cinfo[i].hw.init = &hw_data[i].init;
+ ret = devm_clk_hw_register(&pdev->dev, &cinfo[i].hw);
+ if (ret) {
+ return dev_err_probe(&pdev->dev, ret,
+ "Fail to register clock %s\n",
+ hw_data[i].init.name);
+ }
+ clk_data->hws[i] = &cinfo[i].hw;
+ }
+
+ ret = devm_of_clk_add_hw_provider(&pdev->dev,
+ of_clk_hw_onecell_get, clk_data);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "Fail to add clock driver\n");
+
+ return 0;
+}
+
+static const struct platform_device_id twl_clks_id[] = {
+ {
+ .name = "twl6032-clk",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, twl_clks_id);
+
+static struct platform_driver twl_clks_driver = {
+ .driver = {
+ .name = "twl-clk",
+ },
+ .probe = twl_clks_probe,
+ .id_table = twl_clks_id,
+};
+
+module_platform_driver(twl_clks_driver);
+
+MODULE_DESCRIPTION("Clock driver for TWL Series Devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c
index 3d7de355f8f6..00930d7bca77 100644
--- a/drivers/clk/clk-versaclock3.c
+++ b/drivers/clk/clk-versaclock3.c
@@ -585,17 +585,11 @@ static const struct clk_ops vc3_clk_mux_ops = {
.get_parent = vc3_clk_mux_get_parent,
};
-static bool vc3_regmap_is_writeable(struct device *dev, unsigned int reg)
-{
- return true;
-}
-
static const struct regmap_config vc3_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = 0x24,
- .writeable_reg = vc3_regmap_is_writeable,
};
static struct vc3_hw_data clk_div[5];
diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c
index 17cbb30d20ad..6d31cd54d7cf 100644
--- a/drivers/clk/clk-versaclock5.c
+++ b/drivers/clk/clk-versaclock5.c
@@ -217,7 +217,7 @@ static bool vc5_regmap_is_writeable(struct device *dev, unsigned int reg)
static const struct regmap_config vc5_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = 0x76,
.writeable_reg = vc5_regmap_is_writeable,
};
diff --git a/drivers/clk/clk-versaclock7.c b/drivers/clk/clk-versaclock7.c
index 9ab35c1af0ff..f323263e32c3 100644
--- a/drivers/clk/clk-versaclock7.c
+++ b/drivers/clk/clk-versaclock7.c
@@ -1275,7 +1275,7 @@ static const struct regmap_config vc7_regmap_config = {
.ranges = vc7_range_cfg,
.num_ranges = ARRAY_SIZE(vc7_range_cfg),
.volatile_reg = vc7_volatile_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.can_multi_write = true,
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
.val_format_endian = REGMAP_ENDIAN_LITTLE,
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index c249f9791ae8..2253c154a824 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -3188,28 +3188,41 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
int level)
{
int phase;
+ struct clk *clk_user;
+ int multi_node = 0;
- seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu ",
+ seq_printf(s, "%*s%-*s %-7d %-8d %-8d %-11lu %-10lu ",
level * 3 + 1, "",
- 30 - level * 3, c->name,
+ 35 - level * 3, c->name,
c->enable_count, c->prepare_count, c->protect_count,
clk_core_get_rate_recalc(c),
clk_core_get_accuracy_recalc(c));
phase = clk_core_get_phase(c);
if (phase >= 0)
- seq_printf(s, "%5d", phase);
+ seq_printf(s, "%-5d", phase);
else
seq_puts(s, "-----");
- seq_printf(s, " %6d", clk_core_get_scaled_duty_cycle(c, 100000));
+ seq_printf(s, " %-6d", clk_core_get_scaled_duty_cycle(c, 100000));
if (c->ops->is_enabled)
- seq_printf(s, " %9c\n", clk_core_is_enabled(c) ? 'Y' : 'N');
+ seq_printf(s, " %5c ", clk_core_is_enabled(c) ? 'Y' : 'N');
else if (!c->ops->enable)
- seq_printf(s, " %9c\n", 'Y');
+ seq_printf(s, " %5c ", 'Y');
else
- seq_printf(s, " %9c\n", '?');
+ seq_printf(s, " %5c ", '?');
+
+ hlist_for_each_entry(clk_user, &c->clks, clks_node) {
+ seq_printf(s, "%*s%-*s %-25s\n",
+ level * 3 + 2 + 105 * multi_node, "",
+ 30,
+ clk_user->dev_id ? clk_user->dev_id : "deviceless",
+ clk_user->con_id ? clk_user->con_id : "no_connection_id");
+
+ multi_node = 1;
+ }
+
}
static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
@@ -3230,9 +3243,10 @@ static int clk_summary_show(struct seq_file *s, void *data)
struct clk_core *c;
struct hlist_head **lists = s->private;
- seq_puts(s, " enable prepare protect duty hardware\n");
- seq_puts(s, " clock count count count rate accuracy phase cycle enable\n");
- seq_puts(s, "-------------------------------------------------------------------------------------------------------\n");
+ 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");
+
clk_prepare_lock();
@@ -3329,6 +3343,21 @@ static int clk_rate_set(void *data, u64 val)
#define clk_rate_mode 0644
+static int clk_phase_set(void *data, u64 val)
+{
+ struct clk_core *core = data;
+ int degrees = do_div(val, 360);
+ int ret;
+
+ clk_prepare_lock();
+ ret = clk_core_set_phase_nolock(core, degrees);
+ clk_prepare_unlock();
+
+ return ret;
+}
+
+#define clk_phase_mode 0644
+
static int clk_prepare_enable_set(void *data, u64 val)
{
struct clk_core *core = data;
@@ -3356,6 +3385,9 @@ DEFINE_DEBUGFS_ATTRIBUTE(clk_prepare_enable_fops, clk_prepare_enable_get,
#else
#define clk_rate_set NULL
#define clk_rate_mode 0444
+
+#define clk_phase_set NULL
+#define clk_phase_mode 0644
#endif
static int clk_rate_get(void *data, u64 *val)
@@ -3371,6 +3403,16 @@ static int clk_rate_get(void *data, u64 *val)
DEFINE_DEBUGFS_ATTRIBUTE(clk_rate_fops, clk_rate_get, clk_rate_set, "%llu\n");
+static int clk_phase_get(void *data, u64 *val)
+{
+ struct clk_core *core = data;
+
+ *val = core->phase;
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(clk_phase_fops, clk_phase_get, clk_phase_set, "%llu\n");
+
static const struct {
unsigned long flag;
const char *name;
@@ -3416,6 +3458,7 @@ static void possible_parent_show(struct seq_file *s, struct clk_core *core,
unsigned int i, char terminator)
{
struct clk_core *parent;
+ const char *name = NULL;
/*
* Go through the following options to fetch a parent's name.
@@ -3430,18 +3473,20 @@ static void possible_parent_show(struct seq_file *s, struct clk_core *core,
* registered (yet).
*/
parent = clk_core_get_parent_by_index(core, i);
- if (parent)
+ if (parent) {
seq_puts(s, parent->name);
- else if (core->parents[i].name)
+ } else if (core->parents[i].name) {
seq_puts(s, core->parents[i].name);
- else if (core->parents[i].fw_name)
+ } else if (core->parents[i].fw_name) {
seq_printf(s, "<%s>(fw)", core->parents[i].fw_name);
- else if (core->parents[i].index >= 0)
- seq_puts(s,
- of_clk_get_parent_name(core->of_node,
- core->parents[i].index));
- else
- seq_puts(s, "(missing)");
+ } else {
+ if (core->parents[i].index >= 0)
+ name = of_clk_get_parent_name(core->of_node, core->parents[i].index);
+ if (!name)
+ name = "(missing)";
+
+ seq_puts(s, name);
+ }
seq_putc(s, terminator);
}
@@ -3561,7 +3606,8 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
debugfs_create_file("clk_min_rate", 0444, root, core, &clk_min_rate_fops);
debugfs_create_file("clk_max_rate", 0444, root, core, &clk_max_rate_fops);
debugfs_create_ulong("clk_accuracy", 0444, root, &core->accuracy);
- debugfs_create_u32("clk_phase", 0444, root, &core->phase);
+ debugfs_create_file("clk_phase", clk_phase_mode, root, core,
+ &clk_phase_fops);
debugfs_create_file("clk_flags", 0444, root, core, &clk_flags_fops);
debugfs_create_u32("clk_prepare_count", 0444, root, &core->prepare_count);
debugfs_create_u32("clk_enable_count", 0444, root, &core->enable_count);
diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c
index a154ec9d0111..39e2b5ff4f51 100644
--- a/drivers/clk/clk_test.c
+++ b/drivers/clk/clk_test.c
@@ -10,6 +10,8 @@
#include <kunit/test.h>
+static const struct clk_ops empty_clk_ops = { };
+
#define DUMMY_CLOCK_INIT_RATE (42 * 1000 * 1000)
#define DUMMY_CLOCK_RATE_1 (142 * 1000 * 1000)
#define DUMMY_CLOCK_RATE_2 (242 * 1000 * 1000)
@@ -2155,6 +2157,31 @@ static struct kunit_suite clk_range_minimize_test_suite = {
struct clk_leaf_mux_ctx {
struct clk_multiple_parent_ctx mux_ctx;
struct clk_hw hw;
+ struct clk_hw parent;
+ struct clk_rate_request *req;
+ int (*determine_rate_func)(struct clk_hw *hw, struct clk_rate_request *req);
+};
+
+static int clk_leaf_mux_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
+{
+ struct clk_leaf_mux_ctx *ctx = container_of(hw, struct clk_leaf_mux_ctx, hw);
+ int ret;
+ struct clk_rate_request *parent_req = ctx->req;
+
+ clk_hw_forward_rate_request(hw, req, req->best_parent_hw, parent_req, req->rate);
+ ret = ctx->determine_rate_func(req->best_parent_hw, parent_req);
+ if (ret)
+ return ret;
+
+ req->rate = parent_req->rate;
+
+ return 0;
+}
+
+static const struct clk_ops clk_leaf_mux_set_rate_parent_ops = {
+ .determine_rate = clk_leaf_mux_determine_rate,
+ .set_parent = clk_dummy_single_set_parent,
+ .get_parent = clk_dummy_single_get_parent,
};
static int
@@ -2193,8 +2220,14 @@ clk_leaf_mux_set_rate_parent_test_init(struct kunit *test)
if (ret)
return ret;
- ctx->hw.init = CLK_HW_INIT_HW("test-clock", &ctx->mux_ctx.hw,
- &clk_dummy_single_parent_ops,
+ ctx->parent.init = CLK_HW_INIT_HW("test-parent", &ctx->mux_ctx.hw,
+ &empty_clk_ops, CLK_SET_RATE_PARENT);
+ ret = clk_hw_register(NULL, &ctx->parent);
+ if (ret)
+ return ret;
+
+ ctx->hw.init = CLK_HW_INIT_HW("test-clock", &ctx->parent,
+ &clk_leaf_mux_set_rate_parent_ops,
CLK_SET_RATE_PARENT);
ret = clk_hw_register(NULL, &ctx->hw);
if (ret)
@@ -2208,32 +2241,94 @@ static void clk_leaf_mux_set_rate_parent_test_exit(struct kunit *test)
struct clk_leaf_mux_ctx *ctx = test->priv;
clk_hw_unregister(&ctx->hw);
+ clk_hw_unregister(&ctx->parent);
clk_hw_unregister(&ctx->mux_ctx.hw);
clk_hw_unregister(&ctx->mux_ctx.parents_ctx[0].hw);
clk_hw_unregister(&ctx->mux_ctx.parents_ctx[1].hw);
}
+struct clk_leaf_mux_set_rate_parent_determine_rate_test_case {
+ const char *desc;
+ int (*determine_rate_func)(struct clk_hw *hw, struct clk_rate_request *req);
+};
+
+static void
+clk_leaf_mux_set_rate_parent_determine_rate_test_case_to_desc(
+ const struct clk_leaf_mux_set_rate_parent_determine_rate_test_case *t, char *desc)
+{
+ strcpy(desc, t->desc);
+}
+
+static const struct clk_leaf_mux_set_rate_parent_determine_rate_test_case
+clk_leaf_mux_set_rate_parent_determine_rate_test_cases[] = {
+ {
+ /*
+ * Test that __clk_determine_rate() on the parent that can't
+ * change rate doesn't return a clk_rate_request structure with
+ * the best_parent_hw pointer pointing to the parent.
+ */
+ .desc = "clk_leaf_mux_set_rate_parent__clk_determine_rate_proper_parent",
+ .determine_rate_func = __clk_determine_rate,
+ },
+ {
+ /*
+ * Test that __clk_mux_determine_rate() on the parent that
+ * can't change rate doesn't return a clk_rate_request
+ * structure with the best_parent_hw pointer pointing to
+ * the parent.
+ */
+ .desc = "clk_leaf_mux_set_rate_parent__clk_mux_determine_rate_proper_parent",
+ .determine_rate_func = __clk_mux_determine_rate,
+ },
+ {
+ /*
+ * Test that __clk_mux_determine_rate_closest() on the parent
+ * that can't change rate doesn't return a clk_rate_request
+ * structure with the best_parent_hw pointer pointing to
+ * the parent.
+ */
+ .desc = "clk_leaf_mux_set_rate_parent__clk_mux_determine_rate_closest_proper_parent",
+ .determine_rate_func = __clk_mux_determine_rate_closest,
+ },
+ {
+ /*
+ * Test that clk_hw_determine_rate_no_reparent() on the parent
+ * that can't change rate doesn't return a clk_rate_request
+ * structure with the best_parent_hw pointer pointing to
+ * the parent.
+ */
+ .desc = "clk_leaf_mux_set_rate_parent_clk_hw_determine_rate_no_reparent_proper_parent",
+ .determine_rate_func = clk_hw_determine_rate_no_reparent,
+ },
+};
+
+KUNIT_ARRAY_PARAM(clk_leaf_mux_set_rate_parent_determine_rate_test,
+ clk_leaf_mux_set_rate_parent_determine_rate_test_cases,
+ clk_leaf_mux_set_rate_parent_determine_rate_test_case_to_desc)
+
/*
- * Test that, for a clock that will forward any rate request to its
- * parent, the rate request structure returned by __clk_determine_rate
- * is sane and will be what we expect.
+ * Test that when a clk that can't change rate itself calls a function like
+ * __clk_determine_rate() on its parent it doesn't get back a clk_rate_request
+ * structure that has the best_parent_hw pointer point to the clk_hw passed
+ * into the determine rate function. See commit 262ca38f4b6e ("clk: Stop
+ * forwarding clk_rate_requests to the parent") for more background.
*/
-static void clk_leaf_mux_set_rate_parent_determine_rate(struct kunit *test)
+static void clk_leaf_mux_set_rate_parent_determine_rate_test(struct kunit *test)
{
struct clk_leaf_mux_ctx *ctx = test->priv;
struct clk_hw *hw = &ctx->hw;
struct clk *clk = clk_hw_get_clk(hw, NULL);
struct clk_rate_request req;
unsigned long rate;
- int ret;
+ const struct clk_leaf_mux_set_rate_parent_determine_rate_test_case *test_param;
+
+ test_param = test->param_value;
+ ctx->determine_rate_func = test_param->determine_rate_func;
+ ctx->req = &req;
rate = clk_get_rate(clk);
KUNIT_ASSERT_EQ(test, rate, DUMMY_CLOCK_RATE_1);
-
- clk_hw_init_rate_request(hw, &req, DUMMY_CLOCK_RATE_2);
-
- ret = __clk_determine_rate(hw, &req);
- KUNIT_ASSERT_EQ(test, ret, 0);
+ KUNIT_ASSERT_EQ(test, DUMMY_CLOCK_RATE_2, clk_round_rate(clk, DUMMY_CLOCK_RATE_2));
KUNIT_EXPECT_EQ(test, req.rate, DUMMY_CLOCK_RATE_2);
KUNIT_EXPECT_EQ(test, req.best_parent_rate, DUMMY_CLOCK_RATE_2);
@@ -2243,15 +2338,16 @@ static void clk_leaf_mux_set_rate_parent_determine_rate(struct kunit *test)
}
static struct kunit_case clk_leaf_mux_set_rate_parent_test_cases[] = {
- KUNIT_CASE(clk_leaf_mux_set_rate_parent_determine_rate),
+ KUNIT_CASE_PARAM(clk_leaf_mux_set_rate_parent_determine_rate_test,
+ clk_leaf_mux_set_rate_parent_determine_rate_test_gen_params),
{}
};
/*
- * Test suite for a clock whose parent is a mux with multiple parents.
- * The leaf clock has CLK_SET_RATE_PARENT, and will forward rate
- * requests to the mux, which will then select which parent is the best
- * fit for a given rate.
+ * Test suite for a clock whose parent is a pass-through clk whose parent is a
+ * mux with multiple parents. The leaf and pass-through clocks have the
+ * CLK_SET_RATE_PARENT flag, and will forward rate requests to the mux, which
+ * will then select which parent is the best fit for a given rate.
*
* These tests exercise the behaviour of muxes, and the proper selection
* of parents.
diff --git a/drivers/clk/davinci/da8xx-cfgchip.c b/drivers/clk/davinci/da8xx-cfgchip.c
index e5b2cdfe88ce..ad2d0df43dc6 100644
--- a/drivers/clk/davinci/da8xx-cfgchip.c
+++ b/drivers/clk/davinci/da8xx-cfgchip.c
@@ -11,10 +11,10 @@
#include <linux/init.h>
#include <linux/mfd/da8xx-cfgchip.h>
#include <linux/mfd/syscon.h>
-#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_data/clk-da8xx-cfgchip.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@@ -744,15 +744,13 @@ static int da8xx_cfgchip_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct da8xx_cfgchip_clk_platform_data *pdata = dev->platform_data;
- const struct of_device_id *of_id;
da8xx_cfgchip_init clk_init = NULL;
struct regmap *regmap = NULL;
- of_id = of_match_device(da8xx_cfgchip_of_match, dev);
- if (of_id) {
+ clk_init = device_get_match_data(dev);
+ if (clk_init) {
struct device_node *parent;
- clk_init = of_id->data;
parent = of_get_parent(dev->of_node);
regmap = syscon_node_to_regmap(parent);
of_node_put(parent);
diff --git a/drivers/clk/davinci/pll.c b/drivers/clk/davinci/pll.c
index 87bdf8879045..5bbbb3a66477 100644
--- a/drivers/clk/davinci/pll.c
+++ b/drivers/clk/davinci/pll.c
@@ -18,11 +18,10 @@
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/notifier.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_data/clk-davinci-pll.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/types.h>
@@ -892,14 +891,11 @@ static int davinci_pll_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct davinci_pll_platform_data *pdata;
- const struct of_device_id *of_id;
davinci_pll_init pll_init = NULL;
void __iomem *base;
- of_id = of_match_device(davinci_pll_of_match, dev);
- if (of_id)
- pll_init = of_id->data;
- else if (pdev->id_entry)
+ pll_init = device_get_match_data(dev);
+ if (!pll_init && pdev->id_entry)
pll_init = (void *)pdev->id_entry->driver_data;
if (!pll_init) {
diff --git a/drivers/clk/davinci/psc.c b/drivers/clk/davinci/psc.c
index cd85d9f158b0..355d1be0b5d8 100644
--- a/drivers/clk/davinci/psc.c
+++ b/drivers/clk/davinci/psc.c
@@ -18,10 +18,9 @@
#include <linux/clk/davinci.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/pm_clock.h>
#include <linux/pm_domain.h>
#include <linux/regmap.h>
@@ -517,15 +516,12 @@ static const struct platform_device_id davinci_psc_id_table[] = {
static int davinci_psc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- const struct of_device_id *of_id;
const struct davinci_psc_init_data *init_data = NULL;
void __iomem *base;
int ret;
- of_id = of_match_device(davinci_psc_of_match, dev);
- if (of_id)
- init_data = of_id->data;
- else if (pdev->id_entry)
+ init_data = device_get_match_data(dev);
+ if (!init_data && pdev->id_entry)
init_data = (void *)pdev->id_entry->driver_data;
if (!init_data) {
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
index f6b82e0b9703..db3bca5f4ec9 100644
--- a/drivers/clk/imx/Kconfig
+++ b/drivers/clk/imx/Kconfig
@@ -96,6 +96,7 @@ config CLK_IMX8QXP
depends on (ARCH_MXC && ARM64) || COMPILE_TEST
depends on IMX_SCU && HAVE_ARM_SMCCC
select MXC_CLK_SCU
+ select MXC_CLK
help
Build the driver for IMX8QXP SCU based clocks.
diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c
index 3f1502933e59..69f8f6f9ca49 100644
--- a/drivers/clk/imx/clk-imx6sx.c
+++ b/drivers/clk/imx/clk-imx6sx.c
@@ -121,6 +121,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
void __iomem *base;
+ bool lcdif1_assigned_clk;
clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
IMX6SX_CLK_CLK_END), GFP_KERNEL);
@@ -498,9 +499,16 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clk_set_parent(hws[IMX6SX_CLK_EIM_SLOW_SEL]->clk, hws[IMX6SX_CLK_PLL2_PFD2]->clk);
clk_set_rate(hws[IMX6SX_CLK_EIM_SLOW]->clk, 132000000);
- /* set parent clock for LCDIF1 pixel clock */
- clk_set_parent(hws[IMX6SX_CLK_LCDIF1_PRE_SEL]->clk, hws[IMX6SX_CLK_PLL5_VIDEO_DIV]->clk);
- clk_set_parent(hws[IMX6SX_CLK_LCDIF1_SEL]->clk, hws[IMX6SX_CLK_LCDIF1_PODF]->clk);
+ np = of_find_node_by_path("/soc/bus@2200000/spba-bus@2240000/lcdif@2220000");
+ lcdif1_assigned_clk = of_find_property(np, "assigned-clock-parents", NULL);
+
+ /* Set parent clock for LCDIF1 pixel clock if not done via devicetree */
+ if (!lcdif1_assigned_clk) {
+ clk_set_parent(hws[IMX6SX_CLK_LCDIF1_PRE_SEL]->clk,
+ hws[IMX6SX_CLK_PLL5_VIDEO_DIV]->clk);
+ clk_set_parent(hws[IMX6SX_CLK_LCDIF1_SEL]->clk,
+ hws[IMX6SX_CLK_LCDIF1_PODF]->clk);
+ }
/* Set the parent clks of PCIe lvds1 and pcie_axi to be pcie ref, axi */
if (clk_set_parent(hws[IMX6SX_CLK_LVDS1_SEL]->clk, hws[IMX6SX_CLK_PCIE_REF_125M]->clk))
diff --git a/drivers/clk/imx/clk-imx8-acm.c b/drivers/clk/imx/clk-imx8-acm.c
index 1e82f72b75c6..f68877eef873 100644
--- a/drivers/clk/imx/clk-imx8-acm.c
+++ b/drivers/clk/imx/clk-imx8-acm.c
@@ -77,7 +77,7 @@ struct imx8_acm_priv {
static const struct clk_parent_data imx8qm_aud_clk_sels[] = {
{ .fw_name = "aud_rec_clk0_lpcg_clk" },
{ .fw_name = "aud_rec_clk1_lpcg_clk" },
- { .fw_name = "mlb_clk" },
+ { .fw_name = "dummy" },
{ .fw_name = "hdmi_rx_mclk" },
{ .fw_name = "ext_aud_mclk0" },
{ .fw_name = "ext_aud_mclk1" },
@@ -103,7 +103,7 @@ static const struct clk_parent_data imx8qm_aud_clk_sels[] = {
static const struct clk_parent_data imx8qm_mclk_out_sels[] = {
{ .fw_name = "aud_rec_clk0_lpcg_clk" },
{ .fw_name = "aud_rec_clk1_lpcg_clk" },
- { .fw_name = "mlb_clk" },
+ { .fw_name = "dummy" },
{ .fw_name = "hdmi_rx_mclk" },
{ .fw_name = "spdif0_rx" },
{ .fw_name = "spdif1_rx" },
@@ -122,7 +122,7 @@ static const struct clk_parent_data imx8qm_asrc_mux_clk_sels[] = {
{ .fw_name = "sai4_rx_bclk" },
{ .fw_name = "sai5_tx_bclk" },
{ .index = -1 },
- { .fw_name = "mlb_clk" },
+ { .fw_name = "dummy" },
};
@@ -279,8 +279,10 @@ static int clk_imx_acm_attach_pm_domains(struct device *dev,
for (i = 0; i < dev_pm->num_domains; i++) {
dev_pm->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
- if (IS_ERR(dev_pm->pd_dev[i]))
- return PTR_ERR(dev_pm->pd_dev[i]);
+ if (IS_ERR(dev_pm->pd_dev[i])) {
+ ret = PTR_ERR(dev_pm->pd_dev[i]);
+ goto detach_pm;
+ }
dev_pm->pd_dev_link[i] = device_link_add(dev,
dev_pm->pd_dev[i],
@@ -308,20 +310,18 @@ detach_pm:
* @dev: deivice pointer
* @dev_pm: multi power domain for device
*/
-static int clk_imx_acm_detach_pm_domains(struct device *dev,
- struct clk_imx_acm_pm_domains *dev_pm)
+static void clk_imx_acm_detach_pm_domains(struct device *dev,
+ struct clk_imx_acm_pm_domains *dev_pm)
{
int i;
if (dev_pm->num_domains <= 1)
- return 0;
+ return;
for (i = 0; i < dev_pm->num_domains; i++) {
device_link_del(dev_pm->pd_dev_link[i]);
dev_pm_domain_detach(dev_pm->pd_dev[i], false);
}
-
- return 0;
}
static int imx8_acm_clk_probe(struct platform_device *pdev)
@@ -371,22 +371,25 @@ static int imx8_acm_clk_probe(struct platform_device *pdev)
sels[i].shift, sels[i].width,
0, NULL, NULL);
if (IS_ERR(hws[sels[i].clkid])) {
- pm_runtime_disable(&pdev->dev);
+ ret = PTR_ERR(hws[sels[i].clkid]);
+ imx_check_clk_hws(hws, IMX_ADMA_ACM_CLK_END);
goto err_clk_register;
}
}
- imx_check_clk_hws(hws, IMX_ADMA_ACM_CLK_END);
-
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data);
if (ret < 0) {
dev_err(dev, "failed to register hws for ACM\n");
- pm_runtime_disable(&pdev->dev);
+ goto err_clk_register;
}
-err_clk_register:
+ pm_runtime_put_sync(&pdev->dev);
+ return 0;
+err_clk_register:
pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ clk_imx_acm_detach_pm_domains(&pdev->dev, &priv->dev_pm);
return ret;
}
diff --git a/drivers/clk/imx/clk-imx8dxl-rsrc.c b/drivers/clk/imx/clk-imx8dxl-rsrc.c
index 69b7aa34fff5..0f940335d83c 100644
--- a/drivers/clk/imx/clk-imx8dxl-rsrc.c
+++ b/drivers/clk/imx/clk-imx8dxl-rsrc.c
@@ -47,11 +47,10 @@ static u32 imx8dxl_clk_scu_rsrc_table[] = {
IMX_SC_R_SDHC_2,
IMX_SC_R_ENET_0,
IMX_SC_R_ENET_1,
- IMX_SC_R_MLB_0,
IMX_SC_R_USB_1,
IMX_SC_R_NAND,
- IMX_SC_R_M4_0_I2C,
IMX_SC_R_M4_0_UART,
+ IMX_SC_R_M4_0_I2C,
IMX_SC_R_ELCDIF_PLL,
IMX_SC_R_AUDIO_PLL_0,
IMX_SC_R_AUDIO_PLL_1,
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
index 4bd65879fcd3..f70ed231b92d 100644
--- a/drivers/clk/imx/clk-imx8mq.c
+++ b/drivers/clk/imx/clk-imx8mq.c
@@ -288,8 +288,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
void __iomem *base;
int err;
- clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
- IMX8MQ_CLK_END), GFP_KERNEL);
+ clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX8MQ_CLK_END), GFP_KERNEL);
if (WARN_ON(!clk_hw_data))
return -ENOMEM;
@@ -306,10 +305,12 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
hws[IMX8MQ_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-anatop");
- base = of_iomap(np, 0);
+ base = devm_of_iomap(dev, np, 0, NULL);
of_node_put(np);
- if (WARN_ON(!base))
- return -ENOMEM;
+ if (WARN_ON(IS_ERR(base))) {
+ err = PTR_ERR(base);
+ goto unregister_hws;
+ }
hws[IMX8MQ_ARM_PLL_REF_SEL] = imx_clk_hw_mux("arm_pll_ref_sel", base + 0x28, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
hws[IMX8MQ_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x18, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
@@ -395,8 +396,10 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
np = dev->of_node;
base = devm_platform_ioremap_resource(pdev, 0);
- if (WARN_ON(IS_ERR(base)))
- return PTR_ERR(base);
+ if (WARN_ON(IS_ERR(base))) {
+ err = PTR_ERR(base);
+ goto unregister_hws;
+ }
/* CORE */
hws[IMX8MQ_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mq_a53_sels, base + 0x8000);
diff --git a/drivers/clk/imx/clk-imx8qm-rsrc.c b/drivers/clk/imx/clk-imx8qm-rsrc.c
index 87e0b6ac027e..dadfdd9a4541 100644
--- a/drivers/clk/imx/clk-imx8qm-rsrc.c
+++ b/drivers/clk/imx/clk-imx8qm-rsrc.c
@@ -43,6 +43,8 @@ static const u32 imx8qm_clk_scu_rsrc_table[] = {
IMX_SC_R_FTM_0,
IMX_SC_R_FTM_1,
IMX_SC_R_CAN_0,
+ IMX_SC_R_CAN_1,
+ IMX_SC_R_CAN_2,
IMX_SC_R_GPU_0_PID0,
IMX_SC_R_GPU_1_PID0,
IMX_SC_R_PWM_0,
@@ -65,7 +67,6 @@ static const u32 imx8qm_clk_scu_rsrc_table[] = {
IMX_SC_R_SDHC_2,
IMX_SC_R_ENET_0,
IMX_SC_R_ENET_1,
- IMX_SC_R_MLB_0,
IMX_SC_R_USB_2,
IMX_SC_R_NAND,
IMX_SC_R_LVDS_0,
@@ -79,8 +80,6 @@ static const u32 imx8qm_clk_scu_rsrc_table[] = {
IMX_SC_R_M4_0_I2C,
IMX_SC_R_M4_1_I2C,
IMX_SC_R_AUDIO_PLL_0,
- IMX_SC_R_VPU_UART,
- IMX_SC_R_VPUCORE,
IMX_SC_R_MIPI_0,
IMX_SC_R_MIPI_0_PWM_0,
IMX_SC_R_MIPI_0_I2C_0,
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.h b/drivers/clk/imx/clk-imx8qxp-lpcg.h
index 2a37ce57c500..ebca8fa9268f 100644
--- a/drivers/clk/imx/clk-imx8qxp-lpcg.h
+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.h
@@ -42,7 +42,6 @@
#define CONN_ENET_0_LPCG 0x30000
#define CONN_ENET_1_LPCG 0x40000
#define CONN_DTCP_LPCG 0x50000
-#define CONN_MLB_LPCG 0x60000
#define CONN_USB_2_LPCG 0x70000
#define CONN_USB_3_LPCG 0x80000
#define CONN_NAND_LPCG 0x90000
diff --git a/drivers/clk/imx/clk-imx8qxp-rsrc.c b/drivers/clk/imx/clk-imx8qxp-rsrc.c
index df09f2a7996d..585c425524a4 100644
--- a/drivers/clk/imx/clk-imx8qxp-rsrc.c
+++ b/drivers/clk/imx/clk-imx8qxp-rsrc.c
@@ -54,15 +54,17 @@ static const u32 imx8qxp_clk_scu_rsrc_table[] = {
IMX_SC_R_SDHC_2,
IMX_SC_R_ENET_0,
IMX_SC_R_ENET_1,
- IMX_SC_R_MLB_0,
IMX_SC_R_USB_2,
IMX_SC_R_NAND,
IMX_SC_R_LVDS_0,
IMX_SC_R_LVDS_1,
+ IMX_SC_R_M4_0_UART,
IMX_SC_R_M4_0_I2C,
IMX_SC_R_ELCDIF_PLL,
IMX_SC_R_AUDIO_PLL_0,
IMX_SC_R_PI_0,
+ IMX_SC_R_PI_0_PWM_0,
+ IMX_SC_R_PI_0_I2C_0,
IMX_SC_R_PI_0_PLL,
IMX_SC_R_MIPI_0,
IMX_SC_R_MIPI_0_PWM_0,
diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c
index cadcbb318f5c..41f0a45aa162 100644
--- a/drivers/clk/imx/clk-imx8qxp.c
+++ b/drivers/clk/imx/clk-imx8qxp.c
@@ -90,6 +90,11 @@ static const char * const pi_pll0_sels[] = {
"clk_dummy",
};
+static inline bool clk_on_imx8dxl(struct device_node *node)
+{
+ return of_device_is_compatible(node, "fsl,imx8dxl-clk");
+}
+
static int imx8qxp_clk_probe(struct platform_device *pdev)
{
struct device_node *ccm_node = pdev->dev.of_node;
@@ -147,10 +152,10 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER);
imx_clk_scu("adc1_clk", IMX_SC_R_ADC_1, IMX_SC_PM_CLK_PER);
imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER);
+ imx_clk_scu("elcdif_pll", IMX_SC_R_ELCDIF_PLL, IMX_SC_PM_CLK_PLL);
imx_clk_scu2("lcd_clk", lcd_sels, ARRAY_SIZE(lcd_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER);
imx_clk_scu2("lcd_pxl_clk", lcd_pxl_sels, ARRAY_SIZE(lcd_pxl_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_MISC0);
imx_clk_scu("lcd_pxl_bypass_div_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_BYPASS);
- imx_clk_scu("elcdif_pll", IMX_SC_R_ELCDIF_PLL, IMX_SC_PM_CLK_PLL);
/* Audio SS */
imx_clk_scu("audio_pll0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_PLL);
@@ -169,13 +174,15 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
imx_clk_mux_gpr_scu("enet0_rgmii_txc_sel", enet0_rgmii_txc_sels, ARRAY_SIZE(enet0_rgmii_txc_sels), IMX_SC_R_ENET_0, IMX_SC_C_TXCLK);
imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS);
imx_clk_gate_gpr_scu("enet0_ref_50_clk", "clk_dummy", IMX_SC_R_ENET_0, IMX_SC_C_DISABLE_50, true);
- imx_clk_scu("enet0_rgmii_rx_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0);
+ if (!clk_on_imx8dxl(ccm_node)) {
+ imx_clk_scu("enet0_rgmii_rx_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0);
+ imx_clk_scu("enet1_rgmii_rx_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0);
+ }
imx_clk_scu("enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER);
imx_clk_divider_gpr_scu("enet1_ref_div", "enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_C_CLKDIV);
imx_clk_mux_gpr_scu("enet1_rgmii_txc_sel", enet1_rgmii_txc_sels, ARRAY_SIZE(enet1_rgmii_txc_sels), IMX_SC_R_ENET_1, IMX_SC_C_TXCLK);
imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS);
imx_clk_gate_gpr_scu("enet1_ref_50_clk", "clk_dummy", IMX_SC_R_ENET_1, IMX_SC_C_DISABLE_50, true);
- imx_clk_scu("enet1_rgmii_rx_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0);
imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS);
imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER);
imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER);
diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
index cd83c52e9952..be89180dd19c 100644
--- a/drivers/clk/imx/clk-scu.c
+++ b/drivers/clk/imx/clk-scu.c
@@ -10,10 +10,12 @@
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/of.h>
+#include <linux/firmware/imx/svc/rm.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
+#include <xen/xen.h>
#include "clk-scu.h"
@@ -670,6 +672,18 @@ static int imx_clk_scu_attach_pd(struct device *dev, u32 rsrc_id)
return of_genpd_add_device(&genpdspec, dev);
}
+static bool imx_clk_is_resource_owned(u32 rsrc)
+{
+ /*
+ * A-core resources are special. SCFW reports they are not "owned" by
+ * current partition but linux can still adjust them for cpufreq.
+ */
+ if (rsrc == IMX_SC_R_A53 || rsrc == IMX_SC_R_A72 || rsrc == IMX_SC_R_A35)
+ return true;
+
+ return imx_sc_rm_is_resource_owned(ccm_ipc_handle, rsrc);
+}
+
struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
const char * const *parents,
int num_parents, u32 rsrc_id, u8 clk_type)
@@ -687,6 +701,9 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
if (!imx_scu_clk_is_valid(rsrc_id))
return ERR_PTR(-EINVAL);
+ if (!imx_clk_is_resource_owned(rsrc_id))
+ return NULL;
+
pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE);
if (!pdev) {
pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n",
@@ -869,6 +886,9 @@ struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_na
return ERR_PTR(-EINVAL);
}
+ if (!imx_clk_is_resource_owned(rsrc_id))
+ return NULL;
+
clk = kzalloc(sizeof(*clk), GFP_KERNEL);
if (!clk) {
kfree(clk_node);
diff --git a/drivers/clk/keystone/pll.c b/drivers/clk/keystone/pll.c
index ee5c72369334..6bbdd4705d71 100644
--- a/drivers/clk/keystone/pll.c
+++ b/drivers/clk/keystone/pll.c
@@ -281,12 +281,13 @@ static void __init of_pll_div_clk_init(struct device_node *node)
clk = clk_register_divider(NULL, clk_name, parent_name, 0, reg, shift,
mask, 0, NULL);
- if (clk) {
- of_clk_add_provider(node, of_clk_src_simple_get, clk);
- } else {
+ if (IS_ERR(clk)) {
pr_err("%s: error registering divider %s\n", __func__, clk_name);
iounmap(reg);
+ return;
}
+
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
}
CLK_OF_DECLARE(pll_divider_clock, "ti,keystone,pll-divider-clock", of_pll_div_clk_init);
@@ -328,10 +329,12 @@ static void __init of_pll_mux_clk_init(struct device_node *node)
clk = clk_register_mux(NULL, clk_name, (const char **)&parents,
ARRAY_SIZE(parents) , 0, reg, shift, mask,
0, NULL);
- if (clk)
- of_clk_add_provider(node, of_clk_src_simple_get, clk);
- else
+ if (IS_ERR(clk)) {
pr_err("%s: error registering mux %s\n", __func__, clk_name);
+ return;
+ }
+
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
}
CLK_OF_DECLARE(pll_mux_clock, "ti,keystone,pll-mux-clock", of_pll_mux_clk_init);
diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
index c81f3e33ce56..12d9560eb4ba 100644
--- a/drivers/clk/mediatek/clk-mt2701.c
+++ b/drivers/clk/mediatek/clk-mt2701.c
@@ -667,6 +667,8 @@ static int mtk_topckgen_init(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
clk_data);
@@ -747,6 +749,8 @@ static void __init mtk_infrasys_init_early(struct device_node *node)
if (!infra_clk_data) {
infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+ if (!infra_clk_data)
+ return;
for (i = 0; i < CLK_INFRA_NR; i++)
infra_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);
@@ -774,6 +778,8 @@ static int mtk_infrasys_init(struct platform_device *pdev)
if (!infra_clk_data) {
infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+ if (!infra_clk_data)
+ return -ENOMEM;
} else {
for (i = 0; i < CLK_INFRA_NR; i++) {
if (infra_clk_data->hws[i] == ERR_PTR(-EPROBE_DEFER))
@@ -890,6 +896,8 @@ static int mtk_pericfg_init(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_PERI_NR);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_gates(&pdev->dev, node, peri_clks,
ARRAY_SIZE(peri_clks), clk_data);
diff --git a/drivers/clk/mediatek/clk-mt6765.c b/drivers/clk/mediatek/clk-mt6765.c
index 1f4c8d0c041a..9c7f7407d798 100644
--- a/drivers/clk/mediatek/clk-mt6765.c
+++ b/drivers/clk/mediatek/clk-mt6765.c
@@ -737,6 +737,8 @@ static int clk_mt6765_apmixed_probe(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
@@ -769,6 +771,8 @@ static int clk_mt6765_top_probe(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks),
clk_data);
@@ -807,6 +811,8 @@ static int clk_mt6765_ifr_probe(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_IFR_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_gates(&pdev->dev, node, ifr_clks,
ARRAY_SIZE(ifr_clks), clk_data);
diff --git a/drivers/clk/mediatek/clk-mt6779.c b/drivers/clk/mediatek/clk-mt6779.c
index 3ee2f5a2319a..ffedb1fe3c67 100644
--- a/drivers/clk/mediatek/clk-mt6779.c
+++ b/drivers/clk/mediatek/clk-mt6779.c
@@ -1217,6 +1217,8 @@ static int clk_mt6779_apmixed_probe(struct platform_device *pdev)
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
@@ -1237,6 +1239,8 @@ static int clk_mt6779_top_probe(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
clk_data);
diff --git a/drivers/clk/mediatek/clk-mt6797.c b/drivers/clk/mediatek/clk-mt6797.c
index 2ebd25f0ce71..f12d4e9ff0bb 100644
--- a/drivers/clk/mediatek/clk-mt6797.c
+++ b/drivers/clk/mediatek/clk-mt6797.c
@@ -390,6 +390,8 @@ static int mtk_topckgen_init(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
clk_data);
@@ -545,6 +547,8 @@ static void mtk_infrasys_init_early(struct device_node *node)
if (!infra_clk_data) {
infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+ if (!infra_clk_data)
+ return;
for (i = 0; i < CLK_INFRA_NR; i++)
infra_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);
@@ -570,6 +574,8 @@ static int mtk_infrasys_init(struct platform_device *pdev)
if (!infra_clk_data) {
infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+ if (!infra_clk_data)
+ return -ENOMEM;
} else {
for (i = 0; i < CLK_INFRA_NR; i++) {
if (infra_clk_data->hws[i] == ERR_PTR(-EPROBE_DEFER))
diff --git a/drivers/clk/mediatek/clk-mt7629-eth.c b/drivers/clk/mediatek/clk-mt7629-eth.c
index fe714debdc9e..1bfedc988cfe 100644
--- a/drivers/clk/mediatek/clk-mt7629-eth.c
+++ b/drivers/clk/mediatek/clk-mt7629-eth.c
@@ -77,6 +77,8 @@ static int clk_mt7629_ethsys_init(struct platform_device *pdev)
int r;
clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_gates(&pdev->dev, node, eth_clks,
CLK_ETH_NR_CLK, clk_data);
@@ -100,6 +102,8 @@ static int clk_mt7629_sgmiisys_init(struct platform_device *pdev)
int r;
clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_gates(&pdev->dev, node, sgmii_clks[id++],
CLK_SGMII_NR_CLK, clk_data);
diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c
index 2882107d0f24..b8a1f01bc974 100644
--- a/drivers/clk/mediatek/clk-mt7629.c
+++ b/drivers/clk/mediatek/clk-mt7629.c
@@ -555,6 +555,8 @@ static int mtk_topckgen_init(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
clk_data);
@@ -579,6 +581,8 @@ static int mtk_infrasys_init(struct platform_device *pdev)
struct clk_hw_onecell_data *clk_data;
clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_gates(&pdev->dev, node, infra_clks,
ARRAY_SIZE(infra_clks), clk_data);
@@ -602,6 +606,8 @@ static int mtk_pericfg_init(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
mtk_clk_register_gates(&pdev->dev, node, peri_clks,
ARRAY_SIZE(peri_clks), clk_data);
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index a4eca5fd539c..513ab6b1b322 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -321,10 +321,8 @@ struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll,
ret = clk_hw_register(NULL, &pll->hw);
- if (ret) {
- kfree(pll);
+ if (ret)
return ERR_PTR(ret);
- }
return &pll->hw;
}
@@ -340,6 +338,8 @@ struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data,
return ERR_PTR(-ENOMEM);
hw = mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_ops);
+ if (IS_ERR(hw))
+ kfree(pll);
return hw;
}
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 135da8f2d0b1..29ffd14d267b 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -144,4 +144,29 @@ config COMMON_CLK_G12A
help
Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2
devices, aka g12a. Say Y if you want peripherals to work.
+
+config COMMON_CLK_S4_PLL
+ tristate "S4 SoC PLL clock controllers support"
+ depends on ARM64
+ default y
+ select COMMON_CLK_MESON_CLKC_UTILS
+ select COMMON_CLK_MESON_MPLL
+ select COMMON_CLK_MESON_PLL
+ select COMMON_CLK_MESON_REGMAP
+ help
+ Support for the PLL clock controller on Amlogic S805X2 and S905Y4 devices,
+ AKA S4. Say Y if you want the board to work, because PLLs are the parent of
+ most peripherals.
+
+config COMMON_CLK_S4_PERIPHERALS
+ tristate "S4 SoC peripherals clock controllers support"
+ depends on ARM64
+ default y
+ select COMMON_CLK_MESON_CLKC_UTILS
+ select COMMON_CLK_MESON_REGMAP
+ select COMMON_CLK_MESON_DUALDIV
+ select COMMON_CLK_MESON_VID_PLL_DIV
+ help
+ Support for the peripherals clock controller on Amlogic S805X2 and S905Y4
+ devices, AKA S4. Say Y if you want S4 peripherals clock controller to work.
endmenu
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index cd961cc4f4db..9ee4b954c896 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -22,3 +22,5 @@ obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
+obj-$(CONFIG_COMMON_CLK_S4_PLL) += s4-pll.o
+obj-$(CONFIG_COMMON_CLK_S4_PERIPHERALS) += s4-peripherals.o
diff --git a/drivers/clk/meson/s4-peripherals.c b/drivers/clk/meson/s4-peripherals.c
new file mode 100644
index 000000000000..6c35de3d536f
--- /dev/null
+++ b/drivers/clk/meson/s4-peripherals.c
@@ -0,0 +1,3813 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Amlogic S4 Peripherals Clock Controller Driver
+ *
+ * Copyright (c) 2022-2023 Amlogic, inc. All rights reserved
+ * Author: Yu Tu <yu.tu@amlogic.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-regmap.h"
+#include "vid-pll-div.h"
+#include "clk-dualdiv.h"
+#include "s4-peripherals.h"
+#include "meson-clkc-utils.h"
+#include <dt-bindings/clock/amlogic,s4-peripherals-clkc.h>
+
+static struct clk_regmap s4_rtc_32k_by_oscin_clkin = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_RTC_BY_OSCIN_CTRL0,
+ .bit_idx = 31,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "rtc_32k_by_oscin_clkin",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", }
+ },
+ .num_parents = 1,
+ },
+};
+
+static const struct meson_clk_dualdiv_param s4_32k_div_table[] = {
+ {
+ .dual = 1,
+ .n1 = 733,
+ .m1 = 8,
+ .n2 = 732,
+ .m2 = 11,
+ },
+ {}
+};
+
+static struct clk_regmap s4_rtc_32k_by_oscin_div = {
+ .data = &(struct meson_clk_dualdiv_data){
+ .n1 = {
+ .reg_off = CLKCTRL_RTC_BY_OSCIN_CTRL0,
+ .shift = 0,
+ .width = 12,
+ },
+ .n2 = {
+ .reg_off = CLKCTRL_RTC_BY_OSCIN_CTRL0,
+ .shift = 12,
+ .width = 12,
+ },
+ .m1 = {
+ .reg_off = CLKCTRL_RTC_BY_OSCIN_CTRL1,
+ .shift = 0,
+ .width = 12,
+ },
+ .m2 = {
+ .reg_off = CLKCTRL_RTC_BY_OSCIN_CTRL1,
+ .shift = 12,
+ .width = 12,
+ },
+ .dual = {
+ .reg_off = CLKCTRL_RTC_BY_OSCIN_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .table = s4_32k_div_table,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "rtc_32k_by_oscin_div",
+ .ops = &meson_clk_dualdiv_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_rtc_32k_by_oscin_clkin.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_rtc_32k_by_oscin_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_RTC_BY_OSCIN_CTRL1,
+ .mask = 0x1,
+ .shift = 24,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "rtc_32k_by_oscin_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_rtc_32k_by_oscin_div.hw,
+ &s4_rtc_32k_by_oscin_clkin.hw,
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_rtc_32k_by_oscin = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_RTC_BY_OSCIN_CTRL0,
+ .bit_idx = 30,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "rtc_32k_by_oscin",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_rtc_32k_by_oscin_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_rtc_clk = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_RTC_CTRL,
+ .mask = 0x3,
+ .shift = 0,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "rtc_clk_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_rtc_32k_by_oscin.hw,
+ &s4_rtc_32k_by_oscin_div.hw,
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* The index 5 is AXI_CLK, which is dedicated to AXI. So skip it. */
+static u32 mux_table_sys_ab_clk_sel[] = { 0, 1, 2, 3, 4, 6, 7 };
+static const struct clk_parent_data sys_ab_clk_parent_data[] = {
+ { .fw_name = "xtal" },
+ { .fw_name = "fclk_div2" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "fclk_div7" },
+ { .hw = &s4_rtc_clk.hw }
+};
+
+/*
+ * This clock is initialized by ROMcode.
+ * The chip was changed SYS CLK for security reasons. SYS CLK registers are not writable
+ * in the kernel phase. Write of SYS related register will cause the system to crash.
+ * Meanwhile, these clock won't ever change at runtime.
+ * For the above reasons, we can only use ro_ops for SYS related clocks.
+ */
+static struct clk_regmap s4_sysclk_b_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_SYS_CLK_CTRL0,
+ .mask = 0x7,
+ .shift = 26,
+ .table = mux_table_sys_ab_clk_sel,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sysclk_b_sel",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_data = sys_ab_clk_parent_data,
+ .num_parents = ARRAY_SIZE(sys_ab_clk_parent_data),
+ },
+};
+
+static struct clk_regmap s4_sysclk_b_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_SYS_CLK_CTRL0,
+ .shift = 16,
+ .width = 10,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sysclk_b_div",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sysclk_b_sel.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_sysclk_b = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_SYS_CLK_CTRL0,
+ .bit_idx = 29,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sysclk_b",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sysclk_b_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_sysclk_a_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_SYS_CLK_CTRL0,
+ .mask = 0x7,
+ .shift = 10,
+ .table = mux_table_sys_ab_clk_sel,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sysclk_a_sel",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_data = sys_ab_clk_parent_data,
+ .num_parents = ARRAY_SIZE(sys_ab_clk_parent_data),
+ },
+};
+
+static struct clk_regmap s4_sysclk_a_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_SYS_CLK_CTRL0,
+ .shift = 0,
+ .width = 10,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sysclk_a_div",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sysclk_a_sel.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_sysclk_a = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_SYS_CLK_CTRL0,
+ .bit_idx = 13,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sysclk_a",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sysclk_a_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_sys_clk = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_SYS_CLK_CTRL0,
+ .mask = 0x1,
+ .shift = 31,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sys_clk",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sysclk_a.hw,
+ &s4_sysclk_b.hw
+ },
+ .num_parents = 2,
+ },
+};
+
+static struct clk_regmap s4_ceca_32k_clkin = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_CECA_CTRL0,
+ .bit_idx = 31,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "ceca_32k_clkin",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", }
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_ceca_32k_div = {
+ .data = &(struct meson_clk_dualdiv_data){
+ .n1 = {
+ .reg_off = CLKCTRL_CECA_CTRL0,
+ .shift = 0,
+ .width = 12,
+ },
+ .n2 = {
+ .reg_off = CLKCTRL_CECA_CTRL0,
+ .shift = 12,
+ .width = 12,
+ },
+ .m1 = {
+ .reg_off = CLKCTRL_CECA_CTRL1,
+ .shift = 0,
+ .width = 12,
+ },
+ .m2 = {
+ .reg_off = CLKCTRL_CECA_CTRL1,
+ .shift = 12,
+ .width = 12,
+ },
+ .dual = {
+ .reg_off = CLKCTRL_CECA_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .table = s4_32k_div_table,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ceca_32k_div",
+ .ops = &meson_clk_dualdiv_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_ceca_32k_clkin.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_ceca_32k_sel_pre = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_CECA_CTRL1,
+ .mask = 0x1,
+ .shift = 24,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ceca_32k_sel_pre",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_ceca_32k_div.hw,
+ &s4_ceca_32k_clkin.hw
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_ceca_32k_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_CECA_CTRL1,
+ .mask = 0x1,
+ .shift = 31,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ceca_32k_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_ceca_32k_sel_pre.hw,
+ &s4_rtc_clk.hw
+ },
+ .num_parents = 2,
+ },
+};
+
+static struct clk_regmap s4_ceca_32k_clkout = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_CECA_CTRL0,
+ .bit_idx = 30,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ceca_32k_clkout",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_ceca_32k_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_cecb_32k_clkin = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_CECB_CTRL0,
+ .bit_idx = 31,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "cecb_32k_clkin",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", }
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_cecb_32k_div = {
+ .data = &(struct meson_clk_dualdiv_data){
+ .n1 = {
+ .reg_off = CLKCTRL_CECB_CTRL0,
+ .shift = 0,
+ .width = 12,
+ },
+ .n2 = {
+ .reg_off = CLKCTRL_CECB_CTRL0,
+ .shift = 12,
+ .width = 12,
+ },
+ .m1 = {
+ .reg_off = CLKCTRL_CECB_CTRL1,
+ .shift = 0,
+ .width = 12,
+ },
+ .m2 = {
+ .reg_off = CLKCTRL_CECB_CTRL1,
+ .shift = 12,
+ .width = 12,
+ },
+ .dual = {
+ .reg_off = CLKCTRL_CECB_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .table = s4_32k_div_table,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cecb_32k_div",
+ .ops = &meson_clk_dualdiv_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_cecb_32k_clkin.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_cecb_32k_sel_pre = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_CECB_CTRL1,
+ .mask = 0x1,
+ .shift = 24,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cecb_32k_sel_pre",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_cecb_32k_div.hw,
+ &s4_cecb_32k_clkin.hw
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_cecb_32k_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_CECB_CTRL1,
+ .mask = 0x1,
+ .shift = 31,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cecb_32k_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_cecb_32k_sel_pre.hw,
+ &s4_rtc_clk.hw
+ },
+ .num_parents = 2,
+ },
+};
+
+static struct clk_regmap s4_cecb_32k_clkout = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_CECB_CTRL0,
+ .bit_idx = 30,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cecb_32k_clkout",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_cecb_32k_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data s4_sc_parent_data[] = {
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "xtal", }
+};
+
+static struct clk_regmap s4_sc_clk_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_SC_CLK_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sc_clk_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_sc_parent_data,
+ .num_parents = ARRAY_SIZE(s4_sc_parent_data),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_sc_clk_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_SC_CLK_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sc_clk_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sc_clk_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_sc_clk_gate = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_SC_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sc_clk_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sc_clk_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_12_24M_clk_gate = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_CLK12_24_CTRL,
+ .bit_idx = 11,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "12_24m_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", }
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor s4_12M_clk_div = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "12M",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_12_24M_clk_gate.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_12_24M_clk = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_CLK12_24_CTRL,
+ .mask = 0x1,
+ .shift = 10,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "12_24m",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_12_24M_clk_gate.hw,
+ &s4_12M_clk_div.hw,
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* Video Clocks */
+static struct clk_regmap s4_vid_pll_div = {
+ .data = &(struct meson_vid_pll_div_data){
+ .val = {
+ .reg_off = CLKCTRL_VID_PLL_CLK_DIV,
+ .shift = 0,
+ .width = 15,
+ },
+ .sel = {
+ .reg_off = CLKCTRL_VID_PLL_CLK_DIV,
+ .shift = 16,
+ .width = 2,
+ },
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vid_pll_div",
+ /*
+ * TODO meson_vid_pll_div_ro_ops to meson_vid_pll_div_ops
+ */
+ .ops = &meson_vid_pll_div_ro_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "hdmi_pll", }
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vid_pll_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VID_PLL_CLK_DIV,
+ .mask = 0x1,
+ .shift = 18,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vid_pll_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .hw = &s4_vid_pll_div.hw },
+ { .fw_name = "hdmi_pll", }
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vid_pll = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VID_PLL_CLK_DIV,
+ .bit_idx = 19,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vid_pll",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vid_pll_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data s4_vclk_parent_data[] = {
+ { .hw = &s4_vid_pll.hw },
+ { .fw_name = "gp0_pll", },
+ { .fw_name = "hifi_pll", },
+ { .fw_name = "mpll1", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "fclk_div7", },
+};
+
+static struct clk_regmap s4_vclk_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VID_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 16,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vclk_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_vclk_parent_data,
+ .num_parents = ARRAY_SIZE(s4_vclk_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_vclk2_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VIID_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 16,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vclk2_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_vclk_parent_data,
+ .num_parents = ARRAY_SIZE(s4_vclk_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_vclk_input = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VID_CLK_DIV,
+ .bit_idx = 16,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk_input",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk_sel.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk2_input = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VIID_CLK_DIV,
+ .bit_idx = 16,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk2_input",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk2_sel.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VID_CLK_DIV,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vclk_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vclk_input.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk2_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VIID_CLK_DIV,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vclk2_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vclk2_input.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VID_CLK_CTRL,
+ .bit_idx = 19,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk_div.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk2 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VIID_CLK_CTRL,
+ .bit_idx = 19,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk2",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk2_div.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk_div1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VID_CLK_CTRL,
+ .bit_idx = 0,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk_div1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk_div2_en = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VID_CLK_CTRL,
+ .bit_idx = 1,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk_div2_en",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk_div4_en = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VID_CLK_CTRL,
+ .bit_idx = 2,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk_div4_en",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk_div6_en = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VID_CLK_CTRL,
+ .bit_idx = 3,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk_div6_en",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk_div12_en = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VID_CLK_CTRL,
+ .bit_idx = 4,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk_div12_en",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk2_div1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VIID_CLK_CTRL,
+ .bit_idx = 0,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk2_div1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk2.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk2_div2_en = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VIID_CLK_CTRL,
+ .bit_idx = 1,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk2_div2_en",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk2.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk2_div4_en = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VIID_CLK_CTRL,
+ .bit_idx = 2,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk2_div4_en",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk2.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk2_div6_en = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VIID_CLK_CTRL,
+ .bit_idx = 3,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk2_div6_en",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk2.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vclk2_div12_en = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VIID_CLK_CTRL,
+ .bit_idx = 4,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vclk2_div12_en",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vclk2.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_fixed_factor s4_vclk_div2 = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "vclk_div2",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vclk_div2_en.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_fixed_factor s4_vclk_div4 = {
+ .mult = 1,
+ .div = 4,
+ .hw.init = &(struct clk_init_data){
+ .name = "vclk_div4",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vclk_div4_en.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_fixed_factor s4_vclk_div6 = {
+ .mult = 1,
+ .div = 6,
+ .hw.init = &(struct clk_init_data){
+ .name = "vclk_div6",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vclk_div6_en.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_fixed_factor s4_vclk_div12 = {
+ .mult = 1,
+ .div = 12,
+ .hw.init = &(struct clk_init_data){
+ .name = "vclk_div12",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vclk_div12_en.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_fixed_factor s4_vclk2_div2 = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "vclk2_div2",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vclk2_div2_en.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_fixed_factor s4_vclk2_div4 = {
+ .mult = 1,
+ .div = 4,
+ .hw.init = &(struct clk_init_data){
+ .name = "vclk2_div4",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vclk2_div4_en.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_fixed_factor s4_vclk2_div6 = {
+ .mult = 1,
+ .div = 6,
+ .hw.init = &(struct clk_init_data){
+ .name = "vclk2_div6",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vclk2_div6_en.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_fixed_factor s4_vclk2_div12 = {
+ .mult = 1,
+ .div = 12,
+ .hw.init = &(struct clk_init_data){
+ .name = "vclk2_div12",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vclk2_div12_en.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* The 5,6,7 indexes corresponds to no real clock, so there are not used. */
+static u32 mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
+static const struct clk_hw *s4_cts_parent_hws[] = {
+ &s4_vclk_div1.hw,
+ &s4_vclk_div2.hw,
+ &s4_vclk_div4.hw,
+ &s4_vclk_div6.hw,
+ &s4_vclk_div12.hw,
+ &s4_vclk2_div1.hw,
+ &s4_vclk2_div2.hw,
+ &s4_vclk2_div4.hw,
+ &s4_vclk2_div6.hw,
+ &s4_vclk2_div12.hw
+};
+
+static struct clk_regmap s4_cts_enci_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VID_CLK_DIV,
+ .mask = 0xf,
+ .shift = 28,
+ .table = mux_table_cts_sel,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cts_enci_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = s4_cts_parent_hws,
+ .num_parents = ARRAY_SIZE(s4_cts_parent_hws),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_cts_encp_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VID_CLK_DIV,
+ .mask = 0xf,
+ .shift = 20,
+ .table = mux_table_cts_sel,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cts_encp_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = s4_cts_parent_hws,
+ .num_parents = ARRAY_SIZE(s4_cts_parent_hws),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_cts_vdac_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VIID_CLK_DIV,
+ .mask = 0xf,
+ .shift = 28,
+ .table = mux_table_cts_sel,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cts_vdac_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = s4_cts_parent_hws,
+ .num_parents = ARRAY_SIZE(s4_cts_parent_hws),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* The 5,6,7 indexes corresponds to no real clock, so there are not used. */
+static u32 mux_table_hdmi_tx_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
+static const struct clk_hw *s4_cts_hdmi_tx_parent_hws[] = {
+ &s4_vclk_div1.hw,
+ &s4_vclk_div2.hw,
+ &s4_vclk_div4.hw,
+ &s4_vclk_div6.hw,
+ &s4_vclk_div12.hw,
+ &s4_vclk2_div1.hw,
+ &s4_vclk2_div2.hw,
+ &s4_vclk2_div4.hw,
+ &s4_vclk2_div6.hw,
+ &s4_vclk2_div12.hw
+};
+
+static struct clk_regmap s4_hdmi_tx_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_HDMI_CLK_CTRL,
+ .mask = 0xf,
+ .shift = 16,
+ .table = mux_table_hdmi_tx_sel,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_tx_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = s4_cts_hdmi_tx_parent_hws,
+ .num_parents = ARRAY_SIZE(s4_cts_hdmi_tx_parent_hws),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_cts_enci = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VID_CLK_CTRL2,
+ .bit_idx = 0,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "cts_enci",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_cts_enci_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_cts_encp = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VID_CLK_CTRL2,
+ .bit_idx = 2,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "cts_encp",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_cts_encp_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_cts_vdac = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VID_CLK_CTRL2,
+ .bit_idx = 4,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "cts_vdac",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_cts_vdac_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hdmi_tx = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VID_CLK_CTRL2,
+ .bit_idx = 5,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hdmi_tx",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_hdmi_tx_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* HDMI Clocks */
+static const struct clk_parent_data s4_hdmi_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div5", }
+};
+
+static struct clk_regmap s4_hdmi_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_HDMI_CLK_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_hdmi_parent_data,
+ .num_parents = ARRAY_SIZE(s4_hdmi_parent_data),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hdmi_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_HDMI_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_hdmi_sel.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hdmi = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_HDMI_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hdmi",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_hdmi_div.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_ts_clk_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_TS_CLK_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ts_clk_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_ts_clk_gate = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_TS_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ts_clk",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_ts_clk_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/*
+ * The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
+ * muxed by a glitch-free switch. The CCF can manage this glitch-free
+ * mux because it does top-to-bottom updates the each clock tree and
+ * switches to the "inactive" one when CLK_SET_RATE_GATE is set.
+ */
+static const struct clk_parent_data s4_mali_0_1_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .fw_name = "gp0_pll", },
+ { .fw_name = "hifi_pll", },
+ { .fw_name = "fclk_div2p5", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "fclk_div7", }
+};
+
+static struct clk_regmap s4_mali_0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_MALI_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mali_0_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_mali_0_1_parent_data,
+ .num_parents = ARRAY_SIZE(s4_mali_0_1_parent_data),
+ /*
+ * Don't request the parent to change the rate because
+ * all GPU frequencies can be derived from the fclk_*
+ * clocks and one special GP0_PLL setting. This is
+ * important because we need the HIFI PLL clock for audio.
+ */
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_mali_0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_MALI_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mali_0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_mali_0_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_mali_0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_MALI_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mali_0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_mali_0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_mali_1_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_MALI_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mali_1_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_mali_0_1_parent_data,
+ .num_parents = ARRAY_SIZE(s4_mali_0_1_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_mali_1_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_MALI_CLK_CTRL,
+ .shift = 16,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mali_1_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_mali_1_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_mali_1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_MALI_CLK_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mali_1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_mali_1_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_hw *s4_mali_parent_hws[] = {
+ &s4_mali_0.hw,
+ &s4_mali_1.hw
+};
+
+static struct clk_regmap s4_mali_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_MALI_CLK_CTRL,
+ .mask = 1,
+ .shift = 31,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mali",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = s4_mali_parent_hws,
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* VDEC clocks */
+static const struct clk_parent_data s4_dec_parent_data[] = {
+ { .fw_name = "fclk_div2p5", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "fclk_div7", },
+ { .fw_name = "hifi_pll", },
+ { .fw_name = "gp0_pll", },
+ { .fw_name = "xtal", }
+};
+
+static struct clk_regmap s4_vdec_p0_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VDEC_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vdec_p0_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_dec_parent_data,
+ .num_parents = ARRAY_SIZE(s4_dec_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_vdec_p0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VDEC_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vdec_p0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vdec_p0_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vdec_p0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VDEC_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vdec_p0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vdec_p0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vdec_p1_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VDEC3_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vdec_p1_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_dec_parent_data,
+ .num_parents = ARRAY_SIZE(s4_dec_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_vdec_p1_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VDEC3_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vdec_p1_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vdec_p1_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vdec_p1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VDEC3_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vdec_p1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vdec_p1_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_hw *s4_vdec_mux_parent_hws[] = {
+ &s4_vdec_p0.hw,
+ &s4_vdec_p1.hw
+};
+
+static struct clk_regmap s4_vdec_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VDEC3_CLK_CTRL,
+ .mask = 0x1,
+ .shift = 15,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vdec_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = s4_vdec_mux_parent_hws,
+ .num_parents = ARRAY_SIZE(s4_vdec_mux_parent_hws),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hevcf_p0_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VDEC2_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hevcf_p0_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_dec_parent_data,
+ .num_parents = ARRAY_SIZE(s4_dec_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_hevcf_p0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VDEC2_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hevcf_p0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_hevcf_p0_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hevcf_p0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VDEC2_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hevcf_p0_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_hevcf_p0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hevcf_p1_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VDEC4_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hevcf_p1_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_dec_parent_data,
+ .num_parents = ARRAY_SIZE(s4_dec_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_hevcf_p1_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VDEC4_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hevcf_p1_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_hevcf_p1_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hevcf_p1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VDEC4_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hevcf_p1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_hevcf_p1_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_hw *s4_hevcf_mux_parent_hws[] = {
+ &s4_hevcf_p0.hw,
+ &s4_hevcf_p1.hw
+};
+
+static struct clk_regmap s4_hevcf_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VDEC4_CLK_CTRL,
+ .mask = 0x1,
+ .shift = 15,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hevcf",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = s4_hevcf_mux_parent_hws,
+ .num_parents = ARRAY_SIZE(s4_hevcf_mux_parent_hws),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* VPU Clock */
+static const struct clk_parent_data s4_vpu_parent_data[] = {
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "fclk_div7", },
+ { .fw_name = "mpll1", },
+ { .hw = &s4_vid_pll.hw },
+ { .fw_name = "hifi_pll", },
+ { .fw_name = "gp0_pll", },
+};
+
+static struct clk_regmap s4_vpu_0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VPU_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_0_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_vpu_parent_data,
+ .num_parents = ARRAY_SIZE(s4_vpu_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_vpu_0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VPU_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vpu_0_sel.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vpu_0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VPU_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vpu_0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vpu_0_div.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vpu_1_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VPU_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_1_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_vpu_parent_data,
+ .num_parents = ARRAY_SIZE(s4_vpu_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_vpu_1_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VPU_CLK_CTRL,
+ .shift = 16,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_1_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vpu_1_sel.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vpu_1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VPU_CLK_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vpu_1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vpu_1_div.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vpu = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VPU_CLK_CTRL,
+ .mask = 1,
+ .shift = 31,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vpu_0.hw,
+ &s4_vpu_1.hw,
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data vpu_clkb_tmp_parent_data[] = {
+ { .hw = &s4_vpu.hw },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "fclk_div7", }
+};
+
+static struct clk_regmap s4_vpu_clkb_tmp_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VPU_CLKB_CTRL,
+ .mask = 0x3,
+ .shift = 20,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vpu_clkb_tmp_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = vpu_clkb_tmp_parent_data,
+ .num_parents = ARRAY_SIZE(vpu_clkb_tmp_parent_data),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vpu_clkb_tmp_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VPU_CLKB_CTRL,
+ .shift = 16,
+ .width = 4,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vpu_clkb_tmp_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vpu_clkb_tmp_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vpu_clkb_tmp = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VPU_CLKB_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_clkb_tmp",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vpu_clkb_tmp_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vpu_clkb_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VPU_CLKB_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vpu_clkb_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vpu_clkb_tmp.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vpu_clkb = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VPU_CLKB_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_clkb",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vpu_clkb_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data s4_vpu_clkc_parent_data[] = {
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "fclk_div7", },
+ { .fw_name = "mpll1", },
+ { .hw = &s4_vid_pll.hw },
+ { .fw_name = "mpll2", },
+ { .fw_name = "gp0_pll", },
+};
+
+static struct clk_regmap s4_vpu_clkc_p0_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VPU_CLKC_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vpu_clkc_p0_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_vpu_clkc_parent_data,
+ .num_parents = ARRAY_SIZE(s4_vpu_clkc_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_vpu_clkc_p0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VPU_CLKC_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vpu_clkc_p0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vpu_clkc_p0_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vpu_clkc_p0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VPU_CLKC_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_clkc_p0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vpu_clkc_p0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vpu_clkc_p1_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VPU_CLKC_CTRL,
+ .mask = 0x7,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vpu_clkc_p1_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_vpu_clkc_parent_data,
+ .num_parents = ARRAY_SIZE(s4_vpu_clkc_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_vpu_clkc_p1_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VPU_CLKC_CTRL,
+ .shift = 16,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vpu_clkc_p1_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vpu_clkc_p1_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vpu_clkc_p1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VPU_CLKC_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_clkc_p1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vpu_clkc_p1_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_hw *s4_vpu_mux_parent_hws[] = {
+ &s4_vpu_clkc_p0.hw,
+ &s4_vpu_clkc_p1.hw
+};
+
+static struct clk_regmap s4_vpu_clkc_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VPU_CLKC_CTRL,
+ .mask = 0x1,
+ .shift = 31,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vpu_clkc_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = s4_vpu_mux_parent_hws,
+ .num_parents = ARRAY_SIZE(s4_vpu_mux_parent_hws),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* VAPB Clock */
+static const struct clk_parent_data s4_vapb_parent_data[] = {
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "fclk_div7", },
+ { .fw_name = "mpll1", },
+ { .hw = &s4_vid_pll.hw },
+ { .fw_name = "mpll2", },
+ { .fw_name = "fclk_div2p5", },
+};
+
+static struct clk_regmap s4_vapb_0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VAPBCLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vapb_0_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_vapb_parent_data,
+ .num_parents = ARRAY_SIZE(s4_vapb_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_vapb_0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VAPBCLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vapb_0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vapb_0_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vapb_0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VAPBCLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vapb_0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vapb_0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vapb_1_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VAPBCLK_CTRL,
+ .mask = 0x7,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vapb_1_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_vapb_parent_data,
+ .num_parents = ARRAY_SIZE(s4_vapb_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_vapb_1_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VAPBCLK_CTRL,
+ .shift = 16,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vapb_1_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vapb_1_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vapb_1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VAPBCLK_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vapb_1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vapb_1_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vapb = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VAPBCLK_CTRL,
+ .mask = 1,
+ .shift = 31,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vapb_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vapb_0.hw,
+ &s4_vapb_1.hw
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_ge2d_gate = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VAPBCLK_CTRL,
+ .bit_idx = 30,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "ge2d_clk",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_vapb.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data s4_esmclk_parent_data[] = {
+ { .fw_name = "fclk_div7", },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div5", },
+};
+
+static struct clk_regmap s4_hdcp22_esmclk_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_HDCP22_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hdcp22_esmclk_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_esmclk_parent_data,
+ .num_parents = ARRAY_SIZE(s4_esmclk_parent_data),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hdcp22_esmclk_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_HDCP22_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hdcp22_esmclk_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_hdcp22_esmclk_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hdcp22_esmclk_gate = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_HDCP22_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdcp22_esmclk_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_hdcp22_esmclk_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data s4_skpclk_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div5", },
+};
+
+static struct clk_regmap s4_hdcp22_skpclk_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_HDCP22_CTRL,
+ .mask = 0x3,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hdcp22_skpclk_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_skpclk_parent_data,
+ .num_parents = ARRAY_SIZE(s4_skpclk_parent_data),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hdcp22_skpclk_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_HDCP22_CTRL,
+ .shift = 16,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hdcp22_skpclk_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_hdcp22_skpclk_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hdcp22_skpclk_gate = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_HDCP22_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdcp22_skpclk_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_hdcp22_skpclk_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data s4_vdin_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div5", },
+ { .hw = &s4_vid_pll.hw }
+};
+
+static struct clk_regmap s4_vdin_meas_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_VDIN_MEAS_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vdin_meas_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_vdin_parent_data,
+ .num_parents = ARRAY_SIZE(s4_vdin_parent_data),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vdin_meas_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_VDIN_MEAS_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vdin_meas_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vdin_meas_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_vdin_meas_gate = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_VDIN_MEAS_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vdin_meas_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_vdin_meas_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* EMMC/NAND clock */
+static const struct clk_parent_data s4_sd_emmc_clk0_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .fw_name = "fclk_div2", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "hifi_pll", },
+ { .fw_name = "fclk_div2p5", },
+ { .fw_name = "mpll2", },
+ { .fw_name = "mpll3", },
+ { .fw_name = "gp0_pll", },
+};
+
+static struct clk_regmap s4_sd_emmc_c_clk0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_NAND_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_c_clk0_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_sd_emmc_clk0_parent_data,
+ .num_parents = ARRAY_SIZE(s4_sd_emmc_clk0_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_sd_emmc_c_clk0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_NAND_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_c_clk0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sd_emmc_c_clk0_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_sd_emmc_c_clk0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_NAND_CLK_CTRL,
+ .bit_idx = 7,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sd_emmc_c_clk0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sd_emmc_c_clk0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_sd_emmc_a_clk0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_SD_EMMC_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_a_clk0_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_sd_emmc_clk0_parent_data,
+ .num_parents = ARRAY_SIZE(s4_sd_emmc_clk0_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_sd_emmc_a_clk0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_SD_EMMC_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_a_clk0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sd_emmc_a_clk0_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_sd_emmc_a_clk0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_SD_EMMC_CLK_CTRL,
+ .bit_idx = 7,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sd_emmc_a_clk0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sd_emmc_a_clk0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_sd_emmc_b_clk0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_SD_EMMC_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_b_clk0_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_sd_emmc_clk0_parent_data,
+ .num_parents = ARRAY_SIZE(s4_sd_emmc_clk0_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_sd_emmc_b_clk0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_SD_EMMC_CLK_CTRL,
+ .shift = 16,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_b_clk0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sd_emmc_b_clk0_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_sd_emmc_b_clk0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_SD_EMMC_CLK_CTRL,
+ .bit_idx = 23,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sd_emmc_b_clk0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_sd_emmc_b_clk0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* SPICC Clock */
+static const struct clk_parent_data s4_spicc_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &s4_sys_clk.hw },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div2", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "fclk_div7", },
+};
+
+static struct clk_regmap s4_spicc0_mux = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_SPICC_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spicc0_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_spicc_parent_data,
+ .num_parents = ARRAY_SIZE(s4_spicc_parent_data),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_spicc0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_SPICC_CLK_CTRL,
+ .shift = 0,
+ .width = 6,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spicc0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_spicc0_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_spicc0_gate = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_SPICC_CLK_CTRL,
+ .bit_idx = 6,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "spicc0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_spicc0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* PWM Clock */
+static const struct clk_parent_data s4_pwm_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &s4_vid_pll.hw },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div3", },
+};
+
+static struct clk_regmap s4_pwm_a_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_PWM_CLK_AB_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_a_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_pwm_parent_data,
+ .num_parents = ARRAY_SIZE(s4_pwm_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_pwm_a_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_PWM_CLK_AB_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_a_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_a_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_a_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_PWM_CLK_AB_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_a_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_a_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_b_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_PWM_CLK_AB_CTRL,
+ .mask = 0x3,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_b_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_pwm_parent_data,
+ .num_parents = ARRAY_SIZE(s4_pwm_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_pwm_b_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_PWM_CLK_AB_CTRL,
+ .shift = 16,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_b_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_b_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_b_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_PWM_CLK_AB_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_b_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_b_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_c_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_PWM_CLK_CD_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_c_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_pwm_parent_data,
+ .num_parents = ARRAY_SIZE(s4_pwm_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_pwm_c_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_PWM_CLK_CD_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_c_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_c_mux.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_pwm_c_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_PWM_CLK_CD_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_c_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_c_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_d_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_PWM_CLK_CD_CTRL,
+ .mask = 0x3,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_d_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_pwm_parent_data,
+ .num_parents = ARRAY_SIZE(s4_pwm_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_pwm_d_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_PWM_CLK_CD_CTRL,
+ .shift = 16,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_d_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_d_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_d_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_PWM_CLK_CD_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_d_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_d_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_e_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_PWM_CLK_EF_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_e_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_pwm_parent_data,
+ .num_parents = ARRAY_SIZE(s4_pwm_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_pwm_e_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_PWM_CLK_EF_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_e_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_e_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_e_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_PWM_CLK_EF_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_e_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_e_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_f_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_PWM_CLK_EF_CTRL,
+ .mask = 0x3,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_f_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_pwm_parent_data,
+ .num_parents = ARRAY_SIZE(s4_pwm_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_pwm_f_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_PWM_CLK_EF_CTRL,
+ .shift = 16,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_f_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_f_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_f_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_PWM_CLK_EF_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_f_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_f_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_g_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_PWM_CLK_GH_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_g_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_pwm_parent_data,
+ .num_parents = ARRAY_SIZE(s4_pwm_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_pwm_g_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_PWM_CLK_GH_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_g_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_g_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_g_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_PWM_CLK_GH_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_g_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_g_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_h_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_PWM_CLK_GH_CTRL,
+ .mask = 0x3,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_h_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_pwm_parent_data,
+ .num_parents = ARRAY_SIZE(s4_pwm_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_pwm_h_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_PWM_CLK_GH_CTRL,
+ .shift = 16,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_h_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_h_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_h_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_PWM_CLK_GH_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_h_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_h_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_i_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_PWM_CLK_IJ_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_i_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_pwm_parent_data,
+ .num_parents = ARRAY_SIZE(s4_pwm_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_pwm_i_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_PWM_CLK_IJ_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_i_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_i_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_i_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_PWM_CLK_IJ_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_i_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_i_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_j_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_PWM_CLK_IJ_CTRL,
+ .mask = 0x3,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_j_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_pwm_parent_data,
+ .num_parents = ARRAY_SIZE(s4_pwm_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_pwm_j_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_PWM_CLK_IJ_CTRL,
+ .shift = 16,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_j_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_h_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_pwm_j_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_PWM_CLK_IJ_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_j_gate",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_pwm_j_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_saradc_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_SAR_CLK_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "saradc_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", },
+ { .hw = &s4_sys_clk.hw },
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_saradc_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_SAR_CLK_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "saradc_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_saradc_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_saradc_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_SAR_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "saradc_clk",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_saradc_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/*
+ * gen clk is designed for debug/monitor some internal clock quality. Some of the
+ * corresponding clock sources are not described in the clock tree and internal clock
+ * for debug, so they are skipped.
+ */
+static u32 s4_gen_clk_mux_table[] = { 0, 4, 5, 7, 19, 21, 22,
+ 23, 24, 25, 26, 27, 28 };
+static const struct clk_parent_data s4_gen_clk_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &s4_vid_pll.hw },
+ { .fw_name = "gp0_pll", },
+ { .fw_name = "hifi_pll", },
+ { .fw_name = "fclk_div2", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "fclk_div7", },
+ { .fw_name = "mpll0", },
+ { .fw_name = "mpll1", },
+ { .fw_name = "mpll2", },
+ { .fw_name = "mpll3", },
+};
+
+static struct clk_regmap s4_gen_clk_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = CLKCTRL_GEN_CLK_CTRL,
+ .mask = 0x1f,
+ .shift = 12,
+ .table = s4_gen_clk_mux_table,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "gen_clk_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_gen_clk_parent_data,
+ .num_parents = ARRAY_SIZE(s4_gen_clk_parent_data),
+ /*
+ * Because the GEN clock can be connected to an external pad
+ * and may be set up directly from the device tree. Don't
+ * really want to automatically reparent.
+ */
+ .flags = CLK_SET_RATE_NO_REPARENT,
+ },
+};
+
+static struct clk_regmap s4_gen_clk_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLKCTRL_GEN_CLK_CTRL,
+ .shift = 0,
+ .width = 11,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "gen_clk_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_gen_clk_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_gen_clk = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLKCTRL_GEN_CLK_CTRL,
+ .bit_idx = 11,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "gen_clk",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_gen_clk_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data s4_adc_extclk_in_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .fw_name = "fclk_div4", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "fclk_div7", },
+ { .fw_name = "mpll2", },
+ { .fw_name = "gp0_pll", },
+ { .fw_name = "hifi_pll", },
+};
+
+static struct clk_regmap s4_adc_extclk_in_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_DEMOD_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "adc_extclk_in_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = s4_adc_extclk_in_parent_data,
+ .num_parents = ARRAY_SIZE(s4_adc_extclk_in_parent_data),
+ .flags = 0,
+ },
+};
+
+static struct clk_regmap s4_adc_extclk_in_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_DEMOD_CLK_CTRL,
+ .shift = 16,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "adc_extclk_in_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_adc_extclk_in_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_adc_extclk_in_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_DEMOD_CLK_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "adc_extclk_in",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_adc_extclk_in_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_demod_core_clk_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CLKCTRL_DEMOD_CLK_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "demod_core_clk_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", },
+ { .fw_name = "fclk_div7", },
+ { .fw_name = "fclk_div4", },
+ { .hw = &s4_adc_extclk_in_gate.hw }
+ },
+ .num_parents = 4,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_demod_core_clk_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLKCTRL_DEMOD_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "demod_core_clk_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_demod_core_clk_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_demod_core_clk_gate = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLKCTRL_DEMOD_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "demod_core_clk",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_demod_core_clk_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+#define MESON_GATE(_name, _reg, _bit) \
+ MESON_PCLK(_name, _reg, _bit, &s4_sys_clk.hw)
+
+static MESON_GATE(s4_ddr, CLKCTRL_SYS_CLK_EN0_REG0, 0);
+static MESON_GATE(s4_dos, CLKCTRL_SYS_CLK_EN0_REG0, 1);
+static MESON_GATE(s4_ethphy, CLKCTRL_SYS_CLK_EN0_REG0, 4);
+static MESON_GATE(s4_mali, CLKCTRL_SYS_CLK_EN0_REG0, 6);
+static MESON_GATE(s4_aocpu, CLKCTRL_SYS_CLK_EN0_REG0, 13);
+static MESON_GATE(s4_aucpu, CLKCTRL_SYS_CLK_EN0_REG0, 14);
+static MESON_GATE(s4_cec, CLKCTRL_SYS_CLK_EN0_REG0, 16);
+static MESON_GATE(s4_sdemmca, CLKCTRL_SYS_CLK_EN0_REG0, 24);
+static MESON_GATE(s4_sdemmcb, CLKCTRL_SYS_CLK_EN0_REG0, 25);
+static MESON_GATE(s4_nand, CLKCTRL_SYS_CLK_EN0_REG0, 26);
+static MESON_GATE(s4_smartcard, CLKCTRL_SYS_CLK_EN0_REG0, 27);
+static MESON_GATE(s4_acodec, CLKCTRL_SYS_CLK_EN0_REG0, 28);
+static MESON_GATE(s4_spifc, CLKCTRL_SYS_CLK_EN0_REG0, 29);
+static MESON_GATE(s4_msr_clk, CLKCTRL_SYS_CLK_EN0_REG0, 30);
+static MESON_GATE(s4_ir_ctrl, CLKCTRL_SYS_CLK_EN0_REG0, 31);
+static MESON_GATE(s4_audio, CLKCTRL_SYS_CLK_EN0_REG1, 0);
+static MESON_GATE(s4_eth, CLKCTRL_SYS_CLK_EN0_REG1, 3);
+static MESON_GATE(s4_uart_a, CLKCTRL_SYS_CLK_EN0_REG1, 5);
+static MESON_GATE(s4_uart_b, CLKCTRL_SYS_CLK_EN0_REG1, 6);
+static MESON_GATE(s4_uart_c, CLKCTRL_SYS_CLK_EN0_REG1, 7);
+static MESON_GATE(s4_uart_d, CLKCTRL_SYS_CLK_EN0_REG1, 8);
+static MESON_GATE(s4_uart_e, CLKCTRL_SYS_CLK_EN0_REG1, 9);
+static MESON_GATE(s4_aififo, CLKCTRL_SYS_CLK_EN0_REG1, 11);
+static MESON_GATE(s4_ts_ddr, CLKCTRL_SYS_CLK_EN0_REG1, 15);
+static MESON_GATE(s4_ts_pll, CLKCTRL_SYS_CLK_EN0_REG1, 16);
+static MESON_GATE(s4_g2d, CLKCTRL_SYS_CLK_EN0_REG1, 20);
+static MESON_GATE(s4_spicc0, CLKCTRL_SYS_CLK_EN0_REG1, 21);
+static MESON_GATE(s4_usb, CLKCTRL_SYS_CLK_EN0_REG1, 26);
+static MESON_GATE(s4_i2c_m_a, CLKCTRL_SYS_CLK_EN0_REG1, 30);
+static MESON_GATE(s4_i2c_m_b, CLKCTRL_SYS_CLK_EN0_REG1, 31);
+static MESON_GATE(s4_i2c_m_c, CLKCTRL_SYS_CLK_EN0_REG2, 0);
+static MESON_GATE(s4_i2c_m_d, CLKCTRL_SYS_CLK_EN0_REG2, 1);
+static MESON_GATE(s4_i2c_m_e, CLKCTRL_SYS_CLK_EN0_REG2, 2);
+static MESON_GATE(s4_hdmitx_apb, CLKCTRL_SYS_CLK_EN0_REG2, 4);
+static MESON_GATE(s4_i2c_s_a, CLKCTRL_SYS_CLK_EN0_REG2, 5);
+static MESON_GATE(s4_usb1_to_ddr, CLKCTRL_SYS_CLK_EN0_REG2, 8);
+static MESON_GATE(s4_hdcp22, CLKCTRL_SYS_CLK_EN0_REG2, 10);
+static MESON_GATE(s4_mmc_apb, CLKCTRL_SYS_CLK_EN0_REG2, 11);
+static MESON_GATE(s4_rsa, CLKCTRL_SYS_CLK_EN0_REG2, 18);
+static MESON_GATE(s4_cpu_debug, CLKCTRL_SYS_CLK_EN0_REG2, 19);
+static MESON_GATE(s4_vpu_intr, CLKCTRL_SYS_CLK_EN0_REG2, 25);
+static MESON_GATE(s4_demod, CLKCTRL_SYS_CLK_EN0_REG2, 27);
+static MESON_GATE(s4_sar_adc, CLKCTRL_SYS_CLK_EN0_REG2, 28);
+static MESON_GATE(s4_gic, CLKCTRL_SYS_CLK_EN0_REG2, 30);
+static MESON_GATE(s4_pwm_ab, CLKCTRL_SYS_CLK_EN0_REG3, 7);
+static MESON_GATE(s4_pwm_cd, CLKCTRL_SYS_CLK_EN0_REG3, 8);
+static MESON_GATE(s4_pwm_ef, CLKCTRL_SYS_CLK_EN0_REG3, 9);
+static MESON_GATE(s4_pwm_gh, CLKCTRL_SYS_CLK_EN0_REG3, 10);
+static MESON_GATE(s4_pwm_ij, CLKCTRL_SYS_CLK_EN0_REG3, 11);
+
+/* Array of all clocks provided by this provider */
+static struct clk_hw *s4_periphs_hw_clks[] = {
+ [CLKID_RTC_32K_CLKIN] = &s4_rtc_32k_by_oscin_clkin.hw,
+ [CLKID_RTC_32K_DIV] = &s4_rtc_32k_by_oscin_div.hw,
+ [CLKID_RTC_32K_SEL] = &s4_rtc_32k_by_oscin_sel.hw,
+ [CLKID_RTC_32K_XATL] = &s4_rtc_32k_by_oscin.hw,
+ [CLKID_RTC] = &s4_rtc_clk.hw,
+ [CLKID_SYS_CLK_B_SEL] = &s4_sysclk_b_sel.hw,
+ [CLKID_SYS_CLK_B_DIV] = &s4_sysclk_b_div.hw,
+ [CLKID_SYS_CLK_B] = &s4_sysclk_b.hw,
+ [CLKID_SYS_CLK_A_SEL] = &s4_sysclk_a_sel.hw,
+ [CLKID_SYS_CLK_A_DIV] = &s4_sysclk_a_div.hw,
+ [CLKID_SYS_CLK_A] = &s4_sysclk_a.hw,
+ [CLKID_SYS] = &s4_sys_clk.hw,
+ [CLKID_CECA_32K_CLKIN] = &s4_ceca_32k_clkin.hw,
+ [CLKID_CECA_32K_DIV] = &s4_ceca_32k_div.hw,
+ [CLKID_CECA_32K_SEL_PRE] = &s4_ceca_32k_sel_pre.hw,
+ [CLKID_CECA_32K_SEL] = &s4_ceca_32k_sel.hw,
+ [CLKID_CECA_32K_CLKOUT] = &s4_ceca_32k_clkout.hw,
+ [CLKID_CECB_32K_CLKIN] = &s4_cecb_32k_clkin.hw,
+ [CLKID_CECB_32K_DIV] = &s4_cecb_32k_div.hw,
+ [CLKID_CECB_32K_SEL_PRE] = &s4_cecb_32k_sel_pre.hw,
+ [CLKID_CECB_32K_SEL] = &s4_cecb_32k_sel.hw,
+ [CLKID_CECB_32K_CLKOUT] = &s4_cecb_32k_clkout.hw,
+ [CLKID_SC_CLK_SEL] = &s4_sc_clk_mux.hw,
+ [CLKID_SC_CLK_DIV] = &s4_sc_clk_div.hw,
+ [CLKID_SC] = &s4_sc_clk_gate.hw,
+ [CLKID_12_24M] = &s4_12_24M_clk_gate.hw,
+ [CLKID_12M_CLK_DIV] = &s4_12M_clk_div.hw,
+ [CLKID_12_24M_CLK_SEL] = &s4_12_24M_clk.hw,
+ [CLKID_VID_PLL_DIV] = &s4_vid_pll_div.hw,
+ [CLKID_VID_PLL_SEL] = &s4_vid_pll_sel.hw,
+ [CLKID_VID_PLL] = &s4_vid_pll.hw,
+ [CLKID_VCLK_SEL] = &s4_vclk_sel.hw,
+ [CLKID_VCLK2_SEL] = &s4_vclk2_sel.hw,
+ [CLKID_VCLK_INPUT] = &s4_vclk_input.hw,
+ [CLKID_VCLK2_INPUT] = &s4_vclk2_input.hw,
+ [CLKID_VCLK_DIV] = &s4_vclk_div.hw,
+ [CLKID_VCLK2_DIV] = &s4_vclk2_div.hw,
+ [CLKID_VCLK] = &s4_vclk.hw,
+ [CLKID_VCLK2] = &s4_vclk2.hw,
+ [CLKID_VCLK_DIV1] = &s4_vclk_div1.hw,
+ [CLKID_VCLK_DIV2_EN] = &s4_vclk_div2_en.hw,
+ [CLKID_VCLK_DIV4_EN] = &s4_vclk_div4_en.hw,
+ [CLKID_VCLK_DIV6_EN] = &s4_vclk_div6_en.hw,
+ [CLKID_VCLK_DIV12_EN] = &s4_vclk_div12_en.hw,
+ [CLKID_VCLK2_DIV1] = &s4_vclk2_div1.hw,
+ [CLKID_VCLK2_DIV2_EN] = &s4_vclk2_div2_en.hw,
+ [CLKID_VCLK2_DIV4_EN] = &s4_vclk2_div4_en.hw,
+ [CLKID_VCLK2_DIV6_EN] = &s4_vclk2_div6_en.hw,
+ [CLKID_VCLK2_DIV12_EN] = &s4_vclk2_div12_en.hw,
+ [CLKID_VCLK_DIV2] = &s4_vclk_div2.hw,
+ [CLKID_VCLK_DIV4] = &s4_vclk_div4.hw,
+ [CLKID_VCLK_DIV6] = &s4_vclk_div6.hw,
+ [CLKID_VCLK_DIV12] = &s4_vclk_div12.hw,
+ [CLKID_VCLK2_DIV2] = &s4_vclk2_div2.hw,
+ [CLKID_VCLK2_DIV4] = &s4_vclk2_div4.hw,
+ [CLKID_VCLK2_DIV6] = &s4_vclk2_div6.hw,
+ [CLKID_VCLK2_DIV12] = &s4_vclk2_div12.hw,
+ [CLKID_CTS_ENCI_SEL] = &s4_cts_enci_sel.hw,
+ [CLKID_CTS_ENCP_SEL] = &s4_cts_encp_sel.hw,
+ [CLKID_CTS_VDAC_SEL] = &s4_cts_vdac_sel.hw,
+ [CLKID_HDMI_TX_SEL] = &s4_hdmi_tx_sel.hw,
+ [CLKID_CTS_ENCI] = &s4_cts_enci.hw,
+ [CLKID_CTS_ENCP] = &s4_cts_encp.hw,
+ [CLKID_CTS_VDAC] = &s4_cts_vdac.hw,
+ [CLKID_HDMI_TX] = &s4_hdmi_tx.hw,
+ [CLKID_HDMI_SEL] = &s4_hdmi_sel.hw,
+ [CLKID_HDMI_DIV] = &s4_hdmi_div.hw,
+ [CLKID_HDMI] = &s4_hdmi.hw,
+ [CLKID_TS_CLK_DIV] = &s4_ts_clk_div.hw,
+ [CLKID_TS] = &s4_ts_clk_gate.hw,
+ [CLKID_MALI_0_SEL] = &s4_mali_0_sel.hw,
+ [CLKID_MALI_0_DIV] = &s4_mali_0_div.hw,
+ [CLKID_MALI_0] = &s4_mali_0.hw,
+ [CLKID_MALI_1_SEL] = &s4_mali_1_sel.hw,
+ [CLKID_MALI_1_DIV] = &s4_mali_1_div.hw,
+ [CLKID_MALI_1] = &s4_mali_1.hw,
+ [CLKID_MALI_SEL] = &s4_mali_mux.hw,
+ [CLKID_VDEC_P0_SEL] = &s4_vdec_p0_mux.hw,
+ [CLKID_VDEC_P0_DIV] = &s4_vdec_p0_div.hw,
+ [CLKID_VDEC_P0] = &s4_vdec_p0.hw,
+ [CLKID_VDEC_P1_SEL] = &s4_vdec_p1_mux.hw,
+ [CLKID_VDEC_P1_DIV] = &s4_vdec_p1_div.hw,
+ [CLKID_VDEC_P1] = &s4_vdec_p1.hw,
+ [CLKID_VDEC_SEL] = &s4_vdec_mux.hw,
+ [CLKID_HEVCF_P0_SEL] = &s4_hevcf_p0_mux.hw,
+ [CLKID_HEVCF_P0_DIV] = &s4_hevcf_p0_div.hw,
+ [CLKID_HEVCF_P0] = &s4_hevcf_p0.hw,
+ [CLKID_HEVCF_P1_SEL] = &s4_hevcf_p1_mux.hw,
+ [CLKID_HEVCF_P1_DIV] = &s4_hevcf_p1_div.hw,
+ [CLKID_HEVCF_P1] = &s4_hevcf_p1.hw,
+ [CLKID_HEVCF_SEL] = &s4_hevcf_mux.hw,
+ [CLKID_VPU_0_SEL] = &s4_vpu_0_sel.hw,
+ [CLKID_VPU_0_DIV] = &s4_vpu_0_div.hw,
+ [CLKID_VPU_0] = &s4_vpu_0.hw,
+ [CLKID_VPU_1_SEL] = &s4_vpu_1_sel.hw,
+ [CLKID_VPU_1_DIV] = &s4_vpu_1_div.hw,
+ [CLKID_VPU_1] = &s4_vpu_1.hw,
+ [CLKID_VPU] = &s4_vpu.hw,
+ [CLKID_VPU_CLKB_TMP_SEL] = &s4_vpu_clkb_tmp_mux.hw,
+ [CLKID_VPU_CLKB_TMP_DIV] = &s4_vpu_clkb_tmp_div.hw,
+ [CLKID_VPU_CLKB_TMP] = &s4_vpu_clkb_tmp.hw,
+ [CLKID_VPU_CLKB_DIV] = &s4_vpu_clkb_div.hw,
+ [CLKID_VPU_CLKB] = &s4_vpu_clkb.hw,
+ [CLKID_VPU_CLKC_P0_SEL] = &s4_vpu_clkc_p0_mux.hw,
+ [CLKID_VPU_CLKC_P0_DIV] = &s4_vpu_clkc_p0_div.hw,
+ [CLKID_VPU_CLKC_P0] = &s4_vpu_clkc_p0.hw,
+ [CLKID_VPU_CLKC_P1_SEL] = &s4_vpu_clkc_p1_mux.hw,
+ [CLKID_VPU_CLKC_P1_DIV] = &s4_vpu_clkc_p1_div.hw,
+ [CLKID_VPU_CLKC_P1] = &s4_vpu_clkc_p1.hw,
+ [CLKID_VPU_CLKC_SEL] = &s4_vpu_clkc_mux.hw,
+ [CLKID_VAPB_0_SEL] = &s4_vapb_0_sel.hw,
+ [CLKID_VAPB_0_DIV] = &s4_vapb_0_div.hw,
+ [CLKID_VAPB_0] = &s4_vapb_0.hw,
+ [CLKID_VAPB_1_SEL] = &s4_vapb_1_sel.hw,
+ [CLKID_VAPB_1_DIV] = &s4_vapb_1_div.hw,
+ [CLKID_VAPB_1] = &s4_vapb_1.hw,
+ [CLKID_VAPB] = &s4_vapb.hw,
+ [CLKID_GE2D] = &s4_ge2d_gate.hw,
+ [CLKID_VDIN_MEAS_SEL] = &s4_vdin_meas_mux.hw,
+ [CLKID_VDIN_MEAS_DIV] = &s4_vdin_meas_div.hw,
+ [CLKID_VDIN_MEAS] = &s4_vdin_meas_gate.hw,
+ [CLKID_SD_EMMC_C_CLK_SEL] = &s4_sd_emmc_c_clk0_sel.hw,
+ [CLKID_SD_EMMC_C_CLK_DIV] = &s4_sd_emmc_c_clk0_div.hw,
+ [CLKID_SD_EMMC_C] = &s4_sd_emmc_c_clk0.hw,
+ [CLKID_SD_EMMC_A_CLK_SEL] = &s4_sd_emmc_a_clk0_sel.hw,
+ [CLKID_SD_EMMC_A_CLK_DIV] = &s4_sd_emmc_a_clk0_div.hw,
+ [CLKID_SD_EMMC_A] = &s4_sd_emmc_a_clk0.hw,
+ [CLKID_SD_EMMC_B_CLK_SEL] = &s4_sd_emmc_b_clk0_sel.hw,
+ [CLKID_SD_EMMC_B_CLK_DIV] = &s4_sd_emmc_b_clk0_div.hw,
+ [CLKID_SD_EMMC_B] = &s4_sd_emmc_b_clk0.hw,
+ [CLKID_SPICC0_SEL] = &s4_spicc0_mux.hw,
+ [CLKID_SPICC0_DIV] = &s4_spicc0_div.hw,
+ [CLKID_SPICC0_EN] = &s4_spicc0_gate.hw,
+ [CLKID_PWM_A_SEL] = &s4_pwm_a_mux.hw,
+ [CLKID_PWM_A_DIV] = &s4_pwm_a_div.hw,
+ [CLKID_PWM_A] = &s4_pwm_a_gate.hw,
+ [CLKID_PWM_B_SEL] = &s4_pwm_b_mux.hw,
+ [CLKID_PWM_B_DIV] = &s4_pwm_b_div.hw,
+ [CLKID_PWM_B] = &s4_pwm_b_gate.hw,
+ [CLKID_PWM_C_SEL] = &s4_pwm_c_mux.hw,
+ [CLKID_PWM_C_DIV] = &s4_pwm_c_div.hw,
+ [CLKID_PWM_C] = &s4_pwm_c_gate.hw,
+ [CLKID_PWM_D_SEL] = &s4_pwm_d_mux.hw,
+ [CLKID_PWM_D_DIV] = &s4_pwm_d_div.hw,
+ [CLKID_PWM_D] = &s4_pwm_d_gate.hw,
+ [CLKID_PWM_E_SEL] = &s4_pwm_e_mux.hw,
+ [CLKID_PWM_E_DIV] = &s4_pwm_e_div.hw,
+ [CLKID_PWM_E] = &s4_pwm_e_gate.hw,
+ [CLKID_PWM_F_SEL] = &s4_pwm_f_mux.hw,
+ [CLKID_PWM_F_DIV] = &s4_pwm_f_div.hw,
+ [CLKID_PWM_F] = &s4_pwm_f_gate.hw,
+ [CLKID_PWM_G_SEL] = &s4_pwm_g_mux.hw,
+ [CLKID_PWM_G_DIV] = &s4_pwm_g_div.hw,
+ [CLKID_PWM_G] = &s4_pwm_g_gate.hw,
+ [CLKID_PWM_H_SEL] = &s4_pwm_h_mux.hw,
+ [CLKID_PWM_H_DIV] = &s4_pwm_h_div.hw,
+ [CLKID_PWM_H] = &s4_pwm_h_gate.hw,
+ [CLKID_PWM_I_SEL] = &s4_pwm_i_mux.hw,
+ [CLKID_PWM_I_DIV] = &s4_pwm_i_div.hw,
+ [CLKID_PWM_I] = &s4_pwm_i_gate.hw,
+ [CLKID_PWM_J_SEL] = &s4_pwm_j_mux.hw,
+ [CLKID_PWM_J_DIV] = &s4_pwm_j_div.hw,
+ [CLKID_PWM_J] = &s4_pwm_j_gate.hw,
+ [CLKID_SARADC_SEL] = &s4_saradc_mux.hw,
+ [CLKID_SARADC_DIV] = &s4_saradc_div.hw,
+ [CLKID_SARADC] = &s4_saradc_gate.hw,
+ [CLKID_GEN_SEL] = &s4_gen_clk_sel.hw,
+ [CLKID_GEN_DIV] = &s4_gen_clk_div.hw,
+ [CLKID_GEN] = &s4_gen_clk.hw,
+ [CLKID_DDR] = &s4_ddr.hw,
+ [CLKID_DOS] = &s4_dos.hw,
+ [CLKID_ETHPHY] = &s4_ethphy.hw,
+ [CLKID_MALI] = &s4_mali.hw,
+ [CLKID_AOCPU] = &s4_aocpu.hw,
+ [CLKID_AUCPU] = &s4_aucpu.hw,
+ [CLKID_CEC] = &s4_cec.hw,
+ [CLKID_SDEMMC_A] = &s4_sdemmca.hw,
+ [CLKID_SDEMMC_B] = &s4_sdemmcb.hw,
+ [CLKID_NAND] = &s4_nand.hw,
+ [CLKID_SMARTCARD] = &s4_smartcard.hw,
+ [CLKID_ACODEC] = &s4_acodec.hw,
+ [CLKID_SPIFC] = &s4_spifc.hw,
+ [CLKID_MSR] = &s4_msr_clk.hw,
+ [CLKID_IR_CTRL] = &s4_ir_ctrl.hw,
+ [CLKID_AUDIO] = &s4_audio.hw,
+ [CLKID_ETH] = &s4_eth.hw,
+ [CLKID_UART_A] = &s4_uart_a.hw,
+ [CLKID_UART_B] = &s4_uart_b.hw,
+ [CLKID_UART_C] = &s4_uart_c.hw,
+ [CLKID_UART_D] = &s4_uart_d.hw,
+ [CLKID_UART_E] = &s4_uart_e.hw,
+ [CLKID_AIFIFO] = &s4_aififo.hw,
+ [CLKID_TS_DDR] = &s4_ts_ddr.hw,
+ [CLKID_TS_PLL] = &s4_ts_pll.hw,
+ [CLKID_G2D] = &s4_g2d.hw,
+ [CLKID_SPICC0] = &s4_spicc0.hw,
+ [CLKID_USB] = &s4_usb.hw,
+ [CLKID_I2C_M_A] = &s4_i2c_m_a.hw,
+ [CLKID_I2C_M_B] = &s4_i2c_m_b.hw,
+ [CLKID_I2C_M_C] = &s4_i2c_m_c.hw,
+ [CLKID_I2C_M_D] = &s4_i2c_m_d.hw,
+ [CLKID_I2C_M_E] = &s4_i2c_m_e.hw,
+ [CLKID_HDMITX_APB] = &s4_hdmitx_apb.hw,
+ [CLKID_I2C_S_A] = &s4_i2c_s_a.hw,
+ [CLKID_USB1_TO_DDR] = &s4_usb1_to_ddr.hw,
+ [CLKID_HDCP22] = &s4_hdcp22.hw,
+ [CLKID_MMC_APB] = &s4_mmc_apb.hw,
+ [CLKID_RSA] = &s4_rsa.hw,
+ [CLKID_CPU_DEBUG] = &s4_cpu_debug.hw,
+ [CLKID_VPU_INTR] = &s4_vpu_intr.hw,
+ [CLKID_DEMOD] = &s4_demod.hw,
+ [CLKID_SAR_ADC] = &s4_sar_adc.hw,
+ [CLKID_GIC] = &s4_gic.hw,
+ [CLKID_PWM_AB] = &s4_pwm_ab.hw,
+ [CLKID_PWM_CD] = &s4_pwm_cd.hw,
+ [CLKID_PWM_EF] = &s4_pwm_ef.hw,
+ [CLKID_PWM_GH] = &s4_pwm_gh.hw,
+ [CLKID_PWM_IJ] = &s4_pwm_ij.hw,
+ [CLKID_HDCP22_ESMCLK_SEL] = &s4_hdcp22_esmclk_mux.hw,
+ [CLKID_HDCP22_ESMCLK_DIV] = &s4_hdcp22_esmclk_div.hw,
+ [CLKID_HDCP22_ESMCLK] = &s4_hdcp22_esmclk_gate.hw,
+ [CLKID_HDCP22_SKPCLK_SEL] = &s4_hdcp22_skpclk_mux.hw,
+ [CLKID_HDCP22_SKPCLK_DIV] = &s4_hdcp22_skpclk_div.hw,
+ [CLKID_HDCP22_SKPCLK] = &s4_hdcp22_skpclk_gate.hw,
+};
+
+/* Convenience table to populate regmap in .probe */
+static struct clk_regmap *const s4_periphs_clk_regmaps[] = {
+ &s4_rtc_32k_by_oscin_clkin,
+ &s4_rtc_32k_by_oscin_div,
+ &s4_rtc_32k_by_oscin_sel,
+ &s4_rtc_32k_by_oscin,
+ &s4_rtc_clk,
+ &s4_sysclk_b_sel,
+ &s4_sysclk_b_div,
+ &s4_sysclk_b,
+ &s4_sysclk_a_sel,
+ &s4_sysclk_a_div,
+ &s4_sysclk_a,
+ &s4_sys_clk,
+ &s4_ceca_32k_clkin,
+ &s4_ceca_32k_div,
+ &s4_ceca_32k_sel_pre,
+ &s4_ceca_32k_sel,
+ &s4_ceca_32k_clkout,
+ &s4_cecb_32k_clkin,
+ &s4_cecb_32k_div,
+ &s4_cecb_32k_sel_pre,
+ &s4_cecb_32k_sel,
+ &s4_cecb_32k_clkout,
+ &s4_sc_clk_mux,
+ &s4_sc_clk_div,
+ &s4_sc_clk_gate,
+ &s4_12_24M_clk_gate,
+ &s4_12_24M_clk,
+ &s4_vid_pll_div,
+ &s4_vid_pll_sel,
+ &s4_vid_pll,
+ &s4_vclk_sel,
+ &s4_vclk2_sel,
+ &s4_vclk_input,
+ &s4_vclk2_input,
+ &s4_vclk_div,
+ &s4_vclk2_div,
+ &s4_vclk,
+ &s4_vclk2,
+ &s4_vclk_div1,
+ &s4_vclk_div2_en,
+ &s4_vclk_div4_en,
+ &s4_vclk_div6_en,
+ &s4_vclk_div12_en,
+ &s4_vclk2_div1,
+ &s4_vclk2_div2_en,
+ &s4_vclk2_div4_en,
+ &s4_vclk2_div6_en,
+ &s4_vclk2_div12_en,
+ &s4_cts_enci_sel,
+ &s4_cts_encp_sel,
+ &s4_cts_vdac_sel,
+ &s4_hdmi_tx_sel,
+ &s4_cts_enci,
+ &s4_cts_encp,
+ &s4_cts_vdac,
+ &s4_hdmi_tx,
+ &s4_hdmi_sel,
+ &s4_hdmi_div,
+ &s4_hdmi,
+ &s4_ts_clk_div,
+ &s4_ts_clk_gate,
+ &s4_mali_0_sel,
+ &s4_mali_0_div,
+ &s4_mali_0,
+ &s4_mali_1_sel,
+ &s4_mali_1_div,
+ &s4_mali_1,
+ &s4_mali_mux,
+ &s4_vdec_p0_mux,
+ &s4_vdec_p0_div,
+ &s4_vdec_p0,
+ &s4_vdec_p1_mux,
+ &s4_vdec_p1_div,
+ &s4_vdec_p1,
+ &s4_vdec_mux,
+ &s4_hevcf_p0_mux,
+ &s4_hevcf_p0_div,
+ &s4_hevcf_p0,
+ &s4_hevcf_p1_mux,
+ &s4_hevcf_p1_div,
+ &s4_hevcf_p1,
+ &s4_hevcf_mux,
+ &s4_vpu_0_sel,
+ &s4_vpu_0_div,
+ &s4_vpu_0,
+ &s4_vpu_1_sel,
+ &s4_vpu_1_div,
+ &s4_vpu_1,
+ &s4_vpu,
+ &s4_vpu_clkb_tmp_mux,
+ &s4_vpu_clkb_tmp_div,
+ &s4_vpu_clkb_tmp,
+ &s4_vpu_clkb_div,
+ &s4_vpu_clkb,
+ &s4_vpu_clkc_p0_mux,
+ &s4_vpu_clkc_p0_div,
+ &s4_vpu_clkc_p0,
+ &s4_vpu_clkc_p1_mux,
+ &s4_vpu_clkc_p1_div,
+ &s4_vpu_clkc_p1,
+ &s4_vpu_clkc_mux,
+ &s4_vapb_0_sel,
+ &s4_vapb_0_div,
+ &s4_vapb_0,
+ &s4_vapb_1_sel,
+ &s4_vapb_1_div,
+ &s4_vapb_1,
+ &s4_vapb,
+ &s4_ge2d_gate,
+ &s4_hdcp22_esmclk_mux,
+ &s4_hdcp22_esmclk_div,
+ &s4_hdcp22_esmclk_gate,
+ &s4_hdcp22_skpclk_mux,
+ &s4_hdcp22_skpclk_div,
+ &s4_hdcp22_skpclk_gate,
+ &s4_vdin_meas_mux,
+ &s4_vdin_meas_div,
+ &s4_vdin_meas_gate,
+ &s4_sd_emmc_c_clk0_sel,
+ &s4_sd_emmc_c_clk0_div,
+ &s4_sd_emmc_c_clk0,
+ &s4_sd_emmc_a_clk0_sel,
+ &s4_sd_emmc_a_clk0_div,
+ &s4_sd_emmc_a_clk0,
+ &s4_sd_emmc_b_clk0_sel,
+ &s4_sd_emmc_b_clk0_div,
+ &s4_sd_emmc_b_clk0,
+ &s4_spicc0_mux,
+ &s4_spicc0_div,
+ &s4_spicc0_gate,
+ &s4_pwm_a_mux,
+ &s4_pwm_a_div,
+ &s4_pwm_a_gate,
+ &s4_pwm_b_mux,
+ &s4_pwm_b_div,
+ &s4_pwm_b_gate,
+ &s4_pwm_c_mux,
+ &s4_pwm_c_div,
+ &s4_pwm_c_gate,
+ &s4_pwm_d_mux,
+ &s4_pwm_d_div,
+ &s4_pwm_d_gate,
+ &s4_pwm_e_mux,
+ &s4_pwm_e_div,
+ &s4_pwm_e_gate,
+ &s4_pwm_f_mux,
+ &s4_pwm_f_div,
+ &s4_pwm_f_gate,
+ &s4_pwm_g_mux,
+ &s4_pwm_g_div,
+ &s4_pwm_g_gate,
+ &s4_pwm_h_mux,
+ &s4_pwm_h_div,
+ &s4_pwm_h_gate,
+ &s4_pwm_i_mux,
+ &s4_pwm_i_div,
+ &s4_pwm_i_gate,
+ &s4_pwm_j_mux,
+ &s4_pwm_j_div,
+ &s4_pwm_j_gate,
+ &s4_saradc_mux,
+ &s4_saradc_div,
+ &s4_saradc_gate,
+ &s4_gen_clk_sel,
+ &s4_gen_clk_div,
+ &s4_gen_clk,
+ &s4_ddr,
+ &s4_dos,
+ &s4_ethphy,
+ &s4_mali,
+ &s4_aocpu,
+ &s4_aucpu,
+ &s4_cec,
+ &s4_sdemmca,
+ &s4_sdemmcb,
+ &s4_nand,
+ &s4_smartcard,
+ &s4_acodec,
+ &s4_spifc,
+ &s4_msr_clk,
+ &s4_ir_ctrl,
+ &s4_audio,
+ &s4_eth,
+ &s4_uart_a,
+ &s4_uart_b,
+ &s4_uart_c,
+ &s4_uart_d,
+ &s4_uart_e,
+ &s4_aififo,
+ &s4_ts_ddr,
+ &s4_ts_pll,
+ &s4_g2d,
+ &s4_spicc0,
+ &s4_usb,
+ &s4_i2c_m_a,
+ &s4_i2c_m_b,
+ &s4_i2c_m_c,
+ &s4_i2c_m_d,
+ &s4_i2c_m_e,
+ &s4_hdmitx_apb,
+ &s4_i2c_s_a,
+ &s4_usb1_to_ddr,
+ &s4_hdcp22,
+ &s4_mmc_apb,
+ &s4_rsa,
+ &s4_cpu_debug,
+ &s4_vpu_intr,
+ &s4_demod,
+ &s4_sar_adc,
+ &s4_gic,
+ &s4_pwm_ab,
+ &s4_pwm_cd,
+ &s4_pwm_ef,
+ &s4_pwm_gh,
+ &s4_pwm_ij,
+ &s4_demod_core_clk_mux,
+ &s4_demod_core_clk_div,
+ &s4_demod_core_clk_gate,
+ &s4_adc_extclk_in_mux,
+ &s4_adc_extclk_in_div,
+ &s4_adc_extclk_in_gate,
+};
+
+static struct regmap_config clkc_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static struct meson_clk_hw_data s4_periphs_clks = {
+ .hws = s4_periphs_hw_clks,
+ .num = ARRAY_SIZE(s4_periphs_hw_clks),
+};
+
+static int meson_s4_periphs_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap;
+ void __iomem *base;
+ int ret, i;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return dev_err_probe(dev, PTR_ERR(base),
+ "can't ioremap resource\n");
+
+ regmap = devm_regmap_init_mmio(dev, base, &clkc_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "can't init regmap mmio region\n");
+
+ /* Populate regmap for the regmap backed clocks */
+ for (i = 0; i < ARRAY_SIZE(s4_periphs_clk_regmaps); i++)
+ s4_periphs_clk_regmaps[i]->map = regmap;
+
+ for (i = 0; i < s4_periphs_clks.num; i++) {
+ /* array might be sparse */
+ if (!s4_periphs_clks.hws[i])
+ continue;
+
+ ret = devm_clk_hw_register(dev, s4_periphs_clks.hws[i]);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "clock[%d] registration failed\n", i);
+ }
+
+ return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get, &s4_periphs_clks);
+}
+
+static const struct of_device_id clkc_match_table[] = {
+ {
+ .compatible = "amlogic,s4-peripherals-clkc",
+ },
+ {}
+};
+
+static struct platform_driver s4_driver = {
+ .probe = meson_s4_periphs_probe,
+ .driver = {
+ .name = "s4-periphs-clkc",
+ .of_match_table = clkc_match_table,
+ },
+};
+
+module_platform_driver(s4_driver);
+MODULE_AUTHOR("Yu Tu <yu.tu@amlogic.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/meson/s4-peripherals.h b/drivers/clk/meson/s4-peripherals.h
new file mode 100644
index 000000000000..1e298713c2b2
--- /dev/null
+++ b/drivers/clk/meson/s4-peripherals.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2022-2023 Amlogic, inc. All rights reserved
+ * Author: Yu Tu <yu.tu@amlogic.com>
+ */
+
+#ifndef __MESON_S4_PERIPHERALS_H__
+#define __MESON_S4_PERIPHERALS_H__
+
+#define CLKCTRL_RTC_BY_OSCIN_CTRL0 0x008
+#define CLKCTRL_RTC_BY_OSCIN_CTRL1 0x00c
+#define CLKCTRL_RTC_CTRL 0x010
+#define CLKCTRL_SYS_CLK_CTRL0 0x040
+#define CLKCTRL_SYS_CLK_EN0_REG0 0x044
+#define CLKCTRL_SYS_CLK_EN0_REG1 0x048
+#define CLKCTRL_SYS_CLK_EN0_REG2 0x04c
+#define CLKCTRL_SYS_CLK_EN0_REG3 0x050
+#define CLKCTRL_CECA_CTRL0 0x088
+#define CLKCTRL_CECA_CTRL1 0x08c
+#define CLKCTRL_CECB_CTRL0 0x090
+#define CLKCTRL_CECB_CTRL1 0x094
+#define CLKCTRL_SC_CLK_CTRL 0x098
+#define CLKCTRL_CLK12_24_CTRL 0x0a8
+#define CLKCTRL_VID_CLK_CTRL 0x0c0
+#define CLKCTRL_VID_CLK_CTRL2 0x0c4
+#define CLKCTRL_VID_CLK_DIV 0x0c8
+#define CLKCTRL_VIID_CLK_DIV 0x0cc
+#define CLKCTRL_VIID_CLK_CTRL 0x0d0
+#define CLKCTRL_HDMI_CLK_CTRL 0x0e0
+#define CLKCTRL_VID_PLL_CLK_DIV 0x0e4
+#define CLKCTRL_VPU_CLK_CTRL 0x0e8
+#define CLKCTRL_VPU_CLKB_CTRL 0x0ec
+#define CLKCTRL_VPU_CLKC_CTRL 0x0f0
+#define CLKCTRL_VID_LOCK_CLK_CTRL 0x0f4
+#define CLKCTRL_VDIN_MEAS_CLK_CTRL 0x0f8
+#define CLKCTRL_VAPBCLK_CTRL 0x0fc
+#define CLKCTRL_HDCP22_CTRL 0x100
+#define CLKCTRL_VDEC_CLK_CTRL 0x140
+#define CLKCTRL_VDEC2_CLK_CTRL 0x144
+#define CLKCTRL_VDEC3_CLK_CTRL 0x148
+#define CLKCTRL_VDEC4_CLK_CTRL 0x14c
+#define CLKCTRL_TS_CLK_CTRL 0x158
+#define CLKCTRL_MALI_CLK_CTRL 0x15c
+#define CLKCTRL_NAND_CLK_CTRL 0x168
+#define CLKCTRL_SD_EMMC_CLK_CTRL 0x16c
+#define CLKCTRL_SPICC_CLK_CTRL 0x174
+#define CLKCTRL_GEN_CLK_CTRL 0x178
+#define CLKCTRL_SAR_CLK_CTRL 0x17c
+#define CLKCTRL_PWM_CLK_AB_CTRL 0x180
+#define CLKCTRL_PWM_CLK_CD_CTRL 0x184
+#define CLKCTRL_PWM_CLK_EF_CTRL 0x188
+#define CLKCTRL_PWM_CLK_GH_CTRL 0x18c
+#define CLKCTRL_PWM_CLK_IJ_CTRL 0x190
+#define CLKCTRL_DEMOD_CLK_CTRL 0x200
+
+#endif /* __MESON_S4_PERIPHERALS_H__ */
diff --git a/drivers/clk/meson/s4-pll.c b/drivers/clk/meson/s4-pll.c
new file mode 100644
index 000000000000..8dfaeccaadc2
--- /dev/null
+++ b/drivers/clk/meson/s4-pll.c
@@ -0,0 +1,867 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Amlogic S4 PLL Clock Controller Driver
+ *
+ * Copyright (c) 2022-2023 Amlogic, inc. All rights reserved
+ * Author: Yu Tu <yu.tu@amlogic.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mpll.h"
+#include "clk-pll.h"
+#include "clk-regmap.h"
+#include "s4-pll.h"
+#include "meson-clkc-utils.h"
+#include <dt-bindings/clock/amlogic,s4-pll-clkc.h>
+
+static DEFINE_SPINLOCK(meson_clk_lock);
+
+/*
+ * These clock are a fixed value (fixed_pll is 2GHz) that is initialized by ROMcode.
+ * The chip was changed fixed pll for security reasons. Fixed PLL registers are not writable
+ * in the kernel phase. Write of fixed PLL-related register will cause the system to crash.
+ * Meanwhile, these clock won't ever change at runtime.
+ * For the above reasons, we can only use ro_ops for fixed PLL related clocks.
+ */
+static struct clk_regmap s4_fixed_pll_dco = {
+ .data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 0,
+ .width = 8,
+ },
+ .n = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 10,
+ .width = 5,
+ },
+ .l = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 29,
+ .width = 1,
+ },
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fixed_pll_dco",
+ .ops = &meson_clk_pll_ro_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", }
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_fixed_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = ANACTRL_FIXPLL_CTRL0,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fixed_pll",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_fixed_pll_dco.hw
+ },
+ .num_parents = 1,
+ /*
+ * This clock won't ever change at runtime so
+ * CLK_SET_RATE_PARENT is not required
+ */
+ },
+};
+
+static struct clk_fixed_factor s4_fclk_div2_div = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_fclk_div2 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_FIXPLL_CTRL1,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_fclk_div2_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor s4_fclk_div3_div = {
+ .mult = 1,
+ .div = 3,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div3_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_fclk_div3 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_FIXPLL_CTRL1,
+ .bit_idx = 20,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div3",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_fclk_div3_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor s4_fclk_div4_div = {
+ .mult = 1,
+ .div = 4,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div4_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_fclk_div4 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_FIXPLL_CTRL1,
+ .bit_idx = 21,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div4",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_fclk_div4_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor s4_fclk_div5_div = {
+ .mult = 1,
+ .div = 5,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div5_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_fclk_div5 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_FIXPLL_CTRL1,
+ .bit_idx = 22,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div5",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_fclk_div5_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor s4_fclk_div7_div = {
+ .mult = 1,
+ .div = 7,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div7_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_fclk_div7 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_FIXPLL_CTRL1,
+ .bit_idx = 23,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div7",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_fclk_div7_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor s4_fclk_div2p5_div = {
+ .mult = 2,
+ .div = 5,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2p5_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_fixed_pll.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_fclk_div2p5 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_FIXPLL_CTRL1,
+ .bit_idx = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2p5",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_fclk_div2p5_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static const struct pll_mult_range s4_gp0_pll_mult_range = {
+ .min = 125,
+ .max = 250,
+};
+
+/*
+ * Internal gp0 pll emulation configuration parameters
+ */
+static const struct reg_sequence s4_gp0_init_regs[] = {
+ { .reg = ANACTRL_GP0PLL_CTRL1, .def = 0x00000000 },
+ { .reg = ANACTRL_GP0PLL_CTRL2, .def = 0x00000000 },
+ { .reg = ANACTRL_GP0PLL_CTRL3, .def = 0x48681c00 },
+ { .reg = ANACTRL_GP0PLL_CTRL4, .def = 0x88770290 },
+ { .reg = ANACTRL_GP0PLL_CTRL5, .def = 0x39272000 },
+ { .reg = ANACTRL_GP0PLL_CTRL6, .def = 0x56540000 }
+};
+
+static struct clk_regmap s4_gp0_pll_dco = {
+ .data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = ANACTRL_GP0PLL_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = ANACTRL_GP0PLL_CTRL0,
+ .shift = 0,
+ .width = 8,
+ },
+ .n = {
+ .reg_off = ANACTRL_GP0PLL_CTRL0,
+ .shift = 10,
+ .width = 5,
+ },
+ .l = {
+ .reg_off = ANACTRL_GP0PLL_CTRL0,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = ANACTRL_GP0PLL_CTRL0,
+ .shift = 29,
+ .width = 1,
+ },
+ .range = &s4_gp0_pll_mult_range,
+ .init_regs = s4_gp0_init_regs,
+ .init_count = ARRAY_SIZE(s4_gp0_init_regs),
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "gp0_pll_dco",
+ .ops = &meson_clk_pll_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", }
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_gp0_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = ANACTRL_GP0PLL_CTRL0,
+ .shift = 16,
+ .width = 3,
+ .flags = (CLK_DIVIDER_POWER_OF_TWO |
+ CLK_DIVIDER_ROUND_CLOSEST),
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "gp0_pll",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_gp0_pll_dco.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/*
+ * Internal hifi pll emulation configuration parameters
+ */
+static const struct reg_sequence s4_hifi_init_regs[] = {
+ { .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x00010e56 },
+ { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00000000 },
+ { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x6a285c00 },
+ { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 },
+ { .reg = ANACTRL_HIFIPLL_CTRL5, .def = 0x39272000 },
+ { .reg = ANACTRL_HIFIPLL_CTRL6, .def = 0x56540000 }
+};
+
+static struct clk_regmap s4_hifi_pll_dco = {
+ .data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 0,
+ .width = 8,
+ },
+ .n = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 10,
+ .width = 5,
+ },
+ .l = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 29,
+ .width = 1,
+ },
+ .range = &s4_gp0_pll_mult_range,
+ .init_regs = s4_hifi_init_regs,
+ .init_count = ARRAY_SIZE(s4_hifi_init_regs),
+ .flags = CLK_MESON_PLL_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hifi_pll_dco",
+ .ops = &meson_clk_pll_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", }
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_hifi_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 16,
+ .width = 2,
+ .flags = (CLK_DIVIDER_POWER_OF_TWO |
+ CLK_DIVIDER_ROUND_CLOSEST),
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hifi_pll",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_hifi_pll_dco.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hdmi_pll_dco = {
+ .data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = ANACTRL_HDMIPLL_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = ANACTRL_HDMIPLL_CTRL0,
+ .shift = 0,
+ .width = 8,
+ },
+ .n = {
+ .reg_off = ANACTRL_HDMIPLL_CTRL0,
+ .shift = 10,
+ .width = 5,
+ },
+ .l = {
+ .reg_off = ANACTRL_HDMIPLL_CTRL0,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = ANACTRL_HDMIPLL_CTRL0,
+ .shift = 29,
+ .width = 1,
+ },
+ .range = &s4_gp0_pll_mult_range,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_pll_dco",
+ .ops = &meson_clk_pll_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", }
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_hdmi_pll_od = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = ANACTRL_HDMIPLL_CTRL0,
+ .shift = 16,
+ .width = 4,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_pll_od",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_hdmi_pll_dco.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap s4_hdmi_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = ANACTRL_HDMIPLL_CTRL0,
+ .shift = 20,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_pll",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_hdmi_pll_od.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_fixed_factor s4_mpll_50m_div = {
+ .mult = 1,
+ .div = 80,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll_50m_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_fixed_pll_dco.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_mpll_50m = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = ANACTRL_FIXPLL_CTRL3,
+ .mask = 0x1,
+ .shift = 5,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll_50m",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", },
+ { .hw = &s4_mpll_50m_div.hw },
+ },
+ .num_parents = 2,
+ },
+};
+
+static struct clk_fixed_factor s4_mpll_prediv = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll_prediv",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_fixed_pll_dco.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static const struct reg_sequence s4_mpll0_init_regs[] = {
+ { .reg = ANACTRL_MPLL_CTRL2, .def = 0x40000033 }
+};
+
+static struct clk_regmap s4_mpll0_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = ANACTRL_MPLL_CTRL1,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = ANACTRL_MPLL_CTRL1,
+ .shift = 30,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = ANACTRL_MPLL_CTRL1,
+ .shift = 20,
+ .width = 9,
+ },
+ .ssen = {
+ .reg_off = ANACTRL_MPLL_CTRL1,
+ .shift = 29,
+ .width = 1,
+ },
+ .lock = &meson_clk_lock,
+ .init_regs = s4_mpll0_init_regs,
+ .init_count = ARRAY_SIZE(s4_mpll0_init_regs),
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll0_div",
+ .ops = &meson_clk_mpll_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_mpll_prediv.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_mpll0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_MPLL_CTRL1,
+ .bit_idx = 31,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_mpll0_div.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct reg_sequence s4_mpll1_init_regs[] = {
+ { .reg = ANACTRL_MPLL_CTRL4, .def = 0x40000033 }
+};
+
+static struct clk_regmap s4_mpll1_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = ANACTRL_MPLL_CTRL3,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = ANACTRL_MPLL_CTRL3,
+ .shift = 30,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = ANACTRL_MPLL_CTRL3,
+ .shift = 20,
+ .width = 9,
+ },
+ .ssen = {
+ .reg_off = ANACTRL_MPLL_CTRL3,
+ .shift = 29,
+ .width = 1,
+ },
+ .lock = &meson_clk_lock,
+ .init_regs = s4_mpll1_init_regs,
+ .init_count = ARRAY_SIZE(s4_mpll1_init_regs),
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll1_div",
+ .ops = &meson_clk_mpll_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_mpll_prediv.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_mpll1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_MPLL_CTRL3,
+ .bit_idx = 31,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_mpll1_div.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct reg_sequence s4_mpll2_init_regs[] = {
+ { .reg = ANACTRL_MPLL_CTRL6, .def = 0x40000033 }
+};
+
+static struct clk_regmap s4_mpll2_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = ANACTRL_MPLL_CTRL5,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = ANACTRL_MPLL_CTRL5,
+ .shift = 30,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = ANACTRL_MPLL_CTRL5,
+ .shift = 20,
+ .width = 9,
+ },
+ .ssen = {
+ .reg_off = ANACTRL_MPLL_CTRL5,
+ .shift = 29,
+ .width = 1,
+ },
+ .lock = &meson_clk_lock,
+ .init_regs = s4_mpll2_init_regs,
+ .init_count = ARRAY_SIZE(s4_mpll2_init_regs),
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll2_div",
+ .ops = &meson_clk_mpll_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_mpll_prediv.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_mpll2 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_MPLL_CTRL5,
+ .bit_idx = 31,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll2",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_mpll2_div.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct reg_sequence s4_mpll3_init_regs[] = {
+ { .reg = ANACTRL_MPLL_CTRL8, .def = 0x40000033 }
+};
+
+static struct clk_regmap s4_mpll3_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = ANACTRL_MPLL_CTRL7,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = ANACTRL_MPLL_CTRL7,
+ .shift = 30,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = ANACTRL_MPLL_CTRL7,
+ .shift = 20,
+ .width = 9,
+ },
+ .ssen = {
+ .reg_off = ANACTRL_MPLL_CTRL7,
+ .shift = 29,
+ .width = 1,
+ },
+ .lock = &meson_clk_lock,
+ .init_regs = s4_mpll3_init_regs,
+ .init_count = ARRAY_SIZE(s4_mpll3_init_regs),
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll3_div",
+ .ops = &meson_clk_mpll_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &s4_mpll_prediv.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap s4_mpll3 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_MPLL_CTRL7,
+ .bit_idx = 31,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll3",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) { &s4_mpll3_div.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* Array of all clocks provided by this provider */
+static struct clk_hw *s4_pll_hw_clks[] = {
+ [CLKID_FIXED_PLL_DCO] = &s4_fixed_pll_dco.hw,
+ [CLKID_FIXED_PLL] = &s4_fixed_pll.hw,
+ [CLKID_FCLK_DIV2_DIV] = &s4_fclk_div2_div.hw,
+ [CLKID_FCLK_DIV2] = &s4_fclk_div2.hw,
+ [CLKID_FCLK_DIV3_DIV] = &s4_fclk_div3_div.hw,
+ [CLKID_FCLK_DIV3] = &s4_fclk_div3.hw,
+ [CLKID_FCLK_DIV4_DIV] = &s4_fclk_div4_div.hw,
+ [CLKID_FCLK_DIV4] = &s4_fclk_div4.hw,
+ [CLKID_FCLK_DIV5_DIV] = &s4_fclk_div5_div.hw,
+ [CLKID_FCLK_DIV5] = &s4_fclk_div5.hw,
+ [CLKID_FCLK_DIV7_DIV] = &s4_fclk_div7_div.hw,
+ [CLKID_FCLK_DIV7] = &s4_fclk_div7.hw,
+ [CLKID_FCLK_DIV2P5_DIV] = &s4_fclk_div2p5_div.hw,
+ [CLKID_FCLK_DIV2P5] = &s4_fclk_div2p5.hw,
+ [CLKID_GP0_PLL_DCO] = &s4_gp0_pll_dco.hw,
+ [CLKID_GP0_PLL] = &s4_gp0_pll.hw,
+ [CLKID_HIFI_PLL_DCO] = &s4_hifi_pll_dco.hw,
+ [CLKID_HIFI_PLL] = &s4_hifi_pll.hw,
+ [CLKID_HDMI_PLL_DCO] = &s4_hdmi_pll_dco.hw,
+ [CLKID_HDMI_PLL_OD] = &s4_hdmi_pll_od.hw,
+ [CLKID_HDMI_PLL] = &s4_hdmi_pll.hw,
+ [CLKID_MPLL_50M_DIV] = &s4_mpll_50m_div.hw,
+ [CLKID_MPLL_50M] = &s4_mpll_50m.hw,
+ [CLKID_MPLL_PREDIV] = &s4_mpll_prediv.hw,
+ [CLKID_MPLL0_DIV] = &s4_mpll0_div.hw,
+ [CLKID_MPLL0] = &s4_mpll0.hw,
+ [CLKID_MPLL1_DIV] = &s4_mpll1_div.hw,
+ [CLKID_MPLL1] = &s4_mpll1.hw,
+ [CLKID_MPLL2_DIV] = &s4_mpll2_div.hw,
+ [CLKID_MPLL2] = &s4_mpll2.hw,
+ [CLKID_MPLL3_DIV] = &s4_mpll3_div.hw,
+ [CLKID_MPLL3] = &s4_mpll3.hw,
+};
+
+static struct clk_regmap *const s4_pll_clk_regmaps[] = {
+ &s4_fixed_pll_dco,
+ &s4_fixed_pll,
+ &s4_fclk_div2,
+ &s4_fclk_div3,
+ &s4_fclk_div4,
+ &s4_fclk_div5,
+ &s4_fclk_div7,
+ &s4_fclk_div2p5,
+ &s4_gp0_pll_dco,
+ &s4_gp0_pll,
+ &s4_hifi_pll_dco,
+ &s4_hifi_pll,
+ &s4_hdmi_pll_dco,
+ &s4_hdmi_pll_od,
+ &s4_hdmi_pll,
+ &s4_mpll_50m,
+ &s4_mpll0_div,
+ &s4_mpll0,
+ &s4_mpll1_div,
+ &s4_mpll1,
+ &s4_mpll2_div,
+ &s4_mpll2,
+ &s4_mpll3_div,
+ &s4_mpll3,
+};
+
+static const struct reg_sequence s4_init_regs[] = {
+ { .reg = ANACTRL_MPLL_CTRL0, .def = 0x00000543 },
+};
+
+static struct regmap_config clkc_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static struct meson_clk_hw_data s4_pll_clks = {
+ .hws = s4_pll_hw_clks,
+ .num = ARRAY_SIZE(s4_pll_hw_clks),
+};
+
+static int meson_s4_pll_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap;
+ void __iomem *base;
+ int ret, i;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return dev_err_probe(dev, PTR_ERR(base),
+ "can't ioremap resource\n");
+
+ regmap = devm_regmap_init_mmio(dev, base, &clkc_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "can't init regmap mmio region\n");
+
+ ret = regmap_multi_reg_write(regmap, s4_init_regs, ARRAY_SIZE(s4_init_regs));
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to init registers\n");
+
+ /* Populate regmap for the regmap backed clocks */
+ for (i = 0; i < ARRAY_SIZE(s4_pll_clk_regmaps); i++)
+ s4_pll_clk_regmaps[i]->map = regmap;
+
+ /* Register clocks */
+ for (i = 0; i < s4_pll_clks.num; i++) {
+ /* array might be sparse */
+ if (!s4_pll_clks.hws[i])
+ continue;
+
+ ret = devm_clk_hw_register(dev, s4_pll_clks.hws[i]);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "clock[%d] registration failed\n", i);
+ }
+
+ return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get,
+ &s4_pll_clks);
+}
+
+static const struct of_device_id clkc_match_table[] = {
+ {
+ .compatible = "amlogic,s4-pll-clkc",
+ },
+ {}
+};
+
+static struct platform_driver s4_driver = {
+ .probe = meson_s4_pll_probe,
+ .driver = {
+ .name = "s4-pll-clkc",
+ .of_match_table = clkc_match_table,
+ },
+};
+
+module_platform_driver(s4_driver);
+MODULE_AUTHOR("Yu Tu <yu.tu@amlogic.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/meson/s4-pll.h b/drivers/clk/meson/s4-pll.h
new file mode 100644
index 000000000000..ff7d58302f2a
--- /dev/null
+++ b/drivers/clk/meson/s4-pll.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2022-2023 Amlogic, inc. All rights reserved
+ * Author: Yu Tu <yu.tu@amlogic.com>
+ */
+
+#ifndef __MESON_S4_PLL_H__
+#define __MESON_S4_PLL_H__
+
+#define ANACTRL_FIXPLL_CTRL0 0x040
+#define ANACTRL_FIXPLL_CTRL1 0x044
+#define ANACTRL_FIXPLL_CTRL3 0x04c
+#define ANACTRL_GP0PLL_CTRL0 0x080
+#define ANACTRL_GP0PLL_CTRL1 0x084
+#define ANACTRL_GP0PLL_CTRL2 0x088
+#define ANACTRL_GP0PLL_CTRL3 0x08c
+#define ANACTRL_GP0PLL_CTRL4 0x090
+#define ANACTRL_GP0PLL_CTRL5 0x094
+#define ANACTRL_GP0PLL_CTRL6 0x098
+#define ANACTRL_HIFIPLL_CTRL0 0x100
+#define ANACTRL_HIFIPLL_CTRL1 0x104
+#define ANACTRL_HIFIPLL_CTRL2 0x108
+#define ANACTRL_HIFIPLL_CTRL3 0x10c
+#define ANACTRL_HIFIPLL_CTRL4 0x110
+#define ANACTRL_HIFIPLL_CTRL5 0x114
+#define ANACTRL_HIFIPLL_CTRL6 0x118
+#define ANACTRL_MPLL_CTRL0 0x180
+#define ANACTRL_MPLL_CTRL1 0x184
+#define ANACTRL_MPLL_CTRL2 0x188
+#define ANACTRL_MPLL_CTRL3 0x18c
+#define ANACTRL_MPLL_CTRL4 0x190
+#define ANACTRL_MPLL_CTRL5 0x194
+#define ANACTRL_MPLL_CTRL6 0x198
+#define ANACTRL_MPLL_CTRL7 0x19c
+#define ANACTRL_MPLL_CTRL8 0x1a0
+#define ANACTRL_HDMIPLL_CTRL0 0x1c0
+
+#endif /* __MESON_S4_PLL_H__ */
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 865db5202e4c..dbc3950c5960 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -131,6 +131,7 @@ config IPQ_APSS_6018
tristate "IPQ APSS Clock Controller"
select IPQ_APSS_PLL
depends on QCOM_APCS_IPC || COMPILE_TEST
+ depends on QCOM_SMEM
help
Support for APSS clock controller on IPQ platforms. The
APSS clock controller manages the Mux and enable block that feeds the
@@ -764,6 +765,14 @@ config SM_CAMCC_8450
Support for the camera clock controller on SM8450 devices.
Say Y if you want to support camera devices and camera functionality.
+config SM_CAMCC_8550
+ tristate "SM8550 Camera Clock Controller"
+ depends on ARM64 || COMPILE_TEST
+ select SM_GCC_8550
+ help
+ Support for the camera clock controller on SM8550 devices.
+ Say Y if you want to support camera devices and camera functionality.
+
config SM_DISPCC_6115
tristate "SM6115 Display Clock Controller"
depends on ARM64 || COMPILE_TEST
@@ -834,6 +843,15 @@ config SM_DISPCC_8550
Say Y if you want to support display devices and functionality such as
splash screen.
+config SM_GCC_4450
+ tristate "SM4450 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
+ select QCOM_GDSC
+ help
+ Support for the global clock controller on SM4450 devices.
+ Say Y if you want to use peripheral devices such as UART, SPI,
+ I2C, USB, SD/UFS, PCIe, etc.
+
config SM_GCC_6115
tristate "SM6115 and SM4250 Global Clock Controller"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 4790c8cca426..17edd73f9839 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -102,6 +102,7 @@ obj-$(CONFIG_SDX_GCC_75) += gcc-sdx75.o
obj-$(CONFIG_SM_CAMCC_6350) += camcc-sm6350.o
obj-$(CONFIG_SM_CAMCC_8250) += camcc-sm8250.o
obj-$(CONFIG_SM_CAMCC_8450) += camcc-sm8450.o
+obj-$(CONFIG_SM_CAMCC_8550) += camcc-sm8550.o
obj-$(CONFIG_SM_DISPCC_6115) += dispcc-sm6115.o
obj-$(CONFIG_SM_DISPCC_6125) += dispcc-sm6125.o
obj-$(CONFIG_SM_DISPCC_6350) += dispcc-sm6350.o
@@ -109,6 +110,7 @@ obj-$(CONFIG_SM_DISPCC_6375) += dispcc-sm6375.o
obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o
obj-$(CONFIG_SM_DISPCC_8450) += dispcc-sm8450.o
obj-$(CONFIG_SM_DISPCC_8550) += dispcc-sm8550.o
+obj-$(CONFIG_SM_GCC_4450) += gcc-sm4450.o
obj-$(CONFIG_SM_GCC_6115) += gcc-sm6115.o
obj-$(CONFIG_SM_GCC_6125) += gcc-sm6125.o
obj-$(CONFIG_SM_GCC_6350) += gcc-sm6350.o
diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c
index e170331858cc..41279e5437a6 100644
--- a/drivers/clk/qcom/apss-ipq-pll.c
+++ b/drivers/clk/qcom/apss-ipq-pll.c
@@ -68,13 +68,13 @@ static struct clk_alpha_pll ipq_pll_stromer_plus = {
.fw_name = "xo",
},
.num_parents = 1,
- .ops = &clk_alpha_pll_stromer_ops,
+ .ops = &clk_alpha_pll_stromer_plus_ops,
},
},
};
static const struct alpha_pll_config ipq5332_pll_config = {
- .l = 0x3e,
+ .l = 0x2d,
.config_ctl_val = 0x4001075b,
.config_ctl_hi_val = 0x304,
.main_output_mask = BIT(0),
diff --git a/drivers/clk/qcom/apss-ipq6018.c b/drivers/clk/qcom/apss-ipq6018.c
index f2f502e2d5a4..e6295b832686 100644
--- a/drivers/clk/qcom/apss-ipq6018.c
+++ b/drivers/clk/qcom/apss-ipq6018.c
@@ -9,8 +9,11 @@
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/soc/qcom/smem.h>
#include <dt-bindings/clock/qcom,apss-ipq.h>
+#include <dt-bindings/arm/qcom,ids.h>
#include "common.h"
#include "clk-regmap.h"
@@ -20,16 +23,19 @@
enum {
P_XO,
+ P_GPLL0,
P_APSS_PLL_EARLY,
};
static const struct clk_parent_data parents_apcs_alias0_clk_src[] = {
{ .fw_name = "xo" },
+ { .fw_name = "gpll0" },
{ .fw_name = "pll" },
};
static const struct parent_map parents_apcs_alias0_clk_src_map[] = {
{ P_XO, 0 },
+ { P_GPLL0, 4 },
{ P_APSS_PLL_EARLY, 5 },
};
@@ -81,15 +87,68 @@ static const struct qcom_cc_desc apss_ipq6018_desc = {
.num_clks = ARRAY_SIZE(apss_ipq6018_clks),
};
+static int cpu_clk_notifier_fn(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct clk_hw *hw;
+ u8 index;
+ int err;
+
+ if (action == PRE_RATE_CHANGE)
+ index = P_GPLL0;
+ else if (action == POST_RATE_CHANGE || action == ABORT_RATE_CHANGE)
+ index = P_APSS_PLL_EARLY;
+ else
+ return NOTIFY_OK;
+
+ hw = &apcs_alias0_clk_src.clkr.hw;
+ err = clk_rcg2_mux_closest_ops.set_parent(hw, index);
+
+ return notifier_from_errno(err);
+}
+
static int apss_ipq6018_probe(struct platform_device *pdev)
{
+ struct clk_hw *hw = &apcs_alias0_clk_src.clkr.hw;
+ struct notifier_block *cpu_clk_notifier;
struct regmap *regmap;
+ u32 soc_id;
+ int ret;
+
+ ret = qcom_smem_get_soc_id(&soc_id);
+ if (ret)
+ return ret;
regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!regmap)
return -ENODEV;
- return qcom_cc_really_probe(pdev, &apss_ipq6018_desc, regmap);
+ ret = qcom_cc_really_probe(pdev, &apss_ipq6018_desc, regmap);
+ if (ret)
+ return ret;
+
+ switch (soc_id) {
+ /* Only below variants of IPQ53xx support scaling */
+ case QCOM_ID_IPQ5332:
+ case QCOM_ID_IPQ5322:
+ case QCOM_ID_IPQ5300:
+ cpu_clk_notifier = devm_kzalloc(&pdev->dev,
+ sizeof(*cpu_clk_notifier),
+ GFP_KERNEL);
+ if (!cpu_clk_notifier)
+ return -ENOMEM;
+
+ cpu_clk_notifier->notifier_call = cpu_clk_notifier_fn;
+
+ ret = devm_clk_notifier_register(&pdev->dev, hw->clk, cpu_clk_notifier);
+ if (ret)
+ return ret;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
}
static struct platform_driver apss_ipq6018_driver = {
diff --git a/drivers/clk/qcom/camcc-sm8550.c b/drivers/clk/qcom/camcc-sm8550.c
new file mode 100644
index 000000000000..dd51ba4ea757
--- /dev/null
+++ b/drivers/clk/qcom/camcc-sm8550.c
@@ -0,0 +1,3565 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sm8550-camcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_IFACE,
+ DT_BI_TCXO,
+ DT_BI_TCXO_AO,
+ DT_SLEEP_CLK,
+};
+
+enum {
+ P_BI_TCXO,
+ P_BI_TCXO_AO,
+ P_CAM_CC_PLL0_OUT_EVEN,
+ P_CAM_CC_PLL0_OUT_MAIN,
+ P_CAM_CC_PLL0_OUT_ODD,
+ P_CAM_CC_PLL1_OUT_EVEN,
+ P_CAM_CC_PLL2_OUT_EVEN,
+ P_CAM_CC_PLL2_OUT_MAIN,
+ P_CAM_CC_PLL3_OUT_EVEN,
+ P_CAM_CC_PLL4_OUT_EVEN,
+ P_CAM_CC_PLL5_OUT_EVEN,
+ P_CAM_CC_PLL6_OUT_EVEN,
+ P_CAM_CC_PLL7_OUT_EVEN,
+ P_CAM_CC_PLL8_OUT_EVEN,
+ P_CAM_CC_PLL9_OUT_EVEN,
+ P_CAM_CC_PLL9_OUT_ODD,
+ P_CAM_CC_PLL10_OUT_EVEN,
+ P_CAM_CC_PLL11_OUT_EVEN,
+ P_CAM_CC_PLL12_OUT_EVEN,
+ P_SLEEP_CLK,
+};
+
+static const struct pll_vco lucid_ole_vco[] = {
+ { 249600000, 2300000000, 0 },
+};
+
+static const struct pll_vco rivian_ole_vco[] = {
+ { 777000000, 1285000000, 0 },
+};
+
+static const struct alpha_pll_config cam_cc_pll0_config = {
+ .l = 0x3e,
+ .alpha = 0x8000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00008400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll0_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll0_out_even = {
+ .offset = 0x0,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll0_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll0_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll0_out_odd[] = {
+ { 0x2, 3 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll0_out_odd = {
+ .offset = 0x0,
+ .post_div_shift = 14,
+ .post_div_table = post_div_table_cam_cc_pll0_out_odd,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_odd),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll0_out_odd",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll1_config = {
+ .l = 0x2f,
+ .alpha = 0x6555,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll1 = {
+ .offset = 0x1000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll1_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll1_out_even = {
+ .offset = 0x1000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll1_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll1_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll1_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll1.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll2_config = {
+ .l = 0x32,
+ .alpha = 0x0,
+ .config_ctl_val = 0x10000030,
+ .config_ctl_hi_val = 0x80890263,
+ .config_ctl_hi1_val = 0x00000217,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00100000,
+};
+
+static struct clk_alpha_pll cam_cc_pll2 = {
+ .offset = 0x2000,
+ .vco_table = rivian_ole_vco,
+ .num_vco = ARRAY_SIZE(rivian_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_RIVIAN_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll2",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_rivian_evo_ops,
+ },
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll3_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll3 = {
+ .offset = 0x3000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll3",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll3_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll3_out_even = {
+ .offset = 0x3000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll3_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll3_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll3_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll3.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll4_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll4 = {
+ .offset = 0x4000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll4",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll4_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll4_out_even = {
+ .offset = 0x4000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll4_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll4_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll4_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll4.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll5_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll5 = {
+ .offset = 0x5000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll5",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll5_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll5_out_even = {
+ .offset = 0x5000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll5_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll5_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll5_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll5.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll6_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll6 = {
+ .offset = 0x6000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll6",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll6_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll6_out_even = {
+ .offset = 0x6000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll6_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll6_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll6_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll6.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll7_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll7 = {
+ .offset = 0x7000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll7",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll7_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll7_out_even = {
+ .offset = 0x7000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll7_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll7_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll7_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll7.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll8_config = {
+ .l = 0x14,
+ .alpha = 0xd555,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll8 = {
+ .offset = 0x8000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll8",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll8_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll8_out_even = {
+ .offset = 0x8000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll8_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll8_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll8_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll8.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll9_config = {
+ .l = 0x32,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll9 = {
+ .offset = 0x9000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll9",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll9_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll9_out_even = {
+ .offset = 0x9000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll9_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll9_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll9_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll9.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll10_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll10 = {
+ .offset = 0xa000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll10",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll10_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll10_out_even = {
+ .offset = 0xa000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll10_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll10_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll10_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll10.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll11_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll11 = {
+ .offset = 0xb000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll11",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll11_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll11_out_even = {
+ .offset = 0xb000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll11_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll11_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll11_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll11.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll12_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll12 = {
+ .offset = 0xc000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll12",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll12_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll12_out_even = {
+ .offset = 0xc000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll12_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll12_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll12_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll12.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct parent_map cam_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL0_OUT_MAIN, 1 },
+ { P_CAM_CC_PLL0_OUT_EVEN, 2 },
+ { P_CAM_CC_PLL0_OUT_ODD, 3 },
+ { P_CAM_CC_PLL9_OUT_ODD, 4 },
+ { P_CAM_CC_PLL9_OUT_EVEN, 5 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll0.clkr.hw },
+ { .hw = &cam_cc_pll0_out_even.clkr.hw },
+ { .hw = &cam_cc_pll0_out_odd.clkr.hw },
+ { .hw = &cam_cc_pll9.clkr.hw },
+ { .hw = &cam_cc_pll9_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL2_OUT_EVEN, 3 },
+ { P_CAM_CC_PLL2_OUT_MAIN, 5 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll2.clkr.hw },
+ { .hw = &cam_cc_pll2.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL8_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll8_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL3_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll3_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_4[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL10_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_4[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll10_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_5[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL4_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_5[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll4_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_6[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL11_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_6[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll11_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_7[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL5_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_7[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll5_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_8[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL12_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_8[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll12_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_9[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL1_OUT_EVEN, 4 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_9[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll1_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_10[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL6_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_10[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll6_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_11[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL7_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_11[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll7_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_12[] = {
+ { P_SLEEP_CLK, 0 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_12[] = {
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map cam_cc_parent_map_13_ao[] = {
+ { P_BI_TCXO_AO, 0 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_13_ao[] = {
+ { .index = DT_BI_TCXO_AO },
+};
+
+static const struct freq_tbl ftbl_cam_cc_bps_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(200000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0),
+ F(400000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0),
+ F(480000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_bps_clk_src = {
+ .cmd_rcgr = 0x10278,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_2,
+ .freq_tbl = ftbl_cam_cc_bps_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_bps_clk_src",
+ .parent_data = cam_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_camnoc_axi_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_camnoc_axi_clk_src = {
+ .cmd_rcgr = 0x13de0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_camnoc_axi_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_axi_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_cci_0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(37500000, P_CAM_CC_PLL0_OUT_EVEN, 16, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_cci_0_clk_src = {
+ .cmd_rcgr = 0x13900,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cci_0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_0_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_cci_1_clk_src = {
+ .cmd_rcgr = 0x13a30,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cci_0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_1_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_cci_2_clk_src = {
+ .cmd_rcgr = 0x13b60,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cci_0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_2_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(480000000, P_CAM_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_cphy_rx_clk_src = {
+ .cmd_rcgr = 0x11290,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cphy_rx_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_cre_clk_src[] = {
+ F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAM_CC_PLL9_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_cre_clk_src = {
+ .cmd_rcgr = 0x1353c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cre_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cre_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_csi0phytimer_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_EVEN, 1.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = {
+ .cmd_rcgr = 0x15980,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi0phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = {
+ .cmd_rcgr = 0x15ab8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi1phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi2phytimer_clk_src = {
+ .cmd_rcgr = 0x15bec,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi2phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = {
+ .cmd_rcgr = 0x15d20,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi3phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_csi4phytimer_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_csi4phytimer_clk_src = {
+ .cmd_rcgr = 0x15e54,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi4phytimer_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi4phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi5phytimer_clk_src = {
+ .cmd_rcgr = 0x15f88,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi5phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi6phytimer_clk_src = {
+ .cmd_rcgr = 0x160bc,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi6phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi7phytimer_clk_src = {
+ .cmd_rcgr = 0x161f0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi7phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_csid_clk_src[] = {
+ F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(480000000, P_CAM_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_csid_clk_src = {
+ .cmd_rcgr = 0x13ca8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csid_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csid_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_fast_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_fast_ahb_clk_src = {
+ .cmd_rcgr = 0x10018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_fast_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_fast_ahb_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_icp_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAM_CC_PLL9_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_icp_clk_src = {
+ .cmd_rcgr = 0x137c4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_icp_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_icp_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(466000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ife_0_clk_src = {
+ .cmd_rcgr = 0x11018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_3,
+ .freq_tbl = ftbl_cam_cc_ife_0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_0_clk_src",
+ .parent_data = cam_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_0_dsp_clk_src[] = {
+ F(466000000, P_CAM_CC_PLL10_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL10_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL10_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL10_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ife_0_dsp_clk_src = {
+ .cmd_rcgr = 0x11154,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_4,
+ .freq_tbl = ftbl_cam_cc_ife_0_dsp_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_0_dsp_clk_src",
+ .parent_data = cam_cc_parent_data_4,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_1_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(466000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ife_1_clk_src = {
+ .cmd_rcgr = 0x12018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_5,
+ .freq_tbl = ftbl_cam_cc_ife_1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_1_clk_src",
+ .parent_data = cam_cc_parent_data_5,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_5),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_1_dsp_clk_src[] = {
+ F(466000000, P_CAM_CC_PLL11_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL11_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL11_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL11_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ife_1_dsp_clk_src = {
+ .cmd_rcgr = 0x12154,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_6,
+ .freq_tbl = ftbl_cam_cc_ife_1_dsp_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_1_dsp_clk_src",
+ .parent_data = cam_cc_parent_data_6,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_6),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_2_clk_src[] = {
+ F(466000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ife_2_clk_src = {
+ .cmd_rcgr = 0x122a8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_7,
+ .freq_tbl = ftbl_cam_cc_ife_2_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_2_clk_src",
+ .parent_data = cam_cc_parent_data_7,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_7),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_2_dsp_clk_src[] = {
+ F(466000000, P_CAM_CC_PLL12_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL12_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL12_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL12_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ife_2_dsp_clk_src = {
+ .cmd_rcgr = 0x123e4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_8,
+ .freq_tbl = ftbl_cam_cc_ife_2_dsp_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_2_dsp_clk_src",
+ .parent_data = cam_cc_parent_data_8,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_8),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_ife_lite_clk_src = {
+ .cmd_rcgr = 0x13000,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csid_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = {
+ .cmd_rcgr = 0x1313c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csid_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_csid_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ipe_nps_clk_src[] = {
+ F(455000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0),
+ F(575000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0),
+ F(825000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ipe_nps_clk_src = {
+ .cmd_rcgr = 0x103cc,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_9,
+ .freq_tbl = ftbl_cam_cc_ipe_nps_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_nps_clk_src",
+ .parent_data = cam_cc_parent_data_9,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_9),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_jpeg_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAM_CC_PLL9_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_jpeg_clk_src = {
+ .cmd_rcgr = 0x13674,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_jpeg_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_jpeg_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_mclk0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(24000000, P_CAM_CC_PLL2_OUT_MAIN, 10, 1, 4),
+ F(68571429, P_CAM_CC_PLL2_OUT_MAIN, 14, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_mclk0_clk_src = {
+ .cmd_rcgr = 0x15000,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk0_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_mclk1_clk_src = {
+ .cmd_rcgr = 0x15130,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk1_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_mclk2_clk_src = {
+ .cmd_rcgr = 0x15260,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk2_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_mclk3_clk_src = {
+ .cmd_rcgr = 0x15390,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk3_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_mclk4_clk_src = {
+ .cmd_rcgr = 0x154c0,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk4_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_mclk5_clk_src = {
+ .cmd_rcgr = 0x155f0,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk5_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_mclk6_clk_src = {
+ .cmd_rcgr = 0x15720,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk6_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_mclk7_clk_src = {
+ .cmd_rcgr = 0x15850,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk7_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_qdss_debug_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(75000000, P_CAM_CC_PLL0_OUT_EVEN, 8, 0, 0),
+ F(150000000, P_CAM_CC_PLL0_OUT_EVEN, 4, 0, 0),
+ F(300000000, P_CAM_CC_PLL0_OUT_MAIN, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_qdss_debug_clk_src = {
+ .cmd_rcgr = 0x13f24,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_qdss_debug_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_qdss_debug_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_sfe_0_clk_src[] = {
+ F(466000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_sfe_0_clk_src = {
+ .cmd_rcgr = 0x13294,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_10,
+ .freq_tbl = ftbl_cam_cc_sfe_0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_0_clk_src",
+ .parent_data = cam_cc_parent_data_10,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_10),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_sfe_1_clk_src[] = {
+ F(466000000, P_CAM_CC_PLL7_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL7_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL7_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL7_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_sfe_1_clk_src = {
+ .cmd_rcgr = 0x133f4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_11,
+ .freq_tbl = ftbl_cam_cc_sfe_1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_1_clk_src",
+ .parent_data = cam_cc_parent_data_11,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_11),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_sleep_clk_src = {
+ .cmd_rcgr = 0x141a0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_12,
+ .freq_tbl = ftbl_cam_cc_sleep_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sleep_clk_src",
+ .parent_data = cam_cc_parent_data_12,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_12),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_slow_ahb_clk_src = {
+ .cmd_rcgr = 0x10148,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_slow_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_slow_ahb_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_xo_clk_src[] = {
+ F(19200000, P_BI_TCXO_AO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_xo_clk_src = {
+ .cmd_rcgr = 0x14070,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_13_ao,
+ .freq_tbl = ftbl_cam_cc_xo_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_xo_clk_src",
+ .parent_data = cam_cc_parent_data_13_ao,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_13_ao),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_branch cam_cc_bps_ahb_clk = {
+ .halt_reg = 0x10274,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10274,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_bps_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_bps_clk = {
+ .halt_reg = 0x103a4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x103a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_bps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_bps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_bps_fast_ahb_clk = {
+ .halt_reg = 0x10144,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10144,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_bps_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_axi_clk = {
+ .halt_reg = 0x13f0c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13f0c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_axi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_camnoc_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_dcd_xo_clk = {
+ .halt_reg = 0x13f18,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13f18,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_dcd_xo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_xo_clk = {
+ .halt_reg = 0x13f1c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13f1c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_xo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cci_0_clk = {
+ .halt_reg = 0x13a2c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13a2c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cci_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cci_1_clk = {
+ .halt_reg = 0x13b5c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13b5c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cci_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cci_2_clk = {
+ .halt_reg = 0x13c8c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13c8c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cci_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_core_ahb_clk = {
+ .halt_reg = 0x1406c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x1406c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_core_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_ahb_clk = {
+ .halt_reg = 0x13c90,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13c90,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_bps_clk = {
+ .halt_reg = 0x103b0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x103b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_bps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_bps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_cre_clk = {
+ .halt_reg = 0x1366c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1366c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_cre_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cre_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_fast_ahb_clk = {
+ .halt_reg = 0x13c9c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13c9c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_ife_0_clk = {
+ .halt_reg = 0x11150,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11150,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ife_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_ife_1_clk = {
+ .halt_reg = 0x12150,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x12150,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ife_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_ife_2_clk = {
+ .halt_reg = 0x123e0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x123e0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ife_2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_ife_lite_clk = {
+ .halt_reg = 0x13138,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13138,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ife_lite_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_lite_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_ipe_nps_clk = {
+ .halt_reg = 0x10504,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10504,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ipe_nps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ipe_nps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_sbi_clk = {
+ .halt_reg = 0x1054c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1054c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_sbi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_sfe_0_clk = {
+ .halt_reg = 0x133cc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x133cc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_sfe_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_sfe_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_sfe_1_clk = {
+ .halt_reg = 0x1352c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1352c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_sfe_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_sfe_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cre_ahb_clk = {
+ .halt_reg = 0x13670,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13670,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cre_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cre_clk = {
+ .halt_reg = 0x13668,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13668,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cre_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cre_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi0phytimer_clk = {
+ .halt_reg = 0x15aac,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15aac,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi0phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi0phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi1phytimer_clk = {
+ .halt_reg = 0x15be4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15be4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi1phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi1phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi2phytimer_clk = {
+ .halt_reg = 0x15d18,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15d18,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi2phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi2phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi3phytimer_clk = {
+ .halt_reg = 0x15e4c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15e4c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi3phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi3phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi4phytimer_clk = {
+ .halt_reg = 0x15f80,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15f80,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi4phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi4phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi5phytimer_clk = {
+ .halt_reg = 0x160b4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x160b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi5phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi5phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi6phytimer_clk = {
+ .halt_reg = 0x161e8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x161e8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi6phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi6phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi7phytimer_clk = {
+ .halt_reg = 0x1631c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1631c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi7phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi7phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csid_clk = {
+ .halt_reg = 0x13dd4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13dd4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csid_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csid_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csid_csiphy_rx_clk = {
+ .halt_reg = 0x15ab4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15ab4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csid_csiphy_rx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy0_clk = {
+ .halt_reg = 0x15ab0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15ab0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy1_clk = {
+ .halt_reg = 0x15be8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15be8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy2_clk = {
+ .halt_reg = 0x15d1c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15d1c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy3_clk = {
+ .halt_reg = 0x15e50,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15e50,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy4_clk = {
+ .halt_reg = 0x15f84,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15f84,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy4_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy5_clk = {
+ .halt_reg = 0x160b8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x160b8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy5_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy6_clk = {
+ .halt_reg = 0x161ec,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x161ec,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy6_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy7_clk = {
+ .halt_reg = 0x16320,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x16320,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy7_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_drv_ahb_clk = {
+ .halt_reg = 0x142d8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x142d8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_drv_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_drv_xo_clk = {
+ .halt_reg = 0x142d4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x142d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_drv_xo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_icp_ahb_clk = {
+ .halt_reg = 0x138fc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x138fc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_icp_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_icp_clk = {
+ .halt_reg = 0x138f0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x138f0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_icp_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_icp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_0_clk = {
+ .halt_reg = 0x11144,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11144,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_0_dsp_clk = {
+ .halt_reg = 0x11280,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11280,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_0_dsp_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_0_dsp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_0_fast_ahb_clk = {
+ .halt_reg = 0x1128c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1128c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_0_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_1_clk = {
+ .halt_reg = 0x12144,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x12144,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_1_dsp_clk = {
+ .halt_reg = 0x12280,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x12280,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_1_dsp_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_1_dsp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_1_fast_ahb_clk = {
+ .halt_reg = 0x1228c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1228c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_1_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_2_clk = {
+ .halt_reg = 0x123d4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x123d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_2_dsp_clk = {
+ .halt_reg = 0x12510,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x12510,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_2_dsp_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_2_dsp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_2_fast_ahb_clk = {
+ .halt_reg = 0x1251c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1251c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_2_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_lite_ahb_clk = {
+ .halt_reg = 0x13278,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13278,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_lite_clk = {
+ .halt_reg = 0x1312c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1312c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_lite_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_lite_cphy_rx_clk = {
+ .halt_reg = 0x13274,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13274,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_cphy_rx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_lite_csid_clk = {
+ .halt_reg = 0x13268,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13268,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_csid_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_lite_csid_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_nps_ahb_clk = {
+ .halt_reg = 0x1051c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1051c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_nps_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_nps_clk = {
+ .halt_reg = 0x104f8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x104f8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_nps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ipe_nps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_nps_fast_ahb_clk = {
+ .halt_reg = 0x10520,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10520,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_nps_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_pps_clk = {
+ .halt_reg = 0x10508,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10508,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_pps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ipe_nps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_pps_fast_ahb_clk = {
+ .halt_reg = 0x10524,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10524,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_pps_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_jpeg_1_clk = {
+ .halt_reg = 0x137ac,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x137ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_jpeg_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_jpeg_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_jpeg_clk = {
+ .halt_reg = 0x137a0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x137a0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_jpeg_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_jpeg_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk0_clk = {
+ .halt_reg = 0x1512c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1512c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk1_clk = {
+ .halt_reg = 0x1525c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1525c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk2_clk = {
+ .halt_reg = 0x1538c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1538c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk3_clk = {
+ .halt_reg = 0x154bc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x154bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk4_clk = {
+ .halt_reg = 0x155ec,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x155ec,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk4_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk5_clk = {
+ .halt_reg = 0x1571c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1571c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk5_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk5_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk6_clk = {
+ .halt_reg = 0x1584c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1584c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk6_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk6_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk7_clk = {
+ .halt_reg = 0x1597c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1597c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk7_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk7_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_qdss_debug_clk = {
+ .halt_reg = 0x14050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x14050,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_qdss_debug_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_qdss_debug_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_qdss_debug_xo_clk = {
+ .halt_reg = 0x14054,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x14054,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_qdss_debug_xo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sbi_clk = {
+ .halt_reg = 0x10540,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10540,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sbi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sbi_fast_ahb_clk = {
+ .halt_reg = 0x10550,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10550,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sbi_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sfe_0_clk = {
+ .halt_reg = 0x133c0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x133c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_sfe_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sfe_0_fast_ahb_clk = {
+ .halt_reg = 0x133d8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x133d8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_0_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sfe_1_clk = {
+ .halt_reg = 0x13520,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13520,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_sfe_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sfe_1_fast_ahb_clk = {
+ .halt_reg = 0x13538,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13538,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_1_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc cam_cc_bps_gdsc = {
+ .gdscr = 0x10004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_bps_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_ife_0_gdsc = {
+ .gdscr = 0x11004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_ife_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_ife_1_gdsc = {
+ .gdscr = 0x12004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_ife_1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_ife_2_gdsc = {
+ .gdscr = 0x12294,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_ife_2_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_ipe_0_gdsc = {
+ .gdscr = 0x103b8,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_ipe_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_sbi_gdsc = {
+ .gdscr = 0x1052c,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_sbi_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_sfe_0_gdsc = {
+ .gdscr = 0x13280,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_sfe_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_sfe_1_gdsc = {
+ .gdscr = 0x133e0,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_sfe_1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_titan_top_gdsc = {
+ .gdscr = 0x14058,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_titan_top_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct clk_regmap *cam_cc_sm8550_clocks[] = {
+ [CAM_CC_BPS_AHB_CLK] = &cam_cc_bps_ahb_clk.clkr,
+ [CAM_CC_BPS_CLK] = &cam_cc_bps_clk.clkr,
+ [CAM_CC_BPS_CLK_SRC] = &cam_cc_bps_clk_src.clkr,
+ [CAM_CC_BPS_FAST_AHB_CLK] = &cam_cc_bps_fast_ahb_clk.clkr,
+ [CAM_CC_CAMNOC_AXI_CLK] = &cam_cc_camnoc_axi_clk.clkr,
+ [CAM_CC_CAMNOC_AXI_CLK_SRC] = &cam_cc_camnoc_axi_clk_src.clkr,
+ [CAM_CC_CAMNOC_DCD_XO_CLK] = &cam_cc_camnoc_dcd_xo_clk.clkr,
+ [CAM_CC_CAMNOC_XO_CLK] = &cam_cc_camnoc_xo_clk.clkr,
+ [CAM_CC_CCI_0_CLK] = &cam_cc_cci_0_clk.clkr,
+ [CAM_CC_CCI_0_CLK_SRC] = &cam_cc_cci_0_clk_src.clkr,
+ [CAM_CC_CCI_1_CLK] = &cam_cc_cci_1_clk.clkr,
+ [CAM_CC_CCI_1_CLK_SRC] = &cam_cc_cci_1_clk_src.clkr,
+ [CAM_CC_CCI_2_CLK] = &cam_cc_cci_2_clk.clkr,
+ [CAM_CC_CCI_2_CLK_SRC] = &cam_cc_cci_2_clk_src.clkr,
+ [CAM_CC_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr,
+ [CAM_CC_CPAS_AHB_CLK] = &cam_cc_cpas_ahb_clk.clkr,
+ [CAM_CC_CPAS_BPS_CLK] = &cam_cc_cpas_bps_clk.clkr,
+ [CAM_CC_CPAS_CRE_CLK] = &cam_cc_cpas_cre_clk.clkr,
+ [CAM_CC_CPAS_FAST_AHB_CLK] = &cam_cc_cpas_fast_ahb_clk.clkr,
+ [CAM_CC_CPAS_IFE_0_CLK] = &cam_cc_cpas_ife_0_clk.clkr,
+ [CAM_CC_CPAS_IFE_1_CLK] = &cam_cc_cpas_ife_1_clk.clkr,
+ [CAM_CC_CPAS_IFE_2_CLK] = &cam_cc_cpas_ife_2_clk.clkr,
+ [CAM_CC_CPAS_IFE_LITE_CLK] = &cam_cc_cpas_ife_lite_clk.clkr,
+ [CAM_CC_CPAS_IPE_NPS_CLK] = &cam_cc_cpas_ipe_nps_clk.clkr,
+ [CAM_CC_CPAS_SBI_CLK] = &cam_cc_cpas_sbi_clk.clkr,
+ [CAM_CC_CPAS_SFE_0_CLK] = &cam_cc_cpas_sfe_0_clk.clkr,
+ [CAM_CC_CPAS_SFE_1_CLK] = &cam_cc_cpas_sfe_1_clk.clkr,
+ [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr,
+ [CAM_CC_CRE_AHB_CLK] = &cam_cc_cre_ahb_clk.clkr,
+ [CAM_CC_CRE_CLK] = &cam_cc_cre_clk.clkr,
+ [CAM_CC_CRE_CLK_SRC] = &cam_cc_cre_clk_src.clkr,
+ [CAM_CC_CSI0PHYTIMER_CLK] = &cam_cc_csi0phytimer_clk.clkr,
+ [CAM_CC_CSI0PHYTIMER_CLK_SRC] = &cam_cc_csi0phytimer_clk_src.clkr,
+ [CAM_CC_CSI1PHYTIMER_CLK] = &cam_cc_csi1phytimer_clk.clkr,
+ [CAM_CC_CSI1PHYTIMER_CLK_SRC] = &cam_cc_csi1phytimer_clk_src.clkr,
+ [CAM_CC_CSI2PHYTIMER_CLK] = &cam_cc_csi2phytimer_clk.clkr,
+ [CAM_CC_CSI2PHYTIMER_CLK_SRC] = &cam_cc_csi2phytimer_clk_src.clkr,
+ [CAM_CC_CSI3PHYTIMER_CLK] = &cam_cc_csi3phytimer_clk.clkr,
+ [CAM_CC_CSI3PHYTIMER_CLK_SRC] = &cam_cc_csi3phytimer_clk_src.clkr,
+ [CAM_CC_CSI4PHYTIMER_CLK] = &cam_cc_csi4phytimer_clk.clkr,
+ [CAM_CC_CSI4PHYTIMER_CLK_SRC] = &cam_cc_csi4phytimer_clk_src.clkr,
+ [CAM_CC_CSI5PHYTIMER_CLK] = &cam_cc_csi5phytimer_clk.clkr,
+ [CAM_CC_CSI5PHYTIMER_CLK_SRC] = &cam_cc_csi5phytimer_clk_src.clkr,
+ [CAM_CC_CSI6PHYTIMER_CLK] = &cam_cc_csi6phytimer_clk.clkr,
+ [CAM_CC_CSI6PHYTIMER_CLK_SRC] = &cam_cc_csi6phytimer_clk_src.clkr,
+ [CAM_CC_CSI7PHYTIMER_CLK] = &cam_cc_csi7phytimer_clk.clkr,
+ [CAM_CC_CSI7PHYTIMER_CLK_SRC] = &cam_cc_csi7phytimer_clk_src.clkr,
+ [CAM_CC_CSID_CLK] = &cam_cc_csid_clk.clkr,
+ [CAM_CC_CSID_CLK_SRC] = &cam_cc_csid_clk_src.clkr,
+ [CAM_CC_CSID_CSIPHY_RX_CLK] = &cam_cc_csid_csiphy_rx_clk.clkr,
+ [CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr,
+ [CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr,
+ [CAM_CC_CSIPHY2_CLK] = &cam_cc_csiphy2_clk.clkr,
+ [CAM_CC_CSIPHY3_CLK] = &cam_cc_csiphy3_clk.clkr,
+ [CAM_CC_CSIPHY4_CLK] = &cam_cc_csiphy4_clk.clkr,
+ [CAM_CC_CSIPHY5_CLK] = &cam_cc_csiphy5_clk.clkr,
+ [CAM_CC_CSIPHY6_CLK] = &cam_cc_csiphy6_clk.clkr,
+ [CAM_CC_CSIPHY7_CLK] = &cam_cc_csiphy7_clk.clkr,
+ [CAM_CC_DRV_AHB_CLK] = &cam_cc_drv_ahb_clk.clkr,
+ [CAM_CC_DRV_XO_CLK] = &cam_cc_drv_xo_clk.clkr,
+ [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr,
+ [CAM_CC_ICP_AHB_CLK] = &cam_cc_icp_ahb_clk.clkr,
+ [CAM_CC_ICP_CLK] = &cam_cc_icp_clk.clkr,
+ [CAM_CC_ICP_CLK_SRC] = &cam_cc_icp_clk_src.clkr,
+ [CAM_CC_IFE_0_CLK] = &cam_cc_ife_0_clk.clkr,
+ [CAM_CC_IFE_0_CLK_SRC] = &cam_cc_ife_0_clk_src.clkr,
+ [CAM_CC_IFE_0_DSP_CLK] = &cam_cc_ife_0_dsp_clk.clkr,
+ [CAM_CC_IFE_0_DSP_CLK_SRC] = &cam_cc_ife_0_dsp_clk_src.clkr,
+ [CAM_CC_IFE_0_FAST_AHB_CLK] = &cam_cc_ife_0_fast_ahb_clk.clkr,
+ [CAM_CC_IFE_1_CLK] = &cam_cc_ife_1_clk.clkr,
+ [CAM_CC_IFE_1_CLK_SRC] = &cam_cc_ife_1_clk_src.clkr,
+ [CAM_CC_IFE_1_DSP_CLK] = &cam_cc_ife_1_dsp_clk.clkr,
+ [CAM_CC_IFE_1_DSP_CLK_SRC] = &cam_cc_ife_1_dsp_clk_src.clkr,
+ [CAM_CC_IFE_1_FAST_AHB_CLK] = &cam_cc_ife_1_fast_ahb_clk.clkr,
+ [CAM_CC_IFE_2_CLK] = &cam_cc_ife_2_clk.clkr,
+ [CAM_CC_IFE_2_CLK_SRC] = &cam_cc_ife_2_clk_src.clkr,
+ [CAM_CC_IFE_2_DSP_CLK] = &cam_cc_ife_2_dsp_clk.clkr,
+ [CAM_CC_IFE_2_DSP_CLK_SRC] = &cam_cc_ife_2_dsp_clk_src.clkr,
+ [CAM_CC_IFE_2_FAST_AHB_CLK] = &cam_cc_ife_2_fast_ahb_clk.clkr,
+ [CAM_CC_IFE_LITE_AHB_CLK] = &cam_cc_ife_lite_ahb_clk.clkr,
+ [CAM_CC_IFE_LITE_CLK] = &cam_cc_ife_lite_clk.clkr,
+ [CAM_CC_IFE_LITE_CLK_SRC] = &cam_cc_ife_lite_clk_src.clkr,
+ [CAM_CC_IFE_LITE_CPHY_RX_CLK] = &cam_cc_ife_lite_cphy_rx_clk.clkr,
+ [CAM_CC_IFE_LITE_CSID_CLK] = &cam_cc_ife_lite_csid_clk.clkr,
+ [CAM_CC_IFE_LITE_CSID_CLK_SRC] = &cam_cc_ife_lite_csid_clk_src.clkr,
+ [CAM_CC_IPE_NPS_AHB_CLK] = &cam_cc_ipe_nps_ahb_clk.clkr,
+ [CAM_CC_IPE_NPS_CLK] = &cam_cc_ipe_nps_clk.clkr,
+ [CAM_CC_IPE_NPS_CLK_SRC] = &cam_cc_ipe_nps_clk_src.clkr,
+ [CAM_CC_IPE_NPS_FAST_AHB_CLK] = &cam_cc_ipe_nps_fast_ahb_clk.clkr,
+ [CAM_CC_IPE_PPS_CLK] = &cam_cc_ipe_pps_clk.clkr,
+ [CAM_CC_IPE_PPS_FAST_AHB_CLK] = &cam_cc_ipe_pps_fast_ahb_clk.clkr,
+ [CAM_CC_JPEG_1_CLK] = &cam_cc_jpeg_1_clk.clkr,
+ [CAM_CC_JPEG_CLK] = &cam_cc_jpeg_clk.clkr,
+ [CAM_CC_JPEG_CLK_SRC] = &cam_cc_jpeg_clk_src.clkr,
+ [CAM_CC_MCLK0_CLK] = &cam_cc_mclk0_clk.clkr,
+ [CAM_CC_MCLK0_CLK_SRC] = &cam_cc_mclk0_clk_src.clkr,
+ [CAM_CC_MCLK1_CLK] = &cam_cc_mclk1_clk.clkr,
+ [CAM_CC_MCLK1_CLK_SRC] = &cam_cc_mclk1_clk_src.clkr,
+ [CAM_CC_MCLK2_CLK] = &cam_cc_mclk2_clk.clkr,
+ [CAM_CC_MCLK2_CLK_SRC] = &cam_cc_mclk2_clk_src.clkr,
+ [CAM_CC_MCLK3_CLK] = &cam_cc_mclk3_clk.clkr,
+ [CAM_CC_MCLK3_CLK_SRC] = &cam_cc_mclk3_clk_src.clkr,
+ [CAM_CC_MCLK4_CLK] = &cam_cc_mclk4_clk.clkr,
+ [CAM_CC_MCLK4_CLK_SRC] = &cam_cc_mclk4_clk_src.clkr,
+ [CAM_CC_MCLK5_CLK] = &cam_cc_mclk5_clk.clkr,
+ [CAM_CC_MCLK5_CLK_SRC] = &cam_cc_mclk5_clk_src.clkr,
+ [CAM_CC_MCLK6_CLK] = &cam_cc_mclk6_clk.clkr,
+ [CAM_CC_MCLK6_CLK_SRC] = &cam_cc_mclk6_clk_src.clkr,
+ [CAM_CC_MCLK7_CLK] = &cam_cc_mclk7_clk.clkr,
+ [CAM_CC_MCLK7_CLK_SRC] = &cam_cc_mclk7_clk_src.clkr,
+ [CAM_CC_PLL0] = &cam_cc_pll0.clkr,
+ [CAM_CC_PLL0_OUT_EVEN] = &cam_cc_pll0_out_even.clkr,
+ [CAM_CC_PLL0_OUT_ODD] = &cam_cc_pll0_out_odd.clkr,
+ [CAM_CC_PLL1] = &cam_cc_pll1.clkr,
+ [CAM_CC_PLL1_OUT_EVEN] = &cam_cc_pll1_out_even.clkr,
+ [CAM_CC_PLL2] = &cam_cc_pll2.clkr,
+ [CAM_CC_PLL3] = &cam_cc_pll3.clkr,
+ [CAM_CC_PLL3_OUT_EVEN] = &cam_cc_pll3_out_even.clkr,
+ [CAM_CC_PLL4] = &cam_cc_pll4.clkr,
+ [CAM_CC_PLL4_OUT_EVEN] = &cam_cc_pll4_out_even.clkr,
+ [CAM_CC_PLL5] = &cam_cc_pll5.clkr,
+ [CAM_CC_PLL5_OUT_EVEN] = &cam_cc_pll5_out_even.clkr,
+ [CAM_CC_PLL6] = &cam_cc_pll6.clkr,
+ [CAM_CC_PLL6_OUT_EVEN] = &cam_cc_pll6_out_even.clkr,
+ [CAM_CC_PLL7] = &cam_cc_pll7.clkr,
+ [CAM_CC_PLL7_OUT_EVEN] = &cam_cc_pll7_out_even.clkr,
+ [CAM_CC_PLL8] = &cam_cc_pll8.clkr,
+ [CAM_CC_PLL8_OUT_EVEN] = &cam_cc_pll8_out_even.clkr,
+ [CAM_CC_PLL9] = &cam_cc_pll9.clkr,
+ [CAM_CC_PLL9_OUT_EVEN] = &cam_cc_pll9_out_even.clkr,
+ [CAM_CC_PLL10] = &cam_cc_pll10.clkr,
+ [CAM_CC_PLL10_OUT_EVEN] = &cam_cc_pll10_out_even.clkr,
+ [CAM_CC_PLL11] = &cam_cc_pll11.clkr,
+ [CAM_CC_PLL11_OUT_EVEN] = &cam_cc_pll11_out_even.clkr,
+ [CAM_CC_PLL12] = &cam_cc_pll12.clkr,
+ [CAM_CC_PLL12_OUT_EVEN] = &cam_cc_pll12_out_even.clkr,
+ [CAM_CC_QDSS_DEBUG_CLK] = &cam_cc_qdss_debug_clk.clkr,
+ [CAM_CC_QDSS_DEBUG_CLK_SRC] = &cam_cc_qdss_debug_clk_src.clkr,
+ [CAM_CC_QDSS_DEBUG_XO_CLK] = &cam_cc_qdss_debug_xo_clk.clkr,
+ [CAM_CC_SBI_CLK] = &cam_cc_sbi_clk.clkr,
+ [CAM_CC_SBI_FAST_AHB_CLK] = &cam_cc_sbi_fast_ahb_clk.clkr,
+ [CAM_CC_SFE_0_CLK] = &cam_cc_sfe_0_clk.clkr,
+ [CAM_CC_SFE_0_CLK_SRC] = &cam_cc_sfe_0_clk_src.clkr,
+ [CAM_CC_SFE_0_FAST_AHB_CLK] = &cam_cc_sfe_0_fast_ahb_clk.clkr,
+ [CAM_CC_SFE_1_CLK] = &cam_cc_sfe_1_clk.clkr,
+ [CAM_CC_SFE_1_CLK_SRC] = &cam_cc_sfe_1_clk_src.clkr,
+ [CAM_CC_SFE_1_FAST_AHB_CLK] = &cam_cc_sfe_1_fast_ahb_clk.clkr,
+ [CAM_CC_SLEEP_CLK_SRC] = &cam_cc_sleep_clk_src.clkr,
+ [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr,
+ [CAM_CC_XO_CLK_SRC] = &cam_cc_xo_clk_src.clkr,
+};
+
+static struct gdsc *cam_cc_sm8550_gdscs[] = {
+ [CAM_CC_BPS_GDSC] = &cam_cc_bps_gdsc,
+ [CAM_CC_IFE_0_GDSC] = &cam_cc_ife_0_gdsc,
+ [CAM_CC_IFE_1_GDSC] = &cam_cc_ife_1_gdsc,
+ [CAM_CC_IFE_2_GDSC] = &cam_cc_ife_2_gdsc,
+ [CAM_CC_IPE_0_GDSC] = &cam_cc_ipe_0_gdsc,
+ [CAM_CC_SBI_GDSC] = &cam_cc_sbi_gdsc,
+ [CAM_CC_SFE_0_GDSC] = &cam_cc_sfe_0_gdsc,
+ [CAM_CC_SFE_1_GDSC] = &cam_cc_sfe_1_gdsc,
+ [CAM_CC_TITAN_TOP_GDSC] = &cam_cc_titan_top_gdsc,
+};
+
+static const struct qcom_reset_map cam_cc_sm8550_resets[] = {
+ [CAM_CC_BPS_BCR] = { 0x10000 },
+ [CAM_CC_DRV_BCR] = { 0x142d0 },
+ [CAM_CC_ICP_BCR] = { 0x137c0 },
+ [CAM_CC_IFE_0_BCR] = { 0x11000 },
+ [CAM_CC_IFE_1_BCR] = { 0x12000 },
+ [CAM_CC_IFE_2_BCR] = { 0x12290 },
+ [CAM_CC_IPE_0_BCR] = { 0x103b4 },
+ [CAM_CC_QDSS_DEBUG_BCR] = { 0x13f20 },
+ [CAM_CC_SBI_BCR] = { 0x10528 },
+ [CAM_CC_SFE_0_BCR] = { 0x1327c },
+ [CAM_CC_SFE_1_BCR] = { 0x133dc },
+};
+
+static const struct regmap_config cam_cc_sm8550_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x16320,
+ .fast_io = true,
+};
+
+static struct qcom_cc_desc cam_cc_sm8550_desc = {
+ .config = &cam_cc_sm8550_regmap_config,
+ .clks = cam_cc_sm8550_clocks,
+ .num_clks = ARRAY_SIZE(cam_cc_sm8550_clocks),
+ .resets = cam_cc_sm8550_resets,
+ .num_resets = ARRAY_SIZE(cam_cc_sm8550_resets),
+ .gdscs = cam_cc_sm8550_gdscs,
+ .num_gdscs = ARRAY_SIZE(cam_cc_sm8550_gdscs),
+};
+
+static const struct of_device_id cam_cc_sm8550_match_table[] = {
+ { .compatible = "qcom,sm8550-camcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, cam_cc_sm8550_match_table);
+
+static int cam_cc_sm8550_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
+
+ regmap = qcom_cc_map(pdev, &cam_cc_sm8550_desc);
+ if (IS_ERR(regmap)) {
+ pm_runtime_put(&pdev->dev);
+ return PTR_ERR(regmap);
+ }
+
+ clk_lucid_ole_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll1, regmap, &cam_cc_pll1_config);
+ clk_rivian_evo_pll_configure(&cam_cc_pll2, regmap, &cam_cc_pll2_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll4, regmap, &cam_cc_pll4_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll5, regmap, &cam_cc_pll5_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll6, regmap, &cam_cc_pll6_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll7, regmap, &cam_cc_pll7_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll8, regmap, &cam_cc_pll8_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll9, regmap, &cam_cc_pll9_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll10, regmap, &cam_cc_pll10_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll11, regmap, &cam_cc_pll11_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll12, regmap, &cam_cc_pll12_config);
+
+ /*
+ * Keep clocks always enabled:
+ * cam_cc_gdsc_clk
+ * cam_cc_sleep_clk
+ */
+ regmap_update_bits(regmap, 0x1419c, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x142cc, BIT(0), BIT(0));
+
+ ret = qcom_cc_really_probe(pdev, &cam_cc_sm8550_desc, regmap);
+
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
+}
+
+static struct platform_driver cam_cc_sm8550_driver = {
+ .probe = cam_cc_sm8550_probe,
+ .driver = {
+ .name = "cam_cc-sm8550",
+ .of_match_table = cam_cc_sm8550_match_table,
+ },
+};
+
+module_platform_driver(cam_cc_sm8550_driver);
+
+MODULE_DESCRIPTION("QTI CAMCC SM8550 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index e4ef645f65d1..05898d2a8b22 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -271,6 +271,7 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
#define LUCID_EVO_ENABLE_VOTE_RUN BIT(25)
#define LUCID_EVO_PLL_L_VAL_MASK GENMASK(15, 0)
#define LUCID_EVO_PLL_CAL_L_VAL_SHIFT 16
+#define LUCID_OLE_PLL_RINGOSC_CAL_L_VAL_SHIFT 24
/* ZONDA PLL specific */
#define ZONDA_PLL_OUT_MASK 0xf
@@ -2119,6 +2120,34 @@ void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regma
}
EXPORT_SYMBOL_GPL(clk_lucid_evo_pll_configure);
+void clk_lucid_ole_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+ const struct alpha_pll_config *config)
+{
+ u32 lval = config->l;
+
+ lval |= TRION_PLL_CAL_VAL << LUCID_EVO_PLL_CAL_L_VAL_SHIFT;
+ lval |= TRION_PLL_CAL_VAL << LUCID_OLE_PLL_RINGOSC_CAL_L_VAL_SHIFT;
+ clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), lval);
+ clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);
+ clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val);
+ clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val);
+ clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val);
+ clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val);
+ clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val);
+ clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val);
+ clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val);
+ clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val);
+ clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U2(pll), config->test_ctl_hi2_val);
+
+ /* Disable PLL output */
+ regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
+
+ /* Set operation mode to STANDBY and de-assert the reset */
+ regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);
+ regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
+}
+EXPORT_SYMBOL_GPL(clk_lucid_ole_pll_configure);
+
static int alpha_pll_lucid_evo_enable(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
@@ -2479,3 +2508,66 @@ const struct clk_ops clk_alpha_pll_stromer_ops = {
.set_rate = clk_alpha_pll_stromer_set_rate,
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_stromer_ops);
+
+static int clk_alpha_pll_stromer_plus_set_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long prate)
+{
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ u32 l, alpha_width = pll_alpha_width(pll);
+ int ret, pll_mode;
+ u64 a;
+
+ rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
+
+ ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &pll_mode);
+ if (ret)
+ return ret;
+
+ regmap_write(pll->clkr.regmap, PLL_MODE(pll), 0);
+
+ /* Delay of 2 output clock ticks required until output is disabled */
+ udelay(1);
+
+ regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
+
+ if (alpha_width > ALPHA_BITWIDTH)
+ a <<= alpha_width - ALPHA_BITWIDTH;
+
+ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
+ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll),
+ a >> ALPHA_BITWIDTH);
+
+ regmap_write(pll->clkr.regmap, PLL_MODE(pll), PLL_BYPASSNL);
+
+ /* Wait five micro seconds or more */
+ udelay(5);
+ regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N,
+ PLL_RESET_N);
+
+ /* The lock time should be less than 50 micro seconds worst case */
+ usleep_range(50, 60);
+
+ ret = wait_for_pll_enable_lock(pll);
+ if (ret) {
+ pr_err("Wait for PLL enable lock failed [%s] %d\n",
+ clk_hw_get_name(hw), ret);
+ return ret;
+ }
+
+ if (pll_mode & PLL_OUTCTRL)
+ regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL,
+ PLL_OUTCTRL);
+
+ return 0;
+}
+
+const struct clk_ops clk_alpha_pll_stromer_plus_ops = {
+ .prepare = clk_alpha_pll_enable,
+ .unprepare = clk_alpha_pll_disable,
+ .is_enabled = clk_alpha_pll_is_enabled,
+ .recalc_rate = clk_alpha_pll_recalc_rate,
+ .determine_rate = clk_alpha_pll_stromer_determine_rate,
+ .set_rate = clk_alpha_pll_stromer_plus_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_stromer_plus_ops);
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index e4bd863027ab..a1a75bb12fe8 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -152,6 +152,7 @@ extern const struct clk_ops clk_alpha_pll_postdiv_ops;
extern const struct clk_ops clk_alpha_pll_huayra_ops;
extern const struct clk_ops clk_alpha_pll_postdiv_ro_ops;
extern const struct clk_ops clk_alpha_pll_stromer_ops;
+extern const struct clk_ops clk_alpha_pll_stromer_plus_ops;
extern const struct clk_ops clk_alpha_pll_fabia_ops;
extern const struct clk_ops clk_alpha_pll_fixed_fabia_ops;
@@ -199,6 +200,8 @@ void clk_zonda_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
+void clk_lucid_ole_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+ const struct alpha_pll_config *config);
void clk_rivian_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
void clk_stromer_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
diff --git a/drivers/clk/qcom/clk-cbf-8996.c b/drivers/clk/qcom/clk-cbf-8996.c
index 53f205a3f183..fe24b4abeab4 100644
--- a/drivers/clk/qcom/clk-cbf-8996.c
+++ b/drivers/clk/qcom/clk-cbf-8996.c
@@ -250,13 +250,11 @@ static int qcom_msm8996_cbf_icc_register(struct platform_device *pdev, struct cl
return 0;
}
-static int qcom_msm8996_cbf_icc_remove(struct platform_device *pdev)
+static void qcom_msm8996_cbf_icc_remove(struct platform_device *pdev)
{
struct icc_provider *provider = platform_get_drvdata(pdev);
icc_clk_unregister(provider);
-
- return 0;
}
#define qcom_msm8996_cbf_icc_sync_state icc_sync_state
#else
@@ -266,7 +264,7 @@ static int qcom_msm8996_cbf_icc_register(struct platform_device *pdev, struct c
return 0;
}
-#define qcom_msm8996_cbf_icc_remove(pdev) (0)
+#define qcom_msm8996_cbf_icc_remove(pdev) { }
#define qcom_msm8996_cbf_icc_sync_state NULL
#endif
@@ -340,9 +338,9 @@ static int qcom_msm8996_cbf_probe(struct platform_device *pdev)
return qcom_msm8996_cbf_icc_register(pdev, &cbf_mux.clkr.hw);
}
-static int qcom_msm8996_cbf_remove(struct platform_device *pdev)
+static void qcom_msm8996_cbf_remove(struct platform_device *pdev)
{
- return qcom_msm8996_cbf_icc_remove(pdev);
+ qcom_msm8996_cbf_icc_remove(pdev);
}
static const struct of_device_id qcom_msm8996_cbf_match_table[] = {
@@ -354,7 +352,7 @@ MODULE_DEVICE_TABLE(of, qcom_msm8996_cbf_match_table);
static struct platform_driver qcom_msm8996_cbf_driver = {
.probe = qcom_msm8996_cbf_probe,
- .remove = qcom_msm8996_cbf_remove,
+ .remove_new = qcom_msm8996_cbf_remove,
.driver = {
.name = "qcom-msm8996-cbf",
.of_match_table = qcom_msm8996_cbf_match_table,
diff --git a/drivers/clk/qcom/clk-hfpll.c b/drivers/clk/qcom/clk-hfpll.c
index 86f728dc69e5..705352aff067 100644
--- a/drivers/clk/qcom/clk-hfpll.c
+++ b/drivers/clk/qcom/clk-hfpll.c
@@ -44,6 +44,10 @@ static void __clk_hfpll_init_once(struct clk_hw *hw)
regmap_write(regmap, hd->user_reg, regval);
}
+ /* Write L_VAL from conf if it exist */
+ if (hd->l_val)
+ regmap_write(regmap, hd->l_reg, hd->l_val);
+
if (hd->droop_reg)
regmap_write(regmap, hd->droop_reg, hd->droop_val);
diff --git a/drivers/clk/qcom/clk-hfpll.h b/drivers/clk/qcom/clk-hfpll.h
index 2a57b2fb2f2f..27b9effcb3fd 100644
--- a/drivers/clk/qcom/clk-hfpll.h
+++ b/drivers/clk/qcom/clk-hfpll.h
@@ -18,6 +18,7 @@ struct hfpll_data {
u32 status_reg;
u8 lock_bit;
+ u32 l_val;
u32 droop_val;
u32 config_val;
u32 user_val;
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index e22baf3a7112..5183c74b074f 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -158,17 +158,11 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
static unsigned long
calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div)
{
- if (hid_div) {
- rate *= 2;
- rate /= hid_div + 1;
- }
+ if (hid_div)
+ rate = mult_frac(rate, 2, hid_div + 1);
- if (mode) {
- u64 tmp = rate;
- tmp *= m;
- do_div(tmp, n);
- rate = tmp;
- }
+ if (mode)
+ rate = mult_frac(rate, m, n);
return rate;
}
diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c
index 4c5b552b47b6..5d853fd43294 100644
--- a/drivers/clk/qcom/clk-rpmh.c
+++ b/drivers/clk/qcom/clk-rpmh.c
@@ -350,6 +350,7 @@ DEFINE_CLK_RPMH_VRM(ln_bb_clk3, _a2, "lnbclka3", 2);
DEFINE_CLK_RPMH_VRM(ln_bb_clk1, _a4, "lnbclka1", 4);
DEFINE_CLK_RPMH_VRM(ln_bb_clk2, _a4, "lnbclka2", 4);
+DEFINE_CLK_RPMH_VRM(ln_bb_clk3, _a4, "lnbclka3", 4);
DEFINE_CLK_RPMH_VRM(ln_bb_clk2, _g4, "lnbclkg2", 4);
DEFINE_CLK_RPMH_VRM(ln_bb_clk3, _g4, "lnbclkg3", 4);
@@ -717,6 +718,25 @@ static const struct clk_rpmh_desc clk_rpmh_sdx75 = {
.num_clks = ARRAY_SIZE(sdx75_rpmh_clocks),
};
+static struct clk_hw *sm4450_rpmh_clocks[] = {
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div4.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div4_ao.hw,
+ [RPMH_LN_BB_CLK2] = &clk_rpmh_ln_bb_clk2_a4.hw,
+ [RPMH_LN_BB_CLK2_A] = &clk_rpmh_ln_bb_clk2_a4_ao.hw,
+ [RPMH_LN_BB_CLK3] = &clk_rpmh_ln_bb_clk3_a4.hw,
+ [RPMH_LN_BB_CLK3_A] = &clk_rpmh_ln_bb_clk3_a4_ao.hw,
+ [RPMH_RF_CLK1] = &clk_rpmh_rf_clk1_a.hw,
+ [RPMH_RF_CLK1_A] = &clk_rpmh_rf_clk1_a_ao.hw,
+ [RPMH_RF_CLK5] = &clk_rpmh_rf_clk5_a.hw,
+ [RPMH_RF_CLK5_A] = &clk_rpmh_rf_clk5_a_ao.hw,
+ [RPMH_IPA_CLK] = &clk_rpmh_ipa.hw,
+};
+
+static const struct clk_rpmh_desc clk_rpmh_sm4450 = {
+ .clks = sm4450_rpmh_clocks,
+ .num_clks = ARRAY_SIZE(sm4450_rpmh_clocks),
+};
+
static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
void *data)
{
@@ -810,6 +830,7 @@ static const struct of_device_id clk_rpmh_match_table[] = {
{ .compatible = "qcom,sdx55-rpmh-clk", .data = &clk_rpmh_sdx55},
{ .compatible = "qcom,sdx65-rpmh-clk", .data = &clk_rpmh_sdx65},
{ .compatible = "qcom,sdx75-rpmh-clk", .data = &clk_rpmh_sdx75},
+ { .compatible = "qcom,sm4450-rpmh-clk", .data = &clk_rpmh_sm4450},
{ .compatible = "qcom,sm6350-rpmh-clk", .data = &clk_rpmh_sm6350},
{ .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150},
{ .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250},
diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
index 0191fc0dd7da..8602c02047d0 100644
--- a/drivers/clk/qcom/clk-smd-rpm.c
+++ b/drivers/clk/qcom/clk-smd-rpm.c
@@ -574,6 +574,16 @@ static const struct clk_smd_rpm *sm_qnoc_icc_clks[] = {
&clk_smd_rpm_bus_2_snoc_clk,
};
+static const struct clk_smd_rpm *qcm2290_icc_clks[] = {
+ &clk_smd_rpm_bimc_clk,
+ &clk_smd_rpm_bus_1_cnoc_clk,
+ &clk_smd_rpm_mmnrt_clk,
+ &clk_smd_rpm_mmrt_clk,
+ &clk_smd_rpm_qup_clk,
+ &clk_smd_rpm_bus_2_snoc_clk,
+ &clk_smd_rpm_cpuss_gnoc_clk,
+};
+
static struct clk_smd_rpm *msm8909_clks[] = {
[RPM_SMD_QPIC_CLK] = &clk_smd_rpm_qpic_clk,
[RPM_SMD_QPIC_CLK_A] = &clk_smd_rpm_qpic_a_clk,
@@ -1189,15 +1199,13 @@ static struct clk_smd_rpm *qcm2290_clks[] = {
[RPM_SMD_PKA_A_CLK] = &clk_smd_rpm_pka_a_clk,
[RPM_SMD_BIMC_GPU_CLK] = &clk_smd_rpm_bimc_gpu_clk,
[RPM_SMD_BIMC_GPU_A_CLK] = &clk_smd_rpm_bimc_gpu_a_clk,
- [RPM_SMD_CPUSS_GNOC_CLK] = &clk_smd_rpm_cpuss_gnoc_clk,
- [RPM_SMD_CPUSS_GNOC_A_CLK] = &clk_smd_rpm_cpuss_gnoc_a_clk,
};
static const struct rpm_smd_clk_desc rpm_clk_qcm2290 = {
.clks = qcm2290_clks,
.num_clks = ARRAY_SIZE(qcm2290_clks),
- .icc_clks = sm_qnoc_icc_clks,
- .num_icc_clks = ARRAY_SIZE(sm_qnoc_icc_clks)
+ .icc_clks = qcm2290_icc_clks,
+ .num_icc_clks = ARRAY_SIZE(qcm2290_icc_clks)
};
static const struct of_device_id rpm_smd_clk_match_table[] = {
diff --git a/drivers/clk/qcom/gcc-ipq5018.c b/drivers/clk/qcom/gcc-ipq5018.c
index 19dc2b71cacf..4aba47e8700d 100644
--- a/drivers/clk/qcom/gcc-ipq5018.c
+++ b/drivers/clk/qcom/gcc-ipq5018.c
@@ -3,8 +3,9 @@
* Copyright (c) 2023, The Linux Foundation. All rights reserved.
*/
#include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,gcc-ipq5018.h>
@@ -128,7 +129,6 @@ static struct clk_alpha_pll_postdiv gpll0 = {
},
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -143,7 +143,6 @@ static struct clk_alpha_pll_postdiv gpll2 = {
},
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -158,7 +157,6 @@ static struct clk_alpha_pll_postdiv gpll4 = {
},
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
diff --git a/drivers/clk/qcom/gcc-ipq5332.c b/drivers/clk/qcom/gcc-ipq5332.c
index b02026f8549b..f98591148a97 100644
--- a/drivers/clk/qcom/gcc-ipq5332.c
+++ b/drivers/clk/qcom/gcc-ipq5332.c
@@ -71,7 +71,6 @@ static struct clk_fixed_factor gpll0_div2 = {
&gpll0_main.clkr.hw },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -85,7 +84,6 @@ static struct clk_alpha_pll_postdiv gpll0 = {
&gpll0_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -114,7 +112,6 @@ static struct clk_alpha_pll_postdiv gpll2 = {
&gpll2_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -154,7 +151,6 @@ static struct clk_alpha_pll_postdiv gpll4 = {
&gpll4_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
diff --git a/drivers/clk/qcom/gcc-ipq6018.c b/drivers/clk/qcom/gcc-ipq6018.c
index 6120fbbc5de0..b366912cd648 100644
--- a/drivers/clk/qcom/gcc-ipq6018.c
+++ b/drivers/clk/qcom/gcc-ipq6018.c
@@ -72,7 +72,6 @@ static struct clk_fixed_factor gpll0_out_main_div2 = {
&gpll0_main.clkr.hw },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -86,7 +85,6 @@ static struct clk_alpha_pll_postdiv gpll0 = {
&gpll0_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -161,7 +159,6 @@ static struct clk_alpha_pll_postdiv gpll6 = {
&gpll6_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -192,7 +189,6 @@ static struct clk_alpha_pll_postdiv gpll4 = {
&gpll4_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -243,7 +239,6 @@ static struct clk_alpha_pll_postdiv gpll2 = {
&gpll2_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -274,7 +269,6 @@ static struct clk_alpha_pll_postdiv nss_crypto_pll = {
&nss_crypto_pll_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -2125,6 +2119,26 @@ static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
},
};
+static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
+ .halt_reg = 0x07010,
+ .clkr = {
+ .enable_reg = 0x07010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup6_i2c_apps_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup6_i2c_apps_clk_src.clkr.hw },
+ .num_parents = 1,
+ /*
+ * RPM uses QUP6 I2C to communicate with the external
+ * PMIC so it must not be disabled.
+ */
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
.halt_reg = 0x0700c,
.clkr = {
@@ -4281,6 +4295,7 @@ static struct clk_regmap *gcc_ipq6018_clks[] = {
[GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
[GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr,
[GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr,
[GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr,
[GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
[GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c
index 63ac2ced76bb..b7faf12a511a 100644
--- a/drivers/clk/qcom/gcc-ipq8074.c
+++ b/drivers/clk/qcom/gcc-ipq8074.c
@@ -75,7 +75,6 @@ static struct clk_fixed_factor gpll0_out_main_div2 = {
&gpll0_main.clkr.hw },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -121,7 +120,6 @@ static struct clk_alpha_pll_postdiv gpll2 = {
&gpll2_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -154,7 +152,6 @@ static struct clk_alpha_pll_postdiv gpll4 = {
&gpll4_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -188,7 +185,6 @@ static struct clk_alpha_pll_postdiv gpll6 = {
&gpll6_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -201,7 +197,6 @@ static struct clk_fixed_factor gpll6_out_main_div2 = {
&gpll6_main.clkr.hw },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
@@ -266,7 +261,6 @@ static struct clk_alpha_pll_postdiv nss_crypto_pll = {
&nss_crypto_pll_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
- .flags = CLK_SET_RATE_PARENT,
},
};
diff --git a/drivers/clk/qcom/gcc-ipq9574.c b/drivers/clk/qcom/gcc-ipq9574.c
index 8f430367299e..e8190108e1ae 100644
--- a/drivers/clk/qcom/gcc-ipq9574.c
+++ b/drivers/clk/qcom/gcc-ipq9574.c
@@ -87,7 +87,6 @@ static struct clk_fixed_factor gpll0_out_main_div2 = {
&gpll0_main.clkr.hw
},
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_fixed_factor_ops,
},
};
@@ -102,7 +101,6 @@ static struct clk_alpha_pll_postdiv gpll0 = {
&gpll0_main.clkr.hw
},
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_alpha_pll_postdiv_ro_ops,
},
};
@@ -132,7 +130,6 @@ static struct clk_alpha_pll_postdiv gpll4 = {
&gpll4_main.clkr.hw
},
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_alpha_pll_postdiv_ro_ops,
},
};
@@ -162,7 +159,6 @@ static struct clk_alpha_pll_postdiv gpll2 = {
&gpll2_main.clkr.hw
},
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_alpha_pll_postdiv_ro_ops,
},
};
diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c
index dbc7093ab9cc..6236a458e4eb 100644
--- a/drivers/clk/qcom/gcc-msm8960.c
+++ b/drivers/clk/qcom/gcc-msm8960.c
@@ -7,9 +7,10 @@
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/of_platform.h>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include <linux/reset-controller.h>
@@ -3716,14 +3717,10 @@ MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table);
static int gcc_msm8960_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- const struct of_device_id *match;
struct platform_device *tsens;
+ const struct qcom_cc_desc *desc = device_get_match_data(dev);
int ret;
- match = of_match_device(gcc_msm8960_match_table, &pdev->dev);
- if (!match)
- return -EINVAL;
-
ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000);
if (ret)
return ret;
@@ -3732,11 +3729,11 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = qcom_cc_probe(pdev, match->data);
+ ret = qcom_cc_probe(pdev, desc);
if (ret)
return ret;
- if (match->data == &gcc_apq8064_desc) {
+ if (desc == &gcc_apq8064_desc) {
hfpll1.d = &hfpll1_8064_data;
hfpll_l2.d = &hfpll_l2_8064_data;
}
diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c
index 0231c1efd286..b32e66714951 100644
--- a/drivers/clk/qcom/gcc-msm8974.c
+++ b/drivers/clk/qcom/gcc-msm8974.c
@@ -7,9 +7,9 @@
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include <linux/reset-controller.h>
@@ -2875,14 +2875,10 @@ static int gcc_msm8974_probe(struct platform_device *pdev)
{
int ret;
struct device *dev = &pdev->dev;
- const struct of_device_id *id;
-
- id = of_match_device(gcc_msm8974_match_table, dev);
- if (!id)
- return -ENODEV;
+ const void *data = device_get_match_data(dev);
if (!of_device_is_compatible(dev->of_node, "qcom,gcc-msm8974")) {
- if (id->data == &gcc_msm8226_desc)
+ if (data == &gcc_msm8226_desc)
msm8226_clock_override();
else
msm8974_pro_clock_override();
diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
index 14dcc3f03668..e7b03a17514a 100644
--- a/drivers/clk/qcom/gcc-msm8996.c
+++ b/drivers/clk/qcom/gcc-msm8996.c
@@ -244,71 +244,6 @@ static const struct clk_parent_data gcc_xo_gpll0_gpll4_gpll0_early_div[] = {
{ .hw = &gpll0_early_div.hw }
};
-static const struct freq_tbl ftbl_system_noc_clk_src[] = {
- F(19200000, P_XO, 1, 0, 0),
- F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
- F(100000000, P_GPLL0, 6, 0, 0),
- F(150000000, P_GPLL0, 4, 0, 0),
- F(200000000, P_GPLL0, 3, 0, 0),
- F(240000000, P_GPLL0, 2.5, 0, 0),
- { }
-};
-
-static struct clk_rcg2 system_noc_clk_src = {
- .cmd_rcgr = 0x0401c,
- .hid_width = 5,
- .parent_map = gcc_xo_gpll0_gpll0_early_div_map,
- .freq_tbl = ftbl_system_noc_clk_src,
- .clkr.hw.init = &(struct clk_init_data){
- .name = "system_noc_clk_src",
- .parent_data = gcc_xo_gpll0_gpll0_early_div,
- .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div),
- .ops = &clk_rcg2_ops,
- },
-};
-
-static const struct freq_tbl ftbl_config_noc_clk_src[] = {
- F(19200000, P_XO, 1, 0, 0),
- F(37500000, P_GPLL0, 16, 0, 0),
- F(75000000, P_GPLL0, 8, 0, 0),
- { }
-};
-
-static struct clk_rcg2 config_noc_clk_src = {
- .cmd_rcgr = 0x0500c,
- .hid_width = 5,
- .parent_map = gcc_xo_gpll0_map,
- .freq_tbl = ftbl_config_noc_clk_src,
- .clkr.hw.init = &(struct clk_init_data){
- .name = "config_noc_clk_src",
- .parent_data = gcc_xo_gpll0,
- .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
- .ops = &clk_rcg2_ops,
- },
-};
-
-static const struct freq_tbl ftbl_periph_noc_clk_src[] = {
- F(19200000, P_XO, 1, 0, 0),
- F(37500000, P_GPLL0, 16, 0, 0),
- F(50000000, P_GPLL0, 12, 0, 0),
- F(75000000, P_GPLL0, 8, 0, 0),
- F(100000000, P_GPLL0, 6, 0, 0),
- { }
-};
-
-static struct clk_rcg2 periph_noc_clk_src = {
- .cmd_rcgr = 0x06014,
- .hid_width = 5,
- .parent_map = gcc_xo_gpll0_map,
- .freq_tbl = ftbl_periph_noc_clk_src,
- .clkr.hw.init = &(struct clk_init_data){
- .name = "periph_noc_clk_src",
- .parent_data = gcc_xo_gpll0,
- .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
- .ops = &clk_rcg2_ops,
- },
-};
-
static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
F(19200000, P_XO, 1, 0, 0),
F(120000000, P_GPLL0, 5, 0, 0),
@@ -1297,11 +1232,7 @@ static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_mmss_noc_cfg_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ .flags = CLK_IGNORE_UNUSED,
.ops = &clk_branch2_ops,
},
},
@@ -1464,11 +1395,6 @@ static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb_phy_cfg_ahb2phy_clk",
- .parent_hws = (const struct clk_hw*[]){
- &periph_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -1498,11 +1424,6 @@ static struct clk_branch gcc_sdcc1_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc1_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &periph_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -1549,11 +1470,6 @@ static struct clk_branch gcc_sdcc2_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc2_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &periph_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -1583,11 +1499,6 @@ static struct clk_branch gcc_sdcc3_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc3_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &periph_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -1617,11 +1528,6 @@ static struct clk_branch gcc_sdcc4_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc4_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &periph_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -1635,11 +1541,6 @@ static struct clk_branch gcc_blsp1_ahb_clk = {
.enable_mask = BIT(17),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &periph_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -1977,11 +1878,6 @@ static struct clk_branch gcc_blsp2_ahb_clk = {
.enable_mask = BIT(15),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &periph_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2318,11 +2214,6 @@ static struct clk_branch gcc_pdm_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pdm_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &periph_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2353,11 +2244,6 @@ static struct clk_branch gcc_prng_ahb_clk = {
.enable_mask = BIT(13),
.hw.init = &(struct clk_init_data){
.name = "gcc_prng_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2370,11 +2256,6 @@ static struct clk_branch gcc_tsif_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_tsif_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &periph_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2422,11 +2303,6 @@ static struct clk_branch gcc_boot_rom_ahb_clk = {
.enable_mask = BIT(10),
.hw.init = &(struct clk_init_data){
.name = "gcc_boot_rom_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2520,11 +2396,6 @@ static struct clk_branch gcc_pcie_0_slv_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_0_slv_axi_clk",
- .parent_hws = (const struct clk_hw*[]){
- &system_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2537,11 +2408,6 @@ static struct clk_branch gcc_pcie_0_mstr_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_0_mstr_axi_clk",
- .parent_hws = (const struct clk_hw*[]){
- &system_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2554,11 +2420,6 @@ static struct clk_branch gcc_pcie_0_cfg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_0_cfg_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2606,11 +2467,6 @@ static struct clk_branch gcc_pcie_1_slv_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_1_slv_axi_clk",
- .parent_hws = (const struct clk_hw*[]){
- &system_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2623,11 +2479,6 @@ static struct clk_branch gcc_pcie_1_mstr_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_1_mstr_axi_clk",
- .parent_hws = (const struct clk_hw*[]){
- &system_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2640,11 +2491,6 @@ static struct clk_branch gcc_pcie_1_cfg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_1_cfg_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2692,11 +2538,6 @@ static struct clk_branch gcc_pcie_2_slv_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_2_slv_axi_clk",
- .parent_hws = (const struct clk_hw*[]){
- &system_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2709,11 +2550,6 @@ static struct clk_branch gcc_pcie_2_mstr_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_2_mstr_axi_clk",
- .parent_hws = (const struct clk_hw*[]){
- &system_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2726,11 +2562,6 @@ static struct clk_branch gcc_pcie_2_cfg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_2_cfg_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2778,11 +2609,6 @@ static struct clk_branch gcc_pcie_phy_cfg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_phy_cfg_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2829,11 +2655,6 @@ static struct clk_branch gcc_ufs_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -3060,11 +2881,7 @@ static struct clk_branch gcc_aggre0_snoc_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_aggre0_snoc_axi_clk",
- .parent_hws = (const struct clk_hw*[]){
- &system_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ .flags = CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
@@ -3077,11 +2894,7 @@ static struct clk_branch gcc_aggre0_cnoc_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_aggre0_cnoc_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ .flags = CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
@@ -3094,11 +2907,7 @@ static struct clk_branch gcc_smmu_aggre0_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_smmu_aggre0_axi_clk",
- .parent_hws = (const struct clk_hw*[]){
- &system_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ .flags = CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
@@ -3111,11 +2920,7 @@ static struct clk_branch gcc_smmu_aggre0_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_smmu_aggre0_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ .flags = CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
@@ -3162,10 +2967,6 @@ static struct clk_branch gcc_dcc_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_dcc_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
.ops = &clk_branch2_ops,
},
},
@@ -3178,10 +2979,6 @@ static struct clk_branch gcc_aggre0_noc_mpu_cfg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_aggre0_noc_mpu_cfg_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
.ops = &clk_branch2_ops,
},
},
@@ -3194,11 +2991,6 @@ static struct clk_branch gcc_qspi_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_qspi_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &periph_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -3347,10 +3139,6 @@ static struct clk_branch gcc_mss_cfg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_mss_cfg_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &config_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
.ops = &clk_branch2_ops,
},
},
@@ -3363,10 +3151,6 @@ static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_mss_mnoc_bimc_axi_clk",
- .parent_hws = (const struct clk_hw*[]){
- &system_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
.ops = &clk_branch2_ops,
},
},
@@ -3379,10 +3163,6 @@ static struct clk_branch gcc_mss_snoc_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_mss_snoc_axi_clk",
- .parent_hws = (const struct clk_hw*[]){
- &system_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
.ops = &clk_branch2_ops,
},
},
@@ -3395,10 +3175,6 @@ static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_mss_q6_bimc_axi_clk",
- .parent_hws = (const struct clk_hw*[]){
- &system_noc_clk_src.clkr.hw,
- },
- .num_parents = 1,
.ops = &clk_branch2_ops,
},
},
@@ -3495,9 +3271,6 @@ static struct clk_regmap *gcc_msm8996_clocks[] = {
[GPLL0] = &gpll0.clkr,
[GPLL4_EARLY] = &gpll4_early.clkr,
[GPLL4] = &gpll4.clkr,
- [SYSTEM_NOC_CLK_SRC] = &system_noc_clk_src.clkr,
- [CONFIG_NOC_CLK_SRC] = &config_noc_clk_src.clkr,
- [PERIPH_NOC_CLK_SRC] = &periph_noc_clk_src.clkr,
[USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
[USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
[USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
diff --git a/drivers/clk/qcom/gcc-sm4450.c b/drivers/clk/qcom/gcc-sm4450.c
new file mode 100644
index 000000000000..31abe2775fc8
--- /dev/null
+++ b/drivers/clk/qcom/gcc-sm4450.c
@@ -0,0 +1,2898 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sm4450-gcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "clk-regmap-phy-mux.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_BI_TCXO,
+ DT_SLEEP_CLK,
+ DT_PCIE_0_PIPE_CLK,
+ DT_UFS_PHY_RX_SYMBOL_0_CLK,
+ DT_UFS_PHY_RX_SYMBOL_1_CLK,
+ DT_UFS_PHY_TX_SYMBOL_0_CLK,
+ DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK,
+};
+
+enum {
+ P_BI_TCXO,
+ P_GCC_GPLL0_OUT_EVEN,
+ P_GCC_GPLL0_OUT_MAIN,
+ P_GCC_GPLL0_OUT_ODD,
+ P_GCC_GPLL1_OUT_MAIN,
+ P_GCC_GPLL3_OUT_MAIN,
+ P_GCC_GPLL4_OUT_MAIN,
+ P_GCC_GPLL9_OUT_MAIN,
+ P_GCC_GPLL10_OUT_MAIN,
+ P_SLEEP_CLK,
+ P_UFS_PHY_RX_SYMBOL_0_CLK,
+ P_UFS_PHY_RX_SYMBOL_1_CLK,
+ P_UFS_PHY_TX_SYMBOL_0_CLK,
+ P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK,
+};
+
+static const struct pll_vco lucid_evo_vco[] = {
+ { 249600000, 2020000000, 0 },
+};
+
+static struct clk_alpha_pll gcc_gpll0 = {
+ .offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .enable_reg = 0x62018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gcc_gpll0_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gcc_gpll0_out_even = {
+ .offset = 0x0,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_gcc_gpll0_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_gcc_gpll0_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll0_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_lucid_evo_ops,
+ },
+};
+
+static const struct clk_div_table post_div_table_gcc_gpll0_out_odd[] = {
+ { 0x2, 3 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gcc_gpll0_out_odd = {
+ .offset = 0x0,
+ .post_div_shift = 14,
+ .post_div_table = post_div_table_gcc_gpll0_out_odd,
+ .num_post_div = ARRAY_SIZE(post_div_table_gcc_gpll0_out_odd),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll0_out_odd",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_lucid_evo_ops,
+ },
+};
+
+static struct clk_alpha_pll gcc_gpll1 = {
+ .offset = 0x1000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .enable_reg = 0x62018,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct alpha_pll_config gcc_gpll3_config = {
+ .l = 0x14,
+ .alpha = 0xd555,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000805,
+};
+
+static struct clk_alpha_pll gcc_gpll3 = {
+ .offset = 0x3000,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .enable_reg = 0x62018,
+ .enable_mask = BIT(3),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll3",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll gcc_gpll4 = {
+ .offset = 0x4000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .enable_reg = 0x62018,
+ .enable_mask = BIT(4),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll4",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_evo_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll gcc_gpll9 = {
+ .offset = 0x9000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .enable_reg = 0x62018,
+ .enable_mask = BIT(9),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll9",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_evo_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll gcc_gpll10 = {
+ .offset = 0xa000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .enable_reg = 0x62018,
+ .enable_mask = BIT(10),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll10",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct parent_map gcc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_SLEEP_CLK, 5 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .index = DT_SLEEP_CLK },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL1_OUT_MAIN, 4 },
+ { P_GCC_GPLL4_OUT_MAIN, 5 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &gcc_gpll1.clkr.hw },
+ { .hw = &gcc_gpll4.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_SLEEP_CLK, 5 },
+};
+
+static const struct clk_parent_data gcc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map gcc_parent_map_4[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL0_OUT_ODD, 2 },
+ { P_GCC_GPLL10_OUT_MAIN, 3 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_4[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &gcc_gpll0_out_odd.clkr.hw },
+ { .hw = &gcc_gpll10.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_5[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data gcc_parent_data_5[] = {
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_6[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL9_OUT_MAIN, 2 },
+ { P_GCC_GPLL4_OUT_MAIN, 5 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_6[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &gcc_gpll9.clkr.hw },
+ { .hw = &gcc_gpll4.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_7[] = {
+ { P_UFS_PHY_RX_SYMBOL_0_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_7[] = {
+ { .index = DT_UFS_PHY_RX_SYMBOL_0_CLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_8[] = {
+ { P_UFS_PHY_RX_SYMBOL_1_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_8[] = {
+ { .index = DT_UFS_PHY_RX_SYMBOL_1_CLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_9[] = {
+ { P_UFS_PHY_TX_SYMBOL_0_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_9[] = {
+ { .index = DT_UFS_PHY_TX_SYMBOL_0_CLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_10[] = {
+ { P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_10[] = {
+ { .index = DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_11[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL3_OUT_MAIN, 5 },
+};
+
+static const struct clk_parent_data gcc_parent_data_11[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &gcc_gpll3.clkr.hw },
+};
+
+static struct clk_regmap_phy_mux gcc_pcie_0_pipe_clk_src = {
+ .reg = 0x7b060,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_PCIE_0_PIPE_CLK,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_ufs_phy_rx_symbol_0_clk_src = {
+ .reg = 0x87060,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_7,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_rx_symbol_0_clk_src",
+ .parent_data = gcc_parent_data_7,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_7),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_ufs_phy_rx_symbol_1_clk_src = {
+ .reg = 0x870d0,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_8,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_rx_symbol_1_clk_src",
+ .parent_data = gcc_parent_data_8,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_8),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_ufs_phy_tx_symbol_0_clk_src = {
+ .reg = 0x87050,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_9,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_tx_symbol_0_clk_src",
+ .parent_data = gcc_parent_data_9,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_9),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_usb3_prim_phy_pipe_clk_src = {
+ .reg = 0x49068,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_10,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_pipe_clk_src",
+ .parent_data = gcc_parent_data_10,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_10),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = {
+ F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0),
+ F(200000000, P_GCC_GPLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_gp1_clk_src = {
+ .cmd_rcgr = 0x74004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp1_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp2_clk_src = {
+ .cmd_rcgr = 0x75004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp2_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp3_clk_src = {
+ .cmd_rcgr = 0x76004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp3_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_0_aux_clk_src[] = {
+ F(9600000, P_BI_TCXO, 2, 0, 0),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pcie_0_aux_clk_src = {
+ .cmd_rcgr = 0x7b064,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_aux_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_0_phy_rchng_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pcie_0_phy_rchng_clk_src = {
+ .cmd_rcgr = 0x7b048,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_phy_rchng_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = {
+ F(60000000, P_GCC_GPLL0_OUT_MAIN, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pdm2_clk_src = {
+ .cmd_rcgr = 0x43010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pdm2_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
+ F(7372800, P_GCC_GPLL0_OUT_EVEN, 1, 384, 15625),
+ F(14745600, P_GCC_GPLL0_OUT_EVEN, 1, 768, 15625),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(29491200, P_GCC_GPLL0_OUT_EVEN, 1, 1536, 15625),
+ F(32000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 75),
+ F(48000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 25),
+ F(64000000, P_GCC_GPLL0_OUT_EVEN, 1, 16, 75),
+ F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(80000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 15),
+ F(96000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 25),
+ F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0),
+ F(102400000, P_GCC_GPLL0_OUT_EVEN, 1, 128, 375),
+ F(112000000, P_GCC_GPLL0_OUT_EVEN, 1, 28, 75),
+ F(117964800, P_GCC_GPLL0_OUT_EVEN, 1, 6144, 15625),
+ F(120000000, P_GCC_GPLL0_OUT_EVEN, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = {
+ .cmd_rcgr = 0x27014,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s1_clk_src[] = {
+ F(7372800, P_GCC_GPLL0_OUT_EVEN, 1, 384, 15625),
+ F(14745600, P_GCC_GPLL0_OUT_EVEN, 1, 768, 15625),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(29491200, P_GCC_GPLL0_OUT_EVEN, 1, 1536, 15625),
+ F(32000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 75),
+ F(48000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 25),
+ F(64000000, P_GCC_GPLL0_OUT_EVEN, 1, 16, 75),
+ F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(80000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 15),
+ F(96000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 25),
+ F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0),
+ { }
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = {
+ .cmd_rcgr = 0x27148,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = {
+ .cmd_rcgr = 0x2727c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s3_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = {
+ .cmd_rcgr = 0x273b0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s4_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = {
+ .cmd_rcgr = 0x274e4,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s0_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = {
+ .cmd_rcgr = 0x28014,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s1_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = {
+ .cmd_rcgr = 0x28148,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s2_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = {
+ .cmd_rcgr = 0x2827c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s3_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s3_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = {
+ .cmd_rcgr = 0x283b0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s4_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s4_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = {
+ .cmd_rcgr = 0x284e4,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = {
+ F(144000, P_BI_TCXO, 16, 3, 25),
+ F(400000, P_BI_TCXO, 12, 1, 4),
+ F(20000000, P_GCC_GPLL0_OUT_EVEN, 5, 1, 3),
+ F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0),
+ F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(100000000, P_GCC_GPLL0_OUT_ODD, 2, 0, 0),
+ F(192000000, P_GCC_GPLL10_OUT_MAIN, 2, 0, 0),
+ F(384000000, P_GCC_GPLL10_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0xb3010,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_apps_clk_src",
+ .parent_data = gcc_parent_data_4,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = {
+ F(100000000, P_GCC_GPLL0_OUT_ODD, 2, 0, 0),
+ F(150000000, P_GCC_GPLL0_OUT_EVEN, 2, 0, 0),
+ F(300000000, P_GCC_GPLL0_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = {
+ .cmd_rcgr = 0xb3030,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ice_core_clk_src",
+ .parent_data = gcc_parent_data_4,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
+ F(400000, P_BI_TCXO, 12, 1, 4),
+ F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0),
+ F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0),
+ F(202000000, P_GCC_GPLL9_OUT_MAIN, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
+ .cmd_rcgr = 0x24014,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_6,
+ .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc2_apps_clk_src",
+ .parent_data = gcc_parent_data_6,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_6),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_axi_clk_src[] = {
+ F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0),
+ F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(150000000, P_GCC_GPLL0_OUT_MAIN, 4, 0, 0),
+ F(300000000, P_GCC_GPLL0_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = {
+ .cmd_rcgr = 0x8702c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_axi_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_ice_core_clk_src[] = {
+ F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0),
+ F(200000000, P_GCC_GPLL0_OUT_MAIN, 3, 0, 0),
+ F(403000000, P_GCC_GPLL4_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = {
+ .cmd_rcgr = 0x87074,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_ice_core_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = {
+ .cmd_rcgr = 0x870a8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_5,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_phy_aux_clk_src",
+ .parent_data = gcc_parent_data_5,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_5),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_unipro_core_clk_src[] = {
+ F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(150000000, P_GCC_GPLL0_OUT_MAIN, 4, 0, 0),
+ F(300000000, P_GCC_GPLL0_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = {
+ .cmd_rcgr = 0x8708c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_ufs_phy_unipro_core_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_unipro_core_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = {
+ F(66666667, P_GCC_GPLL0_OUT_EVEN, 4.5, 0, 0),
+ F(133333333, P_GCC_GPLL0_OUT_MAIN, 4.5, 0, 0),
+ F(200000000, P_GCC_GPLL0_OUT_MAIN, 3, 0, 0),
+ F(240000000, P_GCC_GPLL0_OUT_MAIN, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb30_prim_master_clk_src = {
+ .cmd_rcgr = 0x49028,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_prim_master_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_prim_mock_utmi_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x49040,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_prim_mock_utmi_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = {
+ .cmd_rcgr = 0x4906c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_aux_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_video_venus_clk_src[] = {
+ F(133333333, P_GCC_GPLL3_OUT_MAIN, 3, 0, 0),
+ F(240000000, P_GCC_GPLL3_OUT_MAIN, 2, 0, 0),
+ F(365000000, P_GCC_GPLL3_OUT_MAIN, 2, 0, 0),
+ F(384000000, P_GCC_GPLL3_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_video_venus_clk_src = {
+ .cmd_rcgr = 0xb6004,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_11,
+ .freq_tbl = ftbl_gcc_video_venus_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_video_venus_clk_src",
+ .parent_data = gcc_parent_data_11,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_11),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_pcie_0_pipe_div2_clk_src = {
+ .reg = 0x7b084,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_pipe_div2_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_0_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_usb30_prim_mock_utmi_postdiv_clk_src = {
+ .reg = 0x49058,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_prim_mock_utmi_postdiv_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb30_prim_mock_utmi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch gcc_aggre_noc_pcie_0_axi_clk = {
+ .halt_reg = 0x7b08c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x7b08c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(12),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_aggre_noc_pcie_0_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre_ufs_phy_axi_clk = {
+ .halt_reg = 0x870d4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x870d4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x870d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_aggre_ufs_phy_axi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre_ufs_phy_axi_hw_ctl_clk = {
+ .halt_reg = 0x870d4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x870d4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x870d4,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_aggre_ufs_phy_axi_hw_ctl_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre_usb3_prim_axi_clk = {
+ .halt_reg = 0x49088,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x49088,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x49088,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_aggre_usb3_prim_axi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb30_prim_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .halt_reg = 0x48004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x48004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(10),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_boot_rom_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camera_hf_axi_clk = {
+ .halt_reg = 0x36010,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x36010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x36010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_camera_hf_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camera_sf_axi_clk = {
+ .halt_reg = 0x36014,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x36014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x36014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_camera_sf_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_pcie_anoc_ahb_clk = {
+ .halt_reg = 0x20030,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x20030,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(20),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cfg_noc_pcie_anoc_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = {
+ .halt_reg = 0x49084,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x49084,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x49084,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cfg_noc_usb3_prim_axi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb30_prim_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ddrss_gpu_axi_clk = {
+ .halt_reg = 0x81154,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x81154,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x81154,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ddrss_gpu_axi_clk",
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ddrss_pcie_sf_tbu_clk = {
+ .halt_reg = 0x7b090,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x7b090,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(19),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ddrss_pcie_sf_tbu_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_hf_axi_clk = {
+ .halt_reg = 0x3700c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x3700c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3700c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_disp_hf_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_eusb3_0_clkref_en = {
+ .halt_reg = 0x9c00c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x9c00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_eusb3_0_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x74000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x74000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+ .halt_reg = 0x75000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x75000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+ .halt_reg = 0x76000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x76000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_clk_src = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(15),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_gpll0_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_div_clk_src = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(16),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_gpll0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gpll0_out_even.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_memnoc_gfx_clk = {
+ .halt_reg = 0x81010,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x81010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x81010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_memnoc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = {
+ .halt_reg = 0x81018,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x81018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_snoc_dvm_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_hlos1_vote_aggre_noc_mmu_audio_tbu_clk = {
+ .halt_reg = 0x8d004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x8d004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data){
+ .name = "gcc_hlos1_vote_aggre_noc_mmu_audio_tbu_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_hlos1_vote_aggre_noc_mmu_pcie_tbu_clk = {
+ .halt_reg = 0x8d010,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x8d010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data){
+ .name = "gcc_hlos1_vote_aggre_noc_mmu_pcie_tbu_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_hlos1_vote_aggre_noc_mmu_tbu1_clk = {
+ .halt_reg = 0x8d008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x8d008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data){
+ .name = "gcc_hlos1_vote_aggre_noc_mmu_tbu1_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_hlos1_vote_aggre_noc_mmu_tbu2_clk = {
+ .halt_reg = 0x8d00c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x8d00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data){
+ .name = "gcc_hlos1_vote_aggre_noc_mmu_tbu2_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_hlos1_vote_mmnoc_mmu_tbu_hf0_clk = {
+ .halt_reg = 0x8d018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x8d018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data){
+ .name = "gcc_hlos1_vote_mmnoc_mmu_tbu_hf0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_hlos1_vote_mmnoc_mmu_tbu_hf1_clk = {
+ .halt_reg = 0x8d01c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x8d01c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data){
+ .name = "gcc_hlos1_vote_mmnoc_mmu_tbu_hf1_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_hlos1_vote_mmnoc_mmu_tbu_sf0_clk = {
+ .halt_reg = 0x8d014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x8d014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data){
+ .name = "gcc_hlos1_vote_mmnoc_mmu_tbu_sf0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_hlos1_vote_mmu_tcu_clk = {
+ .halt_reg = 0x8d02c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x8d02c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data){
+ .name = "gcc_hlos1_vote_mmu_tcu_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_aux_clk = {
+ .halt_reg = 0x7b034,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(3),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_0_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_cfg_ahb_clk = {
+ .halt_reg = 0x7b030,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7b030,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(2),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_clkref_en = {
+ .halt_reg = 0x9c004,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x9c004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_mstr_axi_clk = {
+ .halt_reg = 0x7b028,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_mstr_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_phy_rchng_clk = {
+ .halt_reg = 0x7b044,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(22),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_phy_rchng_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_0_phy_rchng_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_pipe_clk = {
+ .halt_reg = 0x7b03c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(4),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_pipe_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_0_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_pipe_div2_clk = {
+ .halt_reg = 0x7b094,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x62010,
+ .enable_mask = BIT(26),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_pipe_div2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_0_pipe_div2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_slv_axi_clk = {
+ .halt_reg = 0x7b020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7b020,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_slv_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_slv_q2a_axi_clk = {
+ .halt_reg = 0x7b01c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(5),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_slv_q2a_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+ .halt_reg = 0x4300c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4300c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pdm2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+ .halt_reg = 0x43004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x43004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x43004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_xo4_clk = {
+ .halt_reg = 0x43008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x43008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm_xo4_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_camera_nrt_ahb_clk = {
+ .halt_reg = 0x36008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x36008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x36008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_camera_nrt_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_camera_rt_ahb_clk = {
+ .halt_reg = 0x3600c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x3600c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3600c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_camera_rt_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_disp_ahb_clk = {
+ .halt_reg = 0x37008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x37008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x37008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_disp_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_gpu_ahb_clk = {
+ .halt_reg = 0x81008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x81008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x81008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_gpu_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_pcie_ahb_clk = {
+ .halt_reg = 0x7b018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7b018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7b018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_pcie_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_video_vcodec_ahb_clk = {
+ .halt_reg = 0x42008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x42008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x42008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_video_vcodec_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = {
+ .halt_reg = 0x3300c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(9),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_core_2x_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_core_clk = {
+ .halt_reg = 0x33000,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(8),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s0_clk = {
+ .halt_reg = 0x2700c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(10),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s1_clk = {
+ .halt_reg = 0x27140,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(11),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s2_clk = {
+ .halt_reg = 0x27274,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(12),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s3_clk = {
+ .halt_reg = 0x273a8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(13),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s4_clk = {
+ .halt_reg = 0x274dc,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(14),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s4_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_core_2x_clk = {
+ .halt_reg = 0x3314c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(18),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_core_2x_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_core_clk = {
+ .halt_reg = 0x33140,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(19),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s0_clk = {
+ .halt_reg = 0x2800c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(22),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap1_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s1_clk = {
+ .halt_reg = 0x28140,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(23),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap1_s1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s2_clk = {
+ .halt_reg = 0x28274,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(24),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap1_s2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s3_clk = {
+ .halt_reg = 0x283a8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(25),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap1_s3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s4_clk = {
+ .halt_reg = 0x284dc,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(26),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s4_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap1_s4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = {
+ .halt_reg = 0x27004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x27004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(6),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_0_m_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = {
+ .halt_reg = 0x27008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x27008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(7),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_0_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_1_m_ahb_clk = {
+ .halt_reg = 0x28004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x28004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(20),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_1_m_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_1_s_ahb_clk = {
+ .halt_reg = 0x28008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x28008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(21),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_1_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .halt_reg = 0xb3004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xb3004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0xb3008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xb3008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sdcc1_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ice_core_clk = {
+ .halt_reg = 0xb3028,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0xb3028,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0xb3028,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ice_core_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sdcc1_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+ .halt_reg = 0x2400c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2400c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+ .halt_reg = 0x24004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x24004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc2_apps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sdcc2_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_0_clkref_en = {
+ .halt_reg = 0x9c000,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x9c000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_0_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_pad_clkref_en = {
+ .halt_reg = 0x9c024,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x9c024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_pad_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_ahb_clk = {
+ .halt_reg = 0x87020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x87020,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x87020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_axi_clk = {
+ .halt_reg = 0x87018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x87018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x87018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_axi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_axi_hw_ctl_clk = {
+ .halt_reg = 0x87018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x87018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x87018,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_axi_hw_ctl_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_ice_core_clk = {
+ .halt_reg = 0x8706c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x8706c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x8706c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_ice_core_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_ice_core_hw_ctl_clk = {
+ .halt_reg = 0x8706c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x8706c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x8706c,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_ice_core_hw_ctl_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_phy_aux_clk = {
+ .halt_reg = 0x870a4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x870a4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x870a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_phy_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_phy_aux_hw_ctl_clk = {
+ .halt_reg = 0x870a4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x870a4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x870a4,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_phy_aux_hw_ctl_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = {
+ .halt_reg = 0x87028,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x87028,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_rx_symbol_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_rx_symbol_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_rx_symbol_1_clk = {
+ .halt_reg = 0x870c0,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x870c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_rx_symbol_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_rx_symbol_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = {
+ .halt_reg = 0x87024,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x87024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_tx_symbol_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_tx_symbol_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_unipro_core_clk = {
+ .halt_reg = 0x87064,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x87064,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x87064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_unipro_core_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_unipro_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_unipro_core_hw_ctl_clk = {
+ .halt_reg = 0x87064,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x87064,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x87064,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_unipro_core_hw_ctl_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ufs_phy_unipro_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_prim_master_clk = {
+ .halt_reg = 0x49018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x49018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_prim_master_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb30_prim_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_prim_mock_utmi_clk = {
+ .halt_reg = 0x49024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x49024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_prim_mock_utmi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_prim_sleep_clk = {
+ .halt_reg = 0x49020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x49020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_prim_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_0_clkref_en = {
+ .halt_reg = 0x9c010,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x9c010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_0_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_phy_aux_clk = {
+ .halt_reg = 0x4905c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4905c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb3_prim_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = {
+ .halt_reg = 0x49060,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x49060,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_com_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb3_prim_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_phy_pipe_clk = {
+ .halt_reg = 0x49064,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x49064,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x49064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_pipe_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb3_prim_phy_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_vcodec0_axi_clk = {
+ .halt_reg = 0x42020,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x42020,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x42020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_vcodec0_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_venus_ctl_axi_clk = {
+ .halt_reg = 0x4201c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x4201c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_venus_ctl_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_throttle_core_clk = {
+ .halt_reg = 0x42014,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x42014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x42014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_video_throttle_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_vcodec0_sys_clk = {
+ .halt_reg = 0xb6058,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0xb6058,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0xb6058,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_video_vcodec0_sys_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_video_venus_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_venus_ctl_clk = {
+ .halt_reg = 0xb6038,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xb6038,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_video_venus_ctl_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_video_venus_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc gcc_pcie_0_gdsc = {
+ .gdscr = 0x7b004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_pcie_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | VOTABLE,
+};
+
+static struct gdsc gcc_ufs_phy_gdsc = {
+ .gdscr = 0x87004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_ufs_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gcc_usb30_prim_gdsc = {
+ .gdscr = 0x49004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_usb30_prim_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gcc_vcodec0_gdsc = {
+ .gdscr = 0xb6044,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_vcodec0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL,
+};
+
+static struct gdsc gcc_venus_gdsc = {
+ .gdscr = 0xb6020,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_venus_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct clk_regmap *gcc_sm4450_clocks[] = {
+ [GCC_AGGRE_NOC_PCIE_0_AXI_CLK] = &gcc_aggre_noc_pcie_0_axi_clk.clkr,
+ [GCC_AGGRE_UFS_PHY_AXI_CLK] = &gcc_aggre_ufs_phy_axi_clk.clkr,
+ [GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK] = &gcc_aggre_ufs_phy_axi_hw_ctl_clk.clkr,
+ [GCC_AGGRE_USB3_PRIM_AXI_CLK] = &gcc_aggre_usb3_prim_axi_clk.clkr,
+ [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+ [GCC_CAMERA_HF_AXI_CLK] = &gcc_camera_hf_axi_clk.clkr,
+ [GCC_CAMERA_SF_AXI_CLK] = &gcc_camera_sf_axi_clk.clkr,
+ [GCC_CFG_NOC_PCIE_ANOC_AHB_CLK] = &gcc_cfg_noc_pcie_anoc_ahb_clk.clkr,
+ [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr,
+ [GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr,
+ [GCC_DDRSS_PCIE_SF_TBU_CLK] = &gcc_ddrss_pcie_sf_tbu_clk.clkr,
+ [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr,
+ [GCC_EUSB3_0_CLKREF_EN] = &gcc_eusb3_0_clkref_en.clkr,
+ [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+ [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr,
+ [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+ [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr,
+ [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+ [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr,
+ [GCC_GPLL0] = &gcc_gpll0.clkr,
+ [GCC_GPLL0_OUT_EVEN] = &gcc_gpll0_out_even.clkr,
+ [GCC_GPLL0_OUT_ODD] = &gcc_gpll0_out_odd.clkr,
+ [GCC_GPLL1] = &gcc_gpll1.clkr,
+ [GCC_GPLL3] = &gcc_gpll3.clkr,
+ [GCC_GPLL4] = &gcc_gpll4.clkr,
+ [GCC_GPLL9] = &gcc_gpll9.clkr,
+ [GCC_GPLL10] = &gcc_gpll10.clkr,
+ [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr,
+ [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr,
+ [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr,
+ [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr,
+ [GCC_HLOS1_VOTE_AGGRE_NOC_MMU_AUDIO_TBU_CLK] =
+ &gcc_hlos1_vote_aggre_noc_mmu_audio_tbu_clk.clkr,
+ [GCC_HLOS1_VOTE_AGGRE_NOC_MMU_PCIE_TBU_CLK] =
+ &gcc_hlos1_vote_aggre_noc_mmu_pcie_tbu_clk.clkr,
+ [GCC_HLOS1_VOTE_AGGRE_NOC_MMU_TBU1_CLK] = &gcc_hlos1_vote_aggre_noc_mmu_tbu1_clk.clkr,
+ [GCC_HLOS1_VOTE_AGGRE_NOC_MMU_TBU2_CLK] = &gcc_hlos1_vote_aggre_noc_mmu_tbu2_clk.clkr,
+ [GCC_HLOS1_VOTE_MMNOC_MMU_TBU_HF0_CLK] = &gcc_hlos1_vote_mmnoc_mmu_tbu_hf0_clk.clkr,
+ [GCC_HLOS1_VOTE_MMNOC_MMU_TBU_HF1_CLK] = &gcc_hlos1_vote_mmnoc_mmu_tbu_hf1_clk.clkr,
+ [GCC_HLOS1_VOTE_MMNOC_MMU_TBU_SF0_CLK] = &gcc_hlos1_vote_mmnoc_mmu_tbu_sf0_clk.clkr,
+ [GCC_HLOS1_VOTE_MMU_TCU_CLK] = &gcc_hlos1_vote_mmu_tcu_clk.clkr,
+ [GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr,
+ [GCC_PCIE_0_AUX_CLK_SRC] = &gcc_pcie_0_aux_clk_src.clkr,
+ [GCC_PCIE_0_CFG_AHB_CLK] = &gcc_pcie_0_cfg_ahb_clk.clkr,
+ [GCC_PCIE_0_CLKREF_EN] = &gcc_pcie_0_clkref_en.clkr,
+ [GCC_PCIE_0_MSTR_AXI_CLK] = &gcc_pcie_0_mstr_axi_clk.clkr,
+ [GCC_PCIE_0_PHY_RCHNG_CLK] = &gcc_pcie_0_phy_rchng_clk.clkr,
+ [GCC_PCIE_0_PHY_RCHNG_CLK_SRC] = &gcc_pcie_0_phy_rchng_clk_src.clkr,
+ [GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr,
+ [GCC_PCIE_0_PIPE_CLK_SRC] = &gcc_pcie_0_pipe_clk_src.clkr,
+ [GCC_PCIE_0_PIPE_DIV2_CLK] = &gcc_pcie_0_pipe_div2_clk.clkr,
+ [GCC_PCIE_0_PIPE_DIV2_CLK_SRC] = &gcc_pcie_0_pipe_div2_clk_src.clkr,
+ [GCC_PCIE_0_SLV_AXI_CLK] = &gcc_pcie_0_slv_axi_clk.clkr,
+ [GCC_PCIE_0_SLV_Q2A_AXI_CLK] = &gcc_pcie_0_slv_q2a_axi_clk.clkr,
+ [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+ [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr,
+ [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+ [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr,
+ [GCC_QMIP_CAMERA_NRT_AHB_CLK] = &gcc_qmip_camera_nrt_ahb_clk.clkr,
+ [GCC_QMIP_CAMERA_RT_AHB_CLK] = &gcc_qmip_camera_rt_ahb_clk.clkr,
+ [GCC_QMIP_DISP_AHB_CLK] = &gcc_qmip_disp_ahb_clk.clkr,
+ [GCC_QMIP_GPU_AHB_CLK] = &gcc_qmip_gpu_ahb_clk.clkr,
+ [GCC_QMIP_PCIE_AHB_CLK] = &gcc_qmip_pcie_ahb_clk.clkr,
+ [GCC_QMIP_VIDEO_VCODEC_AHB_CLK] = &gcc_qmip_video_vcodec_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr,
+ [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr,
+ [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr,
+ [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr,
+ [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr,
+ [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr,
+ [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr,
+ [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_CORE_2X_CLK] = &gcc_qupv3_wrap1_core_2x_clk.clkr,
+ [GCC_QUPV3_WRAP1_CORE_CLK] = &gcc_qupv3_wrap1_core_clk.clkr,
+ [GCC_QUPV3_WRAP1_S0_CLK] = &gcc_qupv3_wrap1_s0_clk.clkr,
+ [GCC_QUPV3_WRAP1_S0_CLK_SRC] = &gcc_qupv3_wrap1_s0_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S1_CLK] = &gcc_qupv3_wrap1_s1_clk.clkr,
+ [GCC_QUPV3_WRAP1_S1_CLK_SRC] = &gcc_qupv3_wrap1_s1_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S2_CLK] = &gcc_qupv3_wrap1_s2_clk.clkr,
+ [GCC_QUPV3_WRAP1_S2_CLK_SRC] = &gcc_qupv3_wrap1_s2_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S3_CLK] = &gcc_qupv3_wrap1_s3_clk.clkr,
+ [GCC_QUPV3_WRAP1_S3_CLK_SRC] = &gcc_qupv3_wrap1_s3_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S4_CLK] = &gcc_qupv3_wrap1_s4_clk.clkr,
+ [GCC_QUPV3_WRAP1_S4_CLK_SRC] = &gcc_qupv3_wrap1_s4_clk_src.clkr,
+ [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.clkr,
+ [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK_SRC] = &gcc_sdcc1_ice_core_clk_src.clkr,
+ [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
+ [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+ [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr,
+ [GCC_UFS_0_CLKREF_EN] = &gcc_ufs_0_clkref_en.clkr,
+ [GCC_UFS_PAD_CLKREF_EN] = &gcc_ufs_pad_clkref_en.clkr,
+ [GCC_UFS_PHY_AHB_CLK] = &gcc_ufs_phy_ahb_clk.clkr,
+ [GCC_UFS_PHY_AXI_CLK] = &gcc_ufs_phy_axi_clk.clkr,
+ [GCC_UFS_PHY_AXI_CLK_SRC] = &gcc_ufs_phy_axi_clk_src.clkr,
+ [GCC_UFS_PHY_AXI_HW_CTL_CLK] = &gcc_ufs_phy_axi_hw_ctl_clk.clkr,
+ [GCC_UFS_PHY_ICE_CORE_CLK] = &gcc_ufs_phy_ice_core_clk.clkr,
+ [GCC_UFS_PHY_ICE_CORE_CLK_SRC] = &gcc_ufs_phy_ice_core_clk_src.clkr,
+ [GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK] = &gcc_ufs_phy_ice_core_hw_ctl_clk.clkr,
+ [GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr,
+ [GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr,
+ [GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK] = &gcc_ufs_phy_phy_aux_hw_ctl_clk.clkr,
+ [GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr,
+ [GCC_UFS_PHY_RX_SYMBOL_0_CLK_SRC] = &gcc_ufs_phy_rx_symbol_0_clk_src.clkr,
+ [GCC_UFS_PHY_RX_SYMBOL_1_CLK] = &gcc_ufs_phy_rx_symbol_1_clk.clkr,
+ [GCC_UFS_PHY_RX_SYMBOL_1_CLK_SRC] = &gcc_ufs_phy_rx_symbol_1_clk_src.clkr,
+ [GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr,
+ [GCC_UFS_PHY_TX_SYMBOL_0_CLK_SRC] = &gcc_ufs_phy_tx_symbol_0_clk_src.clkr,
+ [GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr,
+ [GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] = &gcc_ufs_phy_unipro_core_clk_src.clkr,
+ [GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK] = &gcc_ufs_phy_unipro_core_hw_ctl_clk.clkr,
+ [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr,
+ [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr,
+ [GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.clkr,
+ [GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC] = &gcc_usb30_prim_mock_utmi_clk_src.clkr,
+ [GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr,
+ [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr,
+ [GCC_USB3_0_CLKREF_EN] = &gcc_usb3_0_clkref_en.clkr,
+ [GCC_USB3_PRIM_PHY_AUX_CLK] = &gcc_usb3_prim_phy_aux_clk.clkr,
+ [GCC_USB3_PRIM_PHY_AUX_CLK_SRC] = &gcc_usb3_prim_phy_aux_clk_src.clkr,
+ [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.clkr,
+ [GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.clkr,
+ [GCC_USB3_PRIM_PHY_PIPE_CLK_SRC] = &gcc_usb3_prim_phy_pipe_clk_src.clkr,
+ [GCC_VCODEC0_AXI_CLK] = &gcc_vcodec0_axi_clk.clkr,
+ [GCC_VENUS_CTL_AXI_CLK] = &gcc_venus_ctl_axi_clk.clkr,
+ [GCC_VIDEO_THROTTLE_CORE_CLK] = &gcc_video_throttle_core_clk.clkr,
+ [GCC_VIDEO_VCODEC0_SYS_CLK] = &gcc_video_vcodec0_sys_clk.clkr,
+ [GCC_VIDEO_VENUS_CLK_SRC] = &gcc_video_venus_clk_src.clkr,
+ [GCC_VIDEO_VENUS_CTL_CLK] = &gcc_video_venus_ctl_clk.clkr,
+};
+
+static struct gdsc *gcc_sm4450_gdscs[] = {
+ [GCC_PCIE_0_GDSC] = &gcc_pcie_0_gdsc,
+ [GCC_UFS_PHY_GDSC] = &gcc_ufs_phy_gdsc,
+ [GCC_USB30_PRIM_GDSC] = &gcc_usb30_prim_gdsc,
+ [GCC_VCODEC0_GDSC] = &gcc_vcodec0_gdsc,
+ [GCC_VENUS_GDSC] = &gcc_venus_gdsc,
+};
+
+static const struct qcom_reset_map gcc_sm4450_resets[] = {
+ [GCC_CAMERA_BCR] = { 0x36000 },
+ [GCC_DISPLAY_BCR] = { 0x37000 },
+ [GCC_GPU_BCR] = { 0x81000 },
+ [GCC_PCIE_0_BCR] = { 0x7b000 },
+ [GCC_PCIE_0_LINK_DOWN_BCR] = { 0x7c014 },
+ [GCC_PCIE_0_NOCSR_COM_PHY_BCR] = { 0x7c020 },
+ [GCC_PCIE_0_PHY_BCR] = { 0x7c01c },
+ [GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR] = { 0x7c028 },
+ [GCC_PCIE_PHY_BCR] = { 0x7f000 },
+ [GCC_PCIE_PHY_CFG_AHB_BCR] = { 0x7f00c },
+ [GCC_PCIE_PHY_COM_BCR] = { 0x7f010 },
+ [GCC_PDM_BCR] = { 0x43000 },
+ [GCC_QUPV3_WRAPPER_0_BCR] = { 0x27000 },
+ [GCC_QUPV3_WRAPPER_1_BCR] = { 0x28000 },
+ [GCC_QUSB2PHY_PRIM_BCR] = { 0x22000 },
+ [GCC_QUSB2PHY_SEC_BCR] = { 0x22004 },
+ [GCC_SDCC1_BCR] = { 0xb3000 },
+ [GCC_SDCC2_BCR] = { 0x24000 },
+ [GCC_UFS_PHY_BCR] = { 0x87000 },
+ [GCC_USB30_PRIM_BCR] = { 0x49000 },
+ [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x60008 },
+ [GCC_USB3_DP_PHY_SEC_BCR] = { 0x60014 },
+ [GCC_USB3_PHY_PRIM_BCR] = { 0x60000 },
+ [GCC_USB3_PHY_SEC_BCR] = { 0x6000c },
+ [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x60004 },
+ [GCC_USB3PHY_PHY_SEC_BCR] = { 0x60010 },
+ [GCC_VCODEC0_BCR] = { 0xb6040 },
+ [GCC_VENUS_BCR] = { 0xb601c },
+ [GCC_VIDEO_BCR] = { 0x42000 },
+ [GCC_VIDEO_VENUS_BCR] = { 0xb6000 },
+ [GCC_VENUS_CTL_AXI_CLK_ARES] = { 0x4201c, 2 },
+ [GCC_VIDEO_VENUS_CTL_CLK_ARES] = { 0xb6038, 2 },
+};
+
+static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = {
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s0_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s1_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s2_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s3_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s4_clk_src),
+};
+
+static const struct regmap_config gcc_sm4450_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1f41f0,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_sm4450_desc = {
+ .config = &gcc_sm4450_regmap_config,
+ .clks = gcc_sm4450_clocks,
+ .num_clks = ARRAY_SIZE(gcc_sm4450_clocks),
+ .resets = gcc_sm4450_resets,
+ .num_resets = ARRAY_SIZE(gcc_sm4450_resets),
+ .gdscs = gcc_sm4450_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_sm4450_gdscs),
+};
+
+static const struct of_device_id gcc_sm4450_match_table[] = {
+ { .compatible = "qcom,sm4450-gcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_sm4450_match_table);
+
+static int gcc_sm4450_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ regmap = qcom_cc_map(pdev, &gcc_sm4450_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ clk_lucid_evo_pll_configure(&gcc_gpll3, regmap, &gcc_gpll3_config);
+ ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks,
+ ARRAY_SIZE(gcc_dfs_clocks));
+ if (ret)
+ return ret;
+
+ qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true);
+
+ /*
+ * Keep clocks always enabled:
+ * gcc_camera_ahb_clk
+ * gcc_camera_sleep_clk
+ * gcc_camera_xo_clk
+ * gcc_disp_ahb_clk
+ * gcc_disp_xo_clk
+ * gcc_gpu_cfg_ahb_clk
+ * gcc_video_ahb_clk
+ * gcc_video_xo_clk
+ */
+ regmap_update_bits(regmap, 0x36004, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x36018, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x3601c, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x37004, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x37014, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x81004, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x42004, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x42018, BIT(0), BIT(0));
+
+ regmap_update_bits(regmap, 0x4201c, BIT(21), BIT(21));
+
+ return qcom_cc_really_probe(pdev, &gcc_sm4450_desc, regmap);
+}
+
+static struct platform_driver gcc_sm4450_driver = {
+ .probe = gcc_sm4450_probe,
+ .driver = {
+ .name = "gcc-sm4450",
+ .of_match_table = gcc_sm4450_match_table,
+ },
+};
+
+static int __init gcc_sm4450_init(void)
+{
+ return platform_driver_register(&gcc_sm4450_driver);
+}
+subsys_initcall(gcc_sm4450_init);
+
+static void __exit gcc_sm4450_exit(void)
+{
+ platform_driver_unregister(&gcc_sm4450_driver);
+}
+module_exit(gcc_sm4450_exit);
+
+MODULE_DESCRIPTION("QTI GCC SM4450 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/gcc-sm8150.c b/drivers/clk/qcom/gcc-sm8150.c
index 41ab210875fb..05d115c52dfe 100644
--- a/drivers/clk/qcom/gcc-sm8150.c
+++ b/drivers/clk/qcom/gcc-sm8150.c
@@ -774,7 +774,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
.name = "gcc_sdcc2_apps_clk_src",
.parent_data = gcc_parents_6,
.num_parents = ARRAY_SIZE(gcc_parents_6),
- .flags = CLK_SET_RATE_PARENT,
+ .flags = CLK_OPS_PARENT_ENABLE,
.ops = &clk_rcg2_floor_ops,
},
};
diff --git a/drivers/clk/qcom/gpucc-sm8550.c b/drivers/clk/qcom/gpucc-sm8550.c
index 775e0b931923..420dcb27b47d 100644
--- a/drivers/clk/qcom/gpucc-sm8550.c
+++ b/drivers/clk/qcom/gpucc-sm8550.c
@@ -39,8 +39,7 @@ static const struct pll_vco lucid_ole_vco[] = {
};
static const struct alpha_pll_config gpu_cc_pll0_config = {
- /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */
- .l = 0x4444000d,
+ .l = 0x0d,
.alpha = 0x0,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00182261,
@@ -71,8 +70,7 @@ static struct clk_alpha_pll gpu_cc_pll0 = {
};
static const struct alpha_pll_config gpu_cc_pll1_config = {
- /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */
- .l = 0x44440016,
+ .l = 0x16,
.alpha = 0xeaaa,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00182261,
@@ -574,8 +572,8 @@ static int gpu_cc_sm8550_probe(struct platform_device *pdev)
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- clk_lucid_evo_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
- clk_lucid_evo_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
+ clk_lucid_ole_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
+ clk_lucid_ole_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
/*
* Keep clocks always enabled:
diff --git a/drivers/clk/qcom/hfpll.c b/drivers/clk/qcom/hfpll.c
index f4d78003d189..dac27e31ef60 100644
--- a/drivers/clk/qcom/hfpll.c
+++ b/drivers/clk/qcom/hfpll.c
@@ -6,6 +6,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
@@ -31,8 +32,62 @@ static const struct hfpll_data hdata = {
.max_rate = 2900000000UL,
};
+static const struct hfpll_data msm8976_a53 = {
+ .mode_reg = 0x00,
+ .l_reg = 0x04,
+ .m_reg = 0x08,
+ .n_reg = 0x0c,
+ .user_reg = 0x10,
+ .config_reg = 0x14,
+ .config_val = 0x341600,
+ .status_reg = 0x1c,
+ .lock_bit = 16,
+
+ .l_val = 0x35,
+ .user_val = 0x109,
+ .min_rate = 902400000UL,
+ .max_rate = 1478400000UL,
+};
+
+static const struct hfpll_data msm8976_a72 = {
+ .mode_reg = 0x00,
+ .l_reg = 0x04,
+ .m_reg = 0x08,
+ .n_reg = 0x0c,
+ .user_reg = 0x10,
+ .config_reg = 0x14,
+ .config_val = 0x4e0405d,
+ .status_reg = 0x1c,
+ .lock_bit = 16,
+
+ .l_val = 0x3e,
+ .user_val = 0x100109,
+ .min_rate = 940800000UL,
+ .max_rate = 2016000000UL,
+};
+
+static const struct hfpll_data msm8976_cci = {
+ .mode_reg = 0x00,
+ .l_reg = 0x04,
+ .m_reg = 0x08,
+ .n_reg = 0x0c,
+ .user_reg = 0x10,
+ .config_reg = 0x14,
+ .config_val = 0x141400,
+ .status_reg = 0x1c,
+ .lock_bit = 16,
+
+ .l_val = 0x20,
+ .user_val = 0x100109,
+ .min_rate = 556800000UL,
+ .max_rate = 902400000UL,
+};
+
static const struct of_device_id qcom_hfpll_match_table[] = {
- { .compatible = "qcom,hfpll" },
+ { .compatible = "qcom,hfpll", .data = &hdata },
+ { .compatible = "qcom,msm8976-hfpll-a53", .data = &msm8976_a53 },
+ { .compatible = "qcom,msm8976-hfpll-a72", .data = &msm8976_a72 },
+ { .compatible = "qcom,msm8976-hfpll-cci", .data = &msm8976_cci },
{ }
};
MODULE_DEVICE_TABLE(of, qcom_hfpll_match_table);
@@ -83,7 +138,7 @@ static int qcom_hfpll_probe(struct platform_device *pdev)
init.parent_data = &pdata;
- h->d = &hdata;
+ h->d = of_device_get_match_data(&pdev->dev);
h->clkr.hw.init = &init;
spin_lock_init(&h->lock);
diff --git a/drivers/clk/qcom/kpss-xcc.c b/drivers/clk/qcom/kpss-xcc.c
index 97358c98c6c9..23b0b11f0007 100644
--- a/drivers/clk/qcom/kpss-xcc.c
+++ b/drivers/clk/qcom/kpss-xcc.c
@@ -5,10 +5,10 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
@@ -32,20 +32,15 @@ MODULE_DEVICE_TABLE(of, kpss_xcc_match_table);
static int kpss_xcc_driver_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- const struct of_device_id *id;
void __iomem *base;
struct clk_hw *hw;
const char *name;
- id = of_match_device(kpss_xcc_match_table, dev);
- if (!id)
- return -ENODEV;
-
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
- if (id->data) {
+ if (device_get_match_data(&pdev->dev)) {
if (of_property_read_string_index(dev->of_node,
"clock-output-names",
0, &name))
diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
index 410ae8390f1c..ae325f4e1047 100644
--- a/drivers/clk/qcom/krait-cc.c
+++ b/drivers/clk/qcom/krait-cc.c
@@ -5,10 +5,10 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/slab.h>
@@ -347,22 +347,18 @@ MODULE_DEVICE_TABLE(of, krait_cc_match_table);
static int krait_cc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- const struct of_device_id *id;
unsigned long cur_rate, aux_rate;
int cpu;
struct clk_hw *mux, *l2_pri_mux;
struct clk *clk, **clks;
-
- id = of_match_device(krait_cc_match_table, dev);
- if (!id)
- return -ENODEV;
+ bool unique_aux = !!device_get_match_data(dev);
/* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */
clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, 1);
if (IS_ERR(clk))
return PTR_ERR(clk);
- if (!id->data) {
+ if (!unique_aux) {
clk = clk_register_fixed_factor(dev, "acpu_aux",
"gpll0_vote", 0, 1, 2);
if (IS_ERR(clk))
@@ -375,13 +371,13 @@ static int krait_cc_probe(struct platform_device *pdev)
return -ENOMEM;
for_each_possible_cpu(cpu) {
- mux = krait_add_clks(dev, cpu, id->data);
+ mux = krait_add_clks(dev, cpu, unique_aux);
if (IS_ERR(mux))
return PTR_ERR(mux);
clks[cpu] = mux->clk;
}
- l2_pri_mux = krait_add_clks(dev, -1, id->data);
+ l2_pri_mux = krait_add_clks(dev, -1, unique_aux);
if (IS_ERR(l2_pri_mux))
return PTR_ERR(l2_pri_mux);
clks[l2_mux] = l2_pri_mux->clk;
diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c
index 6bf908a51f53..50638ab341ec 100644
--- a/drivers/clk/qcom/mmcc-msm8960.c
+++ b/drivers/clk/qcom/mmcc-msm8960.c
@@ -8,9 +8,9 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
@@ -3105,30 +3105,24 @@ MODULE_DEVICE_TABLE(of, mmcc_msm8960_match_table);
static int mmcc_msm8960_probe(struct platform_device *pdev)
{
- const struct of_device_id *match;
struct regmap *regmap;
- bool is_8064;
struct device *dev = &pdev->dev;
+ const struct qcom_cc_desc *desc = device_get_match_data(dev);
- match = of_match_device(mmcc_msm8960_match_table, dev);
- if (!match)
- return -EINVAL;
-
- is_8064 = of_device_is_compatible(dev->of_node, "qcom,mmcc-apq8064");
- if (is_8064) {
+ if (desc == &mmcc_apq8064_desc) {
gfx3d_src.freq_tbl = clk_tbl_gfx3d_8064;
gfx3d_src.clkr.hw.init = &gfx3d_8064_init;
gfx3d_src.s[0].parent_map = mmcc_pxo_pll8_pll2_pll15_map;
gfx3d_src.s[1].parent_map = mmcc_pxo_pll8_pll2_pll15_map;
}
- regmap = qcom_cc_map(pdev, match->data);
+ regmap = qcom_cc_map(pdev, desc);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
clk_pll_configure_sr(&pll15, regmap, &pll15_config, false);
- return qcom_cc_really_probe(pdev, match->data, regmap);
+ return qcom_cc_really_probe(pdev, desc, regmap);
}
static struct platform_driver mmcc_msm8960_driver = {
diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c
index 1f3bd302fe6e..a31f6cf0c4e0 100644
--- a/drivers/clk/qcom/mmcc-msm8974.c
+++ b/drivers/clk/qcom/mmcc-msm8974.c
@@ -2170,22 +2170,6 @@ static struct clk_branch mmss_s0_axi_clk = {
},
};
-static struct clk_branch ocmemcx_ahb_clk = {
- .halt_reg = 0x405c,
- .clkr = {
- .enable_reg = 0x405c,
- .enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data){
- .name = "ocmemcx_ahb_clk",
- .parent_hws = (const struct clk_hw*[]){
- &mmss_ahb_clk_src.clkr.hw
- },
- .num_parents = 1,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch ocmemcx_ocmemnoc_clk = {
.halt_reg = 0x4058,
.clkr = {
@@ -2503,7 +2487,6 @@ static struct clk_regmap *mmcc_msm8226_clocks[] = {
[MMSS_MMSSNOC_BTO_AHB_CLK] = &mmss_mmssnoc_bto_ahb_clk.clkr,
[MMSS_MMSSNOC_AXI_CLK] = &mmss_mmssnoc_axi_clk.clkr,
[MMSS_S0_AXI_CLK] = &mmss_s0_axi_clk.clkr,
- [OCMEMCX_AHB_CLK] = &ocmemcx_ahb_clk.clkr,
[OXILI_GFX3D_CLK] = &oxili_gfx3d_clk.clkr,
[OXILICX_AHB_CLK] = &oxilicx_ahb_clk.clkr,
[OXILICX_AXI_CLK] = &oxilicx_axi_clk.clkr,
@@ -2660,7 +2643,6 @@ static struct clk_regmap *mmcc_msm8974_clocks[] = {
[MMSS_MMSSNOC_BTO_AHB_CLK] = &mmss_mmssnoc_bto_ahb_clk.clkr,
[MMSS_MMSSNOC_AXI_CLK] = &mmss_mmssnoc_axi_clk.clkr,
[MMSS_S0_AXI_CLK] = &mmss_s0_axi_clk.clkr,
- [OCMEMCX_AHB_CLK] = &ocmemcx_ahb_clk.clkr,
[OCMEMCX_OCMEMNOC_CLK] = &ocmemcx_ocmemnoc_clk.clkr,
[OCMEMNOC_CLK] = &ocmemnoc_clk.clkr,
[OXILI_GFX3D_CLK] = &oxili_gfx3d_clk.clkr,
diff --git a/drivers/clk/qcom/mmcc-msm8998.c b/drivers/clk/qcom/mmcc-msm8998.c
index a023c4374be9..1180e48c687a 100644
--- a/drivers/clk/qcom/mmcc-msm8998.c
+++ b/drivers/clk/qcom/mmcc-msm8998.c
@@ -2439,6 +2439,7 @@ static struct clk_branch fd_ahb_clk = {
static struct clk_branch mnoc_ahb_clk = {
.halt_reg = 0x5024,
+ .halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x5024,
.enable_mask = BIT(0),
@@ -2454,6 +2455,7 @@ static struct clk_branch mnoc_ahb_clk = {
static struct clk_branch bimc_smmu_ahb_clk = {
.halt_reg = 0xe004,
+ .halt_check = BRANCH_HALT_SKIP,
.hwcg_reg = 0xe004,
.hwcg_bit = 1,
.clkr = {
@@ -2471,6 +2473,7 @@ static struct clk_branch bimc_smmu_ahb_clk = {
static struct clk_branch bimc_smmu_axi_clk = {
.halt_reg = 0xe008,
+ .halt_check = BRANCH_HALT_SKIP,
.hwcg_reg = 0xe008,
.hwcg_bit = 1,
.clkr = {
@@ -2607,11 +2610,13 @@ static struct gdsc camss_cpp_gdsc = {
static struct gdsc bimc_smmu_gdsc = {
.gdscr = 0xe020,
.gds_hw_ctrl = 0xe024,
+ .cxcs = (unsigned int []){ 0xe008 },
+ .cxc_count = 1,
.pd = {
.name = "bimc_smmu",
},
.pwrsts = PWRSTS_OFF_ON,
- .flags = HW_CTRL | ALWAYS_ON,
+ .flags = VOTABLE,
};
static struct clk_regmap *mmcc_msm8998_clocks[] = {
diff --git a/drivers/clk/qcom/mmcc-sdm660.c b/drivers/clk/qcom/mmcc-sdm660.c
index bc19a23e13f8..996bd01fb9ac 100644
--- a/drivers/clk/qcom/mmcc-sdm660.c
+++ b/drivers/clk/qcom/mmcc-sdm660.c
@@ -9,9 +9,9 @@
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include <linux/reset-controller.h>
@@ -2828,14 +2828,10 @@ static void sdm630_clock_override(void)
static int mmcc_660_probe(struct platform_device *pdev)
{
- const struct of_device_id *id;
struct regmap *regmap;
bool is_sdm630;
- id = of_match_device(mmcc_660_match_table, &pdev->dev);
- if (!id)
- return -ENODEV;
- is_sdm630 = !!(id->data);
+ is_sdm630 = !!device_get_match_data(&pdev->dev);
regmap = qcom_cc_map(pdev, &mmcc_660_desc);
if (IS_ERR(regmap))
diff --git a/drivers/clk/qcom/videocc-sm8550.c b/drivers/clk/qcom/videocc-sm8550.c
index 3bb136ec31b1..f3c9dfaee968 100644
--- a/drivers/clk/qcom/videocc-sm8550.c
+++ b/drivers/clk/qcom/videocc-sm8550.c
@@ -36,8 +36,7 @@ static const struct pll_vco lucid_ole_vco[] = {
};
static const struct alpha_pll_config video_cc_pll0_config = {
- /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */
- .l = 0x44440025,
+ .l = 0x25,
.alpha = 0x8000,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00182261,
@@ -68,8 +67,7 @@ static struct clk_alpha_pll video_cc_pll0 = {
};
static const struct alpha_pll_config video_cc_pll1_config = {
- /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */
- .l = 0x44440036,
+ .l = 0x36,
.alpha = 0xb000,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00182261,
@@ -427,8 +425,8 @@ static int video_cc_sm8550_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
}
- clk_lucid_evo_pll_configure(&video_cc_pll0, regmap, &video_cc_pll0_config);
- clk_lucid_evo_pll_configure(&video_cc_pll1, regmap, &video_cc_pll1_config);
+ clk_lucid_ole_pll_configure(&video_cc_pll0, regmap, &video_cc_pll0_config);
+ clk_lucid_ole_pll_configure(&video_cc_pll1, regmap, &video_cc_pll1_config);
/*
* Keep clocks always enabled:
diff --git a/drivers/clk/ralink/clk-mtmips.c b/drivers/clk/ralink/clk-mtmips.c
index 1e7991439527..50a443bf79ec 100644
--- a/drivers/clk/ralink/clk-mtmips.c
+++ b/drivers/clk/ralink/clk-mtmips.c
@@ -822,6 +822,10 @@ static const struct mtmips_clk_data mt76x8_clk_data = {
static const struct of_device_id mtmips_of_match[] = {
{
+ .compatible = "ralink,rt2880-reset",
+ .data = NULL,
+ },
+ {
.compatible = "ralink,rt2880-sysc",
.data = &rt2880_clk_data,
},
@@ -1088,25 +1092,11 @@ static int mtmips_clk_probe(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id mtmips_clk_of_match[] = {
- { .compatible = "ralink,rt2880-reset" },
- { .compatible = "ralink,rt2880-sysc" },
- { .compatible = "ralink,rt3050-sysc" },
- { .compatible = "ralink,rt3052-sysc" },
- { .compatible = "ralink,rt3352-sysc" },
- { .compatible = "ralink,rt3883-sysc" },
- { .compatible = "ralink,rt5350-sysc" },
- { .compatible = "ralink,mt7620-sysc" },
- { .compatible = "ralink,mt7628-sysc" },
- { .compatible = "ralink,mt7688-sysc" },
- {}
-};
-
static struct platform_driver mtmips_clk_driver = {
.probe = mtmips_clk_probe,
.driver = {
.name = "mtmips-clk",
- .of_match_table = mtmips_clk_of_match,
+ .of_match_table = mtmips_of_match,
},
};
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
index 37632a0659d8..69396e197959 100644
--- a/drivers/clk/renesas/Kconfig
+++ b/drivers/clk/renesas/Kconfig
@@ -37,6 +37,7 @@ config CLK_RENESAS
select CLK_R9A07G043 if ARCH_R9A07G043
select CLK_R9A07G044 if ARCH_R9A07G044
select CLK_R9A07G054 if ARCH_R9A07G054
+ select CLK_R9A08G045 if ARCH_R9A08G045
select CLK_R9A09G011 if ARCH_R9A09G011
select CLK_SH73A0 if ARCH_SH73A0
@@ -179,6 +180,10 @@ config CLK_R9A07G054
bool "RZ/V2L clock support" if COMPILE_TEST
select CLK_RZG2L
+config CLK_R9A08G045
+ bool "RZ/G3S clock support" if COMPILE_TEST
+ select CLK_RZG2L
+
config CLK_R9A09G011
bool "RZ/V2M clock support" if COMPILE_TEST
select CLK_RZG2L
@@ -215,7 +220,7 @@ config CLK_RCAR_USB2_CLOCK_SEL
This is a driver for R-Car USB2 clock selector
config CLK_RZG2L
- bool "Renesas RZ/{G2L,G2UL,V2L} family clock support" if COMPILE_TEST
+ bool "Renesas RZ/{G2L,G2UL,G3S,V2L} family clock support" if COMPILE_TEST
select RESET_CONTROLLER
# Generic
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
index de907623fe3f..879a07d445f9 100644
--- a/drivers/clk/renesas/Makefile
+++ b/drivers/clk/renesas/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o
obj-$(CONFIG_CLK_R9A07G043) += r9a07g043-cpg.o
obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o
obj-$(CONFIG_CLK_R9A07G054) += r9a07g044-cpg.o
+obj-$(CONFIG_CLK_R9A08G045) += r9a08g045-cpg.o
obj-$(CONFIG_CLK_R9A09G011) += r9a09g011-cpg.o
obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o
diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c
index ad20b3301ef6..e47d9b1fcc0a 100644
--- a/drivers/clk/renesas/r8a7795-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c
@@ -51,7 +51,7 @@ enum clk_ids {
MOD_CLK_BASE
};
-static struct cpg_core_clk r8a7795_core_clks[] __initdata = {
+static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
/* External Clock Inputs */
DEF_INPUT("extal", CLK_EXTAL),
DEF_INPUT("extalr", CLK_EXTALR),
@@ -128,7 +128,7 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = {
DEF_BASE("r", R8A7795_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
};
-static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
+static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
DEF_MOD("3dge", 112, R8A7795_CLK_ZG),
DEF_MOD("fdp1-1", 118, R8A7795_CLK_S0D1),
DEF_MOD("fdp1-0", 119, R8A7795_CLK_S0D1),
diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c
index 55db63c7041a..c1348e2d450c 100644
--- a/drivers/clk/renesas/r9a06g032-clocks.c
+++ b/drivers/clk/renesas/r9a06g032-clocks.c
@@ -102,19 +102,22 @@ enum gate_type {
* @source: the ID+1 of the parent clock element.
* Root clock uses ID of ~0 (PARENT_ID);
* @gate: clock enable/disable
- * @div_min: smallest permitted clock divider
- * @div_max: largest permitted clock divider
- * @reg: clock divider register offset, in 32-bit words
- * @div_table: optional list of fixed clock divider values;
+ * @div: substructure for clock divider
+ * @div.min: smallest permitted clock divider
+ * @div.max: largest permitted clock divider
+ * @div.reg: clock divider register offset, in 32-bit words
+ * @div.table: optional list of fixed clock divider values;
* must be in ascending order, zero for unused
- * @div: divisor for fixed-factor clock
- * @mul: multiplier for fixed-factor clock
- * @group: UART group, 0=UART0/1/2, 1=UART3/4/5/6/7
- * @sel: select either g1/r1 or g2/r2 as clock source
- * @g1: 1st source gate (clock enable/disable)
- * @r1: 1st source reset (module reset)
- * @g2: 2nd source gate (clock enable/disable)
- * @r2: 2nd source reset (module reset)
+ * @ffc: substructure for fixed-factor clocks
+ * @ffc.div: divisor for fixed-factor clock
+ * @ffc.mul: multiplier for fixed-factor clock
+ * @dual: substructure for dual clock gates
+ * @dual.group: UART group, 0=UART0/1/2, 1=UART3/4/5/6/7
+ * @dual.sel: select either g1/r1 or g2/r2 as clock source
+ * @dual.g1: 1st source gate (clock enable/disable)
+ * @dual.r1: 1st source reset (module reset)
+ * @dual.g2: 2nd source gate (clock enable/disable)
+ * @dual.r2: 2nd source reset (module reset)
*
* Describes a single element in the clock tree hierarchy.
* As there are quite a large number of clock elements, this
@@ -131,13 +134,13 @@ struct r9a06g032_clkdesc {
struct r9a06g032_gate gate;
/* type = K_DIV */
struct {
- unsigned int div_min:10, div_max:10, reg:10;
- u16 div_table[4];
- };
+ unsigned int min:10, max:10, reg:10;
+ u16 table[4];
+ } div;
/* type = K_FFC */
struct {
u16 div, mul;
- };
+ } ffc;
/* type = K_DUALGATE */
struct {
uint16_t group:1;
@@ -178,26 +181,26 @@ struct r9a06g032_clkdesc {
.type = K_FFC, \
.index = R9A06G032_##_idx, \
.name = _n, \
- .div = _div, \
- .mul = _mul \
+ .ffc.div = _div, \
+ .ffc.mul = _mul \
}
#define D_FFC(_idx, _n, _src, _div) { \
.type = K_FFC, \
.index = R9A06G032_##_idx, \
.source = 1 + R9A06G032_##_src, \
.name = _n, \
- .div = _div, \
- .mul = 1 \
+ .ffc.div = _div, \
+ .ffc.mul = 1 \
}
#define D_DIV(_idx, _n, _src, _reg, _min, _max, ...) { \
.type = K_DIV, \
.index = R9A06G032_##_idx, \
.source = 1 + R9A06G032_##_src, \
.name = _n, \
- .reg = _reg, \
- .div_min = _min, \
- .div_max = _max, \
- .div_table = { __VA_ARGS__ } \
+ .div.reg = _reg, \
+ .div.min = _min, \
+ .div.max = _max, \
+ .div.table = { __VA_ARGS__ } \
}
#define D_UGATE(_idx, _n, _src, _g, _g1, _r1, _g2, _r2) { \
.type = K_DUALGATE, \
@@ -1063,14 +1066,14 @@ r9a06g032_register_div(struct r9a06g032_priv *clocks,
div->clocks = clocks;
div->index = desc->index;
- div->reg = desc->reg;
+ div->reg = desc->div.reg;
div->hw.init = &init;
- div->min = desc->div_min;
- div->max = desc->div_max;
+ div->min = desc->div.min;
+ div->max = desc->div.max;
/* populate (optional) divider table fixed values */
for (i = 0; i < ARRAY_SIZE(div->table) &&
- i < ARRAY_SIZE(desc->div_table) && desc->div_table[i]; i++) {
- div->table[div->table_size++] = desc->div_table[i];
+ i < ARRAY_SIZE(desc->div.table) && desc->div.table[i]; i++) {
+ div->table[div->table_size++] = desc->div.table[i];
}
clk = clk_register(NULL, &div->hw);
@@ -1269,11 +1272,10 @@ static void r9a06g032_clocks_del_clk_provider(void *data)
static void __init r9a06g032_init_h2mode(struct r9a06g032_priv *clocks)
{
- struct device_node *usbf_np = NULL;
+ struct device_node *usbf_np;
u32 usb;
- while ((usbf_np = of_find_compatible_node(usbf_np, NULL,
- "renesas,rzn1-usbf"))) {
+ for_each_compatible_node(usbf_np, NULL, "renesas,rzn1-usbf") {
if (of_device_is_available(usbf_np))
break;
}
@@ -1333,7 +1335,8 @@ static int __init r9a06g032_clocks_probe(struct platform_device *pdev)
case K_FFC:
clk = clk_register_fixed_factor(NULL, d->name,
parent_name, 0,
- d->mul, d->div);
+ d->ffc.mul,
+ d->ffc.div);
break;
case K_GATE:
clk = r9a06g032_register_gate(clocks, parent_name, d);
diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c
index 1a7a6d60aca4..b70bb378ab46 100644
--- a/drivers/clk/renesas/r9a07g043-cpg.c
+++ b/drivers/clk/renesas/r9a07g043-cpg.c
@@ -14,6 +14,17 @@
#include "rzg2l-cpg.h"
+/* Specific registers. */
+#define CPG_PL2SDHI_DSEL (0x218)
+
+/* Clock select configuration. */
+#define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2)
+#define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2)
+
+/* Clock status configuration. */
+#define SEL_SDHI0_STS SEL_PLL_PACK(CPG_CLKSTATUS, 28, 1)
+#define SEL_SDHI1_STS SEL_PLL_PACK(CPG_CLKSTATUS, 29, 1)
+
enum clk_ids {
/* Core Clock Outputs exported to DT */
LAST_DT_CORE_CLK = R9A07G043_CLK_P0_DIV2,
@@ -78,6 +89,8 @@ static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" };
static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
+static const u32 mtable_sdhi[] = { 1, 2, 3 };
+
static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = {
/* External Clock Inputs */
DEF_INPUT("extal", CLK_EXTAL),
@@ -123,8 +136,10 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = {
DEF_MUX("HP", R9A07G043_CLK_HP, SEL_PLL6_2, sel_pll6_2),
DEF_FIXED("SPI0", R9A07G043_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2),
DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
- DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, sel_shdi),
- DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, sel_shdi),
+ DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4),
DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4),
};
diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c
index c597414a94d8..1047278c9079 100644
--- a/drivers/clk/renesas/r9a07g044-cpg.c
+++ b/drivers/clk/renesas/r9a07g044-cpg.c
@@ -15,6 +15,17 @@
#include "rzg2l-cpg.h"
+/* Specific registers. */
+#define CPG_PL2SDHI_DSEL (0x218)
+
+/* Clock select configuration. */
+#define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2)
+#define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2)
+
+/* Clock status configuration. */
+#define SEL_SDHI0_STS SEL_PLL_PACK(CPG_CLKSTATUS, 28, 1)
+#define SEL_SDHI1_STS SEL_PLL_PACK(CPG_CLKSTATUS, 29, 1)
+
enum clk_ids {
/* Core Clock Outputs exported to DT */
LAST_DT_CORE_CLK = R9A07G054_CLK_DRP_A,
@@ -98,6 +109,8 @@ static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" };
+static const u32 mtable_sdhi[] = { 1, 2, 3 };
+
static const struct {
struct cpg_core_clk common[56];
#ifdef CONFIG_CLK_R9A07G054
@@ -163,8 +176,10 @@ static const struct {
DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, sel_pll6_2),
DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2),
DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
- DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, sel_shdi),
- DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, sel_shdi),
+ DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4),
DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4),
DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8),
diff --git a/drivers/clk/renesas/r9a08g045-cpg.c b/drivers/clk/renesas/r9a08g045-cpg.c
new file mode 100644
index 000000000000..4394cb241d99
--- /dev/null
+++ b/drivers/clk/renesas/r9a08g045-cpg.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/G3S CPG driver
+ *
+ * Copyright (C) 2023 Renesas Electronics Corp.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/clock/r9a08g045-cpg.h>
+
+#include "rzg2l-cpg.h"
+
+/* RZ/G3S Specific registers. */
+#define G3S_CPG_PL2_DDIV (0x204)
+#define G3S_CPG_SDHI_DDIV (0x218)
+#define G3S_CPG_PLL_DSEL (0x240)
+#define G3S_CPG_SDHI_DSEL (0x244)
+#define G3S_CLKDIVSTATUS (0x280)
+#define G3S_CLKSELSTATUS (0x284)
+
+/* RZ/G3S Specific division configuration. */
+#define G3S_DIVPL2B DDIV_PACK(G3S_CPG_PL2_DDIV, 4, 3)
+#define G3S_DIV_SDHI0 DDIV_PACK(G3S_CPG_SDHI_DDIV, 0, 1)
+#define G3S_DIV_SDHI1 DDIV_PACK(G3S_CPG_SDHI_DDIV, 4, 1)
+#define G3S_DIV_SDHI2 DDIV_PACK(G3S_CPG_SDHI_DDIV, 8, 1)
+
+/* RZ/G3S Clock status configuration. */
+#define G3S_DIVPL1A_STS DDIV_PACK(G3S_CLKDIVSTATUS, 0, 1)
+#define G3S_DIVPL2B_STS DDIV_PACK(G3S_CLKDIVSTATUS, 5, 1)
+#define G3S_DIVPL3A_STS DDIV_PACK(G3S_CLKDIVSTATUS, 8, 1)
+#define G3S_DIVPL3B_STS DDIV_PACK(G3S_CLKDIVSTATUS, 9, 1)
+#define G3S_DIVPL3C_STS DDIV_PACK(G3S_CLKDIVSTATUS, 10, 1)
+#define G3S_DIV_SDHI0_STS DDIV_PACK(G3S_CLKDIVSTATUS, 24, 1)
+#define G3S_DIV_SDHI1_STS DDIV_PACK(G3S_CLKDIVSTATUS, 25, 1)
+#define G3S_DIV_SDHI2_STS DDIV_PACK(G3S_CLKDIVSTATUS, 26, 1)
+
+#define G3S_SEL_PLL4_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 6, 1)
+#define G3S_SEL_SDHI0_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 16, 1)
+#define G3S_SEL_SDHI1_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 17, 1)
+#define G3S_SEL_SDHI2_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 18, 1)
+
+/* RZ/G3S Specific clocks select. */
+#define G3S_SEL_PLL4 SEL_PLL_PACK(G3S_CPG_PLL_DSEL, 6, 1)
+#define G3S_SEL_SDHI0 SEL_PLL_PACK(G3S_CPG_SDHI_DSEL, 0, 2)
+#define G3S_SEL_SDHI1 SEL_PLL_PACK(G3S_CPG_SDHI_DSEL, 4, 2)
+#define G3S_SEL_SDHI2 SEL_PLL_PACK(G3S_CPG_SDHI_DSEL, 8, 2)
+
+/* PLL 1/4/6 configuration registers macro. */
+#define G3S_PLL146_CONF(clk1, clk2) ((clk1) << 22 | (clk2) << 12)
+
+#define DEF_G3S_MUX(_name, _id, _conf, _parent_names, _mux_flags, _clk_flags) \
+ DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = (_conf), \
+ .parent_names = (_parent_names), \
+ .num_parents = ARRAY_SIZE((_parent_names)), \
+ .mux_flags = CLK_MUX_HIWORD_MASK | (_mux_flags), \
+ .flag = (_clk_flags))
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A08G045_SWD,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_OSC_DIV1000,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL2_DIV2,
+ CLK_PLL2_DIV2_8,
+ CLK_PLL2_DIV6,
+ CLK_PLL3,
+ CLK_PLL3_DIV2,
+ CLK_PLL3_DIV2_4,
+ CLK_PLL3_DIV2_8,
+ CLK_PLL3_DIV6,
+ CLK_PLL4,
+ CLK_PLL6,
+ CLK_PLL6_DIV2,
+ CLK_SEL_SDHI0,
+ CLK_SEL_SDHI1,
+ CLK_SEL_SDHI2,
+ CLK_SEL_PLL4,
+ CLK_P1_DIV2,
+ CLK_P3_DIV2,
+ CLK_SD0_DIV4,
+ CLK_SD1_DIV4,
+ CLK_SD2_DIV4,
+
+ /* Module Clocks */
+ MOD_CLK_BASE,
+};
+
+/* Divider tables */
+static const struct clk_div_table dtable_1_2[] = {
+ { 0, 1 },
+ { 1, 2 },
+ { 0, 0 },
+};
+
+static const struct clk_div_table dtable_1_8[] = {
+ { 0, 1 },
+ { 1, 2 },
+ { 2, 4 },
+ { 3, 8 },
+ { 0, 0 },
+};
+
+static const struct clk_div_table dtable_1_32[] = {
+ { 0, 1 },
+ { 1, 2 },
+ { 2, 4 },
+ { 3, 8 },
+ { 4, 32 },
+ { 0, 0 },
+};
+
+/* Mux clock names tables. */
+static const char * const sel_sdhi[] = { ".pll2_div2", ".pll6", ".pll2_div6" };
+static const char * const sel_pll4[] = { ".osc_div1000", ".pll4" };
+
+/* Mux clock indices tables. */
+static const u32 mtable_sd[] = { 0, 2, 3 };
+static const u32 mtable_pll4[] = { 0, 1 };
+
+static const struct cpg_core_clk r9a08g045_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000),
+ DEF_G3S_PLL(".pll1", CLK_PLL1, CLK_EXTAL, G3S_PLL146_CONF(0x4, 0x8)),
+ DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 200, 3),
+ DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3),
+ DEF_FIXED(".pll4", CLK_PLL4, CLK_EXTAL, 100, 3),
+ DEF_FIXED(".pll6", CLK_PLL6, CLK_EXTAL, 125, 6),
+ DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2),
+ DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8),
+ DEF_FIXED(".pll2_div6", CLK_PLL2_DIV6, CLK_PLL2, 1, 6),
+ DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2),
+ DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4),
+ DEF_FIXED(".pll3_div2_8", CLK_PLL3_DIV2_8, CLK_PLL3_DIV2, 1, 8),
+ DEF_FIXED(".pll3_div6", CLK_PLL3_DIV6, CLK_PLL3, 1, 6),
+ DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 1, 2),
+ DEF_SD_MUX(".sel_sd0", CLK_SEL_SDHI0, G3S_SEL_SDHI0, G3S_SEL_SDHI0_STS, sel_sdhi,
+ mtable_sd, 0, NULL),
+ DEF_SD_MUX(".sel_sd1", CLK_SEL_SDHI1, G3S_SEL_SDHI1, G3S_SEL_SDHI1_STS, sel_sdhi,
+ mtable_sd, 0, NULL),
+ DEF_SD_MUX(".sel_sd2", CLK_SEL_SDHI2, G3S_SEL_SDHI2, G3S_SEL_SDHI2_STS, sel_sdhi,
+ mtable_sd, 0, NULL),
+ DEF_SD_MUX(".sel_pll4", CLK_SEL_PLL4, G3S_SEL_PLL4, G3S_SEL_PLL4_STS, sel_pll4,
+ mtable_pll4, CLK_SET_PARENT_GATE, NULL),
+
+ /* Core output clk */
+ DEF_G3S_DIV("I", R9A08G045_CLK_I, CLK_PLL1, DIVPL1A, G3S_DIVPL1A_STS, dtable_1_8,
+ 0, 0, 0, NULL),
+ DEF_G3S_DIV("P0", R9A08G045_CLK_P0, CLK_PLL2_DIV2_8, G3S_DIVPL2B, G3S_DIVPL2B_STS,
+ dtable_1_32, 0, 0, 0, NULL),
+ DEF_G3S_DIV("SD0", R9A08G045_CLK_SD0, CLK_SEL_SDHI0, G3S_DIV_SDHI0, G3S_DIV_SDHI0_STS,
+ dtable_1_2, 800000000UL, 500000000UL, CLK_SET_RATE_PARENT,
+ rzg3s_cpg_div_clk_notifier),
+ DEF_G3S_DIV("SD1", R9A08G045_CLK_SD1, CLK_SEL_SDHI1, G3S_DIV_SDHI1, G3S_DIV_SDHI1_STS,
+ dtable_1_2, 800000000UL, 500000000UL, CLK_SET_RATE_PARENT,
+ rzg3s_cpg_div_clk_notifier),
+ DEF_G3S_DIV("SD2", R9A08G045_CLK_SD2, CLK_SEL_SDHI2, G3S_DIV_SDHI2, G3S_DIV_SDHI2_STS,
+ dtable_1_2, 800000000UL, 500000000UL, CLK_SET_RATE_PARENT,
+ rzg3s_cpg_div_clk_notifier),
+ DEF_FIXED(".sd0_div4", CLK_SD0_DIV4, R9A08G045_CLK_SD0, 1, 4),
+ DEF_FIXED(".sd1_div4", CLK_SD1_DIV4, R9A08G045_CLK_SD1, 1, 4),
+ DEF_FIXED(".sd2_div4", CLK_SD2_DIV4, R9A08G045_CLK_SD2, 1, 4),
+ DEF_FIXED("M0", R9A08G045_CLK_M0, CLK_PLL3_DIV2_4, 1, 1),
+ DEF_G3S_DIV("P1", R9A08G045_CLK_P1, CLK_PLL3_DIV2_4, DIVPL3A, G3S_DIVPL3A_STS,
+ dtable_1_32, 0, 0, 0, NULL),
+ DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A08G045_CLK_P1, 1, 2),
+ DEF_G3S_DIV("P2", R9A08G045_CLK_P2, CLK_PLL3_DIV2_8, DIVPL3B, G3S_DIVPL3B_STS,
+ dtable_1_32, 0, 0, 0, NULL),
+ DEF_G3S_DIV("P3", R9A08G045_CLK_P3, CLK_PLL3_DIV2_4, DIVPL3C, G3S_DIVPL3C_STS,
+ dtable_1_32, 0, 0, 0, NULL),
+ DEF_FIXED("P3_DIV2", CLK_P3_DIV2, R9A08G045_CLK_P3, 1, 2),
+ DEF_FIXED("S0", R9A08G045_CLK_S0, CLK_SEL_PLL4, 1, 2),
+ DEF_FIXED("OSC", R9A08G045_OSCCLK, CLK_EXTAL, 1, 1),
+ DEF_FIXED("OSC2", R9A08G045_OSCCLK2, CLK_EXTAL, 1, 3),
+};
+
+static const struct rzg2l_mod_clk r9a08g045_mod_clks[] = {
+ DEF_MOD("gic_gicclk", R9A08G045_GIC600_GICCLK, R9A08G045_CLK_P1, 0x514, 0),
+ DEF_MOD("ia55_clk", R9A08G045_IA55_CLK, R9A08G045_CLK_P1, 0x518, 1),
+ DEF_MOD("dmac_aclk", R9A08G045_DMAC_ACLK, R9A08G045_CLK_P3, 0x52c, 0),
+ DEF_MOD("sdhi0_imclk", R9A08G045_SDHI0_IMCLK, CLK_SD0_DIV4, 0x554, 0),
+ DEF_MOD("sdhi0_imclk2", R9A08G045_SDHI0_IMCLK2, CLK_SD0_DIV4, 0x554, 1),
+ DEF_MOD("sdhi0_clk_hs", R9A08G045_SDHI0_CLK_HS, R9A08G045_CLK_SD0, 0x554, 2),
+ DEF_MOD("sdhi0_aclk", R9A08G045_SDHI0_ACLK, R9A08G045_CLK_P1, 0x554, 3),
+ DEF_MOD("sdhi1_imclk", R9A08G045_SDHI1_IMCLK, CLK_SD1_DIV4, 0x554, 4),
+ DEF_MOD("sdhi1_imclk2", R9A08G045_SDHI1_IMCLK2, CLK_SD1_DIV4, 0x554, 5),
+ DEF_MOD("sdhi1_clk_hs", R9A08G045_SDHI1_CLK_HS, R9A08G045_CLK_SD1, 0x554, 6),
+ DEF_MOD("sdhi1_aclk", R9A08G045_SDHI1_ACLK, R9A08G045_CLK_P1, 0x554, 7),
+ DEF_MOD("sdhi2_imclk", R9A08G045_SDHI2_IMCLK, CLK_SD2_DIV4, 0x554, 8),
+ DEF_MOD("sdhi2_imclk2", R9A08G045_SDHI2_IMCLK2, CLK_SD2_DIV4, 0x554, 9),
+ DEF_MOD("sdhi2_clk_hs", R9A08G045_SDHI2_CLK_HS, R9A08G045_CLK_SD2, 0x554, 10),
+ DEF_MOD("sdhi2_aclk", R9A08G045_SDHI2_ACLK, R9A08G045_CLK_P1, 0x554, 11),
+ DEF_MOD("scif0_clk_pck", R9A08G045_SCIF0_CLK_PCK, R9A08G045_CLK_P0, 0x584, 0),
+ DEF_MOD("gpio_hclk", R9A08G045_GPIO_HCLK, R9A08G045_OSCCLK, 0x598, 0),
+};
+
+static const struct rzg2l_reset r9a08g045_resets[] = {
+ DEF_RST(R9A08G045_GIC600_GICRESET_N, 0x814, 0),
+ DEF_RST(R9A08G045_GIC600_DBG_GICRESET_N, 0x814, 1),
+ DEF_RST(R9A08G045_SDHI0_IXRST, 0x854, 0),
+ DEF_RST(R9A08G045_SDHI1_IXRST, 0x854, 1),
+ DEF_RST(R9A08G045_SDHI2_IXRST, 0x854, 2),
+ DEF_RST(R9A08G045_SCIF0_RST_SYSTEM_N, 0x884, 0),
+ DEF_RST(R9A08G045_GPIO_RSTN, 0x898, 0),
+ DEF_RST(R9A08G045_GPIO_PORT_RESETN, 0x898, 1),
+ DEF_RST(R9A08G045_GPIO_SPARE_RESETN, 0x898, 2),
+};
+
+static const unsigned int r9a08g045_crit_mod_clks[] __initconst = {
+ MOD_CLK_BASE + R9A08G045_GIC600_GICCLK,
+ MOD_CLK_BASE + R9A08G045_IA55_CLK,
+ MOD_CLK_BASE + R9A08G045_DMAC_ACLK,
+};
+
+const struct rzg2l_cpg_info r9a08g045_cpg_info = {
+ /* Core Clocks */
+ .core_clks = r9a08g045_core_clks,
+ .num_core_clks = ARRAY_SIZE(r9a08g045_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r9a08g045_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r9a08g045_crit_mod_clks),
+
+ /* Module Clocks */
+ .mod_clks = r9a08g045_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r9a08g045_mod_clks),
+ .num_hw_mod_clks = R9A08G045_VBAT_BCLK + 1,
+
+ /* Resets */
+ .resets = r9a08g045_resets,
+ .num_resets = R9A08G045_VBAT_BRESETN + 1, /* Last reset ID + 1 */
+
+ .has_clk_mon_regs = true,
+};
diff --git a/drivers/clk/renesas/rcar-cpg-lib.c b/drivers/clk/renesas/rcar-cpg-lib.c
index e2e0447de190..5a15f8788b92 100644
--- a/drivers/clk/renesas/rcar-cpg-lib.c
+++ b/drivers/clk/renesas/rcar-cpg-lib.c
@@ -70,8 +70,21 @@ void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
#define STPnHCK BIT(9 - SDnSRCFC_SHIFT)
static const struct clk_div_table cpg_sdh_div_table[] = {
+ /*
+ * These values are recommended by the datasheet. Because they come
+ * first, Linux will only use these.
+ */
{ 0, 1 }, { 1, 2 }, { STPnHCK | 2, 4 }, { STPnHCK | 3, 8 },
- { STPnHCK | 4, 16 }, { 0, 0 },
+ { STPnHCK | 4, 16 },
+ /*
+ * These values are not recommended because STPnHCK is wrong. But they
+ * have been seen because of broken firmware. So, we support reading
+ * them but Linux will sanitize them when initializing through
+ * recalc_rate.
+ */
+ { STPnHCK | 0, 1 }, { STPnHCK | 1, 2 }, { 2, 4 }, { 3, 8 }, { 4, 16 },
+ /* Sentinel */
+ { 0, 0 }
};
struct clk * __init cpg_sdh_clk_register(const char *name,
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index 47f488387f33..764bd72cf059 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -11,6 +11,7 @@
* Copyright (C) 2015 Renesas Electronics Corp.
*/
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clk/renesas.h>
@@ -38,14 +39,18 @@
#define WARN_DEBUG(x) do { } while (0)
#endif
-#define DIV_RSMASK(v, s, m) ((v >> s) & m)
#define GET_SHIFT(val) ((val >> 12) & 0xff)
#define GET_WIDTH(val) ((val >> 8) & 0xf)
-#define KDIV(val) DIV_RSMASK(val, 16, 0xffff)
-#define MDIV(val) DIV_RSMASK(val, 6, 0x3ff)
-#define PDIV(val) DIV_RSMASK(val, 0, 0x3f)
-#define SDIV(val) DIV_RSMASK(val, 0, 0x7)
+#define KDIV(val) ((s16)FIELD_GET(GENMASK(31, 16), val))
+#define MDIV(val) FIELD_GET(GENMASK(15, 6), val)
+#define PDIV(val) FIELD_GET(GENMASK(5, 0), val)
+#define SDIV(val) FIELD_GET(GENMASK(2, 0), val)
+
+#define RZG3S_DIV_P GENMASK(28, 26)
+#define RZG3S_DIV_M GENMASK(25, 22)
+#define RZG3S_DIV_NI GENMASK(21, 13)
+#define RZG3S_DIV_NF GENMASK(12, 1)
#define CLK_ON_R(reg) (reg)
#define CLK_MON_R(reg) (0x180 + (reg))
@@ -56,15 +61,55 @@
#define GET_REG_SAMPLL_CLK1(val) ((val >> 22) & 0xfff)
#define GET_REG_SAMPLL_CLK2(val) ((val >> 12) & 0xfff)
+#define CPG_WEN_BIT BIT(16)
+
#define MAX_VCLK_FREQ (148500000)
-struct sd_hw_data {
+/**
+ * struct clk_hw_data - clock hardware data
+ * @hw: clock hw
+ * @conf: clock configuration (register offset, shift, width)
+ * @sconf: clock status configuration (register offset, shift, width)
+ * @priv: CPG private data structure
+ */
+struct clk_hw_data {
struct clk_hw hw;
u32 conf;
+ u32 sconf;
struct rzg2l_cpg_priv *priv;
};
-#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw)
+#define to_clk_hw_data(_hw) container_of(_hw, struct clk_hw_data, hw)
+
+/**
+ * struct sd_mux_hw_data - SD MUX clock hardware data
+ * @hw_data: clock hw data
+ * @mtable: clock mux table
+ */
+struct sd_mux_hw_data {
+ struct clk_hw_data hw_data;
+ const u32 *mtable;
+};
+
+#define to_sd_mux_hw_data(_hw) container_of(_hw, struct sd_mux_hw_data, hw_data)
+
+/**
+ * struct div_hw_data - divider clock hardware data
+ * @hw_data: clock hw data
+ * @dtable: pointer to divider table
+ * @invalid_rate: invalid rate for divider
+ * @max_rate: maximum rate for divider
+ * @width: divider width
+ */
+struct div_hw_data {
+ struct clk_hw_data hw_data;
+ const struct clk_div_table *dtable;
+ unsigned long invalid_rate;
+ unsigned long max_rate;
+ u32 width;
+};
+
+#define to_div_hw_data(_hw) container_of(_hw, struct div_hw_data, hw_data)
struct rzg2l_pll5_param {
u32 pl5_fracin;
@@ -121,6 +166,241 @@ static void rzg2l_cpg_del_clk_provider(void *data)
of_clk_del_provider(data);
}
+/* Must be called in atomic context. */
+static int rzg2l_cpg_wait_clk_update_done(void __iomem *base, u32 conf)
+{
+ u32 bitmask = GENMASK(GET_WIDTH(conf) - 1, 0) << GET_SHIFT(conf);
+ u32 off = GET_REG_OFFSET(conf);
+ u32 val;
+
+ return readl_poll_timeout_atomic(base + off, val, !(val & bitmask), 10, 200);
+}
+
+int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+ struct clk_notifier_data *cnd = data;
+ struct clk_hw *hw = __clk_get_hw(cnd->clk);
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 off = GET_REG_OFFSET(clk_hw_data->conf);
+ u32 shift = GET_SHIFT(clk_hw_data->conf);
+ const u32 clk_src_266 = 3;
+ unsigned long flags;
+ int ret;
+
+ if (event != PRE_RATE_CHANGE || (cnd->new_rate / MEGA == 266))
+ return NOTIFY_DONE;
+
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+
+ /*
+ * As per the HW manual, we should not directly switch from 533 MHz to
+ * 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz)
+ * to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first,
+ * and then switch to the target setting (2’b01 (533 MHz) or 2’b10
+ * (400 MHz)).
+ * Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock
+ * switching register is prohibited.
+ * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and
+ * the index to value mapping is done by adding 1 to the index.
+ */
+
+ writel((CPG_WEN_BIT | clk_src_266) << shift, priv->base + off);
+
+ /* Wait for the update done. */
+ ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf);
+
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+
+ if (ret)
+ dev_err(priv->dev, "failed to switch to safe clk source\n");
+
+ return notifier_from_errno(ret);
+}
+
+int rzg3s_cpg_div_clk_notifier(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+ struct clk_notifier_data *cnd = data;
+ struct clk_hw *hw = __clk_get_hw(cnd->clk);
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct div_hw_data *div_hw_data = to_div_hw_data(clk_hw_data);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 off = GET_REG_OFFSET(clk_hw_data->conf);
+ u32 shift = GET_SHIFT(clk_hw_data->conf);
+ unsigned long flags;
+ int ret = 0;
+ u32 val;
+
+ if (event != PRE_RATE_CHANGE || !div_hw_data->invalid_rate ||
+ div_hw_data->invalid_rate % cnd->new_rate)
+ return NOTIFY_DONE;
+
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+
+ val = readl(priv->base + off);
+ val >>= shift;
+ val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0);
+
+ /*
+ * There are different constraints for the user of this notifiers as follows:
+ * 1/ SD div cannot be 1 (val == 0) if parent rate is 800MHz
+ * 2/ OCTA / SPI div cannot be 1 (val == 0) if parent rate is 400MHz
+ * As SD can have only one parent having 800MHz and OCTA div can have
+ * only one parent having 400MHz we took into account the parent rate
+ * at the beginning of function (by checking invalid_rate % new_rate).
+ * Now it is time to check the hardware divider and update it accordingly.
+ */
+ if (!val) {
+ writel((CPG_WEN_BIT | 1) << shift, priv->base + off);
+ /* Wait for the update done. */
+ ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf);
+ }
+
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+
+ if (ret)
+ dev_err(priv->dev, "Failed to downgrade the div\n");
+
+ return notifier_from_errno(ret);
+}
+
+static int rzg2l_register_notifier(struct clk_hw *hw, const struct cpg_core_clk *core,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct notifier_block *nb;
+
+ if (!core->notifier)
+ return 0;
+
+ nb = devm_kzalloc(priv->dev, sizeof(*nb), GFP_KERNEL);
+ if (!nb)
+ return -ENOMEM;
+
+ nb->notifier_call = core->notifier;
+
+ return clk_notifier_register(hw->clk, nb);
+}
+
+static unsigned long rzg3s_div_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct div_hw_data *div_hw_data = to_div_hw_data(clk_hw_data);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 val;
+
+ val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf));
+ val >>= GET_SHIFT(clk_hw_data->conf);
+ val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0);
+
+ return divider_recalc_rate(hw, parent_rate, val, div_hw_data->dtable,
+ CLK_DIVIDER_ROUND_CLOSEST, div_hw_data->width);
+}
+
+static int rzg3s_div_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
+{
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct div_hw_data *div_hw_data = to_div_hw_data(clk_hw_data);
+
+ if (div_hw_data->max_rate && req->rate > div_hw_data->max_rate)
+ req->rate = div_hw_data->max_rate;
+
+ return divider_determine_rate(hw, req, div_hw_data->dtable, div_hw_data->width,
+ CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static int rzg3s_div_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct div_hw_data *div_hw_data = to_div_hw_data(clk_hw_data);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 off = GET_REG_OFFSET(clk_hw_data->conf);
+ u32 shift = GET_SHIFT(clk_hw_data->conf);
+ unsigned long flags;
+ u32 val;
+ int ret;
+
+ val = divider_get_val(rate, parent_rate, div_hw_data->dtable, div_hw_data->width,
+ CLK_DIVIDER_ROUND_CLOSEST);
+
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+ writel((CPG_WEN_BIT | val) << shift, priv->base + off);
+ /* Wait for the update done. */
+ ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf);
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+
+ return ret;
+}
+
+static const struct clk_ops rzg3s_div_clk_ops = {
+ .recalc_rate = rzg3s_div_clk_recalc_rate,
+ .determine_rate = rzg3s_div_clk_determine_rate,
+ .set_rate = rzg3s_div_clk_set_rate,
+};
+
+static struct clk * __init
+rzg3s_cpg_div_clk_register(const struct cpg_core_clk *core, struct clk **clks,
+ void __iomem *base, struct rzg2l_cpg_priv *priv)
+{
+ struct div_hw_data *div_hw_data;
+ struct clk_init_data init = {};
+ const struct clk_div_table *clkt;
+ struct clk_hw *clk_hw;
+ const struct clk *parent;
+ const char *parent_name;
+ u32 max = 0;
+ int ret;
+
+ parent = clks[core->parent & 0xffff];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+
+ div_hw_data = devm_kzalloc(priv->dev, sizeof(*div_hw_data), GFP_KERNEL);
+ if (!div_hw_data)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = core->name;
+ init.flags = core->flag;
+ init.ops = &rzg3s_div_clk_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ /* Get the maximum divider to retrieve div width. */
+ for (clkt = core->dtable; clkt->div; clkt++) {
+ if (max < clkt->div)
+ max = clkt->div;
+ }
+
+ div_hw_data->hw_data.priv = priv;
+ div_hw_data->hw_data.conf = core->conf;
+ div_hw_data->hw_data.sconf = core->sconf;
+ div_hw_data->dtable = core->dtable;
+ div_hw_data->invalid_rate = core->invalid_rate;
+ div_hw_data->max_rate = core->max_rate;
+ div_hw_data->width = fls(max) - 1;
+
+ clk_hw = &div_hw_data->hw_data.hw;
+ clk_hw->init = &init;
+
+ ret = devm_clk_hw_register(priv->dev, clk_hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = rzg2l_register_notifier(clk_hw, core, priv);
+ if (ret) {
+ dev_err(priv->dev, "Failed to register notifier for %s\n",
+ core->name);
+ return ERR_PTR(ret);
+ }
+
+ return clk_hw->clk;
+}
+
static struct clk * __init
rzg2l_cpg_div_clk_register(const struct cpg_core_clk *core,
struct clk **clks,
@@ -183,63 +463,44 @@ rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core,
static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
{
- struct sd_hw_data *hwdata = to_sd_hw_data(hw);
- struct rzg2l_cpg_priv *priv = hwdata->priv;
- u32 off = GET_REG_OFFSET(hwdata->conf);
- u32 shift = GET_SHIFT(hwdata->conf);
- const u32 clk_src_266 = 2;
- u32 bitmask;
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct sd_mux_hw_data *sd_mux_hw_data = to_sd_mux_hw_data(clk_hw_data);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 off = GET_REG_OFFSET(clk_hw_data->conf);
+ u32 shift = GET_SHIFT(clk_hw_data->conf);
+ unsigned long flags;
+ u32 val;
+ int ret;
- /*
- * As per the HW manual, we should not directly switch from 533 MHz to
- * 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz)
- * to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first,
- * and then switch to the target setting (2’b01 (533 MHz) or 2’b10
- * (400 MHz)).
- * Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock
- * switching register is prohibited.
- * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and
- * the index to value mapping is done by adding 1 to the index.
- */
- bitmask = (GENMASK(GET_WIDTH(hwdata->conf) - 1, 0) << shift) << 16;
- if (index != clk_src_266) {
- u32 msk, val;
- int ret;
+ val = clk_mux_index_to_val(sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, index);
- writel(bitmask | ((clk_src_266 + 1) << shift), priv->base + off);
+ spin_lock_irqsave(&priv->rmw_lock, flags);
- msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS;
+ writel((CPG_WEN_BIT | val) << shift, priv->base + off);
- ret = readl_poll_timeout(priv->base + CPG_CLKSTATUS, val,
- !(val & msk), 100,
- CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
- if (ret) {
- dev_err(priv->dev, "failed to switch clk source\n");
- return ret;
- }
- }
+ /* Wait for the update done. */
+ ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf);
- writel(bitmask | ((index + 1) << shift), priv->base + off);
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
- return 0;
+ if (ret)
+ dev_err(priv->dev, "Failed to switch parent\n");
+
+ return ret;
}
static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw)
{
- struct sd_hw_data *hwdata = to_sd_hw_data(hw);
- struct rzg2l_cpg_priv *priv = hwdata->priv;
- u32 val = readl(priv->base + GET_REG_OFFSET(hwdata->conf));
-
- val >>= GET_SHIFT(hwdata->conf);
- val &= GENMASK(GET_WIDTH(hwdata->conf) - 1, 0);
- if (val) {
- val--;
- } else {
- /* Prohibited clk source, change it to 533 MHz(reset value) */
- rzg2l_cpg_sd_clk_mux_set_parent(hw, 0);
- }
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct sd_mux_hw_data *sd_mux_hw_data = to_sd_mux_hw_data(clk_hw_data);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 val;
+
+ val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf));
+ val >>= GET_SHIFT(clk_hw_data->conf);
+ val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0);
- return val;
+ return clk_mux_val_to_index(hw, sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, val);
}
static const struct clk_ops rzg2l_cpg_sd_clk_mux_ops = {
@@ -253,31 +514,40 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core,
void __iomem *base,
struct rzg2l_cpg_priv *priv)
{
- struct sd_hw_data *clk_hw_data;
+ struct sd_mux_hw_data *sd_mux_hw_data;
struct clk_init_data init;
struct clk_hw *clk_hw;
int ret;
- clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
- if (!clk_hw_data)
+ sd_mux_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_mux_hw_data), GFP_KERNEL);
+ if (!sd_mux_hw_data)
return ERR_PTR(-ENOMEM);
- clk_hw_data->priv = priv;
- clk_hw_data->conf = core->conf;
+ sd_mux_hw_data->hw_data.priv = priv;
+ sd_mux_hw_data->hw_data.conf = core->conf;
+ sd_mux_hw_data->hw_data.sconf = core->sconf;
+ sd_mux_hw_data->mtable = core->mtable;
- init.name = GET_SHIFT(core->conf) ? "sd1" : "sd0";
+ init.name = core->name;
init.ops = &rzg2l_cpg_sd_clk_mux_ops;
- init.flags = 0;
+ init.flags = core->flag;
init.num_parents = core->num_parents;
init.parent_names = core->parent_names;
- clk_hw = &clk_hw_data->hw;
+ clk_hw = &sd_mux_hw_data->hw_data.hw;
clk_hw->init = &init;
ret = devm_clk_hw_register(priv->dev, clk_hw);
if (ret)
return ERR_PTR(ret);
+ ret = rzg2l_register_notifier(clk_hw, core, priv);
+ if (ret) {
+ dev_err(priv->dev, "Failed to register notifier for %s\n",
+ core->name);
+ return ERR_PTR(ret);
+ }
+
return clk_hw->clk;
}
@@ -695,29 +965,61 @@ static unsigned long rzg2l_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
struct pll_clk *pll_clk = to_pll(hw);
struct rzg2l_cpg_priv *priv = pll_clk->priv;
unsigned int val1, val2;
- unsigned int mult = 1;
- unsigned int div = 1;
+ u64 rate;
if (pll_clk->type != CLK_TYPE_SAM_PLL)
return parent_rate;
val1 = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf));
val2 = readl(priv->base + GET_REG_SAMPLL_CLK2(pll_clk->conf));
- mult = MDIV(val1) + KDIV(val1) / 65536;
- div = PDIV(val1) << SDIV(val2);
- return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, div);
+ rate = mul_u64_u32_shr(parent_rate, (MDIV(val1) << 16) + KDIV(val1),
+ 16 + SDIV(val2));
+
+ return DIV_ROUND_CLOSEST_ULL(rate, PDIV(val1));
}
static const struct clk_ops rzg2l_cpg_pll_ops = {
.recalc_rate = rzg2l_cpg_pll_clk_recalc_rate,
};
+static unsigned long rzg3s_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzg2l_cpg_priv *priv = pll_clk->priv;
+ u32 nir, nfr, mr, pr, val;
+ u64 rate;
+
+ if (pll_clk->type != CLK_TYPE_G3S_PLL)
+ return parent_rate;
+
+ val = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf));
+
+ pr = 1 << FIELD_GET(RZG3S_DIV_P, val);
+ /* Hardware interprets values higher than 8 as p = 16. */
+ if (pr > 8)
+ pr = 16;
+
+ mr = FIELD_GET(RZG3S_DIV_M, val) + 1;
+ nir = FIELD_GET(RZG3S_DIV_NI, val) + 1;
+ nfr = FIELD_GET(RZG3S_DIV_NF, val);
+
+ rate = mul_u64_u32_shr(parent_rate, 4096 * nir + nfr, 12);
+
+ return DIV_ROUND_CLOSEST_ULL(rate, (mr * pr));
+}
+
+static const struct clk_ops rzg3s_cpg_pll_ops = {
+ .recalc_rate = rzg3s_cpg_pll_clk_recalc_rate,
+};
+
static struct clk * __init
rzg2l_cpg_pll_clk_register(const struct cpg_core_clk *core,
struct clk **clks,
void __iomem *base,
- struct rzg2l_cpg_priv *priv)
+ struct rzg2l_cpg_priv *priv,
+ const struct clk_ops *ops)
{
struct device *dev = priv->dev;
const struct clk *parent;
@@ -735,7 +1037,7 @@ rzg2l_cpg_pll_clk_register(const struct cpg_core_clk *core,
parent_name = __clk_get_name(parent);
init.name = core->name;
- init.ops = &rzg2l_cpg_pll_ops;
+ init.ops = ops;
init.flags = 0;
init.parent_names = &parent_name;
init.num_parents = 1;
@@ -830,8 +1132,12 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
core->mult, div);
break;
case CLK_TYPE_SAM_PLL:
- clk = rzg2l_cpg_pll_clk_register(core, priv->clks,
- priv->base, priv);
+ clk = rzg2l_cpg_pll_clk_register(core, priv->clks, priv->base, priv,
+ &rzg2l_cpg_pll_ops);
+ break;
+ case CLK_TYPE_G3S_PLL:
+ clk = rzg2l_cpg_pll_clk_register(core, priv->clks, priv->base, priv,
+ &rzg3s_cpg_pll_ops);
break;
case CLK_TYPE_SIPLL5:
clk = rzg2l_cpg_sipll5_register(core, priv->clks, priv);
@@ -840,6 +1146,9 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
clk = rzg2l_cpg_div_clk_register(core, priv->clks,
priv->base, priv);
break;
+ case CLK_TYPE_G3S_DIV:
+ clk = rzg3s_cpg_div_clk_register(core, priv->clks, priv->base, priv);
+ break;
case CLK_TYPE_MUX:
clk = rzg2l_cpg_mux_clk_register(core, priv->base, priv);
break;
@@ -895,7 +1204,6 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable)
struct rzg2l_cpg_priv *priv = clock->priv;
unsigned int reg = clock->off;
struct device *dev = priv->dev;
- unsigned long flags;
u32 bitmask = BIT(clock->bit);
u32 value;
int error;
@@ -905,17 +1213,14 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable)
return 0;
}
- dev_dbg(dev, "CLK_ON %u/%pC %s\n", CLK_ON_R(reg), hw->clk,
+ dev_dbg(dev, "CLK_ON 0x%x/%pC %s\n", CLK_ON_R(reg), hw->clk,
enable ? "ON" : "OFF");
- spin_lock_irqsave(&priv->rmw_lock, flags);
+ value = bitmask << 16;
if (enable)
- value = (bitmask << 16) | bitmask;
- else
- value = bitmask << 16;
- writel(value, priv->base + CLK_ON_R(reg));
+ value |= bitmask;
- spin_unlock_irqrestore(&priv->rmw_lock, flags);
+ writel(value, priv->base + CLK_ON_R(reg));
if (!enable)
return 0;
@@ -1401,6 +1706,12 @@ static const struct of_device_id rzg2l_cpg_match[] = {
.data = &r9a07g054_cpg_info,
},
#endif
+#ifdef CONFIG_CLK_R9A08G045
+ {
+ .compatible = "renesas,r9a08g045-cpg",
+ .data = &r9a08g045_cpg_info,
+ },
+#endif
#ifdef CONFIG_CLK_R9A09G011
{
.compatible = "renesas,r9a09g011-cpg",
diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
index 6cee9e56acc7..6e38c8fc888c 100644
--- a/drivers/clk/renesas/rzg2l-cpg.h
+++ b/drivers/clk/renesas/rzg2l-cpg.h
@@ -9,6 +9,8 @@
#ifndef __RENESAS_RZG2L_CPG_H__
#define __RENESAS_RZG2L_CPG_H__
+#include <linux/notifier.h>
+
#define CPG_SIPLL5_STBY (0x140)
#define CPG_SIPLL5_CLK1 (0x144)
#define CPG_SIPLL5_CLK3 (0x14C)
@@ -19,7 +21,6 @@
#define CPG_PL2_DDIV (0x204)
#define CPG_PL3A_DDIV (0x208)
#define CPG_PL6_DDIV (0x210)
-#define CPG_PL2SDHI_DSEL (0x218)
#define CPG_CLKSTATUS (0x280)
#define CPG_PL3_SSEL (0x408)
#define CPG_PL6_SSEL (0x414)
@@ -43,8 +44,6 @@
#define CPG_CLKSTATUS_SELSDHI0_STS BIT(28)
#define CPG_CLKSTATUS_SELSDHI1_STS BIT(29)
-#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 20000
-
/* n = 0/1/2 for PLL1/4/6 */
#define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n))
#define CPG_SAMPLL_CLK2(n) (0x08 + (16 * n))
@@ -69,9 +68,6 @@
#define SEL_PLL6_2 SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1)
#define SEL_GPU2 SEL_PLL_PACK(CPG_PL6_SSEL, 12, 1)
-#define SEL_SDHI0 DDIV_PACK(CPG_PL2SDHI_DSEL, 0, 2)
-#define SEL_SDHI1 DDIV_PACK(CPG_PL2SDHI_DSEL, 4, 2)
-
#define EXTAL_FREQ_IN_MEGA_HZ (24)
/**
@@ -90,10 +86,15 @@ struct cpg_core_clk {
unsigned int mult;
unsigned int type;
unsigned int conf;
+ unsigned int sconf;
const struct clk_div_table *dtable;
+ const u32 *mtable;
+ const unsigned long invalid_rate;
+ const unsigned long max_rate;
const char * const *parent_names;
- int flag;
- int mux_flags;
+ notifier_fn_t notifier;
+ u32 flag;
+ u32 mux_flags;
int num_parents;
};
@@ -102,9 +103,11 @@ enum clk_types {
CLK_TYPE_IN, /* External Clock Input */
CLK_TYPE_FF, /* Fixed Factor Clock */
CLK_TYPE_SAM_PLL,
+ CLK_TYPE_G3S_PLL,
/* Clock with divider */
CLK_TYPE_DIV,
+ CLK_TYPE_G3S_DIV,
/* Clock with clock source selector */
CLK_TYPE_MUX,
@@ -129,6 +132,8 @@ enum clk_types {
DEF_TYPE(_name, _id, _type, .parent = _parent)
#define DEF_SAMPLL(_name, _id, _parent, _conf) \
DEF_TYPE(_name, _id, CLK_TYPE_SAM_PLL, .parent = _parent, .conf = _conf)
+#define DEF_G3S_PLL(_name, _id, _parent, _conf) \
+ DEF_TYPE(_name, _id, CLK_TYPE_G3S_PLL, .parent = _parent, .conf = _conf)
#define DEF_INPUT(_name, _id) \
DEF_TYPE(_name, _id, CLK_TYPE_IN)
#define DEF_FIXED(_name, _id, _parent, _mult, _div) \
@@ -141,6 +146,13 @@ enum clk_types {
DEF_TYPE(_name, _id, CLK_TYPE_DIV, .conf = _conf, \
.parent = _parent, .dtable = _dtable, \
.flag = CLK_DIVIDER_READ_ONLY)
+#define DEF_G3S_DIV(_name, _id, _parent, _conf, _sconf, _dtable, _invalid_rate, \
+ _max_rate, _clk_flags, _notif) \
+ DEF_TYPE(_name, _id, CLK_TYPE_G3S_DIV, .conf = _conf, .sconf = _sconf, \
+ .parent = _parent, .dtable = _dtable, \
+ .invalid_rate = _invalid_rate, \
+ .max_rate = _max_rate, .flag = (_clk_flags), \
+ .notifier = _notif)
#define DEF_MUX(_name, _id, _conf, _parent_names) \
DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = _conf, \
.parent_names = _parent_names, \
@@ -151,10 +163,11 @@ enum clk_types {
.parent_names = _parent_names, \
.num_parents = ARRAY_SIZE(_parent_names), \
.mux_flags = CLK_MUX_READ_ONLY)
-#define DEF_SD_MUX(_name, _id, _conf, _parent_names) \
- DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, \
+#define DEF_SD_MUX(_name, _id, _conf, _sconf, _parent_names, _mtable, _clk_flags, _notifier) \
+ DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, .sconf = _sconf, \
.parent_names = _parent_names, \
- .num_parents = ARRAY_SIZE(_parent_names))
+ .num_parents = ARRAY_SIZE(_parent_names), \
+ .mtable = _mtable, .flag = _clk_flags, .notifier = _notifier)
#define DEF_PLL5_FOUTPOSTDIV(_name, _id, _parent) \
DEF_TYPE(_name, _id, CLK_TYPE_SIPLL5, .parent = _parent)
#define DEF_PLL5_4_MUX(_name, _id, _conf, _parent_names) \
@@ -271,6 +284,10 @@ struct rzg2l_cpg_info {
extern const struct rzg2l_cpg_info r9a07g043_cpg_info;
extern const struct rzg2l_cpg_info r9a07g044_cpg_info;
extern const struct rzg2l_cpg_info r9a07g054_cpg_info;
+extern const struct rzg2l_cpg_info r9a08g045_cpg_info;
extern const struct rzg2l_cpg_info r9a09g011_cpg_info;
+int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event, void *data);
+int rzg3s_cpg_div_clk_notifier(struct notifier_block *nb, unsigned long event, void *data);
+
#endif
diff --git a/drivers/clk/rockchip/clk-rk3128.c b/drivers/clk/rockchip/clk-rk3128.c
index aa53797dbfc1..75071e0cd321 100644
--- a/drivers/clk/rockchip/clk-rk3128.c
+++ b/drivers/clk/rockchip/clk-rk3128.c
@@ -138,7 +138,7 @@ PNAME(mux_pll_src_5plls_p) = { "cpll", "gpll", "gpll_div2", "gpll_div3", "usb480
PNAME(mux_pll_src_4plls_p) = { "cpll", "gpll", "gpll_div2", "usb480m" };
PNAME(mux_pll_src_3plls_p) = { "cpll", "gpll", "gpll_div2" };
-PNAME(mux_aclk_peri_src_p) = { "gpll_peri", "cpll_peri", "gpll_div2_peri", "gpll_div3_peri" };
+PNAME(mux_clk_peri_src_p) = { "gpll", "cpll", "gpll_div2", "gpll_div3" };
PNAME(mux_mmc_src_p) = { "cpll", "gpll", "gpll_div2", "xin24m" };
PNAME(mux_clk_cif_out_src_p) = { "clk_cif_src", "xin24m" };
PNAME(mux_sclk_vop_src_p) = { "cpll", "gpll", "gpll_div2", "gpll_div3" };
@@ -275,23 +275,17 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
RK2928_CLKGATE_CON(0), 11, GFLAGS),
/* PD_PERI */
- GATE(0, "gpll_peri", "gpll", CLK_IGNORE_UNUSED,
+ COMPOSITE(0, "clk_peri_src", mux_clk_peri_src_p, 0,
+ RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS,
RK2928_CLKGATE_CON(2), 0, GFLAGS),
- GATE(0, "cpll_peri", "cpll", CLK_IGNORE_UNUSED,
- RK2928_CLKGATE_CON(2), 0, GFLAGS),
- GATE(0, "gpll_div2_peri", "gpll_div2", CLK_IGNORE_UNUSED,
- RK2928_CLKGATE_CON(2), 0, GFLAGS),
- GATE(0, "gpll_div3_peri", "gpll_div3", CLK_IGNORE_UNUSED,
- RK2928_CLKGATE_CON(2), 0, GFLAGS),
- COMPOSITE_NOGATE(0, "aclk_peri_src", mux_aclk_peri_src_p, 0,
- RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS),
- COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0,
+
+ COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "clk_peri_src", 0,
RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
RK2928_CLKGATE_CON(2), 3, GFLAGS),
- COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", 0,
+ COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "clk_peri_src", 0,
RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
RK2928_CLKGATE_CON(2), 2, GFLAGS),
- GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0,
+ GATE(ACLK_PERI, "aclk_peri", "clk_peri_src", 0,
RK2928_CLKGATE_CON(2), 1, GFLAGS),
GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0,
@@ -316,7 +310,7 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
GATE(SCLK_MIPI_24M, "clk_mipi_24m", "xin24m", CLK_IGNORE_UNUSED,
RK2928_CLKGATE_CON(2), 15, GFLAGS),
- COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
+ COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0,
RK2928_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 6, DFLAGS,
RK2928_CLKGATE_CON(2), 11, GFLAGS),
@@ -490,7 +484,7 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
GATE(HCLK_I2S_2CH, "hclk_i2s_2ch", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 13, GFLAGS),
GATE(HCLK_HOST2, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
- GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 13, GFLAGS),
+ GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 13, GFLAGS),
GATE(0, "hclk_peri_ahb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 14, GFLAGS),
GATE(HCLK_SPDIF, "hclk_spdif", "hclk_peri", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS),
GATE(HCLK_TSP, "hclk_tsp", "hclk_peri", 0, RK2928_CLKGATE_CON(10), 12, GFLAGS),
diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
index 9ebd6c451b3d..9316e5c8a0ea 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -9,8 +9,8 @@
#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/property.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/rk3399-cru.h>
#include "clk.h"
@@ -1634,14 +1634,9 @@ static const struct of_device_id clk_rk3399_match_table[] = {
static int __init clk_rk3399_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- const struct of_device_id *match;
const struct clk_rk3399_inits *init_data;
- match = of_match_device(clk_rk3399_match_table, &pdev->dev);
- if (!match || !match->data)
- return -EINVAL;
-
- init_data = match->data;
+ init_data = device_get_match_data(&pdev->dev);
if (init_data->inits)
init_data->inits(np);
diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c
index 16dabe2b9c47..db713e1526cd 100644
--- a/drivers/clk/rockchip/clk-rk3568.c
+++ b/drivers/clk/rockchip/clk-rk3568.c
@@ -72,6 +72,7 @@ static struct rockchip_pll_rate_table rk3568_pll_rates[] = {
RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0),
RK3036_PLL_RATE(312000000, 1, 78, 6, 1, 1, 0),
RK3036_PLL_RATE(297000000, 2, 99, 4, 1, 1, 0),
+ RK3036_PLL_RATE(292500000, 1, 195, 4, 4, 1, 0),
RK3036_PLL_RATE(241500000, 2, 161, 4, 2, 1, 0),
RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0),
RK3036_PLL_RATE(200000000, 1, 100, 3, 4, 1, 0),
diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c
index 72b6cf83aff4..3484e6cc80ad 100644
--- a/drivers/clk/samsung/clk-exynos-clkout.c
+++ b/drivers/clk/samsung/clk-exynos-clkout.c
@@ -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,19 +84,17 @@ 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;
}
- match = of_match_device(exynos_clkout_ids, dev->parent);
- if (!match) {
+ variant = device_get_match_data(dev->parent);
+ if (!variant) {
dev_err(dev, "cannot match parent device\n");
return -EINVAL;
}
- variant = match->data;
*mux_mask = variant->mux_mask;
diff --git a/drivers/clk/sifive/Kconfig b/drivers/clk/sifive/Kconfig
index 2322f634a910..49597d95602e 100644
--- a/drivers/clk/sifive/Kconfig
+++ b/drivers/clk/sifive/Kconfig
@@ -10,7 +10,7 @@ menuconfig CLK_SIFIVE
if CLK_SIFIVE
config CLK_SIFIVE_PRCI
- bool "PRCI driver for SiFive SoCs"
+ tristate "PRCI driver for SiFive SoCs"
default ARCH_SIFIVE
select RESET_CONTROLLER
select RESET_SIMPLE
diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c
index af81eb835bc2..25b8e1a80ddc 100644
--- a/drivers/clk/sifive/sifive-prci.c
+++ b/drivers/clk/sifive/sifive-prci.c
@@ -7,6 +7,7 @@
#include <linux/clkdev.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/module.h>
#include <linux/of.h>
#include "sifive-prci.h"
#include "fu540-prci.h"
@@ -618,9 +619,8 @@ static struct platform_driver sifive_prci_driver = {
},
.probe = sifive_prci_probe,
};
+module_platform_driver(sifive_prci_driver);
-static int __init sifive_prci_init(void)
-{
- return platform_driver_register(&sifive_prci_driver);
-}
-core_initcall(sifive_prci_init);
+MODULE_AUTHOR("Paul Walmsley <paul.walmsley@sifive.com>");
+MODULE_DESCRIPTION("SiFive Power Reset Clock Interface (PRCI) driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c
index 6b65a74aefa6..8dd94f64756b 100644
--- a/drivers/clk/socfpga/clk-agilex.c
+++ b/drivers/clk/socfpga/clk-agilex.c
@@ -471,12 +471,12 @@ static int agilex_clkmgr_init(struct platform_device *pdev)
if (!clk_data)
return -ENOMEM;
+ clk_data->clk_data.num = num_clks;
+ clk_data->base = base;
+
for (i = 0; i < num_clks; i++)
clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
- clk_data->base = base;
- clk_data->clk_data.num = num_clks;
-
agilex_clk_register_pll(agilex_pll_clks, ARRAY_SIZE(agilex_pll_clks), clk_data);
agilex_clk_register_c_perip(agilex_main_perip_c_clks,
@@ -511,12 +511,12 @@ static int n5x_clkmgr_init(struct platform_device *pdev)
if (!clk_data)
return -ENOMEM;
- for (i = 0; i < num_clks; i++)
- clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
-
clk_data->base = base;
clk_data->clk_data.num = num_clks;
+ for (i = 0; i < num_clks; i++)
+ clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
+
n5x_clk_register_pll(agilex_pll_clks, ARRAY_SIZE(agilex_pll_clks), clk_data);
n5x_clk_register_c_perip(n5x_main_perip_c_clks,
diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c
index 8dd601bd8538..0a5a95e0267f 100644
--- a/drivers/clk/socfpga/clk-gate.c
+++ b/drivers/clk/socfpga/clk-gate.c
@@ -87,10 +87,8 @@ static int socfpga_clk_set_parent(struct clk_hw *hwclk, u8 parent)
return 0;
}
-static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk,
- unsigned long parent_rate)
+static u32 socfpga_clk_get_div(struct socfpga_gate_clk *socfpgaclk)
{
- struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
u32 div = 1, val;
if (socfpgaclk->fixed_div)
@@ -105,12 +103,33 @@ static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk,
div = (1 << val);
}
+ return div;
+}
+
+static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+ u32 div = socfpga_clk_get_div(socfpgaclk);
+
return parent_rate / div;
}
+
+static int socfpga_clk_determine_rate(struct clk_hw *hwclk,
+ struct clk_rate_request *req)
+{
+ struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+ u32 div = socfpga_clk_get_div(socfpgaclk);
+
+ req->rate = req->best_parent_rate / div;
+
+ return 0;
+}
+
static struct clk_ops gateclk_ops = {
.recalc_rate = socfpga_clk_recalc_rate,
- .determine_rate = clk_hw_determine_rate_no_reparent,
+ .determine_rate = socfpga_clk_determine_rate,
.get_parent = socfpga_clk_get_parent,
.set_parent = socfpga_clk_set_parent,
};
diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
index 3752bd9c103c..b4bf4e2d38e1 100644
--- a/drivers/clk/socfpga/clk-s10.c
+++ b/drivers/clk/socfpga/clk-s10.c
@@ -402,12 +402,12 @@ static int s10_clkmgr_init(struct platform_device *pdev)
if (!clk_data)
return -ENOMEM;
- for (i = 0; i < num_clks; i++)
- clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
-
clk_data->base = base;
clk_data->clk_data.num = num_clks;
+ for (i = 0; i < num_clks; i++)
+ clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
+
s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
s10_clk_register_c_perip(s10_main_perip_c_clks,
diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
index 75234e0783e1..83fe4eb3133c 100644
--- a/drivers/clk/socfpga/stratix10-clk.h
+++ b/drivers/clk/socfpga/stratix10-clk.h
@@ -7,8 +7,10 @@
#define __STRATIX10_CLK_H
struct stratix10_clock_data {
- struct clk_hw_onecell_data clk_data;
void __iomem *base;
+
+ /* Must be last */
+ struct clk_hw_onecell_data clk_data;
};
struct stratix10_pll_clock {
diff --git a/drivers/clk/sprd/composite.h b/drivers/clk/sprd/composite.h
index adbabbe596b7..15cec97d2aa7 100644
--- a/drivers/clk/sprd/composite.h
+++ b/drivers/clk/sprd/composite.h
@@ -19,24 +19,24 @@ struct sprd_comp {
};
#define SPRD_COMP_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, _table, \
- _mshift, _mwidth, _dshift, _dwidth, \
- _flags, _fn) \
+ _mshift, _mwidth, _doffset, _dshift, \
+ _dwidth, _flags, _fn) \
struct sprd_comp _struct = { \
.mux = _SPRD_MUX_CLK(_mshift, _mwidth, _table), \
- .div = _SPRD_DIV_CLK(_dshift, _dwidth), \
+ .div = _SPRD_DIV_CLK(_doffset, _dshift, _dwidth), \
.common = { \
.regmap = NULL, \
.reg = _reg, \
.hw.init = _fn(_name, _parent, \
&sprd_comp_ops, _flags), \
- } \
+ } \
}
#define SPRD_COMP_CLK_TABLE(_struct, _name, _parent, _reg, _table, \
_mshift, _mwidth, _dshift, _dwidth, _flags) \
SPRD_COMP_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, _table, \
- _mshift, _mwidth, _dshift, _dwidth, \
- _flags, CLK_HW_INIT_PARENTS)
+ _mshift, _mwidth, 0x0, _dshift, \
+ _dwidth, _flags, CLK_HW_INIT_PARENTS)
#define SPRD_COMP_CLK(_struct, _name, _parent, _reg, _mshift, \
_mwidth, _dshift, _dwidth, _flags) \
@@ -47,15 +47,33 @@ struct sprd_comp {
_mshift, _mwidth, _dshift, \
_dwidth, _flags) \
SPRD_COMP_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, _table, \
- _mshift, _mwidth, _dshift, _dwidth, \
- _flags, CLK_HW_INIT_PARENTS_DATA)
+ _mshift, _mwidth, 0x0, _dshift, \
+ _dwidth, _flags, \
+ CLK_HW_INIT_PARENTS_DATA)
#define SPRD_COMP_CLK_DATA(_struct, _name, _parent, _reg, _mshift, \
_mwidth, _dshift, _dwidth, _flags) \
- SPRD_COMP_CLK_DATA_TABLE(_struct, _name, _parent, _reg, NULL, \
+ SPRD_COMP_CLK_DATA_TABLE(_struct, _name, _parent, _reg, NULL, \
_mshift, _mwidth, _dshift, _dwidth, \
_flags)
+#define SPRD_COMP_CLK_DATA_TABLE_OFFSET(_struct, _name, _parent, _reg, \
+ _table, _mshift, _mwidth, \
+ _doffset, _dshift, _dwidth, \
+ _flags) \
+ SPRD_COMP_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, _table, \
+ _mshift, _mwidth, _doffset, _dshift, \
+ _dwidth, _flags, \
+ CLK_HW_INIT_PARENTS_DATA)
+
+#define SPRD_COMP_CLK_DATA_OFFSET(_struct, _name, _parent, _reg, \
+ _mshift, _mwidth, _doffset, _dshift, \
+ _dwidth, _flags) \
+ SPRD_COMP_CLK_DATA_TABLE_OFFSET(_struct, _name, _parent, _reg, \
+ NULL, _mshift, _mwidth, \
+ _doffset, _dshift, _dwidth, \
+ _flags)
+
static inline struct sprd_comp *hw_to_sprd_comp(const struct clk_hw *hw)
{
struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
diff --git a/drivers/clk/sprd/div.c b/drivers/clk/sprd/div.c
index c7261630cab4..936782c24127 100644
--- a/drivers/clk/sprd/div.c
+++ b/drivers/clk/sprd/div.c
@@ -25,7 +25,7 @@ unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
unsigned long val;
unsigned int reg;
- regmap_read(common->regmap, common->reg, &reg);
+ regmap_read(common->regmap, common->reg + div->offset, &reg);
val = reg >> div->shift;
val &= (1 << div->width) - 1;
@@ -53,10 +53,10 @@ int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
val = divider_get_val(rate, parent_rate, NULL,
div->width, 0);
- regmap_read(common->regmap, common->reg, &reg);
+ regmap_read(common->regmap, common->reg + div->offset, &reg);
reg &= ~GENMASK(div->width + div->shift - 1, div->shift);
- regmap_write(common->regmap, common->reg,
+ regmap_write(common->regmap, common->reg + div->offset,
reg | (val << div->shift));
return 0;
diff --git a/drivers/clk/sprd/div.h b/drivers/clk/sprd/div.h
index f5d614b3dcf1..a0bcad80498f 100644
--- a/drivers/clk/sprd/div.h
+++ b/drivers/clk/sprd/div.h
@@ -20,12 +20,14 @@
* classes.
*/
struct sprd_div_internal {
+ s32 offset;
u8 shift;
u8 width;
};
-#define _SPRD_DIV_CLK(_shift, _width) \
+#define _SPRD_DIV_CLK(_offset, _shift, _width) \
{ \
+ .offset = _offset, \
.shift = _shift, \
.width = _width, \
}
@@ -35,10 +37,10 @@ struct sprd_div {
struct sprd_clk_common common;
};
-#define SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, \
+#define SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, _offset, \
_shift, _width, _flags, _fn) \
struct sprd_div _struct = { \
- .div = _SPRD_DIV_CLK(_shift, _width), \
+ .div = _SPRD_DIV_CLK(_offset, _shift, _width), \
.common = { \
.regmap = NULL, \
.reg = _reg, \
@@ -49,12 +51,17 @@ struct sprd_div {
#define SPRD_DIV_CLK(_struct, _name, _parent, _reg, \
_shift, _width, _flags) \
- SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, \
+ SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, 0x0, \
_shift, _width, _flags, CLK_HW_INIT)
+#define SPRD_DIV_CLK_FW_NAME(_struct, _name, _parent, _reg, \
+ _shift, _width, _flags) \
+ SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, 0x0, \
+ _shift, _width, _flags, CLK_HW_INIT_FW_NAME)
+
#define SPRD_DIV_CLK_HW(_struct, _name, _parent, _reg, \
_shift, _width, _flags) \
- SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, \
+ SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, 0x0, \
_shift, _width, _flags, CLK_HW_INIT_HW)
static inline struct sprd_div *hw_to_sprd_div(const struct clk_hw *hw)
diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c
index d5aa09e9fce4..067b918a8894 100644
--- a/drivers/clk/stm32/clk-stm32-core.c
+++ b/drivers/clk/stm32/clk-stm32-core.c
@@ -431,7 +431,7 @@ static int clk_stm32_composite_determine_rate(struct clk_hw *hw,
{
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
const struct stm32_div_cfg *divider;
- unsigned long rate;
+ long rate;
if (composite->div_id == NO_STM32_DIV)
return 0;
diff --git a/drivers/clk/ti/adpll.c b/drivers/clk/ti/adpll.c
index ff42ea75cb43..6121020b4b38 100644
--- a/drivers/clk/ti/adpll.c
+++ b/drivers/clk/ti/adpll.c
@@ -8,7 +8,9 @@
#include <linux/io.h>
#include <linux/math64.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/string.h>
#define ADPLL_PLLSS_MMR_LOCK_OFFSET 0x00 /* Managed by MPPULL */
@@ -860,24 +862,16 @@ static int ti_adpll_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct device *dev = &pdev->dev;
- const struct of_device_id *match;
- const struct ti_adpll_platform_data *pdata;
struct ti_adpll_data *d;
struct resource *res;
int err;
- match = of_match_device(ti_adpll_match, dev);
- if (match)
- pdata = match->data;
- else
- return -ENODEV;
-
d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
if (!d)
return -ENOMEM;
d->dev = dev;
d->np = node;
- d->c = pdata;
+ d->c = device_get_match_data(dev);
dev_set_drvdata(d->dev, d);
spin_lock_init(&d->lock);
diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c
index 868bc7af21b0..9b2824ed785b 100644
--- a/drivers/clk/ti/clk-44xx.c
+++ b/drivers/clk/ti/clk-44xx.c
@@ -749,9 +749,14 @@ static struct ti_dt_clk omap44xx_clks[] = {
DT_CLK(NULL, "mcbsp1_sync_mux_ck", "abe-clkctrl:0028:26"),
DT_CLK(NULL, "mcbsp2_sync_mux_ck", "abe-clkctrl:0030:26"),
DT_CLK(NULL, "mcbsp3_sync_mux_ck", "abe-clkctrl:0038:26"),
+ DT_CLK("40122000.mcbsp", "prcm_fck", "abe-clkctrl:0028:26"),
+ DT_CLK("40124000.mcbsp", "prcm_fck", "abe-clkctrl:0030:26"),
+ DT_CLK("40126000.mcbsp", "prcm_fck", "abe-clkctrl:0038:26"),
DT_CLK(NULL, "mcbsp4_sync_mux_ck", "l4-per-clkctrl:00c0:26"),
+ DT_CLK("48096000.mcbsp", "prcm_fck", "l4-per-clkctrl:00c0:26"),
DT_CLK(NULL, "ocp2scp_usb_phy_phy_48m", "l3-init-clkctrl:00c0:8"),
DT_CLK(NULL, "otg_60m_gfclk", "l3-init-clkctrl:0040:24"),
+ DT_CLK(NULL, "pad_fck", "pad_clks_ck"),
DT_CLK(NULL, "per_mcbsp4_gfclk", "l4-per-clkctrl:00c0:24"),
DT_CLK(NULL, "pmd_stm_clock_mux_ck", "emu-sys-clkctrl:0000:20"),
DT_CLK(NULL, "pmd_trace_clk_mux_ck", "emu-sys-clkctrl:0000:22"),
diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c
index b4aff76eb373..74dfd5823f83 100644
--- a/drivers/clk/ti/clk-54xx.c
+++ b/drivers/clk/ti/clk-54xx.c
@@ -565,15 +565,19 @@ static struct ti_dt_clk omap54xx_clks[] = {
DT_CLK(NULL, "gpio8_dbclk", "l4per-clkctrl:00f8:8"),
DT_CLK(NULL, "mcbsp1_gfclk", "abe-clkctrl:0028:24"),
DT_CLK(NULL, "mcbsp1_sync_mux_ck", "abe-clkctrl:0028:26"),
+ DT_CLK("40122000.mcbsp", "prcm_fck", "abe-clkctrl:0028:26"),
DT_CLK(NULL, "mcbsp2_gfclk", "abe-clkctrl:0030:24"),
DT_CLK(NULL, "mcbsp2_sync_mux_ck", "abe-clkctrl:0030:26"),
+ DT_CLK("40124000.mcbsp", "prcm_fck", "abe-clkctrl:0030:26"),
DT_CLK(NULL, "mcbsp3_gfclk", "abe-clkctrl:0038:24"),
DT_CLK(NULL, "mcbsp3_sync_mux_ck", "abe-clkctrl:0038:26"),
+ DT_CLK("40126000.mcbsp", "prcm_fck", "abe-clkctrl:0038:26"),
DT_CLK(NULL, "mmc1_32khz_clk", "l3init-clkctrl:0008:8"),
DT_CLK(NULL, "mmc1_fclk", "l3init-clkctrl:0008:25"),
DT_CLK(NULL, "mmc1_fclk_mux", "l3init-clkctrl:0008:24"),
DT_CLK(NULL, "mmc2_fclk", "l3init-clkctrl:0010:25"),
DT_CLK(NULL, "mmc2_fclk_mux", "l3init-clkctrl:0010:24"),
+ DT_CLK(NULL, "pad_fck", "pad_clks_ck"),
DT_CLK(NULL, "sata_ref_clk", "l3init-clkctrl:0068:8"),
DT_CLK(NULL, "timer10_gfclk_mux", "l4per-clkctrl:0008:24"),
DT_CLK(NULL, "timer11_gfclk_mux", "l4per-clkctrl:0010:24"),
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index 768a1f3398b4..5d5bb123ba94 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -309,7 +309,6 @@ static struct clk *_register_divider(struct device_node *node,
u32 flags,
struct clk_omap_divider *div)
{
- struct clk *clk;
struct clk_init_data init;
const char *parent_name;
const char *name;
@@ -326,12 +325,7 @@ static struct clk *_register_divider(struct device_node *node,
div->hw.init = &init;
/* register the clock */
- clk = of_ti_clk_register(node, &div->hw, name);
-
- if (IS_ERR(clk))
- kfree(div);
-
- return clk;
+ return of_ti_clk_register(node, &div->hw, name);
}
int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
diff --git a/drivers/clk/visconti/pll.c b/drivers/clk/visconti/pll.c
index 1f3234f22667..e9cd80e085dc 100644
--- a/drivers/clk/visconti/pll.c
+++ b/drivers/clk/visconti/pll.c
@@ -329,12 +329,12 @@ struct visconti_pll_provider * __init visconti_init_pll(struct device_node *np,
if (!ctx)
return ERR_PTR(-ENOMEM);
- for (i = 0; i < nr_plls; ++i)
- ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
-
ctx->node = np;
ctx->reg_base = base;
ctx->clk_data.num = nr_plls;
+ for (i = 0; i < nr_plls; ++i)
+ ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
+
return ctx;
}
diff --git a/drivers/clk/visconti/pll.h b/drivers/clk/visconti/pll.h
index 01d07f1bf01b..c4bd40676da4 100644
--- a/drivers/clk/visconti/pll.h
+++ b/drivers/clk/visconti/pll.h
@@ -15,8 +15,10 @@
struct visconti_pll_provider {
void __iomem *reg_base;
- struct clk_hw_onecell_data clk_data;
struct device_node *node;
+
+ /* Must be last */
+ struct clk_hw_onecell_data clk_data;
};
#define VISCONTI_PLL_RATE(_rate, _dacen, _dsmen, \
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 0ba0dc4ecf06..34faa0320ece 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -732,4 +732,15 @@ config GOLDFISH_TIMER
help
Support for the timer/counter of goldfish-rtc
+config EP93XX_TIMER
+ bool "Cirrus Logic ep93xx timer driver" if COMPILE_TEST
+ depends on ARCH_EP93XX
+ depends on GENERIC_CLOCKEVENTS
+ depends on HAS_IOMEM
+ select CLKSRC_MMIO
+ select TIMER_OF
+ help
+ Enables support for the Cirrus Logic timer block
+ EP93XX.
+
endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 368c3461dab8..4bb856e4df55 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -89,3 +89,4 @@ obj-$(CONFIG_MSC313E_TIMER) += timer-msc313e.o
obj-$(CONFIG_GOLDFISH_TIMER) += timer-goldfish.o
obj-$(CONFIG_GXP_TIMER) += timer-gxp.o
obj-$(CONFIG_CLKSRC_LOONGSON1_PWM) += timer-loongson1-pwm.o
+obj-$(CONFIG_EP93XX_TIMER) += timer-ep93xx.o
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 7dd2c615bce2..e054de92de91 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -836,8 +836,9 @@ static u64 __arch_timer_check_delta(void)
* Note that TVAL is signed, thus has only 31 of its
* 32 bits to express magnitude.
*/
- MIDR_ALL_VERSIONS(MIDR_CPU_MODEL(ARM_CPU_IMP_APM,
- APM_CPU_PART_POTENZA)),
+ MIDR_REV_RANGE(MIDR_CPU_MODEL(ARM_CPU_IMP_APM,
+ APM_CPU_PART_XGENE),
+ APM_CPU_VAR_POTENZA, 0x0, 0xf),
{},
};
@@ -917,7 +918,7 @@ static void arch_timer_evtstrm_enable(unsigned int divider)
#ifdef CONFIG_ARM64
/* ECV is likely to require a large divider. Use the EVNTIS flag. */
- if (cpus_have_const_cap(ARM64_HAS_ECV) && divider > 15) {
+ if (cpus_have_final_cap(ARM64_HAS_ECV) && divider > 15) {
cntkctl |= ARCH_TIMER_EVT_INTERVAL_SCALE;
divider -= 8;
}
@@ -955,6 +956,30 @@ static void arch_timer_configure_evtstream(void)
arch_timer_evtstrm_enable(max(0, lsb));
}
+static int arch_timer_evtstrm_starting_cpu(unsigned int cpu)
+{
+ arch_timer_configure_evtstream();
+ return 0;
+}
+
+static int arch_timer_evtstrm_dying_cpu(unsigned int cpu)
+{
+ cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
+ return 0;
+}
+
+static int __init arch_timer_evtstrm_register(void)
+{
+ if (!arch_timer_evt || !evtstrm_enable)
+ return 0;
+
+ return cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_EVTSTRM_STARTING,
+ "clockevents/arm/arch_timer_evtstrm:starting",
+ arch_timer_evtstrm_starting_cpu,
+ arch_timer_evtstrm_dying_cpu);
+}
+core_initcall(arch_timer_evtstrm_register);
+
static void arch_counter_set_user_access(void)
{
u32 cntkctl = arch_timer_get_cntkctl();
@@ -1016,8 +1041,6 @@ static int arch_timer_starting_cpu(unsigned int cpu)
}
arch_counter_set_user_access();
- if (evtstrm_enable)
- arch_timer_configure_evtstream();
return 0;
}
@@ -1164,8 +1187,6 @@ static int arch_timer_dying_cpu(unsigned int cpu)
{
struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
- cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
-
arch_timer_stop(clk);
return 0;
}
@@ -1279,6 +1300,7 @@ out_unreg_notify:
out_free:
free_percpu(arch_timer_evt);
+ arch_timer_evt = NULL;
out:
return err;
}
diff --git a/drivers/clocksource/timer-atmel-tcb.c b/drivers/clocksource/timer-atmel-tcb.c
index 27af17c99590..2a90c92a9182 100644
--- a/drivers/clocksource/timer-atmel-tcb.c
+++ b/drivers/clocksource/timer-atmel-tcb.c
@@ -315,6 +315,7 @@ static void __init tcb_setup_dual_chan(struct atmel_tc *tc, int mck_divisor_idx)
writel(mck_divisor_idx /* likely divide-by-8 */
| ATMEL_TC_WAVE
| ATMEL_TC_WAVESEL_UP /* free-run */
+ | ATMEL_TC_ASWTRG_SET /* TIOA0 rises at software trigger */
| ATMEL_TC_ACPA_SET /* TIOA0 rises at 0 */
| ATMEL_TC_ACPC_CLEAR, /* (duty cycle 50%) */
tcaddr + ATMEL_TC_REG(0, CMR));
diff --git a/drivers/clocksource/timer-ep93xx.c b/drivers/clocksource/timer-ep93xx.c
new file mode 100644
index 000000000000..bc0ca6e12334
--- /dev/null
+++ b/drivers/clocksource/timer-ep93xx.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Cirrus Logic EP93xx timer driver.
+ * Copyright (C) 2021 Nikita Shubin <nikita.shubin@maquefel.me>
+ *
+ * Based on a rewrite of arch/arm/mach-ep93xx/timer.c:
+ */
+
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#include <asm/mach/time.h>
+
+/*************************************************************************
+ * Timer handling for EP93xx
+ *************************************************************************
+ * The ep93xx has four internal timers. Timers 1, 2 (both 16 bit) and
+ * 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate
+ * an interrupt on underflow. Timer 4 (40 bit) counts down at 983.04 kHz,
+ * is free-running, and can't generate interrupts.
+ *
+ * The 508 kHz timers are ideal for use for the timer interrupt, as the
+ * most common values of HZ divide 508 kHz nicely. We pick the 32 bit
+ * timer (timer 3) to get as long sleep intervals as possible when using
+ * CONFIG_NO_HZ.
+ *
+ * The higher clock rate of timer 4 makes it a better choice than the
+ * other timers for use as clock source and for sched_clock(), providing
+ * a stable 40 bit time base.
+ *************************************************************************
+ */
+
+#define EP93XX_TIMER1_LOAD 0x00
+#define EP93XX_TIMER1_VALUE 0x04
+#define EP93XX_TIMER1_CONTROL 0x08
+#define EP93XX_TIMER123_CONTROL_ENABLE BIT(7)
+#define EP93XX_TIMER123_CONTROL_MODE BIT(6)
+#define EP93XX_TIMER123_CONTROL_CLKSEL BIT(3)
+#define EP93XX_TIMER1_CLEAR 0x0c
+#define EP93XX_TIMER2_LOAD 0x20
+#define EP93XX_TIMER2_VALUE 0x24
+#define EP93XX_TIMER2_CONTROL 0x28
+#define EP93XX_TIMER2_CLEAR 0x2c
+/*
+ * This read-only register contains the low word of the time stamp debug timer
+ * ( Timer4). When this register is read, the high byte of the Timer4 counter is
+ * saved in the Timer4ValueHigh register.
+ */
+#define EP93XX_TIMER4_VALUE_LOW 0x60
+#define EP93XX_TIMER4_VALUE_HIGH 0x64
+#define EP93XX_TIMER4_VALUE_HIGH_ENABLE BIT(8)
+#define EP93XX_TIMER3_LOAD 0x80
+#define EP93XX_TIMER3_VALUE 0x84
+#define EP93XX_TIMER3_CONTROL 0x88
+#define EP93XX_TIMER3_CLEAR 0x8c
+
+#define EP93XX_TIMER123_RATE 508469
+#define EP93XX_TIMER4_RATE 983040
+
+struct ep93xx_tcu {
+ void __iomem *base;
+};
+
+static struct ep93xx_tcu *ep93xx_tcu;
+
+static u64 ep93xx_clocksource_read(struct clocksource *c)
+{
+ struct ep93xx_tcu *tcu = ep93xx_tcu;
+
+ return lo_hi_readq(tcu->base + EP93XX_TIMER4_VALUE_LOW) & GENMASK_ULL(39, 0);
+}
+
+static u64 notrace ep93xx_read_sched_clock(void)
+{
+ return ep93xx_clocksource_read(NULL);
+}
+
+static int ep93xx_clkevt_set_next_event(unsigned long next,
+ struct clock_event_device *evt)
+{
+ struct ep93xx_tcu *tcu = ep93xx_tcu;
+ /* Default mode: periodic, off, 508 kHz */
+ u32 tmode = EP93XX_TIMER123_CONTROL_MODE |
+ EP93XX_TIMER123_CONTROL_CLKSEL;
+
+ /* Clear timer */
+ writel(tmode, tcu->base + EP93XX_TIMER3_CONTROL);
+
+ /* Set next event */
+ writel(next, tcu->base + EP93XX_TIMER3_LOAD);
+ writel(tmode | EP93XX_TIMER123_CONTROL_ENABLE,
+ tcu->base + EP93XX_TIMER3_CONTROL);
+ return 0;
+}
+
+static int ep93xx_clkevt_shutdown(struct clock_event_device *evt)
+{
+ struct ep93xx_tcu *tcu = ep93xx_tcu;
+ /* Disable timer */
+ writel(0, tcu->base + EP93XX_TIMER3_CONTROL);
+
+ return 0;
+}
+
+static struct clock_event_device ep93xx_clockevent = {
+ .name = "timer1",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .set_state_shutdown = ep93xx_clkevt_shutdown,
+ .set_state_oneshot = ep93xx_clkevt_shutdown,
+ .tick_resume = ep93xx_clkevt_shutdown,
+ .set_next_event = ep93xx_clkevt_set_next_event,
+ .rating = 300,
+};
+
+static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)
+{
+ struct ep93xx_tcu *tcu = ep93xx_tcu;
+ struct clock_event_device *evt = dev_id;
+
+ /* Writing any value clears the timer interrupt */
+ writel(1, tcu->base + EP93XX_TIMER3_CLEAR);
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static int __init ep93xx_timer_of_init(struct device_node *np)
+{
+ int irq;
+ unsigned long flags = IRQF_TIMER | IRQF_IRQPOLL;
+ struct ep93xx_tcu *tcu;
+ int ret;
+
+ tcu = kzalloc(sizeof(*tcu), GFP_KERNEL);
+ if (!tcu)
+ return -ENOMEM;
+
+ tcu->base = of_iomap(np, 0);
+ if (!tcu->base) {
+ pr_err("Can't remap registers\n");
+ ret = -ENXIO;
+ goto out_free;
+ }
+
+ ep93xx_tcu = tcu;
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (irq == 0)
+ irq = -EINVAL;
+ if (irq < 0) {
+ pr_err("EP93XX Timer Can't parse IRQ %d", irq);
+ goto out_free;
+ }
+
+ /* Enable and register clocksource and sched_clock on timer 4 */
+ writel(EP93XX_TIMER4_VALUE_HIGH_ENABLE,
+ tcu->base + EP93XX_TIMER4_VALUE_HIGH);
+ clocksource_mmio_init(NULL, "timer4",
+ EP93XX_TIMER4_RATE, 200, 40,
+ ep93xx_clocksource_read);
+ sched_clock_register(ep93xx_read_sched_clock, 40,
+ EP93XX_TIMER4_RATE);
+
+ /* Set up clockevent on timer 3 */
+ if (request_irq(irq, ep93xx_timer_interrupt, flags, "ep93xx timer",
+ &ep93xx_clockevent))
+ pr_err("Failed to request irq %d (ep93xx timer)\n", irq);
+
+ clockevents_config_and_register(&ep93xx_clockevent,
+ EP93XX_TIMER123_RATE,
+ 1,
+ UINT_MAX);
+
+ return 0;
+
+out_free:
+ kfree(tcu);
+ return ret;
+}
+TIMER_OF_DECLARE(ep93xx_timer, "cirrus,ep9301-timer", ep93xx_timer_of_init);
diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c
index 28ab4f1a7c71..6a878d227a13 100644
--- a/drivers/clocksource/timer-imx-gpt.c
+++ b/drivers/clocksource/timer-imx-gpt.c
@@ -434,12 +434,16 @@ static int __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type t
return -ENOMEM;
imxtm->base = of_iomap(np, 0);
- if (!imxtm->base)
- return -ENXIO;
+ if (!imxtm->base) {
+ ret = -ENXIO;
+ goto err_kfree;
+ }
imxtm->irq = irq_of_parse_and_map(np, 0);
- if (imxtm->irq <= 0)
- return -EINVAL;
+ if (imxtm->irq <= 0) {
+ ret = -EINVAL;
+ goto err_kfree;
+ }
imxtm->clk_ipg = of_clk_get_by_name(np, "ipg");
@@ -452,11 +456,15 @@ static int __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type t
ret = _mxc_timer_init(imxtm);
if (ret)
- return ret;
+ goto err_kfree;
initialized = 1;
return 0;
+
+err_kfree:
+ kfree(imxtm);
+ return ret;
}
static int __init imx1_timer_init_dt(struct device_node *np)
diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
index da3071b387eb..57857c0dfba9 100644
--- a/drivers/clocksource/timer-riscv.c
+++ b/drivers/clocksource/timer-riscv.c
@@ -22,21 +22,32 @@
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/interrupt.h>
#include <linux/of_irq.h>
+#include <linux/limits.h>
#include <clocksource/timer-riscv.h>
#include <asm/smp.h>
-#include <asm/hwcap.h>
+#include <asm/cpufeature.h>
#include <asm/sbi.h>
#include <asm/timex.h>
static DEFINE_STATIC_KEY_FALSE(riscv_sstc_available);
static bool riscv_timer_cannot_wake_cpu;
+static void riscv_clock_event_stop(void)
+{
+ if (static_branch_likely(&riscv_sstc_available)) {
+ csr_write(CSR_STIMECMP, ULONG_MAX);
+ if (IS_ENABLED(CONFIG_32BIT))
+ csr_write(CSR_STIMECMPH, ULONG_MAX);
+ } else {
+ sbi_set_timer(U64_MAX);
+ }
+}
+
static int riscv_clock_next_event(unsigned long delta,
struct clock_event_device *ce)
{
u64 next_tval = get_cycles64() + delta;
- csr_set(CSR_IE, IE_TIE);
if (static_branch_likely(&riscv_sstc_available)) {
#if defined(CONFIG_32BIT)
csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF);
@@ -94,6 +105,8 @@ static int riscv_timer_starting_cpu(unsigned int cpu)
ce->irq = riscv_clock_event_irq;
if (riscv_timer_cannot_wake_cpu)
ce->features |= CLOCK_EVT_FEAT_C3STOP;
+ if (static_branch_likely(&riscv_sstc_available))
+ ce->rating = 450;
clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fffffff);
enable_percpu_irq(riscv_clock_event_irq,
@@ -119,7 +132,7 @@ static irqreturn_t riscv_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event);
- csr_clear(CSR_IE, IE_TIE);
+ riscv_clock_event_stop();
evdev->event_handler(evdev);
return IRQ_HANDLED;
@@ -212,6 +225,10 @@ TIMER_OF_DECLARE(riscv_timer, "riscv", riscv_timer_init_dt);
#ifdef CONFIG_ACPI
static int __init riscv_timer_acpi_init(struct acpi_table_header *table)
{
+ struct acpi_table_rhct *rhct = (struct acpi_table_rhct *)table;
+
+ riscv_timer_cannot_wake_cpu = rhct->flags & ACPI_RHCT_TIMER_CANNOT_WAKEUP_CPU;
+
return riscv_timer_init_common();
}
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c
index 69fee3540d37..0d229a9058da 100644
--- a/drivers/clocksource/timer-sun5i.c
+++ b/drivers/clocksource/timer-sun5i.c
@@ -256,10 +256,8 @@ static int sun5i_timer_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "Can't get IRQ\n");
+ if (irq < 0)
return irq;
- }
clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(clk)) {
diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index 09ab29cb7f64..5f60f6bd3386 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -140,6 +140,8 @@ struct dmtimer {
struct platform_device *pdev;
struct list_head node;
struct notifier_block nb;
+ struct notifier_block fclk_nb;
+ unsigned long fclk_rate;
};
static u32 omap_reserved_systimers;
@@ -253,8 +255,7 @@ static inline void __omap_dm_timer_enable_posted(struct dmtimer *timer)
timer->posted = OMAP_TIMER_POSTED;
}
-static inline void __omap_dm_timer_stop(struct dmtimer *timer,
- unsigned long rate)
+static inline void __omap_dm_timer_stop(struct dmtimer *timer)
{
u32 l;
@@ -269,7 +270,7 @@ static inline void __omap_dm_timer_stop(struct dmtimer *timer,
* Wait for functional clock period x 3.5 to make sure that
* timer is stopped
*/
- udelay(3500000 / rate + 1);
+ udelay(3500000 / timer->fclk_rate + 1);
#endif
}
@@ -348,6 +349,21 @@ static int omap_timer_context_notifier(struct notifier_block *nb,
return NOTIFY_OK;
}
+static int omap_timer_fclk_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct clk_notifier_data *clk_data = data;
+ struct dmtimer *timer = container_of(nb, struct dmtimer, fclk_nb);
+
+ switch (event) {
+ case POST_RATE_CHANGE:
+ timer->fclk_rate = clk_data->new_rate;
+ return NOTIFY_OK;
+ default:
+ return NOTIFY_DONE;
+ }
+}
+
static int omap_dm_timer_reset(struct dmtimer *timer)
{
u32 l, timeout = 100000;
@@ -754,7 +770,6 @@ static int omap_dm_timer_stop(struct omap_dm_timer *cookie)
{
struct dmtimer *timer;
struct device *dev;
- unsigned long rate = 0;
timer = to_dmtimer(cookie);
if (unlikely(!timer))
@@ -762,10 +777,7 @@ static int omap_dm_timer_stop(struct omap_dm_timer *cookie)
dev = &timer->pdev->dev;
- if (!timer->omap1)
- rate = clk_get_rate(timer->fclk);
-
- __omap_dm_timer_stop(timer, rate);
+ __omap_dm_timer_stop(timer);
pm_runtime_put_sync(dev);
@@ -1124,6 +1136,14 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
timer->fclk = devm_clk_get(dev, "fck");
if (IS_ERR(timer->fclk))
return PTR_ERR(timer->fclk);
+
+ timer->fclk_nb.notifier_call = omap_timer_fclk_notifier;
+ ret = devm_clk_notifier_register(dev, timer->fclk,
+ &timer->fclk_nb);
+ if (ret)
+ return ret;
+
+ timer->fclk_rate = clk_get_rate(timer->fclk);
} else {
timer->fclk = ERR_PTR(-ENODEV);
}
diff --git a/drivers/comedi/Kconfig b/drivers/comedi/Kconfig
index 9af280735cba..93c68a40a17b 100644
--- a/drivers/comedi/Kconfig
+++ b/drivers/comedi/Kconfig
@@ -67,6 +67,7 @@ config COMEDI_TEST
config COMEDI_PARPORT
tristate "Parallel port support"
+ depends on HAS_IOPORT
help
Enable support for the standard parallel port.
A cheap and easy way to get a few more digital I/O lines. Steal
@@ -79,6 +80,7 @@ config COMEDI_PARPORT
config COMEDI_SSV_DNP
tristate "SSV Embedded Systems DIL/Net-PC support"
depends on X86_32 || COMPILE_TEST
+ depends on HAS_IOPORT
help
Enable support for SSV Embedded Systems DIL/Net-PC
@@ -89,6 +91,8 @@ endif # COMEDI_MISC_DRIVERS
menuconfig COMEDI_ISA_DRIVERS
bool "Comedi ISA and PC/104 drivers"
+ depends on ISA || ISA_BUS || PC104
+ depends on HAS_IOPORT
help
Enable comedi ISA and PC/104 drivers to be built
@@ -589,6 +593,7 @@ config COMEDI_8255_PCI
config COMEDI_ADDI_WATCHDOG
tristate
+ depends on HAS_IOPORT
help
Provides support for the watchdog subdevice found on many ADDI-DATA
boards. This module will be automatically selected when needed. The
@@ -596,6 +601,7 @@ config COMEDI_ADDI_WATCHDOG
config COMEDI_ADDI_APCI_1032
tristate "ADDI-DATA APCI_1032 support"
+ depends on HAS_IOPORT
help
Enable support for ADDI-DATA APCI_1032 cards
@@ -604,6 +610,7 @@ config COMEDI_ADDI_APCI_1032
config COMEDI_ADDI_APCI_1500
tristate "ADDI-DATA APCI_1500 support"
+ depends on HAS_IOPORT
help
Enable support for ADDI-DATA APCI_1500 cards
@@ -612,6 +619,7 @@ config COMEDI_ADDI_APCI_1500
config COMEDI_ADDI_APCI_1516
tristate "ADDI-DATA APCI-1016/1516/2016 support"
+ depends on HAS_IOPORT
select COMEDI_ADDI_WATCHDOG
help
Enable support for ADDI-DATA APCI-1016, APCI-1516 and APCI-2016 boards.
@@ -623,6 +631,7 @@ config COMEDI_ADDI_APCI_1516
config COMEDI_ADDI_APCI_1564
tristate "ADDI-DATA APCI_1564 support"
+ depends on HAS_IOPORT
select COMEDI_ADDI_WATCHDOG
help
Enable support for ADDI-DATA APCI_1564 cards
@@ -632,6 +641,7 @@ config COMEDI_ADDI_APCI_1564
config COMEDI_ADDI_APCI_16XX
tristate "ADDI-DATA APCI_16xx support"
+ depends on HAS_IOPORT
help
Enable support for ADDI-DATA APCI_16xx cards
@@ -640,6 +650,7 @@ config COMEDI_ADDI_APCI_16XX
config COMEDI_ADDI_APCI_2032
tristate "ADDI-DATA APCI_2032 support"
+ depends on HAS_IOPORT
select COMEDI_ADDI_WATCHDOG
help
Enable support for ADDI-DATA APCI_2032 cards
@@ -649,6 +660,7 @@ config COMEDI_ADDI_APCI_2032
config COMEDI_ADDI_APCI_2200
tristate "ADDI-DATA APCI_2200 support"
+ depends on HAS_IOPORT
select COMEDI_ADDI_WATCHDOG
help
Enable support for ADDI-DATA APCI_2200 cards
@@ -658,6 +670,7 @@ config COMEDI_ADDI_APCI_2200
config COMEDI_ADDI_APCI_3120
tristate "ADDI-DATA APCI_3120/3001 support"
+ depends on HAS_IOPORT
depends on HAS_DMA
help
Enable support for ADDI-DATA APCI_3120/3001 cards
@@ -667,6 +680,7 @@ config COMEDI_ADDI_APCI_3120
config COMEDI_ADDI_APCI_3501
tristate "ADDI-DATA APCI_3501 support"
+ depends on HAS_IOPORT
help
Enable support for ADDI-DATA APCI_3501 cards
@@ -675,6 +689,7 @@ config COMEDI_ADDI_APCI_3501
config COMEDI_ADDI_APCI_3XXX
tristate "ADDI-DATA APCI_3xxx support"
+ depends on HAS_IOPORT
help
Enable support for ADDI-DATA APCI_3xxx cards
@@ -683,6 +698,7 @@ config COMEDI_ADDI_APCI_3XXX
config COMEDI_ADL_PCI6208
tristate "ADLink PCI-6208A support"
+ depends on HAS_IOPORT
help
Enable support for ADLink PCI-6208A cards
@@ -691,6 +707,7 @@ config COMEDI_ADL_PCI6208
config COMEDI_ADL_PCI7X3X
tristate "ADLink PCI-723X/743X isolated digital i/o board support"
+ depends on HAS_IOPORT
help
Enable support for ADlink PCI-723X/743X isolated digital i/o boards.
Supported boards include the 32-channel PCI-7230 (16 in/16 out),
@@ -702,6 +719,7 @@ config COMEDI_ADL_PCI7X3X
config COMEDI_ADL_PCI8164
tristate "ADLink PCI-8164 4 Axes Motion Control board support"
+ depends on HAS_IOPORT
help
Enable support for ADlink PCI-8164 4 Axes Motion Control board
@@ -710,6 +728,7 @@ config COMEDI_ADL_PCI8164
config COMEDI_ADL_PCI9111
tristate "ADLink PCI-9111HR support"
+ depends on HAS_IOPORT
select COMEDI_8254
help
Enable support for ADlink PCI9111 cards
@@ -719,6 +738,7 @@ config COMEDI_ADL_PCI9111
config COMEDI_ADL_PCI9118
tristate "ADLink PCI-9118DG, PCI-9118HG, PCI-9118HR support"
+ depends on HAS_IOPORT
depends on HAS_DMA
select COMEDI_8254
help
@@ -729,6 +749,7 @@ config COMEDI_ADL_PCI9118
config COMEDI_ADV_PCI1710
tristate "Advantech PCI-171x and PCI-1731 support"
+ depends on HAS_IOPORT
select COMEDI_8254
help
Enable support for Advantech PCI-1710, PCI-1710HG, PCI-1711,
@@ -739,6 +760,7 @@ config COMEDI_ADV_PCI1710
config COMEDI_ADV_PCI1720
tristate "Advantech PCI-1720 support"
+ depends on HAS_IOPORT
help
Enable support for Advantech PCI-1720 Analog Output board.
@@ -747,6 +769,7 @@ config COMEDI_ADV_PCI1720
config COMEDI_ADV_PCI1723
tristate "Advantech PCI-1723 support"
+ depends on HAS_IOPORT
help
Enable support for Advantech PCI-1723 cards
@@ -755,6 +778,7 @@ config COMEDI_ADV_PCI1723
config COMEDI_ADV_PCI1724
tristate "Advantech PCI-1724U support"
+ depends on HAS_IOPORT
help
Enable support for Advantech PCI-1724U cards. These are 32-channel
analog output cards with voltage and current loop output ranges and
@@ -765,6 +789,7 @@ config COMEDI_ADV_PCI1724
config COMEDI_ADV_PCI1760
tristate "Advantech PCI-1760 support"
+ depends on HAS_IOPORT
help
Enable support for Advantech PCI-1760 board.
@@ -773,6 +798,7 @@ config COMEDI_ADV_PCI1760
config COMEDI_ADV_PCI_DIO
tristate "Advantech PCI DIO card support"
+ depends on HAS_IOPORT
select COMEDI_8254
select COMEDI_8255
help
@@ -796,6 +822,7 @@ config COMEDI_AMPLC_DIO200_PCI
config COMEDI_AMPLC_PC236_PCI
tristate "Amplicon PCI236 DIO board support"
+ depends on HAS_IOPORT
select COMEDI_AMPLC_PC236
help
Enable support for Amplicon PCI236 DIO board.
@@ -805,6 +832,7 @@ config COMEDI_AMPLC_PC236_PCI
config COMEDI_AMPLC_PC263_PCI
tristate "Amplicon PCI263 relay board support"
+ depends on HAS_IOPORT
help
Enable support for Amplicon PCI263 relay board. This is a PCI board
with 16 reed relay output channels.
@@ -814,6 +842,7 @@ config COMEDI_AMPLC_PC263_PCI
config COMEDI_AMPLC_PCI224
tristate "Amplicon PCI224 and PCI234 support"
+ depends on HAS_IOPORT
select COMEDI_8254
help
Enable support for Amplicon PCI224 and PCI234 AO boards
@@ -823,6 +852,7 @@ config COMEDI_AMPLC_PCI224
config COMEDI_AMPLC_PCI230
tristate "Amplicon PCI230 and PCI260 support"
+ depends on HAS_IOPORT
select COMEDI_8254
select COMEDI_8255
help
@@ -834,6 +864,7 @@ config COMEDI_AMPLC_PCI230
config COMEDI_CONTEC_PCI_DIO
tristate "Contec PIO1616L digital I/O board support"
+ depends on HAS_IOPORT
help
Enable support for the Contec PIO1616L digital I/O board
@@ -842,6 +873,7 @@ config COMEDI_CONTEC_PCI_DIO
config COMEDI_DAS08_PCI
tristate "DAS-08 PCI support"
+ depends on HAS_IOPORT
select COMEDI_DAS08
help
Enable support for PCI DAS-08 cards.
@@ -861,6 +893,7 @@ config COMEDI_DT3000
config COMEDI_DYNA_PCI10XX
tristate "Dynalog PCI DAQ series support"
+ depends on HAS_IOPORT
help
Enable support for Dynalog PCI DAQ series
PCI-1050
@@ -911,6 +944,7 @@ config COMEDI_JR3_PCI
config COMEDI_KE_COUNTER
tristate "Kolter-Electronic PCI Counter 1 card support"
+ depends on HAS_IOPORT
help
Enable support for Kolter-Electronic PCI Counter 1 cards
@@ -929,6 +963,7 @@ config COMEDI_CB_PCIDAS64
config COMEDI_CB_PCIDAS
tristate "MeasurementComputing PCI-DAS support"
+ depends on HAS_IOPORT
select COMEDI_8254
select COMEDI_8255
help
@@ -942,6 +977,7 @@ config COMEDI_CB_PCIDAS
config COMEDI_CB_PCIDDA
tristate "MeasurementComputing PCI-DDA series support"
+ depends on HAS_IOPORT
select COMEDI_8255
help
Enable support for ComputerBoards/MeasurementComputing PCI-DDA
@@ -953,6 +989,7 @@ config COMEDI_CB_PCIDDA
config COMEDI_CB_PCIMDAS
tristate "MeasurementComputing PCIM-DAS1602/16, PCIe-DAS1602/16 support"
+ depends on HAS_IOPORT
select COMEDI_8254
select COMEDI_8255
help
@@ -964,6 +1001,7 @@ config COMEDI_CB_PCIMDAS
config COMEDI_CB_PCIMDDA
tristate "MeasurementComputing PCIM-DDA06-16 support"
+ depends on HAS_IOPORT
select COMEDI_8255
help
Enable support for ComputerBoards/MeasurementComputing PCIM-DDA06-16
@@ -973,6 +1011,7 @@ config COMEDI_CB_PCIMDDA
config COMEDI_ME4000
tristate "Meilhaus ME-4000 support"
+ depends on HAS_IOPORT
select COMEDI_8254
help
Enable support for Meilhaus PCI data acquisition cards
@@ -1042,7 +1081,6 @@ config COMEDI_NI_PCIDIO
tristate "NI PCI-DIO32HS, PCI-6533, PCI-6534 support"
depends on HAS_DMA
select COMEDI_MITE
- select COMEDI_8255
help
Enable support for National Instruments PCI-DIO-32HS, PXI-6533,
PCI-6533 and PCI-6534
@@ -1103,7 +1141,7 @@ endif # COMEDI_PCI_DRIVERS
menuconfig COMEDI_PCMCIA_DRIVERS
tristate "Comedi PCMCIA drivers"
- depends on PCMCIA
+ depends on PCMCIA && HAS_IOPORT
help
Enable support for comedi PCMCIA drivers.
@@ -1254,6 +1292,7 @@ config COMEDI_8255
config COMEDI_8255_SA
tristate "Standalone 8255 support"
+ depends on HAS_IOPORT
select COMEDI_8255
help
Enable support for 8255 digital I/O as a standalone driver.
@@ -1290,10 +1329,12 @@ config COMEDI_AMPLC_DIO200
config COMEDI_AMPLC_PC236
tristate
+ depends on HAS_IOPORT
select COMEDI_8255
config COMEDI_DAS08
tristate
+ depends on HAS_IOPORT
select COMEDI_8254
select COMEDI_8255
diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
index d4e2ed709bfc..376130bfba8a 100644
--- a/drivers/comedi/drivers.c
+++ b/drivers/comedi/drivers.c
@@ -177,7 +177,8 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
dev->n_subdevices = 0;
}
kfree(dev->private);
- kfree(dev->pacer);
+ if (!IS_ERR(dev->pacer))
+ kfree(dev->pacer);
dev->private = NULL;
dev->pacer = NULL;
dev->driver = NULL;
diff --git a/drivers/comedi/drivers/8255.c b/drivers/comedi/drivers/8255.c
index ced8ea09d4fa..f45f7bd1c61a 100644
--- a/drivers/comedi/drivers/8255.c
+++ b/drivers/comedi/drivers/8255.c
@@ -80,7 +80,7 @@ static int dev_8255_attach(struct comedi_device *dev,
if (ret) {
s->type = COMEDI_SUBD_UNUSED;
} else {
- ret = subdev_8255_init(dev, s, NULL, iobase);
+ ret = subdev_8255_io_init(dev, s, iobase);
if (ret) {
/*
* Release the I/O port region here, as the
diff --git a/drivers/comedi/drivers/8255_pci.c b/drivers/comedi/drivers/8255_pci.c
index 0fec048e3a53..8498cabe4d91 100644
--- a/drivers/comedi/drivers/8255_pci.c
+++ b/drivers/comedi/drivers/8255_pci.c
@@ -57,6 +57,7 @@
#include <linux/comedi/comedi_8255.h>
enum pci_8255_boardid {
+#ifdef CONFIG_HAS_IOPORT
BOARD_ADLINK_PCI7224,
BOARD_ADLINK_PCI7248,
BOARD_ADLINK_PCI7296,
@@ -65,6 +66,7 @@ enum pci_8255_boardid {
BOARD_CB_PCIDIO48H_OLD,
BOARD_CB_PCIDIO48H_NEW,
BOARD_CB_PCIDIO96H,
+#endif /* CONFIG_HAS_IOPORT */
BOARD_NI_PCIDIO96,
BOARD_NI_PCIDIO96B,
BOARD_NI_PXI6508,
@@ -82,6 +84,7 @@ struct pci_8255_boardinfo {
};
static const struct pci_8255_boardinfo pci_8255_boards[] = {
+#ifdef CONFIG_HAS_IOPORT
[BOARD_ADLINK_PCI7224] = {
.name = "adl_pci-7224",
.dio_badr = 2,
@@ -122,6 +125,7 @@ static const struct pci_8255_boardinfo pci_8255_boards[] = {
.dio_badr = 2,
.n_8255 = 4,
},
+#endif /* CONFIG_HAS_IOPORT */
[BOARD_NI_PCIDIO96] = {
.name = "ni_pci-dio-96",
.dio_badr = 1,
@@ -219,8 +223,11 @@ static int pci_8255_auto_attach(struct comedi_device *dev,
dev->mmio = pci_ioremap_bar(pcidev, board->dio_badr);
if (!dev->mmio)
return -ENOMEM;
- } else {
+ } else if (IS_ENABLED(CONFIG_HAS_IOPORT)) {
dev->iobase = pci_resource_start(pcidev, board->dio_badr);
+ } else {
+ dev_err(dev->class_dev, "error! need I/O port support\n");
+ return -ENXIO;
}
/*
@@ -235,9 +242,9 @@ static int pci_8255_auto_attach(struct comedi_device *dev,
for (i = 0; i < board->n_8255; i++) {
s = &dev->subdevices[i];
if (dev->mmio)
- ret = subdev_8255_mm_init(dev, s, NULL, i * I8255_SIZE);
+ ret = subdev_8255_mm_init(dev, s, i * I8255_SIZE);
else
- ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE);
+ ret = subdev_8255_io_init(dev, s, i * I8255_SIZE);
if (ret)
return ret;
}
@@ -259,6 +266,7 @@ static int pci_8255_pci_probe(struct pci_dev *dev,
}
static const struct pci_device_id pci_8255_pci_table[] = {
+#ifdef CONFIG_HAS_IOPORT
{ PCI_VDEVICE(ADLINK, 0x7224), BOARD_ADLINK_PCI7224 },
{ PCI_VDEVICE(ADLINK, 0x7248), BOARD_ADLINK_PCI7248 },
{ PCI_VDEVICE(ADLINK, 0x7296), BOARD_ADLINK_PCI7296 },
@@ -269,6 +277,7 @@ static const struct pci_device_id pci_8255_pci_table[] = {
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_CB, 0x000b, PCI_VENDOR_ID_CB, 0x000b),
.driver_data = BOARD_CB_PCIDIO48H_NEW },
{ PCI_VDEVICE(CB, 0x0017), BOARD_CB_PCIDIO96H },
+#endif /* CONFIG_HAS_IOPORT */
{ PCI_VDEVICE(NI, 0x0160), BOARD_NI_PCIDIO96 },
{ PCI_VDEVICE(NI, 0x1630), BOARD_NI_PCIDIO96B },
{ PCI_VDEVICE(NI, 0x13c0), BOARD_NI_PXI6508 },
diff --git a/drivers/comedi/drivers/adl_pci9111.c b/drivers/comedi/drivers/adl_pci9111.c
index c50f94272a74..086d93f40cb9 100644
--- a/drivers/comedi/drivers/adl_pci9111.c
+++ b/drivers/comedi/drivers/adl_pci9111.c
@@ -647,10 +647,10 @@ static int pci9111_auto_attach(struct comedi_device *dev,
dev->irq = pcidev->irq;
}
- dev->pacer = comedi_8254_init(dev->iobase + PCI9111_8254_BASE_REG,
- I8254_OSC_BASE_2MHZ, I8254_IO16, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + PCI9111_8254_BASE_REG,
+ I8254_OSC_BASE_2MHZ, I8254_IO16, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
diff --git a/drivers/comedi/drivers/adl_pci9118.c b/drivers/comedi/drivers/adl_pci9118.c
index 9a816c718303..a76e2666d583 100644
--- a/drivers/comedi/drivers/adl_pci9118.c
+++ b/drivers/comedi/drivers/adl_pci9118.c
@@ -1524,10 +1524,10 @@ static int pci9118_common_attach(struct comedi_device *dev,
devpriv->iobase_a = pci_resource_start(pcidev, 0);
dev->iobase = pci_resource_start(pcidev, 2);
- dev->pacer = comedi_8254_init(dev->iobase + PCI9118_TIMER_BASE,
- I8254_OSC_BASE_4MHZ, I8254_IO32, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + PCI9118_TIMER_BASE,
+ I8254_OSC_BASE_4MHZ, I8254_IO32, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
pci9118_reset(dev);
diff --git a/drivers/comedi/drivers/adv_pci1710.c b/drivers/comedi/drivers/adv_pci1710.c
index 4f2639968260..c49b0f1f5228 100644
--- a/drivers/comedi/drivers/adv_pci1710.c
+++ b/drivers/comedi/drivers/adv_pci1710.c
@@ -767,10 +767,10 @@ static int pci1710_auto_attach(struct comedi_device *dev,
return ret;
dev->iobase = pci_resource_start(pcidev, 2);
- dev->pacer = comedi_8254_init(dev->iobase + PCI171X_TIMER_BASE,
- I8254_OSC_BASE_10MHZ, I8254_IO16, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + PCI171X_TIMER_BASE,
+ I8254_OSC_BASE_10MHZ, I8254_IO16, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
n_subdevices = 1; /* all boards have analog inputs */
if (board->has_ao)
diff --git a/drivers/comedi/drivers/adv_pci_dio.c b/drivers/comedi/drivers/adv_pci_dio.c
index efa3e46b554b..ca8054504760 100644
--- a/drivers/comedi/drivers/adv_pci_dio.c
+++ b/drivers/comedi/drivers/adv_pci_dio.c
@@ -642,8 +642,8 @@ static int pci_dio_auto_attach(struct comedi_device *dev,
for (j = 0; j < d->chans; j++) {
s = &dev->subdevices[subdev++];
- ret = subdev_8255_init(dev, s, NULL,
- d->addr + j * I8255_SIZE);
+ ret = subdev_8255_io_init(dev, s,
+ d->addr + j * I8255_SIZE);
if (ret)
return ret;
}
@@ -664,11 +664,11 @@ static int pci_dio_auto_attach(struct comedi_device *dev,
if (board->timer_regbase) {
s = &dev->subdevices[subdev++];
- dev->pacer = comedi_8254_init(dev->iobase +
- board->timer_regbase,
- 0, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer =
+ comedi_8254_io_alloc(dev->iobase + board->timer_regbase,
+ 0, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
comedi_8254_subdevice_init(s, dev->pacer);
}
diff --git a/drivers/comedi/drivers/aio_aio12_8.c b/drivers/comedi/drivers/aio_aio12_8.c
index 30b8a32204d8..227a86a3a760 100644
--- a/drivers/comedi/drivers/aio_aio12_8.c
+++ b/drivers/comedi/drivers/aio_aio12_8.c
@@ -206,10 +206,10 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
if (ret)
return ret;
- dev->pacer = comedi_8254_init(dev->iobase + AIO12_8_8254_BASE_REG,
- 0, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + AIO12_8_8254_BASE_REG,
+ 0, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
@@ -247,7 +247,7 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
/* Digital I/O subdevice (8255) */
s = &dev->subdevices[2];
- ret = subdev_8255_init(dev, s, NULL, AIO12_8_8255_BASE_REG);
+ ret = subdev_8255_io_init(dev, s, AIO12_8_8255_BASE_REG);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/amplc_dio200_common.c b/drivers/comedi/drivers/amplc_dio200_common.c
index ff651f2eb86c..b1a9b4c4a185 100644
--- a/drivers/comedi/drivers/amplc_dio200_common.c
+++ b/drivers/comedi/drivers/amplc_dio200_common.c
@@ -86,6 +86,70 @@ struct dio200_subdev_intr {
unsigned int active:1;
};
+#ifdef CONFIG_HAS_IOPORT
+
+static unsigned char dio200___read8(struct comedi_device *dev,
+ unsigned int offset)
+{
+ if (dev->mmio)
+ return readb(dev->mmio + offset);
+ return inb(dev->iobase + offset);
+}
+
+static void dio200___write8(struct comedi_device *dev,
+ unsigned int offset, unsigned char val)
+{
+ if (dev->mmio)
+ writeb(val, dev->mmio + offset);
+ else
+ outb(val, dev->iobase + offset);
+}
+
+static unsigned int dio200___read32(struct comedi_device *dev,
+ unsigned int offset)
+{
+ if (dev->mmio)
+ return readl(dev->mmio + offset);
+ return inl(dev->iobase + offset);
+}
+
+static void dio200___write32(struct comedi_device *dev,
+ unsigned int offset, unsigned int val)
+{
+ if (dev->mmio)
+ writel(val, dev->mmio + offset);
+ else
+ outl(val, dev->iobase + offset);
+}
+
+#else /* CONFIG_HAS_IOPORT */
+
+static unsigned char dio200___read8(struct comedi_device *dev,
+ unsigned int offset)
+{
+ return readb(dev->mmio + offset);
+}
+
+static void dio200___write8(struct comedi_device *dev,
+ unsigned int offset, unsigned char val)
+{
+ writeb(val, dev->mmio + offset);
+}
+
+static unsigned int dio200___read32(struct comedi_device *dev,
+ unsigned int offset)
+{
+ return readl(dev->mmio + offset);
+}
+
+static void dio200___write32(struct comedi_device *dev,
+ unsigned int offset, unsigned int val)
+{
+ writel(val, dev->mmio + offset);
+}
+
+#endif /* CONFIG_HAS_IOPORT */
+
static unsigned char dio200_read8(struct comedi_device *dev,
unsigned int offset)
{
@@ -94,9 +158,7 @@ static unsigned char dio200_read8(struct comedi_device *dev,
if (board->is_pcie)
offset <<= 3;
- if (dev->mmio)
- return readb(dev->mmio + offset);
- return inb(dev->iobase + offset);
+ return dio200___read8(dev, offset);
}
static void dio200_write8(struct comedi_device *dev,
@@ -107,10 +169,7 @@ static void dio200_write8(struct comedi_device *dev,
if (board->is_pcie)
offset <<= 3;
- if (dev->mmio)
- writeb(val, dev->mmio + offset);
- else
- outb(val, dev->iobase + offset);
+ dio200___write8(dev, offset, val);
}
static unsigned int dio200_read32(struct comedi_device *dev,
@@ -121,9 +180,7 @@ static unsigned int dio200_read32(struct comedi_device *dev,
if (board->is_pcie)
offset <<= 3;
- if (dev->mmio)
- return readl(dev->mmio + offset);
- return inl(dev->iobase + offset);
+ return dio200___read32(dev, offset);
}
static void dio200_write32(struct comedi_device *dev,
@@ -134,10 +191,7 @@ static void dio200_write32(struct comedi_device *dev,
if (board->is_pcie)
offset <<= 3;
- if (dev->mmio)
- writel(val, dev->mmio + offset);
- else
- outl(val, dev->iobase + offset);
+ dio200___write32(dev, offset, val);
}
static unsigned int dio200_subdev_8254_offset(struct comedi_device *dev,
@@ -149,9 +203,9 @@ static unsigned int dio200_subdev_8254_offset(struct comedi_device *dev,
/* get the offset that was passed to comedi_8254_*_init() */
if (dev->mmio)
- offset = i8254->mmio - dev->mmio;
+ offset = (void __iomem *)i8254->context - dev->mmio;
else
- offset = i8254->iobase - dev->iobase;
+ offset = i8254->context - dev->iobase;
/* remove the shift that was added for PCIe boards */
if (board->is_pcie)
@@ -556,14 +610,14 @@ static int dio200_subdev_8254_init(struct comedi_device *dev,
}
if (dev->mmio) {
- i8254 = comedi_8254_mm_init(dev->mmio + offset,
- 0, I8254_IO8, regshift);
+ i8254 = comedi_8254_mm_alloc(dev->mmio + offset,
+ 0, I8254_IO8, regshift);
} else {
- i8254 = comedi_8254_init(dev->iobase + offset,
- 0, I8254_IO8, regshift);
+ i8254 = comedi_8254_io_alloc(dev->iobase + offset,
+ 0, I8254_IO8, regshift);
}
- if (!i8254)
- return -ENOMEM;
+ if (IS_ERR(i8254))
+ return PTR_ERR(i8254);
comedi_8254_subdevice_init(s, i8254);
@@ -779,6 +833,12 @@ int amplc_dio200_common_attach(struct comedi_device *dev, unsigned int irq,
unsigned int n;
int ret;
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT) && !dev->mmio) {
+ dev_err(dev->class_dev,
+ "error! need I/O port support\n");
+ return -ENXIO;
+ }
+
ret = comedi_alloc_subdevices(dev, board->n_subdevs);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/amplc_dio200_pci.c b/drivers/comedi/drivers/amplc_dio200_pci.c
index 527994d82a1f..cb5b328a28e3 100644
--- a/drivers/comedi/drivers/amplc_dio200_pci.c
+++ b/drivers/comedi/drivers/amplc_dio200_pci.c
@@ -223,14 +223,17 @@
*/
enum dio200_pci_model {
+#ifdef CONFIG_HAS_IOPORT
pci215_model,
pci272_model,
+#endif /* CONFIG_HAS_IOPORT */
pcie215_model,
pcie236_model,
pcie296_model
};
static const struct dio200_board dio200_pci_boards[] = {
+#ifdef CONFIG_HAS_IOPORT
[pci215_model] = {
.name = "pci215",
.mainbar = 2,
@@ -252,6 +255,7 @@ static const struct dio200_board dio200_pci_boards[] = {
.sdinfo = { 0x00, 0x08, 0x10, 0x3f },
.has_int_sce = true,
},
+#endif /* CONFIG_HAS_IOPORT */
[pcie215_model] = {
.name = "pcie215",
.mainbar = 1,
@@ -364,8 +368,12 @@ static int dio200_pci_auto_attach(struct comedi_device *dev,
"error! cannot remap registers\n");
return -ENOMEM;
}
- } else {
+ } else if (IS_ENABLED(CONFIG_HAS_IOPORT)) {
dev->iobase = pci_resource_start(pci_dev, bar);
+ } else {
+ dev_err(dev->class_dev,
+ "error! need I/O port support\n");
+ return -ENXIO;
}
if (board->is_pcie) {
@@ -385,8 +393,10 @@ static struct comedi_driver dio200_pci_comedi_driver = {
};
static const struct pci_device_id dio200_pci_table[] = {
+#ifdef CONFIG_HAS_IOPORT
{ PCI_VDEVICE(AMPLICON, 0x000b), pci215_model },
{ PCI_VDEVICE(AMPLICON, 0x000a), pci272_model },
+#endif /* CONFIG_HAS_IOPORT */
{ PCI_VDEVICE(AMPLICON, 0x0011), pcie236_model },
{ PCI_VDEVICE(AMPLICON, 0x0012), pcie215_model },
{ PCI_VDEVICE(AMPLICON, 0x0014), pcie296_model },
diff --git a/drivers/comedi/drivers/amplc_pc236_common.c b/drivers/comedi/drivers/amplc_pc236_common.c
index 9f4f89b1ef23..326ca72c24ec 100644
--- a/drivers/comedi/drivers/amplc_pc236_common.c
+++ b/drivers/comedi/drivers/amplc_pc236_common.c
@@ -147,7 +147,7 @@ int amplc_pc236_common_attach(struct comedi_device *dev, unsigned long iobase,
s = &dev->subdevices[0];
/* digital i/o subdevice (8255) */
- ret = subdev_8255_init(dev, s, NULL, 0x00);
+ ret = subdev_8255_io_init(dev, s, 0x00);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/amplc_pci224.c b/drivers/comedi/drivers/amplc_pci224.c
index 5a04e55daeea..1373637c2ca2 100644
--- a/drivers/comedi/drivers/amplc_pci224.c
+++ b/drivers/comedi/drivers/amplc_pci224.c
@@ -1051,10 +1051,10 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_model)
outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
dev->iobase + PCI224_DACCON);
- dev->pacer = comedi_8254_init(devpriv->iobase1 + PCI224_Z2_BASE,
- I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(devpriv->iobase1 + PCI224_Z2_BASE,
+ I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 1);
if (ret)
diff --git a/drivers/comedi/drivers/amplc_pci230.c b/drivers/comedi/drivers/amplc_pci230.c
index 92ba8b8c0172..c74209c2e83a 100644
--- a/drivers/comedi/drivers/amplc_pci230.c
+++ b/drivers/comedi/drivers/amplc_pci230.c
@@ -2475,10 +2475,10 @@ static int pci230_auto_attach(struct comedi_device *dev,
dev->irq = pci_dev->irq;
}
- dev->pacer = comedi_8254_init(dev->iobase + PCI230_Z2_CT_BASE,
- 0, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + PCI230_Z2_CT_BASE,
+ 0, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
rc = comedi_alloc_subdevices(dev, 3);
if (rc)
@@ -2529,7 +2529,7 @@ static int pci230_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[2];
/* digital i/o subdevice */
if (board->have_dio) {
- rc = subdev_8255_init(dev, s, NULL, PCI230_PPI_X_BASE);
+ rc = subdev_8255_io_init(dev, s, PCI230_PPI_X_BASE);
if (rc)
return rc;
} else {
diff --git a/drivers/comedi/drivers/cb_das16_cs.c b/drivers/comedi/drivers/cb_das16_cs.c
index 8e0d2fa5f95d..306208a0695b 100644
--- a/drivers/comedi/drivers/cb_das16_cs.c
+++ b/drivers/comedi/drivers/cb_das16_cs.c
@@ -363,10 +363,10 @@ static int das16cs_auto_attach(struct comedi_device *dev,
if (!devpriv)
return -ENOMEM;
- dev->pacer = comedi_8254_init(dev->iobase + DAS16CS_TIMER_BASE,
- I8254_OSC_BASE_10MHZ, I8254_IO16, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + DAS16CS_TIMER_BASE,
+ I8254_OSC_BASE_10MHZ, I8254_IO16, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
diff --git a/drivers/comedi/drivers/cb_pcidas.c b/drivers/comedi/drivers/cb_pcidas.c
index 0c7576b967fc..8bb9b0623869 100644
--- a/drivers/comedi/drivers/cb_pcidas.c
+++ b/drivers/comedi/drivers/cb_pcidas.c
@@ -1288,16 +1288,16 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
}
dev->irq = pcidev->irq;
- dev->pacer = comedi_8254_init(dev->iobase + PCIDAS_AI_8254_BASE,
- I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + PCIDAS_AI_8254_BASE,
+ I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
- devpriv->ao_pacer = comedi_8254_init(dev->iobase + PCIDAS_AO_8254_BASE,
- I8254_OSC_BASE_10MHZ,
- I8254_IO8, 0);
- if (!devpriv->ao_pacer)
- return -ENOMEM;
+ devpriv->ao_pacer =
+ comedi_8254_io_alloc(dev->iobase + PCIDAS_AO_8254_BASE,
+ I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
+ if (IS_ERR(devpriv->ao_pacer))
+ return PTR_ERR(devpriv->ao_pacer);
ret = comedi_alloc_subdevices(dev, 7);
if (ret)
@@ -1352,7 +1352,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
/* 8255 */
s = &dev->subdevices[2];
- ret = subdev_8255_init(dev, s, NULL, PCIDAS_8255_BASE);
+ ret = subdev_8255_io_init(dev, s, PCIDAS_8255_BASE);
if (ret)
return ret;
@@ -1453,7 +1453,8 @@ static void cb_pcidas_detach(struct comedi_device *dev)
if (devpriv->amcc)
outl(INTCSR_INBOX_INTR_STATUS,
devpriv->amcc + AMCC_OP_REG_INTCSR);
- kfree(devpriv->ao_pacer);
+ if (!IS_ERR(devpriv->ao_pacer))
+ kfree(devpriv->ao_pacer);
}
comedi_pci_detach(dev);
}
diff --git a/drivers/comedi/drivers/cb_pcidas64.c b/drivers/comedi/drivers/cb_pcidas64.c
index ca6038a25f26..ff19fc3859e4 100644
--- a/drivers/comedi/drivers/cb_pcidas64.c
+++ b/drivers/comedi/drivers/cb_pcidas64.c
@@ -3877,11 +3877,10 @@ static int setup_subdevices(struct comedi_device *dev)
s = &dev->subdevices[4];
if (board->has_8255) {
if (board->layout == LAYOUT_4020) {
- ret = subdev_8255_init(dev, s, dio_callback_4020,
- I8255_4020_REG);
+ ret = subdev_8255_cb_init(dev, s, dio_callback_4020,
+ I8255_4020_REG);
} else {
- ret = subdev_8255_mm_init(dev, s, NULL,
- DIO_8255_OFFSET);
+ ret = subdev_8255_mm_init(dev, s, DIO_8255_OFFSET);
}
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/cb_pcidda.c b/drivers/comedi/drivers/cb_pcidda.c
index c52204a6bda4..c353d0f87da9 100644
--- a/drivers/comedi/drivers/cb_pcidda.c
+++ b/drivers/comedi/drivers/cb_pcidda.c
@@ -365,7 +365,7 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev,
/* two 8255 digital io subdevices */
for (i = 0; i < 2; i++) {
s = &dev->subdevices[1 + i];
- ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE);
+ ret = subdev_8255_io_init(dev, s, i * I8255_SIZE);
if (ret)
return ret;
}
diff --git a/drivers/comedi/drivers/cb_pcimdas.c b/drivers/comedi/drivers/cb_pcimdas.c
index 8bdb00774f11..641c30df392e 100644
--- a/drivers/comedi/drivers/cb_pcimdas.c
+++ b/drivers/comedi/drivers/cb_pcimdas.c
@@ -364,11 +364,11 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev,
devpriv->BADR3 = pci_resource_start(pcidev, 3);
dev->iobase = pci_resource_start(pcidev, 4);
- dev->pacer = comedi_8254_init(devpriv->BADR3 + PCIMDAS_8254_BASE,
- cb_pcimdas_pacer_clk(dev),
- I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(devpriv->BADR3 + PCIMDAS_8254_BASE,
+ cb_pcimdas_pacer_clk(dev),
+ I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 6);
if (ret)
@@ -405,7 +405,7 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev,
/* Digital I/O subdevice */
s = &dev->subdevices[2];
- ret = subdev_8255_init(dev, s, NULL, PCIMDAS_8255_BASE);
+ ret = subdev_8255_io_init(dev, s, PCIMDAS_8255_BASE);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/cb_pcimdda.c b/drivers/comedi/drivers/cb_pcimdda.c
index bf8093a10315..541b5742bb1b 100644
--- a/drivers/comedi/drivers/cb_pcimdda.c
+++ b/drivers/comedi/drivers/cb_pcimdda.c
@@ -154,7 +154,7 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[1];
/* digital i/o subdevice */
- return subdev_8255_init(dev, s, NULL, PCIMDDA_8255_BASE_REG);
+ return subdev_8255_io_init(dev, s, PCIMDDA_8255_BASE_REG);
}
static struct comedi_driver cb_pcimdda_driver = {
diff --git a/drivers/comedi/drivers/comedi_8254.c b/drivers/comedi/drivers/comedi_8254.c
index b4185c1b2695..6beca2a6d66e 100644
--- a/drivers/comedi/drivers/comedi_8254.c
+++ b/drivers/comedi/drivers/comedi_8254.c
@@ -24,14 +24,17 @@
*
* This module provides the following basic functions:
*
- * comedi_8254_init() / comedi_8254_mm_init()
+ * comedi_8254_io_alloc() / comedi_8254_mm_alloc()
* Initializes this module to access the 8254 registers. The _mm version
- * sets up the module for MMIO register access the other for PIO access.
- * The pointer returned from these functions is normally stored in the
- * comedi_device dev->pacer and will be freed by the comedi core during
- * the driver (*detach). If a driver has multiple 8254 devices, they need
- * to be stored in the drivers private data and freed when the driver is
- * detached.
+ * sets up the module for MMIO register access; the _io version sets it
+ * up for PIO access. These functions return a pointer to a struct
+ * comedi_8254 on success, or an ERR_PTR value on failure. The pointer
+ * returned from these functions is normally stored in the comedi_device
+ * dev->pacer and will be freed by the comedi core during the driver
+ * (*detach). If a driver has multiple 8254 devices, they need to be
+ * stored in the drivers private data and freed when the driver is
+ * detached. If the ERR_PTR value is stored, code should check the
+ * pointer value with !IS_ERR(pointer) before freeing.
*
* NOTE: The counters are reset by setting them to I8254_MODE0 as part of
* this initialization.
@@ -119,63 +122,105 @@
#include <linux/comedi/comedidev.h>
#include <linux/comedi/comedi_8254.h>
-static unsigned int __i8254_read(struct comedi_8254 *i8254, unsigned int reg)
+#ifdef CONFIG_HAS_IOPORT
+
+static unsigned int i8254_io8_cb(struct comedi_8254 *i8254, int dir,
+ unsigned int reg, unsigned int val)
{
- unsigned int reg_offset = (reg * i8254->iosize) << i8254->regshift;
- unsigned int val;
+ unsigned long iobase = i8254->context;
+ unsigned int reg_offset = (reg * I8254_IO8) << i8254->regshift;
- switch (i8254->iosize) {
- default:
- case I8254_IO8:
- if (i8254->mmio)
- val = readb(i8254->mmio + reg_offset);
- else
- val = inb(i8254->iobase + reg_offset);
- break;
- case I8254_IO16:
- if (i8254->mmio)
- val = readw(i8254->mmio + reg_offset);
- else
- val = inw(i8254->iobase + reg_offset);
- break;
- case I8254_IO32:
- if (i8254->mmio)
- val = readl(i8254->mmio + reg_offset);
- else
- val = inl(i8254->iobase + reg_offset);
- break;
+ if (dir) {
+ outb(val, iobase + reg_offset);
+ return 0;
+ } else {
+ return inb(iobase + reg_offset);
}
- return val & 0xff;
}
-static void __i8254_write(struct comedi_8254 *i8254,
- unsigned int val, unsigned int reg)
+static unsigned int i8254_io16_cb(struct comedi_8254 *i8254, int dir,
+ unsigned int reg, unsigned int val)
{
- unsigned int reg_offset = (reg * i8254->iosize) << i8254->regshift;
+ unsigned long iobase = i8254->context;
+ unsigned int reg_offset = (reg * I8254_IO16) << i8254->regshift;
- switch (i8254->iosize) {
- default:
- case I8254_IO8:
- if (i8254->mmio)
- writeb(val, i8254->mmio + reg_offset);
- else
- outb(val, i8254->iobase + reg_offset);
- break;
- case I8254_IO16:
- if (i8254->mmio)
- writew(val, i8254->mmio + reg_offset);
- else
- outw(val, i8254->iobase + reg_offset);
- break;
- case I8254_IO32:
- if (i8254->mmio)
- writel(val, i8254->mmio + reg_offset);
- else
- outl(val, i8254->iobase + reg_offset);
- break;
+ if (dir) {
+ outw(val, iobase + reg_offset);
+ return 0;
+ } else {
+ return inw(iobase + reg_offset);
}
}
+static unsigned int i8254_io32_cb(struct comedi_8254 *i8254, int dir,
+ unsigned int reg, unsigned int val)
+{
+ unsigned long iobase = i8254->context;
+ unsigned int reg_offset = (reg * I8254_IO32) << i8254->regshift;
+
+ if (dir) {
+ outl(val, iobase + reg_offset);
+ return 0;
+ } else {
+ return inl(iobase + reg_offset);
+ }
+}
+
+#endif /* CONFIG_HAS_IOPORT */
+
+static unsigned int i8254_mmio8_cb(struct comedi_8254 *i8254, int dir,
+ unsigned int reg, unsigned int val)
+{
+ void __iomem *mmiobase = (void __iomem *)i8254->context;
+ unsigned int reg_offset = (reg * I8254_IO8) << i8254->regshift;
+
+ if (dir) {
+ writeb(val, mmiobase + reg_offset);
+ return 0;
+ } else {
+ return readb(mmiobase + reg_offset);
+ }
+}
+
+static unsigned int i8254_mmio16_cb(struct comedi_8254 *i8254, int dir,
+ unsigned int reg, unsigned int val)
+{
+ void __iomem *mmiobase = (void __iomem *)i8254->context;
+ unsigned int reg_offset = (reg * I8254_IO16) << i8254->regshift;
+
+ if (dir) {
+ writew(val, mmiobase + reg_offset);
+ return 0;
+ } else {
+ return readw(mmiobase + reg_offset);
+ }
+}
+
+static unsigned int i8254_mmio32_cb(struct comedi_8254 *i8254, int dir,
+ unsigned int reg, unsigned int val)
+{
+ void __iomem *mmiobase = (void __iomem *)i8254->context;
+ unsigned int reg_offset = (reg * I8254_IO32) << i8254->regshift;
+
+ if (dir) {
+ writel(val, mmiobase + reg_offset);
+ return 0;
+ } else {
+ return readl(mmiobase + reg_offset);
+ }
+}
+
+static unsigned int __i8254_read(struct comedi_8254 *i8254, unsigned int reg)
+{
+ return 0xff & i8254->iocb(i8254, 0, reg, 0);
+}
+
+static void __i8254_write(struct comedi_8254 *i8254,
+ unsigned int val, unsigned int reg)
+{
+ i8254->iocb(i8254, 1, reg, val);
+}
+
/**
* comedi_8254_status - return the status of a counter
* @i8254: comedi_8254 struct for the timer
@@ -571,8 +616,8 @@ void comedi_8254_subdevice_init(struct comedi_subdevice *s,
}
EXPORT_SYMBOL_GPL(comedi_8254_subdevice_init);
-static struct comedi_8254 *__i8254_init(unsigned long iobase,
- void __iomem *mmio,
+static struct comedi_8254 *__i8254_init(comedi_8254_iocb_fn *iocb,
+ unsigned long context,
unsigned int osc_base,
unsigned int iosize,
unsigned int regshift)
@@ -583,14 +628,17 @@ static struct comedi_8254 *__i8254_init(unsigned long iobase,
/* sanity check that the iosize is valid */
if (!(iosize == I8254_IO8 || iosize == I8254_IO16 ||
iosize == I8254_IO32))
- return NULL;
+ return ERR_PTR(-EINVAL);
+
+ if (!iocb)
+ return ERR_PTR(-EINVAL);
i8254 = kzalloc(sizeof(*i8254), GFP_KERNEL);
if (!i8254)
- return NULL;
+ return ERR_PTR(-ENOMEM);
- i8254->iobase = iobase;
- i8254->mmio = mmio;
+ i8254->iocb = iocb;
+ i8254->context = context;
i8254->iosize = iosize;
i8254->regshift = regshift;
@@ -604,39 +652,77 @@ static struct comedi_8254 *__i8254_init(unsigned long iobase,
return i8254;
}
+#ifdef CONFIG_HAS_IOPORT
+
/**
- * comedi_8254_init - allocate and initialize the 8254 device for pio access
+ * comedi_8254_io_alloc - allocate and initialize the 8254 device for pio access
* @iobase: port I/O base address
* @osc_base: base time of the counter in ns
* OPTIONAL - only used by comedi_8254_cascade_ns_to_timer()
* @iosize: I/O register size
* @regshift: register gap shift
+ *
+ * Return: A pointer to a struct comedi_8254 or an ERR_PTR value.
*/
-struct comedi_8254 *comedi_8254_init(unsigned long iobase,
- unsigned int osc_base,
- unsigned int iosize,
- unsigned int regshift)
+struct comedi_8254 *comedi_8254_io_alloc(unsigned long iobase,
+ unsigned int osc_base,
+ unsigned int iosize,
+ unsigned int regshift)
{
- return __i8254_init(iobase, NULL, osc_base, iosize, regshift);
+ comedi_8254_iocb_fn *iocb;
+
+ switch (iosize) {
+ case I8254_IO8:
+ iocb = i8254_io8_cb;
+ break;
+ case I8254_IO16:
+ iocb = i8254_io16_cb;
+ break;
+ case I8254_IO32:
+ iocb = i8254_io32_cb;
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+ return __i8254_init(iocb, iobase, osc_base, iosize, regshift);
}
-EXPORT_SYMBOL_GPL(comedi_8254_init);
+EXPORT_SYMBOL_GPL(comedi_8254_io_alloc);
+
+#endif /* CONFIG_HAS_IOPORT */
/**
- * comedi_8254_mm_init - allocate and initialize the 8254 device for mmio access
+ * comedi_8254_mm_alloc - allocate and initialize the 8254 device for mmio access
* @mmio: memory mapped I/O base address
* @osc_base: base time of the counter in ns
* OPTIONAL - only used by comedi_8254_cascade_ns_to_timer()
* @iosize: I/O register size
* @regshift: register gap shift
+ *
+ * Return: A pointer to a struct comedi_8254 or an ERR_PTR value.
*/
-struct comedi_8254 *comedi_8254_mm_init(void __iomem *mmio,
- unsigned int osc_base,
- unsigned int iosize,
- unsigned int regshift)
+struct comedi_8254 *comedi_8254_mm_alloc(void __iomem *mmio,
+ unsigned int osc_base,
+ unsigned int iosize,
+ unsigned int regshift)
{
- return __i8254_init(0, mmio, osc_base, iosize, regshift);
+ comedi_8254_iocb_fn *iocb;
+
+ switch (iosize) {
+ case I8254_IO8:
+ iocb = i8254_mmio8_cb;
+ break;
+ case I8254_IO16:
+ iocb = i8254_mmio16_cb;
+ break;
+ case I8254_IO32:
+ iocb = i8254_mmio32_cb;
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+ return __i8254_init(iocb, (unsigned long)mmio, osc_base, iosize, regshift);
}
-EXPORT_SYMBOL_GPL(comedi_8254_mm_init);
+EXPORT_SYMBOL_GPL(comedi_8254_mm_alloc);
static int __init comedi_8254_module_init(void)
{
diff --git a/drivers/comedi/drivers/comedi_8255.c b/drivers/comedi/drivers/comedi_8255.c
index 5562b9cd0a17..e4974b508328 100644
--- a/drivers/comedi/drivers/comedi_8255.c
+++ b/drivers/comedi/drivers/comedi_8255.c
@@ -33,11 +33,13 @@
#include <linux/comedi/comedi_8255.h>
struct subdev_8255_private {
- unsigned long regbase;
+ unsigned long context;
int (*io)(struct comedi_device *dev, int dir, int port, int data,
- unsigned long regbase);
+ unsigned long context);
};
+#ifdef CONFIG_HAS_IOPORT
+
static int subdev_8255_io(struct comedi_device *dev,
int dir, int port, int data, unsigned long regbase)
{
@@ -48,6 +50,8 @@ static int subdev_8255_io(struct comedi_device *dev,
return inb(dev->iobase + regbase + port);
}
+#endif /* CONFIG_HAS_IOPORT */
+
static int subdev_8255_mmio(struct comedi_device *dev,
int dir, int port, int data, unsigned long regbase)
{
@@ -64,7 +68,7 @@ static int subdev_8255_insn(struct comedi_device *dev,
unsigned int *data)
{
struct subdev_8255_private *spriv = s->private;
- unsigned long regbase = spriv->regbase;
+ unsigned long context = spriv->context;
unsigned int mask;
unsigned int v;
@@ -72,18 +76,18 @@ static int subdev_8255_insn(struct comedi_device *dev,
if (mask) {
if (mask & 0xff)
spriv->io(dev, 1, I8255_DATA_A_REG,
- s->state & 0xff, regbase);
+ s->state & 0xff, context);
if (mask & 0xff00)
spriv->io(dev, 1, I8255_DATA_B_REG,
- (s->state >> 8) & 0xff, regbase);
+ (s->state >> 8) & 0xff, context);
if (mask & 0xff0000)
spriv->io(dev, 1, I8255_DATA_C_REG,
- (s->state >> 16) & 0xff, regbase);
+ (s->state >> 16) & 0xff, context);
}
- v = spriv->io(dev, 0, I8255_DATA_A_REG, 0, regbase);
- v |= (spriv->io(dev, 0, I8255_DATA_B_REG, 0, regbase) << 8);
- v |= (spriv->io(dev, 0, I8255_DATA_C_REG, 0, regbase) << 16);
+ v = spriv->io(dev, 0, I8255_DATA_A_REG, 0, context);
+ v |= (spriv->io(dev, 0, I8255_DATA_B_REG, 0, context) << 8);
+ v |= (spriv->io(dev, 0, I8255_DATA_C_REG, 0, context) << 16);
data[1] = v;
@@ -94,7 +98,7 @@ static void subdev_8255_do_config(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct subdev_8255_private *spriv = s->private;
- unsigned long regbase = spriv->regbase;
+ unsigned long context = spriv->context;
int config;
config = I8255_CTRL_CW;
@@ -108,7 +112,7 @@ static void subdev_8255_do_config(struct comedi_device *dev,
if (!(s->io_bits & 0xf00000))
config |= I8255_CTRL_C_HI_IO;
- spriv->io(dev, 1, I8255_CTRL_REG, config, regbase);
+ spriv->io(dev, 1, I8255_CTRL_REG, config, context);
}
static int subdev_8255_insn_config(struct comedi_device *dev,
@@ -142,23 +146,19 @@ static int __subdev_8255_init(struct comedi_device *dev,
struct comedi_subdevice *s,
int (*io)(struct comedi_device *dev,
int dir, int port, int data,
- unsigned long regbase),
- unsigned long regbase,
- bool is_mmio)
+ unsigned long context),
+ unsigned long context)
{
struct subdev_8255_private *spriv;
+ if (!io)
+ return -EINVAL;
+
spriv = comedi_alloc_spriv(s, sizeof(*spriv));
if (!spriv)
return -ENOMEM;
- if (io)
- spriv->io = io;
- else if (is_mmio)
- spriv->io = subdev_8255_mmio;
- else
- spriv->io = subdev_8255_io;
- spriv->regbase = regbase;
+ spriv->context = context;
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -173,89 +173,88 @@ static int __subdev_8255_init(struct comedi_device *dev,
return 0;
}
+#ifdef CONFIG_HAS_IOPORT
+
/**
- * subdev_8255_init - initialize DIO subdevice for driving I/O mapped 8255
+ * subdev_8255_io_init - initialize DIO subdevice for driving I/O mapped 8255
* @dev: comedi device owning subdevice
* @s: comedi subdevice to initialize
- * @io: (optional) register I/O call-back function
- * @regbase: offset of 8255 registers from dev->iobase, or call-back context
+ * @regbase: offset of 8255 registers from dev->iobase
*
* Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip.
*
- * If the optional I/O call-back function is provided, its prototype is of
- * the following form:
- *
- * int my_8255_callback(struct comedi_device *dev, int dir, int port,
- * int data, unsigned long regbase);
- *
- * where 'dev', and 'regbase' match the values passed to this function,
- * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir'
- * is the direction (0 for read, 1 for write) and 'data' is the value to be
- * written. It should return 0 if writing or the value read if reading.
- *
- * If the optional I/O call-back function is not provided, an internal
- * call-back function is used which uses consecutive I/O port addresses
- * starting at dev->iobase + regbase.
- *
* Return: -ENOMEM if failed to allocate memory, zero on success.
*/
-int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s,
- int (*io)(struct comedi_device *dev, int dir, int port,
- int data, unsigned long regbase),
+int subdev_8255_io_init(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned long regbase)
{
- return __subdev_8255_init(dev, s, io, regbase, false);
+ return __subdev_8255_init(dev, s, subdev_8255_io, regbase);
}
-EXPORT_SYMBOL_GPL(subdev_8255_init);
+EXPORT_SYMBOL_GPL(subdev_8255_io_init);
+
+#endif /* CONFIG_HAS_IOPORT */
/**
* subdev_8255_mm_init - initialize DIO subdevice for driving mmio-mapped 8255
* @dev: comedi device owning subdevice
* @s: comedi subdevice to initialize
- * @io: (optional) register I/O call-back function
- * @regbase: offset of 8255 registers from dev->mmio, or call-back context
+ * @regbase: offset of 8255 registers from dev->mmio
*
* Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip.
*
- * If the optional I/O call-back function is provided, its prototype is of
- * the following form:
+ * Return: -ENOMEM if failed to allocate memory, zero on success.
+ */
+int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s,
+ unsigned long regbase)
+{
+ return __subdev_8255_init(dev, s, subdev_8255_mmio, regbase);
+}
+EXPORT_SYMBOL_GPL(subdev_8255_mm_init);
+
+/**
+ * subdev_8255_cb_init - initialize DIO subdevice for driving callback-mapped 8255
+ * @dev: comedi device owning subdevice
+ * @s: comedi subdevice to initialize
+ * @io: register I/O call-back function
+ * @context: call-back context
+ *
+ * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip.
+ *
+ * The prototype of the I/O call-back function is of the following form:
*
* int my_8255_callback(struct comedi_device *dev, int dir, int port,
- * int data, unsigned long regbase);
+ * int data, unsigned long context);
*
- * where 'dev', and 'regbase' match the values passed to this function,
+ * where 'dev', and 'context' match the values passed to this function,
* 'port' is the 8255 port number 0 to 3 (including the control port), 'dir'
* is the direction (0 for read, 1 for write) and 'data' is the value to be
* written. It should return 0 if writing or the value read if reading.
*
- * If the optional I/O call-back function is not provided, an internal
- * call-back function is used which uses consecutive MMIO virtual addresses
- * starting at dev->mmio + regbase.
*
* Return: -ENOMEM if failed to allocate memory, zero on success.
*/
-int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s,
+int subdev_8255_cb_init(struct comedi_device *dev, struct comedi_subdevice *s,
int (*io)(struct comedi_device *dev, int dir, int port,
- int data, unsigned long regbase),
- unsigned long regbase)
+ int data, unsigned long context),
+ unsigned long context)
{
- return __subdev_8255_init(dev, s, io, regbase, true);
+ return __subdev_8255_init(dev, s, io, context);
}
-EXPORT_SYMBOL_GPL(subdev_8255_mm_init);
+EXPORT_SYMBOL_GPL(subdev_8255_cb_init);
/**
* subdev_8255_regbase - get offset of 8255 registers or call-back context
* @s: comedi subdevice
*
- * Returns the 'regbase' parameter that was previously passed to
- * subdev_8255_init() or subdev_8255_mm_init() to set up the subdevice.
- * Only valid if the subdevice was set up successfully.
+ * Returns the 'regbase' or 'context' parameter that was previously passed to
+ * subdev_8255_io_init(), subdev_8255_mm_init(), or subdev_8255_cb_init() to
+ * set up the subdevice. Only valid if the subdevice was set up successfully.
*/
unsigned long subdev_8255_regbase(struct comedi_subdevice *s)
{
struct subdev_8255_private *spriv = s->private;
- return spriv->regbase;
+ return spriv->context;
}
EXPORT_SYMBOL_GPL(subdev_8255_regbase);
diff --git a/drivers/comedi/drivers/daqboard2000.c b/drivers/comedi/drivers/daqboard2000.c
index c0a4e1b06fb3..897bf46b95ee 100644
--- a/drivers/comedi/drivers/daqboard2000.c
+++ b/drivers/comedi/drivers/daqboard2000.c
@@ -738,8 +738,8 @@ static int db2k_auto_attach(struct comedi_device *dev, unsigned long context)
return result;
s = &dev->subdevices[2];
- return subdev_8255_init(dev, s, db2k_8255_cb,
- DB2K_REG_DIO_P2_EXP_IO_8_BIT);
+ return subdev_8255_cb_init(dev, s, db2k_8255_cb,
+ DB2K_REG_DIO_P2_EXP_IO_8_BIT);
}
static void db2k_detach(struct comedi_device *dev)
diff --git a/drivers/comedi/drivers/das08.c b/drivers/comedi/drivers/das08.c
index f8ab3af2e391..5d5b9174f88a 100644
--- a/drivers/comedi/drivers/das08.c
+++ b/drivers/comedi/drivers/das08.c
@@ -429,7 +429,7 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
s = &dev->subdevices[4];
/* 8255 */
if (board->i8255_offset != 0) {
- ret = subdev_8255_init(dev, s, NULL, board->i8255_offset);
+ ret = subdev_8255_io_init(dev, s, board->i8255_offset);
if (ret)
return ret;
} else {
@@ -439,10 +439,11 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
/* Counter subdevice (8254) */
s = &dev->subdevices[5];
if (board->i8254_offset) {
- dev->pacer = comedi_8254_init(dev->iobase + board->i8254_offset,
- 0, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer =
+ comedi_8254_io_alloc(dev->iobase + board->i8254_offset,
+ 0, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
comedi_8254_subdevice_init(s, dev->pacer);
} else {
diff --git a/drivers/comedi/drivers/das16.c b/drivers/comedi/drivers/das16.c
index 728dc02156c8..4ed56a02150e 100644
--- a/drivers/comedi/drivers/das16.c
+++ b/drivers/comedi/drivers/das16.c
@@ -1067,10 +1067,10 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
osc_base = I8254_OSC_BASE_1MHZ / it->options[3];
}
- dev->pacer = comedi_8254_init(dev->iobase + DAS16_TIMER_BASE_REG,
- osc_base, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + DAS16_TIMER_BASE_REG,
+ osc_base, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
das16_alloc_dma(dev, it->options[2]);
@@ -1145,7 +1145,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* 8255 Digital I/O subdevice */
if (board->has_8255) {
s = &dev->subdevices[4];
- ret = subdev_8255_init(dev, s, NULL, board->i8255_offset);
+ ret = subdev_8255_io_init(dev, s, board->i8255_offset);
if (ret)
return ret;
}
diff --git a/drivers/comedi/drivers/das16m1.c b/drivers/comedi/drivers/das16m1.c
index 275effb77746..b8ea737ad3d1 100644
--- a/drivers/comedi/drivers/das16m1.c
+++ b/drivers/comedi/drivers/das16m1.c
@@ -529,15 +529,16 @@ static int das16m1_attach(struct comedi_device *dev,
dev->irq = it->options[1];
}
- dev->pacer = comedi_8254_init(dev->iobase + DAS16M1_8254_IOBASE2,
- I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + DAS16M1_8254_IOBASE2,
+ I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
- devpriv->counter = comedi_8254_init(dev->iobase + DAS16M1_8254_IOBASE1,
- 0, I8254_IO8, 0);
- if (!devpriv->counter)
- return -ENOMEM;
+ devpriv->counter =
+ comedi_8254_io_alloc(dev->iobase + DAS16M1_8254_IOBASE1,
+ 0, I8254_IO8, 0);
+ if (IS_ERR(devpriv->counter))
+ return PTR_ERR(devpriv->counter);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
@@ -582,7 +583,7 @@ static int das16m1_attach(struct comedi_device *dev,
/* Digital I/O subdevice (8255) */
s = &dev->subdevices[3];
- ret = subdev_8255_init(dev, s, NULL, DAS16M1_8255_IOBASE);
+ ret = subdev_8255_io_init(dev, s, DAS16M1_8255_IOBASE);
if (ret)
return ret;
@@ -603,7 +604,8 @@ static void das16m1_detach(struct comedi_device *dev)
if (devpriv) {
if (devpriv->extra_iobase)
release_region(devpriv->extra_iobase, DAS16M1_SIZE2);
- kfree(devpriv->counter);
+ if (!IS_ERR(devpriv->counter))
+ kfree(devpriv->counter);
}
comedi_legacy_detach(dev);
}
diff --git a/drivers/comedi/drivers/das1800.c b/drivers/comedi/drivers/das1800.c
index f09608c0f4ff..7117c67aee7e 100644
--- a/drivers/comedi/drivers/das1800.c
+++ b/drivers/comedi/drivers/das1800.c
@@ -1233,10 +1233,10 @@ static int das1800_attach(struct comedi_device *dev,
if (!devpriv->fifo_buf)
return -ENOMEM;
- dev->pacer = comedi_8254_init(dev->iobase + DAS1800_COUNTER,
- I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + DAS1800_COUNTER,
+ I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
diff --git a/drivers/comedi/drivers/das6402.c b/drivers/comedi/drivers/das6402.c
index 1af394591e74..68f95330de45 100644
--- a/drivers/comedi/drivers/das6402.c
+++ b/drivers/comedi/drivers/das6402.c
@@ -590,10 +590,10 @@ static int das6402_attach(struct comedi_device *dev,
}
}
- dev->pacer = comedi_8254_init(dev->iobase + DAS6402_TIMER_BASE,
- I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + DAS6402_TIMER_BASE,
+ I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
diff --git a/drivers/comedi/drivers/das800.c b/drivers/comedi/drivers/das800.c
index 4ca33f46eaa7..300775523031 100644
--- a/drivers/comedi/drivers/das800.c
+++ b/drivers/comedi/drivers/das800.c
@@ -672,10 +672,10 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev->irq = irq;
}
- dev->pacer = comedi_8254_init(dev->iobase + DAS800_8254,
- I8254_OSC_BASE_1MHZ, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + DAS800_8254,
+ I8254_OSC_BASE_1MHZ, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 3);
if (ret)
diff --git a/drivers/comedi/drivers/dmm32at.c b/drivers/comedi/drivers/dmm32at.c
index fe023c722aa3..644e3b643c79 100644
--- a/drivers/comedi/drivers/dmm32at.c
+++ b/drivers/comedi/drivers/dmm32at.c
@@ -599,7 +599,8 @@ static int dmm32at_attach(struct comedi_device *dev,
/* Digital I/O subdevice */
s = &dev->subdevices[2];
- return subdev_8255_init(dev, s, dmm32at_8255_io, DMM32AT_8255_IOBASE);
+ return subdev_8255_cb_init(dev, s, dmm32at_8255_io,
+ DMM32AT_8255_IOBASE);
}
static struct comedi_driver dmm32at_driver = {
diff --git a/drivers/comedi/drivers/me4000.c b/drivers/comedi/drivers/me4000.c
index 9aea02b86ed9..7dd3a0071863 100644
--- a/drivers/comedi/drivers/me4000.c
+++ b/drivers/comedi/drivers/me4000.c
@@ -1209,9 +1209,9 @@ static int me4000_auto_attach(struct comedi_device *dev,
if (!timer_base)
return -ENODEV;
- dev->pacer = comedi_8254_init(timer_base, 0, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(timer_base, 0, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
comedi_8254_subdevice_init(s, dev->pacer);
} else {
diff --git a/drivers/comedi/drivers/ni_at_a2150.c b/drivers/comedi/drivers/ni_at_a2150.c
index df8d219e6723..e4e5a0ebd195 100644
--- a/drivers/comedi/drivers/ni_at_a2150.c
+++ b/drivers/comedi/drivers/ni_at_a2150.c
@@ -707,10 +707,10 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* an IRQ and DMA are required to support async commands */
a2150_alloc_irq_and_dma(dev, it);
- dev->pacer = comedi_8254_init(dev->iobase + I8253_BASE_REG,
- 0, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + I8253_BASE_REG,
+ 0, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 1);
if (ret)
diff --git a/drivers/comedi/drivers/ni_at_ao.c b/drivers/comedi/drivers/ni_at_ao.c
index 9f3147b72aa8..9cf6b4ff6b65 100644
--- a/drivers/comedi/drivers/ni_at_ao.c
+++ b/drivers/comedi/drivers/ni_at_ao.c
@@ -303,10 +303,10 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!devpriv)
return -ENOMEM;
- dev->pacer = comedi_8254_init(dev->iobase + ATAO_82C53_BASE,
- 0, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + ATAO_82C53_BASE,
+ 0, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
diff --git a/drivers/comedi/drivers/ni_atmio16d.c b/drivers/comedi/drivers/ni_atmio16d.c
index 9fa902529a8e..e5e7cc423c87 100644
--- a/drivers/comedi/drivers/ni_atmio16d.c
+++ b/drivers/comedi/drivers/ni_atmio16d.c
@@ -677,7 +677,7 @@ static int atmio16d_attach(struct comedi_device *dev,
/* 8255 subdevice */
s = &dev->subdevices[3];
if (board->has_8255) {
- ret = subdev_8255_init(dev, s, NULL, 0x00);
+ ret = subdev_8255_io_init(dev, s, 0x00);
if (ret)
return ret;
} else {
diff --git a/drivers/comedi/drivers/ni_daq_dio24.c b/drivers/comedi/drivers/ni_daq_dio24.c
index 487733111023..9419caf02edc 100644
--- a/drivers/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/comedi/drivers/ni_daq_dio24.c
@@ -45,7 +45,7 @@ static int dio24_auto_attach(struct comedi_device *dev,
/* 8255 dio */
s = &dev->subdevices[0];
- return subdev_8255_init(dev, s, NULL, 0x00);
+ return subdev_8255_io_init(dev, s, 0x00);
}
static struct comedi_driver driver_dio24 = {
diff --git a/drivers/comedi/drivers/ni_labpc_common.c b/drivers/comedi/drivers/ni_labpc_common.c
index 763249653228..7e0ce0ce0adf 100644
--- a/drivers/comedi/drivers/ni_labpc_common.c
+++ b/drivers/comedi/drivers/ni_labpc_common.c
@@ -78,6 +78,9 @@ static const struct comedi_lrange range_labpc_ao = {
* functions that do inb/outb and readb/writeb so we can use
* function pointers to decide which to use
*/
+
+#ifdef CONFIG_HAS_IOPORT
+
static unsigned int labpc_inb(struct comedi_device *dev, unsigned long reg)
{
return inb(dev->iobase + reg);
@@ -89,6 +92,8 @@ static void labpc_outb(struct comedi_device *dev,
outb(byte, dev->iobase + reg);
}
+#endif /* CONFIG_HAS_IOPORT */
+
static unsigned int labpc_readb(struct comedi_device *dev, unsigned long reg)
{
return readb(dev->mmio + reg);
@@ -1200,8 +1205,12 @@ int labpc_common_attach(struct comedi_device *dev,
devpriv->read_byte = labpc_readb;
devpriv->write_byte = labpc_writeb;
} else {
+#ifdef CONFIG_HAS_IOPORT
devpriv->read_byte = labpc_inb;
devpriv->write_byte = labpc_outb;
+#else
+ return -ENXIO;
+#endif
}
/* initialize board's command registers */
@@ -1222,24 +1231,24 @@ int labpc_common_attach(struct comedi_device *dev,
}
if (dev->mmio) {
- dev->pacer = comedi_8254_mm_init(dev->mmio + COUNTER_B_BASE_REG,
- I8254_OSC_BASE_2MHZ,
- I8254_IO8, 0);
- devpriv->counter = comedi_8254_mm_init(dev->mmio +
- COUNTER_A_BASE_REG,
- I8254_OSC_BASE_2MHZ,
- I8254_IO8, 0);
+ dev->pacer =
+ comedi_8254_mm_alloc(dev->mmio + COUNTER_B_BASE_REG,
+ I8254_OSC_BASE_2MHZ, I8254_IO8, 0);
+ devpriv->counter =
+ comedi_8254_mm_alloc(dev->mmio + COUNTER_A_BASE_REG,
+ I8254_OSC_BASE_2MHZ, I8254_IO8, 0);
} else {
- dev->pacer = comedi_8254_init(dev->iobase + COUNTER_B_BASE_REG,
- I8254_OSC_BASE_2MHZ,
- I8254_IO8, 0);
- devpriv->counter = comedi_8254_init(dev->iobase +
- COUNTER_A_BASE_REG,
- I8254_OSC_BASE_2MHZ,
- I8254_IO8, 0);
+ dev->pacer =
+ comedi_8254_io_alloc(dev->iobase + COUNTER_B_BASE_REG,
+ I8254_OSC_BASE_2MHZ, I8254_IO8, 0);
+ devpriv->counter =
+ comedi_8254_io_alloc(dev->iobase + COUNTER_A_BASE_REG,
+ I8254_OSC_BASE_2MHZ, I8254_IO8, 0);
}
- if (!dev->pacer || !devpriv->counter)
- return -ENOMEM;
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
+ if (IS_ERR(devpriv->counter))
+ return PTR_ERR(devpriv->counter);
ret = comedi_alloc_subdevices(dev, 5);
if (ret)
@@ -1287,9 +1296,9 @@ int labpc_common_attach(struct comedi_device *dev,
/* 8255 dio */
s = &dev->subdevices[2];
if (dev->mmio)
- ret = subdev_8255_mm_init(dev, s, NULL, DIO_BASE_REG);
+ ret = subdev_8255_mm_init(dev, s, DIO_BASE_REG);
else
- ret = subdev_8255_init(dev, s, NULL, DIO_BASE_REG);
+ ret = subdev_8255_io_init(dev, s, DIO_BASE_REG);
if (ret)
return ret;
@@ -1341,8 +1350,10 @@ void labpc_common_detach(struct comedi_device *dev)
{
struct labpc_private *devpriv = dev->private;
- if (devpriv)
- kfree(devpriv->counter);
+ if (devpriv) {
+ if (!IS_ERR(devpriv->counter))
+ kfree(devpriv->counter);
+ }
}
EXPORT_SYMBOL_GPL(labpc_common_detach);
diff --git a/drivers/comedi/drivers/ni_mio_common.c b/drivers/comedi/drivers/ni_mio_common.c
index d39998565808..980f309d6de7 100644
--- a/drivers/comedi/drivers/ni_mio_common.c
+++ b/drivers/comedi/drivers/ni_mio_common.c
@@ -46,6 +46,12 @@
#include <linux/comedi/comedi_8255.h>
#include "mite.h"
+#ifdef PCIDMA
+#define IS_PCIMIO 1
+#else
+#define IS_PCIMIO 0
+#endif
+
/* A timeout count */
#define NI_TIMEOUT 1000
@@ -219,54 +225,72 @@ enum timebase_nanoseconds {
static const int num_adc_stages_611x = 3;
+#ifdef PCIDMA
+
static void ni_writel(struct comedi_device *dev, unsigned int data, int reg)
{
- if (dev->mmio)
- writel(data, dev->mmio + reg);
- else
- outl(data, dev->iobase + reg);
+ writel(data, dev->mmio + reg);
}
static void ni_writew(struct comedi_device *dev, unsigned int data, int reg)
{
- if (dev->mmio)
- writew(data, dev->mmio + reg);
- else
- outw(data, dev->iobase + reg);
+ writew(data, dev->mmio + reg);
}
static void ni_writeb(struct comedi_device *dev, unsigned int data, int reg)
{
- if (dev->mmio)
- writeb(data, dev->mmio + reg);
- else
- outb(data, dev->iobase + reg);
+ writeb(data, dev->mmio + reg);
}
static unsigned int ni_readl(struct comedi_device *dev, int reg)
{
- if (dev->mmio)
- return readl(dev->mmio + reg);
+ return readl(dev->mmio + reg);
+}
+
+static unsigned int ni_readw(struct comedi_device *dev, int reg)
+{
+ return readw(dev->mmio + reg);
+}
+
+static unsigned int ni_readb(struct comedi_device *dev, int reg)
+{
+ return readb(dev->mmio + reg);
+}
+#else /* PCIDMA */
+
+static void ni_writel(struct comedi_device *dev, unsigned int data, int reg)
+{
+ outl(data, dev->iobase + reg);
+}
+
+static void ni_writew(struct comedi_device *dev, unsigned int data, int reg)
+{
+ outw(data, dev->iobase + reg);
+}
+
+static void ni_writeb(struct comedi_device *dev, unsigned int data, int reg)
+{
+ outb(data, dev->iobase + reg);
+}
+
+static unsigned int ni_readl(struct comedi_device *dev, int reg)
+{
return inl(dev->iobase + reg);
}
static unsigned int ni_readw(struct comedi_device *dev, int reg)
{
- if (dev->mmio)
- return readw(dev->mmio + reg);
-
return inw(dev->iobase + reg);
}
static unsigned int ni_readb(struct comedi_device *dev, int reg)
{
- if (dev->mmio)
- return readb(dev->mmio + reg);
-
return inb(dev->iobase + reg);
}
+#endif /* PCIDMA */
+
/*
* We automatically take advantage of STC registers that can be
* read/written directly in the I/O space of the board.
@@ -5977,6 +6001,12 @@ static int ni_E_init(struct comedi_device *dev,
int i;
const char *dev_family = devpriv->is_m_series ? "ni_mseries"
: "ni_eseries";
+ if (!IS_PCIMIO != !dev->mmio) {
+ dev_err(dev->class_dev,
+ "%s: bug! %s device not supported.\n",
+ KBUILD_MODNAME, board->name);
+ return -ENXIO;
+ }
/* prepare the device for globally-named routes. */
if (ni_assign_device_routes(dev_family, board->name,
@@ -6137,8 +6167,8 @@ static int ni_E_init(struct comedi_device *dev,
/* 8255 device */
s = &dev->subdevices[NI_8255_DIO_SUBDEV];
if (board->has_8255) {
- ret = subdev_8255_init(dev, s, ni_8255_callback,
- NI_E_8255_BASE);
+ ret = subdev_8255_cb_init(dev, s, ni_8255_callback,
+ NI_E_8255_BASE);
if (ret)
return ret;
} else {
diff --git a/drivers/comedi/drivers/pcl711.c b/drivers/comedi/drivers/pcl711.c
index 05172c553c8a..0cf3917defe7 100644
--- a/drivers/comedi/drivers/pcl711.c
+++ b/drivers/comedi/drivers/pcl711.c
@@ -429,10 +429,10 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev->irq = it->options[1];
}
- dev->pacer = comedi_8254_init(dev->iobase + PCL711_TIMER_BASE,
- I8254_OSC_BASE_2MHZ, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + PCL711_TIMER_BASE,
+ I8254_OSC_BASE_2MHZ, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
diff --git a/drivers/comedi/drivers/pcl724.c b/drivers/comedi/drivers/pcl724.c
index 948a0576c9ef..00474710b81f 100644
--- a/drivers/comedi/drivers/pcl724.c
+++ b/drivers/comedi/drivers/pcl724.c
@@ -124,10 +124,10 @@ static int pcl724_attach(struct comedi_device *dev,
s = &dev->subdevices[i];
if (board->is_pet48) {
iobase = dev->iobase + (i * 0x1000);
- ret = subdev_8255_init(dev, s, pcl724_8255mapped_io,
- iobase);
+ ret = subdev_8255_cb_init(dev, s, pcl724_8255mapped_io,
+ iobase);
} else {
- ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE);
+ ret = subdev_8255_io_init(dev, s, i * I8255_SIZE);
}
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/pcl812.c b/drivers/comedi/drivers/pcl812.c
index 70dbc129fcf5..0df639c6a595 100644
--- a/drivers/comedi/drivers/pcl812.c
+++ b/drivers/comedi/drivers/pcl812.c
@@ -1143,11 +1143,11 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
if (board->irq_bits) {
- dev->pacer = comedi_8254_init(dev->iobase + PCL812_TIMER_BASE,
- I8254_OSC_BASE_2MHZ,
- I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer =
+ comedi_8254_io_alloc(dev->iobase + PCL812_TIMER_BASE,
+ I8254_OSC_BASE_2MHZ, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
if ((1 << it->options[1]) & board->irq_bits) {
ret = request_irq(it->options[1], pcl812_interrupt, 0,
diff --git a/drivers/comedi/drivers/pcl816.c b/drivers/comedi/drivers/pcl816.c
index a5e5320be648..28d1a88c50f6 100644
--- a/drivers/comedi/drivers/pcl816.c
+++ b/drivers/comedi/drivers/pcl816.c
@@ -615,10 +615,10 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* an IRQ and DMA are required to support async commands */
pcl816_alloc_irq_and_dma(dev, it);
- dev->pacer = comedi_8254_init(dev->iobase + PCL816_TIMER_BASE,
- I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + PCL816_TIMER_BASE,
+ I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
diff --git a/drivers/comedi/drivers/pcl818.c b/drivers/comedi/drivers/pcl818.c
index 29e503de8267..4127adcfb229 100644
--- a/drivers/comedi/drivers/pcl818.c
+++ b/drivers/comedi/drivers/pcl818.c
@@ -1015,10 +1015,10 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
else
osc_base = I8254_OSC_BASE_1MHZ;
- dev->pacer = comedi_8254_init(dev->iobase + PCL818_TIMER_BASE,
- osc_base, I8254_IO8, 0);
- if (!dev->pacer)
- return -ENOMEM;
+ dev->pacer = comedi_8254_io_alloc(dev->iobase + PCL818_TIMER_BASE,
+ osc_base, I8254_IO8, 0);
+ if (IS_ERR(dev->pacer))
+ return PTR_ERR(dev->pacer);
/* max sampling speed */
devpriv->ns_min = board->ns_min;
diff --git a/drivers/comedi/drivers/pcm3724.c b/drivers/comedi/drivers/pcm3724.c
index ca8bef54dacc..fb41de3baef8 100644
--- a/drivers/comedi/drivers/pcm3724.c
+++ b/drivers/comedi/drivers/pcm3724.c
@@ -204,7 +204,7 @@ static int pcm3724_attach(struct comedi_device *dev,
for (i = 0; i < dev->n_subdevices; i++) {
s = &dev->subdevices[i];
- ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE);
+ ret = subdev_8255_io_init(dev, s, i * I8255_SIZE);
if (ret)
return ret;
s->insn_config = subdev_3724_insn_config;
diff --git a/drivers/comedi/drivers/rtd520.c b/drivers/comedi/drivers/rtd520.c
index 7e0ec1a2a2ca..44bb0decd7a4 100644
--- a/drivers/comedi/drivers/rtd520.c
+++ b/drivers/comedi/drivers/rtd520.c
@@ -1289,9 +1289,9 @@ static int rtd_auto_attach(struct comedi_device *dev,
/* 8254 Timer/Counter subdevice */
s = &dev->subdevices[3];
- dev->pacer = comedi_8254_mm_init(dev->mmio + LAS0_8254_TIMER_BASE,
- RTD_CLOCK_BASE, I8254_IO8, 2);
- if (!dev->pacer)
+ dev->pacer = comedi_8254_mm_alloc(dev->mmio + LAS0_8254_TIMER_BASE,
+ RTD_CLOCK_BASE, I8254_IO8, 2);
+ if (IS_ERR(dev->pacer))
return -ENOMEM;
comedi_8254_subdevice_init(s, dev->pacer);
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 05d562e9c8b1..44b19e696176 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -54,7 +54,7 @@ static int cn_filter(struct sock *dsk, struct sk_buff *skb, void *data)
enum proc_cn_mcast_op mc_op;
uintptr_t val;
- if (!dsk || !data)
+ if (!dsk || !dsk->sk_user_data || !data)
return 0;
ptr = (__u32 *)data;
diff --git a/drivers/counter/counter-chrdev.c b/drivers/counter/counter-chrdev.c
index 80acdf62794a..afc94d0062b1 100644
--- a/drivers/counter/counter-chrdev.c
+++ b/drivers/counter/counter-chrdev.c
@@ -247,8 +247,8 @@ static int counter_get_ext(const struct counter_comp *const ext,
if (*id == component_id)
return 0;
- if (ext->type == COUNTER_COMP_ARRAY) {
- element = ext->priv;
+ if (ext[*ext_idx].type == COUNTER_COMP_ARRAY) {
+ element = ext[*ext_idx].priv;
if (component_id - *id < element->length)
return 0;
diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
index 975e431d1590..b3e615cbd2ca 100644
--- a/drivers/counter/microchip-tcb-capture.c
+++ b/drivers/counter/microchip-tcb-capture.c
@@ -97,7 +97,7 @@ static int mchp_tc_count_function_write(struct counter_device *counter,
priv->qdec_mode = 0;
/* Set highest rate based on whether soc has gclk or not */
bmr &= ~(ATMEL_TC_QDEN | ATMEL_TC_POSEN);
- if (priv->tc_cfg->has_gclk)
+ if (!priv->tc_cfg->has_gclk)
cmr |= ATMEL_TC_TIMER_CLOCK2;
else
cmr |= ATMEL_TC_TIMER_CLOCK1;
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index f429b9b37b76..35efb53d5492 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -239,17 +239,6 @@ if PPC32 || PPC64
source "drivers/cpufreq/Kconfig.powerpc"
endif
-if IA64
-config IA64_ACPI_CPUFREQ
- tristate "ACPI Processor P-States driver"
- depends on ACPI_PROCESSOR
- help
- This driver adds a CPUFreq driver which utilizes the ACPI
- Processor Performance States.
-
- If in doubt, say N.
-endif
-
if MIPS
config BMIPS_CPUFREQ
tristate "BMIPS CPUfreq Driver"
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 123b4bbfcfee..f911606897b8 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -90,7 +90,7 @@ config ARM_VEXPRESS_SPC_CPUFREQ
config ARM_BRCMSTB_AVS_CPUFREQ
tristate "Broadcom STB AVS CPUfreq driver"
- depends on ARCH_BRCMSTB || COMPILE_TEST
+ depends on (ARCH_BRCMSTB && !ARM_SCMI_CPUFREQ) || COMPILE_TEST
default y
help
Some Broadcom STB SoCs use a co-processor running proprietary firmware
@@ -124,8 +124,8 @@ config ARM_IMX_CPUFREQ_DT
tristate "Freescale i.MX8M cpufreq support"
depends on ARCH_MXC && CPUFREQ_DT
help
- This adds cpufreq driver support for Freescale i.MX8M series SoCs,
- based on cpufreq-dt.
+ This adds cpufreq driver support for Freescale i.MX7/i.MX8M
+ series SoCs, based on cpufreq-dt.
If in doubt, say N.
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index ef8510774913..8d141c71b016 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -102,7 +102,6 @@ obj-$(CONFIG_POWERNV_CPUFREQ) += powernv-cpufreq.o
##################################################################################
# Other platform drivers
obj-$(CONFIG_BMIPS_CPUFREQ) += bmips-cpufreq.o
-obj-$(CONFIG_IA64_ACPI_CPUFREQ) += ia64-acpi-cpufreq.o
obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o
obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o
obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 9a1e194d5cf8..1f6186475715 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -307,11 +307,11 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
highest_perf = AMD_CPPC_HIGHEST_PERF(cap1);
WRITE_ONCE(cpudata->highest_perf, highest_perf);
-
+ WRITE_ONCE(cpudata->max_limit_perf, highest_perf);
WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1));
WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1));
WRITE_ONCE(cpudata->lowest_perf, AMD_CPPC_LOWEST_PERF(cap1));
-
+ WRITE_ONCE(cpudata->min_limit_perf, AMD_CPPC_LOWEST_PERF(cap1));
return 0;
}
@@ -329,11 +329,12 @@ static int cppc_init_perf(struct amd_cpudata *cpudata)
highest_perf = cppc_perf.highest_perf;
WRITE_ONCE(cpudata->highest_perf, highest_perf);
-
+ WRITE_ONCE(cpudata->max_limit_perf, highest_perf);
WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf);
WRITE_ONCE(cpudata->lowest_nonlinear_perf,
cppc_perf.lowest_nonlinear_perf);
WRITE_ONCE(cpudata->lowest_perf, cppc_perf.lowest_perf);
+ WRITE_ONCE(cpudata->min_limit_perf, cppc_perf.lowest_perf);
if (cppc_state == AMD_PSTATE_ACTIVE)
return 0;
@@ -432,6 +433,10 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
u64 prev = READ_ONCE(cpudata->cppc_req_cached);
u64 value = prev;
+ min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf,
+ cpudata->max_limit_perf);
+ max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_perf,
+ cpudata->max_limit_perf);
des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
if ((cppc_state == AMD_PSTATE_GUIDED) && (gov_flags & CPUFREQ_GOV_DYNAMIC_SWITCHING)) {
@@ -470,6 +475,22 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy)
return 0;
}
+static int amd_pstate_update_min_max_limit(struct cpufreq_policy *policy)
+{
+ u32 max_limit_perf, min_limit_perf;
+ struct amd_cpudata *cpudata = policy->driver_data;
+
+ max_limit_perf = div_u64(policy->max * cpudata->highest_perf, cpudata->max_freq);
+ min_limit_perf = div_u64(policy->min * cpudata->highest_perf, cpudata->max_freq);
+
+ WRITE_ONCE(cpudata->max_limit_perf, max_limit_perf);
+ WRITE_ONCE(cpudata->min_limit_perf, min_limit_perf);
+ WRITE_ONCE(cpudata->max_limit_freq, policy->max);
+ WRITE_ONCE(cpudata->min_limit_freq, policy->min);
+
+ return 0;
+}
+
static int amd_pstate_update_freq(struct cpufreq_policy *policy,
unsigned int target_freq, bool fast_switch)
{
@@ -480,6 +501,9 @@ static int amd_pstate_update_freq(struct cpufreq_policy *policy,
if (!cpudata->max_freq)
return -ENODEV;
+ if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq)
+ amd_pstate_update_min_max_limit(policy);
+
cap_perf = READ_ONCE(cpudata->highest_perf);
min_perf = READ_ONCE(cpudata->lowest_perf);
max_perf = cap_perf;
@@ -518,7 +542,9 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
unsigned int target_freq)
{
- return amd_pstate_update_freq(policy, target_freq, true);
+ if (!amd_pstate_update_freq(policy, target_freq, true))
+ return target_freq;
+ return policy->cur;
}
static void amd_pstate_adjust_perf(unsigned int cpu,
@@ -532,6 +558,10 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
struct amd_cpudata *cpudata = policy->driver_data;
unsigned int target_freq;
+ if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq)
+ amd_pstate_update_min_max_limit(policy);
+
+
cap_perf = READ_ONCE(cpudata->highest_perf);
lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
max_freq = READ_ONCE(cpudata->max_freq);
@@ -745,6 +775,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
/* 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;
@@ -850,11 +882,16 @@ static ssize_t show_energy_performance_available_preferences(
{
int i = 0;
int offset = 0;
+ struct amd_cpudata *cpudata = policy->driver_data;
+
+ if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
+ return sysfs_emit_at(buf, offset, "%s\n",
+ energy_perf_strings[EPP_INDEX_PERFORMANCE]);
while (energy_perf_strings[i] != NULL)
offset += sysfs_emit_at(buf, offset, "%s ", energy_perf_strings[i++]);
- sysfs_emit_at(buf, offset, "\n");
+ offset += sysfs_emit_at(buf, offset, "\n");
return offset;
}
@@ -1183,16 +1220,25 @@ static int amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
return 0;
}
-static void amd_pstate_epp_init(unsigned int cpu)
+static void amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
{
- struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
struct amd_cpudata *cpudata = policy->driver_data;
- u32 max_perf, min_perf;
+ u32 max_perf, min_perf, min_limit_perf, max_limit_perf;
u64 value;
s16 epp;
max_perf = READ_ONCE(cpudata->highest_perf);
min_perf = READ_ONCE(cpudata->lowest_perf);
+ max_limit_perf = div_u64(policy->max * cpudata->highest_perf, cpudata->max_freq);
+ min_limit_perf = div_u64(policy->min * cpudata->highest_perf, cpudata->max_freq);
+
+ max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_perf,
+ cpudata->max_limit_perf);
+ min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf,
+ cpudata->max_limit_perf);
+
+ WRITE_ONCE(cpudata->max_limit_perf, max_limit_perf);
+ WRITE_ONCE(cpudata->min_limit_perf, min_limit_perf);
value = READ_ONCE(cpudata->cppc_req_cached);
@@ -1210,9 +1256,6 @@ static void amd_pstate_epp_init(unsigned int cpu)
value &= ~AMD_CPPC_DES_PERF(~0L);
value |= AMD_CPPC_DES_PERF(0);
- if (cpudata->epp_policy == cpudata->policy)
- goto skip_epp;
-
cpudata->epp_policy = cpudata->policy;
/* Get BIOS pre-defined epp value */
@@ -1222,7 +1265,7 @@ static void amd_pstate_epp_init(unsigned int cpu)
* This return value can only be negative for shared_memory
* systems where EPP register read/write not supported.
*/
- goto skip_epp;
+ return;
}
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
@@ -1236,8 +1279,6 @@ static void amd_pstate_epp_init(unsigned int cpu)
WRITE_ONCE(cpudata->cppc_req_cached, value);
amd_pstate_set_epp(cpudata, epp);
-skip_epp:
- cpufreq_cpu_put(policy);
}
static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
@@ -1252,7 +1293,7 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
cpudata->policy = policy->policy;
- amd_pstate_epp_init(policy->cpu);
+ amd_pstate_epp_update_limit(policy);
return 0;
}
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index fb2875ce1fdd..bd1e1357cef8 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -142,9 +142,11 @@ static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "nvidia,tegra234", },
{ .compatible = "qcom,apq8096", },
+ { .compatible = "qcom,msm8909", },
{ .compatible = "qcom,msm8996", },
{ .compatible = "qcom,msm8998", },
{ .compatible = "qcom,qcm2290", },
+ { .compatible = "qcom,qcm6490", },
{ .compatible = "qcom,qcs404", },
{ .compatible = "qcom,qdu1000", },
{ .compatible = "qcom,sa8155p" },
@@ -176,8 +178,13 @@ static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "ti,omap3", },
{ .compatible = "ti,am625", },
{ .compatible = "ti,am62a7", },
+ { .compatible = "ti,am62p5", },
+ { .compatible = "qcom,ipq5332", },
+ { .compatible = "qcom,ipq6018", },
{ .compatible = "qcom,ipq8064", },
+ { .compatible = "qcom,ipq8074", },
+ { .compatible = "qcom,ipq9574", },
{ .compatible = "qcom,apq8064", },
{ .compatible = "qcom,msm8974", },
{ .compatible = "qcom,msm8960", },
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 60ed89000e82..934d35f570b7 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1544,7 +1544,7 @@ static int cpufreq_online(unsigned int cpu)
/*
* Register with the energy model before
- * sched_cpufreq_governor_change() is called, which will result
+ * sugov_eas_rebuild_sd() is called, which will result
* in rebuilding of the sched domains, which should only be done
* once the energy model is properly initialized for the policy
* first.
@@ -1650,7 +1650,7 @@ static void __cpufreq_offline(unsigned int cpu, struct cpufreq_policy *policy)
}
if (has_target())
- strncpy(policy->last_governor, policy->governor->name,
+ strscpy(policy->last_governor, policy->governor->name,
CPUFREQ_NAME_LEN);
else
policy->last_policy = policy->policy;
@@ -2652,7 +2652,6 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
ret = cpufreq_start_governor(policy);
if (!ret) {
pr_debug("governor change\n");
- sched_cpufreq_governor_change(policy, old_gov);
return 0;
}
cpufreq_exit_governor(policy);
@@ -2996,7 +2995,7 @@ static int __init cpufreq_core_init(void)
BUG_ON(!cpufreq_global_kobject);
if (!strlen(default_governor))
- strncpy(default_governor, gov->name, CPUFREQ_NAME_LEN);
+ strscpy(default_governor, gov->name, CPUFREQ_NAME_LEN);
return 0;
}
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index b6bd0ff35323..56500b25d77c 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -187,8 +187,7 @@ static ssize_t down_threshold_store(struct gov_attr_set *attr_set,
ret = sscanf(buf, "%u", &input);
/* cannot be lower than 1 otherwise freq will not fall */
- if (ret != 1 || input < 1 || input > 100 ||
- input >= dbs_data->up_threshold)
+ if (ret != 1 || input < 1 || input >= dbs_data->up_threshold)
return -EINVAL;
cs_tuners->down_threshold = input;
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index a33df3c66c88..40a9ff18da06 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -131,23 +131,23 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
len += sysfs_emit_at(buf, len, " From : To\n");
len += sysfs_emit_at(buf, len, " : ");
for (i = 0; i < stats->state_num; i++) {
- if (len >= PAGE_SIZE)
+ if (len >= PAGE_SIZE - 1)
break;
len += sysfs_emit_at(buf, len, "%9u ", stats->freq_table[i]);
}
- if (len >= PAGE_SIZE)
- return PAGE_SIZE;
+ if (len >= PAGE_SIZE - 1)
+ return PAGE_SIZE - 1;
len += sysfs_emit_at(buf, len, "\n");
for (i = 0; i < stats->state_num; i++) {
- if (len >= PAGE_SIZE)
+ if (len >= PAGE_SIZE - 1)
break;
len += sysfs_emit_at(buf, len, "%9u: ", stats->freq_table[i]);
for (j = 0; j < stats->state_num; j++) {
- if (len >= PAGE_SIZE)
+ if (len >= PAGE_SIZE - 1)
break;
if (pending)
@@ -157,12 +157,12 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
len += sysfs_emit_at(buf, len, "%9u ", count);
}
- if (len >= PAGE_SIZE)
+ if (len >= PAGE_SIZE - 1)
break;
len += sysfs_emit_at(buf, len, "\n");
}
- if (len >= PAGE_SIZE) {
+ if (len >= PAGE_SIZE - 1) {
pr_warn_once("cpufreq transition table exceeds PAGE_SIZE. Disabling\n");
return -EFBIG;
}
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 50a4d7846580..2c42fee76daa 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -15,8 +15,11 @@
#include <linux/mutex.h>
#include <linux/slab.h>
-static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
-static DEFINE_MUTEX(userspace_mutex);
+struct userspace_policy {
+ unsigned int is_managed;
+ unsigned int setspeed;
+ struct mutex mutex;
+};
/**
* cpufreq_set - set the CPU frequency
@@ -28,19 +31,19 @@ static DEFINE_MUTEX(userspace_mutex);
static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
{
int ret = -EINVAL;
- unsigned int *setspeed = policy->governor_data;
+ struct userspace_policy *userspace = policy->governor_data;
pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
- mutex_lock(&userspace_mutex);
- if (!per_cpu(cpu_is_managed, policy->cpu))
+ mutex_lock(&userspace->mutex);
+ if (!userspace->is_managed)
goto err;
- *setspeed = freq;
+ userspace->setspeed = freq;
ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
err:
- mutex_unlock(&userspace_mutex);
+ mutex_unlock(&userspace->mutex);
return ret;
}
@@ -51,67 +54,74 @@ static ssize_t show_speed(struct cpufreq_policy *policy, char *buf)
static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy)
{
- unsigned int *setspeed;
+ struct userspace_policy *userspace;
- setspeed = kzalloc(sizeof(*setspeed), GFP_KERNEL);
- if (!setspeed)
+ userspace = kzalloc(sizeof(*userspace), GFP_KERNEL);
+ if (!userspace)
return -ENOMEM;
- policy->governor_data = setspeed;
+ mutex_init(&userspace->mutex);
+
+ policy->governor_data = userspace;
return 0;
}
+/*
+ * Any routine that writes to the policy struct will hold the "rwsem" of
+ * policy struct that means it is free to free "governor_data" here.
+ */
static void cpufreq_userspace_policy_exit(struct cpufreq_policy *policy)
{
- mutex_lock(&userspace_mutex);
kfree(policy->governor_data);
policy->governor_data = NULL;
- mutex_unlock(&userspace_mutex);
}
static int cpufreq_userspace_policy_start(struct cpufreq_policy *policy)
{
- unsigned int *setspeed = policy->governor_data;
+ struct userspace_policy *userspace = policy->governor_data;
BUG_ON(!policy->cur);
pr_debug("started managing cpu %u\n", policy->cpu);
- mutex_lock(&userspace_mutex);
- per_cpu(cpu_is_managed, policy->cpu) = 1;
- *setspeed = policy->cur;
- mutex_unlock(&userspace_mutex);
+ mutex_lock(&userspace->mutex);
+ userspace->is_managed = 1;
+ userspace->setspeed = policy->cur;
+ mutex_unlock(&userspace->mutex);
return 0;
}
static void cpufreq_userspace_policy_stop(struct cpufreq_policy *policy)
{
- unsigned int *setspeed = policy->governor_data;
+ struct userspace_policy *userspace = policy->governor_data;
pr_debug("managing cpu %u stopped\n", policy->cpu);
- mutex_lock(&userspace_mutex);
- per_cpu(cpu_is_managed, policy->cpu) = 0;
- *setspeed = 0;
- mutex_unlock(&userspace_mutex);
+ mutex_lock(&userspace->mutex);
+ userspace->is_managed = 0;
+ userspace->setspeed = 0;
+ mutex_unlock(&userspace->mutex);
}
static void cpufreq_userspace_policy_limits(struct cpufreq_policy *policy)
{
- unsigned int *setspeed = policy->governor_data;
+ struct userspace_policy *userspace = policy->governor_data;
- mutex_lock(&userspace_mutex);
+ mutex_lock(&userspace->mutex);
pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n",
- policy->cpu, policy->min, policy->max, policy->cur, *setspeed);
-
- if (policy->max < *setspeed)
- __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
- else if (policy->min > *setspeed)
- __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
+ policy->cpu, policy->min, policy->max, policy->cur, userspace->setspeed);
+
+ if (policy->max < userspace->setspeed)
+ __cpufreq_driver_target(policy, policy->max,
+ CPUFREQ_RELATION_H);
+ else if (policy->min > userspace->setspeed)
+ __cpufreq_driver_target(policy, policy->min,
+ CPUFREQ_RELATION_L);
else
- __cpufreq_driver_target(policy, *setspeed, CPUFREQ_RELATION_L);
+ __cpufreq_driver_target(policy, userspace->setspeed,
+ CPUFREQ_RELATION_L);
- mutex_unlock(&userspace_mutex);
+ mutex_unlock(&userspace->mutex);
}
static struct cpufreq_governor cpufreq_gov_userspace = {
diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c
deleted file mode 100644
index c6bdc455517f..000000000000
--- a/drivers/cpufreq/ia64-acpi-cpufreq.c
+++ /dev/null
@@ -1,353 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * This file provides the ACPI based P-state support. This
- * module works with generic cpufreq infrastructure. Most of
- * the code is based on i386 version
- * (arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c)
- *
- * Copyright (C) 2005 Intel Corp
- * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/proc_fs.h>
-#include <asm/io.h>
-#include <linux/uaccess.h>
-#include <asm/pal.h>
-
-#include <linux/acpi.h>
-#include <acpi/processor.h>
-
-MODULE_AUTHOR("Venkatesh Pallipadi");
-MODULE_DESCRIPTION("ACPI Processor P-States Driver");
-MODULE_LICENSE("GPL");
-
-struct cpufreq_acpi_io {
- struct acpi_processor_performance acpi_data;
- unsigned int resume;
-};
-
-struct cpufreq_acpi_req {
- unsigned int cpu;
- unsigned int state;
-};
-
-static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS];
-
-static struct cpufreq_driver acpi_cpufreq_driver;
-
-
-static int
-processor_set_pstate (
- u32 value)
-{
- s64 retval;
-
- pr_debug("processor_set_pstate\n");
-
- retval = ia64_pal_set_pstate((u64)value);
-
- if (retval) {
- pr_debug("Failed to set freq to 0x%x, with error 0x%llx\n",
- value, retval);
- return -ENODEV;
- }
- return (int)retval;
-}
-
-
-static int
-processor_get_pstate (
- u32 *value)
-{
- u64 pstate_index = 0;
- s64 retval;
-
- pr_debug("processor_get_pstate\n");
-
- retval = ia64_pal_get_pstate(&pstate_index,
- PAL_GET_PSTATE_TYPE_INSTANT);
- *value = (u32) pstate_index;
-
- if (retval)
- pr_debug("Failed to get current freq with "
- "error 0x%llx, idx 0x%x\n", retval, *value);
-
- return (int)retval;
-}
-
-
-/* To be used only after data->acpi_data is initialized */
-static unsigned
-extract_clock (
- struct cpufreq_acpi_io *data,
- unsigned value)
-{
- unsigned long i;
-
- pr_debug("extract_clock\n");
-
- for (i = 0; i < data->acpi_data.state_count; i++) {
- if (value == data->acpi_data.states[i].status)
- return data->acpi_data.states[i].core_frequency;
- }
- return data->acpi_data.states[i-1].core_frequency;
-}
-
-
-static long
-processor_get_freq (
- void *arg)
-{
- struct cpufreq_acpi_req *req = arg;
- unsigned int cpu = req->cpu;
- struct cpufreq_acpi_io *data = acpi_io_data[cpu];
- u32 value;
- int ret;
-
- pr_debug("processor_get_freq\n");
- if (smp_processor_id() != cpu)
- return -EAGAIN;
-
- /* processor_get_pstate gets the instantaneous frequency */
- ret = processor_get_pstate(&value);
- if (ret) {
- pr_warn("get performance failed with error %d\n", ret);
- return ret;
- }
- return 1000 * extract_clock(data, value);
-}
-
-
-static long
-processor_set_freq (
- void *arg)
-{
- struct cpufreq_acpi_req *req = arg;
- unsigned int cpu = req->cpu;
- struct cpufreq_acpi_io *data = acpi_io_data[cpu];
- int ret, state = req->state;
- u32 value;
-
- pr_debug("processor_set_freq\n");
- if (smp_processor_id() != cpu)
- return -EAGAIN;
-
- if (state == data->acpi_data.state) {
- if (unlikely(data->resume)) {
- pr_debug("Called after resume, resetting to P%d\n", state);
- data->resume = 0;
- } else {
- pr_debug("Already at target state (P%d)\n", state);
- return 0;
- }
- }
-
- pr_debug("Transitioning from P%d to P%d\n",
- data->acpi_data.state, state);
-
- /*
- * First we write the target state's 'control' value to the
- * control_register.
- */
- value = (u32) data->acpi_data.states[state].control;
-
- pr_debug("Transitioning to state: 0x%08x\n", value);
-
- ret = processor_set_pstate(value);
- if (ret) {
- pr_warn("Transition failed with error %d\n", ret);
- return -ENODEV;
- }
-
- data->acpi_data.state = state;
- return 0;
-}
-
-
-static unsigned int
-acpi_cpufreq_get (
- unsigned int cpu)
-{
- struct cpufreq_acpi_req req;
- long ret;
-
- req.cpu = cpu;
- ret = work_on_cpu(cpu, processor_get_freq, &req);
-
- return ret > 0 ? (unsigned int) ret : 0;
-}
-
-
-static int
-acpi_cpufreq_target (
- struct cpufreq_policy *policy,
- unsigned int index)
-{
- struct cpufreq_acpi_req req;
-
- req.cpu = policy->cpu;
- req.state = index;
-
- return work_on_cpu(req.cpu, processor_set_freq, &req);
-}
-
-static int
-acpi_cpufreq_cpu_init (
- struct cpufreq_policy *policy)
-{
- unsigned int i;
- unsigned int cpu = policy->cpu;
- struct cpufreq_acpi_io *data;
- unsigned int result = 0;
- struct cpufreq_frequency_table *freq_table;
-
- pr_debug("acpi_cpufreq_cpu_init\n");
-
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (!data)
- return (-ENOMEM);
-
- acpi_io_data[cpu] = data;
-
- result = acpi_processor_register_performance(&data->acpi_data, cpu);
-
- if (result)
- goto err_free;
-
- /* capability check */
- if (data->acpi_data.state_count <= 1) {
- pr_debug("No P-States\n");
- result = -ENODEV;
- goto err_unreg;
- }
-
- if ((data->acpi_data.control_register.space_id !=
- ACPI_ADR_SPACE_FIXED_HARDWARE) ||
- (data->acpi_data.status_register.space_id !=
- ACPI_ADR_SPACE_FIXED_HARDWARE)) {
- pr_debug("Unsupported address space [%d, %d]\n",
- (u32) (data->acpi_data.control_register.space_id),
- (u32) (data->acpi_data.status_register.space_id));
- result = -ENODEV;
- goto err_unreg;
- }
-
- /* alloc freq_table */
- freq_table = kcalloc(data->acpi_data.state_count + 1,
- sizeof(*freq_table),
- GFP_KERNEL);
- if (!freq_table) {
- result = -ENOMEM;
- goto err_unreg;
- }
-
- /* detect transition latency */
- policy->cpuinfo.transition_latency = 0;
- for (i=0; i<data->acpi_data.state_count; i++) {
- if ((data->acpi_data.states[i].transition_latency * 1000) >
- policy->cpuinfo.transition_latency) {
- policy->cpuinfo.transition_latency =
- data->acpi_data.states[i].transition_latency * 1000;
- }
- }
-
- /* table init */
- for (i = 0; i <= data->acpi_data.state_count; i++)
- {
- if (i < data->acpi_data.state_count) {
- freq_table[i].frequency =
- data->acpi_data.states[i].core_frequency * 1000;
- } else {
- freq_table[i].frequency = CPUFREQ_TABLE_END;
- }
- }
-
- policy->freq_table = freq_table;
-
- /* notify BIOS that we exist */
- acpi_processor_notify_smm(THIS_MODULE);
-
- pr_info("CPU%u - ACPI performance management activated\n", cpu);
-
- for (i = 0; i < data->acpi_data.state_count; i++)
- pr_debug(" %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n",
- (i == data->acpi_data.state?'*':' '), i,
- (u32) data->acpi_data.states[i].core_frequency,
- (u32) data->acpi_data.states[i].power,
- (u32) data->acpi_data.states[i].transition_latency,
- (u32) data->acpi_data.states[i].bus_master_latency,
- (u32) data->acpi_data.states[i].status,
- (u32) data->acpi_data.states[i].control);
-
- /* the first call to ->target() should result in us actually
- * writing something to the appropriate registers. */
- data->resume = 1;
-
- return (result);
-
- err_unreg:
- acpi_processor_unregister_performance(cpu);
- err_free:
- kfree(data);
- acpi_io_data[cpu] = NULL;
-
- return (result);
-}
-
-
-static int
-acpi_cpufreq_cpu_exit (
- struct cpufreq_policy *policy)
-{
- struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
-
- pr_debug("acpi_cpufreq_cpu_exit\n");
-
- if (data) {
- acpi_io_data[policy->cpu] = NULL;
- acpi_processor_unregister_performance(policy->cpu);
- kfree(policy->freq_table);
- kfree(data);
- }
-
- return (0);
-}
-
-
-static struct cpufreq_driver acpi_cpufreq_driver = {
- .verify = cpufreq_generic_frequency_table_verify,
- .target_index = acpi_cpufreq_target,
- .get = acpi_cpufreq_get,
- .init = acpi_cpufreq_cpu_init,
- .exit = acpi_cpufreq_cpu_exit,
- .name = "acpi-cpufreq",
- .attr = cpufreq_generic_attr,
-};
-
-
-static int __init
-acpi_cpufreq_init (void)
-{
- pr_debug("acpi_cpufreq_init\n");
-
- return cpufreq_register_driver(&acpi_cpufreq_driver);
-}
-
-
-static void __exit
-acpi_cpufreq_exit (void)
-{
- pr_debug("acpi_cpufreq_exit\n");
-
- cpufreq_unregister_driver(&acpi_cpufreq_driver);
-}
-
-late_initcall(acpi_cpufreq_init);
-module_exit(acpi_cpufreq_exit);
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 494d044b9e72..33728c242f66 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -327,7 +327,7 @@ static int imx6ul_opp_check_speed_grading(struct device *dev)
imx6x_disable_freq_in_opp(dev, 696000000);
if (of_machine_is_compatible("fsl,imx6ull")) {
- if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ)
+ if (val < OCOTP_CFG3_6ULL_SPEED_792MHZ)
imx6x_disable_freq_in_opp(dev, 792000000);
if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index dc50c9fb488d..a534a1f7f1ee 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -571,13 +571,9 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
static inline void update_turbo_state(void)
{
u64 misc_en;
- struct cpudata *cpu;
- cpu = all_cpu_data[0];
rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
- global.turbo_disabled =
- (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
- cpu->pstate.max_pstate == cpu->pstate.turbo_pstate);
+ global.turbo_disabled = misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE;
}
static int min_perf_pct_min(void)
diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c
index ec75e79659ac..df3567c1e93b 100644
--- a/drivers/cpufreq/pmac32-cpufreq.c
+++ b/drivers/cpufreq/pmac32-cpufreq.c
@@ -24,6 +24,7 @@
#include <linux/device.h>
#include <linux/hardirq.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <asm/machdep.h>
#include <asm/irq.h>
@@ -378,10 +379,9 @@ static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
static u32 read_gpio(struct device_node *np)
{
- const u32 *reg = of_get_property(np, "reg", NULL);
- u32 offset;
+ u64 offset;
- if (reg == NULL)
+ if (of_property_read_reg(np, 0, &offset, NULL) < 0)
return 0;
/* That works for all keylargos but shall be fixed properly
* some day... The problem is that it seems we can't rely
@@ -389,7 +389,6 @@ static u32 read_gpio(struct device_node *np)
* relative to the base of KeyLargo or to the base of the
* GPIO space, and the device-tree doesn't help.
*/
- offset = *reg;
if (offset < KEYLARGO_GPIO_LEVELS0)
offset += KEYLARGO_GPIO_LEVELS0;
return offset;
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index 84d7033e5efe..ea05d9d67490 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -23,13 +23,28 @@
#include <linux/nvmem-consumer.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/pm.h>
#include <linux/pm_domain.h>
#include <linux/pm_opp.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/soc/qcom/smem.h>
#include <dt-bindings/arm/qcom,ids.h>
+enum ipq806x_versions {
+ IPQ8062_VERSION = 0,
+ IPQ8064_VERSION,
+ IPQ8065_VERSION,
+};
+
+#define IPQ6000_VERSION BIT(2)
+
+enum ipq8074_versions {
+ IPQ8074_HAWKEYE_VERSION = 0,
+ IPQ8074_ACORN_VERSION,
+};
+
struct qcom_cpufreq_drv;
struct qcom_cpufreq_match_data {
@@ -40,16 +55,39 @@ struct qcom_cpufreq_match_data {
const char **genpd_names;
};
+struct qcom_cpufreq_drv_cpu {
+ int opp_token;
+ struct device **virt_devs;
+};
+
struct qcom_cpufreq_drv {
- int *opp_tokens;
u32 versions;
const struct qcom_cpufreq_match_data *data;
+ struct qcom_cpufreq_drv_cpu cpus[];
};
static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev;
+static int qcom_cpufreq_simple_get_version(struct device *cpu_dev,
+ struct nvmem_cell *speedbin_nvmem,
+ char **pvs_name,
+ struct qcom_cpufreq_drv *drv)
+{
+ u8 *speedbin;
+
+ *pvs_name = NULL;
+ speedbin = nvmem_cell_read(speedbin_nvmem, NULL);
+ if (IS_ERR(speedbin))
+ return PTR_ERR(speedbin);
+
+ dev_dbg(cpu_dev, "speedbin: %d\n", *speedbin);
+ drv->versions = 1 << *speedbin;
+ kfree(speedbin);
+ return 0;
+}
+
static void get_krait_bin_format_a(struct device *cpu_dev,
- int *speed, int *pvs, int *pvs_ver,
+ int *speed, int *pvs,
u8 *buf)
{
u32 pte_efuse;
@@ -148,6 +186,16 @@ static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
switch (msm_id) {
case QCOM_ID_MSM8996:
case QCOM_ID_APQ8096:
+ case QCOM_ID_IPQ5332:
+ case QCOM_ID_IPQ5322:
+ case QCOM_ID_IPQ5312:
+ case QCOM_ID_IPQ5302:
+ case QCOM_ID_IPQ5300:
+ case QCOM_ID_IPQ9514:
+ case QCOM_ID_IPQ9550:
+ case QCOM_ID_IPQ9554:
+ case QCOM_ID_IPQ9570:
+ case QCOM_ID_IPQ9574:
drv->versions = 1 << (unsigned int)(*speedbin);
break;
case QCOM_ID_MSM8996SG:
@@ -180,8 +228,7 @@ static int qcom_cpufreq_krait_name_version(struct device *cpu_dev,
switch (len) {
case 4:
- get_krait_bin_format_a(cpu_dev, &speed, &pvs, &pvs_ver,
- speedbin);
+ get_krait_bin_format_a(cpu_dev, &speed, &pvs, speedbin);
break;
case 8:
get_krait_bin_format_b(cpu_dev, &speed, &pvs, &pvs_ver,
@@ -203,6 +250,152 @@ len_error:
return ret;
}
+static int qcom_cpufreq_ipq8064_name_version(struct device *cpu_dev,
+ struct nvmem_cell *speedbin_nvmem,
+ char **pvs_name,
+ struct qcom_cpufreq_drv *drv)
+{
+ int speed = 0, pvs = 0;
+ int msm_id, ret = 0;
+ u8 *speedbin;
+ size_t len;
+
+ speedbin = nvmem_cell_read(speedbin_nvmem, &len);
+ if (IS_ERR(speedbin))
+ return PTR_ERR(speedbin);
+
+ if (len != 4) {
+ dev_err(cpu_dev, "Unable to read nvmem data. Defaulting to 0!\n");
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ get_krait_bin_format_a(cpu_dev, &speed, &pvs, speedbin);
+
+ ret = qcom_smem_get_soc_id(&msm_id);
+ if (ret)
+ goto exit;
+
+ switch (msm_id) {
+ case QCOM_ID_IPQ8062:
+ drv->versions = BIT(IPQ8062_VERSION);
+ break;
+ case QCOM_ID_IPQ8064:
+ case QCOM_ID_IPQ8066:
+ case QCOM_ID_IPQ8068:
+ drv->versions = BIT(IPQ8064_VERSION);
+ break;
+ case QCOM_ID_IPQ8065:
+ case QCOM_ID_IPQ8069:
+ drv->versions = BIT(IPQ8065_VERSION);
+ break;
+ default:
+ dev_err(cpu_dev,
+ "SoC ID %u is not part of IPQ8064 family, limiting to 1.0GHz!\n",
+ msm_id);
+ drv->versions = BIT(IPQ8062_VERSION);
+ break;
+ }
+
+ /* IPQ8064 speed is never fused. Only pvs values are fused. */
+ snprintf(*pvs_name, sizeof("speed0-pvsXX"), "speed0-pvs%d", pvs);
+
+exit:
+ kfree(speedbin);
+ return ret;
+}
+
+static int qcom_cpufreq_ipq6018_name_version(struct device *cpu_dev,
+ struct nvmem_cell *speedbin_nvmem,
+ char **pvs_name,
+ struct qcom_cpufreq_drv *drv)
+{
+ u32 msm_id;
+ int ret;
+ u8 *speedbin;
+ *pvs_name = NULL;
+
+ ret = qcom_smem_get_soc_id(&msm_id);
+ if (ret)
+ return ret;
+
+ speedbin = nvmem_cell_read(speedbin_nvmem, NULL);
+ if (IS_ERR(speedbin))
+ return PTR_ERR(speedbin);
+
+ switch (msm_id) {
+ case QCOM_ID_IPQ6005:
+ case QCOM_ID_IPQ6010:
+ case QCOM_ID_IPQ6018:
+ case QCOM_ID_IPQ6028:
+ /* Fuse Value Freq BIT to set
+ * ---------------------------------
+ * 2’b0 No Limit BIT(0)
+ * 2’b1 1.5 GHz BIT(1)
+ */
+ drv->versions = 1 << (unsigned int)(*speedbin);
+ break;
+ case QCOM_ID_IPQ6000:
+ /*
+ * IPQ6018 family only has one bit to advertise the CPU
+ * speed-bin, but that is not enough for IPQ6000 which
+ * is only rated up to 1.2GHz.
+ * So for IPQ6000 manually set BIT(2) based on SMEM ID.
+ */
+ drv->versions = IPQ6000_VERSION;
+ break;
+ default:
+ dev_err(cpu_dev,
+ "SoC ID %u is not part of IPQ6018 family, limiting to 1.2GHz!\n",
+ msm_id);
+ drv->versions = IPQ6000_VERSION;
+ break;
+ }
+
+ kfree(speedbin);
+ return 0;
+}
+
+static int qcom_cpufreq_ipq8074_name_version(struct device *cpu_dev,
+ struct nvmem_cell *speedbin_nvmem,
+ char **pvs_name,
+ struct qcom_cpufreq_drv *drv)
+{
+ u32 msm_id;
+ int ret;
+ *pvs_name = NULL;
+
+ ret = qcom_smem_get_soc_id(&msm_id);
+ if (ret)
+ return ret;
+
+ switch (msm_id) {
+ case QCOM_ID_IPQ8070A:
+ case QCOM_ID_IPQ8071A:
+ case QCOM_ID_IPQ8172:
+ case QCOM_ID_IPQ8173:
+ case QCOM_ID_IPQ8174:
+ drv->versions = BIT(IPQ8074_ACORN_VERSION);
+ break;
+ case QCOM_ID_IPQ8072A:
+ case QCOM_ID_IPQ8074A:
+ case QCOM_ID_IPQ8076A:
+ case QCOM_ID_IPQ8078A:
+ drv->versions = BIT(IPQ8074_HAWKEYE_VERSION);
+ break;
+ default:
+ dev_err(cpu_dev,
+ "SoC ID %u is not part of IPQ8074 family, limiting to 1.4GHz!\n",
+ msm_id);
+ drv->versions = BIT(IPQ8074_ACORN_VERSION);
+ break;
+ }
+
+ return 0;
+}
+
+static const char *generic_genpd_names[] = { "perf", NULL };
+
static const struct qcom_cpufreq_match_data match_data_kryo = {
.get_version = qcom_cpufreq_kryo_name_version,
};
@@ -211,12 +404,53 @@ static const struct qcom_cpufreq_match_data match_data_krait = {
.get_version = qcom_cpufreq_krait_name_version,
};
+static const struct qcom_cpufreq_match_data match_data_msm8909 = {
+ .get_version = qcom_cpufreq_simple_get_version,
+ .genpd_names = generic_genpd_names,
+};
+
static const char *qcs404_genpd_names[] = { "cpr", NULL };
static const struct qcom_cpufreq_match_data match_data_qcs404 = {
.genpd_names = qcs404_genpd_names,
};
+static const struct qcom_cpufreq_match_data match_data_ipq6018 = {
+ .get_version = qcom_cpufreq_ipq6018_name_version,
+};
+
+static const struct qcom_cpufreq_match_data match_data_ipq8064 = {
+ .get_version = qcom_cpufreq_ipq8064_name_version,
+};
+
+static const struct qcom_cpufreq_match_data match_data_ipq8074 = {
+ .get_version = qcom_cpufreq_ipq8074_name_version,
+};
+
+static void qcom_cpufreq_suspend_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
+{
+ const char * const *name = drv->data->genpd_names;
+ int i;
+
+ if (!drv->cpus[cpu].virt_devs)
+ return;
+
+ for (i = 0; *name; i++, name++)
+ device_set_awake_path(drv->cpus[cpu].virt_devs[i]);
+}
+
+static void qcom_cpufreq_put_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
+{
+ const char * const *name = drv->data->genpd_names;
+ int i;
+
+ if (!drv->cpus[cpu].virt_devs)
+ return;
+
+ for (i = 0; *name; i++, name++)
+ pm_runtime_put(drv->cpus[cpu].virt_devs[i]);
+}
+
static int qcom_cpufreq_probe(struct platform_device *pdev)
{
struct qcom_cpufreq_drv *drv;
@@ -237,49 +471,41 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
if (!np)
return -ENOENT;
- ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu");
+ ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu") ||
+ of_device_is_compatible(np, "operating-points-v2-krait-cpu");
if (!ret) {
of_node_put(np);
return -ENOENT;
}
- drv = kzalloc(sizeof(*drv), GFP_KERNEL);
+ drv = devm_kzalloc(&pdev->dev, struct_size(drv, cpus, num_possible_cpus()),
+ GFP_KERNEL);
if (!drv)
return -ENOMEM;
match = pdev->dev.platform_data;
drv->data = match->data;
- if (!drv->data) {
- ret = -ENODEV;
- goto free_drv;
- }
+ if (!drv->data)
+ return -ENODEV;
if (drv->data->get_version) {
speedbin_nvmem = of_nvmem_cell_get(np, NULL);
- if (IS_ERR(speedbin_nvmem)) {
- ret = dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
- "Could not get nvmem cell\n");
- goto free_drv;
- }
+ if (IS_ERR(speedbin_nvmem))
+ return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
+ "Could not get nvmem cell\n");
ret = drv->data->get_version(cpu_dev,
speedbin_nvmem, &pvs_name, drv);
if (ret) {
nvmem_cell_put(speedbin_nvmem);
- goto free_drv;
+ return ret;
}
nvmem_cell_put(speedbin_nvmem);
}
of_node_put(np);
- drv->opp_tokens = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tokens),
- GFP_KERNEL);
- if (!drv->opp_tokens) {
- ret = -ENOMEM;
- goto free_drv;
- }
-
for_each_possible_cpu(cpu) {
+ struct device **virt_devs = NULL;
struct dev_pm_opp_config config = {
.supported_hw = NULL,
};
@@ -300,17 +526,38 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
if (drv->data->genpd_names) {
config.genpd_names = drv->data->genpd_names;
- config.virt_devs = NULL;
+ config.virt_devs = &virt_devs;
}
if (config.supported_hw || config.genpd_names) {
- drv->opp_tokens[cpu] = dev_pm_opp_set_config(cpu_dev, &config);
- if (drv->opp_tokens[cpu] < 0) {
- ret = drv->opp_tokens[cpu];
+ drv->cpus[cpu].opp_token = dev_pm_opp_set_config(cpu_dev, &config);
+ if (drv->cpus[cpu].opp_token < 0) {
+ ret = drv->cpus[cpu].opp_token;
dev_err(cpu_dev, "Failed to set OPP config\n");
goto free_opp;
}
}
+
+ if (virt_devs) {
+ const char * const *name = config.genpd_names;
+ int i, j;
+
+ for (i = 0; *name; i++, name++) {
+ ret = pm_runtime_resume_and_get(virt_devs[i]);
+ if (ret) {
+ dev_err(cpu_dev, "failed to resume %s: %d\n",
+ *name, ret);
+
+ /* Rollback previous PM runtime calls */
+ name = config.genpd_names;
+ for (j = 0; *name && j < i; j++, name++)
+ pm_runtime_put(virt_devs[j]);
+
+ goto free_opp;
+ }
+ }
+ drv->cpus[cpu].virt_devs = virt_devs;
+ }
}
cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
@@ -324,12 +571,10 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
dev_err(cpu_dev, "Failed to register platform device\n");
free_opp:
- for_each_possible_cpu(cpu)
- dev_pm_opp_clear_config(drv->opp_tokens[cpu]);
- kfree(drv->opp_tokens);
-free_drv:
- kfree(drv);
-
+ for_each_possible_cpu(cpu) {
+ qcom_cpufreq_put_virt_devs(drv, cpu);
+ dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
+ }
return ret;
}
@@ -340,27 +585,45 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
platform_device_unregister(cpufreq_dt_pdev);
+ for_each_possible_cpu(cpu) {
+ qcom_cpufreq_put_virt_devs(drv, cpu);
+ dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
+ }
+}
+
+static int qcom_cpufreq_suspend(struct device *dev)
+{
+ struct qcom_cpufreq_drv *drv = dev_get_drvdata(dev);
+ unsigned int cpu;
+
for_each_possible_cpu(cpu)
- dev_pm_opp_clear_config(drv->opp_tokens[cpu]);
+ qcom_cpufreq_suspend_virt_devs(drv, cpu);
- kfree(drv->opp_tokens);
- kfree(drv);
+ return 0;
}
+static DEFINE_SIMPLE_DEV_PM_OPS(qcom_cpufreq_pm_ops, qcom_cpufreq_suspend, NULL);
+
static struct platform_driver qcom_cpufreq_driver = {
.probe = qcom_cpufreq_probe,
.remove_new = qcom_cpufreq_remove,
.driver = {
.name = "qcom-cpufreq-nvmem",
+ .pm = pm_sleep_ptr(&qcom_cpufreq_pm_ops),
},
};
static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
{ .compatible = "qcom,apq8096", .data = &match_data_kryo },
+ { .compatible = "qcom,msm8909", .data = &match_data_msm8909 },
{ .compatible = "qcom,msm8996", .data = &match_data_kryo },
{ .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
- { .compatible = "qcom,ipq8064", .data = &match_data_krait },
+ { .compatible = "qcom,ipq5332", .data = &match_data_kryo },
+ { .compatible = "qcom,ipq6018", .data = &match_data_ipq6018 },
+ { .compatible = "qcom,ipq8064", .data = &match_data_ipq8064 },
+ { .compatible = "qcom,ipq8074", .data = &match_data_ipq8074 },
{ .compatible = "qcom,apq8064", .data = &match_data_krait },
+ { .compatible = "qcom,ipq9574", .data = &match_data_kryo },
{ .compatible = "qcom,msm8974", .data = &match_data_krait },
{ .compatible = "qcom,msm8960", .data = &match_data_krait },
{},
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index f34e6382a4c5..c8a7ccc42c16 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -70,16 +70,36 @@ static unsigned int scmi_cpufreq_fast_switch(struct cpufreq_policy *policy,
return 0;
}
+static int scmi_cpu_domain_id(struct device *cpu_dev)
+{
+ struct device_node *np = cpu_dev->of_node;
+ struct of_phandle_args domain_id;
+ int index;
+
+ if (of_parse_phandle_with_args(np, "clocks", "#clock-cells", 0,
+ &domain_id)) {
+ /* Find the corresponding index for power-domain "perf". */
+ index = of_property_match_string(np, "power-domain-names",
+ "perf");
+ if (index < 0)
+ return -EINVAL;
+
+ if (of_parse_phandle_with_args(np, "power-domains",
+ "#power-domain-cells", index,
+ &domain_id))
+ return -EINVAL;
+ }
+
+ return domain_id.args[0];
+}
+
static int
-scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
+scmi_get_sharing_cpus(struct device *cpu_dev, int domain,
+ struct cpumask *cpumask)
{
- int cpu, domain, tdomain;
+ int cpu, tdomain;
struct device *tcpu_dev;
- domain = perf_ops->device_domain_id(cpu_dev);
- if (domain < 0)
- return domain;
-
for_each_possible_cpu(cpu) {
if (cpu == cpu_dev->id)
continue;
@@ -88,7 +108,7 @@ scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
if (!tcpu_dev)
continue;
- tdomain = perf_ops->device_domain_id(tcpu_dev);
+ tdomain = scmi_cpu_domain_id(tcpu_dev);
if (tdomain == domain)
cpumask_set_cpu(cpu, cpumask);
}
@@ -104,7 +124,7 @@ scmi_get_cpu_power(struct device *cpu_dev, unsigned long *power,
unsigned long Hz;
int ret, domain;
- domain = perf_ops->device_domain_id(cpu_dev);
+ domain = scmi_cpu_domain_id(cpu_dev);
if (domain < 0)
return domain;
@@ -126,7 +146,7 @@ scmi_get_cpu_power(struct device *cpu_dev, unsigned long *power,
static int scmi_cpufreq_init(struct cpufreq_policy *policy)
{
- int ret, nr_opp;
+ int ret, nr_opp, domain;
unsigned int latency;
struct device *cpu_dev;
struct scmi_data *priv;
@@ -138,6 +158,10 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
return -ENODEV;
}
+ domain = scmi_cpu_domain_id(cpu_dev);
+ if (domain < 0)
+ return domain;
+
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -148,7 +172,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
}
/* Obtain CPUs that share SCMI performance controls */
- ret = scmi_get_sharing_cpus(cpu_dev, policy->cpus);
+ ret = scmi_get_sharing_cpus(cpu_dev, domain, policy->cpus);
if (ret) {
dev_warn(cpu_dev, "failed to get sharing cpumask\n");
goto out_free_cpumask;
@@ -176,7 +200,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
*/
nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
if (nr_opp <= 0) {
- ret = perf_ops->device_opps_add(ph, cpu_dev);
+ ret = perf_ops->device_opps_add(ph, cpu_dev, domain);
if (ret) {
dev_warn(cpu_dev, "failed to add opps to the device\n");
goto out_free_cpumask;
@@ -209,7 +233,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
}
priv->cpu_dev = cpu_dev;
- priv->domain_id = perf_ops->device_domain_id(cpu_dev);
+ priv->domain_id = domain;
policy->driver_data = priv;
policy->freq_table = freq_table;
@@ -217,14 +241,14 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
/* SCMI allows DVFS request for any domain from any CPU */
policy->dvfs_possible_from_any_cpu = true;
- latency = perf_ops->transition_latency_get(ph, cpu_dev);
+ latency = perf_ops->transition_latency_get(ph, domain);
if (!latency)
latency = CPUFREQ_ETERNAL;
policy->cpuinfo.transition_latency = latency;
policy->fast_switch_possible =
- perf_ops->fast_switch_possible(ph, cpu_dev);
+ perf_ops->fast_switch_possible(ph, domain);
return 0;
diff --git a/drivers/cpufreq/tegra194-cpufreq.c b/drivers/cpufreq/tegra194-cpufreq.c
index 88ef5e57ccd0..59865ea455a8 100644
--- a/drivers/cpufreq/tegra194-cpufreq.c
+++ b/drivers/cpufreq/tegra194-cpufreq.c
@@ -5,7 +5,6 @@
#include <linux/cpu.h>
#include <linux/cpufreq.h>
-#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -21,10 +20,11 @@
#define KHZ 1000
#define REF_CLK_MHZ 408 /* 408 MHz */
-#define US_DELAY 500
#define CPUFREQ_TBL_STEP_HZ (50 * KHZ * KHZ)
#define MAX_CNT ~0U
+#define MAX_DELTA_KHZ 115200
+
#define NDIV_MASK 0x1FF
#define CORE_OFFSET(cpu) (cpu * 8)
@@ -39,6 +39,12 @@
/* cpufreq transisition latency */
#define TEGRA_CPUFREQ_TRANSITION_LATENCY (300 * 1000) /* unit in nanoseconds */
+struct tegra_cpu_data {
+ u32 cpuid;
+ u32 clusterid;
+ void __iomem *freq_core_reg;
+};
+
struct tegra_cpu_ctr {
u32 cpu;
u32 coreclk_cnt, last_coreclk_cnt;
@@ -62,6 +68,7 @@ struct tegra_cpufreq_soc {
int maxcpus_per_cluster;
unsigned int num_clusters;
phys_addr_t actmon_cntr_base;
+ u32 refclk_delta_min;
};
struct tegra194_cpufreq_data {
@@ -69,6 +76,7 @@ struct tegra194_cpufreq_data {
struct cpufreq_frequency_table **bpmp_luts;
const struct tegra_cpufreq_soc *soc;
bool icc_dram_bw_scaling;
+ struct tegra_cpu_data *cpu_data;
};
static struct workqueue_struct *read_counters_wq;
@@ -116,14 +124,8 @@ static void tegra234_get_cpu_cluster_id(u32 cpu, u32 *cpuid, u32 *clusterid)
static int tegra234_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv)
{
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
- void __iomem *freq_core_reg;
- u64 mpidr_id;
- /* use physical id to get address of per core frequency register */
- mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid;
- freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id);
-
- *ndiv = readl(freq_core_reg) & NDIV_MASK;
+ *ndiv = readl(data->cpu_data[cpu].freq_core_reg) & NDIV_MASK;
return 0;
}
@@ -131,19 +133,10 @@ static int tegra234_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv)
static void tegra234_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv)
{
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
- void __iomem *freq_core_reg;
- u32 cpu, cpuid, clusterid;
- u64 mpidr_id;
-
- for_each_cpu_and(cpu, policy->cpus, cpu_online_mask) {
- data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid);
-
- /* use physical id to get address of per core frequency register */
- mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid;
- freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id);
+ u32 cpu;
- writel(ndiv, freq_core_reg);
- }
+ for_each_cpu(cpu, policy->cpus)
+ writel(ndiv, data->cpu_data[cpu].freq_core_reg);
}
/*
@@ -157,19 +150,35 @@ static void tegra234_read_counters(struct tegra_cpu_ctr *c)
{
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
void __iomem *actmon_reg;
- u32 cpuid, clusterid;
+ u32 delta_refcnt;
+ int cnt = 0;
u64 val;
- data->soc->ops->get_cpu_cluster_id(c->cpu, &cpuid, &clusterid);
- actmon_reg = CORE_ACTMON_CNTR_REG(data, clusterid, cpuid);
+ actmon_reg = CORE_ACTMON_CNTR_REG(data, data->cpu_data[c->cpu].clusterid,
+ data->cpu_data[c->cpu].cpuid);
val = readq(actmon_reg);
c->last_refclk_cnt = upper_32_bits(val);
c->last_coreclk_cnt = lower_32_bits(val);
- udelay(US_DELAY);
- val = readq(actmon_reg);
- c->refclk_cnt = upper_32_bits(val);
- c->coreclk_cnt = lower_32_bits(val);
+
+ /*
+ * The sampling window is based on the minimum number of reference
+ * clock cycles which is known to give a stable value of CPU frequency.
+ */
+ do {
+ val = readq(actmon_reg);
+ c->refclk_cnt = upper_32_bits(val);
+ c->coreclk_cnt = lower_32_bits(val);
+ if (c->refclk_cnt < c->last_refclk_cnt)
+ delta_refcnt = c->refclk_cnt + (MAX_CNT - c->last_refclk_cnt);
+ else
+ delta_refcnt = c->refclk_cnt - c->last_refclk_cnt;
+ if (++cnt >= 0xFFFF) {
+ pr_warn("cpufreq: problem with refclk on cpu:%d, delta_refcnt:%u, cnt:%d\n",
+ c->cpu, delta_refcnt, cnt);
+ break;
+ }
+ } while (delta_refcnt < data->soc->refclk_delta_min);
}
static struct tegra_cpufreq_ops tegra234_cpufreq_ops = {
@@ -184,6 +193,7 @@ static const struct tegra_cpufreq_soc tegra234_cpufreq_soc = {
.actmon_cntr_base = 0x9000,
.maxcpus_per_cluster = 4,
.num_clusters = 3,
+ .refclk_delta_min = 16000,
};
static const struct tegra_cpufreq_soc tegra239_cpufreq_soc = {
@@ -191,6 +201,7 @@ static const struct tegra_cpufreq_soc tegra239_cpufreq_soc = {
.actmon_cntr_base = 0x4000,
.maxcpus_per_cluster = 8,
.num_clusters = 1,
+ .refclk_delta_min = 16000,
};
static void tegra194_get_cpu_cluster_id(u32 cpu, u32 *cpuid, u32 *clusterid)
@@ -231,15 +242,33 @@ static inline u32 map_ndiv_to_freq(struct mrq_cpu_ndiv_limits_response
static void tegra194_read_counters(struct tegra_cpu_ctr *c)
{
+ struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
+ u32 delta_refcnt;
+ int cnt = 0;
u64 val;
val = read_freq_feedback();
c->last_refclk_cnt = lower_32_bits(val);
c->last_coreclk_cnt = upper_32_bits(val);
- udelay(US_DELAY);
- val = read_freq_feedback();
- c->refclk_cnt = lower_32_bits(val);
- c->coreclk_cnt = upper_32_bits(val);
+
+ /*
+ * The sampling window is based on the minimum number of reference
+ * clock cycles which is known to give a stable value of CPU frequency.
+ */
+ do {
+ val = read_freq_feedback();
+ c->refclk_cnt = lower_32_bits(val);
+ c->coreclk_cnt = upper_32_bits(val);
+ if (c->refclk_cnt < c->last_refclk_cnt)
+ delta_refcnt = c->refclk_cnt + (MAX_CNT - c->last_refclk_cnt);
+ else
+ delta_refcnt = c->refclk_cnt - c->last_refclk_cnt;
+ if (++cnt >= 0xFFFF) {
+ pr_warn("cpufreq: problem with refclk on cpu:%d, delta_refcnt:%u, cnt:%d\n",
+ c->cpu, delta_refcnt, cnt);
+ break;
+ }
+ } while (delta_refcnt < data->soc->refclk_delta_min);
}
static void tegra_read_counters(struct work_struct *work)
@@ -297,9 +326,8 @@ static unsigned int tegra194_calculate_speed(u32 cpu)
u32 rate_mhz;
/*
- * udelay() is required to reconstruct cpu frequency over an
- * observation window. Using workqueue to call udelay() with
- * interrupts enabled.
+ * Reconstruct cpu frequency over an observation/sampling window.
+ * Using workqueue to keep interrupts enabled during the interval.
*/
read_counters_work.c.cpu = cpu;
INIT_WORK_ONSTACK(&read_counters_work.work, tegra_read_counters);
@@ -357,19 +385,17 @@ static void tegra194_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv)
static unsigned int tegra194_get_speed(u32 cpu)
{
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
+ u32 clusterid = data->cpu_data[cpu].clusterid;
struct cpufreq_frequency_table *pos;
- u32 cpuid, clusterid;
unsigned int rate;
u64 ndiv;
int ret;
- data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid);
-
/* reconstruct actual cpu freq using counters */
rate = tegra194_calculate_speed(cpu);
/* get last written ndiv value */
- ret = data->soc->ops->get_cpu_ndiv(cpu, cpuid, clusterid, &ndiv);
+ ret = data->soc->ops->get_cpu_ndiv(cpu, data->cpu_data[cpu].cpuid, clusterid, &ndiv);
if (WARN_ON_ONCE(ret))
return rate;
@@ -383,9 +409,9 @@ static unsigned int tegra194_get_speed(u32 cpu)
if (pos->driver_data != ndiv)
continue;
- if (abs(pos->frequency - rate) > 115200) {
- pr_warn("cpufreq: cpu%d,cur:%u,set:%u,set ndiv:%llu\n",
- cpu, rate, pos->frequency, ndiv);
+ if (abs(pos->frequency - rate) > MAX_DELTA_KHZ) {
+ pr_warn("cpufreq: cpu%d,cur:%u,set:%u,delta:%d,set ndiv:%llu\n",
+ cpu, rate, pos->frequency, abs(rate - pos->frequency), ndiv);
} else {
rate = pos->frequency;
}
@@ -450,6 +476,8 @@ static int tegra_cpufreq_init_cpufreq_table(struct cpufreq_policy *policy,
if (IS_ERR(opp))
continue;
+ dev_pm_opp_put(opp);
+
ret = dev_pm_opp_enable(cpu_dev, pos->frequency * KHZ);
if (ret < 0)
return ret;
@@ -473,13 +501,12 @@ static int tegra194_cpufreq_init(struct cpufreq_policy *policy)
{
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
int maxcpus_per_cluster = data->soc->maxcpus_per_cluster;
+ u32 clusterid = data->cpu_data[policy->cpu].clusterid;
struct cpufreq_frequency_table *freq_table;
struct cpufreq_frequency_table *bpmp_lut;
u32 start_cpu, cpu;
- u32 clusterid;
int ret;
- data->soc->ops->get_cpu_cluster_id(policy->cpu, NULL, &clusterid);
if (clusterid >= data->soc->num_clusters || !data->bpmp_luts[clusterid])
return -EINVAL;
@@ -578,6 +605,7 @@ static const struct tegra_cpufreq_soc tegra194_cpufreq_soc = {
.ops = &tegra194_cpufreq_ops,
.maxcpus_per_cluster = 2,
.num_clusters = 4,
+ .refclk_delta_min = 16000,
};
static void tegra194_cpufreq_free_resources(void)
@@ -657,6 +685,28 @@ tegra_cpufreq_bpmp_read_lut(struct platform_device *pdev, struct tegra_bpmp *bpm
return freq_table;
}
+static int tegra194_cpufreq_store_physids(unsigned int cpu, struct tegra194_cpufreq_data *data)
+{
+ int num_cpus = data->soc->maxcpus_per_cluster * data->soc->num_clusters;
+ u32 cpuid, clusterid;
+ u64 mpidr_id;
+
+ if (cpu > (num_cpus - 1)) {
+ pr_err("cpufreq: wrong num of cpus or clusters in soc data\n");
+ return -EINVAL;
+ }
+
+ data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid);
+
+ mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid;
+
+ data->cpu_data[cpu].cpuid = cpuid;
+ data->cpu_data[cpu].clusterid = clusterid;
+ data->cpu_data[cpu].freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id);
+
+ return 0;
+}
+
static int tegra194_cpufreq_probe(struct platform_device *pdev)
{
const struct tegra_cpufreq_soc *soc;
@@ -664,6 +714,7 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
struct tegra_bpmp *bpmp;
struct device *cpu_dev;
int err, i;
+ u32 cpu;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
@@ -671,7 +722,7 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
soc = of_device_get_match_data(&pdev->dev);
- if (soc->ops && soc->maxcpus_per_cluster && soc->num_clusters) {
+ if (soc->ops && soc->maxcpus_per_cluster && soc->num_clusters && soc->refclk_delta_min) {
data->soc = soc;
} else {
dev_err(&pdev->dev, "soc data missing\n");
@@ -690,6 +741,12 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
return PTR_ERR(data->regs);
}
+ data->cpu_data = devm_kcalloc(&pdev->dev, data->soc->num_clusters *
+ data->soc->maxcpus_per_cluster,
+ sizeof(*data->cpu_data), GFP_KERNEL);
+ if (!data->cpu_data)
+ return -ENOMEM;
+
platform_set_drvdata(pdev, data);
bpmp = tegra_bpmp_get(&pdev->dev);
@@ -711,6 +768,12 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
}
}
+ for_each_possible_cpu(cpu) {
+ err = tegra194_cpufreq_store_physids(cpu, data);
+ if (err)
+ goto err_free_res;
+ }
+
tegra194_cpufreq_driver.driver_data = data;
/* Check for optional OPPv2 and interconnect paths on CPU0 to enable ICC scaling */
diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
index 3c37d7899660..46c41e2ca727 100644
--- a/drivers/cpufreq/ti-cpufreq.c
+++ b/drivers/cpufreq/ti-cpufreq.c
@@ -338,6 +338,7 @@ static const struct of_device_id ti_cpufreq_of_match[] = {
{ .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, },
{ .compatible = "ti,am625", .data = &am625_soc_data, },
{ .compatible = "ti,am62a7", .data = &am625_soc_data, },
+ { .compatible = "ti,am62p5", .data = &am625_soc_data, },
/* legacy */
{ .compatible = "ti,omap3430", .data = &omap34xx_soc_data, },
{ .compatible = "ti,omap3630", .data = &omap36xx_soc_data, },
diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
index 12fec92a85fd..97feb7d8fb23 100644
--- a/drivers/cpuidle/dt_idle_states.c
+++ b/drivers/cpuidle/dt_idle_states.c
@@ -84,8 +84,8 @@ static int init_state_node(struct cpuidle_state *idle_state,
* replace with kstrdup and pointer assignment when name
* and desc become string pointers
*/
- strncpy(idle_state->name, state_node->name, CPUIDLE_NAME_LEN - 1);
- strncpy(idle_state->desc, desc, CPUIDLE_DESC_LEN - 1);
+ strscpy(idle_state->name, state_node->name, CPUIDLE_NAME_LEN);
+ strscpy(idle_state->desc, desc, CPUIDLE_DESC_LEN);
return 0;
}
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index c761952f0dc6..79c3bb9c99c3 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -601,6 +601,7 @@ config CRYPTO_DEV_QCE_SW_MAX_LEN
config CRYPTO_DEV_QCOM_RNG
tristate "Qualcomm Random Number Generator Driver"
depends on ARCH_QCOM || COMPILE_TEST
+ depends on HW_RANDOM
select CRYPTO_RNG
help
This driver provides support for the Random Number
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
index 3bcfcfc37084..890664bd5f0f 100644
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
+++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
@@ -49,7 +49,6 @@ static struct sun4i_ss_alg_template ss_algs[] = {
.cra_name = "md5",
.cra_driver_name = "md5-sun4i-ss",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sun4i_req_ctx),
.cra_module = THIS_MODULE,
@@ -76,7 +75,6 @@ static struct sun4i_ss_alg_template ss_algs[] = {
.cra_name = "sha1",
.cra_driver_name = "sha1-sun4i-ss",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sun4i_req_ctx),
.cra_module = THIS_MODULE,
@@ -509,7 +507,7 @@ error_pm:
return err;
}
-static int sun4i_ss_remove(struct platform_device *pdev)
+static void sun4i_ss_remove(struct platform_device *pdev)
{
int i;
struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev);
@@ -529,7 +527,6 @@ static int sun4i_ss_remove(struct platform_device *pdev)
}
sun4i_ss_pm_exit(ss);
- return 0;
}
static const struct of_device_id a20ss_crypto_of_match_table[] = {
@@ -545,7 +542,7 @@ MODULE_DEVICE_TABLE(of, a20ss_crypto_of_match_table);
static struct platform_driver sun4i_ss_driver = {
.probe = sun4i_ss_probe,
- .remove = sun4i_ss_remove,
+ .remove_new = sun4i_ss_remove,
.driver = {
.name = "sun4i-ss",
.pm = &sun4i_ss_pm_ops,
diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c
index d4ccd5254280..0408b2d5d533 100644
--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c
+++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c
@@ -414,7 +414,6 @@ static struct sun8i_ce_alg_template ce_algs[] = {
.cra_name = "md5",
.cra_driver_name = "md5-sun8i-ce",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_flags = CRYPTO_ALG_TYPE_AHASH |
CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
@@ -448,7 +447,6 @@ static struct sun8i_ce_alg_template ce_algs[] = {
.cra_name = "sha1",
.cra_driver_name = "sha1-sun8i-ce",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_flags = CRYPTO_ALG_TYPE_AHASH |
CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
@@ -481,7 +479,6 @@ static struct sun8i_ce_alg_template ce_algs[] = {
.cra_name = "sha224",
.cra_driver_name = "sha224-sun8i-ce",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_flags = CRYPTO_ALG_TYPE_AHASH |
CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
@@ -514,7 +511,6 @@ static struct sun8i_ce_alg_template ce_algs[] = {
.cra_name = "sha256",
.cra_driver_name = "sha256-sun8i-ce",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_flags = CRYPTO_ALG_TYPE_AHASH |
CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
@@ -547,7 +543,6 @@ static struct sun8i_ce_alg_template ce_algs[] = {
.cra_name = "sha384",
.cra_driver_name = "sha384-sun8i-ce",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_flags = CRYPTO_ALG_TYPE_AHASH |
CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
@@ -580,7 +575,6 @@ static struct sun8i_ce_alg_template ce_algs[] = {
.cra_name = "sha512",
.cra_driver_name = "sha512-sun8i-ce",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_flags = CRYPTO_ALG_TYPE_AHASH |
CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
@@ -1071,7 +1065,7 @@ error_pm:
return err;
}
-static int sun8i_ce_remove(struct platform_device *pdev)
+static void sun8i_ce_remove(struct platform_device *pdev)
{
struct sun8i_ce_dev *ce = platform_get_drvdata(pdev);
@@ -1088,7 +1082,6 @@ static int sun8i_ce_remove(struct platform_device *pdev)
sun8i_ce_free_chanlist(ce, MAXFLOW - 1);
sun8i_ce_pm_exit(ce);
- return 0;
}
static const struct of_device_id sun8i_ce_crypto_of_match_table[] = {
@@ -1110,7 +1103,7 @@ MODULE_DEVICE_TABLE(of, sun8i_ce_crypto_of_match_table);
static struct platform_driver sun8i_ce_driver = {
.probe = sun8i_ce_probe,
- .remove = sun8i_ce_remove,
+ .remove_new = sun8i_ce_remove,
.driver = {
.name = "sun8i-ce",
.pm = &sun8i_ce_pm_ops,
diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
index 4a9587285c04..0dbc0220146c 100644
--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
+++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
@@ -322,7 +322,6 @@ static struct sun8i_ss_alg_template ss_algs[] = {
.cra_name = "md5",
.cra_driver_name = "md5-sun8i-ss",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_flags = CRYPTO_ALG_TYPE_AHASH |
CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
@@ -355,7 +354,6 @@ static struct sun8i_ss_alg_template ss_algs[] = {
.cra_name = "sha1",
.cra_driver_name = "sha1-sun8i-ss",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_flags = CRYPTO_ALG_TYPE_AHASH |
CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
@@ -388,7 +386,6 @@ static struct sun8i_ss_alg_template ss_algs[] = {
.cra_name = "sha224",
.cra_driver_name = "sha224-sun8i-ss",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_flags = CRYPTO_ALG_TYPE_AHASH |
CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
@@ -421,7 +418,6 @@ static struct sun8i_ss_alg_template ss_algs[] = {
.cra_name = "sha256",
.cra_driver_name = "sha256-sun8i-ss",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_flags = CRYPTO_ALG_TYPE_AHASH |
CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
@@ -455,7 +451,6 @@ static struct sun8i_ss_alg_template ss_algs[] = {
.cra_name = "hmac(sha1)",
.cra_driver_name = "hmac-sha1-sun8i-ss",
.cra_priority = 300,
- .cra_alignmask = 3,
.cra_flags = CRYPTO_ALG_TYPE_AHASH |
CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
@@ -908,7 +903,7 @@ error_pm:
return err;
}
-static int sun8i_ss_remove(struct platform_device *pdev)
+static void sun8i_ss_remove(struct platform_device *pdev)
{
struct sun8i_ss_dev *ss = platform_get_drvdata(pdev);
@@ -921,8 +916,6 @@ static int sun8i_ss_remove(struct platform_device *pdev)
sun8i_ss_free_flows(ss, MAXFLOW - 1);
sun8i_ss_pm_exit(ss);
-
- return 0;
}
static const struct of_device_id sun8i_ss_crypto_of_match_table[] = {
@@ -936,7 +929,7 @@ MODULE_DEVICE_TABLE(of, sun8i_ss_crypto_of_match_table);
static struct platform_driver sun8i_ss_driver = {
.probe = sun8i_ss_probe,
- .remove = sun8i_ss_remove,
+ .remove_new = sun8i_ss_remove,
.driver = {
.name = "sun8i-ss",
.pm = &sun8i_ss_pm_ops,
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index d553f3f1efbe..8d53372245ad 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -1507,7 +1507,7 @@ err_alloc_dev:
return rc;
}
-static int crypto4xx_remove(struct platform_device *ofdev)
+static void crypto4xx_remove(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev);
@@ -1523,8 +1523,6 @@ static int crypto4xx_remove(struct platform_device *ofdev)
mutex_destroy(&core_dev->rng_lock);
/* Free all allocated memory */
crypto4xx_stop_all(core_dev);
-
- return 0;
}
static const struct of_device_id crypto4xx_match[] = {
@@ -1539,7 +1537,7 @@ static struct platform_driver crypto4xx_driver = {
.of_match_table = crypto4xx_match,
},
.probe = crypto4xx_probe,
- .remove = crypto4xx_remove,
+ .remove_new = crypto4xx_remove,
};
module_platform_driver(crypto4xx_driver);
diff --git a/drivers/crypto/amlogic/amlogic-gxl-core.c b/drivers/crypto/amlogic/amlogic-gxl-core.c
index da6dfe0f9ac3..f54ab0d0b1e8 100644
--- a/drivers/crypto/amlogic/amlogic-gxl-core.c
+++ b/drivers/crypto/amlogic/amlogic-gxl-core.c
@@ -299,7 +299,7 @@ error_flow:
return err;
}
-static int meson_crypto_remove(struct platform_device *pdev)
+static void meson_crypto_remove(struct platform_device *pdev)
{
struct meson_dev *mc = platform_get_drvdata(pdev);
@@ -312,7 +312,6 @@ static int meson_crypto_remove(struct platform_device *pdev)
meson_free_chanlist(mc, MAXFLOW - 1);
clk_disable_unprepare(mc->busclk);
- return 0;
}
static const struct of_device_id meson_crypto_of_match_table[] = {
@@ -323,7 +322,7 @@ MODULE_DEVICE_TABLE(of, meson_crypto_of_match_table);
static struct platform_driver meson_crypto_driver = {
.probe = meson_crypto_probe,
- .remove = meson_crypto_remove,
+ .remove_new = meson_crypto_remove,
.driver = {
.name = "gxl-crypto",
.of_match_table = meson_crypto_of_match_table,
diff --git a/drivers/crypto/aspeed/aspeed-acry.c b/drivers/crypto/aspeed/aspeed-acry.c
index 247c568aa8df..b4613bd4ad96 100644
--- a/drivers/crypto/aspeed/aspeed-acry.c
+++ b/drivers/crypto/aspeed/aspeed-acry.c
@@ -794,7 +794,7 @@ clk_exit:
return rc;
}
-static int aspeed_acry_remove(struct platform_device *pdev)
+static void aspeed_acry_remove(struct platform_device *pdev)
{
struct aspeed_acry_dev *acry_dev = platform_get_drvdata(pdev);
@@ -802,15 +802,13 @@ static int aspeed_acry_remove(struct platform_device *pdev)
crypto_engine_exit(acry_dev->crypt_engine_rsa);
tasklet_kill(&acry_dev->done_task);
clk_disable_unprepare(acry_dev->clk);
-
- return 0;
}
MODULE_DEVICE_TABLE(of, aspeed_acry_of_matches);
static struct platform_driver aspeed_acry_driver = {
.probe = aspeed_acry_probe,
- .remove = aspeed_acry_remove,
+ .remove_new = aspeed_acry_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = aspeed_acry_of_matches,
diff --git a/drivers/crypto/aspeed/aspeed-hace.c b/drivers/crypto/aspeed/aspeed-hace.c
index 8f7aab82e1d8..062f2a66dd23 100644
--- a/drivers/crypto/aspeed/aspeed-hace.c
+++ b/drivers/crypto/aspeed/aspeed-hace.c
@@ -12,11 +12,9 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_irq.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#ifdef CONFIG_CRYPTO_DEV_ASPEED_DEBUG
#define HACE_DBG(d, fmt, ...) \
@@ -101,7 +99,6 @@ static const struct of_device_id aspeed_hace_of_matches[] = {
static int aspeed_hace_probe(struct platform_device *pdev)
{
struct aspeed_engine_crypto *crypto_engine;
- const struct of_device_id *hace_dev_id;
struct aspeed_engine_hash *hash_engine;
struct aspeed_hace_dev *hace_dev;
int rc;
@@ -111,14 +108,13 @@ static int aspeed_hace_probe(struct platform_device *pdev)
if (!hace_dev)
return -ENOMEM;
- hace_dev_id = of_match_device(aspeed_hace_of_matches, &pdev->dev);
- if (!hace_dev_id) {
+ hace_dev->version = (uintptr_t)device_get_match_data(&pdev->dev);
+ if (!hace_dev->version) {
dev_err(&pdev->dev, "Failed to match hace dev id\n");
return -EINVAL;
}
hace_dev->dev = &pdev->dev;
- hace_dev->version = (unsigned long)hace_dev_id->data;
hash_engine = &hace_dev->hash_engine;
crypto_engine = &hace_dev->crypto_engine;
@@ -249,7 +245,7 @@ clk_exit:
return rc;
}
-static int aspeed_hace_remove(struct platform_device *pdev)
+static void aspeed_hace_remove(struct platform_device *pdev)
{
struct aspeed_hace_dev *hace_dev = platform_get_drvdata(pdev);
struct aspeed_engine_crypto *crypto_engine = &hace_dev->crypto_engine;
@@ -264,15 +260,13 @@ static int aspeed_hace_remove(struct platform_device *pdev)
tasklet_kill(&crypto_engine->done_task);
clk_disable_unprepare(hace_dev->clk);
-
- return 0;
}
MODULE_DEVICE_TABLE(of, aspeed_hace_of_matches);
static struct platform_driver aspeed_hace_driver = {
.probe = aspeed_hace_probe,
- .remove = aspeed_hace_remove,
+ .remove_new = aspeed_hace_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = aspeed_hace_of_matches,
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 55b5f577b01c..d1d93e897892 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -2648,7 +2648,7 @@ err_tasklet_kill:
return err;
}
-static int atmel_aes_remove(struct platform_device *pdev)
+static void atmel_aes_remove(struct platform_device *pdev)
{
struct atmel_aes_dev *aes_dd;
@@ -2667,13 +2667,11 @@ static int atmel_aes_remove(struct platform_device *pdev)
atmel_aes_buff_cleanup(aes_dd);
clk_unprepare(aes_dd->iclk);
-
- return 0;
}
static struct platform_driver atmel_aes_driver = {
.probe = atmel_aes_probe,
- .remove = atmel_aes_remove,
+ .remove_new = atmel_aes_remove,
.driver = {
.name = "atmel_aes",
.of_match_table = atmel_aes_dt_ids,
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 3622120add62..f4cd6158a4f7 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -1300,7 +1300,6 @@ static struct ahash_alg sha_384_512_algs[] = {
.halg.base.cra_name = "sha384",
.halg.base.cra_driver_name = "atmel-sha384",
.halg.base.cra_blocksize = SHA384_BLOCK_SIZE,
- .halg.base.cra_alignmask = 0x3,
.halg.digestsize = SHA384_DIGEST_SIZE,
},
@@ -1308,7 +1307,6 @@ static struct ahash_alg sha_384_512_algs[] = {
.halg.base.cra_name = "sha512",
.halg.base.cra_driver_name = "atmel-sha512",
.halg.base.cra_blocksize = SHA512_BLOCK_SIZE,
- .halg.base.cra_alignmask = 0x3,
.halg.digestsize = SHA512_DIGEST_SIZE,
},
@@ -2680,7 +2678,7 @@ err_tasklet_kill:
return err;
}
-static int atmel_sha_remove(struct platform_device *pdev)
+static void atmel_sha_remove(struct platform_device *pdev)
{
struct atmel_sha_dev *sha_dd = platform_get_drvdata(pdev);
@@ -2697,13 +2695,11 @@ static int atmel_sha_remove(struct platform_device *pdev)
atmel_sha_dma_cleanup(sha_dd);
clk_unprepare(sha_dd->iclk);
-
- return 0;
}
static struct platform_driver atmel_sha_driver = {
.probe = atmel_sha_probe,
- .remove = atmel_sha_remove,
+ .remove_new = atmel_sha_remove,
.driver = {
.name = "atmel_sha",
.of_match_table = atmel_sha_dt_ids,
diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
index 099b32a10dd7..27b7000e25bc 100644
--- a/drivers/crypto/atmel-tdes.c
+++ b/drivers/crypto/atmel-tdes.c
@@ -1246,7 +1246,7 @@ err_tasklet_kill:
return err;
}
-static int atmel_tdes_remove(struct platform_device *pdev)
+static void atmel_tdes_remove(struct platform_device *pdev)
{
struct atmel_tdes_dev *tdes_dd = platform_get_drvdata(pdev);
@@ -1263,13 +1263,11 @@ static int atmel_tdes_remove(struct platform_device *pdev)
atmel_tdes_dma_cleanup(tdes_dd);
atmel_tdes_buff_cleanup(tdes_dd);
-
- return 0;
}
static struct platform_driver atmel_tdes_driver = {
.probe = atmel_tdes_probe,
- .remove = atmel_tdes_remove,
+ .remove_new = atmel_tdes_remove,
.driver = {
.name = "atmel_tdes",
.of_match_table = atmel_tdes_dt_ids,
diff --git a/drivers/crypto/axis/artpec6_crypto.c b/drivers/crypto/axis/artpec6_crypto.c
index 8493a45e1bd4..ef9fe13ffa59 100644
--- a/drivers/crypto/axis/artpec6_crypto.c
+++ b/drivers/crypto/axis/artpec6_crypto.c
@@ -2635,7 +2635,6 @@ static struct ahash_alg hash_algos[] = {
CRYPTO_ALG_ALLOCATES_MEMORY,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct artpec6_hashalg_context),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_init = artpec6_crypto_ahash_init,
.cra_exit = artpec6_crypto_ahash_exit,
@@ -2659,7 +2658,6 @@ static struct ahash_alg hash_algos[] = {
CRYPTO_ALG_ALLOCATES_MEMORY,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct artpec6_hashalg_context),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_init = artpec6_crypto_ahash_init,
.cra_exit = artpec6_crypto_ahash_exit,
@@ -2684,7 +2682,6 @@ static struct ahash_alg hash_algos[] = {
CRYPTO_ALG_ALLOCATES_MEMORY,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct artpec6_hashalg_context),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_init = artpec6_crypto_ahash_init_hmac_sha256,
.cra_exit = artpec6_crypto_ahash_exit,
@@ -2957,7 +2954,7 @@ free_cache:
return err;
}
-static int artpec6_crypto_remove(struct platform_device *pdev)
+static void artpec6_crypto_remove(struct platform_device *pdev)
{
struct artpec6_crypto *ac = platform_get_drvdata(pdev);
int irq = platform_get_irq(pdev, 0);
@@ -2977,12 +2974,11 @@ static int artpec6_crypto_remove(struct platform_device *pdev)
#ifdef CONFIG_DEBUG_FS
artpec6_crypto_free_debugfs();
#endif
- return 0;
}
static struct platform_driver artpec6_crypto_driver = {
.probe = artpec6_crypto_probe,
- .remove = artpec6_crypto_remove,
+ .remove_new = artpec6_crypto_remove,
.driver = {
.name = "artpec6-crypto",
.of_match_table = artpec6_crypto_of_match,
diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c
index 689be70d69c1..10968ddb146b 100644
--- a/drivers/crypto/bcm/cipher.c
+++ b/drivers/crypto/bcm/cipher.c
@@ -4713,7 +4713,7 @@ failure:
return err;
}
-static int bcm_spu_remove(struct platform_device *pdev)
+static void bcm_spu_remove(struct platform_device *pdev)
{
int i;
struct device *dev = &pdev->dev;
@@ -4751,7 +4751,6 @@ static int bcm_spu_remove(struct platform_device *pdev)
}
spu_free_debugfs();
spu_mb_release(pdev);
- return 0;
}
/* ===== Kernel Module API ===== */
@@ -4762,7 +4761,7 @@ static struct platform_driver bcm_spu_pdriver = {
.of_match_table = of_match_ptr(bcm_spu_dt_ids),
},
.probe = bcm_spu_probe,
- .remove = bcm_spu_remove,
+ .remove_new = bcm_spu_remove,
};
module_platform_driver(bcm_spu_pdriver);
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index eba2d750c3b0..066f08a3a040 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -575,7 +575,8 @@ static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key,
if (keylen != CHACHA_KEY_SIZE + saltlen)
return -EINVAL;
- ctx->cdata.key_virt = key;
+ memcpy(ctx->key, key, keylen);
+ ctx->cdata.key_virt = ctx->key;
ctx->cdata.keylen = keylen - saltlen;
return chachapoly_set_sh_desc(aead);
diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
index 9156bbe038b7..a148ff1f0872 100644
--- a/drivers/crypto/caam/caamalg_qi2.c
+++ b/drivers/crypto/caam/caamalg_qi2.c
@@ -641,7 +641,8 @@ static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key,
if (keylen != CHACHA_KEY_SIZE + saltlen)
return -EINVAL;
- ctx->cdata.key_virt = key;
+ memcpy(ctx->key, key, keylen);
+ ctx->cdata.key_virt = ctx->key;
ctx->cdata.keylen = keylen - saltlen;
return chachapoly_set_sh_desc(aead);
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index b1f1b393b98e..26eba7de3fb0 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -180,7 +180,7 @@ static int caam_jr_shutdown(struct device *dev)
return ret;
}
-static int caam_jr_remove(struct platform_device *pdev)
+static void caam_jr_remove(struct platform_device *pdev)
{
int ret;
struct device *jrdev;
@@ -193,11 +193,14 @@ static int caam_jr_remove(struct platform_device *pdev)
caam_rng_exit(jrdev->parent);
/*
- * Return EBUSY if job ring already allocated.
+ * If a job ring is still allocated there is trouble ahead. Once
+ * caam_jr_remove() returned, jrpriv will be freed and the registers
+ * will get unmapped. So any user of such a job ring will probably
+ * crash.
*/
if (atomic_read(&jrpriv->tfm_count)) {
- dev_err(jrdev, "Device is busy\n");
- return -EBUSY;
+ dev_alert(jrdev, "Device is busy; consumers might start to crash\n");
+ return;
}
/* Unregister JR-based RNG & crypto algorithms */
@@ -212,13 +215,6 @@ static int caam_jr_remove(struct platform_device *pdev)
ret = caam_jr_shutdown(jrdev);
if (ret)
dev_err(jrdev, "Failed to shut down job ring\n");
-
- return ret;
-}
-
-static void caam_jr_platform_shutdown(struct platform_device *pdev)
-{
- caam_jr_remove(pdev);
}
/* Main per-ring interrupt handler */
@@ -823,8 +819,8 @@ static struct platform_driver caam_jr_driver = {
.pm = pm_ptr(&caam_jr_pm_ops),
},
.probe = caam_jr_probe,
- .remove = caam_jr_remove,
- .shutdown = caam_jr_platform_shutdown,
+ .remove_new = caam_jr_remove,
+ .shutdown = caam_jr_remove,
};
static int __init jr_driver_init(void)
diff --git a/drivers/crypto/cavium/nitrox/nitrox_hal.c b/drivers/crypto/cavium/nitrox/nitrox_hal.c
index 13b137410b75..1b5abdb6cc5e 100644
--- a/drivers/crypto/cavium/nitrox/nitrox_hal.c
+++ b/drivers/crypto/cavium/nitrox/nitrox_hal.c
@@ -647,7 +647,7 @@ void nitrox_get_hwinfo(struct nitrox_device *ndev)
ndev->hw.revision_id);
/* copy partname */
- strncpy(ndev->hw.partname, name, sizeof(ndev->hw.partname));
+ strscpy(ndev->hw.partname, name, sizeof(ndev->hw.partname));
}
void enable_pf2vf_mbox_interrupts(struct nitrox_device *ndev)
diff --git a/drivers/crypto/ccp/dbc.c b/drivers/crypto/ccp/dbc.c
index 839ea14b9a85..d373caab52f8 100644
--- a/drivers/crypto/ccp/dbc.c
+++ b/drivers/crypto/ccp/dbc.c
@@ -9,6 +9,7 @@
#include "dbc.h"
+#define DBC_DEFAULT_TIMEOUT (10 * MSEC_PER_SEC)
struct error_map {
u32 psp;
int ret;
@@ -37,22 +38,37 @@ static struct error_map error_codes[] = {
{0x0, 0x0},
};
-static int send_dbc_cmd(struct psp_dbc_device *dbc_dev,
- enum psp_platform_access_msg msg)
+static inline int send_dbc_cmd_thru_ext(struct psp_dbc_device *dbc_dev, int msg)
+{
+ dbc_dev->mbox->ext_req.header.sub_cmd_id = msg;
+
+ return psp_extended_mailbox_cmd(dbc_dev->psp,
+ DBC_DEFAULT_TIMEOUT,
+ (struct psp_ext_request *)dbc_dev->mbox);
+}
+
+static inline int send_dbc_cmd_thru_pa(struct psp_dbc_device *dbc_dev, int msg)
+{
+ return psp_send_platform_access_msg(msg,
+ (struct psp_request *)dbc_dev->mbox);
+}
+
+static int send_dbc_cmd(struct psp_dbc_device *dbc_dev, int msg)
{
int ret;
- dbc_dev->mbox->req.header.status = 0;
- ret = psp_send_platform_access_msg(msg, (struct psp_request *)dbc_dev->mbox);
+ *dbc_dev->result = 0;
+ ret = dbc_dev->use_ext ? send_dbc_cmd_thru_ext(dbc_dev, msg) :
+ send_dbc_cmd_thru_pa(dbc_dev, msg);
if (ret == -EIO) {
int i;
dev_dbg(dbc_dev->dev,
"msg 0x%x failed with PSP error: 0x%x\n",
- msg, dbc_dev->mbox->req.header.status);
+ msg, *dbc_dev->result);
for (i = 0; error_codes[i].psp; i++) {
- if (dbc_dev->mbox->req.header.status == error_codes[i].psp)
+ if (*dbc_dev->result == error_codes[i].psp)
return error_codes[i].ret;
}
}
@@ -64,7 +80,7 @@ static int send_dbc_nonce(struct psp_dbc_device *dbc_dev)
{
int ret;
- dbc_dev->mbox->req.header.payload_size = sizeof(dbc_dev->mbox->dbc_nonce);
+ *dbc_dev->payload_size = dbc_dev->header_size + sizeof(struct dbc_user_nonce);
ret = send_dbc_cmd(dbc_dev, PSP_DYNAMIC_BOOST_GET_NONCE);
if (ret == -EAGAIN) {
dev_dbg(dbc_dev->dev, "retrying get nonce\n");
@@ -76,9 +92,9 @@ static int send_dbc_nonce(struct psp_dbc_device *dbc_dev)
static int send_dbc_parameter(struct psp_dbc_device *dbc_dev)
{
- dbc_dev->mbox->req.header.payload_size = sizeof(dbc_dev->mbox->dbc_param);
+ struct dbc_user_param *user_param = (struct dbc_user_param *)dbc_dev->payload;
- switch (dbc_dev->mbox->dbc_param.user.msg_index) {
+ switch (user_param->msg_index) {
case PARAM_SET_FMAX_CAP:
case PARAM_SET_PWR_CAP:
case PARAM_SET_GFX_MODE:
@@ -125,8 +141,7 @@ static long dbc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
switch (cmd) {
case DBCIOCNONCE:
- if (copy_from_user(&dbc_dev->mbox->dbc_nonce.user, argp,
- sizeof(struct dbc_user_nonce))) {
+ if (copy_from_user(dbc_dev->payload, argp, sizeof(struct dbc_user_nonce))) {
ret = -EFAULT;
goto unlock;
}
@@ -135,43 +150,39 @@ static long dbc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (ret)
goto unlock;
- if (copy_to_user(argp, &dbc_dev->mbox->dbc_nonce.user,
- sizeof(struct dbc_user_nonce))) {
+ if (copy_to_user(argp, dbc_dev->payload, sizeof(struct dbc_user_nonce))) {
ret = -EFAULT;
goto unlock;
}
break;
case DBCIOCUID:
- dbc_dev->mbox->req.header.payload_size = sizeof(dbc_dev->mbox->dbc_set_uid);
- if (copy_from_user(&dbc_dev->mbox->dbc_set_uid.user, argp,
- sizeof(struct dbc_user_setuid))) {
+ if (copy_from_user(dbc_dev->payload, argp, sizeof(struct dbc_user_setuid))) {
ret = -EFAULT;
goto unlock;
}
+ *dbc_dev->payload_size = dbc_dev->header_size + sizeof(struct dbc_user_setuid);
ret = send_dbc_cmd(dbc_dev, PSP_DYNAMIC_BOOST_SET_UID);
if (ret)
goto unlock;
- if (copy_to_user(argp, &dbc_dev->mbox->dbc_set_uid.user,
- sizeof(struct dbc_user_setuid))) {
+ if (copy_to_user(argp, dbc_dev->payload, sizeof(struct dbc_user_setuid))) {
ret = -EFAULT;
goto unlock;
}
break;
case DBCIOCPARAM:
- if (copy_from_user(&dbc_dev->mbox->dbc_param.user, argp,
- sizeof(struct dbc_user_param))) {
+ if (copy_from_user(dbc_dev->payload, argp, sizeof(struct dbc_user_param))) {
ret = -EFAULT;
goto unlock;
}
+ *dbc_dev->payload_size = dbc_dev->header_size + sizeof(struct dbc_user_param);
ret = send_dbc_parameter(dbc_dev);
if (ret)
goto unlock;
- if (copy_to_user(argp, &dbc_dev->mbox->dbc_param.user,
- sizeof(struct dbc_user_param))) {
+ if (copy_to_user(argp, dbc_dev->payload, sizeof(struct dbc_user_param))) {
ret = -EFAULT;
goto unlock;
}
@@ -197,15 +208,12 @@ int dbc_dev_init(struct psp_device *psp)
struct psp_dbc_device *dbc_dev;
int ret;
- if (!PSP_FEATURE(psp, DBC))
- return 0;
-
dbc_dev = devm_kzalloc(dev, sizeof(*dbc_dev), GFP_KERNEL);
if (!dbc_dev)
return -ENOMEM;
BUILD_BUG_ON(sizeof(union dbc_buffer) > PAGE_SIZE);
- dbc_dev->mbox = (void *)devm_get_free_pages(dev, GFP_KERNEL, 0);
+ dbc_dev->mbox = (void *)devm_get_free_pages(dev, GFP_KERNEL | __GFP_ZERO, 0);
if (!dbc_dev->mbox) {
ret = -ENOMEM;
goto cleanup_dev;
@@ -213,6 +221,20 @@ int dbc_dev_init(struct psp_device *psp)
psp->dbc_data = dbc_dev;
dbc_dev->dev = dev;
+ dbc_dev->psp = psp;
+
+ if (PSP_CAPABILITY(psp, DBC_THRU_EXT)) {
+ dbc_dev->use_ext = true;
+ dbc_dev->payload_size = &dbc_dev->mbox->ext_req.header.payload_size;
+ dbc_dev->result = &dbc_dev->mbox->ext_req.header.status;
+ dbc_dev->payload = &dbc_dev->mbox->ext_req.buf;
+ dbc_dev->header_size = sizeof(struct psp_ext_req_buffer_hdr);
+ } else {
+ dbc_dev->payload_size = &dbc_dev->mbox->pa_req.header.payload_size;
+ dbc_dev->result = &dbc_dev->mbox->pa_req.header.status;
+ dbc_dev->payload = &dbc_dev->mbox->pa_req.buf;
+ dbc_dev->header_size = sizeof(struct psp_req_buffer_hdr);
+ }
ret = send_dbc_nonce(dbc_dev);
if (ret == -EACCES) {
diff --git a/drivers/crypto/ccp/dbc.h b/drivers/crypto/ccp/dbc.h
index e963099ca38e..e0fecbe92eb1 100644
--- a/drivers/crypto/ccp/dbc.h
+++ b/drivers/crypto/ccp/dbc.h
@@ -20,34 +20,25 @@
struct psp_dbc_device {
struct device *dev;
+ struct psp_device *psp;
union dbc_buffer *mbox;
struct mutex ioctl_mutex;
struct miscdevice char_dev;
-};
-
-struct dbc_nonce {
- struct psp_req_buffer_hdr header;
- struct dbc_user_nonce user;
-} __packed;
-struct dbc_set_uid {
- struct psp_req_buffer_hdr header;
- struct dbc_user_setuid user;
-} __packed;
-
-struct dbc_param {
- struct psp_req_buffer_hdr header;
- struct dbc_user_param user;
-} __packed;
+ /* used to abstract communication path */
+ bool use_ext;
+ u32 header_size;
+ u32 *payload_size;
+ u32 *result;
+ void *payload;
+};
union dbc_buffer {
- struct psp_request req;
- struct dbc_nonce dbc_nonce;
- struct dbc_set_uid dbc_set_uid;
- struct dbc_param dbc_param;
+ struct psp_request pa_req;
+ struct psp_ext_request ext_req;
};
void dbc_dev_destroy(struct psp_device *psp);
diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c
index d42d7bc62352..124a2e0c8999 100644
--- a/drivers/crypto/ccp/psp-dev.c
+++ b/drivers/crypto/ccp/psp-dev.c
@@ -9,6 +9,9 @@
#include <linux/kernel.h>
#include <linux/irqreturn.h>
+#include <linux/mutex.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
#include "sp-dev.h"
#include "psp-dev.h"
@@ -19,6 +22,86 @@
struct psp_device *psp_master;
+#define PSP_C2PMSG_17_CMDRESP_CMD GENMASK(19, 16)
+
+static int psp_mailbox_poll(const void __iomem *cmdresp_reg, unsigned int *cmdresp,
+ unsigned int timeout_msecs)
+{
+ while (true) {
+ *cmdresp = ioread32(cmdresp_reg);
+ if (FIELD_GET(PSP_CMDRESP_RESP, *cmdresp))
+ return 0;
+
+ if (!timeout_msecs--)
+ break;
+
+ usleep_range(1000, 1100);
+ }
+
+ return -ETIMEDOUT;
+}
+
+int psp_mailbox_command(struct psp_device *psp, enum psp_cmd cmd, void *cmdbuff,
+ unsigned int timeout_msecs, unsigned int *cmdresp)
+{
+ void __iomem *cmdresp_reg, *cmdbuff_lo_reg, *cmdbuff_hi_reg;
+ int ret;
+
+ if (!psp || !psp->vdata || !psp->vdata->cmdresp_reg ||
+ !psp->vdata->cmdbuff_addr_lo_reg || !psp->vdata->cmdbuff_addr_hi_reg)
+ return -ENODEV;
+
+ cmdresp_reg = psp->io_regs + psp->vdata->cmdresp_reg;
+ cmdbuff_lo_reg = psp->io_regs + psp->vdata->cmdbuff_addr_lo_reg;
+ cmdbuff_hi_reg = psp->io_regs + psp->vdata->cmdbuff_addr_hi_reg;
+
+ mutex_lock(&psp->mailbox_mutex);
+
+ /* Ensure mailbox is ready for a command */
+ ret = -EBUSY;
+ if (psp_mailbox_poll(cmdresp_reg, cmdresp, 0))
+ goto unlock;
+
+ if (cmdbuff) {
+ iowrite32(lower_32_bits(__psp_pa(cmdbuff)), cmdbuff_lo_reg);
+ iowrite32(upper_32_bits(__psp_pa(cmdbuff)), cmdbuff_hi_reg);
+ }
+
+ *cmdresp = FIELD_PREP(PSP_C2PMSG_17_CMDRESP_CMD, cmd);
+ iowrite32(*cmdresp, cmdresp_reg);
+
+ ret = psp_mailbox_poll(cmdresp_reg, cmdresp, timeout_msecs);
+
+unlock:
+ mutex_unlock(&psp->mailbox_mutex);
+
+ return ret;
+}
+
+int psp_extended_mailbox_cmd(struct psp_device *psp, unsigned int timeout_msecs,
+ struct psp_ext_request *req)
+{
+ unsigned int reg;
+ int ret;
+
+ print_hex_dump_debug("->psp ", DUMP_PREFIX_OFFSET, 16, 2, req,
+ req->header.payload_size, false);
+
+ ret = psp_mailbox_command(psp, PSP_CMD_TEE_EXTENDED_CMD, (void *)req,
+ timeout_msecs, &reg);
+ if (ret) {
+ return ret;
+ } else if (FIELD_GET(PSP_CMDRESP_STS, reg)) {
+ req->header.status = FIELD_GET(PSP_CMDRESP_STS, reg);
+ return -EIO;
+ }
+
+ print_hex_dump_debug("<-psp ", DUMP_PREFIX_OFFSET, 16, 2, req,
+ req->header.payload_size, false);
+
+ return 0;
+}
+
static struct psp_device *psp_alloc_struct(struct sp_device *sp)
{
struct device *dev = sp->dev;
@@ -74,7 +157,7 @@ static unsigned int psp_get_capability(struct psp_device *psp)
psp->capability = val;
/* Detect if TSME and SME are both enabled */
- if (psp->capability & PSP_CAPABILITY_PSP_SECURITY_REPORTING &&
+ if (PSP_CAPABILITY(psp, PSP_SECURITY_REPORTING) &&
psp->capability & (PSP_SECURITY_TSME_STATUS << PSP_CAPABILITY_PSP_SECURITY_OFFSET) &&
cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT))
dev_notice(psp->dev, "psp: Both TSME and SME are active, SME is unnecessary when TSME is active.\n");
@@ -85,7 +168,7 @@ static unsigned int psp_get_capability(struct psp_device *psp)
static int psp_check_sev_support(struct psp_device *psp)
{
/* Check if device supports SEV feature */
- if (!(psp->capability & PSP_CAPABILITY_SEV)) {
+ if (!PSP_CAPABILITY(psp, SEV)) {
dev_dbg(psp->dev, "psp does not support SEV\n");
return -ENODEV;
}
@@ -96,7 +179,7 @@ static int psp_check_sev_support(struct psp_device *psp)
static int psp_check_tee_support(struct psp_device *psp)
{
/* Check if device supports TEE feature */
- if (!(psp->capability & PSP_CAPABILITY_TEE)) {
+ if (!PSP_CAPABILITY(psp, TEE)) {
dev_dbg(psp->dev, "psp does not support TEE\n");
return -ENODEV;
}
@@ -104,23 +187,6 @@ static int psp_check_tee_support(struct psp_device *psp)
return 0;
}
-static void psp_init_platform_access(struct psp_device *psp)
-{
- int ret;
-
- ret = platform_access_dev_init(psp);
- if (ret) {
- dev_warn(psp->dev, "platform access init failed: %d\n", ret);
- return;
- }
-
- /* dbc must come after platform access as it tests the feature */
- ret = dbc_dev_init(psp);
- if (ret)
- dev_warn(psp->dev, "failed to init dynamic boost control: %d\n",
- ret);
-}
-
static int psp_init(struct psp_device *psp)
{
int ret;
@@ -137,8 +203,19 @@ static int psp_init(struct psp_device *psp)
return ret;
}
- if (psp->vdata->platform_access)
- psp_init_platform_access(psp);
+ if (psp->vdata->platform_access) {
+ ret = platform_access_dev_init(psp);
+ if (ret)
+ return ret;
+ }
+
+ /* dbc must come after platform access as it tests the feature */
+ if (PSP_FEATURE(psp, DBC) ||
+ PSP_CAPABILITY(psp, DBC_THRU_EXT)) {
+ ret = dbc_dev_init(psp);
+ if (ret)
+ return ret;
+ }
return 0;
}
@@ -164,6 +241,7 @@ int psp_dev_init(struct sp_device *sp)
}
psp->io_regs = sp->io_map;
+ mutex_init(&psp->mailbox_mutex);
ret = psp_get_capability(psp);
if (ret)
diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h
index 8a4de69399c5..ae582ba63729 100644
--- a/drivers/crypto/ccp/psp-dev.h
+++ b/drivers/crypto/ccp/psp-dev.h
@@ -14,6 +14,9 @@
#include <linux/list.h>
#include <linux/bits.h>
#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/psp.h>
+#include <linux/psp-platform-access.h>
#include "sp-dev.h"
@@ -33,6 +36,7 @@ struct psp_device {
struct sp_device *sp;
void __iomem *io_regs;
+ struct mutex mailbox_mutex;
psp_irq_handler_t sev_irq_handler;
void *sev_irq_data;
@@ -53,6 +57,7 @@ struct psp_device *psp_get_master_device(void);
#define PSP_CAPABILITY_SEV BIT(0)
#define PSP_CAPABILITY_TEE BIT(1)
+#define PSP_CAPABILITY_DBC_THRU_EXT BIT(2)
#define PSP_CAPABILITY_PSP_SECURITY_REPORTING BIT(7)
#define PSP_CAPABILITY_PSP_SECURITY_OFFSET 8
@@ -71,4 +76,54 @@ struct psp_device *psp_get_master_device(void);
#define PSP_SECURITY_HSP_TPM_AVAILABLE BIT(10)
#define PSP_SECURITY_ROM_ARMOR_ENFORCED BIT(11)
+/**
+ * enum psp_cmd - PSP mailbox commands
+ * @PSP_CMD_TEE_RING_INIT: Initialize TEE ring buffer
+ * @PSP_CMD_TEE_RING_DESTROY: Destroy TEE ring buffer
+ * @PSP_CMD_TEE_EXTENDED_CMD: Extended command
+ * @PSP_CMD_MAX: Maximum command id
+ */
+enum psp_cmd {
+ PSP_CMD_TEE_RING_INIT = 1,
+ PSP_CMD_TEE_RING_DESTROY = 2,
+ PSP_CMD_TEE_EXTENDED_CMD = 14,
+ PSP_CMD_MAX = 15,
+};
+
+int psp_mailbox_command(struct psp_device *psp, enum psp_cmd cmd, void *cmdbuff,
+ unsigned int timeout_msecs, unsigned int *cmdresp);
+
+/**
+ * struct psp_ext_req_buffer_hdr - Structure of the extended command header
+ * @payload_size: total payload size
+ * @sub_cmd_id: extended command ID
+ * @status: status of command execution (out)
+ */
+struct psp_ext_req_buffer_hdr {
+ u32 payload_size;
+ u32 sub_cmd_id;
+ u32 status;
+} __packed;
+
+struct psp_ext_request {
+ struct psp_ext_req_buffer_hdr header;
+ void *buf;
+} __packed;
+
+/**
+ * enum psp_sub_cmd - PSP mailbox sub commands
+ * @PSP_SUB_CMD_DBC_GET_NONCE: Get nonce from DBC
+ * @PSP_SUB_CMD_DBC_SET_UID: Set UID for DBC
+ * @PSP_SUB_CMD_DBC_GET_PARAMETER: Get parameter from DBC
+ * @PSP_SUB_CMD_DBC_SET_PARAMETER: Set parameter for DBC
+ */
+enum psp_sub_cmd {
+ PSP_SUB_CMD_DBC_GET_NONCE = PSP_DYNAMIC_BOOST_GET_NONCE,
+ PSP_SUB_CMD_DBC_SET_UID = PSP_DYNAMIC_BOOST_SET_UID,
+ PSP_SUB_CMD_DBC_GET_PARAMETER = PSP_DYNAMIC_BOOST_GET_PARAMETER,
+ PSP_SUB_CMD_DBC_SET_PARAMETER = PSP_DYNAMIC_BOOST_SET_PARAMETER,
+};
+
+int psp_extended_mailbox_cmd(struct psp_device *psp, unsigned int timeout_msecs,
+ struct psp_ext_request *req);
#endif /* __PSP_DEV_H */
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index f97166fba9d9..fcaccd0b5a65 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -309,6 +309,7 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
{
struct psp_device *psp = psp_master;
struct sev_device *sev;
+ unsigned int cmdbuff_hi, cmdbuff_lo;
unsigned int phys_lsb, phys_msb;
unsigned int reg, ret = 0;
int buf_len;
@@ -371,6 +372,19 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
if (FIELD_GET(PSP_CMDRESP_STS, reg)) {
dev_dbg(sev->dev, "sev command %#x failed (%#010lx)\n",
cmd, FIELD_GET(PSP_CMDRESP_STS, reg));
+
+ /*
+ * PSP firmware may report additional error information in the
+ * command buffer registers on error. Print contents of command
+ * buffer registers if they changed.
+ */
+ cmdbuff_hi = ioread32(sev->io_regs + sev->vdata->cmdbuff_addr_hi_reg);
+ cmdbuff_lo = ioread32(sev->io_regs + sev->vdata->cmdbuff_addr_lo_reg);
+ if (cmdbuff_hi != phys_msb || cmdbuff_lo != phys_lsb) {
+ dev_dbg(sev->dev, "Additional error information reported in cmdbuff:");
+ dev_dbg(sev->dev, " cmdbuff hi: %#010x\n", cmdbuff_hi);
+ dev_dbg(sev->dev, " cmdbuff lo: %#010x\n", cmdbuff_lo);
+ }
ret = -EIO;
} else {
ret = sev_write_init_ex_file_if_required(cmd);
diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h
index 2329ad524b49..03d5b9e04084 100644
--- a/drivers/crypto/ccp/sp-dev.h
+++ b/drivers/crypto/ccp/sp-dev.h
@@ -30,6 +30,7 @@
#define PLATFORM_FEATURE_DBC 0x1
+#define PSP_CAPABILITY(psp, cap) (psp->capability & PSP_CAPABILITY_##cap)
#define PSP_FEATURE(psp, feat) (psp->vdata && psp->vdata->platform_features & PLATFORM_FEATURE_##feat)
/* Structure to hold CCP device data */
@@ -71,6 +72,9 @@ struct psp_vdata {
const struct sev_vdata *sev;
const struct tee_vdata *tee;
const struct platform_access_vdata *platform_access;
+ const unsigned int cmdresp_reg;
+ const unsigned int cmdbuff_addr_lo_reg;
+ const unsigned int cmdbuff_addr_hi_reg;
const unsigned int feature_reg;
const unsigned int inten_reg;
const unsigned int intsts_reg;
diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
index b6ab56abeb68..300dda14182b 100644
--- a/drivers/crypto/ccp/sp-pci.c
+++ b/drivers/crypto/ccp/sp-pci.c
@@ -84,7 +84,7 @@ static umode_t psp_security_is_visible(struct kobject *kobj, struct attribute *a
struct sp_device *sp = dev_get_drvdata(dev);
struct psp_device *psp = sp->psp_data;
- if (psp && (psp->capability & PSP_CAPABILITY_PSP_SECURITY_REPORTING))
+ if (psp && PSP_CAPABILITY(psp, PSP_SECURITY_REPORTING))
return 0444;
return 0;
@@ -135,7 +135,7 @@ static umode_t psp_firmware_is_visible(struct kobject *kobj, struct attribute *a
val = ioread32(psp->io_regs + psp->vdata->bootloader_info_reg);
if (attr == &dev_attr_tee_version.attr &&
- psp->capability & PSP_CAPABILITY_TEE &&
+ PSP_CAPABILITY(psp, TEE) &&
psp->vdata->tee->info_reg)
val = ioread32(psp->io_regs + psp->vdata->tee->info_reg);
@@ -418,18 +418,12 @@ static const struct sev_vdata sevv2 = {
};
static const struct tee_vdata teev1 = {
- .cmdresp_reg = 0x10544, /* C2PMSG_17 */
- .cmdbuff_addr_lo_reg = 0x10548, /* C2PMSG_18 */
- .cmdbuff_addr_hi_reg = 0x1054c, /* C2PMSG_19 */
.ring_wptr_reg = 0x10550, /* C2PMSG_20 */
.ring_rptr_reg = 0x10554, /* C2PMSG_21 */
.info_reg = 0x109e8, /* C2PMSG_58 */
};
static const struct tee_vdata teev2 = {
- .cmdresp_reg = 0x10944, /* C2PMSG_17 */
- .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */
- .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */
.ring_wptr_reg = 0x10950, /* C2PMSG_20 */
.ring_rptr_reg = 0x10954, /* C2PMSG_21 */
};
@@ -466,6 +460,9 @@ static const struct psp_vdata pspv2 = {
static const struct psp_vdata pspv3 = {
.tee = &teev1,
.platform_access = &pa_v1,
+ .cmdresp_reg = 0x10544, /* C2PMSG_17 */
+ .cmdbuff_addr_lo_reg = 0x10548, /* C2PMSG_18 */
+ .cmdbuff_addr_hi_reg = 0x1054c, /* C2PMSG_19 */
.bootloader_info_reg = 0x109ec, /* C2PMSG_59 */
.feature_reg = 0x109fc, /* C2PMSG_63 */
.inten_reg = 0x10690, /* P2CMSG_INTEN */
@@ -476,6 +473,9 @@ static const struct psp_vdata pspv3 = {
static const struct psp_vdata pspv4 = {
.sev = &sevv2,
.tee = &teev1,
+ .cmdresp_reg = 0x10544, /* C2PMSG_17 */
+ .cmdbuff_addr_lo_reg = 0x10548, /* C2PMSG_18 */
+ .cmdbuff_addr_hi_reg = 0x1054c, /* C2PMSG_19 */
.bootloader_info_reg = 0x109ec, /* C2PMSG_59 */
.feature_reg = 0x109fc, /* C2PMSG_63 */
.inten_reg = 0x10690, /* P2CMSG_INTEN */
@@ -485,6 +485,9 @@ static const struct psp_vdata pspv4 = {
static const struct psp_vdata pspv5 = {
.tee = &teev2,
.platform_access = &pa_v2,
+ .cmdresp_reg = 0x10944, /* C2PMSG_17 */
+ .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */
+ .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */
.feature_reg = 0x109fc, /* C2PMSG_63 */
.inten_reg = 0x10510, /* P2CMSG_INTEN */
.intsts_reg = 0x10514, /* P2CMSG_INTSTS */
@@ -493,6 +496,9 @@ static const struct psp_vdata pspv5 = {
static const struct psp_vdata pspv6 = {
.sev = &sevv2,
.tee = &teev2,
+ .cmdresp_reg = 0x10944, /* C2PMSG_17 */
+ .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */
+ .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */
.feature_reg = 0x109fc, /* C2PMSG_63 */
.inten_reg = 0x10510, /* P2CMSG_INTEN */
.intsts_reg = 0x10514, /* P2CMSG_INTSTS */
diff --git a/drivers/crypto/ccp/sp-platform.c b/drivers/crypto/ccp/sp-platform.c
index 7d79a8744f9a..473301237760 100644
--- a/drivers/crypto/ccp/sp-platform.c
+++ b/drivers/crypto/ccp/sp-platform.c
@@ -180,7 +180,7 @@ e_err:
return ret;
}
-static int sp_platform_remove(struct platform_device *pdev)
+static void sp_platform_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct sp_device *sp = dev_get_drvdata(dev);
@@ -188,8 +188,6 @@ static int sp_platform_remove(struct platform_device *pdev)
sp_destroy(sp);
dev_notice(dev, "disabled\n");
-
- return 0;
}
#ifdef CONFIG_PM
@@ -222,7 +220,7 @@ static struct platform_driver sp_platform_driver = {
#endif
},
.probe = sp_platform_probe,
- .remove = sp_platform_remove,
+ .remove_new = sp_platform_remove,
#ifdef CONFIG_PM
.suspend = sp_platform_suspend,
.resume = sp_platform_resume,
diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c
index 5560bf8329a1..5e1d80724678 100644
--- a/drivers/crypto/ccp/tee-dev.c
+++ b/drivers/crypto/ccp/tee-dev.c
@@ -62,26 +62,6 @@ static void tee_free_ring(struct psp_tee_device *tee)
mutex_destroy(&rb_mgr->mutex);
}
-static int tee_wait_cmd_poll(struct psp_tee_device *tee, unsigned int timeout,
- unsigned int *reg)
-{
- /* ~10ms sleep per loop => nloop = timeout * 100 */
- int nloop = timeout * 100;
-
- while (--nloop) {
- *reg = ioread32(tee->io_regs + tee->vdata->cmdresp_reg);
- if (FIELD_GET(PSP_CMDRESP_RESP, *reg))
- return 0;
-
- usleep_range(10000, 10100);
- }
-
- dev_err(tee->dev, "tee: command timed out, disabling PSP\n");
- psp_dead = true;
-
- return -ETIMEDOUT;
-}
-
static
struct tee_init_ring_cmd *tee_alloc_cmd_buffer(struct psp_tee_device *tee)
{
@@ -110,7 +90,6 @@ static int tee_init_ring(struct psp_tee_device *tee)
{
int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd);
struct tee_init_ring_cmd *cmd;
- phys_addr_t cmd_buffer;
unsigned int reg;
int ret;
@@ -130,23 +109,15 @@ static int tee_init_ring(struct psp_tee_device *tee)
return -ENOMEM;
}
- cmd_buffer = __psp_pa((void *)cmd);
-
/* Send command buffer details to Trusted OS by writing to
* CPU-PSP message registers
*/
-
- iowrite32(lower_32_bits(cmd_buffer),
- tee->io_regs + tee->vdata->cmdbuff_addr_lo_reg);
- iowrite32(upper_32_bits(cmd_buffer),
- tee->io_regs + tee->vdata->cmdbuff_addr_hi_reg);
- iowrite32(TEE_RING_INIT_CMD,
- tee->io_regs + tee->vdata->cmdresp_reg);
-
- ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, &reg);
+ ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_INIT, cmd,
+ TEE_DEFAULT_CMD_TIMEOUT, &reg);
if (ret) {
- dev_err(tee->dev, "tee: ring init command timed out\n");
+ dev_err(tee->dev, "tee: ring init command timed out, disabling TEE support\n");
tee_free_ring(tee);
+ psp_dead = true;
goto free_buf;
}
@@ -174,12 +145,11 @@ static void tee_destroy_ring(struct psp_tee_device *tee)
if (psp_dead)
goto free_ring;
- iowrite32(TEE_RING_DESTROY_CMD,
- tee->io_regs + tee->vdata->cmdresp_reg);
-
- ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, &reg);
+ ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_DESTROY, NULL,
+ TEE_DEFAULT_CMD_TIMEOUT, &reg);
if (ret) {
- dev_err(tee->dev, "tee: ring destroy command timed out\n");
+ dev_err(tee->dev, "tee: ring destroy command timed out, disabling TEE support\n");
+ psp_dead = true;
} else if (FIELD_GET(PSP_CMDRESP_STS, reg)) {
dev_err(tee->dev, "tee: ring destroy command failed (%#010lx)\n",
FIELD_GET(PSP_CMDRESP_STS, reg));
@@ -370,7 +340,7 @@ int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf, size_t len,
if (ret)
return ret;
- ret = tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_TIMEOUT);
+ ret = tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_RING_TIMEOUT);
if (ret) {
resp->flag = CMD_RESPONSE_TIMEDOUT;
return ret;
diff --git a/drivers/crypto/ccp/tee-dev.h b/drivers/crypto/ccp/tee-dev.h
index 49d26158b71e..ea9a2b7c05f5 100644
--- a/drivers/crypto/ccp/tee-dev.h
+++ b/drivers/crypto/ccp/tee-dev.h
@@ -17,22 +17,11 @@
#include <linux/device.h>
#include <linux/mutex.h>
-#define TEE_DEFAULT_TIMEOUT 10
+#define TEE_DEFAULT_CMD_TIMEOUT (10 * MSEC_PER_SEC)
+#define TEE_DEFAULT_RING_TIMEOUT 10
#define MAX_BUFFER_SIZE 988
/**
- * enum tee_ring_cmd_id - TEE interface commands for ring buffer configuration
- * @TEE_RING_INIT_CMD: Initialize ring buffer
- * @TEE_RING_DESTROY_CMD: Destroy ring buffer
- * @TEE_RING_MAX_CMD: Maximum command id
- */
-enum tee_ring_cmd_id {
- TEE_RING_INIT_CMD = 0x00010000,
- TEE_RING_DESTROY_CMD = 0x00020000,
- TEE_RING_MAX_CMD = 0x000F0000,
-};
-
-/**
* struct tee_init_ring_cmd - Command to init TEE ring buffer
* @low_addr: bits [31:0] of the physical address of ring buffer
* @hi_addr: bits [63:32] of the physical address of ring buffer
diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c
index 0f0694037dd7..9177b54bb0f5 100644
--- a/drivers/crypto/ccree/cc_driver.c
+++ b/drivers/crypto/ccree/cc_driver.c
@@ -623,7 +623,7 @@ static int ccree_probe(struct platform_device *plat_dev)
return 0;
}
-static int ccree_remove(struct platform_device *plat_dev)
+static void ccree_remove(struct platform_device *plat_dev)
{
struct device *dev = &plat_dev->dev;
@@ -632,8 +632,6 @@ static int ccree_remove(struct platform_device *plat_dev)
cleanup_cc_resources(plat_dev);
dev_info(dev, "ARM ccree device terminated\n");
-
- return 0;
}
static struct platform_driver ccree_driver = {
@@ -645,7 +643,7 @@ static struct platform_driver ccree_driver = {
#endif
},
.probe = ccree_probe,
- .remove = ccree_remove,
+ .remove_new = ccree_remove,
};
static int __init ccree_init(void)
diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c
index 16298ae4a00b..177428480c7d 100644
--- a/drivers/crypto/chelsio/chcr_algo.c
+++ b/drivers/crypto/chelsio/chcr_algo.c
@@ -1920,6 +1920,9 @@ err:
return error;
}
+static int chcr_hmac_init(struct ahash_request *areq);
+static int chcr_sha_init(struct ahash_request *areq);
+
static int chcr_ahash_digest(struct ahash_request *req)
{
struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
@@ -1938,7 +1941,11 @@ static int chcr_ahash_digest(struct ahash_request *req)
req_ctx->rxqidx = cpu % ctx->nrxq;
put_cpu();
- rtfm->init(req);
+ if (is_hmac(crypto_ahash_tfm(rtfm)))
+ chcr_hmac_init(req);
+ else
+ chcr_sha_init(req);
+
bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm));
error = chcr_inc_wrcount(dev);
if (error)
diff --git a/drivers/crypto/exynos-rng.c b/drivers/crypto/exynos-rng.c
index 5d60a4bcb511..0dd8baf16cb4 100644
--- a/drivers/crypto/exynos-rng.c
+++ b/drivers/crypto/exynos-rng.c
@@ -306,13 +306,11 @@ static int exynos_rng_probe(struct platform_device *pdev)
return ret;
}
-static int exynos_rng_remove(struct platform_device *pdev)
+static void exynos_rng_remove(struct platform_device *pdev)
{
crypto_unregister_rng(&exynos_rng_alg);
exynos_rng_dev = NULL;
-
- return 0;
}
static int __maybe_unused exynos_rng_suspend(struct device *dev)
@@ -391,7 +389,7 @@ static struct platform_driver exynos_rng_driver = {
.of_match_table = exynos_rng_dt_match,
},
.probe = exynos_rng_probe,
- .remove = exynos_rng_remove,
+ .remove_new = exynos_rng_remove,
};
module_platform_driver(exynos_rng_driver);
diff --git a/drivers/crypto/gemini/sl3516-ce-core.c b/drivers/crypto/gemini/sl3516-ce-core.c
index 0f43c6e39bb9..1d1a889599bb 100644
--- a/drivers/crypto/gemini/sl3516-ce-core.c
+++ b/drivers/crypto/gemini/sl3516-ce-core.c
@@ -505,7 +505,7 @@ error_pm:
return err;
}
-static int sl3516_ce_remove(struct platform_device *pdev)
+static void sl3516_ce_remove(struct platform_device *pdev)
{
struct sl3516_ce_dev *ce = platform_get_drvdata(pdev);
@@ -518,8 +518,6 @@ static int sl3516_ce_remove(struct platform_device *pdev)
#ifdef CONFIG_CRYPTO_DEV_SL3516_DEBUG
debugfs_remove_recursive(ce->dbgfs_dir);
#endif
-
- return 0;
}
static const struct of_device_id sl3516_ce_crypto_of_match_table[] = {
@@ -530,7 +528,7 @@ MODULE_DEVICE_TABLE(of, sl3516_ce_crypto_of_match_table);
static struct platform_driver sl3516_ce_driver = {
.probe = sl3516_ce_probe,
- .remove = sl3516_ce_remove,
+ .remove_new = sl3516_ce_remove,
.driver = {
.name = "sl3516-crypto",
.pm = &sl3516_ce_pm_ops,
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index 8e4a49b7ab4f..7bddc3c786c1 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -2393,9 +2393,13 @@ static int hifn_alg_alloc(struct hifn_device *dev, const struct hifn_alg_templat
alg->alg = t->skcipher;
alg->alg.init = hifn_init_tfm;
- snprintf(alg->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", t->name);
- snprintf(alg->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s-%s",
- t->drv_name, dev->name);
+ err = -EINVAL;
+ if (snprintf(alg->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
+ "%s", t->name) >= CRYPTO_MAX_ALG_NAME)
+ goto out_free_alg;
+ if (snprintf(alg->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "%s-%s", t->drv_name, dev->name) >= CRYPTO_MAX_ALG_NAME)
+ goto out_free_alg;
alg->alg.base.cra_priority = 300;
alg->alg.base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC;
@@ -2411,6 +2415,7 @@ static int hifn_alg_alloc(struct hifn_device *dev, const struct hifn_alg_templat
err = crypto_register_skcipher(&alg->alg);
if (err) {
list_del(&alg->entry);
+out_free_alg:
kfree(alg);
}
diff --git a/drivers/crypto/hisilicon/debugfs.c b/drivers/crypto/hisilicon/debugfs.c
index 2cc1591949db..7e8186fe0512 100644
--- a/drivers/crypto/hisilicon/debugfs.c
+++ b/drivers/crypto/hisilicon/debugfs.c
@@ -137,8 +137,8 @@ static void dump_show(struct hisi_qm *qm, void *info,
static int qm_sqc_dump(struct hisi_qm *qm, char *s, char *name)
{
struct device *dev = &qm->pdev->dev;
- struct qm_sqc *sqc, *sqc_curr;
- dma_addr_t sqc_dma;
+ struct qm_sqc *sqc_curr;
+ struct qm_sqc sqc;
u32 qp_id;
int ret;
@@ -151,35 +151,29 @@ static int qm_sqc_dump(struct hisi_qm *qm, char *s, char *name)
return -EINVAL;
}
- sqc = hisi_qm_ctx_alloc(qm, sizeof(*sqc), &sqc_dma);
- if (IS_ERR(sqc))
- return PTR_ERR(sqc);
+ ret = qm_set_and_get_xqc(qm, QM_MB_CMD_SQC, &sqc, qp_id, 1);
+ if (!ret) {
+ dump_show(qm, &sqc, sizeof(struct qm_sqc), name);
- ret = hisi_qm_mb(qm, QM_MB_CMD_SQC, sqc_dma, qp_id, 1);
- if (ret) {
- down_read(&qm->qps_lock);
- if (qm->sqc) {
- sqc_curr = qm->sqc + qp_id;
+ return 0;
+ }
- dump_show(qm, sqc_curr, sizeof(*sqc), "SOFT SQC");
- }
- up_read(&qm->qps_lock);
+ down_read(&qm->qps_lock);
+ if (qm->sqc) {
+ sqc_curr = qm->sqc + qp_id;
- goto free_ctx;
+ dump_show(qm, sqc_curr, sizeof(*sqc_curr), "SOFT SQC");
}
+ up_read(&qm->qps_lock);
- dump_show(qm, sqc, sizeof(*sqc), name);
-
-free_ctx:
- hisi_qm_ctx_free(qm, sizeof(*sqc), sqc, &sqc_dma);
return 0;
}
static int qm_cqc_dump(struct hisi_qm *qm, char *s, char *name)
{
struct device *dev = &qm->pdev->dev;
- struct qm_cqc *cqc, *cqc_curr;
- dma_addr_t cqc_dma;
+ struct qm_cqc *cqc_curr;
+ struct qm_cqc cqc;
u32 qp_id;
int ret;
@@ -192,34 +186,29 @@ static int qm_cqc_dump(struct hisi_qm *qm, char *s, char *name)
return -EINVAL;
}
- cqc = hisi_qm_ctx_alloc(qm, sizeof(*cqc), &cqc_dma);
- if (IS_ERR(cqc))
- return PTR_ERR(cqc);
+ ret = qm_set_and_get_xqc(qm, QM_MB_CMD_CQC, &cqc, qp_id, 1);
+ if (!ret) {
+ dump_show(qm, &cqc, sizeof(struct qm_cqc), name);
- ret = hisi_qm_mb(qm, QM_MB_CMD_CQC, cqc_dma, qp_id, 1);
- if (ret) {
- down_read(&qm->qps_lock);
- if (qm->cqc) {
- cqc_curr = qm->cqc + qp_id;
+ return 0;
+ }
- dump_show(qm, cqc_curr, sizeof(*cqc), "SOFT CQC");
- }
- up_read(&qm->qps_lock);
+ down_read(&qm->qps_lock);
+ if (qm->cqc) {
+ cqc_curr = qm->cqc + qp_id;
- goto free_ctx;
+ dump_show(qm, cqc_curr, sizeof(*cqc_curr), "SOFT CQC");
}
+ up_read(&qm->qps_lock);
- dump_show(qm, cqc, sizeof(*cqc), name);
-
-free_ctx:
- hisi_qm_ctx_free(qm, sizeof(*cqc), cqc, &cqc_dma);
return 0;
}
static int qm_eqc_aeqc_dump(struct hisi_qm *qm, char *s, char *name)
{
struct device *dev = &qm->pdev->dev;
- dma_addr_t xeqc_dma;
+ struct qm_aeqc aeqc;
+ struct qm_eqc eqc;
size_t size;
void *xeqc;
int ret;
@@ -233,23 +222,19 @@ static int qm_eqc_aeqc_dump(struct hisi_qm *qm, char *s, char *name)
if (!strcmp(name, "EQC")) {
cmd = QM_MB_CMD_EQC;
size = sizeof(struct qm_eqc);
+ xeqc = &eqc;
} else {
cmd = QM_MB_CMD_AEQC;
size = sizeof(struct qm_aeqc);
+ xeqc = &aeqc;
}
- xeqc = hisi_qm_ctx_alloc(qm, size, &xeqc_dma);
- if (IS_ERR(xeqc))
- return PTR_ERR(xeqc);
-
- ret = hisi_qm_mb(qm, cmd, xeqc_dma, 0, 1);
+ ret = qm_set_and_get_xqc(qm, cmd, xeqc, 0, 1);
if (ret)
- goto err_free_ctx;
+ return ret;
dump_show(qm, xeqc, size, name);
-err_free_ctx:
- hisi_qm_ctx_free(qm, size, xeqc, &xeqc_dma);
return ret;
}
diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
index 9a1c61be32cc..764532a6ca82 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
@@ -57,6 +57,9 @@ struct hpre_ctx;
#define HPRE_DRV_ECDH_MASK_CAP BIT(2)
#define HPRE_DRV_X25519_MASK_CAP BIT(5)
+static DEFINE_MUTEX(hpre_algs_lock);
+static unsigned int hpre_available_devs;
+
typedef void (*hpre_cb)(struct hpre_ctx *ctx, void *sqe);
struct hpre_rsa_ctx {
@@ -2202,11 +2205,17 @@ static void hpre_unregister_x25519(struct hisi_qm *qm)
int hpre_algs_register(struct hisi_qm *qm)
{
- int ret;
+ int ret = 0;
+
+ mutex_lock(&hpre_algs_lock);
+ if (hpre_available_devs) {
+ hpre_available_devs++;
+ goto unlock;
+ }
ret = hpre_register_rsa(qm);
if (ret)
- return ret;
+ goto unlock;
ret = hpre_register_dh(qm);
if (ret)
@@ -2220,6 +2229,9 @@ int hpre_algs_register(struct hisi_qm *qm)
if (ret)
goto unreg_ecdh;
+ hpre_available_devs++;
+ mutex_unlock(&hpre_algs_lock);
+
return ret;
unreg_ecdh:
@@ -2228,13 +2240,22 @@ unreg_dh:
hpre_unregister_dh(qm);
unreg_rsa:
hpre_unregister_rsa(qm);
+unlock:
+ mutex_unlock(&hpre_algs_lock);
return ret;
}
void hpre_algs_unregister(struct hisi_qm *qm)
{
+ mutex_lock(&hpre_algs_lock);
+ if (--hpre_available_devs)
+ goto unlock;
+
hpre_unregister_x25519(qm);
hpre_unregister_ecdh(qm);
hpre_unregister_dh(qm);
hpre_unregister_rsa(qm);
+
+unlock:
+ mutex_unlock(&hpre_algs_lock);
}
diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c
index 39297ce70f44..56777099ef69 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_main.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_main.c
@@ -107,6 +107,7 @@
#define HPRE_VIA_MSI_DSM 1
#define HPRE_SQE_MASK_OFFSET 8
#define HPRE_SQE_MASK_LEN 24
+#define HPRE_CTX_Q_NUM_DEF 1
#define HPRE_DFX_BASE 0x301000
#define HPRE_DFX_COMMON1 0x301400
@@ -433,8 +434,11 @@ static u32 uacce_mode = UACCE_MODE_NOUACCE;
module_param_cb(uacce_mode, &hpre_uacce_mode_ops, &uacce_mode, 0444);
MODULE_PARM_DESC(uacce_mode, UACCE_MODE_DESC);
+static bool pf_q_num_flag;
static int pf_q_num_set(const char *val, const struct kernel_param *kp)
{
+ pf_q_num_flag = true;
+
return q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_HPRE_PF);
}
@@ -1033,7 +1037,7 @@ static int hpre_cluster_debugfs_init(struct hisi_qm *qm)
for (i = 0; i < clusters_num; i++) {
ret = snprintf(buf, HPRE_DBGFS_VAL_MAX_LEN, "cluster%d", i);
- if (ret < 0)
+ if (ret >= HPRE_DBGFS_VAL_MAX_LEN)
return -EINVAL;
tmp_d = debugfs_create_dir(buf, qm->debug.debug_root);
@@ -1157,6 +1161,8 @@ static int hpre_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
qm->qp_num = pf_q_num;
qm->debug.curr_qm_qp_num = pf_q_num;
qm->qm_list = &hpre_devices;
+ if (pf_q_num_flag)
+ set_bit(QM_MODULE_PARAM, &qm->misc_ctl);
}
ret = hisi_qm_init(qm);
@@ -1394,10 +1400,11 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
dev_warn(&pdev->dev, "init debugfs fail!\n");
- ret = hisi_qm_alg_register(qm, &hpre_devices);
+ hisi_qm_add_list(qm, &hpre_devices);
+ ret = hisi_qm_alg_register(qm, &hpre_devices, HPRE_CTX_Q_NUM_DEF);
if (ret < 0) {
pci_err(pdev, "fail to register algs to crypto!\n");
- goto err_with_qm_start;
+ goto err_qm_del_list;
}
if (qm->uacce) {
@@ -1419,9 +1426,10 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
err_with_alg_register:
- hisi_qm_alg_unregister(qm, &hpre_devices);
+ hisi_qm_alg_unregister(qm, &hpre_devices, HPRE_CTX_Q_NUM_DEF);
-err_with_qm_start:
+err_qm_del_list:
+ hisi_qm_del_list(qm, &hpre_devices);
hpre_debugfs_exit(qm);
hisi_qm_stop(qm, QM_NORMAL);
@@ -1441,7 +1449,8 @@ static void hpre_remove(struct pci_dev *pdev)
hisi_qm_pm_uninit(qm);
hisi_qm_wait_task_finish(qm, &hpre_devices);
- hisi_qm_alg_unregister(qm, &hpre_devices);
+ hisi_qm_alg_unregister(qm, &hpre_devices, HPRE_CTX_Q_NUM_DEF);
+ hisi_qm_del_list(qm, &hpre_devices);
if (qm->fun_type == QM_HW_PF && qm->vfs_num)
hisi_qm_sriov_disable(pdev, true);
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
index a99fd589445c..18599f3634c3 100644
--- a/drivers/crypto/hisilicon/qm.c
+++ b/drivers/crypto/hisilicon/qm.c
@@ -46,7 +46,7 @@
#define QM_QC_PASID_ENABLE_SHIFT 7
#define QM_SQ_TYPE_MASK GENMASK(3, 0)
-#define QM_SQ_TAIL_IDX(sqc) ((le16_to_cpu((sqc)->w11) >> 6) & 0x1)
+#define QM_SQ_TAIL_IDX(sqc) ((le16_to_cpu((sqc).w11) >> 6) & 0x1)
/* cqc shift */
#define QM_CQ_HOP_NUM_SHIFT 0
@@ -58,7 +58,7 @@
#define QM_CQE_PHASE(cqe) (le16_to_cpu((cqe)->w7) & 0x1)
#define QM_QC_CQE_SIZE 4
-#define QM_CQ_TAIL_IDX(cqc) ((le16_to_cpu((cqc)->w11) >> 6) & 0x1)
+#define QM_CQ_TAIL_IDX(cqc) ((le16_to_cpu((cqc).w11) >> 6) & 0x1)
/* eqc shift */
#define QM_EQE_AEQE_SIZE (2UL << 12)
@@ -69,6 +69,7 @@
#define QM_AEQE_PHASE(aeqe) ((le32_to_cpu((aeqe)->dw0) >> 16) & 0x1)
#define QM_AEQE_TYPE_SHIFT 17
+#define QM_AEQE_TYPE_MASK 0xf
#define QM_AEQE_CQN_MASK GENMASK(15, 0)
#define QM_CQ_OVERFLOW 0
#define QM_EQ_OVERFLOW 1
@@ -206,8 +207,6 @@
#define WAIT_PERIOD 20
#define REMOVE_WAIT_DELAY 10
-#define QM_DRIVER_REMOVING 0
-#define QM_RST_SCHED 1
#define QM_QOS_PARAM_NUM 2
#define QM_QOS_MAX_VAL 1000
#define QM_QOS_RATE 100
@@ -253,19 +252,6 @@
#define QM_MK_SQC_DW3_V2(sqe_sz, sq_depth) \
((((u32)sq_depth) - 1) | ((u32)ilog2(sqe_sz) << QM_SQ_SQE_SIZE_SHIFT))
-#define INIT_QC_COMMON(qc, base, pasid) do { \
- (qc)->head = 0; \
- (qc)->tail = 0; \
- (qc)->base_l = cpu_to_le32(lower_32_bits(base)); \
- (qc)->base_h = cpu_to_le32(upper_32_bits(base)); \
- (qc)->dw3 = 0; \
- (qc)->w8 = 0; \
- (qc)->rsvd0 = 0; \
- (qc)->pasid = cpu_to_le16(pasid); \
- (qc)->w11 = 0; \
- (qc)->rsvd1 = 0; \
-} while (0)
-
enum vft_type {
SQC_VFT = 0,
CQC_VFT,
@@ -687,6 +673,59 @@ int hisi_qm_mb(struct hisi_qm *qm, u8 cmd, dma_addr_t dma_addr, u16 queue,
}
EXPORT_SYMBOL_GPL(hisi_qm_mb);
+/* op 0: set xqc information to hardware, 1: get xqc information from hardware. */
+int qm_set_and_get_xqc(struct hisi_qm *qm, u8 cmd, void *xqc, u32 qp_id, bool op)
+{
+ struct hisi_qm *pf_qm = pci_get_drvdata(pci_physfn(qm->pdev));
+ struct qm_mailbox mailbox;
+ dma_addr_t xqc_dma;
+ void *tmp_xqc;
+ size_t size;
+ int ret;
+
+ switch (cmd) {
+ case QM_MB_CMD_SQC:
+ size = sizeof(struct qm_sqc);
+ tmp_xqc = qm->xqc_buf.sqc;
+ xqc_dma = qm->xqc_buf.sqc_dma;
+ break;
+ case QM_MB_CMD_CQC:
+ size = sizeof(struct qm_cqc);
+ tmp_xqc = qm->xqc_buf.cqc;
+ xqc_dma = qm->xqc_buf.cqc_dma;
+ break;
+ case QM_MB_CMD_EQC:
+ size = sizeof(struct qm_eqc);
+ tmp_xqc = qm->xqc_buf.eqc;
+ xqc_dma = qm->xqc_buf.eqc_dma;
+ break;
+ case QM_MB_CMD_AEQC:
+ size = sizeof(struct qm_aeqc);
+ tmp_xqc = qm->xqc_buf.aeqc;
+ xqc_dma = qm->xqc_buf.aeqc_dma;
+ break;
+ }
+
+ /* Setting xqc will fail if master OOO is blocked. */
+ if (qm_check_dev_error(pf_qm)) {
+ dev_err(&qm->pdev->dev, "failed to send mailbox since qm is stop!\n");
+ return -EIO;
+ }
+
+ mutex_lock(&qm->mailbox_lock);
+ if (!op)
+ memcpy(tmp_xqc, xqc, size);
+
+ qm_mb_pre_init(&mailbox, cmd, xqc_dma, qp_id, op);
+ ret = qm_mb_nolock(qm, &mailbox);
+ if (!ret && op)
+ memcpy(xqc, tmp_xqc, size);
+
+ mutex_unlock(&qm->mailbox_lock);
+
+ return ret;
+}
+
static void qm_db_v1(struct hisi_qm *qm, u16 qn, u8 cmd, u16 index, u8 priority)
{
u64 doorbell;
@@ -849,53 +888,23 @@ static void qm_poll_req_cb(struct hisi_qp *qp)
qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_CQ,
qp->qp_status.cq_head, 0);
atomic_dec(&qp->qp_status.used);
+
+ cond_resched();
}
/* set c_flag */
qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_CQ, qp->qp_status.cq_head, 1);
}
-static int qm_get_complete_eqe_num(struct hisi_qm_poll_data *poll_data)
-{
- struct hisi_qm *qm = poll_data->qm;
- struct qm_eqe *eqe = qm->eqe + qm->status.eq_head;
- u16 eq_depth = qm->eq_depth;
- int eqe_num = 0;
- u16 cqn;
-
- while (QM_EQE_PHASE(eqe) == qm->status.eqc_phase) {
- cqn = le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK;
- poll_data->qp_finish_id[eqe_num] = cqn;
- eqe_num++;
-
- if (qm->status.eq_head == eq_depth - 1) {
- qm->status.eqc_phase = !qm->status.eqc_phase;
- eqe = qm->eqe;
- qm->status.eq_head = 0;
- } else {
- eqe++;
- qm->status.eq_head++;
- }
-
- if (eqe_num == (eq_depth >> 1) - 1)
- break;
- }
-
- qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0);
-
- return eqe_num;
-}
-
static void qm_work_process(struct work_struct *work)
{
struct hisi_qm_poll_data *poll_data =
container_of(work, struct hisi_qm_poll_data, work);
struct hisi_qm *qm = poll_data->qm;
+ u16 eqe_num = poll_data->eqe_num;
struct hisi_qp *qp;
- int eqe_num, i;
+ int i;
- /* Get qp id of completed tasks and re-enable the interrupt. */
- eqe_num = qm_get_complete_eqe_num(poll_data);
for (i = eqe_num - 1; i >= 0; i--) {
qp = &qm->qp_array[poll_data->qp_finish_id[i]];
if (unlikely(atomic_read(&qp->qp_status.flags) == QP_STOP))
@@ -911,39 +920,55 @@ static void qm_work_process(struct work_struct *work)
}
}
-static bool do_qm_eq_irq(struct hisi_qm *qm)
+static void qm_get_complete_eqe_num(struct hisi_qm *qm)
{
struct qm_eqe *eqe = qm->eqe + qm->status.eq_head;
- struct hisi_qm_poll_data *poll_data;
- u16 cqn;
+ struct hisi_qm_poll_data *poll_data = NULL;
+ u16 eq_depth = qm->eq_depth;
+ u16 cqn, eqe_num = 0;
- if (!readl(qm->io_base + QM_VF_EQ_INT_SOURCE))
- return false;
+ if (QM_EQE_PHASE(eqe) != qm->status.eqc_phase) {
+ atomic64_inc(&qm->debug.dfx.err_irq_cnt);
+ qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0);
+ return;
+ }
- if (QM_EQE_PHASE(eqe) == qm->status.eqc_phase) {
+ cqn = le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK;
+ if (unlikely(cqn >= qm->qp_num))
+ return;
+ poll_data = &qm->poll_data[cqn];
+
+ while (QM_EQE_PHASE(eqe) == qm->status.eqc_phase) {
cqn = le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK;
- poll_data = &qm->poll_data[cqn];
- queue_work(qm->wq, &poll_data->work);
+ poll_data->qp_finish_id[eqe_num] = cqn;
+ eqe_num++;
+
+ if (qm->status.eq_head == eq_depth - 1) {
+ qm->status.eqc_phase = !qm->status.eqc_phase;
+ eqe = qm->eqe;
+ qm->status.eq_head = 0;
+ } else {
+ eqe++;
+ qm->status.eq_head++;
+ }
- return true;
+ if (eqe_num == (eq_depth >> 1) - 1)
+ break;
}
- return false;
+ poll_data->eqe_num = eqe_num;
+ queue_work(qm->wq, &poll_data->work);
+ qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0);
}
static irqreturn_t qm_eq_irq(int irq, void *data)
{
struct hisi_qm *qm = data;
- bool ret;
-
- ret = do_qm_eq_irq(qm);
- if (ret)
- return IRQ_HANDLED;
- atomic64_inc(&qm->debug.dfx.err_irq_cnt);
- qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0);
+ /* Get qp id of completed tasks and re-enable the interrupt */
+ qm_get_complete_eqe_num(qm);
- return IRQ_NONE;
+ return IRQ_HANDLED;
}
static irqreturn_t qm_mb_cmd_irq(int irq, void *data)
@@ -1025,8 +1050,11 @@ static irqreturn_t qm_aeq_thread(int irq, void *data)
u16 aeq_depth = qm->aeq_depth;
u32 type, qp_id;
+ atomic64_inc(&qm->debug.dfx.aeq_irq_cnt);
+
while (QM_AEQE_PHASE(aeqe) == qm->status.aeqc_phase) {
- type = le32_to_cpu(aeqe->dw0) >> QM_AEQE_TYPE_SHIFT;
+ type = (le32_to_cpu(aeqe->dw0) >> QM_AEQE_TYPE_SHIFT) &
+ QM_AEQE_TYPE_MASK;
qp_id = le32_to_cpu(aeqe->dw0) & QM_AEQE_CQN_MASK;
switch (type) {
@@ -1062,17 +1090,6 @@ static irqreturn_t qm_aeq_thread(int irq, void *data)
return IRQ_HANDLED;
}
-static irqreturn_t qm_aeq_irq(int irq, void *data)
-{
- struct hisi_qm *qm = data;
-
- atomic64_inc(&qm->debug.dfx.aeq_irq_cnt);
- if (!readl(qm->io_base + QM_VF_AEQ_INT_SOURCE))
- return IRQ_NONE;
-
- return IRQ_WAKE_THREAD;
-}
-
static void qm_init_qp_status(struct hisi_qp *qp)
{
struct hisi_qp_status *qp_status = &qp->qp_status;
@@ -1321,45 +1338,6 @@ static int qm_get_vft_v2(struct hisi_qm *qm, u32 *base, u32 *number)
return 0;
}
-void *hisi_qm_ctx_alloc(struct hisi_qm *qm, size_t ctx_size,
- dma_addr_t *dma_addr)
-{
- struct device *dev = &qm->pdev->dev;
- void *ctx_addr;
-
- ctx_addr = kzalloc(ctx_size, GFP_KERNEL);
- if (!ctx_addr)
- return ERR_PTR(-ENOMEM);
-
- *dma_addr = dma_map_single(dev, ctx_addr, ctx_size, DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, *dma_addr)) {
- dev_err(dev, "DMA mapping error!\n");
- kfree(ctx_addr);
- return ERR_PTR(-ENOMEM);
- }
-
- return ctx_addr;
-}
-
-void hisi_qm_ctx_free(struct hisi_qm *qm, size_t ctx_size,
- const void *ctx_addr, dma_addr_t *dma_addr)
-{
- struct device *dev = &qm->pdev->dev;
-
- dma_unmap_single(dev, *dma_addr, ctx_size, DMA_FROM_DEVICE);
- kfree(ctx_addr);
-}
-
-static int qm_dump_sqc_raw(struct hisi_qm *qm, dma_addr_t dma_addr, u16 qp_id)
-{
- return hisi_qm_mb(qm, QM_MB_CMD_SQC, dma_addr, qp_id, 1);
-}
-
-static int qm_dump_cqc_raw(struct hisi_qm *qm, dma_addr_t dma_addr, u16 qp_id)
-{
- return hisi_qm_mb(qm, QM_MB_CMD_CQC, dma_addr, qp_id, 1);
-}
-
static void qm_hw_error_init_v1(struct hisi_qm *qm)
{
writel(QM_ABNORMAL_INT_MASK_VALUE, qm->io_base + QM_ABNORMAL_INT_MASK);
@@ -1952,84 +1930,51 @@ static void hisi_qm_release_qp(struct hisi_qp *qp)
static int qm_sq_ctx_cfg(struct hisi_qp *qp, int qp_id, u32 pasid)
{
struct hisi_qm *qm = qp->qm;
- struct device *dev = &qm->pdev->dev;
enum qm_hw_ver ver = qm->ver;
- struct qm_sqc *sqc;
- dma_addr_t sqc_dma;
- int ret;
-
- sqc = kzalloc(sizeof(struct qm_sqc), GFP_KERNEL);
- if (!sqc)
- return -ENOMEM;
+ struct qm_sqc sqc = {0};
- INIT_QC_COMMON(sqc, qp->sqe_dma, pasid);
if (ver == QM_HW_V1) {
- sqc->dw3 = cpu_to_le32(QM_MK_SQC_DW3_V1(0, 0, 0, qm->sqe_size));
- sqc->w8 = cpu_to_le16(qp->sq_depth - 1);
+ sqc.dw3 = cpu_to_le32(QM_MK_SQC_DW3_V1(0, 0, 0, qm->sqe_size));
+ sqc.w8 = cpu_to_le16(qp->sq_depth - 1);
} else {
- sqc->dw3 = cpu_to_le32(QM_MK_SQC_DW3_V2(qm->sqe_size, qp->sq_depth));
- sqc->w8 = 0; /* rand_qc */
+ sqc.dw3 = cpu_to_le32(QM_MK_SQC_DW3_V2(qm->sqe_size, qp->sq_depth));
+ sqc.w8 = 0; /* rand_qc */
}
- sqc->cq_num = cpu_to_le16(qp_id);
- sqc->w13 = cpu_to_le16(QM_MK_SQC_W13(0, 1, qp->alg_type));
+ sqc.w13 = cpu_to_le16(QM_MK_SQC_W13(0, 1, qp->alg_type));
+ sqc.base_l = cpu_to_le32(lower_32_bits(qp->sqe_dma));
+ sqc.base_h = cpu_to_le32(upper_32_bits(qp->sqe_dma));
+ sqc.cq_num = cpu_to_le16(qp_id);
+ sqc.pasid = cpu_to_le16(pasid);
if (ver >= QM_HW_V3 && qm->use_sva && !qp->is_in_kernel)
- sqc->w11 = cpu_to_le16(QM_QC_PASID_ENABLE <<
- QM_QC_PASID_ENABLE_SHIFT);
-
- sqc_dma = dma_map_single(dev, sqc, sizeof(struct qm_sqc),
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev, sqc_dma)) {
- kfree(sqc);
- return -ENOMEM;
- }
+ sqc.w11 = cpu_to_le16(QM_QC_PASID_ENABLE <<
+ QM_QC_PASID_ENABLE_SHIFT);
- ret = hisi_qm_mb(qm, QM_MB_CMD_SQC, sqc_dma, qp_id, 0);
- dma_unmap_single(dev, sqc_dma, sizeof(struct qm_sqc), DMA_TO_DEVICE);
- kfree(sqc);
-
- return ret;
+ return qm_set_and_get_xqc(qm, QM_MB_CMD_SQC, &sqc, qp_id, 0);
}
static int qm_cq_ctx_cfg(struct hisi_qp *qp, int qp_id, u32 pasid)
{
struct hisi_qm *qm = qp->qm;
- struct device *dev = &qm->pdev->dev;
enum qm_hw_ver ver = qm->ver;
- struct qm_cqc *cqc;
- dma_addr_t cqc_dma;
- int ret;
-
- cqc = kzalloc(sizeof(struct qm_cqc), GFP_KERNEL);
- if (!cqc)
- return -ENOMEM;
+ struct qm_cqc cqc = {0};
- INIT_QC_COMMON(cqc, qp->cqe_dma, pasid);
if (ver == QM_HW_V1) {
- cqc->dw3 = cpu_to_le32(QM_MK_CQC_DW3_V1(0, 0, 0,
- QM_QC_CQE_SIZE));
- cqc->w8 = cpu_to_le16(qp->cq_depth - 1);
+ cqc.dw3 = cpu_to_le32(QM_MK_CQC_DW3_V1(0, 0, 0, QM_QC_CQE_SIZE));
+ cqc.w8 = cpu_to_le16(qp->cq_depth - 1);
} else {
- cqc->dw3 = cpu_to_le32(QM_MK_CQC_DW3_V2(QM_QC_CQE_SIZE, qp->cq_depth));
- cqc->w8 = 0; /* rand_qc */
+ cqc.dw3 = cpu_to_le32(QM_MK_CQC_DW3_V2(QM_QC_CQE_SIZE, qp->cq_depth));
+ cqc.w8 = 0; /* rand_qc */
}
- cqc->dw6 = cpu_to_le32(1 << QM_CQ_PHASE_SHIFT | 1 << QM_CQ_FLAG_SHIFT);
+ cqc.dw6 = cpu_to_le32(1 << QM_CQ_PHASE_SHIFT | 1 << QM_CQ_FLAG_SHIFT);
+ cqc.base_l = cpu_to_le32(lower_32_bits(qp->cqe_dma));
+ cqc.base_h = cpu_to_le32(upper_32_bits(qp->cqe_dma));
+ cqc.pasid = cpu_to_le16(pasid);
if (ver >= QM_HW_V3 && qm->use_sva && !qp->is_in_kernel)
- cqc->w11 = cpu_to_le16(QM_QC_PASID_ENABLE);
+ cqc.w11 = cpu_to_le16(QM_QC_PASID_ENABLE);
- cqc_dma = dma_map_single(dev, cqc, sizeof(struct qm_cqc),
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev, cqc_dma)) {
- kfree(cqc);
- return -ENOMEM;
- }
-
- ret = hisi_qm_mb(qm, QM_MB_CMD_CQC, cqc_dma, qp_id, 0);
- dma_unmap_single(dev, cqc_dma, sizeof(struct qm_cqc), DMA_TO_DEVICE);
- kfree(cqc);
-
- return ret;
+ return qm_set_and_get_xqc(qm, QM_MB_CMD_CQC, &cqc, qp_id, 0);
}
static int qm_qp_ctx_cfg(struct hisi_qp *qp, int qp_id, u32 pasid)
@@ -2119,14 +2064,11 @@ static void qp_stop_fail_cb(struct hisi_qp *qp)
*/
static int qm_drain_qp(struct hisi_qp *qp)
{
- size_t size = sizeof(struct qm_sqc) + sizeof(struct qm_cqc);
struct hisi_qm *qm = qp->qm;
struct device *dev = &qm->pdev->dev;
- struct qm_sqc *sqc;
- struct qm_cqc *cqc;
- dma_addr_t dma_addr;
- int ret = 0, i = 0;
- void *addr;
+ struct qm_sqc sqc;
+ struct qm_cqc cqc;
+ int ret, i = 0;
/* No need to judge if master OOO is blocked. */
if (qm_check_dev_error(qm))
@@ -2140,44 +2082,32 @@ static int qm_drain_qp(struct hisi_qp *qp)
return ret;
}
- addr = hisi_qm_ctx_alloc(qm, size, &dma_addr);
- if (IS_ERR(addr)) {
- dev_err(dev, "Failed to alloc ctx for sqc and cqc!\n");
- return -ENOMEM;
- }
-
while (++i) {
- ret = qm_dump_sqc_raw(qm, dma_addr, qp->qp_id);
+ ret = qm_set_and_get_xqc(qm, QM_MB_CMD_SQC, &sqc, qp->qp_id, 1);
if (ret) {
dev_err_ratelimited(dev, "Failed to dump sqc!\n");
- break;
+ return ret;
}
- sqc = addr;
- ret = qm_dump_cqc_raw(qm, (dma_addr + sizeof(struct qm_sqc)),
- qp->qp_id);
+ ret = qm_set_and_get_xqc(qm, QM_MB_CMD_CQC, &cqc, qp->qp_id, 1);
if (ret) {
dev_err_ratelimited(dev, "Failed to dump cqc!\n");
- break;
+ return ret;
}
- cqc = addr + sizeof(struct qm_sqc);
- if ((sqc->tail == cqc->tail) &&
+ if ((sqc.tail == cqc.tail) &&
(QM_SQ_TAIL_IDX(sqc) == QM_CQ_TAIL_IDX(cqc)))
break;
if (i == MAX_WAIT_COUNTS) {
dev_err(dev, "Fail to empty queue %u!\n", qp->qp_id);
- ret = -EBUSY;
- break;
+ return -EBUSY;
}
usleep_range(WAIT_PERIOD_US_MIN, WAIT_PERIOD_US_MAX);
}
- hisi_qm_ctx_free(qm, size, addr, &dma_addr);
-
- return ret;
+ return 0;
}
static int qm_stop_qp_nolock(struct hisi_qp *qp)
@@ -2824,7 +2754,6 @@ static void hisi_qm_pre_init(struct hisi_qm *qm)
mutex_init(&qm->mailbox_lock);
init_rwsem(&qm->qps_lock);
qm->qp_in_used = 0;
- qm->misc_ctl = false;
if (test_bit(QM_SUPPORT_RPM, &qm->caps)) {
if (!acpi_device_power_manageable(ACPI_COMPANION(&pdev->dev)))
dev_info(&pdev->dev, "_PS0 and _PR0 are not defined");
@@ -2890,11 +2819,20 @@ static void hisi_qm_unint_work(struct hisi_qm *qm)
destroy_workqueue(qm->wq);
}
+static void hisi_qm_free_rsv_buf(struct hisi_qm *qm)
+{
+ struct qm_dma *xqc_dma = &qm->xqc_buf.qcdma;
+ struct device *dev = &qm->pdev->dev;
+
+ dma_free_coherent(dev, xqc_dma->size, xqc_dma->va, xqc_dma->dma);
+}
+
static void hisi_qm_memory_uninit(struct hisi_qm *qm)
{
struct device *dev = &qm->pdev->dev;
hisi_qp_memory_uninit(qm, qm->qp_num);
+ hisi_qm_free_rsv_buf(qm);
if (qm->qdma.va) {
hisi_qm_cache_wb(qm);
dma_free_coherent(dev, qm->qdma.size,
@@ -3016,62 +2954,26 @@ static void qm_disable_eq_aeq_interrupts(struct hisi_qm *qm)
static int qm_eq_ctx_cfg(struct hisi_qm *qm)
{
- struct device *dev = &qm->pdev->dev;
- struct qm_eqc *eqc;
- dma_addr_t eqc_dma;
- int ret;
-
- eqc = kzalloc(sizeof(struct qm_eqc), GFP_KERNEL);
- if (!eqc)
- return -ENOMEM;
+ struct qm_eqc eqc = {0};
- eqc->base_l = cpu_to_le32(lower_32_bits(qm->eqe_dma));
- eqc->base_h = cpu_to_le32(upper_32_bits(qm->eqe_dma));
+ eqc.base_l = cpu_to_le32(lower_32_bits(qm->eqe_dma));
+ eqc.base_h = cpu_to_le32(upper_32_bits(qm->eqe_dma));
if (qm->ver == QM_HW_V1)
- eqc->dw3 = cpu_to_le32(QM_EQE_AEQE_SIZE);
- eqc->dw6 = cpu_to_le32(((u32)qm->eq_depth - 1) | (1 << QM_EQC_PHASE_SHIFT));
-
- eqc_dma = dma_map_single(dev, eqc, sizeof(struct qm_eqc),
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev, eqc_dma)) {
- kfree(eqc);
- return -ENOMEM;
- }
+ eqc.dw3 = cpu_to_le32(QM_EQE_AEQE_SIZE);
+ eqc.dw6 = cpu_to_le32(((u32)qm->eq_depth - 1) | (1 << QM_EQC_PHASE_SHIFT));
- ret = hisi_qm_mb(qm, QM_MB_CMD_EQC, eqc_dma, 0, 0);
- dma_unmap_single(dev, eqc_dma, sizeof(struct qm_eqc), DMA_TO_DEVICE);
- kfree(eqc);
-
- return ret;
+ return qm_set_and_get_xqc(qm, QM_MB_CMD_EQC, &eqc, 0, 0);
}
static int qm_aeq_ctx_cfg(struct hisi_qm *qm)
{
- struct device *dev = &qm->pdev->dev;
- struct qm_aeqc *aeqc;
- dma_addr_t aeqc_dma;
- int ret;
-
- aeqc = kzalloc(sizeof(struct qm_aeqc), GFP_KERNEL);
- if (!aeqc)
- return -ENOMEM;
+ struct qm_aeqc aeqc = {0};
- aeqc->base_l = cpu_to_le32(lower_32_bits(qm->aeqe_dma));
- aeqc->base_h = cpu_to_le32(upper_32_bits(qm->aeqe_dma));
- aeqc->dw6 = cpu_to_le32(((u32)qm->aeq_depth - 1) | (1 << QM_EQC_PHASE_SHIFT));
+ aeqc.base_l = cpu_to_le32(lower_32_bits(qm->aeqe_dma));
+ aeqc.base_h = cpu_to_le32(upper_32_bits(qm->aeqe_dma));
+ aeqc.dw6 = cpu_to_le32(((u32)qm->aeq_depth - 1) | (1 << QM_EQC_PHASE_SHIFT));
- aeqc_dma = dma_map_single(dev, aeqc, sizeof(struct qm_aeqc),
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev, aeqc_dma)) {
- kfree(aeqc);
- return -ENOMEM;
- }
-
- ret = hisi_qm_mb(qm, QM_MB_CMD_AEQC, aeqc_dma, 0, 0);
- dma_unmap_single(dev, aeqc_dma, sizeof(struct qm_aeqc), DMA_TO_DEVICE);
- kfree(aeqc);
-
- return ret;
+ return qm_set_and_get_xqc(qm, QM_MB_CMD_AEQC, &aeqc, 0, 0);
}
static int qm_eq_aeq_ctx_cfg(struct hisi_qm *qm)
@@ -4861,63 +4763,48 @@ static void qm_cmd_process(struct work_struct *cmd_process)
}
/**
- * hisi_qm_alg_register() - Register alg to crypto and add qm to qm_list.
+ * hisi_qm_alg_register() - Register alg to crypto.
* @qm: The qm needs add.
* @qm_list: The qm list.
+ * @guard: Guard of qp_num.
*
- * This function adds qm to qm list, and will register algorithm to
- * crypto when the qm list is empty.
+ * Register algorithm to crypto when the function is satisfy guard.
*/
-int hisi_qm_alg_register(struct hisi_qm *qm, struct hisi_qm_list *qm_list)
+int hisi_qm_alg_register(struct hisi_qm *qm, struct hisi_qm_list *qm_list, int guard)
{
struct device *dev = &qm->pdev->dev;
- int flag = 0;
- int ret = 0;
-
- mutex_lock(&qm_list->lock);
- if (list_empty(&qm_list->list))
- flag = 1;
- list_add_tail(&qm->list, &qm_list->list);
- mutex_unlock(&qm_list->lock);
if (qm->ver <= QM_HW_V2 && qm->use_sva) {
dev_info(dev, "HW V2 not both use uacce sva mode and hardware crypto algs.\n");
return 0;
}
- if (flag) {
- ret = qm_list->register_to_crypto(qm);
- if (ret) {
- mutex_lock(&qm_list->lock);
- list_del(&qm->list);
- mutex_unlock(&qm_list->lock);
- }
+ if (qm->qp_num < guard) {
+ dev_info(dev, "qp_num is less than task need.\n");
+ return 0;
}
- return ret;
+ return qm_list->register_to_crypto(qm);
}
EXPORT_SYMBOL_GPL(hisi_qm_alg_register);
/**
- * hisi_qm_alg_unregister() - Unregister alg from crypto and delete qm from
- * qm list.
+ * hisi_qm_alg_unregister() - Unregister alg from crypto.
* @qm: The qm needs delete.
* @qm_list: The qm list.
+ * @guard: Guard of qp_num.
*
- * This function deletes qm from qm list, and will unregister algorithm
- * from crypto when the qm list is empty.
+ * Unregister algorithm from crypto when the last function is satisfy guard.
*/
-void hisi_qm_alg_unregister(struct hisi_qm *qm, struct hisi_qm_list *qm_list)
+void hisi_qm_alg_unregister(struct hisi_qm *qm, struct hisi_qm_list *qm_list, int guard)
{
- mutex_lock(&qm_list->lock);
- list_del(&qm->list);
- mutex_unlock(&qm_list->lock);
-
if (qm->ver <= QM_HW_V2 && qm->use_sva)
return;
- if (list_empty(&qm_list->list))
- qm_list->unregister_from_crypto(qm);
+ if (qm->qp_num < guard)
+ return;
+
+ qm_list->unregister_from_crypto(qm);
}
EXPORT_SYMBOL_GPL(hisi_qm_alg_unregister);
@@ -5013,8 +4900,8 @@ static int qm_register_aeq_irq(struct hisi_qm *qm)
return 0;
irq_vector = val & QM_IRQ_VECTOR_MASK;
- ret = request_threaded_irq(pci_irq_vector(pdev, irq_vector), qm_aeq_irq,
- qm_aeq_thread, 0, qm->dev_name, qm);
+ ret = request_threaded_irq(pci_irq_vector(pdev, irq_vector), NULL,
+ qm_aeq_thread, IRQF_ONESHOT, qm->dev_name, qm);
if (ret)
dev_err(&pdev->dev, "failed to request eq irq, ret = %d", ret);
@@ -5093,6 +4980,7 @@ free_eq_irq:
static int qm_get_qp_num(struct hisi_qm *qm)
{
+ struct device *dev = &qm->pdev->dev;
bool is_db_isolation;
/* VF's qp_num assigned by PF in v2, and VF can get qp_num by vft. */
@@ -5109,13 +4997,21 @@ static int qm_get_qp_num(struct hisi_qm *qm)
qm->max_qp_num = hisi_qm_get_hw_info(qm, qm_basic_info,
QM_FUNC_MAX_QP_CAP, is_db_isolation);
- /* check if qp number is valid */
- if (qm->qp_num > qm->max_qp_num) {
- dev_err(&qm->pdev->dev, "qp num(%u) is more than max qp num(%u)!\n",
+ if (qm->qp_num <= qm->max_qp_num)
+ return 0;
+
+ if (test_bit(QM_MODULE_PARAM, &qm->misc_ctl)) {
+ /* Check whether the set qp number is valid */
+ dev_err(dev, "qp num(%u) is more than max qp num(%u)!\n",
qm->qp_num, qm->max_qp_num);
return -EINVAL;
}
+ dev_info(dev, "Default qp num(%u) is too big, reset it to Function's max qp num(%u)!\n",
+ qm->qp_num, qm->max_qp_num);
+ qm->qp_num = qm->max_qp_num;
+ qm->debug.curr_qm_qp_num = qm->qp_num;
+
return 0;
}
@@ -5303,6 +5199,36 @@ err_init_qp_mem:
return ret;
}
+static int hisi_qm_alloc_rsv_buf(struct hisi_qm *qm)
+{
+ struct qm_rsv_buf *xqc_buf = &qm->xqc_buf;
+ struct qm_dma *xqc_dma = &xqc_buf->qcdma;
+ struct device *dev = &qm->pdev->dev;
+ size_t off = 0;
+
+#define QM_XQC_BUF_INIT(xqc_buf, type) do { \
+ (xqc_buf)->type = ((xqc_buf)->qcdma.va + (off)); \
+ (xqc_buf)->type##_dma = (xqc_buf)->qcdma.dma + (off); \
+ off += QMC_ALIGN(sizeof(struct qm_##type)); \
+} while (0)
+
+ xqc_dma->size = QMC_ALIGN(sizeof(struct qm_eqc)) +
+ QMC_ALIGN(sizeof(struct qm_aeqc)) +
+ QMC_ALIGN(sizeof(struct qm_sqc)) +
+ QMC_ALIGN(sizeof(struct qm_cqc));
+ xqc_dma->va = dma_alloc_coherent(dev, xqc_dma->size,
+ &xqc_dma->dma, GFP_KERNEL);
+ if (!xqc_dma->va)
+ return -ENOMEM;
+
+ QM_XQC_BUF_INIT(xqc_buf, eqc);
+ QM_XQC_BUF_INIT(xqc_buf, aeqc);
+ QM_XQC_BUF_INIT(xqc_buf, sqc);
+ QM_XQC_BUF_INIT(xqc_buf, cqc);
+
+ return 0;
+}
+
static int hisi_qm_memory_init(struct hisi_qm *qm)
{
struct device *dev = &qm->pdev->dev;
@@ -5344,13 +5270,19 @@ static int hisi_qm_memory_init(struct hisi_qm *qm)
QM_INIT_BUF(qm, sqc, qm->qp_num);
QM_INIT_BUF(qm, cqc, qm->qp_num);
+ ret = hisi_qm_alloc_rsv_buf(qm);
+ if (ret)
+ goto err_free_qdma;
+
ret = hisi_qp_alloc_memory(qm);
if (ret)
- goto err_alloc_qp_array;
+ goto err_free_reserve_buf;
return 0;
-err_alloc_qp_array:
+err_free_reserve_buf:
+ hisi_qm_free_rsv_buf(qm);
+err_free_qdma:
dma_free_coherent(dev, qm->qdma.size, qm->qdma.va, qm->qdma.dma);
err_destroy_idr:
idr_destroy(&qm->qp_idr);
diff --git a/drivers/crypto/hisilicon/qm_common.h b/drivers/crypto/hisilicon/qm_common.h
index 1406a422d455..7b0b15c83ec1 100644
--- a/drivers/crypto/hisilicon/qm_common.h
+++ b/drivers/crypto/hisilicon/qm_common.h
@@ -4,7 +4,6 @@
#define QM_COMMON_H
#define QM_DBG_READ_LEN 256
-#define QM_RESETTING 2
struct qm_cqe {
__le32 rsvd0;
@@ -77,10 +76,7 @@ static const char * const qm_s[] = {
"init", "start", "close", "stop",
};
-void *hisi_qm_ctx_alloc(struct hisi_qm *qm, size_t ctx_size,
- dma_addr_t *dma_addr);
-void hisi_qm_ctx_free(struct hisi_qm *qm, size_t ctx_size,
- const void *ctx_addr, dma_addr_t *dma_addr);
+int qm_set_and_get_xqc(struct hisi_qm *qm, u8 cmd, void *xqc, u32 qp_id, bool op);
void hisi_qm_show_last_dfx_regs(struct hisi_qm *qm);
void hisi_qm_set_algqos_init(struct hisi_qm *qm);
diff --git a/drivers/crypto/hisilicon/sec/sec_drv.c b/drivers/crypto/hisilicon/sec/sec_drv.c
index e1e08993de12..afdddf87cc34 100644
--- a/drivers/crypto/hisilicon/sec/sec_drv.c
+++ b/drivers/crypto/hisilicon/sec/sec_drv.c
@@ -1271,7 +1271,7 @@ queues_unconfig:
return ret;
}
-static int sec_remove(struct platform_device *pdev)
+static void sec_remove(struct platform_device *pdev)
{
struct sec_dev_info *info = platform_get_drvdata(pdev);
int i;
@@ -1287,8 +1287,6 @@ static int sec_remove(struct platform_device *pdev)
}
sec_base_exit(info);
-
- return 0;
}
static const __maybe_unused struct of_device_id sec_match[] = {
@@ -1306,7 +1304,7 @@ MODULE_DEVICE_TABLE(acpi, sec_acpi_match);
static struct platform_driver sec_driver = {
.probe = sec_probe,
- .remove = sec_remove,
+ .remove_new = sec_remove,
.driver = {
.name = "hisi_sec_platform_driver",
.of_match_table = sec_match,
diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c
index 074e50ef512c..6fcabbc87860 100644
--- a/drivers/crypto/hisilicon/sec2/sec_crypto.c
+++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c
@@ -104,6 +104,9 @@
#define IV_CTR_INIT 0x1
#define IV_BYTE_OFFSET 0x8
+static DEFINE_MUTEX(sec_algs_lock);
+static unsigned int sec_available_devs;
+
struct sec_skcipher {
u64 alg_msk;
struct skcipher_alg alg;
@@ -1011,6 +1014,7 @@ static int sec_cipher_map(struct sec_ctx *ctx, struct sec_req *req,
ret = sec_aead_mac_init(a_req);
if (unlikely(ret)) {
dev_err(dev, "fail to init mac data for ICV!\n");
+ hisi_acc_sg_buf_unmap(dev, src, req->in);
return ret;
}
}
@@ -2544,16 +2548,31 @@ err:
int sec_register_to_crypto(struct hisi_qm *qm)
{
u64 alg_mask = sec_get_alg_bitmap(qm, SEC_DRV_ALG_BITMAP_HIGH, SEC_DRV_ALG_BITMAP_LOW);
- int ret;
+ int ret = 0;
+
+ mutex_lock(&sec_algs_lock);
+ if (sec_available_devs) {
+ sec_available_devs++;
+ goto unlock;
+ }
ret = sec_register_skcipher(alg_mask);
if (ret)
- return ret;
+ goto unlock;
ret = sec_register_aead(alg_mask);
if (ret)
- sec_unregister_skcipher(alg_mask, ARRAY_SIZE(sec_skciphers));
+ goto unreg_skcipher;
+ sec_available_devs++;
+ mutex_unlock(&sec_algs_lock);
+
+ return 0;
+
+unreg_skcipher:
+ sec_unregister_skcipher(alg_mask, ARRAY_SIZE(sec_skciphers));
+unlock:
+ mutex_unlock(&sec_algs_lock);
return ret;
}
@@ -2561,6 +2580,13 @@ void sec_unregister_from_crypto(struct hisi_qm *qm)
{
u64 alg_mask = sec_get_alg_bitmap(qm, SEC_DRV_ALG_BITMAP_HIGH, SEC_DRV_ALG_BITMAP_LOW);
+ mutex_lock(&sec_algs_lock);
+ if (--sec_available_devs)
+ goto unlock;
+
sec_unregister_aead(alg_mask, ARRAY_SIZE(sec_aeads));
sec_unregister_skcipher(alg_mask, ARRAY_SIZE(sec_skciphers));
+
+unlock:
+ mutex_unlock(&sec_algs_lock);
}
diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c
index 77f9f131b850..0e56a47eb862 100644
--- a/drivers/crypto/hisilicon/sec2/sec_main.c
+++ b/drivers/crypto/hisilicon/sec2/sec_main.c
@@ -311,8 +311,11 @@ static int sec_diff_regs_show(struct seq_file *s, void *unused)
}
DEFINE_SHOW_ATTRIBUTE(sec_diff_regs);
+static bool pf_q_num_flag;
static int sec_pf_q_num_set(const char *val, const struct kernel_param *kp)
{
+ pf_q_num_flag = true;
+
return q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_SEC_PF);
}
@@ -1120,6 +1123,8 @@ static int sec_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
qm->qp_num = pf_q_num;
qm->debug.curr_qm_qp_num = pf_q_num;
qm->qm_list = &sec_devices;
+ if (pf_q_num_flag)
+ set_bit(QM_MODULE_PARAM, &qm->misc_ctl);
} else if (qm->fun_type == QM_HW_VF && qm->ver == QM_HW_V1) {
/*
* have no way to get qm configure in VM in v1 hardware,
@@ -1229,15 +1234,11 @@ static int sec_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
pci_warn(pdev, "Failed to init debugfs!\n");
- if (qm->qp_num >= ctx_q_num) {
- ret = hisi_qm_alg_register(qm, &sec_devices);
- if (ret < 0) {
- pr_err("Failed to register driver to crypto.\n");
- goto err_qm_stop;
- }
- } else {
- pci_warn(qm->pdev,
- "Failed to use kernel mode, qp not enough!\n");
+ hisi_qm_add_list(qm, &sec_devices);
+ ret = hisi_qm_alg_register(qm, &sec_devices, ctx_q_num);
+ if (ret < 0) {
+ pr_err("Failed to register driver to crypto.\n");
+ goto err_qm_del_list;
}
if (qm->uacce) {
@@ -1259,9 +1260,9 @@ static int sec_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
err_alg_unregister:
- if (qm->qp_num >= ctx_q_num)
- hisi_qm_alg_unregister(qm, &sec_devices);
-err_qm_stop:
+ hisi_qm_alg_unregister(qm, &sec_devices, ctx_q_num);
+err_qm_del_list:
+ hisi_qm_del_list(qm, &sec_devices);
sec_debugfs_exit(qm);
hisi_qm_stop(qm, QM_NORMAL);
err_probe_uninit:
@@ -1278,8 +1279,8 @@ static void sec_remove(struct pci_dev *pdev)
hisi_qm_pm_uninit(qm);
hisi_qm_wait_task_finish(qm, &sec_devices);
- if (qm->qp_num >= ctx_q_num)
- hisi_qm_alg_unregister(qm, &sec_devices);
+ hisi_qm_alg_unregister(qm, &sec_devices, ctx_q_num);
+ hisi_qm_del_list(qm, &sec_devices);
if (qm->fun_type == QM_HW_PF && qm->vfs_num)
hisi_qm_sriov_disable(pdev, true);
diff --git a/drivers/crypto/hisilicon/trng/trng.c b/drivers/crypto/hisilicon/trng/trng.c
index 97e500db0a82..451b167bcc73 100644
--- a/drivers/crypto/hisilicon/trng/trng.c
+++ b/drivers/crypto/hisilicon/trng/trng.c
@@ -303,7 +303,7 @@ err_remove_from_list:
return ret;
}
-static int hisi_trng_remove(struct platform_device *pdev)
+static void hisi_trng_remove(struct platform_device *pdev)
{
struct hisi_trng *trng = platform_get_drvdata(pdev);
@@ -314,8 +314,6 @@ static int hisi_trng_remove(struct platform_device *pdev)
if (trng->ver != HISI_TRNG_VER_V1 &&
atomic_dec_return(&trng_active_devs) == 0)
crypto_unregister_rng(&hisi_trng_alg);
-
- return 0;
}
static const struct acpi_device_id hisi_trng_acpi_match[] = {
@@ -326,7 +324,7 @@ MODULE_DEVICE_TABLE(acpi, hisi_trng_acpi_match);
static struct platform_driver hisi_trng_driver = {
.probe = hisi_trng_probe,
- .remove = hisi_trng_remove,
+ .remove_new = hisi_trng_remove,
.driver = {
.name = "hisi-trng-v2",
.acpi_match_table = ACPI_PTR(hisi_trng_acpi_match),
diff --git a/drivers/crypto/hisilicon/zip/zip_crypto.c b/drivers/crypto/hisilicon/zip/zip_crypto.c
index 6608971d10cd..c650c741a18d 100644
--- a/drivers/crypto/hisilicon/zip/zip_crypto.c
+++ b/drivers/crypto/hisilicon/zip/zip_crypto.c
@@ -16,36 +16,17 @@
#define HZIP_OUT_SGE_DATA_OFFSET_M GENMASK(23, 0)
/* hisi_zip_sqe dw9 */
#define HZIP_REQ_TYPE_M GENMASK(7, 0)
-#define HZIP_ALG_TYPE_ZLIB 0x02
-#define HZIP_ALG_TYPE_GZIP 0x03
+#define HZIP_ALG_TYPE_DEFLATE 0x01
#define HZIP_BUF_TYPE_M GENMASK(11, 8)
-#define HZIP_PBUFFER 0x0
#define HZIP_SGL 0x1
-#define HZIP_ZLIB_HEAD_SIZE 2
-#define HZIP_GZIP_HEAD_SIZE 10
-
-#define GZIP_HEAD_FHCRC_BIT BIT(1)
-#define GZIP_HEAD_FEXTRA_BIT BIT(2)
-#define GZIP_HEAD_FNAME_BIT BIT(3)
-#define GZIP_HEAD_FCOMMENT_BIT BIT(4)
-
-#define GZIP_HEAD_FLG_SHIFT 3
-#define GZIP_HEAD_FEXTRA_SHIFT 10
-#define GZIP_HEAD_FEXTRA_XLEN 2UL
-#define GZIP_HEAD_FHCRC_SIZE 2
-
-#define HZIP_GZIP_HEAD_BUF 256
#define HZIP_ALG_PRIORITY 300
#define HZIP_SGL_SGE_NR 10
-#define HZIP_ALG_ZLIB GENMASK(1, 0)
-#define HZIP_ALG_GZIP GENMASK(3, 2)
+#define HZIP_ALG_DEFLATE GENMASK(5, 4)
-static const u8 zlib_head[HZIP_ZLIB_HEAD_SIZE] = {0x78, 0x9c};
-static const u8 gzip_head[HZIP_GZIP_HEAD_SIZE] = {
- 0x1f, 0x8b, 0x08, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x03
-};
+static DEFINE_MUTEX(zip_algs_lock);
+static unsigned int zip_available_devs;
enum hisi_zip_alg_type {
HZIP_ALG_TYPE_COMP = 0,
@@ -59,21 +40,10 @@ enum {
};
#define COMP_NAME_TO_TYPE(alg_name) \
- (!strcmp((alg_name), "zlib-deflate") ? HZIP_ALG_TYPE_ZLIB : \
- !strcmp((alg_name), "gzip") ? HZIP_ALG_TYPE_GZIP : 0) \
-
-#define TO_HEAD_SIZE(req_type) \
- (((req_type) == HZIP_ALG_TYPE_ZLIB) ? sizeof(zlib_head) : \
- ((req_type) == HZIP_ALG_TYPE_GZIP) ? sizeof(gzip_head) : 0) \
-
-#define TO_HEAD(req_type) \
- (((req_type) == HZIP_ALG_TYPE_ZLIB) ? zlib_head : \
- ((req_type) == HZIP_ALG_TYPE_GZIP) ? gzip_head : NULL) \
+ (!strcmp((alg_name), "deflate") ? HZIP_ALG_TYPE_DEFLATE : 0)
struct hisi_zip_req {
struct acomp_req *req;
- u32 sskip;
- u32 dskip;
struct hisi_acc_hw_sgl *hw_src;
struct hisi_acc_hw_sgl *hw_dst;
dma_addr_t dma_src;
@@ -138,85 +108,8 @@ static u16 sgl_sge_nr = HZIP_SGL_SGE_NR;
module_param_cb(sgl_sge_nr, &sgl_sge_nr_ops, &sgl_sge_nr, 0444);
MODULE_PARM_DESC(sgl_sge_nr, "Number of sge in sgl(1-255)");
-static u32 get_extra_field_size(const u8 *start)
-{
- return *((u16 *)start) + GZIP_HEAD_FEXTRA_XLEN;
-}
-
-static u32 get_name_field_size(const u8 *start)
-{
- return strlen(start) + 1;
-}
-
-static u32 get_comment_field_size(const u8 *start)
-{
- return strlen(start) + 1;
-}
-
-static u32 __get_gzip_head_size(const u8 *src)
-{
- u8 head_flg = *(src + GZIP_HEAD_FLG_SHIFT);
- u32 size = GZIP_HEAD_FEXTRA_SHIFT;
-
- if (head_flg & GZIP_HEAD_FEXTRA_BIT)
- size += get_extra_field_size(src + size);
- if (head_flg & GZIP_HEAD_FNAME_BIT)
- size += get_name_field_size(src + size);
- if (head_flg & GZIP_HEAD_FCOMMENT_BIT)
- size += get_comment_field_size(src + size);
- if (head_flg & GZIP_HEAD_FHCRC_BIT)
- size += GZIP_HEAD_FHCRC_SIZE;
-
- return size;
-}
-
-static u32 __maybe_unused get_gzip_head_size(struct scatterlist *sgl)
-{
- char buf[HZIP_GZIP_HEAD_BUF];
-
- sg_copy_to_buffer(sgl, sg_nents(sgl), buf, sizeof(buf));
-
- return __get_gzip_head_size(buf);
-}
-
-static int add_comp_head(struct scatterlist *dst, u8 req_type)
-{
- int head_size = TO_HEAD_SIZE(req_type);
- const u8 *head = TO_HEAD(req_type);
- int ret;
-
- ret = sg_copy_from_buffer(dst, sg_nents(dst), head, head_size);
- if (unlikely(ret != head_size)) {
- pr_err("the head size of buffer is wrong (%d)!\n", ret);
- return -ENOMEM;
- }
-
- return head_size;
-}
-
-static int get_comp_head_size(struct acomp_req *acomp_req, u8 req_type)
-{
- if (unlikely(!acomp_req->src || !acomp_req->slen))
- return -EINVAL;
-
- if (unlikely(req_type == HZIP_ALG_TYPE_GZIP &&
- acomp_req->slen < GZIP_HEAD_FEXTRA_SHIFT))
- return -EINVAL;
-
- switch (req_type) {
- case HZIP_ALG_TYPE_ZLIB:
- return TO_HEAD_SIZE(HZIP_ALG_TYPE_ZLIB);
- case HZIP_ALG_TYPE_GZIP:
- return TO_HEAD_SIZE(HZIP_ALG_TYPE_GZIP);
- default:
- pr_err("request type does not support!\n");
- return -EINVAL;
- }
-}
-
-static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
- struct hisi_zip_qp_ctx *qp_ctx,
- size_t head_size, bool is_comp)
+static struct hisi_zip_req *hisi_zip_create_req(struct hisi_zip_qp_ctx *qp_ctx,
+ struct acomp_req *req)
{
struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
struct hisi_zip_req *q = req_q->q;
@@ -239,14 +132,6 @@ static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
req_cache->req_id = req_id;
req_cache->req = req;
- if (is_comp) {
- req_cache->sskip = 0;
- req_cache->dskip = head_size;
- } else {
- req_cache->sskip = head_size;
- req_cache->dskip = 0;
- }
-
return req_cache;
}
@@ -272,10 +157,8 @@ static void hisi_zip_fill_buf_size(struct hisi_zip_sqe *sqe, struct hisi_zip_req
{
struct acomp_req *a_req = req->req;
- sqe->input_data_length = a_req->slen - req->sskip;
- sqe->dest_avail_out = a_req->dlen - req->dskip;
- sqe->dw7 = FIELD_PREP(HZIP_IN_SGE_DATA_OFFSET_M, req->sskip);
- sqe->dw8 = FIELD_PREP(HZIP_OUT_SGE_DATA_OFFSET_M, req->dskip);
+ sqe->input_data_length = a_req->slen;
+ sqe->dest_avail_out = a_req->dlen;
}
static void hisi_zip_fill_buf_type(struct hisi_zip_sqe *sqe, u8 buf_type)
@@ -296,12 +179,7 @@ static void hisi_zip_fill_req_type(struct hisi_zip_sqe *sqe, u8 req_type)
sqe->dw9 = val;
}
-static void hisi_zip_fill_tag_v1(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req)
-{
- sqe->dw13 = req->req_id;
-}
-
-static void hisi_zip_fill_tag_v2(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req)
+static void hisi_zip_fill_tag(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req)
{
sqe->dw26 = req->req_id;
}
@@ -330,8 +208,8 @@ static void hisi_zip_fill_sqe(struct hisi_zip_ctx *ctx, struct hisi_zip_sqe *sqe
ops->fill_sqe_type(sqe, ops->sqe_type);
}
-static int hisi_zip_do_work(struct hisi_zip_req *req,
- struct hisi_zip_qp_ctx *qp_ctx)
+static int hisi_zip_do_work(struct hisi_zip_qp_ctx *qp_ctx,
+ struct hisi_zip_req *req)
{
struct hisi_acc_sgl_pool *pool = qp_ctx->sgl_pool;
struct hisi_zip_dfx *dfx = &qp_ctx->zip_dev->dfx;
@@ -383,12 +261,7 @@ err_unmap_input:
return ret;
}
-static u32 hisi_zip_get_tag_v1(struct hisi_zip_sqe *sqe)
-{
- return sqe->dw13;
-}
-
-static u32 hisi_zip_get_tag_v2(struct hisi_zip_sqe *sqe)
+static u32 hisi_zip_get_tag(struct hisi_zip_sqe *sqe)
{
return sqe->dw26;
}
@@ -414,8 +287,8 @@ static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data)
u32 tag = ops->get_tag(sqe);
struct hisi_zip_req *req = req_q->q + tag;
struct acomp_req *acomp_req = req->req;
- u32 status, dlen, head_size;
int err = 0;
+ u32 status;
atomic64_inc(&dfx->recv_cnt);
status = ops->get_status(sqe);
@@ -427,13 +300,10 @@ static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data)
err = -EIO;
}
- dlen = ops->get_dstlen(sqe);
-
hisi_acc_sg_buf_unmap(dev, acomp_req->src, req->hw_src);
hisi_acc_sg_buf_unmap(dev, acomp_req->dst, req->hw_dst);
- head_size = (qp->alg_type == 0) ? TO_HEAD_SIZE(qp->req_type) : 0;
- acomp_req->dlen = dlen + head_size;
+ acomp_req->dlen = ops->get_dstlen(sqe);
if (acomp_req->base.complete)
acomp_request_complete(acomp_req, err);
@@ -447,22 +317,13 @@ static int hisi_zip_acompress(struct acomp_req *acomp_req)
struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[HZIP_QPC_COMP];
struct device *dev = &qp_ctx->qp->qm->pdev->dev;
struct hisi_zip_req *req;
- int head_size;
int ret;
- /* let's output compression head now */
- head_size = add_comp_head(acomp_req->dst, qp_ctx->qp->req_type);
- if (unlikely(head_size < 0)) {
- dev_err_ratelimited(dev, "failed to add comp head (%d)!\n",
- head_size);
- return head_size;
- }
-
- req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, true);
+ req = hisi_zip_create_req(qp_ctx, acomp_req);
if (IS_ERR(req))
return PTR_ERR(req);
- ret = hisi_zip_do_work(req, qp_ctx);
+ ret = hisi_zip_do_work(qp_ctx, req);
if (unlikely(ret != -EINPROGRESS)) {
dev_info_ratelimited(dev, "failed to do compress (%d)!\n", ret);
hisi_zip_remove_req(qp_ctx, req);
@@ -477,20 +338,13 @@ static int hisi_zip_adecompress(struct acomp_req *acomp_req)
struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[HZIP_QPC_DECOMP];
struct device *dev = &qp_ctx->qp->qm->pdev->dev;
struct hisi_zip_req *req;
- int head_size, ret;
-
- head_size = get_comp_head_size(acomp_req, qp_ctx->qp->req_type);
- if (unlikely(head_size < 0)) {
- dev_err_ratelimited(dev, "failed to get comp head size (%d)!\n",
- head_size);
- return head_size;
- }
+ int ret;
- req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, false);
+ req = hisi_zip_create_req(qp_ctx, acomp_req);
if (IS_ERR(req))
return PTR_ERR(req);
- ret = hisi_zip_do_work(req, qp_ctx);
+ ret = hisi_zip_do_work(qp_ctx, req);
if (unlikely(ret != -EINPROGRESS)) {
dev_info_ratelimited(dev, "failed to do decompress (%d)!\n",
ret);
@@ -527,28 +381,15 @@ static void hisi_zip_release_qp(struct hisi_zip_qp_ctx *qp_ctx)
hisi_qm_free_qps(&qp_ctx->qp, 1);
}
-static const struct hisi_zip_sqe_ops hisi_zip_ops_v1 = {
- .sqe_type = 0,
- .fill_addr = hisi_zip_fill_addr,
- .fill_buf_size = hisi_zip_fill_buf_size,
- .fill_buf_type = hisi_zip_fill_buf_type,
- .fill_req_type = hisi_zip_fill_req_type,
- .fill_tag = hisi_zip_fill_tag_v1,
- .fill_sqe_type = hisi_zip_fill_sqe_type,
- .get_tag = hisi_zip_get_tag_v1,
- .get_status = hisi_zip_get_status,
- .get_dstlen = hisi_zip_get_dstlen,
-};
-
-static const struct hisi_zip_sqe_ops hisi_zip_ops_v2 = {
+static const struct hisi_zip_sqe_ops hisi_zip_ops = {
.sqe_type = 0x3,
.fill_addr = hisi_zip_fill_addr,
.fill_buf_size = hisi_zip_fill_buf_size,
.fill_buf_type = hisi_zip_fill_buf_type,
.fill_req_type = hisi_zip_fill_req_type,
- .fill_tag = hisi_zip_fill_tag_v2,
+ .fill_tag = hisi_zip_fill_tag,
.fill_sqe_type = hisi_zip_fill_sqe_type,
- .get_tag = hisi_zip_get_tag_v2,
+ .get_tag = hisi_zip_get_tag,
.get_status = hisi_zip_get_status,
.get_dstlen = hisi_zip_get_dstlen,
};
@@ -584,10 +425,7 @@ static int hisi_zip_ctx_init(struct hisi_zip_ctx *hisi_zip_ctx, u8 req_type, int
qp_ctx->zip_dev = hisi_zip;
}
- if (hisi_zip->qm.ver < QM_HW_V3)
- hisi_zip_ctx->ops = &hisi_zip_ops_v1;
- else
- hisi_zip_ctx->ops = &hisi_zip_ops_v2;
+ hisi_zip_ctx->ops = &hisi_zip_ops;
return 0;
}
@@ -745,95 +583,67 @@ static void hisi_zip_acomp_exit(struct crypto_acomp *tfm)
hisi_zip_ctx_exit(ctx);
}
-static struct acomp_alg hisi_zip_acomp_zlib = {
- .init = hisi_zip_acomp_init,
- .exit = hisi_zip_acomp_exit,
- .compress = hisi_zip_acompress,
- .decompress = hisi_zip_adecompress,
- .base = {
- .cra_name = "zlib-deflate",
- .cra_driver_name = "hisi-zlib-acomp",
- .cra_module = THIS_MODULE,
- .cra_priority = HZIP_ALG_PRIORITY,
- .cra_ctxsize = sizeof(struct hisi_zip_ctx),
- }
-};
-
-static int hisi_zip_register_zlib(struct hisi_qm *qm)
-{
- int ret;
-
- if (!hisi_zip_alg_support(qm, HZIP_ALG_ZLIB))
- return 0;
-
- ret = crypto_register_acomp(&hisi_zip_acomp_zlib);
- if (ret)
- dev_err(&qm->pdev->dev, "failed to register to zlib (%d)!\n", ret);
-
- return ret;
-}
-
-static void hisi_zip_unregister_zlib(struct hisi_qm *qm)
-{
- if (!hisi_zip_alg_support(qm, HZIP_ALG_ZLIB))
- return;
-
- crypto_unregister_acomp(&hisi_zip_acomp_zlib);
-}
-
-static struct acomp_alg hisi_zip_acomp_gzip = {
+static struct acomp_alg hisi_zip_acomp_deflate = {
.init = hisi_zip_acomp_init,
.exit = hisi_zip_acomp_exit,
.compress = hisi_zip_acompress,
.decompress = hisi_zip_adecompress,
.base = {
- .cra_name = "gzip",
- .cra_driver_name = "hisi-gzip-acomp",
+ .cra_name = "deflate",
+ .cra_driver_name = "hisi-deflate-acomp",
.cra_module = THIS_MODULE,
- .cra_priority = HZIP_ALG_PRIORITY,
+ .cra_priority = HZIP_ALG_PRIORITY,
.cra_ctxsize = sizeof(struct hisi_zip_ctx),
}
};
-static int hisi_zip_register_gzip(struct hisi_qm *qm)
+static int hisi_zip_register_deflate(struct hisi_qm *qm)
{
int ret;
- if (!hisi_zip_alg_support(qm, HZIP_ALG_GZIP))
+ if (!hisi_zip_alg_support(qm, HZIP_ALG_DEFLATE))
return 0;
- ret = crypto_register_acomp(&hisi_zip_acomp_gzip);
+ ret = crypto_register_acomp(&hisi_zip_acomp_deflate);
if (ret)
- dev_err(&qm->pdev->dev, "failed to register to gzip (%d)!\n", ret);
+ dev_err(&qm->pdev->dev, "failed to register to deflate (%d)!\n", ret);
return ret;
}
-static void hisi_zip_unregister_gzip(struct hisi_qm *qm)
+static void hisi_zip_unregister_deflate(struct hisi_qm *qm)
{
- if (!hisi_zip_alg_support(qm, HZIP_ALG_GZIP))
+ if (!hisi_zip_alg_support(qm, HZIP_ALG_DEFLATE))
return;
- crypto_unregister_acomp(&hisi_zip_acomp_gzip);
+ crypto_unregister_acomp(&hisi_zip_acomp_deflate);
}
int hisi_zip_register_to_crypto(struct hisi_qm *qm)
{
int ret = 0;
- ret = hisi_zip_register_zlib(qm);
- if (ret)
- return ret;
+ mutex_lock(&zip_algs_lock);
+ if (zip_available_devs++)
+ goto unlock;
- ret = hisi_zip_register_gzip(qm);
+ ret = hisi_zip_register_deflate(qm);
if (ret)
- hisi_zip_unregister_zlib(qm);
+ zip_available_devs--;
+unlock:
+ mutex_unlock(&zip_algs_lock);
return ret;
}
void hisi_zip_unregister_from_crypto(struct hisi_qm *qm)
{
- hisi_zip_unregister_zlib(qm);
- hisi_zip_unregister_gzip(qm);
+ mutex_lock(&zip_algs_lock);
+ if (--zip_available_devs)
+ goto unlock;
+
+ hisi_zip_unregister_deflate(qm);
+
+unlock:
+ mutex_unlock(&zip_algs_lock);
}
diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c
index f3ce34198775..db4c964cd649 100644
--- a/drivers/crypto/hisilicon/zip/zip_main.c
+++ b/drivers/crypto/hisilicon/zip/zip_main.c
@@ -66,6 +66,7 @@
#define HZIP_SQE_SIZE 128
#define HZIP_PF_DEF_Q_NUM 64
#define HZIP_PF_DEF_Q_BASE 0
+#define HZIP_CTX_Q_NUM_DEF 2
#define HZIP_SOFT_CTRL_CNT_CLR_CE 0x301000
#define HZIP_SOFT_CTRL_CNT_CLR_CE_BIT BIT(0)
@@ -236,8 +237,8 @@ static struct hisi_qm_cap_info zip_basic_cap_info[] = {
{ZIP_CLUSTER_DECOMP_NUM_CAP, 0x313C, 0, GENMASK(7, 0), 0x6, 0x6, 0x3},
{ZIP_DECOMP_ENABLE_BITMAP, 0x3140, 16, GENMASK(15, 0), 0xFC, 0xFC, 0x1C},
{ZIP_COMP_ENABLE_BITMAP, 0x3140, 0, GENMASK(15, 0), 0x3, 0x3, 0x3},
- {ZIP_DRV_ALG_BITMAP, 0x3144, 0, GENMASK(31, 0), 0xF, 0xF, 0xF},
- {ZIP_DEV_ALG_BITMAP, 0x3148, 0, GENMASK(31, 0), 0xF, 0xF, 0xFF},
+ {ZIP_DRV_ALG_BITMAP, 0x3144, 0, GENMASK(31, 0), 0x0, 0x0, 0x30},
+ {ZIP_DEV_ALG_BITMAP, 0x3148, 0, GENMASK(31, 0), 0xF, 0xF, 0x3F},
{ZIP_CORE1_ALG_BITMAP, 0x314C, 0, GENMASK(31, 0), 0x5, 0x5, 0xD5},
{ZIP_CORE2_ALG_BITMAP, 0x3150, 0, GENMASK(31, 0), 0x5, 0x5, 0xD5},
{ZIP_CORE3_ALG_BITMAP, 0x3154, 0, GENMASK(31, 0), 0xA, 0xA, 0x2A},
@@ -364,8 +365,11 @@ static u32 uacce_mode = UACCE_MODE_NOUACCE;
module_param_cb(uacce_mode, &zip_uacce_mode_ops, &uacce_mode, 0444);
MODULE_PARM_DESC(uacce_mode, UACCE_MODE_DESC);
+static bool pf_q_num_flag;
static int pf_q_num_set(const char *val, const struct kernel_param *kp)
{
+ pf_q_num_flag = true;
+
return q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_ZIP_PF);
}
@@ -1139,6 +1143,8 @@ static int hisi_zip_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
qm->qp_num = pf_q_num;
qm->debug.curr_qm_qp_num = pf_q_num;
qm->qm_list = &zip_devices;
+ if (pf_q_num_flag)
+ set_bit(QM_MODULE_PARAM, &qm->misc_ctl);
} else if (qm->fun_type == QM_HW_VF && qm->ver == QM_HW_V1) {
/*
* have no way to get qm configure in VM in v1 hardware,
@@ -1226,10 +1232,11 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
pci_err(pdev, "failed to init debugfs (%d)!\n", ret);
- ret = hisi_qm_alg_register(qm, &zip_devices);
+ hisi_qm_add_list(qm, &zip_devices);
+ ret = hisi_qm_alg_register(qm, &zip_devices, HZIP_CTX_Q_NUM_DEF);
if (ret < 0) {
pci_err(pdev, "failed to register driver to crypto!\n");
- goto err_qm_stop;
+ goto err_qm_del_list;
}
if (qm->uacce) {
@@ -1251,9 +1258,10 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
err_qm_alg_unregister:
- hisi_qm_alg_unregister(qm, &zip_devices);
+ hisi_qm_alg_unregister(qm, &zip_devices, HZIP_CTX_Q_NUM_DEF);
-err_qm_stop:
+err_qm_del_list:
+ hisi_qm_del_list(qm, &zip_devices);
hisi_zip_debugfs_exit(qm);
hisi_qm_stop(qm, QM_NORMAL);
@@ -1273,7 +1281,8 @@ static void hisi_zip_remove(struct pci_dev *pdev)
hisi_qm_pm_uninit(qm);
hisi_qm_wait_task_finish(qm, &zip_devices);
- hisi_qm_alg_unregister(qm, &zip_devices);
+ hisi_qm_alg_unregister(qm, &zip_devices, HZIP_CTX_Q_NUM_DEF);
+ hisi_qm_del_list(qm, &zip_devices);
if (qm->fun_type == QM_HW_PF && qm->vfs_num)
hisi_qm_sriov_disable(pdev, true);
diff --git a/drivers/crypto/img-hash.c b/drivers/crypto/img-hash.c
index 45063693859c..d269036bdaa3 100644
--- a/drivers/crypto/img-hash.c
+++ b/drivers/crypto/img-hash.c
@@ -1043,7 +1043,7 @@ res_err:
return err;
}
-static int img_hash_remove(struct platform_device *pdev)
+static void img_hash_remove(struct platform_device *pdev)
{
struct img_hash_dev *hdev;
@@ -1061,8 +1061,6 @@ static int img_hash_remove(struct platform_device *pdev)
clk_disable_unprepare(hdev->hash_clk);
clk_disable_unprepare(hdev->sys_clk);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1101,7 +1099,7 @@ static const struct dev_pm_ops img_hash_pm_ops = {
static struct platform_driver img_hash_driver = {
.probe = img_hash_probe,
- .remove = img_hash_remove,
+ .remove_new = img_hash_remove,
.driver = {
.name = "img-hash-accelerator",
.pm = &img_hash_pm_ops,
diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c
index 9ff02b5abc4a..76da14af74b5 100644
--- a/drivers/crypto/inside-secure/safexcel.c
+++ b/drivers/crypto/inside-secure/safexcel.c
@@ -1801,7 +1801,7 @@ err_core_clk:
return ret;
}
-static int safexcel_remove(struct platform_device *pdev)
+static void safexcel_remove(struct platform_device *pdev)
{
struct safexcel_crypto_priv *priv = platform_get_drvdata(pdev);
int i;
@@ -1816,8 +1816,6 @@ static int safexcel_remove(struct platform_device *pdev)
irq_set_affinity_hint(priv->ring[i].irq, NULL);
destroy_workqueue(priv->ring[i].workqueue);
}
-
- return 0;
}
static const struct safexcel_priv_data eip97ies_mrvl_data = {
@@ -1874,7 +1872,7 @@ MODULE_DEVICE_TABLE(of, safexcel_of_match_table);
static struct platform_driver crypto_safexcel = {
.probe = safexcel_probe,
- .remove = safexcel_remove,
+ .remove_new = safexcel_remove,
.driver = {
.name = "crypto-safexcel",
.of_match_table = safexcel_of_match_table,
diff --git a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
index 4a18095ae5d8..f8a77bff8844 100644
--- a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
+++ b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
@@ -1563,7 +1563,7 @@ static int ixp_crypto_probe(struct platform_device *_pdev)
return 0;
}
-static int ixp_crypto_remove(struct platform_device *pdev)
+static void ixp_crypto_remove(struct platform_device *pdev)
{
int num = ARRAY_SIZE(ixp4xx_algos);
int i;
@@ -1578,8 +1578,6 @@ static int ixp_crypto_remove(struct platform_device *pdev)
crypto_unregister_skcipher(&ixp4xx_algos[i].crypto);
}
release_ixp_crypto(&pdev->dev);
-
- return 0;
}
static const struct of_device_id ixp4xx_crypto_of_match[] = {
{
@@ -1590,7 +1588,7 @@ static const struct of_device_id ixp4xx_crypto_of_match[] = {
static struct platform_driver ixp_crypto_driver = {
.probe = ixp_crypto_probe,
- .remove = ixp_crypto_remove,
+ .remove_new = ixp_crypto_remove,
.driver = {
.name = "ixp4xx_crypto",
.of_match_table = ixp4xx_crypto_of_match,
diff --git a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c
index 1e2fd9a754ec..9b2d098e5eb2 100644
--- a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c
+++ b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c
@@ -1562,7 +1562,7 @@ static const struct of_device_id kmb_ocs_aes_of_match[] = {
{}
};
-static int kmb_ocs_aes_remove(struct platform_device *pdev)
+static void kmb_ocs_aes_remove(struct platform_device *pdev)
{
struct ocs_aes_dev *aes_dev;
@@ -1575,8 +1575,6 @@ static int kmb_ocs_aes_remove(struct platform_device *pdev)
spin_unlock(&ocs_aes.lock);
crypto_engine_exit(aes_dev->engine);
-
- return 0;
}
static int kmb_ocs_aes_probe(struct platform_device *pdev)
@@ -1658,7 +1656,7 @@ list_del:
/* The OCS driver is a platform device. */
static struct platform_driver kmb_ocs_aes_driver = {
.probe = kmb_ocs_aes_probe,
- .remove = kmb_ocs_aes_remove,
+ .remove_new = kmb_ocs_aes_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = kmb_ocs_aes_of_match,
diff --git a/drivers/crypto/intel/keembay/keembay-ocs-ecc.c b/drivers/crypto/intel/keembay/keembay-ocs-ecc.c
index fb95deed9057..5e24f2d8affc 100644
--- a/drivers/crypto/intel/keembay/keembay-ocs-ecc.c
+++ b/drivers/crypto/intel/keembay/keembay-ocs-ecc.c
@@ -964,7 +964,7 @@ list_del:
return rc;
}
-static int kmb_ocs_ecc_remove(struct platform_device *pdev)
+static void kmb_ocs_ecc_remove(struct platform_device *pdev)
{
struct ocs_ecc_dev *ecc_dev;
@@ -978,8 +978,6 @@ static int kmb_ocs_ecc_remove(struct platform_device *pdev)
spin_unlock(&ocs_ecc.lock);
crypto_engine_exit(ecc_dev->engine);
-
- return 0;
}
/* Device tree driver match. */
@@ -993,7 +991,7 @@ static const struct of_device_id kmb_ocs_ecc_of_match[] = {
/* The OCS driver is a platform device. */
static struct platform_driver kmb_ocs_ecc_driver = {
.probe = kmb_ocs_ecc_probe,
- .remove = kmb_ocs_ecc_remove,
+ .remove_new = kmb_ocs_ecc_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = kmb_ocs_ecc_of_match,
diff --git a/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c b/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c
index daba8ca05dbe..c2dfca73fe4e 100644
--- a/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c
+++ b/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c
@@ -1151,24 +1151,17 @@ static const struct of_device_id kmb_ocs_hcu_of_match[] = {
{}
};
-static int kmb_ocs_hcu_remove(struct platform_device *pdev)
+static void kmb_ocs_hcu_remove(struct platform_device *pdev)
{
- struct ocs_hcu_dev *hcu_dev;
- int rc;
-
- hcu_dev = platform_get_drvdata(pdev);
- if (!hcu_dev)
- return -ENODEV;
+ struct ocs_hcu_dev *hcu_dev = platform_get_drvdata(pdev);
crypto_engine_unregister_ahashes(ocs_hcu_algs, ARRAY_SIZE(ocs_hcu_algs));
- rc = crypto_engine_exit(hcu_dev->engine);
+ crypto_engine_exit(hcu_dev->engine);
spin_lock_bh(&ocs_hcu.lock);
list_del(&hcu_dev->list);
spin_unlock_bh(&ocs_hcu.lock);
-
- return rc;
}
static int kmb_ocs_hcu_probe(struct platform_device *pdev)
@@ -1249,7 +1242,7 @@ list_del:
/* The OCS driver is a platform device. */
static struct platform_driver kmb_ocs_hcu_driver = {
.probe = kmb_ocs_hcu_probe,
- .remove = kmb_ocs_hcu_remove,
+ .remove_new = kmb_ocs_hcu_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = kmb_ocs_hcu_of_match,
diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
index dd4464b7e00b..0faedb5b2eb5 100644
--- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
+++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
@@ -2,17 +2,24 @@
/* Copyright(c) 2020 - 2021 Intel Corporation */
#include <linux/iopoll.h>
#include <adf_accel_devices.h>
+#include <adf_admin.h>
#include <adf_cfg.h>
+#include <adf_cfg_services.h>
#include <adf_clock.h>
#include <adf_common_drv.h>
#include <adf_gen4_dc.h>
#include <adf_gen4_hw_data.h>
#include <adf_gen4_pfvf.h>
#include <adf_gen4_pm.h>
+#include "adf_gen4_ras.h"
#include <adf_gen4_timer.h>
#include "adf_4xxx_hw_data.h"
#include "icp_qat_hw.h"
+#define ADF_AE_GROUP_0 GENMASK(3, 0)
+#define ADF_AE_GROUP_1 GENMASK(7, 4)
+#define ADF_AE_GROUP_2 BIT(8)
+
enum adf_fw_objs {
ADF_FW_SYM_OBJ,
ADF_FW_ASYM_OBJ,
@@ -40,39 +47,45 @@ struct adf_fw_config {
};
static const struct adf_fw_config adf_fw_cy_config[] = {
- {0xF0, ADF_FW_SYM_OBJ},
- {0xF, ADF_FW_ASYM_OBJ},
- {0x100, ADF_FW_ADMIN_OBJ},
+ {ADF_AE_GROUP_1, ADF_FW_SYM_OBJ},
+ {ADF_AE_GROUP_0, ADF_FW_ASYM_OBJ},
+ {ADF_AE_GROUP_2, ADF_FW_ADMIN_OBJ},
};
static const struct adf_fw_config adf_fw_dc_config[] = {
- {0xF0, ADF_FW_DC_OBJ},
- {0xF, ADF_FW_DC_OBJ},
- {0x100, ADF_FW_ADMIN_OBJ},
+ {ADF_AE_GROUP_1, ADF_FW_DC_OBJ},
+ {ADF_AE_GROUP_0, ADF_FW_DC_OBJ},
+ {ADF_AE_GROUP_2, ADF_FW_ADMIN_OBJ},
};
static const struct adf_fw_config adf_fw_sym_config[] = {
- {0xF0, ADF_FW_SYM_OBJ},
- {0xF, ADF_FW_SYM_OBJ},
- {0x100, ADF_FW_ADMIN_OBJ},
+ {ADF_AE_GROUP_1, ADF_FW_SYM_OBJ},
+ {ADF_AE_GROUP_0, ADF_FW_SYM_OBJ},
+ {ADF_AE_GROUP_2, ADF_FW_ADMIN_OBJ},
};
static const struct adf_fw_config adf_fw_asym_config[] = {
- {0xF0, ADF_FW_ASYM_OBJ},
- {0xF, ADF_FW_ASYM_OBJ},
- {0x100, ADF_FW_ADMIN_OBJ},
+ {ADF_AE_GROUP_1, ADF_FW_ASYM_OBJ},
+ {ADF_AE_GROUP_0, ADF_FW_ASYM_OBJ},
+ {ADF_AE_GROUP_2, ADF_FW_ADMIN_OBJ},
};
static const struct adf_fw_config adf_fw_asym_dc_config[] = {
- {0xF0, ADF_FW_ASYM_OBJ},
- {0xF, ADF_FW_DC_OBJ},
- {0x100, ADF_FW_ADMIN_OBJ},
+ {ADF_AE_GROUP_1, ADF_FW_ASYM_OBJ},
+ {ADF_AE_GROUP_0, ADF_FW_DC_OBJ},
+ {ADF_AE_GROUP_2, ADF_FW_ADMIN_OBJ},
};
static const struct adf_fw_config adf_fw_sym_dc_config[] = {
- {0xF0, ADF_FW_SYM_OBJ},
- {0xF, ADF_FW_DC_OBJ},
- {0x100, ADF_FW_ADMIN_OBJ},
+ {ADF_AE_GROUP_1, ADF_FW_SYM_OBJ},
+ {ADF_AE_GROUP_0, ADF_FW_DC_OBJ},
+ {ADF_AE_GROUP_2, ADF_FW_ADMIN_OBJ},
+};
+
+static const struct adf_fw_config adf_fw_dcc_config[] = {
+ {ADF_AE_GROUP_1, ADF_FW_DC_OBJ},
+ {ADF_AE_GROUP_0, ADF_FW_SYM_OBJ},
+ {ADF_AE_GROUP_2, ADF_FW_ADMIN_OBJ},
};
static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_dc_config));
@@ -80,6 +93,7 @@ static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_sym_config));
static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_asym_config));
static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_asym_dc_config));
static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_sym_dc_config));
+static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_dcc_config));
/* Worker thread to service arbiter mappings */
static const u32 default_thrd_to_arb_map[ADF_4XXX_MAX_ACCELENGINES] = {
@@ -94,36 +108,18 @@ static const u32 thrd_to_arb_map_dc[ADF_4XXX_MAX_ACCELENGINES] = {
0x0
};
+static const u32 thrd_to_arb_map_dcc[ADF_4XXX_MAX_ACCELENGINES] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF,
+ 0x0
+};
+
static struct adf_hw_device_class adf_4xxx_class = {
.name = ADF_4XXX_DEVICE_NAME,
.type = DEV_4XXX,
.instances = 0,
};
-enum dev_services {
- SVC_CY = 0,
- SVC_CY2,
- SVC_DC,
- SVC_SYM,
- SVC_ASYM,
- SVC_DC_ASYM,
- SVC_ASYM_DC,
- SVC_DC_SYM,
- SVC_SYM_DC,
-};
-
-static const char *const dev_cfg_services[] = {
- [SVC_CY] = ADF_CFG_CY,
- [SVC_CY2] = ADF_CFG_ASYM_SYM,
- [SVC_DC] = ADF_CFG_DC,
- [SVC_SYM] = ADF_CFG_SYM,
- [SVC_ASYM] = ADF_CFG_ASYM,
- [SVC_DC_ASYM] = ADF_CFG_DC_ASYM,
- [SVC_ASYM_DC] = ADF_CFG_ASYM_DC,
- [SVC_DC_SYM] = ADF_CFG_DC_SYM,
- [SVC_SYM_DC] = ADF_CFG_SYM_DC,
-};
-
static int get_service_enabled(struct adf_accel_dev *accel_dev)
{
char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0};
@@ -137,7 +133,7 @@ static int get_service_enabled(struct adf_accel_dev *accel_dev)
return ret;
}
- ret = match_string(dev_cfg_services, ARRAY_SIZE(dev_cfg_services),
+ ret = match_string(adf_cfg_services, ARRAY_SIZE(adf_cfg_services),
services);
if (ret < 0)
dev_err(&GET_DEV(accel_dev),
@@ -212,6 +208,7 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev)
{
struct pci_dev *pdev = accel_dev->accel_pci_dev.pci_dev;
u32 capabilities_sym, capabilities_asym, capabilities_dc;
+ u32 capabilities_dcc;
u32 fusectl1;
/* Read accelerator capabilities mask */
@@ -284,6 +281,14 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev)
return capabilities_sym | capabilities_asym;
case SVC_DC:
return capabilities_dc;
+ case SVC_DCC:
+ /*
+ * Sym capabilities are available for chaining operations,
+ * but sym crypto instances cannot be supported
+ */
+ capabilities_dcc = capabilities_dc | capabilities_sym;
+ capabilities_dcc &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC;
+ return capabilities_dcc;
case SVC_SYM:
return capabilities_sym;
case SVC_ASYM:
@@ -309,6 +314,8 @@ static const u32 *adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev)
switch (get_service_enabled(accel_dev)) {
case SVC_DC:
return thrd_to_arb_map_dc;
+ case SVC_DCC:
+ return thrd_to_arb_map_dcc;
default:
return default_thrd_to_arb_map;
}
@@ -336,6 +343,24 @@ static u32 get_heartbeat_clock(struct adf_hw_device_data *self)
return ADF_4XXX_KPT_COUNTER_FREQ;
}
+static void adf_init_rl_data(struct adf_rl_hw_data *rl_data)
+{
+ rl_data->pciout_tb_offset = ADF_GEN4_RL_TOKEN_PCIEOUT_BUCKET_OFFSET;
+ rl_data->pciin_tb_offset = ADF_GEN4_RL_TOKEN_PCIEIN_BUCKET_OFFSET;
+ rl_data->r2l_offset = ADF_GEN4_RL_R2L_OFFSET;
+ rl_data->l2c_offset = ADF_GEN4_RL_L2C_OFFSET;
+ rl_data->c2s_offset = ADF_GEN4_RL_C2S_OFFSET;
+
+ rl_data->pcie_scale_div = ADF_4XXX_RL_PCIE_SCALE_FACTOR_DIV;
+ rl_data->pcie_scale_mul = ADF_4XXX_RL_PCIE_SCALE_FACTOR_MUL;
+ rl_data->dcpr_correction = ADF_4XXX_RL_DCPR_CORRECTION;
+ rl_data->max_tp[ADF_SVC_ASYM] = ADF_4XXX_RL_MAX_TP_ASYM;
+ rl_data->max_tp[ADF_SVC_SYM] = ADF_4XXX_RL_MAX_TP_SYM;
+ rl_data->max_tp[ADF_SVC_DC] = ADF_4XXX_RL_MAX_TP_DC;
+ rl_data->scan_interval = ADF_4XXX_RL_SCANS_PER_SEC;
+ rl_data->scale_ref = ADF_4XXX_RL_SLICE_REF;
+}
+
static void adf_enable_error_correction(struct adf_accel_dev *accel_dev)
{
struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_4XXX_PMISC_BAR];
@@ -393,38 +418,96 @@ static u32 uof_get_num_objs(void)
return ARRAY_SIZE(adf_fw_cy_config);
}
-static const char *uof_get_name(struct adf_accel_dev *accel_dev, u32 obj_num,
- const char * const fw_objs[], int num_objs)
+static const struct adf_fw_config *get_fw_config(struct adf_accel_dev *accel_dev)
{
- int id;
-
switch (get_service_enabled(accel_dev)) {
case SVC_CY:
case SVC_CY2:
- id = adf_fw_cy_config[obj_num].obj;
- break;
+ return adf_fw_cy_config;
case SVC_DC:
- id = adf_fw_dc_config[obj_num].obj;
- break;
+ return adf_fw_dc_config;
+ case SVC_DCC:
+ return adf_fw_dcc_config;
case SVC_SYM:
- id = adf_fw_sym_config[obj_num].obj;
- break;
+ return adf_fw_sym_config;
case SVC_ASYM:
- id = adf_fw_asym_config[obj_num].obj;
- break;
+ return adf_fw_asym_config;
case SVC_ASYM_DC:
case SVC_DC_ASYM:
- id = adf_fw_asym_dc_config[obj_num].obj;
- break;
+ return adf_fw_asym_dc_config;
case SVC_SYM_DC:
case SVC_DC_SYM:
- id = adf_fw_sym_dc_config[obj_num].obj;
- break;
+ return adf_fw_sym_dc_config;
default:
- id = -EINVAL;
- break;
+ return NULL;
+ }
+}
+
+enum adf_rp_groups {
+ RP_GROUP_0 = 0,
+ RP_GROUP_1,
+ RP_GROUP_COUNT
+};
+
+static u16 get_ring_to_svc_map(struct adf_accel_dev *accel_dev)
+{
+ enum adf_cfg_service_type rps[RP_GROUP_COUNT];
+ const struct adf_fw_config *fw_config;
+ u16 ring_to_svc_map;
+ int i, j;
+
+ fw_config = get_fw_config(accel_dev);
+ if (!fw_config)
+ return 0;
+
+ for (i = 0; i < RP_GROUP_COUNT; i++) {
+ switch (fw_config[i].ae_mask) {
+ case ADF_AE_GROUP_0:
+ j = RP_GROUP_0;
+ break;
+ case ADF_AE_GROUP_1:
+ j = RP_GROUP_1;
+ break;
+ default:
+ return 0;
+ }
+
+ switch (fw_config[i].obj) {
+ case ADF_FW_SYM_OBJ:
+ rps[j] = SYM;
+ break;
+ case ADF_FW_ASYM_OBJ:
+ rps[j] = ASYM;
+ break;
+ case ADF_FW_DC_OBJ:
+ rps[j] = COMP;
+ break;
+ default:
+ rps[j] = 0;
+ break;
+ }
}
+ ring_to_svc_map = rps[RP_GROUP_0] << ADF_CFG_SERV_RING_PAIR_0_SHIFT |
+ rps[RP_GROUP_1] << ADF_CFG_SERV_RING_PAIR_1_SHIFT |
+ rps[RP_GROUP_0] << ADF_CFG_SERV_RING_PAIR_2_SHIFT |
+ rps[RP_GROUP_1] << ADF_CFG_SERV_RING_PAIR_3_SHIFT;
+
+ return ring_to_svc_map;
+}
+
+static const char *uof_get_name(struct adf_accel_dev *accel_dev, u32 obj_num,
+ const char * const fw_objs[], int num_objs)
+{
+ const struct adf_fw_config *fw_config;
+ int id;
+
+ fw_config = get_fw_config(accel_dev);
+ if (fw_config)
+ id = fw_config[obj_num].obj;
+ else
+ id = -EINVAL;
+
if (id < 0 || id > num_objs)
return NULL;
@@ -447,26 +530,23 @@ static const char *uof_get_name_402xx(struct adf_accel_dev *accel_dev, u32 obj_n
static u32 uof_get_ae_mask(struct adf_accel_dev *accel_dev, u32 obj_num)
{
- switch (get_service_enabled(accel_dev)) {
- case SVC_CY:
- return adf_fw_cy_config[obj_num].ae_mask;
- case SVC_DC:
- return adf_fw_dc_config[obj_num].ae_mask;
- case SVC_CY2:
- return adf_fw_cy_config[obj_num].ae_mask;
- case SVC_SYM:
- return adf_fw_sym_config[obj_num].ae_mask;
- case SVC_ASYM:
- return adf_fw_asym_config[obj_num].ae_mask;
- case SVC_ASYM_DC:
- case SVC_DC_ASYM:
- return adf_fw_asym_dc_config[obj_num].ae_mask;
- case SVC_SYM_DC:
- case SVC_DC_SYM:
- return adf_fw_sym_dc_config[obj_num].ae_mask;
- default:
+ const struct adf_fw_config *fw_config;
+
+ fw_config = get_fw_config(accel_dev);
+ if (!fw_config)
return 0;
- }
+
+ return fw_config[obj_num].ae_mask;
+}
+
+static void adf_gen4_set_err_mask(struct adf_dev_err_mask *dev_err_mask)
+{
+ dev_err_mask->cppagentcmdpar_mask = ADF_4XXX_HICPPAGENTCMDPARERRLOG_MASK;
+ dev_err_mask->parerr_ath_cph_mask = ADF_4XXX_PARITYERRORMASK_ATH_CPH_MASK;
+ dev_err_mask->parerr_cpr_xlt_mask = ADF_4XXX_PARITYERRORMASK_CPR_XLT_MASK;
+ dev_err_mask->parerr_dcpr_ucs_mask = ADF_4XXX_PARITYERRORMASK_DCPR_UCS_MASK;
+ dev_err_mask->parerr_pke_mask = ADF_4XXX_PARITYERRORMASK_PKE_MASK;
+ dev_err_mask->ssmfeatren_mask = ADF_4XXX_SSMFEATREN_MASK;
}
void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id)
@@ -522,6 +602,7 @@ void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id)
hw_data->uof_get_ae_mask = uof_get_ae_mask;
hw_data->set_msix_rttable = set_msix_default_rttable;
hw_data->set_ssm_wdtimer = adf_gen4_set_ssm_wdtimer;
+ hw_data->get_ring_to_svc_map = get_ring_to_svc_map;
hw_data->disable_iov = adf_disable_sriov;
hw_data->ring_pair_reset = adf_gen4_ring_pair_reset;
hw_data->enable_pm = adf_gen4_enable_pm;
@@ -531,10 +612,14 @@ void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id)
hw_data->stop_timer = adf_gen4_timer_stop;
hw_data->get_hb_clock = get_heartbeat_clock;
hw_data->num_hb_ctrs = ADF_NUM_HB_CNT_PER_AE;
+ hw_data->clock_frequency = ADF_4XXX_AE_FREQ;
+ adf_gen4_set_err_mask(&hw_data->dev_err_mask);
adf_gen4_init_hw_csr_ops(&hw_data->csr_ops);
adf_gen4_init_pf_pfvf_ops(&hw_data->pfvf_ops);
adf_gen4_init_dc_ops(&hw_data->dc_ops);
+ adf_gen4_init_ras_ops(&hw_data->ras_ops);
+ adf_init_rl_data(&hw_data->rl_data);
}
void adf_clean_hw_data_4xxx(struct adf_hw_device_data *hw_data)
diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h
index bb3d95a8fb21..33423295e90f 100644
--- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h
+++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h
@@ -28,6 +28,23 @@
#define ADF_4XXX_ACCELENGINES_MASK (0x1FF)
#define ADF_4XXX_ADMIN_AE_MASK (0x100)
+#define ADF_4XXX_HICPPAGENTCMDPARERRLOG_MASK 0x1F
+#define ADF_4XXX_PARITYERRORMASK_ATH_CPH_MASK 0xF000F
+#define ADF_4XXX_PARITYERRORMASK_CPR_XLT_MASK 0x10001
+#define ADF_4XXX_PARITYERRORMASK_DCPR_UCS_MASK 0x30007
+#define ADF_4XXX_PARITYERRORMASK_PKE_MASK 0x3F
+
+/*
+ * SSMFEATREN bit mask
+ * BIT(4) - enables parity detection on CPP
+ * BIT(12) - enables the logging of push/pull data errors
+ * in pperr register
+ * BIT(16) - BIT(23) - enable parity detection on SPPs
+ */
+#define ADF_4XXX_SSMFEATREN_MASK \
+ (BIT(4) | BIT(12) | BIT(16) | BIT(17) | BIT(18) | \
+ BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23))
+
#define ADF_4XXX_ETR_MAX_BANKS 64
/* MSIX interrupt */
@@ -65,8 +82,19 @@
#define ADF_402XX_ASYM_OBJ "qat_402xx_asym.bin"
#define ADF_402XX_ADMIN_OBJ "qat_402xx_admin.bin"
+/* RL constants */
+#define ADF_4XXX_RL_PCIE_SCALE_FACTOR_DIV 100
+#define ADF_4XXX_RL_PCIE_SCALE_FACTOR_MUL 102
+#define ADF_4XXX_RL_DCPR_CORRECTION 1
+#define ADF_4XXX_RL_SCANS_PER_SEC 954
+#define ADF_4XXX_RL_MAX_TP_ASYM 173750UL
+#define ADF_4XXX_RL_MAX_TP_SYM 95000UL
+#define ADF_4XXX_RL_MAX_TP_DC 45000UL
+#define ADF_4XXX_RL_SLICE_REF 1000UL
+
/* Clocks frequency */
-#define ADF_4XXX_KPT_COUNTER_FREQ (100 * HZ_PER_MHZ)
+#define ADF_4XXX_KPT_COUNTER_FREQ (100 * HZ_PER_MHZ)
+#define ADF_4XXX_AE_FREQ (1000 * HZ_PER_MHZ)
/* qat_4xxx fuse bits are different from old GENs, redefine them */
enum icp_qat_4xxx_slice_mask {
diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
index 6d4e2e139ffa..8f483d1197dd 100644
--- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
@@ -11,6 +11,7 @@
#include <adf_heartbeat.h>
#include "adf_4xxx_hw_data.h"
+#include "adf_cfg_services.h"
#include "qat_compression.h"
#include "qat_crypto.h"
#include "adf_transport_access_macros.h"
@@ -23,30 +24,6 @@ static const struct pci_device_id adf_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, adf_pci_tbl);
-enum configs {
- DEV_CFG_CY = 0,
- DEV_CFG_DC,
- DEV_CFG_SYM,
- DEV_CFG_ASYM,
- DEV_CFG_ASYM_SYM,
- DEV_CFG_ASYM_DC,
- DEV_CFG_DC_ASYM,
- DEV_CFG_SYM_DC,
- DEV_CFG_DC_SYM,
-};
-
-static const char * const services_operations[] = {
- ADF_CFG_CY,
- ADF_CFG_DC,
- ADF_CFG_SYM,
- ADF_CFG_ASYM,
- ADF_CFG_ASYM_SYM,
- ADF_CFG_ASYM_DC,
- ADF_CFG_DC_ASYM,
- ADF_CFG_SYM_DC,
- ADF_CFG_DC_SYM,
-};
-
static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
{
if (accel_dev->hw_device) {
@@ -292,16 +269,17 @@ int adf_gen4_dev_config(struct adf_accel_dev *accel_dev)
if (ret)
goto err;
- ret = sysfs_match_string(services_operations, services);
+ ret = sysfs_match_string(adf_cfg_services, services);
if (ret < 0)
goto err;
switch (ret) {
- case DEV_CFG_CY:
- case DEV_CFG_ASYM_SYM:
+ case SVC_CY:
+ case SVC_CY2:
ret = adf_crypto_dev_config(accel_dev);
break;
- case DEV_CFG_DC:
+ case SVC_DC:
+ case SVC_DCC:
ret = adf_comp_dev_config(accel_dev);
break;
default:
@@ -440,6 +418,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_err;
}
+ accel_dev->ras_errors.enabled = true;
adf_dbgfs_init(accel_dev);
ret = adf_dev_up(accel_dev, true);
@@ -489,3 +468,4 @@ MODULE_FIRMWARE(ADF_4XXX_MMP);
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
MODULE_SOFTDEP("pre: crypto-intel_qat");
+MODULE_IMPORT_NS(CRYPTO_QAT);
diff --git a/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c b/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c
index 9c00c441b602..a882e0ea2279 100644
--- a/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c
+++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
/* Copyright(c) 2014 - 2021 Intel Corporation */
#include <adf_accel_devices.h>
+#include <adf_admin.h>
#include <adf_clock.h>
#include <adf_common_drv.h>
#include <adf_gen2_config.h>
diff --git a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c
index 468c9102093f..956a4c85609a 100644
--- a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c
@@ -252,3 +252,4 @@ MODULE_FIRMWARE(ADF_C3XXX_FW);
MODULE_FIRMWARE(ADF_C3XXX_MMP);
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
+MODULE_IMPORT_NS(CRYPTO_QAT);
diff --git a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c
index d5a0ecca9d0b..a8de9cd09c05 100644
--- a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c
@@ -226,3 +226,4 @@ MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Intel");
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
+MODULE_IMPORT_NS(CRYPTO_QAT);
diff --git a/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c b/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c
index 355a781693eb..48cf3eb7c734 100644
--- a/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c
+++ b/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
/* Copyright(c) 2014 - 2021 Intel Corporation */
#include <adf_accel_devices.h>
+#include <adf_admin.h>
#include <adf_clock.h>
#include <adf_common_drv.h>
#include <adf_gen2_config.h>
diff --git a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c
index 0186921be936..ad0ca4384998 100644
--- a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c
@@ -252,3 +252,4 @@ MODULE_FIRMWARE(ADF_C62X_FW);
MODULE_FIRMWARE(ADF_C62X_MMP);
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
+MODULE_IMPORT_NS(CRYPTO_QAT);
diff --git a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c
index c9ae6c0d0dca..53b8ddb63364 100644
--- a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c
@@ -226,3 +226,4 @@ MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Intel");
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
+MODULE_IMPORT_NS(CRYPTO_QAT);
diff --git a/drivers/crypto/intel/qat/qat_common/Makefile b/drivers/crypto/intel/qat/qat_common/Makefile
index 43622c7fca71..779a8aa0b8d2 100644
--- a/drivers/crypto/intel/qat/qat_common/Makefile
+++ b/drivers/crypto/intel/qat/qat_common/Makefile
@@ -1,8 +1,10 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CRYPTO_DEV_QAT) += intel_qat.o
+ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=CRYPTO_QAT
intel_qat-objs := adf_cfg.o \
adf_isr.o \
adf_ctl_drv.o \
+ adf_cfg_services.o \
adf_dev_mgr.o \
adf_init.o \
adf_accel_engine.o \
@@ -11,12 +13,14 @@ intel_qat-objs := adf_cfg.o \
adf_admin.o \
adf_hw_arbiter.o \
adf_sysfs.o \
+ adf_sysfs_ras_counters.o \
adf_gen2_hw_data.o \
adf_gen2_config.o \
adf_gen4_hw_data.o \
adf_gen4_pm.o \
adf_gen2_dc.o \
adf_gen4_dc.o \
+ adf_gen4_ras.o \
adf_gen4_timer.o \
adf_clock.o \
qat_crypto.o \
@@ -25,14 +29,20 @@ intel_qat-objs := adf_cfg.o \
qat_algs.o \
qat_asym_algs.o \
qat_algs_send.o \
+ adf_rl.o \
+ adf_rl_admin.o \
+ adf_sysfs_rl.o \
qat_uclo.o \
qat_hal.o \
qat_bl.o
intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o \
adf_fw_counters.o \
+ adf_cnv_dbgfs.o \
+ adf_gen4_pm_debugfs.o \
adf_heartbeat.o \
adf_heartbeat_dbgfs.o \
+ adf_pm_dbgfs.o \
adf_dbgfs.o
intel_qat-$(CONFIG_PCI_IOV) += adf_sriov.o adf_vf_isr.o adf_pfvf_utils.o \
diff --git a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h
index e57abde66f4f..4ff5729a3496 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h
@@ -7,7 +7,9 @@
#include <linux/list.h>
#include <linux/io.h>
#include <linux/ratelimit.h>
+#include <linux/types.h>
#include "adf_cfg_common.h"
+#include "adf_rl.h"
#include "adf_pfvf_msg.h"
#define ADF_DH895XCC_DEVICE_NAME "dh895xcc"
@@ -29,7 +31,7 @@
#define ADF_PCI_MAX_BARS 3
#define ADF_DEVICE_NAME_LENGTH 32
#define ADF_ETR_MAX_RINGS_PER_BANK 16
-#define ADF_MAX_MSIX_VECTOR_NAME 16
+#define ADF_MAX_MSIX_VECTOR_NAME 48
#define ADF_DEVICE_NAME_PREFIX "qat_"
enum adf_accel_capabilities {
@@ -81,6 +83,18 @@ enum dev_sku_info {
DEV_SKU_UNKNOWN,
};
+enum ras_errors {
+ ADF_RAS_CORR,
+ ADF_RAS_UNCORR,
+ ADF_RAS_FATAL,
+ ADF_RAS_ERRORS,
+};
+
+struct adf_error_counters {
+ atomic_t counter[ADF_RAS_ERRORS];
+ bool enabled;
+};
+
static inline const char *get_sku_info(enum dev_sku_info info)
{
switch (info) {
@@ -152,6 +166,13 @@ struct adf_accel_dev;
struct adf_etr_data;
struct adf_etr_ring_data;
+struct adf_ras_ops {
+ void (*enable_ras_errors)(struct adf_accel_dev *accel_dev);
+ void (*disable_ras_errors)(struct adf_accel_dev *accel_dev);
+ bool (*handle_interrupt)(struct adf_accel_dev *accel_dev,
+ bool *reset_required);
+};
+
struct adf_pfvf_ops {
int (*enable_comms)(struct adf_accel_dev *accel_dev);
u32 (*get_pf2vf_offset)(u32 i);
@@ -169,6 +190,16 @@ struct adf_dc_ops {
void (*build_deflate_ctx)(void *ctx);
};
+struct adf_dev_err_mask {
+ u32 cppagentcmdpar_mask;
+ u32 parerr_ath_cph_mask;
+ u32 parerr_cpr_xlt_mask;
+ u32 parerr_dcpr_ucs_mask;
+ u32 parerr_pke_mask;
+ u32 parerr_wat_wcp_mask;
+ u32 ssmfeatren_mask;
+};
+
struct adf_hw_device_data {
struct adf_hw_device_class *dev_class;
u32 (*get_accel_mask)(struct adf_hw_device_data *self);
@@ -182,6 +213,7 @@ struct adf_hw_device_data {
void (*get_arb_info)(struct arb_info *arb_csrs_info);
void (*get_admin_info)(struct admin_info *admin_csrs_info);
enum dev_sku_info (*get_sku)(struct adf_hw_device_data *self);
+ u16 (*get_ring_to_svc_map)(struct adf_accel_dev *accel_dev);
int (*alloc_irq)(struct adf_accel_dev *accel_dev);
void (*free_irq)(struct adf_accel_dev *accel_dev);
void (*enable_error_correction)(struct adf_accel_dev *accel_dev);
@@ -214,12 +246,16 @@ struct adf_hw_device_data {
struct adf_pfvf_ops pfvf_ops;
struct adf_hw_csr_ops csr_ops;
struct adf_dc_ops dc_ops;
+ struct adf_ras_ops ras_ops;
+ struct adf_dev_err_mask dev_err_mask;
+ struct adf_rl_hw_data rl_data;
const char *fw_name;
const char *fw_mmp_name;
u32 fuses;
u32 straps;
u32 accel_capabilities_mask;
u32 extended_dc_capabilities;
+ u16 fw_capabilities;
u32 clock_frequency;
u32 instance_id;
u16 accel_mask;
@@ -262,6 +298,7 @@ struct adf_hw_device_data {
#define GET_SRV_TYPE(accel_dev, idx) \
(((GET_HW_DATA(accel_dev)->ring_to_svc_map) >> (ADF_SRV_TYPE_BIT_LEN * (idx))) \
& ADF_SRV_TYPE_MASK)
+#define GET_ERR_MASK(accel_dev) (&GET_HW_DATA(accel_dev)->dev_err_mask)
#define GET_MAX_ACCELENGINES(accel_dev) (GET_HW_DATA(accel_dev)->num_engines)
#define GET_CSR_OPS(accel_dev) (&(accel_dev)->hw_device->csr_ops)
#define GET_PFVF_OPS(accel_dev) (&(accel_dev)->hw_device->pfvf_ops)
@@ -291,6 +328,23 @@ struct adf_dc_data {
dma_addr_t ovf_buff_p;
};
+struct adf_pm {
+ struct dentry *debugfs_pm_status;
+ bool present;
+ int idle_irq_counters;
+ int throttle_irq_counters;
+ int fw_irq_counters;
+ int host_ack_counter;
+ int host_nack_counter;
+ ssize_t (*print_pm_status)(struct adf_accel_dev *accel_dev,
+ char __user *buf, size_t count, loff_t *pos);
+};
+
+struct adf_sysfs {
+ int ring_num;
+ struct rw_semaphore lock; /* protects access to the fields in this struct */
+};
+
struct adf_accel_dev {
struct adf_etr_data *transport;
struct adf_hw_device_data *hw_device;
@@ -298,17 +352,21 @@ struct adf_accel_dev {
struct adf_fw_loader_data *fw_loader;
struct adf_admin_comms *admin;
struct adf_dc_data *dc_data;
+ struct adf_pm power_management;
struct list_head crypto_list;
struct list_head compression_list;
unsigned long status;
atomic_t ref_count;
struct dentry *debugfs_dir;
struct dentry *fw_cntr_dbgfile;
+ struct dentry *cnv_dbgfile;
struct list_head list;
struct module *owner;
struct adf_accel_pci accel_pci_dev;
struct adf_timer *timer;
struct adf_heartbeat *heartbeat;
+ struct adf_rl *rate_limiting;
+ struct adf_sysfs sysfs;
union {
struct {
/* protects VF2PF interrupts access */
@@ -326,6 +384,7 @@ struct adf_accel_dev {
u8 pf_compat_ver;
} vf;
};
+ struct adf_error_counters ras_errors;
struct mutex state_lock; /* protect state of the device */
bool is_vf;
u32 accel_id;
diff --git a/drivers/crypto/intel/qat/qat_common/adf_admin.c b/drivers/crypto/intel/qat/qat_common/adf_admin.c
index ff790823b868..54b673ec2362 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_admin.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_admin.c
@@ -7,7 +7,9 @@
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include "adf_accel_devices.h"
+#include "adf_admin.h"
#include "adf_common_drv.h"
+#include "adf_cfg.h"
#include "adf_heartbeat.h"
#include "icp_qat_fw_init_admin.h"
@@ -212,6 +214,17 @@ int adf_get_fw_timestamp(struct adf_accel_dev *accel_dev, u64 *timestamp)
return 0;
}
+static int adf_set_chaining(struct adf_accel_dev *accel_dev)
+{
+ u32 ae_mask = GET_HW_DATA(accel_dev)->ae_mask;
+ struct icp_qat_fw_init_admin_resp resp = { };
+ struct icp_qat_fw_init_admin_req req = { };
+
+ req.cmd_id = ICP_QAT_FW_DC_CHAIN_INIT;
+
+ return adf_send_admin(accel_dev, &req, &resp, ae_mask);
+}
+
static int adf_get_dc_capabilities(struct adf_accel_dev *accel_dev,
u32 *capabilities)
{
@@ -284,6 +297,86 @@ int adf_send_admin_hb_timer(struct adf_accel_dev *accel_dev, uint32_t ticks)
return adf_send_admin(accel_dev, &req, &resp, ae_mask);
}
+static bool is_dcc_enabled(struct adf_accel_dev *accel_dev)
+{
+ char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0};
+ int ret;
+
+ ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
+ ADF_SERVICES_ENABLED, services);
+ if (ret)
+ return false;
+
+ return !strcmp(services, "dcc");
+}
+
+static int adf_get_fw_capabilities(struct adf_accel_dev *accel_dev, u16 *caps)
+{
+ u32 ae_mask = accel_dev->hw_device->admin_ae_mask;
+ struct icp_qat_fw_init_admin_resp resp = { };
+ struct icp_qat_fw_init_admin_req req = { };
+ int ret;
+
+ if (!ae_mask)
+ return 0;
+
+ req.cmd_id = ICP_QAT_FW_CAPABILITIES_GET;
+ ret = adf_send_admin(accel_dev, &req, &resp, ae_mask);
+ if (ret)
+ return ret;
+
+ *caps = resp.fw_capabilities;
+
+ return 0;
+}
+
+int adf_send_admin_rl_init(struct adf_accel_dev *accel_dev,
+ struct icp_qat_fw_init_admin_slice_cnt *slices)
+{
+ u32 ae_mask = accel_dev->hw_device->admin_ae_mask;
+ struct icp_qat_fw_init_admin_resp resp = { };
+ struct icp_qat_fw_init_admin_req req = { };
+ int ret;
+
+ req.cmd_id = ICP_QAT_FW_RL_INIT;
+
+ ret = adf_send_admin(accel_dev, &req, &resp, ae_mask);
+ if (ret)
+ return ret;
+
+ memcpy(slices, &resp.slices, sizeof(*slices));
+
+ return 0;
+}
+
+int adf_send_admin_rl_add_update(struct adf_accel_dev *accel_dev,
+ struct icp_qat_fw_init_admin_req *req)
+{
+ u32 ae_mask = accel_dev->hw_device->admin_ae_mask;
+ struct icp_qat_fw_init_admin_resp resp = { };
+
+ /*
+ * req struct filled in rl implementation. Used commands
+ * ICP_QAT_FW_RL_ADD for a new SLA
+ * ICP_QAT_FW_RL_UPDATE for update SLA
+ */
+ return adf_send_admin(accel_dev, req, &resp, ae_mask);
+}
+
+int adf_send_admin_rl_delete(struct adf_accel_dev *accel_dev, u16 node_id,
+ u8 node_type)
+{
+ u32 ae_mask = accel_dev->hw_device->admin_ae_mask;
+ struct icp_qat_fw_init_admin_resp resp = { };
+ struct icp_qat_fw_init_admin_req req = { };
+
+ req.cmd_id = ICP_QAT_FW_RL_REMOVE;
+ req.node_id = node_id;
+ req.node_type = node_type;
+
+ return adf_send_admin(accel_dev, &req, &resp, ae_mask);
+}
+
/**
* adf_send_admin_init() - Function sends init message to FW
* @accel_dev: Pointer to acceleration device.
@@ -294,9 +387,20 @@ int adf_send_admin_hb_timer(struct adf_accel_dev *accel_dev, uint32_t ticks)
*/
int adf_send_admin_init(struct adf_accel_dev *accel_dev)
{
+ struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
u32 dc_capabilities = 0;
int ret;
+ ret = adf_set_fw_constants(accel_dev);
+ if (ret)
+ return ret;
+
+ if (is_dcc_enabled(accel_dev)) {
+ ret = adf_set_chaining(accel_dev);
+ if (ret)
+ return ret;
+ }
+
ret = adf_get_dc_capabilities(accel_dev, &dc_capabilities);
if (ret) {
dev_err(&GET_DEV(accel_dev), "Cannot get dc capabilities\n");
@@ -304,9 +408,7 @@ int adf_send_admin_init(struct adf_accel_dev *accel_dev)
}
accel_dev->hw_device->extended_dc_capabilities = dc_capabilities;
- ret = adf_set_fw_constants(accel_dev);
- if (ret)
- return ret;
+ adf_get_fw_capabilities(accel_dev, &hw_data->fw_capabilities);
return adf_init_ae(accel_dev);
}
@@ -348,6 +450,54 @@ int adf_init_admin_pm(struct adf_accel_dev *accel_dev, u32 idle_delay)
return adf_send_admin(accel_dev, &req, &resp, ae_mask);
}
+int adf_get_pm_info(struct adf_accel_dev *accel_dev, dma_addr_t p_state_addr,
+ size_t buff_size)
+{
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ struct icp_qat_fw_init_admin_req req = { };
+ struct icp_qat_fw_init_admin_resp resp;
+ u32 ae_mask = hw_data->admin_ae_mask;
+ int ret;
+
+ /* Query pm info via init/admin cmd */
+ if (!accel_dev->admin) {
+ dev_err(&GET_DEV(accel_dev), "adf_admin is not available\n");
+ return -EFAULT;
+ }
+
+ req.cmd_id = ICP_QAT_FW_PM_INFO;
+ req.init_cfg_sz = buff_size;
+ req.init_cfg_ptr = p_state_addr;
+
+ ret = adf_send_admin(accel_dev, &req, &resp, ae_mask);
+ if (ret)
+ dev_err(&GET_DEV(accel_dev),
+ "Failed to query power-management info\n");
+
+ return ret;
+}
+
+int adf_get_cnv_stats(struct adf_accel_dev *accel_dev, u16 ae, u16 *err_cnt,
+ u16 *latest_err)
+{
+ struct icp_qat_fw_init_admin_req req = { };
+ struct icp_qat_fw_init_admin_resp resp;
+ int ret;
+
+ req.cmd_id = ICP_QAT_FW_CNV_STATS_GET;
+
+ ret = adf_put_admin_msg_sync(accel_dev, ae, &req, &resp);
+ if (ret)
+ return ret;
+ if (resp.status)
+ return -EPROTONOSUPPORT;
+
+ *err_cnt = resp.error_count;
+ *latest_err = resp.latest_error;
+
+ return ret;
+}
+
int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
{
struct adf_admin_comms *admin;
diff --git a/drivers/crypto/intel/qat/qat_common/adf_admin.h b/drivers/crypto/intel/qat/qat_common/adf_admin.h
new file mode 100644
index 000000000000..55cbcbc66c9f
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_admin.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Intel Corporation */
+#ifndef ADF_ADMIN
+#define ADF_ADMIN
+
+#include "icp_qat_fw_init_admin.h"
+
+struct adf_accel_dev;
+
+int adf_init_admin_comms(struct adf_accel_dev *accel_dev);
+void adf_exit_admin_comms(struct adf_accel_dev *accel_dev);
+int adf_send_admin_init(struct adf_accel_dev *accel_dev);
+int adf_get_ae_fw_counters(struct adf_accel_dev *accel_dev, u16 ae, u64 *reqs, u64 *resps);
+int adf_init_admin_pm(struct adf_accel_dev *accel_dev, u32 idle_delay);
+int adf_send_admin_tim_sync(struct adf_accel_dev *accel_dev, u32 cnt);
+int adf_send_admin_hb_timer(struct adf_accel_dev *accel_dev, uint32_t ticks);
+int adf_send_admin_rl_init(struct adf_accel_dev *accel_dev,
+ struct icp_qat_fw_init_admin_slice_cnt *slices);
+int adf_send_admin_rl_add_update(struct adf_accel_dev *accel_dev,
+ struct icp_qat_fw_init_admin_req *req);
+int adf_send_admin_rl_delete(struct adf_accel_dev *accel_dev, u16 node_id,
+ u8 node_type);
+int adf_get_fw_timestamp(struct adf_accel_dev *accel_dev, u64 *timestamp);
+int adf_get_pm_info(struct adf_accel_dev *accel_dev, dma_addr_t p_state_addr, size_t buff_size);
+int adf_get_cnv_stats(struct adf_accel_dev *accel_dev, u16 ae, u16 *err_cnt, u16 *latest_err);
+
+#endif
diff --git a/drivers/crypto/intel/qat/qat_common/adf_aer.c b/drivers/crypto/intel/qat/qat_common/adf_aer.c
index 04af32a2811c..a39e70bd4b21 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_aer.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_aer.c
@@ -92,7 +92,8 @@ static void adf_device_reset_worker(struct work_struct *work)
if (adf_dev_restart(accel_dev)) {
/* The device hanged and we can't restart it so stop here */
dev_err(&GET_DEV(accel_dev), "Restart device failed\n");
- kfree(reset_data);
+ if (reset_data->mode == ADF_DEV_RESET_ASYNC)
+ kfree(reset_data);
WARN(1, "QAT: device restart failed. Device is unusable\n");
return;
}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c
new file mode 100644
index 000000000000..8e13fe938959
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Intel Corporation */
+
+#include <linux/export.h>
+#include "adf_cfg_services.h"
+#include "adf_cfg_strings.h"
+
+const char *const adf_cfg_services[] = {
+ [SVC_CY] = ADF_CFG_CY,
+ [SVC_CY2] = ADF_CFG_ASYM_SYM,
+ [SVC_DC] = ADF_CFG_DC,
+ [SVC_DCC] = ADF_CFG_DCC,
+ [SVC_SYM] = ADF_CFG_SYM,
+ [SVC_ASYM] = ADF_CFG_ASYM,
+ [SVC_DC_ASYM] = ADF_CFG_DC_ASYM,
+ [SVC_ASYM_DC] = ADF_CFG_ASYM_DC,
+ [SVC_DC_SYM] = ADF_CFG_DC_SYM,
+ [SVC_SYM_DC] = ADF_CFG_SYM_DC,
+};
+EXPORT_SYMBOL_GPL(adf_cfg_services);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_services.h b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.h
new file mode 100644
index 000000000000..f78fd697b4be
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Intel Corporation */
+#ifndef _ADF_CFG_SERVICES_H_
+#define _ADF_CFG_SERVICES_H_
+
+#include "adf_cfg_strings.h"
+
+enum adf_services {
+ SVC_CY = 0,
+ SVC_CY2,
+ SVC_DC,
+ SVC_DCC,
+ SVC_SYM,
+ SVC_ASYM,
+ SVC_DC_ASYM,
+ SVC_ASYM_DC,
+ SVC_DC_SYM,
+ SVC_SYM_DC,
+ SVC_COUNT
+};
+
+extern const char *const adf_cfg_services[SVC_COUNT];
+
+#endif
diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h b/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h
index 6066dc637352..322b76903a73 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h
@@ -32,6 +32,7 @@
#define ADF_CFG_DC_ASYM "dc;asym"
#define ADF_CFG_SYM_DC "sym;dc"
#define ADF_CFG_DC_SYM "dc;sym"
+#define ADF_CFG_DCC "dcc"
#define ADF_SERVICES_ENABLED "ServicesEnabled"
#define ADF_PM_IDLE_SUPPORT "PmIdleSupport"
#define ADF_ETRMGR_COALESCING_ENABLED "InterruptCoalescingEnabled"
diff --git a/drivers/crypto/intel/qat/qat_common/adf_clock.c b/drivers/crypto/intel/qat/qat_common/adf_clock.c
index dc0778691eb0..01e0a389e462 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_clock.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_clock.c
@@ -10,6 +10,7 @@
#include <linux/types.h>
#include <linux/units.h>
#include <asm/errno.h>
+#include "adf_admin.h"
#include "adf_accel_devices.h"
#include "adf_clock.h"
#include "adf_common_drv.h"
diff --git a/drivers/crypto/intel/qat/qat_common/adf_cnv_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_cnv_dbgfs.c
new file mode 100644
index 000000000000..07119c487da0
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_cnv_dbgfs.c
@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Intel Corporation */
+
+#include <linux/bitfield.h>
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+
+#include "adf_accel_devices.h"
+#include "adf_admin.h"
+#include "adf_common_drv.h"
+#include "adf_cnv_dbgfs.h"
+#include "qat_compression.h"
+
+#define CNV_DEBUGFS_FILENAME "cnv_errors"
+#define CNV_MIN_PADDING 16
+
+#define CNV_ERR_INFO_MASK GENMASK(11, 0)
+#define CNV_ERR_TYPE_MASK GENMASK(15, 12)
+#define CNV_SLICE_ERR_MASK GENMASK(7, 0)
+#define CNV_SLICE_ERR_SIGN_BIT_INDEX 7
+#define CNV_DELTA_ERR_SIGN_BIT_INDEX 11
+
+enum cnv_error_type {
+ CNV_ERR_TYPE_NONE,
+ CNV_ERR_TYPE_CHECKSUM,
+ CNV_ERR_TYPE_DECOMP_PRODUCED_LENGTH,
+ CNV_ERR_TYPE_DECOMPRESSION,
+ CNV_ERR_TYPE_TRANSLATION,
+ CNV_ERR_TYPE_DECOMP_CONSUMED_LENGTH,
+ CNV_ERR_TYPE_UNKNOWN,
+ CNV_ERR_TYPES_COUNT
+};
+
+#define CNV_ERROR_TYPE_GET(latest_err) \
+ min_t(u16, u16_get_bits(latest_err, CNV_ERR_TYPE_MASK), CNV_ERR_TYPE_UNKNOWN)
+
+#define CNV_GET_DELTA_ERR_INFO(latest_error) \
+ sign_extend32(latest_error, CNV_DELTA_ERR_SIGN_BIT_INDEX)
+
+#define CNV_GET_SLICE_ERR_INFO(latest_error) \
+ sign_extend32(latest_error, CNV_SLICE_ERR_SIGN_BIT_INDEX)
+
+#define CNV_GET_DEFAULT_ERR_INFO(latest_error) \
+ u16_get_bits(latest_error, CNV_ERR_INFO_MASK)
+
+enum cnv_fields {
+ CNV_ERR_COUNT,
+ CNV_LATEST_ERR,
+ CNV_FIELDS_COUNT
+};
+
+static const char * const cnv_field_names[CNV_FIELDS_COUNT] = {
+ [CNV_ERR_COUNT] = "Total Errors",
+ [CNV_LATEST_ERR] = "Last Error",
+};
+
+static const char * const cnv_error_names[CNV_ERR_TYPES_COUNT] = {
+ [CNV_ERR_TYPE_NONE] = "No Error",
+ [CNV_ERR_TYPE_CHECKSUM] = "Checksum Error",
+ [CNV_ERR_TYPE_DECOMP_PRODUCED_LENGTH] = "Length Error-P",
+ [CNV_ERR_TYPE_DECOMPRESSION] = "Decomp Error",
+ [CNV_ERR_TYPE_TRANSLATION] = "Xlat Error",
+ [CNV_ERR_TYPE_DECOMP_CONSUMED_LENGTH] = "Length Error-C",
+ [CNV_ERR_TYPE_UNKNOWN] = "Unknown Error",
+};
+
+struct ae_cnv_errors {
+ u16 ae;
+ u16 err_cnt;
+ u16 latest_err;
+ bool is_comp_ae;
+};
+
+struct cnv_err_stats {
+ u16 ae_count;
+ struct ae_cnv_errors ae_cnv_errors[];
+};
+
+static s16 get_err_info(u8 error_type, u16 latest)
+{
+ switch (error_type) {
+ case CNV_ERR_TYPE_DECOMP_PRODUCED_LENGTH:
+ case CNV_ERR_TYPE_DECOMP_CONSUMED_LENGTH:
+ return CNV_GET_DELTA_ERR_INFO(latest);
+ case CNV_ERR_TYPE_DECOMPRESSION:
+ case CNV_ERR_TYPE_TRANSLATION:
+ return CNV_GET_SLICE_ERR_INFO(latest);
+ default:
+ return CNV_GET_DEFAULT_ERR_INFO(latest);
+ }
+}
+
+static void *qat_cnv_errors_seq_start(struct seq_file *sfile, loff_t *pos)
+{
+ struct cnv_err_stats *err_stats = sfile->private;
+
+ if (*pos == 0)
+ return SEQ_START_TOKEN;
+
+ if (*pos > err_stats->ae_count)
+ return NULL;
+
+ return &err_stats->ae_cnv_errors[*pos - 1];
+}
+
+static void *qat_cnv_errors_seq_next(struct seq_file *sfile, void *v,
+ loff_t *pos)
+{
+ struct cnv_err_stats *err_stats = sfile->private;
+
+ (*pos)++;
+
+ if (*pos > err_stats->ae_count)
+ return NULL;
+
+ return &err_stats->ae_cnv_errors[*pos - 1];
+}
+
+static void qat_cnv_errors_seq_stop(struct seq_file *sfile, void *v)
+{
+}
+
+static int qat_cnv_errors_seq_show(struct seq_file *sfile, void *v)
+{
+ struct ae_cnv_errors *ae_errors;
+ unsigned int i;
+ s16 err_info;
+ u8 err_type;
+
+ if (v == SEQ_START_TOKEN) {
+ seq_puts(sfile, "AE ");
+ for (i = 0; i < CNV_FIELDS_COUNT; ++i)
+ seq_printf(sfile, " %*s", CNV_MIN_PADDING,
+ cnv_field_names[i]);
+ } else {
+ ae_errors = v;
+
+ if (!ae_errors->is_comp_ae)
+ return 0;
+
+ err_type = CNV_ERROR_TYPE_GET(ae_errors->latest_err);
+ err_info = get_err_info(err_type, ae_errors->latest_err);
+
+ seq_printf(sfile, "%d:", ae_errors->ae);
+ seq_printf(sfile, " %*d", CNV_MIN_PADDING, ae_errors->err_cnt);
+ seq_printf(sfile, "%*s [%d]", CNV_MIN_PADDING,
+ cnv_error_names[err_type], err_info);
+ }
+ seq_putc(sfile, '\n');
+
+ return 0;
+}
+
+static const struct seq_operations qat_cnv_errors_sops = {
+ .start = qat_cnv_errors_seq_start,
+ .next = qat_cnv_errors_seq_next,
+ .stop = qat_cnv_errors_seq_stop,
+ .show = qat_cnv_errors_seq_show,
+};
+
+/**
+ * cnv_err_stats_alloc() - Get CNV stats for the provided device.
+ * @accel_dev: Pointer to a QAT acceleration device
+ *
+ * Allocates and populates table of CNV errors statistics for each non-admin AE
+ * available through the supplied acceleration device. The caller becomes the
+ * owner of such memory and is responsible for the deallocation through a call
+ * to kfree().
+ *
+ * Returns: a pointer to a dynamically allocated struct cnv_err_stats on success
+ * or a negative value on error.
+ */
+static struct cnv_err_stats *cnv_err_stats_alloc(struct adf_accel_dev *accel_dev)
+{
+ struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
+ struct cnv_err_stats *err_stats;
+ unsigned long ae_count;
+ unsigned long ae_mask;
+ size_t err_stats_size;
+ unsigned long ae;
+ unsigned int i;
+ u16 latest_err;
+ u16 err_cnt;
+ int ret;
+
+ if (!adf_dev_started(accel_dev)) {
+ dev_err(&GET_DEV(accel_dev), "QAT Device not started\n");
+ return ERR_PTR(-EBUSY);
+ }
+
+ /* Ignore the admin AEs */
+ ae_mask = hw_data->ae_mask & ~hw_data->admin_ae_mask;
+ ae_count = hweight_long(ae_mask);
+ if (unlikely(!ae_count))
+ return ERR_PTR(-EINVAL);
+
+ err_stats_size = struct_size(err_stats, ae_cnv_errors, ae_count);
+ err_stats = kmalloc(err_stats_size, GFP_KERNEL);
+ if (!err_stats)
+ return ERR_PTR(-ENOMEM);
+
+ err_stats->ae_count = ae_count;
+
+ i = 0;
+ for_each_set_bit(ae, &ae_mask, GET_MAX_ACCELENGINES(accel_dev)) {
+ ret = adf_get_cnv_stats(accel_dev, ae, &err_cnt, &latest_err);
+ if (ret) {
+ dev_dbg(&GET_DEV(accel_dev),
+ "Failed to get CNV stats for ae %ld, [%d].\n",
+ ae, ret);
+ err_stats->ae_cnv_errors[i++].is_comp_ae = false;
+ continue;
+ }
+ err_stats->ae_cnv_errors[i].is_comp_ae = true;
+ err_stats->ae_cnv_errors[i].latest_err = latest_err;
+ err_stats->ae_cnv_errors[i].err_cnt = err_cnt;
+ err_stats->ae_cnv_errors[i].ae = ae;
+ i++;
+ }
+
+ return err_stats;
+}
+
+static int qat_cnv_errors_file_open(struct inode *inode, struct file *file)
+{
+ struct adf_accel_dev *accel_dev = inode->i_private;
+ struct seq_file *cnv_errors_seq_file;
+ struct cnv_err_stats *cnv_err_stats;
+ int ret;
+
+ cnv_err_stats = cnv_err_stats_alloc(accel_dev);
+ if (IS_ERR(cnv_err_stats))
+ return PTR_ERR(cnv_err_stats);
+
+ ret = seq_open(file, &qat_cnv_errors_sops);
+ if (unlikely(ret)) {
+ kfree(cnv_err_stats);
+ return ret;
+ }
+
+ cnv_errors_seq_file = file->private_data;
+ cnv_errors_seq_file->private = cnv_err_stats;
+ return ret;
+}
+
+static int qat_cnv_errors_file_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *cnv_errors_seq_file = file->private_data;
+
+ kfree(cnv_errors_seq_file->private);
+ cnv_errors_seq_file->private = NULL;
+
+ return seq_release(inode, file);
+}
+
+static const struct file_operations qat_cnv_fops = {
+ .owner = THIS_MODULE,
+ .open = qat_cnv_errors_file_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = qat_cnv_errors_file_release,
+};
+
+static ssize_t no_comp_file_read(struct file *f, char __user *buf, size_t count,
+ loff_t *pos)
+{
+ char *file_msg = "No engine configured for comp\n";
+
+ return simple_read_from_buffer(buf, count, pos, file_msg,
+ strlen(file_msg));
+}
+
+static const struct file_operations qat_cnv_no_comp_fops = {
+ .owner = THIS_MODULE,
+ .read = no_comp_file_read,
+};
+
+void adf_cnv_dbgfs_add(struct adf_accel_dev *accel_dev)
+{
+ const struct file_operations *fops;
+ void *data;
+
+ if (adf_hw_dev_has_compression(accel_dev)) {
+ fops = &qat_cnv_fops;
+ data = accel_dev;
+ } else {
+ fops = &qat_cnv_no_comp_fops;
+ data = NULL;
+ }
+
+ accel_dev->cnv_dbgfile = debugfs_create_file(CNV_DEBUGFS_FILENAME, 0400,
+ accel_dev->debugfs_dir,
+ data, fops);
+}
+
+void adf_cnv_dbgfs_rm(struct adf_accel_dev *accel_dev)
+{
+ debugfs_remove(accel_dev->cnv_dbgfile);
+ accel_dev->cnv_dbgfile = NULL;
+}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_cnv_dbgfs.h b/drivers/crypto/intel/qat/qat_common/adf_cnv_dbgfs.h
new file mode 100644
index 000000000000..b02b0961c433
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_cnv_dbgfs.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Intel Corporation */
+#ifndef ADF_CNV_DBG_H
+#define ADF_CNV_DBG_H
+
+struct adf_accel_dev;
+
+void adf_cnv_dbgfs_add(struct adf_accel_dev *accel_dev);
+void adf_cnv_dbgfs_rm(struct adf_accel_dev *accel_dev);
+
+#endif
diff --git a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h
index 673b5044c62a..f06188033a93 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h
@@ -25,6 +25,8 @@
#define ADF_STATUS_AE_STARTED 6
#define ADF_STATUS_PF_RUNNING 7
#define ADF_STATUS_IRQ_ALLOCATED 8
+#define ADF_STATUS_CRYPTO_ALGS_REGISTERED 9
+#define ADF_STATUS_COMP_ALGS_REGISTERED 10
enum adf_dev_reset_mode {
ADF_DEV_RESET_ASYNC = 0,
@@ -85,14 +87,6 @@ void adf_reset_flr(struct adf_accel_dev *accel_dev);
void adf_dev_restore(struct adf_accel_dev *accel_dev);
int adf_init_aer(void);
void adf_exit_aer(void);
-int adf_init_admin_comms(struct adf_accel_dev *accel_dev);
-void adf_exit_admin_comms(struct adf_accel_dev *accel_dev);
-int adf_send_admin_init(struct adf_accel_dev *accel_dev);
-int adf_get_ae_fw_counters(struct adf_accel_dev *accel_dev, u16 ae, u64 *reqs, u64 *resps);
-int adf_init_admin_pm(struct adf_accel_dev *accel_dev, u32 idle_delay);
-int adf_send_admin_tim_sync(struct adf_accel_dev *accel_dev, u32 cnt);
-int adf_send_admin_hb_timer(struct adf_accel_dev *accel_dev, uint32_t ticks);
-int adf_get_fw_timestamp(struct adf_accel_dev *accel_dev, u64 *timestamp);
int adf_init_arb(struct adf_accel_dev *accel_dev);
void adf_exit_arb(struct adf_accel_dev *accel_dev);
void adf_update_ring_arb(struct adf_etr_ring_data *ring);
@@ -244,4 +238,14 @@ static inline void __iomem *adf_get_pmisc_base(struct adf_accel_dev *accel_dev)
return pmisc->virt_addr;
}
+static inline void __iomem *adf_get_aram_base(struct adf_accel_dev *accel_dev)
+{
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ struct adf_bar *param;
+
+ param = &GET_BARS(accel_dev)[hw_data->get_sram_bar_id(hw_data)];
+
+ return param->virt_addr;
+}
+
#endif
diff --git a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c
index 04845f8d72be..477efcc81a16 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c
@@ -5,9 +5,11 @@
#include "adf_accel_devices.h"
#include "adf_cfg.h"
#include "adf_common_drv.h"
+#include "adf_cnv_dbgfs.h"
#include "adf_dbgfs.h"
#include "adf_fw_counters.h"
#include "adf_heartbeat_dbgfs.h"
+#include "adf_pm_dbgfs.h"
/**
* adf_dbgfs_init() - add persistent debugfs entries
@@ -62,6 +64,8 @@ void adf_dbgfs_add(struct adf_accel_dev *accel_dev)
if (!accel_dev->is_vf) {
adf_fw_counters_dbgfs_add(accel_dev);
adf_heartbeat_dbgfs_add(accel_dev);
+ adf_pm_dbgfs_add(accel_dev);
+ adf_cnv_dbgfs_add(accel_dev);
}
}
@@ -75,6 +79,8 @@ void adf_dbgfs_rm(struct adf_accel_dev *accel_dev)
return;
if (!accel_dev->is_vf) {
+ adf_cnv_dbgfs_rm(accel_dev);
+ adf_pm_dbgfs_rm(accel_dev);
adf_heartbeat_dbgfs_rm(accel_dev);
adf_fw_counters_dbgfs_rm(accel_dev);
}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_fw_counters.c b/drivers/crypto/intel/qat/qat_common/adf_fw_counters.c
index cb6e09ef5c9f..98fb7ccfed9f 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_fw_counters.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_fw_counters.c
@@ -9,6 +9,7 @@
#include <linux/types.h>
#include "adf_accel_devices.h"
+#include "adf_admin.h"
#include "adf_common_drv.h"
#include "adf_fw_counters.h"
@@ -34,7 +35,7 @@ struct adf_ae_counters {
struct adf_fw_counters {
u16 ae_count;
- struct adf_ae_counters ae_counters[];
+ struct adf_ae_counters ae_counters[] __counted_by(ae_count);
};
static void adf_fw_counters_parse_ae_values(struct adf_ae_counters *ae_counters, u32 ae,
diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h b/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h
index 02d7a019ebf8..1813fe1d5a06 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h
@@ -139,6 +139,13 @@ do { \
/* Number of heartbeat counter pairs */
#define ADF_NUM_HB_CNT_PER_AE ADF_NUM_THREADS_PER_AE
+/* Rate Limiting */
+#define ADF_GEN4_RL_R2L_OFFSET 0x508000
+#define ADF_GEN4_RL_L2C_OFFSET 0x509000
+#define ADF_GEN4_RL_C2S_OFFSET 0x508818
+#define ADF_GEN4_RL_TOKEN_PCIEIN_BUCKET_OFFSET 0x508800
+#define ADF_GEN4_RL_TOKEN_PCIEOUT_BUCKET_OFFSET 0x508804
+
void adf_gen4_set_ssm_wdtimer(struct adf_accel_dev *accel_dev);
void adf_gen4_init_hw_csr_ops(struct adf_hw_csr_ops *csr_ops);
int adf_gen4_ring_pair_reset(struct adf_accel_dev *accel_dev, u32 bank_number);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c
index 34c6cd8e27c0..5dafd9a270db 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c
@@ -2,7 +2,10 @@
/* Copyright(c) 2022 Intel Corporation */
#include <linux/bitfield.h>
#include <linux/iopoll.h>
+#include <linux/kernel.h>
+
#include "adf_accel_devices.h"
+#include "adf_admin.h"
#include "adf_common_drv.h"
#include "adf_gen4_pm.h"
#include "adf_cfg_strings.h"
@@ -10,11 +13,6 @@
#include "adf_gen4_hw_data.h"
#include "adf_cfg.h"
-enum qat_pm_host_msg {
- PM_NO_CHANGE = 0,
- PM_SET_MIN,
-};
-
struct adf_gen4_pm_data {
struct work_struct pm_irq_work;
struct adf_accel_dev *accel_dev;
@@ -25,6 +23,7 @@ static int send_host_msg(struct adf_accel_dev *accel_dev)
{
char pm_idle_support_cfg[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {};
void __iomem *pmisc = adf_get_pmisc_base(accel_dev);
+ struct adf_pm *pm = &accel_dev->power_management;
bool pm_idle_support;
u32 msg;
int ret;
@@ -39,6 +38,11 @@ static int send_host_msg(struct adf_accel_dev *accel_dev)
if (ret)
pm_idle_support = true;
+ if (pm_idle_support)
+ pm->host_ack_counter++;
+ else
+ pm->host_nack_counter++;
+
/* Send HOST_MSG */
msg = FIELD_PREP(ADF_GEN4_PM_MSG_PAYLOAD_BIT_MASK,
pm_idle_support ? PM_SET_MIN : PM_NO_CHANGE);
@@ -59,17 +63,27 @@ static void pm_bh_handler(struct work_struct *work)
container_of(work, struct adf_gen4_pm_data, pm_irq_work);
struct adf_accel_dev *accel_dev = pm_data->accel_dev;
void __iomem *pmisc = adf_get_pmisc_base(accel_dev);
+ struct adf_pm *pm = &accel_dev->power_management;
u32 pm_int_sts = pm_data->pm_int_sts;
u32 val;
/* PM Idle interrupt */
if (pm_int_sts & ADF_GEN4_PM_IDLE_STS) {
+ pm->idle_irq_counters++;
/* Issue host message to FW */
if (send_host_msg(accel_dev))
dev_warn_ratelimited(&GET_DEV(accel_dev),
"Failed to send host msg to FW\n");
}
+ /* PM throttle interrupt */
+ if (pm_int_sts & ADF_GEN4_PM_THR_STS)
+ pm->throttle_irq_counters++;
+
+ /* PM fw interrupt */
+ if (pm_int_sts & ADF_GEN4_PM_FW_INT_STS)
+ pm->fw_irq_counters++;
+
/* Clear interrupt status */
ADF_CSR_WR(pmisc, ADF_GEN4_PM_INTERRUPT, pm_int_sts);
@@ -129,6 +143,9 @@ int adf_gen4_enable_pm(struct adf_accel_dev *accel_dev)
if (ret)
return ret;
+ /* Initialize PM internal data */
+ adf_gen4_init_dev_pm_data(accel_dev);
+
/* Enable default PM interrupts: IDLE, THROTTLE */
val = ADF_CSR_RD(pmisc, ADF_GEN4_PM_INTERRUPT);
val |= ADF_GEN4_PM_INT_EN_DEFAULT;
diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h
index c2768762cca3..a49352b79a7a 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h
@@ -3,7 +3,14 @@
#ifndef ADF_GEN4_PM_H
#define ADF_GEN4_PM_H
-#include "adf_accel_devices.h"
+#include <linux/bits.h>
+
+struct adf_accel_dev;
+
+enum qat_pm_host_msg {
+ PM_NO_CHANGE = 0,
+ PM_SET_MIN,
+};
/* Power management registers */
#define ADF_GEN4_PM_HOST_MSG (0x50A01C)
@@ -39,7 +46,48 @@
#define ADF_GEN4_PM_MAX_IDLE_FILTER (0x7)
#define ADF_GEN4_PM_DEFAULT_IDLE_SUPPORT (0x1)
+/* PM CSRs fields masks */
+#define ADF_GEN4_PM_DOMAIN_POWER_GATED_MASK GENMASK(15, 0)
+#define ADF_GEN4_PM_SSM_PM_ENABLE_MASK GENMASK(15, 0)
+#define ADF_GEN4_PM_IDLE_FILTER_MASK GENMASK(5, 3)
+#define ADF_GEN4_PM_IDLE_ENABLE_MASK BIT(2)
+#define ADF_GEN4_PM_ENABLE_PM_MASK BIT(21)
+#define ADF_GEN4_PM_ENABLE_PM_IDLE_MASK BIT(22)
+#define ADF_GEN4_PM_ENABLE_DEEP_PM_IDLE_MASK BIT(23)
+#define ADF_GEN4_PM_CURRENT_WP_MASK GENMASK(19, 11)
+#define ADF_GEN4_PM_CPM_PM_STATE_MASK GENMASK(22, 20)
+#define ADF_GEN4_PM_PENDING_WP_MASK GENMASK(31, 23)
+#define ADF_GEN4_PM_THR_VALUE_MASK GENMASK(6, 4)
+#define ADF_GEN4_PM_MIN_PWR_ACK_MASK BIT(7)
+#define ADF_GEN4_PM_MIN_PWR_ACK_PENDING_MASK BIT(17)
+#define ADF_GEN4_PM_CPR_ACTIVE_COUNT_MASK BIT(0)
+#define ADF_GEN4_PM_CPR_MANAGED_COUNT_MASK BIT(0)
+#define ADF_GEN4_PM_XLT_ACTIVE_COUNT_MASK BIT(1)
+#define ADF_GEN4_PM_XLT_MANAGED_COUNT_MASK BIT(1)
+#define ADF_GEN4_PM_DCPR_ACTIVE_COUNT_MASK GENMASK(3, 2)
+#define ADF_GEN4_PM_DCPR_MANAGED_COUNT_MASK GENMASK(3, 2)
+#define ADF_GEN4_PM_PKE_ACTIVE_COUNT_MASK GENMASK(8, 4)
+#define ADF_GEN4_PM_PKE_MANAGED_COUNT_MASK GENMASK(8, 4)
+#define ADF_GEN4_PM_WAT_ACTIVE_COUNT_MASK GENMASK(13, 9)
+#define ADF_GEN4_PM_WAT_MANAGED_COUNT_MASK GENMASK(13, 9)
+#define ADF_GEN4_PM_WCP_ACTIVE_COUNT_MASK GENMASK(18, 14)
+#define ADF_GEN4_PM_WCP_MANAGED_COUNT_MASK GENMASK(18, 14)
+#define ADF_GEN4_PM_UCS_ACTIVE_COUNT_MASK GENMASK(20, 19)
+#define ADF_GEN4_PM_UCS_MANAGED_COUNT_MASK GENMASK(20, 19)
+#define ADF_GEN4_PM_CPH_ACTIVE_COUNT_MASK GENMASK(24, 21)
+#define ADF_GEN4_PM_CPH_MANAGED_COUNT_MASK GENMASK(24, 21)
+#define ADF_GEN4_PM_ATH_ACTIVE_COUNT_MASK GENMASK(28, 25)
+#define ADF_GEN4_PM_ATH_MANAGED_COUNT_MASK GENMASK(28, 25)
+
int adf_gen4_enable_pm(struct adf_accel_dev *accel_dev);
bool adf_gen4_handle_pm_interrupt(struct adf_accel_dev *accel_dev);
+#ifdef CONFIG_DEBUG_FS
+void adf_gen4_init_dev_pm_data(struct adf_accel_dev *accel_dev);
+#else
+static inline void adf_gen4_init_dev_pm_data(struct adf_accel_dev *accel_dev)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
#endif
diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c
new file mode 100644
index 000000000000..ee0b5079de3e
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Intel Corporation */
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/string_helpers.h>
+#include <linux/stringify.h>
+
+#include "adf_accel_devices.h"
+#include "adf_admin.h"
+#include "adf_common_drv.h"
+#include "adf_gen4_pm.h"
+#include "icp_qat_fw_init_admin.h"
+
+/*
+ * This is needed because a variable is used to index the mask at
+ * pm_scnprint_table(), making it not compile time constant, so the compile
+ * asserts from FIELD_GET() or u32_get_bits() won't be fulfilled.
+ */
+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+
+#define PM_INFO_MEMBER_OFF(member) \
+ (offsetof(struct icp_qat_fw_init_admin_pm_info, member) / sizeof(u32))
+
+#define PM_INFO_REGSET_ENTRY_MASK(_reg_, _field_, _mask_) \
+{ \
+ .reg_offset = PM_INFO_MEMBER_OFF(_reg_), \
+ .key = __stringify(_field_), \
+ .field_mask = _mask_, \
+}
+
+#define PM_INFO_REGSET_ENTRY32(_reg_, _field_) \
+ PM_INFO_REGSET_ENTRY_MASK(_reg_, _field_, GENMASK(31, 0))
+
+#define PM_INFO_REGSET_ENTRY(_reg_, _field_) \
+ PM_INFO_REGSET_ENTRY_MASK(_reg_, _field_, ADF_GEN4_PM_##_field_##_MASK)
+
+#define PM_INFO_MAX_KEY_LEN 21
+
+struct pm_status_row {
+ int reg_offset;
+ u32 field_mask;
+ const char *key;
+};
+
+static struct pm_status_row pm_fuse_rows[] = {
+ PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_PM),
+ PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_PM_IDLE),
+ PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_DEEP_PM_IDLE),
+};
+
+static struct pm_status_row pm_info_rows[] = {
+ PM_INFO_REGSET_ENTRY(pm.status, CPM_PM_STATE),
+ PM_INFO_REGSET_ENTRY(pm.status, PENDING_WP),
+ PM_INFO_REGSET_ENTRY(pm.status, CURRENT_WP),
+ PM_INFO_REGSET_ENTRY(pm.fw_init, IDLE_ENABLE),
+ PM_INFO_REGSET_ENTRY(pm.fw_init, IDLE_FILTER),
+ PM_INFO_REGSET_ENTRY(pm.main, MIN_PWR_ACK),
+ PM_INFO_REGSET_ENTRY(pm.thread, MIN_PWR_ACK_PENDING),
+ PM_INFO_REGSET_ENTRY(pm.main, THR_VALUE),
+};
+
+static struct pm_status_row pm_ssm_rows[] = {
+ PM_INFO_REGSET_ENTRY(ssm.pm_enable, SSM_PM_ENABLE),
+ PM_INFO_REGSET_ENTRY32(ssm.active_constraint, ACTIVE_CONSTRAINT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_domain_status, DOMAIN_POWER_GATED),
+ PM_INFO_REGSET_ENTRY(ssm.pm_active_status, ATH_ACTIVE_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_active_status, CPH_ACTIVE_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_active_status, PKE_ACTIVE_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_active_status, CPR_ACTIVE_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_active_status, DCPR_ACTIVE_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_active_status, UCS_ACTIVE_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_active_status, XLT_ACTIVE_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_active_status, WAT_ACTIVE_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_active_status, WCP_ACTIVE_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, ATH_MANAGED_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, CPH_MANAGED_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, PKE_MANAGED_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, CPR_MANAGED_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, DCPR_MANAGED_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, UCS_MANAGED_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, XLT_MANAGED_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, WAT_MANAGED_COUNT),
+ PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, WCP_MANAGED_COUNT),
+};
+
+static struct pm_status_row pm_log_rows[] = {
+ PM_INFO_REGSET_ENTRY32(event_counters.host_msg, HOST_MSG_EVENT_COUNT),
+ PM_INFO_REGSET_ENTRY32(event_counters.sys_pm, SYS_PM_EVENT_COUNT),
+ PM_INFO_REGSET_ENTRY32(event_counters.local_ssm, SSM_EVENT_COUNT),
+ PM_INFO_REGSET_ENTRY32(event_counters.timer, TIMER_EVENT_COUNT),
+ PM_INFO_REGSET_ENTRY32(event_counters.unknown, UNKNOWN_EVENT_COUNT),
+};
+
+static struct pm_status_row pm_event_rows[ICP_QAT_NUMBER_OF_PM_EVENTS] = {
+ PM_INFO_REGSET_ENTRY32(event_log[0], EVENT0),
+ PM_INFO_REGSET_ENTRY32(event_log[1], EVENT1),
+ PM_INFO_REGSET_ENTRY32(event_log[2], EVENT2),
+ PM_INFO_REGSET_ENTRY32(event_log[3], EVENT3),
+ PM_INFO_REGSET_ENTRY32(event_log[4], EVENT4),
+ PM_INFO_REGSET_ENTRY32(event_log[5], EVENT5),
+ PM_INFO_REGSET_ENTRY32(event_log[6], EVENT6),
+ PM_INFO_REGSET_ENTRY32(event_log[7], EVENT7),
+};
+
+static struct pm_status_row pm_csrs_rows[] = {
+ PM_INFO_REGSET_ENTRY32(pm.fw_init, CPM_PM_FW_INIT),
+ PM_INFO_REGSET_ENTRY32(pm.status, CPM_PM_STATUS),
+ PM_INFO_REGSET_ENTRY32(pm.main, CPM_PM_MASTER_FW),
+ PM_INFO_REGSET_ENTRY32(pm.pwrreq, CPM_PM_PWRREQ),
+};
+
+static int pm_scnprint_table(char *buff, struct pm_status_row *table,
+ u32 *pm_info_regs, size_t buff_size, int table_len,
+ bool lowercase)
+{
+ char key[PM_INFO_MAX_KEY_LEN];
+ int wr = 0;
+ int i;
+
+ for (i = 0; i < table_len; i++) {
+ if (lowercase)
+ string_lower(key, table[i].key);
+ else
+ string_upper(key, table[i].key);
+
+ wr += scnprintf(&buff[wr], buff_size - wr, "%s: %#x\n", key,
+ field_get(table[i].field_mask,
+ pm_info_regs[table[i].reg_offset]));
+ }
+
+ return wr;
+}
+
+static int pm_scnprint_table_upper_keys(char *buff, struct pm_status_row *table,
+ u32 *pm_info_regs, size_t buff_size,
+ int table_len)
+{
+ return pm_scnprint_table(buff, table, pm_info_regs, buff_size,
+ table_len, false);
+}
+
+static int pm_scnprint_table_lower_keys(char *buff, struct pm_status_row *table,
+ u32 *pm_info_regs, size_t buff_size,
+ int table_len)
+{
+ return pm_scnprint_table(buff, table, pm_info_regs, buff_size,
+ table_len, true);
+}
+
+static_assert(sizeof(struct icp_qat_fw_init_admin_pm_info) < PAGE_SIZE);
+
+static ssize_t adf_gen4_print_pm_status(struct adf_accel_dev *accel_dev,
+ char __user *buf, size_t count,
+ loff_t *pos)
+{
+ void __iomem *pmisc = adf_get_pmisc_base(accel_dev);
+ struct adf_pm *pm = &accel_dev->power_management;
+ struct icp_qat_fw_init_admin_pm_info *pm_info;
+ dma_addr_t p_state_addr;
+ u32 *pm_info_regs;
+ char *pm_kv;
+ int len = 0;
+ u32 val;
+ int ret;
+
+ pm_info = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!pm_info)
+ return -ENOMEM;
+
+ pm_kv = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!pm_kv) {
+ ret = -ENOMEM;
+ goto out_free;
+ }
+
+ p_state_addr = dma_map_single(&GET_DEV(accel_dev), pm_info, PAGE_SIZE,
+ DMA_FROM_DEVICE);
+ ret = dma_mapping_error(&GET_DEV(accel_dev), p_state_addr);
+ if (ret)
+ goto out_free;
+
+ /* Query PM info from QAT FW */
+ ret = adf_get_pm_info(accel_dev, p_state_addr, PAGE_SIZE);
+ dma_unmap_single(&GET_DEV(accel_dev), p_state_addr, PAGE_SIZE,
+ DMA_FROM_DEVICE);
+ if (ret)
+ goto out_free;
+
+ pm_info_regs = (u32 *)pm_info;
+
+ /* Fusectl related */
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len,
+ "----------- PM Fuse info ---------\n");
+ len += pm_scnprint_table_lower_keys(&pm_kv[len], pm_fuse_rows,
+ pm_info_regs, PAGE_SIZE - len,
+ ARRAY_SIZE(pm_fuse_rows));
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "max_pwrreq: %#x\n",
+ pm_info->max_pwrreq);
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "min_pwrreq: %#x\n",
+ pm_info->min_pwrreq);
+
+ /* PM related */
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len,
+ "------------ PM Info ------------\n");
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "power_level: %s\n",
+ pm_info->pwr_state == PM_SET_MIN ? "min" : "max");
+ len += pm_scnprint_table_lower_keys(&pm_kv[len], pm_info_rows,
+ pm_info_regs, PAGE_SIZE - len,
+ ARRAY_SIZE(pm_info_rows));
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "pm_mode: STATIC\n");
+
+ /* SSM related */
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len,
+ "----------- SSM_PM Info ----------\n");
+ len += pm_scnprint_table_lower_keys(&pm_kv[len], pm_ssm_rows,
+ pm_info_regs, PAGE_SIZE - len,
+ ARRAY_SIZE(pm_ssm_rows));
+
+ /* Log related */
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len,
+ "------------- PM Log -------------\n");
+ len += pm_scnprint_table_lower_keys(&pm_kv[len], pm_log_rows,
+ pm_info_regs, PAGE_SIZE - len,
+ ARRAY_SIZE(pm_log_rows));
+
+ len += pm_scnprint_table_lower_keys(&pm_kv[len], pm_event_rows,
+ pm_info_regs, PAGE_SIZE - len,
+ ARRAY_SIZE(pm_event_rows));
+
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "idle_irq_count: %#x\n",
+ pm->idle_irq_counters);
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "fw_irq_count: %#x\n",
+ pm->fw_irq_counters);
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len,
+ "throttle_irq_count: %#x\n", pm->throttle_irq_counters);
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "host_ack_count: %#x\n",
+ pm->host_ack_counter);
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len, "host_nack_count: %#x\n",
+ pm->host_nack_counter);
+
+ /* CSRs content */
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len,
+ "----------- HW PM CSRs -----------\n");
+ len += pm_scnprint_table_upper_keys(&pm_kv[len], pm_csrs_rows,
+ pm_info_regs, PAGE_SIZE - len,
+ ARRAY_SIZE(pm_csrs_rows));
+
+ val = ADF_CSR_RD(pmisc, ADF_GEN4_PM_HOST_MSG);
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len,
+ "CPM_PM_HOST_MSG: %#x\n", val);
+ val = ADF_CSR_RD(pmisc, ADF_GEN4_PM_INTERRUPT);
+ len += scnprintf(&pm_kv[len], PAGE_SIZE - len,
+ "CPM_PM_INTERRUPT: %#x\n", val);
+ ret = simple_read_from_buffer(buf, count, pos, pm_kv, len);
+
+out_free:
+ kfree(pm_info);
+ kfree(pm_kv);
+ return ret;
+}
+
+void adf_gen4_init_dev_pm_data(struct adf_accel_dev *accel_dev)
+{
+ accel_dev->power_management.print_pm_status = adf_gen4_print_pm_status;
+ accel_dev->power_management.present = true;
+}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c
new file mode 100644
index 000000000000..048c24607939
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c
@@ -0,0 +1,1566 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Intel Corporation */
+#include "adf_common_drv.h"
+#include "adf_gen4_hw_data.h"
+#include "adf_gen4_ras.h"
+#include "adf_sysfs_ras_counters.h"
+
+#define BITS_PER_REG(_n_) (sizeof(_n_) * BITS_PER_BYTE)
+
+static void enable_errsou_reporting(void __iomem *csr)
+{
+ /* Enable correctable error reporting in ERRSOU0 */
+ ADF_CSR_WR(csr, ADF_GEN4_ERRMSK0, 0);
+
+ /* Enable uncorrectable error reporting in ERRSOU1 */
+ ADF_CSR_WR(csr, ADF_GEN4_ERRMSK1, 0);
+
+ /*
+ * Enable uncorrectable error reporting in ERRSOU2
+ * but disable PM interrupt and CFC attention interrupt by default
+ */
+ ADF_CSR_WR(csr, ADF_GEN4_ERRMSK2,
+ ADF_GEN4_ERRSOU2_PM_INT_BIT |
+ ADF_GEN4_ERRSOU2_CPP_CFC_ATT_INT_BITMASK);
+
+ /*
+ * Enable uncorrectable error reporting in ERRSOU3
+ * but disable RLT error interrupt and VFLR notify interrupt by default
+ */
+ ADF_CSR_WR(csr, ADF_GEN4_ERRMSK3,
+ ADF_GEN4_ERRSOU3_RLTERROR_BIT |
+ ADF_GEN4_ERRSOU3_VFLRNOTIFY_BIT);
+}
+
+static void disable_errsou_reporting(void __iomem *csr)
+{
+ u32 val = 0;
+
+ /* Disable correctable error reporting in ERRSOU0 */
+ ADF_CSR_WR(csr, ADF_GEN4_ERRMSK0, ADF_GEN4_ERRSOU0_BIT);
+
+ /* Disable uncorrectable error reporting in ERRSOU1 */
+ ADF_CSR_WR(csr, ADF_GEN4_ERRMSK1, ADF_GEN4_ERRSOU1_BITMASK);
+
+ /* Disable uncorrectable error reporting in ERRSOU2 */
+ val = ADF_CSR_RD(csr, ADF_GEN4_ERRMSK2);
+ val |= ADF_GEN4_ERRSOU2_DIS_BITMASK;
+ ADF_CSR_WR(csr, ADF_GEN4_ERRMSK2, val);
+
+ /* Disable uncorrectable error reporting in ERRSOU3 */
+ ADF_CSR_WR(csr, ADF_GEN4_ERRMSK3, ADF_GEN4_ERRSOU3_BITMASK);
+}
+
+static void enable_ae_error_reporting(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ u32 ae_mask = GET_HW_DATA(accel_dev)->ae_mask;
+
+ /* Enable Acceleration Engine correctable error reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_HIAECORERRLOGENABLE_CPP0, ae_mask);
+
+ /* Enable Acceleration Engine uncorrectable error reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_HIAEUNCERRLOGENABLE_CPP0, ae_mask);
+}
+
+static void disable_ae_error_reporting(void __iomem *csr)
+{
+ /* Disable Acceleration Engine correctable error reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_HIAECORERRLOGENABLE_CPP0, 0);
+
+ /* Disable Acceleration Engine uncorrectable error reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_HIAEUNCERRLOGENABLE_CPP0, 0);
+}
+
+static void enable_cpp_error_reporting(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev);
+
+ /* Enable HI CPP Agents Command Parity Error Reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_HICPPAGENTCMDPARERRLOGENABLE,
+ err_mask->cppagentcmdpar_mask);
+
+ ADF_CSR_WR(csr, ADF_GEN4_CPP_CFC_ERR_CTRL,
+ ADF_GEN4_CPP_CFC_ERR_CTRL_BITMASK);
+}
+
+static void disable_cpp_error_reporting(void __iomem *csr)
+{
+ /* Disable HI CPP Agents Command Parity Error Reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_HICPPAGENTCMDPARERRLOGENABLE, 0);
+
+ ADF_CSR_WR(csr, ADF_GEN4_CPP_CFC_ERR_CTRL,
+ ADF_GEN4_CPP_CFC_ERR_CTRL_DIS_BITMASK);
+}
+
+static void enable_ti_ri_error_reporting(void __iomem *csr)
+{
+ u32 reg;
+
+ /* Enable RI Memory error reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_RI_MEM_PAR_ERR_EN0,
+ ADF_GEN4_RIMEM_PARERR_STS_FATAL_BITMASK |
+ ADF_GEN4_RIMEM_PARERR_STS_UNCERR_BITMASK);
+
+ /* Enable IOSF Primary Command Parity error Reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_RIMISCCTL, ADF_GEN4_RIMISCSTS_BIT);
+
+ /* Enable TI Internal Memory Parity Error reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_TI_CI_PAR_ERR_MASK, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_TI_PULL0FUB_PAR_ERR_MASK, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_TI_PUSHFUB_PAR_ERR_MASK, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_TI_CD_PAR_ERR_MASK, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_TI_TRNSB_PAR_ERR_MASK, 0);
+
+ /* Enable error handling in RI, TI CPP interface control registers */
+ ADF_CSR_WR(csr, ADF_GEN4_RICPPINTCTL, ADF_GEN4_RICPPINTCTL_BITMASK);
+
+ ADF_CSR_WR(csr, ADF_GEN4_TICPPINTCTL, ADF_GEN4_TICPPINTCTL_BITMASK);
+
+ /*
+ * Enable error detection and reporting in TIMISCSTS
+ * with bits 1, 2 and 30 value preserved
+ */
+ reg = ADF_CSR_RD(csr, ADF_GEN4_TIMISCCTL);
+ reg &= ADF_GEN4_TIMSCCTL_RELAY_BITMASK;
+ reg |= ADF_GEN4_TIMISCCTL_BIT;
+ ADF_CSR_WR(csr, ADF_GEN4_TIMISCCTL, reg);
+}
+
+static void disable_ti_ri_error_reporting(void __iomem *csr)
+{
+ u32 reg;
+
+ /* Disable RI Memory error reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_RI_MEM_PAR_ERR_EN0, 0);
+
+ /* Disable IOSF Primary Command Parity error Reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_RIMISCCTL, 0);
+
+ /* Disable TI Internal Memory Parity Error reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_TI_CI_PAR_ERR_MASK,
+ ADF_GEN4_TI_CI_PAR_STS_BITMASK);
+ ADF_CSR_WR(csr, ADF_GEN4_TI_PULL0FUB_PAR_ERR_MASK,
+ ADF_GEN4_TI_PULL0FUB_PAR_STS_BITMASK);
+ ADF_CSR_WR(csr, ADF_GEN4_TI_PUSHFUB_PAR_ERR_MASK,
+ ADF_GEN4_TI_PUSHFUB_PAR_STS_BITMASK);
+ ADF_CSR_WR(csr, ADF_GEN4_TI_CD_PAR_ERR_MASK,
+ ADF_GEN4_TI_CD_PAR_STS_BITMASK);
+ ADF_CSR_WR(csr, ADF_GEN4_TI_TRNSB_PAR_ERR_MASK,
+ ADF_GEN4_TI_TRNSB_PAR_STS_BITMASK);
+
+ /* Disable error handling in RI, TI CPP interface control registers */
+ ADF_CSR_WR(csr, ADF_GEN4_RICPPINTCTL, 0);
+
+ ADF_CSR_WR(csr, ADF_GEN4_TICPPINTCTL, 0);
+
+ /*
+ * Disable error detection and reporting in TIMISCSTS
+ * with bits 1, 2 and 30 value preserved
+ */
+ reg = ADF_CSR_RD(csr, ADF_GEN4_TIMISCCTL);
+ reg &= ADF_GEN4_TIMSCCTL_RELAY_BITMASK;
+ ADF_CSR_WR(csr, ADF_GEN4_TIMISCCTL, reg);
+}
+
+static void enable_rf_error_reporting(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev);
+
+ /* Enable RF parity error in Shared RAM */
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITYMASK_SRC, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITYMASK_ATH_CPH, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITYMASK_CPR_XLT, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITYMASK_DCPR_UCS, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITYMASK_PKE, 0);
+
+ if (err_mask->parerr_wat_wcp_mask)
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITYMASK_WAT_WCP, 0);
+}
+
+static void disable_rf_error_reporting(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev);
+
+ /* Disable RF Parity Error reporting in Shared RAM */
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITYMASK_SRC,
+ ADF_GEN4_SSMSOFTERRORPARITY_SRC_BIT);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITYMASK_ATH_CPH,
+ err_mask->parerr_ath_cph_mask);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITYMASK_CPR_XLT,
+ err_mask->parerr_cpr_xlt_mask);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITYMASK_DCPR_UCS,
+ err_mask->parerr_dcpr_ucs_mask);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITYMASK_PKE,
+ err_mask->parerr_pke_mask);
+
+ if (err_mask->parerr_wat_wcp_mask)
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITYMASK_WAT_WCP,
+ err_mask->parerr_wat_wcp_mask);
+}
+
+static void enable_ssm_error_reporting(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev);
+ u32 val = 0;
+
+ /* Enable SSM interrupts */
+ ADF_CSR_WR(csr, ADF_GEN4_INTMASKSSM, 0);
+
+ /* Enable shared memory error detection & correction */
+ val = ADF_CSR_RD(csr, ADF_GEN4_SSMFEATREN);
+ val |= err_mask->ssmfeatren_mask;
+ ADF_CSR_WR(csr, ADF_GEN4_SSMFEATREN, val);
+
+ /* Enable SER detection in SER_err_ssmsh register */
+ ADF_CSR_WR(csr, ADF_GEN4_SER_EN_SSMSH,
+ ADF_GEN4_SER_EN_SSMSH_BITMASK);
+
+ /* Enable SSM soft parity error */
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPARERRMSK_ATH_CPH, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPARERRMSK_CPR_XLT, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPARERRMSK_DCPR_UCS, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPARERRMSK_PKE, 0);
+
+ if (err_mask->parerr_wat_wcp_mask)
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPARERRMSK_WAT_WCP, 0);
+
+ /* Enable slice hang interrupt reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_SHINTMASKSSM_ATH_CPH, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_SHINTMASKSSM_CPR_XLT, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_SHINTMASKSSM_DCPR_UCS, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_SHINTMASKSSM_PKE, 0);
+
+ if (err_mask->parerr_wat_wcp_mask)
+ ADF_CSR_WR(csr, ADF_GEN4_SHINTMASKSSM_WAT_WCP, 0);
+}
+
+static void disable_ssm_error_reporting(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev);
+ u32 val = 0;
+
+ /* Disable SSM interrupts */
+ ADF_CSR_WR(csr, ADF_GEN4_INTMASKSSM,
+ ADF_GEN4_INTMASKSSM_BITMASK);
+
+ /* Disable shared memory error detection & correction */
+ val = ADF_CSR_RD(csr, ADF_GEN4_SSMFEATREN);
+ val &= ADF_GEN4_SSMFEATREN_DIS_BITMASK;
+ ADF_CSR_WR(csr, ADF_GEN4_SSMFEATREN, val);
+
+ /* Disable SER detection in SER_err_ssmsh register */
+ ADF_CSR_WR(csr, ADF_GEN4_SER_EN_SSMSH, 0);
+
+ /* Disable SSM soft parity error */
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPARERRMSK_ATH_CPH,
+ err_mask->parerr_ath_cph_mask);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPARERRMSK_CPR_XLT,
+ err_mask->parerr_cpr_xlt_mask);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPARERRMSK_DCPR_UCS,
+ err_mask->parerr_dcpr_ucs_mask);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPARERRMSK_PKE,
+ err_mask->parerr_pke_mask);
+
+ if (err_mask->parerr_wat_wcp_mask)
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPARERRMSK_WAT_WCP,
+ err_mask->parerr_wat_wcp_mask);
+
+ /* Disable slice hang interrupt reporting */
+ ADF_CSR_WR(csr, ADF_GEN4_SHINTMASKSSM_ATH_CPH,
+ err_mask->parerr_ath_cph_mask);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SHINTMASKSSM_CPR_XLT,
+ err_mask->parerr_cpr_xlt_mask);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SHINTMASKSSM_DCPR_UCS,
+ err_mask->parerr_dcpr_ucs_mask);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SHINTMASKSSM_PKE,
+ err_mask->parerr_pke_mask);
+
+ if (err_mask->parerr_wat_wcp_mask)
+ ADF_CSR_WR(csr, ADF_GEN4_SHINTMASKSSM_WAT_WCP,
+ err_mask->parerr_wat_wcp_mask);
+}
+
+static void enable_aram_error_reporting(void __iomem *csr)
+{
+ ADF_CSR_WR(csr, ADF_GEN4_REG_ARAMCERRUERR_EN,
+ ADF_GEN4_REG_ARAMCERRUERR_EN_BITMASK);
+
+ ADF_CSR_WR(csr, ADF_GEN4_REG_ARAMCERR,
+ ADF_GEN4_REG_ARAMCERR_EN_BITMASK);
+
+ ADF_CSR_WR(csr, ADF_GEN4_REG_ARAMUERR,
+ ADF_GEN4_REG_ARAMUERR_EN_BITMASK);
+
+ ADF_CSR_WR(csr, ADF_GEN4_REG_CPPMEMTGTERR,
+ ADF_GEN4_REG_CPPMEMTGTERR_EN_BITMASK);
+}
+
+static void disable_aram_error_reporting(void __iomem *csr)
+{
+ ADF_CSR_WR(csr, ADF_GEN4_REG_ARAMCERRUERR_EN, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_REG_ARAMCERR, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_REG_ARAMUERR, 0);
+ ADF_CSR_WR(csr, ADF_GEN4_REG_CPPMEMTGTERR, 0);
+}
+
+static void adf_gen4_enable_ras(struct adf_accel_dev *accel_dev)
+{
+ void __iomem *aram_csr = adf_get_aram_base(accel_dev);
+ void __iomem *csr = adf_get_pmisc_base(accel_dev);
+
+ enable_errsou_reporting(csr);
+ enable_ae_error_reporting(accel_dev, csr);
+ enable_cpp_error_reporting(accel_dev, csr);
+ enable_ti_ri_error_reporting(csr);
+ enable_rf_error_reporting(accel_dev, csr);
+ enable_ssm_error_reporting(accel_dev, csr);
+ enable_aram_error_reporting(aram_csr);
+}
+
+static void adf_gen4_disable_ras(struct adf_accel_dev *accel_dev)
+{
+ void __iomem *aram_csr = adf_get_aram_base(accel_dev);
+ void __iomem *csr = adf_get_pmisc_base(accel_dev);
+
+ disable_errsou_reporting(csr);
+ disable_ae_error_reporting(csr);
+ disable_cpp_error_reporting(csr);
+ disable_ti_ri_error_reporting(csr);
+ disable_rf_error_reporting(accel_dev, csr);
+ disable_ssm_error_reporting(accel_dev, csr);
+ disable_aram_error_reporting(aram_csr);
+}
+
+static void adf_gen4_process_errsou0(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ u32 aecorrerr = ADF_CSR_RD(csr, ADF_GEN4_HIAECORERRLOG_CPP0);
+
+ aecorrerr &= GET_HW_DATA(accel_dev)->ae_mask;
+
+ dev_warn(&GET_DEV(accel_dev),
+ "Correctable error detected in AE: 0x%x\n",
+ aecorrerr);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_CORR);
+
+ /* Clear interrupt from ERRSOU0 */
+ ADF_CSR_WR(csr, ADF_GEN4_HIAECORERRLOG_CPP0, aecorrerr);
+}
+
+static bool adf_handle_cpp_aeunc(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ u32 aeuncorerr;
+
+ if (!(errsou & ADF_GEN4_ERRSOU1_HIAEUNCERRLOG_CPP0_BIT))
+ return false;
+
+ aeuncorerr = ADF_CSR_RD(csr, ADF_GEN4_HIAEUNCERRLOG_CPP0);
+ aeuncorerr &= GET_HW_DATA(accel_dev)->ae_mask;
+
+ dev_err(&GET_DEV(accel_dev),
+ "Uncorrectable error detected in AE: 0x%x\n",
+ aeuncorerr);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_HIAEUNCERRLOG_CPP0, aeuncorerr);
+
+ return false;
+}
+
+static bool adf_handle_cppcmdparerr(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev);
+ u32 cmdparerr;
+
+ if (!(errsou & ADF_GEN4_ERRSOU1_HICPPAGENTCMDPARERRLOG_BIT))
+ return false;
+
+ cmdparerr = ADF_CSR_RD(csr, ADF_GEN4_HICPPAGENTCMDPARERRLOG);
+ cmdparerr &= err_mask->cppagentcmdpar_mask;
+
+ dev_err(&GET_DEV(accel_dev),
+ "HI CPP agent command parity error: 0x%x\n",
+ cmdparerr);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ ADF_CSR_WR(csr, ADF_GEN4_HICPPAGENTCMDPARERRLOG, cmdparerr);
+
+ return true;
+}
+
+static bool adf_handle_ri_mem_par_err(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ bool reset_required = false;
+ u32 rimem_parerr_sts;
+
+ if (!(errsou & ADF_GEN4_ERRSOU1_RIMEM_PARERR_STS_BIT))
+ return false;
+
+ rimem_parerr_sts = ADF_CSR_RD(csr, ADF_GEN4_RIMEM_PARERR_STS);
+ rimem_parerr_sts &= ADF_GEN4_RIMEM_PARERR_STS_UNCERR_BITMASK |
+ ADF_GEN4_RIMEM_PARERR_STS_FATAL_BITMASK;
+
+ if (rimem_parerr_sts & ADF_GEN4_RIMEM_PARERR_STS_UNCERR_BITMASK) {
+ dev_err(&GET_DEV(accel_dev),
+ "RI Memory Parity uncorrectable error: 0x%x\n",
+ rimem_parerr_sts);
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ }
+
+ if (rimem_parerr_sts & ADF_GEN4_RIMEM_PARERR_STS_FATAL_BITMASK) {
+ dev_err(&GET_DEV(accel_dev),
+ "RI Memory Parity fatal error: 0x%x\n",
+ rimem_parerr_sts);
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+ reset_required = true;
+ }
+
+ ADF_CSR_WR(csr, ADF_GEN4_RIMEM_PARERR_STS, rimem_parerr_sts);
+
+ return reset_required;
+}
+
+static bool adf_handle_ti_ci_par_sts(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ u32 ti_ci_par_sts;
+
+ if (!(errsou & ADF_GEN4_ERRSOU1_TIMEM_PARERR_STS_BIT))
+ return false;
+
+ ti_ci_par_sts = ADF_CSR_RD(csr, ADF_GEN4_TI_CI_PAR_STS);
+ ti_ci_par_sts &= ADF_GEN4_TI_CI_PAR_STS_BITMASK;
+
+ if (ti_ci_par_sts) {
+ dev_err(&GET_DEV(accel_dev),
+ "TI Memory Parity Error: 0x%x\n", ti_ci_par_sts);
+ ADF_CSR_WR(csr, ADF_GEN4_TI_CI_PAR_STS, ti_ci_par_sts);
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ }
+
+ return false;
+}
+
+static bool adf_handle_ti_pullfub_par_sts(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ u32 ti_pullfub_par_sts;
+
+ if (!(errsou & ADF_GEN4_ERRSOU1_TIMEM_PARERR_STS_BIT))
+ return false;
+
+ ti_pullfub_par_sts = ADF_CSR_RD(csr, ADF_GEN4_TI_PULL0FUB_PAR_STS);
+ ti_pullfub_par_sts &= ADF_GEN4_TI_PULL0FUB_PAR_STS_BITMASK;
+
+ if (ti_pullfub_par_sts) {
+ dev_err(&GET_DEV(accel_dev),
+ "TI Pull Parity Error: 0x%x\n", ti_pullfub_par_sts);
+
+ ADF_CSR_WR(csr, ADF_GEN4_TI_PULL0FUB_PAR_STS,
+ ti_pullfub_par_sts);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ }
+
+ return false;
+}
+
+static bool adf_handle_ti_pushfub_par_sts(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ u32 ti_pushfub_par_sts;
+
+ if (!(errsou & ADF_GEN4_ERRSOU1_TIMEM_PARERR_STS_BIT))
+ return false;
+
+ ti_pushfub_par_sts = ADF_CSR_RD(csr, ADF_GEN4_TI_PUSHFUB_PAR_STS);
+ ti_pushfub_par_sts &= ADF_GEN4_TI_PUSHFUB_PAR_STS_BITMASK;
+
+ if (ti_pushfub_par_sts) {
+ dev_err(&GET_DEV(accel_dev),
+ "TI Push Parity Error: 0x%x\n", ti_pushfub_par_sts);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_TI_PUSHFUB_PAR_STS,
+ ti_pushfub_par_sts);
+ }
+
+ return false;
+}
+
+static bool adf_handle_ti_cd_par_sts(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ u32 ti_cd_par_sts;
+
+ if (!(errsou & ADF_GEN4_ERRSOU1_TIMEM_PARERR_STS_BIT))
+ return false;
+
+ ti_cd_par_sts = ADF_CSR_RD(csr, ADF_GEN4_TI_CD_PAR_STS);
+ ti_cd_par_sts &= ADF_GEN4_TI_CD_PAR_STS_BITMASK;
+
+ if (ti_cd_par_sts) {
+ dev_err(&GET_DEV(accel_dev),
+ "TI CD Parity Error: 0x%x\n", ti_cd_par_sts);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_TI_CD_PAR_STS, ti_cd_par_sts);
+ }
+
+ return false;
+}
+
+static bool adf_handle_ti_trnsb_par_sts(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ u32 ti_trnsb_par_sts;
+
+ if (!(errsou & ADF_GEN4_ERRSOU1_TIMEM_PARERR_STS_BIT))
+ return false;
+
+ ti_trnsb_par_sts = ADF_CSR_RD(csr, ADF_GEN4_TI_TRNSB_PAR_STS);
+ ti_trnsb_par_sts &= ADF_GEN4_TI_TRNSB_PAR_STS_BITMASK;
+
+ if (ti_trnsb_par_sts) {
+ dev_err(&GET_DEV(accel_dev),
+ "TI TRNSB Parity Error: 0x%x\n", ti_trnsb_par_sts);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_TI_TRNSB_PAR_STS, ti_trnsb_par_sts);
+ }
+
+ return false;
+}
+
+static bool adf_handle_iosfp_cmd_parerr(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ u32 rimiscsts;
+
+ if (!(errsou & ADF_GEN4_ERRSOU1_TIMEM_PARERR_STS_BIT))
+ return false;
+
+ rimiscsts = ADF_CSR_RD(csr, ADF_GEN4_RIMISCSTS);
+ rimiscsts &= ADF_GEN4_RIMISCSTS_BIT;
+
+ dev_err(&GET_DEV(accel_dev),
+ "Command Parity error detected on IOSFP: 0x%x\n",
+ rimiscsts);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ ADF_CSR_WR(csr, ADF_GEN4_RIMISCSTS, rimiscsts);
+
+ return true;
+}
+
+static void adf_gen4_process_errsou1(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou,
+ bool *reset_required)
+{
+ *reset_required |= adf_handle_cpp_aeunc(accel_dev, csr, errsou);
+ *reset_required |= adf_handle_cppcmdparerr(accel_dev, csr, errsou);
+ *reset_required |= adf_handle_ri_mem_par_err(accel_dev, csr, errsou);
+ *reset_required |= adf_handle_ti_ci_par_sts(accel_dev, csr, errsou);
+ *reset_required |= adf_handle_ti_pullfub_par_sts(accel_dev, csr, errsou);
+ *reset_required |= adf_handle_ti_pushfub_par_sts(accel_dev, csr, errsou);
+ *reset_required |= adf_handle_ti_cd_par_sts(accel_dev, csr, errsou);
+ *reset_required |= adf_handle_ti_trnsb_par_sts(accel_dev, csr, errsou);
+ *reset_required |= adf_handle_iosfp_cmd_parerr(accel_dev, csr, errsou);
+}
+
+static bool adf_handle_uerrssmsh(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 iastatssm)
+{
+ u32 reg;
+
+ if (!(iastatssm & ADF_GEN4_IAINTSTATSSM_UERRSSMSH_BIT))
+ return false;
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_UERRSSMSH);
+ reg &= ADF_GEN4_UERRSSMSH_BITMASK;
+
+ dev_err(&GET_DEV(accel_dev),
+ "Uncorrectable error on ssm shared memory: 0x%x\n",
+ reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_UERRSSMSH, reg);
+
+ return false;
+}
+
+static bool adf_handle_cerrssmsh(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 iastatssm)
+{
+ u32 reg;
+
+ if (!(iastatssm & ADF_GEN4_IAINTSTATSSM_CERRSSMSH_BIT))
+ return false;
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_CERRSSMSH);
+ reg &= ADF_GEN4_CERRSSMSH_ERROR_BIT;
+
+ dev_warn(&GET_DEV(accel_dev),
+ "Correctable error on ssm shared memory: 0x%x\n",
+ reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_CORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_CERRSSMSH, reg);
+
+ return false;
+}
+
+static bool adf_handle_pperr_err(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 iastatssm)
+{
+ u32 reg;
+
+ if (!(iastatssm & ADF_GEN4_IAINTSTATSSM_PPERR_BIT))
+ return false;
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_PPERR);
+ reg &= ADF_GEN4_PPERR_BITMASK;
+
+ dev_err(&GET_DEV(accel_dev),
+ "Uncorrectable error CPP transaction on memory target: 0x%x\n",
+ reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_PPERR, reg);
+
+ return false;
+}
+
+static void adf_poll_slicehang_csr(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 slice_hang_offset,
+ char *slice_name)
+{
+ u32 slice_hang_reg = ADF_CSR_RD(csr, slice_hang_offset);
+
+ if (!slice_hang_reg)
+ return;
+
+ dev_err(&GET_DEV(accel_dev),
+ "Slice %s hang error encountered\n", slice_name);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+}
+
+static bool adf_handle_slice_hang_error(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 iastatssm)
+{
+ struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev);
+
+ if (!(iastatssm & ADF_GEN4_IAINTSTATSSM_SLICEHANG_ERR_BIT))
+ return false;
+
+ adf_poll_slicehang_csr(accel_dev, csr,
+ ADF_GEN4_SLICEHANGSTATUS_ATH_CPH, "ath_cph");
+ adf_poll_slicehang_csr(accel_dev, csr,
+ ADF_GEN4_SLICEHANGSTATUS_CPR_XLT, "cpr_xlt");
+ adf_poll_slicehang_csr(accel_dev, csr,
+ ADF_GEN4_SLICEHANGSTATUS_DCPR_UCS, "dcpr_ucs");
+ adf_poll_slicehang_csr(accel_dev, csr,
+ ADF_GEN4_SLICEHANGSTATUS_PKE, "pke");
+
+ if (err_mask->parerr_wat_wcp_mask)
+ adf_poll_slicehang_csr(accel_dev, csr,
+ ADF_GEN4_SLICEHANGSTATUS_WAT_WCP,
+ "ath_cph");
+
+ return false;
+}
+
+static bool adf_handle_spp_pullcmd_err(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev);
+ bool reset_required = false;
+ u32 reg;
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPULLCMDPARERR_ATH_CPH);
+ reg &= err_mask->parerr_ath_cph_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP pull command fatal error ATH_CPH: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPULLCMDPARERR_ATH_CPH, reg);
+
+ reset_required = true;
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPULLCMDPARERR_CPR_XLT);
+ reg &= err_mask->parerr_cpr_xlt_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP pull command fatal error CPR_XLT: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPULLCMDPARERR_CPR_XLT, reg);
+
+ reset_required = true;
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPULLCMDPARERR_DCPR_UCS);
+ reg &= err_mask->parerr_dcpr_ucs_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP pull command fatal error DCPR_UCS: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPULLCMDPARERR_DCPR_UCS, reg);
+
+ reset_required = true;
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPULLCMDPARERR_PKE);
+ reg &= err_mask->parerr_pke_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP pull command fatal error PKE: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPULLCMDPARERR_PKE, reg);
+
+ reset_required = true;
+ }
+
+ if (err_mask->parerr_wat_wcp_mask) {
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPULLCMDPARERR_WAT_WCP);
+ reg &= err_mask->parerr_wat_wcp_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP pull command fatal error WAT_WCP: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPULLCMDPARERR_WAT_WCP, reg);
+
+ reset_required = true;
+ }
+ }
+
+ return reset_required;
+}
+
+static bool adf_handle_spp_pulldata_err(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev);
+ u32 reg;
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPULLDATAPARERR_ATH_CPH);
+ reg &= err_mask->parerr_ath_cph_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP pull data err ATH_CPH: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPULLDATAPARERR_ATH_CPH, reg);
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPULLDATAPARERR_CPR_XLT);
+ reg &= err_mask->parerr_cpr_xlt_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP pull data err CPR_XLT: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPULLDATAPARERR_CPR_XLT, reg);
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPULLDATAPARERR_DCPR_UCS);
+ reg &= err_mask->parerr_dcpr_ucs_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP pull data err DCPR_UCS: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPULLDATAPARERR_DCPR_UCS, reg);
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPULLDATAPARERR_PKE);
+ reg &= err_mask->parerr_pke_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP pull data err PKE: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPULLDATAPARERR_PKE, reg);
+ }
+
+ if (err_mask->parerr_wat_wcp_mask) {
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPULLDATAPARERR_WAT_WCP);
+ reg &= err_mask->parerr_wat_wcp_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP pull data err WAT_WCP: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPULLDATAPARERR_WAT_WCP, reg);
+ }
+ }
+
+ return false;
+}
+
+static bool adf_handle_spp_pushcmd_err(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev);
+ bool reset_required = false;
+ u32 reg;
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPUSHCMDPARERR_ATH_CPH);
+ reg &= err_mask->parerr_ath_cph_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP push command fatal error ATH_CPH: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPUSHCMDPARERR_ATH_CPH, reg);
+
+ reset_required = true;
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPUSHCMDPARERR_CPR_XLT);
+ reg &= err_mask->parerr_cpr_xlt_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP push command fatal error CPR_XLT: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPUSHCMDPARERR_CPR_XLT, reg);
+
+ reset_required = true;
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPUSHCMDPARERR_DCPR_UCS);
+ reg &= err_mask->parerr_dcpr_ucs_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP push command fatal error DCPR_UCS: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPUSHCMDPARERR_DCPR_UCS, reg);
+
+ reset_required = true;
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPUSHCMDPARERR_PKE);
+ reg &= err_mask->parerr_pke_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP push command fatal error PKE: 0x%x\n",
+ reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPUSHCMDPARERR_PKE, reg);
+
+ reset_required = true;
+ }
+
+ if (err_mask->parerr_wat_wcp_mask) {
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPUSHCMDPARERR_WAT_WCP);
+ reg &= err_mask->parerr_wat_wcp_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP push command fatal error WAT_WCP: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPUSHCMDPARERR_WAT_WCP, reg);
+
+ reset_required = true;
+ }
+ }
+
+ return reset_required;
+}
+
+static bool adf_handle_spp_pushdata_err(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev);
+ u32 reg;
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPUSHDATAPARERR_ATH_CPH);
+ reg &= err_mask->parerr_ath_cph_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP push data err ATH_CPH: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPUSHDATAPARERR_ATH_CPH, reg);
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPUSHDATAPARERR_CPR_XLT);
+ reg &= err_mask->parerr_cpr_xlt_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP push data err CPR_XLT: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPUSHDATAPARERR_CPR_XLT, reg);
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPUSHDATAPARERR_DCPR_UCS);
+ reg &= err_mask->parerr_dcpr_ucs_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP push data err DCPR_UCS: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPUSHDATAPARERR_DCPR_UCS, reg);
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPUSHDATAPARERR_PKE);
+ reg &= err_mask->parerr_pke_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP push data err PKE: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPUSHDATAPARERR_PKE, reg);
+ }
+
+ if (err_mask->parerr_wat_wcp_mask) {
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SPPPUSHDATAPARERR_WAT_WCP);
+ reg &= err_mask->parerr_wat_wcp_mask;
+ if (reg) {
+ dev_err(&GET_DEV(accel_dev),
+ "SPP push data err WAT_WCP: 0x%x\n", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_SPPPUSHDATAPARERR_WAT_WCP,
+ reg);
+ }
+ }
+
+ return false;
+}
+
+static bool adf_handle_spppar_err(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 iastatssm)
+{
+ bool reset_required;
+
+ if (!(iastatssm & ADF_GEN4_IAINTSTATSSM_SPPPARERR_BIT))
+ return false;
+
+ reset_required = adf_handle_spp_pullcmd_err(accel_dev, csr);
+ reset_required |= adf_handle_spp_pulldata_err(accel_dev, csr);
+ reset_required |= adf_handle_spp_pushcmd_err(accel_dev, csr);
+ reset_required |= adf_handle_spp_pushdata_err(accel_dev, csr);
+
+ return reset_required;
+}
+
+static bool adf_handle_ssmcpppar_err(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 iastatssm)
+{
+ u32 reg = ADF_CSR_RD(csr, ADF_GEN4_SSMCPPERR);
+ u32 bits_num = BITS_PER_REG(reg);
+ bool reset_required = false;
+ unsigned long errs_bits;
+ u32 bit_iterator;
+
+ if (!(iastatssm & ADF_GEN4_IAINTSTATSSM_SSMCPPERR_BIT))
+ return false;
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SSMCPPERR);
+ reg &= ADF_GEN4_SSMCPPERR_FATAL_BITMASK | ADF_GEN4_SSMCPPERR_UNCERR_BITMASK;
+ if (reg & ADF_GEN4_SSMCPPERR_FATAL_BITMASK) {
+ dev_err(&GET_DEV(accel_dev),
+ "Fatal SSM CPP parity error: 0x%x\n", reg);
+
+ errs_bits = reg & ADF_GEN4_SSMCPPERR_FATAL_BITMASK;
+ for_each_set_bit(bit_iterator, &errs_bits, bits_num) {
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+ }
+ reset_required = true;
+ }
+
+ if (reg & ADF_GEN4_SSMCPPERR_UNCERR_BITMASK) {
+ dev_err(&GET_DEV(accel_dev),
+ "non-Fatal SSM CPP parity error: 0x%x\n", reg);
+ errs_bits = reg & ADF_GEN4_SSMCPPERR_UNCERR_BITMASK;
+
+ for_each_set_bit(bit_iterator, &errs_bits, bits_num) {
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ }
+ }
+
+ ADF_CSR_WR(csr, ADF_GEN4_SSMCPPERR, reg);
+
+ return reset_required;
+}
+
+static bool adf_handle_rf_parr_err(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 iastatssm)
+{
+ struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev);
+ u32 reg;
+
+ if (!(iastatssm & ADF_GEN4_IAINTSTATSSM_SSMSOFTERRORPARITY_BIT))
+ return false;
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SSMSOFTERRORPARITY_SRC);
+ reg &= ADF_GEN4_SSMSOFTERRORPARITY_SRC_BIT;
+ if (reg) {
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITY_SRC, reg);
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SSMSOFTERRORPARITY_ATH_CPH);
+ reg &= err_mask->parerr_ath_cph_mask;
+ if (reg) {
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITY_ATH_CPH, reg);
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SSMSOFTERRORPARITY_CPR_XLT);
+ reg &= err_mask->parerr_cpr_xlt_mask;
+ if (reg) {
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITY_CPR_XLT, reg);
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SSMSOFTERRORPARITY_DCPR_UCS);
+ reg &= err_mask->parerr_dcpr_ucs_mask;
+ if (reg) {
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITY_DCPR_UCS, reg);
+ }
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SSMSOFTERRORPARITY_PKE);
+ reg &= err_mask->parerr_pke_mask;
+ if (reg) {
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITY_PKE, reg);
+ }
+
+ if (err_mask->parerr_wat_wcp_mask) {
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SSMSOFTERRORPARITY_WAT_WCP);
+ reg &= err_mask->parerr_wat_wcp_mask;
+ if (reg) {
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITY_WAT_WCP,
+ reg);
+ }
+ }
+
+ dev_err(&GET_DEV(accel_dev), "Slice ssm soft parity error reported");
+
+ return false;
+}
+
+static bool adf_handle_ser_err_ssmsh(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 iastatssm)
+{
+ u32 reg = ADF_CSR_RD(csr, ADF_GEN4_SER_ERR_SSMSH);
+ u32 bits_num = BITS_PER_REG(reg);
+ bool reset_required = false;
+ unsigned long errs_bits;
+ u32 bit_iterator;
+
+ if (!(iastatssm & (ADF_GEN4_IAINTSTATSSM_SER_ERR_SSMSH_CERR_BIT |
+ ADF_GEN4_IAINTSTATSSM_SER_ERR_SSMSH_UNCERR_BIT)))
+ return false;
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_SER_ERR_SSMSH);
+ reg &= ADF_GEN4_SER_ERR_SSMSH_FATAL_BITMASK |
+ ADF_GEN4_SER_ERR_SSMSH_UNCERR_BITMASK |
+ ADF_GEN4_SER_ERR_SSMSH_CERR_BITMASK;
+ if (reg & ADF_GEN4_SER_ERR_SSMSH_FATAL_BITMASK) {
+ dev_err(&GET_DEV(accel_dev),
+ "Fatal SER_SSMSH_ERR: 0x%x\n", reg);
+
+ errs_bits = reg & ADF_GEN4_SER_ERR_SSMSH_FATAL_BITMASK;
+ for_each_set_bit(bit_iterator, &errs_bits, bits_num) {
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+ }
+
+ reset_required = true;
+ }
+
+ if (reg & ADF_GEN4_SER_ERR_SSMSH_UNCERR_BITMASK) {
+ dev_err(&GET_DEV(accel_dev),
+ "non-fatal SER_SSMSH_ERR: 0x%x\n", reg);
+
+ errs_bits = reg & ADF_GEN4_SER_ERR_SSMSH_UNCERR_BITMASK;
+ for_each_set_bit(bit_iterator, &errs_bits, bits_num) {
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ }
+ }
+
+ if (reg & ADF_GEN4_SER_ERR_SSMSH_CERR_BITMASK) {
+ dev_warn(&GET_DEV(accel_dev),
+ "Correctable SER_SSMSH_ERR: 0x%x\n", reg);
+
+ errs_bits = reg & ADF_GEN4_SER_ERR_SSMSH_CERR_BITMASK;
+ for_each_set_bit(bit_iterator, &errs_bits, bits_num) {
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_CORR);
+ }
+ }
+
+ ADF_CSR_WR(csr, ADF_GEN4_SER_ERR_SSMSH, reg);
+
+ return reset_required;
+}
+
+static bool adf_handle_iaintstatssm(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ u32 iastatssm = ADF_CSR_RD(csr, ADF_GEN4_IAINTSTATSSM);
+ bool reset_required;
+
+ iastatssm &= ADF_GEN4_IAINTSTATSSM_BITMASK;
+ if (!iastatssm)
+ return false;
+
+ reset_required = adf_handle_uerrssmsh(accel_dev, csr, iastatssm);
+ reset_required |= adf_handle_cerrssmsh(accel_dev, csr, iastatssm);
+ reset_required |= adf_handle_pperr_err(accel_dev, csr, iastatssm);
+ reset_required |= adf_handle_slice_hang_error(accel_dev, csr, iastatssm);
+ reset_required |= adf_handle_spppar_err(accel_dev, csr, iastatssm);
+ reset_required |= adf_handle_ssmcpppar_err(accel_dev, csr, iastatssm);
+ reset_required |= adf_handle_rf_parr_err(accel_dev, csr, iastatssm);
+ reset_required |= adf_handle_ser_err_ssmsh(accel_dev, csr, iastatssm);
+
+ ADF_CSR_WR(csr, ADF_GEN4_IAINTSTATSSM, iastatssm);
+
+ return reset_required;
+}
+
+static bool adf_handle_exprpssmcmpr(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ u32 reg = ADF_CSR_RD(csr, ADF_GEN4_EXPRPSSMCPR);
+
+ reg &= ADF_GEN4_EXPRPSSMCPR_UNCERR_BITMASK;
+ if (!reg)
+ return false;
+
+ dev_err(&GET_DEV(accel_dev),
+ "Uncorrectable error exception in SSM CMP: 0x%x", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_EXPRPSSMCPR, reg);
+
+ return false;
+}
+
+static bool adf_handle_exprpssmxlt(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ u32 reg = ADF_CSR_RD(csr, ADF_GEN4_EXPRPSSMXLT);
+
+ reg &= ADF_GEN4_EXPRPSSMXLT_UNCERR_BITMASK |
+ ADF_GEN4_EXPRPSSMXLT_CERR_BIT;
+ if (!reg)
+ return false;
+
+ if (reg & ADF_GEN4_EXPRPSSMXLT_UNCERR_BITMASK) {
+ dev_err(&GET_DEV(accel_dev),
+ "Uncorrectable error exception in SSM XLT: 0x%x", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ }
+
+ if (reg & ADF_GEN4_EXPRPSSMXLT_CERR_BIT) {
+ dev_warn(&GET_DEV(accel_dev),
+ "Correctable error exception in SSM XLT: 0x%x", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_CORR);
+ }
+
+ ADF_CSR_WR(csr, ADF_GEN4_EXPRPSSMXLT, reg);
+
+ return false;
+}
+
+static bool adf_handle_exprpssmdcpr(struct adf_accel_dev *accel_dev,
+ void __iomem *csr)
+{
+ u32 reg;
+ int i;
+
+ for (i = 0; i < ADF_GEN4_DCPR_SLICES_NUM; i++) {
+ reg = ADF_CSR_RD(csr, ADF_GEN4_EXPRPSSMDCPR(i));
+ reg &= ADF_GEN4_EXPRPSSMDCPR_UNCERR_BITMASK |
+ ADF_GEN4_EXPRPSSMDCPR_CERR_BITMASK;
+ if (!reg)
+ continue;
+
+ if (reg & ADF_GEN4_EXPRPSSMDCPR_UNCERR_BITMASK) {
+ dev_err(&GET_DEV(accel_dev),
+ "Uncorrectable error exception in SSM DCMP: 0x%x", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ }
+
+ if (reg & ADF_GEN4_EXPRPSSMDCPR_CERR_BITMASK) {
+ dev_warn(&GET_DEV(accel_dev),
+ "Correctable error exception in SSM DCMP: 0x%x", reg);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_CORR);
+ }
+
+ ADF_CSR_WR(csr, ADF_GEN4_EXPRPSSMDCPR(i), reg);
+ }
+
+ return false;
+}
+
+static bool adf_handle_ssm(struct adf_accel_dev *accel_dev, void __iomem *csr,
+ u32 errsou)
+{
+ bool reset_required;
+
+ if (!(errsou & ADF_GEN4_ERRSOU2_SSM_ERR_BIT))
+ return false;
+
+ reset_required = adf_handle_iaintstatssm(accel_dev, csr);
+ reset_required |= adf_handle_exprpssmcmpr(accel_dev, csr);
+ reset_required |= adf_handle_exprpssmxlt(accel_dev, csr);
+ reset_required |= adf_handle_exprpssmdcpr(accel_dev, csr);
+
+ return reset_required;
+}
+
+static bool adf_handle_cpp_cfc_err(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ bool reset_required = false;
+ u32 reg;
+
+ if (!(errsou & ADF_GEN4_ERRSOU2_CPP_CFC_ERR_STATUS_BIT))
+ return false;
+
+ reg = ADF_CSR_RD(csr, ADF_GEN4_CPP_CFC_ERR_STATUS);
+ if (reg & ADF_GEN4_CPP_CFC_ERR_STATUS_DATAPAR_BIT) {
+ dev_err(&GET_DEV(accel_dev),
+ "CPP_CFC_ERR: data parity: 0x%x", reg);
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ }
+
+ if (reg & ADF_GEN4_CPP_CFC_ERR_STATUS_CMDPAR_BIT) {
+ dev_err(&GET_DEV(accel_dev),
+ "CPP_CFC_ERR: command parity: 0x%x", reg);
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ reset_required = true;
+ }
+
+ if (reg & ADF_GEN4_CPP_CFC_ERR_STATUS_MERR_BIT) {
+ dev_err(&GET_DEV(accel_dev),
+ "CPP_CFC_ERR: multiple errors: 0x%x", reg);
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ reset_required = true;
+ }
+
+ ADF_CSR_WR(csr, ADF_GEN4_CPP_CFC_ERR_STATUS_CLR,
+ ADF_GEN4_CPP_CFC_ERR_STATUS_CLR_BITMASK);
+
+ return reset_required;
+}
+
+static void adf_gen4_process_errsou2(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou,
+ bool *reset_required)
+{
+ *reset_required |= adf_handle_ssm(accel_dev, csr, errsou);
+ *reset_required |= adf_handle_cpp_cfc_err(accel_dev, csr, errsou);
+}
+
+static bool adf_handle_timiscsts(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ u32 timiscsts;
+
+ if (!(errsou & ADF_GEN4_ERRSOU3_TIMISCSTS_BIT))
+ return false;
+
+ timiscsts = ADF_CSR_RD(csr, ADF_GEN4_TIMISCSTS);
+
+ dev_err(&GET_DEV(accel_dev),
+ "Fatal error in Transmit Interface: 0x%x\n", timiscsts);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ return true;
+}
+
+static bool adf_handle_ricppintsts(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ u32 ricppintsts;
+
+ if (!(errsou & ADF_GEN4_ERRSOU3_RICPPINTSTS_BITMASK))
+ return false;
+
+ ricppintsts = ADF_CSR_RD(csr, ADF_GEN4_RICPPINTSTS);
+ ricppintsts &= ADF_GEN4_RICPPINTSTS_BITMASK;
+
+ dev_err(&GET_DEV(accel_dev),
+ "RI CPP Uncorrectable Error: 0x%x\n", ricppintsts);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_RICPPINTSTS, ricppintsts);
+
+ return false;
+}
+
+static bool adf_handle_ticppintsts(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ u32 ticppintsts;
+
+ if (!(errsou & ADF_GEN4_ERRSOU3_TICPPINTSTS_BITMASK))
+ return false;
+
+ ticppintsts = ADF_CSR_RD(csr, ADF_GEN4_TICPPINTSTS);
+ ticppintsts &= ADF_GEN4_TICPPINTSTS_BITMASK;
+
+ dev_err(&GET_DEV(accel_dev),
+ "TI CPP Uncorrectable Error: 0x%x\n", ticppintsts);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_TICPPINTSTS, ticppintsts);
+
+ return false;
+}
+
+static bool adf_handle_aramcerr(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ u32 aram_cerr;
+
+ if (!(errsou & ADF_GEN4_ERRSOU3_REG_ARAMCERR_BIT))
+ return false;
+
+ aram_cerr = ADF_CSR_RD(csr, ADF_GEN4_REG_ARAMCERR);
+ aram_cerr &= ADF_GEN4_REG_ARAMCERR_BIT;
+
+ dev_warn(&GET_DEV(accel_dev),
+ "ARAM correctable error : 0x%x\n", aram_cerr);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_CORR);
+
+ aram_cerr |= ADF_GEN4_REG_ARAMCERR_EN_BITMASK;
+
+ ADF_CSR_WR(csr, ADF_GEN4_REG_ARAMCERR, aram_cerr);
+
+ return false;
+}
+
+static bool adf_handle_aramuerr(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ bool reset_required = false;
+ u32 aramuerr;
+
+ if (!(errsou & ADF_GEN4_ERRSOU3_REG_ARAMUERR_BIT))
+ return false;
+
+ aramuerr = ADF_CSR_RD(csr, ADF_GEN4_REG_ARAMUERR);
+ aramuerr &= ADF_GEN4_REG_ARAMUERR_ERROR_BIT |
+ ADF_GEN4_REG_ARAMUERR_MULTI_ERRORS_BIT;
+
+ if (!aramuerr)
+ return false;
+
+ if (aramuerr & ADF_GEN4_REG_ARAMUERR_MULTI_ERRORS_BIT) {
+ dev_err(&GET_DEV(accel_dev),
+ "ARAM multiple uncorrectable errors: 0x%x\n", aramuerr);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ reset_required = true;
+ } else {
+ dev_err(&GET_DEV(accel_dev),
+ "ARAM uncorrectable error: 0x%x\n", aramuerr);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ }
+
+ aramuerr |= ADF_GEN4_REG_ARAMUERR_EN_BITMASK;
+
+ ADF_CSR_WR(csr, ADF_GEN4_REG_ARAMUERR, aramuerr);
+
+ return reset_required;
+}
+
+static bool adf_handle_reg_cppmemtgterr(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ bool reset_required = false;
+ u32 cppmemtgterr;
+
+ if (!(errsou & ADF_GEN4_ERRSOU3_REG_ARAMUERR_BIT))
+ return false;
+
+ cppmemtgterr = ADF_CSR_RD(csr, ADF_GEN4_REG_CPPMEMTGTERR);
+ cppmemtgterr &= ADF_GEN4_REG_CPPMEMTGTERR_BITMASK |
+ ADF_GEN4_REG_CPPMEMTGTERR_MULTI_ERRORS_BIT;
+ if (!cppmemtgterr)
+ return false;
+
+ if (cppmemtgterr & ADF_GEN4_REG_CPPMEMTGTERR_MULTI_ERRORS_BIT) {
+ dev_err(&GET_DEV(accel_dev),
+ "Misc memory target multiple uncorrectable errors: 0x%x\n",
+ cppmemtgterr);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL);
+
+ reset_required = true;
+ } else {
+ dev_err(&GET_DEV(accel_dev),
+ "Misc memory target uncorrectable error: 0x%x\n", cppmemtgterr);
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ }
+
+ cppmemtgterr |= ADF_GEN4_REG_CPPMEMTGTERR_EN_BITMASK;
+
+ ADF_CSR_WR(csr, ADF_GEN4_REG_CPPMEMTGTERR, cppmemtgterr);
+
+ return reset_required;
+}
+
+static bool adf_handle_atufaultstatus(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 errsou)
+{
+ u32 i;
+ u32 max_rp_num = GET_HW_DATA(accel_dev)->num_banks;
+
+ if (!(errsou & ADF_GEN4_ERRSOU3_ATUFAULTSTATUS_BIT))
+ return false;
+
+ for (i = 0; i < max_rp_num; i++) {
+ u32 atufaultstatus = ADF_CSR_RD(csr, ADF_GEN4_ATUFAULTSTATUS(i));
+
+ atufaultstatus &= ADF_GEN4_ATUFAULTSTATUS_BIT;
+
+ if (atufaultstatus) {
+ dev_err(&GET_DEV(accel_dev),
+ "Ring Pair (%u) ATU detected fault: 0x%x\n", i,
+ atufaultstatus);
+
+ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR);
+
+ ADF_CSR_WR(csr, ADF_GEN4_ATUFAULTSTATUS(i), atufaultstatus);
+ }
+ }
+
+ return false;
+}
+
+static void adf_gen4_process_errsou3(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, void __iomem *aram_csr,
+ u32 errsou, bool *reset_required)
+{
+ *reset_required |= adf_handle_timiscsts(accel_dev, csr, errsou);
+ *reset_required |= adf_handle_ricppintsts(accel_dev, csr, errsou);
+ *reset_required |= adf_handle_ticppintsts(accel_dev, csr, errsou);
+ *reset_required |= adf_handle_aramcerr(accel_dev, aram_csr, errsou);
+ *reset_required |= adf_handle_aramuerr(accel_dev, aram_csr, errsou);
+ *reset_required |= adf_handle_reg_cppmemtgterr(accel_dev, aram_csr, errsou);
+ *reset_required |= adf_handle_atufaultstatus(accel_dev, csr, errsou);
+}
+
+static bool adf_gen4_handle_interrupt(struct adf_accel_dev *accel_dev,
+ bool *reset_required)
+{
+ void __iomem *aram_csr = adf_get_aram_base(accel_dev);
+ void __iomem *csr = adf_get_pmisc_base(accel_dev);
+ u32 errsou = ADF_CSR_RD(csr, ADF_GEN4_ERRSOU0);
+ bool handled = false;
+
+ *reset_required = false;
+
+ if (errsou & ADF_GEN4_ERRSOU0_BIT) {
+ adf_gen4_process_errsou0(accel_dev, csr);
+ handled = true;
+ }
+
+ errsou = ADF_CSR_RD(csr, ADF_GEN4_ERRSOU1);
+ if (errsou & ADF_GEN4_ERRSOU1_BITMASK) {
+ adf_gen4_process_errsou1(accel_dev, csr, errsou, reset_required);
+ handled = true;
+ }
+
+ errsou = ADF_CSR_RD(csr, ADF_GEN4_ERRSOU2);
+ if (errsou & ADF_GEN4_ERRSOU2_BITMASK) {
+ adf_gen4_process_errsou2(accel_dev, csr, errsou, reset_required);
+ handled = true;
+ }
+
+ errsou = ADF_CSR_RD(csr, ADF_GEN4_ERRSOU3);
+ if (errsou & ADF_GEN4_ERRSOU3_BITMASK) {
+ adf_gen4_process_errsou3(accel_dev, csr, aram_csr, errsou, reset_required);
+ handled = true;
+ }
+
+ return handled;
+}
+
+void adf_gen4_init_ras_ops(struct adf_ras_ops *ras_ops)
+{
+ ras_ops->enable_ras_errors = adf_gen4_enable_ras;
+ ras_ops->disable_ras_errors = adf_gen4_disable_ras;
+ ras_ops->handle_interrupt = adf_gen4_handle_interrupt;
+}
+EXPORT_SYMBOL_GPL(adf_gen4_init_ras_ops);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.h b/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.h
new file mode 100644
index 000000000000..53352083cd12
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.h
@@ -0,0 +1,825 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Intel Corporation */
+#ifndef ADF_GEN4_RAS_H_
+#define ADF_GEN4_RAS_H_
+
+#include <linux/bits.h>
+
+struct adf_ras_ops;
+
+/* ERRSOU0 Correctable error mask*/
+#define ADF_GEN4_ERRSOU0_BIT BIT(0)
+
+/* HI AE Correctable error log */
+#define ADF_GEN4_HIAECORERRLOG_CPP0 0x41A308
+
+/* HI AE Correctable error log enable */
+#define ADF_GEN4_HIAECORERRLOGENABLE_CPP0 0x41A318
+#define ADF_GEN4_ERRSOU1_HIAEUNCERRLOG_CPP0_BIT BIT(0)
+#define ADF_GEN4_ERRSOU1_HICPPAGENTCMDPARERRLOG_BIT BIT(1)
+#define ADF_GEN4_ERRSOU1_RIMEM_PARERR_STS_BIT BIT(2)
+#define ADF_GEN4_ERRSOU1_TIMEM_PARERR_STS_BIT BIT(3)
+#define ADF_GEN4_ERRSOU1_RIMISCSTS_BIT BIT(4)
+
+#define ADF_GEN4_ERRSOU1_BITMASK ( \
+ (ADF_GEN4_ERRSOU1_HIAEUNCERRLOG_CPP0_BIT) | \
+ (ADF_GEN4_ERRSOU1_HICPPAGENTCMDPARERRLOG_BIT) | \
+ (ADF_GEN4_ERRSOU1_RIMEM_PARERR_STS_BIT) | \
+ (ADF_GEN4_ERRSOU1_TIMEM_PARERR_STS_BIT) | \
+ (ADF_GEN4_ERRSOU1_RIMISCSTS_BIT))
+
+/* HI AE Uncorrectable error log */
+#define ADF_GEN4_HIAEUNCERRLOG_CPP0 0x41A300
+
+/* HI AE Uncorrectable error log enable */
+#define ADF_GEN4_HIAEUNCERRLOGENABLE_CPP0 0x41A320
+
+/* HI CPP Agent Command parity error log */
+#define ADF_GEN4_HICPPAGENTCMDPARERRLOG 0x41A310
+
+/* HI CPP Agent Command parity error logging enable */
+#define ADF_GEN4_HICPPAGENTCMDPARERRLOGENABLE 0x41A314
+
+/* RI Memory parity error status register */
+#define ADF_GEN4_RIMEM_PARERR_STS 0x41B128
+
+/* RI Memory parity error reporting enable */
+#define ADF_GEN4_RI_MEM_PAR_ERR_EN0 0x41B12C
+
+/*
+ * RI Memory parity error mask
+ * BIT(0) - BIT(3) - ri_iosf_pdata_rxq[0:3] parity error
+ * BIT(4) - ri_tlq_phdr parity error
+ * BIT(5) - ri_tlq_pdata parity error
+ * BIT(6) - ri_tlq_nphdr parity error
+ * BIT(7) - ri_tlq_npdata parity error
+ * BIT(8) - BIT(9) - ri_tlq_cplhdr[0:1] parity error
+ * BIT(10) - BIT(17) - ri_tlq_cpldata[0:7] parity error
+ * BIT(18) - set this bit to 1 to enable logging status to ri_mem_par_err_sts0
+ * BIT(19) - ri_cds_cmd_fifo parity error
+ * BIT(20) - ri_obc_ricpl_fifo parity error
+ * BIT(21) - ri_obc_tiricpl_fifo parity error
+ * BIT(22) - ri_obc_cppcpl_fifo parity error
+ * BIT(23) - ri_obc_pendcpl_fifo parity error
+ * BIT(24) - ri_cpp_cmd_fifo parity error
+ * BIT(25) - ri_cds_ticmd_fifo parity error
+ * BIT(26) - riti_cmd_fifo parity error
+ * BIT(27) - ri_int_msixtbl parity error
+ * BIT(28) - ri_int_imstbl parity error
+ * BIT(30) - ri_kpt_fuses parity error
+ */
+#define ADF_GEN4_RIMEM_PARERR_STS_UNCERR_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(5) | \
+ BIT(7) | BIT(10) | BIT(11) | BIT(12) | BIT(13) | \
+ BIT(14) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) | \
+ BIT(20) | BIT(21) | BIT(22) | BIT(23) | BIT(24) | BIT(25) | \
+ BIT(26) | BIT(27) | BIT(28) | BIT(30))
+
+#define ADF_GEN4_RIMEM_PARERR_STS_FATAL_BITMASK \
+ (BIT(4) | BIT(6) | BIT(8) | BIT(9))
+
+/* TI CI parity status */
+#define ADF_GEN4_TI_CI_PAR_STS 0x50060C
+
+/* TI CI parity reporting mask */
+#define ADF_GEN4_TI_CI_PAR_ERR_MASK 0x500608
+
+/*
+ * TI CI parity status mask
+ * BIT(0) - CdCmdQ_sts patiry error status
+ * BIT(1) - CdDataQ_sts parity error status
+ * BIT(3) - CPP_SkidQ_sts parity error status
+ * BIT(7) - CPP_SkidQ_sc_sts parity error status
+ */
+#define ADF_GEN4_TI_CI_PAR_STS_BITMASK \
+ (BIT(0) | BIT(1) | BIT(3) | BIT(7))
+
+/* TI PULLFUB parity status */
+#define ADF_GEN4_TI_PULL0FUB_PAR_STS 0x500618
+
+/* TI PULLFUB parity error reporting mask */
+#define ADF_GEN4_TI_PULL0FUB_PAR_ERR_MASK 0x500614
+
+/*
+ * TI PULLFUB parity status mask
+ * BIT(0) - TrnPullReqQ_sts parity status
+ * BIT(1) - TrnSharedDataQ_sts parity status
+ * BIT(2) - TrnPullReqDataQ_sts parity status
+ * BIT(4) - CPP_CiPullReqQ_sts parity status
+ * BIT(5) - CPP_TrnPullReqQ_sts parity status
+ * BIT(6) - CPP_PullidQ_sts parity status
+ * BIT(7) - CPP_WaitDataQ_sts parity status
+ * BIT(8) - CPP_CdDataQ_sts parity status
+ * BIT(9) - CPP_TrnDataQP0_sts parity status
+ * BIT(10) - BIT(11) - CPP_TrnDataQRF[00:01]_sts parity status
+ * BIT(12) - CPP_TrnDataQP1_sts parity status
+ * BIT(13) - BIT(14) - CPP_TrnDataQRF[10:11]_sts parity status
+ */
+#define ADF_GEN4_TI_PULL0FUB_PAR_STS_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | \
+ BIT(8) | BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14))
+
+/* TI PUSHUB parity status */
+#define ADF_GEN4_TI_PUSHFUB_PAR_STS 0x500630
+
+/* TI PUSHFUB parity error reporting mask */
+#define ADF_GEN4_TI_PUSHFUB_PAR_ERR_MASK 0x50062C
+
+/*
+ * TI PUSHUB parity status mask
+ * BIT(0) - SbPushReqQ_sts parity status
+ * BIT(1) - BIT(2) - SbPushDataQ[0:1]_sts parity status
+ * BIT(4) - CPP_CdPushReqQ_sts parity status
+ * BIT(5) - BIT(6) - CPP_CdPushDataQ[0:1]_sts parity status
+ * BIT(7) - CPP_SbPushReqQ_sts parity status
+ * BIT(8) - CPP_SbPushDataQP_sts parity status
+ * BIT(9) - BIT(10) - CPP_SbPushDataQRF[0:1]_sts parity status
+ */
+#define ADF_GEN4_TI_PUSHFUB_PAR_STS_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2) | BIT(4) | BIT(5) | \
+ BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10))
+
+/* TI CD parity status */
+#define ADF_GEN4_TI_CD_PAR_STS 0x50063C
+
+/* TI CD parity error mask */
+#define ADF_GEN4_TI_CD_PAR_ERR_MASK 0x500638
+
+/*
+ * TI CD parity status mask
+ * BIT(0) - BIT(15) - CtxMdRam[0:15]_sts parity status
+ * BIT(16) - Leaf2ClusterRam_sts parity status
+ * BIT(17) - BIT(18) - Ring2LeafRam[0:1]_sts parity status
+ * BIT(19) - VirtualQ_sts parity status
+ * BIT(20) - DtRdQ_sts parity status
+ * BIT(21) - DtWrQ_sts parity status
+ * BIT(22) - RiCmdQ_sts parity status
+ * BIT(23) - BypassQ_sts parity status
+ * BIT(24) - DtRdQ_sc_sts parity status
+ * BIT(25) - DtWrQ_sc_sts parity status
+ */
+#define ADF_GEN4_TI_CD_PAR_STS_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | \
+ BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13) | \
+ BIT(14) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | \
+ BIT(21) | BIT(22) | BIT(23) | BIT(24) | BIT(25))
+
+/* TI TRNSB parity status */
+#define ADF_GEN4_TI_TRNSB_PAR_STS 0x500648
+
+/* TI TRNSB Parity error reporting mask */
+#define ADF_GEN4_TI_TRNSB_PAR_ERR_MASK 0x500644
+
+/*
+ * TI TRNSB parity status mask
+ * BIT(0) - TrnPHdrQP_sts parity status
+ * BIT(1) - TrnPHdrQRF_sts parity status
+ * BIT(2) - TrnPDataQP_sts parity status
+ * BIT(3) - BIT(6) - TrnPDataQRF[0:3]_sts parity status
+ * BIT(7) - TrnNpHdrQP_sts parity status
+ * BIT(8) - BIT(9) - TrnNpHdrQRF[0:1]_sts parity status
+ * BIT(10) - TrnCplHdrQ_sts parity status
+ * BIT(11) - TrnPutObsReqQ_sts parity status
+ * BIT(12) - TrnPushReqQ_sts parity status
+ * BIT(13) - SbSplitIdRam_sts parity status
+ * BIT(14) - SbReqCountQ_sts parity status
+ * BIT(15) - SbCplTrkRam_sts parity status
+ * BIT(16) - SbGetObsReqQ_sts parity status
+ * BIT(17) - SbEpochIdQ_sts parity status
+ * BIT(18) - SbAtCplHdrQ_sts parity status
+ * BIT(19) - SbAtCplDataQ_sts parity status
+ * BIT(20) - SbReqCountRam_sts parity status
+ * BIT(21) - SbAtCplHdrQ_sc_sts parity status
+ */
+#define ADF_GEN4_TI_TRNSB_PAR_STS_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | \
+ BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | BIT(12) | \
+ BIT(13) | BIT(14) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | \
+ BIT(19) | BIT(20) | BIT(21))
+
+/* Status register to log misc error on RI */
+#define ADF_GEN4_RIMISCSTS 0x41B1B8
+
+/* Status control register to log misc RI error */
+#define ADF_GEN4_RIMISCCTL 0x41B1BC
+
+/*
+ * ERRSOU2 bit mask
+ * BIT(0) - SSM Interrupt Mask
+ * BIT(1) - CFC on CPP. ORed of CFC Push error and Pull error
+ * BIT(2) - BIT(4) - CPP attention interrupts, deprecated on gen4 devices
+ * BIT(18) - PM interrupt
+ */
+#define ADF_GEN4_ERRSOU2_SSM_ERR_BIT BIT(0)
+#define ADF_GEN4_ERRSOU2_CPP_CFC_ERR_STATUS_BIT BIT(1)
+#define ADF_GEN4_ERRSOU2_CPP_CFC_ATT_INT_BITMASK \
+ (BIT(2) | BIT(3) | BIT(4))
+
+#define ADF_GEN4_ERRSOU2_PM_INT_BIT BIT(18)
+
+#define ADF_GEN4_ERRSOU2_BITMASK \
+ (ADF_GEN4_ERRSOU2_SSM_ERR_BIT | \
+ ADF_GEN4_ERRSOU2_CPP_CFC_ERR_STATUS_BIT)
+
+#define ADF_GEN4_ERRSOU2_DIS_BITMASK \
+ (ADF_GEN4_ERRSOU2_SSM_ERR_BIT | \
+ ADF_GEN4_ERRSOU2_CPP_CFC_ERR_STATUS_BIT | \
+ ADF_GEN4_ERRSOU2_CPP_CFC_ATT_INT_BITMASK)
+
+#define ADF_GEN4_IAINTSTATSSM 0x28
+
+/* IAINTSTATSSM error bit mask definitions */
+#define ADF_GEN4_IAINTSTATSSM_UERRSSMSH_BIT BIT(0)
+#define ADF_GEN4_IAINTSTATSSM_CERRSSMSH_BIT BIT(1)
+#define ADF_GEN4_IAINTSTATSSM_PPERR_BIT BIT(2)
+#define ADF_GEN4_IAINTSTATSSM_SLICEHANG_ERR_BIT BIT(3)
+#define ADF_GEN4_IAINTSTATSSM_SPPPARERR_BIT BIT(4)
+#define ADF_GEN4_IAINTSTATSSM_SSMCPPERR_BIT BIT(5)
+#define ADF_GEN4_IAINTSTATSSM_SSMSOFTERRORPARITY_BIT BIT(6)
+#define ADF_GEN4_IAINTSTATSSM_SER_ERR_SSMSH_CERR_BIT BIT(7)
+#define ADF_GEN4_IAINTSTATSSM_SER_ERR_SSMSH_UNCERR_BIT BIT(8)
+
+#define ADF_GEN4_IAINTSTATSSM_BITMASK \
+ (ADF_GEN4_IAINTSTATSSM_UERRSSMSH_BIT | \
+ ADF_GEN4_IAINTSTATSSM_CERRSSMSH_BIT | \
+ ADF_GEN4_IAINTSTATSSM_PPERR_BIT | \
+ ADF_GEN4_IAINTSTATSSM_SLICEHANG_ERR_BIT | \
+ ADF_GEN4_IAINTSTATSSM_SPPPARERR_BIT | \
+ ADF_GEN4_IAINTSTATSSM_SSMCPPERR_BIT | \
+ ADF_GEN4_IAINTSTATSSM_SSMSOFTERRORPARITY_BIT | \
+ ADF_GEN4_IAINTSTATSSM_SER_ERR_SSMSH_CERR_BIT | \
+ ADF_GEN4_IAINTSTATSSM_SER_ERR_SSMSH_UNCERR_BIT)
+
+#define ADF_GEN4_UERRSSMSH 0x18
+
+/*
+ * UERRSSMSH error bit masks definitions
+ *
+ * BIT(0) - Indicates one uncorrectable error
+ * BIT(15) - Indicates multiple uncorrectable errors
+ * in device shared memory
+ */
+#define ADF_GEN4_UERRSSMSH_BITMASK (BIT(0) | BIT(15))
+
+#define ADF_GEN4_UERRSSMSHAD 0x1C
+
+#define ADF_GEN4_CERRSSMSH 0x10
+
+/*
+ * CERRSSMSH error bit
+ * BIT(0) - Indicates one correctable error
+ */
+#define ADF_GEN4_CERRSSMSH_ERROR_BIT BIT(0)
+
+#define ADF_GEN4_CERRSSMSHAD 0x14
+
+/* SSM error handling features enable register */
+#define ADF_GEN4_SSMFEATREN 0x198
+
+/*
+ * Disable SSM error detection and reporting features
+ * enabled by device driver on RAS initialization
+ *
+ * following bits should be cleared :
+ * BIT(4) - Disable parity for CPP parity
+ * BIT(12) - Disable logging push/pull data error in pperr register.
+ * BIT(16) - BIT(23) - Disable parity for SPPs
+ * BIT(24) - BIT(27) - Disable parity for SPPs, if it's supported on the device.
+ */
+#define ADF_GEN4_SSMFEATREN_DIS_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(5) | BIT(6) | BIT(7) | \
+ BIT(8) | BIT(9) | BIT(10) | BIT(11) | BIT(13) | BIT(14) | BIT(15))
+
+#define ADF_GEN4_INTMASKSSM 0x0
+
+/*
+ * Error reporting mask in INTMASKSSM
+ * BIT(0) - Shared memory uncorrectable interrupt mask
+ * BIT(1) - Shared memory correctable interrupt mask
+ * BIT(2) - PPERR interrupt mask
+ * BIT(3) - CPP parity error Interrupt mask
+ * BIT(4) - SSM interrupt generated by SER correctable error mask
+ * BIT(5) - SSM interrupt generated by SER uncorrectable error
+ * - not stop and scream - mask
+ */
+#define ADF_GEN4_INTMASKSSM_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5))
+
+/* CPP push or pull error */
+#define ADF_GEN4_PPERR 0x8
+
+#define ADF_GEN4_PPERR_BITMASK (BIT(0) | BIT(1))
+
+#define ADF_GEN4_PPERRID 0xC
+
+/* Slice hang handling related registers */
+#define ADF_GEN4_SLICEHANGSTATUS_ATH_CPH 0x84
+#define ADF_GEN4_SLICEHANGSTATUS_CPR_XLT 0x88
+#define ADF_GEN4_SLICEHANGSTATUS_DCPR_UCS 0x90
+#define ADF_GEN4_SLICEHANGSTATUS_WAT_WCP 0x8C
+#define ADF_GEN4_SLICEHANGSTATUS_PKE 0x94
+
+#define ADF_GEN4_SHINTMASKSSM_ATH_CPH 0xF0
+#define ADF_GEN4_SHINTMASKSSM_CPR_XLT 0xF4
+#define ADF_GEN4_SHINTMASKSSM_DCPR_UCS 0xFC
+#define ADF_GEN4_SHINTMASKSSM_WAT_WCP 0xF8
+#define ADF_GEN4_SHINTMASKSSM_PKE 0x100
+
+/* SPP pull cmd parity err_*slice* CSR */
+#define ADF_GEN4_SPPPULLCMDPARERR_ATH_CPH 0x1A4
+#define ADF_GEN4_SPPPULLCMDPARERR_CPR_XLT 0x1A8
+#define ADF_GEN4_SPPPULLCMDPARERR_DCPR_UCS 0x1B0
+#define ADF_GEN4_SPPPULLCMDPARERR_PKE 0x1B4
+#define ADF_GEN4_SPPPULLCMDPARERR_WAT_WCP 0x1AC
+
+/* SPP pull data parity err_*slice* CSR */
+#define ADF_GEN4_SPPPULLDATAPARERR_ATH_CPH 0x1BC
+#define ADF_GEN4_SPPPULLDATAPARERR_CPR_XLT 0x1C0
+#define ADF_GEN4_SPPPULLDATAPARERR_DCPR_UCS 0x1C8
+#define ADF_GEN4_SPPPULLDATAPARERR_PKE 0x1CC
+#define ADF_GEN4_SPPPULLDATAPARERR_WAT_WCP 0x1C4
+
+/* SPP push cmd parity err_*slice* CSR */
+#define ADF_GEN4_SPPPUSHCMDPARERR_ATH_CPH 0x1D4
+#define ADF_GEN4_SPPPUSHCMDPARERR_CPR_XLT 0x1D8
+#define ADF_GEN4_SPPPUSHCMDPARERR_DCPR_UCS 0x1E0
+#define ADF_GEN4_SPPPUSHCMDPARERR_PKE 0x1E4
+#define ADF_GEN4_SPPPUSHCMDPARERR_WAT_WCP 0x1DC
+
+/* SPP push data parity err_*slice* CSR */
+#define ADF_GEN4_SPPPUSHDATAPARERR_ATH_CPH 0x1EC
+#define ADF_GEN4_SPPPUSHDATAPARERR_CPR_XLT 0x1F0
+#define ADF_GEN4_SPPPUSHDATAPARERR_DCPR_UCS 0x1F8
+#define ADF_GEN4_SPPPUSHDATAPARERR_PKE 0x1FC
+#define ADF_GEN4_SPPPUSHDATAPARERR_WAT_WCP 0x1F4
+
+/* Accelerator SPP parity error mask registers */
+#define ADF_GEN4_SPPPARERRMSK_ATH_CPH 0x204
+#define ADF_GEN4_SPPPARERRMSK_CPR_XLT 0x208
+#define ADF_GEN4_SPPPARERRMSK_DCPR_UCS 0x210
+#define ADF_GEN4_SPPPARERRMSK_PKE 0x214
+#define ADF_GEN4_SPPPARERRMSK_WAT_WCP 0x20C
+
+#define ADF_GEN4_SSMCPPERR 0x224
+
+/*
+ * Uncorrectable error mask in SSMCPPERR
+ * BIT(0) - indicates CPP command parity error
+ * BIT(1) - indicates CPP Main Push PPID parity error
+ * BIT(2) - indicates CPP Main ePPID parity error
+ * BIT(3) - indicates CPP Main push data parity error
+ * BIT(4) - indicates CPP Main Pull PPID parity error
+ * BIT(5) - indicates CPP target pull data parity error
+ */
+#define ADF_GEN4_SSMCPPERR_FATAL_BITMASK \
+ (BIT(0) | BIT(1) | BIT(4))
+
+#define ADF_GEN4_SSMCPPERR_UNCERR_BITMASK \
+ (BIT(2) | BIT(3) | BIT(5))
+
+#define ADF_GEN4_SSMSOFTERRORPARITY_SRC 0x9C
+#define ADF_GEN4_SSMSOFTERRORPARITYMASK_SRC 0xB8
+
+#define ADF_GEN4_SSMSOFTERRORPARITY_ATH_CPH 0xA0
+#define ADF_GEN4_SSMSOFTERRORPARITYMASK_ATH_CPH 0xBC
+
+#define ADF_GEN4_SSMSOFTERRORPARITY_CPR_XLT 0xA4
+#define ADF_GEN4_SSMSOFTERRORPARITYMASK_CPR_XLT 0xC0
+
+#define ADF_GEN4_SSMSOFTERRORPARITY_DCPR_UCS 0xAC
+#define ADF_GEN4_SSMSOFTERRORPARITYMASK_DCPR_UCS 0xC8
+
+#define ADF_GEN4_SSMSOFTERRORPARITY_PKE 0xB0
+#define ADF_GEN4_SSMSOFTERRORPARITYMASK_PKE 0xCC
+
+#define ADF_GEN4_SSMSOFTERRORPARITY_WAT_WCP 0xA8
+#define ADF_GEN4_SSMSOFTERRORPARITYMASK_WAT_WCP 0xC4
+
+/* RF parity error detected in SharedRAM */
+#define ADF_GEN4_SSMSOFTERRORPARITY_SRC_BIT BIT(0)
+
+#define ADF_GEN4_SER_ERR_SSMSH 0x44C
+
+/*
+ * Fatal error mask in SER_ERR_SSMSH
+ * BIT(0) - Indicates an uncorrectable error has occurred in the
+ * accelerator controller command RFs
+ * BIT(2) - Parity error occurred in the bank SPP fifos
+ * BIT(3) - Indicates Parity error occurred in following fifos in
+ * the design
+ * BIT(4) - Parity error occurred in flops in the design
+ * BIT(5) - Uncorrectable error has occurred in the
+ * target push and pull data register flop
+ * BIT(7) - Indicates Parity error occurred in the Resource Manager
+ * pending lock request fifos
+ * BIT(8) - Indicates Parity error occurred in the Resource Manager
+ * MECTX command queues logic
+ * BIT(9) - Indicates Parity error occurred in the Resource Manager
+ * MECTX sigdone fifo flops
+ * BIT(10) - Indicates an uncorrectable error has occurred in the
+ * Resource Manager MECTX command RFs
+ * BIT(14) - Parity error occurred in Buffer Manager sigdone FIFO
+ */
+ #define ADF_GEN4_SER_ERR_SSMSH_FATAL_BITMASK \
+ (BIT(0) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(7) | \
+ BIT(8) | BIT(9) | BIT(10) | BIT(14))
+
+/*
+ * Uncorrectable error mask in SER_ERR_SSMSH
+ * BIT(12) Parity error occurred in Buffer Manager pool 0
+ * BIT(13) Parity error occurred in Buffer Manager pool 1
+ */
+#define ADF_GEN4_SER_ERR_SSMSH_UNCERR_BITMASK \
+ (BIT(12) | BIT(13))
+
+/*
+ * Correctable error mask in SER_ERR_SSMSH
+ * BIT(1) - Indicates a correctable Error has occurred
+ * in the slice controller command RFs
+ * BIT(6) - Indicates a correctable Error has occurred in
+ * the target push and pull data RFs
+ * BIT(11) - Indicates an correctable Error has occurred in
+ * the Resource Manager MECTX command RFs
+ */
+#define ADF_GEN4_SER_ERR_SSMSH_CERR_BITMASK \
+ (BIT(1) | BIT(6) | BIT(11))
+
+/* SSM shared memory SER error reporting mask */
+#define ADF_GEN4_SER_EN_SSMSH 0x450
+
+/*
+ * SSM SER error reporting mask in SER_en_err_ssmsh
+ * BIT(0) - Enables uncorrectable Error detection in :
+ * 1) slice controller command RFs.
+ * 2) target push/pull data registers
+ * BIT(1) - Enables correctable Error detection in :
+ * 1) slice controller command RFs
+ * 2) target push/pull data registers
+ * BIT(2) - Enables Parity error detection in
+ * 1) bank SPP fifos
+ * 2) gen4_pull_id_queue
+ * 3) gen4_push_id_queue
+ * 4) AE_pull_sigdn_fifo
+ * 5) DT_push_sigdn_fifo
+ * 6) slx_push_sigdn_fifo
+ * 7) secure_push_cmd_fifo
+ * 8) secure_pull_cmd_fifo
+ * 9) Head register in FIFO wrapper
+ * 10) current_cmd in individual push queue
+ * 11) current_cmd in individual pull queue
+ * 12) push_command_rxp arbitrated in ssm_push_cmd_queues
+ * 13) pull_command_rxp arbitrated in ssm_pull_cmd_queues
+ * BIT(3) - Enables uncorrectable Error detection in
+ * the resource manager mectx cmd RFs.
+ * BIT(4) - Enables correctable error detection in the Resource Manager
+ * mectx command RFs
+ * BIT(5) - Enables Parity error detection in
+ * 1) resource manager lock request fifo
+ * 2) mectx cmdqueues logic
+ * 3) mectx sigdone fifo
+ * BIT(6) - Enables Parity error detection in Buffer Manager pools
+ * and sigdone fifo
+ */
+#define ADF_GEN4_SER_EN_SSMSH_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6))
+
+#define ADF_GEN4_CPP_CFC_ERR_STATUS 0x640C04
+
+/*
+ * BIT(1) - Indicates multiple CPP CFC errors
+ * BIT(7) - Indicates CPP CFC command parity error type
+ * BIT(8) - Indicated CPP CFC data parity error type
+ */
+#define ADF_GEN4_CPP_CFC_ERR_STATUS_MERR_BIT BIT(1)
+#define ADF_GEN4_CPP_CFC_ERR_STATUS_CMDPAR_BIT BIT(7)
+#define ADF_GEN4_CPP_CFC_ERR_STATUS_DATAPAR_BIT BIT(8)
+
+/*
+ * BIT(0) - Enables CFC to detect and log push/pull data error
+ * BIT(1) - Enables CFC to generate interrupt to PCIEP for CPP error
+ * BIT(4) - When 1 Parity detection is disabled
+ * BIT(5) - When 1 Parity detection is disabled on CPP command bus
+ * BIT(6) - When 1 Parity detection is disabled on CPP push/pull bus
+ * BIT(9) - When 1 RF parity error detection is disabled
+ */
+#define ADF_GEN4_CPP_CFC_ERR_CTRL_BITMASK (BIT(0) | BIT(1))
+
+#define ADF_GEN4_CPP_CFC_ERR_CTRL_DIS_BITMASK \
+ (BIT(4) | BIT(5) | BIT(6) | BIT(9) | BIT(10))
+
+#define ADF_GEN4_CPP_CFC_ERR_CTRL 0x640C00
+
+/*
+ * BIT(0) - Clears bit(0) of ADF_GEN4_CPP_CFC_ERR_STATUS
+ * when an error is reported on CPP
+ * BIT(1) - Clears bit(1) of ADF_GEN4_CPP_CFC_ERR_STATUS
+ * when multiple errors are reported on CPP
+ * BIT(2) - Clears bit(2) of ADF_GEN4_CPP_CFC_ERR_STATUS
+ * when attention interrupt is reported
+ */
+#define ADF_GEN4_CPP_CFC_ERR_STATUS_CLR_BITMASK (BIT(0) | BIT(1) | BIT(2))
+#define ADF_GEN4_CPP_CFC_ERR_STATUS_CLR 0x640C08
+
+#define ADF_GEN4_CPP_CFC_ERR_PPID_LO 0x640C0C
+#define ADF_GEN4_CPP_CFC_ERR_PPID_HI 0x640C10
+
+/* Exception reporting in QAT SSM CMP */
+#define ADF_GEN4_EXPRPSSMCPR 0x2000
+
+/*
+ * Uncorrectable error mask in EXPRPSSMCPR
+ * BIT(2) - Hard fatal error
+ * BIT(16) - Parity error detected in CPR Push FIFO
+ * BIT(17) - Parity error detected in CPR Pull FIFO
+ * BIT(18) - Parity error detected in CPR Hash Table
+ * BIT(19) - Parity error detected in CPR History Buffer Copy 0
+ * BIT(20) - Parity error detected in CPR History Buffer Copy 1
+ * BIT(21) - Parity error detected in CPR History Buffer Copy 2
+ * BIT(22) - Parity error detected in CPR History Buffer Copy 3
+ * BIT(23) - Parity error detected in CPR History Buffer Copy 4
+ * BIT(24) - Parity error detected in CPR History Buffer Copy 5
+ * BIT(25) - Parity error detected in CPR History Buffer Copy 6
+ * BIT(26) - Parity error detected in CPR History Buffer Copy 7
+ */
+#define ADF_GEN4_EXPRPSSMCPR_UNCERR_BITMASK \
+ (BIT(2) | BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | \
+ BIT(21) | BIT(22) | BIT(23) | BIT(24) | BIT(25) | BIT(26))
+
+/* Exception reporting in QAT SSM XLT */
+#define ADF_GEN4_EXPRPSSMXLT 0xA000
+
+/*
+ * Uncorrectable error mask in EXPRPSSMXLT
+ * BIT(2) - If set, an Uncorrectable Error event occurred
+ * BIT(16) - Parity error detected in XLT Push FIFO
+ * BIT(17) - Parity error detected in XLT Pull FIFO
+ * BIT(18) - Parity error detected in XLT HCTB0
+ * BIT(19) - Parity error detected in XLT HCTB1
+ * BIT(20) - Parity error detected in XLT HCTB2
+ * BIT(21) - Parity error detected in XLT HCTB3
+ * BIT(22) - Parity error detected in XLT CBCL
+ * BIT(23) - Parity error detected in XLT LITPTR
+ */
+#define ADF_GEN4_EXPRPSSMXLT_UNCERR_BITMASK \
+ (BIT(2) | BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | \
+ BIT(22) | BIT(23))
+
+/*
+ * Correctable error mask in EXPRPSSMXLT
+ * BIT(3) - Correctable error event occurred.
+ */
+#define ADF_GEN4_EXPRPSSMXLT_CERR_BIT BIT(3)
+
+/* Exception reporting in QAT SSM DCMP */
+#define ADF_GEN4_EXPRPSSMDCPR(_n_) (0x12000 + (_n_) * 0x80)
+
+/*
+ * Uncorrectable error mask in EXPRPSSMDCPR
+ * BIT(2) - Even hard fatal error
+ * BIT(4) - Odd hard fatal error
+ * BIT(6) - decode soft error
+ * BIT(16) - Parity error detected in CPR Push FIFO
+ * BIT(17) - Parity error detected in CPR Pull FIFO
+ * BIT(18) - Parity error detected in the Input Buffer
+ * BIT(19) - symbuf0parerr
+ * Parity error detected in CPR Push FIFO
+ * BIT(20) - symbuf1parerr
+ * Parity error detected in CPR Push FIFO
+ */
+#define ADF_GEN4_EXPRPSSMDCPR_UNCERR_BITMASK \
+ (BIT(2) | BIT(4) | BIT(6) | BIT(16) | BIT(17) | \
+ BIT(18) | BIT(19) | BIT(20))
+
+/*
+ * Correctable error mask in EXPRPSSMDCPR
+ * BIT(3) - Even ecc correctable error
+ * BIT(5) - Odd ecc correctable error
+ */
+#define ADF_GEN4_EXPRPSSMDCPR_CERR_BITMASK (BIT(3) | BIT(5))
+
+#define ADF_GEN4_DCPR_SLICES_NUM 3
+
+/*
+ * ERRSOU3 bit masks
+ * BIT(0) - indicates error Response Order Overflow and/or BME error
+ * BIT(1) - indicates RI push/pull error
+ * BIT(2) - indicates TI push/pull error
+ * BIT(3) - indicates ARAM correctable error
+ * BIT(4) - indicates ARAM uncorrectable error
+ * BIT(5) - indicates TI pull parity error
+ * BIT(6) - indicates RI push parity error
+ * BIT(7) - indicates VFLR interrupt
+ * BIT(8) - indicates ring pair interrupts for ATU detected fault
+ * BIT(9) - indicates error when accessing RLT block
+ */
+#define ADF_GEN4_ERRSOU3_TIMISCSTS_BIT BIT(0)
+#define ADF_GEN4_ERRSOU3_RICPPINTSTS_BITMASK (BIT(1) | BIT(6))
+#define ADF_GEN4_ERRSOU3_TICPPINTSTS_BITMASK (BIT(2) | BIT(5))
+#define ADF_GEN4_ERRSOU3_REG_ARAMCERR_BIT BIT(3)
+#define ADF_GEN4_ERRSOU3_REG_ARAMUERR_BIT BIT(4)
+#define ADF_GEN4_ERRSOU3_VFLRNOTIFY_BIT BIT(7)
+#define ADF_GEN4_ERRSOU3_ATUFAULTSTATUS_BIT BIT(8)
+#define ADF_GEN4_ERRSOU3_RLTERROR_BIT BIT(9)
+
+#define ADF_GEN4_ERRSOU3_BITMASK ( \
+ (ADF_GEN4_ERRSOU3_TIMISCSTS_BIT) | \
+ (ADF_GEN4_ERRSOU3_RICPPINTSTS_BITMASK) | \
+ (ADF_GEN4_ERRSOU3_TICPPINTSTS_BITMASK) | \
+ (ADF_GEN4_ERRSOU3_REG_ARAMCERR_BIT) | \
+ (ADF_GEN4_ERRSOU3_REG_ARAMUERR_BIT) | \
+ (ADF_GEN4_ERRSOU3_VFLRNOTIFY_BIT) | \
+ (ADF_GEN4_ERRSOU3_ATUFAULTSTATUS_BIT) | \
+ (ADF_GEN4_ERRSOU3_RLTERROR_BIT))
+
+/* TI Misc status register */
+#define ADF_GEN4_TIMISCSTS 0x50054C
+
+/* TI Misc error reporting mask */
+#define ADF_GEN4_TIMISCCTL 0x500548
+
+/*
+ * TI Misc error reporting control mask
+ * BIT(0) - Enables error detection and logging in TIMISCSTS register
+ * BIT(1) - It has effect only when SRIOV enabled, this bit is 0 by default
+ * BIT(2) - Enables the D-F-x counter within the dispatch arbiter
+ * to start based on the command triggered from
+ * BIT(30) - Disables VFLR functionality
+ * By setting this bit will revert to CPM1.x functionality
+ * bits 1, 2 and 30 value should be preserved and not meant to be changed
+ * within RAS.
+ */
+#define ADF_GEN4_TIMISCCTL_BIT BIT(0)
+#define ADF_GEN4_TIMSCCTL_RELAY_BITMASK (BIT(1) | BIT(2) | BIT(30))
+
+/* RI CPP interface status register */
+#define ADF_GEN4_RICPPINTSTS 0x41A330
+
+/*
+ * Uncorrectable error mask in RICPPINTSTS register
+ * BIT(0) - RI asserted the CPP error signal during a push
+ * BIT(1) - RI detected the CPP error signal asserted during a pull
+ * BIT(2) - RI detected a push data parity error
+ * BIT(3) - RI detected a push valid parity error
+ */
+#define ADF_GEN4_RICPPINTSTS_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2) | BIT(3))
+
+/* RI CPP interface status register control */
+#define ADF_GEN4_RICPPINTCTL 0x41A32C
+
+/*
+ * Control bit mask for RICPPINTCTL register
+ * BIT(0) - value of 1 enables error detection and reporting
+ * on the RI CPP Push interface
+ * BIT(1) - value of 1 enables error detection and reporting
+ * on the RI CPP Pull interface
+ * BIT(2) - value of 1 enables error detection and reporting
+ * on the RI Parity
+ * BIT(3) - value of 1 enable checking parity on CPP
+ * BIT(4) - value of 1 enables the stop feature of the stop and stream
+ * for all RI CPP Command RFs
+ */
+#define ADF_GEN4_RICPPINTCTL_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4))
+
+/* Push ID of the command which triggered the transaction error on RI */
+#define ADF_GEN4_RIERRPUSHID 0x41A334
+
+/* Pull ID of the command which triggered the transaction error on RI */
+#define ADF_GEN4_RIERRPULLID 0x41A338
+
+/* TI CPP interface status register */
+#define ADF_GEN4_TICPPINTSTS 0x50053C
+
+/*
+ * Uncorrectable error mask in TICPPINTSTS register
+ * BIT(0) - value of 1 indicates that the TI asserted
+ * the CPP error signal during a push
+ * BIT(1) - value of 1 indicates that the TI detected
+ * the CPP error signal asserted during a pull
+ * BIT(2) - value of 1 indicates that the TI detected
+ * a pull data parity error
+ */
+#define ADF_GEN4_TICPPINTSTS_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2))
+
+/* TI CPP interface status register control */
+#define ADF_GEN4_TICPPINTCTL 0x500538
+
+/*
+ * Control bit mask for TICPPINTCTL register
+ * BIT(0) - value of 1 enables error detection and reporting on
+ * the TI CPP Push interface
+ * BIT(1) - value of 1 enables error detection and reporting on
+ * the TI CPP Push interface
+ * BIT(2) - value of 1 enables parity error detection and logging on
+ * the TI CPP Pull interface
+ * BIT(3) - value of 1 enables CPP CMD and Pull Data parity checking
+ * BIT(4) - value of 1 enables TI stop part of stop and scream mode on
+ * CPP/RF Parity error
+ */
+#define ADF_GEN4_TICPPINTCTL_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4))
+
+/* Push ID of the command which triggered the transaction error on TI */
+#define ADF_GEN4_TIERRPUSHID 0x500540
+
+/* Pull ID of the command which triggered the transaction error on TI */
+#define ADF_GEN4_TIERRPULLID 0x500544
+
+/* Correctable error in ARAM agent register */
+#define ADF_GEN4_REG_ARAMCERR 0x1700
+
+#define ADF_GEN4_REG_ARAMCERR_BIT BIT(0)
+
+/*
+ * Correctable error enablement in ARAM bit mask
+ * BIT(3) - enable ARAM RAM to fix and log correctable error
+ * BIT(26) - enables ARAM agent to generate interrupt for correctable error
+ */
+#define ADF_GEN4_REG_ARAMCERR_EN_BITMASK (BIT(3) | BIT(26))
+
+/* Correctable error address in ARAM agent register */
+#define ADF_GEN4_REG_ARAMCERRAD 0x1708
+
+/* Uncorrectable error in ARAM agent register */
+#define ADF_GEN4_REG_ARAMUERR 0x1704
+
+/*
+ * ARAM error bit mask
+ * BIT(0) - indicates error logged in ARAMCERR or ARAMUCERR
+ * BIT(18) - indicates uncorrectable multiple errors in ARAM agent
+ */
+#define ADF_GEN4_REG_ARAMUERR_ERROR_BIT BIT(0)
+#define ADF_GEN4_REG_ARAMUERR_MULTI_ERRORS_BIT BIT(18)
+
+/*
+ * Uncorrectable error enablement in ARAM bit mask
+ * BIT(3) - enable ARAM RAM to fix and log uncorrectable error
+ * BIT(19) - enables ARAM agent to generate interrupt for uncorrectable error
+ */
+#define ADF_GEN4_REG_ARAMUERR_EN_BITMASK (BIT(3) | BIT(19))
+
+/* Unorrectable error address in ARAM agent register */
+#define ADF_GEN4_REG_ARAMUERRAD 0x170C
+
+/* Uncorrectable error transaction push/pull ID registers*/
+#define ADF_GEN4_REG_ERRPPID_LO 0x1714
+#define ADF_GEN4_REG_ERRPPID_HI 0x1718
+
+/* ARAM ECC block error enablement */
+#define ADF_GEN4_REG_ARAMCERRUERR_EN 0x1808
+
+/*
+ * ARAM ECC block error control bit masks
+ * BIT(0) - enable ARAM CD ECC block error detecting
+ * BIT(1) - enable ARAM pull request ECC error detecting
+ * BIT(2) - enable ARAM command dispatch ECC error detecting
+ * BIT(3) - enable ARAM read datapath push ECC error detecting
+ * BIT(4) - enable ARAM read datapath pull ECC error detecting
+ * BIT(5) - enable ARAM RMW ECC error detecting
+ * BIT(6) - enable ARAM write datapath RMW ECC error detecting
+ * BIT(7) - enable ARAM write datapath ECC error detecting
+ */
+#define ADF_GEN4_REG_ARAMCERRUERR_EN_BITMASK \
+ (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | \
+ BIT(5) | BIT(6) | BIT(7))
+
+/* ARAM misc memory target error registers*/
+#define ADF_GEN4_REG_CPPMEMTGTERR 0x1710
+
+/*
+ * ARAM misc memory target error bit masks
+ * BIT(0) - indicates an error in ARAM target memory
+ * BIT(1) - indicates multiple errors in ARAM target memory
+ * BIT(4) - indicates pull error in ARAM target memory
+ * BIT(5) - indicates parity pull error in ARAM target memory
+ * BIT(6) - indicates push error in ARAM target memory
+ */
+#define ADF_GEN4_REG_CPPMEMTGTERR_BITMASK \
+ (BIT(0) | BIT(4) | BIT(5) | BIT(6))
+
+#define ADF_GEN4_REG_CPPMEMTGTERR_MULTI_ERRORS_BIT BIT(1)
+
+/*
+ * ARAM misc memory target error enablement mask
+ * BIT(2) - enables CPP memory to detect and log push/pull data error
+ * BIT(7) - enables push/pull error to generate interrupts to RI
+ * BIT(8) - enables ARAM to check parity on pull data and CPP command buses
+ * BIT(9) - enables ARAM to autopush to AE when push/parity error is detected
+ * on lookaside DT
+ */
+#define ADF_GEN4_REG_CPPMEMTGTERR_EN_BITMASK \
+ (BIT(2) | BIT(7) | BIT(8) | BIT(9))
+
+/* ATU fault status register */
+#define ADF_GEN4_ATUFAULTSTATUS(i) (0x506000 + ((i) * 0x4))
+
+#define ADF_GEN4_ATUFAULTSTATUS_BIT BIT(0)
+
+/* Command Parity error detected on IOSFP Command to QAT */
+#define ADF_GEN4_RIMISCSTS_BIT BIT(0)
+
+void adf_gen4_init_ras_ops(struct adf_ras_ops *ras_ops);
+
+#endif /* ADF_GEN4_RAS_H_ */
diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_timer.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_timer.c
index 646c57922fcd..35ccb91d6ec1 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_timer.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_timer.c
@@ -9,6 +9,7 @@
#include <linux/slab.h>
#include <linux/workqueue.h>
+#include "adf_admin.h"
#include "adf_accel_devices.h"
#include "adf_common_drv.h"
#include "adf_gen4_timer.h"
diff --git a/drivers/crypto/intel/qat/qat_common/adf_heartbeat.c b/drivers/crypto/intel/qat/qat_common/adf_heartbeat.c
index beef9a5f6c75..13f48d2f6da8 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_heartbeat.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_heartbeat.c
@@ -12,6 +12,7 @@
#include <linux/types.h>
#include <asm/errno.h>
#include "adf_accel_devices.h"
+#include "adf_admin.h"
#include "adf_cfg.h"
#include "adf_cfg_strings.h"
#include "adf_clock.h"
diff --git a/drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.c
index 803cbfd838f0..2661af6a2ef6 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/kstrtox.h>
#include <linux/types.h>
+#include "adf_admin.h"
#include "adf_cfg.h"
#include "adf_common_drv.h"
#include "adf_heartbeat.h"
diff --git a/drivers/crypto/intel/qat/qat_common/adf_init.c b/drivers/crypto/intel/qat/qat_common/adf_init.c
index 89001fe92e76..81c39f3d07e1 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_init.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_init.c
@@ -9,6 +9,8 @@
#include "adf_common_drv.h"
#include "adf_dbgfs.h"
#include "adf_heartbeat.h"
+#include "adf_rl.h"
+#include "adf_sysfs_ras_counters.h"
static LIST_HEAD(service_table);
static DEFINE_MUTEX(service_lock);
@@ -61,7 +63,6 @@ int adf_service_unregister(struct service_hndl *service)
static int adf_dev_init(struct adf_accel_dev *accel_dev)
{
struct service_hndl *service;
- struct list_head *list_itr;
struct adf_hw_device_data *hw_data = accel_dev->hw_device;
int ret;
@@ -97,6 +98,9 @@ static int adf_dev_init(struct adf_accel_dev *accel_dev)
return -EFAULT;
}
+ if (hw_data->get_ring_to_svc_map)
+ hw_data->ring_to_svc_map = hw_data->get_ring_to_svc_map(accel_dev);
+
if (adf_ae_init(accel_dev)) {
dev_err(&GET_DEV(accel_dev),
"Failed to initialise Acceleration Engine\n");
@@ -117,6 +121,9 @@ static int adf_dev_init(struct adf_accel_dev *accel_dev)
}
set_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
+ if (hw_data->ras_ops.enable_ras_errors)
+ hw_data->ras_ops.enable_ras_errors(accel_dev);
+
hw_data->enable_ints(accel_dev);
hw_data->enable_error_correction(accel_dev);
@@ -131,14 +138,16 @@ static int adf_dev_init(struct adf_accel_dev *accel_dev)
}
adf_heartbeat_init(accel_dev);
+ ret = adf_rl_init(accel_dev);
+ if (ret && ret != -EOPNOTSUPP)
+ return ret;
/*
* Subservice initialisation is divided into two stages: init and start.
* This is to facilitate any ordering dependencies between services
* prior to starting any of the accelerators.
*/
- list_for_each(list_itr, &service_table) {
- service = list_entry(list_itr, struct service_hndl, list);
+ list_for_each_entry(service, &service_table, list) {
if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
dev_err(&GET_DEV(accel_dev),
"Failed to initialise service %s\n",
@@ -165,7 +174,6 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev)
{
struct adf_hw_device_data *hw_data = accel_dev->hw_device;
struct service_hndl *service;
- struct list_head *list_itr;
int ret;
set_bit(ADF_STATUS_STARTING, &accel_dev->status);
@@ -208,9 +216,11 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev)
}
adf_heartbeat_start(accel_dev);
+ ret = adf_rl_start(accel_dev);
+ if (ret && ret != -EOPNOTSUPP)
+ return ret;
- list_for_each(list_itr, &service_table) {
- service = list_entry(list_itr, struct service_hndl, list);
+ list_for_each_entry(service, &service_table, list) {
if (service->event_hld(accel_dev, ADF_EVENT_START)) {
dev_err(&GET_DEV(accel_dev),
"Failed to start service %s\n",
@@ -231,6 +241,7 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev)
clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
return -EFAULT;
}
+ set_bit(ADF_STATUS_CRYPTO_ALGS_REGISTERED, &accel_dev->status);
if (!list_empty(&accel_dev->compression_list) && qat_comp_algs_register()) {
dev_err(&GET_DEV(accel_dev),
@@ -239,8 +250,10 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev)
clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
return -EFAULT;
}
+ set_bit(ADF_STATUS_COMP_ALGS_REGISTERED, &accel_dev->status);
adf_dbgfs_add(accel_dev);
+ adf_sysfs_start_ras(accel_dev);
return 0;
}
@@ -259,7 +272,6 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev)
{
struct adf_hw_device_data *hw_data = accel_dev->hw_device;
struct service_hndl *service;
- struct list_head *list_itr;
bool wait = false;
int ret;
@@ -267,21 +279,26 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev)
!test_bit(ADF_STATUS_STARTING, &accel_dev->status))
return;
+ adf_rl_stop(accel_dev);
adf_dbgfs_rm(accel_dev);
+ adf_sysfs_stop_ras(accel_dev);
clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
- if (!list_empty(&accel_dev->crypto_list)) {
+ if (!list_empty(&accel_dev->crypto_list) &&
+ test_bit(ADF_STATUS_CRYPTO_ALGS_REGISTERED, &accel_dev->status)) {
qat_algs_unregister();
qat_asym_algs_unregister();
}
+ clear_bit(ADF_STATUS_CRYPTO_ALGS_REGISTERED, &accel_dev->status);
- if (!list_empty(&accel_dev->compression_list))
+ if (!list_empty(&accel_dev->compression_list) &&
+ test_bit(ADF_STATUS_COMP_ALGS_REGISTERED, &accel_dev->status))
qat_comp_algs_unregister();
+ clear_bit(ADF_STATUS_COMP_ALGS_REGISTERED, &accel_dev->status);
- list_for_each(list_itr, &service_table) {
- service = list_entry(list_itr, struct service_hndl, list);
+ list_for_each_entry(service, &service_table, list) {
if (!test_bit(accel_dev->accel_id, service->start_status))
continue;
ret = service->event_hld(accel_dev, ADF_EVENT_STOP);
@@ -318,7 +335,6 @@ static void adf_dev_shutdown(struct adf_accel_dev *accel_dev)
{
struct adf_hw_device_data *hw_data = accel_dev->hw_device;
struct service_hndl *service;
- struct list_head *list_itr;
if (!hw_data) {
dev_err(&GET_DEV(accel_dev),
@@ -340,8 +356,7 @@ static void adf_dev_shutdown(struct adf_accel_dev *accel_dev)
&accel_dev->status);
}
- list_for_each(list_itr, &service_table) {
- service = list_entry(list_itr, struct service_hndl, list);
+ list_for_each_entry(service, &service_table, list) {
if (!test_bit(accel_dev->accel_id, service->init_status))
continue;
if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
@@ -352,6 +367,11 @@ static void adf_dev_shutdown(struct adf_accel_dev *accel_dev)
clear_bit(accel_dev->accel_id, service->init_status);
}
+ adf_rl_exit(accel_dev);
+
+ if (hw_data->ras_ops.disable_ras_errors)
+ hw_data->ras_ops.disable_ras_errors(accel_dev);
+
adf_heartbeat_shutdown(accel_dev);
hw_data->disable_iov(accel_dev);
@@ -378,10 +398,8 @@ static void adf_dev_shutdown(struct adf_accel_dev *accel_dev)
int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev)
{
struct service_hndl *service;
- struct list_head *list_itr;
- list_for_each(list_itr, &service_table) {
- service = list_entry(list_itr, struct service_hndl, list);
+ list_for_each_entry(service, &service_table, list) {
if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
dev_err(&GET_DEV(accel_dev),
"Failed to restart service %s.\n",
@@ -393,10 +411,8 @@ int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev)
int adf_dev_restarted_notify(struct adf_accel_dev *accel_dev)
{
struct service_hndl *service;
- struct list_head *list_itr;
- list_for_each(list_itr, &service_table) {
- service = list_entry(list_itr, struct service_hndl, list);
+ list_for_each_entry(service, &service_table, list) {
if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
dev_err(&GET_DEV(accel_dev),
"Failed to restart service %s.\n",
@@ -440,13 +456,6 @@ int adf_dev_down(struct adf_accel_dev *accel_dev, bool reconfig)
mutex_lock(&accel_dev->state_lock);
- if (!adf_dev_started(accel_dev)) {
- dev_info(&GET_DEV(accel_dev), "Device qat_dev%d already down\n",
- accel_dev->accel_id);
- ret = -EINVAL;
- goto out;
- }
-
if (reconfig) {
ret = adf_dev_shutdown_cache_cfg(accel_dev);
goto out;
diff --git a/drivers/crypto/intel/qat/qat_common/adf_isr.c b/drivers/crypto/intel/qat/qat_common/adf_isr.c
index 2aba194a7c29..3557a0d6dea2 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_isr.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_isr.c
@@ -132,6 +132,21 @@ static bool adf_handle_pm_int(struct adf_accel_dev *accel_dev)
return false;
}
+static bool adf_handle_ras_int(struct adf_accel_dev *accel_dev)
+{
+ struct adf_ras_ops *ras_ops = &accel_dev->hw_device->ras_ops;
+ bool reset_required;
+
+ if (ras_ops->handle_interrupt &&
+ ras_ops->handle_interrupt(accel_dev, &reset_required)) {
+ if (reset_required)
+ dev_err(&GET_DEV(accel_dev), "Fatal error, reset required\n");
+ return true;
+ }
+
+ return false;
+}
+
static irqreturn_t adf_msix_isr_ae(int irq, void *dev_ptr)
{
struct adf_accel_dev *accel_dev = dev_ptr;
@@ -145,6 +160,9 @@ static irqreturn_t adf_msix_isr_ae(int irq, void *dev_ptr)
if (adf_handle_pm_int(accel_dev))
return IRQ_HANDLED;
+ if (adf_handle_ras_int(accel_dev))
+ return IRQ_HANDLED;
+
dev_dbg(&GET_DEV(accel_dev), "qat_dev%d spurious AE interrupt\n",
accel_dev->accel_id);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs.c
new file mode 100644
index 000000000000..f0a13c190196
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Intel Corporation */
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+
+#include "adf_accel_devices.h"
+#include "adf_pm_dbgfs.h"
+
+static ssize_t pm_status_read(struct file *f, char __user *buf, size_t count,
+ loff_t *pos)
+{
+ struct adf_accel_dev *accel_dev = file_inode(f)->i_private;
+ struct adf_pm pm = accel_dev->power_management;
+
+ if (pm.print_pm_status)
+ return pm.print_pm_status(accel_dev, buf, count, pos);
+
+ return count;
+}
+
+static const struct file_operations pm_status_fops = {
+ .owner = THIS_MODULE,
+ .read = pm_status_read,
+};
+
+void adf_pm_dbgfs_add(struct adf_accel_dev *accel_dev)
+{
+ struct adf_pm *pm = &accel_dev->power_management;
+
+ if (!pm->present || !pm->print_pm_status)
+ return;
+
+ pm->debugfs_pm_status = debugfs_create_file("pm_status", 0400,
+ accel_dev->debugfs_dir,
+ accel_dev, &pm_status_fops);
+}
+
+void adf_pm_dbgfs_rm(struct adf_accel_dev *accel_dev)
+{
+ struct adf_pm *pm = &accel_dev->power_management;
+
+ if (!pm->present)
+ return;
+
+ debugfs_remove(pm->debugfs_pm_status);
+ pm->debugfs_pm_status = NULL;
+}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs.h b/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs.h
new file mode 100644
index 000000000000..83632e5aa097
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Intel Corporation */
+
+#ifndef ADF_PM_DBGFS_H_
+#define ADF_PM_DBGFS_H_
+
+struct adf_accel_dev;
+
+void adf_pm_dbgfs_rm(struct adf_accel_dev *accel_dev);
+void adf_pm_dbgfs_add(struct adf_accel_dev *accel_dev);
+
+#endif /* ADF_PM_DBGFS_H_ */
diff --git a/drivers/crypto/intel/qat/qat_common/adf_rl.c b/drivers/crypto/intel/qat/qat_common/adf_rl.c
new file mode 100644
index 000000000000..86e3e2152b1b
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_rl.c
@@ -0,0 +1,1169 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Intel Corporation */
+
+#define dev_fmt(fmt) "RateLimiting: " fmt
+
+#include <asm/errno.h>
+#include <asm/div64.h>
+
+#include <linux/dev_printk.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/units.h>
+
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "adf_rl_admin.h"
+#include "adf_rl.h"
+#include "adf_sysfs_rl.h"
+
+#define RL_TOKEN_GRANULARITY_PCIEIN_BUCKET 0U
+#define RL_TOKEN_GRANULARITY_PCIEOUT_BUCKET 0U
+#define RL_TOKEN_PCIE_SIZE 64
+#define RL_TOKEN_ASYM_SIZE 1024
+#define RL_CSR_SIZE 4U
+#define RL_CAPABILITY_MASK GENMASK(6, 4)
+#define RL_CAPABILITY_VALUE 0x70
+#define RL_VALIDATE_NON_ZERO(input) ((input) == 0)
+#define ROOT_MASK GENMASK(1, 0)
+#define CLUSTER_MASK GENMASK(3, 0)
+#define LEAF_MASK GENMASK(5, 0)
+
+static int validate_user_input(struct adf_accel_dev *accel_dev,
+ struct adf_rl_sla_input_data *sla_in,
+ bool is_update)
+{
+ const unsigned long rp_mask = sla_in->rp_mask;
+ size_t rp_mask_size;
+ int i, cnt;
+
+ if (sla_in->pir < sla_in->cir) {
+ dev_notice(&GET_DEV(accel_dev),
+ "PIR must be >= CIR, setting PIR to CIR\n");
+ sla_in->pir = sla_in->cir;
+ }
+
+ if (!is_update) {
+ cnt = 0;
+ rp_mask_size = sizeof(sla_in->rp_mask) * BITS_PER_BYTE;
+ for_each_set_bit(i, &rp_mask, rp_mask_size) {
+ if (++cnt > RL_RP_CNT_PER_LEAF_MAX) {
+ dev_notice(&GET_DEV(accel_dev),
+ "Too many ring pairs selected for this SLA\n");
+ return -EINVAL;
+ }
+ }
+
+ if (sla_in->srv >= ADF_SVC_NONE) {
+ dev_notice(&GET_DEV(accel_dev),
+ "Wrong service type\n");
+ return -EINVAL;
+ }
+
+ if (sla_in->type > RL_LEAF) {
+ dev_notice(&GET_DEV(accel_dev),
+ "Wrong node type\n");
+ return -EINVAL;
+ }
+
+ if (sla_in->parent_id < RL_PARENT_DEFAULT_ID ||
+ sla_in->parent_id >= RL_NODES_CNT_MAX) {
+ dev_notice(&GET_DEV(accel_dev),
+ "Wrong parent ID\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int validate_sla_id(struct adf_accel_dev *accel_dev, int sla_id)
+{
+ struct rl_sla *sla;
+
+ if (sla_id <= RL_SLA_EMPTY_ID || sla_id >= RL_NODES_CNT_MAX) {
+ dev_notice(&GET_DEV(accel_dev), "Provided ID is out of bounds\n");
+ return -EINVAL;
+ }
+
+ sla = accel_dev->rate_limiting->sla[sla_id];
+
+ if (!sla) {
+ dev_notice(&GET_DEV(accel_dev), "SLA with provided ID does not exist\n");
+ return -EINVAL;
+ }
+
+ if (sla->type != RL_LEAF) {
+ dev_notice(&GET_DEV(accel_dev), "This ID is reserved for internal use\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * find_parent() - Find the parent for a new SLA
+ * @rl_data: pointer to ratelimiting data
+ * @sla_in: pointer to user input data for a new SLA
+ *
+ * Function returns a pointer to the parent SLA. If the parent ID is provided
+ * as input in the user data, then such ID is validated and the parent SLA
+ * is returned.
+ * Otherwise, it returns the default parent SLA (root or cluster) for
+ * the new object.
+ *
+ * Return:
+ * * Pointer to the parent SLA object
+ * * NULL - when parent cannot be found
+ */
+static struct rl_sla *find_parent(struct adf_rl *rl_data,
+ struct adf_rl_sla_input_data *sla_in)
+{
+ int input_parent_id = sla_in->parent_id;
+ struct rl_sla *root = NULL;
+ struct rl_sla *parent_sla;
+ int i;
+
+ if (sla_in->type == RL_ROOT)
+ return NULL;
+
+ if (input_parent_id > RL_PARENT_DEFAULT_ID) {
+ parent_sla = rl_data->sla[input_parent_id];
+ /*
+ * SLA can be a parent if it has the same service as the child
+ * and its type is higher in the hierarchy,
+ * for example the parent type of a LEAF must be a CLUSTER.
+ */
+ if (parent_sla && parent_sla->srv == sla_in->srv &&
+ parent_sla->type == sla_in->type - 1)
+ return parent_sla;
+
+ return NULL;
+ }
+
+ /* If input_parent_id is not valid, get root for this service type. */
+ for (i = 0; i < RL_ROOT_MAX; i++) {
+ if (rl_data->root[i] && rl_data->root[i]->srv == sla_in->srv) {
+ root = rl_data->root[i];
+ break;
+ }
+ }
+
+ if (!root)
+ return NULL;
+
+ /*
+ * If the type of this SLA is cluster, then return the root.
+ * Otherwise, find the default (i.e. first) cluster for this service.
+ */
+ if (sla_in->type == RL_CLUSTER)
+ return root;
+
+ for (i = 0; i < RL_CLUSTER_MAX; i++) {
+ if (rl_data->cluster[i] && rl_data->cluster[i]->parent == root)
+ return rl_data->cluster[i];
+ }
+
+ return NULL;
+}
+
+static enum adf_cfg_service_type srv_to_cfg_svc_type(enum adf_base_services rl_srv)
+{
+ switch (rl_srv) {
+ case ADF_SVC_ASYM:
+ return ASYM;
+ case ADF_SVC_SYM:
+ return SYM;
+ case ADF_SVC_DC:
+ return COMP;
+ default:
+ return UNUSED;
+ }
+}
+
+/**
+ * get_sla_arr_of_type() - Returns a pointer to SLA type specific array
+ * @rl_data: pointer to ratelimiting data
+ * @type: SLA type
+ * @sla_arr: pointer to variable where requested pointer will be stored
+ *
+ * Return: Max number of elements allowed for the returned array
+ */
+static u32 get_sla_arr_of_type(struct adf_rl *rl_data, enum rl_node_type type,
+ struct rl_sla ***sla_arr)
+{
+ switch (type) {
+ case RL_LEAF:
+ *sla_arr = rl_data->leaf;
+ return RL_LEAF_MAX;
+ case RL_CLUSTER:
+ *sla_arr = rl_data->cluster;
+ return RL_CLUSTER_MAX;
+ case RL_ROOT:
+ *sla_arr = rl_data->root;
+ return RL_ROOT_MAX;
+ default:
+ *sla_arr = NULL;
+ return 0;
+ }
+}
+
+static bool is_service_enabled(struct adf_accel_dev *accel_dev,
+ enum adf_base_services rl_srv)
+{
+ enum adf_cfg_service_type arb_srv = srv_to_cfg_svc_type(rl_srv);
+ struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
+ u8 rps_per_bundle = hw_data->num_banks_per_vf;
+ int i;
+
+ for (i = 0; i < rps_per_bundle; i++) {
+ if (GET_SRV_TYPE(accel_dev, i) == arb_srv)
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * prepare_rp_ids() - Creates an array of ring pair IDs from bitmask
+ * @accel_dev: pointer to acceleration device structure
+ * @sla: SLA object data where result will be written
+ * @rp_mask: bitmask of ring pair IDs
+ *
+ * Function tries to convert provided bitmap to an array of IDs. It checks if
+ * RPs aren't in use, are assigned to SLA service or if a number of provided
+ * IDs is not too big. If successful, writes the result into the field
+ * sla->ring_pairs_cnt.
+ *
+ * Return:
+ * * 0 - ok
+ * * -EINVAL - ring pairs array cannot be created from provided mask
+ */
+static int prepare_rp_ids(struct adf_accel_dev *accel_dev, struct rl_sla *sla,
+ const unsigned long rp_mask)
+{
+ enum adf_cfg_service_type arb_srv = srv_to_cfg_svc_type(sla->srv);
+ u16 rps_per_bundle = GET_HW_DATA(accel_dev)->num_banks_per_vf;
+ bool *rp_in_use = accel_dev->rate_limiting->rp_in_use;
+ size_t rp_cnt_max = ARRAY_SIZE(sla->ring_pairs_ids);
+ u16 rp_id_max = GET_HW_DATA(accel_dev)->num_banks;
+ u16 cnt = 0;
+ u16 rp_id;
+
+ for_each_set_bit(rp_id, &rp_mask, rp_id_max) {
+ if (cnt >= rp_cnt_max) {
+ dev_notice(&GET_DEV(accel_dev),
+ "Assigned more ring pairs than supported");
+ return -EINVAL;
+ }
+
+ if (rp_in_use[rp_id]) {
+ dev_notice(&GET_DEV(accel_dev),
+ "RP %u already assigned to other SLA", rp_id);
+ return -EINVAL;
+ }
+
+ if (GET_SRV_TYPE(accel_dev, rp_id % rps_per_bundle) != arb_srv) {
+ dev_notice(&GET_DEV(accel_dev),
+ "RP %u does not support SLA service", rp_id);
+ return -EINVAL;
+ }
+
+ sla->ring_pairs_ids[cnt++] = rp_id;
+ }
+
+ sla->ring_pairs_cnt = cnt;
+
+ return 0;
+}
+
+static void mark_rps_usage(struct rl_sla *sla, bool *rp_in_use, bool used)
+{
+ u16 rp_id;
+ int i;
+
+ for (i = 0; i < sla->ring_pairs_cnt; i++) {
+ rp_id = sla->ring_pairs_ids[i];
+ rp_in_use[rp_id] = used;
+ }
+}
+
+static void assign_rps_to_leaf(struct adf_accel_dev *accel_dev,
+ struct rl_sla *sla, bool clear)
+{
+ struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
+ void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
+ u32 base_offset = hw_data->rl_data.r2l_offset;
+ u32 node_id = clear ? 0U : (sla->node_id & LEAF_MASK);
+ u32 offset;
+ int i;
+
+ for (i = 0; i < sla->ring_pairs_cnt; i++) {
+ offset = base_offset + (RL_CSR_SIZE * sla->ring_pairs_ids[i]);
+ ADF_CSR_WR(pmisc_addr, offset, node_id);
+ }
+}
+
+static void assign_leaf_to_cluster(struct adf_accel_dev *accel_dev,
+ struct rl_sla *sla, bool clear)
+{
+ struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
+ void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
+ u32 base_offset = hw_data->rl_data.l2c_offset;
+ u32 node_id = sla->node_id & LEAF_MASK;
+ u32 parent_id = clear ? 0U : (sla->parent->node_id & CLUSTER_MASK);
+ u32 offset;
+
+ offset = base_offset + (RL_CSR_SIZE * node_id);
+ ADF_CSR_WR(pmisc_addr, offset, parent_id);
+}
+
+static void assign_cluster_to_root(struct adf_accel_dev *accel_dev,
+ struct rl_sla *sla, bool clear)
+{
+ struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
+ void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
+ u32 base_offset = hw_data->rl_data.c2s_offset;
+ u32 node_id = sla->node_id & CLUSTER_MASK;
+ u32 parent_id = clear ? 0U : (sla->parent->node_id & ROOT_MASK);
+ u32 offset;
+
+ offset = base_offset + (RL_CSR_SIZE * node_id);
+ ADF_CSR_WR(pmisc_addr, offset, parent_id);
+}
+
+static void assign_node_to_parent(struct adf_accel_dev *accel_dev,
+ struct rl_sla *sla, bool clear_assignment)
+{
+ switch (sla->type) {
+ case RL_LEAF:
+ assign_rps_to_leaf(accel_dev, sla, clear_assignment);
+ assign_leaf_to_cluster(accel_dev, sla, clear_assignment);
+ break;
+ case RL_CLUSTER:
+ assign_cluster_to_root(accel_dev, sla, clear_assignment);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * can_parent_afford_sla() - Verifies if parent allows to create an SLA
+ * @sla_in: pointer to user input data for a new SLA
+ * @sla_parent: pointer to parent SLA object
+ * @sla_cir: current child CIR value (only for update)
+ * @is_update: request is a update
+ *
+ * Algorithm verifies if parent has enough remaining budget to take assignment
+ * of a child with provided parameters. In update case current CIR value must be
+ * returned to budget first.
+ * PIR value cannot exceed the PIR assigned to parent.
+ *
+ * Return:
+ * * true - SLA can be created
+ * * false - SLA cannot be created
+ */
+static bool can_parent_afford_sla(struct adf_rl_sla_input_data *sla_in,
+ struct rl_sla *sla_parent, u32 sla_cir,
+ bool is_update)
+{
+ u32 rem_cir = sla_parent->rem_cir;
+
+ if (is_update)
+ rem_cir += sla_cir;
+
+ if (sla_in->cir > rem_cir || sla_in->pir > sla_parent->pir)
+ return false;
+
+ return true;
+}
+
+/**
+ * can_node_afford_update() - Verifies if SLA can be updated with input data
+ * @sla_in: pointer to user input data for a new SLA
+ * @sla: pointer to SLA object selected for update
+ *
+ * Algorithm verifies if a new CIR value is big enough to satisfy currently
+ * assigned child SLAs and if PIR can be updated
+ *
+ * Return:
+ * * true - SLA can be updated
+ * * false - SLA cannot be updated
+ */
+static bool can_node_afford_update(struct adf_rl_sla_input_data *sla_in,
+ struct rl_sla *sla)
+{
+ u32 cir_in_use = sla->cir - sla->rem_cir;
+
+ /* new CIR cannot be smaller then currently consumed value */
+ if (cir_in_use > sla_in->cir)
+ return false;
+
+ /* PIR of root/cluster cannot be reduced in node with assigned children */
+ if (sla_in->pir < sla->pir && sla->type != RL_LEAF && cir_in_use > 0)
+ return false;
+
+ return true;
+}
+
+static bool is_enough_budget(struct adf_rl *rl_data, struct rl_sla *sla,
+ struct adf_rl_sla_input_data *sla_in,
+ bool is_update)
+{
+ u32 max_val = rl_data->device_data->scale_ref;
+ struct rl_sla *parent = sla->parent;
+ bool ret = true;
+
+ if (sla_in->cir > max_val || sla_in->pir > max_val)
+ ret = false;
+
+ switch (sla->type) {
+ case RL_LEAF:
+ ret &= can_parent_afford_sla(sla_in, parent, sla->cir,
+ is_update);
+ break;
+ case RL_CLUSTER:
+ ret &= can_parent_afford_sla(sla_in, parent, sla->cir,
+ is_update);
+
+ if (is_update)
+ ret &= can_node_afford_update(sla_in, sla);
+
+ break;
+ case RL_ROOT:
+ if (is_update)
+ ret &= can_node_afford_update(sla_in, sla);
+
+ break;
+ default:
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
+static void update_budget(struct rl_sla *sla, u32 old_cir, bool is_update)
+{
+ switch (sla->type) {
+ case RL_LEAF:
+ if (is_update)
+ sla->parent->rem_cir += old_cir;
+
+ sla->parent->rem_cir -= sla->cir;
+ sla->rem_cir = 0;
+ break;
+ case RL_CLUSTER:
+ if (is_update) {
+ sla->parent->rem_cir += old_cir;
+ sla->rem_cir = sla->cir - (old_cir - sla->rem_cir);
+ } else {
+ sla->rem_cir = sla->cir;
+ }
+
+ sla->parent->rem_cir -= sla->cir;
+ break;
+ case RL_ROOT:
+ if (is_update)
+ sla->rem_cir = sla->cir - (old_cir - sla->rem_cir);
+ else
+ sla->rem_cir = sla->cir;
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * get_next_free_sla_id() - finds next free ID in the SLA array
+ * @rl_data: Pointer to ratelimiting data structure
+ *
+ * Return:
+ * * 0 : RL_NODES_CNT_MAX - correct ID
+ * * -ENOSPC - all SLA slots are in use
+ */
+static int get_next_free_sla_id(struct adf_rl *rl_data)
+{
+ int i = 0;
+
+ while (i < RL_NODES_CNT_MAX && rl_data->sla[i++])
+ ;
+
+ if (i == RL_NODES_CNT_MAX)
+ return -ENOSPC;
+
+ return i - 1;
+}
+
+/**
+ * get_next_free_node_id() - finds next free ID in the array of that node type
+ * @rl_data: Pointer to ratelimiting data structure
+ * @sla: Pointer to SLA object for which the ID is searched
+ *
+ * Return:
+ * * 0 : RL_[NODE_TYPE]_MAX - correct ID
+ * * -ENOSPC - all slots of that type are in use
+ */
+static int get_next_free_node_id(struct adf_rl *rl_data, struct rl_sla *sla)
+{
+ struct adf_hw_device_data *hw_device = GET_HW_DATA(rl_data->accel_dev);
+ int max_id, i, step, rp_per_leaf;
+ struct rl_sla **sla_list;
+
+ rp_per_leaf = hw_device->num_banks / hw_device->num_banks_per_vf;
+
+ /*
+ * Static nodes mapping:
+ * root0 - cluster[0,4,8,12] - leaf[0-15]
+ * root1 - cluster[1,5,9,13] - leaf[16-31]
+ * root2 - cluster[2,6,10,14] - leaf[32-47]
+ */
+ switch (sla->type) {
+ case RL_LEAF:
+ i = sla->srv * rp_per_leaf;
+ step = 1;
+ max_id = i + rp_per_leaf;
+ sla_list = rl_data->leaf;
+ break;
+ case RL_CLUSTER:
+ i = sla->srv;
+ step = 4;
+ max_id = RL_CLUSTER_MAX;
+ sla_list = rl_data->cluster;
+ break;
+ case RL_ROOT:
+ return sla->srv;
+ default:
+ return -EINVAL;
+ }
+
+ while (i < max_id && sla_list[i])
+ i += step;
+
+ if (i >= max_id)
+ return -ENOSPC;
+
+ return i;
+}
+
+u32 adf_rl_calculate_slice_tokens(struct adf_accel_dev *accel_dev, u32 sla_val,
+ enum adf_base_services svc_type)
+{
+ struct adf_rl_hw_data *device_data = &accel_dev->hw_device->rl_data;
+ struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
+ u64 avail_slice_cycles, allocated_tokens;
+
+ if (!sla_val)
+ return 0;
+
+ avail_slice_cycles = hw_data->clock_frequency;
+
+ switch (svc_type) {
+ case ADF_SVC_ASYM:
+ avail_slice_cycles *= device_data->slices.pke_cnt;
+ break;
+ case ADF_SVC_SYM:
+ avail_slice_cycles *= device_data->slices.cph_cnt;
+ break;
+ case ADF_SVC_DC:
+ avail_slice_cycles *= device_data->slices.dcpr_cnt;
+ break;
+ default:
+ break;
+ }
+
+ do_div(avail_slice_cycles, device_data->scan_interval);
+ allocated_tokens = avail_slice_cycles * sla_val;
+ do_div(allocated_tokens, device_data->scale_ref);
+
+ return allocated_tokens;
+}
+
+u32 adf_rl_calculate_ae_cycles(struct adf_accel_dev *accel_dev, u32 sla_val,
+ enum adf_base_services svc_type)
+{
+ struct adf_rl_hw_data *device_data = &accel_dev->hw_device->rl_data;
+ struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
+ u64 allocated_ae_cycles, avail_ae_cycles;
+
+ if (!sla_val)
+ return 0;
+
+ avail_ae_cycles = hw_data->clock_frequency;
+ avail_ae_cycles *= hw_data->get_num_aes(hw_data) - 1;
+ do_div(avail_ae_cycles, device_data->scan_interval);
+
+ sla_val *= device_data->max_tp[svc_type];
+ sla_val /= device_data->scale_ref;
+
+ allocated_ae_cycles = (sla_val * avail_ae_cycles);
+ do_div(allocated_ae_cycles, device_data->max_tp[svc_type]);
+
+ return allocated_ae_cycles;
+}
+
+u32 adf_rl_calculate_pci_bw(struct adf_accel_dev *accel_dev, u32 sla_val,
+ enum adf_base_services svc_type, bool is_bw_out)
+{
+ struct adf_rl_hw_data *device_data = &accel_dev->hw_device->rl_data;
+ u64 sla_to_bytes, allocated_bw, sla_scaled;
+
+ if (!sla_val)
+ return 0;
+
+ sla_to_bytes = sla_val;
+ sla_to_bytes *= device_data->max_tp[svc_type];
+ do_div(sla_to_bytes, device_data->scale_ref);
+
+ sla_to_bytes *= (svc_type == ADF_SVC_ASYM) ? RL_TOKEN_ASYM_SIZE :
+ BYTES_PER_MBIT;
+ if (svc_type == ADF_SVC_DC && is_bw_out)
+ sla_to_bytes *= device_data->slices.dcpr_cnt -
+ device_data->dcpr_correction;
+
+ sla_scaled = sla_to_bytes * device_data->pcie_scale_mul;
+ do_div(sla_scaled, device_data->pcie_scale_div);
+ allocated_bw = sla_scaled;
+ do_div(allocated_bw, RL_TOKEN_PCIE_SIZE);
+ do_div(allocated_bw, device_data->scan_interval);
+
+ return allocated_bw;
+}
+
+/**
+ * add_new_sla_entry() - creates a new SLA object and fills it with user data
+ * @accel_dev: pointer to acceleration device structure
+ * @sla_in: pointer to user input data for a new SLA
+ * @sla_out: Pointer to variable that will contain the address of a new
+ * SLA object if the operation succeeds
+ *
+ * Return:
+ * * 0 - ok
+ * * -ENOMEM - memory allocation failed
+ * * -EINVAL - invalid user input
+ * * -ENOSPC - all available SLAs are in use
+ */
+static int add_new_sla_entry(struct adf_accel_dev *accel_dev,
+ struct adf_rl_sla_input_data *sla_in,
+ struct rl_sla **sla_out)
+{
+ struct adf_rl *rl_data = accel_dev->rate_limiting;
+ struct rl_sla *sla;
+ int ret = 0;
+
+ sla = kzalloc(sizeof(*sla), GFP_KERNEL);
+ if (!sla) {
+ ret = -ENOMEM;
+ goto ret_err;
+ }
+ *sla_out = sla;
+
+ if (!is_service_enabled(accel_dev, sla_in->srv)) {
+ dev_notice(&GET_DEV(accel_dev),
+ "Provided service is not enabled\n");
+ ret = -EINVAL;
+ goto ret_err;
+ }
+
+ sla->srv = sla_in->srv;
+ sla->type = sla_in->type;
+ ret = get_next_free_node_id(rl_data, sla);
+ if (ret < 0) {
+ dev_notice(&GET_DEV(accel_dev),
+ "Exceeded number of available nodes for that service\n");
+ goto ret_err;
+ }
+ sla->node_id = ret;
+
+ ret = get_next_free_sla_id(rl_data);
+ if (ret < 0) {
+ dev_notice(&GET_DEV(accel_dev),
+ "Allocated maximum SLAs number\n");
+ goto ret_err;
+ }
+ sla->sla_id = ret;
+
+ sla->parent = find_parent(rl_data, sla_in);
+ if (!sla->parent && sla->type != RL_ROOT) {
+ if (sla_in->parent_id != RL_PARENT_DEFAULT_ID)
+ dev_notice(&GET_DEV(accel_dev),
+ "Provided parent ID does not exist or cannot be parent for this SLA.");
+ else
+ dev_notice(&GET_DEV(accel_dev),
+ "Unable to find parent node for this service. Is service enabled?");
+ ret = -EINVAL;
+ goto ret_err;
+ }
+
+ if (sla->type == RL_LEAF) {
+ ret = prepare_rp_ids(accel_dev, sla, sla_in->rp_mask);
+ if (!sla->ring_pairs_cnt || ret) {
+ dev_notice(&GET_DEV(accel_dev),
+ "Unable to find ring pairs to assign to the leaf");
+ if (!ret)
+ ret = -EINVAL;
+
+ goto ret_err;
+ }
+ }
+
+ return 0;
+
+ret_err:
+ kfree(sla);
+ *sla_out = NULL;
+
+ return ret;
+}
+
+static int initialize_default_nodes(struct adf_accel_dev *accel_dev)
+{
+ struct adf_rl *rl_data = accel_dev->rate_limiting;
+ struct adf_rl_hw_data *device_data = rl_data->device_data;
+ struct adf_rl_sla_input_data sla_in = { };
+ int ret = 0;
+ int i;
+
+ /* Init root for each enabled service */
+ sla_in.type = RL_ROOT;
+ sla_in.parent_id = RL_PARENT_DEFAULT_ID;
+
+ for (i = 0; i < ADF_SVC_NONE; i++) {
+ if (!is_service_enabled(accel_dev, i))
+ continue;
+
+ sla_in.cir = device_data->scale_ref;
+ sla_in.pir = sla_in.cir;
+ sla_in.srv = i;
+
+ ret = adf_rl_add_sla(accel_dev, &sla_in);
+ if (ret)
+ return ret;
+ }
+
+ /* Init default cluster for each root */
+ sla_in.type = RL_CLUSTER;
+ for (i = 0; i < ADF_SVC_NONE; i++) {
+ if (!rl_data->root[i])
+ continue;
+
+ sla_in.cir = rl_data->root[i]->cir;
+ sla_in.pir = sla_in.cir;
+ sla_in.srv = rl_data->root[i]->srv;
+
+ ret = adf_rl_add_sla(accel_dev, &sla_in);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void clear_sla(struct adf_rl *rl_data, struct rl_sla *sla)
+{
+ bool *rp_in_use = rl_data->rp_in_use;
+ struct rl_sla **sla_type_arr = NULL;
+ int i, sla_id, node_id;
+ u32 old_cir;
+
+ sla_id = sla->sla_id;
+ node_id = sla->node_id;
+ old_cir = sla->cir;
+ sla->cir = 0;
+ sla->pir = 0;
+
+ for (i = 0; i < sla->ring_pairs_cnt; i++)
+ rp_in_use[sla->ring_pairs_ids[i]] = false;
+
+ update_budget(sla, old_cir, true);
+ get_sla_arr_of_type(rl_data, sla->type, &sla_type_arr);
+ assign_node_to_parent(rl_data->accel_dev, sla, true);
+ adf_rl_send_admin_delete_msg(rl_data->accel_dev, node_id, sla->type);
+ mark_rps_usage(sla, rl_data->rp_in_use, false);
+
+ kfree(sla);
+ rl_data->sla[sla_id] = NULL;
+ sla_type_arr[node_id] = NULL;
+}
+
+/**
+ * add_update_sla() - handles the creation and the update of an SLA
+ * @accel_dev: pointer to acceleration device structure
+ * @sla_in: pointer to user input data for a new/updated SLA
+ * @is_update: flag to indicate if this is an update or an add operation
+ *
+ * Return:
+ * * 0 - ok
+ * * -ENOMEM - memory allocation failed
+ * * -EINVAL - user input data cannot be used to create SLA
+ * * -ENOSPC - all available SLAs are in use
+ */
+static int add_update_sla(struct adf_accel_dev *accel_dev,
+ struct adf_rl_sla_input_data *sla_in, bool is_update)
+{
+ struct adf_rl *rl_data = accel_dev->rate_limiting;
+ struct rl_sla **sla_type_arr = NULL;
+ struct rl_sla *sla = NULL;
+ u32 old_cir = 0;
+ int ret;
+
+ if (!sla_in) {
+ dev_warn(&GET_DEV(accel_dev),
+ "SLA input data pointer is missing\n");
+ ret = -EFAULT;
+ goto ret_err;
+ }
+
+ /* Input validation */
+ ret = validate_user_input(accel_dev, sla_in, is_update);
+ if (ret)
+ goto ret_err;
+
+ mutex_lock(&rl_data->rl_lock);
+
+ if (is_update) {
+ ret = validate_sla_id(accel_dev, sla_in->sla_id);
+ if (ret)
+ goto ret_err;
+
+ sla = rl_data->sla[sla_in->sla_id];
+ old_cir = sla->cir;
+ } else {
+ ret = add_new_sla_entry(accel_dev, sla_in, &sla);
+ if (ret)
+ goto ret_err;
+ }
+
+ if (!is_enough_budget(rl_data, sla, sla_in, is_update)) {
+ dev_notice(&GET_DEV(accel_dev),
+ "Input value exceeds the remaining budget%s\n",
+ is_update ? " or more budget is already in use" : "");
+ ret = -EINVAL;
+ goto ret_err;
+ }
+ sla->cir = sla_in->cir;
+ sla->pir = sla_in->pir;
+
+ /* Apply SLA */
+ assign_node_to_parent(accel_dev, sla, false);
+ ret = adf_rl_send_admin_add_update_msg(accel_dev, sla, is_update);
+ if (ret) {
+ dev_notice(&GET_DEV(accel_dev),
+ "Failed to apply an SLA\n");
+ goto ret_err;
+ }
+ update_budget(sla, old_cir, is_update);
+
+ if (!is_update) {
+ mark_rps_usage(sla, rl_data->rp_in_use, true);
+ get_sla_arr_of_type(rl_data, sla->type, &sla_type_arr);
+ sla_type_arr[sla->node_id] = sla;
+ rl_data->sla[sla->sla_id] = sla;
+ }
+
+ sla_in->sla_id = sla->sla_id;
+ goto ret_ok;
+
+ret_err:
+ if (!is_update) {
+ sla_in->sla_id = -1;
+ kfree(sla);
+ }
+ret_ok:
+ mutex_unlock(&rl_data->rl_lock);
+ return ret;
+}
+
+/**
+ * adf_rl_add_sla() - handles the creation of an SLA
+ * @accel_dev: pointer to acceleration device structure
+ * @sla_in: pointer to user input data required to add an SLA
+ *
+ * Return:
+ * * 0 - ok
+ * * -ENOMEM - memory allocation failed
+ * * -EINVAL - invalid user input
+ * * -ENOSPC - all available SLAs are in use
+ */
+int adf_rl_add_sla(struct adf_accel_dev *accel_dev,
+ struct adf_rl_sla_input_data *sla_in)
+{
+ return add_update_sla(accel_dev, sla_in, false);
+}
+
+/**
+ * adf_rl_update_sla() - handles the update of an SLA
+ * @accel_dev: pointer to acceleration device structure
+ * @sla_in: pointer to user input data required to update an SLA
+ *
+ * Return:
+ * * 0 - ok
+ * * -EINVAL - user input data cannot be used to update SLA
+ */
+int adf_rl_update_sla(struct adf_accel_dev *accel_dev,
+ struct adf_rl_sla_input_data *sla_in)
+{
+ return add_update_sla(accel_dev, sla_in, true);
+}
+
+/**
+ * adf_rl_get_sla() - returns an existing SLA data
+ * @accel_dev: pointer to acceleration device structure
+ * @sla_in: pointer to user data where SLA info will be stored
+ *
+ * The sla_id for which data are requested should be set in sla_id structure
+ *
+ * Return:
+ * * 0 - ok
+ * * -EINVAL - provided sla_id does not exist
+ */
+int adf_rl_get_sla(struct adf_accel_dev *accel_dev,
+ struct adf_rl_sla_input_data *sla_in)
+{
+ struct rl_sla *sla;
+ int ret, i;
+
+ ret = validate_sla_id(accel_dev, sla_in->sla_id);
+ if (ret)
+ return ret;
+
+ sla = accel_dev->rate_limiting->sla[sla_in->sla_id];
+ sla_in->type = sla->type;
+ sla_in->srv = sla->srv;
+ sla_in->cir = sla->cir;
+ sla_in->pir = sla->pir;
+ sla_in->rp_mask = 0U;
+ if (sla->parent)
+ sla_in->parent_id = sla->parent->sla_id;
+ else
+ sla_in->parent_id = RL_PARENT_DEFAULT_ID;
+
+ for (i = 0; i < sla->ring_pairs_cnt; i++)
+ sla_in->rp_mask |= BIT(sla->ring_pairs_ids[i]);
+
+ return 0;
+}
+
+/**
+ * adf_rl_get_capability_remaining() - returns the remaining SLA value (CIR) for
+ * selected service or provided sla_id
+ * @accel_dev: pointer to acceleration device structure
+ * @srv: service ID for which capability is requested
+ * @sla_id: ID of the cluster or root to which we want assign a new SLA
+ *
+ * Check if the provided SLA id is valid. If it is and the service matches
+ * the requested service and the type is cluster or root, return the remaining
+ * capability.
+ * If the provided ID does not match the service or type, return the remaining
+ * capacity of the default cluster for that service.
+ *
+ * Return:
+ * * Positive value - correct remaining value
+ * * -EINVAL - algorithm cannot find a remaining value for provided data
+ */
+int adf_rl_get_capability_remaining(struct adf_accel_dev *accel_dev,
+ enum adf_base_services srv, int sla_id)
+{
+ struct adf_rl *rl_data = accel_dev->rate_limiting;
+ struct rl_sla *sla = NULL;
+ int i;
+
+ if (srv >= ADF_SVC_NONE)
+ return -EINVAL;
+
+ if (sla_id > RL_SLA_EMPTY_ID && !validate_sla_id(accel_dev, sla_id)) {
+ sla = rl_data->sla[sla_id];
+
+ if (sla->srv == srv && sla->type <= RL_CLUSTER)
+ goto ret_ok;
+ }
+
+ for (i = 0; i < RL_CLUSTER_MAX; i++) {
+ if (!rl_data->cluster[i])
+ continue;
+
+ if (rl_data->cluster[i]->srv == srv) {
+ sla = rl_data->cluster[i];
+ goto ret_ok;
+ }
+ }
+
+ return -EINVAL;
+ret_ok:
+ return sla->rem_cir;
+}
+
+/**
+ * adf_rl_remove_sla() - removes provided sla_id
+ * @accel_dev: pointer to acceleration device structure
+ * @sla_id: ID of the cluster or root to which we want assign an new SLA
+ *
+ * Return:
+ * * 0 - ok
+ * * -EINVAL - wrong sla_id or it still have assigned children
+ */
+int adf_rl_remove_sla(struct adf_accel_dev *accel_dev, u32 sla_id)
+{
+ struct adf_rl *rl_data = accel_dev->rate_limiting;
+ struct rl_sla *sla;
+ int ret = 0;
+
+ mutex_lock(&rl_data->rl_lock);
+ ret = validate_sla_id(accel_dev, sla_id);
+ if (ret)
+ goto err_ret;
+
+ sla = rl_data->sla[sla_id];
+
+ if (sla->type < RL_LEAF && sla->rem_cir != sla->cir) {
+ dev_notice(&GET_DEV(accel_dev),
+ "To remove parent SLA all its children must be removed first");
+ ret = -EINVAL;
+ goto err_ret;
+ }
+
+ clear_sla(rl_data, sla);
+
+err_ret:
+ mutex_unlock(&rl_data->rl_lock);
+ return ret;
+}
+
+/**
+ * adf_rl_remove_sla_all() - removes all SLAs from device
+ * @accel_dev: pointer to acceleration device structure
+ * @incl_default: set to true if default SLAs also should be removed
+ */
+void adf_rl_remove_sla_all(struct adf_accel_dev *accel_dev, bool incl_default)
+{
+ struct adf_rl *rl_data = accel_dev->rate_limiting;
+ int end_type = incl_default ? RL_ROOT : RL_LEAF;
+ struct rl_sla **sla_type_arr = NULL;
+ u32 max_id;
+ int i, j;
+
+ mutex_lock(&rl_data->rl_lock);
+
+ /* Unregister and remove all SLAs */
+ for (j = RL_LEAF; j >= end_type; j--) {
+ max_id = get_sla_arr_of_type(rl_data, j, &sla_type_arr);
+
+ for (i = 0; i < max_id; i++) {
+ if (!sla_type_arr[i])
+ continue;
+
+ clear_sla(rl_data, sla_type_arr[i]);
+ }
+ }
+
+ mutex_unlock(&rl_data->rl_lock);
+}
+
+int adf_rl_init(struct adf_accel_dev *accel_dev)
+{
+ struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
+ struct adf_rl_hw_data *rl_hw_data = &hw_data->rl_data;
+ struct adf_rl *rl;
+ int ret = 0;
+
+ /* Validate device parameters */
+ if (RL_VALIDATE_NON_ZERO(rl_hw_data->max_tp[ADF_SVC_ASYM]) ||
+ RL_VALIDATE_NON_ZERO(rl_hw_data->max_tp[ADF_SVC_SYM]) ||
+ RL_VALIDATE_NON_ZERO(rl_hw_data->max_tp[ADF_SVC_DC]) ||
+ RL_VALIDATE_NON_ZERO(rl_hw_data->scan_interval) ||
+ RL_VALIDATE_NON_ZERO(rl_hw_data->pcie_scale_div) ||
+ RL_VALIDATE_NON_ZERO(rl_hw_data->pcie_scale_mul) ||
+ RL_VALIDATE_NON_ZERO(rl_hw_data->scale_ref)) {
+ ret = -EOPNOTSUPP;
+ goto err_ret;
+ }
+
+ rl = kzalloc(sizeof(*rl), GFP_KERNEL);
+ if (!rl) {
+ ret = -ENOMEM;
+ goto err_ret;
+ }
+
+ mutex_init(&rl->rl_lock);
+ rl->device_data = &accel_dev->hw_device->rl_data;
+ rl->accel_dev = accel_dev;
+ accel_dev->rate_limiting = rl;
+
+err_ret:
+ return ret;
+}
+
+int adf_rl_start(struct adf_accel_dev *accel_dev)
+{
+ struct adf_rl_hw_data *rl_hw_data = &GET_HW_DATA(accel_dev)->rl_data;
+ void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
+ u16 fw_caps = GET_HW_DATA(accel_dev)->fw_capabilities;
+ int ret;
+
+ if (!accel_dev->rate_limiting) {
+ ret = -EOPNOTSUPP;
+ goto ret_err;
+ }
+
+ if ((fw_caps & RL_CAPABILITY_MASK) != RL_CAPABILITY_VALUE) {
+ dev_info(&GET_DEV(accel_dev), "not supported\n");
+ ret = -EOPNOTSUPP;
+ goto ret_free;
+ }
+
+ ADF_CSR_WR(pmisc_addr, rl_hw_data->pciin_tb_offset,
+ RL_TOKEN_GRANULARITY_PCIEIN_BUCKET);
+ ADF_CSR_WR(pmisc_addr, rl_hw_data->pciout_tb_offset,
+ RL_TOKEN_GRANULARITY_PCIEOUT_BUCKET);
+
+ ret = adf_rl_send_admin_init_msg(accel_dev, &rl_hw_data->slices);
+ if (ret) {
+ dev_err(&GET_DEV(accel_dev), "initialization failed\n");
+ goto ret_free;
+ }
+
+ ret = initialize_default_nodes(accel_dev);
+ if (ret) {
+ dev_err(&GET_DEV(accel_dev),
+ "failed to initialize default SLAs\n");
+ goto ret_sla_rm;
+ }
+
+ ret = adf_sysfs_rl_add(accel_dev);
+ if (ret) {
+ dev_err(&GET_DEV(accel_dev), "failed to add sysfs interface\n");
+ goto ret_sysfs_rm;
+ }
+
+ return 0;
+
+ret_sysfs_rm:
+ adf_sysfs_rl_rm(accel_dev);
+ret_sla_rm:
+ adf_rl_remove_sla_all(accel_dev, true);
+ret_free:
+ kfree(accel_dev->rate_limiting);
+ accel_dev->rate_limiting = NULL;
+ret_err:
+ return ret;
+}
+
+void adf_rl_stop(struct adf_accel_dev *accel_dev)
+{
+ if (!accel_dev->rate_limiting)
+ return;
+
+ adf_sysfs_rl_rm(accel_dev);
+ adf_rl_remove_sla_all(accel_dev, true);
+}
+
+void adf_rl_exit(struct adf_accel_dev *accel_dev)
+{
+ if (!accel_dev->rate_limiting)
+ return;
+
+ kfree(accel_dev->rate_limiting);
+ accel_dev->rate_limiting = NULL;
+}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_rl.h b/drivers/crypto/intel/qat/qat_common/adf_rl.h
new file mode 100644
index 000000000000..eb5a330f8543
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_rl.h
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Intel Corporation */
+
+#ifndef ADF_RL_H_
+#define ADF_RL_H_
+
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+struct adf_accel_dev;
+
+#define RL_ROOT_MAX 4
+#define RL_CLUSTER_MAX 16
+#define RL_LEAF_MAX 64
+#define RL_NODES_CNT_MAX (RL_ROOT_MAX + RL_CLUSTER_MAX + RL_LEAF_MAX)
+#define RL_RP_CNT_PER_LEAF_MAX 4U
+#define RL_RP_CNT_MAX 64
+#define RL_SLA_EMPTY_ID -1
+#define RL_PARENT_DEFAULT_ID -1
+
+enum rl_node_type {
+ RL_ROOT,
+ RL_CLUSTER,
+ RL_LEAF,
+};
+
+enum adf_base_services {
+ ADF_SVC_ASYM = 0,
+ ADF_SVC_SYM,
+ ADF_SVC_DC,
+ ADF_SVC_NONE,
+};
+
+/**
+ * struct adf_rl_sla_input_data - ratelimiting user input data structure
+ * @rp_mask: 64 bit bitmask of ring pair IDs which will be assigned to SLA.
+ * Eg. 0x5 -> RP0 and RP2 assigned; 0xA005 -> RP0,2,13,15 assigned.
+ * @sla_id: ID of current SLA for operations update, rm, get. For the add
+ * operation, this field will be updated with the ID of the newly
+ * added SLA
+ * @parent_id: ID of the SLA to which the current one should be assigned.
+ * Set to -1 to refer to the default parent.
+ * @cir: Committed information rate. Rate guaranteed to be achieved. Input value
+ * is expressed in permille scale, i.e. 1000 refers to the maximum
+ * device throughput for a selected service.
+ * @pir: Peak information rate. Maximum rate available that the SLA can achieve.
+ * Input value is expressed in permille scale, i.e. 1000 refers to
+ * the maximum device throughput for a selected service.
+ * @type: SLA type: root, cluster, node
+ * @srv: Service associated to the SLA: asym, sym dc.
+ *
+ * This structure is used to perform operations on an SLA.
+ * Depending on the operation, some of the parameters are ignored.
+ * The following list reports which parameters should be set for each operation.
+ * - add: all except sla_id
+ * - update: cir, pir, sla_id
+ * - rm: sla_id
+ * - rm_all: -
+ * - get: sla_id
+ * - get_capability_rem: srv, sla_id
+ */
+struct adf_rl_sla_input_data {
+ u64 rp_mask;
+ int sla_id;
+ int parent_id;
+ unsigned int cir;
+ unsigned int pir;
+ enum rl_node_type type;
+ enum adf_base_services srv;
+};
+
+struct rl_slice_cnt {
+ u8 dcpr_cnt;
+ u8 pke_cnt;
+ u8 cph_cnt;
+};
+
+struct adf_rl_interface_data {
+ struct adf_rl_sla_input_data input;
+ enum adf_base_services cap_rem_srv;
+ struct rw_semaphore lock;
+};
+
+struct adf_rl_hw_data {
+ u32 scale_ref;
+ u32 scan_interval;
+ u32 r2l_offset;
+ u32 l2c_offset;
+ u32 c2s_offset;
+ u32 pciin_tb_offset;
+ u32 pciout_tb_offset;
+ u32 pcie_scale_mul;
+ u32 pcie_scale_div;
+ u32 dcpr_correction;
+ u32 max_tp[RL_ROOT_MAX];
+ struct rl_slice_cnt slices;
+};
+
+/**
+ * struct adf_rl - ratelimiting data structure
+ * @accel_dev: pointer to acceleration device data
+ * @device_data: pointer to rate limiting data specific to a device type (or revision)
+ * @sla: array of pointers to SLA objects
+ * @root: array of pointers to root type SLAs, element number reflects node_id
+ * @cluster: array of pointers to cluster type SLAs, element number reflects node_id
+ * @leaf: array of pointers to leaf type SLAs, element number reflects node_id
+ * @rp_in_use: array of ring pair IDs already used in one of SLAs
+ * @rl_lock: mutex object which is protecting data in this structure
+ * @input: structure which is used for holding the data received from user
+ */
+struct adf_rl {
+ struct adf_accel_dev *accel_dev;
+ struct adf_rl_hw_data *device_data;
+ /* mapping sla_id to SLA objects */
+ struct rl_sla *sla[RL_NODES_CNT_MAX];
+ struct rl_sla *root[RL_ROOT_MAX];
+ struct rl_sla *cluster[RL_CLUSTER_MAX];
+ struct rl_sla *leaf[RL_LEAF_MAX];
+ bool rp_in_use[RL_RP_CNT_MAX];
+ /* Mutex protecting writing to SLAs lists */
+ struct mutex rl_lock;
+ struct adf_rl_interface_data user_input;
+};
+
+/**
+ * struct rl_sla - SLA object data structure
+ * @parent: pointer to the parent SLA (root/cluster)
+ * @type: SLA type
+ * @srv: service associated with this SLA
+ * @sla_id: ID of the SLA, used as element number in SLA array and as identifier
+ * shared with the user
+ * @node_id: ID of node, each of SLA type have a separate ID list
+ * @cir: committed information rate
+ * @pir: peak information rate (PIR >= CIR)
+ * @rem_cir: if this SLA is a parent then this field represents a remaining
+ * value to be used by child SLAs.
+ * @ring_pairs_ids: array with numeric ring pairs IDs assigned to this SLA
+ * @ring_pairs_cnt: number of assigned ring pairs listed in the array above
+ */
+struct rl_sla {
+ struct rl_sla *parent;
+ enum rl_node_type type;
+ enum adf_base_services srv;
+ u32 sla_id;
+ u32 node_id;
+ u32 cir;
+ u32 pir;
+ u32 rem_cir;
+ u16 ring_pairs_ids[RL_RP_CNT_PER_LEAF_MAX];
+ u16 ring_pairs_cnt;
+};
+
+int adf_rl_add_sla(struct adf_accel_dev *accel_dev,
+ struct adf_rl_sla_input_data *sla_in);
+int adf_rl_update_sla(struct adf_accel_dev *accel_dev,
+ struct adf_rl_sla_input_data *sla_in);
+int adf_rl_get_sla(struct adf_accel_dev *accel_dev,
+ struct adf_rl_sla_input_data *sla_in);
+int adf_rl_get_capability_remaining(struct adf_accel_dev *accel_dev,
+ enum adf_base_services srv, int sla_id);
+int adf_rl_remove_sla(struct adf_accel_dev *accel_dev, u32 sla_id);
+void adf_rl_remove_sla_all(struct adf_accel_dev *accel_dev, bool incl_default);
+
+int adf_rl_init(struct adf_accel_dev *accel_dev);
+int adf_rl_start(struct adf_accel_dev *accel_dev);
+void adf_rl_stop(struct adf_accel_dev *accel_dev);
+void adf_rl_exit(struct adf_accel_dev *accel_dev);
+
+u32 adf_rl_calculate_pci_bw(struct adf_accel_dev *accel_dev, u32 sla_val,
+ enum adf_base_services svc_type, bool is_bw_out);
+u32 adf_rl_calculate_ae_cycles(struct adf_accel_dev *accel_dev, u32 sla_val,
+ enum adf_base_services svc_type);
+u32 adf_rl_calculate_slice_tokens(struct adf_accel_dev *accel_dev, u32 sla_val,
+ enum adf_base_services svc_type);
+
+#endif /* ADF_RL_H_ */
diff --git a/drivers/crypto/intel/qat/qat_common/adf_rl_admin.c b/drivers/crypto/intel/qat/qat_common/adf_rl_admin.c
new file mode 100644
index 000000000000..698a14f4ce66
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_rl_admin.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Intel Corporation */
+
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+
+#include "adf_admin.h"
+#include "adf_accel_devices.h"
+#include "adf_rl_admin.h"
+
+static void
+prep_admin_req_msg(struct rl_sla *sla, dma_addr_t dma_addr,
+ struct icp_qat_fw_init_admin_sla_config_params *fw_params,
+ struct icp_qat_fw_init_admin_req *req, bool is_update)
+{
+ req->cmd_id = is_update ? ICP_QAT_FW_RL_UPDATE : ICP_QAT_FW_RL_ADD;
+ req->init_cfg_ptr = dma_addr;
+ req->init_cfg_sz = sizeof(*fw_params);
+ req->node_id = sla->node_id;
+ req->node_type = sla->type;
+ req->rp_count = sla->ring_pairs_cnt;
+ req->svc_type = sla->srv;
+}
+
+static void
+prep_admin_req_params(struct adf_accel_dev *accel_dev, struct rl_sla *sla,
+ struct icp_qat_fw_init_admin_sla_config_params *fw_params)
+{
+ fw_params->pcie_in_cir =
+ adf_rl_calculate_pci_bw(accel_dev, sla->cir, sla->srv, false);
+ fw_params->pcie_in_pir =
+ adf_rl_calculate_pci_bw(accel_dev, sla->pir, sla->srv, false);
+ fw_params->pcie_out_cir =
+ adf_rl_calculate_pci_bw(accel_dev, sla->cir, sla->srv, true);
+ fw_params->pcie_out_pir =
+ adf_rl_calculate_pci_bw(accel_dev, sla->pir, sla->srv, true);
+
+ fw_params->slice_util_cir =
+ adf_rl_calculate_slice_tokens(accel_dev, sla->cir, sla->srv);
+ fw_params->slice_util_pir =
+ adf_rl_calculate_slice_tokens(accel_dev, sla->pir, sla->srv);
+
+ fw_params->ae_util_cir =
+ adf_rl_calculate_ae_cycles(accel_dev, sla->cir, sla->srv);
+ fw_params->ae_util_pir =
+ adf_rl_calculate_ae_cycles(accel_dev, sla->pir, sla->srv);
+
+ memcpy(fw_params->rp_ids, sla->ring_pairs_ids,
+ sizeof(sla->ring_pairs_ids));
+}
+
+int adf_rl_send_admin_init_msg(struct adf_accel_dev *accel_dev,
+ struct rl_slice_cnt *slices_int)
+{
+ struct icp_qat_fw_init_admin_slice_cnt slices_resp = { };
+ int ret;
+
+ ret = adf_send_admin_rl_init(accel_dev, &slices_resp);
+ if (ret)
+ return ret;
+
+ slices_int->dcpr_cnt = slices_resp.dcpr_cnt;
+ slices_int->pke_cnt = slices_resp.pke_cnt;
+ /* For symmetric crypto, slice tokens are relative to the UCS slice */
+ slices_int->cph_cnt = slices_resp.ucs_cnt;
+
+ return 0;
+}
+
+int adf_rl_send_admin_add_update_msg(struct adf_accel_dev *accel_dev,
+ struct rl_sla *sla, bool is_update)
+{
+ struct icp_qat_fw_init_admin_sla_config_params *fw_params;
+ struct icp_qat_fw_init_admin_req req = { };
+ dma_addr_t dma_addr;
+ int ret;
+
+ fw_params = dma_alloc_coherent(&GET_DEV(accel_dev), sizeof(*fw_params),
+ &dma_addr, GFP_KERNEL);
+ if (!fw_params)
+ return -ENOMEM;
+
+ prep_admin_req_params(accel_dev, sla, fw_params);
+ prep_admin_req_msg(sla, dma_addr, fw_params, &req, is_update);
+ ret = adf_send_admin_rl_add_update(accel_dev, &req);
+
+ dma_free_coherent(&GET_DEV(accel_dev), sizeof(*fw_params), fw_params,
+ dma_addr);
+
+ return ret;
+}
+
+int adf_rl_send_admin_delete_msg(struct adf_accel_dev *accel_dev, u16 node_id,
+ u8 node_type)
+{
+ return adf_send_admin_rl_delete(accel_dev, node_id, node_type);
+}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_rl_admin.h b/drivers/crypto/intel/qat/qat_common/adf_rl_admin.h
new file mode 100644
index 000000000000..dd5419b7e896
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_rl_admin.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Intel Corporation */
+
+#ifndef ADF_RL_ADMIN_H_
+#define ADF_RL_ADMIN_H_
+
+#include <linux/types.h>
+
+#include "adf_rl.h"
+
+int adf_rl_send_admin_init_msg(struct adf_accel_dev *accel_dev,
+ struct rl_slice_cnt *slices_int);
+int adf_rl_send_admin_add_update_msg(struct adf_accel_dev *accel_dev,
+ struct rl_sla *sla, bool is_update);
+int adf_rl_send_admin_delete_msg(struct adf_accel_dev *accel_dev, u16 node_id,
+ u8 node_type);
+
+#endif /* ADF_RL_ADMIN_H_ */
diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs.c b/drivers/crypto/intel/qat/qat_common/adf_sysfs.c
index a74d2f930367..ddffc98119c6 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_sysfs.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs.c
@@ -5,8 +5,11 @@
#include <linux/pci.h>
#include "adf_accel_devices.h"
#include "adf_cfg.h"
+#include "adf_cfg_services.h"
#include "adf_common_drv.h"
+#define UNSET_RING_NUM -1
+
static const char * const state_operations[] = {
[DEV_DOWN] = "down",
[DEV_UP] = "up",
@@ -52,16 +55,25 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr,
case DEV_DOWN:
dev_info(dev, "Stopping device qat_dev%d\n", accel_id);
+ if (!adf_dev_started(accel_dev)) {
+ dev_info(&GET_DEV(accel_dev), "Device qat_dev%d already down\n",
+ accel_id);
+
+ break;
+ }
+
ret = adf_dev_down(accel_dev, true);
- if (ret < 0)
- return -EINVAL;
+ if (ret)
+ return ret;
break;
case DEV_UP:
dev_info(dev, "Starting device qat_dev%d\n", accel_id);
ret = adf_dev_up(accel_dev, true);
- if (ret < 0) {
+ if (ret == -EALREADY) {
+ break;
+ } else if (ret) {
dev_err(dev, "Failed to start device qat_dev%d\n",
accel_id);
adf_dev_down(accel_dev, true);
@@ -75,18 +87,6 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr,
return count;
}
-static const char * const services_operations[] = {
- ADF_CFG_CY,
- ADF_CFG_DC,
- ADF_CFG_SYM,
- ADF_CFG_ASYM,
- ADF_CFG_ASYM_SYM,
- ADF_CFG_ASYM_DC,
- ADF_CFG_DC_ASYM,
- ADF_CFG_SYM_DC,
- ADF_CFG_DC_SYM,
-};
-
static ssize_t cfg_services_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -121,7 +121,7 @@ static ssize_t cfg_services_store(struct device *dev, struct device_attribute *a
struct adf_accel_dev *accel_dev;
int ret;
- ret = sysfs_match_string(services_operations, buf);
+ ret = sysfs_match_string(adf_cfg_services, buf);
if (ret < 0)
return ret;
@@ -135,7 +135,7 @@ static ssize_t cfg_services_store(struct device *dev, struct device_attribute *a
return -EINVAL;
}
- ret = adf_sysfs_update_dev_config(accel_dev, services_operations[ret]);
+ ret = adf_sysfs_update_dev_config(accel_dev, adf_cfg_services[ret]);
if (ret < 0)
return ret;
@@ -207,10 +207,86 @@ static DEVICE_ATTR_RW(pm_idle_enabled);
static DEVICE_ATTR_RW(state);
static DEVICE_ATTR_RW(cfg_services);
+static ssize_t rp2srv_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adf_hw_device_data *hw_data;
+ struct adf_accel_dev *accel_dev;
+ enum adf_cfg_service_type svc;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ hw_data = GET_HW_DATA(accel_dev);
+
+ if (accel_dev->sysfs.ring_num == UNSET_RING_NUM)
+ return -EINVAL;
+
+ down_read(&accel_dev->sysfs.lock);
+ svc = GET_SRV_TYPE(accel_dev, accel_dev->sysfs.ring_num %
+ hw_data->num_banks_per_vf);
+ up_read(&accel_dev->sysfs.lock);
+
+ switch (svc) {
+ case COMP:
+ return sysfs_emit(buf, "%s\n", ADF_CFG_DC);
+ case SYM:
+ return sysfs_emit(buf, "%s\n", ADF_CFG_SYM);
+ case ASYM:
+ return sysfs_emit(buf, "%s\n", ADF_CFG_ASYM);
+ default:
+ break;
+ }
+ return -EINVAL;
+}
+
+static ssize_t rp2srv_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct adf_accel_dev *accel_dev;
+ int ring, num_rings, ret;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ ret = kstrtouint(buf, 10, &ring);
+ if (ret)
+ return ret;
+
+ num_rings = GET_MAX_BANKS(accel_dev);
+ if (ring >= num_rings) {
+ dev_err(&GET_DEV(accel_dev),
+ "Device does not support more than %u ring pairs\n",
+ num_rings);
+ return -EINVAL;
+ }
+
+ down_write(&accel_dev->sysfs.lock);
+ accel_dev->sysfs.ring_num = ring;
+ up_write(&accel_dev->sysfs.lock);
+
+ return count;
+}
+static DEVICE_ATTR_RW(rp2srv);
+
+static ssize_t num_rps_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adf_accel_dev *accel_dev;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ return sysfs_emit(buf, "%u\n", GET_MAX_BANKS(accel_dev));
+}
+static DEVICE_ATTR_RO(num_rps);
+
static struct attribute *qat_attrs[] = {
&dev_attr_state.attr,
&dev_attr_cfg_services.attr,
&dev_attr_pm_idle_enabled.attr,
+ &dev_attr_rp2srv.attr,
+ &dev_attr_num_rps.attr,
NULL,
};
@@ -229,6 +305,8 @@ int adf_sysfs_init(struct adf_accel_dev *accel_dev)
"Failed to create qat attribute group: %d\n", ret);
}
+ accel_dev->sysfs.ring_num = UNSET_RING_NUM;
+
return ret;
}
EXPORT_SYMBOL_GPL(adf_sysfs_init);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs_ras_counters.c b/drivers/crypto/intel/qat/qat_common/adf_sysfs_ras_counters.c
new file mode 100644
index 000000000000..cffe2d722995
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs_ras_counters.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Intel Corporation */
+
+#include <linux/sysfs.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+
+#include "adf_common_drv.h"
+#include "adf_sysfs_ras_counters.h"
+
+static ssize_t errors_correctable_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct adf_accel_dev *accel_dev;
+ unsigned long counter;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ counter = ADF_RAS_ERR_CTR_READ(accel_dev->ras_errors, ADF_RAS_CORR);
+ return scnprintf(buf, PAGE_SIZE, "%ld\n", counter);
+}
+
+static ssize_t errors_nonfatal_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct adf_accel_dev *accel_dev;
+ unsigned long counter;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ counter = ADF_RAS_ERR_CTR_READ(accel_dev->ras_errors, ADF_RAS_UNCORR);
+ return scnprintf(buf, PAGE_SIZE, "%ld\n", counter);
+}
+
+static ssize_t errors_fatal_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct adf_accel_dev *accel_dev;
+ unsigned long counter;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ counter = ADF_RAS_ERR_CTR_READ(accel_dev->ras_errors, ADF_RAS_FATAL);
+ return scnprintf(buf, PAGE_SIZE, "%ld\n", counter);
+}
+
+static ssize_t reset_error_counters_store(struct device *dev,
+ struct device_attribute *dev_attr,
+ const char *buf, size_t count)
+{
+ struct adf_accel_dev *accel_dev;
+
+ if (buf[0] != '1' || count != 2)
+ return -EINVAL;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ ADF_RAS_ERR_CTR_CLEAR(accel_dev->ras_errors);
+
+ return count;
+}
+
+static DEVICE_ATTR_RO(errors_correctable);
+static DEVICE_ATTR_RO(errors_nonfatal);
+static DEVICE_ATTR_RO(errors_fatal);
+static DEVICE_ATTR_WO(reset_error_counters);
+
+static struct attribute *qat_ras_attrs[] = {
+ &dev_attr_errors_correctable.attr,
+ &dev_attr_errors_nonfatal.attr,
+ &dev_attr_errors_fatal.attr,
+ &dev_attr_reset_error_counters.attr,
+ NULL,
+};
+
+static struct attribute_group qat_ras_group = {
+ .attrs = qat_ras_attrs,
+ .name = "qat_ras",
+};
+
+void adf_sysfs_start_ras(struct adf_accel_dev *accel_dev)
+{
+ if (!accel_dev->ras_errors.enabled)
+ return;
+
+ ADF_RAS_ERR_CTR_CLEAR(accel_dev->ras_errors);
+
+ if (device_add_group(&GET_DEV(accel_dev), &qat_ras_group))
+ dev_err(&GET_DEV(accel_dev),
+ "Failed to create qat_ras attribute group.\n");
+}
+
+void adf_sysfs_stop_ras(struct adf_accel_dev *accel_dev)
+{
+ if (!accel_dev->ras_errors.enabled)
+ return;
+
+ device_remove_group(&GET_DEV(accel_dev), &qat_ras_group);
+
+ ADF_RAS_ERR_CTR_CLEAR(accel_dev->ras_errors);
+}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs_ras_counters.h b/drivers/crypto/intel/qat/qat_common/adf_sysfs_ras_counters.h
new file mode 100644
index 000000000000..99e9d9cf57f8
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs_ras_counters.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Intel Corporation */
+
+#ifndef ADF_RAS_H
+#define ADF_RAS_H
+
+#include <linux/bitops.h>
+#include <linux/atomic.h>
+
+struct adf_accel_dev;
+
+void adf_sysfs_start_ras(struct adf_accel_dev *accel_dev);
+void adf_sysfs_stop_ras(struct adf_accel_dev *accel_dev);
+
+#define ADF_RAS_ERR_CTR_READ(ras_errors, ERR) \
+ atomic_read(&(ras_errors).counter[ERR])
+
+#define ADF_RAS_ERR_CTR_CLEAR(ras_errors) \
+ do { \
+ for (int err = 0; err < ADF_RAS_ERRORS; ++err) \
+ atomic_set(&(ras_errors).counter[err], 0); \
+ } while (0)
+
+#define ADF_RAS_ERR_CTR_INC(ras_errors, ERR) \
+ atomic_inc(&(ras_errors).counter[ERR])
+
+#endif /* ADF_RAS_H */
diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs_rl.c b/drivers/crypto/intel/qat/qat_common/adf_sysfs_rl.c
new file mode 100644
index 000000000000..abf9c52474ec
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs_rl.c
@@ -0,0 +1,451 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Intel Corporation */
+
+#define dev_fmt(fmt) "RateLimiting: " fmt
+
+#include <linux/dev_printk.h>
+#include <linux/pci.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+
+#include "adf_common_drv.h"
+#include "adf_rl.h"
+#include "adf_sysfs_rl.h"
+
+#define GET_RL_STRUCT(accel_dev) ((accel_dev)->rate_limiting->user_input)
+
+enum rl_ops {
+ ADD,
+ UPDATE,
+ RM,
+ RM_ALL,
+ GET,
+};
+
+enum rl_params {
+ RP_MASK,
+ ID,
+ CIR,
+ PIR,
+ SRV,
+ CAP_REM_SRV,
+};
+
+static const char *const rl_services[] = {
+ [ADF_SVC_ASYM] = "asym",
+ [ADF_SVC_SYM] = "sym",
+ [ADF_SVC_DC] = "dc",
+};
+
+static const char *const rl_operations[] = {
+ [ADD] = "add",
+ [UPDATE] = "update",
+ [RM] = "rm",
+ [RM_ALL] = "rm_all",
+ [GET] = "get",
+};
+
+static int set_param_u(struct device *dev, enum rl_params param, u64 set)
+{
+ struct adf_rl_interface_data *data;
+ struct adf_accel_dev *accel_dev;
+ int ret = 0;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ data = &GET_RL_STRUCT(accel_dev);
+
+ down_write(&data->lock);
+ switch (param) {
+ case RP_MASK:
+ data->input.rp_mask = set;
+ break;
+ case CIR:
+ data->input.cir = set;
+ break;
+ case PIR:
+ data->input.pir = set;
+ break;
+ case SRV:
+ data->input.srv = set;
+ break;
+ case CAP_REM_SRV:
+ data->cap_rem_srv = set;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ up_write(&data->lock);
+
+ return ret;
+}
+
+static int set_param_s(struct device *dev, enum rl_params param, int set)
+{
+ struct adf_rl_interface_data *data;
+ struct adf_accel_dev *accel_dev;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev || param != ID)
+ return -EINVAL;
+
+ data = &GET_RL_STRUCT(accel_dev);
+
+ down_write(&data->lock);
+ data->input.sla_id = set;
+ up_write(&data->lock);
+
+ return 0;
+}
+
+static int get_param_u(struct device *dev, enum rl_params param, u64 *get)
+{
+ struct adf_rl_interface_data *data;
+ struct adf_accel_dev *accel_dev;
+ int ret = 0;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ data = &GET_RL_STRUCT(accel_dev);
+
+ down_read(&data->lock);
+ switch (param) {
+ case RP_MASK:
+ *get = data->input.rp_mask;
+ break;
+ case CIR:
+ *get = data->input.cir;
+ break;
+ case PIR:
+ *get = data->input.pir;
+ break;
+ case SRV:
+ *get = data->input.srv;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ up_read(&data->lock);
+
+ return ret;
+}
+
+static int get_param_s(struct device *dev, enum rl_params param)
+{
+ struct adf_rl_interface_data *data;
+ struct adf_accel_dev *accel_dev;
+ int ret = 0;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ data = &GET_RL_STRUCT(accel_dev);
+
+ down_read(&data->lock);
+ if (param == ID)
+ ret = data->input.sla_id;
+ up_read(&data->lock);
+
+ return ret;
+}
+
+static ssize_t rp_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int ret;
+ u64 get;
+
+ ret = get_param_u(dev, RP_MASK, &get);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%#llx\n", get);
+}
+
+static ssize_t rp_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ u64 val;
+
+ err = kstrtou64(buf, 16, &val);
+ if (err)
+ return err;
+
+ err = set_param_u(dev, RP_MASK, val);
+ if (err)
+ return err;
+
+ return count;
+}
+static DEVICE_ATTR_RW(rp);
+
+static ssize_t id_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%d\n", get_param_s(dev, ID));
+}
+
+static ssize_t id_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ int val;
+
+ err = kstrtoint(buf, 10, &val);
+ if (err)
+ return err;
+
+ err = set_param_s(dev, ID, val);
+ if (err)
+ return err;
+
+ return count;
+}
+static DEVICE_ATTR_RW(id);
+
+static ssize_t cir_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int ret;
+ u64 get;
+
+ ret = get_param_u(dev, CIR, &get);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%llu\n", get);
+}
+
+static ssize_t cir_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int val;
+ int err;
+
+ err = kstrtouint(buf, 10, &val);
+ if (err)
+ return err;
+
+ err = set_param_u(dev, CIR, val);
+ if (err)
+ return err;
+
+ return count;
+}
+static DEVICE_ATTR_RW(cir);
+
+static ssize_t pir_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int ret;
+ u64 get;
+
+ ret = get_param_u(dev, PIR, &get);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%llu\n", get);
+}
+
+static ssize_t pir_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int val;
+ int err;
+
+ err = kstrtouint(buf, 10, &val);
+ if (err)
+ return err;
+
+ err = set_param_u(dev, PIR, val);
+ if (err)
+ return err;
+
+ return count;
+}
+static DEVICE_ATTR_RW(pir);
+
+static ssize_t srv_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int ret;
+ u64 get;
+
+ ret = get_param_u(dev, SRV, &get);
+ if (ret)
+ return ret;
+
+ if (get == ADF_SVC_NONE)
+ return -EINVAL;
+
+ return sysfs_emit(buf, "%s\n", rl_services[get]);
+}
+
+static ssize_t srv_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int val;
+ int ret;
+
+ ret = sysfs_match_string(rl_services, buf);
+ if (ret < 0)
+ return ret;
+
+ val = ret;
+ ret = set_param_u(dev, SRV, val);
+ if (ret)
+ return ret;
+
+ return count;
+}
+static DEVICE_ATTR_RW(srv);
+
+static ssize_t cap_rem_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adf_rl_interface_data *data;
+ struct adf_accel_dev *accel_dev;
+ int ret, rem_cap;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ data = &GET_RL_STRUCT(accel_dev);
+
+ down_read(&data->lock);
+ rem_cap = adf_rl_get_capability_remaining(accel_dev, data->cap_rem_srv,
+ RL_SLA_EMPTY_ID);
+ up_read(&data->lock);
+ if (rem_cap < 0)
+ return rem_cap;
+
+ ret = sysfs_emit(buf, "%u\n", rem_cap);
+
+ return ret;
+}
+
+static ssize_t cap_rem_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int val;
+ int ret;
+
+ ret = sysfs_match_string(rl_services, buf);
+ if (ret < 0)
+ return ret;
+
+ val = ret;
+ ret = set_param_u(dev, CAP_REM_SRV, val);
+ if (ret)
+ return ret;
+
+ return count;
+}
+static DEVICE_ATTR_RW(cap_rem);
+
+static ssize_t sla_op_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct adf_rl_interface_data *data;
+ struct adf_accel_dev *accel_dev;
+ int ret;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ data = &GET_RL_STRUCT(accel_dev);
+
+ ret = sysfs_match_string(rl_operations, buf);
+ if (ret < 0)
+ return ret;
+
+ down_write(&data->lock);
+ switch (ret) {
+ case ADD:
+ data->input.parent_id = RL_PARENT_DEFAULT_ID;
+ data->input.type = RL_LEAF;
+ data->input.sla_id = 0;
+ ret = adf_rl_add_sla(accel_dev, &data->input);
+ if (ret)
+ goto err_free_lock;
+ break;
+ case UPDATE:
+ ret = adf_rl_update_sla(accel_dev, &data->input);
+ if (ret)
+ goto err_free_lock;
+ break;
+ case RM:
+ ret = adf_rl_remove_sla(accel_dev, data->input.sla_id);
+ if (ret)
+ goto err_free_lock;
+ break;
+ case RM_ALL:
+ adf_rl_remove_sla_all(accel_dev, false);
+ break;
+ case GET:
+ ret = adf_rl_get_sla(accel_dev, &data->input);
+ if (ret)
+ goto err_free_lock;
+ break;
+ default:
+ ret = -EINVAL;
+ goto err_free_lock;
+ }
+ up_write(&data->lock);
+
+ return count;
+
+err_free_lock:
+ up_write(&data->lock);
+
+ return ret;
+}
+static DEVICE_ATTR_WO(sla_op);
+
+static struct attribute *qat_rl_attrs[] = {
+ &dev_attr_rp.attr,
+ &dev_attr_id.attr,
+ &dev_attr_cir.attr,
+ &dev_attr_pir.attr,
+ &dev_attr_srv.attr,
+ &dev_attr_cap_rem.attr,
+ &dev_attr_sla_op.attr,
+ NULL,
+};
+
+static struct attribute_group qat_rl_group = {
+ .attrs = qat_rl_attrs,
+ .name = "qat_rl",
+};
+
+int adf_sysfs_rl_add(struct adf_accel_dev *accel_dev)
+{
+ struct adf_rl_interface_data *data;
+ int ret;
+
+ data = &GET_RL_STRUCT(accel_dev);
+
+ ret = device_add_group(&GET_DEV(accel_dev), &qat_rl_group);
+ if (ret)
+ dev_err(&GET_DEV(accel_dev),
+ "Failed to create qat_rl attribute group\n");
+
+ data->cap_rem_srv = ADF_SVC_NONE;
+ data->input.srv = ADF_SVC_NONE;
+
+ return ret;
+}
+
+void adf_sysfs_rl_rm(struct adf_accel_dev *accel_dev)
+{
+ device_remove_group(&GET_DEV(accel_dev), &qat_rl_group);
+}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs_rl.h b/drivers/crypto/intel/qat/qat_common/adf_sysfs_rl.h
new file mode 100644
index 000000000000..22d36aa8a757
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs_rl.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Intel Corporation */
+#ifndef ADF_SYSFS_RL_H_
+#define ADF_SYSFS_RL_H_
+
+struct adf_accel_dev;
+
+int adf_sysfs_rl_add(struct adf_accel_dev *accel_dev);
+void adf_sysfs_rl_rm(struct adf_accel_dev *accel_dev);
+
+#endif /* ADF_SYSFS_RL_H_ */
diff --git a/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c b/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c
index 08bca1c506c0..e2dd568b87b5 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c
@@ -90,7 +90,7 @@ DEFINE_SEQ_ATTRIBUTE(adf_ring_debug);
int adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name)
{
struct adf_etr_ring_debug_entry *ring_debug;
- char entry_name[8];
+ char entry_name[16];
ring_debug = kzalloc(sizeof(*ring_debug), GFP_KERNEL);
if (!ring_debug)
@@ -192,7 +192,7 @@ int adf_bank_debugfs_add(struct adf_etr_bank_data *bank)
{
struct adf_accel_dev *accel_dev = bank->accel_dev;
struct dentry *parent = accel_dev->transport->debug;
- char name[8];
+ char name[16];
snprintf(name, sizeof(name), "bank_%02d", bank->bank_number);
bank->bank_debug_dir = debugfs_create_dir(name, parent);
diff --git a/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h b/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h
index 3e968a4bcc9c..cd418b51d9f3 100644
--- a/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h
+++ b/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h
@@ -5,6 +5,8 @@
#include "icp_qat_fw.h"
+#define RL_MAX_RP_IDS 16
+
enum icp_qat_fw_init_admin_cmd_id {
ICP_QAT_FW_INIT_AE = 0,
ICP_QAT_FW_TRNG_ENABLE = 1,
@@ -16,9 +18,17 @@ enum icp_qat_fw_init_admin_cmd_id {
ICP_QAT_FW_HEARTBEAT_SYNC = 7,
ICP_QAT_FW_HEARTBEAT_GET = 8,
ICP_QAT_FW_COMP_CAPABILITY_GET = 9,
+ ICP_QAT_FW_CRYPTO_CAPABILITY_GET = 10,
+ ICP_QAT_FW_DC_CHAIN_INIT = 11,
ICP_QAT_FW_HEARTBEAT_TIMER_SET = 13,
+ ICP_QAT_FW_RL_INIT = 15,
ICP_QAT_FW_TIMER_GET = 19,
+ ICP_QAT_FW_CNV_STATS_GET = 20,
ICP_QAT_FW_PM_STATE_CONFIG = 128,
+ ICP_QAT_FW_PM_INFO = 129,
+ ICP_QAT_FW_RL_ADD = 134,
+ ICP_QAT_FW_RL_UPDATE = 135,
+ ICP_QAT_FW_RL_REMOVE = 136,
};
enum icp_qat_fw_init_admin_resp_status {
@@ -26,6 +36,30 @@ enum icp_qat_fw_init_admin_resp_status {
ICP_QAT_FW_INIT_RESP_STATUS_FAIL
};
+struct icp_qat_fw_init_admin_slice_cnt {
+ __u8 cpr_cnt;
+ __u8 xlt_cnt;
+ __u8 dcpr_cnt;
+ __u8 pke_cnt;
+ __u8 wat_cnt;
+ __u8 wcp_cnt;
+ __u8 ucs_cnt;
+ __u8 cph_cnt;
+ __u8 ath_cnt;
+};
+
+struct icp_qat_fw_init_admin_sla_config_params {
+ __u32 pcie_in_cir;
+ __u32 pcie_in_pir;
+ __u32 pcie_out_cir;
+ __u32 pcie_out_pir;
+ __u32 slice_util_cir;
+ __u32 slice_util_pir;
+ __u32 ae_util_cir;
+ __u32 ae_util_pir;
+ __u16 rp_ids[RL_MAX_RP_IDS];
+};
+
struct icp_qat_fw_init_admin_req {
__u16 init_cfg_sz;
__u8 resrvd1;
@@ -45,6 +79,13 @@ struct icp_qat_fw_init_admin_req {
struct {
__u32 heartbeat_ticks;
};
+ struct {
+ __u16 node_id;
+ __u8 node_type;
+ __u8 svc_type;
+ __u8 resrvd5[3];
+ __u8 rp_count;
+ };
__u32 idle_filter;
};
@@ -63,6 +104,10 @@ struct icp_qat_fw_init_admin_resp {
__u16 version_major_num;
};
__u32 extended_features;
+ struct {
+ __u16 error_count;
+ __u16 latest_error;
+ };
};
__u64 opaque_data;
union {
@@ -102,9 +147,46 @@ struct icp_qat_fw_init_admin_resp {
__u32 unsuccessful_count;
__u64 resrvd8;
};
+ struct icp_qat_fw_init_admin_slice_cnt slices;
+ __u16 fw_capabilities;
};
} __packed;
#define ICP_QAT_FW_SYNC ICP_QAT_FW_HEARTBEAT_SYNC
+#define ICP_QAT_FW_CAPABILITIES_GET ICP_QAT_FW_CRYPTO_CAPABILITY_GET
+
+#define ICP_QAT_NUMBER_OF_PM_EVENTS 8
+
+struct icp_qat_fw_init_admin_pm_info {
+ __u16 max_pwrreq;
+ __u16 min_pwrreq;
+ __u16 resvrd1;
+ __u8 pwr_state;
+ __u8 resvrd2;
+ __u32 fusectl0;
+ struct_group(event_counters,
+ __u32 sys_pm;
+ __u32 host_msg;
+ __u32 unknown;
+ __u32 local_ssm;
+ __u32 timer;
+ );
+ __u32 event_log[ICP_QAT_NUMBER_OF_PM_EVENTS];
+ struct_group(pm,
+ __u32 fw_init;
+ __u32 pwrreq;
+ __u32 status;
+ __u32 main;
+ __u32 thread;
+ );
+ struct_group(ssm,
+ __u32 pm_enable;
+ __u32 pm_active_status;
+ __u32 pm_managed_status;
+ __u32 pm_domain_status;
+ __u32 active_constraint;
+ );
+ __u32 resvrd3[6];
+};
#endif
diff --git a/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h b/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h
index 0c8883e2ccc6..eb2ef225bcee 100644
--- a/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h
+++ b/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h
@@ -3,6 +3,8 @@
#ifndef _ICP_QAT_HW_H_
#define _ICP_QAT_HW_H_
+#include <linux/bits.h>
+
enum icp_qat_hw_ae_id {
ICP_QAT_HW_AE_0 = 0,
ICP_QAT_HW_AE_1 = 1,
diff --git a/drivers/crypto/intel/qat/qat_common/qat_algs_send.c b/drivers/crypto/intel/qat/qat_common/qat_algs_send.c
index bb80455b3e81..b97b678823a9 100644
--- a/drivers/crypto/intel/qat/qat_common/qat_algs_send.c
+++ b/drivers/crypto/intel/qat/qat_common/qat_algs_send.c
@@ -40,40 +40,44 @@ void qat_alg_send_backlog(struct qat_instance_backlog *backlog)
spin_unlock_bh(&backlog->lock);
}
-static void qat_alg_backlog_req(struct qat_alg_req *req,
- struct qat_instance_backlog *backlog)
-{
- INIT_LIST_HEAD(&req->list);
-
- spin_lock_bh(&backlog->lock);
- list_add_tail(&req->list, &backlog->list);
- spin_unlock_bh(&backlog->lock);
-}
-
-static int qat_alg_send_message_maybacklog(struct qat_alg_req *req)
+static bool qat_alg_try_enqueue(struct qat_alg_req *req)
{
struct qat_instance_backlog *backlog = req->backlog;
struct adf_etr_ring_data *tx_ring = req->tx_ring;
u32 *fw_req = req->fw_req;
- /* If any request is already backlogged, then add to backlog list */
+ /* Check if any request is already backlogged */
if (!list_empty(&backlog->list))
- goto enqueue;
+ return false;
- /* If ring is nearly full, then add to backlog list */
+ /* Check if ring is nearly full */
if (adf_ring_nearly_full(tx_ring))
- goto enqueue;
+ return false;
- /* If adding request to HW ring fails, then add to backlog list */
+ /* Try to enqueue to HW ring */
if (adf_send_message(tx_ring, fw_req))
- goto enqueue;
+ return false;
- return -EINPROGRESS;
+ return true;
+}
-enqueue:
- qat_alg_backlog_req(req, backlog);
- return -EBUSY;
+static int qat_alg_send_message_maybacklog(struct qat_alg_req *req)
+{
+ struct qat_instance_backlog *backlog = req->backlog;
+ int ret = -EINPROGRESS;
+
+ if (qat_alg_try_enqueue(req))
+ return ret;
+
+ spin_lock_bh(&backlog->lock);
+ if (!qat_alg_try_enqueue(req)) {
+ list_add_tail(&req->list, &backlog->list);
+ ret = -EBUSY;
+ }
+ spin_unlock_bh(&backlog->lock);
+
+ return ret;
}
int qat_alg_send_message(struct qat_alg_req *req)
diff --git a/drivers/crypto/intel/qat/qat_common/qat_comp_algs.c b/drivers/crypto/intel/qat/qat_common/qat_comp_algs.c
index b533984906ec..bf8c0ee62917 100644
--- a/drivers/crypto/intel/qat/qat_common/qat_comp_algs.c
+++ b/drivers/crypto/intel/qat/qat_common/qat_comp_algs.c
@@ -109,69 +109,6 @@ err:
acomp_request_complete(areq, ret);
}
-static int parse_zlib_header(u16 zlib_h)
-{
- int ret = -EINVAL;
- __be16 header;
- u8 *header_p;
- u8 cmf, flg;
-
- header = cpu_to_be16(zlib_h);
- header_p = (u8 *)&header;
-
- flg = header_p[0];
- cmf = header_p[1];
-
- if (cmf >> QAT_RFC_1950_CM_OFFSET > QAT_RFC_1950_CM_DEFLATE_CINFO_32K)
- return ret;
-
- if ((cmf & QAT_RFC_1950_CM_MASK) != QAT_RFC_1950_CM_DEFLATE)
- return ret;
-
- if (flg & QAT_RFC_1950_DICT_MASK)
- return ret;
-
- return 0;
-}
-
-static int qat_comp_rfc1950_callback(struct qat_compression_req *qat_req,
- void *resp)
-{
- struct acomp_req *areq = qat_req->acompress_req;
- enum direction dir = qat_req->dir;
- __be32 qat_produced_adler;
-
- qat_produced_adler = cpu_to_be32(qat_comp_get_produced_adler32(resp));
-
- if (dir == COMPRESSION) {
- __be16 zlib_header;
-
- zlib_header = cpu_to_be16(QAT_RFC_1950_COMP_HDR);
- scatterwalk_map_and_copy(&zlib_header, areq->dst, 0, QAT_RFC_1950_HDR_SIZE, 1);
- areq->dlen += QAT_RFC_1950_HDR_SIZE;
-
- scatterwalk_map_and_copy(&qat_produced_adler, areq->dst, areq->dlen,
- QAT_RFC_1950_FOOTER_SIZE, 1);
- areq->dlen += QAT_RFC_1950_FOOTER_SIZE;
- } else {
- __be32 decomp_adler;
- int footer_offset;
- int consumed;
-
- consumed = qat_comp_get_consumed_ctr(resp);
- footer_offset = consumed + QAT_RFC_1950_HDR_SIZE;
- if (footer_offset + QAT_RFC_1950_FOOTER_SIZE > areq->slen)
- return -EBADMSG;
-
- scatterwalk_map_and_copy(&decomp_adler, areq->src, footer_offset,
- QAT_RFC_1950_FOOTER_SIZE, 0);
-
- if (qat_produced_adler != decomp_adler)
- return -EBADMSG;
- }
- return 0;
-}
-
static void qat_comp_generic_callback(struct qat_compression_req *qat_req,
void *resp)
{
@@ -293,18 +230,6 @@ static void qat_comp_alg_exit_tfm(struct crypto_acomp *acomp_tfm)
memset(ctx, 0, sizeof(*ctx));
}
-static int qat_comp_alg_rfc1950_init_tfm(struct crypto_acomp *acomp_tfm)
-{
- struct crypto_tfm *tfm = crypto_acomp_tfm(acomp_tfm);
- struct qat_compression_ctx *ctx = crypto_tfm_ctx(tfm);
- int ret;
-
- ret = qat_comp_alg_init_tfm(acomp_tfm);
- ctx->qat_comp_callback = &qat_comp_rfc1950_callback;
-
- return ret;
-}
-
static int qat_comp_alg_compress_decompress(struct acomp_req *areq, enum direction dir,
unsigned int shdr, unsigned int sftr,
unsigned int dhdr, unsigned int dftr)
@@ -400,43 +325,6 @@ static int qat_comp_alg_decompress(struct acomp_req *req)
return qat_comp_alg_compress_decompress(req, DECOMPRESSION, 0, 0, 0, 0);
}
-static int qat_comp_alg_rfc1950_compress(struct acomp_req *req)
-{
- if (!req->dst && req->dlen != 0)
- return -EINVAL;
-
- if (req->dst && req->dlen <= QAT_RFC_1950_HDR_SIZE + QAT_RFC_1950_FOOTER_SIZE)
- return -EINVAL;
-
- return qat_comp_alg_compress_decompress(req, COMPRESSION, 0, 0,
- QAT_RFC_1950_HDR_SIZE,
- QAT_RFC_1950_FOOTER_SIZE);
-}
-
-static int qat_comp_alg_rfc1950_decompress(struct acomp_req *req)
-{
- struct crypto_acomp *acomp_tfm = crypto_acomp_reqtfm(req);
- struct crypto_tfm *tfm = crypto_acomp_tfm(acomp_tfm);
- struct qat_compression_ctx *ctx = crypto_tfm_ctx(tfm);
- struct adf_accel_dev *accel_dev = ctx->inst->accel_dev;
- u16 zlib_header;
- int ret;
-
- if (req->slen <= QAT_RFC_1950_HDR_SIZE + QAT_RFC_1950_FOOTER_SIZE)
- return -EBADMSG;
-
- scatterwalk_map_and_copy(&zlib_header, req->src, 0, QAT_RFC_1950_HDR_SIZE, 0);
-
- ret = parse_zlib_header(zlib_header);
- if (ret) {
- dev_dbg(&GET_DEV(accel_dev), "Error parsing zlib header\n");
- return ret;
- }
-
- return qat_comp_alg_compress_decompress(req, DECOMPRESSION, QAT_RFC_1950_HDR_SIZE,
- QAT_RFC_1950_FOOTER_SIZE, 0, 0);
-}
-
static struct acomp_alg qat_acomp[] = { {
.base = {
.cra_name = "deflate",
@@ -452,22 +340,7 @@ static struct acomp_alg qat_acomp[] = { {
.decompress = qat_comp_alg_decompress,
.dst_free = sgl_free,
.reqsize = sizeof(struct qat_compression_req),
-}, {
- .base = {
- .cra_name = "zlib-deflate",
- .cra_driver_name = "qat_zlib_deflate",
- .cra_priority = 4001,
- .cra_flags = CRYPTO_ALG_ASYNC,
- .cra_ctxsize = sizeof(struct qat_compression_ctx),
- .cra_module = THIS_MODULE,
- },
- .init = qat_comp_alg_rfc1950_init_tfm,
- .exit = qat_comp_alg_exit_tfm,
- .compress = qat_comp_alg_rfc1950_compress,
- .decompress = qat_comp_alg_rfc1950_decompress,
- .dst_free = sgl_free,
- .reqsize = sizeof(struct qat_compression_req),
-} };
+}};
int qat_comp_algs_register(void)
{
diff --git a/drivers/crypto/intel/qat/qat_common/qat_uclo.c b/drivers/crypto/intel/qat/qat_common/qat_uclo.c
index 4bd150d1441a..e27ea7e28c51 100644
--- a/drivers/crypto/intel/qat/qat_common/qat_uclo.c
+++ b/drivers/crypto/intel/qat/qat_common/qat_uclo.c
@@ -200,7 +200,7 @@ static int qat_uclo_parse_num(char *str, unsigned int *num)
unsigned long ae = 0;
int i;
- strncpy(buf, str, 15);
+ strscpy(buf, str, sizeof(buf));
for (i = 0; i < 16; i++) {
if (!isdigit(buf[i])) {
buf[i] = '\0';
diff --git a/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c b/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c
index 09551f949126..af14090cc4be 100644
--- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c
+++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
/* Copyright(c) 2014 - 2021 Intel Corporation */
#include <adf_accel_devices.h>
+#include <adf_admin.h>
#include <adf_common_drv.h>
#include <adf_gen2_config.h>
#include <adf_gen2_dc.h>
diff --git a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c
index 1e748e8ce12d..40b456b8035b 100644
--- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c
@@ -252,3 +252,4 @@ MODULE_FIRMWARE(ADF_DH895XCC_FW);
MODULE_FIRMWARE(ADF_DH895XCC_MMP);
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
+MODULE_IMPORT_NS(CRYPTO_QAT);
diff --git a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c
index fefb85ceaeb9..d59cb1ba2ad5 100644
--- a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c
@@ -226,3 +226,4 @@ MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Intel");
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
+MODULE_IMPORT_NS(CRYPTO_QAT);
diff --git a/drivers/crypto/marvell/cesa/cesa.c b/drivers/crypto/marvell/cesa/cesa.c
index b61e35b932e5..5744df30c838 100644
--- a/drivers/crypto/marvell/cesa/cesa.c
+++ b/drivers/crypto/marvell/cesa/cesa.c
@@ -581,7 +581,7 @@ err_cleanup:
return ret;
}
-static int mv_cesa_remove(struct platform_device *pdev)
+static void mv_cesa_remove(struct platform_device *pdev)
{
struct mv_cesa_dev *cesa = platform_get_drvdata(pdev);
int i;
@@ -594,8 +594,6 @@ static int mv_cesa_remove(struct platform_device *pdev)
mv_cesa_put_sram(pdev, i);
irq_set_affinity_hint(cesa->engines[i].irq, NULL);
}
-
- return 0;
}
static const struct platform_device_id mv_cesa_plat_id_table[] = {
@@ -606,7 +604,7 @@ MODULE_DEVICE_TABLE(platform, mv_cesa_plat_id_table);
static struct platform_driver marvell_cesa = {
.probe = mv_cesa_probe,
- .remove = mv_cesa_remove,
+ .remove_new = mv_cesa_remove,
.id_table = mv_cesa_plat_id_table,
.driver = {
.name = "marvell-cesa",
diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c
index f6b7bce0e656..2b3ebe0db3a6 100644
--- a/drivers/crypto/mxs-dcp.c
+++ b/drivers/crypto/mxs-dcp.c
@@ -908,7 +908,6 @@ static struct ahash_alg dcp_sha1_alg = {
.cra_name = "sha1",
.cra_driver_name = "sha1-dcp",
.cra_priority = 400,
- .cra_alignmask = 63,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct dcp_async_ctx),
@@ -935,7 +934,6 @@ static struct ahash_alg dcp_sha256_alg = {
.cra_name = "sha256",
.cra_driver_name = "sha256-dcp",
.cra_priority = 400,
- .cra_alignmask = 63,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct dcp_async_ctx),
@@ -1131,7 +1129,7 @@ err_destroy_sha_thread:
return ret;
}
-static int mxs_dcp_remove(struct platform_device *pdev)
+static void mxs_dcp_remove(struct platform_device *pdev)
{
struct dcp *sdcp = platform_get_drvdata(pdev);
@@ -1150,8 +1148,6 @@ static int mxs_dcp_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
global_sdcp = NULL;
-
- return 0;
}
static const struct of_device_id mxs_dcp_dt_ids[] = {
@@ -1164,7 +1160,7 @@ MODULE_DEVICE_TABLE(of, mxs_dcp_dt_ids);
static struct platform_driver mxs_dcp_driver = {
.probe = mxs_dcp_probe,
- .remove = mxs_dcp_remove,
+ .remove_new = mxs_dcp_remove,
.driver = {
.name = "mxs-dcp",
.of_match_table = mxs_dcp_dt_ids,
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index d5a32d71a3e9..caea98622c33 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -2011,7 +2011,7 @@ out_free_n2cp:
return err;
}
-static int n2_crypto_remove(struct platform_device *dev)
+static void n2_crypto_remove(struct platform_device *dev)
{
struct n2_crypto *np = dev_get_drvdata(&dev->dev);
@@ -2022,8 +2022,6 @@ static int n2_crypto_remove(struct platform_device *dev)
release_global_resources();
free_n2cp(np);
-
- return 0;
}
static struct n2_mau *alloc_ncp(void)
@@ -2109,7 +2107,7 @@ out_free_ncp:
return err;
}
-static int n2_mau_remove(struct platform_device *dev)
+static void n2_mau_remove(struct platform_device *dev)
{
struct n2_mau *mp = dev_get_drvdata(&dev->dev);
@@ -2118,8 +2116,6 @@ static int n2_mau_remove(struct platform_device *dev)
release_global_resources();
free_ncp(mp);
-
- return 0;
}
static const struct of_device_id n2_crypto_match[] = {
@@ -2146,7 +2142,7 @@ static struct platform_driver n2_crypto_driver = {
.of_match_table = n2_crypto_match,
},
.probe = n2_crypto_probe,
- .remove = n2_crypto_remove,
+ .remove_new = n2_crypto_remove,
};
static const struct of_device_id n2_mau_match[] = {
@@ -2173,7 +2169,7 @@ static struct platform_driver n2_mau_driver = {
.of_match_table = n2_mau_match,
},
.probe = n2_mau_probe,
- .remove = n2_mau_remove,
+ .remove_new = n2_mau_remove,
};
static struct platform_driver * const drivers[] = {
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index ed83023dd77a..bad1adacbc84 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -1255,7 +1255,7 @@ err_data:
return err;
}
-static int omap_aes_remove(struct platform_device *pdev)
+static void omap_aes_remove(struct platform_device *pdev)
{
struct omap_aes_dev *dd = platform_get_drvdata(pdev);
struct aead_engine_alg *aalg;
@@ -1285,8 +1285,6 @@ static int omap_aes_remove(struct platform_device *pdev)
pm_runtime_disable(dd->dev);
sysfs_remove_group(&dd->dev->kobj, &omap_aes_attr_group);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1307,7 +1305,7 @@ static SIMPLE_DEV_PM_OPS(omap_aes_pm_ops, omap_aes_suspend, omap_aes_resume);
static struct platform_driver omap_aes_driver = {
.probe = omap_aes_probe,
- .remove = omap_aes_remove,
+ .remove_new = omap_aes_remove,
.driver = {
.name = "omap-aes",
.pm = &omap_aes_pm_ops,
diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c
index 089dd45eaedd..209d3dc03a9b 100644
--- a/drivers/crypto/omap-des.c
+++ b/drivers/crypto/omap-des.c
@@ -1072,7 +1072,7 @@ err_data:
return err;
}
-static int omap_des_remove(struct platform_device *pdev)
+static void omap_des_remove(struct platform_device *pdev)
{
struct omap_des_dev *dd = platform_get_drvdata(pdev);
int i, j;
@@ -1089,8 +1089,6 @@ static int omap_des_remove(struct platform_device *pdev)
tasklet_kill(&dd->done_task);
omap_des_dma_cleanup(dd);
pm_runtime_disable(dd->dev);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1117,7 +1115,7 @@ static SIMPLE_DEV_PM_OPS(omap_des_pm_ops, omap_des_suspend, omap_des_resume);
static struct platform_driver omap_des_driver = {
.probe = omap_des_probe,
- .remove = omap_des_remove,
+ .remove_new = omap_des_remove,
.driver = {
.name = "omap-des",
.pm = &omap_des_pm_ops,
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index a6b4a0b3ace3..5bcd9ab0f72a 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -356,10 +356,10 @@ static void omap_sham_copy_ready_hash(struct ahash_request *req)
if (big_endian)
for (i = 0; i < d; i++)
- hash[i] = be32_to_cpup((__be32 *)in + i);
+ put_unaligned(be32_to_cpup((__be32 *)in + i), &hash[i]);
else
for (i = 0; i < d; i++)
- hash[i] = le32_to_cpup((__le32 *)in + i);
+ put_unaligned(le32_to_cpup((__le32 *)in + i), &hash[i]);
}
static void omap_sham_write_ctrl_omap2(struct omap_sham_dev *dd, size_t length,
@@ -1435,7 +1435,6 @@ static struct ahash_engine_alg algs_sha1_md5[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_init,
.cra_exit = omap_sham_cra_exit,
@@ -1458,7 +1457,6 @@ static struct ahash_engine_alg algs_sha1_md5[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_init,
.cra_exit = omap_sham_cra_exit,
@@ -1483,7 +1481,6 @@ static struct ahash_engine_alg algs_sha1_md5[] = {
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx) +
sizeof(struct omap_sham_hmac_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_sha1_init,
.cra_exit = omap_sham_cra_exit,
@@ -1508,7 +1505,6 @@ static struct ahash_engine_alg algs_sha1_md5[] = {
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx) +
sizeof(struct omap_sham_hmac_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_md5_init,
.cra_exit = omap_sham_cra_exit,
@@ -1535,7 +1531,6 @@ static struct ahash_engine_alg algs_sha224_sha256[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_init,
.cra_exit = omap_sham_cra_exit,
@@ -1558,7 +1553,6 @@ static struct ahash_engine_alg algs_sha224_sha256[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_init,
.cra_exit = omap_sham_cra_exit,
@@ -1583,7 +1577,6 @@ static struct ahash_engine_alg algs_sha224_sha256[] = {
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx) +
sizeof(struct omap_sham_hmac_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_sha224_init,
.cra_exit = omap_sham_cra_exit,
@@ -1608,7 +1601,6 @@ static struct ahash_engine_alg algs_sha224_sha256[] = {
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx) +
sizeof(struct omap_sham_hmac_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_sha256_init,
.cra_exit = omap_sham_cra_exit,
@@ -1634,7 +1626,6 @@ static struct ahash_engine_alg algs_sha384_sha512[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_init,
.cra_exit = omap_sham_cra_exit,
@@ -1657,7 +1648,6 @@ static struct ahash_engine_alg algs_sha384_sha512[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_init,
.cra_exit = omap_sham_cra_exit,
@@ -1682,7 +1672,6 @@ static struct ahash_engine_alg algs_sha384_sha512[] = {
.cra_blocksize = SHA384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx) +
sizeof(struct omap_sham_hmac_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_sha384_init,
.cra_exit = omap_sham_cra_exit,
@@ -1707,7 +1696,6 @@ static struct ahash_engine_alg algs_sha384_sha512[] = {
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_sham_ctx) +
sizeof(struct omap_sham_hmac_ctx),
- .cra_alignmask = OMAP_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = omap_sham_cra_sha512_init,
.cra_exit = omap_sham_cra_exit,
@@ -2200,7 +2188,7 @@ data_err:
return err;
}
-static int omap_sham_remove(struct platform_device *pdev)
+static void omap_sham_remove(struct platform_device *pdev)
{
struct omap_sham_dev *dd;
int i, j;
@@ -2224,13 +2212,11 @@ static int omap_sham_remove(struct platform_device *pdev)
dma_release_channel(dd->dma_lch);
sysfs_remove_group(&dd->dev->kobj, &omap_sham_attr_group);
-
- return 0;
}
static struct platform_driver omap_sham_driver = {
.probe = omap_sham_probe,
- .remove = omap_sham_remove,
+ .remove_new = omap_sham_remove,
.driver = {
.name = "omap-sham",
.of_match_table = omap_sham_of_match,
diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c
index fce49c0dee3e..28b5fd823827 100644
--- a/drivers/crypto/qce/core.c
+++ b/drivers/crypto/qce/core.c
@@ -277,7 +277,7 @@ err_mem_path_disable:
return ret;
}
-static int qce_crypto_remove(struct platform_device *pdev)
+static void qce_crypto_remove(struct platform_device *pdev)
{
struct qce_device *qce = platform_get_drvdata(pdev);
@@ -287,7 +287,6 @@ static int qce_crypto_remove(struct platform_device *pdev)
clk_disable_unprepare(qce->bus);
clk_disable_unprepare(qce->iface);
clk_disable_unprepare(qce->core);
- return 0;
}
static const struct of_device_id qce_crypto_of_match[] = {
@@ -300,7 +299,7 @@ MODULE_DEVICE_TABLE(of, qce_crypto_of_match);
static struct platform_driver qce_crypto_driver = {
.probe = qce_crypto_probe,
- .remove = qce_crypto_remove,
+ .remove_new = qce_crypto_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = qce_crypto_of_match,
diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c
index 825a729f205e..c670d7d0c11e 100644
--- a/drivers/crypto/qcom-rng.c
+++ b/drivers/crypto/qcom-rng.c
@@ -7,6 +7,7 @@
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/crypto.h>
+#include <linux/hw_random.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
@@ -28,17 +29,25 @@
#define WORD_SZ 4
+#define QCOM_TRNG_QUALITY 1024
+
struct qcom_rng {
struct mutex lock;
void __iomem *base;
struct clk *clk;
- unsigned int skip_init;
+ struct hwrng hwrng;
+ struct qcom_rng_of_data *of_data;
};
struct qcom_rng_ctx {
struct qcom_rng *rng;
};
+struct qcom_rng_of_data {
+ bool skip_init;
+ bool hwrng_support;
+};
+
static struct qcom_rng *qcom_rng_dev;
static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
@@ -66,11 +75,11 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
} else {
/* copy only remaining bytes */
memcpy(data, &val, max - currsize);
- break;
+ currsize = max;
}
} while (currsize < max);
- return 0;
+ return currsize;
}
static int qcom_rng_generate(struct crypto_rng *tfm,
@@ -92,6 +101,9 @@ static int qcom_rng_generate(struct crypto_rng *tfm,
mutex_unlock(&rng->lock);
clk_disable_unprepare(rng->clk);
+ if (ret >= 0)
+ ret = 0;
+
return ret;
}
@@ -101,6 +113,13 @@ static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed,
return 0;
}
+static int qcom_hwrng_read(struct hwrng *hwrng, void *data, size_t max, bool wait)
+{
+ struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng);
+
+ return qcom_rng_read(qrng, data, max);
+}
+
static int qcom_rng_enable(struct qcom_rng *rng)
{
u32 val;
@@ -136,7 +155,7 @@ static int qcom_rng_init(struct crypto_tfm *tfm)
ctx->rng = qcom_rng_dev;
- if (!ctx->rng->skip_init)
+ if (!ctx->rng->of_data->skip_init)
return qcom_rng_enable(ctx->rng);
return 0;
@@ -177,27 +196,56 @@ static int qcom_rng_probe(struct platform_device *pdev)
if (IS_ERR(rng->clk))
return PTR_ERR(rng->clk);
- rng->skip_init = (unsigned long)device_get_match_data(&pdev->dev);
+ rng->of_data = (struct qcom_rng_of_data *)of_device_get_match_data(&pdev->dev);
qcom_rng_dev = rng;
ret = crypto_register_rng(&qcom_rng_alg);
if (ret) {
dev_err(&pdev->dev, "Register crypto rng failed: %d\n", ret);
qcom_rng_dev = NULL;
+ return ret;
}
+ if (rng->of_data->hwrng_support) {
+ rng->hwrng.name = "qcom_hwrng";
+ rng->hwrng.read = qcom_hwrng_read;
+ rng->hwrng.quality = QCOM_TRNG_QUALITY;
+ ret = devm_hwrng_register(&pdev->dev, &rng->hwrng);
+ if (ret) {
+ dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret);
+ qcom_rng_dev = NULL;
+ goto fail;
+ }
+ }
+
+ return ret;
+fail:
+ crypto_unregister_rng(&qcom_rng_alg);
return ret;
}
-static int qcom_rng_remove(struct platform_device *pdev)
+static void qcom_rng_remove(struct platform_device *pdev)
{
crypto_unregister_rng(&qcom_rng_alg);
qcom_rng_dev = NULL;
-
- return 0;
}
+static struct qcom_rng_of_data qcom_prng_of_data = {
+ .skip_init = false,
+ .hwrng_support = false,
+};
+
+static struct qcom_rng_of_data qcom_prng_ee_of_data = {
+ .skip_init = true,
+ .hwrng_support = false,
+};
+
+static struct qcom_rng_of_data qcom_trng_of_data = {
+ .skip_init = true,
+ .hwrng_support = true,
+};
+
static const struct acpi_device_id __maybe_unused qcom_rng_acpi_match[] = {
{ .id = "QCOM8160", .driver_data = 1 },
{}
@@ -205,15 +253,16 @@ static const struct acpi_device_id __maybe_unused qcom_rng_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, qcom_rng_acpi_match);
static const struct of_device_id __maybe_unused qcom_rng_of_match[] = {
- { .compatible = "qcom,prng", .data = (void *)0},
- { .compatible = "qcom,prng-ee", .data = (void *)1},
+ { .compatible = "qcom,prng", .data = &qcom_prng_of_data },
+ { .compatible = "qcom,prng-ee", .data = &qcom_prng_ee_of_data },
+ { .compatible = "qcom,trng", .data = &qcom_trng_of_data },
{}
};
MODULE_DEVICE_TABLE(of, qcom_rng_of_match);
static struct platform_driver qcom_rng_driver = {
.probe = qcom_rng_probe,
- .remove = qcom_rng_remove,
+ .remove_new = qcom_rng_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = of_match_ptr(qcom_rng_of_match),
diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c
index 77d5705a5d96..70edf40bc523 100644
--- a/drivers/crypto/rockchip/rk3288_crypto.c
+++ b/drivers/crypto/rockchip/rk3288_crypto.c
@@ -405,7 +405,7 @@ err_crypto:
return err;
}
-static int rk_crypto_remove(struct platform_device *pdev)
+static void rk_crypto_remove(struct platform_device *pdev)
{
struct rk_crypto_info *crypto_tmp = platform_get_drvdata(pdev);
struct rk_crypto_info *first;
@@ -424,12 +424,11 @@ static int rk_crypto_remove(struct platform_device *pdev)
}
rk_crypto_pm_exit(crypto_tmp);
crypto_engine_exit(crypto_tmp->engine);
- return 0;
}
static struct platform_driver crypto_driver = {
.probe = rk_crypto_probe,
- .remove = rk_crypto_remove,
+ .remove_new = rk_crypto_remove,
.driver = {
.name = "rk3288-crypto",
.pm = &rk_crypto_pm_ops,
diff --git a/drivers/crypto/rockchip/rk3288_crypto_ahash.c b/drivers/crypto/rockchip/rk3288_crypto_ahash.c
index 8c143180645e..1b13b4aa16ec 100644
--- a/drivers/crypto/rockchip/rk3288_crypto_ahash.c
+++ b/drivers/crypto/rockchip/rk3288_crypto_ahash.c
@@ -393,7 +393,6 @@ struct rk_crypto_tmp rk_ahash_sha1 = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct rk_ahash_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
}
@@ -426,7 +425,6 @@ struct rk_crypto_tmp rk_ahash_sha256 = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct rk_ahash_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
}
@@ -459,7 +457,6 @@ struct rk_crypto_tmp rk_ahash_md5 = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct rk_ahash_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
}
diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c
index fe8cf9ba8005..8b6e3f5c94de 100644
--- a/drivers/crypto/s5p-sss.c
+++ b/drivers/crypto/s5p-sss.c
@@ -224,9 +224,6 @@
/* HASH HW constants */
#define BUFLEN HASH_BLOCK_SIZE
-#define SSS_HASH_DMA_LEN_ALIGN 8
-#define SSS_HASH_DMA_ALIGN_MASK (SSS_HASH_DMA_LEN_ALIGN - 1)
-
#define SSS_HASH_QUEUE_LENGTH 10
/**
@@ -1746,7 +1743,6 @@ static struct ahash_alg algs_sha1_md5_sha256[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = HASH_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct s5p_hash_ctx),
- .cra_alignmask = SSS_HASH_DMA_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = s5p_hash_cra_init,
.cra_exit = s5p_hash_cra_exit,
@@ -1771,7 +1767,6 @@ static struct ahash_alg algs_sha1_md5_sha256[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = HASH_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct s5p_hash_ctx),
- .cra_alignmask = SSS_HASH_DMA_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = s5p_hash_cra_init,
.cra_exit = s5p_hash_cra_exit,
@@ -1796,7 +1791,6 @@ static struct ahash_alg algs_sha1_md5_sha256[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = HASH_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct s5p_hash_ctx),
- .cra_alignmask = SSS_HASH_DMA_ALIGN_MASK,
.cra_module = THIS_MODULE,
.cra_init = s5p_hash_cra_init,
.cra_exit = s5p_hash_cra_exit,
@@ -2315,7 +2309,7 @@ err_clk:
return err;
}
-static int s5p_aes_remove(struct platform_device *pdev)
+static void s5p_aes_remove(struct platform_device *pdev)
{
struct s5p_aes_dev *pdata = platform_get_drvdata(pdev);
int i;
@@ -2337,13 +2331,11 @@ static int s5p_aes_remove(struct platform_device *pdev)
clk_disable_unprepare(pdata->clk);
s5p_dev = NULL;
-
- return 0;
}
static struct platform_driver s5p_aes_crypto = {
.probe = s5p_aes_probe,
- .remove = s5p_aes_remove,
+ .remove_new = s5p_aes_remove,
.driver = {
.name = "s5p-secss",
.of_match_table = s5p_sss_dt_match,
diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c
index 6238d34f8db2..6846a8429574 100644
--- a/drivers/crypto/sa2ul.c
+++ b/drivers/crypto/sa2ul.c
@@ -2468,7 +2468,7 @@ destroy_dma_pool:
return ret;
}
-static int sa_ul_remove(struct platform_device *pdev)
+static void sa_ul_remove(struct platform_device *pdev)
{
struct sa_crypto_data *dev_data = platform_get_drvdata(pdev);
@@ -2486,13 +2486,11 @@ static int sa_ul_remove(struct platform_device *pdev)
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
static struct platform_driver sa_ul_driver = {
.probe = sa_ul_probe,
- .remove = sa_ul_remove,
+ .remove_new = sa_ul_remove,
.driver = {
.name = "saul-crypto",
.of_match_table = of_match,
diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c
index 62d93526920f..02065131c300 100644
--- a/drivers/crypto/sahara.c
+++ b/drivers/crypto/sahara.c
@@ -1510,7 +1510,7 @@ clk_ipg_disable:
return err;
}
-static int sahara_remove(struct platform_device *pdev)
+static void sahara_remove(struct platform_device *pdev)
{
struct sahara_dev *dev = platform_get_drvdata(pdev);
@@ -1522,13 +1522,11 @@ static int sahara_remove(struct platform_device *pdev)
clk_disable_unprepare(dev->clk_ahb);
dev_ptr = NULL;
-
- return 0;
}
static struct platform_driver sahara_driver = {
.probe = sahara_probe,
- .remove = sahara_remove,
+ .remove_new = sahara_remove,
.driver = {
.name = SAHARA_NAME,
.of_match_table = sahara_dt_ids,
diff --git a/drivers/crypto/starfive/jh7110-hash.c b/drivers/crypto/starfive/jh7110-hash.c
index cc7650198d70..b6d1808012ca 100644
--- a/drivers/crypto/starfive/jh7110-hash.c
+++ b/drivers/crypto/starfive/jh7110-hash.c
@@ -209,7 +209,8 @@ static int starfive_hash_copy_hash(struct ahash_request *req)
data = (u32 *)req->result;
for (count = 0; count < mlen; count++)
- data[count] = readl(ctx->cryp->base + STARFIVE_HASH_SHARDR);
+ put_unaligned(readl(ctx->cryp->base + STARFIVE_HASH_SHARDR),
+ &data[count]);
return 0;
}
@@ -628,7 +629,6 @@ static struct ahash_engine_alg algs_sha2_sm3[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -658,7 +658,6 @@ static struct ahash_engine_alg algs_sha2_sm3[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -687,7 +686,6 @@ static struct ahash_engine_alg algs_sha2_sm3[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -717,7 +715,6 @@ static struct ahash_engine_alg algs_sha2_sm3[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -746,7 +743,6 @@ static struct ahash_engine_alg algs_sha2_sm3[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -776,7 +772,6 @@ static struct ahash_engine_alg algs_sha2_sm3[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -805,7 +800,6 @@ static struct ahash_engine_alg algs_sha2_sm3[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -835,7 +829,6 @@ static struct ahash_engine_alg algs_sha2_sm3[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -864,7 +857,6 @@ static struct ahash_engine_alg algs_sha2_sm3[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SM3_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -894,7 +886,6 @@ static struct ahash_engine_alg algs_sha2_sm3[] = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SM3_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
diff --git a/drivers/crypto/stm32/stm32-crc32.c b/drivers/crypto/stm32/stm32-crc32.c
index 90a920e7f664..b2d5c8921ab3 100644
--- a/drivers/crypto/stm32/stm32-crc32.c
+++ b/drivers/crypto/stm32/stm32-crc32.c
@@ -283,7 +283,6 @@ static struct shash_alg algs[] = {
.cra_priority = 200,
.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
.cra_blocksize = CHKSUM_BLOCK_SIZE,
- .cra_alignmask = 3,
.cra_ctxsize = sizeof(struct stm32_crc_ctx),
.cra_module = THIS_MODULE,
.cra_init = stm32_crc32_cra_init,
@@ -305,7 +304,6 @@ static struct shash_alg algs[] = {
.cra_priority = 200,
.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
.cra_blocksize = CHKSUM_BLOCK_SIZE,
- .cra_alignmask = 3,
.cra_ctxsize = sizeof(struct stm32_crc_ctx),
.cra_module = THIS_MODULE,
.cra_init = stm32_crc32c_cra_init,
@@ -379,16 +377,11 @@ static int stm32_crc_probe(struct platform_device *pdev)
return 0;
}
-static int stm32_crc_remove(struct platform_device *pdev)
+static void stm32_crc_remove(struct platform_device *pdev)
{
struct stm32_crc *crc = platform_get_drvdata(pdev);
int ret = pm_runtime_get_sync(crc->dev);
- if (ret < 0) {
- pm_runtime_put_noidle(crc->dev);
- return ret;
- }
-
spin_lock(&crc_list.lock);
list_del(&crc->list);
spin_unlock(&crc_list.lock);
@@ -401,9 +394,9 @@ static int stm32_crc_remove(struct platform_device *pdev)
pm_runtime_disable(crc->dev);
pm_runtime_put_noidle(crc->dev);
- clk_disable_unprepare(crc->clk);
-
- return 0;
+ if (ret >= 0)
+ clk_disable(crc->clk);
+ clk_unprepare(crc->clk);
}
static int __maybe_unused stm32_crc_suspend(struct device *dev)
@@ -472,7 +465,7 @@ MODULE_DEVICE_TABLE(of, stm32_dt_ids);
static struct platform_driver stm32_crc_driver = {
.probe = stm32_crc_probe,
- .remove = stm32_crc_remove,
+ .remove_new = stm32_crc_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &stm32_crc_pm_ops,
diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c
index f095f0065428..c3cbc2673338 100644
--- a/drivers/crypto/stm32/stm32-cryp.c
+++ b/drivers/crypto/stm32/stm32-cryp.c
@@ -2084,17 +2084,12 @@ err_rst:
return ret;
}
-static int stm32_cryp_remove(struct platform_device *pdev)
+static void stm32_cryp_remove(struct platform_device *pdev)
{
struct stm32_cryp *cryp = platform_get_drvdata(pdev);
int ret;
- if (!cryp)
- return -ENODEV;
-
- ret = pm_runtime_resume_and_get(cryp->dev);
- if (ret < 0)
- return ret;
+ ret = pm_runtime_get_sync(cryp->dev);
if (cryp->caps->aeads_support)
crypto_engine_unregister_aeads(aead_algs, ARRAY_SIZE(aead_algs));
@@ -2109,9 +2104,8 @@ static int stm32_cryp_remove(struct platform_device *pdev)
pm_runtime_disable(cryp->dev);
pm_runtime_put_noidle(cryp->dev);
- clk_disable_unprepare(cryp->clk);
-
- return 0;
+ if (ret >= 0)
+ clk_disable_unprepare(cryp->clk);
}
#ifdef CONFIG_PM
@@ -2148,7 +2142,7 @@ static const struct dev_pm_ops stm32_cryp_pm_ops = {
static struct platform_driver stm32_cryp_driver = {
.probe = stm32_cryp_probe,
- .remove = stm32_cryp_remove,
+ .remove_new = stm32_cryp_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &stm32_cryp_pm_ops,
diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c
index 2b2382d4332c..34e0d7e381a8 100644
--- a/drivers/crypto/stm32/stm32-hash.c
+++ b/drivers/crypto/stm32/stm32-hash.c
@@ -1283,7 +1283,6 @@ static struct ahash_engine_alg algs_md5[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1313,7 +1312,6 @@ static struct ahash_engine_alg algs_md5[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1345,7 +1343,6 @@ static struct ahash_engine_alg algs_sha1[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1375,7 +1372,6 @@ static struct ahash_engine_alg algs_sha1[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1407,7 +1403,6 @@ static struct ahash_engine_alg algs_sha224[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1437,7 +1432,6 @@ static struct ahash_engine_alg algs_sha224[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1469,7 +1463,6 @@ static struct ahash_engine_alg algs_sha256[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1499,7 +1492,6 @@ static struct ahash_engine_alg algs_sha256[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1531,7 +1523,6 @@ static struct ahash_engine_alg algs_sha384_sha512[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1561,7 +1552,6 @@ static struct ahash_engine_alg algs_sha384_sha512[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1590,7 +1580,6 @@ static struct ahash_engine_alg algs_sha384_sha512[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1620,7 +1609,6 @@ static struct ahash_engine_alg algs_sha384_sha512[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1652,7 +1640,6 @@ static struct ahash_engine_alg algs_sha3[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA3_224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_sha3_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1682,7 +1669,6 @@ static struct ahash_engine_alg algs_sha3[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA3_224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_sha3_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1711,7 +1697,6 @@ static struct ahash_engine_alg algs_sha3[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA3_256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_sha3_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1741,7 +1726,6 @@ static struct ahash_engine_alg algs_sha3[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA3_256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_sha3_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1770,7 +1754,6 @@ static struct ahash_engine_alg algs_sha3[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA3_384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_sha3_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1800,7 +1783,6 @@ static struct ahash_engine_alg algs_sha3[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA3_384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_sha3_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1829,7 +1811,6 @@ static struct ahash_engine_alg algs_sha3[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA3_512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_sha3_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
@@ -1859,7 +1840,6 @@ static struct ahash_engine_alg algs_sha3[] = {
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = SHA3_512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
- .cra_alignmask = 3,
.cra_init = stm32_hash_cra_sha3_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 4ca4fbd227bc..511ddcb0efd4 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -2119,13 +2119,14 @@ static int ahash_finup(struct ahash_request *areq)
static int ahash_digest(struct ahash_request *areq)
{
- struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
- struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
-
- ahash->init(areq);
- req_ctx->last = 1;
+ ahash_init(areq);
+ return ahash_finup(areq);
+}
- return ahash_process_req(areq, areq->nbytes);
+static int ahash_digest_sha224_swinit(struct ahash_request *areq)
+{
+ ahash_init_sha224_swinit(areq);
+ return ahash_finup(areq);
}
static int ahash_export(struct ahash_request *areq, void *out)
@@ -3136,7 +3137,7 @@ static int hw_supports(struct device *dev, __be32 desc_hdr_template)
return ret;
}
-static int talitos_remove(struct platform_device *ofdev)
+static void talitos_remove(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
struct talitos_private *priv = dev_get_drvdata(dev);
@@ -3170,8 +3171,6 @@ static int talitos_remove(struct platform_device *ofdev)
tasklet_kill(&priv->done_task[0]);
if (priv->irq[1])
tasklet_kill(&priv->done_task[1]);
-
- return 0;
}
static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
@@ -3242,6 +3241,8 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
(!strcmp(alg->cra_name, "sha224") ||
!strcmp(alg->cra_name, "hmac(sha224)"))) {
t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
+ t_alg->algt.alg.hash.digest =
+ ahash_digest_sha224_swinit;
t_alg->algt.desc_hdr_template =
DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
DESC_HDR_SEL0_MDEUA |
@@ -3259,7 +3260,7 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
alg->cra_priority = t_alg->algt.priority;
else
alg->cra_priority = TALITOS_CRA_PRIORITY;
- if (has_ftr_sec1(priv))
+ if (has_ftr_sec1(priv) && t_alg->algt.type != CRYPTO_ALG_TYPE_AHASH)
alg->cra_alignmask = 3;
else
alg->cra_alignmask = 0;
@@ -3559,7 +3560,7 @@ static struct platform_driver talitos_driver = {
.of_match_table = talitos_match,
},
.probe = talitos_probe,
- .remove = talitos_remove,
+ .remove_new = talitos_remove,
};
module_platform_driver(talitos_driver);
diff --git a/drivers/crypto/virtio/virtio_crypto_common.h b/drivers/crypto/virtio/virtio_crypto_common.h
index 59a4c0259456..154590e1f764 100644
--- a/drivers/crypto/virtio/virtio_crypto_common.h
+++ b/drivers/crypto/virtio/virtio_crypto_common.h
@@ -35,6 +35,9 @@ struct virtio_crypto {
struct virtqueue *ctrl_vq;
struct data_queue *data_vq;
+ /* Work struct for config space updates */
+ struct work_struct config_work;
+
/* To protect the vq operations for the controlq */
spinlock_t ctrl_lock;
diff --git a/drivers/crypto/virtio/virtio_crypto_core.c b/drivers/crypto/virtio/virtio_crypto_core.c
index 94849fa3bd74..43a0838d31ff 100644
--- a/drivers/crypto/virtio/virtio_crypto_core.c
+++ b/drivers/crypto/virtio/virtio_crypto_core.c
@@ -335,6 +335,14 @@ static void virtcrypto_del_vqs(struct virtio_crypto *vcrypto)
virtcrypto_free_queues(vcrypto);
}
+static void vcrypto_config_changed_work(struct work_struct *work)
+{
+ struct virtio_crypto *vcrypto =
+ container_of(work, struct virtio_crypto, config_work);
+
+ virtcrypto_update_status(vcrypto);
+}
+
static int virtcrypto_probe(struct virtio_device *vdev)
{
int err = -EFAULT;
@@ -454,6 +462,8 @@ static int virtcrypto_probe(struct virtio_device *vdev)
if (err)
goto free_engines;
+ INIT_WORK(&vcrypto->config_work, vcrypto_config_changed_work);
+
return 0;
free_engines:
@@ -490,6 +500,7 @@ static void virtcrypto_remove(struct virtio_device *vdev)
dev_info(&vdev->dev, "Start virtcrypto_remove.\n");
+ flush_work(&vcrypto->config_work);
if (virtcrypto_dev_started(vcrypto))
virtcrypto_dev_stop(vcrypto);
virtio_reset_device(vdev);
@@ -504,7 +515,7 @@ static void virtcrypto_config_changed(struct virtio_device *vdev)
{
struct virtio_crypto *vcrypto = vdev->priv;
- virtcrypto_update_status(vcrypto);
+ schedule_work(&vcrypto->config_work);
}
#ifdef CONFIG_PM_SLEEP
@@ -512,6 +523,7 @@ static int virtcrypto_freeze(struct virtio_device *vdev)
{
struct virtio_crypto *vcrypto = vdev->priv;
+ flush_work(&vcrypto->config_work);
virtio_reset_device(vdev);
virtcrypto_free_unused_reqs(vcrypto);
if (virtcrypto_dev_started(vcrypto))
diff --git a/drivers/crypto/vmx/aesp8-ppc.pl b/drivers/crypto/vmx/aesp8-ppc.pl
index 50a0a18f35da..f729589d792e 100644
--- a/drivers/crypto/vmx/aesp8-ppc.pl
+++ b/drivers/crypto/vmx/aesp8-ppc.pl
@@ -132,11 +132,12 @@ rcon:
.long 0x1b000000, 0x1b000000, 0x1b000000, 0x1b000000 ?rev
.long 0x0d0e0f0c, 0x0d0e0f0c, 0x0d0e0f0c, 0x0d0e0f0c ?rev
.long 0,0,0,0 ?asis
+.long 0x0f102132, 0x43546576, 0x8798a9ba, 0xcbdcedfe
Lconsts:
mflr r0
bcl 20,31,\$+4
mflr $ptr #vvvvv "distance between . and rcon
- addi $ptr,$ptr,-0x48
+ addi $ptr,$ptr,-0x58
mtlr r0
blr
.long 0
@@ -2495,6 +2496,17 @@ _aesp8_xts_encrypt6x:
li $x70,0x70
mtspr 256,r0
+ xxlor 2, 32+$eighty7, 32+$eighty7
+ vsldoi $eighty7,$tmp,$eighty7,1 # 0x010101..87
+ xxlor 1, 32+$eighty7, 32+$eighty7
+
+ # Load XOR Lconsts.
+ mr $x70, r6
+ bl Lconsts
+ lxvw4x 0, $x40, r6 # load XOR contents
+ mr r6, $x70
+ li $x70,0x70
+
subi $rounds,$rounds,3 # -4 in total
lvx $rndkey0,$x00,$key1 # load key schedule
@@ -2537,69 +2549,77 @@ Load_xts_enc_key:
?vperm v31,v31,$twk5,$keyperm
lvx v25,$x10,$key_ # pre-load round[2]
+ # Switch to use the following codes with 0x010101..87 to generate tweak.
+ # eighty7 = 0x010101..87
+ # vsrab tmp, tweak, seven # next tweak value, right shift 7 bits
+ # vand tmp, tmp, eighty7 # last byte with carry
+ # vaddubm tweak, tweak, tweak # left shift 1 bit (x2)
+ # xxlor vsx, 0, 0
+ # vpermxor tweak, tweak, tmp, vsx
+
vperm $in0,$inout,$inptail,$inpperm
subi $inp,$inp,31 # undo "caller"
vxor $twk0,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vand $tmp,$tmp,$eighty7
vxor $out0,$in0,$twk0
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in1, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in1
lvx_u $in1,$x10,$inp
vxor $twk1,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in1,$in1,$in1,$leperm
vand $tmp,$tmp,$eighty7
vxor $out1,$in1,$twk1
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in2, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in2
lvx_u $in2,$x20,$inp
andi. $taillen,$len,15
vxor $twk2,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in2,$in2,$in2,$leperm
vand $tmp,$tmp,$eighty7
vxor $out2,$in2,$twk2
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in3, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in3
lvx_u $in3,$x30,$inp
sub $len,$len,$taillen
vxor $twk3,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in3,$in3,$in3,$leperm
vand $tmp,$tmp,$eighty7
vxor $out3,$in3,$twk3
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in4, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in4
lvx_u $in4,$x40,$inp
subi $len,$len,0x60
vxor $twk4,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in4,$in4,$in4,$leperm
vand $tmp,$tmp,$eighty7
vxor $out4,$in4,$twk4
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in5, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in5
lvx_u $in5,$x50,$inp
addi $inp,$inp,0x60
vxor $twk5,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in5,$in5,$in5,$leperm
vand $tmp,$tmp,$eighty7
vxor $out5,$in5,$twk5
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in0, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in0
vxor v31,v31,$rndkey0
mtctr $rounds
@@ -2625,6 +2645,8 @@ Loop_xts_enc6x:
lvx v25,$x10,$key_ # round[4]
bdnz Loop_xts_enc6x
+ xxlor 32+$eighty7, 1, 1 # 0x010101..87
+
subic $len,$len,96 # $len-=96
vxor $in0,$twk0,v31 # xor with last round key
vcipher $out0,$out0,v24
@@ -2634,7 +2656,6 @@ Loop_xts_enc6x:
vaddubm $tweak,$tweak,$tweak
vcipher $out2,$out2,v24
vcipher $out3,$out3,v24
- vsldoi $tmp,$tmp,$tmp,15
vcipher $out4,$out4,v24
vcipher $out5,$out5,v24
@@ -2642,7 +2663,8 @@ Loop_xts_enc6x:
vand $tmp,$tmp,$eighty7
vcipher $out0,$out0,v25
vcipher $out1,$out1,v25
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in1, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in1
vcipher $out2,$out2,v25
vcipher $out3,$out3,v25
vxor $in1,$twk1,v31
@@ -2653,13 +2675,13 @@ Loop_xts_enc6x:
and r0,r0,$len
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vcipher $out0,$out0,v26
vcipher $out1,$out1,v26
vand $tmp,$tmp,$eighty7
vcipher $out2,$out2,v26
vcipher $out3,$out3,v26
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in2, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in2
vcipher $out4,$out4,v26
vcipher $out5,$out5,v26
@@ -2673,7 +2695,6 @@ Loop_xts_enc6x:
vaddubm $tweak,$tweak,$tweak
vcipher $out0,$out0,v27
vcipher $out1,$out1,v27
- vsldoi $tmp,$tmp,$tmp,15
vcipher $out2,$out2,v27
vcipher $out3,$out3,v27
vand $tmp,$tmp,$eighty7
@@ -2681,7 +2702,8 @@ Loop_xts_enc6x:
vcipher $out5,$out5,v27
addi $key_,$sp,$FRAME+15 # rewind $key_
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in3, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in3
vcipher $out0,$out0,v28
vcipher $out1,$out1,v28
vxor $in3,$twk3,v31
@@ -2690,7 +2712,6 @@ Loop_xts_enc6x:
vcipher $out2,$out2,v28
vcipher $out3,$out3,v28
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vcipher $out4,$out4,v28
vcipher $out5,$out5,v28
lvx v24,$x00,$key_ # re-pre-load round[1]
@@ -2698,7 +2719,8 @@ Loop_xts_enc6x:
vcipher $out0,$out0,v29
vcipher $out1,$out1,v29
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in4, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in4
vcipher $out2,$out2,v29
vcipher $out3,$out3,v29
vxor $in4,$twk4,v31
@@ -2708,14 +2730,14 @@ Loop_xts_enc6x:
vcipher $out5,$out5,v29
lvx v25,$x10,$key_ # re-pre-load round[2]
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vcipher $out0,$out0,v30
vcipher $out1,$out1,v30
vand $tmp,$tmp,$eighty7
vcipher $out2,$out2,v30
vcipher $out3,$out3,v30
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in5, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in5
vcipher $out4,$out4,v30
vcipher $out5,$out5,v30
vxor $in5,$twk5,v31
@@ -2725,7 +2747,6 @@ Loop_xts_enc6x:
vcipherlast $out0,$out0,$in0
lvx_u $in0,$x00,$inp # load next input block
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vcipherlast $out1,$out1,$in1
lvx_u $in1,$x10,$inp
vcipherlast $out2,$out2,$in2
@@ -2738,7 +2759,10 @@ Loop_xts_enc6x:
vcipherlast $out4,$out4,$in4
le?vperm $in2,$in2,$in2,$leperm
lvx_u $in4,$x40,$inp
- vxor $tweak,$tweak,$tmp
+ xxlor 10, 32+$in0, 32+$in0
+ xxlor 32+$in0, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in0
+ xxlor 32+$in0, 10, 10
vcipherlast $tmp,$out5,$in5 # last block might be needed
# in stealing mode
le?vperm $in3,$in3,$in3,$leperm
@@ -2771,6 +2795,8 @@ Loop_xts_enc6x:
mtctr $rounds
beq Loop_xts_enc6x # did $len-=96 borrow?
+ xxlor 32+$eighty7, 2, 2 # 0x010101..87
+
addic. $len,$len,0x60
beq Lxts_enc6x_zero
cmpwi $len,0x20
@@ -3147,6 +3173,17 @@ _aesp8_xts_decrypt6x:
li $x70,0x70
mtspr 256,r0
+ xxlor 2, 32+$eighty7, 32+$eighty7
+ vsldoi $eighty7,$tmp,$eighty7,1 # 0x010101..87
+ xxlor 1, 32+$eighty7, 32+$eighty7
+
+ # Load XOR Lconsts.
+ mr $x70, r6
+ bl Lconsts
+ lxvw4x 0, $x40, r6 # load XOR contents
+ mr r6, $x70
+ li $x70,0x70
+
subi $rounds,$rounds,3 # -4 in total
lvx $rndkey0,$x00,$key1 # load key schedule
@@ -3194,64 +3231,64 @@ Load_xts_dec_key:
vxor $twk0,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vand $tmp,$tmp,$eighty7
vxor $out0,$in0,$twk0
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in1, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in1
lvx_u $in1,$x10,$inp
vxor $twk1,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in1,$in1,$in1,$leperm
vand $tmp,$tmp,$eighty7
vxor $out1,$in1,$twk1
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in2, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in2
lvx_u $in2,$x20,$inp
andi. $taillen,$len,15
vxor $twk2,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in2,$in2,$in2,$leperm
vand $tmp,$tmp,$eighty7
vxor $out2,$in2,$twk2
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in3, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in3
lvx_u $in3,$x30,$inp
sub $len,$len,$taillen
vxor $twk3,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in3,$in3,$in3,$leperm
vand $tmp,$tmp,$eighty7
vxor $out3,$in3,$twk3
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in4, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in4
lvx_u $in4,$x40,$inp
subi $len,$len,0x60
vxor $twk4,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in4,$in4,$in4,$leperm
vand $tmp,$tmp,$eighty7
vxor $out4,$in4,$twk4
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in5, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in5
lvx_u $in5,$x50,$inp
addi $inp,$inp,0x60
vxor $twk5,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in5,$in5,$in5,$leperm
vand $tmp,$tmp,$eighty7
vxor $out5,$in5,$twk5
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in0, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in0
vxor v31,v31,$rndkey0
mtctr $rounds
@@ -3277,6 +3314,8 @@ Loop_xts_dec6x:
lvx v25,$x10,$key_ # round[4]
bdnz Loop_xts_dec6x
+ xxlor 32+$eighty7, 1, 1 # 0x010101..87
+
subic $len,$len,96 # $len-=96
vxor $in0,$twk0,v31 # xor with last round key
vncipher $out0,$out0,v24
@@ -3286,7 +3325,6 @@ Loop_xts_dec6x:
vaddubm $tweak,$tweak,$tweak
vncipher $out2,$out2,v24
vncipher $out3,$out3,v24
- vsldoi $tmp,$tmp,$tmp,15
vncipher $out4,$out4,v24
vncipher $out5,$out5,v24
@@ -3294,7 +3332,8 @@ Loop_xts_dec6x:
vand $tmp,$tmp,$eighty7
vncipher $out0,$out0,v25
vncipher $out1,$out1,v25
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in1, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in1
vncipher $out2,$out2,v25
vncipher $out3,$out3,v25
vxor $in1,$twk1,v31
@@ -3305,13 +3344,13 @@ Loop_xts_dec6x:
and r0,r0,$len
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vncipher $out0,$out0,v26
vncipher $out1,$out1,v26
vand $tmp,$tmp,$eighty7
vncipher $out2,$out2,v26
vncipher $out3,$out3,v26
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in2, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in2
vncipher $out4,$out4,v26
vncipher $out5,$out5,v26
@@ -3325,7 +3364,6 @@ Loop_xts_dec6x:
vaddubm $tweak,$tweak,$tweak
vncipher $out0,$out0,v27
vncipher $out1,$out1,v27
- vsldoi $tmp,$tmp,$tmp,15
vncipher $out2,$out2,v27
vncipher $out3,$out3,v27
vand $tmp,$tmp,$eighty7
@@ -3333,7 +3371,8 @@ Loop_xts_dec6x:
vncipher $out5,$out5,v27
addi $key_,$sp,$FRAME+15 # rewind $key_
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in3, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in3
vncipher $out0,$out0,v28
vncipher $out1,$out1,v28
vxor $in3,$twk3,v31
@@ -3342,7 +3381,6 @@ Loop_xts_dec6x:
vncipher $out2,$out2,v28
vncipher $out3,$out3,v28
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vncipher $out4,$out4,v28
vncipher $out5,$out5,v28
lvx v24,$x00,$key_ # re-pre-load round[1]
@@ -3350,7 +3388,8 @@ Loop_xts_dec6x:
vncipher $out0,$out0,v29
vncipher $out1,$out1,v29
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in4, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in4
vncipher $out2,$out2,v29
vncipher $out3,$out3,v29
vxor $in4,$twk4,v31
@@ -3360,14 +3399,14 @@ Loop_xts_dec6x:
vncipher $out5,$out5,v29
lvx v25,$x10,$key_ # re-pre-load round[2]
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vncipher $out0,$out0,v30
vncipher $out1,$out1,v30
vand $tmp,$tmp,$eighty7
vncipher $out2,$out2,v30
vncipher $out3,$out3,v30
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in5, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in5
vncipher $out4,$out4,v30
vncipher $out5,$out5,v30
vxor $in5,$twk5,v31
@@ -3377,7 +3416,6 @@ Loop_xts_dec6x:
vncipherlast $out0,$out0,$in0
lvx_u $in0,$x00,$inp # load next input block
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vncipherlast $out1,$out1,$in1
lvx_u $in1,$x10,$inp
vncipherlast $out2,$out2,$in2
@@ -3390,7 +3428,10 @@ Loop_xts_dec6x:
vncipherlast $out4,$out4,$in4
le?vperm $in2,$in2,$in2,$leperm
lvx_u $in4,$x40,$inp
- vxor $tweak,$tweak,$tmp
+ xxlor 10, 32+$in0, 32+$in0
+ xxlor 32+$in0, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in0
+ xxlor 32+$in0, 10, 10
vncipherlast $out5,$out5,$in5
le?vperm $in3,$in3,$in3,$leperm
lvx_u $in5,$x50,$inp
@@ -3421,6 +3462,8 @@ Loop_xts_dec6x:
mtctr $rounds
beq Loop_xts_dec6x # did $len-=96 borrow?
+ xxlor 32+$eighty7, 2, 2 # 0x010101..87
+
addic. $len,$len,0x60
beq Lxts_dec6x_zero
cmpwi $len,0x20
diff --git a/drivers/crypto/xilinx/zynqmp-aes-gcm.c b/drivers/crypto/xilinx/zynqmp-aes-gcm.c
index ce335578b759..3c205324b22b 100644
--- a/drivers/crypto/xilinx/zynqmp-aes-gcm.c
+++ b/drivers/crypto/xilinx/zynqmp-aes-gcm.c
@@ -421,12 +421,10 @@ err_engine:
return err;
}
-static int zynqmp_aes_aead_remove(struct platform_device *pdev)
+static void zynqmp_aes_aead_remove(struct platform_device *pdev)
{
crypto_engine_exit(aes_drv_ctx.engine);
crypto_engine_unregister_aead(&aes_drv_ctx.alg.aead);
-
- return 0;
}
static const struct of_device_id zynqmp_aes_dt_ids[] = {
@@ -437,7 +435,7 @@ MODULE_DEVICE_TABLE(of, zynqmp_aes_dt_ids);
static struct platform_driver zynqmp_aes_driver = {
.probe = zynqmp_aes_aead_probe,
- .remove = zynqmp_aes_aead_remove,
+ .remove_new = zynqmp_aes_aead_remove,
.driver = {
.name = "zynqmp-aes",
.of_match_table = zynqmp_aes_dt_ids,
diff --git a/drivers/crypto/xilinx/zynqmp-sha.c b/drivers/crypto/xilinx/zynqmp-sha.c
index 426bf1a72ba6..1bcec6f46c9c 100644
--- a/drivers/crypto/xilinx/zynqmp-sha.c
+++ b/drivers/crypto/xilinx/zynqmp-sha.c
@@ -182,7 +182,6 @@ static struct zynqmp_sha_drv_ctx sha3_drv_ctx = {
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA3_384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct zynqmp_sha_tfm_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
}
@@ -238,20 +237,18 @@ err_shash:
return err;
}
-static int zynqmp_sha_remove(struct platform_device *pdev)
+static void zynqmp_sha_remove(struct platform_device *pdev)
{
sha3_drv_ctx.dev = platform_get_drvdata(pdev);
dma_free_coherent(sha3_drv_ctx.dev, ZYNQMP_DMA_ALLOC_FIXED_SIZE, ubuf, update_dma_addr);
dma_free_coherent(sha3_drv_ctx.dev, SHA3_384_DIGEST_SIZE, fbuf, final_dma_addr);
crypto_unregister_shash(&sha3_drv_ctx.sha3_384);
-
- return 0;
}
static struct platform_driver zynqmp_sha_driver = {
.probe = zynqmp_sha_probe,
- .remove = zynqmp_sha_remove,
+ .remove_new = zynqmp_sha_remove,
.driver = {
.name = "zynqmp-sha3-384",
},
diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
index 40d055560e52..2034eb4ce83f 100644
--- a/drivers/cxl/acpi.c
+++ b/drivers/cxl/acpi.c
@@ -289,6 +289,9 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
}
}
}
+
+ cxlrd->qos_class = cfmws->qtg_id;
+
rc = cxl_decoder_add(cxld, target_map);
err_xormap:
if (rc)
diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index 45e7e044cf4a..86d7ba23235e 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -73,8 +73,10 @@ struct cxl_rcrb_info;
resource_size_t __rcrb_to_component(struct device *dev,
struct cxl_rcrb_info *ri,
enum cxl_rcrb which);
+u16 cxl_rcrb_to_aer(struct device *dev, resource_size_t rcrb);
extern struct rw_semaphore cxl_dpa_rwsem;
+extern struct rw_semaphore cxl_region_rwsem;
int cxl_memdev_init(void);
void cxl_memdev_exit(void);
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index 4449b34a80cc..7d97790b893d 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -81,26 +81,6 @@ static void parse_hdm_decoder_caps(struct cxl_hdm *cxlhdm)
cxlhdm->interleave_mask |= GENMASK(14, 12);
}
-static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
- struct cxl_component_regs *regs)
-{
- struct cxl_register_map map = {
- .dev = &port->dev,
- .resource = port->component_reg_phys,
- .base = crb,
- .max_size = CXL_COMPONENT_REG_BLOCK_SIZE,
- };
-
- cxl_probe_component_regs(&port->dev, crb, &map.component_map);
- if (!map.component_map.hdm_decoder.valid) {
- dev_dbg(&port->dev, "HDM decoder registers not implemented\n");
- /* unique error code to indicate no HDM decoder capability */
- return -ENODEV;
- }
-
- return cxl_map_component_regs(&map, regs, BIT(CXL_CM_CAP_CAP_ID_HDM));
-}
-
static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
{
struct cxl_hdm *cxlhdm;
@@ -153,9 +133,9 @@ static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port,
struct cxl_endpoint_dvsec_info *info)
{
+ struct cxl_register_map *reg_map = &port->reg_map;
struct device *dev = &port->dev;
struct cxl_hdm *cxlhdm;
- void __iomem *crb;
int rc;
cxlhdm = devm_kzalloc(dev, sizeof(*cxlhdm), GFP_KERNEL);
@@ -164,19 +144,29 @@ struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port,
cxlhdm->port = port;
dev_set_drvdata(dev, cxlhdm);
- crb = ioremap(port->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE);
- if (!crb && info && info->mem_enabled) {
+ /* Memory devices can configure device HDM using DVSEC range regs. */
+ if (reg_map->resource == CXL_RESOURCE_NONE) {
+ if (!info || !info->mem_enabled) {
+ dev_err(dev, "No component registers mapped\n");
+ return ERR_PTR(-ENXIO);
+ }
+
cxlhdm->decoder_count = info->ranges;
return cxlhdm;
- } else if (!crb) {
- dev_err(dev, "No component registers mapped\n");
- return ERR_PTR(-ENXIO);
}
- rc = map_hdm_decoder_regs(port, crb, &cxlhdm->regs);
- iounmap(crb);
- if (rc)
+ if (!reg_map->component_map.hdm_decoder.valid) {
+ dev_dbg(&port->dev, "HDM decoder registers not implemented\n");
+ /* unique error code to indicate no HDM decoder capability */
+ return ERR_PTR(-ENODEV);
+ }
+
+ rc = cxl_map_component_regs(reg_map, &cxlhdm->regs,
+ BIT(CXL_CM_CAP_CAP_ID_HDM));
+ if (rc) {
+ dev_err(dev, "Failed to map HDM capability.\n");
return ERR_PTR(rc);
+ }
parse_hdm_decoder_caps(cxlhdm);
if (cxlhdm->decoder_count == 0) {
@@ -373,10 +363,9 @@ resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled)
{
resource_size_t base = -1;
- down_read(&cxl_dpa_rwsem);
+ lockdep_assert_held(&cxl_dpa_rwsem);
if (cxled->dpa_res)
base = cxled->dpa_res->start;
- up_read(&cxl_dpa_rwsem);
return base;
}
@@ -575,17 +564,11 @@ static void cxld_set_type(struct cxl_decoder *cxld, u32 *ctrl)
CXL_HDM_DECODER0_CTRL_HOSTONLY);
}
-static int cxlsd_set_targets(struct cxl_switch_decoder *cxlsd, u64 *tgt)
+static void cxlsd_set_targets(struct cxl_switch_decoder *cxlsd, u64 *tgt)
{
struct cxl_dport **t = &cxlsd->target[0];
int ways = cxlsd->cxld.interleave_ways;
- if (dev_WARN_ONCE(&cxlsd->cxld.dev,
- ways > 8 || ways > cxlsd->nr_targets,
- "ways: %d overflows targets: %d\n", ways,
- cxlsd->nr_targets))
- return -ENXIO;
-
*tgt = FIELD_PREP(GENMASK(7, 0), t[0]->port_id);
if (ways > 1)
*tgt |= FIELD_PREP(GENMASK(15, 8), t[1]->port_id);
@@ -601,8 +584,6 @@ static int cxlsd_set_targets(struct cxl_switch_decoder *cxlsd, u64 *tgt)
*tgt |= FIELD_PREP(GENMASK_ULL(55, 48), t[6]->port_id);
if (ways > 7)
*tgt |= FIELD_PREP(GENMASK_ULL(63, 56), t[7]->port_id);
-
- return 0;
}
/*
@@ -643,13 +624,33 @@ static int cxl_decoder_commit(struct cxl_decoder *cxld)
if (cxld->flags & CXL_DECODER_F_ENABLE)
return 0;
- if (port->commit_end + 1 != id) {
+ if (cxl_num_decoders_committed(port) != id) {
dev_dbg(&port->dev,
"%s: out of order commit, expected decoder%d.%d\n",
- dev_name(&cxld->dev), port->id, port->commit_end + 1);
+ dev_name(&cxld->dev), port->id,
+ cxl_num_decoders_committed(port));
return -EBUSY;
}
+ /*
+ * For endpoint decoders hosted on CXL memory devices that
+ * support the sanitize operation, make sure sanitize is not in-flight.
+ */
+ if (is_endpoint_decoder(&cxld->dev)) {
+ struct cxl_endpoint_decoder *cxled =
+ to_cxl_endpoint_decoder(&cxld->dev);
+ struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
+ struct cxl_memdev_state *mds =
+ to_cxl_memdev_state(cxlmd->cxlds);
+
+ if (mds && mds->security.sanitize_active) {
+ dev_dbg(&cxlmd->dev,
+ "attempted to commit %s during sanitize\n",
+ dev_name(&cxld->dev));
+ return -EBUSY;
+ }
+ }
+
down_read(&cxl_dpa_rwsem);
/* common decoder settings */
ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(cxld->id));
@@ -670,13 +671,7 @@ static int cxl_decoder_commit(struct cxl_decoder *cxld)
void __iomem *tl_lo = hdm + CXL_HDM_DECODER0_TL_LOW(id);
u64 targets;
- rc = cxlsd_set_targets(cxlsd, &targets);
- if (rc) {
- dev_dbg(&port->dev, "%s: target configuration error\n",
- dev_name(&cxld->dev));
- goto err;
- }
-
+ cxlsd_set_targets(cxlsd, &targets);
writel(upper_32_bits(targets), tl_hi);
writel(lower_32_bits(targets), tl_lo);
} else {
@@ -694,7 +689,6 @@ static int cxl_decoder_commit(struct cxl_decoder *cxld)
port->commit_end++;
rc = cxld_await_commit(hdm, cxld->id);
-err:
if (rc) {
dev_dbg(&port->dev, "%s: error %d committing decoder\n",
dev_name(&cxld->dev), rc);
@@ -844,7 +838,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
cxld->target_type = CXL_DECODER_HOSTONLYMEM;
else
cxld->target_type = CXL_DECODER_DEVMEM;
- if (cxld->id != port->commit_end + 1) {
+
+ guard(rwsem_write)(&cxl_region_rwsem);
+ if (cxld->id != cxl_num_decoders_committed(port)) {
dev_warn(&port->dev,
"decoder%d.%d: Committed out of order\n",
port->id, cxld->id);
diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index 4df4f614f490..36270dcfb42e 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -1125,20 +1125,7 @@ int cxl_dev_state_identify(struct cxl_memdev_state *mds)
}
EXPORT_SYMBOL_NS_GPL(cxl_dev_state_identify, CXL);
-/**
- * cxl_mem_sanitize() - Send a sanitization command to the device.
- * @mds: The device data for the operation
- * @cmd: The specific sanitization command opcode
- *
- * Return: 0 if the command was executed successfully, regardless of
- * whether or not the actual security operation is done in the background,
- * such as for the Sanitize case.
- * Error return values can be the result of the mailbox command, -EINVAL
- * when security requirements are not met or invalid contexts.
- *
- * See CXL 3.0 @8.2.9.8.5.1 Sanitize and @8.2.9.8.5.2 Secure Erase.
- */
-int cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd)
+static int __cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd)
{
int rc;
u32 sec_out = 0;
@@ -1183,7 +1170,45 @@ int cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_mem_sanitize, CXL);
+
+
+/**
+ * cxl_mem_sanitize() - Send a sanitization command to the device.
+ * @cxlmd: The device for the operation
+ * @cmd: The specific sanitization command opcode
+ *
+ * Return: 0 if the command was executed successfully, regardless of
+ * whether or not the actual security operation is done in the background,
+ * such as for the Sanitize case.
+ * Error return values can be the result of the mailbox command, -EINVAL
+ * when security requirements are not met or invalid contexts, or -EBUSY
+ * if the sanitize operation is already in flight.
+ *
+ * See CXL 3.0 @8.2.9.8.5.1 Sanitize and @8.2.9.8.5.2 Secure Erase.
+ */
+int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd)
+{
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
+ struct cxl_port *endpoint;
+ int rc;
+
+ /* synchronize with cxl_mem_probe() and decoder write operations */
+ device_lock(&cxlmd->dev);
+ endpoint = cxlmd->endpoint;
+ down_read(&cxl_region_rwsem);
+ /*
+ * Require an endpoint to be safe otherwise the driver can not
+ * be sure that the device is unmapped.
+ */
+ if (endpoint && cxl_num_decoders_committed(endpoint) == 0)
+ rc = __cxl_mem_sanitize(mds, cmd);
+ else
+ rc = -EBUSY;
+ up_read(&cxl_region_rwsem);
+ device_unlock(&cxlmd->dev);
+
+ return rc;
+}
static int add_dpa_res(struct device *dev, struct resource *parent,
struct resource *res, resource_size_t start,
@@ -1224,8 +1249,7 @@ int cxl_mem_create_range_info(struct cxl_memdev_state *mds)
return 0;
}
- cxlds->dpa_res =
- (struct resource)DEFINE_RES_MEM(0, mds->total_bytes);
+ cxlds->dpa_res = DEFINE_RES_MEM(0, mds->total_bytes);
if (mds->partition_align_bytes == 0) {
rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0,
@@ -1377,6 +1401,8 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
mutex_init(&mds->mbox_mutex);
mutex_init(&mds->event.log_lock);
mds->cxlds.dev = dev;
+ mds->cxlds.reg_map.host = dev;
+ mds->cxlds.reg_map.resource = CXL_RESOURCE_NONE;
mds->cxlds.type = CXL_DEVTYPE_CLASSMEM;
return mds;
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 14b547c07f54..2f43d368ba07 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -125,13 +125,16 @@ static ssize_t security_state_show(struct device *dev,
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
- u64 reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET);
- u32 pct = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_PCT_MASK, reg);
- u16 cmd = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK, reg);
unsigned long state = mds->security.state;
+ int rc = 0;
- if (cmd == CXL_MBOX_OP_SANITIZE && pct != 100)
- return sysfs_emit(buf, "sanitize\n");
+ /* sync with latest submission state */
+ mutex_lock(&mds->mbox_mutex);
+ if (mds->security.sanitize_active)
+ rc = sysfs_emit(buf, "sanitize\n");
+ mutex_unlock(&mds->mbox_mutex);
+ if (rc)
+ return rc;
if (!(state & CXL_PMEM_SEC_STATE_USER_PASS_SET))
return sysfs_emit(buf, "disabled\n");
@@ -152,24 +155,17 @@ static ssize_t security_sanitize_store(struct device *dev,
const char *buf, size_t len)
{
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
- struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
- struct cxl_port *port = cxlmd->endpoint;
bool sanitize;
ssize_t rc;
if (kstrtobool(buf, &sanitize) || !sanitize)
return -EINVAL;
- if (!port || !is_cxl_endpoint(port))
- return -EINVAL;
-
- /* ensure no regions are mapped to this memdev */
- if (port->commit_end != -1)
- return -EBUSY;
-
- rc = cxl_mem_sanitize(mds, CXL_MBOX_OP_SANITIZE);
+ rc = cxl_mem_sanitize(cxlmd, CXL_MBOX_OP_SANITIZE);
+ if (rc)
+ return rc;
- return rc ? rc : len;
+ return len;
}
static struct device_attribute dev_attr_security_sanitize =
__ATTR(sanitize, 0200, NULL, security_sanitize_store);
@@ -179,24 +175,17 @@ static ssize_t security_erase_store(struct device *dev,
const char *buf, size_t len)
{
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
- struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
- struct cxl_port *port = cxlmd->endpoint;
ssize_t rc;
bool erase;
if (kstrtobool(buf, &erase) || !erase)
return -EINVAL;
- if (!port || !is_cxl_endpoint(port))
- return -EINVAL;
-
- /* ensure no regions are mapped to this memdev */
- if (port->commit_end != -1)
- return -EBUSY;
-
- rc = cxl_mem_sanitize(mds, CXL_MBOX_OP_SECURE_ERASE);
+ rc = cxl_mem_sanitize(cxlmd, CXL_MBOX_OP_SECURE_ERASE);
+ if (rc)
+ return rc;
- return rc ? rc : len;
+ return len;
}
static struct device_attribute dev_attr_security_erase =
__ATTR(erase, 0200, NULL, security_erase_store);
@@ -238,11 +227,17 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
if (!port || !is_cxl_endpoint(port))
return -EINVAL;
- rc = down_read_interruptible(&cxl_dpa_rwsem);
+ rc = down_read_interruptible(&cxl_region_rwsem);
if (rc)
return rc;
- if (port->commit_end == -1) {
+ rc = down_read_interruptible(&cxl_dpa_rwsem);
+ if (rc) {
+ up_read(&cxl_region_rwsem);
+ return rc;
+ }
+
+ if (cxl_num_decoders_committed(port) == 0) {
/* No regions mapped to this memdev */
rc = cxl_get_poison_by_memdev(cxlmd);
} else {
@@ -250,6 +245,7 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
rc = cxl_get_poison_by_endpoint(port);
}
up_read(&cxl_dpa_rwsem);
+ up_read(&cxl_region_rwsem);
return rc;
}
@@ -293,7 +289,7 @@ static struct cxl_region *cxl_dpa_to_region(struct cxl_memdev *cxlmd, u64 dpa)
.dpa = dpa,
};
port = cxlmd->endpoint;
- if (port && is_cxl_endpoint(port) && port->commit_end != -1)
+ if (port && is_cxl_endpoint(port) && cxl_num_decoders_committed(port))
device_for_each_child(&port->dev, &ctx, __cxl_dpa_to_region);
return ctx.cxlr;
@@ -335,10 +331,16 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
if (!IS_ENABLED(CONFIG_DEBUG_FS))
return 0;
- rc = down_read_interruptible(&cxl_dpa_rwsem);
+ rc = down_read_interruptible(&cxl_region_rwsem);
if (rc)
return rc;
+ rc = down_read_interruptible(&cxl_dpa_rwsem);
+ if (rc) {
+ up_read(&cxl_region_rwsem);
+ return rc;
+ }
+
rc = cxl_validate_poison_dpa(cxlmd, dpa);
if (rc)
goto out;
@@ -366,6 +368,7 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
trace_cxl_poison(cxlmd, cxlr, &record, 0, 0, CXL_POISON_TRACE_INJECT);
out:
up_read(&cxl_dpa_rwsem);
+ up_read(&cxl_region_rwsem);
return rc;
}
@@ -383,10 +386,16 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
if (!IS_ENABLED(CONFIG_DEBUG_FS))
return 0;
- rc = down_read_interruptible(&cxl_dpa_rwsem);
+ rc = down_read_interruptible(&cxl_region_rwsem);
if (rc)
return rc;
+ rc = down_read_interruptible(&cxl_dpa_rwsem);
+ if (rc) {
+ up_read(&cxl_region_rwsem);
+ return rc;
+ }
+
rc = cxl_validate_poison_dpa(cxlmd, dpa);
if (rc)
goto out;
@@ -423,6 +432,7 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
trace_cxl_poison(cxlmd, cxlr, &record, 0, 0, CXL_POISON_TRACE_CLEAR);
out:
up_read(&cxl_dpa_rwsem);
+ up_read(&cxl_region_rwsem);
return rc;
}
@@ -556,21 +566,11 @@ void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds,
}
EXPORT_SYMBOL_NS_GPL(clear_exclusive_cxl_commands, CXL);
-static void cxl_memdev_security_shutdown(struct device *dev)
-{
- struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
- struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
-
- if (mds->security.poll)
- cancel_delayed_work_sync(&mds->security.poll_dwork);
-}
-
static void cxl_memdev_shutdown(struct device *dev)
{
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
down_write(&cxl_memdev_rwsem);
- cxl_memdev_security_shutdown(dev);
cxlmd->cxlds = NULL;
up_write(&cxl_memdev_rwsem);
}
@@ -580,8 +580,8 @@ static void cxl_memdev_unregister(void *_cxlmd)
struct cxl_memdev *cxlmd = _cxlmd;
struct device *dev = &cxlmd->dev;
- cxl_memdev_shutdown(dev);
cdev_device_del(&cxlmd->cdev, dev);
+ cxl_memdev_shutdown(dev);
put_device(dev);
}
@@ -961,17 +961,16 @@ static const struct fw_upload_ops cxl_memdev_fw_ops = {
.cleanup = cxl_fw_cleanup,
};
-static void devm_cxl_remove_fw_upload(void *fwl)
+static void cxl_remove_fw_upload(void *fwl)
{
firmware_upload_unregister(fwl);
}
-int cxl_memdev_setup_fw_upload(struct cxl_memdev_state *mds)
+int devm_cxl_setup_fw_upload(struct device *host, struct cxl_memdev_state *mds)
{
struct cxl_dev_state *cxlds = &mds->cxlds;
struct device *dev = &cxlds->cxlmd->dev;
struct fw_upload *fwl;
- int rc;
if (!test_bit(CXL_MEM_COMMAND_ID_GET_FW_INFO, mds->enabled_cmds))
return 0;
@@ -979,19 +978,10 @@ int cxl_memdev_setup_fw_upload(struct cxl_memdev_state *mds)
fwl = firmware_upload_register(THIS_MODULE, dev, dev_name(dev),
&cxl_memdev_fw_ops, mds);
if (IS_ERR(fwl))
- return dev_err_probe(dev, PTR_ERR(fwl),
- "Failed to register firmware loader\n");
-
- rc = devm_add_action_or_reset(cxlds->dev, devm_cxl_remove_fw_upload,
- fwl);
- if (rc)
- dev_err(dev,
- "Failed to add firmware loader remove action: %d\n",
- rc);
-
- return rc;
+ return PTR_ERR(fwl);
+ return devm_add_action_or_reset(host, cxl_remove_fw_upload, fwl);
}
-EXPORT_SYMBOL_NS_GPL(cxl_memdev_setup_fw_upload, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_fw_upload, CXL);
static const struct file_operations cxl_memdev_fops = {
.owner = THIS_MODULE,
@@ -1002,36 +992,8 @@ static const struct file_operations cxl_memdev_fops = {
.llseek = noop_llseek,
};
-static void put_sanitize(void *data)
-{
- struct cxl_memdev_state *mds = data;
-
- sysfs_put(mds->security.sanitize_node);
-}
-
-static int cxl_memdev_security_init(struct cxl_memdev *cxlmd)
-{
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
- struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
- struct device *dev = &cxlmd->dev;
- struct kernfs_node *sec;
-
- sec = sysfs_get_dirent(dev->kobj.sd, "security");
- if (!sec) {
- dev_err(dev, "sysfs_get_dirent 'security' failed\n");
- return -ENODEV;
- }
- mds->security.sanitize_node = sysfs_get_dirent(sec, "state");
- sysfs_put(sec);
- if (!mds->security.sanitize_node) {
- dev_err(dev, "sysfs_get_dirent 'state' failed\n");
- return -ENODEV;
- }
-
- return devm_add_action_or_reset(cxlds->dev, put_sanitize, mds);
- }
-
-struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds)
+struct cxl_memdev *devm_cxl_add_memdev(struct device *host,
+ struct cxl_dev_state *cxlds)
{
struct cxl_memdev *cxlmd;
struct device *dev;
@@ -1059,11 +1021,7 @@ struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds)
if (rc)
goto err;
- rc = cxl_memdev_security_init(cxlmd);
- if (rc)
- goto err;
-
- rc = devm_add_action_or_reset(cxlds->dev, cxl_memdev_unregister, cxlmd);
+ rc = devm_add_action_or_reset(host, cxl_memdev_unregister, cxlmd);
if (rc)
return ERR_PTR(rc);
return cxlmd;
@@ -1079,6 +1037,50 @@ err:
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_memdev, CXL);
+static void sanitize_teardown_notifier(void *data)
+{
+ struct cxl_memdev_state *mds = data;
+ struct kernfs_node *state;
+
+ /*
+ * Prevent new irq triggered invocations of the workqueue and
+ * flush inflight invocations.
+ */
+ mutex_lock(&mds->mbox_mutex);
+ state = mds->security.sanitize_node;
+ mds->security.sanitize_node = NULL;
+ mutex_unlock(&mds->mbox_mutex);
+
+ cancel_delayed_work_sync(&mds->security.poll_dwork);
+ sysfs_put(state);
+}
+
+int devm_cxl_sanitize_setup_notifier(struct device *host,
+ struct cxl_memdev *cxlmd)
+{
+ struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
+ struct kernfs_node *sec;
+
+ if (!test_bit(CXL_SEC_ENABLED_SANITIZE, mds->security.enabled_cmds))
+ return 0;
+
+ /*
+ * Note, the expectation is that @cxlmd would have failed to be
+ * created if these sysfs_get_dirent calls fail.
+ */
+ sec = sysfs_get_dirent(cxlmd->dev.kobj.sd, "security");
+ if (!sec)
+ return -ENOENT;
+ mds->security.sanitize_node = sysfs_get_dirent(sec, "state");
+ sysfs_put(sec);
+ if (!mds->security.sanitize_node)
+ return -ENOENT;
+
+ return devm_add_action_or_reset(host, sanitize_teardown_notifier, mds);
+}
+EXPORT_SYMBOL_NS_GPL(devm_cxl_sanitize_setup_notifier, CXL);
+
__init int cxl_memdev_init(void)
{
dev_t devt;
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index c7a7887ebdcf..37e1652afbc7 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -5,6 +5,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/pci-doe.h>
+#include <linux/aer.h>
#include <cxlpci.h>
#include <cxlmem.h>
#include <cxl.h>
@@ -595,6 +596,16 @@ static int cxl_cdat_read_table(struct device *dev,
return 0;
}
+static unsigned char cdat_checksum(void *buf, size_t size)
+{
+ unsigned char sum, *data = buf;
+ size_t i;
+
+ for (sum = 0, i = 0; i < size; i++)
+ sum += data[i];
+ return sum;
+}
+
/**
* read_cdat_data - Read the CDAT data on this port
* @port: Port to read data from
@@ -603,18 +614,30 @@ static int cxl_cdat_read_table(struct device *dev,
*/
void read_cdat_data(struct cxl_port *port)
{
- struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
- struct device *host = cxlmd->dev.parent;
+ struct device *uport = port->uport_dev;
struct device *dev = &port->dev;
struct pci_doe_mb *cdat_doe;
+ struct pci_dev *pdev = NULL;
+ struct cxl_memdev *cxlmd;
size_t cdat_length;
- void *cdat_table;
+ void *cdat_table, *cdat_buf;
int rc;
- if (!dev_is_pci(host))
+ if (is_cxl_memdev(uport)) {
+ struct device *host;
+
+ cxlmd = to_cxl_memdev(uport);
+ host = cxlmd->dev.parent;
+ if (dev_is_pci(host))
+ pdev = to_pci_dev(host);
+ } else if (dev_is_pci(uport)) {
+ pdev = to_pci_dev(uport);
+ }
+
+ if (!pdev)
return;
- cdat_doe = pci_find_doe_mailbox(to_pci_dev(host),
- PCI_DVSEC_VENDOR_ID_CXL,
+
+ cdat_doe = pci_find_doe_mailbox(pdev, PCI_DVSEC_VENDOR_ID_CXL,
CXL_DOE_PROTOCOL_TABLE_ACCESS);
if (!cdat_doe) {
dev_dbg(dev, "No CDAT mailbox\n");
@@ -628,50 +651,59 @@ void read_cdat_data(struct cxl_port *port)
return;
}
- cdat_table = devm_kzalloc(dev, cdat_length + sizeof(__le32),
- GFP_KERNEL);
- if (!cdat_table)
+ cdat_buf = devm_kzalloc(dev, cdat_length + sizeof(__le32), GFP_KERNEL);
+ if (!cdat_buf)
return;
- rc = cxl_cdat_read_table(dev, cdat_doe, cdat_table, &cdat_length);
- if (rc) {
- /* Don't leave table data allocated on error */
- devm_kfree(dev, cdat_table);
- dev_err(dev, "CDAT data read error\n");
- return;
- }
+ rc = cxl_cdat_read_table(dev, cdat_doe, cdat_buf, &cdat_length);
+ if (rc)
+ goto err;
+
+ cdat_table = cdat_buf + sizeof(__le32);
+ if (cdat_checksum(cdat_table, cdat_length))
+ goto err;
- port->cdat.table = cdat_table + sizeof(__le32);
+ port->cdat.table = cdat_table;
port->cdat.length = cdat_length;
+ return;
+
+err:
+ /* Don't leave table data allocated on error */
+ devm_kfree(dev, cdat_buf);
+ dev_err(dev, "Failed to read/validate CDAT.\n");
}
EXPORT_SYMBOL_NS_GPL(read_cdat_data, CXL);
-void cxl_cor_error_detected(struct pci_dev *pdev)
+static void __cxl_handle_cor_ras(struct cxl_dev_state *cxlds,
+ void __iomem *ras_base)
{
- struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
void __iomem *addr;
u32 status;
- if (!cxlds->regs.ras)
+ if (!ras_base)
return;
- addr = cxlds->regs.ras + CXL_RAS_CORRECTABLE_STATUS_OFFSET;
+ addr = ras_base + CXL_RAS_CORRECTABLE_STATUS_OFFSET;
status = readl(addr);
if (status & CXL_RAS_CORRECTABLE_STATUS_MASK) {
writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
trace_cxl_aer_correctable_error(cxlds->cxlmd, status);
}
}
-EXPORT_SYMBOL_NS_GPL(cxl_cor_error_detected, CXL);
+
+static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
+{
+ return __cxl_handle_cor_ras(cxlds, cxlds->regs.ras);
+}
/* CXL spec rev3.0 8.2.4.16.1 */
-static void header_log_copy(struct cxl_dev_state *cxlds, u32 *log)
+static void header_log_copy(void __iomem *ras_base, u32 *log)
{
void __iomem *addr;
u32 *log_addr;
int i, log_u32_size = CXL_HEADERLOG_SIZE / sizeof(u32);
- addr = cxlds->regs.ras + CXL_RAS_HEADER_LOG_OFFSET;
+ addr = ras_base + CXL_RAS_HEADER_LOG_OFFSET;
log_addr = log;
for (i = 0; i < log_u32_size; i++) {
@@ -685,17 +717,18 @@ static void header_log_copy(struct cxl_dev_state *cxlds, u32 *log)
* Log the state of the RAS status registers and prepare them to log the
* next error status. Return 1 if reset needed.
*/
-static bool cxl_report_and_clear(struct cxl_dev_state *cxlds)
+static bool __cxl_handle_ras(struct cxl_dev_state *cxlds,
+ void __iomem *ras_base)
{
u32 hl[CXL_HEADERLOG_SIZE_U32];
void __iomem *addr;
u32 status;
u32 fe;
- if (!cxlds->regs.ras)
+ if (!ras_base)
return false;
- addr = cxlds->regs.ras + CXL_RAS_UNCORRECTABLE_STATUS_OFFSET;
+ addr = ras_base + CXL_RAS_UNCORRECTABLE_STATUS_OFFSET;
status = readl(addr);
if (!(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK))
return false;
@@ -703,7 +736,7 @@ static bool cxl_report_and_clear(struct cxl_dev_state *cxlds)
/* If multiple errors, log header points to first error from ctrl reg */
if (hweight32(status) > 1) {
void __iomem *rcc_addr =
- cxlds->regs.ras + CXL_RAS_CAP_CONTROL_OFFSET;
+ ras_base + CXL_RAS_CAP_CONTROL_OFFSET;
fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK,
readl(rcc_addr)));
@@ -711,13 +744,201 @@ static bool cxl_report_and_clear(struct cxl_dev_state *cxlds)
fe = status;
}
- header_log_copy(cxlds, hl);
+ header_log_copy(ras_base, hl);
trace_cxl_aer_uncorrectable_error(cxlds->cxlmd, status, fe, hl);
writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
return true;
}
+static bool cxl_handle_endpoint_ras(struct cxl_dev_state *cxlds)
+{
+ return __cxl_handle_ras(cxlds, cxlds->regs.ras);
+}
+
+#ifdef CONFIG_PCIEAER_CXL
+
+static void cxl_dport_map_rch_aer(struct cxl_dport *dport)
+{
+ struct cxl_rcrb_info *ri = &dport->rcrb;
+ void __iomem *dport_aer = NULL;
+ resource_size_t aer_phys;
+ struct device *host;
+
+ if (dport->rch && ri->aer_cap) {
+ host = dport->reg_map.host;
+ aer_phys = ri->aer_cap + ri->base;
+ dport_aer = devm_cxl_iomap_block(host, aer_phys,
+ sizeof(struct aer_capability_regs));
+ }
+
+ dport->regs.dport_aer = dport_aer;
+}
+
+static void cxl_dport_map_regs(struct cxl_dport *dport)
+{
+ struct cxl_register_map *map = &dport->reg_map;
+ struct device *dev = dport->dport_dev;
+
+ if (!map->component_map.ras.valid)
+ dev_dbg(dev, "RAS registers not found\n");
+ else if (cxl_map_component_regs(map, &dport->regs.component,
+ BIT(CXL_CM_CAP_CAP_ID_RAS)))
+ dev_dbg(dev, "Failed to map RAS capability.\n");
+
+ if (dport->rch)
+ cxl_dport_map_rch_aer(dport);
+}
+
+static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
+{
+ void __iomem *aer_base = dport->regs.dport_aer;
+ struct pci_host_bridge *bridge;
+ u32 aer_cmd_mask, aer_cmd;
+
+ if (!aer_base)
+ return;
+
+ bridge = to_pci_host_bridge(dport->dport_dev);
+
+ /*
+ * Disable RCH root port command interrupts.
+ * CXL 3.0 12.2.1.1 - RCH Downstream Port-detected Errors
+ *
+ * This sequence may not be necessary. CXL spec states disabling
+ * the root cmd register's interrupts is required. But, PCI spec
+ * shows these are disabled by default on reset.
+ */
+ if (bridge->native_aer) {
+ aer_cmd_mask = (PCI_ERR_ROOT_CMD_COR_EN |
+ PCI_ERR_ROOT_CMD_NONFATAL_EN |
+ PCI_ERR_ROOT_CMD_FATAL_EN);
+ aer_cmd = readl(aer_base + PCI_ERR_ROOT_COMMAND);
+ aer_cmd &= ~aer_cmd_mask;
+ writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
+ }
+}
+
+void cxl_setup_parent_dport(struct device *host, struct cxl_dport *dport)
+{
+ struct device *dport_dev = dport->dport_dev;
+ struct pci_host_bridge *host_bridge;
+
+ host_bridge = to_pci_host_bridge(dport_dev);
+ if (host_bridge->native_aer)
+ dport->rcrb.aer_cap = cxl_rcrb_to_aer(dport_dev, dport->rcrb.base);
+
+ dport->reg_map.host = host;
+ cxl_dport_map_regs(dport);
+
+ if (dport->rch)
+ cxl_disable_rch_root_ints(dport);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_setup_parent_dport, CXL);
+
+static void cxl_handle_rdport_cor_ras(struct cxl_dev_state *cxlds,
+ struct cxl_dport *dport)
+{
+ return __cxl_handle_cor_ras(cxlds, dport->regs.ras);
+}
+
+static bool cxl_handle_rdport_ras(struct cxl_dev_state *cxlds,
+ struct cxl_dport *dport)
+{
+ return __cxl_handle_ras(cxlds, dport->regs.ras);
+}
+
+/*
+ * Copy the AER capability registers using 32 bit read accesses.
+ * This is necessary because RCRB AER capability is MMIO mapped. Clear the
+ * status after copying.
+ *
+ * @aer_base: base address of AER capability block in RCRB
+ * @aer_regs: destination for copying AER capability
+ */
+static bool cxl_rch_get_aer_info(void __iomem *aer_base,
+ struct aer_capability_regs *aer_regs)
+{
+ int read_cnt = sizeof(struct aer_capability_regs) / sizeof(u32);
+ u32 *aer_regs_buf = (u32 *)aer_regs;
+ int n;
+
+ if (!aer_base)
+ return false;
+
+ /* Use readl() to guarantee 32-bit accesses */
+ for (n = 0; n < read_cnt; n++)
+ aer_regs_buf[n] = readl(aer_base + n * sizeof(u32));
+
+ writel(aer_regs->uncor_status, aer_base + PCI_ERR_UNCOR_STATUS);
+ writel(aer_regs->cor_status, aer_base + PCI_ERR_COR_STATUS);
+
+ return true;
+}
+
+/* Get AER severity. Return false if there is no error. */
+static bool cxl_rch_get_aer_severity(struct aer_capability_regs *aer_regs,
+ int *severity)
+{
+ if (aer_regs->uncor_status & ~aer_regs->uncor_mask) {
+ if (aer_regs->uncor_status & PCI_ERR_ROOT_FATAL_RCV)
+ *severity = AER_FATAL;
+ else
+ *severity = AER_NONFATAL;
+ return true;
+ }
+
+ if (aer_regs->cor_status & ~aer_regs->cor_mask) {
+ *severity = AER_CORRECTABLE;
+ return true;
+ }
+
+ return false;
+}
+
+static void cxl_handle_rdport_errors(struct cxl_dev_state *cxlds)
+{
+ struct pci_dev *pdev = to_pci_dev(cxlds->dev);
+ struct aer_capability_regs aer_regs;
+ struct cxl_dport *dport;
+ struct cxl_port *port;
+ int severity;
+
+ port = cxl_pci_find_port(pdev, &dport);
+ if (!port)
+ return;
+
+ put_device(&port->dev);
+
+ if (!cxl_rch_get_aer_info(dport->regs.dport_aer, &aer_regs))
+ return;
+
+ if (!cxl_rch_get_aer_severity(&aer_regs, &severity))
+ return;
+
+ pci_print_aer(pdev, severity, &aer_regs);
+
+ if (severity == AER_CORRECTABLE)
+ cxl_handle_rdport_cor_ras(cxlds, dport);
+ else
+ cxl_handle_rdport_ras(cxlds, dport);
+}
+
+#else
+static void cxl_handle_rdport_errors(struct cxl_dev_state *cxlds) { }
+#endif
+
+void cxl_cor_error_detected(struct pci_dev *pdev)
+{
+ struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
+
+ if (cxlds->rcd)
+ cxl_handle_rdport_errors(cxlds);
+
+ cxl_handle_endpoint_cor_ras(cxlds);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_cor_error_detected, CXL);
+
pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
@@ -726,13 +947,16 @@ pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
struct device *dev = &cxlmd->dev;
bool ue;
+ if (cxlds->rcd)
+ cxl_handle_rdport_errors(cxlds);
+
/*
* A frozen channel indicates an impending reset which is fatal to
* CXL.mem operation, and will likely crash the system. On the off
* chance the situation is recoverable dump the status of the RAS
* capability registers and bounce the active state of the memdev.
*/
- ue = cxl_report_and_clear(cxlds);
+ ue = cxl_handle_endpoint_ras(cxlds);
switch (state) {
case pci_channel_io_normal:
diff --git a/drivers/cxl/core/pmu.c b/drivers/cxl/core/pmu.c
index 7684c843e5a5..5d8e06b0ba6e 100644
--- a/drivers/cxl/core/pmu.c
+++ b/drivers/cxl/core/pmu.c
@@ -23,7 +23,7 @@ const struct device_type cxl_pmu_type = {
static void remove_dev(void *dev)
{
- device_del(dev);
+ device_unregister(dev);
}
int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs,
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index 7ca01a834e18..b7c93bb18f6e 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -28,9 +28,22 @@
* instantiated by the core.
*/
+/*
+ * All changes to the interleave configuration occur with this lock held
+ * for write.
+ */
+DECLARE_RWSEM(cxl_region_rwsem);
+
static DEFINE_IDA(cxl_port_ida);
static DEFINE_XARRAY(cxl_root_buses);
+int cxl_num_decoders_committed(struct cxl_port *port)
+{
+ lockdep_assert_held(&cxl_region_rwsem);
+
+ return port->commit_end + 1;
+}
+
static ssize_t devtype_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -213,9 +226,9 @@ static ssize_t dpa_resource_show(struct device *dev, struct device_attribute *at
char *buf)
{
struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev);
- u64 base = cxl_dpa_resource_start(cxled);
- return sysfs_emit(buf, "%#llx\n", base);
+ guard(rwsem_read)(&cxl_dpa_rwsem);
+ return sysfs_emit(buf, "%#llx\n", (u64)cxl_dpa_resource_start(cxled));
}
static DEVICE_ATTR_RO(dpa_resource);
@@ -278,6 +291,15 @@ static ssize_t interleave_ways_show(struct device *dev,
static DEVICE_ATTR_RO(interleave_ways);
+static ssize_t qos_class_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev);
+
+ return sysfs_emit(buf, "%d\n", cxlrd->qos_class);
+}
+static DEVICE_ATTR_RO(qos_class);
+
static struct attribute *cxl_decoder_base_attrs[] = {
&dev_attr_start.attr,
&dev_attr_size.attr,
@@ -297,6 +319,7 @@ static struct attribute *cxl_decoder_root_attrs[] = {
&dev_attr_cap_type2.attr,
&dev_attr_cap_type3.attr,
&dev_attr_target_list.attr,
+ &dev_attr_qos_class.attr,
SET_CXL_REGION_ATTR(create_pmem_region)
SET_CXL_REGION_ATTR(create_ram_region)
SET_CXL_REGION_ATTR(delete_region)
@@ -521,8 +544,33 @@ static void cxl_port_release(struct device *dev)
kfree(port);
}
+static ssize_t decoders_committed_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cxl_port *port = to_cxl_port(dev);
+ int rc;
+
+ down_read(&cxl_region_rwsem);
+ rc = sysfs_emit(buf, "%d\n", cxl_num_decoders_committed(port));
+ up_read(&cxl_region_rwsem);
+
+ return rc;
+}
+
+static DEVICE_ATTR_RO(decoders_committed);
+
+static struct attribute *cxl_port_attrs[] = {
+ &dev_attr_decoders_committed.attr,
+ NULL,
+};
+
+static struct attribute_group cxl_port_attribute_group = {
+ .attrs = cxl_port_attrs,
+};
+
static const struct attribute_group *cxl_port_attribute_groups[] = {
&cxl_base_attribute_group,
+ &cxl_port_attribute_group,
NULL,
};
@@ -619,7 +667,6 @@ static int devm_cxl_link_parent_dport(struct device *host,
static struct lock_class_key cxl_port_key;
static struct cxl_port *cxl_port_alloc(struct device *uport_dev,
- resource_size_t component_reg_phys,
struct cxl_dport *parent_dport)
{
struct cxl_port *port;
@@ -670,7 +717,6 @@ static struct cxl_port *cxl_port_alloc(struct device *uport_dev,
} else
dev->parent = uport_dev;
- port->component_reg_phys = component_reg_phys;
ida_init(&port->decoder_ida);
port->hdm_end = -1;
port->commit_end = -1;
@@ -691,19 +737,21 @@ err:
return ERR_PTR(rc);
}
-static int cxl_setup_comp_regs(struct device *dev, struct cxl_register_map *map,
+static int cxl_setup_comp_regs(struct device *host, struct cxl_register_map *map,
resource_size_t component_reg_phys)
{
- if (component_reg_phys == CXL_RESOURCE_NONE)
- return 0;
-
*map = (struct cxl_register_map) {
- .dev = dev,
- .reg_type = CXL_REGLOC_RBI_COMPONENT,
+ .host = host,
+ .reg_type = CXL_REGLOC_RBI_EMPTY,
.resource = component_reg_phys,
- .max_size = CXL_COMPONENT_REG_BLOCK_SIZE,
};
+ if (component_reg_phys == CXL_RESOURCE_NONE)
+ return 0;
+
+ map->reg_type = CXL_REGLOC_RBI_COMPONENT;
+ map->max_size = CXL_COMPONENT_REG_BLOCK_SIZE;
+
return cxl_setup_regs(map);
}
@@ -712,17 +760,27 @@ static int cxl_port_setup_regs(struct cxl_port *port,
{
if (dev_is_platform(port->uport_dev))
return 0;
- return cxl_setup_comp_regs(&port->dev, &port->comp_map,
+ return cxl_setup_comp_regs(&port->dev, &port->reg_map,
component_reg_phys);
}
-static int cxl_dport_setup_regs(struct cxl_dport *dport,
+static int cxl_dport_setup_regs(struct device *host, struct cxl_dport *dport,
resource_size_t component_reg_phys)
{
+ int rc;
+
if (dev_is_platform(dport->dport_dev))
return 0;
- return cxl_setup_comp_regs(dport->dport_dev, &dport->comp_map,
- component_reg_phys);
+
+ /*
+ * use @dport->dport_dev for the context for error messages during
+ * register probing, and fixup @host after the fact, since @host may be
+ * NULL.
+ */
+ rc = cxl_setup_comp_regs(dport->dport_dev, &dport->reg_map,
+ component_reg_phys);
+ dport->reg_map.host = host;
+ return rc;
}
static struct cxl_port *__devm_cxl_add_port(struct device *host,
@@ -734,21 +792,36 @@ static struct cxl_port *__devm_cxl_add_port(struct device *host,
struct device *dev;
int rc;
- port = cxl_port_alloc(uport_dev, component_reg_phys, parent_dport);
+ port = cxl_port_alloc(uport_dev, parent_dport);
if (IS_ERR(port))
return port;
dev = &port->dev;
- if (is_cxl_memdev(uport_dev))
+ if (is_cxl_memdev(uport_dev)) {
+ struct cxl_memdev *cxlmd = to_cxl_memdev(uport_dev);
+ struct cxl_dev_state *cxlds = cxlmd->cxlds;
+
rc = dev_set_name(dev, "endpoint%d", port->id);
- else if (parent_dport)
+ if (rc)
+ goto err;
+
+ /*
+ * The endpoint driver already enumerated the component and RAS
+ * registers. Reuse that enumeration while prepping them to be
+ * mapped by the cxl_port driver.
+ */
+ port->reg_map = cxlds->reg_map;
+ port->reg_map.host = &port->dev;
+ } else if (parent_dport) {
rc = dev_set_name(dev, "port%d", port->id);
- else
- rc = dev_set_name(dev, "root%d", port->id);
- if (rc)
- goto err;
+ if (rc)
+ goto err;
- rc = cxl_port_setup_regs(port, component_reg_phys);
+ rc = cxl_port_setup_regs(port, component_reg_phys);
+ if (rc)
+ goto err;
+ } else
+ rc = dev_set_name(dev, "root%d", port->id);
if (rc)
goto err;
@@ -983,7 +1056,16 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
if (!dport)
return ERR_PTR(-ENOMEM);
- if (rcrb != CXL_RESOURCE_NONE) {
+ dport->dport_dev = dport_dev;
+ dport->port_id = port_id;
+ dport->port = port;
+
+ if (rcrb == CXL_RESOURCE_NONE) {
+ rc = cxl_dport_setup_regs(&port->dev, dport,
+ component_reg_phys);
+ if (rc)
+ return ERR_PTR(rc);
+ } else {
dport->rcrb.base = rcrb;
component_reg_phys = __rcrb_to_component(dport_dev, &dport->rcrb,
CXL_RCRB_DOWNSTREAM);
@@ -992,6 +1074,14 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
return ERR_PTR(-ENXIO);
}
+ /*
+ * RCH @dport is not ready to map until associated with its
+ * memdev
+ */
+ rc = cxl_dport_setup_regs(NULL, dport, component_reg_phys);
+ if (rc)
+ return ERR_PTR(rc);
+
dport->rch = true;
}
@@ -999,14 +1089,6 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
dev_dbg(dport_dev, "Component Registers found for dport: %pa\n",
&component_reg_phys);
- dport->dport_dev = dport_dev;
- dport->port_id = port_id;
- dport->port = port;
-
- rc = cxl_dport_setup_regs(dport, component_reg_phys);
- if (rc)
- return ERR_PTR(rc);
-
cond_cxl_root_lock(port);
rc = add_dport(port, dport);
cond_cxl_root_unlock(port);
@@ -1217,35 +1299,39 @@ static struct device *grandparent(struct device *dev)
return NULL;
}
+static struct device *endpoint_host(struct cxl_port *endpoint)
+{
+ struct cxl_port *port = to_cxl_port(endpoint->dev.parent);
+
+ if (is_cxl_root(port))
+ return port->uport_dev;
+ return &port->dev;
+}
+
static void delete_endpoint(void *data)
{
struct cxl_memdev *cxlmd = data;
struct cxl_port *endpoint = cxlmd->endpoint;
- struct cxl_port *parent_port;
- struct device *parent;
+ struct device *host = endpoint_host(endpoint);
- parent_port = cxl_mem_find_port(cxlmd, NULL);
- if (!parent_port)
- goto out;
- parent = &parent_port->dev;
-
- device_lock(parent);
- if (parent->driver && !endpoint->dead) {
- devm_release_action(parent, cxl_unlink_parent_dport, endpoint);
- devm_release_action(parent, cxl_unlink_uport, endpoint);
- devm_release_action(parent, unregister_port, endpoint);
+ device_lock(host);
+ if (host->driver && !endpoint->dead) {
+ devm_release_action(host, cxl_unlink_parent_dport, endpoint);
+ devm_release_action(host, cxl_unlink_uport, endpoint);
+ devm_release_action(host, unregister_port, endpoint);
}
cxlmd->endpoint = NULL;
- device_unlock(parent);
- put_device(parent);
-out:
+ device_unlock(host);
put_device(&endpoint->dev);
+ put_device(host);
}
int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint)
{
+ struct device *host = endpoint_host(endpoint);
struct device *dev = &cxlmd->dev;
+ get_device(host);
get_device(&endpoint->dev);
cxlmd->endpoint = endpoint;
cxlmd->depth = endpoint->depth;
@@ -1468,7 +1554,11 @@ retry:
struct cxl_dport *dport;
struct cxl_port *port;
- if (!dport_dev)
+ /*
+ * The terminal "grandparent" in PCI is NULL and @platform_bus
+ * for platform devices
+ */
+ if (!dport_dev || dport_dev == &platform_bus)
return 0;
uport_dev = dport_dev->parent;
@@ -1691,6 +1781,7 @@ struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
}
atomic_set(&cxlrd->region_id, rc);
+ cxlrd->qos_class = CXL_QOS_CLASS_INVALID;
return cxlrd;
}
EXPORT_SYMBOL_NS_GPL(cxl_root_decoder_alloc, CXL);
@@ -2062,3 +2153,4 @@ static void cxl_core_exit(void)
subsys_initcall(cxl_core_init);
module_exit(cxl_core_exit);
MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(CXL);
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 6d63b8798c29..3e817a6f94c6 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -28,12 +28,6 @@
* 3. Decoder targets
*/
-/*
- * All changes to the interleave configuration occur with this lock held
- * for write.
- */
-static DECLARE_RWSEM(cxl_region_rwsem);
-
static struct cxl_region *to_cxl_region(struct device *dev);
static ssize_t uuid_show(struct device *dev, struct device_attribute *attr,
@@ -129,7 +123,7 @@ static int cxl_region_invalidate_memregion(struct cxl_region *cxlr)
{
if (!cpu_cache_has_invalidate_memregion()) {
if (IS_ENABLED(CONFIG_CXL_REGION_INVALIDATION_TEST)) {
- dev_warn_once(
+ dev_info_once(
&cxlr->dev,
"Bypassing cpu_cache_invalidate_memregion() for testing!\n");
return 0;
@@ -294,7 +288,7 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr,
*/
rc = cxl_region_invalidate_memregion(cxlr);
if (rc)
- return rc;
+ goto out;
if (commit) {
rc = cxl_region_decode_commit(cxlr);
@@ -1133,7 +1127,14 @@ static int cxl_port_setup_targets(struct cxl_port *port,
}
if (is_cxl_root(parent_port)) {
- parent_ig = cxlrd->cxlsd.cxld.interleave_granularity;
+ /*
+ * Root decoder IG is always set to value in CFMWS which
+ * may be different than this region's IG. We can use the
+ * region's IG here since interleave_granularity_store()
+ * does not allow interleaved host-bridges with
+ * root IG != region IG.
+ */
+ parent_ig = p->interleave_granularity;
parent_iw = cxlrd->cxlsd.cxld.interleave_ways;
/*
* For purposes of address bit routing, use power-of-2 math for
@@ -1195,6 +1196,14 @@ static int cxl_port_setup_targets(struct cxl_port *port,
return rc;
}
+ if (iw > 8 || iw > cxlsd->nr_targets) {
+ dev_dbg(&cxlr->dev,
+ "%s:%s:%s: ways: %d overflows targets: %d\n",
+ dev_name(port->uport_dev), dev_name(&port->dev),
+ dev_name(&cxld->dev), iw, cxlsd->nr_targets);
+ return -ENXIO;
+ }
+
if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) {
if (cxld->interleave_ways != iw ||
cxld->interleave_granularity != ig ||
@@ -1480,6 +1489,14 @@ static int cxl_region_attach_auto(struct cxl_region *cxlr,
return 0;
}
+static int cmp_interleave_pos(const void *a, const void *b)
+{
+ struct cxl_endpoint_decoder *cxled_a = *(typeof(cxled_a) *)a;
+ struct cxl_endpoint_decoder *cxled_b = *(typeof(cxled_b) *)b;
+
+ return cxled_a->pos - cxled_b->pos;
+}
+
static struct cxl_port *next_port(struct cxl_port *port)
{
if (!port->parent_dport)
@@ -1487,119 +1504,127 @@ static struct cxl_port *next_port(struct cxl_port *port)
return port->parent_dport->port;
}
-static int decoder_match_range(struct device *dev, void *data)
+static int match_switch_decoder_by_range(struct device *dev, void *data)
{
- struct cxl_endpoint_decoder *cxled = data;
struct cxl_switch_decoder *cxlsd;
+ struct range *r1, *r2 = data;
if (!is_switch_decoder(dev))
return 0;
cxlsd = to_cxl_switch_decoder(dev);
- return range_contains(&cxlsd->cxld.hpa_range, &cxled->cxld.hpa_range);
-}
+ r1 = &cxlsd->cxld.hpa_range;
-static void find_positions(const struct cxl_switch_decoder *cxlsd,
- const struct cxl_port *iter_a,
- const struct cxl_port *iter_b, int *a_pos,
- int *b_pos)
-{
- int i;
-
- for (i = 0, *a_pos = -1, *b_pos = -1; i < cxlsd->nr_targets; i++) {
- if (cxlsd->target[i] == iter_a->parent_dport)
- *a_pos = i;
- else if (cxlsd->target[i] == iter_b->parent_dport)
- *b_pos = i;
- if (*a_pos >= 0 && *b_pos >= 0)
- break;
- }
+ if (is_root_decoder(dev))
+ return range_contains(r1, r2);
+ return (r1->start == r2->start && r1->end == r2->end);
}
-static int cmp_decode_pos(const void *a, const void *b)
+static int find_pos_and_ways(struct cxl_port *port, struct range *range,
+ int *pos, int *ways)
{
- struct cxl_endpoint_decoder *cxled_a = *(typeof(cxled_a) *)a;
- struct cxl_endpoint_decoder *cxled_b = *(typeof(cxled_b) *)b;
- struct cxl_memdev *cxlmd_a = cxled_to_memdev(cxled_a);
- struct cxl_memdev *cxlmd_b = cxled_to_memdev(cxled_b);
- struct cxl_port *port_a = cxled_to_port(cxled_a);
- struct cxl_port *port_b = cxled_to_port(cxled_b);
- struct cxl_port *iter_a, *iter_b, *port = NULL;
struct cxl_switch_decoder *cxlsd;
+ struct cxl_port *parent;
struct device *dev;
- int a_pos, b_pos;
- unsigned int seq;
-
- /* Exit early if any prior sorting failed */
- if (cxled_a->pos < 0 || cxled_b->pos < 0)
- return 0;
+ int rc = -ENXIO;
- /*
- * Walk up the hierarchy to find a shared port, find the decoder that
- * maps the range, compare the relative position of those dport
- * mappings.
- */
- for (iter_a = port_a; iter_a; iter_a = next_port(iter_a)) {
- struct cxl_port *next_a, *next_b;
+ parent = next_port(port);
+ if (!parent)
+ return rc;
- next_a = next_port(iter_a);
- if (!next_a)
- break;
+ dev = device_find_child(&parent->dev, range,
+ match_switch_decoder_by_range);
+ if (!dev) {
+ dev_err(port->uport_dev,
+ "failed to find decoder mapping %#llx-%#llx\n",
+ range->start, range->end);
+ return rc;
+ }
+ cxlsd = to_cxl_switch_decoder(dev);
+ *ways = cxlsd->cxld.interleave_ways;
- for (iter_b = port_b; iter_b; iter_b = next_port(iter_b)) {
- next_b = next_port(iter_b);
- if (next_a != next_b)
- continue;
- port = next_a;
+ for (int i = 0; i < *ways; i++) {
+ if (cxlsd->target[i] == port->parent_dport) {
+ *pos = i;
+ rc = 0;
break;
}
-
- if (port)
- break;
}
+ put_device(dev);
- if (!port) {
- dev_err(cxlmd_a->dev.parent,
- "failed to find shared port with %s\n",
- dev_name(cxlmd_b->dev.parent));
- goto err;
- }
+ return rc;
+}
- dev = device_find_child(&port->dev, cxled_a, decoder_match_range);
- if (!dev) {
- struct range *range = &cxled_a->cxld.hpa_range;
+/**
+ * cxl_calc_interleave_pos() - calculate an endpoint position in a region
+ * @cxled: endpoint decoder member of given region
+ *
+ * The endpoint position is calculated by traversing the topology from
+ * the endpoint to the root decoder and iteratively applying this
+ * calculation:
+ *
+ * position = position * parent_ways + parent_pos;
+ *
+ * ...where @position is inferred from switch and root decoder target lists.
+ *
+ * Return: position >= 0 on success
+ * -ENXIO on failure
+ */
+static int cxl_calc_interleave_pos(struct cxl_endpoint_decoder *cxled)
+{
+ struct cxl_port *iter, *port = cxled_to_port(cxled);
+ struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
+ struct range *range = &cxled->cxld.hpa_range;
+ int parent_ways = 0, parent_pos = 0, pos = 0;
+ int rc;
- dev_err(port->uport_dev,
- "failed to find decoder that maps %#llx-%#llx\n",
- range->start, range->end);
- goto err;
- }
+ /*
+ * Example: the expected interleave order of the 4-way region shown
+ * below is: mem0, mem2, mem1, mem3
+ *
+ * root_port
+ * / \
+ * host_bridge_0 host_bridge_1
+ * | | | |
+ * mem0 mem1 mem2 mem3
+ *
+ * In the example the calculator will iterate twice. The first iteration
+ * uses the mem position in the host-bridge and the ways of the host-
+ * bridge to generate the first, or local, position. The second
+ * iteration uses the host-bridge position in the root_port and the ways
+ * of the root_port to refine the position.
+ *
+ * A trace of the calculation per endpoint looks like this:
+ * mem0: pos = 0 * 2 + 0 mem2: pos = 0 * 2 + 0
+ * pos = 0 * 2 + 0 pos = 0 * 2 + 1
+ * pos: 0 pos: 1
+ *
+ * mem1: pos = 0 * 2 + 1 mem3: pos = 0 * 2 + 1
+ * pos = 1 * 2 + 0 pos = 1 * 2 + 1
+ * pos: 2 pos = 3
+ *
+ * Note that while this example is simple, the method applies to more
+ * complex topologies, including those with switches.
+ */
- cxlsd = to_cxl_switch_decoder(dev);
- do {
- seq = read_seqbegin(&cxlsd->target_lock);
- find_positions(cxlsd, iter_a, iter_b, &a_pos, &b_pos);
- } while (read_seqretry(&cxlsd->target_lock, seq));
+ /* Iterate from endpoint to root_port refining the position */
+ for (iter = port; iter; iter = next_port(iter)) {
+ if (is_cxl_root(iter))
+ break;
- put_device(dev);
+ rc = find_pos_and_ways(iter, range, &parent_pos, &parent_ways);
+ if (rc)
+ return rc;
- if (a_pos < 0 || b_pos < 0) {
- dev_err(port->uport_dev,
- "failed to find shared decoder for %s and %s\n",
- dev_name(cxlmd_a->dev.parent),
- dev_name(cxlmd_b->dev.parent));
- goto err;
+ pos = pos * parent_ways + parent_pos;
}
- dev_dbg(port->uport_dev, "%s comes %s %s\n",
- dev_name(cxlmd_a->dev.parent),
- a_pos - b_pos < 0 ? "before" : "after",
- dev_name(cxlmd_b->dev.parent));
+ dev_dbg(&cxlmd->dev,
+ "decoder:%s parent:%s port:%s range:%#llx-%#llx pos:%d\n",
+ dev_name(&cxled->cxld.dev), dev_name(cxlmd->dev.parent),
+ dev_name(&port->dev), range->start, range->end, pos);
- return a_pos - b_pos;
-err:
- cxled_a->pos = -1;
- return 0;
+ return pos;
}
static int cxl_region_sort_targets(struct cxl_region *cxlr)
@@ -1607,22 +1632,21 @@ static int cxl_region_sort_targets(struct cxl_region *cxlr)
struct cxl_region_params *p = &cxlr->params;
int i, rc = 0;
- sort(p->targets, p->nr_targets, sizeof(p->targets[0]), cmp_decode_pos,
- NULL);
-
for (i = 0; i < p->nr_targets; i++) {
struct cxl_endpoint_decoder *cxled = p->targets[i];
+ cxled->pos = cxl_calc_interleave_pos(cxled);
/*
- * Record that sorting failed, but still continue to restore
- * cxled->pos with its ->targets[] position so that follow-on
- * code paths can reliably do p->targets[cxled->pos] to
- * self-reference their entry.
+ * Record that sorting failed, but still continue to calc
+ * cxled->pos so that follow-on code paths can reliably
+ * do p->targets[cxled->pos] to self-reference their entry.
*/
if (cxled->pos < 0)
rc = -ENXIO;
- cxled->pos = i;
}
+ /* Keep the cxlr target list in interleave position order */
+ sort(p->targets, p->nr_targets, sizeof(p->targets[0]),
+ cmp_interleave_pos, NULL);
dev_dbg(&cxlr->dev, "region sort %s\n", rc ? "failed" : "successful");
return rc;
@@ -1658,6 +1682,12 @@ static int cxl_region_attach(struct cxl_region *cxlr,
return -ENXIO;
}
+ if (p->nr_targets >= p->interleave_ways) {
+ dev_dbg(&cxlr->dev, "region already has %d endpoints\n",
+ p->nr_targets);
+ return -EINVAL;
+ }
+
ep_port = cxled_to_port(cxled);
root_port = cxlrd_to_port(cxlrd);
dport = cxl_find_dport_by_dev(root_port, ep_port->host_bridge);
@@ -1750,7 +1780,7 @@ static int cxl_region_attach(struct cxl_region *cxlr,
if (p->nr_targets == p->interleave_ways) {
rc = cxl_region_setup_targets(cxlr);
if (rc)
- goto err_decrement;
+ return rc;
p->state = CXL_CONFIG_ACTIVE;
}
@@ -1761,13 +1791,27 @@ static int cxl_region_attach(struct cxl_region *cxlr,
.end = p->res->end,
};
- return 0;
+ if (p->nr_targets != p->interleave_ways)
+ return 0;
-err_decrement:
- p->nr_targets--;
- cxled->pos = -1;
- p->targets[pos] = NULL;
- return rc;
+ /*
+ * Test the auto-discovery position calculator function
+ * against this successfully created user-defined region.
+ * A fail message here means that this interleave config
+ * will fail when presented as CXL_REGION_F_AUTO.
+ */
+ for (int i = 0; i < p->nr_targets; i++) {
+ struct cxl_endpoint_decoder *cxled = p->targets[i];
+ int test_pos;
+
+ test_pos = cxl_calc_interleave_pos(cxled);
+ dev_dbg(&cxled->cxld.dev,
+ "Test cxl_calc_interleave_pos(): %s test_pos:%d cxled->pos:%d\n",
+ (test_pos == cxled->pos) ? "success" : "fail",
+ test_pos, cxled->pos);
+ }
+
+ return 0;
}
static int cxl_region_detach(struct cxl_endpoint_decoder *cxled)
@@ -2423,10 +2467,6 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
struct cxl_poison_context ctx;
int rc = 0;
- rc = down_read_interruptible(&cxl_region_rwsem);
- if (rc)
- return rc;
-
ctx = (struct cxl_poison_context) {
.port = port
};
@@ -2436,7 +2476,6 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
rc = cxl_get_poison_unmapped(to_cxl_memdev(port->uport_dev),
&ctx);
- up_read(&cxl_region_rwsem);
return rc;
}
@@ -2696,7 +2735,7 @@ err:
return rc;
}
-static int match_decoder_by_range(struct device *dev, void *data)
+static int match_root_decoder_by_range(struct device *dev, void *data)
{
struct range *r1, *r2 = data;
struct cxl_root_decoder *cxlrd;
@@ -2827,7 +2866,7 @@ int cxl_add_to_region(struct cxl_port *root, struct cxl_endpoint_decoder *cxled)
int rc;
cxlrd_dev = device_find_child(&root->dev, &cxld->hpa_range,
- match_decoder_by_range);
+ match_root_decoder_by_range);
if (!cxlrd_dev) {
dev_err(cxlmd->dev.parent,
"%s:%s no CXL window for range %#llx:%#llx\n",
diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
index 6281127b3e9d..372786f80955 100644
--- a/drivers/cxl/core/regs.c
+++ b/drivers/cxl/core/regs.c
@@ -204,7 +204,7 @@ int cxl_map_component_regs(const struct cxl_register_map *map,
struct cxl_component_regs *regs,
unsigned long map_mask)
{
- struct device *dev = map->dev;
+ struct device *host = map->host;
struct mapinfo {
const struct cxl_reg_map *rmap;
void __iomem **addr;
@@ -216,16 +216,16 @@ int cxl_map_component_regs(const struct cxl_register_map *map,
for (i = 0; i < ARRAY_SIZE(mapinfo); i++) {
struct mapinfo *mi = &mapinfo[i];
- resource_size_t phys_addr;
+ resource_size_t addr;
resource_size_t length;
if (!mi->rmap->valid)
continue;
if (!test_bit(mi->rmap->id, &map_mask))
continue;
- phys_addr = map->resource + mi->rmap->offset;
+ addr = map->resource + mi->rmap->offset;
length = mi->rmap->size;
- *(mi->addr) = devm_cxl_iomap_block(dev, phys_addr, length);
+ *(mi->addr) = devm_cxl_iomap_block(host, addr, length);
if (!*(mi->addr))
return -ENOMEM;
}
@@ -237,7 +237,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_map_component_regs, CXL);
int cxl_map_device_regs(const struct cxl_register_map *map,
struct cxl_device_regs *regs)
{
- struct device *dev = map->dev;
+ struct device *host = map->host;
resource_size_t phys_addr = map->resource;
struct mapinfo {
const struct cxl_reg_map *rmap;
@@ -259,7 +259,7 @@ int cxl_map_device_regs(const struct cxl_register_map *map,
addr = phys_addr + mi->rmap->offset;
length = mi->rmap->size;
- *(mi->addr) = devm_cxl_iomap_block(dev, addr, length);
+ *(mi->addr) = devm_cxl_iomap_block(host, addr, length);
if (!*(mi->addr))
return -ENOMEM;
}
@@ -309,7 +309,7 @@ int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type,
int regloc, i;
*map = (struct cxl_register_map) {
- .dev = &pdev->dev,
+ .host = &pdev->dev,
.resource = CXL_RESOURCE_NONE,
};
@@ -386,10 +386,9 @@ int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type)
}
EXPORT_SYMBOL_NS_GPL(cxl_count_regblock, CXL);
-int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs,
- struct cxl_register_map *map)
+int cxl_map_pmu_regs(struct cxl_register_map *map, struct cxl_pmu_regs *regs)
{
- struct device *dev = &pdev->dev;
+ struct device *dev = map->host;
resource_size_t phys_addr;
phys_addr = map->resource;
@@ -403,15 +402,15 @@ EXPORT_SYMBOL_NS_GPL(cxl_map_pmu_regs, CXL);
static int cxl_map_regblock(struct cxl_register_map *map)
{
- struct device *dev = map->dev;
+ struct device *host = map->host;
map->base = ioremap(map->resource, map->max_size);
if (!map->base) {
- dev_err(dev, "failed to map registers\n");
+ dev_err(host, "failed to map registers\n");
return -ENOMEM;
}
- dev_dbg(dev, "Mapped CXL Memory Device resource %pa\n", &map->resource);
+ dev_dbg(host, "Mapped CXL Memory Device resource %pa\n", &map->resource);
return 0;
}
@@ -425,28 +424,28 @@ static int cxl_probe_regs(struct cxl_register_map *map)
{
struct cxl_component_reg_map *comp_map;
struct cxl_device_reg_map *dev_map;
- struct device *dev = map->dev;
+ struct device *host = map->host;
void __iomem *base = map->base;
switch (map->reg_type) {
case CXL_REGLOC_RBI_COMPONENT:
comp_map = &map->component_map;
- cxl_probe_component_regs(dev, base, comp_map);
- dev_dbg(dev, "Set up component registers\n");
+ cxl_probe_component_regs(host, base, comp_map);
+ dev_dbg(host, "Set up component registers\n");
break;
case CXL_REGLOC_RBI_MEMDEV:
dev_map = &map->device_map;
- cxl_probe_device_regs(dev, base, dev_map);
+ cxl_probe_device_regs(host, base, dev_map);
if (!dev_map->status.valid || !dev_map->mbox.valid ||
!dev_map->memdev.valid) {
- dev_err(dev, "registers not found: %s%s%s\n",
+ dev_err(host, "registers not found: %s%s%s\n",
!dev_map->status.valid ? "status " : "",
!dev_map->mbox.valid ? "mbox " : "",
!dev_map->memdev.valid ? "memdev " : "");
return -ENXIO;
}
- dev_dbg(dev, "Probing device registers...\n");
+ dev_dbg(host, "Probing device registers...\n");
break;
default:
break;
@@ -470,6 +469,42 @@ int cxl_setup_regs(struct cxl_register_map *map)
}
EXPORT_SYMBOL_NS_GPL(cxl_setup_regs, CXL);
+u16 cxl_rcrb_to_aer(struct device *dev, resource_size_t rcrb)
+{
+ void __iomem *addr;
+ u16 offset = 0;
+ u32 cap_hdr;
+
+ if (WARN_ON_ONCE(rcrb == CXL_RESOURCE_NONE))
+ return 0;
+
+ if (!request_mem_region(rcrb, SZ_4K, dev_name(dev)))
+ return 0;
+
+ addr = ioremap(rcrb, SZ_4K);
+ if (!addr)
+ goto out;
+
+ cap_hdr = readl(addr + offset);
+ while (PCI_EXT_CAP_ID(cap_hdr) != PCI_EXT_CAP_ID_ERR) {
+ offset = PCI_EXT_CAP_NEXT(cap_hdr);
+
+ /* Offset 0 terminates capability list. */
+ if (!offset)
+ break;
+ cap_hdr = readl(addr + offset);
+ }
+
+ if (offset)
+ dev_dbg(dev, "found AER extended capability (0x%x)\n", offset);
+
+ iounmap(addr);
+out:
+ release_mem_region(rcrb, SZ_4K);
+
+ return offset;
+}
+
resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri,
enum cxl_rcrb which)
{
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 76d92561af29..687043ece101 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -221,6 +221,14 @@ struct cxl_regs {
struct_group_tagged(cxl_pmu_regs, pmu_regs,
void __iomem *pmu;
);
+
+ /*
+ * RCH downstream port specific RAS register
+ * @aer: CXL 3.0 8.2.1.1 RCH Downstream Port RCRB
+ */
+ struct_group_tagged(cxl_rch_regs, rch_regs,
+ void __iomem *dport_aer;
+ );
};
struct cxl_reg_map {
@@ -247,7 +255,7 @@ struct cxl_pmu_reg_map {
/**
* struct cxl_register_map - DVSEC harvested register block mapping parameters
- * @dev: device for devm operations and logging
+ * @host: device for devm operations and logging
* @base: virtual base of the register-block-BAR + @block_offset
* @resource: physical resource base of the register block
* @max_size: maximum mapping size to perform register search
@@ -257,7 +265,7 @@ struct cxl_pmu_reg_map {
* @pmu_map: cxl_reg_maps for CXL Performance Monitoring Units
*/
struct cxl_register_map {
- struct device *dev;
+ struct device *host;
void __iomem *base;
resource_size_t resource;
resource_size_t max_size;
@@ -278,8 +286,7 @@ int cxl_map_component_regs(const struct cxl_register_map *map,
unsigned long map_mask);
int cxl_map_device_regs(const struct cxl_register_map *map,
struct cxl_device_regs *regs);
-int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs,
- struct cxl_register_map *map);
+int cxl_map_pmu_regs(struct cxl_register_map *map, struct cxl_pmu_regs *regs);
enum cxl_regloc_type;
int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type);
@@ -321,6 +328,7 @@ enum cxl_decoder_type {
*/
#define CXL_DECODER_MAX_INTERLEAVE 16
+#define CXL_QOS_CLASS_INVALID -1
/**
* struct cxl_decoder - Common CXL HDM Decoder Attributes
@@ -432,6 +440,7 @@ typedef struct cxl_dport *(*cxl_calc_hb_fn)(struct cxl_root_decoder *cxlrd,
* @calc_hb: which host bridge covers the n'th position by granularity
* @platform_data: platform specific configuration data
* @range_lock: sync region autodiscovery by address range
+ * @qos_class: QoS performance class cookie
* @cxlsd: base cxl switch decoder
*/
struct cxl_root_decoder {
@@ -440,6 +449,7 @@ struct cxl_root_decoder {
cxl_calc_hb_fn calc_hb;
void *platform_data;
struct mutex range_lock;
+ int qos_class;
struct cxl_switch_decoder cxlsd;
};
@@ -572,11 +582,10 @@ struct cxl_dax_region {
* @regions: cxl_region_ref instances, regions mapped by this port
* @parent_dport: dport that points to this port in the parent
* @decoder_ida: allocator for decoder ids
- * @comp_map: component register capability mappings
+ * @reg_map: component and ras register mapping parameters
* @nr_dports: number of entries in @dports
* @hdm_end: track last allocated HDM decoder instance for allocation ordering
* @commit_end: cursor to track highest committed decoder for commit ordering
- * @component_reg_phys: component register capability base address (optional)
* @dead: last ep has been removed, force port re-creation
* @depth: How deep this port is relative to the root. depth 0 is the root.
* @cdat: Cached CDAT data
@@ -592,11 +601,10 @@ struct cxl_port {
struct xarray regions;
struct cxl_dport *parent_dport;
struct ida decoder_ida;
- struct cxl_register_map comp_map;
+ struct cxl_register_map reg_map;
int nr_dports;
int hdm_end;
int commit_end;
- resource_size_t component_reg_phys;
bool dead;
unsigned int depth;
struct cxl_cdat {
@@ -620,19 +628,21 @@ struct cxl_rcrb_info {
/**
* struct cxl_dport - CXL downstream port
* @dport_dev: PCI bridge or firmware device representing the downstream link
- * @comp_map: component register capability mappings
+ * @reg_map: component and ras register mapping parameters
* @port_id: unique hardware identifier for dport in decoder target list
* @rcrb: Data about the Root Complex Register Block layout
* @rch: Indicate whether this dport was enumerated in RCH or VH mode
* @port: reference to cxl_port that contains this downstream port
+ * @regs: Dport parsed register blocks
*/
struct cxl_dport {
struct device *dport_dev;
- struct cxl_register_map comp_map;
+ struct cxl_register_map reg_map;
int port_id;
struct cxl_rcrb_info rcrb;
bool rch;
struct cxl_port *port;
+ struct cxl_regs regs;
};
/**
@@ -679,6 +689,7 @@ static inline bool is_cxl_root(struct cxl_port *port)
return port->uport_dev == port->dev.parent;
}
+int cxl_num_decoders_committed(struct cxl_port *port);
bool is_cxl_port(const struct device *dev);
struct cxl_port *to_cxl_port(const struct device *dev);
struct pci_bus;
@@ -706,6 +717,13 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
struct device *dport_dev, int port_id,
resource_size_t rcrb);
+#ifdef CONFIG_PCIEAER_CXL
+void cxl_setup_parent_dport(struct device *host, struct cxl_dport *dport);
+#else
+static inline void cxl_setup_parent_dport(struct device *host,
+ struct cxl_dport *dport) { }
+#endif
+
struct cxl_decoder *to_cxl_decoder(struct device *dev);
struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev);
struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev);
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 706f8a6d1ef4..a2fcbca253f3 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -84,9 +84,12 @@ static inline bool is_cxl_endpoint(struct cxl_port *port)
return is_cxl_memdev(port->uport_dev);
}
-struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds);
+struct cxl_memdev *devm_cxl_add_memdev(struct device *host,
+ struct cxl_dev_state *cxlds);
+int devm_cxl_sanitize_setup_notifier(struct device *host,
+ struct cxl_memdev *cxlmd);
struct cxl_memdev_state;
-int cxl_memdev_setup_fw_upload(struct cxl_memdev_state *mds);
+int devm_cxl_setup_fw_upload(struct device *host, struct cxl_memdev_state *mds);
int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
resource_size_t base, resource_size_t len,
resource_size_t skipped);
@@ -360,16 +363,16 @@ struct cxl_fw_state {
*
* @state: state of last security operation
* @enabled_cmds: All security commands enabled in the CEL
- * @poll: polling for sanitization is enabled, device has no mbox irq support
* @poll_tmo_secs: polling timeout
+ * @sanitize_active: sanitize completion pending
* @poll_dwork: polling work item
* @sanitize_node: sanitation sysfs file to notify
*/
struct cxl_security_state {
unsigned long state;
DECLARE_BITMAP(enabled_cmds, CXL_SEC_ENABLED_MAX);
- bool poll;
int poll_tmo_secs;
+ bool sanitize_active;
struct delayed_work poll_dwork;
struct kernfs_node *sanitize_node;
};
@@ -397,6 +400,7 @@ enum cxl_devtype {
*
* @dev: The device associated with this CXL state
* @cxlmd: The device representing the CXL.mem capabilities of @dev
+ * @reg_map: component and ras register mapping parameters
* @regs: Parsed register blocks
* @cxl_dvsec: Offset to the PCIe device DVSEC
* @rcd: operating in RCD mode (CXL 3.0 9.11.8 CXL Devices Attached to an RCH)
@@ -404,13 +408,13 @@ enum cxl_devtype {
* @dpa_res: Overall DPA resource tree for the device
* @pmem_res: Active Persistent memory capacity configuration
* @ram_res: Active Volatile memory capacity configuration
- * @component_reg_phys: register base of component registers
* @serial: PCIe Device Serial Number
* @type: Generic Memory Class device or Vendor Specific Memory device
*/
struct cxl_dev_state {
struct device *dev;
struct cxl_memdev *cxlmd;
+ struct cxl_register_map reg_map;
struct cxl_regs regs;
int cxl_dvsec;
bool rcd;
@@ -418,7 +422,6 @@ struct cxl_dev_state {
struct resource dpa_res;
struct resource pmem_res;
struct resource ram_res;
- resource_size_t component_reg_phys;
u64 serial;
enum cxl_devtype type;
};
@@ -883,7 +886,7 @@ static inline void cxl_mem_active_dec(void)
}
#endif
-int cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd);
+int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd);
struct cxl_hdm {
struct cxl_component_regs regs;
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index 317c7548e4e9..e087febf9af0 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -49,7 +49,6 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
struct cxl_dport *parent_dport)
{
struct cxl_port *parent_port = parent_dport->port;
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct cxl_port *endpoint, *iter, *down;
int rc;
@@ -65,8 +64,8 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
ep->next = down;
}
- endpoint = devm_cxl_add_port(host, &cxlmd->dev,
- cxlds->component_reg_phys,
+ /* Note: endpoint port component registers are derived from @cxlds */
+ endpoint = devm_cxl_add_port(host, &cxlmd->dev, CXL_RESOURCE_NONE,
parent_dport);
if (IS_ERR(endpoint))
return PTR_ERR(endpoint);
@@ -158,6 +157,8 @@ static int cxl_mem_probe(struct device *dev)
else
endpoint_parent = &parent_port->dev;
+ cxl_setup_parent_dport(dev, dport);
+
device_lock(endpoint_parent);
if (!endpoint_parent->driver) {
dev_err(dev, "CXL port topology %s not enabled\n",
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index 44a21ab7add5..0155fb66b580 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -85,25 +85,28 @@ static int cxl_pci_mbox_wait_for_doorbell(struct cxl_dev_state *cxlds)
status & CXLMDEV_DEV_FATAL ? " fatal" : "", \
status & CXLMDEV_FW_HALT ? " firmware-halt" : "")
+/*
+ * Threaded irq dev_id's must be globally unique. cxl_dev_id provides a unique
+ * wrapper object for each irq within the same cxlds.
+ */
struct cxl_dev_id {
struct cxl_dev_state *cxlds;
};
static int cxl_request_irq(struct cxl_dev_state *cxlds, int irq,
- irq_handler_t handler, irq_handler_t thread_fn)
+ irq_handler_t thread_fn)
{
struct device *dev = cxlds->dev;
struct cxl_dev_id *dev_id;
- /* dev_id must be globally unique and must contain the cxlds */
dev_id = devm_kzalloc(dev, sizeof(*dev_id), GFP_KERNEL);
if (!dev_id)
return -ENOMEM;
dev_id->cxlds = cxlds;
- return devm_request_threaded_irq(dev, irq, handler, thread_fn,
- IRQF_SHARED | IRQF_ONESHOT,
- NULL, dev_id);
+ return devm_request_threaded_irq(dev, irq, NULL, thread_fn,
+ IRQF_SHARED | IRQF_ONESHOT, NULL,
+ dev_id);
}
static bool cxl_mbox_background_complete(struct cxl_dev_state *cxlds)
@@ -128,10 +131,10 @@ static irqreturn_t cxl_pci_mbox_irq(int irq, void *id)
reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET);
opcode = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK, reg);
if (opcode == CXL_MBOX_OP_SANITIZE) {
+ mutex_lock(&mds->mbox_mutex);
if (mds->security.sanitize_node)
- sysfs_notify_dirent(mds->security.sanitize_node);
-
- dev_dbg(cxlds->dev, "Sanitization operation ended\n");
+ mod_delayed_work(system_wq, &mds->security.poll_dwork, 0);
+ mutex_unlock(&mds->mbox_mutex);
} else {
/* short-circuit the wait in __cxl_pci_mbox_send_cmd() */
rcuwait_wake_up(&mds->mbox_wait);
@@ -152,18 +155,16 @@ static void cxl_mbox_sanitize_work(struct work_struct *work)
mutex_lock(&mds->mbox_mutex);
if (cxl_mbox_background_complete(cxlds)) {
mds->security.poll_tmo_secs = 0;
- put_device(cxlds->dev);
-
if (mds->security.sanitize_node)
sysfs_notify_dirent(mds->security.sanitize_node);
+ mds->security.sanitize_active = false;
dev_dbg(cxlds->dev, "Sanitization operation ended\n");
} else {
int timeout = mds->security.poll_tmo_secs + 10;
mds->security.poll_tmo_secs = min(15 * 60, timeout);
- queue_delayed_work(system_wq, &mds->security.poll_dwork,
- timeout * HZ);
+ schedule_delayed_work(&mds->security.poll_dwork, timeout * HZ);
}
mutex_unlock(&mds->mbox_mutex);
}
@@ -295,18 +296,15 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_memdev_state *mds,
* and allow userspace to poll(2) for completion.
*/
if (mbox_cmd->opcode == CXL_MBOX_OP_SANITIZE) {
- if (mds->security.poll) {
- /* hold the device throughout */
- get_device(cxlds->dev);
-
- /* give first timeout a second */
- timeout = 1;
- mds->security.poll_tmo_secs = timeout;
- queue_delayed_work(system_wq,
- &mds->security.poll_dwork,
- timeout * HZ);
- }
-
+ if (mds->security.sanitize_active)
+ return -EBUSY;
+
+ /* give first timeout a second */
+ timeout = 1;
+ mds->security.poll_tmo_secs = timeout;
+ mds->security.sanitize_active = true;
+ schedule_delayed_work(&mds->security.poll_dwork,
+ timeout * HZ);
dev_dbg(dev, "Sanitization operation started\n");
goto success;
}
@@ -389,7 +387,9 @@ static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds)
const int cap = readl(cxlds->regs.mbox + CXLDEV_MBOX_CAPS_OFFSET);
struct device *dev = cxlds->dev;
unsigned long timeout;
+ int irq, msgnum;
u64 md_status;
+ u32 ctrl;
timeout = jiffies + mbox_ready_timeout * HZ;
do {
@@ -437,33 +437,26 @@ static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds)
dev_dbg(dev, "Mailbox payload sized %zu", mds->payload_size);
rcuwait_init(&mds->mbox_wait);
+ INIT_DELAYED_WORK(&mds->security.poll_dwork, cxl_mbox_sanitize_work);
- if (cap & CXLDEV_MBOX_CAP_BG_CMD_IRQ) {
- u32 ctrl;
- int irq, msgnum;
- struct pci_dev *pdev = to_pci_dev(cxlds->dev);
-
- msgnum = FIELD_GET(CXLDEV_MBOX_CAP_IRQ_MSGNUM_MASK, cap);
- irq = pci_irq_vector(pdev, msgnum);
- if (irq < 0)
- goto mbox_poll;
-
- if (cxl_request_irq(cxlds, irq, cxl_pci_mbox_irq, NULL))
- goto mbox_poll;
+ /* background command interrupts are optional */
+ if (!(cap & CXLDEV_MBOX_CAP_BG_CMD_IRQ))
+ return 0;
- /* enable background command mbox irq support */
- ctrl = readl(cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET);
- ctrl |= CXLDEV_MBOX_CTRL_BG_CMD_IRQ;
- writel(ctrl, cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET);
+ msgnum = FIELD_GET(CXLDEV_MBOX_CAP_IRQ_MSGNUM_MASK, cap);
+ irq = pci_irq_vector(to_pci_dev(cxlds->dev), msgnum);
+ if (irq < 0)
+ return 0;
+ if (cxl_request_irq(cxlds, irq, cxl_pci_mbox_irq))
return 0;
- }
-mbox_poll:
- mds->security.poll = true;
- INIT_DELAYED_WORK(&mds->security.poll_dwork, cxl_mbox_sanitize_work);
+ dev_dbg(cxlds->dev, "Mailbox interrupts enabled\n");
+ /* enable background command mbox irq support */
+ ctrl = readl(cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET);
+ ctrl |= CXLDEV_MBOX_CTRL_BG_CMD_IRQ;
+ writel(ctrl, cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET);
- dev_dbg(cxlds->dev, "Mailbox interrupts are unsupported");
return 0;
}
@@ -484,7 +477,7 @@ static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
resource_size_t component_reg_phys;
*map = (struct cxl_register_map) {
- .dev = &pdev->dev,
+ .host = &pdev->dev,
.resource = CXL_RESOURCE_NONE,
};
@@ -653,7 +646,7 @@ static int cxl_event_req_irq(struct cxl_dev_state *cxlds, u8 setting)
if (irq < 0)
return irq;
- return cxl_request_irq(cxlds, irq, NULL, cxl_event_thread);
+ return cxl_request_irq(cxlds, irq, cxl_event_thread);
}
static int cxl_event_get_int_policy(struct cxl_memdev_state *mds,
@@ -834,16 +827,14 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* If the component registers can't be found, the cxl_pci driver may
* still be useful for management functions so don't return an error.
*/
- cxlds->component_reg_phys = CXL_RESOURCE_NONE;
- rc = cxl_pci_setup_regs(pdev, CXL_REGLOC_RBI_COMPONENT, &map);
+ rc = cxl_pci_setup_regs(pdev, CXL_REGLOC_RBI_COMPONENT,
+ &cxlds->reg_map);
if (rc)
dev_warn(&pdev->dev, "No component registers (%d)\n", rc);
- else if (!map.component_map.ras.valid)
+ else if (!cxlds->reg_map.component_map.ras.valid)
dev_dbg(&pdev->dev, "RAS registers not found\n");
- cxlds->component_reg_phys = map.resource;
-
- rc = cxl_map_component_regs(&map, &cxlds->regs.component,
+ rc = cxl_map_component_regs(&cxlds->reg_map, &cxlds->regs.component,
BIT(CXL_CM_CAP_CAP_ID_RAS));
if (rc)
dev_dbg(&pdev->dev, "Failed to map RAS capability.\n");
@@ -882,11 +873,15 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;
- cxlmd = devm_cxl_add_memdev(cxlds);
+ cxlmd = devm_cxl_add_memdev(&pdev->dev, cxlds);
if (IS_ERR(cxlmd))
return PTR_ERR(cxlmd);
- rc = cxl_memdev_setup_fw_upload(mds);
+ rc = devm_cxl_setup_fw_upload(&pdev->dev, mds);
+ if (rc)
+ return rc;
+
+ rc = devm_cxl_sanitize_setup_notifier(&pdev->dev, cxlmd);
if (rc)
return rc;
@@ -900,7 +895,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
break;
}
- rc = cxl_map_pmu_regs(pdev, &pmu_regs, &map);
+ rc = cxl_map_pmu_regs(&map, &pmu_regs);
if (rc) {
dev_dbg(&pdev->dev, "Could not map PMU regs\n");
break;
diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c
index 6240e05b9542..47bc8e0b8590 100644
--- a/drivers/cxl/port.c
+++ b/drivers/cxl/port.c
@@ -62,6 +62,9 @@ static int cxl_switch_port_probe(struct cxl_port *port)
struct cxl_hdm *cxlhdm;
int rc;
+ /* Cache the data early to ensure is_visible() works */
+ read_cdat_data(port);
+
rc = devm_cxl_port_enumerate_dports(port);
if (rc < 0)
return rc;
diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index 0ee96e6fc426..1659b787b65f 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -103,7 +103,7 @@ static ssize_t do_id_store(struct device_driver *drv, const char *buf,
if (action == ID_ADD) {
dax_id = kzalloc(sizeof(*dax_id), GFP_KERNEL);
if (dax_id) {
- strncpy(dax_id->dev_name, buf, DAX_NAME_LEN);
+ strscpy(dax_id->dev_name, buf, DAX_NAME_LEN);
list_add(&dax_id->list, &dax_drv->ids);
} else
rc = -ENOMEM;
diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c
index c57acb73e3db..369c698b7706 100644
--- a/drivers/dax/kmem.c
+++ b/drivers/dax/kmem.c
@@ -49,14 +49,52 @@ struct dax_kmem_data {
struct resource *res[];
};
-static struct memory_dev_type *dax_slowmem_type;
+static DEFINE_MUTEX(kmem_memory_type_lock);
+static LIST_HEAD(kmem_memory_types);
+
+static struct memory_dev_type *kmem_find_alloc_memory_type(int adist)
+{
+ bool found = false;
+ struct memory_dev_type *mtype;
+
+ mutex_lock(&kmem_memory_type_lock);
+ list_for_each_entry(mtype, &kmem_memory_types, list) {
+ if (mtype->adistance == adist) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ mtype = alloc_memory_type(adist);
+ if (!IS_ERR(mtype))
+ list_add(&mtype->list, &kmem_memory_types);
+ }
+ mutex_unlock(&kmem_memory_type_lock);
+
+ return mtype;
+}
+
+static void kmem_put_memory_types(void)
+{
+ struct memory_dev_type *mtype, *mtn;
+
+ mutex_lock(&kmem_memory_type_lock);
+ list_for_each_entry_safe(mtype, mtn, &kmem_memory_types, list) {
+ list_del(&mtype->list);
+ put_memory_type(mtype);
+ }
+ mutex_unlock(&kmem_memory_type_lock);
+}
+
static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
{
struct device *dev = &dev_dax->dev;
unsigned long total_len = 0;
struct dax_kmem_data *data;
+ struct memory_dev_type *mtype;
int i, rc, mapped = 0;
int numa_node;
+ int adist = MEMTIER_DEFAULT_DAX_ADISTANCE;
/*
* Ensure good NUMA information for the persistent memory.
@@ -71,6 +109,11 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
return -EINVAL;
}
+ mt_calc_adistance(numa_node, &adist);
+ mtype = kmem_find_alloc_memory_type(adist);
+ if (IS_ERR(mtype))
+ return PTR_ERR(mtype);
+
for (i = 0; i < dev_dax->nr_range; i++) {
struct range range;
@@ -88,7 +131,7 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
return -EINVAL;
}
- init_node_memory_type(numa_node, dax_slowmem_type);
+ init_node_memory_type(numa_node, mtype);
rc = -ENOMEM;
data = kzalloc(struct_size(data, res, dev_dax->nr_range), GFP_KERNEL);
@@ -167,7 +210,7 @@ err_reg_mgid:
err_res_name:
kfree(data);
err_dax_kmem_data:
- clear_node_memory_type(numa_node, dax_slowmem_type);
+ clear_node_memory_type(numa_node, mtype);
return rc;
}
@@ -219,7 +262,7 @@ static void dev_dax_kmem_remove(struct dev_dax *dev_dax)
* for that. This implies this reference will be around
* till next reboot.
*/
- clear_node_memory_type(node, dax_slowmem_type);
+ clear_node_memory_type(node, NULL);
}
}
#else
@@ -251,12 +294,6 @@ static int __init dax_kmem_init(void)
if (!kmem_name)
return -ENOMEM;
- dax_slowmem_type = alloc_memory_type(MEMTIER_DEFAULT_DAX_ADISTANCE);
- if (IS_ERR(dax_slowmem_type)) {
- rc = PTR_ERR(dax_slowmem_type);
- goto err_dax_slowmem_type;
- }
-
rc = dax_driver_register(&device_dax_kmem_driver);
if (rc)
goto error_dax_driver;
@@ -264,8 +301,7 @@ static int __init dax_kmem_init(void)
return rc;
error_dax_driver:
- put_memory_type(dax_slowmem_type);
-err_dax_slowmem_type:
+ kmem_put_memory_types();
kfree_const(kmem_name);
return rc;
}
@@ -275,7 +311,7 @@ static void __exit dax_kmem_exit(void)
dax_driver_unregister(&device_dax_kmem_driver);
if (!any_hotremove_failed)
kfree_const(kmem_name);
- put_memory_type(dax_slowmem_type);
+ kmem_put_memory_types();
}
MODULE_AUTHOR("Intel Corporation");
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 474d81831ad3..b3a68d5833bd 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -88,7 +88,7 @@ static unsigned long find_available_min_freq(struct devfreq *devfreq)
struct dev_pm_opp *opp;
unsigned long min_freq = 0;
- opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &min_freq);
+ opp = dev_pm_opp_find_freq_ceil_indexed(devfreq->dev.parent, &min_freq, 0);
if (IS_ERR(opp))
min_freq = 0;
else
@@ -102,7 +102,7 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq)
struct dev_pm_opp *opp;
unsigned long max_freq = ULONG_MAX;
- opp = dev_pm_opp_find_freq_floor(devfreq->dev.parent, &max_freq);
+ opp = dev_pm_opp_find_freq_floor_indexed(devfreq->dev.parent, &max_freq, 0);
if (IS_ERR(opp))
max_freq = 0;
else
@@ -196,7 +196,7 @@ static int set_freq_table(struct devfreq *devfreq)
return -ENOMEM;
for (i = 0, freq = 0; i < devfreq->max_state; i++, freq++) {
- opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);
+ opp = dev_pm_opp_find_freq_ceil_indexed(devfreq->dev.parent, &freq, 0);
if (IS_ERR(opp)) {
devm_kfree(devfreq->dev.parent, devfreq->freq_table);
return PTR_ERR(opp);
@@ -2036,18 +2036,18 @@ struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) {
/* The freq is an upper bound. opp should be lower */
- opp = dev_pm_opp_find_freq_floor(dev, freq);
+ opp = dev_pm_opp_find_freq_floor_indexed(dev, freq, 0);
/* If not available, use the closest opp */
if (opp == ERR_PTR(-ERANGE))
- opp = dev_pm_opp_find_freq_ceil(dev, freq);
+ opp = dev_pm_opp_find_freq_ceil_indexed(dev, freq, 0);
} else {
/* The freq is an lower bound. opp should be higher */
- opp = dev_pm_opp_find_freq_ceil(dev, freq);
+ opp = dev_pm_opp_find_freq_ceil_indexed(dev, freq, 0);
/* If not available, use the closest opp */
if (opp == ERR_PTR(-ERANGE))
- opp = dev_pm_opp_find_freq_floor(dev, freq);
+ opp = dev_pm_opp_find_freq_floor_indexed(dev, freq, 0);
}
return opp;
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c
index 896a6cc93b00..56bac4702006 100644
--- a/drivers/devfreq/event/exynos-ppmu.c
+++ b/drivers/devfreq/event/exynos-ppmu.c
@@ -12,9 +12,9 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/suspend.h>
#include <linux/devfreq-event.h>
@@ -507,7 +507,6 @@ static int of_get_devfreq_events(struct device_node *np,
struct device *dev = info->dev;
struct device_node *events_np, *node;
int i, j, count;
- const struct of_device_id *of_id;
int ret;
events_np = of_get_child_by_name(np, "events");
@@ -525,13 +524,7 @@ static int of_get_devfreq_events(struct device_node *np,
}
info->num_events = count;
- of_id = of_match_device(exynos_ppmu_id_match, dev);
- if (of_id)
- info->ppmu_type = (enum exynos_ppmu_type)of_id->data;
- else {
- of_node_put(events_np);
- return -EINVAL;
- }
+ info->ppmu_type = (enum exynos_ppmu_type)device_get_match_data(dev);
j = 0;
for_each_child_of_node(events_np, node) {
diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c
index 39ac069cabc7..e2a1e4463b6f 100644
--- a/drivers/devfreq/event/rockchip-dfi.c
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -16,30 +16,71 @@
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/list.h>
+#include <linux/seqlock.h>
#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/perf_event.h>
+#include <soc/rockchip/rockchip_grf.h>
#include <soc/rockchip/rk3399_grf.h>
+#include <soc/rockchip/rk3568_grf.h>
+#include <soc/rockchip/rk3588_grf.h>
-#define RK3399_DMC_NUM_CH 2
+#define DMC_MAX_CHANNELS 4
+
+#define HIWORD_UPDATE(val, mask) ((val) | (mask) << 16)
/* DDRMON_CTRL */
#define DDRMON_CTRL 0x04
-#define CLR_DDRMON_CTRL (0x1f0000 << 0)
-#define LPDDR4_EN (0x10001 << 4)
-#define HARDWARE_EN (0x10001 << 3)
-#define LPDDR3_EN (0x10001 << 2)
-#define SOFTWARE_EN (0x10001 << 1)
-#define SOFTWARE_DIS (0x10000 << 1)
-#define TIME_CNT_EN (0x10001 << 0)
-
+#define DDRMON_CTRL_DDR4 BIT(5)
+#define DDRMON_CTRL_LPDDR4 BIT(4)
+#define DDRMON_CTRL_HARDWARE_EN BIT(3)
+#define DDRMON_CTRL_LPDDR23 BIT(2)
+#define DDRMON_CTRL_SOFTWARE_EN BIT(1)
+#define DDRMON_CTRL_TIMER_CNT_EN BIT(0)
+#define DDRMON_CTRL_DDR_TYPE_MASK (DDRMON_CTRL_DDR4 | \
+ DDRMON_CTRL_LPDDR4 | \
+ DDRMON_CTRL_LPDDR23)
+
+#define DDRMON_CH0_WR_NUM 0x20
+#define DDRMON_CH0_RD_NUM 0x24
#define DDRMON_CH0_COUNT_NUM 0x28
#define DDRMON_CH0_DFI_ACCESS_NUM 0x2c
#define DDRMON_CH1_COUNT_NUM 0x3c
#define DDRMON_CH1_DFI_ACCESS_NUM 0x40
-struct dmc_usage {
- u32 access;
- u32 total;
+#define PERF_EVENT_CYCLES 0x0
+#define PERF_EVENT_READ_BYTES 0x1
+#define PERF_EVENT_WRITE_BYTES 0x2
+#define PERF_EVENT_READ_BYTES0 0x3
+#define PERF_EVENT_WRITE_BYTES0 0x4
+#define PERF_EVENT_READ_BYTES1 0x5
+#define PERF_EVENT_WRITE_BYTES1 0x6
+#define PERF_EVENT_READ_BYTES2 0x7
+#define PERF_EVENT_WRITE_BYTES2 0x8
+#define PERF_EVENT_READ_BYTES3 0x9
+#define PERF_EVENT_WRITE_BYTES3 0xa
+#define PERF_EVENT_BYTES 0xb
+#define PERF_ACCESS_TYPE_MAX 0xc
+
+/**
+ * struct dmc_count_channel - structure to hold counter values from the DDR controller
+ * @access: Number of read and write accesses
+ * @clock_cycles: DDR clock cycles
+ * @read_access: number of read accesses
+ * @write_access: number of write accesses
+ */
+struct dmc_count_channel {
+ u64 access;
+ u64 clock_cycles;
+ u64 read_access;
+ u64 write_access;
+};
+
+struct dmc_count {
+ struct dmc_count_channel c[DMC_MAX_CHANNELS];
};
/*
@@ -49,177 +90,735 @@ struct dmc_usage {
*/
struct rockchip_dfi {
struct devfreq_event_dev *edev;
- struct devfreq_event_desc *desc;
- struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
+ struct devfreq_event_desc desc;
+ struct dmc_count last_event_count;
+
+ struct dmc_count last_perf_count;
+ struct dmc_count total_count;
+ seqlock_t count_seqlock; /* protects last_perf_count and total_count */
+
struct device *dev;
void __iomem *regs;
struct regmap *regmap_pmu;
struct clk *clk;
+ int usecount;
+ struct mutex mutex;
+ u32 ddr_type;
+ unsigned int channel_mask;
+ unsigned int max_channels;
+ enum cpuhp_state cpuhp_state;
+ struct hlist_node node;
+ struct pmu pmu;
+ struct hrtimer timer;
+ unsigned int cpu;
+ int active_events;
+ int burst_len;
+ int buswidth[DMC_MAX_CHANNELS];
+ int ddrmon_stride;
+ bool ddrmon_ctrl_single;
};
-static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
+static int rockchip_dfi_enable(struct rockchip_dfi *dfi)
{
- struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
- void __iomem *dfi_regs = info->regs;
- u32 val;
- u32 ddr_type;
+ void __iomem *dfi_regs = dfi->regs;
+ int i, ret = 0;
- /* get ddr type */
- regmap_read(info->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val);
- ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) &
- RK3399_PMUGRF_DDRTYPE_MASK;
+ mutex_lock(&dfi->mutex);
- /* clear DDRMON_CTRL setting */
- writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
+ dfi->usecount++;
+ if (dfi->usecount > 1)
+ goto out;
- /* set ddr type to dfi */
- if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR3)
- writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
- else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR4)
- writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
+ ret = clk_prepare_enable(dfi->clk);
+ if (ret) {
+ dev_err(&dfi->edev->dev, "failed to enable dfi clk: %d\n", ret);
+ goto out;
+ }
- /* enable count, use software mode */
- writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
+ for (i = 0; i < dfi->max_channels; i++) {
+ u32 ctrl = 0;
+
+ if (!(dfi->channel_mask & BIT(i)))
+ continue;
+
+ /* clear DDRMON_CTRL setting */
+ writel_relaxed(HIWORD_UPDATE(0, DDRMON_CTRL_TIMER_CNT_EN |
+ DDRMON_CTRL_SOFTWARE_EN | DDRMON_CTRL_HARDWARE_EN),
+ dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL);
+
+ /* set ddr type to dfi */
+ switch (dfi->ddr_type) {
+ case ROCKCHIP_DDRTYPE_LPDDR2:
+ case ROCKCHIP_DDRTYPE_LPDDR3:
+ ctrl = DDRMON_CTRL_LPDDR23;
+ break;
+ case ROCKCHIP_DDRTYPE_LPDDR4:
+ case ROCKCHIP_DDRTYPE_LPDDR4X:
+ ctrl = DDRMON_CTRL_LPDDR4;
+ break;
+ default:
+ break;
+ }
+
+ writel_relaxed(HIWORD_UPDATE(ctrl, DDRMON_CTRL_DDR_TYPE_MASK),
+ dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL);
+
+ /* enable count, use software mode */
+ writel_relaxed(HIWORD_UPDATE(DDRMON_CTRL_SOFTWARE_EN, DDRMON_CTRL_SOFTWARE_EN),
+ dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL);
+
+ if (dfi->ddrmon_ctrl_single)
+ break;
+ }
+out:
+ mutex_unlock(&dfi->mutex);
+
+ return ret;
}
-static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
+static void rockchip_dfi_disable(struct rockchip_dfi *dfi)
{
- struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
- void __iomem *dfi_regs = info->regs;
+ void __iomem *dfi_regs = dfi->regs;
+ int i;
+
+ mutex_lock(&dfi->mutex);
- writel_relaxed(SOFTWARE_DIS, dfi_regs + DDRMON_CTRL);
+ dfi->usecount--;
+
+ WARN_ON_ONCE(dfi->usecount < 0);
+
+ if (dfi->usecount > 0)
+ goto out;
+
+ for (i = 0; i < dfi->max_channels; i++) {
+ if (!(dfi->channel_mask & BIT(i)))
+ continue;
+
+ writel_relaxed(HIWORD_UPDATE(0, DDRMON_CTRL_SOFTWARE_EN),
+ dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL);
+
+ if (dfi->ddrmon_ctrl_single)
+ break;
+ }
+
+ clk_disable_unprepare(dfi->clk);
+out:
+ mutex_unlock(&dfi->mutex);
+}
+
+static void rockchip_dfi_read_counters(struct rockchip_dfi *dfi, struct dmc_count *res)
+{
+ u32 i;
+ void __iomem *dfi_regs = dfi->regs;
+
+ for (i = 0; i < dfi->max_channels; i++) {
+ if (!(dfi->channel_mask & BIT(i)))
+ continue;
+ res->c[i].read_access = readl_relaxed(dfi_regs +
+ DDRMON_CH0_RD_NUM + i * dfi->ddrmon_stride);
+ res->c[i].write_access = readl_relaxed(dfi_regs +
+ DDRMON_CH0_WR_NUM + i * dfi->ddrmon_stride);
+ res->c[i].access = readl_relaxed(dfi_regs +
+ DDRMON_CH0_DFI_ACCESS_NUM + i * dfi->ddrmon_stride);
+ res->c[i].clock_cycles = readl_relaxed(dfi_regs +
+ DDRMON_CH0_COUNT_NUM + i * dfi->ddrmon_stride);
+ }
+}
+
+static int rockchip_dfi_event_disable(struct devfreq_event_dev *edev)
+{
+ struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev);
+
+ rockchip_dfi_disable(dfi);
+
+ return 0;
+}
+
+static int rockchip_dfi_event_enable(struct devfreq_event_dev *edev)
+{
+ struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev);
+
+ return rockchip_dfi_enable(dfi);
}
-static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)
+static int rockchip_dfi_set_event(struct devfreq_event_dev *edev)
{
- struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
- u32 tmp, max = 0;
- u32 i, busier_ch = 0;
- void __iomem *dfi_regs = info->regs;
+ return 0;
+}
- rockchip_dfi_stop_hardware_counter(edev);
+static int rockchip_dfi_get_event(struct devfreq_event_dev *edev,
+ struct devfreq_event_data *edata)
+{
+ struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev);
+ struct dmc_count count;
+ struct dmc_count *last = &dfi->last_event_count;
+ u32 access = 0, clock_cycles = 0;
+ int i;
+
+ rockchip_dfi_read_counters(dfi, &count);
+
+ /* We can only report one channel, so find the busiest one */
+ for (i = 0; i < dfi->max_channels; i++) {
+ u32 a, c;
- /* Find out which channel is busier */
- for (i = 0; i < RK3399_DMC_NUM_CH; i++) {
- info->ch_usage[i].access = readl_relaxed(dfi_regs +
- DDRMON_CH0_DFI_ACCESS_NUM + i * 20) * 4;
- info->ch_usage[i].total = readl_relaxed(dfi_regs +
- DDRMON_CH0_COUNT_NUM + i * 20);
- tmp = info->ch_usage[i].access;
- if (tmp > max) {
- busier_ch = i;
- max = tmp;
+ if (!(dfi->channel_mask & BIT(i)))
+ continue;
+
+ a = count.c[i].access - last->c[i].access;
+ c = count.c[i].clock_cycles - last->c[i].clock_cycles;
+
+ if (a > access) {
+ access = a;
+ clock_cycles = c;
}
}
- rockchip_dfi_start_hardware_counter(edev);
- return busier_ch;
+ edata->load_count = access * 4;
+ edata->total_count = clock_cycles;
+
+ dfi->last_event_count = count;
+
+ return 0;
+}
+
+static const struct devfreq_event_ops rockchip_dfi_ops = {
+ .disable = rockchip_dfi_event_disable,
+ .enable = rockchip_dfi_event_enable,
+ .get_event = rockchip_dfi_get_event,
+ .set_event = rockchip_dfi_set_event,
+};
+
+#ifdef CONFIG_PERF_EVENTS
+
+static void rockchip_ddr_perf_counters_add(struct rockchip_dfi *dfi,
+ const struct dmc_count *now,
+ struct dmc_count *res)
+{
+ const struct dmc_count *last = &dfi->last_perf_count;
+ int i;
+
+ for (i = 0; i < dfi->max_channels; i++) {
+ res->c[i].read_access = dfi->total_count.c[i].read_access +
+ (u32)(now->c[i].read_access - last->c[i].read_access);
+ res->c[i].write_access = dfi->total_count.c[i].write_access +
+ (u32)(now->c[i].write_access - last->c[i].write_access);
+ res->c[i].access = dfi->total_count.c[i].access +
+ (u32)(now->c[i].access - last->c[i].access);
+ res->c[i].clock_cycles = dfi->total_count.c[i].clock_cycles +
+ (u32)(now->c[i].clock_cycles - last->c[i].clock_cycles);
+ }
+}
+
+static ssize_t ddr_perf_cpumask_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pmu *pmu = dev_get_drvdata(dev);
+ struct rockchip_dfi *dfi = container_of(pmu, struct rockchip_dfi, pmu);
+
+ return cpumap_print_to_pagebuf(true, buf, cpumask_of(dfi->cpu));
+}
+
+static struct device_attribute ddr_perf_cpumask_attr =
+ __ATTR(cpumask, 0444, ddr_perf_cpumask_show, NULL);
+
+static struct attribute *ddr_perf_cpumask_attrs[] = {
+ &ddr_perf_cpumask_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group ddr_perf_cpumask_attr_group = {
+ .attrs = ddr_perf_cpumask_attrs,
+};
+
+PMU_EVENT_ATTR_STRING(cycles, ddr_pmu_cycles, "event="__stringify(PERF_EVENT_CYCLES))
+
+#define DFI_PMU_EVENT_ATTR(_name, _var, _str) \
+ PMU_EVENT_ATTR_STRING(_name, _var, _str); \
+ PMU_EVENT_ATTR_STRING(_name.unit, _var##_unit, "MB"); \
+ PMU_EVENT_ATTR_STRING(_name.scale, _var##_scale, "9.536743164e-07")
+
+DFI_PMU_EVENT_ATTR(read-bytes0, ddr_pmu_read_bytes0, "event="__stringify(PERF_EVENT_READ_BYTES0));
+DFI_PMU_EVENT_ATTR(write-bytes0, ddr_pmu_write_bytes0, "event="__stringify(PERF_EVENT_WRITE_BYTES0));
+
+DFI_PMU_EVENT_ATTR(read-bytes1, ddr_pmu_read_bytes1, "event="__stringify(PERF_EVENT_READ_BYTES1));
+DFI_PMU_EVENT_ATTR(write-bytes1, ddr_pmu_write_bytes1, "event="__stringify(PERF_EVENT_WRITE_BYTES1));
+
+DFI_PMU_EVENT_ATTR(read-bytes2, ddr_pmu_read_bytes2, "event="__stringify(PERF_EVENT_READ_BYTES2));
+DFI_PMU_EVENT_ATTR(write-bytes2, ddr_pmu_write_bytes2, "event="__stringify(PERF_EVENT_WRITE_BYTES2));
+
+DFI_PMU_EVENT_ATTR(read-bytes3, ddr_pmu_read_bytes3, "event="__stringify(PERF_EVENT_READ_BYTES3));
+DFI_PMU_EVENT_ATTR(write-bytes3, ddr_pmu_write_bytes3, "event="__stringify(PERF_EVENT_WRITE_BYTES3));
+
+DFI_PMU_EVENT_ATTR(read-bytes, ddr_pmu_read_bytes, "event="__stringify(PERF_EVENT_READ_BYTES));
+DFI_PMU_EVENT_ATTR(write-bytes, ddr_pmu_write_bytes, "event="__stringify(PERF_EVENT_WRITE_BYTES));
+
+DFI_PMU_EVENT_ATTR(bytes, ddr_pmu_bytes, "event="__stringify(PERF_EVENT_BYTES));
+
+#define DFI_ATTR_MB(_name) \
+ &_name.attr.attr, \
+ &_name##_unit.attr.attr, \
+ &_name##_scale.attr.attr
+
+static struct attribute *ddr_perf_events_attrs[] = {
+ &ddr_pmu_cycles.attr.attr,
+ DFI_ATTR_MB(ddr_pmu_read_bytes),
+ DFI_ATTR_MB(ddr_pmu_write_bytes),
+ DFI_ATTR_MB(ddr_pmu_read_bytes0),
+ DFI_ATTR_MB(ddr_pmu_write_bytes0),
+ DFI_ATTR_MB(ddr_pmu_read_bytes1),
+ DFI_ATTR_MB(ddr_pmu_write_bytes1),
+ DFI_ATTR_MB(ddr_pmu_read_bytes2),
+ DFI_ATTR_MB(ddr_pmu_write_bytes2),
+ DFI_ATTR_MB(ddr_pmu_read_bytes3),
+ DFI_ATTR_MB(ddr_pmu_write_bytes3),
+ DFI_ATTR_MB(ddr_pmu_bytes),
+ NULL,
+};
+
+static const struct attribute_group ddr_perf_events_attr_group = {
+ .name = "events",
+ .attrs = ddr_perf_events_attrs,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-7");
+
+static struct attribute *ddr_perf_format_attrs[] = {
+ &format_attr_event.attr,
+ NULL,
+};
+
+static const struct attribute_group ddr_perf_format_attr_group = {
+ .name = "format",
+ .attrs = ddr_perf_format_attrs,
+};
+
+static const struct attribute_group *attr_groups[] = {
+ &ddr_perf_events_attr_group,
+ &ddr_perf_cpumask_attr_group,
+ &ddr_perf_format_attr_group,
+ NULL,
+};
+
+static int rockchip_ddr_perf_event_init(struct perf_event *event)
+{
+ struct rockchip_dfi *dfi = container_of(event->pmu, struct rockchip_dfi, pmu);
+
+ if (event->attr.type != event->pmu->type)
+ return -ENOENT;
+
+ if (event->attach_state & PERF_ATTACH_TASK)
+ return -EINVAL;
+
+ if (event->cpu < 0) {
+ dev_warn(dfi->dev, "Can't provide per-task data!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static u64 rockchip_ddr_perf_event_get_count(struct perf_event *event)
+{
+ struct rockchip_dfi *dfi = container_of(event->pmu, struct rockchip_dfi, pmu);
+ int blen = dfi->burst_len;
+ struct dmc_count total, now;
+ unsigned int seq;
+ u64 count = 0;
+ int i;
+
+ rockchip_dfi_read_counters(dfi, &now);
+
+ do {
+ seq = read_seqbegin(&dfi->count_seqlock);
+ rockchip_ddr_perf_counters_add(dfi, &now, &total);
+ } while (read_seqretry(&dfi->count_seqlock, seq));
+
+ switch (event->attr.config) {
+ case PERF_EVENT_CYCLES:
+ count = total.c[0].clock_cycles;
+ break;
+ case PERF_EVENT_READ_BYTES:
+ for (i = 0; i < dfi->max_channels; i++)
+ count += total.c[i].read_access * blen * dfi->buswidth[i];
+ break;
+ case PERF_EVENT_WRITE_BYTES:
+ for (i = 0; i < dfi->max_channels; i++)
+ count += total.c[i].write_access * blen * dfi->buswidth[i];
+ break;
+ case PERF_EVENT_READ_BYTES0:
+ count = total.c[0].read_access * blen * dfi->buswidth[0];
+ break;
+ case PERF_EVENT_WRITE_BYTES0:
+ count = total.c[0].write_access * blen * dfi->buswidth[0];
+ break;
+ case PERF_EVENT_READ_BYTES1:
+ count = total.c[1].read_access * blen * dfi->buswidth[1];
+ break;
+ case PERF_EVENT_WRITE_BYTES1:
+ count = total.c[1].write_access * blen * dfi->buswidth[1];
+ break;
+ case PERF_EVENT_READ_BYTES2:
+ count = total.c[2].read_access * blen * dfi->buswidth[2];
+ break;
+ case PERF_EVENT_WRITE_BYTES2:
+ count = total.c[2].write_access * blen * dfi->buswidth[2];
+ break;
+ case PERF_EVENT_READ_BYTES3:
+ count = total.c[3].read_access * blen * dfi->buswidth[3];
+ break;
+ case PERF_EVENT_WRITE_BYTES3:
+ count = total.c[3].write_access * blen * dfi->buswidth[3];
+ break;
+ case PERF_EVENT_BYTES:
+ for (i = 0; i < dfi->max_channels; i++)
+ count += total.c[i].access * blen * dfi->buswidth[i];
+ break;
+ }
+
+ return count;
+}
+
+static void rockchip_ddr_perf_event_update(struct perf_event *event)
+{
+ u64 now;
+ s64 prev;
+
+ if (event->attr.config >= PERF_ACCESS_TYPE_MAX)
+ return;
+
+ now = rockchip_ddr_perf_event_get_count(event);
+ prev = local64_xchg(&event->hw.prev_count, now);
+ local64_add(now - prev, &event->count);
+}
+
+static void rockchip_ddr_perf_event_start(struct perf_event *event, int flags)
+{
+ u64 now = rockchip_ddr_perf_event_get_count(event);
+
+ local64_set(&event->hw.prev_count, now);
+}
+
+static int rockchip_ddr_perf_event_add(struct perf_event *event, int flags)
+{
+ struct rockchip_dfi *dfi = container_of(event->pmu, struct rockchip_dfi, pmu);
+
+ dfi->active_events++;
+
+ if (dfi->active_events == 1) {
+ dfi->total_count = (struct dmc_count){};
+ rockchip_dfi_read_counters(dfi, &dfi->last_perf_count);
+ hrtimer_start(&dfi->timer, ns_to_ktime(NSEC_PER_SEC), HRTIMER_MODE_REL);
+ }
+
+ if (flags & PERF_EF_START)
+ rockchip_ddr_perf_event_start(event, flags);
+
+ return 0;
+}
+
+static void rockchip_ddr_perf_event_stop(struct perf_event *event, int flags)
+{
+ rockchip_ddr_perf_event_update(event);
}
-static int rockchip_dfi_disable(struct devfreq_event_dev *edev)
+static void rockchip_ddr_perf_event_del(struct perf_event *event, int flags)
{
- struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+ struct rockchip_dfi *dfi = container_of(event->pmu, struct rockchip_dfi, pmu);
- rockchip_dfi_stop_hardware_counter(edev);
- clk_disable_unprepare(info->clk);
+ rockchip_ddr_perf_event_stop(event, PERF_EF_UPDATE);
+
+ dfi->active_events--;
+
+ if (dfi->active_events == 0)
+ hrtimer_cancel(&dfi->timer);
+}
+
+static enum hrtimer_restart rockchip_dfi_timer(struct hrtimer *timer)
+{
+ struct rockchip_dfi *dfi = container_of(timer, struct rockchip_dfi, timer);
+ struct dmc_count now, total;
+
+ rockchip_dfi_read_counters(dfi, &now);
+
+ write_seqlock(&dfi->count_seqlock);
+
+ rockchip_ddr_perf_counters_add(dfi, &now, &total);
+ dfi->total_count = total;
+ dfi->last_perf_count = now;
+
+ write_sequnlock(&dfi->count_seqlock);
+
+ hrtimer_forward_now(&dfi->timer, ns_to_ktime(NSEC_PER_SEC));
+
+ return HRTIMER_RESTART;
+};
+
+static int ddr_perf_offline_cpu(unsigned int cpu, struct hlist_node *node)
+{
+ struct rockchip_dfi *dfi = hlist_entry_safe(node, struct rockchip_dfi, node);
+ int target;
+
+ if (cpu != dfi->cpu)
+ return 0;
+
+ target = cpumask_any_but(cpu_online_mask, cpu);
+ if (target >= nr_cpu_ids)
+ return 0;
+
+ perf_pmu_migrate_context(&dfi->pmu, cpu, target);
+ dfi->cpu = target;
return 0;
}
-static int rockchip_dfi_enable(struct devfreq_event_dev *edev)
+static void rockchip_ddr_cpuhp_remove_state(void *data)
+{
+ struct rockchip_dfi *dfi = data;
+
+ cpuhp_remove_multi_state(dfi->cpuhp_state);
+
+ rockchip_dfi_disable(dfi);
+}
+
+static void rockchip_ddr_cpuhp_remove_instance(void *data)
+{
+ struct rockchip_dfi *dfi = data;
+
+ cpuhp_state_remove_instance_nocalls(dfi->cpuhp_state, &dfi->node);
+}
+
+static void rockchip_ddr_perf_remove(void *data)
{
- struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+ struct rockchip_dfi *dfi = data;
+
+ perf_pmu_unregister(&dfi->pmu);
+}
+
+static int rockchip_ddr_perf_init(struct rockchip_dfi *dfi)
+{
+ struct pmu *pmu = &dfi->pmu;
int ret;
- ret = clk_prepare_enable(info->clk);
+ seqlock_init(&dfi->count_seqlock);
+
+ pmu->module = THIS_MODULE;
+ pmu->capabilities = PERF_PMU_CAP_NO_EXCLUDE;
+ pmu->task_ctx_nr = perf_invalid_context;
+ pmu->attr_groups = attr_groups;
+ pmu->event_init = rockchip_ddr_perf_event_init;
+ pmu->add = rockchip_ddr_perf_event_add;
+ pmu->del = rockchip_ddr_perf_event_del;
+ pmu->start = rockchip_ddr_perf_event_start;
+ pmu->stop = rockchip_ddr_perf_event_stop;
+ pmu->read = rockchip_ddr_perf_event_update;
+
+ dfi->cpu = raw_smp_processor_id();
+
+ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
+ "rockchip_ddr_perf_pmu",
+ NULL,
+ ddr_perf_offline_cpu);
+
+ if (ret < 0) {
+ dev_err(dfi->dev, "cpuhp_setup_state_multi failed: %d\n", ret);
+ return ret;
+ }
+
+ dfi->cpuhp_state = ret;
+
+ rockchip_dfi_enable(dfi);
+
+ ret = devm_add_action_or_reset(dfi->dev, rockchip_ddr_cpuhp_remove_state, dfi);
+ if (ret)
+ return ret;
+
+ ret = cpuhp_state_add_instance_nocalls(dfi->cpuhp_state, &dfi->node);
if (ret) {
- dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ret);
+ dev_err(dfi->dev, "Error %d registering hotplug\n", ret);
return ret;
}
- rockchip_dfi_start_hardware_counter(edev);
+ ret = devm_add_action_or_reset(dfi->dev, rockchip_ddr_cpuhp_remove_instance, dfi);
+ if (ret)
+ return ret;
+
+ hrtimer_init(&dfi->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ dfi->timer.function = rockchip_dfi_timer;
+
+ switch (dfi->ddr_type) {
+ case ROCKCHIP_DDRTYPE_LPDDR2:
+ case ROCKCHIP_DDRTYPE_LPDDR3:
+ dfi->burst_len = 8;
+ break;
+ case ROCKCHIP_DDRTYPE_LPDDR4:
+ case ROCKCHIP_DDRTYPE_LPDDR4X:
+ dfi->burst_len = 16;
+ break;
+ }
+
+ ret = perf_pmu_register(pmu, "rockchip_ddr", -1);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(dfi->dev, rockchip_ddr_perf_remove, dfi);
+}
+#else
+static int rockchip_ddr_perf_init(struct rockchip_dfi *dfi)
+{
return 0;
}
+#endif
-static int rockchip_dfi_set_event(struct devfreq_event_dev *edev)
+static int rk3399_dfi_init(struct rockchip_dfi *dfi)
{
+ struct regmap *regmap_pmu = dfi->regmap_pmu;
+ u32 val;
+
+ dfi->clk = devm_clk_get(dfi->dev, "pclk_ddr_mon");
+ if (IS_ERR(dfi->clk))
+ return dev_err_probe(dfi->dev, PTR_ERR(dfi->clk),
+ "Cannot get the clk pclk_ddr_mon\n");
+
+ /* get ddr type */
+ regmap_read(regmap_pmu, RK3399_PMUGRF_OS_REG2, &val);
+ dfi->ddr_type = FIELD_GET(RK3399_PMUGRF_OS_REG2_DDRTYPE, val);
+
+ dfi->channel_mask = GENMASK(1, 0);
+ dfi->max_channels = 2;
+
+ dfi->buswidth[0] = FIELD_GET(RK3399_PMUGRF_OS_REG2_BW_CH0, val) == 0 ? 4 : 2;
+ dfi->buswidth[1] = FIELD_GET(RK3399_PMUGRF_OS_REG2_BW_CH1, val) == 0 ? 4 : 2;
+
+ dfi->ddrmon_stride = 0x14;
+ dfi->ddrmon_ctrl_single = true;
+
return 0;
-}
+};
-static int rockchip_dfi_get_event(struct devfreq_event_dev *edev,
- struct devfreq_event_data *edata)
+static int rk3568_dfi_init(struct rockchip_dfi *dfi)
{
- struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
- int busier_ch;
+ struct regmap *regmap_pmu = dfi->regmap_pmu;
+ u32 reg2, reg3;
+
+ regmap_read(regmap_pmu, RK3568_PMUGRF_OS_REG2, &reg2);
+ regmap_read(regmap_pmu, RK3568_PMUGRF_OS_REG3, &reg3);
+
+ /* lower 3 bits of the DDR type */
+ dfi->ddr_type = FIELD_GET(RK3568_PMUGRF_OS_REG2_DRAMTYPE_INFO, reg2);
+
+ /*
+ * For version three and higher the upper two bits of the DDR type are
+ * in RK3568_PMUGRF_OS_REG3
+ */
+ if (FIELD_GET(RK3568_PMUGRF_OS_REG3_SYSREG_VERSION, reg3) >= 0x3)
+ dfi->ddr_type |= FIELD_GET(RK3568_PMUGRF_OS_REG3_DRAMTYPE_INFO_V3, reg3) << 3;
- busier_ch = rockchip_dfi_get_busier_ch(edev);
+ dfi->channel_mask = BIT(0);
+ dfi->max_channels = 1;
- edata->load_count = info->ch_usage[busier_ch].access;
- edata->total_count = info->ch_usage[busier_ch].total;
+ dfi->buswidth[0] = FIELD_GET(RK3568_PMUGRF_OS_REG2_BW_CH0, reg2) == 0 ? 4 : 2;
+
+ dfi->ddrmon_stride = 0x0; /* not relevant, we only have a single channel on this SoC */
+ dfi->ddrmon_ctrl_single = true;
return 0;
-}
+};
-static const struct devfreq_event_ops rockchip_dfi_ops = {
- .disable = rockchip_dfi_disable,
- .enable = rockchip_dfi_enable,
- .get_event = rockchip_dfi_get_event,
- .set_event = rockchip_dfi_set_event,
+static int rk3588_dfi_init(struct rockchip_dfi *dfi)
+{
+ struct regmap *regmap_pmu = dfi->regmap_pmu;
+ u32 reg2, reg3, reg4;
+
+ regmap_read(regmap_pmu, RK3588_PMUGRF_OS_REG2, &reg2);
+ regmap_read(regmap_pmu, RK3588_PMUGRF_OS_REG3, &reg3);
+ regmap_read(regmap_pmu, RK3588_PMUGRF_OS_REG4, &reg4);
+
+ /* lower 3 bits of the DDR type */
+ dfi->ddr_type = FIELD_GET(RK3588_PMUGRF_OS_REG2_DRAMTYPE_INFO, reg2);
+
+ /*
+ * For version three and higher the upper two bits of the DDR type are
+ * in RK3588_PMUGRF_OS_REG3
+ */
+ if (FIELD_GET(RK3588_PMUGRF_OS_REG3_SYSREG_VERSION, reg3) >= 0x3)
+ dfi->ddr_type |= FIELD_GET(RK3588_PMUGRF_OS_REG3_DRAMTYPE_INFO_V3, reg3) << 3;
+
+ dfi->buswidth[0] = FIELD_GET(RK3588_PMUGRF_OS_REG2_BW_CH0, reg2) == 0 ? 4 : 2;
+ dfi->buswidth[1] = FIELD_GET(RK3588_PMUGRF_OS_REG2_BW_CH1, reg2) == 0 ? 4 : 2;
+ dfi->buswidth[2] = FIELD_GET(RK3568_PMUGRF_OS_REG2_BW_CH0, reg4) == 0 ? 4 : 2;
+ dfi->buswidth[3] = FIELD_GET(RK3588_PMUGRF_OS_REG2_BW_CH1, reg4) == 0 ? 4 : 2;
+ dfi->channel_mask = FIELD_GET(RK3588_PMUGRF_OS_REG2_CH_INFO, reg2) |
+ FIELD_GET(RK3588_PMUGRF_OS_REG2_CH_INFO, reg4) << 2;
+ dfi->max_channels = 4;
+
+ dfi->ddrmon_stride = 0x4000;
+
+ return 0;
};
static const struct of_device_id rockchip_dfi_id_match[] = {
- { .compatible = "rockchip,rk3399-dfi" },
+ { .compatible = "rockchip,rk3399-dfi", .data = rk3399_dfi_init },
+ { .compatible = "rockchip,rk3568-dfi", .data = rk3568_dfi_init },
+ { .compatible = "rockchip,rk3588-dfi", .data = rk3588_dfi_init },
{ },
};
+
MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match);
static int rockchip_dfi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct rockchip_dfi *data;
+ struct rockchip_dfi *dfi;
struct devfreq_event_desc *desc;
struct device_node *np = pdev->dev.of_node, *node;
+ int (*soc_init)(struct rockchip_dfi *dfi);
+ int ret;
- data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
+ soc_init = of_device_get_match_data(&pdev->dev);
+ if (!soc_init)
+ return -EINVAL;
- data->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(data->regs))
- return PTR_ERR(data->regs);
+ dfi = devm_kzalloc(dev, sizeof(*dfi), GFP_KERNEL);
+ if (!dfi)
+ return -ENOMEM;
- data->clk = devm_clk_get(dev, "pclk_ddr_mon");
- if (IS_ERR(data->clk))
- return dev_err_probe(dev, PTR_ERR(data->clk),
- "Cannot get the clk pclk_ddr_mon\n");
+ dfi->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(dfi->regs))
+ return PTR_ERR(dfi->regs);
- /* try to find the optional reference to the pmu syscon */
node = of_parse_phandle(np, "rockchip,pmu", 0);
- if (node) {
- data->regmap_pmu = syscon_node_to_regmap(node);
- of_node_put(node);
- if (IS_ERR(data->regmap_pmu))
- return PTR_ERR(data->regmap_pmu);
- }
- data->dev = dev;
+ if (!node)
+ return dev_err_probe(&pdev->dev, -ENODEV, "Can't find pmu_grf registers\n");
- desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
- if (!desc)
- return -ENOMEM;
+ dfi->regmap_pmu = syscon_node_to_regmap(node);
+ of_node_put(node);
+ if (IS_ERR(dfi->regmap_pmu))
+ return PTR_ERR(dfi->regmap_pmu);
+
+ dfi->dev = dev;
+ mutex_init(&dfi->mutex);
+ desc = &dfi->desc;
desc->ops = &rockchip_dfi_ops;
- desc->driver_data = data;
+ desc->driver_data = dfi;
desc->name = np->name;
- data->desc = desc;
- data->edev = devm_devfreq_event_add_edev(&pdev->dev, desc);
- if (IS_ERR(data->edev)) {
+ ret = soc_init(dfi);
+ if (ret)
+ return ret;
+
+ dfi->edev = devm_devfreq_event_add_edev(&pdev->dev, desc);
+ if (IS_ERR(dfi->edev)) {
dev_err(&pdev->dev,
"failed to add devfreq-event device\n");
- return PTR_ERR(data->edev);
+ return PTR_ERR(dfi->edev);
}
- platform_set_drvdata(pdev, data);
+ ret = rockchip_ddr_perf_init(dfi);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, dfi);
return 0;
}
@@ -229,6 +828,7 @@ static struct platform_driver rockchip_dfi_driver = {
.driver = {
.name = "rockchip-dfi",
.of_match_table = rockchip_dfi_id_match,
+ .suppress_bind_attrs = true,
},
};
module_platform_driver(rockchip_dfi_driver);
diff --git a/drivers/devfreq/mtk-cci-devfreq.c b/drivers/devfreq/mtk-cci-devfreq.c
index 83a73f0ccd80..11bc3d03494c 100644
--- a/drivers/devfreq/mtk-cci-devfreq.c
+++ b/drivers/devfreq/mtk-cci-devfreq.c
@@ -137,6 +137,8 @@ static int mtk_ccifreq_target(struct device *dev, unsigned long *freq,
if (drv->pre_freq == *freq)
return 0;
+ mutex_lock(&drv->reg_lock);
+
inter_voltage = drv->inter_voltage;
cci_pll = clk_get_parent(drv->cci_clk);
@@ -144,11 +146,10 @@ static int mtk_ccifreq_target(struct device *dev, unsigned long *freq,
opp = devfreq_recommended_opp(dev, &opp_rate, 1);
if (IS_ERR(opp)) {
dev_err(dev, "failed to find opp for freq: %ld\n", opp_rate);
- return PTR_ERR(opp);
+ ret = PTR_ERR(opp);
+ goto out_unlock;
}
- mutex_lock(&drv->reg_lock);
-
voltage = dev_pm_opp_get_voltage(opp);
dev_pm_opp_put(opp);
@@ -227,9 +228,9 @@ static int mtk_ccifreq_opp_notifier(struct notifier_block *nb,
drv = container_of(nb, struct mtk_ccifreq_drv, opp_nb);
if (event == OPP_EVENT_ADJUST_VOLTAGE) {
+ mutex_lock(&drv->reg_lock);
freq = dev_pm_opp_get_freq(opp);
- mutex_lock(&drv->reg_lock);
/* current opp item is changed */
if (freq == drv->pre_freq) {
volt = dev_pm_opp_get_voltage(opp);
diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
index daff40702615..fd2c5ffedf41 100644
--- a/drivers/devfreq/rk3399_dmc.c
+++ b/drivers/devfreq/rk3399_dmc.c
@@ -22,6 +22,7 @@
#include <linux/suspend.h>
#include <soc/rockchip/pm_domains.h>
+#include <soc/rockchip/rockchip_grf.h>
#include <soc/rockchip/rk3399_grf.h>
#include <soc/rockchip/rockchip_sip.h>
@@ -381,17 +382,16 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
}
regmap_read(data->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val);
- ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) &
- RK3399_PMUGRF_DDRTYPE_MASK;
+ ddr_type = FIELD_GET(RK3399_PMUGRF_OS_REG2_DDRTYPE, val);
switch (ddr_type) {
- case RK3399_PMUGRF_DDRTYPE_DDR3:
+ case ROCKCHIP_DDRTYPE_DDR3:
data->odt_dis_freq = data->ddr3_odt_dis_freq;
break;
- case RK3399_PMUGRF_DDRTYPE_LPDDR3:
+ case ROCKCHIP_DDRTYPE_LPDDR3:
data->odt_dis_freq = data->lpddr3_odt_dis_freq;
break;
- case RK3399_PMUGRF_DDRTYPE_LPDDR4:
+ case ROCKCHIP_DDRTYPE_LPDDR4:
data->odt_dis_freq = data->lpddr4_odt_dis_freq;
break;
default:
diff --git a/drivers/dma-buf/dma-fence-unwrap.c b/drivers/dma-buf/dma-fence-unwrap.c
index c625bb2b5d56..628af51c81af 100644
--- a/drivers/dma-buf/dma-fence-unwrap.c
+++ b/drivers/dma-buf/dma-fence-unwrap.c
@@ -76,16 +76,11 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) {
if (!dma_fence_is_signaled(tmp)) {
++count;
- } else if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT,
- &tmp->flags)) {
- if (ktime_after(tmp->timestamp, timestamp))
- timestamp = tmp->timestamp;
} else {
- /*
- * Use the current time if the fence is
- * currently signaling.
- */
- timestamp = ktime_get();
+ ktime_t t = dma_fence_timestamp(tmp);
+
+ if (ktime_after(t, timestamp))
+ timestamp = t;
}
}
}
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index 38b4110378de..eb8b733065b2 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -301,7 +301,7 @@ void dma_resv_add_fence(struct dma_resv *obj, struct dma_fence *fence,
dma_resv_list_entry(fobj, i, obj, &old, &old_usage);
if ((old->context == fence->context && old_usage >= usage &&
- dma_fence_is_later(fence, old)) ||
+ dma_fence_is_later_or_same(fence, old)) ||
dma_fence_is_signaled(old)) {
dma_resv_list_set(fobj, i, fence, usage);
dma_fence_put(old);
diff --git a/drivers/dma-buf/st-dma-fence-chain.c b/drivers/dma-buf/st-dma-fence-chain.c
index c0979c8049b5..9c2a0c082a76 100644
--- a/drivers/dma-buf/st-dma-fence-chain.c
+++ b/drivers/dma-buf/st-dma-fence-chain.c
@@ -476,10 +476,9 @@ static int find_race(void *arg)
for (i = 0; i < ncpus; i++) {
int ret;
- ret = kthread_stop(threads[i]);
+ ret = kthread_stop_put(threads[i]);
if (ret && !err)
err = ret;
- put_task_struct(threads[i]);
}
kfree(threads);
@@ -591,8 +590,7 @@ static int wait_forward(void *arg)
for (i = 0; i < fc.chain_length; i++)
dma_fence_signal(fc.fences[i]);
- err = kthread_stop(tsk);
- put_task_struct(tsk);
+ err = kthread_stop_put(tsk);
err:
fence_chains_fini(&fc);
@@ -621,8 +619,7 @@ static int wait_backward(void *arg)
for (i = fc.chain_length; i--; )
dma_fence_signal(fc.fences[i]);
- err = kthread_stop(tsk);
- put_task_struct(tsk);
+ err = kthread_stop_put(tsk);
err:
fence_chains_fini(&fc);
@@ -669,8 +666,7 @@ static int wait_random(void *arg)
for (i = 0; i < fc.chain_length; i++)
dma_fence_signal(fc.fences[i]);
- err = kthread_stop(tsk);
- put_task_struct(tsk);
+ err = kthread_stop_put(tsk);
err:
fence_chains_fini(&fc);
diff --git a/drivers/dma-buf/st-dma-fence.c b/drivers/dma-buf/st-dma-fence.c
index fb6e0a6ae2c9..b7c6f7ea9e0c 100644
--- a/drivers/dma-buf/st-dma-fence.c
+++ b/drivers/dma-buf/st-dma-fence.c
@@ -548,11 +548,9 @@ static int race_signal_callback(void *arg)
for (i = 0; i < ARRAY_SIZE(t); i++) {
int err;
- err = kthread_stop(t[i].task);
+ err = kthread_stop_put(t[i].task);
if (err && !ret)
ret = err;
-
- put_task_struct(t[i].task);
}
}
diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
index af57799c86ce..2e9a316c596a 100644
--- a/drivers/dma-buf/sync_file.c
+++ b/drivers/dma-buf/sync_file.c
@@ -268,13 +268,10 @@ static int sync_fill_fence_info(struct dma_fence *fence,
sizeof(info->driver_name));
info->status = dma_fence_get_status(fence);
- while (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) &&
- !test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags))
- cpu_relax();
info->timestamp_ns =
- test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags) ?
- ktime_to_ns(fence->timestamp) :
- ktime_set(0, 0);
+ dma_fence_is_signaled(fence) ?
+ ktime_to_ns(dma_fence_timestamp(fence)) :
+ ktime_set(0, 0);
return info->status;
}
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 4ccae1a3b884..70ba506dabab 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -362,7 +362,7 @@ config INTEL_IOATDMA
config K3_DMA
tristate "Hisilicon K3 DMA support"
- depends on ARCH_HI3xxx || ARCH_HISI || COMPILE_TEST
+ depends on ARCH_HISI || COMPILE_TEST
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
help
diff --git a/drivers/dma/altera-msgdma.c b/drivers/dma/altera-msgdma.c
index 4153c2edb049..a8e3615235b8 100644
--- a/drivers/dma/altera-msgdma.c
+++ b/drivers/dma/altera-msgdma.c
@@ -923,7 +923,7 @@ fail:
*
* Return: Always '0'
*/
-static int msgdma_remove(struct platform_device *pdev)
+static void msgdma_remove(struct platform_device *pdev)
{
struct msgdma_device *mdev = platform_get_drvdata(pdev);
@@ -933,8 +933,6 @@ static int msgdma_remove(struct platform_device *pdev)
msgdma_dev_remove(mdev);
dev_notice(&pdev->dev, "Altera mSGDMA driver removed\n");
-
- return 0;
}
#ifdef CONFIG_OF
@@ -952,7 +950,7 @@ static struct platform_driver msgdma_driver = {
.of_match_table = of_match_ptr(msgdma_match),
},
.probe = msgdma_probe,
- .remove = msgdma_remove,
+ .remove_new = msgdma_remove,
};
module_platform_driver(msgdma_driver);
diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c
index 3af795635c5c..5b63996640d9 100644
--- a/drivers/dma/apple-admac.c
+++ b/drivers/dma/apple-admac.c
@@ -128,7 +128,7 @@ struct admac_data {
int irq;
int irq_index;
int nchannels;
- struct admac_chan channels[];
+ struct admac_chan channels[] __counted_by(nchannels);
};
struct admac_tx {
@@ -925,7 +925,7 @@ free_reset:
return err;
}
-static int admac_remove(struct platform_device *pdev)
+static void admac_remove(struct platform_device *pdev)
{
struct admac_data *ad = platform_get_drvdata(pdev);
@@ -933,8 +933,6 @@ static int admac_remove(struct platform_device *pdev)
dma_async_device_unregister(&ad->dma);
free_irq(ad->irq, ad);
reset_control_rearm(ad->rstc);
-
- return 0;
}
static const struct of_device_id admac_of_match[] = {
@@ -949,7 +947,7 @@ static struct platform_driver apple_admac_driver = {
.of_match_table = admac_of_match,
},
.probe = admac_probe,
- .remove = admac_remove,
+ .remove_new = admac_remove,
};
module_platform_driver(apple_admac_driver);
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index b2876f67471f..fb89ecbf0cc5 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -239,7 +239,7 @@ struct at_desc {
bool memset_buffer;
dma_addr_t memset_paddr;
int *memset_vaddr;
- struct atdma_sg sg[];
+ struct atdma_sg sg[] __counted_by(sglen);
};
/*-- Channels --------------------------------------------------------*/
@@ -2100,7 +2100,7 @@ err_irq:
return err;
}
-static int at_dma_remove(struct platform_device *pdev)
+static void at_dma_remove(struct platform_device *pdev)
{
struct at_dma *atdma = platform_get_drvdata(pdev);
struct dma_chan *chan, *_chan;
@@ -2122,8 +2122,6 @@ static int at_dma_remove(struct platform_device *pdev)
}
clk_disable_unprepare(atdma->clk);
-
- return 0;
}
static void at_dma_shutdown(struct platform_device *pdev)
@@ -2242,7 +2240,7 @@ static const struct dev_pm_ops __maybe_unused at_dma_dev_pm_ops = {
};
static struct platform_driver at_dma_driver = {
- .remove = at_dma_remove,
+ .remove_new = at_dma_remove,
.shutdown = at_dma_shutdown,
.id_table = atdma_devtypes,
.driver = {
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index c3b37168b21f..299396121e6d 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -2431,7 +2431,7 @@ err_free_irq:
return ret;
}
-static int at_xdmac_remove(struct platform_device *pdev)
+static void at_xdmac_remove(struct platform_device *pdev)
{
struct at_xdmac *atxdmac = (struct at_xdmac *)platform_get_drvdata(pdev);
int i;
@@ -2452,8 +2452,6 @@ static int at_xdmac_remove(struct platform_device *pdev)
tasklet_kill(&atchan->tasklet);
at_xdmac_free_chan_resources(&atchan->chan);
}
-
- return 0;
}
static const struct dev_pm_ops __maybe_unused atmel_xdmac_dev_pm_ops = {
@@ -2478,7 +2476,7 @@ MODULE_DEVICE_TABLE(of, atmel_xdmac_dt_ids);
static struct platform_driver at_xdmac_driver = {
.probe = at_xdmac_probe,
- .remove = at_xdmac_remove,
+ .remove_new = at_xdmac_remove,
.driver = {
.name = "at_xdmac",
.of_match_table = of_match_ptr(atmel_xdmac_dt_ids),
diff --git a/drivers/dma/bcm-sba-raid.c b/drivers/dma/bcm-sba-raid.c
index 94ea35330eb5..fbaacb4c19b2 100644
--- a/drivers/dma/bcm-sba-raid.c
+++ b/drivers/dma/bcm-sba-raid.c
@@ -1734,7 +1734,7 @@ fail_free_mchan:
return ret;
}
-static int sba_remove(struct platform_device *pdev)
+static void sba_remove(struct platform_device *pdev)
{
struct sba_device *sba = platform_get_drvdata(pdev);
@@ -1745,8 +1745,6 @@ static int sba_remove(struct platform_device *pdev)
sba_freeup_channel_resources(sba);
mbox_free_channel(sba->mchan);
-
- return 0;
}
static const struct of_device_id sba_of_match[] = {
@@ -1758,7 +1756,7 @@ MODULE_DEVICE_TABLE(of, sba_of_match);
static struct platform_driver sba_driver = {
.probe = sba_probe,
- .remove = sba_remove,
+ .remove_new = sba_remove,
.driver = {
.name = "bcm-sba-raid",
.of_match_table = sba_of_match,
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index 0807fb9eb262..9d74fe97452e 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -1019,19 +1019,17 @@ err_no_dma:
return rc;
}
-static int bcm2835_dma_remove(struct platform_device *pdev)
+static void bcm2835_dma_remove(struct platform_device *pdev)
{
struct bcm2835_dmadev *od = platform_get_drvdata(pdev);
dma_async_device_unregister(&od->ddev);
bcm2835_dma_free(od);
-
- return 0;
}
static struct platform_driver bcm2835_dma_driver = {
.probe = bcm2835_dma_probe,
- .remove = bcm2835_dma_remove,
+ .remove_new = bcm2835_dma_remove,
.driver = {
.name = "bcm2835-dma",
.of_match_table = of_match_ptr(bcm2835_dma_of_match),
diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c
index 80096f94032d..0bbaa7620bdd 100644
--- a/drivers/dma/bestcomm/bestcomm.c
+++ b/drivers/dma/bestcomm/bestcomm.c
@@ -455,7 +455,7 @@ error_ofput:
}
-static int mpc52xx_bcom_remove(struct platform_device *op)
+static void mpc52xx_bcom_remove(struct platform_device *op)
{
/* Clean up the engine */
bcom_engine_cleanup();
@@ -473,8 +473,6 @@ static int mpc52xx_bcom_remove(struct platform_device *op)
/* Release memory */
kfree(bcom_eng);
bcom_eng = NULL;
-
- return 0;
}
static const struct of_device_id mpc52xx_bcom_of_match[] = {
@@ -488,7 +486,7 @@ MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
static struct platform_driver mpc52xx_bcom_of_platform_driver = {
.probe = mpc52xx_bcom_probe,
- .remove = mpc52xx_bcom_remove,
+ .remove_new = mpc52xx_bcom_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = mpc52xx_bcom_of_match,
diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index fc7cdad37161..2457a420c13d 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -117,7 +117,7 @@ struct axi_dmac_desc {
unsigned int num_submitted;
unsigned int num_completed;
unsigned int num_sgs;
- struct axi_dmac_sg sg[];
+ struct axi_dmac_sg sg[] __counted_by(num_sgs);
};
struct axi_dmac_chan {
@@ -484,12 +484,11 @@ static struct axi_dmac_desc *axi_dmac_alloc_desc(unsigned int num_sgs)
desc = kzalloc(struct_size(desc, sg, num_sgs), GFP_NOWAIT);
if (!desc)
return NULL;
+ desc->num_sgs = num_sgs;
for (i = 0; i < num_sgs; i++)
desc->sg[i].id = AXI_DMAC_SG_UNUSED;
- desc->num_sgs = num_sgs;
-
return desc;
}
@@ -1029,7 +1028,7 @@ err_clk_disable:
return ret;
}
-static int axi_dmac_remove(struct platform_device *pdev)
+static void axi_dmac_remove(struct platform_device *pdev)
{
struct axi_dmac *dmac = platform_get_drvdata(pdev);
@@ -1038,8 +1037,6 @@ static int axi_dmac_remove(struct platform_device *pdev)
tasklet_kill(&dmac->chan.vchan.task);
dma_async_device_unregister(&dmac->dma_dev);
clk_disable_unprepare(dmac->clk);
-
- return 0;
}
static const struct of_device_id axi_dmac_of_match_table[] = {
@@ -1054,7 +1051,7 @@ static struct platform_driver axi_dmac_driver = {
.of_match_table = axi_dmac_of_match_table,
},
.probe = axi_dmac_probe,
- .remove = axi_dmac_remove,
+ .remove_new = axi_dmac_remove,
};
module_platform_driver(axi_dmac_driver);
diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
index adbd47bd6adf..c9cfa341db51 100644
--- a/drivers/dma/dma-jz4780.c
+++ b/drivers/dma/dma-jz4780.c
@@ -1008,7 +1008,7 @@ err_disable_clk:
return ret;
}
-static int jz4780_dma_remove(struct platform_device *pdev)
+static void jz4780_dma_remove(struct platform_device *pdev)
{
struct jz4780_dma_dev *jzdma = platform_get_drvdata(pdev);
int i;
@@ -1020,8 +1020,6 @@ static int jz4780_dma_remove(struct platform_device *pdev)
for (i = 0; i < jzdma->soc_data->nb_channels; i++)
tasklet_kill(&jzdma->chan[i].vchan.task);
-
- return 0;
}
static const struct jz4780_dma_soc_data jz4740_dma_soc_data = {
@@ -1124,7 +1122,7 @@ MODULE_DEVICE_TABLE(of, jz4780_dma_dt_match);
static struct platform_driver jz4780_dma_driver = {
.probe = jz4780_dma_probe,
- .remove = jz4780_dma_remove,
+ .remove_new = jz4780_dma_remove,
.driver = {
.name = "jz4780-dma",
.of_match_table = jz4780_dma_dt_match,
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index dd02f84e404d..a86a81ff0caa 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -63,6 +63,17 @@ static inline u32 axi_dma_ioread32(struct axi_dma_chip *chip, u32 reg)
}
static inline void
+axi_dma_iowrite64(struct axi_dma_chip *chip, u32 reg, u64 val)
+{
+ iowrite64(val, chip->regs + reg);
+}
+
+static inline u64 axi_dma_ioread64(struct axi_dma_chip *chip, u32 reg)
+{
+ return ioread64(chip->regs + reg);
+}
+
+static inline void
axi_chan_iowrite32(struct axi_dma_chan *chan, u32 reg, u32 val)
{
iowrite32(val, chan->chan_regs + reg);
@@ -182,38 +193,73 @@ static inline u32 axi_chan_irq_read(struct axi_dma_chan *chan)
static inline void axi_chan_disable(struct axi_dma_chan *chan)
{
- u32 val;
-
- val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
- val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
- if (chan->chip->dw->hdata->reg_map_8_channels)
- val |= BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
- else
- val |= BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
- axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+ u64 val;
+
+ if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
+ val = axi_dma_ioread64(chan->chip, DMAC_CHEN);
+ if (chan->id >= DMAC_CHAN_16) {
+ val &= ~((u64)(BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_EN_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
+ val |= (u64)(BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_EN2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
+ } else {
+ val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
+ val |= BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
+ }
+ axi_dma_iowrite64(chan->chip, DMAC_CHEN, val);
+ } else {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
+ if (chan->chip->dw->hdata->reg_map_8_channels)
+ val |= BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
+ else
+ val |= BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
+ }
}
static inline void axi_chan_enable(struct axi_dma_chan *chan)
{
- u32 val;
-
- val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
- if (chan->chip->dw->hdata->reg_map_8_channels)
- val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
- BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
- else
- val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
+ u64 val;
+
+ if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
+ val = axi_dma_ioread64(chan->chip, DMAC_CHEN);
+ if (chan->id >= DMAC_CHAN_16) {
+ val |= (u64)(BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_EN_SHIFT + DMAC_CHAN_BLOCK_SHIFT) |
+ (u64)(BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_EN2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
+ } else {
+ val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
- axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+ }
+ axi_dma_iowrite64(chan->chip, DMAC_CHEN, val);
+ } else {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ if (chan->chip->dw->hdata->reg_map_8_channels) {
+ val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
+ } else {
+ val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
+ }
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
+ }
}
static inline bool axi_chan_is_hw_enable(struct axi_dma_chan *chan)
{
- u32 val;
+ u64 val;
- val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16)
+ val = axi_dma_ioread64(chan->chip, DMAC_CHEN);
+ else
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
- return !!(val & (BIT(chan->id) << DMAC_CHAN_EN_SHIFT));
+ if (chan->id >= DMAC_CHAN_16)
+ return !!(val & ((u64)(BIT(chan->id) >> DMAC_CHAN_16) << DMAC_CHAN_BLOCK_SHIFT));
+ else
+ return !!(val & (BIT(chan->id) << DMAC_CHAN_EN_SHIFT));
}
static void axi_dma_hw_init(struct axi_dma_chip *chip)
@@ -1175,20 +1221,34 @@ static int dma_chan_pause(struct dma_chan *dchan)
struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
unsigned long flags;
unsigned int timeout = 20; /* timeout iterations */
- u32 val;
+ u64 val;
spin_lock_irqsave(&chan->vc.lock, flags);
- if (chan->chip->dw->hdata->reg_map_8_channels) {
- val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
- val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT |
- BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
- axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+ if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
+ val = axi_dma_ioread64(chan->chip, DMAC_CHSUSPREG);
+ if (chan->id >= DMAC_CHAN_16) {
+ val |= (u64)(BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_SUSP2_SHIFT + DMAC_CHAN_BLOCK_SHIFT) |
+ (u64)(BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_SUSP2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
+ } else {
+ val |= BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT;
+ }
+ axi_dma_iowrite64(chan->chip, DMAC_CHSUSPREG, val);
} else {
- val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
- val |= BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
+ if (chan->chip->dw->hdata->reg_map_8_channels) {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
+ } else {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
+ val |= BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT;
- axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
+ axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, (u32)val);
+ }
}
do {
@@ -1210,18 +1270,32 @@ static int dma_chan_pause(struct dma_chan *dchan)
/* Called in chan locked context */
static inline void axi_chan_resume(struct axi_dma_chan *chan)
{
- u32 val;
-
- if (chan->chip->dw->hdata->reg_map_8_channels) {
- val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
- val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
- val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
- axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+ u64 val;
+
+ if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
+ val = axi_dma_ioread64(chan->chip, DMAC_CHSUSPREG);
+ if (chan->id >= DMAC_CHAN_16) {
+ val &= ~((u64)(BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_SUSP2_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
+ val |= ((u64)(BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_SUSP2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
+ } else {
+ val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
+ val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
+ }
+ axi_dma_iowrite64(chan->chip, DMAC_CHSUSPREG, val);
} else {
- val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
- val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
- val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
- axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
+ if (chan->chip->dw->hdata->reg_map_8_channels) {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
+ val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
+ } else {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
+ val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
+ val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
+ axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, (u32)val);
+ }
}
chan->is_paused = false;
@@ -1535,7 +1609,7 @@ err_pm_disable:
return ret;
}
-static int dw_remove(struct platform_device *pdev)
+static void dw_remove(struct platform_device *pdev)
{
struct axi_dma_chip *chip = platform_get_drvdata(pdev);
struct dw_axi_dma *dw = chip->dw;
@@ -1564,8 +1638,6 @@ static int dw_remove(struct platform_device *pdev)
list_del(&chan->vc.chan.device_node);
tasklet_kill(&chan->vc.task);
}
-
- return 0;
}
static const struct dev_pm_ops dw_axi_dma_pm_ops = {
@@ -1588,7 +1660,7 @@ MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
static struct platform_driver dw_driver = {
.probe = dw_probe,
- .remove = dw_remove,
+ .remove_new = dw_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = dw_dma_of_id_table,
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
index eb267cb24f67..454904d99654 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
@@ -18,7 +18,7 @@
#include "../virt-dma.h"
-#define DMAC_MAX_CHANNELS 16
+#define DMAC_MAX_CHANNELS 32
#define DMAC_MAX_MASTERS 2
#define DMAC_MAX_BLK_SIZE 0x200000
@@ -222,6 +222,10 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
/* DMAC_CHEN2 */
#define DMAC_CHAN_EN2_WE_SHIFT 16
+/* DMAC CHAN BLOCKS */
+#define DMAC_CHAN_BLOCK_SHIFT 32
+#define DMAC_CHAN_16 16
+
/* DMAC_CHSUSP */
#define DMAC_CHAN_SUSP2_SHIFT 0
#define DMAC_CHAN_SUSP2_WE_SHIFT 16
diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c
index 47f2292dba98..7d9d4c951724 100644
--- a/drivers/dma/dw/platform.c
+++ b/drivers/dma/dw/platform.c
@@ -93,7 +93,7 @@ err_dw_dma_probe:
return err;
}
-static int dw_remove(struct platform_device *pdev)
+static void dw_remove(struct platform_device *pdev)
{
struct dw_dma_chip_pdata *data = platform_get_drvdata(pdev);
struct dw_dma_chip *chip = data->chip;
@@ -109,8 +109,6 @@ static int dw_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(chip->clk);
-
- return 0;
}
static void dw_shutdown(struct platform_device *pdev)
@@ -193,7 +191,7 @@ static const struct dev_pm_ops dw_dev_pm_ops = {
static struct platform_driver dw_driver = {
.probe = dw_probe,
- .remove = dw_remove,
+ .remove_new = dw_remove,
.shutdown = dw_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index 5c4a448a1254..d6c60635e90d 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -213,7 +213,7 @@ struct ep93xx_dma_engine {
#define INTERRUPT_NEXT_BUFFER 2
size_t num_channels;
- struct ep93xx_dma_chan channels[];
+ struct ep93xx_dma_chan channels[] __counted_by(num_channels);
};
static inline struct device *chan2dev(struct ep93xx_dma_chan *edmac)
diff --git a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c
index a42a37634881..7958ac33e36c 100644
--- a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c
+++ b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c
@@ -814,7 +814,6 @@ static const struct fsl_mc_device_id dpaa2_qdma_id_table[] = {
static struct fsl_mc_driver dpaa2_qdma_driver = {
.driver = {
.name = "dpaa2-qdma",
- .owner = THIS_MODULE,
},
.probe = dpaa2_qdma_probe,
.remove = dpaa2_qdma_remove,
diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
index a0f5741abcc4..b53f46245c37 100644
--- a/drivers/dma/fsl-edma-common.c
+++ b/drivers/dma/fsl-edma-common.c
@@ -92,8 +92,14 @@ static void fsl_edma3_enable_request(struct fsl_edma_chan *fsl_chan)
edma_writel_chreg(fsl_chan, val, ch_sbr);
- if (flags & FSL_EDMA_DRV_HAS_CHMUX)
- edma_writel_chreg(fsl_chan, fsl_chan->srcid, ch_mux);
+ if (flags & FSL_EDMA_DRV_HAS_CHMUX) {
+ /*
+ * ch_mux: With the exception of 0, attempts to write a value
+ * already in use will be forced to 0.
+ */
+ if (!edma_readl_chreg(fsl_chan, ch_mux))
+ edma_writel_chreg(fsl_chan, fsl_chan->srcid, ch_mux);
+ }
val = edma_readl_chreg(fsl_chan, ch_csr);
val |= EDMA_V3_CH_CSR_ERQ;
@@ -448,12 +454,25 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
edma_write_tcdreg(fsl_chan, tcd->dlast_sga, dlast_sga);
+ csr = le16_to_cpu(tcd->csr);
+
if (fsl_chan->is_sw) {
- csr = le16_to_cpu(tcd->csr);
csr |= EDMA_TCD_CSR_START;
tcd->csr = cpu_to_le16(csr);
}
+ /*
+ * Must clear CHn_CSR[DONE] bit before enable TCDn_CSR[ESG] at EDMAv3
+ * eDMAv4 have not such requirement.
+ * Change MLINK need clear CHn_CSR[DONE] for both eDMAv3 and eDMAv4.
+ */
+ if (((fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_CLEAR_DONE_E_SG) &&
+ (csr & EDMA_TCD_CSR_E_SG)) ||
+ ((fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_CLEAR_DONE_E_LINK) &&
+ (csr & EDMA_TCD_CSR_E_LINK)))
+ edma_writel_chreg(fsl_chan, edma_readl_chreg(fsl_chan, ch_csr), ch_csr);
+
+
edma_write_tcdreg(fsl_chan, tcd->csr, csr);
}
@@ -809,6 +828,7 @@ void fsl_edma_free_chan_resources(struct dma_chan *chan)
dma_pool_destroy(fsl_chan->tcd_pool);
fsl_chan->tcd_pool = NULL;
fsl_chan->is_sw = false;
+ fsl_chan->srcid = 0;
}
void fsl_edma_cleanup_vchan(struct dma_device *dmadev)
diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
index 3cc0cc8fc2d0..bb5221158a77 100644
--- a/drivers/dma/fsl-edma-common.h
+++ b/drivers/dma/fsl-edma-common.h
@@ -183,11 +183,23 @@ struct fsl_edma_desc {
#define FSL_EDMA_DRV_BUS_8BYTE BIT(10)
#define FSL_EDMA_DRV_DEV_TO_DEV BIT(11)
#define FSL_EDMA_DRV_ALIGN_64BYTE BIT(12)
+/* Need clean CHn_CSR DONE before enable TCD's ESG */
+#define FSL_EDMA_DRV_CLEAR_DONE_E_SG BIT(13)
+/* Need clean CHn_CSR DONE before enable TCD's MAJORELINK */
+#define FSL_EDMA_DRV_CLEAR_DONE_E_LINK BIT(14)
#define FSL_EDMA_DRV_EDMA3 (FSL_EDMA_DRV_SPLIT_REG | \
FSL_EDMA_DRV_BUS_8BYTE | \
FSL_EDMA_DRV_DEV_TO_DEV | \
- FSL_EDMA_DRV_ALIGN_64BYTE)
+ FSL_EDMA_DRV_ALIGN_64BYTE | \
+ FSL_EDMA_DRV_CLEAR_DONE_E_SG | \
+ FSL_EDMA_DRV_CLEAR_DONE_E_LINK)
+
+#define FSL_EDMA_DRV_EDMA4 (FSL_EDMA_DRV_SPLIT_REG | \
+ FSL_EDMA_DRV_BUS_8BYTE | \
+ FSL_EDMA_DRV_DEV_TO_DEV | \
+ FSL_EDMA_DRV_ALIGN_64BYTE | \
+ FSL_EDMA_DRV_CLEAR_DONE_E_LINK)
struct fsl_edma_drvdata {
u32 dmamuxs; /* only used before v3 */
@@ -213,7 +225,7 @@ struct fsl_edma_engine {
bool big_endian;
struct edma_regs regs;
u64 chan_masked;
- struct fsl_edma_chan chans[];
+ struct fsl_edma_chan chans[] __counted_by(n_chans);
};
#define edma_read_tcdreg(chan, __name) \
diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
index 63d48d046f04..238a69bd0d6f 100644
--- a/drivers/dma/fsl-edma-main.c
+++ b/drivers/dma/fsl-edma-main.c
@@ -13,13 +13,11 @@
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
#include <linux/of_dma.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/pm_domain.h>
+#include <linux/property.h>
#include "fsl-edma-common.h"
@@ -154,18 +152,20 @@ static struct dma_chan *fsl_edma3_xlate(struct of_phandle_args *dma_spec,
fsl_chan = to_fsl_edma_chan(chan);
i = fsl_chan - fsl_edma->chans;
- chan = dma_get_slave_channel(chan);
- chan->device->privatecnt++;
fsl_chan->priority = dma_spec->args[1];
fsl_chan->is_rxchan = dma_spec->args[2] & ARGS_RX;
fsl_chan->is_remote = dma_spec->args[2] & ARGS_REMOTE;
fsl_chan->is_multi_fifo = dma_spec->args[2] & ARGS_MULTI_FIFO;
if (!b_chmux && i == dma_spec->args[0]) {
+ chan = dma_get_slave_channel(chan);
+ chan->device->privatecnt++;
mutex_unlock(&fsl_edma->fsl_edma_mutex);
return chan;
} else if (b_chmux && !fsl_chan->srcid) {
/* if controller support channel mux, choose a free channel */
+ chan = dma_get_slave_channel(chan);
+ chan->device->privatecnt++;
fsl_chan->srcid = dma_spec->args[0];
mutex_unlock(&fsl_edma->fsl_edma_mutex);
return chan;
@@ -230,10 +230,8 @@ static int fsl_edma3_irq_init(struct platform_device *pdev, struct fsl_edma_engi
/* request channel irq */
fsl_chan->txirq = platform_get_irq(pdev, i);
- if (fsl_chan->txirq < 0) {
- dev_err(&pdev->dev, "Can't get chan %d's irq.\n", i);
+ if (fsl_chan->txirq < 0)
return -EINVAL;
- }
ret = devm_request_irq(&pdev->dev, fsl_chan->txirq,
fsl_edma3_tx_handler, IRQF_SHARED,
@@ -355,7 +353,7 @@ static struct fsl_edma_drvdata imx93_data3 = {
};
static struct fsl_edma_drvdata imx93_data4 = {
- .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA3,
+ .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4,
.chreg_space_sz = 0x8000,
.chreg_off = 0x10000,
.setup_irq = fsl_edma3_irq_init,
@@ -398,9 +396,8 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
DL_FLAG_PM_RUNTIME |
DL_FLAG_RPM_ACTIVE);
- if (IS_ERR(link)) {
- dev_err(dev, "Failed to add device_link to %d: %ld\n", i,
- PTR_ERR(link));
+ if (!link) {
+ dev_err(dev, "Failed to add device_link to %d\n", i);
return -EINVAL;
}
@@ -416,8 +413,6 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
static int fsl_edma_probe(struct platform_device *pdev)
{
- const struct of_device_id *of_id =
- of_match_device(fsl_edma_dt_ids, &pdev->dev);
struct device_node *np = pdev->dev.of_node;
struct fsl_edma_engine *fsl_edma;
const struct fsl_edma_drvdata *drvdata = NULL;
@@ -426,8 +421,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
int chans;
int ret, i;
- if (of_id)
- drvdata = of_id->data;
+ drvdata = device_get_match_data(&pdev->dev);
if (!drvdata) {
dev_err(&pdev->dev, "unable to find driver data\n");
return -EINVAL;
@@ -615,7 +609,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
return 0;
}
-static int fsl_edma_remove(struct platform_device *pdev)
+static void fsl_edma_remove(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct fsl_edma_engine *fsl_edma = platform_get_drvdata(pdev);
@@ -625,8 +619,6 @@ static int fsl_edma_remove(struct platform_device *pdev)
of_dma_controller_free(np);
dma_async_device_unregister(&fsl_edma->dma_dev);
fsl_disable_clocks(fsl_edma, fsl_edma->drvdata->dmamuxs);
-
- return 0;
}
static int fsl_edma_suspend_late(struct device *dev)
@@ -638,6 +630,8 @@ static int fsl_edma_suspend_late(struct device *dev)
for (i = 0; i < fsl_edma->n_chans; i++) {
fsl_chan = &fsl_edma->chans[i];
+ if (fsl_edma->chan_masked & BIT(i))
+ continue;
spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
/* Make sure chan is idle or will force disable. */
if (unlikely(!fsl_chan->idle)) {
@@ -662,13 +656,16 @@ static int fsl_edma_resume_early(struct device *dev)
for (i = 0; i < fsl_edma->n_chans; i++) {
fsl_chan = &fsl_edma->chans[i];
+ if (fsl_edma->chan_masked & BIT(i))
+ continue;
fsl_chan->pm_state = RUNNING;
edma_write_tcdreg(fsl_chan, 0, csr);
if (fsl_chan->slave_id != 0)
fsl_edma_chan_mux(fsl_chan, fsl_chan->slave_id, true);
}
- edma_writel(fsl_edma, EDMA_CR_ERGA | EDMA_CR_ERCA, regs->cr);
+ if (!(fsl_edma->drvdata->flags & FSL_EDMA_DRV_SPLIT_REG))
+ edma_writel(fsl_edma, EDMA_CR_ERGA | EDMA_CR_ERCA, regs->cr);
return 0;
}
@@ -690,7 +687,7 @@ static struct platform_driver fsl_edma_driver = {
.pm = &fsl_edma_pm_ops,
},
.probe = fsl_edma_probe,
- .remove = fsl_edma_remove,
+ .remove_new = fsl_edma_remove,
};
static int __init fsl_edma_init(void)
diff --git a/drivers/dma/fsl-qdma.c b/drivers/dma/fsl-qdma.c
index a8cc8a4bc610..47cb28468049 100644
--- a/drivers/dma/fsl-qdma.c
+++ b/drivers/dma/fsl-qdma.c
@@ -1266,7 +1266,7 @@ static void fsl_qdma_cleanup_vchan(struct dma_device *dmadev)
}
}
-static int fsl_qdma_remove(struct platform_device *pdev)
+static void fsl_qdma_remove(struct platform_device *pdev)
{
int i;
struct fsl_qdma_queue *status;
@@ -1283,7 +1283,6 @@ static int fsl_qdma_remove(struct platform_device *pdev)
dma_free_coherent(&pdev->dev, sizeof(struct fsl_qdma_format) *
status->n_cq, status->cq, status->bus_addr);
}
- return 0;
}
static const struct of_device_id fsl_qdma_dt_ids[] = {
@@ -1298,7 +1297,7 @@ static struct platform_driver fsl_qdma_driver = {
.of_match_table = fsl_qdma_dt_ids,
},
.probe = fsl_qdma_probe,
- .remove = fsl_qdma_remove,
+ .remove_new = fsl_qdma_remove,
};
module_platform_driver(fsl_qdma_driver);
diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
index 0b9ca93ce3dc..014ff523d5ec 100644
--- a/drivers/dma/fsl_raid.c
+++ b/drivers/dma/fsl_raid.c
@@ -857,7 +857,7 @@ static void fsl_re_remove_chan(struct fsl_re_chan *chan)
chan->oub_phys_addr);
}
-static int fsl_re_remove(struct platform_device *ofdev)
+static void fsl_re_remove(struct platform_device *ofdev)
{
struct fsl_re_drv_private *re_priv;
struct device *dev;
@@ -872,8 +872,6 @@ static int fsl_re_remove(struct platform_device *ofdev)
/* Unregister the driver */
dma_async_device_unregister(&re_priv->dma_dev);
-
- return 0;
}
static const struct of_device_id fsl_re_ids[] = {
@@ -888,7 +886,7 @@ static struct platform_driver fsl_re_driver = {
.of_match_table = fsl_re_ids,
},
.probe = fsl_re_probe,
- .remove = fsl_re_remove,
+ .remove_new = fsl_re_remove,
};
module_platform_driver(fsl_re_driver);
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index ddcf736d283d..18a6c4bf6275 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1306,7 +1306,7 @@ out_return:
return err;
}
-static int fsldma_of_remove(struct platform_device *op)
+static void fsldma_of_remove(struct platform_device *op)
{
struct fsldma_device *fdev;
unsigned int i;
@@ -1324,8 +1324,6 @@ static int fsldma_of_remove(struct platform_device *op)
iounmap(fdev->regs);
kfree(fdev);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -1406,7 +1404,7 @@ static struct platform_driver fsldma_of_driver = {
#endif
},
.probe = fsldma_of_probe,
- .remove = fsldma_of_remove,
+ .remove_new = fsldma_of_remove,
};
/*----------------------------------------------------------------------------*/
diff --git a/drivers/dma/hisi_dma.c b/drivers/dma/hisi_dma.c
index c1350a36fddd..4c47bff81064 100644
--- a/drivers/dma/hisi_dma.c
+++ b/drivers/dma/hisi_dma.c
@@ -163,7 +163,7 @@ struct hisi_dma_dev {
u32 chan_depth;
enum hisi_dma_reg_layout reg_layout;
void __iomem *queue_base; /* queue region start of register */
- struct hisi_dma_chan chan[];
+ struct hisi_dma_chan chan[] __counted_by(chan_num);
};
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c
index 0ac634a51c5e..78a938969d7d 100644
--- a/drivers/dma/idma64.c
+++ b/drivers/dma/idma64.c
@@ -660,13 +660,11 @@ static int idma64_platform_probe(struct platform_device *pdev)
return 0;
}
-static int idma64_platform_remove(struct platform_device *pdev)
+static void idma64_platform_remove(struct platform_device *pdev)
{
struct idma64_chip *chip = platform_get_drvdata(pdev);
idma64_remove(chip);
-
- return 0;
}
static int __maybe_unused idma64_pm_suspend(struct device *dev)
@@ -691,7 +689,7 @@ static const struct dev_pm_ops idma64_dev_pm_ops = {
static struct platform_driver idma64_platform_driver = {
.probe = idma64_platform_probe,
- .remove = idma64_platform_remove,
+ .remove_new = idma64_platform_remove,
.driver = {
.name = LPSS_IDMA64_DRIVER_NAME,
.pm = &idma64_dev_pm_ops,
diff --git a/drivers/dma/idxd/Makefile b/drivers/dma/idxd/Makefile
index dc096839ac63..c5e679070e46 100644
--- a/drivers/dma/idxd/Makefile
+++ b/drivers/dma/idxd/Makefile
@@ -1,12 +1,12 @@
ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=IDXD
+obj-$(CONFIG_INTEL_IDXD_BUS) += idxd_bus.o
+idxd_bus-y := bus.o
+
obj-$(CONFIG_INTEL_IDXD) += idxd.o
idxd-y := init.o irq.o device.o sysfs.o submit.o dma.o cdev.o debugfs.o
idxd-$(CONFIG_INTEL_IDXD_PERFMON) += perfmon.o
-obj-$(CONFIG_INTEL_IDXD_BUS) += idxd_bus.o
-idxd_bus-y := bus.o
-
obj-$(CONFIG_INTEL_IDXD_COMPAT) += idxd_compat.o
idxd_compat-y := compat.o
diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c
index d32deb9b4e3d..0423655f5a88 100644
--- a/drivers/dma/idxd/cdev.c
+++ b/drivers/dma/idxd/cdev.c
@@ -509,6 +509,7 @@ void idxd_wq_del_cdev(struct idxd_wq *wq)
static int idxd_user_drv_probe(struct idxd_dev *idxd_dev)
{
+ struct device *dev = &idxd_dev->conf_dev;
struct idxd_wq *wq = idxd_dev_to_wq(idxd_dev);
struct idxd_device *idxd = wq->idxd;
int rc;
@@ -536,6 +537,12 @@ static int idxd_user_drv_probe(struct idxd_dev *idxd_dev)
mutex_lock(&wq->wq_lock);
+ if (!idxd_wq_driver_name_match(wq, dev)) {
+ idxd->cmd_status = IDXD_SCMD_WQ_NO_DRV_NAME;
+ rc = -ENODEV;
+ goto wq_err;
+ }
+
wq->wq = create_workqueue(dev_name(wq_confdev(wq)));
if (!wq->wq) {
rc = -ENOMEM;
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
index 22d6f4e455b7..8f754f922217 100644
--- a/drivers/dma/idxd/device.c
+++ b/drivers/dma/idxd/device.c
@@ -477,6 +477,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand,
union idxd_command_reg cmd;
DECLARE_COMPLETION_ONSTACK(done);
u32 stat;
+ unsigned long flags;
if (idxd_device_is_halted(idxd)) {
dev_warn(&idxd->pdev->dev, "Device is HALTED!\n");
@@ -490,7 +491,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand,
cmd.operand = operand;
cmd.int_req = 1;
- spin_lock(&idxd->cmd_lock);
+ spin_lock_irqsave(&idxd->cmd_lock, flags);
wait_event_lock_irq(idxd->cmd_waitq,
!test_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags),
idxd->cmd_lock);
@@ -507,7 +508,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand,
* After command submitted, release lock and go to sleep until
* the command completes via interrupt.
*/
- spin_unlock(&idxd->cmd_lock);
+ spin_unlock_irqrestore(&idxd->cmd_lock, flags);
wait_for_completion(&done);
stat = ioread32(idxd->reg_base + IDXD_CMDSTS_OFFSET);
spin_lock(&idxd->cmd_lock);
diff --git a/drivers/dma/idxd/dma.c b/drivers/dma/idxd/dma.c
index 07623fb0f52f..47a01893cfdb 100644
--- a/drivers/dma/idxd/dma.c
+++ b/drivers/dma/idxd/dma.c
@@ -306,6 +306,12 @@ static int idxd_dmaengine_drv_probe(struct idxd_dev *idxd_dev)
return -ENXIO;
mutex_lock(&wq->wq_lock);
+ if (!idxd_wq_driver_name_match(wq, dev)) {
+ idxd->cmd_status = IDXD_SCMD_WQ_NO_DRV_NAME;
+ rc = -ENODEV;
+ goto err;
+ }
+
wq->type = IDXD_WQT_KERNEL;
rc = drv_enable_wq(wq);
diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h
index e269ca1f4862..1e89c80a07fc 100644
--- a/drivers/dma/idxd/idxd.h
+++ b/drivers/dma/idxd/idxd.h
@@ -159,6 +159,8 @@ struct idxd_cdev {
int minor;
};
+#define DRIVER_NAME_SIZE 128
+
#define IDXD_ALLOCATED_BATCH_SIZE 128U
#define WQ_NAME_SIZE 1024
#define WQ_TYPE_SIZE 10
@@ -227,6 +229,8 @@ struct idxd_wq {
/* Lock to protect upasid_xa access. */
struct mutex uc_lock;
struct xarray upasid_xa;
+
+ char driver_name[DRIVER_NAME_SIZE + 1];
};
struct idxd_engine {
@@ -646,6 +650,11 @@ static inline void idxd_wqcfg_set_max_batch_shift(int idxd_type, union wqcfg *wq
wqcfg->max_batch_shift = max_batch_shift;
}
+static inline int idxd_wq_driver_name_match(struct idxd_wq *wq, struct device *dev)
+{
+ return (strncmp(wq->driver_name, dev->driver->name, strlen(dev->driver->name)) == 0);
+}
+
int __must_check __idxd_driver_register(struct idxd_device_driver *idxd_drv,
struct module *module, const char *mod_name);
#define idxd_driver_register(driver) \
diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c
index b501320a9c7a..2183d7f9cdbd 100644
--- a/drivers/dma/idxd/irq.c
+++ b/drivers/dma/idxd/irq.c
@@ -434,8 +434,8 @@ irqreturn_t idxd_misc_thread(int vec, void *data)
val |= IDXD_INTC_ERR;
for (i = 0; i < 4; i++)
- dev_warn(dev, "err[%d]: %#16.16llx\n",
- i, idxd->sw_err.bits[i]);
+ dev_warn_ratelimited(dev, "err[%d]: %#16.16llx\n",
+ i, idxd->sw_err.bits[i]);
err = true;
}
diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h
index 7b54a3939ea1..315c004f58e4 100644
--- a/drivers/dma/idxd/registers.h
+++ b/drivers/dma/idxd/registers.h
@@ -440,12 +440,14 @@ union wqcfg {
/*
* This macro calculates the offset into the GRPCFG register
* idxd - struct idxd *
- * n - wq id
- * ofs - the index of the 32b dword for the config register
+ * n - group id
+ * ofs - the index of the 64b qword for the config register
*
- * The WQCFG register block is divided into groups per each wq. The n index
- * allows us to move to the register group that's for that particular wq.
- * Each register is 32bits. The ofs gives us the number of register to access.
+ * The GRPCFG register block is divided into three sub-registers, which
+ * are GRPWQCFG, GRPENGCFG and GRPFLGCFG. The n index allows us to move
+ * to the register block that contains the three sub-registers.
+ * Each register block is 64bits. And the ofs gives us the offset
+ * within the GRPWQCFG register to access.
*/
#define GRPWQCFG_OFFSET(idxd_dev, n, ofs) ((idxd_dev)->grpcfg_offset +\
(n) * GRPCFG_SIZE + sizeof(u64) * (ofs))
diff --git a/drivers/dma/idxd/submit.c b/drivers/dma/idxd/submit.c
index c01db23e3333..3f922518e3a5 100644
--- a/drivers/dma/idxd/submit.c
+++ b/drivers/dma/idxd/submit.c
@@ -183,13 +183,6 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
portal = idxd_wq_portal_addr(wq);
/*
- * The wmb() flushes writes to coherent DMA data before
- * possibly triggering a DMA read. The wmb() is necessary
- * even on UP because the recipient is a device.
- */
- wmb();
-
- /*
* Pending the descriptor to the lockless list for the irq_entry
* that we designated the descriptor to.
*/
@@ -199,6 +192,13 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
llist_add(&desc->llnode, &ie->pending_llist);
}
+ /*
+ * The wmb() flushes writes to coherent DMA data before
+ * possibly triggering a DMA read. The wmb() is necessary
+ * even on UP because the recipient is a device.
+ */
+ wmb();
+
if (wq_dedicated(wq)) {
iosubmit_cmds512(portal, desc->hw, 1);
} else {
diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c
index 7caba90d85b3..523ae0dff7d4 100644
--- a/drivers/dma/idxd/sysfs.c
+++ b/drivers/dma/idxd/sysfs.c
@@ -1259,6 +1259,39 @@ err:
static struct device_attribute dev_attr_wq_op_config =
__ATTR(op_config, 0644, wq_op_config_show, wq_op_config_store);
+static ssize_t wq_driver_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct idxd_wq *wq = confdev_to_wq(dev);
+
+ return sysfs_emit(buf, "%s\n", wq->driver_name);
+}
+
+static ssize_t wq_driver_name_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct idxd_wq *wq = confdev_to_wq(dev);
+ char *input, *pos;
+
+ if (wq->state != IDXD_WQ_DISABLED)
+ return -EPERM;
+
+ if (strlen(buf) > DRIVER_NAME_SIZE || strlen(buf) == 0)
+ return -EINVAL;
+
+ input = kstrndup(buf, count, GFP_KERNEL);
+ if (!input)
+ return -ENOMEM;
+
+ pos = strim(input);
+ memset(wq->driver_name, 0, DRIVER_NAME_SIZE + 1);
+ sprintf(wq->driver_name, "%s", pos);
+ kfree(input);
+ return count;
+}
+
+static struct device_attribute dev_attr_wq_driver_name =
+ __ATTR(driver_name, 0644, wq_driver_name_show, wq_driver_name_store);
+
static struct attribute *idxd_wq_attributes[] = {
&dev_attr_wq_clients.attr,
&dev_attr_wq_state.attr,
@@ -1278,6 +1311,7 @@ static struct attribute *idxd_wq_attributes[] = {
&dev_attr_wq_occupancy.attr,
&dev_attr_wq_enqcmds_retries.attr,
&dev_attr_wq_op_config.attr,
+ &dev_attr_wq_driver_name.attr,
NULL,
};
diff --git a/drivers/dma/img-mdc-dma.c b/drivers/dma/img-mdc-dma.c
index 9be0d3226e19..0532dd2640dc 100644
--- a/drivers/dma/img-mdc-dma.c
+++ b/drivers/dma/img-mdc-dma.c
@@ -1017,7 +1017,7 @@ suspend:
return ret;
}
-static int mdc_dma_remove(struct platform_device *pdev)
+static void mdc_dma_remove(struct platform_device *pdev)
{
struct mdc_dma *mdma = platform_get_drvdata(pdev);
struct mdc_chan *mchan, *next;
@@ -1037,8 +1037,6 @@ static int mdc_dma_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
img_mdc_runtime_suspend(&pdev->dev);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1078,7 +1076,7 @@ static struct platform_driver mdc_dma_driver = {
.of_match_table = of_match_ptr(mdc_dma_of_match),
},
.probe = mdc_dma_probe,
- .remove = mdc_dma_remove,
+ .remove_new = mdc_dma_remove,
};
module_platform_driver(mdc_dma_driver);
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 114f254b9f50..ebf7c115d553 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -1216,7 +1216,7 @@ static void imxdma_free_irq(struct platform_device *pdev, struct imxdma_engine *
}
}
-static int imxdma_remove(struct platform_device *pdev)
+static void imxdma_remove(struct platform_device *pdev)
{
struct imxdma_engine *imxdma = platform_get_drvdata(pdev);
@@ -1229,8 +1229,6 @@ static int imxdma_remove(struct platform_device *pdev)
clk_disable_unprepare(imxdma->dma_ipg);
clk_disable_unprepare(imxdma->dma_ahb);
-
- return 0;
}
static struct platform_driver imxdma_driver = {
@@ -1238,7 +1236,7 @@ static struct platform_driver imxdma_driver = {
.name = "imx-dma",
.of_match_table = imx_dma_of_dev_id,
},
- .remove = imxdma_remove,
+ .remove_new = imxdma_remove,
};
static int __init imxdma_module_init(void)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 51012bd39900..f81ecf5863e8 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2358,7 +2358,7 @@ err_clk:
return ret;
}
-static int sdma_remove(struct platform_device *pdev)
+static void sdma_remove(struct platform_device *pdev)
{
struct sdma_engine *sdma = platform_get_drvdata(pdev);
int i;
@@ -2377,7 +2377,6 @@ static int sdma_remove(struct platform_device *pdev)
}
platform_set_drvdata(pdev, NULL);
- return 0;
}
static struct platform_driver sdma_driver = {
@@ -2385,7 +2384,7 @@ static struct platform_driver sdma_driver = {
.name = "imx-sdma",
.of_match_table = sdma_dt_ids,
},
- .remove = sdma_remove,
+ .remove_new = sdma_remove,
.probe = sdma_probe,
};
diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c
index ecdaada95120..5de8c21d41e7 100644
--- a/drivers/dma/k3dma.c
+++ b/drivers/dma/k3dma.c
@@ -15,7 +15,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/clk.h>
#include <linux/of_dma.h>
@@ -839,7 +838,6 @@ static int k3_dma_probe(struct platform_device *op)
{
const struct k3dma_soc_data *soc_data;
struct k3_dma_dev *d;
- const struct of_device_id *of_id;
int i, ret, irq = 0;
d = devm_kzalloc(&op->dev, sizeof(*d), GFP_KERNEL);
@@ -854,19 +852,16 @@ static int k3_dma_probe(struct platform_device *op)
if (IS_ERR(d->base))
return PTR_ERR(d->base);
- of_id = of_match_device(k3_pdma_dt_ids, &op->dev);
- if (of_id) {
- of_property_read_u32((&op->dev)->of_node,
- "dma-channels", &d->dma_channels);
- of_property_read_u32((&op->dev)->of_node,
- "dma-requests", &d->dma_requests);
- ret = of_property_read_u32((&op->dev)->of_node,
- "dma-channel-mask", &d->dma_channel_mask);
- if (ret) {
- dev_warn(&op->dev,
- "dma-channel-mask doesn't exist, considering all as available.\n");
- d->dma_channel_mask = (u32)~0UL;
- }
+ of_property_read_u32((&op->dev)->of_node,
+ "dma-channels", &d->dma_channels);
+ of_property_read_u32((&op->dev)->of_node,
+ "dma-requests", &d->dma_requests);
+ ret = of_property_read_u32((&op->dev)->of_node,
+ "dma-channel-mask", &d->dma_channel_mask);
+ if (ret) {
+ dev_warn(&op->dev,
+ "dma-channel-mask doesn't exist, considering all as available.\n");
+ d->dma_channel_mask = (u32)~0UL;
}
if (!(soc_data->flags & K3_FLAG_NOCLK)) {
@@ -974,7 +969,7 @@ dma_async_register_fail:
return ret;
}
-static int k3_dma_remove(struct platform_device *op)
+static void k3_dma_remove(struct platform_device *op)
{
struct k3_dma_chan *c, *cn;
struct k3_dma_dev *d = platform_get_drvdata(op);
@@ -990,7 +985,6 @@ static int k3_dma_remove(struct platform_device *op)
}
tasklet_kill(&d->task);
clk_disable_unprepare(d->clk);
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1034,7 +1028,7 @@ static struct platform_driver k3_pdma_driver = {
.of_match_table = k3_pdma_dt_ids,
},
.probe = k3_dma_probe,
- .remove = k3_dma_remove,
+ .remove_new = k3_dma_remove,
};
module_platform_driver(k3_pdma_driver);
diff --git a/drivers/dma/mcf-edma-main.c b/drivers/dma/mcf-edma-main.c
index b359421ee9ea..ab21455d9c3a 100644
--- a/drivers/dma/mcf-edma-main.c
+++ b/drivers/dma/mcf-edma-main.c
@@ -255,15 +255,13 @@ static int mcf_edma_probe(struct platform_device *pdev)
return 0;
}
-static int mcf_edma_remove(struct platform_device *pdev)
+static void mcf_edma_remove(struct platform_device *pdev)
{
struct fsl_edma_engine *mcf_edma = platform_get_drvdata(pdev);
mcf_edma_irq_free(pdev, mcf_edma);
fsl_edma_cleanup_vchan(&mcf_edma->dma_dev);
dma_async_device_unregister(&mcf_edma->dma_dev);
-
- return 0;
}
static struct platform_driver mcf_edma_driver = {
@@ -271,7 +269,7 @@ static struct platform_driver mcf_edma_driver = {
.name = "mcf-edma",
},
.probe = mcf_edma_probe,
- .remove = mcf_edma_remove,
+ .remove_new = mcf_edma_remove,
};
bool mcf_edma_filter_fn(struct dma_chan *chan, void *param)
diff --git a/drivers/dma/mediatek/mtk-cqdma.c b/drivers/dma/mediatek/mtk-cqdma.c
index 324b7387b1b9..529100c5b9f5 100644
--- a/drivers/dma/mediatek/mtk-cqdma.c
+++ b/drivers/dma/mediatek/mtk-cqdma.c
@@ -885,7 +885,7 @@ err_unregister:
return err;
}
-static int mtk_cqdma_remove(struct platform_device *pdev)
+static void mtk_cqdma_remove(struct platform_device *pdev)
{
struct mtk_cqdma_device *cqdma = platform_get_drvdata(pdev);
struct mtk_cqdma_vchan *vc;
@@ -918,13 +918,11 @@ static int mtk_cqdma_remove(struct platform_device *pdev)
dma_async_device_unregister(&cqdma->ddev);
of_dma_controller_free(pdev->dev.of_node);
-
- return 0;
}
static struct platform_driver mtk_cqdma_driver = {
.probe = mtk_cqdma_probe,
- .remove = mtk_cqdma_remove,
+ .remove_new = mtk_cqdma_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = mtk_cqdma_match,
diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c
index 64120767d983..36ff11e909ea 100644
--- a/drivers/dma/mediatek/mtk-hsdma.c
+++ b/drivers/dma/mediatek/mtk-hsdma.c
@@ -1009,7 +1009,7 @@ err_unregister:
return err;
}
-static int mtk_hsdma_remove(struct platform_device *pdev)
+static void mtk_hsdma_remove(struct platform_device *pdev)
{
struct mtk_hsdma_device *hsdma = platform_get_drvdata(pdev);
struct mtk_hsdma_vchan *vc;
@@ -1034,13 +1034,11 @@ static int mtk_hsdma_remove(struct platform_device *pdev)
dma_async_device_unregister(&hsdma->ddev);
of_dma_controller_free(pdev->dev.of_node);
-
- return 0;
}
static struct platform_driver mtk_hsdma_driver = {
.probe = mtk_hsdma_probe,
- .remove = mtk_hsdma_remove,
+ .remove_new = mtk_hsdma_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = mtk_hsdma_match,
diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c
index c51dc017b48a..1bdc1500be40 100644
--- a/drivers/dma/mediatek/mtk-uart-apdma.c
+++ b/drivers/dma/mediatek/mtk-uart-apdma.c
@@ -450,9 +450,8 @@ static int mtk_uart_apdma_device_pause(struct dma_chan *chan)
mtk_uart_apdma_write(c, VFF_EN, VFF_EN_CLR_B);
mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B);
- synchronize_irq(c->irq);
-
spin_unlock_irqrestore(&c->vc.lock, flags);
+ synchronize_irq(c->irq);
return 0;
}
@@ -573,7 +572,7 @@ err_no_dma:
return rc;
}
-static int mtk_uart_apdma_remove(struct platform_device *pdev)
+static void mtk_uart_apdma_remove(struct platform_device *pdev)
{
struct mtk_uart_apdmadev *mtkd = platform_get_drvdata(pdev);
@@ -584,8 +583,6 @@ static int mtk_uart_apdma_remove(struct platform_device *pdev)
dma_async_device_unregister(&mtkd->ddev);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -640,7 +637,7 @@ static const struct dev_pm_ops mtk_uart_apdma_pm_ops = {
static struct platform_driver mtk_uart_apdma_driver = {
.probe = mtk_uart_apdma_probe,
- .remove = mtk_uart_apdma_remove,
+ .remove_new = mtk_uart_apdma_remove,
.driver = {
.name = KBUILD_MODNAME,
.pm = &mtk_uart_apdma_pm_ops,
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index ebdfdcbb4f7a..136fcaeff8dd 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -15,7 +15,6 @@
#include <linux/device.h>
#include <linux/platform_data/mmp_dma.h>
#include <linux/dmapool.h>
-#include <linux/of_device.h>
#include <linux/of_dma.h>
#include <linux/of.h>
@@ -932,7 +931,7 @@ static void dma_do_tasklet(struct tasklet_struct *t)
}
}
-static int mmp_pdma_remove(struct platform_device *op)
+static void mmp_pdma_remove(struct platform_device *op)
{
struct mmp_pdma_device *pdev = platform_get_drvdata(op);
struct mmp_pdma_phy *phy;
@@ -958,7 +957,6 @@ static int mmp_pdma_remove(struct platform_device *op)
}
dma_async_device_unregister(&pdev->device);
- return 0;
}
static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev, int idx, int irq)
@@ -1020,7 +1018,6 @@ static struct dma_chan *mmp_pdma_dma_xlate(struct of_phandle_args *dma_spec,
static int mmp_pdma_probe(struct platform_device *op)
{
struct mmp_pdma_device *pdev;
- const struct of_device_id *of_id;
struct mmp_dma_platdata *pdata = dev_get_platdata(&op->dev);
int i, ret, irq = 0;
int dma_channels = 0, irq_num = 0;
@@ -1040,8 +1037,7 @@ static int mmp_pdma_probe(struct platform_device *op)
if (IS_ERR(pdev->base))
return PTR_ERR(pdev->base);
- of_id = of_match_device(mmp_pdma_dt_ids, pdev->dev);
- if (of_id) {
+ if (pdev->dev->of_node) {
/* Parse new and deprecated dma-channels properties */
if (of_property_read_u32(pdev->dev->of_node, "dma-channels",
&dma_channels))
@@ -1141,7 +1137,7 @@ static struct platform_driver mmp_pdma_driver = {
},
.id_table = mmp_pdma_id_table,
.probe = mmp_pdma_probe,
- .remove = mmp_pdma_remove,
+ .remove_new = mmp_pdma_remove,
};
module_platform_driver(mmp_pdma_driver);
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
index d49fa6bc6775..b76fe99e1151 100644
--- a/drivers/dma/mmp_tdma.c
+++ b/drivers/dma/mmp_tdma.c
@@ -14,9 +14,9 @@
#include <linux/slab.h>
#include <linux/dmaengine.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/device.h>
#include <linux/genalloc.h>
-#include <linux/of_device.h>
#include <linux/of_dma.h>
#include "dmaengine.h"
@@ -552,12 +552,10 @@ static void mmp_tdma_issue_pending(struct dma_chan *chan)
mmp_tdma_enable_chan(tdmac);
}
-static int mmp_tdma_remove(struct platform_device *pdev)
+static void mmp_tdma_remove(struct platform_device *pdev)
{
if (pdev->dev.of_node)
of_dma_controller_free(pdev->dev.of_node);
-
- return 0;
}
static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
@@ -637,18 +635,13 @@ MODULE_DEVICE_TABLE(of, mmp_tdma_dt_ids);
static int mmp_tdma_probe(struct platform_device *pdev)
{
enum mmp_tdma_type type;
- const struct of_device_id *of_id;
struct mmp_tdma_device *tdev;
int i, ret;
int irq = 0, irq_num = 0;
int chan_num = TDMA_CHANNEL_NUM;
struct gen_pool *pool = NULL;
- of_id = of_match_device(mmp_tdma_dt_ids, &pdev->dev);
- if (of_id)
- type = (enum mmp_tdma_type) of_id->data;
- else
- type = platform_get_device_id(pdev)->driver_data;
+ type = (enum mmp_tdma_type)device_get_match_data(&pdev->dev);
/* always have couple channels */
tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
@@ -726,34 +719,24 @@ static int mmp_tdma_probe(struct platform_device *pdev)
return ret;
}
- if (pdev->dev.of_node) {
- ret = of_dma_controller_register(pdev->dev.of_node,
- mmp_tdma_xlate, tdev);
- if (ret) {
- dev_err(tdev->device.dev,
- "failed to register controller\n");
- return ret;
- }
+ ret = of_dma_controller_register(pdev->dev.of_node,
+ mmp_tdma_xlate, tdev);
+ if (ret) {
+ dev_err(tdev->device.dev, "failed to register controller\n");
+ return ret;
}
dev_info(tdev->device.dev, "initialized\n");
return 0;
}
-static const struct platform_device_id mmp_tdma_id_table[] = {
- { "mmp-adma", MMP_AUD_TDMA },
- { "pxa910-squ", PXA910_SQU },
- { },
-};
-
static struct platform_driver mmp_tdma_driver = {
.driver = {
.name = "mmp-tdma",
.of_match_table = mmp_tdma_dt_ids,
},
- .id_table = mmp_tdma_id_table,
.probe = mmp_tdma_probe,
- .remove = mmp_tdma_remove,
+ .remove_new = mmp_tdma_remove,
};
module_platform_driver(mmp_tdma_driver);
diff --git a/drivers/dma/moxart-dma.c b/drivers/dma/moxart-dma.c
index 7565ad98ba66..c48d68cbff92 100644
--- a/drivers/dma/moxart-dma.c
+++ b/drivers/dma/moxart-dma.c
@@ -124,7 +124,7 @@ struct moxart_desc {
unsigned int dma_cycles;
struct virt_dma_desc vd;
uint8_t es;
- struct moxart_sg sg[];
+ struct moxart_sg sg[] __counted_by(sglen);
};
struct moxart_chan {
@@ -309,6 +309,7 @@ static struct dma_async_tx_descriptor *moxart_prep_slave_sg(
d = kzalloc(struct_size(d, sg, sg_len), GFP_ATOMIC);
if (!d)
return NULL;
+ d->sglen = sg_len;
d->dma_dir = dir;
d->dev_addr = dev_addr;
@@ -319,8 +320,6 @@ static struct dma_async_tx_descriptor *moxart_prep_slave_sg(
d->sg[i].len = sg_dma_len(sgent);
}
- d->sglen = sg_len;
-
ch->error = 0;
return vchan_tx_prep(&ch->vc, &d->vd, tx_flags);
@@ -630,7 +629,7 @@ static int moxart_probe(struct platform_device *pdev)
return 0;
}
-static int moxart_remove(struct platform_device *pdev)
+static void moxart_remove(struct platform_device *pdev)
{
struct moxart_dmadev *m = platform_get_drvdata(pdev);
@@ -640,8 +639,6 @@ static int moxart_remove(struct platform_device *pdev)
if (pdev->dev.of_node)
of_dma_controller_free(pdev->dev.of_node);
-
- return 0;
}
static const struct of_device_id moxart_dma_match[] = {
@@ -652,7 +649,7 @@ MODULE_DEVICE_TABLE(of, moxart_dma_match);
static struct platform_driver moxart_driver = {
.probe = moxart_probe,
- .remove = moxart_remove,
+ .remove_new = moxart_remove,
.driver = {
.name = "moxart-dma-engine",
.of_match_table = moxart_dma_match,
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 1104017320b8..68c247a46321 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -1084,7 +1084,7 @@ err:
return retval;
}
-static int mpc_dma_remove(struct platform_device *op)
+static void mpc_dma_remove(struct platform_device *op)
{
struct device *dev = &op->dev;
struct mpc_dma *mdma = dev_get_drvdata(dev);
@@ -1099,8 +1099,6 @@ static int mpc_dma_remove(struct platform_device *op)
free_irq(mdma->irq, mdma);
irq_dispose_mapping(mdma->irq);
tasklet_kill(&mdma->tasklet);
-
- return 0;
}
static const struct of_device_id mpc_dma_match[] = {
@@ -1112,7 +1110,7 @@ MODULE_DEVICE_TABLE(of, mpc_dma_match);
static struct platform_driver mpc_dma_driver = {
.probe = mpc_dma_probe,
- .remove = mpc_dma_remove,
+ .remove_new = mpc_dma_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = mpc_dma_match,
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 23b232b57518..bcd3b623ac6c 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -10,8 +10,8 @@
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/memory.h>
#include <linux/clk.h>
#include <linux/of.h>
@@ -1328,13 +1328,8 @@ static int mv_xor_probe(struct platform_device *pdev)
* setting up. In non-dt case it can only be the legacy one.
*/
xordev->xor_type = XOR_ORION;
- if (pdev->dev.of_node) {
- const struct of_device_id *of_id =
- of_match_device(mv_xor_dt_ids,
- &pdev->dev);
-
- xordev->xor_type = (uintptr_t)of_id->data;
- }
+ if (pdev->dev.of_node)
+ xordev->xor_type = (uintptr_t)device_get_match_data(&pdev->dev);
/*
* (Re-)program MBUS remapping windows if we are asked to.
diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c
index 0e1e9ca1c005..1ebfbe88e733 100644
--- a/drivers/dma/mv_xor_v2.c
+++ b/drivers/dma/mv_xor_v2.c
@@ -855,7 +855,7 @@ free_msi_irqs:
return ret;
}
-static int mv_xor_v2_remove(struct platform_device *pdev)
+static void mv_xor_v2_remove(struct platform_device *pdev)
{
struct mv_xor_v2_device *xor_dev = platform_get_drvdata(pdev);
@@ -870,8 +870,6 @@ static int mv_xor_v2_remove(struct platform_device *pdev)
platform_msi_domain_free_irqs(&pdev->dev);
tasklet_kill(&xor_dev->irq_tasklet);
-
- return 0;
}
#ifdef CONFIG_OF
@@ -886,7 +884,7 @@ static struct platform_driver mv_xor_v2_driver = {
.probe = mv_xor_v2_probe,
.suspend = mv_xor_v2_suspend,
.resume = mv_xor_v2_resume,
- .remove = mv_xor_v2_remove,
+ .remove_new = mv_xor_v2_remove,
.driver = {
.name = "mv_xor_v2",
.of_match_table = of_match_ptr(mv_xor_v2_dt_ids),
diff --git a/drivers/dma/nbpfaxi.c b/drivers/dma/nbpfaxi.c
index 0b2f96fd8bf0..c08916339aa7 100644
--- a/drivers/dma/nbpfaxi.c
+++ b/drivers/dma/nbpfaxi.c
@@ -1454,7 +1454,7 @@ e_clk_off:
return ret;
}
-static int nbpf_remove(struct platform_device *pdev)
+static void nbpf_remove(struct platform_device *pdev)
{
struct nbpf_device *nbpf = platform_get_drvdata(pdev);
int i;
@@ -1472,8 +1472,6 @@ static int nbpf_remove(struct platform_device *pdev)
of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&nbpf->dma_dev);
clk_disable_unprepare(nbpf->clk);
-
- return 0;
}
static const struct platform_device_id nbpf_ids[] = {
@@ -1517,7 +1515,7 @@ static struct platform_driver nbpf_driver = {
},
.id_table = nbpf_ids,
.probe = nbpf_probe,
- .remove = nbpf_remove,
+ .remove_new = nbpf_remove,
};
module_platform_driver(nbpf_driver);
diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c
index 384476757c5e..4e76c4ec2d39 100644
--- a/drivers/dma/owl-dma.c
+++ b/drivers/dma/owl-dma.c
@@ -1231,7 +1231,7 @@ err_pool_free:
return ret;
}
-static int owl_dma_remove(struct platform_device *pdev)
+static void owl_dma_remove(struct platform_device *pdev)
{
struct owl_dma *od = platform_get_drvdata(pdev);
@@ -1248,13 +1248,11 @@ static int owl_dma_remove(struct platform_device *pdev)
clk_disable_unprepare(od->clk);
dma_pool_destroy(od->lli_pool);
-
- return 0;
}
static struct platform_driver owl_dma_driver = {
.probe = owl_dma_probe,
- .remove = owl_dma_remove,
+ .remove_new = owl_dma_remove,
.driver = {
.name = "dma-owl",
.of_match_table = of_match_ptr(owl_dma_match),
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index f9b82dff3387..bbb60a970dab 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -4230,7 +4230,7 @@ out:
/**
* ppc440spe_adma_remove - remove the asynch device
*/
-static int ppc440spe_adma_remove(struct platform_device *ofdev)
+static void ppc440spe_adma_remove(struct platform_device *ofdev)
{
struct ppc440spe_adma_device *adev = platform_get_drvdata(ofdev);
struct device_node *np = ofdev->dev.of_node;
@@ -4278,7 +4278,6 @@ static int ppc440spe_adma_remove(struct platform_device *ofdev)
of_address_to_resource(np, 0, &res);
release_mem_region(res.start, resource_size(&res));
kfree(adev);
- return 0;
}
/*
@@ -4550,7 +4549,7 @@ MODULE_DEVICE_TABLE(of, ppc440spe_adma_of_match);
static struct platform_driver ppc440spe_adma_driver = {
.probe = ppc440spe_adma_probe,
- .remove = ppc440spe_adma_remove,
+ .remove_new = ppc440spe_adma_remove,
.driver = {
.name = "PPC440SP(E)-ADMA",
.of_match_table = ppc440spe_adma_of_match,
diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c
index 1b046d9a3a26..31f8da810c05 100644
--- a/drivers/dma/pxa_dma.c
+++ b/drivers/dma/pxa_dma.c
@@ -15,9 +15,8 @@
#include <linux/device.h>
#include <linux/platform_data/mmp_dma.h>
#include <linux/dmapool.h>
-#include <linux/of_device.h>
-#include <linux/of_dma.h>
#include <linux/of.h>
+#include <linux/of_dma.h>
#include <linux/wait.h>
#include <linux/dma/pxa-dma.h>
@@ -91,7 +90,8 @@ struct pxad_desc_sw {
bool cyclic;
struct dma_pool *desc_pool; /* Channel's used allocator */
- struct pxad_desc_hw *hw_desc[]; /* DMA coherent descriptors */
+ struct pxad_desc_hw *hw_desc[] __counted_by(nb_desc);
+ /* DMA coherent descriptors */
};
struct pxad_phy {
@@ -722,7 +722,6 @@ static void pxad_free_desc(struct virt_dma_desc *vd)
dma_addr_t dma;
struct pxad_desc_sw *sw_desc = to_pxad_sw_desc(vd);
- BUG_ON(sw_desc->nb_desc == 0);
for (i = sw_desc->nb_desc - 1; i >= 0; i--) {
if (i > 0)
dma = sw_desc->hw_desc[i - 1]->ddadr;
@@ -740,6 +739,7 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc)
{
struct pxad_desc_sw *sw_desc;
dma_addr_t dma;
+ void *desc;
int i;
sw_desc = kzalloc(struct_size(sw_desc, hw_desc, nb_hw_desc),
@@ -749,20 +749,21 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc)
sw_desc->desc_pool = chan->desc_pool;
for (i = 0; i < nb_hw_desc; i++) {
- sw_desc->hw_desc[i] = dma_pool_alloc(sw_desc->desc_pool,
- GFP_NOWAIT, &dma);
- if (!sw_desc->hw_desc[i]) {
+ desc = dma_pool_alloc(sw_desc->desc_pool, GFP_NOWAIT, &dma);
+ if (!desc) {
dev_err(&chan->vc.chan.dev->device,
"%s(): Couldn't allocate the %dth hw_desc from dma_pool %p\n",
__func__, i, sw_desc->desc_pool);
goto err;
}
+ sw_desc->nb_desc++;
+ sw_desc->hw_desc[i] = desc;
+
if (i == 0)
sw_desc->first = dma;
else
sw_desc->hw_desc[i - 1]->ddadr = dma;
- sw_desc->nb_desc++;
}
return sw_desc;
@@ -1221,13 +1222,12 @@ static void pxad_free_channels(struct dma_device *dmadev)
}
}
-static int pxad_remove(struct platform_device *op)
+static void pxad_remove(struct platform_device *op)
{
struct pxad_device *pdev = platform_get_drvdata(op);
pxad_cleanup_debugfs(pdev);
pxad_free_channels(&pdev->slave);
- return 0;
}
static int pxad_init_phys(struct platform_device *op,
@@ -1343,7 +1343,6 @@ static int pxad_init_dmadev(struct platform_device *op,
static int pxad_probe(struct platform_device *op)
{
struct pxad_device *pdev;
- const struct of_device_id *of_id;
const struct dma_slave_map *slave_map = NULL;
struct mmp_dma_platdata *pdata = dev_get_platdata(&op->dev);
int ret, dma_channels = 0, nb_requestors = 0, slave_map_cnt = 0;
@@ -1361,8 +1360,7 @@ static int pxad_probe(struct platform_device *op)
if (IS_ERR(pdev->base))
return PTR_ERR(pdev->base);
- of_id = of_match_device(pxad_dt_ids, &op->dev);
- if (of_id) {
+ if (op->dev.of_node) {
/* Parse new and deprecated dma-channels properties */
if (of_property_read_u32(op->dev.of_node, "dma-channels",
&dma_channels))
@@ -1444,7 +1442,7 @@ static struct platform_driver pxad_driver = {
},
.id_table = pxad_id_table,
.probe = pxad_probe,
- .remove = pxad_remove,
+ .remove_new = pxad_remove,
};
static bool pxad_filter_fn(struct dma_chan *chan, void *param)
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c
index 4c3eb972039d..5e7d332731e0 100644
--- a/drivers/dma/qcom/bam_dma.c
+++ b/drivers/dma/qcom/bam_dma.c
@@ -74,7 +74,7 @@ struct bam_async_desc {
struct list_head desc_node;
enum dma_transfer_direction dir;
size_t length;
- struct bam_desc_hw desc[];
+ struct bam_desc_hw desc[] __counted_by(num_desc);
};
enum bam_reg {
@@ -1386,7 +1386,7 @@ err_disable_clk:
return ret;
}
-static int bam_dma_remove(struct platform_device *pdev)
+static void bam_dma_remove(struct platform_device *pdev)
{
struct bam_device *bdev = platform_get_drvdata(pdev);
u32 i;
@@ -1416,8 +1416,6 @@ static int bam_dma_remove(struct platform_device *pdev)
tasklet_kill(&bdev->task);
clk_disable_unprepare(bdev->bamclk);
-
- return 0;
}
static int __maybe_unused bam_dma_runtime_suspend(struct device *dev)
@@ -1475,7 +1473,7 @@ static const struct dev_pm_ops bam_dma_pm_ops = {
static struct platform_driver bam_dma_driver = {
.probe = bam_dma_probe,
- .remove = bam_dma_remove,
+ .remove_new = bam_dma_remove,
.driver = {
.name = "bam-dma-engine",
.pm = &bam_dma_pm_ops,
diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index 834ae519c15d..d63b93dc7047 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -745,7 +745,7 @@ static bool hidma_test_capability(struct device *dev, enum hidma_cap test_cap)
{
enum hidma_cap cap;
- cap = (enum hidma_cap) device_get_match_data(dev);
+ cap = (uintptr_t) device_get_match_data(dev);
return cap ? ((cap & test_cap) > 0) : 0;
}
@@ -915,7 +915,7 @@ static void hidma_shutdown(struct platform_device *pdev)
}
-static int hidma_remove(struct platform_device *pdev)
+static void hidma_remove(struct platform_device *pdev)
{
struct hidma_dev *dmadev = platform_get_drvdata(pdev);
@@ -935,8 +935,6 @@ static int hidma_remove(struct platform_device *pdev)
dev_info(&pdev->dev, "HI-DMA engine removed\n");
pm_runtime_put_sync_suspend(&pdev->dev);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
#if IS_ENABLED(CONFIG_ACPI)
@@ -960,7 +958,7 @@ MODULE_DEVICE_TABLE(of, hidma_match);
static struct platform_driver hidma_driver = {
.probe = hidma_probe,
- .remove = hidma_remove,
+ .remove_new = hidma_remove,
.shutdown = hidma_shutdown,
.driver = {
.name = "hidma",
diff --git a/drivers/dma/qcom/qcom_adm.c b/drivers/dma/qcom/qcom_adm.c
index d56caf1681ff..53f4273b657c 100644
--- a/drivers/dma/qcom/qcom_adm.c
+++ b/drivers/dma/qcom/qcom_adm.c
@@ -904,7 +904,7 @@ err_disable_core_clk:
return ret;
}
-static int adm_dma_remove(struct platform_device *pdev)
+static void adm_dma_remove(struct platform_device *pdev)
{
struct adm_device *adev = platform_get_drvdata(pdev);
struct adm_chan *achan;
@@ -927,8 +927,6 @@ static int adm_dma_remove(struct platform_device *pdev)
clk_disable_unprepare(adev->core_clk);
clk_disable_unprepare(adev->iface_clk);
-
- return 0;
}
static const struct of_device_id adm_of_match[] = {
@@ -939,7 +937,7 @@ MODULE_DEVICE_TABLE(of, adm_of_match);
static struct platform_driver adm_dma_driver = {
.probe = adm_dma_probe,
- .remove = adm_dma_remove,
+ .remove_new = adm_dma_remove,
.driver = {
.name = "adm-dma-engine",
.of_match_table = adm_of_match,
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
index a29c13cae716..01e656c69e6c 100644
--- a/drivers/dma/sa11x0-dma.c
+++ b/drivers/dma/sa11x0-dma.c
@@ -78,7 +78,7 @@ struct sa11x0_dma_desc {
bool cyclic;
unsigned sglen;
- struct sa11x0_dma_sg sg[];
+ struct sa11x0_dma_sg sg[] __counted_by(sglen);
};
struct sa11x0_dma_phy;
@@ -558,6 +558,7 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg(
dev_dbg(chan->device->dev, "vchan %p: kzalloc failed\n", &c->vc);
return NULL;
}
+ txd->sglen = j;
j = 0;
for_each_sg(sg, sgent, sglen, i) {
@@ -593,7 +594,6 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg(
txd->ddar = c->ddar;
txd->size = size;
- txd->sglen = j;
dev_dbg(chan->device->dev, "vchan %p: txd %p: size %zu nr %u\n",
&c->vc, &txd->vd, txd->size, txd->sglen);
@@ -628,6 +628,7 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_dma_cyclic(
dev_dbg(chan->device->dev, "vchan %p: kzalloc failed\n", &c->vc);
return NULL;
}
+ txd->sglen = sglen;
for (i = k = 0; i < size / period; i++) {
size_t tlen, len = period;
@@ -653,7 +654,6 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_dma_cyclic(
txd->ddar = c->ddar;
txd->size = size;
- txd->sglen = sglen;
txd->cyclic = 1;
txd->period = sgperiod;
@@ -984,7 +984,7 @@ static int sa11x0_dma_probe(struct platform_device *pdev)
return ret;
}
-static int sa11x0_dma_remove(struct platform_device *pdev)
+static void sa11x0_dma_remove(struct platform_device *pdev)
{
struct sa11x0_dma_dev *d = platform_get_drvdata(pdev);
unsigned pch;
@@ -997,8 +997,6 @@ static int sa11x0_dma_remove(struct platform_device *pdev)
tasklet_kill(&d->task);
iounmap(d->base);
kfree(d);
-
- return 0;
}
static __maybe_unused int sa11x0_dma_suspend(struct device *dev)
@@ -1081,7 +1079,7 @@ static struct platform_driver sa11x0_dma_driver = {
.pm = &sa11x0_dma_pm_ops,
},
.probe = sa11x0_dma_probe,
- .remove = sa11x0_dma_remove,
+ .remove_new = sa11x0_dma_remove,
};
static int __init sa11x0_dma_init(void)
diff --git a/drivers/dma/sf-pdma/sf-pdma.c b/drivers/dma/sf-pdma/sf-pdma.c
index d1c6956af452..3125a2f162b4 100644
--- a/drivers/dma/sf-pdma/sf-pdma.c
+++ b/drivers/dma/sf-pdma/sf-pdma.c
@@ -566,7 +566,7 @@ static int sf_pdma_probe(struct platform_device *pdev)
return 0;
}
-static int sf_pdma_remove(struct platform_device *pdev)
+static void sf_pdma_remove(struct platform_device *pdev)
{
struct sf_pdma *pdma = platform_get_drvdata(pdev);
struct sf_pdma_chan *ch;
@@ -584,8 +584,6 @@ static int sf_pdma_remove(struct platform_device *pdev)
}
dma_async_device_unregister(&pdma->dma_dev);
-
- return 0;
}
static const struct of_device_id sf_pdma_dt_ids[] = {
@@ -597,7 +595,7 @@ MODULE_DEVICE_TABLE(of, sf_pdma_dt_ids);
static struct platform_driver sf_pdma_driver = {
.probe = sf_pdma_probe,
- .remove = sf_pdma_remove,
+ .remove_new = sf_pdma_remove,
.driver = {
.name = "sf-pdma",
.of_match_table = sf_pdma_dt_ids,
diff --git a/drivers/dma/sf-pdma/sf-pdma.h b/drivers/dma/sf-pdma/sf-pdma.h
index 5c398a83b491..d05772b5d8d3 100644
--- a/drivers/dma/sf-pdma/sf-pdma.h
+++ b/drivers/dma/sf-pdma/sf-pdma.h
@@ -113,7 +113,7 @@ struct sf_pdma {
void __iomem *membase;
void __iomem *mappedbase;
u32 n_chans;
- struct sf_pdma_chan chans[];
+ struct sf_pdma_chan chans[] __counted_by(n_chans);
};
#endif /* _SF_PDMA_H */
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 641d689d17ff..40482cb73d79 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1990,7 +1990,7 @@ err_pm_disable:
return ret;
}
-static int rcar_dmac_remove(struct platform_device *pdev)
+static void rcar_dmac_remove(struct platform_device *pdev)
{
struct rcar_dmac *dmac = platform_get_drvdata(pdev);
@@ -1998,8 +1998,6 @@ static int rcar_dmac_remove(struct platform_device *pdev)
dma_async_device_unregister(&dmac->engine);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
static void rcar_dmac_shutdown(struct platform_device *pdev)
@@ -2041,7 +2039,7 @@ static struct platform_driver rcar_dmac_driver = {
.of_match_table = rcar_dmac_of_ids,
},
.probe = rcar_dmac_probe,
- .remove = rcar_dmac_remove,
+ .remove_new = rcar_dmac_remove,
.shutdown = rcar_dmac_shutdown,
};
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index f777addda8ba..fea5bda34bc2 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -969,7 +969,7 @@ err_pm_disable:
return ret;
}
-static int rz_dmac_remove(struct platform_device *pdev)
+static void rz_dmac_remove(struct platform_device *pdev)
{
struct rz_dmac *dmac = platform_get_drvdata(pdev);
unsigned int i;
@@ -987,8 +987,6 @@ static int rz_dmac_remove(struct platform_device *pdev)
reset_control_assert(dmac->rstc);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
static const struct of_device_id of_rz_dmac_match[] = {
@@ -1003,7 +1001,7 @@ static struct platform_driver rz_dmac_driver = {
.of_match_table = of_rz_dmac_match,
},
.probe = rz_dmac_probe,
- .remove = rz_dmac_remove,
+ .remove_new = rz_dmac_remove,
};
module_platform_driver(rz_dmac_driver);
diff --git a/drivers/dma/sh/shdmac.c b/drivers/dma/sh/shdmac.c
index 00067b29e232..7cc9eb2217e8 100644
--- a/drivers/dma/sh/shdmac.c
+++ b/drivers/dma/sh/shdmac.c
@@ -882,7 +882,7 @@ eshdma:
return err;
}
-static int sh_dmae_remove(struct platform_device *pdev)
+static void sh_dmae_remove(struct platform_device *pdev)
{
struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
struct dma_device *dma_dev = &shdev->shdma_dev.dma_dev;
@@ -899,8 +899,6 @@ static int sh_dmae_remove(struct platform_device *pdev)
shdma_cleanup(&shdev->shdma_dev);
synchronize_rcu();
-
- return 0;
}
static struct platform_driver sh_dmae_driver = {
@@ -908,7 +906,7 @@ static struct platform_driver sh_dmae_driver = {
.pm = &sh_dmae_pm,
.name = SH_DMAE_DRV_NAME,
},
- .remove = sh_dmae_remove,
+ .remove_new = sh_dmae_remove,
};
static int __init sh_dmae_init(void)
diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c
index b14cf350b669..a9b4302f6050 100644
--- a/drivers/dma/sh/usb-dmac.c
+++ b/drivers/dma/sh/usb-dmac.c
@@ -57,7 +57,7 @@ struct usb_dmac_desc {
u32 residue;
struct list_head node;
dma_cookie_t done_cookie;
- struct usb_dmac_sg sg[];
+ struct usb_dmac_sg sg[] __counted_by(sg_allocated_len);
};
#define to_usb_dmac_desc(vd) container_of(vd, struct usb_dmac_desc, vd)
@@ -866,7 +866,7 @@ static void usb_dmac_chan_remove(struct usb_dmac *dmac,
devm_free_irq(dmac->dev, uchan->irq, uchan);
}
-static int usb_dmac_remove(struct platform_device *pdev)
+static void usb_dmac_remove(struct platform_device *pdev)
{
struct usb_dmac *dmac = platform_get_drvdata(pdev);
int i;
@@ -877,8 +877,6 @@ static int usb_dmac_remove(struct platform_device *pdev)
dma_async_device_unregister(&dmac->engine);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
static void usb_dmac_shutdown(struct platform_device *pdev)
@@ -901,7 +899,7 @@ static struct platform_driver usb_dmac_driver = {
.of_match_table = usb_dmac_of_ids,
},
.probe = usb_dmac_probe,
- .remove = usb_dmac_remove,
+ .remove_new = usb_dmac_remove,
.shutdown = usb_dmac_shutdown,
};
diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c
index 168aa0bd73a0..3f54ff37c5e0 100644
--- a/drivers/dma/sprd-dma.c
+++ b/drivers/dma/sprd-dma.c
@@ -212,7 +212,7 @@ struct sprd_dma_dev {
struct clk *ashb_clk;
int irq;
u32 total_chns;
- struct sprd_dma_chn channels[];
+ struct sprd_dma_chn channels[] __counted_by(total_chns);
};
static void sprd_dma_free_desc(struct virt_dma_desc *vd);
@@ -572,8 +572,7 @@ static void sprd_dma_stop(struct sprd_dma_chn *schan)
schan->cur_desc = NULL;
}
-static bool sprd_dma_check_trans_done(struct sprd_dma_desc *sdesc,
- enum sprd_dma_int_type int_type,
+static bool sprd_dma_check_trans_done(enum sprd_dma_int_type int_type,
enum sprd_dma_req_mode req_mode)
{
if (int_type == SPRD_DMA_NO_INT)
@@ -619,8 +618,7 @@ static irqreturn_t dma_irq_handle(int irq, void *dev_id)
vchan_cyclic_callback(&sdesc->vd);
} else {
/* Check if the dma request descriptor is done. */
- trans_done = sprd_dma_check_trans_done(sdesc, int_type,
- req_type);
+ trans_done = sprd_dma_check_trans_done(int_type, req_type);
if (trans_done == true) {
vchan_cookie_complete(&sdesc->vd);
schan->cur_desc = NULL;
@@ -1117,6 +1115,15 @@ static int sprd_dma_probe(struct platform_device *pdev)
u32 chn_count;
int ret, i;
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36));
+ if (ret) {
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_err(&pdev->dev, "unable to set coherent mask to 32\n");
+ return ret;
+ }
+ }
+
/* Parse new and deprecated dma-channels properties */
ret = device_property_read_u32(&pdev->dev, "dma-channels", &chn_count);
if (ret)
@@ -1232,7 +1239,7 @@ err_rpm:
return ret;
}
-static int sprd_dma_remove(struct platform_device *pdev)
+static void sprd_dma_remove(struct platform_device *pdev)
{
struct sprd_dma_dev *sdev = platform_get_drvdata(pdev);
struct sprd_dma_chn *c, *cn;
@@ -1255,7 +1262,6 @@ static int sprd_dma_remove(struct platform_device *pdev)
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
- return 0;
}
static const struct of_device_id sprd_dma_match[] = {
@@ -1292,7 +1298,7 @@ static const struct dev_pm_ops sprd_dma_pm_ops = {
static struct platform_driver sprd_dma_driver = {
.probe = sprd_dma_probe,
- .remove = sprd_dma_remove,
+ .remove_new = sprd_dma_remove,
.driver = {
.name = "sprd-dma",
.of_match_table = sprd_dma_match,
diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c
index d95c421877fb..8880b5e336f8 100644
--- a/drivers/dma/st_fdma.c
+++ b/drivers/dma/st_fdma.c
@@ -10,9 +10,10 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/of_dma.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/interrupt.h>
#include <linux/remoteproc.h>
#include <linux/slab.h>
@@ -739,18 +740,11 @@ static void st_fdma_free(struct st_fdma_dev *fdev)
static int st_fdma_probe(struct platform_device *pdev)
{
struct st_fdma_dev *fdev;
- const struct of_device_id *match;
struct device_node *np = pdev->dev.of_node;
const struct st_fdma_driverdata *drvdata;
int ret, i;
- match = of_match_device((st_fdma_match), &pdev->dev);
- if (!match || !match->data) {
- dev_err(&pdev->dev, "No device match found\n");
- return -ENODEV;
- }
-
- drvdata = match->data;
+ drvdata = device_get_match_data(&pdev->dev);
fdev = devm_kzalloc(&pdev->dev, sizeof(*fdev), GFP_KERNEL);
if (!fdev)
@@ -849,15 +843,13 @@ err:
return ret;
}
-static int st_fdma_remove(struct platform_device *pdev)
+static void st_fdma_remove(struct platform_device *pdev)
{
struct st_fdma_dev *fdev = platform_get_drvdata(pdev);
devm_free_irq(&pdev->dev, fdev->irq, fdev);
st_slim_rproc_put(fdev->slim_rproc);
of_dma_controller_free(pdev->dev.of_node);
-
- return 0;
}
static struct platform_driver st_fdma_platform_driver = {
@@ -866,7 +858,7 @@ static struct platform_driver st_fdma_platform_driver = {
.of_match_table = st_fdma_match,
},
.probe = st_fdma_probe,
- .remove = st_fdma_remove,
+ .remove_new = st_fdma_remove,
};
module_platform_driver(st_fdma_platform_driver);
diff --git a/drivers/dma/st_fdma.h b/drivers/dma/st_fdma.h
index fa15b97a3bab..f296412e96b6 100644
--- a/drivers/dma/st_fdma.h
+++ b/drivers/dma/st_fdma.h
@@ -97,7 +97,7 @@ struct st_fdma_desc {
struct st_fdma_chan *fchan;
bool iscyclic;
unsigned int n_nodes;
- struct st_fdma_sw_node node[];
+ struct st_fdma_sw_node node[] __counted_by(n_nodes);
};
enum st_fdma_type {
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 89e82508c133..002833fb1fa0 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3668,6 +3668,7 @@ static int __init d40_probe(struct platform_device *pdev)
regulator_disable(base->lcpa_regulator);
regulator_put(base->lcpa_regulator);
}
+ pm_runtime_disable(base->dev);
report_failure:
d40_err(dev, "probe failed\n");
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index 5c36811aa134..90857d08a1a7 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -21,7 +21,6 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/of_dma.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -191,7 +190,7 @@ struct stm32_dma_desc {
struct virt_dma_desc vdesc;
bool cyclic;
u32 num_sgs;
- struct stm32_dma_sg_req sg_req[];
+ struct stm32_dma_sg_req sg_req[] __counted_by(num_sgs);
};
/**
@@ -1105,6 +1104,7 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg(
desc = kzalloc(struct_size(desc, sg_req, sg_len), GFP_NOWAIT);
if (!desc)
return NULL;
+ desc->num_sgs = sg_len;
/* Set peripheral flow controller */
if (chan->dma_sconfig.device_fc)
@@ -1113,8 +1113,10 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg(
chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL;
/* Activate Double Buffer Mode if DMA triggers STM32 MDMA and more than 1 sg */
- if (chan->trig_mdma && sg_len > 1)
+ if (chan->trig_mdma && sg_len > 1) {
chan->chan_reg.dma_scr |= STM32_DMA_SCR_DBM;
+ chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_CT;
+ }
for_each_sg(sgl, sg, sg_len, i) {
ret = stm32_dma_set_xfer_param(chan, direction, &buswidth,
@@ -1141,8 +1143,6 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg(
desc->sg_req[i].chan_reg.dma_sm1ar += sg_dma_len(sg);
desc->sg_req[i].chan_reg.dma_sndtr = nb_data_items;
}
-
- desc->num_sgs = sg_len;
desc->cyclic = false;
return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
@@ -1216,6 +1216,7 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic(
desc = kzalloc(struct_size(desc, sg_req, num_periods), GFP_NOWAIT);
if (!desc)
return NULL;
+ desc->num_sgs = num_periods;
for (i = 0; i < num_periods; i++) {
desc->sg_req[i].len = period_len;
@@ -1232,8 +1233,6 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic(
if (!chan->trig_mdma)
buf_addr += period_len;
}
-
- desc->num_sgs = num_periods;
desc->cyclic = true;
return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
@@ -1247,13 +1246,14 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
enum dma_slave_buswidth max_width;
struct stm32_dma_desc *desc;
size_t xfer_count, offset;
- u32 num_sgs, best_burst, dma_burst, threshold;
- int i;
+ u32 num_sgs, best_burst, threshold;
+ int dma_burst, i;
num_sgs = DIV_ROUND_UP(len, STM32_DMA_ALIGNED_MAX_DATA_ITEMS);
desc = kzalloc(struct_size(desc, sg_req, num_sgs), GFP_NOWAIT);
if (!desc)
return NULL;
+ desc->num_sgs = num_sgs;
threshold = chan->threshold;
@@ -1266,6 +1266,10 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
best_burst = stm32_dma_get_best_burst(len, STM32_DMA_MAX_BURST,
threshold, max_width);
dma_burst = stm32_dma_get_burst(chan, best_burst);
+ if (dma_burst < 0) {
+ kfree(desc);
+ return NULL;
+ }
stm32_dma_clear_reg(&desc->sg_req[i].chan_reg);
desc->sg_req[i].chan_reg.dma_scr =
@@ -1283,8 +1287,6 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
desc->sg_req[i].chan_reg.dma_sndtr = xfer_count;
desc->sg_req[i].len = xfer_count;
}
-
- desc->num_sgs = num_sgs;
desc->cyclic = false;
return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
@@ -1387,11 +1389,12 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
residue = stm32_dma_get_remaining_bytes(chan);
- if (chan->desc->cyclic && !stm32_dma_is_current_sg(chan)) {
+ if ((chan->desc->cyclic || chan->trig_mdma) && !stm32_dma_is_current_sg(chan)) {
n_sg++;
if (n_sg == chan->desc->num_sgs)
n_sg = 0;
- residue = sg_req->len;
+ if (!chan->trig_mdma)
+ residue = sg_req->len;
}
/*
@@ -1401,7 +1404,7 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
* residue = remaining bytes from NDTR + remaining
* periods/sg to be transferred
*/
- if (!chan->desc->cyclic || n_sg != 0)
+ if ((!chan->desc->cyclic && !chan->trig_mdma) || n_sg != 0)
for (i = n_sg; i < desc->num_sgs; i++)
residue += desc->sg_req[i].len;
@@ -1564,17 +1567,10 @@ static int stm32_dma_probe(struct platform_device *pdev)
struct stm32_dma_chan *chan;
struct stm32_dma_device *dmadev;
struct dma_device *dd;
- const struct of_device_id *match;
struct resource *res;
struct reset_control *rst;
int i, ret;
- match = of_match_device(stm32_dma_of_match, &pdev->dev);
- if (!match) {
- dev_err(&pdev->dev, "Error: No device match found\n");
- return -ENODEV;
- }
-
dmadev = devm_kzalloc(&pdev->dev, sizeof(*dmadev), GFP_KERNEL);
if (!dmadev)
return -ENOMEM;
diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c
index 0de234022c6d..6505081ced44 100644
--- a/drivers/dma/stm32-mdma.c
+++ b/drivers/dma/stm32-mdma.c
@@ -224,7 +224,7 @@ struct stm32_mdma_desc {
u32 ccr;
bool cyclic;
u32 count;
- struct stm32_mdma_desc_node node[];
+ struct stm32_mdma_desc_node node[] __counted_by(count);
};
struct stm32_mdma_dma_config {
@@ -256,7 +256,7 @@ struct stm32_mdma_device {
u32 nr_ahb_addr_masks;
u32 chan_reserved;
struct stm32_mdma_chan chan[STM32_MDMA_MAX_CHANNELS];
- u32 ahb_addr_masks[];
+ u32 ahb_addr_masks[] __counted_by(nr_ahb_addr_masks);
};
static struct stm32_mdma_device *stm32_mdma_get_dev(
@@ -321,6 +321,7 @@ static struct stm32_mdma_desc *stm32_mdma_alloc_desc(
desc = kzalloc(struct_size(desc, node, count), GFP_NOWAIT);
if (!desc)
return NULL;
+ desc->count = count;
for (i = 0; i < count; i++) {
desc->node[i].hwdesc =
@@ -330,8 +331,6 @@ static struct stm32_mdma_desc *stm32_mdma_alloc_desc(
goto err;
}
- desc->count = count;
-
return desc;
err:
@@ -489,7 +488,7 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan,
src_maxburst = chan->dma_config.src_maxburst;
dst_maxburst = chan->dma_config.dst_maxburst;
- ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id));
+ ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id)) & ~STM32_MDMA_CCR_EN;
ctcr = stm32_mdma_read(dmadev, STM32_MDMA_CTCR(chan->id));
ctbr = stm32_mdma_read(dmadev, STM32_MDMA_CTBR(chan->id));
@@ -777,8 +776,6 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan,
/* Enable interrupts */
ccr &= ~STM32_MDMA_CCR_IRQ_MASK;
ccr |= STM32_MDMA_CCR_TEIE | STM32_MDMA_CCR_CTCIE;
- if (sg_len > 1)
- ccr |= STM32_MDMA_CCR_BTIE;
desc->ccr = ccr;
return 0;
@@ -967,7 +964,7 @@ stm32_mdma_prep_dma_memcpy(struct dma_chan *c, dma_addr_t dest, dma_addr_t src,
if (!desc)
return NULL;
- ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id));
+ ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id)) & ~STM32_MDMA_CCR_EN;
ctcr = stm32_mdma_read(dmadev, STM32_MDMA_CTCR(chan->id));
ctbr = stm32_mdma_read(dmadev, STM32_MDMA_CTBR(chan->id));
cbndtr = stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id));
@@ -1236,6 +1233,10 @@ static int stm32_mdma_resume(struct dma_chan *c)
unsigned long flags;
u32 status, reg;
+ /* Transfer can be terminated */
+ if (!chan->desc || (stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id)) & STM32_MDMA_CCR_EN))
+ return -EPERM;
+
hwdesc = chan->desc->node[chan->curr_hwdesc].hwdesc;
spin_lock_irqsave(&chan->vchan.lock, flags);
@@ -1316,21 +1317,35 @@ static int stm32_mdma_slave_config(struct dma_chan *c,
static size_t stm32_mdma_desc_residue(struct stm32_mdma_chan *chan,
struct stm32_mdma_desc *desc,
- u32 curr_hwdesc)
+ u32 curr_hwdesc,
+ struct dma_tx_state *state)
{
struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
struct stm32_mdma_hwdesc *hwdesc;
- u32 cbndtr, residue, modulo, burst_size;
+ u32 cisr, clar, cbndtr, residue, modulo, burst_size;
int i;
+ cisr = stm32_mdma_read(dmadev, STM32_MDMA_CISR(chan->id));
+
residue = 0;
- for (i = curr_hwdesc + 1; i < desc->count; i++) {
+ /* Get the next hw descriptor to process from current transfer */
+ clar = stm32_mdma_read(dmadev, STM32_MDMA_CLAR(chan->id));
+ for (i = desc->count - 1; i >= 0; i--) {
hwdesc = desc->node[i].hwdesc;
+
+ if (hwdesc->clar == clar)
+ break;/* Current transfer found, stop cumulating */
+
+ /* Cumulate residue of unprocessed hw descriptors */
residue += STM32_MDMA_CBNDTR_BNDT(hwdesc->cbndtr);
}
cbndtr = stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id));
residue += cbndtr & STM32_MDMA_CBNDTR_BNDT_MASK;
+ state->in_flight_bytes = 0;
+ if (chan->chan_config.m2m_hw && (cisr & STM32_MDMA_CISR_CRQA))
+ state->in_flight_bytes = cbndtr & STM32_MDMA_CBNDTR_BNDT_MASK;
+
if (!chan->mem_burst)
return residue;
@@ -1360,11 +1375,10 @@ static enum dma_status stm32_mdma_tx_status(struct dma_chan *c,
vdesc = vchan_find_desc(&chan->vchan, cookie);
if (chan->desc && cookie == chan->desc->vdesc.tx.cookie)
- residue = stm32_mdma_desc_residue(chan, chan->desc,
- chan->curr_hwdesc);
+ residue = stm32_mdma_desc_residue(chan, chan->desc, chan->curr_hwdesc, state);
else if (vdesc)
- residue = stm32_mdma_desc_residue(chan,
- to_stm32_mdma_desc(vdesc), 0);
+ residue = stm32_mdma_desc_residue(chan, to_stm32_mdma_desc(vdesc), 0, state);
+
dma_set_residue(state, residue);
spin_unlock_irqrestore(&chan->vchan.lock, flags);
@@ -1612,13 +1626,13 @@ static int stm32_mdma_probe(struct platform_device *pdev)
GFP_KERNEL);
if (!dmadev)
return -ENOMEM;
+ dmadev->nr_ahb_addr_masks = count;
dmadev->nr_channels = nr_channels;
dmadev->nr_requests = nr_requests;
device_property_read_u32_array(&pdev->dev, "st,ahb-addr-masks",
dmadev->ahb_addr_masks,
count);
- dmadev->nr_ahb_addr_masks = count;
dmadev->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dmadev->base))
diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
index e86c8829513a..2e7f9b07fdd2 100644
--- a/drivers/dma/sun4i-dma.c
+++ b/drivers/dma/sun4i-dma.c
@@ -1271,7 +1271,7 @@ err_clk_disable:
return ret;
}
-static int sun4i_dma_remove(struct platform_device *pdev)
+static void sun4i_dma_remove(struct platform_device *pdev)
{
struct sun4i_dma_dev *priv = platform_get_drvdata(pdev);
@@ -1282,8 +1282,6 @@ static int sun4i_dma_remove(struct platform_device *pdev)
dma_async_device_unregister(&priv->slave);
clk_disable_unprepare(priv->clk);
-
- return 0;
}
static const struct of_device_id sun4i_dma_match[] = {
@@ -1294,7 +1292,7 @@ MODULE_DEVICE_TABLE(of, sun4i_dma_match);
static struct platform_driver sun4i_dma_driver = {
.probe = sun4i_dma_probe,
- .remove = sun4i_dma_remove,
+ .remove_new = sun4i_dma_remove,
.driver = {
.name = "sun4i-dma",
.of_match_table = sun4i_dma_match,
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 2469efddf540..583bf49031cf 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -1470,7 +1470,7 @@ err_chan_free:
return ret;
}
-static int sun6i_dma_remove(struct platform_device *pdev)
+static void sun6i_dma_remove(struct platform_device *pdev)
{
struct sun6i_dma_dev *sdc = platform_get_drvdata(pdev);
@@ -1484,13 +1484,11 @@ static int sun6i_dma_remove(struct platform_device *pdev)
reset_control_assert(sdc->rstc);
sun6i_dma_free(sdc);
-
- return 0;
}
static struct platform_driver sun6i_dma_driver = {
.probe = sun6i_dma_probe,
- .remove = sun6i_dma_remove,
+ .remove_new = sun6i_dma_remove,
.driver = {
.name = "sun6i-dma",
.of_match_table = sun6i_dma_match,
diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index 33b101001100..fa4d4142a68a 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -221,7 +221,7 @@ struct tegra_dma_desc {
unsigned int sg_count;
struct virt_dma_desc vd;
struct tegra_dma_channel *tdc;
- struct tegra_dma_sg_req sg_req[];
+ struct tegra_dma_sg_req sg_req[] __counted_by(sg_count);
};
/*
@@ -1473,14 +1473,12 @@ static int tegra_dma_probe(struct platform_device *pdev)
return 0;
}
-static int tegra_dma_remove(struct platform_device *pdev)
+static void tegra_dma_remove(struct platform_device *pdev)
{
struct tegra_dma *tdma = platform_get_drvdata(pdev);
of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&tdma->dma_dev);
-
- return 0;
}
static int __maybe_unused tegra_dma_pm_suspend(struct device *dev)
@@ -1533,7 +1531,7 @@ static struct platform_driver tegra_dma_driver = {
.of_match_table = tegra_dma_of_match,
},
.probe = tegra_dma_probe,
- .remove = tegra_dma_remove,
+ .remove_new = tegra_dma_remove,
};
module_platform_driver(tegra_dma_driver);
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index 063022f9df76..ac69778827f2 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -1581,7 +1581,7 @@ err_clk_unprepare:
return ret;
}
-static int tegra_dma_remove(struct platform_device *pdev)
+static void tegra_dma_remove(struct platform_device *pdev)
{
struct tegra_dma *tdma = platform_get_drvdata(pdev);
@@ -1589,8 +1589,6 @@ static int tegra_dma_remove(struct platform_device *pdev)
dma_async_device_unregister(&tdma->dma_dev);
pm_runtime_disable(&pdev->dev);
clk_unprepare(tdma->dma_clk);
-
- return 0;
}
static int __maybe_unused tegra_dma_runtime_suspend(struct device *dev)
@@ -1677,7 +1675,7 @@ static struct platform_driver tegra_dmac_driver = {
.of_match_table = tegra_dma_of_match,
},
.probe = tegra_dma_probe,
- .remove = tegra_dma_remove,
+ .remove_new = tegra_dma_remove,
};
module_platform_driver(tegra_dmac_driver);
diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index e557bada1510..7a0586633bf3 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -162,7 +162,7 @@ struct tegra_adma {
const struct tegra_adma_chip_data *cdata;
/* Last member of the structure */
- struct tegra_adma_chan channels[];
+ struct tegra_adma_chan channels[] __counted_by(nr_channels);
};
static inline void tdma_write(struct tegra_adma *tdma, u32 reg, u32 val)
@@ -949,7 +949,7 @@ irq_dispose:
return ret;
}
-static int tegra_adma_remove(struct platform_device *pdev)
+static void tegra_adma_remove(struct platform_device *pdev)
{
struct tegra_adma *tdma = platform_get_drvdata(pdev);
int i;
@@ -961,8 +961,6 @@ static int tegra_adma_remove(struct platform_device *pdev)
irq_dispose_mapping(tdma->channels[i].irq);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
static const struct dev_pm_ops tegra_adma_dev_pm_ops = {
@@ -979,7 +977,7 @@ static struct platform_driver tegra_admac_driver = {
.of_match_table = tegra_adma_of_match,
},
.probe = tegra_adma_probe,
- .remove = tegra_adma_remove,
+ .remove_new = tegra_adma_remove,
};
module_platform_driver(tegra_admac_driver);
diff --git a/drivers/dma/ti/cppi41.c b/drivers/dma/ti/cppi41.c
index c3555cfb0681..7e0b06b5dff0 100644
--- a/drivers/dma/ti/cppi41.c
+++ b/drivers/dma/ti/cppi41.c
@@ -1156,7 +1156,7 @@ err_get_sync:
return ret;
}
-static int cppi41_dma_remove(struct platform_device *pdev)
+static void cppi41_dma_remove(struct platform_device *pdev)
{
struct cppi41_dd *cdd = platform_get_drvdata(pdev);
int error;
@@ -1173,7 +1173,6 @@ static int cppi41_dma_remove(struct platform_device *pdev)
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
- return 0;
}
static int __maybe_unused cppi41_suspend(struct device *dev)
@@ -1244,7 +1243,7 @@ static const struct dev_pm_ops cppi41_pm_ops = {
static struct platform_driver cpp41_dma_driver = {
.probe = cppi41_dma_probe,
- .remove = cppi41_dma_remove,
+ .remove_new = cppi41_dma_remove,
.driver = {
.name = "cppi41-dma-engine",
.pm = &cppi41_pm_ops,
diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c
index aa8e2e8ac260..f1f920861fa9 100644
--- a/drivers/dma/ti/edma.c
+++ b/drivers/dma/ti/edma.c
@@ -202,7 +202,7 @@ struct edma_desc {
u32 residue;
u32 residue_stat;
- struct edma_pset pset[];
+ struct edma_pset pset[] __counted_by(pset_nr);
};
struct edma_cc;
@@ -2401,7 +2401,7 @@ static int edma_probe(struct platform_device *pdev)
if (irq < 0 && node)
irq = irq_of_parse_and_map(node, 0);
- if (irq >= 0) {
+ if (irq > 0) {
irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccint",
dev_name(dev));
ret = devm_request_irq(dev, irq, dma_irq_handler, 0, irq_name,
@@ -2417,7 +2417,7 @@ static int edma_probe(struct platform_device *pdev)
if (irq < 0 && node)
irq = irq_of_parse_and_map(node, 2);
- if (irq >= 0) {
+ if (irq > 0) {
irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccerrint",
dev_name(dev));
ret = devm_request_irq(dev, irq, dma_ccerr_handler, 0, irq_name,
@@ -2550,7 +2550,7 @@ static void edma_cleanupp_vchan(struct dma_device *dmadev)
}
}
-static int edma_remove(struct platform_device *pdev)
+static void edma_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct edma_cc *ecc = dev_get_drvdata(dev);
@@ -2568,8 +2568,6 @@ static int edma_remove(struct platform_device *pdev)
edma_free_slot(ecc, ecc->dummy_slot);
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -2628,7 +2626,7 @@ static const struct dev_pm_ops edma_pm_ops = {
static struct platform_driver edma_driver = {
.probe = edma_probe,
- .remove = edma_remove,
+ .remove_new = edma_remove,
.driver = {
.name = "edma",
.pm = &edma_pm_ops,
diff --git a/drivers/dma/ti/k3-psil-am62.c b/drivers/dma/ti/k3-psil-am62.c
index 2b6fd6e37c61..1272b1541f61 100644
--- a/drivers/dma/ti/k3-psil-am62.c
+++ b/drivers/dma/ti/k3-psil-am62.c
@@ -74,7 +74,9 @@ static struct psil_ep am62_src_ep_map[] = {
PSIL_SAUL(0x7505, 21, 35, 8, 36, 0),
PSIL_SAUL(0x7506, 22, 43, 8, 43, 0),
PSIL_SAUL(0x7507, 23, 43, 8, 44, 0),
- /* PDMA_MAIN0 - SPI0-3 */
+ /* PDMA_MAIN0 - SPI0-2 */
+ PSIL_PDMA_XY_PKT(0x4300),
+ PSIL_PDMA_XY_PKT(0x4301),
PSIL_PDMA_XY_PKT(0x4302),
PSIL_PDMA_XY_PKT(0x4303),
PSIL_PDMA_XY_PKT(0x4304),
@@ -85,8 +87,6 @@ static struct psil_ep am62_src_ep_map[] = {
PSIL_PDMA_XY_PKT(0x4309),
PSIL_PDMA_XY_PKT(0x430a),
PSIL_PDMA_XY_PKT(0x430b),
- PSIL_PDMA_XY_PKT(0x430c),
- PSIL_PDMA_XY_PKT(0x430d),
/* PDMA_MAIN1 - UART0-6 */
PSIL_PDMA_XY_PKT(0x4400),
PSIL_PDMA_XY_PKT(0x4401),
@@ -141,7 +141,9 @@ static struct psil_ep am62_dst_ep_map[] = {
/* SAUL */
PSIL_SAUL(0xf500, 27, 83, 8, 83, 1),
PSIL_SAUL(0xf501, 28, 91, 8, 91, 1),
- /* PDMA_MAIN0 - SPI0-3 */
+ /* PDMA_MAIN0 - SPI0-2 */
+ PSIL_PDMA_XY_PKT(0xc300),
+ PSIL_PDMA_XY_PKT(0xc301),
PSIL_PDMA_XY_PKT(0xc302),
PSIL_PDMA_XY_PKT(0xc303),
PSIL_PDMA_XY_PKT(0xc304),
@@ -152,8 +154,6 @@ static struct psil_ep am62_dst_ep_map[] = {
PSIL_PDMA_XY_PKT(0xc309),
PSIL_PDMA_XY_PKT(0xc30a),
PSIL_PDMA_XY_PKT(0xc30b),
- PSIL_PDMA_XY_PKT(0xc30c),
- PSIL_PDMA_XY_PKT(0xc30d),
/* PDMA_MAIN1 - UART0-6 */
PSIL_PDMA_XY_PKT(0xc400),
PSIL_PDMA_XY_PKT(0xc401),
diff --git a/drivers/dma/ti/k3-psil-am62a.c b/drivers/dma/ti/k3-psil-am62a.c
index ca9d71f91422..4cf9123b0e93 100644
--- a/drivers/dma/ti/k3-psil-am62a.c
+++ b/drivers/dma/ti/k3-psil-am62a.c
@@ -84,7 +84,9 @@ static struct psil_ep am62a_src_ep_map[] = {
PSIL_SAUL(0x7505, 21, 35, 8, 36, 0),
PSIL_SAUL(0x7506, 22, 43, 8, 43, 0),
PSIL_SAUL(0x7507, 23, 43, 8, 44, 0),
- /* PDMA_MAIN0 - SPI0-3 */
+ /* PDMA_MAIN0 - SPI0-2 */
+ PSIL_PDMA_XY_PKT(0x4300),
+ PSIL_PDMA_XY_PKT(0x4301),
PSIL_PDMA_XY_PKT(0x4302),
PSIL_PDMA_XY_PKT(0x4303),
PSIL_PDMA_XY_PKT(0x4304),
@@ -95,8 +97,6 @@ static struct psil_ep am62a_src_ep_map[] = {
PSIL_PDMA_XY_PKT(0x4309),
PSIL_PDMA_XY_PKT(0x430a),
PSIL_PDMA_XY_PKT(0x430b),
- PSIL_PDMA_XY_PKT(0x430c),
- PSIL_PDMA_XY_PKT(0x430d),
/* PDMA_MAIN1 - UART0-6 */
PSIL_PDMA_XY_PKT(0x4400),
PSIL_PDMA_XY_PKT(0x4401),
@@ -151,7 +151,9 @@ static struct psil_ep am62a_dst_ep_map[] = {
/* SAUL */
PSIL_SAUL(0xf500, 27, 83, 8, 83, 1),
PSIL_SAUL(0xf501, 28, 91, 8, 91, 1),
- /* PDMA_MAIN0 - SPI0-3 */
+ /* PDMA_MAIN0 - SPI0-2 */
+ PSIL_PDMA_XY_PKT(0xc300),
+ PSIL_PDMA_XY_PKT(0xc301),
PSIL_PDMA_XY_PKT(0xc302),
PSIL_PDMA_XY_PKT(0xc303),
PSIL_PDMA_XY_PKT(0xc304),
@@ -162,8 +164,6 @@ static struct psil_ep am62a_dst_ep_map[] = {
PSIL_PDMA_XY_PKT(0xc309),
PSIL_PDMA_XY_PKT(0xc30a),
PSIL_PDMA_XY_PKT(0xc30b),
- PSIL_PDMA_XY_PKT(0xc30c),
- PSIL_PDMA_XY_PKT(0xc30d),
/* PDMA_MAIN1 - UART0-6 */
PSIL_PDMA_XY_PKT(0xc400),
PSIL_PDMA_XY_PKT(0xc401),
diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c
index cf96cf915c0c..b9e0e22383b7 100644
--- a/drivers/dma/ti/omap-dma.c
+++ b/drivers/dma/ti/omap-dma.c
@@ -124,7 +124,7 @@ struct omap_desc {
uint32_t csdp; /* CSDP value */
unsigned sglen;
- struct omap_sg sg[];
+ struct omap_sg sg[] __counted_by(sglen);
};
enum {
@@ -1005,6 +1005,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
d = kzalloc(struct_size(d, sg, sglen), GFP_ATOMIC);
if (!d)
return NULL;
+ d->sglen = sglen;
d->dir = dir;
d->dev_addr = dev_addr;
@@ -1120,8 +1121,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
}
}
- d->sglen = sglen;
-
/* Release the dma_pool entries if one allocation failed */
if (ll_failed) {
for (i = 0; i < d->sglen; i++) {
@@ -1844,7 +1843,7 @@ static int omap_dma_probe(struct platform_device *pdev)
return rc;
}
-static int omap_dma_remove(struct platform_device *pdev)
+static void omap_dma_remove(struct platform_device *pdev)
{
struct omap_dmadev *od = platform_get_drvdata(pdev);
int irq;
@@ -1869,8 +1868,6 @@ static int omap_dma_remove(struct platform_device *pdev)
dma_pool_destroy(od->desc_pool);
omap_dma_free(od);
-
- return 0;
}
static const struct omap_dma_config omap2420_data = {
@@ -1918,7 +1915,7 @@ MODULE_DEVICE_TABLE(of, omap_dma_match);
static struct platform_driver omap_dma_driver = {
.probe = omap_dma_probe,
- .remove = omap_dma_remove,
+ .remove_new = omap_dma_remove,
.driver = {
.name = "omap-dma-engine",
.of_match_table = omap_dma_match,
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index 3f524be69efb..7410025605e0 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -740,7 +740,7 @@ err_release_region:
}
-static int td_remove(struct platform_device *pdev)
+static void td_remove(struct platform_device *pdev)
{
struct timb_dma *td = platform_get_drvdata(pdev);
struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -754,7 +754,6 @@ static int td_remove(struct platform_device *pdev)
release_mem_region(iomem->start, resource_size(iomem));
dev_dbg(&pdev->dev, "Removed...\n");
- return 0;
}
static struct platform_driver td_driver = {
@@ -762,7 +761,7 @@ static struct platform_driver td_driver = {
.name = DRIVER_NAME,
},
.probe = td_probe,
- .remove = td_remove,
+ .remove_new = td_remove,
};
module_platform_driver(td_driver);
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index 5b6b375a257e..44ba377b4b5a 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -1151,7 +1151,7 @@ static int __init txx9dmac_chan_probe(struct platform_device *pdev)
return 0;
}
-static int txx9dmac_chan_remove(struct platform_device *pdev)
+static void txx9dmac_chan_remove(struct platform_device *pdev)
{
struct txx9dmac_chan *dc = platform_get_drvdata(pdev);
@@ -1162,7 +1162,6 @@ static int txx9dmac_chan_remove(struct platform_device *pdev)
tasklet_kill(&dc->tasklet);
}
dc->ddev->chan[pdev->id % TXX9_DMA_MAX_NR_CHANNELS] = NULL;
- return 0;
}
static int __init txx9dmac_probe(struct platform_device *pdev)
@@ -1215,7 +1214,7 @@ static int __init txx9dmac_probe(struct platform_device *pdev)
return 0;
}
-static int txx9dmac_remove(struct platform_device *pdev)
+static void txx9dmac_remove(struct platform_device *pdev)
{
struct txx9dmac_dev *ddev = platform_get_drvdata(pdev);
@@ -1224,7 +1223,6 @@ static int txx9dmac_remove(struct platform_device *pdev)
devm_free_irq(&pdev->dev, ddev->irq, ddev);
tasklet_kill(&ddev->tasklet);
}
- return 0;
}
static void txx9dmac_shutdown(struct platform_device *pdev)
@@ -1262,14 +1260,14 @@ static const struct dev_pm_ops txx9dmac_dev_pm_ops = {
};
static struct platform_driver txx9dmac_chan_driver = {
- .remove = txx9dmac_chan_remove,
+ .remove_new = txx9dmac_chan_remove,
.driver = {
.name = "txx9dmac-chan",
},
};
static struct platform_driver txx9dmac_driver = {
- .remove = txx9dmac_remove,
+ .remove_new = txx9dmac_remove,
.shutdown = txx9dmac_shutdown,
.driver = {
.name = "txx9dmac",
diff --git a/drivers/dma/uniphier-xdmac.c b/drivers/dma/uniphier-xdmac.c
index 290836b7e1be..3a8ee2b173b5 100644
--- a/drivers/dma/uniphier-xdmac.c
+++ b/drivers/dma/uniphier-xdmac.c
@@ -80,7 +80,7 @@ struct uniphier_xdmac_desc {
unsigned int nr_node;
unsigned int cur_node;
enum dma_transfer_direction dir;
- struct uniphier_xdmac_desc_node nodes[];
+ struct uniphier_xdmac_desc_node nodes[] __counted_by(nr_node);
};
struct uniphier_xdmac_chan {
@@ -97,7 +97,7 @@ struct uniphier_xdmac_device {
struct dma_device ddev;
void __iomem *reg_base;
int nr_chans;
- struct uniphier_xdmac_chan channels[];
+ struct uniphier_xdmac_chan channels[] __counted_by(nr_chans);
};
static struct uniphier_xdmac_chan *
@@ -295,6 +295,7 @@ uniphier_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
xd = kzalloc(struct_size(xd, nodes, nr), GFP_NOWAIT);
if (!xd)
return NULL;
+ xd->nr_node = nr;
for (i = 0; i < nr; i++) {
burst_size = min_t(size_t, len, XDMAC_MAX_WORD_SIZE);
@@ -309,7 +310,6 @@ uniphier_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
}
xd->dir = DMA_MEM_TO_MEM;
- xd->nr_node = nr;
xd->cur_node = 0;
return vchan_tx_prep(vc, &xd->vd, flags);
@@ -351,6 +351,7 @@ uniphier_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
xd = kzalloc(struct_size(xd, nodes, sg_len), GFP_NOWAIT);
if (!xd)
return NULL;
+ xd->nr_node = sg_len;
for_each_sg(sgl, sg, sg_len, i) {
xd->nodes[i].src = (direction == DMA_DEV_TO_MEM)
@@ -385,7 +386,6 @@ uniphier_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
}
xd->dir = direction;
- xd->nr_node = sg_len;
xd->cur_node = 0;
return vchan_tx_prep(vc, &xd->vd, flags);
diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c
index bb4ff8c86733..fd4397adeb79 100644
--- a/drivers/dma/xgene-dma.c
+++ b/drivers/dma/xgene-dma.c
@@ -1776,7 +1776,7 @@ err_clk_enable:
return ret;
}
-static int xgene_dma_remove(struct platform_device *pdev)
+static void xgene_dma_remove(struct platform_device *pdev)
{
struct xgene_dma *pdma = platform_get_drvdata(pdev);
struct xgene_dma_chan *chan;
@@ -1797,8 +1797,6 @@ static int xgene_dma_remove(struct platform_device *pdev)
if (!IS_ERR(pdma->clk))
clk_disable_unprepare(pdma->clk);
-
- return 0;
}
#ifdef CONFIG_ACPI
@@ -1817,7 +1815,7 @@ MODULE_DEVICE_TABLE(of, xgene_dma_of_match_ptr);
static struct platform_driver xgene_dma_driver = {
.probe = xgene_dma_probe,
- .remove = xgene_dma_remove,
+ .remove_new = xgene_dma_remove,
.driver = {
.name = "X-Gene-DMA",
.of_match_table = xgene_dma_of_match_ptr,
diff --git a/drivers/dma/xilinx/xdma-regs.h b/drivers/dma/xilinx/xdma-regs.h
index dd98b4526b90..e641a5083e14 100644
--- a/drivers/dma/xilinx/xdma-regs.h
+++ b/drivers/dma/xilinx/xdma-regs.h
@@ -44,6 +44,8 @@
FIELD_PREP(XDMA_DESC_FLAGS_BITS, (flag)))
#define XDMA_DESC_CONTROL_LAST \
XDMA_DESC_CONTROL(1, XDMA_DESC_STOPPED | XDMA_DESC_COMPLETED)
+#define XDMA_DESC_CONTROL_CYCLIC \
+ XDMA_DESC_CONTROL(1, XDMA_DESC_COMPLETED)
/*
* Descriptor for a single contiguous memory block transfer.
diff --git a/drivers/dma/xilinx/xdma.c b/drivers/dma/xilinx/xdma.c
index e0bfd129d563..84a88029226f 100644
--- a/drivers/dma/xilinx/xdma.c
+++ b/drivers/dma/xilinx/xdma.c
@@ -83,6 +83,9 @@ struct xdma_chan {
* @dblk_num: Number of hardware descriptor blocks
* @desc_num: Number of hardware descriptors
* @completed_desc_num: Completed hardware descriptors
+ * @cyclic: Cyclic transfer vs. scatter-gather
+ * @periods: Number of periods in the cyclic transfer
+ * @period_size: Size of a period in bytes in cyclic transfers
*/
struct xdma_desc {
struct virt_dma_desc vdesc;
@@ -93,6 +96,9 @@ struct xdma_desc {
u32 dblk_num;
u32 desc_num;
u32 completed_desc_num;
+ bool cyclic;
+ u32 periods;
+ u32 period_size;
};
#define XDMA_DEV_STATUS_REG_DMA BIT(0)
@@ -137,10 +143,10 @@ static inline void *xdma_blk_last_desc(struct xdma_desc_block *block)
}
/**
- * xdma_link_desc_blocks - Link descriptor blocks for DMA transfer
+ * xdma_link_sg_desc_blocks - Link SG descriptor blocks for DMA transfer
* @sw_desc: Tx descriptor pointer
*/
-static void xdma_link_desc_blocks(struct xdma_desc *sw_desc)
+static void xdma_link_sg_desc_blocks(struct xdma_desc *sw_desc)
{
struct xdma_desc_block *block;
u32 last_blk_desc, desc_control;
@@ -174,6 +180,25 @@ static void xdma_link_desc_blocks(struct xdma_desc *sw_desc)
desc->control = cpu_to_le32(XDMA_DESC_CONTROL_LAST);
}
+/**
+ * xdma_link_cyclic_desc_blocks - Link cyclic descriptor blocks for DMA transfer
+ * @sw_desc: Tx descriptor pointer
+ */
+static void xdma_link_cyclic_desc_blocks(struct xdma_desc *sw_desc)
+{
+ struct xdma_desc_block *block;
+ struct xdma_hw_desc *desc;
+ int i;
+
+ block = sw_desc->desc_blocks;
+ for (i = 0; i < sw_desc->desc_num - 1; i++) {
+ desc = block->virt_addr + i * XDMA_DESC_SIZE;
+ desc->next_desc = cpu_to_le64(block->dma_addr + ((i + 1) * XDMA_DESC_SIZE));
+ }
+ desc = block->virt_addr + i * XDMA_DESC_SIZE;
+ desc->next_desc = cpu_to_le64(block->dma_addr);
+}
+
static inline struct xdma_chan *to_xdma_chan(struct dma_chan *chan)
{
return container_of(chan, struct xdma_chan, vchan.chan);
@@ -231,14 +256,16 @@ static void xdma_free_desc(struct virt_dma_desc *vdesc)
* xdma_alloc_desc - Allocate descriptor
* @chan: DMA channel pointer
* @desc_num: Number of hardware descriptors
+ * @cyclic: Whether this is a cyclic transfer
*/
static struct xdma_desc *
-xdma_alloc_desc(struct xdma_chan *chan, u32 desc_num)
+xdma_alloc_desc(struct xdma_chan *chan, u32 desc_num, bool cyclic)
{
struct xdma_desc *sw_desc;
struct xdma_hw_desc *desc;
dma_addr_t dma_addr;
u32 dblk_num;
+ u32 control;
void *addr;
int i, j;
@@ -248,12 +275,18 @@ xdma_alloc_desc(struct xdma_chan *chan, u32 desc_num)
sw_desc->chan = chan;
sw_desc->desc_num = desc_num;
+ sw_desc->cyclic = cyclic;
dblk_num = DIV_ROUND_UP(desc_num, XDMA_DESC_ADJACENT);
sw_desc->desc_blocks = kcalloc(dblk_num, sizeof(*sw_desc->desc_blocks),
GFP_NOWAIT);
if (!sw_desc->desc_blocks)
goto failed;
+ if (cyclic)
+ control = XDMA_DESC_CONTROL_CYCLIC;
+ else
+ control = XDMA_DESC_CONTROL(1, 0);
+
sw_desc->dblk_num = dblk_num;
for (i = 0; i < sw_desc->dblk_num; i++) {
addr = dma_pool_alloc(chan->desc_pool, GFP_NOWAIT, &dma_addr);
@@ -263,10 +296,13 @@ xdma_alloc_desc(struct xdma_chan *chan, u32 desc_num)
sw_desc->desc_blocks[i].virt_addr = addr;
sw_desc->desc_blocks[i].dma_addr = dma_addr;
for (j = 0, desc = addr; j < XDMA_DESC_ADJACENT; j++)
- desc[j].control = cpu_to_le32(XDMA_DESC_CONTROL(1, 0));
+ desc[j].control = cpu_to_le32(control);
}
- xdma_link_desc_blocks(sw_desc);
+ if (cyclic)
+ xdma_link_cyclic_desc_blocks(sw_desc);
+ else
+ xdma_link_sg_desc_blocks(sw_desc);
return sw_desc;
@@ -466,7 +502,7 @@ xdma_prep_device_sg(struct dma_chan *chan, struct scatterlist *sgl,
for_each_sg(sgl, sg, sg_len, i)
desc_num += DIV_ROUND_UP(sg_dma_len(sg), XDMA_DESC_BLEN_MAX);
- sw_desc = xdma_alloc_desc(xdma_chan, desc_num);
+ sw_desc = xdma_alloc_desc(xdma_chan, desc_num, false);
if (!sw_desc)
return NULL;
sw_desc->dir = dir;
@@ -522,6 +558,81 @@ failed:
}
/**
+ * xdma_prep_dma_cyclic - prepare for cyclic DMA transactions
+ * @chan: DMA channel pointer
+ * @address: Device DMA address to access
+ * @size: Total length to transfer
+ * @period_size: Period size to use for each transfer
+ * @dir: Transfer direction
+ * @flags: Transfer ack flags
+ */
+static struct dma_async_tx_descriptor *
+xdma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t address,
+ size_t size, size_t period_size,
+ enum dma_transfer_direction dir,
+ unsigned long flags)
+{
+ struct xdma_chan *xdma_chan = to_xdma_chan(chan);
+ struct xdma_device *xdev = xdma_chan->xdev_hdl;
+ unsigned int periods = size / period_size;
+ struct dma_async_tx_descriptor *tx_desc;
+ struct xdma_desc_block *dblk;
+ struct xdma_hw_desc *desc;
+ struct xdma_desc *sw_desc;
+ unsigned int i;
+
+ /*
+ * Simplify the whole logic by preventing an abnormally high number of
+ * periods and periods size.
+ */
+ if (period_size > XDMA_DESC_BLEN_MAX) {
+ xdma_err(xdev, "period size limited to %lu bytes\n", XDMA_DESC_BLEN_MAX);
+ return NULL;
+ }
+
+ if (periods > XDMA_DESC_ADJACENT) {
+ xdma_err(xdev, "number of periods limited to %u\n", XDMA_DESC_ADJACENT);
+ return NULL;
+ }
+
+ sw_desc = xdma_alloc_desc(xdma_chan, periods, true);
+ if (!sw_desc)
+ return NULL;
+
+ sw_desc->periods = periods;
+ sw_desc->period_size = period_size;
+ sw_desc->dir = dir;
+
+ dblk = sw_desc->desc_blocks;
+ desc = dblk->virt_addr;
+
+ /* fill hardware descriptor */
+ for (i = 0; i < periods; i++) {
+ desc->bytes = cpu_to_le32(period_size);
+ if (dir == DMA_MEM_TO_DEV) {
+ desc->src_addr = cpu_to_le64(address + i * period_size);
+ desc->dst_addr = cpu_to_le64(xdma_chan->cfg.dst_addr);
+ } else {
+ desc->src_addr = cpu_to_le64(xdma_chan->cfg.src_addr);
+ desc->dst_addr = cpu_to_le64(address + i * period_size);
+ }
+
+ desc++;
+ }
+
+ tx_desc = vchan_tx_prep(&xdma_chan->vchan, &sw_desc->vdesc, flags);
+ if (!tx_desc)
+ goto failed;
+
+ return tx_desc;
+
+failed:
+ xdma_free_desc(&sw_desc->vdesc);
+
+ return NULL;
+}
+
+/**
* xdma_device_config - Configure the DMA channel
* @chan: DMA channel
* @cfg: channel configuration
@@ -577,6 +688,41 @@ static int xdma_alloc_chan_resources(struct dma_chan *chan)
return 0;
}
+static enum dma_status xdma_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
+ struct dma_tx_state *state)
+{
+ struct xdma_chan *xdma_chan = to_xdma_chan(chan);
+ struct xdma_desc *desc = NULL;
+ struct virt_dma_desc *vd;
+ enum dma_status ret;
+ unsigned long flags;
+ unsigned int period_idx;
+ u32 residue = 0;
+
+ ret = dma_cookie_status(chan, cookie, state);
+ if (ret == DMA_COMPLETE)
+ return ret;
+
+ spin_lock_irqsave(&xdma_chan->vchan.lock, flags);
+
+ vd = vchan_find_desc(&xdma_chan->vchan, cookie);
+ if (vd)
+ desc = to_xdma_desc(vd);
+ if (!desc || !desc->cyclic) {
+ spin_unlock_irqrestore(&xdma_chan->vchan.lock, flags);
+ return ret;
+ }
+
+ period_idx = desc->completed_desc_num % desc->periods;
+ residue = (desc->periods - period_idx) * desc->period_size;
+
+ spin_unlock_irqrestore(&xdma_chan->vchan.lock, flags);
+
+ dma_set_residue(state, residue);
+
+ return ret;
+}
+
/**
* xdma_channel_isr - XDMA channel interrupt handler
* @irq: IRQ number
@@ -590,6 +736,7 @@ static irqreturn_t xdma_channel_isr(int irq, void *dev_id)
struct virt_dma_desc *vd;
struct xdma_desc *desc;
int ret;
+ u32 st;
spin_lock(&xchan->vchan.lock);
@@ -608,6 +755,19 @@ static irqreturn_t xdma_channel_isr(int irq, void *dev_id)
goto out;
desc->completed_desc_num += complete_desc_num;
+
+ if (desc->cyclic) {
+ ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS,
+ &st);
+ if (ret)
+ goto out;
+
+ regmap_write(xdev->rmap, xchan->base + XDMA_CHAN_STATUS, st);
+
+ vchan_cyclic_callback(vd);
+ goto out;
+ }
+
/*
* if all data blocks are transferred, remove and complete the request
*/
@@ -621,7 +781,7 @@ static irqreturn_t xdma_channel_isr(int irq, void *dev_id)
complete_desc_num != XDMA_DESC_BLOCK_NUM * XDMA_DESC_ADJACENT)
goto out;
- /* transfer the rest of data */
+ /* transfer the rest of data (SG only) */
xdma_xfer_start(xchan);
out:
@@ -841,7 +1001,7 @@ EXPORT_SYMBOL(xdma_get_user_irq);
* xdma_remove - Driver remove function
* @pdev: Pointer to the platform_device structure
*/
-static int xdma_remove(struct platform_device *pdev)
+static void xdma_remove(struct platform_device *pdev)
{
struct xdma_device *xdev = platform_get_drvdata(pdev);
@@ -850,8 +1010,6 @@ static int xdma_remove(struct platform_device *pdev)
if (xdev->status & XDMA_DEV_STATUS_REG_DMA)
dma_async_device_unregister(&xdev->dma_dev);
-
- return 0;
}
/**
@@ -885,7 +1043,7 @@ static int xdma_probe(struct platform_device *pdev)
goto failed;
}
xdev->irq_start = res->start;
- xdev->irq_num = res->end - res->start + 1;
+ xdev->irq_num = resource_size(res);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -921,17 +1079,20 @@ static int xdma_probe(struct platform_device *pdev)
dma_cap_set(DMA_SLAVE, xdev->dma_dev.cap_mask);
dma_cap_set(DMA_PRIVATE, xdev->dma_dev.cap_mask);
+ dma_cap_set(DMA_CYCLIC, xdev->dma_dev.cap_mask);
xdev->dma_dev.dev = &pdev->dev;
+ xdev->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
xdev->dma_dev.device_free_chan_resources = xdma_free_chan_resources;
xdev->dma_dev.device_alloc_chan_resources = xdma_alloc_chan_resources;
- xdev->dma_dev.device_tx_status = dma_cookie_status;
+ xdev->dma_dev.device_tx_status = xdma_tx_status;
xdev->dma_dev.device_prep_slave_sg = xdma_prep_device_sg;
xdev->dma_dev.device_config = xdma_device_config;
xdev->dma_dev.device_issue_pending = xdma_issue_pending;
xdev->dma_dev.filter.map = pdata->device_map;
xdev->dma_dev.filter.mapcnt = pdata->device_map_cnt;
xdev->dma_dev.filter.fn = xdma_filter_fn;
+ xdev->dma_dev.device_prep_dma_cyclic = xdma_prep_dma_cyclic;
ret = dma_async_device_register(&xdev->dma_dev);
if (ret) {
@@ -966,7 +1127,7 @@ static struct platform_driver xdma_driver = {
},
.id_table = xdma_id_table,
.probe = xdma_probe,
- .remove = xdma_remove,
+ .remove_new = xdma_remove,
};
module_platform_driver(xdma_driver);
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 0a3b2e22f23d..e40696f6f864 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -3242,10 +3242,8 @@ disable_clks:
/**
* xilinx_dma_remove - Driver remove function
* @pdev: Pointer to the platform_device structure
- *
- * Return: Always '0'
*/
-static int xilinx_dma_remove(struct platform_device *pdev)
+static void xilinx_dma_remove(struct platform_device *pdev)
{
struct xilinx_dma_device *xdev = platform_get_drvdata(pdev);
int i;
@@ -3259,8 +3257,6 @@ static int xilinx_dma_remove(struct platform_device *pdev)
xilinx_dma_chan_remove(xdev->chan[i]);
xdma_disable_allclks(xdev);
-
- return 0;
}
static struct platform_driver xilinx_vdma_driver = {
@@ -3269,7 +3265,7 @@ static struct platform_driver xilinx_vdma_driver = {
.of_match_table = xilinx_dma_of_ids,
},
.probe = xilinx_dma_probe,
- .remove = xilinx_dma_remove,
+ .remove_new = xilinx_dma_remove,
};
module_platform_driver(xilinx_vdma_driver);
diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c
index 84dc5240a807..69587d85a7cd 100644
--- a/drivers/dma/xilinx/xilinx_dpdma.c
+++ b/drivers/dma/xilinx/xilinx_dpdma.c
@@ -1736,7 +1736,7 @@ error:
return ret;
}
-static int xilinx_dpdma_remove(struct platform_device *pdev)
+static void xilinx_dpdma_remove(struct platform_device *pdev)
{
struct xilinx_dpdma_device *xdev = platform_get_drvdata(pdev);
unsigned int i;
@@ -1751,8 +1751,6 @@ static int xilinx_dpdma_remove(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(xdev->chan); i++)
xilinx_dpdma_chan_remove(xdev->chan[i]);
-
- return 0;
}
static const struct of_device_id xilinx_dpdma_of_match[] = {
@@ -1763,7 +1761,7 @@ MODULE_DEVICE_TABLE(of, xilinx_dpdma_of_match);
static struct platform_driver xilinx_dpdma_driver = {
.probe = xilinx_dpdma_probe,
- .remove = xilinx_dpdma_remove,
+ .remove_new = xilinx_dpdma_remove,
.driver = {
.name = "xilinx-zynqmp-dpdma",
.of_match_table = xilinx_dpdma_of_match,
diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
index bd8c3cc2eaab..f31631bef961 100644
--- a/drivers/dma/xilinx/zynqmp_dma.c
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -1147,7 +1147,7 @@ err_disable_pm:
*
* Return: Always '0'
*/
-static int zynqmp_dma_remove(struct platform_device *pdev)
+static void zynqmp_dma_remove(struct platform_device *pdev)
{
struct zynqmp_dma_device *zdev = platform_get_drvdata(pdev);
@@ -1158,8 +1158,6 @@ static int zynqmp_dma_remove(struct platform_device *pdev)
pm_runtime_disable(zdev->dev);
if (!pm_runtime_enabled(zdev->dev))
zynqmp_dma_runtime_suspend(zdev->dev);
-
- return 0;
}
static const struct of_device_id zynqmp_dma_of_match[] = {
@@ -1175,7 +1173,7 @@ static struct platform_driver zynqmp_dma_driver = {
.pm = &zynqmp_dma_dev_pm_ops,
},
.probe = zynqmp_dma_probe,
- .remove = zynqmp_dma_remove,
+ .remove_new = zynqmp_dma_remove,
};
module_platform_driver(zynqmp_dma_driver);
diff --git a/drivers/dpll/Kconfig b/drivers/dpll/Kconfig
new file mode 100644
index 000000000000..a4cae73f20d3
--- /dev/null
+++ b/drivers/dpll/Kconfig
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Generic DPLL drivers configuration
+#
+
+config DPLL
+ bool
diff --git a/drivers/dpll/Makefile b/drivers/dpll/Makefile
new file mode 100644
index 000000000000..2e5b27850110
--- /dev/null
+++ b/drivers/dpll/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for DPLL drivers.
+#
+
+obj-$(CONFIG_DPLL) += dpll.o
+dpll-y += dpll_core.o
+dpll-y += dpll_netlink.o
+dpll-y += dpll_nl.o
diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
new file mode 100644
index 000000000000..3568149b9562
--- /dev/null
+++ b/drivers/dpll/dpll_core.c
@@ -0,0 +1,798 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dpll_core.c - DPLL subsystem kernel-space interface implementation.
+ *
+ * Copyright (c) 2023 Meta Platforms, Inc. and affiliates
+ * Copyright (c) 2023 Intel Corporation.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "dpll_core.h"
+#include "dpll_netlink.h"
+
+/* Mutex lock to protect DPLL subsystem devices and pins */
+DEFINE_MUTEX(dpll_lock);
+
+DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC);
+DEFINE_XARRAY_FLAGS(dpll_pin_xa, XA_FLAGS_ALLOC);
+
+static u32 dpll_xa_id;
+
+#define ASSERT_DPLL_REGISTERED(d) \
+ WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
+#define ASSERT_DPLL_NOT_REGISTERED(d) \
+ WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
+#define ASSERT_PIN_REGISTERED(p) \
+ WARN_ON_ONCE(!xa_get_mark(&dpll_pin_xa, (p)->id, DPLL_REGISTERED))
+
+struct dpll_device_registration {
+ struct list_head list;
+ const struct dpll_device_ops *ops;
+ void *priv;
+};
+
+struct dpll_pin_registration {
+ struct list_head list;
+ const struct dpll_pin_ops *ops;
+ void *priv;
+};
+
+struct dpll_device *dpll_device_get_by_id(int id)
+{
+ if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED))
+ return xa_load(&dpll_device_xa, id);
+
+ return NULL;
+}
+
+static struct dpll_pin_registration *
+dpll_pin_registration_find(struct dpll_pin_ref *ref,
+ const struct dpll_pin_ops *ops, void *priv)
+{
+ struct dpll_pin_registration *reg;
+
+ list_for_each_entry(reg, &ref->registration_list, list) {
+ if (reg->ops == ops && reg->priv == priv)
+ return reg;
+ }
+ return NULL;
+}
+
+static int
+dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
+ const struct dpll_pin_ops *ops, void *priv)
+{
+ struct dpll_pin_registration *reg;
+ struct dpll_pin_ref *ref;
+ bool ref_exists = false;
+ unsigned long i;
+ int ret;
+
+ xa_for_each(xa_pins, i, ref) {
+ if (ref->pin != pin)
+ continue;
+ reg = dpll_pin_registration_find(ref, ops, priv);
+ if (reg) {
+ refcount_inc(&ref->refcount);
+ return 0;
+ }
+ ref_exists = true;
+ break;
+ }
+
+ if (!ref_exists) {
+ ref = kzalloc(sizeof(*ref), GFP_KERNEL);
+ if (!ref)
+ return -ENOMEM;
+ ref->pin = pin;
+ INIT_LIST_HEAD(&ref->registration_list);
+ ret = xa_insert(xa_pins, pin->pin_idx, ref, GFP_KERNEL);
+ if (ret) {
+ kfree(ref);
+ return ret;
+ }
+ refcount_set(&ref->refcount, 1);
+ }
+
+ reg = kzalloc(sizeof(*reg), GFP_KERNEL);
+ if (!reg) {
+ if (!ref_exists) {
+ xa_erase(xa_pins, pin->pin_idx);
+ kfree(ref);
+ }
+ return -ENOMEM;
+ }
+ reg->ops = ops;
+ reg->priv = priv;
+ if (ref_exists)
+ refcount_inc(&ref->refcount);
+ list_add_tail(&reg->list, &ref->registration_list);
+
+ return 0;
+}
+
+static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
+ const struct dpll_pin_ops *ops, void *priv)
+{
+ struct dpll_pin_registration *reg;
+ struct dpll_pin_ref *ref;
+ unsigned long i;
+
+ xa_for_each(xa_pins, i, ref) {
+ if (ref->pin != pin)
+ continue;
+ reg = dpll_pin_registration_find(ref, ops, priv);
+ if (WARN_ON(!reg))
+ return -EINVAL;
+ if (refcount_dec_and_test(&ref->refcount)) {
+ list_del(&reg->list);
+ kfree(reg);
+ xa_erase(xa_pins, i);
+ WARN_ON(!list_empty(&ref->registration_list));
+ kfree(ref);
+ }
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int
+dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
+ const struct dpll_pin_ops *ops, void *priv)
+{
+ struct dpll_pin_registration *reg;
+ struct dpll_pin_ref *ref;
+ bool ref_exists = false;
+ unsigned long i;
+ int ret;
+
+ xa_for_each(xa_dplls, i, ref) {
+ if (ref->dpll != dpll)
+ continue;
+ reg = dpll_pin_registration_find(ref, ops, priv);
+ if (reg) {
+ refcount_inc(&ref->refcount);
+ return 0;
+ }
+ ref_exists = true;
+ break;
+ }
+
+ if (!ref_exists) {
+ ref = kzalloc(sizeof(*ref), GFP_KERNEL);
+ if (!ref)
+ return -ENOMEM;
+ ref->dpll = dpll;
+ INIT_LIST_HEAD(&ref->registration_list);
+ ret = xa_insert(xa_dplls, dpll->id, ref, GFP_KERNEL);
+ if (ret) {
+ kfree(ref);
+ return ret;
+ }
+ refcount_set(&ref->refcount, 1);
+ }
+
+ reg = kzalloc(sizeof(*reg), GFP_KERNEL);
+ if (!reg) {
+ if (!ref_exists) {
+ xa_erase(xa_dplls, dpll->id);
+ kfree(ref);
+ }
+ return -ENOMEM;
+ }
+ reg->ops = ops;
+ reg->priv = priv;
+ if (ref_exists)
+ refcount_inc(&ref->refcount);
+ list_add_tail(&reg->list, &ref->registration_list);
+
+ return 0;
+}
+
+static void
+dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll,
+ const struct dpll_pin_ops *ops, void *priv)
+{
+ struct dpll_pin_registration *reg;
+ struct dpll_pin_ref *ref;
+ unsigned long i;
+
+ xa_for_each(xa_dplls, i, ref) {
+ if (ref->dpll != dpll)
+ continue;
+ reg = dpll_pin_registration_find(ref, ops, priv);
+ if (WARN_ON(!reg))
+ return;
+ if (refcount_dec_and_test(&ref->refcount)) {
+ list_del(&reg->list);
+ kfree(reg);
+ xa_erase(xa_dplls, i);
+ WARN_ON(!list_empty(&ref->registration_list));
+ kfree(ref);
+ }
+ return;
+ }
+}
+
+struct dpll_pin_ref *dpll_xa_ref_dpll_first(struct xarray *xa_refs)
+{
+ struct dpll_pin_ref *ref;
+ unsigned long i = 0;
+
+ ref = xa_find(xa_refs, &i, ULONG_MAX, XA_PRESENT);
+ WARN_ON(!ref);
+ return ref;
+}
+
+static struct dpll_device *
+dpll_device_alloc(const u64 clock_id, u32 device_idx, struct module *module)
+{
+ struct dpll_device *dpll;
+ int ret;
+
+ dpll = kzalloc(sizeof(*dpll), GFP_KERNEL);
+ if (!dpll)
+ return ERR_PTR(-ENOMEM);
+ refcount_set(&dpll->refcount, 1);
+ INIT_LIST_HEAD(&dpll->registration_list);
+ dpll->device_idx = device_idx;
+ dpll->clock_id = clock_id;
+ dpll->module = module;
+ ret = xa_alloc_cyclic(&dpll_device_xa, &dpll->id, dpll, xa_limit_32b,
+ &dpll_xa_id, GFP_KERNEL);
+ if (ret < 0) {
+ kfree(dpll);
+ return ERR_PTR(ret);
+ }
+ xa_init_flags(&dpll->pin_refs, XA_FLAGS_ALLOC);
+
+ return dpll;
+}
+
+/**
+ * dpll_device_get - find existing or create new dpll device
+ * @clock_id: clock_id of creator
+ * @device_idx: idx given by device driver
+ * @module: reference to registering module
+ *
+ * Get existing object of a dpll device, unique for given arguments.
+ * Create new if doesn't exist yet.
+ *
+ * Context: Acquires a lock (dpll_lock)
+ * Return:
+ * * valid dpll_device struct pointer if succeeded
+ * * ERR_PTR(X) - error
+ */
+struct dpll_device *
+dpll_device_get(u64 clock_id, u32 device_idx, struct module *module)
+{
+ struct dpll_device *dpll, *ret = NULL;
+ unsigned long index;
+
+ mutex_lock(&dpll_lock);
+ xa_for_each(&dpll_device_xa, index, dpll) {
+ if (dpll->clock_id == clock_id &&
+ dpll->device_idx == device_idx &&
+ dpll->module == module) {
+ ret = dpll;
+ refcount_inc(&ret->refcount);
+ break;
+ }
+ }
+ if (!ret)
+ ret = dpll_device_alloc(clock_id, device_idx, module);
+ mutex_unlock(&dpll_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dpll_device_get);
+
+/**
+ * dpll_device_put - decrease the refcount and free memory if possible
+ * @dpll: dpll_device struct pointer
+ *
+ * Context: Acquires a lock (dpll_lock)
+ * Drop reference for a dpll device, if all references are gone, delete
+ * dpll device object.
+ */
+void dpll_device_put(struct dpll_device *dpll)
+{
+ mutex_lock(&dpll_lock);
+ if (refcount_dec_and_test(&dpll->refcount)) {
+ ASSERT_DPLL_NOT_REGISTERED(dpll);
+ WARN_ON_ONCE(!xa_empty(&dpll->pin_refs));
+ xa_destroy(&dpll->pin_refs);
+ xa_erase(&dpll_device_xa, dpll->id);
+ WARN_ON(!list_empty(&dpll->registration_list));
+ kfree(dpll);
+ }
+ mutex_unlock(&dpll_lock);
+}
+EXPORT_SYMBOL_GPL(dpll_device_put);
+
+static struct dpll_device_registration *
+dpll_device_registration_find(struct dpll_device *dpll,
+ const struct dpll_device_ops *ops, void *priv)
+{
+ struct dpll_device_registration *reg;
+
+ list_for_each_entry(reg, &dpll->registration_list, list) {
+ if (reg->ops == ops && reg->priv == priv)
+ return reg;
+ }
+ return NULL;
+}
+
+/**
+ * dpll_device_register - register the dpll device in the subsystem
+ * @dpll: pointer to a dpll
+ * @type: type of a dpll
+ * @ops: ops for a dpll device
+ * @priv: pointer to private information of owner
+ *
+ * Make dpll device available for user space.
+ *
+ * Context: Acquires a lock (dpll_lock)
+ * Return:
+ * * 0 on success
+ * * negative - error value
+ */
+int dpll_device_register(struct dpll_device *dpll, enum dpll_type type,
+ const struct dpll_device_ops *ops, void *priv)
+{
+ struct dpll_device_registration *reg;
+ bool first_registration = false;
+
+ if (WARN_ON(!ops))
+ return -EINVAL;
+ if (WARN_ON(!ops->mode_get))
+ return -EINVAL;
+ if (WARN_ON(!ops->lock_status_get))
+ return -EINVAL;
+ if (WARN_ON(type < DPLL_TYPE_PPS || type > DPLL_TYPE_MAX))
+ return -EINVAL;
+
+ mutex_lock(&dpll_lock);
+ reg = dpll_device_registration_find(dpll, ops, priv);
+ if (reg) {
+ mutex_unlock(&dpll_lock);
+ return -EEXIST;
+ }
+
+ reg = kzalloc(sizeof(*reg), GFP_KERNEL);
+ if (!reg) {
+ mutex_unlock(&dpll_lock);
+ return -ENOMEM;
+ }
+ reg->ops = ops;
+ reg->priv = priv;
+ dpll->type = type;
+ first_registration = list_empty(&dpll->registration_list);
+ list_add_tail(&reg->list, &dpll->registration_list);
+ if (!first_registration) {
+ mutex_unlock(&dpll_lock);
+ return 0;
+ }
+
+ xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED);
+ dpll_device_create_ntf(dpll);
+ mutex_unlock(&dpll_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_device_register);
+
+/**
+ * dpll_device_unregister - unregister dpll device
+ * @dpll: registered dpll pointer
+ * @ops: ops for a dpll device
+ * @priv: pointer to private information of owner
+ *
+ * Unregister device, make it unavailable for userspace.
+ * Note: It does not free the memory
+ * Context: Acquires a lock (dpll_lock)
+ */
+void dpll_device_unregister(struct dpll_device *dpll,
+ const struct dpll_device_ops *ops, void *priv)
+{
+ struct dpll_device_registration *reg;
+
+ mutex_lock(&dpll_lock);
+ ASSERT_DPLL_REGISTERED(dpll);
+ dpll_device_delete_ntf(dpll);
+ reg = dpll_device_registration_find(dpll, ops, priv);
+ if (WARN_ON(!reg)) {
+ mutex_unlock(&dpll_lock);
+ return;
+ }
+ list_del(&reg->list);
+ kfree(reg);
+
+ if (!list_empty(&dpll->registration_list)) {
+ mutex_unlock(&dpll_lock);
+ return;
+ }
+ xa_clear_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED);
+ mutex_unlock(&dpll_lock);
+}
+EXPORT_SYMBOL_GPL(dpll_device_unregister);
+
+static struct dpll_pin *
+dpll_pin_alloc(u64 clock_id, u32 pin_idx, struct module *module,
+ const struct dpll_pin_properties *prop)
+{
+ struct dpll_pin *pin;
+ int ret;
+
+ pin = kzalloc(sizeof(*pin), GFP_KERNEL);
+ if (!pin)
+ return ERR_PTR(-ENOMEM);
+ pin->pin_idx = pin_idx;
+ pin->clock_id = clock_id;
+ pin->module = module;
+ if (WARN_ON(prop->type < DPLL_PIN_TYPE_MUX ||
+ prop->type > DPLL_PIN_TYPE_MAX)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ pin->prop = prop;
+ refcount_set(&pin->refcount, 1);
+ xa_init_flags(&pin->dpll_refs, XA_FLAGS_ALLOC);
+ xa_init_flags(&pin->parent_refs, XA_FLAGS_ALLOC);
+ ret = xa_alloc(&dpll_pin_xa, &pin->id, pin, xa_limit_16b, GFP_KERNEL);
+ if (ret)
+ goto err;
+ return pin;
+err:
+ xa_destroy(&pin->dpll_refs);
+ xa_destroy(&pin->parent_refs);
+ kfree(pin);
+ return ERR_PTR(ret);
+}
+
+/**
+ * dpll_pin_get - find existing or create new dpll pin
+ * @clock_id: clock_id of creator
+ * @pin_idx: idx given by dev driver
+ * @module: reference to registering module
+ * @prop: dpll pin properties
+ *
+ * Get existing object of a pin (unique for given arguments) or create new
+ * if doesn't exist yet.
+ *
+ * Context: Acquires a lock (dpll_lock)
+ * Return:
+ * * valid allocated dpll_pin struct pointer if succeeded
+ * * ERR_PTR(X) - error
+ */
+struct dpll_pin *
+dpll_pin_get(u64 clock_id, u32 pin_idx, struct module *module,
+ const struct dpll_pin_properties *prop)
+{
+ struct dpll_pin *pos, *ret = NULL;
+ unsigned long i;
+
+ mutex_lock(&dpll_lock);
+ xa_for_each(&dpll_pin_xa, i, pos) {
+ if (pos->clock_id == clock_id &&
+ pos->pin_idx == pin_idx &&
+ pos->module == module) {
+ ret = pos;
+ refcount_inc(&ret->refcount);
+ break;
+ }
+ }
+ if (!ret)
+ ret = dpll_pin_alloc(clock_id, pin_idx, module, prop);
+ mutex_unlock(&dpll_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_get);
+
+/**
+ * dpll_pin_put - decrease the refcount and free memory if possible
+ * @pin: pointer to a pin to be put
+ *
+ * Drop reference for a pin, if all references are gone, delete pin object.
+ *
+ * Context: Acquires a lock (dpll_lock)
+ */
+void dpll_pin_put(struct dpll_pin *pin)
+{
+ mutex_lock(&dpll_lock);
+ if (refcount_dec_and_test(&pin->refcount)) {
+ xa_destroy(&pin->dpll_refs);
+ xa_destroy(&pin->parent_refs);
+ xa_erase(&dpll_pin_xa, pin->id);
+ kfree(pin);
+ }
+ mutex_unlock(&dpll_lock);
+}
+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)
+{
+ int ret;
+
+ ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv);
+ if (ret)
+ return ret;
+ ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv);
+ if (ret)
+ goto ref_pin_del;
+ xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
+ dpll_pin_create_ntf(pin);
+
+ return ret;
+
+ref_pin_del:
+ dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv);
+ return ret;
+}
+
+/**
+ * dpll_pin_register - register the dpll pin in the subsystem
+ * @dpll: pointer to a dpll
+ * @pin: pointer to a dpll pin
+ * @ops: ops for a dpll pin ops
+ * @priv: pointer to private information of owner
+ *
+ * Context: Acquires a lock (dpll_lock)
+ * Return:
+ * * 0 on success
+ * * negative - error value
+ */
+int
+dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
+ const struct dpll_pin_ops *ops, void *priv)
+{
+ int ret;
+
+ if (WARN_ON(!ops) ||
+ WARN_ON(!ops->state_on_dpll_get) ||
+ WARN_ON(!ops->direction_get))
+ return -EINVAL;
+ if (ASSERT_DPLL_REGISTERED(dpll))
+ return -EINVAL;
+
+ mutex_lock(&dpll_lock);
+ if (WARN_ON(!(dpll->module == pin->module &&
+ dpll->clock_id == pin->clock_id)))
+ ret = -EINVAL;
+ else
+ ret = __dpll_pin_register(dpll, pin, ops, priv);
+ mutex_unlock(&dpll_lock);
+
+ return ret;
+}
+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)
+{
+ dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv);
+ dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv);
+ if (xa_empty(&pin->dpll_refs))
+ xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
+}
+
+/**
+ * dpll_pin_unregister - unregister dpll pin from dpll device
+ * @dpll: registered dpll pointer
+ * @pin: pointer to a pin
+ * @ops: ops for a dpll pin
+ * @priv: pointer to private information of owner
+ *
+ * Note: It does not free the memory
+ * Context: Acquires a lock (dpll_lock)
+ */
+void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
+ const struct dpll_pin_ops *ops, void *priv)
+{
+ if (WARN_ON(xa_empty(&dpll->pin_refs)))
+ return;
+ if (WARN_ON(!xa_empty(&pin->parent_refs)))
+ return;
+
+ mutex_lock(&dpll_lock);
+ dpll_pin_delete_ntf(pin);
+ __dpll_pin_unregister(dpll, pin, ops, priv);
+ mutex_unlock(&dpll_lock);
+}
+EXPORT_SYMBOL_GPL(dpll_pin_unregister);
+
+/**
+ * dpll_pin_on_pin_register - register a pin with a parent pin
+ * @parent: pointer to a parent pin
+ * @pin: pointer to a pin
+ * @ops: ops for a dpll pin
+ * @priv: pointer to private information of owner
+ *
+ * Register a pin with a parent pin, create references between them and
+ * between newly registered pin and dplls connected with a parent pin.
+ *
+ * Context: Acquires a lock (dpll_lock)
+ * Return:
+ * * 0 on success
+ * * negative - error value
+ */
+int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
+ const struct dpll_pin_ops *ops, void *priv)
+{
+ struct dpll_pin_ref *ref;
+ unsigned long i, stop;
+ int ret;
+
+ if (WARN_ON(parent->prop->type != DPLL_PIN_TYPE_MUX))
+ return -EINVAL;
+
+ if (WARN_ON(!ops) ||
+ WARN_ON(!ops->state_on_pin_get) ||
+ WARN_ON(!ops->direction_get))
+ return -EINVAL;
+ if (ASSERT_PIN_REGISTERED(parent))
+ return -EINVAL;
+
+ mutex_lock(&dpll_lock);
+ ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv);
+ 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);
+ if (ret) {
+ stop = i;
+ goto dpll_unregister;
+ }
+ dpll_pin_create_ntf(pin);
+ }
+ mutex_unlock(&dpll_lock);
+
+ return ret;
+
+dpll_unregister:
+ xa_for_each(&parent->dpll_refs, i, ref)
+ if (i < stop) {
+ __dpll_pin_unregister(ref->dpll, pin, ops, priv);
+ dpll_pin_delete_ntf(pin);
+ }
+ refcount_dec(&pin->refcount);
+ dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv);
+unlock:
+ mutex_unlock(&dpll_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_on_pin_register);
+
+/**
+ * dpll_pin_on_pin_unregister - unregister dpll pin from a parent pin
+ * @parent: pointer to a parent pin
+ * @pin: pointer to a pin
+ * @ops: ops for a dpll pin
+ * @priv: pointer to private information of owner
+ *
+ * Context: Acquires a lock (dpll_lock)
+ * Note: It does not free the memory
+ */
+void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin,
+ const struct dpll_pin_ops *ops, void *priv)
+{
+ struct dpll_pin_ref *ref;
+ unsigned long i;
+
+ mutex_lock(&dpll_lock);
+ dpll_pin_delete_ntf(pin);
+ dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv);
+ refcount_dec(&pin->refcount);
+ xa_for_each(&pin->dpll_refs, i, ref)
+ __dpll_pin_unregister(ref->dpll, pin, ops, priv);
+ mutex_unlock(&dpll_lock);
+}
+EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister);
+
+static struct dpll_device_registration *
+dpll_device_registration_first(struct dpll_device *dpll)
+{
+ struct dpll_device_registration *reg;
+
+ reg = list_first_entry_or_null((struct list_head *)&dpll->registration_list,
+ struct dpll_device_registration, list);
+ WARN_ON(!reg);
+ return reg;
+}
+
+void *dpll_priv(struct dpll_device *dpll)
+{
+ struct dpll_device_registration *reg;
+
+ reg = dpll_device_registration_first(dpll);
+ return reg->priv;
+}
+
+const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll)
+{
+ struct dpll_device_registration *reg;
+
+ reg = dpll_device_registration_first(dpll);
+ return reg->ops;
+}
+
+static struct dpll_pin_registration *
+dpll_pin_registration_first(struct dpll_pin_ref *ref)
+{
+ struct dpll_pin_registration *reg;
+
+ reg = list_first_entry_or_null(&ref->registration_list,
+ struct dpll_pin_registration, list);
+ WARN_ON(!reg);
+ return reg;
+}
+
+void *dpll_pin_on_dpll_priv(struct dpll_device *dpll,
+ struct dpll_pin *pin)
+{
+ struct dpll_pin_registration *reg;
+ struct dpll_pin_ref *ref;
+
+ ref = xa_load(&dpll->pin_refs, pin->pin_idx);
+ if (!ref)
+ return NULL;
+ reg = dpll_pin_registration_first(ref);
+ return reg->priv;
+}
+
+void *dpll_pin_on_pin_priv(struct dpll_pin *parent,
+ struct dpll_pin *pin)
+{
+ struct dpll_pin_registration *reg;
+ struct dpll_pin_ref *ref;
+
+ ref = xa_load(&pin->parent_refs, parent->pin_idx);
+ if (!ref)
+ return NULL;
+ reg = dpll_pin_registration_first(ref);
+ return reg->priv;
+}
+
+const struct dpll_pin_ops *dpll_pin_ops(struct dpll_pin_ref *ref)
+{
+ struct dpll_pin_registration *reg;
+
+ reg = dpll_pin_registration_first(ref);
+ return reg->ops;
+}
+
+static int __init dpll_init(void)
+{
+ int ret;
+
+ ret = genl_register_family(&dpll_nl_family);
+ if (ret)
+ goto error;
+
+ return 0;
+
+error:
+ mutex_destroy(&dpll_lock);
+ return ret;
+}
+
+static void __exit dpll_exit(void)
+{
+ genl_unregister_family(&dpll_nl_family);
+ mutex_destroy(&dpll_lock);
+}
+
+subsys_initcall(dpll_init);
+module_exit(dpll_exit);
diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
new file mode 100644
index 000000000000..5585873c5c1b
--- /dev/null
+++ b/drivers/dpll/dpll_core.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 Meta Platforms, Inc. and affiliates
+ * Copyright (c) 2023 Intel and affiliates
+ */
+
+#ifndef __DPLL_CORE_H__
+#define __DPLL_CORE_H__
+
+#include <linux/dpll.h>
+#include <linux/list.h>
+#include <linux/refcount.h>
+#include "dpll_nl.h"
+
+#define DPLL_REGISTERED XA_MARK_1
+
+/**
+ * struct dpll_device - stores DPLL device internal data
+ * @id: unique id number for device given by dpll subsystem
+ * @device_idx: id given by dev driver
+ * @clock_id: unique identifier (clock_id) of a dpll
+ * @module: module of creator
+ * @type: type of a dpll
+ * @pin_refs: stores pins registered within a dpll
+ * @refcount: refcount
+ * @registration_list: list of registered ops and priv data of dpll owners
+ **/
+struct dpll_device {
+ u32 id;
+ u32 device_idx;
+ u64 clock_id;
+ struct module *module;
+ enum dpll_type type;
+ struct xarray pin_refs;
+ refcount_t refcount;
+ struct list_head registration_list;
+};
+
+/**
+ * struct dpll_pin - structure for a dpll pin
+ * @id: unique id number for pin given by dpll subsystem
+ * @pin_idx: index of a pin given by dev driver
+ * @clock_id: clock_id of creator
+ * @module: module of creator
+ * @dpll_refs: hold referencees to dplls pin was registered with
+ * @parent_refs: hold references to parent pins pin was registered with
+ * @prop: pointer to pin properties given by registerer
+ * @rclk_dev_name: holds name of device when pin can recover clock from it
+ * @refcount: refcount
+ **/
+struct dpll_pin {
+ u32 id;
+ u32 pin_idx;
+ u64 clock_id;
+ struct module *module;
+ struct xarray dpll_refs;
+ struct xarray parent_refs;
+ const struct dpll_pin_properties *prop;
+ refcount_t refcount;
+};
+
+/**
+ * struct dpll_pin_ref - structure for referencing either dpll or pins
+ * @dpll: pointer to a dpll
+ * @pin: pointer to a pin
+ * @registration_list: list of ops and priv data registered with the ref
+ * @refcount: refcount
+ **/
+struct dpll_pin_ref {
+ union {
+ struct dpll_device *dpll;
+ struct dpll_pin *pin;
+ };
+ struct list_head registration_list;
+ refcount_t refcount;
+};
+
+void *dpll_priv(struct dpll_device *dpll);
+void *dpll_pin_on_dpll_priv(struct dpll_device *dpll, struct dpll_pin *pin);
+void *dpll_pin_on_pin_priv(struct dpll_pin *parent, struct dpll_pin *pin);
+
+const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll);
+struct dpll_device *dpll_device_get_by_id(int id);
+const struct dpll_pin_ops *dpll_pin_ops(struct dpll_pin_ref *ref);
+struct dpll_pin_ref *dpll_xa_ref_dpll_first(struct xarray *xa_refs);
+extern struct xarray dpll_device_xa;
+extern struct xarray dpll_pin_xa;
+extern struct mutex dpll_lock;
+#endif
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
new file mode 100644
index 000000000000..ce7cf736f020
--- /dev/null
+++ b/drivers/dpll/dpll_netlink.c
@@ -0,0 +1,1433 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generic netlink for DPLL management framework
+ *
+ * Copyright (c) 2023 Meta Platforms, Inc. and affiliates
+ * Copyright (c) 2023 Intel and affiliates
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <net/genetlink.h>
+#include "dpll_core.h"
+#include "dpll_netlink.h"
+#include "dpll_nl.h"
+#include <uapi/linux/dpll.h>
+
+#define ASSERT_NOT_NULL(ptr) (WARN_ON(!ptr))
+
+#define xa_for_each_marked_start(xa, index, entry, filter, start) \
+ for (index = start, entry = xa_find(xa, &index, ULONG_MAX, filter); \
+ entry; entry = xa_find_after(xa, &index, ULONG_MAX, filter))
+
+struct dpll_dump_ctx {
+ unsigned long idx;
+};
+
+static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb)
+{
+ return (struct dpll_dump_ctx *)cb->ctx;
+}
+
+static int
+dpll_msg_add_dev_handle(struct sk_buff *msg, struct dpll_device *dpll)
+{
+ if (nla_put_u32(msg, DPLL_A_ID, dpll->id))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int
+dpll_msg_add_dev_parent_handle(struct sk_buff *msg, u32 id)
+{
+ if (nla_put_u32(msg, DPLL_A_PIN_PARENT_ID, id))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+/**
+ * dpll_msg_pin_handle_size - get size of pin handle attribute for given pin
+ * @pin: pin pointer
+ *
+ * Return: byte size of pin handle attribute for given pin.
+ */
+size_t dpll_msg_pin_handle_size(struct dpll_pin *pin)
+{
+ return pin ? nla_total_size(4) : 0; /* DPLL_A_PIN_ID */
+}
+EXPORT_SYMBOL_GPL(dpll_msg_pin_handle_size);
+
+/**
+ * dpll_msg_add_pin_handle - attach pin handle attribute to a given message
+ * @msg: pointer to sk_buff message to attach a pin handle
+ * @pin: pin pointer
+ *
+ * Return:
+ * * 0 - success
+ * * -EMSGSIZE - no space in message to attach pin handle
+ */
+int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin)
+{
+ if (!pin)
+ return 0;
+ if (nla_put_u32(msg, DPLL_A_PIN_ID, pin->id))
+ return -EMSGSIZE;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_msg_add_pin_handle);
+
+static int
+dpll_msg_add_mode(struct sk_buff *msg, struct dpll_device *dpll,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_device_ops *ops = dpll_device_ops(dpll);
+ enum dpll_mode mode;
+ int ret;
+
+ ret = ops->mode_get(dpll, dpll_priv(dpll), &mode, extack);
+ if (ret)
+ return ret;
+ if (nla_put_u32(msg, DPLL_A_MODE, mode))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int
+dpll_msg_add_mode_supported(struct sk_buff *msg, struct dpll_device *dpll,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_device_ops *ops = dpll_device_ops(dpll);
+ enum dpll_mode mode;
+
+ if (!ops->mode_supported)
+ return 0;
+ for (mode = DPLL_MODE_MANUAL; mode <= DPLL_MODE_MAX; mode++)
+ if (ops->mode_supported(dpll, dpll_priv(dpll), mode, extack))
+ if (nla_put_u32(msg, DPLL_A_MODE_SUPPORTED, mode))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int
+dpll_msg_add_lock_status(struct sk_buff *msg, struct dpll_device *dpll,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_device_ops *ops = dpll_device_ops(dpll);
+ enum dpll_lock_status status;
+ int ret;
+
+ ret = ops->lock_status_get(dpll, dpll_priv(dpll), &status, extack);
+ if (ret)
+ return ret;
+ if (nla_put_u32(msg, DPLL_A_LOCK_STATUS, status))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int
+dpll_msg_add_temp(struct sk_buff *msg, struct dpll_device *dpll,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_device_ops *ops = dpll_device_ops(dpll);
+ s32 temp;
+ int ret;
+
+ if (!ops->temp_get)
+ return 0;
+ ret = ops->temp_get(dpll, dpll_priv(dpll), &temp, extack);
+ if (ret)
+ return ret;
+ if (nla_put_s32(msg, DPLL_A_TEMP, temp))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int
+dpll_msg_add_pin_prio(struct sk_buff *msg, struct dpll_pin *pin,
+ struct dpll_pin_ref *ref,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
+ struct dpll_device *dpll = ref->dpll;
+ u32 prio;
+ int ret;
+
+ if (!ops->prio_get)
+ return 0;
+ ret = ops->prio_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
+ dpll_priv(dpll), &prio, extack);
+ if (ret)
+ return ret;
+ if (nla_put_u32(msg, DPLL_A_PIN_PRIO, prio))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int
+dpll_msg_add_pin_on_dpll_state(struct sk_buff *msg, struct dpll_pin *pin,
+ struct dpll_pin_ref *ref,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
+ struct dpll_device *dpll = ref->dpll;
+ enum dpll_pin_state state;
+ int ret;
+
+ if (!ops->state_on_dpll_get)
+ return 0;
+ ret = ops->state_on_dpll_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
+ dpll, dpll_priv(dpll), &state, extack);
+ if (ret)
+ return ret;
+ if (nla_put_u32(msg, DPLL_A_PIN_STATE, state))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int
+dpll_msg_add_pin_direction(struct sk_buff *msg, struct dpll_pin *pin,
+ struct dpll_pin_ref *ref,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
+ struct dpll_device *dpll = ref->dpll;
+ enum dpll_pin_direction direction;
+ int ret;
+
+ ret = ops->direction_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
+ dpll_priv(dpll), &direction, extack);
+ if (ret)
+ return ret;
+ if (nla_put_u32(msg, DPLL_A_PIN_DIRECTION, direction))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int
+dpll_msg_add_pin_phase_adjust(struct sk_buff *msg, struct dpll_pin *pin,
+ struct dpll_pin_ref *ref,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
+ struct dpll_device *dpll = ref->dpll;
+ s32 phase_adjust;
+ int ret;
+
+ if (!ops->phase_adjust_get)
+ return 0;
+ ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
+ dpll, dpll_priv(dpll),
+ &phase_adjust, extack);
+ if (ret)
+ return ret;
+ if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST, phase_adjust))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int
+dpll_msg_add_phase_offset(struct sk_buff *msg, struct dpll_pin *pin,
+ struct dpll_pin_ref *ref,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
+ struct dpll_device *dpll = ref->dpll;
+ s64 phase_offset;
+ int ret;
+
+ if (!ops->phase_offset_get)
+ return 0;
+ ret = ops->phase_offset_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
+ dpll, dpll_priv(dpll), &phase_offset,
+ extack);
+ if (ret)
+ return ret;
+ if (nla_put_64bit(msg, DPLL_A_PIN_PHASE_OFFSET, sizeof(phase_offset),
+ &phase_offset, DPLL_A_PIN_PAD))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int
+dpll_msg_add_pin_freq(struct sk_buff *msg, struct dpll_pin *pin,
+ struct dpll_pin_ref *ref, struct netlink_ext_ack *extack)
+{
+ const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
+ struct dpll_device *dpll = ref->dpll;
+ struct nlattr *nest;
+ int fs, ret;
+ u64 freq;
+
+ if (!ops->frequency_get)
+ return 0;
+ ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
+ dpll_priv(dpll), &freq, extack);
+ if (ret)
+ return ret;
+ if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY, sizeof(freq), &freq,
+ DPLL_A_PIN_PAD))
+ return -EMSGSIZE;
+ for (fs = 0; fs < pin->prop->freq_supported_num; fs++) {
+ nest = nla_nest_start(msg, DPLL_A_PIN_FREQUENCY_SUPPORTED);
+ if (!nest)
+ return -EMSGSIZE;
+ freq = pin->prop->freq_supported[fs].min;
+ if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MIN, sizeof(freq),
+ &freq, DPLL_A_PIN_PAD)) {
+ nla_nest_cancel(msg, nest);
+ return -EMSGSIZE;
+ }
+ freq = pin->prop->freq_supported[fs].max;
+ if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MAX, sizeof(freq),
+ &freq, DPLL_A_PIN_PAD)) {
+ nla_nest_cancel(msg, nest);
+ return -EMSGSIZE;
+ }
+ nla_nest_end(msg, nest);
+ }
+
+ return 0;
+}
+
+static bool dpll_pin_is_freq_supported(struct dpll_pin *pin, u32 freq)
+{
+ int fs;
+
+ for (fs = 0; fs < pin->prop->freq_supported_num; fs++)
+ if (freq >= pin->prop->freq_supported[fs].min &&
+ freq <= pin->prop->freq_supported[fs].max)
+ return true;
+ return false;
+}
+
+static int
+dpll_msg_add_pin_parents(struct sk_buff *msg, struct dpll_pin *pin,
+ struct dpll_pin_ref *dpll_ref,
+ struct netlink_ext_ack *extack)
+{
+ enum dpll_pin_state state;
+ struct dpll_pin_ref *ref;
+ struct dpll_pin *ppin;
+ struct nlattr *nest;
+ unsigned long index;
+ int ret;
+
+ xa_for_each(&pin->parent_refs, index, ref) {
+ const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
+ void *parent_priv;
+
+ ppin = ref->pin;
+ parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, ppin);
+ ret = ops->state_on_pin_get(pin,
+ dpll_pin_on_pin_priv(ppin, pin),
+ ppin, parent_priv, &state, extack);
+ if (ret)
+ return ret;
+ nest = nla_nest_start(msg, DPLL_A_PIN_PARENT_PIN);
+ if (!nest)
+ return -EMSGSIZE;
+ ret = dpll_msg_add_dev_parent_handle(msg, ppin->id);
+ if (ret)
+ goto nest_cancel;
+ if (nla_put_u32(msg, DPLL_A_PIN_STATE, state)) {
+ ret = -EMSGSIZE;
+ goto nest_cancel;
+ }
+ nla_nest_end(msg, nest);
+ }
+
+ return 0;
+
+nest_cancel:
+ nla_nest_cancel(msg, nest);
+ return ret;
+}
+
+static int
+dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin,
+ struct netlink_ext_ack *extack)
+{
+ struct dpll_pin_ref *ref;
+ struct nlattr *attr;
+ unsigned long index;
+ int ret;
+
+ xa_for_each(&pin->dpll_refs, index, ref) {
+ attr = nla_nest_start(msg, DPLL_A_PIN_PARENT_DEVICE);
+ if (!attr)
+ return -EMSGSIZE;
+ ret = dpll_msg_add_dev_parent_handle(msg, ref->dpll->id);
+ if (ret)
+ goto nest_cancel;
+ ret = dpll_msg_add_pin_on_dpll_state(msg, pin, ref, extack);
+ if (ret)
+ goto nest_cancel;
+ ret = dpll_msg_add_pin_prio(msg, pin, ref, extack);
+ if (ret)
+ goto nest_cancel;
+ ret = dpll_msg_add_pin_direction(msg, pin, ref, extack);
+ if (ret)
+ goto nest_cancel;
+ ret = dpll_msg_add_phase_offset(msg, pin, ref, extack);
+ if (ret)
+ goto nest_cancel;
+ nla_nest_end(msg, attr);
+ }
+
+ return 0;
+
+nest_cancel:
+ nla_nest_end(msg, attr);
+ return ret;
+}
+
+static int
+dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_pin_properties *prop = pin->prop;
+ struct dpll_pin_ref *ref;
+ int ret;
+
+ ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
+ ASSERT_NOT_NULL(ref);
+
+ ret = dpll_msg_add_pin_handle(msg, pin);
+ if (ret)
+ return ret;
+ if (nla_put_string(msg, DPLL_A_PIN_MODULE_NAME,
+ module_name(pin->module)))
+ return -EMSGSIZE;
+ if (nla_put_64bit(msg, DPLL_A_PIN_CLOCK_ID, sizeof(pin->clock_id),
+ &pin->clock_id, DPLL_A_PIN_PAD))
+ return -EMSGSIZE;
+ if (prop->board_label &&
+ nla_put_string(msg, DPLL_A_PIN_BOARD_LABEL, prop->board_label))
+ return -EMSGSIZE;
+ if (prop->panel_label &&
+ nla_put_string(msg, DPLL_A_PIN_PANEL_LABEL, prop->panel_label))
+ return -EMSGSIZE;
+ if (prop->package_label &&
+ nla_put_string(msg, DPLL_A_PIN_PACKAGE_LABEL,
+ prop->package_label))
+ return -EMSGSIZE;
+ if (nla_put_u32(msg, DPLL_A_PIN_TYPE, prop->type))
+ return -EMSGSIZE;
+ if (nla_put_u32(msg, DPLL_A_PIN_CAPABILITIES, prop->capabilities))
+ return -EMSGSIZE;
+ ret = dpll_msg_add_pin_freq(msg, pin, ref, extack);
+ if (ret)
+ return ret;
+ if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MIN,
+ prop->phase_range.min))
+ return -EMSGSIZE;
+ if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MAX,
+ prop->phase_range.max))
+ return -EMSGSIZE;
+ ret = dpll_msg_add_pin_phase_adjust(msg, pin, ref, extack);
+ if (ret)
+ return ret;
+ if (xa_empty(&pin->parent_refs))
+ ret = dpll_msg_add_pin_dplls(msg, pin, extack);
+ else
+ ret = dpll_msg_add_pin_parents(msg, pin, ref, extack);
+
+ return ret;
+}
+
+static int
+dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg,
+ struct netlink_ext_ack *extack)
+{
+ int ret;
+
+ ret = dpll_msg_add_dev_handle(msg, dpll);
+ if (ret)
+ return ret;
+ if (nla_put_string(msg, DPLL_A_MODULE_NAME, module_name(dpll->module)))
+ return -EMSGSIZE;
+ if (nla_put_64bit(msg, DPLL_A_CLOCK_ID, sizeof(dpll->clock_id),
+ &dpll->clock_id, DPLL_A_PAD))
+ return -EMSGSIZE;
+ ret = dpll_msg_add_temp(msg, dpll, extack);
+ if (ret)
+ return ret;
+ ret = dpll_msg_add_lock_status(msg, dpll, extack);
+ if (ret)
+ return ret;
+ ret = dpll_msg_add_mode(msg, dpll, extack);
+ if (ret)
+ return ret;
+ ret = dpll_msg_add_mode_supported(msg, dpll, extack);
+ if (ret)
+ return ret;
+ if (nla_put_u32(msg, DPLL_A_TYPE, dpll->type))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int
+dpll_device_event_send(enum dpll_cmd event, struct dpll_device *dpll)
+{
+ struct sk_buff *msg;
+ int ret = -ENOMEM;
+ void *hdr;
+
+ if (WARN_ON(!xa_get_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED)))
+ return -ENODEV;
+ msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+ hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event);
+ if (!hdr)
+ goto err_free_msg;
+ ret = dpll_device_get_one(dpll, msg, NULL);
+ if (ret)
+ goto err_cancel_msg;
+ genlmsg_end(msg, hdr);
+ genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL);
+
+ return 0;
+
+err_cancel_msg:
+ genlmsg_cancel(msg, hdr);
+err_free_msg:
+ nlmsg_free(msg);
+
+ return ret;
+}
+
+int dpll_device_create_ntf(struct dpll_device *dpll)
+{
+ return dpll_device_event_send(DPLL_CMD_DEVICE_CREATE_NTF, dpll);
+}
+
+int dpll_device_delete_ntf(struct dpll_device *dpll)
+{
+ return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF, dpll);
+}
+
+static int
+__dpll_device_change_ntf(struct dpll_device *dpll)
+{
+ return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll);
+}
+
+/**
+ * dpll_device_change_ntf - notify that the dpll device has been changed
+ * @dpll: registered dpll pointer
+ *
+ * Context: acquires and holds a dpll_lock.
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_device_change_ntf(struct dpll_device *dpll)
+{
+ int ret;
+
+ mutex_lock(&dpll_lock);
+ ret = __dpll_device_change_ntf(dpll);
+ mutex_unlock(&dpll_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dpll_device_change_ntf);
+
+static int
+dpll_pin_event_send(enum dpll_cmd event, struct dpll_pin *pin)
+{
+ struct sk_buff *msg;
+ int ret = -ENOMEM;
+ void *hdr;
+
+ if (WARN_ON(!xa_get_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED)))
+ return -ENODEV;
+
+ msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event);
+ if (!hdr)
+ goto err_free_msg;
+ ret = dpll_cmd_pin_get_one(msg, pin, NULL);
+ if (ret)
+ goto err_cancel_msg;
+ genlmsg_end(msg, hdr);
+ genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL);
+
+ return 0;
+
+err_cancel_msg:
+ genlmsg_cancel(msg, hdr);
+err_free_msg:
+ nlmsg_free(msg);
+
+ return ret;
+}
+
+int dpll_pin_create_ntf(struct dpll_pin *pin)
+{
+ return dpll_pin_event_send(DPLL_CMD_PIN_CREATE_NTF, pin);
+}
+
+int dpll_pin_delete_ntf(struct dpll_pin *pin)
+{
+ return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF, pin);
+}
+
+static int __dpll_pin_change_ntf(struct dpll_pin *pin)
+{
+ return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF, pin);
+}
+
+/**
+ * dpll_pin_change_ntf - notify that the pin has been changed
+ * @pin: registered pin pointer
+ *
+ * Context: acquires and holds a dpll_lock.
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_change_ntf(struct dpll_pin *pin)
+{
+ int ret;
+
+ mutex_lock(&dpll_lock);
+ ret = __dpll_pin_change_ntf(pin);
+ mutex_unlock(&dpll_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_change_ntf);
+
+static int
+dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a,
+ struct netlink_ext_ack *extack)
+{
+ u64 freq = nla_get_u64(a), old_freq;
+ struct dpll_pin_ref *ref, *failed;
+ const struct dpll_pin_ops *ops;
+ struct dpll_device *dpll;
+ unsigned long i;
+ int ret;
+
+ if (!dpll_pin_is_freq_supported(pin, freq)) {
+ NL_SET_ERR_MSG_ATTR(extack, a, "frequency is not supported by the device");
+ return -EINVAL;
+ }
+
+ xa_for_each(&pin->dpll_refs, i, ref) {
+ ops = dpll_pin_ops(ref);
+ if (!ops->frequency_set || !ops->frequency_get) {
+ NL_SET_ERR_MSG(extack, "frequency set not supported by the device");
+ return -EOPNOTSUPP;
+ }
+ }
+ ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
+ ops = dpll_pin_ops(ref);
+ dpll = ref->dpll;
+ ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
+ dpll_priv(dpll), &old_freq, extack);
+ if (ret) {
+ NL_SET_ERR_MSG(extack, "unable to get old frequency value");
+ return ret;
+ }
+ if (freq == old_freq)
+ return 0;
+
+ xa_for_each(&pin->dpll_refs, i, ref) {
+ ops = dpll_pin_ops(ref);
+ dpll = ref->dpll;
+ ret = ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
+ dpll, dpll_priv(dpll), freq, extack);
+ if (ret) {
+ failed = ref;
+ NL_SET_ERR_MSG_FMT(extack, "frequency set failed for dpll_id:%u",
+ dpll->id);
+ goto rollback;
+ }
+ }
+ __dpll_pin_change_ntf(pin);
+
+ return 0;
+
+rollback:
+ xa_for_each(&pin->dpll_refs, i, ref) {
+ if (ref == failed)
+ break;
+ ops = dpll_pin_ops(ref);
+ dpll = ref->dpll;
+ if (ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
+ dpll, dpll_priv(dpll), old_freq, extack))
+ NL_SET_ERR_MSG(extack, "set frequency rollback failed");
+ }
+ return ret;
+}
+
+static int
+dpll_pin_on_pin_state_set(struct dpll_pin *pin, u32 parent_idx,
+ enum dpll_pin_state state,
+ struct netlink_ext_ack *extack)
+{
+ struct dpll_pin_ref *parent_ref;
+ const struct dpll_pin_ops *ops;
+ struct dpll_pin_ref *dpll_ref;
+ void *pin_priv, *parent_priv;
+ struct dpll_pin *parent;
+ unsigned long i;
+ int ret;
+
+ if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
+ pin->prop->capabilities)) {
+ NL_SET_ERR_MSG(extack, "state changing is not allowed");
+ return -EOPNOTSUPP;
+ }
+ parent = xa_load(&dpll_pin_xa, parent_idx);
+ if (!parent)
+ return -EINVAL;
+ parent_ref = xa_load(&pin->parent_refs, parent->pin_idx);
+ if (!parent_ref)
+ return -EINVAL;
+ xa_for_each(&parent->dpll_refs, i, dpll_ref) {
+ ops = dpll_pin_ops(parent_ref);
+ if (!ops->state_on_pin_set)
+ return -EOPNOTSUPP;
+ pin_priv = dpll_pin_on_pin_priv(parent, pin);
+ parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, parent);
+ ret = ops->state_on_pin_set(pin, pin_priv, parent, parent_priv,
+ state, extack);
+ if (ret)
+ return ret;
+ }
+ __dpll_pin_change_ntf(pin);
+
+ return 0;
+}
+
+static int
+dpll_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin,
+ enum dpll_pin_state state,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_pin_ops *ops;
+ struct dpll_pin_ref *ref;
+ int ret;
+
+ if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
+ pin->prop->capabilities)) {
+ NL_SET_ERR_MSG(extack, "state changing is not allowed");
+ return -EOPNOTSUPP;
+ }
+ ref = xa_load(&pin->dpll_refs, dpll->id);
+ ASSERT_NOT_NULL(ref);
+ ops = dpll_pin_ops(ref);
+ if (!ops->state_on_dpll_set)
+ return -EOPNOTSUPP;
+ ret = ops->state_on_dpll_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
+ dpll, dpll_priv(dpll), state, extack);
+ if (ret)
+ return ret;
+ __dpll_pin_change_ntf(pin);
+
+ return 0;
+}
+
+static int
+dpll_pin_prio_set(struct dpll_device *dpll, struct dpll_pin *pin,
+ u32 prio, struct netlink_ext_ack *extack)
+{
+ const struct dpll_pin_ops *ops;
+ struct dpll_pin_ref *ref;
+ int ret;
+
+ if (!(DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE &
+ pin->prop->capabilities)) {
+ NL_SET_ERR_MSG(extack, "prio changing is not allowed");
+ return -EOPNOTSUPP;
+ }
+ ref = xa_load(&pin->dpll_refs, dpll->id);
+ ASSERT_NOT_NULL(ref);
+ ops = dpll_pin_ops(ref);
+ if (!ops->prio_set)
+ return -EOPNOTSUPP;
+ ret = ops->prio_set(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
+ dpll_priv(dpll), prio, extack);
+ if (ret)
+ return ret;
+ __dpll_pin_change_ntf(pin);
+
+ return 0;
+}
+
+static int
+dpll_pin_direction_set(struct dpll_pin *pin, struct dpll_device *dpll,
+ enum dpll_pin_direction direction,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_pin_ops *ops;
+ struct dpll_pin_ref *ref;
+ int ret;
+
+ if (!(DPLL_PIN_CAPABILITIES_DIRECTION_CAN_CHANGE &
+ pin->prop->capabilities)) {
+ NL_SET_ERR_MSG(extack, "direction changing is not allowed");
+ return -EOPNOTSUPP;
+ }
+ ref = xa_load(&pin->dpll_refs, dpll->id);
+ ASSERT_NOT_NULL(ref);
+ ops = dpll_pin_ops(ref);
+ if (!ops->direction_set)
+ return -EOPNOTSUPP;
+ ret = ops->direction_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
+ dpll, dpll_priv(dpll), direction, extack);
+ if (ret)
+ return ret;
+ __dpll_pin_change_ntf(pin);
+
+ return 0;
+}
+
+static int
+dpll_pin_phase_adj_set(struct dpll_pin *pin, struct nlattr *phase_adj_attr,
+ struct netlink_ext_ack *extack)
+{
+ struct dpll_pin_ref *ref, *failed;
+ const struct dpll_pin_ops *ops;
+ s32 phase_adj, old_phase_adj;
+ struct dpll_device *dpll;
+ unsigned long i;
+ int ret;
+
+ phase_adj = nla_get_s32(phase_adj_attr);
+ if (phase_adj > pin->prop->phase_range.max ||
+ phase_adj < pin->prop->phase_range.min) {
+ NL_SET_ERR_MSG_ATTR(extack, phase_adj_attr,
+ "phase adjust value not supported");
+ return -EINVAL;
+ }
+
+ xa_for_each(&pin->dpll_refs, i, ref) {
+ ops = dpll_pin_ops(ref);
+ if (!ops->phase_adjust_set || !ops->phase_adjust_get) {
+ NL_SET_ERR_MSG(extack, "phase adjust not supported");
+ return -EOPNOTSUPP;
+ }
+ }
+ ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
+ ops = dpll_pin_ops(ref);
+ dpll = ref->dpll;
+ ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
+ dpll, dpll_priv(dpll), &old_phase_adj,
+ extack);
+ if (ret) {
+ NL_SET_ERR_MSG(extack, "unable to get old phase adjust value");
+ return ret;
+ }
+ if (phase_adj == old_phase_adj)
+ return 0;
+
+ xa_for_each(&pin->dpll_refs, i, ref) {
+ ops = dpll_pin_ops(ref);
+ dpll = ref->dpll;
+ ret = ops->phase_adjust_set(pin,
+ dpll_pin_on_dpll_priv(dpll, pin),
+ dpll, dpll_priv(dpll), phase_adj,
+ extack);
+ if (ret) {
+ failed = ref;
+ NL_SET_ERR_MSG_FMT(extack,
+ "phase adjust set failed for dpll_id:%u",
+ dpll->id);
+ goto rollback;
+ }
+ }
+ __dpll_pin_change_ntf(pin);
+
+ return 0;
+
+rollback:
+ xa_for_each(&pin->dpll_refs, i, ref) {
+ if (ref == failed)
+ break;
+ ops = dpll_pin_ops(ref);
+ dpll = ref->dpll;
+ if (ops->phase_adjust_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
+ dpll, dpll_priv(dpll), old_phase_adj,
+ extack))
+ NL_SET_ERR_MSG(extack, "set phase adjust rollback failed");
+ }
+ return ret;
+}
+
+static int
+dpll_pin_parent_device_set(struct dpll_pin *pin, struct nlattr *parent_nest,
+ struct netlink_ext_ack *extack)
+{
+ struct nlattr *tb[DPLL_A_PIN_MAX + 1];
+ enum dpll_pin_direction direction;
+ enum dpll_pin_state state;
+ struct dpll_pin_ref *ref;
+ struct dpll_device *dpll;
+ u32 pdpll_idx, prio;
+ int ret;
+
+ nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest,
+ dpll_pin_parent_device_nl_policy, extack);
+ if (!tb[DPLL_A_PIN_PARENT_ID]) {
+ NL_SET_ERR_MSG(extack, "device parent id expected");
+ return -EINVAL;
+ }
+ pdpll_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
+ dpll = xa_load(&dpll_device_xa, pdpll_idx);
+ if (!dpll) {
+ NL_SET_ERR_MSG(extack, "parent device not found");
+ return -EINVAL;
+ }
+ ref = xa_load(&pin->dpll_refs, dpll->id);
+ if (!ref) {
+ NL_SET_ERR_MSG(extack, "pin not connected to given parent device");
+ return -EINVAL;
+ }
+ if (tb[DPLL_A_PIN_STATE]) {
+ state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
+ ret = dpll_pin_state_set(dpll, pin, state, extack);
+ if (ret)
+ return ret;
+ }
+ if (tb[DPLL_A_PIN_PRIO]) {
+ prio = nla_get_u32(tb[DPLL_A_PIN_PRIO]);
+ ret = dpll_pin_prio_set(dpll, pin, prio, extack);
+ if (ret)
+ return ret;
+ }
+ if (tb[DPLL_A_PIN_DIRECTION]) {
+ direction = nla_get_u32(tb[DPLL_A_PIN_DIRECTION]);
+ ret = dpll_pin_direction_set(pin, dpll, direction, extack);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int
+dpll_pin_parent_pin_set(struct dpll_pin *pin, struct nlattr *parent_nest,
+ struct netlink_ext_ack *extack)
+{
+ struct nlattr *tb[DPLL_A_PIN_MAX + 1];
+ u32 ppin_idx;
+ int ret;
+
+ nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest,
+ dpll_pin_parent_pin_nl_policy, extack);
+ if (!tb[DPLL_A_PIN_PARENT_ID]) {
+ NL_SET_ERR_MSG(extack, "device parent id expected");
+ return -EINVAL;
+ }
+ ppin_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
+
+ if (tb[DPLL_A_PIN_STATE]) {
+ enum dpll_pin_state state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
+
+ ret = dpll_pin_on_pin_state_set(pin, ppin_idx, state, extack);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info)
+{
+ struct nlattr *a;
+ int rem, ret;
+
+ nla_for_each_attr(a, genlmsg_data(info->genlhdr),
+ genlmsg_len(info->genlhdr), rem) {
+ switch (nla_type(a)) {
+ case DPLL_A_PIN_FREQUENCY:
+ ret = dpll_pin_freq_set(pin, a, info->extack);
+ if (ret)
+ return ret;
+ break;
+ case DPLL_A_PIN_PHASE_ADJUST:
+ ret = dpll_pin_phase_adj_set(pin, a, info->extack);
+ if (ret)
+ return ret;
+ break;
+ case DPLL_A_PIN_PARENT_DEVICE:
+ ret = dpll_pin_parent_device_set(pin, a, info->extack);
+ if (ret)
+ return ret;
+ break;
+ case DPLL_A_PIN_PARENT_PIN:
+ ret = dpll_pin_parent_pin_set(pin, a, info->extack);
+ if (ret)
+ return ret;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static struct dpll_pin *
+dpll_pin_find(u64 clock_id, struct nlattr *mod_name_attr,
+ enum dpll_pin_type type, struct nlattr *board_label,
+ struct nlattr *panel_label, struct nlattr *package_label,
+ struct netlink_ext_ack *extack)
+{
+ bool board_match, panel_match, package_match;
+ struct dpll_pin *pin_match = NULL, *pin;
+ const struct dpll_pin_properties *prop;
+ bool cid_match, mod_match, type_match;
+ unsigned long i;
+
+ xa_for_each_marked(&dpll_pin_xa, i, pin, DPLL_REGISTERED) {
+ prop = pin->prop;
+ cid_match = clock_id ? pin->clock_id == clock_id : true;
+ mod_match = mod_name_attr && module_name(pin->module) ?
+ !nla_strcmp(mod_name_attr,
+ module_name(pin->module)) : true;
+ type_match = type ? prop->type == type : true;
+ board_match = board_label ? (prop->board_label ?
+ !nla_strcmp(board_label, prop->board_label) : false) :
+ true;
+ panel_match = panel_label ? (prop->panel_label ?
+ !nla_strcmp(panel_label, prop->panel_label) : false) :
+ true;
+ package_match = package_label ? (prop->package_label ?
+ !nla_strcmp(package_label, prop->package_label) :
+ false) : true;
+ if (cid_match && mod_match && type_match && board_match &&
+ panel_match && package_match) {
+ if (pin_match) {
+ NL_SET_ERR_MSG(extack, "multiple matches");
+ return ERR_PTR(-EINVAL);
+ }
+ pin_match = pin;
+ }
+ }
+ if (!pin_match) {
+ NL_SET_ERR_MSG(extack, "not found");
+ return ERR_PTR(-ENODEV);
+ }
+ return pin_match;
+}
+
+static struct dpll_pin *dpll_pin_find_from_nlattr(struct genl_info *info)
+{
+ struct nlattr *attr, *mod_name_attr = NULL, *board_label_attr = NULL,
+ *panel_label_attr = NULL, *package_label_attr = NULL;
+ enum dpll_pin_type type = 0;
+ u64 clock_id = 0;
+ int rem = 0;
+
+ nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
+ genlmsg_len(info->genlhdr), rem) {
+ switch (nla_type(attr)) {
+ case DPLL_A_PIN_CLOCK_ID:
+ if (clock_id)
+ goto duplicated_attr;
+ clock_id = nla_get_u64(attr);
+ break;
+ case DPLL_A_PIN_MODULE_NAME:
+ if (mod_name_attr)
+ goto duplicated_attr;
+ mod_name_attr = attr;
+ break;
+ case DPLL_A_PIN_TYPE:
+ if (type)
+ goto duplicated_attr;
+ type = nla_get_u32(attr);
+ break;
+ case DPLL_A_PIN_BOARD_LABEL:
+ if (board_label_attr)
+ goto duplicated_attr;
+ board_label_attr = attr;
+ break;
+ case DPLL_A_PIN_PANEL_LABEL:
+ if (panel_label_attr)
+ goto duplicated_attr;
+ panel_label_attr = attr;
+ break;
+ case DPLL_A_PIN_PACKAGE_LABEL:
+ if (package_label_attr)
+ goto duplicated_attr;
+ package_label_attr = attr;
+ break;
+ default:
+ break;
+ }
+ }
+ if (!(clock_id || mod_name_attr || board_label_attr ||
+ panel_label_attr || package_label_attr)) {
+ NL_SET_ERR_MSG(info->extack, "missing attributes");
+ return ERR_PTR(-EINVAL);
+ }
+ return dpll_pin_find(clock_id, mod_name_attr, type, board_label_attr,
+ panel_label_attr, package_label_attr,
+ info->extack);
+duplicated_attr:
+ NL_SET_ERR_MSG(info->extack, "duplicated attribute");
+ return ERR_PTR(-EINVAL);
+}
+
+int dpll_nl_pin_id_get_doit(struct sk_buff *skb, struct genl_info *info)
+{
+ struct dpll_pin *pin;
+ struct sk_buff *msg;
+ struct nlattr *hdr;
+ int ret;
+
+ msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+ hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
+ DPLL_CMD_PIN_ID_GET);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return -EMSGSIZE;
+ }
+ pin = dpll_pin_find_from_nlattr(info);
+ if (!IS_ERR(pin)) {
+ ret = dpll_msg_add_pin_handle(msg, pin);
+ if (ret) {
+ nlmsg_free(msg);
+ return ret;
+ }
+ }
+ genlmsg_end(msg, hdr);
+
+ return genlmsg_reply(msg, info);
+}
+
+int dpll_nl_pin_get_doit(struct sk_buff *skb, struct genl_info *info)
+{
+ struct dpll_pin *pin = info->user_ptr[0];
+ struct sk_buff *msg;
+ struct nlattr *hdr;
+ int ret;
+
+ if (!pin)
+ return -ENODEV;
+ msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+ hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
+ DPLL_CMD_PIN_GET);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return -EMSGSIZE;
+ }
+ ret = dpll_cmd_pin_get_one(msg, pin, info->extack);
+ if (ret) {
+ nlmsg_free(msg);
+ return ret;
+ }
+ genlmsg_end(msg, hdr);
+
+ return genlmsg_reply(msg, info);
+}
+
+int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
+ struct dpll_pin *pin;
+ struct nlattr *hdr;
+ unsigned long i;
+ int ret = 0;
+
+ xa_for_each_marked_start(&dpll_pin_xa, i, pin, DPLL_REGISTERED,
+ ctx->idx) {
+ hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq,
+ &dpll_nl_family, NLM_F_MULTI,
+ DPLL_CMD_PIN_GET);
+ if (!hdr) {
+ ret = -EMSGSIZE;
+ break;
+ }
+ ret = dpll_cmd_pin_get_one(skb, pin, cb->extack);
+ if (ret) {
+ genlmsg_cancel(skb, hdr);
+ break;
+ }
+ genlmsg_end(skb, hdr);
+ }
+ if (ret == -EMSGSIZE) {
+ ctx->idx = i;
+ return skb->len;
+ }
+ return ret;
+}
+
+int dpll_nl_pin_set_doit(struct sk_buff *skb, struct genl_info *info)
+{
+ struct dpll_pin *pin = info->user_ptr[0];
+
+ return dpll_pin_set_from_nlattr(pin, info);
+}
+
+static struct dpll_device *
+dpll_device_find(u64 clock_id, struct nlattr *mod_name_attr,
+ enum dpll_type type, struct netlink_ext_ack *extack)
+{
+ struct dpll_device *dpll_match = NULL, *dpll;
+ bool cid_match, mod_match, type_match;
+ unsigned long i;
+
+ xa_for_each_marked(&dpll_device_xa, i, dpll, DPLL_REGISTERED) {
+ cid_match = clock_id ? dpll->clock_id == clock_id : true;
+ mod_match = mod_name_attr ? (module_name(dpll->module) ?
+ !nla_strcmp(mod_name_attr,
+ module_name(dpll->module)) : false) : true;
+ type_match = type ? dpll->type == type : true;
+ if (cid_match && mod_match && type_match) {
+ if (dpll_match) {
+ NL_SET_ERR_MSG(extack, "multiple matches");
+ return ERR_PTR(-EINVAL);
+ }
+ dpll_match = dpll;
+ }
+ }
+ if (!dpll_match) {
+ NL_SET_ERR_MSG(extack, "not found");
+ return ERR_PTR(-ENODEV);
+ }
+
+ return dpll_match;
+}
+
+static struct dpll_device *
+dpll_device_find_from_nlattr(struct genl_info *info)
+{
+ struct nlattr *attr, *mod_name_attr = NULL;
+ enum dpll_type type = 0;
+ u64 clock_id = 0;
+ int rem = 0;
+
+ nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
+ genlmsg_len(info->genlhdr), rem) {
+ switch (nla_type(attr)) {
+ case DPLL_A_CLOCK_ID:
+ if (clock_id)
+ goto duplicated_attr;
+ clock_id = nla_get_u64(attr);
+ break;
+ case DPLL_A_MODULE_NAME:
+ if (mod_name_attr)
+ goto duplicated_attr;
+ mod_name_attr = attr;
+ break;
+ case DPLL_A_TYPE:
+ if (type)
+ goto duplicated_attr;
+ type = nla_get_u32(attr);
+ break;
+ default:
+ break;
+ }
+ }
+ if (!clock_id && !mod_name_attr && !type) {
+ NL_SET_ERR_MSG(info->extack, "missing attributes");
+ return ERR_PTR(-EINVAL);
+ }
+ return dpll_device_find(clock_id, mod_name_attr, type, info->extack);
+duplicated_attr:
+ NL_SET_ERR_MSG(info->extack, "duplicated attribute");
+ return ERR_PTR(-EINVAL);
+}
+
+int dpll_nl_device_id_get_doit(struct sk_buff *skb, struct genl_info *info)
+{
+ struct dpll_device *dpll;
+ struct sk_buff *msg;
+ struct nlattr *hdr;
+ int ret;
+
+ msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+ hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
+ DPLL_CMD_DEVICE_ID_GET);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return -EMSGSIZE;
+ }
+
+ dpll = dpll_device_find_from_nlattr(info);
+ if (!IS_ERR(dpll)) {
+ ret = dpll_msg_add_dev_handle(msg, dpll);
+ if (ret) {
+ nlmsg_free(msg);
+ return ret;
+ }
+ }
+ genlmsg_end(msg, hdr);
+
+ return genlmsg_reply(msg, info);
+}
+
+int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info)
+{
+ struct dpll_device *dpll = info->user_ptr[0];
+ struct sk_buff *msg;
+ struct nlattr *hdr;
+ int ret;
+
+ msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+ hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
+ DPLL_CMD_DEVICE_GET);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return -EMSGSIZE;
+ }
+
+ ret = dpll_device_get_one(dpll, msg, info->extack);
+ if (ret) {
+ nlmsg_free(msg);
+ return ret;
+ }
+ genlmsg_end(msg, hdr);
+
+ return genlmsg_reply(msg, info);
+}
+
+int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info)
+{
+ /* placeholder for set command */
+ return 0;
+}
+
+int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
+ struct dpll_device *dpll;
+ struct nlattr *hdr;
+ unsigned long i;
+ int ret = 0;
+
+ xa_for_each_marked_start(&dpll_device_xa, i, dpll, DPLL_REGISTERED,
+ ctx->idx) {
+ hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq, &dpll_nl_family,
+ NLM_F_MULTI, DPLL_CMD_DEVICE_GET);
+ if (!hdr) {
+ ret = -EMSGSIZE;
+ break;
+ }
+ ret = dpll_device_get_one(dpll, skb, cb->extack);
+ if (ret) {
+ genlmsg_cancel(skb, hdr);
+ break;
+ }
+ genlmsg_end(skb, hdr);
+ }
+ if (ret == -EMSGSIZE) {
+ ctx->idx = i;
+ return skb->len;
+ }
+ return ret;
+}
+
+int dpll_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
+ struct genl_info *info)
+{
+ u32 id;
+
+ if (GENL_REQ_ATTR_CHECK(info, DPLL_A_ID))
+ return -EINVAL;
+
+ mutex_lock(&dpll_lock);
+ id = nla_get_u32(info->attrs[DPLL_A_ID]);
+ info->user_ptr[0] = dpll_device_get_by_id(id);
+ if (!info->user_ptr[0]) {
+ NL_SET_ERR_MSG(info->extack, "device not found");
+ goto unlock;
+ }
+ return 0;
+unlock:
+ mutex_unlock(&dpll_lock);
+ return -ENODEV;
+}
+
+void dpll_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
+ struct genl_info *info)
+{
+ mutex_unlock(&dpll_lock);
+}
+
+int
+dpll_lock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
+ struct genl_info *info)
+{
+ mutex_lock(&dpll_lock);
+
+ return 0;
+}
+
+void
+dpll_unlock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
+ struct genl_info *info)
+{
+ mutex_unlock(&dpll_lock);
+}
+
+int dpll_lock_dumpit(struct netlink_callback *cb)
+{
+ mutex_lock(&dpll_lock);
+
+ return 0;
+}
+
+int dpll_unlock_dumpit(struct netlink_callback *cb)
+{
+ mutex_unlock(&dpll_lock);
+
+ return 0;
+}
+
+int dpll_pin_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
+ struct genl_info *info)
+{
+ int ret;
+
+ mutex_lock(&dpll_lock);
+ if (GENL_REQ_ATTR_CHECK(info, DPLL_A_PIN_ID)) {
+ ret = -EINVAL;
+ goto unlock_dev;
+ }
+ info->user_ptr[0] = xa_load(&dpll_pin_xa,
+ nla_get_u32(info->attrs[DPLL_A_PIN_ID]));
+ if (!info->user_ptr[0]) {
+ NL_SET_ERR_MSG(info->extack, "pin not found");
+ ret = -ENODEV;
+ goto unlock_dev;
+ }
+
+ return 0;
+
+unlock_dev:
+ mutex_unlock(&dpll_lock);
+ return ret;
+}
+
+void dpll_pin_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
+ struct genl_info *info)
+{
+ mutex_unlock(&dpll_lock);
+}
diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
new file mode 100644
index 000000000000..a9cfd55f57fc
--- /dev/null
+++ b/drivers/dpll/dpll_netlink.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 Meta Platforms, Inc. and affiliates
+ * Copyright (c) 2023 Intel and affiliates
+ */
+
+int dpll_device_create_ntf(struct dpll_device *dpll);
+
+int dpll_device_delete_ntf(struct dpll_device *dpll);
+
+int dpll_pin_create_ntf(struct dpll_pin *pin);
+
+int dpll_pin_delete_ntf(struct dpll_pin *pin);
diff --git a/drivers/dpll/dpll_nl.c b/drivers/dpll/dpll_nl.c
new file mode 100644
index 000000000000..eaee5be7aa64
--- /dev/null
+++ b/drivers/dpll/dpll_nl.c
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/dpll.yaml */
+/* YNL-GEN kernel source */
+
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include "dpll_nl.h"
+
+#include <uapi/linux/dpll.h>
+
+/* Common nested types */
+const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_PHASE_OFFSET + 1] = {
+ [DPLL_A_PIN_PARENT_ID] = { .type = NLA_U32, },
+ [DPLL_A_PIN_DIRECTION] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
+ [DPLL_A_PIN_PRIO] = { .type = NLA_U32, },
+ [DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 3),
+ [DPLL_A_PIN_PHASE_OFFSET] = { .type = NLA_S64, },
+};
+
+const struct nla_policy dpll_pin_parent_pin_nl_policy[DPLL_A_PIN_STATE + 1] = {
+ [DPLL_A_PIN_PARENT_ID] = { .type = NLA_U32, },
+ [DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 3),
+};
+
+/* DPLL_CMD_DEVICE_ID_GET - do */
+static const struct nla_policy dpll_device_id_get_nl_policy[DPLL_A_TYPE + 1] = {
+ [DPLL_A_MODULE_NAME] = { .type = NLA_NUL_STRING, },
+ [DPLL_A_CLOCK_ID] = { .type = NLA_U64, },
+ [DPLL_A_TYPE] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
+};
+
+/* DPLL_CMD_DEVICE_GET - do */
+static const struct nla_policy dpll_device_get_nl_policy[DPLL_A_ID + 1] = {
+ [DPLL_A_ID] = { .type = NLA_U32, },
+};
+
+/* DPLL_CMD_DEVICE_SET - do */
+static const struct nla_policy dpll_device_set_nl_policy[DPLL_A_ID + 1] = {
+ [DPLL_A_ID] = { .type = NLA_U32, },
+};
+
+/* DPLL_CMD_PIN_ID_GET - do */
+static const struct nla_policy dpll_pin_id_get_nl_policy[DPLL_A_PIN_TYPE + 1] = {
+ [DPLL_A_PIN_MODULE_NAME] = { .type = NLA_NUL_STRING, },
+ [DPLL_A_PIN_CLOCK_ID] = { .type = NLA_U64, },
+ [DPLL_A_PIN_BOARD_LABEL] = { .type = NLA_NUL_STRING, },
+ [DPLL_A_PIN_PANEL_LABEL] = { .type = NLA_NUL_STRING, },
+ [DPLL_A_PIN_PACKAGE_LABEL] = { .type = NLA_NUL_STRING, },
+ [DPLL_A_PIN_TYPE] = NLA_POLICY_RANGE(NLA_U32, 1, 5),
+};
+
+/* DPLL_CMD_PIN_GET - do */
+static const struct nla_policy dpll_pin_get_do_nl_policy[DPLL_A_PIN_ID + 1] = {
+ [DPLL_A_PIN_ID] = { .type = NLA_U32, },
+};
+
+/* DPLL_CMD_PIN_GET - dump */
+static const struct nla_policy dpll_pin_get_dump_nl_policy[DPLL_A_PIN_ID + 1] = {
+ [DPLL_A_PIN_ID] = { .type = NLA_U32, },
+};
+
+/* DPLL_CMD_PIN_SET - do */
+static const struct nla_policy dpll_pin_set_nl_policy[DPLL_A_PIN_PHASE_ADJUST + 1] = {
+ [DPLL_A_PIN_ID] = { .type = NLA_U32, },
+ [DPLL_A_PIN_FREQUENCY] = { .type = NLA_U64, },
+ [DPLL_A_PIN_DIRECTION] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
+ [DPLL_A_PIN_PRIO] = { .type = NLA_U32, },
+ [DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 3),
+ [DPLL_A_PIN_PARENT_DEVICE] = NLA_POLICY_NESTED(dpll_pin_parent_device_nl_policy),
+ [DPLL_A_PIN_PARENT_PIN] = NLA_POLICY_NESTED(dpll_pin_parent_pin_nl_policy),
+ [DPLL_A_PIN_PHASE_ADJUST] = { .type = NLA_S32, },
+};
+
+/* Ops table for dpll */
+static const struct genl_split_ops dpll_nl_ops[] = {
+ {
+ .cmd = DPLL_CMD_DEVICE_ID_GET,
+ .pre_doit = dpll_lock_doit,
+ .doit = dpll_nl_device_id_get_doit,
+ .post_doit = dpll_unlock_doit,
+ .policy = dpll_device_id_get_nl_policy,
+ .maxattr = DPLL_A_TYPE,
+ .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+ },
+ {
+ .cmd = DPLL_CMD_DEVICE_GET,
+ .pre_doit = dpll_pre_doit,
+ .doit = dpll_nl_device_get_doit,
+ .post_doit = dpll_post_doit,
+ .policy = dpll_device_get_nl_policy,
+ .maxattr = DPLL_A_ID,
+ .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+ },
+ {
+ .cmd = DPLL_CMD_DEVICE_GET,
+ .start = dpll_lock_dumpit,
+ .dumpit = dpll_nl_device_get_dumpit,
+ .done = dpll_unlock_dumpit,
+ .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP,
+ },
+ {
+ .cmd = DPLL_CMD_DEVICE_SET,
+ .pre_doit = dpll_pre_doit,
+ .doit = dpll_nl_device_set_doit,
+ .post_doit = dpll_post_doit,
+ .policy = dpll_device_set_nl_policy,
+ .maxattr = DPLL_A_ID,
+ .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+ },
+ {
+ .cmd = DPLL_CMD_PIN_ID_GET,
+ .pre_doit = dpll_lock_doit,
+ .doit = dpll_nl_pin_id_get_doit,
+ .post_doit = dpll_unlock_doit,
+ .policy = dpll_pin_id_get_nl_policy,
+ .maxattr = DPLL_A_PIN_TYPE,
+ .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+ },
+ {
+ .cmd = DPLL_CMD_PIN_GET,
+ .pre_doit = dpll_pin_pre_doit,
+ .doit = dpll_nl_pin_get_doit,
+ .post_doit = dpll_pin_post_doit,
+ .policy = dpll_pin_get_do_nl_policy,
+ .maxattr = DPLL_A_PIN_ID,
+ .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+ },
+ {
+ .cmd = DPLL_CMD_PIN_GET,
+ .start = dpll_lock_dumpit,
+ .dumpit = dpll_nl_pin_get_dumpit,
+ .done = dpll_unlock_dumpit,
+ .policy = dpll_pin_get_dump_nl_policy,
+ .maxattr = DPLL_A_PIN_ID,
+ .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP,
+ },
+ {
+ .cmd = DPLL_CMD_PIN_SET,
+ .pre_doit = dpll_pin_pre_doit,
+ .doit = dpll_nl_pin_set_doit,
+ .post_doit = dpll_pin_post_doit,
+ .policy = dpll_pin_set_nl_policy,
+ .maxattr = DPLL_A_PIN_PHASE_ADJUST,
+ .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+ },
+};
+
+static const struct genl_multicast_group dpll_nl_mcgrps[] = {
+ [DPLL_NLGRP_MONITOR] = { "monitor", },
+};
+
+struct genl_family dpll_nl_family __ro_after_init = {
+ .name = DPLL_FAMILY_NAME,
+ .version = DPLL_FAMILY_VERSION,
+ .netnsok = true,
+ .parallel_ops = true,
+ .module = THIS_MODULE,
+ .split_ops = dpll_nl_ops,
+ .n_split_ops = ARRAY_SIZE(dpll_nl_ops),
+ .mcgrps = dpll_nl_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(dpll_nl_mcgrps),
+};
diff --git a/drivers/dpll/dpll_nl.h b/drivers/dpll/dpll_nl.h
new file mode 100644
index 000000000000..92d4c9c4f788
--- /dev/null
+++ b/drivers/dpll/dpll_nl.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/dpll.yaml */
+/* YNL-GEN kernel header */
+
+#ifndef _LINUX_DPLL_GEN_H
+#define _LINUX_DPLL_GEN_H
+
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include <uapi/linux/dpll.h>
+
+/* Common nested types */
+extern const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_PHASE_OFFSET + 1];
+extern const struct nla_policy dpll_pin_parent_pin_nl_policy[DPLL_A_PIN_STATE + 1];
+
+int dpll_lock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
+ struct genl_info *info);
+int dpll_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
+ struct genl_info *info);
+int dpll_pin_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
+ struct genl_info *info);
+void
+dpll_unlock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
+ struct genl_info *info);
+void
+dpll_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
+ struct genl_info *info);
+void
+dpll_pin_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
+ struct genl_info *info);
+int dpll_lock_dumpit(struct netlink_callback *cb);
+int dpll_unlock_dumpit(struct netlink_callback *cb);
+
+int dpll_nl_device_id_get_doit(struct sk_buff *skb, struct genl_info *info);
+int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info);
+int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
+int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info);
+int dpll_nl_pin_id_get_doit(struct sk_buff *skb, struct genl_info *info);
+int dpll_nl_pin_get_doit(struct sk_buff *skb, struct genl_info *info);
+int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
+int dpll_nl_pin_set_doit(struct sk_buff *skb, struct genl_info *info);
+
+enum {
+ DPLL_NLGRP_MONITOR,
+};
+
+extern struct genl_family dpll_nl_family;
+
+#endif /* _LINUX_DPLL_GEN_H */
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 110e99b86a66..5a7f3fabee22 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -561,4 +561,16 @@ config EDAC_NPCM
error detection (in-line ECC in which a section 1/8th of the memory
device used to store data is used for ECC storage).
+config EDAC_VERSAL
+ tristate "Xilinx Versal DDR Memory Controller"
+ depends on ARCH_ZYNQMP || COMPILE_TEST
+ help
+ Support for error detection and correction on the Xilinx Versal DDR
+ memory controller.
+
+ Report both single bit errors (CE) and double bit errors (UE).
+ Support injecting both correctable and uncorrectable errors
+ for debugging purposes.
+
+
endif # EDAC
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 61945d3113cc..9c09893695b7 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -86,3 +86,4 @@ obj-$(CONFIG_EDAC_BLUEFIELD) += bluefield_edac.o
obj-$(CONFIG_EDAC_DMC520) += dmc520_edac.o
obj-$(CONFIG_EDAC_NPCM) += npcm_edac.o
obj-$(CONFIG_EDAC_ZYNQMP) += zynqmp_edac.o
+obj-$(CONFIG_EDAC_VERSAL) += versal_edac.o
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 15f63452a9be..5116873c3330 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -229,7 +229,7 @@ static ssize_t channel_dimm_label_store(struct device *dev,
if (copy_count == 0 || copy_count >= sizeof(rank->dimm->label))
return -EINVAL;
- strncpy(rank->dimm->label, data, copy_count);
+ memcpy(rank->dimm->label, data, copy_count);
rank->dimm->label[copy_count] = '\0';
return count;
@@ -535,7 +535,7 @@ static ssize_t dimmdev_label_store(struct device *dev,
if (copy_count == 0 || copy_count >= sizeof(dimm->label))
return -EINVAL;
- strncpy(dimm->label, data, copy_count);
+ memcpy(dimm->label, data, copy_count);
dimm->label[copy_count] = '\0';
return count;
diff --git a/drivers/edac/versal_edac.c b/drivers/edac/versal_edac.c
new file mode 100644
index 000000000000..8625de20fc71
--- /dev/null
+++ b/drivers/edac/versal_edac.c
@@ -0,0 +1,1069 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Versal memory controller driver
+ * Copyright (C) 2023 Advanced Micro Devices, Inc.
+ */
+#include <linux/bitfield.h>
+#include <linux/edac.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/sizes.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+#include <linux/firmware/xlnx-event-manager.h>
+
+#include "edac_module.h"
+
+/* Granularity of reported error in bytes */
+#define XDDR_EDAC_ERR_GRAIN 1
+
+#define XDDR_EDAC_MSG_SIZE 256
+#define EVENT 2
+
+#define XDDR_PCSR_OFFSET 0xC
+#define XDDR_ISR_OFFSET 0x14
+#define XDDR_IRQ_EN_OFFSET 0x20
+#define XDDR_IRQ1_EN_OFFSET 0x2C
+#define XDDR_IRQ_DIS_OFFSET 0x24
+#define XDDR_IRQ_CE_MASK GENMASK(18, 15)
+#define XDDR_IRQ_UE_MASK GENMASK(14, 11)
+
+#define XDDR_REG_CONFIG0_OFFSET 0x258
+#define XDDR_REG_CONFIG0_BUS_WIDTH_MASK GENMASK(19, 18)
+#define XDDR_REG_CONFIG0_NUM_CHANS_MASK BIT(17)
+#define XDDR_REG_CONFIG0_NUM_RANKS_MASK GENMASK(15, 14)
+#define XDDR_REG_CONFIG0_SIZE_MASK GENMASK(10, 8)
+
+#define XDDR_REG_PINOUT_OFFSET 0x25C
+#define XDDR_REG_PINOUT_ECC_EN_MASK GENMASK(7, 5)
+
+#define ECCW0_FLIP_CTRL 0x109C
+#define ECCW0_FLIP0_OFFSET 0x10A0
+#define ECCW1_FLIP_CTRL 0x10AC
+#define ECCW1_FLIP0_OFFSET 0x10B0
+#define ECCR0_CERR_STAT_OFFSET 0x10BC
+#define ECCR0_CE_ADDR_LO_OFFSET 0x10C0
+#define ECCR0_CE_ADDR_HI_OFFSET 0x10C4
+#define ECCR0_CE_DATA_LO_OFFSET 0x10C8
+#define ECCR0_CE_DATA_HI_OFFSET 0x10CC
+#define ECCR0_CE_DATA_PAR_OFFSET 0x10D0
+
+#define ECCR0_UERR_STAT_OFFSET 0x10D4
+#define ECCR0_UE_ADDR_LO_OFFSET 0x10D8
+#define ECCR0_UE_ADDR_HI_OFFSET 0x10DC
+#define ECCR0_UE_DATA_LO_OFFSET 0x10E0
+#define ECCR0_UE_DATA_HI_OFFSET 0x10E4
+#define ECCR0_UE_DATA_PAR_OFFSET 0x10E8
+
+#define ECCR1_CERR_STAT_OFFSET 0x10F4
+#define ECCR1_CE_ADDR_LO_OFFSET 0x10F8
+#define ECCR1_CE_ADDR_HI_OFFSET 0x10FC
+#define ECCR1_CE_DATA_LO_OFFSET 0x1100
+#define ECCR1_CE_DATA_HI_OFFSET 0x110C
+#define ECCR1_CE_DATA_PAR_OFFSET 0x1108
+
+#define ECCR1_UERR_STAT_OFFSET 0x110C
+#define ECCR1_UE_ADDR_LO_OFFSET 0x1110
+#define ECCR1_UE_ADDR_HI_OFFSET 0x1114
+#define ECCR1_UE_DATA_LO_OFFSET 0x1118
+#define ECCR1_UE_DATA_HI_OFFSET 0x111C
+#define ECCR1_UE_DATA_PAR_OFFSET 0x1120
+
+#define XDDR_NOC_REG_ADEC4_OFFSET 0x44
+#define RANK_1_MASK GENMASK(11, 6)
+#define LRANK_0_MASK GENMASK(17, 12)
+#define LRANK_1_MASK GENMASK(23, 18)
+#define MASK_24 GENMASK(29, 24)
+
+#define XDDR_NOC_REG_ADEC5_OFFSET 0x48
+#define XDDR_NOC_REG_ADEC6_OFFSET 0x4C
+#define XDDR_NOC_REG_ADEC7_OFFSET 0x50
+#define XDDR_NOC_REG_ADEC8_OFFSET 0x54
+#define XDDR_NOC_REG_ADEC9_OFFSET 0x58
+#define XDDR_NOC_REG_ADEC10_OFFSET 0x5C
+
+#define XDDR_NOC_REG_ADEC11_OFFSET 0x60
+#define MASK_0 GENMASK(5, 0)
+#define GRP_0_MASK GENMASK(11, 6)
+#define GRP_1_MASK GENMASK(17, 12)
+#define CH_0_MASK GENMASK(23, 18)
+
+#define XDDR_NOC_REG_ADEC12_OFFSET 0x71C
+#define XDDR_NOC_REG_ADEC13_OFFSET 0x720
+
+#define XDDR_NOC_REG_ADEC14_OFFSET 0x724
+#define XDDR_NOC_ROW_MATCH_MASK GENMASK(17, 0)
+#define XDDR_NOC_COL_MATCH_MASK GENMASK(27, 18)
+#define XDDR_NOC_BANK_MATCH_MASK GENMASK(29, 28)
+#define XDDR_NOC_GRP_MATCH_MASK GENMASK(31, 30)
+
+#define XDDR_NOC_REG_ADEC15_OFFSET 0x728
+#define XDDR_NOC_RANK_MATCH_MASK GENMASK(1, 0)
+#define XDDR_NOC_LRANK_MATCH_MASK GENMASK(4, 2)
+#define XDDR_NOC_CH_MATCH_MASK BIT(5)
+#define XDDR_NOC_MOD_SEL_MASK BIT(6)
+#define XDDR_NOC_MATCH_EN_MASK BIT(8)
+
+#define ECCR_UE_CE_ADDR_HI_ROW_MASK GENMASK(7, 0)
+
+#define XDDR_EDAC_NR_CSROWS 1
+#define XDDR_EDAC_NR_CHANS 1
+
+#define XDDR_BUS_WIDTH_64 0
+#define XDDR_BUS_WIDTH_32 1
+#define XDDR_BUS_WIDTH_16 2
+
+#define ECC_CEPOISON_MASK 0x1
+#define ECC_UEPOISON_MASK 0x3
+
+#define XDDR_MAX_ROW_CNT 18
+#define XDDR_MAX_COL_CNT 10
+#define XDDR_MAX_RANK_CNT 2
+#define XDDR_MAX_LRANK_CNT 3
+#define XDDR_MAX_BANK_CNT 2
+#define XDDR_MAX_GRP_CNT 2
+
+/*
+ * Config and system registers are usually locked. This is the
+ * code which unlocks them in order to accept writes. See
+ *
+ * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/PCSR_LOCK-XRAM_SLCR-Register
+ */
+#define PCSR_UNLOCK_VAL 0xF9E8D7C6
+#define XDDR_ERR_TYPE_CE 0
+#define XDDR_ERR_TYPE_UE 1
+
+#define XILINX_DRAM_SIZE_4G 0
+#define XILINX_DRAM_SIZE_6G 1
+#define XILINX_DRAM_SIZE_8G 2
+#define XILINX_DRAM_SIZE_12G 3
+#define XILINX_DRAM_SIZE_16G 4
+#define XILINX_DRAM_SIZE_32G 5
+
+/**
+ * struct ecc_error_info - ECC error log information.
+ * @burstpos: Burst position.
+ * @lrank: Logical Rank number.
+ * @rank: Rank number.
+ * @group: Group number.
+ * @bank: Bank number.
+ * @col: Column number.
+ * @row: Row number.
+ * @rowhi: Row number higher bits.
+ * @i: ECC error info.
+ */
+union ecc_error_info {
+ struct {
+ u32 burstpos:3;
+ u32 lrank:3;
+ u32 rank:2;
+ u32 group:2;
+ u32 bank:2;
+ u32 col:10;
+ u32 row:10;
+ u32 rowhi;
+ };
+ u64 i;
+} __packed;
+
+union edac_info {
+ struct {
+ u32 row0:6;
+ u32 row1:6;
+ u32 row2:6;
+ u32 row3:6;
+ u32 row4:6;
+ u32 reserved:2;
+ };
+ struct {
+ u32 col1:6;
+ u32 col2:6;
+ u32 col3:6;
+ u32 col4:6;
+ u32 col5:6;
+ u32 reservedcol:2;
+ };
+ u32 i;
+} __packed;
+
+/**
+ * struct ecc_status - ECC status information to report.
+ * @ceinfo: Correctable error log information.
+ * @ueinfo: Uncorrectable error log information.
+ * @channel: Channel number.
+ * @error_type: Error type information.
+ */
+struct ecc_status {
+ union ecc_error_info ceinfo[2];
+ union ecc_error_info ueinfo[2];
+ u8 channel;
+ u8 error_type;
+};
+
+/**
+ * struct edac_priv - DDR memory controller private instance data.
+ * @ddrmc_baseaddr: Base address of the DDR controller.
+ * @ddrmc_noc_baseaddr: Base address of the DDRMC NOC.
+ * @message: Buffer for framing the event specific info.
+ * @mc_id: Memory controller ID.
+ * @ce_cnt: Correctable error count.
+ * @ue_cnt: UnCorrectable error count.
+ * @stat: ECC status information.
+ * @lrank_bit: Bit shifts for lrank bit.
+ * @rank_bit: Bit shifts for rank bit.
+ * @row_bit: Bit shifts for row bit.
+ * @col_bit: Bit shifts for column bit.
+ * @bank_bit: Bit shifts for bank bit.
+ * @grp_bit: Bit shifts for group bit.
+ * @ch_bit: Bit shifts for channel bit.
+ * @err_inject_addr: Data poison address.
+ * @debugfs: Debugfs handle.
+ */
+struct edac_priv {
+ void __iomem *ddrmc_baseaddr;
+ void __iomem *ddrmc_noc_baseaddr;
+ char message[XDDR_EDAC_MSG_SIZE];
+ u32 mc_id;
+ u32 ce_cnt;
+ u32 ue_cnt;
+ struct ecc_status stat;
+ u32 lrank_bit[3];
+ u32 rank_bit[2];
+ u32 row_bit[18];
+ u32 col_bit[10];
+ u32 bank_bit[2];
+ u32 grp_bit[2];
+ u32 ch_bit;
+#ifdef CONFIG_EDAC_DEBUG
+ u64 err_inject_addr;
+ struct dentry *debugfs;
+#endif
+};
+
+static void get_ce_error_info(struct edac_priv *priv)
+{
+ void __iomem *ddrmc_base;
+ struct ecc_status *p;
+ u32 regval;
+ u64 reghi;
+
+ ddrmc_base = priv->ddrmc_baseaddr;
+ p = &priv->stat;
+
+ p->error_type = XDDR_ERR_TYPE_CE;
+ regval = readl(ddrmc_base + ECCR0_CE_ADDR_LO_OFFSET);
+ reghi = regval & ECCR_UE_CE_ADDR_HI_ROW_MASK;
+ p->ceinfo[0].i = regval | reghi << 32;
+ regval = readl(ddrmc_base + ECCR0_CE_ADDR_HI_OFFSET);
+
+ edac_dbg(2, "ERR DATA: 0x%08X%08X ERR DATA PARITY: 0x%08X\n",
+ readl(ddrmc_base + ECCR0_CE_DATA_LO_OFFSET),
+ readl(ddrmc_base + ECCR0_CE_DATA_HI_OFFSET),
+ readl(ddrmc_base + ECCR0_CE_DATA_PAR_OFFSET));
+
+ regval = readl(ddrmc_base + ECCR1_CE_ADDR_LO_OFFSET);
+ reghi = readl(ddrmc_base + ECCR1_CE_ADDR_HI_OFFSET);
+ p->ceinfo[1].i = regval | reghi << 32;
+ regval = readl(ddrmc_base + ECCR1_CE_ADDR_HI_OFFSET);
+
+ edac_dbg(2, "ERR DATA: 0x%08X%08X ERR DATA PARITY: 0x%08X\n",
+ readl(ddrmc_base + ECCR1_CE_DATA_LO_OFFSET),
+ readl(ddrmc_base + ECCR1_CE_DATA_HI_OFFSET),
+ readl(ddrmc_base + ECCR1_CE_DATA_PAR_OFFSET));
+}
+
+static void get_ue_error_info(struct edac_priv *priv)
+{
+ void __iomem *ddrmc_base;
+ struct ecc_status *p;
+ u32 regval;
+ u64 reghi;
+
+ ddrmc_base = priv->ddrmc_baseaddr;
+ p = &priv->stat;
+
+ p->error_type = XDDR_ERR_TYPE_UE;
+ regval = readl(ddrmc_base + ECCR0_UE_ADDR_LO_OFFSET);
+ reghi = readl(ddrmc_base + ECCR0_UE_ADDR_HI_OFFSET);
+
+ p->ueinfo[0].i = regval | reghi << 32;
+ regval = readl(ddrmc_base + ECCR0_UE_ADDR_HI_OFFSET);
+
+ edac_dbg(2, "ERR DATA: 0x%08X%08X ERR DATA PARITY: 0x%08X\n",
+ readl(ddrmc_base + ECCR0_UE_DATA_LO_OFFSET),
+ readl(ddrmc_base + ECCR0_UE_DATA_HI_OFFSET),
+ readl(ddrmc_base + ECCR0_UE_DATA_PAR_OFFSET));
+
+ regval = readl(ddrmc_base + ECCR1_UE_ADDR_LO_OFFSET);
+ reghi = readl(ddrmc_base + ECCR1_UE_ADDR_HI_OFFSET);
+ p->ueinfo[1].i = regval | reghi << 32;
+
+ edac_dbg(2, "ERR DATA: 0x%08X%08X ERR DATA PARITY: 0x%08X\n",
+ readl(ddrmc_base + ECCR1_UE_DATA_LO_OFFSET),
+ readl(ddrmc_base + ECCR1_UE_DATA_HI_OFFSET),
+ readl(ddrmc_base + ECCR1_UE_DATA_PAR_OFFSET));
+}
+
+static bool get_error_info(struct edac_priv *priv)
+{
+ u32 eccr0_ceval, eccr1_ceval, eccr0_ueval, eccr1_ueval;
+ void __iomem *ddrmc_base;
+ struct ecc_status *p;
+
+ ddrmc_base = priv->ddrmc_baseaddr;
+ p = &priv->stat;
+
+ eccr0_ceval = readl(ddrmc_base + ECCR0_CERR_STAT_OFFSET);
+ eccr1_ceval = readl(ddrmc_base + ECCR1_CERR_STAT_OFFSET);
+ eccr0_ueval = readl(ddrmc_base + ECCR0_UERR_STAT_OFFSET);
+ eccr1_ueval = readl(ddrmc_base + ECCR1_UERR_STAT_OFFSET);
+
+ if (!eccr0_ceval && !eccr1_ceval && !eccr0_ueval && !eccr1_ueval)
+ return 1;
+ if (!eccr0_ceval)
+ p->channel = 1;
+ else
+ p->channel = 0;
+
+ if (eccr0_ceval || eccr1_ceval)
+ get_ce_error_info(priv);
+
+ if (eccr0_ueval || eccr1_ueval) {
+ if (!eccr0_ueval)
+ p->channel = 1;
+ else
+ p->channel = 0;
+ get_ue_error_info(priv);
+ }
+
+ /* Unlock the PCSR registers */
+ writel(PCSR_UNLOCK_VAL, ddrmc_base + XDDR_PCSR_OFFSET);
+
+ writel(0, ddrmc_base + ECCR0_CERR_STAT_OFFSET);
+ writel(0, ddrmc_base + ECCR1_CERR_STAT_OFFSET);
+ writel(0, ddrmc_base + ECCR0_UERR_STAT_OFFSET);
+ writel(0, ddrmc_base + ECCR1_UERR_STAT_OFFSET);
+
+ /* Lock the PCSR registers */
+ writel(1, ddrmc_base + XDDR_PCSR_OFFSET);
+
+ return 0;
+}
+
+/**
+ * convert_to_physical - Convert to physical address.
+ * @priv: DDR memory controller private instance data.
+ * @pinf: ECC error info structure.
+ *
+ * Return: Physical address of the DDR memory.
+ */
+static unsigned long convert_to_physical(struct edac_priv *priv, union ecc_error_info pinf)
+{
+ unsigned long err_addr = 0;
+ u32 index;
+ u32 row;
+
+ row = pinf.rowhi << 10 | pinf.row;
+ for (index = 0; index < XDDR_MAX_ROW_CNT; index++) {
+ err_addr |= (row & BIT(0)) << priv->row_bit[index];
+ row >>= 1;
+ }
+
+ for (index = 0; index < XDDR_MAX_COL_CNT; index++) {
+ err_addr |= (pinf.col & BIT(0)) << priv->col_bit[index];
+ pinf.col >>= 1;
+ }
+
+ for (index = 0; index < XDDR_MAX_BANK_CNT; index++) {
+ err_addr |= (pinf.bank & BIT(0)) << priv->bank_bit[index];
+ pinf.bank >>= 1;
+ }
+
+ for (index = 0; index < XDDR_MAX_GRP_CNT; index++) {
+ err_addr |= (pinf.group & BIT(0)) << priv->grp_bit[index];
+ pinf.group >>= 1;
+ }
+
+ for (index = 0; index < XDDR_MAX_RANK_CNT; index++) {
+ err_addr |= (pinf.rank & BIT(0)) << priv->rank_bit[index];
+ pinf.rank >>= 1;
+ }
+
+ for (index = 0; index < XDDR_MAX_LRANK_CNT; index++) {
+ err_addr |= (pinf.lrank & BIT(0)) << priv->lrank_bit[index];
+ pinf.lrank >>= 1;
+ }
+
+ err_addr |= (priv->stat.channel & BIT(0)) << priv->ch_bit;
+
+ return err_addr;
+}
+
+/**
+ * handle_error - Handle Correctable and Uncorrectable errors.
+ * @mci: EDAC memory controller instance.
+ * @stat: ECC status structure.
+ *
+ * Handles ECC correctable and uncorrectable errors.
+ */
+static void handle_error(struct mem_ctl_info *mci, struct ecc_status *stat)
+{
+ struct edac_priv *priv = mci->pvt_info;
+ union ecc_error_info pinf;
+
+ if (stat->error_type == XDDR_ERR_TYPE_CE) {
+ priv->ce_cnt++;
+ pinf = stat->ceinfo[stat->channel];
+ snprintf(priv->message, XDDR_EDAC_MSG_SIZE,
+ "Error type:%s MC ID: %d Addr at %lx Burst Pos: %d\n",
+ "CE", priv->mc_id,
+ 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,
+ priv->message, "");
+ }
+
+ if (stat->error_type == XDDR_ERR_TYPE_UE) {
+ priv->ue_cnt++;
+ pinf = stat->ueinfo[stat->channel];
+ snprintf(priv->message, XDDR_EDAC_MSG_SIZE,
+ "Error type:%s MC ID: %d Addr at %lx Burst Pos: %d\n",
+ "UE", priv->mc_id,
+ 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,
+ priv->message, "");
+ }
+
+ memset(stat, 0, sizeof(*stat));
+}
+
+/**
+ * err_callback - Handle Correctable and Uncorrectable errors.
+ * @payload: payload data.
+ * @data: mci controller data.
+ *
+ * Handles ECC correctable and uncorrectable errors.
+ */
+static void err_callback(const u32 *payload, void *data)
+{
+ struct mem_ctl_info *mci = (struct mem_ctl_info *)data;
+ struct edac_priv *priv;
+ struct ecc_status *p;
+ int regval;
+
+ priv = mci->pvt_info;
+ p = &priv->stat;
+
+ regval = readl(priv->ddrmc_baseaddr + XDDR_ISR_OFFSET);
+
+ if (payload[EVENT] == XPM_EVENT_ERROR_MASK_DDRMC_CR)
+ p->error_type = XDDR_ERR_TYPE_CE;
+ if (payload[EVENT] == XPM_EVENT_ERROR_MASK_DDRMC_NCR)
+ p->error_type = XDDR_ERR_TYPE_UE;
+
+ if (get_error_info(priv))
+ return;
+
+ handle_error(mci, &priv->stat);
+
+ /* Unlock the PCSR registers */
+ writel(PCSR_UNLOCK_VAL, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+
+ /* Clear the ISR */
+ writel(regval, priv->ddrmc_baseaddr + XDDR_ISR_OFFSET);
+
+ /* Lock the PCSR registers */
+ writel(1, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+ edac_dbg(3, "Total error count CE %d UE %d\n",
+ priv->ce_cnt, priv->ue_cnt);
+}
+
+/**
+ * get_dwidth - Return the controller memory width.
+ * @base: DDR memory controller base address.
+ *
+ * Get the EDAC device type width appropriate for the controller
+ * configuration.
+ *
+ * Return: a device type width enumeration.
+ */
+static enum dev_type get_dwidth(const void __iomem *base)
+{
+ enum dev_type dt;
+ u32 regval;
+ u32 width;
+
+ regval = readl(base + XDDR_REG_CONFIG0_OFFSET);
+ width = FIELD_GET(XDDR_REG_CONFIG0_BUS_WIDTH_MASK, regval);
+
+ switch (width) {
+ case XDDR_BUS_WIDTH_16:
+ dt = DEV_X2;
+ break;
+ case XDDR_BUS_WIDTH_32:
+ dt = DEV_X4;
+ break;
+ case XDDR_BUS_WIDTH_64:
+ dt = DEV_X8;
+ break;
+ default:
+ dt = DEV_UNKNOWN;
+ }
+
+ return dt;
+}
+
+/**
+ * get_ecc_state - Return the controller ECC enable/disable status.
+ * @base: DDR memory controller base address.
+ *
+ * Get the ECC enable/disable status for the controller.
+ *
+ * Return: a ECC status boolean i.e true/false - enabled/disabled.
+ */
+static bool get_ecc_state(void __iomem *base)
+{
+ enum dev_type dt;
+ u32 ecctype;
+
+ dt = get_dwidth(base);
+ if (dt == DEV_UNKNOWN)
+ return false;
+
+ ecctype = readl(base + XDDR_REG_PINOUT_OFFSET);
+ ecctype &= XDDR_REG_PINOUT_ECC_EN_MASK;
+
+ return !!ecctype;
+}
+
+/**
+ * get_memsize - Get the size of the attached memory device.
+ * @priv: DDR memory controller private instance data.
+ *
+ * Return: the memory size in bytes.
+ */
+static u64 get_memsize(struct edac_priv *priv)
+{
+ u32 regval;
+ u64 size;
+
+ regval = readl(priv->ddrmc_baseaddr + XDDR_REG_CONFIG0_OFFSET);
+ regval = FIELD_GET(XDDR_REG_CONFIG0_SIZE_MASK, regval);
+
+ switch (regval) {
+ case XILINX_DRAM_SIZE_4G:
+ size = 4U; break;
+ case XILINX_DRAM_SIZE_6G:
+ size = 6U; break;
+ case XILINX_DRAM_SIZE_8G:
+ size = 8U; break;
+ case XILINX_DRAM_SIZE_12G:
+ size = 12U; break;
+ case XILINX_DRAM_SIZE_16G:
+ size = 16U; break;
+ case XILINX_DRAM_SIZE_32G:
+ size = 32U; break;
+ /* Invalid configuration */
+ default:
+ size = 0; break;
+ }
+
+ size *= SZ_1G;
+ return size;
+}
+
+/**
+ * init_csrows - Initialize the csrow data.
+ * @mci: EDAC memory controller instance.
+ *
+ * Initialize the chip select rows associated with the EDAC memory
+ * controller instance.
+ */
+static void init_csrows(struct mem_ctl_info *mci)
+{
+ struct edac_priv *priv = mci->pvt_info;
+ struct csrow_info *csi;
+ struct dimm_info *dimm;
+ unsigned long size;
+ u32 row;
+ int ch;
+
+ size = get_memsize(priv);
+ for (row = 0; row < mci->nr_csrows; row++) {
+ csi = mci->csrows[row];
+ for (ch = 0; ch < csi->nr_channels; ch++) {
+ dimm = csi->channels[ch]->dimm;
+ dimm->edac_mode = EDAC_SECDED;
+ dimm->mtype = MEM_DDR4;
+ dimm->nr_pages = (size >> PAGE_SHIFT) / csi->nr_channels;
+ dimm->grain = XDDR_EDAC_ERR_GRAIN;
+ dimm->dtype = get_dwidth(priv->ddrmc_baseaddr);
+ }
+ }
+}
+
+/**
+ * mc_init - Initialize one driver instance.
+ * @mci: EDAC memory controller instance.
+ * @pdev: platform device.
+ *
+ * Perform initialization of the EDAC memory controller instance and
+ * related driver-private data associated with the memory controller the
+ * instance is bound to.
+ */
+static void mc_init(struct mem_ctl_info *mci, struct platform_device *pdev)
+{
+ mci->pdev = &pdev->dev;
+ platform_set_drvdata(pdev, mci);
+
+ /* Initialize controller capabilities and configuration */
+ mci->mtype_cap = MEM_FLAG_DDR4;
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+ mci->scrub_cap = SCRUB_HW_SRC;
+ mci->scrub_mode = SCRUB_NONE;
+
+ mci->edac_cap = EDAC_FLAG_SECDED;
+ mci->ctl_name = "xlnx_ddr_controller";
+ mci->dev_name = dev_name(&pdev->dev);
+ mci->mod_name = "xlnx_edac";
+
+ edac_op_state = EDAC_OPSTATE_INT;
+
+ init_csrows(mci);
+}
+
+static void enable_intr(struct edac_priv *priv)
+{
+ /* Unlock the PCSR registers */
+ writel(PCSR_UNLOCK_VAL, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+
+ /* Enable UE and CE Interrupts to support the interrupt case */
+ writel(XDDR_IRQ_CE_MASK | XDDR_IRQ_UE_MASK,
+ priv->ddrmc_baseaddr + XDDR_IRQ_EN_OFFSET);
+
+ writel(XDDR_IRQ_UE_MASK,
+ priv->ddrmc_baseaddr + XDDR_IRQ1_EN_OFFSET);
+ /* Lock the PCSR registers */
+ writel(1, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+}
+
+static void disable_intr(struct edac_priv *priv)
+{
+ /* Unlock the PCSR registers */
+ writel(PCSR_UNLOCK_VAL, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+
+ /* Disable UE/CE Interrupts */
+ writel(XDDR_IRQ_CE_MASK | XDDR_IRQ_UE_MASK,
+ priv->ddrmc_baseaddr + XDDR_IRQ_DIS_OFFSET);
+
+ /* Lock the PCSR registers */
+ writel(1, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+}
+
+#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
+
+#ifdef CONFIG_EDAC_DEBUG
+/**
+ * poison_setup - Update poison registers.
+ * @priv: DDR memory controller private instance data.
+ *
+ * Update poison registers as per DDR mapping upon write of the address
+ * location the fault is injected.
+ * Return: none.
+ */
+static void poison_setup(struct edac_priv *priv)
+{
+ u32 col = 0, row = 0, bank = 0, grp = 0, rank = 0, lrank = 0, ch = 0;
+ u32 index, regval;
+
+ for (index = 0; index < XDDR_MAX_ROW_CNT; index++) {
+ row |= (((priv->err_inject_addr >> priv->row_bit[index]) &
+ BIT(0)) << index);
+ }
+
+ for (index = 0; index < XDDR_MAX_COL_CNT; index++) {
+ col |= (((priv->err_inject_addr >> priv->col_bit[index]) &
+ BIT(0)) << index);
+ }
+
+ for (index = 0; index < XDDR_MAX_BANK_CNT; index++) {
+ bank |= (((priv->err_inject_addr >> priv->bank_bit[index]) &
+ BIT(0)) << index);
+ }
+
+ for (index = 0; index < XDDR_MAX_GRP_CNT; index++) {
+ grp |= (((priv->err_inject_addr >> priv->grp_bit[index]) &
+ BIT(0)) << index);
+ }
+
+ for (index = 0; index < XDDR_MAX_RANK_CNT; index++) {
+ rank |= (((priv->err_inject_addr >> priv->rank_bit[index]) &
+ BIT(0)) << index);
+ }
+
+ for (index = 0; index < XDDR_MAX_LRANK_CNT; index++) {
+ lrank |= (((priv->err_inject_addr >> priv->lrank_bit[index]) &
+ BIT(0)) << index);
+ }
+
+ ch = (priv->err_inject_addr >> priv->ch_bit) & BIT(0);
+ if (ch)
+ writel(0xFF, priv->ddrmc_baseaddr + ECCW1_FLIP_CTRL);
+ else
+ writel(0xFF, priv->ddrmc_baseaddr + ECCW0_FLIP_CTRL);
+
+ writel(0, priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC12_OFFSET);
+ writel(0, priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC13_OFFSET);
+
+ regval = row & XDDR_NOC_ROW_MATCH_MASK;
+ regval |= FIELD_PREP(XDDR_NOC_COL_MATCH_MASK, col);
+ regval |= FIELD_PREP(XDDR_NOC_BANK_MATCH_MASK, bank);
+ regval |= FIELD_PREP(XDDR_NOC_GRP_MATCH_MASK, grp);
+ writel(regval, priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC14_OFFSET);
+
+ regval = rank & XDDR_NOC_RANK_MATCH_MASK;
+ regval |= FIELD_PREP(XDDR_NOC_LRANK_MATCH_MASK, lrank);
+ regval |= FIELD_PREP(XDDR_NOC_CH_MATCH_MASK, ch);
+ regval |= (XDDR_NOC_MOD_SEL_MASK | XDDR_NOC_MATCH_EN_MASK);
+ writel(regval, priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC15_OFFSET);
+}
+
+static ssize_t xddr_inject_data_poison_store(struct mem_ctl_info *mci,
+ const char __user *data)
+{
+ struct edac_priv *priv = mci->pvt_info;
+
+ writel(0, priv->ddrmc_baseaddr + ECCW0_FLIP0_OFFSET);
+ writel(0, priv->ddrmc_baseaddr + ECCW1_FLIP0_OFFSET);
+
+ if (strncmp(data, "CE", 2) == 0) {
+ writel(ECC_CEPOISON_MASK, priv->ddrmc_baseaddr +
+ ECCW0_FLIP0_OFFSET);
+ writel(ECC_CEPOISON_MASK, priv->ddrmc_baseaddr +
+ ECCW1_FLIP0_OFFSET);
+ } else {
+ writel(ECC_UEPOISON_MASK, priv->ddrmc_baseaddr +
+ ECCW0_FLIP0_OFFSET);
+ writel(ECC_UEPOISON_MASK, priv->ddrmc_baseaddr +
+ ECCW1_FLIP0_OFFSET);
+ }
+
+ /* Lock the PCSR registers */
+ writel(1, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+
+ return 0;
+}
+
+static ssize_t inject_data_poison_store(struct file *file, const char __user *data,
+ size_t count, loff_t *ppos)
+{
+ struct device *dev = file->private_data;
+ struct mem_ctl_info *mci = to_mci(dev);
+ struct edac_priv *priv = mci->pvt_info;
+
+ /* Unlock the PCSR registers */
+ writel(PCSR_UNLOCK_VAL, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+ writel(PCSR_UNLOCK_VAL, priv->ddrmc_noc_baseaddr + XDDR_PCSR_OFFSET);
+
+ poison_setup(priv);
+
+ /* Lock the PCSR registers */
+ writel(1, priv->ddrmc_noc_baseaddr + XDDR_PCSR_OFFSET);
+
+ xddr_inject_data_poison_store(mci, data);
+
+ return count;
+}
+
+static const struct file_operations xddr_inject_enable_fops = {
+ .open = simple_open,
+ .write = inject_data_poison_store,
+ .llseek = generic_file_llseek,
+};
+
+static void create_debugfs_attributes(struct mem_ctl_info *mci)
+{
+ struct edac_priv *priv = mci->pvt_info;
+
+ priv->debugfs = edac_debugfs_create_dir(mci->dev_name);
+ if (!priv->debugfs)
+ return;
+
+ edac_debugfs_create_file("inject_error", 0200, priv->debugfs,
+ &mci->dev, &xddr_inject_enable_fops);
+ debugfs_create_x64("address", 0600, priv->debugfs,
+ &priv->err_inject_addr);
+ mci->debugfs = priv->debugfs;
+}
+
+static inline void process_bit(struct edac_priv *priv, unsigned int start, u32 regval)
+{
+ union edac_info rows;
+
+ rows.i = regval;
+ priv->row_bit[start] = rows.row0;
+ priv->row_bit[start + 1] = rows.row1;
+ priv->row_bit[start + 2] = rows.row2;
+ priv->row_bit[start + 3] = rows.row3;
+ priv->row_bit[start + 4] = rows.row4;
+}
+
+static void setup_row_address_map(struct edac_priv *priv)
+{
+ u32 regval;
+ union edac_info rows;
+
+ regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC5_OFFSET);
+ process_bit(priv, 0, regval);
+
+ regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC6_OFFSET);
+ process_bit(priv, 5, regval);
+
+ regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC7_OFFSET);
+ process_bit(priv, 10, regval);
+
+ regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC8_OFFSET);
+ rows.i = regval;
+
+ priv->row_bit[15] = rows.row0;
+ priv->row_bit[16] = rows.row1;
+ priv->row_bit[17] = rows.row2;
+}
+
+static void setup_column_address_map(struct edac_priv *priv)
+{
+ u32 regval;
+ union edac_info cols;
+
+ regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC8_OFFSET);
+ priv->col_bit[0] = FIELD_GET(MASK_24, regval);
+
+ regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC9_OFFSET);
+ cols.i = regval;
+ priv->col_bit[1] = cols.col1;
+ priv->col_bit[2] = cols.col2;
+ priv->col_bit[3] = cols.col3;
+ priv->col_bit[4] = cols.col4;
+ priv->col_bit[5] = cols.col5;
+
+ regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC10_OFFSET);
+ cols.i = regval;
+ priv->col_bit[6] = cols.col1;
+ priv->col_bit[7] = cols.col2;
+ priv->col_bit[8] = cols.col3;
+ priv->col_bit[9] = cols.col4;
+}
+
+static void setup_bank_grp_ch_address_map(struct edac_priv *priv)
+{
+ u32 regval;
+
+ regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC10_OFFSET);
+ priv->bank_bit[0] = FIELD_GET(MASK_24, regval);
+
+ regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC11_OFFSET);
+ priv->bank_bit[1] = (regval & MASK_0);
+ priv->grp_bit[0] = FIELD_GET(GRP_0_MASK, regval);
+ priv->grp_bit[1] = FIELD_GET(GRP_1_MASK, regval);
+ priv->ch_bit = FIELD_GET(CH_0_MASK, regval);
+}
+
+static void setup_rank_lrank_address_map(struct edac_priv *priv)
+{
+ u32 regval;
+
+ regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC4_OFFSET);
+ priv->rank_bit[0] = (regval & MASK_0);
+ priv->rank_bit[1] = FIELD_GET(RANK_1_MASK, regval);
+ priv->lrank_bit[0] = FIELD_GET(LRANK_0_MASK, regval);
+ priv->lrank_bit[1] = FIELD_GET(LRANK_1_MASK, regval);
+ priv->lrank_bit[2] = FIELD_GET(MASK_24, regval);
+}
+
+/**
+ * setup_address_map - Set Address Map by querying ADDRMAP registers.
+ * @priv: DDR memory controller private instance data.
+ *
+ * Set Address Map by querying ADDRMAP registers.
+ *
+ * Return: none.
+ */
+static void setup_address_map(struct edac_priv *priv)
+{
+ setup_row_address_map(priv);
+
+ setup_column_address_map(priv);
+
+ setup_bank_grp_ch_address_map(priv);
+
+ setup_rank_lrank_address_map(priv);
+}
+#endif /* CONFIG_EDAC_DEBUG */
+
+static const struct of_device_id xlnx_edac_match[] = {
+ { .compatible = "xlnx,versal-ddrmc", },
+ {
+ /* end of table */
+ }
+};
+
+MODULE_DEVICE_TABLE(of, xlnx_edac_match);
+static u32 emif_get_id(struct device_node *node)
+{
+ u32 addr, my_addr, my_id = 0;
+ struct device_node *np;
+ const __be32 *addrp;
+
+ addrp = of_get_address(node, 0, NULL, NULL);
+ my_addr = (u32)of_translate_address(node, addrp);
+
+ for_each_matching_node(np, xlnx_edac_match) {
+ if (np == node)
+ continue;
+
+ addrp = of_get_address(np, 0, NULL, NULL);
+ addr = (u32)of_translate_address(np, addrp);
+
+ edac_printk(KERN_INFO, EDAC_MC,
+ "addr=%x, my_addr=%x\n",
+ addr, my_addr);
+
+ if (addr < my_addr)
+ my_id++;
+ }
+
+ return my_id;
+}
+
+static int mc_probe(struct platform_device *pdev)
+{
+ void __iomem *ddrmc_baseaddr, *ddrmc_noc_baseaddr;
+ struct edac_mc_layer layers[2];
+ struct mem_ctl_info *mci;
+ u8 num_chans, num_csrows;
+ struct edac_priv *priv;
+ u32 edac_mc_id, regval;
+ int rc;
+
+ ddrmc_baseaddr = devm_platform_ioremap_resource_byname(pdev, "base");
+ if (IS_ERR(ddrmc_baseaddr))
+ return PTR_ERR(ddrmc_baseaddr);
+
+ ddrmc_noc_baseaddr = devm_platform_ioremap_resource_byname(pdev, "noc");
+ if (IS_ERR(ddrmc_noc_baseaddr))
+ return PTR_ERR(ddrmc_noc_baseaddr);
+
+ if (!get_ecc_state(ddrmc_baseaddr))
+ return -ENXIO;
+
+ /* Allocate ID number for the EMIF controller */
+ edac_mc_id = emif_get_id(pdev->dev.of_node);
+
+ regval = readl(ddrmc_baseaddr + XDDR_REG_CONFIG0_OFFSET);
+ num_chans = FIELD_GET(XDDR_REG_CONFIG0_NUM_CHANS_MASK, regval);
+ num_chans++;
+
+ num_csrows = FIELD_GET(XDDR_REG_CONFIG0_NUM_RANKS_MASK, regval);
+ num_csrows *= 2;
+ if (!num_csrows)
+ num_csrows = 1;
+
+ layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
+ layers[0].size = num_csrows;
+ layers[0].is_virt_csrow = true;
+ layers[1].type = EDAC_MC_LAYER_CHANNEL;
+ layers[1].size = num_chans;
+ layers[1].is_virt_csrow = false;
+
+ mci = edac_mc_alloc(edac_mc_id, ARRAY_SIZE(layers), layers,
+ sizeof(struct edac_priv));
+ if (!mci) {
+ edac_printk(KERN_ERR, EDAC_MC,
+ "Failed memory allocation for mc instance\n");
+ return -ENOMEM;
+ }
+
+ priv = mci->pvt_info;
+ priv->ddrmc_baseaddr = ddrmc_baseaddr;
+ priv->ddrmc_noc_baseaddr = ddrmc_noc_baseaddr;
+ priv->ce_cnt = 0;
+ priv->ue_cnt = 0;
+ priv->mc_id = edac_mc_id;
+
+ mc_init(mci, pdev);
+
+ rc = edac_mc_add_mc(mci);
+ if (rc) {
+ edac_printk(KERN_ERR, EDAC_MC,
+ "Failed to register with EDAC core\n");
+ goto free_edac_mc;
+ }
+
+ rc = xlnx_register_event(PM_NOTIFY_CB, 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,
+ false, err_callback, mci);
+ if (rc) {
+ if (rc == -EACCES)
+ rc = -EPROBE_DEFER;
+
+ goto del_mc;
+ }
+
+#ifdef CONFIG_EDAC_DEBUG
+ create_debugfs_attributes(mci);
+ setup_address_map(priv);
+#endif
+ enable_intr(priv);
+ return rc;
+
+del_mc:
+ edac_mc_del_mc(&pdev->dev);
+free_edac_mc:
+ edac_mc_free(mci);
+
+ return rc;
+}
+
+static int mc_remove(struct platform_device *pdev)
+{
+ struct mem_ctl_info *mci = platform_get_drvdata(pdev);
+ struct edac_priv *priv = mci->pvt_info;
+
+ disable_intr(priv);
+
+#ifdef CONFIG_EDAC_DEBUG
+ debugfs_remove_recursive(priv->debugfs);
+#endif
+
+ xlnx_unregister_event(PM_NOTIFY_CB, 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);
+
+ return 0;
+}
+
+static struct platform_driver xilinx_ddr_edac_mc_driver = {
+ .driver = {
+ .name = "xilinx-ddrmc-edac",
+ .of_match_table = xlnx_edac_match,
+ },
+ .probe = mc_probe,
+ .remove = mc_remove,
+};
+
+module_platform_driver(xilinx_ddr_edac_mc_driver);
+
+MODULE_AUTHOR("AMD Inc");
+MODULE_DESCRIPTION("Xilinx DDRMC ECC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index 8de9023c2a38..5f869eacd19a 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -191,4 +191,15 @@ config EXTCON_USBC_TUSB320
Say Y here to enable support for USB Type C cable detection extcon
support using a TUSB320.
+config EXTCON_RTK_TYPE_C
+ tristate "Realtek RTD SoC extcon Type-C Driver"
+ depends on ARCH_REALTEK || COMPILE_TEST
+ depends on TYPEC
+ select USB_COMMON
+ help
+ Say Y here to enable extcon support for USB Type C cable detection
+ when using the Realtek RTD SoC USB Type-C port.
+ The DHC (Digital Home Hub) RTD series SoC contains a type c module.
+ This driver will detect the status of the type-c port.
+
endif
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
index 1b390d934ca9..f779adb5e4c7 100644
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o
obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o
obj-$(CONFIG_EXTCON_USBC_CROS_EC) += extcon-usbc-cros-ec.o
obj-$(CONFIG_EXTCON_USBC_TUSB320) += extcon-usbc-tusb320.o
+obj-$(CONFIG_EXTCON_RTK_TYPE_C) += extcon-rtk-type-c.o
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index 1f1d9ab0c5c7..2c567e0b7b7f 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -1258,9 +1258,16 @@ static int max77693_muic_probe(struct platform_device *pdev)
return ret;
}
+static const struct of_device_id of_max77693_muic_dt_match[] = {
+ { .compatible = "maxim,max77693-muic", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, of_max77693_muic_dt_match);
+
static struct platform_driver max77693_muic_driver = {
.driver = {
.name = DEV_NAME,
+ .of_match_table = of_max77693_muic_dt_match,
},
.probe = max77693_muic_probe,
};
diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c
index 1bc0426ce3f1..acb11a54f875 100644
--- a/drivers/extcon/extcon-max77843.c
+++ b/drivers/extcon/extcon-max77843.c
@@ -946,9 +946,16 @@ static const struct platform_device_id max77843_muic_id[] = {
};
MODULE_DEVICE_TABLE(platform, max77843_muic_id);
+static const struct of_device_id of_max77843_muic_dt_match[] = {
+ { .compatible = "maxim,max77843-muic", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, of_max77843_muic_dt_match);
+
static struct platform_driver max77843_muic_driver = {
.driver = {
.name = "max77843-muic",
+ .of_match_table = of_max77843_muic_dt_match,
},
.probe = max77843_muic_probe,
.remove = max77843_muic_remove,
diff --git a/drivers/extcon/extcon-rtk-type-c.c b/drivers/extcon/extcon-rtk-type-c.c
new file mode 100644
index 000000000000..a592bab77538
--- /dev/null
+++ b/drivers/extcon/extcon-rtk-type-c.c
@@ -0,0 +1,1794 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * * extcon-rtk-type-c.c - Realtek Extcon Type C driver
+ *
+ * Copyright (C) 2023 Realtek Semiconductor Corporation
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/syscalls.h>
+#include <linux/suspend.h>
+#include <linux/debugfs.h>
+#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
+#include <linux/sys_soc.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/gpio/consumer.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/typec.h>
+
+struct cc_param {
+ u32 rp_4p7k_code;
+ u32 rp_36k_code;
+ u32 rp_12k_code;
+ u32 rd_code;
+ u32 ra_code;
+ u32 vref_2p6v;
+ u32 vref_1p23v;
+ u32 vref_0p8v;
+ u32 vref_0p66v;
+ u32 vref_0p4v;
+ u32 vref_0p2v;
+ u32 vref_1_1p6v;
+ u32 vref_0_1p6v;
+};
+
+struct type_c_cfg {
+ int parameter_ver; /* Parameter version */
+ int cc_dfp_mode;
+ struct cc_param cc1_param;
+ struct cc_param cc2_param;
+
+ u32 debounce_val;
+ bool use_defalut_parameter;
+};
+
+struct type_c_data {
+ void __iomem *reg_base;
+ struct device *dev;
+ struct extcon_dev *edev;
+
+ u32 irq;
+
+ /* rd control GPIO only for rtd1295 */
+ struct gpio_desc *rd_ctrl_gpio_desc;
+
+ /* Parameters */
+ struct type_c_cfg *type_c_cfg;
+ u32 dfp_mode_rp_en;
+ u32 ufp_mode_rd_en;
+ u32 cc1_code;
+ u32 cc2_code;
+ u32 cc1_vref;
+ u32 cc2_vref;
+ u32 debounce; /* 1b,1us 7f,4.7us */
+
+ /* type_c state */
+ int connect_change;
+#define CONNECT_CHANGE 1
+#define CONNECT_NO_CHANGE 0
+ int cc_mode; /* cc is host or device */
+#define IN_HOST_MODE 0x10
+#define IN_DEVICE_MODE 0x20
+ int is_attach;
+#define IN_ATTACH 1
+#define TO_ATTACH 1
+#define IN_DETACH 0
+#define TO_DETACH 0
+ int at_cc1;
+#define AT_CC1 1
+#define AT_CC2 0
+
+ u32 int_status;
+ u32 cc_status;
+ /* protect the data member */
+ spinlock_t lock;
+ struct delayed_work delayed_work;
+
+ bool rd_en_at_first;
+
+ struct dentry *debug_dir;
+
+ struct typec_port *port;
+};
+
+/* Type C register offset */
+#define USB_TYPEC_CTRL_CC1_0 0x0
+#define USB_TYPEC_CTRL_CC1_1 0x4
+#define USB_TYPEC_CTRL_CC2_0 0x8
+#define USB_TYPEC_CTRL_CC2_1 0xC
+#define USB_TYPEC_STS 0x10
+#define USB_TYPEC_CTRL 0x14
+#define USB_DBUS_PWR_CTRL 0x18
+
+#define ENABLE_CC1 0x1
+#define ENABLE_CC2 0x2
+#define DISABLE_CC 0x0
+
+/* Bit mapping USB_TYPEC_CTRL_CC1_0 and USB_TYPEC_CTRL_CC2_0 */
+#define PLR_EN BIT(29)
+#define CC_SWITCH_MASK (BIT(29) | BIT(28) | BIT(27))
+#define CC_CODE_MASK (0xfffff << 7)
+#define rp4pk_code(val) ((0x1f & (val)) << 22)
+#define code_rp4pk(val) (((val) >> 22) & 0x1f)
+#define rp36k_code(val) ((0x1f & (val)) << 17)
+#define code_rp36k(val) (((val) >> 17) & 0x1f)
+#define rp12k_code(val) ((0x1f & (val)) << 12)
+#define code_rp12k(val) (((val) >> 12) & 0x1f)
+#define rd_code(val) ((0x1f & (val)) << 7)
+#define code_rd(val) (((val) >> 7) & 0x1f)
+#define dfp_mode(val) ((0x3 & (val)) << 5)
+#define EN_RP4P7K BIT(4)
+#define EN_RP36K BIT(3)
+#define EN_RP12K BIT(2)
+#define EN_RD BIT(1)
+#define EN_CC_DET BIT(0)
+
+#define CC_MODE_UFP 0x0
+#define CC_MODE_DFP_USB 0x1
+#define CC_MODE_DFP_1_5 0x2
+#define CC_MODE_DFP_3_0 0x3
+
+/*
+ * PARAMETER_V0:
+ * Realtek Kylin rtd1295
+ * Realtek Hercules rtd1395
+ * Realtek Thor rtd1619
+ * Realtek Hank rtd1319
+ * Realtek Groot rtd1312c
+ * PARAMETER_V1:
+ * Realtek Stark rtd1619b
+ * Realtek Parker rtd1319d
+ * Realtek Danvers rtd1315e
+ */
+enum parameter_version {
+ PARAMETER_V0 = 0,
+ PARAMETER_V1 = 1,
+};
+
+/* Bit mapping USB_TYPEC_CTRL_CC1_1 and USB_TYPEC_CTRL_CC2_1 */
+#define V0_vref_2p6v(val) ((0xf & (val)) << 26) /* Bit 29 for groot */
+#define V0_vref_1p23v(val) ((0xf & (val)) << 22)
+#define V0_vref_0p8v(val) ((0xf & (val)) << 18)
+#define V0_vref_0p66v(val) ((0xf & (val)) << 14)
+#define V0_vref_0p4v(val) ((0x7 & (val)) << 11)
+#define V0_vref_0p2v(val) ((0x7 & (val)) << 8)
+#define V0_vref_1_1p6v(val) ((0xf & (val)) << 4)
+#define V0_vref_0_1p6v(val) ((0xf & (val)) << 0)
+
+#define V0_decode_2p6v(val) (((val) >> 26) & 0xf) /* Bit 29 for groot */
+#define V0_decode_1p23v(val) (((val) >> 22) & 0xf)
+#define V0_decode_0p8v(val) (((val) >> 18) & 0xf)
+#define V0_decode_0p66v(val) (((val) >> 14) & 0xf)
+#define V0_decode_0p4v(val) (((val) >> 11) & 0x7)
+#define V0_decode_0p2v(val) (((val) >> 8) & 0x7)
+#define V0_decode_1_1p6v(val) (((val) >> 4) & 0xf)
+#define V0_decode_0_1p6v(val) (((val) >> 0) & 0xf)
+
+/* new Bit mapping USB_TYPEC_CTRL_CC1_1 and USB_TYPEC_CTRL_CC2_1 */
+#define V1_vref_2p6v(val) ((0xf & (val)) << 28)
+#define V1_vref_1p23v(val) ((0xf & (val)) << 24)
+#define V1_vref_0p8v(val) ((0xf & (val)) << 20)
+#define V1_vref_0p66v(val) ((0xf & (val)) << 16)
+#define V1_vref_0p4v(val) ((0xf & (val)) << 12)
+#define V1_vref_0p2v(val) ((0xf & (val)) << 8)
+#define V1_vref_1_1p6v(val) ((0xf & (val)) << 4)
+#define V1_vref_0_1p6v(val) ((0xf & (val)) << 0)
+
+#define V1_decode_2p6v(val) (((val) >> 28) & 0xf)
+#define V1_decode_1p23v(val) (((val) >> 24) & 0xf)
+#define V1_decode_0p8v(val) (((val) >> 20) & 0xf)
+#define V1_decode_0p66v(val) (((val) >> 16) & 0xf)
+#define V1_decode_0p4v(val) (((val) >> 12) & 0xf)
+#define V1_decode_0p2v(val) (((val) >> 8) & 0xf)
+#define V1_decode_1_1p6v(val) (((val) >> 4) & 0xf)
+#define V1_decode_0_1p6v(val) (((val) >> 0) & 0xf)
+
+/* Bit mapping USB_TYPEC_STS */
+#define DET_STS 0x7
+#define CC1_DET_STS (DET_STS)
+#define CC2_DET_STS (DET_STS << 3)
+#define DET_STS_RA 0x1
+#define DET_STS_RD 0x3
+#define DET_STS_RP 0x1
+#define CC1_DET_STS_RA (DET_STS_RA)
+#define CC1_DET_STS_RD (DET_STS_RD)
+#define CC1_DET_STS_RP (DET_STS_RP)
+#define CC2_DET_STS_RA (DET_STS_RA << 3)
+#define CC2_DET_STS_RD (DET_STS_RD << 3)
+#define CC2_DET_STS_RP (DET_STS_RP << 3)
+
+/* Bit mapping USB_TYPEC_CTRL */
+#define CC2_INT_EN BIT(11)
+#define CC1_INT_EN BIT(10)
+#define CC2_INT_STS BIT(9)
+#define CC1_INT_STS BIT(8)
+#define DEBOUNCE_TIME_MASK 0xff
+#define DEBOUNCE_EN BIT(0)
+#define ENABLE_TYPE_C_DETECT (CC1_INT_EN | CC2_INT_EN)
+#define ALL_CC_INT_STS (CC1_INT_STS | CC2_INT_STS)
+
+/* Parameter */
+#define DETECT_TIME 50 /* ms */
+
+static const unsigned int usb_type_c_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_NONE,
+};
+
+enum usb_data_roles {
+ DR_NONE,
+ DR_HOST,
+ DR_DEVICE,
+};
+
+static const struct soc_device_attribute rtk_soc_kylin[] = {
+ { .family = "Realtek Kylin", },
+ { /* empty */ }
+};
+
+static int rtd129x_switch_type_c_plug_config(struct type_c_data *type_c,
+ int dr_mode, int cc)
+{
+ void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_0;
+ int val_cc;
+
+#define TYPE_C_EN_SWITCH BIT(29)
+#define TYPE_C_TXRX_SEL (BIT(28) | BIT(27))
+#define TYPE_C_SWITCH_MASK (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
+#define TYPE_C_ENABLE_CC1 TYPE_C_EN_SWITCH
+#define TYPE_C_ENABLE_CC2 (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
+#define TYPE_C_DISABLE_CC ~TYPE_C_SWITCH_MASK
+
+ val_cc = readl(reg);
+ val_cc &= ~TYPE_C_SWITCH_MASK;
+
+ if (cc == DISABLE_CC) {
+ val_cc &= TYPE_C_DISABLE_CC;
+ } else if (cc == ENABLE_CC1) {
+ val_cc |= TYPE_C_ENABLE_CC1;
+ } else if (cc == ENABLE_CC2) {
+ val_cc |= TYPE_C_ENABLE_CC2;
+ } else {
+ dev_err(type_c->dev, "%s: Error cc setting cc=0x%x\n", __func__, cc);
+ return -EINVAL;
+ }
+ writel(val_cc, reg);
+
+ /* waiting cc stable for enable/disable */
+ mdelay(1);
+
+ dev_dbg(type_c->dev, "%s: cc=0x%x val_cc=0x%x usb_typec_ctrl_cc1_0=0x%x\n",
+ __func__, cc, val_cc, readl(reg));
+
+ return 0;
+}
+
+static inline void switch_type_c_plug_config(struct type_c_data *type_c,
+ int dr_mode, int cc)
+{
+ int ret = 0;
+
+ if (soc_device_match(rtk_soc_kylin))
+ ret = rtd129x_switch_type_c_plug_config(type_c, dr_mode, cc);
+
+ if (ret < 0)
+ dev_err(type_c->dev, "%s: Error set type c plug config\n",
+ __func__);
+}
+
+static void switch_type_c_dr_mode(struct type_c_data *type_c, int dr_mode, int cc)
+{
+ bool is_host = false;
+ bool is_device = false;
+ bool polarity = false;
+ bool vbus = false;
+ bool ss = true;
+
+ switch_type_c_plug_config(type_c, dr_mode, cc);
+ if (cc == ENABLE_CC2)
+ polarity = true;
+
+ switch (dr_mode) {
+ case USB_DR_MODE_HOST:
+ is_host = true;
+ break;
+ case USB_DR_MODE_PERIPHERAL:
+ is_device = true;
+ vbus = true;
+ break;
+ default:
+ dev_dbg(type_c->dev, "%s dr_mode=%d ==> no host or device\n",
+ __func__, dr_mode);
+ break;
+ }
+
+ dev_dbg(type_c->dev, "%s is_host=%d is_device=%d vbus=%d polarity=%d\n",
+ __func__, is_host, is_device, vbus, polarity);
+
+ /* for EXTCON_USB device mode */
+ extcon_set_state(type_c->edev, EXTCON_USB, is_device);
+ extcon_set_property(type_c->edev, EXTCON_USB,
+ EXTCON_PROP_USB_VBUS,
+ (union extcon_property_value)(int)vbus);
+ extcon_set_property(type_c->edev, EXTCON_USB,
+ EXTCON_PROP_USB_TYPEC_POLARITY,
+ (union extcon_property_value)(int)polarity);
+ extcon_set_property(type_c->edev, EXTCON_USB,
+ EXTCON_PROP_USB_SS,
+ (union extcon_property_value)(int)ss);
+
+ /* for EXTCON_USB_HOST host mode */
+ extcon_set_state(type_c->edev, EXTCON_USB_HOST, is_host);
+ extcon_set_property(type_c->edev, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_VBUS,
+ (union extcon_property_value)(int)vbus);
+ extcon_set_property(type_c->edev, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_TYPEC_POLARITY,
+ (union extcon_property_value)(int)polarity);
+ extcon_set_property(type_c->edev, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_SS,
+ (union extcon_property_value)(int)ss);
+
+ /* sync EXTCON_USB and EXTCON_USB_HOST */
+ extcon_sync(type_c->edev, EXTCON_USB);
+ extcon_sync(type_c->edev, EXTCON_USB_HOST);
+
+ if (type_c->port) {
+ switch (dr_mode) {
+ case USB_DR_MODE_HOST:
+ typec_set_data_role(type_c->port, TYPEC_HOST);
+ typec_set_pwr_role(type_c->port, TYPEC_SOURCE);
+ break;
+ case USB_DR_MODE_PERIPHERAL:
+ typec_set_data_role(type_c->port, TYPEC_DEVICE);
+ typec_set_pwr_role(type_c->port, TYPEC_SINK);
+ break;
+ default:
+ dev_dbg(type_c->dev, "%s unknown dr_mode=%d\n",
+ __func__, dr_mode);
+ break;
+ }
+ }
+}
+
+/* connector attached/detached */
+static int connector_attached(struct type_c_data *type_c, u32 cc, int dr_mode)
+{
+ void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
+
+ cancel_delayed_work(&type_c->delayed_work);
+
+ switch_type_c_dr_mode(type_c, dr_mode, cc);
+
+ writel(ENABLE_TYPE_C_DETECT | readl(reg), reg);
+
+ return 0;
+}
+
+static int connector_detached(struct type_c_data *type_c, u32 cc, int dr_mode)
+{
+ void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
+
+ writel(~ENABLE_TYPE_C_DETECT & readl(reg), reg);
+
+ switch_type_c_dr_mode(type_c, 0, cc);
+
+ schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(DETECT_TIME));
+
+ return 0;
+}
+
+/* detect host device switch */
+static int __detect_host_device(struct type_c_data *type_c, u32 rp_or_rd_en)
+{
+ struct device *dev = type_c->dev;
+ void __iomem *reg_base = type_c->reg_base;
+ u32 cc1_config, cc2_config, default_ctrl;
+ u32 cc1_switch = 0;
+
+ default_ctrl = readl(reg_base + USB_TYPEC_CTRL) & DEBOUNCE_TIME_MASK;
+ writel(default_ctrl, reg_base + USB_TYPEC_CTRL);
+
+ cc1_config = readl(reg_base + USB_TYPEC_CTRL_CC1_0);
+ cc2_config = readl(reg_base + USB_TYPEC_CTRL_CC2_0);
+
+ cc1_config &= ~EN_CC_DET;
+ cc2_config &= ~EN_CC_DET;
+ writel(cc1_config, reg_base + USB_TYPEC_CTRL_CC1_0);
+ writel(cc2_config, reg_base + USB_TYPEC_CTRL_CC2_0);
+
+ if (soc_device_match(rtk_soc_kylin))
+ cc1_switch = cc1_config & CC_SWITCH_MASK;
+
+ cc1_config &= CC_CODE_MASK;
+ cc1_config |= rp_or_rd_en | cc1_switch;
+ cc2_config &= CC_CODE_MASK;
+ cc2_config |= rp_or_rd_en;
+ writel(cc2_config, reg_base + USB_TYPEC_CTRL_CC2_0);
+ writel(cc1_config, reg_base + USB_TYPEC_CTRL_CC1_0);
+
+ /* For kylin to disable external rd control gpio */
+ if (soc_device_match(rtk_soc_kylin)) {
+ struct gpio_desc *gpio = type_c->rd_ctrl_gpio_desc;
+
+ if (gpio && gpiod_direction_output(gpio, 1))
+ dev_err(dev, "%s ERROR set rd_ctrl_gpio_desc fail\n", __func__);
+ }
+
+ cc1_config |= EN_CC_DET;
+ cc2_config |= EN_CC_DET;
+ writel(cc1_config, reg_base + USB_TYPEC_CTRL_CC1_0);
+ writel(cc2_config, reg_base + USB_TYPEC_CTRL_CC2_0);
+
+ return 0;
+}
+
+static int detect_device(struct type_c_data *type_c)
+{
+ return __detect_host_device(type_c, type_c->dfp_mode_rp_en);
+}
+
+static int detect_host(struct type_c_data *type_c)
+{
+ return __detect_host_device(type_c, type_c->ufp_mode_rd_en);
+}
+
+static int host_device_switch_detection(struct type_c_data *type_c)
+{
+ if (type_c->cc_mode == IN_HOST_MODE) {
+ type_c->cc_mode = IN_DEVICE_MODE;
+ detect_host(type_c);
+ } else {
+ type_c->cc_mode = IN_HOST_MODE;
+ detect_device(type_c);
+ }
+
+ return 0;
+}
+
+static int detect_type_c_state(struct type_c_data *type_c)
+{
+ struct device *dev = type_c->dev;
+ void __iomem *reg_base = type_c->reg_base;
+ u32 int_status, cc_status, cc_status_check;
+ unsigned long flags;
+
+ spin_lock_irqsave(&type_c->lock, flags);
+
+ int_status = readl(reg_base + USB_TYPEC_CTRL);
+ cc_status = readl(reg_base + USB_TYPEC_STS);
+
+ type_c->connect_change = CONNECT_NO_CHANGE;
+
+ switch (type_c->cc_mode | type_c->is_attach) {
+ case IN_HOST_MODE | IN_ATTACH:
+ if (((cc_status & CC1_DET_STS) == CC1_DET_STS) && type_c->at_cc1 == AT_CC1) {
+ dev_dbg(dev, "IN host mode and cc1 device detach (cc_status=0x%x)",
+ cc_status);
+ type_c->is_attach = TO_DETACH;
+ type_c->connect_change = CONNECT_CHANGE;
+ } else if (((cc_status & CC2_DET_STS) == CC2_DET_STS) &&
+ type_c->at_cc1 == AT_CC2) {
+ dev_dbg(dev, "IN host mode and cc2 device detach (cc_status=0x%x)",
+ cc_status);
+ type_c->is_attach = TO_DETACH;
+ type_c->connect_change = CONNECT_CHANGE;
+ }
+ break;
+ case IN_HOST_MODE | IN_DETACH:
+ cc_status_check = readl(reg_base + USB_TYPEC_STS);
+ if (cc_status_check != (CC1_DET_STS | CC2_DET_STS)) {
+ if (in_interrupt()) {
+ /* Add delay time to avoid capacitive effect of cable. */
+ mdelay(300);
+ } else {
+ spin_unlock_irqrestore(&type_c->lock, flags);
+ /* Add delay time to avoid capacitive effect of cable. */
+ msleep(300);
+ spin_lock_irqsave(&type_c->lock, flags);
+ }
+ cc_status_check = readl(reg_base + USB_TYPEC_STS);
+ }
+ if (cc_status != cc_status_check) {
+ dev_warn(dev, "IN_HOST_MODE: cc_status (0x%x) != cc_status_check (0x%x)\n",
+ cc_status, cc_status_check);
+ cc_status = readl(reg_base + USB_TYPEC_STS);
+ }
+
+ if ((cc_status & CC1_DET_STS) == CC1_DET_STS_RD) {
+ dev_dbg(dev, "IN host mode and cc1 device attach (cc_status=0x%x)",
+ cc_status);
+ type_c->is_attach = TO_ATTACH;
+ type_c->at_cc1 = AT_CC1;
+ type_c->connect_change = CONNECT_CHANGE;
+ } else if ((cc_status & CC2_DET_STS) == CC2_DET_STS_RD) {
+ dev_dbg(dev, "In host mode and cc2 device attach (cc_status=0x%x)",
+ cc_status);
+ type_c->is_attach = TO_ATTACH;
+ type_c->at_cc1 = AT_CC2;
+ type_c->connect_change = CONNECT_CHANGE;
+ }
+ break;
+ case IN_DEVICE_MODE | IN_ATTACH:
+ if ((cc_status & CC1_DET_STS) < CC1_DET_STS_RP ||
+ (cc_status & CC2_DET_STS) < CC2_DET_STS_RP) {
+ /* Add a sw debounce to filter cc signal sent from apple pd adapter */
+ mdelay(5);
+ cc_status_check = readl(reg_base + USB_TYPEC_STS);
+
+ if (cc_status != cc_status_check) {
+ dev_dbg(dev, "IN_DEVICE_MODE: cc_status (0x%x) != cc_status_check (0x%x) maybe use a pd adapter\n",
+ cc_status, cc_status_check);
+ cc_status = cc_status_check;
+ }
+ }
+
+ if ((cc_status & CC1_DET_STS) < CC1_DET_STS_RP && type_c->at_cc1 == AT_CC1) {
+ dev_dbg(dev, "IN device mode and cc1 host disconnect (cc_status=0x%x)",
+ cc_status);
+ type_c->is_attach = TO_DETACH;
+ type_c->connect_change = CONNECT_CHANGE;
+ } else if ((cc_status & CC2_DET_STS) < CC2_DET_STS_RP &&
+ type_c->at_cc1 == AT_CC2) {
+ dev_dbg(dev, "IN device mode and cc2 host disconnect (cc_status=0x%x)",
+ cc_status);
+ type_c->is_attach = TO_DETACH;
+ type_c->connect_change = CONNECT_CHANGE;
+ }
+ break;
+ case IN_DEVICE_MODE | IN_DETACH:
+ cc_status_check = readl(reg_base + USB_TYPEC_STS);
+ if (cc_status_check != 0x0) {
+ if (in_interrupt()) {
+ /* Add delay time to avoid capacitive effect of cable. */
+ mdelay(300);
+ } else {
+ spin_unlock_irqrestore(&type_c->lock, flags);
+ /* Add delay time to avoid capacitive effect of cable. */
+ msleep(300);
+ spin_lock_irqsave(&type_c->lock, flags);
+ }
+ cc_status_check = readl(reg_base + USB_TYPEC_STS);
+ }
+
+ if (cc_status != cc_status_check) {
+ dev_warn(dev, "IN_DEVICE_MODE: cc_status (0x%x) != cc_status_check (0x%x)\n",
+ cc_status, cc_status_check);
+ cc_status = readl(reg_base + USB_TYPEC_STS);
+ }
+
+ if ((cc_status & CC1_DET_STS) >= CC1_DET_STS_RP) {
+ dev_dbg(dev, "IN device mode and cc1 host connect (cc_status=0x%x)",
+ cc_status);
+ type_c->at_cc1 = AT_CC1;
+ type_c->is_attach = TO_ATTACH;
+ type_c->connect_change = CONNECT_CHANGE;
+ } else if ((cc_status & CC2_DET_STS) >= CC2_DET_STS_RP) {
+ dev_dbg(dev, "IN device mode and cc2 host connect (cc_status=0x%x)",
+ cc_status);
+ type_c->at_cc1 = AT_CC2;
+ type_c->is_attach = TO_ATTACH;
+ type_c->connect_change = CONNECT_CHANGE;
+ }
+ break;
+ default:
+ dev_err(dev, "error host or device mode (cc_mode=%d, is_attach=%d) ",
+ type_c->cc_mode, type_c->is_attach);
+ }
+
+ type_c->int_status = int_status;
+ type_c->cc_status = cc_status;
+
+ spin_unlock_irqrestore(&type_c->lock, flags);
+ return 0;
+}
+
+static void host_device_switch(struct work_struct *work)
+{
+ struct type_c_data *type_c = container_of(work, struct type_c_data,
+ delayed_work.work);
+ struct device *dev = type_c->dev;
+ unsigned long flags;
+ int connect_change = 0;
+ int cc_mode = 0;
+ int is_attach = 0;
+ int at_cc1 = 0;
+
+ spin_lock_irqsave(&type_c->lock, flags);
+ if (type_c->connect_change)
+ connect_change = type_c->connect_change;
+ spin_unlock_irqrestore(&type_c->lock, flags);
+
+ if (!connect_change)
+ detect_type_c_state(type_c);
+
+ spin_lock_irqsave(&type_c->lock, flags);
+ if (type_c->connect_change) {
+ connect_change = type_c->connect_change;
+ cc_mode = type_c->cc_mode;
+ is_attach = type_c->is_attach;
+ at_cc1 = type_c->at_cc1;
+ type_c->connect_change = CONNECT_NO_CHANGE;
+ } else {
+ host_device_switch_detection(type_c);
+
+ schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(DETECT_TIME));
+ }
+ spin_unlock_irqrestore(&type_c->lock, flags);
+
+ if (!connect_change)
+ return;
+
+ dev_dbg(dev, "%s: usb cable connection change\n", __func__);
+ if (cc_mode == IN_HOST_MODE) {
+ if (is_attach && at_cc1)
+ connector_attached(type_c, ENABLE_CC1, USB_DR_MODE_HOST);
+ else if (is_attach && !at_cc1)
+ connector_attached(type_c, ENABLE_CC2, USB_DR_MODE_HOST);
+ else
+ connector_detached(type_c, DISABLE_CC, USB_DR_MODE_HOST);
+ } else if (cc_mode == IN_DEVICE_MODE) {
+ if (is_attach && at_cc1)
+ connector_attached(type_c, ENABLE_CC1, USB_DR_MODE_PERIPHERAL);
+ else if (is_attach && !at_cc1)
+ connector_attached(type_c, ENABLE_CC2, USB_DR_MODE_PERIPHERAL);
+ else
+ connector_detached(type_c, DISABLE_CC, USB_DR_MODE_PERIPHERAL);
+ } else {
+ dev_err(dev, "Error: IN unknown mode %d to %s at %s (cc_status=0x%x)\n",
+ cc_mode, is_attach ? "attach" : "detach",
+ at_cc1 ? "cc1" : "cc2", type_c->cc_status);
+ }
+ dev_info(dev, "Connection change OK: IN %s mode to %s at %s (cc_status=0x%x)\n",
+ cc_mode == IN_HOST_MODE ? "host" : "device",
+ is_attach ? "attach" : "detach",
+ at_cc1 ? "cc1" : "cc2", type_c->cc_status);
+}
+
+static irqreturn_t type_c_detect_irq(int irq, void *__data)
+{
+ struct type_c_data *type_c = (struct type_c_data *)__data;
+ struct device *dev = type_c->dev;
+ void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
+ unsigned long flags;
+
+ detect_type_c_state(type_c);
+
+ spin_lock_irqsave(&type_c->lock, flags);
+
+ if (type_c->connect_change) {
+ dev_dbg(dev, "%s: IN %s mode to %s (at %s interrupt) int_status=0x%x, cc_status=0x%x",
+ __func__,
+ type_c->cc_mode == IN_HOST_MODE ? "host" : "device",
+ type_c->is_attach ? "attach" : "detach",
+ type_c->at_cc1 ? "cc1" : "cc2",
+ type_c->int_status, type_c->cc_status);
+
+ /* clear interrupt status */
+ writel(~ALL_CC_INT_STS & readl(reg), reg);
+
+ cancel_delayed_work(&type_c->delayed_work);
+ schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(0));
+ } else {
+ static int local_count;
+
+ /* if no connect_change, we keep the status to avoid status lose */
+ if (local_count++ > 10) {
+ /* clear interrupt status */
+ writel(~ALL_CC_INT_STS & readl(reg), reg);
+ local_count = 0;
+ }
+ }
+
+ spin_unlock_irqrestore(&type_c->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int type_c_port_dr_set(struct typec_port *port,
+ enum typec_data_role role)
+{
+ struct type_c_data *type_c = typec_get_drvdata(port);
+ u32 enable_cc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&type_c->lock, flags);
+ enable_cc = type_c->at_cc1 ? ENABLE_CC1 : ENABLE_CC2;
+ spin_unlock_irqrestore(&type_c->lock, flags);
+
+ if (role == TYPEC_HOST)
+ switch_type_c_dr_mode(type_c, USB_DR_MODE_HOST, enable_cc);
+ else if (role == TYPEC_DEVICE)
+ switch_type_c_dr_mode(type_c, USB_DR_MODE_PERIPHERAL, enable_cc);
+ else
+ switch_type_c_dr_mode(type_c, 0, DISABLE_CC);
+
+ return 0;
+}
+
+static const struct typec_operations type_c_port_ops = {
+ .dr_set = type_c_port_dr_set,
+};
+
+#ifdef CONFIG_DEBUG_FS
+static int type_c_parameter_show(struct seq_file *s, void *unused)
+{
+ struct type_c_data *type_c = s->private;
+ struct type_c_cfg *type_c_cfg = type_c->type_c_cfg;
+ struct cc_param *cc_param;
+ unsigned long flags;
+
+ spin_lock_irqsave(&type_c->lock, flags);
+
+ seq_printf(s, "cc_dfp_mode %s\n",
+ ({ char *tmp;
+ switch (type_c_cfg->cc_dfp_mode) {
+ case CC_MODE_DFP_USB:
+ tmp = "CC_MODE_DFP_USB"; break;
+ case CC_MODE_DFP_1_5:
+ tmp = "CC_MODE_DFP_1_5"; break;
+ case CC_MODE_DFP_3_0:
+ tmp = "CC_MODE_DFP_3_0"; break;
+ default:
+ tmp = "?"; break;
+ } tmp; }));
+
+ seq_printf(s, "dfp_mode_rp_en 0x%x\n", type_c->dfp_mode_rp_en);
+ seq_printf(s, "ufp_mode_rd_en 0x%x\n", type_c->ufp_mode_rd_en);
+ seq_printf(s, "cc1_code 0x%x\n", type_c->cc1_code);
+ seq_printf(s, "cc2_code 0x%x\n", type_c->cc2_code);
+ seq_printf(s, "cc1_vref 0x%x\n", type_c->cc1_vref);
+ seq_printf(s, "cc2_vref 0x%x\n", type_c->cc2_vref);
+ seq_printf(s, "debounce 0x%x\n", type_c->debounce);
+ seq_puts(s, "\n");
+
+ cc_param = &type_c_cfg->cc1_param;
+ seq_puts(s, "cc1_param:\n");
+ seq_printf(s, " rp_4p7k_code 0x%x\n", cc_param->rp_4p7k_code);
+ seq_printf(s, " rp_36k_code 0x%x\n", cc_param->rp_36k_code);
+ seq_printf(s, " rp_12k_code 0x%x\n", cc_param->rp_12k_code);
+ seq_printf(s, " rd_code 0x%x\n", cc_param->rd_code);
+ seq_printf(s, " vref_2p6v 0x%x\n", cc_param->vref_2p6v);
+ seq_printf(s, " vref_1p23v 0x%x\n", cc_param->vref_1p23v);
+ seq_printf(s, " vref_0p8v 0x%x\n", cc_param->vref_0p8v);
+ seq_printf(s, " vref_0p66v 0x%x\n", cc_param->vref_0p66v);
+ seq_printf(s, " vref_0p4v 0x%x\n", cc_param->vref_0p4v);
+ seq_printf(s, " vref_0p2v 0x%x\n", cc_param->vref_0p2v);
+ seq_printf(s, " vref_1_1p6v 0x%x\n", cc_param->vref_1_1p6v);
+ seq_printf(s, " vref_0_1p6v 0x%x\n", cc_param->vref_0_1p6v);
+
+ cc_param = &type_c_cfg->cc2_param;
+ seq_puts(s, "cc2_param:\n");
+ seq_printf(s, " rp_4p7k_code 0x%x\n", cc_param->rp_4p7k_code);
+ seq_printf(s, " rp_36k_code 0x%x\n", cc_param->rp_36k_code);
+ seq_printf(s, " rp_12k_code 0x%x\n", cc_param->rp_12k_code);
+ seq_printf(s, " rd_code 0x%x\n", cc_param->rd_code);
+ seq_printf(s, " vref_2p6v 0x%x\n", cc_param->vref_2p6v);
+ seq_printf(s, " vref_1p23v 0x%x\n", cc_param->vref_1p23v);
+ seq_printf(s, " vref_0p8v 0x%x\n", cc_param->vref_0p8v);
+ seq_printf(s, " vref_0p66v 0x%x\n", cc_param->vref_0p66v);
+ seq_printf(s, " vref_0p4v 0x%x\n", cc_param->vref_0p4v);
+ seq_printf(s, " vref_0p2v 0x%x\n", cc_param->vref_0p2v);
+ seq_printf(s, " vref_1_1p6v 0x%x\n", cc_param->vref_1_1p6v);
+ seq_printf(s, " vref_0_1p6v 0x%x\n", cc_param->vref_0_1p6v);
+
+ spin_unlock_irqrestore(&type_c->lock, flags);
+
+ return 0;
+}
+
+static int type_c_parameter_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, type_c_parameter_show, inode->i_private);
+}
+
+static const struct file_operations type_c_parameter_fops = {
+ .open = type_c_parameter_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int type_c_status_show(struct seq_file *s, void *unused)
+{
+ struct type_c_data *type_c = s->private;
+ unsigned long flags;
+
+ spin_lock_irqsave(&type_c->lock, flags);
+
+ seq_printf(s, "In %s mode %s at %s (cc_status=0x%x)\n",
+ type_c->cc_mode == IN_HOST_MODE ? "host" : "device",
+ type_c->is_attach ? "attach" : "detach",
+ type_c->at_cc1 ? "cc1" : "cc2", type_c->cc_status);
+
+ seq_printf(s, "Read Register (type_c_ctrl_cc1_0=0x%x)\n",
+ readl(type_c->reg_base + 0x0));
+ seq_printf(s, "Read Register (type_c_ctrl_cc1_1=0x%x)\n",
+ readl(type_c->reg_base + 0x4));
+ seq_printf(s, "Read Register (type_c_ctrl_cc2_0=0x%x)\n",
+ readl(type_c->reg_base + 0x8));
+ seq_printf(s, "Read Register (type_c_ctrl_cc2_1=0x%x)\n",
+ readl(type_c->reg_base + 0xc));
+ seq_printf(s, "Read Register (type_c_status=0x%x)\n",
+ readl(type_c->reg_base + 0x10));
+ seq_printf(s, "Read Register (type_c_ctrl=0x%x)\n",
+ readl(type_c->reg_base + 0x14));
+
+ spin_unlock_irqrestore(&type_c->lock, flags);
+
+ return 0;
+}
+
+static int type_c_status_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, type_c_status_show, inode->i_private);
+}
+
+static const struct file_operations type_c_status_fops = {
+ .open = type_c_status_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static inline void create_debug_files(struct type_c_data *type_c)
+{
+ type_c->debug_dir = debugfs_create_dir("type_c", usb_debug_root);
+
+ debugfs_create_file("parameter", 0444, type_c->debug_dir, type_c,
+ &type_c_parameter_fops);
+
+ debugfs_create_file("status", 0444, type_c->debug_dir, type_c,
+ &type_c_status_fops);
+}
+
+static inline void remove_debug_files(struct type_c_data *type_c)
+{
+ debugfs_remove_recursive(type_c->debug_dir);
+}
+#else
+static inline void create_debug_files(struct type_c_data *type_c) { }
+static inline void remove_debug_files(struct type_c_data *type_c) { }
+#endif /* CONFIG_DEBUG_FS */
+
+/* Init and probe */
+
+static inline s8 get_value(s8 value)
+{
+ return (((s8)value & 0x8) ? (-(s8)(0x7 & value)) : ((s8)(value)));
+}
+
+static int __updated_type_c_parameter_by_efuse(struct type_c_data *type_c)
+{
+ struct type_c_cfg *type_c_cfg = type_c->type_c_cfg;
+ struct cc_param *cc_param;
+ struct nvmem_cell *cell;
+ s8 cc1_4p7k = 0;
+ s8 cc1_12k = 0;
+ s8 cc1_0p2v = 0;
+ s8 cc1_0p8v = 0;
+ s8 cc1_2p6v = 0;
+ s8 cc1_0p66v = 0;
+ s8 cc1_1p23v = 0;
+ s8 cc2_4p7k = 0;
+ s8 cc2_12k = 0;
+ s8 cc2_0p2v = 0;
+ s8 cc2_0p8v = 0;
+ s8 cc2_2p6v = 0;
+ s8 cc2_0p66v = 0;
+ s8 cc2_1p23v = 0;
+
+ cell = nvmem_cell_get(type_c->dev, "usb-cal");
+ if (IS_ERR(cell)) {
+ dev_warn(type_c->dev, "%s failed to get usb-cal: %ld\n",
+ __func__, PTR_ERR(cell));
+ } else {
+ unsigned char *buf;
+ size_t buf_size;
+ int value_size = 4;
+ int value_mask = (BIT(value_size) - 1);
+
+ buf = nvmem_cell_read(cell, &buf_size);
+ if (!IS_ERR(buf)) {
+ cc1_0p2v = get_value((buf[0] >> value_size * 0) & value_mask);
+ cc1_0p8v = get_value((buf[0] >> value_size * 1) & value_mask);
+ cc1_2p6v = get_value((buf[1] >> value_size * 0) & value_mask);
+ cc1_0p66v = get_value((buf[1] >> value_size * 1) & value_mask);
+ cc1_1p23v = get_value((buf[2] >> value_size * 0) & value_mask);
+
+ cc2_0p2v = get_value((buf[3] >> value_size * 0) & value_mask);
+ cc2_0p8v = get_value((buf[3] >> value_size * 1) & value_mask);
+ cc2_2p6v = get_value((buf[4] >> value_size * 0) & value_mask);
+ cc2_0p66v = get_value((buf[4] >> value_size * 1) & value_mask);
+ cc2_1p23v = get_value((buf[5] >> value_size * 0) & value_mask);
+
+ cc1_4p7k = get_value((buf[6] >> value_size * 0) & value_mask);
+ cc1_12k = get_value((buf[6] >> value_size * 1) & value_mask);
+ cc2_4p7k = get_value((buf[7] >> value_size * 0) & value_mask);
+ cc2_12k = get_value((buf[7] >> value_size * 1) & value_mask);
+
+ kfree(buf);
+ }
+ nvmem_cell_put(cell);
+ }
+
+ dev_dbg(type_c->dev, "check efuse cc1_4p7k=%d cc1_12k=%d cc2_4p7k=%d cc2_12k=%d\n",
+ cc1_4p7k, cc1_12k, cc2_4p7k, cc2_12k);
+ dev_dbg(type_c->dev, "check efuse cc1_0p2v=%d cc1_0p8v=%d cc1_2p6v=%d cc1_0p66v=%d cc1_1p23v=%d\n",
+ cc1_0p2v, cc1_0p8v, cc1_2p6v, cc1_0p66v, cc1_1p23v);
+ dev_dbg(type_c->dev, "check efuse cc2_0p2v=%d cc2_0p8v=%d cc2_2p6v=%d cc2_0p66v=%d cc2_1p23v=%d\n",
+ cc2_0p2v, cc2_0p8v, cc2_2p6v, cc2_0p66v, cc2_1p23v);
+
+ cc_param = &type_c_cfg->cc1_param;
+ cc_param->rp_4p7k_code = cc_param->rp_4p7k_code + cc1_4p7k;
+ cc_param->rp_12k_code = cc_param->rp_12k_code + cc1_12k;
+
+ cc_param->vref_1p23v = cc_param->vref_1p23v + cc1_1p23v;
+ cc_param->vref_0p66v = cc_param->vref_0p66v + cc1_0p66v;
+ cc_param->vref_2p6v = cc_param->vref_2p6v + cc1_2p6v;
+ cc_param->vref_0p8v = cc_param->vref_0p8v + cc1_0p8v;
+ cc_param->vref_0p2v = cc_param->vref_0p2v + cc1_0p2v;
+
+ cc_param = &type_c_cfg->cc2_param;
+ cc_param->rp_4p7k_code = cc_param->rp_4p7k_code + cc2_4p7k;
+ cc_param->rp_12k_code = cc_param->rp_12k_code + cc2_12k;
+
+ cc_param->vref_1p23v = cc_param->vref_1p23v + cc2_1p23v;
+ cc_param->vref_0p66v = cc_param->vref_0p66v + cc2_0p66v;
+ cc_param->vref_2p6v = cc_param->vref_2p6v + cc2_2p6v;
+ cc_param->vref_0p8v = cc_param->vref_0p8v + cc2_0p8v;
+ cc_param->vref_0p2v = cc_param->vref_0p2v + cc2_0p2v;
+
+ return 0;
+}
+
+static int __updated_type_c_parameter_by_efuse_v2(struct type_c_data *type_c)
+{
+ struct type_c_cfg *type_c_cfg = type_c->type_c_cfg;
+ struct cc_param *cc_param;
+ struct nvmem_cell *cell;
+ s8 cc1_4p7k = 0;
+ s8 cc1_12k = 0;
+ s8 cc1_0p2v = 0;
+ s8 cc1_0p8v = 0;
+ s8 cc1_2p6v = 0;
+ s8 cc1_0p66v = 0;
+ s8 cc1_1p23v = 0;
+ s8 cc2_4p7k = 0;
+ s8 cc2_12k = 0;
+ s8 cc2_0p2v = 0;
+ s8 cc2_0p8v = 0;
+ s8 cc2_2p6v = 0;
+ s8 cc2_0p66v = 0;
+ s8 cc2_1p23v = 0;
+
+ cell = nvmem_cell_get(type_c->dev, "usb-type-c-cal");
+ if (IS_ERR(cell)) {
+ dev_warn(type_c->dev, "%s failed to get usb-type-c-cal: %ld\n",
+ __func__, PTR_ERR(cell));
+ } else {
+ unsigned char *buf;
+ size_t buf_size;
+ int value_size = 0;
+ int value_mask = (BIT(value_size) - 1);
+
+ buf = nvmem_cell_read(cell, &buf_size);
+ if (!IS_ERR(buf)) {
+ value_size = 5;
+ value_mask = (BIT(value_size) - 1);
+ cc1_4p7k = buf[0] & value_mask;
+ cc1_12k = buf[1] & value_mask;
+ cc2_4p7k = buf[2] & value_mask;
+ cc2_12k = buf[3] & value_mask;
+
+ value_size = 4;
+ value_mask = (BIT(value_size) - 1);
+ cc1_0p2v = (buf[4] >> value_size * 0) & value_mask;
+ cc1_0p66v = (buf[4] >> value_size * 1) & value_mask;
+ cc1_0p8v = (buf[5] >> value_size * 0) & value_mask;
+ cc1_1p23v = (buf[5] >> value_size * 1) & value_mask;
+ cc1_2p6v = (buf[6] >> value_size * 0) & value_mask;
+
+ cc2_0p2v = (buf[6] >> value_size * 1) & value_mask;
+ cc2_0p66v = (buf[7] >> value_size * 0) & value_mask;
+ cc2_0p8v = (buf[7] >> value_size * 1) & value_mask;
+ cc2_1p23v = (buf[8] >> value_size * 0) & value_mask;
+ cc2_2p6v = (buf[8] >> value_size * 1) & value_mask;
+
+ kfree(buf);
+ }
+ nvmem_cell_put(cell);
+ }
+
+ dev_dbg(type_c->dev, "check efuse v2 cc1_4p7k=%d cc1_12k=%d cc2_4p7k=%d cc2_12k=%d\n",
+ cc1_4p7k, cc1_12k, cc2_4p7k, cc2_12k);
+ dev_dbg(type_c->dev, "check efuse v2 cc1_0p2v=%d cc1_0p8v=%d cc1_2p6v=%d cc1_0p66v=%d cc1_1p23v=%d\n",
+ cc1_0p2v, cc1_0p8v, cc1_2p6v, cc1_0p66v, cc1_1p23v);
+ dev_dbg(type_c->dev, "check efuse v2 cc2_0p2v=%d cc2_0p8v=%d cc2_2p6v=%d cc2_0p66v=%d cc2_1p23v=%d\n",
+ cc2_0p2v, cc2_0p8v, cc2_2p6v, cc2_0p66v, cc2_1p23v);
+
+ cc_param = &type_c_cfg->cc1_param;
+ if (cc1_4p7k)
+ cc_param->rp_4p7k_code = cc1_4p7k;
+ if (cc1_12k)
+ cc_param->rp_12k_code = cc1_12k;
+
+ if (cc1_1p23v)
+ cc_param->vref_1p23v = cc1_1p23v;
+ if (cc1_0p66v)
+ cc_param->vref_0p66v = cc1_0p66v;
+ if (cc1_2p6v)
+ cc_param->vref_2p6v = cc1_2p6v;
+ if (cc1_0p8v)
+ cc_param->vref_0p8v = cc1_0p8v;
+ if (cc1_0p2v)
+ cc_param->vref_0p2v = cc1_0p2v;
+
+ cc_param = &type_c_cfg->cc2_param;
+ if (cc2_4p7k)
+ cc_param->rp_4p7k_code = cc2_4p7k;
+ if (cc2_12k)
+ cc_param->rp_12k_code = cc2_12k;
+
+ if (cc2_1p23v)
+ cc_param->vref_1p23v = cc2_1p23v;
+ if (cc2_0p66v)
+ cc_param->vref_0p66v = cc2_0p66v;
+ if (cc2_2p6v)
+ cc_param->vref_2p6v = cc2_2p6v;
+ if (cc2_0p8v)
+ cc_param->vref_0p8v = cc2_0p8v;
+ if (cc2_0p2v)
+ cc_param->vref_0p2v = cc2_0p2v;
+
+ return 0;
+}
+
+static void get_default_type_c_parameter(struct type_c_data *type_c)
+{
+ void __iomem *reg;
+ int val;
+
+ type_c->dfp_mode_rp_en = dfp_mode(CC_MODE_DFP_3_0) | EN_RP4P7K;
+ type_c->ufp_mode_rd_en = EN_RD;
+
+ reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_0;
+ val = readl(reg);
+ type_c->cc1_code = CC_CODE_MASK & val;
+
+ reg = type_c->reg_base + USB_TYPEC_CTRL_CC2_0;
+ val = readl(reg);
+ type_c->cc2_code = CC_CODE_MASK & val;
+
+ reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_1;
+ val = readl(reg);
+ type_c->cc1_vref = val;
+
+ reg = type_c->reg_base + USB_TYPEC_CTRL_CC2_1;
+ val = readl(reg);
+ type_c->cc2_vref = val;
+
+ reg = type_c->reg_base + USB_TYPEC_CTRL;
+ val = readl(reg);
+ type_c->debounce = DEBOUNCE_TIME_MASK & val;
+}
+
+static int setup_type_c_parameter(struct type_c_data *type_c)
+{
+ struct type_c_cfg *type_c_cfg = type_c->type_c_cfg;
+ struct cc_param *cc_param;
+ struct soc_device_attribute rtk_soc_efuse_v1[] = {
+ { .family = "Realtek Phoenix",},
+ { .family = "Realtek Kylin",},
+ { .family = "Realtek Hercules",},
+ { .family = "Realtek Thor",},
+ { .family = "Realtek Hank",},
+ { .family = "Realtek Groot",},
+ { .family = "Realtek Stark",},
+ { .family = "Realtek Parker",},
+ { /* empty */ }
+ };
+
+ if (type_c_cfg->use_defalut_parameter) {
+ get_default_type_c_parameter(type_c);
+ return 0;
+ }
+
+ if (soc_device_match(rtk_soc_efuse_v1))
+ __updated_type_c_parameter_by_efuse(type_c);
+ else
+ __updated_type_c_parameter_by_efuse_v2(type_c);
+
+ /*
+ * UFP rd vref_ufp : 1p23v, 0p66v, 0p2v
+ * DFP_USB rp36k vref_dfp_usb: 0_1p6v, 0p2v, unused
+ * DFP_1.5 rp12k vref_dfp_1_5: 1_1p6v, 0p4v, 0p2v
+ * DFP_3.0 rp4p7k vref_dfp_3_0: 2p6v, 0p8v, 0p2v
+ */
+
+ switch (type_c_cfg->cc_dfp_mode) {
+ case CC_MODE_DFP_USB:
+ type_c->dfp_mode_rp_en = dfp_mode(CC_MODE_DFP_USB) | EN_RP36K;
+ break;
+ case CC_MODE_DFP_1_5:
+ type_c->dfp_mode_rp_en = dfp_mode(CC_MODE_DFP_1_5) | EN_RP12K;
+ break;
+ case CC_MODE_DFP_3_0:
+ type_c->dfp_mode_rp_en = dfp_mode(CC_MODE_DFP_3_0) | EN_RP4P7K;
+ break;
+ default:
+ dev_err(type_c->dev, "%s: unknown cc_dfp_mode %d\n",
+ __func__, type_c_cfg->cc_dfp_mode);
+ }
+
+ type_c->ufp_mode_rd_en = EN_RD;
+
+ cc_param = &type_c_cfg->cc1_param;
+ type_c->cc1_code = rp4pk_code(cc_param->rp_4p7k_code) |
+ rp36k_code(cc_param->rp_36k_code) |
+ rp12k_code(cc_param->rp_12k_code) |
+ rd_code(cc_param->rd_code);
+
+ if (type_c_cfg->parameter_ver == PARAMETER_V0)
+ type_c->cc1_vref = V0_vref_2p6v(cc_param->vref_2p6v) |
+ V0_vref_1p23v(cc_param->vref_1p23v) |
+ V0_vref_0p8v(cc_param->vref_0p8v) |
+ V0_vref_0p66v(cc_param->vref_0p66v) |
+ V0_vref_0p4v(cc_param->vref_0p4v) |
+ V0_vref_0p2v(cc_param->vref_0p2v) |
+ V0_vref_1_1p6v(cc_param->vref_1_1p6v) |
+ V0_vref_0_1p6v(cc_param->vref_0_1p6v);
+ else if (type_c_cfg->parameter_ver == PARAMETER_V1)
+ type_c->cc1_vref = V1_vref_2p6v(cc_param->vref_2p6v) |
+ V1_vref_1p23v(cc_param->vref_1p23v) |
+ V1_vref_0p8v(cc_param->vref_0p8v) |
+ V1_vref_0p66v(cc_param->vref_0p66v) |
+ V1_vref_0p4v(cc_param->vref_0p4v) |
+ V1_vref_0p2v(cc_param->vref_0p2v) |
+ V1_vref_1_1p6v(cc_param->vref_1_1p6v) |
+ V1_vref_0_1p6v(cc_param->vref_0_1p6v);
+ else
+ dev_err(type_c->dev, "%s: unknown parameter_ver %d\n",
+ __func__, type_c_cfg->parameter_ver);
+
+ cc_param = &type_c_cfg->cc2_param;
+ type_c->cc2_code = rp4pk_code(cc_param->rp_4p7k_code)
+ | rp36k_code(cc_param->rp_36k_code)
+ | rp12k_code(cc_param->rp_12k_code)
+ | rd_code(cc_param->rd_code);
+
+ if (type_c_cfg->parameter_ver == PARAMETER_V0)
+ type_c->cc2_vref = V0_vref_2p6v(cc_param->vref_2p6v) |
+ V0_vref_1p23v(cc_param->vref_1p23v) |
+ V0_vref_0p8v(cc_param->vref_0p8v) |
+ V0_vref_0p66v(cc_param->vref_0p66v) |
+ V0_vref_0p4v(cc_param->vref_0p4v) |
+ V0_vref_0p2v(cc_param->vref_0p2v) |
+ V0_vref_1_1p6v(cc_param->vref_1_1p6v) |
+ V0_vref_0_1p6v(cc_param->vref_0_1p6v);
+ else if (type_c_cfg->parameter_ver == PARAMETER_V1)
+ type_c->cc2_vref = V1_vref_2p6v(cc_param->vref_2p6v) |
+ V1_vref_1p23v(cc_param->vref_1p23v) |
+ V1_vref_0p8v(cc_param->vref_0p8v) |
+ V1_vref_0p66v(cc_param->vref_0p66v) |
+ V1_vref_0p4v(cc_param->vref_0p4v) |
+ V1_vref_0p2v(cc_param->vref_0p2v) |
+ V1_vref_1_1p6v(cc_param->vref_1_1p6v) |
+ V1_vref_0_1p6v(cc_param->vref_0_1p6v);
+ else
+ dev_err(type_c->dev, "%s: unknown parameter_ver %d\n",
+ __func__, type_c_cfg->parameter_ver);
+
+ type_c->debounce = (type_c_cfg->debounce_val << 1) | DEBOUNCE_EN;
+
+ return 0;
+}
+
+static int extcon_rtk_type_c_init(struct type_c_data *type_c)
+{
+ struct device *dev = type_c->dev;
+ unsigned long flags;
+ void __iomem *reg;
+ int val;
+
+ spin_lock_irqsave(&type_c->lock, flags);
+
+ /* set parameter */
+ reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_0;
+ val = readl(reg);
+ val = (~CC_CODE_MASK & val) | (type_c->cc1_code & CC_CODE_MASK);
+ writel(val, reg);
+
+ reg = type_c->reg_base + USB_TYPEC_CTRL_CC2_0;
+ val = readl(reg);
+ val = (~CC_CODE_MASK & val) | (type_c->cc2_code & CC_CODE_MASK);
+
+ reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_1;
+ writel(type_c->cc1_vref, reg);
+
+ reg = type_c->reg_base + USB_TYPEC_CTRL_CC2_1;
+ writel(type_c->cc2_vref, reg);
+
+ reg = type_c->reg_base + USB_TYPEC_CTRL;
+ val = readl(reg);
+ val = (~DEBOUNCE_TIME_MASK & val) | (type_c->debounce & DEBOUNCE_TIME_MASK);
+
+ dev_info(dev, "First check USB_DR_MODE_PERIPHERAL");
+ type_c->cc_mode = IN_DEVICE_MODE;
+ type_c->is_attach = IN_DETACH;
+ type_c->connect_change = CONNECT_NO_CHANGE;
+
+ detect_host(type_c);
+
+ spin_unlock_irqrestore(&type_c->lock, flags);
+
+ schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(0));
+
+ if (!type_c->port) {
+ struct typec_capability typec_cap = { };
+ struct fwnode_handle *fwnode;
+ const char *buf;
+ int ret;
+
+ typec_cap.revision = USB_TYPEC_REV_1_0;
+ typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
+ typec_cap.driver_data = type_c;
+ typec_cap.ops = &type_c_port_ops;
+
+ fwnode = device_get_named_child_node(dev, "connector");
+ if (!fwnode)
+ return -EINVAL;
+
+ ret = fwnode_property_read_string(fwnode, "power-role", &buf);
+ if (ret) {
+ dev_err(dev, "power-role not found: %d\n", ret);
+ return ret;
+ }
+
+ ret = typec_find_port_power_role(buf);
+ if (ret < 0)
+ return ret;
+ typec_cap.type = ret;
+
+ ret = fwnode_property_read_string(fwnode, "data-role", &buf);
+ if (ret) {
+ dev_err(dev, "data-role not found: %d\n", ret);
+ return ret;
+ }
+
+ ret = typec_find_port_data_role(buf);
+ if (ret < 0)
+ return ret;
+ typec_cap.data = ret;
+
+ type_c->port = typec_register_port(type_c->dev, &typec_cap);
+ if (IS_ERR(type_c->port))
+ return PTR_ERR(type_c->port);
+ }
+
+ return 0;
+}
+
+static int extcon_rtk_type_c_edev_register(struct type_c_data *type_c)
+{
+ struct device *dev = type_c->dev;
+ int ret = 0;
+
+ type_c->edev = devm_extcon_dev_allocate(dev, usb_type_c_cable);
+ if (IS_ERR(type_c->edev)) {
+ dev_err(dev, "failed to allocate extcon device\n");
+ return -ENOMEM;
+ }
+
+ ret = devm_extcon_dev_register(dev, type_c->edev);
+ if (ret < 0) {
+ dev_err(dev, "failed to register extcon device\n");
+ return ret;
+ }
+
+ extcon_set_property_capability(type_c->edev, EXTCON_USB,
+ EXTCON_PROP_USB_VBUS);
+ extcon_set_property_capability(type_c->edev, EXTCON_USB,
+ EXTCON_PROP_USB_TYPEC_POLARITY);
+ extcon_set_property_capability(type_c->edev, EXTCON_USB,
+ EXTCON_PROP_USB_SS);
+
+ extcon_set_property_capability(type_c->edev, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_VBUS);
+ extcon_set_property_capability(type_c->edev, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_TYPEC_POLARITY);
+ extcon_set_property_capability(type_c->edev, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_SS);
+
+ return ret;
+}
+
+static int extcon_rtk_type_c_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct type_c_data *type_c;
+ const struct type_c_cfg *type_c_cfg;
+ int ret = 0;
+
+ type_c = devm_kzalloc(dev, sizeof(*type_c), GFP_KERNEL);
+ if (!type_c)
+ return -ENOMEM;
+
+ type_c->reg_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(type_c->reg_base))
+ return PTR_ERR(type_c->reg_base);
+
+ type_c->dev = dev;
+
+ type_c->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ if (type_c->irq <= 0) {
+ dev_err(&pdev->dev, "Type C driver with no IRQ. Check %s setup!\n",
+ dev_name(&pdev->dev));
+ ret = -ENODEV;
+ goto err;
+ }
+
+ ret = devm_request_irq(dev, type_c->irq, type_c_detect_irq,
+ IRQF_SHARED, "type_c_detect", type_c);
+
+ spin_lock_init(&type_c->lock);
+
+ type_c->rd_ctrl_gpio_desc = NULL;
+ if (soc_device_match(rtk_soc_kylin)) {
+ struct gpio_desc *gpio;
+
+ gpio = fwnode_gpiod_get_index(of_fwnode_handle(dev->of_node),
+ "realtek,rd-ctrl-gpios",
+ 0, GPIOD_OUT_HIGH, "rd-ctrl-gpio");
+ if (IS_ERR(gpio)) {
+ dev_err(dev, "Error rd_ctrl-gpios no found (err=%d)\n",
+ (int)PTR_ERR(gpio));
+ } else {
+ type_c->rd_ctrl_gpio_desc = gpio;
+ dev_dbg(dev, "%s get rd-ctrl-gpios (id=%d) OK\n",
+ __func__, desc_to_gpio(gpio));
+ }
+ }
+
+ type_c_cfg = of_device_get_match_data(dev);
+ if (!type_c_cfg) {
+ dev_err(dev, "type_c config are not assigned!\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ type_c->type_c_cfg = devm_kzalloc(dev, sizeof(*type_c_cfg), GFP_KERNEL);
+
+ memcpy(type_c->type_c_cfg, type_c_cfg, sizeof(*type_c_cfg));
+
+ if (setup_type_c_parameter(type_c)) {
+ dev_err(dev, "ERROR: %s to setup type c parameter!!", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ INIT_DELAYED_WORK(&type_c->delayed_work, host_device_switch);
+
+ ret = extcon_rtk_type_c_init(type_c);
+ if (ret) {
+ dev_err(dev, "%s failed to init type_c\n", __func__);
+ goto err;
+ }
+
+ platform_set_drvdata(pdev, type_c);
+
+ ret = extcon_rtk_type_c_edev_register(type_c);
+
+ create_debug_files(type_c);
+
+ return 0;
+
+err:
+ dev_err(&pdev->dev, "%s: Probe fail, %d\n", __func__, ret);
+
+ return ret;
+}
+
+static void extcon_rtk_type_c_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct type_c_data *type_c = dev_get_drvdata(dev);
+ u32 default_ctrl;
+ unsigned long flags;
+
+ remove_debug_files(type_c);
+
+ if (type_c->port) {
+ typec_unregister_port(type_c->port);
+ type_c->port = NULL;
+ }
+
+ cancel_delayed_work_sync(&type_c->delayed_work);
+ flush_delayed_work(&type_c->delayed_work);
+ WARN_ON_ONCE(delayed_work_pending(&type_c->delayed_work));
+
+ spin_lock_irqsave(&type_c->lock, flags);
+ /* disable interrupt */
+ default_ctrl = readl(type_c->reg_base + USB_TYPEC_CTRL) &
+ DEBOUNCE_TIME_MASK;
+ writel(default_ctrl, type_c->reg_base + USB_TYPEC_CTRL);
+
+ /* disable cc detect, rp, rd */
+ writel(PLR_EN, type_c->reg_base + USB_TYPEC_CTRL_CC1_0);
+ writel(0, type_c->reg_base + USB_TYPEC_CTRL_CC2_0);
+
+ spin_unlock_irqrestore(&type_c->lock, flags);
+
+ if (type_c->rd_ctrl_gpio_desc)
+ gpiod_put(type_c->rd_ctrl_gpio_desc);
+ type_c->rd_ctrl_gpio_desc = NULL;
+
+ free_irq(type_c->irq, type_c);
+}
+
+static const struct type_c_cfg rtd1295_type_c_cfg = {
+ .parameter_ver = PARAMETER_V0,
+ .cc_dfp_mode = CC_MODE_DFP_3_0,
+ .cc1_param = { .rp_4p7k_code = 0xb,
+ .rp_36k_code = 0x17,
+ .rp_12k_code = 0x10,
+ .rd_code = 0,
+ .ra_code = 0,
+ .vref_2p6v = 0x0,
+ .vref_1p23v = 0x0,
+ .vref_0p8v = 0x3,
+ .vref_0p66v = 0x0,
+ .vref_0p4v = 0x0,
+ .vref_0p2v = 0x4,
+ .vref_1_1p6v = 0,
+ .vref_0_1p6v = 0 },
+ .cc2_param = { .rp_4p7k_code = 0xc,
+ .rp_36k_code = 0x17,
+ .rp_12k_code = 0x12,
+ .rd_code = 0,
+ .ra_code = 0,
+ .vref_2p6v = 0x2,
+ .vref_1p23v = 0x0,
+ .vref_0p8v = 0x3,
+ .vref_0p66v = 0x0,
+ .vref_0p4v = 0x0,
+ .vref_0p2v = 0x5,
+ .vref_1_1p6v = 0,
+ .vref_0_1p6v = 0 },
+ .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+ .use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1395_type_c_cfg = {
+ .parameter_ver = PARAMETER_V0,
+ .cc_dfp_mode = CC_MODE_DFP_3_0,
+ .cc1_param = { .rp_4p7k_code = 0xc,
+ .rp_36k_code = 0xb,
+ .rp_12k_code = 0xe,
+ .rd_code = 0x10,
+ .ra_code = 0x0,
+ .vref_2p6v = 0x0,
+ .vref_1p23v = 0x1,
+ .vref_0p8v = 0x0,
+ .vref_0p66v = 0x0,
+ .vref_0p4v = 0x3,
+ .vref_0p2v = 0x0,
+ .vref_1_1p6v = 0x7,
+ .vref_0_1p6v = 0x7 },
+ .cc2_param = { .rp_4p7k_code = 0xb,
+ .rp_36k_code = 0x9,
+ .rp_12k_code = 0xe,
+ .rd_code = 0xf,
+ .ra_code = 0x0,
+ .vref_2p6v = 0x1,
+ .vref_1p23v = 0x3,
+ .vref_0p8v = 0x3,
+ .vref_0p66v = 0x2,
+ .vref_0p4v = 0x3,
+ .vref_0p2v = 0x2,
+ .vref_1_1p6v = 0x7,
+ .vref_0_1p6v = 0x7 },
+ .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+ .use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1619_type_c_cfg = {
+ .parameter_ver = PARAMETER_V0,
+ .cc_dfp_mode = CC_MODE_DFP_3_0,
+ .cc1_param = { .rp_4p7k_code = 0xc,
+ .rp_36k_code = 0xf,
+ .rp_12k_code = 0xe,
+ .rd_code = 0x11,
+ .ra_code = 0x0,
+ .vref_2p6v = 0x5,
+ .vref_1p23v = 0x7,
+ .vref_0p8v = 0xa,
+ .vref_0p66v = 0xa,
+ .vref_0p4v = 0x3,
+ .vref_0p2v = 0x2,
+ .vref_1_1p6v = 0x7,
+ .vref_0_1p6v = 0x7 },
+ .cc2_param = { .rp_4p7k_code = 0xc,
+ .rp_36k_code = 0xf,
+ .rp_12k_code = 0xe,
+ .rd_code = 0xf,
+ .ra_code = 0x0,
+ .vref_2p6v = 0x5,
+ .vref_1p23v = 0x8,
+ .vref_0p8v = 0xa,
+ .vref_0p66v = 0xa,
+ .vref_0p4v = 0x3,
+ .vref_0p2v = 0x2,
+ .vref_1_1p6v = 0x7,
+ .vref_0_1p6v = 0x7 },
+ .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+ .use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1319_type_c_cfg = {
+ .parameter_ver = PARAMETER_V0,
+ .cc_dfp_mode = CC_MODE_DFP_1_5,
+ .cc1_param = { .rp_4p7k_code = 0x9,
+ .rp_36k_code = 0xe,
+ .rp_12k_code = 0x9,
+ .rd_code = 0x9,
+ .ra_code = 0x7,
+ .vref_2p6v = 0x3,
+ .vref_1p23v = 0x7,
+ .vref_0p8v = 0x7,
+ .vref_0p66v = 0x6,
+ .vref_0p4v = 0x2,
+ .vref_0p2v = 0x3,
+ .vref_1_1p6v = 0x4,
+ .vref_0_1p6v = 0x7 },
+ .cc2_param = { .rp_4p7k_code = 0x8,
+ .rp_36k_code = 0xe,
+ .rp_12k_code = 0x9,
+ .rd_code = 0x9,
+ .ra_code = 0x7,
+ .vref_2p6v = 0x3,
+ .vref_1p23v = 0x7,
+ .vref_0p8v = 0x7,
+ .vref_0p66v = 0x6,
+ .vref_0p4v = 0x3,
+ .vref_0p2v = 0x3,
+ .vref_1_1p6v = 0x6,
+ .vref_0_1p6v = 0x7 },
+ .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+ .use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1312c_type_c_cfg = {
+ .parameter_ver = PARAMETER_V0,
+ .cc_dfp_mode = CC_MODE_DFP_1_5,
+ .cc1_param = { .rp_4p7k_code = 0xe,
+ .rp_36k_code = 0xc,
+ .rp_12k_code = 0xc,
+ .rd_code = 0xa,
+ .ra_code = 0x3,
+ .vref_2p6v = 0xa,
+ .vref_1p23v = 0x7,
+ .vref_0p8v = 0x7,
+ .vref_0p66v = 0x7,
+ .vref_0p4v = 0x4,
+ .vref_0p2v = 0x4,
+ .vref_1_1p6v = 0x7,
+ .vref_0_1p6v = 0x7 },
+ .cc2_param = { .rp_4p7k_code = 0xe,
+ .rp_36k_code = 0xc,
+ .rp_12k_code = 0xc,
+ .rd_code = 0xa,
+ .ra_code = 0x3,
+ .vref_2p6v = 0xa,
+ .vref_1p23v = 0x7,
+ .vref_0p8v = 0x7,
+ .vref_0p66v = 0x7,
+ .vref_0p4v = 0x4,
+ .vref_0p2v = 0x4,
+ .vref_1_1p6v = 0x7,
+ .vref_0_1p6v = 0x7 },
+ .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+ .use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1619b_type_c_cfg = {
+ .parameter_ver = PARAMETER_V1,
+ .cc_dfp_mode = CC_MODE_DFP_1_5,
+ .cc1_param = { .rp_4p7k_code = 0xf,
+ .rp_36k_code = 0xf,
+ .rp_12k_code = 0xf,
+ .rd_code = 0xf,
+ .ra_code = 0x7,
+ .vref_2p6v = 0x9,
+ .vref_1p23v = 0x7,
+ .vref_0p8v = 0x9,
+ .vref_0p66v = 0x8,
+ .vref_0p4v = 0x7,
+ .vref_0p2v = 0x9,
+ .vref_1_1p6v = 0x7,
+ .vref_0_1p6v = 0x7 },
+ .cc2_param = { .rp_4p7k_code = 0xf,
+ .rp_36k_code = 0xf,
+ .rp_12k_code = 0xf,
+ .rd_code = 0xf,
+ .ra_code = 0x7,
+ .vref_1p23v = 0x7,
+ .vref_0p8v = 0x9,
+ .vref_0p66v = 0x8,
+ .vref_0p4v = 0x7,
+ .vref_0p2v = 0x8,
+ .vref_1_1p6v = 0x7,
+ .vref_0_1p6v = 0x7 },
+ .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+ .use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1319d_type_c_cfg = {
+ .parameter_ver = PARAMETER_V1,
+ .cc_dfp_mode = CC_MODE_DFP_1_5,
+ .cc1_param = { .rp_4p7k_code = 0xe,
+ .rp_36k_code = 0x3,
+ .rp_12k_code = 0xe,
+ .rd_code = 0xf,
+ .ra_code = 0x6,
+ .vref_2p6v = 0x7,
+ .vref_1p23v = 0x7,
+ .vref_0p8v = 0x8,
+ .vref_0p66v = 0x7,
+ .vref_0p4v = 0x7,
+ .vref_0p2v = 0x7,
+ .vref_1_1p6v = 0x7,
+ .vref_0_1p6v = 0x7 },
+ .cc2_param = { .rp_4p7k_code = 0xe,
+ .rp_36k_code = 0x3,
+ .rp_12k_code = 0xe,
+ .rd_code = 0xf,
+ .ra_code = 0x6,
+ .vref_2p6v = 0x7,
+ .vref_1p23v = 0x7,
+ .vref_0p8v = 0x8,
+ .vref_0p66v = 0x7,
+ .vref_0p4v = 0x7,
+ .vref_0p2v = 0x8,
+ .vref_1_1p6v = 0x7,
+ .vref_0_1p6v = 0x7 },
+ .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+ .use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1315e_type_c_cfg = {
+ .parameter_ver = PARAMETER_V1,
+ .cc_dfp_mode = CC_MODE_DFP_1_5,
+ .cc1_param = { .rp_4p7k_code = 0xe,
+ .rp_36k_code = 0x3,
+ .rp_12k_code = 0xe,
+ .rd_code = 0xf,
+ .ra_code = 0x6,
+ .vref_2p6v = 0x7,
+ .vref_1p23v = 0x7,
+ .vref_0p8v = 0x8,
+ .vref_0p66v = 0x7,
+ .vref_0p4v = 0x7,
+ .vref_0p2v = 0x7,
+ .vref_1_1p6v = 0x7,
+ .vref_0_1p6v = 0x7 },
+ .cc2_param = { .rp_4p7k_code = 0xe,
+ .rp_36k_code = 0x3,
+ .rp_12k_code = 0xe,
+ .rd_code = 0xf,
+ .ra_code = 0x6,
+ .vref_2p6v = 0x7,
+ .vref_1p23v = 0x7,
+ .vref_0p8v = 0x8,
+ .vref_0p66v = 0x7,
+ .vref_0p4v = 0x7,
+ .vref_0p2v = 0x8,
+ .vref_1_1p6v = 0x7,
+ .vref_0_1p6v = 0x7 },
+ .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+ .use_defalut_parameter = false,
+};
+
+static const struct of_device_id extcon_rtk_type_c_match[] = {
+ { .compatible = "realtek,rtd1295-type-c", .data = &rtd1295_type_c_cfg },
+ { .compatible = "realtek,rtd1312c-type-c", .data = &rtd1312c_type_c_cfg },
+ { .compatible = "realtek,rtd1315e-type-c", .data = &rtd1315e_type_c_cfg },
+ { .compatible = "realtek,rtd1319-type-c", .data = &rtd1319_type_c_cfg },
+ { .compatible = "realtek,rtd1319d-type-c", .data = &rtd1319d_type_c_cfg },
+ { .compatible = "realtek,rtd1395-type-c", .data = &rtd1395_type_c_cfg },
+ { .compatible = "realtek,rtd1619-type-c", .data = &rtd1619_type_c_cfg },
+ { .compatible = "realtek,rtd1619b-type-c", .data = &rtd1619b_type_c_cfg },
+ {},
+};
+MODULE_DEVICE_TABLE(of, extcon_rtk_type_c_match);
+
+#ifdef CONFIG_PM_SLEEP
+static int extcon_rtk_type_c_prepare(struct device *dev)
+{
+ struct type_c_data *type_c = dev_get_drvdata(dev);
+ u32 default_ctrl;
+ unsigned long flags;
+
+ cancel_delayed_work_sync(&type_c->delayed_work);
+ flush_delayed_work(&type_c->delayed_work);
+ WARN_ON_ONCE(delayed_work_pending(&type_c->delayed_work));
+
+ spin_lock_irqsave(&type_c->lock, flags);
+ /* disable interrupt */
+ default_ctrl = readl(type_c->reg_base + USB_TYPEC_CTRL) &
+ DEBOUNCE_TIME_MASK;
+ writel(default_ctrl, type_c->reg_base + USB_TYPEC_CTRL);
+
+ /* disable cc detect, rp, rd */
+ writel(PLR_EN, type_c->reg_base + USB_TYPEC_CTRL_CC1_0);
+ writel(0, type_c->reg_base + USB_TYPEC_CTRL_CC2_0);
+
+ spin_unlock_irqrestore(&type_c->lock, flags);
+
+ return 0;
+}
+
+static void extcon_rtk_type_c_complete(struct device *dev)
+{
+ /* nothing */
+}
+
+static int extcon_rtk_type_c_suspend(struct device *dev)
+{
+ /* nothing */
+
+ return 0;
+}
+
+static int extcon_rtk_type_c_resume(struct device *dev)
+{
+ struct type_c_data *type_c = dev_get_drvdata(dev);
+ int ret;
+
+ ret = extcon_rtk_type_c_init(type_c);
+ if (ret) {
+ dev_err(dev, "%s failed to init type_c\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops extcon_rtk_type_c_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(extcon_rtk_type_c_suspend, extcon_rtk_type_c_resume)
+ .prepare = extcon_rtk_type_c_prepare,
+ .complete = extcon_rtk_type_c_complete,
+};
+
+#define DEV_PM_OPS (&extcon_rtk_type_c_pm_ops)
+#else
+#define DEV_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP */
+
+static struct platform_driver extcon_rtk_type_c_driver = {
+ .probe = extcon_rtk_type_c_probe,
+ .remove_new = extcon_rtk_type_c_remove,
+ .driver = {
+ .name = "extcon-rtk-type_c",
+ .of_match_table = extcon_rtk_type_c_match,
+ .pm = DEV_PM_OPS,
+ },
+};
+
+module_platform_driver(extcon_rtk_type_c_driver);
+
+MODULE_DESCRIPTION("Realtek Extcon Type C driver");
+MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index aa597cda0d88..2828e9573e90 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -717,14 +717,11 @@ static void create_units(struct fw_device *device)
fw_unit_attributes,
&unit->attribute_group);
- if (device_register(&unit->device) < 0)
- goto skip_unit;
-
fw_device_get(device);
- continue;
-
- skip_unit:
- kfree(unit);
+ if (device_register(&unit->device) < 0) {
+ put_device(&unit->device);
+ continue;
+ }
}
}
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index 2a05f411328f..95c10f3d2282 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -191,7 +191,7 @@ struct fw_node {
/* Upper layer specific data. */
void *data;
- struct fw_node *ports[];
+ struct fw_node *ports[] __counted_by(port_count);
};
static inline struct fw_node *fw_node_get(struct fw_node *node)
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index 749868b9e80d..e779d866022b 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -1519,8 +1519,9 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
sdev->use_10_for_rw = 1;
if (sbp2_param_exclusive_login) {
- sdev->manage_system_start_stop = true;
- sdev->manage_runtime_start_stop = true;
+ sdev->manage_system_start_stop = 1;
+ sdev->manage_runtime_start_stop = 1;
+ sdev->manage_shutdown = 1;
}
if (sdev->type == TYPE_ROM)
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index b59e3041fd62..4a98a859d44d 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -77,30 +77,6 @@ config FIRMWARE_MEMMAP
See also Documentation/ABI/testing/sysfs-firmware-memmap.
-config EFI_PCDP
- bool "Console device selection via EFI PCDP or HCDP table"
- depends on ACPI && EFI && IA64
- default y if IA64
- help
- If your firmware supplies the PCDP table, and you want to
- automatically use the primary console device it describes
- as the Linux console, say Y here.
-
- If your firmware supplies the HCDP table, and you want to
- use the first serial port it describes as the Linux console,
- say Y here. If your EFI ConOut path contains only a UART
- device, it will become the console automatically. Otherwise,
- you must specify the "console=hcdp" kernel boot argument.
-
- Neither the PCDP nor the HCDP affects naming of serial devices,
- so a serial console may be /dev/ttyS0, /dev/ttyS1, etc, depending
- on how the driver discovers devices.
-
- You must also enable the appropriate drivers (serial, VGA, etc.)
-
- See DIG64_HCDPv20_042804.pdf available from
- <http://www.dig64.org/specifications/>
-
config DMIID
bool "Export DMI identification via sysfs to userspace"
depends on DMI
@@ -155,7 +131,7 @@ config RASPBERRYPI_FIRMWARE
config FW_CFG_SYSFS
tristate "QEMU fw_cfg device support in sysfs"
- depends on SYSFS && (ARM || ARM64 || PARISC || PPC_PMAC || SPARC || X86)
+ depends on SYSFS && (ARM || ARM64 || PARISC || PPC_PMAC || RISCV || SPARC || X86)
depends on HAS_IOPORT_MAP
default n
help
@@ -212,20 +188,6 @@ config MTK_ADSP_IPC
ADSP exists on some mtk processors.
Client might use shared memory to exchange information with ADSP.
-config QCOM_SCM
- tristate
-
-config QCOM_SCM_DOWNLOAD_MODE_DEFAULT
- bool "Qualcomm download mode enabled by default"
- depends on QCOM_SCM
- help
- A device with "download mode" enabled will upon an unexpected
- warm-restart enter a special debug mode that allows the user to
- "download" memory content over USB for offline postmortem analysis.
- The feature can be enabled/disabled on the kernel command line.
-
- Say Y here to enable "download mode" by default.
-
config SYSFB
bool
select BOOT_VESA_SUPPORT
@@ -311,6 +273,7 @@ source "drivers/firmware/efi/Kconfig"
source "drivers/firmware/imx/Kconfig"
source "drivers/firmware/meson/Kconfig"
source "drivers/firmware/psci/Kconfig"
+source "drivers/firmware/qcom/Kconfig"
source "drivers/firmware/smccc/Kconfig"
source "drivers/firmware/tegra/Kconfig"
source "drivers/firmware/xilinx/Kconfig"
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 28fcddcd688f..5f9dab82e1a0 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_ARM_SDE_INTERFACE) += arm_sdei.o
obj-$(CONFIG_DMI) += dmi_scan.o
obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o
obj-$(CONFIG_EDD) += edd.o
-obj-$(CONFIG_EFI_PCDP) += pcdp.o
obj-$(CONFIG_DMIID) += dmi-id.o
obj-$(CONFIG_INTEL_STRATIX10_SERVICE) += stratix10-svc.o
obj-$(CONFIG_INTEL_STRATIX10_RSU) += stratix10-rsu.o
@@ -18,8 +17,6 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
obj-$(CONFIG_MTK_ADSP_IPC) += mtk-adsp-ipc.o
obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o
-obj-$(CONFIG_QCOM_SCM) += qcom-scm.o
-qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
obj-$(CONFIG_SYSFB) += sysfb.o
obj-$(CONFIG_SYSFB_SIMPLEFB) += sysfb_simplefb.o
obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
@@ -35,6 +32,7 @@ obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
obj-y += efi/
obj-y += imx/
obj-y += psci/
+obj-y += qcom/
obj-y += smccc/
obj-y += tegra/
obj-y += xilinx/
diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c
index 2b8bfcd010f5..1c7940ba5539 100644
--- a/drivers/firmware/arm_ffa/bus.c
+++ b/drivers/firmware/arm_ffa/bus.c
@@ -15,6 +15,8 @@
#include "common.h"
+#define SCMI_UEVENT_MODALIAS_FMT "arm_ffa:%04x:%pUb"
+
static DEFINE_IDA(ffa_bus_id);
static int ffa_device_match(struct device *dev, struct device_driver *drv)
@@ -63,10 +65,20 @@ static int ffa_device_uevent(const struct device *dev, struct kobj_uevent_env *e
{
const struct ffa_device *ffa_dev = to_ffa_dev(dev);
- return add_uevent_var(env, "MODALIAS=arm_ffa:%04x:%pUb",
+ return add_uevent_var(env, "MODALIAS=" SCMI_UEVENT_MODALIAS_FMT,
ffa_dev->vm_id, &ffa_dev->uuid);
}
+static ssize_t modalias_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ffa_device *ffa_dev = to_ffa_dev(dev);
+
+ return sysfs_emit(buf, SCMI_UEVENT_MODALIAS_FMT, ffa_dev->vm_id,
+ &ffa_dev->uuid);
+}
+static DEVICE_ATTR_RO(modalias);
+
static ssize_t partition_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -88,6 +100,7 @@ static DEVICE_ATTR_RO(uuid);
static struct attribute *ffa_device_attributes_attrs[] = {
&dev_attr_partition_id.attr,
&dev_attr_uuid.attr,
+ &dev_attr_modalias.attr,
NULL,
};
ATTRIBUTE_GROUPS(ffa_device_attributes);
@@ -193,6 +206,7 @@ struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
dev->release = ffa_release_device;
dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id);
+ ffa_dev->id = id;
ffa_dev->vm_id = vm_id;
ffa_dev->ops = ops;
uuid_copy(&ffa_dev->uuid, uuid);
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 121f4fc903cd..6146b2927d5c 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -22,20 +22,28 @@
#define DRIVER_NAME "ARM FF-A"
#define pr_fmt(fmt) DRIVER_NAME ": " fmt
+#include <linux/acpi.h>
#include <linux/arm_ffa.h>
#include <linux/bitfield.h>
+#include <linux/cpuhotplug.h>
#include <linux/device.h>
+#include <linux/hashtable.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/of_irq.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
+#include <linux/smp.h>
#include <linux/uuid.h>
+#include <linux/xarray.h>
#include "common.h"
-#define FFA_DRIVER_VERSION FFA_VERSION_1_0
+#define FFA_DRIVER_VERSION FFA_VERSION_1_1
#define FFA_MIN_VERSION FFA_VERSION_1_0
#define SENDER_ID_MASK GENMASK(31, 16)
@@ -51,6 +59,8 @@
*/
#define RXTX_BUFFER_SIZE SZ_4K
+#define FFA_MAX_NOTIFICATIONS 64
+
static ffa_fn *invoke_ffa_fn;
static const int ffa_linux_errmap[] = {
@@ -64,6 +74,7 @@ static const int ffa_linux_errmap[] = {
-EACCES, /* FFA_RET_DENIED */
-EAGAIN, /* FFA_RET_RETRY */
-ECANCELED, /* FFA_RET_ABORTED */
+ -ENODATA, /* FFA_RET_NO_DATA */
};
static inline int ffa_to_linux_errno(int errno)
@@ -75,6 +86,10 @@ static inline int ffa_to_linux_errno(int errno)
return -EINVAL;
}
+struct ffa_pcpu_irq {
+ struct ffa_drv_info *info;
+};
+
struct ffa_drv_info {
u32 version;
u16 vm_id;
@@ -83,6 +98,18 @@ struct ffa_drv_info {
void *rx_buffer;
void *tx_buffer;
bool mem_ops_native;
+ bool bitmap_created;
+ bool notif_enabled;
+ unsigned int sched_recv_irq;
+ unsigned int cpuhp_state;
+ struct ffa_pcpu_irq __percpu *irq_pcpu;
+ struct workqueue_struct *notif_pcpu_wq;
+ struct work_struct notif_pcpu_work;
+ struct work_struct irq_work;
+ struct xarray partition_info;
+ unsigned int partition_count;
+ DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS));
+ struct mutex notify_lock; /* lock to protect notifier hashtable */
};
static struct ffa_drv_info *drv_info;
@@ -397,7 +424,7 @@ static u32 ffa_get_num_pages_sg(struct scatterlist *sg)
return num_pages;
}
-static u8 ffa_memory_attributes_get(u32 func_id)
+static u16 ffa_memory_attributes_get(u32 func_id)
{
/*
* For the memory lend or donate operation, if the receiver is a PE or
@@ -416,38 +443,47 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
{
int rc = 0;
bool first = true;
+ u32 composite_offset;
phys_addr_t addr = 0;
+ struct ffa_mem_region *mem_region = buffer;
struct ffa_composite_mem_region *composite;
struct ffa_mem_region_addr_range *constituents;
struct ffa_mem_region_attributes *ep_mem_access;
- struct ffa_mem_region *mem_region = buffer;
u32 idx, frag_len, length, buf_sz = 0, num_entries = sg_nents(args->sg);
mem_region->tag = args->tag;
mem_region->flags = args->flags;
mem_region->sender_id = drv_info->vm_id;
mem_region->attributes = ffa_memory_attributes_get(func_id);
- ep_mem_access = &mem_region->ep_mem_access[0];
+ ep_mem_access = buffer +
+ ffa_mem_desc_offset(buffer, 0, drv_info->version);
+ composite_offset = ffa_mem_desc_offset(buffer, args->nattrs,
+ drv_info->version);
for (idx = 0; idx < args->nattrs; idx++, ep_mem_access++) {
ep_mem_access->receiver = args->attrs[idx].receiver;
ep_mem_access->attrs = args->attrs[idx].attrs;
- ep_mem_access->composite_off = COMPOSITE_OFFSET(args->nattrs);
+ ep_mem_access->composite_off = composite_offset;
ep_mem_access->flag = 0;
ep_mem_access->reserved = 0;
}
mem_region->handle = 0;
- mem_region->reserved_0 = 0;
- mem_region->reserved_1 = 0;
mem_region->ep_count = args->nattrs;
+ if (drv_info->version <= FFA_VERSION_1_0) {
+ mem_region->ep_mem_size = 0;
+ } else {
+ mem_region->ep_mem_size = sizeof(*ep_mem_access);
+ mem_region->ep_mem_offset = sizeof(*mem_region);
+ memset(mem_region->reserved, 0, 12);
+ }
- composite = buffer + COMPOSITE_OFFSET(args->nattrs);
+ composite = buffer + composite_offset;
composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg);
composite->addr_range_cnt = num_entries;
composite->reserved = 0;
- length = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, num_entries);
- frag_len = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, 0);
+ length = composite_offset + CONSTITUENTS_OFFSET(num_entries);
+ frag_len = composite_offset + CONSTITUENTS_OFFSET(0);
if (frag_len > max_fragsize)
return -ENXIO;
@@ -554,6 +590,236 @@ static int ffa_features(u32 func_feat_id, u32 input_props,
return 0;
}
+static int ffa_notification_bitmap_create(void)
+{
+ ffa_value_t ret;
+ u16 vcpu_count = nr_cpu_ids;
+
+ invoke_ffa_fn((ffa_value_t){
+ .a0 = FFA_NOTIFICATION_BITMAP_CREATE,
+ .a1 = drv_info->vm_id, .a2 = vcpu_count,
+ }, &ret);
+
+ if (ret.a0 == FFA_ERROR)
+ return ffa_to_linux_errno((int)ret.a2);
+
+ return 0;
+}
+
+static int ffa_notification_bitmap_destroy(void)
+{
+ ffa_value_t ret;
+
+ invoke_ffa_fn((ffa_value_t){
+ .a0 = FFA_NOTIFICATION_BITMAP_DESTROY,
+ .a1 = drv_info->vm_id,
+ }, &ret);
+
+ if (ret.a0 == FFA_ERROR)
+ return ffa_to_linux_errno((int)ret.a2);
+
+ return 0;
+}
+
+#define NOTIFICATION_LOW_MASK GENMASK(31, 0)
+#define NOTIFICATION_HIGH_MASK GENMASK(63, 32)
+#define NOTIFICATION_BITMAP_HIGH(x) \
+ ((u32)(FIELD_GET(NOTIFICATION_HIGH_MASK, (x))))
+#define NOTIFICATION_BITMAP_LOW(x) \
+ ((u32)(FIELD_GET(NOTIFICATION_LOW_MASK, (x))))
+#define PACK_NOTIFICATION_BITMAP(low, high) \
+ (FIELD_PREP(NOTIFICATION_LOW_MASK, (low)) | \
+ FIELD_PREP(NOTIFICATION_HIGH_MASK, (high)))
+
+#define RECEIVER_VCPU_MASK GENMASK(31, 16)
+#define PACK_NOTIFICATION_GET_RECEIVER_INFO(vcpu_r, r) \
+ (FIELD_PREP(RECEIVER_VCPU_MASK, (vcpu_r)) | \
+ FIELD_PREP(RECEIVER_ID_MASK, (r)))
+
+#define NOTIFICATION_INFO_GET_MORE_PEND_MASK BIT(0)
+#define NOTIFICATION_INFO_GET_ID_COUNT GENMASK(11, 7)
+#define ID_LIST_MASK_64 GENMASK(51, 12)
+#define ID_LIST_MASK_32 GENMASK(31, 12)
+#define MAX_IDS_64 20
+#define MAX_IDS_32 10
+
+#define PER_VCPU_NOTIFICATION_FLAG BIT(0)
+#define SECURE_PARTITION_BITMAP BIT(0)
+#define NON_SECURE_VM_BITMAP BIT(1)
+#define SPM_FRAMEWORK_BITMAP BIT(2)
+#define NS_HYP_FRAMEWORK_BITMAP BIT(3)
+
+static int ffa_notification_bind_common(u16 dst_id, u64 bitmap,
+ u32 flags, bool is_bind)
+{
+ ffa_value_t ret;
+ u32 func, src_dst_ids = PACK_TARGET_INFO(dst_id, drv_info->vm_id);
+
+ func = is_bind ? FFA_NOTIFICATION_BIND : FFA_NOTIFICATION_UNBIND;
+
+ invoke_ffa_fn((ffa_value_t){
+ .a0 = func, .a1 = src_dst_ids, .a2 = flags,
+ .a3 = NOTIFICATION_BITMAP_LOW(bitmap),
+ .a4 = NOTIFICATION_BITMAP_HIGH(bitmap),
+ }, &ret);
+
+ if (ret.a0 == FFA_ERROR)
+ return ffa_to_linux_errno((int)ret.a2);
+ else if (ret.a0 != FFA_SUCCESS)
+ return -EINVAL;
+
+ return 0;
+}
+
+static
+int ffa_notification_set(u16 src_id, u16 dst_id, u32 flags, u64 bitmap)
+{
+ ffa_value_t ret;
+ u32 src_dst_ids = PACK_TARGET_INFO(dst_id, src_id);
+
+ invoke_ffa_fn((ffa_value_t) {
+ .a0 = FFA_NOTIFICATION_SET, .a1 = src_dst_ids, .a2 = flags,
+ .a3 = NOTIFICATION_BITMAP_LOW(bitmap),
+ .a4 = NOTIFICATION_BITMAP_HIGH(bitmap),
+ }, &ret);
+
+ if (ret.a0 == FFA_ERROR)
+ return ffa_to_linux_errno((int)ret.a2);
+ else if (ret.a0 != FFA_SUCCESS)
+ return -EINVAL;
+
+ return 0;
+}
+
+struct ffa_notify_bitmaps {
+ u64 sp_map;
+ u64 vm_map;
+ u64 arch_map;
+};
+
+static int ffa_notification_get(u32 flags, struct ffa_notify_bitmaps *notify)
+{
+ ffa_value_t ret;
+ u16 src_id = drv_info->vm_id;
+ u16 cpu_id = smp_processor_id();
+ u32 rec_vcpu_ids = PACK_NOTIFICATION_GET_RECEIVER_INFO(cpu_id, src_id);
+
+ invoke_ffa_fn((ffa_value_t){
+ .a0 = FFA_NOTIFICATION_GET, .a1 = rec_vcpu_ids, .a2 = flags,
+ }, &ret);
+
+ if (ret.a0 == FFA_ERROR)
+ return ffa_to_linux_errno((int)ret.a2);
+ else if (ret.a0 != FFA_SUCCESS)
+ return -EINVAL; /* Something else went wrong. */
+
+ notify->sp_map = PACK_NOTIFICATION_BITMAP(ret.a2, ret.a3);
+ notify->vm_map = PACK_NOTIFICATION_BITMAP(ret.a4, ret.a5);
+ notify->arch_map = PACK_NOTIFICATION_BITMAP(ret.a6, ret.a7);
+
+ return 0;
+}
+
+struct ffa_dev_part_info {
+ ffa_sched_recv_cb callback;
+ void *cb_data;
+ rwlock_t rw_lock;
+};
+
+static void __do_sched_recv_cb(u16 part_id, u16 vcpu, bool is_per_vcpu)
+{
+ struct ffa_dev_part_info *partition;
+ ffa_sched_recv_cb callback;
+ void *cb_data;
+
+ partition = xa_load(&drv_info->partition_info, part_id);
+ read_lock(&partition->rw_lock);
+ callback = partition->callback;
+ cb_data = partition->cb_data;
+ read_unlock(&partition->rw_lock);
+
+ if (callback)
+ callback(vcpu, is_per_vcpu, cb_data);
+}
+
+static void ffa_notification_info_get(void)
+{
+ int idx, list, max_ids, lists_cnt, ids_processed, ids_count[MAX_IDS_64];
+ bool is_64b_resp;
+ ffa_value_t ret;
+ u64 id_list;
+
+ do {
+ invoke_ffa_fn((ffa_value_t){
+ .a0 = FFA_FN_NATIVE(NOTIFICATION_INFO_GET),
+ }, &ret);
+
+ if (ret.a0 != FFA_FN_NATIVE(SUCCESS) && ret.a0 != FFA_SUCCESS) {
+ if (ret.a2 != FFA_RET_NO_DATA)
+ pr_err("Notification Info fetch failed: 0x%lx (0x%lx)",
+ ret.a0, ret.a2);
+ return;
+ }
+
+ is_64b_resp = (ret.a0 == FFA_FN64_SUCCESS);
+
+ ids_processed = 0;
+ lists_cnt = FIELD_GET(NOTIFICATION_INFO_GET_ID_COUNT, ret.a2);
+ if (is_64b_resp) {
+ max_ids = MAX_IDS_64;
+ id_list = FIELD_GET(ID_LIST_MASK_64, ret.a2);
+ } else {
+ max_ids = MAX_IDS_32;
+ id_list = FIELD_GET(ID_LIST_MASK_32, ret.a2);
+ }
+
+ for (idx = 0; idx < lists_cnt; idx++, id_list >>= 2)
+ ids_count[idx] = (id_list & 0x3) + 1;
+
+ /* Process IDs */
+ for (list = 0; list < lists_cnt; list++) {
+ u16 vcpu_id, part_id, *packed_id_list = (u16 *)&ret.a3;
+
+ if (ids_processed >= max_ids - 1)
+ break;
+
+ part_id = packed_id_list[ids_processed++];
+
+ if (!ids_count[list]) { /* Global Notification */
+ __do_sched_recv_cb(part_id, 0, false);
+ continue;
+ }
+
+ /* Per vCPU Notification */
+ for (idx = 0; idx < ids_count[list]; idx++) {
+ if (ids_processed >= max_ids - 1)
+ break;
+
+ vcpu_id = packed_id_list[ids_processed++];
+
+ __do_sched_recv_cb(part_id, vcpu_id, true);
+ }
+ }
+ } while (ret.a2 & NOTIFICATION_INFO_GET_MORE_PEND_MASK);
+}
+
+static int ffa_run(struct ffa_device *dev, u16 vcpu)
+{
+ ffa_value_t ret;
+ u32 target = dev->vm_id << 16 | vcpu;
+
+ invoke_ffa_fn((ffa_value_t){ .a0 = FFA_RUN, .a1 = target, }, &ret);
+
+ while (ret.a0 == FFA_INTERRUPT)
+ invoke_ffa_fn((ffa_value_t){ .a0 = FFA_RUN, .a1 = ret.a1, },
+ &ret);
+
+ if (ret.a0 == FFA_ERROR)
+ return ffa_to_linux_errno((int)ret.a2);
+
+ return 0;
+}
+
static void ffa_set_up_mem_ops_native_flag(void)
{
if (!ffa_features(FFA_FN_NATIVE(MEM_LEND), 0, NULL, NULL) ||
@@ -587,17 +853,9 @@ static int ffa_partition_info_get(const char *uuid_str,
return 0;
}
-static void _ffa_mode_32bit_set(struct ffa_device *dev)
-{
- dev->mode_32bit = true;
-}
-
static void ffa_mode_32bit_set(struct ffa_device *dev)
{
- if (drv_info->version > FFA_VERSION_1_0)
- return;
-
- _ffa_mode_32bit_set(dev);
+ dev->mode_32bit = true;
}
static int ffa_sync_send_receive(struct ffa_device *dev,
@@ -630,6 +888,245 @@ static int ffa_memory_lend(struct ffa_mem_ops_args *args)
return ffa_memory_ops(FFA_MEM_LEND, args);
}
+#define FFA_SECURE_PARTITION_ID_FLAG BIT(15)
+
+#define ffa_notifications_disabled() (!drv_info->notif_enabled)
+
+enum notify_type {
+ NON_SECURE_VM,
+ SECURE_PARTITION,
+ FRAMEWORK,
+};
+
+struct notifier_cb_info {
+ struct hlist_node hnode;
+ ffa_notifier_cb cb;
+ void *cb_data;
+ enum notify_type type;
+};
+
+static int ffa_sched_recv_cb_update(u16 part_id, ffa_sched_recv_cb callback,
+ void *cb_data, bool is_registration)
+{
+ struct ffa_dev_part_info *partition;
+ bool cb_valid;
+
+ if (ffa_notifications_disabled())
+ return -EOPNOTSUPP;
+
+ partition = xa_load(&drv_info->partition_info, part_id);
+ write_lock(&partition->rw_lock);
+
+ cb_valid = !!partition->callback;
+ if (!(is_registration ^ cb_valid)) {
+ write_unlock(&partition->rw_lock);
+ return -EINVAL;
+ }
+
+ partition->callback = callback;
+ partition->cb_data = cb_data;
+
+ write_unlock(&partition->rw_lock);
+ return 0;
+}
+
+static int ffa_sched_recv_cb_register(struct ffa_device *dev,
+ ffa_sched_recv_cb cb, void *cb_data)
+{
+ return ffa_sched_recv_cb_update(dev->vm_id, cb, cb_data, true);
+}
+
+static int ffa_sched_recv_cb_unregister(struct ffa_device *dev)
+{
+ return ffa_sched_recv_cb_update(dev->vm_id, NULL, NULL, false);
+}
+
+static int ffa_notification_bind(u16 dst_id, u64 bitmap, u32 flags)
+{
+ return ffa_notification_bind_common(dst_id, bitmap, flags, true);
+}
+
+static int ffa_notification_unbind(u16 dst_id, u64 bitmap)
+{
+ return ffa_notification_bind_common(dst_id, bitmap, 0, false);
+}
+
+/* Should be called while the notify_lock is taken */
+static struct notifier_cb_info *
+notifier_hash_node_get(u16 notify_id, enum notify_type type)
+{
+ struct notifier_cb_info *node;
+
+ hash_for_each_possible(drv_info->notifier_hash, node, hnode, notify_id)
+ if (type == node->type)
+ return node;
+
+ return NULL;
+}
+
+static int
+update_notifier_cb(int notify_id, enum notify_type type, ffa_notifier_cb cb,
+ void *cb_data, bool is_registration)
+{
+ struct notifier_cb_info *cb_info = NULL;
+ bool cb_found;
+
+ cb_info = notifier_hash_node_get(notify_id, type);
+ cb_found = !!cb_info;
+
+ if (!(is_registration ^ cb_found))
+ return -EINVAL;
+
+ if (is_registration) {
+ cb_info = kzalloc(sizeof(*cb_info), GFP_KERNEL);
+ if (!cb_info)
+ return -ENOMEM;
+
+ cb_info->type = type;
+ cb_info->cb = cb;
+ cb_info->cb_data = cb_data;
+
+ hash_add(drv_info->notifier_hash, &cb_info->hnode, notify_id);
+ } else {
+ hash_del(&cb_info->hnode);
+ }
+
+ return 0;
+}
+
+static enum notify_type ffa_notify_type_get(u16 vm_id)
+{
+ if (vm_id & FFA_SECURE_PARTITION_ID_FLAG)
+ return SECURE_PARTITION;
+ else
+ return NON_SECURE_VM;
+}
+
+static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id)
+{
+ int rc;
+ enum notify_type type = ffa_notify_type_get(dev->vm_id);
+
+ if (ffa_notifications_disabled())
+ return -EOPNOTSUPP;
+
+ if (notify_id >= FFA_MAX_NOTIFICATIONS)
+ return -EINVAL;
+
+ mutex_lock(&drv_info->notify_lock);
+
+ rc = update_notifier_cb(notify_id, type, NULL, NULL, false);
+ if (rc) {
+ pr_err("Could not unregister notification callback\n");
+ mutex_unlock(&drv_info->notify_lock);
+ return rc;
+ }
+
+ rc = ffa_notification_unbind(dev->vm_id, BIT(notify_id));
+
+ mutex_unlock(&drv_info->notify_lock);
+
+ return rc;
+}
+
+static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
+ ffa_notifier_cb cb, void *cb_data, int notify_id)
+{
+ int rc;
+ u32 flags = 0;
+ enum notify_type type = ffa_notify_type_get(dev->vm_id);
+
+ if (ffa_notifications_disabled())
+ return -EOPNOTSUPP;
+
+ if (notify_id >= FFA_MAX_NOTIFICATIONS)
+ return -EINVAL;
+
+ mutex_lock(&drv_info->notify_lock);
+
+ if (is_per_vcpu)
+ flags = PER_VCPU_NOTIFICATION_FLAG;
+
+ rc = ffa_notification_bind(dev->vm_id, BIT(notify_id), flags);
+ if (rc) {
+ mutex_unlock(&drv_info->notify_lock);
+ return rc;
+ }
+
+ rc = update_notifier_cb(notify_id, type, cb, cb_data, true);
+ if (rc) {
+ pr_err("Failed to register callback for %d - %d\n",
+ notify_id, rc);
+ ffa_notification_unbind(dev->vm_id, BIT(notify_id));
+ }
+ mutex_unlock(&drv_info->notify_lock);
+
+ return rc;
+}
+
+static int ffa_notify_send(struct ffa_device *dev, int notify_id,
+ bool is_per_vcpu, u16 vcpu)
+{
+ u32 flags = 0;
+
+ if (ffa_notifications_disabled())
+ return -EOPNOTSUPP;
+
+ if (is_per_vcpu)
+ flags |= (PER_VCPU_NOTIFICATION_FLAG | vcpu << 16);
+
+ return ffa_notification_set(dev->vm_id, drv_info->vm_id, flags,
+ BIT(notify_id));
+}
+
+static void handle_notif_callbacks(u64 bitmap, enum notify_type type)
+{
+ int notify_id;
+ struct notifier_cb_info *cb_info = NULL;
+
+ for (notify_id = 0; notify_id <= FFA_MAX_NOTIFICATIONS && bitmap;
+ notify_id++, bitmap >>= 1) {
+ if (!(bitmap & 1))
+ continue;
+
+ mutex_lock(&drv_info->notify_lock);
+ cb_info = notifier_hash_node_get(notify_id, type);
+ mutex_unlock(&drv_info->notify_lock);
+
+ if (cb_info && cb_info->cb)
+ cb_info->cb(notify_id, cb_info->cb_data);
+ }
+}
+
+static void notif_pcpu_irq_work_fn(struct work_struct *work)
+{
+ int rc;
+ struct ffa_notify_bitmaps bitmaps;
+
+ rc = ffa_notification_get(SECURE_PARTITION_BITMAP |
+ SPM_FRAMEWORK_BITMAP, &bitmaps);
+ if (rc) {
+ pr_err("Failed to retrieve notifications with %d!\n", rc);
+ return;
+ }
+
+ handle_notif_callbacks(bitmaps.vm_map, NON_SECURE_VM);
+ handle_notif_callbacks(bitmaps.sp_map, SECURE_PARTITION);
+ handle_notif_callbacks(bitmaps.arch_map, FRAMEWORK);
+}
+
+static void
+ffa_self_notif_handle(u16 vcpu, bool is_per_vcpu, void *cb_data)
+{
+ struct ffa_drv_info *info = cb_data;
+
+ if (!is_per_vcpu)
+ notif_pcpu_irq_work_fn(&info->notif_pcpu_work);
+ else
+ queue_work_on(vcpu, info->notif_pcpu_wq,
+ &info->notif_pcpu_work);
+}
+
static const struct ffa_info_ops ffa_drv_info_ops = {
.api_version_get = ffa_api_version_get,
.partition_info_get = ffa_partition_info_get,
@@ -646,10 +1143,24 @@ static const struct ffa_mem_ops ffa_drv_mem_ops = {
.memory_lend = ffa_memory_lend,
};
+static const struct ffa_cpu_ops ffa_drv_cpu_ops = {
+ .run = ffa_run,
+};
+
+static const struct ffa_notifier_ops ffa_drv_notifier_ops = {
+ .sched_recv_cb_register = ffa_sched_recv_cb_register,
+ .sched_recv_cb_unregister = ffa_sched_recv_cb_unregister,
+ .notify_request = ffa_notify_request,
+ .notify_relinquish = ffa_notify_relinquish,
+ .notify_send = ffa_notify_send,
+};
+
static const struct ffa_ops ffa_drv_ops = {
.info_ops = &ffa_drv_info_ops,
.msg_ops = &ffa_drv_msg_ops,
.mem_ops = &ffa_drv_mem_ops,
+ .cpu_ops = &ffa_drv_cpu_ops,
+ .notifier_ops = &ffa_drv_notifier_ops,
};
void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
@@ -680,6 +1191,7 @@ static void ffa_setup_partitions(void)
int count, idx;
uuid_t uuid;
struct ffa_device *ffa_dev;
+ struct ffa_dev_part_info *info;
struct ffa_partition_info *pbuf, *tpbuf;
count = ffa_partition_probe(&uuid_null, &pbuf);
@@ -688,6 +1200,7 @@ static void ffa_setup_partitions(void)
return;
}
+ xa_init(&drv_info->partition_info);
for (idx = 0, tpbuf = pbuf; idx < count; idx++, tpbuf++) {
import_uuid(&uuid, (u8 *)tpbuf->uuid);
@@ -706,9 +1219,238 @@ static void ffa_setup_partitions(void)
if (drv_info->version > FFA_VERSION_1_0 &&
!(tpbuf->properties & FFA_PARTITION_AARCH64_EXEC))
- _ffa_mode_32bit_set(ffa_dev);
+ ffa_mode_32bit_set(ffa_dev);
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ ffa_device_unregister(ffa_dev);
+ continue;
+ }
+ xa_store(&drv_info->partition_info, tpbuf->id, info, GFP_KERNEL);
}
+ drv_info->partition_count = count;
+
kfree(pbuf);
+
+ /* Allocate for the host */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return;
+ xa_store(&drv_info->partition_info, drv_info->vm_id, info, GFP_KERNEL);
+ drv_info->partition_count++;
+}
+
+static void ffa_partitions_cleanup(void)
+{
+ struct ffa_dev_part_info **info;
+ int idx, count = drv_info->partition_count;
+
+ if (!count)
+ return;
+
+ info = kcalloc(count, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return;
+
+ xa_extract(&drv_info->partition_info, (void **)info, 0, VM_ID_MASK,
+ count, XA_PRESENT);
+
+ for (idx = 0; idx < count; idx++)
+ kfree(info[idx]);
+ kfree(info);
+
+ drv_info->partition_count = 0;
+ xa_destroy(&drv_info->partition_info);
+}
+
+/* FFA FEATURE IDs */
+#define FFA_FEAT_NOTIFICATION_PENDING_INT (1)
+#define FFA_FEAT_SCHEDULE_RECEIVER_INT (2)
+#define FFA_FEAT_MANAGED_EXIT_INT (3)
+
+static irqreturn_t irq_handler(int irq, void *irq_data)
+{
+ struct ffa_pcpu_irq *pcpu = irq_data;
+ struct ffa_drv_info *info = pcpu->info;
+
+ queue_work(info->notif_pcpu_wq, &info->irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static void ffa_sched_recv_irq_work_fn(struct work_struct *work)
+{
+ ffa_notification_info_get();
+}
+
+static int ffa_sched_recv_irq_map(void)
+{
+ int ret, irq, sr_intid;
+
+ /* The returned sr_intid is assumed to be SGI donated to NS world */
+ ret = ffa_features(FFA_FEAT_SCHEDULE_RECEIVER_INT, 0, &sr_intid, NULL);
+ if (ret < 0) {
+ if (ret != -EOPNOTSUPP)
+ pr_err("Failed to retrieve scheduler Rx interrupt\n");
+ return ret;
+ }
+
+ if (acpi_disabled) {
+ struct of_phandle_args oirq = {};
+ struct device_node *gic;
+
+ /* Only GICv3 supported currently with the device tree */
+ gic = of_find_compatible_node(NULL, NULL, "arm,gic-v3");
+ if (!gic)
+ return -ENXIO;
+
+ oirq.np = gic;
+ oirq.args_count = 1;
+ oirq.args[0] = sr_intid;
+ irq = irq_create_of_mapping(&oirq);
+ of_node_put(gic);
+#ifdef CONFIG_ACPI
+ } else {
+ irq = acpi_register_gsi(NULL, sr_intid, ACPI_EDGE_SENSITIVE,
+ ACPI_ACTIVE_HIGH);
+#endif
+ }
+
+ if (irq <= 0) {
+ pr_err("Failed to create IRQ mapping!\n");
+ return -ENODATA;
+ }
+
+ return irq;
+}
+
+static void ffa_sched_recv_irq_unmap(void)
+{
+ if (drv_info->sched_recv_irq) {
+ irq_dispose_mapping(drv_info->sched_recv_irq);
+ drv_info->sched_recv_irq = 0;
+ }
+}
+
+static int ffa_cpuhp_pcpu_irq_enable(unsigned int cpu)
+{
+ enable_percpu_irq(drv_info->sched_recv_irq, IRQ_TYPE_NONE);
+ return 0;
+}
+
+static int ffa_cpuhp_pcpu_irq_disable(unsigned int cpu)
+{
+ disable_percpu_irq(drv_info->sched_recv_irq);
+ return 0;
+}
+
+static void ffa_uninit_pcpu_irq(void)
+{
+ if (drv_info->cpuhp_state) {
+ cpuhp_remove_state(drv_info->cpuhp_state);
+ drv_info->cpuhp_state = 0;
+ }
+
+ if (drv_info->notif_pcpu_wq) {
+ destroy_workqueue(drv_info->notif_pcpu_wq);
+ drv_info->notif_pcpu_wq = NULL;
+ }
+
+ if (drv_info->sched_recv_irq)
+ free_percpu_irq(drv_info->sched_recv_irq, drv_info->irq_pcpu);
+
+ if (drv_info->irq_pcpu) {
+ free_percpu(drv_info->irq_pcpu);
+ drv_info->irq_pcpu = NULL;
+ }
+}
+
+static int ffa_init_pcpu_irq(unsigned int irq)
+{
+ struct ffa_pcpu_irq __percpu *irq_pcpu;
+ int ret, cpu;
+
+ irq_pcpu = alloc_percpu(struct ffa_pcpu_irq);
+ if (!irq_pcpu)
+ return -ENOMEM;
+
+ for_each_present_cpu(cpu)
+ per_cpu_ptr(irq_pcpu, cpu)->info = drv_info;
+
+ drv_info->irq_pcpu = irq_pcpu;
+
+ ret = request_percpu_irq(irq, irq_handler, "ARM-FFA", irq_pcpu);
+ if (ret) {
+ pr_err("Error registering notification IRQ %d: %d\n", irq, ret);
+ return ret;
+ }
+
+ INIT_WORK(&drv_info->irq_work, ffa_sched_recv_irq_work_fn);
+ INIT_WORK(&drv_info->notif_pcpu_work, notif_pcpu_irq_work_fn);
+ drv_info->notif_pcpu_wq = create_workqueue("ffa_pcpu_irq_notification");
+ if (!drv_info->notif_pcpu_wq)
+ return -EINVAL;
+
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ffa/pcpu-irq:starting",
+ ffa_cpuhp_pcpu_irq_enable,
+ ffa_cpuhp_pcpu_irq_disable);
+
+ if (ret < 0)
+ return ret;
+
+ drv_info->cpuhp_state = ret;
+ return 0;
+}
+
+static void ffa_notifications_cleanup(void)
+{
+ ffa_uninit_pcpu_irq();
+ ffa_sched_recv_irq_unmap();
+
+ if (drv_info->bitmap_created) {
+ ffa_notification_bitmap_destroy();
+ drv_info->bitmap_created = false;
+ }
+ drv_info->notif_enabled = false;
+}
+
+static void ffa_notifications_setup(void)
+{
+ int ret, irq;
+
+ ret = ffa_features(FFA_NOTIFICATION_BITMAP_CREATE, 0, NULL, NULL);
+ if (ret) {
+ pr_info("Notifications not supported, continuing with it ..\n");
+ return;
+ }
+
+ ret = ffa_notification_bitmap_create();
+ if (ret) {
+ pr_info("Notification bitmap create error %d\n", ret);
+ return;
+ }
+ drv_info->bitmap_created = true;
+
+ irq = ffa_sched_recv_irq_map();
+ if (irq <= 0) {
+ ret = irq;
+ goto cleanup;
+ }
+
+ drv_info->sched_recv_irq = irq;
+
+ ret = ffa_init_pcpu_irq(irq);
+ if (ret)
+ goto cleanup;
+
+ hash_init(drv_info->notifier_hash);
+ mutex_init(&drv_info->notify_lock);
+
+ drv_info->notif_enabled = true;
+ return;
+cleanup:
+ pr_info("Notification setup failed %d, not enabled\n", ret);
+ ffa_notifications_cleanup();
}
static int __init ffa_init(void)
@@ -762,9 +1504,16 @@ static int __init ffa_init(void)
mutex_init(&drv_info->rx_lock);
mutex_init(&drv_info->tx_lock);
+ ffa_set_up_mem_ops_native_flag();
+
+ ffa_notifications_setup();
+
ffa_setup_partitions();
- ffa_set_up_mem_ops_native_flag();
+ ret = ffa_sched_recv_cb_update(drv_info->vm_id, ffa_self_notif_handle,
+ drv_info, true);
+ if (ret)
+ pr_info("Failed to register driver sched callback %d\n", ret);
return 0;
free_pages:
@@ -781,9 +1530,12 @@ subsys_initcall(ffa_init);
static void __exit ffa_exit(void)
{
+ ffa_notifications_cleanup();
+ ffa_partitions_cleanup();
ffa_rxtx_unmap(drv_info->vm_id);
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE);
+ xa_destroy(&drv_info->partition_info);
kfree(drv_info);
arm_ffa_bus_exit();
}
diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/Kconfig
index ea0f5083ac47..706d1264d038 100644
--- a/drivers/firmware/arm_scmi/Kconfig
+++ b/drivers/firmware/arm_scmi/Kconfig
@@ -181,6 +181,18 @@ config ARM_SCMI_POWER_DOMAIN
will be called scmi_pm_domain. Note this may needed early in boot
before rootfs may be available.
+config ARM_SCMI_PERF_DOMAIN
+ tristate "SCMI performance domain driver"
+ depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+ default y
+ select PM_GENERIC_DOMAINS if PM
+ help
+ This enables support for the SCMI performance domains which can be
+ enabled or disabled via the SCP firmware.
+
+ This driver can also be built as a module. If so, the module will be
+ called scmi_perf_domain.
+
config ARM_SCMI_POWER_CONTROL
tristate "SCMI system power control driver"
depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index b31d78fa66cc..a7bc4796519c 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -16,7 +16,6 @@ scmi-module-objs := $(scmi-driver-y) $(scmi-protocols-y) $(scmi-transport-y)
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-core.o
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o
-obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
obj-$(CONFIG_ARM_SCMI_POWER_CONTROL) += scmi_power_control.o
ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index 96060bf90a24..42b81c181d68 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -21,6 +21,17 @@ enum scmi_clock_protocol_cmd {
CLOCK_NAME_GET = 0x8,
CLOCK_RATE_NOTIFY = 0x9,
CLOCK_RATE_CHANGE_REQUESTED_NOTIFY = 0xA,
+ CLOCK_CONFIG_GET = 0xB,
+ CLOCK_POSSIBLE_PARENTS_GET = 0xC,
+ CLOCK_PARENT_SET = 0xD,
+ CLOCK_PARENT_GET = 0xE,
+};
+
+enum clk_state {
+ CLK_STATE_DISABLE,
+ CLK_STATE_ENABLE,
+ CLK_STATE_RESERVED,
+ CLK_STATE_UNCHANGED,
};
struct scmi_msg_resp_clock_protocol_attributes {
@@ -31,17 +42,57 @@ struct scmi_msg_resp_clock_protocol_attributes {
struct scmi_msg_resp_clock_attributes {
__le32 attributes;
-#define CLOCK_ENABLE BIT(0)
#define SUPPORTS_RATE_CHANGED_NOTIF(x) ((x) & BIT(31))
#define SUPPORTS_RATE_CHANGE_REQUESTED_NOTIF(x) ((x) & BIT(30))
#define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(29))
+#define SUPPORTS_PARENT_CLOCK(x) ((x) & BIT(28))
u8 name[SCMI_SHORT_NAME_MAX_SIZE];
__le32 clock_enable_latency;
};
-struct scmi_clock_set_config {
+struct scmi_msg_clock_possible_parents {
+ __le32 id;
+ __le32 skip_parents;
+};
+
+struct scmi_msg_resp_clock_possible_parents {
+ __le32 num_parent_flags;
+#define NUM_PARENTS_RETURNED(x) ((x) & 0xff)
+#define NUM_PARENTS_REMAINING(x) ((x) >> 24)
+ __le32 possible_parents[];
+};
+
+struct scmi_msg_clock_set_parent {
+ __le32 id;
+ __le32 parent_id;
+};
+
+struct scmi_msg_clock_config_set {
+ __le32 id;
+ __le32 attributes;
+};
+
+/* Valid only from SCMI clock v2.1 */
+struct scmi_msg_clock_config_set_v2 {
__le32 id;
__le32 attributes;
+#define NULL_OEM_TYPE 0
+#define REGMASK_OEM_TYPE_SET GENMASK(23, 16)
+#define REGMASK_CLK_STATE GENMASK(1, 0)
+ __le32 oem_config_val;
+};
+
+struct scmi_msg_clock_config_get {
+ __le32 id;
+ __le32 flags;
+#define REGMASK_OEM_TYPE_GET GENMASK(7, 0)
+};
+
+struct scmi_msg_resp_clock_config_get {
+ __le32 attributes;
+ __le32 config;
+#define IS_CLK_ENABLED(x) le32_get_bits((x), BIT(0))
+ __le32 oem_config_val;
};
struct scmi_msg_clock_describe_rates {
@@ -100,6 +151,12 @@ struct clock_info {
int max_async_req;
atomic_t cur_async_req;
struct scmi_clock_info *clk;
+ int (*clock_config_set)(const struct scmi_protocol_handle *ph,
+ u32 clk_id, enum clk_state state,
+ u8 oem_type, u32 oem_val, bool atomic);
+ int (*clock_config_get)(const struct scmi_protocol_handle *ph,
+ u32 clk_id, u8 oem_type, u32 *attributes,
+ bool *enabled, u32 *oem_val, bool atomic);
};
static enum scmi_clock_protocol_cmd evt_2_cmd[] = {
@@ -132,6 +189,98 @@ scmi_clock_protocol_attributes_get(const struct scmi_protocol_handle *ph,
return ret;
}
+struct scmi_clk_ipriv {
+ struct device *dev;
+ u32 clk_id;
+ struct scmi_clock_info *clk;
+};
+
+static void iter_clk_possible_parents_prepare_message(void *message, unsigned int desc_index,
+ const void *priv)
+{
+ struct scmi_msg_clock_possible_parents *msg = message;
+ const struct scmi_clk_ipriv *p = priv;
+
+ msg->id = cpu_to_le32(p->clk_id);
+ /* Set the number of OPPs to be skipped/already read */
+ msg->skip_parents = cpu_to_le32(desc_index);
+}
+
+static int iter_clk_possible_parents_update_state(struct scmi_iterator_state *st,
+ const void *response, void *priv)
+{
+ const struct scmi_msg_resp_clock_possible_parents *r = response;
+ struct scmi_clk_ipriv *p = priv;
+ struct device *dev = ((struct scmi_clk_ipriv *)p)->dev;
+ u32 flags;
+
+ flags = le32_to_cpu(r->num_parent_flags);
+ st->num_returned = NUM_PARENTS_RETURNED(flags);
+ st->num_remaining = NUM_PARENTS_REMAINING(flags);
+
+ /*
+ * num parents is not declared previously anywhere so we
+ * assume it's returned+remaining on first call.
+ */
+ if (!st->max_resources) {
+ p->clk->num_parents = st->num_returned + st->num_remaining;
+ p->clk->parents = devm_kcalloc(dev, p->clk->num_parents,
+ sizeof(*p->clk->parents),
+ GFP_KERNEL);
+ if (!p->clk->parents) {
+ p->clk->num_parents = 0;
+ return -ENOMEM;
+ }
+ st->max_resources = st->num_returned + st->num_remaining;
+ }
+
+ return 0;
+}
+
+static int iter_clk_possible_parents_process_response(const struct scmi_protocol_handle *ph,
+ const void *response,
+ struct scmi_iterator_state *st,
+ void *priv)
+{
+ const struct scmi_msg_resp_clock_possible_parents *r = response;
+ struct scmi_clk_ipriv *p = priv;
+
+ u32 *parent = &p->clk->parents[st->desc_index + st->loop_idx];
+
+ *parent = le32_to_cpu(r->possible_parents[st->loop_idx]);
+
+ return 0;
+}
+
+static int scmi_clock_possible_parents(const struct scmi_protocol_handle *ph, u32 clk_id,
+ struct scmi_clock_info *clk)
+{
+ struct scmi_iterator_ops ops = {
+ .prepare_message = iter_clk_possible_parents_prepare_message,
+ .update_state = iter_clk_possible_parents_update_state,
+ .process_response = iter_clk_possible_parents_process_response,
+ };
+
+ struct scmi_clk_ipriv ppriv = {
+ .clk_id = clk_id,
+ .clk = clk,
+ .dev = ph->dev,
+ };
+ void *iter;
+ int ret;
+
+ iter = ph->hops->iter_response_init(ph, &ops, 0,
+ CLOCK_POSSIBLE_PARENTS_GET,
+ sizeof(struct scmi_msg_clock_possible_parents),
+ &ppriv);
+ if (IS_ERR(iter))
+ return PTR_ERR(iter);
+
+ ret = ph->hops->iter_response_run(iter);
+
+ return ret;
+}
+
static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
u32 clk_id, struct scmi_clock_info *clk,
u32 version)
@@ -176,6 +325,8 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
clk->rate_changed_notifications = true;
if (SUPPORTS_RATE_CHANGE_REQUESTED_NOTIF(attributes))
clk->rate_change_requested_notifications = true;
+ if (SUPPORTS_PARENT_CLOCK(attributes))
+ scmi_clock_possible_parents(ph, clk_id, clk);
}
return ret;
@@ -193,12 +344,6 @@ static int rate_cmp_func(const void *_r1, const void *_r2)
return 1;
}
-struct scmi_clk_ipriv {
- struct device *dev;
- u32 clk_id;
- struct scmi_clock_info *clk;
-};
-
static void iter_clk_describe_prepare_message(void *message,
const unsigned int desc_index,
const void *priv)
@@ -395,11 +540,105 @@ static int scmi_clock_rate_set(const struct scmi_protocol_handle *ph,
static int
scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id,
- u32 config, bool atomic)
+ enum clk_state state, u8 __unused0, u32 __unused1,
+ bool atomic)
+{
+ int ret;
+ struct scmi_xfer *t;
+ struct scmi_msg_clock_config_set *cfg;
+
+ if (state >= CLK_STATE_RESERVED)
+ return -EINVAL;
+
+ ret = ph->xops->xfer_get_init(ph, CLOCK_CONFIG_SET,
+ sizeof(*cfg), 0, &t);
+ if (ret)
+ return ret;
+
+ t->hdr.poll_completion = atomic;
+
+ cfg = t->tx.buf;
+ cfg->id = cpu_to_le32(clk_id);
+ cfg->attributes = cpu_to_le32(state);
+
+ ret = ph->xops->do_xfer(ph, t);
+
+ ph->xops->xfer_put(ph, t);
+ return ret;
+}
+
+static int
+scmi_clock_set_parent(const struct scmi_protocol_handle *ph, u32 clk_id,
+ u32 parent_id)
+{
+ int ret;
+ struct scmi_xfer *t;
+ struct scmi_msg_clock_set_parent *cfg;
+ struct clock_info *ci = ph->get_priv(ph);
+ struct scmi_clock_info *clk;
+
+ if (clk_id >= ci->num_clocks)
+ return -EINVAL;
+
+ clk = ci->clk + clk_id;
+
+ if (parent_id >= clk->num_parents)
+ return -EINVAL;
+
+ ret = ph->xops->xfer_get_init(ph, CLOCK_PARENT_SET,
+ sizeof(*cfg), 0, &t);
+ if (ret)
+ return ret;
+
+ t->hdr.poll_completion = false;
+
+ cfg = t->tx.buf;
+ cfg->id = cpu_to_le32(clk_id);
+ cfg->parent_id = cpu_to_le32(clk->parents[parent_id]);
+
+ ret = ph->xops->do_xfer(ph, t);
+
+ ph->xops->xfer_put(ph, t);
+
+ return ret;
+}
+
+static int
+scmi_clock_get_parent(const struct scmi_protocol_handle *ph, u32 clk_id,
+ u32 *parent_id)
{
int ret;
struct scmi_xfer *t;
- struct scmi_clock_set_config *cfg;
+
+ ret = ph->xops->xfer_get_init(ph, CLOCK_PARENT_GET,
+ sizeof(__le32), sizeof(u32), &t);
+ if (ret)
+ return ret;
+
+ put_unaligned_le32(clk_id, t->tx.buf);
+
+ ret = ph->xops->do_xfer(ph, t);
+ if (!ret)
+ *parent_id = get_unaligned_le32(t->rx.buf);
+
+ ph->xops->xfer_put(ph, t);
+ return ret;
+}
+
+/* For SCMI clock v2.1 and onwards */
+static int
+scmi_clock_config_set_v2(const struct scmi_protocol_handle *ph, u32 clk_id,
+ enum clk_state state, u8 oem_type, u32 oem_val,
+ bool atomic)
+{
+ int ret;
+ u32 attrs;
+ struct scmi_xfer *t;
+ struct scmi_msg_clock_config_set_v2 *cfg;
+
+ if (state == CLK_STATE_RESERVED ||
+ (!oem_type && state == CLK_STATE_UNCHANGED))
+ return -EINVAL;
ret = ph->xops->xfer_get_init(ph, CLOCK_CONFIG_SET,
sizeof(*cfg), 0, &t);
@@ -408,9 +647,16 @@ scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id,
t->hdr.poll_completion = atomic;
+ attrs = FIELD_PREP(REGMASK_OEM_TYPE_SET, oem_type) |
+ FIELD_PREP(REGMASK_CLK_STATE, state);
+
cfg = t->tx.buf;
cfg->id = cpu_to_le32(clk_id);
- cfg->attributes = cpu_to_le32(config);
+ cfg->attributes = cpu_to_le32(attrs);
+ /* Clear in any case */
+ cfg->oem_config_val = cpu_to_le32(0);
+ if (oem_type)
+ cfg->oem_config_val = cpu_to_le32(oem_val);
ret = ph->xops->do_xfer(ph, t);
@@ -418,26 +664,124 @@ scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id,
return ret;
}
-static int scmi_clock_enable(const struct scmi_protocol_handle *ph, u32 clk_id)
+static int scmi_clock_enable(const struct scmi_protocol_handle *ph, u32 clk_id,
+ bool atomic)
{
- return scmi_clock_config_set(ph, clk_id, CLOCK_ENABLE, false);
+ struct clock_info *ci = ph->get_priv(ph);
+
+ return ci->clock_config_set(ph, clk_id, CLK_STATE_ENABLE,
+ NULL_OEM_TYPE, 0, atomic);
}
-static int scmi_clock_disable(const struct scmi_protocol_handle *ph, u32 clk_id)
+static int scmi_clock_disable(const struct scmi_protocol_handle *ph, u32 clk_id,
+ bool atomic)
{
- return scmi_clock_config_set(ph, clk_id, 0, false);
+ struct clock_info *ci = ph->get_priv(ph);
+
+ return ci->clock_config_set(ph, clk_id, CLK_STATE_DISABLE,
+ NULL_OEM_TYPE, 0, atomic);
}
-static int scmi_clock_enable_atomic(const struct scmi_protocol_handle *ph,
- u32 clk_id)
+/* For SCMI clock v2.1 and onwards */
+static int
+scmi_clock_config_get_v2(const struct scmi_protocol_handle *ph, u32 clk_id,
+ u8 oem_type, u32 *attributes, bool *enabled,
+ u32 *oem_val, bool atomic)
{
- return scmi_clock_config_set(ph, clk_id, CLOCK_ENABLE, true);
+ int ret;
+ u32 flags;
+ struct scmi_xfer *t;
+ struct scmi_msg_clock_config_get *cfg;
+
+ ret = ph->xops->xfer_get_init(ph, CLOCK_CONFIG_GET,
+ sizeof(*cfg), 0, &t);
+ if (ret)
+ return ret;
+
+ t->hdr.poll_completion = atomic;
+
+ flags = FIELD_PREP(REGMASK_OEM_TYPE_GET, oem_type);
+
+ cfg = t->tx.buf;
+ cfg->id = cpu_to_le32(clk_id);
+ cfg->flags = cpu_to_le32(flags);
+
+ ret = ph->xops->do_xfer(ph, t);
+ if (!ret) {
+ struct scmi_msg_resp_clock_config_get *resp = t->rx.buf;
+
+ if (attributes)
+ *attributes = le32_to_cpu(resp->attributes);
+
+ if (enabled)
+ *enabled = IS_CLK_ENABLED(resp->config);
+
+ if (oem_val && oem_type)
+ *oem_val = le32_to_cpu(resp->oem_config_val);
+ }
+
+ ph->xops->xfer_put(ph, t);
+
+ return ret;
+}
+
+static int
+scmi_clock_config_get(const struct scmi_protocol_handle *ph, u32 clk_id,
+ u8 oem_type, u32 *attributes, bool *enabled,
+ u32 *oem_val, bool atomic)
+{
+ int ret;
+ struct scmi_xfer *t;
+ struct scmi_msg_resp_clock_attributes *resp;
+
+ if (!enabled)
+ return -EINVAL;
+
+ ret = ph->xops->xfer_get_init(ph, CLOCK_ATTRIBUTES,
+ sizeof(clk_id), sizeof(*resp), &t);
+ if (ret)
+ return ret;
+
+ t->hdr.poll_completion = atomic;
+ put_unaligned_le32(clk_id, t->tx.buf);
+ resp = t->rx.buf;
+
+ ret = ph->xops->do_xfer(ph, t);
+ if (!ret)
+ *enabled = IS_CLK_ENABLED(resp->attributes);
+
+ ph->xops->xfer_put(ph, t);
+
+ return ret;
}
-static int scmi_clock_disable_atomic(const struct scmi_protocol_handle *ph,
- u32 clk_id)
+static int scmi_clock_state_get(const struct scmi_protocol_handle *ph,
+ u32 clk_id, bool *enabled, bool atomic)
{
- return scmi_clock_config_set(ph, clk_id, 0, true);
+ struct clock_info *ci = ph->get_priv(ph);
+
+ return ci->clock_config_get(ph, clk_id, NULL_OEM_TYPE, NULL,
+ enabled, NULL, atomic);
+}
+
+static int scmi_clock_config_oem_set(const struct scmi_protocol_handle *ph,
+ u32 clk_id, u8 oem_type, u32 oem_val,
+ bool atomic)
+{
+ struct clock_info *ci = ph->get_priv(ph);
+
+ return ci->clock_config_set(ph, clk_id, CLK_STATE_UNCHANGED,
+ oem_type, oem_val, atomic);
+}
+
+static int scmi_clock_config_oem_get(const struct scmi_protocol_handle *ph,
+ u32 clk_id, u8 oem_type, u32 *oem_val,
+ u32 *attributes, bool atomic)
+{
+ struct clock_info *ci = ph->get_priv(ph);
+
+ return ci->clock_config_get(ph, clk_id, oem_type, attributes,
+ NULL, oem_val, atomic);
}
static int scmi_clock_count_get(const struct scmi_protocol_handle *ph)
@@ -470,8 +814,11 @@ static const struct scmi_clk_proto_ops clk_proto_ops = {
.rate_set = scmi_clock_rate_set,
.enable = scmi_clock_enable,
.disable = scmi_clock_disable,
- .enable_atomic = scmi_clock_enable_atomic,
- .disable_atomic = scmi_clock_disable_atomic,
+ .state_get = scmi_clock_state_get,
+ .config_oem_get = scmi_clock_config_oem_get,
+ .config_oem_set = scmi_clock_config_oem_set,
+ .parent_set = scmi_clock_set_parent,
+ .parent_get = scmi_clock_get_parent,
};
static int scmi_clk_rate_notify(const struct scmi_protocol_handle *ph,
@@ -604,6 +951,15 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
scmi_clock_describe_rates_get(ph, clkid, clk);
}
+ if (PROTOCOL_REV_MAJOR(version) >= 0x2 &&
+ PROTOCOL_REV_MINOR(version) >= 0x1) {
+ cinfo->clock_config_set = scmi_clock_config_set_v2;
+ cinfo->clock_config_get = scmi_clock_config_get_v2;
+ } else {
+ cinfo->clock_config_set = scmi_clock_config_set;
+ cinfo->clock_config_get = scmi_clock_config_get;
+ }
+
cinfo->version = version;
return ph->set_priv(ph, cinfo);
}
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 87383c05424b..09371f40d61f 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -2915,6 +2915,7 @@ static const struct of_device_id scmi_of_match[] = {
#ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC
{ .compatible = "arm,scmi-smc", .data = &scmi_smc_desc},
{ .compatible = "arm,scmi-smc-param", .data = &scmi_smc_desc},
+ { .compatible = "qcom,scmi-smc", .data = &scmi_smc_desc},
#endif
#ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO
{ .compatible = "arm,scmi-virtio", .data = &scmi_virtio_desc},
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 30dedd6ebfde..e11555de99ab 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -145,7 +145,6 @@ struct scmi_msg_resp_perf_describe_levels_v4 {
struct perf_dom_info {
u32 id;
bool set_limits;
- bool set_perf;
bool perf_limit_notify;
bool perf_level_notify;
bool perf_fastchannels;
@@ -153,8 +152,8 @@ struct perf_dom_info {
u32 opp_count;
u32 sustained_freq_khz;
u32 sustained_perf_level;
- u32 mult_factor;
- char name[SCMI_MAX_STR_SIZE];
+ unsigned long mult_factor;
+ struct scmi_perf_domain_info info;
struct scmi_opp opp[MAX_OPPS];
struct scmi_fc_info *fc_info;
struct xarray opps_by_idx;
@@ -257,7 +256,7 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
flags = le32_to_cpu(attr->flags);
dom_info->set_limits = SUPPORTS_SET_LIMITS(flags);
- dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags);
+ dom_info->info.set_perf = SUPPORTS_SET_PERF_LVL(flags);
dom_info->perf_limit_notify = SUPPORTS_PERF_LIMIT_NOTIFY(flags);
dom_info->perf_level_notify = SUPPORTS_PERF_LEVEL_NOTIFY(flags);
dom_info->perf_fastchannels = SUPPORTS_PERF_FASTCHANNELS(flags);
@@ -269,14 +268,16 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
dom_info->sustained_perf_level =
le32_to_cpu(attr->sustained_perf_level);
if (!dom_info->sustained_freq_khz ||
- !dom_info->sustained_perf_level)
+ !dom_info->sustained_perf_level ||
+ dom_info->level_indexing_mode)
/* CPUFreq converts to kHz, hence default 1000 */
dom_info->mult_factor = 1000;
else
dom_info->mult_factor =
- (dom_info->sustained_freq_khz * 1000) /
- dom_info->sustained_perf_level;
- strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
+ (dom_info->sustained_freq_khz * 1000UL)
+ / dom_info->sustained_perf_level;
+ strscpy(dom_info->info.name, attr->name,
+ SCMI_SHORT_NAME_MAX_SIZE);
}
ph->xops->xfer_put(ph, t);
@@ -288,7 +289,7 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 &&
SUPPORTS_EXTENDED_NAMES(flags))
ph->hops->extended_name_get(ph, PERF_DOMAIN_NAME_GET,
- dom_info->id, dom_info->name,
+ dom_info->id, dom_info->info.name,
SCMI_MAX_STR_SIZE);
if (dom_info->level_indexing_mode) {
@@ -423,6 +424,36 @@ scmi_perf_describe_levels_get(const struct scmi_protocol_handle *ph,
return ret;
}
+static int scmi_perf_num_domains_get(const struct scmi_protocol_handle *ph)
+{
+ struct scmi_perf_info *pi = ph->get_priv(ph);
+
+ return pi->num_domains;
+}
+
+static inline struct perf_dom_info *
+scmi_perf_domain_lookup(const struct scmi_protocol_handle *ph, u32 domain)
+{
+ struct scmi_perf_info *pi = ph->get_priv(ph);
+
+ if (domain >= pi->num_domains)
+ return ERR_PTR(-EINVAL);
+
+ return pi->dom_info + domain;
+}
+
+static const struct scmi_perf_domain_info *
+scmi_perf_info_get(const struct scmi_protocol_handle *ph, u32 domain)
+{
+ struct perf_dom_info *dom;
+
+ dom = scmi_perf_domain_lookup(ph, domain);
+ if (IS_ERR(dom))
+ return ERR_PTR(-EINVAL);
+
+ return &dom->info;
+}
+
static int scmi_perf_msg_limits_set(const struct scmi_protocol_handle *ph,
u32 domain, u32 max_perf, u32 min_perf)
{
@@ -446,17 +477,6 @@ static int scmi_perf_msg_limits_set(const struct scmi_protocol_handle *ph,
return ret;
}
-static inline struct perf_dom_info *
-scmi_perf_domain_lookup(const struct scmi_protocol_handle *ph, u32 domain)
-{
- struct scmi_perf_info *pi = ph->get_priv(ph);
-
- if (domain >= pi->num_domains)
- return ERR_PTR(-EINVAL);
-
- return pi->dom_info + domain;
-}
-
static int __scmi_perf_limits_set(const struct scmi_protocol_handle *ph,
struct perf_dom_info *dom, u32 max_perf,
u32 min_perf)
@@ -763,71 +783,46 @@ static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph,
*p_fc = fc;
}
-/* Device specific ops */
-static int scmi_dev_domain_id(struct device *dev)
-{
- struct of_phandle_args clkspec;
-
- if (of_parse_phandle_with_args(dev->of_node, "clocks", "#clock-cells",
- 0, &clkspec))
- return -EINVAL;
-
- return clkspec.args[0];
-}
-
static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
- struct device *dev)
+ struct device *dev, u32 domain)
{
- int idx, ret, domain;
+ int idx, ret;
unsigned long freq;
- struct scmi_opp *opp;
+ struct dev_pm_opp_data data = {};
struct perf_dom_info *dom;
- domain = scmi_dev_domain_id(dev);
- if (domain < 0)
- return -EINVAL;
-
dom = scmi_perf_domain_lookup(ph, domain);
if (IS_ERR(dom))
return PTR_ERR(dom);
- for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) {
+ for (idx = 0; idx < dom->opp_count; idx++) {
if (!dom->level_indexing_mode)
- freq = opp->perf * dom->mult_factor;
+ freq = dom->opp[idx].perf * dom->mult_factor;
else
- freq = opp->indicative_freq * 1000;
+ freq = dom->opp[idx].indicative_freq * dom->mult_factor;
+
+ data.level = dom->opp[idx].perf;
+ data.freq = freq;
- ret = dev_pm_opp_add(dev, freq, 0);
+ ret = dev_pm_opp_add_dynamic(dev, &data);
if (ret) {
dev_warn(dev, "failed to add opp %luHz\n", freq);
-
- while (idx-- > 0) {
- if (!dom->level_indexing_mode)
- freq = (--opp)->perf * dom->mult_factor;
- else
- freq = (--opp)->indicative_freq * 1000;
- dev_pm_opp_remove(dev, freq);
- }
+ dev_pm_opp_remove_all_dynamic(dev);
return ret;
}
dev_dbg(dev, "[%d][%s]:: Registered OPP[%d] %lu\n",
- domain, dom->name, idx, freq);
+ domain, dom->info.name, idx, freq);
}
return 0;
}
static int
scmi_dvfs_transition_latency_get(const struct scmi_protocol_handle *ph,
- struct device *dev)
+ u32 domain)
{
- int domain;
struct perf_dom_info *dom;
- domain = scmi_dev_domain_id(dev);
- if (domain < 0)
- return -EINVAL;
-
dom = scmi_perf_domain_lookup(ph, domain);
if (IS_ERR(dom))
return PTR_ERR(dom);
@@ -851,7 +846,8 @@ static int scmi_dvfs_freq_set(const struct scmi_protocol_handle *ph, u32 domain,
} else {
struct scmi_opp *opp;
- opp = LOOKUP_BY_FREQ(dom->opps_by_freq, freq / 1000);
+ opp = LOOKUP_BY_FREQ(dom->opps_by_freq,
+ freq / dom->mult_factor);
if (!opp)
return -EIO;
@@ -885,7 +881,7 @@ static int scmi_dvfs_freq_get(const struct scmi_protocol_handle *ph, u32 domain,
if (!opp)
return -EIO;
- *freq = opp->indicative_freq * 1000;
+ *freq = opp->indicative_freq * dom->mult_factor;
}
return ret;
@@ -908,7 +904,7 @@ static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph,
if (!dom->level_indexing_mode)
opp_freq = opp->perf * dom->mult_factor;
else
- opp_freq = opp->indicative_freq * 1000;
+ opp_freq = opp->indicative_freq * dom->mult_factor;
if (opp_freq < *freq)
continue;
@@ -923,15 +919,10 @@ static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph,
}
static bool scmi_fast_switch_possible(const struct scmi_protocol_handle *ph,
- struct device *dev)
+ u32 domain)
{
- int domain;
struct perf_dom_info *dom;
- domain = scmi_dev_domain_id(dev);
- if (domain < 0)
- return false;
-
dom = scmi_perf_domain_lookup(ph, domain);
if (IS_ERR(dom))
return false;
@@ -948,11 +939,12 @@ scmi_power_scale_get(const struct scmi_protocol_handle *ph)
}
static const struct scmi_perf_proto_ops perf_proto_ops = {
+ .num_domains_get = scmi_perf_num_domains_get,
+ .info_get = scmi_perf_info_get,
.limits_set = scmi_perf_limits_set,
.limits_get = scmi_perf_limits_get,
.level_set = scmi_perf_level_set,
.level_get = scmi_perf_level_get,
- .device_domain_id = scmi_dev_domain_id,
.transition_latency_get = scmi_dvfs_transition_latency_get,
.device_opps_add = scmi_dvfs_device_opps_add,
.freq_set = scmi_dvfs_freq_set,
diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c
index 244929cb4f3e..cb5617443a14 100644
--- a/drivers/firmware/arm_scmi/powercap.c
+++ b/drivers/firmware/arm_scmi/powercap.c
@@ -360,8 +360,8 @@ static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph,
msg = t->tx.buf;
msg->domain = cpu_to_le32(pc->id);
msg->flags =
- cpu_to_le32(FIELD_PREP(CAP_SET_ASYNC, !!pc->async_powercap_cap_set) |
- FIELD_PREP(CAP_SET_IGNORE_DRESP, !!ignore_dresp));
+ cpu_to_le32(FIELD_PREP(CAP_SET_ASYNC, pc->async_powercap_cap_set) |
+ FIELD_PREP(CAP_SET_IGNORE_DRESP, ignore_dresp));
msg->value = cpu_to_le32(power_cap);
if (!pc->async_powercap_cap_set || ignore_dresp) {
diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c
index c193516a254d..7611e9665038 100644
--- a/drivers/firmware/arm_scmi/smc.c
+++ b/drivers/firmware/arm_scmi/smc.c
@@ -15,6 +15,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/limits.h>
#include <linux/processor.h>
#include <linux/slab.h>
@@ -50,6 +51,8 @@
* @func_id: smc/hvc call function id
* @param_page: 4K page number of the shmem channel
* @param_offset: Offset within the 4K page of the shmem channel
+ * @cap_id: smc/hvc doorbell's capability id to be used on Qualcomm virtual
+ * platforms
*/
struct scmi_smc {
@@ -60,9 +63,10 @@ struct scmi_smc {
struct mutex shmem_lock;
#define INFLIGHT_NONE MSG_TOKEN_MAX
atomic_t inflight;
- u32 func_id;
- u32 param_page;
- u32 param_offset;
+ unsigned long func_id;
+ unsigned long param_page;
+ unsigned long param_offset;
+ unsigned long cap_id;
};
static irqreturn_t smc_msg_done_isr(int irq, void *data)
@@ -124,6 +128,7 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
bool tx)
{
struct device *cdev = cinfo->dev;
+ unsigned long cap_id = ULONG_MAX;
struct scmi_smc *scmi_info;
resource_size_t size;
struct resource res;
@@ -162,6 +167,18 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
if (ret < 0)
return ret;
+ if (of_device_is_compatible(dev->of_node, "qcom,scmi-smc")) {
+ void __iomem *ptr = (void __iomem *)scmi_info->shmem + size - 8;
+ /* The capability-id is kept in last 8 bytes of shmem.
+ * +-------+ <-- 0
+ * | shmem |
+ * +-------+ <-- size - 8
+ * | capId |
+ * +-------+ <-- size
+ */
+ memcpy_fromio(&cap_id, ptr, sizeof(cap_id));
+ }
+
if (of_device_is_compatible(dev->of_node, "arm,scmi-smc-param")) {
scmi_info->param_page = SHMEM_PAGE(res.start);
scmi_info->param_offset = SHMEM_OFFSET(res.start);
@@ -184,6 +201,7 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
}
scmi_info->func_id = func_id;
+ scmi_info->cap_id = cap_id;
scmi_info->cinfo = cinfo;
smc_channel_lock_init(scmi_info);
cinfo->transport_info = scmi_info;
@@ -211,8 +229,6 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
{
struct scmi_smc *scmi_info = cinfo->transport_info;
struct arm_smccc_res res;
- unsigned long page = scmi_info->param_page;
- unsigned long offset = scmi_info->param_offset;
/*
* Channel will be released only once response has been
@@ -222,8 +238,13 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
shmem_tx_prepare(scmi_info->shmem, xfer, cinfo);
- arm_smccc_1_1_invoke(scmi_info->func_id, page, offset, 0, 0, 0, 0, 0,
- &res);
+ if (scmi_info->cap_id != ULONG_MAX)
+ arm_smccc_1_1_invoke(scmi_info->func_id, scmi_info->cap_id, 0,
+ 0, 0, 0, 0, 0, &res);
+ else
+ arm_smccc_1_1_invoke(scmi_info->func_id, scmi_info->param_page,
+ scmi_info->param_offset, 0, 0, 0, 0, 0,
+ &res);
/* Only SMCCC_RET_NOT_SUPPORTED is valid error code */
if (res.a0) {
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 435d0e2658a4..3f123f592cb4 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -26,9 +26,12 @@
#include <linux/list.h>
#include <linux/mailbox_client.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
+#include <linux/platform_device.h>
#include <linux/printk.h>
+#include <linux/property.h>
#include <linux/pm_opp.h>
#include <linux/scpi_protocol.h>
#include <linux/slab.h>
@@ -894,11 +897,6 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
return 0;
}
-static const struct of_device_id legacy_scpi_of_match[] = {
- {.compatible = "arm,scpi-pre-1.0"},
- {},
-};
-
static const struct of_device_id shmem_of_match[] __maybe_unused = {
{ .compatible = "amlogic,meson-gxbb-scp-shmem", },
{ .compatible = "amlogic,meson-axg-scp-shmem", },
@@ -919,8 +917,7 @@ static int scpi_probe(struct platform_device *pdev)
if (!scpi_drvinfo)
return -ENOMEM;
- if (of_match_device(legacy_scpi_of_match, &pdev->dev))
- scpi_drvinfo->is_legacy = true;
+ scpi_drvinfo->is_legacy = !!device_get_match_data(dev);
count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
if (count < 0) {
@@ -1038,7 +1035,7 @@ static int scpi_probe(struct platform_device *pdev)
static const struct of_device_id scpi_of_match[] = {
{.compatible = "arm,scpi"},
- {.compatible = "arm,scpi-pre-1.0"},
+ {.compatible = "arm,scpi-pre-1.0", .data = (void *)1UL },
{},
};
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 231f1c70d1db..cb374b2da9b7 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -4,7 +4,7 @@ menu "EFI (Extensible Firmware Interface) Support"
config EFI_ESRT
bool
- depends on EFI && !IA64
+ depends on EFI
default y
config EFI_VARS_PSTORE
@@ -123,7 +123,7 @@ config EFI_BOOTLOADER_CONTROL
config EFI_CAPSULE_LOADER
tristate "EFI capsule loader"
- depends on EFI && !IA64
+ depends on EFI
help
This option exposes a loader interface "/dev/efi_capsule_loader" for
users to load EFI capsules. This driver requires working runtime
@@ -224,7 +224,7 @@ config EFI_DISABLE_PCI_DMA
config EFI_EARLYCON
def_bool y
- depends on SERIAL_EARLYCON && !ARM && !IA64
+ depends on SERIAL_EARLYCON && !ARM
select FONT_SUPPORT
select ARCH_USE_MEMREMAP_PROT
diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c
index ef0820f1a924..d4987d013080 100644
--- a/drivers/firmware/efi/efi-init.c
+++ b/drivers/firmware/efi/efi-init.c
@@ -55,6 +55,15 @@ static phys_addr_t __init efi_to_phys(unsigned long addr)
extern __weak const efi_config_table_type_t efi_arch_tables[];
+/*
+ * x86 defines its own screen_info and uses it even without EFI,
+ * everything else can get it from here.
+ */
+#if !defined(CONFIG_X86) && (defined(CONFIG_SYSFB) || defined(CONFIG_EFI_EARLYCON))
+struct screen_info screen_info __section(".data");
+EXPORT_SYMBOL_GPL(screen_info);
+#endif
+
static void __init init_screen_info(void)
{
struct screen_info *si;
@@ -240,5 +249,8 @@ void __init efi_init(void)
memblock_reserve(data.phys_map & PAGE_MASK,
PAGE_ALIGN(data.size + (data.phys_map & ~PAGE_MASK)));
- init_screen_info();
+ if (IS_ENABLED(CONFIG_X86) ||
+ IS_ENABLED(CONFIG_SYSFB) ||
+ IS_ENABLED(CONFIG_EFI_EARLYCON))
+ init_screen_info();
}
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index ce20a60676f0..9d3910d1abe1 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -147,7 +147,7 @@ static ssize_t systab_show(struct kobject *kobj,
if (efi.smbios != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
- if (IS_ENABLED(CONFIG_IA64) || IS_ENABLED(CONFIG_X86))
+ if (IS_ENABLED(CONFIG_X86))
str = efi_systab_show_arch(str);
return str - buf;
@@ -273,9 +273,13 @@ static __init int efivar_ssdt_load(void)
if (status == EFI_NOT_FOUND) {
break;
} else if (status == EFI_BUFFER_TOO_SMALL) {
- name = krealloc(name, name_size, GFP_KERNEL);
- if (!name)
+ efi_char16_t *name_tmp =
+ krealloc(name, name_size, GFP_KERNEL);
+ if (!name_tmp) {
+ kfree(name);
return -ENOMEM;
+ }
+ name = name_tmp;
continue;
}
@@ -803,7 +807,6 @@ int __init efi_systab_check_header(const efi_table_hdr_t *systab_hdr)
return 0;
}
-#ifndef CONFIG_IA64
static const efi_char16_t *__init map_fw_vendor(unsigned long fw_vendor,
size_t size)
{
@@ -819,10 +822,6 @@ static void __init unmap_fw_vendor(const void *fw_vendor, size_t size)
{
early_memunmap((void *)fw_vendor, size);
}
-#else
-#define map_fw_vendor(p, s) __va(p)
-#define unmap_fw_vendor(v, s)
-#endif
void __init efi_systab_report_header(const efi_table_hdr_t *systab_hdr,
unsigned long fw_vendor)
@@ -926,11 +925,6 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,
}
/*
- * IA64 has a funky EFI memory map that doesn't work the same way as
- * other architectures.
- */
-#ifndef CONFIG_IA64
-/*
* efi_mem_attributes - lookup memmap attributes for physical address
* @phys_addr: the physical address to lookup
*
@@ -977,7 +971,6 @@ int efi_mem_type(unsigned long phys_addr)
}
return -EINVAL;
}
-#endif
int efi_status_to_err(efi_status_t status)
{
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index a1157c2a7170..06964a3c130f 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -28,7 +28,7 @@ cflags-$(CONFIG_ARM) += -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \
-DEFI_HAVE_MEMCHR -DEFI_HAVE_STRRCHR \
-DEFI_HAVE_STRCMP -fno-builtin -fpic \
$(call cc-option,-mno-single-pic-base)
-cflags-$(CONFIG_RISCV) += -fpic
+cflags-$(CONFIG_RISCV) += -fpic -DNO_ALTERNATIVE
cflags-$(CONFIG_LOONGARCH) += -fpie
cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt
@@ -108,13 +108,6 @@ lib-y := $(patsubst %.o,%.stub.o,$(lib-y))
# https://bugs.llvm.org/show_bug.cgi?id=46480
STUBCOPY_FLAGS-y += --remove-section=.note.gnu.property
-#
-# For x86, bootloaders like systemd-boot or grub-efi do not zero-initialize the
-# .bss section, so the .bss section of the EFI stub needs to be included in the
-# .data section of the compressed kernel to ensure initialization. Rename the
-# .bss section here so it's easy to pick out in the linker script.
-#
-STUBCOPY_FLAGS-$(CONFIG_X86) += --rename-section .bss=.bss.efistub,load,alloc
STUBCOPY_RELOC-$(CONFIG_X86_32) := R_386_32
STUBCOPY_RELOC-$(CONFIG_X86_64) := R_X86_64_64
diff --git a/drivers/firmware/efi/libstub/efi-stub-entry.c b/drivers/firmware/efi/libstub/efi-stub-entry.c
index 2f1902e5d407..a6c049835190 100644
--- a/drivers/firmware/efi/libstub/efi-stub-entry.c
+++ b/drivers/firmware/efi/libstub/efi-stub-entry.c
@@ -13,7 +13,13 @@ struct screen_info *alloc_screen_info(void)
{
if (IS_ENABLED(CONFIG_ARM))
return __alloc_screen_info();
- return (void *)&screen_info + screen_info_offset;
+
+ if (IS_ENABLED(CONFIG_X86) ||
+ IS_ENABLED(CONFIG_EFI_EARLYCON) ||
+ IS_ENABLED(CONFIG_SYSFB))
+ return (void *)&screen_info + screen_info_offset;
+
+ return NULL;
}
/*
diff --git a/drivers/firmware/efi/libstub/loongarch-stub.c b/drivers/firmware/efi/libstub/loongarch-stub.c
index 72c71ae201f0..d6ec5d4b8dbe 100644
--- a/drivers/firmware/efi/libstub/loongarch-stub.c
+++ b/drivers/firmware/efi/libstub/loongarch-stub.c
@@ -35,9 +35,9 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
return status;
}
-unsigned long kernel_entry_address(void)
+unsigned long kernel_entry_address(unsigned long kernel_addr)
{
unsigned long base = (unsigned long)&kernel_offset - kernel_offset;
- return (unsigned long)&kernel_entry - base + VMLINUX_LOAD_ADDRESS;
+ return (unsigned long)&kernel_entry - base + kernel_addr;
}
diff --git a/drivers/firmware/efi/libstub/loongarch.c b/drivers/firmware/efi/libstub/loongarch.c
index 807cba2693fc..0e0aa6cda73f 100644
--- a/drivers/firmware/efi/libstub/loongarch.c
+++ b/drivers/firmware/efi/libstub/loongarch.c
@@ -37,9 +37,9 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
return EFI_SUCCESS;
}
-unsigned long __weak kernel_entry_address(void)
+unsigned long __weak kernel_entry_address(unsigned long kernel_addr)
{
- return *(unsigned long *)(PHYSADDR(VMLINUX_LOAD_ADDRESS) + 8);
+ return *(unsigned long *)(kernel_addr + 8) - VMLINUX_LOAD_ADDRESS + kernel_addr;
}
efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
@@ -73,7 +73,7 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0);
csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);
- real_kernel_entry = (void *)kernel_entry_address();
+ real_kernel_entry = (void *)kernel_entry_address(kernel_addr);
real_kernel_entry(true, (unsigned long)cmdline_ptr,
(unsigned long)efi_system_table);
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index 2fee52ed335d..da9b7b8d0716 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -307,17 +307,20 @@ static void setup_unaccepted_memory(void)
efi_err("Memory acceptance protocol failed\n");
}
+static efi_char16_t *efistub_fw_vendor(void)
+{
+ unsigned long vendor = efi_table_attr(efi_system_table, fw_vendor);
+
+ return (efi_char16_t *)vendor;
+}
+
static const efi_char16_t apple[] = L"Apple";
static void setup_quirks(struct boot_params *boot_params)
{
- efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long)
- efi_table_attr(efi_system_table, fw_vendor);
-
- if (!memcmp(fw_vendor, apple, sizeof(apple))) {
- if (IS_ENABLED(CONFIG_APPLE_PROPERTIES))
- retrieve_apple_device_properties(boot_params);
- }
+ if (IS_ENABLED(CONFIG_APPLE_PROPERTIES) &&
+ !memcmp(efistub_fw_vendor(), apple, sizeof(apple)))
+ retrieve_apple_device_properties(boot_params);
}
/*
@@ -449,9 +452,8 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_system_table_t *sys_table_arg)
{
- struct boot_params *boot_params;
- struct setup_header *hdr;
- void *image_base;
+ static struct boot_params boot_params __page_aligned_bss;
+ struct setup_header *hdr = &boot_params.hdr;
efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
int options_size = 0;
efi_status_t status;
@@ -469,30 +471,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_exit(handle, status);
}
- image_base = efi_table_attr(image, image_base);
-
- status = efi_allocate_pages(sizeof(struct boot_params),
- (unsigned long *)&boot_params, ULONG_MAX);
- if (status != EFI_SUCCESS) {
- efi_err("Failed to allocate lowmem for boot params\n");
- efi_exit(handle, status);
- }
-
- memset(boot_params, 0x0, sizeof(struct boot_params));
-
- hdr = &boot_params->hdr;
-
- /* Copy the setup header from the second sector to boot_params */
- memcpy(&hdr->jump, image_base + 512,
- sizeof(struct setup_header) - offsetof(struct setup_header, jump));
-
- /*
- * Fill out some of the header fields ourselves because the
- * EFI firmware loader doesn't load the first sector.
- */
+ /* Assign the setup_header fields that the kernel actually cares about */
hdr->root_flags = 1;
hdr->vid_mode = 0xffff;
- hdr->boot_flag = 0xAA55;
hdr->type_of_loader = 0x21;
@@ -501,25 +482,13 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
if (!cmdline_ptr)
goto fail;
- efi_set_u64_split((unsigned long)cmdline_ptr,
- &hdr->cmd_line_ptr, &boot_params->ext_cmd_line_ptr);
+ efi_set_u64_split((unsigned long)cmdline_ptr, &hdr->cmd_line_ptr,
+ &boot_params.ext_cmd_line_ptr);
- hdr->ramdisk_image = 0;
- hdr->ramdisk_size = 0;
-
- /*
- * Disregard any setup data that was provided by the bootloader:
- * setup_data could be pointing anywhere, and we have no way of
- * authenticating or validating the payload.
- */
- hdr->setup_data = 0;
-
- efi_stub_entry(handle, sys_table_arg, boot_params);
+ efi_stub_entry(handle, sys_table_arg, &boot_params);
/* not reached */
fail:
- efi_free(sizeof(struct boot_params), (unsigned long)boot_params);
-
efi_exit(handle, status);
}
@@ -605,11 +574,8 @@ setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_s
break;
case EFI_UNACCEPTED_MEMORY:
- if (!IS_ENABLED(CONFIG_UNACCEPTED_MEMORY)) {
- efi_warn_once(
-"The system has unaccepted memory, but kernel does not support it\nConsider enabling CONFIG_UNACCEPTED_MEMORY\n");
+ if (!IS_ENABLED(CONFIG_UNACCEPTED_MEMORY))
continue;
- }
e820_type = E820_TYPE_RAM;
process_unaccepted_memory(d->phys_addr,
d->phys_addr + PAGE_SIZE * d->num_pages);
@@ -802,11 +768,25 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && !efi_nokaslr) {
u64 range = KERNEL_IMAGE_SIZE - LOAD_PHYSICAL_ADDR - kernel_total_size;
+ static const efi_char16_t ami[] = L"American Megatrends";
efi_get_seed(seed, sizeof(seed));
virt_addr += (range * seed[1]) >> 32;
virt_addr &= ~(CONFIG_PHYSICAL_ALIGN - 1);
+
+ /*
+ * Older Dell systems with AMI UEFI firmware v2.0 may hang
+ * while decompressing the kernel if physical address
+ * randomization is enabled.
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=218173
+ */
+ if (efi_system_table->hdr.revision <= EFI_2_00_SYSTEM_TABLE_REVISION &&
+ !memcmp(efistub_fw_vendor(), ami, sizeof(ami))) {
+ efi_debug("AMI firmware v2.0 or older detected - disabling physical KASLR\n");
+ seed[0] = 0;
+ }
}
status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr,
@@ -852,6 +832,8 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
unsigned long kernel_entry;
efi_status_t status;
+ boot_params_ptr = boot_params;
+
efi_system_table = sys_table_arg;
/* Check if we were booted by the EFI firmware */
if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
diff --git a/drivers/firmware/efi/unaccepted_memory.c b/drivers/firmware/efi/unaccepted_memory.c
index 853f7dc3c21d..5b439d04079c 100644
--- a/drivers/firmware/efi/unaccepted_memory.c
+++ b/drivers/firmware/efi/unaccepted_memory.c
@@ -3,11 +3,20 @@
#include <linux/efi.h>
#include <linux/memblock.h>
#include <linux/spinlock.h>
+#include <linux/crash_dump.h>
#include <asm/unaccepted_memory.h>
-/* Protects unaccepted memory bitmap */
+/* Protects unaccepted memory bitmap and accepting_list */
static DEFINE_SPINLOCK(unaccepted_memory_lock);
+struct accept_range {
+ struct list_head list;
+ unsigned long start;
+ unsigned long end;
+};
+
+static LIST_HEAD(accepting_list);
+
/*
* accept_memory() -- Consult bitmap and accept the memory if needed.
*
@@ -24,6 +33,7 @@ void accept_memory(phys_addr_t start, phys_addr_t end)
{
struct efi_unaccepted_memory *unaccepted;
unsigned long range_start, range_end;
+ struct accept_range range, *entry;
unsigned long flags;
u64 unit_size;
@@ -78,20 +88,67 @@ void accept_memory(phys_addr_t start, phys_addr_t end)
if (end > unaccepted->size * unit_size * BITS_PER_BYTE)
end = unaccepted->size * unit_size * BITS_PER_BYTE;
- range_start = start / unit_size;
-
+ range.start = start / unit_size;
+ range.end = DIV_ROUND_UP(end, unit_size);
+retry:
spin_lock_irqsave(&unaccepted_memory_lock, flags);
+
+ /*
+ * Check if anybody works on accepting the same range of the memory.
+ *
+ * The check is done with unit_size granularity. It is crucial to catch
+ * all accept requests to the same unit_size block, even if they don't
+ * overlap on physical address level.
+ */
+ list_for_each_entry(entry, &accepting_list, list) {
+ if (entry->end <= range.start)
+ continue;
+ if (entry->start >= range.end)
+ continue;
+
+ /*
+ * Somebody else accepting the range. Or at least part of it.
+ *
+ * Drop the lock and retry until it is complete.
+ */
+ spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
+ goto retry;
+ }
+
+ /*
+ * Register that the range is about to be accepted.
+ * Make sure nobody else will accept it.
+ */
+ list_add(&range.list, &accepting_list);
+
+ range_start = range.start;
for_each_set_bitrange_from(range_start, range_end, unaccepted->bitmap,
- DIV_ROUND_UP(end, unit_size)) {
+ range.end) {
unsigned long phys_start, phys_end;
unsigned long len = range_end - range_start;
phys_start = range_start * unit_size + unaccepted->phys_base;
phys_end = range_end * unit_size + unaccepted->phys_base;
+ /*
+ * Keep interrupts disabled until the accept operation is
+ * complete in order to prevent deadlocks.
+ *
+ * Enabling interrupts before calling arch_accept_memory()
+ * creates an opportunity for an interrupt handler to request
+ * acceptance for the same memory. The handler will continuously
+ * spin with interrupts disabled, preventing other task from
+ * making progress with the acceptance process.
+ */
+ spin_unlock(&unaccepted_memory_lock);
+
arch_accept_memory(phys_start, phys_end);
+
+ spin_lock(&unaccepted_memory_lock);
bitmap_clear(unaccepted->bitmap, range_start, len);
}
+
+ list_del(&range.list);
spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
}
@@ -145,3 +202,22 @@ bool range_contains_unaccepted_memory(phys_addr_t start, phys_addr_t end)
return ret;
}
+
+#ifdef CONFIG_PROC_VMCORE
+static bool unaccepted_memory_vmcore_pfn_is_ram(struct vmcore_cb *cb,
+ unsigned long pfn)
+{
+ return !pfn_is_unaccepted_memory(pfn);
+}
+
+static struct vmcore_cb vmcore_cb = {
+ .pfn_is_ram = unaccepted_memory_vmcore_pfn_is_ram,
+};
+
+static int __init unaccepted_memory_init_kdump(void)
+{
+ register_vmcore_cb(&vmcore_cb);
+ return 0;
+}
+core_initcall(unaccepted_memory_init_kdump);
+#endif /* CONFIG_PROC_VMCORE */
diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
index c027d99f2a59..183613f82a11 100644
--- a/drivers/firmware/imx/Kconfig
+++ b/drivers/firmware/imx/Kconfig
@@ -22,9 +22,3 @@ config IMX_SCU
This driver manages the IPC interface between host CPU and the
SCU firmware running on M4.
-
-config IMX_SCU_PD
- bool "IMX SCU Power Domain driver"
- depends on IMX_SCU
- help
- The System Controller Firmware (SCFW) based power domain driver.
diff --git a/drivers/firmware/imx/imx-dsp.c b/drivers/firmware/imx/imx-dsp.c
index 508eab346fc6..a48a58e0c61f 100644
--- a/drivers/firmware/imx/imx-dsp.c
+++ b/drivers/firmware/imx/imx-dsp.c
@@ -114,11 +114,11 @@ static int imx_dsp_setup_channels(struct imx_dsp_ipc *dsp_ipc)
dsp_chan->idx = i % 2;
dsp_chan->ch = mbox_request_channel_byname(cl, chan_name);
if (IS_ERR(dsp_chan->ch)) {
- kfree(dsp_chan->name);
ret = PTR_ERR(dsp_chan->ch);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to request mbox chan %s ret %d\n",
chan_name, ret);
+ kfree(dsp_chan->name);
goto out;
}
diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
index 9a2656d73600..ed60f1103053 100644
--- a/drivers/firmware/meson/meson_sm.c
+++ b/drivers/firmware/meson/meson_sm.c
@@ -13,9 +13,10 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/printk.h>
+#include <linux/property.h>
#include <linux/types.h>
#include <linux/sizes.h>
#include <linux/slab.h>
@@ -67,7 +68,7 @@ static u32 meson_sm_get_cmd(const struct meson_sm_chip *chip,
return cmd->smc_id;
}
-static u32 __meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2,
+static s32 __meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2,
u32 arg3, u32 arg4)
{
struct arm_smccc_res res;
@@ -102,9 +103,10 @@ static void __iomem *meson_sm_map_shmem(u32 cmd_shmem, unsigned int size)
* Return: 0 on success, a negative value on error
*/
int meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index,
- u32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+ s32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
{
- u32 cmd, lret;
+ u32 cmd;
+ s32 lret;
if (!fw->chip)
return -ENOENT;
@@ -143,7 +145,7 @@ int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
unsigned int bsize, unsigned int cmd_index, u32 arg0,
u32 arg1, u32 arg2, u32 arg3, u32 arg4)
{
- u32 size;
+ s32 size;
int ret;
if (!fw->chip)
@@ -158,11 +160,16 @@ int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
if (meson_sm_call(fw, cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
return -EINVAL;
- if (size > bsize)
+ if (size < 0 || size > bsize)
return -EINVAL;
ret = size;
+ /* In some cases (for example GET_CHIP_ID command),
+ * SMC doesn't return the number of bytes read, even
+ * though the bytes were actually read into sm_shmem_out.
+ * So this check is needed.
+ */
if (!size)
size = bsize;
@@ -192,7 +199,7 @@ int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
unsigned int size, unsigned int cmd_index, u32 arg0,
u32 arg1, u32 arg2, u32 arg3, u32 arg4)
{
- u32 written;
+ s32 written;
if (!fw->chip)
return -ENOENT;
@@ -208,7 +215,7 @@ int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
if (meson_sm_call(fw, cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0)
return -EINVAL;
- if (!written)
+ if (written <= 0 || written > size)
return -EINVAL;
return written;
@@ -291,7 +298,7 @@ static int __init meson_sm_probe(struct platform_device *pdev)
if (!fw)
return -ENOMEM;
- chip = of_match_device(meson_sm_ids, dev)->data;
+ chip = device_get_match_data(dev);
if (!chip)
return -EINVAL;
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
deleted file mode 100644
index 715a45442d1c..000000000000
--- a/drivers/firmware/pcdp.c
+++ /dev/null
@@ -1,135 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Parse the EFI PCDP table to locate the console device.
- *
- * (c) Copyright 2002, 2003, 2004 Hewlett-Packard Development Company, L.P.
- * Khalid Aziz <khalid.aziz@hp.com>
- * Alex Williamson <alex.williamson@hp.com>
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- */
-
-#include <linux/acpi.h>
-#include <linux/console.h>
-#include <linux/efi.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <asm/vga.h>
-#include "pcdp.h"
-
-static int __init
-setup_serial_console(struct pcdp_uart *uart)
-{
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- int mmio;
- static char options[64], *p = options;
- char parity;
-
- mmio = (uart->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY);
- p += sprintf(p, "uart8250,%s,0x%llx",
- mmio ? "mmio" : "io", uart->addr.address);
- if (uart->baud) {
- p += sprintf(p, ",%llu", uart->baud);
- if (uart->bits) {
- switch (uart->parity) {
- case 0x2: parity = 'e'; break;
- case 0x3: parity = 'o'; break;
- default: parity = 'n';
- }
- p += sprintf(p, "%c%d", parity, uart->bits);
- }
- }
-
- add_preferred_console("uart", 8250, &options[9]);
- return setup_earlycon(options);
-#else
- return -ENODEV;
-#endif
-}
-
-static int __init
-setup_vga_console(struct pcdp_device *dev)
-{
-#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
- u8 *if_ptr;
-
- if_ptr = ((u8 *)dev + sizeof(struct pcdp_device));
- if (if_ptr[0] == PCDP_IF_PCI) {
- struct pcdp_if_pci if_pci;
-
- /* struct copy since ifptr might not be correctly aligned */
-
- memcpy(&if_pci, if_ptr, sizeof(if_pci));
-
- if (if_pci.trans & PCDP_PCI_TRANS_IOPORT)
- vga_console_iobase = if_pci.ioport_tra;
-
- if (if_pci.trans & PCDP_PCI_TRANS_MMIO)
- vga_console_membase = if_pci.mmio_tra;
- }
-
- if (efi_mem_type(vga_console_membase + 0xA0000) == EFI_CONVENTIONAL_MEMORY) {
- printk(KERN_ERR "PCDP: VGA selected, but frame buffer is not MMIO!\n");
- return -ENODEV;
- }
-
- conswitchp = &vga_con;
- printk(KERN_INFO "PCDP: VGA console\n");
- return 0;
-#else
- return -ENODEV;
-#endif
-}
-
-extern unsigned long hcdp_phys;
-
-int __init
-efi_setup_pcdp_console(char *cmdline)
-{
- struct pcdp *pcdp;
- struct pcdp_uart *uart;
- struct pcdp_device *dev, *end;
- int i, serial = 0;
- int rc = -ENODEV;
-
- if (hcdp_phys == EFI_INVALID_TABLE_ADDR)
- return -ENODEV;
-
- pcdp = early_memremap(hcdp_phys, 4096);
- printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, hcdp_phys);
-
- if (strstr(cmdline, "console=hcdp")) {
- if (pcdp->rev < 3)
- serial = 1;
- } else if (strstr(cmdline, "console=")) {
- printk(KERN_INFO "Explicit \"console=\"; ignoring PCDP\n");
- goto out;
- }
-
- if (pcdp->rev < 3 && efi_uart_console_only())
- serial = 1;
-
- for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) {
- if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) {
- if (uart->type == PCDP_CONSOLE_UART) {
- rc = setup_serial_console(uart);
- goto out;
- }
- }
- }
-
- end = (struct pcdp_device *) ((u8 *) pcdp + pcdp->length);
- for (dev = (struct pcdp_device *) (pcdp->uart + pcdp->num_uarts);
- dev < end;
- dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) {
- if (dev->flags & PCDP_PRIMARY_CONSOLE) {
- if (dev->type == PCDP_CONSOLE_VGA) {
- rc = setup_vga_console(dev);
- goto out;
- }
- }
- }
-
-out:
- early_memunmap(pcdp, 4096);
- return rc;
-}
diff --git a/drivers/firmware/pcdp.h b/drivers/firmware/pcdp.h
deleted file mode 100644
index e02540571c52..000000000000
--- a/drivers/firmware/pcdp.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Definitions for PCDP-defined console devices
- *
- * For DIG64_HCDPv10a_01.pdf and DIG64_PCDPv20.pdf (v1.0a and v2.0 resp.),
- * please see <http://www.dig64.org/specifications/>
- *
- * (c) Copyright 2002, 2004 Hewlett-Packard Development Company, L.P.
- * Khalid Aziz <khalid.aziz@hp.com>
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- */
-
-#define PCDP_CONSOLE 0
-#define PCDP_DEBUG 1
-#define PCDP_CONSOLE_OUTPUT 2
-#define PCDP_CONSOLE_INPUT 3
-
-#define PCDP_UART (0 << 3)
-#define PCDP_VGA (1 << 3)
-#define PCDP_USB (2 << 3)
-
-/* pcdp_uart.type and pcdp_device.type */
-#define PCDP_CONSOLE_UART (PCDP_UART | PCDP_CONSOLE)
-#define PCDP_DEBUG_UART (PCDP_UART | PCDP_DEBUG)
-#define PCDP_CONSOLE_VGA (PCDP_VGA | PCDP_CONSOLE_OUTPUT)
-#define PCDP_CONSOLE_USB (PCDP_USB | PCDP_CONSOLE_INPUT)
-
-/* pcdp_uart.flags */
-#define PCDP_UART_EDGE_SENSITIVE (1 << 0)
-#define PCDP_UART_ACTIVE_LOW (1 << 1)
-#define PCDP_UART_PRIMARY_CONSOLE (1 << 2)
-#define PCDP_UART_IRQ (1 << 6) /* in pci_func for rev < 3 */
-#define PCDP_UART_PCI (1 << 7) /* in pci_func for rev < 3 */
-
-struct pcdp_uart {
- u8 type;
- u8 bits;
- u8 parity;
- u8 stop_bits;
- u8 pci_seg;
- u8 pci_bus;
- u8 pci_dev;
- u8 pci_func;
- u64 baud;
- struct acpi_generic_address addr;
- u16 pci_dev_id;
- u16 pci_vendor_id;
- u32 gsi;
- u32 clock_rate;
- u8 pci_prog_intfc;
- u8 flags;
- u16 conout_index;
- u32 reserved;
-} __attribute__((packed));
-
-#define PCDP_IF_PCI 1
-
-/* pcdp_if_pci.trans */
-#define PCDP_PCI_TRANS_IOPORT 0x02
-#define PCDP_PCI_TRANS_MMIO 0x01
-
-struct pcdp_if_pci {
- u8 interconnect;
- u8 reserved;
- u16 length;
- u8 segment;
- u8 bus;
- u8 dev;
- u8 fun;
- u16 dev_id;
- u16 vendor_id;
- u32 acpi_interrupt;
- u64 mmio_tra;
- u64 ioport_tra;
- u8 flags;
- u8 trans;
-} __attribute__((packed));
-
-struct pcdp_vga {
- u8 count; /* address space descriptors */
-} __attribute__((packed));
-
-/* pcdp_device.flags */
-#define PCDP_PRIMARY_CONSOLE 1
-
-struct pcdp_device {
- u8 type;
- u8 flags;
- u16 length;
- u16 efi_index;
- /* next data is pcdp_if_pci or pcdp_if_acpi (not yet supported) */
- /* next data is device specific type (currently only pcdp_vga) */
-} __attribute__((packed));
-
-struct pcdp {
- u8 signature[4];
- u32 length;
- u8 rev; /* PCDP v2.0 is rev 3 */
- u8 chksum;
- u8 oemid[6];
- u8 oem_tabid[8];
- u32 oem_rev;
- u8 creator_id[4];
- u32 creator_rev;
- u32 num_uarts;
- struct pcdp_uart uart[]; /* actual size is num_uarts */
- /* remainder of table is pcdp_device structures */
-} __attribute__((packed));
diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig
new file mode 100644
index 000000000000..3f05d9854ddf
--- /dev/null
+++ b/drivers/firmware/qcom/Kconfig
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.rst.
+#
+
+menu "Qualcomm firmware drivers"
+
+config QCOM_SCM
+ tristate
+
+config QCOM_SCM_DOWNLOAD_MODE_DEFAULT
+ bool "Qualcomm download mode enabled by default"
+ depends on QCOM_SCM
+ help
+ A device with "download mode" enabled will upon an unexpected
+ warm-restart enter a special debug mode that allows the user to
+ "download" memory content over USB for offline postmortem analysis.
+ The feature can be enabled/disabled on the kernel command line.
+
+ Say Y here to enable "download mode" by default.
+
+config QCOM_QSEECOM
+ bool "Qualcomm QSEECOM interface driver"
+ depends on QCOM_SCM=y
+ select AUXILIARY_BUS
+ help
+ Various Qualcomm SoCs have a Secure Execution Environment (SEE) running
+ in the Trust Zone. This module provides an interface to that via the
+ QSEECOM mechanism, using SCM calls.
+
+ The QSEECOM interface allows, among other things, access to applications
+ running in the SEE. An example of such an application is 'uefisecapp',
+ which is required to access UEFI variables on certain systems. If
+ selected, the interface will also attempt to detect and register client
+ devices for supported applications.
+
+ Select Y here to enable the QSEECOM interface driver.
+
+config QCOM_QSEECOM_UEFISECAPP
+ bool "Qualcomm SEE UEFI Secure App client driver"
+ depends on QCOM_QSEECOM
+ depends on EFI
+ help
+ Various Qualcomm SoCs do not allow direct access to EFI variables.
+ Instead, these need to be accessed via the UEFI Secure Application
+ (uefisecapp), residing in the Secure Execution Environment (SEE).
+
+ This module provides a client driver for uefisecapp, installing efivar
+ operations to allow the kernel accessing EFI variables, and via that also
+ provide user-space with access to EFI variables via efivarfs.
+
+ Select Y here to provide access to EFI variables on the aforementioned
+ platforms.
+
+endmenu
diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile
new file mode 100644
index 000000000000..c9f12ee8224a
--- /dev/null
+++ b/drivers/firmware/qcom/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the linux kernel.
+#
+
+obj-$(CONFIG_QCOM_SCM) += qcom-scm.o
+qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
+obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o
+obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o
diff --git a/drivers/firmware/qcom/qcom_qseecom.c b/drivers/firmware/qcom/qcom_qseecom.c
new file mode 100644
index 000000000000..731e6d5719f9
--- /dev/null
+++ b/drivers/firmware/qcom/qcom_qseecom.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for Qualcomm Secure Execution Environment (SEE) interface (QSEECOM).
+ * Responsible for setting up and managing QSEECOM client devices.
+ *
+ * Copyright (C) 2023 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+#include <linux/auxiliary_bus.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <linux/firmware/qcom/qcom_qseecom.h>
+#include <linux/firmware/qcom/qcom_scm.h>
+
+struct qseecom_app_desc {
+ const char *app_name;
+ const char *dev_name;
+};
+
+static void qseecom_client_release(struct device *dev)
+{
+ struct qseecom_client *client;
+
+ client = container_of(dev, struct qseecom_client, aux_dev.dev);
+ kfree(client);
+}
+
+static void qseecom_client_remove(void *data)
+{
+ struct qseecom_client *client = data;
+
+ auxiliary_device_delete(&client->aux_dev);
+ auxiliary_device_uninit(&client->aux_dev);
+}
+
+static int qseecom_client_register(struct platform_device *qseecom_dev,
+ const struct qseecom_app_desc *desc)
+{
+ struct qseecom_client *client;
+ u32 app_id;
+ int ret;
+
+ /* Try to find the app ID, skip device if not found */
+ ret = qcom_scm_qseecom_app_get_id(desc->app_name, &app_id);
+ if (ret)
+ return ret == -ENOENT ? 0 : ret;
+
+ dev_info(&qseecom_dev->dev, "setting up client for %s\n", desc->app_name);
+
+ /* Allocate and set-up the client device */
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client)
+ return -ENOMEM;
+
+ client->aux_dev.name = desc->dev_name;
+ client->aux_dev.dev.parent = &qseecom_dev->dev;
+ client->aux_dev.dev.release = qseecom_client_release;
+ client->app_id = app_id;
+
+ ret = auxiliary_device_init(&client->aux_dev);
+ if (ret) {
+ kfree(client);
+ return ret;
+ }
+
+ ret = auxiliary_device_add(&client->aux_dev);
+ if (ret) {
+ auxiliary_device_uninit(&client->aux_dev);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(&qseecom_dev->dev, qseecom_client_remove, client);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * List of supported applications. One client device will be created per entry,
+ * assuming the app has already been loaded (usually by firmware bootloaders)
+ * and its ID can be queried successfully.
+ */
+static const struct qseecom_app_desc qcom_qseecom_apps[] = {
+ { "qcom.tz.uefisecapp", "uefisecapp" },
+};
+
+static int qcom_qseecom_probe(struct platform_device *qseecom_dev)
+{
+ int ret;
+ int i;
+
+ /* Set up client devices for each base application */
+ for (i = 0; i < ARRAY_SIZE(qcom_qseecom_apps); i++) {
+ ret = qseecom_client_register(qseecom_dev, &qcom_qseecom_apps[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct platform_driver qcom_qseecom_driver = {
+ .driver = {
+ .name = "qcom_qseecom",
+ },
+ .probe = qcom_qseecom_probe,
+};
+
+static int __init qcom_qseecom_init(void)
+{
+ return platform_driver_register(&qcom_qseecom_driver);
+}
+subsys_initcall(qcom_qseecom_init);
+
+MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
+MODULE_DESCRIPTION("Driver for the Qualcomm SEE (QSEECOM) interface");
+MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
new file mode 100644
index 000000000000..a33acdaf7b78
--- /dev/null
+++ b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
@@ -0,0 +1,871 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Client driver for Qualcomm UEFI Secure Application (qcom.tz.uefisecapp).
+ * Provides access to UEFI variables on platforms where they are secured by the
+ * aforementioned Secure Execution Environment (SEE) application.
+ *
+ * Copyright (C) 2023 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+#include <linux/efi.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/ucs2_string.h>
+
+#include <linux/firmware/qcom/qcom_qseecom.h>
+
+/* -- Qualcomm "uefisecapp" interface definitions. -------------------------- */
+
+/* Maximum length of name string with null-terminator */
+#define QSEE_MAX_NAME_LEN 1024
+
+#define QSEE_CMD_UEFI(x) (0x8000 | (x))
+#define QSEE_CMD_UEFI_GET_VARIABLE QSEE_CMD_UEFI(0)
+#define QSEE_CMD_UEFI_SET_VARIABLE QSEE_CMD_UEFI(1)
+#define QSEE_CMD_UEFI_GET_NEXT_VARIABLE QSEE_CMD_UEFI(2)
+#define QSEE_CMD_UEFI_QUERY_VARIABLE_INFO QSEE_CMD_UEFI(3)
+
+/**
+ * struct qsee_req_uefi_get_variable - Request for GetVariable command.
+ * @command_id: The ID of the command. Must be %QSEE_CMD_UEFI_GET_VARIABLE.
+ * @length: Length of the request in bytes, including this struct and any
+ * parameters (name, GUID) stored after it as well as any padding
+ * thereof for alignment.
+ * @name_offset: Offset from the start of this struct to where the variable
+ * name is stored (as utf-16 string), in bytes.
+ * @name_size: Size of the name parameter in bytes, including null-terminator.
+ * @guid_offset: Offset from the start of this struct to where the GUID
+ * parameter is stored, in bytes.
+ * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t).
+ * @data_size: Size of the output buffer, in bytes.
+ */
+struct qsee_req_uefi_get_variable {
+ u32 command_id;
+ u32 length;
+ u32 name_offset;
+ u32 name_size;
+ u32 guid_offset;
+ u32 guid_size;
+ u32 data_size;
+} __packed;
+
+/**
+ * struct qsee_rsp_uefi_get_variable - Response for GetVariable command.
+ * @command_id: The ID of the command. Should be %QSEE_CMD_UEFI_GET_VARIABLE.
+ * @length: Length of the response in bytes, including this struct and the
+ * returned data.
+ * @status: Status of this command.
+ * @attributes: EFI variable attributes.
+ * @data_offset: Offset from the start of this struct to where the data is
+ * stored, in bytes.
+ * @data_size: Size of the returned data, in bytes. In case status indicates
+ * that the buffer is too small, this will be the size required
+ * to store the EFI variable data.
+ */
+struct qsee_rsp_uefi_get_variable {
+ u32 command_id;
+ u32 length;
+ u32 status;
+ u32 attributes;
+ u32 data_offset;
+ u32 data_size;
+} __packed;
+
+/**
+ * struct qsee_req_uefi_set_variable - Request for the SetVariable command.
+ * @command_id: The ID of the command. Must be %QSEE_CMD_UEFI_SET_VARIABLE.
+ * @length: Length of the request in bytes, including this struct and any
+ * parameters (name, GUID, data) stored after it as well as any
+ * padding thereof required for alignment.
+ * @name_offset: Offset from the start of this struct to where the variable
+ * name is stored (as utf-16 string), in bytes.
+ * @name_size: Size of the name parameter in bytes, including null-terminator.
+ * @guid_offset: Offset from the start of this struct to where the GUID
+ * parameter is stored, in bytes.
+ * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t).
+ * @attributes: The EFI variable attributes to set for this variable.
+ * @data_offset: Offset from the start of this struct to where the EFI variable
+ * data is stored, in bytes.
+ * @data_size: Size of EFI variable data, in bytes.
+ *
+ */
+struct qsee_req_uefi_set_variable {
+ u32 command_id;
+ u32 length;
+ u32 name_offset;
+ u32 name_size;
+ u32 guid_offset;
+ u32 guid_size;
+ u32 attributes;
+ u32 data_offset;
+ u32 data_size;
+} __packed;
+
+/**
+ * struct qsee_rsp_uefi_set_variable - Response for the SetVariable command.
+ * @command_id: The ID of the command. Should be %QSEE_CMD_UEFI_SET_VARIABLE.
+ * @length: The length of this response, i.e. the size of this struct in
+ * bytes.
+ * @status: Status of this command.
+ * @_unknown1: Unknown response field.
+ * @_unknown2: Unknown response field.
+ */
+struct qsee_rsp_uefi_set_variable {
+ u32 command_id;
+ u32 length;
+ u32 status;
+ u32 _unknown1;
+ u32 _unknown2;
+} __packed;
+
+/**
+ * struct qsee_req_uefi_get_next_variable - Request for the
+ * GetNextVariableName command.
+ * @command_id: The ID of the command. Must be
+ * %QSEE_CMD_UEFI_GET_NEXT_VARIABLE.
+ * @length: Length of the request in bytes, including this struct and any
+ * parameters (name, GUID) stored after it as well as any padding
+ * thereof for alignment.
+ * @guid_offset: Offset from the start of this struct to where the GUID
+ * parameter is stored, in bytes.
+ * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t).
+ * @name_offset: Offset from the start of this struct to where the variable
+ * name is stored (as utf-16 string), in bytes.
+ * @name_size: Size of the name parameter in bytes, including null-terminator.
+ */
+struct qsee_req_uefi_get_next_variable {
+ u32 command_id;
+ u32 length;
+ u32 guid_offset;
+ u32 guid_size;
+ u32 name_offset;
+ u32 name_size;
+} __packed;
+
+/**
+ * struct qsee_rsp_uefi_get_next_variable - Response for the
+ * GetNextVariableName command.
+ * @command_id: The ID of the command. Should be
+ * %QSEE_CMD_UEFI_GET_NEXT_VARIABLE.
+ * @length: Length of the response in bytes, including this struct and any
+ * parameters (name, GUID) stored after it as well as any padding
+ * thereof for alignment.
+ * @status: Status of this command.
+ * @guid_offset: Offset from the start of this struct to where the GUID
+ * parameter is stored, in bytes.
+ * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t).
+ * @name_offset: Offset from the start of this struct to where the variable
+ * name is stored (as utf-16 string), in bytes.
+ * @name_size: Size of the name parameter in bytes, including null-terminator.
+ */
+struct qsee_rsp_uefi_get_next_variable {
+ u32 command_id;
+ u32 length;
+ u32 status;
+ u32 guid_offset;
+ u32 guid_size;
+ u32 name_offset;
+ u32 name_size;
+} __packed;
+
+/**
+ * struct qsee_req_uefi_query_variable_info - Response for the
+ * GetNextVariableName command.
+ * @command_id: The ID of the command. Must be
+ * %QSEE_CMD_UEFI_QUERY_VARIABLE_INFO.
+ * @length: The length of this request, i.e. the size of this struct in
+ * bytes.
+ * @attributes: The storage attributes to query the info for.
+ */
+struct qsee_req_uefi_query_variable_info {
+ u32 command_id;
+ u32 length;
+ u32 attributes;
+} __packed;
+
+/**
+ * struct qsee_rsp_uefi_query_variable_info - Response for the
+ * GetNextVariableName command.
+ * @command_id: The ID of the command. Must be
+ * %QSEE_CMD_UEFI_QUERY_VARIABLE_INFO.
+ * @length: The length of this response, i.e. the size of this
+ * struct in bytes.
+ * @status: Status of this command.
+ * @_pad: Padding.
+ * @storage_space: Full storage space size, in bytes.
+ * @remaining_space: Free storage space available, in bytes.
+ * @max_variable_size: Maximum variable data size, in bytes.
+ */
+struct qsee_rsp_uefi_query_variable_info {
+ u32 command_id;
+ u32 length;
+ u32 status;
+ u32 _pad;
+ u64 storage_space;
+ u64 remaining_space;
+ u64 max_variable_size;
+} __packed;
+
+/* -- Alignment helpers ----------------------------------------------------- */
+
+/*
+ * Helper macro to ensure proper alignment of types (fields and arrays) when
+ * stored in some (contiguous) buffer.
+ *
+ * Note: The driver from which this one has been reverse-engineered expects an
+ * 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.
+ */
+#define qcuefi_buf_align_fields(fields...) \
+ ({ \
+ size_t __len = 0; \
+ fields \
+ __len; \
+ })
+
+#define __field_impl(size, align, offset) \
+ ({ \
+ size_t *__offset = (offset); \
+ size_t __aligned; \
+ \
+ __aligned = ALIGN(__len, align); \
+ __len = __aligned + (size); \
+ \
+ if (__offset) \
+ *__offset = __aligned; \
+ });
+
+#define __array_offs(type, count, offset) \
+ __field_impl(sizeof(type) * (count), __alignof__(type), 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)
+
+/* -- UEFI app interface. --------------------------------------------------- */
+
+struct qcuefi_client {
+ struct qseecom_client *client;
+ struct efivars efivars;
+};
+
+static struct device *qcuefi_dev(struct qcuefi_client *qcuefi)
+{
+ return &qcuefi->client->aux_dev.dev;
+}
+
+static efi_status_t qsee_uefi_status_to_efi(u32 status)
+{
+ u64 category = status & 0xf0000000;
+ u64 code = status & 0x0fffffff;
+
+ return category << (BITS_PER_LONG - 32) | code;
+}
+
+static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const efi_char16_t *name,
+ const efi_guid_t *guid, u32 *attributes,
+ unsigned long *data_size, void *data)
+{
+ struct qsee_req_uefi_get_variable *req_data;
+ struct qsee_rsp_uefi_get_variable *rsp_data;
+ unsigned long buffer_size = *data_size;
+ efi_status_t efi_status = EFI_SUCCESS;
+ unsigned long name_length;
+ size_t guid_offs;
+ size_t name_offs;
+ size_t req_size;
+ size_t rsp_size;
+ ssize_t status;
+
+ if (!name || !guid)
+ return EFI_INVALID_PARAMETER;
+
+ name_length = ucs2_strnlen(name, QSEE_MAX_NAME_LEN) + 1;
+ if (name_length > QSEE_MAX_NAME_LEN)
+ return EFI_INVALID_PARAMETER;
+
+ if (buffer_size && !data)
+ return EFI_INVALID_PARAMETER;
+
+ req_size = qcuefi_buf_align_fields(
+ __field(*req_data)
+ __array_offs(*name, name_length, &name_offs)
+ __field_offs(*guid, &guid_offs)
+ );
+
+ rsp_size = qcuefi_buf_align_fields(
+ __field(*rsp_data)
+ __array(u8, buffer_size)
+ );
+
+ req_data = kzalloc(req_size, GFP_KERNEL);
+ if (!req_data) {
+ 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->command_id = QSEE_CMD_UEFI_GET_VARIABLE;
+ req_data->data_size = buffer_size;
+ req_data->name_offset = name_offs;
+ req_data->name_size = name_length * sizeof(*name);
+ req_data->guid_offset = guid_offs;
+ req_data->guid_size = sizeof(*guid);
+ req_data->length = req_size;
+
+ status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length);
+ if (status < 0)
+ return EFI_INVALID_PARAMETER;
+
+ 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);
+ if (status) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->command_id != QSEE_CMD_UEFI_GET_VARIABLE) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->length < sizeof(*rsp_data)) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->status) {
+ dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
+ __func__, rsp_data->status);
+ efi_status = qsee_uefi_status_to_efi(rsp_data->status);
+
+ /* Update size and attributes in case buffer is too small. */
+ if (efi_status == EFI_BUFFER_TOO_SMALL) {
+ *data_size = rsp_data->data_size;
+ if (attributes)
+ *attributes = rsp_data->attributes;
+ }
+
+ goto out_free;
+ }
+
+ if (rsp_data->length > rsp_size) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->data_offset + rsp_data->data_size > rsp_data->length) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ /*
+ * Note: We need to set attributes and data size even if the buffer is
+ * too small and we won't copy any data. This is described in spec, so
+ * that callers can either allocate a buffer properly (with two calls
+ * to this function) or just read back attributes withouth having to
+ * deal with that.
+ *
+ * Specifically:
+ * - If we have a buffer size of zero and no buffer, just return the
+ * attributes, required size, and indicate success.
+ * - If the buffer size is nonzero but too small, indicate that as an
+ * error.
+ * - Otherwise, we are good to copy the data.
+ *
+ * Note that we have already ensured above that the buffer pointer is
+ * non-NULL if its size is nonzero.
+ */
+ *data_size = rsp_data->data_size;
+ if (attributes)
+ *attributes = rsp_data->attributes;
+
+ if (buffer_size == 0 && !data) {
+ efi_status = EFI_SUCCESS;
+ goto out_free;
+ }
+
+ if (buffer_size < rsp_data->data_size) {
+ efi_status = EFI_BUFFER_TOO_SMALL;
+ goto out_free;
+ }
+
+ memcpy(data, ((void *)rsp_data) + rsp_data->data_offset, rsp_data->data_size);
+
+out_free:
+ kfree(rsp_data);
+out_free_req:
+ kfree(req_data);
+out:
+ return efi_status;
+}
+
+static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const efi_char16_t *name,
+ const efi_guid_t *guid, u32 attributes,
+ unsigned long data_size, const void *data)
+{
+ struct qsee_req_uefi_set_variable *req_data;
+ struct qsee_rsp_uefi_set_variable *rsp_data;
+ efi_status_t efi_status = EFI_SUCCESS;
+ unsigned long name_length;
+ size_t name_offs;
+ size_t guid_offs;
+ size_t data_offs;
+ size_t req_size;
+ ssize_t status;
+
+ if (!name || !guid)
+ return EFI_INVALID_PARAMETER;
+
+ name_length = ucs2_strnlen(name, QSEE_MAX_NAME_LEN) + 1;
+ if (name_length > QSEE_MAX_NAME_LEN)
+ return EFI_INVALID_PARAMETER;
+
+ /*
+ * Make sure we have some data if data_size is nonzero. Note that using
+ * a size of zero is a valid use-case described in spec and deletes the
+ * variable.
+ */
+ if (data_size && !data)
+ return EFI_INVALID_PARAMETER;
+
+ req_size = qcuefi_buf_align_fields(
+ __field(*req_data)
+ __array_offs(*name, name_length, &name_offs)
+ __field_offs(*guid, &guid_offs)
+ __array_offs(u8, data_size, &data_offs)
+ );
+
+ req_data = kzalloc(req_size, GFP_KERNEL);
+ if (!req_data) {
+ 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->command_id = QSEE_CMD_UEFI_SET_VARIABLE;
+ req_data->attributes = attributes;
+ req_data->name_offset = name_offs;
+ req_data->name_size = name_length * sizeof(*name);
+ req_data->guid_offset = guid_offs;
+ req_data->guid_size = sizeof(*guid);
+ req_data->data_offset = data_offs;
+ req_data->data_size = data_size;
+ req_data->length = req_size;
+
+ status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length);
+ if (status < 0)
+ return EFI_INVALID_PARAMETER;
+
+ memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
+
+ 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));
+ if (status) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->command_id != QSEE_CMD_UEFI_SET_VARIABLE) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->length != sizeof(*rsp_data)) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->status) {
+ dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
+ __func__, rsp_data->status);
+ efi_status = qsee_uefi_status_to_efi(rsp_data->status);
+ }
+
+out_free:
+ kfree(rsp_data);
+out_free_req:
+ kfree(req_data);
+out:
+ return efi_status;
+}
+
+static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
+ unsigned long *name_size, efi_char16_t *name,
+ efi_guid_t *guid)
+{
+ 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;
+ size_t guid_offs;
+ size_t name_offs;
+ size_t req_size;
+ size_t rsp_size;
+ ssize_t status;
+
+ if (!name_size || !name || !guid)
+ return EFI_INVALID_PARAMETER;
+
+ if (*name_size == 0)
+ return EFI_INVALID_PARAMETER;
+
+ req_size = qcuefi_buf_align_fields(
+ __field(*req_data)
+ __field_offs(*guid, &guid_offs)
+ __array_offs(*name, *name_size / sizeof(*name), &name_offs)
+ );
+
+ rsp_size = qcuefi_buf_align_fields(
+ __field(*rsp_data)
+ __field(*guid)
+ __array(*name, *name_size / sizeof(*name))
+ );
+
+ req_data = kzalloc(req_size, GFP_KERNEL);
+ if (!req_data) {
+ 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->command_id = QSEE_CMD_UEFI_GET_NEXT_VARIABLE;
+ req_data->guid_offset = guid_offs;
+ req_data->guid_size = sizeof(*guid);
+ req_data->name_offset = name_offs;
+ req_data->name_size = *name_size;
+ req_data->length = req_size;
+
+ memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
+ status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name,
+ *name_size / sizeof(*name));
+ if (status < 0)
+ return EFI_INVALID_PARAMETER;
+
+ status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size);
+ if (status) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->command_id != QSEE_CMD_UEFI_GET_NEXT_VARIABLE) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->length < sizeof(*rsp_data)) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->status) {
+ dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
+ __func__, rsp_data->status);
+ efi_status = qsee_uefi_status_to_efi(rsp_data->status);
+
+ /*
+ * If the buffer to hold the name is too small, update the
+ * name_size with the required size, so that callers can
+ * reallocate it accordingly.
+ */
+ if (efi_status == EFI_BUFFER_TOO_SMALL)
+ *name_size = rsp_data->name_size;
+
+ goto out_free;
+ }
+
+ if (rsp_data->length > rsp_size) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->name_offset + rsp_data->name_size > rsp_data->length) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->guid_offset + rsp_data->guid_size > rsp_data->length) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->name_size > *name_size) {
+ *name_size = rsp_data->name_size;
+ efi_status = EFI_BUFFER_TOO_SMALL;
+ goto out_free;
+ }
+
+ if (rsp_data->guid_size != sizeof(*guid)) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ memcpy(guid, ((void *)rsp_data) + rsp_data->guid_offset, rsp_data->guid_size);
+ status = ucs2_strscpy(name, ((void *)rsp_data) + rsp_data->name_offset,
+ rsp_data->name_size / sizeof(*name));
+ *name_size = rsp_data->name_size;
+
+ if (status < 0) {
+ /*
+ * Return EFI_DEVICE_ERROR here because the buffer size should
+ * have already been validated above, causing this function to
+ * bail with EFI_BUFFER_TOO_SMALL.
+ */
+ return EFI_DEVICE_ERROR;
+ }
+
+out_free:
+ kfree(rsp_data);
+out_free_req:
+ kfree(req_data);
+out:
+ return efi_status;
+}
+
+static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi, u32 attr,
+ u64 *storage_space, u64 *remaining_space,
+ u64 *max_variable_size)
+{
+ 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;
+ int status;
+
+ req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
+ if (!req_data) {
+ 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->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));
+ if (status) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->command_id != QSEE_CMD_UEFI_QUERY_VARIABLE_INFO) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->length != sizeof(*rsp_data)) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+ }
+
+ if (rsp_data->status) {
+ dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
+ __func__, rsp_data->status);
+ efi_status = qsee_uefi_status_to_efi(rsp_data->status);
+ goto out_free;
+ }
+
+ if (storage_space)
+ *storage_space = rsp_data->storage_space;
+
+ if (remaining_space)
+ *remaining_space = rsp_data->remaining_space;
+
+ if (max_variable_size)
+ *max_variable_size = rsp_data->max_variable_size;
+
+out_free:
+ kfree(rsp_data);
+out_free_req:
+ kfree(req_data);
+out:
+ return efi_status;
+}
+
+/* -- Global efivar interface. ---------------------------------------------- */
+
+static struct qcuefi_client *__qcuefi;
+static DEFINE_MUTEX(__qcuefi_lock);
+
+static int qcuefi_set_reference(struct qcuefi_client *qcuefi)
+{
+ mutex_lock(&__qcuefi_lock);
+
+ if (qcuefi && __qcuefi) {
+ mutex_unlock(&__qcuefi_lock);
+ return -EEXIST;
+ }
+
+ __qcuefi = qcuefi;
+
+ mutex_unlock(&__qcuefi_lock);
+ return 0;
+}
+
+static struct qcuefi_client *qcuefi_acquire(void)
+{
+ mutex_lock(&__qcuefi_lock);
+ return __qcuefi;
+}
+
+static void qcuefi_release(void)
+{
+ mutex_unlock(&__qcuefi_lock);
+}
+
+static efi_status_t qcuefi_get_variable(efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
+ unsigned long *data_size, void *data)
+{
+ struct qcuefi_client *qcuefi;
+ efi_status_t status;
+
+ qcuefi = qcuefi_acquire();
+ if (!qcuefi)
+ return EFI_NOT_READY;
+
+ status = qsee_uefi_get_variable(qcuefi, name, vendor, attr, data_size, data);
+
+ qcuefi_release();
+ return status;
+}
+
+static efi_status_t qcuefi_set_variable(efi_char16_t *name, efi_guid_t *vendor,
+ u32 attr, unsigned long data_size, void *data)
+{
+ struct qcuefi_client *qcuefi;
+ efi_status_t status;
+
+ qcuefi = qcuefi_acquire();
+ if (!qcuefi)
+ return EFI_NOT_READY;
+
+ status = qsee_uefi_set_variable(qcuefi, name, vendor, attr, data_size, data);
+
+ qcuefi_release();
+ return status;
+}
+
+static efi_status_t qcuefi_get_next_variable(unsigned long *name_size, efi_char16_t *name,
+ efi_guid_t *vendor)
+{
+ struct qcuefi_client *qcuefi;
+ efi_status_t status;
+
+ qcuefi = qcuefi_acquire();
+ if (!qcuefi)
+ return EFI_NOT_READY;
+
+ status = qsee_uefi_get_next_variable(qcuefi, name_size, name, vendor);
+
+ qcuefi_release();
+ return status;
+}
+
+static efi_status_t qcuefi_query_variable_info(u32 attr, u64 *storage_space, u64 *remaining_space,
+ u64 *max_variable_size)
+{
+ struct qcuefi_client *qcuefi;
+ efi_status_t status;
+
+ qcuefi = qcuefi_acquire();
+ if (!qcuefi)
+ return EFI_NOT_READY;
+
+ status = qsee_uefi_query_variable_info(qcuefi, attr, storage_space, remaining_space,
+ max_variable_size);
+
+ qcuefi_release();
+ return status;
+}
+
+static const struct efivar_operations qcom_efivar_ops = {
+ .get_variable = qcuefi_get_variable,
+ .set_variable = qcuefi_set_variable,
+ .get_next_variable = qcuefi_get_next_variable,
+ .query_variable_info = qcuefi_query_variable_info,
+};
+
+/* -- Driver setup. --------------------------------------------------------- */
+
+static int qcom_uefisecapp_probe(struct auxiliary_device *aux_dev,
+ const struct auxiliary_device_id *aux_dev_id)
+{
+ struct qcuefi_client *qcuefi;
+ int status;
+
+ qcuefi = devm_kzalloc(&aux_dev->dev, sizeof(*qcuefi), GFP_KERNEL);
+ if (!qcuefi)
+ return -ENOMEM;
+
+ qcuefi->client = container_of(aux_dev, struct qseecom_client, aux_dev);
+
+ auxiliary_set_drvdata(aux_dev, qcuefi);
+ status = qcuefi_set_reference(qcuefi);
+ if (status)
+ return status;
+
+ status = efivars_register(&qcuefi->efivars, &qcom_efivar_ops);
+ if (status)
+ qcuefi_set_reference(NULL);
+
+ return status;
+}
+
+static void qcom_uefisecapp_remove(struct auxiliary_device *aux_dev)
+{
+ struct qcuefi_client *qcuefi = auxiliary_get_drvdata(aux_dev);
+
+ efivars_unregister(&qcuefi->efivars);
+ qcuefi_set_reference(NULL);
+}
+
+static const struct auxiliary_device_id qcom_uefisecapp_id_table[] = {
+ { .name = "qcom_qseecom.uefisecapp" },
+ {}
+};
+MODULE_DEVICE_TABLE(auxiliary, qcom_uefisecapp_id_table);
+
+static struct auxiliary_driver qcom_uefisecapp_driver = {
+ .probe = qcom_uefisecapp_probe,
+ .remove = qcom_uefisecapp_remove,
+ .id_table = qcom_uefisecapp_id_table,
+ .driver = {
+ .name = "qcom_qseecom_uefisecapp",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+};
+module_auxiliary_driver(qcom_uefisecapp_driver);
+
+MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
+MODULE_DESCRIPTION("Client driver for Qualcomm SEE UEFI Secure App");
+MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/qcom_scm-legacy.c b/drivers/firmware/qcom/qcom_scm-legacy.c
index 029e6d117cb8..029e6d117cb8 100644
--- a/drivers/firmware/qcom_scm-legacy.c
+++ b/drivers/firmware/qcom/qcom_scm-legacy.c
diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom/qcom_scm-smc.c
index 16cf88acfa8e..16cf88acfa8e 100644
--- a/drivers/firmware/qcom_scm-smc.c
+++ b/drivers/firmware/qcom/qcom_scm-smc.c
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index 06fe8aca870d..520de9b5633a 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -2,24 +2,25 @@
/* Copyright (c) 2010,2015,2019 The Linux Foundation. All rights reserved.
* Copyright (C) 2015 Linaro Ltd.
*/
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
+
+#include <linux/arm-smccc.h>
+#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/cpumask.h>
-#include <linux/export.h>
#include <linux/dma-mapping.h>
+#include <linux/export.h>
+#include <linux/firmware/qcom/qcom_scm.h>
+#include <linux/init.h>
#include <linux/interconnect.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/firmware/qcom/qcom_scm.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
-#include <linux/clk.h>
+#include <linux/platform_device.h>
#include <linux/reset-controller.h>
-#include <linux/arm-smccc.h>
+#include <linux/types.h>
#include "qcom_scm.h"
@@ -55,6 +56,53 @@ struct qcom_scm_mem_map_info {
__le64 mem_size;
};
+/**
+ * struct qcom_scm_qseecom_resp - QSEECOM SCM call response.
+ * @result: Result or status of the SCM call. See &enum qcom_scm_qseecom_result.
+ * @resp_type: Type of the response. See &enum qcom_scm_qseecom_resp_type.
+ * @data: Response data. The type of this data is given in @resp_type.
+ */
+struct qcom_scm_qseecom_resp {
+ u64 result;
+ u64 resp_type;
+ u64 data;
+};
+
+enum qcom_scm_qseecom_result {
+ QSEECOM_RESULT_SUCCESS = 0,
+ QSEECOM_RESULT_INCOMPLETE = 1,
+ QSEECOM_RESULT_BLOCKED_ON_LISTENER = 2,
+ QSEECOM_RESULT_FAILURE = 0xFFFFFFFF,
+};
+
+enum qcom_scm_qseecom_resp_type {
+ QSEECOM_SCM_RES_APP_ID = 0xEE01,
+ QSEECOM_SCM_RES_QSEOS_LISTENER_ID = 0xEE02,
+};
+
+enum qcom_scm_qseecom_tz_owner {
+ QSEECOM_TZ_OWNER_SIP = 2,
+ QSEECOM_TZ_OWNER_TZ_APPS = 48,
+ QSEECOM_TZ_OWNER_QSEE_OS = 50
+};
+
+enum qcom_scm_qseecom_tz_svc {
+ QSEECOM_TZ_SVC_APP_ID_PLACEHOLDER = 0,
+ QSEECOM_TZ_SVC_APP_MGR = 1,
+ QSEECOM_TZ_SVC_INFO = 6,
+};
+
+enum qcom_scm_qseecom_tz_cmd_app {
+ QSEECOM_TZ_CMD_APP_SEND = 1,
+ QSEECOM_TZ_CMD_APP_LOOKUP = 3,
+};
+
+enum qcom_scm_qseecom_tz_cmd_info {
+ QSEECOM_TZ_CMD_INFO_VERSION = 3,
+};
+
+#define QSEECOM_MAX_APP_NAME_SIZE 64
+
/* Each bit configures cold/warm boot address for one of the 4 CPUs */
static const u8 qcom_scm_cpu_cold_bits[QCOM_SCM_BOOT_MAX_CPUS] = {
0, BIT(0), BIT(3), BIT(5)
@@ -168,6 +216,12 @@ static enum qcom_scm_convention __get_convention(void)
return qcom_scm_convention;
/*
+ * Per the "SMC calling convention specification", the 64-bit calling
+ * convention can only be used when the client is 64-bit, otherwise
+ * system will encounter the undefined behaviour.
+ */
+#if IS_ENABLED(CONFIG_ARM64)
+ /*
* Device isn't required as there is only one argument - no device
* needed to dma_map_single to secure world
*/
@@ -187,6 +241,7 @@ static enum qcom_scm_convention __get_convention(void)
forced = true;
goto found;
}
+#endif
probed_convention = SMC_CONVENTION_ARM_32;
ret = __scm_smc_call(NULL, &desc, probed_convention, &res, true);
@@ -403,6 +458,29 @@ int qcom_scm_set_remote_state(u32 state, u32 id)
}
EXPORT_SYMBOL_GPL(qcom_scm_set_remote_state);
+static int qcom_scm_disable_sdi(void)
+{
+ int ret;
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_BOOT,
+ .cmd = QCOM_SCM_BOOT_SDI_CONFIG,
+ .args[0] = 1, /* Disable watchdog debug */
+ .args[1] = 0, /* Disable SDI */
+ .arginfo = QCOM_SCM_ARGS(2),
+ .owner = ARM_SMCCC_OWNER_SIP,
+ };
+ struct qcom_scm_res res;
+
+ ret = qcom_scm_clk_enable();
+ if (ret)
+ return ret;
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
+
+ qcom_scm_clk_disable();
+
+ return ret ? : res.result[0];
+}
+
static int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
{
struct qcom_scm_desc desc = {
@@ -1321,6 +1399,340 @@ static int qcom_scm_find_dload_address(struct device *dev, u64 *addr)
return 0;
}
+#ifdef CONFIG_QCOM_QSEECOM
+
+/* Lock for QSEECOM SCM call executions */
+static DEFINE_MUTEX(qcom_scm_qseecom_call_lock);
+
+static int __qcom_scm_qseecom_call(const struct qcom_scm_desc *desc,
+ struct qcom_scm_qseecom_resp *res)
+{
+ struct qcom_scm_res scm_res = {};
+ int status;
+
+ /*
+ * QSEECOM SCM calls should not be executed concurrently. Therefore, we
+ * require the respective call lock to be held.
+ */
+ lockdep_assert_held(&qcom_scm_qseecom_call_lock);
+
+ status = qcom_scm_call(__scm->dev, desc, &scm_res);
+
+ res->result = scm_res.result[0];
+ res->resp_type = scm_res.result[1];
+ res->data = scm_res.result[2];
+
+ if (status)
+ return status;
+
+ return 0;
+}
+
+/**
+ * qcom_scm_qseecom_call() - Perform a QSEECOM SCM call.
+ * @desc: SCM call descriptor.
+ * @res: SCM call response (output).
+ *
+ * Performs the QSEECOM SCM call described by @desc, returning the response in
+ * @rsp.
+ *
+ * Return: Zero on success, nonzero on failure.
+ */
+static int qcom_scm_qseecom_call(const struct qcom_scm_desc *desc,
+ struct qcom_scm_qseecom_resp *res)
+{
+ int status;
+
+ /*
+ * Note: Multiple QSEECOM SCM calls should not be executed same time,
+ * so lock things here. This needs to be extended to callback/listener
+ * handling when support for that is implemented.
+ */
+
+ mutex_lock(&qcom_scm_qseecom_call_lock);
+ status = __qcom_scm_qseecom_call(desc, res);
+ mutex_unlock(&qcom_scm_qseecom_call_lock);
+
+ dev_dbg(__scm->dev, "%s: owner=%x, svc=%x, cmd=%x, result=%lld, type=%llx, data=%llx\n",
+ __func__, desc->owner, desc->svc, desc->cmd, res->result,
+ res->resp_type, res->data);
+
+ if (status) {
+ dev_err(__scm->dev, "qseecom: scm call failed with error %d\n", status);
+ return status;
+ }
+
+ /*
+ * TODO: Handle incomplete and blocked calls:
+ *
+ * Incomplete and blocked calls are not supported yet. Some devices
+ * and/or commands require those, some don't. Let's warn about them
+ * prominently in case someone attempts to try these commands with a
+ * device/command combination that isn't supported yet.
+ */
+ WARN_ON(res->result == QSEECOM_RESULT_INCOMPLETE);
+ WARN_ON(res->result == QSEECOM_RESULT_BLOCKED_ON_LISTENER);
+
+ return 0;
+}
+
+/**
+ * qcom_scm_qseecom_get_version() - Query the QSEECOM version.
+ * @version: Pointer where the QSEECOM version will be stored.
+ *
+ * Performs the QSEECOM SCM querying the QSEECOM version currently running in
+ * the TrustZone.
+ *
+ * Return: Zero on success, nonzero on failure.
+ */
+static int qcom_scm_qseecom_get_version(u32 *version)
+{
+ struct qcom_scm_desc desc = {};
+ struct qcom_scm_qseecom_resp res = {};
+ u32 feature = 10;
+ int ret;
+
+ desc.owner = QSEECOM_TZ_OWNER_SIP;
+ desc.svc = QSEECOM_TZ_SVC_INFO;
+ desc.cmd = QSEECOM_TZ_CMD_INFO_VERSION;
+ desc.arginfo = QCOM_SCM_ARGS(1, QCOM_SCM_VAL);
+ desc.args[0] = feature;
+
+ ret = qcom_scm_qseecom_call(&desc, &res);
+ if (ret)
+ return ret;
+
+ *version = res.result;
+ return 0;
+}
+
+/**
+ * qcom_scm_qseecom_app_get_id() - Query the app ID for a given QSEE app name.
+ * @app_name: The name of the app.
+ * @app_id: The returned app ID.
+ *
+ * Query and return the application ID of the SEE app identified by the given
+ * name. This returned ID is the unique identifier of the app required for
+ * subsequent communication.
+ *
+ * Return: Zero on success, nonzero on failure, -ENOENT if the app has not been
+ * loaded or could not be found.
+ */
+int qcom_scm_qseecom_app_get_id(const char *app_name, u32 *app_id)
+{
+ unsigned long name_buf_size = QSEECOM_MAX_APP_NAME_SIZE;
+ unsigned long app_name_len = strlen(app_name);
+ struct qcom_scm_desc desc = {};
+ struct qcom_scm_qseecom_resp res = {};
+ dma_addr_t name_buf_phys;
+ char *name_buf;
+ int status;
+
+ if (app_name_len >= name_buf_size)
+ return -EINVAL;
+
+ name_buf = kzalloc(name_buf_size, GFP_KERNEL);
+ if (!name_buf)
+ return -ENOMEM;
+
+ memcpy(name_buf, app_name, app_name_len);
+
+ name_buf_phys = dma_map_single(__scm->dev, name_buf, name_buf_size, DMA_TO_DEVICE);
+ status = dma_mapping_error(__scm->dev, name_buf_phys);
+ if (status) {
+ kfree(name_buf);
+ dev_err(__scm->dev, "qseecom: failed to map dma address\n");
+ return status;
+ }
+
+ desc.owner = QSEECOM_TZ_OWNER_QSEE_OS;
+ desc.svc = QSEECOM_TZ_SVC_APP_MGR;
+ desc.cmd = QSEECOM_TZ_CMD_APP_LOOKUP;
+ desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL);
+ desc.args[0] = name_buf_phys;
+ desc.args[1] = app_name_len;
+
+ status = qcom_scm_qseecom_call(&desc, &res);
+ dma_unmap_single(__scm->dev, name_buf_phys, name_buf_size, DMA_TO_DEVICE);
+ kfree(name_buf);
+
+ if (status)
+ return status;
+
+ if (res.result == QSEECOM_RESULT_FAILURE)
+ return -ENOENT;
+
+ if (res.result != QSEECOM_RESULT_SUCCESS)
+ return -EINVAL;
+
+ if (res.resp_type != QSEECOM_SCM_RES_APP_ID)
+ return -EINVAL;
+
+ *app_id = res.data;
+ return 0;
+}
+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_size: Size of the request buffer.
+ * @rsp: Response buffer, written to by the app (must be DMA-mappable).
+ * @rsp_size: Size of the response buffer.
+ *
+ * Sends a request to the QSEE app associated with the given ID and read back
+ * its response. The caller must provide two DMA memory regions, one for the
+ * request and one for the response, and fill out the @req region with the
+ * respective (app-specific) request data. The QSEE app reads this and returns
+ * its response in the @rsp region.
+ *
+ * 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)
+{
+ 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;
+ desc.arginfo = QCOM_SCM_ARGS(5, QCOM_SCM_VAL,
+ QCOM_SCM_RW, QCOM_SCM_VAL,
+ QCOM_SCM_RW, QCOM_SCM_VAL);
+ desc.args[0] = app_id;
+ desc.args[1] = req_phys;
+ desc.args[2] = req_size;
+ desc.args[3] = rsp_phys;
+ 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;
+
+ if (res.result != QSEECOM_RESULT_SUCCESS)
+ return -EIO;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_send);
+
+/*
+ * We do not yet support re-entrant calls via the qseecom interface. To prevent
+ + any potential issues with this, only allow validated machines for now.
+ */
+static const struct of_device_id qcom_scm_qseecom_allowlist[] = {
+ { .compatible = "lenovo,thinkpad-x13s", },
+ { }
+};
+
+static bool qcom_scm_qseecom_machine_is_allowed(void)
+{
+ struct device_node *np;
+ bool match;
+
+ np = of_find_node_by_path("/");
+ if (!np)
+ return false;
+
+ match = of_match_node(qcom_scm_qseecom_allowlist, np);
+ of_node_put(np);
+
+ return match;
+}
+
+static void qcom_scm_qseecom_free(void *data)
+{
+ struct platform_device *qseecom_dev = data;
+
+ platform_device_del(qseecom_dev);
+ platform_device_put(qseecom_dev);
+}
+
+static int qcom_scm_qseecom_init(struct qcom_scm *scm)
+{
+ struct platform_device *qseecom_dev;
+ u32 version;
+ int ret;
+
+ /*
+ * Note: We do two steps of validation here: First, we try to query the
+ * QSEECOM version as a check to see if the interface exists on this
+ * device. Second, we check against known good devices due to current
+ * driver limitations (see comment in qcom_scm_qseecom_allowlist).
+ *
+ * Note that we deliberately do the machine check after the version
+ * check so that we can log potentially supported devices. This should
+ * be safe as downstream sources indicate that the version query is
+ * neither blocking nor reentrant.
+ */
+ ret = qcom_scm_qseecom_get_version(&version);
+ if (ret)
+ return 0;
+
+ dev_info(scm->dev, "qseecom: found qseecom with version 0x%x\n", version);
+
+ if (!qcom_scm_qseecom_machine_is_allowed()) {
+ dev_info(scm->dev, "qseecom: untested machine, skipping\n");
+ return 0;
+ }
+
+ /*
+ * Set up QSEECOM interface device. All application clients will be
+ * set up and managed by the corresponding driver for it.
+ */
+ qseecom_dev = platform_device_alloc("qcom_qseecom", -1);
+ if (!qseecom_dev)
+ return -ENOMEM;
+
+ qseecom_dev->dev.parent = scm->dev;
+
+ ret = platform_device_add(qseecom_dev);
+ if (ret) {
+ platform_device_put(qseecom_dev);
+ return ret;
+ }
+
+ return devm_add_action_or_reset(scm->dev, qcom_scm_qseecom_free, qseecom_dev);
+}
+
+#else /* CONFIG_QCOM_QSEECOM */
+
+static int qcom_scm_qseecom_init(struct qcom_scm *scm)
+{
+ return 0;
+}
+
+#endif /* CONFIG_QCOM_QSEECOM */
+
/**
* qcom_scm_is_available() - Checks if SCM is available
*/
@@ -1468,6 +1880,26 @@ static int qcom_scm_probe(struct platform_device *pdev)
if (download_mode)
qcom_scm_set_download_mode(true);
+
+ /*
+ * Disable SDI if indicated by DT that it is enabled by default.
+ */
+ if (of_property_read_bool(pdev->dev.of_node, "qcom,sdi-enabled"))
+ qcom_scm_disable_sdi();
+
+ /*
+ * Initialize the QSEECOM interface.
+ *
+ * Note: QSEECOM is fairly self-contained and this only adds the
+ * interface device (the driver of which does most of the heavy
+ * lifting). So any errors returned here should be either -ENOMEM or
+ * -EINVAL (with the latter only in case there's a bug in our code).
+ * This means that there is no need to bring down the whole SCM driver.
+ * Just log the error instead and let SCM live.
+ */
+ ret = qcom_scm_qseecom_init(scm);
+ WARN(ret < 0, "failed to initialize qseecom: %d\n", ret);
+
return 0;
}
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h
index e6e512bd57d1..4532907e8489 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom/qcom_scm.h
@@ -4,6 +4,8 @@
#ifndef __QCOM_SCM_INT_H
#define __QCOM_SCM_INT_H
+struct device;
+
enum qcom_scm_convention {
SMC_CONVENTION_UNKNOWN,
SMC_CONVENTION_LEGACY,
@@ -64,22 +66,22 @@ int qcom_scm_wait_for_wq_completion(u32 wq_ctx);
int scm_get_wq_ctx(u32 *wq_ctx, u32 *flags, u32 *more_pending);
#define SCM_SMC_FNID(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF))
-extern int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
- enum qcom_scm_convention qcom_convention,
- struct qcom_scm_res *res, bool atomic);
+int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
+ enum qcom_scm_convention qcom_convention,
+ struct qcom_scm_res *res, bool atomic);
#define scm_smc_call(dev, desc, res, atomic) \
__scm_smc_call((dev), (desc), qcom_scm_convention, (res), (atomic))
#define SCM_LEGACY_FNID(s, c) (((s) << 10) | ((c) & 0x3ff))
-extern int scm_legacy_call_atomic(struct device *dev,
- const struct qcom_scm_desc *desc,
- struct qcom_scm_res *res);
-extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
+int scm_legacy_call_atomic(struct device *dev, const struct qcom_scm_desc *desc,
struct qcom_scm_res *res);
+int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
+ struct qcom_scm_res *res);
#define QCOM_SCM_SVC_BOOT 0x01
#define QCOM_SCM_BOOT_SET_ADDR 0x01
#define QCOM_SCM_BOOT_TERMINATE_PC 0x02
+#define QCOM_SCM_BOOT_SDI_CONFIG 0x09
#define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10
#define QCOM_SCM_BOOT_SET_ADDR_MC 0x11
#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a
diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index a69399a6b7c0..1448f61173b3 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -211,7 +211,7 @@ static void fw_cfg_io_cleanup(void)
/* arch-specific ctrl & data register offsets are not available in ACPI, DT */
#if !(defined(FW_CFG_CTRL_OFF) && defined(FW_CFG_DATA_OFF))
-# if (defined(CONFIG_ARM) || defined(CONFIG_ARM64))
+# if (defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV))
# define FW_CFG_CTRL_OFF 0x08
# define FW_CFG_DATA_OFF 0x00
# define FW_CFG_DMA_OFF 0x10
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index f66efaa5196d..4cd290a60fba 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -378,6 +378,7 @@ EXPORT_SYMBOL_GPL(rpi_firmware_get);
/**
* devm_rpi_firmware_get - Get pointer to rpi_firmware structure.
+ * @dev: The firmware device structure
* @firmware_node: Pointer to the firmware Device Tree node.
*
* Returns NULL is the firmware device is not ready.
diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c
index 6dfe3d34109e..bbcdd9fed3fb 100644
--- a/drivers/firmware/tegra/bpmp-debugfs.c
+++ b/drivers/firmware/tegra/bpmp-debugfs.c
@@ -610,7 +610,7 @@ static int debugfs_show(struct seq_file *m, void *p)
}
len = strlen(filename);
- strncpy(namevirt, filename, namesize);
+ strscpy_pad(namevirt, filename, namesize);
err = mrq_debugfs_read(bpmp, namephys, len, dataphys, datasize,
&nbytes);
@@ -661,7 +661,7 @@ static ssize_t debugfs_store(struct file *file, const char __user *buf,
}
len = strlen(filename);
- strncpy(namevirt, filename, namesize);
+ strscpy_pad(namevirt, filename, namesize);
if (copy_from_user(datavirt, buf, count)) {
err = -EFAULT;
diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index 51d062e0c3f1..c1590d3aa9cb 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -313,6 +313,8 @@ static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
return __tegra_bpmp_channel_write(channel, mrq, flags, data, size);
}
+static int __maybe_unused tegra_bpmp_resume(struct device *dev);
+
int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
struct tegra_bpmp_message *msg)
{
@@ -325,6 +327,14 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
if (!tegra_bpmp_message_valid(msg))
return -EINVAL;
+ if (bpmp->suspended) {
+ /* Reset BPMP IPC channels during resume based on flags passed */
+ if (msg->flags & TEGRA_BPMP_MESSAGE_RESET)
+ tegra_bpmp_resume(bpmp->dev);
+ else
+ return -EAGAIN;
+ }
+
channel = bpmp->tx_channel;
spin_lock(&bpmp->atomic_tx_lock);
@@ -364,6 +374,14 @@ int tegra_bpmp_transfer(struct tegra_bpmp *bpmp,
if (!tegra_bpmp_message_valid(msg))
return -EINVAL;
+ if (bpmp->suspended) {
+ /* Reset BPMP IPC channels during resume based on flags passed */
+ if (msg->flags & TEGRA_BPMP_MESSAGE_RESET)
+ tegra_bpmp_resume(bpmp->dev);
+ else
+ return -EAGAIN;
+ }
+
channel = tegra_bpmp_write_threaded(bpmp, msg->mrq, msg->tx.data,
msg->tx.size);
if (IS_ERR(channel))
@@ -796,10 +814,21 @@ deinit:
return err;
}
+static int __maybe_unused tegra_bpmp_suspend(struct device *dev)
+{
+ struct tegra_bpmp *bpmp = dev_get_drvdata(dev);
+
+ bpmp->suspended = true;
+
+ return 0;
+}
+
static int __maybe_unused tegra_bpmp_resume(struct device *dev)
{
struct tegra_bpmp *bpmp = dev_get_drvdata(dev);
+ bpmp->suspended = false;
+
if (bpmp->soc->ops->resume)
return bpmp->soc->ops->resume(bpmp);
else
@@ -807,6 +836,7 @@ static int __maybe_unused tegra_bpmp_resume(struct device *dev)
}
static const struct dev_pm_ops tegra_bpmp_pm_ops = {
+ .suspend_noirq = tegra_bpmp_suspend,
.resume_noirq = tegra_bpmp_resume,
};
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 26a37f47f4ca..7041befc756a 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -16,7 +16,10 @@
#include <linux/kernel.h>
#include <linux/mailbox_client.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/semaphore.h>
#include <linux/slab.h>
#include <linux/soc/ti/ti-msgmgr.h>
@@ -190,19 +193,6 @@ static int ti_sci_debugfs_create(struct platform_device *pdev,
return 0;
}
-/**
- * ti_sci_debugfs_destroy() - clean up log debug file
- * @pdev: platform device pointer
- * @info: Pointer to SCI entity information
- */
-static void ti_sci_debugfs_destroy(struct platform_device *pdev,
- struct ti_sci_info *info)
-{
- if (IS_ERR(info->debug_region))
- return;
-
- debugfs_remove(info->d);
-}
#else /* CONFIG_DEBUG_FS */
static inline int ti_sci_debugfs_create(struct platform_device *dev,
struct ti_sci_info *info)
@@ -485,7 +475,7 @@ static int ti_sci_cmd_get_revision(struct ti_sci_info *info)
ver->abi_major = rev_info->abi_major;
ver->abi_minor = rev_info->abi_minor;
ver->firmware_revision = rev_info->firmware_revision;
- strncpy(ver->firmware_description, rev_info->firmware_description,
+ strscpy(ver->firmware_description, rev_info->firmware_description,
sizeof(ver->firmware_description));
fail:
@@ -2886,7 +2876,6 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
const struct ti_sci_handle *ti_sci_get_handle(struct device *dev)
{
struct device_node *ti_sci_np;
- struct list_head *p;
struct ti_sci_handle *handle = NULL;
struct ti_sci_info *info;
@@ -2901,8 +2890,7 @@ const struct ti_sci_handle *ti_sci_get_handle(struct device *dev)
}
mutex_lock(&ti_sci_list_mutex);
- list_for_each(p, &ti_sci_list) {
- info = list_entry(p, struct ti_sci_info, node);
+ list_for_each_entry(info, &ti_sci_list, node) {
if (ti_sci_np == info->dev->of_node) {
handle = &info->handle;
info->users++;
@@ -3012,7 +3000,6 @@ const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np,
struct ti_sci_handle *handle = NULL;
struct device_node *ti_sci_np;
struct ti_sci_info *info;
- struct list_head *p;
if (!np) {
pr_err("I need a device pointer\n");
@@ -3024,8 +3011,7 @@ const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np,
return ERR_PTR(-ENODEV);
mutex_lock(&ti_sci_list_mutex);
- list_for_each(p, &ti_sci_list) {
- info = list_entry(p, struct ti_sci_info, node);
+ list_for_each_entry(info, &ti_sci_list, node) {
if (ti_sci_np == info->dev->of_node) {
handle = &info->handle;
info->users++;
@@ -3310,7 +3296,6 @@ MODULE_DEVICE_TABLE(of, ti_sci_of_match);
static int ti_sci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- const struct of_device_id *of_id;
const struct ti_sci_desc *desc;
struct ti_sci_xfer *xfer;
struct ti_sci_info *info = NULL;
@@ -3321,12 +3306,7 @@ static int ti_sci_probe(struct platform_device *pdev)
int reboot = 0;
u32 h_id;
- of_id = of_match_device(ti_sci_of_match, dev);
- if (!of_id) {
- dev_err(dev, "OF data missing\n");
- return -EINVAL;
- }
- desc = of_id->data;
+ desc = device_get_match_data(dev);
info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
if (!info)
@@ -3449,43 +3429,12 @@ out:
return ret;
}
-static int ti_sci_remove(struct platform_device *pdev)
-{
- struct ti_sci_info *info;
- struct device *dev = &pdev->dev;
- int ret = 0;
-
- of_platform_depopulate(dev);
-
- info = platform_get_drvdata(pdev);
-
- if (info->nb.notifier_call)
- unregister_restart_handler(&info->nb);
-
- mutex_lock(&ti_sci_list_mutex);
- if (info->users)
- ret = -EBUSY;
- else
- list_del(&info->node);
- mutex_unlock(&ti_sci_list_mutex);
-
- if (!ret) {
- ti_sci_debugfs_destroy(pdev, info);
-
- /* Safe to free channels since no more users */
- mbox_free_channel(info->chan_tx);
- mbox_free_channel(info->chan_rx);
- }
-
- return ret;
-}
-
static struct platform_driver ti_sci_driver = {
.probe = ti_sci_probe,
- .remove = ti_sci_remove,
.driver = {
.name = "ti-sci",
.of_match_table = of_match_ptr(ti_sci_of_match),
+ .suppress_bind_attrs = true,
},
};
module_platform_driver(ti_sci_driver);
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index 4cc1ac7f76ed..b0d22d4455d9 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -226,7 +226,6 @@ static int do_feature_check_call(const u32 api_id)
return ret;
}
-EXPORT_SYMBOL_GPL(zynqmp_pm_feature);
/**
* zynqmp_pm_feature() - Check whether given feature is supported or not and
@@ -246,6 +245,7 @@ int zynqmp_pm_feature(const u32 api_id)
return ret;
}
+EXPORT_SYMBOL_GPL(zynqmp_pm_feature);
/**
* zynqmp_pm_is_function_supported() - Check whether given IOCTL/QUERY function
diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c
index aa758426c22b..578663503297 100644
--- a/drivers/fpga/altera-hps2fpga.c
+++ b/drivers/fpga/altera-hps2fpga.c
@@ -24,7 +24,8 @@
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
-#include <linux/of_platform.h>
+#include <linux/of.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/spinlock.h>
@@ -127,18 +128,11 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct altera_hps2fpga_data *priv;
- const struct of_device_id *of_id;
struct fpga_bridge *br;
u32 enable;
int ret;
- of_id = of_match_device(altera_fpga_of_match, dev);
- if (!of_id) {
- dev_err(dev, "failed to match device\n");
- return -ENODEV;
- }
-
- priv = (struct altera_hps2fpga_data *)of_id->data;
+ priv = (struct altera_hps2fpga_data *)device_get_match_data(dev);
priv->bridge_reset = of_reset_control_get_exclusive_by_index(dev->of_node,
0);
diff --git a/drivers/fpga/altera-ps-spi.c b/drivers/fpga/altera-ps-spi.c
index 5e1e009dba89..740980e7cef8 100644
--- a/drivers/fpga/altera-ps-spi.c
+++ b/drivers/fpga/altera-ps-spi.c
@@ -18,8 +18,7 @@
#include <linux/fpga/fpga-mgr.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
-#include <linux/of_gpio.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/spi/spi.h>
#include <linux/sizes.h>
@@ -72,12 +71,6 @@ static struct altera_ps_data a10_data = {
.t_st2ck_us = 10, /* min(t_ST2CK) */
};
-/* Array index is enum altera_ps_devtype */
-static const struct altera_ps_data *altera_ps_data_map[] = {
- &c5_data,
- &a10_data,
-};
-
static const struct of_device_id of_ef_match[] = {
{ .compatible = "altr,fpga-passive-serial", .data = &c5_data },
{ .compatible = "altr,fpga-arria10-passive-serial", .data = &a10_data },
@@ -237,43 +230,16 @@ static const struct fpga_manager_ops altera_ps_ops = {
.write_complete = altera_ps_write_complete,
};
-static const struct altera_ps_data *id_to_data(const struct spi_device_id *id)
-{
- kernel_ulong_t devtype = id->driver_data;
- const struct altera_ps_data *data;
-
- /* someone added a altera_ps_devtype without adding to the map array */
- if (devtype >= ARRAY_SIZE(altera_ps_data_map))
- return NULL;
-
- data = altera_ps_data_map[devtype];
- if (!data || data->devtype != devtype)
- return NULL;
-
- return data;
-}
-
static int altera_ps_probe(struct spi_device *spi)
{
struct altera_ps_conf *conf;
- const struct of_device_id *of_id;
struct fpga_manager *mgr;
conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL);
if (!conf)
return -ENOMEM;
- if (spi->dev.of_node) {
- of_id = of_match_device(of_ef_match, &spi->dev);
- if (!of_id)
- return -ENODEV;
- conf->data = of_id->data;
- } else {
- conf->data = id_to_data(spi_get_device_id(spi));
- if (!conf->data)
- return -ENODEV;
- }
-
+ conf->data = spi_get_device_match_data(spi);
conf->spi = spi;
conf->config = devm_gpiod_get(&spi->dev, "nconfig", GPIOD_OUT_LOW);
if (IS_ERR(conf->config)) {
@@ -308,9 +274,9 @@ static int altera_ps_probe(struct spi_device *spi)
}
static const struct spi_device_id altera_ps_spi_ids[] = {
- { "cyclone-ps-spi", CYCLONE5 },
- { "fpga-passive-serial", CYCLONE5 },
- { "fpga-arria10-passive-serial", ARRIA10 },
+ { "cyclone-ps-spi", (uintptr_t)&c5_data },
+ { "fpga-passive-serial", (uintptr_t)&c5_data },
+ { "fpga-arria10-passive-serial", (uintptr_t)&a10_data },
{}
};
MODULE_DEVICE_TABLE(spi, altera_ps_spi_ids);
@@ -319,7 +285,7 @@ static struct spi_driver altera_ps_driver = {
.driver = {
.name = "altera-ps-spi",
.owner = THIS_MODULE,
- .of_match_table = of_match_ptr(of_ef_match),
+ .of_match_table = of_ef_match,
},
.id_table = altera_ps_spi_ids,
.probe = altera_ps_probe,
diff --git a/drivers/fpga/tests/Kconfig b/drivers/fpga/tests/Kconfig
index e4a64815f16d..d4e55204c092 100644
--- a/drivers/fpga/tests/Kconfig
+++ b/drivers/fpga/tests/Kconfig
@@ -1,6 +1,6 @@
config FPGA_KUNIT_TESTS
- tristate "KUnit test for the FPGA subsystem" if !KUNIT_ALL_TESTS
- depends on FPGA && FPGA_REGION && FPGA_BRIDGE && KUNIT=y
+ bool "KUnit test for the FPGA subsystem" if !KUNIT_ALL_TESTS
+ depends on FPGA=y && FPGA_REGION=y && FPGA_BRIDGE=y && KUNIT=y && MODULES=n
default KUNIT_ALL_TESTS
help
This builds unit tests for the FPGA subsystem
diff --git a/drivers/fpga/tests/fpga-region-test.c b/drivers/fpga/tests/fpga-region-test.c
index 9f9d50ee7871..baab07e3fc59 100644
--- a/drivers/fpga/tests/fpga-region-test.c
+++ b/drivers/fpga/tests/fpga-region-test.c
@@ -93,6 +93,8 @@ static void fpga_region_test_class_find(struct kunit *test)
region = fpga_region_class_find(NULL, &ctx->region_pdev->dev, fake_region_match);
KUNIT_EXPECT_PTR_EQ(test, region, ctx->region);
+
+ put_device(&region->dev);
}
/*
diff --git a/drivers/fpga/versal-fpga.c b/drivers/fpga/versal-fpga.c
index e1601b3a345b..3710e8f01be2 100644
--- a/drivers/fpga/versal-fpga.c
+++ b/drivers/fpga/versal-fpga.c
@@ -48,7 +48,7 @@ static int versal_fpga_probe(struct platform_device *pdev)
struct fpga_manager *mgr;
int ret;
- ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44));
if (ret < 0) {
dev_err(dev, "no usable DMA configuration\n");
return ret;
diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c
index 208d9560f56d..68835896f180 100644
--- a/drivers/fpga/xilinx-pr-decoupler.c
+++ b/drivers/fpga/xilinx-pr-decoupler.c
@@ -10,8 +10,10 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/kernel.h>
-#include <linux/of_device.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/fpga/fpga-bridge.h>
#define CTRL_CMD_DECOUPLE BIT(0)
@@ -81,7 +83,6 @@ static const struct fpga_bridge_ops xlnx_pr_decoupler_br_ops = {
.enable_show = xlnx_pr_decoupler_enable_show,
};
-#ifdef CONFIG_OF
static const struct xlnx_config_data decoupler_config = {
.name = "Xilinx PR Decoupler",
};
@@ -100,11 +101,9 @@ static const struct of_device_id xlnx_pr_decoupler_of_match[] = {
{},
};
MODULE_DEVICE_TABLE(of, xlnx_pr_decoupler_of_match);
-#endif
static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
struct xlnx_pr_decoupler_data *priv;
struct fpga_bridge *br;
int err;
@@ -113,13 +112,7 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- if (np) {
- const struct of_device_id *match;
-
- match = of_match_node(xlnx_pr_decoupler_of_match, np);
- if (match && match->data)
- priv->ipconfig = match->data;
- }
+ priv->ipconfig = device_get_match_data(&pdev->dev);
priv->io_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->io_base))
@@ -174,7 +167,7 @@ static struct platform_driver xlnx_pr_decoupler_driver = {
.remove = xlnx_pr_decoupler_remove,
.driver = {
.name = "xlnx_pr_decoupler",
- .of_match_table = of_match_ptr(xlnx_pr_decoupler_of_match),
+ .of_match_table = xlnx_pr_decoupler_of_match,
},
};
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 673bafb8be58..b3a133ed31ee 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1312,9 +1312,9 @@ config GPIO_KEMPLD
config GPIO_LJCA
tristate "INTEL La Jolla Cove Adapter GPIO support"
- depends on MFD_LJCA
+ depends on USB_LJCA
select GPIOLIB_IRQCHIP
- default MFD_LJCA
+ default USB_LJCA
help
Select this option to enable GPIO driver for the INTEL
La Jolla Cove Adapter (LJCA) board.
@@ -1790,9 +1790,11 @@ config GPIO_LATCH
connected to other GPIOs.
config GPIO_MOCKUP
- tristate "GPIO Testing Driver"
+ tristate "GPIO Testing Driver (DEPRECATED)"
select IRQ_SIM
help
+ This module is DEPRECATED. Please consider using gpio-sim instead.
+
This enables GPIO Testing driver, which provides a way to test GPIO
subsystem through sysfs (or char device) and debugfs.
User could use it through the script in
diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c
index 54d7c450c596..c2edfbb231fc 100644
--- a/drivers/gpio/gpio-altera.c
+++ b/drivers/gpio/gpio-altera.c
@@ -317,13 +317,11 @@ skip_irq:
return 0;
}
-static int altera_gpio_remove(struct platform_device *pdev)
+static void altera_gpio_remove(struct platform_device *pdev)
{
struct altera_gpio_chip *altera_gc = platform_get_drvdata(pdev);
of_mm_gpiochip_remove(&altera_gc->mmchip);
-
- return 0;
}
static const struct of_device_id altera_gpio_of_match[] = {
@@ -338,7 +336,7 @@ static struct platform_driver altera_gpio_driver = {
.of_match_table = altera_gpio_of_match,
},
.probe = altera_gpio_probe,
- .remove = altera_gpio_remove,
+ .remove_new = altera_gpio_remove,
};
static int __init altera_gpio_init(void)
diff --git a/drivers/gpio/gpio-amdpt.c b/drivers/gpio/gpio-amdpt.c
index 07c6d090058d..0a2ea9db4682 100644
--- a/drivers/gpio/gpio-amdpt.c
+++ b/drivers/gpio/gpio-amdpt.c
@@ -122,13 +122,11 @@ static int pt_gpio_probe(struct platform_device *pdev)
return ret;
}
-static int pt_gpio_remove(struct platform_device *pdev)
+static void pt_gpio_remove(struct platform_device *pdev)
{
struct pt_gpio_chip *pt_gpio = platform_get_drvdata(pdev);
gpiochip_remove(&pt_gpio->gc);
-
- return 0;
}
static const struct acpi_device_id pt_gpio_acpi_match[] = {
@@ -145,7 +143,7 @@ static struct platform_driver pt_gpio_driver = {
.acpi_match_table = ACPI_PTR(pt_gpio_acpi_match),
},
.probe = pt_gpio_probe,
- .remove = pt_gpio_remove,
+ .remove_new = pt_gpio_remove,
};
module_platform_driver(pt_gpio_driver);
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index 58f107194fda..04c03402db6d 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -750,12 +750,12 @@ static int aspeed_gpio_request(struct gpio_chip *chip, unsigned int offset)
if (!have_gpio(gpiochip_get_data(chip), offset))
return -ENODEV;
- return pinctrl_gpio_request(chip->base + offset);
+ return pinctrl_gpio_request(chip, offset);
}
static void aspeed_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
- pinctrl_gpio_free(chip->base + offset);
+ pinctrl_gpio_free(chip, offset);
}
static int usecs_to_cycles(struct aspeed_gpio *gpio, unsigned long usecs,
@@ -973,7 +973,7 @@ static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
else if (param == PIN_CONFIG_BIAS_DISABLE ||
param == PIN_CONFIG_BIAS_PULL_DOWN ||
param == PIN_CONFIG_DRIVE_STRENGTH)
- return pinctrl_gpio_set_config(chip->base + offset, config);
+ return pinctrl_gpio_set_config(chip, offset, config);
else if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN ||
param == PIN_CONFIG_DRIVE_OPEN_SOURCE)
/* Return -ENOTSUPP to trigger emulation, as per datasheet */
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c
index bccdbfd5ec80..a789af4a5c85 100644
--- a/drivers/gpio/gpio-brcmstb.c
+++ b/drivers/gpio/gpio-brcmstb.c
@@ -371,7 +371,7 @@ static int brcmstb_gpio_sanity_check_banks(struct device *dev,
}
}
-static int brcmstb_gpio_remove(struct platform_device *pdev)
+static void brcmstb_gpio_remove(struct platform_device *pdev)
{
struct brcmstb_gpio_priv *priv = platform_get_drvdata(pdev);
struct brcmstb_gpio_bank *bank;
@@ -395,8 +395,6 @@ static int brcmstb_gpio_remove(struct platform_device *pdev)
*/
list_for_each_entry(bank, &priv->bank_list, node)
gpiochip_remove(&bank->gc);
-
- return 0;
}
static int brcmstb_gpio_of_xlate(struct gpio_chip *gc,
@@ -757,7 +755,7 @@ static struct platform_driver brcmstb_gpio_driver = {
.pm = &brcmstb_gpio_pm_ops,
},
.probe = brcmstb_gpio_probe,
- .remove = brcmstb_gpio_remove,
+ .remove_new = brcmstb_gpio_remove,
.shutdown = brcmstb_gpio_shutdown,
};
module_platform_driver(brcmstb_gpio_driver);
diff --git a/drivers/gpio/gpio-cadence.c b/drivers/gpio/gpio-cadence.c
index 3720b90cad10..6a439cf78459 100644
--- a/drivers/gpio/gpio-cadence.c
+++ b/drivers/gpio/gpio-cadence.c
@@ -268,14 +268,12 @@ err_revert_dir:
return ret;
}
-static int cdns_gpio_remove(struct platform_device *pdev)
+static void cdns_gpio_remove(struct platform_device *pdev)
{
struct cdns_gpio_chip *cgpio = platform_get_drvdata(pdev);
iowrite32(cgpio->bypass_orig, cgpio->regs + CDNS_GPIO_BYPASS_MODE);
clk_disable_unprepare(cgpio->pclk);
-
- return 0;
}
static const struct of_device_id cdns_of_ids[] = {
@@ -290,7 +288,7 @@ static struct platform_driver cdns_gpio_driver = {
.of_match_table = cdns_of_ids,
},
.probe = cdns_gpio_probe,
- .remove = cdns_gpio_remove,
+ .remove_new = cdns_gpio_remove,
};
module_platform_driver(cdns_gpio_driver);
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index 8db5717bdabe..bb499e362912 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -16,10 +16,10 @@
#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/platform_data/gpio-davinci.h>
+#include <linux/property.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/spinlock.h>
#include <linux/pm_runtime.h>
@@ -486,7 +486,6 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
struct davinci_gpio_platform_data *pdata = dev->platform_data;
struct davinci_gpio_regs __iomem *g;
struct irq_domain *irq_domain = NULL;
- const struct of_device_id *match;
struct irq_chip *irq_chip;
struct davinci_gpio_irq_data *irqdata;
gpio_get_irq_chip_cb_t gpio_get_irq_chip;
@@ -495,10 +494,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
* Use davinci_gpio_get_irq_chip by default to handle non DT cases
*/
gpio_get_irq_chip = davinci_gpio_get_irq_chip;
- match = of_match_device(of_match_ptr(davinci_gpio_ids),
- dev);
- if (match)
- gpio_get_irq_chip = (gpio_get_irq_chip_cb_t)match->data;
+ if (dev->of_node)
+ gpio_get_irq_chip = (gpio_get_irq_chip_cb_t)device_get_match_data(dev);
ngpio = pdata->ngpio;
diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c
index 71fa437b491f..7ead1f51128a 100644
--- a/drivers/gpio/gpio-dln2.c
+++ b/drivers/gpio/gpio-dln2.c
@@ -504,17 +504,15 @@ static int dln2_gpio_probe(struct platform_device *pdev)
return 0;
}
-static int dln2_gpio_remove(struct platform_device *pdev)
+static void dln2_gpio_remove(struct platform_device *pdev)
{
dln2_unregister_event_cb(pdev, DLN2_GPIO_CONDITION_MET_EV);
-
- return 0;
}
static struct platform_driver dln2_gpio_driver = {
.driver.name = "dln2-gpio",
.probe = dln2_gpio_probe,
- .remove = dln2_gpio_remove,
+ .remove_new = dln2_gpio_remove,
};
module_platform_driver(dln2_gpio_driver);
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index c22fcaa44a61..4a4f61bf6c58 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -21,7 +21,6 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include "gpiolib.h"
#include "gpiolib-acpi.h"
#define GPIO_SWPORTA_DR 0x00
diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c
index 5320cf1de89c..be7f2fa5aa7b 100644
--- a/drivers/gpio/gpio-eic-sprd.c
+++ b/drivers/gpio/gpio-eic-sprd.c
@@ -9,6 +9,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
@@ -91,12 +92,20 @@ enum sprd_eic_type {
struct sprd_eic {
struct gpio_chip chip;
+ struct notifier_block irq_nb;
void __iomem *base[SPRD_EIC_MAX_BANK];
enum sprd_eic_type type;
spinlock_t lock;
int irq;
};
+static ATOMIC_NOTIFIER_HEAD(sprd_eic_irq_notifier);
+
+static struct sprd_eic *to_sprd_eic(struct notifier_block *nb)
+{
+ return container_of(nb, struct sprd_eic, irq_nb);
+}
+
struct sprd_eic_variant_data {
enum sprd_eic_type type;
u32 num_eics;
@@ -494,13 +503,6 @@ retry:
sprd_eic_irq_unmask(data);
}
-static int sprd_eic_match_chip_by_type(struct gpio_chip *chip, void *data)
-{
- enum sprd_eic_type type = *(enum sprd_eic_type *)data;
-
- return !strcmp(chip->label, sprd_eic_label_name[type]);
-}
-
static void sprd_eic_handle_one_type(struct gpio_chip *chip)
{
struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
@@ -546,27 +548,29 @@ static void sprd_eic_handle_one_type(struct gpio_chip *chip)
static void sprd_eic_irq_handler(struct irq_desc *desc)
{
struct irq_chip *ic = irq_desc_get_chip(desc);
- struct gpio_chip *chip;
- enum sprd_eic_type type;
chained_irq_enter(ic, desc);
/*
* Since the digital-chip EIC 4 sub-modules (debounce, latch, async
- * and sync) share one same interrupt line, we should iterate each
- * EIC module to check if there are EIC interrupts were triggered.
+ * and sync) share one same interrupt line, we should notify all of
+ * them to let them check if there are EIC interrupts were triggered.
*/
- for (type = SPRD_EIC_DEBOUNCE; type < SPRD_EIC_MAX; type++) {
- chip = gpiochip_find(&type, sprd_eic_match_chip_by_type);
- if (!chip)
- continue;
-
- sprd_eic_handle_one_type(chip);
- }
+ atomic_notifier_call_chain(&sprd_eic_irq_notifier, 0, NULL);
chained_irq_exit(ic, desc);
}
+static int sprd_eic_irq_notify(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct sprd_eic *sprd_eic = to_sprd_eic(nb);
+
+ sprd_eic_handle_one_type(&sprd_eic->chip);
+
+ return NOTIFY_OK;
+}
+
static const struct irq_chip sprd_eic_irq = {
.name = "sprd-eic",
.irq_ack = sprd_eic_irq_ack,
@@ -576,21 +580,30 @@ static const struct irq_chip sprd_eic_irq = {
.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE,
GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
+
+static void sprd_eic_unregister_notifier(void *data)
+{
+ struct notifier_block *nb = data;
+
+ atomic_notifier_chain_unregister(&sprd_eic_irq_notifier, nb);
+}
+
static int sprd_eic_probe(struct platform_device *pdev)
{
const struct sprd_eic_variant_data *pdata;
+ struct device *dev = &pdev->dev;
struct gpio_irq_chip *irq;
struct sprd_eic *sprd_eic;
struct resource *res;
int ret, i;
- pdata = of_device_get_match_data(&pdev->dev);
+ pdata = of_device_get_match_data(dev);
if (!pdata) {
- dev_err(&pdev->dev, "No matching driver data found.\n");
+ dev_err(dev, "No matching driver data found.\n");
return -EINVAL;
}
- sprd_eic = devm_kzalloc(&pdev->dev, sizeof(*sprd_eic), GFP_KERNEL);
+ sprd_eic = devm_kzalloc(dev, sizeof(*sprd_eic), GFP_KERNEL);
if (!sprd_eic)
return -ENOMEM;
@@ -612,7 +625,7 @@ static int sprd_eic_probe(struct platform_device *pdev)
if (!res)
break;
- sprd_eic->base[i] = devm_ioremap_resource(&pdev->dev, res);
+ sprd_eic->base[i] = devm_ioremap_resource(dev, res);
if (IS_ERR(sprd_eic->base[i]))
return PTR_ERR(sprd_eic->base[i]);
}
@@ -620,7 +633,7 @@ static int sprd_eic_probe(struct platform_device *pdev)
sprd_eic->chip.label = sprd_eic_label_name[sprd_eic->type];
sprd_eic->chip.ngpio = pdata->num_eics;
sprd_eic->chip.base = -1;
- sprd_eic->chip.parent = &pdev->dev;
+ sprd_eic->chip.parent = dev;
sprd_eic->chip.direction_input = sprd_eic_direction_input;
switch (sprd_eic->type) {
case SPRD_EIC_DEBOUNCE:
@@ -647,13 +660,21 @@ static int sprd_eic_probe(struct platform_device *pdev)
irq->num_parents = 1;
irq->parents = &sprd_eic->irq;
- ret = devm_gpiochip_add_data(&pdev->dev, &sprd_eic->chip, sprd_eic);
+ ret = devm_gpiochip_add_data(dev, &sprd_eic->chip, sprd_eic);
if (ret < 0) {
- dev_err(&pdev->dev, "Could not register gpiochip %d.\n", ret);
+ dev_err(dev, "Could not register gpiochip %d.\n", ret);
return ret;
}
- return 0;
+ sprd_eic->irq_nb.notifier_call = sprd_eic_irq_notify;
+ ret = atomic_notifier_chain_register(&sprd_eic_irq_notifier,
+ &sprd_eic->irq_nb);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register with the interrupt notifier");
+
+ return devm_add_action_or_reset(dev, sprd_eic_unregister_notifier,
+ &sprd_eic->irq_nb);
}
static const struct of_device_id sprd_eic_of_match[] = {
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index 858e6ebbb584..6c862c572322 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -227,14 +227,9 @@ static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
}
-static int em_gio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_gpio_request(chip->base + offset);
-}
-
static void em_gio_free(struct gpio_chip *chip, unsigned offset)
{
- pinctrl_gpio_free(chip->base + offset);
+ pinctrl_gpio_free(chip, offset);
/* Set the GPIO as an input to ensure that the next GPIO request won't
* drive the GPIO pin as an output.
@@ -311,7 +306,7 @@ static int em_gio_probe(struct platform_device *pdev)
gpio_chip->direction_output = em_gio_direction_output;
gpio_chip->set = em_gio_set;
gpio_chip->to_irq = em_gio_to_irq;
- gpio_chip->request = em_gio_request;
+ gpio_chip->request = pinctrl_gpio_request;
gpio_chip->free = em_gio_free;
gpio_chip->label = name;
gpio_chip->parent = dev;
diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c
index f54ca5a1775e..3875fd940ccb 100644
--- a/drivers/gpio/gpio-f7188x.c
+++ b/drivers/gpio/gpio-f7188x.c
@@ -163,7 +163,7 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value);
static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned long config);
-#define F7188X_GPIO_BANK(_base, _ngpio, _regbase, _label) \
+#define F7188X_GPIO_BANK(_ngpio, _regbase, _label) \
{ \
.chip = { \
.label = _label, \
@@ -174,7 +174,7 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
.direction_output = f7188x_gpio_direction_out, \
.set = f7188x_gpio_set, \
.set_config = f7188x_gpio_set_config, \
- .base = _base, \
+ .base = -1, \
.ngpio = _ngpio, \
.can_sleep = true, \
}, \
@@ -191,98 +191,98 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
#define f7188x_gpio_data_single(type) ((type) == nct6126d)
static struct f7188x_gpio_bank f71869_gpio_bank[] = {
- F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"),
- F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
- F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
- F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
- F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
- F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"),
- F7188X_GPIO_BANK(60, 6, 0x90, DRVNAME "-6"),
+ F7188X_GPIO_BANK(6, 0xF0, DRVNAME "-0"),
+ F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"),
+ F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
+ F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"),
+ F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"),
+ F7188X_GPIO_BANK(5, 0xA0, DRVNAME "-5"),
+ F7188X_GPIO_BANK(6, 0x90, DRVNAME "-6"),
};
static struct f7188x_gpio_bank f71869a_gpio_bank[] = {
- F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"),
- F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
- F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
- F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
- F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
- F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"),
- F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"),
- F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"),
+ F7188X_GPIO_BANK(6, 0xF0, DRVNAME "-0"),
+ F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"),
+ F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
+ F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"),
+ F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"),
+ F7188X_GPIO_BANK(5, 0xA0, DRVNAME "-5"),
+ F7188X_GPIO_BANK(8, 0x90, DRVNAME "-6"),
+ F7188X_GPIO_BANK(8, 0x80, DRVNAME "-7"),
};
static struct f7188x_gpio_bank f71882_gpio_bank[] = {
- F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"),
- F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
- F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
- F7188X_GPIO_BANK(30, 4, 0xC0, DRVNAME "-3"),
- F7188X_GPIO_BANK(40, 4, 0xB0, DRVNAME "-4"),
+ F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-0"),
+ F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"),
+ F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
+ F7188X_GPIO_BANK(4, 0xC0, DRVNAME "-3"),
+ F7188X_GPIO_BANK(4, 0xB0, DRVNAME "-4"),
};
static struct f7188x_gpio_bank f71889a_gpio_bank[] = {
- F7188X_GPIO_BANK(0, 7, 0xF0, DRVNAME "-0"),
- F7188X_GPIO_BANK(10, 7, 0xE0, DRVNAME "-1"),
- F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
- F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
- F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
- F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"),
- F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"),
- F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"),
+ F7188X_GPIO_BANK(7, 0xF0, DRVNAME "-0"),
+ F7188X_GPIO_BANK(7, 0xE0, DRVNAME "-1"),
+ F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
+ F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"),
+ F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"),
+ F7188X_GPIO_BANK(5, 0xA0, DRVNAME "-5"),
+ F7188X_GPIO_BANK(8, 0x90, DRVNAME "-6"),
+ F7188X_GPIO_BANK(8, 0x80, DRVNAME "-7"),
};
static struct f7188x_gpio_bank f71889_gpio_bank[] = {
- F7188X_GPIO_BANK(0, 7, 0xF0, DRVNAME "-0"),
- F7188X_GPIO_BANK(10, 7, 0xE0, DRVNAME "-1"),
- F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
- F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
- F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
- F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"),
- F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"),
- F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"),
+ F7188X_GPIO_BANK(7, 0xF0, DRVNAME "-0"),
+ F7188X_GPIO_BANK(7, 0xE0, DRVNAME "-1"),
+ F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
+ F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"),
+ F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"),
+ F7188X_GPIO_BANK(5, 0xA0, DRVNAME "-5"),
+ F7188X_GPIO_BANK(8, 0x90, DRVNAME "-6"),
+ F7188X_GPIO_BANK(8, 0x80, DRVNAME "-7"),
};
static struct f7188x_gpio_bank f81866_gpio_bank[] = {
- F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"),
- F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
- F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
- F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
- F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
- F7188X_GPIO_BANK(50, 8, 0xA0, DRVNAME "-5"),
- F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"),
- F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"),
- F7188X_GPIO_BANK(80, 8, 0x88, DRVNAME "-8"),
+ F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-0"),
+ F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"),
+ F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
+ F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"),
+ F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"),
+ F7188X_GPIO_BANK(8, 0xA0, DRVNAME "-5"),
+ F7188X_GPIO_BANK(8, 0x90, DRVNAME "-6"),
+ F7188X_GPIO_BANK(8, 0x80, DRVNAME "-7"),
+ F7188X_GPIO_BANK(8, 0x88, DRVNAME "-8"),
};
static struct f7188x_gpio_bank f81804_gpio_bank[] = {
- F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"),
- F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
- F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
- F7188X_GPIO_BANK(50, 8, 0xA0, DRVNAME "-3"),
- F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-4"),
- F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-5"),
- F7188X_GPIO_BANK(90, 8, 0x98, DRVNAME "-6"),
+ F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-0"),
+ F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"),
+ F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
+ F7188X_GPIO_BANK(8, 0xA0, DRVNAME "-3"),
+ F7188X_GPIO_BANK(8, 0x90, DRVNAME "-4"),
+ F7188X_GPIO_BANK(8, 0x80, DRVNAME "-5"),
+ F7188X_GPIO_BANK(8, 0x98, DRVNAME "-6"),
};
static struct f7188x_gpio_bank f81865_gpio_bank[] = {
- F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"),
- F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
- F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
- F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
- F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
- F7188X_GPIO_BANK(50, 8, 0xA0, DRVNAME "-5"),
- F7188X_GPIO_BANK(60, 5, 0x90, DRVNAME "-6"),
+ F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-0"),
+ F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"),
+ F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
+ F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"),
+ F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"),
+ F7188X_GPIO_BANK(8, 0xA0, DRVNAME "-5"),
+ F7188X_GPIO_BANK(5, 0x90, DRVNAME "-6"),
};
static struct f7188x_gpio_bank nct6126d_gpio_bank[] = {
- F7188X_GPIO_BANK(0, 8, 0xE0, DRVNAME "-0"),
- F7188X_GPIO_BANK(10, 8, 0xE4, DRVNAME "-1"),
- F7188X_GPIO_BANK(20, 8, 0xE8, DRVNAME "-2"),
- F7188X_GPIO_BANK(30, 8, 0xEC, DRVNAME "-3"),
- F7188X_GPIO_BANK(40, 8, 0xF0, DRVNAME "-4"),
- F7188X_GPIO_BANK(50, 8, 0xF4, DRVNAME "-5"),
- F7188X_GPIO_BANK(60, 8, 0xF8, DRVNAME "-6"),
- F7188X_GPIO_BANK(70, 8, 0xFC, DRVNAME "-7"),
+ F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-0"),
+ F7188X_GPIO_BANK(8, 0xE4, DRVNAME "-1"),
+ F7188X_GPIO_BANK(8, 0xE8, DRVNAME "-2"),
+ F7188X_GPIO_BANK(8, 0xEC, DRVNAME "-3"),
+ F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-4"),
+ F7188X_GPIO_BANK(8, 0xF4, DRVNAME "-5"),
+ F7188X_GPIO_BANK(8, 0xF8, DRVNAME "-6"),
+ F7188X_GPIO_BANK(8, 0xFC, DRVNAME "-7"),
};
static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c
index 5ce59dcf02e3..97d345b59352 100644
--- a/drivers/gpio/gpio-ftgpio010.c
+++ b/drivers/gpio/gpio-ftgpio010.c
@@ -324,13 +324,11 @@ dis_clk:
return ret;
}
-static int ftgpio_gpio_remove(struct platform_device *pdev)
+static void ftgpio_gpio_remove(struct platform_device *pdev)
{
struct ftgpio_gpio *g = platform_get_drvdata(pdev);
clk_disable_unprepare(g->clk);
-
- return 0;
}
static const struct of_device_id ftgpio_gpio_of_match[] = {
@@ -352,6 +350,6 @@ static struct platform_driver ftgpio_gpio_driver = {
.of_match_table = ftgpio_gpio_of_match,
},
.probe = ftgpio_gpio_probe,
- .remove = ftgpio_gpio_remove,
+ .remove_new = ftgpio_gpio_remove,
};
builtin_platform_driver(ftgpio_gpio_driver);
diff --git a/drivers/gpio/gpio-fxl6408.c b/drivers/gpio/gpio-fxl6408.c
index c14b5cc5e519..991549888904 100644
--- a/drivers/gpio/gpio-fxl6408.c
+++ b/drivers/gpio/gpio-fxl6408.c
@@ -84,7 +84,7 @@ static const struct regmap_config regmap = {
.rd_table = &rd_table,
.volatile_table = &volatile_table,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.num_reg_defaults_raw = FXL6408_REG_INT_STS + 1,
};
diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c
index 0163c95f6dd7..017c7170eb57 100644
--- a/drivers/gpio/gpio-grgpio.c
+++ b/drivers/gpio/gpio-grgpio.c
@@ -431,7 +431,7 @@ static int grgpio_probe(struct platform_device *ofdev)
return 0;
}
-static int grgpio_remove(struct platform_device *ofdev)
+static void grgpio_remove(struct platform_device *ofdev)
{
struct grgpio_priv *priv = platform_get_drvdata(ofdev);
@@ -439,8 +439,6 @@ static int grgpio_remove(struct platform_device *ofdev)
if (priv->domain)
irq_domain_remove(priv->domain);
-
- return 0;
}
static const struct of_device_id grgpio_match[] = {
@@ -457,7 +455,7 @@ static struct platform_driver grgpio_driver = {
.of_match_table = grgpio_match,
},
.probe = grgpio_probe,
- .remove = grgpio_remove,
+ .remove_new = grgpio_remove,
};
module_platform_driver(grgpio_driver);
diff --git a/drivers/gpio/gpio-hisi.c b/drivers/gpio/gpio-hisi.c
index 29a03de37fd8..ef5cc654a24e 100644
--- a/drivers/gpio/gpio-hisi.c
+++ b/drivers/gpio/gpio-hisi.c
@@ -255,7 +255,7 @@ static void hisi_gpio_get_pdata(struct device *dev,
hisi_gpio->irq = platform_get_irq(pdev, idx);
dev_info(dev,
- "get hisi_gpio[%d] with %d lines\n", idx,
+ "get hisi_gpio[%d] with %u lines\n", idx,
hisi_gpio->line_num);
idx++;
diff --git a/drivers/gpio/gpio-ljca.c b/drivers/gpio/gpio-ljca.c
index 87863f0230f5..dfec9fbfc7a9 100644
--- a/drivers/gpio/gpio-ljca.c
+++ b/drivers/gpio/gpio-ljca.c
@@ -6,6 +6,7 @@
*/
#include <linux/acpi.h>
+#include <linux/auxiliary_bus.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/dev_printk.h>
@@ -13,19 +14,18 @@
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/kref.h>
-#include <linux/mfd/ljca.h>
#include <linux/module.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/usb/ljca.h>
/* GPIO commands */
-#define LJCA_GPIO_CONFIG 1
-#define LJCA_GPIO_READ 2
-#define LJCA_GPIO_WRITE 3
-#define LJCA_GPIO_INT_EVENT 4
-#define LJCA_GPIO_INT_MASK 5
-#define LJCA_GPIO_INT_UNMASK 6
+#define LJCA_GPIO_CONFIG 1
+#define LJCA_GPIO_READ 2
+#define LJCA_GPIO_WRITE 3
+#define LJCA_GPIO_INT_EVENT 4
+#define LJCA_GPIO_INT_MASK 5
+#define LJCA_GPIO_INT_UNMASK 6
#define LJCA_GPIO_CONF_DISABLE BIT(0)
#define LJCA_GPIO_CONF_INPUT BIT(1)
@@ -36,45 +36,49 @@
#define LJCA_GPIO_CONF_INTERRUPT BIT(6)
#define LJCA_GPIO_INT_TYPE BIT(7)
-#define LJCA_GPIO_CONF_EDGE FIELD_PREP(LJCA_GPIO_INT_TYPE, 1)
-#define LJCA_GPIO_CONF_LEVEL FIELD_PREP(LJCA_GPIO_INT_TYPE, 0)
+#define LJCA_GPIO_CONF_EDGE FIELD_PREP(LJCA_GPIO_INT_TYPE, 1)
+#define LJCA_GPIO_CONF_LEVEL FIELD_PREP(LJCA_GPIO_INT_TYPE, 0)
/* Intentional overlap with PULLUP / PULLDOWN */
-#define LJCA_GPIO_CONF_SET BIT(3)
-#define LJCA_GPIO_CONF_CLR BIT(4)
+#define LJCA_GPIO_CONF_SET BIT(3)
+#define LJCA_GPIO_CONF_CLR BIT(4)
-struct gpio_op {
+#define LJCA_GPIO_BUF_SIZE 60u
+
+struct ljca_gpio_op {
u8 index;
u8 value;
} __packed;
-struct gpio_packet {
+struct ljca_gpio_packet {
u8 num;
- struct gpio_op item[];
+ struct ljca_gpio_op item[] __counted_by(num);
} __packed;
-#define LJCA_GPIO_BUF_SIZE 60
struct ljca_gpio_dev {
- struct platform_device *pdev;
+ struct ljca_client *ljca;
struct gpio_chip gc;
struct ljca_gpio_info *gpio_info;
DECLARE_BITMAP(unmasked_irqs, LJCA_MAX_GPIO_NUM);
DECLARE_BITMAP(enabled_irqs, LJCA_MAX_GPIO_NUM);
DECLARE_BITMAP(reenable_irqs, LJCA_MAX_GPIO_NUM);
+ DECLARE_BITMAP(output_enabled, LJCA_MAX_GPIO_NUM);
u8 *connect_mode;
- /* mutex to protect irq bus */
+ /* protect irq bus */
struct mutex irq_lock;
struct work_struct work;
- /* lock to protect package transfer to Hardware */
+ /* protect package transfer to hardware */
struct mutex trans_lock;
u8 obuf[LJCA_GPIO_BUF_SIZE];
u8 ibuf[LJCA_GPIO_BUF_SIZE];
};
-static int gpio_config(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id, u8 config)
+static int ljca_gpio_config(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id,
+ u8 config)
{
- struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf;
+ struct ljca_gpio_packet *packet =
+ (struct ljca_gpio_packet *)ljca_gpio->obuf;
int ret;
mutex_lock(&ljca_gpio->trans_lock);
@@ -82,43 +86,43 @@ static int gpio_config(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id, u8 config)
packet->item[0].value = config | ljca_gpio->connect_mode[gpio_id];
packet->num = 1;
- ret = ljca_transfer(ljca_gpio->gpio_info->ljca, LJCA_GPIO_CONFIG, packet,
- struct_size(packet, item, packet->num), NULL, NULL);
+ ret = ljca_transfer(ljca_gpio->ljca, LJCA_GPIO_CONFIG, (u8 *)packet,
+ struct_size(packet, item, packet->num), NULL, 0);
mutex_unlock(&ljca_gpio->trans_lock);
- return ret;
+
+ return ret < 0 ? ret : 0;
}
static int ljca_gpio_read(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id)
{
- struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf;
- struct gpio_packet *ack_packet = (struct gpio_packet *)ljca_gpio->ibuf;
- unsigned int ibuf_len = LJCA_GPIO_BUF_SIZE;
+ struct ljca_gpio_packet *ack_packet =
+ (struct ljca_gpio_packet *)ljca_gpio->ibuf;
+ struct ljca_gpio_packet *packet =
+ (struct ljca_gpio_packet *)ljca_gpio->obuf;
int ret;
mutex_lock(&ljca_gpio->trans_lock);
packet->num = 1;
packet->item[0].index = gpio_id;
- ret = ljca_transfer(ljca_gpio->gpio_info->ljca, LJCA_GPIO_READ, packet,
- struct_size(packet, item, packet->num), ljca_gpio->ibuf, &ibuf_len);
- if (ret)
- goto out_unlock;
-
- if (!ibuf_len || ack_packet->num != packet->num) {
- dev_err(&ljca_gpio->pdev->dev, "failed gpio_id:%u %u", gpio_id, ack_packet->num);
- ret = -EIO;
+ ret = ljca_transfer(ljca_gpio->ljca, LJCA_GPIO_READ, (u8 *)packet,
+ struct_size(packet, item, packet->num),
+ ljca_gpio->ibuf, LJCA_GPIO_BUF_SIZE);
+
+ if (ret <= 0 || ack_packet->num != packet->num) {
+ dev_err(&ljca_gpio->ljca->auxdev.dev,
+ "read package error, gpio_id: %u num: %u ret: %d\n",
+ gpio_id, ack_packet->num, ret);
+ ret = ret < 0 ? ret : -EIO;
}
-
-out_unlock:
mutex_unlock(&ljca_gpio->trans_lock);
- if (ret)
- return ret;
- return ack_packet->item[0].value > 0;
+
+ return ret < 0 ? ret : ack_packet->item[0].value > 0;
}
-static int ljca_gpio_write(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id,
- int value)
+static int ljca_gpio_write(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id, int value)
{
- struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf;
+ struct ljca_gpio_packet *packet =
+ (struct ljca_gpio_packet *)ljca_gpio->obuf;
int ret;
mutex_lock(&ljca_gpio->trans_lock);
@@ -126,10 +130,11 @@ static int ljca_gpio_write(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id,
packet->item[0].index = gpio_id;
packet->item[0].value = value & 1;
- ret = ljca_transfer(ljca_gpio->gpio_info->ljca, LJCA_GPIO_WRITE, packet,
- struct_size(packet, item, packet->num), NULL, NULL);
+ ret = ljca_transfer(ljca_gpio->ljca, LJCA_GPIO_WRITE, (u8 *)packet,
+ struct_size(packet, item, packet->num), NULL, 0);
mutex_unlock(&ljca_gpio->trans_lock);
- return ret;
+
+ return ret < 0 ? ret : 0;
}
static int ljca_gpio_get_value(struct gpio_chip *chip, unsigned int offset)
@@ -147,16 +152,24 @@ static void ljca_gpio_set_value(struct gpio_chip *chip, unsigned int offset,
ret = ljca_gpio_write(ljca_gpio, offset, val);
if (ret)
- dev_err(chip->parent, "offset:%u val:%d set value failed %d\n", offset, val, ret);
+ dev_err(chip->parent,
+ "set value failed offset: %u val: %d ret: %d\n",
+ offset, val, ret);
}
-static int ljca_gpio_direction_input(struct gpio_chip *chip,
- unsigned int offset)
+static int ljca_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
u8 config = LJCA_GPIO_CONF_INPUT | LJCA_GPIO_CONF_CLR;
+ int ret;
- return gpio_config(ljca_gpio, offset, config);
+ ret = ljca_gpio_config(ljca_gpio, offset, config);
+ if (ret)
+ return ret;
+
+ clear_bit(offset, ljca_gpio->output_enabled);
+
+ return 0;
}
static int ljca_gpio_direction_output(struct gpio_chip *chip,
@@ -166,14 +179,26 @@ static int ljca_gpio_direction_output(struct gpio_chip *chip,
u8 config = LJCA_GPIO_CONF_OUTPUT | LJCA_GPIO_CONF_CLR;
int ret;
- ret = gpio_config(ljca_gpio, offset, config);
+ ret = ljca_gpio_config(ljca_gpio, offset, config);
if (ret)
return ret;
ljca_gpio_set_value(chip, offset, val);
+ set_bit(offset, ljca_gpio->output_enabled);
+
return 0;
}
+static int ljca_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
+
+ if (test_bit(offset, ljca_gpio->output_enabled))
+ return GPIO_LINE_DIRECTION_OUT;
+
+ return GPIO_LINE_DIRECTION_IN;
+}
+
static int ljca_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
@@ -197,7 +222,8 @@ static int ljca_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
return 0;
}
-static int ljca_gpio_init_valid_mask(struct gpio_chip *chip, unsigned long *valid_mask,
+static int ljca_gpio_init_valid_mask(struct gpio_chip *chip,
+ unsigned long *valid_mask,
unsigned int ngpios)
{
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
@@ -208,15 +234,18 @@ static int ljca_gpio_init_valid_mask(struct gpio_chip *chip, unsigned long *vali
return 0;
}
-static void ljca_gpio_irq_init_valid_mask(struct gpio_chip *chip, unsigned long *valid_mask,
+static void ljca_gpio_irq_init_valid_mask(struct gpio_chip *chip,
+ unsigned long *valid_mask,
unsigned int ngpios)
{
ljca_gpio_init_valid_mask(chip, valid_mask, ngpios);
}
-static int ljca_enable_irq(struct ljca_gpio_dev *ljca_gpio, int gpio_id, bool enable)
+static int ljca_enable_irq(struct ljca_gpio_dev *ljca_gpio, int gpio_id,
+ bool enable)
{
- struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf;
+ struct ljca_gpio_packet *packet =
+ (struct ljca_gpio_packet *)ljca_gpio->obuf;
int ret;
mutex_lock(&ljca_gpio->trans_lock);
@@ -224,18 +253,20 @@ static int ljca_enable_irq(struct ljca_gpio_dev *ljca_gpio, int gpio_id, bool en
packet->item[0].index = gpio_id;
packet->item[0].value = 0;
- ret = ljca_transfer(ljca_gpio->gpio_info->ljca,
- enable ? LJCA_GPIO_INT_UNMASK : LJCA_GPIO_INT_MASK, packet,
- struct_size(packet, item, packet->num), NULL, NULL);
+ ret = ljca_transfer(ljca_gpio->ljca,
+ enable ? LJCA_GPIO_INT_UNMASK : LJCA_GPIO_INT_MASK,
+ (u8 *)packet, struct_size(packet, item, packet->num),
+ NULL, 0);
mutex_unlock(&ljca_gpio->trans_lock);
- return ret;
+
+ return ret < 0 ? ret : 0;
}
static void ljca_gpio_async(struct work_struct *work)
{
- struct ljca_gpio_dev *ljca_gpio = container_of(work, struct ljca_gpio_dev, work);
- int gpio_id;
- int unmasked;
+ struct ljca_gpio_dev *ljca_gpio =
+ container_of(work, struct ljca_gpio_dev, work);
+ int gpio_id, unmasked;
for_each_set_bit(gpio_id, ljca_gpio->reenable_irqs, ljca_gpio->gc.ngpio) {
clear_bit(gpio_id, ljca_gpio->reenable_irqs);
@@ -245,20 +276,22 @@ static void ljca_gpio_async(struct work_struct *work)
}
}
-static void ljca_gpio_event_cb(void *context, u8 cmd, const void *evt_data, int len)
+static void ljca_gpio_event_cb(void *context, u8 cmd, const void *evt_data,
+ int len)
{
- const struct gpio_packet *packet = evt_data;
+ const struct ljca_gpio_packet *packet = evt_data;
struct ljca_gpio_dev *ljca_gpio = context;
- int i;
- int irq;
+ int i, irq;
if (cmd != LJCA_GPIO_INT_EVENT)
return;
for (i = 0; i < packet->num; i++) {
- irq = irq_find_mapping(ljca_gpio->gc.irq.domain, packet->item[i].index);
+ irq = irq_find_mapping(ljca_gpio->gc.irq.domain,
+ packet->item[i].index);
if (!irq) {
- dev_err(ljca_gpio->gc.parent, "gpio_id %u does not mapped to IRQ yet\n",
+ dev_err(ljca_gpio->gc.parent,
+ "gpio_id %u does not mapped to IRQ yet\n",
packet->item[i].index);
return;
}
@@ -299,18 +332,22 @@ static int ljca_irq_set_type(struct irq_data *irqd, unsigned int type)
ljca_gpio->connect_mode[gpio_id] = LJCA_GPIO_CONF_INTERRUPT;
switch (type) {
case IRQ_TYPE_LEVEL_HIGH:
- ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_LEVEL | LJCA_GPIO_CONF_PULLUP);
+ ljca_gpio->connect_mode[gpio_id] |=
+ (LJCA_GPIO_CONF_LEVEL | LJCA_GPIO_CONF_PULLUP);
break;
case IRQ_TYPE_LEVEL_LOW:
- ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_LEVEL | LJCA_GPIO_CONF_PULLDOWN);
+ ljca_gpio->connect_mode[gpio_id] |=
+ (LJCA_GPIO_CONF_LEVEL | LJCA_GPIO_CONF_PULLDOWN);
break;
case IRQ_TYPE_EDGE_BOTH:
break;
case IRQ_TYPE_EDGE_RISING:
- ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_EDGE | LJCA_GPIO_CONF_PULLUP);
+ ljca_gpio->connect_mode[gpio_id] |=
+ (LJCA_GPIO_CONF_EDGE | LJCA_GPIO_CONF_PULLUP);
break;
case IRQ_TYPE_EDGE_FALLING:
- ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_EDGE | LJCA_GPIO_CONF_PULLDOWN);
+ ljca_gpio->connect_mode[gpio_id] |=
+ (LJCA_GPIO_CONF_EDGE | LJCA_GPIO_CONF_PULLDOWN);
break;
default:
return -EINVAL;
@@ -332,15 +369,14 @@ static void ljca_irq_bus_unlock(struct irq_data *irqd)
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc);
int gpio_id = irqd_to_hwirq(irqd);
- int enabled;
- int unmasked;
+ int enabled, unmasked;
enabled = test_bit(gpio_id, ljca_gpio->enabled_irqs);
unmasked = test_bit(gpio_id, ljca_gpio->unmasked_irqs);
if (enabled != unmasked) {
if (unmasked) {
- gpio_config(ljca_gpio, gpio_id, 0);
+ ljca_gpio_config(ljca_gpio, gpio_id, 0);
ljca_enable_irq(ljca_gpio, gpio_id, true);
set_bit(gpio_id, ljca_gpio->enabled_irqs);
} else {
@@ -363,43 +399,48 @@ static const struct irq_chip ljca_gpio_irqchip = {
GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
-static int ljca_gpio_probe(struct platform_device *pdev)
+static int ljca_gpio_probe(struct auxiliary_device *auxdev,
+ const struct auxiliary_device_id *aux_dev_id)
{
+ struct ljca_client *ljca = auxiliary_dev_to_ljca_client(auxdev);
struct ljca_gpio_dev *ljca_gpio;
struct gpio_irq_chip *girq;
int ret;
- ljca_gpio = devm_kzalloc(&pdev->dev, sizeof(*ljca_gpio), GFP_KERNEL);
+ ljca_gpio = devm_kzalloc(&auxdev->dev, sizeof(*ljca_gpio), GFP_KERNEL);
if (!ljca_gpio)
return -ENOMEM;
- ljca_gpio->gpio_info = dev_get_platdata(&pdev->dev);
- ljca_gpio->connect_mode = devm_kcalloc(&pdev->dev, ljca_gpio->gpio_info->num,
- sizeof(*ljca_gpio->connect_mode), GFP_KERNEL);
+ ljca_gpio->ljca = ljca;
+ ljca_gpio->gpio_info = dev_get_platdata(&auxdev->dev);
+ ljca_gpio->connect_mode = devm_kcalloc(&auxdev->dev,
+ ljca_gpio->gpio_info->num,
+ sizeof(*ljca_gpio->connect_mode),
+ GFP_KERNEL);
if (!ljca_gpio->connect_mode)
return -ENOMEM;
mutex_init(&ljca_gpio->irq_lock);
mutex_init(&ljca_gpio->trans_lock);
- ljca_gpio->pdev = pdev;
ljca_gpio->gc.direction_input = ljca_gpio_direction_input;
ljca_gpio->gc.direction_output = ljca_gpio_direction_output;
+ ljca_gpio->gc.get_direction = ljca_gpio_get_direction;
ljca_gpio->gc.get = ljca_gpio_get_value;
ljca_gpio->gc.set = ljca_gpio_set_value;
ljca_gpio->gc.set_config = ljca_gpio_set_config;
ljca_gpio->gc.init_valid_mask = ljca_gpio_init_valid_mask;
ljca_gpio->gc.can_sleep = true;
- ljca_gpio->gc.parent = &pdev->dev;
+ ljca_gpio->gc.parent = &auxdev->dev;
ljca_gpio->gc.base = -1;
ljca_gpio->gc.ngpio = ljca_gpio->gpio_info->num;
- ljca_gpio->gc.label = ACPI_COMPANION(&pdev->dev) ?
- acpi_dev_name(ACPI_COMPANION(&pdev->dev)) :
- dev_name(&pdev->dev);
+ ljca_gpio->gc.label = ACPI_COMPANION(&auxdev->dev) ?
+ acpi_dev_name(ACPI_COMPANION(&auxdev->dev)) :
+ dev_name(&auxdev->dev);
ljca_gpio->gc.owner = THIS_MODULE;
- platform_set_drvdata(pdev, ljca_gpio);
- ljca_register_event_cb(ljca_gpio->gpio_info->ljca, ljca_gpio_event_cb, ljca_gpio);
+ auxiliary_set_drvdata(auxdev, ljca_gpio);
+ ljca_register_event_cb(ljca, ljca_gpio_event_cb, ljca_gpio);
girq = &ljca_gpio->gc.irq;
gpio_irq_chip_set_chip(girq, &ljca_gpio_irqchip);
@@ -413,7 +454,7 @@ static int ljca_gpio_probe(struct platform_device *pdev)
INIT_WORK(&ljca_gpio->work, ljca_gpio_async);
ret = gpiochip_add_data(&ljca_gpio->gc, ljca_gpio);
if (ret) {
- ljca_unregister_event_cb(ljca_gpio->gpio_info->ljca);
+ ljca_unregister_event_cb(ljca);
mutex_destroy(&ljca_gpio->irq_lock);
mutex_destroy(&ljca_gpio->trans_lock);
}
@@ -421,34 +462,33 @@ static int ljca_gpio_probe(struct platform_device *pdev)
return ret;
}
-static int ljca_gpio_remove(struct platform_device *pdev)
+static void ljca_gpio_remove(struct auxiliary_device *auxdev)
{
- struct ljca_gpio_dev *ljca_gpio = platform_get_drvdata(pdev);
+ struct ljca_gpio_dev *ljca_gpio = auxiliary_get_drvdata(auxdev);
gpiochip_remove(&ljca_gpio->gc);
- ljca_unregister_event_cb(ljca_gpio->gpio_info->ljca);
+ ljca_unregister_event_cb(ljca_gpio->ljca);
+ cancel_work_sync(&ljca_gpio->work);
mutex_destroy(&ljca_gpio->irq_lock);
mutex_destroy(&ljca_gpio->trans_lock);
- return 0;
}
-#define LJCA_GPIO_DRV_NAME "ljca-gpio"
-static const struct platform_device_id ljca_gpio_id[] = {
- { LJCA_GPIO_DRV_NAME, 0 },
- { /* sentinel */ }
+static const struct auxiliary_device_id ljca_gpio_id_table[] = {
+ { "usb_ljca.ljca-gpio", 0 },
+ { /* sentinel */ },
};
-MODULE_DEVICE_TABLE(platform, ljca_gpio_id);
+MODULE_DEVICE_TABLE(auxiliary, ljca_gpio_id_table);
-static struct platform_driver ljca_gpio_driver = {
- .driver.name = LJCA_GPIO_DRV_NAME,
+static struct auxiliary_driver ljca_gpio_driver = {
.probe = ljca_gpio_probe,
.remove = ljca_gpio_remove,
+ .id_table = ljca_gpio_id_table,
};
-module_platform_driver(ljca_gpio_driver);
+module_auxiliary_driver(ljca_gpio_driver);
-MODULE_AUTHOR("Ye Xiang <xiang.ye@intel.com>");
-MODULE_AUTHOR("Wang Zhifeng <zhifeng.wang@intel.com>");
-MODULE_AUTHOR("Zhang Lixu <lixu.zhang@intel.com>");
+MODULE_AUTHOR("Wentong Wu <wentong.wu@intel.com>");
+MODULE_AUTHOR("Zhifeng Wang <zhifeng.wang@intel.com>");
+MODULE_AUTHOR("Lixu Zhang <lixu.zhang@intel.com>");
MODULE_DESCRIPTION("Intel La Jolla Cove Adapter USB-GPIO driver");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(LJCA);
diff --git a/drivers/gpio/gpio-loongson-64bit.c b/drivers/gpio/gpio-loongson-64bit.c
index 06213bbfabdd..6749d4dd6d64 100644
--- a/drivers/gpio/gpio-loongson-64bit.c
+++ b/drivers/gpio/gpio-loongson-64bit.c
@@ -26,6 +26,7 @@ struct loongson_gpio_chip_data {
unsigned int conf_offset;
unsigned int out_offset;
unsigned int in_offset;
+ unsigned int inten_offset;
};
struct loongson_gpio_chip {
@@ -117,19 +118,29 @@ static void loongson_gpio_set(struct gpio_chip *chip, unsigned int pin, int valu
static int loongson_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
{
+ unsigned int u;
struct platform_device *pdev = to_platform_device(chip->parent);
+ struct loongson_gpio_chip *lgpio = to_loongson_gpio_chip(chip);
+
+ if (lgpio->chip_data->mode == BIT_CTRL_MODE) {
+ /* Get the register index from offset then multiply by bytes per register */
+ u = readl(lgpio->reg_base + lgpio->chip_data->inten_offset + (offset / 32) * 4);
+ u |= BIT(offset % 32);
+ writel(u, lgpio->reg_base + lgpio->chip_data->inten_offset + (offset / 32) * 4);
+ } else {
+ writeb(1, lgpio->reg_base + lgpio->chip_data->inten_offset + offset);
+ }
return platform_get_irq(pdev, offset);
}
static int loongson_gpio_init(struct device *dev, struct loongson_gpio_chip *lgpio,
- struct device_node *np, void __iomem *reg_base)
+ void __iomem *reg_base)
{
int ret;
u32 ngpios;
lgpio->reg_base = reg_base;
-
if (lgpio->chip_data->mode == BIT_CTRL_MODE) {
ret = bgpio_init(&lgpio->chip, dev, 8,
lgpio->reg_base + lgpio->chip_data->in_offset,
@@ -148,15 +159,15 @@ static int loongson_gpio_init(struct device *dev, struct loongson_gpio_chip *lgp
lgpio->chip.direction_output = loongson_gpio_direction_output;
lgpio->chip.set = loongson_gpio_set;
lgpio->chip.parent = dev;
+ device_property_read_u32(dev, "ngpios", &ngpios);
+ lgpio->chip.ngpio = ngpios;
spin_lock_init(&lgpio->lock);
}
- device_property_read_u32(dev, "ngpios", &ngpios);
-
- lgpio->chip.can_sleep = 0;
- lgpio->chip.ngpio = ngpios;
lgpio->chip.label = lgpio->chip_data->label;
- lgpio->chip.to_irq = loongson_gpio_to_irq;
+ lgpio->chip.can_sleep = false;
+ if (lgpio->chip_data->inten_offset)
+ lgpio->chip.to_irq = loongson_gpio_to_irq;
return devm_gpiochip_add_data(dev, &lgpio->chip, lgpio);
}
@@ -165,7 +176,6 @@ static int loongson_gpio_probe(struct platform_device *pdev)
{
void __iomem *reg_base;
struct loongson_gpio_chip *lgpio;
- struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
lgpio = devm_kzalloc(dev, sizeof(*lgpio), GFP_KERNEL);
@@ -178,7 +188,7 @@ static int loongson_gpio_probe(struct platform_device *pdev)
if (IS_ERR(reg_base))
return PTR_ERR(reg_base);
- return loongson_gpio_init(dev, lgpio, np, reg_base);
+ return loongson_gpio_init(dev, lgpio, reg_base);
}
static const struct loongson_gpio_chip_data loongson_gpio_ls2k_data = {
@@ -187,6 +197,57 @@ static const struct loongson_gpio_chip_data loongson_gpio_ls2k_data = {
.conf_offset = 0x0,
.in_offset = 0x20,
.out_offset = 0x10,
+ .inten_offset = 0x30,
+};
+
+static const struct loongson_gpio_chip_data loongson_gpio_ls2k0500_data0 = {
+ .label = "ls2k0500_gpio",
+ .mode = BIT_CTRL_MODE,
+ .conf_offset = 0x0,
+ .in_offset = 0x8,
+ .out_offset = 0x10,
+ .inten_offset = 0xb0,
+};
+
+static const struct loongson_gpio_chip_data loongson_gpio_ls2k0500_data1 = {
+ .label = "ls2k0500_gpio",
+ .mode = BIT_CTRL_MODE,
+ .conf_offset = 0x0,
+ .in_offset = 0x8,
+ .out_offset = 0x10,
+ .inten_offset = 0x98,
+};
+
+static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data0 = {
+ .label = "ls2k2000_gpio",
+ .mode = BIT_CTRL_MODE,
+ .conf_offset = 0x0,
+ .in_offset = 0xc,
+ .out_offset = 0x8,
+};
+
+static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data1 = {
+ .label = "ls2k2000_gpio",
+ .mode = BIT_CTRL_MODE,
+ .conf_offset = 0x0,
+ .in_offset = 0x20,
+ .out_offset = 0x10,
+};
+
+static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data2 = {
+ .label = "ls2k2000_gpio",
+ .mode = BIT_CTRL_MODE,
+ .conf_offset = 0x84,
+ .in_offset = 0x88,
+ .out_offset = 0x80,
+};
+
+static const struct loongson_gpio_chip_data loongson_gpio_ls3a5000_data = {
+ .label = "ls3a5000_gpio",
+ .mode = BIT_CTRL_MODE,
+ .conf_offset = 0x0,
+ .in_offset = 0xc,
+ .out_offset = 0x8,
};
static const struct loongson_gpio_chip_data loongson_gpio_ls7a_data = {
@@ -203,6 +264,30 @@ static const struct of_device_id loongson_gpio_of_match[] = {
.data = &loongson_gpio_ls2k_data,
},
{
+ .compatible = "loongson,ls2k0500-gpio0",
+ .data = &loongson_gpio_ls2k0500_data0,
+ },
+ {
+ .compatible = "loongson,ls2k0500-gpio1",
+ .data = &loongson_gpio_ls2k0500_data1,
+ },
+ {
+ .compatible = "loongson,ls2k2000-gpio0",
+ .data = &loongson_gpio_ls2k2000_data0,
+ },
+ {
+ .compatible = "loongson,ls2k2000-gpio1",
+ .data = &loongson_gpio_ls2k2000_data1,
+ },
+ {
+ .compatible = "loongson,ls2k2000-gpio2",
+ .data = &loongson_gpio_ls2k2000_data2,
+ },
+ {
+ .compatible = "loongson,ls3a5000-gpio",
+ .data = &loongson_gpio_ls3a5000_data,
+ },
+ {
.compatible = "loongson,ls7a-gpio",
.data = &loongson_gpio_ls7a_data,
},
@@ -215,6 +300,22 @@ static const struct acpi_device_id loongson_gpio_acpi_match[] = {
.id = "LOON0002",
.driver_data = (kernel_ulong_t)&loongson_gpio_ls7a_data,
},
+ {
+ .id = "LOON0007",
+ .driver_data = (kernel_ulong_t)&loongson_gpio_ls3a5000_data,
+ },
+ {
+ .id = "LOON000A",
+ .driver_data = (kernel_ulong_t)&loongson_gpio_ls2k2000_data0,
+ },
+ {
+ .id = "LOON000B",
+ .driver_data = (kernel_ulong_t)&loongson_gpio_ls2k2000_data1,
+ },
+ {
+ .id = "LOON000C",
+ .driver_data = (kernel_ulong_t)&loongson_gpio_ls2k2000_data2,
+ },
{}
};
MODULE_DEVICE_TABLE(acpi, loongson_gpio_acpi_match);
diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c
index ed3f653a1dfc..5c6bb57a8c99 100644
--- a/drivers/gpio/gpio-lpc18xx.c
+++ b/drivers/gpio/gpio-lpc18xx.c
@@ -381,7 +381,7 @@ static int lpc18xx_gpio_probe(struct platform_device *pdev)
return 0;
}
-static int lpc18xx_gpio_remove(struct platform_device *pdev)
+static void lpc18xx_gpio_remove(struct platform_device *pdev)
{
struct lpc18xx_gpio_chip *gc = platform_get_drvdata(pdev);
@@ -389,8 +389,6 @@ static int lpc18xx_gpio_remove(struct platform_device *pdev)
irq_domain_remove(gc->pin_ic->domain);
clk_disable_unprepare(gc->clk);
-
- return 0;
}
static const struct of_device_id lpc18xx_gpio_match[] = {
@@ -401,7 +399,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_gpio_match);
static struct platform_driver lpc18xx_gpio_driver = {
.probe = lpc18xx_gpio_probe,
- .remove = lpc18xx_gpio_remove,
+ .remove_new = lpc18xx_gpio_remove,
.driver = {
.name = "lpc18xx-gpio",
.of_match_table = lpc18xx_gpio_match,
diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c
index ca7eb5e8bfaa..7fb298b4571b 100644
--- a/drivers/gpio/gpio-mb86s7x.c
+++ b/drivers/gpio/gpio-mb86s7x.c
@@ -20,7 +20,6 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
-#include "gpiolib.h"
#include "gpiolib-acpi.h"
/*
@@ -205,15 +204,13 @@ static int mb86s70_gpio_probe(struct platform_device *pdev)
return 0;
}
-static int mb86s70_gpio_remove(struct platform_device *pdev)
+static void mb86s70_gpio_remove(struct platform_device *pdev)
{
struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev);
acpi_gpiochip_free_interrupts(&gchip->gc);
gpiochip_remove(&gchip->gc);
clk_disable_unprepare(gchip->clk);
-
- return 0;
}
static const struct of_device_id mb86s70_gpio_dt_ids[] = {
@@ -237,7 +234,7 @@ static struct platform_driver mb86s70_gpio_driver = {
.acpi_match_table = ACPI_PTR(mb86s70_gpio_acpi_ids),
},
.probe = mb86s70_gpio_probe,
- .remove = mb86s70_gpio_remove,
+ .remove_new = mb86s70_gpio_remove,
};
module_platform_driver(mb86s70_gpio_driver);
diff --git a/drivers/gpio/gpio-mm-lantiq.c b/drivers/gpio/gpio-mm-lantiq.c
index f3c158259636..e855c68c981b 100644
--- a/drivers/gpio/gpio-mm-lantiq.c
+++ b/drivers/gpio/gpio-mm-lantiq.c
@@ -121,13 +121,11 @@ static int ltq_mm_probe(struct platform_device *pdev)
return of_mm_gpiochip_add_data(pdev->dev.of_node, &chip->mmchip, chip);
}
-static int ltq_mm_remove(struct platform_device *pdev)
+static void ltq_mm_remove(struct platform_device *pdev)
{
struct ltq_mm *chip = platform_get_drvdata(pdev);
of_mm_gpiochip_remove(&chip->mmchip);
-
- return 0;
}
static const struct of_device_id ltq_mm_match[] = {
@@ -138,7 +136,7 @@ MODULE_DEVICE_TABLE(of, ltq_mm_match);
static struct platform_driver ltq_mm_driver = {
.probe = ltq_mm_probe,
- .remove = ltq_mm_remove,
+ .remove_new = ltq_mm_remove,
.driver = {
.name = "gpio-mm-ltq",
.of_match_table = ltq_mm_match,
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 74fdf0d87b2c..3ff0ea1e351c 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -56,9 +56,9 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.`
#include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include "gpiolib.h"
@@ -702,7 +702,7 @@ static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
{
struct bgpio_pdata *pdata;
- if (!of_match_device(bgpio_of_match, &pdev->dev))
+ if (!pdev->dev.of_node)
return NULL;
pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata),
diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c
index b32063ac845a..4870e267a402 100644
--- a/drivers/gpio/gpio-mockup.c
+++ b/drivers/gpio/gpio-mockup.c
@@ -9,7 +9,9 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/cleanup.h>
#include <linux/debugfs.h>
+#include <linux/device.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@@ -24,8 +26,6 @@
#include <linux/string_helpers.h>
#include <linux/uaccess.h>
-#include "gpiolib.h"
-
#define GPIO_MOCKUP_MAX_GC 10
/*
* We're storing two values per chip: the GPIO base and the number
@@ -39,11 +39,15 @@
* struct gpio_pin_status - structure describing a GPIO status
* @dir: Configures direction of gpio as "in" or "out"
* @value: Configures status of the gpio as 0(low) or 1(high)
+ * @pull: Configures the current pull of the GPIO as 0 (pull-down) or
+ * 1 (pull-up)
+ * @requested: Request status of this GPIO
*/
struct gpio_mockup_line_status {
int dir;
int value;
int pull;
+ bool requested;
};
struct gpio_mockup_chip {
@@ -56,7 +60,6 @@ struct gpio_mockup_chip {
struct gpio_mockup_dbgfs_private {
struct gpio_mockup_chip *chip;
- struct gpio_desc *desc;
unsigned int offset;
};
@@ -91,9 +94,8 @@ static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset)
struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
int val;
- mutex_lock(&chip->lock);
- val = __gpio_mockup_get(chip, offset);
- mutex_unlock(&chip->lock);
+ scoped_guard(mutex, &chip->lock)
+ val = __gpio_mockup_get(chip, offset);
return val;
}
@@ -104,12 +106,12 @@ static int gpio_mockup_get_multiple(struct gpio_chip *gc,
struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
unsigned int bit, val;
- mutex_lock(&chip->lock);
- for_each_set_bit(bit, mask, gc->ngpio) {
- val = __gpio_mockup_get(chip, bit);
- __assign_bit(bit, bits, val);
+ scoped_guard(mutex, &chip->lock) {
+ for_each_set_bit(bit, mask, gc->ngpio) {
+ val = __gpio_mockup_get(chip, bit);
+ __assign_bit(bit, bits, val);
+ }
}
- mutex_unlock(&chip->lock);
return 0;
}
@@ -125,9 +127,9 @@ static void gpio_mockup_set(struct gpio_chip *gc,
{
struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
- mutex_lock(&chip->lock);
+ guard(mutex)(&chip->lock);
+
__gpio_mockup_set(chip, offset, value);
- mutex_unlock(&chip->lock);
}
static void gpio_mockup_set_multiple(struct gpio_chip *gc,
@@ -136,23 +138,21 @@ static void gpio_mockup_set_multiple(struct gpio_chip *gc,
struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
unsigned int bit;
- mutex_lock(&chip->lock);
+ guard(mutex)(&chip->lock);
+
for_each_set_bit(bit, mask, gc->ngpio)
__gpio_mockup_set(chip, bit, test_bit(bit, bits));
- mutex_unlock(&chip->lock);
}
static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
unsigned int offset, int value)
{
- struct gpio_chip *gc = &chip->gc;
- struct gpio_desc *desc = gpiochip_get_desc(gc, offset);
+ struct gpio_mockup_line_status *line = &chip->lines[offset];
int curr, irq, irq_type, ret = 0;
- mutex_lock(&chip->lock);
+ guard(mutex)(&chip->lock);
- if (test_bit(FLAG_REQUESTED, &desc->flags) &&
- !test_bit(FLAG_IS_OUT, &desc->flags)) {
+ if (line->requested && line->dir == GPIO_LINE_DIRECTION_IN) {
curr = __gpio_mockup_get(chip, offset);
if (curr == value)
goto out;
@@ -180,13 +180,11 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
set_value:
/* Change the value unless we're actively driving the line. */
- if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
- !test_bit(FLAG_IS_OUT, &desc->flags))
+ if (!line->requested || line->dir == GPIO_LINE_DIRECTION_IN)
__gpio_mockup_set(chip, offset, value);
out:
chip->lines[offset].pull = value;
- mutex_unlock(&chip->lock);
return ret;
}
@@ -211,10 +209,10 @@ static int gpio_mockup_dirout(struct gpio_chip *gc,
{
struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
- mutex_lock(&chip->lock);
- chip->lines[offset].dir = GPIO_LINE_DIRECTION_OUT;
- __gpio_mockup_set(chip, offset, value);
- mutex_unlock(&chip->lock);
+ scoped_guard(mutex, &chip->lock) {
+ chip->lines[offset].dir = GPIO_LINE_DIRECTION_OUT;
+ __gpio_mockup_set(chip, offset, value);
+ }
return 0;
}
@@ -223,9 +221,8 @@ static int gpio_mockup_dirin(struct gpio_chip *gc, unsigned int offset)
{
struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
- mutex_lock(&chip->lock);
- chip->lines[offset].dir = GPIO_LINE_DIRECTION_IN;
- mutex_unlock(&chip->lock);
+ scoped_guard(mutex, &chip->lock)
+ chip->lines[offset].dir = GPIO_LINE_DIRECTION_IN;
return 0;
}
@@ -235,9 +232,8 @@ static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset)
struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
int direction;
- mutex_lock(&chip->lock);
- direction = chip->lines[offset].dir;
- mutex_unlock(&chip->lock);
+ scoped_guard(mutex, &chip->lock)
+ direction = chip->lines[offset].dir;
return direction;
}
@@ -249,10 +245,23 @@ static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset)
return irq_create_mapping(chip->irq_sim_domain, offset);
}
+static int gpio_mockup_request(struct gpio_chip *gc, unsigned int offset)
+{
+ struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
+
+ scoped_guard(mutex, &chip->lock)
+ chip->lines[offset].requested = true;
+
+ return 0;
+}
+
static void gpio_mockup_free(struct gpio_chip *gc, unsigned int offset)
{
struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
+ guard(mutex)(&chip->lock);
+
+ chip->lines[offset].requested = false;
__gpio_mockup_set(chip, offset, chip->lines[offset].pull);
}
@@ -345,6 +354,7 @@ static const struct file_operations gpio_mockup_debugfs_ops = {
static void gpio_mockup_debugfs_setup(struct device *dev,
struct gpio_mockup_chip *chip)
{
+ struct device *child __free(put_device) = NULL;
struct gpio_mockup_dbgfs_private *priv;
struct gpio_chip *gc;
const char *devname;
@@ -352,8 +362,16 @@ static void gpio_mockup_debugfs_setup(struct device *dev,
int i;
gc = &chip->gc;
- devname = dev_name(&gc->gpiodev->dev);
+ /*
+ * There can only be a single GPIO device per platform device in
+ * gpio-mockup so using device_find_any_child() is OK.
+ */
+ child = device_find_any_child(dev);
+ if (!child)
+ return;
+
+ devname = dev_name(child);
chip->dbg_dir = debugfs_create_dir(devname, gpio_mockup_dbg_dir);
for (i = 0; i < gc->ngpio; i++) {
@@ -367,7 +385,6 @@ static void gpio_mockup_debugfs_setup(struct device *dev,
priv->chip = chip;
priv->offset = i;
- priv->desc = gpiochip_get_desc(gc, i);
debugfs_create_file(name, 0600, chip->dbg_dir, priv,
&gpio_mockup_debugfs_ops);
@@ -438,6 +455,7 @@ static int gpio_mockup_probe(struct platform_device *pdev)
gc->get_direction = gpio_mockup_get_direction;
gc->set_config = gpio_mockup_set_config;
gc->to_irq = gpio_mockup_to_irq;
+ gc->request = gpio_mockup_request;
gc->free = gpio_mockup_free;
chip->lines = devm_kcalloc(dev, gc->ngpio,
diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c
index b49e3ca64015..a199dce3394a 100644
--- a/drivers/gpio/gpio-mpc5200.c
+++ b/drivers/gpio/gpio-mpc5200.c
@@ -165,13 +165,11 @@ static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
return 0;
}
-static int mpc52xx_gpiochip_remove(struct platform_device *ofdev)
+static void mpc52xx_gpiochip_remove(struct platform_device *ofdev)
{
struct mpc52xx_gpiochip *chip = platform_get_drvdata(ofdev);
of_mm_gpiochip_remove(&chip->mmchip);
-
- return 0;
}
static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {
@@ -185,7 +183,7 @@ static struct platform_driver mpc52xx_wkup_gpiochip_driver = {
.of_match_table = mpc52xx_wkup_gpiochip_match,
},
.probe = mpc52xx_wkup_gpiochip_probe,
- .remove = mpc52xx_gpiochip_remove,
+ .remove_new = mpc52xx_gpiochip_remove,
};
/*
@@ -338,7 +336,7 @@ static struct platform_driver mpc52xx_simple_gpiochip_driver = {
.of_match_table = mpc52xx_simple_gpiochip_match,
},
.probe = mpc52xx_simple_gpiochip_probe,
- .remove = mpc52xx_gpiochip_remove,
+ .remove_new = mpc52xx_gpiochip_remove,
};
static struct platform_driver * const drivers[] = {
diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c
index ebf2f511df59..c0125ac73906 100644
--- a/drivers/gpio/gpio-mpc8xxx.c
+++ b/drivers/gpio/gpio-mpc8xxx.c
@@ -419,7 +419,7 @@ err:
return ret;
}
-static int mpc8xxx_remove(struct platform_device *pdev)
+static void mpc8xxx_remove(struct platform_device *pdev)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = platform_get_drvdata(pdev);
@@ -427,8 +427,6 @@ static int mpc8xxx_remove(struct platform_device *pdev)
irq_set_chained_handler_and_data(mpc8xxx_gc->irqn, NULL, NULL);
irq_domain_remove(mpc8xxx_gc->irq);
}
-
- return 0;
}
#ifdef CONFIG_ACPI
@@ -441,7 +439,7 @@ MODULE_DEVICE_TABLE(acpi, gpio_acpi_ids);
static struct platform_driver mpc8xxx_plat_driver = {
.probe = mpc8xxx_probe,
- .remove = mpc8xxx_remove,
+ .remove_new = mpc8xxx_remove,
.driver = {
.name = "gpio-mpc8xxx",
.of_match_table = mpc8xxx_gpio_ids,
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 67497116ce27..a13f3c18ccd4 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -42,9 +42,10 @@
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/mfd/syscon.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/pwm.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@@ -345,7 +346,7 @@ static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned int pin)
* Check with the pinctrl driver whether this pin is usable as
* an input GPIO
*/
- ret = pinctrl_gpio_direction_input(chip->base + pin);
+ ret = pinctrl_gpio_direction_input(chip, pin);
if (ret)
return ret;
@@ -365,7 +366,7 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned int pin,
* Check with the pinctrl driver whether this pin is usable as
* an output GPIO
*/
- ret = pinctrl_gpio_direction_output(chip->base + pin);
+ ret = pinctrl_gpio_direction_output(chip, pin);
if (ret)
return ret;
@@ -756,7 +757,6 @@ static const struct pwm_ops mvebu_pwm_ops = {
.free = mvebu_pwm_free,
.get_state = mvebu_pwm_get_state,
.apply = mvebu_pwm_apply,
- .owner = THIS_MODULE,
};
static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)
@@ -1122,7 +1122,6 @@ static void mvebu_gpio_remove_irq_domain(void *data)
static int mvebu_gpio_probe(struct platform_device *pdev)
{
struct mvebu_gpio_chip *mvchip;
- const struct of_device_id *match;
struct device_node *np = pdev->dev.of_node;
struct irq_chip_generic *gc;
struct irq_chip_type *ct;
@@ -1132,11 +1131,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
int i, cpu, id;
int err;
- match = of_match_device(mvebu_gpio_of_match, &pdev->dev);
- if (match)
- soc_variant = (unsigned long) match->data;
- else
- soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
+ soc_variant = (unsigned long)device_get_match_data(&pdev->dev);
/* Some gpio controllers do not provide irq support */
err = platform_irq_count(pdev);
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index a927680c66f8..76d5d87e9681 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -1048,15 +1048,14 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct device *pm_dev)
bank->chip.label = "mpuio";
if (bank->regs->wkup_en)
bank->chip.parent = &omap_mpuio_device.dev;
- bank->chip.base = OMAP_MPUIO(0);
} else {
label = devm_kasprintf(bank->chip.parent, GFP_KERNEL, "gpio-%d-%d",
gpio, gpio + bank->width - 1);
if (!label)
return -ENOMEM;
bank->chip.label = label;
- bank->chip.base = -1;
}
+ bank->chip.base = -1;
bank->chip.ngpio = bank->width;
irq = &bank->chip.irq;
@@ -1489,7 +1488,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
return 0;
}
-static int omap_gpio_remove(struct platform_device *pdev)
+static void omap_gpio_remove(struct platform_device *pdev)
{
struct gpio_bank *bank = platform_get_drvdata(pdev);
@@ -1498,8 +1497,6 @@ static int omap_gpio_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
if (bank->dbck_flag)
clk_unprepare(bank->dbck);
-
- return 0;
}
static int __maybe_unused omap_gpio_runtime_suspend(struct device *dev)
@@ -1560,7 +1557,7 @@ static const struct dev_pm_ops gpio_pm_ops = {
static struct platform_driver omap_gpio_driver = {
.probe = omap_gpio_probe,
- .remove = omap_gpio_remove,
+ .remove_new = omap_gpio_remove,
.driver = {
.name = "omap_gpio",
.pm = &gpio_pm_ops,
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index bdd50a78e414..00ffa168e405 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -8,22 +8,30 @@
* Derived from drivers/i2c/chips/pca9539.c
*/
-#include <linux/acpi.h>
+#include <linux/atomic.h>
#include <linux/bitmap.h>
-#include <linux/gpio/consumer.h>
-#include <linux/gpio/driver.h>
+#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/of_platform.h>
-#include <linux/platform_data/pca953x.h>
+#include <linux/mutex.h>
+#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
-#include <asm/unaligned.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+
+#include <linux/pinctrl/pinconf-generic.h>
+
+#include <linux/platform_data/pca953x.h>
#define PCA953X_INPUT 0x00
#define PCA953X_OUTPUT 0x01
@@ -118,6 +126,7 @@ MODULE_DEVICE_TABLE(i2c, pca953x_id);
#ifdef CONFIG_GPIO_PCA953X_IRQ
+#include <linux/acpi.h>
#include <linux/dmi.h>
static const struct acpi_gpio_params pca953x_irq_gpios = { 0, 0, true };
@@ -211,7 +220,6 @@ struct pca953x_chip {
struct i2c_client *client;
struct gpio_chip gpio_chip;
- const char *const *names;
unsigned long driver_data;
struct regulator *regulator;
@@ -414,7 +422,7 @@ static const struct regmap_config pca953x_i2c_regmap = {
.volatile_reg = pca953x_volatile_register,
.disable_locking = true,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = 0x7f,
};
@@ -430,7 +438,7 @@ static const struct regmap_config pca953x_ai_i2c_regmap = {
.volatile_reg = pca953x_volatile_register,
.disable_locking = true,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = 0x7f,
};
@@ -520,12 +528,10 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
struct pca953x_chip *chip = gpiochip_get_data(gc);
u8 dirreg = chip->recalc_addr(chip, chip->regs->direction, off);
u8 bit = BIT(off % BANK_SZ);
- int ret;
- mutex_lock(&chip->i2c_lock);
- ret = regmap_write_bits(chip->regmap, dirreg, bit, bit);
- mutex_unlock(&chip->i2c_lock);
- return ret;
+ guard(mutex)(&chip->i2c_lock);
+
+ return regmap_write_bits(chip->regmap, dirreg, bit, bit);
}
static int pca953x_gpio_direction_output(struct gpio_chip *gc,
@@ -537,17 +543,15 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
u8 bit = BIT(off % BANK_SZ);
int ret;
- mutex_lock(&chip->i2c_lock);
+ guard(mutex)(&chip->i2c_lock);
+
/* set output level */
ret = regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0);
if (ret)
- goto exit;
+ return ret;
/* then direction */
- ret = regmap_write_bits(chip->regmap, dirreg, bit, 0);
-exit:
- mutex_unlock(&chip->i2c_lock);
- return ret;
+ return regmap_write_bits(chip->regmap, dirreg, bit, 0);
}
static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
@@ -558,9 +562,8 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
u32 reg_val;
int ret;
- mutex_lock(&chip->i2c_lock);
- ret = regmap_read(chip->regmap, inreg, &reg_val);
- mutex_unlock(&chip->i2c_lock);
+ scoped_guard(mutex, &chip->i2c_lock)
+ ret = regmap_read(chip->regmap, inreg, &reg_val);
if (ret < 0)
return ret;
@@ -573,9 +576,9 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
u8 outreg = chip->recalc_addr(chip, chip->regs->output, off);
u8 bit = BIT(off % BANK_SZ);
- mutex_lock(&chip->i2c_lock);
+ guard(mutex)(&chip->i2c_lock);
+
regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0);
- mutex_unlock(&chip->i2c_lock);
}
static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
@@ -586,9 +589,8 @@ static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
u32 reg_val;
int ret;
- mutex_lock(&chip->i2c_lock);
- ret = regmap_read(chip->regmap, dirreg, &reg_val);
- mutex_unlock(&chip->i2c_lock);
+ scoped_guard(mutex, &chip->i2c_lock)
+ ret = regmap_read(chip->regmap, dirreg, &reg_val);
if (ret < 0)
return ret;
@@ -605,9 +607,8 @@ static int pca953x_gpio_get_multiple(struct gpio_chip *gc,
DECLARE_BITMAP(reg_val, MAX_LINE);
int ret;
- mutex_lock(&chip->i2c_lock);
- ret = pca953x_read_regs(chip, chip->regs->input, reg_val);
- mutex_unlock(&chip->i2c_lock);
+ scoped_guard(mutex, &chip->i2c_lock)
+ ret = pca953x_read_regs(chip, chip->regs->input, reg_val);
if (ret)
return ret;
@@ -622,16 +623,15 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc,
DECLARE_BITMAP(reg_val, MAX_LINE);
int ret;
- mutex_lock(&chip->i2c_lock);
+ guard(mutex)(&chip->i2c_lock);
+
ret = pca953x_read_regs(chip, chip->regs->output, reg_val);
if (ret)
- goto exit;
+ return;
bitmap_replace(reg_val, reg_val, bits, mask, gc->ngpio);
pca953x_write_regs(chip, chip->regs->output, reg_val);
-exit:
- mutex_unlock(&chip->i2c_lock);
}
static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip,
@@ -639,7 +639,6 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip,
unsigned long config)
{
enum pin_config_param param = pinconf_to_config_param(config);
-
u8 pull_en_reg = chip->recalc_addr(chip, PCAL953X_PULL_EN, offset);
u8 pull_sel_reg = chip->recalc_addr(chip, PCAL953X_PULL_SEL, offset);
u8 bit = BIT(offset % BANK_SZ);
@@ -652,7 +651,7 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip,
if (!(chip->driver_data & PCA_PCAL))
return -ENOTSUPP;
- mutex_lock(&chip->i2c_lock);
+ guard(mutex)(&chip->i2c_lock);
/* Configure pull-up/pull-down */
if (param == PIN_CONFIG_BIAS_PULL_UP)
@@ -662,17 +661,13 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip,
else
ret = 0;
if (ret)
- goto exit;
+ return ret;
/* Disable/Enable pull-up/pull-down */
if (param == PIN_CONFIG_BIAS_DISABLE)
- ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0);
+ return regmap_write_bits(chip->regmap, pull_en_reg, bit, 0);
else
- ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit);
-
-exit:
- mutex_unlock(&chip->i2c_lock);
- return ret;
+ return regmap_write_bits(chip->regmap, pull_en_reg, bit, bit);
}
static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
@@ -693,9 +688,7 @@ static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
{
- struct gpio_chip *gc;
-
- gc = &chip->gpio_chip;
+ struct gpio_chip *gc = &chip->gpio_chip;
gc->direction_input = pca953x_gpio_direction_input;
gc->direction_output = pca953x_gpio_direction_output;
@@ -712,7 +705,6 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
gc->label = dev_name(&chip->client->dev);
gc->parent = &chip->client->dev;
gc->owner = THIS_MODULE;
- gc->names = chip->names;
}
#ifdef CONFIG_GPIO_PCA953X_IRQ
@@ -793,11 +785,11 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct pca953x_chip *chip = gpiochip_get_data(gc);
+ struct device *dev = &chip->client->dev;
irq_hw_number_t hwirq = irqd_to_hwirq(d);
if (!(type & IRQ_TYPE_EDGE_BOTH)) {
- dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
- d->irq, type);
+ dev_err(dev, "irq %d: unsupported type %d\n", d->irq, type);
return -EINVAL;
}
@@ -902,10 +894,8 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
bitmap_zero(pending, MAX_LINE);
- mutex_lock(&chip->i2c_lock);
- ret = pca953x_irq_pending(chip, pending);
- mutex_unlock(&chip->i2c_lock);
-
+ scoped_guard(mutex, &chip->i2c_lock)
+ ret = pca953x_irq_pending(chip, pending);
if (ret) {
ret = 0;
@@ -928,13 +918,15 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base)
{
struct i2c_client *client = chip->client;
+ struct device *dev = &client->dev;
DECLARE_BITMAP(reg_direction, MAX_LINE);
DECLARE_BITMAP(irq_stat, MAX_LINE);
+ struct gpio_chip *gc = &chip->gpio_chip;
struct gpio_irq_chip *girq;
int ret;
if (dmi_first_match(pca953x_dmi_acpi_irq_info)) {
- ret = pca953x_acpi_get_irq(&client->dev);
+ ret = pca953x_acpi_get_irq(dev);
if (ret > 0)
client->irq = ret;
}
@@ -958,7 +950,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base)
* this purpose.
*/
pca953x_read_regs(chip, chip->regs->direction, reg_direction);
- bitmap_and(chip->irq_stat, irq_stat, reg_direction, chip->gpio_chip.ngpio);
+ bitmap_and(chip->irq_stat, irq_stat, reg_direction, gc->ngpio);
mutex_init(&chip->irq_lock);
girq = &chip->gpio_chip.irq;
@@ -972,33 +964,29 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base)
girq->threaded = true;
girq->first = irq_base; /* FIXME: get rid of this */
- ret = devm_request_threaded_irq(&client->dev, client->irq,
- NULL, pca953x_irq_handler,
- IRQF_ONESHOT | IRQF_SHARED,
- dev_name(&client->dev), chip);
- if (ret) {
- dev_err(&client->dev, "failed to request irq %d\n",
- client->irq);
- return ret;
- }
+ ret = devm_request_threaded_irq(dev, client->irq, NULL, pca953x_irq_handler,
+ IRQF_ONESHOT | IRQF_SHARED, dev_name(dev),
+ chip);
+ if (ret)
+ return dev_err_probe(dev, client->irq, "failed to request irq\n");
return 0;
}
#else /* CONFIG_GPIO_PCA953X_IRQ */
-static int pca953x_irq_setup(struct pca953x_chip *chip,
- int irq_base)
+static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base)
{
struct i2c_client *client = chip->client;
+ struct device *dev = &client->dev;
if (client->irq && irq_base != -1 && (chip->driver_data & PCA_INT))
- dev_warn(&client->dev, "interrupt support not compiled in\n");
+ dev_warn(dev, "interrupt support not compiled in\n");
return 0;
}
#endif
-static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert)
+static int device_pca95xx_init(struct pca953x_chip *chip)
{
DECLARE_BITMAP(val, MAX_LINE);
u8 regaddr;
@@ -1008,68 +996,81 @@ static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert)
ret = regcache_sync_region(chip->regmap, regaddr,
regaddr + NBANK(chip) - 1);
if (ret)
- goto out;
+ return ret;
regaddr = chip->recalc_addr(chip, chip->regs->direction, 0);
ret = regcache_sync_region(chip->regmap, regaddr,
regaddr + NBANK(chip) - 1);
if (ret)
- goto out;
+ return ret;
- /* set platform specific polarity inversion */
- if (invert)
- bitmap_fill(val, MAX_LINE);
- else
- bitmap_zero(val, MAX_LINE);
+ /* clear polarity inversion */
+ bitmap_zero(val, MAX_LINE);
- ret = pca953x_write_regs(chip, chip->regs->invert, val);
-out:
- return ret;
+ return pca953x_write_regs(chip, chip->regs->invert, val);
}
-static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
+static int device_pca957x_init(struct pca953x_chip *chip)
{
DECLARE_BITMAP(val, MAX_LINE);
unsigned int i;
int ret;
- ret = device_pca95xx_init(chip, invert);
+ ret = device_pca95xx_init(chip);
if (ret)
- goto out;
+ return ret;
/* To enable register 6, 7 to control pull up and pull down */
for (i = 0; i < NBANK(chip); i++)
bitmap_set_value8(val, 0x02, i * BANK_SZ);
- ret = pca953x_write_regs(chip, PCA957X_BKEN, val);
+ return pca953x_write_regs(chip, PCA957X_BKEN, val);
+}
+
+static void pca953x_disable_regulator(void *reg)
+{
+ regulator_disable(reg);
+}
+
+static int pca953x_get_and_enable_regulator(struct pca953x_chip *chip)
+{
+ struct device *dev = &chip->client->dev;
+ struct regulator *reg = chip->regulator;
+ int ret;
+
+ reg = devm_regulator_get(dev, "vcc");
+ if (IS_ERR(reg))
+ return dev_err_probe(dev, PTR_ERR(reg), "reg get err\n");
+
+ ret = regulator_enable(reg);
if (ret)
- goto out;
+ return dev_err_probe(dev, ret, "reg en err\n");
+ ret = devm_add_action_or_reset(dev, pca953x_disable_regulator, reg);
+ if (ret)
+ return ret;
+
+ chip->regulator = reg;
return 0;
-out:
- return ret;
}
static int pca953x_probe(struct i2c_client *client)
{
+ struct device *dev = &client->dev;
struct pca953x_platform_data *pdata;
struct pca953x_chip *chip;
- int irq_base = 0;
+ int irq_base;
int ret;
- u32 invert = 0;
- struct regulator *reg;
const struct regmap_config *regmap_config;
- chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
- pdata = dev_get_platdata(&client->dev);
+ pdata = dev_get_platdata(dev);
if (pdata) {
irq_base = pdata->irq_base;
chip->gpio_start = pdata->gpio_base;
- invert = pdata->invert;
- chip->names = pdata->names;
} else {
struct gpio_desc *reset_gpio;
@@ -1083,8 +1084,7 @@ static int pca953x_probe(struct i2c_client *client)
* using "reset" GPIO. Otherwise any of those platform
* must use _DSD method with corresponding property.
*/
- reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
- GPIOD_OUT_LOW);
+ reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(reset_gpio))
return PTR_ERR(reset_gpio);
}
@@ -1094,26 +1094,19 @@ static int pca953x_probe(struct i2c_client *client)
if (!chip->driver_data)
return -ENODEV;
- reg = devm_regulator_get(&client->dev, "vcc");
- if (IS_ERR(reg))
- return dev_err_probe(&client->dev, PTR_ERR(reg), "reg get err\n");
-
- ret = regulator_enable(reg);
- if (ret) {
- dev_err(&client->dev, "reg en err: %d\n", ret);
+ ret = pca953x_get_and_enable_regulator(chip);
+ if (ret)
return ret;
- }
- chip->regulator = reg;
i2c_set_clientdata(client, chip);
pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK);
if (NBANK(chip) > 2 || PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) {
- dev_info(&client->dev, "using AI\n");
+ dev_info(dev, "using AI\n");
regmap_config = &pca953x_ai_i2c_regmap;
} else {
- dev_info(&client->dev, "using no AI\n");
+ dev_info(dev, "using no AI\n");
regmap_config = &pca953x_i2c_regmap;
}
@@ -1126,10 +1119,8 @@ static int pca953x_probe(struct i2c_client *client)
}
chip->regmap = devm_regmap_init_i2c(client, regmap_config);
- if (IS_ERR(chip->regmap)) {
- ret = PTR_ERR(chip->regmap);
- goto err_exit;
- }
+ if (IS_ERR(chip->regmap))
+ return PTR_ERR(chip->regmap);
regcache_mark_dirty(chip->regmap);
@@ -1158,53 +1149,24 @@ static int pca953x_probe(struct i2c_client *client)
*/
if (PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) {
chip->regs = &pca957x_regs;
- ret = device_pca957x_init(chip, invert);
+ ret = device_pca957x_init(chip);
} else {
chip->regs = &pca953x_regs;
- ret = device_pca95xx_init(chip, invert);
+ ret = device_pca95xx_init(chip);
}
if (ret)
- goto err_exit;
+ return ret;
ret = pca953x_irq_setup(chip, irq_base);
if (ret)
- goto err_exit;
-
- ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip);
- if (ret)
- goto err_exit;
-
- if (pdata && pdata->setup) {
- ret = pdata->setup(client, chip->gpio_chip.base,
- chip->gpio_chip.ngpio, pdata->context);
- if (ret < 0)
- dev_warn(&client->dev, "setup failed, %d\n", ret);
- }
-
- return 0;
-
-err_exit:
- regulator_disable(chip->regulator);
- return ret;
-}
-
-static void pca953x_remove(struct i2c_client *client)
-{
- struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev);
- struct pca953x_chip *chip = i2c_get_clientdata(client);
-
- if (pdata && pdata->teardown) {
- pdata->teardown(client, chip->gpio_chip.base,
- chip->gpio_chip.ngpio, pdata->context);
- }
+ return ret;
- regulator_disable(chip->regulator);
+ return devm_gpiochip_add_data(dev, &chip->gpio_chip, chip);
}
-#ifdef CONFIG_PM_SLEEP
-static int pca953x_regcache_sync(struct device *dev)
+static int pca953x_regcache_sync(struct pca953x_chip *chip)
{
- struct pca953x_chip *chip = dev_get_drvdata(dev);
+ struct device *dev = &chip->client->dev;
int ret;
u8 regaddr;
@@ -1251,13 +1213,32 @@ static int pca953x_regcache_sync(struct device *dev)
return 0;
}
+static int pca953x_restore_context(struct pca953x_chip *chip)
+{
+ int ret;
+
+ guard(mutex)(&chip->i2c_lock);
+
+ regcache_cache_only(chip->regmap, false);
+ regcache_mark_dirty(chip->regmap);
+ ret = pca953x_regcache_sync(chip);
+ if (ret)
+ return ret;
+
+ return regcache_sync(chip->regmap);
+}
+
+static void pca953x_save_context(struct pca953x_chip *chip)
+{
+ guard(mutex)(&chip->i2c_lock);
+ regcache_cache_only(chip->regmap, true);
+}
+
static int pca953x_suspend(struct device *dev)
{
struct pca953x_chip *chip = dev_get_drvdata(dev);
- mutex_lock(&chip->i2c_lock);
- regcache_cache_only(chip->regmap, true);
- mutex_unlock(&chip->i2c_lock);
+ pca953x_save_context(chip);
if (atomic_read(&chip->wakeup_path))
device_set_wakeup_path(dev);
@@ -1280,25 +1261,14 @@ static int pca953x_resume(struct device *dev)
}
}
- mutex_lock(&chip->i2c_lock);
- regcache_cache_only(chip->regmap, false);
- regcache_mark_dirty(chip->regmap);
- ret = pca953x_regcache_sync(dev);
- if (ret) {
- mutex_unlock(&chip->i2c_lock);
- return ret;
- }
-
- ret = regcache_sync(chip->regmap);
- mutex_unlock(&chip->i2c_lock);
- if (ret) {
+ ret = pca953x_restore_context(chip);
+ if (ret)
dev_err(dev, "Failed to restore register map: %d\n", ret);
- return ret;
- }
- return 0;
+ return ret;
}
-#endif
+
+static DEFINE_SIMPLE_DEV_PM_OPS(pca953x_pm_ops, pca953x_suspend, pca953x_resume);
/* convenience to stop overlong match-table lines */
#define OF_653X(__nrgpio, __int) ((void *)(__nrgpio | PCAL653X_TYPE | __int))
@@ -1356,17 +1326,14 @@ static const struct of_device_id pca953x_dt_ids[] = {
MODULE_DEVICE_TABLE(of, pca953x_dt_ids);
-static SIMPLE_DEV_PM_OPS(pca953x_pm_ops, pca953x_suspend, pca953x_resume);
-
static struct i2c_driver pca953x_driver = {
.driver = {
.name = "pca953x",
- .pm = &pca953x_pm_ops,
+ .pm = pm_sleep_ptr(&pca953x_pm_ops),
.of_match_table = pca953x_dt_ids,
.acpi_match_table = pca953x_acpi_ids,
},
.probe = pca953x_probe,
- .remove = pca953x_remove,
.id_table = pca953x_id,
};
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index cae9661862fe..91cea97255fa 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -260,7 +260,7 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
int ret;
if (pxa_gpio_has_pinctrl()) {
- ret = pinctrl_gpio_direction_input(chip->base + offset);
+ ret = pinctrl_gpio_direction_input(chip, offset);
if (ret)
return ret;
}
@@ -289,7 +289,7 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip,
writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
if (pxa_gpio_has_pinctrl()) {
- ret = pinctrl_gpio_direction_output(chip->base + offset);
+ ret = pinctrl_gpio_direction_output(chip, offset);
if (ret)
return ret;
}
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index 86e69cde04da..6159fda38d5d 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -275,7 +275,7 @@ static int gpio_rcar_request(struct gpio_chip *chip, unsigned offset)
return error;
}
- error = pinctrl_gpio_request(chip->base + offset);
+ error = pinctrl_gpio_request(chip, offset);
if (error)
pm_runtime_put(p->dev);
@@ -286,7 +286,7 @@ static void gpio_rcar_free(struct gpio_chip *chip, unsigned offset)
{
struct gpio_rcar_priv *p = gpiochip_get_data(chip);
- pinctrl_gpio_free(chip->base + offset);
+ pinctrl_gpio_free(chip, offset);
/*
* Set the GPIO as an input to ensure that the next GPIO request won't
@@ -583,14 +583,13 @@ err0:
return ret;
}
-static int gpio_rcar_remove(struct platform_device *pdev)
+static void gpio_rcar_remove(struct platform_device *pdev)
{
struct gpio_rcar_priv *p = platform_get_drvdata(pdev);
gpiochip_remove(&p->gpio_chip);
pm_runtime_disable(&pdev->dev);
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -658,7 +657,7 @@ static SIMPLE_DEV_PM_OPS(gpio_rcar_pm_ops, gpio_rcar_suspend, gpio_rcar_resume);
static struct platform_driver gpio_rcar_device_driver = {
.probe = gpio_rcar_probe,
- .remove = gpio_rcar_remove,
+ .remove_new = gpio_rcar_remove,
.driver = {
.name = "gpio_rcar",
.pm = &gpio_rcar_pm_ops,
diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
index b35b9604413f..0bd339813110 100644
--- a/drivers/gpio/gpio-rockchip.c
+++ b/drivers/gpio/gpio-rockchip.c
@@ -159,9 +159,9 @@ static int rockchip_gpio_set_direction(struct gpio_chip *chip,
if (input)
- pinctrl_gpio_direction_input(bank->pin_base + offset);
+ pinctrl_gpio_direction_input(chip, offset);
else
- pinctrl_gpio_direction_output(bank->pin_base + offset);
+ pinctrl_gpio_direction_output(chip, offset);
raw_spin_lock_irqsave(&bank->slock, flags);
rockchip_gpio_writel_bit(bank, offset, data, bank->gpio_regs->port_ddr);
@@ -778,14 +778,12 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
return 0;
}
-static int rockchip_gpio_remove(struct platform_device *pdev)
+static void rockchip_gpio_remove(struct platform_device *pdev)
{
struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
clk_disable_unprepare(bank->clk);
gpiochip_remove(&bank->gpio_chip);
-
- return 0;
}
static const struct of_device_id rockchip_gpio_match[] = {
@@ -796,7 +794,7 @@ static const struct of_device_id rockchip_gpio_match[] = {
static struct platform_driver rockchip_gpio_driver = {
.probe = rockchip_gpio_probe,
- .remove = rockchip_gpio_remove,
+ .remove_new = rockchip_gpio_remove,
.driver = {
.name = "rockchip-gpio",
.of_match_table = rockchip_gpio_match,
diff --git a/drivers/gpio/gpio-sim.c b/drivers/gpio/gpio-sim.c
index 44bf1709a648..1928209491e1 100644
--- a/drivers/gpio/gpio-sim.c
+++ b/drivers/gpio/gpio-sim.c
@@ -12,6 +12,8 @@
#include <linux/completion.h>
#include <linux/configfs.h>
#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
#include <linux/idr.h>
@@ -30,8 +32,7 @@
#include <linux/string.h>
#include <linux/string_helpers.h>
#include <linux/sysfs.h>
-
-#include "gpiolib.h"
+#include <linux/types.h>
#define GPIO_SIM_NGPIO_MAX 1024
#define GPIO_SIM_PROP_MAX 4 /* Max 3 properties + sentinel. */
@@ -41,6 +42,8 @@ static DEFINE_IDA(gpio_sim_ida);
struct gpio_sim_chip {
struct gpio_chip gc;
+ struct device *dev;
+ unsigned long *request_map;
unsigned long *direction_map;
unsigned long *value_map;
unsigned long *pull_map;
@@ -64,16 +67,11 @@ static int gpio_sim_apply_pull(struct gpio_sim_chip *chip,
unsigned int offset, int value)
{
int irq, irq_type, ret;
- struct gpio_desc *desc;
- struct gpio_chip *gc;
-
- gc = &chip->gc;
- desc = &gc->gpiodev->descs[offset];
guard(mutex)(&chip->lock);
- if (test_bit(FLAG_REQUESTED, &desc->flags) &&
- !test_bit(FLAG_IS_OUT, &desc->flags)) {
+ if (test_bit(offset, chip->request_map) &&
+ test_bit(offset, chip->direction_map)) {
if (value == !!test_bit(offset, chip->value_map))
goto set_pull;
@@ -100,8 +98,8 @@ static int gpio_sim_apply_pull(struct gpio_sim_chip *chip,
set_value:
/* Change the value unless we're actively driving the line. */
- if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
- !test_bit(FLAG_IS_OUT, &desc->flags))
+ if (!test_bit(offset, chip->request_map) ||
+ test_bit(offset, chip->direction_map))
__assign_bit(offset, chip->value_map, value);
set_pull:
@@ -181,8 +179,8 @@ static int gpio_sim_get_direction(struct gpio_chip *gc, unsigned int offset)
return direction ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
}
-static int gpio_sim_set_config(struct gpio_chip *gc,
- unsigned int offset, unsigned long config)
+static int gpio_sim_set_config(struct gpio_chip *gc, unsigned int offset,
+ unsigned long config)
{
struct gpio_sim_chip *chip = gpiochip_get_data(gc);
@@ -205,13 +203,25 @@ static int gpio_sim_to_irq(struct gpio_chip *gc, unsigned int offset)
return irq_create_mapping(chip->irq_sim, offset);
}
-static void gpio_sim_free(struct gpio_chip *gc, unsigned int offset)
+static int gpio_sim_request(struct gpio_chip *gc, unsigned int offset)
{
struct gpio_sim_chip *chip = gpiochip_get_data(gc);
scoped_guard(mutex, &chip->lock)
+ __set_bit(offset, chip->request_map);
+
+ return 0;
+}
+
+static void gpio_sim_free(struct gpio_chip *gc, unsigned int offset)
+{
+ struct gpio_sim_chip *chip = gpiochip_get_data(gc);
+
+ scoped_guard(mutex, &chip->lock) {
__assign_bit(offset, chip->value_map,
!!test_bit(offset, chip->pull_map));
+ __clear_bit(offset, chip->request_map);
+ }
}
static ssize_t gpio_sim_sysfs_val_show(struct device *dev,
@@ -283,6 +293,13 @@ static void gpio_sim_mutex_destroy(void *data)
mutex_destroy(lock);
}
+static void gpio_sim_put_device(void *data)
+{
+ struct device *dev = data;
+
+ put_device(dev);
+}
+
static void gpio_sim_dispose_mappings(void *data)
{
struct gpio_sim_chip *chip = data;
@@ -296,7 +313,7 @@ static void gpio_sim_sysfs_remove(void *data)
{
struct gpio_sim_chip *chip = data;
- sysfs_remove_groups(&chip->gc.gpiodev->dev.kobj, chip->attr_groups);
+ sysfs_remove_groups(&chip->dev->kobj, chip->attr_groups);
}
static int gpio_sim_setup_sysfs(struct gpio_sim_chip *chip)
@@ -353,14 +370,18 @@ static int gpio_sim_setup_sysfs(struct gpio_sim_chip *chip)
chip->attr_groups[i] = attr_group;
}
- ret = sysfs_create_groups(&chip->gc.gpiodev->dev.kobj,
- chip->attr_groups);
+ ret = sysfs_create_groups(&chip->dev->kobj, chip->attr_groups);
if (ret)
return ret;
return devm_add_action_or_reset(dev, gpio_sim_sysfs_remove, chip);
}
+static int gpio_sim_dev_match_fwnode(struct device *dev, void *data)
+{
+ return device_match_fwnode(dev, data);
+}
+
static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
{
struct gpio_sim_chip *chip;
@@ -388,6 +409,10 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
if (!chip)
return -ENOMEM;
+ chip->request_map = devm_bitmap_zalloc(dev, num_lines, GFP_KERNEL);
+ if (!chip->request_map)
+ return -ENOMEM;
+
chip->direction_map = devm_bitmap_alloc(dev, num_lines, GFP_KERNEL);
if (!chip->direction_map)
return -ENOMEM;
@@ -433,6 +458,7 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
gc->get_direction = gpio_sim_get_direction;
gc->set_config = gpio_sim_set_config;
gc->to_irq = gpio_sim_to_irq;
+ gc->request = gpio_sim_request;
gc->free = gpio_sim_free;
gc->can_sleep = true;
@@ -440,8 +466,16 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
if (ret)
return ret;
- /* Used by sysfs and configfs callbacks. */
- dev_set_drvdata(&gc->gpiodev->dev, chip);
+ chip->dev = device_find_child(dev, swnode, gpio_sim_dev_match_fwnode);
+ if (!chip->dev)
+ return -ENODEV;
+
+ ret = devm_add_action_or_reset(dev, gpio_sim_put_device, chip->dev);
+ if (ret)
+ return ret;
+
+ /* Used by sysfs callbacks. */
+ dev_set_drvdata(chip->dev, chip);
return gpio_sim_setup_sysfs(chip);
}
@@ -1438,10 +1472,10 @@ static const struct config_item_type gpio_sim_device_config_group_type = {
static struct config_group *
gpio_sim_config_make_device_group(struct config_group *group, const char *name)
{
- struct gpio_sim_device *dev __free(kfree) = NULL;
int id;
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ struct gpio_sim_device *dev __free(kfree) = kzalloc(sizeof(*dev),
+ GFP_KERNEL);
if (!dev)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c
index f96d260a4a19..e8c1485b9c73 100644
--- a/drivers/gpio/gpio-tb10x.c
+++ b/drivers/gpio/gpio-tb10x.c
@@ -215,7 +215,7 @@ err_remove_domain:
return ret;
}
-static int tb10x_gpio_remove(struct platform_device *pdev)
+static void tb10x_gpio_remove(struct platform_device *pdev)
{
struct tb10x_gpio *tb10x_gpio = platform_get_drvdata(pdev);
@@ -225,8 +225,6 @@ static int tb10x_gpio_remove(struct platform_device *pdev)
kfree(tb10x_gpio->domain->gc);
irq_domain_remove(tb10x_gpio->domain);
}
-
- return 0;
}
static const struct of_device_id tb10x_gpio_dt_ids[] = {
@@ -237,7 +235,7 @@ MODULE_DEVICE_TABLE(of, tb10x_gpio_dt_ids);
static struct platform_driver tb10x_gpio_driver = {
.probe = tb10x_gpio_probe,
- .remove = tb10x_gpio_remove,
+ .remove_new = tb10x_gpio_remove,
.driver = {
.name = "tb10x-gpio",
.of_match_table = tb10x_gpio_dt_ids,
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index ea715582bcf3..ea5f9cc14bc4 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -137,16 +137,11 @@ static void tegra_gpio_disable(struct tegra_gpio_info *tgi, unsigned int gpio)
tegra_gpio_mask_write(tgi, GPIO_MSK_CNF(tgi, gpio), gpio, 0);
}
-static int tegra_gpio_request(struct gpio_chip *chip, unsigned int offset)
-{
- return pinctrl_gpio_request(chip->base + offset);
-}
-
static void tegra_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
- pinctrl_gpio_free(chip->base + offset);
+ pinctrl_gpio_free(chip, offset);
tegra_gpio_disable(tgi, offset);
}
@@ -179,7 +174,7 @@ static int tegra_gpio_direction_input(struct gpio_chip *chip,
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0);
tegra_gpio_enable(tgi, offset);
- ret = pinctrl_gpio_direction_input(chip->base + offset);
+ ret = pinctrl_gpio_direction_input(chip, offset);
if (ret < 0)
dev_err(tgi->dev,
"Failed to set pinctrl input direction of GPIO %d: %d",
@@ -199,7 +194,7 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip,
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1);
tegra_gpio_enable(tgi, offset);
- ret = pinctrl_gpio_direction_output(chip->base + offset);
+ ret = pinctrl_gpio_direction_output(chip, offset);
if (ret < 0)
dev_err(tgi->dev,
"Failed to set pinctrl output direction of GPIO %d: %d",
@@ -717,7 +712,7 @@ static int tegra_gpio_probe(struct platform_device *pdev)
}
tgi->gc.label = "tegra-gpio";
- tgi->gc.request = tegra_gpio_request;
+ tgi->gc.request = pinctrl_gpio_request;
tgi->gc.free = tegra_gpio_free;
tgi->gc.direction_input = tegra_gpio_direction_input;
tgi->gc.get = tegra_gpio_get;
diff --git a/drivers/gpio/gpio-ts5500.c b/drivers/gpio/gpio-ts5500.c
index 8e03614c7a24..90f8e9e9915e 100644
--- a/drivers/gpio/gpio-ts5500.c
+++ b/drivers/gpio/gpio-ts5500.c
@@ -412,13 +412,11 @@ static int ts5500_dio_probe(struct platform_device *pdev)
return 0;
}
-static int ts5500_dio_remove(struct platform_device *pdev)
+static void ts5500_dio_remove(struct platform_device *pdev)
{
struct ts5500_priv *priv = platform_get_drvdata(pdev);
ts5500_disable_irq(priv);
-
- return 0;
}
static const struct platform_device_id ts5500_dio_ids[] = {
@@ -435,7 +433,7 @@ static struct platform_driver ts5500_dio_driver = {
.name = "ts5500-dio",
},
.probe = ts5500_dio_probe,
- .remove = ts5500_dio_remove,
+ .remove_new = ts5500_dio_remove,
.id_table = ts5500_dio_ids,
};
diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c
index 9725b7aa18a7..1f440707f8f4 100644
--- a/drivers/gpio/gpio-uniphier.c
+++ b/drivers/gpio/gpio-uniphier.c
@@ -414,13 +414,11 @@ static int uniphier_gpio_probe(struct platform_device *pdev)
return 0;
}
-static int uniphier_gpio_remove(struct platform_device *pdev)
+static void uniphier_gpio_remove(struct platform_device *pdev)
{
struct uniphier_gpio_priv *priv = platform_get_drvdata(pdev);
irq_domain_remove(priv->domain);
-
- return 0;
}
static int __maybe_unused uniphier_gpio_suspend(struct device *dev)
@@ -482,7 +480,7 @@ MODULE_DEVICE_TABLE(of, uniphier_gpio_match);
static struct platform_driver uniphier_gpio_driver = {
.probe = uniphier_gpio_probe,
- .remove = uniphier_gpio_remove,
+ .remove_new = uniphier_gpio_remove,
.driver = {
.name = "uniphier-gpio",
.of_match_table = uniphier_gpio_match,
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index dbc7ba0ee72c..07e5e6323e86 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -25,6 +25,7 @@
struct fsl_gpio_soc_data {
/* SoCs has a Port Data Direction Register (PDDR) */
bool have_paddr;
+ bool have_dual_base;
};
struct vf610_gpio_port {
@@ -60,13 +61,26 @@ struct vf610_gpio_port {
#define PORT_INT_EITHER_EDGE 0xb
#define PORT_INT_LOGIC_ONE 0xc
+#define IMX8ULP_GPIO_BASE_OFF 0x40
+#define IMX8ULP_BASE_OFF 0x80
+
+static const struct fsl_gpio_soc_data vf610_data = {
+ .have_dual_base = true,
+};
+
static const struct fsl_gpio_soc_data imx_data = {
.have_paddr = true,
+ .have_dual_base = true,
+};
+
+static const struct fsl_gpio_soc_data imx8ulp_data = {
+ .have_paddr = true,
};
static const struct of_device_id vf610_gpio_dt_ids[] = {
- { .compatible = "fsl,vf610-gpio", .data = NULL, },
+ { .compatible = "fsl,vf610-gpio", .data = &vf610_data },
{ .compatible = "fsl,imx7ulp-gpio", .data = &imx_data, },
+ { .compatible = "fsl,imx8ulp-gpio", .data = &imx8ulp_data, },
{ /* sentinel */ }
};
@@ -86,7 +100,7 @@ static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio)
unsigned long mask = BIT(gpio);
unsigned long offset = GPIO_PDIR;
- if (port->sdata && port->sdata->have_paddr) {
+ if (port->sdata->have_paddr) {
mask &= vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
if (mask)
offset = GPIO_PDOR;
@@ -110,13 +124,13 @@ static int vf610_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
unsigned long mask = BIT(gpio);
u32 val;
- if (port->sdata && port->sdata->have_paddr) {
+ if (port->sdata->have_paddr) {
val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
val &= ~mask;
vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR);
}
- return pinctrl_gpio_direction_input(chip->base + gpio);
+ return pinctrl_gpio_direction_input(chip, gpio);
}
static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
@@ -126,15 +140,15 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
unsigned long mask = BIT(gpio);
u32 val;
- if (port->sdata && port->sdata->have_paddr) {
+ vf610_gpio_set(chip, gpio, value);
+
+ if (port->sdata->have_paddr) {
val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
val |= mask;
vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR);
}
- vf610_gpio_set(chip, gpio, value);
-
- return pinctrl_gpio_direction_output(chip->base + gpio);
+ return pinctrl_gpio_direction_output(chip, gpio);
}
static void vf610_gpio_irq_handler(struct irq_desc *desc)
@@ -246,7 +260,8 @@ static const struct irq_chip vf610_irqchip = {
.irq_unmask = vf610_gpio_irq_unmask,
.irq_set_type = vf610_gpio_irq_set_type,
.irq_set_wake = vf610_gpio_irq_set_wake,
- .flags = IRQCHIP_IMMUTABLE,
+ .flags = IRQCHIP_IMMUTABLE | IRQCHIP_MASK_ON_SUSPEND
+ | IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND,
GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
@@ -263,19 +278,41 @@ static int vf610_gpio_probe(struct platform_device *pdev)
struct gpio_irq_chip *girq;
int i;
int ret;
+ bool dual_base;
port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
if (!port)
return -ENOMEM;
port->sdata = of_device_get_match_data(dev);
- port->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(port->base))
- return PTR_ERR(port->base);
- port->gpio_base = devm_platform_ioremap_resource(pdev, 1);
- if (IS_ERR(port->gpio_base))
- return PTR_ERR(port->gpio_base);
+ dual_base = port->sdata->have_dual_base;
+
+ /*
+ * Handle legacy compatible combinations which used two reg values
+ * for the i.MX8ULP and i.MX93.
+ */
+ if (device_is_compatible(dev, "fsl,imx7ulp-gpio") &&
+ (device_is_compatible(dev, "fsl,imx93-gpio") ||
+ (device_is_compatible(dev, "fsl,imx8ulp-gpio"))))
+ dual_base = true;
+
+ if (dual_base) {
+ port->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(port->base))
+ return PTR_ERR(port->base);
+
+ port->gpio_base = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(port->gpio_base))
+ return PTR_ERR(port->gpio_base);
+ } else {
+ port->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(port->base))
+ return PTR_ERR(port->base);
+
+ port->gpio_base = port->base + IMX8ULP_GPIO_BASE_OFF;
+ port->base = port->base + IMX8ULP_BASE_OFF;
+ }
port->irq = platform_get_irq(pdev, 0);
if (port->irq < 0)
diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c
index a809609ee957..bd5befa807c3 100644
--- a/drivers/gpio/gpio-xgene-sb.c
+++ b/drivers/gpio/gpio-xgene-sb.c
@@ -15,7 +15,6 @@
#include <linux/gpio/driver.h>
#include <linux/acpi.h>
-#include "gpiolib.h"
#include "gpiolib-acpi.h"
/* Common property names */
@@ -296,15 +295,13 @@ static int xgene_gpio_sb_probe(struct platform_device *pdev)
return ret;
}
-static int xgene_gpio_sb_remove(struct platform_device *pdev)
+static void xgene_gpio_sb_remove(struct platform_device *pdev)
{
struct xgene_gpio_sb *priv = platform_get_drvdata(pdev);
acpi_gpiochip_free_interrupts(&priv->gc);
irq_domain_remove(priv->irq_domain);
-
- return 0;
}
static const struct of_device_id xgene_gpio_sb_of_match[] = {
@@ -328,7 +325,7 @@ static struct platform_driver xgene_gpio_sb_driver = {
.acpi_match_table = ACPI_PTR(xgene_gpio_sb_acpi_match),
},
.probe = xgene_gpio_sb_probe,
- .remove = xgene_gpio_sb_remove,
+ .remove_new = xgene_gpio_sb_remove,
};
module_platform_driver(xgene_gpio_sb_driver);
diff --git a/drivers/gpio/gpio-xgs-iproc.c b/drivers/gpio/gpio-xgs-iproc.c
index 2d23b27d55af..d445eea03687 100644
--- a/drivers/gpio/gpio-xgs-iproc.c
+++ b/drivers/gpio/gpio-xgs-iproc.c
@@ -291,7 +291,7 @@ static int iproc_gpio_probe(struct platform_device *pdev)
return 0;
}
-static int iproc_gpio_remove(struct platform_device *pdev)
+static void iproc_gpio_remove(struct platform_device *pdev)
{
struct iproc_gpio_chip *chip = platform_get_drvdata(pdev);
@@ -302,8 +302,6 @@ static int iproc_gpio_remove(struct platform_device *pdev)
val &= ~IPROC_CCA_INT_F_GPIOINT;
writel_relaxed(val, chip->intr + IPROC_CCA_INT_MASK);
}
-
- return 0;
}
static const struct of_device_id bcm_iproc_gpio_of_match[] = {
@@ -318,7 +316,7 @@ static struct platform_driver bcm_iproc_gpio_driver = {
.of_match_table = bcm_iproc_gpio_of_match,
},
.probe = iproc_gpio_probe,
- .remove = iproc_gpio_remove,
+ .remove_new = iproc_gpio_remove,
};
module_platform_driver(bcm_iproc_gpio_driver);
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
index a16945e8319e..823198368250 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/gpio-xilinx.c
@@ -332,7 +332,7 @@ static int __maybe_unused xgpio_suspend(struct device *dev)
*
* Return: 0 always
*/
-static int xgpio_remove(struct platform_device *pdev)
+static void xgpio_remove(struct platform_device *pdev)
{
struct xgpio_instance *gpio = platform_get_drvdata(pdev);
@@ -340,8 +340,6 @@ static int xgpio_remove(struct platform_device *pdev)
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(gpio->clk);
-
- return 0;
}
/**
@@ -715,7 +713,7 @@ MODULE_DEVICE_TABLE(of, xgpio_of_match);
static struct platform_driver xgpio_plat_driver = {
.probe = xgpio_probe,
- .remove = xgpio_remove,
+ .remove_new = xgpio_remove,
.driver = {
.name = "gpio-xilinx",
.of_match_table = xgpio_of_match,
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index 324e942c0650..466e23031afc 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -1010,7 +1010,7 @@ err_pm_dis:
*
* Return: 0 always
*/
-static int zynq_gpio_remove(struct platform_device *pdev)
+static void zynq_gpio_remove(struct platform_device *pdev)
{
struct zynq_gpio *gpio = platform_get_drvdata(pdev);
int ret;
@@ -1022,7 +1022,6 @@ static int zynq_gpio_remove(struct platform_device *pdev)
clk_disable_unprepare(gpio->clk);
device_set_wakeup_capable(&pdev->dev, 0);
pm_runtime_disable(&pdev->dev);
- return 0;
}
static struct platform_driver zynq_gpio_driver = {
@@ -1032,7 +1031,7 @@ static struct platform_driver zynq_gpio_driver = {
.of_match_table = zynq_gpio_of_match,
},
.probe = zynq_gpio_probe,
- .remove = zynq_gpio_remove,
+ .remove_new = zynq_gpio_remove,
};
module_platform_driver(zynq_gpio_driver);
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index fbda452fb4d6..88066826d8e5 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -143,7 +143,6 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
*/
static struct gpio_desc *acpi_get_gpiod(char *path, unsigned int pin)
{
- struct gpio_chip *chip;
acpi_handle handle;
acpi_status status;
@@ -151,40 +150,17 @@ static struct gpio_desc *acpi_get_gpiod(char *path, unsigned int pin)
if (ACPI_FAILURE(status))
return ERR_PTR(-ENODEV);
- chip = gpiochip_find(handle, acpi_gpiochip_find);
- if (!chip)
+ struct gpio_device *gdev __free(gpio_device_put) =
+ gpio_device_find(handle, acpi_gpiochip_find);
+ if (!gdev)
return ERR_PTR(-EPROBE_DEFER);
- return gpiochip_get_desc(chip, pin);
-}
-
-/**
- * acpi_get_and_request_gpiod - Translate ACPI GPIO pin to GPIO descriptor and
- * hold a refcount to the GPIO device.
- * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
- * @pin: ACPI GPIO pin number (0-based, controller-relative)
- * @label: Label to pass to gpiod_request()
- *
- * This function is a simple pass-through to acpi_get_gpiod(), except that
- * as it is intended for use outside of the GPIO layer (in a similar fashion to
- * gpiod_get_index() for example) it also holds a reference to the GPIO device.
- */
-struct gpio_desc *acpi_get_and_request_gpiod(char *path, unsigned int pin, char *label)
-{
- struct gpio_desc *gpio;
- int ret;
-
- gpio = acpi_get_gpiod(path, pin);
- if (IS_ERR(gpio))
- return gpio;
-
- ret = gpiod_request(gpio, label);
- if (ret)
- return ERR_PTR(ret);
-
- return gpio;
+ /*
+ * FIXME: keep track of the reference to the GPIO device somehow
+ * instead of putting it here.
+ */
+ return gpio_device_get_desc(gdev, pin);
}
-EXPORT_SYMBOL_GPL(acpi_get_and_request_gpiod);
static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
{
@@ -437,6 +413,11 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
if (!handler)
return AE_OK;
+ if (acpi_gpio_in_ignore_list(ignore_interrupt, dev_name(chip->parent), pin)) {
+ dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin);
+ return AE_OK;
+ }
+
desc = acpi_request_own_gpiod(chip, agpio, 0, "ACPI:Event");
if (IS_ERR(desc)) {
dev_err(chip->parent,
@@ -461,11 +442,6 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
goto fail_unlock_irq;
}
- if (acpi_gpio_in_ignore_list(ignore_interrupt, dev_name(chip->parent), pin)) {
- dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin);
- return AE_OK;
- }
-
event = kzalloc(sizeof(*event), GFP_KERNEL);
if (!event)
goto fail_unlock_irq;
@@ -951,6 +927,7 @@ static struct gpio_desc *acpi_get_gpiod_from_data(struct fwnode_handle *fwnode,
if (!propname)
return ERR_PTR(-EINVAL);
+ memset(&lookup, 0, sizeof(lookup));
lookup.index = index;
ret = acpi_gpio_property_lookup(fwnode, propname, index, &lookup);
@@ -1654,6 +1631,26 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
.ignore_wake = "SYNA1202:00@16",
},
},
+ {
+ /*
+ * On the Peaq C1010 2-in-1 INT33FC:00 pin 3 is connected to
+ * a "dolby" button. At the ACPI level an _AEI event-handler
+ * is connected which sets an ACPI variable to 1 on both
+ * edges. This variable can be polled + cleared to 0 using
+ * WMI. But since the variable is set on both edges the WMI
+ * interface is pretty useless even when polling.
+ * So instead the x86-android-tablets code instantiates
+ * a gpio-keys platform device for it.
+ * Ignore the _AEI handler for the pin, so that it is not busy.
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PEAQ PMM C1010 MD99187"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .ignore_interrupt = "INT33FC:00@3",
+ },
+ },
{} /* Terminating entry */
};
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index e39d344feb28..02ffda6c1e51 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -572,7 +572,7 @@ struct linereq {
DECLARE_KFIFO_PTR(events, struct gpio_v2_line_event);
atomic_t seqno;
struct mutex config_mutex;
- struct line lines[];
+ struct line lines[] __counted_by(num_lines);
};
#define GPIO_V2_LINE_BIAS_FLAGS \
@@ -1656,6 +1656,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
lr = kzalloc(struct_size(lr, lines, ulr.num_lines), GFP_KERNEL);
if (!lr)
return -ENOMEM;
+ lr->num_lines = ulr.num_lines;
lr->gdev = gpio_device_get(gdev);
@@ -1684,7 +1685,6 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
lr->event_buffer_size = GPIO_V2_LINES_MAX * 16;
atomic_set(&lr->seqno, 0);
- lr->num_lines = ulr.num_lines;
/* Request each GPIO */
for (i = 0; i < ulr.num_lines; i++) {
@@ -2287,8 +2287,7 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
* FIXME: find a non-racy way to retrieve this information. Maybe a
* lock common to both frameworks?
*/
- ok_for_pinctrl =
- pinctrl_gpio_can_use_line(gc->base + info->offset);
+ ok_for_pinctrl = pinctrl_gpio_can_use_line(gc, info->offset);
spin_lock_irqsave(&gpio_lock, flags);
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 531faabead0f..402f7d99b0c1 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -127,10 +127,10 @@ static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data)
chip->of_xlate(chip, gpiospec, NULL) >= 0;
}
-static struct gpio_chip *of_find_gpiochip_by_xlate(
- struct of_phandle_args *gpiospec)
+static struct gpio_device *
+of_find_gpio_device_by_xlate(struct of_phandle_args *gpiospec)
{
- return gpiochip_find(gpiospec, of_gpiochip_match_node_and_xlate);
+ return gpio_device_find(gpiospec, of_gpiochip_match_node_and_xlate);
}
static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
@@ -192,6 +192,15 @@ static void of_gpio_try_fixup_polarity(const struct device_node *np,
*/
{ "himax,hx8357", "gpios-reset", false },
{ "himax,hx8369", "gpios-reset", false },
+ /*
+ * The rb-gpios semantics was undocumented and qi,lb60 (along with
+ * the ingenic driver) got it wrong. The active state encodes the
+ * NAND ready state, which is high level. Since there's no signal
+ * inverter on this board, it should be active-high. Let's fix that
+ * here for older DTs so we can re-use the generic nand_gpio_waitrdy()
+ * helper, and be consistent with what other drivers do.
+ */
+ { "qi,lb60", "rb-gpios", true },
#endif
};
unsigned int i;
@@ -363,7 +372,6 @@ static struct gpio_desc *of_get_named_gpiod_flags(const struct device_node *np,
const char *propname, int index, enum of_gpio_flags *flags)
{
struct of_phandle_args gpiospec;
- struct gpio_chip *chip;
struct gpio_desc *desc;
int ret;
@@ -375,13 +383,15 @@ static struct gpio_desc *of_get_named_gpiod_flags(const struct device_node *np,
return ERR_PTR(ret);
}
- chip = of_find_gpiochip_by_xlate(&gpiospec);
- if (!chip) {
+ struct gpio_device *gdev __free(gpio_device_put) =
+ of_find_gpio_device_by_xlate(&gpiospec);
+ if (!gdev) {
desc = ERR_PTR(-EPROBE_DEFER);
goto out;
}
- desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, flags);
+ desc = of_xlate_and_get_gpiod_flags(gpio_device_get_chip(gdev),
+ &gpiospec, flags);
if (IS_ERR(desc))
goto out;
@@ -512,6 +522,10 @@ static struct gpio_desc *of_find_gpio_rename(struct device_node *np,
#if IS_ENABLED(CONFIG_SND_SOC_CS42L56)
{ "reset", "cirrus,gpio-nreset", "cirrus,cs42l56" },
#endif
+#if IS_ENABLED(CONFIG_SND_SOC_MT2701_CS42448)
+ { "i2s1-in-sel-gpio1", NULL, "mediatek,mt2701-cs42448-machine" },
+ { "i2s1-in-sel-gpio2", NULL, "mediatek,mt2701-cs42448-machine" },
+#endif
#if IS_ENABLED(CONFIG_SND_SOC_TLV320AIC3X)
{ "reset", "gpio-reset", "ti,tlv320aic3x" },
{ "reset", "gpio-reset", "ti,tlv320aic33" },
@@ -611,6 +625,33 @@ static struct gpio_desc *of_find_mt2701_gpio(struct device_node *np,
return desc;
}
+/*
+ * Trigger sources are special, they allow us to use any GPIO as a LED trigger
+ * and have the name "trigger-sources" no matter which kind of phandle it is
+ * pointing to, whether to a GPIO, a USB host, a network PHY etc. So in this case
+ * we allow looking something up that is not named "foo-gpios".
+ */
+static struct gpio_desc *of_find_trigger_gpio(struct device_node *np,
+ const char *con_id,
+ unsigned int idx,
+ enum of_gpio_flags *of_flags)
+{
+ struct gpio_desc *desc;
+
+ if (!IS_ENABLED(CONFIG_LEDS_TRIGGER_GPIO))
+ return ERR_PTR(-ENOENT);
+
+ if (!con_id || strcmp(con_id, "trigger-sources"))
+ return ERR_PTR(-ENOENT);
+
+ desc = of_get_named_gpiod_flags(np, con_id, idx, of_flags);
+ if (!gpiod_not_found(desc))
+ pr_debug("%s is used as a trigger\n", of_node_full_name(np));
+
+ return desc;
+}
+
+
typedef struct gpio_desc *(*of_find_gpio_quirk)(struct device_node *np,
const char *con_id,
unsigned int idx,
@@ -618,6 +659,7 @@ typedef struct gpio_desc *(*of_find_gpio_quirk)(struct device_node *np,
static const of_find_gpio_quirk of_find_gpio_quirks[] = {
of_find_gpio_rename,
of_find_mt2701_gpio,
+ of_find_trigger_gpio,
NULL
};
@@ -813,16 +855,16 @@ static int of_gpiochip_match_node(struct gpio_chip *chip, void *data)
return device_match_of_node(&chip->gpiodev->dev, data);
}
-static struct gpio_chip *of_find_gpiochip_by_node(struct device_node *np)
+static struct gpio_device *of_find_gpio_device_by_node(struct device_node *np)
{
- return gpiochip_find(np, of_gpiochip_match_node);
+ return gpio_device_find(np, of_gpiochip_match_node);
}
static int of_gpio_notify(struct notifier_block *nb, unsigned long action,
void *arg)
{
+ struct gpio_device *gdev __free(gpio_device_put) = NULL;
struct of_reconfig_data *rd = arg;
- struct gpio_chip *chip;
int ret;
/*
@@ -834,38 +876,38 @@ static int of_gpio_notify(struct notifier_block *nb, unsigned long action,
switch (of_reconfig_get_state_change(action, arg)) {
case OF_RECONFIG_CHANGE_ADD:
if (!of_property_read_bool(rd->dn, "gpio-hog"))
- return NOTIFY_OK; /* not for us */
+ return NOTIFY_DONE; /* not for us */
if (of_node_test_and_set_flag(rd->dn, OF_POPULATED))
- return NOTIFY_OK;
+ return NOTIFY_DONE;
- chip = of_find_gpiochip_by_node(rd->dn->parent);
- if (chip == NULL)
- return NOTIFY_OK; /* not for us */
+ gdev = of_find_gpio_device_by_node(rd->dn->parent);
+ if (!gdev)
+ return NOTIFY_DONE; /* not for us */
- ret = of_gpiochip_add_hog(chip, rd->dn);
+ ret = of_gpiochip_add_hog(gpio_device_get_chip(gdev), rd->dn);
if (ret < 0) {
pr_err("%s: failed to add hogs for %pOF\n", __func__,
rd->dn);
of_node_clear_flag(rd->dn, OF_POPULATED);
return notifier_from_errno(ret);
}
- break;
+ return NOTIFY_OK;
case OF_RECONFIG_CHANGE_REMOVE:
if (!of_node_check_flag(rd->dn, OF_POPULATED))
- return NOTIFY_OK; /* already depopulated */
+ return NOTIFY_DONE; /* already depopulated */
- chip = of_find_gpiochip_by_node(rd->dn->parent);
- if (chip == NULL)
- return NOTIFY_OK; /* not for us */
+ gdev = of_find_gpio_device_by_node(rd->dn->parent);
+ if (!gdev)
+ return NOTIFY_DONE; /* not for us */
- of_gpiochip_remove_hog(chip, rd->dn);
+ of_gpiochip_remove_hog(gpio_device_get_chip(gdev), rd->dn);
of_node_clear_flag(rd->dn, OF_POPULATED);
- break;
+ return NOTIFY_OK;
}
- return NOTIFY_OK;
+ return NOTIFY_DONE;
}
struct notifier_block gpio_of_notifier = {
diff --git a/drivers/gpio/gpiolib-swnode.c b/drivers/gpio/gpiolib-swnode.c
index b5a6eaf3729b..fa52bdb1a29a 100644
--- a/drivers/gpio/gpiolib-swnode.c
+++ b/drivers/gpio/gpiolib-swnode.c
@@ -31,22 +31,17 @@ static void swnode_format_propname(const char *con_id, char *propname,
strscpy(propname, "gpios", max_size);
}
-static int swnode_gpiochip_match_name(struct gpio_chip *chip, void *data)
+static struct gpio_device *swnode_get_gpio_device(struct fwnode_handle *fwnode)
{
- return !strcmp(chip->label, data);
-}
-
-static struct gpio_chip *swnode_get_chip(struct fwnode_handle *fwnode)
-{
- const struct software_node *chip_node;
- struct gpio_chip *chip;
+ const struct software_node *gdev_node;
+ struct gpio_device *gdev;
- chip_node = to_software_node(fwnode);
- if (!chip_node || !chip_node->name)
+ gdev_node = to_software_node(fwnode);
+ if (!gdev_node || !gdev_node->name)
return ERR_PTR(-EINVAL);
- chip = gpiochip_find((void *)chip_node->name, swnode_gpiochip_match_name);
- return chip ?: ERR_PTR(-EPROBE_DEFER);
+ gdev = gpio_device_find_by_label(gdev_node->name);
+ return gdev ?: ERR_PTR(-EPROBE_DEFER);
}
struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode,
@@ -55,7 +50,6 @@ struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode,
{
const struct software_node *swnode;
struct fwnode_reference_args args;
- struct gpio_chip *chip;
struct gpio_desc *desc;
char propname[32]; /* 32 is max size of property name */
int error;
@@ -77,12 +71,17 @@ struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode,
return ERR_PTR(error);
}
- chip = swnode_get_chip(args.fwnode);
+ struct gpio_device *gdev __free(gpio_device_put) =
+ swnode_get_gpio_device(args.fwnode);
fwnode_handle_put(args.fwnode);
- if (IS_ERR(chip))
- return ERR_CAST(chip);
+ if (IS_ERR(gdev))
+ return ERR_CAST(gdev);
- desc = gpiochip_get_desc(chip, args.args[0]);
+ /*
+ * FIXME: The GPIO device reference is put at return but the descriptor
+ * is passed on. Find a proper solution.
+ */
+ desc = gpio_device_get_desc(gdev, args.args[0]);
*flags = args.args[1]; /* We expect native GPIO flags */
pr_debug("%s: parsed '%s' property of node '%pfwP[%d]' - status (%d)\n",
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 50503a4525eb..12d853845bb8 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -474,14 +474,17 @@ static ssize_t export_store(const struct class *class,
goto done;
status = gpiod_set_transitory(desc, false);
- if (!status) {
- status = gpiod_export(desc, true);
- if (status < 0)
- gpiod_free(desc);
- else
- set_bit(FLAG_SYSFS, &desc->flags);
+ if (status) {
+ gpiod_free(desc);
+ goto done;
}
+ status = gpiod_export(desc, true);
+ if (status < 0)
+ gpiod_free(desc);
+ else
+ set_bit(FLAG_SYSFS, &desc->flags);
+
done:
if (status)
pr_debug("%s: status %d\n", __func__, status);
@@ -814,7 +817,7 @@ static int __init gpiolib_sysfs_init(void)
* gpiochip_sysfs_register() acquires a mutex. This is unsafe
* and needs to be fixed.
*
- * Also it would be nice to use gpiochip_find() here so we
+ * Also it would be nice to use gpio_device_find() here so we
* can keep gpio_chips local to gpiolib.c, but the yield of
* gpio_lock prevents us from doing this.
*/
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 40a0022ea719..95d2a7b2ea3e 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -20,6 +20,7 @@
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/string.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
@@ -146,27 +147,49 @@ struct gpio_desc *gpio_to_desc(unsigned gpio)
}
EXPORT_SYMBOL_GPL(gpio_to_desc);
+/* This function is deprecated and will be removed soon, don't use. */
+struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc,
+ unsigned int hwnum)
+{
+ return gpio_device_get_desc(gc->gpiodev, hwnum);
+}
+EXPORT_SYMBOL_GPL(gpiochip_get_desc);
+
/**
- * gpiochip_get_desc - get the GPIO descriptor corresponding to the given
- * hardware number for this chip
- * @gc: GPIO chip
+ * gpio_device_get_desc() - get the GPIO descriptor corresponding to the given
+ * hardware number for this GPIO device
+ * @gdev: GPIO device to get the descriptor from
* @hwnum: hardware number of the GPIO for this chip
*
* Returns:
- * A pointer to the GPIO descriptor or ``ERR_PTR(-EINVAL)`` if no GPIO exists
- * in the given chip for the specified hardware number.
+ * A pointer to the GPIO descriptor or %EINVAL if no GPIO exists in the given
+ * chip for the specified hardware number or %ENODEV if the underlying chip
+ * already vanished.
+ *
+ * The reference count of struct gpio_device is *NOT* increased like when the
+ * GPIO is being requested for exclusive usage. It's up to the caller to make
+ * sure the GPIO device will stay alive together with the descriptor returned
+ * by this function.
*/
-struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc,
- unsigned int hwnum)
+struct gpio_desc *
+gpio_device_get_desc(struct gpio_device *gdev, unsigned int hwnum)
{
- struct gpio_device *gdev = gc->gpiodev;
+ struct gpio_chip *gc;
+
+ /*
+ * FIXME: This will be locked once we protect gdev->chip everywhere
+ * with SRCU.
+ */
+ gc = gdev->chip;
+ if (!gc)
+ return ERR_PTR(-ENODEV);
if (hwnum >= gdev->ngpio)
return ERR_PTR(-EINVAL);
return &gdev->descs[hwnum];
}
-EXPORT_SYMBOL_GPL(gpiochip_get_desc);
+EXPORT_SYMBOL_GPL(gpio_device_get_desc);
/**
* desc_to_gpio - convert a GPIO descriptor to the integer namespace
@@ -197,6 +220,61 @@ struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
}
EXPORT_SYMBOL_GPL(gpiod_to_chip);
+/**
+ * gpiod_to_gpio_device() - Return the GPIO device to which this descriptor
+ * belongs.
+ * @desc: Descriptor for which to return the GPIO device.
+ *
+ * This *DOES NOT* increase the reference count of the GPIO device as it's
+ * expected that the descriptor is requested and the users already holds a
+ * reference to the device.
+ *
+ * Returns:
+ * Address of the GPIO device owning this descriptor.
+ */
+struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc)
+{
+ if (!desc)
+ return NULL;
+
+ return desc->gdev;
+}
+EXPORT_SYMBOL_GPL(gpiod_to_gpio_device);
+
+/**
+ * gpio_device_get_base() - Get the base GPIO number allocated by this device
+ * @gdev: GPIO device
+ *
+ * Returns:
+ * First GPIO number in the global GPIO numberspace for this device.
+ */
+int gpio_device_get_base(struct gpio_device *gdev)
+{
+ return gdev->base;
+}
+EXPORT_SYMBOL_GPL(gpio_device_get_base);
+
+/**
+ * gpio_device_get_chip() - Get the gpio_chip implementation of this GPIO device
+ * @gdev: GPIO device
+ *
+ * Returns:
+ * Address of the GPIO chip backing this device.
+ *
+ * Until we can get rid of all non-driver users of struct gpio_chip, we must
+ * provide a way of retrieving the pointer to it from struct gpio_device. This
+ * is *NOT* safe as the GPIO API is considered to be hot-unpluggable and the
+ * chip can dissapear at any moment (unlike reference-counted struct
+ * gpio_device).
+ *
+ * Use at your own risk.
+ */
+struct gpio_chip *gpio_device_get_chip(struct gpio_device *gdev)
+{
+ return gdev->chip;
+}
+EXPORT_SYMBOL_GPL(gpio_device_get_chip);
+
/* dynamic allocation of GPIOs, e.g. on a hotplugged device */
static int gpiochip_find_base(int ngpio)
{
@@ -1015,48 +1093,130 @@ void gpiochip_remove(struct gpio_chip *gc)
EXPORT_SYMBOL_GPL(gpiochip_remove);
/**
- * gpiochip_find() - iterator for locating a specific gpio_chip
+ * gpio_device_find() - find a specific GPIO device
* @data: data to pass to match function
* @match: Callback function to check gpio_chip
*
- * Similar to bus_find_device. It returns a reference to a gpio_chip as
- * determined by a user supplied @match callback. The callback should return
- * 0 if the device doesn't match and non-zero if it does. If the callback is
- * non-zero, this function will return to the caller and not iterate over any
- * more gpio_chips.
+ * Returns:
+ * New reference to struct gpio_device.
+ *
+ * Similar to bus_find_device(). It returns a reference to a gpio_device as
+ * determined by a user supplied @match callback. The callback should return
+ * 0 if the device doesn't match and non-zero if it does. If the callback
+ * returns non-zero, this function will return to the caller and not iterate
+ * over any more gpio_devices.
+ *
+ * The callback takes the GPIO chip structure as argument. During the execution
+ * of the callback function the chip is protected from being freed. TODO: This
+ * actually has yet to be implemented.
+ *
+ * If the function returns non-NULL, the returned reference must be freed by
+ * the caller using gpio_device_put().
*/
-struct gpio_chip *gpiochip_find(void *data,
- int (*match)(struct gpio_chip *gc,
- void *data))
+struct gpio_device *gpio_device_find(void *data,
+ int (*match)(struct gpio_chip *gc,
+ void *data))
{
struct gpio_device *gdev;
- struct gpio_chip *gc = NULL;
- unsigned long flags;
- spin_lock_irqsave(&gpio_lock, flags);
- list_for_each_entry(gdev, &gpio_devices, list)
- if (gdev->chip && match(gdev->chip, data)) {
- gc = gdev->chip;
- break;
- }
+ /*
+ * Not yet but in the future the spinlock below will become a mutex.
+ * Annotate this function before anyone tries to use it in interrupt
+ * context like it happened with gpiochip_find().
+ */
+ might_sleep();
- spin_unlock_irqrestore(&gpio_lock, flags);
+ guard(spinlock_irqsave)(&gpio_lock);
- return gc;
+ list_for_each_entry(gdev, &gpio_devices, list) {
+ if (gdev->chip && match(gdev->chip, data))
+ return gpio_device_get(gdev);
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gpio_device_find);
+
+static int gpio_chip_match_by_label(struct gpio_chip *gc, void *label)
+{
+ return gc->label && !strcmp(gc->label, label);
+}
+
+/**
+ * gpio_device_find_by_label() - wrapper around gpio_device_find() finding the
+ * GPIO device by its backing chip's label
+ * @label: Label to lookup
+ *
+ * Returns:
+ * Reference to the GPIO device or NULL. Reference must be released with
+ * gpio_device_put().
+ */
+struct gpio_device *gpio_device_find_by_label(const char *label)
+{
+ return gpio_device_find((void *)label, gpio_chip_match_by_label);
}
-EXPORT_SYMBOL_GPL(gpiochip_find);
+EXPORT_SYMBOL_GPL(gpio_device_find_by_label);
-static int gpiochip_match_name(struct gpio_chip *gc, void *data)
+static int gpio_chip_match_by_fwnode(struct gpio_chip *gc, void *fwnode)
{
- const char *name = data;
+ return device_match_fwnode(&gc->gpiodev->dev, fwnode);
+}
- return !strcmp(gc->label, name);
+/**
+ * gpio_device_find_by_fwnode() - wrapper around gpio_device_find() finding
+ * the GPIO device by its fwnode
+ * @fwnode: Firmware node to lookup
+ *
+ * Returns:
+ * Reference to the GPIO device or NULL. Reference must be released with
+ * gpio_device_put().
+ */
+struct gpio_device *gpio_device_find_by_fwnode(const struct fwnode_handle *fwnode)
+{
+ return gpio_device_find((void *)fwnode, gpio_chip_match_by_fwnode);
}
+EXPORT_SYMBOL_GPL(gpio_device_find_by_fwnode);
-static struct gpio_chip *find_chip_by_name(const char *name)
+/**
+ * gpio_device_get() - Increase the reference count of this GPIO device
+ * @gdev: GPIO device to increase the refcount for
+ *
+ * Returns:
+ * Pointer to @gdev.
+ */
+struct gpio_device *gpio_device_get(struct gpio_device *gdev)
{
- return gpiochip_find((void *)name, gpiochip_match_name);
+ return to_gpio_device(get_device(&gdev->dev));
}
+EXPORT_SYMBOL_GPL(gpio_device_get);
+
+/**
+ * gpio_device_put() - Decrease the reference count of this GPIO device and
+ * possibly free all resources associated with it.
+ * @gdev: GPIO device to decrease the reference count for
+ */
+void gpio_device_put(struct gpio_device *gdev)
+{
+ put_device(&gdev->dev);
+}
+EXPORT_SYMBOL_GPL(gpio_device_put);
+
+/**
+ * gpio_device_to_device() - Retrieve the address of the underlying struct
+ * device.
+ * @gdev: GPIO device for which to return the address.
+ *
+ * This does not increase the reference count of the GPIO device nor the
+ * underlying struct device.
+ *
+ * Returns:
+ * Address of struct device backing this GPIO device.
+ */
+struct device *gpio_device_to_device(struct gpio_device *gdev)
+{
+ return &gdev->dev;
+}
+EXPORT_SYMBOL_GPL(gpio_device_to_device);
#ifdef CONFIG_GPIOLIB_IRQCHIP
@@ -1854,7 +2014,7 @@ int gpiochip_generic_request(struct gpio_chip *gc, unsigned int offset)
return 0;
#endif
- return pinctrl_gpio_request(gc->gpiodev->base + offset);
+ return pinctrl_gpio_request(gc, offset);
}
EXPORT_SYMBOL_GPL(gpiochip_generic_request);
@@ -1870,7 +2030,7 @@ void gpiochip_generic_free(struct gpio_chip *gc, unsigned int offset)
return;
#endif
- pinctrl_gpio_free(gc->gpiodev->base + offset);
+ pinctrl_gpio_free(gc, offset);
}
EXPORT_SYMBOL_GPL(gpiochip_generic_free);
@@ -1883,7 +2043,7 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_free);
int gpiochip_generic_config(struct gpio_chip *gc, unsigned int offset,
unsigned long config)
{
- return pinctrl_gpio_set_config(gc->gpiodev->base + offset, config);
+ return pinctrl_gpio_set_config(gc, offset, config);
}
EXPORT_SYMBOL_GPL(gpiochip_generic_config);
@@ -2700,7 +2860,6 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory)
PIN_CONFIG_PERSIST_STATE,
!transitory);
}
-EXPORT_SYMBOL_GPL(gpiod_set_transitory);
/**
* gpiod_is_active_low - test whether a GPIO is active-low or not
@@ -3786,7 +3945,6 @@ EXPORT_SYMBOL_GPL(gpiod_remove_lookup_table);
*/
void gpiod_add_hogs(struct gpiod_hog *hogs)
{
- struct gpio_chip *gc;
struct gpiod_hog *hog;
mutex_lock(&gpio_machine_hogs_mutex);
@@ -3798,9 +3956,10 @@ void gpiod_add_hogs(struct gpiod_hog *hogs)
* The chip may have been registered earlier, so check if it
* exists and, if so, try to hog the line now.
*/
- gc = find_chip_by_name(hog->chip_label);
- if (gc)
- gpiochip_machine_hog(gc, hog);
+ struct gpio_device *gdev __free(gpio_device_put) =
+ gpio_device_find_by_label(hog->chip_label);
+ if (gdev)
+ gpiochip_machine_hog(gpio_device_get_chip(gdev), hog);
}
mutex_unlock(&gpio_machine_hogs_mutex);
@@ -3823,8 +3982,6 @@ static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)
const char *dev_id = dev ? dev_name(dev) : NULL;
struct gpiod_lookup_table *table;
- mutex_lock(&gpio_lookup_lock);
-
list_for_each_entry(table, &gpio_lookup_list, list) {
if (table->dev_id && dev_id) {
/*
@@ -3832,21 +3989,18 @@ static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)
* a match
*/
if (!strcmp(table->dev_id, dev_id))
- goto found;
+ return table;
} else {
/*
* One of the pointers is NULL, so both must be to have
* a match
*/
if (dev_id == table->dev_id)
- goto found;
+ return table;
}
}
- table = NULL;
-found:
- mutex_unlock(&gpio_lookup_lock);
- return table;
+ return NULL;
}
static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
@@ -3855,14 +4009,15 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
struct gpio_desc *desc = ERR_PTR(-ENOENT);
struct gpiod_lookup_table *table;
struct gpiod_lookup *p;
+ struct gpio_chip *gc;
+
+ guard(mutex)(&gpio_lookup_lock);
table = gpiod_find_lookup_table(dev);
if (!table)
return desc;
for (p = &table->table[0]; p->key; p++) {
- struct gpio_chip *gc;
-
/* idx must always match exactly */
if (p->idx != idx)
continue;
@@ -3883,9 +4038,9 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
return ERR_PTR(-EPROBE_DEFER);
}
- gc = find_chip_by_name(p->key);
-
- if (!gc) {
+ struct gpio_device *gdev __free(gpio_device_put) =
+ gpio_device_find_by_label(p->key);
+ if (!gdev) {
/*
* As the lookup table indicates a chip with
* p->key should exist, assume it may
@@ -3898,6 +4053,8 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
return ERR_PTR(-EPROBE_DEFER);
}
+ gc = gpio_device_get_chip(gdev);
+
if (gc->ngpio <= p->chip_hwnum) {
dev_err(dev,
"requested GPIO %u (%u) is out of range [0..%u] for chip %s\n",
@@ -3906,7 +4063,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
return ERR_PTR(-EINVAL);
}
- desc = gpiochip_get_desc(gc, p->chip_hwnum);
+ desc = gpio_device_get_desc(gdev, p->chip_hwnum);
*flags = p->flags;
return desc;
@@ -3921,15 +4078,18 @@ static int platform_gpio_count(struct device *dev, const char *con_id)
struct gpiod_lookup *p;
unsigned int count = 0;
- table = gpiod_find_lookup_table(dev);
- if (!table)
- return -ENOENT;
+ scoped_guard(mutex, &gpio_lookup_lock) {
+ table = gpiod_find_lookup_table(dev);
+ if (!table)
+ return -ENOENT;
- for (p = &table->table[0]; p->key; p++) {
- if ((con_id && p->con_id && !strcmp(con_id, p->con_id)) ||
- (!con_id && !p->con_id))
- count++;
+ for (p = &table->table[0]; p->key; p++) {
+ if ((con_id && p->con_id && !strcmp(con_id, p->con_id)) ||
+ (!con_id && !p->con_id))
+ count++;
+ }
}
+
if (!count)
return -ENOENT;
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index a0a67569300b..3ccacf3c1288 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -86,16 +86,6 @@ static inline struct gpio_device *to_gpio_device(struct device *dev)
return container_of(dev, struct gpio_device, dev);
}
-static inline struct gpio_device *gpio_device_get(struct gpio_device *gdev)
-{
- return to_gpio_device(get_device(&gdev->dev));
-}
-
-static inline void gpio_device_put(struct gpio_device *gdev)
-{
- put_device(&gdev->dev);
-}
-
/* gpio suffixes used for ACPI and device tree lookup */
static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" };
@@ -122,8 +112,6 @@ struct gpio_array {
unsigned long invert_mask[];
};
-struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum);
-
#define for_each_gpio_desc(gc, desc) \
for (unsigned int __i = 0; \
__i < gc->ngpio && (desc = gpiochip_get_desc(gc, __i)); \
@@ -144,6 +132,8 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
struct gpio_array *array_info,
unsigned long *value_bitmap);
+int gpiod_set_transitory(struct gpio_desc *desc, bool transitory);
+
extern spinlock_t gpio_lock;
extern struct list_head gpio_devices;
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 3caa020391c7..3eee8636f847 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -216,6 +216,13 @@ config DRM_EXEC
help
Execution context for command submissions
+config DRM_GPUVM
+ tristate
+ depends on DRM
+ help
+ GPU-VM representation providing helpers to manage a GPUs virtual
+ address space
+
config DRM_BUDDY
tristate
depends on DRM
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 215e78e79125..8e1bde059170 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -45,7 +45,6 @@ drm-y := \
drm_vblank.o \
drm_vblank_work.o \
drm_vma_manager.o \
- drm_gpuva_mgr.o \
drm_writeback.o
drm-$(CONFIG_DRM_LEGACY) += \
drm_agpsupport.o \
@@ -81,6 +80,7 @@ obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
#
#
obj-$(CONFIG_DRM_EXEC) += drm_exec.o
+obj-$(CONFIG_DRM_GPUVM) += drm_gpuvm.o
obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 384b798a9bad..2afecc55090f 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -98,13 +98,14 @@ amdgpu-y += \
vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o arct_reg_init.o mxgpu_nv.o \
nbio_v7_2.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o soc21.o \
sienna_cichlid.o smu_v13_0_10.o nbio_v4_3.o hdp_v6_0.o nbio_v7_7.o hdp_v5_2.o lsdma_v6_0.o \
- nbio_v7_9.o aqua_vanjaram.o
+ nbio_v7_9.o aqua_vanjaram.o nbio_v7_11.o
# add DF block
amdgpu-y += \
df_v1_7.o \
df_v3_6.o \
- df_v4_3.o
+ df_v4_3.o \
+ df_v4_6_2.o
# add GMC block
amdgpu-y += \
@@ -113,11 +114,12 @@ amdgpu-y += \
gfxhub_v1_0.o mmhub_v1_0.o gmc_v9_0.o gfxhub_v1_1.o mmhub_v9_4.o \
gfxhub_v2_0.o mmhub_v2_0.o gmc_v10_0.o gfxhub_v2_1.o mmhub_v2_3.o \
mmhub_v1_7.o gfxhub_v3_0.o mmhub_v3_0.o mmhub_v3_0_2.o gmc_v11_0.o \
- mmhub_v3_0_1.o gfxhub_v3_0_3.o gfxhub_v1_2.o mmhub_v1_8.o
+ mmhub_v3_0_1.o gfxhub_v3_0_3.o gfxhub_v1_2.o mmhub_v1_8.o mmhub_v3_3.o \
+ gfxhub_v11_5_0.o
# add UMC block
amdgpu-y += \
- umc_v6_0.o umc_v6_1.o umc_v6_7.o umc_v8_7.o umc_v8_10.o
+ umc_v6_0.o umc_v6_1.o umc_v6_7.o umc_v8_7.o umc_v8_10.o umc_v12_0.o
# add IH block
amdgpu-y += \
@@ -205,14 +207,27 @@ amdgpu-y += \
vcn_v3_0.o \
vcn_v4_0.o \
vcn_v4_0_3.o \
+ vcn_v4_0_5.o \
amdgpu_jpeg.o \
jpeg_v1_0.o \
jpeg_v2_0.o \
jpeg_v2_5.o \
jpeg_v3_0.o \
jpeg_v4_0.o \
- jpeg_v4_0_3.o
+ jpeg_v4_0_3.o \
+ jpeg_v4_0_5.o
+# add VPE block
+amdgpu-y += \
+ amdgpu_vpe.o \
+ vpe_v6_1.o
+
+# add UMSCH block
+amdgpu-y += \
+ amdgpu_umsch_mm.o \
+ umsch_mm_v4_0.o
+
+#
# add ATHUB block
amdgpu-y += \
athub_v1_0.o \
diff --git a/drivers/gpu/drm/amd/amdgpu/aldebaran.c b/drivers/gpu/drm/amd/amdgpu/aldebaran.c
index 2b97b8a96fb4..02f4c6f9d4f6 100644
--- a/drivers/gpu/drm/amd/amdgpu/aldebaran.c
+++ b/drivers/gpu/drm/amd/amdgpu/aldebaran.c
@@ -35,7 +35,7 @@ static bool aldebaran_is_mode2_default(struct amdgpu_reset_control *reset_ctl)
{
struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;
- if ((adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2) &&
+ if ((amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 2) &&
adev->gmc.xgmi.connected_to_cpu))
return true;
@@ -48,27 +48,24 @@ aldebaran_get_reset_handler(struct amdgpu_reset_control *reset_ctl,
{
struct amdgpu_reset_handler *handler;
struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;
+ int i;
+
+ if (reset_context->method == AMD_RESET_METHOD_NONE) {
+ if (aldebaran_is_mode2_default(reset_ctl))
+ reset_context->method = AMD_RESET_METHOD_MODE2;
+ else
+ reset_context->method = amdgpu_asic_reset_method(adev);
+ }
if (reset_context->method != AMD_RESET_METHOD_NONE) {
dev_dbg(adev->dev, "Getting reset handler for method %d\n",
reset_context->method);
- list_for_each_entry(handler, &reset_ctl->reset_handlers,
- handler_list) {
+ for_each_handler(i, handler, reset_ctl) {
if (handler->reset_method == reset_context->method)
return handler;
}
}
- if (aldebaran_is_mode2_default(reset_ctl)) {
- list_for_each_entry(handler, &reset_ctl->reset_handlers,
- handler_list) {
- if (handler->reset_method == AMD_RESET_METHOD_MODE2) {
- reset_context->method = AMD_RESET_METHOD_MODE2;
- return handler;
- }
- }
- }
-
dev_dbg(adev->dev, "Reset handler not found!\n");
return NULL;
@@ -124,9 +121,9 @@ static void aldebaran_async_reset(struct work_struct *work)
struct amdgpu_reset_control *reset_ctl =
container_of(work, struct amdgpu_reset_control, reset_work);
struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;
+ int i;
- list_for_each_entry(handler, &reset_ctl->reset_handlers,
- handler_list) {
+ for_each_handler(i, handler, reset_ctl) {
if (handler->reset_method == reset_ctl->active_reset) {
dev_dbg(adev->dev, "Resetting device\n");
handler->do_reset(adev);
@@ -157,7 +154,7 @@ aldebaran_mode2_perform_reset(struct amdgpu_reset_control *reset_ctl,
if (reset_device_list == NULL)
return -EINVAL;
- if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2) &&
+ if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 2) &&
reset_context->hive == NULL) {
/* Wrong context, return error */
return -EINVAL;
@@ -338,7 +335,7 @@ aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
if (reset_device_list == NULL)
return -EINVAL;
- if (reset_context->reset_req_dev->ip_versions[MP1_HWIP][0] ==
+ if (amdgpu_ip_version(reset_context->reset_req_dev, MP1_HWIP, 0) ==
IP_VERSION(13, 0, 2) &&
reset_context->hive == NULL) {
/* Wrong context, return error */
@@ -395,6 +392,11 @@ static struct amdgpu_reset_handler aldebaran_mode2_handler = {
.do_reset = aldebaran_mode2_reset,
};
+static struct amdgpu_reset_handler
+ *aldebaran_rst_handlers[AMDGPU_RESET_MAX_HANDLERS] = {
+ &aldebaran_mode2_handler,
+ };
+
int aldebaran_reset_init(struct amdgpu_device *adev)
{
struct amdgpu_reset_control *reset_ctl;
@@ -408,10 +410,9 @@ int aldebaran_reset_init(struct amdgpu_device *adev)
reset_ctl->active_reset = AMD_RESET_METHOD_NONE;
reset_ctl->get_reset_handler = aldebaran_get_reset_handler;
- INIT_LIST_HEAD(&reset_ctl->reset_handlers);
INIT_WORK(&reset_ctl->reset_work, reset_ctl->async_reset);
/* Only mode2 is handled through reset control now */
- amdgpu_reset_add_handler(reset_ctl, &aldebaran_mode2_handler);
+ reset_ctl->reset_handlers = &aldebaran_rst_handlers;
adev->reset_cntl = reset_ctl;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index a79d53bdbe13..9d92ca157677 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -79,6 +79,8 @@
#include "amdgpu_vce.h"
#include "amdgpu_vcn.h"
#include "amdgpu_jpeg.h"
+#include "amdgpu_vpe.h"
+#include "amdgpu_umsch_mm.h"
#include "amdgpu_gmc.h"
#include "amdgpu_gfx.h"
#include "amdgpu_sdma.h"
@@ -242,8 +244,11 @@ extern int amdgpu_num_kcq;
#define AMDGPU_VCNFW_LOG_SIZE (32 * 1024)
extern int amdgpu_vcnfw_log;
extern int amdgpu_sg_display;
+extern int amdgpu_umsch_mm;
+extern int amdgpu_seamless;
extern int amdgpu_user_partt_mode;
+extern int amdgpu_agp;
#define AMDGPU_VM_MAX_NUM_CTX 4096
#define AMDGPU_SG_THRESHOLD (256*1024*1024)
@@ -359,9 +364,6 @@ struct amdgpu_ip_block_version {
const struct amd_ip_funcs *funcs;
};
-#define HW_REV(_Major, _Minor, _Rev) \
- ((((uint32_t) (_Major)) << 16) | ((uint32_t) (_Minor) << 8) | ((uint32_t) (_Rev)))
-
struct amdgpu_ip_block {
struct amdgpu_ip_block_status status;
const struct amdgpu_ip_block_version *version;
@@ -623,6 +625,9 @@ typedef void (*amdgpu_wreg_ext_t)(struct amdgpu_device*, uint64_t, uint32_t);
typedef uint64_t (*amdgpu_rreg64_t)(struct amdgpu_device*, uint32_t);
typedef void (*amdgpu_wreg64_t)(struct amdgpu_device*, uint32_t, uint64_t);
+typedef uint64_t (*amdgpu_rreg64_ext_t)(struct amdgpu_device*, uint64_t);
+typedef void (*amdgpu_wreg64_ext_t)(struct amdgpu_device*, uint64_t, uint64_t);
+
typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t);
@@ -654,6 +659,7 @@ enum amd_hw_ip_block_type {
JPEG_HWIP = VCN_HWIP,
VCN1_HWIP,
VCE_HWIP,
+ VPE_HWIP,
DF_HWIP,
DCE_HWIP,
OSSSYS_HWIP,
@@ -673,10 +679,15 @@ enum amd_hw_ip_block_type {
#define HWIP_MAX_INSTANCE 44
#define HW_ID_MAX 300
-#define IP_VERSION(mj, mn, rv) (((mj) << 16) | ((mn) << 8) | (rv))
-#define IP_VERSION_MAJ(ver) ((ver) >> 16)
-#define IP_VERSION_MIN(ver) (((ver) >> 8) & 0xFF)
-#define IP_VERSION_REV(ver) ((ver) & 0xFF)
+#define IP_VERSION_FULL(mj, mn, rv, var, srev) \
+ (((mj) << 24) | ((mn) << 16) | ((rv) << 8) | ((var) << 4) | (srev))
+#define IP_VERSION(mj, mn, rv) IP_VERSION_FULL(mj, mn, rv, 0, 0)
+#define IP_VERSION_MAJ(ver) ((ver) >> 24)
+#define IP_VERSION_MIN(ver) (((ver) >> 16) & 0xFF)
+#define IP_VERSION_REV(ver) (((ver) >> 8) & 0xFF)
+#define IP_VERSION_VARIANT(ver) (((ver) >> 4) & 0xF)
+#define IP_VERSION_SUBREV(ver) ((ver) & 0xF)
+#define IP_VERSION_MAJ_MIN_REV(ver) ((ver) >> 8)
struct amdgpu_ip_map_info {
/* Map of logical to actual dev instances/mask */
@@ -757,8 +768,19 @@ struct amdgpu_mqd {
#define AMDGPU_RESET_MAGIC_NUM 64
#define AMDGPU_MAX_DF_PERFMONS 4
-#define AMDGPU_PRODUCT_NAME_LEN 64
struct amdgpu_reset_domain;
+struct amdgpu_fru_info;
+
+struct amdgpu_reset_info {
+ /* reset dump register */
+ u32 *reset_dump_reg_list;
+ u32 *reset_dump_reg_value;
+ int num_regs;
+
+#ifdef CONFIG_DEV_COREDUMP
+ struct amdgpu_coredump_info *coredump_info;
+#endif
+};
/*
* Non-zero (true) if the GPU has VRAM. Zero (false) otherwise.
@@ -826,6 +848,8 @@ struct amdgpu_device {
amdgpu_wreg_ext_t pcie_wreg_ext;
amdgpu_rreg64_t pcie_rreg64;
amdgpu_wreg64_t pcie_wreg64;
+ amdgpu_rreg64_ext_t pcie_rreg64_ext;
+ amdgpu_wreg64_ext_t pcie_wreg64_ext;
/* protects concurrent UVD register access */
spinlock_t uvd_ctx_idx_lock;
amdgpu_rreg_t uvd_ctx_rreg;
@@ -946,6 +970,13 @@ struct amdgpu_device {
/* jpeg */
struct amdgpu_jpeg jpeg;
+ /* vpe */
+ struct amdgpu_vpe vpe;
+
+ /* umsch */
+ struct amdgpu_umsch_mm umsch_mm;
+ bool enable_umsch_mm;
+
/* firmwares */
struct amdgpu_firmware firmware;
@@ -1033,11 +1064,7 @@ struct amdgpu_device {
bool ucode_sysfs_en;
- /* Chip product information */
- char product_number[20];
- char product_name[AMDGPU_PRODUCT_NAME_LEN];
- char serial[20];
-
+ struct amdgpu_fru_info *fru_info;
atomic_t throttling_logging_enabled;
struct ratelimit_state throttling_logging_rs;
uint32_t ras_hw_enabled;
@@ -1063,15 +1090,7 @@ struct amdgpu_device {
struct mutex benchmark_mutex;
- /* reset dump register */
- uint32_t *reset_dump_reg_list;
- uint32_t *reset_dump_reg_value;
- int num_regs;
-#ifdef CONFIG_DEV_COREDUMP
- struct amdgpu_task_info reset_task_info;
- bool reset_vram_lost;
- struct timespec64 reset_time;
-#endif
+ struct amdgpu_reset_info reset_info;
bool scpm_enabled;
uint32_t scpm_status;
@@ -1082,8 +1101,29 @@ struct amdgpu_device {
bool dc_enabled;
/* Mask of active clusters */
uint32_t aid_mask;
+
+ /* Debug */
+ bool debug_vm;
+ bool debug_largebar;
+ bool debug_disable_soft_recovery;
};
+static inline uint32_t amdgpu_ip_version(const struct amdgpu_device *adev,
+ uint8_t ip, uint8_t inst)
+{
+ /* This considers only major/minor/rev and ignores
+ * subrevision/variant fields.
+ */
+ return adev->ip_versions[ip][inst] & ~0xFFU;
+}
+
+static inline uint32_t amdgpu_ip_version_full(const struct amdgpu_device *adev,
+ uint8_t ip, uint8_t inst)
+{
+ /* This returns full version - major/minor/rev/variant/subrevision */
+ return adev->ip_versions[ip][inst];
+}
+
static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev)
{
return container_of(ddev, struct amdgpu_device, ddev);
@@ -1120,11 +1160,18 @@ uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
uint32_t reg, uint32_t acc_flags);
u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev,
u64 reg_addr);
+uint32_t amdgpu_device_xcc_rreg(struct amdgpu_device *adev,
+ uint32_t reg, uint32_t acc_flags,
+ uint32_t xcc_id);
void amdgpu_device_wreg(struct amdgpu_device *adev,
uint32_t reg, uint32_t v,
uint32_t acc_flags);
void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev,
u64 reg_addr, u32 reg_data);
+void amdgpu_device_xcc_wreg(struct amdgpu_device *adev,
+ uint32_t reg, uint32_t v,
+ uint32_t acc_flags,
+ uint32_t xcc_id);
void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
uint32_t reg, uint32_t v, uint32_t xcc_id);
void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value);
@@ -1134,10 +1181,14 @@ u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev,
u32 reg_addr);
u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev,
u32 reg_addr);
+u64 amdgpu_device_indirect_rreg64_ext(struct amdgpu_device *adev,
+ u64 reg_addr);
void amdgpu_device_indirect_wreg(struct amdgpu_device *adev,
u32 reg_addr, u32 reg_data);
void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev,
u32 reg_addr, u64 reg_data);
+void amdgpu_device_indirect_wreg64_ext(struct amdgpu_device *adev,
+ u64 reg_addr, u64 reg_data);
u32 amdgpu_device_get_rev_id(struct amdgpu_device *adev);
bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type);
bool amdgpu_device_has_dc_support(struct amdgpu_device *adev);
@@ -1161,8 +1212,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
#define RREG32_NO_KIQ(reg) amdgpu_device_rreg(adev, (reg), AMDGPU_REGS_NO_KIQ)
#define WREG32_NO_KIQ(reg, v) amdgpu_device_wreg(adev, (reg), (v), AMDGPU_REGS_NO_KIQ)
-#define RREG32_KIQ(reg) amdgpu_kiq_rreg(adev, (reg))
-#define WREG32_KIQ(reg, v) amdgpu_kiq_wreg(adev, (reg), (v))
+#define RREG32_KIQ(reg) amdgpu_kiq_rreg(adev, (reg), 0)
+#define WREG32_KIQ(reg, v) amdgpu_kiq_wreg(adev, (reg), (v), 0)
#define RREG8(reg) amdgpu_mm_rreg8(adev, (reg))
#define WREG8(reg, v) amdgpu_mm_wreg8(adev, (reg), (v))
@@ -1172,6 +1223,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
#define WREG32(reg, v) amdgpu_device_wreg(adev, (reg), (v), 0)
#define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
#define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
+#define RREG32_XCC(reg, inst) amdgpu_device_xcc_rreg(adev, (reg), 0, inst)
+#define WREG32_XCC(reg, v, inst) amdgpu_device_xcc_wreg(adev, (reg), (v), 0, inst)
#define RREG32_PCIE(reg) adev->pcie_rreg(adev, (reg))
#define WREG32_PCIE(reg, v) adev->pcie_wreg(adev, (reg), (v))
#define RREG32_PCIE_PORT(reg) adev->pciep_rreg(adev, (reg))
@@ -1180,6 +1233,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
#define WREG32_PCIE_EXT(reg, v) adev->pcie_wreg_ext(adev, (reg), (v))
#define RREG64_PCIE(reg) adev->pcie_rreg64(adev, (reg))
#define WREG64_PCIE(reg, v) adev->pcie_wreg64(adev, (reg), (v))
+#define RREG64_PCIE_EXT(reg) adev->pcie_rreg64_ext(adev, (reg))
+#define WREG64_PCIE_EXT(reg, v) adev->pcie_wreg64_ext(adev, (reg), (v))
#define RREG32_SMC(reg) adev->smc_rreg(adev, (reg))
#define WREG32_SMC(reg, v) adev->smc_wreg(adev, (reg), (v))
#define RREG32_UVD_CTX(reg) adev->uvd_ctx_rreg(adev, (reg))
@@ -1275,15 +1330,13 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
((adev)->asic_funcs->update_umd_stable_pstate ? (adev)->asic_funcs->update_umd_stable_pstate((adev), (enter)) : 0)
#define amdgpu_asic_query_video_codecs(adev, e, c) (adev)->asic_funcs->query_video_codecs((adev), (e), (c))
-#define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter));
+#define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter))
#define BIT_MASK_UPPER(i) ((i) >= BITS_PER_LONG ? 0 : ~0UL << (i))
#define for_each_inst(i, inst_mask) \
for (i = ffs(inst_mask); i-- != 0; \
i = ffs(inst_mask & BIT_MASK_UPPER(i + 1)))
-#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
-
/* Common functions */
bool amdgpu_device_has_job_running(struct amdgpu_device *adev);
bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev);
@@ -1293,9 +1346,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
void amdgpu_device_pci_config_reset(struct amdgpu_device *adev);
int amdgpu_device_pci_reset(struct amdgpu_device *adev);
bool amdgpu_device_need_post(struct amdgpu_device *adev);
-bool amdgpu_device_pcie_dynamic_switching_supported(void);
+bool amdgpu_device_seamless_boot_supported(struct amdgpu_device *adev);
bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev);
-bool amdgpu_device_aspm_support_quirk(void);
void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes,
u64 num_vis_bytes);
@@ -1367,6 +1419,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
void amdgpu_driver_release_kms(struct drm_device *dev);
int amdgpu_device_ip_suspend(struct amdgpu_device *adev);
+int amdgpu_device_prepare(struct drm_device *dev);
int amdgpu_device_suspend(struct drm_device *dev, bool fbcon);
int amdgpu_device_resume(struct drm_device *dev, bool fbcon);
u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index 2bca37044ad0..2deebece810e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -68,7 +68,7 @@ struct amdgpu_acpi_xcc_info {
struct amdgpu_acpi_dev_info {
struct list_head list;
struct list_head xcc_list;
- uint16_t bdf;
+ uint32_t sbdf;
uint16_t supp_xcp_mode;
uint16_t xcp_mode;
uint16_t mem_mode;
@@ -927,7 +927,7 @@ static acpi_status amdgpu_acpi_get_node_id(acpi_handle handle,
#endif
}
-static struct amdgpu_acpi_dev_info *amdgpu_acpi_get_dev(u16 bdf)
+static struct amdgpu_acpi_dev_info *amdgpu_acpi_get_dev(u32 sbdf)
{
struct amdgpu_acpi_dev_info *acpi_dev;
@@ -935,14 +935,14 @@ static struct amdgpu_acpi_dev_info *amdgpu_acpi_get_dev(u16 bdf)
return NULL;
list_for_each_entry(acpi_dev, &amdgpu_acpi_dev_list, list)
- if (acpi_dev->bdf == bdf)
+ if (acpi_dev->sbdf == sbdf)
return acpi_dev;
return NULL;
}
static int amdgpu_acpi_dev_init(struct amdgpu_acpi_dev_info **dev_info,
- struct amdgpu_acpi_xcc_info *xcc_info, u16 bdf)
+ struct amdgpu_acpi_xcc_info *xcc_info, u32 sbdf)
{
struct amdgpu_acpi_dev_info *tmp;
union acpi_object *obj;
@@ -955,7 +955,7 @@ static int amdgpu_acpi_dev_init(struct amdgpu_acpi_dev_info **dev_info,
INIT_LIST_HEAD(&tmp->xcc_list);
INIT_LIST_HEAD(&tmp->list);
- tmp->bdf = bdf;
+ tmp->sbdf = sbdf;
obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
AMD_XCC_DSM_GET_SUPP_MODE, NULL,
@@ -1007,7 +1007,7 @@ static int amdgpu_acpi_dev_init(struct amdgpu_acpi_dev_info **dev_info,
DRM_DEBUG_DRIVER(
"New dev(%x): Supported xcp mode: %x curr xcp_mode : %x mem mode : %x, tmr base: %llx tmr size: %llx ",
- tmp->bdf, tmp->supp_xcp_mode, tmp->xcp_mode, tmp->mem_mode,
+ tmp->sbdf, tmp->supp_xcp_mode, tmp->xcp_mode, tmp->mem_mode,
tmp->tmr_base, tmp->tmr_size);
list_add_tail(&tmp->list, &amdgpu_acpi_dev_list);
*dev_info = tmp;
@@ -1023,7 +1023,7 @@ out:
}
static int amdgpu_acpi_get_xcc_info(struct amdgpu_acpi_xcc_info *xcc_info,
- u16 *bdf)
+ u32 *sbdf)
{
union acpi_object *obj;
acpi_status status;
@@ -1054,8 +1054,10 @@ static int amdgpu_acpi_get_xcc_info(struct amdgpu_acpi_xcc_info *xcc_info,
xcc_info->phy_id = (obj->integer.value >> 32) & 0xFF;
/* xcp node of this xcc [47:40] */
xcc_info->xcp_node = (obj->integer.value >> 40) & 0xFF;
+ /* PF domain of this xcc [31:16] */
+ *sbdf = (obj->integer.value) & 0xFFFF0000;
/* PF bus/dev/fn of this xcc [63:48] */
- *bdf = (obj->integer.value >> 48) & 0xFFFF;
+ *sbdf |= (obj->integer.value >> 48) & 0xFFFF;
ACPI_FREE(obj);
obj = NULL;
@@ -1079,7 +1081,7 @@ static int amdgpu_acpi_enumerate_xcc(void)
struct acpi_device *acpi_dev;
char hid[ACPI_ID_LEN];
int ret, id;
- u16 bdf;
+ u32 sbdf;
INIT_LIST_HEAD(&amdgpu_acpi_dev_list);
xa_init(&numa_info_xa);
@@ -1107,16 +1109,16 @@ static int amdgpu_acpi_enumerate_xcc(void)
xcc_info->handle = acpi_device_handle(acpi_dev);
acpi_dev_put(acpi_dev);
- ret = amdgpu_acpi_get_xcc_info(xcc_info, &bdf);
+ ret = amdgpu_acpi_get_xcc_info(xcc_info, &sbdf);
if (ret) {
kfree(xcc_info);
continue;
}
- dev_info = amdgpu_acpi_get_dev(bdf);
+ dev_info = amdgpu_acpi_get_dev(sbdf);
if (!dev_info)
- ret = amdgpu_acpi_dev_init(&dev_info, xcc_info, bdf);
+ ret = amdgpu_acpi_dev_init(&dev_info, xcc_info, sbdf);
if (ret == -ENOMEM)
return ret;
@@ -1136,13 +1138,14 @@ int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev, u64 *tmr_offset,
u64 *tmr_size)
{
struct amdgpu_acpi_dev_info *dev_info;
- u16 bdf;
+ u32 sbdf;
if (!tmr_offset || !tmr_size)
return -EINVAL;
- bdf = pci_dev_id(adev->pdev);
- dev_info = amdgpu_acpi_get_dev(bdf);
+ sbdf = (pci_domain_nr(adev->pdev->bus) << 16);
+ sbdf |= pci_dev_id(adev->pdev);
+ dev_info = amdgpu_acpi_get_dev(sbdf);
if (!dev_info)
return -ENOENT;
@@ -1157,13 +1160,14 @@ int amdgpu_acpi_get_mem_info(struct amdgpu_device *adev, int xcc_id,
{
struct amdgpu_acpi_dev_info *dev_info;
struct amdgpu_acpi_xcc_info *xcc_info;
- u16 bdf;
+ u32 sbdf;
if (!numa_info)
return -EINVAL;
- bdf = pci_dev_id(adev->pdev);
- dev_info = amdgpu_acpi_get_dev(bdf);
+ sbdf = (pci_domain_nr(adev->pdev->bus) << 16);
+ sbdf |= pci_dev_id(adev->pdev);
+ dev_info = amdgpu_acpi_get_dev(sbdf);
if (!dev_info)
return -ENOENT;
@@ -1389,14 +1393,11 @@ void amdgpu_acpi_detect(void)
struct pci_dev *pdev = NULL;
int ret;
- while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
- if (!atif->handle)
- amdgpu_atif_pci_probe_handle(pdev);
- if (!atcs->handle)
- amdgpu_atcs_pci_probe_handle(pdev);
- }
+ while ((pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) {
+ if ((pdev->class != PCI_CLASS_DISPLAY_VGA << 8) &&
+ (pdev->class != PCI_CLASS_DISPLAY_OTHER << 8))
+ continue;
- while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
if (!atif->handle)
amdgpu_atif_pci_probe_handle(pdev);
if (!atcs->handle)
@@ -1493,6 +1494,9 @@ bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev)
if (adev->asic_type < CHIP_RAVEN)
return false;
+ if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
+ return false;
+
/*
* If ACPI_FADT_LOW_POWER_S0 is not set in the FADT, it is generally
* risky to do any special firmware-related preparations for entering
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index 25d5fda5b243..75dc58470393 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -28,6 +28,7 @@
#include "amdgpu.h"
#include "amdgpu_gfx.h"
#include "amdgpu_dma_buf.h"
+#include <drm/ttm/ttm_tt.h>
#include <linux/module.h>
#include <linux/dma-buf.h>
#include "amdgpu_xgmi.h"
@@ -164,7 +165,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
*/
bitmap_complement(gpu_resources.cp_queue_bitmap,
adev->gfx.mec_bitmap[0].queue_bitmap,
- KGD_MAX_QUEUES);
+ AMDGPU_MAX_QUEUES);
/* According to linux/bitmap.h we shouldn't use bitmap_clear if
* nbits is not compile time constant
@@ -172,7 +173,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
last_valid_bit = 1 /* only first MEC can have compute queues */
* adev->gfx.mec.num_pipe_per_mec
* adev->gfx.mec.num_queue_per_pipe;
- for (i = last_valid_bit; i < KGD_MAX_QUEUES; ++i)
+ for (i = last_valid_bit; i < AMDGPU_MAX_QUEUES; ++i)
clear_bit(i, gpu_resources.cp_queue_bitmap);
amdgpu_doorbell_get_kfd_info(adev,
@@ -467,28 +468,6 @@ uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev)
return 100;
}
-void amdgpu_amdkfd_get_cu_info(struct amdgpu_device *adev, struct kfd_cu_info *cu_info)
-{
- struct amdgpu_cu_info acu_info = adev->gfx.cu_info;
-
- memset(cu_info, 0, sizeof(*cu_info));
- if (sizeof(cu_info->cu_bitmap) != sizeof(acu_info.bitmap))
- return;
-
- cu_info->cu_active_number = acu_info.number;
- cu_info->cu_ao_mask = acu_info.ao_cu_mask;
- memcpy(&cu_info->cu_bitmap[0], &acu_info.bitmap[0],
- sizeof(cu_info->cu_bitmap));
- cu_info->num_shader_engines = adev->gfx.config.max_shader_engines;
- cu_info->num_shader_arrays_per_engine = adev->gfx.config.max_sh_per_se;
- cu_info->num_cu_per_sh = adev->gfx.config.max_cu_per_sh;
- cu_info->simd_per_cu = acu_info.simd_per_cu;
- cu_info->max_waves_per_simd = acu_info.max_waves_per_simd;
- cu_info->wave_front_size = acu_info.wave_front_size;
- cu_info->max_scratch_slots_per_cu = acu_info.max_scratch_slots_per_cu;
- cu_info->lds_size = acu_info.lds_size;
-}
-
int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
struct amdgpu_device **dmabuf_adev,
uint64_t *bo_size, void *metadata_buffer,
@@ -568,7 +547,7 @@ int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct amdgpu_device *dst,
struct amdgpu_device *adev = dst, *peer_adev;
int num_links;
- if (adev->asic_type != CHIP_ALDEBARAN)
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(9, 4, 2))
return 0;
if (src)
@@ -704,12 +683,19 @@ err:
void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle)
{
+ enum amd_powergating_state state = idle ? AMD_PG_STATE_GATE : AMD_PG_STATE_UNGATE;
/* Temporary workaround to fix issues observed in some
* compute applications when GFXOFF is enabled on GFX11.
*/
- if (IP_VERSION_MAJ(adev->ip_versions[GC_HWIP][0]) == 11) {
+ if (IP_VERSION_MAJ(amdgpu_ip_version(adev, GC_HWIP, 0)) == 11) {
pr_debug("GFXOFF is %s\n", idle ? "enabled" : "disabled");
amdgpu_gfx_off_ctrl(adev, idle);
+ } else if ((IP_VERSION_MAJ(amdgpu_ip_version(adev, GC_HWIP, 0)) == 9) &&
+ (adev->flags & AMD_IS_APU)) {
+ /* Disable GFXOFF and PG. Temporary workaround
+ * to fix some compute applications issue on GFX9.
+ */
+ adev->ip_blocks[AMD_IP_BLOCK_TYPE_GFX].version->funcs->set_powergating_state((void *)adev, state);
}
amdgpu_dpm_switch_power_profile(adev,
PP_SMC_POWER_PROFILE_COMPUTE,
@@ -805,11 +791,23 @@ void amdgpu_amdkfd_unlock_kfd(struct amdgpu_device *adev)
u64 amdgpu_amdkfd_xcp_memory_size(struct amdgpu_device *adev, int xcp_id)
{
- u64 tmp;
s8 mem_id = KFD_XCP_MEM_ID(adev, xcp_id);
+ u64 tmp;
if (adev->gmc.num_mem_partitions && xcp_id >= 0 && mem_id >= 0) {
- tmp = adev->gmc.mem_partitions[mem_id].size;
+ if (adev->gmc.is_app_apu && adev->gmc.num_mem_partitions == 1) {
+ /* In NPS1 mode, we should restrict the vram reporting
+ * tied to the ttm_pages_limit which is 1/2 of the system
+ * memory. For other partition modes, the HBM is uniformly
+ * divided already per numa node reported. If user wants to
+ * go beyond the default ttm limit and maximize the ROCm
+ * allocations, they can go up to max ttm and sysmem limits.
+ */
+
+ tmp = (ttm_tt_pages_limit() << PAGE_SHIFT) / num_online_nodes();
+ } else {
+ tmp = adev->gmc.mem_partitions[mem_id].size;
+ }
do_div(tmp, adev->xcp_mgr->num_xcp_per_mem_partition);
return ALIGN_DOWN(tmp, PAGE_SIZE);
} else {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index 2fe9860725bd..dac983da961d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -235,8 +235,6 @@ void amdgpu_amdkfd_get_local_mem_info(struct amdgpu_device *adev,
uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct amdgpu_device *adev);
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev);
-void amdgpu_amdkfd_get_cu_info(struct amdgpu_device *adev,
- struct kfd_cu_info *cu_info);
int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
struct amdgpu_device **dmabuf_adev,
uint64_t *bo_size, void *metadata_buffer,
@@ -303,6 +301,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(struct amdgpu_device *adev,
struct kgd_mem *mem, void *drm_priv);
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv);
+void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv);
int amdgpu_amdkfd_gpuvm_sync_memory(
struct amdgpu_device *adev, struct kgd_mem *mem, bool intr);
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c
index 490c8f5ddb60..f6598b9e4faa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c
@@ -300,14 +300,13 @@ static int kgd_gfx_v9_4_3_hqd_load(struct amdgpu_device *adev, void *mqd,
hqd_end = SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_AQL_DISPATCH_ID_HI);
for (reg = hqd_base; reg <= hqd_end; reg++)
- WREG32_RLC(reg, mqd_hqd[reg - hqd_base]);
+ WREG32_XCC(reg, mqd_hqd[reg - hqd_base], inst);
/* Activate doorbell logic before triggering WPTR poll. */
data = REG_SET_FIELD(m->cp_hqd_pq_doorbell_control,
CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1);
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_DOORBELL_CONTROL),
- data);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_PQ_DOORBELL_CONTROL, data);
if (wptr) {
/* Don't read wptr with get_user because the user
@@ -336,27 +335,24 @@ static int kgd_gfx_v9_4_3_hqd_load(struct amdgpu_device *adev, void *mqd,
guessed_wptr += m->cp_hqd_pq_wptr_lo & ~(queue_size - 1);
guessed_wptr += (uint64_t)m->cp_hqd_pq_wptr_hi << 32;
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_LO),
- lower_32_bits(guessed_wptr));
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_HI),
- upper_32_bits(guessed_wptr));
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_POLL_ADDR),
- lower_32_bits((uintptr_t)wptr));
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
- regCP_HQD_PQ_WPTR_POLL_ADDR_HI),
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_LO,
+ lower_32_bits(guessed_wptr));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_HI,
+ upper_32_bits(guessed_wptr));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_POLL_ADDR,
+ lower_32_bits((uintptr_t)wptr));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_POLL_ADDR_HI,
upper_32_bits((uintptr_t)wptr));
- WREG32(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_PQ_WPTR_POLL_CNTL1),
- (uint32_t)kgd_gfx_v9_get_queue_mask(adev, pipe_id,
- queue_id));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_PQ_WPTR_POLL_CNTL1,
+ (uint32_t)kgd_gfx_v9_get_queue_mask(adev, pipe_id, queue_id));
}
/* Start the EOP fetcher */
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_EOP_RPTR),
- REG_SET_FIELD(m->cp_hqd_eop_rptr,
- CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_EOP_RPTR,
+ REG_SET_FIELD(m->cp_hqd_eop_rptr, CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_ACTIVE), data);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_ACTIVE, data);
kgd_gfx_v9_release_queue(adev, inst);
@@ -494,15 +490,15 @@ static uint32_t kgd_gfx_v9_4_3_set_address_watch(
VALID,
1);
- WREG32_RLC((SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
+ WREG32_XCC((SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
regTCP_WATCH0_ADDR_H) +
(watch_id * TCP_WATCH_STRIDE)),
- watch_address_high);
+ watch_address_high, inst);
- WREG32_RLC((SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
+ WREG32_XCC((SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
regTCP_WATCH0_ADDR_L) +
(watch_id * TCP_WATCH_STRIDE)),
- watch_address_low);
+ watch_address_low, inst);
return watch_address_cntl;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c
index d67d003bada2..b61a32d6af4b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c
@@ -658,7 +658,7 @@ static int kgd_gfx_v11_validate_trap_override_request(struct amdgpu_device *adev
KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH |
KFD_DBG_TRAP_MASK_DBG_MEMORY_VIOLATION;
- if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(11, 0, 4))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(11, 0, 4))
*trap_mask_supported |= KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_START |
KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_END;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
index 3c45a188b701..00fbc0f44c92 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
@@ -91,8 +91,8 @@ void kgd_gfx_v9_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
{
kgd_gfx_v9_lock_srbm(adev, 0, 0, 0, vmid, inst);
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmSH_MEM_CONFIG), sh_mem_config);
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmSH_MEM_BASES), sh_mem_bases);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmSH_MEM_CONFIG, sh_mem_config);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmSH_MEM_BASES, sh_mem_bases);
/* APE1 no longer exists on GFX9 */
kgd_gfx_v9_unlock_srbm(adev, inst);
@@ -239,14 +239,13 @@ int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd,
for (reg = hqd_base;
reg <= SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_HI); reg++)
- WREG32_RLC(reg, mqd_hqd[reg - hqd_base]);
+ WREG32_XCC(reg, mqd_hqd[reg - hqd_base], inst);
/* Activate doorbell logic before triggering WPTR poll. */
data = REG_SET_FIELD(m->cp_hqd_pq_doorbell_control,
CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1);
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_DOORBELL_CONTROL),
- data);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_PQ_DOORBELL_CONTROL, data);
if (wptr) {
/* Don't read wptr with get_user because the user
@@ -275,25 +274,24 @@ int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd,
guessed_wptr += m->cp_hqd_pq_wptr_lo & ~(queue_size - 1);
guessed_wptr += (uint64_t)m->cp_hqd_pq_wptr_hi << 32;
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_LO),
- lower_32_bits(guessed_wptr));
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_HI),
- upper_32_bits(guessed_wptr));
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_POLL_ADDR),
- lower_32_bits((uintptr_t)wptr));
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_POLL_ADDR_HI),
- upper_32_bits((uintptr_t)wptr));
- WREG32_SOC15(GC, GET_INST(GC, inst), mmCP_PQ_WPTR_POLL_CNTL1,
- (uint32_t)kgd_gfx_v9_get_queue_mask(adev, pipe_id, queue_id));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_LO,
+ lower_32_bits(guessed_wptr));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_HI,
+ upper_32_bits(guessed_wptr));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_POLL_ADDR,
+ lower_32_bits((uintptr_t)wptr));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_POLL_ADDR_HI,
+ upper_32_bits((uintptr_t)wptr));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_PQ_WPTR_POLL_CNTL1,
+ (uint32_t)kgd_gfx_v9_get_queue_mask(adev, pipe_id, queue_id));
}
/* Start the EOP fetcher */
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_EOP_RPTR),
- REG_SET_FIELD(m->cp_hqd_eop_rptr,
- CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_EOP_RPTR,
+ REG_SET_FIELD(m->cp_hqd_eop_rptr, CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_ACTIVE), data);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_ACTIVE, data);
kgd_gfx_v9_release_queue(adev, inst);
@@ -556,7 +554,7 @@ int kgd_gfx_v9_hqd_destroy(struct amdgpu_device *adev, void *mqd,
break;
}
- WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_DEQUEUE_REQUEST), type);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_DEQUEUE_REQUEST, type);
end_jiffies = (utimeout * HZ / 1000) + jiffies;
while (true) {
@@ -677,7 +675,7 @@ void kgd_gfx_v9_set_wave_launch_stall(struct amdgpu_device *adev,
int i;
uint32_t data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 1))
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_VMID,
stall ? 1 << vmid : 0);
else
@@ -908,8 +906,8 @@ void kgd_gfx_v9_get_iq_wait_times(struct amdgpu_device *adev,
uint32_t inst)
{
- *wait_times = RREG32(SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
- mmCP_IQ_WAIT_TIME2));
+ *wait_times = RREG32_SOC15_RLC(GC, GET_INST(GC, inst),
+ mmCP_IQ_WAIT_TIME2);
}
void kgd_gfx_v9_set_vm_context_page_table_base(struct amdgpu_device *adev,
@@ -1037,7 +1035,7 @@ void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
int pasid_tmp;
int max_queue_cnt;
int vmid_wave_cnt = 0;
- DECLARE_BITMAP(cp_queue_bitmap, KGD_MAX_QUEUES);
+ DECLARE_BITMAP(cp_queue_bitmap, AMDGPU_MAX_QUEUES);
lock_spi_csq_mutexes(adev);
soc15_grbm_select(adev, 1, 0, 0, 0, inst);
@@ -1047,7 +1045,7 @@ void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
* to get number of waves in flight
*/
bitmap_complement(cp_queue_bitmap, adev->gfx.mec_bitmap[0].queue_bitmap,
- KGD_MAX_QUEUES);
+ AMDGPU_MAX_QUEUES);
max_queue_cnt = adev->gfx.mec.num_pipe_per_mec *
adev->gfx.mec.num_queue_per_pipe;
sh_cnt = adev->gfx.config.max_sh_per_se;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 7d6daf8d2bfa..41fbc4fd0fac 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -44,6 +44,7 @@
* changes to accumulate
*/
#define AMDGPU_USERPTR_RESTORE_DELAY_MS 1
+#define AMDGPU_RESERVE_MEM_LIMIT (3UL << 29)
/*
* Align VRAM availability to 2MB to avoid fragmentation caused by 4K allocations in the tail 2MB
@@ -117,11 +118,16 @@ void amdgpu_amdkfd_gpuvm_init_mem_limits(void)
return;
si_meminfo(&si);
- mem = si.freeram - si.freehigh;
+ mem = si.totalram - si.totalhigh;
mem *= si.mem_unit;
spin_lock_init(&kfd_mem_limit.mem_limit_lock);
- kfd_mem_limit.max_system_mem_limit = mem - (mem >> 4);
+ kfd_mem_limit.max_system_mem_limit = mem - (mem >> 6);
+ if (kfd_mem_limit.max_system_mem_limit < 2 * AMDGPU_RESERVE_MEM_LIMIT)
+ kfd_mem_limit.max_system_mem_limit >>= 1;
+ else
+ kfd_mem_limit.max_system_mem_limit -= AMDGPU_RESERVE_MEM_LIMIT;
+
kfd_mem_limit.max_ttm_mem_limit = ttm_tt_pages_limit() << PAGE_SHIFT;
pr_debug("Kernel memory limit %lluM, TTM limit %lluM\n",
(kfd_mem_limit.max_system_mem_limit >> 20),
@@ -419,6 +425,32 @@ validate_fail:
return ret;
}
+static int amdgpu_amdkfd_bo_validate_and_fence(struct amdgpu_bo *bo,
+ uint32_t domain,
+ struct dma_fence *fence)
+{
+ int ret = amdgpu_bo_reserve(bo, false);
+
+ if (ret)
+ return ret;
+
+ ret = amdgpu_amdkfd_bo_validate(bo, domain, true);
+ if (ret)
+ goto unreserve_out;
+
+ ret = dma_resv_reserve_fences(bo->tbo.base.resv, 1);
+ if (ret)
+ goto unreserve_out;
+
+ dma_resv_add_fence(bo->tbo.base.resv, fence,
+ DMA_RESV_USAGE_BOOKKEEP);
+
+unreserve_out:
+ amdgpu_bo_unreserve(bo);
+
+ return ret;
+}
+
static int amdgpu_amdkfd_validate_vm_bo(void *_unused, struct amdgpu_bo *bo)
{
return amdgpu_amdkfd_bo_validate(bo, bo->allowed_domains, false);
@@ -733,7 +765,7 @@ kfd_mem_dmaunmap_sg_bo(struct kgd_mem *mem,
enum dma_data_direction dir;
if (unlikely(!ttm->sg)) {
- pr_err("SG Table of BO is UNEXPECTEDLY NULL");
+ pr_debug("SG Table of BO is NULL");
return;
}
@@ -828,6 +860,7 @@ static int kfd_mem_attach(struct amdgpu_device *adev, struct kgd_mem *mem,
uint64_t va = mem->va;
struct kfd_mem_attachment *attachment[2] = {NULL, NULL};
struct amdgpu_bo *bo[2] = {NULL, NULL};
+ struct amdgpu_bo_va *bo_va;
bool same_hive = false;
int i, ret;
@@ -866,9 +899,10 @@ static int kfd_mem_attach(struct amdgpu_device *adev, struct kgd_mem *mem,
if ((adev == bo_adev && !(mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) ||
(amdgpu_ttm_tt_get_usermm(mem->bo->tbo.ttm) && reuse_dmamap(adev, bo_adev)) ||
- same_hive) {
+ (mem->domain == AMDGPU_GEM_DOMAIN_GTT && reuse_dmamap(adev, bo_adev)) ||
+ same_hive) {
/* Mappings on the local GPU, or VRAM mappings in the
- * local hive, or userptr mapping can reuse dma map
+ * local hive, or userptr, or GTT mapping can reuse dma map
* address space share the original BO
*/
attachment[i]->type = KFD_MEM_ATT_SHARED;
@@ -914,7 +948,12 @@ static int kfd_mem_attach(struct amdgpu_device *adev, struct kgd_mem *mem,
pr_debug("Unable to reserve BO during memory attach");
goto unwind;
}
- attachment[i]->bo_va = amdgpu_vm_bo_add(adev, vm, bo[i]);
+ bo_va = amdgpu_vm_bo_find(vm, bo[i]);
+ if (!bo_va)
+ bo_va = amdgpu_vm_bo_add(adev, vm, bo[i]);
+ else
+ ++bo_va->ref_count;
+ attachment[i]->bo_va = bo_va;
amdgpu_bo_unreserve(bo[i]);
if (unlikely(!attachment[i]->bo_va)) {
ret = -ENOMEM;
@@ -938,7 +977,8 @@ unwind:
continue;
if (attachment[i]->bo_va) {
amdgpu_bo_reserve(bo[i], true);
- amdgpu_vm_bo_del(adev, attachment[i]->bo_va);
+ if (--attachment[i]->bo_va->ref_count == 0)
+ amdgpu_vm_bo_del(adev, attachment[i]->bo_va);
amdgpu_bo_unreserve(bo[i]);
list_del(&attachment[i]->list);
}
@@ -955,7 +995,8 @@ static void kfd_mem_detach(struct kfd_mem_attachment *attachment)
pr_debug("\t remove VA 0x%llx in entry %p\n",
attachment->va, attachment);
- amdgpu_vm_bo_del(attachment->adev, attachment->bo_va);
+ if (--attachment->bo_va->ref_count == 0)
+ amdgpu_vm_bo_del(attachment->adev, attachment->bo_va);
drm_gem_object_put(&bo->tbo.base);
list_del(&attachment->list);
kfree(attachment);
@@ -1103,7 +1144,7 @@ static int reserve_bo_and_vm(struct kgd_mem *mem,
if (unlikely(ret))
goto error;
- ret = drm_exec_lock_obj(&ctx->exec, &bo->tbo.base);
+ ret = drm_exec_prepare_obj(&ctx->exec, &bo->tbo.base, 1);
drm_exec_retry_on_contention(&ctx->exec);
if (unlikely(ret))
goto error;
@@ -1201,8 +1242,6 @@ static void unmap_bo_from_gpuvm(struct kgd_mem *mem,
amdgpu_vm_clear_freed(adev, vm, &bo_va->last_pt_update);
amdgpu_sync_fence(sync, bo_va->last_pt_update);
-
- kfd_mem_dmaunmap_attachment(mem, entry);
}
static int update_gpuvm_pte(struct kgd_mem *mem,
@@ -1257,6 +1296,7 @@ static int map_bo_to_gpuvm(struct kgd_mem *mem,
update_gpuvm_pte_failed:
unmap_bo_from_gpuvm(mem, entry, sync);
+ kfd_mem_dmaunmap_attachment(mem, entry);
return ret;
}
@@ -1690,6 +1730,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT)
alloc_flags |= AMDGPU_GEM_CREATE_COHERENT;
+ if (flags & KFD_IOC_ALLOC_MEM_FLAGS_EXT_COHERENT)
+ alloc_flags |= AMDGPU_GEM_CREATE_EXT_COHERENT;
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED)
alloc_flags |= AMDGPU_GEM_CREATE_UNCACHED;
@@ -1768,6 +1810,15 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
}
bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
+ } else {
+ mutex_lock(&avm->process_info->lock);
+ if (avm->process_info->eviction_fence &&
+ !dma_fence_is_signaled(&avm->process_info->eviction_fence->base))
+ ret = amdgpu_amdkfd_bo_validate_and_fence(bo, domain,
+ &avm->process_info->eviction_fence->base);
+ mutex_unlock(&avm->process_info->lock);
+ if (ret)
+ goto err_validate_bo;
}
if (offset)
@@ -1777,6 +1828,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
allocate_init_user_pages_failed:
err_pin_bo:
+err_validate_bo:
remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info);
drm_vma_node_revoke(&gobj->vma_node, drm_priv);
err_node_allow:
@@ -1850,18 +1902,16 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
if (unlikely(ret))
return ret;
- /* The eviction fence should be removed by the last unmap.
- * TODO: Log an error condition if the bo still has the eviction fence
- * attached
- */
amdgpu_amdkfd_remove_eviction_fence(mem->bo,
process_info->eviction_fence);
pr_debug("Release VA 0x%llx - 0x%llx\n", mem->va,
mem->va + bo_size * (1 + mem->aql_queue));
/* Remove from VM internal data structures */
- list_for_each_entry_safe(entry, tmp, &mem->attachments, list)
+ list_for_each_entry_safe(entry, tmp, &mem->attachments, list) {
+ kfd_mem_dmaunmap_attachment(mem, entry);
kfd_mem_detach(entry);
+ }
ret = unreserve_bo_and_vms(&ctx, false, false);
@@ -1980,19 +2030,6 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
if (unlikely(ret))
goto out_unreserve;
- if (mem->mapped_to_gpu_memory == 0 &&
- !amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) {
- /* Validate BO only once. The eviction fence gets added to BO
- * the first time it is mapped. Validate will wait for all
- * background evictions to complete.
- */
- ret = amdgpu_amdkfd_bo_validate(bo, domain, true);
- if (ret) {
- pr_debug("Validate failed\n");
- goto out_unreserve;
- }
- }
-
list_for_each_entry(entry, &mem->attachments, list) {
if (entry->bo_va->base.vm != avm || entry->is_mapped)
continue;
@@ -2019,10 +2056,6 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
mem->mapped_to_gpu_memory);
}
- if (!amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) && !bo->tbo.pin_count)
- dma_resv_add_fence(bo->tbo.base.resv,
- &avm->process_info->eviction_fence->base,
- DMA_RESV_USAGE_BOOKKEEP);
ret = unreserve_bo_and_vms(&ctx, false, false);
goto out;
@@ -2035,11 +2068,27 @@ out:
return ret;
}
+void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv)
+{
+ struct kfd_mem_attachment *entry;
+ struct amdgpu_vm *vm;
+
+ vm = drm_priv_to_vm(drm_priv);
+
+ mutex_lock(&mem->lock);
+
+ list_for_each_entry(entry, &mem->attachments, list) {
+ if (entry->bo_va->base.vm == vm)
+ kfd_mem_dmaunmap_attachment(mem, entry);
+ }
+
+ mutex_unlock(&mem->lock);
+}
+
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv)
{
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
- struct amdkfd_process_info *process_info = avm->process_info;
unsigned long bo_size = mem->bo->tbo.base.size;
struct kfd_mem_attachment *entry;
struct bo_vm_reservation_context ctx;
@@ -2080,15 +2129,6 @@ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
mem->mapped_to_gpu_memory);
}
- /* If BO is unmapped from all VMs, unfence it. It can be evicted if
- * required.
- */
- if (mem->mapped_to_gpu_memory == 0 &&
- !amdgpu_ttm_tt_get_usermm(mem->bo->tbo.ttm) &&
- !mem->bo->tbo.pin_count)
- amdgpu_amdkfd_remove_eviction_fence(mem->bo,
- process_info->eviction_fence);
-
unreserve_out:
unreserve_bo_and_vms(&ctx, false, false);
out:
@@ -2316,8 +2356,20 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
amdgpu_sync_create(&(*mem)->sync);
(*mem)->is_imported = true;
+ mutex_lock(&avm->process_info->lock);
+ if (avm->process_info->eviction_fence &&
+ !dma_fence_is_signaled(&avm->process_info->eviction_fence->base))
+ ret = amdgpu_amdkfd_bo_validate_and_fence(bo, (*mem)->domain,
+ &avm->process_info->eviction_fence->base);
+ mutex_unlock(&avm->process_info->lock);
+ if (ret)
+ goto err_remove_mem;
+
return 0;
+err_remove_mem:
+ remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info);
+ drm_vma_node_revoke(&obj->vma_node, drm_priv);
err_free_mem:
kfree(*mem);
err_put_obj:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index 38ccec913f00..618e469e3622 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -29,6 +29,7 @@
#include "amdgpu.h"
#include "atom.h"
+#include <linux/device.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/acpi.h>
@@ -287,7 +288,15 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
if (adev->flags & AMD_IS_APU)
return false;
- while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
+ /* ATRM is for on-platform devices only */
+ if (dev_is_removable(&adev->pdev->dev))
+ return false;
+
+ while ((pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) {
+ if ((pdev->class != PCI_CLASS_DISPLAY_VGA << 8) &&
+ (pdev->class != PCI_CLASS_DISPLAY_OTHER << 8))
+ continue;
+
dhandle = ACPI_HANDLE(&pdev->dev);
if (!dhandle)
continue;
@@ -299,20 +308,6 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
}
}
- if (!found) {
- while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
- dhandle = ACPI_HANDLE(&pdev->dev);
- if (!dhandle)
- continue;
-
- status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
- if (ACPI_SUCCESS(status)) {
- found = true;
- break;
- }
- }
- }
-
if (!found)
return false;
pci_dev_put(pdev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
index b6298e901cbd..702f6610d024 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
@@ -75,27 +75,17 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp,
struct amdgpu_bo_list_entry *array;
struct amdgpu_bo_list *list;
uint64_t total_size = 0;
- size_t size;
unsigned i;
int r;
- if (num_entries > (SIZE_MAX - sizeof(struct amdgpu_bo_list))
- / sizeof(struct amdgpu_bo_list_entry))
- return -EINVAL;
-
- size = sizeof(struct amdgpu_bo_list);
- size += num_entries * sizeof(struct amdgpu_bo_list_entry);
- list = kvmalloc(size, GFP_KERNEL);
+ list = kvzalloc(struct_size(list, entries, num_entries), GFP_KERNEL);
if (!list)
return -ENOMEM;
kref_init(&list->refcount);
- list->gds_obj = NULL;
- list->gws_obj = NULL;
- list->oa_obj = NULL;
- array = amdgpu_bo_list_array_entry(list, 0);
- memset(array, 0, num_entries * sizeof(struct amdgpu_bo_list_entry));
+ list->num_entries = num_entries;
+ array = list->entries;
for (i = 0; i < num_entries; ++i) {
struct amdgpu_bo_list_entry *entry;
@@ -140,7 +130,6 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp,
}
list->first_userptr = first_userptr;
- list->num_entries = num_entries;
sort(array, last_entry, sizeof(struct amdgpu_bo_list_entry),
amdgpu_bo_list_entry_cmp, NULL);
@@ -183,6 +172,7 @@ int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id,
}
rcu_read_unlock();
+ *result = NULL;
return -ENOENT;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h
index 26c01cb131f2..555cd6d877c3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h
@@ -55,6 +55,8 @@ struct amdgpu_bo_list {
/* Protect access during command submission.
*/
struct mutex bo_list_mutex;
+
+ struct amdgpu_bo_list_entry entries[] __counted_by(num_entries);
};
int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id,
@@ -69,22 +71,14 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev,
size_t num_entries,
struct amdgpu_bo_list **list);
-static inline struct amdgpu_bo_list_entry *
-amdgpu_bo_list_array_entry(struct amdgpu_bo_list *list, unsigned index)
-{
- struct amdgpu_bo_list_entry *array = (void *)&list[1];
-
- return &array[index];
-}
-
#define amdgpu_bo_list_for_each_entry(e, list) \
- for (e = amdgpu_bo_list_array_entry(list, 0); \
- e != amdgpu_bo_list_array_entry(list, (list)->num_entries); \
+ for (e = list->entries; \
+ e != &list->entries[list->num_entries]; \
++e)
#define amdgpu_bo_list_for_each_userptr_entry(e, list) \
- for (e = amdgpu_bo_list_array_entry(list, (list)->first_userptr); \
- e != amdgpu_bo_list_array_entry(list, (list)->num_entries); \
+ for (e = &list->entries[list->first_userptr]; \
+ e != &list->entries[list->num_entries]; \
++e)
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index d34037b85cf8..7473a42f7d45 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -264,16 +264,9 @@ struct edid *amdgpu_connector_edid(struct drm_connector *connector)
static struct edid *
amdgpu_connector_get_hardcoded_edid(struct amdgpu_device *adev)
{
- struct edid *edid;
-
if (adev->mode_info.bios_hardcoded_edid) {
- edid = kmalloc(adev->mode_info.bios_hardcoded_edid_size, GFP_KERNEL);
- if (edid) {
- memcpy((unsigned char *)edid,
- (unsigned char *)adev->mode_info.bios_hardcoded_edid,
- adev->mode_info.bios_hardcoded_edid_size);
- return edid;
- }
+ return kmemdup((unsigned char *)adev->mode_info.bios_hardcoded_edid,
+ adev->mode_info.bios_hardcoded_edid_size, GFP_KERNEL);
}
return NULL;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index efdb1c48f431..e50be6500030 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -65,7 +65,8 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p,
}
amdgpu_sync_create(&p->sync);
- drm_exec_init(&p->exec, DRM_EXEC_INTERRUPTIBLE_WAIT);
+ drm_exec_init(&p->exec, DRM_EXEC_INTERRUPTIBLE_WAIT |
+ DRM_EXEC_IGNORE_DUPLICATES);
return 0;
}
@@ -206,7 +207,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
}
for (i = 0; i < p->nchunks; i++) {
- struct drm_amdgpu_cs_chunk __user **chunk_ptr = NULL;
+ struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL;
struct drm_amdgpu_cs_chunk user_chunk;
uint32_t __user *cdata;
@@ -1116,6 +1117,11 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
return r;
}
+ /* FIXME: In theory this loop shouldn't be needed any more when
+ * amdgpu_vm_handle_moved handles all moved BOs that are reserved
+ * with p->ticket. But removing it caused test regressions, so I'm
+ * leaving it here for now.
+ */
amdgpu_bo_list_for_each_entry(e, p->bo_list) {
bo_va = e->bo_va;
if (bo_va == NULL)
@@ -1130,7 +1136,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
return r;
}
- r = amdgpu_vm_handle_moved(adev, vm);
+ r = amdgpu_vm_handle_moved(adev, vm, &p->exec.ticket);
if (r)
return r;
@@ -1151,7 +1157,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
job->vm_pd_addr = amdgpu_gmc_pd_addr(vm->root.bo);
}
- if (amdgpu_vm_debug) {
+ if (adev->debug_vm) {
/* Invalidate all BOs to test for userspace bugs */
amdgpu_bo_list_for_each_entry(e, p->bo_list) {
struct amdgpu_bo *bo = e->bo;
@@ -1392,8 +1398,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
r = amdgpu_cs_parser_init(&parser, adev, filp, data);
if (r) {
- if (printk_ratelimit())
- DRM_ERROR("Failed to initialize parser %d!\n", r);
+ DRM_ERROR_RATELIMITED("Failed to initialize parser %d!\n", r);
return r;
}
@@ -1410,7 +1415,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
if (r == -ENOMEM)
DRM_ERROR("Not enough memory for command submission!\n");
else if (r != -ERESTARTSYS && r != -EAGAIN)
- DRM_ERROR("Failed to process the buffer list %d!\n", r);
+ DRM_DEBUG("Failed to process the buffer list %d!\n", r);
goto error_fini;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index 0dc9c655c4fb..e2ae9ba147ba 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -42,12 +42,12 @@ const unsigned int amdgpu_ctx_num_entities[AMDGPU_HW_IP_NUM] = {
[AMDGPU_HW_IP_VCN_DEC] = 1,
[AMDGPU_HW_IP_VCN_ENC] = 1,
[AMDGPU_HW_IP_VCN_JPEG] = 1,
+ [AMDGPU_HW_IP_VPE] = 1,
};
bool amdgpu_ctx_priority_is_valid(int32_t ctx_prio)
{
switch (ctx_prio) {
- case AMDGPU_CTX_PRIORITY_UNSET:
case AMDGPU_CTX_PRIORITY_VERY_LOW:
case AMDGPU_CTX_PRIORITY_LOW:
case AMDGPU_CTX_PRIORITY_NORMAL:
@@ -55,6 +55,11 @@ bool amdgpu_ctx_priority_is_valid(int32_t ctx_prio)
case AMDGPU_CTX_PRIORITY_VERY_HIGH:
return true;
default:
+ case AMDGPU_CTX_PRIORITY_UNSET:
+ /* UNSET priority is not valid and we don't carry that
+ * around, but set it to NORMAL in the only place this
+ * function is called, amdgpu_ctx_ioctl().
+ */
return false;
}
}
@@ -64,7 +69,8 @@ amdgpu_ctx_to_drm_sched_prio(int32_t ctx_prio)
{
switch (ctx_prio) {
case AMDGPU_CTX_PRIORITY_UNSET:
- return DRM_SCHED_PRIORITY_UNSET;
+ pr_warn_once("AMD-->DRM context priority value UNSET-->NORMAL");
+ return DRM_SCHED_PRIORITY_NORMAL;
case AMDGPU_CTX_PRIORITY_VERY_LOW:
return DRM_SCHED_PRIORITY_MIN;
@@ -94,9 +100,6 @@ amdgpu_ctx_to_drm_sched_prio(int32_t ctx_prio)
static int amdgpu_ctx_priority_permit(struct drm_file *filp,
int32_t priority)
{
- if (!amdgpu_ctx_priority_is_valid(priority))
- return -EINVAL;
-
/* NORMAL and below are accessible by everyone */
if (priority <= AMDGPU_CTX_PRIORITY_NORMAL)
return 0;
@@ -631,8 +634,6 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev,
return 0;
}
-
-
static int amdgpu_ctx_stable_pstate(struct amdgpu_device *adev,
struct amdgpu_fpriv *fpriv, uint32_t id,
bool set, u32 *stable_pstate)
@@ -675,8 +676,10 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
id = args->in.ctx_id;
priority = args->in.priority;
- /* For backwards compatibility reasons, we need to accept
- * ioctls with garbage in the priority field */
+ /* For backwards compatibility, we need to accept ioctls with garbage
+ * in the priority field. Garbage values in the priority field, result
+ * in the priority being set to NORMAL.
+ */
if (!amdgpu_ctx_priority_is_valid(priority))
priority = AMDGPU_CTX_PRIORITY_NORMAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index a4faea4fa0b5..0e61ebdb3f3e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -638,6 +638,9 @@ static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf,
if (size & 0x3 || *pos & 0x3)
return -EINVAL;
+ if (!adev->didt_rreg)
+ return -EOPNOTSUPP;
+
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
if (r < 0) {
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -694,6 +697,9 @@ static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user
if (size & 0x3 || *pos & 0x3)
return -EINVAL;
+ if (!adev->didt_wreg)
+ return -EOPNOTSUPP;
+
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
if (r < 0) {
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -748,6 +754,9 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf,
ssize_t result = 0;
int r;
+ if (!adev->smc_rreg)
+ return -EPERM;
+
if (size & 0x3 || *pos & 0x3)
return -EINVAL;
@@ -804,6 +813,9 @@ static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *
ssize_t result = 0;
int r;
+ if (!adev->smc_wreg)
+ return -EPERM;
+
if (size & 0x3 || *pos & 0x3)
return -EINVAL;
@@ -2016,8 +2028,8 @@ static ssize_t amdgpu_reset_dump_register_list_read(struct file *f,
if (ret)
return ret;
- for (i = 0; i < adev->num_regs; i++) {
- sprintf(reg_offset, "0x%x\n", adev->reset_dump_reg_list[i]);
+ for (i = 0; i < adev->reset_info.num_regs; i++) {
+ sprintf(reg_offset, "0x%x\n", adev->reset_info.reset_dump_reg_list[i]);
up_read(&adev->reset_domain->sem);
if (copy_to_user(buf + len, reg_offset, strlen(reg_offset)))
return -EFAULT;
@@ -2074,9 +2086,9 @@ static ssize_t amdgpu_reset_dump_register_list_write(struct file *f,
if (ret)
goto error_free;
- swap(adev->reset_dump_reg_list, tmp);
- swap(adev->reset_dump_reg_value, new);
- adev->num_regs = i;
+ swap(adev->reset_info.reset_dump_reg_list, tmp);
+ swap(adev->reset_info.reset_dump_reg_value, new);
+ adev->reset_info.num_regs = i;
up_write(&adev->reset_domain->sem);
ret = size;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 2b8356699f23..8dee52ce26d0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -32,8 +32,6 @@
#include <linux/slab.h>
#include <linux/iommu.h>
#include <linux/pci.h>
-#include <linux/devcoredump.h>
-#include <generated/utsrelease.h>
#include <linux/pci-p2pdma.h>
#include <linux/apple-gmux.h>
@@ -43,6 +41,7 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/amdgpu_drm.h>
+#include <linux/device.h>
#include <linux/vgaarb.h>
#include <linux/vga_switcheroo.h>
#include <linux/efi.h>
@@ -74,6 +73,7 @@
#include "amdgpu_pmu.h"
#include "amdgpu_fru_eeprom.h"
#include "amdgpu_reset.h"
+#include "amdgpu_virt.h"
#include <linux/suspend.h>
#include <drm/task_barrier.h>
@@ -162,6 +162,74 @@ static ssize_t amdgpu_device_get_pcie_replay_count(struct device *dev,
static DEVICE_ATTR(pcie_replay_count, 0444,
amdgpu_device_get_pcie_replay_count, NULL);
+/**
+ * DOC: board_info
+ *
+ * The amdgpu driver provides a sysfs API for giving board related information.
+ * It provides the form factor information in the format
+ *
+ * type : form factor
+ *
+ * Possible form factor values
+ *
+ * - "cem" - PCIE CEM card
+ * - "oam" - Open Compute Accelerator Module
+ * - "unknown" - Not known
+ *
+ */
+
+static ssize_t amdgpu_device_get_board_info(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+ enum amdgpu_pkg_type pkg_type = AMDGPU_PKG_TYPE_CEM;
+ const char *pkg;
+
+ if (adev->smuio.funcs && adev->smuio.funcs->get_pkg_type)
+ pkg_type = adev->smuio.funcs->get_pkg_type(adev);
+
+ switch (pkg_type) {
+ case AMDGPU_PKG_TYPE_CEM:
+ pkg = "cem";
+ break;
+ case AMDGPU_PKG_TYPE_OAM:
+ pkg = "oam";
+ break;
+ default:
+ pkg = "unknown";
+ break;
+ }
+
+ return sysfs_emit(buf, "%s : %s\n", "type", pkg);
+}
+
+static DEVICE_ATTR(board_info, 0444, amdgpu_device_get_board_info, NULL);
+
+static struct attribute *amdgpu_board_attrs[] = {
+ &dev_attr_board_info.attr,
+ NULL,
+};
+
+static umode_t amdgpu_board_attrs_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ if (adev->flags & AMD_IS_APU)
+ return 0;
+
+ return attr->mode;
+}
+
+static const struct attribute_group amdgpu_board_attrs_group = {
+ .attrs = amdgpu_board_attrs,
+ .is_visible = amdgpu_board_attrs_is_visible
+};
+
static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev);
@@ -405,7 +473,7 @@ uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
amdgpu_sriov_runtime(adev) &&
down_read_trylock(&adev->reset_domain->sem)) {
- ret = amdgpu_kiq_rreg(adev, reg);
+ ret = amdgpu_kiq_rreg(adev, reg, 0);
up_read(&adev->reset_domain->sem);
} else {
ret = readl(((void __iomem *)adev->rmmio) + (reg * 4));
@@ -442,6 +510,49 @@ uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset)
BUG();
}
+
+/**
+ * amdgpu_device_xcc_rreg - read a memory mapped IO or indirect register with specific XCC
+ *
+ * @adev: amdgpu_device pointer
+ * @reg: dword aligned register offset
+ * @acc_flags: access flags which require special behavior
+ * @xcc_id: xcc accelerated compute core id
+ *
+ * Returns the 32 bit value from the offset specified.
+ */
+uint32_t amdgpu_device_xcc_rreg(struct amdgpu_device *adev,
+ uint32_t reg, uint32_t acc_flags,
+ uint32_t xcc_id)
+{
+ uint32_t ret, rlcg_flag;
+
+ if (amdgpu_device_skip_hw_access(adev))
+ return 0;
+
+ if ((reg * 4) < adev->rmmio_size) {
+ if (amdgpu_sriov_vf(adev) &&
+ !amdgpu_sriov_runtime(adev) &&
+ adev->gfx.rlc.rlcg_reg_access_supported &&
+ amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags,
+ GC_HWIP, false,
+ &rlcg_flag)) {
+ ret = amdgpu_virt_rlcg_reg_rw(adev, reg, 0, rlcg_flag, xcc_id);
+ } else if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
+ amdgpu_sriov_runtime(adev) &&
+ down_read_trylock(&adev->reset_domain->sem)) {
+ ret = amdgpu_kiq_rreg(adev, reg, xcc_id);
+ up_read(&adev->reset_domain->sem);
+ } else {
+ ret = readl(((void __iomem *)adev->rmmio) + (reg * 4));
+ }
+ } else {
+ ret = adev->pcie_rreg(adev, reg * 4);
+ }
+
+ return ret;
+}
+
/*
* MMIO register write with bytes helper functions
* @offset:bytes offset from MMIO start
@@ -489,7 +600,7 @@ void amdgpu_device_wreg(struct amdgpu_device *adev,
if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
amdgpu_sriov_runtime(adev) &&
down_read_trylock(&adev->reset_domain->sem)) {
- amdgpu_kiq_wreg(adev, reg, v);
+ amdgpu_kiq_wreg(adev, reg, v, 0);
up_read(&adev->reset_domain->sem);
} else {
writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
@@ -507,6 +618,7 @@ void amdgpu_device_wreg(struct amdgpu_device *adev,
* @adev: amdgpu_device pointer
* @reg: mmio/rlc register
* @v: value to write
+ * @xcc_id: xcc accelerated compute core id
*
* this function is invoked only for the debugfs register access
*/
@@ -530,6 +642,47 @@ void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
}
/**
+ * amdgpu_device_xcc_wreg - write to a memory mapped IO or indirect register with specific XCC
+ *
+ * @adev: amdgpu_device pointer
+ * @reg: dword aligned register offset
+ * @v: 32 bit value to write to the register
+ * @acc_flags: access flags which require special behavior
+ * @xcc_id: xcc accelerated compute core id
+ *
+ * Writes the value specified to the offset specified.
+ */
+void amdgpu_device_xcc_wreg(struct amdgpu_device *adev,
+ uint32_t reg, uint32_t v,
+ uint32_t acc_flags, uint32_t xcc_id)
+{
+ uint32_t rlcg_flag;
+
+ if (amdgpu_device_skip_hw_access(adev))
+ return;
+
+ if ((reg * 4) < adev->rmmio_size) {
+ if (amdgpu_sriov_vf(adev) &&
+ !amdgpu_sriov_runtime(adev) &&
+ adev->gfx.rlc.rlcg_reg_access_supported &&
+ amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags,
+ GC_HWIP, true,
+ &rlcg_flag)) {
+ amdgpu_virt_rlcg_reg_rw(adev, reg, v, rlcg_flag, xcc_id);
+ } else if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
+ amdgpu_sriov_runtime(adev) &&
+ down_read_trylock(&adev->reset_domain->sem)) {
+ amdgpu_kiq_wreg(adev, reg, v, xcc_id);
+ up_read(&adev->reset_domain->sem);
+ } else {
+ writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
+ }
+ } else {
+ adev->pcie_wreg(adev, reg * 4, v);
+ }
+}
+
+/**
* amdgpu_device_indirect_rreg - read an indirect register
*
* @adev: amdgpu_device pointer
@@ -571,7 +724,7 @@ u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev,
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
- if (adev->nbio.funcs->get_pcie_index_hi_offset)
+ if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset))
pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);
else
pcie_index_hi = 0;
@@ -638,6 +791,56 @@ u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev,
return r;
}
+u64 amdgpu_device_indirect_rreg64_ext(struct amdgpu_device *adev,
+ u64 reg_addr)
+{
+ unsigned long flags, pcie_index, pcie_data;
+ unsigned long pcie_index_hi = 0;
+ void __iomem *pcie_index_offset;
+ void __iomem *pcie_index_hi_offset;
+ void __iomem *pcie_data_offset;
+ u64 r;
+
+ pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
+ pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
+ if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset))
+ pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);
+
+ spin_lock_irqsave(&adev->pcie_idx_lock, flags);
+ pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
+ pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
+ if (pcie_index_hi != 0)
+ pcie_index_hi_offset = (void __iomem *)adev->rmmio +
+ pcie_index_hi * 4;
+
+ /* read low 32 bits */
+ writel(reg_addr, pcie_index_offset);
+ readl(pcie_index_offset);
+ if (pcie_index_hi != 0) {
+ writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
+ readl(pcie_index_hi_offset);
+ }
+ r = readl(pcie_data_offset);
+ /* read high 32 bits */
+ writel(reg_addr + 4, pcie_index_offset);
+ readl(pcie_index_offset);
+ if (pcie_index_hi != 0) {
+ writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
+ readl(pcie_index_hi_offset);
+ }
+ r |= ((u64)readl(pcie_data_offset) << 32);
+
+ /* clear the high bits */
+ if (pcie_index_hi != 0) {
+ writel(0, pcie_index_hi_offset);
+ readl(pcie_index_hi_offset);
+ }
+
+ spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
+
+ return r;
+}
+
/**
* amdgpu_device_indirect_wreg - write an indirect register address
*
@@ -677,7 +880,7 @@ void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev,
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
- if (adev->nbio.funcs->get_pcie_index_hi_offset)
+ if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset))
pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);
else
pcie_index_hi = 0;
@@ -742,6 +945,55 @@ void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev,
spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
}
+void amdgpu_device_indirect_wreg64_ext(struct amdgpu_device *adev,
+ u64 reg_addr, u64 reg_data)
+{
+ unsigned long flags, pcie_index, pcie_data;
+ unsigned long pcie_index_hi = 0;
+ void __iomem *pcie_index_offset;
+ void __iomem *pcie_index_hi_offset;
+ void __iomem *pcie_data_offset;
+
+ pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
+ pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
+ if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset))
+ pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);
+
+ spin_lock_irqsave(&adev->pcie_idx_lock, flags);
+ pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
+ pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
+ if (pcie_index_hi != 0)
+ pcie_index_hi_offset = (void __iomem *)adev->rmmio +
+ pcie_index_hi * 4;
+
+ /* write low 32 bits */
+ writel(reg_addr, pcie_index_offset);
+ readl(pcie_index_offset);
+ if (pcie_index_hi != 0) {
+ writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
+ readl(pcie_index_hi_offset);
+ }
+ writel((u32)(reg_data & 0xffffffffULL), pcie_data_offset);
+ readl(pcie_data_offset);
+ /* write high 32 bits */
+ writel(reg_addr + 4, pcie_index_offset);
+ readl(pcie_index_offset);
+ if (pcie_index_hi != 0) {
+ writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
+ readl(pcie_index_hi_offset);
+ }
+ writel((u32)(reg_data >> 32), pcie_data_offset);
+ readl(pcie_data_offset);
+
+ /* clear the high bits */
+ if (pcie_index_hi != 0) {
+ writel(0, pcie_index_hi_offset);
+ readl(pcie_index_hi_offset);
+ }
+
+ spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
+}
+
/**
* amdgpu_device_get_rev_id - query device rev_id
*
@@ -819,6 +1071,13 @@ static uint64_t amdgpu_invalid_rreg64(struct amdgpu_device *adev, uint32_t reg)
return 0;
}
+static uint64_t amdgpu_invalid_rreg64_ext(struct amdgpu_device *adev, uint64_t reg)
+{
+ DRM_ERROR("Invalid callback to read register 0x%llX\n", reg);
+ BUG();
+ return 0;
+}
+
/**
* amdgpu_invalid_wreg64 - dummy reg write function
*
@@ -836,6 +1095,13 @@ static void amdgpu_invalid_wreg64(struct amdgpu_device *adev, uint32_t reg, uint
BUG();
}
+static void amdgpu_invalid_wreg64_ext(struct amdgpu_device *adev, uint64_t reg, uint64_t v)
+{
+ DRM_ERROR("Invalid callback to write 64 bit register 0x%llX with 0x%08llX\n",
+ reg, v);
+ BUG();
+}
+
/**
* amdgpu_block_invalid_rreg - dummy reg read function
*
@@ -889,10 +1155,12 @@ static int amdgpu_device_asic_init(struct amdgpu_device *adev)
amdgpu_asic_pre_asic_init(adev);
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3) ||
- adev->ip_versions[GC_HWIP][0] >= IP_VERSION(11, 0, 0)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(11, 0, 0)) {
amdgpu_psp_wait_for_bootloader(adev);
ret = amdgpu_atomfirmware_asic_init(adev, true);
+ /* TODO: check the return val and stop device initialization if boot fails */
+ amdgpu_psp_query_boot_status(adev);
return ret;
} else {
return amdgpu_atom_asic_init(adev->mode_info.atom_context);
@@ -1245,14 +1513,45 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev)
}
/*
- * Intel hosts such as Raptor Lake and Sapphire Rapids don't support dynamic
- * speed switching. Until we have confirmation from Intel that a specific host
- * supports it, it's safer that we keep it disabled for all.
+ * Check whether seamless boot is supported.
+ *
+ * So far we only support seamless boot on DCE 3.0 or later.
+ * If users report that it works on older ASICS as well, we may
+ * loosen this.
+ */
+bool amdgpu_device_seamless_boot_supported(struct amdgpu_device *adev)
+{
+ switch (amdgpu_seamless) {
+ case -1:
+ break;
+ case 1:
+ return true;
+ case 0:
+ return false;
+ default:
+ DRM_ERROR("Invalid value for amdgpu.seamless: %d\n",
+ amdgpu_seamless);
+ return false;
+ }
+
+ if (!(adev->flags & AMD_IS_APU))
+ return false;
+
+ if (adev->mman.keep_stolen_vga_memory)
+ return false;
+
+ return adev->ip_versions[DCE_HWIP][0] >= IP_VERSION(3, 0, 0);
+}
+
+/*
+ * Intel hosts such as Rocket Lake, Alder Lake, Raptor Lake and Sapphire Rapids
+ * don't support dynamic speed switching. Until we have confirmation from Intel
+ * that a specific host supports it, it's safer that we keep it disabled for all.
*
* https://edc.intel.com/content/www/us/en/design/products/platforms/details/raptor-lake-s/13th-generation-core-processors-datasheet-volume-1-of-2/005/pci-express-support/
* https://gitlab.freedesktop.org/drm/amd/-/issues/2663
*/
-bool amdgpu_device_pcie_dynamic_switching_supported(void)
+static bool amdgpu_device_pcie_dynamic_switching_supported(void)
{
#if IS_ENABLED(CONFIG_X86)
struct cpuinfo_x86 *c = &cpu_data(0);
@@ -1285,20 +1584,13 @@ bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev)
default:
return false;
}
+ if (adev->flags & AMD_IS_APU)
+ return false;
+ if (!(adev->pm.pp_feature & PP_PCIE_DPM_MASK))
+ return false;
return pcie_aspm_enabled(adev->pdev);
}
-bool amdgpu_device_aspm_support_quirk(void)
-{
-#if IS_ENABLED(CONFIG_X86)
- struct cpuinfo_x86 *c = &cpu_data(0);
-
- return !(c->x86 == 6 && c->x86_model == INTEL_FAM6_ALDERLAKE);
-#else
- return true;
-#endif
-}
-
/* if we get transitioned to only one device, take VGA back */
/**
* amdgpu_device_vga_set_decode - enable/disable vga decode
@@ -1547,6 +1839,7 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev,
} else {
pr_info("switched off\n");
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
+ amdgpu_device_prepare(dev);
amdgpu_device_suspend(dev, true);
amdgpu_device_cache_pci_state(pdev);
/* Shut down the device */
@@ -2018,7 +2311,6 @@ out:
*/
static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
{
- struct drm_device *dev = adev_to_drm(adev);
struct pci_dev *parent;
int i, r;
bool total;
@@ -2089,7 +2381,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
(amdgpu_is_atpx_hybrid() ||
amdgpu_has_atpx_dgpu_power_cntl()) &&
((adev->flags & AMD_IS_APU) == 0) &&
- !pci_is_thunderbolt_attached(to_pci_dev(dev->dev)))
+ !dev_is_removable(&adev->pdev->dev))
adev->flags |= AMD_IS_PX;
if (!(adev->flags & AMD_IS_APU)) {
@@ -2103,6 +2395,8 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
if (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_SIENNA_CICHLID)
adev->pm.pp_feature &= ~PP_OVERDRIVE_MASK;
+ if (!amdgpu_device_pcie_dynamic_switching_supported())
+ adev->pm.pp_feature &= ~PP_PCIE_DPM_MASK;
total = true;
for (i = 0; i < adev->num_ip_blocks; i++) {
@@ -2280,6 +2574,7 @@ static int amdgpu_device_init_schedulers(struct amdgpu_device *adev)
}
r = drm_sched_init(&ring->sched, &amdgpu_sched_ops,
+ DRM_SCHED_PRIORITY_COUNT,
ring->num_hw_submission, 0,
timeout, adev->reset_domain->wq,
ring->sched_score, ring->name,
@@ -2289,6 +2584,18 @@ static int amdgpu_device_init_schedulers(struct amdgpu_device *adev)
ring->name);
return r;
}
+ r = amdgpu_uvd_entity_init(adev, ring);
+ if (r) {
+ DRM_ERROR("Failed to create UVD scheduling entity on ring %s.\n",
+ ring->name);
+ return r;
+ }
+ r = amdgpu_vce_entity_init(adev, ring);
+ if (r) {
+ DRM_ERROR("Failed to create VCE scheduling entity on ring %s.\n",
+ ring->name);
+ return r;
+ }
}
amdgpu_xcp_update_partition_sched_list(adev);
@@ -2449,6 +2756,9 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
if (r)
goto init_failed;
+ if (adev->mman.buffer_funcs_ring->sched.ready)
+ amdgpu_ttm_set_buffer_funcs_status(adev, true);
+
/* Don't init kfd if whole hive need to be reset during init */
if (!adev->gmc.xgmi.pending_reset) {
kgd2kfd_init_zone_device(adev);
@@ -2731,7 +3041,7 @@ static void amdgpu_device_smu_fini_early(struct amdgpu_device *adev)
{
int i, r;
- if (adev->ip_versions[GC_HWIP][0] > IP_VERSION(9, 0, 0))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) > IP_VERSION(9, 0, 0))
return;
for (i = 0; i < adev->num_ip_blocks; i++) {
@@ -2984,8 +3294,10 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
/* SDMA 5.x+ is part of GFX power domain so it's covered by GFXOFF */
if (adev->in_s0ix &&
- (adev->ip_versions[SDMA0_HWIP][0] >= IP_VERSION(5, 0, 0)) &&
- (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SDMA))
+ (amdgpu_ip_version(adev, SDMA0_HWIP, 0) >=
+ IP_VERSION(5, 0, 0)) &&
+ (adev->ip_blocks[i].version->type ==
+ AMD_IP_BLOCK_TYPE_SDMA))
continue;
/* Once swPSP provides the IMU, RLC FW binaries to TOS during cold-boot.
@@ -3044,6 +3356,8 @@ int amdgpu_device_ip_suspend(struct amdgpu_device *adev)
amdgpu_virt_request_full_gpu(adev, false);
}
+ amdgpu_ttm_set_buffer_funcs_status(adev, false);
+
r = amdgpu_device_ip_suspend_phase1(adev);
if (r)
return r;
@@ -3233,6 +3547,9 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev)
r = amdgpu_device_ip_resume_phase2(adev);
+ if (adev->mman.buffer_funcs_ring->sched.ready)
+ amdgpu_ttm_set_buffer_funcs_status(adev, true);
+
return r;
}
@@ -3362,9 +3679,7 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work)
if (adev->asic_reset_res)
goto fail;
- if (adev->mmhub.ras && adev->mmhub.ras->ras_block.hw_ops &&
- adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count)
- adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count(adev);
+ amdgpu_ras_reset_error_count(adev, AMDGPU_RAS_BLOCK__MMHUB);
} else {
task_barrier_full(&hive->tb);
@@ -3476,10 +3791,6 @@ static void amdgpu_device_set_mcbp(struct amdgpu_device *adev)
adev->gfx.mcbp = true;
else if (amdgpu_mcbp == 0)
adev->gfx.mcbp = false;
- else if ((adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 0, 0)) &&
- (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 0, 0)) &&
- adev->gfx.num_gfx_rings)
- adev->gfx.mcbp = true;
if (amdgpu_sriov_vf(adev))
adev->gfx.mcbp = true;
@@ -3542,6 +3853,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
adev->pciep_wreg = &amdgpu_invalid_wreg;
adev->pcie_rreg64 = &amdgpu_invalid_rreg64;
adev->pcie_wreg64 = &amdgpu_invalid_wreg64;
+ adev->pcie_rreg64_ext = &amdgpu_invalid_rreg64_ext;
+ adev->pcie_wreg64_ext = &amdgpu_invalid_wreg64_ext;
adev->uvd_ctx_rreg = &amdgpu_invalid_rreg;
adev->uvd_ctx_wreg = &amdgpu_invalid_wreg;
adev->didt_rreg = &amdgpu_invalid_rreg;
@@ -3597,6 +3910,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
INIT_LIST_HEAD(&adev->ras_list);
+ INIT_LIST_HEAD(&adev->pm.od_kobj_list);
+
INIT_DELAYED_WORK(&adev->delayed_init_work,
amdgpu_device_delayed_init_work_handler);
INIT_DELAYED_WORK(&adev->gfx.gfx_off_delay_work,
@@ -3693,7 +4008,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
* internal path natively support atomics, set have_atomics_support to true.
*/
} else if ((adev->flags & AMD_IS_APU) &&
- (adev->ip_versions[GC_HWIP][0] > IP_VERSION(9, 0, 0))) {
+ (amdgpu_ip_version(adev, GC_HWIP, 0) >
+ IP_VERSION(9, 0, 0))) {
adev->have_atomics_support = true;
} else {
adev->have_atomics_support =
@@ -3741,13 +4057,23 @@ int amdgpu_device_init(struct amdgpu_device *adev,
}
}
} else {
- tmp = amdgpu_reset_method;
- /* It should do a default reset when loading or reloading the driver,
- * regardless of the module parameter reset_method.
- */
- amdgpu_reset_method = AMD_RESET_METHOD_NONE;
- r = amdgpu_asic_reset(adev);
- amdgpu_reset_method = tmp;
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
+ case IP_VERSION(13, 0, 0):
+ case IP_VERSION(13, 0, 7):
+ case IP_VERSION(13, 0, 10):
+ r = psp_gpu_reset(adev);
+ break;
+ default:
+ tmp = amdgpu_reset_method;
+ /* It should do a default reset when loading or reloading the driver,
+ * regardless of the module parameter reset_method.
+ */
+ amdgpu_reset_method = AMD_RESET_METHOD_NONE;
+ r = amdgpu_asic_reset(adev);
+ amdgpu_reset_method = tmp;
+ break;
+ }
+
if (r) {
dev_err(adev->dev, "asic reset on init failed\n");
goto failed;
@@ -3833,22 +4159,6 @@ fence_driver_init:
/* Get a log2 for easy divisions. */
adev->mm_stats.log2_max_MBps = ilog2(max(1u, max_MBps));
- r = amdgpu_atombios_sysfs_init(adev);
- if (r)
- drm_err(&adev->ddev,
- "registering atombios sysfs failed (%d).\n", r);
-
- r = amdgpu_pm_sysfs_init(adev);
- if (r)
- DRM_ERROR("registering pm sysfs failed (%d).\n", r);
-
- r = amdgpu_ucode_sysfs_init(adev);
- if (r) {
- adev->ucode_sysfs_en = false;
- DRM_ERROR("Creating firmware sysfs failed (%d).\n", r);
- } else
- adev->ucode_sysfs_en = true;
-
/*
* Register gpu instance before amdgpu_device_enable_mgpu_fan_boost.
* Otherwise the mgpu fan boost feature will be skipped due to the
@@ -3877,10 +4187,36 @@ fence_driver_init:
flush_delayed_work(&adev->delayed_init_work);
}
+ /*
+ * Place those sysfs registering after `late_init`. As some of those
+ * operations performed in `late_init` might affect the sysfs
+ * interfaces creating.
+ */
+ r = amdgpu_atombios_sysfs_init(adev);
+ if (r)
+ drm_err(&adev->ddev,
+ "registering atombios sysfs failed (%d).\n", r);
+
+ r = amdgpu_pm_sysfs_init(adev);
+ if (r)
+ DRM_ERROR("registering pm sysfs failed (%d).\n", r);
+
+ r = amdgpu_ucode_sysfs_init(adev);
+ if (r) {
+ adev->ucode_sysfs_en = false;
+ DRM_ERROR("Creating firmware sysfs failed (%d).\n", r);
+ } else
+ adev->ucode_sysfs_en = true;
+
r = sysfs_create_files(&adev->dev->kobj, amdgpu_dev_attributes);
if (r)
dev_err(adev->dev, "Could not create amdgpu device attr\n");
+ r = devm_device_add_group(adev->dev, &amdgpu_board_attrs_group);
+ if (r)
+ dev_err(adev->dev,
+ "Could not create amdgpu board attributes\n");
+
amdgpu_fru_sysfs_init(adev);
if (IS_ENABLED(CONFIG_PERF_EVENTS))
@@ -3901,7 +4237,7 @@ fence_driver_init:
px = amdgpu_device_supports_px(ddev);
- if (px || (!pci_is_thunderbolt_attached(adev->pdev) &&
+ if (px || (!dev_is_removable(&adev->pdev->dev) &&
apple_gmux_detect(NULL, NULL)))
vga_switcheroo_register_client(adev->pdev,
&amdgpu_switcheroo_ops, px);
@@ -4007,6 +4343,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
/* disable ras feature must before hw fini */
amdgpu_ras_pre_fini(adev);
+ amdgpu_ttm_set_buffer_funcs_status(adev, false);
+
amdgpu_device_ip_fini_early(adev);
amdgpu_irq_fini_hw(adev);
@@ -4044,9 +4382,12 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
kfree(adev->bios);
adev->bios = NULL;
+ kfree(adev->fru_info);
+ adev->fru_info = NULL;
+
px = amdgpu_device_supports_px(adev_to_drm(adev));
- if (px || (!pci_is_thunderbolt_attached(adev->pdev) &&
+ if (px || (!dev_is_removable(&adev->pdev->dev) &&
apple_gmux_detect(NULL, NULL)))
vga_switcheroo_unregister_client(adev->pdev);
@@ -4103,6 +4444,41 @@ static int amdgpu_device_evict_resources(struct amdgpu_device *adev)
* Suspend & resume.
*/
/**
+ * amdgpu_device_prepare - prepare for device suspend
+ *
+ * @dev: drm dev pointer
+ *
+ * Prepare to put the hw in the suspend state (all asics).
+ * Returns 0 for success or an error on failure.
+ * Called at driver suspend.
+ */
+int amdgpu_device_prepare(struct drm_device *dev)
+{
+ struct amdgpu_device *adev = drm_to_adev(dev);
+ int i, r;
+
+ if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+ return 0;
+
+ /* Evict the majority of BOs before starting suspend sequence */
+ r = amdgpu_device_evict_resources(adev);
+ if (r)
+ return r;
+
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+ if (!adev->ip_blocks[i].status.valid)
+ continue;
+ if (!adev->ip_blocks[i].version->funcs->prepare_suspend)
+ continue;
+ r = adev->ip_blocks[i].version->funcs->prepare_suspend((void *)adev);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+/**
* amdgpu_device_suspend - initiate device suspend
*
* @dev: drm dev pointer
@@ -4122,11 +4498,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
adev->in_suspend = true;
- /* Evict the majority of BOs before grabbing the full access */
- r = amdgpu_device_evict_resources(adev);
- if (r)
- return r;
-
if (amdgpu_sriov_vf(adev)) {
amdgpu_virt_fini_data_exchange(adev);
r = amdgpu_virt_request_full_gpu(adev, false);
@@ -4154,6 +4525,8 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
if (r)
return r;
+ amdgpu_ttm_set_buffer_funcs_status(adev, false);
+
amdgpu_fence_driver_hw_fini(adev);
amdgpu_device_ip_suspend_phase2(adev);
@@ -4161,6 +4534,10 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
if (amdgpu_sriov_vf(adev))
amdgpu_virt_release_full_gpu(adev, false);
+ r = amdgpu_dpm_notify_rlc_state(adev, false);
+ if (r)
+ return r;
+
return 0;
}
@@ -4206,19 +4583,18 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
}
amdgpu_fence_driver_hw_init(adev);
- r = amdgpu_device_ip_late_init(adev);
- if (r)
- goto exit;
-
- queue_delayed_work(system_wq, &adev->delayed_init_work,
- msecs_to_jiffies(AMDGPU_RESUME_MS));
-
if (!adev->in_s0ix) {
r = amdgpu_amdkfd_resume(adev, adev->in_runpm);
if (r)
goto exit;
}
+ r = amdgpu_device_ip_late_init(adev);
+ if (r)
+ goto exit;
+
+ queue_delayed_work(system_wq, &adev->delayed_init_work,
+ msecs_to_jiffies(AMDGPU_RESUME_MS));
exit:
if (amdgpu_sriov_vf(adev)) {
amdgpu_virt_init_data_exchange(adev);
@@ -4786,67 +5162,16 @@ static int amdgpu_reset_reg_dumps(struct amdgpu_device *adev)
lockdep_assert_held(&adev->reset_domain->sem);
- for (i = 0; i < adev->num_regs; i++) {
- adev->reset_dump_reg_value[i] = RREG32(adev->reset_dump_reg_list[i]);
- trace_amdgpu_reset_reg_dumps(adev->reset_dump_reg_list[i],
- adev->reset_dump_reg_value[i]);
- }
-
- return 0;
-}
-
-#ifdef CONFIG_DEV_COREDUMP
-static ssize_t amdgpu_devcoredump_read(char *buffer, loff_t offset,
- size_t count, void *data, size_t datalen)
-{
- struct drm_printer p;
- struct amdgpu_device *adev = data;
- struct drm_print_iterator iter;
- int i;
-
- iter.data = buffer;
- iter.offset = 0;
- iter.start = offset;
- iter.remain = count;
-
- p = drm_coredump_printer(&iter);
-
- drm_printf(&p, "**** AMDGPU Device Coredump ****\n");
- drm_printf(&p, "kernel: " UTS_RELEASE "\n");
- drm_printf(&p, "module: " KBUILD_MODNAME "\n");
- drm_printf(&p, "time: %lld.%09ld\n", adev->reset_time.tv_sec, adev->reset_time.tv_nsec);
- if (adev->reset_task_info.pid)
- drm_printf(&p, "process_name: %s PID: %d\n",
- adev->reset_task_info.process_name,
- adev->reset_task_info.pid);
+ for (i = 0; i < adev->reset_info.num_regs; i++) {
+ adev->reset_info.reset_dump_reg_value[i] =
+ RREG32(adev->reset_info.reset_dump_reg_list[i]);
- if (adev->reset_vram_lost)
- drm_printf(&p, "VRAM is lost due to GPU reset!\n");
- if (adev->num_regs) {
- drm_printf(&p, "AMDGPU register dumps:\nOffset: Value:\n");
-
- for (i = 0; i < adev->num_regs; i++)
- drm_printf(&p, "0x%08x: 0x%08x\n",
- adev->reset_dump_reg_list[i],
- adev->reset_dump_reg_value[i]);
+ trace_amdgpu_reset_reg_dumps(adev->reset_info.reset_dump_reg_list[i],
+ adev->reset_info.reset_dump_reg_value[i]);
}
- return count - iter.remain;
-}
-
-static void amdgpu_devcoredump_free(void *data)
-{
-}
-
-static void amdgpu_reset_capture_coredumpm(struct amdgpu_device *adev)
-{
- struct drm_device *dev = adev_to_drm(adev);
-
- ktime_get_ts64(&adev->reset_time);
- dev_coredumpm(dev->dev, THIS_MODULE, adev, 0, GFP_NOWAIT,
- amdgpu_devcoredump_read, amdgpu_devcoredump_free);
+ return 0;
}
-#endif
int amdgpu_do_asic_reset(struct list_head *device_list_handle,
struct amdgpu_reset_context *reset_context)
@@ -4895,7 +5220,7 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,
if (r) {
dev_err(tmp_adev->dev, "ASIC reset failed with error, %d for drm dev, %s",
r, adev_to_drm(tmp_adev)->unique);
- break;
+ goto out;
}
}
@@ -4914,9 +5239,7 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,
if (!r && amdgpu_ras_intr_triggered()) {
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
- if (tmp_adev->mmhub.ras && tmp_adev->mmhub.ras->ras_block.hw_ops &&
- tmp_adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count)
- tmp_adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count(tmp_adev);
+ amdgpu_ras_reset_error_count(tmp_adev, AMDGPU_RAS_BLOCK__MMHUB);
}
amdgpu_ras_intr_cleared();
@@ -4948,15 +5271,9 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,
goto out;
vram_lost = amdgpu_device_check_vram_lost(tmp_adev);
-#ifdef CONFIG_DEV_COREDUMP
- tmp_adev->reset_vram_lost = vram_lost;
- memset(&tmp_adev->reset_task_info, 0,
- sizeof(tmp_adev->reset_task_info));
- if (reset_context->job && reset_context->job->vm)
- tmp_adev->reset_task_info =
- reset_context->job->vm->task_info;
- amdgpu_reset_capture_coredumpm(tmp_adev);
-#endif
+
+ amdgpu_coredump(tmp_adev, vram_lost, reset_context);
+
if (vram_lost) {
DRM_INFO("VRAM is lost due to GPU reset!\n");
amdgpu_inc_vram_lost(tmp_adev);
@@ -4966,10 +5283,18 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,
if (r)
return r;
+ r = amdgpu_xcp_restore_partition_mode(
+ tmp_adev->xcp_mgr);
+ if (r)
+ goto out;
+
r = amdgpu_device_ip_resume_phase2(tmp_adev);
if (r)
goto out;
+ if (tmp_adev->mman.buffer_funcs_ring->sched.ready)
+ amdgpu_ttm_set_buffer_funcs_status(tmp_adev, true);
+
if (vram_lost)
amdgpu_device_fill_reset_magic(tmp_adev);
@@ -5183,7 +5508,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
* Flush RAM to disk so that after reboot
* the user can read log and see why the system rebooted.
*/
- if (need_emergency_restart && amdgpu_ras_get_context(adev)->reboot) {
+ if (need_emergency_restart && amdgpu_ras_get_context(adev) &&
+ amdgpu_ras_get_context(adev)->reboot) {
DRM_WARN("Emergency reboot.");
ksys_sync_helper();
@@ -5321,8 +5647,9 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
adev->asic_reset_res = r;
/* Aldebaran and gfx_11_0_3 support ras in SRIOV, so need resume ras during reset */
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 3))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(9, 4, 2) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 0, 3))
amdgpu_ras_resume(adev);
} else {
r = amdgpu_do_asic_reset(device_list_handle, reset_context);
@@ -5347,9 +5674,6 @@ skip_hw_reset:
drm_sched_start(&ring->sched, true);
}
- if (adev->enable_mes && adev->ip_versions[GC_HWIP][0] != IP_VERSION(11, 0, 3))
- amdgpu_mes_self_test(tmp_adev);
-
if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled)
drm_helper_resume_force_mode(adev_to_drm(tmp_adev));
@@ -6024,7 +6348,7 @@ bool amdgpu_device_has_display_hardware(struct amdgpu_device *adev)
return true;
default:
/* IP discovery */
- if (!adev->ip_versions[DCE_HWIP][0] ||
+ if (!amdgpu_ip_version(adev, DCE_HWIP, 0) ||
(adev->harvest_ip_mask & AMD_HARVEST_IP_DMU_MASK))
return false;
return true;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index 7d5e7ad28ba8..0431eafa86b5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -35,10 +35,12 @@
#include "df_v1_7.h"
#include "df_v3_6.h"
#include "df_v4_3.h"
+#include "df_v4_6_2.h"
#include "nbio_v6_1.h"
#include "nbio_v7_0.h"
#include "nbio_v7_4.h"
#include "nbio_v7_9.h"
+#include "nbio_v7_11.h"
#include "hdp_v4_0.h"
#include "vega10_ih.h"
#include "vega20_ih.h"
@@ -80,6 +82,8 @@
#include "jpeg_v4_0.h"
#include "vcn_v4_0_3.h"
#include "jpeg_v4_0_3.h"
+#include "vcn_v4_0_5.h"
+#include "jpeg_v4_0_5.h"
#include "amdgpu_vkms.h"
#include "mes_v10_1.h"
#include "mes_v11_0.h"
@@ -89,10 +93,13 @@
#include "smuio_v13_0_3.h"
#include "smuio_v13_0_6.h"
+#include "amdgpu_vpe.h"
+
#define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin"
MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY);
#define mmRCC_CONFIG_MEMSIZE 0xde3
+#define mmMP0_SMN_C2PMSG_33 0x16061
#define mmMM_INDEX 0x0
#define mmMM_INDEX_HI 0x6
#define mmMM_DATA 0x1
@@ -174,6 +181,7 @@ static const char *hw_id_names[HW_ID_MAX] = {
[XGMI_HWID] = "XGMI",
[XGBE_HWID] = "XGBE",
[MP0_HWID] = "MP0",
+ [VPE_HWID] = "VPE",
};
static int hw_id_map[MAX_HWIP] = {
@@ -203,6 +211,7 @@ static int hw_id_map[MAX_HWIP] = {
[XGMI_HWIP] = XGMI_HWID,
[DCI_HWIP] = DCI_HWID,
[PCIE_HWIP] = PCIE_HWID,
+ [VPE_HWIP] = VPE_HWID,
};
static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev, uint8_t *binary)
@@ -231,8 +240,26 @@ static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev,
static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
uint8_t *binary)
{
- uint64_t vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
- int ret = 0;
+ uint64_t vram_size;
+ u32 msg;
+ int i, ret = 0;
+
+ /* It can take up to a second for IFWI init to complete on some dGPUs,
+ * but generally it should be in the 60-100ms range. Normally this starts
+ * as soon as the device gets power so by the time the OS loads this has long
+ * completed. However, when a card is hotplugged via e.g., USB4, we need to
+ * wait for this to complete. Once the C2PMSG is updated, we can
+ * continue.
+ */
+ if (dev_is_removable(&adev->pdev->dev)) {
+ for (i = 0; i < 1000; i++) {
+ msg = RREG32(mmMP0_SMN_C2PMSG_33);
+ if (msg & 0x80000000)
+ break;
+ msleep(1);
+ }
+ }
+ vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
if (vram_size) {
uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET;
@@ -304,8 +331,8 @@ static void amdgpu_discovery_harvest_config_quirk(struct amdgpu_device *adev)
* So far, apply this quirk only on those Navy Flounder boards which
* have a bad harvest table of VCN config.
*/
- if ((adev->ip_versions[UVD_HWIP][1] == IP_VERSION(3, 0, 1)) &&
- (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 2))) {
+ if ((amdgpu_ip_version(adev, UVD_HWIP, 1) == IP_VERSION(3, 0, 1)) &&
+ (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 3, 2))) {
switch (adev->pdev->revision) {
case 0xC1:
case 0xC2:
@@ -655,7 +682,7 @@ struct ip_hw_instance {
u8 harvest;
int num_base_addresses;
- u32 base_addr[];
+ u32 base_addr[] __counted_by(num_base_addresses);
};
struct ip_hw_id {
@@ -1184,6 +1211,7 @@ static void amdgpu_discovery_sysfs_fini(struct amdgpu_device *adev)
static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
{
+ uint8_t num_base_address, subrev, variant;
struct binary_header *bhdr;
struct ip_discovery_header *ihdr;
struct die_header *dhdr;
@@ -1192,7 +1220,6 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
uint16_t ip_offset;
uint16_t num_dies;
uint16_t num_ips;
- uint8_t num_base_address;
int hw_ip;
int i, j, k;
int r;
@@ -1330,8 +1357,22 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
* example. On most chips there are multiple instances
* with the same HWID.
*/
- adev->ip_versions[hw_ip][ip->instance_number] =
- IP_VERSION(ip->major, ip->minor, ip->revision);
+
+ if (ihdr->version < 3) {
+ subrev = 0;
+ variant = 0;
+ } else {
+ subrev = ip->sub_revision;
+ variant = ip->variant;
+ }
+
+ adev->ip_versions[hw_ip]
+ [ip->instance_number] =
+ IP_VERSION_FULL(ip->major,
+ ip->minor,
+ ip->revision,
+ variant,
+ subrev);
}
}
@@ -1356,8 +1397,8 @@ static void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
* so read harvest bit per IP data structure to set
* harvest configuration.
*/
- if (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 2, 0) &&
- adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 3)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(10, 2, 0) &&
+ amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 3)) {
if ((adev->pdev->device == 0x731E &&
(adev->pdev->revision == 0xC6 ||
adev->pdev->revision == 0xC7)) ||
@@ -1432,12 +1473,12 @@ static int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
adev->gfx.config.num_sc_per_sh = le32_to_cpu(gc_info->v1.gc_num_sc_per_se) /
le32_to_cpu(gc_info->v1.gc_num_sa_per_se);
adev->gfx.config.num_packer_per_sc = le32_to_cpu(gc_info->v1.gc_num_packer_per_sc);
- if (gc_info->v1.header.version_minor >= 1) {
+ if (le16_to_cpu(gc_info->v1.header.version_minor) >= 1) {
adev->gfx.config.gc_num_tcp_per_sa = le32_to_cpu(gc_info->v1_1.gc_num_tcp_per_sa);
adev->gfx.config.gc_num_sdp_interface = le32_to_cpu(gc_info->v1_1.gc_num_sdp_interface);
adev->gfx.config.gc_num_tcps = le32_to_cpu(gc_info->v1_1.gc_num_tcps);
}
- if (gc_info->v1.header.version_minor >= 2) {
+ if (le16_to_cpu(gc_info->v1.header.version_minor) >= 2) {
adev->gfx.config.gc_num_tcp_per_wpg = le32_to_cpu(gc_info->v1_2.gc_num_tcp_per_wpg);
adev->gfx.config.gc_tcp_l1_size = le32_to_cpu(gc_info->v1_2.gc_tcp_l1_size);
adev->gfx.config.gc_num_sqc_per_wgp = le32_to_cpu(gc_info->v1_2.gc_num_sqc_per_wgp);
@@ -1466,7 +1507,7 @@ static int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
adev->gfx.config.num_sc_per_sh = le32_to_cpu(gc_info->v2.gc_num_sc_per_se) /
le32_to_cpu(gc_info->v2.gc_num_sh_per_se);
adev->gfx.config.num_packer_per_sc = le32_to_cpu(gc_info->v2.gc_num_packer_per_sc);
- if (gc_info->v2.header.version_minor == 1) {
+ if (le16_to_cpu(gc_info->v2.header.version_minor) == 1) {
adev->gfx.config.gc_num_tcp_per_sa = le32_to_cpu(gc_info->v2_1.gc_num_tcp_per_sh);
adev->gfx.config.gc_tcp_size_per_cu = le32_to_cpu(gc_info->v2_1.gc_tcp_size_per_cu);
adev->gfx.config.gc_num_sdp_interface = le32_to_cpu(gc_info->v2_1.gc_num_sdp_interface); /* per XCD */
@@ -1600,7 +1641,7 @@ static int amdgpu_discovery_get_vcn_info(struct amdgpu_device *adev)
static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev)
{
/* what IP to use for this? */
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 1):
@@ -1632,12 +1673,13 @@ static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
amdgpu_device_ip_block_add(adev, &soc21_common_ip_block);
break;
default:
dev_err(adev->dev,
"Failed to add common ip block(GC_HWIP:0x%x)\n",
- adev->ip_versions[GC_HWIP][0]);
+ amdgpu_ip_version(adev, GC_HWIP, 0));
return -EINVAL;
}
return 0;
@@ -1646,7 +1688,7 @@ static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev)
static int amdgpu_discovery_set_gmc_ip_blocks(struct amdgpu_device *adev)
{
/* use GC or MMHUB IP version */
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 1):
@@ -1678,12 +1720,12 @@ static int amdgpu_discovery_set_gmc_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
amdgpu_device_ip_block_add(adev, &gmc_v11_0_ip_block);
break;
default:
- dev_err(adev->dev,
- "Failed to add gmc ip block(GC_HWIP:0x%x)\n",
- adev->ip_versions[GC_HWIP][0]);
+ dev_err(adev->dev, "Failed to add gmc ip block(GC_HWIP:0x%x)\n",
+ amdgpu_ip_version(adev, GC_HWIP, 0));
return -EINVAL;
}
return 0;
@@ -1691,7 +1733,7 @@ static int amdgpu_discovery_set_gmc_ip_blocks(struct amdgpu_device *adev)
static int amdgpu_discovery_set_ih_ip_blocks(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[OSSSYS_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, OSSSYS_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
case IP_VERSION(4, 0, 1):
case IP_VERSION(4, 1, 0):
@@ -1724,7 +1766,7 @@ static int amdgpu_discovery_set_ih_ip_blocks(struct amdgpu_device *adev)
default:
dev_err(adev->dev,
"Failed to add ih ip block(OSSSYS_HWIP:0x%x)\n",
- adev->ip_versions[OSSSYS_HWIP][0]);
+ amdgpu_ip_version(adev, OSSSYS_HWIP, 0));
return -EINVAL;
}
return 0;
@@ -1732,7 +1774,7 @@ static int amdgpu_discovery_set_ih_ip_blocks(struct amdgpu_device *adev)
static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
case IP_VERSION(9, 0, 0):
amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block);
break;
@@ -1778,7 +1820,7 @@ static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev)
default:
dev_err(adev->dev,
"Failed to add psp ip block(MP0_HWIP:0x%x)\n",
- adev->ip_versions[MP0_HWIP][0]);
+ amdgpu_ip_version(adev, MP0_HWIP, 0));
return -EINVAL;
}
return 0;
@@ -1786,7 +1828,7 @@ static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev)
static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[MP1_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(9, 0, 0):
case IP_VERSION(10, 0, 0):
case IP_VERSION(10, 0, 1):
@@ -1824,10 +1866,13 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 11):
amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
break;
+ case IP_VERSION(14, 0, 0):
+ amdgpu_device_ip_block_add(adev, &smu_v14_0_ip_block);
+ break;
default:
dev_err(adev->dev,
"Failed to add smu ip block(MP1_HWIP:0x%x)\n",
- adev->ip_versions[MP1_HWIP][0]);
+ amdgpu_ip_version(adev, MP1_HWIP, 0));
return -EINVAL;
}
return 0;
@@ -1852,8 +1897,8 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
return 0;
#if defined(CONFIG_DRM_AMD_DC)
- if (adev->ip_versions[DCE_HWIP][0]) {
- switch (adev->ip_versions[DCE_HWIP][0]) {
+ if (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
case IP_VERSION(2, 0, 2):
@@ -1871,6 +1916,7 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(3, 1, 6):
case IP_VERSION(3, 2, 0):
case IP_VERSION(3, 2, 1):
+ case IP_VERSION(3, 5, 0):
if (amdgpu_sriov_vf(adev))
amdgpu_discovery_set_sriov_display(adev);
else
@@ -1879,11 +1925,11 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
default:
dev_err(adev->dev,
"Failed to add dm ip block(DCE_HWIP:0x%x)\n",
- adev->ip_versions[DCE_HWIP][0]);
+ amdgpu_ip_version(adev, DCE_HWIP, 0));
return -EINVAL;
}
- } else if (adev->ip_versions[DCI_HWIP][0]) {
- switch (adev->ip_versions[DCI_HWIP][0]) {
+ } else if (amdgpu_ip_version(adev, DCI_HWIP, 0)) {
+ switch (amdgpu_ip_version(adev, DCI_HWIP, 0)) {
case IP_VERSION(12, 0, 0):
case IP_VERSION(12, 0, 1):
case IP_VERSION(12, 1, 0):
@@ -1895,7 +1941,7 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
default:
dev_err(adev->dev,
"Failed to add dm ip block(DCI_HWIP:0x%x)\n",
- adev->ip_versions[DCI_HWIP][0]);
+ amdgpu_ip_version(adev, DCI_HWIP, 0));
return -EINVAL;
}
}
@@ -1905,7 +1951,7 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 1):
@@ -1941,12 +1987,12 @@ static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
amdgpu_device_ip_block_add(adev, &gfx_v11_0_ip_block);
break;
default:
- dev_err(adev->dev,
- "Failed to add gfx ip block(GC_HWIP:0x%x)\n",
- adev->ip_versions[GC_HWIP][0]);
+ dev_err(adev->dev, "Failed to add gfx ip block(GC_HWIP:0x%x)\n",
+ amdgpu_ip_version(adev, GC_HWIP, 0));
return -EINVAL;
}
return 0;
@@ -1954,7 +2000,7 @@ static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev)
static int amdgpu_discovery_set_sdma_ip_blocks(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
case IP_VERSION(4, 0, 1):
case IP_VERSION(4, 1, 0):
@@ -1994,7 +2040,7 @@ static int amdgpu_discovery_set_sdma_ip_blocks(struct amdgpu_device *adev)
default:
dev_err(adev->dev,
"Failed to add sdma ip block(SDMA0_HWIP:0x%x)\n",
- adev->ip_versions[SDMA0_HWIP][0]);
+ amdgpu_ip_version(adev, SDMA0_HWIP, 0));
return -EINVAL;
}
return 0;
@@ -2002,8 +2048,8 @@ static int amdgpu_discovery_set_sdma_ip_blocks(struct amdgpu_device *adev)
static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
{
- if (adev->ip_versions[VCE_HWIP][0]) {
- switch (adev->ip_versions[UVD_HWIP][0]) {
+ if (amdgpu_ip_version(adev, VCE_HWIP, 0)) {
+ switch (amdgpu_ip_version(adev, UVD_HWIP, 0)) {
case IP_VERSION(7, 0, 0):
case IP_VERSION(7, 2, 0):
/* UVD is not supported on vega20 SR-IOV */
@@ -2013,10 +2059,10 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
default:
dev_err(adev->dev,
"Failed to add uvd v7 ip block(UVD_HWIP:0x%x)\n",
- adev->ip_versions[UVD_HWIP][0]);
+ amdgpu_ip_version(adev, UVD_HWIP, 0));
return -EINVAL;
}
- switch (adev->ip_versions[VCE_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, VCE_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
case IP_VERSION(4, 1, 0):
/* VCE is not supported on vega20 SR-IOV */
@@ -2026,11 +2072,11 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
default:
dev_err(adev->dev,
"Failed to add VCE v4 ip block(VCE_HWIP:0x%x)\n",
- adev->ip_versions[VCE_HWIP][0]);
+ amdgpu_ip_version(adev, VCE_HWIP, 0));
return -EINVAL;
}
} else {
- switch (adev->ip_versions[UVD_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, UVD_HWIP, 0)) {
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
amdgpu_device_ip_block_add(adev, &vcn_v1_0_ip_block);
@@ -2074,10 +2120,14 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &vcn_v4_0_3_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v4_0_3_ip_block);
break;
+ case IP_VERSION(4, 0, 5):
+ amdgpu_device_ip_block_add(adev, &vcn_v4_0_5_ip_block);
+ amdgpu_device_ip_block_add(adev, &jpeg_v4_0_5_ip_block);
+ break;
default:
dev_err(adev->dev,
"Failed to add vcn/jpeg ip block(UVD_HWIP:0x%x)\n",
- adev->ip_versions[UVD_HWIP][0]);
+ amdgpu_ip_version(adev, UVD_HWIP, 0));
return -EINVAL;
}
}
@@ -2086,7 +2136,7 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 2):
@@ -2111,6 +2161,7 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
amdgpu_device_ip_block_add(adev, &mes_v11_0_ip_block);
adev->enable_mes = true;
adev->enable_mes_kiq = true;
@@ -2123,7 +2174,7 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)
static void amdgpu_discovery_init_soc_config(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 4, 3):
aqua_vanjaram_init_soc_config(adev);
break;
@@ -2132,6 +2183,35 @@ static void amdgpu_discovery_init_soc_config(struct amdgpu_device *adev)
}
}
+static int amdgpu_discovery_set_vpe_ip_blocks(struct amdgpu_device *adev)
+{
+ switch (amdgpu_ip_version(adev, VPE_HWIP, 0)) {
+ case IP_VERSION(6, 1, 0):
+ amdgpu_device_ip_block_add(adev, &vpe_v6_1_ip_block);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int amdgpu_discovery_set_umsch_mm_ip_blocks(struct amdgpu_device *adev)
+{
+ switch (amdgpu_ip_version(adev, VCN_HWIP, 0)) {
+ case IP_VERSION(4, 0, 5):
+ if (amdgpu_umsch_mm & 0x1) {
+ amdgpu_device_ip_block_add(adev, &umsch_mm_v4_0_ip_block);
+ adev->enable_umsch_mm = true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
{
int r;
@@ -2312,7 +2392,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_discovery_init_soc_config(adev);
amdgpu_discovery_sysfs_init(adev);
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 2, 1):
case IP_VERSION(9, 4, 0):
@@ -2359,11 +2439,14 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 4):
adev->family = AMDGPU_FAMILY_GC_11_0_1;
break;
+ case IP_VERSION(11, 5, 0):
+ adev->family = AMDGPU_FAMILY_GC_11_5_0;
+ break;
default:
return -EINVAL;
}
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 2):
case IP_VERSION(9, 3, 0):
@@ -2375,17 +2458,21 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(10, 3, 7):
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
adev->flags |= AMD_IS_APU;
break;
default:
break;
}
- if (adev->ip_versions[XGMI_HWIP][0] == IP_VERSION(4, 8, 0))
+ if (amdgpu_ip_version(adev, XGMI_HWIP, 0) == IP_VERSION(4, 8, 0))
adev->gmc.xgmi.supported = true;
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3))
+ adev->ip_versions[XGMI_HWIP][0] = IP_VERSION(6, 4, 0);
+
/* set NBIO version */
- switch (adev->ip_versions[NBIO_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
case IP_VERSION(6, 1, 0):
case IP_VERSION(6, 2, 0):
adev->nbio.funcs = &nbio_v6_1_funcs;
@@ -2407,6 +2494,10 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
adev->nbio.funcs = &nbio_v7_9_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_9_hdp_flush_reg;
break;
+ case IP_VERSION(7, 11, 0):
+ adev->nbio.funcs = &nbio_v7_11_funcs;
+ adev->nbio.hdp_flush_reg = &nbio_v7_11_hdp_flush_reg;
+ break;
case IP_VERSION(7, 2, 0):
case IP_VERSION(7, 2, 1):
case IP_VERSION(7, 3, 0):
@@ -2443,7 +2534,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
break;
}
- switch (adev->ip_versions[HDP_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, HDP_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
case IP_VERSION(4, 0, 1):
case IP_VERSION(4, 1, 0):
@@ -2475,7 +2566,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
break;
}
- switch (adev->ip_versions[DF_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, DF_HWIP, 0)) {
case IP_VERSION(3, 6, 0):
case IP_VERSION(3, 6, 1):
case IP_VERSION(3, 6, 2):
@@ -2491,11 +2582,14 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(4, 3, 0):
adev->df.funcs = &df_v4_3_funcs;
break;
+ case IP_VERSION(4, 6, 2):
+ adev->df.funcs = &df_v4_6_2_funcs;
+ break;
default:
break;
}
- switch (adev->ip_versions[SMUIO_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SMUIO_HWIP, 0)) {
case IP_VERSION(9, 0, 0):
case IP_VERSION(9, 0, 1):
case IP_VERSION(10, 0, 0):
@@ -2538,7 +2632,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
break;
}
- switch (adev->ip_versions[LSDMA_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, LSDMA_HWIP, 0)) {
case IP_VERSION(6, 0, 0):
case IP_VERSION(6, 0, 1):
case IP_VERSION(6, 0, 2):
@@ -2611,6 +2705,14 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
if (r)
return r;
+ r = amdgpu_discovery_set_vpe_ip_blocks(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_discovery_set_umsch_mm_ip_blocks(adev);
+ if (r)
+ return r;
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
index 3a2f347bd50d..4d03cd5b3410 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
@@ -24,7 +24,7 @@
#ifndef __AMDGPU_DISCOVERY__
#define __AMDGPU_DISCOVERY__
-#define DISCOVERY_TMR_SIZE (8 << 10)
+#define DISCOVERY_TMR_SIZE (10 << 10)
#define DISCOVERY_TMR_OFFSET (64 << 10)
void amdgpu_discovery_fini(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 363e6a2cad8c..b8fbe97efe1d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -340,14 +340,11 @@ int amdgpu_display_crtc_set_config(struct drm_mode_set *set,
adev->have_disp_power_ref = true;
return ret;
}
- /* if we have no active crtcs, then drop the power ref
- * we got before
+ /* if we have no active crtcs, then go to
+ * drop the power ref we got before
*/
- if (!active && adev->have_disp_power_ref) {
- pm_runtime_put_autosuspend(dev->dev);
+ if (!active && adev->have_disp_power_ref)
adev->have_disp_power_ref = false;
- }
-
out:
/* drop the power reference we got coming in here */
pm_runtime_put_autosuspend(dev->dev);
@@ -766,11 +763,13 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
return -EINVAL;
}
- if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(11, 0, 0))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(11, 0, 0))
version = AMD_FMT_MOD_TILE_VER_GFX11;
- else if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0))
+ else if (amdgpu_ip_version(adev, GC_HWIP, 0) >=
+ IP_VERSION(10, 3, 0))
version = AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS;
- else if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 0, 0))
+ else if (amdgpu_ip_version(adev, GC_HWIP, 0) >=
+ IP_VERSION(10, 0, 0))
version = AMD_FMT_MOD_TILE_VER_GFX10;
else
version = AMD_FMT_MOD_TILE_VER_GFX9;
@@ -779,13 +778,15 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
case 0: /* Z microtiling */
return -EINVAL;
case 1: /* S microtiling */
- if (adev->ip_versions[GC_HWIP][0] < IP_VERSION(11, 0, 0)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) <
+ IP_VERSION(11, 0, 0)) {
if (!has_xor)
version = AMD_FMT_MOD_TILE_VER_GFX9;
}
break;
case 2:
- if (adev->ip_versions[GC_HWIP][0] < IP_VERSION(11, 0, 0)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) <
+ IP_VERSION(11, 0, 0)) {
if (!has_xor && afb->base.format->cpp[0] != 4)
version = AMD_FMT_MOD_TILE_VER_GFX9;
}
@@ -838,10 +839,12 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
u64 render_dcc_offset;
/* Enable constant encode on RAVEN2 and later. */
- bool dcc_constant_encode = (adev->asic_type > CHIP_RAVEN ||
- (adev->asic_type == CHIP_RAVEN &&
- adev->external_rev_id >= 0x81)) &&
- adev->ip_versions[GC_HWIP][0] < IP_VERSION(11, 0, 0);
+ bool dcc_constant_encode =
+ (adev->asic_type > CHIP_RAVEN ||
+ (adev->asic_type == CHIP_RAVEN &&
+ adev->external_rev_id >= 0x81)) &&
+ amdgpu_ip_version(adev, GC_HWIP, 0) <
+ IP_VERSION(11, 0, 0);
int max_cblock_size = dcc_i64b ? AMD_FMT_MOD_DCC_BLOCK_64B :
dcc_i128b ? AMD_FMT_MOD_DCC_BLOCK_128B :
@@ -878,7 +881,9 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
if (adev->family >= AMDGPU_FAMILY_NV) {
int extra_pipe = 0;
- if ((adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0)) &&
+ if ((amdgpu_ip_version(adev, GC_HWIP,
+ 0) >=
+ IP_VERSION(10, 3, 0)) &&
pipes == packers && pipes > 1)
extra_pipe = 1;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 12210598e5b8..e7e87a3b2601 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -331,6 +331,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
flags |= other->flags & (AMDGPU_GEM_CREATE_CPU_GTT_USWC |
AMDGPU_GEM_CREATE_COHERENT |
+ AMDGPU_GEM_CREATE_EXT_COHERENT |
AMDGPU_GEM_CREATE_UNCACHED);
}
@@ -403,9 +404,12 @@ amdgpu_dma_buf_move_notify(struct dma_buf_attachment *attach)
continue;
}
- r = amdgpu_vm_clear_freed(adev, vm, NULL);
+ /* Reserve fences for two SDMA page table updates */
+ r = dma_resv_reserve_fences(resv, 2);
if (!r)
- r = amdgpu_vm_handle_moved(adev, vm);
+ r = amdgpu_vm_clear_freed(adev, vm, NULL);
+ if (!r)
+ r = amdgpu_vm_handle_moved(adev, vm, ticket);
if (r && r != -EBUSY)
DRM_ERROR("Failed to invalidate VM page tables (%d))\n",
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell.h
index 09f6727e7c73..2675689ef70f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell.h
@@ -86,6 +86,7 @@ struct amdgpu_doorbell_index {
uint32_t vce_ring6_7;
} uvd_vce;
};
+ uint32_t vpe_ring;
uint32_t first_non_cp;
uint32_t last_non_cp;
uint32_t max_assignment;
@@ -226,10 +227,12 @@ enum AMDGPU_NAVI10_DOORBELL_ASSIGNMENT {
AMDGPU_NAVI10_DOORBELL64_VCNc_d = 0x18E,
AMDGPU_NAVI10_DOORBELL64_VCNe_f = 0x18F,
+ AMDGPU_NAVI10_DOORBELL64_VPE = 0x190,
+
AMDGPU_NAVI10_DOORBELL64_FIRST_NON_CP = AMDGPU_NAVI10_DOORBELL_sDMA_ENGINE0,
- AMDGPU_NAVI10_DOORBELL64_LAST_NON_CP = AMDGPU_NAVI10_DOORBELL64_VCNe_f,
+ AMDGPU_NAVI10_DOORBELL64_LAST_NON_CP = AMDGPU_NAVI10_DOORBELL64_VPE,
- AMDGPU_NAVI10_DOORBELL_MAX_ASSIGNMENT = 0x18F,
+ AMDGPU_NAVI10_DOORBELL_MAX_ASSIGNMENT = AMDGPU_NAVI10_DOORBELL64_VPE,
AMDGPU_NAVI10_DOORBELL_INVALID = 0xFFFF
};
@@ -357,8 +360,9 @@ int amdgpu_doorbell_init(struct amdgpu_device *adev);
void amdgpu_doorbell_fini(struct amdgpu_device *adev);
int amdgpu_doorbell_create_kernel_doorbells(struct amdgpu_device *adev);
uint32_t amdgpu_doorbell_index_on_bar(struct amdgpu_device *adev,
- struct amdgpu_bo *db_bo,
- uint32_t doorbell_index);
+ struct amdgpu_bo *db_bo,
+ uint32_t doorbell_index,
+ uint32_t db_size);
#define RDOORBELL32(index) amdgpu_mm_rdoorbell(adev, (index))
#define WDOORBELL32(index, v) amdgpu_mm_wdoorbell(adev, (index), (v))
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.c
index da4be0bbb446..3f3662e8b871 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.c
@@ -113,20 +113,25 @@ void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v)
*
* @adev: amdgpu_device pointer
* @db_bo: doorbell object's bo
- * @db_index: doorbell relative index in this doorbell object
+ * @doorbell_index: doorbell relative index in this doorbell object
+ * @db_size: doorbell size is in byte
*
* returns doorbell's absolute index in BAR
*/
uint32_t amdgpu_doorbell_index_on_bar(struct amdgpu_device *adev,
- struct amdgpu_bo *db_bo,
- uint32_t doorbell_index)
+ struct amdgpu_bo *db_bo,
+ uint32_t doorbell_index,
+ uint32_t db_size)
{
int db_bo_offset;
db_bo_offset = amdgpu_bo_gpu_offset_no_check(db_bo);
- /* doorbell index is 32 bit but doorbell's size is 64-bit, so *2 */
- return db_bo_offset / sizeof(u32) + doorbell_index * 2;
+ /* doorbell index is 32 bit but doorbell's size can be 32 bit
+ * or 64 bit, so *db_size(in byte)/4 for alignment.
+ */
+ return db_bo_offset / sizeof(u32) + doorbell_index *
+ DIV_ROUND_UP(db_size, 4);
}
/**
@@ -142,6 +147,10 @@ int amdgpu_doorbell_create_kernel_doorbells(struct amdgpu_device *adev)
int r;
int size;
+ /* SI HW does not have doorbells, skip allocation */
+ if (adev->doorbell.num_kernel_doorbells == 0)
+ return 0;
+
/* Reserve first num_kernel_doorbells (page-aligned) for kernel ops */
size = ALIGN(adev->doorbell.num_kernel_doorbells * sizeof(u32), PAGE_SIZE);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 81edf66dbea8..8b33b130ea36 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -113,11 +113,22 @@
* gl1c_cache_size, gl2c_cache_size, mall_size, enabled_rb_pipes_mask_hi
* 3.53.0 - Support for GFX11 CP GFX shadowing
* 3.54.0 - Add AMDGPU_CTX_QUERY2_FLAGS_RESET_IN_PROGRESS support
+ * - 3.55.0 - Add AMDGPU_INFO_GPUVM_FAULT query
+ * - 3.56.0 - Update IB start address and size alignment for decode and encode
*/
#define KMS_DRIVER_MAJOR 3
-#define KMS_DRIVER_MINOR 54
+#define KMS_DRIVER_MINOR 56
#define KMS_DRIVER_PATCHLEVEL 0
+/*
+ * amdgpu.debug module options. Are all disabled by default
+ */
+enum AMDGPU_DEBUG_MASK {
+ AMDGPU_DEBUG_VM = BIT(0),
+ AMDGPU_DEBUG_LARGEBAR = BIT(1),
+ AMDGPU_DEBUG_DISABLE_GPU_SOFT_RECOVERY = BIT(2),
+};
+
unsigned int amdgpu_vram_limit = UINT_MAX;
int amdgpu_vis_vram_limit;
int amdgpu_gart_size = -1; /* auto */
@@ -140,7 +151,6 @@ int amdgpu_vm_size = -1;
int amdgpu_vm_fragment_size = -1;
int amdgpu_vm_block_size = -1;
int amdgpu_vm_fault_stop;
-int amdgpu_vm_debug;
int amdgpu_vm_update_mode = -1;
int amdgpu_exp_hw_support;
int amdgpu_dc = -1;
@@ -194,6 +204,10 @@ int amdgpu_use_xgmi_p2p = 1;
int amdgpu_vcnfw_log;
int amdgpu_sg_display = -1; /* auto */
int amdgpu_user_partt_mode = AMDGPU_AUTO_COMPUTE_PARTITION_MODE;
+int amdgpu_umsch_mm;
+int amdgpu_seamless = -1; /* auto */
+uint amdgpu_debug_mask;
+int amdgpu_agp = -1; /* auto */
static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);
@@ -406,13 +420,6 @@ MODULE_PARM_DESC(vm_fault_stop, "Stop on VM fault (0 = never (default), 1 = prin
module_param_named(vm_fault_stop, amdgpu_vm_fault_stop, int, 0444);
/**
- * DOC: vm_debug (int)
- * Debug VM handling (0 = disabled, 1 = enabled). The default is 0 (Disabled).
- */
-MODULE_PARM_DESC(vm_debug, "Debug VM handling (0 = disabled (default), 1 = enabled)");
-module_param_named(vm_debug, amdgpu_vm_debug, int, 0644);
-
-/**
* DOC: vm_update_mode (int)
* Override VM update mode. VM updated by using CPU (0 = never, 1 = Graphics only, 2 = Compute only, 3 = Both). The default
* is -1 (Only in large BAR(LB) systems Compute VM tables will be updated by CPU, otherwise 0, never).
@@ -744,18 +751,6 @@ MODULE_PARM_DESC(send_sigterm,
"Send sigterm to HSA process on unhandled exception (0 = disable, 1 = enable)");
/**
- * DOC: debug_largebar (int)
- * Set debug_largebar as 1 to enable simulating large-bar capability on non-large bar
- * system. This limits the VRAM size reported to ROCm applications to the visible
- * size, usually 256MB.
- * Default value is 0, diabled.
- */
-int debug_largebar;
-module_param(debug_largebar, int, 0444);
-MODULE_PARM_DESC(debug_largebar,
- "Debug large-bar flag used to simulate large-bar capability on non-large bar machine (0 = disable, 1 = enable)");
-
-/**
* DOC: halt_if_hws_hang (int)
* Halt if HWS hang is detected. Default value, 0, disables the halt on hang.
* Setting 1 enables halt on hang.
@@ -908,6 +903,15 @@ MODULE_PARM_DESC(sg_display, "S/G Display (-1 = auto (default), 0 = disable)");
module_param_named(sg_display, amdgpu_sg_display, int, 0444);
/**
+ * DOC: umsch_mm (int)
+ * Enable Multi Media User Mode Scheduler. This is a HW scheduling engine for VCN and VPE.
+ * (0 = disabled (default), 1 = enabled)
+ */
+MODULE_PARM_DESC(umsch_mm,
+ "Enable Multi Media User Mode Scheduler (0 = disabled (default), 1 = enabled)");
+module_param_named(umsch_mm, amdgpu_umsch_mm, int, 0444);
+
+/**
* DOC: smu_pptable_id (int)
* Used to override pptable id. id = 0 use VBIOS pptable.
* id > 0 use the soft pptable with specicfied id.
@@ -938,6 +942,35 @@ module_param_named(user_partt_mode, amdgpu_user_partt_mode, uint, 0444);
module_param(enforce_isolation, bool, 0444);
MODULE_PARM_DESC(enforce_isolation, "enforce process isolation between graphics and compute . enforce_isolation = on");
+/**
+ * DOC: seamless (int)
+ * Seamless boot will keep the image on the screen during the boot process.
+ */
+MODULE_PARM_DESC(seamless, "Seamless boot (-1 = auto (default), 0 = disable, 1 = enable)");
+module_param_named(seamless, amdgpu_seamless, int, 0444);
+
+/**
+ * DOC: debug_mask (uint)
+ * Debug options for amdgpu, work as a binary mask with the following options:
+ *
+ * - 0x1: Debug VM handling
+ * - 0x2: Enable simulating large-bar capability on non-large bar system. This
+ * limits the VRAM size reported to ROCm applications to the visible
+ * size, usually 256MB.
+ * - 0x4: Disable GPU soft recovery, always do a full reset
+ */
+MODULE_PARM_DESC(debug_mask, "debug options for amdgpu, disabled by default");
+module_param_named(debug_mask, amdgpu_debug_mask, uint, 0444);
+
+/**
+ * DOC: agp (int)
+ * Enable the AGP aperture. This provides an aperture in the GPU's internal
+ * address space for direct access to system memory. Note that these accesses
+ * are non-snooped, so they are only used for access to uncached memory.
+ */
+MODULE_PARM_DESC(agp, "AGP (-1 = auto (default), 0 = disable, 1 = enable)");
+module_param_named(agp, amdgpu_agp, int, 0444);
+
/* These devices are not supported by amdgpu.
* They are supported by the mach64, r128, radeon drivers
*/
@@ -2018,6 +2051,14 @@ static const struct pci_device_id pciidlist[] = {
MODULE_DEVICE_TABLE(pci, pciidlist);
+static const struct amdgpu_asic_type_quirk asic_type_quirks[] = {
+ /* differentiate between P10 and P11 asics with the same DID */
+ {0x67FF, 0xE3, CHIP_POLARIS10},
+ {0x67FF, 0xE7, CHIP_POLARIS10},
+ {0x67FF, 0xF3, CHIP_POLARIS10},
+ {0x67FF, 0xF7, CHIP_POLARIS10},
+};
+
static const struct drm_driver amdgpu_kms_driver;
static void amdgpu_get_secondary_funcs(struct amdgpu_device *adev)
@@ -2042,6 +2083,40 @@ static void amdgpu_get_secondary_funcs(struct amdgpu_device *adev)
}
}
+static void amdgpu_init_debug_options(struct amdgpu_device *adev)
+{
+ if (amdgpu_debug_mask & AMDGPU_DEBUG_VM) {
+ pr_info("debug: VM handling debug enabled\n");
+ adev->debug_vm = true;
+ }
+
+ if (amdgpu_debug_mask & AMDGPU_DEBUG_LARGEBAR) {
+ pr_info("debug: enabled simulating large-bar capability on non-large bar system\n");
+ adev->debug_largebar = true;
+ }
+
+ if (amdgpu_debug_mask & AMDGPU_DEBUG_DISABLE_GPU_SOFT_RECOVERY) {
+ pr_info("debug: soft reset for GPU recovery disabled\n");
+ adev->debug_disable_soft_recovery = true;
+ }
+}
+
+static unsigned long amdgpu_fix_asic_type(struct pci_dev *pdev, unsigned long flags)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(asic_type_quirks); i++) {
+ if (pdev->device == asic_type_quirks[i].device &&
+ pdev->revision == asic_type_quirks[i].revision) {
+ flags &= ~AMD_ASIC_MASK;
+ flags |= asic_type_quirks[i].type;
+ break;
+ }
+ }
+
+ return flags;
+}
+
static int amdgpu_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -2069,15 +2144,8 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
"See modparam exp_hw_support\n");
return -ENODEV;
}
- /* differentiate between P10 and P11 asics with the same DID */
- if (pdev->device == 0x67FF &&
- (pdev->revision == 0xE3 ||
- pdev->revision == 0xE7 ||
- pdev->revision == 0xF3 ||
- pdev->revision == 0xF7)) {
- flags &= ~AMD_ASIC_MASK;
- flags |= CHIP_POLARIS10;
- }
+
+ flags = amdgpu_fix_asic_type(pdev, flags);
/* Due to hardware bugs, S/G Display on raven requires a 1:1 IOMMU mapping,
* however, SME requires an indirect IOMMU mapping because the encryption
@@ -2195,6 +2263,8 @@ retry_init:
pm_runtime_mark_last_busy(ddev->dev);
pm_runtime_put_autosuspend(ddev->dev);
+ pci_wake_from_d3(pdev, TRUE);
+
/*
* For runpm implemented via BACO, PMFW will handle the
* timing for BACO in and out:
@@ -2220,6 +2290,8 @@ retry_init:
amdgpu_get_secondary_funcs(adev);
}
+ amdgpu_init_debug_options(adev);
+
return 0;
err_pci:
@@ -2241,7 +2313,7 @@ amdgpu_pci_remove(struct pci_dev *pdev)
pm_runtime_forbid(dev->dev);
}
- if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2) &&
+ if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 2) &&
!amdgpu_sriov_vf(adev)) {
bool need_to_reset_gpu = false;
@@ -2384,8 +2456,9 @@ static int amdgpu_pmops_prepare(struct device *dev)
/* Return a positive number here so
* DPM_FLAG_SMART_SUSPEND works properly
*/
- if (amdgpu_device_supports_boco(drm_dev))
- return pm_runtime_suspended(dev);
+ if (amdgpu_device_supports_boco(drm_dev) &&
+ pm_runtime_suspended(dev))
+ return 1;
/* if we will not support s3 or s2i for the device
* then skip suspend
@@ -2394,7 +2467,7 @@ static int amdgpu_pmops_prepare(struct device *dev)
!amdgpu_acpi_is_s3_active(adev))
return 1;
- return 0;
+ return amdgpu_device_prepare(drm_dev);
}
static void amdgpu_pmops_complete(struct device *dev)
@@ -2594,6 +2667,9 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
if (amdgpu_device_supports_boco(drm_dev))
adev->mp1_state = PP_MP1_STATE_UNLOAD;
+ ret = amdgpu_device_prepare(drm_dev);
+ if (ret)
+ return ret;
ret = amdgpu_device_suspend(drm_dev, false);
if (ret) {
adev->in_runpm = false;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c
index 6038b5021b27..5706b282a0c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c
@@ -51,25 +51,20 @@ static const char *amdgpu_ip_name[AMDGPU_HW_IP_NUM] = {
[AMDGPU_HW_IP_VCN_DEC] = "dec",
[AMDGPU_HW_IP_VCN_ENC] = "enc",
[AMDGPU_HW_IP_VCN_JPEG] = "jpeg",
+ [AMDGPU_HW_IP_VPE] = "vpe",
};
void amdgpu_show_fdinfo(struct drm_printer *p, struct drm_file *file)
{
- struct amdgpu_device *adev = drm_to_adev(file->minor->dev);
struct amdgpu_fpriv *fpriv = file->driver_priv;
struct amdgpu_vm *vm = &fpriv->vm;
struct amdgpu_mem_stats stats;
ktime_t usage[AMDGPU_HW_IP_NUM];
- uint32_t bus, dev, fn, domain;
unsigned int hw_ip;
int ret;
memset(&stats, 0, sizeof(stats));
- bus = adev->pdev->bus->number;
- domain = pci_domain_nr(adev->pdev->bus);
- dev = PCI_SLOT(adev->pdev->devfn);
- fn = PCI_FUNC(adev->pdev->devfn);
ret = amdgpu_bo_reserve(vm->root.bo, false);
if (ret)
@@ -87,9 +82,6 @@ void amdgpu_show_fdinfo(struct drm_printer *p, struct drm_file *file)
*/
drm_printf(p, "pasid:\t%u\n", fpriv->vm.pasid);
- drm_printf(p, "drm-driver:\t%s\n", file->minor->dev->driver->name);
- drm_printf(p, "drm-pdev:\t%04x:%02x:%02x.%d\n", domain, bus, dev, fn);
- drm_printf(p, "drm-client-id:\t%llu\n", vm->immediate.fence_context);
drm_printf(p, "drm-memory-vram:\t%llu KiB\n", stats.vram/1024UL);
drm_printf(p, "drm-memory-gtt: \t%llu KiB\n", stats.gtt/1024UL);
drm_printf(p, "drm-memory-cpu: \t%llu KiB\n", stats.cpu/1024UL);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index 7537f5aa76f0..dc230212746a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -570,7 +570,8 @@ static bool amdgpu_fence_need_ring_interrupt_restore(struct amdgpu_ring *ring)
switch (ring->funcs->type) {
case AMDGPU_RING_TYPE_SDMA:
/* SDMA 5.x+ is part of GFX power domain so it's covered by GFXOFF */
- if (adev->ip_versions[SDMA0_HWIP][0] >= IP_VERSION(5, 0, 0))
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) >=
+ IP_VERSION(5, 0, 0))
is_gfx_power_domain = true;
break;
case AMDGPU_RING_TYPE_GFX:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
index 7cd0dfaeee20..a08c148b13f9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
@@ -42,8 +42,9 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr)
/* The i2c access is blocked on VF
* TODO: Need other way to get the info
+ * Also, FRU not valid for APU devices.
*/
- if (amdgpu_sriov_vf(adev))
+ if (amdgpu_sriov_vf(adev) || (adev->flags & AMD_IS_APU))
return false;
/* The default I2C EEPROM address of the FRU.
@@ -57,27 +58,26 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr)
* for ease/speed/readability. For now, 2 string comparisons are
* reasonable and not too expensive
*/
- switch (adev->asic_type) {
- case CHIP_VEGA20:
- /* D161 and D163 are the VG20 server SKUs */
- if (strnstr(atom_ctx->vbios_pn, "D161",
- sizeof(atom_ctx->vbios_pn)) ||
- strnstr(atom_ctx->vbios_pn, "D163",
- sizeof(atom_ctx->vbios_pn))) {
- if (fru_addr)
- *fru_addr = FRU_EEPROM_MADDR_6;
- return true;
- } else {
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
+ case IP_VERSION(11, 0, 2):
+ switch (adev->asic_type) {
+ case CHIP_VEGA20:
+ /* D161 and D163 are the VG20 server SKUs */
+ if (strnstr(atom_ctx->vbios_pn, "D161",
+ sizeof(atom_ctx->vbios_pn)) ||
+ strnstr(atom_ctx->vbios_pn, "D163",
+ sizeof(atom_ctx->vbios_pn))) {
+ if (fru_addr)
+ *fru_addr = FRU_EEPROM_MADDR_6;
+ return true;
+ } else {
+ return false;
+ }
+ case CHIP_ARCTURUS:
+ default:
return false;
}
- case CHIP_ALDEBARAN:
- /* All Aldebaran SKUs have an FRU */
- if (!strnstr(atom_ctx->vbios_pn, "D673",
- sizeof(atom_ctx->vbios_pn)))
- if (fru_addr)
- *fru_addr = FRU_EEPROM_MADDR_6;
- return true;
- case CHIP_SIENNA_CICHLID:
+ case IP_VERSION(11, 0, 7):
if (strnstr(atom_ctx->vbios_pn, "D603",
sizeof(atom_ctx->vbios_pn))) {
if (strnstr(atom_ctx->vbios_pn, "D603GLXE",
@@ -92,6 +92,17 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr)
} else {
return false;
}
+ case IP_VERSION(13, 0, 2):
+ /* All Aldebaran SKUs have an FRU */
+ if (!strnstr(atom_ctx->vbios_pn, "D673",
+ sizeof(atom_ctx->vbios_pn)))
+ if (fru_addr)
+ *fru_addr = FRU_EEPROM_MADDR_6;
+ return true;
+ case IP_VERSION(13, 0, 6):
+ if (fru_addr)
+ *fru_addr = FRU_EEPROM_MADDR_8;
+ return true;
default:
return false;
}
@@ -99,6 +110,7 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr)
int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
{
+ struct amdgpu_fru_info *fru_info;
unsigned char buf[8], *pia;
u32 addr, fru_addr;
int size, len;
@@ -107,6 +119,19 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
if (!is_fru_eeprom_supported(adev, &fru_addr))
return 0;
+ if (!adev->fru_info) {
+ adev->fru_info = kzalloc(sizeof(*adev->fru_info), GFP_KERNEL);
+ if (!adev->fru_info)
+ return -ENOMEM;
+ }
+
+ fru_info = adev->fru_info;
+ /* For Arcturus-and-later, default value of serial_number is unique_id
+ * so convert it to a 16-digit HEX string for convenience and
+ * backwards-compatibility.
+ */
+ sprintf(fru_info->serial, "%llx", adev->unique_id);
+
/* If algo exists, it means that the i2c_adapter's initialized */
if (!adev->pm.fru_eeprom_i2c_bus || !adev->pm.fru_eeprom_i2c_bus->algo) {
DRM_WARN("Cannot access FRU, EEPROM accessor not initialized");
@@ -176,27 +201,33 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
/* Now extract useful information from the PIA.
*
- * Skip the Manufacturer Name at [3] and go directly to
- * the Product Name field.
+ * Read Manufacturer Name field whose length is [3].
*/
- addr = 3 + 1 + (pia[3] & 0x3F);
+ addr = 3;
if (addr + 1 >= len)
goto Out;
- memcpy(adev->product_name, pia + addr + 1,
- min_t(size_t,
- sizeof(adev->product_name),
+ memcpy(fru_info->manufacturer_name, pia + addr + 1,
+ min_t(size_t, sizeof(fru_info->manufacturer_name),
pia[addr] & 0x3F));
- adev->product_name[sizeof(adev->product_name) - 1] = '\0';
+ fru_info->manufacturer_name[sizeof(fru_info->manufacturer_name) - 1] =
+ '\0';
+
+ /* Read Product Name field. */
+ addr += 1 + (pia[addr] & 0x3F);
+ if (addr + 1 >= len)
+ goto Out;
+ memcpy(fru_info->product_name, pia + addr + 1,
+ min_t(size_t, sizeof(fru_info->product_name), pia[addr] & 0x3F));
+ fru_info->product_name[sizeof(fru_info->product_name) - 1] = '\0';
/* Go to the Product Part/Model Number field. */
addr += 1 + (pia[addr] & 0x3F);
if (addr + 1 >= len)
goto Out;
- memcpy(adev->product_number, pia + addr + 1,
- min_t(size_t,
- sizeof(adev->product_number),
+ memcpy(fru_info->product_number, pia + addr + 1,
+ min_t(size_t, sizeof(fru_info->product_number),
pia[addr] & 0x3F));
- adev->product_number[sizeof(adev->product_number) - 1] = '\0';
+ fru_info->product_number[sizeof(fru_info->product_number) - 1] = '\0';
/* Go to the Product Version field. */
addr += 1 + (pia[addr] & 0x3F);
@@ -205,10 +236,21 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
addr += 1 + (pia[addr] & 0x3F);
if (addr + 1 >= len)
goto Out;
- memcpy(adev->serial, pia + addr + 1, min_t(size_t,
- sizeof(adev->serial),
- pia[addr] & 0x3F));
- adev->serial[sizeof(adev->serial) - 1] = '\0';
+ memcpy(fru_info->serial, pia + addr + 1,
+ min_t(size_t, sizeof(fru_info->serial), pia[addr] & 0x3F));
+ fru_info->serial[sizeof(fru_info->serial) - 1] = '\0';
+
+ /* Asset Tag field */
+ addr += 1 + (pia[addr] & 0x3F);
+
+ /* FRU File Id field. This could be 'null'. */
+ addr += 1 + (pia[addr] & 0x3F);
+ if ((addr + 1 >= len) || !(pia[addr] & 0x3F))
+ goto Out;
+ memcpy(fru_info->fru_id, pia + addr + 1,
+ min_t(size_t, sizeof(fru_info->fru_id), pia[addr] & 0x3F));
+ fru_info->fru_id[sizeof(fru_info->fru_id) - 1] = '\0';
+
Out:
kfree(pia);
return 0;
@@ -231,7 +273,7 @@ static ssize_t amdgpu_fru_product_name_show(struct device *dev,
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
- return sysfs_emit(buf, "%s\n", adev->product_name);
+ return sysfs_emit(buf, "%s\n", adev->fru_info->product_name);
}
static DEVICE_ATTR(product_name, 0444, amdgpu_fru_product_name_show, NULL);
@@ -253,7 +295,7 @@ static ssize_t amdgpu_fru_product_number_show(struct device *dev,
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
- return sysfs_emit(buf, "%s\n", adev->product_number);
+ return sysfs_emit(buf, "%s\n", adev->fru_info->product_number);
}
static DEVICE_ATTR(product_number, 0444, amdgpu_fru_product_number_show, NULL);
@@ -275,21 +317,65 @@ static ssize_t amdgpu_fru_serial_number_show(struct device *dev,
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
- return sysfs_emit(buf, "%s\n", adev->serial);
+ return sysfs_emit(buf, "%s\n", adev->fru_info->serial);
}
static DEVICE_ATTR(serial_number, 0444, amdgpu_fru_serial_number_show, NULL);
+/**
+ * DOC: fru_id
+ *
+ * The amdgpu driver provides a sysfs API for reporting FRU File Id
+ * for the device.
+ * The file fru_id is used for this and returns the File Id value
+ * as returned from the FRU.
+ * NOTE: This is only available for certain server cards
+ */
+
+static ssize_t amdgpu_fru_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ return sysfs_emit(buf, "%s\n", adev->fru_info->fru_id);
+}
+
+static DEVICE_ATTR(fru_id, 0444, amdgpu_fru_id_show, NULL);
+
+/**
+ * DOC: manufacturer
+ *
+ * The amdgpu driver provides a sysfs API for reporting manufacturer name from
+ * FRU information.
+ * The file manufacturer returns the value as returned from the FRU.
+ * NOTE: This is only available for certain server cards
+ */
+
+static ssize_t amdgpu_fru_manufacturer_name_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ return sysfs_emit(buf, "%s\n", adev->fru_info->manufacturer_name);
+}
+
+static DEVICE_ATTR(manufacturer, 0444, amdgpu_fru_manufacturer_name_show, NULL);
+
static const struct attribute *amdgpu_fru_attributes[] = {
&dev_attr_product_name.attr,
&dev_attr_product_number.attr,
&dev_attr_serial_number.attr,
+ &dev_attr_fru_id.attr,
+ &dev_attr_manufacturer.attr,
NULL
};
int amdgpu_fru_sysfs_init(struct amdgpu_device *adev)
{
- if (!is_fru_eeprom_supported(adev, NULL))
+ if (!is_fru_eeprom_supported(adev, NULL) || !adev->fru_info)
return 0;
return sysfs_create_files(&adev->dev->kobj, amdgpu_fru_attributes);
@@ -297,7 +383,7 @@ int amdgpu_fru_sysfs_init(struct amdgpu_device *adev)
void amdgpu_fru_sysfs_fini(struct amdgpu_device *adev)
{
- if (!is_fru_eeprom_supported(adev, NULL))
+ if (!is_fru_eeprom_supported(adev, NULL) || !adev->fru_info)
return;
sysfs_remove_files(&adev->dev->kobj, amdgpu_fru_attributes);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.h
index c817db17cfa7..bc58dca18035 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.h
@@ -24,6 +24,17 @@
#ifndef __AMDGPU_FRU_EEPROM_H__
#define __AMDGPU_FRU_EEPROM_H__
+#define AMDGPU_PRODUCT_NAME_LEN 64
+
+/* FRU product information */
+struct amdgpu_fru_info {
+ char product_number[20];
+ char product_name[AMDGPU_PRODUCT_NAME_LEN];
+ char serial[20];
+ char manufacturer_name[32];
+ char fru_id[32];
+};
+
int amdgpu_fru_get_product_info(struct amdgpu_device *adev);
int amdgpu_fru_sysfs_init(struct amdgpu_device *adev);
void amdgpu_fru_sysfs_fini(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index ca4d2d430e28..84beeaa4d21c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -791,7 +791,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
default:
break;
}
- if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) && !amdgpu_vm_debug)
+ if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) && !adev->debug_vm)
amdgpu_gem_va_update_vm(adev, &fpriv->vm, bo_va,
args->operation);
@@ -962,6 +962,7 @@ static int amdgpu_debugfs_gem_info_show(struct seq_file *m, void *unused)
list_for_each_entry(file, &dev->filelist, lhead) {
struct task_struct *task;
struct drm_gem_object *gobj;
+ struct pid *pid;
int id;
/*
@@ -971,8 +972,9 @@ static int amdgpu_debugfs_gem_info_show(struct seq_file *m, void *unused)
* Therefore, we need to protect this ->comm access using RCU.
*/
rcu_read_lock();
- task = pid_task(file->pid, PIDTYPE_TGID);
- seq_printf(m, "pid %8d command %s:\n", pid_nr(file->pid),
+ pid = rcu_dereference(file->pid);
+ task = pid_task(pid, PIDTYPE_TGID);
+ seq_printf(m, "pid %8d command %s:\n", pid_nr(pid),
task ? task->comm : "<unknown>");
rcu_read_unlock();
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index 2382921710ec..b9674c57c436 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -29,6 +29,7 @@
#include "amdgpu_rlc.h"
#include "amdgpu_ras.h"
#include "amdgpu_xcp.h"
+#include "amdgpu_xgmi.h"
/* delay 0.1 second to enable gfx off feature */
#define GFX_OFF_DELAY_ENABLE msecs_to_jiffies(100)
@@ -158,7 +159,7 @@ static bool amdgpu_gfx_is_compute_multipipe_capable(struct amdgpu_device *adev)
return amdgpu_compute_multipipe == 1;
}
- if (adev->ip_versions[GC_HWIP][0] > IP_VERSION(9, 0, 0))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) > IP_VERSION(9, 0, 0))
return true;
/* FIXME: spreading the queues across pipes causes perf regressions
@@ -384,9 +385,11 @@ int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
struct amdgpu_ring *ring = &kiq->ring;
u32 domain = AMDGPU_GEM_DOMAIN_GTT;
+#if !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
/* Only enable on gfx10 and 11 for now to avoid changing behavior on older chips */
- if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 0, 0))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 0, 0))
domain |= AMDGPU_GEM_DOMAIN_VRAM;
+#endif
/* create MQD for KIQ */
if (!adev->enable_mes_kiq && !ring->mqd_obj) {
@@ -501,6 +504,9 @@ int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id)
{
struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
struct amdgpu_ring *kiq_ring = &kiq->ring;
+ struct amdgpu_hive_info *hive;
+ struct amdgpu_ras *ras;
+ int hive_ras_recovery = 0;
int i, r = 0;
int j;
@@ -521,6 +527,23 @@ int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id)
RESET_QUEUES, 0, 0);
}
+ /**
+ * This is workaround: only skip kiq_ring test
+ * during ras recovery in suspend stage for gfx9.4.3
+ */
+ hive = amdgpu_get_xgmi_hive(adev);
+ if (hive) {
+ hive_ras_recovery = atomic_read(&hive->ras_recovery);
+ amdgpu_put_xgmi_hive(hive);
+ }
+
+ ras = amdgpu_ras_get_context(adev);
+ if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3)) &&
+ ras && (atomic_read(&ras->in_recovery) || hive_ras_recovery)) {
+ spin_unlock(&kiq->ring_lock);
+ return 0;
+ }
+
if (kiq_ring->sched.ready && !adev->job_hang)
r = amdgpu_ring_test_helper(kiq_ring);
spin_unlock(&kiq->ring_lock);
@@ -908,12 +931,12 @@ void amdgpu_gfx_ras_error_func(struct amdgpu_device *adev,
func(adev, ras_error_status, i);
}
-uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg)
+uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg, uint32_t xcc_id)
{
signed long r, cnt = 0;
unsigned long flags;
uint32_t seq, reg_val_offs = 0, value = 0;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
struct amdgpu_ring *ring = &kiq->ring;
if (amdgpu_device_skip_hw_access(adev))
@@ -976,12 +999,12 @@ failed_kiq_read:
return ~0;
}
-void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v)
+void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t xcc_id)
{
signed long r, cnt = 0;
unsigned long flags;
uint32_t seq;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
struct amdgpu_ring *ring = &kiq->ring;
BUG_ON(!ring->funcs->emit_wreg);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index 0ca95c4d4bfb..f23bafec71c5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -43,10 +43,10 @@
#define AMDGPU_GFX_LBPW_DISABLED_MODE 0x00000008L
#define AMDGPU_MAX_GC_INSTANCES 8
-#define KGD_MAX_QUEUES 128
+#define AMDGPU_MAX_QUEUES 128
-#define AMDGPU_MAX_GFX_QUEUES KGD_MAX_QUEUES
-#define AMDGPU_MAX_COMPUTE_QUEUES KGD_MAX_QUEUES
+#define AMDGPU_MAX_GFX_QUEUES AMDGPU_MAX_QUEUES
+#define AMDGPU_MAX_COMPUTE_QUEUES AMDGPU_MAX_QUEUES
enum amdgpu_gfx_pipe_priority {
AMDGPU_GFX_PIPE_PRIO_NORMAL = AMDGPU_RING_PRIO_1,
@@ -69,11 +69,6 @@ enum amdgpu_gfx_partition {
#define NUM_XCC(x) hweight16(x)
-enum amdgpu_pkg_type {
- AMDGPU_PKG_TYPE_APU = 2,
- AMDGPU_PKG_TYPE_UNKNOWN,
-};
-
enum amdgpu_gfx_ras_mem_id_type {
AMDGPU_GFX_CP_MEM = 0,
AMDGPU_GFX_GCEA_MEM,
@@ -526,8 +521,8 @@ int amdgpu_gfx_process_ras_data_cb(struct amdgpu_device *adev,
int amdgpu_gfx_cp_ecc_error_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry);
-uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg);
-void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v);
+uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg, uint32_t xcc_id);
+void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t xcc_id);
int amdgpu_gfx_get_num_kcq(struct amdgpu_device *adev);
void amdgpu_gfx_cp_init_microcode(struct amdgpu_device *adev, uint32_t ucode_id);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index d78bd9732543..d2f273d77e59 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -32,6 +32,7 @@
#include "amdgpu.h"
#include "amdgpu_gmc.h"
#include "amdgpu_ras.h"
+#include "amdgpu_reset.h"
#include "amdgpu_xgmi.h"
#include <drm/drm_drv.h>
@@ -180,6 +181,9 @@ uint64_t amdgpu_gmc_agp_addr(struct ttm_buffer_object *bo)
{
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
+ if (!bo->ttm)
+ return AMDGPU_BO_INVALID_OFFSET;
+
if (bo->ttm->num_pages != 1 || bo->ttm->caching == ttm_cached)
return AMDGPU_BO_INVALID_OFFSET;
@@ -263,12 +267,14 @@ void amdgpu_gmc_sysvm_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc
*
* @adev: amdgpu device structure holding all necessary information
* @mc: memory controller structure holding memory information
+ * @gart_placement: GART placement policy with respect to VRAM
*
* Function will place try to place GART before or after VRAM.
* If GART size is bigger than space left then we ajust GART size.
* Thus function will never fails.
*/
-void amdgpu_gmc_gart_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc)
+void amdgpu_gmc_gart_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc,
+ enum amdgpu_gart_placement gart_placement)
{
const uint64_t four_gb = 0x100000000ULL;
u64 size_af, size_bf;
@@ -286,11 +292,22 @@ void amdgpu_gmc_gart_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc)
mc->gart_size = max(size_bf, size_af);
}
- if ((size_bf >= mc->gart_size && size_bf < size_af) ||
- (size_af < mc->gart_size))
- mc->gart_start = 0;
- else
+ switch (gart_placement) {
+ case AMDGPU_GART_PLACEMENT_HIGH:
mc->gart_start = max_mc_address - mc->gart_size + 1;
+ break;
+ case AMDGPU_GART_PLACEMENT_LOW:
+ mc->gart_start = 0;
+ break;
+ case AMDGPU_GART_PLACEMENT_BEST_FIT:
+ default:
+ if ((size_bf >= mc->gart_size && size_bf < size_af) ||
+ (size_af < mc->gart_size))
+ mc->gart_start = 0;
+ else
+ mc->gart_start = max_mc_address - mc->gart_size + 1;
+ break;
+ }
mc->gart_start &= ~(four_gb - 1);
mc->gart_end = mc->gart_start + mc->gart_size - 1;
@@ -315,14 +332,6 @@ void amdgpu_gmc_agp_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc)
const uint64_t sixteen_gb_mask = ~(sixteen_gb - 1);
u64 size_af, size_bf;
- if (amdgpu_sriov_vf(adev)) {
- mc->agp_start = 0xffffffffffff;
- mc->agp_end = 0x0;
- mc->agp_size = 0;
-
- return;
- }
-
if (mc->fb_start > mc->gart_start) {
size_bf = (mc->fb_start & sixteen_gb_mask) -
ALIGN(mc->gart_end + 1, sixteen_gb);
@@ -347,6 +356,25 @@ void amdgpu_gmc_agp_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc)
}
/**
+ * amdgpu_gmc_set_agp_default - Set the default AGP aperture value.
+ * @adev: amdgpu device structure holding all necessary information
+ * @mc: memory controller structure holding memory information
+ *
+ * To disable the AGP aperture, you need to set the start to a larger
+ * value than the end. This function sets the default value which
+ * can then be overridden using amdgpu_gmc_agp_location() if you want
+ * to enable the AGP aperture on a specific chip.
+ *
+ */
+void amdgpu_gmc_set_agp_default(struct amdgpu_device *adev,
+ struct amdgpu_gmc *mc)
+{
+ mc->agp_start = 0xffffffffffff;
+ mc->agp_end = 0;
+ mc->agp_size = 0;
+}
+
+/**
* amdgpu_gmc_fault_key - get hask key from vm fault address and pasid
*
* @addr: 48 bit physical address, page aligned (36 significant bits)
@@ -452,7 +480,10 @@ void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr,
uint32_t hash;
uint64_t tmp;
- ih = adev->irq.retry_cam_enabled ? &adev->irq.ih_soft : &adev->irq.ih1;
+ if (adev->irq.retry_cam_enabled)
+ return;
+
+ ih = &adev->irq.ih1;
/* Get the WPTR of the last entry in IH ring */
last_wptr = amdgpu_ih_get_wptr(adev, ih);
/* Order wptr with ring data. */
@@ -549,13 +580,17 @@ int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev)
/* reserve engine 5 for firmware */
if (adev->enable_mes)
vm_inv_engs[i] &= ~(1 << 5);
+ /* reserve mmhub engine 3 for firmware */
+ if (adev->enable_umsch_mm)
+ vm_inv_engs[i] &= ~(1 << 3);
}
for (i = 0; i < adev->num_rings; ++i) {
ring = adev->rings[i];
vmhub = ring->vm_hub;
- if (ring == &adev->mes.ring)
+ if (ring == &adev->mes.ring ||
+ ring == &adev->umsch_mm.ring)
continue;
inv_eng = ffs(vm_inv_engs[vmhub]);
@@ -575,6 +610,142 @@ int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev)
return 0;
}
+void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
+ uint32_t vmhub, uint32_t flush_type)
+{
+ struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
+ struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
+ struct dma_fence *fence;
+ struct amdgpu_job *job;
+ int r;
+
+ if (!hub->sdma_invalidation_workaround || vmid ||
+ !adev->mman.buffer_funcs_enabled ||
+ !adev->ib_pool_ready || amdgpu_in_reset(adev) ||
+ !ring->sched.ready) {
+
+ /*
+ * A GPU reset should flush all TLBs anyway, so no need to do
+ * this while one is ongoing.
+ */
+ if (!down_read_trylock(&adev->reset_domain->sem))
+ return;
+
+ if (adev->gmc.flush_tlb_needs_extra_type_2)
+ adev->gmc.gmc_funcs->flush_gpu_tlb(adev, vmid,
+ vmhub, 2);
+
+ if (adev->gmc.flush_tlb_needs_extra_type_0 && flush_type == 2)
+ adev->gmc.gmc_funcs->flush_gpu_tlb(adev, vmid,
+ vmhub, 0);
+
+ adev->gmc.gmc_funcs->flush_gpu_tlb(adev, vmid, vmhub,
+ flush_type);
+ up_read(&adev->reset_domain->sem);
+ return;
+ }
+
+ /* The SDMA on Navi 1x has a bug which can theoretically result in memory
+ * corruption if an invalidation happens at the same time as an VA
+ * translation. Avoid this by doing the invalidation from the SDMA
+ * itself at least for GART.
+ */
+ mutex_lock(&adev->mman.gtt_window_lock);
+ r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.high_pr,
+ AMDGPU_FENCE_OWNER_UNDEFINED,
+ 16 * 4, AMDGPU_IB_POOL_IMMEDIATE,
+ &job);
+ if (r)
+ goto error_alloc;
+
+ job->vm_pd_addr = amdgpu_gmc_pd_addr(adev->gart.bo);
+ job->vm_needs_flush = true;
+ job->ibs->ptr[job->ibs->length_dw++] = ring->funcs->nop;
+ amdgpu_ring_pad_ib(ring, &job->ibs[0]);
+ fence = amdgpu_job_submit(job);
+ mutex_unlock(&adev->mman.gtt_window_lock);
+
+ dma_fence_wait(fence, false);
+ dma_fence_put(fence);
+
+ return;
+
+error_alloc:
+ mutex_unlock(&adev->mman.gtt_window_lock);
+ dev_err(adev->dev, "Error flushing GPU TLB using the SDMA (%d)!\n", r);
+}
+
+int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
+ uint32_t flush_type, bool all_hub,
+ uint32_t inst)
+{
+ u32 usec_timeout = amdgpu_sriov_vf(adev) ? SRIOV_USEC_TIMEOUT :
+ adev->usec_timeout;
+ struct amdgpu_ring *ring = &adev->gfx.kiq[inst].ring;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[inst];
+ unsigned int ndw;
+ signed long r;
+ uint32_t seq;
+
+ if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready ||
+ !down_read_trylock(&adev->reset_domain->sem)) {
+
+ if (adev->gmc.flush_tlb_needs_extra_type_2)
+ adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
+ 2, all_hub,
+ inst);
+
+ if (adev->gmc.flush_tlb_needs_extra_type_0 && flush_type == 2)
+ adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
+ 0, all_hub,
+ inst);
+
+ adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
+ flush_type, all_hub,
+ inst);
+ return 0;
+ }
+
+ /* 2 dwords flush + 8 dwords fence */
+ ndw = kiq->pmf->invalidate_tlbs_size + 8;
+
+ if (adev->gmc.flush_tlb_needs_extra_type_2)
+ ndw += kiq->pmf->invalidate_tlbs_size;
+
+ if (adev->gmc.flush_tlb_needs_extra_type_0)
+ ndw += kiq->pmf->invalidate_tlbs_size;
+
+ spin_lock(&adev->gfx.kiq[inst].ring_lock);
+ amdgpu_ring_alloc(ring, ndw);
+ if (adev->gmc.flush_tlb_needs_extra_type_2)
+ kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 2, all_hub);
+
+ if (flush_type == 2 && adev->gmc.flush_tlb_needs_extra_type_0)
+ kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 0, all_hub);
+
+ kiq->pmf->kiq_invalidate_tlbs(ring, pasid, flush_type, all_hub);
+ r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
+ if (r) {
+ amdgpu_ring_undo(ring);
+ spin_unlock(&adev->gfx.kiq[inst].ring_lock);
+ goto error_unlock_reset;
+ }
+
+ amdgpu_ring_commit(ring);
+ spin_unlock(&adev->gfx.kiq[inst].ring_lock);
+ r = amdgpu_fence_wait_polling(ring, seq, usec_timeout);
+ if (r < 1) {
+ dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
+ r = -ETIME;
+ goto error_unlock_reset;
+ }
+ r = 0;
+
+error_unlock_reset:
+ up_read(&adev->reset_domain->sem);
+ return r;
+}
+
/**
* amdgpu_gmc_tmz_set -- check and set if a device supports TMZ
* @adev: amdgpu_device pointer
@@ -584,7 +755,7 @@ int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev)
*/
void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
/* RAVEN */
case IP_VERSION(9, 2, 2):
case IP_VERSION(9, 1, 0):
@@ -618,6 +789,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
/* YELLOW_CARP*/
case IP_VERSION(10, 3, 3):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
/* Don't enable it by default yet.
*/
if (amdgpu_tmz < 1) {
@@ -648,7 +820,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
void amdgpu_gmc_noretry_set(struct amdgpu_device *adev)
{
struct amdgpu_gmc *gmc = &adev->gmc;
- uint32_t gc_ver = adev->ip_versions[GC_HWIP][0];
+ uint32_t gc_ver = amdgpu_ip_version(adev, GC_HWIP, 0);
bool noretry_default = (gc_ver == IP_VERSION(9, 0, 1) ||
gc_ver == IP_VERSION(9, 3, 0) ||
gc_ver == IP_VERSION(9, 4, 0) ||
@@ -657,7 +829,10 @@ void amdgpu_gmc_noretry_set(struct amdgpu_device *adev)
gc_ver == IP_VERSION(9, 4, 3) ||
gc_ver >= IP_VERSION(10, 3, 0));
- gmc->noretry = (amdgpu_noretry == -1) ? noretry_default : amdgpu_noretry;
+ if (!amdgpu_sriov_xnack_support(adev))
+ gmc->noretry = 1;
+ else
+ gmc->noretry = (amdgpu_noretry == -1) ? noretry_default : amdgpu_noretry;
}
void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type,
@@ -721,12 +896,6 @@ void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev)
case CHIP_RENOIR:
adev->mman.keep_stolen_vga_memory = true;
break;
- case CHIP_YELLOW_CARP:
- if (amdgpu_discovery == 0) {
- adev->mman.stolen_reserved_offset = 0x1ffb0000;
- adev->mman.stolen_reserved_size = 64 * PAGE_SIZE;
- }
- break;
default:
adev->mman.keep_stolen_vga_memory = false;
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
index fdc25cd559b6..e699d1ca8deb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
@@ -117,6 +117,8 @@ struct amdgpu_vmhub {
uint32_t vm_contexts_disable;
+ bool sdma_invalidation_workaround;
+
const struct amdgpu_vmhub_funcs *vmhub_funcs;
};
@@ -128,9 +130,9 @@ struct amdgpu_gmc_funcs {
void (*flush_gpu_tlb)(struct amdgpu_device *adev, uint32_t vmid,
uint32_t vmhub, uint32_t flush_type);
/* flush the vm tlb via pasid */
- int (*flush_gpu_tlb_pasid)(struct amdgpu_device *adev, uint16_t pasid,
- uint32_t flush_type, bool all_hub,
- uint32_t inst);
+ void (*flush_gpu_tlb_pasid)(struct amdgpu_device *adev, uint16_t pasid,
+ uint32_t flush_type, bool all_hub,
+ uint32_t inst);
/* flush the vm tlb via ring */
uint64_t (*emit_flush_gpu_tlb)(struct amdgpu_ring *ring, unsigned vmid,
uint64_t pd_addr);
@@ -197,6 +199,12 @@ struct amdgpu_mem_partition_info {
#define INVALID_PFN -1
+enum amdgpu_gart_placement {
+ AMDGPU_GART_PLACEMENT_BEST_FIT = 0,
+ AMDGPU_GART_PLACEMENT_HIGH,
+ AMDGPU_GART_PLACEMENT_LOW,
+};
+
struct amdgpu_gmc {
/* FB's physical address in MMIO space (for CPU to
* map FB). This is different compared to the agp/
@@ -333,12 +341,12 @@ struct amdgpu_gmc {
u64 MC_VM_MX_L1_TLB_CNTL;
u64 noretry_flags;
+
+ bool flush_tlb_needs_extra_type_0;
+ bool flush_tlb_needs_extra_type_2;
+ bool flush_pasid_uses_kiq;
};
-#define amdgpu_gmc_flush_gpu_tlb(adev, vmid, vmhub, type) ((adev)->gmc.gmc_funcs->flush_gpu_tlb((adev), (vmid), (vmhub), (type)))
-#define amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, type, allhub, inst) \
- ((adev)->gmc.gmc_funcs->flush_gpu_tlb_pasid \
- ((adev), (pasid), (type), (allhub), (inst)))
#define amdgpu_gmc_emit_flush_gpu_tlb(r, vmid, addr) (r)->adev->gmc.gmc_funcs->emit_flush_gpu_tlb((r), (vmid), (addr))
#define amdgpu_gmc_emit_pasid_mapping(r, vmid, pasid) (r)->adev->gmc.gmc_funcs->emit_pasid_mapping((r), (vmid), (pasid))
#define amdgpu_gmc_map_mtype(adev, flags) (adev)->gmc.gmc_funcs->map_mtype((adev),(flags))
@@ -389,9 +397,12 @@ void amdgpu_gmc_sysvm_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc
void amdgpu_gmc_vram_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc,
u64 base);
void amdgpu_gmc_gart_location(struct amdgpu_device *adev,
- struct amdgpu_gmc *mc);
+ struct amdgpu_gmc *mc,
+ enum amdgpu_gart_placement gart_placement);
void amdgpu_gmc_agp_location(struct amdgpu_device *adev,
struct amdgpu_gmc *mc);
+void amdgpu_gmc_set_agp_default(struct amdgpu_device *adev,
+ struct amdgpu_gmc *mc);
bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih, uint64_t addr,
uint16_t pasid, uint64_t timestamp);
@@ -401,6 +412,11 @@ int amdgpu_gmc_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev);
void amdgpu_gmc_ras_fini(struct amdgpu_device *adev);
int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev);
+void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
+ uint32_t vmhub, uint32_t flush_type);
+int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
+ uint32_t flush_type, bool all_hub,
+ uint32_t inst);
extern void amdgpu_gmc_tmz_set(struct amdgpu_device *adev);
extern void amdgpu_gmc_noretry_set(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
index ff1ea99292fb..ddd0891da116 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
@@ -188,7 +188,6 @@ static bool amdgpu_vmid_compatible(struct amdgpu_vmid *id,
/**
* amdgpu_vmid_grab_idle - grab idle VMID
*
- * @vm: vm to allocate id for
* @ring: ring we want to submit job to
* @idle: resulting idle VMID
* @fence: fence to wait for if no id could be grabbed
@@ -196,8 +195,7 @@ static bool amdgpu_vmid_compatible(struct amdgpu_vmid *id,
* Try to find an idle VMID, if none is idle add a fence to wait to the sync
* object. Returns -ENOMEM when we are out of memory.
*/
-static int amdgpu_vmid_grab_idle(struct amdgpu_vm *vm,
- struct amdgpu_ring *ring,
+static int amdgpu_vmid_grab_idle(struct amdgpu_ring *ring,
struct amdgpu_vmid **idle,
struct dma_fence **fence)
{
@@ -405,7 +403,7 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
int r = 0;
mutex_lock(&id_mgr->lock);
- r = amdgpu_vmid_grab_idle(vm, ring, &idle, fence);
+ r = amdgpu_vmid_grab_idle(ring, &idle, fence);
if (r || !idle)
goto error;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
index 6c6184f0dbc1..508f02eb0cf8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
@@ -28,7 +28,7 @@
#define AMDGPU_IH_MAX_NUM_IVS 32
#define IH_RING_SIZE (256 * 1024)
-#define IH_SW_RING_SIZE (8 * 1024) /* enough for 256 CAM entries */
+#define IH_SW_RING_SIZE (16 * 1024) /* enough for 512 CAM entries */
struct amdgpu_device;
struct amdgpu_iv_entry;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index fa6d0adcec20..7e6d09730e6d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -270,29 +270,29 @@ static void amdgpu_restore_msix(struct amdgpu_device *adev)
*/
int amdgpu_irq_init(struct amdgpu_device *adev)
{
- int r = 0;
- unsigned int irq;
+ unsigned int irq, flags;
+ int r;
spin_lock_init(&adev->irq.lock);
/* Enable MSI if not disabled by module parameter */
adev->irq.msi_enabled = false;
+ if (!amdgpu_msi_ok(adev))
+ flags = PCI_IRQ_LEGACY;
+ else
+ flags = PCI_IRQ_ALL_TYPES;
+
+ /* we only need one vector */
+ r = pci_alloc_irq_vectors(adev->pdev, 1, 1, flags);
+ if (r < 0) {
+ dev_err(adev->dev, "Failed to alloc msi vectors\n");
+ return r;
+ }
+
if (amdgpu_msi_ok(adev)) {
- int nvec = pci_msix_vec_count(adev->pdev);
- unsigned int flags;
-
- if (nvec <= 0)
- flags = PCI_IRQ_MSI;
- else
- flags = PCI_IRQ_MSI | PCI_IRQ_MSIX;
-
- /* we only need one vector */
- nvec = pci_alloc_irq_vectors(adev->pdev, 1, 1, flags);
- if (nvec > 0) {
- adev->irq.msi_enabled = true;
- dev_dbg(adev->dev, "using MSI/MSI-X.\n");
- }
+ adev->irq.msi_enabled = true;
+ dev_dbg(adev->dev, "using MSI/MSI-X.\n");
}
INIT_WORK(&adev->irq.ih1_work, amdgpu_irq_handle_ih1);
@@ -302,22 +302,29 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
/* Use vector 0 for MSI-X. */
r = pci_irq_vector(adev->pdev, 0);
if (r < 0)
- return r;
+ goto free_vectors;
irq = r;
/* PCI devices require shared interrupts. */
r = request_irq(irq, amdgpu_irq_handler, IRQF_SHARED, adev_to_drm(adev)->driver->name,
adev_to_drm(adev));
if (r)
- return r;
+ goto free_vectors;
+
adev->irq.installed = true;
adev->irq.irq = irq;
adev_to_drm(adev)->max_vblank_count = 0x00ffffff;
DRM_DEBUG("amdgpu: irq initialized.\n");
return 0;
-}
+free_vectors:
+ if (adev->irq.msi_enabled)
+ pci_free_irq_vectors(adev->pdev);
+
+ adev->irq.msi_enabled = false;
+ return r;
+}
void amdgpu_irq_fini_hw(struct amdgpu_device *adev)
{
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index 78476bc75b4e..1f357198533f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -325,8 +325,8 @@ void amdgpu_job_stop_all_jobs_on_sched(struct drm_gpu_scheduler *sched)
int i;
/* Signal all jobs not yet scheduled */
- for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) {
- struct drm_sched_rq *rq = &sched->sched_rq[i];
+ for (i = sched->num_rqs - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) {
+ struct drm_sched_rq *rq = sched->sched_rq[i];
spin_lock(&rq->lock);
list_for_each_entry(s_entity, &rq->entities, list) {
while ((s_job = to_drm_sched_job(spsc_queue_pop(&s_entity->job_queue)))) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index d30dc0b718c7..583cf03950cd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -200,6 +200,44 @@ out:
return r;
}
+static enum amd_ip_block_type
+ amdgpu_ip_get_block_type(struct amdgpu_device *adev, uint32_t ip)
+{
+ enum amd_ip_block_type type;
+
+ switch (ip) {
+ case AMDGPU_HW_IP_GFX:
+ type = AMD_IP_BLOCK_TYPE_GFX;
+ break;
+ case AMDGPU_HW_IP_COMPUTE:
+ type = AMD_IP_BLOCK_TYPE_GFX;
+ break;
+ case AMDGPU_HW_IP_DMA:
+ type = AMD_IP_BLOCK_TYPE_SDMA;
+ break;
+ case AMDGPU_HW_IP_UVD:
+ case AMDGPU_HW_IP_UVD_ENC:
+ type = AMD_IP_BLOCK_TYPE_UVD;
+ break;
+ case AMDGPU_HW_IP_VCE:
+ type = AMD_IP_BLOCK_TYPE_VCE;
+ break;
+ case AMDGPU_HW_IP_VCN_DEC:
+ case AMDGPU_HW_IP_VCN_ENC:
+ type = AMD_IP_BLOCK_TYPE_VCN;
+ break;
+ case AMDGPU_HW_IP_VCN_JPEG:
+ type = (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_JPEG)) ?
+ AMD_IP_BLOCK_TYPE_JPEG : AMD_IP_BLOCK_TYPE_VCN;
+ break;
+ default:
+ type = AMD_IP_BLOCK_TYPE_NUM;
+ break;
+ }
+
+ return type;
+}
+
static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
struct drm_amdgpu_query_fw *query_fw,
struct amdgpu_device *adev)
@@ -352,6 +390,10 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
fw_info->ver = adev->gfx.imu_fw_version;
fw_info->feature = 0;
break;
+ case AMDGPU_INFO_FW_VPE:
+ fw_info->ver = adev->vpe.fw_version;
+ fw_info->feature = adev->vpe.feature_version;
+ break;
default:
return -EINVAL;
}
@@ -405,7 +447,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
if (adev->uvd.inst[i].ring.sched.ready)
++num_rings;
}
- ib_start_alignment = 64;
+ ib_start_alignment = 256;
ib_size_alignment = 64;
break;
case AMDGPU_HW_IP_VCE:
@@ -413,8 +455,8 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
for (i = 0; i < adev->vce.num_rings; i++)
if (adev->vce.ring[i].sched.ready)
++num_rings;
- ib_start_alignment = 4;
- ib_size_alignment = 1;
+ ib_start_alignment = 256;
+ ib_size_alignment = 4;
break;
case AMDGPU_HW_IP_UVD_ENC:
type = AMD_IP_BLOCK_TYPE_UVD;
@@ -426,8 +468,8 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
if (adev->uvd.inst[i].ring_enc[j].sched.ready)
++num_rings;
}
- ib_start_alignment = 64;
- ib_size_alignment = 64;
+ ib_start_alignment = 256;
+ ib_size_alignment = 4;
break;
case AMDGPU_HW_IP_VCN_DEC:
type = AMD_IP_BLOCK_TYPE_VCN;
@@ -438,8 +480,8 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
if (adev->vcn.inst[i].ring_dec.sched.ready)
++num_rings;
}
- ib_start_alignment = 16;
- ib_size_alignment = 16;
+ ib_start_alignment = 256;
+ ib_size_alignment = 64;
break;
case AMDGPU_HW_IP_VCN_ENC:
type = AMD_IP_BLOCK_TYPE_VCN;
@@ -451,8 +493,8 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
if (adev->vcn.inst[i].ring_enc[j].sched.ready)
++num_rings;
}
- ib_start_alignment = 64;
- ib_size_alignment = 1;
+ ib_start_alignment = 256;
+ ib_size_alignment = 4;
break;
case AMDGPU_HW_IP_VCN_JPEG:
type = (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_JPEG)) ?
@@ -466,8 +508,15 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
if (adev->jpeg.inst[i].ring_dec[j].sched.ready)
++num_rings;
}
- ib_start_alignment = 16;
- ib_size_alignment = 16;
+ ib_start_alignment = 256;
+ ib_size_alignment = 64;
+ break;
+ case AMDGPU_HW_IP_VPE:
+ type = AMD_IP_BLOCK_TYPE_VPE;
+ if (adev->vpe.ring.sched.ready)
+ ++num_rings;
+ ib_start_alignment = 256;
+ ib_size_alignment = 4;
break;
default:
return -EINVAL;
@@ -490,18 +539,26 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
if (adev->asic_type >= CHIP_VEGA10) {
switch (type) {
case AMD_IP_BLOCK_TYPE_GFX:
- result->ip_discovery_version = adev->ip_versions[GC_HWIP][0];
+ result->ip_discovery_version =
+ IP_VERSION_MAJ_MIN_REV(amdgpu_ip_version(adev, GC_HWIP, 0));
break;
case AMD_IP_BLOCK_TYPE_SDMA:
- result->ip_discovery_version = adev->ip_versions[SDMA0_HWIP][0];
+ result->ip_discovery_version =
+ IP_VERSION_MAJ_MIN_REV(amdgpu_ip_version(adev, SDMA0_HWIP, 0));
break;
case AMD_IP_BLOCK_TYPE_UVD:
case AMD_IP_BLOCK_TYPE_VCN:
case AMD_IP_BLOCK_TYPE_JPEG:
- result->ip_discovery_version = adev->ip_versions[UVD_HWIP][0];
+ result->ip_discovery_version =
+ IP_VERSION_MAJ_MIN_REV(amdgpu_ip_version(adev, UVD_HWIP, 0));
break;
case AMD_IP_BLOCK_TYPE_VCE:
- result->ip_discovery_version = adev->ip_versions[VCE_HWIP][0];
+ result->ip_discovery_version =
+ IP_VERSION_MAJ_MIN_REV(amdgpu_ip_version(adev, VCE_HWIP, 0));
+ break;
+ case AMD_IP_BLOCK_TYPE_VPE:
+ result->ip_discovery_version =
+ IP_VERSION_MAJ_MIN_REV(amdgpu_ip_version(adev, VPE_HWIP, 0));
break;
default:
result->ip_discovery_version = 0;
@@ -538,11 +595,16 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
struct drm_amdgpu_info *info = data;
struct amdgpu_mode_info *minfo = &adev->mode_info;
void __user *out = (void __user *)(uintptr_t)info->return_pointer;
+ struct amdgpu_fpriv *fpriv;
+ struct amdgpu_ip_block *ip_block;
+ enum amd_ip_block_type type;
+ struct amdgpu_xcp *xcp;
+ u32 count, inst_mask;
uint32_t size = info->return_size;
struct drm_crtc *crtc;
uint32_t ui32 = 0;
uint64_t ui64 = 0;
- int i, found;
+ int i, found, ret;
int ui32_size = sizeof(ui32);
if (!info->return_size || !info->return_pointer)
@@ -570,7 +632,6 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
return copy_to_user(out, &ui32, min(size, 4u)) ? -EFAULT : 0;
case AMDGPU_INFO_HW_IP_INFO: {
struct drm_amdgpu_info_hw_ip ip = {};
- int ret;
ret = amdgpu_hw_ip_info(adev, info, &ip);
if (ret)
@@ -580,46 +641,66 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
return ret ? -EFAULT : 0;
}
case AMDGPU_INFO_HW_IP_COUNT: {
- enum amd_ip_block_type type;
- uint32_t count = 0;
+ fpriv = (struct amdgpu_fpriv *)filp->driver_priv;
+ type = amdgpu_ip_get_block_type(adev, info->query_hw_ip.type);
+ ip_block = amdgpu_device_ip_get_ip_block(adev, type);
- switch (info->query_hw_ip.type) {
- case AMDGPU_HW_IP_GFX:
- type = AMD_IP_BLOCK_TYPE_GFX;
- break;
- case AMDGPU_HW_IP_COMPUTE:
- type = AMD_IP_BLOCK_TYPE_GFX;
- break;
- case AMDGPU_HW_IP_DMA:
- type = AMD_IP_BLOCK_TYPE_SDMA;
- break;
- case AMDGPU_HW_IP_UVD:
- type = AMD_IP_BLOCK_TYPE_UVD;
+ if (!ip_block || !ip_block->status.valid)
+ return -EINVAL;
+
+ if (adev->xcp_mgr && adev->xcp_mgr->num_xcps > 0 &&
+ fpriv->xcp_id >= 0 && fpriv->xcp_id < adev->xcp_mgr->num_xcps) {
+ xcp = &adev->xcp_mgr->xcp[fpriv->xcp_id];
+ switch (type) {
+ case AMD_IP_BLOCK_TYPE_GFX:
+ ret = amdgpu_xcp_get_inst_details(xcp, AMDGPU_XCP_GFX, &inst_mask);
+ count = hweight32(inst_mask);
+ break;
+ case AMD_IP_BLOCK_TYPE_SDMA:
+ ret = amdgpu_xcp_get_inst_details(xcp, AMDGPU_XCP_SDMA, &inst_mask);
+ count = hweight32(inst_mask);
+ break;
+ case AMD_IP_BLOCK_TYPE_JPEG:
+ ret = amdgpu_xcp_get_inst_details(xcp, AMDGPU_XCP_VCN, &inst_mask);
+ count = hweight32(inst_mask) * adev->jpeg.num_jpeg_rings;
+ break;
+ case AMD_IP_BLOCK_TYPE_VCN:
+ ret = amdgpu_xcp_get_inst_details(xcp, AMDGPU_XCP_VCN, &inst_mask);
+ count = hweight32(inst_mask);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (ret)
+ return ret;
+ return copy_to_user(out, &count, min(size, 4u)) ? -EFAULT : 0;
+ }
+
+ switch (type) {
+ case AMD_IP_BLOCK_TYPE_GFX:
+ case AMD_IP_BLOCK_TYPE_VCE:
+ count = 1;
break;
- case AMDGPU_HW_IP_VCE:
- type = AMD_IP_BLOCK_TYPE_VCE;
+ case AMD_IP_BLOCK_TYPE_SDMA:
+ count = adev->sdma.num_instances;
break;
- case AMDGPU_HW_IP_UVD_ENC:
- type = AMD_IP_BLOCK_TYPE_UVD;
+ case AMD_IP_BLOCK_TYPE_JPEG:
+ count = adev->jpeg.num_jpeg_inst * adev->jpeg.num_jpeg_rings;
break;
- case AMDGPU_HW_IP_VCN_DEC:
- case AMDGPU_HW_IP_VCN_ENC:
- type = AMD_IP_BLOCK_TYPE_VCN;
+ case AMD_IP_BLOCK_TYPE_VCN:
+ count = adev->vcn.num_vcn_inst;
break;
- case AMDGPU_HW_IP_VCN_JPEG:
- type = (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_JPEG)) ?
- AMD_IP_BLOCK_TYPE_JPEG : AMD_IP_BLOCK_TYPE_VCN;
+ case AMD_IP_BLOCK_TYPE_UVD:
+ count = adev->uvd.num_uvd_inst;
break;
+ /* For all other IP block types not listed in the switch statement
+ * the ip status is valid here and the instance count is one.
+ */
default:
- return -EINVAL;
+ count = 1;
+ break;
}
- for (i = 0; i < adev->num_ip_blocks; i++)
- if (adev->ip_blocks[i].version->type == type &&
- adev->ip_blocks[i].status.valid &&
- count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT)
- count++;
-
return copy_to_user(out, &count, min(size, 4u)) ? -EFAULT : 0;
}
case AMDGPU_INFO_TIMESTAMP:
@@ -627,7 +708,6 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
case AMDGPU_INFO_FW_VERSION: {
struct drm_amdgpu_info_firmware fw_info;
- int ret;
/* We only support one instance of each IP block right now. */
if (info->query_fw.ip_instance != 0)
@@ -772,7 +852,6 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
struct drm_amdgpu_info_device *dev_info;
uint64_t vm_size;
uint32_t pcie_gen_mask;
- int ret;
dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
if (!dev_info)
@@ -1173,6 +1252,26 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
return copy_to_user(out, max_ibs,
min((size_t)size, sizeof(max_ibs))) ? -EFAULT : 0;
}
+ case AMDGPU_INFO_GPUVM_FAULT: {
+ struct amdgpu_fpriv *fpriv = filp->driver_priv;
+ struct amdgpu_vm *vm = &fpriv->vm;
+ struct drm_amdgpu_info_gpuvm_fault gpuvm_fault;
+ unsigned long flags;
+
+ if (!vm)
+ return -EINVAL;
+
+ memset(&gpuvm_fault, 0, sizeof(gpuvm_fault));
+
+ xa_lock_irqsave(&adev->vm_manager.pasids, flags);
+ gpuvm_fault.addr = vm->fault_info.addr;
+ gpuvm_fault.status = vm->fault_info.status;
+ gpuvm_fault.vmhub = vm->fault_info.vmhub;
+ xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
+
+ return copy_to_user(out, &gpuvm_fault,
+ min((size_t)size, sizeof(gpuvm_fault))) ? -EFAULT : 0;
+ }
default:
DRM_DEBUG_KMS("Invalid request %d\n", info->query);
return -EINVAL;
@@ -1729,6 +1828,14 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused)
seq_printf(m, "MES feature version: %u, firmware version: 0x%08x\n",
fw_info.feature, fw_info.ver);
+ /* VPE */
+ query_fw.fw_type = AMDGPU_INFO_FW_VPE;
+ ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
+ if (ret)
+ return ret;
+ seq_printf(m, "VPE feature version: %u, firmware version: 0x%08x\n",
+ fw_info.feature, fw_info.ver);
+
seq_printf(m, "VBIOS version: %s\n", ctx->vbios_pn);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c
index 8d9ff9e151de..cf33eb219e25 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c
@@ -142,3 +142,355 @@ int amdgpu_mca_mpio_ras_sw_init(struct amdgpu_device *adev)
return 0;
}
+
+void amdgpu_mca_bank_set_init(struct mca_bank_set *mca_set)
+{
+ if (!mca_set)
+ return;
+
+ memset(mca_set, 0, sizeof(*mca_set));
+ INIT_LIST_HEAD(&mca_set->list);
+}
+
+int amdgpu_mca_bank_set_add_entry(struct mca_bank_set *mca_set, struct mca_bank_entry *entry)
+{
+ struct mca_bank_node *node;
+
+ if (!entry)
+ return -EINVAL;
+
+ node = kvzalloc(sizeof(*node), GFP_KERNEL);
+ if (!node)
+ return -ENOMEM;
+
+ memcpy(&node->entry, entry, sizeof(*entry));
+
+ INIT_LIST_HEAD(&node->node);
+ list_add_tail(&node->node, &mca_set->list);
+
+ mca_set->nr_entries++;
+
+ return 0;
+}
+
+void amdgpu_mca_bank_set_release(struct mca_bank_set *mca_set)
+{
+ struct mca_bank_node *node, *tmp;
+
+ list_for_each_entry_safe(node, tmp, &mca_set->list, node) {
+ list_del(&node->node);
+ kvfree(node);
+ }
+}
+
+void amdgpu_mca_smu_init_funcs(struct amdgpu_device *adev, const struct amdgpu_mca_smu_funcs *mca_funcs)
+{
+ struct amdgpu_mca *mca = &adev->mca;
+
+ mca->mca_funcs = mca_funcs;
+}
+
+int amdgpu_mca_smu_set_debug_mode(struct amdgpu_device *adev, bool enable)
+{
+ const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
+
+ if (mca_funcs && mca_funcs->mca_set_debug_mode)
+ return mca_funcs->mca_set_debug_mode(adev, enable);
+
+ return -EOPNOTSUPP;
+}
+
+static void amdgpu_mca_smu_mca_bank_dump(struct amdgpu_device *adev, int idx, struct mca_bank_entry *entry)
+{
+ dev_info(adev->dev, "[Hardware error] Accelerator Check Architecture events logged\n");
+ dev_info(adev->dev, "[Hardware error] aca entry[%02d].STATUS=0x%016llx\n",
+ idx, entry->regs[MCA_REG_IDX_STATUS]);
+ dev_info(adev->dev, "[Hardware error] aca entry[%02d].ADDR=0x%016llx\n",
+ idx, entry->regs[MCA_REG_IDX_ADDR]);
+ dev_info(adev->dev, "[Hardware error] aca entry[%02d].MISC0=0x%016llx\n",
+ idx, entry->regs[MCA_REG_IDX_MISC0]);
+ dev_info(adev->dev, "[Hardware error] aca entry[%02d].IPID=0x%016llx\n",
+ idx, entry->regs[MCA_REG_IDX_IPID]);
+ dev_info(adev->dev, "[Hardware error] aca entry[%02d].SYND=0x%016llx\n",
+ idx, entry->regs[MCA_REG_IDX_SYND]);
+}
+
+int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type, struct ras_err_data *err_data)
+{
+ struct amdgpu_smuio_mcm_config_info mcm_info;
+ struct mca_bank_set mca_set;
+ struct mca_bank_node *node;
+ struct mca_bank_entry *entry;
+ uint32_t count;
+ int ret, i = 0;
+
+ amdgpu_mca_bank_set_init(&mca_set);
+
+ ret = amdgpu_mca_smu_get_mca_set(adev, blk, type, &mca_set);
+ if (ret)
+ goto out_mca_release;
+
+ list_for_each_entry(node, &mca_set.list, node) {
+ entry = &node->entry;
+
+ amdgpu_mca_smu_mca_bank_dump(adev, i++, entry);
+
+ count = 0;
+ ret = amdgpu_mca_smu_parse_mca_error_count(adev, blk, type, entry, &count);
+ if (ret)
+ goto out_mca_release;
+
+ if (!count)
+ continue;
+
+ mcm_info.socket_id = entry->info.socket_id;
+ mcm_info.die_id = entry->info.aid;
+
+ if (type == AMDGPU_MCA_ERROR_TYPE_UE)
+ amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, (uint64_t)count);
+ else
+ amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, (uint64_t)count);
+ }
+
+out_mca_release:
+ amdgpu_mca_bank_set_release(&mca_set);
+
+ return ret;
+}
+
+
+int amdgpu_mca_smu_get_valid_mca_count(struct amdgpu_device *adev, enum amdgpu_mca_error_type type, uint32_t *count)
+{
+ const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
+
+ if (!count)
+ return -EINVAL;
+
+ if (mca_funcs && mca_funcs->mca_get_valid_mca_count)
+ return mca_funcs->mca_get_valid_mca_count(adev, type, count);
+
+ return -EOPNOTSUPP;
+}
+
+int amdgpu_mca_smu_get_mca_set_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
+ enum amdgpu_mca_error_type type, uint32_t *total)
+{
+ const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
+ struct mca_bank_set mca_set;
+ struct mca_bank_node *node;
+ struct mca_bank_entry *entry;
+ uint32_t count;
+ int ret;
+
+ if (!total)
+ return -EINVAL;
+
+ if (!mca_funcs)
+ return -EOPNOTSUPP;
+
+ if (!mca_funcs->mca_get_ras_mca_set || !mca_funcs->mca_get_valid_mca_count)
+ return -EOPNOTSUPP;
+
+ amdgpu_mca_bank_set_init(&mca_set);
+
+ ret = mca_funcs->mca_get_ras_mca_set(adev, blk, type, &mca_set);
+ if (ret)
+ goto err_mca_set_release;
+
+ *total = 0;
+ list_for_each_entry(node, &mca_set.list, node) {
+ entry = &node->entry;
+
+ count = 0;
+ ret = mca_funcs->mca_parse_mca_error_count(adev, blk, type, entry, &count);
+ if (ret)
+ goto err_mca_set_release;
+
+ *total += count;
+ }
+
+err_mca_set_release:
+ amdgpu_mca_bank_set_release(&mca_set);
+
+ return ret;
+}
+
+int amdgpu_mca_smu_parse_mca_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
+ enum amdgpu_mca_error_type type, struct mca_bank_entry *entry, uint32_t *count)
+{
+ const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
+ if (!count || !entry)
+ return -EINVAL;
+
+ if (!mca_funcs || !mca_funcs->mca_parse_mca_error_count)
+ return -EOPNOTSUPP;
+
+
+ return mca_funcs->mca_parse_mca_error_count(adev, blk, type, entry, count);
+}
+
+int amdgpu_mca_smu_get_mca_set(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
+ enum amdgpu_mca_error_type type, struct mca_bank_set *mca_set)
+{
+ const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
+
+ if (!mca_set)
+ return -EINVAL;
+
+ if (!mca_funcs || !mca_funcs->mca_get_ras_mca_set)
+ return -EOPNOTSUPP;
+
+ WARN_ON(!list_empty(&mca_set->list));
+
+ return mca_funcs->mca_get_ras_mca_set(adev, blk, type, mca_set);
+}
+
+int amdgpu_mca_smu_get_mca_entry(struct amdgpu_device *adev, enum amdgpu_mca_error_type type,
+ int idx, struct mca_bank_entry *entry)
+{
+ const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
+ int count;
+
+ switch (type) {
+ case AMDGPU_MCA_ERROR_TYPE_UE:
+ count = mca_funcs->max_ue_count;
+ break;
+ case AMDGPU_MCA_ERROR_TYPE_CE:
+ count = mca_funcs->max_ce_count;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (idx >= count)
+ return -EINVAL;
+
+ if (mca_funcs && mca_funcs->mca_get_mca_entry)
+ return mca_funcs->mca_get_mca_entry(adev, type, idx, entry);
+
+ return -EOPNOTSUPP;
+}
+
+#if defined(CONFIG_DEBUG_FS)
+static int amdgpu_mca_smu_debug_mode_set(void *data, u64 val)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)data;
+ int ret;
+
+ ret = amdgpu_mca_smu_set_debug_mode(adev, val ? true : false);
+ if (ret)
+ return ret;
+
+ dev_info(adev->dev, "amdgpu set smu mca debug mode %s success\n", val ? "on" : "off");
+
+ return 0;
+}
+
+static void mca_dump_entry(struct seq_file *m, struct mca_bank_entry *entry)
+{
+ int i, idx = entry->idx;
+ int reg_idx_array[] = {
+ MCA_REG_IDX_STATUS,
+ MCA_REG_IDX_ADDR,
+ MCA_REG_IDX_MISC0,
+ MCA_REG_IDX_IPID,
+ MCA_REG_IDX_SYND,
+ };
+
+ seq_printf(m, "mca entry[%d].type: %s\n", idx, entry->type == AMDGPU_MCA_ERROR_TYPE_UE ? "UE" : "CE");
+ seq_printf(m, "mca entry[%d].ip: %d\n", idx, entry->ip);
+ seq_printf(m, "mca entry[%d].info: socketid:%d aid:%d hwid:0x%03x mcatype:0x%04x\n",
+ idx, entry->info.socket_id, entry->info.aid, entry->info.hwid, entry->info.mcatype);
+
+ for (i = 0; i < ARRAY_SIZE(reg_idx_array); i++)
+ seq_printf(m, "mca entry[%d].regs[%d]: 0x%016llx\n", idx, reg_idx_array[i], entry->regs[reg_idx_array[i]]);
+}
+
+static int mca_dump_show(struct seq_file *m, enum amdgpu_mca_error_type type)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
+ struct mca_bank_entry *entry;
+ uint32_t count = 0;
+ int i, ret;
+
+ ret = amdgpu_mca_smu_get_valid_mca_count(adev, type, &count);
+ if (ret)
+ return ret;
+
+ seq_printf(m, "amdgpu smu %s valid mca count: %d\n",
+ type == AMDGPU_MCA_ERROR_TYPE_UE ? "UE" : "CE", count);
+
+ if (!count)
+ return 0;
+
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++) {
+ memset(entry, 0, sizeof(*entry));
+
+ ret = amdgpu_mca_smu_get_mca_entry(adev, type, i, entry);
+ if (ret)
+ goto err_free_entry;
+
+ mca_dump_entry(m, entry);
+ }
+
+err_free_entry:
+ kfree(entry);
+
+ return ret;
+}
+
+static int mca_dump_ce_show(struct seq_file *m, void *unused)
+{
+ return mca_dump_show(m, AMDGPU_MCA_ERROR_TYPE_CE);
+}
+
+static int mca_dump_ce_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mca_dump_ce_show, inode->i_private);
+}
+
+static const struct file_operations mca_ce_dump_debug_fops = {
+ .owner = THIS_MODULE,
+ .open = mca_dump_ce_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int mca_dump_ue_show(struct seq_file *m, void *unused)
+{
+ return mca_dump_show(m, AMDGPU_MCA_ERROR_TYPE_UE);
+}
+
+static int mca_dump_ue_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mca_dump_ue_show, inode->i_private);
+}
+
+static const struct file_operations mca_ue_dump_debug_fops = {
+ .owner = THIS_MODULE,
+ .open = mca_dump_ue_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+DEFINE_DEBUGFS_ATTRIBUTE(mca_debug_mode_fops, NULL, amdgpu_mca_smu_debug_mode_set, "%llu\n");
+#endif
+
+void amdgpu_mca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root)
+{
+#if defined(CONFIG_DEBUG_FS)
+ if (!root || adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 6))
+ return;
+
+ debugfs_create_file("mca_debug_mode", 0200, root, adev, &mca_debug_mode_fops);
+ debugfs_create_file("mca_ue_dump", 0400, root, adev, &mca_ue_dump_debug_fops);
+ debugfs_create_file("mca_ce_dump", 0400, root, adev, &mca_ce_dump_debug_fops);
+#endif
+}
+
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h
index 997a073e2409..e51e8918e667 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h
@@ -21,6 +21,50 @@
#ifndef __AMDGPU_MCA_H__
#define __AMDGPU_MCA_H__
+#include "amdgpu_ras.h"
+
+#define MCA_MAX_REGS_COUNT (16)
+
+#define MCA_REG_FIELD(x, h, l) (((x) & GENMASK_ULL(h, l)) >> l)
+#define MCA_REG__STATUS__VAL(x) MCA_REG_FIELD(x, 63, 63)
+#define MCA_REG__STATUS__OVERFLOW(x) MCA_REG_FIELD(x, 62, 62)
+#define MCA_REG__STATUS__UC(x) MCA_REG_FIELD(x, 61, 61)
+#define MCA_REG__STATUS__EN(x) MCA_REG_FIELD(x, 60, 60)
+#define MCA_REG__STATUS__MISCV(x) MCA_REG_FIELD(x, 59, 59)
+#define MCA_REG__STATUS__ADDRV(x) MCA_REG_FIELD(x, 58, 58)
+#define MCA_REG__STATUS__PCC(x) MCA_REG_FIELD(x, 57, 57)
+#define MCA_REG__STATUS__ERRCOREIDVAL(x) MCA_REG_FIELD(x, 56, 56)
+#define MCA_REG__STATUS__TCC(x) MCA_REG_FIELD(x, 55, 55)
+#define MCA_REG__STATUS__SYNDV(x) MCA_REG_FIELD(x, 53, 53)
+#define MCA_REG__STATUS__CECC(x) MCA_REG_FIELD(x, 46, 46)
+#define MCA_REG__STATUS__UECC(x) MCA_REG_FIELD(x, 45, 45)
+#define MCA_REG__STATUS__DEFERRED(x) MCA_REG_FIELD(x, 44, 44)
+#define MCA_REG__STATUS__POISON(x) MCA_REG_FIELD(x, 43, 43)
+#define MCA_REG__STATUS__SCRUB(x) MCA_REG_FIELD(x, 40, 40)
+#define MCA_REG__STATUS__ERRCOREID(x) MCA_REG_FIELD(x, 37, 32)
+#define MCA_REG__STATUS__ADDRLSB(x) MCA_REG_FIELD(x, 29, 24)
+#define MCA_REG__STATUS__ERRORCODEEXT(x) MCA_REG_FIELD(x, 21, 16)
+#define MCA_REG__STATUS__ERRORCODE(x) MCA_REG_FIELD(x, 15, 0)
+
+#define MCA_REG__SYND__ERRORINFORMATION(x) MCA_REG_FIELD(x, 17, 0)
+
+enum amdgpu_mca_ip {
+ AMDGPU_MCA_IP_UNKNOW = -1,
+ AMDGPU_MCA_IP_PSP = 0,
+ AMDGPU_MCA_IP_SDMA,
+ AMDGPU_MCA_IP_GC,
+ AMDGPU_MCA_IP_SMU,
+ AMDGPU_MCA_IP_MP5,
+ AMDGPU_MCA_IP_UMC,
+ AMDGPU_MCA_IP_PCS_XGMI,
+ AMDGPU_MCA_IP_COUNT,
+};
+
+enum amdgpu_mca_error_type {
+ AMDGPU_MCA_ERROR_TYPE_UE = 0,
+ AMDGPU_MCA_ERROR_TYPE_CE,
+};
+
struct amdgpu_mca_ras_block {
struct amdgpu_ras_block_object ras_block;
};
@@ -34,6 +78,55 @@ struct amdgpu_mca {
struct amdgpu_mca_ras mp0;
struct amdgpu_mca_ras mp1;
struct amdgpu_mca_ras mpio;
+ const struct amdgpu_mca_smu_funcs *mca_funcs;
+};
+
+enum mca_reg_idx {
+ MCA_REG_IDX_STATUS = 1,
+ MCA_REG_IDX_ADDR = 2,
+ MCA_REG_IDX_MISC0 = 3,
+ MCA_REG_IDX_IPID = 5,
+ MCA_REG_IDX_SYND = 6,
+ MCA_REG_IDX_COUNT = 16,
+};
+
+struct mca_bank_info {
+ int socket_id;
+ int aid;
+ int hwid;
+ int mcatype;
+};
+
+struct mca_bank_entry {
+ int idx;
+ enum amdgpu_mca_error_type type;
+ enum amdgpu_mca_ip ip;
+ struct mca_bank_info info;
+ uint64_t regs[MCA_MAX_REGS_COUNT];
+};
+
+struct mca_bank_node {
+ struct mca_bank_entry entry;
+ struct list_head node;
+};
+
+struct mca_bank_set {
+ int nr_entries;
+ struct list_head list;
+};
+
+struct amdgpu_mca_smu_funcs {
+ int max_ue_count;
+ int max_ce_count;
+ int (*mca_set_debug_mode)(struct amdgpu_device *adev, bool enable);
+ int (*mca_get_ras_mca_set)(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type,
+ struct mca_bank_set *mca_set);
+ int (*mca_parse_mca_error_count)(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type,
+ struct mca_bank_entry *entry, uint32_t *count);
+ int (*mca_get_valid_mca_count)(struct amdgpu_device *adev, enum amdgpu_mca_error_type type,
+ uint32_t *count);
+ int (*mca_get_mca_entry)(struct amdgpu_device *adev, enum amdgpu_mca_error_type type,
+ int idx, struct mca_bank_entry *entry);
};
void amdgpu_mca_query_correctable_error_count(struct amdgpu_device *adev,
@@ -53,4 +146,26 @@ void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev,
int amdgpu_mca_mp0_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_mca_mp1_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_mca_mpio_ras_sw_init(struct amdgpu_device *adev);
+
+void amdgpu_mca_smu_init_funcs(struct amdgpu_device *adev, const struct amdgpu_mca_smu_funcs *mca_funcs);
+int amdgpu_mca_smu_set_debug_mode(struct amdgpu_device *adev, bool enable);
+int amdgpu_mca_smu_get_valid_mca_count(struct amdgpu_device *adev, enum amdgpu_mca_error_type type, uint32_t *count);
+int amdgpu_mca_smu_get_mca_set_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
+ enum amdgpu_mca_error_type type, uint32_t *total);
+int amdgpu_mca_smu_get_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
+ enum amdgpu_mca_error_type type, uint32_t *count);
+int amdgpu_mca_smu_parse_mca_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
+ enum amdgpu_mca_error_type type, struct mca_bank_entry *entry, uint32_t *count);
+int amdgpu_mca_smu_get_mca_set(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
+ enum amdgpu_mca_error_type type, struct mca_bank_set *mca_set);
+int amdgpu_mca_smu_get_mca_entry(struct amdgpu_device *adev, enum amdgpu_mca_error_type type,
+ int idx, struct mca_bank_entry *entry);
+
+void amdgpu_mca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root);
+
+void amdgpu_mca_bank_set_init(struct mca_bank_set *mca_set);
+int amdgpu_mca_bank_set_add_entry(struct mca_bank_set *mca_set, struct mca_bank_entry *entry);
+void amdgpu_mca_bank_set_release(struct mca_bank_set *mca_set);
+int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type, struct ras_err_data *err_data);
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
index b6015157763a..9ddbf1494326 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
@@ -132,7 +132,8 @@ int amdgpu_mes_init(struct amdgpu_device *adev)
adev->mes.gfx_hqd_mask[i] = i ? 0 : 0xfffffffe;
for (i = 0; i < AMDGPU_MES_MAX_SDMA_PIPES; i++) {
- if (adev->ip_versions[SDMA0_HWIP][0] < IP_VERSION(6, 0, 0))
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) <
+ IP_VERSION(6, 0, 0))
adev->mes.sdma_hqd_mask[i] = i ? 0 : 0x3fc;
/* zero sdma_hqd_mask for non-existent engine */
else if (adev->sdma.num_instances == 1)
@@ -556,8 +557,20 @@ static void amdgpu_mes_queue_init_mqd(struct amdgpu_device *adev,
mqd_prop.hqd_queue_priority = p->hqd_queue_priority;
mqd_prop.hqd_active = false;
+ if (p->queue_type == AMDGPU_RING_TYPE_GFX ||
+ p->queue_type == AMDGPU_RING_TYPE_COMPUTE) {
+ mutex_lock(&adev->srbm_mutex);
+ amdgpu_gfx_select_me_pipe_q(adev, p->ring->me, p->ring->pipe, 0, 0, 0);
+ }
+
mqd_mgr->init_mqd(adev, q->mqd_cpu_ptr, &mqd_prop);
+ if (p->queue_type == AMDGPU_RING_TYPE_GFX ||
+ p->queue_type == AMDGPU_RING_TYPE_COMPUTE) {
+ amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0, 0);
+ mutex_unlock(&adev->srbm_mutex);
+ }
+
amdgpu_bo_unreserve(q->mqd_obj);
}
@@ -993,9 +1006,13 @@ int amdgpu_mes_add_ring(struct amdgpu_device *adev, int gang_id,
switch (queue_type) {
case AMDGPU_RING_TYPE_GFX:
ring->funcs = adev->gfx.gfx_ring[0].funcs;
+ ring->me = adev->gfx.gfx_ring[0].me;
+ ring->pipe = adev->gfx.gfx_ring[0].pipe;
break;
case AMDGPU_RING_TYPE_COMPUTE:
ring->funcs = adev->gfx.compute_ring[0].funcs;
+ ring->me = adev->gfx.compute_ring[0].me;
+ ring->pipe = adev->gfx.compute_ring[0].pipe;
break;
case AMDGPU_RING_TYPE_SDMA:
ring->funcs = adev->sdma.instance[0].ring.funcs;
@@ -1335,8 +1352,10 @@ int amdgpu_mes_self_test(struct amdgpu_device *adev)
for (i = 0; i < ARRAY_SIZE(queue_types); i++) {
/* On GFX v10.3, fw hasn't supported to map sdma queue. */
- if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0) &&
- adev->ip_versions[GC_HWIP][0] < IP_VERSION(11, 0, 0) &&
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) >=
+ IP_VERSION(10, 3, 0) &&
+ amdgpu_ip_version(adev, GC_HWIP, 0) <
+ IP_VERSION(11, 0, 0) &&
queue_types[i][0] == AMDGPU_RING_TYPE_SDMA)
continue;
@@ -1397,7 +1416,7 @@ int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe)
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix,
sizeof(ucode_prefix));
- if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(11, 0, 0)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(11, 0, 0)) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes%s.bin",
ucode_prefix,
pipe == AMDGPU_MES_SCHED_PIPE ? "_2" : "1");
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
index 6cf7a8829a52..65e35059de40 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
@@ -69,6 +69,8 @@ struct amdgpu_nbio_funcs {
u32 (*get_memsize)(struct amdgpu_device *adev);
void (*sdma_doorbell_range)(struct amdgpu_device *adev, int instance,
bool use_doorbell, int doorbell_index, int doorbell_size);
+ void (*vpe_doorbell_range)(struct amdgpu_device *adev, int instance,
+ bool use_doorbell, int doorbell_index, int doorbell_size);
void (*vcn_doorbell_range)(struct amdgpu_device *adev, bool use_doorbell,
int doorbell_index, int instance);
void (*gc_doorbell_init)(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index ace837cfa0a6..5ad03f2afdb4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -459,7 +459,7 @@ void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr,
*cpu_addr = NULL;
}
-/* Validate bo size is bit bigger then the request domain */
+/* Validate bo size is bit bigger than the request domain */
static bool amdgpu_bo_validate_size(struct amdgpu_device *adev,
unsigned long size, u32 domain)
{
@@ -469,29 +469,24 @@ static bool amdgpu_bo_validate_size(struct amdgpu_device *adev,
* If GTT is part of requested domains the check must succeed to
* allow fall back to GTT.
*/
- if (domain & AMDGPU_GEM_DOMAIN_GTT) {
+ if (domain & AMDGPU_GEM_DOMAIN_GTT)
man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT);
-
- if (man && size < man->size)
- return true;
- else if (!man)
- WARN_ON_ONCE("GTT domain requested but GTT mem manager uninitialized");
- goto fail;
- } else if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
+ else if (domain & AMDGPU_GEM_DOMAIN_VRAM)
man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
+ else
+ return true;
- if (man && size < man->size)
- return true;
- goto fail;
+ if (!man) {
+ if (domain & AMDGPU_GEM_DOMAIN_GTT)
+ WARN_ON_ONCE("GTT domain requested but GTT mem manager uninitialized");
+ return false;
}
/* TODO add more domains checks, such as AMDGPU_GEM_DOMAIN_CPU, _DOMAIN_DOORBELL */
- return true;
+ if (size < man->size)
+ return true;
-fail:
- if (man)
- DRM_DEBUG("BO size %lu > total memory in domain: %llu\n", size,
- man->size);
+ DRM_DEBUG("BO size %lu > total memory in domain: %llu\n", size, man->size);
return false;
}
@@ -1348,6 +1343,8 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
abo = ttm_to_amdgpu_bo(bo);
+ WARN_ON(abo->vm_bo);
+
if (abo->kfd_bo)
amdgpu_amdkfd_release_notify(abo);
@@ -1532,10 +1529,14 @@ u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
u64 amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo *bo)
{
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
- uint64_t offset;
+ uint64_t offset = AMDGPU_BO_INVALID_OFFSET;
+
+ if (bo->tbo.resource->mem_type == TTM_PL_TT)
+ offset = amdgpu_gmc_agp_addr(&bo->tbo);
- offset = (bo->tbo.resource->start << PAGE_SHIFT) +
- amdgpu_ttm_domain_start(adev, bo->tbo.resource->mem_type);
+ if (offset == AMDGPU_BO_INVALID_OFFSET)
+ offset = (bo->tbo.resource->start << PAGE_SHIFT) +
+ amdgpu_ttm_domain_start(adev, bo->tbo.resource->mem_type);
return amdgpu_gmc_sign_extend(offset);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index f3ee83cdf97e..d28e21baef16 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -252,7 +252,7 @@ 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->mem_type != TTM_PL_VRAM)
+ 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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 429ef212c1f2..a21045d018f2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -100,7 +100,7 @@ static void psp_check_pmfw_centralized_cstate_management(struct psp_context *psp
return;
}
- switch (adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 0, 5):
@@ -128,7 +128,7 @@ static int psp_init_sriov_microcode(struct psp_context *psp)
amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));
- switch (adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
case IP_VERSION(9, 0, 0):
case IP_VERSION(11, 0, 7):
case IP_VERSION(11, 0, 9):
@@ -162,7 +162,7 @@ static int psp_early_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct psp_context *psp = &adev->psp;
- switch (adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
case IP_VERSION(9, 0, 0):
psp_v3_1_set_psp_funcs(psp);
psp->autoload_supported = false;
@@ -334,7 +334,7 @@ static bool psp_get_runtime_db_entry(struct amdgpu_device *adev,
bool ret = false;
int i;
- if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 6))
+ if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 6))
return false;
db_header_pos = adev->gmc.mc_vram_size - PSP_RUNTIME_DB_OFFSET;
@@ -413,7 +413,7 @@ static int psp_sw_init(void *handle)
adev->psp.xgmi_context.supports_extended_data =
!adev->gmc.xgmi.connected_to_cpu &&
- adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2);
+ amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 2);
memset(&scpm_entry, 0, sizeof(scpm_entry));
if ((psp_get_runtime_db_entry(adev,
@@ -773,7 +773,7 @@ static int psp_load_toc(struct psp_context *psp,
static bool psp_boottime_tmr(struct psp_context *psp)
{
- switch (psp->adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(psp->adev, MP0_HWIP, 0)) {
case IP_VERSION(13, 0, 6):
return true;
default:
@@ -828,7 +828,7 @@ static int psp_tmr_init(struct psp_context *psp)
static bool psp_skip_tmr(struct psp_context *psp)
{
- switch (psp->adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(psp->adev, MP0_HWIP, 0)) {
case IP_VERSION(11, 0, 9):
case IP_VERSION(11, 0, 7):
case IP_VERSION(13, 0, 2):
@@ -1215,8 +1215,8 @@ int psp_xgmi_terminate(struct psp_context *psp)
struct amdgpu_device *adev = psp->adev;
/* XGMI TA unload currently is not supported on Arcturus/Aldebaran A+A */
- if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 4) ||
- (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2) &&
+ if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(11, 0, 4) ||
+ (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 2) &&
adev->gmc.xgmi.connected_to_cpu))
return 0;
@@ -1267,6 +1267,8 @@ invoke:
xgmi_cmd->cmd_id = TA_COMMAND_XGMI__INITIALIZE;
ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id);
+ /* note down the capbility flag for XGMI TA */
+ psp->xgmi_context.xgmi_ta_caps = xgmi_cmd->caps_flag;
return ret;
}
@@ -1313,9 +1315,11 @@ int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id)
static bool psp_xgmi_peer_link_info_supported(struct psp_context *psp)
{
- return (psp->adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2) &&
+ return (amdgpu_ip_version(psp->adev, MP0_HWIP, 0) ==
+ IP_VERSION(13, 0, 2) &&
psp->xgmi_context.context.bin_desc.fw_version >= 0x2000000b) ||
- psp->adev->ip_versions[MP0_HWIP][0] >= IP_VERSION(13, 0, 6);
+ amdgpu_ip_version(psp->adev, MP0_HWIP, 0) >=
+ IP_VERSION(13, 0, 6);
}
/*
@@ -1386,7 +1390,7 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
/* Fill in the shared memory with topology information as input */
topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info;
- xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO;
+ xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_TOPOLOGY_INFO;
topology_info_input->num_nodes = number_devices;
for (i = 0; i < topology_info_input->num_nodes; i++) {
@@ -1397,7 +1401,7 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
}
/* Invoke xgmi ta to get the topology information */
- ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO);
+ ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_TOPOLOGY_INFO);
if (ret)
return ret;
@@ -1422,26 +1426,58 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
/* Invoke xgmi ta again to get the link information */
if (psp_xgmi_peer_link_info_supported(psp)) {
- struct ta_xgmi_cmd_get_peer_link_info_output *link_info_output;
+ struct ta_xgmi_cmd_get_peer_link_info *link_info_output;
+ struct ta_xgmi_cmd_get_extend_peer_link_info *link_extend_info_output;
bool requires_reflection =
- (psp->xgmi_context.supports_extended_data && get_extended_data) ||
- psp->adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 6);
+ (psp->xgmi_context.supports_extended_data &&
+ get_extended_data) ||
+ amdgpu_ip_version(psp->adev, MP0_HWIP, 0) ==
+ IP_VERSION(13, 0, 6);
+ bool ta_port_num_support = psp->xgmi_context.xgmi_ta_caps &
+ EXTEND_PEER_LINK_INFO_CMD_FLAG;
+
+ /* popluate the shared output buffer rather than the cmd input buffer
+ * with node_ids as the input for GET_PEER_LINKS command execution.
+ * This is required for GET_PEER_LINKS per xgmi ta implementation.
+ * The same requirement for GET_EXTEND_PEER_LINKS command.
+ */
+ if (ta_port_num_support) {
+ link_extend_info_output = &xgmi_cmd->xgmi_out_message.get_extend_link_info;
+
+ for (i = 0; i < topology->num_nodes; i++)
+ link_extend_info_output->nodes[i].node_id = topology->nodes[i].node_id;
+
+ link_extend_info_output->num_nodes = topology->num_nodes;
+ xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_EXTEND_PEER_LINKS;
+ } else {
+ link_info_output = &xgmi_cmd->xgmi_out_message.get_link_info;
- xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_PEER_LINKS;
+ for (i = 0; i < topology->num_nodes; i++)
+ link_info_output->nodes[i].node_id = topology->nodes[i].node_id;
- ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_PEER_LINKS);
+ link_info_output->num_nodes = topology->num_nodes;
+ xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_PEER_LINKS;
+ }
+ ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id);
if (ret)
return ret;
- link_info_output = &xgmi_cmd->xgmi_out_message.get_link_info;
for (i = 0; i < topology->num_nodes; i++) {
+ uint8_t node_num_links = ta_port_num_support ?
+ link_extend_info_output->nodes[i].num_links : link_info_output->nodes[i].num_links;
/* accumulate num_links on extended data */
- topology->nodes[i].num_links = get_extended_data ?
- topology->nodes[i].num_links +
- link_info_output->nodes[i].num_links :
- ((requires_reflection && topology->nodes[i].num_links) ? topology->nodes[i].num_links :
- link_info_output->nodes[i].num_links);
+ if (get_extended_data) {
+ topology->nodes[i].num_links = topology->nodes[i].num_links + node_num_links;
+ } else {
+ topology->nodes[i].num_links = (requires_reflection && topology->nodes[i].num_links) ?
+ topology->nodes[i].num_links : node_num_links;
+ }
+ /* popluate the connected port num info if supported and available */
+ if (ta_port_num_support && topology->nodes[i].num_links) {
+ memcpy(topology->nodes[i].port_num, link_extend_info_output->nodes[i].port_num,
+ sizeof(struct xgmi_connected_port_num) * TA_XGMI__MAX_PORT_NUM);
+ }
/* reflect the topology information for bi-directionality */
if (requires_reflection && topology->nodes[i].num_hops)
@@ -2089,6 +2125,21 @@ int amdgpu_psp_wait_for_bootloader(struct amdgpu_device *adev)
return ret;
}
+int amdgpu_psp_query_boot_status(struct amdgpu_device *adev)
+{
+ struct psp_context *psp = &adev->psp;
+ int ret = 0;
+
+ if (amdgpu_sriov_vf(adev) || (adev->flags & AMD_IS_APU))
+ return 0;
+
+ if (psp->funcs &&
+ psp->funcs->query_boot_status)
+ ret = psp->funcs->query_boot_status(psp);
+
+ return ret;
+}
+
static int psp_hw_start(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
@@ -2390,6 +2441,27 @@ static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,
case AMDGPU_UCODE_ID_CP_RS64_MEC_P3_STACK:
*type = GFX_FW_TYPE_RS64_MEC_P3_STACK;
break;
+ case AMDGPU_UCODE_ID_VPE_CTX:
+ *type = GFX_FW_TYPE_VPEC_FW1;
+ break;
+ case AMDGPU_UCODE_ID_VPE_CTL:
+ *type = GFX_FW_TYPE_VPEC_FW2;
+ break;
+ case AMDGPU_UCODE_ID_VPE:
+ *type = GFX_FW_TYPE_VPE;
+ break;
+ case AMDGPU_UCODE_ID_UMSCH_MM_UCODE:
+ *type = GFX_FW_TYPE_UMSCH_UCODE;
+ break;
+ case AMDGPU_UCODE_ID_UMSCH_MM_DATA:
+ *type = GFX_FW_TYPE_UMSCH_DATA;
+ break;
+ case AMDGPU_UCODE_ID_UMSCH_MM_CMD_BUFFER:
+ *type = GFX_FW_TYPE_UMSCH_CMD_BUFFER;
+ break;
+ case AMDGPU_UCODE_ID_P2S_TABLE:
+ *type = GFX_FW_TYPE_P2S_TABLE;
+ break;
case AMDGPU_UCODE_ID_MAXIMUM:
default:
return -EINVAL;
@@ -2481,6 +2553,31 @@ int psp_execute_ip_fw_load(struct psp_context *psp,
return ret;
}
+static int psp_load_p2s_table(struct psp_context *psp)
+{
+ int ret;
+ struct amdgpu_device *adev = psp->adev;
+ struct amdgpu_firmware_info *ucode =
+ &adev->firmware.ucode[AMDGPU_UCODE_ID_P2S_TABLE];
+
+ if (adev->in_runpm && (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO))
+ return 0;
+
+ if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 6)) {
+ uint32_t supp_vers = adev->flags & AMD_IS_APU ? 0x0036013D :
+ 0x0036003C;
+ if (psp->sos.fw_version < supp_vers)
+ return 0;
+ }
+
+ if (!ucode->fw || amdgpu_sriov_vf(psp->adev))
+ return 0;
+
+ ret = psp_execute_ip_fw_load(psp, ucode);
+
+ return ret;
+}
+
static int psp_load_smu_fw(struct psp_context *psp)
{
int ret;
@@ -2499,10 +2596,9 @@ static int psp_load_smu_fw(struct psp_context *psp)
if (!ucode->fw || amdgpu_sriov_vf(psp->adev))
return 0;
- if ((amdgpu_in_reset(adev) &&
- ras && adev->ras_enabled &&
- (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 4) ||
- adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 2)))) {
+ if ((amdgpu_in_reset(adev) && ras && adev->ras_enabled &&
+ (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(11, 0, 4) ||
+ amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(11, 0, 2)))) {
ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD);
if (ret)
DRM_WARN("Failed to set MP1 state prepare for reload\n");
@@ -2522,6 +2618,9 @@ static bool fw_load_skip_check(struct psp_context *psp,
if (!ucode->fw || !ucode->ucode_size)
return true;
+ if (ucode->ucode_id == AMDGPU_UCODE_ID_P2S_TABLE)
+ return true;
+
if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC &&
(psp_smu_reload_quirk(psp) ||
psp->autoload_supported ||
@@ -2570,6 +2669,9 @@ static int psp_load_non_psp_fw(struct psp_context *psp)
return ret;
}
+ /* Load P2S table first if it's available */
+ psp_load_p2s_table(psp);
+
for (i = 0; i < adev->firmware.max_ucodes; i++) {
ucode = &adev->firmware.ucode[i];
@@ -2585,9 +2687,12 @@ static int psp_load_non_psp_fw(struct psp_context *psp)
continue;
if (psp->autoload_supported &&
- (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 7) ||
- adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 11) ||
- adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 12)) &&
+ (amdgpu_ip_version(adev, MP0_HWIP, 0) ==
+ IP_VERSION(11, 0, 7) ||
+ amdgpu_ip_version(adev, MP0_HWIP, 0) ==
+ IP_VERSION(11, 0, 11) ||
+ amdgpu_ip_version(adev, MP0_HWIP, 0) ==
+ IP_VERSION(11, 0, 12)) &&
(ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 ||
ucode->ucode_id == AMDGPU_UCODE_ID_SDMA2 ||
ucode->ucode_id == AMDGPU_UCODE_ID_SDMA3))
@@ -3128,7 +3233,7 @@ static int psp_init_sos_base_fw(struct amdgpu_device *adev)
le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes);
if (adev->gmc.xgmi.connected_to_cpu ||
- (adev->ip_versions[MP0_HWIP][0] != IP_VERSION(13, 0, 2))) {
+ (amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(13, 0, 2))) {
adev->psp.sos.fw_version = le32_to_cpu(sos_hdr->header.ucode_version);
adev->psp.sos.feature_version = le32_to_cpu(sos_hdr->sos.fw_version);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index 3e67ed63e638..c4d9cbde55b9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -134,6 +134,7 @@ struct psp_funcs {
int (*update_spirom)(struct psp_context *psp, uint64_t fw_pri_mc_addr);
int (*vbflash_stat)(struct psp_context *psp);
int (*fatal_error_recovery_quirk)(struct psp_context *psp);
+ int (*query_boot_status)(struct psp_context *psp);
};
struct ta_funcs {
@@ -149,6 +150,7 @@ struct psp_xgmi_node_info {
uint8_t is_sharing_enabled;
enum ta_xgmi_assigned_sdma_engine sdma_engine;
uint8_t num_links;
+ struct xgmi_connected_port_num port_num[TA_XGMI__MAX_PORT_NUM];
};
struct psp_xgmi_topology_info {
@@ -189,6 +191,7 @@ struct psp_xgmi_context {
struct ta_context context;
struct psp_xgmi_topology_info top_info;
bool supports_extended_data;
+ uint8_t xgmi_ta_caps;
};
struct psp_ras_context {
@@ -536,4 +539,6 @@ int is_psp_fw_valid(struct psp_bin_desc bin);
int amdgpu_psp_wait_for_bootloader(struct amdgpu_device *adev);
+int amdgpu_psp_query_boot_status(struct amdgpu_device *adev);
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 163445baa4fc..63fb4cd85e53 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -28,6 +28,7 @@
#include <linux/reboot.h>
#include <linux/syscalls.h>
#include <linux/pm_runtime.h>
+#include <linux/list_sort.h>
#include "amdgpu.h"
#include "amdgpu_ras.h"
@@ -152,8 +153,9 @@ static bool amdgpu_ras_get_error_query_ready(struct amdgpu_device *adev)
static int amdgpu_reserve_page_direct(struct amdgpu_device *adev, uint64_t address)
{
- struct ras_err_data err_data = {0, 0, 0, NULL};
+ struct ras_err_data err_data;
struct eeprom_table_record err_rec;
+ int ret;
if ((address >= adev->gmc.mc_vram_size) ||
(address >= RAS_UMC_INJECT_ADDR_LIMIT)) {
@@ -170,6 +172,10 @@ static int amdgpu_reserve_page_direct(struct amdgpu_device *adev, uint64_t addre
return 0;
}
+ ret = amdgpu_ras_error_data_init(&err_data);
+ if (ret)
+ return ret;
+
memset(&err_rec, 0x0, sizeof(struct eeprom_table_record));
err_data.err_addr = &err_rec;
amdgpu_umc_fill_error_record(&err_data, address, address, 0, 0);
@@ -180,6 +186,8 @@ static int amdgpu_reserve_page_direct(struct amdgpu_device *adev, uint64_t addre
amdgpu_ras_save_bad_pages(adev, NULL);
}
+ amdgpu_ras_error_data_fini(&err_data);
+
dev_warn(adev->dev, "WARNING: THIS IS ONLY FOR TEST PURPOSES AND WILL CORRUPT RAS EEPROM\n");
dev_warn(adev->dev, "Clear EEPROM:\n");
dev_warn(adev->dev, " echo 1 > /sys/kernel/debug/dri/0/ras/ras_eeprom_reset\n");
@@ -201,8 +209,8 @@ static ssize_t amdgpu_ras_debugfs_read(struct file *f, char __user *buf,
return -EINVAL;
/* Hardware counter will be reset automatically after the query on Vega20 and Arcturus */
- if (obj->adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 2) &&
- obj->adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 4)) {
+ if (amdgpu_ip_version(obj->adev, MP0_HWIP, 0) != IP_VERSION(11, 0, 2) &&
+ amdgpu_ip_version(obj->adev, MP0_HWIP, 0) != IP_VERSION(11, 0, 4)) {
if (amdgpu_ras_reset_error_status(obj->adev, info.head.block))
dev_warn(obj->adev->dev, "Failed to reset error counter and error status");
}
@@ -611,8 +619,8 @@ static ssize_t amdgpu_ras_sysfs_read(struct device *dev,
if (amdgpu_ras_query_error_status(obj->adev, &info))
return -EINVAL;
- if (obj->adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 2) &&
- obj->adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 4)) {
+ if (amdgpu_ip_version(obj->adev, MP0_HWIP, 0) != IP_VERSION(11, 0, 2) &&
+ amdgpu_ip_version(obj->adev, MP0_HWIP, 0) != IP_VERSION(11, 0, 4)) {
if (amdgpu_ras_reset_error_status(obj->adev, info.head.block))
dev_warn(obj->adev->dev, "Failed to reset error counter and error status");
}
@@ -628,8 +636,11 @@ static ssize_t amdgpu_ras_sysfs_read(struct device *dev,
static inline void put_obj(struct ras_manager *obj)
{
- if (obj && (--obj->use == 0))
+ if (obj && (--obj->use == 0)) {
list_del(&obj->node);
+ amdgpu_ras_error_data_fini(&obj->err_data);
+ }
+
if (obj && (obj->use < 0))
DRM_ERROR("RAS ERROR: Unbalance obj(%s) use\n", get_ras_block_str(&obj->head));
}
@@ -659,6 +670,9 @@ static struct ras_manager *amdgpu_ras_create_obj(struct amdgpu_device *adev,
if (alive_obj(obj))
return NULL;
+ if (amdgpu_ras_error_data_init(&obj->err_data))
+ return NULL;
+
obj->head = *head;
obj->adev = adev;
list_add(&obj->node, &con->head);
@@ -769,9 +783,10 @@ int amdgpu_ras_feature_enable(struct amdgpu_device *adev,
if (!con)
return -EINVAL;
- /* Do not enable ras feature if it is not allowed */
- if (enable &&
- head->block != AMDGPU_RAS_BLOCK__GFX &&
+ /* For non-gfx ip, do not enable ras feature if it is not allowed */
+ /* For gfx ip, regardless of feature support status, */
+ /* Force issue enable or disable ras feature commands */
+ if (head->block != AMDGPU_RAS_BLOCK__GFX &&
!amdgpu_ras_is_feature_allowed(adev, head))
return 0;
@@ -1014,105 +1029,266 @@ static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_d
}
}
-/* query/inject/cure begin */
-int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
- struct ras_query_if *info)
-{
- struct amdgpu_ras_block_object *block_obj = NULL;
- struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head);
- struct ras_err_data err_data = {0, 0, 0, NULL};
+static void amdgpu_ras_error_print_error_data(struct amdgpu_device *adev,
+ struct ras_manager *ras_mgr,
+ struct ras_err_data *err_data,
+ const char *blk_name,
+ bool is_ue)
+{
+ struct amdgpu_smuio_mcm_config_info *mcm_info;
+ struct ras_err_node *err_node;
+ struct ras_err_info *err_info;
+
+ if (is_ue) {
+ for_each_ras_error(err_node, err_data) {
+ err_info = &err_node->err_info;
+ mcm_info = &err_info->mcm_info;
+ if (err_info->ue_count) {
+ dev_info(adev->dev, "socket: %d, die: %d, "
+ "%lld new uncorrectable hardware errors detected in %s block\n",
+ mcm_info->socket_id,
+ mcm_info->die_id,
+ err_info->ue_count,
+ blk_name);
+ }
+ }
- if (!obj)
- return -EINVAL;
+ for_each_ras_error(err_node, &ras_mgr->err_data) {
+ err_info = &err_node->err_info;
+ mcm_info = &err_info->mcm_info;
+ dev_info(adev->dev, "socket: %d, die: %d, "
+ "%lld uncorrectable hardware errors detected in total in %s block\n",
+ mcm_info->socket_id, mcm_info->die_id, err_info->ue_count, blk_name);
+ }
- if (info->head.block == AMDGPU_RAS_BLOCK__UMC) {
- amdgpu_ras_get_ecc_info(adev, &err_data);
} else {
- block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, 0);
- if (!block_obj || !block_obj->hw_ops) {
- dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
- get_ras_block_str(&info->head));
- return -EINVAL;
+ for_each_ras_error(err_node, err_data) {
+ err_info = &err_node->err_info;
+ mcm_info = &err_info->mcm_info;
+ if (err_info->ce_count) {
+ dev_info(adev->dev, "socket: %d, die: %d, "
+ "%lld new correctable hardware errors detected in %s block, "
+ "no user action is needed\n",
+ mcm_info->socket_id,
+ mcm_info->die_id,
+ err_info->ce_count,
+ blk_name);
+ }
}
- if (block_obj->hw_ops->query_ras_error_count)
- block_obj->hw_ops->query_ras_error_count(adev, &err_data);
-
- if ((info->head.block == AMDGPU_RAS_BLOCK__SDMA) ||
- (info->head.block == AMDGPU_RAS_BLOCK__GFX) ||
- (info->head.block == AMDGPU_RAS_BLOCK__MMHUB)) {
- if (block_obj->hw_ops->query_ras_error_status)
- block_obj->hw_ops->query_ras_error_status(adev);
- }
+ for_each_ras_error(err_node, &ras_mgr->err_data) {
+ err_info = &err_node->err_info;
+ mcm_info = &err_info->mcm_info;
+ dev_info(adev->dev, "socket: %d, die: %d, "
+ "%lld correctable hardware errors detected in total in %s block, "
+ "no user action is needed\n",
+ mcm_info->socket_id, mcm_info->die_id, err_info->ce_count, blk_name);
+ }
}
+}
- obj->err_data.ue_count += err_data.ue_count;
- obj->err_data.ce_count += err_data.ce_count;
+static inline bool err_data_has_source_info(struct ras_err_data *data)
+{
+ return !list_empty(&data->err_node_list);
+}
- info->ue_count = obj->err_data.ue_count;
- info->ce_count = obj->err_data.ce_count;
+static void amdgpu_ras_error_generate_report(struct amdgpu_device *adev,
+ struct ras_query_if *query_if,
+ struct ras_err_data *err_data)
+{
+ struct ras_manager *ras_mgr = amdgpu_ras_find_obj(adev, &query_if->head);
+ const char *blk_name = get_ras_block_str(&query_if->head);
- if (err_data.ce_count) {
- if (!adev->aid_mask &&
- adev->smuio.funcs &&
- adev->smuio.funcs->get_socket_id &&
- adev->smuio.funcs->get_die_id) {
+ if (err_data->ce_count) {
+ if (err_data_has_source_info(err_data)) {
+ amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, blk_name, false);
+ } else if (!adev->aid_mask &&
+ adev->smuio.funcs &&
+ adev->smuio.funcs->get_socket_id &&
+ adev->smuio.funcs->get_die_id) {
dev_info(adev->dev, "socket: %d, die: %d "
- "%ld correctable hardware errors "
- "detected in %s block, no user "
- "action is needed.\n",
- adev->smuio.funcs->get_socket_id(adev),
- adev->smuio.funcs->get_die_id(adev),
- obj->err_data.ce_count,
- get_ras_block_str(&info->head));
+ "%ld correctable hardware errors "
+ "detected in %s block, no user "
+ "action is needed.\n",
+ adev->smuio.funcs->get_socket_id(adev),
+ adev->smuio.funcs->get_die_id(adev),
+ ras_mgr->err_data.ce_count,
+ blk_name);
} else {
dev_info(adev->dev, "%ld correctable hardware errors "
- "detected in %s block, no user "
- "action is needed.\n",
- obj->err_data.ce_count,
- get_ras_block_str(&info->head));
+ "detected in %s block, no user "
+ "action is needed.\n",
+ ras_mgr->err_data.ce_count,
+ blk_name);
}
}
- if (err_data.ue_count) {
- if (!adev->aid_mask &&
- adev->smuio.funcs &&
- adev->smuio.funcs->get_socket_id &&
- adev->smuio.funcs->get_die_id) {
+
+ if (err_data->ue_count) {
+ if (err_data_has_source_info(err_data)) {
+ amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, blk_name, true);
+ } else if (!adev->aid_mask &&
+ adev->smuio.funcs &&
+ adev->smuio.funcs->get_socket_id &&
+ adev->smuio.funcs->get_die_id) {
dev_info(adev->dev, "socket: %d, die: %d "
- "%ld uncorrectable hardware errors "
- "detected in %s block\n",
- adev->smuio.funcs->get_socket_id(adev),
- adev->smuio.funcs->get_die_id(adev),
- obj->err_data.ue_count,
- get_ras_block_str(&info->head));
+ "%ld uncorrectable hardware errors "
+ "detected in %s block\n",
+ adev->smuio.funcs->get_socket_id(adev),
+ adev->smuio.funcs->get_die_id(adev),
+ ras_mgr->err_data.ue_count,
+ blk_name);
} else {
dev_info(adev->dev, "%ld uncorrectable hardware errors "
- "detected in %s block\n",
- obj->err_data.ue_count,
- get_ras_block_str(&info->head));
+ "detected in %s block\n",
+ ras_mgr->err_data.ue_count,
+ blk_name);
+ }
+ }
+
+}
+
+static void amdgpu_rasmgr_error_data_statistic_update(struct ras_manager *obj, struct ras_err_data *err_data)
+{
+ struct ras_err_node *err_node;
+ struct ras_err_info *err_info;
+
+ if (err_data_has_source_info(err_data)) {
+ for_each_ras_error(err_node, err_data) {
+ err_info = &err_node->err_info;
+
+ amdgpu_ras_error_statistic_ce_count(&obj->err_data, &err_info->mcm_info, err_info->ce_count);
+ amdgpu_ras_error_statistic_ue_count(&obj->err_data, &err_info->mcm_info, err_info->ue_count);
+ }
+ } else {
+ /* for legacy asic path which doesn't has error source info */
+ obj->err_data.ue_count += err_data->ue_count;
+ obj->err_data.ce_count += err_data->ce_count;
+ }
+}
+
+static int amdgpu_ras_query_error_status_helper(struct amdgpu_device *adev,
+ struct ras_query_if *info,
+ struct ras_err_data *err_data,
+ unsigned int error_query_mode)
+{
+ enum amdgpu_ras_block blk = info ? info->head.block : AMDGPU_RAS_BLOCK_COUNT;
+ struct amdgpu_ras_block_object *block_obj = NULL;
+
+ if (error_query_mode == AMDGPU_RAS_INVALID_ERROR_QUERY)
+ return -EINVAL;
+
+ if (error_query_mode == AMDGPU_RAS_DIRECT_ERROR_QUERY) {
+ if (info->head.block == AMDGPU_RAS_BLOCK__UMC) {
+ amdgpu_ras_get_ecc_info(adev, err_data);
+ } else {
+ block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, 0);
+ if (!block_obj || !block_obj->hw_ops) {
+ dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
+ get_ras_block_str(&info->head));
+ return -EINVAL;
+ }
+
+ if (block_obj->hw_ops->query_ras_error_count)
+ block_obj->hw_ops->query_ras_error_count(adev, err_data);
+
+ if ((info->head.block == AMDGPU_RAS_BLOCK__SDMA) ||
+ (info->head.block == AMDGPU_RAS_BLOCK__GFX) ||
+ (info->head.block == AMDGPU_RAS_BLOCK__MMHUB)) {
+ if (block_obj->hw_ops->query_ras_error_status)
+ block_obj->hw_ops->query_ras_error_status(adev);
+ }
}
+ } else {
+ /* FIXME: add code to check return value later */
+ amdgpu_mca_smu_log_ras_error(adev, blk, AMDGPU_MCA_ERROR_TYPE_UE, err_data);
+ amdgpu_mca_smu_log_ras_error(adev, blk, AMDGPU_MCA_ERROR_TYPE_CE, err_data);
}
return 0;
}
-int amdgpu_ras_reset_error_status(struct amdgpu_device *adev,
- enum amdgpu_ras_block block)
+/* query/inject/cure begin */
+int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_if *info)
{
- struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev, block, 0);
+ struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head);
+ struct ras_err_data err_data;
+ unsigned int error_query_mode;
+ int ret;
- if (!amdgpu_ras_is_supported(adev, block))
+ if (!obj)
return -EINVAL;
- if (!block_obj || !block_obj->hw_ops) {
- dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
- ras_block_str(block));
+ ret = amdgpu_ras_error_data_init(&err_data);
+ if (ret)
+ return ret;
+
+ if (!amdgpu_ras_get_error_query_mode(adev, &error_query_mode))
return -EINVAL;
+
+ ret = amdgpu_ras_query_error_status_helper(adev, info,
+ &err_data,
+ error_query_mode);
+ if (ret)
+ goto out_fini_err_data;
+
+ amdgpu_rasmgr_error_data_statistic_update(obj, &err_data);
+
+ info->ue_count = obj->err_data.ue_count;
+ info->ce_count = obj->err_data.ce_count;
+
+ amdgpu_ras_error_generate_report(adev, info, &err_data);
+
+out_fini_err_data:
+ amdgpu_ras_error_data_fini(&err_data);
+
+ return ret;
+}
+
+int amdgpu_ras_reset_error_count(struct amdgpu_device *adev,
+ enum amdgpu_ras_block block)
+{
+ struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev, block, 0);
+ struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
+ struct amdgpu_hive_info *hive;
+ int hive_ras_recovery = 0;
+
+ if (!block_obj || !block_obj->hw_ops) {
+ dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
+ ras_block_str(block));
+ return -EOPNOTSUPP;
}
+ if (!amdgpu_ras_is_supported(adev, block) ||
+ !amdgpu_ras_get_mca_debug_mode(adev))
+ return -EOPNOTSUPP;
+
+ hive = amdgpu_get_xgmi_hive(adev);
+ if (hive) {
+ hive_ras_recovery = atomic_read(&hive->ras_recovery);
+ amdgpu_put_xgmi_hive(hive);
+ }
+
+ /* skip ras error reset in gpu reset */
+ if ((amdgpu_in_reset(adev) || atomic_read(&ras->in_recovery) ||
+ hive_ras_recovery) &&
+ mca_funcs && mca_funcs->mca_set_debug_mode)
+ return -EOPNOTSUPP;
+
if (block_obj->hw_ops->reset_ras_error_count)
block_obj->hw_ops->reset_ras_error_count(adev);
+ return 0;
+}
+
+int amdgpu_ras_reset_error_status(struct amdgpu_device *adev,
+ enum amdgpu_ras_block block)
+{
+ struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev, block, 0);
+
+ if (amdgpu_ras_reset_error_count(adev, block) == -EOPNOTSUPP)
+ return 0;
+
if ((block == AMDGPU_RAS_BLOCK__GFX) ||
(block == AMDGPU_RAS_BLOCK__MMHUB)) {
if (block_obj->hw_ops->reset_ras_error_status)
@@ -1208,8 +1384,8 @@ static int amdgpu_ras_query_error_count_helper(struct amdgpu_device *adev,
/* some hardware/IP supports read to clear
* no need to explictly reset the err status after the query call */
- if (adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 2) &&
- adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 4)) {
+ if (amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(11, 0, 2) &&
+ amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(11, 0, 4)) {
if (amdgpu_ras_reset_error_status(adev, query_info->head.block))
dev_warn(adev->dev,
"Failed to reset error counter and error status\n");
@@ -1369,20 +1545,39 @@ static ssize_t amdgpu_ras_sysfs_features_read(struct device *dev,
return sysfs_emit(buf, "feature mask: 0x%x\n", con->features);
}
+static ssize_t amdgpu_ras_sysfs_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct amdgpu_ras *con =
+ container_of(attr, struct amdgpu_ras, version_attr);
+ return sysfs_emit(buf, "table version: 0x%x\n", con->eeprom_control.tbl_hdr.version);
+}
+
+static ssize_t amdgpu_ras_sysfs_schema_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct amdgpu_ras *con =
+ container_of(attr, struct amdgpu_ras, schema_attr);
+ return sysfs_emit(buf, "schema: 0x%x\n", con->schema);
+}
+
static void amdgpu_ras_sysfs_remove_bad_page_node(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
- sysfs_remove_file_from_group(&adev->dev->kobj,
+ if (adev->dev->kobj.sd)
+ sysfs_remove_file_from_group(&adev->dev->kobj,
&con->badpages_attr.attr,
RAS_FS_NAME);
}
-static int amdgpu_ras_sysfs_remove_feature_node(struct amdgpu_device *adev)
+static int amdgpu_ras_sysfs_remove_dev_attr_node(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
struct attribute *attrs[] = {
&con->features_attr.attr,
+ &con->version_attr.attr,
+ &con->schema_attr.attr,
NULL
};
struct attribute_group group = {
@@ -1390,7 +1585,8 @@ static int amdgpu_ras_sysfs_remove_feature_node(struct amdgpu_device *adev)
.attrs = attrs,
};
- sysfs_remove_group(&adev->dev->kobj, &group);
+ if (adev->dev->kobj.sd)
+ sysfs_remove_group(&adev->dev->kobj, &group);
return 0;
}
@@ -1437,7 +1633,8 @@ int amdgpu_ras_sysfs_remove(struct amdgpu_device *adev,
if (!obj || !obj->attr_inuse)
return -EINVAL;
- sysfs_remove_file_from_group(&adev->dev->kobj,
+ if (adev->dev->kobj.sd)
+ sysfs_remove_file_from_group(&adev->dev->kobj,
&obj->sysfs_attr.attr,
RAS_FS_NAME);
obj->attr_inuse = 0;
@@ -1458,7 +1655,7 @@ static int amdgpu_ras_sysfs_remove_all(struct amdgpu_device *adev)
if (amdgpu_bad_page_threshold != 0)
amdgpu_ras_sysfs_remove_bad_page_node(adev);
- amdgpu_ras_sysfs_remove_feature_node(adev);
+ amdgpu_ras_sysfs_remove_dev_attr_node(adev);
return 0;
}
@@ -1570,6 +1767,8 @@ void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev)
amdgpu_ras_debugfs_create(adev, &fs_info, dir);
}
}
+
+ amdgpu_mca_smu_debugfs_init(adev, dir);
}
/* debugfs end */
@@ -1579,6 +1778,10 @@ static BIN_ATTR(gpu_vram_bad_pages, S_IRUGO,
amdgpu_ras_sysfs_badpages_read, NULL, 0);
static DEVICE_ATTR(features, S_IRUGO,
amdgpu_ras_sysfs_features_read, NULL);
+static DEVICE_ATTR(version, 0444,
+ amdgpu_ras_sysfs_version_show, NULL);
+static DEVICE_ATTR(schema, 0444,
+ amdgpu_ras_sysfs_schema_show, NULL);
static int amdgpu_ras_fs_init(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
@@ -1587,6 +1790,8 @@ static int amdgpu_ras_fs_init(struct amdgpu_device *adev)
};
struct attribute *attrs[] = {
&con->features_attr.attr,
+ &con->version_attr.attr,
+ &con->schema_attr.attr,
NULL
};
struct bin_attribute *bin_attrs[] = {
@@ -1595,11 +1800,20 @@ static int amdgpu_ras_fs_init(struct amdgpu_device *adev)
};
int r;
+ group.attrs = attrs;
+
/* add features entry */
con->features_attr = dev_attr_features;
- group.attrs = attrs;
sysfs_attr_init(attrs[0]);
+ /* add version entry */
+ con->version_attr = dev_attr_version;
+ sysfs_attr_init(attrs[1]);
+
+ /* add schema entry */
+ con->schema_attr = dev_attr_schema;
+ sysfs_attr_init(attrs[2]);
+
if (amdgpu_bad_page_threshold != 0) {
/* add bad_page_features entry */
bin_attr_gpu_vram_bad_pages.private = NULL;
@@ -1708,12 +1922,16 @@ static void amdgpu_ras_interrupt_umc_handler(struct ras_manager *obj,
struct amdgpu_iv_entry *entry)
{
struct ras_ih_data *data = &obj->ih_data;
- struct ras_err_data err_data = {0, 0, 0, NULL};
+ struct ras_err_data err_data;
int ret;
if (!data->cb)
return;
+ ret = amdgpu_ras_error_data_init(&err_data);
+ if (ret)
+ return;
+
/* Let IP handle its data, maybe we need get the output
* from the callback to update the error type/count, etc
*/
@@ -1730,6 +1948,8 @@ static void amdgpu_ras_interrupt_umc_handler(struct ras_manager *obj,
obj->err_data.ue_count += err_data.ue_count;
obj->err_data.ce_count += err_data.ce_count;
}
+
+ amdgpu_ras_error_data_fini(&err_data);
}
static void amdgpu_ras_interrupt_handler(struct ras_manager *obj)
@@ -1905,14 +2125,18 @@ static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev)
* should be removed until smu fix handle ecc_info table.
*/
if ((info.head.block == AMDGPU_RAS_BLOCK__UMC) &&
- (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2)))
+ (amdgpu_ip_version(adev, MP1_HWIP, 0) ==
+ IP_VERSION(13, 0, 2)))
continue;
amdgpu_ras_query_error_status(adev, &info);
- if (adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 2) &&
- adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 4) &&
- adev->ip_versions[MP0_HWIP][0] != IP_VERSION(13, 0, 0)) {
+ if (amdgpu_ip_version(adev, MP0_HWIP, 0) !=
+ IP_VERSION(11, 0, 2) &&
+ amdgpu_ip_version(adev, MP0_HWIP, 0) !=
+ IP_VERSION(11, 0, 4) &&
+ amdgpu_ip_version(adev, MP0_HWIP, 0) !=
+ IP_VERSION(13, 0, 0)) {
if (amdgpu_ras_reset_error_status(adev, info.head.block))
dev_warn(adev->dev, "Failed to reset error counter and error status");
}
@@ -2021,9 +2245,11 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
struct amdgpu_device *remote_adev = NULL;
struct amdgpu_device *adev = ras->adev;
struct list_head device_list, *device_list_handle = NULL;
+ struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev);
+ if (hive)
+ atomic_set(&hive->ras_recovery, 1);
if (!ras->disable_ras_err_cnt_harvest) {
- struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev);
/* Build list of devices to query RAS related errors */
if (hive && adev->gmc.xgmi.num_physical_nodes > 1) {
@@ -2040,7 +2266,6 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
amdgpu_ras_log_on_err_counter(remote_adev);
}
- amdgpu_put_xgmi_hive(hive);
}
if (amdgpu_device_should_recover_gpu(ras->adev)) {
@@ -2075,6 +2300,10 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
amdgpu_device_gpu_recover(ras->adev, NULL, &reset_context);
}
atomic_set(&ras->in_recovery, 0);
+ if (hive) {
+ atomic_set(&hive->ras_recovery, 0);
+ amdgpu_put_xgmi_hive(hive);
+ }
}
/* alloc/realloc bps array */
@@ -2400,7 +2629,7 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev)
static bool amdgpu_ras_asic_supported(struct amdgpu_device *adev)
{
if (amdgpu_sriov_vf(adev)) {
- switch (adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
case IP_VERSION(13, 0, 2):
case IP_VERSION(13, 0, 6):
return true;
@@ -2410,7 +2639,7 @@ static bool amdgpu_ras_asic_supported(struct amdgpu_device *adev)
}
if (adev->asic_type == CHIP_IP_DISCOVERY) {
- switch (adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
case IP_VERSION(13, 0, 0):
case IP_VERSION(13, 0, 6):
case IP_VERSION(13, 0, 10):
@@ -2484,8 +2713,12 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev)
/* VCN/JPEG RAS can be supported on both bare metal and
* SRIOV environment
*/
- if (adev->ip_versions[VCN_HWIP][0] == IP_VERSION(2, 6, 0) ||
- adev->ip_versions[VCN_HWIP][0] == IP_VERSION(4, 0, 0))
+ if (amdgpu_ip_version(adev, VCN_HWIP, 0) ==
+ IP_VERSION(2, 6, 0) ||
+ amdgpu_ip_version(adev, VCN_HWIP, 0) ==
+ IP_VERSION(4, 0, 0) ||
+ amdgpu_ip_version(adev, VCN_HWIP, 0) ==
+ IP_VERSION(4, 0, 3))
adev->ras_hw_enabled |= (1 << AMDGPU_RAS_BLOCK__VCN |
1 << AMDGPU_RAS_BLOCK__JPEG);
else
@@ -2514,18 +2747,8 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev)
/* hw_supported needs to be aligned with RAS block mask. */
adev->ras_hw_enabled &= AMDGPU_RAS_BLOCK_MASK;
-
- /*
- * Disable ras feature for aqua vanjaram
- * by default on apu platform.
- */
- if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 6) &&
- adev->gmc.is_app_apu)
- adev->ras_enabled = amdgpu_ras_enable != 1 ? 0 :
- adev->ras_hw_enabled & amdgpu_ras_mask;
- else
- adev->ras_enabled = amdgpu_ras_enable == 0 ? 0 :
- adev->ras_hw_enabled & amdgpu_ras_mask;
+ adev->ras_enabled = amdgpu_ras_enable == 0 ? 0 :
+ adev->ras_hw_enabled & amdgpu_ras_mask;
}
static void amdgpu_ras_counte_dw(struct work_struct *work)
@@ -2563,7 +2786,8 @@ static void amdgpu_ras_query_poison_mode(struct amdgpu_device *adev)
return;
/* Init poison supported flag, the default value is false */
- if (adev->gmc.xgmi.connected_to_cpu) {
+ if (adev->gmc.xgmi.connected_to_cpu ||
+ adev->gmc.is_app_apu) {
/* enabled by default when GPU is connected to CPU */
con->poison_supported = true;
} else if (adev->df.funcs &&
@@ -2585,6 +2809,14 @@ static void amdgpu_ras_query_poison_mode(struct amdgpu_device *adev)
}
}
+static int amdgpu_get_ras_schema(struct amdgpu_device *adev)
+{
+ return amdgpu_ras_is_poison_mode_supported(adev) ? AMDGPU_RAS_ERROR__POISON : 0 |
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE |
+ AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE |
+ AMDGPU_RAS_ERROR__PARITY;
+}
+
int amdgpu_ras_init(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
@@ -2627,6 +2859,7 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
con->update_channel_flag = false;
con->features = 0;
+ con->schema = 0;
INIT_LIST_HEAD(&con->head);
/* Might need get this flag from vbios. */
con->flags = RAS_DEFAULT_FLAGS;
@@ -2634,7 +2867,7 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
/* initialize nbio ras function ahead of any other
* ras functions so hardware fatal error interrupt
* can be enabled as early as possible */
- switch (adev->ip_versions[NBIO_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
case IP_VERSION(7, 4, 0):
case IP_VERSION(7, 4, 1):
case IP_VERSION(7, 4, 4):
@@ -2682,6 +2915,9 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
amdgpu_ras_query_poison_mode(adev);
+ /* Get RAS schema for particular SOC */
+ con->schema = amdgpu_get_ras_schema(adev);
+
if (amdgpu_ras_fs_init(adev)) {
r = -EINVAL;
goto release_con;
@@ -3170,6 +3406,47 @@ int amdgpu_ras_reset_gpu(struct amdgpu_device *adev)
return 0;
}
+void amdgpu_ras_set_mca_debug_mode(struct amdgpu_device *adev, bool enable)
+{
+ struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+
+ if (con)
+ con->is_mca_debug_mode = enable;
+}
+
+bool amdgpu_ras_get_mca_debug_mode(struct amdgpu_device *adev)
+{
+ struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+ const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
+
+ if (!con)
+ return false;
+
+ if (mca_funcs && mca_funcs->mca_set_debug_mode)
+ return con->is_mca_debug_mode;
+ else
+ return true;
+}
+
+bool amdgpu_ras_get_error_query_mode(struct amdgpu_device *adev,
+ unsigned int *error_query_mode)
+{
+ struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+ const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
+
+ if (!con) {
+ *error_query_mode = AMDGPU_RAS_INVALID_ERROR_QUERY;
+ return false;
+ }
+
+ if (mca_funcs && mca_funcs->mca_set_debug_mode)
+ *error_query_mode =
+ (con->is_mca_debug_mode) ? AMDGPU_RAS_DIRECT_ERROR_QUERY : AMDGPU_RAS_FIRMWARE_ERROR_QUERY;
+ else
+ *error_query_mode = AMDGPU_RAS_DIRECT_ERROR_QUERY;
+
+ return true;
+}
/* Register each ip ras block into amdgpu ras */
int amdgpu_ras_register_ras_block(struct amdgpu_device *adev,
@@ -3329,3 +3606,141 @@ void amdgpu_ras_inst_reset_ras_error_count(struct amdgpu_device *adev,
WREG32(err_status_hi_offset, 0);
}
}
+
+int amdgpu_ras_error_data_init(struct ras_err_data *err_data)
+{
+ memset(err_data, 0, sizeof(*err_data));
+
+ INIT_LIST_HEAD(&err_data->err_node_list);
+
+ return 0;
+}
+
+static void amdgpu_ras_error_node_release(struct ras_err_node *err_node)
+{
+ if (!err_node)
+ return;
+
+ list_del(&err_node->node);
+ kvfree(err_node);
+}
+
+void amdgpu_ras_error_data_fini(struct ras_err_data *err_data)
+{
+ struct ras_err_node *err_node, *tmp;
+
+ list_for_each_entry_safe(err_node, tmp, &err_data->err_node_list, node)
+ amdgpu_ras_error_node_release(err_node);
+}
+
+static struct ras_err_node *amdgpu_ras_error_find_node_by_id(struct ras_err_data *err_data,
+ struct amdgpu_smuio_mcm_config_info *mcm_info)
+{
+ struct ras_err_node *err_node;
+ struct amdgpu_smuio_mcm_config_info *ref_id;
+
+ if (!err_data || !mcm_info)
+ return NULL;
+
+ for_each_ras_error(err_node, err_data) {
+ ref_id = &err_node->err_info.mcm_info;
+
+ if (mcm_info->socket_id == ref_id->socket_id &&
+ mcm_info->die_id == ref_id->die_id)
+ return err_node;
+ }
+
+ return NULL;
+}
+
+static struct ras_err_node *amdgpu_ras_error_node_new(void)
+{
+ struct ras_err_node *err_node;
+
+ err_node = kvzalloc(sizeof(*err_node), GFP_KERNEL);
+ if (!err_node)
+ return NULL;
+
+ INIT_LIST_HEAD(&err_node->node);
+
+ return err_node;
+}
+
+static int ras_err_info_cmp(void *priv, const struct list_head *a, const struct list_head *b)
+{
+ struct ras_err_node *nodea = container_of(a, struct ras_err_node, node);
+ struct ras_err_node *nodeb = container_of(b, struct ras_err_node, node);
+ struct amdgpu_smuio_mcm_config_info *infoa = &nodea->err_info.mcm_info;
+ struct amdgpu_smuio_mcm_config_info *infob = &nodeb->err_info.mcm_info;
+
+ if (unlikely(infoa->socket_id != infob->socket_id))
+ return infoa->socket_id - infob->socket_id;
+ else
+ return infoa->die_id - infob->die_id;
+
+ return 0;
+}
+
+static struct ras_err_info *amdgpu_ras_error_get_info(struct ras_err_data *err_data,
+ struct amdgpu_smuio_mcm_config_info *mcm_info)
+{
+ struct ras_err_node *err_node;
+
+ err_node = amdgpu_ras_error_find_node_by_id(err_data, mcm_info);
+ if (err_node)
+ return &err_node->err_info;
+
+ err_node = amdgpu_ras_error_node_new();
+ if (!err_node)
+ return NULL;
+
+ memcpy(&err_node->err_info.mcm_info, mcm_info, sizeof(*mcm_info));
+
+ err_data->err_list_count++;
+ list_add_tail(&err_node->node, &err_data->err_node_list);
+ list_sort(NULL, &err_data->err_node_list, ras_err_info_cmp);
+
+ return &err_node->err_info;
+}
+
+int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data,
+ struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count)
+{
+ struct ras_err_info *err_info;
+
+ if (!err_data || !mcm_info)
+ return -EINVAL;
+
+ if (!count)
+ return 0;
+
+ err_info = amdgpu_ras_error_get_info(err_data, mcm_info);
+ if (!err_info)
+ return -EINVAL;
+
+ err_info->ue_count += count;
+ err_data->ue_count += count;
+
+ return 0;
+}
+
+int amdgpu_ras_error_statistic_ce_count(struct ras_err_data *err_data,
+ struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count)
+{
+ struct ras_err_info *err_info;
+
+ if (!err_data || !mcm_info)
+ return -EINVAL;
+
+ if (!count)
+ return 0;
+
+ err_info = amdgpu_ras_error_get_info(err_data, mcm_info);
+ if (!err_info)
+ return -EINVAL;
+
+ err_info->ce_count += count;
+ err_data->ce_count += count;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
index ffb49b2d533a..19161916ac46 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
@@ -28,6 +28,7 @@
#include <linux/list.h>
#include "ta_ras_if.h"
#include "amdgpu_ras_eeprom.h"
+#include "amdgpu_smuio.h"
struct amdgpu_iv_entry;
@@ -319,6 +320,12 @@ enum amdgpu_ras_ret {
AMDGPU_RAS_PT,
};
+enum amdgpu_ras_error_query_mode {
+ AMDGPU_RAS_INVALID_ERROR_QUERY = 0,
+ AMDGPU_RAS_DIRECT_ERROR_QUERY = 1,
+ AMDGPU_RAS_FIRMWARE_ERROR_QUERY = 2,
+};
+
/* ras error status reisger fields */
#define ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
#define ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
@@ -389,9 +396,12 @@ struct amdgpu_ras {
/* ras infrastructure */
/* for ras itself. */
uint32_t features;
+ uint32_t schema;
struct list_head head;
/* sysfs */
struct device_attribute features_attr;
+ struct device_attribute version_attr;
+ struct device_attribute schema_attr;
struct bin_attribute badpages_attr;
struct dentry *de_ras_eeprom_table;
/* block array */
@@ -430,23 +440,41 @@ struct amdgpu_ras {
/* Indicates smu whether need update bad channel info */
bool update_channel_flag;
+ /* Record status of smu mca debug mode */
+ bool is_mca_debug_mode;
/* Record special requirements of gpu reset caller */
uint32_t gpu_reset_flags;
};
struct ras_fs_data {
- char sysfs_name[32];
+ char sysfs_name[48];
char debugfs_name[32];
};
+struct ras_err_info {
+ struct amdgpu_smuio_mcm_config_info mcm_info;
+ u64 ce_count;
+ u64 ue_count;
+};
+
+struct ras_err_node {
+ struct list_head node;
+ struct ras_err_info err_info;
+};
+
struct ras_err_data {
unsigned long ue_count;
unsigned long ce_count;
unsigned long err_addr_cnt;
struct eeprom_table_record *err_addr;
+ u32 err_list_count;
+ struct list_head err_node_list;
};
+#define for_each_ras_error(err_node, err_data) \
+ list_for_each_entry(err_node, &(err_data)->err_node_list, node)
+
struct ras_err_handler_data {
/* point to bad page records array */
struct eeprom_table_record *bps;
@@ -691,6 +719,8 @@ void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev);
int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
struct ras_query_if *info);
+int amdgpu_ras_reset_error_count(struct amdgpu_device *adev,
+ enum amdgpu_ras_block block);
int amdgpu_ras_reset_error_status(struct amdgpu_device *adev,
enum amdgpu_ras_block block);
@@ -743,6 +773,11 @@ struct amdgpu_ras* amdgpu_ras_get_context(struct amdgpu_device *adev);
int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras *ras_con);
+void amdgpu_ras_set_mca_debug_mode(struct amdgpu_device *adev, bool enable);
+bool amdgpu_ras_get_mca_debug_mode(struct amdgpu_device *adev);
+bool amdgpu_ras_get_error_query_mode(struct amdgpu_device *adev,
+ unsigned int *mode);
+
int amdgpu_ras_register_ras_block(struct amdgpu_device *adev,
struct amdgpu_ras_block_object *ras_block_obj);
void amdgpu_ras_interrupt_fatal_error_handler(struct amdgpu_device *adev);
@@ -767,4 +802,12 @@ void amdgpu_ras_inst_reset_ras_error_count(struct amdgpu_device *adev,
const struct amdgpu_ras_err_status_reg_entry *reg_list,
uint32_t reg_list_size,
uint32_t instance);
+
+int amdgpu_ras_error_data_init(struct ras_err_data *err_data);
+void amdgpu_ras_error_data_fini(struct ras_err_data *err_data);
+int amdgpu_ras_error_statistic_ce_count(struct ras_err_data *err_data,
+ struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count);
+int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data,
+ struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count);
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 595d5e535aca..2fde93b00cab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -149,11 +149,11 @@
RAS_TABLE_HEADER_SIZE - \
RAS_TABLE_V2_1_INFO_SIZE) / RAS_TABLE_RECORD_SIZE)
-#define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control))->adev
+#define to_amdgpu_device(x) ((container_of(x, struct amdgpu_ras, eeprom_control))->adev)
static bool __is_ras_eeprom_supported(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[MP1_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(11, 0, 2): /* VEGA20 and ARCTURUS */
case IP_VERSION(11, 0, 7): /* Sienna cichlid */
case IP_VERSION(13, 0, 0):
@@ -191,7 +191,7 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
return true;
}
- switch (adev->ip_versions[MP1_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(11, 0, 2):
/* VEGA20 and ARCTURUS */
if (adev->asic_type == CHIP_VEGA20)
@@ -214,6 +214,12 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
control->i2c_address = EEPROM_I2C_MADDR_0;
return true;
case IP_VERSION(13, 0, 0):
+ if (strnstr(atom_ctx->vbios_pn, "D707",
+ sizeof(atom_ctx->vbios_pn)))
+ control->i2c_address = EEPROM_I2C_MADDR_0;
+ else
+ control->i2c_address = EEPROM_I2C_MADDR_4;
+ return true;
case IP_VERSION(13, 0, 6):
case IP_VERSION(13, 0, 10):
control->i2c_address = EEPROM_I2C_MADDR_4;
@@ -616,7 +622,8 @@ amdgpu_ras_eeprom_append_table(struct amdgpu_ras_eeprom_control *control,
__encode_table_record_to_buf(control, &record[i], pp);
/* update bad channel bitmap */
- if (!(control->bad_channel_bitmap & (1 << record[i].mem_channel))) {
+ if ((record[i].mem_channel < BITS_PER_TYPE(control->bad_channel_bitmap)) &&
+ !(control->bad_channel_bitmap & (1 << record[i].mem_channel))) {
control->bad_channel_bitmap |= 1 << record[i].mem_channel;
con->update_channel_flag = true;
}
@@ -969,7 +976,8 @@ int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
__decode_table_record_from_buf(control, &record[i], pp);
/* update bad channel bitmap */
- if (!(control->bad_channel_bitmap & (1 << record[i].mem_channel))) {
+ if ((record[i].mem_channel < BITS_PER_TYPE(control->bad_channel_bitmap)) &&
+ !(control->bad_channel_bitmap & (1 << record[i].mem_channel))) {
control->bad_channel_bitmap |= 1 << record[i].mem_channel;
con->update_channel_flag = true;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
index 3c988cc406e4..381101d2bf05 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
@@ -112,7 +112,6 @@ fallback:
cur->remaining = size;
cur->node = NULL;
WARN_ON(res && start + size > res->size);
- return;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
index 5fed06ffcc6b..4baa300121d8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
@@ -21,24 +21,19 @@
*
*/
+#include <linux/devcoredump.h>
+#include <generated/utsrelease.h>
+
#include "amdgpu_reset.h"
#include "aldebaran.h"
#include "sienna_cichlid.h"
#include "smu_v13_0_10.h"
-int amdgpu_reset_add_handler(struct amdgpu_reset_control *reset_ctl,
- struct amdgpu_reset_handler *handler)
-{
- /* TODO: Check if handler exists? */
- list_add_tail(&handler->handler_list, &reset_ctl->reset_handlers);
- return 0;
-}
-
int amdgpu_reset_init(struct amdgpu_device *adev)
{
int ret = 0;
- switch (adev->ip_versions[MP1_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(13, 0, 2):
case IP_VERSION(13, 0, 6):
ret = aldebaran_reset_init(adev);
@@ -60,7 +55,7 @@ int amdgpu_reset_fini(struct amdgpu_device *adev)
{
int ret = 0;
- switch (adev->ip_versions[MP1_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(13, 0, 2):
case IP_VERSION(13, 0, 6):
ret = aldebaran_reset_fini(adev);
@@ -167,5 +162,82 @@ void amdgpu_device_unlock_reset_domain(struct amdgpu_reset_domain *reset_domain)
up_write(&reset_domain->sem);
}
+#ifndef CONFIG_DEV_COREDUMP
+void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost,
+ struct amdgpu_reset_context *reset_context)
+{
+}
+#else
+static ssize_t
+amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
+ void *data, size_t datalen)
+{
+ struct drm_printer p;
+ struct amdgpu_coredump_info *coredump = data;
+ struct drm_print_iterator iter;
+ int i;
+
+ iter.data = buffer;
+ iter.offset = 0;
+ iter.start = offset;
+ iter.remain = count;
+
+ p = drm_coredump_printer(&iter);
+
+ drm_printf(&p, "**** AMDGPU Device Coredump ****\n");
+ drm_printf(&p, "version: " AMDGPU_COREDUMP_VERSION "\n");
+ drm_printf(&p, "kernel: " UTS_RELEASE "\n");
+ drm_printf(&p, "module: " KBUILD_MODNAME "\n");
+ drm_printf(&p, "time: %lld.%09ld\n", coredump->reset_time.tv_sec,
+ coredump->reset_time.tv_nsec);
+
+ if (coredump->reset_task_info.pid)
+ drm_printf(&p, "process_name: %s PID: %d\n",
+ coredump->reset_task_info.process_name,
+ coredump->reset_task_info.pid);
+
+ if (coredump->reset_vram_lost)
+ drm_printf(&p, "VRAM is lost due to GPU reset!\n");
+ if (coredump->adev->reset_info.num_regs) {
+ drm_printf(&p, "AMDGPU register dumps:\nOffset: Value:\n");
+
+ for (i = 0; i < coredump->adev->reset_info.num_regs; i++)
+ drm_printf(&p, "0x%08x: 0x%08x\n",
+ coredump->adev->reset_info.reset_dump_reg_list[i],
+ coredump->adev->reset_info.reset_dump_reg_value[i]);
+ }
+
+ return count - iter.remain;
+}
+
+static void amdgpu_devcoredump_free(void *data)
+{
+ kfree(data);
+}
+
+void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost,
+ struct amdgpu_reset_context *reset_context)
+{
+ struct amdgpu_coredump_info *coredump;
+ struct drm_device *dev = adev_to_drm(adev);
+
+ coredump = kzalloc(sizeof(*coredump), GFP_NOWAIT);
+ if (!coredump) {
+ DRM_ERROR("%s: failed to allocate memory for coredump\n", __func__);
+ return;
+ }
+ coredump->reset_vram_lost = vram_lost;
+
+ if (reset_context->job && reset_context->job->vm)
+ coredump->reset_task_info = reset_context->job->vm->task_info;
+
+ coredump->adev = adev;
+
+ ktime_get_ts64(&coredump->reset_time);
+
+ dev_coredumpm(dev->dev, THIS_MODULE, coredump, 0, GFP_NOWAIT,
+ amdgpu_devcoredump_read, amdgpu_devcoredump_free);
+}
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
index f4a501ff87d9..b0335a1c5e90 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
@@ -26,6 +26,8 @@
#include "amdgpu.h"
+#define AMDGPU_RESET_MAX_HANDLERS 5
+
enum AMDGPU_RESET_FLAGS {
AMDGPU_NEED_FULL_RESET = 0,
@@ -44,7 +46,6 @@ struct amdgpu_reset_context {
struct amdgpu_reset_handler {
enum amd_reset_method reset_method;
- struct list_head handler_list;
int (*prepare_env)(struct amdgpu_reset_control *reset_ctl,
struct amdgpu_reset_context *context);
int (*prepare_hwcontext)(struct amdgpu_reset_control *reset_ctl,
@@ -63,7 +64,8 @@ struct amdgpu_reset_control {
void *handle;
struct work_struct reset_work;
struct mutex reset_lock;
- struct list_head reset_handlers;
+ struct amdgpu_reset_handler *(
+ *reset_handlers)[AMDGPU_RESET_MAX_HANDLERS];
atomic_t in_reset;
enum amd_reset_method active_reset;
struct amdgpu_reset_handler *(*get_reset_handler)(
@@ -87,6 +89,17 @@ struct amdgpu_reset_domain {
atomic_t reset_res;
};
+#ifdef CONFIG_DEV_COREDUMP
+
+#define AMDGPU_COREDUMP_VERSION "1"
+
+struct amdgpu_coredump_info {
+ struct amdgpu_device *adev;
+ struct amdgpu_task_info reset_task_info;
+ struct timespec64 reset_time;
+ bool reset_vram_lost;
+};
+#endif
int amdgpu_reset_init(struct amdgpu_device *adev);
int amdgpu_reset_fini(struct amdgpu_device *adev);
@@ -97,8 +110,10 @@ int amdgpu_reset_prepare_hwcontext(struct amdgpu_device *adev,
int amdgpu_reset_perform_reset(struct amdgpu_device *adev,
struct amdgpu_reset_context *reset_context);
-int amdgpu_reset_add_handler(struct amdgpu_reset_control *reset_ctl,
- struct amdgpu_reset_handler *handler);
+int amdgpu_reset_prepare_env(struct amdgpu_device *adev,
+ struct amdgpu_reset_context *reset_context);
+int amdgpu_reset_restore_env(struct amdgpu_device *adev,
+ struct amdgpu_reset_context *reset_context);
struct amdgpu_reset_domain *amdgpu_reset_create_reset_domain(enum amdgpu_reset_domain_type type,
char *wq_name);
@@ -126,4 +141,11 @@ void amdgpu_device_lock_reset_domain(struct amdgpu_reset_domain *reset_domain);
void amdgpu_device_unlock_reset_domain(struct amdgpu_reset_domain *reset_domain);
+void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost,
+ struct amdgpu_reset_context *reset_context);
+
+#define for_each_handler(i, handler, reset_ctl) \
+ for (i = 0; (i < AMDGPU_RESET_MAX_HANDLERS) && \
+ (handler = (*reset_ctl->reset_handlers)[i]); \
+ ++i)
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index 80d6e132e409..6a80d3ec887e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -434,8 +434,12 @@ bool amdgpu_ring_soft_recovery(struct amdgpu_ring *ring, unsigned int vmid,
struct dma_fence *fence)
{
unsigned long flags;
+ ktime_t deadline;
- ktime_t deadline = ktime_add_us(ktime_get(), 10000);
+ if (unlikely(ring->adev->debug_disable_soft_recovery))
+ return false;
+
+ deadline = ktime_add_us(ktime_get(), 10000);
if (amdgpu_sriov_vf(ring->adev) || !ring->funcs->soft_recovery || !fence)
return false;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index e2ab303ad270..bbb53720a018 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -44,6 +44,7 @@ struct amdgpu_vm;
#define AMDGPU_MAX_COMPUTE_RINGS 8
#define AMDGPU_MAX_VCE_RINGS 3
#define AMDGPU_MAX_UVD_ENC_RINGS 2
+#define AMDGPU_MAX_VPE_RINGS 2
enum amdgpu_ring_priority_level {
AMDGPU_RING_PRIO_0,
@@ -77,8 +78,10 @@ enum amdgpu_ring_type {
AMDGPU_RING_TYPE_VCN_DEC = AMDGPU_HW_IP_VCN_DEC,
AMDGPU_RING_TYPE_VCN_ENC = AMDGPU_HW_IP_VCN_ENC,
AMDGPU_RING_TYPE_VCN_JPEG = AMDGPU_HW_IP_VCN_JPEG,
+ AMDGPU_RING_TYPE_VPE = AMDGPU_HW_IP_VPE,
AMDGPU_RING_TYPE_KIQ,
- AMDGPU_RING_TYPE_MES
+ AMDGPU_RING_TYPE_MES,
+ AMDGPU_RING_TYPE_UMSCH_MM,
};
enum amdgpu_ib_pool_type {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index e2b9392d7f0d..1d9d187de6ee 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -208,7 +208,7 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
const struct sdma_firmware_header_v2_0 *sdma_hdr;
uint16_t version_major;
char ucode_prefix[30];
- char fw_name[40];
+ char fw_name[52];
amdgpu_ucode_ip_version_decode(adev, SDMA0_HWIP, ucode_prefix, sizeof(ucode_prefix));
if (instance == 0)
@@ -251,8 +251,11 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
else {
/* Use a single copy per SDMA firmware type. PSP uses the same instance for all
* groups of SDMAs */
- if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 4, 2) &&
- adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
+ if (amdgpu_ip_version(adev, SDMA0_HWIP,
+ 0) ==
+ IP_VERSION(4, 4, 2) &&
+ adev->firmware.load_type ==
+ AMDGPU_FW_LOAD_PSP &&
adev->sdma.num_inst_per_aid == i) {
break;
}
@@ -289,27 +292,6 @@ out:
return err;
}
-void amdgpu_sdma_unset_buffer_funcs_helper(struct amdgpu_device *adev)
-{
- struct amdgpu_ring *sdma;
- int i;
-
- for (i = 0; i < adev->sdma.num_instances; i++) {
- if (adev->sdma.has_page_queue) {
- sdma = &adev->sdma.instance[i].page;
- if (adev->mman.buffer_funcs_ring == sdma) {
- amdgpu_ttm_set_buffer_funcs_status(adev, false);
- break;
- }
- }
- sdma = &adev->sdma.instance[i].ring;
- if (adev->mman.buffer_funcs_ring == sdma) {
- amdgpu_ttm_set_buffer_funcs_status(adev, false);
- break;
- }
- }
-}
-
int amdgpu_sdma_ras_sw_init(struct amdgpu_device *adev)
{
int err = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
index 513ac22120c1..173a2a308078 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
@@ -169,7 +169,6 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev, u32 instance,
bool duplicate);
void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev,
bool duplicate);
-void amdgpu_sdma_unset_buffer_funcs_helper(struct amdgpu_device *adev);
int amdgpu_sdma_ras_sw_init(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h
index 89c38d864471..ff4435181055 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h
@@ -23,6 +23,18 @@
#ifndef __AMDGPU_SMUIO_H__
#define __AMDGPU_SMUIO_H__
+enum amdgpu_pkg_type {
+ AMDGPU_PKG_TYPE_APU = 2,
+ AMDGPU_PKG_TYPE_CEM = 3,
+ AMDGPU_PKG_TYPE_OAM = 4,
+ AMDGPU_PKG_TYPE_UNKNOWN,
+};
+
+struct amdgpu_smuio_mcm_config_info {
+ int socket_id;
+ int die_id;
+};
+
struct amdgpu_smuio_funcs {
u32 (*get_rom_index_offset)(struct amdgpu_device *adev);
u32 (*get_rom_data_offset)(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 4e51dce3aab5..ab4a762aed5b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -959,10 +959,8 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo)
return 0;
addr = amdgpu_gmc_agp_addr(bo);
- if (addr != AMDGPU_BO_INVALID_OFFSET) {
- bo->resource->start = addr >> PAGE_SHIFT;
+ if (addr != AMDGPU_BO_INVALID_OFFSET)
return 0;
- }
/* allocate GART space */
placement.num_placement = 1;
@@ -1727,7 +1725,8 @@ static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev)
reserve_size =
amdgpu_atomfirmware_get_fw_reserved_fb_size(adev);
- if (!adev->bios && adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
+ if (!adev->bios &&
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3))
reserve_size = max(reserve_size, (uint32_t)280 << 20);
else if (!reserve_size)
reserve_size = DISCOVERY_TMR_OFFSET;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index 8beefc045e14..b14127429f30 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -642,6 +642,8 @@ const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id)
return "SMC";
case AMDGPU_UCODE_ID_PPTABLE:
return "PPTABLE";
+ case AMDGPU_UCODE_ID_P2S_TABLE:
+ return "P2STABLE";
case AMDGPU_UCODE_ID_UVD:
return "UVD";
case AMDGPU_UCODE_ID_UVD1:
@@ -664,20 +666,42 @@ const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id)
return "DMCUB";
case AMDGPU_UCODE_ID_CAP:
return "CAP";
+ case AMDGPU_UCODE_ID_VPE_CTX:
+ return "VPE_CTX";
+ case AMDGPU_UCODE_ID_VPE_CTL:
+ return "VPE_CTL";
+ case AMDGPU_UCODE_ID_VPE:
+ return "VPE";
+ case AMDGPU_UCODE_ID_UMSCH_MM_UCODE:
+ return "UMSCH_MM_UCODE";
+ case AMDGPU_UCODE_ID_UMSCH_MM_DATA:
+ return "UMSCH_MM_DATA";
+ case AMDGPU_UCODE_ID_UMSCH_MM_CMD_BUFFER:
+ return "UMSCH_MM_CMD_BUFFER";
default:
return "UNKNOWN UCODE";
}
}
+static inline int amdgpu_ucode_is_valid(uint32_t fw_version)
+{
+ if (!fw_version)
+ return -EINVAL;
+
+ return 0;
+}
+
#define FW_VERSION_ATTR(name, mode, field) \
static ssize_t show_##name(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
+ struct device_attribute *attr, char *buf) \
{ \
struct drm_device *ddev = dev_get_drvdata(dev); \
struct amdgpu_device *adev = drm_to_adev(ddev); \
\
- return sysfs_emit(buf, "0x%08x\n", adev->field); \
+ if (!buf) \
+ return amdgpu_ucode_is_valid(adev->field); \
+ \
+ return sysfs_emit(buf, "0x%08x\n", adev->field); \
} \
static DEVICE_ATTR(name, mode, show_##name, NULL)
@@ -722,9 +746,24 @@ static struct attribute *fw_attrs[] = {
NULL
};
+#define to_dev_attr(x) container_of(x, struct device_attribute, attr)
+
+static umode_t amdgpu_ucode_sys_visible(struct kobject *kobj,
+ struct attribute *attr, int idx)
+{
+ struct device_attribute *dev_attr = to_dev_attr(attr);
+ struct device *dev = kobj_to_dev(kobj);
+
+ if (dev_attr->show(dev, dev_attr, NULL) == -EINVAL)
+ return 0;
+
+ return attr->mode;
+}
+
static const struct attribute_group fw_attr_group = {
.name = "fw_version",
- .attrs = fw_attrs
+ .attrs = fw_attrs,
+ .is_visible = amdgpu_ucode_sys_visible
};
int amdgpu_ucode_sysfs_init(struct amdgpu_device *adev)
@@ -749,6 +788,8 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
const struct mes_firmware_header_v1_0 *mes_hdr = NULL;
const struct sdma_firmware_header_v2_0 *sdma_hdr = NULL;
const struct imu_firmware_header_v1_0 *imu_hdr = NULL;
+ const struct vpe_firmware_header_v1_0 *vpe_hdr = NULL;
+ const struct umsch_mm_firmware_header_v1_0 *umsch_mm_hdr = NULL;
u8 *ucode_addr;
if (!ucode->fw)
@@ -768,6 +809,8 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
mes_hdr = (const struct mes_firmware_header_v1_0 *)ucode->fw->data;
sdma_hdr = (const struct sdma_firmware_header_v2_0 *)ucode->fw->data;
imu_hdr = (const struct imu_firmware_header_v1_0 *)ucode->fw->data;
+ vpe_hdr = (const struct vpe_firmware_header_v1_0 *)ucode->fw->data;
+ umsch_mm_hdr = (const struct umsch_mm_firmware_header_v1_0 *)ucode->fw->data;
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
switch (ucode->ucode_id) {
@@ -884,6 +927,10 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
ucode->ucode_size = ucode->fw->size;
ucode_addr = (u8 *)ucode->fw->data;
break;
+ case AMDGPU_UCODE_ID_P2S_TABLE:
+ ucode->ucode_size = ucode->fw->size;
+ ucode_addr = (u8 *)ucode->fw->data;
+ break;
case AMDGPU_UCODE_ID_IMU_I:
ucode->ucode_size = le32_to_cpu(imu_hdr->imu_iram_ucode_size_bytes);
ucode_addr = (u8 *)ucode->fw->data +
@@ -950,6 +997,26 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
ucode_addr = (u8 *)ucode->fw->data +
le32_to_cpu(cpv2_hdr->data_offset_bytes);
break;
+ case AMDGPU_UCODE_ID_VPE_CTX:
+ ucode->ucode_size = le32_to_cpu(vpe_hdr->ctx_ucode_size_bytes);
+ ucode_addr = (u8 *)ucode->fw->data +
+ le32_to_cpu(vpe_hdr->header.ucode_array_offset_bytes);
+ break;
+ case AMDGPU_UCODE_ID_VPE_CTL:
+ ucode->ucode_size = le32_to_cpu(vpe_hdr->ctl_ucode_size_bytes);
+ ucode_addr = (u8 *)ucode->fw->data +
+ le32_to_cpu(vpe_hdr->ctl_ucode_offset);
+ break;
+ case AMDGPU_UCODE_ID_UMSCH_MM_UCODE:
+ ucode->ucode_size = le32_to_cpu(umsch_mm_hdr->umsch_mm_ucode_size_bytes);
+ ucode_addr = (u8 *)ucode->fw->data +
+ le32_to_cpu(umsch_mm_hdr->header.ucode_array_offset_bytes);
+ break;
+ case AMDGPU_UCODE_ID_UMSCH_MM_DATA:
+ ucode->ucode_size = le32_to_cpu(umsch_mm_hdr->umsch_mm_ucode_data_size_bytes);
+ ucode_addr = (u8 *)ucode->fw->data +
+ le32_to_cpu(umsch_mm_hdr->umsch_mm_ucode_data_offset_bytes);
+ break;
default:
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes);
ucode_addr = (u8 *)ucode->fw->data +
@@ -1061,7 +1128,7 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
static const char *amdgpu_ucode_legacy_naming(struct amdgpu_device *adev, int block_type)
{
if (block_type == MP0_HWIP) {
- switch (adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
case IP_VERSION(9, 0, 0):
switch (adev->asic_type) {
case CHIP_VEGA10:
@@ -1112,7 +1179,7 @@ static const char *amdgpu_ucode_legacy_naming(struct amdgpu_device *adev, int bl
return "yellow_carp";
}
} else if (block_type == MP1_HWIP) {
- switch (adev->ip_versions[MP1_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(9, 0, 0):
case IP_VERSION(10, 0, 0):
case IP_VERSION(10, 0, 1):
@@ -1138,7 +1205,7 @@ static const char *amdgpu_ucode_legacy_naming(struct amdgpu_device *adev, int bl
return "aldebaran_smc";
}
} else if (block_type == SDMA0_HWIP) {
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
return "vega10_sdma";
case IP_VERSION(4, 0, 1):
@@ -1182,7 +1249,7 @@ static const char *amdgpu_ucode_legacy_naming(struct amdgpu_device *adev, int bl
return "vangogh_sdma";
}
} else if (block_type == UVD_HWIP) {
- switch (adev->ip_versions[UVD_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, UVD_HWIP, 0)) {
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
@@ -1207,7 +1274,8 @@ static const char *amdgpu_ucode_legacy_naming(struct amdgpu_device *adev, int bl
case IP_VERSION(3, 0, 0):
case IP_VERSION(3, 0, 64):
case IP_VERSION(3, 0, 192):
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(10, 3, 0))
return "sienna_cichlid_vcn";
return "navy_flounder_vcn";
case IP_VERSION(3, 0, 2):
@@ -1220,7 +1288,7 @@ static const char *amdgpu_ucode_legacy_naming(struct amdgpu_device *adev, int bl
return "yellow_carp_vcn";
}
} else if (block_type == GC_HWIP) {
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
return "vega10";
case IP_VERSION(9, 2, 1):
@@ -1273,7 +1341,7 @@ void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type,
int maj, min, rev;
char *ip_name;
const char *legacy;
- uint32_t version = adev->ip_versions[block_type][0];
+ uint32_t version = amdgpu_ip_version(adev, block_type, 0);
legacy = amdgpu_ucode_legacy_naming(adev, block_type);
if (legacy) {
@@ -1297,6 +1365,9 @@ void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type,
case UVD_HWIP:
ip_name = "vcn";
break;
+ case VPE_HWIP:
+ ip_name = "vpe";
+ break;
default:
BUG();
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index b03321e7d2d8..4244a13f9f22 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -315,6 +315,36 @@ struct sdma_firmware_header_v2_0 {
uint32_t ctl_jt_size; /* control thread size of jt */
};
+/* version_major=1, version_minor=0 */
+struct vpe_firmware_header_v1_0 {
+ struct common_firmware_header header;
+ uint32_t ucode_feature_version;
+ uint32_t ctx_ucode_size_bytes; /* context thread ucode size */
+ uint32_t ctx_jt_offset; /* context thread jt location */
+ uint32_t ctx_jt_size; /* context thread size of jt */
+ uint32_t ctl_ucode_offset;
+ uint32_t ctl_ucode_size_bytes; /* control thread ucode size */
+ uint32_t ctl_jt_offset; /* control thread jt location */
+ uint32_t ctl_jt_size; /* control thread size of jt */
+};
+
+/* version_major=1, version_minor=0 */
+struct umsch_mm_firmware_header_v1_0 {
+ struct common_firmware_header header;
+ uint32_t umsch_mm_ucode_version;
+ uint32_t umsch_mm_ucode_size_bytes;
+ uint32_t umsch_mm_ucode_offset_bytes;
+ uint32_t umsch_mm_ucode_data_version;
+ uint32_t umsch_mm_ucode_data_size_bytes;
+ uint32_t umsch_mm_ucode_data_offset_bytes;
+ uint32_t umsch_mm_irq_start_addr_lo;
+ uint32_t umsch_mm_irq_start_addr_hi;
+ uint32_t umsch_mm_uc_start_addr_lo;
+ uint32_t umsch_mm_uc_start_addr_hi;
+ uint32_t umsch_mm_data_start_addr_lo;
+ uint32_t umsch_mm_data_start_addr_hi;
+};
+
/* gpu info payload */
struct gpu_info_firmware_v1_0 {
uint32_t gc_num_se;
@@ -474,6 +504,13 @@ enum AMDGPU_UCODE_ID {
AMDGPU_UCODE_ID_VCN0_RAM,
AMDGPU_UCODE_ID_VCN1_RAM,
AMDGPU_UCODE_ID_DMCUB,
+ AMDGPU_UCODE_ID_VPE_CTX,
+ AMDGPU_UCODE_ID_VPE_CTL,
+ AMDGPU_UCODE_ID_VPE,
+ AMDGPU_UCODE_ID_UMSCH_MM_UCODE,
+ AMDGPU_UCODE_ID_UMSCH_MM_DATA,
+ AMDGPU_UCODE_ID_UMSCH_MM_CMD_BUFFER,
+ AMDGPU_UCODE_ID_P2S_TABLE,
AMDGPU_UCODE_ID_MAXIMUM,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
index db0d94ca4ffc..d65e21914d8c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
@@ -28,7 +28,7 @@ static int amdgpu_umc_convert_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data, uint64_t err_addr,
uint32_t ch_inst, uint32_t umc_inst)
{
- switch (adev->ip_versions[UMC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, UMC_HWIP, 0)) {
case IP_VERSION(6, 7, 0):
umc_v6_7_convert_error_address(adev,
err_data, err_addr, ch_inst, umc_inst);
@@ -45,8 +45,12 @@ static int amdgpu_umc_convert_error_address(struct amdgpu_device *adev,
int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev,
uint64_t err_addr, uint32_t ch_inst, uint32_t umc_inst)
{
- struct ras_err_data err_data = {0, 0, 0, NULL};
- int ret = AMDGPU_RAS_FAIL;
+ struct ras_err_data err_data;
+ int ret;
+
+ ret = amdgpu_ras_error_data_init(&err_data);
+ if (ret)
+ return ret;
err_data.err_addr =
kcalloc(adev->umc.max_ras_err_cnt_per_query,
@@ -54,7 +58,8 @@ int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev,
if (!err_data.err_addr) {
dev_warn(adev->dev,
"Failed to alloc memory for umc error record in MCA notifier!\n");
- return AMDGPU_RAS_FAIL;
+ ret = AMDGPU_RAS_FAIL;
+ goto out_fini_err_data;
}
/*
@@ -63,7 +68,7 @@ int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev,
ret = amdgpu_umc_convert_error_address(adev, &err_data, err_addr,
ch_inst, umc_inst);
if (ret)
- goto out;
+ goto out_free_err_addr;
if (amdgpu_bad_page_threshold != 0) {
amdgpu_ras_add_bad_pages(adev, err_data.err_addr,
@@ -71,8 +76,12 @@ int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev,
amdgpu_ras_save_bad_pages(adev, NULL);
}
-out:
+out_free_err_addr:
kfree(err_data.err_addr);
+
+out_fini_err_data:
+ amdgpu_ras_error_data_fini(&err_data);
+
return ret;
}
@@ -157,8 +166,12 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
}
}
- if (reset)
+ if (reset) {
+ /* use mode-2 reset for poison consumption */
+ if (!entry)
+ con->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE2_RESET;
amdgpu_ras_reset_gpu(adev);
+ }
}
kfree(err_data->err_addr);
@@ -182,18 +195,24 @@ int amdgpu_umc_poison_handler(struct amdgpu_device *adev, bool reset)
}
if (!amdgpu_sriov_vf(adev)) {
- struct ras_err_data err_data = {0, 0, 0, NULL};
+ struct ras_err_data err_data;
struct ras_common_if head = {
.block = AMDGPU_RAS_BLOCK__UMC,
};
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head);
+ ret = amdgpu_ras_error_data_init(&err_data);
+ if (ret)
+ return ret;
+
ret = amdgpu_umc_do_page_retirement(adev, &err_data, NULL, reset);
if (ret == AMDGPU_RAS_SUCCESS && obj) {
obj->err_data.ue_count += err_data.ue_count;
obj->err_data.ce_count += err_data.ce_count;
}
+
+ amdgpu_ras_error_data_fini(&err_data);
} else {
if (adev->virt.ops && adev->virt.ops->ras_poison_handler)
adev->virt.ops->ras_poison_handler(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
index 43321f57f557..417a6726c71b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
@@ -32,6 +32,11 @@
* is the index of 8KB block
*/
#define ADDR_OF_8KB_BLOCK(addr) (((addr) & ~0xffULL) << 5)
+/*
+ * (addr / 256) * 32768, the higher 26 bits in ErrorAddr
+ * is the index of 8KB block
+ */
+#define ADDR_OF_32KB_BLOCK(addr) (((addr) & ~0xffULL) << 7)
/* channel index is the index of 256B block */
#define ADDR_OF_256B_BLOCK(channel_index) ((channel_index) << 8)
/* offset in 256B block */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c
new file mode 100644
index 000000000000..ca45ba8ac171
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c
@@ -0,0 +1,878 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/firmware.h>
+#include <drm/drm_exec.h>
+
+#include "amdgpu.h"
+#include "amdgpu_umsch_mm.h"
+#include "umsch_mm_v4_0.h"
+
+struct umsch_mm_test_ctx_data {
+ uint8_t process_csa[PAGE_SIZE];
+ uint8_t vpe_ctx_csa[PAGE_SIZE];
+ uint8_t vcn_ctx_csa[PAGE_SIZE];
+};
+
+struct umsch_mm_test_mqd_data {
+ uint8_t vpe_mqd[PAGE_SIZE];
+ uint8_t vcn_mqd[PAGE_SIZE];
+};
+
+struct umsch_mm_test_ring_data {
+ uint8_t vpe_ring[PAGE_SIZE];
+ uint8_t vpe_ib[PAGE_SIZE];
+ uint8_t vcn_ring[PAGE_SIZE];
+ uint8_t vcn_ib[PAGE_SIZE];
+};
+
+struct umsch_mm_test_queue_info {
+ uint64_t mqd_addr;
+ uint64_t csa_addr;
+ uint32_t doorbell_offset_0;
+ uint32_t doorbell_offset_1;
+ enum UMSCH_SWIP_ENGINE_TYPE engine;
+};
+
+struct umsch_mm_test {
+ struct amdgpu_bo *ctx_data_obj;
+ uint64_t ctx_data_gpu_addr;
+ uint32_t *ctx_data_cpu_addr;
+
+ struct amdgpu_bo *mqd_data_obj;
+ uint64_t mqd_data_gpu_addr;
+ uint32_t *mqd_data_cpu_addr;
+
+ struct amdgpu_bo *ring_data_obj;
+ uint64_t ring_data_gpu_addr;
+ uint32_t *ring_data_cpu_addr;
+
+
+ struct amdgpu_vm *vm;
+ struct amdgpu_bo_va *bo_va;
+ uint32_t pasid;
+ uint32_t vm_cntx_cntl;
+ uint32_t num_queues;
+};
+
+static int map_ring_data(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ struct amdgpu_bo *bo, struct amdgpu_bo_va **bo_va,
+ uint64_t addr, uint32_t size)
+{
+ struct amdgpu_sync sync;
+ struct drm_exec exec;
+ int r;
+
+ amdgpu_sync_create(&sync);
+
+ drm_exec_init(&exec, 0);
+ drm_exec_until_all_locked(&exec) {
+ r = drm_exec_lock_obj(&exec, &bo->tbo.base);
+ drm_exec_retry_on_contention(&exec);
+ if (unlikely(r))
+ goto error_fini_exec;
+
+ r = amdgpu_vm_lock_pd(vm, &exec, 0);
+ drm_exec_retry_on_contention(&exec);
+ if (unlikely(r))
+ goto error_fini_exec;
+ }
+
+ *bo_va = amdgpu_vm_bo_add(adev, vm, bo);
+ if (!*bo_va) {
+ r = -ENOMEM;
+ goto error_fini_exec;
+ }
+
+ r = amdgpu_vm_bo_map(adev, *bo_va, addr, 0, size,
+ AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE |
+ AMDGPU_PTE_EXECUTABLE);
+
+ if (r)
+ goto error_del_bo_va;
+
+
+ r = amdgpu_vm_bo_update(adev, *bo_va, false);
+ if (r)
+ goto error_del_bo_va;
+
+ amdgpu_sync_fence(&sync, (*bo_va)->last_pt_update);
+
+ r = amdgpu_vm_update_pdes(adev, vm, false);
+ if (r)
+ goto error_del_bo_va;
+
+ amdgpu_sync_fence(&sync, vm->last_update);
+
+ amdgpu_sync_wait(&sync, false);
+ drm_exec_fini(&exec);
+
+ amdgpu_sync_free(&sync);
+
+ return 0;
+
+error_del_bo_va:
+ amdgpu_vm_bo_del(adev, *bo_va);
+ amdgpu_sync_free(&sync);
+
+error_fini_exec:
+ drm_exec_fini(&exec);
+ amdgpu_sync_free(&sync);
+ return r;
+}
+
+static int unmap_ring_data(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ struct amdgpu_bo *bo, struct amdgpu_bo_va *bo_va,
+ uint64_t addr)
+{
+ struct drm_exec exec;
+ long r;
+
+ drm_exec_init(&exec, 0);
+ drm_exec_until_all_locked(&exec) {
+ r = drm_exec_lock_obj(&exec, &bo->tbo.base);
+ drm_exec_retry_on_contention(&exec);
+ if (unlikely(r))
+ goto out_unlock;
+
+ r = amdgpu_vm_lock_pd(vm, &exec, 0);
+ drm_exec_retry_on_contention(&exec);
+ if (unlikely(r))
+ goto out_unlock;
+ }
+
+
+ r = amdgpu_vm_bo_unmap(adev, bo_va, addr);
+ if (r)
+ goto out_unlock;
+
+ amdgpu_vm_bo_del(adev, bo_va);
+
+out_unlock:
+ drm_exec_fini(&exec);
+
+ return r;
+}
+
+static void setup_vpe_queue(struct amdgpu_device *adev,
+ struct umsch_mm_test *test,
+ struct umsch_mm_test_queue_info *qinfo)
+{
+ struct MQD_INFO *mqd = (struct MQD_INFO *)test->mqd_data_cpu_addr;
+ uint64_t ring_gpu_addr = test->ring_data_gpu_addr;
+
+ mqd->rb_base_lo = (ring_gpu_addr >> 8);
+ mqd->rb_base_hi = (ring_gpu_addr >> 40);
+ mqd->rb_size = PAGE_SIZE / 4;
+ mqd->wptr_val = 0;
+ mqd->rptr_val = 0;
+ mqd->unmapped = 1;
+
+ qinfo->mqd_addr = test->mqd_data_gpu_addr;
+ qinfo->csa_addr = test->ctx_data_gpu_addr +
+ offsetof(struct umsch_mm_test_ctx_data, vpe_ctx_csa);
+ qinfo->doorbell_offset_0 = (adev->doorbell_index.vpe_ring + 1) << 1;
+ qinfo->doorbell_offset_1 = 0;
+}
+
+static void setup_vcn_queue(struct amdgpu_device *adev,
+ struct umsch_mm_test *test,
+ struct umsch_mm_test_queue_info *qinfo)
+{
+}
+
+static int add_test_queue(struct amdgpu_device *adev,
+ struct umsch_mm_test *test,
+ struct umsch_mm_test_queue_info *qinfo)
+{
+ struct umsch_mm_add_queue_input queue_input = {};
+ int r;
+
+ queue_input.process_id = test->pasid;
+ queue_input.page_table_base_addr = amdgpu_gmc_pd_addr(test->vm->root.bo);
+
+ queue_input.process_va_start = 0;
+ queue_input.process_va_end = (adev->vm_manager.max_pfn - 1) << AMDGPU_GPU_PAGE_SHIFT;
+
+ queue_input.process_quantum = 100000; /* 10ms */
+ queue_input.process_csa_addr = test->ctx_data_gpu_addr +
+ offsetof(struct umsch_mm_test_ctx_data, process_csa);
+
+ queue_input.context_quantum = 10000; /* 1ms */
+ queue_input.context_csa_addr = qinfo->csa_addr;
+
+ queue_input.inprocess_context_priority = CONTEXT_PRIORITY_LEVEL_NORMAL;
+ queue_input.context_global_priority_level = CONTEXT_PRIORITY_LEVEL_NORMAL;
+ queue_input.doorbell_offset_0 = qinfo->doorbell_offset_0;
+ queue_input.doorbell_offset_1 = qinfo->doorbell_offset_1;
+
+ queue_input.engine_type = qinfo->engine;
+ queue_input.mqd_addr = qinfo->mqd_addr;
+ queue_input.vm_context_cntl = test->vm_cntx_cntl;
+
+ amdgpu_umsch_mm_lock(&adev->umsch_mm);
+ r = adev->umsch_mm.funcs->add_queue(&adev->umsch_mm, &queue_input);
+ amdgpu_umsch_mm_unlock(&adev->umsch_mm);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static int remove_test_queue(struct amdgpu_device *adev,
+ struct umsch_mm_test *test,
+ struct umsch_mm_test_queue_info *qinfo)
+{
+ struct umsch_mm_remove_queue_input queue_input = {};
+ int r;
+
+ queue_input.doorbell_offset_0 = qinfo->doorbell_offset_0;
+ queue_input.doorbell_offset_1 = qinfo->doorbell_offset_1;
+ queue_input.context_csa_addr = qinfo->csa_addr;
+
+ amdgpu_umsch_mm_lock(&adev->umsch_mm);
+ r = adev->umsch_mm.funcs->remove_queue(&adev->umsch_mm, &queue_input);
+ amdgpu_umsch_mm_unlock(&adev->umsch_mm);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static int submit_vpe_queue(struct amdgpu_device *adev, struct umsch_mm_test *test)
+{
+ struct MQD_INFO *mqd = (struct MQD_INFO *)test->mqd_data_cpu_addr;
+ uint32_t *ring = test->ring_data_cpu_addr +
+ offsetof(struct umsch_mm_test_ring_data, vpe_ring) / 4;
+ uint32_t *ib = test->ring_data_cpu_addr +
+ offsetof(struct umsch_mm_test_ring_data, vpe_ib) / 4;
+ uint64_t ib_gpu_addr = test->ring_data_gpu_addr +
+ offsetof(struct umsch_mm_test_ring_data, vpe_ib);
+ uint32_t *fence = ib + 2048 / 4;
+ uint64_t fence_gpu_addr = ib_gpu_addr + 2048;
+ const uint32_t test_pattern = 0xdeadbeef;
+ int i;
+
+ ib[0] = VPE_CMD_HEADER(VPE_CMD_OPCODE_FENCE, 0);
+ ib[1] = lower_32_bits(fence_gpu_addr);
+ ib[2] = upper_32_bits(fence_gpu_addr);
+ ib[3] = test_pattern;
+
+ ring[0] = VPE_CMD_HEADER(VPE_CMD_OPCODE_INDIRECT, 0);
+ ring[1] = (ib_gpu_addr & 0xffffffe0);
+ ring[2] = upper_32_bits(ib_gpu_addr);
+ ring[3] = 4;
+ ring[4] = 0;
+ ring[5] = 0;
+
+ mqd->wptr_val = (6 << 2);
+ // WDOORBELL32(adev->umsch_mm.agdb_index[CONTEXT_PRIORITY_LEVEL_NORMAL], mqd->wptr_val);
+
+ for (i = 0; i < adev->usec_timeout; i++) {
+ if (*fence == test_pattern)
+ return 0;
+ udelay(1);
+ }
+
+ dev_err(adev->dev, "vpe queue submission timeout\n");
+
+ return -ETIMEDOUT;
+}
+
+static int submit_vcn_queue(struct amdgpu_device *adev, struct umsch_mm_test *test)
+{
+ return 0;
+}
+
+static int setup_umsch_mm_test(struct amdgpu_device *adev,
+ struct umsch_mm_test *test)
+{
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
+ int r;
+
+ test->vm_cntx_cntl = hub->vm_cntx_cntl;
+
+ test->vm = kzalloc(sizeof(*test->vm), GFP_KERNEL);
+ if (!test->vm) {
+ r = -ENOMEM;
+ return r;
+ }
+
+ r = amdgpu_vm_init(adev, test->vm, -1);
+ if (r)
+ goto error_free_vm;
+
+ r = amdgpu_pasid_alloc(16);
+ if (r < 0)
+ goto error_fini_vm;
+ test->pasid = r;
+
+ r = amdgpu_bo_create_kernel(adev, sizeof(struct umsch_mm_test_ctx_data),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
+ &test->ctx_data_obj,
+ &test->ctx_data_gpu_addr,
+ (void **)&test->ctx_data_cpu_addr);
+ if (r)
+ goto error_free_pasid;
+
+ memset(test->ctx_data_cpu_addr, 0, sizeof(struct umsch_mm_test_ctx_data));
+
+ r = amdgpu_bo_create_kernel(adev, PAGE_SIZE,
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
+ &test->mqd_data_obj,
+ &test->mqd_data_gpu_addr,
+ (void **)&test->mqd_data_cpu_addr);
+ if (r)
+ goto error_free_ctx_data_obj;
+
+ memset(test->mqd_data_cpu_addr, 0, PAGE_SIZE);
+
+ r = amdgpu_bo_create_kernel(adev, sizeof(struct umsch_mm_test_ring_data),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
+ &test->ring_data_obj,
+ NULL,
+ (void **)&test->ring_data_cpu_addr);
+ if (r)
+ goto error_free_mqd_data_obj;
+
+ memset(test->ring_data_cpu_addr, 0, sizeof(struct umsch_mm_test_ring_data));
+
+ test->ring_data_gpu_addr = AMDGPU_VA_RESERVED_SIZE;
+ r = map_ring_data(adev, test->vm, test->ring_data_obj, &test->bo_va,
+ test->ring_data_gpu_addr, sizeof(struct umsch_mm_test_ring_data));
+ if (r)
+ goto error_free_ring_data_obj;
+
+ return 0;
+
+error_free_ring_data_obj:
+ amdgpu_bo_free_kernel(&test->ring_data_obj, NULL,
+ (void **)&test->ring_data_cpu_addr);
+error_free_mqd_data_obj:
+ amdgpu_bo_free_kernel(&test->mqd_data_obj, &test->mqd_data_gpu_addr,
+ (void **)&test->mqd_data_cpu_addr);
+error_free_ctx_data_obj:
+ amdgpu_bo_free_kernel(&test->ctx_data_obj, &test->ctx_data_gpu_addr,
+ (void **)&test->ctx_data_cpu_addr);
+error_free_pasid:
+ amdgpu_pasid_free(test->pasid);
+error_fini_vm:
+ amdgpu_vm_fini(adev, test->vm);
+error_free_vm:
+ kfree(test->vm);
+
+ return r;
+}
+
+static void cleanup_umsch_mm_test(struct amdgpu_device *adev,
+ struct umsch_mm_test *test)
+{
+ unmap_ring_data(adev, test->vm, test->ring_data_obj,
+ test->bo_va, test->ring_data_gpu_addr);
+ amdgpu_bo_free_kernel(&test->mqd_data_obj, &test->mqd_data_gpu_addr,
+ (void **)&test->mqd_data_cpu_addr);
+ amdgpu_bo_free_kernel(&test->ring_data_obj, NULL,
+ (void **)&test->ring_data_cpu_addr);
+ amdgpu_bo_free_kernel(&test->ctx_data_obj, &test->ctx_data_gpu_addr,
+ (void **)&test->ctx_data_cpu_addr);
+ amdgpu_pasid_free(test->pasid);
+ amdgpu_vm_fini(adev, test->vm);
+ kfree(test->vm);
+}
+
+static int setup_test_queues(struct amdgpu_device *adev,
+ struct umsch_mm_test *test,
+ struct umsch_mm_test_queue_info *qinfo)
+{
+ int i, r;
+
+ for (i = 0; i < test->num_queues; i++) {
+ if (qinfo[i].engine == UMSCH_SWIP_ENGINE_TYPE_VPE)
+ setup_vpe_queue(adev, test, &qinfo[i]);
+ else
+ setup_vcn_queue(adev, test, &qinfo[i]);
+
+ r = add_test_queue(adev, test, &qinfo[i]);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static int submit_test_queues(struct amdgpu_device *adev,
+ struct umsch_mm_test *test,
+ struct umsch_mm_test_queue_info *qinfo)
+{
+ int i, r;
+
+ for (i = 0; i < test->num_queues; i++) {
+ if (qinfo[i].engine == UMSCH_SWIP_ENGINE_TYPE_VPE)
+ r = submit_vpe_queue(adev, test);
+ else
+ r = submit_vcn_queue(adev, test);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static void cleanup_test_queues(struct amdgpu_device *adev,
+ struct umsch_mm_test *test,
+ struct umsch_mm_test_queue_info *qinfo)
+{
+ int i;
+
+ for (i = 0; i < test->num_queues; i++)
+ remove_test_queue(adev, test, &qinfo[i]);
+}
+
+static int umsch_mm_test(struct amdgpu_device *adev)
+{
+ struct umsch_mm_test_queue_info qinfo[] = {
+ { .engine = UMSCH_SWIP_ENGINE_TYPE_VPE },
+ };
+ struct umsch_mm_test test = { .num_queues = ARRAY_SIZE(qinfo) };
+ int r;
+
+ r = setup_umsch_mm_test(adev, &test);
+ if (r)
+ return r;
+
+ r = setup_test_queues(adev, &test, qinfo);
+ if (r)
+ goto cleanup;
+
+ r = submit_test_queues(adev, &test, qinfo);
+ if (r)
+ goto cleanup;
+
+ cleanup_test_queues(adev, &test, qinfo);
+ cleanup_umsch_mm_test(adev, &test);
+
+ return 0;
+
+cleanup:
+ cleanup_test_queues(adev, &test, qinfo);
+ cleanup_umsch_mm_test(adev, &test);
+ return r;
+}
+
+int amdgpu_umsch_mm_submit_pkt(struct amdgpu_umsch_mm *umsch, void *pkt, int ndws)
+{
+ struct amdgpu_ring *ring = &umsch->ring;
+
+ if (amdgpu_ring_alloc(ring, ndws))
+ return -ENOMEM;
+
+ amdgpu_ring_write_multiple(ring, pkt, ndws);
+ amdgpu_ring_commit(ring);
+
+ return 0;
+}
+
+int amdgpu_umsch_mm_query_fence(struct amdgpu_umsch_mm *umsch)
+{
+ struct amdgpu_ring *ring = &umsch->ring;
+ struct amdgpu_device *adev = ring->adev;
+ int r;
+
+ r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, adev->usec_timeout);
+ if (r < 1) {
+ dev_err(adev->dev, "ring umsch timeout, emitted fence %u\n",
+ ring->fence_drv.sync_seq);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static void umsch_mm_ring_set_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_umsch_mm *umsch = (struct amdgpu_umsch_mm *)ring;
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring->use_doorbell)
+ WDOORBELL32(ring->doorbell_index, ring->wptr << 2);
+ else
+ WREG32(umsch->rb_wptr, ring->wptr << 2);
+}
+
+static u64 umsch_mm_ring_get_rptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_umsch_mm *umsch = (struct amdgpu_umsch_mm *)ring;
+ struct amdgpu_device *adev = ring->adev;
+
+ return RREG32(umsch->rb_rptr);
+}
+
+static u64 umsch_mm_ring_get_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_umsch_mm *umsch = (struct amdgpu_umsch_mm *)ring;
+ struct amdgpu_device *adev = ring->adev;
+
+ return RREG32(umsch->rb_wptr);
+}
+
+static const struct amdgpu_ring_funcs umsch_v4_0_ring_funcs = {
+ .type = AMDGPU_RING_TYPE_UMSCH_MM,
+ .align_mask = 0,
+ .nop = 0,
+ .support_64bit_ptrs = false,
+ .get_rptr = umsch_mm_ring_get_rptr,
+ .get_wptr = umsch_mm_ring_get_wptr,
+ .set_wptr = umsch_mm_ring_set_wptr,
+ .insert_nop = amdgpu_ring_insert_nop,
+};
+
+int amdgpu_umsch_mm_ring_init(struct amdgpu_umsch_mm *umsch)
+{
+ struct amdgpu_device *adev = container_of(umsch, struct amdgpu_device, umsch_mm);
+ struct amdgpu_ring *ring = &umsch->ring;
+
+ ring->vm_hub = AMDGPU_MMHUB0(0);
+ ring->use_doorbell = true;
+ ring->no_scheduler = true;
+ ring->doorbell_index = (AMDGPU_NAVI10_DOORBELL64_VCN0_1 << 1) + 6;
+
+ snprintf(ring->name, sizeof(ring->name), "umsch");
+
+ return amdgpu_ring_init(adev, ring, 1024, NULL, 0, AMDGPU_RING_PRIO_DEFAULT, NULL);
+}
+
+int amdgpu_umsch_mm_init_microcode(struct amdgpu_umsch_mm *umsch)
+{
+ const struct umsch_mm_firmware_header_v1_0 *umsch_mm_hdr;
+ struct amdgpu_device *adev = umsch->ring.adev;
+ const char *fw_name = NULL;
+ int r;
+
+ switch (amdgpu_ip_version(adev, VCN_HWIP, 0)) {
+ case IP_VERSION(4, 0, 5):
+ fw_name = "amdgpu/umsch_mm_4_0_0.bin";
+ break;
+ default:
+ break;
+ }
+
+ r = amdgpu_ucode_request(adev, &adev->umsch_mm.fw, fw_name);
+ if (r) {
+ release_firmware(adev->umsch_mm.fw);
+ adev->umsch_mm.fw = NULL;
+ return r;
+ }
+
+ umsch_mm_hdr = (const struct umsch_mm_firmware_header_v1_0 *)adev->umsch_mm.fw->data;
+
+ adev->umsch_mm.ucode_size = le32_to_cpu(umsch_mm_hdr->umsch_mm_ucode_size_bytes);
+ adev->umsch_mm.data_size = le32_to_cpu(umsch_mm_hdr->umsch_mm_ucode_data_size_bytes);
+
+ adev->umsch_mm.irq_start_addr =
+ le32_to_cpu(umsch_mm_hdr->umsch_mm_irq_start_addr_lo) |
+ ((uint64_t)(le32_to_cpu(umsch_mm_hdr->umsch_mm_irq_start_addr_hi)) << 32);
+ adev->umsch_mm.uc_start_addr =
+ le32_to_cpu(umsch_mm_hdr->umsch_mm_uc_start_addr_lo) |
+ ((uint64_t)(le32_to_cpu(umsch_mm_hdr->umsch_mm_uc_start_addr_hi)) << 32);
+ adev->umsch_mm.data_start_addr =
+ le32_to_cpu(umsch_mm_hdr->umsch_mm_data_start_addr_lo) |
+ ((uint64_t)(le32_to_cpu(umsch_mm_hdr->umsch_mm_data_start_addr_hi)) << 32);
+
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+ struct amdgpu_firmware_info *info;
+
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_UMSCH_MM_UCODE];
+ info->ucode_id = AMDGPU_UCODE_ID_UMSCH_MM_UCODE;
+ info->fw = adev->umsch_mm.fw;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(umsch_mm_hdr->umsch_mm_ucode_size_bytes), PAGE_SIZE);
+
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_UMSCH_MM_DATA];
+ info->ucode_id = AMDGPU_UCODE_ID_UMSCH_MM_DATA;
+ info->fw = adev->umsch_mm.fw;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(umsch_mm_hdr->umsch_mm_ucode_data_size_bytes), PAGE_SIZE);
+ }
+
+ return 0;
+}
+
+int amdgpu_umsch_mm_allocate_ucode_buffer(struct amdgpu_umsch_mm *umsch)
+{
+ const struct umsch_mm_firmware_header_v1_0 *umsch_mm_hdr;
+ struct amdgpu_device *adev = umsch->ring.adev;
+ const __le32 *fw_data;
+ uint32_t fw_size;
+ int r;
+
+ umsch_mm_hdr = (const struct umsch_mm_firmware_header_v1_0 *)
+ adev->umsch_mm.fw->data;
+
+ fw_data = (const __le32 *)(adev->umsch_mm.fw->data +
+ le32_to_cpu(umsch_mm_hdr->umsch_mm_ucode_offset_bytes));
+ fw_size = le32_to_cpu(umsch_mm_hdr->umsch_mm_ucode_size_bytes);
+
+ r = amdgpu_bo_create_reserved(adev, fw_size,
+ 4 * 1024, AMDGPU_GEM_DOMAIN_VRAM,
+ &adev->umsch_mm.ucode_fw_obj,
+ &adev->umsch_mm.ucode_fw_gpu_addr,
+ (void **)&adev->umsch_mm.ucode_fw_ptr);
+ if (r) {
+ dev_err(adev->dev, "(%d) failed to create umsch_mm fw ucode bo\n", r);
+ return r;
+ }
+
+ memcpy(adev->umsch_mm.ucode_fw_ptr, fw_data, fw_size);
+
+ amdgpu_bo_kunmap(adev->umsch_mm.ucode_fw_obj);
+ amdgpu_bo_unreserve(adev->umsch_mm.ucode_fw_obj);
+ return 0;
+}
+
+int amdgpu_umsch_mm_allocate_ucode_data_buffer(struct amdgpu_umsch_mm *umsch)
+{
+ const struct umsch_mm_firmware_header_v1_0 *umsch_mm_hdr;
+ struct amdgpu_device *adev = umsch->ring.adev;
+ const __le32 *fw_data;
+ uint32_t fw_size;
+ int r;
+
+ umsch_mm_hdr = (const struct umsch_mm_firmware_header_v1_0 *)
+ adev->umsch_mm.fw->data;
+
+ fw_data = (const __le32 *)(adev->umsch_mm.fw->data +
+ le32_to_cpu(umsch_mm_hdr->umsch_mm_ucode_data_offset_bytes));
+ fw_size = le32_to_cpu(umsch_mm_hdr->umsch_mm_ucode_data_size_bytes);
+
+ r = amdgpu_bo_create_reserved(adev, fw_size,
+ 64 * 1024, AMDGPU_GEM_DOMAIN_VRAM,
+ &adev->umsch_mm.data_fw_obj,
+ &adev->umsch_mm.data_fw_gpu_addr,
+ (void **)&adev->umsch_mm.data_fw_ptr);
+ if (r) {
+ dev_err(adev->dev, "(%d) failed to create umsch_mm fw data bo\n", r);
+ return r;
+ }
+
+ memcpy(adev->umsch_mm.data_fw_ptr, fw_data, fw_size);
+
+ amdgpu_bo_kunmap(adev->umsch_mm.data_fw_obj);
+ amdgpu_bo_unreserve(adev->umsch_mm.data_fw_obj);
+ return 0;
+}
+
+int amdgpu_umsch_mm_psp_execute_cmd_buf(struct amdgpu_umsch_mm *umsch)
+{
+ struct amdgpu_device *adev = umsch->ring.adev;
+ struct amdgpu_firmware_info ucode = {
+ .ucode_id = AMDGPU_UCODE_ID_UMSCH_MM_CMD_BUFFER,
+ .mc_addr = adev->umsch_mm.cmd_buf_gpu_addr,
+ .ucode_size = ((uintptr_t)adev->umsch_mm.cmd_buf_curr_ptr -
+ (uintptr_t)adev->umsch_mm.cmd_buf_ptr),
+ };
+
+ return psp_execute_ip_fw_load(&adev->psp, &ucode);
+}
+
+static void umsch_mm_agdb_index_init(struct amdgpu_device *adev)
+{
+ uint32_t umsch_mm_agdb_start;
+ int i;
+
+ umsch_mm_agdb_start = adev->doorbell_index.max_assignment + 1;
+ umsch_mm_agdb_start = roundup(umsch_mm_agdb_start, 1024);
+ umsch_mm_agdb_start += (AMDGPU_NAVI10_DOORBELL64_VCN0_1 << 1);
+
+ for (i = 0; i < CONTEXT_PRIORITY_NUM_LEVELS; i++)
+ adev->umsch_mm.agdb_index[i] = umsch_mm_agdb_start + i;
+}
+
+static int umsch_mm_init(struct amdgpu_device *adev)
+{
+ int r;
+
+ adev->umsch_mm.vmid_mask_mm_vpe = 0xf00;
+ adev->umsch_mm.engine_mask = (1 << UMSCH_SWIP_ENGINE_TYPE_VPE);
+ adev->umsch_mm.vpe_hqd_mask = 0xfe;
+
+ r = amdgpu_device_wb_get(adev, &adev->umsch_mm.wb_index);
+ if (r) {
+ dev_err(adev->dev, "failed to alloc wb for umsch: %d\n", r);
+ return r;
+ }
+
+ adev->umsch_mm.sch_ctx_gpu_addr = adev->wb.gpu_addr +
+ (adev->umsch_mm.wb_index * 4);
+
+ r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_GTT,
+ &adev->umsch_mm.cmd_buf_obj,
+ &adev->umsch_mm.cmd_buf_gpu_addr,
+ (void **)&adev->umsch_mm.cmd_buf_ptr);
+ if (r) {
+ dev_err(adev->dev, "failed to allocate cmdbuf bo %d\n", r);
+ amdgpu_device_wb_free(adev, adev->umsch_mm.wb_index);
+ return r;
+ }
+
+ mutex_init(&adev->umsch_mm.mutex_hidden);
+
+ umsch_mm_agdb_index_init(adev);
+
+ return 0;
+}
+
+
+static int umsch_mm_early_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ switch (amdgpu_ip_version(adev, VCN_HWIP, 0)) {
+ case IP_VERSION(4, 0, 5):
+ umsch_mm_v4_0_set_funcs(&adev->umsch_mm);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ adev->umsch_mm.ring.funcs = &umsch_v4_0_ring_funcs;
+ umsch_mm_set_regs(&adev->umsch_mm);
+
+ return 0;
+}
+
+static int umsch_mm_late_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ return umsch_mm_test(adev);
+}
+
+static int umsch_mm_sw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = umsch_mm_init(adev);
+ if (r)
+ return r;
+
+ r = umsch_mm_ring_init(&adev->umsch_mm);
+ if (r)
+ return r;
+
+ r = umsch_mm_init_microcode(&adev->umsch_mm);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static int umsch_mm_sw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ release_firmware(adev->umsch_mm.fw);
+ adev->umsch_mm.fw = NULL;
+
+ amdgpu_ring_fini(&adev->umsch_mm.ring);
+
+ mutex_destroy(&adev->umsch_mm.mutex_hidden);
+
+ amdgpu_bo_free_kernel(&adev->umsch_mm.cmd_buf_obj,
+ &adev->umsch_mm.cmd_buf_gpu_addr,
+ (void **)&adev->umsch_mm.cmd_buf_ptr);
+
+ amdgpu_device_wb_free(adev, adev->umsch_mm.wb_index);
+
+ return 0;
+}
+
+static int umsch_mm_hw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = umsch_mm_load_microcode(&adev->umsch_mm);
+ if (r)
+ return r;
+
+ umsch_mm_ring_start(&adev->umsch_mm);
+
+ r = umsch_mm_set_hw_resources(&adev->umsch_mm);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static int umsch_mm_hw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ umsch_mm_ring_stop(&adev->umsch_mm);
+
+ amdgpu_bo_free_kernel(&adev->umsch_mm.data_fw_obj,
+ &adev->umsch_mm.data_fw_gpu_addr,
+ (void **)&adev->umsch_mm.data_fw_ptr);
+
+ amdgpu_bo_free_kernel(&adev->umsch_mm.ucode_fw_obj,
+ &adev->umsch_mm.ucode_fw_gpu_addr,
+ (void **)&adev->umsch_mm.ucode_fw_ptr);
+ return 0;
+}
+
+static int umsch_mm_suspend(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ return umsch_mm_hw_fini(adev);
+}
+
+static int umsch_mm_resume(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ return umsch_mm_hw_init(adev);
+}
+
+static const struct amd_ip_funcs umsch_mm_v4_0_ip_funcs = {
+ .name = "umsch_mm_v4_0",
+ .early_init = umsch_mm_early_init,
+ .late_init = umsch_mm_late_init,
+ .sw_init = umsch_mm_sw_init,
+ .sw_fini = umsch_mm_sw_fini,
+ .hw_init = umsch_mm_hw_init,
+ .hw_fini = umsch_mm_hw_fini,
+ .suspend = umsch_mm_suspend,
+ .resume = umsch_mm_resume,
+};
+
+const struct amdgpu_ip_block_version umsch_mm_v4_0_ip_block = {
+ .type = AMD_IP_BLOCK_TYPE_UMSCH_MM,
+ .major = 4,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &umsch_mm_v4_0_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.h
new file mode 100644
index 000000000000..8258a43a6236
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.h
@@ -0,0 +1,228 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __AMDGPU_UMSCH_MM_H__
+#define __AMDGPU_UMSCH_MM_H__
+
+enum UMSCH_SWIP_ENGINE_TYPE {
+ UMSCH_SWIP_ENGINE_TYPE_VCN0 = 0,
+ UMSCH_SWIP_ENGINE_TYPE_VCN1 = 1,
+ UMSCH_SWIP_ENGINE_TYPE_VCN = 2,
+ UMSCH_SWIP_ENGINE_TYPE_VPE = 3,
+ UMSCH_SWIP_ENGINE_TYPE_MAX
+};
+
+enum UMSCH_SWIP_AFFINITY_TYPE {
+ UMSCH_SWIP_AFFINITY_TYPE_ANY = 0,
+ UMSCH_SWIP_AFFINITY_TYPE_VCN0 = 1,
+ UMSCH_SWIP_AFFINITY_TYPE_VCN1 = 2,
+ UMSCH_SWIP_AFFINITY_TYPE_MAX
+};
+
+enum UMSCH_CONTEXT_PRIORITY_LEVEL {
+ CONTEXT_PRIORITY_LEVEL_IDLE = 0,
+ CONTEXT_PRIORITY_LEVEL_NORMAL = 1,
+ CONTEXT_PRIORITY_LEVEL_FOCUS = 2,
+ CONTEXT_PRIORITY_LEVEL_REALTIME = 3,
+ CONTEXT_PRIORITY_NUM_LEVELS
+};
+
+struct umsch_mm_set_resource_input {
+ uint32_t vmid_mask_mm_vcn;
+ uint32_t vmid_mask_mm_vpe;
+ uint32_t logging_vmid;
+ uint32_t engine_mask;
+ union {
+ struct {
+ uint32_t disable_reset : 1;
+ uint32_t disable_umsch_mm_log : 1;
+ uint32_t reserved : 30;
+ };
+ uint32_t uint32_all;
+ };
+};
+
+struct umsch_mm_add_queue_input {
+ uint32_t process_id;
+ uint64_t page_table_base_addr;
+ uint64_t process_va_start;
+ uint64_t process_va_end;
+ uint64_t process_quantum;
+ uint64_t process_csa_addr;
+ uint64_t context_quantum;
+ uint64_t context_csa_addr;
+ uint32_t inprocess_context_priority;
+ enum UMSCH_CONTEXT_PRIORITY_LEVEL context_global_priority_level;
+ uint32_t doorbell_offset_0;
+ uint32_t doorbell_offset_1;
+ enum UMSCH_SWIP_ENGINE_TYPE engine_type;
+ uint32_t affinity;
+ enum UMSCH_SWIP_AFFINITY_TYPE affinity_type;
+ uint64_t mqd_addr;
+ uint64_t h_context;
+ uint64_t h_queue;
+ uint32_t vm_context_cntl;
+
+ struct {
+ uint32_t is_context_suspended : 1;
+ uint32_t reserved : 31;
+ };
+};
+
+struct umsch_mm_remove_queue_input {
+ uint32_t doorbell_offset_0;
+ uint32_t doorbell_offset_1;
+ uint64_t context_csa_addr;
+};
+
+struct MQD_INFO {
+ uint32_t rb_base_hi;
+ uint32_t rb_base_lo;
+ uint32_t rb_size;
+ uint32_t wptr_val;
+ uint32_t rptr_val;
+ uint32_t unmapped;
+};
+
+struct amdgpu_umsch_mm;
+
+struct umsch_mm_funcs {
+ int (*set_hw_resources)(struct amdgpu_umsch_mm *umsch);
+ int (*add_queue)(struct amdgpu_umsch_mm *umsch,
+ struct umsch_mm_add_queue_input *input);
+ int (*remove_queue)(struct amdgpu_umsch_mm *umsch,
+ struct umsch_mm_remove_queue_input *input);
+ int (*set_regs)(struct amdgpu_umsch_mm *umsch);
+ int (*init_microcode)(struct amdgpu_umsch_mm *umsch);
+ int (*load_microcode)(struct amdgpu_umsch_mm *umsch);
+ int (*ring_init)(struct amdgpu_umsch_mm *umsch);
+ int (*ring_start)(struct amdgpu_umsch_mm *umsch);
+ int (*ring_stop)(struct amdgpu_umsch_mm *umsch);
+ int (*ring_fini)(struct amdgpu_umsch_mm *umsch);
+};
+
+struct amdgpu_umsch_mm {
+ struct amdgpu_ring ring;
+
+ uint32_t rb_wptr;
+ uint32_t rb_rptr;
+
+ const struct umsch_mm_funcs *funcs;
+
+ const struct firmware *fw;
+ uint32_t fw_version;
+ uint32_t feature_version;
+
+ struct amdgpu_bo *ucode_fw_obj;
+ uint64_t ucode_fw_gpu_addr;
+ uint32_t *ucode_fw_ptr;
+ uint64_t irq_start_addr;
+ uint64_t uc_start_addr;
+ uint32_t ucode_size;
+
+ struct amdgpu_bo *data_fw_obj;
+ uint64_t data_fw_gpu_addr;
+ uint32_t *data_fw_ptr;
+ uint64_t data_start_addr;
+ uint32_t data_size;
+
+ struct amdgpu_bo *cmd_buf_obj;
+ uint64_t cmd_buf_gpu_addr;
+ uint32_t *cmd_buf_ptr;
+ uint32_t *cmd_buf_curr_ptr;
+
+ uint32_t wb_index;
+ uint64_t sch_ctx_gpu_addr;
+ uint32_t *sch_ctx_cpu_addr;
+
+ uint32_t vmid_mask_mm_vcn;
+ uint32_t vmid_mask_mm_vpe;
+ uint32_t engine_mask;
+ uint32_t vcn0_hqd_mask;
+ uint32_t vcn1_hqd_mask;
+ uint32_t vcn_hqd_mask[2];
+ uint32_t vpe_hqd_mask;
+ uint32_t agdb_index[CONTEXT_PRIORITY_NUM_LEVELS];
+
+ struct mutex mutex_hidden;
+};
+
+int amdgpu_umsch_mm_submit_pkt(struct amdgpu_umsch_mm *umsch, void *pkt, int ndws);
+int amdgpu_umsch_mm_query_fence(struct amdgpu_umsch_mm *umsch);
+
+int amdgpu_umsch_mm_init_microcode(struct amdgpu_umsch_mm *umsch);
+int amdgpu_umsch_mm_allocate_ucode_buffer(struct amdgpu_umsch_mm *umsch);
+int amdgpu_umsch_mm_allocate_ucode_data_buffer(struct amdgpu_umsch_mm *umsch);
+
+int amdgpu_umsch_mm_psp_execute_cmd_buf(struct amdgpu_umsch_mm *umsch);
+
+int amdgpu_umsch_mm_ring_init(struct amdgpu_umsch_mm *umsch);
+
+#define WREG32_SOC15_UMSCH(reg, value) \
+ do { \
+ uint32_t reg_offset = adev->reg_offset[VCN_HWIP][0][reg##_BASE_IDX] + reg; \
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { \
+ *adev->umsch_mm.cmd_buf_curr_ptr++ = (reg_offset << 2); \
+ *adev->umsch_mm.cmd_buf_curr_ptr++ = value; \
+ } else { \
+ WREG32(reg_offset, value); \
+ } \
+ } while (0)
+
+#define umsch_mm_set_hw_resources(umsch) \
+ ((umsch)->funcs->set_hw_resources ? (umsch)->funcs->set_hw_resources((umsch)) : 0)
+#define umsch_mm_add_queue(umsch, input) \
+ ((umsch)->funcs->add_queue ? (umsch)->funcs->add_queue((umsch), (input)) : 0)
+#define umsch_mm_remove_queue(umsch, input) \
+ ((umsch)->funcs->remove_queue ? (umsch)->funcs->remove_queue((umsch), (input)) : 0)
+
+#define umsch_mm_set_regs(umsch) \
+ ((umsch)->funcs->set_regs ? (umsch)->funcs->set_regs((umsch)) : 0)
+#define umsch_mm_init_microcode(umsch) \
+ ((umsch)->funcs->init_microcode ? (umsch)->funcs->init_microcode((umsch)) : 0)
+#define umsch_mm_load_microcode(umsch) \
+ ((umsch)->funcs->load_microcode ? (umsch)->funcs->load_microcode((umsch)) : 0)
+
+#define umsch_mm_ring_init(umsch) \
+ ((umsch)->funcs->ring_init ? (umsch)->funcs->ring_init((umsch)) : 0)
+#define umsch_mm_ring_start(umsch) \
+ ((umsch)->funcs->ring_start ? (umsch)->funcs->ring_start((umsch)) : 0)
+#define umsch_mm_ring_stop(umsch) \
+ ((umsch)->funcs->ring_stop ? (umsch)->funcs->ring_stop((umsch)) : 0)
+#define umsch_mm_ring_fini(umsch) \
+ ((umsch)->funcs->ring_fini ? (umsch)->funcs->ring_fini((umsch)) : 0)
+
+static inline void amdgpu_umsch_mm_lock(struct amdgpu_umsch_mm *umsch)
+{
+ mutex_lock(&umsch->mutex_hidden);
+}
+
+static inline void amdgpu_umsch_mm_unlock(struct amdgpu_umsch_mm *umsch)
+{
+ mutex_unlock(&umsch->mutex_hidden);
+}
+
+extern const struct amdgpu_ip_block_version umsch_mm_v4_0_ip_block;
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index b7441654e6fa..07d930339b07 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -398,32 +398,32 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
* amdgpu_uvd_entity_init - init entity
*
* @adev: amdgpu_device pointer
+ * @ring: amdgpu_ring pointer to check
*
+ * Initialize the entity used for handle management in the kernel driver.
*/
-int amdgpu_uvd_entity_init(struct amdgpu_device *adev)
+int amdgpu_uvd_entity_init(struct amdgpu_device *adev, struct amdgpu_ring *ring)
{
- struct amdgpu_ring *ring;
- struct drm_gpu_scheduler *sched;
- int r;
+ if (ring == &adev->uvd.inst[0].ring) {
+ struct drm_gpu_scheduler *sched = &ring->sched;
+ int r;
- ring = &adev->uvd.inst[0].ring;
- sched = &ring->sched;
- r = drm_sched_entity_init(&adev->uvd.entity, DRM_SCHED_PRIORITY_NORMAL,
- &sched, 1, NULL);
- if (r) {
- DRM_ERROR("Failed setting up UVD kernel entity.\n");
- return r;
+ r = drm_sched_entity_init(&adev->uvd.entity, DRM_SCHED_PRIORITY_NORMAL,
+ &sched, 1, NULL);
+ if (r) {
+ DRM_ERROR("Failed setting up UVD kernel entity.\n");
+ return r;
+ }
}
return 0;
}
-int amdgpu_uvd_suspend(struct amdgpu_device *adev)
+int amdgpu_uvd_prepare_suspend(struct amdgpu_device *adev)
{
unsigned int size;
void *ptr;
int i, j, idx;
- bool in_ras_intr = amdgpu_ras_intr_triggered();
cancel_delayed_work_sync(&adev->uvd.idle_work);
@@ -452,7 +452,7 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
/* re-write 0 since err_event_athub will corrupt VCPU buffer */
- if (in_ras_intr)
+ if (amdgpu_ras_intr_triggered())
memset(adev->uvd.inst[j].saved_bo, 0, size);
else
memcpy_fromio(adev->uvd.inst[j].saved_bo, ptr, size);
@@ -461,7 +461,12 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)
}
}
- if (in_ras_intr)
+ return 0;
+}
+
+int amdgpu_uvd_suspend(struct amdgpu_device *adev)
+{
+ if (amdgpu_ras_intr_triggered())
DRM_WARN("UVD VCPU state may lost due to RAS ERREVENT_ATHUB_INTERRUPT\n");
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
index 9f89bb7cd60b..9dfad2f48ef4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
@@ -73,7 +73,8 @@ struct amdgpu_uvd {
int amdgpu_uvd_sw_init(struct amdgpu_device *adev);
int amdgpu_uvd_sw_fini(struct amdgpu_device *adev);
-int amdgpu_uvd_entity_init(struct amdgpu_device *adev);
+int amdgpu_uvd_entity_init(struct amdgpu_device *adev, struct amdgpu_ring *ring);
+int amdgpu_uvd_prepare_suspend(struct amdgpu_device *adev);
int amdgpu_uvd_suspend(struct amdgpu_device *adev);
int amdgpu_uvd_resume(struct amdgpu_device *adev);
int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 1904edf68407..59acf424a078 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -230,21 +230,22 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
* amdgpu_vce_entity_init - init entity
*
* @adev: amdgpu_device pointer
+ * @ring: amdgpu_ring pointer to check
*
+ * Initialize the entity used for handle management in the kernel driver.
*/
-int amdgpu_vce_entity_init(struct amdgpu_device *adev)
+int amdgpu_vce_entity_init(struct amdgpu_device *adev, struct amdgpu_ring *ring)
{
- struct amdgpu_ring *ring;
- struct drm_gpu_scheduler *sched;
- int r;
-
- ring = &adev->vce.ring[0];
- sched = &ring->sched;
- r = drm_sched_entity_init(&adev->vce.entity, DRM_SCHED_PRIORITY_NORMAL,
- &sched, 1, NULL);
- if (r != 0) {
- DRM_ERROR("Failed setting up VCE run queue.\n");
- return r;
+ if (ring == &adev->vce.ring[0]) {
+ struct drm_gpu_scheduler *sched = &ring->sched;
+ int r;
+
+ r = drm_sched_entity_init(&adev->vce.entity, DRM_SCHED_PRIORITY_NORMAL,
+ &sched, 1, NULL);
+ if (r != 0) {
+ DRM_ERROR("Failed setting up VCE run queue.\n");
+ return r;
+ }
}
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
index ea680fc9a6c3..6e53f872d084 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
@@ -55,7 +55,7 @@ struct amdgpu_vce {
int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size);
int amdgpu_vce_sw_fini(struct amdgpu_device *adev);
-int amdgpu_vce_entity_init(struct amdgpu_device *adev);
+int amdgpu_vce_entity_init(struct amdgpu_device *adev, struct amdgpu_ring *ring);
int amdgpu_vce_suspend(struct amdgpu_device *adev);
int amdgpu_vce_resume(struct amdgpu_device *adev);
void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 36b55d2bd51a..f4963330c772 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -58,6 +58,7 @@
#define FIRMWARE_VCN4_0_2 "amdgpu/vcn_4_0_2.bin"
#define FIRMWARE_VCN4_0_3 "amdgpu/vcn_4_0_3.bin"
#define FIRMWARE_VCN4_0_4 "amdgpu/vcn_4_0_4.bin"
+#define FIRMWARE_VCN4_0_5 "amdgpu/vcn_4_0_5.bin"
MODULE_FIRMWARE(FIRMWARE_RAVEN);
MODULE_FIRMWARE(FIRMWARE_PICASSO);
@@ -80,6 +81,7 @@ MODULE_FIRMWARE(FIRMWARE_VCN4_0_0);
MODULE_FIRMWARE(FIRMWARE_VCN4_0_2);
MODULE_FIRMWARE(FIRMWARE_VCN4_0_3);
MODULE_FIRMWARE(FIRMWARE_VCN4_0_4);
+MODULE_FIRMWARE(FIRMWARE_VCN4_0_5);
static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
@@ -124,7 +126,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
* Hence, check for these versions here - notice this is
* restricted to Vangogh (Deck's APU).
*/
- if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(3, 0, 2)) {
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
@@ -169,7 +171,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
- if (adev->ip_versions[UVD_HWIP][0] >= IP_VERSION(4, 0, 0)) {
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
} else {
@@ -265,7 +267,7 @@ static bool amdgpu_vcn_using_unified_queue(struct amdgpu_ring *ring)
struct amdgpu_device *adev = ring->adev;
bool ret = false;
- if (adev->ip_versions[UVD_HWIP][0] >= IP_VERSION(4, 0, 0))
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0))
ret = true;
return ret;
@@ -292,8 +294,15 @@ int amdgpu_vcn_suspend(struct amdgpu_device *adev)
void *ptr;
int i, idx;
+ bool in_ras_intr = amdgpu_ras_intr_triggered();
+
cancel_delayed_work_sync(&adev->vcn.idle_work);
+ /* err_event_athub will corrupt VCPU buffer, so we need to
+ * restore fw data and clear buffer in amdgpu_vcn_resume() */
+ if (in_ras_intr)
+ return 0;
+
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
if (adev->vcn.harvest_config & (1 << i))
continue;
@@ -996,7 +1005,7 @@ int amdgpu_vcn_unified_ring_test_ib(struct amdgpu_ring *ring, long timeout)
struct amdgpu_device *adev = ring->adev;
long r;
- if (adev->ip_versions[UVD_HWIP][0] != IP_VERSION(4, 0, 3)) {
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) != IP_VERSION(4, 0, 3)) {
r = amdgpu_vcn_enc_ring_test_ib(ring, timeout);
if (r)
goto error;
@@ -1046,7 +1055,8 @@ void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev)
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
- if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(4, 0, 3))
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
+ IP_VERSION(4, 0, 3))
break;
}
dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
@@ -1087,7 +1097,7 @@ static ssize_t amdgpu_debugfs_vcn_fwlog_read(struct file *f, char __user *buf,
if (write_pos > read_pos) {
available = write_pos - read_pos;
- read_num[0] = min(size, (size_t)available);
+ read_num[0] = min_t(size_t, size, available);
} else {
read_num[0] = AMDGPU_VCNFW_LOG_SIZE - read_pos;
available = read_num[0] + write_pos - plog->header_size;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index a3eed90b6af0..514c98ea144f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -33,7 +33,7 @@
#define AMDGPU_VCN_MAX_ENC_RINGS 3
#define AMDGPU_MAX_VCN_INSTANCES 4
-#define AMDGPU_MAX_VCN_ENC_RINGS AMDGPU_VCN_MAX_ENC_RINGS * AMDGPU_MAX_VCN_INSTANCES
+#define AMDGPU_MAX_VCN_ENC_RINGS (AMDGPU_VCN_MAX_ENC_RINGS * AMDGPU_MAX_VCN_INSTANCES)
#define AMDGPU_VCN_HARVEST_VCN0 (1 << 0)
#define AMDGPU_VCN_HARVEST_VCN1 (1 << 1)
@@ -169,6 +169,9 @@
#define AMDGPU_VCN_SMU_VERSION_INFO_FLAG (1 << 11)
#define AMDGPU_VCN_SMU_DPM_INTERFACE_FLAG (1 << 11)
#define AMDGPU_VCN_VF_RB_SETUP_FLAG (1 << 14)
+#define AMDGPU_VCN_VF_RB_DECOUPLE_FLAG (1 << 15)
+
+#define MAX_NUM_VCN_RB_SETUP 4
#define AMDGPU_VCN_IB_FLAG_DECODE_BUFFER 0x00000001
#define AMDGPU_VCN_CMD_FLAG_MSG_BUFFER 0x00000001
@@ -335,15 +338,30 @@ struct amdgpu_fw_shared {
struct amdgpu_fw_shared_smu_interface_info smu_interface_info;
};
+struct amdgpu_vcn_rb_setup_info {
+ uint32_t rb_addr_lo;
+ uint32_t rb_addr_hi;
+ uint32_t rb_size;
+};
+
struct amdgpu_fw_shared_rb_setup {
uint32_t is_rb_enabled_flags;
- uint32_t rb_addr_lo;
- uint32_t rb_addr_hi;
- uint32_t rb_size;
- uint32_t rb4_addr_lo;
- uint32_t rb4_addr_hi;
- uint32_t rb4_size;
- uint32_t reserved[6];
+
+ union {
+ struct {
+ uint32_t rb_addr_lo;
+ uint32_t rb_addr_hi;
+ uint32_t rb_size;
+ uint32_t rb4_addr_lo;
+ uint32_t rb4_addr_hi;
+ uint32_t rb4_size;
+ uint32_t reserved[6];
+ };
+
+ struct {
+ struct amdgpu_vcn_rb_setup_info rb_info[MAX_NUM_VCN_RB_SETUP];
+ };
+ };
};
struct amdgpu_fw_shared_drm_key_wa {
@@ -351,6 +369,11 @@ struct amdgpu_fw_shared_drm_key_wa {
uint8_t reserved[3];
};
+struct amdgpu_fw_shared_queue_decouple {
+ uint8_t is_enabled;
+ uint8_t reserved[7];
+};
+
struct amdgpu_vcn4_fw_shared {
uint32_t present_flag_0;
uint8_t pad[12];
@@ -361,6 +384,8 @@ struct amdgpu_vcn4_fw_shared {
struct amdgpu_fw_shared_rb_setup rb_setup;
struct amdgpu_fw_shared_smu_interface_info smu_dpm_interface;
struct amdgpu_fw_shared_drm_key_wa drm_key_wa;
+ uint8_t pad3[9];
+ struct amdgpu_fw_shared_queue_decouple decouple;
};
struct amdgpu_vcn_fwlog {
@@ -378,6 +403,15 @@ struct amdgpu_vcn_decode_buffer {
uint32_t pad[30];
};
+struct amdgpu_vcn_rb_metadata {
+ uint32_t size;
+ uint32_t present_flag_0;
+
+ uint8_t version;
+ uint8_t ring_id;
+ uint8_t pad[26];
+};
+
#define VCN_BLOCK_ENCODE_DISABLE_MASK 0x80
#define VCN_BLOCK_DECODE_DISABLE_MASK 0x40
#define VCN_BLOCK_QUEUE_DISABLE_MASK 0xC0
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
index 96857ae7fb5b..3a632c3b1a2c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -73,9 +73,10 @@ void amdgpu_virt_init_setting(struct amdgpu_device *adev)
void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
uint32_t reg0, uint32_t reg1,
- uint32_t ref, uint32_t mask)
+ uint32_t ref, uint32_t mask,
+ uint32_t xcc_inst)
{
- struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_inst];
struct amdgpu_ring *ring = &kiq->ring;
signed long r, cnt = 0;
unsigned long flags;
@@ -837,7 +838,7 @@ enum amdgpu_sriov_vf_mode amdgpu_virt_get_sriov_vf_mode(struct amdgpu_device *ad
void amdgpu_virt_post_reset(struct amdgpu_device *adev)
{
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 3)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 0, 3)) {
/* force set to GFXOFF state after reset,
* to avoid some invalid operation before GC enable
*/
@@ -847,7 +848,7 @@ void amdgpu_virt_post_reset(struct amdgpu_device *adev)
bool amdgpu_virt_fw_load_skip_check(struct amdgpu_device *adev, uint32_t ucode_id)
{
- switch (adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
case IP_VERSION(13, 0, 0):
/* no vf autoload, white list */
if (ucode_id == AMDGPU_UCODE_ID_VCN1 ||
@@ -942,7 +943,7 @@ void amdgpu_virt_update_sriov_video_codec(struct amdgpu_device *adev,
}
}
-static bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev,
+bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev,
u32 acc_flags, u32 hwip,
bool write, u32 *rlcg_flag)
{
@@ -975,7 +976,7 @@ static bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev,
return ret;
}
-static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag, u32 xcc_id)
+u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag, u32 xcc_id)
{
struct amdgpu_rlcg_reg_access_ctrl *reg_access_ctrl;
uint32_t timeout = 50000;
@@ -1093,3 +1094,13 @@ u32 amdgpu_sriov_rreg(struct amdgpu_device *adev,
else
return RREG32(offset);
}
+
+bool amdgpu_sriov_xnack_support(struct amdgpu_device *adev)
+{
+ bool xnack_mode = true;
+
+ if (amdgpu_sriov_vf(adev) && adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2))
+ xnack_mode = false;
+
+ return xnack_mode;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
index fabb83e9d9ae..d4207e44141f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
@@ -126,6 +126,8 @@ enum AMDGIM_FEATURE_FLAG {
AMDGIM_FEATURE_INDIRECT_REG_ACCESS = (1 << 5),
/* AV1 Support MODE*/
AMDGIM_FEATURE_AV1_SUPPORT = (1 << 6),
+ /* VCN RB decouple */
+ AMDGIM_FEATURE_VCN_RB_DECOUPLE = (1 << 7),
};
enum AMDGIM_REG_ACCESS_FLAG {
@@ -326,11 +328,14 @@ static inline bool is_virtual_machine(void)
((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug))
#define amdgpu_sriov_is_av1_support(adev) \
((adev)->virt.gim_feature & AMDGIM_FEATURE_AV1_SUPPORT)
+#define amdgpu_sriov_is_vcn_rb_decouple(adev) \
+ ((adev)->virt.gim_feature & AMDGIM_FEATURE_VCN_RB_DECOUPLE)
bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev);
void amdgpu_virt_init_setting(struct amdgpu_device *adev);
void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
uint32_t reg0, uint32_t rreg1,
- uint32_t ref, uint32_t mask);
+ uint32_t ref, uint32_t mask,
+ uint32_t xcc_inst);
int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init);
int amdgpu_virt_release_full_gpu(struct amdgpu_device *adev, bool init);
int amdgpu_virt_reset_gpu(struct amdgpu_device *adev);
@@ -361,4 +366,9 @@ u32 amdgpu_sriov_rreg(struct amdgpu_device *adev,
bool amdgpu_virt_fw_load_skip_check(struct amdgpu_device *adev,
uint32_t ucode_id);
void amdgpu_virt_post_reset(struct amdgpu_device *adev);
+bool amdgpu_sriov_xnack_support(struct amdgpu_device *adev);
+bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev,
+ u32 acc_flags, u32 hwip,
+ bool write, u32 *rlcg_flag);
+u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag, u32 xcc_id);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
index 7148a216ae2f..db6fc0cb18eb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -239,6 +239,8 @@ static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
+ if (!mode)
+ continue;
drm_mode_probed_add(connector, mode);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index f5daadcec865..d1b8afd105c9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -844,6 +844,7 @@ static void amdgpu_vm_tlb_seq_cb(struct dma_fence *fence,
* @immediate: immediate submission in a page fault
* @unlocked: unlocked invalidation during MM callback
* @flush_tlb: trigger tlb invalidation after update completed
+ * @allow_override: change MTYPE for local NUMA nodes
* @resv: fences we need to sync to
* @start: start of mapped range
* @last: last mapped entry
@@ -860,7 +861,7 @@ static void amdgpu_vm_tlb_seq_cb(struct dma_fence *fence,
* 0 for success, negative erro code for failure.
*/
int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm,
- bool immediate, bool unlocked, bool flush_tlb,
+ bool immediate, bool unlocked, bool flush_tlb, bool allow_override,
struct dma_resv *resv, uint64_t start, uint64_t last,
uint64_t flags, uint64_t offset, uint64_t vram_base,
struct ttm_resource *res, dma_addr_t *pages_addr,
@@ -885,12 +886,12 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm,
* heavy-weight flush TLB unconditionally.
*/
flush_tlb |= adev->gmc.xgmi.num_physical_nodes &&
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 0);
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 0);
/*
* On GFX8 and older any 8 PTE block with a valid bit set enters the TLB
*/
- flush_tlb |= adev->ip_versions[GC_HWIP][0] < IP_VERSION(9, 0, 0);
+ flush_tlb |= amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(9, 0, 0);
memset(&params, 0, sizeof(params));
params.adev = adev;
@@ -898,6 +899,7 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm,
params.immediate = immediate;
params.pages_addr = pages_addr;
params.unlocked = unlocked;
+ params.allow_override = allow_override;
/* Implicitly sync to command submissions in the same VM before
* unmapping. Sync to moving fences before mapping.
@@ -1073,6 +1075,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
struct ttm_resource *mem;
struct dma_fence **last_update;
bool flush_tlb = clear;
+ bool uncached;
struct dma_resv *resv;
uint64_t vram_base;
uint64_t flags;
@@ -1090,12 +1093,13 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
struct drm_gem_object *gobj = dma_buf->priv;
struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj);
- if (abo->tbo.resource->mem_type == TTM_PL_VRAM)
+ if (abo->tbo.resource &&
+ abo->tbo.resource->mem_type == TTM_PL_VRAM)
bo = gem_to_amdgpu_bo(gobj);
}
mem = bo->tbo.resource;
- if (mem->mem_type == TTM_PL_TT ||
- mem->mem_type == AMDGPU_PL_PREEMPT)
+ if (mem && (mem->mem_type == TTM_PL_TT ||
+ mem->mem_type == AMDGPU_PL_PREEMPT))
pages_addr = bo->tbo.ttm->dma_address;
}
@@ -1109,9 +1113,11 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
vram_base = bo_adev->vm_manager.vram_base_offset;
+ uncached = (bo->flags & AMDGPU_GEM_CREATE_UNCACHED) != 0;
} else {
flags = 0x0;
vram_base = 0;
+ uncached = false;
}
if (clear || (bo && bo->tbo.base.resv ==
@@ -1145,7 +1151,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
trace_amdgpu_vm_bo_update(mapping);
r = amdgpu_vm_update_range(adev, vm, false, false, flush_tlb,
- resv, mapping->start, mapping->last,
+ !uncached, resv, mapping->start, mapping->last,
update_flags, mapping->offset,
vram_base, mem, pages_addr,
last_update);
@@ -1340,8 +1346,8 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
mapping->start < AMDGPU_GMC_HOLE_START)
init_pte_value = AMDGPU_PTE_DEFAULT_ATC;
- r = amdgpu_vm_update_range(adev, vm, false, false, true, resv,
- mapping->start, mapping->last,
+ r = amdgpu_vm_update_range(adev, vm, false, false, true, false,
+ resv, mapping->start, mapping->last,
init_pte_value, 0, 0, NULL, NULL,
&f);
amdgpu_vm_free_mapping(adev, vm, mapping, f);
@@ -1367,6 +1373,7 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
*
* @adev: amdgpu_device pointer
* @vm: requested vm
+ * @ticket: optional reservation ticket used to reserve the VM
*
* Make sure all BOs which are moved are updated in the PTs.
*
@@ -1376,11 +1383,12 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
* PTs have to be reserved!
*/
int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
- struct amdgpu_vm *vm)
+ struct amdgpu_vm *vm,
+ struct ww_acquire_ctx *ticket)
{
struct amdgpu_bo_va *bo_va;
struct dma_resv *resv;
- bool clear;
+ bool clear, unlock;
int r;
spin_lock(&vm->status_lock);
@@ -1403,17 +1411,24 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
spin_unlock(&vm->status_lock);
/* Try to reserve the BO to avoid clearing its ptes */
- if (!amdgpu_vm_debug && dma_resv_trylock(resv))
+ if (!adev->debug_vm && dma_resv_trylock(resv)) {
+ clear = false;
+ unlock = true;
+ /* The caller is already holding the reservation lock */
+ } else if (ticket && dma_resv_locking_ctx(resv) == ticket) {
clear = false;
+ unlock = false;
/* Somebody else is using the BO right now */
- else
+ } else {
clear = true;
+ unlock = false;
+ }
r = amdgpu_vm_bo_update(adev, bo_va, clear);
if (r)
return r;
- if (!clear)
+ if (unlock)
dma_resv_unlock(resv);
spin_lock(&vm->status_lock);
}
@@ -2059,7 +2074,7 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size,
if (amdgpu_vm_block_size != -1)
tmp >>= amdgpu_vm_block_size - 9;
tmp = DIV_ROUND_UP(fls64(tmp) - 1, 9) - 1;
- adev->vm_manager.num_level = min(max_level, (unsigned)tmp);
+ adev->vm_manager.num_level = min_t(unsigned int, max_level, tmp);
switch (adev->vm_manager.num_level) {
case 3:
adev->vm_manager.root_level = AMDGPU_VM_PDB2;
@@ -2124,7 +2139,8 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
* Returns:
* 0 for success, error for failure.
*/
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp_id)
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ int32_t xcp_id)
{
struct amdgpu_bo *root_bo;
struct amdgpu_bo_vm *root;
@@ -2143,6 +2159,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp
INIT_LIST_HEAD(&vm->done);
INIT_LIST_HEAD(&vm->pt_freed);
INIT_WORK(&vm->pt_free_work, amdgpu_vm_pt_free_work);
+ INIT_KFIFO(vm->faults);
r = amdgpu_vm_init_entities(adev, vm);
if (r)
@@ -2177,34 +2194,33 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp
false, &root, xcp_id);
if (r)
goto error_free_delayed;
- root_bo = &root->bo;
+
+ root_bo = amdgpu_bo_ref(&root->bo);
r = amdgpu_bo_reserve(root_bo, true);
- if (r)
- goto error_free_root;
+ if (r) {
+ amdgpu_bo_unref(&root->shadow);
+ amdgpu_bo_unref(&root_bo);
+ goto error_free_delayed;
+ }
+ amdgpu_vm_bo_base_init(&vm->root, vm, root_bo);
r = dma_resv_reserve_fences(root_bo->tbo.base.resv, 1);
if (r)
- goto error_unreserve;
-
- amdgpu_vm_bo_base_init(&vm->root, vm, root_bo);
+ goto error_free_root;
r = amdgpu_vm_pt_clear(adev, vm, root, false);
if (r)
- goto error_unreserve;
+ goto error_free_root;
amdgpu_bo_unreserve(vm->root.bo);
-
- INIT_KFIFO(vm->faults);
+ amdgpu_bo_unref(&root_bo);
return 0;
-error_unreserve:
- amdgpu_bo_unreserve(vm->root.bo);
-
error_free_root:
- amdgpu_bo_unref(&root->shadow);
+ amdgpu_vm_pt_free_root(adev, vm);
+ amdgpu_bo_unreserve(vm->root.bo);
amdgpu_bo_unref(&root_bo);
- vm->root.bo = NULL;
error_free_delayed:
dma_fence_put(vm->last_tlb_flush);
@@ -2617,8 +2633,8 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
goto error_unlock;
}
- r = amdgpu_vm_update_range(adev, vm, true, false, false, NULL, addr,
- addr, flags, value, 0, NULL, NULL, NULL);
+ r = amdgpu_vm_update_range(adev, vm, true, false, false, false,
+ NULL, addr, addr, flags, value, 0, NULL, NULL, NULL);
if (r)
goto error_unlock;
@@ -2730,3 +2746,53 @@ void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m)
total_done_objs);
}
#endif
+
+/**
+ * amdgpu_vm_update_fault_cache - update cached fault into.
+ * @adev: amdgpu device pointer
+ * @pasid: PASID of the VM
+ * @addr: Address of the fault
+ * @status: GPUVM fault status register
+ * @vmhub: which vmhub got the fault
+ *
+ * Cache the fault info for later use by userspace in debugging.
+ */
+void amdgpu_vm_update_fault_cache(struct amdgpu_device *adev,
+ unsigned int pasid,
+ uint64_t addr,
+ uint32_t status,
+ unsigned int vmhub)
+{
+ struct amdgpu_vm *vm;
+ unsigned long flags;
+
+ xa_lock_irqsave(&adev->vm_manager.pasids, flags);
+
+ vm = xa_load(&adev->vm_manager.pasids, pasid);
+ /* Don't update the fault cache if status is 0. In the multiple
+ * fault case, subsequent faults will return a 0 status which is
+ * useless for userspace and replaces the useful fault status, so
+ * only update if status is non-0.
+ */
+ if (vm && status) {
+ vm->fault_info.addr = addr;
+ vm->fault_info.status = status;
+ if (AMDGPU_IS_GFXHUB(vmhub)) {
+ vm->fault_info.vmhub = AMDGPU_VMHUB_TYPE_GFX;
+ vm->fault_info.vmhub |=
+ (vmhub - AMDGPU_GFXHUB_START) << AMDGPU_VMHUB_IDX_SHIFT;
+ } else if (AMDGPU_IS_MMHUB0(vmhub)) {
+ vm->fault_info.vmhub = AMDGPU_VMHUB_TYPE_MM0;
+ vm->fault_info.vmhub |=
+ (vmhub - AMDGPU_MMHUB0_START) << AMDGPU_VMHUB_IDX_SHIFT;
+ } else if (AMDGPU_IS_MMHUB1(vmhub)) {
+ vm->fault_info.vmhub = AMDGPU_VMHUB_TYPE_MM1;
+ vm->fault_info.vmhub |=
+ (vmhub - AMDGPU_MMHUB1_START) << AMDGPU_VMHUB_IDX_SHIFT;
+ } else {
+ WARN_ONCE(1, "Invalid vmhub %u\n", vmhub);
+ }
+ }
+ xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
+}
+
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 204ab13184ed..2cd86d2bf73f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -124,9 +124,16 @@ struct amdgpu_mem_stats;
* layout: max 8 GFXHUB + 4 MMHUB0 + 1 MMHUB1
*/
#define AMDGPU_MAX_VMHUBS 13
-#define AMDGPU_GFXHUB(x) (x)
-#define AMDGPU_MMHUB0(x) (8 + x)
-#define AMDGPU_MMHUB1(x) (8 + 4 + x)
+#define AMDGPU_GFXHUB_START 0
+#define AMDGPU_MMHUB0_START 8
+#define AMDGPU_MMHUB1_START 12
+#define AMDGPU_GFXHUB(x) (AMDGPU_GFXHUB_START + (x))
+#define AMDGPU_MMHUB0(x) (AMDGPU_MMHUB0_START + (x))
+#define AMDGPU_MMHUB1(x) (AMDGPU_MMHUB1_START + (x))
+
+#define AMDGPU_IS_GFXHUB(x) ((x) >= AMDGPU_GFXHUB_START && (x) < AMDGPU_MMHUB0_START)
+#define AMDGPU_IS_MMHUB0(x) ((x) >= AMDGPU_MMHUB0_START && (x) < AMDGPU_MMHUB1_START)
+#define AMDGPU_IS_MMHUB1(x) ((x) >= AMDGPU_MMHUB1_START && (x) < AMDGPU_MAX_VMHUBS)
/* Reserve 2MB at top/bottom of address space for kernel use */
#define AMDGPU_VA_RESERVED_SIZE (2ULL << 20)
@@ -239,6 +246,12 @@ struct amdgpu_vm_update_params {
* @table_freed: return true if page table is freed when updating
*/
bool table_freed;
+
+ /**
+ * @allow_override: true for memory that is not uncached: allows MTYPE
+ * to be overridden for NUMA local memory.
+ */
+ bool allow_override;
};
struct amdgpu_vm_update_funcs {
@@ -252,6 +265,15 @@ struct amdgpu_vm_update_funcs {
struct dma_fence **fence);
};
+struct amdgpu_vm_fault_info {
+ /* fault address */
+ uint64_t addr;
+ /* fault status register */
+ uint32_t status;
+ /* which vmhub? gfxhub, mmhub, etc. */
+ unsigned int vmhub;
+};
+
struct amdgpu_vm {
/* tree of virtual addresses mapped */
struct rb_root_cached va;
@@ -343,6 +365,9 @@ struct amdgpu_vm {
/* Memory partition number, -1 means any partition */
int8_t mem_id;
+
+ /* cached fault info */
+ struct amdgpu_vm_fault_info fault_info;
};
struct amdgpu_vm_manager {
@@ -418,11 +443,12 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
struct amdgpu_vm *vm,
struct dma_fence **fence);
int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
- struct amdgpu_vm *vm);
+ struct amdgpu_vm *vm,
+ struct ww_acquire_ctx *ticket);
void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base,
struct amdgpu_vm *vm, struct amdgpu_bo *bo);
int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm,
- bool immediate, bool unlocked, bool flush_tlb,
+ bool immediate, bool unlocked, bool flush_tlb, bool allow_override,
struct dma_resv *resv, uint64_t start, uint64_t last,
uint64_t flags, uint64_t offset, uint64_t vram_base,
struct ttm_resource *res, dma_addr_t *pages_addr,
@@ -554,4 +580,10 @@ static inline void amdgpu_vm_eviction_unlock(struct amdgpu_vm *vm)
mutex_unlock(&vm->eviction_lock);
}
+void amdgpu_vm_update_fault_cache(struct amdgpu_device *adev,
+ unsigned int pasid,
+ uint64_t addr,
+ uint32_t status,
+ unsigned int vmhub);
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
index 96d601e209b8..a160265ddc07 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
@@ -642,13 +642,14 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry)
if (!entry->bo)
return;
+
+ entry->bo->vm_bo = NULL;
shadow = amdgpu_bo_shadowed(entry->bo);
if (shadow) {
ttm_bo_set_bulk_move(&shadow->tbo, NULL);
amdgpu_bo_unref(&shadow);
}
ttm_bo_set_bulk_move(&entry->bo->tbo, NULL);
- entry->bo->vm_bo = NULL;
spin_lock(&entry->vm->status_lock);
list_del(&entry->vm_status);
@@ -843,14 +844,8 @@ static void amdgpu_vm_pte_update_flags(struct amdgpu_vm_update_params *params,
*/
if ((flags & AMDGPU_PTE_SYSTEM) && (adev->flags & AMD_IS_APU) &&
adev->gmc.gmc_funcs->override_vm_pte_flags &&
- num_possible_nodes() > 1) {
- if (!params->pages_addr)
- amdgpu_gmc_override_vm_pte_flags(adev, params->vm,
- addr, &flags);
- else
- dev_dbg(adev->dev,
- "override_vm_pte_flags skipped: non-contiguous\n");
- }
+ num_possible_nodes() > 1 && !params->pages_addr && params->allow_override)
+ amdgpu_gmc_override_vm_pte_flags(adev, params->vm, addr, &flags);
params->vm->update_funcs->update(params, pt, pe, addr, count, incr,
flags);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
new file mode 100644
index 000000000000..e81579708e96
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
@@ -0,0 +1,656 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/firmware.h>
+#include <drm/drm_drv.h>
+
+#include "amdgpu.h"
+#include "amdgpu_ucode.h"
+#include "amdgpu_vpe.h"
+#include "soc15_common.h"
+#include "vpe_v6_1.h"
+
+#define AMDGPU_CSA_VPE_SIZE 64
+/* VPE CSA resides in the 4th page of CSA */
+#define AMDGPU_CSA_VPE_OFFSET (4096 * 3)
+
+static void vpe_set_ring_funcs(struct amdgpu_device *adev);
+
+int amdgpu_vpe_psp_update_sram(struct amdgpu_device *adev)
+{
+ struct amdgpu_firmware_info ucode = {
+ .ucode_id = AMDGPU_UCODE_ID_VPE,
+ .mc_addr = adev->vpe.cmdbuf_gpu_addr,
+ .ucode_size = 8,
+ };
+
+ return psp_execute_ip_fw_load(&adev->psp, &ucode);
+}
+
+int amdgpu_vpe_init_microcode(struct amdgpu_vpe *vpe)
+{
+ struct amdgpu_device *adev = vpe->ring.adev;
+ const struct vpe_firmware_header_v1_0 *vpe_hdr;
+ char fw_prefix[32], fw_name[64];
+ int ret;
+
+ amdgpu_ucode_ip_version_decode(adev, VPE_HWIP, fw_prefix, sizeof(fw_prefix));
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", fw_prefix);
+
+ ret = amdgpu_ucode_request(adev, &adev->vpe.fw, fw_name);
+ if (ret)
+ goto out;
+
+ vpe_hdr = (const struct vpe_firmware_header_v1_0 *)adev->vpe.fw->data;
+ adev->vpe.fw_version = le32_to_cpu(vpe_hdr->header.ucode_version);
+ adev->vpe.feature_version = le32_to_cpu(vpe_hdr->ucode_feature_version);
+
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+ struct amdgpu_firmware_info *info;
+
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_VPE_CTX];
+ info->ucode_id = AMDGPU_UCODE_ID_VPE_CTX;
+ info->fw = adev->vpe.fw;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(vpe_hdr->ctx_ucode_size_bytes), PAGE_SIZE);
+
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_VPE_CTL];
+ info->ucode_id = AMDGPU_UCODE_ID_VPE_CTL;
+ info->fw = adev->vpe.fw;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(vpe_hdr->ctl_ucode_size_bytes), PAGE_SIZE);
+ }
+
+ return 0;
+out:
+ dev_err(adev->dev, "fail to initialize vpe microcode\n");
+ release_firmware(adev->vpe.fw);
+ adev->vpe.fw = NULL;
+ return ret;
+}
+
+int amdgpu_vpe_ring_init(struct amdgpu_vpe *vpe)
+{
+ struct amdgpu_device *adev = container_of(vpe, struct amdgpu_device, vpe);
+ struct amdgpu_ring *ring = &vpe->ring;
+ int ret;
+
+ ring->ring_obj = NULL;
+ ring->use_doorbell = true;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
+ ring->doorbell_index = (adev->doorbell_index.vpe_ring << 1);
+ snprintf(ring->name, 4, "vpe");
+
+ ret = amdgpu_ring_init(adev, ring, 1024, &vpe->trap_irq, 0,
+ AMDGPU_RING_PRIO_DEFAULT, NULL);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int amdgpu_vpe_ring_fini(struct amdgpu_vpe *vpe)
+{
+ amdgpu_ring_fini(&vpe->ring);
+
+ return 0;
+}
+
+static int vpe_early_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_vpe *vpe = &adev->vpe;
+
+ switch (amdgpu_ip_version(adev, VPE_HWIP, 0)) {
+ case IP_VERSION(6, 1, 0):
+ vpe_v6_1_set_funcs(vpe);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ vpe_set_ring_funcs(adev);
+ vpe_set_regs(vpe);
+
+ return 0;
+}
+
+
+static int vpe_common_init(struct amdgpu_vpe *vpe)
+{
+ struct amdgpu_device *adev = container_of(vpe, struct amdgpu_device, vpe);
+ int r;
+
+ r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_GTT,
+ &adev->vpe.cmdbuf_obj,
+ &adev->vpe.cmdbuf_gpu_addr,
+ (void **)&adev->vpe.cmdbuf_cpu_addr);
+ if (r) {
+ dev_err(adev->dev, "VPE: failed to allocate cmdbuf bo %d\n", r);
+ return r;
+ }
+
+ return 0;
+}
+
+static int vpe_sw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_vpe *vpe = &adev->vpe;
+ int ret;
+
+ ret = vpe_common_init(vpe);
+ if (ret)
+ goto out;
+
+ ret = vpe_irq_init(vpe);
+ if (ret)
+ goto out;
+
+ ret = vpe_ring_init(vpe);
+ if (ret)
+ goto out;
+
+ ret = vpe_init_microcode(vpe);
+ if (ret)
+ goto out;
+out:
+ return ret;
+}
+
+static int vpe_sw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_vpe *vpe = &adev->vpe;
+
+ release_firmware(vpe->fw);
+ vpe->fw = NULL;
+
+ vpe_ring_fini(vpe);
+
+ amdgpu_bo_free_kernel(&adev->vpe.cmdbuf_obj,
+ &adev->vpe.cmdbuf_gpu_addr,
+ (void **)&adev->vpe.cmdbuf_cpu_addr);
+
+ return 0;
+}
+
+static int vpe_hw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_vpe *vpe = &adev->vpe;
+ int ret;
+
+ ret = vpe_load_microcode(vpe);
+ if (ret)
+ return ret;
+
+ ret = vpe_ring_start(vpe);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int vpe_hw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_vpe *vpe = &adev->vpe;
+
+ vpe_ring_stop(vpe);
+
+ return 0;
+}
+
+static int vpe_suspend(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ return vpe_hw_fini(adev);
+}
+
+static int vpe_resume(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ return vpe_hw_init(adev);
+}
+
+static void vpe_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ if (i == 0)
+ amdgpu_ring_write(ring, ring->funcs->nop |
+ VPE_CMD_NOP_HEADER_COUNT(count - 1));
+ else
+ amdgpu_ring_write(ring, ring->funcs->nop);
+}
+
+static uint64_t vpe_get_csa_mc_addr(struct amdgpu_ring *ring, uint32_t vmid)
+{
+ struct amdgpu_device *adev = ring->adev;
+ uint32_t index = 0;
+ uint64_t csa_mc_addr;
+
+ if (amdgpu_sriov_vf(adev) || vmid == 0 || !adev->gfx.mcbp)
+ return 0;
+
+ csa_mc_addr = amdgpu_csa_vaddr(adev) + AMDGPU_CSA_VPE_OFFSET +
+ index * AMDGPU_CSA_VPE_SIZE;
+
+ return csa_mc_addr;
+}
+
+static void vpe_ring_emit_ib(struct amdgpu_ring *ring,
+ struct amdgpu_job *job,
+ struct amdgpu_ib *ib,
+ uint32_t flags)
+{
+ uint32_t vmid = AMDGPU_JOB_GET_VMID(job);
+ uint64_t csa_mc_addr = vpe_get_csa_mc_addr(ring, vmid);
+
+ amdgpu_ring_write(ring, VPE_CMD_HEADER(VPE_CMD_OPCODE_INDIRECT, 0) |
+ VPE_CMD_INDIRECT_HEADER_VMID(vmid & 0xf));
+
+ /* base must be 32 byte aligned */
+ amdgpu_ring_write(ring, ib->gpu_addr & 0xffffffe0);
+ amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
+ amdgpu_ring_write(ring, ib->length_dw);
+ amdgpu_ring_write(ring, lower_32_bits(csa_mc_addr));
+ amdgpu_ring_write(ring, upper_32_bits(csa_mc_addr));
+}
+
+static void vpe_ring_emit_fence(struct amdgpu_ring *ring, uint64_t addr,
+ uint64_t seq, unsigned int flags)
+{
+ int i = 0;
+
+ do {
+ /* write the fence */
+ amdgpu_ring_write(ring, VPE_CMD_HEADER(VPE_CMD_OPCODE_FENCE, 0));
+ /* zero in first two bits */
+ WARN_ON_ONCE(addr & 0x3);
+ amdgpu_ring_write(ring, lower_32_bits(addr));
+ amdgpu_ring_write(ring, upper_32_bits(addr));
+ amdgpu_ring_write(ring, i == 0 ? lower_32_bits(seq) : upper_32_bits(seq));
+ addr += 4;
+ } while ((flags & AMDGPU_FENCE_FLAG_64BIT) && (i++ < 1));
+
+ if (flags & AMDGPU_FENCE_FLAG_INT) {
+ /* generate an interrupt */
+ amdgpu_ring_write(ring, VPE_CMD_HEADER(VPE_CMD_OPCODE_TRAP, 0));
+ amdgpu_ring_write(ring, 0);
+ }
+
+}
+
+static void vpe_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
+{
+ uint32_t seq = ring->fence_drv.sync_seq;
+ uint64_t addr = ring->fence_drv.gpu_addr;
+
+ /* wait for idle */
+ amdgpu_ring_write(ring, VPE_CMD_HEADER(VPE_CMD_OPCODE_POLL_REGMEM,
+ VPE_POLL_REGMEM_SUBOP_REGMEM) |
+ VPE_CMD_POLL_REGMEM_HEADER_FUNC(3) | /* equal */
+ VPE_CMD_POLL_REGMEM_HEADER_MEM(1));
+ amdgpu_ring_write(ring, addr & 0xfffffffc);
+ amdgpu_ring_write(ring, upper_32_bits(addr));
+ amdgpu_ring_write(ring, seq); /* reference */
+ amdgpu_ring_write(ring, 0xffffffff); /* mask */
+ amdgpu_ring_write(ring, VPE_CMD_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
+ VPE_CMD_POLL_REGMEM_DW5_INTERVAL(4));
+}
+
+static void vpe_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val)
+{
+ amdgpu_ring_write(ring, VPE_CMD_HEADER(VPE_CMD_OPCODE_REG_WRITE, 0));
+ amdgpu_ring_write(ring, reg << 2);
+ amdgpu_ring_write(ring, val);
+}
+
+static void vpe_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
+ uint32_t val, uint32_t mask)
+{
+ amdgpu_ring_write(ring, VPE_CMD_HEADER(VPE_CMD_OPCODE_POLL_REGMEM,
+ VPE_POLL_REGMEM_SUBOP_REGMEM) |
+ VPE_CMD_POLL_REGMEM_HEADER_FUNC(3) | /* equal */
+ VPE_CMD_POLL_REGMEM_HEADER_MEM(0));
+ amdgpu_ring_write(ring, reg << 2);
+ amdgpu_ring_write(ring, 0);
+ amdgpu_ring_write(ring, val); /* reference */
+ amdgpu_ring_write(ring, mask); /* mask */
+ amdgpu_ring_write(ring, VPE_CMD_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
+ VPE_CMD_POLL_REGMEM_DW5_INTERVAL(10));
+}
+
+static void vpe_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned int vmid,
+ uint64_t pd_addr)
+{
+ amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
+}
+
+static unsigned int vpe_ring_init_cond_exec(struct amdgpu_ring *ring)
+{
+ unsigned int ret;
+
+ amdgpu_ring_write(ring, VPE_CMD_HEADER(VPE_CMD_OPCODE_COND_EXE, 0));
+ amdgpu_ring_write(ring, lower_32_bits(ring->cond_exe_gpu_addr));
+ amdgpu_ring_write(ring, upper_32_bits(ring->cond_exe_gpu_addr));
+ amdgpu_ring_write(ring, 1);
+ ret = ring->wptr & ring->buf_mask;/* this is the offset we need patch later */
+ amdgpu_ring_write(ring, 0x55aa55aa);/* insert dummy here and patch it later */
+
+ return ret;
+}
+
+static void vpe_ring_patch_cond_exec(struct amdgpu_ring *ring, unsigned int offset)
+{
+ unsigned int cur;
+
+ WARN_ON_ONCE(offset > ring->buf_mask);
+ WARN_ON_ONCE(ring->ring[offset] != 0x55aa55aa);
+
+ cur = (ring->wptr - 1) & ring->buf_mask;
+ if (cur > offset)
+ ring->ring[offset] = cur - offset;
+ else
+ ring->ring[offset] = (ring->buf_mask + 1) - offset + cur;
+}
+
+static int vpe_ring_preempt_ib(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_vpe *vpe = &adev->vpe;
+ uint32_t preempt_reg = vpe->regs.queue0_preempt;
+ int i, r = 0;
+
+ /* assert preemption condition */
+ amdgpu_ring_set_preempt_cond_exec(ring, false);
+
+ /* emit the trailing fence */
+ ring->trail_seq += 1;
+ amdgpu_ring_alloc(ring, 10);
+ vpe_ring_emit_fence(ring, ring->trail_fence_gpu_addr, ring->trail_seq, 0);
+ amdgpu_ring_commit(ring);
+
+ /* assert IB preemption */
+ WREG32(vpe_get_reg_offset(vpe, ring->me, preempt_reg), 1);
+
+ /* poll the trailing fence */
+ for (i = 0; i < adev->usec_timeout; i++) {
+ if (ring->trail_seq ==
+ le32_to_cpu(*(ring->trail_fence_cpu_addr)))
+ break;
+ udelay(1);
+ }
+
+ if (i >= adev->usec_timeout) {
+ r = -EINVAL;
+ dev_err(adev->dev, "ring %d failed to be preempted\n", ring->idx);
+ }
+
+ /* deassert IB preemption */
+ WREG32(vpe_get_reg_offset(vpe, ring->me, preempt_reg), 0);
+
+ /* deassert the preemption condition */
+ amdgpu_ring_set_preempt_cond_exec(ring, true);
+
+ return r;
+}
+
+static int vpe_set_clockgating_state(void *handle,
+ enum amd_clockgating_state state)
+{
+ return 0;
+}
+
+static int vpe_set_powergating_state(void *handle,
+ enum amd_powergating_state state)
+{
+ return 0;
+}
+
+static uint64_t vpe_ring_get_rptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_vpe *vpe = &adev->vpe;
+ uint64_t rptr;
+
+ if (ring->use_doorbell) {
+ rptr = atomic64_read((atomic64_t *)ring->rptr_cpu_addr);
+ dev_dbg(adev->dev, "rptr/doorbell before shift == 0x%016llx\n", rptr);
+ } else {
+ rptr = RREG32(vpe_get_reg_offset(vpe, ring->me, vpe->regs.queue0_rb_rptr_hi));
+ rptr = rptr << 32;
+ rptr |= RREG32(vpe_get_reg_offset(vpe, ring->me, vpe->regs.queue0_rb_rptr_lo));
+ dev_dbg(adev->dev, "rptr before shift [%i] == 0x%016llx\n", ring->me, rptr);
+ }
+
+ return (rptr >> 2);
+}
+
+static uint64_t vpe_ring_get_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_vpe *vpe = &adev->vpe;
+ uint64_t wptr;
+
+ if (ring->use_doorbell) {
+ wptr = atomic64_read((atomic64_t *)ring->wptr_cpu_addr);
+ dev_dbg(adev->dev, "wptr/doorbell before shift == 0x%016llx\n", wptr);
+ } else {
+ wptr = RREG32(vpe_get_reg_offset(vpe, ring->me, vpe->regs.queue0_rb_wptr_hi));
+ wptr = wptr << 32;
+ wptr |= RREG32(vpe_get_reg_offset(vpe, ring->me, vpe->regs.queue0_rb_wptr_lo));
+ dev_dbg(adev->dev, "wptr before shift [%i] == 0x%016llx\n", ring->me, wptr);
+ }
+
+ return (wptr >> 2);
+}
+
+static void vpe_ring_set_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_vpe *vpe = &adev->vpe;
+
+ if (ring->use_doorbell) {
+ dev_dbg(adev->dev, "Using doorbell, \
+ wptr_offs == 0x%08x, \
+ lower_32_bits(ring->wptr) << 2 == 0x%08x, \
+ upper_32_bits(ring->wptr) << 2 == 0x%08x\n",
+ ring->wptr_offs,
+ lower_32_bits(ring->wptr << 2),
+ upper_32_bits(ring->wptr << 2));
+ atomic64_set((atomic64_t *)ring->wptr_cpu_addr, ring->wptr << 2);
+ WDOORBELL64(ring->doorbell_index, ring->wptr << 2);
+ } else {
+ dev_dbg(adev->dev, "Not using doorbell, \
+ regVPEC_QUEUE0_RB_WPTR == 0x%08x, \
+ regVPEC_QUEUE0_RB_WPTR_HI == 0x%08x\n",
+ lower_32_bits(ring->wptr << 2),
+ upper_32_bits(ring->wptr << 2));
+ WREG32(vpe_get_reg_offset(vpe, ring->me, vpe->regs.queue0_rb_wptr_lo),
+ lower_32_bits(ring->wptr << 2));
+ WREG32(vpe_get_reg_offset(vpe, ring->me, vpe->regs.queue0_rb_wptr_hi),
+ upper_32_bits(ring->wptr << 2));
+ }
+}
+
+static int vpe_ring_test_ring(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ const uint32_t test_pattern = 0xdeadbeef;
+ uint32_t index, i;
+ uint64_t wb_addr;
+ int ret;
+
+ ret = amdgpu_device_wb_get(adev, &index);
+ if (ret) {
+ dev_err(adev->dev, "(%d) failed to allocate wb slot\n", ret);
+ return ret;
+ }
+
+ adev->wb.wb[index] = 0;
+ wb_addr = adev->wb.gpu_addr + (index * 4);
+
+ ret = amdgpu_ring_alloc(ring, 4);
+ if (ret) {
+ dev_err(adev->dev, "amdgpu: dma failed to lock ring %d (%d).\n", ring->idx, ret);
+ goto out;
+ }
+
+ amdgpu_ring_write(ring, VPE_CMD_HEADER(VPE_CMD_OPCODE_FENCE, 0));
+ amdgpu_ring_write(ring, lower_32_bits(wb_addr));
+ amdgpu_ring_write(ring, upper_32_bits(wb_addr));
+ amdgpu_ring_write(ring, test_pattern);
+ amdgpu_ring_commit(ring);
+
+ for (i = 0; i < adev->usec_timeout; i++) {
+ if (le32_to_cpu(adev->wb.wb[index]) == test_pattern)
+ goto out;
+ udelay(1);
+ }
+
+ ret = -ETIMEDOUT;
+out:
+ amdgpu_device_wb_free(adev, index);
+
+ return ret;
+}
+
+static int vpe_ring_test_ib(struct amdgpu_ring *ring, long timeout)
+{
+ struct amdgpu_device *adev = ring->adev;
+ const uint32_t test_pattern = 0xdeadbeef;
+ struct amdgpu_ib ib = {};
+ struct dma_fence *f = NULL;
+ uint32_t index;
+ uint64_t wb_addr;
+ int ret;
+
+ ret = amdgpu_device_wb_get(adev, &index);
+ if (ret) {
+ dev_err(adev->dev, "(%d) failed to allocate wb slot\n", ret);
+ return ret;
+ }
+
+ adev->wb.wb[index] = 0;
+ wb_addr = adev->wb.gpu_addr + (index * 4);
+
+ ret = amdgpu_ib_get(adev, NULL, 256, AMDGPU_IB_POOL_DIRECT, &ib);
+ if (ret)
+ goto err0;
+
+ ib.ptr[0] = VPE_CMD_HEADER(VPE_CMD_OPCODE_FENCE, 0);
+ ib.ptr[1] = lower_32_bits(wb_addr);
+ ib.ptr[2] = upper_32_bits(wb_addr);
+ ib.ptr[3] = test_pattern;
+ ib.ptr[4] = VPE_CMD_HEADER(VPE_CMD_OPCODE_NOP, 0);
+ ib.ptr[5] = VPE_CMD_HEADER(VPE_CMD_OPCODE_NOP, 0);
+ ib.ptr[6] = VPE_CMD_HEADER(VPE_CMD_OPCODE_NOP, 0);
+ ib.ptr[7] = VPE_CMD_HEADER(VPE_CMD_OPCODE_NOP, 0);
+ ib.length_dw = 8;
+
+ ret = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
+ if (ret)
+ goto err1;
+
+ ret = dma_fence_wait_timeout(f, false, timeout);
+ if (ret <= 0) {
+ ret = ret ? : -ETIMEDOUT;
+ goto err1;
+ }
+
+ ret = (le32_to_cpu(adev->wb.wb[index]) == test_pattern) ? 0 : -EINVAL;
+
+err1:
+ amdgpu_ib_free(adev, &ib, NULL);
+ dma_fence_put(f);
+err0:
+ amdgpu_device_wb_free(adev, index);
+
+ return ret;
+}
+
+static const struct amdgpu_ring_funcs vpe_ring_funcs = {
+ .type = AMDGPU_RING_TYPE_VPE,
+ .align_mask = 0xf,
+ .nop = VPE_CMD_HEADER(VPE_CMD_OPCODE_NOP, 0),
+ .support_64bit_ptrs = true,
+ .get_rptr = vpe_ring_get_rptr,
+ .get_wptr = vpe_ring_get_wptr,
+ .set_wptr = vpe_ring_set_wptr,
+ .emit_frame_size =
+ 5 + /* vpe_ring_init_cond_exec */
+ 6 + /* vpe_ring_emit_pipeline_sync */
+ 10 + 10 + 10 + /* vpe_ring_emit_fence */
+ /* vpe_ring_emit_vm_flush */
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 6,
+ .emit_ib_size = 7 + 6,
+ .emit_ib = vpe_ring_emit_ib,
+ .emit_pipeline_sync = vpe_ring_emit_pipeline_sync,
+ .emit_fence = vpe_ring_emit_fence,
+ .emit_vm_flush = vpe_ring_emit_vm_flush,
+ .emit_wreg = vpe_ring_emit_wreg,
+ .emit_reg_wait = vpe_ring_emit_reg_wait,
+ .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+ .insert_nop = vpe_ring_insert_nop,
+ .pad_ib = amdgpu_ring_generic_pad_ib,
+ .test_ring = vpe_ring_test_ring,
+ .test_ib = vpe_ring_test_ib,
+ .init_cond_exec = vpe_ring_init_cond_exec,
+ .patch_cond_exec = vpe_ring_patch_cond_exec,
+ .preempt_ib = vpe_ring_preempt_ib,
+};
+
+static void vpe_set_ring_funcs(struct amdgpu_device *adev)
+{
+ adev->vpe.ring.funcs = &vpe_ring_funcs;
+}
+
+const struct amd_ip_funcs vpe_ip_funcs = {
+ .name = "vpe_v6_1",
+ .early_init = vpe_early_init,
+ .late_init = NULL,
+ .sw_init = vpe_sw_init,
+ .sw_fini = vpe_sw_fini,
+ .hw_init = vpe_hw_init,
+ .hw_fini = vpe_hw_fini,
+ .suspend = vpe_suspend,
+ .resume = vpe_resume,
+ .soft_reset = NULL,
+ .set_clockgating_state = vpe_set_clockgating_state,
+ .set_powergating_state = vpe_set_powergating_state,
+};
+
+const struct amdgpu_ip_block_version vpe_v6_1_ip_block = {
+ .type = AMD_IP_BLOCK_TYPE_VPE,
+ .major = 6,
+ .minor = 1,
+ .rev = 0,
+ .funcs = &vpe_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.h
new file mode 100644
index 000000000000..29d56f7ae4a9
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __AMDGPU_VPE_H__
+#define __AMDGPU_VPE_H__
+
+#include "amdgpu_ring.h"
+#include "amdgpu_irq.h"
+#include "vpe_6_1_fw_if.h"
+
+struct amdgpu_vpe;
+
+struct vpe_funcs {
+ uint32_t (*get_reg_offset)(struct amdgpu_vpe *vpe, uint32_t inst, uint32_t offset);
+ int (*set_regs)(struct amdgpu_vpe *vpe);
+ int (*irq_init)(struct amdgpu_vpe *vpe);
+ int (*init_microcode)(struct amdgpu_vpe *vpe);
+ int (*load_microcode)(struct amdgpu_vpe *vpe);
+ int (*ring_init)(struct amdgpu_vpe *vpe);
+ int (*ring_start)(struct amdgpu_vpe *vpe);
+ int (*ring_stop)(struct amdgpu_vpe *vpe);
+ int (*ring_fini)(struct amdgpu_vpe *vpe);
+};
+
+struct vpe_regs {
+ uint32_t queue0_rb_rptr_lo;
+ uint32_t queue0_rb_rptr_hi;
+ uint32_t queue0_rb_wptr_lo;
+ uint32_t queue0_rb_wptr_hi;
+ uint32_t queue0_preempt;
+};
+
+struct amdgpu_vpe {
+ struct amdgpu_ring ring;
+ struct amdgpu_irq_src trap_irq;
+
+ const struct vpe_funcs *funcs;
+ struct vpe_regs regs;
+
+ const struct firmware *fw;
+ uint32_t fw_version;
+ uint32_t feature_version;
+
+ struct amdgpu_bo *cmdbuf_obj;
+ uint64_t cmdbuf_gpu_addr;
+ uint32_t *cmdbuf_cpu_addr;
+};
+
+int amdgpu_vpe_psp_update_sram(struct amdgpu_device *adev);
+int amdgpu_vpe_init_microcode(struct amdgpu_vpe *vpe);
+int amdgpu_vpe_ring_init(struct amdgpu_vpe *vpe);
+int amdgpu_vpe_ring_fini(struct amdgpu_vpe *vpe);
+
+#define vpe_ring_init(vpe) ((vpe)->funcs->ring_init ? (vpe)->funcs->ring_init((vpe)) : 0)
+#define vpe_ring_start(vpe) ((vpe)->funcs->ring_start ? (vpe)->funcs->ring_start((vpe)) : 0)
+#define vpe_ring_stop(vpe) ((vpe)->funcs->ring_stop ? (vpe)->funcs->ring_stop((vpe)) : 0)
+#define vpe_ring_fini(vpe) ((vpe)->funcs->ring_fini ? (vpe)->funcs->ring_fini((vpe)) : 0)
+
+#define vpe_get_reg_offset(vpe, inst, offset) \
+ ((vpe)->funcs->get_reg_offset ? (vpe)->funcs->get_reg_offset((vpe), (inst), (offset)) : 0)
+#define vpe_set_regs(vpe) \
+ ((vpe)->funcs->set_regs ? (vpe)->funcs->set_regs((vpe)) : 0)
+#define vpe_irq_init(vpe) \
+ ((vpe)->funcs->irq_init ? (vpe)->funcs->irq_init((vpe)) : 0)
+#define vpe_init_microcode(vpe) \
+ ((vpe)->funcs->init_microcode ? (vpe)->funcs->init_microcode((vpe)) : 0)
+#define vpe_load_microcode(vpe) \
+ ((vpe)->funcs->load_microcode ? (vpe)->funcs->load_microcode((vpe)) : 0)
+
+extern const struct amdgpu_ip_block_version vpe_v6_1_ip_block;
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
index c7085a747b03..08916538a615 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -77,7 +77,16 @@ static inline bool amdgpu_is_vram_mgr_blocks_contiguous(struct list_head *head)
return true;
}
+static inline u64 amdgpu_vram_mgr_blocks_size(struct list_head *head)
+{
+ struct drm_buddy_block *block;
+ u64 size = 0;
+
+ list_for_each_entry(block, head, link)
+ size += amdgpu_vram_mgr_block_size(block);
+ return size;
+}
/**
* DOC: mem_info_vram_total
@@ -424,9 +433,9 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
const struct ttm_place *place,
struct ttm_resource **res)
{
- u64 vis_usage = 0, max_bytes, cur_size, min_block_size;
struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
struct amdgpu_device *adev = to_amdgpu_device(mgr);
+ u64 vis_usage = 0, max_bytes, min_block_size;
struct amdgpu_vram_mgr_resource *vres;
u64 size, remaining_size, lpfn, fpfn;
struct drm_buddy *mm = &mgr->mm;
@@ -474,6 +483,9 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
if (place->flags & TTM_PL_FLAG_TOPDOWN)
vres->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+ if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
+ vres->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION;
+
if (fpfn || lpfn != mgr->mm.size)
/* Allocate blocks in desired range */
vres->flags |= DRM_BUDDY_RANGE_ALLOCATION;
@@ -496,25 +508,6 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
!(size & (((u64)pages_per_block << PAGE_SHIFT) - 1)))
min_block_size = (u64)pages_per_block << PAGE_SHIFT;
- cur_size = size;
-
- if (fpfn + size != (u64)place->lpfn << PAGE_SHIFT) {
- /*
- * Except for actual range allocation, modify the size and
- * min_block_size conforming to continuous flag enablement
- */
- if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
- size = roundup_pow_of_two(size);
- min_block_size = size;
- /*
- * Modify the size value if size is not
- * aligned with min_block_size
- */
- } else if (!IS_ALIGNED(size, min_block_size)) {
- size = round_up(size, min_block_size);
- }
- }
-
r = drm_buddy_alloc_blocks(mm, fpfn,
lpfn,
size,
@@ -531,41 +524,9 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
}
mutex_unlock(&mgr->lock);
- if (cur_size != size) {
- struct drm_buddy_block *block;
- struct list_head *trim_list;
- u64 original_size;
- LIST_HEAD(temp);
-
- trim_list = &vres->blocks;
- original_size = (u64)vres->base.size;
-
- /*
- * If size value is rounded up to min_block_size, trim the last
- * block to the required size
- */
- if (!list_is_singular(&vres->blocks)) {
- block = list_last_entry(&vres->blocks, typeof(*block), link);
- list_move_tail(&block->link, &temp);
- trim_list = &temp;
- /*
- * Compute the original_size value by subtracting the
- * last block size with (aligned size - original size)
- */
- original_size = amdgpu_vram_mgr_block_size(block) - (size - cur_size);
- }
-
- mutex_lock(&mgr->lock);
- drm_buddy_block_trim(mm,
- original_size,
- trim_list);
- mutex_unlock(&mgr->lock);
-
- if (!list_empty(&temp))
- list_splice_tail(trim_list, &vres->blocks);
- }
-
vres->base.start = 0;
+ size = max_t(u64, amdgpu_vram_mgr_blocks_size(&vres->blocks),
+ vres->base.size);
list_for_each_entry(block, &vres->blocks, link) {
unsigned long start;
@@ -573,8 +534,8 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
amdgpu_vram_mgr_block_size(block);
start >>= PAGE_SHIFT;
- if (start > PFN_UP(vres->base.size))
- start -= PFN_UP(vres->base.size);
+ if (start > PFN_UP(size))
+ start -= PFN_UP(size);
else
start = 0;
vres->base.start = max(vres->base.start, start);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
index 565a1fa436d4..2b99eed5ba19 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
@@ -163,16 +163,11 @@ int amdgpu_xcp_init(struct amdgpu_xcp_mgr *xcp_mgr, int num_xcps, int mode)
return 0;
}
-int amdgpu_xcp_switch_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, int mode)
+static int __amdgpu_xcp_switch_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr,
+ int mode)
{
int ret, curr_mode, num_xcps = 0;
- if (!xcp_mgr || mode == AMDGPU_XCP_MODE_NONE)
- return -EINVAL;
-
- if (xcp_mgr->mode == mode)
- return 0;
-
if (!xcp_mgr->funcs || !xcp_mgr->funcs->switch_partition_mode)
return 0;
@@ -201,6 +196,25 @@ out:
return ret;
}
+int amdgpu_xcp_switch_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, int mode)
+{
+ if (!xcp_mgr || mode == AMDGPU_XCP_MODE_NONE)
+ return -EINVAL;
+
+ if (xcp_mgr->mode == mode)
+ return 0;
+
+ return __amdgpu_xcp_switch_partition_mode(xcp_mgr, mode);
+}
+
+int amdgpu_xcp_restore_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr)
+{
+ if (!xcp_mgr || xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
+ return 0;
+
+ return __amdgpu_xcp_switch_partition_mode(xcp_mgr, xcp_mgr->mode);
+}
+
int amdgpu_xcp_query_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, u32 flags)
{
int mode;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
index 9a1036aeec2a..90138bc5f03d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
@@ -129,6 +129,7 @@ int amdgpu_xcp_mgr_init(struct amdgpu_device *adev, int init_mode,
int amdgpu_xcp_init(struct amdgpu_xcp_mgr *xcp_mgr, int num_xcps, int mode);
int amdgpu_xcp_query_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, u32 flags);
int amdgpu_xcp_switch_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, int mode);
+int amdgpu_xcp_restore_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr);
int amdgpu_xcp_get_partition(struct amdgpu_xcp_mgr *xcp_mgr,
enum AMDGPU_XCP_IP_BLOCK ip, int instance);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
index 7e91b24784e5..bd20cb3b9819 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -103,6 +103,53 @@ static const int walf_pcs_err_noncorrectable_mask_reg_aldebaran[] = {
smnPCS_GOPX1_PCS_ERROR_NONCORRECTABLE_MASK + 0x100000
};
+static const int xgmi3x16_pcs_err_status_reg_v6_4[] = {
+ smnPCS_XGMI3X16_PCS_ERROR_STATUS,
+ smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x100000
+};
+
+static const int xgmi3x16_pcs_err_noncorrectable_mask_reg_v6_4[] = {
+ smnPCS_XGMI3X16_PCS_ERROR_NONCORRECTABLE_MASK,
+ smnPCS_XGMI3X16_PCS_ERROR_NONCORRECTABLE_MASK + 0x100000
+};
+
+static const u64 xgmi_v6_4_0_mca_base_array[] = {
+ 0x11a09200,
+ 0x11b09200,
+};
+
+static const char *xgmi_v6_4_0_ras_error_code_ext[32] = {
+ [0x00] = "XGMI PCS DataLossErr",
+ [0x01] = "XGMI PCS TrainingErr",
+ [0x02] = "XGMI PCS FlowCtrlAckErr",
+ [0x03] = "XGMI PCS RxFifoUnderflowErr",
+ [0x04] = "XGMI PCS RxFifoOverflowErr",
+ [0x05] = "XGMI PCS CRCErr",
+ [0x06] = "XGMI PCS BERExceededErr",
+ [0x07] = "XGMI PCS TxMetaDataErr",
+ [0x08] = "XGMI PCS ReplayBufParityErr",
+ [0x09] = "XGMI PCS DataParityErr",
+ [0x0a] = "XGMI PCS ReplayFifoOverflowErr",
+ [0x0b] = "XGMI PCS ReplayFifoUnderflowErr",
+ [0x0c] = "XGMI PCS ElasticFifoOverflowErr",
+ [0x0d] = "XGMI PCS DeskewErr",
+ [0x0e] = "XGMI PCS FlowCtrlCRCErr",
+ [0x0f] = "XGMI PCS DataStartupLimitErr",
+ [0x10] = "XGMI PCS FCInitTimeoutErr",
+ [0x11] = "XGMI PCS RecoveryTimeoutErr",
+ [0x12] = "XGMI PCS ReadySerialTimeoutErr",
+ [0x13] = "XGMI PCS ReadySerialAttemptErr",
+ [0x14] = "XGMI PCS RecoveryAttemptErr",
+ [0x15] = "XGMI PCS RecoveryRelockAttemptErr",
+ [0x16] = "XGMI PCS ReplayAttemptErr",
+ [0x17] = "XGMI PCS SyncHdrErr",
+ [0x18] = "XGMI PCS TxReplayTimeoutErr",
+ [0x19] = "XGMI PCS RxReplayTimeoutErr",
+ [0x1a] = "XGMI PCS LinkSubTxTimeoutErr",
+ [0x1b] = "XGMI PCS LinkSubRxTimeoutErr",
+ [0x1c] = "XGMI PCS RxCMDPktErr",
+};
+
static const struct amdgpu_pcs_ras_field xgmi_pcs_ras_fields[] = {
{"XGMI PCS DataLossErr",
SOC15_REG_FIELD(XGMI0_PCS_GOPX16_PCS_ERROR_STATUS, DataLossErr)},
@@ -325,6 +372,17 @@ static ssize_t amdgpu_xgmi_show_device_id(struct device *dev,
}
+static ssize_t amdgpu_xgmi_show_physical_id(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ return sysfs_emit(buf, "%u\n", adev->gmc.xgmi.physical_node_id);
+
+}
+
static ssize_t amdgpu_xgmi_show_num_hops(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -390,6 +448,7 @@ static ssize_t amdgpu_xgmi_show_error(struct device *dev,
static DEVICE_ATTR(xgmi_device_id, S_IRUGO, amdgpu_xgmi_show_device_id, NULL);
+static DEVICE_ATTR(xgmi_physical_id, 0444, amdgpu_xgmi_show_physical_id, NULL);
static DEVICE_ATTR(xgmi_error, S_IRUGO, amdgpu_xgmi_show_error, NULL);
static DEVICE_ATTR(xgmi_num_hops, S_IRUGO, amdgpu_xgmi_show_num_hops, NULL);
static DEVICE_ATTR(xgmi_num_links, S_IRUGO, amdgpu_xgmi_show_num_links, NULL);
@@ -407,6 +466,12 @@ static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev,
return ret;
}
+ ret = device_create_file(adev->dev, &dev_attr_xgmi_physical_id);
+ if (ret) {
+ dev_err(adev->dev, "XGMI: Failed to create device file xgmi_physical_id\n");
+ return ret;
+ }
+
/* Create xgmi error file */
ret = device_create_file(adev->dev, &dev_attr_xgmi_error);
if (ret)
@@ -448,6 +513,7 @@ remove_link:
remove_file:
device_remove_file(adev->dev, &dev_attr_xgmi_device_id);
+ device_remove_file(adev->dev, &dev_attr_xgmi_physical_id);
device_remove_file(adev->dev, &dev_attr_xgmi_error);
device_remove_file(adev->dev, &dev_attr_xgmi_num_hops);
device_remove_file(adev->dev, &dev_attr_xgmi_num_links);
@@ -463,6 +529,7 @@ static void amdgpu_xgmi_sysfs_rem_dev_info(struct amdgpu_device *adev,
memset(node, 0, sizeof(node));
device_remove_file(adev->dev, &dev_attr_xgmi_device_id);
+ device_remove_file(adev->dev, &dev_attr_xgmi_physical_id);
device_remove_file(adev->dev, &dev_attr_xgmi_error);
device_remove_file(adev->dev, &dev_attr_xgmi_num_hops);
device_remove_file(adev->dev, &dev_attr_xgmi_num_links);
@@ -888,7 +955,7 @@ static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev, struct ras_comm
adev->gmc.xgmi.num_physical_nodes == 0)
return 0;
- adev->gmc.xgmi.ras->ras_block.hw_ops->reset_ras_error_count(adev);
+ amdgpu_ras_reset_error_count(adev, AMDGPU_RAS_BLOCK__XGMI_WAFL);
return amdgpu_ras_block_late_init(adev, ras_block);
}
@@ -906,7 +973,7 @@ static void pcs_clear_status(struct amdgpu_device *adev, uint32_t pcs_status_reg
WREG32_PCIE(pcs_status_reg, 0);
}
-static void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev)
+static void amdgpu_xgmi_legacy_reset_ras_error_count(struct amdgpu_device *adev)
{
uint32_t i;
@@ -932,6 +999,49 @@ static void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev)
default:
break;
}
+
+ switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
+ case IP_VERSION(6, 4, 0):
+ for (i = 0; i < ARRAY_SIZE(xgmi3x16_pcs_err_status_reg_v6_4); i++)
+ pcs_clear_status(adev,
+ xgmi3x16_pcs_err_status_reg_v6_4[i]);
+ break;
+ default:
+ break;
+ }
+}
+
+static void __xgmi_v6_4_0_reset_error_count(struct amdgpu_device *adev, int xgmi_inst, u64 mca_base)
+{
+ WREG64_MCA(xgmi_inst, mca_base, MCA_REG_IDX_STATUS, 0ULL);
+}
+
+static void xgmi_v6_4_0_reset_error_count(struct amdgpu_device *adev, int xgmi_inst)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(xgmi_v6_4_0_mca_base_array); i++)
+ __xgmi_v6_4_0_reset_error_count(adev, xgmi_inst, xgmi_v6_4_0_mca_base_array[i]);
+}
+
+static void xgmi_v6_4_0_reset_ras_error_count(struct amdgpu_device *adev)
+{
+ int i;
+
+ for_each_inst(i, adev->aid_mask)
+ xgmi_v6_4_0_reset_error_count(adev, i);
+}
+
+static void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev)
+{
+ switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
+ case IP_VERSION(6, 4, 0):
+ xgmi_v6_4_0_reset_ras_error_count(adev);
+ break;
+ default:
+ amdgpu_xgmi_legacy_reset_ras_error_count(adev);
+ break;
+ }
}
static int amdgpu_xgmi_query_pcs_error_status(struct amdgpu_device *adev,
@@ -948,7 +1058,10 @@ static int amdgpu_xgmi_query_pcs_error_status(struct amdgpu_device *adev,
uint32_t field_array_size = 0;
if (is_xgmi_pcs) {
- if (adev->ip_versions[XGMI_HWIP][0] == IP_VERSION(6, 1, 0)) {
+ if (amdgpu_ip_version(adev, XGMI_HWIP, 0) ==
+ IP_VERSION(6, 1, 0) ||
+ amdgpu_ip_version(adev, XGMI_HWIP, 0) ==
+ IP_VERSION(6, 4, 0)) {
pcs_ras_fields = &xgmi3x16_pcs_ras_fields[0];
field_array_size = ARRAY_SIZE(xgmi3x16_pcs_ras_fields);
} else {
@@ -982,11 +1095,11 @@ static int amdgpu_xgmi_query_pcs_error_status(struct amdgpu_device *adev,
return 0;
}
-static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
- void *ras_error_status)
+static void amdgpu_xgmi_legacy_query_ras_error_count(struct amdgpu_device *adev,
+ void *ras_error_status)
{
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
- int i;
+ int i, supported = 1;
uint32_t data, mask_data = 0;
uint32_t ue_cnt = 0, ce_cnt = 0;
@@ -1050,42 +1163,144 @@ static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
}
break;
default:
- dev_warn(adev->dev, "XGMI RAS error query not supported");
+ supported = 0;
break;
}
- adev->gmc.xgmi.ras->ras_block.hw_ops->reset_ras_error_count(adev);
+ switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
+ case IP_VERSION(6, 4, 0):
+ /* check xgmi3x16 pcs error */
+ for (i = 0; i < ARRAY_SIZE(xgmi3x16_pcs_err_status_reg_v6_4); i++) {
+ data = RREG32_PCIE(xgmi3x16_pcs_err_status_reg_v6_4[i]);
+ mask_data =
+ RREG32_PCIE(xgmi3x16_pcs_err_noncorrectable_mask_reg_v6_4[i]);
+ if (data)
+ amdgpu_xgmi_query_pcs_error_status(adev, data,
+ mask_data, &ue_cnt, &ce_cnt, true, true);
+ }
+ break;
+ default:
+ if (!supported)
+ dev_warn(adev->dev, "XGMI RAS error query not supported");
+ break;
+ }
+
+ amdgpu_ras_reset_error_count(adev, AMDGPU_RAS_BLOCK__XGMI_WAFL);
err_data->ue_count += ue_cnt;
err_data->ce_count += ce_cnt;
}
+static enum amdgpu_mca_error_type xgmi_v6_4_0_pcs_mca_get_error_type(struct amdgpu_device *adev, u64 status)
+{
+ const char *error_str;
+ int ext_error_code;
+
+ ext_error_code = MCA_REG__STATUS__ERRORCODEEXT(status);
+
+ error_str = ext_error_code < ARRAY_SIZE(xgmi_v6_4_0_ras_error_code_ext) ?
+ xgmi_v6_4_0_ras_error_code_ext[ext_error_code] : NULL;
+ if (error_str)
+ dev_info(adev->dev, "%s detected\n", error_str);
+
+ switch (ext_error_code) {
+ case 0:
+ return AMDGPU_MCA_ERROR_TYPE_UE;
+ case 6:
+ return AMDGPU_MCA_ERROR_TYPE_CE;
+ default:
+ return -EINVAL;
+ }
+
+ return -EINVAL;
+}
+
+static void __xgmi_v6_4_0_query_error_count(struct amdgpu_device *adev, struct amdgpu_smuio_mcm_config_info *mcm_info,
+ u64 mca_base, struct ras_err_data *err_data)
+{
+ int xgmi_inst = mcm_info->die_id;
+ u64 status = 0;
+
+ status = RREG64_MCA(xgmi_inst, mca_base, MCA_REG_IDX_STATUS);
+ if (!MCA_REG__STATUS__VAL(status))
+ return;
+
+ switch (xgmi_v6_4_0_pcs_mca_get_error_type(adev, status)) {
+ case AMDGPU_MCA_ERROR_TYPE_UE:
+ amdgpu_ras_error_statistic_ue_count(err_data, mcm_info, 1ULL);
+ break;
+ case AMDGPU_MCA_ERROR_TYPE_CE:
+ amdgpu_ras_error_statistic_ce_count(err_data, mcm_info, 1ULL);
+ break;
+ default:
+ break;
+ }
+
+ WREG64_MCA(xgmi_inst, mca_base, MCA_REG_IDX_STATUS, 0ULL);
+}
+
+static void xgmi_v6_4_0_query_error_count(struct amdgpu_device *adev, int xgmi_inst, struct ras_err_data *err_data)
+{
+ struct amdgpu_smuio_mcm_config_info mcm_info = {
+ .socket_id = adev->smuio.funcs->get_socket_id(adev),
+ .die_id = xgmi_inst,
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(xgmi_v6_4_0_mca_base_array); i++)
+ __xgmi_v6_4_0_query_error_count(adev, &mcm_info, xgmi_v6_4_0_mca_base_array[i], err_data);
+}
+
+static void xgmi_v6_4_0_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status)
+{
+ struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
+ int i;
+
+ for_each_inst(i, adev->aid_mask)
+ xgmi_v6_4_0_query_error_count(adev, i, err_data);
+}
+
+static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
+ void *ras_error_status)
+{
+ switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
+ case IP_VERSION(6, 4, 0):
+ xgmi_v6_4_0_query_ras_error_count(adev, ras_error_status);
+ break;
+ default:
+ amdgpu_xgmi_legacy_query_ras_error_count(adev, ras_error_status);
+ break;
+ }
+}
+
/* Trigger XGMI/WAFL error */
static int amdgpu_ras_error_inject_xgmi(struct amdgpu_device *adev,
void *inject_if, uint32_t instance_mask)
{
- int ret = 0;
+ int ret1, ret2;
struct ta_ras_trigger_error_input *block_info =
(struct ta_ras_trigger_error_input *)inject_if;
if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_DISALLOW))
dev_warn(adev->dev, "Failed to disallow df cstate");
- if (amdgpu_dpm_allow_xgmi_power_down(adev, false))
+ ret1 = amdgpu_dpm_set_xgmi_plpd_mode(adev, XGMI_PLPD_DISALLOW);
+ if (ret1 && ret1 != -EOPNOTSUPP)
dev_warn(adev->dev, "Failed to disallow XGMI power down");
- ret = psp_ras_trigger_error(&adev->psp, block_info, instance_mask);
+ ret2 = psp_ras_trigger_error(&adev->psp, block_info, instance_mask);
if (amdgpu_ras_intr_triggered())
- return ret;
+ return ret2;
- if (amdgpu_dpm_allow_xgmi_power_down(adev, true))
+ ret1 = amdgpu_dpm_set_xgmi_plpd_mode(adev, XGMI_PLPD_DEFAULT);
+ if (ret1 && ret1 != -EOPNOTSUPP)
dev_warn(adev->dev, "Failed to allow XGMI power down");
if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_ALLOW))
dev_warn(adev->dev, "Failed to allow df cstate");
- return ret;
+ return ret2;
}
struct amdgpu_ras_block_hw_ops xgmi_ras_hw_ops = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
index 86fbf56938f4..6cab882e8061 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
@@ -44,6 +44,7 @@ struct amdgpu_hive_info {
struct amdgpu_reset_domain *reset_domain;
uint32_t device_remove_count;
+ atomic_t ras_recovery;
};
struct amdgpu_pcs_ras_field {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
index 104a5ad8397d..51a14f6d93bd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
@@ -90,10 +90,11 @@ union amd_sriov_msg_feature_flags {
uint32_t host_load_ucodes : 1;
uint32_t host_flr_vramlost : 1;
uint32_t mm_bw_management : 1;
- uint32_t pp_one_vf_mode : 1;
+ uint32_t pp_one_vf_mode : 1;
uint32_t reg_indirect_acc : 1;
uint32_t av1_support : 1;
- uint32_t reserved : 25;
+ uint32_t vcn_rb_decouple : 1;
+ uint32_t reserved : 24;
} flags;
uint32_t all;
};
diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
index d0fc62784e82..3f715e7fe1a9 100644
--- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
+++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
@@ -500,7 +500,7 @@ static int aqua_vanjaram_switch_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr,
return -EINVAL;
}
- if (adev->kfd.init_complete)
+ if (adev->kfd.init_complete && !amdgpu_in_reset(adev))
flags |= AMDGPU_XCP_OPS_KFD;
if (flags & AMDGPU_XCP_OPS_KFD) {
diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c
index a13c443ea10f..42f4e163e251 100644
--- a/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c
@@ -68,7 +68,7 @@ int athub_v1_0_set_clockgating(struct amdgpu_device *adev,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[ATHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, ATHUB_HWIP, 0)) {
case IP_VERSION(9, 0, 0):
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 0):
diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c
index a9521c98e7f7..5a122f50a6e7 100644
--- a/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c
@@ -77,7 +77,7 @@ int athub_v2_0_set_clockgating(struct amdgpu_device *adev,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[ATHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, ATHUB_HWIP, 0)) {
case IP_VERSION(1, 3, 1):
case IP_VERSION(2, 0, 0):
case IP_VERSION(2, 0, 2):
diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/athub_v2_1.c
index 78508ae6a670..e143fcc46148 100644
--- a/drivers/gpu/drm/amd/amdgpu/athub_v2_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/athub_v2_1.c
@@ -70,7 +70,7 @@ int athub_v2_1_set_clockgating(struct amdgpu_device *adev,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[ATHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, ATHUB_HWIP, 0)) {
case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 1, 2):
diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v3_0.c b/drivers/gpu/drm/amd/amdgpu/athub_v3_0.c
index f0e235f98afb..f0737fb3a999 100644
--- a/drivers/gpu/drm/amd/amdgpu/athub_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/athub_v3_0.c
@@ -36,7 +36,7 @@ static uint32_t athub_v3_0_get_cg_cntl(struct amdgpu_device *adev)
{
uint32_t data;
- switch (adev->ip_versions[ATHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, ATHUB_HWIP, 0)) {
case IP_VERSION(3, 0, 1):
data = RREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL_V3_0_1);
break;
@@ -49,7 +49,7 @@ static uint32_t athub_v3_0_get_cg_cntl(struct amdgpu_device *adev)
static void athub_v3_0_set_cg_cntl(struct amdgpu_device *adev, uint32_t data)
{
- switch (adev->ip_versions[ATHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, ATHUB_HWIP, 0)) {
case IP_VERSION(3, 0, 1):
WREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL_V3_0_1, data);
break;
@@ -99,10 +99,11 @@ int athub_v3_0_set_clockgating(struct amdgpu_device *adev,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[ATHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, ATHUB_HWIP, 0)) {
case IP_VERSION(3, 0, 0):
case IP_VERSION(3, 0, 1):
case IP_VERSION(3, 0, 2):
+ case IP_VERSION(3, 3, 0):
athub_v3_0_update_medium_grain_clock_gating(adev,
state == AMD_CG_STATE_GATE);
athub_v3_0_update_medium_grain_light_sleep(adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c
index 9f63ddb89b75..2c221000782c 100644
--- a/drivers/gpu/drm/amd/amdgpu/atom.c
+++ b/drivers/gpu/drm/amd/amdgpu/atom.c
@@ -1444,10 +1444,27 @@ static void atom_get_vbios_pn(struct atom_context *ctx)
static void atom_get_vbios_version(struct atom_context *ctx)
{
+ unsigned short start = 3, end;
unsigned char *vbios_ver;
+ unsigned char *p_rom;
+
+ p_rom = ctx->bios;
+ /* Search from strings offset if it's present */
+ start = *(unsigned short *)(p_rom +
+ OFFSET_TO_GET_ATOMBIOS_STRING_START);
+
+ /* Search till atom rom header start point */
+ end = *(unsigned short *)(p_rom + OFFSET_TO_ATOM_ROM_HEADER_POINTER);
+
+ /* Use hardcoded offsets, if the offsets are not populated */
+ if (end <= start) {
+ start = 3;
+ end = 1024;
+ }
/* find anchor ATOMBIOSBK-AMD */
- vbios_ver = atom_find_str_in_rom(ctx, BIOS_VERSION_PREFIX, 3, 1024, 64);
+ vbios_ver =
+ atom_find_str_in_rom(ctx, BIOS_VERSION_PREFIX, start, end, 64);
if (vbios_ver != NULL) {
/* skip ATOMBIOSBK-AMD VER */
vbios_ver += 18;
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
index d95b2dc78063..3ee219aa2891 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
@@ -228,7 +228,6 @@ error:
register_acpi_backlight:
/* Try registering an ACPI video backlight device instead. */
acpi_video_register_backlight();
- return;
}
void
diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index e63abdf52b6c..4dfaa017cf7f 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1709,10 +1709,6 @@ static void cik_program_aspm(struct amdgpu_device *adev)
if (pci_is_root_bus(adev->pdev->bus))
return;
- /* XXX double check APUs */
- if (adev->flags & AMD_IS_APU)
- return;
-
orig = data = RREG32_PCIE(ixPCIE_LC_N_FTS_CNTL);
data &= ~PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS_MASK;
data |= (0x24 << PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS__SHIFT) |
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index 52598fbc9b39..a3fccc4c1f43 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -308,8 +308,6 @@ static void cik_sdma_gfx_stop(struct amdgpu_device *adev)
u32 rb_cntl;
int i;
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
-
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);
rb_cntl &= ~SDMA0_GFX_RB_CNTL__RB_ENABLE_MASK;
@@ -498,9 +496,6 @@ static int cik_sdma_gfx_resume(struct amdgpu_device *adev)
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
-
- if (adev->mman.buffer_funcs_ring == ring)
- amdgpu_ttm_set_buffer_funcs_status(adev, true);
}
return 0;
@@ -925,9 +920,14 @@ static void cik_enable_sdma_mgls(struct amdgpu_device *adev,
static int cik_sdma_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
adev->sdma.num_instances = SDMA_MAX_INSTANCE;
+ r = cik_sdma_init_microcode(adev);
+ if (r)
+ return r;
+
cik_sdma_set_ring_funcs(adev);
cik_sdma_set_irq_funcs(adev);
cik_sdma_set_buffer_funcs(adev);
@@ -942,12 +942,6 @@ static int cik_sdma_sw_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int r, i;
- r = cik_sdma_init_microcode(adev);
- if (r) {
- DRM_ERROR("Failed to load sdma firmware!\n");
- return r;
- }
-
/* SDMA trap event */
r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 224,
&adev->sdma.trap_irq);
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index 584cd5277f92..bb666cb7522e 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -1036,7 +1036,7 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev,
(u32)mode->clock);
line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
(u32)mode->clock);
- line_time = min(line_time, (u32)65535);
+ line_time = min_t(u32, line_time, 65535);
/* watermark for high clocks */
if (adev->pm.dpm_enabled) {
@@ -1066,7 +1066,7 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev,
wm_high.num_heads = num_heads;
/* set for high clocks */
- latency_watermark_a = min(dce_v10_0_latency_watermark(&wm_high), (u32)65535);
+ latency_watermark_a = min_t(u32, dce_v10_0_latency_watermark(&wm_high), 65535);
/* possibly force display priority to high */
/* should really do this at mode validation time... */
@@ -1105,7 +1105,7 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev,
wm_low.num_heads = num_heads;
/* set for low clocks */
- latency_watermark_b = min(dce_v10_0_latency_watermark(&wm_low), (u32)65535);
+ latency_watermark_b = min_t(u32, dce_v10_0_latency_watermark(&wm_low), 65535);
/* possibly force display priority to high */
/* should really do this at mode validation time... */
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index c14b70350a51..7af277f61cca 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -1068,7 +1068,7 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev,
(u32)mode->clock);
line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
(u32)mode->clock);
- line_time = min(line_time, (u32)65535);
+ line_time = min_t(u32, line_time, 65535);
/* watermark for high clocks */
if (adev->pm.dpm_enabled) {
@@ -1098,7 +1098,7 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev,
wm_high.num_heads = num_heads;
/* set for high clocks */
- latency_watermark_a = min(dce_v11_0_latency_watermark(&wm_high), (u32)65535);
+ latency_watermark_a = min_t(u32, dce_v11_0_latency_watermark(&wm_high), 65535);
/* possibly force display priority to high */
/* should really do this at mode validation time... */
@@ -1137,7 +1137,7 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev,
wm_low.num_heads = num_heads;
/* set for low clocks */
- latency_watermark_b = min(dce_v11_0_latency_watermark(&wm_low), (u32)65535);
+ latency_watermark_b = min_t(u32, dce_v11_0_latency_watermark(&wm_low), 65535);
/* possibly force display priority to high */
/* should really do this at mode validation time... */
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
index 7f85ba5b726f..143efc37a17f 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
@@ -845,7 +845,7 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev,
(u32)mode->clock);
line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
(u32)mode->clock);
- line_time = min(line_time, (u32)65535);
+ line_time = min_t(u32, line_time, 65535);
priority_a_cnt = 0;
priority_b_cnt = 0;
@@ -906,9 +906,9 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev,
wm_low.num_heads = num_heads;
/* set for high clocks */
- latency_watermark_a = min(dce_v6_0_latency_watermark(&wm_high), (u32)65535);
+ latency_watermark_a = min_t(u32, dce_v6_0_latency_watermark(&wm_high), 65535);
/* set for low clocks */
- latency_watermark_b = min(dce_v6_0_latency_watermark(&wm_low), (u32)65535);
+ latency_watermark_b = min_t(u32, dce_v6_0_latency_watermark(&wm_low), 65535);
/* possibly force display priority to high */
/* should really do this at mode validation time... */
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index f2b3cb5ed6be..adeddfb7ff12 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -975,7 +975,7 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev,
(u32)mode->clock);
line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
(u32)mode->clock);
- line_time = min(line_time, (u32)65535);
+ line_time = min_t(u32, line_time, 65535);
/* watermark for high clocks */
if (adev->pm.dpm_enabled) {
@@ -1005,7 +1005,7 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev,
wm_high.num_heads = num_heads;
/* set for high clocks */
- latency_watermark_a = min(dce_v8_0_latency_watermark(&wm_high), (u32)65535);
+ latency_watermark_a = min_t(u32, dce_v8_0_latency_watermark(&wm_high), 65535);
/* possibly force display priority to high */
/* should really do this at mode validation time... */
@@ -1044,7 +1044,7 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev,
wm_low.num_heads = num_heads;
/* set for low clocks */
- latency_watermark_b = min(dce_v8_0_latency_watermark(&wm_low), (u32)65535);
+ latency_watermark_b = min_t(u32, dce_v8_0_latency_watermark(&wm_low), 65535);
/* possibly force display priority to high */
/* should really do this at mode validation time... */
diff --git a/drivers/gpu/drm/amd/amdgpu/df_v4_6_2.c b/drivers/gpu/drm/amd/amdgpu/df_v4_6_2.c
new file mode 100644
index 000000000000..a47960a0babd
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/df_v4_6_2.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "df_v4_6_2.h"
+
+static bool df_v4_6_2_query_ras_poison_mode(struct amdgpu_device *adev)
+{
+ /* return true since related regs are inaccessible */
+ return true;
+}
+
+const struct amdgpu_df_funcs df_v4_6_2_funcs = {
+ .query_ras_poison_mode = df_v4_6_2_query_ras_poison_mode,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/df_v4_6_2.h b/drivers/gpu/drm/amd/amdgpu/df_v4_6_2.h
new file mode 100644
index 000000000000..3bc3e6d216e2
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/df_v4_6_2.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __DF_V4_6_2_H__
+#define __DF_V4_6_2_H__
+
+#include "soc15_common.h"
+
+extern const struct amdgpu_df_funcs df_v4_6_2_funcs;
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 9032d7a24d7c..c8a3bf01743f 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -102,6 +102,11 @@
#define mmGCR_GENERAL_CNTL_Sienna_Cichlid 0x1580
#define mmGCR_GENERAL_CNTL_Sienna_Cichlid_BASE_IDX 0
+#define mmGOLDEN_TSC_COUNT_UPPER_Cyan_Skillfish 0x0105
+#define mmGOLDEN_TSC_COUNT_UPPER_Cyan_Skillfish_BASE_IDX 1
+#define mmGOLDEN_TSC_COUNT_LOWER_Cyan_Skillfish 0x0106
+#define mmGOLDEN_TSC_COUNT_LOWER_Cyan_Skillfish_BASE_IDX 1
+
#define mmGOLDEN_TSC_COUNT_UPPER_Vangogh 0x0025
#define mmGOLDEN_TSC_COUNT_UPPER_Vangogh_BASE_IDX 1
#define mmGOLDEN_TSC_COUNT_LOWER_Vangogh 0x0026
@@ -3493,6 +3498,8 @@ static void gfx_v10_0_ring_invalidate_tlbs(struct amdgpu_ring *ring,
static void gfx_v10_0_update_spm_vmid_internal(struct amdgpu_device *adev,
unsigned int vmid);
+static int gfx_v10_0_set_powergating_state(void *handle,
+ enum amd_powergating_state state);
static void gfx10_kiq_set_resources(struct amdgpu_ring *kiq_ring, uint64_t queue_mask)
{
amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_SET_RESOURCES, 6));
@@ -3627,7 +3634,7 @@ static void gfx_v10_0_set_kiq_pm4_funcs(struct amdgpu_device *adev)
static void gfx_v10_0_init_spm_golden_registers(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
soc15_program_register_sequence(adev,
golden_settings_gc_rlc_spm_10_0_nv10,
@@ -3650,7 +3657,7 @@ static void gfx_v10_0_init_spm_golden_registers(struct amdgpu_device *adev)
static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
soc15_program_register_sequence(adev,
golden_settings_gc_10_1,
@@ -3891,7 +3898,7 @@ static void gfx_v10_0_check_fw_write_wait(struct amdgpu_device *adev)
{
adev->gfx.cp_fw_write_wait = false;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 2):
case IP_VERSION(10, 1, 1):
@@ -3942,7 +3949,7 @@ static bool gfx_v10_0_navi10_gfxoff_should_enable(struct amdgpu_device *adev)
static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
if (!gfx_v10_0_navi10_gfxoff_should_enable(adev))
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
@@ -3964,8 +3971,8 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
DRM_DEBUG("\n");
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 1) &&
- (!(adev->pdev->device == 0x7340 && adev->pdev->revision != 0x00)))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 1, 1) &&
+ (!(adev->pdev->device == 0x7340 && adev->pdev->revision != 0x00)))
wks = "_wks";
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
@@ -4144,7 +4151,7 @@ static void gfx_v10_0_init_rlcg_reg_access_ctrl(struct amdgpu_device *adev)
reg_access_ctrl->scratch_reg3 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG3);
reg_access_ctrl->grbm_cntl = SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_CNTL);
reg_access_ctrl->grbm_idx = SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_INDEX);
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
reg_access_ctrl->spare_int =
SOC15_REG_OFFSET(GC, 0, mmRLC_SPARE_INT_0_Sienna_Cichlid);
@@ -4358,7 +4365,7 @@ static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev)
{
u32 gb_addr_config;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 2):
@@ -4491,7 +4498,7 @@ static int gfx_v10_0_sw_init(void *handle)
struct amdgpu_kiq *kiq;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 2):
@@ -4749,9 +4756,12 @@ static void gfx_v10_0_setup_rb(struct amdgpu_device *adev)
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
bitmap = i * adev->gfx.config.max_sh_per_se + j;
- if (((adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0)) ||
- (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 3)) ||
- (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 6))) &&
+ if (((amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(10, 3, 0)) ||
+ (amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(10, 3, 3)) ||
+ (amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(10, 3, 6))) &&
((gfx_v10_3_get_disabled_sa(adev) >> bitmap) & 1))
continue;
gfx_v10_0_select_se_sh(adev, i, j, 0xffffffff, 0);
@@ -4779,7 +4789,7 @@ static u32 gfx_v10_0_init_pa_sc_tile_steering_override(struct amdgpu_device *ade
/* for ASICs that integrates GFX v10.3
* pa_sc_tile_steering_override should be set to 0
*/
- if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 3, 0))
return 0;
/* init num_sc */
@@ -4960,7 +4970,7 @@ static void gfx_v10_0_get_tcc_info(struct amdgpu_device *adev)
/* TCCs are global (not instanced). */
uint32_t tcc_disable;
- if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 3, 0)) {
tcc_disable = RREG32_SOC15(GC, 0, mmCGTS_TCC_DISABLE_gc_10_3) |
RREG32_SOC15(GC, 0, mmCGTS_USER_TCC_DISABLE_gc_10_3);
} else {
@@ -5037,7 +5047,7 @@ static int gfx_v10_0_init_csb(struct amdgpu_device *adev)
adev->gfx.rlc.funcs->get_csb_buffer(adev, adev->gfx.rlc.cs_ptr);
/* csib */
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 2)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 1, 2)) {
WREG32_SOC15_RLC(GC, 0, mmRLC_CSIB_ADDR_HI,
adev->gfx.rlc.clear_state_gpu_addr >> 32);
WREG32_SOC15_RLC(GC, 0, mmRLC_CSIB_ADDR_LO,
@@ -5666,7 +5676,7 @@ static int gfx_v10_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable)
tmp = REG_SET_FIELD(tmp, CP_ME_CNTL, PFP_HALT, enable ? 0 : 1);
tmp = REG_SET_FIELD(tmp, CP_ME_CNTL, CE_HALT, enable ? 0 : 1);
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 2))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 1, 2))
WREG32_SOC15_RLC(GC, 0, mmCP_ME_CNTL, tmp);
else
WREG32_SOC15(GC, 0, mmCP_ME_CNTL, tmp);
@@ -6057,7 +6067,7 @@ static void gfx_v10_0_cp_gfx_set_doorbell(struct amdgpu_device *adev,
}
WREG32_SOC15(GC, 0, mmCP_RB_DOORBELL_CONTROL, tmp);
}
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 1):
@@ -6190,7 +6200,7 @@ static int gfx_v10_0_cp_gfx_resume(struct amdgpu_device *adev)
static void gfx_v10_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
{
if (enable) {
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 1):
@@ -6206,7 +6216,7 @@ static void gfx_v10_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
break;
}
} else {
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 1):
@@ -6306,7 +6316,7 @@ static void gfx_v10_0_kiq_setting(struct amdgpu_ring *ring)
struct amdgpu_device *adev = ring->adev;
/* tell RLC which is KIQ queue */
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 1):
@@ -6457,11 +6467,18 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring)
nv_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.me.mqd_backup[mqd_idx])
- memcpy(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
+ memcpy_fromio(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
} else {
+ mutex_lock(&adev->srbm_mutex);
+ nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
+ if (ring->doorbell_index == adev->doorbell_index.gfx_ring0 << 1)
+ gfx_v10_0_cp_gfx_set_doorbell(adev, ring);
+
+ nv_grbm_select(adev, 0, 0, 0, 0);
+ mutex_unlock(&adev->srbm_mutex);
/* restore mqd with the backup copy */
if (adev->gfx.me.mqd_backup[mqd_idx])
- memcpy(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd));
+ memcpy_toio(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd));
/* reset the ring */
ring->wptr = 0;
*ring->wptr_cpu_addr = 0;
@@ -6735,7 +6752,7 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring)
if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */
/* reset MQD to a clean status */
if (adev->gfx.kiq[0].mqd_backup)
- memcpy(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(*mqd));
+ memcpy_toio(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(*mqd));
/* reset ring buffer */
ring->wptr = 0;
@@ -6758,7 +6775,7 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring)
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.kiq[0].mqd_backup)
- memcpy(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(*mqd));
+ memcpy_fromio(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(*mqd));
}
return 0;
@@ -6779,11 +6796,11 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring)
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.mec.mqd_backup[mqd_idx])
- memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
+ memcpy_fromio(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
} else {
/* restore MQD to a clean status */
if (adev->gfx.mec.mqd_backup[mqd_idx])
- memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd));
+ memcpy_toio(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd));
/* reset ring buffer */
ring->wptr = 0;
atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0);
@@ -6917,7 +6934,7 @@ static bool gfx_v10_0_check_grbm_cam_remapping(struct amdgpu_device *adev)
* check if mmVGT_ESGS_RING_SIZE_UMD
* has been remapped to mmVGT_ESGS_RING_SIZE
*/
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 4):
@@ -6966,7 +6983,7 @@ static void gfx_v10_0_setup_grbm_cam_remapping(struct amdgpu_device *adev)
*/
WREG32_SOC15(GC, 0, mmGRBM_CAM_INDEX, 0);
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 1):
@@ -7139,19 +7156,19 @@ static int gfx_v10_0_hw_init(void *handle)
* init golden registers and rlc resume may override some registers,
* reconfig them here
*/
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 10) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 1) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 2))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 1, 10) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 1, 1) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 1, 2))
gfx_v10_0_tcp_harvest(adev);
r = gfx_v10_0_cp_resume(adev);
if (r)
return r;
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 3, 0))
gfx_v10_3_program_pbb_mode(adev);
- if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 3, 0))
gfx_v10_3_set_power_brake_sequence(adev);
return r;
@@ -7164,6 +7181,13 @@ static int gfx_v10_0_hw_fini(void *handle)
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
+ /* WA added for Vangogh asic fixing the SMU suspend failure
+ * It needs to set power gating again during gfxoff control
+ * otherwise the gfxoff disallowing will be failed to set.
+ */
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 3, 1))
+ gfx_v10_0_set_powergating_state(handle, AMD_PG_STATE_UNGATE);
+
if (!adev->no_hw_access) {
if (amdgpu_async_gfx_ring) {
if (amdgpu_gfx_disable_kgq(adev, 0))
@@ -7255,7 +7279,7 @@ static int gfx_v10_0_soft_reset(void *handle)
/* GRBM_STATUS2 */
tmp = RREG32_SOC15(GC, 0, mmGRBM_STATUS2);
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 1):
@@ -7312,7 +7336,23 @@ static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev)
{
uint64_t clock, clock_lo, clock_hi, hi_check;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
+ case IP_VERSION(10, 1, 3):
+ case IP_VERSION(10, 1, 4):
+ preempt_disable();
+ clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Cyan_Skillfish);
+ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Cyan_Skillfish);
+ hi_check = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Cyan_Skillfish);
+ /* The SMUIO TSC clock frequency is 100MHz, which sets 32-bit carry over
+ * roughly every 42 seconds.
+ */
+ if (hi_check != clock_hi) {
+ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Cyan_Skillfish);
+ clock_hi = hi_check;
+ }
+ preempt_enable();
+ clock = clock_lo | (clock_hi << 32ULL);
+ break;
case IP_VERSION(10, 3, 1):
case IP_VERSION(10, 3, 3):
case IP_VERSION(10, 3, 7):
@@ -7399,7 +7439,7 @@ static int gfx_v10_0_early_init(void *handle)
adev->gfx.funcs = &gfx_v10_0_gfx_funcs;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 2):
@@ -7470,7 +7510,7 @@ static void gfx_v10_0_set_safe_mode(struct amdgpu_device *adev, int xcc_id)
data = RLC_SAFE_MODE__CMD_MASK;
data |= (1 << RLC_SAFE_MODE__MESSAGE__SHIFT);
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 1):
@@ -7508,7 +7548,7 @@ static void gfx_v10_0_unset_safe_mode(struct amdgpu_device *adev, int xcc_id)
uint32_t data;
data = RLC_SAFE_MODE__CMD_MASK;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 1):
@@ -7819,7 +7859,7 @@ static void gfx_v10_0_apply_medium_grain_clock_gating_workaround(struct amdgpu_d
mmCGTS_SA1_QUAD1_SM_CTRL_REG
};
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 2)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 1, 2)) {
for (i = 0; i < ARRAY_SIZE(tcp_ctrl_regs_nv12); i++) {
reg_idx = adev->reg_offset[GC_HWIP][0][mmCGTS_SA0_WGP00_CU0_TCP_CTRL_REG_BASE_IDX] +
tcp_ctrl_regs_nv12[i];
@@ -7864,9 +7904,12 @@ static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev,
/* === CGCG + CGLS === */
gfx_v10_0_update_coarse_grain_clock_gating(adev, enable);
- if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 10)) ||
- (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 1)) ||
- (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 2)))
+ if ((amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(10, 1, 10)) ||
+ (amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(10, 1, 1)) ||
+ (amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(10, 1, 2)))
gfx_v10_0_apply_medium_grain_clock_gating_workaround(adev);
} else {
/* CGCG/CGLS should be disabled before MGCG/MGLS
@@ -7897,22 +7940,15 @@ static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev,
static void gfx_v10_0_update_spm_vmid_internal(struct amdgpu_device *adev,
unsigned int vmid)
{
- u32 reg, data;
+ u32 data;
/* not for *_SOC15 */
- reg = SOC15_REG_OFFSET(GC, 0, mmRLC_SPM_MC_CNTL);
- if (amdgpu_sriov_is_pp_one_vf(adev))
- data = RREG32_NO_KIQ(reg);
- else
- data = RREG32_SOC15(GC, 0, mmRLC_SPM_MC_CNTL);
+ data = RREG32_SOC15_NO_KIQ(GC, 0, mmRLC_SPM_MC_CNTL);
data &= ~RLC_SPM_MC_CNTL__RLC_SPM_VMID_MASK;
data |= (vmid & RLC_SPM_MC_CNTL__RLC_SPM_VMID_MASK) << RLC_SPM_MC_CNTL__RLC_SPM_VMID__SHIFT;
- if (amdgpu_sriov_is_pp_one_vf(adev))
- WREG32_SOC15_NO_KIQ(GC, 0, mmRLC_SPM_MC_CNTL, data);
- else
- WREG32_SOC15(GC, 0, mmRLC_SPM_MC_CNTL, data);
+ WREG32_SOC15_NO_KIQ(GC, 0, mmRLC_SPM_MC_CNTL, data);
}
static void gfx_v10_0_update_spm_vmid(struct amdgpu_device *adev, unsigned int vmid)
@@ -7973,7 +8009,7 @@ static void gfx_v10_cntl_power_gating(struct amdgpu_device *adev, bool enable)
* Power/performance team will optimize it and might give a new value later.
*/
if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) {
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 1):
case IP_VERSION(10, 3, 3):
case IP_VERSION(10, 3, 6):
@@ -8034,7 +8070,7 @@ static int gfx_v10_0_set_powergating_state(void *handle,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 2):
@@ -8071,7 +8107,7 @@ static int gfx_v10_0_set_clockgating_state(void *handle,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 2):
@@ -9318,7 +9354,7 @@ static void gfx_v10_0_set_irq_funcs(struct amdgpu_device *adev)
static void gfx_v10_0_set_rlc_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 3):
@@ -9435,10 +9471,14 @@ static int gfx_v10_0_get_cu_info(struct amdgpu_device *adev,
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
bitmap = i * adev->gfx.config.max_sh_per_se + j;
- if (((adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0)) ||
- (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 3)) ||
- (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 6)) ||
- (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 7))) &&
+ if (((amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(10, 3, 0)) ||
+ (amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(10, 3, 3)) ||
+ (amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(10, 3, 6)) ||
+ (amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(10, 3, 7))) &&
((gfx_v10_3_get_disabled_sa(adev) >> bitmap) & 1))
continue;
mask = 1;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 762d7a19f1be..8ed4a6fb147a 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -60,6 +60,8 @@
#define regCGTT_WD_CLK_CTRL_BASE_IDX 1
#define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1 0x4e7e
#define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1_BASE_IDX 1
+#define regPC_CONFIG_CNTL_1 0x194d
+#define regPC_CONFIG_CNTL_1_BASE_IDX 1
MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin");
@@ -82,6 +84,14 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_4_pfp.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_4_me.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_4_mec.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_4_rlc.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_0_pfp.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_0_me.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_0_mec.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_0_rlc.bin");
+
+static const struct soc15_reg_golden golden_settings_gc_11_0[] = {
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regTCP_CNTL, 0x20000000, 0x20000000)
+};
static const struct soc15_reg_golden golden_settings_gc_11_0_1[] =
{
@@ -96,6 +106,23 @@ static const struct soc15_reg_golden golden_settings_gc_11_0_1[] =
SOC15_REG_GOLDEN_VALUE(GC, 0, regTCP_CNTL2, 0xfcffffff, 0x0000000a)
};
+static const struct soc15_reg_golden golden_settings_gc_11_5_0[] = {
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regDB_DEBUG5, 0xffffffff, 0x00000800),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regGB_ADDR_CONFIG, 0x0c1807ff, 0x00000242),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regGCR_GENERAL_CNTL, 0x1ff1ffff, 0x00000500),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2A_ADDR_MATCH_MASK, 0xffffffff, 0xfffffff3),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_ADDR_MATCH_MASK, 0xffffffff, 0xfffffff3),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_CTRL, 0xffffffff, 0xf37fff3f),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_CTRL3, 0xfffffffb, 0x00f40188),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_CTRL4, 0xf0ffffff, 0x8000b007),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regPA_CL_ENHANCE, 0xf1ffffff, 0x00880007),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regPC_CONFIG_CNTL_1, 0xffffffff, 0x00010000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regTA_CNTL_AUX, 0xf7f7ffff, 0x01030000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regTA_CNTL2, 0x007f0000, 0x00000000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regTCP_CNTL2, 0xffcfffff, 0x0000200a),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, regUTCL1_CTRL_2, 0xffffffff, 0x0000048f)
+};
+
#define DEFAULT_SH_MEM_CONFIG \
((SH_MEM_ADDRESS_MODE_64 << SH_MEM_CONFIG__ADDRESS_MODE__SHIFT) | \
(SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \
@@ -132,6 +159,7 @@ static void gfx11_kiq_set_resources(struct amdgpu_ring *kiq_ring, uint64_t queue
{
amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_SET_RESOURCES, 6));
amdgpu_ring_write(kiq_ring, PACKET3_SET_RESOURCES_VMID_MASK(0) |
+ PACKET3_SET_RESOURCES_UNMAP_LATENTY(0xa) | /* unmap_latency: 0xa (~ 1s) */
PACKET3_SET_RESOURCES_QUEUE_TYPE(0)); /* vmid_mask:0 queue_type:0 (KIQ) */
amdgpu_ring_write(kiq_ring, lower_32_bits(queue_mask)); /* queue mask lo */
amdgpu_ring_write(kiq_ring, upper_32_bits(queue_mask)); /* queue mask hi */
@@ -265,16 +293,25 @@ static void gfx_v11_0_set_kiq_pm4_funcs(struct amdgpu_device *adev)
static void gfx_v11_0_init_golden_registers(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 4):
soc15_program_register_sequence(adev,
golden_settings_gc_11_0_1,
(const u32)ARRAY_SIZE(golden_settings_gc_11_0_1));
break;
+ case IP_VERSION(11, 5, 0):
+ soc15_program_register_sequence(adev,
+ golden_settings_gc_11_5_0,
+ (const u32)ARRAY_SIZE(golden_settings_gc_11_5_0));
+ break;
default:
break;
}
+ soc15_program_register_sequence(adev,
+ golden_settings_gc_11_0,
+ (const u32)ARRAY_SIZE(golden_settings_gc_11_0));
+
}
static void gfx_v11_0_write_data_to_reg(struct amdgpu_ring *ring, int eng_sel,
@@ -390,7 +427,7 @@ static int gfx_v11_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
adev->wb.wb[index] = cpu_to_le32(0xCAFEDEAD);
cpu_ptr = &adev->wb.wb[index];
- r = amdgpu_ib_get(adev, NULL, 16, AMDGPU_IB_POOL_DIRECT, &ib);
+ r = amdgpu_ib_get(adev, NULL, 20, AMDGPU_IB_POOL_DIRECT, &ib);
if (r) {
DRM_ERROR("amdgpu: failed to get ib (%ld).\n", r);
goto err1;
@@ -465,7 +502,7 @@ out:
static void gfx_v11_0_check_fw_cp_gfx_shadow(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
@@ -561,6 +598,14 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
adev->gfx.mec2_fw = NULL;
gfx_v11_0_check_fw_cp_gfx_shadow(adev);
+
+ if (adev->gfx.imu.funcs && adev->gfx.imu.funcs->init_microcode) {
+ err = adev->gfx.imu.funcs->init_microcode(adev);
+ if (err)
+ DRM_ERROR("Failed to init imu firmware!\n");
+ return err;
+ }
+
out:
if (err) {
amdgpu_ucode_release(&adev->gfx.pfp_fw);
@@ -856,8 +901,7 @@ static const struct amdgpu_gfx_funcs gfx_v11_0_gfx_funcs = {
static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
{
-
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 2):
adev->gfx.config.max_hw_contexts = 8;
@@ -876,6 +920,7 @@ static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
break;
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
adev->gfx.config.max_hw_contexts = 8;
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
@@ -1301,9 +1346,7 @@ static int gfx_v11_0_sw_init(void *handle)
struct amdgpu_kiq *kiq;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- adev->gfxhub.funcs->init(adev);
-
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
@@ -1316,6 +1359,7 @@ static int gfx_v11_0_sw_init(void *handle)
break;
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
adev->gfx.me.num_me = 1;
adev->gfx.me.num_pipe_per_me = 1;
adev->gfx.me.num_queue_per_pipe = 1;
@@ -1334,8 +1378,8 @@ static int gfx_v11_0_sw_init(void *handle)
}
/* Enable CG flag in one VF mode for enabling RLC safe mode enter/exit */
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 3) &&
- amdgpu_sriov_is_pp_one_vf(adev))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 0, 3) &&
+ amdgpu_sriov_is_pp_one_vf(adev))
adev->cg_flags = AMD_CG_SUPPORT_GFX_CGCG;
/* EOP Event */
@@ -1368,14 +1412,6 @@ static int gfx_v11_0_sw_init(void *handle)
adev->gfx.gfx_current_status = AMDGPU_GFX_NORMAL_MODE;
- if (adev->gfx.imu.funcs) {
- if (adev->gfx.imu.funcs->init_microcode) {
- r = adev->gfx.imu.funcs->init_microcode(adev);
- if (r)
- DRM_ERROR("Failed to load imu firmware!\n");
- }
- }
-
gfx_v11_0_me_init(adev);
r = gfx_v11_0_rlc_init(adev);
@@ -2562,8 +2598,11 @@ static int gfx_v11_0_wait_for_rlc_autoload_complete(struct amdgpu_device *adev)
for (i = 0; i < adev->usec_timeout; i++) {
cp_status = RREG32_SOC15(GC, 0, regCP_STAT);
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 1) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 4))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(11, 0, 1) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(11, 0, 4) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 0))
bootload_status = RREG32_SOC15(GC, 0,
regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1);
else
@@ -3684,11 +3723,11 @@ static int gfx_v11_0_gfx_init_queue(struct amdgpu_ring *ring)
soc21_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.me.mqd_backup[mqd_idx])
- memcpy(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
+ memcpy_fromio(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
} else {
/* restore mqd with the backup copy */
if (adev->gfx.me.mqd_backup[mqd_idx])
- memcpy(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd));
+ memcpy_toio(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd));
/* reset the ring */
ring->wptr = 0;
*ring->wptr_cpu_addr = 0;
@@ -3977,7 +4016,7 @@ static int gfx_v11_0_kiq_init_queue(struct amdgpu_ring *ring)
if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */
/* reset MQD to a clean status */
if (adev->gfx.kiq[0].mqd_backup)
- memcpy(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(*mqd));
+ memcpy_toio(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(*mqd));
/* reset ring buffer */
ring->wptr = 0;
@@ -4000,7 +4039,7 @@ static int gfx_v11_0_kiq_init_queue(struct amdgpu_ring *ring)
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.kiq[0].mqd_backup)
- memcpy(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(*mqd));
+ memcpy_fromio(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(*mqd));
}
return 0;
@@ -4021,11 +4060,11 @@ static int gfx_v11_0_kcq_init_queue(struct amdgpu_ring *ring)
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.mec.mqd_backup[mqd_idx])
- memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
+ memcpy_fromio(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
} else {
/* restore MQD to a clean status */
if (adev->gfx.mec.mqd_backup[mqd_idx])
- memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd));
+ memcpy_toio(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd));
/* reset ring buffer */
ring->wptr = 0;
atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0);
@@ -4343,6 +4382,10 @@ static int gfx_v11_0_hw_init(void *handle)
if (r)
return r;
+ /* get IMU version from HW if it's not set */
+ if (!adev->gfx.imu_fw_version)
+ adev->gfx.imu_fw_version = RREG32_SOC15(GC, 0, regGFX_IMU_SCRATCH_0);
+
return r;
}
@@ -4953,23 +4996,16 @@ static int gfx_v11_0_update_gfx_clock_gating(struct amdgpu_device *adev,
static void gfx_v11_0_update_spm_vmid(struct amdgpu_device *adev, unsigned vmid)
{
- u32 reg, data;
+ u32 data;
amdgpu_gfx_off_ctrl(adev, false);
- reg = SOC15_REG_OFFSET(GC, 0, regRLC_SPM_MC_CNTL);
- if (amdgpu_sriov_is_pp_one_vf(adev))
- data = RREG32_NO_KIQ(reg);
- else
- data = RREG32(reg);
+ data = RREG32_SOC15_NO_KIQ(GC, 0, regRLC_SPM_MC_CNTL);
data &= ~RLC_SPM_MC_CNTL__RLC_SPM_VMID_MASK;
data |= (vmid & RLC_SPM_MC_CNTL__RLC_SPM_VMID_MASK) << RLC_SPM_MC_CNTL__RLC_SPM_VMID__SHIFT;
- if (amdgpu_sriov_is_pp_one_vf(adev))
- WREG32_SOC15_NO_KIQ(GC, 0, regRLC_SPM_MC_CNTL, data);
- else
- WREG32_SOC15(GC, 0, regRLC_SPM_MC_CNTL, data);
+ WREG32_SOC15_NO_KIQ(GC, 0, regRLC_SPM_MC_CNTL, data);
amdgpu_gfx_off_ctrl(adev, true);
}
@@ -5001,9 +5037,10 @@ static void gfx_v11_cntl_power_gating(struct amdgpu_device *adev, bool enable)
// Program RLC_PG_DELAY3 for CGPG hysteresis
if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) {
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
WREG32_SOC15(GC, 0, regRLC_PG_DELAY_3, RLC_PG_DELAY_3_DEFAULT_GC_11_0_1);
break;
default:
@@ -5030,7 +5067,7 @@ static int gfx_v11_0_set_powergating_state(void *handle,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
@@ -5038,6 +5075,7 @@ static int gfx_v11_0_set_powergating_state(void *handle,
break;
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
if (!enable)
amdgpu_gfx_off_ctrl(adev, false);
@@ -5062,12 +5100,13 @@ static int gfx_v11_0_set_clockgating_state(void *handle,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
gfx_v11_0_update_gfx_clock_gating(adev,
state == AMD_CG_STATE_GATE);
break;
@@ -5144,45 +5183,17 @@ static u64 gfx_v11_0_ring_get_wptr_gfx(struct amdgpu_ring *ring)
static void gfx_v11_0_ring_set_wptr_gfx(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
- uint32_t *wptr_saved;
- uint32_t *is_queue_unmap;
- uint64_t aggregated_db_index;
- uint32_t mqd_size = adev->mqds[AMDGPU_HW_IP_GFX].mqd_size;
- uint64_t wptr_tmp;
-
- if (ring->is_mes_queue) {
- wptr_saved = (uint32_t *)(ring->mqd_ptr + mqd_size);
- is_queue_unmap = (uint32_t *)(ring->mqd_ptr + mqd_size +
- sizeof(uint32_t));
- aggregated_db_index =
- amdgpu_mes_get_aggregated_doorbell_index(adev,
- ring->hw_prio);
-
- wptr_tmp = ring->wptr & ring->buf_mask;
- atomic64_set((atomic64_t *)ring->wptr_cpu_addr, wptr_tmp);
- *wptr_saved = wptr_tmp;
- /* assume doorbell always being used by mes mapped queue */
- if (*is_queue_unmap) {
- WDOORBELL64(aggregated_db_index, wptr_tmp);
- WDOORBELL64(ring->doorbell_index, wptr_tmp);
- } else {
- WDOORBELL64(ring->doorbell_index, wptr_tmp);
- if (*is_queue_unmap)
- WDOORBELL64(aggregated_db_index, wptr_tmp);
- }
+ if (ring->use_doorbell) {
+ /* XXX check if swapping is necessary on BE */
+ atomic64_set((atomic64_t *)ring->wptr_cpu_addr,
+ ring->wptr);
+ WDOORBELL64(ring->doorbell_index, ring->wptr);
} else {
- if (ring->use_doorbell) {
- /* XXX check if swapping is necessary on BE */
- atomic64_set((atomic64_t *)ring->wptr_cpu_addr,
- ring->wptr);
- WDOORBELL64(ring->doorbell_index, ring->wptr);
- } else {
- WREG32_SOC15(GC, 0, regCP_RB0_WPTR,
- lower_32_bits(ring->wptr));
- WREG32_SOC15(GC, 0, regCP_RB0_WPTR_HI,
- upper_32_bits(ring->wptr));
- }
+ WREG32_SOC15(GC, 0, regCP_RB0_WPTR,
+ lower_32_bits(ring->wptr));
+ WREG32_SOC15(GC, 0, regCP_RB0_WPTR_HI,
+ upper_32_bits(ring->wptr));
}
}
@@ -5207,42 +5218,14 @@ static u64 gfx_v11_0_ring_get_wptr_compute(struct amdgpu_ring *ring)
static void gfx_v11_0_ring_set_wptr_compute(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
- uint32_t *wptr_saved;
- uint32_t *is_queue_unmap;
- uint64_t aggregated_db_index;
- uint32_t mqd_size = adev->mqds[AMDGPU_HW_IP_COMPUTE].mqd_size;
- uint64_t wptr_tmp;
- if (ring->is_mes_queue) {
- wptr_saved = (uint32_t *)(ring->mqd_ptr + mqd_size);
- is_queue_unmap = (uint32_t *)(ring->mqd_ptr + mqd_size +
- sizeof(uint32_t));
- aggregated_db_index =
- amdgpu_mes_get_aggregated_doorbell_index(adev,
- ring->hw_prio);
-
- wptr_tmp = ring->wptr & ring->buf_mask;
- atomic64_set((atomic64_t *)ring->wptr_cpu_addr, wptr_tmp);
- *wptr_saved = wptr_tmp;
- /* assume doorbell always used by mes mapped queue */
- if (*is_queue_unmap) {
- WDOORBELL64(aggregated_db_index, wptr_tmp);
- WDOORBELL64(ring->doorbell_index, wptr_tmp);
- } else {
- WDOORBELL64(ring->doorbell_index, wptr_tmp);
-
- if (*is_queue_unmap)
- WDOORBELL64(aggregated_db_index, wptr_tmp);
- }
+ /* XXX check if swapping is necessary on BE */
+ if (ring->use_doorbell) {
+ atomic64_set((atomic64_t *)ring->wptr_cpu_addr,
+ ring->wptr);
+ WDOORBELL64(ring->doorbell_index, ring->wptr);
} else {
- /* XXX check if swapping is necessary on BE */
- if (ring->use_doorbell) {
- atomic64_set((atomic64_t *)ring->wptr_cpu_addr,
- ring->wptr);
- WDOORBELL64(ring->doorbell_index, ring->wptr);
- } else {
- BUG(); /* only DOORBELL method supported on gfx11 now */
- }
+ BUG(); /* only DOORBELL method supported on gfx11 now */
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 885ebd703260..1943beb135c4 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -883,8 +883,8 @@ static int gfx_v8_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
gpu_addr = adev->wb.gpu_addr + (index * 4);
adev->wb.wb[index] = cpu_to_le32(0xCAFEDEAD);
memset(&ib, 0, sizeof(ib));
- r = amdgpu_ib_get(adev, NULL, 16,
- AMDGPU_IB_POOL_DIRECT, &ib);
+
+ r = amdgpu_ib_get(adev, NULL, 20, AMDGPU_IB_POOL_DIRECT, &ib);
if (r)
goto err1;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index fd61574a737c..69c500910746 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -895,7 +895,7 @@ static void gfx_v9_0_set_kiq_pm4_funcs(struct amdgpu_device *adev)
static void gfx_v9_0_init_golden_registers(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
soc15_program_register_sequence(adev,
golden_settings_gc_9_0,
@@ -951,8 +951,8 @@ static void gfx_v9_0_init_golden_registers(struct amdgpu_device *adev)
break;
}
- if ((adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 1)) &&
- (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 2)))
+ if ((amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 1)) &&
+ (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 2)))
soc15_program_register_sequence(adev, golden_settings_gc_9_x_common,
(const u32)ARRAY_SIZE(golden_settings_gc_9_x_common));
}
@@ -1039,8 +1039,8 @@ static int gfx_v9_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
gpu_addr = adev->wb.gpu_addr + (index * 4);
adev->wb.wb[index] = cpu_to_le32(0xCAFEDEAD);
memset(&ib, 0, sizeof(ib));
- r = amdgpu_ib_get(adev, NULL, 16,
- AMDGPU_IB_POOL_DIRECT, &ib);
+
+ r = amdgpu_ib_get(adev, NULL, 20, AMDGPU_IB_POOL_DIRECT, &ib);
if (r)
goto err1;
@@ -1095,14 +1095,14 @@ static void gfx_v9_0_check_fw_write_wait(struct amdgpu_device *adev)
adev->gfx.me_fw_write_wait = false;
adev->gfx.mec_fw_write_wait = false;
- if ((adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 1)) &&
+ if ((amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 1)) &&
((adev->gfx.mec_fw_version < 0x000001a5) ||
- (adev->gfx.mec_feature_version < 46) ||
- (adev->gfx.pfp_fw_version < 0x000000b7) ||
- (adev->gfx.pfp_feature_version < 46)))
+ (adev->gfx.mec_feature_version < 46) ||
+ (adev->gfx.pfp_fw_version < 0x000000b7) ||
+ (adev->gfx.pfp_feature_version < 46)))
DRM_WARN_ONCE("CP firmware version too old, please update!");
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
if ((adev->gfx.me_fw_version >= 0x0000009c) &&
(adev->gfx.me_feature_version >= 42) &&
@@ -1202,7 +1202,7 @@ static bool is_raven_kicker(struct amdgpu_device *adev)
static bool check_if_enlarge_doorbell_range(struct amdgpu_device *adev)
{
- if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 3, 0)) &&
+ if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 3, 0)) &&
(adev->gfx.me_fw_version >= 0x000000a5) &&
(adev->gfx.me_feature_version >= 52))
return true;
@@ -1215,7 +1215,7 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
if (gfx_v9_0_should_disable_gfxoff(adev->pdev))
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 2, 1):
case IP_VERSION(9, 4, 0):
@@ -1326,9 +1326,9 @@ out:
static bool gfx_v9_0_load_mec2_fw_bin_support(struct amdgpu_device *adev)
{
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 3, 0))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 1) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 3, 0))
return false;
return true;
@@ -1485,7 +1485,7 @@ static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev)
if (adev->flags & AMD_IS_APU)
always_on_cu_num = 4;
- else if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 2, 1))
+ else if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 2, 1))
always_on_cu_num = 8;
else
always_on_cu_num = 12;
@@ -1836,7 +1836,7 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
u32 gb_addr_config;
int err;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
adev->gfx.config.max_hw_contexts = 8;
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
@@ -2002,7 +2002,7 @@ static int gfx_v9_0_sw_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
unsigned int hw_prio;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 2, 1):
case IP_VERSION(9, 4, 0):
@@ -2363,7 +2363,7 @@ static void gfx_v9_0_init_sq_config(struct amdgpu_device *adev)
{
uint32_t tmp;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 4, 1):
tmp = RREG32_SOC15(GC, 0, mmSQ_CONFIG);
tmp = REG_SET_FIELD(tmp, SQ_CONFIG, DISABLE_BARRIER_WAITCNT,
@@ -2700,7 +2700,7 @@ static void gfx_v9_0_init_gfx_power_gating(struct amdgpu_device *adev)
/* program GRBM_REG_SAVE_GFX_IDLE_THRESHOLD to 0x55f0 */
data |= (0x55f0 << RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD__SHIFT);
WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_AUTO_PG_CTRL), data);
- if (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 3, 0))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 3, 0))
pwr_10_0_gfxip_control_over_cgpg(adev, true);
}
}
@@ -2812,7 +2812,8 @@ static void gfx_v9_0_init_pg(struct amdgpu_device *adev)
* And it's needed by gfxoff feature.
*/
if (adev->gfx.rlc.is_rlc_v2_1) {
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 2, 1) ||
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(9, 2, 1) ||
(adev->apu_flags & AMD_APU_IS_RAVEN2))
gfx_v9_1_init_rlc_save_restore_list(adev);
gfx_v9_0_enable_save_restore_machine(adev);
@@ -2925,7 +2926,7 @@ static int gfx_v9_0_rlc_resume(struct amdgpu_device *adev)
return r;
}
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 2, 2):
case IP_VERSION(9, 1, 0):
gfx_v9_0_init_lbpw(adev);
@@ -3713,8 +3714,8 @@ static void gfx_v9_0_init_tcp_config(struct amdgpu_device *adev)
{
u32 tmp;
- if (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 1) &&
- adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 2))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 1) &&
+ amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 2))
return;
tmp = RREG32_SOC15(GC, 0, mmTCP_ADDR_CONFIG);
@@ -3754,7 +3755,7 @@ static int gfx_v9_0_hw_init(void *handle)
if (r)
return r;
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2))
gfx_v9_4_2_set_power_brake_sequence(adev);
return r;
@@ -3802,7 +3803,7 @@ static int gfx_v9_0_hw_fini(void *handle)
/* Skip stopping RLC with A+A reset or when RLC controls GFX clock */
if ((adev->gmc.xgmi.connected_to_cpu && amdgpu_in_reset(adev)) ||
- (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 4, 2))) {
+ (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(9, 4, 2))) {
dev_dbg(adev->dev, "Skipping RLC halt\n");
return 0;
}
@@ -3986,7 +3987,7 @@ static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev)
{
uint64_t clock, clock_lo, clock_hi, hi_check;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 3, 0):
preempt_disable();
clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Renoir);
@@ -4005,7 +4006,9 @@ static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev)
default:
amdgpu_gfx_off_ctrl(adev, false);
mutex_lock(&adev->gfx.gpu_clock_mutex);
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 0, 1) && amdgpu_sriov_runtime(adev)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(9, 0, 1) &&
+ amdgpu_sriov_runtime(adev)) {
clock = gfx_v9_0_kiq_read_clock(adev);
} else {
WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
@@ -4357,7 +4360,7 @@ static int gfx_v9_0_do_edc_gpr_workarounds(struct amdgpu_device *adev)
if (!ring->sched.ready)
return 0;
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 1)) {
vgpr_init_shader_ptr = vgpr_init_compute_shader_arcturus;
vgpr_init_shader_size = sizeof(vgpr_init_compute_shader_arcturus);
vgpr_init_regs_ptr = vgpr_init_regs_arcturus;
@@ -4509,8 +4512,8 @@ static int gfx_v9_0_early_init(void *handle)
adev->gfx.funcs = &gfx_v9_0_gfx_funcs;
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 1) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2))
adev->gfx.num_gfx_rings = 0;
else
adev->gfx.num_gfx_rings = GFX9_NUM_GFX_RINGS;
@@ -4548,7 +4551,7 @@ static int gfx_v9_0_ecc_late_init(void *handle)
}
/* requires IBs so do in late init after IB pool is initialized */
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2))
r = gfx_v9_4_2_do_edc_gpr_workarounds(adev);
else
r = gfx_v9_0_do_edc_gpr_workarounds(adev);
@@ -4580,7 +4583,7 @@ static int gfx_v9_0_late_init(void *handle)
if (r)
return r;
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2))
gfx_v9_4_2_debug_trap_config_init(adev,
adev->vm_manager.first_kfd_vmid, AMDGPU_NUM_VMID);
else
@@ -4676,7 +4679,7 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
/* 1 - RLC_CGTT_MGCG_OVERRIDE */
def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
- if (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 2, 1))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 2, 1))
data &= ~RLC_CGTT_MGCG_OVERRIDE__CPF_CGTT_SCLK_OVERRIDE_MASK;
data &= ~(RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK |
@@ -4710,7 +4713,7 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
/* 1 - MGCG_OVERRIDE */
def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
- if (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 2, 1))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 2, 1))
data |= RLC_CGTT_MGCG_OVERRIDE__CPF_CGTT_SCLK_OVERRIDE_MASK;
data |= (RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK |
@@ -4816,7 +4819,7 @@ static void gfx_v9_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
/* enable cgcg FSM(0x0000363F) */
def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL);
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 1))
data = (0x2000 << RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD__SHIFT) |
RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK;
else
@@ -4951,7 +4954,7 @@ static int gfx_v9_0_set_powergating_state(void *handle,
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
bool enable = (state == AMD_PG_STATE_GATE);
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 2, 2):
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 3, 0):
@@ -4998,7 +5001,7 @@ static int gfx_v9_0_set_clockgating_state(void *handle,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 2, 1):
case IP_VERSION(9, 4, 0):
@@ -5048,7 +5051,7 @@ static void gfx_v9_0_get_clockgating_state(void *handle, u64 *flags)
if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK)
*flags |= AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_MGLS;
- if (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 1)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 1)) {
/* AMD_CG_SUPPORT_GFX_3D_CGCG */
data = RREG32_KIQ(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D));
if (data & RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK)
@@ -6454,7 +6457,7 @@ static int gfx_v9_0_ras_error_inject(struct amdgpu_device *adev,
return ret;
}
-static const char *vml2_mems[] = {
+static const char * const vml2_mems[] = {
"UTC_VML2_BANK_CACHE_0_BIGK_MEM0",
"UTC_VML2_BANK_CACHE_0_BIGK_MEM1",
"UTC_VML2_BANK_CACHE_0_4K_MEM0",
@@ -6473,7 +6476,7 @@ static const char *vml2_mems[] = {
"UTC_VML2_BANK_CACHE_3_4K_MEM1",
};
-static const char *vml2_walker_mems[] = {
+static const char * const vml2_walker_mems[] = {
"UTC_VML2_CACHE_PDE0_MEM0",
"UTC_VML2_CACHE_PDE0_MEM1",
"UTC_VML2_CACHE_PDE1_MEM0",
@@ -6483,7 +6486,7 @@ static const char *vml2_walker_mems[] = {
"UTC_VML2_RDIF_LOG_FIFO",
};
-static const char *atc_l2_cache_2m_mems[] = {
+static const char * const atc_l2_cache_2m_mems[] = {
"UTC_ATCL2_CACHE_2M_BANK0_WAY0_MEM",
"UTC_ATCL2_CACHE_2M_BANK0_WAY1_MEM",
"UTC_ATCL2_CACHE_2M_BANK1_WAY0_MEM",
@@ -7087,7 +7090,7 @@ static void gfx_v9_0_set_irq_funcs(struct amdgpu_device *adev)
static void gfx_v9_0_set_rlc_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 2, 1):
case IP_VERSION(9, 4, 0):
@@ -7106,7 +7109,7 @@ static void gfx_v9_0_set_rlc_funcs(struct amdgpu_device *adev)
static void gfx_v9_0_set_gds_init(struct amdgpu_device *adev)
{
/* init asci gds info */
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 2, 1):
case IP_VERSION(9, 4, 0):
@@ -7128,7 +7131,7 @@ static void gfx_v9_0_set_gds_init(struct amdgpu_device *adev)
break;
}
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 4, 0):
adev->gds.gds_compute_max_wave_id = 0x7ff;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c
index 63f6843a069e..065b2bd5f5a6 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c
@@ -746,8 +746,6 @@ void gfx_v9_4_2_init_golden_registers(struct amdgpu_device *adev,
die_id);
break;
}
-
- return;
}
void gfx_v9_4_2_debug_trap_config_init(struct amdgpu_device *adev,
@@ -1548,8 +1546,8 @@ static void gfx_v9_4_2_log_utc_edc_count(struct amdgpu_device *adev,
uint32_t ded_cnt)
{
uint32_t bank, way, mem;
- static const char *vml2_way_str[] = { "BIGK", "4K" };
- static const char *utcl2_rounter_str[] = { "VMC", "APT" };
+ static const char * const vml2_way_str[] = { "BIGK", "4K" };
+ static const char * const utcl2_rounter_str[] = { "VMC", "APT" };
mem = instance % blk->num_mem_blocks;
way = (instance / blk->num_mem_blocks) % blk->num_ways;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
index 18ce5fe45f6f..4a09cc0d8ce0 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
@@ -256,6 +256,7 @@ static int gfx_v9_4_3_ring_test_ring(struct amdgpu_ring *ring)
xcc_offset = SOC15_REG_OFFSET(GC, 0, regSCRATCH_REG0);
scratch_reg0_offset = SOC15_REG_OFFSET(GC, GET_INST(GC, ring->xcc_id), regSCRATCH_REG0);
WREG32(scratch_reg0_offset, 0xCAFEDEAD);
+ tmp = RREG32(scratch_reg0_offset);
r = amdgpu_ring_alloc(ring, 3);
if (r)
@@ -296,8 +297,8 @@ static int gfx_v9_4_3_ring_test_ib(struct amdgpu_ring *ring, long timeout)
gpu_addr = adev->wb.gpu_addr + (index * 4);
adev->wb.wb[index] = cpu_to_le32(0xCAFEDEAD);
memset(&ib, 0, sizeof(ib));
- r = amdgpu_ib_get(adev, NULL, 16,
- AMDGPU_IB_POOL_DIRECT, &ib);
+
+ r = amdgpu_ib_get(adev, NULL, 20, AMDGPU_IB_POOL_DIRECT, &ib);
if (r)
goto err1;
@@ -623,7 +624,7 @@ static int gfx_v9_4_3_switch_compute_partition(struct amdgpu_device *adev,
int num_xccs_per_xcp)
{
int ret, i, num_xcc;
- u32 tmp = 0, regval;
+ u32 tmp = 0;
if (adev->psp.funcs) {
ret = psp_spatial_partition(&adev->psp,
@@ -631,24 +632,23 @@ static int gfx_v9_4_3_switch_compute_partition(struct amdgpu_device *adev,
num_xccs_per_xcp);
if (ret)
return ret;
- }
-
- num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ } else {
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
- for (i = 0; i < num_xcc; i++) {
- tmp = REG_SET_FIELD(tmp, CP_HYP_XCP_CTL, NUM_XCC_IN_XCP,
- num_xccs_per_xcp);
- tmp = REG_SET_FIELD(tmp, CP_HYP_XCP_CTL, VIRTUAL_XCC_ID,
- i % num_xccs_per_xcp);
- regval = RREG32_SOC15(GC, GET_INST(GC, i), regCP_HYP_XCP_CTL);
- if (regval != tmp)
+ for (i = 0; i < num_xcc; i++) {
+ tmp = REG_SET_FIELD(tmp, CP_HYP_XCP_CTL, NUM_XCC_IN_XCP,
+ num_xccs_per_xcp);
+ tmp = REG_SET_FIELD(tmp, CP_HYP_XCP_CTL, VIRTUAL_XCC_ID,
+ i % num_xccs_per_xcp);
WREG32_SOC15(GC, GET_INST(GC, i), regCP_HYP_XCP_CTL,
tmp);
+ }
+ ret = 0;
}
adev->gfx.num_xcc_per_xcp = num_xccs_per_xcp;
- return 0;
+ return ret;
}
static int gfx_v9_4_3_ih_to_xcc_inst(struct amdgpu_device *adev, int ih_node)
@@ -682,7 +682,7 @@ static int gfx_v9_4_3_gpu_early_init(struct amdgpu_device *adev)
adev->gfx.funcs = &gfx_v9_4_3_gfx_funcs;
adev->gfx.ras = &gfx_v9_4_3_ras;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 4, 3):
adev->gfx.config.max_hw_contexts = 8;
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
@@ -1102,6 +1102,7 @@ static void gfx_v9_4_3_init_rlcg_reg_access_ctrl(struct amdgpu_device *adev)
reg_access_ctrl->grbm_idx = SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regGRBM_GFX_INDEX);
reg_access_ctrl->spare_int = SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regRLC_SPARE_INT);
}
+ adev->gfx.rlc.rlcg_reg_access_supported = true;
}
static int gfx_v9_4_3_rlc_init(struct amdgpu_device *adev)
@@ -2430,7 +2431,7 @@ static int gfx_v9_4_3_set_clockgating_state(void *handle,
return 0;
num_xcc = NUM_XCC(adev->gfx.xcc_mask);
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 4, 3):
for (i = 0; i < num_xcc; i++)
gfx_v9_4_3_xcc_update_gfx_clock_gating(
@@ -2738,16 +2739,16 @@ static void gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
- mec_int_cntl = RREG32(mec_int_cntl_reg);
+ mec_int_cntl = RREG32_XCC(mec_int_cntl_reg, xcc_id);
mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL,
TIME_STAMP_INT_ENABLE, 0);
- WREG32(mec_int_cntl_reg, mec_int_cntl);
+ WREG32_XCC(mec_int_cntl_reg, mec_int_cntl, xcc_id);
break;
case AMDGPU_IRQ_STATE_ENABLE:
- mec_int_cntl = RREG32(mec_int_cntl_reg);
+ mec_int_cntl = RREG32_XCC(mec_int_cntl_reg, xcc_id);
mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL,
TIME_STAMP_INT_ENABLE, 1);
- WREG32(mec_int_cntl_reg, mec_int_cntl);
+ WREG32_XCC(mec_int_cntl_reg, mec_int_cntl, xcc_id);
break;
default:
break;
@@ -3653,19 +3654,19 @@ static const struct amdgpu_gfx_ras_reg_entry gfx_v9_4_3_ce_reg_list[] = {
AMDGPU_GFX_GC_CANE_MEM, 1},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regSPI_CE_ERR_STATUS_LO, regSPI_CE_ERR_STATUS_HI),
1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SPI"},
- AMDGPU_GFX_SPI_MEM, 8},
+ AMDGPU_GFX_SPI_MEM, 1},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regSP0_CE_ERR_STATUS_LO, regSP0_CE_ERR_STATUS_HI),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SP0"},
- AMDGPU_GFX_SP_MEM, 1},
+ AMDGPU_GFX_SP_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regSP1_CE_ERR_STATUS_LO, regSP1_CE_ERR_STATUS_HI),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SP1"},
- AMDGPU_GFX_SP_MEM, 1},
+ AMDGPU_GFX_SP_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regSQ_CE_ERR_STATUS_LO, regSQ_CE_ERR_STATUS_HI),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SQ"},
- AMDGPU_GFX_SQ_MEM, 8},
+ AMDGPU_GFX_SQ_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regSQC_CE_EDC_LO, regSQC_CE_EDC_HI),
5, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SQC"},
- AMDGPU_GFX_SQC_MEM, 8},
+ AMDGPU_GFX_SQC_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCX_CE_ERR_STATUS_LO, regTCX_CE_ERR_STATUS_HI),
2, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCX"},
AMDGPU_GFX_TCX_MEM, 1},
@@ -3674,22 +3675,22 @@ static const struct amdgpu_gfx_ras_reg_entry gfx_v9_4_3_ce_reg_list[] = {
AMDGPU_GFX_TCC_MEM, 1},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regTA_CE_EDC_LO, regTA_CE_EDC_HI),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TA"},
- AMDGPU_GFX_TA_MEM, 8},
+ AMDGPU_GFX_TA_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCI_CE_EDC_LO_REG, regTCI_CE_EDC_HI_REG),
- 31, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCI"},
+ 27, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCI"},
AMDGPU_GFX_TCI_MEM, 1},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCP_CE_EDC_LO_REG, regTCP_CE_EDC_HI_REG),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCP"},
- AMDGPU_GFX_TCP_MEM, 8},
+ AMDGPU_GFX_TCP_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regTD_CE_EDC_LO, regTD_CE_EDC_HI),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TD"},
- AMDGPU_GFX_TD_MEM, 8},
+ AMDGPU_GFX_TD_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regGCEA_CE_ERR_STATUS_LO, regGCEA_CE_ERR_STATUS_HI),
16, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "GCEA"},
AMDGPU_GFX_GCEA_MEM, 1},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regLDS_CE_ERR_STATUS_LO, regLDS_CE_ERR_STATUS_HI),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "LDS"},
- AMDGPU_GFX_LDS_MEM, 1},
+ AMDGPU_GFX_LDS_MEM, 4},
};
static const struct amdgpu_gfx_ras_reg_entry gfx_v9_4_3_ue_reg_list[] = {
@@ -3713,19 +3714,19 @@ static const struct amdgpu_gfx_ras_reg_entry gfx_v9_4_3_ue_reg_list[] = {
AMDGPU_GFX_GC_CANE_MEM, 1},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regSPI_UE_ERR_STATUS_LO, regSPI_UE_ERR_STATUS_HI),
1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SPI"},
- AMDGPU_GFX_SPI_MEM, 8},
+ AMDGPU_GFX_SPI_MEM, 1},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regSP0_UE_ERR_STATUS_LO, regSP0_UE_ERR_STATUS_HI),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SP0"},
- AMDGPU_GFX_SP_MEM, 1},
+ AMDGPU_GFX_SP_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regSP1_UE_ERR_STATUS_LO, regSP1_UE_ERR_STATUS_HI),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SP1"},
- AMDGPU_GFX_SP_MEM, 1},
+ AMDGPU_GFX_SP_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regSQ_UE_ERR_STATUS_LO, regSQ_UE_ERR_STATUS_HI),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SQ"},
- AMDGPU_GFX_SQ_MEM, 8},
+ AMDGPU_GFX_SQ_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regSQC_UE_EDC_LO, regSQC_UE_EDC_HI),
5, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SQC"},
- AMDGPU_GFX_SQC_MEM, 8},
+ AMDGPU_GFX_SQC_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCX_UE_ERR_STATUS_LO, regTCX_UE_ERR_STATUS_HI),
2, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCX"},
AMDGPU_GFX_TCX_MEM, 1},
@@ -3734,16 +3735,16 @@ static const struct amdgpu_gfx_ras_reg_entry gfx_v9_4_3_ue_reg_list[] = {
AMDGPU_GFX_TCC_MEM, 1},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regTA_UE_EDC_LO, regTA_UE_EDC_HI),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TA"},
- AMDGPU_GFX_TA_MEM, 8},
+ AMDGPU_GFX_TA_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCI_UE_EDC_LO_REG, regTCI_UE_EDC_HI_REG),
- 31, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCI"},
+ 27, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCI"},
AMDGPU_GFX_TCI_MEM, 1},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCP_UE_EDC_LO_REG, regTCP_UE_EDC_HI_REG),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCP"},
- AMDGPU_GFX_TCP_MEM, 8},
+ AMDGPU_GFX_TCP_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regTD_UE_EDC_LO, regTD_UE_EDC_HI),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TD"},
- AMDGPU_GFX_TD_MEM, 8},
+ AMDGPU_GFX_TD_MEM, 4},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCA_UE_ERR_STATUS_LO, regTCA_UE_ERR_STATUS_HI),
2, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCA"},
AMDGPU_GFX_TCA_MEM, 1},
@@ -3752,11 +3753,7 @@ static const struct amdgpu_gfx_ras_reg_entry gfx_v9_4_3_ue_reg_list[] = {
AMDGPU_GFX_GCEA_MEM, 1},
{{AMDGPU_RAS_REG_ENTRY(GC, 0, regLDS_UE_ERR_STATUS_LO, regLDS_UE_ERR_STATUS_HI),
10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "LDS"},
- AMDGPU_GFX_LDS_MEM, 1},
-};
-
-static const struct soc15_reg_entry gfx_v9_4_3_ea_err_status_regs = {
- SOC15_REG_ENTRY(GC, 0, regGCEA_ERR_STATUS), 0, 1, 16
+ AMDGPU_GFX_LDS_MEM, 4},
};
static void gfx_v9_4_3_inst_query_ras_err_count(struct amdgpu_device *adev,
@@ -3766,6 +3763,12 @@ static void gfx_v9_4_3_inst_query_ras_err_count(struct amdgpu_device *adev,
unsigned long ce_count = 0, ue_count = 0;
uint32_t i, j, k;
+ /* NOTE: convert xcc_id to physical XCD ID (XCD0 or XCD1) */
+ struct amdgpu_smuio_mcm_config_info mcm_info = {
+ .socket_id = adev->smuio.funcs->get_socket_id(adev),
+ .die_id = xcc_id & 0x01 ? 1 : 0,
+ };
+
mutex_lock(&adev->grbm_idx_mutex);
for (i = 0; i < ARRAY_SIZE(gfx_v9_4_3_ce_reg_list); i++) {
@@ -3797,6 +3800,27 @@ static void gfx_v9_4_3_inst_query_ras_err_count(struct amdgpu_device *adev,
}
}
+ /* handle extra register entries of UE */
+ for (; i < ARRAY_SIZE(gfx_v9_4_3_ue_reg_list); i++) {
+ for (j = 0; j < gfx_v9_4_3_ue_reg_list[i].se_num; j++) {
+ for (k = 0; k < gfx_v9_4_3_ue_reg_list[i].reg_entry.reg_inst; k++) {
+ /* no need to select if instance number is 1 */
+ if (gfx_v9_4_3_ue_reg_list[i].se_num > 1 ||
+ gfx_v9_4_3_ue_reg_list[i].reg_entry.reg_inst > 1)
+ gfx_v9_4_3_xcc_select_se_sh(adev, j, 0, k, xcc_id);
+
+ amdgpu_ras_inst_query_ras_error_count(adev,
+ &(gfx_v9_4_3_ue_reg_list[i].reg_entry),
+ 1,
+ gfx_v9_4_3_ras_mem_list_array[gfx_v9_4_3_ue_reg_list[i].mem_id_type].mem_id_ent,
+ gfx_v9_4_3_ras_mem_list_array[gfx_v9_4_3_ue_reg_list[i].mem_id_type].size,
+ GET_INST(GC, xcc_id),
+ AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
+ &ue_count);
+ }
+ }
+ }
+
gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
xcc_id);
mutex_unlock(&adev->grbm_idx_mutex);
@@ -3804,8 +3828,8 @@ static void gfx_v9_4_3_inst_query_ras_err_count(struct amdgpu_device *adev,
/* the caller should make sure initialize value of
* err_data->ue_count and err_data->ce_count
*/
- err_data->ce_count += ce_count;
- err_data->ue_count += ue_count;
+ amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count);
+ amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, ce_count);
}
static void gfx_v9_4_3_inst_reset_ras_err_count(struct amdgpu_device *adev,
@@ -3836,36 +3860,20 @@ static void gfx_v9_4_3_inst_reset_ras_err_count(struct amdgpu_device *adev,
}
}
- gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
- xcc_id);
- mutex_unlock(&adev->grbm_idx_mutex);
-}
-
-static void gfx_v9_4_3_inst_query_ea_err_status(struct amdgpu_device *adev,
- int xcc_id)
-{
- uint32_t i, j;
- uint32_t reg_value;
-
- mutex_lock(&adev->grbm_idx_mutex);
+ /* handle extra register entries of UE */
+ for (; i < ARRAY_SIZE(gfx_v9_4_3_ue_reg_list); i++) {
+ for (j = 0; j < gfx_v9_4_3_ue_reg_list[i].se_num; j++) {
+ for (k = 0; k < gfx_v9_4_3_ue_reg_list[i].reg_entry.reg_inst; k++) {
+ /* no need to select if instance number is 1 */
+ if (gfx_v9_4_3_ue_reg_list[i].se_num > 1 ||
+ gfx_v9_4_3_ue_reg_list[i].reg_entry.reg_inst > 1)
+ gfx_v9_4_3_xcc_select_se_sh(adev, j, 0, k, xcc_id);
- for (i = 0; i < gfx_v9_4_3_ea_err_status_regs.se_num; i++) {
- for (j = 0; j < gfx_v9_4_3_ea_err_status_regs.instance; j++) {
- gfx_v9_4_3_xcc_select_se_sh(adev, i, 0, j, xcc_id);
- reg_value = RREG32_SOC15(GC, GET_INST(GC, xcc_id),
- regGCEA_ERR_STATUS);
- if (REG_GET_FIELD(reg_value, GCEA_ERR_STATUS, SDP_RDRSP_STATUS) ||
- REG_GET_FIELD(reg_value, GCEA_ERR_STATUS, SDP_WRRSP_STATUS) ||
- REG_GET_FIELD(reg_value, GCEA_ERR_STATUS, SDP_RDRSP_DATAPARITY_ERROR)) {
- dev_warn(adev->dev,
- "GCEA err detected at instance: %d, status: 0x%x!\n",
- j, reg_value);
+ amdgpu_ras_inst_reset_ras_error_count(adev,
+ &(gfx_v9_4_3_ue_reg_list[i].reg_entry),
+ 1,
+ GET_INST(GC, xcc_id));
}
- /* clear after read */
- reg_value = REG_SET_FIELD(reg_value, GCEA_ERR_STATUS,
- CLEAR_ERROR_STATUS, 0x1);
- WREG32_SOC15(GC, GET_INST(GC, xcc_id), regGCEA_ERR_STATUS,
- reg_value);
}
}
@@ -3978,7 +3986,6 @@ static void gfx_v9_4_3_inst_query_sq_timeout_status(struct amdgpu_device *adev,
static void gfx_v9_4_3_inst_query_ras_err_status(struct amdgpu_device *adev,
void *ras_error_status, int xcc_id)
{
- gfx_v9_4_3_inst_query_ea_err_status(adev, xcc_id);
gfx_v9_4_3_inst_query_utc_err_status(adev, xcc_id);
gfx_v9_4_3_inst_query_sq_timeout_status(adev, xcc_id);
}
@@ -3991,27 +3998,6 @@ static void gfx_v9_4_3_inst_reset_utc_err_status(struct amdgpu_device *adev,
WREG32_SOC15(GC, GET_INST(GC, xcc_id), regVML2_WALKER_MEM_ECC_STATUS, 0x3);
}
-static void gfx_v9_4_3_inst_reset_ea_err_status(struct amdgpu_device *adev,
- int xcc_id)
-{
- uint32_t i, j;
- uint32_t value;
-
- mutex_lock(&adev->grbm_idx_mutex);
- for (i = 0; i < gfx_v9_4_3_ea_err_status_regs.se_num; i++) {
- for (j = 0; j < gfx_v9_4_3_ea_err_status_regs.instance; j++) {
- gfx_v9_4_3_xcc_select_se_sh(adev, i, 0, j, xcc_id);
- value = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regGCEA_ERR_STATUS);
- value = REG_SET_FIELD(value, GCEA_ERR_STATUS,
- CLEAR_ERROR_STATUS, 0x1);
- WREG32_SOC15(GC, GET_INST(GC, xcc_id), regGCEA_ERR_STATUS, value);
- }
- }
- gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
- xcc_id);
- mutex_unlock(&adev->grbm_idx_mutex);
-}
-
static void gfx_v9_4_3_inst_reset_sq_timeout_status(struct amdgpu_device *adev,
int xcc_id)
{
@@ -4037,7 +4023,6 @@ static void gfx_v9_4_3_inst_reset_ras_err_status(struct amdgpu_device *adev,
void *ras_error_status, int xcc_id)
{
gfx_v9_4_3_inst_reset_utc_err_status(adev, xcc_id);
- gfx_v9_4_3_inst_reset_ea_err_status(adev, xcc_id);
gfx_v9_4_3_inst_reset_sq_timeout_status(adev, xcc_id);
}
@@ -4231,7 +4216,7 @@ static void gfx_v9_4_3_set_rlc_funcs(struct amdgpu_device *adev)
static void gfx_v9_4_3_set_gds_init(struct amdgpu_device *adev)
{
/* init asci gds info */
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 4, 3):
/* 9.4.3 removed all the GDS internal memory,
* only support GWS opcode in kernel, like barrier
@@ -4243,7 +4228,7 @@ static void gfx_v9_4_3_set_gds_init(struct amdgpu_device *adev)
break;
}
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 4, 3):
/* deprecated for 9.4.3, no usage at all */
adev->gds.gds_compute_max_wave_id = 0;
@@ -4354,7 +4339,7 @@ const struct amdgpu_ip_block_version gfx_v9_4_3_ip_block = {
.type = AMD_IP_BLOCK_TYPE_GFX,
.major = 9,
.minor = 4,
- .rev = 0,
+ .rev = 3,
.funcs = &gfx_v9_4_3_ip_funcs,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.c
new file mode 100644
index 000000000000..f9949fedfbb9
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.c
@@ -0,0 +1,516 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "amdgpu.h"
+#include "gfxhub_v11_5_0.h"
+
+#include "gc/gc_11_5_0_offset.h"
+#include "gc/gc_11_5_0_sh_mask.h"
+
+#include "navi10_enum.h"
+#include "soc15_common.h"
+
+#define regGCVM_L2_CNTL3_DEFAULT 0x80100007
+#define regGCVM_L2_CNTL4_DEFAULT 0x000000c1
+#define regGCVM_L2_CNTL5_DEFAULT 0x00003fe0
+
+
+static const char *gfxhub_client_ids[] = {
+ "CB/DB",
+ "Reserved",
+ "GE1",
+ "GE2",
+ "CPF",
+ "CPC",
+ "CPG",
+ "RLC",
+ "TCP",
+ "SQC (inst)",
+ "SQC (data)",
+ "SQG",
+ "Reserved",
+ "SDMA0",
+ "SDMA1",
+ "GCR",
+ "SDMA2",
+ "SDMA3",
+};
+
+static uint32_t gfxhub_v11_5_0_get_invalidate_req(unsigned int vmid,
+ uint32_t flush_type)
+{
+ u32 req = 0;
+
+ /* invalidate using legacy mode on vmid*/
+ req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ,
+ PER_VMID_INVALIDATE_REQ, 1 << vmid);
+ req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, flush_type);
+ req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PTES, 1);
+ req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE0, 1);
+ req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE1, 1);
+ req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE2, 1);
+ req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L1_PTES, 1);
+ req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ,
+ CLEAR_PROTECTION_FAULT_STATUS_ADDR, 0);
+
+ return req;
+}
+
+static void
+gfxhub_v11_5_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
+ uint32_t status)
+{
+ u32 cid = REG_GET_FIELD(status,
+ GCVM_L2_PROTECTION_FAULT_STATUS, CID);
+
+ dev_err(adev->dev,
+ "GCVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
+ status);
+ dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
+ cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" : gfxhub_client_ids[cid],
+ cid);
+ dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
+ REG_GET_FIELD(status,
+ GCVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS));
+ dev_err(adev->dev, "\t WALKER_ERROR: 0x%lx\n",
+ REG_GET_FIELD(status,
+ GCVM_L2_PROTECTION_FAULT_STATUS, WALKER_ERROR));
+ dev_err(adev->dev, "\t PERMISSION_FAULTS: 0x%lx\n",
+ REG_GET_FIELD(status,
+ GCVM_L2_PROTECTION_FAULT_STATUS, PERMISSION_FAULTS));
+ dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n",
+ REG_GET_FIELD(status,
+ GCVM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR));
+ dev_err(adev->dev, "\t RW: 0x%lx\n",
+ REG_GET_FIELD(status,
+ GCVM_L2_PROTECTION_FAULT_STATUS, RW));
+}
+
+static u64 gfxhub_v11_5_0_get_fb_location(struct amdgpu_device *adev)
+{
+ u64 base = RREG32_SOC15(GC, 0, regGCMC_VM_FB_LOCATION_BASE);
+
+ base &= GCMC_VM_FB_LOCATION_BASE__FB_BASE_MASK;
+ base <<= 24;
+
+ return base;
+}
+
+static u64 gfxhub_v11_5_0_get_mc_fb_offset(struct amdgpu_device *adev)
+{
+ return (u64)RREG32_SOC15(GC, 0, regGCMC_VM_FB_OFFSET) << 24;
+}
+
+static void gfxhub_v11_5_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
+ uint64_t page_table_base)
+{
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
+
+ WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
+ hub->ctx_addr_distance * vmid,
+ lower_32_bits(page_table_base));
+
+ WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
+ hub->ctx_addr_distance * vmid,
+ upper_32_bits(page_table_base));
+}
+
+static void gfxhub_v11_5_0_init_gart_aperture_regs(struct amdgpu_device *adev)
+{
+ uint64_t pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
+
+ gfxhub_v11_5_0_setup_vm_pt_regs(adev, 0, pt_base);
+
+ WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
+ (u32)(adev->gmc.gart_start >> 12));
+ WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
+ (u32)(adev->gmc.gart_start >> 44));
+
+ WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
+ (u32)(adev->gmc.gart_end >> 12));
+ WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
+ (u32)(adev->gmc.gart_end >> 44));
+}
+
+static void gfxhub_v11_5_0_init_system_aperture_regs(struct amdgpu_device *adev)
+{
+ uint64_t value;
+
+ WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BASE, 0);
+ WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BOT, adev->gmc.agp_start >> 24);
+ WREG32_SOC15(GC, 0, regGCMC_VM_AGP_TOP, adev->gmc.agp_end >> 24);
+
+ /* Program the system aperture low logical page number. */
+ WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_LOW_ADDR,
+ min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
+
+ WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+ max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
+
+ /* Set default page address. */
+ value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
+ WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
+ (u32)(value >> 12));
+ WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
+ (u32)(value >> 44));
+
+ /* Program "protection fault". */
+ WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
+ (u32)(adev->dummy_page_addr >> 12));
+ WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
+ (u32)((u64)adev->dummy_page_addr >> 44));
+
+ WREG32_FIELD15_PREREG(GC, 0, GCVM_L2_PROTECTION_FAULT_CNTL2,
+ ACTIVE_PAGE_MIGRATION_PTE_READ_RETRY, 1);
+}
+
+static void gfxhub_v11_5_0_init_tlb_regs(struct amdgpu_device *adev)
+{
+ uint32_t tmp;
+
+ /* Setup TLB control */
+ tmp = RREG32_SOC15(GC, 0, regGCMC_VM_MX_L1_TLB_CNTL);
+
+ tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 1);
+ tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, 3);
+ tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
+ ENABLE_ADVANCED_DRIVER_MODEL, 1);
+ tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
+ SYSTEM_APERTURE_UNMAPPED_ACCESS, 0);
+ tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0);
+ tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
+ MTYPE, MTYPE_UC); /* UC, uncached */
+
+ WREG32_SOC15(GC, 0, regGCMC_VM_MX_L1_TLB_CNTL, tmp);
+}
+
+static void gfxhub_v11_5_0_init_cache_regs(struct amdgpu_device *adev)
+{
+ uint32_t tmp;
+
+ /* These registers are not accessible to VF-SRIOV.
+ * The PF will program them instead.
+ */
+ if (amdgpu_sriov_vf(adev))
+ return;
+
+ /* Setup L2 cache */
+ tmp = RREG32_SOC15(GC, 0, regGCVM_L2_CNTL);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, ENABLE_L2_CACHE, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING, 0);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL,
+ ENABLE_DEFAULT_PAGE_OUT_TO_SYSTEM_MEMORY, 1);
+ /* XXX for emulation, Refer to closed source code.*/
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL,
+ L2_PDE0_CACHE_TAG_GENERATION_MODE, 0);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, PDE_FAULT_CLASSIFICATION, 0);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, IDENTITY_MODE_FRAGMENT_SIZE, 0);
+ WREG32_SOC15(GC, 0, regGCVM_L2_CNTL, tmp);
+
+ tmp = RREG32_SOC15(GC, 0, regGCVM_L2_CNTL2);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
+ WREG32_SOC15(GC, 0, regGCVM_L2_CNTL2, tmp);
+
+ tmp = regGCVM_L2_CNTL3_DEFAULT;
+ if (adev->gmc.translate_further) {
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3, BANK_SELECT, 12);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3,
+ L2_CACHE_BIGK_FRAGMENT_SIZE, 9);
+ } else {
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3, BANK_SELECT, 9);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3,
+ L2_CACHE_BIGK_FRAGMENT_SIZE, 6);
+ }
+ WREG32_SOC15(GC, 0, regGCVM_L2_CNTL3, tmp);
+
+ tmp = regGCVM_L2_CNTL4_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4, VMC_TAP_PDE_REQUEST_PHYSICAL, 0);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4, VMC_TAP_PTE_REQUEST_PHYSICAL, 0);
+ WREG32_SOC15(GC, 0, regGCVM_L2_CNTL4, tmp);
+
+ tmp = regGCVM_L2_CNTL5_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL5, L2_CACHE_SMALLK_FRAGMENT_SIZE, 0);
+ WREG32_SOC15(GC, 0, regGCVM_L2_CNTL5, tmp);
+}
+
+static void gfxhub_v11_5_0_enable_system_domain(struct amdgpu_device *adev)
+{
+ uint32_t tmp;
+
+ tmp = RREG32_SOC15(GC, 0, regGCVM_CONTEXT0_CNTL);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH, 0);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL,
+ RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
+ WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_CNTL, tmp);
+}
+
+static void gfxhub_v11_5_0_disable_identity_aperture(struct amdgpu_device *adev)
+{
+ /* These registers are not accessible to VF-SRIOV.
+ * The PF will program them instead.
+ */
+ if (amdgpu_sriov_vf(adev))
+ return;
+
+ WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32,
+ 0xFFFFFFFF);
+ WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32,
+ 0x0000000F);
+
+ WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_LO32,
+ 0);
+ WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_HI32,
+ 0);
+
+ WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_LO32, 0);
+ WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_HI32, 0);
+
+}
+
+static void gfxhub_v11_5_0_setup_vmid_config(struct amdgpu_device *adev)
+{
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
+ int i;
+ uint32_t tmp;
+
+ for (i = 0; i <= 14; i++) {
+ tmp = RREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL, i * hub->ctx_distance);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
+ adev->vm_manager.num_level);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
+ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
+ VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
+ READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
+ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
+ EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
+ PAGE_TABLE_BLOCK_SIZE,
+ adev->vm_manager.block_size - 9);
+ /* Send no-retry XNACK on fault to suppress VM fault storm. */
+ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
+ RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
+ !amdgpu_noretry);
+ WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL,
+ i * hub->ctx_distance, tmp);
+ WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
+ i * hub->ctx_addr_distance, 0);
+ WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_HI32,
+ i * hub->ctx_addr_distance, 0);
+ WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_END_ADDR_LO32,
+ i * hub->ctx_addr_distance,
+ lower_32_bits(adev->vm_manager.max_pfn - 1));
+ WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_END_ADDR_HI32,
+ i * hub->ctx_addr_distance,
+ upper_32_bits(adev->vm_manager.max_pfn - 1));
+ }
+
+ hub->vm_cntx_cntl = tmp;
+}
+
+static void gfxhub_v11_5_0_program_invalidation(struct amdgpu_device *adev)
+{
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
+ unsigned i;
+
+ for (i = 0 ; i < 18; ++i) {
+ WREG32_SOC15_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_ADDR_RANGE_LO32,
+ i * hub->eng_addr_distance, 0xffffffff);
+ WREG32_SOC15_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_ADDR_RANGE_HI32,
+ i * hub->eng_addr_distance, 0x1f);
+ }
+}
+
+static int gfxhub_v11_5_0_gart_enable(struct amdgpu_device *adev)
+{
+ if (amdgpu_sriov_vf(adev)) {
+ /*
+ * GCMC_VM_FB_LOCATION_BASE/TOP is NULL for VF, becuase they are
+ * VF copy registers so vbios post doesn't program them, for
+ * SRIOV driver need to program them
+ */
+ WREG32_SOC15(GC, 0, regGCMC_VM_FB_LOCATION_BASE,
+ adev->gmc.vram_start >> 24);
+ WREG32_SOC15(GC, 0, regGCMC_VM_FB_LOCATION_TOP,
+ adev->gmc.vram_end >> 24);
+ }
+
+ /* GART Enable. */
+ gfxhub_v11_5_0_init_gart_aperture_regs(adev);
+ gfxhub_v11_5_0_init_system_aperture_regs(adev);
+ gfxhub_v11_5_0_init_tlb_regs(adev);
+ gfxhub_v11_5_0_init_cache_regs(adev);
+
+ gfxhub_v11_5_0_enable_system_domain(adev);
+ gfxhub_v11_5_0_disable_identity_aperture(adev);
+ gfxhub_v11_5_0_setup_vmid_config(adev);
+ gfxhub_v11_5_0_program_invalidation(adev);
+
+ return 0;
+}
+
+static void gfxhub_v11_5_0_gart_disable(struct amdgpu_device *adev)
+{
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
+ u32 tmp;
+ u32 i;
+
+ /* Disable all tables */
+ for (i = 0; i < 16; i++)
+ WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT0_CNTL,
+ i * hub->ctx_distance, 0);
+
+ /* Setup TLB control */
+ tmp = RREG32_SOC15(GC, 0, regGCMC_VM_MX_L1_TLB_CNTL);
+ tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 0);
+ tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
+ ENABLE_ADVANCED_DRIVER_MODEL, 0);
+ WREG32_SOC15(GC, 0, regGCMC_VM_MX_L1_TLB_CNTL, tmp);
+
+ /* Setup L2 cache */
+ WREG32_FIELD15_PREREG(GC, 0, GCVM_L2_CNTL, ENABLE_L2_CACHE, 0);
+ WREG32_SOC15(GC, 0, regGCVM_L2_CNTL3, 0);
+}
+
+/**
+ * gfxhub_v11_5_0_set_fault_enable_default - update GART/VM fault handling
+ *
+ * @adev: amdgpu_device pointer
+ * @value: true redirects VM faults to the default page
+ */
+static void gfxhub_v11_5_0_set_fault_enable_default(struct amdgpu_device *adev,
+ bool value)
+{
+ u32 tmp;
+
+ /* NO halt CP when page fault */
+ tmp = RREG32_SOC15(GC, 0, regCP_DEBUG);
+ tmp = REG_SET_FIELD(tmp, CP_DEBUG, CPG_UTCL1_ERROR_HALT_DISABLE, 1);
+ WREG32_SOC15(GC, 0, regCP_DEBUG, tmp);
+
+ /* These registers are not accessible to VF-SRIOV.
+ * The PF will program them instead.
+ */
+ if (amdgpu_sriov_vf(adev))
+ return;
+
+ tmp = RREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ PDE1_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ PDE2_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ TRANSLATE_FURTHER_PROTECTION_FAULT_ENABLE_DEFAULT,
+ value);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ NACK_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ if (!value) {
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ CRASH_ON_NO_RETRY_FAULT, 1);
+ tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
+ CRASH_ON_RETRY_FAULT, 1);
+ }
+ WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
+}
+
+static const struct amdgpu_vmhub_funcs gfxhub_v11_5_0_vmhub_funcs = {
+ .print_l2_protection_fault_status = gfxhub_v11_5_0_print_l2_protection_fault_status,
+ .get_invalidate_req = gfxhub_v11_5_0_get_invalidate_req,
+};
+
+static void gfxhub_v11_5_0_init(struct amdgpu_device *adev)
+{
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
+
+ hub->ctx0_ptb_addr_lo32 =
+ SOC15_REG_OFFSET(GC, 0,
+ regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32);
+ hub->ctx0_ptb_addr_hi32 =
+ SOC15_REG_OFFSET(GC, 0,
+ regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
+ hub->vm_inv_eng0_sem =
+ SOC15_REG_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_SEM);
+ hub->vm_inv_eng0_req =
+ SOC15_REG_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_REQ);
+ hub->vm_inv_eng0_ack =
+ SOC15_REG_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_ACK);
+ hub->vm_context0_cntl =
+ SOC15_REG_OFFSET(GC, 0, regGCVM_CONTEXT0_CNTL);
+ hub->vm_l2_pro_fault_status =
+ SOC15_REG_OFFSET(GC, 0, regGCVM_L2_PROTECTION_FAULT_STATUS);
+ hub->vm_l2_pro_fault_cntl =
+ SOC15_REG_OFFSET(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL);
+
+ hub->ctx_distance = regGCVM_CONTEXT1_CNTL - regGCVM_CONTEXT0_CNTL;
+ hub->ctx_addr_distance = regGCVM_CONTEXT1_PAGE_TABLE_BASE_ADDR_LO32 -
+ regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32;
+ hub->eng_distance = regGCVM_INVALIDATE_ENG1_REQ -
+ regGCVM_INVALIDATE_ENG0_REQ;
+ hub->eng_addr_distance = regGCVM_INVALIDATE_ENG1_ADDR_RANGE_LO32 -
+ regGCVM_INVALIDATE_ENG0_ADDR_RANGE_LO32;
+
+ hub->vm_cntx_cntl_vm_fault = GCVM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ GCVM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ GCVM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ GCVM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ GCVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ GCVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ GCVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK;
+
+ hub->vmhub_funcs = &gfxhub_v11_5_0_vmhub_funcs;
+}
+
+const struct amdgpu_gfxhub_funcs gfxhub_v11_5_0_funcs = {
+ .get_fb_location = gfxhub_v11_5_0_get_fb_location,
+ .get_mc_fb_offset = gfxhub_v11_5_0_get_mc_fb_offset,
+ .setup_vm_pt_regs = gfxhub_v11_5_0_setup_vm_pt_regs,
+ .gart_enable = gfxhub_v11_5_0_gart_enable,
+ .gart_disable = gfxhub_v11_5_0_gart_disable,
+ .set_fault_enable_default = gfxhub_v11_5_0_set_fault_enable_default,
+ .init = gfxhub_v11_5_0_init,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.h b/drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.h
new file mode 100644
index 000000000000..265ab631b3d0
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __GFXHUB_V11_5_0_H__
+#define __GFXHUB_V11_5_0_H__
+
+extern const struct amdgpu_gfxhub_funcs gfxhub_v11_5_0_funcs;
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
index cdc290a474a9..53a2ba5fcf4b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
@@ -260,7 +260,7 @@ static void gfxhub_v1_0_setup_vmid_config(struct amdgpu_device *adev)
block_size -= 9;
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(GC, 0, mmVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(GC, 0, mmVM_CONTEXT1_CNTL, i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
num_level);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
index 0834af771549..55423ff1bb49 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
@@ -329,7 +329,8 @@ static void gfxhub_v1_2_xcc_setup_vmid_config(struct amdgpu_device *adev,
for_each_inst(j, xcc_mask) {
hub = &adev->vmhub[AMDGPU_GFXHUB(j)];
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(GC, GET_INST(GC, j), regVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(GC, GET_INST(GC, j), regVM_CONTEXT1_CNTL,
+ i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
num_level);
@@ -356,11 +357,14 @@ static void gfxhub_v1_2_xcc_setup_vmid_config(struct amdgpu_device *adev,
* the SQ per-process.
* Retry faults need to be enabled for that to work.
*/
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
- !adev->gmc.noretry ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3));
+ tmp = REG_SET_FIELD(
+ tmp, VM_CONTEXT1_CNTL,
+ RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
+ !adev->gmc.noretry ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(9, 4, 2) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(9, 4, 3));
WREG32_SOC15_OFFSET(GC, GET_INST(GC, j), regVM_CONTEXT1_CNTL,
i * hub->ctx_distance, tmp);
WREG32_SOC15_OFFSET(GC, GET_INST(GC, j),
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c
index a041c6c970e1..793faf62cb07 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c
@@ -287,7 +287,7 @@ static void gfxhub_v2_0_setup_vmid_config(struct amdgpu_device *adev)
uint32_t tmp;
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_CNTL, i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
adev->vm_manager.num_level);
@@ -471,6 +471,9 @@ static void gfxhub_v2_0_init(struct amdgpu_device *adev)
GCVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
GCVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK;
+ /* TODO: This is only needed on some Navi 1x revisions */
+ hub->sdma_invalidation_workaround = true;
+
hub->vmhub_funcs = &gfxhub_v2_0_vmhub_funcs;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c
index 7708d5ded7b8..cd0e8a321e46 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c
@@ -296,7 +296,7 @@ static void gfxhub_v2_1_setup_vmid_config(struct amdgpu_device *adev)
uint32_t tmp;
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_CNTL, i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
adev->vm_manager.num_level);
@@ -510,7 +510,7 @@ static int gfxhub_v2_1_get_xgmi_info(struct amdgpu_device *adev)
u32 max_num_physical_nodes = 0;
u32 max_physical_node_id = 0;
- switch (adev->ip_versions[XGMI_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
case IP_VERSION(4, 8, 0):
max_num_physical_nodes = 4;
max_physical_node_id = 3;
@@ -548,7 +548,7 @@ static void gfxhub_v2_1_utcl2_harvest(struct amdgpu_device *adev)
adev->gfx.config.max_sh_per_se *
adev->gfx.config.max_shader_engines);
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 1):
case IP_VERSION(10, 3, 3):
/* Get SA disabled bitmap from eFuse setting */
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c
index e1c76c070ba9..abe30c8bd2ba 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c
@@ -164,8 +164,7 @@ static void gfxhub_v3_0_init_system_aperture_regs(struct amdgpu_device *adev)
max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
/* Set default page address. */
- value = adev->mem_scratch.gpu_addr - adev->gmc.vram_start
- + adev->vm_manager.vram_base_offset;
+ value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
(u32)(value >> 12));
WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
@@ -295,7 +294,7 @@ static void gfxhub_v3_0_setup_vmid_config(struct amdgpu_device *adev)
uint32_t tmp;
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL, i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
adev->vm_manager.num_level);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c
index 07f369c7a1ed..b3ef6e71811f 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c
@@ -169,8 +169,7 @@ static void gfxhub_v3_0_3_init_system_aperture_regs(struct amdgpu_device *adev)
max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
/* Set default page address. */
- value = adev->mem_scratch.gpu_addr - adev->gmc.vram_start
- + adev->vm_manager.vram_base_offset;
+ value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
(u32)(value >> 12));
WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
@@ -300,7 +299,7 @@ static void gfxhub_v3_0_3_setup_vmid_config(struct amdgpu_device *adev)
uint32_t tmp;
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL, i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
adev->vm_manager.num_level);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
index fa87a85e1017..a5a05c16c10d 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -51,8 +51,6 @@
#include "athub_v2_0.h"
#include "athub_v2_1.h"
-#include "amdgpu_reset.h"
-
static int gmc_v10_0_ecc_interrupt_state(struct amdgpu_device *adev,
struct amdgpu_irq_src *src,
unsigned int type,
@@ -145,11 +143,15 @@ static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev,
* the new fast GRBM interface.
*/
if ((entry->vmid_src == AMDGPU_GFXHUB(0)) &&
- (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 3, 0)))
+ (amdgpu_ip_version(adev, GC_HWIP, 0) <
+ IP_VERSION(10, 3, 0)))
RREG32(hub->vm_l2_pro_fault_status);
status = RREG32(hub->vm_l2_pro_fault_status);
WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
+
+ amdgpu_vm_update_fault_cache(adev, entry->pasid, addr, status,
+ entry->vmid_src ? AMDGPU_MMHUB0(0) : AMDGPU_GFXHUB(0));
}
if (!printk_ratelimit())
@@ -230,20 +232,47 @@ static bool gmc_v10_0_get_atc_vmid_pasid_mapping_info(
* by the amdgpu vm/hsa code.
*/
-static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
- unsigned int vmhub, uint32_t flush_type)
+/**
+ * gmc_v10_0_flush_gpu_tlb - gart tlb flush callback
+ *
+ * @adev: amdgpu_device pointer
+ * @vmid: vm instance to flush
+ * @vmhub: vmhub type
+ * @flush_type: the flush type
+ *
+ * Flush the TLB for the requested page table.
+ */
+static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
+ uint32_t vmhub, uint32_t flush_type)
{
bool use_semaphore = gmc_v10_0_use_invalidate_semaphore(adev, vmhub);
struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type);
- u32 tmp;
/* Use register 17 for GART */
const unsigned int eng = 17;
- unsigned int i;
unsigned char hub_ip = 0;
+ u32 sem, req, ack;
+ unsigned int i;
+ u32 tmp;
+
+ sem = hub->vm_inv_eng0_sem + hub->eng_distance * eng;
+ req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
+ ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
- hub_ip = (vmhub == AMDGPU_GFXHUB(0)) ?
- GC_HWIP : MMHUB_HWIP;
+ /* flush hdp cache */
+ adev->hdp.funcs->flush_hdp(adev, NULL);
+
+ /* For SRIOV run time, driver shouldn't access the register through MMIO
+ * Directly use kiq to do the vm invalidation instead
+ */
+ if (adev->gfx.kiq[0].ring.sched.ready && !adev->enable_mes &&
+ (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
+ amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
+ 1 << vmid, GET_INST(GC, 0));
+ return;
+ }
+
+ hub_ip = (vmhub == AMDGPU_GFXHUB(0)) ? GC_HWIP : MMHUB_HWIP;
spin_lock(&adev->gmc.invalidate_lock);
/*
@@ -257,9 +286,7 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
if (use_semaphore) {
for (i = 0; i < adev->usec_timeout; i++) {
/* a read return value of 1 means semaphore acuqire */
- tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem +
- hub->eng_distance * eng, hub_ip);
-
+ tmp = RREG32_RLC_NO_KIQ(sem, hub_ip);
if (tmp & 0x1)
break;
udelay(1);
@@ -269,24 +296,19 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
}
- WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_req +
- hub->eng_distance * eng,
- inv_req, hub_ip);
+ WREG32_RLC_NO_KIQ(req, inv_req, hub_ip);
/*
* Issue a dummy read to wait for the ACK register to be cleared
* to avoid a false ACK due to the new fast GRBM interface.
*/
if ((vmhub == AMDGPU_GFXHUB(0)) &&
- (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 3, 0)))
- RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_req +
- hub->eng_distance * eng, hub_ip);
+ (amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(10, 3, 0)))
+ RREG32_RLC_NO_KIQ(req, hub_ip);
/* Wait for ACK with a delay.*/
for (i = 0; i < adev->usec_timeout; i++) {
- tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_ack +
- hub->eng_distance * eng, hub_ip);
-
+ tmp = RREG32_RLC_NO_KIQ(ack, hub_ip);
tmp &= 1 << vmid;
if (tmp)
break;
@@ -296,109 +318,13 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
if (use_semaphore)
- /*
- * add semaphore release after invalidation,
- * write with 0 means semaphore release
- */
- WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem +
- hub->eng_distance * eng, 0, hub_ip);
+ WREG32_RLC_NO_KIQ(sem, 0, hub_ip);
spin_unlock(&adev->gmc.invalidate_lock);
- if (i < adev->usec_timeout)
- return;
-
- DRM_ERROR("Timeout waiting for VM flush hub: %d!\n", vmhub);
-}
-
-/**
- * gmc_v10_0_flush_gpu_tlb - gart tlb flush callback
- *
- * @adev: amdgpu_device pointer
- * @vmid: vm instance to flush
- * @vmhub: vmhub type
- * @flush_type: the flush type
- *
- * Flush the TLB for the requested page table.
- */
-static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
- uint32_t vmhub, uint32_t flush_type)
-{
- struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
- struct dma_fence *fence;
- struct amdgpu_job *job;
-
- int r;
-
- /* flush hdp cache */
- adev->hdp.funcs->flush_hdp(adev, NULL);
-
- /* For SRIOV run time, driver shouldn't access the register through MMIO
- * Directly use kiq to do the vm invalidation instead
- */
- if (adev->gfx.kiq[0].ring.sched.ready && !adev->enable_mes &&
- (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) &&
- down_read_trylock(&adev->reset_domain->sem)) {
- struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
- const unsigned int eng = 17;
- u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type);
- u32 req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
- u32 ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
-
- amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
- 1 << vmid);
-
- up_read(&adev->reset_domain->sem);
- return;
- }
-
- mutex_lock(&adev->mman.gtt_window_lock);
-
- if (vmhub == AMDGPU_MMHUB0(0)) {
- gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_MMHUB0(0), 0);
- mutex_unlock(&adev->mman.gtt_window_lock);
- return;
- }
-
- BUG_ON(vmhub != AMDGPU_GFXHUB(0));
-
- if (!adev->mman.buffer_funcs_enabled ||
- !adev->ib_pool_ready ||
- amdgpu_in_reset(adev) ||
- ring->sched.ready == false) {
- gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_GFXHUB(0), 0);
- mutex_unlock(&adev->mman.gtt_window_lock);
- return;
- }
-
- /* The SDMA on Navi has a bug which can theoretically result in memory
- * corruption if an invalidation happens at the same time as an VA
- * translation. Avoid this by doing the invalidation from the SDMA
- * itself.
- */
- r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.high_pr,
- AMDGPU_FENCE_OWNER_UNDEFINED,
- 16 * 4, AMDGPU_IB_POOL_IMMEDIATE,
- &job);
- if (r)
- goto error_alloc;
-
- job->vm_pd_addr = amdgpu_gmc_pd_addr(adev->gart.bo);
- job->vm_needs_flush = true;
- job->ibs->ptr[job->ibs->length_dw++] = ring->funcs->nop;
- amdgpu_ring_pad_ib(ring, &job->ibs[0]);
- fence = amdgpu_job_submit(job);
-
- mutex_unlock(&adev->mman.gtt_window_lock);
-
- dma_fence_wait(fence, false);
- dma_fence_put(fence);
-
- return;
-
-error_alloc:
- mutex_unlock(&adev->mman.gtt_window_lock);
- DRM_ERROR("Error flushing GPU TLB using the SDMA (%d)!\n", r);
+ if (i >= adev->usec_timeout)
+ dev_err(adev->dev, "Timeout waiting for VM flush hub: %d!\n",
+ vmhub);
}
/**
@@ -412,62 +338,31 @@ error_alloc:
*
* Flush the TLB for the requested pasid.
*/
-static int gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
- uint16_t pasid, uint32_t flush_type,
- bool all_hub, uint32_t inst)
+static void gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
+ uint16_t pasid, uint32_t flush_type,
+ bool all_hub, uint32_t inst)
{
+ uint16_t queried;
int vmid, i;
- signed long r;
- uint32_t seq;
- uint16_t queried_pasid;
- bool ret;
- u32 usec_timeout = amdgpu_sriov_vf(adev) ? SRIOV_USEC_TIMEOUT : adev->usec_timeout;
- struct amdgpu_ring *ring = &adev->gfx.kiq[0].ring;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
-
- if (amdgpu_emu_mode == 0 && ring->sched.ready) {
- spin_lock(&adev->gfx.kiq[0].ring_lock);
- /* 2 dwords flush + 8 dwords fence */
- amdgpu_ring_alloc(ring, kiq->pmf->invalidate_tlbs_size + 8);
- kiq->pmf->kiq_invalidate_tlbs(ring,
- pasid, flush_type, all_hub);
- r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
- if (r) {
- amdgpu_ring_undo(ring);
- spin_unlock(&adev->gfx.kiq[0].ring_lock);
- return -ETIME;
- }
-
- amdgpu_ring_commit(ring);
- spin_unlock(&adev->gfx.kiq[0].ring_lock);
- r = amdgpu_fence_wait_polling(ring, seq, usec_timeout);
- if (r < 1) {
- dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
- return -ETIME;
- }
-
- return 0;
- }
for (vmid = 1; vmid < AMDGPU_NUM_VMID; vmid++) {
-
- ret = gmc_v10_0_get_atc_vmid_pasid_mapping_info(adev, vmid,
- &queried_pasid);
- if (ret && queried_pasid == pasid) {
- if (all_hub) {
- for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
- gmc_v10_0_flush_gpu_tlb(adev, vmid,
- i, flush_type);
- } else {
- gmc_v10_0_flush_gpu_tlb(adev, vmid,
- AMDGPU_GFXHUB(0), flush_type);
- }
- if (!adev->enable_mes)
- break;
+ bool valid;
+
+ valid = gmc_v10_0_get_atc_vmid_pasid_mapping_info(adev, vmid,
+ &queried);
+ if (!valid || queried != pasid)
+ continue;
+
+ if (all_hub) {
+ for_each_set_bit(i, adev->vmhubs_mask,
+ AMDGPU_MAX_VMHUBS)
+ gmc_v10_0_flush_gpu_tlb(adev, vmid, i,
+ flush_type);
+ } else {
+ gmc_v10_0_flush_gpu_tlb(adev, vmid, AMDGPU_GFXHUB(0),
+ flush_type);
}
}
-
- return 0;
}
static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
@@ -634,6 +529,7 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev,
}
if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+ AMDGPU_GEM_CREATE_EXT_COHERENT |
AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
@@ -680,7 +576,7 @@ static void gmc_v10_0_set_gmc_funcs(struct amdgpu_device *adev)
static void gmc_v10_0_set_umc_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[UMC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, UMC_HWIP, 0)) {
case IP_VERSION(8, 7, 0):
adev->umc.max_ras_err_cnt_per_query = UMC_V8_7_TOTAL_CHANNEL_NUM;
adev->umc.channel_inst_num = UMC_V8_7_CHANNEL_INSTANCE_NUM;
@@ -697,7 +593,7 @@ static void gmc_v10_0_set_umc_funcs(struct amdgpu_device *adev)
static void gmc_v10_0_set_mmhub_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(2, 3, 0):
case IP_VERSION(2, 4, 0):
case IP_VERSION(2, 4, 1):
@@ -711,7 +607,7 @@ static void gmc_v10_0_set_mmhub_funcs(struct amdgpu_device *adev)
static void gmc_v10_0_set_gfxhub_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 1):
@@ -776,9 +672,11 @@ static void gmc_v10_0_vram_gtt_location(struct amdgpu_device *adev,
/* add the xgmi offset of the physical node */
base += adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size;
+ amdgpu_gmc_set_agp_default(adev, mc);
amdgpu_gmc_vram_location(adev, &adev->gmc, base);
- amdgpu_gmc_gart_location(adev, mc);
- amdgpu_gmc_agp_location(adev, mc);
+ amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_BEST_FIT);
+ if (!amdgpu_sriov_vf(adev) && (amdgpu_agp == 1))
+ amdgpu_gmc_agp_location(adev, mc);
/* base offset of vram pages */
adev->vm_manager.vram_base_offset = adev->gfxhub.funcs->get_mc_fb_offset(adev);
@@ -825,7 +723,7 @@ static int gmc_v10_0_mc_init(struct amdgpu_device *adev)
/* set the gart size */
if (amdgpu_gart_size == -1) {
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
default:
adev->gmc.gart_size = 512ULL << 20;
break;
@@ -892,7 +790,7 @@ static int gmc_v10_0_sw_init(void *handle)
adev->gmc.vram_vendor = vram_vendor;
}
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
adev->gmc.mall_size = 128 * 1024 * 1024;
break;
@@ -910,7 +808,7 @@ static int gmc_v10_0_sw_init(void *handle)
break;
}
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 2):
@@ -1084,8 +982,10 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev)
static int gmc_v10_0_hw_init(void *handle)
{
- int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ adev->gmc.flush_pasid_uses_kiq = !amdgpu_emu_mode;
/* The sequence of these two function calls matters.*/
gmc_v10_0_init_golden_registers(adev);
@@ -1195,7 +1095,8 @@ static int gmc_v10_0_set_clockgating_state(void *handle,
* is a new problem observed at DF 3.0.3, however with the same suspend sequence not
* seen any issue on the DF 3.0.2 series platform.
*/
- if (adev->in_s0ix && adev->ip_versions[DF_HWIP][0] > IP_VERSION(3, 0, 2)) {
+ if (adev->in_s0ix &&
+ amdgpu_ip_version(adev, DF_HWIP, 0) > IP_VERSION(3, 0, 2)) {
dev_dbg(adev->dev, "keep mmhub clock gating being enabled for s0ix\n");
return 0;
}
@@ -1204,7 +1105,7 @@ static int gmc_v10_0_set_clockgating_state(void *handle,
if (r)
return r;
- if (adev->ip_versions[ATHUB_HWIP][0] >= IP_VERSION(2, 1, 0))
+ if (amdgpu_ip_version(adev, ATHUB_HWIP, 0) >= IP_VERSION(2, 1, 0))
return athub_v2_1_set_clockgating(adev, state);
else
return athub_v2_0_set_clockgating(adev, state);
@@ -1214,13 +1115,13 @@ static void gmc_v10_0_get_clockgating_state(void *handle, u64 *flags)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 3) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 4))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 1, 3) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 1, 4))
return;
adev->mmhub.funcs->get_clockgating(adev, flags);
- if (adev->ip_versions[ATHUB_HWIP][0] >= IP_VERSION(2, 1, 0))
+ if (amdgpu_ip_version(adev, ATHUB_HWIP, 0) >= IP_VERSION(2, 1, 0))
athub_v2_1_get_clockgating(adev, flags);
else
athub_v2_0_get_clockgating(adev, flags);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
index e3b76fd28d15..23d7b548d13f 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
@@ -42,9 +42,11 @@
#include "nbio_v4_3.h"
#include "gfxhub_v3_0.h"
#include "gfxhub_v3_0_3.h"
+#include "gfxhub_v11_5_0.h"
#include "mmhub_v3_0.h"
#include "mmhub_v3_0_1.h"
#include "mmhub_v3_0_2.h"
+#include "mmhub_v3_3.h"
#include "athub_v3_0.h"
@@ -71,7 +73,8 @@ gmc_v11_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
* fini/suspend, so the overall state doesn't
* change over the course of suspend/resume.
*/
- if (!adev->in_s0ix)
+ if (!adev->in_s0ix && (adev->in_runpm || adev->in_suspend ||
+ amdgpu_in_reset(adev)))
amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB(0), false);
break;
case AMDGPU_IRQ_STATE_ENABLE:
@@ -117,6 +120,9 @@ static int gmc_v11_0_process_interrupt(struct amdgpu_device *adev,
status = RREG32(hub->vm_l2_pro_fault_status);
WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
+
+ amdgpu_vm_update_fault_cache(adev, entry->pasid, addr, status,
+ entry->vmid_src ? AMDGPU_MMHUB0(0) : AMDGPU_GFXHUB(0));
}
if (printk_ratelimit()) {
@@ -184,27 +190,50 @@ static bool gmc_v11_0_get_vmid_pasid_mapping_info(
return !!(*p_pasid);
}
-/*
- * GART
- * VMID 0 is the physical GPU addresses as used by the kernel.
- * VMIDs 1-15 are used for userspace clients and are handled
- * by the amdgpu vm/hsa code.
+/**
+ * gmc_v11_0_flush_gpu_tlb - gart tlb flush callback
+ *
+ * @adev: amdgpu_device pointer
+ * @vmid: vm instance to flush
+ * @vmhub: which hub to flush
+ * @flush_type: the flush type
+ *
+ * Flush the TLB for the requested page table.
*/
-
-static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
- unsigned int vmhub, uint32_t flush_type)
+static void gmc_v11_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
+ uint32_t vmhub, uint32_t flush_type)
{
bool use_semaphore = gmc_v11_0_use_invalidate_semaphore(adev, vmhub);
struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type);
- u32 tmp;
/* Use register 17 for GART */
const unsigned int eng = 17;
+ unsigned char hub_ip;
+ u32 sem, req, ack;
unsigned int i;
- unsigned char hub_ip = 0;
+ u32 tmp;
- hub_ip = (vmhub == AMDGPU_GFXHUB(0)) ?
- GC_HWIP : MMHUB_HWIP;
+ if ((vmhub == AMDGPU_GFXHUB(0)) && !adev->gfx.is_poweron)
+ return;
+
+ sem = hub->vm_inv_eng0_sem + hub->eng_distance * eng;
+ req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
+ ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
+
+ /* flush hdp cache */
+ adev->hdp.funcs->flush_hdp(adev, NULL);
+
+ /* For SRIOV run time, driver shouldn't access the register through MMIO
+ * Directly use kiq to do the vm invalidation instead
+ */
+ if ((adev->gfx.kiq[0].ring.sched.ready || adev->mes.ring.sched.ready) &&
+ (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
+ amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
+ 1 << vmid, GET_INST(GC, 0));
+ return;
+ }
+
+ hub_ip = (vmhub == AMDGPU_GFXHUB(0)) ? GC_HWIP : MMHUB_HWIP;
spin_lock(&adev->gmc.invalidate_lock);
/*
@@ -218,8 +247,7 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
if (use_semaphore) {
for (i = 0; i < adev->usec_timeout; i++) {
/* a read return value of 1 means semaphore acuqire */
- tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem +
- hub->eng_distance * eng, hub_ip);
+ tmp = RREG32_RLC_NO_KIQ(sem, hub_ip);
if (tmp & 0x1)
break;
udelay(1);
@@ -229,12 +257,11 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
}
- WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req, hub_ip);
+ WREG32_RLC_NO_KIQ(req, inv_req, hub_ip);
/* Wait for ACK with a delay.*/
for (i = 0; i < adev->usec_timeout; i++) {
- tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_ack +
- hub->eng_distance * eng, hub_ip);
+ tmp = RREG32_RLC_NO_KIQ(ack, hub_ip);
tmp &= 1 << vmid;
if (tmp)
break;
@@ -244,12 +271,7 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
if (use_semaphore)
- /*
- * add semaphore release after invalidation,
- * write with 0 means semaphore release
- */
- WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem +
- hub->eng_distance * eng, 0, hub_ip);
+ WREG32_RLC_NO_KIQ(sem, 0, hub_ip);
/* Issue additional private vm invalidation to MMHUB */
if ((vmhub != AMDGPU_GFXHUB(0)) &&
@@ -266,50 +288,8 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
spin_unlock(&adev->gmc.invalidate_lock);
- if (i < adev->usec_timeout)
- return;
-
- DRM_ERROR("Timeout waiting for VM flush ACK!\n");
-}
-
-/**
- * gmc_v11_0_flush_gpu_tlb - gart tlb flush callback
- *
- * @adev: amdgpu_device pointer
- * @vmid: vm instance to flush
- * @vmhub: which hub to flush
- * @flush_type: the flush type
- *
- * Flush the TLB for the requested page table.
- */
-static void gmc_v11_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
- uint32_t vmhub, uint32_t flush_type)
-{
- if ((vmhub == AMDGPU_GFXHUB(0)) && !adev->gfx.is_poweron)
- return;
-
- /* flush hdp cache */
- adev->hdp.funcs->flush_hdp(adev, NULL);
-
- /* For SRIOV run time, driver shouldn't access the register through MMIO
- * Directly use kiq to do the vm invalidation instead
- */
- if ((adev->gfx.kiq[0].ring.sched.ready || adev->mes.ring.sched.ready) &&
- (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
- struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
- const unsigned int eng = 17;
- u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type);
- u32 req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
- u32 ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
-
- amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
- 1 << vmid);
- return;
- }
-
- mutex_lock(&adev->mman.gtt_window_lock);
- gmc_v11_0_flush_vm_hub(adev, vmid, vmhub, 0);
- mutex_unlock(&adev->mman.gtt_window_lock);
+ if (i >= adev->usec_timeout)
+ dev_err(adev->dev, "Timeout waiting for VM flush ACK!\n");
}
/**
@@ -323,59 +303,31 @@ static void gmc_v11_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
*
* Flush the TLB for the requested pasid.
*/
-static int gmc_v11_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
- uint16_t pasid, uint32_t flush_type,
- bool all_hub, uint32_t inst)
+static void gmc_v11_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
+ uint16_t pasid, uint32_t flush_type,
+ bool all_hub, uint32_t inst)
{
+ uint16_t queried;
int vmid, i;
- signed long r;
- uint32_t seq;
- uint16_t queried_pasid;
- bool ret;
- struct amdgpu_ring *ring = &adev->gfx.kiq[0].ring;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
-
- if (amdgpu_emu_mode == 0 && ring->sched.ready) {
- spin_lock(&adev->gfx.kiq[0].ring_lock);
- /* 2 dwords flush + 8 dwords fence */
- amdgpu_ring_alloc(ring, kiq->pmf->invalidate_tlbs_size + 8);
- kiq->pmf->kiq_invalidate_tlbs(ring,
- pasid, flush_type, all_hub);
- r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
- if (r) {
- amdgpu_ring_undo(ring);
- spin_unlock(&adev->gfx.kiq[0].ring_lock);
- return -ETIME;
- }
-
- amdgpu_ring_commit(ring);
- spin_unlock(&adev->gfx.kiq[0].ring_lock);
- r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout);
- if (r < 1) {
- dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
- return -ETIME;
- }
-
- return 0;
- }
for (vmid = 1; vmid < 16; vmid++) {
-
- ret = gmc_v11_0_get_vmid_pasid_mapping_info(adev, vmid,
- &queried_pasid);
- if (ret && queried_pasid == pasid) {
- if (all_hub) {
- for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
- gmc_v11_0_flush_gpu_tlb(adev, vmid,
- i, flush_type);
- } else {
- gmc_v11_0_flush_gpu_tlb(adev, vmid,
- AMDGPU_GFXHUB(0), flush_type);
- }
+ bool valid;
+
+ valid = gmc_v11_0_get_vmid_pasid_mapping_info(adev, vmid,
+ &queried);
+ if (!valid || queried != pasid)
+ continue;
+
+ if (all_hub) {
+ for_each_set_bit(i, adev->vmhubs_mask,
+ AMDGPU_MAX_VMHUBS)
+ gmc_v11_0_flush_gpu_tlb(adev, vmid, i,
+ flush_type);
+ } else {
+ gmc_v11_0_flush_gpu_tlb(adev, vmid, AMDGPU_GFXHUB(0),
+ flush_type);
}
}
-
- return 0;
}
static uint64_t gmc_v11_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
@@ -498,8 +450,7 @@ static void gmc_v11_0_get_vm_pde(struct amdgpu_device *adev, int level,
uint64_t *addr, uint64_t *flags)
{
if (!(*flags & AMDGPU_PDE_PTE) && !(*flags & AMDGPU_PTE_SYSTEM))
- *addr = adev->vm_manager.vram_base_offset + *addr -
- adev->gmc.vram_start;
+ *addr = amdgpu_gmc_vram_mc2pa(adev, *addr);
BUG_ON(*addr & 0xFFFF00000000003FULL);
if (!adev->gmc.translate_further)
@@ -542,6 +493,7 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev,
}
if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+ AMDGPU_GEM_CREATE_EXT_COHERENT |
AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
@@ -587,7 +539,7 @@ static void gmc_v11_0_set_gmc_funcs(struct amdgpu_device *adev)
static void gmc_v11_0_set_umc_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[UMC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, UMC_HWIP, 0)) {
case IP_VERSION(8, 10, 0):
adev->umc.channel_inst_num = UMC_V8_10_CHANNEL_INSTANCE_NUM;
adev->umc.umc_inst_num = UMC_V8_10_UMC_INSTANCE_NUM;
@@ -610,13 +562,16 @@ static void gmc_v11_0_set_umc_funcs(struct amdgpu_device *adev)
static void gmc_v11_0_set_mmhub_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(3, 0, 1):
adev->mmhub.funcs = &mmhub_v3_0_1_funcs;
break;
case IP_VERSION(3, 0, 2):
adev->mmhub.funcs = &mmhub_v3_0_2_funcs;
break;
+ case IP_VERSION(3, 3, 0):
+ adev->mmhub.funcs = &mmhub_v3_3_funcs;
+ break;
default:
adev->mmhub.funcs = &mmhub_v3_0_funcs;
break;
@@ -625,10 +580,13 @@ static void gmc_v11_0_set_mmhub_funcs(struct amdgpu_device *adev)
static void gmc_v11_0_set_gfxhub_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(11, 0, 3):
adev->gfxhub.funcs = &gfxhub_v3_0_3_funcs;
break;
+ case IP_VERSION(11, 5, 0):
+ adev->gfxhub.funcs = &gfxhub_v11_5_0_funcs;
+ break;
default:
adev->gfxhub.funcs = &gfxhub_v3_0_funcs;
break;
@@ -679,9 +637,13 @@ static void gmc_v11_0_vram_gtt_location(struct amdgpu_device *adev,
base = adev->mmhub.funcs->get_fb_location(adev);
+ amdgpu_gmc_set_agp_default(adev, mc);
amdgpu_gmc_vram_location(adev, &adev->gmc, base);
- amdgpu_gmc_gart_location(adev, mc);
- amdgpu_gmc_agp_location(adev, mc);
+ amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_HIGH);
+ if (!amdgpu_sriov_vf(adev) &&
+ (amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(11, 5, 0)) &&
+ (amdgpu_agp == 1))
+ amdgpu_gmc_agp_location(adev, mc);
/* base offset of vram pages */
if (amdgpu_sriov_vf(adev))
@@ -766,6 +728,8 @@ static int gmc_v11_0_sw_init(void *handle)
adev->mmhub.funcs->init(adev);
+ adev->gfxhub.funcs->init(adev);
+
spin_lock_init(&adev->gmc.invalidate_lock);
r = amdgpu_atomfirmware_get_vram_info(adev,
@@ -775,12 +739,13 @@ static int gmc_v11_0_sw_init(void *handle)
adev->gmc.vram_type = vram_type;
adev->gmc.vram_vendor = vram_vendor;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
/*
@@ -935,8 +900,10 @@ static int gmc_v11_0_gart_enable(struct amdgpu_device *adev)
static int gmc_v11_0_hw_init(void *handle)
{
- int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ adev->gmc.flush_pasid_uses_kiq = !amdgpu_emu_mode;
/* The sequence of these two function calls matters.*/
gmc_v11_0_init_golden_registers(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
index 5b837a65fad2..42e103d7077d 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
@@ -211,8 +211,9 @@ static void gmc_v6_0_vram_gtt_location(struct amdgpu_device *adev,
base <<= 24;
+ amdgpu_gmc_set_agp_default(adev, mc);
amdgpu_gmc_vram_location(adev, mc, base);
- amdgpu_gmc_gart_location(adev, mc);
+ amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_BEST_FIT);
}
static void gmc_v6_0_mc_program(struct amdgpu_device *adev)
@@ -253,8 +254,8 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev)
WREG32(mmMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR,
adev->mem_scratch.gpu_addr >> 12);
WREG32(mmMC_VM_AGP_BASE, 0);
- WREG32(mmMC_VM_AGP_TOP, 0x0FFFFFFF);
- WREG32(mmMC_VM_AGP_BOT, 0x0FFFFFFF);
+ WREG32(mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 22);
+ WREG32(mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 22);
if (gmc_v6_0_wait_for_idle((void *)adev))
dev_warn(adev->dev, "Wait for MC idle timedout !\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index 6a6929ac2748..efc16e580f1e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -239,8 +239,9 @@ static void gmc_v7_0_vram_gtt_location(struct amdgpu_device *adev,
base <<= 24;
+ amdgpu_gmc_set_agp_default(adev, mc);
amdgpu_gmc_vram_location(adev, mc, base);
- amdgpu_gmc_gart_location(adev, mc);
+ amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_BEST_FIT);
}
/**
@@ -288,8 +289,8 @@ static void gmc_v7_0_mc_program(struct amdgpu_device *adev)
WREG32(mmMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR,
adev->mem_scratch.gpu_addr >> 12);
WREG32(mmMC_VM_AGP_BASE, 0);
- WREG32(mmMC_VM_AGP_TOP, 0x0FFFFFFF);
- WREG32(mmMC_VM_AGP_BOT, 0x0FFFFFFF);
+ WREG32(mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 22);
+ WREG32(mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 22);
if (gmc_v7_0_wait_for_idle((void *)adev))
dev_warn(adev->dev, "Wait for MC idle timedout !\n");
@@ -422,28 +423,23 @@ static int gmc_v7_0_mc_init(struct amdgpu_device *adev)
*
* Flush the TLB for the requested pasid.
*/
-static int gmc_v7_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
- uint16_t pasid, uint32_t flush_type,
- bool all_hub, uint32_t inst)
+static void gmc_v7_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
+ uint16_t pasid, uint32_t flush_type,
+ bool all_hub, uint32_t inst)
{
+ u32 mask = 0x0;
int vmid;
- unsigned int tmp;
-
- if (amdgpu_in_reset(adev))
- return -EIO;
for (vmid = 1; vmid < 16; vmid++) {
+ u32 tmp = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
- tmp = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
if ((tmp & ATC_VMID0_PASID_MAPPING__VALID_MASK) &&
- (tmp & ATC_VMID0_PASID_MAPPING__PASID_MASK) == pasid) {
- WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid);
- RREG32(mmVM_INVALIDATE_RESPONSE);
- break;
- }
+ (tmp & ATC_VMID0_PASID_MAPPING__PASID_MASK) == pasid)
+ mask |= 1 << vmid;
}
- return 0;
+ WREG32(mmVM_INVALIDATE_REQUEST, mask);
+ RREG32(mmVM_INVALIDATE_RESPONSE);
}
/*
@@ -1273,6 +1269,9 @@ static int gmc_v7_0_process_interrupt(struct amdgpu_device *adev,
if (!addr && !status)
return 0;
+ amdgpu_vm_update_fault_cache(adev, entry->pasid,
+ ((u64)addr) << AMDGPU_GPU_PAGE_SHIFT, status, AMDGPU_GFXHUB(0));
+
if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_FIRST)
gmc_v7_0_set_fault_enable_default(adev, false);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index 5af235202513..ff4ae73d27ec 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -413,8 +413,9 @@ static void gmc_v8_0_vram_gtt_location(struct amdgpu_device *adev,
base = RREG32(mmMC_VM_FB_LOCATION) & 0xFFFF;
base <<= 24;
+ amdgpu_gmc_set_agp_default(adev, mc);
amdgpu_gmc_vram_location(adev, mc, base);
- amdgpu_gmc_gart_location(adev, mc);
+ amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_BEST_FIT);
}
/**
@@ -473,8 +474,8 @@ static void gmc_v8_0_mc_program(struct amdgpu_device *adev)
}
WREG32(mmMC_VM_AGP_BASE, 0);
- WREG32(mmMC_VM_AGP_TOP, 0x0FFFFFFF);
- WREG32(mmMC_VM_AGP_BOT, 0x0FFFFFFF);
+ WREG32(mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 22);
+ WREG32(mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 22);
if (gmc_v8_0_wait_for_idle((void *)adev))
dev_warn(adev->dev, "Wait for MC idle timedout !\n");
@@ -612,29 +613,23 @@ static int gmc_v8_0_mc_init(struct amdgpu_device *adev)
*
* Flush the TLB for the requested pasid.
*/
-static int gmc_v8_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
- uint16_t pasid, uint32_t flush_type,
- bool all_hub, uint32_t inst)
+static void gmc_v8_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
+ uint16_t pasid, uint32_t flush_type,
+ bool all_hub, uint32_t inst)
{
+ u32 mask = 0x0;
int vmid;
- unsigned int tmp;
-
- if (amdgpu_in_reset(adev))
- return -EIO;
for (vmid = 1; vmid < 16; vmid++) {
+ u32 tmp = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
- tmp = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
if ((tmp & ATC_VMID0_PASID_MAPPING__VALID_MASK) &&
- (tmp & ATC_VMID0_PASID_MAPPING__PASID_MASK) == pasid) {
- WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid);
- RREG32(mmVM_INVALIDATE_RESPONSE);
- break;
- }
+ (tmp & ATC_VMID0_PASID_MAPPING__PASID_MASK) == pasid)
+ mask |= 1 << vmid;
}
- return 0;
-
+ WREG32(mmVM_INVALIDATE_REQUEST, mask);
+ RREG32(mmVM_INVALIDATE_RESPONSE);
}
/*
@@ -1442,6 +1437,9 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev,
if (!addr && !status)
return 0;
+ amdgpu_vm_update_fault_cache(adev, entry->pasid,
+ ((u64)addr) << AMDGPU_GPU_PAGE_SHIFT, status, AMDGPU_GFXHUB(0));
+
if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_FIRST)
gmc_v8_0_set_fault_enable_default(adev, false);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index f9a5a2c0573e..2ac5820e9c92 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -56,6 +56,7 @@
#include "umc_v6_1.h"
#include "umc_v6_0.h"
#include "umc_v6_7.h"
+#include "umc_v12_0.h"
#include "hdp_v4_0.h"
#include "mca_v3_0.h"
@@ -64,8 +65,6 @@
#include "amdgpu_ras.h"
#include "amdgpu_xgmi.h"
-#include "amdgpu_reset.h"
-
/* add these here since we already include dce12 headers and these are for DCN */
#define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION 0x055d
#define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_BASE_IDX 2
@@ -554,6 +553,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
struct amdgpu_vmhub *hub;
const char *mmhub_cid;
const char *hub_name;
+ unsigned int vmhub;
u64 addr;
uint32_t cam_index = 0;
int ret, xcc_id = 0;
@@ -566,10 +566,10 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
if (entry->client_id == SOC15_IH_CLIENTID_VMC) {
hub_name = "mmhub0";
- hub = &adev->vmhub[AMDGPU_MMHUB0(node_id / 4)];
+ vmhub = AMDGPU_MMHUB0(node_id / 4);
} else if (entry->client_id == SOC15_IH_CLIENTID_VMC1) {
hub_name = "mmhub1";
- hub = &adev->vmhub[AMDGPU_MMHUB1(0)];
+ vmhub = AMDGPU_MMHUB1(0);
} else {
hub_name = "gfxhub0";
if (adev->gfx.funcs->ih_node_to_logical_xcc) {
@@ -578,8 +578,9 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
if (xcc_id < 0)
xcc_id = 0;
}
- hub = &adev->vmhub[xcc_id];
+ vmhub = xcc_id;
}
+ hub = &adev->vmhub[vmhub];
if (retry_fault) {
if (adev->irq.retry_cam_enabled) {
@@ -625,7 +626,6 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
if (!printk_ratelimit())
return 0;
-
memset(&task_info, 0, sizeof(struct amdgpu_task_info));
amdgpu_vm_get_task_info(adev, entry->pasid, &task_info);
@@ -639,7 +639,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
addr, entry->client_id,
soc15_ih_clientid_name[entry->client_id]);
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3))
dev_err(adev->dev, " cookie node_id %d fault from die %s%d%s\n",
node_id, node_id % 4 == 3 ? "RSV" : "AID", node_id / 4,
node_id % 4 == 1 ? ".XCD0" : node_id % 4 == 2 ? ".XCD1" : "");
@@ -653,7 +653,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
* the new fast GRBM interface.
*/
if ((entry->vmid_src == AMDGPU_GFXHUB(0)) &&
- (adev->ip_versions[GC_HWIP][0] < IP_VERSION(9, 4, 2)))
+ (amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(9, 4, 2)))
RREG32(hub->vm_l2_pro_fault_status);
status = RREG32(hub->vm_l2_pro_fault_status);
@@ -661,6 +661,8 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
rw = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, RW);
WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
+ amdgpu_vm_update_fault_cache(adev, entry->pasid, addr, status, vmhub);
+
dev_err(adev->dev,
"VM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
@@ -670,7 +672,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
gfxhub_client_ids[cid],
cid);
} else {
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(9, 0, 0):
mmhub_cid = mmhub_client_ids_vega10[cid][rw];
break;
@@ -735,7 +737,8 @@ static void gmc_v9_0_set_irq_funcs(struct amdgpu_device *adev)
adev->gmc.vm_fault.funcs = &gmc_v9_0_irq_funcs;
if (!amdgpu_sriov_vf(adev) &&
- !adev->gmc.xgmi.connected_to_cpu) {
+ !adev->gmc.xgmi.connected_to_cpu &&
+ !adev->gmc.is_app_apu) {
adev->gmc.ecc_irq.num_types = 1;
adev->gmc.ecc_irq.funcs = &gmc_v9_0_ecc_funcs;
}
@@ -770,8 +773,8 @@ static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid,
static bool gmc_v9_0_use_invalidate_semaphore(struct amdgpu_device *adev,
uint32_t vmhub)
{
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3))
return false;
return ((vmhub == AMDGPU_MMHUB0(0) ||
@@ -814,45 +817,32 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
uint32_t vmhub, uint32_t flush_type)
{
bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(adev, vmhub);
+ u32 j, inv_req, tmp, sem, req, ack, inst;
const unsigned int eng = 17;
- u32 j, inv_req, inv_req2, tmp;
struct amdgpu_vmhub *hub;
BUG_ON(vmhub >= AMDGPU_MAX_VMHUBS);
hub = &adev->vmhub[vmhub];
- if (adev->gmc.xgmi.num_physical_nodes &&
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 0)) {
- /* Vega20+XGMI caches PTEs in TC and TLB. Add a
- * heavy-weight TLB flush (type 2), which flushes
- * both. Due to a race condition with concurrent
- * memory accesses using the same TLB cache line, we
- * still need a second TLB flush after this.
- */
- inv_req = gmc_v9_0_get_invalidate_req(vmid, 2);
- inv_req2 = gmc_v9_0_get_invalidate_req(vmid, flush_type);
- } else if (flush_type == 2 &&
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3) &&
- adev->rev_id == 0) {
- inv_req = gmc_v9_0_get_invalidate_req(vmid, 0);
- inv_req2 = gmc_v9_0_get_invalidate_req(vmid, flush_type);
- } else {
- inv_req = gmc_v9_0_get_invalidate_req(vmid, flush_type);
- inv_req2 = 0;
- }
+ inv_req = gmc_v9_0_get_invalidate_req(vmid, flush_type);
+ sem = hub->vm_inv_eng0_sem + hub->eng_distance * eng;
+ req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
+ ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
/* This is necessary for a HW workaround under SRIOV as well
* as GFXOFF under bare metal
*/
- if (adev->gfx.kiq[0].ring.sched.ready &&
- (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) &&
- down_read_trylock(&adev->reset_domain->sem)) {
+ if (vmhub >= AMDGPU_MMHUB0(0))
+ inst = GET_INST(GC, 0);
+ else
+ inst = vmhub;
+ if (adev->gfx.kiq[inst].ring.sched.ready &&
+ (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
- 1 << vmid);
- up_read(&adev->reset_domain->sem);
+ 1 << vmid, inst);
return;
}
@@ -870,9 +860,9 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
for (j = 0; j < adev->usec_timeout; j++) {
/* a read return value of 1 means semaphore acquire */
if (vmhub >= AMDGPU_MMHUB0(0))
- tmp = RREG32_SOC15_IP_NO_KIQ(MMHUB, hub->vm_inv_eng0_sem + hub->eng_distance * eng);
+ tmp = RREG32_SOC15_IP_NO_KIQ(MMHUB, sem, inst);
else
- tmp = RREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_sem + hub->eng_distance * eng);
+ tmp = RREG32_SOC15_IP_NO_KIQ(GC, sem, inst);
if (tmp & 0x1)
break;
udelay(1);
@@ -882,35 +872,29 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
}
- do {
- if (vmhub >= AMDGPU_MMHUB0(0))
- WREG32_SOC15_IP_NO_KIQ(MMHUB, hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req);
- else
- WREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req);
-
- /*
- * Issue a dummy read to wait for the ACK register to
- * be cleared to avoid a false ACK due to the new fast
- * GRBM interface.
- */
- if ((vmhub == AMDGPU_GFXHUB(0)) &&
- (adev->ip_versions[GC_HWIP][0] < IP_VERSION(9, 4, 2)))
- RREG32_NO_KIQ(hub->vm_inv_eng0_req +
- hub->eng_distance * eng);
+ if (vmhub >= AMDGPU_MMHUB0(0))
+ WREG32_SOC15_IP_NO_KIQ(MMHUB, req, inv_req, inst);
+ else
+ WREG32_SOC15_IP_NO_KIQ(GC, req, inv_req, inst);
- for (j = 0; j < adev->usec_timeout; j++) {
- if (vmhub >= AMDGPU_MMHUB0(0))
- tmp = RREG32_SOC15_IP_NO_KIQ(MMHUB, hub->vm_inv_eng0_ack + hub->eng_distance * eng);
- else
- tmp = RREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_ack + hub->eng_distance * eng);
- if (tmp & (1 << vmid))
- break;
- udelay(1);
- }
+ /*
+ * Issue a dummy read to wait for the ACK register to
+ * be cleared to avoid a false ACK due to the new fast
+ * GRBM interface.
+ */
+ if ((vmhub == AMDGPU_GFXHUB(0)) &&
+ (adev->ip_versions[GC_HWIP][0] < IP_VERSION(9, 4, 2)))
+ RREG32_NO_KIQ(req);
- inv_req = inv_req2;
- inv_req2 = 0;
- } while (inv_req);
+ for (j = 0; j < adev->usec_timeout; j++) {
+ if (vmhub >= AMDGPU_MMHUB0(0))
+ tmp = RREG32_SOC15_IP_NO_KIQ(MMHUB, ack, inst);
+ else
+ tmp = RREG32_SOC15_IP_NO_KIQ(GC, ack, inst);
+ if (tmp & (1 << vmid))
+ break;
+ udelay(1);
+ }
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
if (use_semaphore) {
@@ -919,9 +903,9 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
* write with 0 means semaphore release
*/
if (vmhub >= AMDGPU_MMHUB0(0))
- WREG32_SOC15_IP_NO_KIQ(MMHUB, hub->vm_inv_eng0_sem + hub->eng_distance * eng, 0);
+ WREG32_SOC15_IP_NO_KIQ(MMHUB, sem, 0, inst);
else
- WREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_sem + hub->eng_distance * eng, 0);
+ WREG32_SOC15_IP_NO_KIQ(GC, sem, 0, inst);
}
spin_unlock(&adev->gmc.invalidate_lock);
@@ -943,91 +927,32 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
*
* Flush the TLB for the requested pasid.
*/
-static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
- uint16_t pasid, uint32_t flush_type,
- bool all_hub, uint32_t inst)
+static void gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
+ uint16_t pasid, uint32_t flush_type,
+ bool all_hub, uint32_t inst)
{
- int vmid, i;
- signed long r;
- uint32_t seq;
- uint16_t queried_pasid;
- bool ret;
- u32 usec_timeout = amdgpu_sriov_vf(adev) ? SRIOV_USEC_TIMEOUT : adev->usec_timeout;
- struct amdgpu_ring *ring = &adev->gfx.kiq[inst].ring;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq[inst];
-
- if (amdgpu_in_reset(adev))
- return -EIO;
-
- if (ring->sched.ready && down_read_trylock(&adev->reset_domain->sem)) {
- /* Vega20+XGMI caches PTEs in TC and TLB. Add a
- * heavy-weight TLB flush (type 2), which flushes
- * both. Due to a race condition with concurrent
- * memory accesses using the same TLB cache line, we
- * still need a second TLB flush after this.
- */
- bool vega20_xgmi_wa = (adev->gmc.xgmi.num_physical_nodes &&
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 0));
- /* 2 dwords flush + 8 dwords fence */
- unsigned int ndw = kiq->pmf->invalidate_tlbs_size + 8;
-
- if (vega20_xgmi_wa)
- ndw += kiq->pmf->invalidate_tlbs_size;
-
- spin_lock(&adev->gfx.kiq[inst].ring_lock);
- /* 2 dwords flush + 8 dwords fence */
- amdgpu_ring_alloc(ring, ndw);
- if (vega20_xgmi_wa)
- kiq->pmf->kiq_invalidate_tlbs(ring,
- pasid, 2, all_hub);
-
- if (flush_type == 2 &&
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3) &&
- adev->rev_id == 0)
- kiq->pmf->kiq_invalidate_tlbs(ring,
- pasid, 0, all_hub);
-
- kiq->pmf->kiq_invalidate_tlbs(ring,
- pasid, flush_type, all_hub);
- r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
- if (r) {
- amdgpu_ring_undo(ring);
- spin_unlock(&adev->gfx.kiq[inst].ring_lock);
- up_read(&adev->reset_domain->sem);
- return -ETIME;
- }
-
- amdgpu_ring_commit(ring);
- spin_unlock(&adev->gfx.kiq[inst].ring_lock);
- r = amdgpu_fence_wait_polling(ring, seq, usec_timeout);
- if (r < 1) {
- dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
- up_read(&adev->reset_domain->sem);
- return -ETIME;
- }
- up_read(&adev->reset_domain->sem);
- return 0;
- }
+ uint16_t queried;
+ int i, vmid;
for (vmid = 1; vmid < 16; vmid++) {
+ bool valid;
- ret = gmc_v9_0_get_atc_vmid_pasid_mapping_info(adev, vmid,
- &queried_pasid);
- if (ret && queried_pasid == pasid) {
- if (all_hub) {
- for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
- gmc_v9_0_flush_gpu_tlb(adev, vmid,
- i, flush_type);
- } else {
- gmc_v9_0_flush_gpu_tlb(adev, vmid,
- AMDGPU_GFXHUB(0), flush_type);
- }
- break;
+ valid = gmc_v9_0_get_atc_vmid_pasid_mapping_info(adev, vmid,
+ &queried);
+ if (!valid || queried != pasid)
+ continue;
+
+ if (all_hub) {
+ for_each_set_bit(i, adev->vmhubs_mask,
+ AMDGPU_MAX_VMHUBS)
+ gmc_v9_0_flush_gpu_tlb(adev, vmid, i,
+ flush_type);
+ } else {
+ gmc_v9_0_flush_gpu_tlb(adev, vmid,
+ AMDGPU_GFXHUB(0),
+ flush_type);
}
}
-
- return 0;
-
}
static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
@@ -1183,14 +1108,15 @@ static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
{
struct amdgpu_device *bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
bool is_vram = bo->tbo.resource->mem_type == TTM_PL_VRAM;
- bool coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT;
+ bool coherent = bo->flags & (AMDGPU_GEM_CREATE_COHERENT | AMDGPU_GEM_CREATE_EXT_COHERENT);
+ bool ext_coherent = bo->flags & AMDGPU_GEM_CREATE_EXT_COHERENT;
bool uncached = bo->flags & AMDGPU_GEM_CREATE_UNCACHED;
struct amdgpu_vm *vm = mapping->bo_va->base.vm;
unsigned int mtype_local, mtype;
bool snoop = false;
bool is_local;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 4, 1):
case IP_VERSION(9, 4, 2):
if (is_vram) {
@@ -1204,8 +1130,10 @@ static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
/* FIXME: is this still needed? Or does
* amdgpu_ttm_tt_pde_flags already handle this?
*/
- if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) &&
+ if ((amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(9, 4, 2) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) ==
+ IP_VERSION(9, 4, 3)) &&
adev->gmc.xgmi.connected_to_cpu)
snoop = true;
} else {
@@ -1251,6 +1179,11 @@ static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
snoop = true;
if (uncached) {
mtype = MTYPE_UC;
+ } else if (ext_coherent) {
+ if (adev->rev_id)
+ mtype = is_local ? MTYPE_CC : MTYPE_UC;
+ else
+ mtype = MTYPE_UC;
} else if (adev->flags & AMD_IS_APU) {
mtype = is_local ? mtype_local : MTYPE_NC;
} else {
@@ -1314,23 +1247,26 @@ static void gmc_v9_0_override_vm_pte_flags(struct amdgpu_device *adev,
/* Only GFX 9.4.3 APUs associate GPUs with NUMA nodes. Local system
* memory can use more efficient MTYPEs.
*/
- if (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 3))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 3))
return;
/* Only direct-mapped memory allows us to determine the NUMA node from
* the DMA address.
*/
if (!adev->ram_is_direct_mapped) {
- dev_dbg(adev->dev, "RAM is not direct mapped\n");
+ dev_dbg_ratelimited(adev->dev, "RAM is not direct mapped\n");
return;
}
- /* Only override mappings with MTYPE_NC, which is the safe default for
- * cacheable memory.
+ /* MTYPE_NC is the same default and can be overridden.
+ * MTYPE_UC will be present if the memory is extended-coherent
+ * and can also be overridden.
*/
if ((*flags & AMDGPU_PTE_MTYPE_VG10_MASK) !=
- AMDGPU_PTE_MTYPE_VG10(MTYPE_NC)) {
- dev_dbg(adev->dev, "MTYPE is not NC\n");
+ AMDGPU_PTE_MTYPE_VG10(MTYPE_NC) &&
+ (*flags & AMDGPU_PTE_MTYPE_VG10_MASK) !=
+ AMDGPU_PTE_MTYPE_VG10(MTYPE_UC)) {
+ dev_dbg_ratelimited(adev->dev, "MTYPE is not NC or UC\n");
return;
}
@@ -1341,7 +1277,7 @@ static void gmc_v9_0_override_vm_pte_flags(struct amdgpu_device *adev,
if (adev->gmc.is_app_apu && vm->mem_id >= 0) {
local_node = adev->gmc.mem_partitions[vm->mem_id].numa.node;
} else {
- dev_dbg(adev->dev, "Only native mode APU is supported.\n");
+ dev_dbg_ratelimited(adev->dev, "Only native mode APU is supported.\n");
return;
}
@@ -1349,25 +1285,33 @@ static void gmc_v9_0_override_vm_pte_flags(struct amdgpu_device *adev,
* page or NUMA nodes.
*/
if (!page_is_ram(addr >> PAGE_SHIFT)) {
- dev_dbg(adev->dev, "Page is not RAM.\n");
+ dev_dbg_ratelimited(adev->dev, "Page is not RAM.\n");
return;
}
nid = pfn_to_nid(addr >> PAGE_SHIFT);
- dev_dbg(adev->dev, "vm->mem_id=%d, local_node=%d, nid=%d\n",
- vm->mem_id, local_node, nid);
+ dev_dbg_ratelimited(adev->dev, "vm->mem_id=%d, local_node=%d, nid=%d\n",
+ vm->mem_id, local_node, nid);
if (nid == local_node) {
uint64_t old_flags = *flags;
- unsigned int mtype_local = MTYPE_RW;
-
- if (amdgpu_mtype_local == 1)
- mtype_local = MTYPE_NC;
- else if (amdgpu_mtype_local == 2)
- mtype_local = MTYPE_CC;
+ if ((*flags & AMDGPU_PTE_MTYPE_VG10_MASK) ==
+ AMDGPU_PTE_MTYPE_VG10(MTYPE_NC)) {
+ unsigned int mtype_local = MTYPE_RW;
+
+ if (amdgpu_mtype_local == 1)
+ mtype_local = MTYPE_NC;
+ else if (amdgpu_mtype_local == 2)
+ mtype_local = MTYPE_CC;
+
+ *flags = (*flags & ~AMDGPU_PTE_MTYPE_VG10_MASK) |
+ AMDGPU_PTE_MTYPE_VG10(mtype_local);
+ } else if (adev->rev_id) {
+ /* MTYPE_UC case */
+ *flags = (*flags & ~AMDGPU_PTE_MTYPE_VG10_MASK) |
+ AMDGPU_PTE_MTYPE_VG10(MTYPE_CC);
+ }
- *flags = (*flags & ~AMDGPU_PTE_MTYPE_VG10_MASK) |
- AMDGPU_PTE_MTYPE_VG10(mtype_local);
- dev_dbg(adev->dev, "flags updated from %llx to %llx\n",
- old_flags, *flags);
+ dev_dbg_ratelimited(adev->dev, "flags updated from %llx to %llx\n",
+ old_flags, *flags);
}
}
@@ -1383,7 +1327,7 @@ static unsigned int gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev)
} else {
u32 viewport;
- switch (adev->ip_versions[DCE_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION);
@@ -1454,7 +1398,7 @@ static void gmc_v9_0_set_gmc_funcs(struct amdgpu_device *adev)
static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[UMC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, UMC_HWIP, 0)) {
case IP_VERSION(6, 0, 0):
adev->umc.funcs = &umc_v6_0_funcs;
break;
@@ -1490,6 +1434,19 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
else
adev->umc.channel_idx_tbl = &umc_v6_7_channel_idx_tbl_second[0][0];
break;
+ case IP_VERSION(12, 0, 0):
+ adev->umc.max_ras_err_cnt_per_query =
+ UMC_V12_0_TOTAL_CHANNEL_NUM(adev) * UMC_V12_0_BAD_PAGE_NUM_PER_CHANNEL;
+ adev->umc.channel_inst_num = UMC_V12_0_CHANNEL_INSTANCE_NUM;
+ adev->umc.umc_inst_num = UMC_V12_0_UMC_INSTANCE_NUM;
+ adev->umc.node_inst_num /= UMC_V12_0_UMC_INSTANCE_NUM;
+ adev->umc.channel_offs = UMC_V12_0_PER_CHANNEL_OFFSET;
+ adev->umc.active_mask = adev->aid_mask;
+ adev->umc.retire_unit = UMC_V12_0_BAD_PAGE_NUM_PER_CHANNEL;
+ adev->umc.channel_idx_tbl = &umc_v12_0_channel_idx_tbl[0][0][0];
+ if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu)
+ adev->umc.ras = &umc_v12_0_ras;
+ break;
default:
break;
}
@@ -1497,7 +1454,7 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(9, 4, 1):
adev->mmhub.funcs = &mmhub_v9_4_funcs;
break;
@@ -1515,7 +1472,7 @@ static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev)
static void gmc_v9_0_set_mmhub_ras_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(9, 4, 0):
adev->mmhub.ras = &mmhub_v1_0_ras;
break;
@@ -1536,7 +1493,7 @@ static void gmc_v9_0_set_mmhub_ras_funcs(struct amdgpu_device *adev)
static void gmc_v9_0_set_gfxhub_funcs(struct amdgpu_device *adev)
{
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3))
adev->gfxhub.funcs = &gfxhub_v1_2_funcs;
else
adev->gfxhub.funcs = &gfxhub_v1_0_funcs;
@@ -1552,7 +1509,7 @@ static void gmc_v9_0_set_mca_ras_funcs(struct amdgpu_device *adev)
struct amdgpu_mca *mca = &adev->mca;
/* is UMC the right IP to check for MCA? Maybe DF? */
- switch (adev->ip_versions[UMC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, UMC_HWIP, 0)) {
case IP_VERSION(6, 7, 0):
if (!adev->gmc.xgmi.connected_to_cpu) {
mca->mp0.ras = &mca_v3_0_mp0_ras;
@@ -1579,18 +1536,18 @@ static int gmc_v9_0_early_init(void *handle)
* 9.4.0, 9.4.1 and 9.4.3 don't have XGMI defined
* in their IP discovery tables
*/
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 0) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 0) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 1) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3))
adev->gmc.xgmi.supported = true;
- if (adev->ip_versions[XGMI_HWIP][0] == IP_VERSION(6, 1, 0)) {
+ if (amdgpu_ip_version(adev, XGMI_HWIP, 0) == IP_VERSION(6, 1, 0)) {
adev->gmc.xgmi.supported = true;
adev->gmc.xgmi.connected_to_cpu =
adev->smuio.funcs->is_host_gpu_xgmi_supported(adev);
}
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3)) {
enum amdgpu_pkg_type pkg_type =
adev->smuio.funcs->get_pkg_type(adev);
/* On GFXIP 9.4.3. APU, there is no physical VRAM domain present
@@ -1639,7 +1596,7 @@ static int gmc_v9_0_late_init(void *handle)
* writes, while disables HBM ECC for vega10.
*/
if (!amdgpu_sriov_vf(adev) &&
- (adev->ip_versions[UMC_HWIP][0] == IP_VERSION(6, 0, 0))) {
+ (amdgpu_ip_version(adev, UMC_HWIP, 0) == IP_VERSION(6, 0, 0))) {
if (!(adev->ras_enabled & (1 << AMDGPU_RAS_BLOCK__UMC))) {
if (adev->df.funcs &&
adev->df.funcs->enable_ecc_force_par_wr_rmw)
@@ -1648,13 +1605,8 @@ static int gmc_v9_0_late_init(void *handle)
}
if (!amdgpu_persistent_edc_harvesting_supported(adev)) {
- if (adev->mmhub.ras && adev->mmhub.ras->ras_block.hw_ops &&
- adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count)
- adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count(adev);
-
- if (adev->hdp.ras && adev->hdp.ras->ras_block.hw_ops &&
- adev->hdp.ras->ras_block.hw_ops->reset_ras_error_count)
- adev->hdp.ras->ras_block.hw_ops->reset_ras_error_count(adev);
+ amdgpu_ras_reset_error_count(adev, AMDGPU_RAS_BLOCK__MMHUB);
+ amdgpu_ras_reset_error_count(adev, AMDGPU_RAS_BLOCK__HDP);
}
r = amdgpu_gmc_ras_late_init(adev);
@@ -1669,14 +1621,17 @@ static void gmc_v9_0_vram_gtt_location(struct amdgpu_device *adev,
{
u64 base = adev->mmhub.funcs->get_fb_location(adev);
+ amdgpu_gmc_set_agp_default(adev, mc);
+
/* add the xgmi offset of the physical node */
base += adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size;
if (adev->gmc.xgmi.connected_to_cpu) {
amdgpu_gmc_sysvm_location(adev, mc);
} else {
amdgpu_gmc_vram_location(adev, mc, base);
- amdgpu_gmc_gart_location(adev, mc);
- amdgpu_gmc_agp_location(adev, mc);
+ amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_BEST_FIT);
+ if (!amdgpu_sriov_vf(adev) && (amdgpu_agp == 1))
+ amdgpu_gmc_agp_location(adev, mc);
}
/* base offset of vram pages */
adev->vm_manager.vram_base_offset = adev->gfxhub.funcs->get_mc_fb_offset(adev);
@@ -1747,7 +1702,7 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev)
/* set the gart size */
if (amdgpu_gart_size == -1) {
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1): /* all engines support GPUVM */
case IP_VERSION(9, 2, 1): /* all engines support GPUVM */
case IP_VERSION(9, 4, 0):
@@ -1826,8 +1781,8 @@ static int gmc_v9_0_gart_init(struct amdgpu_device *adev)
*/
static void gmc_v9_0_save_registers(struct amdgpu_device *adev)
{
- if ((adev->ip_versions[DCE_HWIP][0] == IP_VERSION(1, 0, 0)) ||
- (adev->ip_versions[DCE_HWIP][0] == IP_VERSION(1, 0, 1)))
+ if ((amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(1, 0, 0)) ||
+ (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(1, 0, 1)))
adev->gmc.sdpif_register = RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0);
}
@@ -1879,15 +1834,14 @@ static void
gmc_v9_0_init_acpi_mem_ranges(struct amdgpu_device *adev,
struct amdgpu_mem_partition_info *mem_ranges)
{
- int num_ranges = 0, ret, mem_groups;
struct amdgpu_numa_info numa_info;
int node_ids[MAX_MEM_RANGES];
+ int num_ranges = 0, ret;
int num_xcc, xcc_id;
uint32_t xcc_mask;
num_xcc = NUM_XCC(adev->gfx.xcc_mask);
xcc_mask = (1U << num_xcc) - 1;
- mem_groups = hweight32(adev->aid_mask);
for_each_inst(xcc_id, xcc_mask) {
ret = amdgpu_acpi_get_mem_info(adev, xcc_id, &numa_info);
@@ -1912,12 +1866,6 @@ gmc_v9_0_init_acpi_mem_ranges(struct amdgpu_device *adev,
}
adev->gmc.num_mem_partitions = num_ranges;
-
- /* If there is only partition, don't use entire size */
- if (adev->gmc.num_mem_partitions == 1) {
- mem_ranges[0].size = mem_ranges[0].size * (mem_groups - 1);
- do_div(mem_ranges[0].size, mem_groups);
- }
}
static void
@@ -1972,10 +1920,9 @@ static int gmc_v9_0_init_mem_ranges(struct amdgpu_device *adev)
{
bool valid;
- adev->gmc.mem_partitions = kzalloc(
- MAX_MEM_RANGES * sizeof(struct amdgpu_mem_partition_info),
- GFP_KERNEL);
-
+ adev->gmc.mem_partitions = kcalloc(MAX_MEM_RANGES,
+ sizeof(struct amdgpu_mem_partition_info),
+ GFP_KERNEL);
if (!adev->gmc.mem_partitions)
return -ENOMEM;
@@ -2023,7 +1970,7 @@ static int gmc_v9_0_sw_init(void *handle)
spin_lock_init(&adev->gmc.invalidate_lock);
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3)) {
gmc_v9_4_3_init_vram_info(adev);
} else if (!adev->bios) {
if (adev->flags & AMD_IS_APU) {
@@ -2063,7 +2010,7 @@ static int gmc_v9_0_sw_init(void *handle)
adev->gmc.vram_type = vram_type;
adev->gmc.vram_vendor = vram_vendor;
}
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 2):
set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
@@ -2091,12 +2038,9 @@ static int gmc_v9_0_sw_init(void *handle)
* vm size is 256TB (48bit), maximum size of Vega10,
* block size 512 (9bit)
*/
- /* sriov restrict max_pfn below AMDGPU_GMC_HOLE */
- if (amdgpu_sriov_vf(adev))
- amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 47);
- else
- amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2))
+
+ amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2))
adev->gmc.translate_further = adev->vm_manager.num_level > 1;
break;
case IP_VERSION(9, 4, 1):
@@ -2128,7 +2072,7 @@ static int gmc_v9_0_sw_init(void *handle)
if (r)
return r;
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 1)) {
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VMC1, VMC_1_0__SRCID__VM_FAULT,
&adev->gmc.vm_fault);
if (r)
@@ -2142,7 +2086,8 @@ static int gmc_v9_0_sw_init(void *handle)
return r;
if (!amdgpu_sriov_vf(adev) &&
- !adev->gmc.xgmi.connected_to_cpu) {
+ !adev->gmc.xgmi.connected_to_cpu &&
+ !adev->gmc.is_app_apu) {
/* interrupt sent to DF. */
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DF, 0,
&adev->gmc.ecc_irq);
@@ -2156,7 +2101,10 @@ static int gmc_v9_0_sw_init(void *handle)
*/
adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
- dma_addr_bits = adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 4, 2) ? 48:44;
+ dma_addr_bits = amdgpu_ip_version(adev, GC_HWIP, 0) >=
+ IP_VERSION(9, 4, 2) ?
+ 48 :
+ 44;
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(dma_addr_bits));
if (r) {
dev_warn(adev->dev, "amdgpu: No suitable DMA available.\n");
@@ -2170,7 +2118,7 @@ static int gmc_v9_0_sw_init(void *handle)
amdgpu_gmc_get_vbios_allocations(adev);
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) {
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3)) {
r = gmc_v9_0_init_mem_ranges(adev);
if (r)
return r;
@@ -2196,9 +2144,11 @@ static int gmc_v9_0_sw_init(void *handle)
* for video processing.
*/
adev->vm_manager.first_kfd_vmid =
- (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) ? 3 : 8;
+ (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 1) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3)) ?
+ 3 :
+ 8;
amdgpu_vm_manager_init(adev);
@@ -2208,7 +2158,7 @@ static int gmc_v9_0_sw_init(void *handle)
if (r)
return r;
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3))
amdgpu_gmc_sysfs_init(adev);
return 0;
@@ -2218,10 +2168,8 @@ static int gmc_v9_0_sw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3))
amdgpu_gmc_sysfs_fini(adev);
- adev->gmc.num_mem_partitions = 0;
- kfree(adev->gmc.mem_partitions);
amdgpu_gmc_ras_fini(adev);
amdgpu_gem_force_release(adev);
@@ -2235,13 +2183,15 @@ static int gmc_v9_0_sw_fini(void *handle)
amdgpu_bo_free_kernel(&adev->gmc.pdb0_bo, NULL, &adev->gmc.ptr_pdb0);
amdgpu_bo_fini(adev);
+ adev->gmc.num_mem_partitions = 0;
+ kfree(adev->gmc.mem_partitions);
+
return 0;
}
static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev)
{
-
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(9, 0, 0):
if (amdgpu_sriov_vf(adev))
break;
@@ -2275,8 +2225,8 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev)
*/
void gmc_v9_0_restore_registers(struct amdgpu_device *adev)
{
- if ((adev->ip_versions[DCE_HWIP][0] == IP_VERSION(1, 0, 0)) ||
- (adev->ip_versions[DCE_HWIP][0] == IP_VERSION(1, 0, 1))) {
+ if ((amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(1, 0, 0)) ||
+ (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(1, 0, 1))) {
WREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register);
WARN_ON(adev->gmc.sdpif_register !=
RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0));
@@ -2329,6 +2279,24 @@ static int gmc_v9_0_hw_init(void *handle)
bool value;
int i, r;
+ adev->gmc.flush_pasid_uses_kiq = true;
+
+ /* Vega20+XGMI caches PTEs in TC and TLB. Add a heavy-weight TLB flush
+ * (type 2), which flushes both. Due to a race condition with
+ * concurrent memory accesses using the same TLB cache line, we still
+ * need a second TLB flush after this.
+ */
+ adev->gmc.flush_tlb_needs_extra_type_2 =
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 0) &&
+ adev->gmc.xgmi.num_physical_nodes;
+ /*
+ * TODO: This workaround is badly documented and had a buggy
+ * implementation. We should probably verify what we do here.
+ */
+ adev->gmc.flush_tlb_needs_extra_type_0 =
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) &&
+ adev->rev_id == 0;
+
/* The sequence of these two function calls matters.*/
gmc_v9_0_init_golden_registers(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c
index 71d1a2e3bac9..4db6bb73ead4 100644
--- a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c
@@ -49,8 +49,8 @@ static void hdp_v4_0_flush_hdp(struct amdgpu_device *adev,
static void hdp_v4_0_invalidate_hdp(struct amdgpu_device *adev,
struct amdgpu_ring *ring)
{
- if (adev->ip_versions[HDP_HWIP][0] == IP_VERSION(4, 4, 0) ||
- adev->ip_versions[HDP_HWIP][0] == IP_VERSION(4, 4, 2))
+ if (amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(4, 4, 0) ||
+ amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(4, 4, 2))
return;
if (!ring || !ring->funcs->emit_wreg)
@@ -80,7 +80,7 @@ static void hdp_v4_0_reset_ras_error_count(struct amdgpu_device *adev)
if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__HDP))
return;
- if (adev->ip_versions[HDP_HWIP][0] >= IP_VERSION(4, 4, 0))
+ if (amdgpu_ip_version(adev, HDP_HWIP, 0) >= IP_VERSION(4, 4, 0))
WREG32_SOC15(HDP, 0, mmHDP_EDC_CNT, 0);
else
/*read back hdp ras counter to reset it to 0 */
@@ -92,10 +92,10 @@ static void hdp_v4_0_update_clock_gating(struct amdgpu_device *adev,
{
uint32_t def, data;
- if (adev->ip_versions[HDP_HWIP][0] == IP_VERSION(4, 0, 0) ||
- adev->ip_versions[HDP_HWIP][0] == IP_VERSION(4, 0, 1) ||
- adev->ip_versions[HDP_HWIP][0] == IP_VERSION(4, 1, 1) ||
- adev->ip_versions[HDP_HWIP][0] == IP_VERSION(4, 1, 0)) {
+ if (amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(4, 0, 0) ||
+ amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(4, 0, 1) ||
+ amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(4, 1, 1) ||
+ amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(4, 1, 0)) {
def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS));
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
@@ -129,6 +129,11 @@ static void hdp_v4_0_get_clockgating_state(struct amdgpu_device *adev,
{
int data;
+ if (amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(4, 4, 2)) {
+ /* Default enabled */
+ *flags |= AMD_CG_SUPPORT_HDP_MGCG;
+ return;
+ }
/* AMD_CG_SUPPORT_HDP_LS */
data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS));
if (data & HDP_MEM_POWER_LS__LS_ENABLE_MASK)
@@ -137,7 +142,7 @@ static void hdp_v4_0_get_clockgating_state(struct amdgpu_device *adev,
static void hdp_v4_0_init_registers(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[HDP_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, HDP_HWIP, 0)) {
case IP_VERSION(4, 2, 1):
WREG32_FIELD15(HDP, 0, HDP_MMHUB_CNTL, HDP_MMHUB_GCC, 1);
break;
@@ -145,9 +150,13 @@ static void hdp_v4_0_init_registers(struct amdgpu_device *adev)
break;
}
+ /* Do not program registers if VF */
+ if (amdgpu_sriov_vf(adev))
+ return;
+
WREG32_FIELD15(HDP, 0, HDP_MISC_CNTL, FLUSH_INVALIDATE_CACHE, 1);
- if (adev->ip_versions[HDP_HWIP][0] == IP_VERSION(4, 4, 0))
+ if (amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(4, 4, 0))
WREG32_FIELD15(HDP, 0, HDP_MISC_CNTL, READ_BUFFER_WATERMARK, 2);
WREG32_SOC15(HDP, 0, mmHDP_NONSURFACE_BASE, (adev->gmc.vram_start >> 8));
diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c
index 063eba619f2f..ab06c2b4b20b 100644
--- a/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c
@@ -28,6 +28,9 @@
#include "hdp/hdp_6_0_0_sh_mask.h"
#include <uapi/linux/kfd_ioctl.h>
+#define regHDP_CLK_CNTL_V6_1 0xd5
+#define regHDP_CLK_CNTL_V6_1_BASE_IDX 0
+
static void hdp_v6_0_flush_hdp(struct amdgpu_device *adev,
struct amdgpu_ring *ring)
{
@@ -40,7 +43,7 @@ static void hdp_v6_0_flush_hdp(struct amdgpu_device *adev,
static void hdp_v6_0_update_clock_gating(struct amdgpu_device *adev,
bool enable)
{
- uint32_t hdp_clk_cntl, hdp_clk_cntl1;
+ uint32_t hdp_clk_cntl;
uint32_t hdp_mem_pwr_cntl;
if (!(adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS |
@@ -48,14 +51,20 @@ static void hdp_v6_0_update_clock_gating(struct amdgpu_device *adev,
AMD_CG_SUPPORT_HDP_SD)))
return;
- hdp_clk_cntl = hdp_clk_cntl1 = RREG32_SOC15(HDP, 0,regHDP_CLK_CNTL);
+ if (amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(6, 1, 0))
+ hdp_clk_cntl = RREG32_SOC15(HDP, 0, regHDP_CLK_CNTL_V6_1);
+ else
+ hdp_clk_cntl = RREG32_SOC15(HDP, 0, regHDP_CLK_CNTL);
hdp_mem_pwr_cntl = RREG32_SOC15(HDP, 0, regHDP_MEM_POWER_CTRL);
/* Before doing clock/power mode switch,
* forced on IPH & RC clock */
hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
RC_MEM_CLK_SOFT_OVERRIDE, 1);
- WREG32_SOC15(HDP, 0, regHDP_CLK_CNTL, hdp_clk_cntl);
+ if (amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(6, 1, 0))
+ WREG32_SOC15(HDP, 0, regHDP_CLK_CNTL_V6_1, hdp_clk_cntl);
+ else
+ WREG32_SOC15(HDP, 0, regHDP_CLK_CNTL, hdp_clk_cntl);
/* disable clock and power gating before any changing */
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
@@ -117,7 +126,10 @@ static void hdp_v6_0_update_clock_gating(struct amdgpu_device *adev,
/* disable IPH & RC clock override after clock/power mode changing */
hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
RC_MEM_CLK_SOFT_OVERRIDE, 0);
- WREG32_SOC15(HDP, 0, regHDP_CLK_CNTL, hdp_clk_cntl);
+ if (amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(6, 1, 0))
+ WREG32_SOC15(HDP, 0, regHDP_CLK_CNTL_V6_1, hdp_clk_cntl);
+ else
+ WREG32_SOC15(HDP, 0, regHDP_CLK_CNTL, hdp_clk_cntl);
}
static void hdp_v6_0_get_clockgating_state(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c
index ec0c8f8b465a..d9ed7332d805 100644
--- a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c
@@ -641,8 +641,6 @@ static void ih_v6_0_update_clockgating_state(struct amdgpu_device *adev,
if (def != data)
WREG32_SOC15(OSSSYS, 0, regIH_CLK_CTRL, data);
}
-
- return;
}
static int ih_v6_0_set_clockgating_state(void *handle,
@@ -726,8 +724,6 @@ static void ih_v6_0_get_clockgating_state(void *handle, u64 *flags)
if (!RREG32_SOC15(OSSSYS, 0, regIH_CLK_CTRL))
*flags |= AMD_CG_SUPPORT_IH_CG;
-
- return;
}
static const struct amd_ip_funcs ih_v6_0_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c b/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c
index 4ab90c7852c3..c0bdab3bf0e4 100644
--- a/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c
@@ -36,10 +36,11 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_1_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_2_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_3_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_4_imu.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_0_imu.bin");
static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
{
- char fw_name[40];
+ char fw_name[45];
char ucode_prefix[30];
int err;
const struct imu_firmware_header_v1_0 *imu_hdr;
@@ -54,7 +55,6 @@ static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
if (err)
goto out;
imu_hdr = (const struct imu_firmware_header_v1_0 *)adev->gfx.imu_fw->data;
- adev->gfx.imu_fw_version = le32_to_cpu(imu_hdr->header.ucode_version);
//adev->gfx.imu_feature_version = le32_to_cpu(imu_hdr->ucode_feature_version);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
@@ -68,7 +68,8 @@ static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
info->fw = adev->gfx.imu_fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(imu_hdr->imu_dram_ucode_size_bytes), PAGE_SIZE);
- }
+ } else
+ adev->gfx.imu_fw_version = le32_to_cpu(imu_hdr->header.ucode_version);
out:
if (err) {
@@ -352,7 +353,7 @@ static void imu_v11_0_program_rlc_ram(struct amdgpu_device *adev)
WREG32_SOC15(GC, 0, regGFX_IMU_RLC_RAM_INDEX, 0x2);
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(11, 0, 0):
program_imu_rlc_ram(adev, imu_rlc_ram_golden_11,
(const u32)ARRAY_SIZE(imu_rlc_ram_golden_11));
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
index aadb74de52bc..e67a337457ed 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
@@ -128,7 +128,7 @@ static int jpeg_v2_5_sw_init(void *handle)
ring = adev->jpeg.inst[i].ring_dec;
ring->use_doorbell = true;
- if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(2, 5, 0))
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(2, 5, 0))
ring->vm_hub = AMDGPU_MMHUB1(0);
else
ring->vm_hub = AMDGPU_MMHUB0(0);
@@ -822,7 +822,7 @@ static struct amdgpu_jpeg_ras jpeg_v2_6_ras = {
static void jpeg_v2_5_set_ras_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[JPEG_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, JPEG_HWIP, 0)) {
case IP_VERSION(2, 6, 0):
adev->jpeg.ras = &jpeg_v2_6_ras;
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
index df4440c21bbf..a92481da60cd 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
@@ -52,7 +52,7 @@ static int jpeg_v3_0_early_init(void *handle)
u32 harvest;
- switch (adev->ip_versions[UVD_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, UVD_HWIP, 0)) {
case IP_VERSION(3, 1, 1):
case IP_VERSION(3, 1, 2):
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index 3eb3dcd56b57..bc38b90f8cf8 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -431,6 +431,10 @@ static int jpeg_v4_0_start_sriov(struct amdgpu_device *adev)
end.cmd_header.command_type =
MMSCH_COMMAND__END;
+ size = sizeof(struct mmsch_v4_0_init_header);
+ table_loc = (uint32_t *)table->cpu_addr;
+ memcpy(&header, (void *)table_loc, size);
+
header.version = MMSCH_VERSION;
header.total_size = RREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_SIZE);
@@ -468,6 +472,9 @@ static int jpeg_v4_0_start_sriov(struct amdgpu_device *adev)
table_loc = (uint32_t *)table->cpu_addr;
memcpy((void *)table_loc, &header, size);
+ /* Perform HDP flush before writing to MMSCH registers */
+ amdgpu_device_flush_hdp(adev, NULL);
+
/* message MMSCH (in VCN[0]) to initialize this client
* 1, write to mmsch_vf_ctx_addr_lo/hi register with GPU mc addr
* of memory descriptor location
@@ -515,8 +522,11 @@ static int jpeg_v4_0_start_sriov(struct amdgpu_device *adev)
return -EBUSY;
}
}
- if (resp != expected && resp != MMSCH_VF_MAILBOX_RESP__INCOMPLETE && init_status != MMSCH_VF_ENGINE_STATUS__PASS)
+ if (resp != expected && resp != MMSCH_VF_MAILBOX_RESP__INCOMPLETE
+ && init_status != MMSCH_VF_ENGINE_STATUS__PASS) {
DRM_ERROR("MMSCH init status is incorrect! readback=0x%08x, header init status for jpeg: %x\n", resp, init_status);
+ return -EINVAL;
+ }
return 0;
@@ -831,7 +841,7 @@ static struct amdgpu_jpeg_ras jpeg_v4_0_ras = {
static void jpeg_v4_0_set_ras_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[JPEG_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, JPEG_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
adev->jpeg.ras = &jpeg_v4_0_ras;
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
index 1de79d660285..82b6b62c170b 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
@@ -654,9 +654,11 @@ static void jpeg_v4_0_3_dec_ring_set_wptr(struct amdgpu_ring *ring)
*/
static void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring)
{
- amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
- 0, 0, PACKETJ_TYPE0));
- amdgpu_ring_write(ring, 0x62a04); /* PCTL0_MMHUB_DEEPSLEEP_IB */
+ if (!amdgpu_sriov_vf(ring->adev)) {
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x62a04); /* PCTL0_MMHUB_DEEPSLEEP_IB */
+ }
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
0, 0, PACKETJ_TYPE0));
@@ -672,9 +674,11 @@ static void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring)
*/
static void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring)
{
- amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
- 0, 0, PACKETJ_TYPE0));
- amdgpu_ring_write(ring, 0x62a04);
+ if (!amdgpu_sriov_vf(ring->adev)) {
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x62a04);
+ }
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
0, 0, PACKETJ_TYPE0));
@@ -950,6 +954,11 @@ static int jpeg_v4_0_3_set_powergating_state(void *handle,
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int ret;
+ if (amdgpu_sriov_vf(adev)) {
+ adev->jpeg.cur_state = AMD_PG_STATE_UNGATE;
+ return 0;
+ }
+
if (state == adev->jpeg.cur_state)
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
new file mode 100644
index 000000000000..6ede85b28cc8
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
@@ -0,0 +1,623 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "amdgpu.h"
+#include "amdgpu_jpeg.h"
+#include "amdgpu_pm.h"
+#include "soc15.h"
+#include "soc15d.h"
+#include "jpeg_v2_0.h"
+#include "jpeg_v4_0_5.h"
+#include "mmsch_v4_0.h"
+
+#include "vcn/vcn_4_0_5_offset.h"
+#include "vcn/vcn_4_0_5_sh_mask.h"
+#include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"
+
+#define regUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f
+
+static void jpeg_v4_0_5_set_dec_ring_funcs(struct amdgpu_device *adev);
+static void jpeg_v4_0_5_set_irq_funcs(struct amdgpu_device *adev);
+static int jpeg_v4_0_5_set_powergating_state(void *handle,
+ enum amd_powergating_state state);
+
+static void jpeg_v4_0_5_dec_ring_set_wptr(struct amdgpu_ring *ring);
+
+/**
+ * jpeg_v4_0_5_early_init - set function pointers
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Set ring and irq function pointers
+ */
+static int jpeg_v4_0_5_early_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+
+ adev->jpeg.num_jpeg_inst = 1;
+ adev->jpeg.num_jpeg_rings = 1;
+
+ jpeg_v4_0_5_set_dec_ring_funcs(adev);
+ jpeg_v4_0_5_set_irq_funcs(adev);
+
+ return 0;
+}
+
+/**
+ * jpeg_v4_0_5_sw_init - sw init for JPEG block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Load firmware and sw initialization
+ */
+static int jpeg_v4_0_5_sw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_ring *ring;
+ int r;
+
+ /* JPEG TRAP */
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
+ VCN_4_0__SRCID__JPEG_DECODE, &adev->jpeg.inst->irq);
+ if (r)
+ return r;
+
+ /* JPEG DJPEG POISON EVENT */
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
+ VCN_4_0__SRCID_DJPEG0_POISON, &adev->jpeg.inst->irq);
+ if (r)
+ return r;
+
+ /* JPEG EJPEG POISON EVENT */
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
+ VCN_4_0__SRCID_EJPEG0_POISON, &adev->jpeg.inst->irq);
+ if (r)
+ return r;
+
+ r = amdgpu_jpeg_sw_init(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_jpeg_resume(adev);
+ if (r)
+ return r;
+
+ ring = adev->jpeg.inst->ring_dec;
+ ring->use_doorbell = true;
+ ring->doorbell_index = amdgpu_sriov_vf(adev) ?
+ (((adev->doorbell_index.vcn.vcn_ring0_1) << 1) + 4) :
+ ((adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1);
+ ring->vm_hub = AMDGPU_MMHUB0(0);
+
+ sprintf(ring->name, "jpeg_dec");
+ r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0,
+ AMDGPU_RING_PRIO_DEFAULT, NULL);
+ if (r)
+ return r;
+
+ adev->jpeg.internal.jpeg_pitch[0] = regUVD_JPEG_PITCH_INTERNAL_OFFSET;
+ adev->jpeg.inst->external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_PITCH);
+
+ return 0;
+}
+
+/**
+ * jpeg_v4_0_5_sw_fini - sw fini for JPEG block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * JPEG suspend and free up sw allocation
+ */
+static int jpeg_v4_0_5_sw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = amdgpu_jpeg_suspend(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_jpeg_sw_fini(adev);
+
+ return r;
+}
+
+/**
+ * jpeg_v4_0_5_hw_init - start and test JPEG block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ */
+static int jpeg_v4_0_5_hw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
+ int r;
+
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+
+ DRM_DEV_INFO(adev->dev, "JPEG decode initialized successfully.\n");
+
+ return 0;
+}
+
+/**
+ * jpeg_v4_0_5_hw_fini - stop the hardware block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Stop the JPEG block, mark ring as not ready any more
+ */
+static int jpeg_v4_0_5_hw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ cancel_delayed_work_sync(&adev->vcn.idle_work);
+ if (!amdgpu_sriov_vf(adev)) {
+ if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
+ RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))
+ jpeg_v4_0_5_set_powergating_state(adev, AMD_PG_STATE_GATE);
+ }
+ amdgpu_irq_put(adev, &adev->jpeg.inst->irq, 0);
+
+ return 0;
+}
+
+/**
+ * jpeg_v4_0_5_suspend - suspend JPEG block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * HW fini and suspend JPEG block
+ */
+static int jpeg_v4_0_5_suspend(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = jpeg_v4_0_5_hw_fini(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_jpeg_suspend(adev);
+
+ return r;
+}
+
+/**
+ * jpeg_v4_0_5_resume - resume JPEG block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Resume firmware and hw init JPEG block
+ */
+static int jpeg_v4_0_5_resume(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = amdgpu_jpeg_resume(adev);
+ if (r)
+ return r;
+
+ r = jpeg_v4_0_5_hw_init(adev);
+
+ return r;
+}
+
+static void jpeg_v4_0_5_disable_clock_gating(struct amdgpu_device *adev)
+{
+ uint32_t data = 0;
+
+ data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL);
+ if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) {
+ data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ data &= (~JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK);
+ } else {
+ data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ }
+
+ data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+ data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+ WREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL, data);
+
+ data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE);
+ data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK
+ | JPEG_CGC_GATE__JPEG2_DEC_MASK
+ | JPEG_CGC_GATE__JMCIF_MASK
+ | JPEG_CGC_GATE__JRBBM_MASK);
+ WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data);
+}
+
+static void jpeg_v4_0_5_enable_clock_gating(struct amdgpu_device *adev)
+{
+ uint32_t data = 0;
+
+ data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL);
+ if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) {
+ data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ data |= JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK;
+ } else {
+ data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ }
+
+ data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+ data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+ WREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL, data);
+
+ data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE);
+ data |= (JPEG_CGC_GATE__JPEG_DEC_MASK
+ |JPEG_CGC_GATE__JPEG2_DEC_MASK
+ |JPEG_CGC_GATE__JMCIF_MASK
+ |JPEG_CGC_GATE__JRBBM_MASK);
+ WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data);
+}
+
+static int jpeg_v4_0_5_disable_static_power_gating(struct amdgpu_device *adev)
+{
+ if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {
+ WREG32(SOC15_REG_OFFSET(JPEG, 0, regUVD_IPX_DLDO_CONFIG),
+ 1 << UVD_IPX_DLDO_CONFIG__ONO1_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_IPX_DLDO_STATUS,
+ 0, UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS_MASK);
+ }
+
+ /* disable anti hang mechanism */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), 0,
+ ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
+
+ /* keep the JPEG in static PG mode */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), 0,
+ ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK);
+
+ return 0;
+}
+
+static int jpeg_v4_0_5_enable_static_power_gating(struct amdgpu_device *adev)
+{
+ /* enable anti hang mechanism */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS),
+ UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
+ ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
+
+ if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {
+ WREG32(SOC15_REG_OFFSET(JPEG, 0, regUVD_IPX_DLDO_CONFIG),
+ 2 << UVD_IPX_DLDO_CONFIG__ONO1_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_IPX_DLDO_STATUS,
+ 1 << UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS__SHIFT,
+ UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS_MASK);
+ }
+
+ return 0;
+}
+
+/**
+ * jpeg_v4_0_5_start - start JPEG block
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Setup and start the JPEG block
+ */
+static int jpeg_v4_0_5_start(struct amdgpu_device *adev)
+{
+ struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
+ int r;
+
+ if (adev->pm.dpm_enabled)
+ amdgpu_dpm_enable_jpeg(adev, true);
+
+ /* doorbell programming is done for every playback */
+ adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
+ (adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
+
+ WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
+ ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
+ VCN_JPEG_DB_CTRL__EN_MASK);
+
+ /* disable power gating */
+ r = jpeg_v4_0_5_disable_static_power_gating(adev);
+ if (r)
+ return r;
+
+ /* JPEG disable CGC */
+ jpeg_v4_0_5_disable_clock_gating(adev);
+
+ /* MJPEG global tiling registers */
+ WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG,
+ adev->gfx.config.gb_addr_config);
+
+
+ /* enable JMI channel */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL), 0,
+ ~UVD_JMI_CNTL__SOFT_RESET_MASK);
+
+ /* enable System Interrupt for JRBC */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regJPEG_SYS_INT_EN),
+ JPEG_SYS_INT_EN__DJRBC_MASK,
+ ~JPEG_SYS_INT_EN__DJRBC_MASK);
+
+ WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_VMID, 0);
+ WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
+ WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
+ lower_32_bits(ring->gpu_addr));
+ WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
+ upper_32_bits(ring->gpu_addr));
+ WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_RPTR, 0);
+ WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR, 0);
+ WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_CNTL, 0x00000002L);
+ WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_SIZE, ring->ring_size / 4);
+ ring->wptr = RREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR);
+
+ return 0;
+}
+
+/**
+ * jpeg_v4_0_5_stop - stop JPEG block
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * stop the JPEG block
+ */
+static int jpeg_v4_0_5_stop(struct amdgpu_device *adev)
+{
+ int r;
+
+ /* reset JMI */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL),
+ UVD_JMI_CNTL__SOFT_RESET_MASK,
+ ~UVD_JMI_CNTL__SOFT_RESET_MASK);
+
+ jpeg_v4_0_5_enable_clock_gating(adev);
+
+ /* enable power gating */
+ r = jpeg_v4_0_5_enable_static_power_gating(adev);
+ if (r)
+ return r;
+
+ if (adev->pm.dpm_enabled)
+ amdgpu_dpm_enable_jpeg(adev, false);
+
+ return 0;
+}
+
+/**
+ * jpeg_v4_0_5_dec_ring_get_rptr - get read pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Returns the current hardware read pointer
+ */
+static uint64_t jpeg_v4_0_5_dec_ring_get_rptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ return RREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_RPTR);
+}
+
+/**
+ * jpeg_v4_0_5_dec_ring_get_wptr - get write pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Returns the current hardware write pointer
+ */
+static uint64_t jpeg_v4_0_5_dec_ring_get_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring->use_doorbell)
+ return *ring->wptr_cpu_addr;
+ else
+ return RREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR);
+}
+
+/**
+ * jpeg_v4_0_5_dec_ring_set_wptr - set write pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Commits the write pointer to the hardware
+ */
+static void jpeg_v4_0_5_dec_ring_set_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring->use_doorbell) {
+ *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);
+ WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
+ } else {
+ WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
+ }
+}
+
+static bool jpeg_v4_0_5_is_idle(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret = 1;
+
+ ret &= (((RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS) &
+ UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==
+ UVD_JRBC_STATUS__RB_JOB_DONE_MASK));
+
+ return ret;
+}
+
+static int jpeg_v4_0_5_wait_for_idle(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ return SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_JRBC_STATUS,
+ UVD_JRBC_STATUS__RB_JOB_DONE_MASK,
+ UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
+}
+
+static int jpeg_v4_0_5_set_clockgating_state(void *handle,
+ enum amd_clockgating_state state)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
+
+ if (enable) {
+ if (!jpeg_v4_0_5_is_idle(handle))
+ return -EBUSY;
+ jpeg_v4_0_5_enable_clock_gating(adev);
+ } else {
+ jpeg_v4_0_5_disable_clock_gating(adev);
+ }
+
+ return 0;
+}
+
+static int jpeg_v4_0_5_set_powergating_state(void *handle,
+ enum amd_powergating_state state)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
+
+ if (amdgpu_sriov_vf(adev)) {
+ adev->jpeg.cur_state = AMD_PG_STATE_UNGATE;
+ return 0;
+ }
+
+ if (state == adev->jpeg.cur_state)
+ return 0;
+
+ if (state == AMD_PG_STATE_GATE)
+ ret = jpeg_v4_0_5_stop(adev);
+ else
+ ret = jpeg_v4_0_5_start(adev);
+
+ if (!ret)
+ adev->jpeg.cur_state = state;
+
+ return ret;
+}
+
+static int jpeg_v4_0_5_set_interrupt_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ unsigned type,
+ enum amdgpu_interrupt_state state)
+{
+ return 0;
+}
+
+static int jpeg_v4_0_5_process_interrupt(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ DRM_DEBUG("IH: JPEG TRAP\n");
+
+ switch (entry->src_id) {
+ case VCN_4_0__SRCID__JPEG_DECODE:
+ amdgpu_fence_process(adev->jpeg.inst->ring_dec);
+ break;
+ case VCN_4_0__SRCID_DJPEG0_POISON:
+ case VCN_4_0__SRCID_EJPEG0_POISON:
+ amdgpu_jpeg_process_poison_irq(adev, source, entry);
+ break;
+ default:
+ DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",
+ entry->src_id, entry->src_data[0]);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct amd_ip_funcs jpeg_v4_0_5_ip_funcs = {
+ .name = "jpeg_v4_0_5",
+ .early_init = jpeg_v4_0_5_early_init,
+ .late_init = NULL,
+ .sw_init = jpeg_v4_0_5_sw_init,
+ .sw_fini = jpeg_v4_0_5_sw_fini,
+ .hw_init = jpeg_v4_0_5_hw_init,
+ .hw_fini = jpeg_v4_0_5_hw_fini,
+ .suspend = jpeg_v4_0_5_suspend,
+ .resume = jpeg_v4_0_5_resume,
+ .is_idle = jpeg_v4_0_5_is_idle,
+ .wait_for_idle = jpeg_v4_0_5_wait_for_idle,
+ .check_soft_reset = NULL,
+ .pre_soft_reset = NULL,
+ .soft_reset = NULL,
+ .post_soft_reset = NULL,
+ .set_clockgating_state = jpeg_v4_0_5_set_clockgating_state,
+ .set_powergating_state = jpeg_v4_0_5_set_powergating_state,
+};
+
+static const struct amdgpu_ring_funcs jpeg_v4_0_5_dec_ring_vm_funcs = {
+ .type = AMDGPU_RING_TYPE_VCN_JPEG,
+ .align_mask = 0xf,
+ .get_rptr = jpeg_v4_0_5_dec_ring_get_rptr,
+ .get_wptr = jpeg_v4_0_5_dec_ring_get_wptr,
+ .set_wptr = jpeg_v4_0_5_dec_ring_set_wptr,
+ .emit_frame_size =
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
+ 8 + /* jpeg_v4_0_5_dec_ring_emit_vm_flush */
+ 18 + 18 + /* jpeg_v4_0_5_dec_ring_emit_fence x2 vm fence */
+ 8 + 16,
+ .emit_ib_size = 22, /* jpeg_v4_0_5_dec_ring_emit_ib */
+ .emit_ib = jpeg_v2_0_dec_ring_emit_ib,
+ .emit_fence = jpeg_v2_0_dec_ring_emit_fence,
+ .emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,
+ .test_ring = amdgpu_jpeg_dec_ring_test_ring,
+ .test_ib = amdgpu_jpeg_dec_ring_test_ib,
+ .insert_nop = jpeg_v2_0_dec_ring_nop,
+ .insert_start = jpeg_v2_0_dec_ring_insert_start,
+ .insert_end = jpeg_v2_0_dec_ring_insert_end,
+ .pad_ib = amdgpu_ring_generic_pad_ib,
+ .begin_use = amdgpu_jpeg_ring_begin_use,
+ .end_use = amdgpu_jpeg_ring_end_use,
+ .emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,
+ .emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,
+ .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+};
+
+static void jpeg_v4_0_5_set_dec_ring_funcs(struct amdgpu_device *adev)
+{
+ adev->jpeg.inst->ring_dec->funcs = &jpeg_v4_0_5_dec_ring_vm_funcs;
+ DRM_DEV_INFO(adev->dev, "JPEG decode is enabled in VM mode\n");
+}
+
+static const struct amdgpu_irq_src_funcs jpeg_v4_0_5_irq_funcs = {
+ .set = jpeg_v4_0_5_set_interrupt_state,
+ .process = jpeg_v4_0_5_process_interrupt,
+};
+
+static void jpeg_v4_0_5_set_irq_funcs(struct amdgpu_device *adev)
+{
+ adev->jpeg.inst->irq.num_types = 1;
+ adev->jpeg.inst->irq.funcs = &jpeg_v4_0_5_irq_funcs;
+}
+
+const struct amdgpu_ip_block_version jpeg_v4_0_5_ip_block = {
+ .type = AMD_IP_BLOCK_TYPE_JPEG,
+ .major = 4,
+ .minor = 0,
+ .rev = 5,
+ .funcs = &jpeg_v4_0_5_ip_funcs,
+};
+
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.h
new file mode 100644
index 000000000000..c5eee572079c
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __JPEG_V4_0_5_H__
+#define __JPEG_V4_0_5_H__
+
+enum amdgpu_jpeg_v4_0_5_sub_block {
+ AMDGPU_JPEG_V4_0_5_JPEG0 = 0,
+
+ AMDGPU_JPEG_V4_0_5_MAX_SUB_BLOCK,
+};
+
+extern const struct amdgpu_ip_block_version jpeg_v4_0_5_ip_block;
+
+#endif /* __JPEG_V4_0_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
index eb06d749876f..1e5ad1e08d2a 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
@@ -558,7 +558,7 @@ static int mes_v10_1_load_microcode(struct amdgpu_device *adev,
WREG32_SOC15(GC, 0, mmCP_MES_MDBOUND_LO, 0x3FFFF);
/* invalidate ICACHE */
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
data = RREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL_Sienna_Cichlid);
break;
@@ -568,7 +568,7 @@ static int mes_v10_1_load_microcode(struct amdgpu_device *adev,
}
data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 0);
data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, INVALIDATE_CACHE, 1);
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
WREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL_Sienna_Cichlid, data);
break;
@@ -578,7 +578,7 @@ static int mes_v10_1_load_microcode(struct amdgpu_device *adev,
}
/* prime the ICACHE. */
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
data = RREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL_Sienna_Cichlid);
break;
@@ -587,7 +587,7 @@ static int mes_v10_1_load_microcode(struct amdgpu_device *adev,
break;
}
data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 1);
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
WREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL_Sienna_Cichlid, data);
break;
@@ -995,7 +995,7 @@ static void mes_v10_1_kiq_setting(struct amdgpu_ring *ring)
struct amdgpu_device *adev = ring->adev;
/* tell RLC which is KIQ queue */
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 1):
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index 6827d547042e..4dfec56e1b7f 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -47,6 +47,9 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_3_mes1.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_4_mes.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_4_mes_2.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_4_mes1.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_0_mes_2.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_5_0_mes1.bin");
+
static int mes_v11_0_hw_fini(void *handle);
static int mes_v11_0_kiq_hw_init(struct amdgpu_device *adev);
@@ -403,6 +406,7 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes)
mes_set_hw_res_pkt.disable_mes_log = 1;
mes_set_hw_res_pkt.use_different_vmid_compute = 1;
mes_set_hw_res_pkt.enable_reg_active_poll = 1;
+ mes_set_hw_res_pkt.enable_level_process_quantum_check = 1;
mes_set_hw_res_pkt.oversubscription_timer = 50;
return mes_v11_0_submit_pkt_and_poll_completion(mes,
@@ -410,60 +414,6 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes)
offsetof(union MESAPI_SET_HW_RESOURCES, api_status));
}
-static void mes_v11_0_init_aggregated_doorbell(struct amdgpu_mes *mes)
-{
- struct amdgpu_device *adev = mes->adev;
- uint32_t data;
-
- data = RREG32_SOC15(GC, 0, regCP_MES_DOORBELL_CONTROL1);
- data &= ~(CP_MES_DOORBELL_CONTROL1__DOORBELL_OFFSET_MASK |
- CP_MES_DOORBELL_CONTROL1__DOORBELL_EN_MASK |
- CP_MES_DOORBELL_CONTROL1__DOORBELL_HIT_MASK);
- data |= mes->aggregated_doorbells[AMDGPU_MES_PRIORITY_LEVEL_LOW] <<
- CP_MES_DOORBELL_CONTROL1__DOORBELL_OFFSET__SHIFT;
- data |= 1 << CP_MES_DOORBELL_CONTROL1__DOORBELL_EN__SHIFT;
- WREG32_SOC15(GC, 0, regCP_MES_DOORBELL_CONTROL1, data);
-
- data = RREG32_SOC15(GC, 0, regCP_MES_DOORBELL_CONTROL2);
- data &= ~(CP_MES_DOORBELL_CONTROL2__DOORBELL_OFFSET_MASK |
- CP_MES_DOORBELL_CONTROL2__DOORBELL_EN_MASK |
- CP_MES_DOORBELL_CONTROL2__DOORBELL_HIT_MASK);
- data |= mes->aggregated_doorbells[AMDGPU_MES_PRIORITY_LEVEL_NORMAL] <<
- CP_MES_DOORBELL_CONTROL2__DOORBELL_OFFSET__SHIFT;
- data |= 1 << CP_MES_DOORBELL_CONTROL2__DOORBELL_EN__SHIFT;
- WREG32_SOC15(GC, 0, regCP_MES_DOORBELL_CONTROL2, data);
-
- data = RREG32_SOC15(GC, 0, regCP_MES_DOORBELL_CONTROL3);
- data &= ~(CP_MES_DOORBELL_CONTROL3__DOORBELL_OFFSET_MASK |
- CP_MES_DOORBELL_CONTROL3__DOORBELL_EN_MASK |
- CP_MES_DOORBELL_CONTROL3__DOORBELL_HIT_MASK);
- data |= mes->aggregated_doorbells[AMDGPU_MES_PRIORITY_LEVEL_MEDIUM] <<
- CP_MES_DOORBELL_CONTROL3__DOORBELL_OFFSET__SHIFT;
- data |= 1 << CP_MES_DOORBELL_CONTROL3__DOORBELL_EN__SHIFT;
- WREG32_SOC15(GC, 0, regCP_MES_DOORBELL_CONTROL3, data);
-
- data = RREG32_SOC15(GC, 0, regCP_MES_DOORBELL_CONTROL4);
- data &= ~(CP_MES_DOORBELL_CONTROL4__DOORBELL_OFFSET_MASK |
- CP_MES_DOORBELL_CONTROL4__DOORBELL_EN_MASK |
- CP_MES_DOORBELL_CONTROL4__DOORBELL_HIT_MASK);
- data |= mes->aggregated_doorbells[AMDGPU_MES_PRIORITY_LEVEL_HIGH] <<
- CP_MES_DOORBELL_CONTROL4__DOORBELL_OFFSET__SHIFT;
- data |= 1 << CP_MES_DOORBELL_CONTROL4__DOORBELL_EN__SHIFT;
- WREG32_SOC15(GC, 0, regCP_MES_DOORBELL_CONTROL4, data);
-
- data = RREG32_SOC15(GC, 0, regCP_MES_DOORBELL_CONTROL5);
- data &= ~(CP_MES_DOORBELL_CONTROL5__DOORBELL_OFFSET_MASK |
- CP_MES_DOORBELL_CONTROL5__DOORBELL_EN_MASK |
- CP_MES_DOORBELL_CONTROL5__DOORBELL_HIT_MASK);
- data |= mes->aggregated_doorbells[AMDGPU_MES_PRIORITY_LEVEL_REALTIME] <<
- CP_MES_DOORBELL_CONTROL5__DOORBELL_OFFSET__SHIFT;
- data |= 1 << CP_MES_DOORBELL_CONTROL5__DOORBELL_EN__SHIFT;
- WREG32_SOC15(GC, 0, regCP_MES_DOORBELL_CONTROL5, data);
-
- data = 1 << CP_HQD_GFX_CONTROL__DB_UPDATED_MSG_EN__SHIFT;
- WREG32_SOC15(GC, 0, regCP_HQD_GFX_CONTROL, data);
-}
-
static const struct amdgpu_mes_funcs mes_v11_0_funcs = {
.add_hw_queue = mes_v11_0_add_hw_queue,
.remove_hw_queue = mes_v11_0_remove_hw_queue,
@@ -1239,8 +1189,6 @@ static int mes_v11_0_hw_init(void *handle)
if (r)
goto failure;
- mes_v11_0_init_aggregated_doorbell(&adev->mes);
-
r = mes_v11_0_query_sched_status(&adev->mes);
if (r) {
DRM_ERROR("MES is busy\n");
@@ -1313,7 +1261,7 @@ static int mes_v11_0_late_init(void *handle)
/* it's only intended for use in mes_self_test case, not for s0ix and reset */
if (!amdgpu_in_reset(adev) && !adev->in_s0ix && !adev->in_suspend &&
- (adev->ip_versions[GC_HWIP][0] != IP_VERSION(11, 0, 3)))
+ (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(11, 0, 3)))
amdgpu_mes_self_test(adev);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
index fb91b31056ca..843219a91736 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
@@ -242,7 +242,7 @@ static void mmhub_v1_0_setup_vmid_config(struct amdgpu_device *adev)
block_size -= 9;
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(MMHUB, 0, mmVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, mmVM_CONTEXT1_CNTL, i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
num_level);
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c
index 9086f2fdfaf4..92432cd2c0c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c
@@ -274,7 +274,7 @@ static void mmhub_v1_7_setup_vmid_config(struct amdgpu_device *adev)
block_size -= 9;
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(MMHUB, 0, regVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, regVM_CONTEXT1_CNTL, i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
num_level);
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
index 784c4e077470..9b0146732e13 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
@@ -130,6 +130,9 @@ static void mmhub_v1_8_init_system_aperture_regs(struct amdgpu_device *adev)
uint64_t value;
int i;
+ if (amdgpu_sriov_vf(adev))
+ return;
+
inst_mask = adev->aid_mask;
for_each_inst(i, inst_mask) {
/* Program the AGP BAR */
@@ -139,9 +142,6 @@ static void mmhub_v1_8_init_system_aperture_regs(struct amdgpu_device *adev)
WREG32_SOC15(MMHUB, i, regMC_VM_AGP_TOP,
adev->gmc.agp_end >> 24);
- if (amdgpu_sriov_vf(adev))
- return;
-
/* Program the system aperture low logical page number. */
WREG32_SOC15(MMHUB, i, regMC_VM_SYSTEM_APERTURE_LOW_ADDR,
min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
@@ -344,7 +344,7 @@ static void mmhub_v1_8_setup_vmid_config(struct amdgpu_device *adev)
hub = &adev->vmhub[AMDGPU_MMHUB0(j)];
for (i = 0; i <= 14; i++) {
tmp = RREG32_SOC15_OFFSET(MMHUB, j, regVM_CONTEXT1_CNTL,
- i);
+ i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
@@ -626,6 +626,14 @@ static void mmhub_v1_8_inst_query_ras_error_count(struct amdgpu_device *adev,
void *ras_err_status)
{
struct ras_err_data *err_data = (struct ras_err_data *)ras_err_status;
+ unsigned long ue_count = 0, ce_count = 0;
+
+ /* NOTE: mmhub is converted by aid_mask and the range is 0-3,
+ * which can be used as die ID directly */
+ struct amdgpu_smuio_mcm_config_info mcm_info = {
+ .socket_id = adev->smuio.funcs->get_socket_id(adev),
+ .die_id = mmhub_inst,
+ };
amdgpu_ras_inst_query_ras_error_count(adev,
mmhub_v1_8_ce_reg_list,
@@ -634,7 +642,7 @@ static void mmhub_v1_8_inst_query_ras_error_count(struct amdgpu_device *adev,
ARRAY_SIZE(mmhub_v1_8_ras_memory_list),
mmhub_inst,
AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE,
- &err_data->ce_count);
+ &ce_count);
amdgpu_ras_inst_query_ras_error_count(adev,
mmhub_v1_8_ue_reg_list,
ARRAY_SIZE(mmhub_v1_8_ue_reg_list),
@@ -642,7 +650,10 @@ static void mmhub_v1_8_inst_query_ras_error_count(struct amdgpu_device *adev,
ARRAY_SIZE(mmhub_v1_8_ras_memory_list),
mmhub_inst,
AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
- &err_data->ue_count);
+ &ue_count);
+
+ amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, ce_count);
+ amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count);
}
static void mmhub_v1_8_query_ras_error_count(struct amdgpu_device *adev,
@@ -689,152 +700,9 @@ static void mmhub_v1_8_reset_ras_error_count(struct amdgpu_device *adev)
mmhub_v1_8_inst_reset_ras_error_count(adev, i);
}
-static const u32 mmhub_v1_8_mmea_err_status_reg[] __maybe_unused = {
- regMMEA0_ERR_STATUS,
- regMMEA1_ERR_STATUS,
- regMMEA2_ERR_STATUS,
- regMMEA3_ERR_STATUS,
- regMMEA4_ERR_STATUS,
-};
-
-static void mmhub_v1_8_inst_query_ras_err_status(struct amdgpu_device *adev,
- uint32_t mmhub_inst)
-{
- uint32_t reg_value;
- uint32_t mmea_err_status_addr_dist;
- uint32_t i;
-
- /* query mmea ras err status */
- mmea_err_status_addr_dist = regMMEA1_ERR_STATUS - regMMEA0_ERR_STATUS;
- for (i = 0; i < ARRAY_SIZE(mmhub_v1_8_mmea_err_status_reg); i++) {
- reg_value = RREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
- regMMEA0_ERR_STATUS,
- i * mmea_err_status_addr_dist);
- if (REG_GET_FIELD(reg_value, MMEA0_ERR_STATUS, SDP_RDRSP_STATUS) ||
- REG_GET_FIELD(reg_value, MMEA0_ERR_STATUS, SDP_WRRSP_STATUS) ||
- REG_GET_FIELD(reg_value, MMEA0_ERR_STATUS, SDP_RDRSP_DATAPARITY_ERROR)) {
- dev_warn(adev->dev,
- "Detected MMEA%d err in MMHUB%d, status: 0x%x\n",
- i, mmhub_inst, reg_value);
- }
- }
-
- /* query mm_cane ras err status */
- reg_value = RREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ERR_STATUS);
- if (REG_GET_FIELD(reg_value, MM_CANE_ERR_STATUS, SDPM_RDRSP_STATUS) ||
- REG_GET_FIELD(reg_value, MM_CANE_ERR_STATUS, SDPM_WRRSP_STATUS) ||
- REG_GET_FIELD(reg_value, MM_CANE_ERR_STATUS, SDPM_RDRSP_DATAPARITY_ERROR)) {
- dev_warn(adev->dev,
- "Detected MM CANE err in MMHUB%d, status: 0x%x\n",
- mmhub_inst, reg_value);
- }
-}
-
-static void mmhub_v1_8_query_ras_error_status(struct amdgpu_device *adev)
-{
- uint32_t inst_mask;
- uint32_t i;
-
- if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__MMHUB)) {
- dev_warn(adev->dev, "MMHUB RAS is not supported\n");
- return;
- }
-
- inst_mask = adev->aid_mask;
- for_each_inst(i, inst_mask)
- mmhub_v1_8_inst_query_ras_err_status(adev, i);
-}
-
-static void mmhub_v1_8_inst_reset_ras_err_status(struct amdgpu_device *adev,
- uint32_t mmhub_inst)
-{
- uint32_t mmea_cgtt_clk_cntl_addr_dist;
- uint32_t mmea_err_status_addr_dist;
- uint32_t reg_value;
- uint32_t i;
-
- /* reset mmea ras err status */
- mmea_cgtt_clk_cntl_addr_dist = regMMEA1_CGTT_CLK_CTRL - regMMEA0_CGTT_CLK_CTRL;
- mmea_err_status_addr_dist = regMMEA1_ERR_STATUS - regMMEA0_ERR_STATUS;
- for (i = 0; i < ARRAY_SIZE(mmhub_v1_8_mmea_err_status_reg); i++) {
- /* force clk branch on for response path
- * set MMEA0_CGTT_CLK_CTRL.SOFT_OVERRIDE_RETURN = 1
- */
- reg_value = RREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
- regMMEA0_CGTT_CLK_CTRL,
- i * mmea_cgtt_clk_cntl_addr_dist);
- reg_value = REG_SET_FIELD(reg_value, MMEA0_CGTT_CLK_CTRL,
- SOFT_OVERRIDE_RETURN, 1);
- WREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
- regMMEA0_CGTT_CLK_CTRL,
- i * mmea_cgtt_clk_cntl_addr_dist,
- reg_value);
-
- /* set MMEA0_ERR_STATUS.CLEAR_ERROR_STATUS = 1 */
- reg_value = RREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
- regMMEA0_ERR_STATUS,
- i * mmea_err_status_addr_dist);
- reg_value = REG_SET_FIELD(reg_value, MMEA0_ERR_STATUS,
- CLEAR_ERROR_STATUS, 1);
- WREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
- regMMEA0_ERR_STATUS,
- i * mmea_err_status_addr_dist,
- reg_value);
-
- /* set MMEA0_CGTT_CLK_CTRL.SOFT_OVERRIDE_RETURN = 0 */
- reg_value = RREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
- regMMEA0_CGTT_CLK_CTRL,
- i * mmea_cgtt_clk_cntl_addr_dist);
- reg_value = REG_SET_FIELD(reg_value, MMEA0_CGTT_CLK_CTRL,
- SOFT_OVERRIDE_RETURN, 0);
- WREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
- regMMEA0_CGTT_CLK_CTRL,
- i * mmea_cgtt_clk_cntl_addr_dist,
- reg_value);
- }
-
- /* reset mm_cane ras err status
- * force clk branch on for response path
- * set MM_CANE_ICG_CTRL.SOFT_OVERRIDE_ATRET = 1
- */
- reg_value = RREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ICG_CTRL);
- reg_value = REG_SET_FIELD(reg_value, MM_CANE_ICG_CTRL,
- SOFT_OVERRIDE_ATRET, 1);
- WREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ICG_CTRL, reg_value);
-
- /* set MM_CANE_ERR_STATUS.CLEAR_ERROR_STATUS = 1 */
- reg_value = RREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ERR_STATUS);
- reg_value = REG_SET_FIELD(reg_value, MM_CANE_ERR_STATUS,
- CLEAR_ERROR_STATUS, 1);
- WREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ERR_STATUS, reg_value);
-
- /* set MM_CANE_ICG_CTRL.SOFT_OVERRIDE_ATRET = 0 */
- reg_value = RREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ICG_CTRL);
- reg_value = REG_SET_FIELD(reg_value, MM_CANE_ICG_CTRL,
- SOFT_OVERRIDE_ATRET, 0);
- WREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ICG_CTRL, reg_value);
-}
-
-static void mmhub_v1_8_reset_ras_error_status(struct amdgpu_device *adev)
-{
- uint32_t inst_mask;
- uint32_t i;
-
- if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__MMHUB)) {
- dev_warn(adev->dev, "MMHUB RAS is not supported\n");
- return;
- }
-
- inst_mask = adev->aid_mask;
- for_each_inst(i, inst_mask)
- mmhub_v1_8_inst_reset_ras_err_status(adev, i);
-}
-
static const struct amdgpu_ras_block_hw_ops mmhub_v1_8_ras_hw_ops = {
.query_ras_error_count = mmhub_v1_8_query_ras_error_count,
.reset_ras_error_count = mmhub_v1_8_reset_ras_error_count,
- .query_ras_error_status = mmhub_v1_8_query_ras_error_status,
- .reset_ras_error_status = mmhub_v1_8_reset_ras_error_status,
};
struct amdgpu_mmhub_ras mmhub_v1_8_ras = {
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
index 8f76c6ecf50a..02fd45261399 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
@@ -151,7 +151,7 @@ mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
dev_err(adev->dev,
"MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(2, 0, 0):
case IP_VERSION(2, 0, 2):
mmhub_cid = mmhub_client_ids_navi1x[cid][rw];
@@ -367,7 +367,7 @@ static void mmhub_v2_0_setup_vmid_config(struct amdgpu_device *adev)
uint32_t tmp;
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT1_CNTL, i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
adev->vm_manager.num_level);
@@ -568,7 +568,7 @@ static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *ad
if (!(adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG))
return;
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 1, 2):
@@ -601,7 +601,7 @@ static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *ad
DAGB0_CNTL_MISC2__DISABLE_TLBRD_CG_MASK);
}
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 1, 2):
@@ -625,7 +625,7 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade
if (!(adev->cg_flags & AMD_CG_SUPPORT_MC_LS))
return;
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 1, 2):
@@ -651,7 +651,7 @@ static int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(2, 0, 0):
case IP_VERSION(2, 0, 2):
case IP_VERSION(2, 1, 0):
@@ -676,7 +676,7 @@ static void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u64 *flags)
if (amdgpu_sriov_vf(adev))
*flags = 0;
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 1, 2):
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
index 1dce053a4c4d..5eb8122e2746 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
@@ -90,7 +90,7 @@ mmhub_v2_3_print_l2_protection_fault_status(struct amdgpu_device *adev,
dev_err(adev->dev,
"MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(2, 3, 0):
case IP_VERSION(2, 4, 0):
case IP_VERSION(2, 4, 1):
@@ -285,7 +285,7 @@ static void mmhub_v2_3_setup_vmid_config(struct amdgpu_device *adev)
uint32_t tmp;
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT1_CNTL, i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
adev->vm_manager.num_level);
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c
index 441379e91cfa..7d5242df58a5 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c
@@ -107,7 +107,7 @@ mmhub_v3_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
dev_err(adev->dev,
"MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(3, 0, 0):
case IP_VERSION(3, 0, 1):
mmhub_cid = mmhub_client_ids_v3_0_0[cid][rw];
@@ -189,8 +189,7 @@ static void mmhub_v3_0_init_system_aperture_regs(struct amdgpu_device *adev)
max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
/* Set default page address. */
- value = adev->mem_scratch.gpu_addr - adev->gmc.vram_start +
- adev->vm_manager.vram_base_offset;
+ value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
WREG32_SOC15(MMHUB, 0, regMMMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
(u32)(value >> 12));
WREG32_SOC15(MMHUB, 0, regMMMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
@@ -324,7 +323,7 @@ static void mmhub_v3_0_setup_vmid_config(struct amdgpu_device *adev)
uint32_t tmp;
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL, i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
adev->vm_manager.num_level);
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c
index 12c7f4b46ea9..134c4ec10887 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c
@@ -108,7 +108,7 @@ mmhub_v3_0_1_print_l2_protection_fault_status(struct amdgpu_device *adev,
"MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(3, 0, 1):
mmhub_cid = mmhub_client_ids_v3_0_1[cid][rw];
break;
@@ -188,8 +188,7 @@ static void mmhub_v3_0_1_init_system_aperture_regs(struct amdgpu_device *adev)
max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
/* Set default page address. */
- value = adev->mem_scratch.gpu_addr - adev->gmc.vram_start +
- adev->vm_manager.vram_base_offset;
+ value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
WREG32_SOC15(MMHUB, 0, regMMMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
(u32)(value >> 12));
WREG32_SOC15(MMHUB, 0, regMMMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
@@ -311,7 +310,7 @@ static void mmhub_v3_0_1_setup_vmid_config(struct amdgpu_device *adev)
uint32_t tmp;
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL, i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
adev->vm_manager.num_level);
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c
index 5dadc85abf7e..f0f182f033b9 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c
@@ -181,8 +181,7 @@ static void mmhub_v3_0_2_init_system_aperture_regs(struct amdgpu_device *adev)
}
/* Set default page address. */
- value = adev->mem_scratch.gpu_addr - adev->gmc.vram_start +
- adev->vm_manager.vram_base_offset;
+ value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
WREG32_SOC15(MMHUB, 0, regMMMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
(u32)(value >> 12));
WREG32_SOC15(MMHUB, 0, regMMMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
@@ -316,7 +315,7 @@ static void mmhub_v3_0_2_setup_vmid_config(struct amdgpu_device *adev)
uint32_t tmp;
for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL, i);
+ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL, i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
adev->vm_manager.num_level);
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c
new file mode 100644
index 000000000000..dc4812ecc98d
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c
@@ -0,0 +1,589 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "amdgpu.h"
+#include "mmhub_v3_3.h"
+
+#include "mmhub/mmhub_3_3_0_offset.h"
+#include "mmhub/mmhub_3_3_0_sh_mask.h"
+
+#include "navi10_enum.h"
+#include "soc15_common.h"
+
+#define regMMVM_L2_CNTL3_DEFAULT 0x80100007
+#define regMMVM_L2_CNTL4_DEFAULT 0x000000c1
+#define regMMVM_L2_CNTL5_DEFAULT 0x00003fe0
+
+static const char *mmhub_client_ids_v3_3[][2] = {
+ [0][0] = "VMC",
+ [4][0] = "DCEDMC",
+ [6][0] = "MP0",
+ [7][0] = "MP1",
+ [8][0] = "MPM",
+ [24][0] = "HDP",
+ [25][0] = "LSDMA",
+ [26][0] = "JPEG",
+ [27][0] = "VPE",
+ [29][0] = "VCNU",
+ [30][0] = "VCN",
+ [3][1] = "DCEDWB",
+ [4][1] = "DCEDMC",
+ [6][1] = "MP0",
+ [7][1] = "MP1",
+ [8][1] = "MPM",
+ [21][1] = "OSSSYS",
+ [24][1] = "HDP",
+ [25][1] = "LSDMA",
+ [26][1] = "JPEG",
+ [27][1] = "VPE",
+ [29][1] = "VCNU",
+ [30][1] = "VCN",
+};
+
+static uint32_t mmhub_v3_3_get_invalidate_req(unsigned int vmid,
+ uint32_t flush_type)
+{
+ u32 req = 0;
+
+ /* invalidate using legacy mode on vmid*/
+ req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ,
+ PER_VMID_INVALIDATE_REQ, 1 << vmid);
+ req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, flush_type ? : 1);
+ req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PTES, 1);
+ req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE0, 1);
+ req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE1, 1);
+ req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE2, 1);
+ req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L1_PTES, 1);
+ req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ,
+ CLEAR_PROTECTION_FAULT_STATUS_ADDR, 0);
+
+ return req;
+}
+
+static void
+mmhub_v3_3_print_l2_protection_fault_status(struct amdgpu_device *adev,
+ uint32_t status)
+{
+ uint32_t cid, rw;
+ const char *mmhub_cid = NULL;
+
+ cid = REG_GET_FIELD(status,
+ MMVM_L2_PROTECTION_FAULT_STATUS, CID);
+ rw = REG_GET_FIELD(status,
+ MMVM_L2_PROTECTION_FAULT_STATUS, RW);
+
+ dev_err(adev->dev,
+ "MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
+ status);
+
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
+ case IP_VERSION(3, 3, 0):
+ mmhub_cid = mmhub_client_ids_v3_3[cid][rw];
+ break;
+ default:
+ mmhub_cid = NULL;
+ break;
+ }
+
+ if (!mmhub_cid && cid == 0x140)
+ mmhub_cid = "UMSCH";
+
+ dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
+ mmhub_cid ? mmhub_cid : "unknown", cid);
+ dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
+ REG_GET_FIELD(status,
+ MMVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS));
+ dev_err(adev->dev, "\t WALKER_ERROR: 0x%lx\n",
+ REG_GET_FIELD(status,
+ MMVM_L2_PROTECTION_FAULT_STATUS, WALKER_ERROR));
+ dev_err(adev->dev, "\t PERMISSION_FAULTS: 0x%lx\n",
+ REG_GET_FIELD(status,
+ MMVM_L2_PROTECTION_FAULT_STATUS, PERMISSION_FAULTS));
+ dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n",
+ REG_GET_FIELD(status,
+ MMVM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR));
+ dev_err(adev->dev, "\t RW: 0x%x\n", rw);
+}
+
+static void mmhub_v3_3_setup_vm_pt_regs(struct amdgpu_device *adev,
+ uint32_t vmid,
+ uint64_t page_table_base)
+{
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
+
+ WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
+ hub->ctx_addr_distance * vmid,
+ lower_32_bits(page_table_base));
+
+ WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
+ hub->ctx_addr_distance * vmid,
+ upper_32_bits(page_table_base));
+
+}
+
+static void mmhub_v3_3_init_gart_aperture_regs(struct amdgpu_device *adev)
+{
+ uint64_t pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
+
+ mmhub_v3_3_setup_vm_pt_regs(adev, 0, pt_base);
+
+ WREG32_SOC15(MMHUB, 0, regMMVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
+ (u32)(adev->gmc.gart_start >> 12));
+ WREG32_SOC15(MMHUB, 0, regMMVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
+ (u32)(adev->gmc.gart_start >> 44));
+
+ WREG32_SOC15(MMHUB, 0, regMMVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
+ (u32)(adev->gmc.gart_end >> 12));
+ WREG32_SOC15(MMHUB, 0, regMMVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
+ (u32)(adev->gmc.gart_end >> 44));
+}
+
+static void mmhub_v3_3_init_system_aperture_regs(struct amdgpu_device *adev)
+{
+ uint64_t value;
+ uint32_t tmp;
+
+ /* Program the AGP BAR */
+ WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_BASE, 0);
+ WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_BOT, adev->gmc.agp_start >> 24);
+ WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_TOP, adev->gmc.agp_end >> 24);
+
+ /*
+ * the new L1 policy will block SRIOV guest from writing
+ * these regs, and they will be programed at host.
+ * so skip programing these regs.
+ */
+ /* Program the system aperture low logical page number. */
+ WREG32_SOC15(MMHUB, 0, regMMMC_VM_SYSTEM_APERTURE_LOW_ADDR,
+ min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
+ WREG32_SOC15(MMHUB, 0, regMMMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+ max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
+
+ /* Set default page address. */
+ value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
+ WREG32_SOC15(MMHUB, 0, regMMMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
+ (u32)(value >> 12));
+ WREG32_SOC15(MMHUB, 0, regMMMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
+ (u32)(value >> 44));
+
+ /* Program "protection fault". */
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
+ (u32)(adev->dummy_page_addr >> 12));
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
+ (u32)((u64)adev->dummy_page_addr >> 44));
+
+ tmp = RREG32_SOC15(MMHUB, 0, regMMVM_L2_PROTECTION_FAULT_CNTL2);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL2,
+ ACTIVE_PAGE_MIGRATION_PTE_READ_RETRY, 1);
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_PROTECTION_FAULT_CNTL2, tmp);
+}
+
+static void mmhub_v3_3_init_tlb_regs(struct amdgpu_device *adev)
+{
+ uint32_t tmp;
+
+ /* Setup TLB control */
+ tmp = RREG32_SOC15(MMHUB, 0, regMMMC_VM_MX_L1_TLB_CNTL);
+
+ tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 1);
+ tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, 3);
+ tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL,
+ ENABLE_ADVANCED_DRIVER_MODEL, 1);
+ tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL,
+ SYSTEM_APERTURE_UNMAPPED_ACCESS, 0);
+ tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0);
+ tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL,
+ MTYPE, MTYPE_UC); /* UC, uncached */
+
+ WREG32_SOC15(MMHUB, 0, regMMMC_VM_MX_L1_TLB_CNTL, tmp);
+}
+
+static void mmhub_v3_3_init_cache_regs(struct amdgpu_device *adev)
+{
+ uint32_t tmp;
+
+ /* Setup L2 cache */
+ tmp = RREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, ENABLE_L2_CACHE, 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING, 0);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL,
+ ENABLE_DEFAULT_PAGE_OUT_TO_SYSTEM_MEMORY, 1);
+ /* XXX for emulation, Refer to closed source code.*/
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, L2_PDE0_CACHE_TAG_GENERATION_MODE,
+ 0);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, PDE_FAULT_CLASSIFICATION, 0);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, IDENTITY_MODE_FRAGMENT_SIZE, 0);
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL, tmp);
+
+ tmp = RREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL2);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL2, tmp);
+
+ tmp = regMMVM_L2_CNTL3_DEFAULT;
+ if (adev->gmc.translate_further) {
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL3, BANK_SELECT, 12);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL3,
+ L2_CACHE_BIGK_FRAGMENT_SIZE, 9);
+ } else {
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL3, BANK_SELECT, 9);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL3,
+ L2_CACHE_BIGK_FRAGMENT_SIZE, 6);
+ }
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL3, tmp);
+
+ tmp = regMMVM_L2_CNTL4_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL4, VMC_TAP_PDE_REQUEST_PHYSICAL, 0);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL4, VMC_TAP_PTE_REQUEST_PHYSICAL, 0);
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL4, tmp);
+
+ tmp = regMMVM_L2_CNTL5_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL5, L2_CACHE_SMALLK_FRAGMENT_SIZE, 0);
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL5, tmp);
+}
+
+static void mmhub_v3_3_enable_system_domain(struct amdgpu_device *adev)
+{
+ uint32_t tmp;
+
+ tmp = RREG32_SOC15(MMHUB, 0, regMMVM_CONTEXT0_CNTL);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH, 0);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT0_CNTL,
+ RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
+
+ WREG32_SOC15(MMHUB, 0, regMMVM_CONTEXT0_CNTL, tmp);
+}
+
+static void mmhub_v3_3_disable_identity_aperture(struct amdgpu_device *adev)
+{
+ WREG32_SOC15(MMHUB, 0,
+ regMMVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32,
+ 0xFFFFFFFF);
+ WREG32_SOC15(MMHUB, 0,
+ regMMVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32,
+ 0x0000000F);
+
+ WREG32_SOC15(MMHUB, 0,
+ regMMVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_LO32, 0);
+ WREG32_SOC15(MMHUB, 0,
+ regMMVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_HI32, 0);
+
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_LO32,
+ 0);
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_HI32,
+ 0);
+}
+
+static void mmhub_v3_3_setup_vmid_config(struct amdgpu_device *adev)
+{
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
+ int i;
+ uint32_t tmp;
+
+ for (i = 0; i <= 14; i++) {
+ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL, i * hub->ctx_distance);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
+ adev->vm_manager.num_level);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT,
+ 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
+ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
+ VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
+ READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
+ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
+ EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
+ PAGE_TABLE_BLOCK_SIZE,
+ adev->vm_manager.block_size - 9);
+ /* Send no-retry XNACK on fault to suppress VM fault storm. */
+ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
+ RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
+ !amdgpu_noretry);
+ WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL,
+ i * hub->ctx_distance, tmp);
+ WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
+ i * hub->ctx_addr_distance, 0);
+ WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_PAGE_TABLE_START_ADDR_HI32,
+ i * hub->ctx_addr_distance, 0);
+ WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_PAGE_TABLE_END_ADDR_LO32,
+ i * hub->ctx_addr_distance,
+ lower_32_bits(adev->vm_manager.max_pfn - 1));
+ WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_PAGE_TABLE_END_ADDR_HI32,
+ i * hub->ctx_addr_distance,
+ upper_32_bits(adev->vm_manager.max_pfn - 1));
+ }
+
+ hub->vm_cntx_cntl = tmp;
+}
+
+static void mmhub_v3_3_program_invalidation(struct amdgpu_device *adev)
+{
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
+ unsigned int i;
+
+ for (i = 0; i < 18; ++i) {
+ WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_INVALIDATE_ENG0_ADDR_RANGE_LO32,
+ i * hub->eng_addr_distance, 0xffffffff);
+ WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_INVALIDATE_ENG0_ADDR_RANGE_HI32,
+ i * hub->eng_addr_distance, 0x1f);
+ }
+}
+
+static int mmhub_v3_3_gart_enable(struct amdgpu_device *adev)
+{
+ /* GART Enable. */
+ mmhub_v3_3_init_gart_aperture_regs(adev);
+ mmhub_v3_3_init_system_aperture_regs(adev);
+ mmhub_v3_3_init_tlb_regs(adev);
+ mmhub_v3_3_init_cache_regs(adev);
+
+ mmhub_v3_3_enable_system_domain(adev);
+ mmhub_v3_3_disable_identity_aperture(adev);
+ mmhub_v3_3_setup_vmid_config(adev);
+ mmhub_v3_3_program_invalidation(adev);
+
+ return 0;
+}
+
+static void mmhub_v3_3_gart_disable(struct amdgpu_device *adev)
+{
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
+ u32 tmp;
+ u32 i;
+
+ /* Disable all tables */
+ for (i = 0; i < 16; i++)
+ WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT0_CNTL,
+ i * hub->ctx_distance, 0);
+
+ /* Setup TLB control */
+ tmp = RREG32_SOC15(MMHUB, 0, regMMMC_VM_MX_L1_TLB_CNTL);
+ tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 0);
+ tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL,
+ ENABLE_ADVANCED_DRIVER_MODEL, 0);
+ WREG32_SOC15(MMHUB, 0, regMMMC_VM_MX_L1_TLB_CNTL, tmp);
+
+ /* Setup L2 cache */
+ tmp = RREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, ENABLE_L2_CACHE, 0);
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL, tmp);
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL3, 0);
+}
+
+/**
+ * mmhub_v3_3_set_fault_enable_default - update GART/VM fault handling
+ *
+ * @adev: amdgpu_device pointer
+ * @value: true redirects VM faults to the default page
+ */
+static void mmhub_v3_3_set_fault_enable_default(struct amdgpu_device *adev,
+ bool value)
+{
+ u32 tmp;
+
+ tmp = RREG32_SOC15(MMHUB, 0, regMMVM_L2_PROTECTION_FAULT_CNTL);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ PDE1_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ PDE2_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ TRANSLATE_FURTHER_PROTECTION_FAULT_ENABLE_DEFAULT,
+ value);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ NACK_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ if (!value) {
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ CRASH_ON_NO_RETRY_FAULT, 1);
+ tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
+ CRASH_ON_RETRY_FAULT, 1);
+ }
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_PROTECTION_FAULT_CNTL, tmp);
+}
+
+static const struct amdgpu_vmhub_funcs mmhub_v3_3_vmhub_funcs = {
+ .print_l2_protection_fault_status = mmhub_v3_3_print_l2_protection_fault_status,
+ .get_invalidate_req = mmhub_v3_3_get_invalidate_req,
+};
+
+static void mmhub_v3_3_init(struct amdgpu_device *adev)
+{
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
+
+ hub->ctx0_ptb_addr_lo32 =
+ SOC15_REG_OFFSET(MMHUB, 0,
+ regMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32);
+ hub->ctx0_ptb_addr_hi32 =
+ SOC15_REG_OFFSET(MMHUB, 0,
+ regMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
+ hub->vm_inv_eng0_sem =
+ SOC15_REG_OFFSET(MMHUB, 0, regMMVM_INVALIDATE_ENG0_SEM);
+ hub->vm_inv_eng0_req =
+ SOC15_REG_OFFSET(MMHUB, 0, regMMVM_INVALIDATE_ENG0_REQ);
+ hub->vm_inv_eng0_ack =
+ SOC15_REG_OFFSET(MMHUB, 0, regMMVM_INVALIDATE_ENG0_ACK);
+ hub->vm_context0_cntl =
+ SOC15_REG_OFFSET(MMHUB, 0, regMMVM_CONTEXT0_CNTL);
+ hub->vm_l2_pro_fault_status =
+ SOC15_REG_OFFSET(MMHUB, 0, regMMVM_L2_PROTECTION_FAULT_STATUS);
+ hub->vm_l2_pro_fault_cntl =
+ SOC15_REG_OFFSET(MMHUB, 0, regMMVM_L2_PROTECTION_FAULT_CNTL);
+
+ hub->ctx_distance = regMMVM_CONTEXT1_CNTL - regMMVM_CONTEXT0_CNTL;
+ hub->ctx_addr_distance = regMMVM_CONTEXT1_PAGE_TABLE_BASE_ADDR_LO32 -
+ regMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32;
+ hub->eng_distance = regMMVM_INVALIDATE_ENG1_REQ -
+ regMMVM_INVALIDATE_ENG0_REQ;
+ hub->eng_addr_distance = regMMVM_INVALIDATE_ENG1_ADDR_RANGE_LO32 -
+ regMMVM_INVALIDATE_ENG0_ADDR_RANGE_LO32;
+
+ hub->vm_cntx_cntl_vm_fault = MMVM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ MMVM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ MMVM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ MMVM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ MMVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ MMVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
+ MMVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK;
+
+ hub->vmhub_funcs = &mmhub_v3_3_vmhub_funcs;
+}
+
+static u64 mmhub_v3_3_get_fb_location(struct amdgpu_device *adev)
+{
+ u64 base;
+
+ base = RREG32_SOC15(MMHUB, 0, regMMMC_VM_FB_LOCATION_BASE);
+ base &= MMMC_VM_FB_LOCATION_BASE__FB_BASE_MASK;
+ base <<= 24;
+
+ return base;
+}
+
+static u64 mmhub_v3_3_get_mc_fb_offset(struct amdgpu_device *adev)
+{
+ u64 offset;
+
+ offset = RREG32_SOC15(MMHUB, 0, regMMMC_VM_FB_OFFSET);
+ offset &= MMMC_VM_FB_OFFSET__FB_OFFSET_MASK;
+ offset <<= 24;
+
+ return offset;
+}
+
+static void mmhub_v3_3_update_medium_grain_clock_gating(struct amdgpu_device *adev,
+ bool enable)
+{
+ uint32_t def, data;
+
+ def = data = RREG32_SOC15(MMHUB, 0, regMM_ATC_L2_MISC_CG);
+
+ if (enable)
+ data |= MM_ATC_L2_MISC_CG__ENABLE_MASK;
+ else
+ data &= ~MM_ATC_L2_MISC_CG__ENABLE_MASK;
+
+ if (def != data)
+ WREG32_SOC15(MMHUB, 0, regMM_ATC_L2_MISC_CG, data);
+}
+
+static void mmhub_v3_3_update_medium_grain_light_sleep(struct amdgpu_device *adev,
+ bool enable)
+{
+ uint32_t def, data;
+
+ def = data = RREG32_SOC15(MMHUB, 0, regMM_ATC_L2_MISC_CG);
+
+ if (enable)
+ data |= MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK;
+ else
+ data &= ~MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK;
+
+ if (def != data)
+ WREG32_SOC15(MMHUB, 0, regMM_ATC_L2_MISC_CG, data);
+}
+
+static int mmhub_v3_3_set_clockgating(struct amdgpu_device *adev,
+ enum amd_clockgating_state state)
+{
+ if (amdgpu_sriov_vf(adev))
+ return 0;
+
+ mmhub_v3_3_update_medium_grain_clock_gating(adev,
+ state == AMD_CG_STATE_GATE);
+ mmhub_v3_3_update_medium_grain_light_sleep(adev,
+ state == AMD_CG_STATE_GATE);
+ return 0;
+}
+
+static void mmhub_v3_3_get_clockgating(struct amdgpu_device *adev, u64 *flags)
+{
+ int data;
+
+ if (amdgpu_sriov_vf(adev))
+ *flags = 0;
+
+ data = RREG32_SOC15(MMHUB, 0, regMM_ATC_L2_MISC_CG);
+
+ /* AMD_CG_SUPPORT_MC_MGCG */
+ if (data & MM_ATC_L2_MISC_CG__ENABLE_MASK)
+ *flags |= AMD_CG_SUPPORT_MC_MGCG;
+
+ /* AMD_CG_SUPPORT_MC_LS */
+ if (data & MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK)
+ *flags |= AMD_CG_SUPPORT_MC_LS;
+}
+
+const struct amdgpu_mmhub_funcs mmhub_v3_3_funcs = {
+ .init = mmhub_v3_3_init,
+ .get_fb_location = mmhub_v3_3_get_fb_location,
+ .get_mc_fb_offset = mmhub_v3_3_get_mc_fb_offset,
+ .gart_enable = mmhub_v3_3_gart_enable,
+ .set_fault_enable_default = mmhub_v3_3_set_fault_enable_default,
+ .gart_disable = mmhub_v3_3_gart_disable,
+ .set_clockgating = mmhub_v3_3_set_clockgating,
+ .get_clockgating = mmhub_v3_3_get_clockgating,
+ .setup_vm_pt_regs = mmhub_v3_3_setup_vm_pt_regs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.h b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.h
new file mode 100644
index 000000000000..37b62c7e5a4a
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __MMHUB_V3_3_H__
+#define __MMHUB_V3_3_H__
+
+extern const struct amdgpu_mmhub_funcs mmhub_v3_3_funcs;
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
index 5718e4d40e66..1b7da4aff2b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
@@ -308,7 +308,7 @@ static void mmhub_v9_4_setup_vmid_config(struct amdgpu_device *adev, int hubid)
for (i = 0; i <= 14; i++) {
tmp = RREG32_SOC15_OFFSET(MMHUB, 0, mmVML2VC0_VM_CONTEXT1_CNTL,
- hubid * MMHUB_INSTANCE_REGISTER_OFFSET + i);
+ hubid * MMHUB_INSTANCE_REGISTER_OFFSET + i * hub->ctx_distance);
tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
ENABLE_CONTEXT, 1);
tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
diff --git a/drivers/gpu/drm/amd/amdgpu/mmsch_v4_0.h b/drivers/gpu/drm/amd/amdgpu/mmsch_v4_0.h
index 796d4f8791e5..ced26cc5123a 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmsch_v4_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/mmsch_v4_0.h
@@ -35,13 +35,11 @@
#define MMSCH_VF_ENGINE_STATUS__PASS 0x1
-#define MMSCH_VF_MAILBOX_RESP__OK 0x1
-#define MMSCH_VF_MAILBOX_RESP__INCOMPLETE 0x2
-
-#define MMSCH_VF_ENGINE_STATUS__PASS 0x1
-
-#define MMSCH_VF_MAILBOX_RESP__OK 0x1
-#define MMSCH_VF_MAILBOX_RESP__INCOMPLETE 0x2
+#define MMSCH_VF_MAILBOX_RESP__OK 0x1
+#define MMSCH_VF_MAILBOX_RESP__INCOMPLETE 0x2
+#define MMSCH_VF_MAILBOX_RESP__FAILED 0x3
+#define MMSCH_VF_MAILBOX_RESP__FAILED_SMALL_CTX_SIZE 0x4
+#define MMSCH_VF_MAILBOX_RESP__UNKNOWN_CMD 0x5
#define MMSCH_V4_0_VCN_INSTANCES 0x2
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h
index af1a784696bd..c520b2fabfb9 100644
--- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h
+++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h
@@ -62,7 +62,9 @@ int xgpu_ai_mailbox_add_irq_id(struct amdgpu_device *adev);
int xgpu_ai_mailbox_get_irq(struct amdgpu_device *adev);
void xgpu_ai_mailbox_put_irq(struct amdgpu_device *adev);
-#define AI_MAIBOX_CONTROL_TRN_OFFSET_BYTE SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_MAILBOX_CONTROL) * 4
-#define AI_MAIBOX_CONTROL_RCV_OFFSET_BYTE SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_MAILBOX_CONTROL) * 4 + 1
+#define AI_MAIBOX_CONTROL_TRN_OFFSET_BYTE \
+ (SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_MAILBOX_CONTROL) * 4)
+#define AI_MAIBOX_CONTROL_RCV_OFFSET_BYTE \
+ (SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_MAILBOX_CONTROL) * 4 + 1)
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
index b6a8478dabf4..e64b33115848 100644
--- a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
@@ -107,7 +107,7 @@ force_update_wptr_for_self_int(struct amdgpu_device *adev,
{
u32 ih_cntl, ih_rb_cntl;
- if (adev->ip_versions[OSSSYS_HWIP][0] < IP_VERSION(5, 0, 3))
+ if (amdgpu_ip_version(adev, OSSSYS_HWIP, 0) < IP_VERSION(5, 0, 3))
return;
ih_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_CNTL2);
@@ -330,7 +330,7 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev)
if (unlikely(adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT)) {
if (ih[0]->use_bus_addr) {
- switch (adev->ip_versions[OSSSYS_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, OSSSYS_HWIP, 0)) {
case IP_VERSION(5, 0, 3):
case IP_VERSION(5, 2, 0):
case IP_VERSION(5, 2, 1):
@@ -665,8 +665,6 @@ static void navi10_ih_update_clockgating_state(struct amdgpu_device *adev,
if (def != data)
WREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL, data);
}
-
- return;
}
static int navi10_ih_set_clockgating_state(void *handle,
@@ -691,8 +689,6 @@ static void navi10_ih_get_clockgating_state(void *handle, u64 *flags)
if (!RREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL))
*flags |= AMD_CG_SUPPORT_IH_CG;
-
- return;
}
static const struct amd_ip_funcs navi10_ih_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
index 4038455d7998..df218d5ca775 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
@@ -28,6 +28,7 @@
#include "nbio/nbio_2_3_offset.h"
#include "nbio/nbio_2_3_sh_mask.h"
#include <uapi/linux/kfd_ioctl.h>
+#include <linux/device.h>
#include <linux/pci.h>
#define smnPCIE_CONFIG_CNTL 0x11180044
@@ -361,7 +362,7 @@ static void nbio_v2_3_enable_aspm(struct amdgpu_device *adev,
data |= NAVI10_PCIE__LC_L0S_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L0S_INACTIVITY__SHIFT;
- if (pci_is_thunderbolt_attached(adev->pdev))
+ if (dev_is_removable(&adev->pdev->dev))
data |= NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
else
data |= NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
@@ -480,7 +481,7 @@ static void nbio_v2_3_program_aspm(struct amdgpu_device *adev)
def = data = RREG32_PCIE(smnPCIE_LC_CNTL);
data |= NAVI10_PCIE__LC_L0S_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L0S_INACTIVITY__SHIFT;
- if (pci_is_thunderbolt_attached(adev->pdev))
+ if (dev_is_removable(&adev->pdev->dev))
data |= NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
else
data |= NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
@@ -536,7 +537,7 @@ static void nbio_v2_3_clear_doorbell_interrupt(struct amdgpu_device *adev)
{
uint32_t reg, reg_data;
- if (adev->ip_versions[NBIO_HWIP][0] != IP_VERSION(3, 3, 0))
+ if (amdgpu_ip_version(adev, NBIO_HWIP, 0) != IP_VERSION(3, 3, 0))
return;
reg = RREG32_SOC15(NBIO, 0, mmBIF_RB_CNTL);
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c b/drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c
index e5b5b0f4940f..a3622897e3fe 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c
@@ -338,7 +338,7 @@ const struct nbio_hdp_flush_reg nbio_v4_3_hdp_flush_reg = {
static void nbio_v4_3_init_registers(struct amdgpu_device *adev)
{
- if (adev->ip_versions[NBIO_HWIP][0] == IP_VERSION(4, 3, 0)) {
+ if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(4, 3, 0)) {
uint32_t data;
data = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF2_STRAP2);
@@ -392,8 +392,8 @@ static void nbio_v4_3_program_aspm(struct amdgpu_device *adev)
#ifdef CONFIG_PCIEASPM
uint32_t def, data;
- if (!(adev->ip_versions[PCIE_HWIP][0] == IP_VERSION(7, 4, 0)) &&
- !(adev->ip_versions[PCIE_HWIP][0] == IP_VERSION(7, 6, 0)))
+ if (!(amdgpu_ip_version(adev, PCIE_HWIP, 0) == IP_VERSION(7, 4, 0)) &&
+ !(amdgpu_ip_version(adev, PCIE_HWIP, 0) == IP_VERSION(7, 6, 0)))
return;
def = data = RREG32_SOC15(NBIO, 0, regPCIE_LC_CNTL);
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c
new file mode 100644
index 000000000000..1f52b4b1db03
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "amdgpu_atombios.h"
+#include "nbio_v7_11.h"
+
+#include "nbio/nbio_7_11_0_offset.h"
+#include "nbio/nbio_7_11_0_sh_mask.h"
+#include <uapi/linux/kfd_ioctl.h>
+
+static void nbio_v7_11_remap_hdp_registers(struct amdgpu_device *adev)
+{
+ WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL,
+ adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL);
+ WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_REG_FLUSH_CNTL,
+ adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_REG_FLUSH_CNTL);
+}
+
+static u32 nbio_v7_11_get_rev_id(struct amdgpu_device *adev)
+{
+ u32 tmp;
+
+ tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP1_RCC_DEV0_EPF0_STRAP0);
+ tmp &= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0_MASK;
+ tmp >>= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0__SHIFT;
+
+ return tmp;
+}
+
+static void nbio_v7_11_mc_access_enable(struct amdgpu_device *adev, bool enable)
+{
+ if (enable)
+ WREG32_SOC15(NBIO, 0, regBIF_BX1_BIF_FB_EN,
+ BIF_BX1_BIF_FB_EN__FB_READ_EN_MASK |
+ BIF_BX1_BIF_FB_EN__FB_WRITE_EN_MASK);
+ else
+ WREG32_SOC15(NBIO, 0, regBIF_BX1_BIF_FB_EN, 0);
+}
+
+static u32 nbio_v7_11_get_memsize(struct amdgpu_device *adev)
+{
+ return RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF0_0_RCC_CONFIG_MEMSIZE);
+}
+
+static void nbio_v7_11_sdma_doorbell_range(struct amdgpu_device *adev, int instance,
+ bool use_doorbell, int doorbell_index,
+ int doorbell_size)
+{
+ u32 reg = SOC15_REG_OFFSET(NBIO, 0, regGDC0_BIF_CSDMA_DOORBELL_RANGE);
+ u32 doorbell_range = RREG32_PCIE_PORT(reg);
+
+ if (use_doorbell) {
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC0_BIF_CSDMA_DOORBELL_RANGE,
+ OFFSET, doorbell_index);
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC0_BIF_CSDMA_DOORBELL_RANGE,
+ SIZE, doorbell_size);
+ } else {
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC0_BIF_CSDMA_DOORBELL_RANGE,
+ SIZE, 0);
+ }
+
+ WREG32_PCIE_PORT(reg, doorbell_range);
+}
+
+static void nbio_v7_11_vpe_doorbell_range(struct amdgpu_device *adev, int instance,
+ bool use_doorbell, int doorbell_index,
+ int doorbell_size)
+{
+ u32 reg = SOC15_REG_OFFSET(NBIO, 0, regGDC0_BIF_VPE_DOORBELL_RANGE);
+ u32 doorbell_range = RREG32_PCIE_PORT(reg);
+
+ if (use_doorbell) {
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC0_BIF_VPE_DOORBELL_RANGE,
+ OFFSET, doorbell_index);
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC0_BIF_VPE_DOORBELL_RANGE,
+ SIZE, doorbell_size);
+ } else {
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC0_BIF_VPE_DOORBELL_RANGE,
+ SIZE, 0);
+ }
+
+ WREG32_PCIE_PORT(reg, doorbell_range);
+}
+
+static void nbio_v7_11_vcn_doorbell_range(struct amdgpu_device *adev,
+ bool use_doorbell,
+ int doorbell_index, int instance)
+{
+ u32 reg = SOC15_REG_OFFSET(NBIO, 0, regGDC0_BIF_VCN0_DOORBELL_RANGE);
+ u32 doorbell_range = RREG32_PCIE_PORT(reg);
+
+ if (use_doorbell) {
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC0_BIF_VCN0_DOORBELL_RANGE, OFFSET,
+ doorbell_index);
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC0_BIF_VCN0_DOORBELL_RANGE, SIZE, 8);
+ } else {
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC0_BIF_VCN0_DOORBELL_RANGE, SIZE, 0);
+ }
+
+ WREG32_PCIE_PORT(reg, doorbell_range);
+}
+
+static void nbio_v7_11_enable_doorbell_aperture(struct amdgpu_device *adev,
+ bool enable)
+{
+ u32 reg;
+
+
+ reg = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF0_0_RCC_DOORBELL_APER_EN);
+ reg = REG_SET_FIELD(reg, RCC_DEV0_EPF0_0_RCC_DOORBELL_APER_EN,
+ BIF_DOORBELL_APER_EN, enable ? 1 : 0);
+
+ WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF0_0_RCC_DOORBELL_APER_EN, reg);
+}
+
+static void nbio_v7_11_enable_doorbell_selfring_aperture(struct amdgpu_device *adev,
+ bool enable)
+{
+ u32 tmp = 0;
+
+ if (enable) {
+ tmp = REG_SET_FIELD(tmp, BIF_BX_PF1_DOORBELL_SELFRING_GPA_APER_CNTL,
+ DOORBELL_SELFRING_GPA_APER_EN, 1) |
+ REG_SET_FIELD(tmp, BIF_BX_PF1_DOORBELL_SELFRING_GPA_APER_CNTL,
+ DOORBELL_SELFRING_GPA_APER_MODE, 1) |
+ REG_SET_FIELD(tmp, BIF_BX_PF1_DOORBELL_SELFRING_GPA_APER_CNTL,
+ DOORBELL_SELFRING_GPA_APER_SIZE, 0);
+
+ WREG32_SOC15(NBIO, 0,
+ regBIF_BX_PF1_DOORBELL_SELFRING_GPA_APER_BASE_LOW,
+ lower_32_bits(adev->doorbell.base));
+ WREG32_SOC15(NBIO, 0,
+ regBIF_BX_PF1_DOORBELL_SELFRING_GPA_APER_BASE_HIGH,
+ upper_32_bits(adev->doorbell.base));
+ }
+
+ WREG32_SOC15(NBIO, 0, regBIF_BX_PF1_DOORBELL_SELFRING_GPA_APER_CNTL, tmp);
+}
+
+
+static void nbio_v7_11_ih_doorbell_range(struct amdgpu_device *adev,
+ bool use_doorbell, int doorbell_index)
+{
+ u32 ih_doorbell_range = RREG32_SOC15(NBIO, 0,regGDC0_BIF_IH_DOORBELL_RANGE);
+
+ if (use_doorbell) {
+ ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
+ GDC0_BIF_IH_DOORBELL_RANGE, OFFSET,
+ doorbell_index);
+ ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
+ GDC0_BIF_IH_DOORBELL_RANGE, SIZE,
+ 2);
+ } else {
+ ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
+ GDC0_BIF_IH_DOORBELL_RANGE, SIZE,
+ 0);
+ }
+
+ WREG32_SOC15(NBIO, 0, regGDC0_BIF_IH_DOORBELL_RANGE,
+ ih_doorbell_range);
+}
+
+static void nbio_v7_11_ih_control(struct amdgpu_device *adev)
+{
+ u32 interrupt_cntl;
+
+ /* setup interrupt control */
+ WREG32_SOC15(NBIO, 0, regBIF_BX1_INTERRUPT_CNTL2,
+ adev->dummy_page_addr >> 8);
+
+ interrupt_cntl = RREG32_SOC15(NBIO, 0, regBIF_BX1_INTERRUPT_CNTL);
+ /*
+ * INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK=0 - dummy read disabled with msi, enabled without msi
+ * INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK=1 - dummy read controlled by IH_DUMMY_RD_EN
+ */
+ interrupt_cntl = REG_SET_FIELD(interrupt_cntl, BIF_BX1_INTERRUPT_CNTL,
+ IH_DUMMY_RD_OVERRIDE, 0);
+
+ /* INTERRUPT_CNTL__IH_REQ_NONSNOOP_EN_MASK=1 if ring is in non-cacheable memory, e.g., vram */
+ interrupt_cntl = REG_SET_FIELD(interrupt_cntl, BIF_BX1_INTERRUPT_CNTL,
+ IH_REQ_NONSNOOP_EN, 0);
+
+ WREG32_SOC15(NBIO, 0, regBIF_BX1_INTERRUPT_CNTL, interrupt_cntl);
+}
+
+static u32 nbio_v7_11_get_hdp_flush_req_offset(struct amdgpu_device *adev)
+{
+ return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF1_GPU_HDP_FLUSH_REQ);
+}
+
+static u32 nbio_v7_11_get_hdp_flush_done_offset(struct amdgpu_device *adev)
+{
+ return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF1_GPU_HDP_FLUSH_DONE);
+}
+
+static u32 nbio_v7_11_get_pcie_index_offset(struct amdgpu_device *adev)
+{
+ return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX1_PCIE_INDEX2);
+}
+
+static u32 nbio_v7_11_get_pcie_data_offset(struct amdgpu_device *adev)
+{
+ return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX1_PCIE_DATA2);
+}
+
+static u32 nbio_v7_11_get_pcie_port_index_offset(struct amdgpu_device *adev)
+{
+ return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF1_RSMU_INDEX);
+}
+
+static u32 nbio_v7_11_get_pcie_port_data_offset(struct amdgpu_device *adev)
+{
+ return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF1_RSMU_DATA);
+}
+
+const struct nbio_hdp_flush_reg nbio_v7_11_hdp_flush_reg = {
+ .ref_and_mask_cp0 = BIF_BX_PF1_GPU_HDP_FLUSH_DONE__CP0_MASK,
+ .ref_and_mask_cp1 = BIF_BX_PF1_GPU_HDP_FLUSH_DONE__CP1_MASK,
+ .ref_and_mask_cp2 = BIF_BX_PF1_GPU_HDP_FLUSH_DONE__CP2_MASK,
+ .ref_and_mask_cp3 = BIF_BX_PF1_GPU_HDP_FLUSH_DONE__CP3_MASK,
+ .ref_and_mask_cp4 = BIF_BX_PF1_GPU_HDP_FLUSH_DONE__CP4_MASK,
+ .ref_and_mask_cp5 = BIF_BX_PF1_GPU_HDP_FLUSH_DONE__CP5_MASK,
+ .ref_and_mask_cp6 = BIF_BX_PF1_GPU_HDP_FLUSH_DONE__CP6_MASK,
+ .ref_and_mask_cp7 = BIF_BX_PF1_GPU_HDP_FLUSH_DONE__CP7_MASK,
+ .ref_and_mask_cp8 = BIF_BX_PF1_GPU_HDP_FLUSH_DONE__CP8_MASK,
+ .ref_and_mask_cp9 = BIF_BX_PF1_GPU_HDP_FLUSH_DONE__CP9_MASK,
+ .ref_and_mask_sdma0 = BIF_BX_PF1_GPU_HDP_FLUSH_DONE__SDMA0_MASK,
+ .ref_and_mask_sdma1 = BIF_BX_PF1_GPU_HDP_FLUSH_DONE__SDMA1_MASK,
+};
+
+static void nbio_v7_11_init_registers(struct amdgpu_device *adev)
+{
+ uint32_t def, data;
+
+ def = data = RREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3);
+ data = REG_SET_FIELD(data, BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3,
+ CI_SWUS_MAX_READ_REQUEST_SIZE_MODE, 1);
+ data = REG_SET_FIELD(data, BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3,
+ CI_SWUS_MAX_READ_REQUEST_SIZE_PRIV, 1);
+
+ if (def != data)
+ WREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3, data);
+
+}
+
+static void nbio_v7_11_update_medium_grain_clock_gating(struct amdgpu_device *adev,
+ bool enable)
+{
+ uint32_t def, data;
+
+ if (!(adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG))
+ return;
+
+ def = data = RREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL);
+ if (enable) {
+ data |= (BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK |
+ BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__TXCLK_DYN_GATE_ENABLE_MASK |
+ BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__TXCLK_LCNT_GATE_ENABLE_MASK |
+ BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__TXCLK_REGS_GATE_ENABLE_MASK |
+ BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__TXCLK_PRBS_GATE_ENABLE_MASK |
+ BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__REFCLK_REGS_GATE_ENABLE_MASK);
+ } else {
+ data &= ~(BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK |
+ BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__TXCLK_DYN_GATE_ENABLE_MASK |
+ BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__TXCLK_LCNT_GATE_ENABLE_MASK |
+ BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__TXCLK_REGS_GATE_ENABLE_MASK |
+ BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__TXCLK_PRBS_GATE_ENABLE_MASK |
+ BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__REFCLK_REGS_GATE_ENABLE_MASK);
+ }
+
+ if (def != data)
+ WREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL, data);
+}
+
+static void nbio_v7_11_update_medium_grain_light_sleep(struct amdgpu_device *adev,
+ bool enable)
+{
+ uint32_t def, data;
+
+ if (!(adev->cg_flags & AMD_CG_SUPPORT_BIF_LS))
+ return;
+
+ def = data = RREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_CNTL2);
+ if (enable)
+ data |= BIF_BIF256_CI256_RC3X4_USB4_PCIE_CNTL2__SLV_MEM_LS_EN_MASK;
+ else
+ data &= ~BIF_BIF256_CI256_RC3X4_USB4_PCIE_CNTL2__SLV_MEM_LS_EN_MASK;
+
+ if (def != data)
+ WREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_CNTL2, data);
+
+ def = data = RREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_TX_POWER_CTRL_1);
+ if (enable) {
+ data |= (BIF_BIF256_CI256_RC3X4_USB4_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN_MASK |
+ BIF_BIF256_CI256_RC3X4_USB4_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN_MASK);
+ } else {
+ data &= ~(BIF_BIF256_CI256_RC3X4_USB4_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN_MASK |
+ BIF_BIF256_CI256_RC3X4_USB4_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN_MASK);
+ }
+
+ if (def != data)
+ WREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_TX_POWER_CTRL_1, data);
+}
+
+static void nbio_v7_11_get_clockgating_state(struct amdgpu_device *adev,
+ u64 *flags)
+{
+ uint32_t data;
+
+ /* AMD_CG_SUPPORT_BIF_MGCG */
+ data = RREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL);
+ if (data & BIF_BIF256_CI256_RC3X4_USB4_CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK)
+ *flags |= AMD_CG_SUPPORT_BIF_MGCG;
+
+ /* AMD_CG_SUPPORT_BIF_LS */
+ data = RREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_CNTL2);
+ if (data & BIF_BIF256_CI256_RC3X4_USB4_PCIE_CNTL2__SLV_MEM_LS_EN_MASK)
+ *flags |= AMD_CG_SUPPORT_BIF_LS;
+}
+
+const struct amdgpu_nbio_funcs nbio_v7_11_funcs = {
+ .get_hdp_flush_req_offset = nbio_v7_11_get_hdp_flush_req_offset,
+ .get_hdp_flush_done_offset = nbio_v7_11_get_hdp_flush_done_offset,
+ .get_pcie_index_offset = nbio_v7_11_get_pcie_index_offset,
+ .get_pcie_data_offset = nbio_v7_11_get_pcie_data_offset,
+ .get_pcie_port_index_offset = nbio_v7_11_get_pcie_port_index_offset,
+ .get_pcie_port_data_offset = nbio_v7_11_get_pcie_port_data_offset,
+ .get_rev_id = nbio_v7_11_get_rev_id,
+ .mc_access_enable = nbio_v7_11_mc_access_enable,
+ .get_memsize = nbio_v7_11_get_memsize,
+ .sdma_doorbell_range = nbio_v7_11_sdma_doorbell_range,
+ .vcn_doorbell_range = nbio_v7_11_vcn_doorbell_range,
+ .vpe_doorbell_range = nbio_v7_11_vpe_doorbell_range,
+ .enable_doorbell_aperture = nbio_v7_11_enable_doorbell_aperture,
+ .enable_doorbell_selfring_aperture = nbio_v7_11_enable_doorbell_selfring_aperture,
+ .ih_doorbell_range = nbio_v7_11_ih_doorbell_range,
+ .update_medium_grain_clock_gating = nbio_v7_11_update_medium_grain_clock_gating,
+ .update_medium_grain_light_sleep = nbio_v7_11_update_medium_grain_light_sleep,
+ .get_clockgating_state = nbio_v7_11_get_clockgating_state,
+ .ih_control = nbio_v7_11_ih_control,
+ .init_registers = nbio_v7_11_init_registers,
+ .remap_hdp_registers = nbio_v7_11_remap_hdp_registers,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.h b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.h
new file mode 100644
index 000000000000..9d8258ed3f0a
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __NBIO_V7_11_H__
+#define __NBIO_V7_11_H__
+
+#include "soc15_common.h"
+
+extern const struct nbio_hdp_flush_reg nbio_v7_11_hdp_flush_reg;
+extern const struct amdgpu_nbio_funcs nbio_v7_11_funcs;
+extern const struct amdgpu_nbio_ras_funcs nbio_v7_11_ras_funcs;
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c
index 4ef1fa4603c8..e962821ae6a1 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c
@@ -59,7 +59,7 @@ static u32 nbio_v7_2_get_rev_id(struct amdgpu_device *adev)
{
u32 tmp;
- switch (adev->ip_versions[NBIO_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
case IP_VERSION(7, 2, 1):
case IP_VERSION(7, 3, 0):
case IP_VERSION(7, 5, 0):
@@ -78,7 +78,7 @@ static u32 nbio_v7_2_get_rev_id(struct amdgpu_device *adev)
static void nbio_v7_2_mc_access_enable(struct amdgpu_device *adev, bool enable)
{
- switch (adev->ip_versions[NBIO_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
case IP_VERSION(7, 2, 1):
case IP_VERSION(7, 3, 0):
case IP_VERSION(7, 5, 0):
@@ -262,7 +262,7 @@ static void nbio_v7_2_update_medium_grain_light_sleep(struct amdgpu_device *adev
{
uint32_t def, data;
- switch (adev->ip_versions[NBIO_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
case IP_VERSION(7, 2, 1):
case IP_VERSION(7, 3, 0):
case IP_VERSION(7, 5, 0):
@@ -369,7 +369,7 @@ const struct nbio_hdp_flush_reg nbio_v7_2_hdp_flush_reg = {
static void nbio_v7_2_init_registers(struct amdgpu_device *adev)
{
uint32_t def, data;
- switch (adev->ip_versions[NBIO_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
case IP_VERSION(7, 2, 1):
case IP_VERSION(7, 3, 0):
case IP_VERSION(7, 5, 0):
@@ -394,7 +394,7 @@ static void nbio_v7_2_init_registers(struct amdgpu_device *adev)
break;
}
- switch (adev->ip_versions[NBIO_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
case IP_VERSION(7, 3, 0):
case IP_VERSION(7, 5, 1):
data = RREG32_SOC15(NBIO, 0, regRCC_DEV2_EPF0_STRAP2);
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
index 685abf57ffdd..6d24c84924cb 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
@@ -347,7 +347,7 @@ static void nbio_v7_4_init_registers(struct amdgpu_device *adev)
adev->rmmio_remap.reg_offset = SOC15_REG_OFFSET(NBIO, 0,
mmBIF_BX_DEV0_EPF0_VF0_HDP_MEM_COHERENCY_FLUSH_CNTL) << 2;
- if (adev->ip_versions[NBIO_HWIP][0] == IP_VERSION(7, 4, 4) &&
+ if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 4, 4) &&
!amdgpu_sriov_vf(adev)) {
baco_cntl = RREG32_SOC15(NBIO, 0, mmBACO_CNTL);
if (baco_cntl &
@@ -365,9 +365,12 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device
{
uint32_t bif_doorbell_intr_cntl;
struct ras_manager *obj = amdgpu_ras_find_obj(adev, adev->nbio.ras_if);
- struct ras_err_data err_data = {0, 0, 0, NULL};
+ struct ras_err_data err_data;
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ if (amdgpu_ras_error_data_init(&err_data))
+ return;
+
if (adev->asic_type == CHIP_ALDEBARAN)
bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL_ALDE);
else
@@ -418,6 +421,8 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device
*/
amdgpu_ras_reset_gpu(adev);
}
+
+ amdgpu_ras_error_data_fini(&err_data);
}
static void nbio_v7_4_handle_ras_err_event_athub_intr_no_bifring(struct amdgpu_device *adev)
@@ -702,7 +707,7 @@ static void nbio_v7_4_program_aspm(struct amdgpu_device *adev)
#ifdef CONFIG_PCIEASPM
uint32_t def, data;
- if (adev->ip_versions[NBIO_HWIP][0] == IP_VERSION(7, 4, 4))
+ if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 4, 4))
return;
def = data = RREG32_PCIE(smnPCIE_LC_CNTL);
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c
index def89379b51a..4df1055e640a 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c
@@ -254,7 +254,7 @@ static void nbio_v7_7_update_medium_grain_clock_gating(struct amdgpu_device *ade
{
uint32_t def, data;
- if (enable && !(adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG))
+ if (!(adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG))
return;
def = data = RREG32_SOC15(NBIO, 0, regBIF0_CPM_CONTROL);
@@ -283,7 +283,7 @@ static void nbio_v7_7_update_medium_grain_light_sleep(struct amdgpu_device *adev
{
uint32_t def, data;
- if (enable && !(adev->cg_flags & AMD_CG_SUPPORT_BIF_LS))
+ if (!(adev->cg_flags & AMD_CG_SUPPORT_BIF_LS))
return;
def = data = RREG32_SOC15(NBIO, 0, regBIF0_PCIE_CNTL2);
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c
index f85eec05d218..25a3da83e0fb 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c
@@ -56,8 +56,15 @@ static u32 nbio_v7_9_get_rev_id(struct amdgpu_device *adev)
{
u32 tmp;
+ tmp = IP_VERSION_SUBREV(amdgpu_ip_version_full(adev, NBIO_HWIP, 0));
+ /* If it is VF or subrevision holds a non-zero value, that should be used */
+ if (tmp || amdgpu_sriov_vf(adev))
+ return tmp;
+
+ /* If discovery subrev is not updated, use register version */
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0);
- tmp = REG_GET_FIELD(tmp, RCC_STRAP0_RCC_DEV0_EPF0_STRAP0, STRAP_ATI_REV_ID_DEV0_F0);
+ tmp = REG_GET_FIELD(tmp, RCC_STRAP0_RCC_DEV0_EPF0_STRAP0,
+ STRAP_ATI_REV_ID_DEV0_F0);
return tmp;
}
@@ -173,8 +180,6 @@ static void nbio_v7_9_sdma_doorbell_range(struct amdgpu_device *adev, int instan
default:
break;
}
-
- return;
}
static void nbio_v7_9_vcn_doorbell_range(struct amdgpu_device *adev, bool use_doorbell,
@@ -556,16 +561,18 @@ const struct amdgpu_nbio_funcs nbio_v7_9_funcs = {
static void nbio_v7_9_query_ras_error_count(struct amdgpu_device *adev,
void *ras_error_status)
{
- return;
}
static void nbio_v7_9_handle_ras_controller_intr_no_bifring(struct amdgpu_device *adev)
{
uint32_t bif_doorbell_intr_cntl;
struct ras_manager *obj = amdgpu_ras_find_obj(adev, adev->nbio.ras_if);
- struct ras_err_data err_data = {0, 0, 0, NULL};
+ struct ras_err_data err_data;
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ if (amdgpu_ras_error_data_init(&err_data))
+ return;
+
bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_DOORBELL_INT_CNTL);
if (REG_GET_FIELD(bif_doorbell_intr_cntl,
@@ -604,12 +611,9 @@ static void nbio_v7_9_handle_ras_controller_intr_no_bifring(struct amdgpu_device
dev_info(adev->dev, "RAS controller interrupt triggered "
"by NBIF error\n");
-
- /* ras_controller_int is dedicated for nbif ras error,
- * not the global interrupt for sync flood
- */
- amdgpu_ras_reset_gpu(adev);
}
+
+ amdgpu_ras_error_data_fini(&err_data);
}
static void nbio_v7_9_handle_ras_err_event_athub_intr_no_bifring(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
index 13aca808ecab..4d7976b77767 100644
--- a/drivers/gpu/drm/amd/amdgpu/nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/nv.c
@@ -214,7 +214,7 @@ static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode,
if (adev->vcn.num_vcn_inst == hweight8(adev->vcn.harvest_config))
return -EINVAL;
- switch (adev->ip_versions[UVD_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, UVD_HWIP, 0)) {
case IP_VERSION(3, 0, 0):
case IP_VERSION(3, 0, 64):
case IP_VERSION(3, 0, 192):
@@ -453,7 +453,7 @@ nv_asic_reset_method(struct amdgpu_device *adev)
dev_warn(adev->dev, "Specified reset method:%d isn't supported, using AUTO instead.\n",
amdgpu_reset_method);
- switch (adev->ip_versions[MP1_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(11, 5, 0):
case IP_VERSION(13, 0, 1):
case IP_VERSION(13, 0, 3):
@@ -513,11 +513,10 @@ static int nv_set_vce_clocks(struct amdgpu_device *adev, u32 evclk, u32 ecclk)
static void nv_program_aspm(struct amdgpu_device *adev)
{
- if (!amdgpu_device_should_use_aspm(adev) || !amdgpu_device_aspm_support_quirk())
+ if (!amdgpu_device_should_use_aspm(adev))
return;
- if (!(adev->flags & AMD_IS_APU) &&
- (adev->nbio.funcs->program_aspm))
+ if (adev->nbio.funcs->program_aspm)
adev->nbio.funcs->program_aspm(adev);
}
@@ -609,9 +608,8 @@ static int nv_update_umd_stable_pstate(struct amdgpu_device *adev,
if (adev->gfx.funcs->update_perfmon_mgcg)
adev->gfx.funcs->update_perfmon_mgcg(adev, !enter);
- if (!(adev->flags & AMD_IS_APU) &&
- (adev->nbio.funcs->enable_aspm) &&
- amdgpu_device_should_use_aspm(adev))
+ if (adev->nbio.funcs->enable_aspm &&
+ amdgpu_device_should_use_aspm(adev))
adev->nbio.funcs->enable_aspm(adev, !enter);
return 0;
@@ -669,7 +667,7 @@ static int nv_common_early_init(void *handle)
/* TODO: split the GC and PG flags based on the relevant IP version for which
* they are relevant.
*/
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
AMD_CG_SUPPORT_GFX_CGCG |
@@ -1073,7 +1071,7 @@ static int nv_common_set_clockgating_state(void *handle,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[NBIO_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
case IP_VERSION(2, 3, 0):
case IP_VERSION(2, 3, 1):
case IP_VERSION(2, 3, 2):
@@ -1115,8 +1113,6 @@ static void nv_common_get_clockgating_state(void *handle, u64 *flags)
adev->hdp.funcs->get_clock_gating_state(adev, flags);
adev->smuio.funcs->get_clock_gating_state(adev, flags);
-
- return;
}
static const struct amd_ip_funcs nv_common_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
index 18917df785ec..4bb5e10217bb 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
+++ b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
@@ -293,6 +293,10 @@ enum psp_gfx_fw_type {
GFX_FW_TYPE_RS64_MEC_P1_STACK = 95, /* RS64 MEC stack P1 SOC21 */
GFX_FW_TYPE_RS64_MEC_P2_STACK = 96, /* RS64 MEC stack P2 SOC21 */
GFX_FW_TYPE_RS64_MEC_P3_STACK = 97, /* RS64 MEC stack P3 SOC21 */
+ GFX_FW_TYPE_VPEC_FW1 = 100, /* VPEC FW1 To Save VPE */
+ GFX_FW_TYPE_VPEC_FW2 = 101, /* VPEC FW2 To Save VPE */
+ GFX_FW_TYPE_VPE = 102,
+ GFX_FW_TYPE_P2S_TABLE = 129,
GFX_FW_TYPE_MAX
};
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
index 5f10883da6a2..145186a1e48f 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
@@ -58,9 +58,10 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
return err;
err = psp_init_ta_microcode(psp, ucode_prefix);
- if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 1, 0)) &&
- (adev->pdev->revision == 0xa1) &&
- (psp->securedisplay_context.context.bin_desc.fw_version >= 0x27000008)) {
+ if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 1, 0)) &&
+ (adev->pdev->revision == 0xa1) &&
+ (psp->securedisplay_context.context.bin_desc.fw_version >=
+ 0x27000008)) {
adev->psp.securedisplay_context.context.bin_desc.size_bytes = 0;
}
return err;
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
index 8f84fe40abbb..efa37e3b7931 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
@@ -95,7 +95,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));
- switch (adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 4):
err = psp_init_sos_microcode(psp, ucode_prefix);
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
index 469eed084976..df1844d0800f 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
@@ -59,6 +59,9 @@ MODULE_FIRMWARE("amdgpu/psp_14_0_0_ta.bin");
/* Read USB-PD from LFB */
#define GFX_CMD_USB_PD_USE_LFB 0x480
+/* Retry times for vmbx ready wait */
+#define PSP_VMBX_POLLING_LIMIT 3000
+
/* VBIOS gfl defines */
#define MBOX_READY_MASK 0x80000000
#define MBOX_STATUS_MASK 0x0000FFFF
@@ -79,7 +82,7 @@ static int psp_v13_0_init_microcode(struct psp_context *psp)
amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));
- switch (adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
case IP_VERSION(13, 0, 2):
err = psp_init_sos_microcode(psp, ucode_prefix);
if (err)
@@ -138,7 +141,7 @@ static int psp_v13_0_wait_for_vmbx_ready(struct psp_context *psp)
struct amdgpu_device *adev = psp->adev;
int retry_loop, ret;
- for (retry_loop = 0; retry_loop < 70; retry_loop++) {
+ for (retry_loop = 0; retry_loop < PSP_VMBX_POLLING_LIMIT; retry_loop++) {
/* Wait for bootloader to signify that is
ready having bit 31 of C2PMSG_33 set to 1 */
ret = psp_wait_for(
@@ -158,14 +161,18 @@ static int psp_v13_0_wait_for_vmbx_ready(struct psp_context *psp)
static int psp_v13_0_wait_for_bootloader(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
- int retry_loop, ret;
+ int retry_loop, retry_cnt, ret;
+ retry_cnt =
+ (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 6)) ?
+ PSP_VMBX_POLLING_LIMIT :
+ 10;
/* Wait for bootloader to signify that it is ready having bit 31 of
* C2PMSG_35 set to 1. All other bits are expected to be cleared.
* If there is an error in processing command, bits[7:0] will be set.
* This is applicable for PSP v13.0.6 and newer.
*/
- for (retry_loop = 0; retry_loop < 10; retry_loop++) {
+ for (retry_loop = 0; retry_loop < retry_cnt; retry_loop++) {
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
0x80000000, 0xffffffff, false);
@@ -181,7 +188,7 @@ static int psp_v13_0_wait_for_bootloader_steady_state(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
- if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 6)) {
+ if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 6)) {
psp_v13_0_wait_for_vmbx_ready(psp);
return psp_v13_0_wait_for_bootloader(psp);
@@ -260,6 +267,12 @@ static int psp_v13_0_bootloader_load_ras_drv(struct psp_context *psp)
return psp_v13_0_bootloader_load_component(psp, &psp->ras_drv, PSP_BL__LOAD_RASDRV);
}
+static inline void psp_v13_0_init_sos_version(struct psp_context *psp)
+{
+ struct amdgpu_device *adev = psp->adev;
+
+ psp->sos.fw_version = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_58);
+}
static int psp_v13_0_bootloader_load_sos(struct psp_context *psp)
{
@@ -270,8 +283,10 @@ static int psp_v13_0_bootloader_load_sos(struct psp_context *psp)
/* Check sOS sign of life register to confirm sys driver and sOS
* are already been loaded.
*/
- if (psp_v13_0_is_sos_alive(psp))
+ if (psp_v13_0_is_sos_alive(psp)) {
+ psp_v13_0_init_sos_version(psp);
return 0;
+ }
ret = psp_v13_0_wait_for_bootloader(psp);
if (ret)
@@ -295,6 +310,9 @@ static int psp_v13_0_bootloader_load_sos(struct psp_context *psp)
RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81),
0, true);
+ if (!ret)
+ psp_v13_0_init_sos_version(psp);
+
return ret;
}
@@ -728,7 +746,7 @@ static int psp_v13_0_fatal_error_recovery_quirk(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
- if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 10)) {
+ if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 10)) {
uint32_t reg_data;
/* MP1 fatal error: trigger PSP dram read to unhalt PSP
* during MP1 triggered sync flood.
@@ -745,6 +763,83 @@ static int psp_v13_0_fatal_error_recovery_quirk(struct psp_context *psp)
return 0;
}
+
+static void psp_v13_0_boot_error_reporting(struct amdgpu_device *adev,
+ uint32_t inst,
+ uint32_t boot_error)
+{
+ uint32_t socket_id;
+ uint32_t aid_id;
+ uint32_t hbm_id;
+ uint32_t reg_data;
+
+ socket_id = REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, SOCKET_ID);
+ aid_id = REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, AID_ID);
+ hbm_id = REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, HBM_ID);
+
+ reg_data = RREG32_SOC15(MP0, inst, regMP0_SMN_C2PMSG_109);
+ dev_info(adev->dev, "socket: %d, aid: %d, firmware boot failed, fw status is 0x%x\n",
+ socket_id, aid_id, reg_data);
+
+ if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_MEM_TRAINING))
+ dev_info(adev->dev, "socket: %d, aid: %d, hbm: %d, memory training failed\n",
+ socket_id, aid_id, hbm_id);
+
+ if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_FW_LOAD))
+ dev_info(adev->dev, "socket: %d, aid: %d, firmware load failed at boot time\n",
+ socket_id, aid_id);
+
+ if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_WAFL_LINK_TRAINING))
+ dev_info(adev->dev, "socket: %d, aid: %d, wafl link training failed\n",
+ socket_id, aid_id);
+
+ if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_XGMI_LINK_TRAINING))
+ dev_info(adev->dev, "socket: %d, aid: %d, xgmi link training failed\n",
+ socket_id, aid_id);
+
+ if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_USR_CP_LINK_TRAINING))
+ dev_info(adev->dev, "socket: %d, aid: %d, usr cp link training failed\n",
+ socket_id, aid_id);
+
+ if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_USR_DP_LINK_TRAINING))
+ dev_info(adev->dev, "socket: %d, aid: %d, usr dp link training failed\n",
+ socket_id, aid_id);
+
+ if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_HBM_MEM_TEST))
+ dev_info(adev->dev, "socket: %d, aid: %d, hbm: %d, hbm memory test failed\n",
+ socket_id, aid_id, hbm_id);
+
+ if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_HBM_BIST_TEST))
+ dev_info(adev->dev, "socket: %d, aid: %d, hbm: %d, hbm bist test failed\n",
+ socket_id, aid_id, hbm_id);
+}
+
+static int psp_v13_0_query_boot_status(struct psp_context *psp)
+{
+ struct amdgpu_device *adev = psp->adev;
+ int inst_mask = adev->aid_mask;
+ uint32_t reg_data;
+ uint32_t i;
+ int ret = 0;
+
+ if (amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(13, 0, 6))
+ return 0;
+
+ if (RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_59) < 0x00a10109)
+ return 0;
+
+ for_each_inst(i, inst_mask) {
+ reg_data = RREG32_SOC15(MP0, i, regMP0_SMN_C2PMSG_126);
+ if (!REG_GET_FIELD(reg_data, MP0_SMN_C2PMSG_126, BOOT_STATUS)) {
+ psp_v13_0_boot_error_reporting(adev, i, reg_data);
+ ret = -EINVAL;
+ break;
+ }
+ }
+
+ return ret;
+}
+
static const struct psp_funcs psp_v13_0_funcs = {
.init_microcode = psp_v13_0_init_microcode,
.wait_for_bootloader = psp_v13_0_wait_for_bootloader_steady_state,
@@ -767,6 +862,7 @@ static const struct psp_funcs psp_v13_0_funcs = {
.update_spirom = psp_v13_0_update_spirom,
.vbflash_stat = psp_v13_0_vbflash_status,
.fatal_error_recovery_quirk = psp_v13_0_fatal_error_recovery_quirk,
+ .query_boot_status = psp_v13_0_query_boot_status,
};
void psp_v13_0_set_psp_funcs(struct psp_context *psp)
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c
index d5ba58eba3e2..eaa5512a21da 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c
@@ -40,7 +40,7 @@ static int psp_v13_0_4_init_microcode(struct psp_context *psp)
amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));
- switch (adev->ip_versions[MP0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
case IP_VERSION(13, 0, 4):
err = psp_init_toc_microcode(psp, ucode_prefix);
if (err)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index 51afc92994a8..8d5d86675a7f 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -339,8 +339,6 @@ static void sdma_v2_4_gfx_stop(struct amdgpu_device *adev)
u32 rb_cntl, ib_cntl;
int i;
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
-
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
@@ -474,9 +472,6 @@ static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev)
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
-
- if (adev->mman.buffer_funcs_ring == ring)
- amdgpu_ttm_set_buffer_funcs_status(adev, true);
}
return 0;
@@ -816,9 +811,14 @@ static void sdma_v2_4_ring_emit_wreg(struct amdgpu_ring *ring,
static int sdma_v2_4_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
adev->sdma.num_instances = SDMA_MAX_INSTANCE;
+ r = sdma_v2_4_init_microcode(adev);
+ if (r)
+ return r;
+
sdma_v2_4_set_ring_funcs(adev);
sdma_v2_4_set_buffer_funcs(adev);
sdma_v2_4_set_vm_pte_funcs(adev);
@@ -851,12 +851,6 @@ static int sdma_v2_4_sw_init(void *handle)
if (r)
return r;
- r = sdma_v2_4_init_microcode(adev);
- if (r) {
- DRM_ERROR("Failed to load sdma firmware!\n");
- return r;
- }
-
for (i = 0; i < adev->sdma.num_instances; i++) {
ring = &adev->sdma.instance[i].ring;
ring->ring_obj = NULL;
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 344202870aeb..2ad615be4bb3 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -513,8 +513,6 @@ static void sdma_v3_0_gfx_stop(struct amdgpu_device *adev)
u32 rb_cntl, ib_cntl;
int i;
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
-
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
@@ -746,9 +744,6 @@ static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev)
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
-
- if (adev->mman.buffer_funcs_ring == ring)
- amdgpu_ttm_set_buffer_funcs_status(adev, true);
}
return 0;
@@ -1087,6 +1082,7 @@ static void sdma_v3_0_ring_emit_wreg(struct amdgpu_ring *ring,
static int sdma_v3_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
switch (adev->asic_type) {
case CHIP_STONEY:
@@ -1097,6 +1093,10 @@ static int sdma_v3_0_early_init(void *handle)
break;
}
+ r = sdma_v3_0_init_microcode(adev);
+ if (r)
+ return r;
+
sdma_v3_0_set_ring_funcs(adev);
sdma_v3_0_set_buffer_funcs(adev);
sdma_v3_0_set_vm_pte_funcs(adev);
@@ -1129,12 +1129,6 @@ static int sdma_v3_0_sw_init(void *handle)
if (r)
return r;
- r = sdma_v3_0_init_microcode(adev);
- if (r) {
- DRM_ERROR("Failed to load sdma firmware!\n");
- return r;
- }
-
for (i = 0; i < adev->sdma.num_instances; i++) {
ring = &adev->sdma.instance[i].ring;
ring->ring_obj = NULL;
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
index cd37f45e01a1..3d68dd5523c6 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
@@ -469,7 +469,7 @@ static int sdma_v4_0_irq_id_to_seq(unsigned client_id)
static void sdma_v4_0_init_golden_registers(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
soc15_program_register_sequence(adev,
golden_settings_sdma_4,
@@ -539,7 +539,7 @@ static void sdma_v4_0_setup_ulv(struct amdgpu_device *adev)
* The only chips with SDMAv4 and ULV are VG10 and VG20.
* Server SKUs take a different hysteresis setting from other SKUs.
*/
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
if (adev->pdev->device == 0x6860)
break;
@@ -578,8 +578,10 @@ static int sdma_v4_0_init_microcode(struct amdgpu_device *adev)
int ret, i;
for (i = 0; i < adev->sdma.num_instances; i++) {
- if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 2, 2) ||
- adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 4, 0)) {
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) ==
+ IP_VERSION(4, 2, 2) ||
+ amdgpu_ip_version(adev, SDMA0_HWIP, 0) ==
+ IP_VERSION(4, 4, 0)) {
/* Acturus & Aldebaran will leverage the same FW memory
for every SDMA instance */
ret = amdgpu_sdma_init_microcode(adev, 0, true);
@@ -875,8 +877,6 @@ static void sdma_v4_0_gfx_enable(struct amdgpu_device *adev, bool enable)
u32 rb_cntl, ib_cntl;
int i;
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
-
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32_SDMA(i, mmSDMA0_GFX_RB_CNTL);
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, enable ? 1 : 0);
@@ -911,8 +911,6 @@ static void sdma_v4_0_page_stop(struct amdgpu_device *adev)
u32 rb_cntl, ib_cntl;
int i;
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
-
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32_SDMA(i, mmSDMA0_PAGE_RB_CNTL);
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_PAGE_RB_CNTL,
@@ -978,7 +976,8 @@ static void sdma_v4_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable)
* Arcturus for the moment and firmware version 14
* and above.
*/
- if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 2, 2) &&
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) ==
+ IP_VERSION(4, 2, 2) &&
adev->sdma.instance[i].fw_version >= 14)
WREG32_SDMA(i, mmSDMA0_PUB_DUMMY_REG2, enable);
/* Extend page fault timeout to avoid interrupt storm */
@@ -1255,7 +1254,7 @@ static void sdma_v4_0_init_pg(struct amdgpu_device *adev)
if (!(adev->pg_flags & AMD_PG_SUPPORT_SDMA))
return;
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(4, 1, 0):
case IP_VERSION(4, 1, 1):
case IP_VERSION(4, 1, 2):
@@ -1399,13 +1398,7 @@ static int sdma_v4_0_start(struct amdgpu_device *adev)
r = amdgpu_ring_test_helper(page);
if (r)
return r;
-
- if (adev->mman.buffer_funcs_ring == page)
- amdgpu_ttm_set_buffer_funcs_status(adev, true);
}
-
- if (adev->mman.buffer_funcs_ring == ring)
- amdgpu_ttm_set_buffer_funcs_status(adev, true);
}
return r;
@@ -1698,7 +1691,7 @@ static bool sdma_v4_0_fw_support_paging_queue(struct amdgpu_device *adev)
{
uint fw_version = adev->sdma.instance[0].fw_version;
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
return fw_version >= 430;
case IP_VERSION(4, 0, 1):
@@ -1717,13 +1710,11 @@ static int sdma_v4_0_early_init(void *handle)
int r;
r = sdma_v4_0_init_microcode(adev);
- if (r) {
- DRM_ERROR("Failed to load sdma firmware!\n");
+ if (r)
return r;
- }
/* TODO: Page queue breaks driver reload under SRIOV */
- if ((adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 0, 0)) &&
+ if ((amdgpu_ip_version(adev, SDMA0_HWIP, 0) == IP_VERSION(4, 0, 0)) &&
amdgpu_sriov_vf((adev)))
adev->sdma.has_page_queue = false;
else if (sdma_v4_0_fw_support_paging_queue(adev))
@@ -1748,11 +1739,8 @@ static int sdma_v4_0_late_init(void *handle)
sdma_v4_0_setup_ulv(adev);
- if (!amdgpu_persistent_edc_harvesting_supported(adev)) {
- if (adev->sdma.ras && adev->sdma.ras->ras_block.hw_ops &&
- adev->sdma.ras->ras_block.hw_ops->reset_ras_error_count)
- adev->sdma.ras->ras_block.hw_ops->reset_ras_error_count(adev);
- }
+ if (!amdgpu_persistent_edc_harvesting_supported(adev))
+ amdgpu_ras_reset_error_count(adev, AMDGPU_RAS_BLOCK__SDMA);
return 0;
}
@@ -1823,7 +1811,9 @@ static int sdma_v4_0_sw_init(void *handle)
* On Arcturus, SDMA instance 5~7 has a different vmhub
* type(AMDGPU_MMHUB1).
*/
- if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 2, 2) && i >= 5)
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) ==
+ IP_VERSION(4, 2, 2) &&
+ i >= 5)
ring->vm_hub = AMDGPU_MMHUB1(0);
else
ring->vm_hub = AMDGPU_MMHUB0(0);
@@ -1843,8 +1833,10 @@ static int sdma_v4_0_sw_init(void *handle)
/* paging queue use same doorbell index/routing as gfx queue
* with 0x400 (4096 dwords) offset on second doorbell page
*/
- if (adev->ip_versions[SDMA0_HWIP][0] >= IP_VERSION(4, 0, 0) &&
- adev->ip_versions[SDMA0_HWIP][0] < IP_VERSION(4, 2, 0)) {
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) >=
+ IP_VERSION(4, 0, 0) &&
+ amdgpu_ip_version(adev, SDMA0_HWIP, 0) <
+ IP_VERSION(4, 2, 0)) {
ring->doorbell_index =
adev->doorbell_index.sdma_engine[i] << 1;
ring->doorbell_index += 0x400;
@@ -1856,7 +1848,9 @@ static int sdma_v4_0_sw_init(void *handle)
(adev->doorbell_index.sdma_engine[i] + 1) << 1;
}
- if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 2, 2) && i >= 5)
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) ==
+ IP_VERSION(4, 2, 2) &&
+ i >= 5)
ring->vm_hub = AMDGPU_MMHUB1(0);
else
ring->vm_hub = AMDGPU_MMHUB0(0);
@@ -1890,8 +1884,8 @@ static int sdma_v4_0_sw_fini(void *handle)
amdgpu_ring_fini(&adev->sdma.instance[i].page);
}
- if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 2, 2) ||
- adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 4, 0))
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) == IP_VERSION(4, 2, 2) ||
+ amdgpu_ip_version(adev, SDMA0_HWIP, 0) == IP_VERSION(4, 4, 0))
amdgpu_sdma_destroy_inst_ctx(adev, true);
else
amdgpu_sdma_destroy_inst_ctx(adev, false);
@@ -1917,11 +1911,8 @@ static int sdma_v4_0_hw_fini(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int i;
- if (amdgpu_sriov_vf(adev)) {
- /* disable the scheduler for SDMA */
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
+ if (amdgpu_sriov_vf(adev))
return 0;
- }
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA)) {
for (i = 0; i < adev->sdma.num_instances; i++) {
@@ -1960,7 +1951,6 @@ static int sdma_v4_0_resume(void *handle)
if (adev->in_s0ix) {
sdma_v4_0_enable(adev, true);
sdma_v4_0_gfx_enable(adev, true);
- amdgpu_ttm_set_buffer_funcs_status(adev, true);
return 0;
}
@@ -2036,14 +2026,16 @@ static int sdma_v4_0_process_trap_irq(struct amdgpu_device *adev,
amdgpu_fence_process(&adev->sdma.instance[instance].ring);
break;
case 1:
- if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 2, 0))
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) ==
+ IP_VERSION(4, 2, 0))
amdgpu_fence_process(&adev->sdma.instance[instance].page);
break;
case 2:
/* XXX compute */
break;
case 3:
- if (adev->ip_versions[SDMA0_HWIP][0] != IP_VERSION(4, 2, 0))
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) !=
+ IP_VERSION(4, 2, 0))
amdgpu_fence_process(&adev->sdma.instance[instance].page);
break;
}
@@ -2259,7 +2251,7 @@ static int sdma_v4_0_set_powergating_state(void *handle,
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(4, 1, 0):
case IP_VERSION(4, 1, 1):
case IP_VERSION(4, 1, 2):
@@ -2622,7 +2614,7 @@ static struct amdgpu_sdma_ras sdma_v4_0_ras = {
static void sdma_v4_0_set_ras_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(4, 2, 0):
case IP_VERSION(4, 2, 2):
adev->sdma.ras = &sdma_v4_0_ras;
@@ -2633,7 +2625,6 @@ static void sdma_v4_0_set_ras_funcs(struct amdgpu_device *adev)
default:
break;
}
-
}
const struct amdgpu_ip_block_version sdma_v4_0_ip_block = {
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
index f413898dda37..0f24af6f2810 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
@@ -132,7 +132,8 @@ static int sdma_v4_4_2_init_microcode(struct amdgpu_device *adev)
int ret, i;
for (i = 0; i < adev->sdma.num_instances; i++) {
- if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 4, 2)) {
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) ==
+ IP_VERSION(4, 4, 2)) {
ret = amdgpu_sdma_init_microcode(adev, 0, true);
break;
} else {
@@ -154,13 +155,13 @@ static int sdma_v4_4_2_init_microcode(struct amdgpu_device *adev)
*/
static uint64_t sdma_v4_4_2_ring_get_rptr(struct amdgpu_ring *ring)
{
- u64 *rptr;
+ u64 rptr;
/* XXX check if swapping is necessary on BE */
- rptr = ((u64 *)&ring->adev->wb.wb[ring->rptr_offs]);
+ rptr = READ_ONCE(*((u64 *)&ring->adev->wb.wb[ring->rptr_offs]));
- DRM_DEBUG("rptr before shift == 0x%016llx\n", *rptr);
- return ((*rptr) >> 2);
+ DRM_DEBUG("rptr before shift == 0x%016llx\n", rptr);
+ return rptr >> 2;
}
/**
@@ -426,6 +427,7 @@ static void sdma_v4_4_2_inst_gfx_stop(struct amdgpu_device *adev,
uint32_t inst_mask)
{
struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES];
+ u32 doorbell_offset, doorbell;
u32 rb_cntl, ib_cntl;
int i, unset = 0;
@@ -443,6 +445,18 @@ static void sdma_v4_4_2_inst_gfx_stop(struct amdgpu_device *adev,
ib_cntl = RREG32_SDMA(i, regSDMA_GFX_IB_CNTL);
ib_cntl = REG_SET_FIELD(ib_cntl, SDMA_GFX_IB_CNTL, IB_ENABLE, 0);
WREG32_SDMA(i, regSDMA_GFX_IB_CNTL, ib_cntl);
+
+ if (sdma[i]->use_doorbell) {
+ doorbell = RREG32_SDMA(i, regSDMA_GFX_DOORBELL);
+ doorbell_offset = RREG32_SDMA(i, regSDMA_GFX_DOORBELL_OFFSET);
+
+ doorbell = REG_SET_FIELD(doorbell, SDMA_GFX_DOORBELL, ENABLE, 0);
+ doorbell_offset = REG_SET_FIELD(doorbell_offset,
+ SDMA_GFX_DOORBELL_OFFSET,
+ OFFSET, 0);
+ WREG32_SDMA(i, regSDMA_GFX_DOORBELL, doorbell);
+ WREG32_SDMA(i, regSDMA_GFX_DOORBELL_OFFSET, doorbell_offset);
+ }
}
}
@@ -630,12 +644,6 @@ static void sdma_v4_4_2_gfx_resume(struct amdgpu_device *adev, unsigned int i)
rb_cntl = sdma_v4_4_2_rb_cntl(ring, rb_cntl);
WREG32_SDMA(i, regSDMA_GFX_RB_CNTL, rb_cntl);
- /* Initialize the ring buffer's read and write pointers */
- WREG32_SDMA(i, regSDMA_GFX_RB_RPTR, 0);
- WREG32_SDMA(i, regSDMA_GFX_RB_RPTR_HI, 0);
- WREG32_SDMA(i, regSDMA_GFX_RB_WPTR, 0);
- WREG32_SDMA(i, regSDMA_GFX_RB_WPTR_HI, 0);
-
/* set the wb address whether it's enabled or not */
WREG32_SDMA(i, regSDMA_GFX_RB_RPTR_ADDR_HI,
upper_32_bits(adev->wb.gpu_addr + wb_offset) & 0xFFFFFFFF);
@@ -653,6 +661,12 @@ static void sdma_v4_4_2_gfx_resume(struct amdgpu_device *adev, unsigned int i)
/* before programing wptr to a less value, need set minor_ptr_update first */
WREG32_SDMA(i, regSDMA_GFX_MINOR_PTR_UPDATE, 1);
+ /* Initialize the ring buffer's read and write pointers */
+ WREG32_SDMA(i, regSDMA_GFX_RB_RPTR, 0);
+ WREG32_SDMA(i, regSDMA_GFX_RB_RPTR_HI, 0);
+ WREG32_SDMA(i, regSDMA_GFX_RB_WPTR, 0);
+ WREG32_SDMA(i, regSDMA_GFX_RB_WPTR_HI, 0);
+
doorbell = RREG32_SDMA(i, regSDMA_GFX_DOORBELL);
doorbell_offset = RREG32_SDMA(i, regSDMA_GFX_DOORBELL_OFFSET);
@@ -1231,7 +1245,7 @@ static void sdma_v4_4_2_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t re
static bool sdma_v4_4_2_fw_support_paging_queue(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(4, 4, 2):
return false;
default:
@@ -1245,10 +1259,8 @@ static int sdma_v4_4_2_early_init(void *handle)
int r;
r = sdma_v4_4_2_init_microcode(adev);
- if (r) {
- DRM_ERROR("Failed to load sdma firmware!\n");
+ if (r)
return r;
- }
/* TODO: Page queue breaks driver reload under SRIOV */
if (sdma_v4_4_2_fw_support_paging_queue(adev))
@@ -1277,11 +1289,8 @@ static int sdma_v4_4_2_late_init(void *handle)
.cb = sdma_v4_4_2_process_ras_data_cb,
};
#endif
- if (!amdgpu_persistent_edc_harvesting_supported(adev)) {
- if (adev->sdma.ras && adev->sdma.ras->ras_block.hw_ops &&
- adev->sdma.ras->ras_block.hw_ops->reset_ras_error_count)
- adev->sdma.ras->ras_block.hw_ops->reset_ras_error_count(adev);
- }
+ if (!amdgpu_persistent_edc_harvesting_supported(adev))
+ amdgpu_ras_reset_error_count(adev, AMDGPU_RAS_BLOCK__SDMA);
return 0;
}
@@ -1401,7 +1410,7 @@ static int sdma_v4_4_2_sw_fini(void *handle)
amdgpu_ring_fini(&adev->sdma.instance[i].page);
}
- if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 4, 2))
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) == IP_VERSION(4, 4, 2))
amdgpu_sdma_destroy_inst_ctx(adev, true);
else
amdgpu_sdma_destroy_inst_ctx(adev, false);
@@ -2052,7 +2061,7 @@ const struct amdgpu_ip_block_version sdma_v4_4_2_ip_block = {
.type = AMD_IP_BLOCK_TYPE_SDMA,
.major = 4,
.minor = 4,
- .rev = 0,
+ .rev = 2,
.funcs = &sdma_v4_4_2_ip_funcs,
};
@@ -2131,6 +2140,11 @@ static void sdma_v4_4_2_inst_query_ras_error_count(struct amdgpu_device *adev,
{
struct ras_err_data *err_data = (struct ras_err_data *)ras_err_status;
uint32_t sdma_dev_inst = GET_INST(SDMA0, sdma_inst);
+ unsigned long ue_count = 0;
+ struct amdgpu_smuio_mcm_config_info mcm_info = {
+ .socket_id = adev->smuio.funcs->get_socket_id(adev),
+ .die_id = adev->sdma.instance[sdma_inst].aid_id,
+ };
/* sdma v4_4_2 doesn't support query ce counts */
amdgpu_ras_inst_query_ras_error_count(adev,
@@ -2140,7 +2154,9 @@ static void sdma_v4_4_2_inst_query_ras_error_count(struct amdgpu_device *adev,
ARRAY_SIZE(sdma_v4_4_2_ras_memory_list),
sdma_dev_inst,
AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
- &err_data->ue_count);
+ &ue_count);
+
+ amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count);
}
static void sdma_v4_4_2_query_ras_error_count(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
index 1cc34efb455b..3c485e5a531a 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
@@ -184,7 +184,7 @@ static u32 sdma_v5_0_get_reg_offset(struct amdgpu_device *adev, u32 instance, u3
static void sdma_v5_0_init_golden_registers(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(5, 0, 0):
soc15_program_register_sequence(adev,
golden_settings_sdma_5,
@@ -559,8 +559,6 @@ static void sdma_v5_0_gfx_stop(struct amdgpu_device *adev)
u32 rb_cntl, ib_cntl;
int i;
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
-
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32_SOC15_IP(GC, sdma_v5_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_CNTL));
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
@@ -825,9 +823,6 @@ static int sdma_v5_0_gfx_resume(struct amdgpu_device *adev)
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
-
- if (adev->mman.buffer_funcs_ring == ring)
- amdgpu_ttm_set_buffer_funcs_status(adev, true);
}
return 0;
@@ -1336,6 +1331,11 @@ static void sdma_v5_0_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
static int sdma_v5_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = sdma_v5_0_init_microcode(adev);
+ if (r)
+ return r;
sdma_v5_0_set_ring_funcs(adev);
sdma_v5_0_set_buffer_funcs(adev);
@@ -1367,12 +1367,6 @@ static int sdma_v5_0_sw_init(void *handle)
if (r)
return r;
- r = sdma_v5_0_init_microcode(adev);
- if (r) {
- DRM_ERROR("Failed to load sdma firmware!\n");
- return r;
- }
-
for (i = 0; i < adev->sdma.num_instances; i++) {
ring = &adev->sdma.instance[i].ring;
ring->ring_obj = NULL;
@@ -1427,11 +1421,8 @@ static int sdma_v5_0_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (amdgpu_sriov_vf(adev)) {
- /* disable the scheduler for SDMA */
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
+ if (amdgpu_sriov_vf(adev))
return 0;
- }
sdma_v5_0_ctx_switch_enable(adev, false);
sdma_v5_0_enable(adev, false);
@@ -1697,7 +1688,7 @@ static int sdma_v5_0_set_clockgating_state(void *handle,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(5, 0, 0):
case IP_VERSION(5, 0, 2):
case IP_VERSION(5, 0, 5):
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
index 2b3ebebc4299..0058f3f7cf6e 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
@@ -364,8 +364,6 @@ static void sdma_v5_2_gfx_stop(struct amdgpu_device *adev)
u32 rb_cntl, ib_cntl;
int i;
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
-
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32_SOC15_IP(GC, sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_GFX_RB_CNTL));
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
@@ -625,9 +623,6 @@ static int sdma_v5_2_gfx_resume(struct amdgpu_device *adev)
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
-
- if (adev->mman.buffer_funcs_ring == ring)
- amdgpu_ttm_set_buffer_funcs_status(adev, true);
}
return 0;
@@ -1172,6 +1167,11 @@ static void sdma_v5_2_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
static int sdma_v5_2_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = amdgpu_sdma_init_microcode(adev, 0, true);
+ if (r)
+ return r;
sdma_v5_2_set_ring_funcs(adev);
sdma_v5_2_set_buffer_funcs(adev);
@@ -1231,12 +1231,6 @@ static int sdma_v5_2_sw_init(void *handle)
return r;
}
- r = amdgpu_sdma_init_microcode(adev, 0, true);
- if (r) {
- DRM_ERROR("Failed to load sdma firmware!\n");
- return r;
- }
-
for (i = 0; i < adev->sdma.num_instances; i++) {
ring = &adev->sdma.instance[i].ring;
ring->ring_obj = NULL;
@@ -1285,11 +1279,8 @@ static int sdma_v5_2_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (amdgpu_sriov_vf(adev)) {
- /* disable the scheduler for SDMA */
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
+ if (amdgpu_sriov_vf(adev))
return 0;
- }
sdma_v5_2_ctx_switch_enable(adev, false);
sdma_v5_2_enable(adev, false);
@@ -1510,7 +1501,7 @@ static int sdma_v5_2_process_illegal_inst_irq(struct amdgpu_device *adev,
static bool sdma_v5_2_firmware_mgcg_support(struct amdgpu_device *adev,
int i)
{
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(5, 2, 1):
if (adev->sdma.instance[i].fw_version < 70)
return false;
@@ -1575,8 +1566,9 @@ static void sdma_v5_2_update_medium_grain_light_sleep(struct amdgpu_device *adev
int i;
for (i = 0; i < adev->sdma.num_instances; i++) {
-
- if (adev->sdma.instance[i].fw_version < 70 && adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(5, 2, 1))
+ if (adev->sdma.instance[i].fw_version < 70 &&
+ amdgpu_ip_version(adev, SDMA0_HWIP, 0) ==
+ IP_VERSION(5, 2, 1))
adev->cg_flags &= ~AMD_CG_SUPPORT_SDMA_LS;
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_LS)) {
@@ -1605,7 +1597,7 @@ static int sdma_v5_2_set_clockgating_state(void *handle,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(5, 2, 0):
case IP_VERSION(5, 2, 2):
case IP_VERSION(5, 2, 1):
@@ -1651,6 +1643,32 @@ static void sdma_v5_2_get_clockgating_state(void *handle, u64 *flags)
*flags |= AMD_CG_SUPPORT_SDMA_LS;
}
+static void sdma_v5_2_ring_begin_use(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ /* SDMA 5.2.3 (RMB) FW doesn't seem to properly
+ * disallow GFXOFF in some cases leading to
+ * hangs in SDMA. Disallow GFXOFF while SDMA is active.
+ * We can probably just limit this to 5.2.3,
+ * but it shouldn't hurt for other parts since
+ * this GFXOFF will be disallowed anyway when SDMA is
+ * active, this just makes it explicit.
+ */
+ amdgpu_gfx_off_ctrl(adev, false);
+}
+
+static void sdma_v5_2_ring_end_use(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ /* SDMA 5.2.3 (RMB) FW doesn't seem to properly
+ * disallow GFXOFF in some cases leading to
+ * hangs in SDMA. Allow GFXOFF when SDMA is complete.
+ */
+ amdgpu_gfx_off_ctrl(adev, true);
+}
+
const struct amd_ip_funcs sdma_v5_2_ip_funcs = {
.name = "sdma_v5_2",
.early_init = sdma_v5_2_early_init,
@@ -1698,6 +1716,8 @@ static const struct amdgpu_ring_funcs sdma_v5_2_ring_funcs = {
.test_ib = sdma_v5_2_ring_test_ib,
.insert_nop = sdma_v5_2_ring_insert_nop,
.pad_ib = sdma_v5_2_ring_pad_ib,
+ .begin_use = sdma_v5_2_ring_begin_use,
+ .end_use = sdma_v5_2_ring_end_use,
.emit_wreg = sdma_v5_2_ring_emit_wreg,
.emit_reg_wait = sdma_v5_2_ring_emit_reg_wait,
.emit_reg_write_reg_wait = sdma_v5_2_ring_emit_reg_write_reg_wait,
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index 45be0af2570b..3c7ddd219de8 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -156,68 +156,35 @@ static uint64_t sdma_v6_0_ring_get_wptr(struct amdgpu_ring *ring)
static void sdma_v6_0_ring_set_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
- uint32_t *wptr_saved;
- uint32_t *is_queue_unmap;
- uint64_t aggregated_db_index;
- uint32_t mqd_size = adev->mqds[AMDGPU_HW_IP_DMA].mqd_size;
-
- DRM_DEBUG("Setting write pointer\n");
-
- if (ring->is_mes_queue) {
- wptr_saved = (uint32_t *)(ring->mqd_ptr + mqd_size);
- is_queue_unmap = (uint32_t *)(ring->mqd_ptr + mqd_size +
- sizeof(uint32_t));
- aggregated_db_index =
- amdgpu_mes_get_aggregated_doorbell_index(adev,
- ring->hw_prio);
+ if (ring->use_doorbell) {
+ DRM_DEBUG("Using doorbell -- "
+ "wptr_offs == 0x%08x "
+ "lower_32_bits(ring->wptr) << 2 == 0x%08x "
+ "upper_32_bits(ring->wptr) << 2 == 0x%08x\n",
+ ring->wptr_offs,
+ lower_32_bits(ring->wptr << 2),
+ upper_32_bits(ring->wptr << 2));
+ /* XXX check if swapping is necessary on BE */
atomic64_set((atomic64_t *)ring->wptr_cpu_addr,
ring->wptr << 2);
- *wptr_saved = ring->wptr << 2;
- if (*is_queue_unmap) {
- WDOORBELL64(aggregated_db_index, ring->wptr << 2);
- DRM_DEBUG("calling WDOORBELL64(0x%08x, 0x%016llx)\n",
- ring->doorbell_index, ring->wptr << 2);
- WDOORBELL64(ring->doorbell_index, ring->wptr << 2);
- } else {
- DRM_DEBUG("calling WDOORBELL64(0x%08x, 0x%016llx)\n",
- ring->doorbell_index, ring->wptr << 2);
- WDOORBELL64(ring->doorbell_index, ring->wptr << 2);
-
- if (*is_queue_unmap)
- WDOORBELL64(aggregated_db_index,
- ring->wptr << 2);
- }
+ DRM_DEBUG("calling WDOORBELL64(0x%08x, 0x%016llx)\n",
+ ring->doorbell_index, ring->wptr << 2);
+ WDOORBELL64(ring->doorbell_index, ring->wptr << 2);
} else {
- if (ring->use_doorbell) {
- DRM_DEBUG("Using doorbell -- "
- "wptr_offs == 0x%08x "
- "lower_32_bits(ring->wptr) << 2 == 0x%08x "
- "upper_32_bits(ring->wptr) << 2 == 0x%08x\n",
- ring->wptr_offs,
- lower_32_bits(ring->wptr << 2),
- upper_32_bits(ring->wptr << 2));
- /* XXX check if swapping is necessary on BE */
- atomic64_set((atomic64_t *)ring->wptr_cpu_addr,
- ring->wptr << 2);
- DRM_DEBUG("calling WDOORBELL64(0x%08x, 0x%016llx)\n",
- ring->doorbell_index, ring->wptr << 2);
- WDOORBELL64(ring->doorbell_index, ring->wptr << 2);
- } else {
- DRM_DEBUG("Not using doorbell -- "
- "regSDMA%i_GFX_RB_WPTR == 0x%08x "
- "regSDMA%i_GFX_RB_WPTR_HI == 0x%08x\n",
- ring->me,
- lower_32_bits(ring->wptr << 2),
- ring->me,
- upper_32_bits(ring->wptr << 2));
- WREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev,
- ring->me, regSDMA0_QUEUE0_RB_WPTR),
- lower_32_bits(ring->wptr << 2));
- WREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev,
- ring->me, regSDMA0_QUEUE0_RB_WPTR_HI),
- upper_32_bits(ring->wptr << 2));
- }
+ DRM_DEBUG("Not using doorbell -- "
+ "regSDMA%i_GFX_RB_WPTR == 0x%08x "
+ "regSDMA%i_GFX_RB_WPTR_HI == 0x%08x\n",
+ ring->me,
+ lower_32_bits(ring->wptr << 2),
+ ring->me,
+ upper_32_bits(ring->wptr << 2));
+ WREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev,
+ ring->me, regSDMA0_QUEUE0_RB_WPTR),
+ lower_32_bits(ring->wptr << 2));
+ WREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev,
+ ring->me, regSDMA0_QUEUE0_RB_WPTR_HI),
+ upper_32_bits(ring->wptr << 2));
}
}
@@ -234,7 +201,7 @@ static void sdma_v6_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
amdgpu_ring_write(ring, ring->funcs->nop);
}
-/**
+/*
* sdma_v6_0_ring_emit_ib - Schedule an IB on the DMA engine
*
* @ring: amdgpu ring pointer
@@ -381,8 +348,6 @@ static void sdma_v6_0_gfx_stop(struct amdgpu_device *adev)
u32 rb_cntl, ib_cntl;
int i;
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
-
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev, i, regSDMA0_QUEUE0_RB_CNTL));
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_QUEUE0_RB_CNTL, RB_ENABLE, 0);
@@ -594,9 +559,6 @@ static int sdma_v6_0_gfx_resume(struct amdgpu_device *adev)
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
-
- if (adev->mman.buffer_funcs_ring == ring)
- amdgpu_ttm_set_buffer_funcs_status(adev, true);
}
return 0;
@@ -937,7 +899,7 @@ static int sdma_v6_0_ring_test_ring(struct amdgpu_ring *ring)
return r;
}
-/**
+/*
* sdma_v6_0_ring_test_ib - test an IB on the DMA engine
*
* @ring: amdgpu_ring structure holding ring information
@@ -1119,7 +1081,7 @@ static void sdma_v6_0_vm_set_pte_pde(struct amdgpu_ib *ib,
ib->ptr[ib->length_dw++] = count - 1; /* number of entries */
}
-/**
+/*
* sdma_v6_0_ring_pad_ib - pad the IB
* @ib: indirect buffer to fill with padding
* @ring: amdgpu ring pointer
@@ -1168,7 +1130,7 @@ static void sdma_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(4)); /* retry count, poll interval */
}
-/**
+/*
* sdma_v6_0_ring_emit_vm_flush - vm flush using sDMA
*
* @ring: amdgpu_ring pointer
@@ -1246,19 +1208,23 @@ static struct amdgpu_sdma_ras sdma_v6_0_3_ras = {
static void sdma_v6_0_set_ras_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(6, 0, 3):
adev->sdma.ras = &sdma_v6_0_3_ras;
break;
default:
break;
}
-
}
static int sdma_v6_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = amdgpu_sdma_init_microcode(adev, 0, true);
+ if (r)
+ return r;
sdma_v6_0_set_ring_funcs(adev);
sdma_v6_0_set_buffer_funcs(adev);
@@ -1283,12 +1249,6 @@ static int sdma_v6_0_sw_init(void *handle)
if (r)
return r;
- r = amdgpu_sdma_init_microcode(adev, 0, true);
- if (r) {
- DRM_ERROR("Failed to load sdma firmware!\n");
- return r;
- }
-
for (i = 0; i < adev->sdma.num_instances; i++) {
ring = &adev->sdma.instance[i].ring;
ring->ring_obj = NULL;
@@ -1343,11 +1303,8 @@ static int sdma_v6_0_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (amdgpu_sriov_vf(adev)) {
- /* disable the scheduler for SDMA */
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
+ if (amdgpu_sriov_vf(adev))
return 0;
- }
sdma_v6_0_ctxempty_int_enable(adev, false);
sdma_v6_0_enable(adev, false);
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index 4b81f29e5fd5..a757526153e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -2440,8 +2440,6 @@ static void si_program_aspm(struct amdgpu_device *adev)
if (!amdgpu_device_should_use_aspm(adev))
return;
- if (adev->flags & AMD_IS_APU)
- return;
orig = data = RREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL);
data &= ~LC_XMIT_N_FTS_MASK;
data |= LC_XMIT_N_FTS(0x24) | LC_XMIT_N_FTS_OVERRIDE_EN;
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c
index 42c4547f32ec..9aa0e11ee673 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dma.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c
@@ -115,8 +115,6 @@ static void si_dma_stop(struct amdgpu_device *adev)
u32 rb_cntl;
unsigned i;
- amdgpu_sdma_unset_buffer_funcs_helper(adev);
-
for (i = 0; i < adev->sdma.num_instances; i++) {
/* dma0 */
rb_cntl = RREG32(DMA_RB_CNTL + sdma_offsets[i]);
@@ -177,9 +175,6 @@ static int si_dma_start(struct amdgpu_device *adev)
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
-
- if (adev->mman.buffer_funcs_ring == ring)
- amdgpu_ttm_set_buffer_funcs_status(adev, true);
}
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c b/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c
index 8b8086d5c864..93f6772d1b24 100644
--- a/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c
+++ b/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c
@@ -36,7 +36,7 @@ static bool sienna_cichlid_is_mode2_default(struct amdgpu_reset_control *reset_c
#if 0
struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;
- if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 7) &&
+ if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 0, 7) &&
adev->pm.fw_version >= 0x3a5500 && !amdgpu_sriov_vf(adev))
return true;
#endif
@@ -48,18 +48,17 @@ sienna_cichlid_get_reset_handler(struct amdgpu_reset_control *reset_ctl,
struct amdgpu_reset_context *reset_context)
{
struct amdgpu_reset_handler *handler;
+ int i;
if (reset_context->method != AMD_RESET_METHOD_NONE) {
- list_for_each_entry(handler, &reset_ctl->reset_handlers,
- handler_list) {
+ for_each_handler(i, handler, reset_ctl) {
if (handler->reset_method == reset_context->method)
return handler;
}
}
if (sienna_cichlid_is_mode2_default(reset_ctl)) {
- list_for_each_entry (handler, &reset_ctl->reset_handlers,
- handler_list) {
+ for_each_handler(i, handler, reset_ctl) {
if (handler->reset_method == AMD_RESET_METHOD_MODE2)
return handler;
}
@@ -120,9 +119,9 @@ static void sienna_cichlid_async_reset(struct work_struct *work)
struct amdgpu_reset_control *reset_ctl =
container_of(work, struct amdgpu_reset_control, reset_work);
struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;
+ int i;
- list_for_each_entry(handler, &reset_ctl->reset_handlers,
- handler_list) {
+ for_each_handler(i, handler, reset_ctl) {
if (handler->reset_method == reset_ctl->active_reset) {
dev_dbg(adev->dev, "Resetting device\n");
handler->do_reset(adev);
@@ -281,6 +280,11 @@ static struct amdgpu_reset_handler sienna_cichlid_mode2_handler = {
.do_reset = sienna_cichlid_mode2_reset,
};
+static struct amdgpu_reset_handler
+ *sienna_cichlid_rst_handlers[AMDGPU_RESET_MAX_HANDLERS] = {
+ &sienna_cichlid_mode2_handler,
+ };
+
int sienna_cichlid_reset_init(struct amdgpu_device *adev)
{
struct amdgpu_reset_control *reset_ctl;
@@ -294,11 +298,9 @@ int sienna_cichlid_reset_init(struct amdgpu_device *adev)
reset_ctl->active_reset = AMD_RESET_METHOD_NONE;
reset_ctl->get_reset_handler = sienna_cichlid_get_reset_handler;
- INIT_LIST_HEAD(&reset_ctl->reset_handlers);
INIT_WORK(&reset_ctl->reset_work, reset_ctl->async_reset);
/* Only mode2 is handled through reset control now */
- amdgpu_reset_add_handler(reset_ctl, &sienna_cichlid_mode2_handler);
-
+ reset_ctl->reset_handlers = &sienna_cichlid_rst_handlers;
adev->reset_cntl = reset_ctl;
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c b/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
index ae29620b1ea4..04c797d54511 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
@@ -44,10 +44,10 @@ smu_v13_0_10_get_reset_handler(struct amdgpu_reset_control *reset_ctl,
{
struct amdgpu_reset_handler *handler;
struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;
+ int i;
if (reset_context->method != AMD_RESET_METHOD_NONE) {
- list_for_each_entry(handler, &reset_ctl->reset_handlers,
- handler_list) {
+ for_each_handler(i, handler, reset_ctl) {
if (handler->reset_method == reset_context->method)
return handler;
}
@@ -55,8 +55,7 @@ smu_v13_0_10_get_reset_handler(struct amdgpu_reset_control *reset_ctl,
if (smu_v13_0_10_is_mode2_default(reset_ctl) &&
amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_MODE2) {
- list_for_each_entry (handler, &reset_ctl->reset_handlers,
- handler_list) {
+ for_each_handler(i, handler, reset_ctl) {
if (handler->reset_method == AMD_RESET_METHOD_MODE2)
return handler;
}
@@ -119,9 +118,9 @@ static void smu_v13_0_10_async_reset(struct work_struct *work)
struct amdgpu_reset_control *reset_ctl =
container_of(work, struct amdgpu_reset_control, reset_work);
struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;
+ int i;
- list_for_each_entry(handler, &reset_ctl->reset_handlers,
- handler_list) {
+ for_each_handler(i, handler, reset_ctl) {
if (handler->reset_method == reset_ctl->active_reset) {
dev_dbg(adev->dev, "Resetting device\n");
handler->do_reset(adev);
@@ -272,6 +271,11 @@ static struct amdgpu_reset_handler smu_v13_0_10_mode2_handler = {
.do_reset = smu_v13_0_10_mode2_reset,
};
+static struct amdgpu_reset_handler
+ *smu_v13_0_10_rst_handlers[AMDGPU_RESET_MAX_HANDLERS] = {
+ &smu_v13_0_10_mode2_handler,
+ };
+
int smu_v13_0_10_reset_init(struct amdgpu_device *adev)
{
struct amdgpu_reset_control *reset_ctl;
@@ -285,10 +289,9 @@ int smu_v13_0_10_reset_init(struct amdgpu_device *adev)
reset_ctl->active_reset = AMD_RESET_METHOD_NONE;
reset_ctl->get_reset_handler = smu_v13_0_10_get_reset_handler;
- INIT_LIST_HEAD(&reset_ctl->reset_handlers);
INIT_WORK(&reset_ctl->reset_work, reset_ctl->async_reset);
/* Only mode2 is handled through reset control now */
- amdgpu_reset_add_handler(reset_ctl, &smu_v13_0_10_mode2_handler);
+ reset_ctl->reset_handlers = &smu_v13_0_10_rst_handlers;
adev->reset_cntl = reset_ctl;
diff --git a/drivers/gpu/drm/amd/amdgpu/smuio_v13_0.c b/drivers/gpu/drm/amd/amdgpu/smuio_v13_0.c
index 13e905c22592..bf8b8e5ddf5d 100644
--- a/drivers/gpu/drm/amd/amdgpu/smuio_v13_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/smuio_v13_0.c
@@ -128,6 +128,27 @@ static bool smuio_v13_0_is_host_gpu_xgmi_supported(struct amdgpu_device *adev)
return data ? true : false;
}
+static enum amdgpu_pkg_type smuio_v13_0_get_pkg_type(struct amdgpu_device *adev)
+{
+ enum amdgpu_pkg_type pkg_type;
+ u32 data;
+
+ data = RREG32_SOC15(SMUIO, 0, regSMUIO_MCM_CONFIG);
+ data = REG_GET_FIELD(data, SMUIO_MCM_CONFIG, TOPOLOGY_ID);
+
+ switch (data) {
+ case 0x4:
+ case 0xC:
+ pkg_type = AMDGPU_PKG_TYPE_CEM;
+ break;
+ default:
+ pkg_type = AMDGPU_PKG_TYPE_OAM;
+ break;
+ }
+
+ return pkg_type;
+}
+
const struct amdgpu_smuio_funcs smuio_v13_0_funcs = {
.get_rom_index_offset = smuio_v13_0_get_rom_index_offset,
.get_rom_data_offset = smuio_v13_0_get_rom_data_offset,
@@ -136,4 +157,5 @@ const struct amdgpu_smuio_funcs smuio_v13_0_funcs = {
.is_host_gpu_xgmi_supported = smuio_v13_0_is_host_gpu_xgmi_supported,
.update_rom_clock_gating = smuio_v13_0_update_rom_clock_gating,
.get_clock_gating_state = smuio_v13_0_get_clock_gating_state,
+ .get_pkg_type = smuio_v13_0_get_pkg_type,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.c b/drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.c
index 4368a5891eeb..5461b5289793 100644
--- a/drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.c
@@ -84,6 +84,12 @@ static enum amdgpu_pkg_type smuio_v13_0_3_get_pkg_type(struct amdgpu_device *ade
* b0100 - b1111 - Reserved
*/
switch (data & PKG_TYPE_MASK) {
+ case 0x0:
+ pkg_type = AMDGPU_PKG_TYPE_CEM;
+ break;
+ case 0x1:
+ pkg_type = AMDGPU_PKG_TYPE_OAM;
+ break;
case 0x2:
pkg_type = AMDGPU_PKG_TYPE_APU;
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
index f5be40d7ba36..51342809af03 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -174,8 +174,8 @@ static const struct amdgpu_video_codecs vcn_4_0_3_video_codecs_encode = {
static int soc15_query_video_codecs(struct amdgpu_device *adev, bool encode,
const struct amdgpu_video_codecs **codecs)
{
- if (adev->ip_versions[VCE_HWIP][0]) {
- switch (adev->ip_versions[VCE_HWIP][0]) {
+ if (amdgpu_ip_version(adev, VCE_HWIP, 0)) {
+ switch (amdgpu_ip_version(adev, VCE_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
case IP_VERSION(4, 1, 0):
if (encode)
@@ -187,7 +187,7 @@ static int soc15_query_video_codecs(struct amdgpu_device *adev, bool encode,
return -EINVAL;
}
} else {
- switch (adev->ip_versions[UVD_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, UVD_HWIP, 0)) {
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
if (encode)
@@ -324,11 +324,12 @@ static u32 soc15_get_xclk(struct amdgpu_device *adev)
{
u32 reference_clock = adev->clock.spll.reference_freq;
- if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(12, 0, 0) ||
- adev->ip_versions[MP1_HWIP][0] == IP_VERSION(12, 0, 1))
+ if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(12, 0, 0) ||
+ amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(12, 0, 1) ||
+ amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 6))
return 10000;
- if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(10, 0, 0) ||
- adev->ip_versions[MP1_HWIP][0] == IP_VERSION(10, 0, 1))
+ if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(10, 0, 0) ||
+ amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(10, 0, 1))
return reference_clock / 4;
return reference_clock;
@@ -522,7 +523,7 @@ soc15_asic_reset_method(struct amdgpu_device *adev)
dev_warn(adev->dev, "Specified reset method:%d isn't supported, using AUTO instead.\n",
amdgpu_reset_method);
- switch (adev->ip_versions[MP1_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(10, 0, 0):
case IP_VERSION(10, 0, 1):
case IP_VERSION(12, 0, 0):
@@ -598,7 +599,7 @@ static int soc15_asic_reset(struct amdgpu_device *adev)
static bool soc15_supports_baco(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[MP1_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(9, 0, 0):
case IP_VERSION(11, 0, 2):
if (adev->asic_type == CHIP_VEGA20) {
@@ -645,8 +646,7 @@ static void soc15_program_aspm(struct amdgpu_device *adev)
if (!amdgpu_device_should_use_aspm(adev))
return;
- if (!(adev->flags & AMD_IS_APU) &&
- (adev->nbio.funcs->program_aspm))
+ if (adev->nbio.funcs->program_aspm)
adev->nbio.funcs->program_aspm(adev);
}
@@ -921,6 +921,8 @@ static int soc15_common_early_init(void *handle)
adev->pcie_wreg_ext = &amdgpu_device_indirect_wreg_ext;
adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64;
adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64;
+ adev->pcie_rreg64_ext = &amdgpu_device_indirect_rreg64_ext;
+ adev->pcie_wreg64_ext = &amdgpu_device_indirect_wreg64_ext;
adev->uvd_ctx_rreg = &soc15_uvd_ctx_rreg;
adev->uvd_ctx_wreg = &soc15_uvd_ctx_wreg;
adev->didt_rreg = &soc15_didt_rreg;
@@ -935,7 +937,7 @@ static int soc15_common_early_init(void *handle)
/* TODO: split the GC and PG flags based on the relevant IP version for which
* they are relevant.
*/
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 0, 1):
adev->asic_funcs = &soc15_asic_funcs;
adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
@@ -1159,6 +1161,11 @@ static int soc15_common_early_init(void *handle)
AMD_PG_SUPPORT_VCN_DPG |
AMD_PG_SUPPORT_JPEG;
adev->external_rev_id = adev->rev_id + 0x46;
+ /* GC 9.4.3 uses MMIO register region hole at a different offset */
+ if (!amdgpu_sriov_vf(adev)) {
+ adev->rmmio_remap.reg_offset = 0x1A000;
+ adev->rmmio_remap.bus_addr = adev->rmmio_base + 0x1A000;
+ }
break;
default:
/* FIXME: not supported yet */
@@ -1364,7 +1371,7 @@ static int soc15_common_set_clockgating_state(void *handle,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[NBIO_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
case IP_VERSION(6, 1, 0):
case IP_VERSION(6, 2, 0):
case IP_VERSION(7, 4, 0):
@@ -1416,12 +1423,14 @@ static void soc15_common_get_clockgating_state(void *handle, u64 *flags)
if (amdgpu_sriov_vf(adev))
*flags = 0;
- adev->nbio.funcs->get_clockgating_state(adev, flags);
-
- adev->hdp.funcs->get_clock_gating_state(adev, flags);
+ if (adev->nbio.funcs && adev->nbio.funcs->get_clockgating_state)
+ adev->nbio.funcs->get_clockgating_state(adev, flags);
- if (adev->ip_versions[MP0_HWIP][0] != IP_VERSION(13, 0, 2)) {
+ if (adev->hdp.funcs && adev->hdp.funcs->get_clock_gating_state)
+ adev->hdp.funcs->get_clock_gating_state(adev, flags);
+ if ((amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(13, 0, 2)) &&
+ (amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(13, 0, 6))) {
/* AMD_CG_SUPPORT_DRM_MGCG */
data = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_CGTT_CTRL0));
if (!(data & 0x01000000))
@@ -1434,9 +1443,11 @@ static void soc15_common_get_clockgating_state(void *handle, u64 *flags)
}
/* AMD_CG_SUPPORT_ROM_MGCG */
- adev->smuio.funcs->get_clock_gating_state(adev, flags);
+ if (adev->smuio.funcs && adev->smuio.funcs->get_clock_gating_state)
+ adev->smuio.funcs->get_clock_gating_state(adev, flags);
- adev->df.funcs->get_clockgating_state(adev, flags);
+ if (adev->df.funcs && adev->df.funcs->get_clockgating_state)
+ adev->df.funcs->get_clockgating_state(adev, flags);
}
static int soc15_common_set_powergating_state(void *handle,
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15_common.h b/drivers/gpu/drm/amd/amdgpu/soc15_common.h
index da683afa0222..242b24f73c17 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15_common.h
+++ b/drivers/gpu/drm/amd/amdgpu/soc15_common.h
@@ -69,7 +69,7 @@
#define RREG32_SOC15_IP(ip, reg) __RREG32_SOC15_RLC__(reg, 0, ip##_HWIP, 0)
-#define RREG32_SOC15_IP_NO_KIQ(ip, reg) __RREG32_SOC15_RLC__(reg, AMDGPU_REGS_NO_KIQ, ip##_HWIP, 0)
+#define RREG32_SOC15_IP_NO_KIQ(ip, reg, inst) __RREG32_SOC15_RLC__(reg, AMDGPU_REGS_NO_KIQ, ip##_HWIP, inst)
#define RREG32_SOC15_NO_KIQ(ip, inst, reg) \
__RREG32_SOC15_RLC__(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg, \
@@ -86,8 +86,8 @@
#define WREG32_SOC15_IP(ip, reg, value) \
__WREG32_SOC15_RLC__(reg, value, 0, ip##_HWIP, 0)
-#define WREG32_SOC15_IP_NO_KIQ(ip, reg, value) \
- __WREG32_SOC15_RLC__(reg, value, AMDGPU_REGS_NO_KIQ, ip##_HWIP, 0)
+#define WREG32_SOC15_IP_NO_KIQ(ip, reg, value, inst) \
+ __WREG32_SOC15_RLC__(reg, value, AMDGPU_REGS_NO_KIQ, ip##_HWIP, inst)
#define WREG32_SOC15_NO_KIQ(ip, inst, reg, value) \
__WREG32_SOC15_RLC__(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg, \
@@ -140,7 +140,7 @@
/* for GC only */
#define RREG32_RLC(reg) \
- __RREG32_SOC15_RLC__(reg, AMDGPU_REGS_RLC, GC_HWIP)
+ __RREG32_SOC15_RLC__(reg, AMDGPU_REGS_RLC, GC_HWIP, 0)
#define WREG32_RLC_NO_KIQ(reg, value, hwip) \
__WREG32_SOC15_RLC__(reg, value, AMDGPU_REGS_NO_KIQ | AMDGPU_REGS_RLC, hwip, 0)
@@ -204,4 +204,10 @@
+ adev->asic_funcs->encode_ext_smn_addressing(ext), \
value) \
+#define RREG64_MCA(ext, mca_base, idx) \
+ RREG64_PCIE_EXT(adev->asic_funcs->encode_ext_smn_addressing(ext) + mca_base + (idx * 8))
+
+#define WREG64_MCA(ext, mca_base, idx, val) \
+ WREG64_PCIE_EXT(adev->asic_funcs->encode_ext_smn_addressing(ext) + mca_base + (idx * 8), val)
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c
index 8b2ff2b281b0..48c6efcdeac9 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc21.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc21.c
@@ -153,10 +153,11 @@ static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode,
if (adev->vcn.num_vcn_inst == hweight8(adev->vcn.harvest_config))
return -EINVAL;
- switch (adev->ip_versions[UVD_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, UVD_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
case IP_VERSION(4, 0, 2):
case IP_VERSION(4, 0, 4):
+ case IP_VERSION(4, 0, 5):
if (amdgpu_sriov_vf(adev)) {
if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) ||
!amdgpu_sriov_is_av1_support(adev)) {
@@ -373,13 +374,14 @@ soc21_asic_reset_method(struct amdgpu_device *adev)
dev_warn(adev->dev, "Specified reset method:%d isn't supported, using AUTO instead.\n",
amdgpu_reset_method);
- switch (adev->ip_versions[MP1_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(13, 0, 0):
case IP_VERSION(13, 0, 7):
case IP_VERSION(13, 0, 10):
return AMD_RESET_METHOD_MODE1;
case IP_VERSION(13, 0, 4):
case IP_VERSION(13, 0, 11):
+ case IP_VERSION(14, 0, 0):
return AMD_RESET_METHOD_MODE2;
default:
if (amdgpu_dpm_is_baco_supported(adev))
@@ -432,8 +434,7 @@ static void soc21_program_aspm(struct amdgpu_device *adev)
if (!amdgpu_device_should_use_aspm(adev))
return;
- if (!(adev->flags & AMD_IS_APU) &&
- (adev->nbio.funcs->program_aspm))
+ if (adev->nbio.funcs->program_aspm)
adev->nbio.funcs->program_aspm(adev);
}
@@ -447,7 +448,7 @@ const struct amdgpu_ip_block_version soc21_common_ip_block = {
static bool soc21_need_full_reset(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(11, 0, 0):
return amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC);
case IP_VERSION(11, 0, 2):
@@ -503,6 +504,7 @@ static void soc21_init_doorbell_index(struct amdgpu_device *adev)
adev->doorbell_index.vcn.vcn_ring2_3 = AMDGPU_NAVI10_DOORBELL64_VCN2_3;
adev->doorbell_index.vcn.vcn_ring4_5 = AMDGPU_NAVI10_DOORBELL64_VCN4_5;
adev->doorbell_index.vcn.vcn_ring6_7 = AMDGPU_NAVI10_DOORBELL64_VCN6_7;
+ adev->doorbell_index.vpe_ring = AMDGPU_NAVI10_DOORBELL64_VPE;
adev->doorbell_index.first_non_cp = AMDGPU_NAVI10_DOORBELL64_FIRST_NON_CP;
adev->doorbell_index.last_non_cp = AMDGPU_NAVI10_DOORBELL64_LAST_NON_CP;
@@ -575,7 +577,7 @@ static int soc21_common_early_init(void *handle)
adev->rev_id = amdgpu_device_get_rev_id(adev);
adev->external_rev_id = 0xff;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(11, 0, 0):
adev->cg_flags = AMD_CG_SUPPORT_GFX_CGCG |
AMD_CG_SUPPORT_GFX_CGLS |
@@ -687,7 +689,33 @@ static int soc21_common_early_init(void *handle)
AMD_PG_SUPPORT_JPEG;
adev->external_rev_id = adev->rev_id + 0x80;
break;
-
+ case IP_VERSION(11, 5, 0):
+ adev->cg_flags = AMD_CG_SUPPORT_VCN_MGCG |
+ AMD_CG_SUPPORT_JPEG_MGCG |
+ AMD_CG_SUPPORT_GFX_CGCG |
+ AMD_CG_SUPPORT_GFX_CGLS |
+ AMD_CG_SUPPORT_GFX_MGCG |
+ AMD_CG_SUPPORT_GFX_FGCG |
+ AMD_CG_SUPPORT_REPEATER_FGCG |
+ AMD_CG_SUPPORT_GFX_PERF_CLK |
+ AMD_CG_SUPPORT_GFX_3D_CGCG |
+ AMD_CG_SUPPORT_GFX_3D_CGLS |
+ AMD_CG_SUPPORT_MC_MGCG |
+ AMD_CG_SUPPORT_MC_LS |
+ AMD_CG_SUPPORT_HDP_LS |
+ AMD_CG_SUPPORT_HDP_DS |
+ AMD_CG_SUPPORT_HDP_SD |
+ AMD_CG_SUPPORT_ATHUB_MGCG |
+ AMD_CG_SUPPORT_ATHUB_LS |
+ AMD_CG_SUPPORT_IH_CG |
+ AMD_CG_SUPPORT_BIF_MGCG |
+ AMD_CG_SUPPORT_BIF_LS;
+ adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG |
+ AMD_PG_SUPPORT_VCN |
+ AMD_PG_SUPPORT_JPEG |
+ AMD_PG_SUPPORT_GFX_PG;
+ adev->external_rev_id = adev->rev_id + 0x1;
+ break;
default:
/* FIXME: not supported yet */
return -EINVAL;
@@ -831,10 +859,12 @@ static int soc21_common_set_clockgating_state(void *handle,
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- switch (adev->ip_versions[NBIO_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
case IP_VERSION(4, 3, 0):
case IP_VERSION(4, 3, 1):
case IP_VERSION(7, 7, 0):
+ case IP_VERSION(7, 7, 1):
+ case IP_VERSION(7, 11, 0):
adev->nbio.funcs->update_medium_grain_clock_gating(adev,
state == AMD_CG_STATE_GATE);
adev->nbio.funcs->update_medium_grain_light_sleep(adev,
@@ -853,7 +883,7 @@ static int soc21_common_set_powergating_state(void *handle,
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- switch (adev->ip_versions[LSDMA_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, LSDMA_HWIP, 0)) {
case IP_VERSION(6, 0, 0):
case IP_VERSION(6, 0, 2):
adev->lsdma.funcs->update_memory_power_gating(adev,
@@ -873,8 +903,6 @@ static void soc21_common_get_clockgating_state(void *handle, u64 *flags)
adev->nbio.funcs->get_clockgating_state(adev, flags);
adev->hdp.funcs->get_clock_gating_state(adev, flags);
-
- return;
}
static const struct amd_ip_funcs soc21_common_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h b/drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h
index da815a93d46e..d5748032674e 100644
--- a/drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h
+++ b/drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Advanced Micro Devices, Inc.
+ * Copyright 2018-2022 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -20,7 +20,6 @@
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
-
#ifndef _TA_XGMI_IF_H
#define _TA_XGMI_IF_H
@@ -28,20 +27,31 @@
#define RSP_ID_MASK (1U << 31)
#define RSP_ID(cmdId) (((uint32_t)(cmdId)) | RSP_ID_MASK)
+#define EXTEND_PEER_LINK_INFO_CMD_FLAG 1
+
enum ta_command_xgmi {
+ /* Initialize the Context and Session Topology */
TA_COMMAND_XGMI__INITIALIZE = 0x00,
+ /* Gets the current GPU's node ID */
TA_COMMAND_XGMI__GET_NODE_ID = 0x01,
+ /* Gets the current GPU's hive ID */
TA_COMMAND_XGMI__GET_HIVE_ID = 0x02,
- TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO = 0x03,
+ /* Gets the Peer's topology Information */
+ TA_COMMAND_XGMI__GET_TOPOLOGY_INFO = 0x03,
+ /* Sets the Peer's topology Information */
TA_COMMAND_XGMI__SET_TOPOLOGY_INFO = 0x04,
- TA_COMMAND_XGMI__GET_PEER_LINKS = 0x0B
+ /* Gets the total links between adjacent peer dies in hive */
+ TA_COMMAND_XGMI__GET_PEER_LINKS = 0x0B,
+ /* Gets the total links and connected port numbers between adjacent peer dies in hive */
+ TA_COMMAND_XGMI__GET_EXTEND_PEER_LINKS = 0x0C
};
/* XGMI related enumerations */
/**********************************************************/;
-enum ta_xgmi_connected_nodes {
- TA_XGMI__MAX_CONNECTED_NODES = 64
-};
+enum { TA_XGMI__MAX_CONNECTED_NODES = 64 };
+enum { TA_XGMI__MAX_INTERNAL_STATE = 32 };
+enum { TA_XGMI__MAX_INTERNAL_STATE_BUFFER = 128 };
+enum { TA_XGMI__MAX_PORT_NUM = 8 };
enum ta_xgmi_status {
TA_XGMI_STATUS__SUCCESS = 0x00,
@@ -81,6 +91,18 @@ struct ta_xgmi_peer_link_info {
uint8_t num_links;
};
+struct xgmi_connected_port_num {
+ uint8_t dst_xgmi_port_num;
+ uint8_t src_xgmi_port_num;
+};
+
+/* support both the port num and num_links */
+struct ta_xgmi_extend_peer_link_info {
+ uint64_t node_id;
+ uint8_t num_links;
+ struct xgmi_connected_port_num port_num[TA_XGMI__MAX_PORT_NUM];
+};
+
struct ta_xgmi_cmd_initialize_output {
uint32_t status;
};
@@ -103,16 +125,21 @@ struct ta_xgmi_cmd_get_topology_info_output {
struct ta_xgmi_node_info nodes[TA_XGMI__MAX_CONNECTED_NODES];
};
-struct ta_xgmi_cmd_get_peer_link_info_output {
+struct ta_xgmi_cmd_set_topology_info_input {
uint32_t num_nodes;
- struct ta_xgmi_peer_link_info nodes[TA_XGMI__MAX_CONNECTED_NODES];
+ struct ta_xgmi_node_info nodes[TA_XGMI__MAX_CONNECTED_NODES];
};
-struct ta_xgmi_cmd_set_topology_info_input {
+/* support XGMI TA w/ and w/o port_num both so two similar structs defined */
+struct ta_xgmi_cmd_get_peer_link_info {
uint32_t num_nodes;
- struct ta_xgmi_node_info nodes[TA_XGMI__MAX_CONNECTED_NODES];
+ struct ta_xgmi_peer_link_info nodes[TA_XGMI__MAX_CONNECTED_NODES];
};
+struct ta_xgmi_cmd_get_extend_peer_link_info {
+ uint32_t num_nodes;
+ struct ta_xgmi_extend_peer_link_info nodes[TA_XGMI__MAX_CONNECTED_NODES];
+};
/**********************************************************/
/* Common input structure for XGMI callbacks */
union ta_xgmi_cmd_input {
@@ -126,16 +153,23 @@ union ta_xgmi_cmd_output {
struct ta_xgmi_cmd_get_node_id_output get_node_id;
struct ta_xgmi_cmd_get_hive_id_output get_hive_id;
struct ta_xgmi_cmd_get_topology_info_output get_topology_info;
- struct ta_xgmi_cmd_get_peer_link_info_output get_link_info;
+ struct ta_xgmi_cmd_get_peer_link_info get_link_info;
+ struct ta_xgmi_cmd_get_extend_peer_link_info get_extend_link_info;
};
-/**********************************************************/
struct ta_xgmi_shared_memory {
uint32_t cmd_id;
uint32_t resp_id;
enum ta_xgmi_status xgmi_status;
+
+ /* if the number of xgmi link record is more than 128, driver will set the
+ * flag 0 to get the first 128 of the link records and will set to 1, to get
+ * the second set
+ */
uint8_t flag_extend_link_record;
- uint8_t reserved0[3];
+ /* bit0: port_num info support flag for GET_EXTEND_PEER_LINKS commmand */
+ uint8_t caps_flag;
+ uint8_t reserved[2];
union ta_xgmi_cmd_input xgmi_in_message;
union ta_xgmi_cmd_output xgmi_out_message;
};
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c
new file mode 100644
index 000000000000..e9c2ff74f0bc
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "umc_v12_0.h"
+#include "amdgpu_ras.h"
+#include "amdgpu_umc.h"
+#include "amdgpu.h"
+#include "umc/umc_12_0_0_offset.h"
+#include "umc/umc_12_0_0_sh_mask.h"
+
+const uint32_t
+ umc_v12_0_channel_idx_tbl[]
+ [UMC_V12_0_UMC_INSTANCE_NUM]
+ [UMC_V12_0_CHANNEL_INSTANCE_NUM] = {
+ {{3, 7, 11, 15, 2, 6, 10, 14}, {1, 5, 9, 13, 0, 4, 8, 12},
+ {19, 23, 27, 31, 18, 22, 26, 30}, {17, 21, 25, 29, 16, 20, 24, 28}},
+ {{47, 43, 39, 35, 46, 42, 38, 34}, {45, 41, 37, 33, 44, 40, 36, 32},
+ {63, 59, 55, 51, 62, 58, 54, 50}, {61, 57, 53, 49, 60, 56, 52, 48}},
+ {{79, 75, 71, 67, 78, 74, 70, 66}, {77, 73, 69, 65, 76, 72, 68, 64},
+ {95, 91, 87, 83, 94, 90, 86, 82}, {93, 89, 85, 81, 92, 88, 84, 80}},
+ {{99, 103, 107, 111, 98, 102, 106, 110}, {97, 101, 105, 109, 96, 100, 104, 108},
+ {115, 119, 123, 127, 114, 118, 122, 126}, {113, 117, 121, 125, 112, 116, 120, 124}}
+ };
+
+/* mapping of MCA error address to normalized address */
+static const uint32_t umc_v12_0_ma2na_mapping[] = {
+ 0, 5, 6, 8, 9, 14, 12, 13,
+ 10, 11, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28,
+ 24, 7, 29, 30,
+};
+
+static inline uint64_t get_umc_v12_0_reg_offset(struct amdgpu_device *adev,
+ uint32_t node_inst,
+ uint32_t umc_inst,
+ uint32_t ch_inst)
+{
+ uint32_t index = umc_inst * adev->umc.channel_inst_num + ch_inst;
+ uint64_t cross_node_offset = (node_inst == 0) ? 0 : UMC_V12_0_CROSS_NODE_OFFSET;
+
+ umc_inst = index / 4;
+ ch_inst = index % 4;
+
+ return adev->umc.channel_offs * ch_inst + UMC_V12_0_INST_DIST * umc_inst +
+ UMC_V12_0_NODE_DIST * node_inst + cross_node_offset;
+}
+
+static int umc_v12_0_reset_error_count_per_channel(struct amdgpu_device *adev,
+ uint32_t node_inst, uint32_t umc_inst,
+ uint32_t ch_inst, void *data)
+{
+ uint64_t odecc_err_cnt_addr;
+ uint64_t umc_reg_offset =
+ get_umc_v12_0_reg_offset(adev, node_inst, umc_inst, ch_inst);
+
+ odecc_err_cnt_addr =
+ SOC15_REG_OFFSET(UMC, 0, regUMCCH0_OdEccErrCnt);
+
+ /* clear error count */
+ WREG32_PCIE_EXT((odecc_err_cnt_addr + umc_reg_offset) * 4,
+ UMC_V12_0_CE_CNT_INIT);
+
+ return 0;
+}
+
+static void umc_v12_0_reset_error_count(struct amdgpu_device *adev)
+{
+ amdgpu_umc_loop_channels(adev,
+ umc_v12_0_reset_error_count_per_channel, NULL);
+}
+
+bool umc_v12_0_is_uncorrectable_error(uint64_t mc_umc_status)
+{
+ return ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
+ (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
+ REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 ||
+ REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1));
+}
+
+bool umc_v12_0_is_correctable_error(uint64_t mc_umc_status)
+{
+ return (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
+ (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1 ||
+ (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 &&
+ REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 0) ||
+ /* Identify data parity error in replay mode */
+ ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, ErrorCodeExt) == 0x5 ||
+ REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, ErrorCodeExt) == 0xb) &&
+ !(umc_v12_0_is_uncorrectable_error(mc_umc_status)))));
+}
+
+static void umc_v12_0_query_correctable_error_count(struct amdgpu_device *adev,
+ uint64_t umc_reg_offset,
+ unsigned long *error_count)
+{
+ uint64_t mc_umc_status;
+ uint64_t mc_umc_status_addr;
+
+ mc_umc_status_addr =
+ SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
+
+ /* Rely on MCUMC_STATUS for correctable error counter
+ * MCUMC_STATUS is a 64 bit register
+ */
+ mc_umc_status =
+ RREG64_PCIE_EXT((mc_umc_status_addr + umc_reg_offset) * 4);
+
+ if (umc_v12_0_is_correctable_error(mc_umc_status))
+ *error_count += 1;
+}
+
+static void umc_v12_0_query_uncorrectable_error_count(struct amdgpu_device *adev,
+ uint64_t umc_reg_offset,
+ unsigned long *error_count)
+{
+ uint64_t mc_umc_status;
+ uint64_t mc_umc_status_addr;
+
+ mc_umc_status_addr =
+ SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
+
+ /* Check the MCUMC_STATUS. */
+ mc_umc_status =
+ RREG64_PCIE_EXT((mc_umc_status_addr + umc_reg_offset) * 4);
+
+ if (umc_v12_0_is_uncorrectable_error(mc_umc_status))
+ *error_count += 1;
+}
+
+static int umc_v12_0_query_error_count(struct amdgpu_device *adev,
+ uint32_t node_inst, uint32_t umc_inst,
+ uint32_t ch_inst, void *data)
+{
+ struct ras_err_data *err_data = (struct ras_err_data *)data;
+ unsigned long ue_count = 0, ce_count = 0;
+
+ /* NOTE: node_inst is converted by adev->umc.active_mask and the range is [0-3],
+ * which can be used as die ID directly */
+ struct amdgpu_smuio_mcm_config_info mcm_info = {
+ .socket_id = adev->smuio.funcs->get_socket_id(adev),
+ .die_id = node_inst,
+ };
+
+ uint64_t umc_reg_offset =
+ get_umc_v12_0_reg_offset(adev, node_inst, umc_inst, ch_inst);
+
+ umc_v12_0_query_correctable_error_count(adev, umc_reg_offset, &ce_count);
+ umc_v12_0_query_uncorrectable_error_count(adev, umc_reg_offset, &ue_count);
+
+ amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count);
+ amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, ce_count);
+
+ return 0;
+}
+
+static void umc_v12_0_query_ras_error_count(struct amdgpu_device *adev,
+ void *ras_error_status)
+{
+ amdgpu_umc_loop_channels(adev,
+ umc_v12_0_query_error_count, ras_error_status);
+
+ umc_v12_0_reset_error_count(adev);
+}
+
+static bool umc_v12_0_bit_wise_xor(uint32_t val)
+{
+ bool result = 0;
+ int i;
+
+ for (i = 0; i < 32; i++)
+ result = result ^ ((val >> i) & 0x1);
+
+ return result;
+}
+
+static void umc_v12_0_convert_error_address(struct amdgpu_device *adev,
+ struct ras_err_data *err_data, uint64_t err_addr,
+ uint32_t ch_inst, uint32_t umc_inst,
+ uint32_t node_inst)
+{
+ uint32_t channel_index, i;
+ uint64_t soc_pa, na, retired_page, column;
+ uint32_t bank_hash0, bank_hash1, bank_hash2, bank_hash3, col, row, row_xor;
+ uint32_t bank0, bank1, bank2, bank3, bank;
+
+ bank_hash0 = (err_addr >> UMC_V12_0_MCA_B0_BIT) & 0x1ULL;
+ bank_hash1 = (err_addr >> UMC_V12_0_MCA_B1_BIT) & 0x1ULL;
+ bank_hash2 = (err_addr >> UMC_V12_0_MCA_B2_BIT) & 0x1ULL;
+ bank_hash3 = (err_addr >> UMC_V12_0_MCA_B3_BIT) & 0x1ULL;
+ col = (err_addr >> 1) & 0x1fULL;
+ row = (err_addr >> 10) & 0x3fffULL;
+
+ /* apply bank hash algorithm */
+ bank0 =
+ bank_hash0 ^ (UMC_V12_0_XOR_EN0 &
+ (umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR0) ^
+ (umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR0))));
+ bank1 =
+ bank_hash1 ^ (UMC_V12_0_XOR_EN1 &
+ (umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR1) ^
+ (umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR1))));
+ bank2 =
+ bank_hash2 ^ (UMC_V12_0_XOR_EN2 &
+ (umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR2) ^
+ (umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR2))));
+ bank3 =
+ bank_hash3 ^ (UMC_V12_0_XOR_EN3 &
+ (umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR3) ^
+ (umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR3))));
+
+ bank = bank0 | (bank1 << 1) | (bank2 << 2) | (bank3 << 3);
+ err_addr &= ~0x3c0ULL;
+ err_addr |= (bank << UMC_V12_0_MCA_B0_BIT);
+
+ na = 0x0;
+ /* convert mca error address to normalized address */
+ for (i = 1; i < ARRAY_SIZE(umc_v12_0_ma2na_mapping); i++)
+ na |= ((err_addr >> i) & 0x1ULL) << umc_v12_0_ma2na_mapping[i];
+
+ channel_index =
+ adev->umc.channel_idx_tbl[node_inst * adev->umc.umc_inst_num *
+ adev->umc.channel_inst_num +
+ umc_inst * adev->umc.channel_inst_num +
+ ch_inst];
+ /* translate umc channel address to soc pa, 3 parts are included */
+ soc_pa = ADDR_OF_32KB_BLOCK(na) |
+ ADDR_OF_256B_BLOCK(channel_index) |
+ OFFSET_IN_256B_BLOCK(na);
+
+ /* the umc channel bits are not original values, they are hashed */
+ UMC_V12_0_SET_CHANNEL_HASH(channel_index, soc_pa);
+
+ /* clear [C3 C2] in soc physical address */
+ soc_pa &= ~(0x3ULL << UMC_V12_0_PA_C2_BIT);
+ /* clear [C4] in soc physical address */
+ soc_pa &= ~(0x1ULL << UMC_V12_0_PA_C4_BIT);
+
+ row_xor = row ^ (0x1ULL << 13);
+ /* loop for all possibilities of [C4 C3 C2] */
+ for (column = 0; column < UMC_V12_0_NA_MAP_PA_NUM; column++) {
+ retired_page = soc_pa | ((column & 0x3) << UMC_V12_0_PA_C2_BIT);
+ retired_page |= (((column & 0x4) >> 2) << UMC_V12_0_PA_C4_BIT);
+ /* include column bit 0 and 1 */
+ col &= 0x3;
+ col |= (column << 2);
+ dev_info(adev->dev,
+ "Error Address(PA):0x%-10llx Row:0x%-4x Col:0x%-2x Bank:0x%x Channel:0x%x\n",
+ retired_page, row, col, bank, channel_index);
+ amdgpu_umc_fill_error_record(err_data, err_addr,
+ retired_page, channel_index, umc_inst);
+
+ /* shift R13 bit */
+ retired_page ^= (0x1ULL << UMC_V12_0_PA_R13_BIT);
+ dev_info(adev->dev,
+ "Error Address(PA):0x%-10llx Row:0x%-4x Col:0x%-2x Bank:0x%x Channel:0x%x\n",
+ retired_page, row_xor, col, bank, channel_index);
+ amdgpu_umc_fill_error_record(err_data, err_addr,
+ retired_page, channel_index, umc_inst);
+ }
+}
+
+static int umc_v12_0_query_error_address(struct amdgpu_device *adev,
+ uint32_t node_inst, uint32_t umc_inst,
+ uint32_t ch_inst, void *data)
+{
+ uint64_t mc_umc_status_addr;
+ uint64_t mc_umc_status, err_addr;
+ uint64_t mc_umc_addrt0;
+ struct ras_err_data *err_data = (struct ras_err_data *)data;
+ uint64_t umc_reg_offset =
+ get_umc_v12_0_reg_offset(adev, node_inst, umc_inst, ch_inst);
+
+ mc_umc_status_addr =
+ SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
+
+ mc_umc_status = RREG64_PCIE_EXT((mc_umc_status_addr + umc_reg_offset) * 4);
+
+ if (mc_umc_status == 0)
+ return 0;
+
+ if (!err_data->err_addr) {
+ /* clear umc status */
+ WREG64_PCIE_EXT((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
+
+ return 0;
+ }
+
+ /* calculate error address if ue error is detected */
+ if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
+ REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, AddrV) == 1 &&
+ REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1) {
+
+ mc_umc_addrt0 =
+ SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_ADDRT0);
+
+ err_addr = RREG64_PCIE_EXT((mc_umc_addrt0 + umc_reg_offset) * 4);
+
+ err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
+
+ umc_v12_0_convert_error_address(adev, err_data, err_addr,
+ ch_inst, umc_inst, node_inst);
+ }
+
+ /* clear umc status */
+ WREG64_PCIE_EXT((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
+
+ return 0;
+}
+
+static void umc_v12_0_query_ras_error_address(struct amdgpu_device *adev,
+ void *ras_error_status)
+{
+ amdgpu_umc_loop_channels(adev,
+ umc_v12_0_query_error_address, ras_error_status);
+}
+
+static int umc_v12_0_err_cnt_init_per_channel(struct amdgpu_device *adev,
+ uint32_t node_inst, uint32_t umc_inst,
+ uint32_t ch_inst, void *data)
+{
+ uint32_t odecc_cnt_sel;
+ uint64_t odecc_cnt_sel_addr, odecc_err_cnt_addr;
+ uint64_t umc_reg_offset =
+ get_umc_v12_0_reg_offset(adev, node_inst, umc_inst, ch_inst);
+
+ odecc_cnt_sel_addr =
+ SOC15_REG_OFFSET(UMC, 0, regUMCCH0_OdEccCntSel);
+ odecc_err_cnt_addr =
+ SOC15_REG_OFFSET(UMC, 0, regUMCCH0_OdEccErrCnt);
+
+ odecc_cnt_sel = RREG32_PCIE_EXT((odecc_cnt_sel_addr + umc_reg_offset) * 4);
+
+ /* set ce error interrupt type to APIC based interrupt */
+ odecc_cnt_sel = REG_SET_FIELD(odecc_cnt_sel, UMCCH0_OdEccCntSel,
+ OdEccErrInt, 0x1);
+ WREG32_PCIE_EXT((odecc_cnt_sel_addr + umc_reg_offset) * 4, odecc_cnt_sel);
+
+ /* set error count to initial value */
+ WREG32_PCIE_EXT((odecc_err_cnt_addr + umc_reg_offset) * 4, UMC_V12_0_CE_CNT_INIT);
+
+ return 0;
+}
+
+static void umc_v12_0_err_cnt_init(struct amdgpu_device *adev)
+{
+ amdgpu_umc_loop_channels(adev,
+ umc_v12_0_err_cnt_init_per_channel, NULL);
+}
+
+static bool umc_v12_0_query_ras_poison_mode(struct amdgpu_device *adev)
+{
+ /*
+ * Force return true, because regUMCCH0_EccCtrl
+ * is not accessible from host side
+ */
+ return true;
+}
+
+const struct amdgpu_ras_block_hw_ops umc_v12_0_ras_hw_ops = {
+ .query_ras_error_count = umc_v12_0_query_ras_error_count,
+ .query_ras_error_address = umc_v12_0_query_ras_error_address,
+};
+
+struct amdgpu_umc_ras umc_v12_0_ras = {
+ .ras_block = {
+ .hw_ops = &umc_v12_0_ras_hw_ops,
+ },
+ .err_cnt_init = umc_v12_0_err_cnt_init,
+ .query_ras_poison_mode = umc_v12_0_query_ras_poison_mode,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.h b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.h
new file mode 100644
index 000000000000..b34b1e358f8b
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __UMC_V12_0_H__
+#define __UMC_V12_0_H__
+
+#include "soc15_common.h"
+#include "amdgpu.h"
+
+#define UMC_V12_0_NODE_DIST 0x40000000
+#define UMC_V12_0_INST_DIST 0x40000
+
+/* UMC register per channel offset */
+#define UMC_V12_0_PER_CHANNEL_OFFSET 0x400
+
+/* UMC cross node offset */
+#define UMC_V12_0_CROSS_NODE_OFFSET 0x100000000
+
+/* OdEccErrCnt max value */
+#define UMC_V12_0_CE_CNT_MAX 0xffff
+/* umc ce interrupt threshold */
+#define UMC_V12_0_CE_INT_THRESHOLD 0xffff
+/* umc ce count initial value */
+#define UMC_V12_0_CE_CNT_INIT (UMC_V12_0_CE_CNT_MAX - UMC_V12_0_CE_INT_THRESHOLD)
+
+/* number of umc channel instance with memory map register access */
+#define UMC_V12_0_CHANNEL_INSTANCE_NUM 8
+/* number of umc instance with memory map register access */
+#define UMC_V12_0_UMC_INSTANCE_NUM 4
+
+/* Total channel instances for all available umc nodes */
+#define UMC_V12_0_TOTAL_CHANNEL_NUM(adev) \
+ (UMC_V12_0_CHANNEL_INSTANCE_NUM * (adev)->gmc.num_umc)
+
+/* one piece of normalized address is mapped to 8 pieces of physical address */
+#define UMC_V12_0_NA_MAP_PA_NUM 8
+/* R13 bit shift should be considered, double the number */
+#define UMC_V12_0_BAD_PAGE_NUM_PER_CHANNEL (UMC_V12_0_NA_MAP_PA_NUM * 2)
+/* bank bits in MCA error address */
+#define UMC_V12_0_MCA_B0_BIT 6
+#define UMC_V12_0_MCA_B1_BIT 7
+#define UMC_V12_0_MCA_B2_BIT 8
+#define UMC_V12_0_MCA_B3_BIT 9
+/* column bits in SOC physical address */
+#define UMC_V12_0_PA_C2_BIT 15
+#define UMC_V12_0_PA_C4_BIT 21
+/* row bits in SOC physical address */
+#define UMC_V12_0_PA_R13_BIT 35
+/* channel index bits in SOC physical address */
+#define UMC_V12_0_PA_CH4_BIT 12
+#define UMC_V12_0_PA_CH5_BIT 13
+#define UMC_V12_0_PA_CH6_BIT 14
+
+/* bank hash settings */
+#define UMC_V12_0_XOR_EN0 1
+#define UMC_V12_0_XOR_EN1 1
+#define UMC_V12_0_XOR_EN2 1
+#define UMC_V12_0_XOR_EN3 1
+#define UMC_V12_0_COL_XOR0 0x0
+#define UMC_V12_0_COL_XOR1 0x0
+#define UMC_V12_0_COL_XOR2 0x800
+#define UMC_V12_0_COL_XOR3 0x1000
+#define UMC_V12_0_ROW_XOR0 0x11111
+#define UMC_V12_0_ROW_XOR1 0x22222
+#define UMC_V12_0_ROW_XOR2 0x4444
+#define UMC_V12_0_ROW_XOR3 0x8888
+
+/* channel hash settings */
+#define UMC_V12_0_HASH_4K 0
+#define UMC_V12_0_HASH_64K 1
+#define UMC_V12_0_HASH_2M 1
+#define UMC_V12_0_HASH_1G 1
+#define UMC_V12_0_HASH_1T 1
+
+/* XOR some bits of PA into CH4~CH6 bits (bits 12~14 of PA),
+ * hash bit is only effective when related setting is enabled
+ */
+#define UMC_V12_0_CHANNEL_HASH_CH4(channel_idx, pa) ((((channel_idx) >> 5) & 0x1) ^ \
+ (((pa) >> 20) & 0x1ULL & UMC_V12_0_HASH_64K) ^ \
+ (((pa) >> 27) & 0x1ULL & UMC_V12_0_HASH_2M) ^ \
+ (((pa) >> 34) & 0x1ULL & UMC_V12_0_HASH_1G) ^ \
+ (((pa) >> 41) & 0x1ULL & UMC_V12_0_HASH_1T))
+#define UMC_V12_0_CHANNEL_HASH_CH5(channel_idx, pa) ((((channel_idx) >> 6) & 0x1) ^ \
+ (((pa) >> 21) & 0x1ULL & UMC_V12_0_HASH_64K) ^ \
+ (((pa) >> 28) & 0x1ULL & UMC_V12_0_HASH_2M) ^ \
+ (((pa) >> 35) & 0x1ULL & UMC_V12_0_HASH_1G) ^ \
+ (((pa) >> 42) & 0x1ULL & UMC_V12_0_HASH_1T))
+#define UMC_V12_0_CHANNEL_HASH_CH6(channel_idx, pa) ((((channel_idx) >> 4) & 0x1) ^ \
+ (((pa) >> 19) & 0x1ULL & UMC_V12_0_HASH_64K) ^ \
+ (((pa) >> 26) & 0x1ULL & UMC_V12_0_HASH_2M) ^ \
+ (((pa) >> 33) & 0x1ULL & UMC_V12_0_HASH_1G) ^ \
+ (((pa) >> 40) & 0x1ULL & UMC_V12_0_HASH_1T) ^ \
+ (((pa) >> 47) & 0x1ULL & UMC_V12_0_HASH_4K))
+#define UMC_V12_0_SET_CHANNEL_HASH(channel_idx, pa) do { \
+ (pa) &= ~(0x7ULL << UMC_V12_0_PA_CH4_BIT); \
+ (pa) |= (UMC_V12_0_CHANNEL_HASH_CH4(channel_idx, pa) << UMC_V12_0_PA_CH4_BIT); \
+ (pa) |= (UMC_V12_0_CHANNEL_HASH_CH5(channel_idx, pa) << UMC_V12_0_PA_CH5_BIT); \
+ (pa) |= (UMC_V12_0_CHANNEL_HASH_CH6(channel_idx, pa) << UMC_V12_0_PA_CH6_BIT); \
+ } while (0)
+
+bool umc_v12_0_is_uncorrectable_error(uint64_t mc_umc_status);
+bool umc_v12_0_is_correctable_error(uint64_t mc_umc_status);
+
+extern const uint32_t
+ umc_v12_0_channel_idx_tbl[]
+ [UMC_V12_0_UMC_INSTANCE_NUM]
+ [UMC_V12_0_CHANNEL_INSTANCE_NUM];
+
+extern struct amdgpu_umc_ras umc_v12_0_ras;
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
index 46bfdee79bfd..c4c77257710c 100644
--- a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
@@ -336,7 +336,7 @@ static void umc_v8_10_ecc_info_query_correctable_error_count(struct amdgpu_devic
uint32_t node_inst, uint32_t umc_inst, uint32_t ch_inst,
unsigned long *error_count)
{
- uint64_t mc_umc_status;
+ uint16_t ecc_ce_cnt;
uint32_t eccinfo_table_idx;
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
@@ -345,12 +345,10 @@ static void umc_v8_10_ecc_info_query_correctable_error_count(struct amdgpu_devic
umc_inst * adev->umc.channel_inst_num +
ch_inst;
- /* check the MCUMC_STATUS */
- mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status;
- if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
- REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1) {
- *error_count += 1;
- }
+ /* Retrieve CE count */
+ ecc_ce_cnt = ras->umc_ecc.ecc[eccinfo_table_idx].ce_count_lo_chip;
+ if (ecc_ce_cnt)
+ *error_count += ecc_ce_cnt;
}
static void umc_v8_10_ecc_info_query_uncorrectable_error_count(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
new file mode 100644
index 000000000000..8e7b763cfdb7
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include "amdgpu.h"
+#include "soc15_common.h"
+#include "soc21.h"
+#include "vcn/vcn_4_0_0_offset.h"
+#include "vcn/vcn_4_0_0_sh_mask.h"
+
+#include "amdgpu_umsch_mm.h"
+#include "umsch_mm_4_0_api_def.h"
+#include "umsch_mm_v4_0.h"
+
+#define regUVD_IPX_DLDO_CONFIG 0x0064
+#define regUVD_IPX_DLDO_CONFIG_BASE_IDX 1
+#define regUVD_IPX_DLDO_STATUS 0x0065
+#define regUVD_IPX_DLDO_STATUS_BASE_IDX 1
+
+#define UVD_IPX_DLDO_CONFIG__ONO0_PWR_CONFIG__SHIFT 0x00000002
+#define UVD_IPX_DLDO_CONFIG__ONO0_PWR_CONFIG_MASK 0x0000000cUL
+#define UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS__SHIFT 0x00000001
+#define UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS_MASK 0x00000002UL
+
+static int umsch_mm_v4_0_load_microcode(struct amdgpu_umsch_mm *umsch)
+{
+ struct amdgpu_device *adev = umsch->ring.adev;
+ uint64_t data;
+ int r;
+
+ r = amdgpu_umsch_mm_allocate_ucode_buffer(umsch);
+ if (r)
+ return r;
+
+ r = amdgpu_umsch_mm_allocate_ucode_data_buffer(umsch);
+ if (r)
+ goto err_free_ucode_bo;
+
+ umsch->cmd_buf_curr_ptr = umsch->cmd_buf_ptr;
+
+ if (amdgpu_ip_version(adev, VCN_HWIP, 0) == IP_VERSION(4, 0, 5)) {
+ WREG32_SOC15(VCN, 0, regUVD_IPX_DLDO_CONFIG,
+ 1 << UVD_IPX_DLDO_CONFIG__ONO0_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, 0, regUVD_IPX_DLDO_STATUS,
+ 0 << UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS__SHIFT,
+ UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS_MASK);
+ }
+
+ data = RREG32_SOC15(VCN, 0, regUMSCH_MES_RESET_CTRL);
+ data = REG_SET_FIELD(data, UMSCH_MES_RESET_CTRL, MES_CORE_SOFT_RESET, 0);
+ WREG32_SOC15_UMSCH(regUMSCH_MES_RESET_CTRL, data);
+
+ data = RREG32_SOC15(VCN, 0, regVCN_MES_CNTL);
+ data = REG_SET_FIELD(data, VCN_MES_CNTL, MES_INVALIDATE_ICACHE, 1);
+ data = REG_SET_FIELD(data, VCN_MES_CNTL, MES_PIPE0_RESET, 1);
+ data = REG_SET_FIELD(data, VCN_MES_CNTL, MES_PIPE0_ACTIVE, 0);
+ data = REG_SET_FIELD(data, VCN_MES_CNTL, MES_HALT, 1);
+ WREG32_SOC15_UMSCH(regVCN_MES_CNTL, data);
+
+ data = RREG32_SOC15(VCN, 0, regVCN_MES_IC_BASE_CNTL);
+ data = REG_SET_FIELD(data, VCN_MES_IC_BASE_CNTL, VMID, 0);
+ data = REG_SET_FIELD(data, VCN_MES_IC_BASE_CNTL, EXE_DISABLE, 0);
+ data = REG_SET_FIELD(data, VCN_MES_IC_BASE_CNTL, CACHE_POLICY, 0);
+ WREG32_SOC15_UMSCH(regVCN_MES_IC_BASE_CNTL, data);
+
+ WREG32_SOC15_UMSCH(regVCN_MES_INTR_ROUTINE_START,
+ lower_32_bits(adev->umsch_mm.irq_start_addr >> 2));
+ WREG32_SOC15_UMSCH(regVCN_MES_INTR_ROUTINE_START_HI,
+ upper_32_bits(adev->umsch_mm.irq_start_addr >> 2));
+
+ WREG32_SOC15_UMSCH(regVCN_MES_PRGRM_CNTR_START,
+ lower_32_bits(adev->umsch_mm.uc_start_addr >> 2));
+ WREG32_SOC15_UMSCH(regVCN_MES_PRGRM_CNTR_START_HI,
+ upper_32_bits(adev->umsch_mm.uc_start_addr >> 2));
+
+ WREG32_SOC15_UMSCH(regVCN_MES_LOCAL_INSTR_BASE_LO, 0);
+ WREG32_SOC15_UMSCH(regVCN_MES_LOCAL_INSTR_BASE_HI, 0);
+
+ data = adev->umsch_mm.uc_start_addr + adev->umsch_mm.ucode_size - 1;
+ WREG32_SOC15_UMSCH(regVCN_MES_LOCAL_INSTR_MASK_LO, lower_32_bits(data));
+ WREG32_SOC15_UMSCH(regVCN_MES_LOCAL_INSTR_MASK_HI, upper_32_bits(data));
+
+ data = adev->firmware.load_type == AMDGPU_FW_LOAD_PSP ?
+ 0 : adev->umsch_mm.ucode_fw_gpu_addr;
+ WREG32_SOC15_UMSCH(regVCN_MES_IC_BASE_LO, lower_32_bits(data));
+ WREG32_SOC15_UMSCH(regVCN_MES_IC_BASE_HI, upper_32_bits(data));
+
+ WREG32_SOC15_UMSCH(regVCN_MES_MIBOUND_LO, 0x1FFFFF);
+
+ WREG32_SOC15_UMSCH(regVCN_MES_LOCAL_BASE0_LO,
+ lower_32_bits(adev->umsch_mm.data_start_addr));
+ WREG32_SOC15_UMSCH(regVCN_MES_LOCAL_BASE0_HI,
+ upper_32_bits(adev->umsch_mm.data_start_addr));
+
+ WREG32_SOC15_UMSCH(regVCN_MES_LOCAL_MASK0_LO,
+ lower_32_bits(adev->umsch_mm.data_size - 1));
+ WREG32_SOC15_UMSCH(regVCN_MES_LOCAL_MASK0_HI,
+ upper_32_bits(adev->umsch_mm.data_size - 1));
+
+ data = adev->firmware.load_type == AMDGPU_FW_LOAD_PSP ?
+ 0 : adev->umsch_mm.data_fw_gpu_addr;
+ WREG32_SOC15_UMSCH(regVCN_MES_DC_BASE_LO, lower_32_bits(data));
+ WREG32_SOC15_UMSCH(regVCN_MES_DC_BASE_HI, upper_32_bits(data));
+
+ WREG32_SOC15_UMSCH(regVCN_MES_MDBOUND_LO, 0x3FFFF);
+
+ data = RREG32_SOC15(VCN, 0, regUVD_UMSCH_FORCE);
+ data = REG_SET_FIELD(data, UVD_UMSCH_FORCE, IC_FORCE_GPUVM, 1);
+ data = REG_SET_FIELD(data, UVD_UMSCH_FORCE, DC_FORCE_GPUVM, 1);
+ WREG32_SOC15_UMSCH(regUVD_UMSCH_FORCE, data);
+
+ data = RREG32_SOC15(VCN, 0, regVCN_MES_IC_OP_CNTL);
+ data = REG_SET_FIELD(data, VCN_MES_IC_OP_CNTL, PRIME_ICACHE, 0);
+ data = REG_SET_FIELD(data, VCN_MES_IC_OP_CNTL, INVALIDATE_CACHE, 1);
+ WREG32_SOC15_UMSCH(regVCN_MES_IC_OP_CNTL, data);
+
+ data = RREG32_SOC15(VCN, 0, regVCN_MES_IC_OP_CNTL);
+ data = REG_SET_FIELD(data, VCN_MES_IC_OP_CNTL, PRIME_ICACHE, 1);
+ WREG32_SOC15_UMSCH(regVCN_MES_IC_OP_CNTL, data);
+
+ WREG32_SOC15_UMSCH(regVCN_MES_GP0_LO, 0);
+ WREG32_SOC15_UMSCH(regVCN_MES_GP0_HI, 0);
+
+ WREG32_SOC15_UMSCH(regVCN_MES_GP1_LO, 0);
+ WREG32_SOC15_UMSCH(regVCN_MES_GP1_HI, 0);
+
+ data = RREG32_SOC15(VCN, 0, regVCN_MES_CNTL);
+ data = REG_SET_FIELD(data, VCN_MES_CNTL, MES_INVALIDATE_ICACHE, 0);
+ data = REG_SET_FIELD(data, VCN_MES_CNTL, MES_PIPE0_RESET, 0);
+ data = REG_SET_FIELD(data, VCN_MES_CNTL, MES_HALT, 0);
+ data = REG_SET_FIELD(data, VCN_MES_CNTL, MES_PIPE0_ACTIVE, 1);
+ WREG32_SOC15_UMSCH(regVCN_MES_CNTL, data);
+
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
+ amdgpu_umsch_mm_psp_execute_cmd_buf(umsch);
+
+ r = SOC15_WAIT_ON_RREG(VCN, 0, regVCN_MES_MSTATUS_LO, 0xAAAAAAAA, 0xFFFFFFFF);
+ if (r) {
+ dev_err(adev->dev, "UMSCH FW Load: Failed, regVCN_MES_MSTATUS_LO: 0x%08x\n",
+ RREG32_SOC15(VCN, 0, regVCN_MES_MSTATUS_LO));
+ goto err_free_data_bo;
+ }
+
+ return 0;
+
+err_free_data_bo:
+ amdgpu_bo_free_kernel(&adev->umsch_mm.data_fw_obj,
+ &adev->umsch_mm.data_fw_gpu_addr,
+ (void **)&adev->umsch_mm.data_fw_ptr);
+err_free_ucode_bo:
+ amdgpu_bo_free_kernel(&adev->umsch_mm.ucode_fw_obj,
+ &adev->umsch_mm.ucode_fw_gpu_addr,
+ (void **)&adev->umsch_mm.ucode_fw_ptr);
+ return r;
+}
+
+static void umsch_mm_v4_0_aggregated_doorbell_init(struct amdgpu_umsch_mm *umsch)
+{
+ struct amdgpu_device *adev = umsch->ring.adev;
+ uint32_t data;
+
+ data = RREG32_SOC15(VCN, 0, regVCN_AGDB_CTRL0);
+ data = REG_SET_FIELD(data, VCN_AGDB_CTRL0, OFFSET,
+ umsch->agdb_index[CONTEXT_PRIORITY_LEVEL_REALTIME]);
+ data = REG_SET_FIELD(data, VCN_AGDB_CTRL0, EN, 1);
+ WREG32_SOC15(VCN, 0, regVCN_AGDB_CTRL0, data);
+
+ data = RREG32_SOC15(VCN, 0, regVCN_AGDB_CTRL1);
+ data = REG_SET_FIELD(data, VCN_AGDB_CTRL1, OFFSET,
+ umsch->agdb_index[CONTEXT_PRIORITY_LEVEL_FOCUS]);
+ data = REG_SET_FIELD(data, VCN_AGDB_CTRL1, EN, 1);
+ WREG32_SOC15(VCN, 0, regVCN_AGDB_CTRL1, data);
+
+ data = RREG32_SOC15(VCN, 0, regVCN_AGDB_CTRL2);
+ data = REG_SET_FIELD(data, VCN_AGDB_CTRL2, OFFSET,
+ umsch->agdb_index[CONTEXT_PRIORITY_LEVEL_NORMAL]);
+ data = REG_SET_FIELD(data, VCN_AGDB_CTRL2, EN, 1);
+ WREG32_SOC15(VCN, 0, regVCN_AGDB_CTRL2, data);
+
+ data = RREG32_SOC15(VCN, 0, regVCN_AGDB_CTRL3);
+ data = REG_SET_FIELD(data, VCN_AGDB_CTRL3, OFFSET,
+ umsch->agdb_index[CONTEXT_PRIORITY_LEVEL_IDLE]);
+ data = REG_SET_FIELD(data, VCN_AGDB_CTRL3, EN, 1);
+ WREG32_SOC15(VCN, 0, regVCN_AGDB_CTRL3, data);
+}
+
+static int umsch_mm_v4_0_ring_start(struct amdgpu_umsch_mm *umsch)
+{
+ struct amdgpu_ring *ring = &umsch->ring;
+ struct amdgpu_device *adev = ring->adev;
+ uint32_t data;
+
+ data = RREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_DB_CTRL);
+ data = REG_SET_FIELD(data, VCN_UMSCH_RB_DB_CTRL, OFFSET, ring->doorbell_index);
+ data = REG_SET_FIELD(data, VCN_UMSCH_RB_DB_CTRL, EN, 1);
+ WREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_DB_CTRL, data);
+
+ adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
+ (adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
+
+ WREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_BASE_LO, lower_32_bits(ring->gpu_addr));
+ WREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+
+ WREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_SIZE, ring->ring_size);
+
+ data = RREG32_SOC15(VCN, 0, regVCN_RB_ENABLE);
+ data &= ~(VCN_RB_ENABLE__AUDIO_RB_EN_MASK);
+ WREG32_SOC15(VCN, 0, regVCN_RB_ENABLE, data);
+
+ umsch_mm_v4_0_aggregated_doorbell_init(umsch);
+
+ return 0;
+}
+
+static int umsch_mm_v4_0_ring_stop(struct amdgpu_umsch_mm *umsch)
+{
+ struct amdgpu_ring *ring = &umsch->ring;
+ struct amdgpu_device *adev = ring->adev;
+ uint32_t data;
+
+ data = RREG32_SOC15(VCN, 0, regVCN_RB_ENABLE);
+ data = REG_SET_FIELD(data, VCN_RB_ENABLE, UMSCH_RB_EN, 0);
+ WREG32_SOC15(VCN, 0, regVCN_RB_ENABLE, data);
+
+ data = RREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_DB_CTRL);
+ data = REG_SET_FIELD(data, VCN_UMSCH_RB_DB_CTRL, EN, 0);
+ WREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_DB_CTRL, data);
+
+ if (amdgpu_ip_version(adev, VCN_HWIP, 0) == IP_VERSION(4, 0, 5)) {
+ WREG32_SOC15(VCN, 0, regUVD_IPX_DLDO_CONFIG,
+ 2 << UVD_IPX_DLDO_CONFIG__ONO0_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, 0, regUVD_IPX_DLDO_STATUS,
+ 1 << UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS__SHIFT,
+ UVD_IPX_DLDO_STATUS__ONO0_PWR_STATUS_MASK);
+ }
+
+ return 0;
+}
+
+static int umsch_mm_v4_0_set_hw_resources(struct amdgpu_umsch_mm *umsch)
+{
+ union UMSCHAPI__SET_HW_RESOURCES set_hw_resources = {};
+ struct amdgpu_device *adev = umsch->ring.adev;
+ int r;
+
+ set_hw_resources.header.type = UMSCH_API_TYPE_SCHEDULER;
+ set_hw_resources.header.opcode = UMSCH_API_SET_HW_RSRC;
+ set_hw_resources.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
+
+ set_hw_resources.vmid_mask_mm_vcn = umsch->vmid_mask_mm_vcn;
+ set_hw_resources.vmid_mask_mm_vpe = umsch->vmid_mask_mm_vpe;
+ set_hw_resources.engine_mask = umsch->engine_mask;
+
+ set_hw_resources.vcn0_hqd_mask[0] = umsch->vcn0_hqd_mask;
+ set_hw_resources.vcn1_hqd_mask[0] = umsch->vcn1_hqd_mask;
+ set_hw_resources.vcn_hqd_mask[0] = umsch->vcn_hqd_mask[0];
+ set_hw_resources.vcn_hqd_mask[1] = umsch->vcn_hqd_mask[1];
+ set_hw_resources.vpe_hqd_mask[0] = umsch->vpe_hqd_mask;
+
+ set_hw_resources.g_sch_ctx_gpu_mc_ptr = umsch->sch_ctx_gpu_addr;
+
+ set_hw_resources.enable_level_process_quantum_check = 1;
+
+ memcpy(set_hw_resources.mmhub_base, adev->reg_offset[MMHUB_HWIP][0],
+ sizeof(uint32_t) * 5);
+ set_hw_resources.mmhub_version =
+ IP_VERSION_MAJ_MIN_REV(amdgpu_ip_version(adev, MMHUB_HWIP, 0));
+
+ memcpy(set_hw_resources.osssys_base, adev->reg_offset[OSSSYS_HWIP][0],
+ sizeof(uint32_t) * 5);
+ set_hw_resources.osssys_version =
+ IP_VERSION_MAJ_MIN_REV(amdgpu_ip_version(adev, OSSSYS_HWIP, 0));
+
+ set_hw_resources.vcn_version =
+ IP_VERSION_MAJ_MIN_REV(amdgpu_ip_version(adev, VCN_HWIP, 0));
+ set_hw_resources.vpe_version =
+ IP_VERSION_MAJ_MIN_REV(amdgpu_ip_version(adev, VPE_HWIP, 0));
+
+ set_hw_resources.api_status.api_completion_fence_addr = umsch->ring.fence_drv.gpu_addr;
+ set_hw_resources.api_status.api_completion_fence_value = ++umsch->ring.fence_drv.sync_seq;
+
+ r = amdgpu_umsch_mm_submit_pkt(umsch, &set_hw_resources.max_dwords_in_api,
+ API_FRAME_SIZE_IN_DWORDS);
+ if (r)
+ return r;
+
+ r = amdgpu_umsch_mm_query_fence(umsch);
+ if (r) {
+ dev_err(adev->dev, "UMSCH SET_HW_RESOURCES: Failed\n");
+ return r;
+ }
+
+ return 0;
+}
+
+static int umsch_mm_v4_0_add_queue(struct amdgpu_umsch_mm *umsch,
+ struct umsch_mm_add_queue_input *input_ptr)
+{
+ struct amdgpu_device *adev = umsch->ring.adev;
+ union UMSCHAPI__ADD_QUEUE add_queue = {};
+ int r;
+
+ add_queue.header.type = UMSCH_API_TYPE_SCHEDULER;
+ add_queue.header.opcode = UMSCH_API_ADD_QUEUE;
+ add_queue.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
+
+ add_queue.process_id = input_ptr->process_id;
+ add_queue.page_table_base_addr = input_ptr->page_table_base_addr;
+ add_queue.process_va_start = input_ptr->process_va_start;
+ add_queue.process_va_end = input_ptr->process_va_end;
+ add_queue.process_quantum = input_ptr->process_quantum;
+ add_queue.process_csa_addr = input_ptr->process_csa_addr;
+ add_queue.context_quantum = input_ptr->context_quantum;
+ add_queue.context_csa_addr = input_ptr->context_csa_addr;
+ add_queue.inprocess_context_priority = input_ptr->inprocess_context_priority;
+ add_queue.context_global_priority_level =
+ (enum UMSCH_AMD_PRIORITY_LEVEL)input_ptr->context_global_priority_level;
+ add_queue.doorbell_offset_0 = input_ptr->doorbell_offset_0;
+ add_queue.doorbell_offset_1 = input_ptr->doorbell_offset_1;
+ add_queue.affinity.u32All = input_ptr->affinity;
+ add_queue.mqd_addr = input_ptr->mqd_addr;
+ add_queue.engine_type = (enum UMSCH_ENGINE_TYPE)input_ptr->engine_type;
+ add_queue.h_context = input_ptr->h_context;
+ add_queue.h_queue = input_ptr->h_queue;
+ add_queue.vm_context_cntl = input_ptr->vm_context_cntl;
+ add_queue.is_context_suspended = input_ptr->is_context_suspended;
+
+ add_queue.api_status.api_completion_fence_addr = umsch->ring.fence_drv.gpu_addr;
+ add_queue.api_status.api_completion_fence_value = ++umsch->ring.fence_drv.sync_seq;
+
+ r = amdgpu_umsch_mm_submit_pkt(umsch, &add_queue.max_dwords_in_api,
+ API_FRAME_SIZE_IN_DWORDS);
+ if (r)
+ return r;
+
+ r = amdgpu_umsch_mm_query_fence(umsch);
+ if (r) {
+ dev_err(adev->dev, "UMSCH ADD_QUEUE: Failed\n");
+ return r;
+ }
+
+ return 0;
+}
+
+static int umsch_mm_v4_0_remove_queue(struct amdgpu_umsch_mm *umsch,
+ struct umsch_mm_remove_queue_input *input_ptr)
+{
+ union UMSCHAPI__REMOVE_QUEUE remove_queue = {};
+ struct amdgpu_device *adev = umsch->ring.adev;
+ int r;
+
+ remove_queue.header.type = UMSCH_API_TYPE_SCHEDULER;
+ remove_queue.header.opcode = UMSCH_API_REMOVE_QUEUE;
+ remove_queue.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
+
+ remove_queue.doorbell_offset_0 = input_ptr->doorbell_offset_0;
+ remove_queue.doorbell_offset_1 = input_ptr->doorbell_offset_1;
+ remove_queue.context_csa_addr = input_ptr->context_csa_addr;
+
+ remove_queue.api_status.api_completion_fence_addr = umsch->ring.fence_drv.gpu_addr;
+ remove_queue.api_status.api_completion_fence_value = ++umsch->ring.fence_drv.sync_seq;
+
+ r = amdgpu_umsch_mm_submit_pkt(umsch, &remove_queue.max_dwords_in_api,
+ API_FRAME_SIZE_IN_DWORDS);
+ if (r)
+ return r;
+
+ r = amdgpu_umsch_mm_query_fence(umsch);
+ if (r) {
+ dev_err(adev->dev, "UMSCH REMOVE_QUEUE: Failed\n");
+ return r;
+ }
+
+ return 0;
+}
+
+static int umsch_mm_v4_0_set_regs(struct amdgpu_umsch_mm *umsch)
+{
+ struct amdgpu_device *adev = container_of(umsch, struct amdgpu_device, umsch_mm);
+
+ umsch->rb_wptr = SOC15_REG_OFFSET(VCN, 0, regVCN_UMSCH_RB_WPTR);
+ umsch->rb_rptr = SOC15_REG_OFFSET(VCN, 0, regVCN_UMSCH_RB_RPTR);
+
+ return 0;
+}
+
+static const struct umsch_mm_funcs umsch_mm_v4_0_funcs = {
+ .set_hw_resources = umsch_mm_v4_0_set_hw_resources,
+ .add_queue = umsch_mm_v4_0_add_queue,
+ .remove_queue = umsch_mm_v4_0_remove_queue,
+ .set_regs = umsch_mm_v4_0_set_regs,
+ .init_microcode = amdgpu_umsch_mm_init_microcode,
+ .load_microcode = umsch_mm_v4_0_load_microcode,
+ .ring_init = amdgpu_umsch_mm_ring_init,
+ .ring_start = umsch_mm_v4_0_ring_start,
+ .ring_stop = umsch_mm_v4_0_ring_stop,
+};
+
+void umsch_mm_v4_0_set_funcs(struct amdgpu_umsch_mm *umsch)
+{
+ umsch->funcs = &umsch_mm_v4_0_funcs;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.h b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.h
new file mode 100644
index 000000000000..06bc0fa74996
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __UMSCH_MM_V4_0_H__
+#define __UMSCH_MM_V4_0_H__
+
+void umsch_mm_v4_0_set_funcs(struct amdgpu_umsch_mm *umsch);
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c
index 5534c769b655..a6006f231c65 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c
@@ -577,8 +577,6 @@ static int uvd_v3_1_sw_init(void *handle)
ptr += ucode_len;
memcpy(&adev->uvd.keyselect, ptr, 4);
- r = amdgpu_uvd_entity_init(adev);
-
return r;
}
@@ -706,6 +704,13 @@ static int uvd_v3_1_hw_fini(void *handle)
return 0;
}
+static int uvd_v3_1_prepare_suspend(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ return amdgpu_uvd_prepare_suspend(adev);
+}
+
static int uvd_v3_1_suspend(void *handle)
{
int r;
@@ -806,6 +811,7 @@ static const struct amd_ip_funcs uvd_v3_1_ip_funcs = {
.sw_fini = uvd_v3_1_sw_fini,
.hw_init = uvd_v3_1_hw_init,
.hw_fini = uvd_v3_1_hw_fini,
+ .prepare_suspend = uvd_v3_1_prepare_suspend,
.suspend = uvd_v3_1_suspend,
.resume = uvd_v3_1_resume,
.is_idle = uvd_v3_1_is_idle,
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
index c108b8381795..1aa09ad7bbe3 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
@@ -127,8 +127,6 @@ static int uvd_v4_2_sw_init(void *handle)
if (r)
return r;
- r = amdgpu_uvd_entity_init(adev);
-
return r;
}
@@ -220,6 +218,13 @@ static int uvd_v4_2_hw_fini(void *handle)
return 0;
}
+static int uvd_v4_2_prepare_suspend(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ return amdgpu_uvd_prepare_suspend(adev);
+}
+
static int uvd_v4_2_suspend(void *handle)
{
int r;
@@ -756,6 +761,7 @@ static const struct amd_ip_funcs uvd_v4_2_ip_funcs = {
.sw_fini = uvd_v4_2_sw_fini,
.hw_init = uvd_v4_2_hw_init,
.hw_fini = uvd_v4_2_hw_fini,
+ .prepare_suspend = uvd_v4_2_prepare_suspend,
.suspend = uvd_v4_2_suspend,
.resume = uvd_v4_2_resume,
.is_idle = uvd_v4_2_is_idle,
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
index d7e31e48a2b8..f8b229b75435 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
@@ -125,8 +125,6 @@ static int uvd_v5_0_sw_init(void *handle)
if (r)
return r;
- r = amdgpu_uvd_entity_init(adev);
-
return r;
}
@@ -218,6 +216,13 @@ static int uvd_v5_0_hw_fini(void *handle)
return 0;
}
+static int uvd_v5_0_prepare_suspend(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ return amdgpu_uvd_prepare_suspend(adev);
+}
+
static int uvd_v5_0_suspend(void *handle)
{
int r;
@@ -863,6 +868,7 @@ static const struct amd_ip_funcs uvd_v5_0_ip_funcs = {
.sw_fini = uvd_v5_0_sw_fini,
.hw_init = uvd_v5_0_hw_init,
.hw_fini = uvd_v5_0_hw_fini,
+ .prepare_suspend = uvd_v5_0_prepare_suspend,
.suspend = uvd_v5_0_suspend,
.resume = uvd_v5_0_resume,
.is_idle = uvd_v5_0_is_idle,
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
index 5fe872f4bea7..a9a6880f44e3 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
@@ -432,8 +432,6 @@ static int uvd_v6_0_sw_init(void *handle)
}
}
- r = amdgpu_uvd_entity_init(adev);
-
return r;
}
@@ -542,6 +540,13 @@ static int uvd_v6_0_hw_fini(void *handle)
return 0;
}
+static int uvd_v6_0_prepare_suspend(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ return amdgpu_uvd_prepare_suspend(adev);
+}
+
static int uvd_v6_0_suspend(void *handle)
{
int r;
@@ -1528,6 +1533,7 @@ static const struct amd_ip_funcs uvd_v6_0_ip_funcs = {
.sw_fini = uvd_v6_0_sw_fini,
.hw_init = uvd_v6_0_hw_init,
.hw_fini = uvd_v6_0_hw_fini,
+ .prepare_suspend = uvd_v6_0_prepare_suspend,
.suspend = uvd_v6_0_suspend,
.resume = uvd_v6_0_resume,
.is_idle = uvd_v6_0_is_idle,
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
index 86d1d46e1e5e..6068b784dc69 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
@@ -480,10 +480,6 @@ static int uvd_v7_0_sw_init(void *handle)
if (r)
return r;
- r = amdgpu_uvd_entity_init(adev);
- if (r)
- return r;
-
r = amdgpu_virt_alloc_mm_table(adev);
if (r)
return r;
@@ -612,6 +608,13 @@ static int uvd_v7_0_hw_fini(void *handle)
return 0;
}
+static int uvd_v7_0_prepare_suspend(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ return amdgpu_uvd_prepare_suspend(adev);
+}
+
static int uvd_v7_0_suspend(void *handle)
{
int r;
@@ -1787,6 +1790,7 @@ const struct amd_ip_funcs uvd_v7_0_ip_funcs = {
.sw_fini = uvd_v7_0_sw_fini,
.hw_init = uvd_v7_0_hw_init,
.hw_fini = uvd_v7_0_hw_fini,
+ .prepare_suspend = uvd_v7_0_prepare_suspend,
.suspend = uvd_v7_0_suspend,
.resume = uvd_v7_0_resume,
.is_idle = NULL /* uvd_v7_0_is_idle */,
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
index 67eb01fef789..a08e7abca423 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
@@ -441,8 +441,6 @@ static int vce_v2_0_sw_init(void *handle)
return r;
}
- r = amdgpu_vce_entity_init(adev);
-
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index 18f6e62af339..f4760748d349 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -450,8 +450,6 @@ static int vce_v3_0_sw_init(void *handle)
return r;
}
- r = amdgpu_vce_entity_init(adev);
-
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
index e0b70cd3b697..06d787385ad4 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
@@ -486,11 +486,6 @@ static int vce_v4_0_sw_init(void *handle)
return r;
}
-
- r = amdgpu_vce_entity_init(adev);
- if (r)
- return r;
-
r = amdgpu_virt_alloc_mm_table(adev);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index 6fbea38f4d3e..aba403d71806 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -187,7 +187,7 @@ static int vcn_v2_5_sw_init(void *handle)
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
(amdgpu_sriov_vf(adev) ? 2*j : 8*j);
- if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(2, 5, 0))
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(2, 5, 0))
ring->vm_hub = AMDGPU_MMHUB1(0);
else
ring->vm_hub = AMDGPU_MMHUB0(0);
@@ -207,7 +207,8 @@ static int vcn_v2_5_sw_init(void *handle)
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
(amdgpu_sriov_vf(adev) ? (1 + i + 2*j) : (2 + i + 8*j));
- if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(2, 5, 0))
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
+ IP_VERSION(2, 5, 0))
ring->vm_hub = AMDGPU_MMHUB1(0);
else
ring->vm_hub = AMDGPU_MMHUB0(0);
@@ -794,7 +795,7 @@ static void vcn_v2_6_enable_ras(struct amdgpu_device *adev, int inst_idx,
{
uint32_t tmp;
- if (adev->ip_versions[UVD_HWIP][0] != IP_VERSION(2, 6, 0))
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) != IP_VERSION(2, 6, 0))
return;
tmp = VCN_RAS_CNTL__VCPU_VCODEC_REARM_MASK |
@@ -1985,7 +1986,7 @@ static struct amdgpu_vcn_ras vcn_v2_6_ras = {
static void vcn_v2_5_set_ras_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[VCN_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, VCN_HWIP, 0)) {
case IP_VERSION(2, 6, 0):
adev->vcn.ras = &vcn_v2_6_ras;
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index a61ecefdafc5..e02af4de521c 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -100,7 +100,8 @@ static int vcn_v3_0_early_init(void *handle)
/* both instances are harvested, disable the block */
return -ENOENT;
- if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(3, 0, 33))
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
+ IP_VERSION(3, 0, 33))
adev->vcn.num_enc_rings = 0;
else
adev->vcn.num_enc_rings = 2;
@@ -227,9 +228,10 @@ static int vcn_v3_0_sw_init(void *handle)
cpu_to_le32(AMDGPU_VCN_FW_SHARED_FLAG_0_RB);
fw_shared->sw_ring.is_enabled = cpu_to_le32(DEC_SW_RING_ENABLED);
fw_shared->present_flag_0 |= AMDGPU_VCN_SMU_VERSION_INFO_FLAG;
- if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(3, 1, 2))
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 1, 2))
fw_shared->smu_interface_info.smu_interface_type = 2;
- else if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(3, 1, 1))
+ else if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
+ IP_VERSION(3, 1, 1))
fw_shared->smu_interface_info.smu_interface_type = 1;
if (amdgpu_vcnfw_log)
@@ -1255,7 +1257,8 @@ static int vcn_v3_0_start(struct amdgpu_device *adev)
fw_shared->rb.wptr = lower_32_bits(ring->wptr);
fw_shared->multi_queue.decode_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
- if (adev->ip_versions[UVD_HWIP][0] != IP_VERSION(3, 0, 33)) {
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) !=
+ IP_VERSION(3, 0, 33)) {
fw_shared->multi_queue.encode_generalpurpose_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
ring = &adev->vcn.inst[i].ring_enc[0];
WREG32_SOC15(VCN, i, mmUVD_RB_RPTR, lower_32_bits(ring->wptr));
@@ -1628,7 +1631,8 @@ static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev,
UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK,
~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
- if (adev->ip_versions[UVD_HWIP][0] != IP_VERSION(3, 0, 33)) {
+ if (amdgpu_ip_version(adev, UVD_HWIP, 0) !=
+ IP_VERSION(3, 0, 33)) {
/* Restore */
fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
fw_shared->multi_queue.encode_generalpurpose_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 29164289c5f3..48bfcd0d558b 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -169,15 +169,13 @@ static int vcn_v4_0_sw_init(void *handle)
fw_shared->smu_dpm_interface.smu_interface_type = (adev->flags & AMD_IS_APU) ?
AMDGPU_VCN_SMU_DPM_INTERFACE_APU : AMDGPU_VCN_SMU_DPM_INTERFACE_DGPU;
- if (adev->ip_versions[VCN_HWIP][0] == IP_VERSION(4, 0, 2)) {
+ if (amdgpu_ip_version(adev, VCN_HWIP, 0) ==
+ IP_VERSION(4, 0, 2)) {
fw_shared->present_flag_0 |= AMDGPU_FW_SHARED_FLAG_0_DRM_KEY_INJECT;
fw_shared->drm_key_wa.method =
AMDGPU_DRM_KEY_INJECT_WORKAROUND_VCNFW_ASD_HANDSHAKING;
}
- if (amdgpu_sriov_vf(adev))
- fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_VF_RB_SETUP_FLAG);
-
if (amdgpu_vcnfw_log)
amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
}
@@ -876,8 +874,6 @@ static void vcn_v4_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
| UVD_SUVD_CGC_CTRL__IME_MODE_MASK
| UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data);
-
- return;
}
static void vcn_v4_0_enable_ras(struct amdgpu_device *adev, int inst_idx,
@@ -1210,6 +1206,24 @@ static int vcn_v4_0_start(struct amdgpu_device *adev)
return 0;
}
+static int vcn_v4_0_init_ring_metadata(struct amdgpu_device *adev, uint32_t vcn_inst, struct amdgpu_ring *ring_enc)
+{
+ struct amdgpu_vcn_rb_metadata *rb_metadata = NULL;
+ uint8_t *rb_ptr = (uint8_t *)ring_enc->ring;
+
+ rb_ptr += ring_enc->ring_size;
+ rb_metadata = (struct amdgpu_vcn_rb_metadata *)rb_ptr;
+
+ memset(rb_metadata, 0, sizeof(struct amdgpu_vcn_rb_metadata));
+ rb_metadata->size = sizeof(struct amdgpu_vcn_rb_metadata);
+ rb_metadata->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_VF_RB_SETUP_FLAG);
+ rb_metadata->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_VF_RB_DECOUPLE_FLAG);
+ rb_metadata->version = 1;
+ rb_metadata->ring_id = vcn_inst & 0xFF;
+
+ return 0;
+}
+
static int vcn_v4_0_start_sriov(struct amdgpu_device *adev)
{
int i;
@@ -1332,11 +1346,30 @@ static int vcn_v4_0_start_sriov(struct amdgpu_device *adev)
rb_enc_addr = ring_enc->gpu_addr;
rb_setup->is_rb_enabled_flags |= RB_ENABLED;
- rb_setup->rb_addr_lo = lower_32_bits(rb_enc_addr);
- rb_setup->rb_addr_hi = upper_32_bits(rb_enc_addr);
- rb_setup->rb_size = ring_enc->ring_size / 4;
fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_VF_RB_SETUP_FLAG);
+ if (amdgpu_sriov_is_vcn_rb_decouple(adev)) {
+ vcn_v4_0_init_ring_metadata(adev, i, ring_enc);
+
+ memset((void *)&rb_setup->rb_info, 0, sizeof(struct amdgpu_vcn_rb_setup_info) * MAX_NUM_VCN_RB_SETUP);
+ if (!(adev->vcn.harvest_config & (1 << 0))) {
+ rb_setup->rb_info[0].rb_addr_lo = lower_32_bits(adev->vcn.inst[0].ring_enc[0].gpu_addr);
+ rb_setup->rb_info[0].rb_addr_hi = upper_32_bits(adev->vcn.inst[0].ring_enc[0].gpu_addr);
+ rb_setup->rb_info[0].rb_size = adev->vcn.inst[0].ring_enc[0].ring_size / 4;
+ }
+ if (!(adev->vcn.harvest_config & (1 << 1))) {
+ rb_setup->rb_info[2].rb_addr_lo = lower_32_bits(adev->vcn.inst[1].ring_enc[0].gpu_addr);
+ rb_setup->rb_info[2].rb_addr_hi = upper_32_bits(adev->vcn.inst[1].ring_enc[0].gpu_addr);
+ rb_setup->rb_info[2].rb_size = adev->vcn.inst[1].ring_enc[0].ring_size / 4;
+ }
+ fw_shared->decouple.is_enabled = 1;
+ fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_VF_RB_DECOUPLE_FLAG);
+ } else {
+ rb_setup->rb_addr_lo = lower_32_bits(rb_enc_addr);
+ rb_setup->rb_addr_hi = upper_32_bits(rb_enc_addr);
+ rb_setup->rb_size = ring_enc->ring_size / 4;
+ }
+
MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i,
regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW),
lower_32_bits(adev->vcn.inst[i].fw_shared.gpu_addr));
@@ -1808,6 +1841,7 @@ static struct amdgpu_ring_funcs vcn_v4_0_unified_ring_vm_funcs = {
.type = AMDGPU_RING_TYPE_VCN_ENC,
.align_mask = 0x3f,
.nop = VCN_ENC_CMD_NO_OP,
+ .extra_dw = sizeof(struct amdgpu_vcn_rb_metadata),
.get_rptr = vcn_v4_0_unified_ring_get_rptr,
.get_wptr = vcn_v4_0_unified_ring_get_wptr,
.set_wptr = vcn_v4_0_unified_ring_set_wptr,
@@ -1849,7 +1883,7 @@ static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev)
if (adev->vcn.harvest_config & (1 << i))
continue;
- if (adev->ip_versions[VCN_HWIP][0] == IP_VERSION(4, 0, 2))
+ if (amdgpu_ip_version(adev, VCN_HWIP, 0) == IP_VERSION(4, 0, 2))
vcn_v4_0_unified_ring_vm_funcs.secure_submission_supported = true;
adev->vcn.inst[i].ring_enc[0].funcs =
@@ -2021,16 +2055,20 @@ static int vcn_v4_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_
{
uint32_t ip_instance;
- switch (entry->client_id) {
- case SOC15_IH_CLIENTID_VCN:
- ip_instance = 0;
- break;
- case SOC15_IH_CLIENTID_VCN1:
- ip_instance = 1;
- break;
- default:
- DRM_ERROR("Unhandled client id: %d\n", entry->client_id);
- return 0;
+ if (amdgpu_sriov_is_vcn_rb_decouple(adev)) {
+ ip_instance = entry->ring_id;
+ } else {
+ switch (entry->client_id) {
+ case SOC15_IH_CLIENTID_VCN:
+ ip_instance = 0;
+ break;
+ case SOC15_IH_CLIENTID_VCN1:
+ ip_instance = 1;
+ break;
+ default:
+ DRM_ERROR("Unhandled client id: %d\n", entry->client_id);
+ return 0;
+ }
}
DRM_DEBUG("IH: VCN TRAP\n");
@@ -2156,7 +2194,7 @@ static struct amdgpu_vcn_ras vcn_v4_0_ras = {
static void vcn_v4_0_set_ras_funcs(struct amdgpu_device *adev)
{
- switch (adev->ip_versions[VCN_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, VCN_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
adev->vcn.ras = &vcn_v4_0_ras;
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index f85d18cd74ec..810bbfccd6f2 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -1760,6 +1760,11 @@ static void vcn_v4_0_3_enable_ras(struct amdgpu_device *adev,
SOC15_DPG_MODE_OFFSET(VCN, 0, regVCN_RAS_CNTL),
tmp, 0, indirect);
+ tmp = UVD_VCPU_INT_EN2__RASCNTL_VCPU_VCODEC_EN_MASK;
+ WREG32_SOC15_DPG_MODE(inst_idx,
+ SOC15_DPG_MODE_OFFSET(VCN, 0, regUVD_VCPU_INT_EN2),
+ tmp, 0, indirect);
+
tmp = UVD_SYS_INT_EN__RASCNTL_VCPU_VCODEC_EN_MASK;
WREG32_SOC15_DPG_MODE(inst_idx,
SOC15_DPG_MODE_OFFSET(VCN, 0, regUVD_SYS_INT_EN),
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
new file mode 100644
index 000000000000..2eda30e78f61
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -0,0 +1,1779 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/firmware.h>
+#include "amdgpu.h"
+#include "amdgpu_vcn.h"
+#include "amdgpu_pm.h"
+#include "amdgpu_cs.h"
+#include "soc15.h"
+#include "soc15d.h"
+#include "soc15_hw_ip.h"
+#include "vcn_v2_0.h"
+#include "mmsch_v4_0.h"
+#include "vcn_v4_0_5.h"
+
+#include "vcn/vcn_4_0_5_offset.h"
+#include "vcn/vcn_4_0_5_sh_mask.h"
+#include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"
+
+#include <drm/drm_drv.h>
+
+#define mmUVD_DPG_LMA_CTL regUVD_DPG_LMA_CTL
+#define mmUVD_DPG_LMA_CTL_BASE_IDX regUVD_DPG_LMA_CTL_BASE_IDX
+#define mmUVD_DPG_LMA_DATA regUVD_DPG_LMA_DATA
+#define mmUVD_DPG_LMA_DATA_BASE_IDX regUVD_DPG_LMA_DATA_BASE_IDX
+
+#define VCN_VID_SOC_ADDRESS_2_0 0x1fb00
+#define VCN1_VID_SOC_ADDRESS_3_0 0x48300
+
+#define VCN_HARVEST_MMSCH 0
+
+#define RDECODE_MSG_CREATE 0x00000000
+#define RDECODE_MESSAGE_CREATE 0x00000001
+
+static int amdgpu_ih_clientid_vcns[] = {
+ SOC15_IH_CLIENTID_VCN,
+ SOC15_IH_CLIENTID_VCN1
+};
+
+static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev);
+static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev);
+static int vcn_v4_0_5_set_powergating_state(void *handle,
+ enum amd_powergating_state state);
+static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev,
+ int inst_idx, struct dpg_pause_state *new_state);
+static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);
+
+/**
+ * vcn_v4_0_5_early_init - set function pointers and load microcode
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Set ring and irq function pointers
+ * Load microcode from filesystem
+ */
+static int vcn_v4_0_5_early_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ /* re-use enc ring as unified ring */
+ adev->vcn.num_enc_rings = 1;
+ vcn_v4_0_5_set_unified_ring_funcs(adev);
+ vcn_v4_0_5_set_irq_funcs(adev);
+
+ return amdgpu_vcn_early_init(adev);
+}
+
+/**
+ * vcn_v4_0_5_sw_init - sw init for VCN block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Load firmware and sw initialization
+ */
+static int vcn_v4_0_5_sw_init(void *handle)
+{
+ struct amdgpu_ring *ring;
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i, r;
+
+ r = amdgpu_vcn_sw_init(adev);
+ if (r)
+ return r;
+
+ amdgpu_vcn_setup_ucode(adev);
+
+ r = amdgpu_vcn_resume(adev);
+ if (r)
+ return r;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ volatile struct amdgpu_vcn4_fw_shared *fw_shared;
+
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
+ atomic_set(&adev->vcn.inst[i].sched_score, 0);
+
+ /* VCN UNIFIED TRAP */
+ r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i],
+ VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst[i].irq);
+ if (r)
+ return r;
+
+ /* VCN POISON TRAP */
+ r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i],
+ VCN_4_0__SRCID_UVD_POISON, &adev->vcn.inst[i].irq);
+ if (r)
+ return r;
+
+ ring = &adev->vcn.inst[i].ring_enc[0];
+ ring->use_doorbell = true;
+ if (amdgpu_sriov_vf(adev))
+ ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
+ i * (adev->vcn.num_enc_rings + 1) + 1;
+ else
+ ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
+ 2 + 8 * i;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
+ sprintf(ring->name, "vcn_unified_%d", i);
+
+ r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0,
+ AMDGPU_RING_PRIO_0, &adev->vcn.inst[i].sched_score);
+ if (r)
+ return r;
+
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+ fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
+ fw_shared->sq.is_enabled = 1;
+
+ fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_SMU_DPM_INTERFACE_FLAG);
+ fw_shared->smu_dpm_interface.smu_interface_type = (adev->flags & AMD_IS_APU) ?
+ AMDGPU_VCN_SMU_DPM_INTERFACE_APU : AMDGPU_VCN_SMU_DPM_INTERFACE_DGPU;
+
+ if (amdgpu_sriov_vf(adev))
+ fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_VF_RB_SETUP_FLAG);
+
+ if (amdgpu_vcnfw_log)
+ amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
+ }
+
+ if (amdgpu_sriov_vf(adev)) {
+ r = amdgpu_virt_alloc_mm_table(adev);
+ if (r)
+ return r;
+ }
+
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+ adev->vcn.pause_dpg_mode = vcn_v4_0_5_pause_dpg_mode;
+
+ return 0;
+}
+
+/**
+ * vcn_v4_0_5_sw_fini - sw fini for VCN block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * VCN suspend and free up sw allocation
+ */
+static int vcn_v4_0_5_sw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i, r, idx;
+
+ if (drm_dev_enter(adev_to_drm(adev), &idx)) {
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ volatile struct amdgpu_vcn4_fw_shared *fw_shared;
+
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+ fw_shared->present_flag_0 = 0;
+ fw_shared->sq.is_enabled = 0;
+ }
+
+ drm_dev_exit(idx);
+ }
+
+ if (amdgpu_sriov_vf(adev))
+ amdgpu_virt_free_mm_table(adev);
+
+ r = amdgpu_vcn_suspend(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_vcn_sw_fini(adev);
+
+ return r;
+}
+
+/**
+ * vcn_v4_0_5_hw_init - start and test VCN block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Initialize the hardware, boot up the VCPU and do some testing
+ */
+static int vcn_v4_0_5_hw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_ring *ring;
+ int i, r;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
+ ring = &adev->vcn.inst[i].ring_enc[0];
+
+ adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
+ ((adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i), i);
+
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ goto done;
+ }
+
+done:
+ if (!r)
+ DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
+ (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
+
+ return r;
+}
+
+/**
+ * vcn_v4_0_5_hw_fini - stop the hardware block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Stop the VCN block, mark ring as not ready any more
+ */
+static int vcn_v4_0_5_hw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i;
+
+ cancel_delayed_work_sync(&adev->vcn.idle_work);
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+ if (!amdgpu_sriov_vf(adev)) {
+ if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
+ (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
+ RREG32_SOC15(VCN, i, regUVD_STATUS))) {
+ vcn_v4_0_5_set_powergating_state(adev, AMD_PG_STATE_GATE);
+ }
+ }
+
+ amdgpu_irq_put(adev, &adev->vcn.inst[i].irq, 0);
+ }
+
+ return 0;
+}
+
+/**
+ * vcn_v4_0_5_suspend - suspend VCN block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * HW fini and suspend VCN block
+ */
+static int vcn_v4_0_5_suspend(void *handle)
+{
+ int r;
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ r = vcn_v4_0_5_hw_fini(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_vcn_suspend(adev);
+
+ return r;
+}
+
+/**
+ * vcn_v4_0_5_resume - resume VCN block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Resume firmware and hw init VCN block
+ */
+static int vcn_v4_0_5_resume(void *handle)
+{
+ int r;
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ r = amdgpu_vcn_resume(adev);
+ if (r)
+ return r;
+
+ r = vcn_v4_0_5_hw_init(adev);
+
+ return r;
+}
+
+/**
+ * vcn_v4_0_5_mc_resume - memory controller programming
+ *
+ * @adev: amdgpu_device pointer
+ * @inst: instance number
+ *
+ * Let the VCN memory controller know it's offsets
+ */
+static void vcn_v4_0_5_mc_resume(struct amdgpu_device *adev, int inst)
+{
+ uint32_t offset, size;
+ const struct common_firmware_header *hdr;
+
+ hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
+ size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
+
+ /* cache window 0: fw */
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+ WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
+ (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_lo));
+ WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
+ (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_hi));
+ WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET0, 0);
+ offset = 0;
+ } else {
+ WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
+ lower_32_bits(adev->vcn.inst[inst].gpu_addr));
+ WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
+ upper_32_bits(adev->vcn.inst[inst].gpu_addr));
+ offset = size;
+ WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET0, AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
+ }
+ WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE0, size);
+
+ /* cache window 1: stack */
+ WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
+ lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset));
+ WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
+ upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset));
+ WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET1, 0);
+ WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE);
+
+ /* cache window 2: context */
+ WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
+ lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
+ WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
+ upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
+ WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET2, 0);
+ WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);
+
+ /* non-cache window */
+ WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW,
+ lower_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr));
+ WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH,
+ upper_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr));
+ WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_OFFSET0, 0);
+ WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_SIZE0,
+ AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)));
+}
+
+/**
+ * vcn_v4_0_5_mc_resume_dpg_mode - memory controller programming for dpg mode
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number index
+ * @indirect: indirectly write sram
+ *
+ * Let the VCN memory controller know it's offsets with dpg mode
+ */
+static void vcn_v4_0_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+{
+ uint32_t offset, size;
+ const struct common_firmware_header *hdr;
+
+ hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
+ size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
+
+ /* cache window 0: fw */
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+ if (!indirect) {
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
+ (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx].tmr_mc_addr_lo),
+ 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
+ (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx].tmr_mc_addr_hi),
+ 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);
+ } else {
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 0, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 0, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);
+ }
+ offset = 0;
+ } else {
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
+ lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
+ upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);
+ offset = size;
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0),
+ AMDGPU_UVD_FIRMWARE_OFFSET >> 3, 0, indirect);
+ }
+
+ if (!indirect)
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_CACHE_SIZE0), size, 0, indirect);
+ else
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_CACHE_SIZE0), 0, 0, indirect);
+
+ /* cache window 1: stack */
+ if (!indirect) {
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW),
+ lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH),
+ upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);
+ } else {
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), 0, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), 0, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);
+ }
+
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_CACHE_SIZE1), AMDGPU_VCN_STACK_SIZE, 0, indirect);
+
+ /* cache window 2: context */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW),
+ lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE),
+ 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH),
+ upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE),
+ 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET2), 0, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE, 0, indirect);
+
+ /* non-cache window */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW),
+ lower_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH),
+ upper_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_NONCACHE_OFFSET0), 0, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_NONCACHE_SIZE0),
+ AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)), 0, indirect);
+
+ /* VCN global tiling registers */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect);
+}
+
+/**
+ * vcn_v4_0_5_disable_static_power_gating - disable VCN static power gating
+ *
+ * @adev: amdgpu_device pointer
+ * @inst: instance number
+ *
+ * Disable static power gating for VCN block
+ */
+static void vcn_v4_0_5_disable_static_power_gating(struct amdgpu_device *adev, int inst)
+{
+ uint32_t data = 0;
+
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
+ WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,
+ 1 << UVD_IPX_DLDO_CONFIG__ONO2_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS, 0,
+ UVD_IPX_DLDO_STATUS__ONO2_PWR_STATUS_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,
+ 2 << UVD_IPX_DLDO_CONFIG__ONO3_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,
+ 1 << UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS__SHIFT,
+ UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,
+ 2 << UVD_IPX_DLDO_CONFIG__ONO4_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,
+ 1 << UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS__SHIFT,
+ UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,
+ 2 << UVD_IPX_DLDO_CONFIG__ONO5_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,
+ 1 << UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS__SHIFT,
+ UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS_MASK);
+ } else {
+ WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,
+ 1 << UVD_IPX_DLDO_CONFIG__ONO2_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,
+ 0, UVD_IPX_DLDO_STATUS__ONO2_PWR_STATUS_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,
+ 1 << UVD_IPX_DLDO_CONFIG__ONO3_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,
+ 0, UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,
+ 1 << UVD_IPX_DLDO_CONFIG__ONO4_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,
+ 0, UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,
+ 1 << UVD_IPX_DLDO_CONFIG__ONO5_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,
+ 0, UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS_MASK);
+ }
+
+ data = RREG32_SOC15(VCN, inst, regUVD_POWER_STATUS);
+ data &= ~0x103;
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN)
+ data |= UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON |
+ UVD_POWER_STATUS__UVD_PG_EN_MASK;
+ WREG32_SOC15(VCN, inst, regUVD_POWER_STATUS, data);
+}
+
+/**
+ * vcn_v4_0_5_enable_static_power_gating - enable VCN static power gating
+ *
+ * @adev: amdgpu_device pointer
+ * @inst: instance number
+ *
+ * Enable static power gating for VCN block
+ */
+static void vcn_v4_0_5_enable_static_power_gating(struct amdgpu_device *adev, int inst)
+{
+ uint32_t data;
+
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
+ /* Before power off, this indicator has to be turned on */
+ data = RREG32_SOC15(VCN, inst, regUVD_POWER_STATUS);
+ data &= ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK;
+ data |= UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF;
+ WREG32_SOC15(VCN, inst, regUVD_POWER_STATUS, data);
+
+ WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,
+ 2 << UVD_IPX_DLDO_CONFIG__ONO5_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,
+ 1 << UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS__SHIFT,
+ UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,
+ 2 << UVD_IPX_DLDO_CONFIG__ONO4_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,
+ 1 << UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS__SHIFT,
+ UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,
+ 2 << UVD_IPX_DLDO_CONFIG__ONO3_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,
+ 1 << UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS__SHIFT,
+ UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,
+ 2 << UVD_IPX_DLDO_CONFIG__ONO2_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,
+ 1 << UVD_IPX_DLDO_STATUS__ONO2_PWR_STATUS__SHIFT,
+ UVD_IPX_DLDO_STATUS__ONO2_PWR_STATUS_MASK);
+ }
+}
+
+/**
+ * vcn_v4_0_5_disable_clock_gating - disable VCN clock gating
+ *
+ * @adev: amdgpu_device pointer
+ * @inst: instance number
+ *
+ * Disable clock gating for VCN block
+ */
+static void vcn_v4_0_5_disable_clock_gating(struct amdgpu_device *adev, int inst)
+{
+ uint32_t data;
+
+ if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
+ return;
+
+ /* VCN disable CGC */
+ data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL);
+ data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+ data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+ data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+ WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data);
+
+ data = RREG32_SOC15(VCN, inst, regUVD_CGC_GATE);
+ data &= ~(UVD_CGC_GATE__SYS_MASK
+ | UVD_CGC_GATE__UDEC_MASK
+ | UVD_CGC_GATE__MPEG2_MASK
+ | UVD_CGC_GATE__REGS_MASK
+ | UVD_CGC_GATE__RBC_MASK
+ | UVD_CGC_GATE__LMI_MC_MASK
+ | UVD_CGC_GATE__LMI_UMC_MASK
+ | UVD_CGC_GATE__IDCT_MASK
+ | UVD_CGC_GATE__MPRD_MASK
+ | UVD_CGC_GATE__MPC_MASK
+ | UVD_CGC_GATE__LBSI_MASK
+ | UVD_CGC_GATE__LRBBM_MASK
+ | UVD_CGC_GATE__UDEC_RE_MASK
+ | UVD_CGC_GATE__UDEC_CM_MASK
+ | UVD_CGC_GATE__UDEC_IT_MASK
+ | UVD_CGC_GATE__UDEC_DB_MASK
+ | UVD_CGC_GATE__UDEC_MP_MASK
+ | UVD_CGC_GATE__WCB_MASK
+ | UVD_CGC_GATE__VCPU_MASK
+ | UVD_CGC_GATE__MMSCH_MASK);
+
+ WREG32_SOC15(VCN, inst, regUVD_CGC_GATE, data);
+ SOC15_WAIT_ON_RREG(VCN, inst, regUVD_CGC_GATE, 0, 0xFFFFFFFF);
+
+ data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL);
+ data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK
+ | UVD_CGC_CTRL__UDEC_CM_MODE_MASK
+ | UVD_CGC_CTRL__UDEC_IT_MODE_MASK
+ | UVD_CGC_CTRL__UDEC_DB_MODE_MASK
+ | UVD_CGC_CTRL__UDEC_MP_MODE_MASK
+ | UVD_CGC_CTRL__SYS_MODE_MASK
+ | UVD_CGC_CTRL__UDEC_MODE_MASK
+ | UVD_CGC_CTRL__MPEG2_MODE_MASK
+ | UVD_CGC_CTRL__REGS_MODE_MASK
+ | UVD_CGC_CTRL__RBC_MODE_MASK
+ | UVD_CGC_CTRL__LMI_MC_MODE_MASK
+ | UVD_CGC_CTRL__LMI_UMC_MODE_MASK
+ | UVD_CGC_CTRL__IDCT_MODE_MASK
+ | UVD_CGC_CTRL__MPRD_MODE_MASK
+ | UVD_CGC_CTRL__MPC_MODE_MASK
+ | UVD_CGC_CTRL__LBSI_MODE_MASK
+ | UVD_CGC_CTRL__LRBBM_MODE_MASK
+ | UVD_CGC_CTRL__WCB_MODE_MASK
+ | UVD_CGC_CTRL__VCPU_MODE_MASK
+ | UVD_CGC_CTRL__MMSCH_MODE_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data);
+
+ data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_GATE);
+ data |= (UVD_SUVD_CGC_GATE__SRE_MASK
+ | UVD_SUVD_CGC_GATE__SIT_MASK
+ | UVD_SUVD_CGC_GATE__SMP_MASK
+ | UVD_SUVD_CGC_GATE__SCM_MASK
+ | UVD_SUVD_CGC_GATE__SDB_MASK
+ | UVD_SUVD_CGC_GATE__SRE_H264_MASK
+ | UVD_SUVD_CGC_GATE__SRE_HEVC_MASK
+ | UVD_SUVD_CGC_GATE__SIT_H264_MASK
+ | UVD_SUVD_CGC_GATE__SIT_HEVC_MASK
+ | UVD_SUVD_CGC_GATE__SCM_H264_MASK
+ | UVD_SUVD_CGC_GATE__SCM_HEVC_MASK
+ | UVD_SUVD_CGC_GATE__SDB_H264_MASK
+ | UVD_SUVD_CGC_GATE__SDB_HEVC_MASK
+ | UVD_SUVD_CGC_GATE__SCLR_MASK
+ | UVD_SUVD_CGC_GATE__UVD_SC_MASK
+ | UVD_SUVD_CGC_GATE__ENT_MASK
+ | UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK
+ | UVD_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK
+ | UVD_SUVD_CGC_GATE__SITE_MASK
+ | UVD_SUVD_CGC_GATE__SRE_VP9_MASK
+ | UVD_SUVD_CGC_GATE__SCM_VP9_MASK
+ | UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK
+ | UVD_SUVD_CGC_GATE__SDB_VP9_MASK
+ | UVD_SUVD_CGC_GATE__IME_HEVC_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_GATE, data);
+
+ data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL);
+ data &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__IME_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data);
+}
+
+/**
+ * vcn_v4_0_5_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode
+ *
+ * @adev: amdgpu_device pointer
+ * @sram_sel: sram select
+ * @inst_idx: instance number index
+ * @indirect: indirectly write sram
+ *
+ * Disable clock gating for VCN block with dpg mode
+ */
+static void vcn_v4_0_5_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,
+ int inst_idx, uint8_t indirect)
+{
+ uint32_t reg_data = 0;
+
+ if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
+ return;
+
+ /* enable sw clock gating control */
+ reg_data = 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ reg_data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+ reg_data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+ reg_data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK |
+ UVD_CGC_CTRL__UDEC_CM_MODE_MASK |
+ UVD_CGC_CTRL__UDEC_IT_MODE_MASK |
+ UVD_CGC_CTRL__UDEC_DB_MODE_MASK |
+ UVD_CGC_CTRL__UDEC_MP_MODE_MASK |
+ UVD_CGC_CTRL__SYS_MODE_MASK |
+ UVD_CGC_CTRL__UDEC_MODE_MASK |
+ UVD_CGC_CTRL__MPEG2_MODE_MASK |
+ UVD_CGC_CTRL__REGS_MODE_MASK |
+ UVD_CGC_CTRL__RBC_MODE_MASK |
+ UVD_CGC_CTRL__LMI_MC_MODE_MASK |
+ UVD_CGC_CTRL__LMI_UMC_MODE_MASK |
+ UVD_CGC_CTRL__IDCT_MODE_MASK |
+ UVD_CGC_CTRL__MPRD_MODE_MASK |
+ UVD_CGC_CTRL__MPC_MODE_MASK |
+ UVD_CGC_CTRL__LBSI_MODE_MASK |
+ UVD_CGC_CTRL__LRBBM_MODE_MASK |
+ UVD_CGC_CTRL__WCB_MODE_MASK |
+ UVD_CGC_CTRL__VCPU_MODE_MASK);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_CGC_CTRL), reg_data, sram_sel, indirect);
+
+ /* turn off clock gating */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_CGC_GATE), 0, sram_sel, indirect);
+
+ /* turn on SUVD clock gating */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_SUVD_CGC_GATE), 1, sram_sel, indirect);
+
+ /* turn on sw mode in UVD_SUVD_CGC_CTRL */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_SUVD_CGC_CTRL), 0, sram_sel, indirect);
+}
+
+/**
+ * vcn_v4_0_5_enable_clock_gating - enable VCN clock gating
+ *
+ * @adev: amdgpu_device pointer
+ * @inst: instance number
+ *
+ * Enable clock gating for VCN block
+ */
+static void vcn_v4_0_5_enable_clock_gating(struct amdgpu_device *adev, int inst)
+{
+ uint32_t data;
+
+ if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
+ return;
+
+ /* enable VCN CGC */
+ data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL);
+ data |= 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+ data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+ WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data);
+
+ data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL);
+ data |= (UVD_CGC_CTRL__UDEC_RE_MODE_MASK
+ | UVD_CGC_CTRL__UDEC_CM_MODE_MASK
+ | UVD_CGC_CTRL__UDEC_IT_MODE_MASK
+ | UVD_CGC_CTRL__UDEC_DB_MODE_MASK
+ | UVD_CGC_CTRL__UDEC_MP_MODE_MASK
+ | UVD_CGC_CTRL__SYS_MODE_MASK
+ | UVD_CGC_CTRL__UDEC_MODE_MASK
+ | UVD_CGC_CTRL__MPEG2_MODE_MASK
+ | UVD_CGC_CTRL__REGS_MODE_MASK
+ | UVD_CGC_CTRL__RBC_MODE_MASK
+ | UVD_CGC_CTRL__LMI_MC_MODE_MASK
+ | UVD_CGC_CTRL__LMI_UMC_MODE_MASK
+ | UVD_CGC_CTRL__IDCT_MODE_MASK
+ | UVD_CGC_CTRL__MPRD_MODE_MASK
+ | UVD_CGC_CTRL__MPC_MODE_MASK
+ | UVD_CGC_CTRL__LBSI_MODE_MASK
+ | UVD_CGC_CTRL__LRBBM_MODE_MASK
+ | UVD_CGC_CTRL__WCB_MODE_MASK
+ | UVD_CGC_CTRL__VCPU_MODE_MASK
+ | UVD_CGC_CTRL__MMSCH_MODE_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data);
+
+ data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL);
+ data |= (UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__IME_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
+ WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data);
+}
+
+/**
+ * vcn_v4_0_5_start_dpg_mode - VCN start with dpg mode
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number index
+ * @indirect: indirectly write sram
+ *
+ * Start VCN block with dpg mode
+ */
+static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+{
+ volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
+ struct amdgpu_ring *ring;
+ uint32_t tmp;
+
+ /* disable register anti-hang mechanism */
+ WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 1,
+ ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+ /* enable dynamic power gating mode */
+ tmp = RREG32_SOC15(VCN, inst_idx, regUVD_POWER_STATUS);
+ tmp |= UVD_POWER_STATUS__UVD_PG_MODE_MASK;
+ tmp |= UVD_POWER_STATUS__UVD_PG_EN_MASK;
+ WREG32_SOC15(VCN, inst_idx, regUVD_POWER_STATUS, tmp);
+
+ if (indirect)
+ adev->vcn.inst[inst_idx].dpg_sram_curr_addr =
+ (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
+
+ /* enable clock gating */
+ vcn_v4_0_5_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
+
+ /* enable VCPU clock */
+ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
+ tmp |= UVD_VCPU_CNTL__CLK_EN_MASK | UVD_VCPU_CNTL__BLK_RST_MASK;
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_CNTL), tmp, 0, indirect);
+
+ /* disable master interrupt */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_MASTINT_EN), 0, 0, indirect);
+
+ /* setup regUVD_LMI_CTRL */
+ tmp = (UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+ UVD_LMI_CTRL__REQ_MODE_MASK |
+ UVD_LMI_CTRL__CRC_RESET_MASK |
+ UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+ UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+ UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK |
+ (8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |
+ 0x00100000L);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_CTRL), tmp, 0, indirect);
+
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_MPC_CNTL),
+ 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT, 0, indirect);
+
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_MPC_SET_MUXA0),
+ ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
+ (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
+ (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
+ (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)), 0, indirect);
+
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_MPC_SET_MUXB0),
+ ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
+ (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
+ (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
+ (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)), 0, indirect);
+
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_MPC_SET_MUX),
+ ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
+ (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
+ (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
+
+ vcn_v4_0_5_mc_resume_dpg_mode(adev, inst_idx, indirect);
+
+ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
+ tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_VCPU_CNTL), tmp, 0, indirect);
+
+ /* enable LMI MC and UMC channels */
+ tmp = 0x1f << UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM__SHIFT;
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_LMI_CTRL2), tmp, 0, indirect);
+
+ /* enable master interrupt */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, inst_idx, regUVD_MASTINT_EN),
+ UVD_MASTINT_EN__VCPU_EN_MASK, 0, indirect);
+
+
+ if (indirect)
+ amdgpu_vcn_psp_update_sram(adev, inst_idx, 0);
+
+ ring = &adev->vcn.inst[inst_idx].ring_enc[0];
+
+ WREG32_SOC15(VCN, inst_idx, regUVD_RB_BASE_LO, ring->gpu_addr);
+ WREG32_SOC15(VCN, inst_idx, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+ WREG32_SOC15(VCN, inst_idx, regUVD_RB_SIZE, ring->ring_size / 4);
+
+ tmp = RREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE);
+ tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
+ WREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE, tmp);
+ fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
+ WREG32_SOC15(VCN, inst_idx, regUVD_RB_RPTR, 0);
+ WREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR, 0);
+
+ tmp = RREG32_SOC15(VCN, inst_idx, regUVD_RB_RPTR);
+ WREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR, tmp);
+ ring->wptr = RREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR);
+
+ tmp = RREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE);
+ tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
+ WREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE, tmp);
+ fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
+
+ WREG32_SOC15(VCN, inst_idx, regVCN_RB1_DB_CTRL,
+ ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
+ VCN_RB1_DB_CTRL__EN_MASK);
+
+ return 0;
+}
+
+
+/**
+ * vcn_v4_0_5_start - VCN start
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Start VCN block
+ */
+static int vcn_v4_0_5_start(struct amdgpu_device *adev)
+{
+ volatile struct amdgpu_vcn4_fw_shared *fw_shared;
+ struct amdgpu_ring *ring;
+ uint32_t tmp;
+ int i, j, k, r;
+
+ if (adev->pm.dpm_enabled)
+ amdgpu_dpm_enable_uvd(adev, true);
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+ r = vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
+ continue;
+ }
+
+ /* disable VCN power gating */
+ vcn_v4_0_5_disable_static_power_gating(adev, i);
+
+ /* set VCN status busy */
+ tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
+ WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
+
+ /*SW clock gating */
+ vcn_v4_0_5_disable_clock_gating(adev, i);
+
+ /* enable VCPU clock */
+ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+ UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
+
+ /* disable master interrupt */
+ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
+ ~UVD_MASTINT_EN__VCPU_EN_MASK);
+
+ /* enable LMI MC and UMC channels */
+ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
+ ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
+
+ tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+ tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+ tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+ WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+
+ /* setup regUVD_LMI_CTRL */
+ tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
+ WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
+ UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+ UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+ UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+ UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
+
+ /* setup regUVD_MPC_CNTL */
+ tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);
+ tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
+ tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
+ WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);
+
+ /* setup UVD_MPC_SET_MUXA0 */
+ WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,
+ ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
+ (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
+ (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
+ (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
+
+ /* setup UVD_MPC_SET_MUXB0 */
+ WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,
+ ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
+ (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
+ (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
+ (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
+
+ /* setup UVD_MPC_SET_MUX */
+ WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,
+ ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
+ (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
+ (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
+
+ vcn_v4_0_5_mc_resume(adev, i);
+
+ /* VCN global tiling registers */
+ WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
+ adev->gfx.config.gb_addr_config);
+
+ /* unblock VCPU register access */
+ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
+ ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+ /* release VCPU reset to boot */
+ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+ ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+ for (j = 0; j < 10; ++j) {
+ uint32_t status;
+
+ for (k = 0; k < 100; ++k) {
+ status = RREG32_SOC15(VCN, i, regUVD_STATUS);
+ if (status & 2)
+ break;
+ mdelay(10);
+ if (amdgpu_emu_mode == 1)
+ msleep(1);
+ }
+
+ if (amdgpu_emu_mode == 1) {
+ r = -1;
+ if (status & 2) {
+ r = 0;
+ break;
+ }
+ } else {
+ r = 0;
+ if (status & 2)
+ break;
+
+ dev_err(adev->dev,
+ "VCN[%d] is not responding, trying to reset VCPU!!!\n", i);
+ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+ UVD_VCPU_CNTL__BLK_RST_MASK,
+ ~UVD_VCPU_CNTL__BLK_RST_MASK);
+ mdelay(10);
+ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+ ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+ mdelay(10);
+ r = -1;
+ }
+ }
+
+ if (r) {
+ dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
+ return r;
+ }
+
+ /* enable master interrupt */
+ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
+ UVD_MASTINT_EN__VCPU_EN_MASK,
+ ~UVD_MASTINT_EN__VCPU_EN_MASK);
+
+ /* clear the busy bit of VCN_STATUS */
+ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
+ ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
+
+ ring = &adev->vcn.inst[i].ring_enc[0];
+ WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
+ ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
+ VCN_RB1_DB_CTRL__EN_MASK);
+
+ WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
+ WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+ WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
+
+ tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
+ tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
+ WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
+ fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
+ WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
+ WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
+
+ tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
+ WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
+ ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
+
+ tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
+ tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
+ WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
+ fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
+ }
+
+ return 0;
+}
+
+/**
+ * vcn_v4_0_5_stop_dpg_mode - VCN stop with dpg mode
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number index
+ *
+ * Stop VCN block with dpg mode
+ */
+static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
+{
+ uint32_t tmp;
+
+ /* Wait for power status to be 1 */
+ SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1,
+ UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+
+ /* wait for read ptr to be equal to write ptr */
+ tmp = RREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR);
+ SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_RB_RPTR, tmp, 0xFFFFFFFF);
+
+ SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1,
+ UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+
+ /* disable dynamic power gating mode */
+ WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 0,
+ ~UVD_POWER_STATUS__UVD_PG_MODE_MASK);
+}
+
+/**
+ * vcn_v4_0_5_stop - VCN stop
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Stop VCN block
+ */
+static int vcn_v4_0_5_stop(struct amdgpu_device *adev)
+{
+ volatile struct amdgpu_vcn4_fw_shared *fw_shared;
+ uint32_t tmp;
+ int i, r = 0;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+ fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
+
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+ vcn_v4_0_5_stop_dpg_mode(adev, i);
+ continue;
+ }
+
+ /* wait for vcn idle */
+ r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
+ if (r)
+ return r;
+
+ tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
+ UVD_LMI_STATUS__READ_CLEAN_MASK |
+ UVD_LMI_STATUS__WRITE_CLEAN_MASK |
+ UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
+ r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
+ if (r)
+ return r;
+
+ /* disable LMI UMC channel */
+ tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
+ tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
+ WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
+ tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
+ UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
+ r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
+ if (r)
+ return r;
+
+ /* block VCPU register access */
+ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
+ UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
+ ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+ /* reset VCPU */
+ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+ UVD_VCPU_CNTL__BLK_RST_MASK,
+ ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+ /* disable VCPU clock */
+ WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+ ~(UVD_VCPU_CNTL__CLK_EN_MASK));
+
+ /* apply soft reset */
+ tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+ tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+ WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+ tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+ tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+ WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+
+ /* clear status */
+ WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
+
+ /* apply HW clock gating */
+ vcn_v4_0_5_enable_clock_gating(adev, i);
+
+ /* enable VCN power gating */
+ vcn_v4_0_5_enable_static_power_gating(adev, i);
+ }
+
+ if (adev->pm.dpm_enabled)
+ amdgpu_dpm_enable_uvd(adev, false);
+
+ return 0;
+}
+
+/**
+ * vcn_v4_0_5_pause_dpg_mode - VCN pause with dpg mode
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number index
+ * @new_state: pause state
+ *
+ * Pause dpg mode for VCN block
+ */
+static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,
+ struct dpg_pause_state *new_state)
+{
+ uint32_t reg_data = 0;
+ int ret_code;
+
+ /* pause/unpause if state is changed */
+ if (adev->vcn.inst[inst_idx].pause_state.fw_based != new_state->fw_based) {
+ DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d",
+ adev->vcn.inst[inst_idx].pause_state.fw_based, new_state->fw_based);
+ reg_data = RREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE) &
+ (~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
+
+ if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {
+ ret_code = SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 0x1,
+ UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+
+ if (!ret_code) {
+ /* pause DPG */
+ reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
+ WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);
+
+ /* wait for ACK */
+ SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_DPG_PAUSE,
+ UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
+ UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
+
+ SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS,
+ UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON,
+ UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+ }
+ } else {
+ /* unpause dpg, no need to wait */
+ reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
+ WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);
+ }
+ adev->vcn.inst[inst_idx].pause_state.fw_based = new_state->fw_based;
+ }
+
+ return 0;
+}
+
+/**
+ * vcn_v4_0_5_unified_ring_get_rptr - get unified read pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Returns the current hardware unified read pointer
+ */
+static uint64_t vcn_v4_0_5_unified_ring_get_rptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
+ DRM_ERROR("wrong ring id is identified in %s", __func__);
+
+ return RREG32_SOC15(VCN, ring->me, regUVD_RB_RPTR);
+}
+
+/**
+ * vcn_v4_0_5_unified_ring_get_wptr - get unified write pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Returns the current hardware unified write pointer
+ */
+static uint64_t vcn_v4_0_5_unified_ring_get_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
+ DRM_ERROR("wrong ring id is identified in %s", __func__);
+
+ if (ring->use_doorbell)
+ return *ring->wptr_cpu_addr;
+ else
+ return RREG32_SOC15(VCN, ring->me, regUVD_RB_WPTR);
+}
+
+/**
+ * vcn_v4_0_5_unified_ring_set_wptr - set enc write pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Commits the enc write pointer to the hardware
+ */
+static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
+ DRM_ERROR("wrong ring id is identified in %s", __func__);
+
+ if (ring->use_doorbell) {
+ *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);
+ WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
+ } else {
+ WREG32_SOC15(VCN, ring->me, regUVD_RB_WPTR, lower_32_bits(ring->wptr));
+ }
+}
+
+static int vcn_v4_0_5_limit_sched(struct amdgpu_cs_parser *p,
+ struct amdgpu_job *job)
+{
+ struct drm_gpu_scheduler **scheds;
+
+ /* The create msg must be in the first IB submitted */
+ if (atomic_read(&job->base.entity->fence_seq))
+ return -EINVAL;
+
+ /* if VCN0 is harvested, we can't support AV1 */
+ if (p->adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0)
+ return -EINVAL;
+
+ scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_ENC]
+ [AMDGPU_RING_PRIO_0].sched;
+ drm_sched_entity_modify_sched(job->base.entity, scheds, 1);
+ return 0;
+}
+
+static int vcn_v4_0_5_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
+ uint64_t addr)
+{
+ struct ttm_operation_ctx ctx = { false, false };
+ struct amdgpu_bo_va_mapping *map;
+ uint32_t *msg, num_buffers;
+ struct amdgpu_bo *bo;
+ uint64_t start, end;
+ unsigned int i;
+ void *ptr;
+ int r;
+
+ addr &= AMDGPU_GMC_HOLE_MASK;
+ r = amdgpu_cs_find_mapping(p, addr, &bo, &map);
+ if (r) {
+ DRM_ERROR("Can't find BO for addr 0x%08llx\n", addr);
+ return r;
+ }
+
+ start = map->start * AMDGPU_GPU_PAGE_SIZE;
+ end = (map->last + 1) * AMDGPU_GPU_PAGE_SIZE;
+ if (addr & 0x7) {
+ DRM_ERROR("VCN messages must be 8 byte aligned!\n");
+ return -EINVAL;
+ }
+
+ bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
+ amdgpu_bo_placement_from_domain(bo, bo->allowed_domains);
+ r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
+ if (r) {
+ DRM_ERROR("Failed validating the VCN message BO (%d)!\n", r);
+ return r;
+ }
+
+ r = amdgpu_bo_kmap(bo, &ptr);
+ if (r) {
+ DRM_ERROR("Failed mapping the VCN message (%d)!\n", r);
+ return r;
+ }
+
+ msg = ptr + addr - start;
+
+ /* Check length */
+ if (msg[1] > end - addr) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (msg[3] != RDECODE_MSG_CREATE)
+ goto out;
+
+ num_buffers = msg[2];
+ for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) {
+ uint32_t offset, size, *create;
+
+ if (msg[0] != RDECODE_MESSAGE_CREATE)
+ continue;
+
+ offset = msg[1];
+ size = msg[2];
+
+ if (offset + size > end) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ create = ptr + addr + offset - start;
+
+ /* H264, HEVC and VP9 can run on any instance */
+ if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
+ continue;
+
+ r = vcn_v4_0_5_limit_sched(p, job);
+ if (r)
+ goto out;
+ }
+
+out:
+ amdgpu_bo_kunmap(bo);
+ return r;
+}
+
+#define RADEON_VCN_ENGINE_TYPE_ENCODE (0x00000002)
+#define RADEON_VCN_ENGINE_TYPE_DECODE (0x00000003)
+
+#define RADEON_VCN_ENGINE_INFO (0x30000001)
+#define RADEON_VCN_ENGINE_INFO_MAX_OFFSET 16
+
+#define RENCODE_ENCODE_STANDARD_AV1 2
+#define RENCODE_IB_PARAM_SESSION_INIT 0x00000003
+#define RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET 64
+
+/* return the offset in ib if id is found, -1 otherwise
+ * to speed up the searching we only search upto max_offset
+ */
+static int vcn_v4_0_5_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int max_offset)
+{
+ int i;
+
+ for (i = 0; i < ib->length_dw && i < max_offset && ib->ptr[i] >= 8; i += ib->ptr[i]/4) {
+ if (ib->ptr[i + 1] == id)
+ return i;
+ }
+ return -1;
+}
+
+static int vcn_v4_0_5_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
+ struct amdgpu_job *job,
+ struct amdgpu_ib *ib)
+{
+ struct amdgpu_ring *ring = amdgpu_job_ring(job);
+ struct amdgpu_vcn_decode_buffer *decode_buffer;
+ uint64_t addr;
+ uint32_t val;
+ int idx;
+
+ /* The first instance can decode anything */
+ if (!ring->me)
+ return 0;
+
+ /* RADEON_VCN_ENGINE_INFO is at the top of ib block */
+ idx = vcn_v4_0_5_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO,
+ RADEON_VCN_ENGINE_INFO_MAX_OFFSET);
+ if (idx < 0) /* engine info is missing */
+ return 0;
+
+ val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
+ if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
+ decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
+
+ if (!(decode_buffer->valid_buf_flag & 0x1))
+ return 0;
+
+ addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
+ decode_buffer->msg_buffer_address_lo;
+ return vcn_v4_0_5_dec_msg(p, job, addr);
+ } else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
+ idx = vcn_v4_0_5_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT,
+ RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET);
+ if (idx >= 0 && ib->ptr[idx + 2] == RENCODE_ENCODE_STANDARD_AV1)
+ return vcn_v4_0_5_limit_sched(p, job);
+ }
+ return 0;
+}
+
+static const struct amdgpu_ring_funcs vcn_v4_0_5_unified_ring_vm_funcs = {
+ .type = AMDGPU_RING_TYPE_VCN_ENC,
+ .align_mask = 0x3f,
+ .nop = VCN_ENC_CMD_NO_OP,
+ .get_rptr = vcn_v4_0_5_unified_ring_get_rptr,
+ .get_wptr = vcn_v4_0_5_unified_ring_get_wptr,
+ .set_wptr = vcn_v4_0_5_unified_ring_set_wptr,
+ .patch_cs_in_place = vcn_v4_0_5_ring_patch_cs_in_place,
+ .emit_frame_size =
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 +
+ 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */
+ 5 + 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */
+ 1, /* vcn_v2_0_enc_ring_insert_end */
+ .emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */
+ .emit_ib = vcn_v2_0_enc_ring_emit_ib,
+ .emit_fence = vcn_v2_0_enc_ring_emit_fence,
+ .emit_vm_flush = vcn_v2_0_enc_ring_emit_vm_flush,
+ .test_ring = amdgpu_vcn_enc_ring_test_ring,
+ .test_ib = amdgpu_vcn_unified_ring_test_ib,
+ .insert_nop = amdgpu_ring_insert_nop,
+ .insert_end = vcn_v2_0_enc_ring_insert_end,
+ .pad_ib = amdgpu_ring_generic_pad_ib,
+ .begin_use = amdgpu_vcn_ring_begin_use,
+ .end_use = amdgpu_vcn_ring_end_use,
+ .emit_wreg = vcn_v2_0_enc_ring_emit_wreg,
+ .emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,
+ .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+};
+
+/**
+ * vcn_v4_0_5_set_unified_ring_funcs - set unified ring functions
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Set unified ring functions
+ */
+static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev)
+{
+ int i;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
+ adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v4_0_5_unified_ring_vm_funcs;
+ adev->vcn.inst[i].ring_enc[0].me = i;
+
+ DRM_INFO("VCN(%d) encode/decode are enabled in VM mode\n", i);
+ }
+}
+
+/**
+ * vcn_v4_0_5_is_idle - check VCN block is idle
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Check whether VCN block is idle
+ */
+static bool vcn_v4_0_5_is_idle(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i, ret = 1;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
+ ret &= (RREG32_SOC15(VCN, i, regUVD_STATUS) == UVD_STATUS__IDLE);
+ }
+
+ return ret;
+}
+
+/**
+ * vcn_v4_0_5_wait_for_idle - wait for VCN block idle
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Wait for VCN block idle
+ */
+static int vcn_v4_0_5_wait_for_idle(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i, ret = 0;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
+ ret = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE,
+ UVD_STATUS__IDLE);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * vcn_v4_0_5_set_clockgating_state - set VCN block clockgating state
+ *
+ * @handle: amdgpu_device pointer
+ * @state: clock gating state
+ *
+ * Set VCN block clockgating state
+ */
+static int vcn_v4_0_5_set_clockgating_state(void *handle, enum amd_clockgating_state state)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
+ int i;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
+ if (enable) {
+ if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE)
+ return -EBUSY;
+ vcn_v4_0_5_enable_clock_gating(adev, i);
+ } else {
+ vcn_v4_0_5_disable_clock_gating(adev, i);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * vcn_v4_0_5_set_powergating_state - set VCN block powergating state
+ *
+ * @handle: amdgpu_device pointer
+ * @state: power gating state
+ *
+ * Set VCN block powergating state
+ */
+static int vcn_v4_0_5_set_powergating_state(void *handle, enum amd_powergating_state state)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
+
+ if (state == adev->vcn.cur_state)
+ return 0;
+
+ if (state == AMD_PG_STATE_GATE)
+ ret = vcn_v4_0_5_stop(adev);
+ else
+ ret = vcn_v4_0_5_start(adev);
+
+ if (!ret)
+ adev->vcn.cur_state = state;
+
+ return ret;
+}
+
+/**
+ * vcn_v4_0_5_set_interrupt_state - set VCN block interrupt state
+ *
+ * @adev: amdgpu_device pointer
+ * @source: interrupt sources
+ * @type: interrupt types
+ * @state: interrupt states
+ *
+ * Set VCN block interrupt state
+ */
+static int vcn_v4_0_5_set_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source,
+ unsigned type, enum amdgpu_interrupt_state state)
+{
+ return 0;
+}
+
+/**
+ * vcn_v4_0_5_process_interrupt - process VCN block interrupt
+ *
+ * @adev: amdgpu_device pointer
+ * @source: interrupt sources
+ * @entry: interrupt entry from clients and sources
+ *
+ * Process VCN block interrupt
+ */
+static int vcn_v4_0_5_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ uint32_t ip_instance;
+
+ switch (entry->client_id) {
+ case SOC15_IH_CLIENTID_VCN:
+ ip_instance = 0;
+ break;
+ default:
+ DRM_ERROR("Unhandled client id: %d\n", entry->client_id);
+ return 0;
+ }
+
+ DRM_DEBUG("IH: VCN TRAP\n");
+
+ switch (entry->src_id) {
+ case VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE:
+ amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_enc[0]);
+ break;
+ case VCN_4_0__SRCID_UVD_POISON:
+ amdgpu_vcn_process_poison_irq(adev, source, entry);
+ break;
+ default:
+ DRM_ERROR("Unhandled interrupt: %d %d\n",
+ entry->src_id, entry->src_data[0]);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct amdgpu_irq_src_funcs vcn_v4_0_5_irq_funcs = {
+ .set = vcn_v4_0_5_set_interrupt_state,
+ .process = vcn_v4_0_5_process_interrupt,
+};
+
+/**
+ * vcn_v4_0_5_set_irq_funcs - set VCN block interrupt irq functions
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Set VCN block interrupt irq functions
+ */
+static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev)
+{
+ int i;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
+ adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
+ adev->vcn.inst[i].irq.funcs = &vcn_v4_0_5_irq_funcs;
+ }
+}
+
+static const struct amd_ip_funcs vcn_v4_0_5_ip_funcs = {
+ .name = "vcn_v4_0_5",
+ .early_init = vcn_v4_0_5_early_init,
+ .late_init = NULL,
+ .sw_init = vcn_v4_0_5_sw_init,
+ .sw_fini = vcn_v4_0_5_sw_fini,
+ .hw_init = vcn_v4_0_5_hw_init,
+ .hw_fini = vcn_v4_0_5_hw_fini,
+ .suspend = vcn_v4_0_5_suspend,
+ .resume = vcn_v4_0_5_resume,
+ .is_idle = vcn_v4_0_5_is_idle,
+ .wait_for_idle = vcn_v4_0_5_wait_for_idle,
+ .check_soft_reset = NULL,
+ .pre_soft_reset = NULL,
+ .soft_reset = NULL,
+ .post_soft_reset = NULL,
+ .set_clockgating_state = vcn_v4_0_5_set_clockgating_state,
+ .set_powergating_state = vcn_v4_0_5_set_powergating_state,
+};
+
+const struct amdgpu_ip_block_version vcn_v4_0_5_ip_block = {
+ .type = AMD_IP_BLOCK_TYPE_VCN,
+ .major = 4,
+ .minor = 0,
+ .rev = 5,
+ .funcs = &vcn_v4_0_5_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.h b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.h
new file mode 100644
index 000000000000..ff9b3d6f6a47
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __VCN_V4_0_5_H__
+#define __VCN_V4_0_5_H__
+
+enum amdgpu_vcn_v4_0_5_sub_block {
+ AMDGPU_VCN_V4_0_5_VCPU_VCODEC = 0,
+
+ AMDGPU_VCN_V4_0_5_MAX_SUB_BLOCK,
+};
+
+extern const struct amdgpu_ip_block_version vcn_v4_0_5_ip_block;
+
+#endif /* __VCN_V4_0_5_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
index dbc99536440f..ddfc6941f9d5 100644
--- a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
@@ -291,7 +291,7 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)
adev->nbio.funcs->ih_control(adev);
- if ((adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 2, 1)) &&
+ if ((amdgpu_ip_version(adev, OSSSYS_HWIP, 0) == IP_VERSION(4, 2, 1)) &&
adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN);
if (adev->irq.ih.use_bus_addr) {
@@ -304,8 +304,8 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)
/* psp firmware won't program IH_CHICKEN for aldebaran
* driver needs to program it properly according to
* MC_SPACE type in IH_RB_CNTL */
- if ((adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 0)) ||
- (adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 2))) {
+ if ((amdgpu_ip_version(adev, OSSSYS_HWIP, 0) == IP_VERSION(4, 4, 0)) ||
+ (amdgpu_ip_version(adev, OSSSYS_HWIP, 0) == IP_VERSION(4, 4, 2))) {
ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN_ALDEBARAN);
if (adev->irq.ih.use_bus_addr) {
ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN,
@@ -334,8 +334,8 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)
vega20_setup_retry_doorbell(adev->irq.retry_cam_doorbell_index));
/* Enable IH Retry CAM */
- if (adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 0) ||
- adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 2))
+ if (amdgpu_ip_version(adev, OSSSYS_HWIP, 0) == IP_VERSION(4, 4, 0) ||
+ amdgpu_ip_version(adev, OSSSYS_HWIP, 0) == IP_VERSION(4, 4, 2))
WREG32_FIELD15(OSSSYS, 0, IH_RETRY_INT_CAM_CNTL_ALDEBARAN,
ENABLE, 1);
else
@@ -537,7 +537,7 @@ static int vega20_ih_sw_init(void *handle)
return r;
if ((adev->flags & AMD_IS_APU) &&
- (adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 2)))
+ (amdgpu_ip_version(adev, OSSSYS_HWIP, 0) == IP_VERSION(4, 4, 2)))
use_bus_addr = false;
r = amdgpu_ih_ring_init(adev, &adev->irq.ih, IH_RING_SIZE, use_bus_addr);
@@ -554,7 +554,7 @@ static int vega20_ih_sw_init(void *handle)
adev->irq.ih1.use_doorbell = true;
adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1;
- if (adev->ip_versions[OSSSYS_HWIP][0] != IP_VERSION(4, 4, 2)) {
+ if (amdgpu_ip_version(adev, OSSSYS_HWIP, 0) != IP_VERSION(4, 4, 2)) {
r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 6a8494f98d3e..1a98812981f4 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -1124,11 +1124,10 @@ static void vi_program_aspm(struct amdgpu_device *adev)
bool bL1SS = false;
bool bClkReqSupport = true;
- if (!amdgpu_device_should_use_aspm(adev) || !amdgpu_device_aspm_support_quirk())
+ if (!amdgpu_device_should_use_aspm(adev))
return;
- if (adev->flags & AMD_IS_APU ||
- adev->asic_type < CHIP_POLARIS10)
+ if (adev->asic_type < CHIP_POLARIS10)
return;
orig = data = RREG32_PCIE(ixPCIE_LC_CNTL);
diff --git a/drivers/gpu/drm/amd/amdgpu/vpe_6_1_fw_if.h b/drivers/gpu/drm/amd/amdgpu/vpe_6_1_fw_if.h
new file mode 100644
index 000000000000..9b550deb48d3
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/vpe_6_1_fw_if.h
@@ -0,0 +1,217 @@
+/* Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __VPE_6_1_FW_IF_H_
+#define __VPE_6_1_FW_IF_H_
+
+/****************
+ * VPE OP Codes
+ ****************/
+enum VPE_CMD_OPCODE {
+ VPE_CMD_OPCODE_NOP = 0x0,
+ VPE_CMD_OPCODE_VPE_DESC = 0x1,
+ VPE_CMD_OPCODE_PLANE_CFG = 0x2,
+ VPE_CMD_OPCODE_VPEP_CFG = 0x3,
+ VPE_CMD_OPCODE_INDIRECT = 0x4,
+ VPE_CMD_OPCODE_FENCE = 0x5,
+ VPE_CMD_OPCODE_TRAP = 0x6,
+ VPE_CMD_OPCODE_REG_WRITE = 0x7,
+ VPE_CMD_OPCODE_POLL_REGMEM = 0x8,
+ VPE_CMD_OPCODE_COND_EXE = 0x9,
+ VPE_CMD_OPCODE_ATOMIC = 0xA,
+ VPE_CMD_OPCODE_PLANE_FILL = 0xB,
+ VPE_CMD_OPCODE_TIMESTAMP = 0xD
+};
+
+/** Generic Command Header
+ * Generic Commands include:
+ * Noop, Fence, Trap,
+ * RegisterWrite, PollRegisterWriteMemory,
+ * SetLocalTimestamp, GetLocalTimestamp
+ * GetGlobalGPUTimestamp */
+#define VPE_HEADER_SUB_OPCODE__SHIFT 8
+#define VPE_HEADER_SUB_OPCODE_MASK 0x0000FF00
+#define VPE_HEADER_OPCODE__SHIFT 0
+#define VPE_HEADER_OPCODE_MASK 0x000000FF
+
+#define VPE_CMD_HEADER(op, subop) \
+ (((subop << VPE_HEADER_SUB_OPCODE__SHIFT) & VPE_HEADER_SUB_OPCODE_MASK) | \
+ ((op << VPE_HEADER_OPCODE__SHIFT) & VPE_HEADER_OPCODE_MASK))
+
+
+ /***************************
+ * VPE NOP
+ ***************************/
+#define VPE_CMD_NOP_HEADER_COUNT__SHIFT 16
+#define VPE_CMD_NOP_HEADER_COUNT_MASK 0x00003FFF
+
+#define VPE_CMD_NOP_HEADER_COUNT(count) \
+ (((count) & VPE_CMD_NOP_HEADER_COUNT_MASK) << VPE_CMD_NOP_HEADER_COUNT__SHIFT)
+
+ /***************************
+ * VPE Descriptor
+ ***************************/
+#define VPE_DESC_CD__SHIFT 16
+#define VPE_DESC_CD_MASK 0x000F0000
+
+#define VPE_DESC_CMD_HEADER(cd) \
+ (VPE_CMD_HEADER(VPE_CMD_OPCODE_VPE_DESC, 0) | \
+ (((cd) << VPE_DESC_CD__SHIFT) & VPE_DESC_CD_MASK))
+
+ /***************************
+ * VPE Plane Config
+ ***************************/
+enum VPE_PLANE_CFG_SUBOP {
+ VPE_PLANE_CFG_SUBOP_1_TO_1 = 0x0,
+ VPE_PLANE_CFG_SUBOP_2_TO_1 = 0x1,
+ VPE_PLANE_CFG_SUBOP_2_TO_2 = 0x2
+};
+
+#define VPE_PLANE_CFG_ONE_PLANE 0
+#define VPE_PLANE_CFG_TWO_PLANES 1
+
+#define VPE_PLANE_CFG_NPS0__SHIFT 16
+#define VPE_PLANE_CFG_NPS0_MASK 0x00030000
+
+#define VPE_PLANE_CFG_NPD0__SHIFT 18
+#define VPE_PLANE_CFG_NPD0_MASK 0x000C0000
+
+#define VPE_PLANE_CFG_NPS1__SHIFT 20
+#define VPE_PLANE_CFG_NPS1_MASK 0x00300000
+
+#define VPE_PLANE_CFG_NPD1__SHIFT 22
+#define VPE_PLANE_CFG_NPD1_MASK 0x00C00000
+
+#define VPE_PLANE_CFG_TMZ__SHIFT 16
+#define VPE_PLANE_CFG_TMZ_MASK 0x00010000
+
+#define VPE_PLANE_CFG_SWIZZLE_MODE__SHIFT 3
+#define VPE_PLANE_CFG_SWIZZLE_MODE_MASK 0x000000F8
+
+#define VPE_PLANE_CFG_ROTATION__SHIFT 0
+#define VPE_PLANE_CFG_ROTATION_MASK 0x00000003
+
+#define VPE_PLANE_ADDR_LO__SHIFT 0
+#define VPE_PLANE_ADDR_LO_MASK 0xFFFFFF00
+
+#define VPE_PLANE_CFG_PITCH__SHIFT 0
+#define VPE_PLANE_CFG_PITCH_MASK 0x00003FFF
+
+#define VPE_PLANE_CFG_VIEWPORT_Y__SHIFT 16
+#define VPE_PLANE_CFG_VIEWPORT_Y_MASK 0x3FFF0000
+#define VPE_PLANE_CFG_VIEWPORT_X__SHIFT 0
+#define VPE_PLANE_CFG_VIEWPORT_X_MASK 0x00003FFF
+
+
+#define VPE_PLANE_CFG_VIEWPORT_HEIGHT__SHIFT 16
+#define VPE_PLANE_CFG_VIEWPORT_HEIGHT_MASK 0x1FFF0000
+#define VPE_PLANE_CFG_VIEWPORT_ELEMENT_SIZE__SHIFT 13
+#define VPE_PLANE_CFG_VIEWPORT_ELEMENT_SIZE_MASK 0x0000E000
+#define VPE_PLANE_CFG_VIEWPORT_WIDTH__SHIFT 0
+#define VPE_PLANE_CFG_VIEWPORT_WIDTH_MASK 0x00001FFF
+
+enum VPE_PLANE_CFG_ELEMENT_SIZE {
+ VPE_PLANE_CFG_ELEMENT_SIZE_8BPE = 0,
+ VPE_PLANE_CFG_ELEMENT_SIZE_16BPE = 1,
+ VPE_PLANE_CFG_ELEMENT_SIZE_32BPE = 2,
+ VPE_PLANE_CFG_ELEMENT_SIZE_64BPE = 3
+};
+
+#define VPE_PLANE_CFG_CMD_HEADER(subop, nps0, npd0, nps1, npd1) \
+ (VPE_CMD_HEADER(VPE_CMD_OPCODE_PLANE_CFG, subop) | \
+ (((nps0) << VPE_PLANE_CFG_NPS0__SHIFT) & VPE_PLANE_CFG_NPS0_MASK) | \
+ (((npd0) << VPE_PLANE_CFG_NPD0__SHIFT) & VPE_PLANE_CFG_NPD0_MASK) | \
+ (((nps1) << VPE_PLANE_CFG_NPS1__SHIFT) & VPE_PLANE_CFG_NPS1_MASK) | \
+ (((npd0) << VPE_PLANE_CFG_NPD1__SHIFT) & VPE_PLANE_CFG_NPD1_MASK))
+
+
+/************************
+ * VPEP Config
+ ************************/
+enum VPE_VPEP_CFG_SUBOP {
+ VPE_VPEP_CFG_SUBOP_DIR_CFG = 0x0,
+ VPE_VPEP_CFG_SUBOP_IND_CFG = 0x1
+};
+
+
+// Direct Config Command Header
+#define VPE_DIR_CFG_HEADER_ARRAY_SIZE__SHIFT 16
+#define VPE_DIR_CFG_HEADER_ARRAY_SIZE_MASK 0xFFFF0000
+
+#define VPE_DIR_CFG_CMD_HEADER(subop, arr_sz) \
+ (VPE_CMD_HEADER(VPE_CMD_OPCODE_VPEP_CFG, subop) | \
+ (((arr_sz) << VPE_DIR_CFG_HEADER_ARRAY_SIZE__SHIFT) & VPE_DIR_CFG_HEADER_ARRAY_SIZE_MASK))
+
+
+#define VPE_DIR_CFG_PKT_REGISTER_OFFSET__SHIFT 2
+#define VPE_DIR_CFG_PKT_REGISTER_OFFSET_MASK 0x000FFFFC
+
+#define VPE_DIR_CFG_PKT_DATA_SIZE__SHIFT 20
+#define VPE_DIR_CFG_PKT_DATA_SIZE_MASK 0xFFF00000
+
+
+// InDirect Config Command Header
+#define VPE_IND_CFG_HEADER_NUM_DST__SHIFT 28
+#define VPE_IND_CFG_HEADER_NUM_DST_MASK 0xF0000000
+
+#define VPE_IND_CFG_CMD_HEADER(subop, num_dst) \
+ (VPE_CMD_HEADER(VPE_CMD_OPCODE_VPEP_CFG, subop) | \
+ (((num_dst) << VPE_IND_CFG_HEADER_NUM_DST__SHIFT) & VPE_IND_CFG_HEADER_NUM_DST_MASK))
+
+// Indirect Buffer Command Header
+#define VPE_CMD_INDIRECT_HEADER_VMID__SHIFT 16
+#define VPE_CMD_INDIRECT_HEADER_VMID_MASK 0x0000000F
+#define VPE_CMD_INDIRECT_HEADER_VMID(vmid) \
+ (((vmid) & VPE_CMD_INDIRECT_HEADER_VMID_MASK) << VPE_CMD_INDIRECT_HEADER_VMID__SHIFT)
+
+
+/**************************
+ * Poll Reg/Mem Sub-OpCode
+ **************************/
+enum VPE_POLL_REGMEM_SUBOP {
+ VPE_POLL_REGMEM_SUBOP_REGMEM = 0x0,
+ VPE_POLL_REGMEM_SUBOP_REGMEM_WRITE = 0x1
+};
+
+#define VPE_CMD_POLL_REGMEM_HEADER_FUNC__SHIFT 28
+#define VPE_CMD_POLL_REGMEM_HEADER_FUNC_MASK 0x00000007
+#define VPE_CMD_POLL_REGMEM_HEADER_FUNC(func) \
+ (((func) & VPE_CMD_POLL_REGMEM_HEADER_FUNC_MASK) << VPE_CMD_POLL_REGMEM_HEADER_FUNC__SHIFT)
+
+#define VPE_CMD_POLL_REGMEM_HEADER_MEM__SHIFT 31
+#define VPE_CMD_POLL_REGMEM_HEADER_MEM_MASK 0x00000001
+#define VPE_CMD_POLL_REGMEM_HEADER_MEM(mem) \
+ (((mem) & VPE_CMD_POLL_REGMEM_HEADER_MEM_MASK) << VPE_CMD_POLL_REGMEM_HEADER_MEM__SHIFT)
+
+#define VPE_CMD_POLL_REGMEM_DW5_INTERVAL__SHIFT 0
+#define VPE_CMD_POLL_REGMEM_DW5_INTERVAL_MASK 0x0000FFFF
+#define VPE_CMD_POLL_REGMEM_DW5_INTERVAL(interval) \
+ (((interval) & VPE_CMD_POLL_REGMEM_DW5_INTERVAL_MASK) << VPE_CMD_POLL_REGMEM_DW5_INTERVAL__SHIFT)
+
+#define VPE_CMD_POLL_REGMEM_DW5_RETRY_COUNT__SHIFT 16
+#define VPE_CMD_POLL_REGMEM_DW5_RETRY_COUNT_MASK 0x00000FFF
+#define VPE_CMD_POLL_REGMEM_DW5_RETRY_COUNT(count) \
+ (((count) & VPE_CMD_POLL_REGMEM_DW5_RETRY_COUNT_MASK) << VPE_CMD_POLL_REGMEM_DW5_RETRY_COUNT__SHIFT)
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c b/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c
new file mode 100644
index 000000000000..174f13eff575
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/firmware.h>
+#include <drm/drm_drv.h>
+
+#include "amdgpu.h"
+#include "amdgpu_ucode.h"
+#include "amdgpu_vpe.h"
+#include "vpe_v6_1.h"
+#include "soc15_common.h"
+#include "ivsrcid/vpe/irqsrcs_vpe_6_1.h"
+#include "vpe/vpe_6_1_0_offset.h"
+#include "vpe/vpe_6_1_0_sh_mask.h"
+
+MODULE_FIRMWARE("amdgpu/vpe_6_1_0.bin");
+
+#define VPE_THREAD1_UCODE_OFFSET 0x8000
+
+static uint32_t vpe_v6_1_get_reg_offset(struct amdgpu_vpe *vpe, uint32_t inst, uint32_t offset)
+{
+ uint32_t base;
+
+ base = vpe->ring.adev->reg_offset[VPE_HWIP][0][0];
+
+ return base + offset;
+}
+
+static void vpe_v6_1_halt(struct amdgpu_vpe *vpe, bool halt)
+{
+ struct amdgpu_device *adev = vpe->ring.adev;
+ uint32_t f32_cntl;
+
+ f32_cntl = RREG32(vpe_get_reg_offset(vpe, 0, regVPEC_F32_CNTL));
+ f32_cntl = REG_SET_FIELD(f32_cntl, VPEC_F32_CNTL, HALT, halt ? 1 : 0);
+ f32_cntl = REG_SET_FIELD(f32_cntl, VPEC_F32_CNTL, TH1_RESET, halt ? 1 : 0);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_F32_CNTL), f32_cntl);
+}
+
+static int vpe_v6_1_irq_init(struct amdgpu_vpe *vpe)
+{
+ struct amdgpu_device *adev = container_of(vpe, struct amdgpu_device, vpe);
+ int ret;
+
+ ret = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_VPE,
+ VPE_6_1_SRCID__VPE_TRAP,
+ &adev->vpe.trap_irq);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe)
+{
+ struct amdgpu_device *adev = vpe->ring.adev;
+ const struct vpe_firmware_header_v1_0 *vpe_hdr;
+ const __le32 *data;
+ uint32_t ucode_offset[2], ucode_size[2];
+ uint32_t i, size_dw;
+ uint32_t ret;
+
+ // disable UMSCH_INT_ENABLE
+ ret = RREG32(vpe_get_reg_offset(vpe, 0, regVPEC_CNTL));
+ ret = REG_SET_FIELD(ret, VPEC_CNTL, UMSCH_INT_ENABLE, 0);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_CNTL), ret);
+
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+ uint32_t f32_offset, f32_cntl;
+
+ f32_offset = vpe_get_reg_offset(vpe, 0, regVPEC_F32_CNTL);
+ f32_cntl = RREG32(f32_offset);
+ f32_cntl = REG_SET_FIELD(f32_cntl, VPEC_F32_CNTL, HALT, 0);
+ f32_cntl = REG_SET_FIELD(f32_cntl, VPEC_F32_CNTL, TH1_RESET, 0);
+
+ adev->vpe.cmdbuf_cpu_addr[0] = f32_offset;
+ adev->vpe.cmdbuf_cpu_addr[1] = f32_cntl;
+
+ amdgpu_vpe_psp_update_sram(adev);
+ return 0;
+ }
+
+ vpe_hdr = (const struct vpe_firmware_header_v1_0 *)adev->vpe.fw->data;
+
+ /* Thread 0(command thread) ucode offset/size */
+ ucode_offset[0] = le32_to_cpu(vpe_hdr->header.ucode_array_offset_bytes);
+ ucode_size[0] = le32_to_cpu(vpe_hdr->ctx_ucode_size_bytes);
+ /* Thread 1(control thread) ucode offset/size */
+ ucode_offset[1] = le32_to_cpu(vpe_hdr->ctl_ucode_offset);
+ ucode_size[1] = le32_to_cpu(vpe_hdr->ctl_ucode_size_bytes);
+
+ vpe_v6_1_halt(vpe, true);
+
+ for (i = 0; i < 2; i++) {
+ if (i > 0)
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_UCODE_ADDR), VPE_THREAD1_UCODE_OFFSET);
+ else
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_UCODE_ADDR), 0);
+
+ data = (const __le32 *)(adev->vpe.fw->data + ucode_offset[i]);
+ size_dw = ucode_size[i] / sizeof(__le32);
+
+ while (size_dw--) {
+ if (amdgpu_emu_mode && size_dw % 500 == 0)
+ msleep(1);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_UCODE_DATA), le32_to_cpup(data++));
+ }
+
+ }
+
+ vpe_v6_1_halt(vpe, false);
+
+ return 0;
+}
+
+static int vpe_v6_1_ring_start(struct amdgpu_vpe *vpe)
+{
+ struct amdgpu_ring *ring = &vpe->ring;
+ struct amdgpu_device *adev = ring->adev;
+ uint32_t rb_bufsz, rb_cntl;
+ uint32_t ib_cntl;
+ uint32_t doorbell, doorbell_offset;
+ int ret;
+
+ rb_bufsz = order_base_2(ring->ring_size / 4);
+ rb_cntl = RREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_CNTL));
+ rb_cntl = REG_SET_FIELD(rb_cntl, VPEC_QUEUE0_RB_CNTL, RB_SIZE, rb_bufsz);
+ rb_cntl = REG_SET_FIELD(rb_cntl, VPEC_QUEUE0_RB_CNTL, RB_PRIV, 1);
+ rb_cntl = REG_SET_FIELD(rb_cntl, VPEC_QUEUE0_RB_CNTL, RB_VMID, 0);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_CNTL), rb_cntl);
+
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_RPTR), 0);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_RPTR_HI), 0);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_WPTR), 0);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_WPTR_HI), 0);
+
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_RPTR_ADDR_LO),
+ lower_32_bits(ring->rptr_gpu_addr) & 0xFFFFFFFC);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_RPTR_ADDR_HI),
+ upper_32_bits(ring->rptr_gpu_addr) & 0xFFFFFFFF);
+
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_BASE), ring->gpu_addr >> 8);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_BASE_HI), ring->gpu_addr >> 40);
+
+ ring->wptr = 0;
+
+ /* before programing wptr to a less value, need set minor_ptr_update first */
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_MINOR_PTR_UPDATE), 1);
+
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_WPTR), lower_32_bits(ring->wptr) << 2);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_WPTR_HI), upper_32_bits(ring->wptr) << 2);
+
+ /* set minor_ptr_update to 0 after wptr programed */
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_MINOR_PTR_UPDATE), 0);
+
+ doorbell = RREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_DOORBELL));
+ doorbell_offset = RREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_DOORBELL_OFFSET));
+
+ doorbell = REG_SET_FIELD(doorbell, VPEC_QUEUE0_DOORBELL, ENABLE, ring->use_doorbell ? 1 : 0);
+ doorbell_offset = REG_SET_FIELD(doorbell_offset, VPEC_QUEUE0_DOORBELL_OFFSET, OFFSET, ring->doorbell_index);
+
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_DOORBELL), doorbell);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_DOORBELL_OFFSET), doorbell_offset);
+
+ adev->nbio.funcs->vpe_doorbell_range(adev, 0, ring->use_doorbell, ring->doorbell_index, 2);
+
+ rb_cntl = REG_SET_FIELD(rb_cntl, VPEC_QUEUE0_RB_CNTL, RPTR_WRITEBACK_ENABLE, 1);
+ rb_cntl = REG_SET_FIELD(rb_cntl, VPEC_QUEUE0_RB_CNTL, RB_ENABLE, 1);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_RB_CNTL), rb_cntl);
+
+ ib_cntl = RREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_IB_CNTL));
+ ib_cntl = REG_SET_FIELD(ib_cntl, VPEC_QUEUE0_IB_CNTL, IB_ENABLE, 1);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE0_IB_CNTL), ib_cntl);
+
+ ring->sched.ready = true;
+
+ ret = amdgpu_ring_test_helper(ring);
+ if (ret) {
+ ring->sched.ready = false;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int vpe_v_6_1_ring_stop(struct amdgpu_vpe *vpe)
+{
+ struct amdgpu_device *adev = vpe->ring.adev;
+ uint32_t queue_reset;
+ int ret;
+
+ queue_reset = RREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE_RESET_REQ));
+ queue_reset = REG_SET_FIELD(queue_reset, VPEC_QUEUE_RESET_REQ, QUEUE0_RESET, 1);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_QUEUE_RESET_REQ), queue_reset);
+
+ ret = SOC15_WAIT_ON_RREG(VPE, 0, regVPEC_QUEUE_RESET_REQ, 0,
+ VPEC_QUEUE_RESET_REQ__QUEUE0_RESET_MASK);
+ if (ret)
+ dev_err(adev->dev, "VPE queue reset failed\n");
+
+ vpe->ring.sched.ready = false;
+
+ return ret;
+}
+
+static int vpe_v6_1_set_trap_irq_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ unsigned int type,
+ enum amdgpu_interrupt_state state)
+{
+ struct amdgpu_vpe *vpe = &adev->vpe;
+ uint32_t vpe_cntl;
+
+ vpe_cntl = RREG32(vpe_get_reg_offset(vpe, 0, regVPEC_CNTL));
+ vpe_cntl = REG_SET_FIELD(vpe_cntl, VPEC_CNTL, TRAP_ENABLE,
+ state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
+ WREG32(vpe_get_reg_offset(vpe, 0, regVPEC_CNTL), vpe_cntl);
+
+ return 0;
+}
+
+static int vpe_v6_1_process_trap_irq(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+
+ dev_dbg(adev->dev, "IH: VPE trap\n");
+
+ switch (entry->client_id) {
+ case SOC21_IH_CLIENTID_VPE:
+ amdgpu_fence_process(&adev->vpe.ring);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int vpe_v6_1_set_regs(struct amdgpu_vpe *vpe)
+{
+ vpe->regs.queue0_rb_rptr_lo = regVPEC_QUEUE0_RB_RPTR;
+ vpe->regs.queue0_rb_rptr_hi = regVPEC_QUEUE0_RB_RPTR_HI;
+ vpe->regs.queue0_rb_wptr_lo = regVPEC_QUEUE0_RB_WPTR;
+ vpe->regs.queue0_rb_wptr_hi = regVPEC_QUEUE0_RB_WPTR_HI;
+ vpe->regs.queue0_preempt = regVPEC_QUEUE0_PREEMPT;
+
+ return 0;
+}
+
+static const struct vpe_funcs vpe_v6_1_funcs = {
+ .get_reg_offset = vpe_v6_1_get_reg_offset,
+ .set_regs = vpe_v6_1_set_regs,
+ .irq_init = vpe_v6_1_irq_init,
+ .init_microcode = amdgpu_vpe_init_microcode,
+ .load_microcode = vpe_v6_1_load_microcode,
+ .ring_init = amdgpu_vpe_ring_init,
+ .ring_start = vpe_v6_1_ring_start,
+ .ring_stop = vpe_v_6_1_ring_stop,
+ .ring_fini = amdgpu_vpe_ring_fini,
+};
+
+static const struct amdgpu_irq_src_funcs vpe_v6_1_trap_irq_funcs = {
+ .set = vpe_v6_1_set_trap_irq_state,
+ .process = vpe_v6_1_process_trap_irq,
+};
+
+void vpe_v6_1_set_funcs(struct amdgpu_vpe *vpe)
+{
+ vpe->funcs = &vpe_v6_1_funcs;
+ vpe->trap_irq.funcs = &vpe_v6_1_trap_irq_funcs;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.h b/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.h
new file mode 100644
index 000000000000..a9bea7905a77
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __VPE_V6_1_H__
+#define __VPE_V6_1_H__
+
+#include "amdgpu_vpe.h"
+
+void vpe_v6_1_set_funcs(struct amdgpu_vpe *vpe);
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index c37f1fcd2165..f6d4748c1980 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1021,7 +1021,7 @@ err_drm_file:
bool kfd_dev_is_large_bar(struct kfd_node *dev)
{
- if (debug_largebar) {
+ if (dev->kfd->adev->debug_largebar) {
pr_debug("Simulate large-bar allocation on non large-bar machine\n");
return true;
}
@@ -1432,17 +1432,21 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
goto sync_memory_failed;
}
}
- mutex_unlock(&p->mutex);
- if (flush_tlb) {
- /* Flush TLBs after waiting for the page table updates to complete */
- for (i = 0; i < args->n_devices; i++) {
- peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
- if (WARN_ON_ONCE(!peer_pdd))
- continue;
+ /* Flush TLBs after waiting for the page table updates to complete */
+ for (i = 0; i < args->n_devices; i++) {
+ peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
+ if (WARN_ON_ONCE(!peer_pdd))
+ continue;
+ if (flush_tlb)
kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT);
- }
+
+ /* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */
+ amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv);
}
+
+ mutex_unlock(&p->mutex);
+
kfree(devices_arr);
return 0;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index f76b7aee5c0a..cd8e459201f1 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -1404,6 +1404,66 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
return i;
}
+static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev,
+ struct kfd_gpu_cache_info *pcache_info)
+{
+ struct amdgpu_device *adev = kdev->adev;
+ int i = 0;
+
+ /* TCP L1 Cache per CU */
+ if (adev->gfx.config.gc_tcp_size_per_cu) {
+ pcache_info[i].cache_size = adev->gfx.config.gc_tcp_size_per_cu;
+ pcache_info[i].cache_level = 1;
+ pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
+ CRAT_CACHE_FLAGS_DATA_CACHE |
+ CRAT_CACHE_FLAGS_SIMD_CACHE);
+ pcache_info[i].num_cu_shared = 1;
+ i++;
+ }
+ /* Scalar L1 Instruction Cache per SQC */
+ if (adev->gfx.config.gc_l1_instruction_cache_size_per_sqc) {
+ pcache_info[i].cache_size =
+ adev->gfx.config.gc_l1_instruction_cache_size_per_sqc;
+ pcache_info[i].cache_level = 1;
+ pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
+ CRAT_CACHE_FLAGS_INST_CACHE |
+ CRAT_CACHE_FLAGS_SIMD_CACHE);
+ pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_cu_per_sqc;
+ i++;
+ }
+ /* Scalar L1 Data Cache per SQC */
+ if (adev->gfx.config.gc_l1_data_cache_size_per_sqc) {
+ pcache_info[i].cache_size = adev->gfx.config.gc_l1_data_cache_size_per_sqc;
+ pcache_info[i].cache_level = 1;
+ pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
+ CRAT_CACHE_FLAGS_DATA_CACHE |
+ CRAT_CACHE_FLAGS_SIMD_CACHE);
+ pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_cu_per_sqc;
+ i++;
+ }
+ /* L2 Data Cache per GPU (Total Tex Cache) */
+ if (adev->gfx.config.gc_tcc_size) {
+ pcache_info[i].cache_size = adev->gfx.config.gc_tcc_size;
+ pcache_info[i].cache_level = 2;
+ pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
+ CRAT_CACHE_FLAGS_DATA_CACHE |
+ CRAT_CACHE_FLAGS_SIMD_CACHE);
+ pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
+ i++;
+ }
+ /* L3 Data Cache per GPU */
+ if (adev->gmc.mall_size) {
+ pcache_info[i].cache_size = adev->gmc.mall_size / 1024;
+ pcache_info[i].cache_level = 3;
+ pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
+ CRAT_CACHE_FLAGS_DATA_CACHE |
+ CRAT_CACHE_FLAGS_SIMD_CACHE);
+ pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
+ i++;
+ }
+ return i;
+}
+
int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pcache_info)
{
int num_of_cache_types = 0;
@@ -1461,10 +1521,14 @@ int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pc
num_of_cache_types = ARRAY_SIZE(vega20_cache_info);
break;
case IP_VERSION(9, 4, 2):
- case IP_VERSION(9, 4, 3):
*pcache_info = aldebaran_cache_info;
num_of_cache_types = ARRAY_SIZE(aldebaran_cache_info);
break;
+ case IP_VERSION(9, 4, 3):
+ num_of_cache_types =
+ kfd_fill_gpu_cache_info_from_gfx_config_v2(kdev->kfd,
+ *pcache_info);
+ break;
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 2):
*pcache_info = raven_cache_info;
@@ -1522,6 +1586,7 @@ int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pc
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
num_of_cache_types =
kfd_fill_gpu_cache_info_from_gfx_config(kdev->kfd, *pcache_info);
break;
@@ -2037,11 +2102,12 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
uint32_t proximity_domain)
{
struct crat_header *crat_table = (struct crat_header *)pcrat_image;
+ struct amdgpu_gfx_config *gfx_info = &kdev->adev->gfx.config;
+ struct amdgpu_cu_info *cu_info = &kdev->adev->gfx.cu_info;
struct crat_subtype_generic *sub_type_hdr;
struct kfd_local_mem_info local_mem_info;
struct kfd_topology_device *peer_dev;
struct crat_subtype_computeunit *cu;
- struct kfd_cu_info cu_info;
int avail_size = *size;
uint32_t total_num_of_cu;
uint32_t nid = 0;
@@ -2085,21 +2151,20 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
cu->flags |= CRAT_CU_FLAGS_GPU_PRESENT;
cu->proximity_domain = proximity_domain;
- amdgpu_amdkfd_get_cu_info(kdev->adev, &cu_info);
- cu->num_simd_per_cu = cu_info.simd_per_cu;
- cu->num_simd_cores = cu_info.simd_per_cu *
- (cu_info.cu_active_number / kdev->kfd->num_nodes);
- cu->max_waves_simd = cu_info.max_waves_per_simd;
+ cu->num_simd_per_cu = cu_info->simd_per_cu;
+ cu->num_simd_cores = cu_info->simd_per_cu *
+ (cu_info->number / kdev->kfd->num_nodes);
+ cu->max_waves_simd = cu_info->max_waves_per_simd;
- cu->wave_front_size = cu_info.wave_front_size;
- cu->array_count = cu_info.num_shader_arrays_per_engine *
- cu_info.num_shader_engines;
- total_num_of_cu = (cu->array_count * cu_info.num_cu_per_sh);
+ cu->wave_front_size = cu_info->wave_front_size;
+ cu->array_count = gfx_info->max_sh_per_se *
+ gfx_info->max_shader_engines;
+ total_num_of_cu = (cu->array_count * gfx_info->max_cu_per_sh);
cu->processor_id_low = get_and_inc_gpu_processor_id(total_num_of_cu);
- cu->num_cu_per_array = cu_info.num_cu_per_sh;
- cu->max_slots_scatch_cu = cu_info.max_scratch_slots_per_cu;
- cu->num_banks = cu_info.num_shader_engines;
- cu->lds_size_in_kb = cu_info.lds_size;
+ cu->num_cu_per_array = gfx_info->max_cu_per_sh;
+ cu->max_slots_scatch_cu = cu_info->max_scratch_slots_per_cu;
+ cu->num_banks = gfx_info->max_shader_engines;
+ cu->lds_size_in_kb = cu_info->lds_size;
cu->hsa_capability = 0;
@@ -2115,7 +2180,7 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
sub_type_hdr->length);
- if (debug_largebar)
+ if (kdev->adev->debug_largebar)
local_mem_info.local_mem_size_private = 0;
if (local_mem_info.local_mem_size_private == 0)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
index 93ce181eb3ba..0a9cf9dfc224 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
@@ -65,7 +65,7 @@ static int kfd_resume(struct kfd_node *kfd);
static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd)
{
- uint32_t sdma_version = kfd->adev->ip_versions[SDMA0_HWIP][0];
+ uint32_t sdma_version = amdgpu_ip_version(kfd->adev, SDMA0_HWIP, 0);
switch (sdma_version) {
case IP_VERSION(4, 0, 0):/* VEGA10 */
@@ -95,6 +95,7 @@ static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd)
case IP_VERSION(6, 0, 1):
case IP_VERSION(6, 0, 2):
case IP_VERSION(6, 0, 3):
+ case IP_VERSION(6, 1, 0):
kfd->device_info.num_sdma_queues_per_engine = 8;
break;
default:
@@ -111,6 +112,7 @@ static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd)
case IP_VERSION(6, 0, 1):
case IP_VERSION(6, 0, 2):
case IP_VERSION(6, 0, 3):
+ case IP_VERSION(6, 1, 0):
/* Reserve 1 for paging and 1 for gfx */
kfd->device_info.num_reserved_sdma_queues_per_engine = 2;
/* BIT(0)=engine-0 queue-0; BIT(1)=engine-1 queue-0; BIT(2)=engine-0 queue-1; ... */
@@ -162,6 +164,7 @@ static void kfd_device_info_set_event_interrupt_class(struct kfd_dev *kfd)
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
case IP_VERSION(11, 0, 4):
+ case IP_VERSION(11, 5, 0):
kfd->device_info.event_interrupt_class = &event_interrupt_class_v11;
break;
default:
@@ -279,7 +282,7 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
f2g = &gfx_v8_kfd2kgd;
break;
default:
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
/* Vega 10 */
case IP_VERSION(9, 0, 1):
gfx_target_version = 90000;
@@ -413,6 +416,10 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
gfx_target_version = 110001;
f2g = &gfx_v11_kfd2kgd;
break;
+ case IP_VERSION(11, 5, 0):
+ gfx_target_version = 110500;
+ f2g = &gfx_v11_kfd2kgd;
+ break;
default:
break;
}
@@ -420,9 +427,11 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
}
if (!f2g) {
- if (adev->ip_versions[GC_HWIP][0])
- dev_err(kfd_device, "GC IP %06x %s not supported in kfd\n",
- adev->ip_versions[GC_HWIP][0], vf ? "VF" : "");
+ if (amdgpu_ip_version(adev, GC_HWIP, 0))
+ dev_err(kfd_device,
+ "GC IP %06x %s not supported in kfd\n",
+ amdgpu_ip_version(adev, GC_HWIP, 0),
+ vf ? "VF" : "");
else
dev_err(kfd_device, "%s %s not supported in kfd\n",
amdgpu_asic_name[adev->asic_type], vf ? "VF" : "");
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index 0d3d538b64eb..c0e71543389a 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -92,7 +92,7 @@ static bool is_pipe_enabled(struct device_queue_manager *dqm, int mec, int pipe)
unsigned int get_cp_queues_num(struct device_queue_manager *dqm)
{
return bitmap_weight(dqm->dev->kfd->shared_resources.cp_queue_bitmap,
- KGD_MAX_QUEUES);
+ AMDGPU_MAX_QUEUES);
}
unsigned int get_queues_per_pipe(struct device_queue_manager *dqm)
@@ -227,13 +227,15 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
queue_input.tba_addr = qpd->tba_addr;
queue_input.tma_addr = qpd->tma_addr;
queue_input.trap_en = !kfd_dbg_has_cwsr_workaround(q->device);
- queue_input.skip_process_ctx_clear = qpd->pqm->process->debug_trap_enabled ||
- kfd_dbg_has_ttmps_always_setup(q->device);
+ queue_input.skip_process_ctx_clear =
+ qpd->pqm->process->runtime_info.runtime_state == DEBUG_RUNTIME_STATE_ENABLED &&
+ (qpd->pqm->process->debug_trap_enabled ||
+ kfd_dbg_has_ttmps_always_setup(q->device));
queue_type = convert_to_mes_queue_type(q->properties.type);
if (queue_type < 0) {
- pr_err("Queue type not supported with MES, queue:%d\n",
- q->properties.type);
+ dev_err(adev->dev, "Queue type not supported with MES, queue:%d\n",
+ q->properties.type);
return -EINVAL;
}
queue_input.queue_type = (uint32_t)queue_type;
@@ -244,9 +246,9 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
r = adev->mes.funcs->add_hw_queue(&adev->mes, &queue_input);
amdgpu_mes_unlock(&adev->mes);
if (r) {
- pr_err("failed to add hardware queue to MES, doorbell=0x%x\n",
+ dev_err(adev->dev, "failed to add hardware queue to MES, doorbell=0x%x\n",
q->properties.doorbell_off);
- pr_err("MES might be in unrecoverable state, issue a GPU reset\n");
+ dev_err(adev->dev, "MES might be in unrecoverable state, issue a GPU reset\n");
kfd_hws_hang(dqm);
}
@@ -272,9 +274,9 @@ static int remove_queue_mes(struct device_queue_manager *dqm, struct queue *q,
amdgpu_mes_unlock(&adev->mes);
if (r) {
- pr_err("failed to remove hardware queue from MES, doorbell=0x%x\n",
+ dev_err(adev->dev, "failed to remove hardware queue from MES, doorbell=0x%x\n",
q->properties.doorbell_off);
- pr_err("MES might be in unrecoverable state, issue a GPU reset\n");
+ dev_err(adev->dev, "MES might be in unrecoverable state, issue a GPU reset\n");
kfd_hws_hang(dqm);
}
@@ -284,6 +286,7 @@ static int remove_queue_mes(struct device_queue_manager *dqm, struct queue *q,
static int remove_all_queues_mes(struct device_queue_manager *dqm)
{
struct device_process_node *cur;
+ struct device *dev = dqm->dev->adev->dev;
struct qcm_process_device *qpd;
struct queue *q;
int retval = 0;
@@ -294,7 +297,7 @@ static int remove_all_queues_mes(struct device_queue_manager *dqm)
if (q->properties.is_active) {
retval = remove_queue_mes(dqm, q, qpd);
if (retval) {
- pr_err("%s: Failed to remove queue %d for dev %d",
+ dev_err(dev, "%s: Failed to remove queue %d for dev %d",
__func__,
q->properties.queue_id,
dqm->dev->id);
@@ -407,7 +410,8 @@ static int allocate_doorbell(struct qcm_process_device *qpd,
q->properties.doorbell_off = amdgpu_doorbell_index_on_bar(dev->adev,
qpd->proc_doorbells,
- q->doorbell_id);
+ q->doorbell_id,
+ dev->kfd->device_info.doorbell_size);
return 0;
}
@@ -443,6 +447,7 @@ static int allocate_vmid(struct device_queue_manager *dqm,
struct qcm_process_device *qpd,
struct queue *q)
{
+ struct device *dev = dqm->dev->adev->dev;
int allocated_vmid = -1, i;
for (i = dqm->dev->vm_info.first_vmid_kfd;
@@ -454,7 +459,7 @@ static int allocate_vmid(struct device_queue_manager *dqm,
}
if (allocated_vmid < 0) {
- pr_err("no more vmid to allocate\n");
+ dev_err(dev, "no more vmid to allocate\n");
return -ENOSPC;
}
@@ -510,10 +515,12 @@ static void deallocate_vmid(struct device_queue_manager *dqm,
struct qcm_process_device *qpd,
struct queue *q)
{
+ struct device *dev = dqm->dev->adev->dev;
+
/* On GFX v7, CP doesn't flush TC at dequeue */
if (q->device->adev->asic_type == CHIP_HAWAII)
if (flush_texture_cache_nocpsch(q->device, qpd))
- pr_err("Failed to flush TC\n");
+ dev_err(dev, "Failed to flush TC\n");
kfd_flush_tlb(qpd_to_pdd(qpd), TLB_FLUSH_LEGACY);
@@ -708,7 +715,7 @@ static int dbgdev_wave_reset_wavefronts(struct kfd_node *dev, struct kfd_process
pr_debug("Killing all process wavefronts\n");
if (!dev->kfd2kgd->get_atc_vmid_pasid_mapping_info) {
- pr_err("no vmid pasid mapping supported \n");
+ dev_err(dev->adev->dev, "no vmid pasid mapping supported\n");
return -EOPNOTSUPP;
}
@@ -729,7 +736,7 @@ static int dbgdev_wave_reset_wavefronts(struct kfd_node *dev, struct kfd_process
}
if (vmid > last_vmid_to_scan) {
- pr_err("Didn't find vmid for pasid 0x%x\n", p->pasid);
+ dev_err(dev->adev->dev, "Didn't find vmid for pasid 0x%x\n", p->pasid);
return -EFAULT;
}
@@ -821,6 +828,7 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm,
{
int retval;
uint64_t sdma_val = 0;
+ struct device *dev = dqm->dev->adev->dev;
struct kfd_process_device *pdd = qpd_to_pdd(qpd);
struct mqd_manager *mqd_mgr =
dqm->mqd_mgrs[get_mqd_type_from_queue_type(q->properties.type)];
@@ -831,7 +839,7 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm,
retval = read_sdma_queue_counter((uint64_t __user *)q->properties.read_ptr,
&sdma_val);
if (retval)
- pr_err("Failed to read SDMA queue counter for queue: %d\n",
+ dev_err(dev, "Failed to read SDMA queue counter for queue: %d\n",
q->properties.queue_id);
}
@@ -850,6 +858,7 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q,
struct mqd_update_info *minfo)
{
int retval = 0;
+ struct device *dev = dqm->dev->adev->dev;
struct mqd_manager *mqd_mgr;
struct kfd_process_device *pdd;
bool prev_active = false;
@@ -875,7 +884,7 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q,
retval = remove_queue_mes(dqm, q, &pdd->qpd);
if (retval) {
- pr_err("unmap queue failed\n");
+ dev_err(dev, "unmap queue failed\n");
goto out_unlock;
}
} else if (prev_active &&
@@ -894,7 +903,7 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q,
KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN),
KFD_UNMAP_LATENCY_MS, q->pipe, q->queue);
if (retval) {
- pr_err("destroy mqd failed\n");
+ dev_err(dev, "destroy mqd failed\n");
goto out_unlock;
}
}
@@ -1088,6 +1097,7 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
struct qcm_process_device *qpd)
{
struct queue *q;
+ struct device *dev = dqm->dev->adev->dev;
struct kfd_process_device *pdd;
int retval = 0;
@@ -1121,7 +1131,7 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
if (dqm->dev->kfd->shared_resources.enable_mes) {
retval = remove_queue_mes(dqm, q, qpd);
if (retval) {
- pr_err("Failed to evict queue %d\n",
+ dev_err(dev, "Failed to evict queue %d\n",
q->properties.queue_id);
goto out;
}
@@ -1225,6 +1235,7 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm,
struct qcm_process_device *qpd)
{
struct queue *q;
+ struct device *dev = dqm->dev->adev->dev;
struct kfd_process_device *pdd;
uint64_t eviction_duration;
int retval = 0;
@@ -1265,7 +1276,7 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm,
if (dqm->dev->kfd->shared_resources.enable_mes) {
retval = add_queue_mes(dqm, q, qpd);
if (retval) {
- pr_err("Failed to restore queue %d\n",
+ dev_err(dev, "Failed to restore queue %d\n",
q->properties.queue_id);
goto out;
}
@@ -1474,18 +1485,19 @@ static void pre_reset(struct device_queue_manager *dqm)
static int allocate_sdma_queue(struct device_queue_manager *dqm,
struct queue *q, const uint32_t *restore_sdma_id)
{
+ struct device *dev = dqm->dev->adev->dev;
int bit;
if (q->properties.type == KFD_QUEUE_TYPE_SDMA) {
if (bitmap_empty(dqm->sdma_bitmap, KFD_MAX_SDMA_QUEUES)) {
- pr_err("No more SDMA queue to allocate\n");
+ dev_err(dev, "No more SDMA queue to allocate\n");
return -ENOMEM;
}
if (restore_sdma_id) {
/* Re-use existing sdma_id */
if (!test_bit(*restore_sdma_id, dqm->sdma_bitmap)) {
- pr_err("SDMA queue already in use\n");
+ dev_err(dev, "SDMA queue already in use\n");
return -EBUSY;
}
clear_bit(*restore_sdma_id, dqm->sdma_bitmap);
@@ -1504,13 +1516,13 @@ static int allocate_sdma_queue(struct device_queue_manager *dqm,
kfd_get_num_sdma_engines(dqm->dev);
} else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) {
if (bitmap_empty(dqm->xgmi_sdma_bitmap, KFD_MAX_SDMA_QUEUES)) {
- pr_err("No more XGMI SDMA queue to allocate\n");
+ dev_err(dev, "No more XGMI SDMA queue to allocate\n");
return -ENOMEM;
}
if (restore_sdma_id) {
/* Re-use existing sdma_id */
if (!test_bit(*restore_sdma_id, dqm->xgmi_sdma_bitmap)) {
- pr_err("SDMA queue already in use\n");
+ dev_err(dev, "SDMA queue already in use\n");
return -EBUSY;
}
clear_bit(*restore_sdma_id, dqm->xgmi_sdma_bitmap);
@@ -1562,11 +1574,12 @@ static int set_sched_resources(struct device_queue_manager *dqm)
{
int i, mec;
struct scheduling_resources res;
+ struct device *dev = dqm->dev->adev->dev;
res.vmid_mask = dqm->dev->compute_vmid_bitmap;
res.queue_mask = 0;
- for (i = 0; i < KGD_MAX_QUEUES; ++i) {
+ for (i = 0; i < AMDGPU_MAX_QUEUES; ++i) {
mec = (i / dqm->dev->kfd->shared_resources.num_queue_per_pipe)
/ dqm->dev->kfd->shared_resources.num_pipe_per_mec;
@@ -1582,7 +1595,7 @@ static int set_sched_resources(struct device_queue_manager *dqm)
* definition of res.queue_mask needs updating
*/
if (WARN_ON(i >= (sizeof(res.queue_mask)*8))) {
- pr_err("Invalid queue enabled by amdgpu: %d\n", i);
+ dev_err(dev, "Invalid queue enabled by amdgpu: %d\n", i);
break;
}
@@ -1625,6 +1638,7 @@ static int initialize_cpsch(struct device_queue_manager *dqm)
static int start_cpsch(struct device_queue_manager *dqm)
{
+ struct device *dev = dqm->dev->adev->dev;
int retval;
retval = 0;
@@ -1671,7 +1685,7 @@ static int start_cpsch(struct device_queue_manager *dqm)
retval = pm_update_grace_period(&dqm->packet_mgr,
grace_period);
if (retval)
- pr_err("Setting grace timeout failed\n");
+ dev_err(dev, "Setting grace timeout failed\n");
else if (dqm->dev->kfd2kgd->build_grace_period_packet_info)
/* Update dqm->wait_times maintained in software */
dqm->dev->kfd2kgd->build_grace_period_packet_info(
@@ -1880,15 +1894,17 @@ out:
return retval;
}
-int amdkfd_fence_wait_timeout(uint64_t *fence_addr,
- uint64_t fence_value,
- unsigned int timeout_ms)
+int amdkfd_fence_wait_timeout(struct device_queue_manager *dqm,
+ uint64_t fence_value,
+ unsigned int timeout_ms)
{
unsigned long end_jiffies = msecs_to_jiffies(timeout_ms) + jiffies;
+ struct device *dev = dqm->dev->adev->dev;
+ uint64_t *fence_addr = dqm->fence_addr;
while (*fence_addr != fence_value) {
if (time_after(jiffies, end_jiffies)) {
- pr_err("qcm fence wait loop timeout expired\n");
+ dev_err(dev, "qcm fence wait loop timeout expired\n");
/* In HWS case, this is used to halt the driver thread
* in order not to mess up CP states before doing
* scandumps for FW debugging.
@@ -1907,6 +1923,7 @@ int amdkfd_fence_wait_timeout(uint64_t *fence_addr,
/* dqm->lock mutex has to be locked before calling this function */
static int map_queues_cpsch(struct device_queue_manager *dqm)
{
+ struct device *dev = dqm->dev->adev->dev;
int retval;
if (!dqm->sched_running)
@@ -1919,7 +1936,7 @@ static int map_queues_cpsch(struct device_queue_manager *dqm)
retval = pm_send_runlist(&dqm->packet_mgr, &dqm->queues);
pr_debug("%s sent runlist\n", __func__);
if (retval) {
- pr_err("failed to execute runlist\n");
+ dev_err(dev, "failed to execute runlist\n");
return retval;
}
dqm->active_runlist = true;
@@ -1934,8 +1951,9 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
uint32_t grace_period,
bool reset)
{
- int retval = 0;
+ struct device *dev = dqm->dev->adev->dev;
struct mqd_manager *mqd_mgr;
+ int retval = 0;
if (!dqm->sched_running)
return 0;
@@ -1958,10 +1976,10 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
pm_send_query_status(&dqm->packet_mgr, dqm->fence_gpu_addr,
KFD_FENCE_COMPLETED);
/* should be timed out */
- retval = amdkfd_fence_wait_timeout(dqm->fence_addr, KFD_FENCE_COMPLETED,
- queue_preemption_timeout_ms);
+ retval = amdkfd_fence_wait_timeout(dqm, KFD_FENCE_COMPLETED,
+ queue_preemption_timeout_ms);
if (retval) {
- pr_err("The cp might be in an unrecoverable state due to an unsuccessful queues preemption\n");
+ dev_err(dev, "The cp might be in an unrecoverable state due to an unsuccessful queues preemption\n");
kfd_hws_hang(dqm);
return retval;
}
@@ -1976,7 +1994,7 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
*/
mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ];
if (mqd_mgr->read_doorbell_id(dqm->packet_mgr.priv_queue->queue->mqd)) {
- pr_err("HIQ MQD's queue_doorbell_id0 is not 0, Queue preemption time out\n");
+ dev_err(dev, "HIQ MQD's queue_doorbell_id0 is not 0, Queue preemption time out\n");
while (halt_if_hws_hang)
schedule();
return -ETIME;
@@ -1986,7 +2004,7 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
if (grace_period != USE_DEFAULT_GRACE_PERIOD) {
if (pm_update_grace_period(&dqm->packet_mgr,
USE_DEFAULT_GRACE_PERIOD))
- pr_err("Failed to reset grace period\n");
+ dev_err(dev, "Failed to reset grace period\n");
}
pm_release_ib(&dqm->packet_mgr);
@@ -2060,6 +2078,7 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
struct mqd_manager *mqd_mgr;
uint64_t sdma_val = 0;
struct kfd_process_device *pdd = qpd_to_pdd(qpd);
+ struct device *dev = dqm->dev->adev->dev;
/* Get the SDMA queue stats */
if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) ||
@@ -2067,7 +2086,7 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
retval = read_sdma_queue_counter((uint64_t __user *)q->properties.read_ptr,
&sdma_val);
if (retval)
- pr_err("Failed to read SDMA queue counter for queue: %d\n",
+ dev_err(dev, "Failed to read SDMA queue counter for queue: %d\n",
q->properties.queue_id);
}
@@ -2348,6 +2367,7 @@ static int process_termination_cpsch(struct device_queue_manager *dqm,
{
int retval;
struct queue *q;
+ struct device *dev = dqm->dev->adev->dev;
struct kernel_queue *kq, *kq_next;
struct mqd_manager *mqd_mgr;
struct device_process_node *cur, *next_dpn;
@@ -2381,7 +2401,7 @@ static int process_termination_cpsch(struct device_queue_manager *dqm,
if (dqm->dev->kfd->shared_resources.enable_mes) {
retval = remove_queue_mes(dqm, q, qpd);
if (retval)
- pr_err("Failed to remove queue %d\n",
+ dev_err(dev, "Failed to remove queue %d\n",
q->properties.queue_id);
}
}
@@ -2436,12 +2456,13 @@ static int process_termination_cpsch(struct device_queue_manager *dqm,
static int init_mqd_managers(struct device_queue_manager *dqm)
{
int i, j;
+ struct device *dev = dqm->dev->adev->dev;
struct mqd_manager *mqd_mgr;
for (i = 0; i < KFD_MQD_TYPE_MAX; i++) {
mqd_mgr = dqm->asic_ops.mqd_manager_init(i, dqm->dev);
if (!mqd_mgr) {
- pr_err("mqd manager [%d] initialization failed\n", i);
+ dev_err(dev, "mqd manager [%d] initialization failed\n", i);
goto out_free;
}
dqm->mqd_mgrs[i] = mqd_mgr;
@@ -2551,7 +2572,7 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
dqm->ops.checkpoint_mqd = checkpoint_mqd;
break;
default:
- pr_err("Invalid scheduling policy %d\n", dqm->sched_policy);
+ dev_err(dev->adev->dev, "Invalid scheduling policy %d\n", dqm->sched_policy);
goto out_free;
}
@@ -2589,7 +2610,7 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
goto out_free;
if (!dev->kfd->shared_resources.enable_mes && allocate_hiq_sdma_mqd(dqm)) {
- pr_err("Failed to allocate hiq sdma mqd trunk buffer\n");
+ dev_err(dev->adev->dev, "Failed to allocate hiq sdma mqd trunk buffer\n");
goto out_free;
}
@@ -2648,17 +2669,18 @@ int reserve_debug_trap_vmid(struct device_queue_manager *dqm,
struct qcm_process_device *qpd)
{
int r;
+ struct device *dev = dqm->dev->adev->dev;
int updated_vmid_mask;
if (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) {
- pr_err("Unsupported on sched_policy: %i\n", dqm->sched_policy);
+ dev_err(dev, "Unsupported on sched_policy: %i\n", dqm->sched_policy);
return -EINVAL;
}
dqm_lock(dqm);
if (dqm->trap_debug_vmid != 0) {
- pr_err("Trap debug id already reserved\n");
+ dev_err(dev, "Trap debug id already reserved\n");
r = -EBUSY;
goto out_unlock;
}
@@ -2694,19 +2716,20 @@ out_unlock:
int release_debug_trap_vmid(struct device_queue_manager *dqm,
struct qcm_process_device *qpd)
{
+ struct device *dev = dqm->dev->adev->dev;
int r;
int updated_vmid_mask;
uint32_t trap_debug_vmid;
if (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) {
- pr_err("Unsupported on sched_policy: %i\n", dqm->sched_policy);
+ dev_err(dev, "Unsupported on sched_policy: %i\n", dqm->sched_policy);
return -EINVAL;
}
dqm_lock(dqm);
trap_debug_vmid = dqm->trap_debug_vmid;
if (dqm->trap_debug_vmid == 0) {
- pr_err("Trap debug id is not reserved\n");
+ dev_err(dev, "Trap debug id is not reserved\n");
r = -EINVAL;
goto out_unlock;
}
@@ -2843,6 +2866,7 @@ int resume_queues(struct kfd_process *p,
for (i = 0; i < p->n_pdds; i++) {
struct kfd_process_device *pdd = p->pdds[i];
struct device_queue_manager *dqm = pdd->dev->dqm;
+ struct device *dev = dqm->dev->adev->dev;
struct qcm_process_device *qpd = &pdd->qpd;
struct queue *q;
int r, per_device_resumed = 0;
@@ -2893,7 +2917,7 @@ int resume_queues(struct kfd_process *p,
0,
USE_DEFAULT_GRACE_PERIOD);
if (r) {
- pr_err("Failed to resume process queues\n");
+ dev_err(dev, "Failed to resume process queues\n");
if (queue_ids) {
list_for_each_entry(q, &qpd->queues_list, list) {
int q_idx = q_array_get_index(
@@ -2945,6 +2969,7 @@ int suspend_queues(struct kfd_process *p,
for (i = 0; i < p->n_pdds; i++) {
struct kfd_process_device *pdd = p->pdds[i];
struct device_queue_manager *dqm = pdd->dev->dqm;
+ struct device *dev = dqm->dev->adev->dev;
struct qcm_process_device *qpd = &pdd->qpd;
struct queue *q;
int r, per_device_suspended = 0;
@@ -2993,7 +3018,7 @@ int suspend_queues(struct kfd_process *p,
grace_period);
if (r)
- pr_err("Failed to suspend process queues.\n");
+ dev_err(dev, "Failed to suspend process queues.\n");
else
total_suspended += per_device_suspended;
@@ -3080,10 +3105,11 @@ void set_queue_snapshot_entry(struct queue *q,
int debug_lock_and_unmap(struct device_queue_manager *dqm)
{
+ struct device *dev = dqm->dev->adev->dev;
int r;
if (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) {
- pr_err("Unsupported on sched_policy: %i\n", dqm->sched_policy);
+ dev_err(dev, "Unsupported on sched_policy: %i\n", dqm->sched_policy);
return -EINVAL;
}
@@ -3101,10 +3127,11 @@ int debug_lock_and_unmap(struct device_queue_manager *dqm)
int debug_map_and_unlock(struct device_queue_manager *dqm)
{
+ struct device *dev = dqm->dev->adev->dev;
int r;
if (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) {
- pr_err("Unsupported on sched_policy: %i\n", dqm->sched_policy);
+ dev_err(dev, "Unsupported on sched_policy: %i\n", dqm->sched_policy);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
index 7b38537c7c99..05c74887fd6f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
@@ -161,7 +161,10 @@ void __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd,
if (inx >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
return NULL;
- *doorbell_off = amdgpu_doorbell_index_on_bar(kfd->adev, kfd->doorbells, inx);
+ *doorbell_off = amdgpu_doorbell_index_on_bar(kfd->adev,
+ kfd->doorbells,
+ inx,
+ kfd->device_info.doorbell_size);
inx *= 2;
pr_debug("Get kernel queue doorbell\n"
@@ -240,7 +243,10 @@ phys_addr_t kfd_get_process_doorbells(struct kfd_process_device *pdd)
return 0;
}
- first_db_index = amdgpu_doorbell_index_on_bar(adev, pdd->qpd.proc_doorbells, 0);
+ first_db_index = amdgpu_doorbell_index_on_bar(adev,
+ pdd->qpd.proc_doorbells,
+ 0,
+ pdd->dev->kfd->device_info.doorbell_size);
return adev->doorbell.base + first_db_index * sizeof(uint32_t);
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c
index c7991e07b6be..a7697ec8188e 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c
@@ -268,7 +268,7 @@ static void event_interrupt_wq_v10(struct kfd_node *dev,
SQ_INTERRUPT_WORD_WAVE_CTXID1, ENCODING);
switch (encoding) {
case SQ_INTERRUPT_WORD_ENCODING_AUTO:
- pr_debug(
+ pr_debug_ratelimited(
"sq_intr: auto, se %d, ttrace %d, wlt %d, ttrac_buf0_full %d, ttrac_buf1_full %d, ttrace_utc_err %d\n",
REG_GET_FIELD(context_id1, SQ_INTERRUPT_WORD_AUTO_CTXID1,
SE_ID),
@@ -284,7 +284,7 @@ static void event_interrupt_wq_v10(struct kfd_node *dev,
THREAD_TRACE_UTC_ERROR));
break;
case SQ_INTERRUPT_WORD_ENCODING_INST:
- pr_debug("sq_intr: inst, se %d, data 0x%x, sa %d, priv %d, wave_id %d, simd_id %d, wgp_id %d\n",
+ pr_debug_ratelimited("sq_intr: inst, se %d, data 0x%x, sa %d, priv %d, wave_id %d, simd_id %d, wgp_id %d\n",
REG_GET_FIELD(context_id1, SQ_INTERRUPT_WORD_WAVE_CTXID1,
SE_ID),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0,
@@ -310,7 +310,7 @@ static void event_interrupt_wq_v10(struct kfd_node *dev,
case SQ_INTERRUPT_WORD_ENCODING_ERROR:
sq_intr_err_type = REG_GET_FIELD(context_id0, KFD_CTXID0,
ERR_TYPE);
- pr_warn("sq_intr: error, se %d, data 0x%x, sa %d, priv %d, wave_id %d, simd_id %d, wgp_id %d, err_type %d\n",
+ pr_warn_ratelimited("sq_intr: error, se %d, data 0x%x, sa %d, priv %d, wave_id %d, simd_id %d, wgp_id %d, err_type %d\n",
REG_GET_FIELD(context_id1, SQ_INTERRUPT_WORD_WAVE_CTXID1,
SE_ID),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
index f933bd231fb9..2a65792fd116 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
@@ -150,7 +150,7 @@ enum SQ_INTERRUPT_ERROR_TYPE {
static void print_sq_intr_info_auto(uint32_t context_id0, uint32_t context_id1)
{
- pr_debug(
+ pr_debug_ratelimited(
"sq_intr: auto, ttrace %d, wlt %d, ttrace_buf_full %d, reg_tms %d, cmd_tms %d, host_cmd_ovf %d, host_reg_ovf %d, immed_ovf %d, ttrace_utc_err %d\n",
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0, THREAD_TRACE),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0, WLT),
@@ -165,7 +165,7 @@ static void print_sq_intr_info_auto(uint32_t context_id0, uint32_t context_id1)
static void print_sq_intr_info_inst(uint32_t context_id0, uint32_t context_id1)
{
- pr_debug(
+ pr_debug_ratelimited(
"sq_intr: inst, data 0x%08x, sh %d, priv %d, wave_id %d, simd_id %d, wgp_id %d\n",
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0, DATA),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0, SH_ID),
@@ -177,7 +177,7 @@ static void print_sq_intr_info_inst(uint32_t context_id0, uint32_t context_id1)
static void print_sq_intr_info_error(uint32_t context_id0, uint32_t context_id1)
{
- pr_warn(
+ pr_warn_ratelimited(
"sq_intr: error, detail 0x%08x, type %d, sh %d, priv %d, wave_id %d, simd_id %d, wgp_id %d\n",
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_ERROR_CTXID0, DETAIL),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_ERROR_CTXID0, TYPE),
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
index 830396b1c3b1..27cdaea40501 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
@@ -333,7 +333,7 @@ static void event_interrupt_wq_v9(struct kfd_node *dev,
encoding = REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID, ENCODING);
switch (encoding) {
case SQ_INTERRUPT_WORD_ENCODING_AUTO:
- pr_debug(
+ pr_debug_ratelimited(
"sq_intr: auto, se %d, ttrace %d, wlt %d, ttrac_buf_full %d, reg_tms %d, cmd_tms %d, host_cmd_ovf %d, host_reg_ovf %d, immed_ovf %d, ttrace_utc_err %d\n",
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID, SE_ID),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID, THREAD_TRACE),
@@ -347,7 +347,7 @@ static void event_interrupt_wq_v9(struct kfd_node *dev,
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID, THREAD_TRACE_UTC_ERROR));
break;
case SQ_INTERRUPT_WORD_ENCODING_INST:
- pr_debug("sq_intr: inst, se %d, data 0x%x, sh %d, priv %d, wave_id %d, simd_id %d, cu_id %d, intr_data 0x%x\n",
+ pr_debug_ratelimited("sq_intr: inst, se %d, data 0x%x, sh %d, priv %d, wave_id %d, simd_id %d, cu_id %d, intr_data 0x%x\n",
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID, SE_ID),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID, DATA),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID, SH_ID),
@@ -366,7 +366,7 @@ static void event_interrupt_wq_v9(struct kfd_node *dev,
break;
case SQ_INTERRUPT_WORD_ENCODING_ERROR:
sq_intr_err = REG_GET_FIELD(sq_int_data, KFD_SQ_INT_DATA, ERR_TYPE);
- pr_warn("sq_intr: error, se %d, data 0x%x, sh %d, priv %d, wave_id %d, simd_id %d, cu_id %d, err_type %d\n",
+ pr_warn_ratelimited("sq_intr: error, se %d, data 0x%x, sh %d, priv %d, wave_id %d, simd_id %d, cu_id %d, err_type %d\n",
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID, SE_ID),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID, DATA),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID, SH_ID),
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 7d82c7da223a..6c25dab051d5 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -460,7 +460,7 @@ svm_migrate_vma_to_vram(struct kfd_node *node, struct svm_range *prange,
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
0, node->id, trigger);
- svm_range_dma_unmap(adev->dev, scratch, 0, npages);
+ svm_range_dma_unmap_dev(adev->dev, scratch, 0, npages);
out_free:
kvfree(buf);
@@ -544,7 +544,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
if (cpages) {
prange->actual_loc = best_loc;
- svm_range_free_dma_mappings(prange, true);
+ svm_range_dma_unmap(prange);
} else {
svm_range_vram_node_free(prange);
}
@@ -745,7 +745,7 @@ svm_migrate_vma_to_ram(struct kfd_node *node, struct svm_range *prange,
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
node->id, 0, trigger);
- svm_range_dma_unmap(adev->dev, scratch, 0, npages);
+ svm_range_dma_unmap_dev(adev->dev, scratch, 0, npages);
out_free:
kvfree(buf);
@@ -1001,7 +1001,7 @@ int kgd2kfd_init_zone_device(struct amdgpu_device *adev)
void *r;
/* Page migration works on gfx9 or newer */
- if (adev->ip_versions[GC_HWIP][0] < IP_VERSION(9, 0, 1))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(9, 0, 1))
return -EINVAL;
if (adev->gmc.is_app_apu)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
index 447829c22295..050a6936ff84 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
@@ -99,7 +99,8 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm,
const uint32_t *cu_mask, uint32_t cu_mask_count,
uint32_t *se_mask, uint32_t inst)
{
- struct kfd_cu_info cu_info;
+ struct amdgpu_cu_info *cu_info = &mm->dev->adev->gfx.cu_info;
+ struct amdgpu_gfx_config *gfx_info = &mm->dev->adev->gfx.config;
uint32_t cu_per_sh[KFD_MAX_NUM_SE][KFD_MAX_NUM_SH_PER_SE] = {0};
bool wgp_mode_req = KFD_GC_VERSION(mm->dev) >= IP_VERSION(10, 0, 0);
uint32_t en_mask = wgp_mode_req ? 0x3 : 0x1;
@@ -108,9 +109,7 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm,
int inc = cu_inc * NUM_XCC(mm->dev->xcc_mask);
int xcc_inst = inst + ffs(mm->dev->xcc_mask) - 1;
- amdgpu_amdkfd_get_cu_info(mm->dev->adev, &cu_info);
-
- cu_active_per_node = cu_info.cu_active_number / mm->dev->kfd->num_nodes;
+ cu_active_per_node = cu_info->number / mm->dev->kfd->num_nodes;
if (cu_mask_count > cu_active_per_node)
cu_mask_count = cu_active_per_node;
@@ -118,13 +117,14 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm,
* Returning with no CU's enabled will hang the queue, which should be
* attention grabbing.
*/
- if (cu_info.num_shader_engines > KFD_MAX_NUM_SE) {
- pr_err("Exceeded KFD_MAX_NUM_SE, chip reports %d\n", cu_info.num_shader_engines);
+ if (gfx_info->max_shader_engines > KFD_MAX_NUM_SE) {
+ pr_err("Exceeded KFD_MAX_NUM_SE, chip reports %d\n",
+ gfx_info->max_shader_engines);
return;
}
- if (cu_info.num_shader_arrays_per_engine > KFD_MAX_NUM_SH_PER_SE) {
+ if (gfx_info->max_sh_per_se > KFD_MAX_NUM_SH_PER_SE) {
pr_err("Exceeded KFD_MAX_NUM_SH, chip reports %d\n",
- cu_info.num_shader_arrays_per_engine * cu_info.num_shader_engines);
+ gfx_info->max_sh_per_se * gfx_info->max_shader_engines);
return;
}
@@ -142,10 +142,10 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm,
* See note on Arcturus cu_bitmap layout in gfx_v9_0_get_cu_info.
* See note on GFX11 cu_bitmap layout in gfx_v11_0_get_cu_info.
*/
- for (se = 0; se < cu_info.num_shader_engines; se++)
- for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++)
+ for (se = 0; se < gfx_info->max_shader_engines; se++)
+ for (sh = 0; sh < gfx_info->max_sh_per_se; sh++)
cu_per_sh[se][sh] = hweight32(
- cu_info.cu_bitmap[xcc_inst][se % 4][sh + (se / 4) *
+ cu_info->bitmap[xcc_inst][se % 4][sh + (se / 4) *
cu_bitmap_sh_mul]);
/* Symmetrically map cu_mask to all SEs & SHs:
@@ -184,13 +184,13 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm,
*
* First ensure all CUs are disabled, then enable user specified CUs.
*/
- for (i = 0; i < cu_info.num_shader_engines; i++)
+ for (i = 0; i < gfx_info->max_shader_engines; i++)
se_mask[i] = 0;
i = inst;
for (cu = 0; cu < 16; cu += cu_inc) {
- for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++) {
- for (se = 0; se < cu_info.num_shader_engines; se++) {
+ for (sh = 0; sh < gfx_info->max_sh_per_se; sh++) {
+ for (se = 0; se < gfx_info->max_shader_engines; se++) {
if (cu_per_sh[se][sh] > cu) {
if (cu_mask[i / 32] & (en_mask << (i % 32)))
se_mask[se] |= en_mask << (cu + sh * 16);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c
index 1a03173e2313..8ee2bedd301a 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c
@@ -205,7 +205,8 @@ static int pm_set_resources_v9(struct packet_manager *pm, uint32_t *buffer,
static inline bool pm_use_ext_eng(struct kfd_dev *dev)
{
- return dev->adev->ip_versions[SDMA0_HWIP][0] >= IP_VERSION(5, 2, 0);
+ return amdgpu_ip_version(dev->adev, SDMA0_HWIP, 0) >=
+ IP_VERSION(5, 2, 0);
}
static int pm_map_queues_v9(struct packet_manager *pm, uint32_t *buffer,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index fa24e1852493..4c8e278a0d0c 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -202,7 +202,7 @@ enum cache_policy {
cache_policy_noncoherent
};
-#define KFD_GC_VERSION(dev) ((dev)->adev->ip_versions[GC_HWIP][0])
+#define KFD_GC_VERSION(dev) (amdgpu_ip_version((dev)->adev, GC_HWIP, 0))
#define KFD_IS_SOC15(dev) ((KFD_GC_VERSION(dev)) >= (IP_VERSION(9, 0, 1)))
#define KFD_SUPPORT_XNACK_PER_PROCESS(dev)\
((KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 2)) || \
@@ -1128,7 +1128,7 @@ static inline struct kfd_node *kfd_node_by_irq_ids(struct amdgpu_device *adev,
struct kfd_dev *dev = adev->kfd.dev;
uint32_t i;
- if (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 3))
+ if (KFD_GC_VERSION(dev) != IP_VERSION(9, 4, 3))
return dev->nodes[0];
for (i = 0; i < dev->num_nodes; i++)
@@ -1343,7 +1343,7 @@ int pqm_get_queue_snapshot(struct process_queue_manager *pqm,
int *num_qss_entries,
uint32_t *entry_size);
-int amdkfd_fence_wait_timeout(uint64_t *fence_addr,
+int amdkfd_fence_wait_timeout(struct device_queue_manager *dqm,
uint64_t fence_value,
unsigned int timeout_ms);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index fbf053001af9..7a33e06f5c90 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -1416,8 +1416,13 @@ bool kfd_process_xnack_mode(struct kfd_process *p, bool supported)
* per-process XNACK mode selection. But let the dev->noretry
* setting still influence the default XNACK mode.
*/
- if (supported && KFD_SUPPORT_XNACK_PER_PROCESS(dev))
+ if (supported && KFD_SUPPORT_XNACK_PER_PROCESS(dev)) {
+ if (!amdgpu_sriov_xnack_support(dev->kfd->adev)) {
+ pr_debug("SRIOV platform xnack not supported\n");
+ return false;
+ }
continue;
+ }
/* GFXv10 and later GPUs do not support shader preemption
* during page faults. This can lead to poor QoS for queue
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
index adb5e4bdc0b2..77f493262e05 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
@@ -169,16 +169,43 @@ int pqm_init(struct process_queue_manager *pqm, struct kfd_process *p)
return 0;
}
+static void pqm_clean_queue_resource(struct process_queue_manager *pqm,
+ struct process_queue_node *pqn)
+{
+ struct kfd_node *dev;
+ struct kfd_process_device *pdd;
+
+ dev = pqn->q->device;
+
+ pdd = kfd_get_process_device_data(dev, pqm->process);
+ if (!pdd) {
+ pr_err("Process device data doesn't exist\n");
+ return;
+ }
+
+ if (pqn->q->gws) {
+ if (KFD_GC_VERSION(pqn->q->device) != IP_VERSION(9, 4, 3) &&
+ !dev->kfd->shared_resources.enable_mes)
+ amdgpu_amdkfd_remove_gws_from_process(
+ pqm->process->kgd_process_info, pqn->q->gws);
+ pdd->qpd.num_gws = 0;
+ }
+
+ if (dev->kfd->shared_resources.enable_mes) {
+ amdgpu_amdkfd_free_gtt_mem(dev->adev, pqn->q->gang_ctx_bo);
+ if (pqn->q->wptr_bo)
+ amdgpu_amdkfd_free_gtt_mem(dev->adev, pqn->q->wptr_bo);
+ }
+}
+
void pqm_uninit(struct process_queue_manager *pqm)
{
struct process_queue_node *pqn, *next;
list_for_each_entry_safe(pqn, next, &pqm->queues, process_queue_list) {
- if (pqn->q && pqn->q->gws &&
- KFD_GC_VERSION(pqn->q->device) != IP_VERSION(9, 4, 3) &&
- !pqn->q->device->kfd->shared_resources.enable_mes)
- amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info,
- pqn->q->gws);
+ if (pqn->q)
+ pqm_clean_queue_resource(pqm, pqn);
+
kfd_procfs_del_queue(pqn->q);
uninit_queue(pqn->q);
list_del(&pqn->process_queue_list);
@@ -377,7 +404,8 @@ int pqm_create_queue(struct process_queue_manager *pqm,
*/
uint32_t first_db_index = amdgpu_doorbell_index_on_bar(pdd->dev->adev,
pdd->qpd.proc_doorbells,
- 0);
+ 0,
+ pdd->dev->kfd->device_info.doorbell_size);
*p_doorbell_offset_in_process = (q->properties.doorbell_off
- first_db_index) * sizeof(uint32_t);
@@ -460,22 +488,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid)
goto err_destroy_queue;
}
- if (pqn->q->gws) {
- if (KFD_GC_VERSION(pqn->q->device) != IP_VERSION(9, 4, 3) &&
- !dev->kfd->shared_resources.enable_mes)
- amdgpu_amdkfd_remove_gws_from_process(
- pqm->process->kgd_process_info,
- pqn->q->gws);
- pdd->qpd.num_gws = 0;
- }
-
- if (dev->kfd->shared_resources.enable_mes) {
- amdgpu_amdkfd_free_gtt_mem(dev->adev,
- pqn->q->gang_ctx_bo);
- if (pqn->q->wptr_bo)
- amdgpu_amdkfd_free_gtt_mem(dev->adev, pqn->q->wptr_bo);
-
- }
+ pqm_clean_queue_resource(pqm, pqn);
uninit_queue(pqn->q);
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index bb16b795d1bc..f2f3c338fd94 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -231,7 +231,7 @@ svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap,
return r;
}
-void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr,
+void svm_range_dma_unmap_dev(struct device *dev, dma_addr_t *dma_addr,
unsigned long offset, unsigned long npages)
{
enum dma_data_direction dir = DMA_BIDIRECTIONAL;
@@ -249,7 +249,7 @@ void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr,
}
}
-void svm_range_free_dma_mappings(struct svm_range *prange, bool unmap_dma)
+void svm_range_dma_unmap(struct svm_range *prange)
{
struct kfd_process_device *pdd;
dma_addr_t *dma_addr;
@@ -270,10 +270,8 @@ void svm_range_free_dma_mappings(struct svm_range *prange, bool unmap_dma)
continue;
}
dev = &pdd->dev->adev->pdev->dev;
- if (unmap_dma)
- svm_range_dma_unmap(dev, dma_addr, 0, prange->npages);
- kvfree(dma_addr);
- prange->dma_addr[gpuidx] = NULL;
+
+ svm_range_dma_unmap_dev(dev, dma_addr, 0, prange->npages);
}
}
@@ -281,18 +279,29 @@ static void svm_range_free(struct svm_range *prange, bool do_unmap)
{
uint64_t size = (prange->last - prange->start + 1) << PAGE_SHIFT;
struct kfd_process *p = container_of(prange->svms, struct kfd_process, svms);
+ uint32_t gpuidx;
pr_debug("svms 0x%p prange 0x%p [0x%lx 0x%lx]\n", prange->svms, prange,
prange->start, prange->last);
svm_range_vram_node_free(prange);
- svm_range_free_dma_mappings(prange, do_unmap);
+ if (do_unmap)
+ svm_range_dma_unmap(prange);
if (do_unmap && !p->xnack_enabled) {
pr_debug("unreserve prange 0x%p size: 0x%llx\n", prange, size);
amdgpu_amdkfd_unreserve_mem_limit(NULL, size,
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR, 0);
}
+
+ /* free dma_addr array for each gpu */
+ for (gpuidx = 0; gpuidx < MAX_GPU_INSTANCE; gpuidx++) {
+ if (prange->dma_addr[gpuidx]) {
+ kvfree(prange->dma_addr[gpuidx]);
+ prange->dma_addr[gpuidx] = NULL;
+ }
+ }
+
mutex_destroy(&prange->lock);
mutex_destroy(&prange->migrate_mutex);
kfree(prange);
@@ -495,11 +504,11 @@ svm_range_validate_svm_bo(struct kfd_node *node, struct svm_range *prange)
/* We need a new svm_bo. Spin-loop to wait for concurrent
* svm_range_bo_release to finish removing this range from
- * its range list. After this, it is safe to reuse the
- * svm_bo pointer and svm_bo_list head.
+ * its range list and set prange->svm_bo to null. After this,
+ * it is safe to reuse the svm_bo pointer and svm_bo_list head.
*/
- while (!list_empty_careful(&prange->svm_bo_list))
- ;
+ while (!list_empty_careful(&prange->svm_bo_list) || prange->svm_bo)
+ cond_resched();
return false;
}
@@ -628,8 +637,15 @@ create_bo_failed:
void svm_range_vram_node_free(struct svm_range *prange)
{
- svm_range_bo_unref(prange->svm_bo);
- prange->ttm_res = NULL;
+ /* serialize prange->svm_bo unref */
+ mutex_lock(&prange->lock);
+ /* prange->svm_bo has not been unref */
+ if (prange->ttm_res) {
+ prange->ttm_res = NULL;
+ mutex_unlock(&prange->lock);
+ svm_range_bo_unref(prange->svm_bo);
+ } else
+ mutex_unlock(&prange->lock);
}
struct kfd_node *
@@ -760,7 +776,7 @@ svm_range_apply_attrs(struct kfd_process *p, struct svm_range *prange,
prange->flags &= ~attrs[i].value;
break;
case KFD_IOCTL_SVM_ATTR_GRANULARITY:
- prange->granularity = attrs[i].value;
+ prange->granularity = min_t(uint32_t, attrs[i].value, 0x3F);
break;
default:
WARN_ONCE(1, "svm_range_check_attrs wasn't called?");
@@ -820,7 +836,7 @@ svm_range_is_same_attrs(struct kfd_process *p, struct svm_range *prange,
}
}
- return !prange->is_error_flag;
+ return true;
}
/**
@@ -1078,26 +1094,32 @@ svm_range_split(struct svm_range *prange, uint64_t start, uint64_t last,
}
static int
-svm_range_split_tail(struct svm_range *prange,
- uint64_t new_last, struct list_head *insert_list)
+svm_range_split_tail(struct svm_range *prange, uint64_t new_last,
+ struct list_head *insert_list, struct list_head *remap_list)
{
struct svm_range *tail;
int r = svm_range_split(prange, prange->start, new_last, &tail);
- if (!r)
+ if (!r) {
list_add(&tail->list, insert_list);
+ if (!IS_ALIGNED(new_last + 1, 1UL << prange->granularity))
+ list_add(&tail->update_list, remap_list);
+ }
return r;
}
static int
-svm_range_split_head(struct svm_range *prange,
- uint64_t new_start, struct list_head *insert_list)
+svm_range_split_head(struct svm_range *prange, uint64_t new_start,
+ struct list_head *insert_list, struct list_head *remap_list)
{
struct svm_range *head;
int r = svm_range_split(prange, new_start, prange->last, &head);
- if (!r)
+ if (!r) {
list_add(&head->list, insert_list);
+ if (!IS_ALIGNED(new_start, 1UL << prange->granularity))
+ list_add(&head->update_list, remap_list);
+ }
return r;
}
@@ -1189,14 +1211,15 @@ svm_range_get_pte_flags(struct kfd_node *node,
uint32_t mapping_flags = 0;
uint64_t pte_flags;
bool snoop = (domain != SVM_RANGE_VRAM_DOMAIN);
- bool coherent = flags & KFD_IOCTL_SVM_FLAG_COHERENT;
+ bool coherent = flags & (KFD_IOCTL_SVM_FLAG_COHERENT | KFD_IOCTL_SVM_FLAG_EXT_COHERENT);
+ bool ext_coherent = flags & KFD_IOCTL_SVM_FLAG_EXT_COHERENT;
bool uncached = false; /*flags & KFD_IOCTL_SVM_FLAG_UNCACHED;*/
unsigned int mtype_local;
if (domain == SVM_RANGE_VRAM_DOMAIN)
bo_node = prange->svm_bo->node;
- switch (node->adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(node->adev, GC_HWIP, 0)) {
case IP_VERSION(9, 4, 1):
if (domain == SVM_RANGE_VRAM_DOMAIN) {
if (bo_node == node) {
@@ -1232,8 +1255,11 @@ svm_range_get_pte_flags(struct kfd_node *node,
}
break;
case IP_VERSION(9, 4, 3):
- mtype_local = amdgpu_mtype_local == 1 ? AMDGPU_VM_MTYPE_NC :
- (amdgpu_mtype_local == 2 ? AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW);
+ if (ext_coherent)
+ mtype_local = node->adev->rev_id ? AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_UC;
+ else
+ mtype_local = amdgpu_mtype_local == 1 ? AMDGPU_VM_MTYPE_NC :
+ amdgpu_mtype_local == 2 ? AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
snoop = true;
if (uncached) {
mapping_flags |= AMDGPU_VM_MTYPE_UC;
@@ -1242,10 +1268,12 @@ svm_range_get_pte_flags(struct kfd_node *node,
if (bo_node->adev == node->adev &&
(!bo_node->xcp || !node->xcp || bo_node->xcp->mem_id == node->xcp->mem_id))
mapping_flags |= mtype_local;
- /* local HBM region far from partition or remote XGMI GPU */
- else if (svm_nodes_in_same_hive(bo_node, node))
+ /* local HBM region far from partition or remote XGMI GPU
+ * with regular system scope coherence
+ */
+ else if (svm_nodes_in_same_hive(bo_node, node) && !ext_coherent)
mapping_flags |= AMDGPU_VM_MTYPE_NC;
- /* PCIe P2P */
+ /* PCIe P2P or extended system scope coherence */
else
mapping_flags |= AMDGPU_VM_MTYPE_UC;
/* system memory accessed by the APU */
@@ -1256,7 +1284,7 @@ svm_range_get_pte_flags(struct kfd_node *node,
if (num_possible_nodes() <= 1)
mapping_flags |= mtype_local;
else
- mapping_flags |= AMDGPU_VM_MTYPE_NC;
+ mapping_flags |= ext_coherent ? AMDGPU_VM_MTYPE_UC : AMDGPU_VM_MTYPE_NC;
/* system memory accessed by the dGPU */
} else {
mapping_flags |= AMDGPU_VM_MTYPE_UC;
@@ -1291,7 +1319,7 @@ svm_range_unmap_from_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
pr_debug("[0x%llx 0x%llx]\n", start, last);
- return amdgpu_vm_update_range(adev, vm, false, true, true, NULL, start,
+ return amdgpu_vm_update_range(adev, vm, false, true, true, false, NULL, start,
last, init_pte_value, 0, 0, NULL, NULL,
fence);
}
@@ -1398,8 +1426,8 @@ svm_range_map_to_gpu(struct kfd_process_device *pdd, struct svm_range *prange,
* different memory partition based on fpfn/lpfn, we should use
* same vm_manager.vram_base_offset regardless memory partition.
*/
- r = amdgpu_vm_update_range(adev, vm, false, false, flush_tlb, NULL,
- last_start, prange->start + i,
+ r = amdgpu_vm_update_range(adev, vm, false, false, flush_tlb, true,
+ NULL, last_start, prange->start + i,
pte_flags,
(last_start - prange->start) << PAGE_SHIFT,
bo_adev ? bo_adev->vm_manager.vram_base_offset : 0,
@@ -1662,73 +1690,66 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
start = prange->start << PAGE_SHIFT;
end = (prange->last + 1) << PAGE_SHIFT;
- for (addr = start; addr < end && !r; ) {
+ for (addr = start; !r && addr < end; ) {
struct hmm_range *hmm_range;
struct vm_area_struct *vma;
- unsigned long next;
+ unsigned long next = 0;
unsigned long offset;
unsigned long npages;
bool readonly;
vma = vma_lookup(mm, addr);
- if (!vma) {
+ if (vma) {
+ readonly = !(vma->vm_flags & VM_WRITE);
+
+ next = min(vma->vm_end, end);
+ npages = (next - addr) >> PAGE_SHIFT;
+ WRITE_ONCE(p->svms.faulting_task, current);
+ r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
+ readonly, owner, NULL,
+ &hmm_range);
+ WRITE_ONCE(p->svms.faulting_task, NULL);
+ if (r) {
+ pr_debug("failed %d to get svm range pages\n", r);
+ if (r == -EBUSY)
+ r = -EAGAIN;
+ }
+ } else {
r = -EFAULT;
- goto unreserve_out;
- }
- readonly = !(vma->vm_flags & VM_WRITE);
-
- next = min(vma->vm_end, end);
- npages = (next - addr) >> PAGE_SHIFT;
- WRITE_ONCE(p->svms.faulting_task, current);
- r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
- readonly, owner, NULL,
- &hmm_range);
- WRITE_ONCE(p->svms.faulting_task, NULL);
- if (r) {
- pr_debug("failed %d to get svm range pages\n", r);
- if (r == -EBUSY)
- r = -EAGAIN;
- goto unreserve_out;
}
- offset = (addr - start) >> PAGE_SHIFT;
- r = svm_range_dma_map(prange, ctx->bitmap, offset, npages,
- hmm_range->hmm_pfns);
- if (r) {
- pr_debug("failed %d to dma map range\n", r);
- goto unreserve_out;
+ if (!r) {
+ offset = (addr - start) >> PAGE_SHIFT;
+ r = svm_range_dma_map(prange, ctx->bitmap, offset, npages,
+ hmm_range->hmm_pfns);
+ if (r)
+ pr_debug("failed %d to dma map range\n", r);
}
svm_range_lock(prange);
- if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
+ if (!r && amdgpu_hmm_range_get_pages_done(hmm_range)) {
pr_debug("hmm update the range, need validate again\n");
r = -EAGAIN;
- goto unlock_out;
}
- if (!list_empty(&prange->child_list)) {
+
+ if (!r && !list_empty(&prange->child_list)) {
pr_debug("range split by unmap in parallel, validate again\n");
r = -EAGAIN;
- goto unlock_out;
}
- r = svm_range_map_to_gpus(prange, offset, npages, readonly,
- ctx->bitmap, wait, flush_tlb);
+ if (!r)
+ r = svm_range_map_to_gpus(prange, offset, npages, readonly,
+ ctx->bitmap, wait, flush_tlb);
+
+ if (!r && next == end)
+ prange->mapped_to_gpu = true;
-unlock_out:
svm_range_unlock(prange);
addr = next;
}
- if (addr == end) {
- prange->validated_once = true;
- prange->mapped_to_gpu = true;
- }
-
-unreserve_out:
svm_range_unreserve_bos(ctx);
-
- prange->is_error_flag = !!r;
if (!r)
prange->validate_timestamp = ktime_get_boottime();
@@ -2045,6 +2066,7 @@ svm_range_split_new(struct svm_range_list *svms, uint64_t start, uint64_t last,
* @update_list: output, the ranges need validate and update GPU mapping
* @insert_list: output, the ranges need insert to svms
* @remove_list: output, the ranges are replaced and need remove from svms
+ * @remap_list: output, remap unaligned svm ranges
*
* Check if the virtual address range has overlap with any existing ranges,
* split partly overlapping ranges and add new ranges in the gaps. All changes
@@ -2068,7 +2090,7 @@ static int
svm_range_add(struct kfd_process *p, uint64_t start, uint64_t size,
uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs,
struct list_head *update_list, struct list_head *insert_list,
- struct list_head *remove_list)
+ struct list_head *remove_list, struct list_head *remap_list)
{
unsigned long last = start + size - 1UL;
struct svm_range_list *svms = &p->svms;
@@ -2084,6 +2106,7 @@ svm_range_add(struct kfd_process *p, uint64_t start, uint64_t size,
INIT_LIST_HEAD(insert_list);
INIT_LIST_HEAD(remove_list);
INIT_LIST_HEAD(&new_list);
+ INIT_LIST_HEAD(remap_list);
node = interval_tree_iter_first(&svms->objects, start, last);
while (node) {
@@ -2097,7 +2120,8 @@ svm_range_add(struct kfd_process *p, uint64_t start, uint64_t size,
next = interval_tree_iter_next(node, start, last);
next_start = min(node->last, last) + 1;
- if (svm_range_is_same_attrs(p, prange, nattr, attrs)) {
+ if (svm_range_is_same_attrs(p, prange, nattr, attrs) &&
+ prange->mapped_to_gpu) {
/* nothing to do */
} else if (node->start < start || node->last > last) {
/* node intersects the update range and its attributes
@@ -2119,14 +2143,14 @@ svm_range_add(struct kfd_process *p, uint64_t start, uint64_t size,
if (node->start < start) {
pr_debug("change old range start\n");
r = svm_range_split_head(prange, start,
- insert_list);
+ insert_list, remap_list);
if (r)
goto out;
}
if (node->last > last) {
pr_debug("change old range last\n");
r = svm_range_split_tail(prange, last,
- insert_list);
+ insert_list, remap_list);
if (r)
goto out;
}
@@ -3502,12 +3526,13 @@ svm_range_set_attr(struct kfd_process *p, struct mm_struct *mm,
struct list_head update_list;
struct list_head insert_list;
struct list_head remove_list;
+ struct list_head remap_list;
struct svm_range_list *svms;
struct svm_range *prange;
struct svm_range *next;
bool update_mapping = false;
bool flush_tlb;
- int r = 0;
+ int r, ret = 0;
pr_debug("pasid 0x%x svms 0x%p [0x%llx 0x%llx] pages 0x%llx\n",
p->pasid, &p->svms, start, start + size - 1, size);
@@ -3533,7 +3558,7 @@ svm_range_set_attr(struct kfd_process *p, struct mm_struct *mm,
/* Add new range and split existing ranges as needed */
r = svm_range_add(p, start, size, nattr, attrs, &update_list,
- &insert_list, &remove_list);
+ &insert_list, &remove_list, &remap_list);
if (r) {
mutex_unlock(&svms->lock);
mmap_write_unlock(mm);
@@ -3595,7 +3620,20 @@ svm_range_set_attr(struct kfd_process *p, struct mm_struct *mm,
out_unlock_range:
mutex_unlock(&prange->migrate_mutex);
if (r)
- break;
+ ret = r;
+ }
+
+ list_for_each_entry(prange, &remap_list, update_list) {
+ pr_debug("Remapping prange 0x%p [0x%lx 0x%lx]\n",
+ prange, prange->start, prange->last);
+ mutex_lock(&prange->migrate_mutex);
+ r = svm_range_validate_and_map(mm, prange, MAX_GPU_INSTANCE,
+ true, true, prange->mapped_to_gpu);
+ if (r)
+ pr_debug("failed %d on remap svm range\n", r);
+ mutex_unlock(&prange->migrate_mutex);
+ if (r)
+ ret = r;
}
dynamic_svm_range_dump(svms);
@@ -3608,7 +3646,7 @@ out:
pr_debug("pasid 0x%x svms 0x%p [0x%llx 0x%llx] done, r=%d\n", p->pasid,
&p->svms, start, start + size - 1, r);
- return r;
+ return ret ? ret : r;
}
static int
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index 9e668eeefb32..c528df1d0ba2 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -132,9 +132,7 @@ struct svm_range {
struct list_head child_list;
DECLARE_BITMAP(bitmap_access, MAX_GPU_INSTANCE);
DECLARE_BITMAP(bitmap_aip, MAX_GPU_INSTANCE);
- bool validated_once;
bool mapped_to_gpu;
- bool is_error_flag;
};
static inline void svm_range_lock(struct svm_range *prange)
@@ -181,9 +179,9 @@ void svm_range_add_list_work(struct svm_range_list *svms,
struct svm_range *prange, struct mm_struct *mm,
enum svm_work_list_ops op);
void schedule_deferred_list_work(struct svm_range_list *svms);
-void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr,
+void svm_range_dma_unmap_dev(struct device *dev, dma_addr_t *dma_addr,
unsigned long offset, unsigned long npages);
-void svm_range_free_dma_mappings(struct svm_range *prange, bool unmap_dma);
+void svm_range_dma_unmap(struct svm_range *prange);
int svm_range_get_info(struct kfd_process *p, uint32_t *num_svm_ranges,
uint64_t *svm_priv_data_size);
int kfd_criu_checkpoint_svm(struct kfd_process *p,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index c8c75ff7cea8..057284bf50bb 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -1533,7 +1533,6 @@ out:
/* Helper function. See kfd_fill_gpu_cache_info for parameter description */
static int fill_in_l1_pcache(struct kfd_cache_properties **props_ext,
struct kfd_gpu_cache_info *pcache_info,
- struct kfd_cu_info *cu_info,
int cu_bitmask,
int cache_type, unsigned int cu_processor_id,
int cu_block)
@@ -1595,18 +1594,22 @@ static int fill_in_l1_pcache(struct kfd_cache_properties **props_ext,
/* Helper function. See kfd_fill_gpu_cache_info for parameter description */
static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
struct kfd_gpu_cache_info *pcache_info,
- struct kfd_cu_info *cu_info,
+ struct amdgpu_cu_info *cu_info,
+ struct amdgpu_gfx_config *gfx_info,
int cache_type, unsigned int cu_processor_id,
struct kfd_node *knode)
{
unsigned int cu_sibling_map_mask;
int first_active_cu;
int i, j, k, xcc, start, end;
+ int num_xcc = NUM_XCC(knode->xcc_mask);
struct kfd_cache_properties *pcache = NULL;
+ enum amdgpu_memory_partition mode;
+ struct amdgpu_device *adev = knode->adev;
start = ffs(knode->xcc_mask) - 1;
- end = start + NUM_XCC(knode->xcc_mask);
- cu_sibling_map_mask = cu_info->cu_bitmap[start][0][0];
+ end = start + num_xcc;
+ cu_sibling_map_mask = cu_info->bitmap[start][0][0];
cu_sibling_map_mask &=
((1 << pcache_info[cache_type].num_cu_shared) - 1);
first_active_cu = ffs(cu_sibling_map_mask);
@@ -1624,7 +1627,18 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
pcache->processor_id_low = cu_processor_id
+ (first_active_cu - 1);
pcache->cache_level = pcache_info[cache_type].cache_level;
- pcache->cache_size = pcache_info[cache_type].cache_size;
+
+ if (KFD_GC_VERSION(knode) == IP_VERSION(9, 4, 3))
+ mode = adev->gmc.gmc_funcs->query_mem_partition_mode(adev);
+ else
+ mode = UNKNOWN_MEMORY_PARTITION_MODE;
+
+ if (pcache->cache_level == 2)
+ pcache->cache_size = pcache_info[cache_type].cache_size * num_xcc;
+ else if (mode)
+ pcache->cache_size = pcache_info[cache_type].cache_size / mode;
+ else
+ pcache->cache_size = pcache_info[cache_type].cache_size;
if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_DATA_CACHE)
pcache->cache_type |= HSA_CACHE_TYPE_DATA;
@@ -1642,15 +1656,15 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
k = 0;
for (xcc = start; xcc < end; xcc++) {
- for (i = 0; i < cu_info->num_shader_engines; i++) {
- for (j = 0; j < cu_info->num_shader_arrays_per_engine; j++) {
+ for (i = 0; i < gfx_info->max_shader_engines; i++) {
+ for (j = 0; j < gfx_info->max_sh_per_se; j++) {
pcache->sibling_map[k] = (uint8_t)(cu_sibling_map_mask & 0xFF);
pcache->sibling_map[k+1] = (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF);
pcache->sibling_map[k+2] = (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF);
pcache->sibling_map[k+3] = (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF);
k += 4;
- cu_sibling_map_mask = cu_info->cu_bitmap[xcc][i % 4][j + i / 4];
+ cu_sibling_map_mask = cu_info->bitmap[xcc][i % 4][j + i / 4];
cu_sibling_map_mask &= ((1 << pcache_info[cache_type].num_cu_shared) - 1);
}
}
@@ -1675,16 +1689,14 @@ static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct
unsigned int cu_processor_id;
int ret;
unsigned int num_cu_shared;
- struct kfd_cu_info cu_info;
- struct kfd_cu_info *pcu_info;
+ struct amdgpu_cu_info *cu_info = &kdev->adev->gfx.cu_info;
+ struct amdgpu_gfx_config *gfx_info = &kdev->adev->gfx.config;
int gpu_processor_id;
struct kfd_cache_properties *props_ext;
int num_of_entries = 0;
int num_of_cache_types = 0;
struct kfd_gpu_cache_info cache_info[KFD_MAX_CACHE_TYPES];
- amdgpu_amdkfd_get_cu_info(kdev->adev, &cu_info);
- pcu_info = &cu_info;
gpu_processor_id = dev->node_props.simd_id_base;
@@ -1711,12 +1723,12 @@ static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct
cu_processor_id = gpu_processor_id;
if (pcache_info[ct].cache_level == 1) {
for (xcc = start; xcc < end; xcc++) {
- for (i = 0; i < pcu_info->num_shader_engines; i++) {
- for (j = 0; j < pcu_info->num_shader_arrays_per_engine; j++) {
- for (k = 0; k < pcu_info->num_cu_per_sh; k += pcache_info[ct].num_cu_shared) {
+ for (i = 0; i < gfx_info->max_shader_engines; i++) {
+ for (j = 0; j < gfx_info->max_sh_per_se; j++) {
+ for (k = 0; k < gfx_info->max_cu_per_sh; k += pcache_info[ct].num_cu_shared) {
- ret = fill_in_l1_pcache(&props_ext, pcache_info, pcu_info,
- pcu_info->cu_bitmap[xcc][i % 4][j + i / 4], ct,
+ ret = fill_in_l1_pcache(&props_ext, pcache_info,
+ cu_info->bitmap[xcc][i % 4][j + i / 4], ct,
cu_processor_id, k);
if (ret < 0)
@@ -1729,9 +1741,9 @@ static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct
/* Move to next CU block */
num_cu_shared = ((k + pcache_info[ct].num_cu_shared) <=
- pcu_info->num_cu_per_sh) ?
+ gfx_info->max_cu_per_sh) ?
pcache_info[ct].num_cu_shared :
- (pcu_info->num_cu_per_sh - k);
+ (gfx_info->max_cu_per_sh - k);
cu_processor_id += num_cu_shared;
}
}
@@ -1739,7 +1751,7 @@ static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct
}
} else {
ret = fill_in_l2_l3_pcache(&props_ext, pcache_info,
- pcu_info, ct, cu_processor_id, kdev);
+ cu_info, gfx_info, ct, cu_processor_id, kdev);
if (ret < 0)
break;
@@ -1918,10 +1930,11 @@ int kfd_topology_add_device(struct kfd_node *gpu)
{
uint32_t gpu_id;
struct kfd_topology_device *dev;
- struct kfd_cu_info cu_info;
int res = 0;
int i;
const char *asic_name = amdgpu_asic_name[gpu->adev->asic_type];
+ struct amdgpu_gfx_config *gfx_info = &gpu->adev->gfx.config;
+ struct amdgpu_cu_info *cu_info = &gpu->adev->gfx.cu_info;
gpu_id = kfd_generate_gpu_id(gpu);
if (gpu->xcp && !gpu->xcp->ddev) {
@@ -1959,9 +1972,6 @@ int kfd_topology_add_device(struct kfd_node *gpu)
/* Fill-in additional information that is not available in CRAT but
* needed for the topology
*/
-
- amdgpu_amdkfd_get_cu_info(dev->gpu->adev, &cu_info);
-
for (i = 0; i < KFD_TOPOLOGY_PUBLIC_NAME_SIZE-1; i++) {
dev->node_props.name[i] = __tolower(asic_name[i]);
if (asic_name[i] == '\0')
@@ -1970,7 +1980,7 @@ int kfd_topology_add_device(struct kfd_node *gpu)
dev->node_props.name[i] = '\0';
dev->node_props.simd_arrays_per_engine =
- cu_info.num_shader_arrays_per_engine;
+ gfx_info->max_sh_per_se;
dev->node_props.gfx_target_version =
gpu->kfd->device_info.gfx_target_version;
@@ -2051,7 +2061,7 @@ int kfd_topology_add_device(struct kfd_node *gpu)
*/
if (dev->gpu->adev->asic_type == CHIP_CARRIZO) {
dev->node_props.simd_count =
- cu_info.simd_per_cu * cu_info.cu_active_number;
+ cu_info->simd_per_cu * cu_info->number;
dev->node_props.max_waves_per_simd = 10;
}
@@ -2218,7 +2228,7 @@ static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
if (first_cpu_of_numa_node >= nr_cpu_ids)
return -1;
#ifdef CONFIG_X86_64
- return cpu_data(first_cpu_of_numa_node).apicid;
+ return cpu_data(first_cpu_of_numa_node).topo.apicid;
#else
return first_cpu_of_numa_node;
#endif
diff --git a/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c b/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c
index 353597fc908d..90ddd8371176 100644
--- a/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c
+++ b/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c
@@ -89,9 +89,10 @@ EXPORT_SYMBOL(amdgpu_xcp_drm_dev_alloc);
void amdgpu_xcp_drv_release(void)
{
for (--pdev_num; pdev_num >= 0; --pdev_num) {
- devres_release_group(&xcp_dev[pdev_num]->pdev->dev, NULL);
- platform_device_unregister(xcp_dev[pdev_num]->pdev);
- xcp_dev[pdev_num]->pdev = NULL;
+ struct platform_device *pdev = xcp_dev[pdev_num]->pdev;
+
+ devres_release_group(&pdev->dev, NULL);
+ platform_device_unregister(pdev);
xcp_dev[pdev_num] = NULL;
}
pdev_num = 0;
diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile
index 0d610cb376bb..af17ab8027df 100644
--- a/drivers/gpu/drm/amd/display/Makefile
+++ b/drivers/gpu/drm/amd/display/Makefile
@@ -29,6 +29,7 @@ AMDDALPATH = $(RELATIVE_AMD_DISPLAY_PATH)
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/hw
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/clk_mgr
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/hwss
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 868946dd7ef1..c8c00c2a5224 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -142,6 +142,9 @@ MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
#define FIRMWARE_NAVI12_DMCU "amdgpu/navi12_dmcu.bin"
MODULE_FIRMWARE(FIRMWARE_NAVI12_DMCU);
+#define FIRMWARE_DCN_35_DMUB "amdgpu/dcn_3_5_dmcub.bin"
+MODULE_FIRMWARE(FIRMWARE_DCN_35_DMUB);
+
/* Number of bytes in PSP header for firmware. */
#define PSP_HEADER_BYTES 0x100
@@ -410,6 +413,7 @@ static void dm_pflip_high_irq(void *interrupt_params)
struct amdgpu_crtc *amdgpu_crtc;
struct common_irq_params *irq_params = interrupt_params;
struct amdgpu_device *adev = irq_params->adev;
+ struct drm_device *dev = adev_to_drm(adev);
unsigned long flags;
struct drm_pending_vblank_event *e;
u32 vpos, hpos, v_blank_start, v_blank_end;
@@ -420,18 +424,17 @@ static void dm_pflip_high_irq(void *interrupt_params)
/* IRQ could occur when in initial stage */
/* TODO work and BO cleanup */
if (amdgpu_crtc == NULL) {
- DC_LOG_PFLIP("CRTC is null, returning.\n");
+ drm_dbg_state(dev, "CRTC is null, returning.\n");
return;
}
spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
- DC_LOG_PFLIP("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p]\n",
- amdgpu_crtc->pflip_status,
- AMDGPU_FLIP_SUBMITTED,
- amdgpu_crtc->crtc_id,
- amdgpu_crtc);
+ drm_dbg_state(dev,
+ "amdgpu_crtc->pflip_status = %d != AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p]\n",
+ amdgpu_crtc->pflip_status, AMDGPU_FLIP_SUBMITTED,
+ amdgpu_crtc->crtc_id, amdgpu_crtc);
spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
return;
}
@@ -497,9 +500,9 @@ static void dm_pflip_high_irq(void *interrupt_params)
amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
- DC_LOG_PFLIP("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_NONE, vrr[%d]-fp %d\n",
- amdgpu_crtc->crtc_id, amdgpu_crtc,
- vrr_active, (int) !e);
+ drm_dbg_state(dev,
+ "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_NONE, vrr[%d]-fp %d\n",
+ amdgpu_crtc->crtc_id, amdgpu_crtc, vrr_active, (int)!e);
}
static void dm_vupdate_high_irq(void *interrupt_params)
@@ -529,9 +532,9 @@ static void dm_vupdate_high_irq(void *interrupt_params)
atomic64_set(&irq_params->previous_timestamp, vblank->time);
}
- DC_LOG_VBLANK("crtc:%d, vupdate-vrr:%d\n",
- acrtc->crtc_id,
- vrr_active);
+ drm_dbg_vbl(drm_dev,
+ "crtc:%d, vupdate-vrr:%d\n", acrtc->crtc_id,
+ vrr_active);
/* Core vblank handling is done here after end of front-porch in
* vrr mode, as vblank timestamping will give valid results
@@ -582,8 +585,9 @@ static void dm_crtc_high_irq(void *interrupt_params)
vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
- DC_LOG_VBLANK("crtc:%d, vupdate-vrr:%d, planes:%d\n", acrtc->crtc_id,
- vrr_active, acrtc->dm_irq_params.active_planes);
+ drm_dbg_vbl(adev_to_drm(adev),
+ "crtc:%d, vupdate-vrr:%d, planes:%d\n", acrtc->crtc_id,
+ vrr_active, acrtc->dm_irq_params.active_planes);
/**
* Core vblank handling at start of front-porch is only possible
@@ -1069,6 +1073,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
const struct firmware *dmub_fw = adev->dm.dmub_fw;
struct dmcu *dmcu = adev->dm.dc->res_pool->dmcu;
struct abm *abm = adev->dm.dc->res_pool->abm;
+ struct dc_context *ctx = adev->dm.dc->ctx;
struct dmub_srv_hw_params hw_params;
enum dmub_status status;
const unsigned char *fw_inst_const, *fw_bss_data;
@@ -1090,6 +1095,10 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
return -EINVAL;
}
+ /* initialize register offsets for ASICs with runtime initialization available */
+ if (dmub_srv->hw_funcs.init_reg_offsets)
+ dmub_srv->hw_funcs.init_reg_offsets(dmub_srv, ctx);
+
status = dmub_srv_has_hw_support(dmub_srv, &has_hw_support);
if (status != DMUB_STATUS_OK) {
DRM_ERROR("Error checking HW support for DMUB: %d\n", status);
@@ -1165,9 +1174,10 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
for (i = 0; i < fb_info->num_fb; ++i)
hw_params.fb[i] = &fb_info->fb[i];
- switch (adev->ip_versions[DCE_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(3, 1, 3):
case IP_VERSION(3, 1, 4):
+ case IP_VERSION(3, 5, 0):
hw_params.dpia_supported = true;
hw_params.disable_dpia = adev->dm.dc->debug.dpia_debug.bits.disable_dpia;
break;
@@ -1246,7 +1256,7 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
agp_top = adev->gmc.agp_end >> 24;
/* AGP aperture is disabled */
- if (agp_bot == agp_top) {
+ if (agp_bot > agp_top) {
logical_addr_low = adev->gmc.fb_start >> 18;
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
/*
@@ -1597,7 +1607,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
init_data.dce_environment = DCE_ENV_PRODUCTION_DRV;
- switch (adev->ip_versions[DCE_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(2, 1, 0):
switch (adev->dm.dmcub_fw_version) {
case 0: /* development */
@@ -1616,40 +1626,23 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
break;
}
- switch (adev->asic_type) {
- case CHIP_CARRIZO:
- case CHIP_STONEY:
- init_data.flags.gpu_vm_support = true;
- break;
- default:
- switch (adev->ip_versions[DCE_HWIP][0]) {
- case IP_VERSION(1, 0, 0):
- case IP_VERSION(1, 0, 1):
- /* enable S/G on PCO and RV2 */
- if ((adev->apu_flags & AMD_APU_IS_RAVEN2) ||
- (adev->apu_flags & AMD_APU_IS_PICASSO))
- init_data.flags.gpu_vm_support = true;
- break;
- case IP_VERSION(2, 1, 0):
- case IP_VERSION(3, 0, 1):
- case IP_VERSION(3, 1, 2):
- case IP_VERSION(3, 1, 3):
- case IP_VERSION(3, 1, 4):
- case IP_VERSION(3, 1, 5):
- case IP_VERSION(3, 1, 6):
- init_data.flags.gpu_vm_support = true;
- break;
- default:
- break;
- }
- break;
- }
- if (init_data.flags.gpu_vm_support &&
- (amdgpu_sg_display == 0))
+ /* APU support S/G display by default except:
+ * ASICs before Carrizo,
+ * RAVEN1 (Users reported stability issue)
+ */
+
+ if (adev->asic_type < CHIP_CARRIZO) {
init_data.flags.gpu_vm_support = false;
+ } else if (adev->asic_type == CHIP_RAVEN) {
+ if (adev->apu_flags & AMD_APU_IS_RAVEN)
+ init_data.flags.gpu_vm_support = false;
+ else
+ init_data.flags.gpu_vm_support = (amdgpu_sg_display != 0);
+ } else {
+ init_data.flags.gpu_vm_support = (amdgpu_sg_display != 0) && (adev->flags & AMD_IS_APU);
+ }
- if (init_data.flags.gpu_vm_support)
- adev->mode_info.gpu_vm_support = true;
+ adev->mode_info.gpu_vm_support = init_data.flags.gpu_vm_support;
if (amdgpu_dc_feature_mask & DC_FBC_MASK)
init_data.flags.fbc_support = true;
@@ -1670,7 +1663,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
init_data.flags.seamless_boot_edp_requested = false;
- if (check_seamless_boot_capability(adev)) {
+ if (amdgpu_device_seamless_boot_supported(adev)) {
init_data.flags.seamless_boot_edp_requested = true;
init_data.flags.allow_seamless_boot_optimization = true;
DRM_INFO("Seamless boot condition check passed\n");
@@ -1680,6 +1673,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
init_data.dcn_reg_offsets = adev->reg_offset[DCE_HWIP][0];
init_data.nbio_reg_offsets = adev->reg_offset[NBIO_HWIP][0];
+ init_data.clk_reg_offsets = adev->reg_offset[CLK_HWIP][0];
INIT_LIST_HEAD(&adev->dm.da_list);
@@ -1692,8 +1686,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
DRM_INFO("Display Core v%s initialized on %s\n", DC_VER,
dce_version_to_string(adev->dm.dc->ctx->dce_version));
} else {
- DRM_INFO("Display Core v%s failed to initialize on %s\n", DC_VER,
- dce_version_to_string(adev->dm.dc->ctx->dce_version));
+ DRM_INFO("Display Core failed to initialize with v%s!\n", DC_VER);
goto error;
}
@@ -2004,7 +1997,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
return 0;
break;
default:
- switch (adev->ip_versions[DCE_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(2, 0, 2):
case IP_VERSION(2, 0, 3):
case IP_VERSION(2, 0, 0):
@@ -2020,6 +2013,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
case IP_VERSION(3, 1, 6):
case IP_VERSION(3, 2, 0):
case IP_VERSION(3, 2, 1):
+ case IP_VERSION(3, 5, 0):
return 0;
default:
break;
@@ -2085,7 +2079,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
struct dmub_srv_create_params create_params;
struct dmub_srv_region_params region_params;
struct dmub_srv_region_info region_info;
- struct dmub_srv_fb_params fb_params;
+ struct dmub_srv_memory_params memory_params;
struct dmub_srv_fb_info *fb_info;
struct dmub_srv *dmub_srv;
const struct dmcub_firmware_header_v1_0 *hdr;
@@ -2093,7 +2087,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
enum dmub_status status;
int r;
- switch (adev->ip_versions[DCE_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(2, 1, 0):
dmub_asic = DMUB_ASIC_DCN21;
break;
@@ -2128,6 +2122,9 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
case IP_VERSION(3, 2, 1):
dmub_asic = DMUB_ASIC_DCN321;
break;
+ case IP_VERSION(3, 5, 0):
+ dmub_asic = DMUB_ASIC_DCN35;
+ break;
default:
/* ASIC doesn't support DMUB. */
return 0;
@@ -2185,6 +2182,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
adev->dm.dmub_fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
PSP_HEADER_BYTES;
+ region_params.is_mailbox_in_inbox = false;
status = dmub_srv_calc_region_info(dmub_srv, &region_params,
&region_info);
@@ -2208,10 +2206,10 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
return r;
/* Rebase the regions on the framebuffer address. */
- memset(&fb_params, 0, sizeof(fb_params));
- fb_params.cpu_addr = adev->dm.dmub_bo_cpu_addr;
- fb_params.gpu_addr = adev->dm.dmub_bo_gpu_addr;
- fb_params.region_info = &region_info;
+ memset(&memory_params, 0, sizeof(memory_params));
+ memory_params.cpu_fb_addr = adev->dm.dmub_bo_cpu_addr;
+ memory_params.gpu_fb_addr = adev->dm.dmub_bo_gpu_addr;
+ memory_params.region_info = &region_info;
adev->dm.dmub_fb_info =
kzalloc(sizeof(*adev->dm.dmub_fb_info), GFP_KERNEL);
@@ -2223,7 +2221,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
return -ENOMEM;
}
- status = dmub_srv_calc_fb_info(dmub_srv, &fb_params, fb_info);
+ status = dmub_srv_calc_mem_info(dmub_srv, &memory_params, fb_info);
if (status != DMUB_STATUS_OK) {
DRM_ERROR("Error calculating DMUB FB info: %d\n", status);
return -EINVAL;
@@ -2462,7 +2460,7 @@ static int amdgpu_dm_smu_write_watermarks_table(struct amdgpu_device *adev)
* therefore, this function apply to navi10/12/14 but not Renoir
* *
*/
- switch (adev->ip_versions[DCE_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(2, 0, 2):
case IP_VERSION(2, 0, 0):
break;
@@ -2648,6 +2646,8 @@ static int dm_suspend(void *handle)
WARN_ON(adev->dm.cached_state);
adev->dm.cached_state = drm_atomic_helper_suspend(adev_to_drm(adev));
+ if (IS_ERR(adev->dm.cached_state))
+ return PTR_ERR(adev->dm.cached_state);
s3_handle_mst(adev_to_drm(adev), true);
@@ -2685,6 +2685,7 @@ static void emulated_link_detect(struct dc_link *link)
struct display_sink_capability sink_caps = { 0 };
enum dc_edid_status edid_status;
struct dc_context *dc_ctx = link->ctx;
+ struct drm_device *dev = adev_to_drm(dc_ctx->driver_context);
struct dc_sink *sink = NULL;
struct dc_sink *prev_sink = NULL;
@@ -2734,7 +2735,7 @@ static void emulated_link_detect(struct dc_link *link)
}
default:
- DC_ERROR("Invalid connector type! signal:%d\n",
+ drm_err(dev, "Invalid connector type! signal:%d\n",
link->connector_signal);
return;
}
@@ -2744,7 +2745,7 @@ static void emulated_link_detect(struct dc_link *link)
sink = dc_sink_create(&sink_init_data);
if (!sink) {
- DC_ERROR("Failed to create sink!\n");
+ drm_err(dev, "Failed to create sink!\n");
return;
}
@@ -2757,7 +2758,7 @@ static void emulated_link_detect(struct dc_link *link)
sink);
if (edid_status != EDID_OK)
- DC_ERROR("Failed to read EDID");
+ drm_err(dev, "Failed to read EDID\n");
}
@@ -2776,7 +2777,7 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
if (!bundle) {
- dm_error("Failed to allocate update bundle\n");
+ drm_err(dm->ddev, "Failed to allocate update bundle\n");
goto cleanup;
}
@@ -2822,6 +2823,10 @@ static int dm_resume(void *handle)
int i, r, j, ret;
bool need_hotplug = false;
+ if (dm->dc->caps.ips_support) {
+ dc_dmub_srv_exit_low_power_state(dm->dc);
+ }
+
if (amdgpu_in_reset(adev)) {
dc_state = dm->cached_dc_state;
@@ -2847,6 +2852,7 @@ static int dm_resume(void *handle)
DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r);
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);
+
dc_resume(dm->dc);
amdgpu_dm_irq_resume_early(adev);
@@ -3224,7 +3230,8 @@ void amdgpu_dm_update_connector_after_detect(
aconnector->timing_requested =
kzalloc(sizeof(struct dc_crtc_timing), GFP_KERNEL);
if (!aconnector->timing_requested)
- dm_error("failed to create aconnector->requested_timing\n");
+ drm_err(dev,
+ "failed to create aconnector->requested_timing\n");
}
drm_connector_update_edid_property(connector, aconnector->edid);
@@ -4410,7 +4417,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
}
/* Use Outbox interrupt */
- switch (adev->ip_versions[DCE_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(3, 0, 0):
case IP_VERSION(3, 1, 2):
case IP_VERSION(3, 1, 3):
@@ -4420,6 +4427,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
case IP_VERSION(3, 2, 0):
case IP_VERSION(3, 2, 1):
case IP_VERSION(2, 1, 0):
+ case IP_VERSION(3, 5, 0):
if (register_outbox_irq_handlers(dm->adev)) {
DRM_ERROR("DM: Failed to initialize IRQ\n");
goto fail;
@@ -4427,12 +4435,12 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
break;
default:
DRM_DEBUG_KMS("Unsupported DCN IP version for outbox: 0x%X\n",
- adev->ip_versions[DCE_HWIP][0]);
+ amdgpu_ip_version(adev, DCE_HWIP, 0));
}
/* Determine whether to enable PSR support by default. */
if (!(amdgpu_dc_debug_mask & DC_DISABLE_PSR)) {
- switch (adev->ip_versions[DCE_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(3, 1, 2):
case IP_VERSION(3, 1, 3):
case IP_VERSION(3, 1, 4):
@@ -4440,6 +4448,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
case IP_VERSION(3, 1, 6):
case IP_VERSION(3, 2, 0):
case IP_VERSION(3, 2, 1):
+ case IP_VERSION(3, 5, 0):
psr_feature_enabled = true;
break;
default:
@@ -4564,7 +4573,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
}
break;
default:
- switch (adev->ip_versions[DCE_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
case IP_VERSION(2, 0, 2):
@@ -4582,6 +4591,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
case IP_VERSION(3, 1, 6):
case IP_VERSION(3, 2, 0):
case IP_VERSION(3, 2, 1):
+ case IP_VERSION(3, 5, 0):
if (dcn10_register_irq_handlers(dm->adev)) {
DRM_ERROR("DM: Failed to initialize IRQ\n");
goto fail;
@@ -4589,7 +4599,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
break;
default:
DRM_ERROR("Unsupported DCE IP versions: 0x%X\n",
- adev->ip_versions[DCE_HWIP][0]);
+ amdgpu_ip_version(adev, DCE_HWIP, 0));
goto fail;
}
break;
@@ -4672,14 +4682,14 @@ static int dm_init_microcode(struct amdgpu_device *adev)
char *fw_name_dmub;
int r;
- switch (adev->ip_versions[DCE_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(2, 1, 0):
fw_name_dmub = FIRMWARE_RENOIR_DMUB;
if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id))
fw_name_dmub = FIRMWARE_GREEN_SARDINE_DMUB;
break;
case IP_VERSION(3, 0, 0):
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 3, 0))
fw_name_dmub = FIRMWARE_SIENNA_CICHLID_DMUB;
else
fw_name_dmub = FIRMWARE_NAVY_FLOUNDER_DMUB;
@@ -4712,13 +4722,14 @@ static int dm_init_microcode(struct amdgpu_device *adev)
case IP_VERSION(3, 2, 1):
fw_name_dmub = FIRMWARE_DCN_V3_2_1_DMCUB;
break;
+ case IP_VERSION(3, 5, 0):
+ fw_name_dmub = FIRMWARE_DCN_35_DMUB;
+ break;
default:
/* ASIC doesn't support DMUB. */
return 0;
}
r = amdgpu_ucode_request(adev, &adev->dm.dmub_fw, fw_name_dmub);
- if (r)
- DRM_ERROR("DMUB firmware loading failed: %d\n", r);
return r;
}
@@ -4806,7 +4817,7 @@ static int dm_early_init(void *handle)
break;
default:
- switch (adev->ip_versions[DCE_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
case IP_VERSION(2, 0, 2):
case IP_VERSION(3, 0, 0):
adev->mode_info.num_crtc = 6;
@@ -4836,13 +4847,14 @@ static int dm_early_init(void *handle)
case IP_VERSION(3, 1, 6):
case IP_VERSION(3, 2, 0):
case IP_VERSION(3, 2, 1):
+ case IP_VERSION(3, 5, 0):
adev->mode_info.num_crtc = 4;
adev->mode_info.num_hpd = 4;
adev->mode_info.num_dig = 4;
break;
default:
DRM_ERROR("Unsupported DCE IP versions: 0x%x\n",
- adev->ip_versions[DCE_HWIP][0]);
+ amdgpu_ip_version(adev, DCE_HWIP, 0));
return -EINVAL;
}
break;
@@ -5170,6 +5182,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
if (plane->type == DRM_PLANE_TYPE_CURSOR)
return;
+ if (new_plane_state->rotation != DRM_MODE_ROTATE_0)
+ goto ffu;
+
num_clips = drm_plane_get_damage_clips_count(new_plane_state);
clips = drm_plane_get_damage_clips(new_plane_state);
@@ -5431,6 +5446,24 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing,
return color_space;
}
+static enum display_content_type
+get_output_content_type(const struct drm_connector_state *connector_state)
+{
+ switch (connector_state->content_type) {
+ default:
+ case DRM_MODE_CONTENT_TYPE_NO_DATA:
+ return DISPLAY_CONTENT_TYPE_NO_DATA;
+ case DRM_MODE_CONTENT_TYPE_GRAPHICS:
+ return DISPLAY_CONTENT_TYPE_GRAPHICS;
+ case DRM_MODE_CONTENT_TYPE_PHOTO:
+ return DISPLAY_CONTENT_TYPE_PHOTO;
+ case DRM_MODE_CONTENT_TYPE_CINEMA:
+ return DISPLAY_CONTENT_TYPE_CINEMA;
+ case DRM_MODE_CONTENT_TYPE_GAME:
+ return DISPLAY_CONTENT_TYPE_GAME;
+ }
+}
+
static bool adjust_colour_depth_from_display_info(
struct dc_crtc_timing *timing_out,
const struct drm_display_info *info)
@@ -5565,6 +5598,7 @@ static void fill_stream_properties_from_drm_display_mode(
}
stream->output_color_space = get_output_color_space(timing_out, connector_state);
+ stream->content_type = get_output_content_type(connector_state);
}
static void fill_audio_info(struct audio_info *audio_info,
@@ -6113,10 +6147,10 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
requested_bpc);
if (aconnector->timing_changed) {
- DC_LOG_DEBUG("%s: overriding timing for automated test, bpc %d, changing to %d\n",
- __func__,
- stream->timing.display_color_depth,
- aconnector->timing_requested->display_color_depth);
+ drm_dbg(aconnector->base.dev,
+ "overriding timing for automated test, bpc %d, changing to %d\n",
+ stream->timing.display_color_depth,
+ aconnector->timing_requested->display_color_depth);
stream->timing = *aconnector->timing_requested;
}
@@ -6236,7 +6270,7 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector,
dm_new_state->underscan_enable = val;
ret = 0;
} else if (property == adev->mode_info.abm_level_property) {
- dm_new_state->abm_level = val;
+ dm_new_state->abm_level = val ?: ABM_LEVEL_IMMEDIATE_DISABLE;
ret = 0;
}
@@ -6281,7 +6315,8 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector,
*val = dm_state->underscan_enable;
ret = 0;
} else if (property == adev->mode_info.abm_level_property) {
- *val = dm_state->abm_level;
+ *val = (dm_state->abm_level != ABM_LEVEL_IMMEDIATE_DISABLE) ?
+ dm_state->abm_level : 0;
ret = 0;
}
@@ -6354,7 +6389,8 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector)
state->pbn = 0;
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
- state->abm_level = amdgpu_dm_abm_level;
+ state->abm_level = amdgpu_dm_abm_level ?:
+ ABM_LEVEL_IMMEDIATE_DISABLE;
__drm_atomic_helper_connector_reset(connector, &state->base);
}
@@ -6412,15 +6448,23 @@ amdgpu_dm_connector_late_register(struct drm_connector *connector)
static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector)
{
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+ struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
struct dc_link *dc_link = aconnector->dc_link;
struct dc_sink *dc_em_sink = aconnector->dc_em_sink;
struct edid *edid;
- if (!connector->edid_override)
+ /*
+ * Note: drm_get_edid gets edid in the following order:
+ * 1) override EDID if set via edid_override debugfs,
+ * 2) firmware EDID if set via edid_firmware module parameter
+ * 3) regular DDC read.
+ */
+ edid = drm_get_edid(connector, &amdgpu_connector->ddc_bus->aux.ddc);
+ if (!edid) {
+ DRM_ERROR("No EDID found on connector: %s.\n", connector->name);
return;
+ }
- drm_edid_override_connector_update(&aconnector->base);
- edid = aconnector->base.edid_blob_ptr->data;
aconnector->edid = edid;
/* Update emulated (virtual) sink's EDID */
@@ -6455,29 +6499,28 @@ static int get_modes(struct drm_connector *connector)
static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
{
+ struct drm_connector *connector = &aconnector->base;
+ struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(&aconnector->base);
struct dc_sink_init_data init_params = {
.link = aconnector->dc_link,
.sink_signal = SIGNAL_TYPE_VIRTUAL
};
struct edid *edid;
- if (!aconnector->base.edid_blob_ptr) {
- /* if connector->edid_override valid, pass
- * it to edid_override to edid_blob_ptr
- */
-
- drm_edid_override_connector_update(&aconnector->base);
-
- if (!aconnector->base.edid_blob_ptr) {
- DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n",
- aconnector->base.name);
-
- aconnector->base.force = DRM_FORCE_OFF;
- return;
- }
+ /*
+ * Note: drm_get_edid gets edid in the following order:
+ * 1) override EDID if set via edid_override debugfs,
+ * 2) firmware EDID if set via edid_firmware module parameter
+ * 3) regular DDC read.
+ */
+ edid = drm_get_edid(connector, &amdgpu_connector->ddc_bus->aux.ddc);
+ if (!edid) {
+ DRM_ERROR("No EDID found on connector: %s.\n", connector->name);
+ return;
}
- edid = (struct edid *) aconnector->base.edid_blob_ptr->data;
+ if (drm_detect_hdmi_monitor(edid))
+ init_params.sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
aconnector->edid = edid;
@@ -6765,6 +6808,14 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
new_crtc_state->mode_changed = true;
}
+ if (new_con_state->content_type != old_con_state->content_type) {
+ new_crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(new_crtc_state))
+ return PTR_ERR(new_crtc_state);
+
+ new_crtc_state->mode_changed = true;
+ }
+
if (!drm_connector_atomic_hdr_metadata_equal(old_con_state, new_con_state)) {
struct dc_info_packet hdr_infopacket;
@@ -7401,6 +7452,11 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
}
if (connector_type == DRM_MODE_CONNECTOR_HDMIA) {
+ /* Content Type is currently only implemented for HDMI. */
+ drm_connector_attach_content_type_property(&aconnector->base);
+ }
+
+ if (connector_type == DRM_MODE_CONNECTOR_HDMIA) {
if (!drm_mode_create_hdmi_colorspace_property(&aconnector->base, supported_colorspaces))
drm_connector_attach_colorspace_property(&aconnector->base);
} else if ((connector_type == DRM_MODE_CONNECTOR_DisplayPort && !aconnector->mst_root) ||
@@ -7431,6 +7487,9 @@ static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
int i;
int result = -EIO;
+ if (!ddc_service->ddc_pin || !ddc_service->ddc_pin->hw_info.hw_supported)
+ return result;
+
cmd.payloads = kcalloc(num, sizeof(struct i2c_payload), GFP_KERNEL);
if (!cmd.payloads)
@@ -7823,8 +7882,9 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc)
/* Mark this event as consumed */
acrtc->base.state->event = NULL;
- DC_LOG_PFLIP("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n",
- acrtc->crtc_id);
+ drm_dbg_state(acrtc->base.dev,
+ "crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n",
+ acrtc->crtc_id);
}
static void update_freesync_state_on_stream(
@@ -8067,7 +8127,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
if (!bundle) {
- dm_error("Failed to allocate update bundle\n");
+ drm_err(dev, "Failed to allocate update bundle\n");
goto cleanup;
}
@@ -8655,7 +8715,9 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
status = dc_stream_get_status_from_state(dc_state,
dm_new_crtc_state->stream);
if (!status)
- DC_ERR("got no status for stream %p on acrtc%p\n", dm_new_crtc_state->stream, acrtc);
+ drm_err(dev,
+ "got no status for stream %p on acrtc%p\n",
+ dm_new_crtc_state->stream, acrtc);
else
acrtc->otg_inst = status->primary_otg_inst;
}
@@ -8689,6 +8751,17 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
trace_amdgpu_dm_atomic_commit_tail_begin(state);
+ if (dm->dc->caps.ips_support) {
+ for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) {
+ if (new_con_state->crtc &&
+ new_con_state->crtc->state->active &&
+ drm_atomic_crtc_needs_modeset(new_con_state->crtc->state)) {
+ dc_dmub_srv_exit_low_power_state(dm->dc);
+ break;
+ }
+ }
+ }
+
drm_atomic_helper_update_legacy_modeset_state(dev, state);
drm_dp_mst_atomic_wait_for_dependencies(state);
@@ -9539,14 +9612,14 @@ static bool should_reset_plane(struct drm_atomic_state *state,
struct drm_plane *other;
struct drm_plane_state *old_other_state, *new_other_state;
struct drm_crtc_state *new_crtc_state;
+ struct amdgpu_device *adev = drm_to_adev(plane->dev);
int i;
/*
- * TODO: Remove this hack once the checks below are sufficient
- * enough to determine when we need to reset all the planes on
- * the stream.
+ * TODO: Remove this hack for all asics once it proves that the
+ * fast updates works fine on DCN3.2+.
*/
- if (state->allow_modeset)
+ if (adev->ip_versions[DCE_HWIP][0] < IP_VERSION(3, 2, 0) && state->allow_modeset)
return true;
/* Exit early if we know that we're adding or removing the plane. */
@@ -9816,7 +9889,7 @@ static int dm_update_plane_state(struct dc *dc,
/* Block top most plane from being a video plane */
if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
- if (is_video_format(new_plane_state->fb->format->format) && *is_top_most_overlay)
+ if (amdgpu_dm_plane_is_video_format(new_plane_state->fb->format->format) && *is_top_most_overlay)
return -EINVAL;
*is_top_most_overlay = false;
@@ -9892,16 +9965,27 @@ static void dm_get_oriented_plane_size(struct drm_plane_state *plane_state,
}
}
+static void
+dm_get_plane_scale(struct drm_plane_state *plane_state,
+ int *out_plane_scale_w, int *out_plane_scale_h)
+{
+ int plane_src_w, plane_src_h;
+
+ dm_get_oriented_plane_size(plane_state, &plane_src_w, &plane_src_h);
+ *out_plane_scale_w = plane_state->crtc_w * 1000 / plane_src_w;
+ *out_plane_scale_h = plane_state->crtc_h * 1000 / plane_src_h;
+}
+
static int dm_check_crtc_cursor(struct drm_atomic_state *state,
struct drm_crtc *crtc,
struct drm_crtc_state *new_crtc_state)
{
- struct drm_plane *cursor = crtc->cursor, *underlying;
+ struct drm_plane *cursor = crtc->cursor, *plane, *underlying;
+ struct drm_plane_state *old_plane_state, *new_plane_state;
struct drm_plane_state *new_cursor_state, *new_underlying_state;
int i;
int cursor_scale_w, cursor_scale_h, underlying_scale_w, underlying_scale_h;
- int cursor_src_w, cursor_src_h;
- int underlying_src_w, underlying_src_h;
+ bool any_relevant_change = false;
/* On DCE and DCN there is no dedicated hardware cursor plane. We get a
* cursor per pipe but it's going to inherit the scaling and
@@ -9909,13 +9993,50 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
* blending properties match the underlying planes'.
*/
- new_cursor_state = drm_atomic_get_new_plane_state(state, cursor);
- if (!new_cursor_state || !new_cursor_state->fb)
+ /* If no plane was enabled or changed scaling, no need to check again */
+ for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
+ int new_scale_w, new_scale_h, old_scale_w, old_scale_h;
+
+ if (!new_plane_state || !new_plane_state->fb || new_plane_state->crtc != crtc)
+ continue;
+
+ if (!old_plane_state || !old_plane_state->fb || old_plane_state->crtc != crtc) {
+ any_relevant_change = true;
+ break;
+ }
+
+ if (new_plane_state->fb == old_plane_state->fb &&
+ new_plane_state->crtc_w == old_plane_state->crtc_w &&
+ new_plane_state->crtc_h == old_plane_state->crtc_h)
+ continue;
+
+ dm_get_plane_scale(new_plane_state, &new_scale_w, &new_scale_h);
+ dm_get_plane_scale(old_plane_state, &old_scale_w, &old_scale_h);
+
+ if (new_scale_w != old_scale_w || new_scale_h != old_scale_h) {
+ any_relevant_change = true;
+ break;
+ }
+ }
+
+ if (!any_relevant_change)
+ return 0;
+
+ new_cursor_state = drm_atomic_get_plane_state(state, cursor);
+ if (IS_ERR(new_cursor_state))
+ return PTR_ERR(new_cursor_state);
+
+ if (!new_cursor_state->fb)
return 0;
- dm_get_oriented_plane_size(new_cursor_state, &cursor_src_w, &cursor_src_h);
- cursor_scale_w = new_cursor_state->crtc_w * 1000 / cursor_src_w;
- cursor_scale_h = new_cursor_state->crtc_h * 1000 / cursor_src_h;
+ dm_get_plane_scale(new_cursor_state, &cursor_scale_w, &cursor_scale_h);
+
+ /* Need to check all enabled planes, even if this commit doesn't change
+ * their state
+ */
+ i = drm_atomic_add_affected_planes(state, crtc);
+ if (i)
+ return i;
for_each_new_plane_in_state_reverse(state, underlying, new_underlying_state, i) {
/* Narrow down to non-cursor planes on the same CRTC as the cursor */
@@ -9926,10 +10047,8 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
if (!new_underlying_state->fb)
continue;
- dm_get_oriented_plane_size(new_underlying_state,
- &underlying_src_w, &underlying_src_h);
- underlying_scale_w = new_underlying_state->crtc_w * 1000 / underlying_src_w;
- underlying_scale_h = new_underlying_state->crtc_h * 1000 / underlying_src_h;
+ dm_get_plane_scale(new_underlying_state,
+ &underlying_scale_w, &underlying_scale_h);
if (cursor_scale_w != underlying_scale_w ||
cursor_scale_h != underlying_scale_h) {
@@ -10832,7 +10951,8 @@ void dm_write_reg_func(const struct dc_context *ctx, uint32_t address,
{
#ifdef DM_CHECK_ADDR_0
if (address == 0) {
- DC_ERR("invalid register write. address = 0");
+ drm_err(adev_to_drm(ctx->driver_context),
+ "invalid register write. address = 0");
return;
}
#endif
@@ -10846,7 +10966,8 @@ uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address,
u32 value;
#ifdef DM_CHECK_ADDR_0
if (address == 0) {
- DC_ERR("invalid register read; address = 0\n");
+ drm_err(adev_to_drm(ctx->driver_context),
+ "invalid register read; address = 0\n");
return 0;
}
#endif
@@ -10956,27 +11077,6 @@ int amdgpu_dm_process_dmub_set_config_sync(
return ret;
}
-/*
- * Check whether seamless boot is supported.
- *
- * So far we only support seamless boot on CHIP_VANGOGH.
- * If everything goes well, we may consider expanding
- * seamless boot to other ASICs.
- */
-bool check_seamless_boot_capability(struct amdgpu_device *adev)
-{
- switch (adev->ip_versions[DCE_HWIP][0]) {
- case IP_VERSION(3, 0, 1):
- if (!adev->mman.keep_stolen_vga_memory)
- return true;
- break;
- default:
- break;
- }
-
- return false;
-}
-
bool dm_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
{
return dc_dmub_srv_cmd_run(ctx->dmub_srv, cmd, wait_type);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 9e4cc5eeda76..3d480be802cb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -825,8 +825,6 @@ int amdgpu_dm_process_dmub_aux_transfer_sync(struct dc_context *ctx, unsigned in
int amdgpu_dm_process_dmub_set_config_sync(struct dc_context *ctx, unsigned int link_index,
struct set_config_cmd_payload *payload, enum set_config_status *operation_result);
-bool check_seamless_boot_capability(struct amdgpu_device *adev);
-
struct dc_stream_state *
create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
const struct drm_display_mode *drm_mode,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index 97b7a0b8a1c2..cb0b48bb2a7d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -96,7 +96,7 @@ bool amdgpu_dm_crtc_vrr_active(struct dm_crtc_state *dm_state)
dm_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
}
-static void vblank_control_worker(struct work_struct *work)
+static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
{
struct vblank_control_work *vblank_work =
container_of(work, struct vblank_control_work, work);
@@ -151,7 +151,7 @@ static void vblank_control_worker(struct work_struct *work)
kfree(vblank_work);
}
-static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
+static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)
{
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
struct amdgpu_device *adev = drm_to_adev(crtc->dev);
@@ -191,7 +191,7 @@ skip:
if (!work)
return -ENOMEM;
- INIT_WORK(&work->work, vblank_control_worker);
+ INIT_WORK(&work->work, amdgpu_dm_crtc_vblank_control_worker);
work->dm = dm;
work->acrtc = acrtc;
work->enable = enable;
@@ -209,15 +209,15 @@ skip:
int amdgpu_dm_crtc_enable_vblank(struct drm_crtc *crtc)
{
- return dm_set_vblank(crtc, true);
+ return amdgpu_dm_crtc_set_vblank(crtc, true);
}
void amdgpu_dm_crtc_disable_vblank(struct drm_crtc *crtc)
{
- dm_set_vblank(crtc, false);
+ amdgpu_dm_crtc_set_vblank(crtc, false);
}
-static void dm_crtc_destroy_state(struct drm_crtc *crtc,
+static void amdgpu_dm_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
struct dm_crtc_state *cur = to_dm_crtc_state(state);
@@ -233,7 +233,7 @@ static void dm_crtc_destroy_state(struct drm_crtc *crtc,
kfree(state);
}
-static struct drm_crtc_state *dm_crtc_duplicate_state(struct drm_crtc *crtc)
+static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *crtc)
{
struct dm_crtc_state *state, *cur;
@@ -273,12 +273,12 @@ static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc)
kfree(crtc);
}
-static void dm_crtc_reset_state(struct drm_crtc *crtc)
+static void amdgpu_dm_crtc_reset_state(struct drm_crtc *crtc)
{
struct dm_crtc_state *state;
if (crtc->state)
- dm_crtc_destroy_state(crtc, crtc->state);
+ amdgpu_dm_crtc_destroy_state(crtc, crtc->state);
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (WARN_ON(!state))
@@ -298,12 +298,12 @@ static int amdgpu_dm_crtc_late_register(struct drm_crtc *crtc)
/* Implemented only the options currently available for the driver */
static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
- .reset = dm_crtc_reset_state,
+ .reset = amdgpu_dm_crtc_reset_state,
.destroy = amdgpu_dm_crtc_destroy,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
- .atomic_duplicate_state = dm_crtc_duplicate_state,
- .atomic_destroy_state = dm_crtc_destroy_state,
+ .atomic_duplicate_state = amdgpu_dm_crtc_duplicate_state,
+ .atomic_destroy_state = amdgpu_dm_crtc_destroy_state,
.set_crc_source = amdgpu_dm_crtc_set_crc_source,
.verify_crc_source = amdgpu_dm_crtc_verify_crc_source,
.get_crc_sources = amdgpu_dm_crtc_get_crc_sources,
@@ -316,11 +316,11 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
#endif
};
-static void dm_crtc_helper_disable(struct drm_crtc *crtc)
+static void amdgpu_dm_crtc_helper_disable(struct drm_crtc *crtc)
{
}
-static int count_crtc_active_planes(struct drm_crtc_state *new_crtc_state)
+static int amdgpu_dm_crtc_count_crtc_active_planes(struct drm_crtc_state *new_crtc_state)
{
struct drm_atomic_state *state = new_crtc_state->state;
struct drm_plane *plane;
@@ -352,8 +352,8 @@ static int count_crtc_active_planes(struct drm_crtc_state *new_crtc_state)
return num_active;
}
-static void dm_update_crtc_active_planes(struct drm_crtc *crtc,
- struct drm_crtc_state *new_crtc_state)
+static void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc,
+ struct drm_crtc_state *new_crtc_state)
{
struct dm_crtc_state *dm_new_crtc_state =
to_dm_crtc_state(new_crtc_state);
@@ -364,18 +364,18 @@ static void dm_update_crtc_active_planes(struct drm_crtc *crtc,
return;
dm_new_crtc_state->active_planes =
- count_crtc_active_planes(new_crtc_state);
+ amdgpu_dm_crtc_count_crtc_active_planes(new_crtc_state);
}
-static bool dm_crtc_helper_mode_fixup(struct drm_crtc *crtc,
+static bool amdgpu_dm_crtc_helper_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
-static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
+static int amdgpu_dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
{
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
crtc);
@@ -386,7 +386,7 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
trace_amdgpu_dm_crtc_atomic_check(crtc_state);
- dm_update_crtc_active_planes(crtc, crtc_state);
+ amdgpu_dm_crtc_update_crtc_active_planes(crtc, crtc_state);
if (WARN_ON(unlikely(!dm_crtc_state->stream &&
amdgpu_dm_crtc_modeset_required(crtc_state, NULL, dm_crtc_state->stream)))) {
@@ -429,9 +429,9 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
}
static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = {
- .disable = dm_crtc_helper_disable,
- .atomic_check = dm_crtc_helper_atomic_check,
- .mode_fixup = dm_crtc_helper_mode_fixup,
+ .disable = amdgpu_dm_crtc_helper_disable,
+ .atomic_check = amdgpu_dm_crtc_helper_atomic_check,
+ .mode_fixup = amdgpu_dm_crtc_helper_mode_fixup,
.get_scanout_position = amdgpu_crtc_get_scanout_position,
};
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 7c21e21bcc51..13a177d34376 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -37,6 +37,7 @@
#include "link_hwss.h"
#include "dc/dc_dmub_srv.h"
#include "link/protocols/link_dp_capability.h"
+#include "inc/hw/dchubbub.h"
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
#include "amdgpu_dm_psr.h"
@@ -1201,6 +1202,35 @@ static int internal_display_show(struct seq_file *m, void *data)
return 0;
}
+/*
+ * Returns the number of segments used if ODM Combine mode is enabled.
+ * Example usage: cat /sys/kernel/debug/dri/0/DP-1/odm_combine_segments
+ */
+static int odm_combine_segments_show(struct seq_file *m, void *unused)
+{
+ struct drm_connector *connector = m->private;
+ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+ struct dc_link *link = aconnector->dc_link;
+ struct pipe_ctx *pipe_ctx = NULL;
+ int i, segments = -EOPNOTSUPP;
+
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+ pipe_ctx->stream->link == link)
+ break;
+ }
+
+ if (connector->status != connector_status_connected)
+ return -ENODEV;
+
+ if (pipe_ctx != NULL && pipe_ctx->stream_res.tg->funcs->get_odm_combine_segments)
+ pipe_ctx->stream_res.tg->funcs->get_odm_combine_segments(pipe_ctx->stream_res.tg, &segments);
+
+ seq_printf(m, "%d\n", segments);
+ return 0;
+}
+
/* function description
*
* generic SDP message access for testing
@@ -2713,6 +2743,7 @@ DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer);
DEFINE_SHOW_ATTRIBUTE(dp_lttpr_status);
DEFINE_SHOW_ATTRIBUTE(hdcp_sink_capability);
DEFINE_SHOW_ATTRIBUTE(internal_display);
+DEFINE_SHOW_ATTRIBUTE(odm_combine_segments);
DEFINE_SHOW_ATTRIBUTE(psr_capability);
DEFINE_SHOW_ATTRIBUTE(dp_is_mst_connector);
DEFINE_SHOW_ATTRIBUTE(dp_mst_progress_status);
@@ -2991,7 +3022,8 @@ static const struct {
} connector_debugfs_entries[] = {
{"force_yuv420_output", &force_yuv420_output_fops},
{"trigger_hotplug", &trigger_hotplug_debugfs_fops},
- {"internal_display", &internal_display_fops}
+ {"internal_display", &internal_display_fops},
+ {"odm_combine_segments", &odm_combine_segments_fops}
};
/*
@@ -3606,6 +3638,32 @@ DEFINE_DEBUGFS_ATTRIBUTE(disable_hpd_ops, disable_hpd_get,
disable_hpd_set, "%llu\n");
/*
+ * Prints hardware capabilities. These are used for IGT testing.
+ */
+static int capabilities_show(struct seq_file *m, void *unused)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
+ struct dc *dc = adev->dm.dc;
+ bool mall_supported = dc->caps.mall_size_total;
+ bool subvp_supported = dc->caps.subvp_fw_processing_delay_us;
+ unsigned int mall_in_use = false;
+ unsigned int subvp_in_use = dc->cap_funcs.get_subvp_en(dc, dc->current_state);
+ struct hubbub *hubbub = dc->res_pool->hubbub;
+
+ if (hubbub->funcs->get_mall_en)
+ hubbub->funcs->get_mall_en(hubbub, &mall_in_use);
+
+ seq_printf(m, "mall supported: %s, enabled: %s\n",
+ mall_supported ? "yes" : "no", mall_in_use ? "yes" : "no");
+ seq_printf(m, "sub-viewport supported: %s, enabled: %s\n",
+ subvp_supported ? "yes" : "no", subvp_in_use ? "yes" : "no");
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(capabilities);
+
+/*
* Temporary w/a to force sst sequence in M42D DP2 mst receiver
* Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dp_set_mst_en_for_sst
*/
@@ -3798,6 +3856,8 @@ void dtn_debugfs_init(struct amdgpu_device *adev)
debugfs_create_file("amdgpu_mst_topology", 0444, root,
adev, &mst_topo_fops);
+ debugfs_create_file("amdgpu_dm_capabilities", 0444, root,
+ adev, &capabilities_fops);
debugfs_create_file("amdgpu_dm_dtn_log", 0644, root, adev,
&dtn_log_fops);
debugfs_create_file("amdgpu_dm_dp_set_mst_en_for_sst", 0644, root, adev,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
index 20cfc5be21a4..b54d646a7c73 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
@@ -740,6 +740,7 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev,
if (dc->ctx->dce_version == DCN_VERSION_3_1 ||
dc->ctx->dce_version == DCN_VERSION_3_14 ||
dc->ctx->dce_version == DCN_VERSION_3_15 ||
+ dc->ctx->dce_version == DCN_VERSION_3_5 ||
dc->ctx->dce_version == DCN_VERSION_3_16)
hdcp_work[i].hdcp.config.psp.caps.dtm_v3_supported = 1;
hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 4b230933b28e..aac98f93545a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -63,6 +63,12 @@ static void apply_edid_quirks(struct edid *edid, struct dc_edid_caps *edid_caps)
DRM_DEBUG_DRIVER("Disabling FAMS on monitor with panel id %X\n", panel_id);
edid_caps->panel_patch.disable_fams = true;
break;
+ /* Workaround for some monitors that do not clear DPCD 0x317 if FreeSync is unsupported */
+ case drm_edid_encode_panel_id('A', 'U', 'O', 0xA7AB):
+ case drm_edid_encode_panel_id('A', 'U', 'O', 0xE69B):
+ DRM_DEBUG_DRIVER("Clearing DPCD 0x317 on monitor with panel id %X\n", panel_id);
+ edid_caps->panel_patch.remove_sink_ext_caps = true;
+ break;
default:
return;
}
@@ -204,37 +210,35 @@ void dm_helpers_dp_update_branch_info(
{}
static void dm_helpers_construct_old_payload(
- struct dc_link *link,
- int pbn_per_slot,
+ struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_topology_state *mst_state,
struct drm_dp_mst_atomic_payload *new_payload,
struct drm_dp_mst_atomic_payload *old_payload)
{
- struct link_mst_stream_allocation_table current_link_table =
- link->mst_stream_alloc_table;
- struct link_mst_stream_allocation *dc_alloc;
- int i;
+ struct drm_dp_mst_atomic_payload *pos;
+ int pbn_per_slot = mst_state->pbn_div;
+ u8 next_payload_vc_start = mgr->next_start_slot;
+ u8 payload_vc_start = new_payload->vc_start_slot;
+ u8 allocated_time_slots;
*old_payload = *new_payload;
/* Set correct time_slots/PBN of old payload.
* other fields (delete & dsc_enabled) in
* struct drm_dp_mst_atomic_payload are don't care fields
- * while calling drm_dp_remove_payload()
+ * while calling drm_dp_remove_payload_part2()
*/
- for (i = 0; i < current_link_table.stream_count; i++) {
- dc_alloc =
- &current_link_table.stream_allocations[i];
-
- if (dc_alloc->vcp_id == new_payload->vcpi) {
- old_payload->time_slots = dc_alloc->slot_count;
- old_payload->pbn = dc_alloc->slot_count * pbn_per_slot;
- break;
- }
+ list_for_each_entry(pos, &mst_state->payloads, next) {
+ if (pos != new_payload &&
+ pos->vc_start_slot > payload_vc_start &&
+ pos->vc_start_slot < next_payload_vc_start)
+ next_payload_vc_start = pos->vc_start_slot;
}
- /* make sure there is an old payload*/
- ASSERT(i != current_link_table.stream_count);
+ allocated_time_slots = next_payload_vc_start - payload_vc_start;
+ old_payload->time_slots = allocated_time_slots;
+ old_payload->pbn = allocated_time_slots * pbn_per_slot;
}
/*
@@ -263,21 +267,20 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
mst_mgr = &aconnector->mst_root->mst_mgr;
mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);
-
- /* It's OK for this to fail */
new_payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port);
if (enable) {
target_payload = new_payload;
+ /* It's OK for this to fail */
drm_dp_add_payload_part1(mst_mgr, mst_state, new_payload);
} else {
/* construct old payload by VCPI*/
- dm_helpers_construct_old_payload(stream->link, mst_state->pbn_div,
- new_payload, &old_payload);
+ dm_helpers_construct_old_payload(mst_mgr, mst_state,
+ new_payload, &old_payload);
target_payload = &old_payload;
- drm_dp_remove_payload(mst_mgr, mst_state, &old_payload, new_payload);
+ drm_dp_remove_payload_part1(mst_mgr, mst_state, new_payload);
}
/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
@@ -344,7 +347,7 @@ bool dm_helpers_dp_mst_send_payload_allocation(
struct amdgpu_dm_connector *aconnector;
struct drm_dp_mst_topology_state *mst_state;
struct drm_dp_mst_topology_mgr *mst_mgr;
- struct drm_dp_mst_atomic_payload *payload;
+ struct drm_dp_mst_atomic_payload *new_payload, old_payload;
enum mst_progress_status set_flag = MST_ALLOCATE_NEW_PAYLOAD;
enum mst_progress_status clr_flag = MST_CLEAR_ALLOCATED_PAYLOAD;
int ret = 0;
@@ -357,15 +360,20 @@ bool dm_helpers_dp_mst_send_payload_allocation(
mst_mgr = &aconnector->mst_root->mst_mgr;
mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);
- payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port);
+ new_payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port);
if (!enable) {
set_flag = MST_CLEAR_ALLOCATED_PAYLOAD;
clr_flag = MST_ALLOCATE_NEW_PAYLOAD;
}
- if (enable)
- ret = drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, payload);
+ if (enable) {
+ ret = drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, new_payload);
+ } else {
+ dm_helpers_construct_old_payload(mst_mgr, mst_state,
+ new_payload, &old_payload);
+ drm_dp_remove_payload_part2(mst_mgr, mst_state, &old_payload, new_payload);
+ }
if (ret) {
amdgpu_dm_set_mst_status(&aconnector->mst_status,
@@ -534,10 +542,8 @@ bool dm_helpers_dp_read_dpcd(
struct amdgpu_dm_connector *aconnector = link->priv;
- if (!aconnector) {
- DC_LOG_DC("Failed to find connector for link!\n");
+ if (!aconnector)
return false;
- }
return drm_dp_dpcd_read(&aconnector->dm_dp_aux.aux, address, data,
size) == size;
@@ -657,7 +663,7 @@ static bool execute_synaptics_rc_command(struct drm_dp_aux *aux,
drm_dp_dpcd_read(aux, SYNAPTICS_RC_DATA, data, length);
}
- DC_LOG_DC("%s: success = %d\n", __func__, success);
+ drm_dbg_dp(aux->drm_dev, "success = %d\n", success);
return success;
}
@@ -666,7 +672,7 @@ static void apply_synaptics_fifo_reset_wa(struct drm_dp_aux *aux)
{
unsigned char data[16] = {0};
- DC_LOG_DC("Start %s\n", __func__);
+ drm_dbg_dp(aux->drm_dev, "Start\n");
// Step 2
data[0] = 'P';
@@ -724,7 +730,7 @@ static void apply_synaptics_fifo_reset_wa(struct drm_dp_aux *aux)
if (!execute_synaptics_rc_command(aux, true, 0x02, 0, 0, NULL))
return;
- DC_LOG_DC("Done %s\n", __func__);
+ drm_dbg_dp(aux->drm_dev, "Done\n");
}
/* MST Dock */
@@ -737,7 +743,8 @@ static uint8_t write_dsc_enable_synaptics_non_virtual_dpcd_mst(
{
uint8_t ret = 0;
- DC_LOG_DC("Configure DSC to non-virtual dpcd synaptics\n");
+ drm_dbg_dp(aux->drm_dev,
+ "Configure DSC to non-virtual dpcd synaptics\n");
if (enable) {
/* When DSC is enabled on previous boot and reboot with the hub,
@@ -775,7 +782,9 @@ bool dm_helpers_dp_write_dsc_enable(
static const uint8_t DSC_DECODING = 0x01;
static const uint8_t DSC_PASSTHROUGH = 0x02;
- struct amdgpu_dm_connector *aconnector;
+ struct amdgpu_dm_connector *aconnector =
+ (struct amdgpu_dm_connector *)stream->dm_stream_context;
+ struct drm_device *dev = aconnector->base.dev;
struct drm_dp_mst_port *port;
uint8_t enable_dsc = enable ? DSC_DECODING : DSC_DISABLE;
uint8_t enable_passthrough = enable ? DSC_PASSTHROUGH : DSC_DISABLE;
@@ -785,8 +794,6 @@ bool dm_helpers_dp_write_dsc_enable(
return false;
if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
- aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
-
if (!aconnector->dsc_aux)
return false;
@@ -803,30 +810,34 @@ bool dm_helpers_dp_write_dsc_enable(
ret = drm_dp_dpcd_write(port->passthrough_aux,
DP_DSC_ENABLE,
&enable_passthrough, 1);
- DC_LOG_DC("Sent DSC pass-through enable to virtual dpcd port, ret = %u\n",
- ret);
+ drm_dbg_dp(dev,
+ "Sent DSC pass-through enable to virtual dpcd port, ret = %u\n",
+ ret);
}
ret = drm_dp_dpcd_write(aconnector->dsc_aux,
DP_DSC_ENABLE, &enable_dsc, 1);
- DC_LOG_DC("Sent DSC decoding enable to %s port, ret = %u\n",
- (port->passthrough_aux) ? "remote RX" :
- "virtual dpcd",
- ret);
+ drm_dbg_dp(dev,
+ "Sent DSC decoding enable to %s port, ret = %u\n",
+ (port->passthrough_aux) ? "remote RX" :
+ "virtual dpcd",
+ ret);
} else {
ret = drm_dp_dpcd_write(aconnector->dsc_aux,
DP_DSC_ENABLE, &enable_dsc, 1);
- DC_LOG_DC("Sent DSC decoding disable to %s port, ret = %u\n",
- (port->passthrough_aux) ? "remote RX" :
- "virtual dpcd",
- ret);
+ drm_dbg_dp(dev,
+ "Sent DSC decoding disable to %s port, ret = %u\n",
+ (port->passthrough_aux) ? "remote RX" :
+ "virtual dpcd",
+ ret);
if (port->passthrough_aux) {
ret = drm_dp_dpcd_write(port->passthrough_aux,
DP_DSC_ENABLE,
&enable_passthrough, 1);
- DC_LOG_DC("Sent DSC pass-through disable to virtual dpcd port, ret = %u\n",
- ret);
+ drm_dbg_dp(dev,
+ "Sent DSC pass-through disable to virtual dpcd port, ret = %u\n",
+ ret);
}
}
}
@@ -834,10 +845,14 @@ bool dm_helpers_dp_write_dsc_enable(
if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || stream->signal == SIGNAL_TYPE_EDP) {
if (stream->sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_NONE) {
ret = dm_helpers_dp_write_dpcd(ctx, stream->link, DP_DSC_ENABLE, &enable_dsc, 1);
- DC_LOG_DC("Send DSC %s to SST RX\n", enable_dsc ? "enable" : "disable");
+ drm_dbg_dp(dev,
+ "Send DSC %s to SST RX\n",
+ enable_dsc ? "enable" : "disable");
} else if (stream->sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER) {
ret = dm_helpers_dp_write_dpcd(ctx, stream->link, DP_DSC_ENABLE, &enable_dsc, 1);
- DC_LOG_DC("Send DSC %s to DP-HDMI PCON\n", enable_dsc ? "enable" : "disable");
+ drm_dbg_dp(dev,
+ "Send DSC %s to DP-HDMI PCON\n",
+ enable_dsc ? "enable" : "disable");
}
}
@@ -1106,6 +1121,7 @@ bool dm_helpers_dp_handle_test_pattern_request(
struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
struct pipe_ctx *pipe_ctx = NULL;
struct amdgpu_dm_connector *aconnector = link->priv;
+ struct drm_device *dev = aconnector->base.dev;
int i;
for (i = 0; i < MAX_PIPES; i++) {
@@ -1183,12 +1199,12 @@ bool dm_helpers_dp_handle_test_pattern_request(
&& pipe_ctx->stream->timing.display_color_depth != requestColorDepth)
|| (requestPixelEncoding != PIXEL_ENCODING_UNDEFINED
&& pipe_ctx->stream->timing.pixel_encoding != requestPixelEncoding)) {
- DC_LOG_DEBUG("%s: original bpc %d pix encoding %d, changing to %d %d\n",
- __func__,
- pipe_ctx->stream->timing.display_color_depth,
- pipe_ctx->stream->timing.pixel_encoding,
- requestColorDepth,
- requestPixelEncoding);
+ drm_dbg(dev,
+ "original bpc %d pix encoding %d, changing to %d %d\n",
+ pipe_ctx->stream->timing.display_color_depth,
+ pipe_ctx->stream->timing.pixel_encoding,
+ requestColorDepth,
+ requestPixelEncoding);
pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
pipe_ctx->stream->timing.pixel_encoding = requestPixelEncoding;
@@ -1199,10 +1215,13 @@ bool dm_helpers_dp_handle_test_pattern_request(
if (aconnector->timing_requested)
*aconnector->timing_requested = pipe_ctx->stream->timing;
else
- DC_LOG_ERROR("%s: timing storage failed\n", __func__);
+ drm_err(dev, "timing storage failed\n");
}
+ pipe_ctx->stream->test_pattern.type = test_pattern;
+ pipe_ctx->stream->test_pattern.color_space = test_pattern_color_space;
+
dc_link_dp_set_test_pattern(
(struct dc_link *) link,
test_pattern,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 57230661132b..11da0eebee6c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -173,8 +173,9 @@ amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
if (dc_link->sink_count)
dc_link_remove_remote_sink(dc_link, dc_sink);
- DC_LOG_MST("DM_MST: remove remote sink 0x%p, %d remaining\n",
- dc_sink, dc_link->sink_count);
+ drm_dbg_dp(connector->dev,
+ "DM_MST: remove remote sink 0x%p, %d remaining\n",
+ dc_sink, dc_link->sink_count);
dc_sink_release(dc_sink);
aconnector->dc_sink = NULL;
@@ -325,8 +326,10 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
return 0;
}
- DC_LOG_MST("DM_MST: add remote sink 0x%p, %d remaining\n",
- dc_sink, aconnector->dc_link->sink_count);
+ drm_dbg_dp(connector->dev,
+ "DM_MST: add remote sink 0x%p, %d remaining\n",
+ dc_sink,
+ aconnector->dc_link->sink_count);
dc_sink->priv = aconnector;
aconnector->dc_sink = dc_sink;
@@ -361,8 +364,9 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
return 0;
}
- DC_LOG_MST("DM_MST: add remote sink 0x%p, %d remaining\n",
- dc_sink, aconnector->dc_link->sink_count);
+ drm_dbg_dp(connector->dev,
+ "DM_MST: add remote sink 0x%p, %d remaining\n",
+ dc_sink, aconnector->dc_link->sink_count);
dc_sink->priv = aconnector;
/* dc_link_add_remote_sink returns a new reference */
@@ -481,8 +485,10 @@ dm_dp_mst_detect(struct drm_connector *connector,
if (aconnector->dc_link->sink_count)
dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink);
- DC_LOG_MST("DM_MST: remove remote sink 0x%p, %d remaining\n",
- aconnector->dc_link, aconnector->dc_link->sink_count);
+ drm_dbg_dp(connector->dev,
+ "DM_MST: remove remote sink 0x%p, %d remaining\n",
+ aconnector->dc_link,
+ aconnector->dc_link->sink_count);
dc_sink_release(aconnector->dc_sink);
aconnector->dc_sink = NULL;
@@ -1598,31 +1604,31 @@ enum dc_status dm_dp_mst_is_port_support_mode(
unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0;
unsigned int max_compressed_bw_in_kbps = 0;
struct dc_dsc_bw_range bw_range = {0};
- struct drm_dp_mst_topology_mgr *mst_mgr;
+ uint16_t full_pbn = aconnector->mst_output_port->full_pbn;
/*
- * check if the mode could be supported if DSC pass-through is supported
- * AND check if there enough bandwidth available to support the mode
- * with DSC enabled.
+ * Consider the case with the depth of the mst topology tree is equal or less than 2
+ * A. When dsc bitstream can be transmitted along the entire path
+ * 1. dsc is possible between source and branch/leaf device (common dsc params is possible), AND
+ * 2. dsc passthrough supported at MST branch, or
+ * 3. dsc decoding supported at leaf MST device
+ * Use maximum dsc compression as bw constraint
+ * B. When dsc bitstream cannot be transmitted along the entire path
+ * Use native bw as bw constraint
*/
if (is_dsc_common_config_possible(stream, &bw_range) &&
- aconnector->mst_output_port->passthrough_aux) {
- mst_mgr = aconnector->mst_output_port->mgr;
- mutex_lock(&mst_mgr->lock);
-
+ (aconnector->mst_output_port->passthrough_aux ||
+ aconnector->dsc_aux == &aconnector->mst_output_port->aux)) {
cur_link_settings = stream->link->verified_link_cap;
upper_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link,
- &cur_link_settings
- );
- down_link_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn);
+ &cur_link_settings);
+ down_link_bw_in_kbps = kbps_from_pbn(full_pbn);
/* pick the bottleneck */
end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps,
down_link_bw_in_kbps);
- mutex_unlock(&mst_mgr->lock);
-
/*
* use the maximum dsc compression bandwidth as the required
* bandwidth for the mode
@@ -1637,8 +1643,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
/* check if mode could be supported within full_pbn */
bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3;
pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false);
-
- if (pbn > aconnector->mst_output_port->full_pbn)
+ if (pbn > full_pbn)
return DC_FAIL_BANDWIDTH_VALIDATE;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index cc74dd69acf2..116121e647ca 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -139,7 +139,7 @@ void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state
}
}
-static void add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t mod)
+static void amdgpu_dm_plane_add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t mod)
{
if (!*mods)
return;
@@ -164,12 +164,12 @@ static void add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_
*size += 1;
}
-static bool modifier_has_dcc(uint64_t modifier)
+static bool amdgpu_dm_plane_modifier_has_dcc(uint64_t modifier)
{
return IS_AMD_FMT_MOD(modifier) && AMD_FMT_MOD_GET(DCC, modifier);
}
-static unsigned int modifier_gfx9_swizzle_mode(uint64_t modifier)
+static unsigned int amdgpu_dm_plane_modifier_gfx9_swizzle_mode(uint64_t modifier)
{
if (modifier == DRM_FORMAT_MOD_LINEAR)
return 0;
@@ -177,8 +177,8 @@ static unsigned int modifier_gfx9_swizzle_mode(uint64_t modifier)
return AMD_FMT_MOD_GET(TILE, modifier);
}
-static void fill_gfx8_tiling_info_from_flags(union dc_tiling_info *tiling_info,
- uint64_t tiling_flags)
+static void amdgpu_dm_plane_fill_gfx8_tiling_info_from_flags(union dc_tiling_info *tiling_info,
+ uint64_t tiling_flags)
{
/* Fill GFX8 params */
if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) {
@@ -209,8 +209,8 @@ static void fill_gfx8_tiling_info_from_flags(union dc_tiling_info *tiling_info,
AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
}
-static void fill_gfx9_tiling_info_from_device(const struct amdgpu_device *adev,
- union dc_tiling_info *tiling_info)
+static void amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(const struct amdgpu_device *adev,
+ union dc_tiling_info *tiling_info)
{
/* Fill GFX9 params */
tiling_info->gfx9.num_pipes =
@@ -226,13 +226,13 @@ static void fill_gfx9_tiling_info_from_device(const struct amdgpu_device *adev,
tiling_info->gfx9.num_rb_per_se =
adev->gfx.config.gb_addr_config_fields.num_rb_per_se;
tiling_info->gfx9.shaderEnable = 1;
- if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0))
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 3, 0))
tiling_info->gfx9.num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs;
}
-static void fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
- union dc_tiling_info *tiling_info,
- uint64_t modifier)
+static void amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
+ union dc_tiling_info *tiling_info,
+ uint64_t modifier)
{
unsigned int mod_bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier);
unsigned int mod_pipe_xor_bits = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier);
@@ -241,7 +241,7 @@ static void fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev
pipes_log2 = min(5u, mod_pipe_xor_bits);
- fill_gfx9_tiling_info_from_device(adev, tiling_info);
+ amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(adev, tiling_info);
if (!IS_AMD_FMT_MOD(modifier))
return;
@@ -258,13 +258,13 @@ static void fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev
}
}
-static int validate_dcc(struct amdgpu_device *adev,
- const enum surface_pixel_format format,
- const enum dc_rotation_angle rotation,
- const union dc_tiling_info *tiling_info,
- const struct dc_plane_dcc_param *dcc,
- const struct dc_plane_address *address,
- const struct plane_size *plane_size)
+static int amdgpu_dm_plane_validate_dcc(struct amdgpu_device *adev,
+ const enum surface_pixel_format format,
+ const enum dc_rotation_angle rotation,
+ const union dc_tiling_info *tiling_info,
+ const struct dc_plane_dcc_param *dcc,
+ const struct dc_plane_address *address,
+ const struct plane_size *plane_size)
{
struct dc *dc = adev->dm.dc;
struct dc_dcc_surface_param input;
@@ -303,23 +303,23 @@ static int validate_dcc(struct amdgpu_device *adev,
return 0;
}
-static int fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
- const struct amdgpu_framebuffer *afb,
- const enum surface_pixel_format format,
- const enum dc_rotation_angle rotation,
- const struct plane_size *plane_size,
- union dc_tiling_info *tiling_info,
- struct dc_plane_dcc_param *dcc,
- struct dc_plane_address *address,
- const bool force_disable_dcc)
+static int amdgpu_dm_plane_fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
+ const struct amdgpu_framebuffer *afb,
+ const enum surface_pixel_format format,
+ const enum dc_rotation_angle rotation,
+ const struct plane_size *plane_size,
+ union dc_tiling_info *tiling_info,
+ struct dc_plane_dcc_param *dcc,
+ struct dc_plane_address *address,
+ const bool force_disable_dcc)
{
const uint64_t modifier = afb->base.modifier;
int ret = 0;
- fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier);
- tiling_info->gfx9.swizzle = modifier_gfx9_swizzle_mode(modifier);
+ amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier);
+ tiling_info->gfx9.swizzle = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier);
- if (modifier_has_dcc(modifier) && !force_disable_dcc) {
+ if (amdgpu_dm_plane_modifier_has_dcc(modifier) && !force_disable_dcc) {
uint64_t dcc_address = afb->address + afb->base.offsets[1];
bool independent_64b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier);
bool independent_128b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_128B, modifier);
@@ -347,60 +347,64 @@ static int fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
address->grph.meta_addr.high_part = upper_32_bits(dcc_address);
}
- ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
+ ret = amdgpu_dm_plane_validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
if (ret)
- drm_dbg_kms(adev_to_drm(adev), "validate_dcc: returned error: %d\n", ret);
+ drm_dbg_kms(adev_to_drm(adev), "amdgpu_dm_plane_validate_dcc: returned error: %d\n", ret);
return ret;
}
-static void add_gfx10_1_modifiers(const struct amdgpu_device *adev,
- uint64_t **mods, uint64_t *size, uint64_t *capacity)
+static void amdgpu_dm_plane_add_gfx10_1_modifiers(const struct amdgpu_device *adev,
+ uint64_t **mods,
+ uint64_t *size,
+ uint64_t *capacity)
{
int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(DCC, 1) |
- AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
- AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
- AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
-
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(DCC, 1) |
- AMD_FMT_MOD_SET(DCC_RETILE, 1) |
- AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
- AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
- AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
-
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
-
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
-
-
- /* Only supported for 64bpp, will be filtered in dm_plane_format_mod_supported */
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
-
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(DCC, 1) |
+ AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
+
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(DCC, 1) |
+ AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+ AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
+
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
+
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
+
+
+ /* Only supported for 64bpp, will be filtered in amdgpu_dm_plane_format_mod_supported */
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
}
-static void add_gfx9_modifiers(const struct amdgpu_device *adev,
- uint64_t **mods, uint64_t *size, uint64_t *capacity)
+static void amdgpu_dm_plane_add_gfx9_modifiers(const struct amdgpu_device *adev,
+ uint64_t **mods,
+ uint64_t *size,
+ uint64_t *capacity)
{
int pipes = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
int pipe_xor_bits = min(8, pipes +
@@ -421,163 +425,164 @@ static void add_gfx9_modifiers(const struct amdgpu_device *adev,
*/
if (has_constant_encode) {
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
- AMD_FMT_MOD_SET(DCC, 1) |
- AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
- AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
- AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+ AMD_FMT_MOD_SET(DCC, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+ AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
}
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
- AMD_FMT_MOD_SET(DCC, 1) |
- AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
- AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
- AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+ AMD_FMT_MOD_SET(DCC, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+ AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
if (has_constant_encode) {
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
- AMD_FMT_MOD_SET(DCC, 1) |
- AMD_FMT_MOD_SET(DCC_RETILE, 1) |
- AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
- AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
-
- AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
- AMD_FMT_MOD_SET(RB, rb) |
- AMD_FMT_MOD_SET(PIPE, pipes));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+ AMD_FMT_MOD_SET(DCC, 1) |
+ AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+ AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+ AMD_FMT_MOD_SET(RB, rb) |
+ AMD_FMT_MOD_SET(PIPE, pipes));
}
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
- AMD_FMT_MOD_SET(DCC, 1) |
- AMD_FMT_MOD_SET(DCC_RETILE, 1) |
- AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
- AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
- AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
- AMD_FMT_MOD_SET(RB, rb) |
- AMD_FMT_MOD_SET(PIPE, pipes));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+ AMD_FMT_MOD_SET(DCC, 1) |
+ AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+ AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
+ AMD_FMT_MOD_SET(RB, rb) |
+ AMD_FMT_MOD_SET(PIPE, pipes));
}
/*
* Only supported for 64bpp on Raven, will be filtered on format in
- * dm_plane_format_mod_supported.
+ * amdgpu_dm_plane_format_mod_supported.
*/
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
if (adev->family == AMDGPU_FAMILY_RV) {
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
}
/*
* Only supported for 64bpp on Raven, will be filtered on format in
- * dm_plane_format_mod_supported.
+ * amdgpu_dm_plane_format_mod_supported.
*/
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
if (adev->family == AMDGPU_FAMILY_RV) {
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
}
}
-static void add_gfx10_3_modifiers(const struct amdgpu_device *adev,
- uint64_t **mods, uint64_t *size, uint64_t *capacity)
+static void amdgpu_dm_plane_add_gfx10_3_modifiers(const struct amdgpu_device *adev,
+ uint64_t **mods,
+ uint64_t *size,
+ uint64_t *capacity)
{
int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
int pkrs = ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs);
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(PACKERS, pkrs) |
- AMD_FMT_MOD_SET(DCC, 1) |
- AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
- AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
- AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
- AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
-
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(PACKERS, pkrs) |
- AMD_FMT_MOD_SET(DCC, 1) |
- AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
- AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
- AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
-
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(PACKERS, pkrs) |
- AMD_FMT_MOD_SET(DCC, 1) |
- AMD_FMT_MOD_SET(DCC_RETILE, 1) |
- AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
- AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
- AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
- AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
-
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(PACKERS, pkrs) |
- AMD_FMT_MOD_SET(DCC, 1) |
- AMD_FMT_MOD_SET(DCC_RETILE, 1) |
- AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
- AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
- AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
-
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(PACKERS, pkrs));
-
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
- AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
- AMD_FMT_MOD_SET(PACKERS, pkrs));
-
- /* Only supported for 64bpp, will be filtered in dm_plane_format_mod_supported */
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
-
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(PACKERS, pkrs) |
+ AMD_FMT_MOD_SET(DCC, 1) |
+ AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
+
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(PACKERS, pkrs) |
+ AMD_FMT_MOD_SET(DCC, 1) |
+ AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
+
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(PACKERS, pkrs) |
+ AMD_FMT_MOD_SET(DCC, 1) |
+ AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+ AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
+
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(PACKERS, pkrs) |
+ AMD_FMT_MOD_SET(DCC, 1) |
+ AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+ AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+ AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
+ AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
+
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(PACKERS, pkrs));
+
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+ AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+ AMD_FMT_MOD_SET(PACKERS, pkrs));
+
+ /* Only supported for 64bpp, will be filtered in amdgpu_dm_plane_format_mod_supported */
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
}
-static void add_gfx11_modifiers(struct amdgpu_device *adev,
+static void amdgpu_dm_plane_add_gfx11_modifiers(struct amdgpu_device *adev,
uint64_t **mods, uint64_t *size, uint64_t *capacity)
{
int num_pipes = 0;
@@ -628,21 +633,21 @@ static void add_gfx11_modifiers(struct amdgpu_device *adev,
AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B);
- add_modifier(mods, size, capacity, modifier_dcc_best);
- add_modifier(mods, size, capacity, modifier_dcc_4k);
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_dcc_best);
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_dcc_4k);
- add_modifier(mods, size, capacity, modifier_dcc_best | AMD_FMT_MOD_SET(DCC_RETILE, 1));
- add_modifier(mods, size, capacity, modifier_dcc_4k | AMD_FMT_MOD_SET(DCC_RETILE, 1));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_dcc_best | AMD_FMT_MOD_SET(DCC_RETILE, 1));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_dcc_4k | AMD_FMT_MOD_SET(DCC_RETILE, 1));
- add_modifier(mods, size, capacity, modifier_r_x);
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_r_x);
}
- add_modifier(mods, size, capacity, AMD_FMT_MOD |
- AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX11) |
- AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D));
+ amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
+ AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX11) |
+ AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D));
}
-static int get_plane_modifiers(struct amdgpu_device *adev, unsigned int plane_type, uint64_t **mods)
+static int amdgpu_dm_plane_get_plane_modifiers(struct amdgpu_device *adev, unsigned int plane_type, uint64_t **mods)
{
uint64_t size = 0, capacity = 128;
*mods = NULL;
@@ -654,36 +659,37 @@ static int get_plane_modifiers(struct amdgpu_device *adev, unsigned int plane_ty
*mods = kmalloc(capacity * sizeof(uint64_t), GFP_KERNEL);
if (plane_type == DRM_PLANE_TYPE_CURSOR) {
- add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
- add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
+ amdgpu_dm_plane_add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
+ amdgpu_dm_plane_add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
return *mods ? 0 : -ENOMEM;
}
switch (adev->family) {
case AMDGPU_FAMILY_AI:
case AMDGPU_FAMILY_RV:
- add_gfx9_modifiers(adev, mods, &size, &capacity);
+ amdgpu_dm_plane_add_gfx9_modifiers(adev, mods, &size, &capacity);
break;
case AMDGPU_FAMILY_NV:
case AMDGPU_FAMILY_VGH:
case AMDGPU_FAMILY_YC:
case AMDGPU_FAMILY_GC_10_3_6:
case AMDGPU_FAMILY_GC_10_3_7:
- if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0))
- add_gfx10_3_modifiers(adev, mods, &size, &capacity);
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 3, 0))
+ amdgpu_dm_plane_add_gfx10_3_modifiers(adev, mods, &size, &capacity);
else
- add_gfx10_1_modifiers(adev, mods, &size, &capacity);
+ amdgpu_dm_plane_add_gfx10_1_modifiers(adev, mods, &size, &capacity);
break;
case AMDGPU_FAMILY_GC_11_0_0:
case AMDGPU_FAMILY_GC_11_0_1:
- add_gfx11_modifiers(adev, mods, &size, &capacity);
+ case AMDGPU_FAMILY_GC_11_5_0:
+ amdgpu_dm_plane_add_gfx11_modifiers(adev, mods, &size, &capacity);
break;
}
- add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
+ amdgpu_dm_plane_add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
/* INVALID marks the end of the list. */
- add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
+ amdgpu_dm_plane_add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
if (!*mods)
return -ENOMEM;
@@ -691,9 +697,9 @@ static int get_plane_modifiers(struct amdgpu_device *adev, unsigned int plane_ty
return 0;
}
-static int get_plane_formats(const struct drm_plane *plane,
- const struct dc_plane_cap *plane_cap,
- uint32_t *formats, int max_formats)
+static int amdgpu_dm_plane_get_plane_formats(const struct drm_plane *plane,
+ const struct dc_plane_cap *plane_cap,
+ uint32_t *formats, int max_formats)
{
int i, num_formats = 0;
@@ -817,22 +823,22 @@ int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev,
}
if (adev->family >= AMDGPU_FAMILY_AI) {
- ret = fill_gfx9_plane_attributes_from_modifiers(adev, afb, format,
- rotation, plane_size,
- tiling_info, dcc,
- address,
- force_disable_dcc);
+ ret = amdgpu_dm_plane_fill_gfx9_plane_attributes_from_modifiers(adev, afb, format,
+ rotation, plane_size,
+ tiling_info, dcc,
+ address,
+ force_disable_dcc);
if (ret)
return ret;
} else {
- fill_gfx8_tiling_info_from_flags(tiling_info, tiling_flags);
+ amdgpu_dm_plane_fill_gfx8_tiling_info_from_flags(tiling_info, tiling_flags);
}
return 0;
}
-static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
- struct drm_plane_state *new_state)
+static int amdgpu_dm_plane_helper_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *new_state)
{
struct amdgpu_framebuffer *afb;
struct drm_gem_object *obj;
@@ -927,8 +933,8 @@ error_unlock:
return r;
}
-static void dm_plane_helper_cleanup_fb(struct drm_plane *plane,
- struct drm_plane_state *old_state)
+static void amdgpu_dm_plane_helper_cleanup_fb(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
{
struct amdgpu_bo *rbo;
int r;
@@ -948,7 +954,7 @@ static void dm_plane_helper_cleanup_fb(struct drm_plane *plane,
amdgpu_bo_unref(&rbo);
}
-static void get_min_max_dc_plane_scaling(struct drm_device *dev,
+static void amdgpu_dm_plane_get_min_max_dc_plane_scaling(struct drm_device *dev,
struct drm_framebuffer *fb,
int *min_downscale, int *max_upscale)
{
@@ -1029,8 +1035,8 @@ int amdgpu_dm_plane_helper_check_state(struct drm_plane_state *state,
}
/* Get min/max allowed scaling factors from plane caps. */
- get_min_max_dc_plane_scaling(state->crtc->dev, fb,
- &min_downscale, &max_upscale);
+ amdgpu_dm_plane_get_min_max_dc_plane_scaling(state->crtc->dev, fb,
+ &min_downscale, &max_upscale);
/*
* Convert to drm convention: 16.16 fixed point, instead of dc's
* 1.0 == 1000. Also drm scaling is src/dst instead of dc's
@@ -1068,8 +1074,8 @@ int amdgpu_dm_plane_fill_dc_scaling_info(struct amdgpu_device *adev,
* is to gesture the YouTube Android app into full screen
* on ChromeOS.
*/
- if (((adev->ip_versions[DCE_HWIP][0] == IP_VERSION(1, 0, 0)) ||
- (adev->ip_versions[DCE_HWIP][0] == IP_VERSION(1, 0, 1))) &&
+ if (((amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(1, 0, 0)) ||
+ (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(1, 0, 1))) &&
(state->fb && state->fb->format->format == DRM_FORMAT_NV12 &&
(scaling_info->src_rect.x != 0 || scaling_info->src_rect.y != 0)))
return -EINVAL;
@@ -1100,8 +1106,8 @@ int amdgpu_dm_plane_fill_dc_scaling_info(struct amdgpu_device *adev,
/* Validate scaling per-format with DC plane caps */
if (state->plane && state->plane->dev && state->fb) {
- get_min_max_dc_plane_scaling(state->plane->dev, state->fb,
- &min_downscale, &max_upscale);
+ amdgpu_dm_plane_get_min_max_dc_plane_scaling(state->plane->dev, state->fb,
+ &min_downscale, &max_upscale);
} else {
min_downscale = 250;
max_upscale = 16000;
@@ -1127,8 +1133,8 @@ int amdgpu_dm_plane_fill_dc_scaling_info(struct amdgpu_device *adev,
return 0;
}
-static int dm_plane_atomic_check(struct drm_plane *plane,
- struct drm_atomic_state *state)
+static int amdgpu_dm_plane_atomic_check(struct drm_plane *plane,
+ struct drm_atomic_state *state)
{
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
plane);
@@ -1166,8 +1172,8 @@ static int dm_plane_atomic_check(struct drm_plane *plane,
return -EINVAL;
}
-static int dm_plane_atomic_async_check(struct drm_plane *plane,
- struct drm_atomic_state *state)
+static int amdgpu_dm_plane_atomic_async_check(struct drm_plane *plane,
+ struct drm_atomic_state *state)
{
/* Only support async updates on cursor planes. */
if (plane->type != DRM_PLANE_TYPE_CURSOR)
@@ -1176,8 +1182,8 @@ static int dm_plane_atomic_async_check(struct drm_plane *plane,
return 0;
}
-static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc,
- struct dc_cursor_position *position)
+static int amdgpu_dm_plane_get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc,
+ struct dc_cursor_position *position)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
int x, y;
@@ -1236,13 +1242,11 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
if (!plane->state->fb && !old_plane_state->fb)
return;
- DC_LOG_CURSOR("%s: crtc_id=%d with size %d to %d\n",
- __func__,
- amdgpu_crtc->crtc_id,
- plane->state->crtc_w,
- plane->state->crtc_h);
+ drm_dbg_atomic(plane->dev, "crtc_id=%d with size %d to %d\n",
+ amdgpu_crtc->crtc_id, plane->state->crtc_w,
+ plane->state->crtc_h);
- ret = get_cursor_position(plane, crtc, &position);
+ ret = amdgpu_dm_plane_get_cursor_position(plane, crtc, &position);
if (ret)
return;
@@ -1291,8 +1295,8 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
}
}
-static void dm_plane_atomic_async_update(struct drm_plane *plane,
- struct drm_atomic_state *state)
+static void amdgpu_dm_plane_atomic_async_update(struct drm_plane *plane,
+ struct drm_atomic_state *state)
{
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
plane);
@@ -1316,14 +1320,14 @@ static void dm_plane_atomic_async_update(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs dm_plane_helper_funcs = {
- .prepare_fb = dm_plane_helper_prepare_fb,
- .cleanup_fb = dm_plane_helper_cleanup_fb,
- .atomic_check = dm_plane_atomic_check,
- .atomic_async_check = dm_plane_atomic_async_check,
- .atomic_async_update = dm_plane_atomic_async_update
+ .prepare_fb = amdgpu_dm_plane_helper_prepare_fb,
+ .cleanup_fb = amdgpu_dm_plane_helper_cleanup_fb,
+ .atomic_check = amdgpu_dm_plane_atomic_check,
+ .atomic_async_check = amdgpu_dm_plane_atomic_async_check,
+ .atomic_async_update = amdgpu_dm_plane_atomic_async_update
};
-static void dm_drm_plane_reset(struct drm_plane *plane)
+static void amdgpu_dm_plane_drm_plane_reset(struct drm_plane *plane)
{
struct dm_plane_state *amdgpu_state = NULL;
@@ -1337,8 +1341,7 @@ static void dm_drm_plane_reset(struct drm_plane *plane)
__drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
}
-static struct drm_plane_state *
-dm_drm_plane_duplicate_state(struct drm_plane *plane)
+static struct drm_plane_state *amdgpu_dm_plane_drm_plane_duplicate_state(struct drm_plane *plane)
{
struct dm_plane_state *dm_plane_state, *old_dm_plane_state;
@@ -1357,15 +1360,15 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
return &dm_plane_state->base;
}
-static bool dm_plane_format_mod_supported(struct drm_plane *plane,
- uint32_t format,
- uint64_t modifier)
+static bool amdgpu_dm_plane_format_mod_supported(struct drm_plane *plane,
+ uint32_t format,
+ uint64_t modifier)
{
struct amdgpu_device *adev = drm_to_adev(plane->dev);
const struct drm_format_info *info = drm_format_info(format);
int i;
- enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3;
+ enum dm_micro_swizzle microtile = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier) & 3;
if (!info)
return false;
@@ -1402,7 +1405,7 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane,
info->cpp[0] < 8)
return false;
- if (modifier_has_dcc(modifier)) {
+ if (amdgpu_dm_plane_modifier_has_dcc(modifier)) {
/* Per radeonsi comments 16/64 bpp are more complicated. */
if (info->cpp[0] != 4)
return false;
@@ -1416,8 +1419,8 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane,
return true;
}
-static void dm_drm_plane_destroy_state(struct drm_plane *plane,
- struct drm_plane_state *state)
+static void amdgpu_dm_plane_drm_plane_destroy_state(struct drm_plane *plane,
+ struct drm_plane_state *state)
{
struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
@@ -1431,10 +1434,10 @@ static const struct drm_plane_funcs dm_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = drm_plane_helper_destroy,
- .reset = dm_drm_plane_reset,
- .atomic_duplicate_state = dm_drm_plane_duplicate_state,
- .atomic_destroy_state = dm_drm_plane_destroy_state,
- .format_mod_supported = dm_plane_format_mod_supported,
+ .reset = amdgpu_dm_plane_drm_plane_reset,
+ .atomic_duplicate_state = amdgpu_dm_plane_drm_plane_duplicate_state,
+ .atomic_destroy_state = amdgpu_dm_plane_drm_plane_destroy_state,
+ .format_mod_supported = amdgpu_dm_plane_format_mod_supported,
};
int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
@@ -1448,10 +1451,10 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
unsigned int supported_rotations;
uint64_t *modifiers = NULL;
- num_formats = get_plane_formats(plane, plane_cap, formats,
- ARRAY_SIZE(formats));
+ num_formats = amdgpu_dm_plane_get_plane_formats(plane, plane_cap, formats,
+ ARRAY_SIZE(formats));
- res = get_plane_modifiers(dm->adev, plane->type, &modifiers);
+ res = amdgpu_dm_plane_get_plane_modifiers(dm->adev, plane->type, &modifiers);
if (res)
return res;
@@ -1508,7 +1511,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
supported_rotations);
- if (dm->adev->ip_versions[DCE_HWIP][0] > IP_VERSION(3, 0, 1) &&
+ if (amdgpu_ip_version(dm->adev, DCE_HWIP, 0) > IP_VERSION(3, 0, 1) &&
plane->type != DRM_PLANE_TYPE_CURSOR)
drm_plane_enable_fb_damage_clips(plane);
@@ -1521,7 +1524,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
return 0;
}
-bool is_video_format(uint32_t format)
+bool amdgpu_dm_plane_is_video_format(uint32_t format)
{
int i;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h
index 930f1572f898..b51a6b57bd9b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h
@@ -62,5 +62,5 @@ void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state
bool *per_pixel_alpha, bool *pre_multiplied_alpha,
bool *global_alpha, int *global_alpha_value);
-bool is_video_format(uint32_t format);
+bool amdgpu_dm_plane_is_video_format(uint32_t format);
#endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c
index 32d3086c4cb7..5ce542b1f860 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c
@@ -91,7 +91,7 @@ bool amdgpu_dm_setup_replay(struct dc_link *link, struct amdgpu_dm_connector *ac
pr_config.replay_supported = true;
pr_config.replay_power_opt_supported = 0;
pr_config.replay_enable_option |= pr_enable_option_static_screen;
- pr_config.replay_timing_sync_supported = aconnector->max_vfreq >= 2 * aconnector->min_vfreq ? true : false;
+ pr_config.replay_timing_sync_supported = aconnector->max_vfreq >= 2 * aconnector->min_vfreq;
if (!pr_config.replay_timing_sync_supported)
pr_config.replay_enable_option &= ~pr_enable_option_general_ui;
@@ -99,7 +99,7 @@ bool amdgpu_dm_setup_replay(struct dc_link *link, struct amdgpu_dm_connector *ac
debug_flags = (union replay_debug_flags *)&pr_config.debug_flags;
debug_flags->u32All = 0;
debug_flags->bitfields.visual_confirm =
- link->ctx->dc->debug.visual_confirm == VISUAL_CONFIRM_REPLAY ? true : false;
+ link->ctx->dc->debug.visual_confirm == VISUAL_CONFIRM_REPLAY;
link->replay_settings.replay_feature_enabled = true;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index 0f580ea37576..133af994a08c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -37,7 +37,7 @@
#include <drm/drm_framebuffer.h>
#include <drm/drm_encoder.h>
#include <drm/drm_atomic.h>
-#include "dcn10/dcn10_optc.h"
+#include "dc/inc/hw/optc.h"
#include "dc/inc/core_types.h"
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
index 172aa10a8800..4ae4720535a5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
@@ -60,11 +60,9 @@ static DEFINE_PER_CPU(int, fpu_recursion_depth);
*/
inline void dc_assert_fp_enabled(void)
{
- int *pcpu, depth = 0;
+ int depth;
- pcpu = get_cpu_ptr(&fpu_recursion_depth);
- depth = *pcpu;
- put_cpu_ptr(&fpu_recursion_depth);
+ depth = __this_cpu_read(fpu_recursion_depth);
ASSERT(depth >= 1);
}
@@ -84,33 +82,28 @@ inline void dc_assert_fp_enabled(void)
*/
void dc_fpu_begin(const char *function_name, const int line)
{
- int *pcpu;
+ int depth;
- pcpu = get_cpu_ptr(&fpu_recursion_depth);
- *pcpu += 1;
+ WARN_ON_ONCE(!in_task());
+ preempt_disable();
+ depth = __this_cpu_inc_return(fpu_recursion_depth);
- if (*pcpu == 1) {
+ if (depth == 1) {
#if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
- migrate_disable();
kernel_fpu_begin();
#elif defined(CONFIG_PPC64)
- if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
- preempt_disable();
+ if (cpu_has_feature(CPU_FTR_VSX_COMP))
enable_kernel_vsx();
- } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) {
- preempt_disable();
+ else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP))
enable_kernel_altivec();
- } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) {
- preempt_disable();
+ else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE))
enable_kernel_fp();
- }
#elif defined(CONFIG_ARM64)
kernel_neon_begin();
#endif
}
- TRACE_DCN_FPU(true, function_name, line, *pcpu);
- put_cpu_ptr(&fpu_recursion_depth);
+ TRACE_DCN_FPU(true, function_name, line, depth);
}
/**
@@ -125,30 +118,26 @@ void dc_fpu_begin(const char *function_name, const int line)
*/
void dc_fpu_end(const char *function_name, const int line)
{
- int *pcpu;
+ int depth;
- pcpu = get_cpu_ptr(&fpu_recursion_depth);
- *pcpu -= 1;
- if (*pcpu <= 0) {
+ depth = __this_cpu_dec_return(fpu_recursion_depth);
+ if (depth == 0) {
#if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
kernel_fpu_end();
- migrate_enable();
#elif defined(CONFIG_PPC64)
- if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
+ if (cpu_has_feature(CPU_FTR_VSX_COMP))
disable_kernel_vsx();
- preempt_enable();
- } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) {
+ else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP))
disable_kernel_altivec();
- preempt_enable();
- } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) {
+ else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE))
disable_kernel_fp();
- preempt_enable();
- }
#elif defined(CONFIG_ARM64)
kernel_neon_end();
#endif
+ } else {
+ WARN_ON_ONCE(depth < 0);
}
- TRACE_DCN_FPU(false, function_name, line, *pcpu);
- put_cpu_ptr(&fpu_recursion_depth);
+ TRACE_DCN_FPU(false, function_name, line, depth);
+ preempt_enable();
}
diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile
index 1b8c2aef4633..3a169b78e7e4 100644
--- a/drivers/gpu/drm/amd/display/dc/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/Makefile
@@ -22,14 +22,14 @@
#
# Makefile for Display Core (dc) component.
-DC_LIBS = basics bios dml clk_mgr dce gpio irq link virtual dsc
+DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtual dsc
ifdef CONFIG_DRM_AMD_DC_FP
KCOV_INSTRUMENT := n
-DC_LIBS += dcn20
DC_LIBS += dcn10
+DC_LIBS += dcn20
DC_LIBS += dcn21
DC_LIBS += dcn201
DC_LIBS += dcn30
@@ -42,6 +42,9 @@ DC_LIBS += dcn315
DC_LIBS += dcn316
DC_LIBS += dcn32
DC_LIBS += dcn321
+DC_LIBS += dcn35
+DC_LIBS += dml
+DC_LIBS += dml2
endif
DC_LIBS += dce120
diff --git a/drivers/gpu/drm/amd/display/dc/basics/Makefile b/drivers/gpu/drm/amd/display/dc/basics/Makefile
index 01b99e0d788e..aabcebf69049 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/basics/Makefile
@@ -24,7 +24,14 @@
# It provides the general basic services required by other DAL
# subcomponents.
-BASICS = conversion.o fixpt31_32.o vector.o dc_common.o
+BASICS := \
+ conversion.o \
+ fixpt31_32.o \
+ vector.o \
+ dc_common.o \
+ dce_calcs.o \
+ custom_float.o \
+ bw_fixed.o
AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS))
diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c b/drivers/gpu/drm/amd/display/dc/basics/bw_fixed.c
index 3aa8dd0acd5e..c8cb89e0d4d0 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/bw_fixed.c
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: MIT
/*
- * Copyright 2015 Advanced Micro Devices, Inc.
+ * Copyright 2023 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -106,9 +107,8 @@ struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator)
return res;
}
-struct bw_fixed bw_floor2(
- const struct bw_fixed arg,
- const struct bw_fixed significance)
+struct bw_fixed bw_floor2(const struct bw_fixed arg,
+ const struct bw_fixed significance)
{
struct bw_fixed result;
int64_t multiplicand;
@@ -119,9 +119,8 @@ struct bw_fixed bw_floor2(
return result;
}
-struct bw_fixed bw_ceil2(
- const struct bw_fixed arg,
- const struct bw_fixed significance)
+struct bw_fixed bw_ceil2(const struct bw_fixed arg,
+ const struct bw_fixed significance)
{
struct bw_fixed result;
int64_t multiplicand;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/calcs_logger.h b/drivers/gpu/drm/amd/display/dc/basics/calcs_logger.h
index 62435bfc274d..62435bfc274d 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/calcs/calcs_logger.h
+++ b/drivers/gpu/drm/amd/display/dc/basics/calcs_logger.h
diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/custom_float.c b/drivers/gpu/drm/amd/display/dc/basics/custom_float.c
index 31d167bc548f..ae05ded9a7f3 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/calcs/custom_float.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/custom_float.c
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: MIT
/*
- * Copyright 2017 Advanced Micro Devices, Inc.
+ * Copyright 2023 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -25,52 +26,41 @@
#include "dm_services.h"
#include "custom_float.h"
-
-static bool build_custom_float(
- struct fixed31_32 value,
- const struct custom_float_format *format,
- bool *negative,
- uint32_t *mantissa,
- uint32_t *exponenta)
+static bool build_custom_float(struct fixed31_32 value,
+ const struct custom_float_format *format,
+ bool *negative,
+ uint32_t *mantissa,
+ uint32_t *exponenta)
{
uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
const struct fixed31_32 mantissa_constant_plus_max_fraction =
- dc_fixpt_from_fraction(
- (1LL << (format->mantissa_bits + 1)) - 1,
- 1LL << format->mantissa_bits);
+ dc_fixpt_from_fraction((1LL << (format->mantissa_bits + 1)) - 1,
+ 1LL << format->mantissa_bits);
struct fixed31_32 mantiss;
- if (dc_fixpt_eq(
- value,
- dc_fixpt_zero)) {
+ if (dc_fixpt_eq(value, dc_fixpt_zero)) {
*negative = false;
*mantissa = 0;
*exponenta = 0;
return true;
}
- if (dc_fixpt_lt(
- value,
- dc_fixpt_zero)) {
+ if (dc_fixpt_lt(value, dc_fixpt_zero)) {
*negative = format->sign;
value = dc_fixpt_neg(value);
} else {
*negative = false;
}
- if (dc_fixpt_lt(
- value,
- dc_fixpt_one)) {
+ if (dc_fixpt_lt(value, dc_fixpt_one)) {
uint32_t i = 1;
do {
value = dc_fixpt_shl(value, 1);
++i;
- } while (dc_fixpt_lt(
- value,
- dc_fixpt_one));
+ } while (dc_fixpt_lt(value, dc_fixpt_one));
--i;
@@ -81,54 +71,40 @@ static bool build_custom_float(
}
*exponenta = exp_offset - i;
- } else if (dc_fixpt_le(
- mantissa_constant_plus_max_fraction,
- value)) {
+ } else if (dc_fixpt_le(mantissa_constant_plus_max_fraction, value)) {
uint32_t i = 1;
do {
value = dc_fixpt_shr(value, 1);
++i;
- } while (dc_fixpt_lt(
- mantissa_constant_plus_max_fraction,
- value));
+ } while (dc_fixpt_lt(mantissa_constant_plus_max_fraction, value));
*exponenta = exp_offset + i - 1;
} else {
*exponenta = exp_offset;
}
- mantiss = dc_fixpt_sub(
- value,
- dc_fixpt_one);
+ mantiss = dc_fixpt_sub(value, dc_fixpt_one);
- if (dc_fixpt_lt(
- mantiss,
- dc_fixpt_zero) ||
- dc_fixpt_lt(
- dc_fixpt_one,
- mantiss))
+ if (dc_fixpt_lt(mantiss, dc_fixpt_zero) ||
+ dc_fixpt_lt(dc_fixpt_one, mantiss))
mantiss = dc_fixpt_zero;
else
- mantiss = dc_fixpt_shl(
- mantiss,
- format->mantissa_bits);
+ mantiss = dc_fixpt_shl(mantiss, format->mantissa_bits);
*mantissa = dc_fixpt_floor(mantiss);
return true;
}
-static bool setup_custom_float(
- const struct custom_float_format *format,
- bool negative,
- uint32_t mantissa,
- uint32_t exponenta,
- uint32_t *result)
+static bool setup_custom_float(const struct custom_float_format *format,
+ bool negative,
+ uint32_t mantissa,
+ uint32_t exponenta,
+ uint32_t *result)
{
uint32_t i = 0;
uint32_t j = 0;
-
uint32_t value = 0;
/* verification code:
@@ -179,19 +155,19 @@ static bool setup_custom_float(
return true;
}
-bool convert_to_custom_float_format(
- struct fixed31_32 value,
- const struct custom_float_format *format,
- uint32_t *result)
+bool convert_to_custom_float_format(struct fixed31_32 value,
+ const struct custom_float_format *format,
+ uint32_t *result)
{
uint32_t mantissa;
uint32_t exponenta;
bool negative;
- return build_custom_float(
- value, format, &negative, &mantissa, &exponenta) &&
- setup_custom_float(
- format, negative, mantissa, exponenta, result);
+ return build_custom_float(value, format, &negative, &mantissa, &exponenta) &&
+ setup_custom_float(format,
+ negative,
+ mantissa,
+ exponenta,
+ result);
}
-
diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c
index f2dfa96f9ef5..f2dfa96f9ef5 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
index 6b3190447581..6450853fea94 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
@@ -2746,6 +2746,7 @@ static enum bp_result bios_get_board_layout_info(
struct board_layout_info *board_layout_info)
{
unsigned int i;
+ struct bios_parser *bp;
enum bp_result record_result;
const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
@@ -2754,6 +2755,8 @@ static enum bp_result bios_get_board_layout_info(
0, 0
};
+ bp = BP_FROM_DCB(dcb);
+
if (board_layout_info == NULL) {
DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
return BP_RESULT_BADINPUT;
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
index 484d62bcf2c2..6a96810a477e 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
@@ -355,7 +355,7 @@ static struct atom_display_object_path_v3 *get_bios_object_from_path_v3(struct b
&& id.enum_id == obj_id.enum_id)
return &bp->object_info_tbl.v1_5->display_path[i];
}
- break;
+ break;
case OBJECT_TYPE_CONNECTOR:
case OBJECT_TYPE_GENERIC:
@@ -369,7 +369,7 @@ static struct atom_display_object_path_v3 *get_bios_object_from_path_v3(struct b
&& id.enum_id == obj_id.enum_id)
return &bp->object_info_tbl.v1_5->display_path[i];
}
- break;
+ break;
default:
return NULL;
@@ -405,16 +405,16 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
}
switch (bp->object_info_tbl.revision.minor) {
- case 4:
- default:
- object = get_bios_object(bp, id);
+ case 4:
+ default:
+ object = get_bios_object(bp, id);
- if (!object)
- return BP_RESULT_BADINPUT;
+ if (!object)
+ return BP_RESULT_BADINPUT;
- offset = object->disp_recordoffset + bp->object_info_tbl_offset;
- break;
- case 5:
+ offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+ break;
+ case 5:
object_path_v3 = get_bios_object_from_path_v3(bp, id);
if (!object_path_v3)
@@ -568,17 +568,16 @@ static enum bp_result bios_parser_get_hpd_info(
return BP_RESULT_BADINPUT;
switch (bp->object_info_tbl.revision.minor) {
- case 4:
- default:
- object = get_bios_object(bp, id);
+ case 4:
+ default:
+ object = get_bios_object(bp, id);
if (!object)
return BP_RESULT_BADINPUT;
- record = get_hpd_record(bp, object);
-
- break;
- case 5:
+ record = get_hpd_record(bp, object);
+ break;
+ case 5:
object_path_v3 = get_bios_object_from_path_v3(bp, id);
if (!object_path_v3)
@@ -1723,15 +1722,6 @@ static void bios_parser_set_scratch_critical_state(
bios_set_scratch_critical_state(dcb, state);
}
-struct atom_dig_transmitter_info_header_v5_3 {
- struct atom_common_table_header table_header;
- uint16_t dpphy_hdmi_settings_offset;
- uint16_t dpphy_dvi_settings_offset;
- uint16_t dpphy_dp_setting_table_offset;
- uint16_t uniphy_xbar_settings_v2_table_offset;
- uint16_t dpphy_internal_reg_overide_offset;
-};
-
static enum bp_result bios_parser_get_firmware_info(
struct dc_bios *dcb,
struct dc_firmware_info *info)
@@ -1755,7 +1745,7 @@ static enum bp_result bios_parser_get_firmware_info(
case 2:
case 3:
result = get_firmware_info_v3_2(bp, info);
- break;
+ break;
case 4:
result = get_firmware_info_v3_4(bp, info);
break;
@@ -2215,10 +2205,8 @@ static enum bp_result bios_parser_get_disp_connector_caps_info(
{
struct bios_parser *bp = BP_FROM_DCB(dcb);
struct atom_display_object_path_v2 *object;
-
struct atom_display_object_path_v3 *object_path_v3;
struct atom_connector_caps_record *record_path_v3;
-
struct atom_disp_connector_caps_record *record = NULL;
if (!info)
@@ -2398,7 +2386,13 @@ static enum bp_result get_vram_info_v30(
return BP_RESULT_BADBIOSTABLE;
info->num_chans = info_v30->channel_num;
- info->dram_channel_width_bytes = (1 << info_v30->channel_width) / 8;
+ /* As suggested by VBIOS we should always use
+ * dram_channel_width_bytes = 2 when using VRAM
+ * table version 3.0. This is because the channel_width
+ * param in the VRAM info table is changed in 7000 series and
+ * no longer represents the memory channel width.
+ */
+ info->dram_channel_width_bytes = 2;
return result;
}
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
index 8538f13e01bf..9d347960e2b0 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
@@ -80,6 +80,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2(
case DCN_VERSION_3_16:
case DCN_VERSION_3_2:
case DCN_VERSION_3_21:
+ case DCN_VERSION_3_5:
*h = dal_cmd_tbl_helper_dce112_get_table2();
return true;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
index ad390e4cd0a9..1c443e549afa 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
@@ -172,4 +172,12 @@ AMD_DAL_CLK_MGR_DCN32 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn32/,$(CLK_MGR_DC
AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN32)
+###############################################################################
+# DCN35
+###############################################################################
+CLK_MGR_DCN35 = dcn35_smu.o dcn35_clk_mgr.o
+
+AMD_DAL_CLK_MGR_DCN35 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn35/,$(CLK_MGR_DCN35))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN35)
endif
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
index dcedf9645161..3e73c4e59d40 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
@@ -48,6 +48,7 @@
#include "dcn315/dcn315_clk_mgr.h"
#include "dcn316/dcn316_clk_mgr.h"
#include "dcn32/dcn32_clk_mgr.h"
+#include "dcn35/dcn35_clk_mgr.h"
int clk_mgr_helper_get_active_display_cnt(
struct dc *dc,
@@ -354,6 +355,19 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
}
break;
+ case AMDGPU_FAMILY_GC_11_5_0: {
+ struct clk_mgr_dcn35 *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL);
+
+ if (clk_mgr == NULL) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+ dcn35_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
+ return &clk_mgr->base.base;
+ }
+ break;
+
#endif /* CONFIG_DRM_AMD_DC_FP - Family RV */
default:
ASSERT(0); /* Unknown Asic */
@@ -405,6 +419,10 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base)
dcn314_clk_mgr_destroy(clk_mgr);
break;
+ case AMDGPU_FAMILY_GC_11_5_0:
+ dcn35_clk_mgr_destroy(clk_mgr);
+ break;
+
default:
break;
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce120/dce120_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce120/dce120_clk_mgr.c
index 5399b8cf6b75..c9ba7b3fd2c3 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce120/dce120_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce120/dce120_clk_mgr.c
@@ -30,7 +30,7 @@
#include "dce110/dce110_clk_mgr.h"
#include "dce120_clk_mgr.h"
#include "dce100/dce_clk_mgr.h"
-#include "dce120/dce120_hw_sequencer.h"
+#include "dce120/dce120_hwseq.h"
static const struct state_dependent_clocks dce120_max_clks_by_state[] = {
/*ClocksStateInvalid - should not be used*/
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c
index 694fe4271b4d..9c90090e7351 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c
@@ -59,8 +59,6 @@
#define CTX \
clk_mgr->base.ctx
-#define DC_LOGGER \
- clk_mgr->base.ctx->logger
static const struct clk_mgr_registers clk_mgr_regs = {
CLK_COMMON_REG_LIST_DCN_201()
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
index b2c4f97afc8b..8776055bbeaa 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
@@ -334,7 +334,7 @@ static struct wm_table lpddr5_wm_table = {
{
.wm_inst = WM_A,
.wm_type = WM_TYPE_PSTATE_CHG,
- .pstate_latency_us = 11.65333,
+ .pstate_latency_us = 129.0,
.sr_exit_time_us = 11.5,
.sr_enter_plus_exit_time_us = 14.5,
.valid = true,
@@ -342,7 +342,7 @@ static struct wm_table lpddr5_wm_table = {
{
.wm_inst = WM_B,
.wm_type = WM_TYPE_PSTATE_CHG,
- .pstate_latency_us = 11.65333,
+ .pstate_latency_us = 129.0,
.sr_exit_time_us = 11.5,
.sr_enter_plus_exit_time_us = 14.5,
.valid = true,
@@ -350,7 +350,7 @@ static struct wm_table lpddr5_wm_table = {
{
.wm_inst = WM_C,
.wm_type = WM_TYPE_PSTATE_CHG,
- .pstate_latency_us = 11.65333,
+ .pstate_latency_us = 129.0,
.sr_exit_time_us = 11.5,
.sr_enter_plus_exit_time_us = 14.5,
.valid = true,
@@ -358,7 +358,7 @@ static struct wm_table lpddr5_wm_table = {
{
.wm_inst = WM_D,
.wm_type = WM_TYPE_PSTATE_CHG,
- .pstate_latency_us = 11.65333,
+ .pstate_latency_us = 129.0,
.sr_exit_time_us = 11.5,
.sr_enter_plus_exit_time_us = 14.5,
.valid = true,
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dalsmc.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dalsmc.h
index c427be6add8a..724a508b0adb 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dalsmc.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dalsmc.h
@@ -55,7 +55,16 @@
#define DALSMC_MSG_SetFclkSwitchAllow 0x11
#define DALSMC_MSG_SetCabForUclkPstate 0x12
#define DALSMC_MSG_SetWorstCaseUclkLatency 0x13
-#define DALSMC_Message_Count 0x14
+#define DALSMC_MSG_SetAlwaysWaitDmcubResp 0x14
+#define DALSMC_MSG_ReturnHardMinStatus 0x15
+#define DALSMC_Message_Count 0x16
+
+#define CHECK_HARD_MIN_CLK_DISPCLK 0x1
+#define CHECK_HARD_MIN_CLK_DPPCLK 0x2
+#define CHECK_HARD_MIN_CLK_DPREFCLK 0x4
+#define CHECK_HARD_MIN_CLK_DCFCLK 0x8
+#define CHECK_HARD_MIN_CLK_DTBCLK 0x10
+#define CHECK_HARD_MIN_CLK_UCLK 0x20
typedef enum {
FCLK_SWITCH_DISALLOW,
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
index e9345f6554db..a496930b1f9c 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
@@ -53,6 +53,14 @@
#define mmCLK1_CLK3_DFS_CNTL 0x16E72
#define mmCLK1_CLK4_DFS_CNTL 0x16E75
+#define mmCLK1_CLK0_CURRENT_CNT 0x16EE7
+#define mmCLK1_CLK1_CURRENT_CNT 0x16EE8
+#define mmCLK1_CLK2_CURRENT_CNT 0x16EE9
+#define mmCLK1_CLK3_CURRENT_CNT 0x16EEA
+#define mmCLK1_CLK4_CURRENT_CNT 0x16EEB
+
+#define mmCLK4_CLK0_CURRENT_CNT 0x1B0C9
+
#define CLK1_CLK_PLL_REQ__FbMult_int_MASK 0x000001ffUL
#define CLK1_CLK_PLL_REQ__PllSpineDiv_MASK 0x0000f000UL
#define CLK1_CLK_PLL_REQ__FbMult_frac_MASK 0xffff0000UL
@@ -450,6 +458,58 @@ static int dcn32_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base)
return 0;
}
+static void dcn32_auto_dpm_test_log(struct dc_clocks *new_clocks, struct clk_mgr_internal *clk_mgr)
+{
+ unsigned int dispclk_khz_reg = REG_READ(CLK1_CLK0_CURRENT_CNT); // DISPCLK
+ unsigned int dppclk_khz_reg = REG_READ(CLK1_CLK1_CURRENT_CNT); // DPPCLK
+ unsigned int dprefclk_khz_reg = REG_READ(CLK1_CLK2_CURRENT_CNT); // DPREFCLK
+ unsigned int dcfclk_khz_reg = REG_READ(CLK1_CLK3_CURRENT_CNT); // DCFCLK
+ unsigned int dtbclk_khz_reg = REG_READ(CLK1_CLK4_CURRENT_CNT); // DTBCLK
+ unsigned int fclk_khz_reg = REG_READ(CLK4_CLK0_CURRENT_CNT); // FCLK
+
+ // Overrides for these clocks in case there is no p_state change support
+ int dramclk_khz_override = new_clocks->dramclk_khz;
+ int fclk_khz_override = new_clocks->fclk_khz;
+
+ int num_fclk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_fclk_levels - 1;
+
+ if (!new_clocks->p_state_change_support) {
+ dramclk_khz_override = clk_mgr->base.bw_params->max_memclk_mhz * 1000;
+ }
+ if (!new_clocks->fclk_p_state_change_support) {
+ fclk_khz_override = clk_mgr->base.bw_params->clk_table.entries[num_fclk_levels].fclk_mhz * 1000;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // IMPORTANT: When adding more clocks to these logs, do NOT put a newline
+ // anywhere other than at the very end of the string.
+ //
+ // Formatting example (make sure to have " - " between each entry):
+ //
+ // AutoDPMTest: clk1:%d - clk2:%d - clk3:%d - clk4:%d\n"
+ ////////////////////////////////////////////////////////////////////////////
+ if (new_clocks &&
+ new_clocks->dramclk_khz > 0 &&
+ new_clocks->fclk_khz > 0 &&
+ new_clocks->dcfclk_khz > 0 &&
+ new_clocks->dppclk_khz > 0) {
+
+ DC_LOG_AUTO_DPM_TEST("AutoDPMTest: dramclk:%d - fclk:%d - "
+ "dcfclk:%d - dppclk:%d - dispclk_hw:%d - "
+ "dppclk_hw:%d - dprefclk_hw:%d - dcfclk_hw:%d - "
+ "dtbclk_hw:%d - fclk_hw:%d\n",
+ dramclk_khz_override,
+ fclk_khz_override,
+ new_clocks->dcfclk_khz,
+ new_clocks->dppclk_khz,
+ dispclk_khz_reg,
+ dppclk_khz_reg,
+ dprefclk_khz_reg,
+ dcfclk_khz_reg,
+ dtbclk_khz_reg,
+ fclk_khz_reg);
+ }
+}
static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
struct dc_state *context,
@@ -646,6 +706,10 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
/*update dmcu for wait_loop count*/
dmcu->funcs->set_psr_wait_loop(dmcu,
clk_mgr_base->clks.dispclk_khz / 1000 / 7);
+
+ if (dc->config.enable_auto_dpm_test_logs) {
+ dcn32_auto_dpm_test_log(new_clocks, clk_mgr);
+ }
}
static uint32_t dcn32_get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c
index 700ce42036d7..df244b175fdb 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c
@@ -90,6 +90,64 @@ static bool dcn32_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr, uint
return false;
}
+/*
+ * Use these functions to return back delay information so we can aggregate the total
+ * delay when requesting hardmin clk
+ *
+ * dcn32_smu_wait_for_response_delay
+ * dcn32_smu_send_msg_with_param_delay
+ *
+ */
+static uint32_t dcn32_smu_wait_for_response_delay(struct clk_mgr_internal *clk_mgr, unsigned int delay_us, unsigned int max_retries, unsigned int *total_delay_us)
+{
+ uint32_t reg = 0;
+ *total_delay_us = 0;
+
+ do {
+ reg = REG_READ(DAL_RESP_REG);
+ if (reg)
+ break;
+
+ if (delay_us >= 1000)
+ msleep(delay_us/1000);
+ else if (delay_us > 0)
+ udelay(delay_us);
+ *total_delay_us += delay_us;
+ } while (max_retries--);
+
+ return reg;
+}
+
+static bool dcn32_smu_send_msg_with_param_delay(struct clk_mgr_internal *clk_mgr, uint32_t msg_id, uint32_t param_in, uint32_t *param_out, unsigned int *total_delay_us)
+{
+ unsigned int delay1_us, delay2_us;
+ *total_delay_us = 0;
+
+ /* Wait for response register to be ready */
+ dcn32_smu_wait_for_response_delay(clk_mgr, 10, 200000, &delay1_us);
+
+ /* Clear response register */
+ REG_WRITE(DAL_RESP_REG, 0);
+
+ /* Set the parameter register for the SMU message */
+ REG_WRITE(DAL_ARG_REG, param_in);
+
+ /* Trigger the message transaction by writing the message ID */
+ REG_WRITE(DAL_MSG_REG, msg_id);
+
+ /* Wait for response */
+ if (dcn32_smu_wait_for_response_delay(clk_mgr, 10, 200000, &delay2_us) == DALSMC_Result_OK) {
+ if (param_out)
+ *param_out = REG_READ(DAL_ARG_REG);
+
+ *total_delay_us = delay1_us + delay2_us;
+ return true;
+ }
+
+ *total_delay_us = delay1_us + 2000000;
+ return false;
+}
+
void dcn32_smu_send_fclk_pstate_message(struct clk_mgr_internal *clk_mgr, bool enable)
{
smu_print("FCLK P-state support value is : %d\n", enable);
@@ -122,10 +180,98 @@ void dcn32_smu_set_pme_workaround(struct clk_mgr_internal *clk_mgr)
DALSMC_MSG_BacoAudioD3PME, 0, NULL);
}
+/* Check PMFW version if it supports ReturnHardMinStatus message */
+static bool dcn32_get_hard_min_status_supported(struct clk_mgr_internal *clk_mgr)
+{
+ if (ASICREV_IS_GC_11_0_0(clk_mgr->base.ctx->asic_id.hw_internal_rev)) {
+ if (clk_mgr->smu_ver >= 0x4e6a00)
+ return true;
+ } else if (ASICREV_IS_GC_11_0_2(clk_mgr->base.ctx->asic_id.hw_internal_rev)) {
+ if (clk_mgr->smu_ver >= 0x524e00)
+ return true;
+ } else { /* ASICREV_IS_GC_11_0_3 */
+ if (clk_mgr->smu_ver >= 0x503900)
+ return true;
+ }
+ return false;
+}
+
+/* Returns the clocks which were fulfilled by the DAL hard min arbiter in PMFW */
+static unsigned int dcn32_smu_get_hard_min_status(struct clk_mgr_internal *clk_mgr, bool *no_timeout, unsigned int *total_delay_us)
+{
+ uint32_t response = 0;
+
+ /* bits 23:16 for clock type, lower 16 bits for frequency in MHz */
+ uint32_t param = 0;
+
+ *no_timeout = dcn32_smu_send_msg_with_param_delay(clk_mgr,
+ DALSMC_MSG_ReturnHardMinStatus, param, &response, total_delay_us);
+
+ smu_print("SMU Get hard min status: no_timeout %d delay %d us clk bits %x\n",
+ *no_timeout, *total_delay_us, response);
+
+ return response;
+}
+
+static bool dcn32_smu_wait_get_hard_min_status(struct clk_mgr_internal *clk_mgr,
+ uint32_t clk)
+{
+ int readDalHardMinClkBits, checkDalHardMinClkBits;
+ unsigned int total_delay_us, read_total_delay_us;
+ bool no_timeout, hard_min_done;
+
+ static unsigned int cur_wait_get_hard_min_max_us;
+ static unsigned int cur_wait_get_hard_min_max_timeouts;
+
+ checkDalHardMinClkBits = CHECK_HARD_MIN_CLK_DPREFCLK;
+ if (clk == PPCLK_DISPCLK)
+ checkDalHardMinClkBits |= CHECK_HARD_MIN_CLK_DISPCLK;
+ if (clk == PPCLK_DPPCLK)
+ checkDalHardMinClkBits |= CHECK_HARD_MIN_CLK_DPPCLK;
+ if (clk == PPCLK_DCFCLK)
+ checkDalHardMinClkBits |= CHECK_HARD_MIN_CLK_DCFCLK;
+ if (clk == PPCLK_DTBCLK)
+ checkDalHardMinClkBits |= CHECK_HARD_MIN_CLK_DTBCLK;
+ if (clk == PPCLK_UCLK)
+ checkDalHardMinClkBits |= CHECK_HARD_MIN_CLK_UCLK;
+
+ if (checkDalHardMinClkBits == CHECK_HARD_MIN_CLK_DPREFCLK)
+ return 0;
+
+ total_delay_us = 0;
+ hard_min_done = false;
+ while (1) {
+ readDalHardMinClkBits = dcn32_smu_get_hard_min_status(clk_mgr, &no_timeout, &read_total_delay_us);
+ total_delay_us += read_total_delay_us;
+ if (checkDalHardMinClkBits == (readDalHardMinClkBits & checkDalHardMinClkBits)) {
+ hard_min_done = true;
+ break;
+ }
+
+
+ if (total_delay_us >= 2000000) {
+ cur_wait_get_hard_min_max_timeouts++;
+ smu_print("SMU Wait get hard min status: %d timeouts\n", cur_wait_get_hard_min_max_timeouts);
+ break;
+ }
+ msleep(1);
+ total_delay_us += 1000;
+ }
+
+ if (total_delay_us > cur_wait_get_hard_min_max_us)
+ cur_wait_get_hard_min_max_us = total_delay_us;
+
+ smu_print("SMU Wait get hard min status: no_timeout %d, delay %d us, max %d us, read %x, check %x\n",
+ no_timeout, total_delay_us, cur_wait_get_hard_min_max_us, readDalHardMinClkBits, checkDalHardMinClkBits);
+
+ return hard_min_done;
+}
+
/* Returns the actual frequency that was set in MHz, 0 on failure */
unsigned int dcn32_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, uint32_t clk, uint16_t freq_mhz)
{
uint32_t response = 0;
+ bool hard_min_done = false;
/* bits 23:16 for clock type, lower 16 bits for frequency in MHz */
uint32_t param = (clk << 16) | freq_mhz;
@@ -133,9 +279,13 @@ unsigned int dcn32_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, ui
smu_print("SMU Set hard min by freq: clk = %d, freq_mhz = %d MHz\n", clk, freq_mhz);
dcn32_smu_send_msg_with_param(clk_mgr,
- DALSMC_MSG_SetHardMinByFreq, param, &response);
+ DALSMC_MSG_SetHardMinByFreq, param, &response);
- smu_print("SMU Frequency set = %d KHz\n", response);
+ if (dcn32_get_hard_min_status_supported(clk_mgr)) {
+ hard_min_done = dcn32_smu_wait_get_hard_min_status(clk_mgr, clk);
+ smu_print("SMU Frequency set = %d KHz hard_min_done %d\n", response, hard_min_done);
+ } else
+ smu_print("SMU Frequency set = %d KHz\n", response);
return response;
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
new file mode 100644
index 000000000000..d5fde7d23fbf
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
@@ -0,0 +1,1146 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+
+#include "dcn35_clk_mgr.h"
+
+#include "dccg.h"
+#include "clk_mgr_internal.h"
+
+// For dce12_get_dp_ref_freq_khz
+#include "dce100/dce_clk_mgr.h"
+
+// For dcn20_update_clocks_update_dpp_dto
+#include "dcn20/dcn20_clk_mgr.h"
+
+
+
+
+#include "reg_helper.h"
+#include "core_types.h"
+#include "dcn35_smu.h"
+#include "dm_helpers.h"
+
+/* TODO: remove this include once we ported over remaining clk mgr functions*/
+#include "dcn30/dcn30_clk_mgr.h"
+#include "dcn31/dcn31_clk_mgr.h"
+
+#include "dc_dmub_srv.h"
+#include "link.h"
+#include "logger_types.h"
+#undef DC_LOGGER
+#define DC_LOGGER \
+ clk_mgr->base.base.ctx->logger
+
+#define regCLK1_CLK_PLL_REQ 0x0237
+#define regCLK1_CLK_PLL_REQ_BASE_IDX 0
+
+#define CLK1_CLK_PLL_REQ__FbMult_int__SHIFT 0x0
+#define CLK1_CLK_PLL_REQ__PllSpineDiv__SHIFT 0xc
+#define CLK1_CLK_PLL_REQ__FbMult_frac__SHIFT 0x10
+#define CLK1_CLK_PLL_REQ__FbMult_int_MASK 0x000001FFL
+#define CLK1_CLK_PLL_REQ__PllSpineDiv_MASK 0x0000F000L
+#define CLK1_CLK_PLL_REQ__FbMult_frac_MASK 0xFFFF0000L
+
+#define regCLK1_CLK2_BYPASS_CNTL 0x029c
+#define regCLK1_CLK2_BYPASS_CNTL_BASE_IDX 0
+
+#define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL__SHIFT 0x0
+#define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV__SHIFT 0x10
+#define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL_MASK 0x00000007L
+#define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV_MASK 0x000F0000L
+
+#define REG(reg_name) \
+ (ctx->clk_reg_offsets[reg ## reg_name ## _BASE_IDX] + reg ## reg_name)
+
+#define TO_CLK_MGR_DCN35(clk_mgr)\
+ container_of(clk_mgr, struct clk_mgr_dcn35, base)
+
+static int dcn35_get_active_display_cnt_wa(
+ struct dc *dc,
+ struct dc_state *context)
+{
+ int i, display_count;
+ bool tmds_present = false;
+
+ display_count = 0;
+ for (i = 0; i < context->stream_count; i++) {
+ const struct dc_stream_state *stream = context->streams[i];
+
+ if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
+ stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
+ stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
+ tmds_present = true;
+ }
+
+ for (i = 0; i < dc->link_count; i++) {
+ const struct dc_link *link = dc->links[i];
+
+ /* abusing the fact that the dig and phy are coupled to see if the phy is enabled */
+ if (link->link_enc && link->link_enc->funcs->is_dig_enabled &&
+ link->link_enc->funcs->is_dig_enabled(link->link_enc))
+ display_count++;
+ }
+
+ /* WA for hang on HDMI after display off back on*/
+ if (display_count == 0 && tmds_present)
+ display_count = 1;
+
+ return display_count;
+}
+
+static void dcn35_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context,
+ bool safe_to_lower, bool disable)
+{
+ struct dc *dc = clk_mgr_base->ctx->dc;
+ int i;
+
+ for (i = 0; i < dc->res_pool->pipe_count; ++i) {
+ struct pipe_ctx *pipe = safe_to_lower
+ ? &context->res_ctx.pipe_ctx[i]
+ : &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (pipe->top_pipe || pipe->prev_odm_pipe)
+ continue;
+ if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) ||
+ !pipe->stream->link_enc)) {
+ struct stream_encoder *stream_enc = pipe->stream_res.stream_enc;
+
+ if (disable) {
+ if (stream_enc && stream_enc->funcs->disable_fifo)
+ pipe->stream_res.stream_enc->funcs->disable_fifo(stream_enc);
+
+ if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->immediate_disable_crtc)
+ pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
+
+ reset_sync_context_for_pipe(dc, context, i);
+ } else {
+ pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
+
+ if (stream_enc && stream_enc->funcs->enable_fifo)
+ pipe->stream_res.stream_enc->funcs->enable_fifo(stream_enc);
+ }
+ }
+ }
+}
+
+static void dcn35_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
+ struct dc_state *context,
+ int ref_dtbclk_khz)
+{
+ struct dccg *dccg = clk_mgr->dccg;
+ uint32_t tg_mask = 0;
+ int i;
+
+ for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+ struct dtbclk_dto_params dto_params = {0};
+
+ /* use mask to program DTO once per tg */
+ if (pipe_ctx->stream_res.tg &&
+ !(tg_mask & (1 << pipe_ctx->stream_res.tg->inst))) {
+ tg_mask |= (1 << pipe_ctx->stream_res.tg->inst);
+
+ dto_params.otg_inst = pipe_ctx->stream_res.tg->inst;
+ dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
+
+ dccg->funcs->set_dtbclk_dto(clk_mgr->dccg, &dto_params);
+ //dccg->funcs->set_audio_dtbclk_dto(clk_mgr->dccg, &dto_params);
+ }
+ }
+}
+
+static void dcn35_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr,
+ struct dc_state *context, bool safe_to_lower)
+{
+ int i;
+ bool dppclk_active[MAX_PIPES] = {0};
+
+
+ clk_mgr->dccg->ref_dppclk = clk_mgr->base.clks.dppclk_khz;
+ for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
+ int dpp_inst = 0, dppclk_khz, prev_dppclk_khz;
+
+ dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz;
+
+ if (context->res_ctx.pipe_ctx[i].plane_res.dpp)
+ dpp_inst = context->res_ctx.pipe_ctx[i].plane_res.dpp->inst;
+ else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz == 0) {
+ /* dpp == NULL && dppclk_khz == 0 is valid because of pipe harvesting.
+ * In this case just continue in loop
+ */
+ continue;
+ } else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz > 0) {
+ /* The software state is not valid if dpp resource is NULL and
+ * dppclk_khz > 0.
+ */
+ ASSERT(false);
+ continue;
+ }
+
+ prev_dppclk_khz = clk_mgr->dccg->pipe_dppclk_khz[i];
+
+ if (safe_to_lower || prev_dppclk_khz < dppclk_khz)
+ clk_mgr->dccg->funcs->update_dpp_dto(
+ clk_mgr->dccg, dpp_inst, dppclk_khz);
+ dppclk_active[dpp_inst] = true;
+ }
+ if (safe_to_lower)
+ for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
+ struct dpp *old_dpp = clk_mgr->base.ctx->dc->current_state->res_ctx.pipe_ctx[i].plane_res.dpp;
+
+ if (old_dpp && !dppclk_active[old_dpp->inst])
+ clk_mgr->dccg->funcs->update_dpp_dto(clk_mgr->dccg, old_dpp->inst, 0);
+ }
+}
+
+void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
+ struct dc_state *context,
+ bool safe_to_lower)
+{
+ union dmub_rb_cmd cmd;
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
+ struct dc *dc = clk_mgr_base->ctx->dc;
+ int display_count;
+ bool update_dppclk = false;
+ bool update_dispclk = false;
+ bool dpp_clock_lowered = false;
+
+ if (dc->work_arounds.skip_clock_update)
+ return;
+
+ /* DTBCLK is fixed, so set a default if unspecified. */
+ if (new_clocks->dtbclk_en && !new_clocks->ref_dtbclk_khz)
+ new_clocks->ref_dtbclk_khz = 600000;
+
+ /*
+ * if it is safe to lower, but we are already in the lower state, we don't have to do anything
+ * also if safe to lower is false, we just go in the higher state
+ */
+ if (safe_to_lower) {
+ if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
+ new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
+ dcn35_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
+ dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
+ clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
+ }
+
+ if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) {
+ dcn35_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 = dcn35_get_active_display_cnt_wa(dc, context);
+ /* if we can go lower, go lower */
+ if (display_count == 0)
+ clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
+ }
+ } else {
+ if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
+ new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
+ dcn35_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
+ dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
+ clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
+ }
+
+ if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
+ dcn35_smu_set_dtbclk(clk_mgr, true);
+ clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
+
+ dcn35_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
+ clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;
+ }
+
+ /* 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 };
+
+ dcn35_smu_set_display_idle_optimization(clk_mgr, idle_info.data);
+ /* update power state */
+ clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_MISSION_MODE;
+ }
+ }
+ if (dc->debug.force_min_dcfclk_mhz > 0)
+ new_clocks->dcfclk_khz = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ?
+ new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000);
+
+ if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
+ clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
+ dcn35_smu_set_hard_min_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_khz);
+ }
+
+ if (should_set_clock(safe_to_lower,
+ new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
+ clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
+ dcn35_smu_set_min_deep_sleep_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz);
+ }
+
+ // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
+ if (new_clocks->dppclk_khz < 100000)
+ new_clocks->dppclk_khz = 100000;
+
+ if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
+ if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
+ dpp_clock_lowered = true;
+ clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
+ update_dppclk = true;
+ }
+
+ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
+ dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true);
+
+ clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
+ dcn35_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz);
+ dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false);
+
+ update_dispclk = true;
+ }
+
+ /* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */
+ if (!dc->debug.disable_dtb_ref_clk_switch &&
+ should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000,
+ clk_mgr_base->clks.ref_dtbclk_khz / 1000)) {
+ dcn35_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
+ clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;
+ }
+
+ if (dpp_clock_lowered) {
+ // increase per DPP DTO before lowering global dppclk
+ dcn35_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
+ dcn35_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
+ } else {
+ // increase global DPPCLK before lowering per DPP DTO
+ if (update_dppclk || update_dispclk)
+ dcn35_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
+ dcn35_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
+ }
+
+ // notify DMCUB of latest clocks
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.notify_clocks.header.type = DMUB_CMD__CLK_MGR;
+ cmd.notify_clocks.header.sub_type = DMUB_CMD__CLK_MGR_NOTIFY_CLOCKS;
+ cmd.notify_clocks.clocks.dcfclk_khz = clk_mgr_base->clks.dcfclk_khz;
+ cmd.notify_clocks.clocks.dcfclk_deep_sleep_khz =
+ clk_mgr_base->clks.dcfclk_deep_sleep_khz;
+ cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz;
+ cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz;
+
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+}
+
+static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr)
+{
+ /* get FbMult value */
+ struct fixed31_32 pll_req;
+ unsigned int fbmult_frac_val = 0;
+ unsigned int fbmult_int_val = 0;
+ struct dc_context *ctx = clk_mgr->base.ctx;
+
+ /*
+ * Register value of fbmult is in 8.16 format, we are converting to 314.32
+ * to leverage the fix point operations available in driver
+ */
+
+ REG_GET(CLK1_CLK_PLL_REQ, FbMult_frac, &fbmult_frac_val); /* 16 bit fractional part*/
+ REG_GET(CLK1_CLK_PLL_REQ, FbMult_int, &fbmult_int_val); /* 8 bit integer part */
+
+ pll_req = dc_fixpt_from_int(fbmult_int_val);
+
+ /*
+ * since fractional part is only 16 bit in register definition but is 32 bit
+ * in our fix point definiton, need to shift left by 16 to obtain correct value
+ */
+ pll_req.value |= fbmult_frac_val << 16;
+
+ /* multiply by REFCLK period */
+ pll_req = dc_fixpt_mul_int(pll_req, clk_mgr->dfs_ref_freq_khz);
+
+ /* integer part is now VCO frequency in kHz */
+ return dc_fixpt_floor(pll_req);
+}
+
+static void dcn35_enable_pme_wa(struct clk_mgr *clk_mgr_base)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+ dcn35_smu_enable_pme_wa(clk_mgr);
+}
+
+void dcn35_init_clocks(struct clk_mgr *clk_mgr)
+{
+ uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz;
+
+ memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
+
+ // Assumption is that boot state always supports pstate
+ clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk; // restore ref_dtbclk
+ clk_mgr->clks.p_state_change_support = true;
+ clk_mgr->clks.prev_p_state_change_support = true;
+ clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN;
+ clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN;
+}
+
+bool dcn35_are_clock_states_equal(struct dc_clocks *a,
+ struct dc_clocks *b)
+{
+ if (a->dispclk_khz != b->dispclk_khz)
+ return false;
+ else if (a->dppclk_khz != b->dppclk_khz)
+ return false;
+ else if (a->dcfclk_khz != b->dcfclk_khz)
+ return false;
+ else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
+ return false;
+ else if (a->zstate_support != b->zstate_support)
+ return false;
+ else if (a->dtbclk_en != b->dtbclk_en)
+ return false;
+
+ return true;
+}
+
+static void dcn35_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
+ struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
+{
+
+}
+
+static struct clk_bw_params dcn35_bw_params = {
+ .vram_type = Ddr4MemType,
+ .num_channels = 1,
+ .clk_table = {
+ .num_entries = 4,
+ },
+
+};
+
+static struct wm_table ddr5_wm_table = {
+ .entries = {
+ {
+ .wm_inst = WM_A,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.72,
+ .sr_exit_time_us = 14.0,
+ .sr_enter_plus_exit_time_us = 16.0,
+ .valid = true,
+ },
+ {
+ .wm_inst = WM_B,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.72,
+ .sr_exit_time_us = 14.0,
+ .sr_enter_plus_exit_time_us = 16.0,
+ .valid = true,
+ },
+ {
+ .wm_inst = WM_C,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.72,
+ .sr_exit_time_us = 14.0,
+ .sr_enter_plus_exit_time_us = 16.0,
+ .valid = true,
+ },
+ {
+ .wm_inst = WM_D,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.72,
+ .sr_exit_time_us = 14.0,
+ .sr_enter_plus_exit_time_us = 16.0,
+ .valid = true,
+ },
+ }
+};
+
+static struct wm_table lpddr5_wm_table = {
+ .entries = {
+ {
+ .wm_inst = WM_A,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.65333,
+ .sr_exit_time_us = 14.0,
+ .sr_enter_plus_exit_time_us = 16.0,
+ .valid = true,
+ },
+ {
+ .wm_inst = WM_B,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.65333,
+ .sr_exit_time_us = 14.0,
+ .sr_enter_plus_exit_time_us = 16.0,
+ .valid = true,
+ },
+ {
+ .wm_inst = WM_C,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.65333,
+ .sr_exit_time_us = 14.0,
+ .sr_enter_plus_exit_time_us = 16.0,
+ .valid = true,
+ },
+ {
+ .wm_inst = WM_D,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.65333,
+ .sr_exit_time_us = 14.0,
+ .sr_enter_plus_exit_time_us = 16.0,
+ .valid = true,
+ },
+ }
+};
+
+static DpmClocks_t_dcn35 dummy_clocks;
+
+static struct dcn35_watermarks dummy_wms = { 0 };
+
+static void dcn35_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn35_watermarks *table)
+{
+ int i, num_valid_sets;
+
+ num_valid_sets = 0;
+
+ for (i = 0; i < WM_SET_COUNT; i++) {
+ /* skip empty entries, the smu array has no holes*/
+ if (!bw_params->wm_table.entries[i].valid)
+ continue;
+
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmSetting = bw_params->wm_table.entries[i].wm_inst;
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType = bw_params->wm_table.entries[i].wm_type;
+ /* We will not select WM based on fclk, so leave it as unconstrained */
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0;
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF;
+
+ if (table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType == WM_TYPE_PSTATE_CHG) {
+ if (i == 0)
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk = 0;
+ else {
+ /* add 1 to make it non-overlapping with next lvl */
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk =
+ bw_params->clk_table.entries[i - 1].dcfclk_mhz + 1;
+ }
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxMclk =
+ bw_params->clk_table.entries[i].dcfclk_mhz;
+
+ } else {
+ /* unconstrained for memory retraining */
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0;
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF;
+
+ /* Modify previous watermark range to cover up to max */
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF;
+ }
+ num_valid_sets++;
+ }
+
+ ASSERT(num_valid_sets != 0); /* Must have at least one set of valid watermarks */
+
+ /* modify the min and max to make sure we cover the whole range*/
+ table->WatermarkRow[WM_DCFCLK][0].MinMclk = 0;
+ table->WatermarkRow[WM_DCFCLK][0].MinClock = 0;
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxMclk = 0xFFFF;
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF;
+
+ /* This is for writeback only, does not matter currently as no writeback support*/
+ table->WatermarkRow[WM_SOCCLK][0].WmSetting = WM_A;
+ table->WatermarkRow[WM_SOCCLK][0].MinClock = 0;
+ table->WatermarkRow[WM_SOCCLK][0].MaxClock = 0xFFFF;
+ table->WatermarkRow[WM_SOCCLK][0].MinMclk = 0;
+ table->WatermarkRow[WM_SOCCLK][0].MaxMclk = 0xFFFF;
+}
+
+static void dcn35_notify_wm_ranges(struct clk_mgr *clk_mgr_base)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ struct clk_mgr_dcn35 *clk_mgr_dcn35 = TO_CLK_MGR_DCN35(clk_mgr);
+ struct dcn35_watermarks *table = clk_mgr_dcn35->smu_wm_set.wm_set;
+
+ if (!clk_mgr->smu_ver)
+ return;
+
+ if (!table || clk_mgr_dcn35->smu_wm_set.mc_address.quad_part == 0)
+ return;
+
+ memset(table, 0, sizeof(*table));
+
+ dcn35_build_watermark_ranges(clk_mgr_base->bw_params, table);
+
+ dcn35_smu_set_dram_addr_high(clk_mgr,
+ clk_mgr_dcn35->smu_wm_set.mc_address.high_part);
+ dcn35_smu_set_dram_addr_low(clk_mgr,
+ clk_mgr_dcn35->smu_wm_set.mc_address.low_part);
+ dcn35_smu_transfer_wm_table_dram_2_smu(clk_mgr);
+}
+
+static void dcn35_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr,
+ struct dcn35_smu_dpm_clks *smu_dpm_clks)
+{
+ DpmClocks_t_dcn35 *table = smu_dpm_clks->dpm_clks;
+
+ if (!clk_mgr->smu_ver)
+ return;
+
+ if (!table || smu_dpm_clks->mc_address.quad_part == 0)
+ return;
+
+ memset(table, 0, sizeof(*table));
+
+ dcn35_smu_set_dram_addr_high(clk_mgr,
+ smu_dpm_clks->mc_address.high_part);
+ dcn35_smu_set_dram_addr_low(clk_mgr,
+ smu_dpm_clks->mc_address.low_part);
+ dcn35_smu_transfer_dpm_table_smu_2_dram(clk_mgr);
+}
+
+static uint32_t find_max_clk_value(const uint32_t clocks[], uint32_t num_clocks)
+{
+ uint32_t max = 0;
+ int i;
+
+ for (i = 0; i < num_clocks; ++i) {
+ if (clocks[i] > max)
+ max = clocks[i];
+ }
+
+ return max;
+}
+
+static inline bool is_valid_clock_value(uint32_t clock_value)
+{
+ return clock_value > 1 && clock_value < 100000;
+}
+
+static unsigned int convert_wck_ratio(uint8_t wck_ratio)
+{
+ switch (wck_ratio) {
+ case WCK_RATIO_1_2:
+ return 2;
+
+ case WCK_RATIO_1_4:
+ return 4;
+ /* Find lowest DPM, FCLK is filled in reverse order*/
+
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+static inline uint32_t calc_dram_speed_mts(const MemPstateTable_t *entry)
+{
+ return entry->UClk * convert_wck_ratio(entry->WckRatio) * 2;
+}
+
+static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk_mgr,
+ struct integrated_info *bios_info,
+ DpmClocks_t_dcn35 *clock_table)
+{
+ struct clk_bw_params *bw_params = clk_mgr->base.bw_params;
+ struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1];
+ uint32_t max_fclk = 0, min_pstate = 0, max_dispclk = 0, max_dppclk = 0;
+ uint32_t max_pstate = 0, max_dram_speed_mts = 0, min_dram_speed_mts = 0;
+ int i;
+
+ /* Determine min/max p-state values. */
+ for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) {
+ uint32_t dram_speed_mts = calc_dram_speed_mts(&clock_table->MemPstateTable[i]);
+
+ if (is_valid_clock_value(dram_speed_mts) && dram_speed_mts > max_dram_speed_mts) {
+ max_dram_speed_mts = dram_speed_mts;
+ max_pstate = i;
+ }
+ }
+
+ min_dram_speed_mts = max_dram_speed_mts;
+ min_pstate = max_pstate;
+
+ for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) {
+ uint32_t dram_speed_mts = calc_dram_speed_mts(&clock_table->MemPstateTable[i]);
+
+ if (is_valid_clock_value(dram_speed_mts) && dram_speed_mts < min_dram_speed_mts) {
+ min_dram_speed_mts = dram_speed_mts;
+ min_pstate = i;
+ }
+ }
+
+ /* We expect the table to contain at least one valid P-state entry. */
+ ASSERT(clock_table->NumMemPstatesEnabled &&
+ is_valid_clock_value(max_dram_speed_mts) &&
+ is_valid_clock_value(min_dram_speed_mts));
+
+ /* dispclk and dppclk can be max at any voltage, same number of levels for both */
+ if (clock_table->NumDispClkLevelsEnabled <= NUM_DISPCLK_DPM_LEVELS &&
+ clock_table->NumDispClkLevelsEnabled <= NUM_DPPCLK_DPM_LEVELS) {
+ max_dispclk = find_max_clk_value(clock_table->DispClocks,
+ clock_table->NumDispClkLevelsEnabled);
+ max_dppclk = find_max_clk_value(clock_table->DppClocks,
+ clock_table->NumDispClkLevelsEnabled);
+ } else {
+ /* Invalid number of entries in the table from PMFW. */
+ ASSERT(0);
+ }
+
+ /* Base the clock table on dcfclk, need at least one entry regardless of pmfw table */
+ ASSERT(clock_table->NumDcfClkLevelsEnabled > 0);
+
+ max_fclk = find_max_clk_value(clock_table->FclkClocks_Freq, clock_table->NumFclkLevelsEnabled);
+
+ for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) {
+ int j;
+
+ /* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */
+ for (j = bw_params->clk_table.num_entries - 1; j > 0; j--)
+ if (bw_params->clk_table.entries[j].dcfclk_mhz <= clock_table->DcfClocks[i])
+ break;
+
+ bw_params->clk_table.entries[i].phyclk_mhz = bw_params->clk_table.entries[j].phyclk_mhz;
+ bw_params->clk_table.entries[i].phyclk_d18_mhz = bw_params->clk_table.entries[j].phyclk_d18_mhz;
+ bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz;
+
+ /* Now update clocks we do read */
+ bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemPstateTable[min_pstate].MemClk;
+ bw_params->clk_table.entries[i].voltage = clock_table->MemPstateTable[min_pstate].Voltage;
+ bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i];
+ bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i];
+ bw_params->clk_table.entries[i].dispclk_mhz = max_dispclk;
+ bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk;
+ bw_params->clk_table.entries[i].wck_ratio =
+ convert_wck_ratio(clock_table->MemPstateTable[min_pstate].WckRatio);
+
+ /* Dcfclk and Fclk are tied, but at a different ratio */
+ bw_params->clk_table.entries[i].fclk_mhz = min(max_fclk, 2 * clock_table->DcfClocks[i]);
+ }
+
+ /* Make sure to include at least one entry at highest pstate */
+ if (max_pstate != min_pstate || i == 0) {
+ if (i > MAX_NUM_DPM_LVL - 1)
+ i = MAX_NUM_DPM_LVL - 1;
+
+ bw_params->clk_table.entries[i].fclk_mhz = max_fclk;
+ bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemPstateTable[max_pstate].MemClk;
+ bw_params->clk_table.entries[i].voltage = clock_table->MemPstateTable[max_pstate].Voltage;
+ bw_params->clk_table.entries[i].dcfclk_mhz =
+ find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS);
+ bw_params->clk_table.entries[i].socclk_mhz =
+ find_max_clk_value(clock_table->SocClocks, NUM_SOCCLK_DPM_LEVELS);
+ bw_params->clk_table.entries[i].dispclk_mhz = max_dispclk;
+ bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk;
+ bw_params->clk_table.entries[i].wck_ratio = convert_wck_ratio(
+ clock_table->MemPstateTable[max_pstate].WckRatio);
+ i++;
+ }
+ bw_params->clk_table.num_entries = i--;
+
+ /* Make sure all highest clocks are included*/
+ bw_params->clk_table.entries[i].socclk_mhz =
+ find_max_clk_value(clock_table->SocClocks, NUM_SOCCLK_DPM_LEVELS);
+ bw_params->clk_table.entries[i].dispclk_mhz =
+ find_max_clk_value(clock_table->DispClocks, NUM_DISPCLK_DPM_LEVELS);
+ bw_params->clk_table.entries[i].dppclk_mhz =
+ find_max_clk_value(clock_table->DppClocks, NUM_DPPCLK_DPM_LEVELS);
+ bw_params->clk_table.entries[i].fclk_mhz =
+ find_max_clk_value(clock_table->FclkClocks_Freq, NUM_FCLK_DPM_LEVELS);
+ ASSERT(clock_table->DcfClocks[i] == find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS));
+ bw_params->clk_table.entries[i].phyclk_mhz = def_max.phyclk_mhz;
+ bw_params->clk_table.entries[i].phyclk_d18_mhz = def_max.phyclk_d18_mhz;
+ bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz;
+ bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels = clock_table->NumDcfClkLevelsEnabled;
+ bw_params->clk_table.num_entries_per_clk.num_dispclk_levels = clock_table->NumDispClkLevelsEnabled;
+ bw_params->clk_table.num_entries_per_clk.num_dppclk_levels = clock_table->NumDispClkLevelsEnabled;
+ bw_params->clk_table.num_entries_per_clk.num_fclk_levels = clock_table->NumFclkLevelsEnabled;
+ bw_params->clk_table.num_entries_per_clk.num_memclk_levels = clock_table->NumMemPstatesEnabled;
+ bw_params->clk_table.num_entries_per_clk.num_socclk_levels = clock_table->NumSocClkLevelsEnabled;
+
+ /*
+ * Set any 0 clocks to max default setting. Not an issue for
+ * power since we aren't doing switching in such case anyway
+ */
+ for (i = 0; i < bw_params->clk_table.num_entries; i++) {
+ if (!bw_params->clk_table.entries[i].fclk_mhz) {
+ bw_params->clk_table.entries[i].fclk_mhz = def_max.fclk_mhz;
+ bw_params->clk_table.entries[i].memclk_mhz = def_max.memclk_mhz;
+ bw_params->clk_table.entries[i].voltage = def_max.voltage;
+ }
+ if (!bw_params->clk_table.entries[i].dcfclk_mhz)
+ bw_params->clk_table.entries[i].dcfclk_mhz = def_max.dcfclk_mhz;
+ if (!bw_params->clk_table.entries[i].socclk_mhz)
+ bw_params->clk_table.entries[i].socclk_mhz = def_max.socclk_mhz;
+ if (!bw_params->clk_table.entries[i].dispclk_mhz)
+ bw_params->clk_table.entries[i].dispclk_mhz = def_max.dispclk_mhz;
+ if (!bw_params->clk_table.entries[i].dppclk_mhz)
+ bw_params->clk_table.entries[i].dppclk_mhz = def_max.dppclk_mhz;
+ if (!bw_params->clk_table.entries[i].fclk_mhz)
+ bw_params->clk_table.entries[i].fclk_mhz = def_max.fclk_mhz;
+ if (!bw_params->clk_table.entries[i].phyclk_mhz)
+ bw_params->clk_table.entries[i].phyclk_mhz = def_max.phyclk_mhz;
+ if (!bw_params->clk_table.entries[i].phyclk_d18_mhz)
+ bw_params->clk_table.entries[i].phyclk_d18_mhz = def_max.phyclk_d18_mhz;
+ if (!bw_params->clk_table.entries[i].dtbclk_mhz)
+ bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz;
+ }
+ ASSERT(bw_params->clk_table.entries[i-1].dcfclk_mhz);
+ bw_params->vram_type = bios_info->memory_type;
+ bw_params->dram_channel_width_bytes = bios_info->memory_type == 0x22 ? 8 : 4;
+ bw_params->num_channels = bios_info->ma_channel_number ? bios_info->ma_channel_number : 4;
+
+ for (i = 0; i < WM_SET_COUNT; i++) {
+ bw_params->wm_table.entries[i].wm_inst = i;
+
+ if (i >= bw_params->clk_table.num_entries) {
+ bw_params->wm_table.entries[i].valid = false;
+ continue;
+ }
+
+ bw_params->wm_table.entries[i].wm_type = WM_TYPE_PSTATE_CHG;
+ bw_params->wm_table.entries[i].valid = true;
+ }
+}
+
+static void dcn35_set_low_power_state(struct clk_mgr *clk_mgr_base)
+{
+ int display_count;
+ struct dc *dc = clk_mgr_base->ctx->dc;
+ struct dc_state *context = dc->current_state;
+
+ if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
+ display_count = dcn35_get_active_display_cnt_wa(dc, context);
+ /* if we can go lower, go lower */
+ if (display_count == 0)
+ clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
+ }
+}
+
+static void dcn35_set_idle_state(struct clk_mgr *clk_mgr_base, bool allow_idle)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ struct dc *dc = clk_mgr_base->ctx->dc;
+ uint32_t val = dcn35_smu_read_ips_scratch(clk_mgr);
+
+ if (dc->config.disable_ips == DMUB_IPS_ENABLE ||
+ dc->config.disable_ips == DMUB_IPS_DISABLE_DYNAMIC) {
+ val = val & ~DMUB_IPS1_ALLOW_MASK;
+ val = val & ~DMUB_IPS2_ALLOW_MASK;
+ } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS1) {
+ val |= DMUB_IPS1_ALLOW_MASK;
+ val |= DMUB_IPS2_ALLOW_MASK;
+ } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2) {
+ val = val & ~DMUB_IPS1_ALLOW_MASK;
+ val |= DMUB_IPS2_ALLOW_MASK;
+ } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2_Z10) {
+ val = val & ~DMUB_IPS1_ALLOW_MASK;
+ val = val & ~DMUB_IPS2_ALLOW_MASK;
+ }
+
+ if (!allow_idle) {
+ val |= DMUB_IPS1_ALLOW_MASK;
+ val |= DMUB_IPS2_ALLOW_MASK;
+ }
+
+ dcn35_smu_write_ips_scratch(clk_mgr, val);
+}
+
+static void dcn35_exit_low_power_state(struct clk_mgr *clk_mgr_base)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+ //SMU optimization is performed part of low power state exit.
+ dcn35_smu_exit_low_power_state(clk_mgr);
+
+}
+
+static bool dcn35_is_ips_supported(struct clk_mgr *clk_mgr_base)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ bool ips_supported = true;
+
+ ips_supported = dcn35_smu_get_ips_supported(clk_mgr) ? true : false;
+
+ return ips_supported;
+}
+
+static uint32_t dcn35_get_idle_state(struct clk_mgr *clk_mgr_base)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+ return dcn35_smu_read_ips_scratch(clk_mgr);
+}
+
+static void dcn35_init_clocks_fpga(struct clk_mgr *clk_mgr)
+{
+ dcn35_init_clocks(clk_mgr);
+
+/* TODO: Implement the functions and remove the ifndef guard */
+}
+
+static void dcn35_update_clocks_fpga(struct clk_mgr *clk_mgr,
+ struct dc_state *context,
+ bool safe_to_lower)
+{
+ struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
+ struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
+ int fclk_adj = new_clocks->fclk_khz;
+
+ /* TODO: remove this after correctly set by DML */
+ new_clocks->dcfclk_khz = 400000;
+ new_clocks->socclk_khz = 400000;
+
+ /* Min fclk = 1.2GHz since all the extra scemi logic seems to run off of it */
+ //int fclk_adj = new_clocks->fclk_khz > 1200000 ? new_clocks->fclk_khz : 1200000;
+ new_clocks->fclk_khz = 4320000;
+
+ if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr->clks.phyclk_khz)) {
+ clk_mgr->clks.phyclk_khz = new_clocks->phyclk_khz;
+ }
+
+ if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr->clks.dcfclk_khz)) {
+ clk_mgr->clks.dcfclk_khz = new_clocks->dcfclk_khz;
+ }
+
+ if (should_set_clock(safe_to_lower,
+ new_clocks->dcfclk_deep_sleep_khz, clk_mgr->clks.dcfclk_deep_sleep_khz)) {
+ clk_mgr->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
+ }
+
+ if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr->clks.socclk_khz)) {
+ clk_mgr->clks.socclk_khz = new_clocks->socclk_khz;
+ }
+
+ if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr->clks.dramclk_khz)) {
+ clk_mgr->clks.dramclk_khz = new_clocks->dramclk_khz;
+ }
+
+ if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->clks.dppclk_khz)) {
+ clk_mgr->clks.dppclk_khz = new_clocks->dppclk_khz;
+ }
+
+ if (should_set_clock(safe_to_lower, fclk_adj, clk_mgr->clks.fclk_khz)) {
+ clk_mgr->clks.fclk_khz = fclk_adj;
+ }
+
+ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr->clks.dispclk_khz)) {
+ clk_mgr->clks.dispclk_khz = new_clocks->dispclk_khz;
+ }
+
+ /* Both fclk and ref_dppclk run on the same scemi clock.
+ * So take the higher value since the DPP DTO is typically programmed
+ * such that max dppclk is 1:1 with ref_dppclk.
+ */
+ if (clk_mgr->clks.fclk_khz > clk_mgr->clks.dppclk_khz)
+ clk_mgr->clks.dppclk_khz = clk_mgr->clks.fclk_khz;
+ if (clk_mgr->clks.dppclk_khz > clk_mgr->clks.fclk_khz)
+ clk_mgr->clks.fclk_khz = clk_mgr->clks.dppclk_khz;
+
+ // Both fclk and ref_dppclk run on the same scemi clock.
+ clk_mgr_int->dccg->ref_dppclk = clk_mgr->clks.fclk_khz;
+
+ /* TODO: set dtbclk in correct place */
+ clk_mgr->clks.dtbclk_en = true;
+ dm_set_dcn_clocks(clk_mgr->ctx, &clk_mgr->clks);
+ dcn35_update_clocks_update_dpp_dto(clk_mgr_int, context, safe_to_lower);
+
+ dcn35_update_clocks_update_dtb_dto(clk_mgr_int, context, clk_mgr->clks.ref_dtbclk_khz);
+}
+
+static struct clk_mgr_funcs dcn35_funcs = {
+ .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
+ .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
+ .update_clocks = dcn35_update_clocks,
+ .init_clocks = dcn35_init_clocks,
+ .enable_pme_wa = dcn35_enable_pme_wa,
+ .are_clock_states_equal = dcn35_are_clock_states_equal,
+ .notify_wm_ranges = dcn35_notify_wm_ranges,
+ .set_low_power_state = dcn35_set_low_power_state,
+ .exit_low_power_state = dcn35_exit_low_power_state,
+ .is_ips_supported = dcn35_is_ips_supported,
+ .set_idle_state = dcn35_set_idle_state,
+ .get_idle_state = dcn35_get_idle_state
+};
+
+struct clk_mgr_funcs dcn35_fpga_funcs = {
+ .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
+ .update_clocks = dcn35_update_clocks_fpga,
+ .init_clocks = dcn35_init_clocks_fpga,
+ .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
+};
+
+void dcn35_clk_mgr_construct(
+ struct dc_context *ctx,
+ struct clk_mgr_dcn35 *clk_mgr,
+ struct pp_smu_funcs *pp_smu,
+ struct dccg *dccg)
+{
+ struct dcn35_smu_dpm_clks smu_dpm_clks = { 0 };
+ struct clk_log_info log_info = {0};
+ clk_mgr->base.base.ctx = ctx;
+ clk_mgr->base.base.funcs = &dcn35_funcs;
+
+ clk_mgr->base.pp_smu = pp_smu;
+
+ clk_mgr->base.dccg = dccg;
+ clk_mgr->base.dfs_bypass_disp_clk = 0;
+
+ clk_mgr->base.dprefclk_ss_percentage = 0;
+ clk_mgr->base.dprefclk_ss_divider = 1000;
+ clk_mgr->base.ss_on_dprefclk = false;
+ clk_mgr->base.dfs_ref_freq_khz = 48000;
+
+ clk_mgr->smu_wm_set.wm_set = (struct dcn35_watermarks *)dm_helpers_allocate_gpu_mem(
+ clk_mgr->base.base.ctx,
+ DC_MEM_ALLOC_TYPE_FRAME_BUFFER,
+ sizeof(struct dcn35_watermarks),
+ &clk_mgr->smu_wm_set.mc_address.quad_part);
+
+ if (!clk_mgr->smu_wm_set.wm_set) {
+ clk_mgr->smu_wm_set.wm_set = &dummy_wms;
+ clk_mgr->smu_wm_set.mc_address.quad_part = 0;
+ }
+ ASSERT(clk_mgr->smu_wm_set.wm_set);
+
+ smu_dpm_clks.dpm_clks = (DpmClocks_t_dcn35 *)dm_helpers_allocate_gpu_mem(
+ clk_mgr->base.base.ctx,
+ DC_MEM_ALLOC_TYPE_FRAME_BUFFER,
+ sizeof(DpmClocks_t_dcn35),
+ &smu_dpm_clks.mc_address.quad_part);
+
+ if (smu_dpm_clks.dpm_clks == NULL) {
+ smu_dpm_clks.dpm_clks = &dummy_clocks;
+ smu_dpm_clks.mc_address.quad_part = 0;
+ }
+
+ ASSERT(smu_dpm_clks.dpm_clks);
+
+ clk_mgr->base.smu_ver = dcn35_smu_get_smu_version(&clk_mgr->base);
+
+ if (clk_mgr->base.smu_ver)
+ clk_mgr->base.smu_present = true;
+
+ /* TODO: Check we get what we expect during bringup */
+ clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
+
+ if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ dcn35_bw_params.wm_table = lpddr5_wm_table;
+ } else {
+ dcn35_bw_params.wm_table = ddr5_wm_table;
+ }
+ /* Saved clocks configured at boot for debug purposes */
+ dcn35_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info);
+
+ clk_mgr->base.base.dprefclk_khz = dcn35_smu_get_dprefclk(&clk_mgr->base);
+ clk_mgr->base.base.clks.ref_dtbclk_khz = 600000;
+
+ dce_clock_read_ss_info(&clk_mgr->base);
+ /*when clk src is from FCH, it could have ss, same clock src as DPREF clk*/
+
+ clk_mgr->base.base.bw_params = &dcn35_bw_params;
+
+ if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) {
+ int i;
+ dcn35_get_dpm_table_from_smu(&clk_mgr->base, &smu_dpm_clks);
+ DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n"
+ "NumDispClkLevelsEnabled: %d\n"
+ "NumSocClkLevelsEnabled: %d\n"
+ "VcnClkLevelsEnabled: %d\n"
+ "FClkLevelsEnabled: %d\n"
+ "NumMemPstatesEnabled: %d\n"
+ "MinGfxClk: %d\n"
+ "MaxGfxClk: %d\n",
+ smu_dpm_clks.dpm_clks->NumDcfClkLevelsEnabled,
+ smu_dpm_clks.dpm_clks->NumDispClkLevelsEnabled,
+ smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled,
+ smu_dpm_clks.dpm_clks->VcnClkLevelsEnabled,
+ smu_dpm_clks.dpm_clks->NumFclkLevelsEnabled,
+ smu_dpm_clks.dpm_clks->NumMemPstatesEnabled,
+ smu_dpm_clks.dpm_clks->MinGfxClk,
+ smu_dpm_clks.dpm_clks->MaxGfxClk);
+ for (i = 0; i < smu_dpm_clks.dpm_clks->NumDcfClkLevelsEnabled; i++) {
+ DC_LOG_SMU("smu_dpm_clks.dpm_clks->DcfClocks[%d] = %d\n",
+ i,
+ smu_dpm_clks.dpm_clks->DcfClocks[i]);
+ }
+ for (i = 0; i < smu_dpm_clks.dpm_clks->NumDispClkLevelsEnabled; i++) {
+ DC_LOG_SMU("smu_dpm_clks.dpm_clks->DispClocks[%d] = %d\n",
+ i, smu_dpm_clks.dpm_clks->DispClocks[i]);
+ }
+ for (i = 0; i < smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled; i++) {
+ DC_LOG_SMU("smu_dpm_clks.dpm_clks->SocClocks[%d] = %d\n",
+ i, smu_dpm_clks.dpm_clks->SocClocks[i]);
+ }
+ for (i = 0; i < smu_dpm_clks.dpm_clks->NumFclkLevelsEnabled; i++) {
+ DC_LOG_SMU("smu_dpm_clks.dpm_clks->FclkClocks_Freq[%d] = %d\n",
+ i, smu_dpm_clks.dpm_clks->FclkClocks_Freq[i]);
+ DC_LOG_SMU("smu_dpm_clks.dpm_clks->FclkClocks_Voltage[%d] = %d\n",
+ i, smu_dpm_clks.dpm_clks->FclkClocks_Voltage[i]);
+ }
+ for (i = 0; i < smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled; i++)
+ DC_LOG_SMU("smu_dpm_clks.dpm_clks->SocVoltage[%d] = %d\n",
+ i, smu_dpm_clks.dpm_clks->SocVoltage[i]);
+
+ for (i = 0; i < smu_dpm_clks.dpm_clks->NumMemPstatesEnabled; i++) {
+ DC_LOG_SMU("smu_dpm_clks.dpm_clks.MemPstateTable[%d].UClk = %d\n"
+ "smu_dpm_clks.dpm_clks->MemPstateTable[%d].MemClk= %d\n"
+ "smu_dpm_clks.dpm_clks->MemPstateTable[%d].Voltage = %d\n",
+ i, smu_dpm_clks.dpm_clks->MemPstateTable[i].UClk,
+ i, smu_dpm_clks.dpm_clks->MemPstateTable[i].MemClk,
+ i, smu_dpm_clks.dpm_clks->MemPstateTable[i].Voltage);
+ }
+
+ if (ctx->dc_bios && ctx->dc_bios->integrated_info && ctx->dc->config.use_default_clock_table == false) {
+ dcn35_clk_mgr_helper_populate_bw_params(
+ &clk_mgr->base,
+ ctx->dc_bios->integrated_info,
+ smu_dpm_clks.dpm_clks);
+ }
+ }
+
+ if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0)
+ dm_helpers_free_gpu_mem(clk_mgr->base.base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER,
+ smu_dpm_clks.dpm_clks);
+
+ if (ctx->dc->config.disable_ips != DMUB_IPS_DISABLE_ALL) {
+ bool ips_support = false;
+
+ /*avoid call pmfw at init*/
+ ips_support = dcn35_smu_get_ips_supported(&clk_mgr->base);
+ if (ips_support) {
+ ctx->dc->debug.ignore_pg = false;
+ ctx->dc->debug.disable_dpp_power_gate = false;
+ ctx->dc->debug.disable_hubp_power_gate = false;
+ ctx->dc->debug.disable_dsc_power_gate = false;
+ } else {
+ /*let's reset the config control flag*/
+ ctx->dc->config.disable_ips = DMUB_IPS_DISABLE_ALL; /*pmfw not support it, disable it all*/
+ }
+ }
+}
+
+void dcn35_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int)
+{
+ struct clk_mgr_dcn35 *clk_mgr = TO_CLK_MGR_DCN35(clk_mgr_int);
+
+ if (clk_mgr->smu_wm_set.wm_set && clk_mgr->smu_wm_set.mc_address.quad_part != 0)
+ dm_helpers_free_gpu_mem(clk_mgr_int->base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER,
+ clk_mgr->smu_wm_set.wm_set);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.h
new file mode 100644
index 000000000000..1203dc605b12
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DCN35_CLK_MGR_H__
+#define __DCN35_CLK_MGR_H__
+#include "clk_mgr_internal.h"
+
+#define NUM_CLOCK_SOURCES 5
+
+struct dcn35_watermarks;
+
+struct dcn35_smu_watermark_set {
+ struct dcn35_watermarks *wm_set;
+ union large_integer mc_address;
+};
+
+struct dcn35_ss_info_table {
+ uint32_t ss_divider;
+ uint32_t ss_percentage[NUM_CLOCK_SOURCES];
+};
+
+struct clk_mgr_dcn35 {
+ struct clk_mgr_internal base;
+ struct dcn35_smu_watermark_set smu_wm_set;
+};
+
+bool dcn35_are_clock_states_equal(struct dc_clocks *a,
+ struct dc_clocks *b);
+void dcn35_init_clocks(struct clk_mgr *clk_mgr);
+void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
+ struct dc_state *context,
+ bool safe_to_lower);
+
+void dcn35_clk_mgr_construct(struct dc_context *ctx,
+ struct clk_mgr_dcn35 *clk_mgr,
+ struct pp_smu_funcs *pp_smu,
+ struct dccg *dccg);
+
+void dcn35_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int);
+
+#endif //__DCN35_CLK_MGR_H__
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c
new file mode 100644
index 000000000000..b6b8c3ca1572
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c
@@ -0,0 +1,471 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+
+
+#include "core_types.h"
+#include "clk_mgr_internal.h"
+#include "reg_helper.h"
+#include "dm_helpers.h"
+#include "dcn35_smu.h"
+
+#include "mp/mp_14_0_0_offset.h"
+#include "mp/mp_14_0_0_sh_mask.h"
+
+/* TODO: Use the real headers when they're correct */
+#define MP1_BASE__INST0_SEG0 0x00016000
+#define MP1_BASE__INST0_SEG1 0x0243FC00
+#define MP1_BASE__INST0_SEG2 0x00DC0000
+#define MP1_BASE__INST0_SEG3 0x00E00000
+#define MP1_BASE__INST0_SEG4 0x00E40000
+#define MP1_BASE__INST0_SEG5 0
+
+#ifdef BASE_INNER
+#undef BASE_INNER
+#endif
+
+#define BASE_INNER(seg) MP1_BASE__INST0_SEG ## seg
+
+#define BASE(seg) BASE_INNER(seg)
+
+#define REG(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name)
+
+#define FN(reg_name, field) \
+ FD(reg_name##__##field)
+
+#include "logger_types.h"
+#undef DC_LOGGER
+#define DC_LOGGER \
+ CTX->logger
+#define smu_print(str, ...) {DC_LOG_SMU(str, ##__VA_ARGS__); }
+
+#define VBIOSSMC_MSG_TestMessage 0x1
+#define VBIOSSMC_MSG_GetSmuVersion 0x2
+#define VBIOSSMC_MSG_PowerUpGfx 0x3
+#define VBIOSSMC_MSG_SetDispclkFreq 0x4
+#define VBIOSSMC_MSG_SetDprefclkFreq 0x5 //Not used. DPRef is constant
+#define VBIOSSMC_MSG_SetDppclkFreq 0x6
+#define VBIOSSMC_MSG_SetHardMinDcfclkByFreq 0x7
+#define VBIOSSMC_MSG_SetMinDeepSleepDcfclk 0x8
+#define VBIOSSMC_MSG_SetPhyclkVoltageByFreq 0x9 //Keep it in case VMIN dees not support phy clk
+#define VBIOSSMC_MSG_GetFclkFrequency 0xA
+#define VBIOSSMC_MSG_SetDisplayCount 0xB //Not used anymore
+#define VBIOSSMC_MSG_EnableTmdp48MHzRefclkPwrDown 0xC //To ask PMFW turn off TMDP 48MHz refclk during display off to save power
+#define VBIOSSMC_MSG_UpdatePmeRestore 0xD
+#define VBIOSSMC_MSG_SetVbiosDramAddrHigh 0xE //Used for WM table txfr
+#define VBIOSSMC_MSG_SetVbiosDramAddrLow 0xF
+#define VBIOSSMC_MSG_TransferTableSmu2Dram 0x10
+#define VBIOSSMC_MSG_TransferTableDram2Smu 0x11
+#define VBIOSSMC_MSG_SetDisplayIdleOptimizations 0x12
+#define VBIOSSMC_MSG_GetDprefclkFreq 0x13
+#define VBIOSSMC_MSG_GetDtbclkFreq 0x14
+#define VBIOSSMC_MSG_AllowZstatesEntry 0x15
+#define VBIOSSMC_MSG_DisallowZstatesEntry 0x16
+#define VBIOSSMC_MSG_SetDtbClk 0x17
+#define VBIOSSMC_MSG_DispPsrEntry 0x18 ///< Display PSR entry, DMU
+#define VBIOSSMC_MSG_DispPsrExit 0x19 ///< Display PSR exit, DMU
+#define VBIOSSMC_MSG_DisableLSdma 0x1A ///< Disable LSDMA; only sent by VBIOS
+#define VBIOSSMC_MSG_DpControllerPhyStatus 0x1B ///< Inform PMFW about the pre conditions for turning SLDO2 on/off . bit[0]==1 precondition is met, bit[1-2] are for DPPHY number
+#define VBIOSSMC_MSG_QueryIPS2Support 0x1C ///< Return 1: support; else not supported
+#define VBIOSSMC_Message_Count 0x1D
+
+#define VBIOSSMC_Status_BUSY 0x0
+#define VBIOSSMC_Result_OK 0x1
+#define VBIOSSMC_Result_Failed 0xFF
+#define VBIOSSMC_Result_UnknownCmd 0xFE
+#define VBIOSSMC_Result_CmdRejectedPrereq 0xFD
+#define VBIOSSMC_Result_CmdRejectedBusy 0xFC
+
+/*
+ * Function to be used instead of REG_WAIT macro because the wait ends when
+ * the register is NOT EQUAL to zero, and because `the translation in msg_if.h
+ * won't work with REG_WAIT.
+ */
+static uint32_t dcn35_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, unsigned int delay_us, unsigned int max_retries)
+{
+ uint32_t res_val = VBIOSSMC_Status_BUSY;
+
+ do {
+ res_val = REG_READ(MP1_SMN_C2PMSG_91);
+ if (res_val != VBIOSSMC_Status_BUSY)
+ break;
+
+ if (delay_us >= 1000)
+ msleep(delay_us/1000);
+ else if (delay_us > 0)
+ udelay(delay_us);
+ } while (max_retries--);
+
+ return res_val;
+}
+
+static int dcn35_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr,
+ unsigned int msg_id,
+ unsigned int param)
+{
+ uint32_t result;
+
+ result = dcn35_smu_wait_for_response(clk_mgr, 10, 2000000);
+ ASSERT(result == VBIOSSMC_Result_OK);
+
+ if (result != VBIOSSMC_Result_OK) {
+ DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id);
+
+ if (result == VBIOSSMC_Status_BUSY)
+ return -1;
+ }
+
+ /* First clear response register */
+ REG_WRITE(MP1_SMN_C2PMSG_91, VBIOSSMC_Status_BUSY);
+
+ /* Set the parameter register for the SMU message, unit is Mhz */
+ REG_WRITE(MP1_SMN_C2PMSG_83, param);
+
+ /* Trigger the message transaction by writing the message ID */
+ REG_WRITE(MP1_SMN_C2PMSG_67, msg_id);
+
+ result = dcn35_smu_wait_for_response(clk_mgr, 10, 2000000);
+
+ if (result == VBIOSSMC_Result_Failed) {
+ if (msg_id == VBIOSSMC_MSG_TransferTableDram2Smu &&
+ param == TABLE_WATERMARKS)
+ DC_LOG_WARNING("Watermarks table not configured properly by SMU");
+ else
+ ASSERT(0);
+ REG_WRITE(MP1_SMN_C2PMSG_91, VBIOSSMC_Result_OK);
+ DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id);
+ return -1;
+ }
+
+ if (IS_SMU_TIMEOUT(result)) {
+ ASSERT(0);
+ result = dcn35_smu_wait_for_response(clk_mgr, 10, 2000000);
+ //dm_helpers_smu_timeout(CTX, msg_id, param, 10 * 200000);
+ DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id);
+ }
+
+ return REG_READ(MP1_SMN_C2PMSG_83);
+}
+
+int dcn35_smu_get_smu_version(struct clk_mgr_internal *clk_mgr)
+{
+ return dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_GetSmuVersion,
+ 0);
+}
+
+
+int dcn35_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz)
+{
+ int actual_dispclk_set_mhz = -1;
+
+ if (!clk_mgr->smu_present)
+ return requested_dispclk_khz;
+
+ /* Unit of SMU msg parameter is Mhz */
+ actual_dispclk_set_mhz = dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_SetDispclkFreq,
+ khz_to_mhz_ceil(requested_dispclk_khz));
+
+ smu_print("requested_dispclk_khz = %d, actual_dispclk_set_mhz: %d\n", requested_dispclk_khz, actual_dispclk_set_mhz);
+ return actual_dispclk_set_mhz * 1000;
+}
+
+int dcn35_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
+{
+ int actual_dprefclk_set_mhz = -1;
+
+ if (!clk_mgr->smu_present)
+ return clk_mgr->base.dprefclk_khz;
+
+ actual_dprefclk_set_mhz = dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_SetDprefclkFreq,
+ khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz));
+
+ /* TODO: add code for programing DP DTO, currently this is down by command table */
+
+ return actual_dprefclk_set_mhz * 1000;
+}
+
+int dcn35_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz)
+{
+ int actual_dcfclk_set_mhz = -1;
+
+ if (!clk_mgr->smu_present)
+ return requested_dcfclk_khz;
+
+ actual_dcfclk_set_mhz = dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
+ khz_to_mhz_ceil(requested_dcfclk_khz));
+
+ smu_print("requested_dcfclk_khz = %d, actual_dcfclk_set_mhz: %d\n", requested_dcfclk_khz, actual_dcfclk_set_mhz);
+
+ return actual_dcfclk_set_mhz * 1000;
+}
+
+int dcn35_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz)
+{
+ int actual_min_ds_dcfclk_mhz = -1;
+
+ if (!clk_mgr->smu_present)
+ return requested_min_ds_dcfclk_khz;
+
+ actual_min_ds_dcfclk_mhz = dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
+ khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
+
+ smu_print("requested_min_ds_dcfclk_khz = %d, actual_min_ds_dcfclk_mhz: %d\n", requested_min_ds_dcfclk_khz, actual_min_ds_dcfclk_mhz);
+
+ return actual_min_ds_dcfclk_mhz * 1000;
+}
+
+int dcn35_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
+{
+ int actual_dppclk_set_mhz = -1;
+
+ if (!clk_mgr->smu_present)
+ return requested_dpp_khz;
+
+ actual_dppclk_set_mhz = dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_SetDppclkFreq,
+ khz_to_mhz_ceil(requested_dpp_khz));
+
+ smu_print("requested_dpp_khz = %d, actual_dppclk_set_mhz: %d\n", requested_dpp_khz, actual_dppclk_set_mhz);
+
+ return actual_dppclk_set_mhz * 1000;
+}
+
+void dcn35_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info)
+{
+ if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
+ return;
+
+ if (!clk_mgr->smu_present)
+ return;
+
+ //TODO: Work with smu team to define optimization options.
+ dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_SetDisplayIdleOptimizations,
+ idle_info);
+ smu_print("VBIOSSMC_MSG_SetDisplayIdleOptimizations idle_info = %d\n", idle_info);
+}
+
+void dcn35_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable)
+{
+ union display_idle_optimization_u idle_info = { 0 };
+
+ if (!clk_mgr->smu_present)
+ return;
+
+ if (enable) {
+ idle_info.idle_info.df_request_disabled = 1;
+ idle_info.idle_info.phy_ref_clk_off = 1;
+ }
+
+ dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_SetDisplayIdleOptimizations,
+ idle_info.data);
+ smu_print("dcn35_smu_enable_phy_refclk_pwrdwn = %d\n", enable ? 1 : 0);
+}
+
+void dcn35_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr)
+{
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_UpdatePmeRestore,
+ 0);
+}
+
+void dcn35_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high)
+{
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn35_smu_send_msg_with_param(clk_mgr,
+ VBIOSSMC_MSG_SetVbiosDramAddrHigh, addr_high);
+}
+
+void dcn35_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low)
+{
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn35_smu_send_msg_with_param(clk_mgr,
+ VBIOSSMC_MSG_SetVbiosDramAddrLow, addr_low);
+}
+
+void dcn35_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr)
+{
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn35_smu_send_msg_with_param(clk_mgr,
+ VBIOSSMC_MSG_TransferTableSmu2Dram, TABLE_DPMCLOCKS);
+}
+
+void dcn35_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr)
+{
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn35_smu_send_msg_with_param(clk_mgr,
+ VBIOSSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS);
+}
+
+void dcn35_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support)
+{
+ unsigned int msg_id, param;
+
+ if (!clk_mgr->smu_present)
+ return;
+
+ switch (support) {
+
+ case DCN_ZSTATE_SUPPORT_ALLOW:
+ msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
+ param = (1 << 10) | (1 << 9) | (1 << 8);
+ break;
+
+ case DCN_ZSTATE_SUPPORT_DISALLOW:
+ msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
+ param = 0;
+ break;
+
+
+ case DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY:
+ msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
+ param = (1 << 10);
+ break;
+
+ case DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY:
+ msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
+ param = (1 << 10) | (1 << 8);
+ break;
+
+ case DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY:
+ msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
+ param = (1 << 8);
+ break;
+
+ default: //DCN_ZSTATE_SUPPORT_UNKNOWN
+ msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
+ param = 0;
+ break;
+ }
+
+
+ dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ msg_id,
+ param);
+ smu_print("dcn35_smu_set_zstate_support msg_id = %d, param = %d\n", msg_id, param);
+}
+
+int dcn35_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr)
+{
+ int dprefclk;
+
+ if (!clk_mgr->smu_present)
+ return 0;
+
+ dprefclk = dcn35_smu_send_msg_with_param(clk_mgr,
+ VBIOSSMC_MSG_GetDprefclkFreq,
+ 0);
+
+ smu_print("dcn35_smu_get_DPREF clk = %d mhz\n", dprefclk);
+ return dprefclk * 1000;
+}
+
+int dcn35_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr)
+{
+ int dtbclk;
+
+ if (!clk_mgr->smu_present)
+ return 0;
+
+ dtbclk = dcn35_smu_send_msg_with_param(clk_mgr,
+ VBIOSSMC_MSG_GetDtbclkFreq,
+ 0);
+
+ smu_print("dcn35_smu_get_dtbclk = %d mhz\n", dtbclk);
+ return dtbclk * 1000;
+}
+/* Arg = 1: Turn DTB on; 0: Turn DTB CLK OFF. when it is on, it is 600MHZ */
+void dcn35_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable)
+{
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_SetDtbClk,
+ enable);
+ smu_print("dcn35_smu_set_dtbclk = %d \n", enable ? 1 : 0);
+}
+
+void dcn35_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable)
+{
+ dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_EnableTmdp48MHzRefclkPwrDown,
+ enable);
+}
+
+int dcn35_smu_exit_low_power_state(struct clk_mgr_internal *clk_mgr)
+{
+ return dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_DispPsrExit,
+ 0);
+}
+
+int dcn35_smu_get_ips_supported(struct clk_mgr_internal *clk_mgr)
+{
+ return dcn35_smu_send_msg_with_param(
+ clk_mgr,
+ VBIOSSMC_MSG_QueryIPS2Support,
+ 0);
+}
+
+void dcn35_smu_write_ips_scratch(struct clk_mgr_internal *clk_mgr, uint32_t param)
+{
+ REG_WRITE(MP1_SMN_C2PMSG_71, param);
+}
+
+uint32_t dcn35_smu_read_ips_scratch(struct clk_mgr_internal *clk_mgr)
+{
+ return REG_READ(MP1_SMN_C2PMSG_71);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h
new file mode 100644
index 000000000000..2b8e6959a03d
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef DAL_DC_35_SMU_H_
+#define DAL_DC_35_SMU_H_
+
+#include "os_types.h"
+
+#ifndef PMFW_DRIVER_IF_H
+#define PMFW_DRIVER_IF_H
+#define PMFW_DRIVER_IF_VERSION 4
+
+typedef enum {
+ DSPCLK_DCFCLK = 0,
+ DSPCLK_DISPCLK,
+ DSPCLK_PIXCLK,
+ DSPCLK_PHYCLK,
+ DSPCLK_COUNT,
+} DSPCLK_e;
+
+typedef struct {
+ uint16_t Freq; // in MHz
+ uint16_t Vid; // min voltage in SVI3 VID
+} DisplayClockTable_t;
+
+typedef struct {
+ uint16_t MinClock; // This is either DCFCLK or SOCCLK (in MHz)
+ uint16_t MaxClock; // This is either DCFCLK or SOCCLK (in MHz)
+ uint16_t MinMclk;
+ uint16_t MaxMclk;
+
+ uint8_t WmSetting;
+ uint8_t WmType; // Used for normal pstate change or memory retraining
+ uint8_t Padding[2];
+} WatermarkRowGeneric_t;
+
+#define NUM_WM_RANGES 4
+#define WM_PSTATE_CHG 0
+#define WM_RETRAINING 1
+
+typedef enum {
+ WM_SOCCLK = 0,
+ WM_DCFCLK,
+ WM_COUNT,
+} WM_CLOCK_e;
+
+typedef struct {
+ // Watermarks
+ WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES];
+
+ uint32_t MmHubPadding[7]; // SMU internal use
+} Watermarks_t;
+
+#define NUM_DCFCLK_DPM_LEVELS 8
+#define NUM_DISPCLK_DPM_LEVELS 8
+#define NUM_DPPCLK_DPM_LEVELS 8
+#define NUM_SOCCLK_DPM_LEVELS 8
+#define NUM_VCN_DPM_LEVELS 8
+#define NUM_SOC_VOLTAGE_LEVELS 8
+#define NUM_VPE_DPM_LEVELS 8
+#define NUM_FCLK_DPM_LEVELS 8
+#define NUM_MEM_PSTATE_LEVELS 4
+
+typedef enum{
+ WCK_RATIO_1_1 = 0, // DDR5, Wck:ck is always 1:1;
+ WCK_RATIO_1_2,
+ WCK_RATIO_1_4,
+ WCK_RATIO_MAX
+} WCK_RATIO_e;
+
+typedef struct {
+ uint32_t UClk;
+ uint32_t MemClk;
+ uint32_t Voltage;
+ uint8_t WckRatio;
+ uint8_t Spare[3];
+} MemPstateTable_t;
+
+//Freq in MHz
+//Voltage in milli volts with 2 fractional bits
+typedef struct {
+ uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS];
+ uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS];
+ uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS];
+ uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS];
+ uint32_t VClocks[NUM_VCN_DPM_LEVELS];
+ uint32_t DClocks[NUM_VCN_DPM_LEVELS];
+ uint32_t VPEClocks[NUM_VPE_DPM_LEVELS];
+ uint32_t FclkClocks_Freq[NUM_FCLK_DPM_LEVELS];
+ uint32_t FclkClocks_Voltage[NUM_FCLK_DPM_LEVELS];
+ uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS];
+ MemPstateTable_t MemPstateTable[NUM_MEM_PSTATE_LEVELS];
+
+ uint8_t NumDcfClkLevelsEnabled;
+ uint8_t NumDispClkLevelsEnabled; //Applies to both Dispclk and Dppclk
+ uint8_t NumSocClkLevelsEnabled;
+ uint8_t VcnClkLevelsEnabled; //Applies to both Vclk and Dclk
+ uint8_t VpeClkLevelsEnabled;
+ uint8_t NumMemPstatesEnabled;
+ uint8_t NumFclkLevelsEnabled;
+ uint8_t spare[2];
+
+ uint32_t MinGfxClk;
+ uint32_t MaxGfxClk;
+} DpmClocks_t_dcn35;
+
+
+// Throttler Status Bitmask
+
+
+
+
+
+
+
+
+
+
+
+#define TABLE_BIOS_IF 0 // Called by BIOS
+#define TABLE_WATERMARKS 1 // Called by DAL through VBIOS
+#define TABLE_CUSTOM_DPM 2 // Called by Driver
+#define TABLE_SPARE1 3
+#define TABLE_DPMCLOCKS 4 // Called by Driver
+#define TABLE_MOMENTARY_PM 5 // Called by Tools
+#define TABLE_MODERN_STDBY 6 // Called by Tools for Modern Standby Log
+#define TABLE_SMU_METRICS 7 // Called by Driver
+#define TABLE_COUNT 8
+
+#endif
+
+struct dcn35_watermarks {
+ // Watermarks
+ WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES];
+
+ uint32_t MmHubPadding[7]; // SMU internal use
+};
+
+struct dcn35_smu_dpm_clks {
+ DpmClocks_t_dcn35 *dpm_clks;
+ union large_integer mc_address;
+};
+
+/* TODO: taken from vgh, may not be correct */
+struct display_idle_optimization {
+ unsigned int df_request_disabled : 1;
+ unsigned int phy_ref_clk_off : 1;
+ unsigned int s0i2_rdy : 1;
+ unsigned int reserved : 29;
+};
+
+union display_idle_optimization_u {
+ struct display_idle_optimization idle_info;
+ uint32_t data;
+};
+
+int dcn35_smu_get_smu_version(struct clk_mgr_internal *clk_mgr);
+int dcn35_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz);
+int dcn35_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr);
+int dcn35_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz);
+int dcn35_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz);
+int dcn35_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz);
+void dcn35_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info);
+void dcn35_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable);
+void dcn35_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr);
+void dcn35_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high);
+void dcn35_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low);
+void dcn35_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr);
+void dcn35_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr);
+
+void dcn35_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support);
+void dcn35_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable);
+void dcn35_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable);
+
+int dcn35_smu_exit_low_power_state(struct clk_mgr_internal *clk_mgr);
+int dcn35_smu_get_ips_supported(struct clk_mgr_internal *clk_mgr);
+int dcn35_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr);
+int dcn35_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr);
+void dcn35_smu_write_ips_scratch(struct clk_mgr_internal *clk_mgr, uint32_t param);
+uint32_t dcn35_smu_read_ips_scratch(struct clk_mgr_internal *clk_mgr);
+#endif /* DAL_DC_35_SMU_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 3a9077b60029..76b47f178127 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -24,6 +24,8 @@
#include "dm_services.h"
+#include "amdgpu.h"
+
#include "dc.h"
#include "core_status.h"
@@ -75,6 +77,8 @@
#include "hw_sequencer_private.h"
+#include "dml2/dml2_internal_types.h"
+
#include "dce/dmub_outbox.h"
#define CTX \
@@ -828,6 +832,7 @@ static void dc_destruct(struct dc *dc)
if (dc->ctx->created_bios)
dal_bios_parser_destroy(&dc->ctx->dc_bios);
+ kfree(dc->ctx->logger);
dc_perf_trace_destroy(&dc->ctx->perf_trace);
kfree(dc->ctx);
@@ -868,8 +873,18 @@ static bool dc_construct_ctx(struct dc *dc,
dc_ctx->dce_environment = init_params->dce_environment;
dc_ctx->dcn_reg_offsets = init_params->dcn_reg_offsets;
dc_ctx->nbio_reg_offsets = init_params->nbio_reg_offsets;
+ dc_ctx->clk_reg_offsets = init_params->clk_reg_offsets;
/* Create logger */
+ dc_ctx->logger = kmalloc(sizeof(*dc_ctx->logger), GFP_KERNEL);
+
+ if (!dc_ctx->logger) {
+ kfree(dc_ctx);
+ return false;
+ }
+
+ dc_ctx->logger->dev = adev_to_drm(init_params->driver);
+ dc->dml.logger = dc_ctx->logger;
dc_ctx->dce_version = resource_parse_asic_id(init_params->asic_id);
@@ -990,7 +1005,8 @@ static bool dc_construct(struct dc *dc,
/* set i2c speed if not done by the respective dcnxxx__resource.c */
if (dc->caps.i2c_speed_in_khz_hdcp == 0)
dc->caps.i2c_speed_in_khz_hdcp = dc->caps.i2c_speed_in_khz;
-
+ if (dc->caps.max_optimizable_video_width == 0)
+ dc->caps.max_optimizable_video_width = 5120;
dc->clk_mgr = dc_clk_mgr_create(dc->ctx, dc->res_pool->pp_smu, dc->res_pool->dccg);
if (!dc->clk_mgr)
goto fail;
@@ -1069,53 +1085,6 @@ static void apply_ctx_interdependent_lock(struct dc *dc,
}
}
-static void phantom_pipe_blank(
- struct dc *dc,
- struct timing_generator *tg,
- int width,
- int height)
-{
- struct dce_hwseq *hws = dc->hwseq;
- enum dc_color_space color_space;
- struct tg_color black_color = {0};
- struct output_pixel_processor *opp = NULL;
- uint32_t num_opps, opp_id_src0, opp_id_src1;
- uint32_t otg_active_width, otg_active_height;
- uint32_t i;
-
- /* program opp dpg blank color */
- color_space = COLOR_SPACE_SRGB;
- color_space_to_black_color(dc, color_space, &black_color);
-
- otg_active_width = width;
- otg_active_height = height;
-
- /* get the OPTC source */
- tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
- ASSERT(opp_id_src0 < dc->res_pool->res_cap->num_opp);
-
- for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
- if (dc->res_pool->opps[i] != NULL && dc->res_pool->opps[i]->inst == opp_id_src0) {
- opp = dc->res_pool->opps[i];
- break;
- }
- }
-
- if (opp && opp->funcs->opp_set_disp_pattern_generator)
- opp->funcs->opp_set_disp_pattern_generator(
- opp,
- CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
- CONTROLLER_DP_COLOR_SPACE_UDEFINED,
- COLOR_DEPTH_UNDEFINED,
- &black_color,
- otg_active_width,
- otg_active_height,
- 0);
-
- if (tg->funcs->is_tg_enabled(tg))
- hws->funcs.wait_for_blank_complete(opp);
-}
-
static void dc_update_viusal_confirm_color(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
{
if (dc->ctx->dce_version >= DCN_VERSION_1_0) {
@@ -1206,7 +1175,8 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
main_pipe_width = old_stream->mall_stream_config.paired_stream->dst.width;
main_pipe_height = old_stream->mall_stream_config.paired_stream->dst.height;
- phantom_pipe_blank(dc, tg, main_pipe_width, main_pipe_height);
+ if (dc->hwss.blank_phantom)
+ dc->hwss.blank_phantom(dc, tg, main_pipe_width, main_pipe_height);
tg->funcs->enable_crtc(tg);
}
}
@@ -1262,6 +1232,9 @@ static void disable_vbios_mode_if_required(
if (stream == NULL)
continue;
+ if (stream->apply_seamless_boot_optimization)
+ continue;
+
// only looking for first odm pipe
if (pipe->prev_odm_pipe)
continue;
@@ -1367,6 +1340,7 @@ struct dc *dc_create(const struct dc_init_data *init_params)
dc->dcn_reg_offsets = init_params->dcn_reg_offsets;
dc->nbio_reg_offsets = init_params->nbio_reg_offsets;
+ dc->clk_reg_offsets = init_params->clk_reg_offsets;
/* Populate versioning information */
dc->versions.dc_ver = DC_VER;
@@ -1885,7 +1859,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
if (dc->hwss.subvp_pipe_control_lock)
dc->hwss.subvp_pipe_control_lock(dc, context, true, true, NULL, subvp_prev_use);
- if (dc->debug.enable_double_buffered_dsc_pg_support)
+ if (dc->hwss.update_dsc_pg)
dc->hwss.update_dsc_pg(dc, context, false);
disable_dangling_plane(dc, context);
@@ -1992,7 +1966,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
dc->hwss.optimize_bandwidth(dc, context);
}
- if (dc->debug.enable_double_buffered_dsc_pg_support)
+ if (dc->hwss.update_dsc_pg)
dc->hwss.update_dsc_pg(dc, context, true);
if (dc->ctx->dce_version >= DCE_VERSION_MAX)
@@ -2239,7 +2213,7 @@ void dc_post_update_surfaces_to_stream(struct dc *dc)
dc->hwss.optimize_bandwidth(dc, context);
- if (dc->debug.enable_double_buffered_dsc_pg_support)
+ if (dc->hwss.update_dsc_pg)
dc->hwss.update_dsc_pg(dc, context, true);
}
@@ -2266,6 +2240,11 @@ struct dc_state *dc_create_state(struct dc *dc)
init_state(dc, context);
+#ifdef CONFIG_DRM_AMD_DC_FP
+ if (dc->debug.using_dml2) {
+ dml2_create(dc, &dc->dml2_options, &context->bw_ctx.dml2);
+ }
+#endif
kref_init(&context->refcount);
return context;
@@ -2275,11 +2254,25 @@ struct dc_state *dc_copy_state(struct dc_state *src_ctx)
{
int i, j;
struct dc_state *new_ctx = kvmalloc(sizeof(struct dc_state), GFP_KERNEL);
+#ifdef CONFIG_DRM_AMD_DC_FP
+ struct dml2_context *dml2 = NULL;
+#endif
if (!new_ctx)
return NULL;
memcpy(new_ctx, src_ctx, sizeof(struct dc_state));
+#ifdef CONFIG_DRM_AMD_DC_FP
+ if (new_ctx->bw_ctx.dml2) {
+ dml2 = kzalloc(sizeof(struct dml2_context), GFP_KERNEL);
+ if (!dml2)
+ return NULL;
+
+ memcpy(dml2, src_ctx->bw_ctx.dml2, sizeof(struct dml2_context));
+ new_ctx->bw_ctx.dml2 = dml2;
+ }
+#endif
+
for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *cur_pipe = &new_ctx->res_ctx.pipe_ctx[i];
@@ -2318,6 +2311,12 @@ static void dc_state_free(struct kref *kref)
{
struct dc_state *context = container_of(kref, struct dc_state, refcount);
dc_resource_state_destruct(context);
+
+#ifdef CONFIG_DRM_AMD_DC_FP
+ dml2_destroy(context->bw_ctx.dml2);
+ context->bw_ctx.dml2 = 0;
+#endif
+
kvfree(context);
}
@@ -2485,6 +2484,7 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
}
static enum surface_update_type get_scaling_info_update_type(
+ const struct dc *dc,
const struct dc_surface_update *u)
{
union surface_update_flags *update_flags = &u->surface->update_flags;
@@ -2517,6 +2517,12 @@ static enum surface_update_type get_scaling_info_update_type(
update_flags->bits.clock_change = 1;
}
+ if (u->scaling_info->src_rect.width > dc->caps.max_optimizable_video_width &&
+ (u->scaling_info->clip_rect.width > u->surface->clip_rect.width ||
+ u->scaling_info->clip_rect.height > u->surface->clip_rect.height))
+ /* Changing clip size of a large surface may result in MPC slice count change */
+ update_flags->bits.bandwidth_change = 1;
+
if (u->scaling_info->src_rect.x != u->surface->src_rect.x
|| u->scaling_info->src_rect.y != u->surface->src_rect.y
|| u->scaling_info->clip_rect.x != u->surface->clip_rect.x
@@ -2554,7 +2560,7 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
type = get_plane_info_update_type(u);
elevate_update_type(&overall_type, type);
- type = get_scaling_info_update_type(u);
+ type = get_scaling_info_update_type(dc, u);
elevate_update_type(&overall_type, type);
if (u->flip_addr) {
@@ -2576,6 +2582,9 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
if (u->gamut_remap_matrix)
update_flags->bits.gamut_remap_change = 1;
+ if (u->blend_tf)
+ update_flags->bits.gamma_change = 1;
+
if (u->gamma) {
enum surface_pixel_format format = SURFACE_PIXEL_FORMAT_GRPH_BEGIN;
@@ -3009,6 +3018,34 @@ static void copy_stream_update_to_stream(struct dc *dc,
}
}
+static void backup_plane_states_for_stream(
+ struct dc_plane_state plane_states[MAX_SURFACE_NUM],
+ struct dc_stream_state *stream)
+{
+ int i;
+ struct dc_stream_status *status = dc_stream_get_status(stream);
+
+ if (!status)
+ return;
+
+ for (i = 0; i < status->plane_count; i++)
+ plane_states[i] = *status->plane_states[i];
+}
+
+static void restore_plane_states_for_stream(
+ struct dc_plane_state plane_states[MAX_SURFACE_NUM],
+ struct dc_stream_state *stream)
+{
+ int i;
+ struct dc_stream_status *status = dc_stream_get_status(stream);
+
+ if (!status)
+ return;
+
+ for (i = 0; i < status->plane_count; i++)
+ *status->plane_states[i] = plane_states[i];
+}
+
static bool update_planes_and_stream_state(struct dc *dc,
struct dc_surface_update *srf_updates, int surface_count,
struct dc_stream_state *stream,
@@ -3032,7 +3069,7 @@ static bool update_planes_and_stream_state(struct dc *dc,
}
context = dc->current_state;
-
+ backup_plane_states_for_stream(dc->current_state->scratch.plane_states, stream);
update_type = dc_check_update_surfaces_for_stream(
dc, srf_updates, surface_count, stream_update, stream_status);
@@ -3062,6 +3099,9 @@ static bool update_planes_and_stream_state(struct dc *dc,
if (update_type >= update_surface_trace_level)
update_surface_trace(dc, srf_updates, surface_count);
+ for (i = 0; i < surface_count; i++)
+ copy_surface_update_to_plane(srf_updates[i].surface, &srf_updates[i]);
+
if (update_type >= UPDATE_TYPE_FULL) {
struct dc_plane_state *new_planes[MAX_SURFACES] = {0};
@@ -3103,8 +3143,6 @@ static bool update_planes_and_stream_state(struct dc *dc,
for (i = 0; i < surface_count; i++) {
struct dc_plane_state *surface = srf_updates[i].surface;
- copy_surface_update_to_plane(surface, &srf_updates[i]);
-
if (update_type >= UPDATE_TYPE_MED) {
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
@@ -3135,10 +3173,19 @@ static bool update_planes_and_stream_state(struct dc *dc,
BREAK_TO_DEBUGGER();
goto fail;
}
+
+ for (i = 0; i < context->stream_count; i++) {
+ struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(&context->res_ctx,
+ context->streams[i]);
+
+ if (otg_master && otg_master->stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE)
+ resource_build_test_pattern_params(&context->res_ctx, otg_master);
+ }
}
*new_context = context;
*new_update_type = update_type;
+ backup_plane_states_for_stream(context->scratch.plane_states, stream);
return true;
@@ -3510,7 +3557,7 @@ static void wait_for_outstanding_hw_updates(struct dc *dc, const struct dc_state
*/
int pipe_idx;
int opp_inst;
- int opp_count = dc->res_pool->pipe_count;
+ int opp_count = dc->res_pool->res_cap->num_opp;
struct hubp *hubp;
int mpcc_inst;
const struct pipe_ctx *pipe_ctx;
@@ -3531,7 +3578,8 @@ static void wait_for_outstanding_hw_updates(struct dc *dc, const struct dc_state
mpcc_inst = hubp->inst;
// MPCC inst is equal to pipe index in practice
for (opp_inst = 0; opp_inst < opp_count; opp_inst++) {
- if (dc->res_pool->opps[opp_inst]->mpcc_disconnect_pending[mpcc_inst]) {
+ if ((dc->res_pool->opps[opp_inst] != NULL) &&
+ (dc->res_pool->opps[opp_inst]->mpcc_disconnect_pending[mpcc_inst])) {
dc->res_pool->mpc->funcs->wait_for_idle(dc->res_pool->mpc, mpcc_inst);
dc->res_pool->opps[opp_inst]->mpcc_disconnect_pending[mpcc_inst] = false;
break;
@@ -3553,6 +3601,7 @@ static void commit_planes_for_stream(struct dc *dc,
bool should_lock_all_pipes = (update_type != UPDATE_TYPE_FAST);
bool subvp_prev_use = false;
bool subvp_curr_use = false;
+ uint8_t current_stream_mask = 0;
// Once we apply the new subvp context to hardware it won't be in the
// dc->current_state anymore, so we have to cache it before we apply
@@ -3568,7 +3617,7 @@ static void commit_planes_for_stream(struct dc *dc,
if (get_seamless_boot_stream_count(context) == 0)
dc->hwss.prepare_bandwidth(dc, context);
- if (dc->debug.enable_double_buffered_dsc_pg_support)
+ if (dc->hwss.update_dsc_pg)
dc->hwss.update_dsc_pg(dc, context, false);
context_clock_trace(dc, context);
@@ -3902,6 +3951,12 @@ static void commit_planes_for_stream(struct dc *dc,
if (pipe_ctx->stream_res.tg->funcs->program_manual_trigger)
pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg);
}
+
+ current_stream_mask = get_stream_mask(dc, context);
+ if (current_stream_mask != context->stream_mask) {
+ context->stream_mask = current_stream_mask;
+ dc_dmub_srv_notify_stream_mask(dc->ctx->dmub_srv, current_stream_mask);
+ }
}
/**
@@ -3909,6 +3964,7 @@ static void commit_planes_for_stream(struct dc *dc,
*
* @dc: Used to get the current state status
* @stream: Target stream, which we want to remove the attached planes
+ * @srf_updates: Array of surface updates
* @surface_count: Number of surface update
* @is_plane_addition: [in] Fill out with true if it is a plane addition case
*
@@ -3925,6 +3981,7 @@ static void commit_planes_for_stream(struct dc *dc,
*/
static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
struct dc_stream_state *stream,
+ struct dc_surface_update *srf_updates,
int surface_count,
bool *is_plane_addition)
{
@@ -3995,6 +4052,127 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
return force_minimal_pipe_splitting;
}
+struct pipe_split_policy_backup {
+ bool dynamic_odm_policy;
+ bool subvp_policy;
+ enum pipe_split_policy mpc_policy;
+};
+
+static void release_minimal_transition_state(struct dc *dc,
+ struct dc_state *context, struct pipe_split_policy_backup *policy)
+{
+ dc_release_state(context);
+ /* restore previous pipe split and odm policy */
+ if (!dc->config.is_vmin_only_asic)
+ dc->debug.pipe_split_policy = policy->mpc_policy;
+ dc->debug.enable_single_display_2to1_odm_policy = policy->dynamic_odm_policy;
+ dc->debug.force_disable_subvp = policy->subvp_policy;
+}
+
+static struct dc_state *create_minimal_transition_state(struct dc *dc,
+ struct dc_state *base_context, struct pipe_split_policy_backup *policy)
+{
+ struct dc_state *minimal_transition_context = dc_create_state(dc);
+ unsigned int i, j;
+
+ if (!dc->config.is_vmin_only_asic) {
+ policy->mpc_policy = dc->debug.pipe_split_policy;
+ dc->debug.pipe_split_policy = MPC_SPLIT_AVOID;
+ }
+ policy->dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy;
+ dc->debug.enable_single_display_2to1_odm_policy = false;
+ policy->subvp_policy = dc->debug.force_disable_subvp;
+ dc->debug.force_disable_subvp = true;
+
+ dc_resource_state_copy_construct(base_context, minimal_transition_context);
+
+ /* commit minimal state */
+ if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, false)) {
+ for (i = 0; i < minimal_transition_context->stream_count; i++) {
+ struct dc_stream_status *stream_status = &minimal_transition_context->stream_status[i];
+
+ for (j = 0; j < stream_status->plane_count; j++) {
+ struct dc_plane_state *plane_state = stream_status->plane_states[j];
+
+ /* force vsync flip when reconfiguring pipes to prevent underflow
+ * and corruption
+ */
+ plane_state->flip_immediate = false;
+ }
+ }
+ } else {
+ /* this should never happen */
+ release_minimal_transition_state(dc, minimal_transition_context, policy);
+ BREAK_TO_DEBUGGER();
+ minimal_transition_context = NULL;
+ }
+ return minimal_transition_context;
+}
+
+static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc,
+ struct dc_state *context,
+ struct dc_stream_state *stream)
+{
+ bool success = false;
+ struct dc_state *minimal_transition_context;
+ struct pipe_split_policy_backup policy;
+ struct mall_temp_config mall_temp_config;
+
+ /* commit based on new context */
+ /* Since all phantom pipes are removed in full validation,
+ * we have to save and restore the subvp/mall config when
+ * we do a minimal transition since the flags marking the
+ * pipe as subvp/phantom will be cleared (dc copy constructor
+ * creates a shallow copy).
+ */
+ if (dc->res_pool->funcs->save_mall_state)
+ dc->res_pool->funcs->save_mall_state(dc, context, &mall_temp_config);
+ minimal_transition_context = create_minimal_transition_state(dc,
+ context, &policy);
+ if (minimal_transition_context) {
+ if (dc->hwss.is_pipe_topology_transition_seamless(
+ dc, dc->current_state, minimal_transition_context) &&
+ dc->hwss.is_pipe_topology_transition_seamless(
+ dc, minimal_transition_context, context)) {
+ DC_LOG_DC("%s base = new state\n", __func__);
+
+ success = dc_commit_state_no_check(dc, minimal_transition_context) == DC_OK;
+ }
+ release_minimal_transition_state(dc, minimal_transition_context, &policy);
+ if (dc->res_pool->funcs->restore_mall_state)
+ dc->res_pool->funcs->restore_mall_state(dc, context, &mall_temp_config);
+ /* If we do a minimal transition with plane removal and the context
+ * has subvp we also have to retain back the phantom stream / planes
+ * since the refcount is decremented as part of the min transition
+ * (we commit a state with no subvp, so the phantom streams / planes
+ * had to be removed).
+ */
+ if (dc->res_pool->funcs->retain_phantom_pipes)
+ dc->res_pool->funcs->retain_phantom_pipes(dc, context);
+ }
+
+ if (!success) {
+ /* commit based on current context */
+ restore_plane_states_for_stream(dc->current_state->scratch.plane_states, stream);
+ minimal_transition_context = create_minimal_transition_state(dc,
+ dc->current_state, &policy);
+ if (minimal_transition_context) {
+ if (dc->hwss.is_pipe_topology_transition_seamless(
+ dc, dc->current_state, minimal_transition_context) &&
+ dc->hwss.is_pipe_topology_transition_seamless(
+ dc, minimal_transition_context, context)) {
+ DC_LOG_DC("%s base = current state\n", __func__);
+ success = dc_commit_state_no_check(dc, minimal_transition_context) == DC_OK;
+ }
+ release_minimal_transition_state(dc, minimal_transition_context, &policy);
+ }
+ restore_plane_states_for_stream(context->scratch.plane_states, stream);
+ }
+
+ ASSERT(success);
+ return success;
+}
+
/**
* commit_minimal_transition_state - Create a transition pipe split state
*
@@ -4016,23 +4194,14 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
static bool commit_minimal_transition_state(struct dc *dc,
struct dc_state *transition_base_context)
{
- struct dc_state *transition_context = dc_create_state(dc);
- enum pipe_split_policy tmp_mpc_policy = 0;
- bool temp_dynamic_odm_policy = 0;
- bool temp_subvp_policy = 0;
+ struct dc_state *transition_context;
+ struct pipe_split_policy_backup policy;
enum dc_status ret = DC_ERROR_UNEXPECTED;
unsigned int i, j;
unsigned int pipe_in_use = 0;
bool subvp_in_use = false;
bool odm_in_use = false;
- if (!transition_context)
- return false;
- /* Setup:
- * Store the current ODM and MPC config in some temp variables to be
- * restored after we commit the transition state.
- */
-
/* check current pipes in use*/
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &transition_base_context->res_ctx.pipe_ctx[i];
@@ -4057,10 +4226,10 @@ static bool commit_minimal_transition_state(struct dc *dc,
* pipe, we must use the minimal transition.
*/
for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+ struct pipe_ctx *pipe = &transition_base_context->res_ctx.pipe_ctx[i];
- if (pipe->stream && pipe->next_odm_pipe) {
- odm_in_use = true;
+ if (resource_is_pipe_type(pipe, OTG_MASTER)) {
+ odm_in_use = resource_get_odm_slice_count(pipe) > 1;
break;
}
}
@@ -4073,54 +4242,23 @@ static bool commit_minimal_transition_state(struct dc *dc,
* Reduce the scenarios to use dc_commit_state_no_check in the stage of flip. Especially
* enter/exit MPO when DCN still have enough resources.
*/
- if (pipe_in_use != dc->res_pool->pipe_count && !subvp_in_use && !odm_in_use) {
- dc_release_state(transition_context);
+ if (pipe_in_use != dc->res_pool->pipe_count && !subvp_in_use && !odm_in_use)
return true;
- }
-
- if (!dc->config.is_vmin_only_asic) {
- tmp_mpc_policy = dc->debug.pipe_split_policy;
- dc->debug.pipe_split_policy = MPC_SPLIT_AVOID;
- }
-
- temp_dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy;
- dc->debug.enable_single_display_2to1_odm_policy = false;
-
- temp_subvp_policy = dc->debug.force_disable_subvp;
- dc->debug.force_disable_subvp = true;
-
- dc_resource_state_copy_construct(transition_base_context, transition_context);
-
- /* commit minimal state */
- if (dc->res_pool->funcs->validate_bandwidth(dc, transition_context, false)) {
- for (i = 0; i < transition_context->stream_count; i++) {
- struct dc_stream_status *stream_status = &transition_context->stream_status[i];
-
- for (j = 0; j < stream_status->plane_count; j++) {
- struct dc_plane_state *plane_state = stream_status->plane_states[j];
- /* force vsync flip when reconfiguring pipes to prevent underflow
- * and corruption
- */
- plane_state->flip_immediate = false;
- }
- }
+ DC_LOG_DC("%s base = %s state, reason = %s\n", __func__,
+ dc->current_state == transition_base_context ? "current" : "new",
+ subvp_in_use ? "Subvp In Use" :
+ odm_in_use ? "ODM in Use" :
+ dc->debug.pipe_split_policy != MPC_SPLIT_AVOID ? "MPC in Use" :
+ "Unknown");
+ transition_context = create_minimal_transition_state(dc,
+ transition_base_context, &policy);
+ if (transition_context) {
ret = dc_commit_state_no_check(dc, transition_context);
+ release_minimal_transition_state(dc, transition_context, &policy);
}
- /* always release as dc_commit_state_no_check retains in good case */
- dc_release_state(transition_context);
-
- /* TearDown:
- * Restore original configuration for ODM and MPO.
- */
- if (!dc->config.is_vmin_only_asic)
- dc->debug.pipe_split_policy = tmp_mpc_policy;
-
- dc->debug.enable_single_display_2to1_odm_policy = temp_dynamic_odm_policy;
- dc->debug.force_disable_subvp = temp_subvp_policy;
-
if (ret != DC_OK) {
/* this should never happen */
BREAK_TO_DEBUGGER();
@@ -4233,7 +4371,6 @@ static bool full_update_required(struct dc *dc,
srf_updates[i].in_transfer_func ||
srf_updates[i].func_shaper ||
srf_updates[i].lut3d_func ||
- srf_updates[i].blend_tf ||
srf_updates[i].surface->force_full_update ||
(srf_updates[i].flip_addr &&
srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface) ||
@@ -4292,6 +4429,51 @@ static bool fast_update_only(struct dc *dc,
&& !full_update_required(dc, srf_updates, surface_count, stream_update, stream);
}
+static bool should_commit_minimal_transition_for_windowed_mpo_odm(struct dc *dc,
+ struct dc_stream_state *stream,
+ struct dc_state *context)
+{
+ struct pipe_ctx *cur_pipe, *new_pipe;
+ bool cur_is_odm_in_use, new_is_odm_in_use;
+ struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream);
+ struct dc_stream_status *new_stream_status = stream_get_status(context, stream);
+
+ if (!dc->debug.enable_single_display_2to1_odm_policy ||
+ !dc->config.enable_windowed_mpo_odm)
+ /* skip the check if windowed MPO ODM or dynamic ODM is turned
+ * off.
+ */
+ return false;
+
+ if (context == dc->current_state)
+ /* skip the check for fast update */
+ return false;
+
+ if (new_stream_status->plane_count != cur_stream_status->plane_count)
+ /* plane count changed, not a plane scaling update so not the
+ * case we are looking for
+ */
+ return false;
+
+ cur_pipe = resource_get_otg_master_for_stream(&dc->current_state->res_ctx, stream);
+ new_pipe = resource_get_otg_master_for_stream(&context->res_ctx, stream);
+ cur_is_odm_in_use = resource_get_odm_slice_count(cur_pipe) > 1;
+ new_is_odm_in_use = resource_get_odm_slice_count(new_pipe) > 1;
+ if (cur_is_odm_in_use == new_is_odm_in_use)
+ /* ODM state isn't changed, not the case we are looking for */
+ return false;
+
+ if (dc->hwss.is_pipe_topology_transition_seamless &&
+ dc->hwss.is_pipe_topology_transition_seamless(
+ dc, dc->current_state, context))
+ /* transition can be achieved without the need for committing
+ * minimal transition state first
+ */
+ return false;
+
+ return true;
+}
+
bool dc_update_planes_and_stream(struct dc *dc,
struct dc_surface_update *srf_updates, int surface_count,
struct dc_stream_state *stream,
@@ -4309,11 +4491,15 @@ bool dc_update_planes_and_stream(struct dc *dc,
*/
bool force_minimal_pipe_splitting = 0;
bool is_plane_addition = 0;
+ bool is_fast_update_only;
populate_fast_updates(fast_update, srf_updates, surface_count, stream_update);
+ is_fast_update_only = fast_update_only(dc, fast_update, srf_updates,
+ surface_count, stream_update, stream);
force_minimal_pipe_splitting = could_mpcc_tree_change_for_active_pipes(
dc,
stream,
+ srf_updates,
surface_count,
&is_plane_addition);
@@ -4360,9 +4546,21 @@ bool dc_update_planes_and_stream(struct dc *dc,
update_type = UPDATE_TYPE_FULL;
}
+ /* when windowed MPO ODM is supported, we need to handle a special case
+ * where we can transition between ODM combine and MPC combine due to
+ * plane scaling update. This transition will require us to commit
+ * minimal transition state. The condition to trigger this update can't
+ * be predicted by could_mpcc_tree_change_for_active_pipes because we
+ * can only determine it after DML validation. Therefore we can't rely
+ * on the existing commit minimal transition state sequence. Instead
+ * we have to add additional handling here to handle this transition
+ * with its own special sequence.
+ */
+ if (should_commit_minimal_transition_for_windowed_mpo_odm(dc, stream, context))
+ commit_minimal_transition_state_for_windowed_mpo_odm(dc,
+ context, stream);
update_seamless_boot_flags(dc, context, surface_count, stream);
- if (fast_update_only(dc, fast_update, srf_updates, surface_count, stream_update, stream) &&
- !dc->debug.enable_legacy_fast_update) {
+ if (is_fast_update_only && !dc->debug.enable_legacy_fast_update) {
commit_planes_for_stream_fast(dc,
srf_updates,
surface_count,
@@ -4371,6 +4569,13 @@ bool dc_update_planes_and_stream(struct dc *dc,
update_type,
context);
} else {
+ if (!stream_update &&
+ dc->hwss.is_pipe_topology_transition_seamless &&
+ !dc->hwss.is_pipe_topology_transition_seamless(
+ dc, dc->current_state, context)) {
+ DC_LOG_ERROR("performing non-seamless pipe topology transition with surface only update!\n");
+ BREAK_TO_DEBUGGER();
+ }
commit_planes_for_stream(
dc,
srf_updates,
@@ -4600,9 +4805,6 @@ void dc_set_power_state(
struct dc *dc,
enum dc_acpi_cm_power_state power_state)
{
- struct kref refcount;
- struct display_mode_lib *dml;
-
if (!dc->current_state)
return;
@@ -4622,30 +4824,8 @@ void dc_set_power_state(
break;
default:
ASSERT(dc->current_state->stream_count == 0);
- /* Zero out the current context so that on resume we start with
- * clean state, and dc hw programming optimizations will not
- * cause any trouble.
- */
- dml = kzalloc(sizeof(struct display_mode_lib),
- GFP_KERNEL);
-
- ASSERT(dml);
- if (!dml)
- return;
-
- /* Preserve refcount */
- refcount = dc->current_state->refcount;
- /* Preserve display mode lib */
- memcpy(dml, &dc->current_state->bw_ctx.dml, sizeof(struct display_mode_lib));
dc_resource_state_destruct(dc->current_state);
- memset(dc->current_state, 0,
- sizeof(*dc->current_state));
-
- dc->current_state->refcount = refcount;
- dc->current_state->bw_ctx.dml = *dml;
-
- kfree(dml);
break;
}
@@ -4727,6 +4907,9 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow)
if (dc->debug.disable_idle_power_optimizations)
return;
+ if (dc->caps.ips_support && (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL))
+ return;
+
if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->is_smu_present)
if (!dc->clk_mgr->funcs->is_smu_present(dc->clk_mgr))
return;
@@ -4738,6 +4921,26 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow)
dc->idle_optimizations_allowed = allow;
}
+bool dc_dmub_is_ips_idle_state(struct dc *dc)
+{
+ uint32_t idle_state = 0;
+
+ if (dc->debug.disable_idle_power_optimizations)
+ return false;
+
+ if (!dc->caps.ips_support || (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL))
+ return false;
+
+ if (dc->hwss.get_idle_state)
+ idle_state = dc->hwss.get_idle_state(dc);
+
+ if (!(idle_state & DMUB_IPS1_ALLOW_MASK) ||
+ !(idle_state & DMUB_IPS2_ALLOW_MASK))
+ return true;
+
+ return false;
+}
+
/* set min and max memory clock to lowest and highest DPM level, respectively */
void dc_unlock_memory_clock_frequency(struct dc *dc)
{
@@ -5270,14 +5473,55 @@ bool dc_abm_save_restore(
void dc_query_current_properties(struct dc *dc, struct dc_current_properties *properties)
{
unsigned int i;
- bool subvp_in_use = false;
+ bool subvp_sw_cursor_req = false;
for (i = 0; i < dc->current_state->stream_count; i++) {
- if (dc->current_state->streams[i]->mall_stream_config.type != SUBVP_NONE) {
- subvp_in_use = true;
+ if (check_subvp_sw_cursor_fallback_req(dc, dc->current_state->streams[i])) {
+ subvp_sw_cursor_req = true;
break;
}
}
- properties->cursor_size_limit = subvp_in_use ? 64 : dc->caps.max_cursor_size;
+ properties->cursor_size_limit = subvp_sw_cursor_req ? 64 : dc->caps.max_cursor_size;
+}
+
+/**
+ * dc_set_edp_power() - DM controls eDP power to be ON/OFF
+ *
+ * Called when DM wants to power on/off eDP.
+ * Only work on links with flag skip_implict_edp_power_control is set.
+ *
+ * @dc: Current DC state
+ * @edp_link: a link with eDP connector signal type
+ * @powerOn: power on/off eDP
+ *
+ * Return: void
+ */
+void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link,
+ bool powerOn)
+{
+ if (edp_link->connector_signal != SIGNAL_TYPE_EDP)
+ return;
+
+ if (edp_link->skip_implict_edp_power_control == false)
+ return;
+
+ edp_link->dc->link_srv->edp_set_panel_power(edp_link, powerOn);
+}
+
+/*
+ *****************************************************************************
+ * dc_get_power_profile_for_dc_state() - extracts power profile from dc state
+ *
+ * Called when DM wants to make power policy decisions based on dc_state
+ *
+ *****************************************************************************
+ */
+struct dc_power_profile dc_get_power_profile_for_dc_state(const struct dc_state *context)
+{
+ struct dc_power_profile profile = { 0 };
+
+ profile.power_level += !context->bw_ctx.bw.dcn.clk.p_state_change_support;
+
+ return profile;
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
index 69f1c2b89a57..801cdbc8117d 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
@@ -36,6 +36,8 @@
#include "resource.h"
+#define DC_LOGGER \
+ dc->ctx->logger
#define DC_LOGGER_INIT(logger)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index f99ec1b0efaf..fe07160932d6 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -29,6 +29,8 @@
#include "hw_sequencer.h"
#include "hw_sequencer_private.h"
#include "basics/dc_common.h"
+#include "resource.h"
+#include "dc_dmub_srv.h"
#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
@@ -526,6 +528,15 @@ void hwss_build_fast_sequence(struct dc *dc,
(*num_steps)++;
}
if (dc->hwss.update_plane_addr && current_mpc_pipe->plane_state->update_flags.bits.addr_update) {
+ if (resource_is_pipe_type(current_mpc_pipe, OTG_MASTER) &&
+ current_mpc_pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
+ block_sequence[*num_steps].params.subvp_save_surf_addr.dc_dmub_srv = dc->ctx->dmub_srv;
+ block_sequence[*num_steps].params.subvp_save_surf_addr.addr = &current_mpc_pipe->plane_state->address;
+ block_sequence[*num_steps].params.subvp_save_surf_addr.subvp_index = current_mpc_pipe->subvp_index;
+ block_sequence[*num_steps].func = DMUB_SUBVP_SAVE_SURF_ADDR;
+ (*num_steps)++;
+ }
+
block_sequence[*num_steps].params.update_plane_addr_params.dc = dc;
block_sequence[*num_steps].params.update_plane_addr_params.pipe_ctx = current_mpc_pipe;
block_sequence[*num_steps].func = HUBP_UPDATE_PLANE_ADDR;
@@ -697,6 +708,9 @@ void hwss_execute_sequence(struct dc *dc,
case DMUB_SEND_DMCUB_CMD:
hwss_send_dmcub_cmd(params);
break;
+ case DMUB_SUBVP_SAVE_SURF_ADDR:
+ hwss_subvp_save_surf_addr(params);
+ break;
default:
ASSERT(false);
break;
@@ -789,6 +803,15 @@ void hwss_set_ocsc_default(union block_sequence_params *params)
ocsc_mode);
}
+void hwss_subvp_save_surf_addr(union block_sequence_params *params)
+{
+ struct dc_dmub_srv *dc_dmub_srv = params->subvp_save_surf_addr.dc_dmub_srv;
+ const struct dc_plane_address *addr = params->subvp_save_surf_addr.addr;
+ uint8_t subvp_index = params->subvp_save_surf_addr.subvp_index;
+
+ dc_dmub_srv_subvp_save_surf_addr(dc_dmub_srv, addr, subvp_index);
+}
+
void get_mclk_switch_visual_confirm_color(
struct dc *dc,
struct dc_state *context,
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index f7b51aca6020..a1f1d1003992 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -41,6 +41,7 @@
#include "dpcd_defs.h"
#include "link_enc_cfg.h"
#include "link.h"
+#include "clk_mgr.h"
#include "virtual/virtual_link_hwss.h"
#include "link/hwss/link_hwss_dio.h"
#include "link/hwss/link_hwss_dpia.h"
@@ -70,6 +71,7 @@
#include "dcn316/dcn316_resource.h"
#include "../dcn32/dcn32_resource.h"
#include "../dcn321/dcn321_resource.h"
+#include "dcn35/dcn35_resource.h"
#define VISUAL_CONFIRM_BASE_DEFAULT 3
#define VISUAL_CONFIRM_BASE_MIN 1
@@ -81,8 +83,12 @@
*/
#define VISUAL_CONFIRM_DPP_OFFSET_DENO 240
+#define DC_LOGGER \
+ dc->ctx->logger
#define DC_LOGGER_INIT(logger)
+#include "dml2/dml2_wrapper.h"
+
#define UNABLE_TO_SPLIT -1
enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
@@ -186,6 +192,9 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
case AMDGPU_FAMILY_GC_11_0_1:
dc_version = DCN_VERSION_3_14;
break;
+ case AMDGPU_FAMILY_GC_11_5_0:
+ dc_version = DCN_VERSION_3_5;
+ break;
default:
dc_version = DCE_VERSION_UNKNOWN;
break;
@@ -290,6 +299,9 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc,
case DCN_VERSION_3_21:
res_pool = dcn321_create_resource_pool(init_data, dc);
break;
+ case DCN_VERSION_3_5:
+ res_pool = dcn35_create_resource_pool(init_data, dc);
+ break;
#endif /* CONFIG_DRM_AMD_DC_FP */
default:
break;
@@ -309,6 +321,11 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc,
res_pool->ref_clocks.xtalin_clock_inKhz;
res_pool->ref_clocks.dchub_ref_clock_inKhz =
res_pool->ref_clocks.xtalin_clock_inKhz;
+ if (dc->debug.using_dml2)
+ if (res_pool->hubbub && res_pool->hubbub->funcs->get_dchub_ref_freq)
+ res_pool->hubbub->funcs->get_dchub_ref_freq(res_pool->hubbub,
+ res_pool->ref_clocks.dccg_ref_clock_inKhz,
+ &res_pool->ref_clocks.dchub_ref_clock_inKhz);
} else
ASSERT_CRITICAL(false);
}
@@ -732,66 +749,6 @@ static inline void get_vp_scan_direction(
*flip_horz_scan_dir = !*flip_horz_scan_dir;
}
-int resource_get_num_mpc_splits(const struct pipe_ctx *pipe)
-{
- int mpc_split_count = 0;
- const struct pipe_ctx *other_pipe = pipe->bottom_pipe;
-
- while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
- mpc_split_count++;
- other_pipe = other_pipe->bottom_pipe;
- }
- other_pipe = pipe->top_pipe;
- while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
- mpc_split_count++;
- other_pipe = other_pipe->top_pipe;
- }
-
- return mpc_split_count;
-}
-
-int resource_get_num_odm_splits(const struct pipe_ctx *pipe)
-{
- int odm_split_count = 0;
-
- pipe = resource_get_otg_master(pipe);
-
- while (pipe->next_odm_pipe) {
- odm_split_count++;
- pipe = pipe->next_odm_pipe;
- }
- return odm_split_count;
-}
-
-static int get_odm_split_index(struct pipe_ctx *pipe_ctx)
-{
- int index = 0;
-
- pipe_ctx = resource_get_opp_head(pipe_ctx);
- if (!pipe_ctx)
- return 0;
-
- while (pipe_ctx->prev_odm_pipe) {
- index++;
- pipe_ctx = pipe_ctx->prev_odm_pipe;
- }
-
- return index;
-}
-
-static int get_mpc_split_index(struct pipe_ctx *pipe_ctx)
-{
- struct pipe_ctx *split_pipe = pipe_ctx->top_pipe;
- int index = 0;
-
- while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) {
- index++;
- split_pipe = split_pipe->top_pipe;
- }
-
- return index;
-}
-
/*
* This is a preliminary vp size calculation to allow us to check taps support.
* The result is completely overridden afterwards.
@@ -844,8 +801,8 @@ static struct rect shift_rec(const struct rect *rec_in, int x, int y)
static struct rect calculate_odm_slice_in_timing_active(struct pipe_ctx *pipe_ctx)
{
const struct dc_stream_state *stream = pipe_ctx->stream;
- int odm_slice_count = resource_get_num_odm_splits(pipe_ctx) + 1;
- int odm_slice_idx = get_odm_split_index(pipe_ctx);
+ int odm_slice_count = resource_get_odm_slice_count(pipe_ctx);
+ int odm_slice_idx = resource_get_odm_slice_index(pipe_ctx);
bool is_last_odm_slice = (odm_slice_idx + 1) == odm_slice_count;
int h_active = stream->timing.h_addressable +
stream->timing.h_border_left +
@@ -962,8 +919,8 @@ static struct rect calculate_mpc_slice_in_timing_active(
struct rect *plane_clip_rec)
{
const struct dc_stream_state *stream = pipe_ctx->stream;
- int mpc_slice_count = resource_get_num_mpc_splits(pipe_ctx) + 1;
- int mpc_slice_idx = get_mpc_split_index(pipe_ctx);
+ int mpc_slice_count = resource_get_mpc_slice_count(pipe_ctx);
+ int mpc_slice_idx = resource_get_mpc_slice_index(pipe_ctx);
int epimo = mpc_slice_count - plane_clip_rec->width % mpc_slice_count - 1;
struct rect mpc_rec;
@@ -996,7 +953,7 @@ static void adjust_recout_for_visual_confirm(struct rect *recout,
struct dc *dc = pipe_ctx->stream->ctx->dc;
int dpp_offset, base_offset;
- if (dc->debug.visual_confirm == VISUAL_CONFIRM_DISABLE)
+ if (dc->debug.visual_confirm == VISUAL_CONFIRM_DISABLE || !pipe_ctx->plane_res.dpp)
return;
dpp_offset = pipe_ctx->stream->timing.v_addressable / VISUAL_CONFIRM_DPP_OFFSET_DENO;
@@ -1385,6 +1342,136 @@ static void calculate_inits_and_viewports(struct pipe_ctx *pipe_ctx)
data->viewport_c.y += src.y / vpc_div;
}
+static bool is_subvp_high_refresh_candidate(struct dc_stream_state *stream)
+{
+ uint32_t refresh_rate;
+ struct dc *dc = stream->ctx->dc;
+
+ refresh_rate = (stream->timing.pix_clk_100hz * (uint64_t)100 +
+ stream->timing.v_total * stream->timing.h_total - (uint64_t)1);
+ refresh_rate = div_u64(refresh_rate, stream->timing.v_total);
+ refresh_rate = div_u64(refresh_rate, stream->timing.h_total);
+
+ /* If there's any stream that fits the SubVP high refresh criteria,
+ * we must return true. This is because cursor updates are asynchronous
+ * with full updates, so we could transition into a SubVP config and
+ * remain in HW cursor mode if there's no cursor update which will
+ * then cause corruption.
+ */
+ if ((refresh_rate >= 120 && refresh_rate <= 175 &&
+ stream->timing.v_addressable >= 1080 &&
+ stream->timing.v_addressable <= 2160) &&
+ (dc->current_state->stream_count > 1 ||
+ (dc->current_state->stream_count == 1 && !stream->allow_freesync)))
+ return true;
+
+ return false;
+}
+
+static enum controller_dp_test_pattern convert_dp_to_controller_test_pattern(
+ enum dp_test_pattern test_pattern)
+{
+ enum controller_dp_test_pattern controller_test_pattern;
+
+ switch (test_pattern) {
+ case DP_TEST_PATTERN_COLOR_SQUARES:
+ controller_test_pattern =
+ CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
+ break;
+ case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
+ controller_test_pattern =
+ CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
+ break;
+ case DP_TEST_PATTERN_VERTICAL_BARS:
+ controller_test_pattern =
+ CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
+ break;
+ case DP_TEST_PATTERN_HORIZONTAL_BARS:
+ controller_test_pattern =
+ CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
+ break;
+ case DP_TEST_PATTERN_COLOR_RAMP:
+ controller_test_pattern =
+ CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
+ break;
+ default:
+ controller_test_pattern =
+ CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
+ break;
+ }
+
+ return controller_test_pattern;
+}
+
+static enum controller_dp_color_space convert_dp_to_controller_color_space(
+ enum dp_test_pattern_color_space color_space)
+{
+ enum controller_dp_color_space controller_color_space;
+
+ switch (color_space) {
+ case DP_TEST_PATTERN_COLOR_SPACE_RGB:
+ controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
+ break;
+ case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
+ controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
+ break;
+ case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
+ controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
+ break;
+ case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
+ default:
+ controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
+ break;
+ }
+
+ return controller_color_space;
+}
+
+void resource_build_test_pattern_params(struct resource_context *res_ctx,
+ struct pipe_ctx *otg_master)
+{
+ int odm_slice_width, last_odm_slice_width, offset = 0;
+ struct pipe_ctx *opp_heads[MAX_PIPES];
+ struct test_pattern_params *params;
+ int odm_cnt = 1;
+ enum controller_dp_test_pattern controller_test_pattern;
+ enum controller_dp_color_space controller_color_space;
+ enum dc_color_depth color_depth = otg_master->stream->timing.display_color_depth;
+ int h_active = otg_master->stream->timing.h_addressable +
+ otg_master->stream->timing.h_border_left +
+ otg_master->stream->timing.h_border_right;
+ int v_active = otg_master->stream->timing.v_addressable +
+ otg_master->stream->timing.v_border_bottom +
+ otg_master->stream->timing.v_border_top;
+ int i;
+
+ controller_test_pattern = convert_dp_to_controller_test_pattern(
+ otg_master->stream->test_pattern.type);
+ controller_color_space = convert_dp_to_controller_color_space(
+ otg_master->stream->test_pattern.color_space);
+
+ odm_cnt = resource_get_opp_heads_for_otg_master(otg_master, res_ctx, opp_heads);
+
+ odm_slice_width = h_active / odm_cnt;
+ last_odm_slice_width = h_active - odm_slice_width * (odm_cnt - 1);
+
+ for (i = 0; i < odm_cnt; i++) {
+ params = &opp_heads[i]->stream_res.test_pattern_params;
+ params->test_pattern = controller_test_pattern;
+ params->color_space = controller_color_space;
+ params->color_depth = color_depth;
+ params->height = v_active;
+ params->offset = offset;
+
+ if (i < odm_cnt - 1)
+ params->width = odm_slice_width;
+ else
+ params->width = last_odm_slice_width;
+
+ offset += odm_slice_width;
+ }
+}
+
bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
{
const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
@@ -1424,13 +1511,6 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
/* depends on scaling ratios and recout, does not calculate offset yet */
calculate_viewport_size(pipe_ctx);
- if (!pipe_ctx->stream->ctx->dc->config.enable_windowed_mpo_odm) {
- /* Stopgap for validation of ODM + MPO on one side of screen case */
- if (pipe_ctx->plane_res.scl_data.viewport.height < 1 ||
- pipe_ctx->plane_res.scl_data.viewport.width < 1)
- return false;
- }
-
/*
* LB calculations depend on vp size, h/v_active and scaling ratios
* Setting line buffer pixel depth to 24bpp yields banding
@@ -1615,6 +1695,27 @@ struct pipe_ctx *resource_find_free_secondary_pipe_legacy(
return secondary_pipe;
}
+int resource_find_free_pipe_used_as_sec_opp_head_by_cur_otg_master(
+ const struct resource_context *cur_res_ctx,
+ struct resource_context *new_res_ctx,
+ const struct pipe_ctx *cur_otg_master)
+{
+ const struct pipe_ctx *cur_sec_opp_head = cur_otg_master->next_odm_pipe;
+ struct pipe_ctx *new_pipe;
+ int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND;
+
+ while (cur_sec_opp_head) {
+ new_pipe = &new_res_ctx->pipe_ctx[cur_sec_opp_head->pipe_idx];
+ if (resource_is_pipe_type(new_pipe, FREE_PIPE)) {
+ free_pipe_idx = cur_sec_opp_head->pipe_idx;
+ break;
+ }
+ cur_sec_opp_head = cur_sec_opp_head->next_odm_pipe;
+ }
+
+ return free_pipe_idx;
+}
+
int resource_find_free_pipe_used_in_cur_mpc_blending_tree(
const struct resource_context *cur_res_ctx,
struct resource_context *new_res_ctx,
@@ -1678,7 +1779,7 @@ int resource_find_free_pipe_used_as_cur_sec_dpp_in_mpcc_combine(
if (resource_is_pipe_type(cur_pipe, DPP_PIPE) &&
!resource_is_pipe_type(cur_pipe, OPP_HEAD) &&
- resource_is_for_mpcc_combine(cur_pipe) &&
+ resource_get_mpc_slice_index(cur_pipe) > 0 &&
resource_is_pipe_type(new_pipe, FREE_PIPE)) {
free_pipe_idx = i;
break;
@@ -1742,14 +1843,9 @@ bool resource_is_pipe_type(const struct pipe_ctx *pipe_ctx, enum pipe_type type)
}
}
-bool resource_is_for_mpcc_combine(const struct pipe_ctx *pipe_ctx)
-{
- return resource_get_num_mpc_splits(pipe_ctx) > 0;
-}
-
struct pipe_ctx *resource_get_otg_master_for_stream(
struct resource_context *res_ctx,
- struct dc_stream_state *stream)
+ const struct dc_stream_state *stream)
{
int i;
@@ -1761,6 +1857,75 @@ struct pipe_ctx *resource_get_otg_master_for_stream(
return NULL;
}
+int resource_get_opp_heads_for_otg_master(const struct pipe_ctx *otg_master,
+ struct resource_context *res_ctx,
+ struct pipe_ctx *opp_heads[MAX_PIPES])
+{
+ struct pipe_ctx *opp_head = &res_ctx->pipe_ctx[otg_master->pipe_idx];
+ int i = 0;
+
+ if (!resource_is_pipe_type(otg_master, OTG_MASTER)) {
+ ASSERT(0);
+ return 0;
+ }
+ while (opp_head) {
+ ASSERT(i < MAX_PIPES);
+ opp_heads[i++] = opp_head;
+ opp_head = opp_head->next_odm_pipe;
+ }
+ return i;
+}
+
+int resource_get_dpp_pipes_for_opp_head(const struct pipe_ctx *opp_head,
+ struct resource_context *res_ctx,
+ struct pipe_ctx *dpp_pipes[MAX_PIPES])
+{
+ struct pipe_ctx *pipe = &res_ctx->pipe_ctx[opp_head->pipe_idx];
+ int i = 0;
+
+ if (!resource_is_pipe_type(opp_head, OPP_HEAD)) {
+ ASSERT(0);
+ return 0;
+ }
+ while (pipe && resource_is_pipe_type(pipe, DPP_PIPE)) {
+ ASSERT(i < MAX_PIPES);
+ dpp_pipes[i++] = pipe;
+ pipe = pipe->bottom_pipe;
+ }
+ return i;
+}
+
+int resource_get_dpp_pipes_for_plane(const struct dc_plane_state *plane,
+ struct resource_context *res_ctx,
+ struct pipe_ctx *dpp_pipes[MAX_PIPES])
+{
+ int i = 0, j;
+ struct pipe_ctx *pipe;
+
+ for (j = 0; j < MAX_PIPES; j++) {
+ pipe = &res_ctx->pipe_ctx[j];
+ if (pipe->plane_state == plane && pipe->prev_odm_pipe == NULL) {
+ if (resource_is_pipe_type(pipe, OPP_HEAD) ||
+ pipe->top_pipe->plane_state != plane)
+ break;
+ }
+ }
+
+ if (j < MAX_PIPES) {
+ if (pipe->next_odm_pipe)
+ while (pipe) {
+ dpp_pipes[i++] = pipe;
+ pipe = pipe->next_odm_pipe;
+ }
+ else
+ while (pipe && pipe->plane_state == plane) {
+ dpp_pipes[i++] = pipe;
+ pipe = pipe->bottom_pipe;
+ }
+ }
+ return i;
+}
+
struct pipe_ctx *resource_get_otg_master(const struct pipe_ctx *pipe_ctx)
{
struct pipe_ctx *otg_master = resource_get_opp_head(pipe_ctx);
@@ -1780,6 +1945,261 @@ struct pipe_ctx *resource_get_opp_head(const struct pipe_ctx *pipe_ctx)
return opp_head;
}
+struct pipe_ctx *resource_get_primary_dpp_pipe(const struct pipe_ctx *dpp_pipe)
+{
+ struct pipe_ctx *pri_dpp_pipe = (struct pipe_ctx *) dpp_pipe;
+
+ ASSERT(resource_is_pipe_type(dpp_pipe, DPP_PIPE));
+ while (pri_dpp_pipe->prev_odm_pipe)
+ pri_dpp_pipe = pri_dpp_pipe->prev_odm_pipe;
+ while (pri_dpp_pipe->top_pipe &&
+ pri_dpp_pipe->top_pipe->plane_state == pri_dpp_pipe->plane_state)
+ pri_dpp_pipe = pri_dpp_pipe->top_pipe;
+ return pri_dpp_pipe;
+}
+
+
+int resource_get_mpc_slice_index(const struct pipe_ctx *pipe_ctx)
+{
+ struct pipe_ctx *split_pipe = pipe_ctx->top_pipe;
+ int index = 0;
+
+ while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) {
+ index++;
+ split_pipe = split_pipe->top_pipe;
+ }
+
+ return index;
+}
+
+int resource_get_mpc_slice_count(const struct pipe_ctx *pipe)
+{
+ int mpc_split_count = 1;
+ const struct pipe_ctx *other_pipe = pipe->bottom_pipe;
+
+ while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
+ mpc_split_count++;
+ other_pipe = other_pipe->bottom_pipe;
+ }
+ other_pipe = pipe->top_pipe;
+ while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
+ mpc_split_count++;
+ other_pipe = other_pipe->top_pipe;
+ }
+
+ return mpc_split_count;
+}
+
+int resource_get_odm_slice_count(const struct pipe_ctx *pipe)
+{
+ int odm_split_count = 1;
+
+ pipe = resource_get_otg_master(pipe);
+
+ while (pipe->next_odm_pipe) {
+ odm_split_count++;
+ pipe = pipe->next_odm_pipe;
+ }
+ return odm_split_count;
+}
+
+int resource_get_odm_slice_index(const struct pipe_ctx *pipe_ctx)
+{
+ int index = 0;
+
+ pipe_ctx = resource_get_opp_head(pipe_ctx);
+ if (!pipe_ctx)
+ return 0;
+
+ while (pipe_ctx->prev_odm_pipe) {
+ index++;
+ pipe_ctx = pipe_ctx->prev_odm_pipe;
+ }
+
+ return index;
+}
+
+bool resource_is_pipe_topology_changed(const struct dc_state *state_a,
+ const struct dc_state *state_b)
+{
+ int i;
+ const struct pipe_ctx *pipe_a, *pipe_b;
+
+ if (state_a->stream_count != state_b->stream_count)
+ return true;
+
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_a = &state_a->res_ctx.pipe_ctx[i];
+ pipe_b = &state_b->res_ctx.pipe_ctx[i];
+
+ if (pipe_a->stream && !pipe_b->stream)
+ return true;
+ else if (!pipe_a->stream && pipe_b->stream)
+ return true;
+
+ if (pipe_a->plane_state && !pipe_b->plane_state)
+ return true;
+ else if (!pipe_a->plane_state && pipe_b->plane_state)
+ return true;
+
+ if (pipe_a->bottom_pipe && pipe_b->bottom_pipe) {
+ if (pipe_a->bottom_pipe->pipe_idx != pipe_b->bottom_pipe->pipe_idx)
+ return true;
+ if ((pipe_a->bottom_pipe->plane_state == pipe_a->plane_state) &&
+ (pipe_b->bottom_pipe->plane_state != pipe_b->plane_state))
+ return true;
+ else if ((pipe_a->bottom_pipe->plane_state != pipe_a->plane_state) &&
+ (pipe_b->bottom_pipe->plane_state == pipe_b->plane_state))
+ return true;
+ } else if (pipe_a->bottom_pipe || pipe_b->bottom_pipe) {
+ return true;
+ }
+
+ if (pipe_a->next_odm_pipe && pipe_b->next_odm_pipe) {
+ if (pipe_a->next_odm_pipe->pipe_idx != pipe_b->next_odm_pipe->pipe_idx)
+ return true;
+ } else if (pipe_a->next_odm_pipe || pipe_b->next_odm_pipe) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool resource_is_odm_topology_changed(const struct pipe_ctx *otg_master_a,
+ const struct pipe_ctx *otg_master_b)
+{
+ const struct pipe_ctx *opp_head_a = otg_master_a;
+ const struct pipe_ctx *opp_head_b = otg_master_b;
+
+ if (!resource_is_pipe_type(otg_master_a, OTG_MASTER) ||
+ !resource_is_pipe_type(otg_master_b, OTG_MASTER))
+ return true;
+
+ while (opp_head_a && opp_head_b) {
+ if (opp_head_a->stream_res.opp != opp_head_b->stream_res.opp)
+ return true;
+ if ((opp_head_a->next_odm_pipe && !opp_head_b->next_odm_pipe) ||
+ (!opp_head_a->next_odm_pipe && opp_head_b->next_odm_pipe))
+ return true;
+ opp_head_a = opp_head_a->next_odm_pipe;
+ opp_head_b = opp_head_b->next_odm_pipe;
+ }
+
+ return false;
+}
+
+/*
+ * Sample log:
+ * pipe topology update
+ * ________________________
+ * | plane0 slice0 stream0|
+ * |DPP0----OPP0----OTG0----| <--- case 0 (OTG master pipe with plane)
+ * | plane1 | | |
+ * |DPP1----| | | <--- case 5 (DPP pipe not in last slice)
+ * | plane0 slice1 | |
+ * |DPP2----OPP2----| | <--- case 2 (OPP head pipe with plane)
+ * | plane1 | |
+ * |DPP3----| | <--- case 4 (DPP pipe in last slice)
+ * | slice0 stream1|
+ * |DPG4----OPP4----OTG4----| <--- case 1 (OTG master pipe without plane)
+ * | slice1 | |
+ * |DPG5----OPP5----| | <--- case 3 (OPP head pipe without plane)
+ * |________________________|
+ */
+
+static void resource_log_pipe(struct dc *dc, struct pipe_ctx *pipe,
+ int stream_idx, int slice_idx, int plane_idx, int slice_count,
+ bool is_primary)
+{
+ DC_LOGGER_INIT(dc->ctx->logger);
+
+ if (slice_idx == 0 && plane_idx == 0 && is_primary) {
+ /* case 0 (OTG master pipe with plane) */
+ DC_LOG_DC(" | plane%d slice%d stream%d|",
+ plane_idx, slice_idx, stream_idx);
+ DC_LOG_DC(" |DPP%d----OPP%d----OTG%d----|",
+ pipe->plane_res.dpp->inst,
+ pipe->stream_res.opp->inst,
+ pipe->stream_res.tg->inst);
+ } else if (slice_idx == 0 && plane_idx == -1) {
+ /* case 1 (OTG master pipe without plane) */
+ DC_LOG_DC(" | slice%d stream%d|",
+ slice_idx, stream_idx);
+ DC_LOG_DC(" |DPG%d----OPP%d----OTG%d----|",
+ pipe->stream_res.opp->inst,
+ pipe->stream_res.opp->inst,
+ pipe->stream_res.tg->inst);
+ } else if (slice_idx != 0 && plane_idx == 0 && is_primary) {
+ /* case 2 (OPP head pipe with plane) */
+ DC_LOG_DC(" | plane%d slice%d | |",
+ plane_idx, slice_idx);
+ DC_LOG_DC(" |DPP%d----OPP%d----| |",
+ pipe->plane_res.dpp->inst,
+ pipe->stream_res.opp->inst);
+ } else if (slice_idx != 0 && plane_idx == -1) {
+ /* case 3 (OPP head pipe without plane) */
+ DC_LOG_DC(" | slice%d | |", slice_idx);
+ DC_LOG_DC(" |DPG%d----OPP%d----| |",
+ pipe->plane_res.dpp->inst,
+ pipe->stream_res.opp->inst);
+ } else if (slice_idx == slice_count - 1) {
+ /* case 4 (DPP pipe in last slice) */
+ DC_LOG_DC(" | plane%d | |", plane_idx);
+ DC_LOG_DC(" |DPP%d----| |",
+ pipe->plane_res.dpp->inst);
+ } else {
+ /* case 5 (DPP pipe not in last slice) */
+ DC_LOG_DC(" | plane%d | | |", plane_idx);
+ DC_LOG_DC(" |DPP%d----| | |",
+ pipe->plane_res.dpp->inst);
+ }
+}
+
+void resource_log_pipe_topology_update(struct dc *dc, struct dc_state *state)
+{
+ struct pipe_ctx *otg_master;
+ struct pipe_ctx *opp_heads[MAX_PIPES];
+ struct pipe_ctx *dpp_pipes[MAX_PIPES];
+
+ int stream_idx, slice_idx, dpp_idx, plane_idx, slice_count, dpp_count;
+ bool is_primary;
+ DC_LOGGER_INIT(dc->ctx->logger);
+
+ DC_LOG_DC(" pipe topology update");
+ DC_LOG_DC(" ________________________");
+ for (stream_idx = 0; stream_idx < state->stream_count; stream_idx++) {
+ otg_master = resource_get_otg_master_for_stream(
+ &state->res_ctx, state->streams[stream_idx]);
+ slice_count = resource_get_opp_heads_for_otg_master(otg_master,
+ &state->res_ctx, opp_heads);
+ for (slice_idx = 0; slice_idx < slice_count; slice_idx++) {
+ plane_idx = -1;
+ if (opp_heads[slice_idx]->plane_state) {
+ dpp_count = resource_get_dpp_pipes_for_opp_head(
+ opp_heads[slice_idx],
+ &state->res_ctx,
+ dpp_pipes);
+ for (dpp_idx = 0; dpp_idx < dpp_count; dpp_idx++) {
+ is_primary = !dpp_pipes[dpp_idx]->top_pipe ||
+ dpp_pipes[dpp_idx]->top_pipe->plane_state != dpp_pipes[dpp_idx]->plane_state;
+ if (is_primary)
+ plane_idx++;
+ resource_log_pipe(dc, dpp_pipes[dpp_idx],
+ stream_idx, slice_idx,
+ plane_idx, slice_count,
+ is_primary);
+ }
+ } else {
+ resource_log_pipe(dc, opp_heads[slice_idx],
+ stream_idx, slice_idx, plane_idx,
+ slice_count, true);
+ }
+
+ }
+ }
+ DC_LOG_DC(" |________________________|\n");
+}
+
static struct pipe_ctx *get_tail_pipe(
struct pipe_ctx *head_pipe)
{
@@ -1793,6 +2213,59 @@ static struct pipe_ctx *get_tail_pipe(
return head_pipe;
}
+static struct pipe_ctx *get_last_opp_head(
+ struct pipe_ctx *opp_head)
+{
+ ASSERT(resource_is_pipe_type(opp_head, OPP_HEAD));
+ while (opp_head->next_odm_pipe)
+ opp_head = opp_head->next_odm_pipe;
+ return opp_head;
+}
+
+static struct pipe_ctx *get_last_dpp_pipe_in_mpcc_combine(
+ struct pipe_ctx *dpp_pipe)
+{
+ ASSERT(resource_is_pipe_type(dpp_pipe, DPP_PIPE));
+ while (dpp_pipe->bottom_pipe &&
+ dpp_pipe->plane_state == dpp_pipe->bottom_pipe->plane_state)
+ dpp_pipe = dpp_pipe->bottom_pipe;
+ return dpp_pipe;
+}
+
+static bool update_pipe_params_after_odm_slice_count_change(
+ const struct dc_stream_state *stream,
+ struct dc_state *context,
+ const struct resource_pool *pool)
+{
+ int i;
+ struct pipe_ctx *pipe;
+ bool result = true;
+
+ for (i = 0; i < pool->pipe_count && result; i++) {
+ pipe = &context->res_ctx.pipe_ctx[i];
+ if (pipe->stream == stream && pipe->plane_state)
+ result = resource_build_scaling_params(pipe);
+ }
+ return result;
+}
+
+static bool update_pipe_params_after_mpc_slice_count_change(
+ const struct dc_plane_state *plane,
+ struct dc_state *context,
+ const struct resource_pool *pool)
+{
+ int i;
+ struct pipe_ctx *pipe;
+ bool result = true;
+
+ for (i = 0; i < pool->pipe_count && result; i++) {
+ pipe = &context->res_ctx.pipe_ctx[i];
+ if (pipe->plane_state == plane)
+ result = resource_build_scaling_params(pipe);
+ }
+ return result;
+}
+
static int acquire_first_split_pipe(
struct resource_context *res_ctx,
const struct resource_pool *pool,
@@ -1825,9 +2298,199 @@ static int acquire_first_split_pipe(
return i;
}
}
- return UNABLE_TO_SPLIT;
+ return FREE_PIPE_INDEX_NOT_FOUND;
}
+static void update_stream_engine_usage(
+ struct resource_context *res_ctx,
+ const struct resource_pool *pool,
+ struct stream_encoder *stream_enc,
+ bool acquired)
+{
+ int i;
+
+ for (i = 0; i < pool->stream_enc_count; i++) {
+ if (pool->stream_enc[i] == stream_enc)
+ res_ctx->is_stream_enc_acquired[i] = acquired;
+ }
+}
+
+static void update_hpo_dp_stream_engine_usage(
+ struct resource_context *res_ctx,
+ const struct resource_pool *pool,
+ struct hpo_dp_stream_encoder *hpo_dp_stream_enc,
+ bool acquired)
+{
+ int i;
+
+ for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) {
+ if (pool->hpo_dp_stream_enc[i] == hpo_dp_stream_enc)
+ res_ctx->is_hpo_dp_stream_enc_acquired[i] = acquired;
+ }
+}
+
+static inline int find_acquired_hpo_dp_link_enc_for_link(
+ const struct resource_context *res_ctx,
+ const struct dc_link *link)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_to_link_idx); i++)
+ if (res_ctx->hpo_dp_link_enc_ref_cnts[i] > 0 &&
+ res_ctx->hpo_dp_link_enc_to_link_idx[i] == link->link_index)
+ return i;
+
+ return -1;
+}
+
+static inline int find_free_hpo_dp_link_enc(const struct resource_context *res_ctx,
+ const struct resource_pool *pool)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_ref_cnts); i++)
+ if (res_ctx->hpo_dp_link_enc_ref_cnts[i] == 0)
+ break;
+
+ return (i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_ref_cnts) &&
+ i < pool->hpo_dp_link_enc_count) ? i : -1;
+}
+
+static inline void acquire_hpo_dp_link_enc(
+ struct resource_context *res_ctx,
+ unsigned int link_index,
+ int enc_index)
+{
+ res_ctx->hpo_dp_link_enc_to_link_idx[enc_index] = link_index;
+ res_ctx->hpo_dp_link_enc_ref_cnts[enc_index] = 1;
+}
+
+static inline void retain_hpo_dp_link_enc(
+ struct resource_context *res_ctx,
+ int enc_index)
+{
+ res_ctx->hpo_dp_link_enc_ref_cnts[enc_index]++;
+}
+
+static inline void release_hpo_dp_link_enc(
+ struct resource_context *res_ctx,
+ int enc_index)
+{
+ ASSERT(res_ctx->hpo_dp_link_enc_ref_cnts[enc_index] > 0);
+ res_ctx->hpo_dp_link_enc_ref_cnts[enc_index]--;
+}
+
+static bool add_hpo_dp_link_enc_to_ctx(struct resource_context *res_ctx,
+ const struct resource_pool *pool,
+ struct pipe_ctx *pipe_ctx,
+ struct dc_stream_state *stream)
+{
+ int enc_index;
+
+ enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, stream->link);
+
+ if (enc_index >= 0) {
+ retain_hpo_dp_link_enc(res_ctx, enc_index);
+ } else {
+ enc_index = find_free_hpo_dp_link_enc(res_ctx, pool);
+ if (enc_index >= 0)
+ acquire_hpo_dp_link_enc(res_ctx, stream->link->link_index, enc_index);
+ }
+
+ if (enc_index >= 0)
+ pipe_ctx->link_res.hpo_dp_link_enc = pool->hpo_dp_link_enc[enc_index];
+
+ return pipe_ctx->link_res.hpo_dp_link_enc != NULL;
+}
+
+static void remove_hpo_dp_link_enc_from_ctx(struct resource_context *res_ctx,
+ struct pipe_ctx *pipe_ctx,
+ struct dc_stream_state *stream)
+{
+ int enc_index;
+
+ enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, stream->link);
+
+ if (enc_index >= 0) {
+ release_hpo_dp_link_enc(res_ctx, enc_index);
+ pipe_ctx->link_res.hpo_dp_link_enc = NULL;
+ }
+}
+
+enum dc_status resource_add_otg_master_for_stream_output(struct dc_state *new_ctx,
+ const struct resource_pool *pool,
+ struct dc_stream_state *stream)
+{
+ struct dc *dc = stream->ctx->dc;
+
+ return dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream);
+}
+
+void resource_remove_otg_master_for_stream_output(struct dc_state *context,
+ const struct resource_pool *pool,
+ struct dc_stream_state *stream)
+{
+ struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(
+ &context->res_ctx, stream);
+
+ ASSERT(resource_get_odm_slice_count(otg_master) == 1);
+ ASSERT(otg_master->plane_state == NULL);
+ ASSERT(otg_master->stream_res.stream_enc);
+ update_stream_engine_usage(
+ &context->res_ctx,
+ pool,
+ otg_master->stream_res.stream_enc,
+ false);
+
+ if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(otg_master)) {
+ update_hpo_dp_stream_engine_usage(
+ &context->res_ctx, pool,
+ otg_master->stream_res.hpo_dp_stream_enc,
+ false);
+ remove_hpo_dp_link_enc_from_ctx(
+ &context->res_ctx, otg_master, stream);
+ }
+ if (otg_master->stream_res.audio)
+ update_audio_usage(
+ &context->res_ctx,
+ pool,
+ otg_master->stream_res.audio,
+ false);
+
+ resource_unreference_clock_source(&context->res_ctx,
+ pool,
+ otg_master->clock_source);
+
+ if (pool->funcs->remove_stream_from_ctx)
+ pool->funcs->remove_stream_from_ctx(
+ stream->ctx->dc, context, stream);
+ memset(otg_master, 0, sizeof(*otg_master));
+}
+
+/* For each OPP head of an OTG master, add top plane at plane index 0.
+ *
+ * In the following example, the stream has 2 ODM slices without a top plane.
+ * By adding a plane 0 to OPP heads, we are configuring our hardware to render
+ * plane 0 by using each OPP head's DPP.
+ *
+ * Inter-pipe Relation (Before Adding Plane)
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | | slice 0 | |
+ * | 0 | |blank ----ODM----------- |
+ * | | | slice 1 | | |
+ * | 1 | |blank ---- | |
+ * |________|_______________|___________|_____________|
+ *
+ * Inter-pipe Relation (After Adding Plane)
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | plane 0 | slice 0 | |
+ * | 0 | -------------------------ODM----------- |
+ * | | plane 0 | slice 1 | | |
+ * | 1 | ------------------------- | |
+ * |________|_______________|___________|_____________|
+ */
static bool add_plane_to_opp_head_pipes(struct pipe_ctx *otg_master_pipe,
struct dc_plane_state *plane_state,
struct dc_state *context)
@@ -1846,24 +2509,36 @@ static bool add_plane_to_opp_head_pipes(struct pipe_ctx *otg_master_pipe,
return true;
}
-static void insert_secondary_dpp_pipe_with_plane(struct pipe_ctx *opp_head_pipe,
- struct pipe_ctx *sec_pipe, struct dc_plane_state *plane_state)
-{
- struct pipe_ctx *tail_pipe = get_tail_pipe(opp_head_pipe);
-
- tail_pipe->bottom_pipe = sec_pipe;
- sec_pipe->top_pipe = tail_pipe;
- if (tail_pipe->prev_odm_pipe) {
- ASSERT(tail_pipe->prev_odm_pipe->bottom_pipe);
- sec_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe;
- tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = sec_pipe;
- }
- sec_pipe->plane_state = plane_state;
-}
-
-/* for each opp head pipe of an otg master pipe, acquire a secondary dpp pipe
- * and add the plane. So the plane is added to all MPC blend trees associated
- * with the otg master pipe.
+/* For each OPP head of an OTG master, acquire a secondary DPP pipe and add
+ * the plane. So the plane is added to all ODM slices associated with the OTG
+ * master pipe in the bottom layer.
+ *
+ * In the following example, the stream has 2 ODM slices and a top plane 0.
+ * By acquiring secondary DPP pipes and adding a plane 1, we are configuring our
+ * hardware to render the plane 1 by acquiring a new pipe for each ODM slice and
+ * render plane 1 using new pipes' DPP in the Z axis below plane 0.
+ *
+ * Inter-pipe Relation (Before Adding Plane)
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | plane 0 | slice 0 | |
+ * | 0 | -------------------------ODM----------- |
+ * | | plane 0 | slice 1 | | |
+ * | 1 | ------------------------- | |
+ * |________|_______________|___________|_____________|
+ *
+ * Inter-pipe Relation (After Acquiring and Adding Plane)
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | plane 0 | slice 0 | |
+ * | 0 | -------------MPC---------ODM----------- |
+ * | | plane 1 | | | | |
+ * | 2 | ------------- | | | |
+ * | | plane 0 | slice 1 | | |
+ * | 1 | -------------MPC--------- | |
+ * | | plane 1 | | | |
+ * | 3 | ------------- | | |
+ * |________|_______________|___________|_____________|
*/
static bool acquire_secondary_dpp_pipes_and_add_plane(
struct pipe_ctx *otg_master_pipe,
@@ -1872,10 +2547,12 @@ static bool acquire_secondary_dpp_pipes_and_add_plane(
struct dc_state *cur_ctx,
struct resource_pool *pool)
{
- struct pipe_ctx *opp_head_pipe, *sec_pipe;
+ struct pipe_ctx *opp_head_pipe, *sec_pipe, *tail_pipe;
- if (!pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe)
+ if (!pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe) {
+ ASSERT(0);
return false;
+ }
opp_head_pipe = otg_master_pipe;
while (opp_head_pipe) {
@@ -1897,13 +2574,399 @@ static bool acquire_secondary_dpp_pipes_and_add_plane(
if (!sec_pipe)
return false;
- insert_secondary_dpp_pipe_with_plane(opp_head_pipe, sec_pipe,
- plane_state);
+ sec_pipe->plane_state = plane_state;
+
+ /* establish pipe relationship */
+ tail_pipe = get_tail_pipe(opp_head_pipe);
+ tail_pipe->bottom_pipe = sec_pipe;
+ sec_pipe->top_pipe = tail_pipe;
+ sec_pipe->bottom_pipe = NULL;
+ if (tail_pipe->prev_odm_pipe) {
+ ASSERT(tail_pipe->prev_odm_pipe->bottom_pipe);
+ sec_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe;
+ tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = sec_pipe;
+ } else {
+ sec_pipe->prev_odm_pipe = NULL;
+ }
+
opp_head_pipe = opp_head_pipe->next_odm_pipe;
}
return true;
}
+bool resource_append_dpp_pipes_for_plane_composition(
+ struct dc_state *new_ctx,
+ struct dc_state *cur_ctx,
+ struct resource_pool *pool,
+ struct pipe_ctx *otg_master_pipe,
+ struct dc_plane_state *plane_state)
+{
+ if (otg_master_pipe->plane_state == NULL)
+ return add_plane_to_opp_head_pipes(otg_master_pipe,
+ plane_state, new_ctx);
+ else
+ return acquire_secondary_dpp_pipes_and_add_plane(
+ otg_master_pipe, plane_state, new_ctx,
+ cur_ctx, pool);
+}
+
+void resource_remove_dpp_pipes_for_plane_composition(
+ struct dc_state *context,
+ const struct resource_pool *pool,
+ const struct dc_plane_state *plane_state)
+{
+ int i;
+ for (i = pool->pipe_count - 1; i >= 0; i--) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+ if (pipe_ctx->plane_state == plane_state) {
+ if (pipe_ctx->top_pipe)
+ pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
+
+ /* Second condition is to avoid setting NULL to top pipe
+ * of tail pipe making it look like head pipe in subsequent
+ * deletes
+ */
+ if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe)
+ pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe;
+
+ /*
+ * For head pipe detach surfaces from pipe for tail
+ * pipe just zero it out
+ */
+ if (!pipe_ctx->top_pipe)
+ pipe_ctx->plane_state = NULL;
+ else
+ memset(pipe_ctx, 0, sizeof(*pipe_ctx));
+ }
+ }
+}
+
+/*
+ * Increase ODM slice count by 1 by acquiring pipes and adding a new ODM slice
+ * at the last index.
+ * return - true if a new ODM slice is added and required pipes are acquired.
+ * false if new_ctx is no longer a valid state after new ODM slice is added.
+ *
+ * This is achieved by duplicating MPC blending tree from previous ODM slice.
+ * In the following example, we have a single MPC tree and 1 ODM slice 0. We
+ * want to add a new odm slice by duplicating the MPC blending tree and add
+ * ODM slice 1.
+ *
+ * Inter-pipe Relation (Before Acquiring and Adding ODM Slice)
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | plane 0 | slice 0 | |
+ * | 0 | -------------MPC---------ODM----------- |
+ * | | plane 1 | | | |
+ * | 1 | ------------- | | |
+ * |________|_______________|___________|_____________|
+ *
+ * Inter-pipe Relation (After Acquiring and Adding ODM Slice)
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | plane 0 | slice 0 | |
+ * | 0 | -------------MPC---------ODM----------- |
+ * | | plane 1 | | | | |
+ * | 1 | ------------- | | | |
+ * | | plane 0 | slice 1 | | |
+ * | 2 | -------------MPC--------- | |
+ * | | plane 1 | | | |
+ * | 3 | ------------- | | |
+ * |________|_______________|___________|_____________|
+ */
+static bool acquire_pipes_and_add_odm_slice(
+ struct pipe_ctx *otg_master_pipe,
+ struct dc_state *new_ctx,
+ const struct dc_state *cur_ctx,
+ const struct resource_pool *pool)
+{
+ struct pipe_ctx *last_opp_head = get_last_opp_head(otg_master_pipe);
+ struct pipe_ctx *new_opp_head;
+ struct pipe_ctx *last_top_dpp_pipe, *last_bottom_dpp_pipe,
+ *new_top_dpp_pipe, *new_bottom_dpp_pipe;
+
+ if (!pool->funcs->acquire_free_pipe_as_secondary_opp_head) {
+ ASSERT(0);
+ return false;
+ }
+ new_opp_head = pool->funcs->acquire_free_pipe_as_secondary_opp_head(
+ cur_ctx, new_ctx, pool,
+ otg_master_pipe);
+ if (!new_opp_head)
+ return false;
+
+ last_opp_head->next_odm_pipe = new_opp_head;
+ new_opp_head->prev_odm_pipe = last_opp_head;
+ new_opp_head->next_odm_pipe = NULL;
+ new_opp_head->plane_state = last_opp_head->plane_state;
+ last_top_dpp_pipe = last_opp_head;
+ new_top_dpp_pipe = new_opp_head;
+
+ while (last_top_dpp_pipe->bottom_pipe) {
+ last_bottom_dpp_pipe = last_top_dpp_pipe->bottom_pipe;
+ new_bottom_dpp_pipe = pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe(
+ cur_ctx, new_ctx, pool,
+ new_opp_head);
+ if (!new_bottom_dpp_pipe)
+ return false;
+
+ new_bottom_dpp_pipe->plane_state = last_bottom_dpp_pipe->plane_state;
+ new_top_dpp_pipe->bottom_pipe = new_bottom_dpp_pipe;
+ new_bottom_dpp_pipe->top_pipe = new_top_dpp_pipe;
+ last_bottom_dpp_pipe->next_odm_pipe = new_bottom_dpp_pipe;
+ new_bottom_dpp_pipe->prev_odm_pipe = last_bottom_dpp_pipe;
+ new_bottom_dpp_pipe->next_odm_pipe = NULL;
+ last_top_dpp_pipe = last_bottom_dpp_pipe;
+ }
+
+ return true;
+}
+
+/*
+ * Decrease ODM slice count by 1 by releasing pipes and removing the ODM slice
+ * at the last index.
+ * return - true if the last ODM slice is removed and related pipes are
+ * released. false if there is no removable ODM slice.
+ *
+ * In the following example, we have 2 MPC trees and ODM slice 0 and slice 1.
+ * We want to remove the last ODM i.e slice 1. We are releasing secondary DPP
+ * pipe 3 and OPP head pipe 2.
+ *
+ * Inter-pipe Relation (Before Releasing and Removing ODM Slice)
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | plane 0 | slice 0 | |
+ * | 0 | -------------MPC---------ODM----------- |
+ * | | plane 1 | | | | |
+ * | 1 | ------------- | | | |
+ * | | plane 0 | slice 1 | | |
+ * | 2 | -------------MPC--------- | |
+ * | | plane 1 | | | |
+ * | 3 | ------------- | | |
+ * |________|_______________|___________|_____________|
+ *
+ * Inter-pipe Relation (After Releasing and Removing ODM Slice)
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | plane 0 | slice 0 | |
+ * | 0 | -------------MPC---------ODM----------- |
+ * | | plane 1 | | | |
+ * | 1 | ------------- | | |
+ * |________|_______________|___________|_____________|
+ */
+static bool release_pipes_and_remove_odm_slice(
+ struct pipe_ctx *otg_master_pipe,
+ struct dc_state *context,
+ const struct resource_pool *pool)
+{
+ struct pipe_ctx *last_opp_head = get_last_opp_head(otg_master_pipe);
+ struct pipe_ctx *tail_pipe = get_tail_pipe(last_opp_head);
+
+ if (!pool->funcs->release_pipe) {
+ ASSERT(0);
+ return false;
+ }
+
+ if (resource_is_pipe_type(last_opp_head, OTG_MASTER))
+ return false;
+
+ while (tail_pipe->top_pipe) {
+ tail_pipe->prev_odm_pipe->next_odm_pipe = NULL;
+ tail_pipe = tail_pipe->top_pipe;
+ pool->funcs->release_pipe(context, tail_pipe->bottom_pipe, pool);
+ tail_pipe->bottom_pipe = NULL;
+ }
+ last_opp_head->prev_odm_pipe->next_odm_pipe = NULL;
+ pool->funcs->release_pipe(context, last_opp_head, pool);
+
+ return true;
+}
+
+/*
+ * Increase MPC slice count by 1 by acquiring a new DPP pipe and add it as the
+ * last MPC slice of the plane associated with dpp_pipe.
+ *
+ * return - true if a new MPC slice is added and required pipes are acquired.
+ * false if new_ctx is no longer a valid state after new MPC slice is added.
+ *
+ * In the following example, we add a new MPC slice for plane 0 into the
+ * new_ctx. To do so we pass pipe 0 as dpp_pipe. The function acquires a new DPP
+ * pipe 2 for plane 0 as the bottom most pipe for plane 0.
+ *
+ * Inter-pipe Relation (Before Acquiring and Adding MPC Slice)
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | plane 0 | | |
+ * | 0 | -------------MPC----------------------- |
+ * | | plane 1 | | | |
+ * | 1 | ------------- | | |
+ * |________|_______________|___________|_____________|
+ *
+ * Inter-pipe Relation (After Acquiring and Adding MPC Slice)
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | plane 0 | | |
+ * | 0 | -------------MPC----------------------- |
+ * | | plane 0 | | | |
+ * | 2 | ------------- | | |
+ * | | plane 1 | | | |
+ * | 1 | ------------- | | |
+ * |________|_______________|___________|_____________|
+ */
+static bool acquire_dpp_pipe_and_add_mpc_slice(
+ struct pipe_ctx *dpp_pipe,
+ struct dc_state *new_ctx,
+ const struct dc_state *cur_ctx,
+ const struct resource_pool *pool)
+{
+ struct pipe_ctx *last_dpp_pipe =
+ get_last_dpp_pipe_in_mpcc_combine(dpp_pipe);
+ struct pipe_ctx *opp_head = resource_get_opp_head(dpp_pipe);
+ struct pipe_ctx *new_dpp_pipe;
+
+ if (!pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe) {
+ ASSERT(0);
+ return false;
+ }
+ new_dpp_pipe = pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe(
+ cur_ctx, new_ctx, pool, opp_head);
+ if (!new_dpp_pipe || resource_get_odm_slice_count(dpp_pipe) > 1)
+ return false;
+
+ new_dpp_pipe->bottom_pipe = last_dpp_pipe->bottom_pipe;
+ if (new_dpp_pipe->bottom_pipe)
+ new_dpp_pipe->bottom_pipe->top_pipe = new_dpp_pipe;
+ new_dpp_pipe->top_pipe = last_dpp_pipe;
+ last_dpp_pipe->bottom_pipe = new_dpp_pipe;
+ new_dpp_pipe->plane_state = last_dpp_pipe->plane_state;
+
+ return true;
+}
+
+/*
+ * Reduce MPC slice count by 1 by releasing the bottom DPP pipe in MPCC combine
+ * with dpp_pipe and removing last MPC slice of the plane associated with
+ * dpp_pipe.
+ *
+ * return - true if the last MPC slice of the plane associated with dpp_pipe is
+ * removed and last DPP pipe in MPCC combine with dpp_pipe is released.
+ * false if there is no removable MPC slice.
+ *
+ * In the following example, we remove an MPC slice for plane 0 from the
+ * context. To do so we pass pipe 0 as dpp_pipe. The function releases pipe 1 as
+ * it is the last pipe for plane 0.
+ *
+ * Inter-pipe Relation (Before Releasing and Removing MPC Slice)
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | plane 0 | | |
+ * | 0 | -------------MPC----------------------- |
+ * | | plane 0 | | | |
+ * | 1 | ------------- | | |
+ * | | plane 1 | | | |
+ * | 2 | ------------- | | |
+ * |________|_______________|___________|_____________|
+ *
+ * Inter-pipe Relation (After Releasing and Removing MPC Slice)
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | plane 0 | | |
+ * | 0 | -------------MPC----------------------- |
+ * | | plane 1 | | | |
+ * | 2 | ------------- | | |
+ * |________|_______________|___________|_____________|
+ */
+static bool release_dpp_pipe_and_remove_mpc_slice(
+ struct pipe_ctx *dpp_pipe,
+ struct dc_state *context,
+ const struct resource_pool *pool)
+{
+ struct pipe_ctx *last_dpp_pipe =
+ get_last_dpp_pipe_in_mpcc_combine(dpp_pipe);
+
+ if (!pool->funcs->release_pipe) {
+ ASSERT(0);
+ return false;
+ }
+
+ if (resource_is_pipe_type(last_dpp_pipe, OPP_HEAD) ||
+ resource_get_odm_slice_count(dpp_pipe) > 1)
+ return false;
+
+ last_dpp_pipe->top_pipe->bottom_pipe = last_dpp_pipe->bottom_pipe;
+ if (last_dpp_pipe->bottom_pipe)
+ last_dpp_pipe->bottom_pipe->top_pipe = last_dpp_pipe->top_pipe;
+ pool->funcs->release_pipe(context, last_dpp_pipe, pool);
+
+ return true;
+}
+
+bool resource_update_pipes_for_stream_with_slice_count(
+ struct dc_state *new_ctx,
+ const struct dc_state *cur_ctx,
+ const struct resource_pool *pool,
+ const struct dc_stream_state *stream,
+ int new_slice_count)
+{
+ int i;
+ struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(
+ &new_ctx->res_ctx, stream);
+ int cur_slice_count = resource_get_odm_slice_count(otg_master);
+ bool result = true;
+
+ if (new_slice_count == cur_slice_count)
+ return result;
+
+ if (new_slice_count > cur_slice_count)
+ for (i = 0; i < new_slice_count - cur_slice_count && result; i++)
+ result = acquire_pipes_and_add_odm_slice(
+ otg_master, new_ctx, cur_ctx, pool);
+ else
+ for (i = 0; i < cur_slice_count - new_slice_count && result; i++)
+ result = release_pipes_and_remove_odm_slice(
+ otg_master, new_ctx, pool);
+ if (result)
+ result = update_pipe_params_after_odm_slice_count_change(
+ otg_master->stream, new_ctx, pool);
+ return result;
+}
+
+bool resource_update_pipes_for_plane_with_slice_count(
+ struct dc_state *new_ctx,
+ const struct dc_state *cur_ctx,
+ const struct resource_pool *pool,
+ const struct dc_plane_state *plane,
+ int new_slice_count)
+{
+ int i;
+ int dpp_pipe_count;
+ int cur_slice_count;
+ struct pipe_ctx *dpp_pipes[MAX_PIPES];
+ bool result = true;
+
+ dpp_pipe_count = resource_get_dpp_pipes_for_plane(plane,
+ &new_ctx->res_ctx, dpp_pipes);
+ ASSERT(dpp_pipe_count > 0);
+ cur_slice_count = resource_get_mpc_slice_count(dpp_pipes[0]);
+
+ if (new_slice_count == cur_slice_count)
+ return result;
+
+ if (new_slice_count > cur_slice_count)
+ for (i = 0; i < new_slice_count - cur_slice_count && result; i++)
+ result = acquire_dpp_pipe_and_add_mpc_slice(
+ dpp_pipes[0], new_ctx, cur_ctx, pool);
+ else
+ for (i = 0; i < cur_slice_count - new_slice_count && result; i++)
+ result = release_dpp_pipe_and_remove_mpc_slice(
+ dpp_pipes[0], new_ctx, pool);
+ if (result)
+ result = update_pipe_params_after_mpc_slice_count_change(
+ dpp_pipes[0]->plane_state, new_ctx, pool);
+ return result;
+}
+
bool dc_add_plane_to_context(
const struct dc *dc,
struct dc_stream_state *stream,
@@ -1927,13 +2990,9 @@ bool dc_add_plane_to_context(
otg_master_pipe = resource_get_otg_master_for_stream(
&context->res_ctx, stream);
- if (otg_master_pipe->plane_state == NULL)
- added = add_plane_to_opp_head_pipes(otg_master_pipe,
- plane_state, context);
- else
- added = acquire_secondary_dpp_pipes_and_add_plane(
- otg_master_pipe, plane_state, context,
- dc->current_state, pool);
+ added = resource_append_dpp_pipes_for_plane_composition(context,
+ dc->current_state, pool, otg_master_pipe, plane_state);
+
if (added) {
stream_status->plane_states[stream_status->plane_count] =
plane_state;
@@ -1969,32 +3028,8 @@ bool dc_remove_plane_from_context(
return false;
}
- /* release pipe for plane*/
- for (i = pool->pipe_count - 1; i >= 0; i--) {
- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-
- if (pipe_ctx->plane_state == plane_state) {
- if (pipe_ctx->top_pipe)
- pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
-
- /* Second condition is to avoid setting NULL to top pipe
- * of tail pipe making it look like head pipe in subsequent
- * deletes
- */
- if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe)
- pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe;
-
- /*
- * For head pipe detach surfaces from pipe for tail
- * pipe just zero it out
- */
- if (!pipe_ctx->top_pipe)
- pipe_ctx->plane_state = NULL;
- else
- memset(pipe_ctx, 0, sizeof(*pipe_ctx));
- }
- }
-
+ resource_remove_dpp_pipes_for_plane_composition(
+ context, pool, plane_state);
for (i = 0; i < stream_status->plane_count; i++) {
if (stream_status->plane_states[i] == plane_state) {
@@ -2016,6 +3051,15 @@ bool dc_remove_plane_from_context(
stream_status->plane_states[stream_status->plane_count] = NULL;
+ if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm)
+ /* ODM combine could prevent us from supporting more planes
+ * we will reset ODM slice count back to 1 when all planes have
+ * been removed to maximize the amount of planes supported when
+ * new planes are added.
+ */
+ resource_update_pipes_for_stream_with_slice_count(
+ context, dc->current_state, dc->res_pool, stream, 1);
+
return true;
}
@@ -2193,122 +3237,6 @@ bool dc_is_stream_scaling_unchanged(struct dc_stream_state *old_stream,
return true;
}
-static void update_stream_engine_usage(
- struct resource_context *res_ctx,
- const struct resource_pool *pool,
- struct stream_encoder *stream_enc,
- bool acquired)
-{
- int i;
-
- for (i = 0; i < pool->stream_enc_count; i++) {
- if (pool->stream_enc[i] == stream_enc)
- res_ctx->is_stream_enc_acquired[i] = acquired;
- }
-}
-
-static void update_hpo_dp_stream_engine_usage(
- struct resource_context *res_ctx,
- const struct resource_pool *pool,
- struct hpo_dp_stream_encoder *hpo_dp_stream_enc,
- bool acquired)
-{
- int i;
-
- for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) {
- if (pool->hpo_dp_stream_enc[i] == hpo_dp_stream_enc)
- res_ctx->is_hpo_dp_stream_enc_acquired[i] = acquired;
- }
-}
-
-static inline int find_acquired_hpo_dp_link_enc_for_link(
- const struct resource_context *res_ctx,
- const struct dc_link *link)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_to_link_idx); i++)
- if (res_ctx->hpo_dp_link_enc_ref_cnts[i] > 0 &&
- res_ctx->hpo_dp_link_enc_to_link_idx[i] == link->link_index)
- return i;
-
- return -1;
-}
-
-static inline int find_free_hpo_dp_link_enc(const struct resource_context *res_ctx,
- const struct resource_pool *pool)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_ref_cnts); i++)
- if (res_ctx->hpo_dp_link_enc_ref_cnts[i] == 0)
- break;
-
- return (i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_ref_cnts) &&
- i < pool->hpo_dp_link_enc_count) ? i : -1;
-}
-
-static inline void acquire_hpo_dp_link_enc(
- struct resource_context *res_ctx,
- unsigned int link_index,
- int enc_index)
-{
- res_ctx->hpo_dp_link_enc_to_link_idx[enc_index] = link_index;
- res_ctx->hpo_dp_link_enc_ref_cnts[enc_index] = 1;
-}
-
-static inline void retain_hpo_dp_link_enc(
- struct resource_context *res_ctx,
- int enc_index)
-{
- res_ctx->hpo_dp_link_enc_ref_cnts[enc_index]++;
-}
-
-static inline void release_hpo_dp_link_enc(
- struct resource_context *res_ctx,
- int enc_index)
-{
- ASSERT(res_ctx->hpo_dp_link_enc_ref_cnts[enc_index] > 0);
- res_ctx->hpo_dp_link_enc_ref_cnts[enc_index]--;
-}
-
-static bool add_hpo_dp_link_enc_to_ctx(struct resource_context *res_ctx,
- const struct resource_pool *pool,
- struct pipe_ctx *pipe_ctx,
- struct dc_stream_state *stream)
-{
- int enc_index;
-
- enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, stream->link);
-
- if (enc_index >= 0) {
- retain_hpo_dp_link_enc(res_ctx, enc_index);
- } else {
- enc_index = find_free_hpo_dp_link_enc(res_ctx, pool);
- if (enc_index >= 0)
- acquire_hpo_dp_link_enc(res_ctx, stream->link->link_index, enc_index);
- }
-
- if (enc_index >= 0)
- pipe_ctx->link_res.hpo_dp_link_enc = pool->hpo_dp_link_enc[enc_index];
-
- return pipe_ctx->link_res.hpo_dp_link_enc != NULL;
-}
-
-static void remove_hpo_dp_link_enc_from_ctx(struct resource_context *res_ctx,
- struct pipe_ctx *pipe_ctx,
- struct dc_stream_state *stream)
-{
- int enc_index;
-
- enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, stream->link);
-
- if (enc_index >= 0) {
- release_hpo_dp_link_enc(res_ctx, enc_index);
- pipe_ctx->link_res.hpo_dp_link_enc = NULL;
- }
-}
-
/* TODO: release audio object */
void update_audio_usage(
struct resource_context *res_ctx,
@@ -2323,42 +3251,6 @@ void update_audio_usage(
}
}
-static int acquire_first_free_pipe(
- struct resource_context *res_ctx,
- const struct resource_pool *pool,
- struct dc_stream_state *stream)
-{
- int i;
-
- for (i = 0; i < pool->pipe_count; i++) {
- if (!res_ctx->pipe_ctx[i].stream) {
- struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
-
- pipe_ctx->stream_res.tg = pool->timing_generators[i];
- pipe_ctx->plane_res.mi = pool->mis[i];
- pipe_ctx->plane_res.hubp = pool->hubps[i];
- pipe_ctx->plane_res.ipp = pool->ipps[i];
- pipe_ctx->plane_res.xfm = pool->transforms[i];
- pipe_ctx->plane_res.dpp = pool->dpps[i];
- pipe_ctx->stream_res.opp = pool->opps[i];
- if (pool->dpps[i])
- pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst;
- pipe_ctx->pipe_idx = i;
-
- if (i >= pool->timing_generator_count) {
- int tg_inst = pool->timing_generator_count - 1;
-
- pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst];
- pipe_ctx->stream_res.opp = pool->opps[tg_inst];
- }
-
- pipe_ctx->stream = stream;
- return i;
- }
- }
- return -1;
-}
-
static struct hpo_dp_stream_encoder *find_first_free_match_hpo_dp_stream_enc_for_link(
struct resource_context *res_ctx,
const struct resource_pool *pool,
@@ -2429,7 +3321,8 @@ enum dc_status dc_add_stream_to_ctx(
dc_stream_retain(stream);
new_ctx->stream_count++;
- res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream);
+ res = resource_add_otg_master_for_stream_output(
+ new_ctx, dc->res_pool, stream);
if (res != DC_OK)
DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res);
@@ -2446,53 +3339,18 @@ enum dc_status dc_remove_stream_from_ctx(
{
int i;
struct dc_context *dc_ctx = dc->ctx;
- struct pipe_ctx *del_pipe = resource_get_otg_master_for_stream(&new_ctx->res_ctx, stream);
- struct pipe_ctx *odm_pipe;
+ struct pipe_ctx *del_pipe = resource_get_otg_master_for_stream(
+ &new_ctx->res_ctx, stream);
if (!del_pipe) {
DC_ERROR("Pipe not found for stream %p !\n", stream);
return DC_ERROR_UNEXPECTED;
}
- odm_pipe = del_pipe->next_odm_pipe;
-
- /* Release primary pipe */
- ASSERT(del_pipe->stream_res.stream_enc);
- update_stream_engine_usage(
- &new_ctx->res_ctx,
- dc->res_pool,
- del_pipe->stream_res.stream_enc,
- false);
-
- if (dc->link_srv->dp_is_128b_132b_signal(del_pipe)) {
- update_hpo_dp_stream_engine_usage(
- &new_ctx->res_ctx, dc->res_pool,
- del_pipe->stream_res.hpo_dp_stream_enc,
- false);
- remove_hpo_dp_link_enc_from_ctx(&new_ctx->res_ctx, del_pipe, del_pipe->stream);
- }
-
- if (del_pipe->stream_res.audio)
- update_audio_usage(
- &new_ctx->res_ctx,
- dc->res_pool,
- del_pipe->stream_res.audio,
- false);
-
- resource_unreference_clock_source(&new_ctx->res_ctx,
- dc->res_pool,
- del_pipe->clock_source);
-
- if (dc->res_pool->funcs->remove_stream_from_ctx)
- dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream);
-
- while (odm_pipe) {
- struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe;
-
- memset(odm_pipe, 0, sizeof(*odm_pipe));
- odm_pipe = next_odm_pipe;
- }
- memset(del_pipe, 0, sizeof(*del_pipe));
+ resource_update_pipes_for_stream_with_slice_count(new_ctx,
+ dc->current_state, dc->res_pool, stream, 1);
+ resource_remove_otg_master_for_stream_output(
+ new_ctx, dc->res_pool, stream);
for (i = 0; i < new_ctx->stream_count; i++)
if (new_ctx->streams[i] == stream)
@@ -2711,6 +3569,66 @@ static void mark_seamless_boot_stream(
}
}
+/*
+ * Acquire a pipe as OTG master and assign to the stream in new dc context.
+ * return - true if OTG master pipe is acquired and new dc context is updated.
+ * false if it fails to acquire an OTG master pipe for this stream.
+ *
+ * In the example below, we acquired pipe 0 as OTG master pipe for the stream.
+ * After the function its Inter-pipe Relation is represented by the diagram
+ * below.
+ *
+ * Inter-pipe Relation
+ * __________________________________________________
+ * |PIPE IDX| DPP PIPES | OPP HEADS | OTG MASTER |
+ * | | | | |
+ * | 0 | |blank ------------------ |
+ * |________|_______________|___________|_____________|
+ */
+static bool acquire_otg_master_pipe_for_stream(
+ struct dc_state *new_ctx,
+ const struct resource_pool *pool,
+ struct dc_stream_state *stream)
+{
+ /* TODO: Move this function to DCN specific resource file and acquire
+ * DSC resource here. The reason is that the function should have the
+ * same level of responsibility as when we acquire secondary OPP head.
+ * We acquire DSC when we acquire secondary OPP head, so we should
+ * acquire DSC when we acquire OTG master.
+ */
+ int pipe_idx;
+ struct pipe_ctx *pipe_ctx = NULL;
+
+ pipe_idx = resource_find_any_free_pipe(&new_ctx->res_ctx, pool);
+ if (pipe_idx != FREE_PIPE_INDEX_NOT_FOUND) {
+ pipe_ctx = &new_ctx->res_ctx.pipe_ctx[pipe_idx];
+ memset(pipe_ctx, 0, sizeof(*pipe_ctx));
+ pipe_ctx->pipe_idx = pipe_idx;
+ pipe_ctx->stream_res.tg = pool->timing_generators[pipe_idx];
+ pipe_ctx->plane_res.mi = pool->mis[pipe_idx];
+ pipe_ctx->plane_res.hubp = pool->hubps[pipe_idx];
+ pipe_ctx->plane_res.ipp = pool->ipps[pipe_idx];
+ pipe_ctx->plane_res.xfm = pool->transforms[pipe_idx];
+ pipe_ctx->plane_res.dpp = pool->dpps[pipe_idx];
+ pipe_ctx->stream_res.opp = pool->opps[pipe_idx];
+ if (pool->dpps[pipe_idx])
+ pipe_ctx->plane_res.mpcc_inst = pool->dpps[pipe_idx]->inst;
+
+ if (pipe_idx >= pool->timing_generator_count) {
+ int tg_inst = pool->timing_generator_count - 1;
+
+ pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst];
+ pipe_ctx->stream_res.opp = pool->opps[tg_inst];
+ }
+
+ pipe_ctx->stream = stream;
+ } else {
+ pipe_idx = acquire_first_split_pipe(&new_ctx->res_ctx, pool, stream);
+ }
+
+ return pipe_idx != FREE_PIPE_INDEX_NOT_FOUND;
+}
+
enum dc_status resource_map_pool_resources(
const struct dc *dc,
struct dc_state *context,
@@ -2721,6 +3639,7 @@ enum dc_status resource_map_pool_resources(
struct dc_context *dc_ctx = dc->ctx;
struct pipe_ctx *pipe_ctx = NULL;
int pipe_idx = -1;
+ bool acquired = false;
calculate_phy_pix_clks(stream);
@@ -2734,20 +3653,20 @@ enum dc_status resource_map_pool_resources(
if (pipe_idx < 0)
/* hw resource was assigned to other stream */
stream->apply_seamless_boot_optimization = false;
+ else
+ acquired = true;
}
- if (pipe_idx < 0)
+ if (!acquired)
/* acquire new resources */
- pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
+ acquired = acquire_otg_master_pipe_for_stream(
+ context, pool, stream);
- if (pipe_idx < 0)
- pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
+ pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
- if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL)
+ if (!pipe_ctx || pipe_ctx->stream_res.tg == NULL)
return DC_NO_CONTROLLER_RESOURCE;
- pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
-
pipe_ctx->stream_res.stream_enc =
dc->res_pool->funcs->find_first_free_match_stream_enc_for_link(
&context->res_ctx, pool, stream);
@@ -3195,14 +4114,9 @@ static void set_avi_info_frame(
uint32_t pixel_encoding = 0;
enum scanning_type scan_type = SCANNING_TYPE_NODATA;
enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
- bool itc = false;
- uint8_t itc_value = 0;
- uint8_t cn0_cn1 = 0;
- unsigned int cn0_cn1_value = 0;
uint8_t *check_sum = NULL;
uint8_t byte_index = 0;
union hdmi_info_packet hdmi_info;
- union display_content_support support = {0};
unsigned int vic = pipe_ctx->stream->timing.vic;
unsigned int rid = pipe_ctx->stream->timing.rid;
unsigned int fr_ind = pipe_ctx->stream->timing.fr_index;
@@ -3312,49 +4226,27 @@ static void set_avi_info_frame(
/* Active Format Aspect ratio - same as Picture Aspect Ratio. */
hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
- /* TODO: un-hardcode cn0_cn1 and itc */
-
- cn0_cn1 = 0;
- cn0_cn1_value = 0;
-
- itc = true;
- itc_value = 1;
-
- support = stream->content_support;
-
- if (itc) {
- if (!support.bits.valid_content_type) {
- cn0_cn1_value = 0;
- } else {
- if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) {
- if (support.bits.graphics_content == 1) {
- cn0_cn1_value = 0;
- }
- } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) {
- if (support.bits.photo_content == 1) {
- cn0_cn1_value = 1;
- } else {
- cn0_cn1_value = 0;
- itc_value = 0;
- }
- } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) {
- if (support.bits.cinema_content == 1) {
- cn0_cn1_value = 2;
- } else {
- cn0_cn1_value = 0;
- itc_value = 0;
- }
- } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) {
- if (support.bits.game_content == 1) {
- cn0_cn1_value = 3;
- } else {
- cn0_cn1_value = 0;
- itc_value = 0;
- }
- }
- }
- hdmi_info.bits.CN0_CN1 = cn0_cn1_value;
- hdmi_info.bits.ITC = itc_value;
+ switch (stream->content_type) {
+ case DISPLAY_CONTENT_TYPE_NO_DATA:
+ hdmi_info.bits.CN0_CN1 = 0;
+ hdmi_info.bits.ITC = 1;
+ break;
+ case DISPLAY_CONTENT_TYPE_GRAPHICS:
+ hdmi_info.bits.CN0_CN1 = 0;
+ hdmi_info.bits.ITC = 1;
+ break;
+ case DISPLAY_CONTENT_TYPE_PHOTO:
+ hdmi_info.bits.CN0_CN1 = 1;
+ hdmi_info.bits.ITC = 1;
+ break;
+ case DISPLAY_CONTENT_TYPE_CINEMA:
+ hdmi_info.bits.CN0_CN1 = 2;
+ hdmi_info.bits.ITC = 1;
+ break;
+ case DISPLAY_CONTENT_TYPE_GAME:
+ hdmi_info.bits.CN0_CN1 = 3;
+ hdmi_info.bits.ITC = 1;
+ break;
}
if (stream->qs_bit == 1) {
@@ -3596,6 +4488,18 @@ void dc_resource_state_destruct(struct dc_state *context)
context->streams[i] = NULL;
}
context->stream_count = 0;
+ context->stream_mask = 0;
+ memset(&context->res_ctx, 0, sizeof(context->res_ctx));
+ memset(&context->pp_display_cfg, 0, sizeof(context->pp_display_cfg));
+ memset(&context->dcn_bw_vars, 0, sizeof(context->dcn_bw_vars));
+ context->clk_mgr = NULL;
+ memset(&context->bw_ctx.bw, 0, sizeof(context->bw_ctx.bw));
+ memset(context->block_sequence, 0, sizeof(context->block_sequence));
+ context->block_sequence_steps = 0;
+ memset(context->dc_dmub_cmd, 0, sizeof(context->dc_dmub_cmd));
+ context->dmub_cmd_count = 0;
+ memset(&context->perf_params, 0, sizeof(context->perf_params));
+ memset(&context->scratch, 0, sizeof(context->scratch));
}
void dc_resource_state_copy_construct(
@@ -3604,9 +4508,22 @@ void dc_resource_state_copy_construct(
{
int i, j;
struct kref refcount = dst_ctx->refcount;
+#ifdef CONFIG_DRM_AMD_DC_FP
+ struct dml2_context *dml2 = NULL;
+
+ // Need to preserve allocated dml2 context
+ if (src_ctx->clk_mgr->ctx->dc->debug.using_dml2)
+ dml2 = dst_ctx->bw_ctx.dml2;
+#endif
*dst_ctx = *src_ctx;
+#ifdef CONFIG_DRM_AMD_DC_FP
+ // Preserve allocated dml2 context
+ if (src_ctx->clk_mgr->ctx->dc->debug.using_dml2)
+ dst_ctx->bw_ctx.dml2 = dml2;
+#endif
+
for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
@@ -4247,7 +5164,17 @@ bool is_h_timing_divisible_by_2(struct dc_stream_state *stream)
return divisible;
}
-bool dc_resource_acquire_secondary_pipe_for_mpc_odm(
+/* This interface is deprecated for new DCNs. It is replaced by the following
+ * new interfaces. These two interfaces encapsulate pipe selection priority
+ * with DCN specific minimum hardware transition optimization algorithm. With
+ * the new interfaces caller no longer needs to know the implementation detail
+ * of a pipe topology.
+ *
+ * resource_update_pipes_with_odm_slice_count
+ * resource_update_pipes_with_mpc_slice_count
+ *
+ */
+bool dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy(
const struct dc *dc,
struct dc_state *state,
struct pipe_ctx *pri_pipe,
@@ -4263,6 +5190,9 @@ bool dc_resource_acquire_secondary_pipe_for_mpc_odm(
sec_next = sec_pipe->next_odm_pipe;
sec_prev = sec_pipe->prev_odm_pipe;
+ if (pri_pipe == NULL)
+ return false;
+
*sec_pipe = *pri_pipe;
sec_pipe->top_pipe = sec_top;
@@ -4337,3 +5267,16 @@ enum dc_status update_dp_encoder_resources_for_test_harness(const struct dc *dc,
return DC_OK;
}
+bool check_subvp_sw_cursor_fallback_req(const struct dc *dc, struct dc_stream_state *stream)
+{
+ if (!dc->debug.disable_subvp_high_refresh && is_subvp_high_refresh_candidate(stream))
+ return true;
+ if (dc->current_state->stream_count == 1 && stream->timing.v_addressable >= 2880 &&
+ ((stream->timing.pix_clk_100hz * 100) / stream->timing.v_total / stream->timing.h_total) < 120)
+ return true;
+ else if (dc->current_state->stream_count > 1 && stream->timing.v_addressable >= 2160 &&
+ ((stream->timing.pix_clk_100hz * 100) / stream->timing.v_total / stream->timing.h_total) < 120)
+ return true;
+
+ return false;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index 01fe2d2fd241..4bdf105d1d71 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -288,49 +288,6 @@ static void program_cursor_attributes(
}
}
-#ifndef TRIM_FSFT
-/*
- * dc_optimize_timing_for_fsft() - dc to optimize timing
- */
-bool dc_optimize_timing_for_fsft(
- struct dc_stream_state *pStream,
- unsigned int max_input_rate_in_khz)
-{
- struct dc *dc;
-
- dc = pStream->ctx->dc;
-
- return (dc->hwss.optimize_timing_for_fsft &&
- dc->hwss.optimize_timing_for_fsft(dc, &pStream->timing, max_input_rate_in_khz));
-}
-#endif
-
-static bool is_subvp_high_refresh_candidate(struct dc_stream_state *stream)
-{
- uint32_t refresh_rate;
- struct dc *dc = stream->ctx->dc;
-
- refresh_rate = (stream->timing.pix_clk_100hz * (uint64_t)100 +
- stream->timing.v_total * stream->timing.h_total - (uint64_t)1);
- refresh_rate = div_u64(refresh_rate, stream->timing.v_total);
- refresh_rate = div_u64(refresh_rate, stream->timing.h_total);
-
- /* If there's any stream that fits the SubVP high refresh criteria,
- * we must return true. This is because cursor updates are asynchronous
- * with full updates, so we could transition into a SubVP config and
- * remain in HW cursor mode if there's no cursor update which will
- * then cause corruption.
- */
- if ((refresh_rate >= 120 && refresh_rate <= 175 &&
- stream->timing.v_addressable >= 1440 &&
- stream->timing.v_addressable <= 2160) &&
- (dc->current_state->stream_count > 1 ||
- (dc->current_state->stream_count == 1 && !stream->allow_freesync)))
- return true;
-
- return false;
-}
-
/*
* dc_stream_set_cursor_attributes() - Update cursor attributes and set cursor surface address
*/
@@ -364,13 +321,7 @@ bool dc_stream_set_cursor_attributes(
* 3. If not subvp high refresh, for multi display cases, if resolution is >= 4K and refresh rate < 120hz
*/
if (dc->debug.allow_sw_cursor_fallback && attributes->height * attributes->width * 4 > 16384) {
- if (!dc->debug.disable_subvp_high_refresh && is_subvp_high_refresh_candidate(stream))
- return false;
- if (dc->current_state->stream_count == 1 && stream->timing.v_addressable >= 2880 &&
- ((stream->timing.pix_clk_100hz * 100) / stream->timing.v_total / stream->timing.h_total) < 120)
- return false;
- else if (dc->current_state->stream_count > 1 && stream->timing.v_addressable >= 2160 &&
- ((stream->timing.pix_clk_100hz * 100) / stream->timing.v_total / stream->timing.h_total) < 120)
+ if (check_subvp_sw_cursor_fallback_req(dc, stream))
return false;
}
@@ -582,7 +533,7 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream)
for (i = 0; i < MAX_PIPES; i++) {
struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
- if (res_ctx->pipe_ctx[i].stream != stream)
+ if (res_ctx->pipe_ctx[i].stream != stream || !tg)
continue;
return tg->funcs->get_frame_count(tg);
@@ -641,7 +592,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
for (i = 0; i < MAX_PIPES; i++) {
struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
- if (res_ctx->pipe_ctx[i].stream != stream)
+ if (res_ctx->pipe_ctx[i].stream != stream || !tg)
continue;
tg->funcs->get_scanoutpos(tg,
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 31e3183497a7..2cafd644baff 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -35,11 +35,13 @@
#include "grph_object_ctrl_defs.h"
#include <inc/hw/opp.h>
-#include "inc/hw_sequencer.h"
+#include "hwss/hw_sequencer.h"
#include "inc/compressor.h"
#include "inc/hw/dmcu.h"
#include "dml/display_mode_lib.h"
+#include "dml2/dml2_wrapper.h"
+
struct abm_save_restore;
/* forward declaration */
@@ -47,7 +49,7 @@ struct aux_payload;
struct set_config_cmd_payload;
struct dmub_notification;
-#define DC_VER "3.2.247"
+#define DC_VER "3.2.259"
#define MAX_SURFACES 3
#define MAX_PLANES 6
@@ -231,6 +233,11 @@ struct dc_caps {
uint32_t dmdata_alloc_size;
unsigned int max_cursor_size;
unsigned int max_video_width;
+ /*
+ * max video plane width that can be safely assumed to be always
+ * supported by single DPP pipe.
+ */
+ unsigned int max_optimizable_video_width;
unsigned int min_horizontal_blanking_period;
int linear_pitch_alignment;
bool dcc_const_color;
@@ -244,6 +251,7 @@ struct dc_caps {
bool extended_aux_timeout_support;
bool dmcub_support;
bool zstate_support;
+ bool ips_support;
uint32_t num_of_internal_disp;
enum dp_protocol_version max_dp_protocol_version;
unsigned int mall_size_per_mem_channel;
@@ -269,6 +277,7 @@ struct dc_caps {
uint16_t subvp_vertical_int_margin_us;
bool seamless_odm;
uint32_t max_v_total;
+ uint32_t max_disp_clock_khz_at_vmin;
uint8_t subvp_drr_vblank_start_margin_us;
};
@@ -373,6 +382,7 @@ struct dc_cap_funcs {
bool (*get_dcc_compression_cap)(const struct dc *dc,
const struct dc_dcc_surface_param *input,
struct dc_surface_dcc_cap *output);
+ bool (*get_subvp_en)(struct dc *dc, struct dc_state *context);
};
struct link_training_settings;
@@ -419,6 +429,9 @@ struct dc_config {
int sdpif_request_limit_words_per_umc;
bool use_old_fixed_vs_sequence;
bool dc_mode_clk_limit_support;
+ bool EnableMinDispClkODM;
+ bool enable_auto_dpm_test_logs;
+ unsigned int disable_ips;
};
enum visual_confirm {
@@ -643,6 +656,53 @@ union root_clock_optimization_options {
uint32_t u32All;
};
+union fine_grain_clock_gating_enable_options {
+ struct {
+ bool dccg_global_fgcg_rep : 1; /* Global fine grain clock gating of repeaters */
+ bool dchub : 1; /* Display controller hub */
+ bool dchubbub : 1;
+ bool dpp : 1; /* Display pipes and planes */
+ bool opp : 1; /* Output pixel processing */
+ bool optc : 1; /* Output pipe timing combiner */
+ bool dio : 1; /* Display output */
+ bool dwb : 1; /* Display writeback */
+ bool mmhubbub : 1; /* Multimedia hub */
+ bool dmu : 1; /* Display core management unit */
+ bool az : 1; /* Azalia */
+ bool dchvm : 1;
+ bool dsc : 1; /* Display stream compression */
+
+ uint32_t reserved : 19;
+ } bits;
+ uint32_t u32All;
+};
+
+enum pg_hw_pipe_resources {
+ PG_HUBP = 0,
+ PG_DPP,
+ PG_DSC,
+ PG_MPCC,
+ PG_OPP,
+ PG_OPTC,
+ PG_HW_PIPE_RESOURCES_NUM_ELEMENT
+};
+
+enum pg_hw_resources {
+ PG_DCCG = 0,
+ PG_DCIO,
+ PG_DIO,
+ PG_DCHUBBUB,
+ PG_DCHVM,
+ PG_DWB,
+ PG_HPO,
+ PG_HW_RESOURCES_NUM_ELEMENT
+};
+
+struct pg_block_update {
+ bool pg_pipe_res_update[PG_HW_PIPE_RESOURCES_NUM_ELEMENT][MAX_PIPES];
+ bool pg_res_update[PG_HW_RESOURCES_NUM_ELEMENT];
+};
+
union dpia_debug_options {
struct {
uint32_t disable_dpia:1; /* bit 0 */
@@ -772,6 +832,8 @@ struct dc_debug_options {
bool disable_dpp_power_gate;
bool disable_hubp_power_gate;
bool disable_dsc_power_gate;
+ bool disable_optc_power_gate;
+ bool disable_hpo_power_gate;
int dsc_min_slice_height_override;
int dsc_bpp_increment_div;
bool disable_pplib_wm_range;
@@ -812,6 +874,7 @@ struct dc_debug_options {
unsigned int seamless_boot_odm_combine;
unsigned int force_odm_combine_4to1; //bit vector based on otg inst
int minimum_z8_residency_time;
+ int minimum_z10_residency_time;
bool disable_z9_mpc;
unsigned int force_fclk_khz;
bool enable_tri_buf;
@@ -847,6 +910,7 @@ struct dc_debug_options {
bool ignore_cable_id;
union mem_low_power_enable_options enable_mem_low_power;
union root_clock_optimization_options root_clock_optimization;
+ union fine_grain_clock_gating_enable_options enable_fine_grain_clock_gating;
bool hpo_optimization;
bool force_vblank_alignment;
@@ -883,6 +947,7 @@ struct dc_debug_options {
bool dml_disallow_alternate_prefetch_modes;
bool use_legacy_soc_bb_mechanism;
bool exit_idle_opt_for_cursor_updates;
+ bool using_dml2;
bool enable_single_display_2to1_odm_policy;
bool enable_double_buffered_dsc_pg_support;
bool enable_dp_dig_pixel_rate_div_policy;
@@ -893,6 +958,8 @@ struct dc_debug_options {
bool dig_fifo_off_in_blank;
bool temp_mst_deallocation_sequence;
bool override_dispclk_programming;
+ bool otg_crc_db;
+ bool disallow_dispclk_dppclk_ds;
bool disable_fpo_optimizations;
bool support_eDP1_5;
uint32_t fpo_vactive_margin_us;
@@ -904,9 +971,14 @@ struct dc_debug_options {
bool disable_dp_plus_plus_wa;
uint32_t fpo_vactive_min_active_margin_us;
uint32_t fpo_vactive_max_blank_us;
+ bool enable_hpo_pg_support;
bool enable_legacy_fast_update;
bool disable_dc_mode_overwrite;
bool replay_skip_crtc_disabled;
+ bool ignore_pg;/*do nothing, let pmfw control it*/
+ bool psp_disabled_wa;
+ unsigned int ips2_eval_delay_us;
+ unsigned int ips2_entry_delay_us;
};
struct gpu_info_soc_bounding_box_v1_0;
@@ -971,6 +1043,7 @@ struct dc {
uint32_t *dcn_reg_offsets;
uint32_t *nbio_reg_offsets;
+ uint32_t *clk_reg_offsets;
/* Scratch memory */
struct {
@@ -982,6 +1055,8 @@ struct dc {
struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES];
} update_bw_bounding_box;
} scratch;
+
+ struct dml2_configuration_options dml2_options;
};
enum frame_buffer_mode {
@@ -1030,6 +1105,7 @@ struct dc_init_data {
*/
uint32_t *dcn_reg_offsets;
uint32_t *nbio_reg_offsets;
+ uint32_t *clk_reg_offsets;
};
struct dc_callback_init {
@@ -1533,7 +1609,6 @@ struct dc_link {
enum edp_revision edp_revision;
union dpcd_sink_ext_caps dpcd_sink_ext_caps;
- struct backlight_settings backlight_settings;
struct psr_settings psr_settings;
struct replay_settings replay_settings;
@@ -1573,6 +1648,7 @@ struct dc_link {
struct phy_state phy_state;
// BW ALLOCATON USB4 ONLY
struct dc_dpia_bw_alloc dpia_bw_alloc_config;
+ bool skip_implict_edp_power_control;
};
/* Return an enumerated dc_link.
@@ -1592,6 +1668,9 @@ void dc_get_edp_links(const struct dc *dc,
struct dc_link **edp_links,
int *edp_num);
+void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link,
+ bool powerOn);
+
/* The function initiates detection handshake over the given link. It first
* determines if there are display connections over the link. If so it initiates
* detection protocols supported by the connected receiver device. The function
@@ -2239,6 +2318,7 @@ bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, struct dc_plane_
struct dc_cursor_attributes *cursor_attr);
void dc_allow_idle_optimizations(struct dc *dc, bool allow);
+bool dc_dmub_is_ips_idle_state(struct dc *dc);
/* set min and max memory clock to lowest and highest DPM level, respectively */
void dc_unlock_memory_clock_frequency(struct dc *dc);
@@ -2294,6 +2374,12 @@ void dc_print_dmub_diagnostic_data(const struct dc *dc);
void dc_query_current_properties(struct dc *dc, struct dc_current_properties *properties);
+struct dc_power_profile {
+ int power_level; /* Lower is better */
+};
+
+struct dc_power_profile dc_get_power_profile_for_dc_state(const struct dc_state *context);
+
/* DSC Interfaces */
#include "dc_dsc.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
index 4c5ef3ef8dbd..0e07699c1e83 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -32,6 +32,7 @@
#include "../basics/conversion.h"
#include "cursor_reg_cache.h"
#include "resource.h"
+#include "clk_mgr.h"
#define CTX dc_dmub_srv->ctx
#define DC_LOGGER CTX->logger
@@ -79,46 +80,120 @@ void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv)
}
}
-void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dmub_srv)
+void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dc_dmub_srv)
{
- struct dmub_srv *dmub = dmub_srv->dmub;
- struct dc_context *dc_ctx = dmub_srv->ctx;
+ struct dmub_srv *dmub = dc_dmub_srv->dmub;
+ struct dc_context *dc_ctx = dc_dmub_srv->ctx;
enum dmub_status status = DMUB_STATUS_OK;
status = dmub_srv_clear_inbox0_ack(dmub);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error clearing INBOX0 ack: status=%d\n", status);
- dc_dmub_srv_log_diagnostic_data(dmub_srv);
+ dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
}
}
-void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dmub_srv)
+void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dc_dmub_srv)
{
- struct dmub_srv *dmub = dmub_srv->dmub;
- struct dc_context *dc_ctx = dmub_srv->ctx;
+ struct dmub_srv *dmub = dc_dmub_srv->dmub;
+ struct dc_context *dc_ctx = dc_dmub_srv->ctx;
enum dmub_status status = DMUB_STATUS_OK;
status = dmub_srv_wait_for_inbox0_ack(dmub, 100000);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error waiting for INBOX0 HW Lock Ack\n");
- dc_dmub_srv_log_diagnostic_data(dmub_srv);
+ dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
}
}
-void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
- union dmub_inbox0_data_register data)
+void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dc_dmub_srv,
+ union dmub_inbox0_data_register data)
{
- struct dmub_srv *dmub = dmub_srv->dmub;
- struct dc_context *dc_ctx = dmub_srv->ctx;
+ struct dmub_srv *dmub = dc_dmub_srv->dmub;
+ struct dc_context *dc_ctx = dc_dmub_srv->ctx;
enum dmub_status status = DMUB_STATUS_OK;
status = dmub_srv_send_inbox0_cmd(dmub, data);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error sending INBOX0 cmd\n");
- dc_dmub_srv_log_diagnostic_data(dmub_srv);
+ dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
}
}
+bool dc_dmub_srv_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_srv,
+ unsigned int count,
+ union dmub_rb_cmd *cmd_list)
+{
+ struct dc_context *dc_ctx = dc_dmub_srv->ctx;
+ struct dmub_srv *dmub;
+ enum dmub_status status;
+ int i;
+
+ if (!dc_dmub_srv || !dc_dmub_srv->dmub)
+ return false;
+
+ dmub = dc_dmub_srv->dmub;
+
+ for (i = 0 ; i < count; i++) {
+ // Queue command
+ status = dmub_srv_cmd_queue(dmub, &cmd_list[i]);
+
+ if (status == DMUB_STATUS_QUEUE_FULL) {
+ /* Execute and wait for queue to become empty again. */
+ dmub_srv_cmd_execute(dmub);
+ dmub_srv_wait_for_idle(dmub, 100000);
+
+ /* Requeue the command. */
+ status = dmub_srv_cmd_queue(dmub, &cmd_list[i]);
+ }
+
+ if (status != DMUB_STATUS_OK) {
+ DC_ERROR("Error queueing DMUB command: status=%d\n", status);
+ dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ return false;
+ }
+ }
+
+ status = dmub_srv_cmd_execute(dmub);
+ if (status != DMUB_STATUS_OK) {
+ DC_ERROR("Error starting DMUB execution: status=%d\n", status);
+ dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ return false;
+ }
+
+ return true;
+}
+
+bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
+ enum dm_dmub_wait_type wait_type,
+ union dmub_rb_cmd *cmd_list)
+{
+ struct dmub_srv *dmub;
+ enum dmub_status status;
+
+ if (!dc_dmub_srv || !dc_dmub_srv->dmub)
+ return false;
+
+ dmub = dc_dmub_srv->dmub;
+
+ // Wait for DMUB to process command
+ if (wait_type != DM_DMUB_WAIT_TYPE_NO_WAIT) {
+ status = dmub_srv_wait_for_idle(dmub, 100000);
+
+ if (status != DMUB_STATUS_OK) {
+ DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status);
+ dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ return false;
+ }
+
+ // Copy data back from ring buffer into command
+ if (wait_type == DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)
+ dmub_rb_get_return_data(&dmub->inbox1_rb, cmd_list);
+ }
+
+ return true;
+}
+
bool dc_dmub_srv_cmd_run(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
{
return dc_dmub_srv_cmd_run_list(dc_dmub_srv, 1, cmd, wait_type);
@@ -552,7 +627,8 @@ static void populate_subvp_cmd_vblank_pipe_info(struct dc *dc,
pipe_data->pipe_config.vblank_data.vblank_end =
vblank_pipe->stream->timing.v_total - vblank_pipe->stream->timing.v_front_porch - vblank_pipe->stream->timing.v_addressable;
- if (vblank_pipe->stream->ignore_msa_timing_param)
+ if (vblank_pipe->stream->ignore_msa_timing_param &&
+ (vblank_pipe->stream->allow_freesync || vblank_pipe->stream->vrr_active_variable || vblank_pipe->stream->vrr_active_fixed))
populate_subvp_cmd_drr_info(dc, pipe, vblank_pipe, pipe_data);
}
@@ -645,7 +721,8 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc,
main_timing->v_total - main_timing->v_front_porch - main_timing->v_addressable;
pipe_data->pipe_config.subvp_data.mall_region_lines = phantom_timing->v_addressable;
pipe_data->pipe_config.subvp_data.main_pipe_index = subvp_pipe->stream_res.tg->inst;
- pipe_data->pipe_config.subvp_data.is_drr = subvp_pipe->stream->ignore_msa_timing_param;
+ pipe_data->pipe_config.subvp_data.is_drr = subvp_pipe->stream->ignore_msa_timing_param &&
+ (subvp_pipe->stream->allow_freesync || subvp_pipe->stream->vrr_active_variable || subvp_pipe->stream->vrr_active_fixed);
/* Calculate the scaling factor from the src and dst height.
* e.g. If 3840x2160 being downscaled to 1920x1080, the scaling factor is 1/2.
@@ -1054,4 +1131,123 @@ void dc_dmub_srv_enable_dpia_trace(const struct dc *dc)
}
DC_LOG_DEBUG("Enabled DPIA trace\n");
-} \ No newline at end of file
+}
+
+void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, const struct dc_plane_address *addr, uint8_t subvp_index)
+{
+ dmub_srv_subvp_save_surf_addr(dc_dmub_srv->dmub, addr, subvp_index);
+}
+
+bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait)
+{
+ struct dc_context *dc_ctx = dc_dmub_srv->ctx;
+ enum dmub_status status;
+
+ if (dc_dmub_srv->ctx->dc->debug.dmcub_emulation)
+ return true;
+
+ if (wait) {
+ status = dmub_srv_wait_for_hw_pwr_up(dc_dmub_srv->dmub, 500000);
+ if (status != DMUB_STATUS_OK) {
+ DC_ERROR("Error querying DMUB hw power up status: error=%d\n", status);
+ return false;
+ }
+ } else
+ return dmub_srv_is_hw_pwr_up(dc_dmub_srv->dmub);
+
+ return true;
+}
+
+void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle)
+{
+ union dmub_rb_cmd cmd = {0};
+
+ if (dc->debug.dmcub_emulation)
+ return;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.idle_opt_notify_idle.header.type = DMUB_CMD__IDLE_OPT;
+ cmd.idle_opt_notify_idle.header.sub_type = DMUB_CMD__IDLE_OPT_DCN_NOTIFY_IDLE;
+ cmd.idle_opt_notify_idle.header.payload_bytes =
+ sizeof(cmd.idle_opt_notify_idle) -
+ sizeof(cmd.idle_opt_notify_idle.header);
+
+ cmd.idle_opt_notify_idle.cntl_data.driver_idle = allow_idle;
+
+ if (allow_idle) {
+ if (dc->hwss.set_idle_state)
+ dc->hwss.set_idle_state(dc, true);
+ }
+
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+}
+
+void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
+{
+ const uint32_t max_num_polls = 10000;
+ uint32_t allow_state = 0;
+ uint32_t commit_state = 0;
+ uint32_t i;
+
+ if (dc->debug.dmcub_emulation)
+ return;
+
+ if (!dc->idle_optimizations_allowed)
+ return;
+
+ if (dc->hwss.get_idle_state &&
+ dc->hwss.set_idle_state &&
+ dc->clk_mgr->funcs->exit_low_power_state) {
+
+ allow_state = dc->hwss.get_idle_state(dc);
+ dc->hwss.set_idle_state(dc, false);
+
+ if (!(allow_state & DMUB_IPS2_ALLOW_MASK)) {
+ // Wait for evaluation time
+ udelay(dc->debug.ips2_eval_delay_us);
+ commit_state = dc->hwss.get_idle_state(dc);
+ if (!(commit_state & DMUB_IPS2_COMMIT_MASK)) {
+ // Tell PMFW to exit low power state
+ dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr);
+
+ // Wait for IPS2 entry upper bound
+ udelay(dc->debug.ips2_entry_delay_us);
+ dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr);
+
+ for (i = 0; i < max_num_polls; ++i) {
+ commit_state = dc->hwss.get_idle_state(dc);
+ if (commit_state & DMUB_IPS2_COMMIT_MASK)
+ break;
+
+ udelay(1);
+ }
+ ASSERT(i < max_num_polls);
+
+ if (!dc_dmub_srv_is_hw_pwr_up(dc->ctx->dmub_srv, true))
+ ASSERT(0);
+
+ /* TODO: See if we can return early here - IPS2 should go
+ * back directly to IPS0 and clear the flags, but it will
+ * be safer to directly notify DMCUB of this.
+ */
+ allow_state = dc->hwss.get_idle_state(dc);
+ }
+ }
+
+ dc_dmub_srv_notify_idle(dc, false);
+ if (!(allow_state & DMUB_IPS1_ALLOW_MASK)) {
+ for (i = 0; i < max_num_polls; ++i) {
+ commit_state = dc->hwss.get_idle_state(dc);
+ if (commit_state & DMUB_IPS1_COMMIT_MASK)
+ break;
+
+ udelay(1);
+ }
+ ASSERT(i < max_num_polls);
+ }
+ }
+
+ if (!dc_dmub_srv_is_hw_pwr_up(dc->ctx->dmub_srv, true))
+ ASSERT(0);
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
index bb3fe162dd93..d4a60f53faab 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
@@ -56,6 +56,14 @@ void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv);
bool dc_dmub_srv_optimized_init_done(struct dc_dmub_srv *dc_dmub_srv);
+bool dc_dmub_srv_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_srv,
+ unsigned int count,
+ union dmub_rb_cmd *cmd_list);
+
+bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
+ enum dm_dmub_wait_type wait_type,
+ union dmub_rb_cmd *cmd_list);
+
bool dc_dmub_srv_cmd_run(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type);
bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int count, union dmub_rb_cmd *cmd_list, enum dm_dmub_wait_type wait_type);
@@ -89,5 +97,9 @@ void dc_send_update_cursor_info_to_dmu(struct pipe_ctx *pCtx, uint8_t pipe_idx);
bool dc_dmub_check_min_version(struct dmub_srv *srv);
void dc_dmub_srv_enable_dpia_trace(const struct dc *dc);
+void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, const struct dc_plane_address *addr, uint8_t subvp_index);
+bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait);
+void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle);
+void dc_dmub_srv_exit_low_power_state(const struct dc *dc);
#endif /* _DMUB_DC_SRV_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
index cfaa39c5dd16..eeeeeef4d717 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
@@ -142,7 +142,8 @@ enum dp_test_link_rate {
DP_TEST_LINK_RATE_HBR3 = 0x1E,
DP_TEST_LINK_RATE_UHBR10 = 0x01,
DP_TEST_LINK_RATE_UHBR20 = 0x02,
- DP_TEST_LINK_RATE_UHBR13_5 = 0x03,
+ DP_TEST_LINK_RATE_UHBR13_5_LEGACY = 0x03, /* For backward compatibility*/
+ DP_TEST_LINK_RATE_UHBR13_5 = 0x04,
};
struct dc_link_settings {
@@ -916,73 +917,16 @@ struct dpcd_usb4_dp_tunneling_info {
uint8_t usb4_topology_id[DPCD_USB4_TOPOLOGY_ID_LEN];
};
-#ifndef DP_MAIN_LINK_CHANNEL_CODING_CAP
-#define DP_MAIN_LINK_CHANNEL_CODING_CAP 0x006
-#endif
-#ifndef DP_SINK_VIDEO_FALLBACK_FORMATS
-#define DP_SINK_VIDEO_FALLBACK_FORMATS 0x020
-#endif
-#ifndef DP_FEC_CAPABILITY_1
-#define DP_FEC_CAPABILITY_1 0x091
-#endif
#ifndef DP_DFP_CAPABILITY_EXTENSION_SUPPORT
#define DP_DFP_CAPABILITY_EXTENSION_SUPPORT 0x0A3
#endif
-#ifndef DP_DSC_CONFIGURATION
-#define DP_DSC_CONFIGURATION 0x161
-#endif
-#ifndef DP_PHY_SQUARE_PATTERN
-#define DP_PHY_SQUARE_PATTERN 0x249
-#endif
-#ifndef DP_128b_132b_SUPPORTED_LINK_RATES
-#define DP_128b_132b_SUPPORTED_LINK_RATES 0x2215
-#endif
-#ifndef DP_128b_132b_TRAINING_AUX_RD_INTERVAL
-#define DP_128b_132b_TRAINING_AUX_RD_INTERVAL 0x2216
-#endif
#ifndef DP_TEST_264BIT_CUSTOM_PATTERN_7_0
#define DP_TEST_264BIT_CUSTOM_PATTERN_7_0 0X2230
#endif
#ifndef DP_TEST_264BIT_CUSTOM_PATTERN_263_256
#define DP_TEST_264BIT_CUSTOM_PATTERN_263_256 0X2250
#endif
-#ifndef DP_DSC_SUPPORT_AND_DECODER_COUNT
-#define DP_DSC_SUPPORT_AND_DECODER_COUNT 0x2260
-#endif
-#ifndef DP_DSC_MAX_SLICE_COUNT_AND_AGGREGATION_0
-#define DP_DSC_MAX_SLICE_COUNT_AND_AGGREGATION_0 0x2270
-#endif
-#ifndef DP_DSC_DECODER_0_MAXIMUM_SLICE_COUNT_MASK
-#define DP_DSC_DECODER_0_MAXIMUM_SLICE_COUNT_MASK (1 << 0)
-#endif
-#ifndef DP_DSC_DECODER_0_AGGREGATION_SUPPORT_MASK
-#define DP_DSC_DECODER_0_AGGREGATION_SUPPORT_MASK (0b111 << 1)
-#endif
-#ifndef DP_DSC_DECODER_0_AGGREGATION_SUPPORT_SHIFT
-#define DP_DSC_DECODER_0_AGGREGATION_SUPPORT_SHIFT 1
-#endif
-#ifndef DP_DSC_DECODER_COUNT_MASK
-#define DP_DSC_DECODER_COUNT_MASK (0b111 << 5)
-#endif
-#ifndef DP_DSC_DECODER_COUNT_SHIFT
-#define DP_DSC_DECODER_COUNT_SHIFT 5
-#endif
-#ifndef DP_MAIN_LINK_CHANNEL_CODING_SET
-#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108
-#endif
-#ifndef DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER
-#define DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER 0xF0006
-#endif
-#ifndef DP_PHY_REPEATER_128b_132b_RATES
-#define DP_PHY_REPEATER_128b_132b_RATES 0xF0007
-#endif
-#ifndef DP_128b_132b_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1
-#define DP_128b_132b_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 0xF0022
-#endif
-#ifndef DP_INTRA_HOP_AUX_REPLY_INDICATION
-#define DP_INTRA_HOP_AUX_REPLY_INDICATION (1 << 3)
-/* TODO - Use DRM header to replace above once available */
-#endif // DP_INTRA_HOP_AUX_REPLY_INDICATION
+
union dp_main_line_channel_coding_cap {
struct {
uint8_t DP_8b_10b_SUPPORTED :1;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c
index 3907eeff560c..cb6eaddab720 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c
@@ -36,6 +36,9 @@
#include "dc_dmub_srv.h"
#include "reg_helper.h"
+#define DC_LOGGER \
+ ctx->logger
+
static inline void submit_dmub_read_modify_write(
struct dc_reg_helper_state *offload,
const struct dc_context *ctx)
@@ -740,6 +743,10 @@ char *dce_version_to_string(const int version)
return "DCN 3.2";
case DCN_VERSION_3_21:
return "DCN 3.2.1";
+ case DCN_VERSION_3_5:
+ return "DCN 3.5";
+ case DCN_VERSION_3_51:
+ return "DCN 3.5.1";
default:
return "Unknown";
}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index 100d62162b71..e2a3aa8812df 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -465,6 +465,7 @@ struct dc_cursor_mi_param {
struct fixed31_32 v_scale_ratio;
enum dc_rotation_angle rotation;
bool mirror;
+ struct dc_stream_state *stream;
};
/* IPP related types */
@@ -769,9 +770,6 @@ struct dc_crtc_timing_flags {
uint32_t LTE_340MCSC_SCRAMBLE:1;
uint32_t DSC : 1; /* Use DSC with this timing */
-#ifndef TRIM_FSFT
- uint32_t FAST_TRANSPORT: 1;
-#endif
uint32_t VBLANK_SYNCHRONIZABLE: 1;
};
@@ -950,10 +948,6 @@ struct dc_crtc_timing {
enum dc_aspect_ratio aspect_ratio;
enum scanning_type scan_type;
-#ifndef TRIM_FSFT
- uint32_t fast_transport_output_rate_100hz;
-#endif
-
struct dc_crtc_timing_flags flags;
uint32_t dsc_fixed_bits_per_pixel_x16; /* DSC target bitrate in 1/16 of bpp (e.g. 128 -> 8bpp) */
struct dc_dsc_config dsc_cfg;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 3697ea1d14c1..e61eea6db29c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -188,7 +188,6 @@ struct dc_stream_state {
struct link_encoder *link_enc;
struct dc_stream_debug_options debug;
struct dc_panel_patch sink_patches;
- union display_content_support content_support;
struct dc_crtc_timing timing;
struct dc_crtc_timing_adjust adjust;
struct dc_info_packet vrr_infopacket;
@@ -212,6 +211,7 @@ struct dc_stream_state {
struct dc_csc_transform csc_color_matrix;
enum dc_color_space output_color_space;
+ enum display_content_type content_type;
enum dc_dither_option dither_option;
enum view_3d_format view_format;
@@ -302,7 +302,6 @@ struct dc_stream_state {
bool vblank_synchronized;
bool fpo_in_use;
struct mall_stream_config mall_stream_config;
- bool skip_edp_power_down;
};
#define ABM_LEVEL_IMMEDIATE_DISABLE 255
@@ -521,12 +520,6 @@ struct dc_stream_status *dc_stream_get_status_from_state(
struct dc_stream_status *dc_stream_get_status(
struct dc_stream_state *dc_stream);
-#ifndef TRIM_FSFT
-bool dc_optimize_timing_for_fsft(
- struct dc_stream_state *pStream,
- unsigned int max_input_rate_in_khz);
-#endif
-
/*******************************************************************************
* Cursor interfaces - To manages the cursor within a stream
******************************************************************************/
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 445ad79001ce..35d146217aef 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -163,18 +163,6 @@ struct dc_edid {
#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20
-union display_content_support {
- unsigned int raw;
- struct {
- unsigned int valid_content_type :1;
- unsigned int game_content :1;
- unsigned int cinema_content :1;
- unsigned int photo_content :1;
- unsigned int graphics_content :1;
- unsigned int reserved :27;
- } bits;
-};
-
struct dc_panel_patch {
unsigned int dppowerup_delay;
unsigned int extra_t12_ms;
@@ -189,6 +177,7 @@ struct dc_panel_patch {
unsigned int disable_fams;
unsigned int skip_avmute;
unsigned int mst_start_top_delay;
+ unsigned int remove_sink_ext_caps;
};
struct dc_edid_caps {
@@ -207,8 +196,6 @@ struct dc_edid_caps {
uint32_t audio_latency;
uint32_t video_latency;
- union display_content_support content_support;
-
uint8_t qs_bit;
uint8_t qy_bit;
@@ -787,6 +774,7 @@ struct dc_context {
struct dc *dc;
void *driver_context; /* e.g. amdgpu_device */
+ struct dal_logger *logger;
struct dc_perf_trace *perf_trace;
void *cgs_device;
@@ -808,6 +796,7 @@ struct dc_context {
struct cp_psp cp_psp;
uint32_t *dcn_reg_offsets;
uint32_t *nbio_reg_offsets;
+ uint32_t *clk_reg_offsets;
};
/* DSC DPCD capabilities */
@@ -1002,10 +991,6 @@ struct link_mst_stream_allocation_table {
struct link_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM];
};
-struct backlight_settings {
- uint32_t backlight_millinits;
-};
-
/* PSR feature flags */
struct psr_settings {
bool psr_feature_enabled; // PSR is supported by sink
@@ -1049,7 +1034,9 @@ struct replay_config {
bool replay_smu_opt_supported; // SMU optimization is supported
unsigned int replay_enable_option; // Replay enablement option
uint32_t debug_flags; // Replay debug flags
- bool replay_timing_sync_supported; // Replay desync is supported
+ bool replay_timing_sync_supported; // Replay desync is supported
+ bool force_disable_desync_error_check; // Replay desync is supported
+ bool received_desync_error_hpd; //Replay Received Desync Error HPD.
union replay_error_status replay_error_status; // Replay error status
};
diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile
index 15b64c26d5a2..986e0e7abbc2 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile
@@ -26,7 +26,7 @@
# - register programming through common macros that look up register
# offset/shift/mask stored in dce_hw struct
-DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \
+DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o \
dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \
dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o dce_aux.o \
dce_i2c.o dce_i2c_hw.o dce_i2c_sw.o dmub_psr.o dmub_abm.o dmub_abm_lcd.o dce_panel_cntl.o \
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
index 168cb7094c95..051e4c2b4cf2 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
@@ -128,21 +128,6 @@
SRI(DC_ABM1_ACE_THRES_12, ABM, id), \
NBIO_SR(BIOS_SCRATCH_2)
-#define ABM_DCN32_REG_LIST(id)\
- SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \
- SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \
- SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \
- SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \
- SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \
- SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \
- SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \
- SRI(BL1_PWM_USER_LEVEL, ABM, id), \
- SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \
- SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \
- SRI(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \
- SRI(DC_ABM1_ACE_THRES_12, ABM, id), \
- NBIO_SR(BIOS_SCRATCH_2)
-
#define ABM_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
@@ -183,8 +168,7 @@
ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh)
-#define ABM_MASK_SH_LIST_DCN10(mask_sh) \
- ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
+#define ABM_MASK_SH_LIST_DCN10_COMMON(mask_sh) \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
@@ -214,9 +198,13 @@
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh)
-#define ABM_MASK_SH_LIST_DCN20(mask_sh) ABM_MASK_SH_LIST_DCE110(mask_sh)
+#define ABM_MASK_SH_LIST_DCN10(mask_sh) \
+ ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
+ ABM_MASK_SH_LIST_DCN10_COMMON(mask_sh)
+#define ABM_MASK_SH_LIST_DCN20(mask_sh) ABM_MASK_SH_LIST_DCE110(mask_sh)
#define ABM_MASK_SH_LIST_DCN30(mask_sh) ABM_MASK_SH_LIST_DCN10(mask_sh)
+#define ABM_MASK_SH_LIST_DCN35(mask_sh) ABM_MASK_SH_LIST_DCN10_COMMON(mask_sh)
#define ABM_MASK_SH_LIST_DCN32(mask_sh) \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
index c94a966c6612..140598f18bbd 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
@@ -407,6 +407,10 @@ void dce_aud_az_configure(
bool is_ac3_supported = false;
union audio_sample_rates sample_rate;
uint32_t strlen = 0;
+
+ if (signal == SIGNAL_TYPE_VIRTUAL)
+ return;
+
value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL);
set_reg_field_value(value, 1,
AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index ed8936405dfa..5d3f6fa1011e 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -34,6 +34,7 @@
#include "dce_clock_source.h"
#include "clk_mgr.h"
+#include "dccg.h"
#include "reg_helper.h"
@@ -43,7 +44,10 @@
#define CTX \
clk_src->base.ctx
-#define DC_LOGGER_INIT()
+#define DC_LOGGER \
+ calc_pll_cs->ctx->logger
+#define DC_LOGGER_INIT() \
+ struct calc_pll_clock_source *calc_pll_cs = &clk_src->calc_pll
#undef FN
#define FN(reg_name, field_name) \
@@ -1254,6 +1258,7 @@ static uint32_t dcn3_get_pix_clk_dividers(
struct pll_settings *pll_settings)
{
unsigned long long actual_pix_clk_100Hz = pix_clk_params ? pix_clk_params->requested_pix_clk_100hz : 0;
+ struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs);
DC_LOGGER_INIT();
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
index b87bfecb7755..a8e79104b684 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
@@ -586,7 +586,8 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait)
if (state == PSR_STATE0)
break;
}
- fsleep(500);
+ /* must *not* be fsleep - this can be called from high irq levels */
+ udelay(500);
}
/* assert if max retry hit */
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
index 4f552c3e7663..a2f48d46d199 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
@@ -308,6 +308,10 @@ static bool setup_engine(
}
}
+ if (dce_i2c_hw->masks->DC_I2C_DDC1_CLK_EN)
+ REG_UPDATE_N(SETUP, 1,
+ FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_EN), 1);
+
/* we have checked I2c not used by DMCU, set SW use I2C REQ to 1 to indicate SW using it*/
REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, 1);
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h
index 3f45ecd189a2..3da32217d9ec 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h
@@ -188,6 +188,7 @@ struct dce_i2c_shift {
uint8_t DC_I2C_REG_RW_CNTL_STATUS;
uint8_t I2C_LIGHT_SLEEP_FORCE;
uint8_t I2C_MEM_PWR_STATE;
+ uint8_t DC_I2C_DDC1_CLK_EN;
};
struct dce_i2c_mask {
@@ -232,6 +233,7 @@ struct dce_i2c_mask {
uint32_t DC_I2C_REG_RW_CNTL_STATUS;
uint32_t I2C_LIGHT_SLEEP_FORCE;
uint32_t I2C_MEM_PWR_STATE;
+ uint32_t DC_I2C_DDC1_CLK_EN;
};
#define I2C_COMMON_MASK_SH_LIST_DCN2(mask_sh)\
@@ -243,6 +245,10 @@ struct dce_i2c_mask {
I2C_SF(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh),\
I2C_SF(DIO_MEM_PWR_STATUS, I2C_MEM_PWR_STATE, mask_sh)
+#define I2C_COMMON_MASK_SH_LIST_DCN35(mask_sh)\
+ I2C_COMMON_MASK_SH_LIST_DCN30(mask_sh),\
+ I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_EN, mask_sh)
+
struct dce_i2c_registers {
uint32_t SETUP;
uint32_t SPEED;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
index 0f24b6fbd220..9d4170a356a2 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
@@ -35,6 +35,7 @@
static const uint8_t DP_SINK_DEVICE_STR_ID_1[] = {7, 1, 8, 7, 3};
static const uint8_t DP_SINK_DEVICE_STR_ID_2[] = {7, 1, 8, 7, 5};
+static const uint8_t DP_SINK_DEVICE_STR_ID_3[] = {0x42, 0x61, 0x6c, 0x73, 0x61};
/*
* Convert dmcub psr state to dmcu psr state.
@@ -216,7 +217,8 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait, uint8
break;
}
- fsleep(500);
+ /* must *not* be fsleep - this can be called from high irq levels */
+ udelay(500);
}
/* assert if max retry hit */
@@ -295,7 +297,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
struct psr_context *psr_context,
uint8_t panel_inst)
{
- union dmub_rb_cmd cmd;
+ union dmub_rb_cmd cmd = { 0 };
struct dc_context *dc = dmub->ctx;
struct dmub_cmd_psr_copy_settings_data *copy_settings_data
= &cmd.psr_copy_settings.psr_copy_settings_data;
@@ -408,6 +410,13 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
else
copy_settings_data->debug.bitfields.force_wakeup_by_tps3 = 0;
+ if (link->psr_settings.psr_version == DC_PSR_VERSION_1 &&
+ link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_0022B9 &&
+ !memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_3,
+ sizeof(DP_SINK_DEVICE_STR_ID_3))) {
+ copy_settings_data->poweroff_before_vertical_line = 16;
+ }
+
//WA for PSR1 on specific TCON, require frame delay for frame re-lock
copy_settings_data->relock_delay_frame_cnt = 0;
if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8)
diff --git a/drivers/gpu/drm/amd/display/dc/dce100/Makefile b/drivers/gpu/drm/amd/display/dc/dce100/Makefile
index ff20c47f559e..0d2f6bbf7558 100644
--- a/drivers/gpu/drm/amd/display/dc/dce100/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dce100/Makefile
@@ -25,7 +25,7 @@
CFLAGS_$(AMDDALPATH)/dc/dce100/dce100_resource.o = $(call cc-disable-warning, override-init)
-DCE100 = dce100_resource.o dce100_hw_sequencer.o
+DCE100 = dce100_resource.o
AMD_DAL_DCE100 = $(addprefix $(AMDDALPATH)/dc/dce100/,$(DCE100))
diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
index 899b25b0bad8..53a5f4cb648c 100644
--- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
@@ -30,7 +30,7 @@
#include "resource.h"
#include "include/irq_service_interface.h"
-#include "../virtual/virtual_stream_encoder.h"
+#include "virtual/virtual_stream_encoder.h"
#include "dce110/dce110_resource.h"
#include "dce110/dce110_timing_generator.h"
#include "irq/dce110/irq_service_dce110.h"
@@ -43,7 +43,7 @@
#include "dce/dce_clock_source.h"
#include "dce/dce_audio.h"
#include "dce/dce_hwseq.h"
-#include "dce100/dce100_hw_sequencer.h"
+#include "dce100/dce100_hwseq.h"
#include "dce/dce_panel_cntl.h"
#include "reg_helper.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile
index 84ab48df0c26..695a50ed5ad2 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dce110/Makefile
@@ -26,7 +26,7 @@
CFLAGS_$(AMDDALPATH)/dc/dce110/dce110_resource.o = $(call cc-disable-warning, override-init)
DCE110 = dce110_timing_generator.o \
-dce110_compressor.o dce110_hw_sequencer.o dce110_resource.o \
+dce110_compressor.o dce110_resource.o \
dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \
dce110_mem_input_v.o dce110_opp_v.o dce110_transform_v.o
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
index 1289b9418877..fe518fd27b08 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
@@ -46,7 +46,7 @@
#include "dce110/dce110_opp_v.h"
#include "dce/dce_clock_source.h"
#include "dce/dce_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
#include "dce/dce_aux.h"
#include "dce/dce_abm.h"
#include "dce/dce_dmcu.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dce112/Makefile b/drivers/gpu/drm/amd/display/dc/dce112/Makefile
index 9de6501702d2..e846ef58cab3 100644
--- a/drivers/gpu/drm/amd/display/dc/dce112/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dce112/Makefile
@@ -25,7 +25,7 @@
CFLAGS_$(AMDDALPATH)/dc/dce112/dce112_resource.o = $(call cc-disable-warning, override-init)
-DCE112 = dce112_compressor.o dce112_hw_sequencer.o \
+DCE112 = dce112_compressor.o \
dce112_resource.o
AMD_DAL_DCE112 = $(addprefix $(AMDDALPATH)/dc/dce112/,$(DCE112))
diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
index 2b20180f1a32..d1edac46c9a0 100644
--- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
@@ -44,7 +44,7 @@
#include "dce/dce_clock_source.h"
#include "dce/dce_hwseq.h"
-#include "dce112/dce112_hw_sequencer.h"
+#include "dce112/dce112_hwseq.h"
#include "dce/dce_abm.h"
#include "dce/dce_dmcu.h"
#include "dce/dce_aux.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/Makefile b/drivers/gpu/drm/amd/display/dc/dce120/Makefile
index a9cc4b73270b..097cf407a15d 100644
--- a/drivers/gpu/drm/amd/display/dc/dce120/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dce120/Makefile
@@ -27,7 +27,6 @@
CFLAGS_$(AMDDALPATH)/dc/dce120/dce120_resource.o = $(call cc-disable-warning, override-init)
DCE120 = dce120_resource.o dce120_timing_generator.o \
-dce120_hw_sequencer.o
AMD_DAL_DCE120 = $(addprefix $(AMDDALPATH)/dc/dce120/,$(DCE120))
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c
index 18c5a86d2d61..962de79be169 100644
--- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c
@@ -35,7 +35,7 @@
#include "dce112/dce112_resource.h"
#include "dce110/dce110_resource.h"
-#include "../virtual/virtual_stream_encoder.h"
+#include "virtual/virtual_stream_encoder.h"
#include "dce120_timing_generator.h"
#include "irq/dce120/irq_service_dce120.h"
#include "dce/dce_opp.h"
@@ -44,8 +44,8 @@
#include "dce/dce_mem_input.h"
#include "dce/dce_panel_cntl.h"
-#include "dce110/dce110_hw_sequencer.h"
-#include "dce120/dce120_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
+#include "dce120/dce120_hwseq.h"
#include "dce/dce_transform.h"
#include "clk_mgr.h"
#include "dce/dce_audio.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c
index 920c7ae29d53..1fdeef47e4dc 100644
--- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c
@@ -29,8 +29,8 @@
#include "dce60_hw_sequencer.h"
#include "dce/dce_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
-#include "dce100/dce100_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
+#include "dce100/dce100_hwseq.h"
/* include DCE6 register header files */
#include "dce/dce_6_0_d.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile
index 0a9d1a350d8b..93dd68c31275 100644
--- a/drivers/gpu/drm/amd/display/dc/dce80/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile
@@ -25,7 +25,7 @@
CFLAGS_$(AMDDALPATH)/dc/dce80/dce80_resource.o = $(call cc-disable-warning, override-init)
-DCE80 = dce80_timing_generator.o dce80_hw_sequencer.o \
+DCE80 = dce80_timing_generator.o \
dce80_resource.o
AMD_DAL_DCE80 = $(addprefix $(AMDDALPATH)/dc/dce80/,$(DCE80))
diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
index 061221394ce0..35a2cce0c2b8 100644
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
@@ -46,7 +46,7 @@
#include "dce/dce_clock_source.h"
#include "dce/dce_audio.h"
#include "dce/dce_hwseq.h"
-#include "dce80/dce80_hw_sequencer.h"
+#include "dce80/dce80_hwseq.h"
#include "dce100/dce100_resource.h"
#include "dce/dce_panel_cntl.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile
index 62ad1a11bff9..2d2007c3e2b6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile
@@ -22,7 +22,7 @@
#
# Makefile for DCN.
-DCN10 = dcn10_init.o dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \
+DCN10 = dcn10_init.o dcn10_resource.o dcn10_ipp.o \
dcn10_hw_sequencer_debug.o \
dcn10_dpp.o dcn10_opp.o dcn10_optc.o \
dcn10_hubp.o dcn10_mpc.o \
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
index e8752077571a..4201b7627030 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
@@ -171,11 +171,13 @@ struct dcn_hubbub_registers {
uint32_t DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B;
uint32_t DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C;
uint32_t DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D;
+ uint32_t DCHUBBUB_ARB_MALL_CNTL;
uint32_t SDPIF_REQUEST_RATE_LIMIT;
uint32_t DCHUBBUB_SDPIF_CFG0;
uint32_t DCHUBBUB_SDPIF_CFG1;
uint32_t DCHUBBUB_CLOCK_CNTL;
uint32_t DCHUBBUB_MEM_PWR_MODE_CTRL;
+ uint32_t DCHUBBUB_ARB_QOS_FORCE;
};
#define HUBBUB_REG_FIELD_LIST_DCN32(type) \
@@ -194,7 +196,13 @@ struct dcn_hubbub_registers {
type DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A;\
type DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B;\
type DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C;\
- type DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D
+ type DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D;\
+ type MALL_PREFETCH_COMPLETE;\
+ type MALL_IN_USE
+
+ #define HUBBUB_REG_FIELD_LIST_DCN35(type) \
+ type DCHUBBUB_FGCG_REP_DIS;\
+ type DCHUBBUB_ARB_ALLOW_CSTATE_DEEPSLEEP_LEGACY_MODE
/* set field name */
#define HUBBUB_SF(reg_name, field_name, post_fix)\
@@ -381,6 +389,7 @@ struct dcn_hubbub_shift {
HUBBUB_HVM_REG_FIELD_LIST(uint8_t);
HUBBUB_RET_REG_FIELD_LIST(uint8_t);
HUBBUB_REG_FIELD_LIST_DCN32(uint8_t);
+ HUBBUB_REG_FIELD_LIST_DCN35(uint8_t);
};
struct dcn_hubbub_mask {
@@ -389,6 +398,7 @@ struct dcn_hubbub_mask {
HUBBUB_HVM_REG_FIELD_LIST(uint32_t);
HUBBUB_RET_REG_FIELD_LIST(uint32_t);
HUBBUB_REG_FIELD_LIST_DCN32(uint32_t);
+ HUBBUB_REG_FIELD_LIST_DCN35(uint32_t);
};
struct dc;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
index 46a2ebcabd1a..92fdab731f4a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
@@ -27,8 +27,8 @@
#include "core_types.h"
#include "resource.h"
#include "custom_float.h"
-#include "dcn10_hw_sequencer.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dcn10/dcn10_hwseq.h"
+#include "dce110/dce110_hwseq.h"
#include "dce/dce_hwseq.h"
#include "abm.h"
#include "dmcu.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
index f2371c948822..a5bdac79a744 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
@@ -24,8 +24,8 @@
*/
#include "hw_sequencer_private.h"
-#include "dce110/dce110_hw_sequencer.h"
-#include "dcn10_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
+#include "dcn10/dcn10_hwseq.h"
#include "dcn20/dcn20_hwseq.h"
static const struct hw_sequencer_funcs dcn10_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h
index 773380ef4997..d980e6bd6c66 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h
@@ -168,6 +168,8 @@ struct dcn10_link_enc_registers {
uint32_t DIO_LINKE_CNTL;
uint32_t DIO_LINKF_CNTL;
uint32_t DIG_FIFO_CTRL0;
+ uint32_t DIO_CLK_CNTL;
+ uint32_t DIG_BE_CLK_CNTL;
};
#define LE_SF(reg_name, field_name, post_fix)\
@@ -476,12 +478,42 @@ struct dcn10_link_enc_registers {
#define DCN32_LINK_ENCODER_REG_FIELD_LIST(type) \
type DIG_FIFO_OUTPUT_PIXEL_MODE
+#define DCN35_LINK_ENCODER_REG_FIELD_LIST(type) \
+ type DIG_BE_ENABLE;\
+ type DIG_RB_SWITCH_EN;\
+ type DIG_BE_MODE;\
+ type DIG_BE_CLK_EN;\
+ type DIG_BE_SOFT_RESET;\
+ type HDCP_SOFT_RESET;\
+ type DIG_BE_SYMCLK_G_CLOCK_ON;\
+ type DIG_BE_SYMCLK_G_HDCP_CLOCK_ON;\
+ type DIG_BE_SYMCLK_G_TMDS_CLOCK_ON;\
+ type DISPCLK_R_GATE_DIS;\
+ type DISPCLK_G_GATE_DIS;\
+ type REFCLK_R_GATE_DIS;\
+ type REFCLK_G_GATE_DIS;\
+ type SOCCLK_G_GATE_DIS;\
+ type SYMCLK_FE_R_GATE_DIS;\
+ type SYMCLK_FE_G_GATE_DIS;\
+ type SYMCLK_R_GATE_DIS;\
+ type SYMCLK_G_GATE_DIS;\
+ type DIO_FGCG_REP_DIS;\
+ type DISPCLK_G_HDCP_GATE_DIS;\
+ type SYMCLKA_G_HDCP_GATE_DIS;\
+ type SYMCLKB_G_HDCP_GATE_DIS;\
+ type SYMCLKC_G_HDCP_GATE_DIS;\
+ type SYMCLKD_G_HDCP_GATE_DIS;\
+ type SYMCLKE_G_HDCP_GATE_DIS;\
+ type SYMCLKF_G_HDCP_GATE_DIS;\
+ type SYMCLKG_G_HDCP_GATE_DIS
+
struct dcn10_link_enc_shift {
DCN_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
DCN20_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
DCN30_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
DCN31_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
DCN32_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
+ DCN35_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
};
struct dcn10_link_enc_mask {
@@ -490,6 +522,7 @@ struct dcn10_link_enc_mask {
DCN30_LINK_ENCODER_REG_FIELD_LIST(uint32_t);
DCN31_LINK_ENCODER_REG_FIELD_LIST(uint32_t);
DCN32_LINK_ENCODER_REG_FIELD_LIST(uint32_t);
+ DCN35_LINK_ENCODER_REG_FIELD_LIST(uint32_t);
};
struct dcn10_link_encoder {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
index db766689af58..ab81594a7fad 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
@@ -26,7 +26,7 @@
#ifndef __DC_TIMING_GENERATOR_DCN10_H__
#define __DC_TIMING_GENERATOR_DCN10_H__
-#include "timing_generator.h"
+#include "optc.h"
#define DCN10TG_FROM_TG(tg)\
container_of(tg, struct optc, base)
@@ -189,6 +189,15 @@ struct dcn_optc_registers {
uint32_t OTG_M_CONST_DTO1;
uint32_t OTG_DRR_V_TOTAL_CHANGE;
uint32_t OTG_GLOBAL_CONTROL4;
+ uint32_t OTG_CRC0_WINDOWA_X_CONTROL_READBACK;
+ uint32_t OTG_CRC0_WINDOWA_Y_CONTROL_READBACK;
+ uint32_t OTG_CRC0_WINDOWB_X_CONTROL_READBACK;
+ uint32_t OTG_CRC0_WINDOWB_Y_CONTROL_READBACK;
+ uint32_t OTG_CRC1_WINDOWA_X_CONTROL_READBACK;
+ uint32_t OTG_CRC1_WINDOWA_Y_CONTROL_READBACK;
+ uint32_t OTG_CRC1_WINDOWB_X_CONTROL_READBACK;
+ uint32_t OTG_CRC1_WINDOWB_Y_CONTROL_READBACK;
+ uint32_t OPTC_CLOCK_CONTROL;
};
#define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\
@@ -554,200 +563,37 @@ struct dcn_optc_registers {
type OTG_H_TIMING_DIV_MODE_MANUAL;
+#define TG_REG_FIELD_LIST_DCN3_5(type) \
+ type OTG_CRC0_WINDOWA_X_START_READBACK;\
+ type OTG_CRC0_WINDOWA_X_END_READBACK;\
+ type OTG_CRC0_WINDOWA_Y_START_READBACK;\
+ type OTG_CRC0_WINDOWA_Y_END_READBACK;\
+ type OTG_CRC0_WINDOWB_X_START_READBACK;\
+ type OTG_CRC0_WINDOWB_X_END_READBACK;\
+ type OTG_CRC0_WINDOWB_Y_START_READBACK;\
+ type OTG_CRC0_WINDOWB_Y_END_READBACK; \
+ type OTG_CRC1_WINDOWA_X_START_READBACK;\
+ type OTG_CRC1_WINDOWA_X_END_READBACK;\
+ type OTG_CRC1_WINDOWA_Y_START_READBACK;\
+ type OTG_CRC1_WINDOWA_Y_END_READBACK;\
+ type OTG_CRC1_WINDOWB_X_START_READBACK;\
+ type OTG_CRC1_WINDOWB_X_END_READBACK;\
+ type OTG_CRC1_WINDOWB_Y_START_READBACK;\
+ type OTG_CRC1_WINDOWB_Y_END_READBACK;\
+ type OPTC_FGCG_REP_DIS;
+
struct dcn_optc_shift {
TG_REG_FIELD_LIST(uint8_t)
TG_REG_FIELD_LIST_DCN3_2(uint8_t)
+ TG_REG_FIELD_LIST_DCN3_5(uint8_t)
};
struct dcn_optc_mask {
TG_REG_FIELD_LIST(uint32_t)
TG_REG_FIELD_LIST_DCN3_2(uint32_t)
-};
-
-struct optc {
- struct timing_generator base;
-
- const struct dcn_optc_registers *tg_regs;
- const struct dcn_optc_shift *tg_shift;
- const struct dcn_optc_mask *tg_mask;
-
- int opp_count;
-
- uint32_t max_h_total;
- uint32_t max_v_total;
-
- uint32_t min_h_blank;
-
- uint32_t min_h_sync_width;
- uint32_t min_v_sync_width;
- uint32_t min_v_blank;
- uint32_t min_v_blank_interlace;
-
- int vstartup_start;
- int vupdate_offset;
- int vupdate_width;
- int vready_offset;
- struct dc_crtc_timing orginal_patched_timing;
- enum signal_type signal;
+ TG_REG_FIELD_LIST_DCN3_5(uint32_t)
};
void dcn10_timing_generator_init(struct optc *optc);
-struct dcn_otg_state {
- uint32_t v_blank_start;
- uint32_t v_blank_end;
- uint32_t v_sync_a_pol;
- uint32_t v_total;
- uint32_t v_total_max;
- uint32_t v_total_min;
- uint32_t v_total_min_sel;
- uint32_t v_total_max_sel;
- uint32_t v_sync_a_start;
- uint32_t v_sync_a_end;
- uint32_t h_blank_start;
- uint32_t h_blank_end;
- uint32_t h_sync_a_start;
- uint32_t h_sync_a_end;
- uint32_t h_sync_a_pol;
- uint32_t h_total;
- uint32_t underflow_occurred_status;
- uint32_t otg_enabled;
- uint32_t blank_enabled;
- uint32_t vertical_interrupt1_en;
- uint32_t vertical_interrupt1_line;
- uint32_t vertical_interrupt2_en;
- uint32_t vertical_interrupt2_line;
-};
-
-void optc1_read_otg_state(struct optc *optc1,
- struct dcn_otg_state *s);
-
-bool optc1_get_hw_timing(struct timing_generator *tg,
- struct dc_crtc_timing *hw_crtc_timing);
-
-bool optc1_validate_timing(
- struct timing_generator *optc,
- const struct dc_crtc_timing *timing);
-
-void optc1_program_timing(
- struct timing_generator *optc,
- const struct dc_crtc_timing *dc_crtc_timing,
- int vready_offset,
- int vstartup_start,
- int vupdate_offset,
- int vupdate_width,
- const enum signal_type signal,
- bool use_vbios);
-
-void optc1_setup_vertical_interrupt0(
- struct timing_generator *optc,
- uint32_t start_line,
- uint32_t end_line);
-void optc1_setup_vertical_interrupt1(
- struct timing_generator *optc,
- uint32_t start_line);
-void optc1_setup_vertical_interrupt2(
- struct timing_generator *optc,
- uint32_t start_line);
-
-void optc1_program_global_sync(
- struct timing_generator *optc,
- int vready_offset,
- int vstartup_start,
- int vupdate_offset,
- int vupdate_width);
-
-bool optc1_disable_crtc(struct timing_generator *optc);
-
-bool optc1_is_counter_moving(struct timing_generator *optc);
-
-void optc1_get_position(struct timing_generator *optc,
- struct crtc_position *position);
-
-uint32_t optc1_get_vblank_counter(struct timing_generator *optc);
-
-void optc1_get_crtc_scanoutpos(
- struct timing_generator *optc,
- uint32_t *v_blank_start,
- uint32_t *v_blank_end,
- uint32_t *h_position,
- uint32_t *v_position);
-
-void optc1_set_early_control(
- struct timing_generator *optc,
- uint32_t early_cntl);
-
-void optc1_wait_for_state(struct timing_generator *optc,
- enum crtc_state state);
-
-void optc1_set_blank(struct timing_generator *optc,
- bool enable_blanking);
-
-bool optc1_is_blanked(struct timing_generator *optc);
-
-void optc1_program_blank_color(
- struct timing_generator *optc,
- const struct tg_color *black_color);
-
-bool optc1_did_triggered_reset_occur(
- struct timing_generator *optc);
-
-void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst);
-
-void optc1_disable_reset_trigger(struct timing_generator *optc);
-
-void optc1_lock(struct timing_generator *optc);
-
-void optc1_unlock(struct timing_generator *optc);
-
-void optc1_enable_optc_clock(struct timing_generator *optc, bool enable);
-
-void optc1_set_drr(
- struct timing_generator *optc,
- const struct drr_params *params);
-
-void optc1_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max);
-
-void optc1_set_static_screen_control(
- struct timing_generator *optc,
- uint32_t event_triggers,
- uint32_t num_frames);
-
-void optc1_program_stereo(struct timing_generator *optc,
- const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags);
-
-bool optc1_is_stereo_left_eye(struct timing_generator *optc);
-
-void optc1_clear_optc_underflow(struct timing_generator *optc);
-
-void optc1_tg_init(struct timing_generator *optc);
-
-bool optc1_is_tg_enabled(struct timing_generator *optc);
-
-bool optc1_is_optc_underflow_occurred(struct timing_generator *optc);
-
-void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable);
-
-void optc1_set_timing_double_buffer(struct timing_generator *optc, bool enable);
-
-bool optc1_get_otg_active_size(struct timing_generator *optc,
- uint32_t *otg_active_width,
- uint32_t *otg_active_height);
-
-void optc1_enable_crtc_reset(
- struct timing_generator *optc,
- int source_tg_inst,
- struct crtc_trigger_info *crtc_tp);
-
-bool optc1_configure_crc(struct timing_generator *optc,
- const struct crc_params *params);
-
-bool optc1_get_crc(struct timing_generator *optc,
- uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb);
-
-bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing);
-
-void optc1_set_vtg_params(struct timing_generator *optc,
- const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2);
-
#endif /* __DC_TIMING_GENERATOR_DCN10_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
index 9f9145742f14..b94c5c97eee7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
@@ -36,8 +36,8 @@
#include "irq/dcn10/irq_service_dcn10.h"
#include "dcn10_dpp.h"
#include "dcn10_optc.h"
-#include "dcn10_hw_sequencer.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dcn10/dcn10_hwseq.h"
+#include "dce110/dce110_hwseq.h"
#include "dcn10_opp.h"
#include "dcn10_link_encoder.h"
#include "dcn10_stream_encoder.h"
@@ -554,6 +554,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.max_downscale_src_width = 3840,
.underflow_assert_delay_us = 0xFFFFFFFF,
.enable_legacy_fast_update = true,
+ .using_dml2 = false,
};
static const struct dc_debug_options debug_defaults_diags = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h
index 9d5e2a7848dd..c429590f1298 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h
@@ -188,6 +188,9 @@ struct dcn10_stream_enc_registers {
uint32_t HDMI_GENERIC_PACKET_CONTROL10;
uint32_t DIG_CLOCK_PATTERN;
uint32_t DIG_FIFO_CTRL0;
+ uint32_t DIG_FE_CLK_CNTL;
+ uint32_t DIG_FE_EN_CNTL;
+ uint32_t STREAM_MAPPER_CONTROL;
};
@@ -574,7 +577,22 @@ struct dcn10_stream_enc_registers {
type DIG_FIFO_READ_START_LEVEL;\
type DIG_FIFO_ENABLE;\
type DIG_FIFO_RESET;\
- type DIG_FIFO_RESET_DONE
+ type DIG_FIFO_RESET_DONE;\
+ type PIXEL_ENCODING_TYPE;\
+ type UNCOMPRESSED_PIXEL_FORMAT;\
+ type UNCOMPRESSED_COMPONENT_DEPTH
+
+#define SE_REG_FIELD_LIST_DCN3_5_COMMON(type) \
+ type DIG_FE_CLK_EN;\
+ type DIG_FE_MODE;\
+ type DIG_FE_SOFT_RESET;\
+ type DIG_FE_ENABLE;\
+ type DIG_FE_SYMCLK_FE_G_CLOCK_ON;\
+ type DIG_FE_DISPCLK_G_CLOCK_ON;\
+ type DIG_FE_SYMCLK_FE_G_AFMT_CLOCK_ON;\
+ type DIG_FE_SYMCLK_FE_G_TMDS_CLOCK_ON;\
+ type DIG_FE_SOCCLK_G_AFMT_CLOCK_ON;\
+ type DIG_STREAM_LINK_TARGET
struct dcn10_stream_encoder_shift {
SE_REG_FIELD_LIST_DCN1_0(uint8_t);
@@ -582,7 +600,7 @@ struct dcn10_stream_encoder_shift {
SE_REG_FIELD_LIST_DCN2_0(uint8_t);
SE_REG_FIELD_LIST_DCN3_0(uint8_t);
SE_REG_FIELD_LIST_DCN3_2(uint8_t);
-
+ SE_REG_FIELD_LIST_DCN3_5_COMMON(uint8_t);
};
struct dcn10_stream_encoder_mask {
@@ -591,7 +609,7 @@ struct dcn10_stream_encoder_mask {
SE_REG_FIELD_LIST_DCN2_0(uint32_t);
SE_REG_FIELD_LIST_DCN3_0(uint32_t);
SE_REG_FIELD_LIST_DCN3_2(uint32_t);
-
+ SE_REG_FIELD_LIST_DCN3_5_COMMON(uint32_t);
};
struct dcn10_stream_encoder {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile
index abaed2121feb..d7dc9696a8c8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile
@@ -2,7 +2,7 @@
#
# Makefile for DCN.
-DCN20 = dcn20_resource.o dcn20_init.o dcn20_hwseq.o dcn20_dpp.o dcn20_dpp_cm.o dcn20_hubp.o \
+DCN20 = dcn20_resource.o dcn20_init.o dcn20_dpp.o dcn20_dpp_cm.o dcn20_hubp.o \
dcn20_mpc.o dcn20_opp.o dcn20_hubbub.o dcn20_optc.o dcn20_mmhubbub.o \
dcn20_stream_encoder.o dcn20_link_encoder.o dcn20_dccg.o \
dcn20_vmid.o dcn20_dwb.o dcn20_dwb_scl.o
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h
index c8602bcfa393..ab6d09c6fe34 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h
@@ -240,12 +240,66 @@
type DTBCLK_P3_EN;\
type DENTIST_DISPCLK_CHG_DONE;
+#define DCCG35_REG_FIELD_LIST(type) \
+ type DPPCLK0_EN;\
+ type DPPCLK1_EN;\
+ type DPPCLK2_EN;\
+ type DPPCLK3_EN;\
+ type DSCCLK0_EN;\
+ type DSCCLK1_EN;\
+ type DSCCLK2_EN;\
+ type DSCCLK3_EN;\
+ type DISPCLK_DCCG_GATE_DISABLE;\
+ type DCCG_GLOBAL_FGCG_REP_DIS; \
+ type PHYASYMCLK_EN;\
+ type PHYASYMCLK_SRC_SEL;\
+ type PHYBSYMCLK_EN;\
+ type PHYBSYMCLK_SRC_SEL;\
+ type PHYCSYMCLK_EN;\
+ type PHYCSYMCLK_SRC_SEL;\
+ type PHYDSYMCLK_EN;\
+ type PHYDSYMCLK_SRC_SEL;\
+ type PHYESYMCLK_EN;\
+ type PHYESYMCLK_SRC_SEL;\
+ type PHYASYMCLK_ROOT_GATE_DISABLE;\
+ type PHYBSYMCLK_ROOT_GATE_DISABLE;\
+ type PHYCSYMCLK_ROOT_GATE_DISABLE;\
+ type PHYDSYMCLK_ROOT_GATE_DISABLE;\
+ type PHYESYMCLK_ROOT_GATE_DISABLE;\
+ type HDMISTREAMCLK0_GATE_DISABLE;\
+ type HDMISTREAMCLK1_GATE_DISABLE;\
+ type HDMISTREAMCLK2_GATE_DISABLE;\
+ type HDMISTREAMCLK3_GATE_DISABLE;\
+ type HDMISTREAMCLK4_GATE_DISABLE;\
+ type HDMISTREAMCLK5_GATE_DISABLE;\
+ type SYMCLKA_CLOCK_ENABLE;\
+ type SYMCLKB_CLOCK_ENABLE;\
+ type SYMCLKC_CLOCK_ENABLE;\
+ type SYMCLKD_CLOCK_ENABLE;\
+ type SYMCLKE_CLOCK_ENABLE;\
+ type SYMCLKA_FE_EN;\
+ type SYMCLKB_FE_EN;\
+ type SYMCLKC_FE_EN;\
+ type SYMCLKD_FE_EN;\
+ type SYMCLKE_FE_EN;\
+ type SYMCLKA_SRC_SEL;\
+ type SYMCLKB_SRC_SEL;\
+ type SYMCLKC_SRC_SEL;\
+ type SYMCLKD_SRC_SEL;\
+ type SYMCLKE_SRC_SEL;\
+ type SYMCLKA_FE_SRC_SEL;\
+ type SYMCLKB_FE_SRC_SEL;\
+ type SYMCLKC_FE_SRC_SEL;\
+ type SYMCLKD_FE_SRC_SEL;\
+ type SYMCLKE_FE_SRC_SEL;
+
struct dccg_shift {
DCCG_REG_FIELD_LIST(uint8_t)
DCCG3_REG_FIELD_LIST(uint8_t)
DCCG31_REG_FIELD_LIST(uint8_t)
DCCG314_REG_FIELD_LIST(uint8_t)
DCCG32_REG_FIELD_LIST(uint8_t)
+ DCCG35_REG_FIELD_LIST(uint8_t)
};
struct dccg_mask {
@@ -254,6 +308,7 @@ struct dccg_mask {
DCCG31_REG_FIELD_LIST(uint32_t)
DCCG314_REG_FIELD_LIST(uint32_t)
DCCG32_REG_FIELD_LIST(uint32_t)
+ DCCG35_REG_FIELD_LIST(uint32_t)
};
struct dccg_registers {
@@ -292,6 +347,15 @@ struct dccg_registers {
uint32_t DCCG_GATE_DISABLE_CNTL4;
uint32_t OTG_PIXEL_RATE_DIV;
uint32_t DTBCLK_P_CNTL;
+ uint32_t DPPCLK_CTRL;
+ uint32_t DCCG_GATE_DISABLE_CNTL5;
+ uint32_t DCCG_GATE_DISABLE_CNTL6;
+ uint32_t DCCG_GLOBAL_FGCG_REP_CNTL;
+ uint32_t SYMCLKA_CLOCK_ENABLE;
+ uint32_t SYMCLKB_CLOCK_ENABLE;
+ uint32_t SYMCLKC_CLOCK_ENABLE;
+ uint32_t SYMCLKD_CLOCK_ENABLE;
+ uint32_t SYMCLKE_CLOCK_ENABLE;
};
struct dcn_dccg {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
index 5eebe7f03ddc..c9ae2d8f0096 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
@@ -137,7 +137,15 @@ void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz)
dsc_enc_caps->max_total_throughput_mps = DCN20_MAX_DISPLAY_CLOCK_Mhz * 2;
}
- // TODO DSC: This is actually image width limitation, not a slice width. This should be added to the criteria to use ODM.
+ /* For pixel clock bigger than a single-pipe limit needing four engines ODM 4:1, which then quardruples our
+ * throughput and number of slices
+ */
+ if (pixel_clock_100Hz > DCN20_MAX_PIXEL_CLOCK_Mhz*10000*2) {
+ dsc_enc_caps->slice_caps.bits.NUM_SLICES_12 = 1;
+ dsc_enc_caps->slice_caps.bits.NUM_SLICES_16 = 1;
+ dsc_enc_caps->max_total_throughput_mps = DCN20_MAX_DISPLAY_CLOCK_Mhz * 4;
+ }
+
dsc_enc_caps->max_slice_width = 5184; /* (including 64 overlap pixels for eDP MSO mode) */
dsc_enc_caps->bpp_increment_div = 16; /* 1/16th of a bit */
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
index 4566bc7abf17..89c3bf0fe0c9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
@@ -30,6 +30,8 @@
#include "reg_helper.h"
#include "basics/conversion.h"
+#define DC_LOGGER \
+ ctx->logger
#define DC_LOGGER_INIT(logger)
#define REG(reg)\
@@ -1075,8 +1077,16 @@ void hubp2_cursor_set_position(
if (src_y_offset < 0)
src_y_offset = 0;
/* Save necessary cursor info x, y position. w, h is saved in attribute func. */
- hubp->cur_rect.x = src_x_offset + param->viewport.x;
- hubp->cur_rect.y = src_y_offset + param->viewport.y;
+ if (param->stream->link->psr_settings.psr_version >= DC_PSR_VERSION_SU_1 &&
+ param->rotation != ROTATION_ANGLE_0) {
+ hubp->cur_rect.x = 0;
+ hubp->cur_rect.y = 0;
+ hubp->cur_rect.w = param->stream->timing.h_addressable;
+ hubp->cur_rect.h = param->stream->timing.v_addressable;
+ } else {
+ hubp->cur_rect.x = src_x_offset + param->viewport.x;
+ hubp->cur_rect.y = src_y_offset + param->viewport.y;
+ }
}
void hubp2_clk_cntl(struct hubp *hubp, bool enable)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
index e4b44e691ce6..884e3e323338 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
@@ -23,9 +23,9 @@
*
*/
-#include "dce110/dce110_hw_sequencer.h"
-#include "dcn10/dcn10_hw_sequencer.h"
-#include "dcn20_hwseq.h"
+#include "dce110/dce110_hwseq.h"
+#include "dcn10/dcn10_hwseq.h"
+#include "dcn20/dcn20_hwseq.h"
#include "dcn20_init.h"
@@ -93,9 +93,6 @@ static const struct hw_sequencer_funcs dcn20_funcs = {
.set_backlight_level = dce110_set_backlight_level,
.set_abm_immediate_disable = dce110_set_abm_immediate_disable,
.set_pipe = dce110_set_pipe,
-#ifndef TRIM_FSFT
- .optimize_timing_for_fsft = dcn20_optimize_timing_for_fsft,
-#endif
.enable_lvds_link_output = dce110_enable_lvds_link_output,
.enable_tmds_link_output = dce110_enable_tmds_link_output,
.enable_dp_link_output = dce110_enable_dp_link_output,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
index d587f807dfd7..0a422fbb14bc 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -45,8 +45,8 @@
#include "irq/dcn20/irq_service_dcn20.h"
#include "dcn20_dpp.h"
#include "dcn20_optc.h"
-#include "dcn20_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dcn20/dcn20_hwseq.h"
+#include "dce110/dce110_hwseq.h"
#include "dcn10/dcn10_resource.h"
#include "dcn20_opp.h"
@@ -723,6 +723,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.sanity_checks = false,
.underflow_assert_delay_us = 0xFFFFFFFF,
.enable_legacy_fast_update = true,
+ .using_dml2 = false,
};
void dcn20_dpp_destroy(struct dpp **dpp)
@@ -1948,7 +1949,7 @@ int dcn20_validate_apply_pipe_split_flags(
v->ODMCombineEnablePerState[vlevel][pipe_plane];
if (v->ODMCombineEnabled[pipe_plane] == dm_odm_combine_mode_disabled) {
- if (resource_get_num_mpc_splits(pipe) == 1) {
+ if (resource_get_mpc_slice_count(pipe) == 2) {
/*If need split for mpc but 2 way split already*/
if (split[i] == 4)
split[i] = 2; /* 2 -> 4 MPC */
@@ -1956,7 +1957,7 @@ int dcn20_validate_apply_pipe_split_flags(
split[i] = 0; /* 2 -> 2 MPC */
else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state)
merge[i] = true; /* 2 -> 1 MPC */
- } else if (resource_get_num_mpc_splits(pipe) == 3) {
+ } else if (resource_get_mpc_slice_count(pipe) == 4) {
/*If need split for mpc but 4 way split already*/
if (split[i] == 2 && ((pipe->top_pipe && !pipe->top_pipe->top_pipe)
|| !pipe->bottom_pipe)) {
@@ -1965,7 +1966,7 @@ int dcn20_validate_apply_pipe_split_flags(
pipe->top_pipe->plane_state == pipe->plane_state)
merge[i] = true; /* 4 -> 1 MPC */
split[i] = 0;
- } else if (resource_get_num_odm_splits(pipe)) {
+ } else if (resource_get_odm_slice_count(pipe) > 1) {
/* ODM -> MPC transition */
if (pipe->prev_odm_pipe) {
split[i] = 0;
@@ -1973,7 +1974,7 @@ int dcn20_validate_apply_pipe_split_flags(
}
}
} else {
- if (resource_get_num_odm_splits(pipe) == 1) {
+ if (resource_get_odm_slice_count(pipe) == 2) {
/*If need split for odm but 2 way split already*/
if (split[i] == 4)
split[i] = 2; /* 2 -> 4 ODM */
@@ -1983,7 +1984,7 @@ int dcn20_validate_apply_pipe_split_flags(
ASSERT(0); /* NOT expected yet */
merge[i] = true; /* exit ODM */
}
- } else if (resource_get_num_odm_splits(pipe) == 3) {
+ } else if (resource_get_odm_slice_count(pipe) == 4) {
/*If need split for odm but 4 way split already*/
if (split[i] == 2 && ((pipe->prev_odm_pipe && !pipe->prev_odm_pipe->prev_odm_pipe)
|| !pipe->next_odm_pipe)) {
@@ -1993,7 +1994,7 @@ int dcn20_validate_apply_pipe_split_flags(
merge[i] = true; /* exit ODM */
}
split[i] = 0;
- } else if (resource_get_num_mpc_splits(pipe)) {
+ } else if (resource_get_mpc_slice_count(pipe) > 1) {
/* MPC -> ODM transition */
ASSERT(0); /* NOT expected yet */
if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) {
@@ -2141,9 +2142,17 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
bool fast_validate)
{
bool voltage_supported;
+ display_e2e_pipe_params_st *pipes;
+
+ pipes = kcalloc(dc->res_pool->pipe_count, sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
+ if (!pipes)
+ return false;
+
DC_FP_START();
- voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate);
+ voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate, pipes);
DC_FP_END();
+
+ kfree(pipes);
return voltage_supported;
}
@@ -2211,12 +2220,22 @@ enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_stat
return DC_OK;
}
+void dcn20_release_pipe(struct dc_state *context,
+ struct pipe_ctx *pipe,
+ const struct resource_pool *pool)
+{
+ if (resource_is_pipe_type(pipe, OPP_HEAD) && pipe->stream_res.dsc)
+ dcn20_release_dsc(&context->res_ctx, pool, &pipe->stream_res.dsc);
+ memset(pipe, 0, sizeof(*pipe));
+}
+
static const struct resource_funcs dcn20_res_pool_funcs = {
.destroy = dcn20_destroy_resource_pool,
.link_enc_create = dcn20_link_encoder_create,
.panel_cntl_create = dcn20_panel_cntl_create,
.validate_bandwidth = dcn20_validate_bandwidth,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer,
+ .release_pipe = dcn20_release_pipe,
.add_stream_to_ctx = dcn20_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
index 6d1a8924e57b..37ecaccc5d12 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
@@ -63,7 +63,9 @@ struct pipe_ctx *dcn20_acquire_free_pipe_for_layer(
struct dc_state *new_ctx,
const struct resource_pool *pool,
const struct pipe_ctx *opp_head_pipe);
-
+void dcn20_release_pipe(struct dc_state *context,
+ struct pipe_ctx *pipe,
+ const struct resource_pool *pool);
struct stream_encoder *dcn20_stream_encoder_create(
enum engine_id eng_id,
struct dc_context *ctx);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.c
index 96c263223315..5bc3bc60a2ac 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.c
@@ -38,6 +38,9 @@
#define FN(reg_name, field_name) \
vmid->shifts->field_name, vmid->masks->field_name
+#define DC_LOGGER \
+ CTX->logger
+
static void dcn20_wait_for_vmid_ready(struct dcn20_vmid *vmid)
{
/* According the hardware spec, we need to poll for the lowest
diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/Makefile b/drivers/gpu/drm/amd/display/dc/dcn201/Makefile
index 5c9ce2cebb0f..3a41a97b0729 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn201/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn201/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: MIT
#
# Makefile for DCN.
-DCN201 = dcn201_init.o dcn201_resource.o dcn201_hwseq.o \
+DCN201 = dcn201_init.o dcn201_resource.o \
dcn201_hubbub.o\
dcn201_mpc.o dcn201_hubp.o dcn201_opp.o dcn201_optc.o dcn201_dpp.o \
dcn201_dccg.o dcn201_link_encoder.o
diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c
index 92dd4cddbab8..a13bf6c9386e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c
@@ -23,10 +23,10 @@
*
*/
-#include "dce110/dce110_hw_sequencer.h"
-#include "dcn10/dcn10_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
+#include "dcn10/dcn10_hwseq.h"
#include "dcn20/dcn20_hwseq.h"
-#include "dcn201_hwseq.h"
+#include "dcn201/dcn201_hwseq.h"
#include "dcn201_init.h"
static const struct hw_sequencer_funcs dcn201_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c
index 2dc4d2c1410b..bca22d867696 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c
@@ -43,8 +43,8 @@
#include "dcn201/dcn201_hubbub.h"
#include "dcn201_dccg.h"
#include "dcn201_optc.h"
-#include "dcn201_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dcn201/dcn201_hwseq.h"
+#include "dce110/dce110_hwseq.h"
#include "dcn201_opp.h"
#include "dcn201/dcn201_link_encoder.h"
#include "dcn20/dcn20_stream_encoder.h"
@@ -614,6 +614,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.underflow_assert_delay_us = 0xFFFFFFFF,
.enable_tri_buf = false,
.enable_legacy_fast_update = true,
+ .using_dml2 = false,
};
static void dcn201_dpp_destroy(struct dpp **dpp)
@@ -1069,6 +1070,7 @@ static struct resource_funcs dcn201_res_pool_funcs = {
.add_dsc_to_stream_resource = NULL,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn201_acquire_free_pipe_for_layer,
+ .release_pipe = dcn20_release_pipe,
.populate_dml_writeback_from_context = dcn201_populate_dml_writeback_from_context,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.set_mcif_arb_params = dcn20_set_mcif_arb_params,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile
index 0dc06e428999..ce1be0afae4a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile
@@ -3,7 +3,7 @@
# Makefile for DCN21.
DCN21 = dcn21_init.o dcn21_hubp.o dcn21_hubbub.o dcn21_resource.o \
- dcn21_hwseq.o dcn21_link_encoder.o dcn21_dccg.o
+ dcn21_link_encoder.o dcn21_dccg.o
AMD_DAL_DCN21 = $(addprefix $(AMDDALPATH)/dc/dcn21/,$(DCN21))
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
index f976fac8dc3f..68cad55c72ab 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
@@ -31,6 +31,8 @@
#include "dc_dmub_srv.h"
+#define DC_LOGGER \
+ ctx->logger
#define DC_LOGGER_INIT(logger)
#define REG(reg)\
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c
index f024157bd6eb..18249c6b6d81 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c
@@ -23,10 +23,10 @@
*
*/
-#include "dce110/dce110_hw_sequencer.h"
-#include "dcn10/dcn10_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
+#include "dcn10/dcn10_hwseq.h"
#include "dcn20/dcn20_hwseq.h"
-#include "dcn21_hwseq.h"
+#include "dcn21/dcn21_hwseq.h"
#include "dcn21_init.h"
@@ -96,9 +96,6 @@ static const struct hw_sequencer_funcs dcn21_funcs = {
.set_backlight_level = dcn21_set_backlight_level,
.set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
.set_pipe = dcn21_set_pipe,
-#ifndef TRIM_FSFT
- .optimize_timing_for_fsft = dcn20_optimize_timing_for_fsft,
-#endif
.enable_lvds_link_output = dce110_enable_lvds_link_output,
.enable_tmds_link_output = dce110_enable_tmds_link_output,
.enable_dp_link_output = dce110_enable_dp_link_output,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
index d1a25fe6c44f..42277b280586 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
@@ -49,7 +49,7 @@
#include "dcn20/dcn20_dpp.h"
#include "dcn20/dcn20_optc.h"
#include "dcn21/dcn21_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
#include "dcn20/dcn20_opp.h"
#include "dcn20/dcn20_dsc.h"
#include "dcn21/dcn21_link_encoder.h"
@@ -654,6 +654,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.dmub_command_table = true,
.use_max_lb = true,
.enable_legacy_fast_update = true,
+ .using_dml2 = false,
};
static const struct dc_panel_config panel_config_defaults = {
@@ -953,9 +954,17 @@ static bool dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context,
bool fast_validate)
{
bool voltage_supported;
+ display_e2e_pipe_params_st *pipes;
+
+ pipes = kcalloc(dc->res_pool->pipe_count, sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
+ if (!pipes)
+ return false;
+
DC_FP_START();
- voltage_supported = dcn21_validate_bandwidth_fp(dc, context, fast_validate);
+ voltage_supported = dcn21_validate_bandwidth_fp(dc, context, fast_validate, pipes);
DC_FP_END();
+
+ kfree(pipes);
return voltage_supported;
}
@@ -1389,6 +1398,7 @@ static const struct resource_funcs dcn21_res_pool_funcs = {
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer,
+ .release_pipe = dcn20_release_pipe,
.populate_dml_writeback_from_context = dcn20_populate_dml_writeback_from_context,
.patch_unknown_plane_state = dcn21_patch_unknown_plane_state,
.set_mcif_arb_params = dcn20_set_mcif_arb_params,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
index 4a3e9e47b6b6..af4d2065d2c1 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
@@ -30,7 +30,6 @@ DCN30 := \
dcn30_dpp.o \
dcn30_optc.o \
dcn30_dccg.o \
- dcn30_hwseq.o \
dcn30_mpc.o dcn30_vpg.o \
dcn30_afmt.o \
dcn30_dio_stream_encoder.o \
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
index e0df9b0065f9..ddb344056d40 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
@@ -114,7 +114,6 @@ bool cm3_helper_translate_curve_to_hw_format(
struct pwl_result_data *rgb;
struct pwl_result_data *rgb_plus_1;
struct pwl_result_data *rgb_minus_1;
- struct fixed31_32 end_value;
int32_t region_start, region_end;
int32_t i;
@@ -176,7 +175,7 @@ bool cm3_helper_translate_curve_to_hw_format(
NUMBER_SW_SEGMENTS;
for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
i += increment) {
- if (j == hw_points - 1)
+ if (j == hw_points)
break;
rgb_resulted[j].red = output_tf->tf_pts.red[i];
rgb_resulted[j].green = output_tf->tf_pts.green[i];
@@ -187,13 +186,13 @@ bool cm3_helper_translate_curve_to_hw_format(
/* last point */
start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
- rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
- rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
- rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
+ rgb_resulted[hw_points].red = output_tf->tf_pts.red[start_index];
+ rgb_resulted[hw_points].green = output_tf->tf_pts.green[start_index];
+ rgb_resulted[hw_points].blue = output_tf->tf_pts.blue[start_index];
- rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red;
- rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green;
- rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue;
+ rgb_resulted[hw_points+1].red = rgb_resulted[hw_points].red;
+ rgb_resulted[hw_points+1].green = rgb_resulted[hw_points].green;
+ rgb_resulted[hw_points+1].blue = rgb_resulted[hw_points].blue;
// All 3 color channels have same x
corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
@@ -220,34 +219,16 @@ bool cm3_helper_translate_curve_to_hw_format(
/* see comment above, m_arrPoints[1].y should be the Y value for the
* region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
*/
- corner_points[1].red.y = rgb_resulted[hw_points - 1].red;
- corner_points[1].green.y = rgb_resulted[hw_points - 1].green;
- corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;
+ corner_points[1].red.y = rgb_resulted[hw_points].red;
+ corner_points[1].green.y = rgb_resulted[hw_points].green;
+ corner_points[1].blue.y = rgb_resulted[hw_points].blue;
corner_points[1].red.slope = dc_fixpt_zero;
corner_points[1].green.slope = dc_fixpt_zero;
corner_points[1].blue.slope = dc_fixpt_zero;
- if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_HLG) {
- /* for PQ/HLG, we want to have a straight line from last HW X point,
- * and the slope to be such that we hit 1.0 at 10000/1000 nits.
- */
-
- if (output_tf->tf == TRANSFER_FUNCTION_PQ)
- end_value = dc_fixpt_from_int(125);
- else
- end_value = dc_fixpt_from_fraction(125, 10);
-
- corner_points[1].red.slope = dc_fixpt_div(
- dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y),
- dc_fixpt_sub(end_value, corner_points[1].red.x));
- corner_points[1].green.slope = dc_fixpt_div(
- dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y),
- dc_fixpt_sub(end_value, corner_points[1].green.x));
- corner_points[1].blue.slope = dc_fixpt_div(
- dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y),
- dc_fixpt_sub(end_value, corner_points[1].blue.x));
- }
- lut_params->hw_points_num = hw_points;
+ // DCN3+ have 257 pts in lieu of no separate slope registers
+ // Prior HW had 256 base+slope pairs
+ lut_params->hw_points_num = hw_points + 1;
k = 0;
for (i = 1; i < MAX_REGIONS_NUMBER; i++) {
@@ -267,38 +248,37 @@ bool cm3_helper_translate_curve_to_hw_format(
rgb_plus_1 = rgb_resulted + 1;
rgb_minus_1 = rgb;
- i = 1;
- while (i != hw_points + 1) {
- if (i >= hw_points - 1) {
- if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
- rgb_plus_1->red = dc_fixpt_add(rgb->red, rgb_minus_1->delta_red);
- if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
- rgb_plus_1->green = dc_fixpt_add(rgb->green, rgb_minus_1->delta_green);
- if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
- rgb_plus_1->blue = dc_fixpt_add(rgb->blue, rgb_minus_1->delta_blue);
- }
-
- rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red);
- rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
- rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue);
+ if (fixpoint == true) {
+ i = 1;
+ while (i != hw_points + 2) {
+ if (i >= hw_points) {
+ if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
+ rgb_plus_1->red = dc_fixpt_add(rgb->red,
+ rgb_minus_1->delta_red);
+ if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
+ rgb_plus_1->green = dc_fixpt_add(rgb->green,
+ rgb_minus_1->delta_green);
+ if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
+ rgb_plus_1->blue = dc_fixpt_add(rgb->blue,
+ rgb_minus_1->delta_blue);
+ }
- if (fixpoint == true) {
rgb->delta_red_reg = dc_fixpt_clamp_u0d10(rgb->delta_red);
rgb->delta_green_reg = dc_fixpt_clamp_u0d10(rgb->delta_green);
rgb->delta_blue_reg = dc_fixpt_clamp_u0d10(rgb->delta_blue);
rgb->red_reg = dc_fixpt_clamp_u0d14(rgb->red);
rgb->green_reg = dc_fixpt_clamp_u0d14(rgb->green);
rgb->blue_reg = dc_fixpt_clamp_u0d14(rgb->blue);
- }
- ++rgb_plus_1;
- rgb_minus_1 = rgb;
- ++rgb;
- ++i;
+ ++rgb_plus_1;
+ rgb_minus_1 = rgb;
+ ++rgb;
+ ++i;
+ }
}
cm3_helper_convert_to_custom_float(rgb_resulted,
lut_params->corner_points,
- hw_points, fixpoint);
+ hw_points+1, fixpoint);
return true;
}
@@ -603,24 +583,6 @@ bool cm3_helper_convert_to_custom_float(
return false;
}
- if (!convert_to_custom_float_format(rgb->delta_red, &fmt,
- &rgb->delta_red_reg)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
- if (!convert_to_custom_float_format(rgb->delta_green, &fmt,
- &rgb->delta_green_reg)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
- if (!convert_to_custom_float_format(rgb->delta_blue, &fmt,
- &rgb->delta_blue_reg)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
++rgb;
++i;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
index 50dc83404644..11f7746f3a65 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
@@ -613,16 +613,19 @@ static void dpp3_program_blnd_pwl(
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].red_reg);
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, last_base_value_red);
} else {
+ REG_SET(CM_BLNDGAM_LUT_INDEX, 0, CM_BLNDGAM_LUT_INDEX, 0);
REG_UPDATE(CM_BLNDGAM_LUT_CONTROL, CM_BLNDGAM_LUT_WRITE_COLOR_MASK, 4);
for (i = 0 ; i < num; i++)
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].red_reg);
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, last_base_value_red);
+ REG_SET(CM_BLNDGAM_LUT_INDEX, 0, CM_BLNDGAM_LUT_INDEX, 0);
REG_UPDATE(CM_BLNDGAM_LUT_CONTROL, CM_BLNDGAM_LUT_WRITE_COLOR_MASK, 2);
for (i = 0 ; i < num; i++)
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].green_reg);
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, last_base_value_green);
+ REG_SET(CM_BLNDGAM_LUT_INDEX, 0, CM_BLNDGAM_LUT_INDEX, 0);
REG_UPDATE(CM_BLNDGAM_LUT_CONTROL, CM_BLNDGAM_LUT_WRITE_COLOR_MASK, 1);
for (i = 0 ; i < num; i++)
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].blue_reg);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h
index 2082372d69ee..cea3208e4ab1 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h
@@ -195,7 +195,6 @@
TF_SF(CM0_CM_GAMCOR_LUT_DATA, CM_GAMCOR_LUT_DATA, mask_sh),\
TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_WRITE_COLOR_MASK, mask_sh),\
TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_READ_COLOR_SEL, mask_sh),\
- TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_READ_DBG, mask_sh),\
TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_HOST_SEL, mask_sh),\
TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_CONFIG_MODE, mask_sh),\
TF_SF(CM0_CM_GAMCOR_RAMA_START_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_B, mask_sh),\
@@ -427,7 +426,6 @@
type CM_GAMCOR_LUT_DATA; \
type CM_GAMCOR_LUT_WRITE_COLOR_MASK; \
type CM_GAMCOR_LUT_READ_COLOR_SEL; \
- type CM_GAMCOR_LUT_READ_DBG; \
type CM_GAMCOR_LUT_HOST_SEL; \
type CM_GAMCOR_LUT_CONFIG_MODE; \
type CM_GAMCOR_LUT_STATUS; \
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h
index fc00ec0a0881..a5d1b81e768d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h
@@ -217,7 +217,6 @@
SF_DWB2(DWB_OGAM_LUT_DATA, DWBCP, 0, DWB_OGAM_LUT_DATA, mask_sh),\
SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_WRITE_COLOR_MASK, mask_sh),\
SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_READ_COLOR_SEL, mask_sh),\
- SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_READ_DBG, mask_sh),\
SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_HOST_SEL, mask_sh),\
SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_CONFIG_MODE, mask_sh),\
SF_DWB2(DWB_OGAM_RAMA_START_CNTL_B, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_B, mask_sh),\
@@ -525,7 +524,6 @@
type DWB_OGAM_LUT_DATA;\
type DWB_OGAM_LUT_WRITE_COLOR_MASK;\
type DWB_OGAM_LUT_READ_COLOR_SEL;\
- type DWB_OGAM_LUT_READ_DBG;\
type DWB_OGAM_LUT_HOST_SEL;\
type DWB_OGAM_LUT_CONFIG_MODE;\
type DWB_OGAM_LUT_STATUS;\
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c
index 2861d974fcf6..75547ce86c09 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c
@@ -316,7 +316,7 @@ bool hubp3_program_surface_flip_and_addr(
return true;
}
-static void hubp3_program_tiling(
+void hubp3_program_tiling(
struct dcn20_hubp *hubp2,
const union dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h
index 8a32772d4e91..b010531a7fe8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h
@@ -278,6 +278,11 @@ void hubp3_setup(
struct _vcs_dpi_display_rq_regs_st *rq_regs,
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest);
+void hubp3_program_tiling(
+ struct dcn20_hubp *hubp2,
+ const union dc_tiling_info *info,
+ const enum surface_pixel_format pixel_format);
+
void hubp3_dcc_control(struct hubp *hubp, bool enable,
enum hubp_ind_block_size blk_size);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c
index 0de8b2783cf6..9894caedffed 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c
@@ -23,16 +23,16 @@
*
*/
-#include "dce110/dce110_hw_sequencer.h"
-#include "dcn10/dcn10_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
+#include "dcn10/dcn10_hwseq.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn21/dcn21_hwseq.h"
-#include "dcn30_hwseq.h"
+#include "dcn30/dcn30_hwseq.h"
#include "dcn30_init.h"
static const struct hw_sequencer_funcs dcn30_funcs = {
- .program_gamut_remap = dcn10_program_gamut_remap,
+ .program_gamut_remap = dcn30_program_gamut_remap,
.init_hw = dcn30_init_hw,
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
.apply_ctx_for_surface = NULL,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
index 6cf40c1332bc..d1500b223858 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
@@ -278,22 +278,10 @@ static void mpc3_program_ogam_pwl(
{
uint32_t i;
struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
- uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg;
- uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg;
- uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg;
-
- /*the entries of DCN3AG gamma LUTs take 18bit base values as opposed to
- *38 base+delta values per entry in earlier DCN architectures
- *last base value for our lut is compute by adding the last base value
- *in our data + last delta
- */
if (is_rgb_equal(rgb, num)) {
for (i = 0 ; i < num; i++)
REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg);
-
- REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_red);
-
} else {
REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id],
@@ -302,8 +290,6 @@ static void mpc3_program_ogam_pwl(
for (i = 0 ; i < num; i++)
REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg);
- REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_red);
-
REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0);
REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id],
@@ -312,8 +298,6 @@ static void mpc3_program_ogam_pwl(
for (i = 0 ; i < num; i++)
REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].green_reg);
- REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_green);
-
REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0);
REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id],
@@ -322,7 +306,6 @@ static void mpc3_program_ogam_pwl(
for (i = 0 ; i < num; i++)
REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].blue_reg);
- REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_blue);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h
index c8a3a6a96ff7..5198f2167c7c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h
@@ -779,7 +779,6 @@
type MPCC_MCM_1DLUT_LUT_DATA;\
type MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK;\
type MPCC_MCM_1DLUT_LUT_READ_COLOR_SEL;\
- type MPCC_MCM_1DLUT_LUT_READ_DBG;\
type MPCC_MCM_1DLUT_LUT_HOST_SEL;\
type MPCC_MCM_1DLUT_LUT_CONFIG_MODE;\
type MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_B;\
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
index 5bf4d0aa6230..b97bdb868a0e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
@@ -207,7 +207,7 @@ void optc3_set_odm_bypass(struct timing_generator *optc,
);
h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing);
- REG_SET(OTG_H_TIMING_CNTL, 0,
+ REG_UPDATE(OTG_H_TIMING_CNTL,
OTG_H_TIMING_DIV_MODE, h_div);
REG_SET(OPTC_MEMORY_CONFIG, 0,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
index 88c0b24a3249..7b259cb5f418 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
@@ -44,7 +44,7 @@
#include "dcn30/dcn30_optc.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
#include "dcn30/dcn30_opp.h"
#include "dcn20/dcn20_dsc.h"
#include "dcn30/dcn30_vpg.h"
@@ -91,6 +91,8 @@
#include "amdgpu_socbb.h"
#include "dc_dmub_srv.h"
+#define DC_LOGGER \
+ dc->ctx->logger
#define DC_LOGGER_INIT(logger)
enum dcn30_clk_src_array_id {
@@ -727,6 +729,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.use_max_lb = true,
.exit_idle_opt_for_cursor_updates = true,
.enable_legacy_fast_update = false,
+ .using_dml2 = false,
};
static const struct dc_panel_config panel_config_defaults = {
@@ -2217,6 +2220,7 @@ static const struct resource_funcs dcn30_res_pool_funcs = {
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
.populate_dml_pipes = dcn30_populate_dml_pipes_from_context,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer,
+ .release_pipe = dcn20_release_pipe,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
index 9002cb10a6ae..30fbc5e06dca 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
@@ -11,7 +11,7 @@
# Makefile for dcn30.
DCN301 = dcn301_init.o dcn301_resource.o dcn301_dccg.o \
- dcn301_dio_link_encoder.o dcn301_hwseq.o dcn301_panel_cntl.o dcn301_hubbub.o \
+ dcn301_dio_link_encoder.o dcn301_panel_cntl.o dcn301_hubbub.o \
dcn301_optc.o
AMD_DAL_DCN301 = $(addprefix $(AMDDALPATH)/dc/dcn301/,$(DCN301))
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c
index 61205cdbe2d5..6477009ce065 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c
@@ -23,17 +23,17 @@
*
*/
-#include "dce110/dce110_hw_sequencer.h"
-#include "dcn10/dcn10_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
+#include "dcn10/dcn10_hwseq.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn21/dcn21_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
-#include "dcn301_hwseq.h"
+#include "dcn301/dcn301_hwseq.h"
#include "dcn301_init.h"
static const struct hw_sequencer_funcs dcn301_funcs = {
- .program_gamut_remap = dcn10_program_gamut_remap,
+ .program_gamut_remap = dcn30_program_gamut_remap,
.init_hw = dcn10_init_hw,
.power_down_on_boot = dcn10_power_down_on_boot,
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
index 79d6697d13b6..f3b75f283aa2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
@@ -45,7 +45,7 @@
#include "dcn301/dcn301_optc.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
#include "dcn30/dcn30_opp.h"
#include "dcn20/dcn20_dsc.h"
#include "dcn30/dcn30_vpg.h"
@@ -92,6 +92,8 @@
#define TO_DCN301_RES_POOL(pool)\
container_of(pool, struct dcn301_resource_pool, base)
+#define DC_LOGGER \
+ dc->ctx->logger
#define DC_LOGGER_INIT(logger)
enum dcn301_clk_src_array_id {
@@ -699,7 +701,8 @@ static const struct dc_debug_options debug_defaults_drv = {
.dwb_fi_phase = -1, // -1 = disable
.dmub_command_table = true,
.use_max_lb = false,
- .exit_idle_opt_for_cursor_updates = true
+ .exit_idle_opt_for_cursor_updates = true,
+ .using_dml2 = false,
};
static void dcn301_dpp_destroy(struct dpp **dpp)
@@ -1380,6 +1383,7 @@ static struct resource_funcs dcn301_res_pool_funcs = {
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
.populate_dml_pipes = dcn30_populate_dml_pipes_from_context,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer,
+ .release_pipe = dcn20_release_pipe,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/Makefile b/drivers/gpu/drm/amd/display/dc/dcn302/Makefile
index ebd01cb467b7..95b66baf39e9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn302/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn302/Makefile
@@ -5,7 +5,7 @@
#
# Makefile for dcn302.
-DCN3_02 = dcn302_init.o dcn302_hwseq.o dcn302_resource.o
+DCN3_02 = dcn302_init.o dcn302_resource.o
AMD_DAL_DCN3_02 = $(addprefix $(AMDDALPATH)/dc/dcn302/,$(DCN3_02))
diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_init.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_init.c
index eb375f30f5bc..637f9514d37b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_init.c
@@ -23,7 +23,7 @@
*
*/
-#include "dcn302_hwseq.h"
+#include "dcn302/dcn302_hwseq.h"
#include "dcn30/dcn30_init.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
index 447abcd593be..63ac984a04f7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
@@ -74,6 +74,8 @@
#include "nbio/nbio_7_4_offset.h"
#include "amdgpu_socbb.h"
+#define DC_LOGGER \
+ dc->ctx->logger
#define DC_LOGGER_INIT(logger)
static const struct dc_debug_options debug_defaults_drv = {
@@ -97,6 +99,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.use_max_lb = true,
.exit_idle_opt_for_cursor_updates = true,
.enable_legacy_fast_update = false,
+ .using_dml2 = false,
};
static const struct dc_panel_config panel_config_defaults = {
@@ -1137,6 +1140,7 @@ static struct resource_funcs dcn302_res_pool_funcs = {
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
.populate_dml_pipes = dcn30_populate_dml_pipes_from_context,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer,
+ .release_pipe = dcn20_release_pipe,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/Makefile b/drivers/gpu/drm/amd/display/dc/dcn303/Makefile
index 8702e0b7fda3..d7b3ad780e5d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn303/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn303/Makefile
@@ -6,7 +6,7 @@
#
# Makefile for dcn303.
-DCN3_03 = dcn303_init.o dcn303_hwseq.o dcn303_resource.o
+DCN3_03 = dcn303_init.o dcn303_resource.o
AMD_DAL_DCN3_03 = $(addprefix $(AMDDALPATH)/dc/dcn303/,$(DCN3_03))
diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_dccg.h
index 294bd757bcb5..2e12fb643005 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_dccg.h
@@ -2,6 +2,24 @@
/*
* Copyright (C) 2021 Advanced Micro Devices, Inc.
*
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
* Authors: AMD
*/
diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.c
deleted file mode 100644
index b48b732aa647..000000000000
--- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.c
+++ /dev/null
@@ -1,45 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright (C) 2021 Advanced Micro Devices, Inc.
- *
- * Authors: AMD
- */
-
-#include "dcn303_hwseq.h"
-
-#include "dce/dce_hwseq.h"
-
-#include "reg_helper.h"
-#include "dc.h"
-
-#define DC_LOGGER_INIT(logger)
-
-#define CTX \
- hws->ctx
-#define REG(reg)\
- hws->regs->reg
-
-#undef FN
-#define FN(reg_name, field_name) \
- hws->shifts->field_name, hws->masks->field_name
-
-
-void dcn303_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on)
-{
- /*DCN303 removes PG registers*/
-}
-
-void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
-{
- /*DCN303 removes PG registers*/
-}
-
-void dcn303_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on)
-{
- /*DCN303 removes PG registers*/
-}
-
-void dcn303_enable_power_gating_plane(struct dce_hwseq *hws, bool enable)
-{
- /*DCN303 removes PG registers*/
-}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.h
deleted file mode 100644
index 8b69a3b76c11..000000000000
--- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright (C) 2021 Advanced Micro Devices, Inc.
- *
- * Authors: AMD
- */
-
-#ifndef __DC_HWSS_DCN303_H__
-#define __DC_HWSS_DCN303_H__
-
-#include "hw_sequencer_private.h"
-
-void dcn303_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on);
-void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on);
-void dcn303_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on);
-void dcn303_enable_power_gating_plane(struct dce_hwseq *hws, bool enable);
-
-#endif /* __DC_HWSS_DCN303_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.c
index f499f8ab5e47..edb4d68b8187 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.c
@@ -2,10 +2,28 @@
/*
* Copyright (C) 2021 Advanced Micro Devices, Inc.
*
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
* Authors: AMD
*/
-#include "dcn303_hwseq.h"
+#include "dcn303/dcn303_hwseq.h"
#include "dcn30/dcn30_init.h"
#include "dc.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.h b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.h
index 66b1e3604f07..4949981126d7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.h
@@ -2,6 +2,24 @@
/*
* Copyright (C) 2021 Advanced Micro Devices, Inc.
*
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
* Authors: AMD
*/
diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
index adf4989177f7..49cb7fde416a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
@@ -2,6 +2,24 @@
/*
* Copyright (C) 2021 Advanced Micro Devices, Inc.
*
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
* Authors: AMD
*/
@@ -56,6 +74,8 @@
#include "dml/dcn303/dcn303_fpu.h"
+#define DC_LOGGER \
+ dc->ctx->logger
#define DC_LOGGER_INIT(logger)
@@ -79,6 +99,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.dmub_command_table = true,
.exit_idle_opt_for_cursor_updates = true,
.disable_idle_power_optimizations = false,
+ .using_dml2 = false,
};
static const struct dc_panel_config panel_config_defaults = {
@@ -1063,6 +1084,7 @@ static struct resource_funcs dcn303_res_pool_funcs = {
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
.populate_dml_pipes = dcn30_populate_dml_pipes_from_context,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer,
+ .release_pipe = dcn20_release_pipe,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h
index 9c7d79540900..37cf1525820b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h
@@ -2,6 +2,24 @@
/*
* Copyright (C) 2021 Advanced Micro Devices, Inc.
*
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
* Authors: AMD
*/
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile
index ec041e3cda30..96e45c9efb46 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile
@@ -1,5 +1,5 @@
#
-# (c) Copyright 2020 Advanced Micro Devices, Inc. All the rights reserved
+# Copyright 2020 Advanced Micro Devices, Inc. All the rights reserved
#
# All rights reserved. This notice is intended as a precaution against
# inadvertent publication and does not imply publication or any waiver
@@ -10,7 +10,7 @@
#
# Makefile for dcn31.
-DCN31 = dcn31_resource.o dcn31_hubbub.o dcn31_hwseq.o dcn31_init.o dcn31_hubp.o \
+DCN31 = dcn31_resource.o dcn31_hubbub.o dcn31_init.o dcn31_hubp.o \
dcn31_dccg.o dcn31_optc.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o \
dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o \
dcn31_afmt.o dcn31_vpg.o
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h
index e324e9b83136..51f5781325e8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h
@@ -104,7 +104,10 @@ struct dcn31_hpo_dp_link_encoder_registers {
uint32_t RDPCSTX_PHY_CNTL6[5];
};
-#define DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(mask_sh)\
+#define DCN3_1_HPO_DP_LINK_ENC_RDPCSTX_MASK_SH_LIST(mask_sh)\
+ SE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh)
+
+#define DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(mask_sh)\
SE_SF(DP_LINK_ENC0_DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, DPHY_RESET, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, DPHY_ENABLE, mask_sh),\
@@ -126,11 +129,14 @@ struct dcn31_hpo_dp_link_encoder_registers {
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_SQ_PULSE, TP_SQ_PULSE_WIDTH, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_VC0, SAT_STREAM_SOURCE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_VC0, SAT_SLOT_COUNT, mask_sh),\
- SE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_VC_RATE_CNTL0, STREAM_VC_RATE_X, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_VC_RATE_CNTL0, STREAM_VC_RATE_Y, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_UPDATE, SAT_UPDATE, mask_sh)
+#define DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(mask_sh)\
+ DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(mask_sh),\
+ DCN3_1_HPO_DP_LINK_ENC_RDPCSTX_MASK_SH_LIST(mask_sh)\
+
#define DCN3_1_HPO_DP_LINK_ENC_REG_FIELD_LIST(type) \
type DP_LINK_ENC_CLOCK_EN;\
type DPHY_RESET;\
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
index 1f4e0b6261ad..5b5b5e0775fa 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
@@ -109,6 +109,28 @@ static void dcn31_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigne
+ hubbub2->det3_size + hubbub2->compbuf_size_segments <= hubbub2->crb_size_segs);
}
+static void dcn31_wait_for_det_apply(struct hubbub *hubbub, int hubp_inst)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+ switch (hubp_inst) {
+ case 0:
+ REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1000, 30);
+ break;
+ case 1:
+ REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1000, 30);
+ break;
+ case 2:
+ REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1000, 30);
+ break;
+ case 3:
+ REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1000, 30);
+ break;
+ default:
+ break;
+ }
+}
+
static void dcn31_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase)
{
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
@@ -355,7 +377,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
@@ -371,7 +393,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->a.cstate_pstate.cstate_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->a.cstate_pstate.cstate_exit_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
@@ -387,7 +409,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_A calculated =%d\n"
@@ -403,7 +425,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->a.cstate_pstate.cstate_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->a.cstate_pstate.cstate_exit_z8_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_A calculated =%d\n"
@@ -420,7 +442,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"
@@ -436,7 +458,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->b.cstate_pstate.cstate_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->b.cstate_pstate.cstate_exit_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
@@ -452,7 +474,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_B calculated =%d\n"
@@ -468,7 +490,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->b.cstate_pstate.cstate_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->b.cstate_pstate.cstate_exit_z8_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_B calculated =%d\n"
@@ -485,7 +507,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"
@@ -501,7 +523,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->c.cstate_pstate.cstate_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->c.cstate_pstate.cstate_exit_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
@@ -517,7 +539,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_C calculated =%d\n"
@@ -533,7 +555,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->c.cstate_pstate.cstate_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->c.cstate_pstate.cstate_exit_z8_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_C calculated =%d\n"
@@ -550,7 +572,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"
@@ -566,7 +588,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->d.cstate_pstate.cstate_exit_ns;
prog_wm_value = convert_and_clamp(
watermarks->d.cstate_pstate.cstate_exit_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
@@ -582,7 +604,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0,
DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_D calculated =%d\n"
@@ -598,7 +620,7 @@ static bool hubbub31_program_stutter_watermarks(
watermarks->d.cstate_pstate.cstate_exit_z8_ns;
prog_wm_value = convert_and_clamp(
watermarks->d.cstate_pstate.cstate_exit_z8_ns,
- refclk_mhz, 0xffff);
+ refclk_mhz, 0xfffff);
REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0,
DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, prog_wm_value);
DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_D calculated =%d\n"
@@ -1041,6 +1063,7 @@ static const struct hubbub_funcs hubbub31_funcs = {
.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
.verify_allow_pstate_change_high = hubbub31_verify_allow_pstate_change_high,
.program_det_size = dcn31_program_det_size,
+ .wait_for_det_apply = dcn31_wait_for_det_apply,
.program_compbuf_size = dcn31_program_compbuf_size,
.init_crb = dcn31_init_crb,
.hubbub_read_state = hubbub2_read_state,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c
index 39a57bcd7866..8394e8c06919 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c
@@ -62,6 +62,12 @@ static void hubp31_program_extended_blank(struct hubp *hubp,
REG_UPDATE(BLANK_OFFSET_1, MIN_DST_Y_NEXT_START, min_dst_y_next_start_optimized);
}
+void hubp31_program_extended_blank_value(
+ struct hubp *hubp, unsigned int min_dst_y_next_start_optimized)
+{
+ hubp31_program_extended_blank(hubp, min_dst_y_next_start_optimized);
+}
+
static struct hubp_funcs dcn31_hubp_funcs = {
.hubp_enable_tripleBuffer = hubp2_enable_triplebuffer,
.hubp_is_triplebuffer_enabled = hubp2_is_triplebuffer_enabled,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.h
index c31a7b8f81ee..d688db79b750 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.h
@@ -243,4 +243,7 @@ void hubp31_soft_reset(struct hubp *hubp, bool reset);
void hubp31_set_unbounded_requesting(struct hubp *hubp, bool enable);
+void hubp31_program_extended_blank_value(
+ struct hubp *hubp, unsigned int min_dst_y_next_start_optimized);
+
#endif /* __DC_HUBP_DCN31_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
index 1d7bc1e39afe..669f524bd064 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
@@ -23,8 +23,8 @@
*
*/
-#include "dce110/dce110_hw_sequencer.h"
-#include "dcn10/dcn10_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
+#include "dcn10/dcn10_hwseq.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn21/dcn21_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
@@ -34,7 +34,7 @@
#include "dcn31_init.h"
static const struct hw_sequencer_funcs dcn31_funcs = {
- .program_gamut_remap = dcn10_program_gamut_remap,
+ .program_gamut_remap = dcn30_program_gamut_remap,
.init_hw = dcn31_init_hw,
.power_down_on_boot = dcn10_power_down_on_boot,
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
index 82de4fe2637f..79416cfb22f0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
@@ -48,7 +48,7 @@
#include "dcn31/dcn31_optc.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
#include "dcn30/dcn30_opp.h"
#include "dcn20/dcn20_dsc.h"
#include "dcn30/dcn30_vpg.h"
@@ -104,6 +104,8 @@
#include "link_enc_cfg.h"
+#define DC_LOGGER \
+ dc->ctx->logger
#define DC_LOGGER_INIT(logger)
enum dcn31_clk_src_array_id {
@@ -891,6 +893,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.enable_legacy_fast_update = true,
.enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/
.dml_hostvm_override = DML_HOSTVM_OVERRIDE_FALSE,
+ .using_dml2 = false,
};
static const struct dc_panel_config panel_config_defaults = {
@@ -1824,6 +1827,7 @@ static struct resource_funcs dcn31_res_pool_funcs = {
.update_soc_for_wm_a = dcn31_update_soc_for_wm_a,
.populate_dml_pipes = dcn31_populate_dml_pipes_from_context,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer,
+ .release_pipe = dcn20_release_pipe,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/Makefile b/drivers/gpu/drm/amd/display/dc/dcn314/Makefile
index 702c28c2560e..72456debb99f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/Makefile
@@ -10,7 +10,7 @@
#
# Makefile for dcn314.
-DCN314 = dcn314_resource.o dcn314_hwseq.o dcn314_init.o \
+DCN314 = dcn314_resource.o dcn314_init.o \
dcn314_dio_stream_encoder.o dcn314_dccg.o dcn314_optc.o
AMD_DAL_DCN314 = $(addprefix $(AMDDALPATH)/dc/dcn314/,$(DCN314))
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
index ad3f019a784f..17a1174b8d80 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
@@ -245,7 +245,7 @@ static void dccg314_set_dtbclk_dto(
}
}
-static void dccg314_set_dpstreamclk(
+void dccg314_set_dpstreamclk(
struct dccg *dccg,
enum streamclk_source src,
int otg_inst,
@@ -375,6 +375,7 @@ static const struct dccg_funcs dccg314_funcs = {
.set_pixel_rate_div = dccg314_set_pixel_rate_div,
.trigger_dio_fifo_resync = dccg314_trigger_dio_fifo_resync,
.set_valid_pixel_rate = dccg314_set_valid_pixel_rate,
+ .set_dtbclk_p_src = dccg314_set_dtbclk_p_src
};
struct dccg *dccg314_create(
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h
index 8e07d3151f91..60ea1d248deb 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h
@@ -203,4 +203,10 @@ struct dccg *dccg314_create(
const struct dccg_shift *dccg_shift,
const struct dccg_mask *dccg_mask);
+void dccg314_set_dpstreamclk(
+ struct dccg *dccg,
+ enum streamclk_source src,
+ int otg_inst,
+ int dp_hpo_inst);
+
#endif //__DCN314_DCCG_H__
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c
index 467509a65fa7..5b343f745cf3 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c
@@ -49,7 +49,7 @@
#define CTX \
enc1->base.ctx
-static void enc314_reset_fifo(struct stream_encoder *enc, bool reset)
+void enc314_reset_fifo(struct stream_encoder *enc, bool reset)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
uint32_t reset_val = reset ? 1 : 0;
@@ -64,7 +64,7 @@ static void enc314_reset_fifo(struct stream_encoder *enc, bool reset)
udelay(10);
}
-static void enc314_enable_fifo(struct stream_encoder *enc)
+void enc314_enable_fifo(struct stream_encoder *enc)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
@@ -76,14 +76,14 @@ static void enc314_enable_fifo(struct stream_encoder *enc)
REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 1);
}
-static void enc314_disable_fifo(struct stream_encoder *enc)
+void enc314_disable_fifo(struct stream_encoder *enc)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 0);
}
-static void enc314_dp_set_odm_combine(
+void enc314_dp_set_odm_combine(
struct stream_encoder *enc,
bool odm_combine)
{
@@ -93,7 +93,7 @@ static void enc314_dp_set_odm_combine(
}
/* setup stream encoder in dvi mode */
-static void enc314_stream_encoder_dvi_set_stream_attribute(
+void enc314_stream_encoder_dvi_set_stream_attribute(
struct stream_encoder *enc,
struct dc_crtc_timing *crtc_timing,
bool is_dual_link)
@@ -133,7 +133,7 @@ static void enc314_stream_encoder_dvi_set_stream_attribute(
}
/* setup stream encoder in hdmi mode */
-static void enc314_stream_encoder_hdmi_set_stream_attribute(
+void enc314_stream_encoder_hdmi_set_stream_attribute(
struct stream_encoder *enc,
struct dc_crtc_timing *crtc_timing,
int actual_pix_clk_khz,
@@ -274,7 +274,7 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
return two_pix;
}
-static void enc314_stream_encoder_dp_blank(
+void enc314_stream_encoder_dp_blank(
struct dc_link *link,
struct stream_encoder *enc)
{
@@ -285,7 +285,7 @@ static void enc314_stream_encoder_dp_blank(
enc314_disable_fifo(enc);
}
-static void enc314_stream_encoder_dp_unblank(
+void enc314_stream_encoder_dp_unblank(
struct dc_link *link,
struct stream_encoder *enc,
const struct encoder_unblank_param *param)
@@ -380,7 +380,7 @@ static void enc314_stream_encoder_dp_unblank(
* sc_bytes_per_pixel: DP_DSC_BYTES_PER_PIXEL removed in DCN32
* dsc_slice_width: DP_DSC_SLICE_WIDTH removed in DCN32
*/
-static void enc314_dp_set_dsc_config(struct stream_encoder *enc,
+void enc314_dp_set_dsc_config(struct stream_encoder *enc,
enum optc_dsc_mode dsc_mode,
uint32_t dsc_bytes_per_pixel,
uint32_t dsc_slice_width)
@@ -393,7 +393,7 @@ static void enc314_dp_set_dsc_config(struct stream_encoder *enc,
/* this function read dsc related register fields to be logged later in dcn10_log_hw_state
* into a dcn_dsc_state struct.
*/
-static void enc314_read_state(struct stream_encoder *enc, struct enc_state *s)
+void enc314_read_state(struct stream_encoder *enc, struct enc_state *s)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
@@ -410,7 +410,7 @@ static void enc314_read_state(struct stream_encoder *enc, struct enc_state *s)
}
}
-static void enc314_set_dig_input_mode(struct stream_encoder *enc, unsigned int pix_per_container)
+void enc314_set_dig_input_mode(struct stream_encoder *enc, unsigned int pix_per_container)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.h
index ed0772387903..86548be591be 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.h
@@ -312,4 +312,44 @@ void enc3_dp_set_dsc_pps_info_packet(
uint8_t *dsc_packed_pps,
bool immediate_update);
+void enc314_stream_encoder_dvi_set_stream_attribute(
+ struct stream_encoder *enc,
+ struct dc_crtc_timing *crtc_timing,
+ bool is_dual_link);
+
+void enc314_stream_encoder_hdmi_set_stream_attribute(
+ struct stream_encoder *enc,
+ struct dc_crtc_timing *crtc_timing,
+ int actual_pix_clk_khz,
+ bool enable_audio);
+
+void enc314_stream_encoder_dp_blank(
+ struct dc_link *link,
+ struct stream_encoder *enc);
+
+void enc314_stream_encoder_dp_unblank(
+ struct dc_link *link,
+ struct stream_encoder *enc,
+ const struct encoder_unblank_param *param);
+
+void enc314_reset_fifo(struct stream_encoder *enc, bool reset);
+
+void enc314_enable_fifo(struct stream_encoder *enc);
+
+void enc314_disable_fifo(struct stream_encoder *enc);
+
+void enc314_set_dig_input_mode(struct stream_encoder *enc, unsigned int pix_per_container);
+
+void enc314_read_state(struct stream_encoder *enc, struct enc_state *s);
+
+void enc314_dp_set_odm_combine(
+ struct stream_encoder *enc,
+ bool odm_combine);
+
+void enc314_dp_set_dsc_config(
+ struct stream_encoder *enc,
+ enum optc_dsc_mode dsc_mode,
+ uint32_t dsc_bytes_per_pixel,
+ uint32_t dsc_slice_width);
+
#endif /* __DC_DIO_STREAM_ENCODER_DCN314_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
index 4ef85c3a0688..ccb7e317e86a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
@@ -24,8 +24,8 @@
*
*/
-#include "dce110/dce110_hw_sequencer.h"
-#include "dcn10/dcn10_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
+#include "dcn10/dcn10_hwseq.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn21/dcn21_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
@@ -36,7 +36,7 @@
#include "dcn314_init.h"
static const struct hw_sequencer_funcs dcn314_funcs = {
- .program_gamut_remap = dcn10_program_gamut_remap,
+ .program_gamut_remap = dcn30_program_gamut_remap,
.init_hw = dcn31_init_hw,
.power_down_on_boot = dcn10_power_down_on_boot,
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
index 004beed9bd44..c97391edb5ff 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
@@ -50,7 +50,7 @@
#include "dcn314/dcn314_optc.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
#include "dcn30/dcn30_opp.h"
#include "dcn20/dcn20_dsc.h"
#include "dcn30/dcn30_vpg.h"
@@ -118,6 +118,8 @@
#define regBIF_BX2_BIOS_SCRATCH_6 0x003e
#define regBIF_BX2_BIOS_SCRATCH_6_BASE_IDX 1
+#define DC_LOGGER \
+ dc->ctx->logger
#define DC_LOGGER_INIT(logger)
enum dcn31_clk_src_array_id {
@@ -869,7 +871,7 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_z10 = false,
.enable_z9_disable_interface = true,
- .minimum_z8_residency_time = 2000,
+ .minimum_z8_residency_time = 2100,
.psr_skip_crtc_disable = true,
.replay_skip_crtc_disabled = true,
.disable_dmcu = true,
@@ -914,7 +916,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.hdmistream = true,
.hdmichar = true,
.dpstream = true,
- .symclk32_se = true,
+ .symclk32_se = false,
.symclk32_le = true,
.symclk_fe = true,
.physymclk = true,
@@ -922,7 +924,8 @@ static const struct dc_debug_options debug_defaults_drv = {
}
},
- .seamless_boot_odm_combine = true
+ .seamless_boot_odm_combine = true,
+ .using_dml2 = false,
};
static const struct dc_debug_options debug_defaults_diags = {
@@ -1796,6 +1799,7 @@ static struct resource_funcs dcn314_res_pool_funcs = {
.update_soc_for_wm_a = dcn31_update_soc_for_wm_a,
.populate_dml_pipes = dcn314_populate_dml_pipes_from_context,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer,
+ .release_pipe = dcn20_release_pipe,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
@@ -1911,6 +1915,8 @@ static bool dcn314_resource_construct(
dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
dc->caps.color.mpc.ocsc = 1;
+ dc->caps.max_disp_clock_khz_at_vmin = 650000;
+
/* Use pipe context based otg sync logic */
dc->config.use_pipe_ctx_sync_logic = true;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
index 127487ea3d7d..cb8024eee8e4 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
@@ -47,7 +47,7 @@
#include "dcn31/dcn31_optc.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
#include "dcn30/dcn30_opp.h"
#include "dcn20/dcn20_dsc.h"
#include "dcn30/dcn30_vpg.h"
@@ -137,8 +137,8 @@
#define DCN3_15_MAX_DET_SIZE 384
#define DCN3_15_CRB_SEGMENT_SIZE_KB 64
#define DCN3_15_MAX_DET_SEGS (DCN3_15_MAX_DET_SIZE / DCN3_15_CRB_SEGMENT_SIZE_KB)
-/* Minimum 2 extra segments need to be in compbuf and claimable to guarantee seamless mpo transitions */
-#define MIN_RESERVED_DET_SEGS 2
+/* Minimum 3 extra segments need to be in compbuf and claimable to guarantee seamless mpo transitions */
+#define MIN_RESERVED_DET_SEGS 3
enum dcn31_clk_src_array_id {
DCN31_CLK_SRC_PLL0,
@@ -889,6 +889,7 @@ static const struct dc_debug_options debug_defaults_drv = {
},
.enable_legacy_fast_update = true,
.psr_power_use_phy_fsm = 0,
+ .using_dml2 = false,
};
static const struct dc_panel_config panel_config_defaults = {
@@ -1819,6 +1820,7 @@ static struct resource_funcs dcn315_res_pool_funcs = {
.update_soc_for_wm_a = dcn315_update_soc_for_wm_a,
.populate_dml_pipes = dcn315_populate_dml_pipes_from_context,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer,
+ .release_pipe = dcn20_release_pipe,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c
index 5fe2c61527df..b9753d4606f8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c
@@ -47,7 +47,7 @@
#include "dcn31/dcn31_optc.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
#include "dcn30/dcn30_opp.h"
#include "dcn20/dcn20_dsc.h"
#include "dcn30/dcn30_vpg.h"
@@ -885,6 +885,7 @@ static const struct dc_debug_options debug_defaults_drv = {
}
},
.enable_legacy_fast_update = true,
+ .using_dml2 = false,
};
static const struct dc_panel_config panel_config_defaults = {
@@ -1706,6 +1707,7 @@ static struct resource_funcs dcn316_res_pool_funcs = {
.update_soc_for_wm_a = dcn31_update_soc_for_wm_a,
.populate_dml_pipes = dcn316_populate_dml_pipes_from_context,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer,
+ .release_pipe = dcn20_release_pipe,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/Makefile b/drivers/gpu/drm/amd/display/dc/dcn32/Makefile
index e943b643ab6b..8bb251307247 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/Makefile
@@ -10,7 +10,7 @@
#
# Makefile for dcn32.
-DCN32 = dcn32_resource.o dcn32_hubbub.o dcn32_hwseq.o dcn32_init.o \
+DCN32 = dcn32_resource.o dcn32_hubbub.o dcn32_init.o dcn32_dccg.o \
dcn32_dccg.o dcn32_optc.o dcn32_mmhubbub.o dcn32_hubp.o dcn32_dpp.o \
dcn32_dio_stream_encoder.o dcn32_dio_link_encoder.o dcn32_hpo_dp_link_encoder.o \
dcn32_resource_helpers.o dcn32_mpc.o
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
index 921f58c0c729..036d05468d76 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
@@ -345,6 +345,7 @@ static const struct dccg_funcs dccg32_funcs = {
.otg_drop_pixel = dccg32_otg_drop_pixel,
.set_pixel_rate_div = dccg32_set_pixel_rate_div,
.trigger_dio_fifo_resync = dccg32_trigger_dio_fifo_resync,
+ .set_dtbclk_p_src = dccg32_set_dtbclk_p_src,
};
struct dccg *dccg32_create(
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c
index 8bfef6d095b2..88dfc907553d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c
@@ -945,6 +945,17 @@ void hubbub32_force_wm_propagate_to_pipes(struct hubbub *hubbub)
DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
}
+void hubbub32_get_mall_en(struct hubbub *hubbub, unsigned int *mall_in_use)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ uint32_t prefetch_complete, mall_en;
+
+ REG_GET_2(DCHUBBUB_ARB_MALL_CNTL, MALL_IN_USE, &mall_en,
+ MALL_PREFETCH_COMPLETE, &prefetch_complete);
+
+ *mall_in_use = prefetch_complete && mall_en;
+}
+
void hubbub32_init(struct hubbub *hubbub)
{
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
@@ -995,7 +1006,8 @@ static const struct hubbub_funcs hubbub32_funcs = {
.init_crb = dcn32_init_crb,
.hubbub_read_state = hubbub2_read_state,
.force_usr_retraining_allow = hubbub32_force_usr_retraining_allow,
- .set_request_limit = hubbub32_set_request_limit
+ .set_request_limit = hubbub32_set_request_limit,
+ .get_mall_en = hubbub32_get_mall_en,
};
void hubbub32_construct(struct dcn20_hubbub *hubbub2,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h
index ad33427192c6..f073839a4b6d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h
@@ -110,7 +110,9 @@
HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DCFCLK_R_DCHUBBUB_GATE_DIS, mask_sh),\
HUBBUB_SF(DCHUBBUB_SDPIF_CFG0, SDPIF_PORT_CONTROL, mask_sh),\
HUBBUB_SF(DCHUBBUB_SDPIF_CFG1, SDPIF_MAX_NUM_OUTSTANDING, mask_sh),\
- HUBBUB_SF(DCHUBBUB_MEM_PWR_MODE_CTRL, DET_MEM_PWR_LS_MODE, mask_sh)
+ HUBBUB_SF(DCHUBBUB_MEM_PWR_MODE_CTRL, DET_MEM_PWR_LS_MODE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_MALL_CNTL, MALL_PREFETCH_COMPLETE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_MALL_CNTL, MALL_IN_USE, mask_sh)
@@ -157,4 +159,6 @@ void hubbub32_construct(struct dcn20_hubbub *hubbub2,
void hubbub32_set_request_limit(struct hubbub *hubbub, int umc_count, int words_per_umc);
+void hubbub32_get_mall_en(struct hubbub *hubbub, unsigned int *mall_in_use);
+
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
index c7417147dff1..427cfc8c24a4 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
@@ -23,17 +23,17 @@
*
*/
-#include "dce110/dce110_hw_sequencer.h"
-#include "dcn10/dcn10_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
+#include "dcn10/dcn10_hwseq.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn21/dcn21_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
#include "dcn31/dcn31_hwseq.h"
-#include "dcn32_hwseq.h"
+#include "dcn32/dcn32_hwseq.h"
#include "dcn32_init.h"
static const struct hw_sequencer_funcs dcn32_funcs = {
- .program_gamut_remap = dcn10_program_gamut_remap,
+ .program_gamut_remap = dcn30_program_gamut_remap,
.init_hw = dcn32_init_hw,
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
.apply_ctx_for_surface = NULL,
@@ -60,7 +60,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
.pipe_control_lock = dcn20_pipe_control_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.cursor_lock = dcn10_cursor_lock,
- .prepare_bandwidth = dcn30_prepare_bandwidth,
+ .prepare_bandwidth = dcn32_prepare_bandwidth,
.optimize_bandwidth = dcn20_optimize_bandwidth,
.update_bandwidth = dcn20_update_bandwidth,
.set_drr = dcn10_set_drr,
@@ -115,6 +115,8 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
.update_phantom_vp_position = dcn32_update_phantom_vp_position,
.update_dsc_pg = dcn32_update_dsc_pg,
.apply_update_flags_for_phantom = dcn32_apply_update_flags_for_phantom,
+ .blank_phantom = dcn32_blank_phantom,
+ .is_pipe_topology_transition_seamless = dcn32_is_pipe_topology_transition_seamless,
};
static const struct hwseq_private_funcs dcn32_private_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h
index e460cf8d9041..ef15b4f1f6b9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h
@@ -43,8 +43,6 @@
SRI2(MCIF_WB_BUF_4_STATUS2, MCIF_WB, inst),\
SRI2(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst),\
SRI2(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst),\
- SRI2(MCIF_WB_TEST_DEBUG_INDEX, MCIF_WB, inst),\
- SRI2(MCIF_WB_TEST_DEBUG_DATA, MCIF_WB, inst),\
SRI2(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst),\
SRI2(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst),\
SRI2(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst),\
@@ -157,8 +155,6 @@
SF(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, mask_sh),\
SF(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, mask_sh),\
SF(MCIF_WB_SCLK_CHANGE, WM_CHANGE_ACK_FORCE_ON, mask_sh),\
- SF(MCIF_WB_TEST_DEBUG_INDEX, MCIF_WB_TEST_DEBUG_INDEX, mask_sh),\
- SF(MCIF_WB_TEST_DEBUG_DATA, MCIF_WB_TEST_DEBUG_DATA, mask_sh),\
SF(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, mask_sh),\
SF(MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, mask_sh),\
SF(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, mask_sh),\
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
index 1d052f08aff5..994b21ed272f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
@@ -237,16 +237,19 @@ void mpc32_program_post1dlut_pwl(
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].red_reg);
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_red);
} else {
+ REG_SET(MPCC_MCM_1DLUT_LUT_INDEX[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_INDEX, 0);
REG_UPDATE(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 4);
for (i = 0 ; i < num; i++)
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].red_reg);
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_red);
+ REG_SET(MPCC_MCM_1DLUT_LUT_INDEX[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_INDEX, 0);
REG_UPDATE(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 2);
for (i = 0 ; i < num; i++)
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].green_reg);
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_green);
+ REG_SET(MPCC_MCM_1DLUT_LUT_INDEX[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_INDEX, 0);
REG_UPDATE(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 1);
for (i = 0 ; i < num; i++)
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].blue_reg);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.h
index 9ac584fa89ce..9622518826c9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.h
@@ -232,7 +232,6 @@
SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT_CURRENT, mask_sh),\
SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_WRITE_COLOR_MASK, mask_sh),\
SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_COLOR_SEL, mask_sh),\
- SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_DBG, mask_sh),\
SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_HOST_SEL, mask_sh),\
SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_CONFIG_MODE, mask_sh),\
SF(MPCC_OGAM0_MPCC_OGAM_LUT_DATA, MPCC_OGAM_LUT_DATA, mask_sh),\
@@ -276,7 +275,6 @@
SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_DATA, MPCC_MCM_1DLUT_LUT_DATA, mask_sh),\
SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, mask_sh),\
SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_READ_COLOR_SEL, mask_sh),\
- SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_READ_DBG, mask_sh),\
SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_HOST_SEL, mask_sh),\
SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_CONFIG_MODE, mask_sh),\
SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_B, mask_sh),\
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
index 8abb94f60078..a2c4db2cebdd 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
@@ -98,6 +98,30 @@ static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, i
optc1->opp_count = opp_cnt;
}
+void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combine_segments)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(tg);
+ int segments;
+
+ REG_GET(OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, &segments);
+
+ switch (segments) {
+ case 0:
+ *odm_combine_segments = 1;
+ break;
+ case 1:
+ *odm_combine_segments = 2;
+ break;
+ case 3:
+ *odm_combine_segments = 4;
+ break;
+ /* 2 is reserved */
+ case 2:
+ default:
+ *odm_combine_segments = -1;
+ }
+}
+
void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode)
{
struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -177,7 +201,7 @@ static void optc32_disable_phantom_otg(struct timing_generator *optc)
REG_UPDATE(OTG_CONTROL, OTG_MASTER_EN, 0);
}
-static void optc32_set_odm_bypass(struct timing_generator *optc,
+void optc32_set_odm_bypass(struct timing_generator *optc,
const struct dc_crtc_timing *dc_crtc_timing)
{
struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -303,6 +327,7 @@ static struct timing_generator_funcs dcn32_tg_funcs = {
.set_dwb_source = NULL,
.set_odm_bypass = optc32_set_odm_bypass,
.set_odm_combine = optc32_set_odm_combine,
+ .get_odm_combine_segments = optc32_get_odm_combine_segments,
.set_h_timing_div_manual_mode = optc32_set_h_timing_div_manual_mode,
.get_optc_source = optc2_get_optc_source,
.set_out_mux = optc3_set_out_mux,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h
index abf0121a1006..8ce3b178cab0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h
@@ -180,5 +180,8 @@
void dcn32_timing_generator_init(struct optc *optc1);
void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode);
+void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combine_segments);
+void optc32_set_odm_bypass(struct timing_generator *optc,
+ const struct dc_crtc_timing *dc_crtc_timing);
#endif /* __DC_OPTC_DCN32_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
index f9d601c8c721..89b072447dba 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
@@ -47,7 +47,7 @@
#include "dcn32/dcn32_optc.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
#include "dcn30/dcn30_opp.h"
#include "dcn20/dcn20_dsc.h"
#include "dcn30/dcn30_vpg.h"
@@ -89,6 +89,8 @@
#include "dcn20/dcn20_vmid.h"
#include "dml/dcn32/dcn32_fpu.h"
+#include "dml2/dml2_wrapper.h"
+
#define DC_LOGGER_INIT(logger)
enum dcn32_clk_src_array_id {
@@ -714,6 +716,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.use_max_lb = true,
.force_disable_subvp = false,
.exit_idle_opt_for_cursor_updates = true,
+ .using_dml2 = false,
.enable_single_display_2to1_odm_policy = true,
/* Must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/
@@ -1805,9 +1808,7 @@ void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context,
}
}
-bool dcn32_validate_bandwidth(struct dc *dc,
- struct dc_state *context,
- bool fast_validate)
+static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_validate)
{
bool out = false;
@@ -1885,6 +1886,19 @@ validate_out:
return out;
}
+bool dcn32_validate_bandwidth(struct dc *dc,
+ struct dc_state *context,
+ bool fast_validate)
+{
+ bool out = false;
+
+ if (dc->debug.using_dml2)
+ out = dml2_validate(dc, context, fast_validate);
+ else
+ out = dml1_validate(dc, context, fast_validate);
+ return out;
+}
+
int dcn32_populate_dml_pipes_from_context(
struct dc *dc, struct dc_state *context,
display_e2e_pipe_params_st *pipes,
@@ -1895,38 +1909,9 @@ int dcn32_populate_dml_pipes_from_context(
struct pipe_ctx *pipe = NULL;
bool subvp_in_use = false;
struct dc_crtc_timing *timing;
- bool vsr_odm_support = false;
dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
- /* Determine whether we will apply ODM 2to1 policy:
- * Applies to single display and where the number of planes is less than 3.
- * For 3 plane case ( 2 MPO planes ), we will not set the policy for the MPO pipes.
- *
- * Apply pipe split policy first so we can predict the pipe split correctly
- * (dcn32_predict_pipe_split).
- */
- for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
- if (!res_ctx->pipe_ctx[i].stream)
- continue;
- pipe = &res_ctx->pipe_ctx[i];
- timing = &pipe->stream->timing;
-
- pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
- vsr_odm_support = (res_ctx->pipe_ctx[i].stream->src.width >= 5120 &&
- res_ctx->pipe_ctx[i].stream->src.width > res_ctx->pipe_ctx[i].stream->dst.width);
- if (context->stream_count == 1 &&
- context->stream_status[0].plane_count == 1 &&
- !dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) &&
- is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) &&
- pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ &&
- dc->debug.enable_single_display_2to1_odm_policy &&
- !vsr_odm_support) { //excluding 2to1 ODM combine on >= 5k vsr
- pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
- }
- pipe_cnt++;
- }
-
for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
if (!res_ctx->pipe_ctx[i].stream)
@@ -1939,6 +1924,7 @@ int dcn32_populate_dml_pipes_from_context(
dcn32_zero_pipe_dcc_fraction(pipes, pipe_cnt);
DC_FP_END();
pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch;
+ pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet
pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_19;
@@ -1985,9 +1971,6 @@ int dcn32_populate_dml_pipes_from_context(
}
}
- DC_FP_START();
- dcn32_predict_pipe_split(context, &pipes[pipe_cnt]);
- DC_FP_END();
pipe_cnt++;
}
@@ -2010,7 +1993,8 @@ int dcn32_populate_dml_pipes_from_context(
}
static struct dc_cap_funcs cap_funcs = {
- .get_dcc_compression_cap = dcn20_get_dcc_compression_cap
+ .get_dcc_compression_cap = dcn20_get_dcc_compression_cap,
+ .get_subvp_en = dcn32_subvp_in_use,
};
void dcn32_calculate_wm_and_dlg(struct dc *dc, struct dc_state *context,
@@ -2039,6 +2023,8 @@ static struct resource_funcs dcn32_res_pool_funcs = {
.calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg,
.populate_dml_pipes = dcn32_populate_dml_pipes_from_context,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe,
+ .acquire_free_pipe_as_secondary_opp_head = dcn32_acquire_free_pipe_as_secondary_opp_head,
+ .release_pipe = dcn20_release_pipe,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
@@ -2451,6 +2437,53 @@ static bool dcn32_resource_construct(
pool->base.oem_device = NULL;
}
+ dc->dml2_options.dcn_pipe_count = pool->base.pipe_count;
+ dc->dml2_options.use_native_pstate_optimization = false;
+ dc->dml2_options.use_native_soc_bb_construction = true;
+ dc->dml2_options.minimize_dispclk_using_odm = true;
+
+ dc->dml2_options.callbacks.dc = dc;
+ dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params;
+ dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch;
+ dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy;
+ dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count;
+ dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count;
+ dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index;
+ dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index;
+ dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head;
+
+ dc->dml2_options.svp_pstate.callbacks.dc = dc;
+ dc->dml2_options.svp_pstate.callbacks.add_plane_to_context = &dc_add_plane_to_context;
+ dc->dml2_options.svp_pstate.callbacks.add_stream_to_ctx = &dc_add_stream_to_ctx;
+ dc->dml2_options.svp_pstate.callbacks.build_scaling_params = &resource_build_scaling_params;
+ dc->dml2_options.svp_pstate.callbacks.create_plane = &dc_create_plane_state;
+ dc->dml2_options.svp_pstate.callbacks.remove_plane_from_context = &dc_remove_plane_from_context;
+ dc->dml2_options.svp_pstate.callbacks.remove_stream_from_ctx = &dc_remove_stream_from_ctx;
+ dc->dml2_options.svp_pstate.callbacks.create_stream_for_sink = &dc_create_stream_for_sink;
+ dc->dml2_options.svp_pstate.callbacks.plane_state_release = &dc_plane_state_release;
+ dc->dml2_options.svp_pstate.callbacks.stream_release = &dc_stream_release;
+ dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc;
+
+ dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us;
+ dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us;
+ dc->dml2_options.svp_pstate.subvp_pstate_allow_width_us = dc->caps.subvp_pstate_allow_width_us;
+ dc->dml2_options.svp_pstate.subvp_swath_height_margin_lines = dc->caps.subvp_swath_height_margin_lines;
+
+ dc->dml2_options.svp_pstate.force_disable_subvp = dc->debug.force_disable_subvp;
+ dc->dml2_options.svp_pstate.force_enable_subvp = dc->debug.force_subvp_mclk_switch;
+
+ dc->dml2_options.mall_cfg.cache_line_size_bytes = dc->caps.cache_line_size;
+ dc->dml2_options.mall_cfg.cache_num_ways = dc->caps.cache_num_ways;
+ dc->dml2_options.mall_cfg.max_cab_allocation_bytes = dc->caps.max_cab_allocation_bytes;
+ dc->dml2_options.mall_cfg.mblk_height_4bpe_pixels = DCN3_2_MBLK_HEIGHT_4BPE;
+ dc->dml2_options.mall_cfg.mblk_height_8bpe_pixels = DCN3_2_MBLK_HEIGHT_8BPE;
+ dc->dml2_options.mall_cfg.mblk_size_bytes = DCN3_2_MALL_MBLK_SIZE_BYTES;
+ dc->dml2_options.mall_cfg.mblk_width_pixels = DCN3_2_MBLK_WIDTH;
+
+ dc->dml2_options.max_segments_per_hubp = 18;
+ dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;
+ dc->dml2_options.map_dc_pipes_with_callbacks = true;
+
if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev) && (dc->config.sdpif_request_limit_words_per_umc == 0))
dc->config.sdpif_request_limit_words_per_umc = 16;
@@ -2669,6 +2702,33 @@ static struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
return idle_pipe;
}
+static int find_optimal_free_pipe_as_secondary_opp_head(
+ const struct resource_context *cur_res_ctx,
+ struct resource_context *new_res_ctx,
+ const struct resource_pool *pool,
+ const struct pipe_ctx *new_otg_master)
+{
+ const struct pipe_ctx *cur_otg_master;
+ int free_pipe_idx;
+
+ cur_otg_master = &cur_res_ctx->pipe_ctx[new_otg_master->pipe_idx];
+ free_pipe_idx = resource_find_free_pipe_used_as_sec_opp_head_by_cur_otg_master(
+ cur_res_ctx, new_res_ctx, cur_otg_master);
+
+ /* Up until here if we have not found a free secondary pipe, we will
+ * need to wait for at least one frame to complete the transition
+ * sequence.
+ */
+ if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)
+ free_pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx(
+ cur_res_ctx, new_res_ctx, pool);
+
+ if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)
+ free_pipe_idx = resource_find_any_free_pipe(new_res_ctx, pool);
+
+ return free_pipe_idx;
+}
+
struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe(
const struct dc_state *cur_ctx,
struct dc_state *new_ctx,
@@ -2706,6 +2766,49 @@ struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe(
return free_pipe;
}
+struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_opp_head(
+ const struct dc_state *cur_ctx,
+ struct dc_state *new_ctx,
+ const struct resource_pool *pool,
+ const struct pipe_ctx *otg_master)
+{
+ int free_pipe_idx = find_optimal_free_pipe_as_secondary_opp_head(
+ &cur_ctx->res_ctx, &new_ctx->res_ctx,
+ pool, otg_master);
+ struct pipe_ctx *free_pipe;
+
+ if (free_pipe_idx >= 0) {
+ free_pipe = &new_ctx->res_ctx.pipe_ctx[free_pipe_idx];
+ free_pipe->pipe_idx = free_pipe_idx;
+ free_pipe->stream = otg_master->stream;
+ free_pipe->stream_res.tg = otg_master->stream_res.tg;
+ free_pipe->stream_res.dsc = NULL;
+ free_pipe->stream_res.opp = pool->opps[free_pipe_idx];
+ free_pipe->plane_res.mi = pool->mis[free_pipe_idx];
+ free_pipe->plane_res.hubp = pool->hubps[free_pipe_idx];
+ free_pipe->plane_res.ipp = pool->ipps[free_pipe_idx];
+ free_pipe->plane_res.xfm = pool->transforms[free_pipe_idx];
+ free_pipe->plane_res.dpp = pool->dpps[free_pipe_idx];
+ free_pipe->plane_res.mpcc_inst = pool->dpps[free_pipe_idx]->inst;
+ if (free_pipe->stream->timing.flags.DSC == 1) {
+ dcn20_acquire_dsc(free_pipe->stream->ctx->dc,
+ &new_ctx->res_ctx,
+ &free_pipe->stream_res.dsc,
+ free_pipe_idx);
+ ASSERT(free_pipe->stream_res.dsc);
+ if (free_pipe->stream_res.dsc == NULL) {
+ memset(free_pipe, 0, sizeof(*free_pipe));
+ free_pipe = NULL;
+ }
+ }
+ } else {
+ ASSERT(otg_master);
+ free_pipe = NULL;
+ }
+
+ return free_pipe;
+}
+
unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans)
{
/*
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
index 103a2b54d025..b931008114c9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
@@ -38,7 +38,7 @@
#define DCN3_2_MBLK_HEIGHT_4BPE 128
#define DCN3_2_MBLK_HEIGHT_8BPE 64
#define DCN3_2_DCFCLK_DS_INIT_KHZ 10000 // Choose 10Mhz for init DCFCLK DS freq
-#define SUBVP_HIGH_REFRESH_LIST_LEN 3
+#define SUBVP_HIGH_REFRESH_LIST_LEN 4
#define DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ 1800
#define DCN3_2_VMIN_DISPCLK_HZ 717000000
@@ -142,6 +142,16 @@ struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe(
const struct resource_pool *pool,
const struct pipe_ctx *opp_head_pipe);
+struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_opp_head(
+ const struct dc_state *cur_ctx,
+ struct dc_state *new_ctx,
+ const struct resource_pool *pool,
+ const struct pipe_ctx *otg_master);
+
+void dcn32_release_pipe(struct dc_state *context,
+ struct pipe_ctx *pipe,
+ const struct resource_pool *pool);
+
void dcn32_determine_det_override(struct dc *dc,
struct dc_state *context,
display_e2e_pipe_params_st *pipes);
@@ -177,7 +187,6 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
/* CLK SRC */
#define CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) \
- ( \
SRI_ARR_ALPHABET(PIXCLK_RESYNC_CNTL, PHYPLL, index, pllid), \
SRII_ARR_2(PHASE, DP_DTO, 0, index), \
SRII_ARR_2(PHASE, DP_DTO, 1, index), \
@@ -190,12 +199,10 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 0, index), \
SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 1, index), \
SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 2, index), \
- SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 3, index) \
- )
+ SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 3, index)
/* ABM */
#define ABM_DCN32_REG_LIST_RI(id) \
- ( \
SRI_ARR(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \
SRI_ARR(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \
SRI_ARR(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \
@@ -207,12 +214,10 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI_ARR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \
SRI_ARR(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \
SRI_ARR(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \
- SRI_ARR(DC_ABM1_ACE_THRES_12, ABM, id), NBIO_SR_ARR(BIOS_SCRATCH_2, id) \
- )
+ SRI_ARR(DC_ABM1_ACE_THRES_12, ABM, id), NBIO_SR_ARR(BIOS_SCRATCH_2, id)
/* Audio */
#define AUD_COMMON_REG_LIST_RI(id) \
- ( \
SRI_ARR(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZF0ENDPOINT, id), \
SRI_ARR(AZALIA_F0_CODEC_ENDPOINT_DATA, AZF0ENDPOINT, id), \
SR_ARR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS, id), \
@@ -221,41 +226,33 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SR_ARR(DCCG_AUDIO_DTO_SOURCE, id), SR_ARR(DCCG_AUDIO_DTO0_MODULE, id), \
SR_ARR(DCCG_AUDIO_DTO0_PHASE, id), SR_ARR(DCCG_AUDIO_DTO1_MODULE, id), \
SR_ARR(DCCG_AUDIO_DTO1_PHASE, id) \
- )
/* VPG */
#define VPG_DCN3_REG_LIST_RI(id) \
- ( \
SRI_ARR(VPG_GENERIC_STATUS, VPG, id), \
SRI_ARR(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \
SRI_ARR(VPG_GENERIC_PACKET_DATA, VPG, id), \
SRI_ARR(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \
- SRI_ARR(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id) \
- )
+ SRI_ARR(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id)
/* AFMT */
#define AFMT_DCN3_REG_LIST_RI(id) \
- ( \
SRI_ARR(AFMT_INFOFRAME_CONTROL0, AFMT, id), \
SRI_ARR(AFMT_VBI_PACKET_CONTROL, AFMT, id), \
SRI_ARR(AFMT_AUDIO_PACKET_CONTROL, AFMT, id), \
SRI_ARR(AFMT_AUDIO_PACKET_CONTROL2, AFMT, id), \
SRI_ARR(AFMT_AUDIO_SRC_CONTROL, AFMT, id), \
SRI_ARR(AFMT_60958_0, AFMT, id), SRI_ARR(AFMT_60958_1, AFMT, id), \
- SRI_ARR(AFMT_60958_2, AFMT, id), SRI_ARR(AFMT_MEM_PWR, AFMT, id) \
- )
+ SRI_ARR(AFMT_60958_2, AFMT, id), SRI_ARR(AFMT_MEM_PWR, AFMT, id)
/* APG */
#define APG_DCN31_REG_LIST_RI(id) \
- (\
SRI_ARR(APG_CONTROL, APG, id), SRI_ARR(APG_CONTROL2, APG, id), \
- SRI_ARR(APG_MEM_PWR, APG, id), SRI_ARR(APG_DBG_GEN_CONTROL, APG, id) \
- )
+ SRI_ARR(APG_MEM_PWR, APG, id), SRI_ARR(APG_DBG_GEN_CONTROL, APG, id)
/* Stream encoder */
#define SE_DCN32_REG_LIST_RI(id) \
- ( \
SRI_ARR(AFMT_CNTL, DIG, id), SRI_ARR(DIG_FE_CNTL, DIG, id), \
SRI_ARR(HDMI_CONTROL, DIG, id), SRI_ARR(HDMI_DB_CONTROL, DIG, id), \
SRI_ARR(HDMI_GC, DIG, id), \
@@ -299,28 +296,22 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \
SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \
SRI_ARR(DIG_FE_CNTL, DIG, id), SRI_ARR(DIG_CLOCK_PATTERN, DIG, id), \
- SRI_ARR(DIG_FIFO_CTRL0, DIG, id) \
- )
+ SRI_ARR(DIG_FIFO_CTRL0, DIG, id)
/* Aux regs */
#define AUX_REG_LIST_RI(id) \
- ( \
SRI_ARR(AUX_CONTROL, DP_AUX, id), SRI_ARR(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \
- SRI_ARR(AUX_DPHY_RX_CONTROL1, DP_AUX, id) \
- )
+ SRI_ARR(AUX_DPHY_RX_CONTROL1, DP_AUX, id)
#define DCN2_AUX_REG_LIST_RI(id) \
- ( \
- AUX_REG_LIST_RI(id), SRI_ARR(AUX_DPHY_TX_CONTROL, DP_AUX, id) \
- )
+ AUX_REG_LIST_RI(id), SRI_ARR(AUX_DPHY_TX_CONTROL, DP_AUX, id)
/* HDP */
#define HPD_REG_LIST_RI(id) SRI_ARR(DC_HPD_CONTROL, HPD, id)
/* Link encoder */
#define LE_DCN3_REG_LIST_RI(id) \
- ( \
SRI_ARR(DIG_BE_CNTL, DIG, id), SRI_ARR(DIG_BE_EN_CNTL, DIG, id), \
SRI_ARR(TMDS_CTL_BITS, DIG, id), \
SRI_ARR(TMDS_DCBALANCER_CONTROL, DIG, id), SRI_ARR(DP_CONFIG, DP, id), \
@@ -334,26 +325,20 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI_ARR(DP_SEC_CNTL, DP, id), SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \
SRI_ARR(DP_DPHY_FAST_TRAINING, DP, id), SRI_ARR(DP_SEC_CNTL1, DP, id), \
SRI_ARR(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
- SRI_ARR(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) \
- )
+ SRI_ARR(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id)
#define LE_DCN31_REG_LIST_RI(id) \
- ( \
LE_DCN3_REG_LIST_RI(id), SRI_ARR(DP_DPHY_INTERNAL_CTRL, DP, id), \
SR_ARR(DIO_LINKA_CNTL, id), SR_ARR(DIO_LINKB_CNTL, id), \
SR_ARR(DIO_LINKC_CNTL, id), SR_ARR(DIO_LINKD_CNTL, id), \
- SR_ARR(DIO_LINKE_CNTL, id), SR_ARR(DIO_LINKF_CNTL, id) \
- )
+ SR_ARR(DIO_LINKE_CNTL, id), SR_ARR(DIO_LINKF_CNTL, id)
#define UNIPHY_DCN2_REG_LIST_RI(id, phyid) \
- ( \
SRI_ARR_ALPHABET(CLOCK_ENABLE, SYMCLK, id, phyid), \
- SRI_ARR_ALPHABET(CHANNEL_XBAR_CNTL, UNIPHY, id, phyid) \
- )
+ SRI_ARR_ALPHABET(CHANNEL_XBAR_CNTL, UNIPHY, id, phyid)
/* HPO DP stream encoder */
#define DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) \
- ( \
SR_ARR(DP_STREAM_MAPPER_CONTROL0, id), \
SR_ARR(DP_STREAM_MAPPER_CONTROL1, id), \
SR_ARR(DP_STREAM_MAPPER_CONTROL2, id), \
@@ -388,12 +373,10 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI_ARR(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, DP_SYM32_ENC, id), \
SRI_ARR(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, DP_SYM32_ENC, id), \
SRI_ARR(DP_SYM32_ENC_VID_CRC_CONTROL, DP_SYM32_ENC, id), \
- SRI_ARR(DP_SYM32_ENC_HBLANK_CONTROL, DP_SYM32_ENC, id) \
- )
+ SRI_ARR(DP_SYM32_ENC_HBLANK_CONTROL, DP_SYM32_ENC, id)
/* HPO DP link encoder regs */
#define DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) \
- ( \
SRI_ARR(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC, id), \
SRI_ARR(DP_DPHY_SYM32_CONTROL, DP_DPHY_SYM32, id), \
SRI_ARR(DP_DPHY_SYM32_STATUS, DP_DPHY_SYM32, id), \
@@ -422,12 +405,10 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL1, DP_DPHY_SYM32, id), \
SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL2, DP_DPHY_SYM32, id), \
SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL3, DP_DPHY_SYM32, id), \
- SRI_ARR(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id) \
- )
+ SRI_ARR(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id)
/* DPP */
#define DPP_REG_LIST_DCN30_COMMON_RI(id) \
- ( \
SRI_ARR(CM_DEALPHA, CM, id), SRI_ARR(CM_MEM_PWR_STATUS, CM, id), \
SRI_ARR(CM_BIAS_CR_R, CM, id), SRI_ARR(CM_BIAS_Y_G_CB_B, CM, id), \
SRI_ARR(PRE_DEGAM, CNVC_CFG, id), SRI_ARR(CM_GAMCOR_CONTROL, CM, id), \
@@ -542,12 +523,10 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \
SRI_ARR(OBUF_MEM_PWR_CTRL, DSCL, id), \
SRI_ARR(DSCL_MEM_PWR_STATUS, DSCL, id), \
- SRI_ARR(DSCL_MEM_PWR_CTRL, DSCL, id) \
- )
+ SRI_ARR(DSCL_MEM_PWR_CTRL, DSCL, id)
/* OPP */
#define OPP_REG_LIST_DCN_RI(id) \
- ( \
SRI_ARR(FMT_BIT_DEPTH_CONTROL, FMT, id), SRI_ARR(FMT_CONTROL, FMT, id), \
SRI_ARR(FMT_DITHER_RAND_R_SEED, FMT, id), \
SRI_ARR(FMT_DITHER_RAND_G_SEED, FMT, id), \
@@ -559,37 +538,29 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI_ARR(OPPBUF_3D_PARAMETERS_0, OPPBUF, id), \
SRI_ARR(OPPBUF_3D_PARAMETERS_1, OPPBUF, id), \
SRI_ARR(OPP_PIPE_CONTROL, OPP_PIPE, id) \
- )
#define OPP_REG_LIST_DCN10_RI(id) OPP_REG_LIST_DCN_RI(id)
#define OPP_DPG_REG_LIST_RI(id) \
- ( \
SRI_ARR(DPG_CONTROL, DPG, id), SRI_ARR(DPG_DIMENSIONS, DPG, id), \
SRI_ARR(DPG_OFFSET_SEGMENT, DPG, id), SRI_ARR(DPG_COLOUR_B_CB, DPG, id), \
SRI_ARR(DPG_COLOUR_G_Y, DPG, id), SRI_ARR(DPG_COLOUR_R_CR, DPG, id), \
- SRI_ARR(DPG_RAMP_CONTROL, DPG, id), SRI_ARR(DPG_STATUS, DPG, id) \
- )
+ SRI_ARR(DPG_RAMP_CONTROL, DPG, id), SRI_ARR(DPG_STATUS, DPG, id)
#define OPP_REG_LIST_DCN30_RI(id) \
- ( \
OPP_REG_LIST_DCN10_RI(id), OPP_DPG_REG_LIST_RI(id), \
- SRI_ARR(FMT_422_CONTROL, FMT, id) \
- )
+ SRI_ARR(FMT_422_CONTROL, FMT, id)
/* Aux engine regs */
#define AUX_COMMON_REG_LIST0_RI(id) \
- ( \
SRI_ARR(AUX_CONTROL, DP_AUX, id), SRI_ARR(AUX_ARB_CONTROL, DP_AUX, id), \
SRI_ARR(AUX_SW_DATA, DP_AUX, id), SRI_ARR(AUX_SW_CONTROL, DP_AUX, id), \
SRI_ARR(AUX_INTERRUPT_CONTROL, DP_AUX, id), \
SRI_ARR(AUX_DPHY_RX_CONTROL1, DP_AUX, id), \
- SRI_ARR(AUX_SW_STATUS, DP_AUX, id) \
- )
+ SRI_ARR(AUX_SW_STATUS, DP_AUX, id)
/* DWBC */
#define DWBC_COMMON_REG_LIST_DCN30_RI(id) \
- ( \
SR_ARR(DWB_ENABLE_CLK_CTRL, id), SR_ARR(DWB_MEM_PWR_CTRL, id), \
SR_ARR(FC_MODE_CTRL, id), SR_ARR(FC_FLOW_CTRL, id), \
SR_ARR(FC_WINDOW_START, id), SR_ARR(FC_WINDOW_SIZE, id), \
@@ -683,13 +654,11 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SR_ARR(DWB_OGAM_RAMB_REGION_26_27, id), \
SR_ARR(DWB_OGAM_RAMB_REGION_28_29, id), \
SR_ARR(DWB_OGAM_RAMB_REGION_30_31, id), \
- SR_ARR(DWB_OGAM_RAMB_REGION_32_33, id) \
- )
+ SR_ARR(DWB_OGAM_RAMB_REGION_32_33, id)
/* MCIF */
#define MCIF_WB_COMMON_REG_LIST_DCN32_RI(inst) \
- ( \
SRI2_ARR(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst), \
SRI2_ARR(MCIF_WB_BUFMGR_STATUS, MCIF_WB, inst), \
SRI2_ARR(MCIF_WB_BUF_PITCH, MCIF_WB, inst), \
@@ -703,8 +672,6 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI2_ARR(MCIF_WB_BUF_4_STATUS2, MCIF_WB, inst), \
SRI2_ARR(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst), \
SRI2_ARR(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst), \
- SRI2_ARR(MCIF_WB_TEST_DEBUG_INDEX, MCIF_WB, inst), \
- SRI2_ARR(MCIF_WB_TEST_DEBUG_DATA, MCIF_WB, inst), \
SRI2_ARR(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst), \
SRI2_ARR(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst), \
SRI2_ARR(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst), \
@@ -739,13 +706,11 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI2_ARR(MMHUBBUB_WARMUP_ADDR_REGION, MMHUBBUB, inst), \
SRI2_ARR(MMHUBBUB_WARMUP_BASE_ADDR_HIGH, MMHUBBUB, inst), \
SRI2_ARR(MMHUBBUB_WARMUP_BASE_ADDR_LOW, MMHUBBUB, inst), \
- SRI2_ARR(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB, inst) \
- )
+ SRI2_ARR(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB, inst)
/* DSC */
#define DSC_REG_LIST_DCN20_RI(id) \
- ( \
SRI_ARR(DSC_TOP_CONTROL, DSC_TOP, id), \
SRI_ARR(DSC_DEBUG_CONTROL, DSC_TOP, id), \
SRI_ARR(DSCC_CONFIG0, DSCC, id), SRI_ARR(DSCC_CONFIG1, DSCC, id), \
@@ -793,8 +758,7 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI_ARR(DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id), \
SRI_ARR(DSCCIF_CONFIG0, DSCCIF, id), \
SRI_ARR(DSCCIF_CONFIG1, DSCCIF, id), \
- SRI_ARR(DSCRM_DSC_FORWARD_CONFIG, DSCRM, id) \
- )
+ SRI_ARR(DSCRM_DSC_FORWARD_CONFIG, DSCRM, id)
/* MPC */
@@ -802,32 +766,25 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRII_DWB(DWB_MUX, MUX, MPC_DWB, inst)
#define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0_RI(inst) \
- ( \
- SRII(MUX, MPC_OUT, inst), VUPDATE_SRII(CUR, VUPDATE_LOCK_SET, inst) \
- )
+ SRII(MUX, MPC_OUT, inst), VUPDATE_SRII(CUR, VUPDATE_LOCK_SET, inst)
#define MPC_OUT_MUX_REG_LIST_DCN3_0_RI(inst) \
- ( \
MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0_RI(inst), SRII(CSC_MODE, MPC_OUT, inst), \
SRII(CSC_C11_C12_A, MPC_OUT, inst), SRII(CSC_C33_C34_A, MPC_OUT, inst), \
SRII(CSC_C11_C12_B, MPC_OUT, inst), SRII(CSC_C33_C34_B, MPC_OUT, inst), \
SRII(DENORM_CONTROL, MPC_OUT, inst), \
SRII(DENORM_CLAMP_G_Y, MPC_OUT, inst), \
- SRII(DENORM_CLAMP_B_CB, MPC_OUT, inst), SR(MPC_OUT_CSC_COEF_FORMAT) \
- )
+ SRII(DENORM_CLAMP_B_CB, MPC_OUT, inst), SR(MPC_OUT_CSC_COEF_FORMAT)
#define MPC_COMMON_REG_LIST_DCN1_0_RI(inst) \
- ( \
SRII(MPCC_TOP_SEL, MPCC, inst), SRII(MPCC_BOT_SEL, MPCC, inst), \
SRII(MPCC_CONTROL, MPCC, inst), SRII(MPCC_STATUS, MPCC, inst), \
SRII(MPCC_OPP_ID, MPCC, inst), SRII(MPCC_BG_G_Y, MPCC, inst), \
SRII(MPCC_BG_R_CR, MPCC, inst), SRII(MPCC_BG_B_CB, MPCC, inst), \
SRII(MPCC_SM_CONTROL, MPCC, inst), \
- SRII(MPCC_UPDATE_LOCK_SEL, MPCC, inst) \
- )
+ SRII(MPCC_UPDATE_LOCK_SEL, MPCC, inst)
#define MPC_REG_LIST_DCN3_0_RI(inst) \
- ( \
MPC_COMMON_REG_LIST_DCN1_0_RI(inst), SRII(MPCC_TOP_GAIN, MPCC, inst), \
SRII(MPCC_BOT_GAIN_INSIDE, MPCC, inst), \
SRII(MPCC_BOT_GAIN_OUTSIDE, MPCC, inst), \
@@ -881,8 +838,7 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_G, MPCC_OGAM, inst), \
SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_R, MPCC_OGAM, inst), \
SRII(MPCC_OGAM_CONTROL, MPCC_OGAM, inst), \
- SRII(MPCC_OGAM_LUT_CONTROL, MPCC_OGAM, inst) \
- )
+ SRII(MPCC_OGAM_LUT_CONTROL, MPCC_OGAM, inst)
#define MPC_REG_LIST_DCN3_2_RI(inst) \
MPC_REG_LIST_DCN3_0_RI(inst),\
@@ -1026,11 +982,9 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRII(MPCC_MCM_1DLUT_RAMB_REGION_30_31, MPCC_MCM, inst),\
SRII(MPCC_MCM_1DLUT_RAMB_REGION_32_33, MPCC_MCM, inst),\
SRII(MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM, inst)
-
/* OPTC */
#define OPTC_COMMON_REG_LIST_DCN3_2_RI(inst) \
- ( \
SRI_ARR(OTG_VSTARTUP_PARAM, OTG, inst), \
SRI_ARR(OTG_VUPDATE_PARAM, OTG, inst), \
SRI_ARR(OTG_VREADY_PARAM, OTG, inst), \
@@ -1092,22 +1046,17 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI_ARR(OPTC_BYTES_PER_PIXEL, ODM, inst), \
SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst), \
SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst), \
- SRI_ARR(OTG_DRR_CONTROL, OTG, inst) \
- )
+ SRI_ARR(OTG_DRR_CONTROL, OTG, inst)
/* HUBP */
#define HUBP_REG_LIST_DCN_VM_RI(id) \
- ( \
SRI_ARR(NOM_PARAMETERS_0, HUBPREQ, id), \
SRI_ARR(NOM_PARAMETERS_1, HUBPREQ, id), \
SRI_ARR(NOM_PARAMETERS_2, HUBPREQ, id), \
SRI_ARR(NOM_PARAMETERS_3, HUBPREQ, id), \
- SRI_ARR(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id) \
- )
-
+ SRI_ARR(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id)
#define HUBP_REG_LIST_DCN_RI(id) \
- ( \
SRI_ARR(DCHUBP_CNTL, HUBP, id), SRI_ARR(HUBPREQ_DEBUG_DB, HUBP, id), \
SRI_ARR(HUBPREQ_DEBUG, HUBP, id), SRI_ARR(DCSURF_ADDR_CONFIG, HUBP, id), \
SRI_ARR(DCSURF_TILING_CONFIG, HUBP, id), \
@@ -1178,11 +1127,8 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI_ARR(DCN_SURF1_TTU_CNTL1, HUBPREQ, id), \
SRI_ARR(DCN_CUR0_TTU_CNTL0, HUBPREQ, id), \
SRI_ARR(DCN_CUR0_TTU_CNTL1, HUBPREQ, id), \
- SRI_ARR(HUBP_CLK_CNTL, HUBP, id) \
- )
-
+ SRI_ARR(HUBP_CLK_CNTL, HUBP, id)
#define HUBP_REG_LIST_DCN2_COMMON_RI(id) \
- ( \
HUBP_REG_LIST_DCN_RI(id), HUBP_REG_LIST_DCN_VM_RI(id), \
SRI_ARR(PREFETCH_SETTINGS, HUBPREQ, id), \
SRI_ARR(PREFETCH_SETTINGS_C, HUBPREQ, id), \
@@ -1209,35 +1155,24 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SRI_ARR(DCN_CUR1_TTU_CNTL0, HUBPREQ, id), \
SRI_ARR(DCN_CUR1_TTU_CNTL1, HUBPREQ, id), \
SRI_ARR(DCSURF_FLIP_CONTROL2, HUBPREQ, id), \
- SRI_ARR(VMID_SETTINGS_0, HUBPREQ, id) \
- )
-
+ SRI_ARR(VMID_SETTINGS_0, HUBPREQ, id)
#define HUBP_REG_LIST_DCN21_RI(id) \
- ( \
HUBP_REG_LIST_DCN2_COMMON_RI(id), SRI_ARR(FLIP_PARAMETERS_3, HUBPREQ, id), \
SRI_ARR(FLIP_PARAMETERS_4, HUBPREQ, id), \
SRI_ARR(FLIP_PARAMETERS_5, HUBPREQ, id), \
SRI_ARR(FLIP_PARAMETERS_6, HUBPREQ, id), \
SRI_ARR(VBLANK_PARAMETERS_5, HUBPREQ, id), \
- SRI_ARR(VBLANK_PARAMETERS_6, HUBPREQ, id) \
- )
-
+ SRI_ARR(VBLANK_PARAMETERS_6, HUBPREQ, id)
#define HUBP_REG_LIST_DCN30_RI(id) \
- ( \
- HUBP_REG_LIST_DCN21_RI(id), SRI_ARR(DCN_DMDATA_VM_CNTL, HUBPREQ, id) \
- )
-
+ HUBP_REG_LIST_DCN21_RI(id), SRI_ARR(DCN_DMDATA_VM_CNTL, HUBPREQ, id)
#define HUBP_REG_LIST_DCN32_RI(id) \
- ( \
HUBP_REG_LIST_DCN30_RI(id), SRI_ARR(DCHUBP_MALL_CONFIG, HUBP, id), \
SRI_ARR(DCHUBP_VMPG_CONFIG, HUBP, id), \
- SRI_ARR(UCLK_PSTATE_FORCE, HUBPREQ, id) \
- )
+ SRI_ARR(UCLK_PSTATE_FORCE, HUBPREQ, id)
/* HUBBUB */
#define HUBBUB_REG_LIST_DCN32_RI(id) \
- ( \
SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A), \
SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B), \
SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C), \
@@ -1275,15 +1210,14 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B), \
SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C), \
SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D), \
+ SR(DCHUBBUB_ARB_MALL_CNTL), \
SR(DCN_VM_FAULT_ADDR_MSB), SR(DCN_VM_FAULT_ADDR_LSB), \
SR(DCN_VM_FAULT_CNTL), SR(DCN_VM_FAULT_STATUS), \
- SR(SDPIF_REQUEST_RATE_LIMIT) \
- )
+ SR(SDPIF_REQUEST_RATE_LIMIT)
/* DCCG */
#define DCCG_REG_LIST_DCN32_RI() \
- ( \
SR(DPPCLK_DTO_CTRL), DCCG_SRII(DTO_PARAM, DPPCLK, 0), \
DCCG_SRII(DTO_PARAM, DPPCLK, 1), DCCG_SRII(DTO_PARAM, DPPCLK, 2), \
DCCG_SRII(DTO_PARAM, DPPCLK, 3), DCCG_SRII(CLOCK_CNTL, HDMICHARCLK, 0), \
@@ -1299,38 +1233,31 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
DCCG_SRII(PHASE, DTBCLK_DTO, 2), DCCG_SRII(PHASE, DTBCLK_DTO, 3), \
SR(DCCG_AUDIO_DTBCLK_DTO_MODULO), SR(DCCG_AUDIO_DTBCLK_DTO_PHASE), \
SR(OTG_PIXEL_RATE_DIV), SR(DTBCLK_P_CNTL), \
- SR(DCCG_AUDIO_DTO_SOURCE), SR(DENTIST_DISPCLK_CNTL) \
- )
+ SR(DCCG_AUDIO_DTO_SOURCE), SR(DENTIST_DISPCLK_CNTL)
/* VMID */
#define DCN20_VMID_REG_LIST_RI(id) \
- ( \
SRI_ARR(CNTL, DCN_VM_CONTEXT, id), \
SRI_ARR(PAGE_TABLE_BASE_ADDR_HI32, DCN_VM_CONTEXT, id), \
SRI_ARR(PAGE_TABLE_BASE_ADDR_LO32, DCN_VM_CONTEXT, id), \
SRI_ARR(PAGE_TABLE_START_ADDR_HI32, DCN_VM_CONTEXT, id), \
SRI_ARR(PAGE_TABLE_START_ADDR_LO32, DCN_VM_CONTEXT, id), \
SRI_ARR(PAGE_TABLE_END_ADDR_HI32, DCN_VM_CONTEXT, id), \
- SRI_ARR(PAGE_TABLE_END_ADDR_LO32, DCN_VM_CONTEXT, id) \
- )
+ SRI_ARR(PAGE_TABLE_END_ADDR_LO32, DCN_VM_CONTEXT, id)
/* I2C HW */
#define I2C_HW_ENGINE_COMMON_REG_LIST_RI(id) \
- ( \
SRI_ARR_I2C(SETUP, DC_I2C_DDC, id), SRI_ARR_I2C(SPEED, DC_I2C_DDC, id), \
SRI_ARR_I2C(HW_STATUS, DC_I2C_DDC, id), \
SR_ARR_I2C(DC_I2C_ARBITRATION, id), \
SR_ARR_I2C(DC_I2C_CONTROL, id), SR_ARR_I2C(DC_I2C_SW_STATUS, id), \
SR_ARR_I2C(DC_I2C_TRANSACTION0, id), SR_ARR_I2C(DC_I2C_TRANSACTION1, id),\
SR_ARR_I2C(DC_I2C_TRANSACTION2, id), SR_ARR_I2C(DC_I2C_TRANSACTION3, id),\
- SR_ARR_I2C(DC_I2C_DATA, id), SR_ARR_I2C(MICROSECOND_TIME_BASE_DIV, id) \
- )
+ SR_ARR_I2C(DC_I2C_DATA, id), SR_ARR_I2C(MICROSECOND_TIME_BASE_DIV, id)
#define I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) \
- ( \
I2C_HW_ENGINE_COMMON_REG_LIST_RI(id), SR_ARR_I2C(DIO_MEM_PWR_CTRL, id), \
- SR_ARR_I2C(DIO_MEM_PWR_STATUS, id) \
- )
+ SR_ARR_I2C(DIO_MEM_PWR_STATUS, id)
#endif /* _DCN32_RESOURCE_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
index 3ad2b48954e0..bc5f0db23d0c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
@@ -255,6 +255,51 @@ bool dcn32_is_psr_capable(struct pipe_ctx *pipe)
return psr_capable;
}
+static void override_det_for_subvp(struct dc *dc, struct dc_state *context, uint8_t pipe_segments[])
+{
+ uint32_t i;
+ uint8_t fhd_count = 0;
+ uint8_t subvp_high_refresh_count = 0;
+ uint8_t stream_count = 0;
+
+ // Do not override if a stream has multiple planes
+ for (i = 0; i < context->stream_count; i++) {
+ if (context->stream_status[i].plane_count > 1) {
+ return;
+ }
+ if (context->streams[i]->mall_stream_config.type != SUBVP_PHANTOM) {
+ stream_count++;
+ }
+ }
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+ if (pipe_ctx->stream && pipe_ctx->plane_state && pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) {
+ if (dcn32_allow_subvp_high_refresh_rate(dc, context, pipe_ctx)) {
+
+ if (pipe_ctx->stream->timing.v_addressable == 1080 && pipe_ctx->stream->timing.h_addressable == 1920) {
+ fhd_count++;
+ }
+ subvp_high_refresh_count++;
+ }
+ }
+ }
+
+ if (stream_count == 2 && subvp_high_refresh_count == 2 && fhd_count == 1) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+ if (pipe_ctx->stream && pipe_ctx->plane_state && pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) {
+ if (pipe_ctx->stream->timing.v_addressable == 1080 && pipe_ctx->stream->timing.h_addressable == 1920) {
+ if (pipe_segments[i] > 4)
+ pipe_segments[i] = 4;
+ }
+ }
+ }
+ }
+}
+
/**
* dcn32_determine_det_override(): Determine DET allocation for each pipe
*
@@ -336,6 +381,7 @@ void dcn32_determine_det_override(struct dc *dc,
}
}
+ override_det_for_subvp(dc, context, pipe_segments);
for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
if (!context->res_ctx.pipe_ctx[i].stream)
continue;
@@ -660,7 +706,7 @@ bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context)
non_subvp_pipes++;
drr_psr_capable = (drr_psr_capable || dcn32_is_psr_capable(pipe));
if (pipe->stream->ignore_msa_timing_param &&
- (pipe->stream->allow_freesync || pipe->stream->vrr_active_variable)) {
+ (pipe->stream->allow_freesync || pipe->stream->vrr_active_variable || pipe->stream->vrr_active_fixed)) {
drr_pipe_found = true;
}
}
@@ -718,7 +764,7 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
non_subvp_pipes++;
vblank_psr_capable = (vblank_psr_capable || dcn32_is_psr_capable(pipe));
if (pipe->stream->ignore_msa_timing_param &&
- (pipe->stream->allow_freesync || pipe->stream->vrr_active_variable)) {
+ (pipe->stream->allow_freesync || pipe->stream->vrr_active_variable || pipe->stream->vrr_active_fixed)) {
drr_pipe_found = true;
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
index 8d73cceb485b..f7de3eca1225 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
@@ -50,7 +50,7 @@
#include "dcn32/dcn32_optc.h"
#include "dcn20/dcn20_hwseq.h"
#include "dcn30/dcn30_hwseq.h"
-#include "dce110/dce110_hw_sequencer.h"
+#include "dce110/dce110_hwseq.h"
#include "dcn30/dcn30_opp.h"
#include "dcn20/dcn20_dsc.h"
#include "dcn30/dcn30_vpg.h"
@@ -732,6 +732,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.fpo_vactive_max_blank_us = 1000,
.enable_legacy_fast_update = false,
.disable_dc_mode_overwrite = true,
+ .using_dml2 = false,
};
static struct dce_aux *dcn321_aux_engine_create(
@@ -1570,7 +1571,8 @@ static void dcn321_destroy_resource_pool(struct resource_pool **pool)
}
static struct dc_cap_funcs cap_funcs = {
- .get_dcc_compression_cap = dcn20_get_dcc_compression_cap
+ .get_dcc_compression_cap = dcn20_get_dcc_compression_cap,
+ .get_subvp_en = dcn32_subvp_in_use,
};
static void dcn321_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
@@ -1589,6 +1591,8 @@ static struct resource_funcs dcn321_res_pool_funcs = {
.calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg,
.populate_dml_pipes = dcn32_populate_dml_pipes_from_context,
.acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe,
+ .acquire_free_pipe_as_secondary_opp_head = dcn32_acquire_free_pipe_as_secondary_opp_head,
+ .release_pipe = dcn20_release_pipe,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
@@ -1987,6 +1991,52 @@ static bool dcn321_resource_construct(
pool->base.oem_device = NULL;
}
+ dc->dml2_options.dcn_pipe_count = pool->base.pipe_count;
+ dc->dml2_options.use_native_pstate_optimization = false;
+ dc->dml2_options.use_native_soc_bb_construction = true;
+ dc->dml2_options.minimize_dispclk_using_odm = true;
+
+ dc->dml2_options.callbacks.dc = dc;
+ dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params;
+ dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch;
+ dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy;
+ dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count;
+ dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count;
+ dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index;
+ dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index;
+ dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head;
+
+ dc->dml2_options.svp_pstate.callbacks.dc = dc;
+ dc->dml2_options.svp_pstate.callbacks.add_plane_to_context = &dc_add_plane_to_context;
+ dc->dml2_options.svp_pstate.callbacks.add_stream_to_ctx = &dc_add_stream_to_ctx;
+ dc->dml2_options.svp_pstate.callbacks.build_scaling_params = &resource_build_scaling_params;
+ dc->dml2_options.svp_pstate.callbacks.create_plane = &dc_create_plane_state;
+ dc->dml2_options.svp_pstate.callbacks.remove_plane_from_context = &dc_remove_plane_from_context;
+ dc->dml2_options.svp_pstate.callbacks.remove_stream_from_ctx = &dc_remove_stream_from_ctx;
+ dc->dml2_options.svp_pstate.callbacks.create_stream_for_sink = &dc_create_stream_for_sink;
+ dc->dml2_options.svp_pstate.callbacks.plane_state_release = &dc_plane_state_release;
+ dc->dml2_options.svp_pstate.callbacks.stream_release = &dc_stream_release;
+ dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc;
+
+ dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us;
+ dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us;
+ dc->dml2_options.svp_pstate.subvp_pstate_allow_width_us = dc->caps.subvp_pstate_allow_width_us;
+ dc->dml2_options.svp_pstate.subvp_swath_height_margin_lines = dc->caps.subvp_swath_height_margin_lines;
+
+ dc->dml2_options.svp_pstate.force_disable_subvp = dc->debug.force_disable_subvp;
+ dc->dml2_options.svp_pstate.force_enable_subvp = dc->debug.force_subvp_mclk_switch;
+
+ dc->dml2_options.mall_cfg.cache_line_size_bytes = dc->caps.cache_line_size;
+ dc->dml2_options.mall_cfg.cache_num_ways = dc->caps.cache_num_ways;
+ dc->dml2_options.mall_cfg.max_cab_allocation_bytes = dc->caps.max_cab_allocation_bytes;
+ dc->dml2_options.mall_cfg.mblk_height_4bpe_pixels = DCN3_2_MBLK_HEIGHT_4BPE;
+ dc->dml2_options.mall_cfg.mblk_height_8bpe_pixels = DCN3_2_MBLK_HEIGHT_8BPE;
+ dc->dml2_options.mall_cfg.mblk_size_bytes = DCN3_2_MALL_MBLK_SIZE_BYTES;
+ dc->dml2_options.mall_cfg.mblk_width_pixels = DCN3_2_MBLK_WIDTH;
+
+ dc->dml2_options.max_segments_per_hubp = 18;
+ dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;
+
return true;
create_fail:
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/Makefile b/drivers/gpu/drm/amd/display/dc/dcn35/Makefile
new file mode 100644
index 000000000000..20d0eef1a13b
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/Makefile
@@ -0,0 +1,20 @@
+#
+# (c) Copyright 2022 Advanced Micro Devices, Inc. All the rights reserved
+#
+# All rights reserved. This notice is intended as a precaution against
+# inadvertent publication and does not imply publication or any waiver
+# of confidentiality. The year included in the foregoing notice is the
+# year of creation of the work.
+#
+# Authors: AMD
+#
+# Makefile for DCN35.
+
+DCN35 = dcn35_resource.o dcn35_init.o dcn35_dio_stream_encoder.o \
+ dcn35_dio_link_encoder.o dcn35_dccg.o dcn35_optc.o \
+ dcn35_dsc.o dcn35_hubp.o dcn35_hubbub.o \
+ dcn35_mmhubbub.o dcn35_opp.o dcn35_dpp.o dcn35_pg_cntl.o dcn35_dwb.o
+
+AMD_DAL_DCN35 = $(addprefix $(AMDDALPATH)/dc/dcn35/,$(DCN35))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DCN35)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c
new file mode 100644
index 000000000000..479f3683c0b7
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c
@@ -0,0 +1,805 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "reg_helper.h"
+#include "core_types.h"
+#include "dcn35_dccg.h"
+
+#define TO_DCN_DCCG(dccg)\
+ container_of(dccg, struct dcn_dccg, base)
+
+#define REG(reg) \
+ (dccg_dcn->regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+ dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name
+
+#define CTX \
+ dccg_dcn->base.ctx
+#define DC_LOGGER \
+ dccg->ctx->logger
+
+static void dcn35_set_dppclk_enable(struct dccg *dccg,
+ uint32_t dpp_inst, uint32_t enable)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ switch (dpp_inst) {
+ case 0:
+ REG_UPDATE(DPPCLK_CTRL, DPPCLK0_EN, enable);
+ break;
+ case 1:
+ REG_UPDATE(DPPCLK_CTRL, DPPCLK1_EN, enable);
+ break;
+ case 2:
+ REG_UPDATE(DPPCLK_CTRL, DPPCLK2_EN, enable);
+ break;
+ case 3:
+ REG_UPDATE(DPPCLK_CTRL, DPPCLK3_EN, enable);
+ break;
+ default:
+ break;
+ }
+
+}
+
+static void dccg35_update_dpp_dto(struct dccg *dccg, int dpp_inst,
+ int req_dppclk)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ if (dccg->dpp_clock_gated[dpp_inst]) {
+ /*
+ * Do not update the DPPCLK DTO if the clock is stopped.
+ */
+ return;
+ }
+
+ if (dccg->ref_dppclk && req_dppclk) {
+ int ref_dppclk = dccg->ref_dppclk;
+ int modulo, phase;
+
+ // phase / modulo = dpp pipe clk / dpp global clk
+ modulo = 0xff; // use FF at the end
+ phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk;
+
+ if (phase > 0xff) {
+ ASSERT(false);
+ phase = 0xff;
+ }
+
+ REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
+ DPPCLK0_DTO_PHASE, phase,
+ DPPCLK0_DTO_MODULO, modulo);
+
+ dcn35_set_dppclk_enable(dccg, dpp_inst, true);
+ } else
+ dcn35_set_dppclk_enable(dccg, dpp_inst, false);
+ dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
+}
+
+static void dccg35_get_pixel_rate_div(
+ struct dccg *dccg,
+ uint32_t otg_inst,
+ enum pixel_rate_div *k1,
+ enum pixel_rate_div *k2)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+ uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
+
+ *k1 = PIXEL_RATE_DIV_NA;
+ *k2 = PIXEL_RATE_DIV_NA;
+
+ switch (otg_inst) {
+ case 0:
+ REG_GET_2(OTG_PIXEL_RATE_DIV,
+ OTG0_PIXEL_RATE_DIVK1, &val_k1,
+ OTG0_PIXEL_RATE_DIVK2, &val_k2);
+ break;
+ case 1:
+ REG_GET_2(OTG_PIXEL_RATE_DIV,
+ OTG1_PIXEL_RATE_DIVK1, &val_k1,
+ OTG1_PIXEL_RATE_DIVK2, &val_k2);
+ break;
+ case 2:
+ REG_GET_2(OTG_PIXEL_RATE_DIV,
+ OTG2_PIXEL_RATE_DIVK1, &val_k1,
+ OTG2_PIXEL_RATE_DIVK2, &val_k2);
+ break;
+ case 3:
+ REG_GET_2(OTG_PIXEL_RATE_DIV,
+ OTG3_PIXEL_RATE_DIVK1, &val_k1,
+ OTG3_PIXEL_RATE_DIVK2, &val_k2);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+
+ *k1 = (enum pixel_rate_div)val_k1;
+ *k2 = (enum pixel_rate_div)val_k2;
+}
+
+static void dccg35_set_pixel_rate_div(
+ struct dccg *dccg,
+ uint32_t otg_inst,
+ enum pixel_rate_div k1,
+ enum pixel_rate_div k2)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+ enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
+
+ // Don't program 0xF into the register field. Not valid since
+ // K1 / K2 field is only 1 / 2 bits wide
+ if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA) {
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+
+ dccg35_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);
+ if (k1 == cur_k1 && k2 == cur_k2)
+ return;
+
+ switch (otg_inst) {
+ case 0:
+ REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
+ OTG0_PIXEL_RATE_DIVK1, k1,
+ OTG0_PIXEL_RATE_DIVK2, k2);
+ break;
+ case 1:
+ REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
+ OTG1_PIXEL_RATE_DIVK1, k1,
+ OTG1_PIXEL_RATE_DIVK2, k2);
+ break;
+ case 2:
+ REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
+ OTG2_PIXEL_RATE_DIVK1, k1,
+ OTG2_PIXEL_RATE_DIVK2, k2);
+ break;
+ case 3:
+ REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
+ OTG3_PIXEL_RATE_DIVK1, k1,
+ OTG3_PIXEL_RATE_DIVK2, k2);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+}
+
+static void dccg35_set_dtbclk_p_src(
+ struct dccg *dccg,
+ enum streamclk_source src,
+ uint32_t otg_inst)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ uint32_t p_src_sel = 0; /* selects dprefclk */
+ if (src == DTBCLK0)
+ p_src_sel = 2; /* selects dtbclk0 */
+
+ switch (otg_inst) {
+ case 0:
+ if (src == REFCLK)
+ REG_UPDATE(DTBCLK_P_CNTL,
+ DTBCLK_P0_EN, 0);
+ else
+ REG_UPDATE_2(DTBCLK_P_CNTL,
+ DTBCLK_P0_SRC_SEL, p_src_sel,
+ DTBCLK_P0_EN, 1);
+ break;
+ case 1:
+ if (src == REFCLK)
+ REG_UPDATE(DTBCLK_P_CNTL,
+ DTBCLK_P1_EN, 0);
+ else
+ REG_UPDATE_2(DTBCLK_P_CNTL,
+ DTBCLK_P1_SRC_SEL, p_src_sel,
+ DTBCLK_P1_EN, 1);
+ break;
+ case 2:
+ if (src == REFCLK)
+ REG_UPDATE(DTBCLK_P_CNTL,
+ DTBCLK_P2_EN, 0);
+ else
+ REG_UPDATE_2(DTBCLK_P_CNTL,
+ DTBCLK_P2_SRC_SEL, p_src_sel,
+ DTBCLK_P2_EN, 1);
+ break;
+ case 3:
+ if (src == REFCLK)
+ REG_UPDATE(DTBCLK_P_CNTL,
+ DTBCLK_P3_EN, 0);
+ else
+ REG_UPDATE_2(DTBCLK_P_CNTL,
+ DTBCLK_P3_SRC_SEL, p_src_sel,
+ DTBCLK_P3_EN, 1);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+
+}
+
+/* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
+static void dccg35_set_dtbclk_dto(
+ struct dccg *dccg,
+ const struct dtbclk_dto_params *params)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+ /* DTO Output Rate / Pixel Rate = 1/4 */
+ int req_dtbclk_khz = params->pixclk_khz / 4;
+
+ if (params->ref_dtbclk_khz && req_dtbclk_khz) {
+ uint32_t modulo, phase;
+
+ // phase / modulo = dtbclk / dtbclk ref
+ modulo = params->ref_dtbclk_khz * 1000;
+ phase = req_dtbclk_khz * 1000;
+
+ REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);
+ REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);
+
+ REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
+ DTBCLK_DTO_ENABLE[params->otg_inst], 1);
+
+ REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],
+ DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,
+ 1, 100);
+
+ /* program OTG_PIXEL_RATE_DIV for DIVK1 and DIVK2 fields */
+ dccg35_set_pixel_rate_div(dccg, params->otg_inst, PIXEL_RATE_DIV_BY_1, PIXEL_RATE_DIV_BY_1);
+
+ /* The recommended programming sequence to enable DTBCLK DTO to generate
+ * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
+ * be set only after DTO is enabled
+ */
+ REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
+ PIPE_DTO_SRC_SEL[params->otg_inst], 2);
+ } else {
+ REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
+ DTBCLK_DTO_ENABLE[params->otg_inst], 0,
+ PIPE_DTO_SRC_SEL[params->otg_inst], params->is_hdmi ? 0 : 1);
+
+ REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
+ REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
+ }
+}
+
+static void dccg35_set_dpstreamclk(
+ struct dccg *dccg,
+ enum streamclk_source src,
+ int otg_inst,
+ int dp_hpo_inst)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ /* set the dtbclk_p source */
+ dccg35_set_dtbclk_p_src(dccg, src, otg_inst);
+
+ /* enabled to select one of the DTBCLKs for pipe */
+ switch (dp_hpo_inst) {
+ case 0:
+ REG_UPDATE_2(DPSTREAMCLK_CNTL,
+ DPSTREAMCLK0_EN,
+ (src == REFCLK) ? 0 : 1, DPSTREAMCLK0_SRC_SEL, otg_inst);
+ break;
+ case 1:
+ REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN,
+ (src == REFCLK) ? 0 : 1, DPSTREAMCLK1_SRC_SEL, otg_inst);
+ break;
+ case 2:
+ REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN,
+ (src == REFCLK) ? 0 : 1, DPSTREAMCLK2_SRC_SEL, otg_inst);
+ break;
+ case 3:
+ REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN,
+ (src == REFCLK) ? 0 : 1, DPSTREAMCLK3_SRC_SEL, otg_inst);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+}
+
+static void dccg35_set_physymclk_root_clock_gating(
+ struct dccg *dccg,
+ int phy_inst,
+ bool enable)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ if (!dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
+ return;
+
+ switch (phy_inst) {
+ case 0:
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYASYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
+ break;
+ case 1:
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYBSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
+ break;
+ case 2:
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYCSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
+ break;
+ case 3:
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYDSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
+ break;
+ case 4:
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYESYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+}
+
+static void dccg35_set_physymclk(
+ struct dccg *dccg,
+ int phy_inst,
+ enum physymclk_clock_source clk_src,
+ bool force_enable)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ /* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */
+ switch (phy_inst) {
+ case 0:
+ if (force_enable) {
+ REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
+ PHYASYMCLK_EN, 1,
+ PHYASYMCLK_SRC_SEL, clk_src);
+ } else {
+ REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
+ PHYASYMCLK_EN, 0,
+ PHYASYMCLK_SRC_SEL, 0);
+ }
+ break;
+ case 1:
+ if (force_enable) {
+ REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
+ PHYBSYMCLK_EN, 1,
+ PHYBSYMCLK_SRC_SEL, clk_src);
+ } else {
+ REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
+ PHYBSYMCLK_EN, 0,
+ PHYBSYMCLK_SRC_SEL, 0);
+ }
+ break;
+ case 2:
+ if (force_enable) {
+ REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
+ PHYCSYMCLK_EN, 1,
+ PHYCSYMCLK_SRC_SEL, clk_src);
+ } else {
+ REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
+ PHYCSYMCLK_EN, 0,
+ PHYCSYMCLK_SRC_SEL, 0);
+ }
+ break;
+ case 3:
+ if (force_enable) {
+ REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
+ PHYDSYMCLK_EN, 1,
+ PHYDSYMCLK_SRC_SEL, clk_src);
+ } else {
+ REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
+ PHYDSYMCLK_EN, 0,
+ PHYDSYMCLK_SRC_SEL, 0);
+ }
+ break;
+ case 4:
+ if (force_enable) {
+ REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
+ PHYESYMCLK_EN, 1,
+ PHYESYMCLK_SRC_SEL, clk_src);
+ } else {
+ REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
+ PHYESYMCLK_EN, 0,
+ PHYESYMCLK_SRC_SEL, 0);
+ }
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+}
+
+static void dccg35_set_valid_pixel_rate(
+ struct dccg *dccg,
+ int ref_dtbclk_khz,
+ int otg_inst,
+ int pixclk_khz)
+{
+ struct dtbclk_dto_params dto_params = {0};
+
+ dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
+ dto_params.otg_inst = otg_inst;
+ dto_params.pixclk_khz = pixclk_khz;
+ dto_params.is_hdmi = true;
+
+ dccg35_set_dtbclk_dto(dccg, &dto_params);
+}
+
+static void dccg35_dpp_root_clock_control(
+ struct dccg *dccg,
+ unsigned int dpp_inst,
+ bool clock_on)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ if (dccg->dpp_clock_gated[dpp_inst] == clock_on)
+ return;
+
+ if (clock_on) {
+ /* turn off the DTO and leave phase/modulo at max */
+ dcn35_set_dppclk_enable(dccg, dpp_inst, 0);
+ REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
+ DPPCLK0_DTO_PHASE, 0xFF,
+ DPPCLK0_DTO_MODULO, 0xFF);
+ } else {
+ dcn35_set_dppclk_enable(dccg, dpp_inst, 1);
+ /* turn on the DTO to generate a 0hz clock */
+ REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
+ DPPCLK0_DTO_PHASE, 0,
+ DPPCLK0_DTO_MODULO, 1);
+ }
+
+ dccg->dpp_clock_gated[dpp_inst] = !clock_on;
+}
+
+void dccg35_init(struct dccg *dccg)
+{
+ int otg_inst;
+ /* Set HPO stream encoder to use refclk to avoid case where PHY is
+ * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
+ * will cause DCN to hang.
+ */
+ for (otg_inst = 0; otg_inst < 4; otg_inst++)
+ dccg31_disable_symclk32_se(dccg, otg_inst);
+
+ if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
+ for (otg_inst = 0; otg_inst < 2; otg_inst++)
+ dccg31_disable_symclk32_le(dccg, otg_inst);
+
+ if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
+ for (otg_inst = 0; otg_inst < 4; otg_inst++)
+ dccg314_set_dpstreamclk(dccg, REFCLK, otg_inst,
+ otg_inst);
+
+ if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
+ for (otg_inst = 0; otg_inst < 5; otg_inst++)
+ dccg35_set_physymclk_root_clock_gating(dccg, otg_inst,
+ false);
+/*
+ dccg35_enable_global_fgcg_rep(
+ dccg, dccg->ctx->dc->debug.enable_fine_grain_clock_gating.bits
+ .dccg_global_fgcg_rep);*/
+}
+
+void dccg35_enable_global_fgcg_rep(struct dccg *dccg, bool value)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ REG_UPDATE(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, !value);
+}
+
+static void dccg35_enable_dscclk(struct dccg *dccg, int inst)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ //Disable DTO
+ switch (inst) {
+ case 0:
+ REG_UPDATE_2(DSCCLK0_DTO_PARAM,
+ DSCCLK0_DTO_PHASE, 0,
+ DSCCLK0_DTO_MODULO, 0);
+ REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1);
+ break;
+ case 1:
+ REG_UPDATE_2(DSCCLK1_DTO_PARAM,
+ DSCCLK1_DTO_PHASE, 0,
+ DSCCLK1_DTO_MODULO, 0);
+ REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1);
+ break;
+ case 2:
+ REG_UPDATE_2(DSCCLK2_DTO_PARAM,
+ DSCCLK2_DTO_PHASE, 0,
+ DSCCLK2_DTO_MODULO, 0);
+ REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1);
+ break;
+ case 3:
+ REG_UPDATE_2(DSCCLK3_DTO_PARAM,
+ DSCCLK3_DTO_PHASE, 0,
+ DSCCLK3_DTO_MODULO, 0);
+ REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 1);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+}
+
+static void dccg35_disable_dscclk(struct dccg *dccg,
+ int inst)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
+ return;
+
+ switch (inst) {
+ case 0:
+ REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 0);
+ REG_UPDATE_2(DSCCLK0_DTO_PARAM,
+ DSCCLK0_DTO_PHASE, 0,
+ DSCCLK0_DTO_MODULO, 1);
+ break;
+ case 1:
+ REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 0);
+ REG_UPDATE_2(DSCCLK1_DTO_PARAM,
+ DSCCLK1_DTO_PHASE, 0,
+ DSCCLK1_DTO_MODULO, 1);
+ break;
+ case 2:
+ REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 0);
+ REG_UPDATE_2(DSCCLK2_DTO_PARAM,
+ DSCCLK2_DTO_PHASE, 0,
+ DSCCLK2_DTO_MODULO, 1);
+ break;
+ case 3:
+ REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 0);
+ REG_UPDATE_2(DSCCLK3_DTO_PARAM,
+ DSCCLK3_DTO_PHASE, 0,
+ DSCCLK3_DTO_MODULO, 1);
+ break;
+ default:
+ return;
+ }
+}
+
+static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ switch (link_enc_inst) {
+ case 0:
+ REG_UPDATE(SYMCLKA_CLOCK_ENABLE,
+ SYMCLKA_CLOCK_ENABLE, 1);
+ break;
+ case 1:
+ REG_UPDATE(SYMCLKB_CLOCK_ENABLE,
+ SYMCLKB_CLOCK_ENABLE, 1);
+ break;
+ case 2:
+ REG_UPDATE(SYMCLKC_CLOCK_ENABLE,
+ SYMCLKC_CLOCK_ENABLE, 1);
+ break;
+ case 3:
+ REG_UPDATE(SYMCLKD_CLOCK_ENABLE,
+ SYMCLKD_CLOCK_ENABLE, 1);
+ break;
+ case 4:
+ REG_UPDATE(SYMCLKE_CLOCK_ENABLE,
+ SYMCLKE_CLOCK_ENABLE, 1);
+ break;
+ }
+
+ switch (stream_enc_inst) {
+ case 0:
+ REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,
+ SYMCLKA_FE_EN, 1,
+ SYMCLKA_FE_SRC_SEL, link_enc_inst);
+ break;
+ case 1:
+ REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,
+ SYMCLKB_FE_EN, 1,
+ SYMCLKB_FE_SRC_SEL, link_enc_inst);
+ break;
+ case 2:
+ REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,
+ SYMCLKC_FE_EN, 1,
+ SYMCLKC_FE_SRC_SEL, link_enc_inst);
+ break;
+ case 3:
+ REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,
+ SYMCLKD_FE_EN, 1,
+ SYMCLKD_FE_SRC_SEL, link_enc_inst);
+ break;
+ case 4:
+ REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE,
+ SYMCLKE_FE_EN, 1,
+ SYMCLKE_FE_SRC_SEL, link_enc_inst);
+ break;
+ }
+}
+
+/*get other front end connected to this backend*/
+static uint8_t dccg35_get_other_enabled_symclk_fe(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
+{
+ uint8_t num_enabled_symclk_fe = 0;
+ uint32_t be_clk_en = 0, fe_clk_en[5] = {0}, be_clk_sel[5] = {0};
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ switch (link_enc_inst) {
+ case 0:
+ REG_GET_3(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, &be_clk_en,
+ SYMCLKA_FE_EN, &fe_clk_en[0],
+ SYMCLKA_FE_SRC_SEL, &be_clk_sel[0]);
+ break;
+ case 1:
+ REG_GET_3(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, &be_clk_en,
+ SYMCLKB_FE_EN, &fe_clk_en[1],
+ SYMCLKB_FE_SRC_SEL, &be_clk_sel[1]);
+ break;
+ case 2:
+ REG_GET_3(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, &be_clk_en,
+ SYMCLKC_FE_EN, &fe_clk_en[2],
+ SYMCLKC_FE_SRC_SEL, &be_clk_sel[2]);
+ break;
+ case 3:
+ REG_GET_3(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, &be_clk_en,
+ SYMCLKD_FE_EN, &fe_clk_en[3],
+ SYMCLKD_FE_SRC_SEL, &be_clk_sel[3]);
+ break;
+ case 4:
+ REG_GET_3(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, &be_clk_en,
+ SYMCLKE_FE_EN, &fe_clk_en[4],
+ SYMCLKE_FE_SRC_SEL, &be_clk_sel[4]);
+ break;
+ }
+ if (be_clk_en) {
+ /* for DPMST, this backend could be used by multiple front end.
+ only disable the backend if this stream_enc_ins is the last active stream enc connected to this back_end*/
+ uint8_t i;
+ for (i = 0; i != link_enc_inst && i < sizeof(fe_clk_en); i++) {
+ if (fe_clk_en[i] && be_clk_sel[i] == link_enc_inst)
+ num_enabled_symclk_fe++;
+ }
+ }
+ return num_enabled_symclk_fe;
+}
+
+static void dccg35_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
+{
+ uint8_t num_enabled_symclk_fe = 0;
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ switch (stream_enc_inst) {
+ case 0:
+ REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,
+ SYMCLKA_FE_EN, 0,
+ SYMCLKA_FE_SRC_SEL, 0);
+ break;
+ case 1:
+ REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,
+ SYMCLKB_FE_EN, 0,
+ SYMCLKB_FE_SRC_SEL, 0);
+ break;
+ case 2:
+ REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,
+ SYMCLKC_FE_EN, 0,
+ SYMCLKC_FE_SRC_SEL, 0);
+ break;
+ case 3:
+ REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,
+ SYMCLKD_FE_EN, 0,
+ SYMCLKD_FE_SRC_SEL, 0);
+ break;
+ case 4:
+ REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE,
+ SYMCLKE_FE_EN, 0,
+ SYMCLKE_FE_SRC_SEL, 0);
+ break;
+ }
+
+ /*check other enabled symclk fe */
+ num_enabled_symclk_fe = dccg35_get_other_enabled_symclk_fe(dccg, stream_enc_inst, link_enc_inst);
+ /*only turn off backend clk if other front end attachecd to this backend are all off,
+ for mst, only turn off the backend if this is the last front end*/
+ if (num_enabled_symclk_fe == 0) {
+ switch (link_enc_inst) {
+ case 0:
+ REG_UPDATE(SYMCLKA_CLOCK_ENABLE,
+ SYMCLKA_CLOCK_ENABLE, 0);
+ break;
+ case 1:
+ REG_UPDATE(SYMCLKB_CLOCK_ENABLE,
+ SYMCLKB_CLOCK_ENABLE, 0);
+ break;
+ case 2:
+ REG_UPDATE(SYMCLKC_CLOCK_ENABLE,
+ SYMCLKC_CLOCK_ENABLE, 0);
+ break;
+ case 3:
+ REG_UPDATE(SYMCLKD_CLOCK_ENABLE,
+ SYMCLKD_CLOCK_ENABLE, 0);
+ break;
+ case 4:
+ REG_UPDATE(SYMCLKE_CLOCK_ENABLE,
+ SYMCLKE_CLOCK_ENABLE, 0);
+ break;
+ }
+ }
+}
+
+static const struct dccg_funcs dccg35_funcs = {
+ .update_dpp_dto = dccg35_update_dpp_dto,
+ .dpp_root_clock_control = dccg35_dpp_root_clock_control,
+ .get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
+ .dccg_init = dccg35_init,
+ .set_dpstreamclk = dccg35_set_dpstreamclk,
+ .enable_symclk32_se = dccg31_enable_symclk32_se,
+ .disable_symclk32_se = dccg31_disable_symclk32_se,
+ .enable_symclk32_le = dccg31_enable_symclk32_le,
+ .disable_symclk32_le = dccg31_disable_symclk32_le,
+ .set_symclk32_le_root_clock_gating = dccg31_set_symclk32_le_root_clock_gating,
+ .set_physymclk = dccg35_set_physymclk,
+ .set_physymclk_root_clock_gating = dccg35_set_physymclk_root_clock_gating,
+ .set_dtbclk_dto = dccg35_set_dtbclk_dto,
+ .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
+ .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
+ .otg_add_pixel = dccg31_otg_add_pixel,
+ .otg_drop_pixel = dccg31_otg_drop_pixel,
+ .set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
+ .disable_dsc = dccg35_disable_dscclk,
+ .enable_dsc = dccg35_enable_dscclk,
+ .set_pixel_rate_div = dccg35_set_pixel_rate_div,
+ .set_valid_pixel_rate = dccg35_set_valid_pixel_rate,
+ .enable_symclk_se = dccg35_enable_symclk_se,
+ .disable_symclk_se = dccg35_disable_symclk_se,
+ .set_dtbclk_p_src = dccg35_set_dtbclk_p_src,
+};
+
+struct dccg *dccg35_create(
+ struct dc_context *ctx,
+ const struct dccg_registers *regs,
+ const struct dccg_shift *dccg_shift,
+ const struct dccg_mask *dccg_mask)
+{
+ struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
+ struct dccg *base;
+
+ if (dccg_dcn == NULL) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+ base = &dccg_dcn->base;
+ base->ctx = ctx;
+ base->funcs = &dccg35_funcs;
+
+ dccg_dcn->regs = regs;
+ dccg_dcn->dccg_shift = dccg_shift;
+ dccg_dcn->dccg_mask = dccg_mask;
+
+ return &dccg_dcn->base;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h
new file mode 100644
index 000000000000..423feb4c2f3f
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h
@@ -0,0 +1,190 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __DCN35_DCCG_H__
+#define __DCN35_DCCG_H__
+
+#include "dcn314/dcn314_dccg.h"
+
+#define DCCG_SFII(block, reg_name, field_prefix, field_name, inst, post_fix)\
+ .field_prefix ## _ ## field_name[inst] = block ## inst ## _ ## reg_name ## __ ## field_prefix ## inst ## _ ## field_name ## post_fix
+
+
+#define DCCG_REG_LIST_DCN35() \
+ DCCG_REG_LIST_DCN314(),\
+ SR(DPPCLK_CTRL),\
+ SR(DCCG_GATE_DISABLE_CNTL6),\
+ SR(DCCG_GLOBAL_FGCG_REP_CNTL),\
+ SR(SYMCLKA_CLOCK_ENABLE),\
+ SR(SYMCLKB_CLOCK_ENABLE),\
+ SR(SYMCLKC_CLOCK_ENABLE),\
+ SR(SYMCLKD_CLOCK_ENABLE),\
+ SR(SYMCLKE_CLOCK_ENABLE)
+
+#define DCCG_MASK_SH_LIST_DCN35(mask_sh) \
+ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 0, mask_sh),\
+ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 1, mask_sh),\
+ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 2, mask_sh),\
+ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 3, mask_sh),\
+ DCCG_SF(DPPCLK_CTRL, DPPCLK0_EN, mask_sh),\
+ DCCG_SF(DPPCLK_CTRL, DPPCLK1_EN, mask_sh),\
+ DCCG_SF(DPPCLK_CTRL, DPPCLK2_EN, mask_sh),\
+ DCCG_SF(DPPCLK_CTRL, DPPCLK3_EN, mask_sh),\
+ DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_PHASE, mask_sh),\
+ DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_MODULO, mask_sh),\
+ DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_EN, mask_sh),\
+ DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_SRC_SEL, mask_sh),\
+ DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_EN, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_SRC_SEL, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_SRC_SEL, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_SRC_SEL, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_SRC_SEL, mask_sh),\
+ DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_EN, mask_sh),\
+ DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_SRC_SEL, mask_sh),\
+ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK0_EN, mask_sh),\
+ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK1_EN, mask_sh),\
+ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK2_EN, mask_sh),\
+ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK3_EN, mask_sh),\
+ DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_PHASE, mask_sh),\
+ DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_MODULO, mask_sh),\
+ DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_PHASE, mask_sh),\
+ DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_MODULO, mask_sh),\
+ DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_PHASE, mask_sh),\
+ DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_MODULO, mask_sh),\
+ DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_PHASE, mask_sh),\
+ DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_MODULO, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_EN, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_EN, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_EN, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_EN, mask_sh),\
+ DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE0_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE1_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE0_EN, mask_sh),\
+ DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE1_EN, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, DTBCLK_DTO, ENABLE, 0, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, DTBCLK_DTO, ENABLE, 1, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, DTBCLK_DTO, ENABLE, 2, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, DTBCLK_DTO, ENABLE, 3, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, DTBCLKDTO, ENABLE_STATUS, 0, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, DTBCLKDTO, ENABLE_STATUS, 1, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, DTBCLKDTO, ENABLE_STATUS, 2, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, DTBCLKDTO, ENABLE_STATUS, 3, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 0, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 1, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 2, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 3, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, ADD_PIXEL, 0, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, ADD_PIXEL, 1, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, ADD_PIXEL, 2, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, ADD_PIXEL, 3, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG0_PIXEL_RATE_DIVK1, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG0_PIXEL_RATE_DIVK2, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG1_PIXEL_RATE_DIVK1, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG1_PIXEL_RATE_DIVK2, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG2_PIXEL_RATE_DIVK1, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG2_PIXEL_RATE_DIVK2, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG3_PIXEL_RATE_DIVK1, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG3_PIXEL_RATE_DIVK2, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG3_PIXEL_RATE_DIVK2, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, DROP_PIXEL, 0, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, DROP_PIXEL, 1, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, DROP_PIXEL, 2, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, DROP_PIXEL, 3, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P0_SRC_SEL, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P0_EN, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P1_SRC_SEL, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P1_EN, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P2_SRC_SEL, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P2_EN, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_SRC_SEL, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_EN, mask_sh),\
+ DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\
+ DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\
+ DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh),\
+ DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, mask_sh),\
+ DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, mask_sh),\
+ DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, mask_sh),\
+ DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, mask_sh),\
+ DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, mask_sh),\
+ DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, mask_sh),\
+ DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, mask_sh),\
+ DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, mask_sh),\
+ DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, mask_sh),\
+ DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, mask_sh),\
+ DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, mask_sh),\
+ DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, mask_sh),\
+ DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, mask_sh)
+
+struct dccg *dccg35_create(
+ struct dc_context *ctx,
+ const struct dccg_registers *regs,
+ const struct dccg_shift *dccg_shift,
+ const struct dccg_mask *dccg_mask);
+
+void dccg35_init(struct dccg *dccg);
+
+void dccg35_enable_global_fgcg_rep(struct dccg *dccg, bool value);
+
+
+#endif //__DCN35_DCCG_H__
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c
new file mode 100644
index 000000000000..f91e08895275
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c
@@ -0,0 +1,267 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "reg_helper.h"
+
+#include "core_types.h"
+#include "link_encoder.h"
+#include "dcn31/dcn31_dio_link_encoder.h"
+#include "dcn35_dio_link_encoder.h"
+#define CTX \
+ enc10->base.ctx
+#define DC_LOGGER \
+ enc10->base.ctx->logger
+
+#define REG(reg)\
+ (enc10->link_regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+ enc10->link_shift->field_name, enc10->link_mask->field_name
+/*
+ * @brief
+ * Trigger Source Select
+ * ASIC-dependent, actual values for register programming
+ */
+#define DCN35_DIG_FE_SOURCE_SELECT_INVALID 0x0
+#define DCN35_DIG_FE_SOURCE_SELECT_DIGA 0x1
+#define DCN35_DIG_FE_SOURCE_SELECT_DIGB 0x2
+#define DCN35_DIG_FE_SOURCE_SELECT_DIGC 0x4
+#define DCN35_DIG_FE_SOURCE_SELECT_DIGD 0x08
+#define DCN35_DIG_FE_SOURCE_SELECT_DIGE 0x10
+
+
+bool dcn35_is_dig_enabled(struct link_encoder *enc)
+{
+ uint32_t enabled;
+ struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+
+ REG_GET(DIG_BE_CLK_CNTL, DIG_BE_CLK_EN, &enabled);
+ return (enabled == 1);
+}
+
+enum signal_type dcn35_get_dig_mode(
+ struct link_encoder *enc)
+{
+ uint32_t value;
+ struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+
+ REG_GET(DIG_BE_CLK_CNTL, DIG_BE_MODE, &value);
+ switch (value) {
+ case 0:
+ return SIGNAL_TYPE_DISPLAY_PORT;
+ case 2:
+ return SIGNAL_TYPE_DVI_SINGLE_LINK;
+ case 3:
+ return SIGNAL_TYPE_HDMI_TYPE_A;
+ case 5:
+ return SIGNAL_TYPE_DISPLAY_PORT_MST;
+ default:
+ return SIGNAL_TYPE_NONE;
+ }
+ return SIGNAL_TYPE_NONE;
+}
+
+void dcn35_link_encoder_setup(
+ struct link_encoder *enc,
+ enum signal_type signal)
+{
+ struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+
+ switch (signal) {
+ case SIGNAL_TYPE_EDP:
+ case SIGNAL_TYPE_DISPLAY_PORT:
+ /* DP SST */
+ REG_UPDATE(DIG_BE_CLK_CNTL, DIG_BE_MODE, 0);
+ break;
+ case SIGNAL_TYPE_DVI_SINGLE_LINK:
+ case SIGNAL_TYPE_DVI_DUAL_LINK:
+ /* TMDS-DVI */
+ REG_UPDATE(DIG_BE_CLK_CNTL, DIG_BE_MODE, 2);
+ break;
+ case SIGNAL_TYPE_HDMI_TYPE_A:
+ /* TMDS-HDMI */
+ REG_UPDATE(DIG_BE_CLK_CNTL, DIG_BE_MODE, 3);
+ break;
+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
+ /* DP MST */
+ REG_UPDATE(DIG_BE_CLK_CNTL, DIG_BE_MODE, 5);
+ break;
+ default:
+ ASSERT_CRITICAL(false);
+ /* invalid mode ! */
+ break;
+ }
+ REG_UPDATE(DIG_BE_CLK_CNTL, DIG_BE_CLK_EN, 1);
+
+}
+
+void dcn35_link_encoder_init(struct link_encoder *enc)
+{
+ enc32_hw_init(enc);
+ dcn35_link_encoder_set_fgcg(enc, enc->ctx->dc->debug.enable_fine_grain_clock_gating.bits.dio);
+}
+
+void dcn35_link_encoder_set_fgcg(struct link_encoder *enc, bool enable)
+{
+ struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+
+ REG_UPDATE(DIO_CLK_CNTL, DIO_FGCG_REP_DIS, !enable);
+}
+
+static const struct link_encoder_funcs dcn35_link_enc_funcs = {
+ .read_state = link_enc2_read_state,
+ .validate_output_with_stream =
+ dcn30_link_encoder_validate_output_with_stream,
+ .hw_init = dcn35_link_encoder_init,
+ .setup = dcn35_link_encoder_setup,
+ .enable_tmds_output = dcn10_link_encoder_enable_tmds_output,
+ .enable_dp_output = dcn31_link_encoder_enable_dp_output,
+ .enable_dp_mst_output = dcn31_link_encoder_enable_dp_mst_output,
+ .disable_output = dcn31_link_encoder_disable_output,
+ .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings,
+ .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern,
+ .update_mst_stream_allocation_table =
+ dcn10_link_encoder_update_mst_stream_allocation_table,
+ .psr_program_dp_dphy_fast_training =
+ dcn10_psr_program_dp_dphy_fast_training,
+ .psr_program_secondary_packet = dcn10_psr_program_secondary_packet,
+ .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe,
+ .enable_hpd = dcn10_link_encoder_enable_hpd,
+ .disable_hpd = dcn10_link_encoder_disable_hpd,
+ .is_dig_enabled = dcn35_is_dig_enabled,
+ .destroy = dcn10_link_encoder_destroy,
+ .fec_set_enable = enc2_fec_set_enable,
+ .fec_set_ready = enc2_fec_set_ready,
+ .fec_is_active = enc2_fec_is_active,
+ .get_dig_frontend = dcn10_get_dig_frontend,
+ .get_dig_mode = dcn35_get_dig_mode,
+ .is_in_alt_mode = dcn31_link_encoder_is_in_alt_mode,
+ .get_max_link_cap = dcn31_link_encoder_get_max_link_cap,
+ .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+};
+
+void dcn35_link_encoder_construct(
+ struct dcn20_link_encoder *enc20,
+ const struct encoder_init_data *init_data,
+ const struct encoder_feature_support *enc_features,
+ const struct dcn10_link_enc_registers *link_regs,
+ const struct dcn10_link_enc_aux_registers *aux_regs,
+ const struct dcn10_link_enc_hpd_registers *hpd_regs,
+ const struct dcn10_link_enc_shift *link_shift,
+ const struct dcn10_link_enc_mask *link_mask)
+{
+ struct bp_connector_speed_cap_info bp_cap_info = {0};
+ const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
+ enum bp_result result = BP_RESULT_OK;
+ struct dcn10_link_encoder *enc10 = &enc20->enc10;
+
+ enc10->base.funcs = &dcn35_link_enc_funcs;
+ enc10->base.ctx = init_data->ctx;
+ enc10->base.id = init_data->encoder;
+
+ 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;
+
+ enc10->base.features = *enc_features;
+
+ enc10->base.transmitter = init_data->transmitter;
+
+ /* set the flag to indicate whether driver poll the I2C data pin
+ * while doing the DP sink detect
+ */
+
+/* if (dal_adapter_service_is_feature_supported(as,
+ * FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))
+ * enc10->base.features.flags.bits.
+ * DP_SINK_DETECT_POLL_DATA_PIN = true;
+ */
+
+ enc10->base.output_signals =
+ SIGNAL_TYPE_DVI_SINGLE_LINK |
+ SIGNAL_TYPE_DVI_DUAL_LINK |
+ SIGNAL_TYPE_LVDS |
+ SIGNAL_TYPE_DISPLAY_PORT |
+ SIGNAL_TYPE_DISPLAY_PORT_MST |
+ SIGNAL_TYPE_EDP |
+ SIGNAL_TYPE_HDMI_TYPE_A;
+
+ enc10->link_regs = link_regs;
+ enc10->aux_regs = aux_regs;
+ enc10->hpd_regs = hpd_regs;
+ enc10->link_shift = link_shift;
+ enc10->link_mask = link_mask;
+
+ switch (enc10->base.transmitter) {
+ case TRANSMITTER_UNIPHY_A:
+ enc10->base.preferred_engine = ENGINE_ID_DIGA;
+ break;
+ case TRANSMITTER_UNIPHY_B:
+ enc10->base.preferred_engine = ENGINE_ID_DIGB;
+ break;
+ case TRANSMITTER_UNIPHY_C:
+ enc10->base.preferred_engine = ENGINE_ID_DIGC;
+ break;
+ case TRANSMITTER_UNIPHY_D:
+ enc10->base.preferred_engine = ENGINE_ID_DIGD;
+ break;
+ case TRANSMITTER_UNIPHY_E:
+ enc10->base.preferred_engine = ENGINE_ID_DIGE;
+ break;
+ default:
+ ASSERT_CRITICAL(false);
+ enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
+ }
+
+ enc10->base.features.flags.bits.HDMI_6GB_EN = 1;
+
+ if (bp_funcs->get_connector_speed_cap_info)
+ result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios,
+ enc10->base.connector, &bp_cap_info);
+
+ /* Override features with DCE-specific values */
+ if (result == BP_RESULT_OK) {
+ enc10->base.features.flags.bits.IS_HBR2_CAPABLE =
+ bp_cap_info.DP_HBR2_EN;
+ enc10->base.features.flags.bits.IS_HBR3_CAPABLE =
+ bp_cap_info.DP_HBR3_EN;
+ enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;
+ enc10->base.features.flags.bits.IS_DP2_CAPABLE = 1;
+ enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN;
+ enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN;
+ enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN;
+
+ } else {
+ DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
+ __func__,
+ result);
+ }
+ if (enc10->base.ctx->dc->debug.hdmi20_disable)
+ enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.h
new file mode 100644
index 000000000000..e1e560732a9d
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.h
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __DC_LINK_ENCODER__DCN35_H__
+#define __DC_LINK_ENCODER__DCN35_H__
+
+#include "dcn32/dcn32_dio_link_encoder.h"
+#include "dcn30/dcn30_dio_link_encoder.h"
+#include "dcn31/dcn31_dio_link_encoder.h"
+
+#define LINK_ENCODER_MASK_SH_LIST_DCN35(mask_sh) \
+ LE_SF(DIG0_DIG_BE_EN_CNTL, DIG_BE_ENABLE, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CNTL, DIG_RB_SWITCH_EN, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CNTL, DIG_HPD_SELECT, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_MODE, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_CLK_EN, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SOFT_RESET, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_CLOCK_ON, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_TMDS_CLOCK_ON, mask_sh),\
+ LE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\
+ LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_BYPASS, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE0, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE1, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE2, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE3, mask_sh),\
+ LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, mask_sh),\
+ LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM1, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM2, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM3, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM4, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM5, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM6, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM7, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM8, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, mask_sh),\
+ LE_SF(DP0_DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, mask_sh),\
+ LE_SF(DP0_DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, mask_sh),\
+ LE_SF(DP0_DP_DPHY_TRAINING_PATTERN_SEL, DPHY_TRAINING_PATTERN_SEL, mask_sh),\
+ LE_SF(DP0_DP_DPHY_HBR2_PATTERN_CONTROL, DP_DPHY_HBR2_PATTERN_CONTROL, mask_sh),\
+ LE_SF(DP0_DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, mask_sh),\
+ LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL, mask_sh),\
+ LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE, mask_sh),\
+ LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE, mask_sh),\
+ LE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\
+ LE_SF(DP0_DP_CONFIG, DP_UDI_LANES, mask_sh),\
+ LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_LINE_NUM, mask_sh),\
+ LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_PRIORITY, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC0, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC1, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT0, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT1, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC2, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC3, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT2, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT3, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_SAT_UPDATE, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_16_MTP_KEEPOUT, mask_sh),\
+ LE_SF(DP_AUX0_AUX_CONTROL, AUX_HPD_SEL, mask_sh),\
+ LE_SF(DP_AUX0_AUX_CONTROL, AUX_LS_READ_EN, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW, mask_sh),\
+ LE_SF(HPD0_DC_HPD_CONTROL, DC_HPD_EN, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\
+ LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \
+ LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh),\
+ LE_SF(DIO_LINKA_CNTL, ENC_TYPE_SEL, mask_sh),\
+ LE_SF(DIO_LINKA_CNTL, HPO_DP_ENC_SEL, mask_sh),\
+ LE_SF(DIO_LINKA_CNTL, HPO_HDMI_ENC_SEL, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, DISPCLK_R_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, DISPCLK_G_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, REFCLK_R_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, REFCLK_G_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SOCCLK_G_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLK_FE_R_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLK_FE_G_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLK_R_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLK_G_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, DIO_FGCG_REP_DIS, mask_sh)
+
+
+void dcn35_link_encoder_construct(
+ struct dcn20_link_encoder *enc20,
+ const struct encoder_init_data *init_data,
+ const struct encoder_feature_support *enc_features,
+ const struct dcn10_link_enc_registers *link_regs,
+ const struct dcn10_link_enc_aux_registers *aux_regs,
+ const struct dcn10_link_enc_hpd_registers *hpd_regs,
+ const struct dcn10_link_enc_shift *link_shift,
+ const struct dcn10_link_enc_mask *link_mask);
+
+void dcn35_link_encoder_init(struct link_encoder *enc);
+void dcn35_link_encoder_set_fgcg(struct link_encoder *enc, bool enabled);
+bool dcn35_is_dig_enabled(struct link_encoder *enc);
+
+enum signal_type dcn35_get_dig_mode(struct link_encoder *enc);
+void dcn35_link_encoder_setup(struct link_encoder *enc, enum signal_type signal);
+
+#endif /* __DC_LINK_ENCODER__DCN35_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.c
new file mode 100644
index 000000000000..62a8f0b56006
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.c
@@ -0,0 +1,526 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+
+#include "dc_bios_types.h"
+#include "dcn30/dcn30_dio_stream_encoder.h"
+#include "dcn314/dcn314_dio_stream_encoder.h"
+#include "dcn32/dcn32_dio_stream_encoder.h"
+#include "dcn35_dio_stream_encoder.h"
+#include "reg_helper.h"
+#include "hw_shared.h"
+#include "link.h"
+#include "dpcd_defs.h"
+
+#define DC_LOGGER \
+ enc1->base.ctx->logger
+
+#define REG(reg)\
+ (enc1->regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+ enc1->se_shift->field_name, enc1->se_mask->field_name
+
+#define VBI_LINE_0 0
+#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000
+
+#define CTX \
+ enc1->base.ctx
+/* setup stream encoder in dvi mode */
+static void enc35_stream_encoder_dvi_set_stream_attribute(
+ struct stream_encoder *enc,
+ struct dc_crtc_timing *crtc_timing,
+ bool is_dual_link)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ if (!enc->ctx->dc->debug.avoid_vbios_exec_table) {
+ struct bp_encoder_control cntl = {0};
+
+ cntl.action = ENCODER_CONTROL_SETUP;
+ cntl.engine_id = enc1->base.id;
+ cntl.signal = is_dual_link ?
+ SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK;
+ cntl.enable_dp_audio = false;
+ cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10;
+ cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR;
+
+ if (enc1->base.bp->funcs->encoder_control(
+ enc1->base.bp, &cntl) != BP_RESULT_OK)
+ return;
+
+ } else {
+
+ //Set pattern for clock channel, default vlue 0x63 does not work
+ REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F);
+
+ //DIG_BE_TMDS_DVI_MODE : TMDS-DVI mode is already set in link_encoder_setup
+
+ //DIG_SOURCE_SELECT is already set in dig_connect_to_otg
+
+ /* DIG_START is removed from the register spec */
+ }
+
+ ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB);
+ ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888);
+ enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing);
+}
+/* setup stream encoder in hdmi mode */
+static void enc35_stream_encoder_hdmi_set_stream_attribute(
+ struct stream_encoder *enc,
+ struct dc_crtc_timing *crtc_timing,
+ int actual_pix_clk_khz,
+ bool enable_audio)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ if (!enc->ctx->dc->debug.avoid_vbios_exec_table) {
+ struct bp_encoder_control cntl = {0};
+
+ cntl.action = ENCODER_CONTROL_SETUP;
+ cntl.engine_id = enc1->base.id;
+ cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A;
+ cntl.enable_dp_audio = enable_audio;
+ cntl.pixel_clock = actual_pix_clk_khz;
+ cntl.lanes_number = LANE_COUNT_FOUR;
+
+ if (enc1->base.bp->funcs->encoder_control(
+ enc1->base.bp, &cntl) != BP_RESULT_OK)
+ return;
+
+ } else {
+
+ //Set pattern for clock channel, default vlue 0x63 does not work
+ REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F);
+
+ //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup
+
+ //DIG_SOURCE_SELECT is already set in dig_connect_to_otg
+
+ /* DIG_START is removed from the register spec */
+ enc314_enable_fifo(enc);
+ }
+
+ /* Configure pixel encoding */
+ enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing);
+
+ /* setup HDMI engine */
+ REG_UPDATE_6(HDMI_CONTROL,
+ HDMI_PACKET_GEN_VERSION, 1,
+ HDMI_KEEPOUT_MODE, 1,
+ HDMI_DEEP_COLOR_ENABLE, 0,
+ HDMI_DATA_SCRAMBLE_EN, 0,
+ HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1,
+ HDMI_CLOCK_CHANNEL_RATE, 0);
+
+ /* Configure color depth */
+ switch (crtc_timing->display_color_depth) {
+ case COLOR_DEPTH_888:
+ REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0);
+ break;
+ case COLOR_DEPTH_101010:
+ if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DEEP_COLOR_DEPTH, 1,
+ HDMI_DEEP_COLOR_ENABLE, 0);
+ } else {
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DEEP_COLOR_DEPTH, 1,
+ HDMI_DEEP_COLOR_ENABLE, 1);
+ }
+ break;
+ case COLOR_DEPTH_121212:
+ if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DEEP_COLOR_DEPTH, 2,
+ HDMI_DEEP_COLOR_ENABLE, 0);
+ } else {
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DEEP_COLOR_DEPTH, 2,
+ HDMI_DEEP_COLOR_ENABLE, 1);
+ }
+ break;
+ case COLOR_DEPTH_161616:
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DEEP_COLOR_DEPTH, 3,
+ HDMI_DEEP_COLOR_ENABLE, 1);
+ break;
+ default:
+ break;
+ }
+
+ if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) {
+ /* enable HDMI data scrambler
+ * HDMI_CLOCK_CHANNEL_RATE_MORE_340M
+ * Clock channel frequency is 1/4 of character rate.
+ */
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DATA_SCRAMBLE_EN, 1,
+ HDMI_CLOCK_CHANNEL_RATE, 1);
+ } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) {
+
+ /* TODO: New feature for DCE11, still need to implement */
+
+ /* enable HDMI data scrambler
+ * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE
+ * Clock channel frequency is the same
+ * as character rate
+ */
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DATA_SCRAMBLE_EN, 1,
+ HDMI_CLOCK_CHANNEL_RATE, 0);
+ }
+
+
+ /* Enable transmission of General Control packet on every frame */
+ REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL,
+ HDMI_GC_CONT, 1,
+ HDMI_GC_SEND, 1,
+ HDMI_NULL_SEND, 1);
+
+ /* Disable Audio Content Protection packet transmission */
+ REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0);
+
+ /* following belongs to audio */
+ /* Enable Audio InfoFrame packet transmission. */
+ REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1);
+
+ /* update double-buffered AUDIO_INFO registers immediately */
+ ASSERT(enc->afmt);
+ enc->afmt->funcs->audio_info_immediate_update(enc->afmt);
+
+ /* Select line number on which to send Audio InfoFrame packets */
+ REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE,
+ VBI_LINE_0 + 2);
+
+ /* set HDMI GC AVMUTE */
+ REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0);
+ switch (crtc_timing->pixel_encoding) {
+ case PIXEL_ENCODING_YCBCR422:
+ REG_UPDATE(HDMI_CONTROL, TMDS_PIXEL_ENCODING, 1);
+ break;
+ default:
+ REG_UPDATE(HDMI_CONTROL, TMDS_PIXEL_ENCODING, 0);
+ break;
+ }
+ REG_UPDATE(HDMI_CONTROL, TMDS_COLOR_FORMAT, 0);
+}
+
+
+
+static void enc35_stream_encoder_enable(
+ struct stream_encoder *enc,
+ enum signal_type signal,
+ bool enable)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ if (enable) {
+ switch (signal) {
+ case SIGNAL_TYPE_DVI_SINGLE_LINK:
+ case SIGNAL_TYPE_DVI_DUAL_LINK:
+ /* TMDS-DVI */
+ REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_MODE, 2);
+ break;
+ case SIGNAL_TYPE_HDMI_TYPE_A:
+ /* TMDS-HDMI */
+ REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_MODE, 3);
+ break;
+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
+ /* DP MST */
+ REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_MODE, 5);
+ break;
+ case SIGNAL_TYPE_EDP:
+ case SIGNAL_TYPE_DISPLAY_PORT:
+ /* DP SST */
+ REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_MODE, 0);
+ break;
+ default:
+ /* invalid mode ! */
+ ASSERT_CRITICAL(false);
+ }
+ }
+}
+
+static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
+{
+ bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420;
+
+ two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
+ && !timing->dsc_cfg.ycbcr422_simple);
+ return two_pix;
+}
+
+static bool is_h_timing_divisible_by_2(const struct dc_crtc_timing *timing)
+{
+ /* math borrowed from function of same name in inc/resource
+ * checks if h_timing is divisible by 2
+ */
+
+ bool divisible = false;
+ uint16_t h_blank_start = 0;
+ uint16_t h_blank_end = 0;
+
+ if (timing) {
+ h_blank_start = timing->h_total - timing->h_front_porch;
+ h_blank_end = h_blank_start - timing->h_addressable;
+
+ /* HTOTAL, Hblank start/end, and Hsync start/end all must be
+ * divisible by 2 in order for the horizontal timing params
+ * to be considered divisible by 2. Hsync start is always 0.
+ */
+ divisible = (timing->h_total % 2 == 0) &&
+ (h_blank_start % 2 == 0) &&
+ (h_blank_end % 2 == 0) &&
+ (timing->h_sync_width % 2 == 0);
+ }
+ return divisible;
+}
+
+static bool is_dp_dig_pixel_rate_div_policy(struct dc *dc, const struct dc_crtc_timing *timing)
+{
+ /* should be functionally the same as dcn32_is_dp_dig_pixel_rate_div_policy for DP encoders*/
+ return is_h_timing_divisible_by_2(timing) &&
+ dc->debug.enable_dp_dig_pixel_rate_div_policy;
+}
+
+static void enc35_stream_encoder_dp_unblank(
+ struct dc_link *link,
+ struct stream_encoder *enc,
+ const struct encoder_unblank_param *param)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+ struct dc *dc = enc->ctx->dc;
+
+ if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
+ uint32_t n_vid = 0x8000;
+ uint32_t m_vid;
+ uint32_t n_multiply = 0;
+ uint32_t pix_per_cycle = 0;
+ uint64_t m_vid_l = n_vid;
+
+ /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */
+ if (is_two_pixels_per_containter(&param->timing) || param->opp_cnt > 1
+ || is_dp_dig_pixel_rate_div_policy(dc, &param->timing)) {
+ /*this logic should be the same in get_pixel_clock_parameters() */
+ n_multiply = 1;
+ pix_per_cycle = 1;
+ }
+ /* M / N = Fstream / Flink
+ * m_vid / n_vid = pixel rate / link rate
+ */
+
+ m_vid_l *= param->timing.pix_clk_100hz / 10;
+ m_vid_l = div_u64(m_vid_l,
+ param->link_settings.link_rate
+ * LINK_RATE_REF_FREQ_IN_KHZ);
+
+ m_vid = (uint32_t) m_vid_l;
+
+ /* enable auto measurement */
+
+ REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0);
+
+ /* auto measurement need 1 full 0x8000 symbol cycle to kick in,
+ * therefore program initial value for Mvid and Nvid
+ */
+
+ REG_UPDATE(DP_VID_N, DP_VID_N, n_vid);
+
+ REG_UPDATE(DP_VID_M, DP_VID_M, m_vid);
+
+ REG_UPDATE_2(DP_VID_TIMING,
+ DP_VID_M_N_GEN_EN, 1,
+ DP_VID_N_MUL, n_multiply);
+
+ REG_UPDATE(DP_PIXEL_FORMAT,
+ DP_PIXEL_PER_CYCLE_PROCESSING_MODE,
+ pix_per_cycle);
+ }
+
+ /* make sure stream is disabled before resetting steer fifo */
+ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false);
+ REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000);
+
+ /* DIG_START is removed from the register spec */
+
+ /* switch DP encoder to CRTC data, but reset it the fifo first. It may happen
+ * that it overflows during mode transition, and sometimes doesn't recover.
+ */
+ REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1);
+ udelay(10);
+
+ REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
+
+ /* wait 100us for DIG/DP logic to prime
+ * (i.e. a few video lines)
+ */
+ udelay(100);
+
+ /* the hardware would start sending video at the start of the next DP
+ * frame (i.e. rising edge of the vblank).
+ * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this
+ * register has no effect on enable transition! HW always makes sure
+ * VID_STREAM enable at start of next frame, and this is not
+ * programmable
+ */
+
+ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true);
+
+ /*
+ * DIG Resync FIFO now needs to be explicitly enabled.
+ * This should come after DP_VID_STREAM_ENABLE per HW docs.
+ */
+ enc314_enable_fifo(enc);
+
+ link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM);
+}
+
+static void enc35_stream_encoder_map_to_link(
+ struct stream_encoder *enc,
+ uint32_t stream_enc_inst,
+ uint32_t link_enc_inst)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ ASSERT(stream_enc_inst < 5 && link_enc_inst < 5);
+ REG_UPDATE(STREAM_MAPPER_CONTROL,
+ DIG_STREAM_LINK_TARGET, link_enc_inst);
+}
+
+static void enc35_reset_fifo(struct stream_encoder *enc, bool reset)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+ uint32_t reset_val = reset ? 1 : 0;
+ uint32_t is_symclk_on;
+
+ REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, reset_val);
+ REG_GET(DIG_FE_CLK_CNTL, DIG_FE_SYMCLK_FE_G_CLOCK_ON, &is_symclk_on);
+
+ if (is_symclk_on)
+ REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, reset_val, 10, 5000);
+ else
+ udelay(10);
+}
+
+static void enc35_disable_fifo(struct stream_encoder *enc)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 0);
+ REG_UPDATE(DIG_FE_EN_CNTL, DIG_FE_ENABLE, 0);
+ REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, 0);
+}
+
+static void enc35_enable_fifo(struct stream_encoder *enc)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7);
+ REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, 1);
+ REG_UPDATE(DIG_FE_EN_CNTL, DIG_FE_ENABLE, 1);
+
+ enc35_reset_fifo(enc, true);
+ enc35_reset_fifo(enc, false);
+
+ REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 1);
+}
+
+static const struct stream_encoder_funcs dcn35_str_enc_funcs = {
+ .dp_set_odm_combine =
+ enc314_dp_set_odm_combine,
+ .dp_set_stream_attribute =
+ enc2_stream_encoder_dp_set_stream_attribute,
+ .hdmi_set_stream_attribute =
+ enc35_stream_encoder_hdmi_set_stream_attribute,
+ .dvi_set_stream_attribute =
+ enc35_stream_encoder_dvi_set_stream_attribute,
+ .set_throttled_vcp_size =
+ enc1_stream_encoder_set_throttled_vcp_size,
+ .update_hdmi_info_packets =
+ enc3_stream_encoder_update_hdmi_info_packets,
+ .stop_hdmi_info_packets =
+ enc3_stream_encoder_stop_hdmi_info_packets,
+ .update_dp_info_packets_sdp_line_num =
+ enc3_stream_encoder_update_dp_info_packets_sdp_line_num,
+ .update_dp_info_packets =
+ enc3_stream_encoder_update_dp_info_packets,
+ .stop_dp_info_packets =
+ enc1_stream_encoder_stop_dp_info_packets,
+ .dp_blank =
+ enc314_stream_encoder_dp_blank,
+ .dp_unblank =
+ enc35_stream_encoder_dp_unblank,
+ .audio_mute_control = enc3_audio_mute_control,
+
+ .dp_audio_setup = enc3_se_dp_audio_setup,
+ .dp_audio_enable = enc3_se_dp_audio_enable,
+ .dp_audio_disable = enc1_se_dp_audio_disable,
+
+ .hdmi_audio_setup = enc3_se_hdmi_audio_setup,
+ .hdmi_audio_disable = enc1_se_hdmi_audio_disable,
+ .setup_stereo_sync = enc1_setup_stereo_sync,
+ .set_avmute = enc1_stream_encoder_set_avmute,
+ .dig_connect_to_otg = enc1_dig_connect_to_otg,
+ .dig_source_otg = enc1_dig_source_otg,
+
+ .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format,
+
+ .enc_read_state = enc314_read_state,
+ .dp_set_dsc_config = enc314_dp_set_dsc_config,
+ .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet,
+ .set_dynamic_metadata = enc2_set_dynamic_metadata,
+ .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute,
+ .dig_stream_enable = enc35_stream_encoder_enable,
+
+ .set_input_mode = enc314_set_dig_input_mode,
+ .enable_fifo = enc35_enable_fifo,
+ .disable_fifo = enc35_disable_fifo,
+ .map_stream_to_link = enc35_stream_encoder_map_to_link,
+};
+
+void dcn35_dio_stream_encoder_construct(
+ struct dcn10_stream_encoder *enc1,
+ struct dc_context *ctx,
+ struct dc_bios *bp,
+ enum engine_id eng_id,
+ struct vpg *vpg,
+ struct afmt *afmt,
+ const struct dcn10_stream_enc_registers *regs,
+ const struct dcn10_stream_encoder_shift *se_shift,
+ const struct dcn10_stream_encoder_mask *se_mask)
+{
+ enc1->base.funcs = &dcn35_str_enc_funcs;
+ enc1->base.ctx = ctx;
+ enc1->base.id = eng_id;
+ enc1->base.bp = bp;
+ enc1->base.vpg = vpg;
+ enc1->base.afmt = afmt;
+ enc1->regs = regs;
+ enc1->se_shift = se_shift;
+ enc1->se_mask = se_mask;
+ enc1->base.stream_enc_inst = vpg->inst;
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.h
new file mode 100644
index 000000000000..1212fcee38f2
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.h
@@ -0,0 +1,326 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __DC_DIO_STREAM_ENCODER_DCN35_H__
+#define __DC_DIO_STREAM_ENCODER_DCN35_H__
+
+#include "dcn30/dcn30_vpg.h"
+#include "dcn30/dcn30_afmt.h"
+#include "stream_encoder.h"
+#include "dcn20/dcn20_stream_encoder.h"
+
+/* Register bit field name change */
+#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_GATE_DIS__SHIFT 0x8
+#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_EN__SHIFT 0x9
+#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_CLOCK_ON__SHIFT 0xa
+#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP__SHIFT 0xe
+#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_ORDER_INVERT__SHIFT 0xf
+
+#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_GATE_DIS_MASK 0x00000100L
+#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_EN_MASK 0x00000200L
+#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_CLOCK_ON_MASK 0x00000400L
+#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP_MASK 0x00004000L
+#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_ORDER_INVERT_MASK 0x00008000L
+
+
+#define SE_DCN35_REG_LIST(id)\
+ SRI(AFMT_CNTL, DIG, id), \
+ SRI(DIG_FE_CNTL, DIG, id), \
+ SRI(HDMI_CONTROL, DIG, id), \
+ SRI(HDMI_DB_CONTROL, DIG, id), \
+ SRI(HDMI_GC, DIG, id), \
+ SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \
+ SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \
+ SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \
+ SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \
+ SRI(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \
+ SRI(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \
+ SRI(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \
+ SRI(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \
+ SRI(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \
+ SRI(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \
+ SRI(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \
+ SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \
+ SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \
+ SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \
+ SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\
+ SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\
+ SRI(HDMI_ACR_32_0, DIG, id),\
+ SRI(HDMI_ACR_32_1, DIG, id),\
+ SRI(HDMI_ACR_44_0, DIG, id),\
+ SRI(HDMI_ACR_44_1, DIG, id),\
+ SRI(HDMI_ACR_48_0, DIG, id),\
+ SRI(HDMI_ACR_48_1, DIG, id),\
+ SRI(DP_DB_CNTL, DP, id), \
+ SRI(DP_MSA_MISC, DP, id), \
+ SRI(DP_MSA_VBID_MISC, DP, id), \
+ SRI(DP_MSA_COLORIMETRY, DP, id), \
+ SRI(DP_MSA_TIMING_PARAM1, DP, id), \
+ SRI(DP_MSA_TIMING_PARAM2, DP, id), \
+ SRI(DP_MSA_TIMING_PARAM3, DP, id), \
+ SRI(DP_MSA_TIMING_PARAM4, DP, id), \
+ SRI(DP_MSE_RATE_CNTL, DP, id), \
+ SRI(DP_MSE_RATE_UPDATE, DP, id), \
+ SRI(DP_PIXEL_FORMAT, DP, id), \
+ SRI(DP_SEC_CNTL, DP, id), \
+ SRI(DP_SEC_CNTL1, DP, id), \
+ SRI(DP_SEC_CNTL2, DP, id), \
+ SRI(DP_SEC_CNTL5, DP, id), \
+ SRI(DP_SEC_CNTL6, DP, id), \
+ SRI(DP_STEER_FIFO, DP, id), \
+ SRI(DP_VID_M, DP, id), \
+ SRI(DP_VID_N, DP, id), \
+ SRI(DP_VID_STREAM_CNTL, DP, id), \
+ SRI(DP_VID_TIMING, DP, id), \
+ SRI(DP_SEC_AUD_N, DP, id), \
+ SRI(DP_SEC_TIMESTAMP, DP, id), \
+ SRI(DP_DSC_CNTL, DP, id), \
+ SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \
+ SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \
+ SRI(DP_SEC_FRAMING4, DP, id), \
+ SRI(DP_GSP11_CNTL, DP, id), \
+ SRI(DME_CONTROL, DME, id),\
+ SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \
+ SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \
+ SRI(DIG_FE_CNTL, DIG, id), \
+ SRI(DIG_FE_EN_CNTL, DIG, id), \
+ SRI(DIG_FE_CLK_CNTL, DIG, id), \
+ SRI(DIG_CLOCK_PATTERN, DIG, id), \
+ SRI(DIG_FIFO_CTRL0, DIG, id),\
+ SRI(STREAM_MAPPER_CONTROL, DIG, id)
+
+
+#define SE_COMMON_MASK_SH_LIST_DCN35(mask_sh)\
+ SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\
+ SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\
+ SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_PER_CYCLE_PROCESSING_MODE, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\
+ SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\
+ SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\
+ SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\
+ SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\
+ SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\
+ SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\
+ SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\
+ SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\
+ SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\
+ SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\
+ SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\
+ SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\
+ SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\
+ SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, TMDS_PIXEL_ENCODING, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, TMDS_COLOR_FORMAT, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP11_PPS, mask_sh),\
+ SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, mask_sh),\
+ SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\
+ SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\
+ SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\
+ SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh), \
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC8_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC9_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC10_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC11_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC12_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC13_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL10, HDMI_GENERIC14_LINE, mask_sh),\
+ SE_SF(DP0_DP_DSC_CNTL, DP_DSC_MODE, mask_sh),\
+ SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\
+ SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\
+ SE_SF(DME0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\
+ SE_SF(DME0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\
+ SE_SF(DME0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\
+ SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\
+ SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\
+ SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\
+ SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, DOLBY_VISION_EN, mask_sh),\
+ SE_SF(DIG0_DIG_FE_EN_CNTL, DIG_FE_ENABLE, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_MODE, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_SOFT_RESET, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_DISPCLK_G_CLOCK_ON, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_SYMCLK_FE_G_CLOCK_ON, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_SYMCLK_FE_G_AFMT_CLOCK_ON, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_SYMCLK_FE_G_TMDS_CLOCK_ON, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_SOCCLK_G_AFMT_CLOCK_ON, mask_sh),\
+ SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh),\
+ SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\
+ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_MODE, mask_sh),\
+ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, mask_sh),\
+ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, mask_sh),\
+ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET, mask_sh),\
+ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh),\
+ SE_SF(DIG0_STREAM_MAPPER_CONTROL, DIG_STREAM_LINK_TARGET, mask_sh),
+
+void dcn35_dio_stream_encoder_construct(
+ struct dcn10_stream_encoder *enc1,
+ struct dc_context *ctx,
+ struct dc_bios *bp,
+ enum engine_id eng_id,
+ struct vpg *vpg,
+ struct afmt *afmt,
+ const struct dcn10_stream_enc_registers *regs,
+ const struct dcn10_stream_encoder_shift *se_shift,
+ const struct dcn10_stream_encoder_mask *se_mask);
+
+void enc3_stream_encoder_update_hdmi_info_packets(
+ struct stream_encoder *enc,
+ const struct encoder_info_frame *info_frame);
+
+void enc3_stream_encoder_stop_hdmi_info_packets(
+ struct stream_encoder *enc);
+
+void enc3_stream_encoder_update_dp_info_packets_sdp_line_num(
+ struct stream_encoder *enc,
+ struct encoder_info_frame *info_frame);
+
+void enc3_stream_encoder_update_dp_info_packets(
+ struct stream_encoder *enc,
+ const struct encoder_info_frame *info_frame);
+
+void enc3_audio_mute_control(
+ struct stream_encoder *enc,
+ bool mute);
+
+void enc3_se_dp_audio_setup(
+ struct stream_encoder *enc,
+ unsigned int az_inst,
+ struct audio_info *info);
+
+void enc3_se_dp_audio_enable(
+ struct stream_encoder *enc);
+
+void enc3_se_hdmi_audio_setup(
+ struct stream_encoder *enc,
+ unsigned int az_inst,
+ struct audio_info *info,
+ struct audio_crtc_info *audio_crtc_info);
+
+void enc3_dp_set_dsc_pps_info_packet(
+ struct stream_encoder *enc,
+ bool enable,
+ uint8_t *dsc_packed_pps,
+ bool immediate_update);
+
+
+#endif /* __DC_DIO_STREAM_ENCODER_DCN35_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.c
new file mode 100644
index 000000000000..3341ef71009b
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.c
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "core_types.h"
+#include "dcn35_dpp.h"
+#include "reg_helper.h"
+
+#define REG(reg) dpp->tf_regs->reg
+
+#define CTX dpp->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+ ((const struct dcn35_dpp_shift *)(dpp->tf_shift))->field_name, \
+ ((const struct dcn35_dpp_mask *)(dpp->tf_mask))->field_name
+
+bool dpp35_construct(struct dcn3_dpp *dpp, struct dc_context *ctx,
+ uint32_t inst, const struct dcn3_dpp_registers *tf_regs,
+ const struct dcn35_dpp_shift *tf_shift,
+ const struct dcn35_dpp_mask *tf_mask)
+{
+ return dpp32_construct(dpp, ctx, inst, tf_regs,
+ (const struct dcn3_dpp_shift *)(tf_shift),
+ (const struct dcn3_dpp_mask *)(tf_mask));
+}
+
+void dpp35_set_fgcg(struct dcn3_dpp *dpp, bool enable)
+{
+ REG_UPDATE(DPP_CONTROL, DPP_FGCG_REP_DIS, !enable);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.h
new file mode 100644
index 000000000000..09b84307cd9e
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DCN35_DPP_H__
+#define __DCN35_DPP_H__
+
+#include "dcn32/dcn32_dpp.h"
+
+#define DPP_REG_LIST_SH_MASK_DCN35(mask_sh) \
+ DPP_REG_LIST_SH_MASK_DCN30_COMMON(mask_sh), \
+ TF_SF(DPP_TOP0_DPP_CONTROL, DPP_FGCG_REP_DIS, mask_sh)
+
+#define DPP_REG_FIELD_LIST_DCN35(type) \
+ struct { \
+ DPP_REG_FIELD_LIST_DCN3(type); \
+ type DPP_FGCG_REP_DIS; \
+ }
+
+struct dcn35_dpp_shift {
+ DPP_REG_FIELD_LIST_DCN35(uint8_t);
+};
+
+struct dcn35_dpp_mask {
+ DPP_REG_FIELD_LIST_DCN35(uint32_t);
+};
+
+bool dpp35_construct(struct dcn3_dpp *dpp3, struct dc_context *ctx,
+ uint32_t inst, const struct dcn3_dpp_registers *tf_regs,
+ const struct dcn35_dpp_shift *tf_shift,
+ const struct dcn35_dpp_mask *tf_mask);
+
+void dpp35_set_fgcg(struct dcn3_dpp *dpp, bool enable);
+
+#endif // __DCN35_DPP_H
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.c
new file mode 100644
index 000000000000..71d2dff9986d
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.c
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dcn35_dsc.h"
+#include "reg_helper.h"
+
+/* Macro definitios for REG_SET macros*/
+#define CTX \
+ dsc20->base.ctx
+
+#define REG(reg)\
+ dsc20->dsc_regs->reg
+
+#undef FN
+#define FN(reg_name, field_name) \
+ ((const struct dcn35_dsc_shift *)(dsc20->dsc_shift))->field_name, \
+ ((const struct dcn35_dsc_mask *)(dsc20->dsc_mask))->field_name
+
+#define DC_LOGGER \
+ dsc->ctx->logger
+
+void dsc35_construct(struct dcn20_dsc *dsc,
+ struct dc_context *ctx,
+ int inst,
+ const struct dcn20_dsc_registers *dsc_regs,
+ const struct dcn35_dsc_shift *dsc_shift,
+ const struct dcn35_dsc_mask *dsc_mask)
+{
+ dsc2_construct(dsc, ctx, inst, dsc_regs,
+ (const struct dcn20_dsc_shift *)(dsc_shift),
+ (const struct dcn20_dsc_mask *)(dsc_mask));
+}
+
+void dsc35_set_fgcg(struct dcn20_dsc *dsc20, bool enable)
+{
+ REG_UPDATE(DSC_TOP_CONTROL, DSC_FGCG_REP_DIS, !enable);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.h
new file mode 100644
index 000000000000..133ad38842cc
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DCN35_DSC_H__
+#define __DCN35_DSC_H__
+
+#include "dcn20/dcn20_dsc.h"
+
+#define DSC_REG_LIST_SH_MASK_DCN35(mask_sh) \
+ DSC_REG_LIST_SH_MASK_DCN20(mask_sh), \
+ DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_FGCG_REP_DIS, mask_sh)
+
+#define DSC_FIELD_LIST_DCN35(type) \
+ struct { \
+ DSC_FIELD_LIST_DCN20(type); \
+ type DSC_FGCG_REP_DIS; \
+ }
+
+struct dcn35_dsc_shift {
+ DSC_FIELD_LIST_DCN35(uint8_t);
+};
+
+struct dcn35_dsc_mask {
+ DSC_FIELD_LIST_DCN35(uint32_t);
+};
+
+void dsc35_construct(struct dcn20_dsc *dsc,
+ struct dc_context *ctx,
+ int inst,
+ const struct dcn20_dsc_registers *dsc_regs,
+ const struct dcn35_dsc_shift *dsc_shift,
+ const struct dcn35_dsc_mask *dsc_mask);
+
+void dsc35_set_fgcg(struct dcn20_dsc *dsc20, bool enable);
+
+#endif /* __DCN35_DSC_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.c
new file mode 100644
index 000000000000..b23a809999ed
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.c
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "reg_helper.h"
+#include "dcn35_dwb.h"
+
+#define REG(reg)\
+ dwbc30->dwbc_regs->reg
+
+#define CTX \
+ dwbc30->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+ ((const struct dcn35_dwbc_shift *)(dwbc30->dwbc_shift))->field_name, \
+ ((const struct dcn35_dwbc_mask *)(dwbc30->dwbc_mask)) \
+ ->field_name
+
+#define DC_LOGGER \
+ dwbc30->base.ctx->logger
+
+void dcn35_dwbc_construct(struct dcn30_dwbc *dwbc30,
+ struct dc_context *ctx,
+ const struct dcn30_dwbc_registers *dwbc_regs,
+ const struct dcn35_dwbc_shift *dwbc_shift,
+ const struct dcn35_dwbc_mask *dwbc_mask,
+ int inst)
+{
+ dcn30_dwbc_construct(dwbc30, ctx, dwbc_regs,
+ (const struct dcn30_dwbc_shift *)dwbc_shift,
+ (const struct dcn30_dwbc_mask *)dwbc_mask, inst);
+}
+
+void dcn35_dwbc_set_fgcg(struct dcn30_dwbc *dwbc30, bool enable)
+{
+ REG_UPDATE(DWB_ENABLE_CLK_CTRL, DWB_FGCG_REP_DIS, !enable);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.h
new file mode 100644
index 000000000000..886e727ed080
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dwb.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DCN35_DWB_H
+#define __DCN35_DWB_H
+
+#include "resource.h"
+#include "dwb.h"
+#include "dcn30/dcn30_dwb.h"
+
+#define DWBC_COMMON_MASK_SH_LIST_DCN35(mask_sh) \
+ DWBC_COMMON_MASK_SH_LIST_DCN30(mask_sh), \
+ SF_DWB2(DWB_ENABLE_CLK_CTRL, DWB_TOP, 0, DWB_FGCG_REP_DIS, mask_sh)
+
+#define DWBC_REG_FIELD_LIST_DCN3_5(type) \
+ struct { \
+ DWBC_REG_FIELD_LIST_DCN3_0(type); \
+ type DWB_FGCG_REP_DIS; \
+ }
+
+struct dcn35_dwbc_mask {
+ DWBC_REG_FIELD_LIST_DCN3_5(uint32_t);
+};
+
+struct dcn35_dwbc_shift {
+ DWBC_REG_FIELD_LIST_DCN3_5(uint8_t);
+};
+
+void dcn35_dwbc_construct(struct dcn30_dwbc *dwbc30,
+ struct dc_context *ctx,
+ const struct dcn30_dwbc_registers *dwbc_regs,
+ const struct dcn35_dwbc_shift *dwbc_shift,
+ const struct dcn35_dwbc_mask *dwbc_mask,
+ int inst);
+
+void dcn35_dwbc_set_fgcg(struct dcn30_dwbc *dwbc30, bool enable);
+
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubbub.c
new file mode 100644
index 000000000000..339bf0c722dd
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubbub.c
@@ -0,0 +1,611 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+
+#include "dcn30/dcn30_hubbub.h"
+#include "dcn31/dcn31_hubbub.h"
+#include "dcn32/dcn32_hubbub.h"
+#include "dcn35_hubbub.h"
+#include "dm_services.h"
+#include "reg_helper.h"
+
+
+#define CTX \
+ hubbub2->base.ctx
+#define DC_LOGGER \
+ hubbub2->base.ctx->logger
+#define REG(reg)\
+ hubbub2->regs->reg
+
+#undef FN
+#define FN(reg_name, field_name) \
+ hubbub2->shifts->field_name, hubbub2->masks->field_name
+
+#define DCN35_CRB_SEGMENT_SIZE_KB 64
+
+static void dcn35_init_crb(struct hubbub *hubbub)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+ REG_GET(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT,
+ &hubbub2->det0_size);
+
+ REG_GET(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT,
+ &hubbub2->det1_size);
+
+ REG_GET(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT,
+ &hubbub2->det2_size);
+
+ REG_GET(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT,
+ &hubbub2->det3_size);
+
+ REG_GET(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT,
+ &hubbub2->compbuf_size_segments);
+
+ REG_SET_2(COMPBUF_RESERVED_SPACE, 0,
+ COMPBUF_RESERVED_SPACE_64B, hubbub2->pixel_chunk_size / 32,
+ COMPBUF_RESERVED_SPACE_ZS, hubbub2->pixel_chunk_size / 128);
+ REG_UPDATE(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, 0x5FF);
+}
+
+static void dcn35_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ unsigned int compbuf_size_segments = (compbuf_size_kb + DCN35_CRB_SEGMENT_SIZE_KB - 1) / DCN35_CRB_SEGMENT_SIZE_KB;
+
+ if (safe_to_increase || compbuf_size_segments <= hubbub2->compbuf_size_segments) {
+ if (compbuf_size_segments > hubbub2->compbuf_size_segments) {
+ REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100);
+ REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1, 100);
+ REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1, 100);
+ REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1, 100);
+ }
+ /* Should never be hit, if it is we have an erroneous hw config*/
+ ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
+ + hubbub2->det3_size + compbuf_size_segments <= hubbub2->crb_size_segs);
+ REG_UPDATE(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, compbuf_size_segments);
+ hubbub2->compbuf_size_segments = compbuf_size_segments;
+ ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &compbuf_size_segments) && !compbuf_size_segments);
+ }
+}
+
+static uint32_t convert_and_clamp(
+ uint32_t wm_ns,
+ uint32_t refclk_mhz,
+ uint32_t clamp_value)
+{
+ uint32_t ret_val = 0;
+
+ ret_val = wm_ns * refclk_mhz;
+
+ ret_val /= 1000;
+
+ if (ret_val > clamp_value)
+ ret_val = clamp_value;
+
+ return ret_val;
+}
+
+static bool hubbub35_program_stutter_z8_watermarks(
+ struct hubbub *hubbub,
+ struct dcn_watermark_set *watermarks,
+ unsigned int refclk_mhz,
+ bool safe_to_lower)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ uint32_t prog_wm_value;
+ bool wm_pending = false;
+
+ /* clock state A */
+ if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns
+ > hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns) {
+ hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns =
+ watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns;
+ prog_wm_value = convert_and_clamp(
+ watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns,
+ refclk_mhz, 0xfffff);
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, prog_wm_value);
+ DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_A calculated =%d\n"
+ "HW register value = 0x%x\n",
+ watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value);
+ } else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns
+ < hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_z8_ns
+ > hubbub2->watermarks.a.cstate_pstate.cstate_exit_z8_ns) {
+ hubbub2->watermarks.a.cstate_pstate.cstate_exit_z8_ns =
+ watermarks->a.cstate_pstate.cstate_exit_z8_ns;
+ prog_wm_value = convert_and_clamp(
+ watermarks->a.cstate_pstate.cstate_exit_z8_ns,
+ refclk_mhz, 0xfffff);
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, prog_wm_value);
+ DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_A calculated =%d\n"
+ "HW register value = 0x%x\n",
+ watermarks->a.cstate_pstate.cstate_exit_z8_ns, prog_wm_value);
+ } else if (watermarks->a.cstate_pstate.cstate_exit_z8_ns
+ < hubbub2->watermarks.a.cstate_pstate.cstate_exit_z8_ns)
+ wm_pending = true;
+
+ /* clock state B */
+
+ if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns
+ > hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns) {
+ hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns =
+ watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns;
+ prog_wm_value = convert_and_clamp(
+ watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns,
+ refclk_mhz, 0xfffff);
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, prog_wm_value);
+ DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_B calculated =%d\n"
+ "HW register value = 0x%x\n",
+ watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value);
+ } else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns
+ < hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_z8_ns
+ > hubbub2->watermarks.b.cstate_pstate.cstate_exit_z8_ns) {
+ hubbub2->watermarks.b.cstate_pstate.cstate_exit_z8_ns =
+ watermarks->b.cstate_pstate.cstate_exit_z8_ns;
+ prog_wm_value = convert_and_clamp(
+ watermarks->b.cstate_pstate.cstate_exit_z8_ns,
+ refclk_mhz, 0xfffff);
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, prog_wm_value);
+ DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_B calculated =%d\n"
+ "HW register value = 0x%x\n",
+ watermarks->b.cstate_pstate.cstate_exit_z8_ns, prog_wm_value);
+ } else if (watermarks->b.cstate_pstate.cstate_exit_z8_ns
+ < hubbub2->watermarks.b.cstate_pstate.cstate_exit_z8_ns)
+ wm_pending = true;
+
+ /* clock state C */
+ if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns
+ > hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns) {
+ hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns =
+ watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns;
+ prog_wm_value = convert_and_clamp(
+ watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns,
+ refclk_mhz, 0xfffff);
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, prog_wm_value);
+ DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_C calculated =%d\n"
+ "HW register value = 0x%x\n",
+ watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value);
+ } else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns
+ < hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_z8_ns
+ > hubbub2->watermarks.c.cstate_pstate.cstate_exit_z8_ns) {
+ hubbub2->watermarks.c.cstate_pstate.cstate_exit_z8_ns =
+ watermarks->c.cstate_pstate.cstate_exit_z8_ns;
+ prog_wm_value = convert_and_clamp(
+ watermarks->c.cstate_pstate.cstate_exit_z8_ns,
+ refclk_mhz, 0xfffff);
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, prog_wm_value);
+ DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_C calculated =%d\n"
+ "HW register value = 0x%x\n",
+ watermarks->c.cstate_pstate.cstate_exit_z8_ns, prog_wm_value);
+ } else if (watermarks->c.cstate_pstate.cstate_exit_z8_ns
+ < hubbub2->watermarks.c.cstate_pstate.cstate_exit_z8_ns)
+ wm_pending = true;
+
+ /* clock state D */
+ if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns
+ > hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns) {
+ hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns =
+ watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns;
+ prog_wm_value = convert_and_clamp(
+ watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns,
+ refclk_mhz, 0xfffff);
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, prog_wm_value);
+ DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_D calculated =%d\n"
+ "HW register value = 0x%x\n",
+ watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value);
+ } else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns
+ < hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_z8_ns
+ > hubbub2->watermarks.d.cstate_pstate.cstate_exit_z8_ns) {
+ hubbub2->watermarks.d.cstate_pstate.cstate_exit_z8_ns =
+ watermarks->d.cstate_pstate.cstate_exit_z8_ns;
+ prog_wm_value = convert_and_clamp(
+ watermarks->d.cstate_pstate.cstate_exit_z8_ns,
+ refclk_mhz, 0xfffff);
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, prog_wm_value);
+ DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_D calculated =%d\n"
+ "HW register value = 0x%x\n",
+ watermarks->d.cstate_pstate.cstate_exit_z8_ns, prog_wm_value);
+ } else if (watermarks->d.cstate_pstate.cstate_exit_z8_ns
+ < hubbub2->watermarks.d.cstate_pstate.cstate_exit_z8_ns)
+ wm_pending = true;
+
+ return wm_pending;
+}
+
+static void hubbub35_get_dchub_ref_freq(struct hubbub *hubbub,
+ unsigned int dccg_ref_freq_inKhz,
+ unsigned int *dchub_ref_freq_inKhz)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ uint32_t ref_div = 0;
+ uint32_t ref_en = 0;
+ unsigned int dc_refclk_khz = 24000;
+
+ REG_GET_2(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, &ref_div,
+ DCHUBBUB_GLOBAL_TIMER_ENABLE, &ref_en);
+
+ if (ref_en) {
+ if (ref_div == 2)
+ *dchub_ref_freq_inKhz = dc_refclk_khz / 2;
+ else
+ *dchub_ref_freq_inKhz = dc_refclk_khz;
+
+ /*
+ * The external Reference Clock may change based on the board or
+ * platform requirements and the programmable integer divide must
+ * be programmed to provide a suitable DLG RefClk frequency between
+ * a minimum of 20MHz and maximum of 50MHz
+ */
+ if (*dchub_ref_freq_inKhz < 20000 || *dchub_ref_freq_inKhz > 50000)
+ ASSERT_CRITICAL(false);
+
+ return;
+ } else {
+ *dchub_ref_freq_inKhz = dc_refclk_khz;
+ /*init sequence issue on bringup patch*/
+ REG_UPDATE_2(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 1,
+ DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
+ // HUBBUB global timer must be enabled.
+ ASSERT_CRITICAL(false);
+ return;
+ }
+}
+
+
+static bool hubbub35_program_watermarks(
+ struct hubbub *hubbub,
+ struct dcn_watermark_set *watermarks,
+ unsigned int refclk_mhz,
+ bool safe_to_lower)
+{
+ bool wm_pending = false;
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+ if (hubbub32_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
+ wm_pending = true;
+
+ if (hubbub32_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
+ wm_pending = true;
+
+ if (hubbub32_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
+ wm_pending = true;
+
+ if (hubbub32_program_usr_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
+ wm_pending = true;
+
+ if (hubbub35_program_stutter_z8_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
+ wm_pending = true;
+
+ REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,
+ DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
+ REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
+ DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0xFF,
+ DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);/*hw delta*/
+ REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF);
+
+ hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
+
+ hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow);
+
+ return wm_pending;
+}
+
+/* Copy values from WM set A to all other sets */
+static void hubbub35_init_watermarks(struct hubbub *hubbub)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ uint32_t reg;
+
+ reg = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);
+ REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, reg);
+ REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, reg);
+ REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, reg);
+
+ reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A);
+ REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, reg);
+ REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, reg);
+ REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, reg);
+
+ reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A);
+ REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, reg);
+ REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, reg);
+ REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, reg);
+
+ reg = REG_READ(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A);
+ REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, reg);
+ REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, reg);
+ REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, reg);
+
+ reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A);
+ REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, reg);
+ REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, reg);
+ REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, reg);
+
+ reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A);
+ REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, reg);
+ REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, reg);
+ REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, reg);
+
+ reg = REG_READ(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A);
+ REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, reg);
+ REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, reg);
+ REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, reg);
+
+ reg = REG_READ(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A);
+ REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, reg);
+ REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, reg);
+ REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, reg);
+
+ reg = REG_READ(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A);
+ REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, reg);
+ REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, reg);
+ REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, reg);
+
+ reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A);
+ REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, reg);
+ REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, reg);
+ REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, reg);
+
+ reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A);
+ REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, reg);
+ REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, reg);
+ REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, reg);
+
+}
+
+static void hubbub35_wm_read_state(struct hubbub *hubbub,
+ struct dcn_hubbub_wm *wm)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ struct dcn_hubbub_wm_set *s;
+
+ memset(wm, 0, sizeof(struct dcn_hubbub_wm));
+
+ s = &wm->sets[0];
+ s->wm_set = 0;
+ REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A,
+ DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, &s->data_urgent);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, &s->sr_enter);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit);
+
+ REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A,
+ DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, &s->dram_clk_change);
+
+ REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A,
+ DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, &s->usr_retrain);
+
+ REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A,
+ DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, &s->fclk_pstate_change);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, &s->sr_enter_exit_Z8);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, &s->sr_enter_Z8);
+ s = &wm->sets[1];
+ s->wm_set = 1;
+ REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B,
+ DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, &s->data_urgent);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, &s->sr_enter);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit);
+
+ REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B,
+ DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, &s->dram_clk_change);
+
+ REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B,
+ DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, &s->usr_retrain);
+
+ REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B,
+ DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, &s->fclk_pstate_change);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, &s->sr_enter_exit_Z8);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, &s->sr_enter_Z8);
+
+ s = &wm->sets[2];
+ s->wm_set = 2;
+ REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C,
+ DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, &s->data_urgent);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, &s->sr_enter);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, &s->sr_exit);
+
+ REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C,
+ DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, &s->dram_clk_change);
+
+ REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C,
+ DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, &s->usr_retrain);
+
+ REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C,
+ DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, &s->fclk_pstate_change);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, &s->sr_enter_exit_Z8);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, &s->sr_enter_Z8);
+
+ s = &wm->sets[3];
+ s->wm_set = 3;
+ REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D,
+ DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, &s->data_urgent);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, &s->sr_enter);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, &s->sr_exit);
+
+ REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D,
+ DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, &s->dram_clk_change);
+
+ REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D,
+ DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, &s->usr_retrain);
+
+ REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D,
+ DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, &s->fclk_pstate_change);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, &s->sr_enter_exit_Z8);
+
+ REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, &s->sr_enter_Z8);
+}
+
+static void hubbub35_set_fgcg(struct dcn20_hubbub *hubbub2, bool enable)
+{
+ REG_UPDATE(DCHUBBUB_CLOCK_CNTL, DCHUBBUB_FGCG_REP_DIS, !enable);
+}
+
+static void hubbub35_init(struct hubbub *hubbub)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ /*Enable clock gaters*/
+ if (hubbub->ctx->dc->debug.disable_clock_gate) {
+ /*done in hwseq*/
+ /*REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);*/
+
+ REG_UPDATE_2(DCHUBBUB_CLOCK_CNTL,
+ DISPCLK_R_DCHUBBUB_GATE_DIS, 1,
+ DCFCLK_R_DCHUBBUB_GATE_DIS, 1);
+ }
+ hubbub35_set_fgcg(hubbub2,
+ hubbub->ctx->dc->debug.enable_fine_grain_clock_gating
+ .bits.dchubbub);
+ /*
+ ignore the "df_pre_cstate_req" from the SDP port control.
+ only the DCN will determine when to connect the SDP port
+ */
+ REG_UPDATE(DCHUBBUB_SDPIF_CFG0,
+ SDPIF_PORT_CONTROL, 1);
+ /*Set SDP's max outstanding request
+ When set to 1: Max outstanding is 512
+ When set to 0: Max outstanding is 256
+ must set the register back to 0 (max outstanding = 256) in zero frame buffer mode*/
+ REG_UPDATE(DCHUBBUB_SDPIF_CFG1,
+ SDPIF_MAX_NUM_OUTSTANDING, 0);
+
+ REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
+ DCHUBBUB_ARB_MAX_REQ_OUTSTAND, 256,
+ DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 256);
+
+}
+
+/*static void hubbub35_set_request_limit(struct hubbub *hubbub,
+ int memory_channel_count,
+ int words_per_channel)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+ uint32_t request_limit = 3 * memory_channel_count * words_per_channel / 4;
+
+ ASSERT((request_limit & (~0xFFF)) == 0); //field is only 24 bits long
+ ASSERT(request_limit > 0); //field is only 24 bits long
+
+ if (request_limit > 0xFFF)
+ request_limit = 0xFFF;
+
+ if (request_limit > 0)
+ REG_UPDATE(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, request_limit);
+}*/
+
+static const struct hubbub_funcs hubbub35_funcs = {
+ .update_dchub = hubbub2_update_dchub,
+ .init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx,
+ .init_vm_ctx = hubbub2_init_vm_ctx,
+ .dcc_support_swizzle = hubbub3_dcc_support_swizzle,
+ .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,
+ .get_dcc_compression_cap = hubbub3_get_dcc_compression_cap,
+ .wm_read_state = hubbub35_wm_read_state,
+ .get_dchub_ref_freq = hubbub35_get_dchub_ref_freq,
+ .program_watermarks = hubbub35_program_watermarks,
+ .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
+ .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
+ .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high,
+ .force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes,
+ .force_pstate_change_control = hubbub3_force_pstate_change_control,
+ .init_watermarks = hubbub35_init_watermarks,
+ .program_det_size = dcn32_program_det_size,
+ .program_compbuf_size = dcn35_program_compbuf_size,
+ .init_crb = dcn35_init_crb,
+ .hubbub_read_state = hubbub2_read_state,
+ .force_usr_retraining_allow = hubbub32_force_usr_retraining_allow,
+ .dchubbub_init = hubbub35_init,
+};
+
+void hubbub35_construct(struct dcn20_hubbub *hubbub2,
+ struct dc_context *ctx,
+ const struct dcn_hubbub_registers *hubbub_regs,
+ const struct dcn_hubbub_shift *hubbub_shift,
+ const struct dcn_hubbub_mask *hubbub_mask,
+ int det_size_kb,
+ int pixel_chunk_size_kb,
+ int config_return_buffer_size_kb)
+{
+ hubbub2->base.ctx = ctx;
+ hubbub2->base.funcs = &hubbub35_funcs;
+ hubbub2->regs = hubbub_regs;
+ hubbub2->shifts = hubbub_shift;
+ hubbub2->masks = hubbub_mask;
+
+ hubbub2->debug_test_index_pstate = 0xB;
+ hubbub2->detile_buf_size = det_size_kb * 1024;
+ hubbub2->pixel_chunk_size = pixel_chunk_size_kb * 1024;
+ hubbub2->crb_size_segs = config_return_buffer_size_kb / DCN35_CRB_SEGMENT_SIZE_KB; /*todo*/
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubbub.h
new file mode 100644
index 000000000000..54cf00ffceb8
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubbub.h
@@ -0,0 +1,155 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_HUBBUB_DCN35_H__
+#define __DC_HUBBUB_DCN35_H__
+
+#include "dcn32/dcn32_hubbub.h"
+
+#define HUBBUB_REG_LIST_DCN35(id)\
+ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\
+ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\
+ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\
+ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\
+ SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\
+ SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\
+ SR(DCHUBBUB_ARB_SAT_LEVEL),\
+ SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\
+ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \
+ SR(DCHUBBUB_SOFT_RESET),\
+ SR(DCHUBBUB_CRC_CTRL), \
+ SR(DCN_VM_FB_LOCATION_BASE),\
+ SR(DCN_VM_FB_LOCATION_TOP),\
+ SR(DCN_VM_FB_OFFSET),\
+ SR(DCN_VM_AGP_BOT),\
+ SR(DCN_VM_AGP_TOP),\
+ SR(DCN_VM_AGP_BASE),\
+ HUBBUB_SR_WATERMARK_REG_LIST(), \
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D),\
+ SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A),\
+ SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B),\
+ SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C),\
+ SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D),\
+ SR(DCHUBBUB_DET0_CTRL),\
+ SR(DCHUBBUB_DET1_CTRL),\
+ SR(DCHUBBUB_DET2_CTRL),\
+ SR(DCHUBBUB_DET3_CTRL),\
+ SR(DCHUBBUB_COMPBUF_CTRL),\
+ SR(COMPBUF_RESERVED_SPACE),\
+ SR(DCHUBBUB_DEBUG_CTRL_0),\
+ SR(DCHUBBUB_ARB_USR_RETRAINING_CNTL),\
+ SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A),\
+ SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B),\
+ SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C),\
+ SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D),\
+ SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A),\
+ SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B),\
+ SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C),\
+ SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D),\
+ SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A),\
+ SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B),\
+ SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C),\
+ SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D),\
+ SR(DCN_VM_FAULT_ADDR_MSB),\
+ SR(DCN_VM_FAULT_ADDR_LSB),\
+ SR(DCN_VM_FAULT_CNTL),\
+ SR(DCN_VM_FAULT_STATUS),\
+ SR(SDPIF_REQUEST_RATE_LIMIT),\
+ SR(DCHUBBUB_CLOCK_CNTL),\
+ SR(DCHUBBUB_SDPIF_CFG0),\
+ SR(DCHUBBUB_SDPIF_CFG1),\
+ SR(DCHUBBUB_MEM_PWR_MODE_CTRL),\
+ SR(DCHUBBUB_ARB_HOSTVM_CNTL),\
+ SR(DCHVM_CTRL0),\
+ SR(DCHVM_MEM_CTRL),\
+ SR(DCHVM_CLK_CTRL),\
+ SR(DCHVM_RIOMMU_CTRL0),\
+ SR(DCHVM_RIOMMU_STAT0),\
+ SR(DCHUBBUB_COMPBUF_CTRL),\
+ SR(COMPBUF_RESERVED_SPACE),\
+ SR(DCHUBBUB_DEBUG_CTRL_0),\
+ SR(DCHUBBUB_CLOCK_CNTL),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D),\
+ SR(DCHUBBUB_ARB_QOS_FORCE)
+
+
+#define HUBBUB_MASK_SH_LIST_DCN35(mask_sh)\
+ HUBBUB_MASK_SH_LIST_DCN32(mask_sh), \
+ HUBBUB_SF(DCHVM_CTRL0, HOSTVM_INIT_REQ, mask_sh),\
+ HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_PWR_REQ_DIS, mask_sh),\
+ HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_FORCE_REQ, mask_sh),\
+ HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_POWER_STATUS, mask_sh),\
+ HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DISPCLK_R_GATE_DIS, mask_sh),\
+ HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DISPCLK_G_GATE_DIS, mask_sh),\
+ HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DCFCLK_R_GATE_DIS, mask_sh),\
+ HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DCFCLK_G_GATE_DIS, mask_sh),\
+ HUBBUB_SF(DCHVM_CLK_CTRL, TR_REQ_REQCLKREQ_MODE, mask_sh),\
+ HUBBUB_SF(DCHVM_CLK_CTRL, TW_RSP_COMPCLKREQ_MODE, mask_sh),\
+ HUBBUB_SF(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, mask_sh),\
+ HUBBUB_SF(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, mask_sh),\
+ HUBBUB_SF(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, mask_sh),\
+ HUBBUB_SF(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, mask_sh),\
+ HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_64B, mask_sh),\
+ HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_ZS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DCHUBBUB_FGCG_REP_DIS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_CSTATE_DEEPSLEEP_LEGACY_MODE, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, mask_sh)
+
+void hubbub35_construct(struct dcn20_hubbub *hubbub2,
+ struct dc_context *ctx,
+ const struct dcn_hubbub_registers *hubbub_regs,
+ const struct dcn_hubbub_shift *hubbub_shift,
+ const struct dcn_hubbub_mask *hubbub_mask,
+ int det_size_kb,
+ int pixel_chunk_size_kb,
+ int config_return_buffer_size_kb);
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubp.c
new file mode 100644
index 000000000000..771fcd0d3b99
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubp.c
@@ -0,0 +1,241 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dcn35_hubp.h"
+#include "reg_helper.h"
+
+#define REG(reg)\
+ hubp2->hubp_regs->reg
+
+#define CTX \
+ hubp2->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+ ((const struct dcn35_hubp2_shift *)hubp2->hubp_shift)->field_name, \
+ ((const struct dcn35_hubp2_mask *)hubp2->hubp_mask)->field_name
+
+void hubp35_set_fgcg(struct hubp *hubp, bool enable)
+{
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+ REG_UPDATE(HUBP_CLK_CNTL, HUBP_FGCG_REP_DIS, !enable);
+}
+
+static void hubp35_init(struct hubp *hubp)
+{
+ hubp3_init(hubp);
+
+ hubp35_set_fgcg(hubp, hubp->ctx->dc->debug.enable_fine_grain_clock_gating.bits.dchub);
+
+ /*do nothing for now for dcn3.5 or later*/
+}
+
+void hubp35_program_pixel_format(
+ struct hubp *hubp,
+ enum surface_pixel_format format)
+{
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+ uint32_t green_bar = 1;
+ uint32_t red_bar = 3;
+ uint32_t blue_bar = 2;
+
+ /* swap for ABGR format */
+ if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888
+ || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
+ || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS
+ || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616
+ || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
+ red_bar = 2;
+ blue_bar = 3;
+ }
+
+ REG_UPDATE_3(HUBPRET_CONTROL,
+ CROSSBAR_SRC_Y_G, green_bar,
+ CROSSBAR_SRC_CB_B, blue_bar,
+ CROSSBAR_SRC_CR_R, red_bar);
+
+ /* Mapping is same as ipp programming (cnvc) */
+
+ switch (format) {
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 1);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 3);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 8);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 10);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: /* we use crossbar already */
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 26); /* ARGB16161616_UNORM */
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:/*we use crossbar already*/
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 24);
+ break;
+
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 65);
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 64);
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 67);
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 66);
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 12);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 112);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 113);
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 114);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 118);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 119);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
+ REG_UPDATE_2(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 116,
+ ALPHA_PLANE_EN, 0);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
+ REG_UPDATE_2(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 116,
+ ALPHA_PLANE_EN, 1);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ break;
+ }
+
+ /* don't see the need of program the xbar in DCN 1.0 */
+}
+
+void hubp35_program_surface_config(
+ struct hubp *hubp,
+ enum surface_pixel_format format,
+ union dc_tiling_info *tiling_info,
+ struct plane_size *plane_size,
+ enum dc_rotation_angle rotation,
+ struct dc_plane_dcc_param *dcc,
+ bool horizontal_mirror,
+ unsigned int compat_level)
+{
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+ hubp3_dcc_control_sienna_cichlid(hubp, dcc);
+ hubp3_program_tiling(hubp2, tiling_info, format);
+ hubp2_program_size(hubp, format, plane_size, dcc);
+ hubp2_program_rotation(hubp, rotation, horizontal_mirror);
+ hubp35_program_pixel_format(hubp, format);
+}
+
+struct hubp_funcs dcn35_hubp_funcs = {
+ .hubp_enable_tripleBuffer = hubp2_enable_triplebuffer,
+ .hubp_is_triplebuffer_enabled = hubp2_is_triplebuffer_enabled,
+ .hubp_program_surface_flip_and_addr = hubp3_program_surface_flip_and_addr,
+ .hubp_program_surface_config = hubp35_program_surface_config,
+ .hubp_is_flip_pending = hubp2_is_flip_pending,
+ .hubp_setup = hubp3_setup,
+ .hubp_setup_interdependent = hubp2_setup_interdependent,
+ .hubp_set_vm_system_aperture_settings = hubp3_set_vm_system_aperture_settings,
+ .set_blank = hubp2_set_blank,
+ .dcc_control = hubp3_dcc_control,
+ .mem_program_viewport = min_set_viewport,
+ .set_cursor_attributes = hubp2_cursor_set_attributes,
+ .set_cursor_position = hubp2_cursor_set_position,
+ .hubp_clk_cntl = hubp2_clk_cntl,
+ .hubp_vtg_sel = hubp2_vtg_sel,
+ .dmdata_set_attributes = hubp3_dmdata_set_attributes,
+ .dmdata_load = hubp2_dmdata_load,
+ .dmdata_status_done = hubp2_dmdata_status_done,
+ .hubp_read_state = hubp3_read_state,
+ .hubp_clear_underflow = hubp2_clear_underflow,
+ .hubp_set_flip_control_surface_gsl = hubp2_set_flip_control_surface_gsl,
+ .hubp_init = hubp35_init,
+ .set_unbounded_requesting = hubp31_set_unbounded_requesting,
+ .hubp_soft_reset = hubp31_soft_reset,
+ .hubp_set_flip_int = hubp1_set_flip_int,
+ .hubp_in_blank = hubp1_in_blank,
+ .program_extended_blank = hubp31_program_extended_blank_value,
+};
+
+bool hubp35_construct(
+ struct dcn20_hubp *hubp2,
+ struct dc_context *ctx,
+ uint32_t inst,
+ const struct dcn_hubp2_registers *hubp_regs,
+ const struct dcn35_hubp2_shift *hubp_shift,
+ const struct dcn35_hubp2_mask *hubp_mask)
+{
+ hubp2->base.funcs = &dcn35_hubp_funcs;
+ hubp2->base.ctx = ctx;
+ hubp2->hubp_regs = hubp_regs;
+ hubp2->hubp_shift = (const struct dcn_hubp2_shift *)hubp_shift;
+ hubp2->hubp_mask = (const struct dcn_hubp2_mask *)hubp_mask;
+ hubp2->base.inst = inst;
+ hubp2->base.opp_id = OPP_ID_INVALID;
+ hubp2->base.mpcc_id = 0xf;
+
+ return true;
+}
+
+
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubp.h
new file mode 100644
index 000000000000..586b43aa5834
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubp.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_HUBP_DCN35_H__
+#define __DC_HUBP_DCN35_H__
+
+#include "dcn31/dcn31_hubp.h"
+#include "dcn32/dcn32_hubp.h"
+#define HUBP_MASK_SH_LIST_DCN35(mask_sh)\
+ HUBP_MASK_SH_LIST_DCN32(mask_sh),\
+ HUBP_SF(HUBP0_HUBP_CLK_CNTL, HUBP_FGCG_REP_DIS, mask_sh)
+
+#define DCN35_HUBP_REG_FIELD_VARIABLE_LIST(type) \
+ struct { \
+ DCN32_HUBP_REG_FIELD_VARIABLE_LIST(type); \
+ type HUBP_FGCG_REP_DIS; \
+ }
+
+struct dcn35_hubp2_shift {
+ DCN35_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t);
+};
+
+struct dcn35_hubp2_mask {
+ DCN35_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t);
+};
+
+
+bool hubp35_construct(
+ struct dcn20_hubp *hubp2,
+ struct dc_context *ctx,
+ uint32_t inst,
+ const struct dcn_hubp2_registers *hubp_regs,
+ const struct dcn35_hubp2_shift *hubp_shift,
+ const struct dcn35_hubp2_mask *hubp_mask);
+
+void hubp35_set_fgcg(struct hubp *hubp, bool enable);
+
+void hubp35_program_pixel_format(
+ struct hubp *hubp,
+ enum surface_pixel_format format);
+
+void hubp35_program_surface_config(
+ struct hubp *hubp,
+ enum surface_pixel_format format,
+ union dc_tiling_info *tiling_info,
+ struct plane_size *plane_size,
+ enum dc_rotation_angle rotation,
+ struct dc_plane_dcc_param *dcc,
+ bool horizontal_mirror,
+ unsigned int compat_level);
+
+#endif /* __DC_HUBP_DCN35_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.c
new file mode 100644
index 000000000000..296bf3a38cb9
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.c
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dce110/dce110_hwseq.h"
+#include "dcn10/dcn10_hwseq.h"
+#include "dcn20/dcn20_hwseq.h"
+#include "dcn21/dcn21_hwseq.h"
+#include "dcn30/dcn30_hwseq.h"
+#include "dcn301/dcn301_hwseq.h"
+#include "dcn31/dcn31_hwseq.h"
+#include "dcn32/dcn32_hwseq.h"
+#include "dcn35/dcn35_hwseq.h"
+
+#include "dcn35_init.h"
+
+static const struct hw_sequencer_funcs dcn35_funcs = {
+ .program_gamut_remap = dcn30_program_gamut_remap,
+ .init_hw = dcn35_init_hw,
+ .power_down_on_boot = dcn35_power_down_on_boot,
+ .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
+ .apply_ctx_for_surface = NULL,
+ .program_front_end_for_ctx = dcn20_program_front_end_for_ctx,
+ .wait_for_pending_cleared = dcn10_wait_for_pending_cleared,
+ .post_unlock_program_front_end = dcn20_post_unlock_program_front_end,
+ .update_plane_addr = dcn20_update_plane_addr,
+ .update_dchub = dcn10_update_dchub,
+ .update_pending_status = dcn10_update_pending_status,
+ .program_output_csc = dcn20_program_output_csc,
+ .enable_accelerated_mode = dce110_enable_accelerated_mode,
+ .enable_timing_synchronization = dcn10_enable_timing_synchronization,
+ .enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset,
+ .update_info_frame = dcn31_update_info_frame,
+ .send_immediate_sdp_message = dcn10_send_immediate_sdp_message,
+ .enable_stream = dcn20_enable_stream,
+ .disable_stream = dce110_disable_stream,
+ .unblank_stream = dcn32_unblank_stream,
+ .blank_stream = dce110_blank_stream,
+ .enable_audio_stream = dce110_enable_audio_stream,
+ .disable_audio_stream = dce110_disable_audio_stream,
+ .disable_plane = dcn35_disable_plane,
+ .disable_pixel_data = dcn20_disable_pixel_data,
+ .pipe_control_lock = dcn20_pipe_control_lock,
+ .interdependent_update_lock = dcn10_lock_all_pipes,
+ .cursor_lock = dcn10_cursor_lock,
+ .prepare_bandwidth = dcn35_prepare_bandwidth,
+ .optimize_bandwidth = dcn35_optimize_bandwidth,
+ .update_bandwidth = dcn20_update_bandwidth,
+ .set_drr = dcn10_set_drr,
+ .get_position = dcn10_get_position,
+ .set_static_screen_control = dcn30_set_static_screen_control,
+ .setup_stereo = dcn10_setup_stereo,
+ .set_avmute = dcn30_set_avmute,
+ .log_hw_state = dcn10_log_hw_state,
+ .get_hw_state = dcn10_get_hw_state,
+ .clear_status_bits = dcn10_clear_status_bits,
+ .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
+ .edp_backlight_control = dce110_edp_backlight_control,
+ .edp_power_control = dce110_edp_power_control,
+ .edp_wait_for_T12 = dce110_edp_wait_for_T12,
+ .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready,
+ .set_cursor_position = dcn10_set_cursor_position,
+ .set_cursor_attribute = dcn10_set_cursor_attribute,
+ .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level,
+ .setup_periodic_interrupt = dcn10_setup_periodic_interrupt,
+ .set_clock = dcn10_set_clock,
+ .get_clock = dcn10_get_clock,
+ .program_triplebuffer = dcn20_program_triple_buffer,
+ .enable_writeback = dcn30_enable_writeback,
+ .disable_writeback = dcn30_disable_writeback,
+ .update_writeback = dcn30_update_writeback,
+ .mmhubbub_warmup = dcn30_mmhubbub_warmup,
+ .dmdata_status_done = dcn20_dmdata_status_done,
+ .program_dmdata_engine = dcn30_program_dmdata_engine,
+ .set_dmdata_attributes = dcn20_set_dmdata_attributes,
+ .init_sys_ctx = dcn31_init_sys_ctx,
+ .init_vm_ctx = dcn20_init_vm_ctx,
+ .set_flip_control_gsl = dcn20_set_flip_control_gsl,
+ .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync,
+ .calc_vupdate_position = dcn10_calc_vupdate_position,
+ .power_down = dce110_power_down,
+ .set_backlight_level = dcn21_set_backlight_level,
+ .set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
+ .set_pipe = dcn21_set_pipe,
+ .enable_lvds_link_output = dce110_enable_lvds_link_output,
+ .enable_tmds_link_output = dce110_enable_tmds_link_output,
+ .enable_dp_link_output = dce110_enable_dp_link_output,
+ .disable_link_output = dcn32_disable_link_output,
+ .z10_restore = dcn35_z10_restore,
+ .z10_save_init = dcn31_z10_save_init,
+ .set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
+ .optimize_pwr_state = dcn21_optimize_pwr_state,
+ .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state,
+ .update_visual_confirm_color = dcn10_update_visual_confirm_color,
+ .apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations,
+ .update_dsc_pg = dcn32_update_dsc_pg,
+ .calc_blocks_to_gate = dcn35_calc_blocks_to_gate,
+ .calc_blocks_to_ungate = dcn35_calc_blocks_to_ungate,
+ .block_power_control = dcn35_block_power_control,
+ .root_clock_control = dcn35_root_clock_control,
+ .set_idle_state = dcn35_set_idle_state,
+ .get_idle_state = dcn35_get_idle_state
+};
+
+static const struct hwseq_private_funcs dcn35_private_funcs = {
+ .init_pipes = dcn35_init_pipes,
+ .update_plane_addr = dcn20_update_plane_addr,
+ .plane_atomic_disconnect = dcn10_plane_atomic_disconnect,
+ .update_mpcc = dcn20_update_mpcc,
+ .set_input_transfer_func = dcn32_set_input_transfer_func,
+ .set_output_transfer_func = dcn32_set_output_transfer_func,
+ .power_down = dce110_power_down,
+ .enable_display_power_gating = dcn10_dummy_display_power_gating,
+ .blank_pixel_data = dcn20_blank_pixel_data,
+ .reset_hw_ctx_wrap = dcn31_reset_hw_ctx_wrap,
+ .enable_stream_timing = dcn20_enable_stream_timing,
+ .edp_backlight_control = dce110_edp_backlight_control,
+ .setup_vupdate_interrupt = dcn20_setup_vupdate_interrupt,
+ .did_underflow_occur = dcn10_did_underflow_occur,
+ .init_blank = dcn20_init_blank,
+ .disable_vga = NULL,
+ .bios_golden_init = dcn10_bios_golden_init,
+ .plane_atomic_disable = dcn35_plane_atomic_disable,
+ //.plane_atomic_disable = dcn20_plane_atomic_disable,/*todo*/
+ //.hubp_pg_control = dcn35_hubp_pg_control,
+ .enable_power_gating_plane = dcn35_enable_power_gating_plane,
+ .dpp_root_clock_control = dcn35_dpp_root_clock_control,
+ .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree,
+ .update_odm = dcn35_update_odm,
+ .set_hdr_multiplier = dcn10_set_hdr_multiplier,
+ .verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
+ .wait_for_blank_complete = dcn20_wait_for_blank_complete,
+ .dccg_init = dcn20_dccg_init,
+ .set_mcm_luts = dcn32_set_mcm_luts,
+ .setup_hpo_hw_control = dcn35_setup_hpo_hw_control,
+ .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
+ .set_pixels_per_cycle = dcn32_set_pixels_per_cycle,
+ .is_dp_dig_pixel_rate_div_policy = dcn32_is_dp_dig_pixel_rate_div_policy,
+ .dsc_pg_control = dcn35_dsc_pg_control,
+ .dsc_pg_status = dcn32_dsc_pg_status,
+ .enable_plane = dcn35_enable_plane,
+};
+
+void dcn35_hw_sequencer_construct(struct dc *dc)
+{
+ dc->hwss = dcn35_funcs;
+ dc->hwseq->funcs = dcn35_private_funcs;
+
+}
diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_fpga.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.h
index 3a80f5595943..b67015032c35 100644
--- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_fpga.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: MIT */
/*
* Copyright 2023 Advanced Micro Devices, Inc.
*
@@ -22,9 +23,12 @@
* Authors: AMD
*
*/
-#ifndef __LINK_FPGA_H__
-#define __LINK_FPGA_H__
-#include "link.h"
-void dp_fpga_hpo_enable_link_and_stream(struct dc_state *state,
- struct pipe_ctx *pipe_ctx);
-#endif /* __LINK_FPGA_H__ */
+
+#ifndef __DC_DCN35_INIT_H__
+#define __DC_DCN35_INIT_H__
+
+struct dc;
+
+void dcn35_hw_sequencer_construct(struct dc *dc);
+
+#endif /* __DC_DCN35_INIT_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.c
new file mode 100644
index 000000000000..4317100564a4
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.c
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dcn35_mmhubbub.h"
+#include "reg_helper.h"
+
+#define REG(reg) \
+ ((const struct dcn35_mmhubbub_registers *)(mcif_wb30->mcif_wb_regs)) \
+ ->reg
+
+#define CTX mcif_wb30->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+ ((const struct dcn35_mmhubbub_shift *)(mcif_wb30->mcif_wb_shift)) \
+ ->field_name, \
+ ((const struct dcn35_mmhubbub_mask *)(mcif_wb30->mcif_wb_mask)) \
+ ->field_name
+
+void dcn35_mmhubbub_construct(
+ struct dcn30_mmhubbub *mcif_wb30, struct dc_context *ctx,
+ const struct dcn35_mmhubbub_registers *mcif_wb_regs,
+ const struct dcn35_mmhubbub_shift *mcif_wb_shift,
+ const struct dcn35_mmhubbub_mask *mcif_wb_mask, int inst)
+{
+ dcn32_mmhubbub_construct(
+ mcif_wb30, ctx,
+ (const struct dcn30_mmhubbub_registers *)(mcif_wb_regs),
+ (const struct dcn30_mmhubbub_shift *)(mcif_wb_shift),
+ (const struct dcn30_mmhubbub_mask *)(mcif_wb_mask), inst);
+}
+
+void dcn35_mmhubbub_set_fgcg(struct dcn30_mmhubbub *mcif_wb30, bool enabled)
+{
+ REG_UPDATE(MMHUBBUB_CLOCK_CNTL, MMHUBBUB_FGCG_REP_DIS, !enabled);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.h
new file mode 100644
index 000000000000..098e13e07272
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_mmhubbub.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DCN35_MMHUBBUB_H
+#define __DCN35_MMHUBBUB_H
+
+#include "mcif_wb.h"
+#include "dcn32/dcn32_mmhubbub.h"
+
+#define MCIF_WB_REG_VARIABLE_LIST_DCN3_5 \
+ MCIF_WB_REG_VARIABLE_LIST_DCN3_0; \
+ uint32_t MMHUBBUB_CLOCK_CNTL
+
+#define MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(mask_sh) \
+ MCIF_WB_COMMON_MASK_SH_LIST_DCN32(mask_sh), \
+ SF(MMHUBBUB_CLOCK_CNTL, MMHUBBUB_TEST_CLK_SEL, mask_sh), \
+ SF(MMHUBBUB_CLOCK_CNTL, DISPCLK_R_MMHUBBUB_GATE_DIS, mask_sh), \
+ SF(MMHUBBUB_CLOCK_CNTL, DISPCLK_G_WBIF0_GATE_DIS, mask_sh), \
+ SF(MMHUBBUB_CLOCK_CNTL, SOCCLK_G_WBIF0_GATE_DIS, mask_sh), \
+ SF(MMHUBBUB_CLOCK_CNTL, MMHUBBUB_FGCG_REP_DIS, mask_sh)
+
+#define MCIF_WB_REG_FIELD_LIST_DCN3_5(type) \
+ struct { \
+ MCIF_WB_REG_FIELD_LIST_DCN3_0(type); \
+ type MMHUBBUB_TEST_CLK_SEL; \
+ type DISPCLK_R_MMHUBBUB_GATE_DIS; \
+ type DISPCLK_G_WBIF0_GATE_DIS; \
+ type SOCCLK_G_WBIF0_GATE_DIS; \
+ type MMHUBBUB_FGCG_REP_DIS; \
+ }
+
+struct dcn35_mmhubbub_registers {
+ MCIF_WB_REG_VARIABLE_LIST_DCN3_5;
+};
+
+struct dcn35_mmhubbub_mask {
+ MCIF_WB_REG_FIELD_LIST_DCN3_5(uint32_t);
+};
+
+struct dcn35_mmhubbub_shift {
+ MCIF_WB_REG_FIELD_LIST_DCN3_5(uint8_t);
+};
+
+void dcn35_mmhubbub_construct(
+ struct dcn30_mmhubbub *mcif_wb30, struct dc_context *ctx,
+ const struct dcn35_mmhubbub_registers *mcif_wb_regs,
+ const struct dcn35_mmhubbub_shift *mcif_wb_shift,
+ const struct dcn35_mmhubbub_mask *mcif_wb_mask, int inst);
+
+void dcn35_mmhubbub_set_fgcg(struct dcn30_mmhubbub *mcif_wb30, bool enabled);
+
+#endif // __DCN35_MMHUBBUB_H
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.c
new file mode 100644
index 000000000000..3542b51c9aac
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.c
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dcn35_opp.h"
+#include "reg_helper.h"
+
+#define REG(reg) ((const struct dcn35_opp_registers *)(oppn20->regs))->reg
+
+#undef FN
+#define FN(reg_name, field_name) \
+ ((const struct dcn35_opp_shift *)(oppn20->opp_shift))->field_name, \
+ ((const struct dcn35_opp_mask *)(oppn20->opp_mask))->field_name
+
+#define CTX oppn20->base.ctx
+
+void dcn35_opp_construct(struct dcn20_opp *oppn20, struct dc_context *ctx,
+ uint32_t inst, const struct dcn35_opp_registers *regs,
+ const struct dcn35_opp_shift *opp_shift,
+ const struct dcn35_opp_mask *opp_mask)
+{
+ dcn20_opp_construct(oppn20, ctx, inst,
+ (const struct dcn20_opp_registers *)regs,
+ (const struct dcn20_opp_shift *)opp_shift,
+ (const struct dcn20_opp_mask *)opp_mask);
+}
+
+void dcn35_opp_set_fgcg(struct dcn20_opp *oppn20, bool enable)
+{
+ REG_UPDATE(OPP_TOP_CLK_CONTROL, OPP_FGCG_REP_DIS, !enable);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.h
new file mode 100644
index 000000000000..a9a413527801
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_opp.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DCN35_OPP_H
+#define __DCN35_OPP_H
+
+#include "dcn20/dcn20_opp.h"
+
+#define OPP_REG_VARIABLE_LIST_DCN3_5 \
+ OPP_REG_VARIABLE_LIST_DCN2_0; \
+ uint32_t OPP_TOP_CLK_CONTROL
+
+#define OPP_MASK_SH_LIST_DCN35(mask_sh) \
+ OPP_MASK_SH_LIST_DCN20(mask_sh), \
+ OPP_SF(OPP_TOP_CLK_CONTROL, OPP_FGCG_REP_DIS, mask_sh)
+
+#define OPP_DCN35_REG_FIELD_LIST(type) \
+ struct { \
+ OPP_DCN20_REG_FIELD_LIST(type); \
+ type OPP_FGCG_REP_DIS; \
+ }
+
+struct dcn35_opp_registers {
+ OPP_REG_VARIABLE_LIST_DCN3_5;
+};
+
+struct dcn35_opp_shift {
+ OPP_DCN35_REG_FIELD_LIST(uint8_t);
+};
+
+struct dcn35_opp_mask {
+ OPP_DCN35_REG_FIELD_LIST(uint32_t);
+};
+
+void dcn35_opp_construct(struct dcn20_opp *oppn20,
+ struct dc_context *ctx,
+ uint32_t inst,
+ const struct dcn35_opp_registers *regs,
+ const struct dcn35_opp_shift *opp_shift,
+ const struct dcn35_opp_mask *opp_mask);
+
+void dcn35_opp_set_fgcg(struct dcn20_opp *oppn20, bool enable);
+
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c
new file mode 100644
index 000000000000..a4a39f1638cf
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c
@@ -0,0 +1,290 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dcn35_optc.h"
+
+#include "dcn30/dcn30_optc.h"
+#include "dcn31/dcn31_optc.h"
+#include "dcn32/dcn32_optc.h"
+#include "reg_helper.h"
+#include "dc.h"
+#include "dcn_calc_math.h"
+
+#define REG(reg)\
+ optc1->tg_regs->reg
+
+#define CTX \
+ optc1->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+ optc1->tg_shift->field_name, optc1->tg_mask->field_name
+
+/**
+ * optc35_set_odm_combine() - Enable CRTC - call ASIC Control Object to enable Timing generator.
+ *
+ * @optc: Output Pipe Timing Combine instance reference.
+ * @opp_id: Output Plane Processor instance ID.
+ * @opp_cnt: Output Plane Processor count.
+ * @timing: Timing parameters used to configure DCN blocks.
+ *
+ * Return: void.
+ */
+static void optc35_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
+ struct dc_crtc_timing *timing)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+ uint32_t memory_mask = 0;
+ int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right;
+ int mpcc_hactive = h_active / opp_cnt;
+ /* Each memory instance is 2048x(314x2) bits to support half line of 4096 */
+ int odm_mem_count = (h_active + 2047) / 2048;
+
+ /*
+ * display <= 4k : 2 memories + 2 pipes
+ * 4k < display <= 8k : 4 memories + 2 pipes
+ * 8k < display <= 12k : 6 memories + 4 pipes
+ */
+ if (opp_cnt == 4) {
+ if (odm_mem_count <= 2)
+ memory_mask = 0x3;
+ else if (odm_mem_count <= 4)
+ memory_mask = 0xf;
+ else
+ memory_mask = 0x3f;
+ } else {
+ if (odm_mem_count <= 2)
+ memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2);
+ else if (odm_mem_count <= 4)
+ memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2);
+ else
+ memory_mask = 0x77;
+ }
+
+ REG_SET(OPTC_MEMORY_CONFIG, 0,
+ OPTC_MEM_SEL, memory_mask);
+
+ if (opp_cnt == 2) {
+ REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0,
+ OPTC_NUM_OF_INPUT_SEGMENT, 1,
+ OPTC_SEG0_SRC_SEL, opp_id[0],
+ OPTC_SEG1_SRC_SEL, opp_id[1]);
+ } else if (opp_cnt == 4) {
+ REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0,
+ OPTC_NUM_OF_INPUT_SEGMENT, 3,
+ OPTC_SEG0_SRC_SEL, opp_id[0],
+ OPTC_SEG1_SRC_SEL, opp_id[1],
+ OPTC_SEG2_SRC_SEL, opp_id[2],
+ OPTC_SEG3_SRC_SEL, opp_id[3]);
+ }
+
+ REG_UPDATE(OPTC_WIDTH_CONTROL,
+ OPTC_SEGMENT_WIDTH, mpcc_hactive);
+
+ REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, opp_cnt - 1);
+ optc1->opp_count = opp_cnt;
+}
+
+static bool optc35_enable_crtc(struct timing_generator *optc)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+ /* opp instance for OTG, 1 to 1 mapping and odm will adjust */
+ REG_UPDATE(OPTC_DATA_SOURCE_SELECT,
+ OPTC_SEG0_SRC_SEL, optc->inst);
+
+ /* VTG enable first is for HW workaround */
+ REG_UPDATE(CONTROL,
+ VTG0_ENABLE, 1);
+
+ REG_SEQ_START();
+
+ /* Enable CRTC */
+ REG_UPDATE_2(OTG_CONTROL,
+ OTG_DISABLE_POINT_CNTL, 2,
+ OTG_MASTER_EN, 1);
+
+ REG_SEQ_SUBMIT();
+ REG_SEQ_WAIT_DONE();
+
+ return true;
+}
+
+/* disable_crtc */
+static bool optc35_disable_crtc(struct timing_generator *optc)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+ /* disable otg request until end of the first line
+ * in the vertical blank region
+ */
+ REG_UPDATE(OTG_CONTROL,
+ OTG_MASTER_EN, 0);
+
+ REG_UPDATE(CONTROL,
+ VTG0_ENABLE, 0);
+
+ /* CRTC disabled, so disable clock. */
+ REG_WAIT(OTG_CLOCK_CONTROL,
+ OTG_BUSY, 0,
+ 1, 100000);
+ optc1_clear_optc_underflow(optc);
+
+ return true;
+}
+
+static void optc35_phantom_crtc_post_enable(struct timing_generator *optc)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+ /* Disable immediately. */
+ REG_UPDATE_2(OTG_CONTROL, OTG_DISABLE_POINT_CNTL, 0, OTG_MASTER_EN, 0);
+
+ /* CRTC disabled, so disable clock. */
+ REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000);
+}
+
+static bool optc35_configure_crc(struct timing_generator *optc,
+ const struct crc_params *params)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+ if (!optc1_is_tg_enabled(optc))
+ return false;
+ REG_WRITE(OTG_CRC_CNTL, 0);
+ if (!params->enable)
+ return true;
+ REG_UPDATE_2(OTG_CRC0_WINDOWA_X_CONTROL,
+ OTG_CRC0_WINDOWA_X_START, params->windowa_x_start,
+ OTG_CRC0_WINDOWA_X_END, params->windowa_x_end);
+ REG_UPDATE_2(OTG_CRC0_WINDOWA_Y_CONTROL,
+ OTG_CRC0_WINDOWA_Y_START, params->windowa_y_start,
+ OTG_CRC0_WINDOWA_Y_END, params->windowa_y_end);
+ REG_UPDATE_2(OTG_CRC0_WINDOWB_X_CONTROL,
+ OTG_CRC0_WINDOWB_X_START, params->windowb_x_start,
+ OTG_CRC0_WINDOWB_X_END, params->windowb_x_end);
+ REG_UPDATE_2(OTG_CRC0_WINDOWB_Y_CONTROL,
+ OTG_CRC0_WINDOWB_Y_START, params->windowb_y_start,
+ OTG_CRC0_WINDOWB_Y_END, params->windowb_y_end);
+ if (optc1->base.ctx->dc->debug.otg_crc_db && optc1->tg_mask->OTG_CRC_WINDOW_DB_EN != 0) {
+ REG_UPDATE_4(OTG_CRC_CNTL,
+ OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
+ OTG_CRC0_SELECT, params->selection,
+ OTG_CRC_EN, 1,
+ OTG_CRC_WINDOW_DB_EN, 1);
+ } else
+ REG_UPDATE_3(OTG_CRC_CNTL,
+ OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
+ OTG_CRC0_SELECT, params->selection,
+ OTG_CRC_EN, 1);
+ return true;
+}
+
+static struct timing_generator_funcs dcn35_tg_funcs = {
+ .validate_timing = optc1_validate_timing,
+ .program_timing = optc1_program_timing,
+ .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
+ .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
+ .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
+ .program_global_sync = optc1_program_global_sync,
+ .enable_crtc = optc35_enable_crtc,
+ .disable_crtc = optc35_disable_crtc,
+ .immediate_disable_crtc = optc31_immediate_disable_crtc,
+ .phantom_crtc_post_enable = optc35_phantom_crtc_post_enable,
+ /* used by enable_timing_synchronization. Not need for FPGA */
+ .is_counter_moving = optc1_is_counter_moving,
+ .get_position = optc1_get_position,
+ .get_frame_count = optc1_get_vblank_counter,
+ .get_scanoutpos = optc1_get_crtc_scanoutpos,
+ .get_otg_active_size = optc1_get_otg_active_size,
+ .set_early_control = optc1_set_early_control,
+ /* used by enable_timing_synchronization. Not need for FPGA */
+ .wait_for_state = optc1_wait_for_state,
+ .set_blank_color = optc3_program_blank_color,
+ .did_triggered_reset_occur = optc1_did_triggered_reset_occur,
+ .triplebuffer_lock = optc3_triplebuffer_lock,
+ .triplebuffer_unlock = optc2_triplebuffer_unlock,
+ .enable_reset_trigger = optc1_enable_reset_trigger,
+ .enable_crtc_reset = optc1_enable_crtc_reset,
+ .disable_reset_trigger = optc1_disable_reset_trigger,
+ .lock = optc3_lock,
+ .unlock = optc1_unlock,
+ .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
+ .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
+ .enable_optc_clock = optc1_enable_optc_clock,
+ .set_drr = optc31_set_drr,
+ .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
+ .set_vtotal_min_max = optc1_set_vtotal_min_max,
+ .set_static_screen_control = optc1_set_static_screen_control,
+ .program_stereo = optc1_program_stereo,
+ .is_stereo_left_eye = optc1_is_stereo_left_eye,
+ .tg_init = optc3_tg_init,
+ .is_tg_enabled = optc1_is_tg_enabled,
+ .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
+ .clear_optc_underflow = optc1_clear_optc_underflow,
+ .setup_global_swap_lock = NULL,
+ .get_crc = optc1_get_crc,
+ .configure_crc = optc35_configure_crc,
+ .set_dsc_config = optc3_set_dsc_config,
+ .get_dsc_status = optc2_get_dsc_status,
+ .set_dwb_source = NULL,
+ .set_odm_bypass = optc32_set_odm_bypass,
+ .set_odm_combine = optc35_set_odm_combine,
+ .get_optc_source = optc2_get_optc_source,
+ .set_h_timing_div_manual_mode = optc32_set_h_timing_div_manual_mode,
+ .set_out_mux = optc3_set_out_mux,
+ .set_drr_trigger_window = optc3_set_drr_trigger_window,
+ .set_vtotal_change_limit = optc3_set_vtotal_change_limit,
+ .set_gsl = optc2_set_gsl,
+ .set_gsl_source_select = optc2_set_gsl_source_select,
+ .set_vtg_params = optc1_set_vtg_params,
+ .program_manual_trigger = optc2_program_manual_trigger,
+ .setup_manual_trigger = optc2_setup_manual_trigger,
+ .get_hw_timing = optc1_get_hw_timing,
+ .init_odm = optc3_init_odm,
+};
+
+void dcn35_timing_generator_init(struct optc *optc1)
+{
+ optc1->base.funcs = &dcn35_tg_funcs;
+
+ optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
+ optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
+
+ optc1->min_h_blank = 32;
+ optc1->min_v_blank = 3;
+ optc1->min_v_blank_interlace = 5;
+ optc1->min_h_sync_width = 4;
+ optc1->min_v_sync_width = 1;
+
+ dcn35_timing_generator_set_fgcg(
+ optc1, CTX->dc->debug.enable_fine_grain_clock_gating.bits.optc);
+}
+
+void dcn35_timing_generator_set_fgcg(struct optc *optc1, bool enable)
+{
+ REG_UPDATE(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, !enable);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.h
new file mode 100644
index 000000000000..1f422e4c468f
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_OPTC_DCN35_H__
+#define __DC_OPTC_DCN35_H__
+
+#include "dcn10/dcn10_optc.h"
+#include "dcn32/dcn32_optc.h"
+#define OPTC_COMMON_MASK_SH_LIST_DCN3_5(mask_sh)\
+ OPTC_COMMON_MASK_SH_LIST_DCN3_2(mask_sh),\
+ SF(OTG0_OTG_CRC_CNTL, OTG_CRC_WINDOW_DB_EN, mask_sh),\
+ SF(OTG0_OTG_CRC1_DATA_RG, CRC1_R_CR, mask_sh),\
+ SF(OTG0_OTG_CRC1_DATA_RG, CRC1_G_Y, mask_sh),\
+ SF(OTG0_OTG_CRC1_DATA_B, CRC1_B_CB, mask_sh),\
+ SF(OTG0_OTG_CRC2_DATA_RG, CRC2_R_CR, mask_sh),\
+ SF(OTG0_OTG_CRC2_DATA_RG, CRC2_G_Y, mask_sh),\
+ SF(OTG0_OTG_CRC2_DATA_B, CRC2_B_CB, mask_sh),\
+ SF(OTG0_OTG_CRC3_DATA_RG, CRC3_R_CR, mask_sh),\
+ SF(OTG0_OTG_CRC3_DATA_RG, CRC3_G_Y, mask_sh),\
+ SF(OTG0_OTG_CRC3_DATA_B, CRC3_B_CB, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_END, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL_READBACK, OTG_CRC0_WINDOWA_X_START_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL_READBACK, OTG_CRC0_WINDOWA_X_END_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL_READBACK, OTG_CRC0_WINDOWA_Y_START_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL_READBACK, OTG_CRC0_WINDOWA_Y_END_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL_READBACK, OTG_CRC0_WINDOWB_X_START_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL_READBACK, OTG_CRC0_WINDOWB_X_END_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL_READBACK, OTG_CRC0_WINDOWB_Y_START_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL_READBACK, OTG_CRC0_WINDOWB_Y_END_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL_READBACK, OTG_CRC1_WINDOWA_X_START_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL_READBACK, OTG_CRC1_WINDOWA_X_END_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL_READBACK, OTG_CRC1_WINDOWA_Y_START_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL_READBACK, OTG_CRC1_WINDOWA_Y_END_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG_CRC1_WINDOWB_X_START_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG_CRC1_WINDOWB_X_END_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG_CRC1_WINDOWB_Y_START_READBACK, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG_CRC1_WINDOWB_Y_END_READBACK, mask_sh),\
+ SF(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, mask_sh)
+
+void dcn35_timing_generator_init(struct optc *optc1);
+
+void dcn35_timing_generator_set_fgcg(struct optc *optc1, bool enable);
+
+#endif /* __DC_OPTC_DCN35_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c
new file mode 100644
index 000000000000..d19db8e9b8a5
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c
@@ -0,0 +1,559 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "reg_helper.h"
+#include "core_types.h"
+#include "dcn35_pg_cntl.h"
+#include "dccg.h"
+
+#define TO_DCN_PG_CNTL(pg_cntl)\
+ container_of(pg_cntl, struct dcn_pg_cntl, base)
+
+#define REG(reg) \
+ (pg_cntl_dcn->regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+ pg_cntl_dcn->pg_cntl_shift->field_name, pg_cntl_dcn->pg_cntl_mask->field_name
+
+#define CTX \
+ pg_cntl_dcn->base.ctx
+#define DC_LOGGER \
+ pg_cntl->ctx->logger
+
+static bool pg_cntl35_dsc_pg_status(struct pg_cntl *pg_cntl, unsigned int dsc_inst)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg)
+ return true;
+
+ switch (dsc_inst) {
+ case 0: /* DSC0 */
+ REG_GET(DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ case 1: /* DSC1 */
+ REG_GET(DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ case 2: /* DSC2 */
+ REG_GET(DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ case 3: /* DSC3 */
+ REG_GET(DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ break;
+ }
+
+ return pwr_status == 0;
+}
+
+void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t power_gate = power_on ? 0 : 1;
+ uint32_t pwr_status = power_on ? 0 : 2;
+ uint32_t org_ip_request_cntl = 0;
+ bool block_enabled;
+
+ /*need to enable dscclk regardless DSC_PG*/
+ if (pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc && power_on)
+ pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc(
+ pg_cntl->ctx->dc->res_pool->dccg, dsc_inst);
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->debug.disable_dsc_power_gate ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ block_enabled = pg_cntl35_dsc_pg_status(pg_cntl, dsc_inst);
+ if (power_on) {
+ if (block_enabled)
+ return;
+ } else {
+ if (!block_enabled)
+ return;
+ }
+
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+ if (org_ip_request_cntl == 0)
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+ switch (dsc_inst) {
+ case 0: /* DSC0 */
+ REG_UPDATE(DOMAIN16_PG_CONFIG,
+ DOMAIN_POWER_GATE, power_gate);
+
+ REG_WAIT(DOMAIN16_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+ 1, 1000);
+ break;
+ case 1: /* DSC1 */
+ REG_UPDATE(DOMAIN17_PG_CONFIG,
+ DOMAIN_POWER_GATE, power_gate);
+
+ REG_WAIT(DOMAIN17_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+ 1, 1000);
+ break;
+ case 2: /* DSC2 */
+ REG_UPDATE(DOMAIN18_PG_CONFIG,
+ DOMAIN_POWER_GATE, power_gate);
+
+ REG_WAIT(DOMAIN18_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+ 1, 1000);
+ break;
+ case 3: /* DSC3 */
+ REG_UPDATE(DOMAIN19_PG_CONFIG,
+ DOMAIN_POWER_GATE, power_gate);
+
+ REG_WAIT(DOMAIN19_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+ 1, 1000);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ break;
+ }
+
+ if (dsc_inst < MAX_PIPES)
+ pg_cntl->pg_pipe_res_enable[PG_DSC][dsc_inst] = power_on;
+
+ if (pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc && !power_on) {
+ /*this is to disable dscclk*/
+ pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc(
+ pg_cntl->ctx->dc->res_pool->dccg, dsc_inst);
+ }
+}
+
+static bool pg_cntl35_hubp_dpp_pg_status(struct pg_cntl *pg_cntl, unsigned int hubp_dpp_inst)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ switch (hubp_dpp_inst) {
+ case 0:
+ /* DPP0 & HUBP0 */
+ REG_GET(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ case 1:
+ /* DPP1 & HUBP1 */
+ REG_GET(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ case 2:
+ /* DPP2 & HUBP2 */
+ REG_GET(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ case 3:
+ /* DPP3 & HUBP3 */
+ REG_GET(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ break;
+ }
+
+ return pwr_status == 0;
+}
+
+void pg_cntl35_hubp_dpp_pg_control(struct pg_cntl *pg_cntl, unsigned int hubp_dpp_inst, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t power_gate = power_on ? 0 : 1;
+ uint32_t pwr_status = power_on ? 0 : 2;
+ uint32_t org_ip_request_cntl;
+ bool block_enabled;
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->debug.disable_hubp_power_gate ||
+ pg_cntl->ctx->dc->debug.disable_dpp_power_gate ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ block_enabled = pg_cntl35_hubp_dpp_pg_status(pg_cntl, hubp_dpp_inst);
+ if (power_on) {
+ if (block_enabled)
+ return;
+ } else {
+ if (!block_enabled)
+ return;
+ }
+
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+ if (org_ip_request_cntl == 0)
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+ switch (hubp_dpp_inst) {
+ case 0:
+ /* DPP0 & HUBP0 */
+ REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+ break;
+ case 1:
+ /* DPP1 & HUBP1 */
+ REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+ break;
+ case 2:
+ /* DPP2 & HUBP2 */
+ REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+ break;
+ case 3:
+ /* DPP3 & HUBP3 */
+ REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ break;
+ }
+
+ DC_LOG_DEBUG("HUBP DPP instance %d, power %s", hubp_dpp_inst,
+ power_on ? "ON" : "OFF");
+
+ if (hubp_dpp_inst < MAX_PIPES) {
+ pg_cntl->pg_pipe_res_enable[PG_HUBP][hubp_dpp_inst] = power_on;
+ pg_cntl->pg_pipe_res_enable[PG_DPP][hubp_dpp_inst] = power_on;
+ }
+}
+
+static bool pg_cntl35_hpo_pg_status(struct pg_cntl *pg_cntl)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ REG_GET(DOMAIN25_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+ return pwr_status == 0;
+}
+
+void pg_cntl35_hpo_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t power_gate = power_on ? 0 : 1;
+ uint32_t pwr_status = power_on ? 0 : 2;
+ uint32_t org_ip_request_cntl;
+ uint32_t power_forceon;
+ bool block_enabled;
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->debug.disable_hpo_power_gate ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ block_enabled = pg_cntl35_hpo_pg_status(pg_cntl);
+ if (power_on) {
+ if (block_enabled)
+ return;
+ } else {
+ if (!block_enabled)
+ return;
+ }
+
+ REG_GET(DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon);
+ if (power_forceon)
+ return;
+
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+ if (org_ip_request_cntl == 0)
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+ REG_UPDATE(DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+ pg_cntl->pg_res_enable[PG_HPO] = power_on;
+}
+
+static bool pg_cntl35_io_clk_status(struct pg_cntl *pg_cntl)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ REG_GET(DOMAIN22_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+ return pwr_status == 0;
+}
+
+void pg_cntl35_io_clk_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t power_gate = power_on ? 0 : 1;
+ uint32_t pwr_status = power_on ? 0 : 2;
+ uint32_t org_ip_request_cntl;
+ uint32_t power_forceon;
+ bool block_enabled;
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ block_enabled = pg_cntl35_io_clk_status(pg_cntl);
+ if (power_on) {
+ if (block_enabled)
+ return;
+ } else {
+ if (!block_enabled)
+ return;
+ }
+
+ REG_GET(DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon);
+ if (power_forceon)
+ return;
+
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+ if (org_ip_request_cntl == 0)
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+ /* DCCG, DIO, DCIO */
+ REG_UPDATE(DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+ pg_cntl->pg_res_enable[PG_DCCG] = power_on;
+ pg_cntl->pg_res_enable[PG_DIO] = power_on;
+ pg_cntl->pg_res_enable[PG_DCIO] = power_on;
+}
+
+void pg_cntl35_set_force_poweron_domain22(struct pg_cntl *pg_cntl, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+
+ REG_UPDATE(DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, power_on ? 1 : 0);
+}
+
+static bool pg_cntl35_plane_otg_status(struct pg_cntl *pg_cntl)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ REG_GET(DOMAIN24_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+ return pwr_status == 0;
+}
+
+void pg_cntl35_mpcc_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int mpcc_inst, bool power_on)
+{
+ if (pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ if (mpcc_inst >= 0 && mpcc_inst < MAX_PIPES)
+ pg_cntl->pg_pipe_res_enable[PG_MPCC][mpcc_inst] = power_on;
+}
+
+void pg_cntl35_opp_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int opp_inst, bool power_on)
+{
+ if (pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ if (opp_inst >= 0 && opp_inst < MAX_PIPES)
+ pg_cntl->pg_pipe_res_enable[PG_OPP][opp_inst] = power_on;
+}
+
+void pg_cntl35_optc_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int optc_inst, bool power_on)
+{
+ if (pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ if (optc_inst >= 0 && optc_inst < MAX_PIPES)
+ pg_cntl->pg_pipe_res_enable[PG_OPTC][optc_inst] = power_on;
+}
+
+void pg_cntl35_plane_otg_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t power_gate = power_on ? 0 : 1;
+ uint32_t pwr_status = power_on ? 0 : 2;
+ uint32_t org_ip_request_cntl;
+ int i;
+ bool block_enabled;
+ bool all_mpcc_disabled = true, all_opp_disabled = true;
+ bool all_optc_disabled = true, all_stream_disabled = true;
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->debug.disable_optc_power_gate ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ block_enabled = pg_cntl35_plane_otg_status(pg_cntl);
+ if (power_on) {
+ if (block_enabled)
+ return;
+ } else {
+ if (!block_enabled)
+ return;
+ }
+
+ for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &pg_cntl->ctx->dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (pipe_ctx) {
+ if (pipe_ctx->stream)
+ all_stream_disabled = false;
+ }
+
+ if (pg_cntl->pg_pipe_res_enable[PG_MPCC][i])
+ all_mpcc_disabled = false;
+
+ if (pg_cntl->pg_pipe_res_enable[PG_OPP][i])
+ all_opp_disabled = false;
+
+ if (pg_cntl->pg_pipe_res_enable[PG_OPTC][i])
+ all_optc_disabled = false;
+ }
+
+ if (!power_on) {
+ if (!all_mpcc_disabled || !all_opp_disabled || !all_optc_disabled
+ || !all_stream_disabled || pg_cntl->pg_res_enable[PG_DWB])
+ return;
+ }
+
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+ if (org_ip_request_cntl == 0)
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+ /* MPC, OPP, OPTC, DWB */
+ REG_UPDATE(DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+ for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
+ pg_cntl->pg_pipe_res_enable[PG_MPCC][i] = power_on;
+ pg_cntl->pg_pipe_res_enable[PG_OPP][i] = power_on;
+ pg_cntl->pg_pipe_res_enable[PG_OPTC][i] = power_on;
+ }
+ pg_cntl->pg_res_enable[PG_DWB] = power_on;
+}
+
+void pg_cntl35_dwb_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+ if (pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ pg_cntl->pg_res_enable[PG_DWB] = power_on;
+}
+
+static bool pg_cntl35_mem_status(struct pg_cntl *pg_cntl)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ REG_GET(DOMAIN23_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+ return pwr_status == 0;
+}
+
+void pg_cntl35_init_pg_status(struct pg_cntl *pg_cntl)
+{
+ int i = 0;
+ bool block_enabled;
+
+ pg_cntl->pg_res_enable[PG_HPO] = pg_cntl35_hpo_pg_status(pg_cntl);
+
+ block_enabled = pg_cntl35_io_clk_status(pg_cntl);
+ pg_cntl->pg_res_enable[PG_DCCG] = block_enabled;
+ pg_cntl->pg_res_enable[PG_DIO] = block_enabled;
+ pg_cntl->pg_res_enable[PG_DCIO] = block_enabled;
+
+ block_enabled = pg_cntl35_mem_status(pg_cntl);
+ pg_cntl->pg_res_enable[PG_DCHUBBUB] = block_enabled;
+ pg_cntl->pg_res_enable[PG_DCHVM] = block_enabled;
+
+ for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
+ block_enabled = pg_cntl35_hubp_dpp_pg_status(pg_cntl, i);
+ pg_cntl->pg_pipe_res_enable[PG_HUBP][i] = block_enabled;
+ pg_cntl->pg_pipe_res_enable[PG_DPP][i] = block_enabled;
+
+ block_enabled = pg_cntl35_dsc_pg_status(pg_cntl, i);
+ pg_cntl->pg_pipe_res_enable[PG_DSC][i] = block_enabled;
+ }
+
+ block_enabled = pg_cntl35_plane_otg_status(pg_cntl);
+ for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
+ pg_cntl->pg_pipe_res_enable[PG_MPCC][i] = block_enabled;
+ pg_cntl->pg_pipe_res_enable[PG_OPP][i] = block_enabled;
+ pg_cntl->pg_pipe_res_enable[PG_OPTC][i] = block_enabled;
+ }
+ pg_cntl->pg_res_enable[PG_DWB] = block_enabled;
+}
+
+static const struct pg_cntl_funcs pg_cntl35_funcs = {
+ .init_pg_status = pg_cntl35_init_pg_status,
+ .dsc_pg_control = pg_cntl35_dsc_pg_control,
+ .hubp_dpp_pg_control = pg_cntl35_hubp_dpp_pg_control,
+ .hpo_pg_control = pg_cntl35_hpo_pg_control,
+ .io_clk_pg_control = pg_cntl35_io_clk_pg_control,
+ .plane_otg_pg_control = pg_cntl35_plane_otg_pg_control,
+ .mpcc_pg_control = pg_cntl35_mpcc_pg_control,
+ .opp_pg_control = pg_cntl35_opp_pg_control,
+ .optc_pg_control = pg_cntl35_optc_pg_control,
+ .dwb_pg_control = pg_cntl35_dwb_pg_control,
+ .set_force_poweron_domain22 = pg_cntl35_set_force_poweron_domain22
+};
+
+struct pg_cntl *pg_cntl35_create(
+ struct dc_context *ctx,
+ const struct pg_cntl_registers *regs,
+ const struct pg_cntl_shift *pg_cntl_shift,
+ const struct pg_cntl_mask *pg_cntl_mask)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = kzalloc(sizeof(*pg_cntl_dcn), GFP_KERNEL);
+ struct pg_cntl *base;
+
+ if (pg_cntl_dcn == NULL) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+ base = &pg_cntl_dcn->base;
+ base->ctx = ctx;
+ base->funcs = &pg_cntl35_funcs;
+
+ pg_cntl_dcn->regs = regs;
+ pg_cntl_dcn->pg_cntl_shift = pg_cntl_shift;
+ pg_cntl_dcn->pg_cntl_mask = pg_cntl_mask;
+
+ memset(base->pg_pipe_res_enable, 0, PG_HW_PIPE_RESOURCES_NUM_ELEMENT * MAX_PIPES * sizeof(bool));
+ memset(base->pg_res_enable, 0, PG_HW_RESOURCES_NUM_ELEMENT * sizeof(bool));
+
+ return &pg_cntl_dcn->base;
+}
+
+void dcn_pg_cntl_destroy(struct pg_cntl **pg_cntl)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(*pg_cntl);
+
+ kfree(pg_cntl_dcn);
+ *pg_cntl = NULL;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.h
new file mode 100644
index 000000000000..069dae08e222
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.h
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef _DCN35_PG_CNTL_H_
+#define _DCN35_PG_CNTL_H_
+
+#include "pg_cntl.h"
+
+#define PG_CNTL_REG_LIST_DCN35()\
+ SR(DOMAIN0_PG_CONFIG), \
+ SR(DOMAIN1_PG_CONFIG), \
+ SR(DOMAIN2_PG_CONFIG), \
+ SR(DOMAIN3_PG_CONFIG), \
+ SR(DOMAIN16_PG_CONFIG), \
+ SR(DOMAIN17_PG_CONFIG), \
+ SR(DOMAIN18_PG_CONFIG), \
+ SR(DOMAIN19_PG_CONFIG), \
+ SR(DOMAIN22_PG_CONFIG), \
+ SR(DOMAIN23_PG_CONFIG), \
+ SR(DOMAIN24_PG_CONFIG), \
+ SR(DOMAIN25_PG_CONFIG), \
+ SR(DOMAIN0_PG_STATUS), \
+ SR(DOMAIN1_PG_STATUS), \
+ SR(DOMAIN2_PG_STATUS), \
+ SR(DOMAIN3_PG_STATUS), \
+ SR(DOMAIN16_PG_STATUS), \
+ SR(DOMAIN17_PG_STATUS), \
+ SR(DOMAIN18_PG_STATUS), \
+ SR(DOMAIN19_PG_STATUS), \
+ SR(DOMAIN22_PG_STATUS), \
+ SR(DOMAIN23_PG_STATUS), \
+ SR(DOMAIN24_PG_STATUS), \
+ SR(DOMAIN25_PG_STATUS), \
+ SR(DC_IP_REQUEST_CNTL)
+
+#define PG_CNTL_SF(reg_name, field_name, post_fix)\
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
+#define PG_CNTL_MASK_SH_LIST_DCN35(mask_sh) \
+ PG_CNTL_SF(DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN24_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN0_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN1_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN2_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN3_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN16_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN17_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN18_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN19_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN22_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN23_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN24_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN25_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh)
+
+#define PG_CNTL_REG_FIELD_LIST(type) \
+ type IPS2;\
+ type IPS1;\
+ type IPS0;\
+ type IPS0_All
+
+#define PG_CNTL_DCN35_REG_FIELD_LIST(type) \
+ type IP_REQUEST_EN; \
+ type DOMAIN_POWER_FORCEON; \
+ type DOMAIN_POWER_GATE; \
+ type DOMAIN_DESIRED_PWR_STATE; \
+ type DOMAIN_PGFSM_PWR_STATUS
+
+struct pg_cntl_shift {
+ PG_CNTL_REG_FIELD_LIST(uint8_t);
+ PG_CNTL_DCN35_REG_FIELD_LIST(uint8_t);
+};
+
+struct pg_cntl_mask {
+ PG_CNTL_REG_FIELD_LIST(uint32_t);
+ PG_CNTL_DCN35_REG_FIELD_LIST(uint32_t);
+};
+
+struct pg_cntl_registers {
+ uint32_t LONO_STATE;
+ uint32_t DC_IP_REQUEST_CNTL;
+ uint32_t DOMAIN0_PG_CONFIG;
+ uint32_t DOMAIN1_PG_CONFIG;
+ uint32_t DOMAIN2_PG_CONFIG;
+ uint32_t DOMAIN3_PG_CONFIG;
+ uint32_t DOMAIN16_PG_CONFIG;
+ uint32_t DOMAIN17_PG_CONFIG;
+ uint32_t DOMAIN18_PG_CONFIG;
+ uint32_t DOMAIN19_PG_CONFIG;
+ uint32_t DOMAIN22_PG_CONFIG;
+ uint32_t DOMAIN23_PG_CONFIG;
+ uint32_t DOMAIN24_PG_CONFIG;
+ uint32_t DOMAIN25_PG_CONFIG;
+ uint32_t DOMAIN0_PG_STATUS;
+ uint32_t DOMAIN1_PG_STATUS;
+ uint32_t DOMAIN2_PG_STATUS;
+ uint32_t DOMAIN3_PG_STATUS;
+ uint32_t DOMAIN16_PG_STATUS;
+ uint32_t DOMAIN17_PG_STATUS;
+ uint32_t DOMAIN18_PG_STATUS;
+ uint32_t DOMAIN19_PG_STATUS;
+ uint32_t DOMAIN22_PG_STATUS;
+ uint32_t DOMAIN23_PG_STATUS;
+ uint32_t DOMAIN24_PG_STATUS;
+ uint32_t DOMAIN25_PG_STATUS;
+};
+
+struct dcn_pg_cntl {
+ struct pg_cntl base;
+ const struct pg_cntl_registers *regs;
+ const struct pg_cntl_shift *pg_cntl_shift;
+ const struct pg_cntl_mask *pg_cntl_mask;
+};
+
+void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bool power_on);
+void pg_cntl35_hubp_dpp_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int hubp_dpp_inst, bool power_on);
+void pg_cntl35_hpo_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void pg_cntl35_io_clk_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void pg_cntl35_plane_otg_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void pg_cntl35_mpcc_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int mpcc_inst, bool power_on);
+void pg_cntl35_opp_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int opp_inst, bool power_on);
+void pg_cntl35_optc_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int optc_inst, bool power_on);
+void pg_cntl35_dwb_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void pg_cntl35_init_pg_status(struct pg_cntl *pg_cntl);
+void pg_cntl35_set_force_poweron_domain22(struct pg_cntl *pg_cntl, bool power_on);
+
+struct pg_cntl *pg_cntl35_create(
+ struct dc_context *ctx,
+ const struct pg_cntl_registers *regs,
+ const struct pg_cntl_shift *pg_cntl_shift,
+ const struct pg_cntl_mask *pg_cntl_mask);
+
+void dcn_pg_cntl_destroy(struct pg_cntl **pg_cntl);
+
+#endif /* DCN35_PG_CNTL */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c
new file mode 100644
index 000000000000..70ef1e7ff841
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c
@@ -0,0 +1,2148 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dc.h"
+
+#include "dcn31/dcn31_init.h"
+#include "dcn35/dcn35_init.h"
+
+#include "resource.h"
+#include "include/irq_service_interface.h"
+#include "dcn35_resource.h"
+#include "dml2/dml2_wrapper.h"
+
+#include "dcn20/dcn20_resource.h"
+#include "dcn30/dcn30_resource.h"
+#include "dcn31/dcn31_resource.h"
+#include "dcn32/dcn32_resource.h"
+
+#include "dcn10/dcn10_ipp.h"
+#include "dcn30/dcn30_hubbub.h"
+#include "dcn31/dcn31_hubbub.h"
+#include "dcn35/dcn35_hubbub.h"
+#include "dcn32/dcn32_mpc.h"
+#include "dcn35/dcn35_hubp.h"
+#include "irq/dcn35/irq_service_dcn35.h"
+#include "dcn35/dcn35_dpp.h"
+#include "dcn35/dcn35_optc.h"
+#include "dcn20/dcn20_hwseq.h"
+#include "dcn30/dcn30_hwseq.h"
+#include "dce110/dce110_hwseq.h"
+#include "dcn35/dcn35_opp.h"
+#include "dcn35/dcn35_dsc.h"
+#include "dcn30/dcn30_vpg.h"
+#include "dcn30/dcn30_afmt.h"
+#include "dcn31/dcn31_dio_link_encoder.h"
+#include "dcn35/dcn35_dio_stream_encoder.h"
+#include "dcn31/dcn31_hpo_dp_stream_encoder.h"
+#include "dcn31/dcn31_hpo_dp_link_encoder.h"
+#include "dcn32/dcn32_hpo_dp_link_encoder.h"
+#include "link.h"
+#include "dcn31/dcn31_apg.h"
+#include "dcn32/dcn32_dio_link_encoder.h"
+#include "dcn31/dcn31_vpg.h"
+#include "dcn31/dcn31_afmt.h"
+#include "dce/dce_clock_source.h"
+#include "dce/dce_audio.h"
+#include "dce/dce_hwseq.h"
+#include "clk_mgr.h"
+#include "virtual/virtual_stream_encoder.h"
+#include "dce110/dce110_resource.h"
+#include "dml/display_mode_vba.h"
+#include "dcn35/dcn35_dccg.h"
+#include "dcn35/dcn35_pg_cntl.h"
+#include "dcn10/dcn10_resource.h"
+#include "dcn31/dcn31_panel_cntl.h"
+#include "dcn35/dcn35_hwseq.h"
+#include "dcn35_dio_link_encoder.h"
+#include "dml/dcn31/dcn31_fpu.h" /*todo*/
+#include "dml/dcn35/dcn35_fpu.h"
+#include "dcn35/dcn35_dwb.h"
+#include "dcn35/dcn35_mmhubbub.h"
+
+#include "dcn/dcn_3_5_0_offset.h"
+#include "dcn/dcn_3_5_0_sh_mask.h"
+#include "nbio/nbio_7_11_0_offset.h"
+#include "mmhub/mmhub_3_3_0_offset.h"
+#include "mmhub/mmhub_3_3_0_sh_mask.h"
+
+#define DSCC0_DSCC_CONFIG0__ICH_RESET_AT_END_OF_LINE__SHIFT 0x0
+#define DSCC0_DSCC_CONFIG0__ICH_RESET_AT_END_OF_LINE_MASK 0x0000000FL
+
+#include "reg_helper.h"
+#include "dce/dmub_abm.h"
+#include "dce/dmub_psr.h"
+#include "dce/dce_aux.h"
+#include "dce/dce_i2c.h"
+#include "dml/dcn31/display_mode_vba_31.h" /*temp*/
+#include "vm_helper.h"
+#include "dcn20/dcn20_vmid.h"
+
+#include "link_enc_cfg.h"
+#define DC_LOGGER_INIT(logger)
+
+enum dcn35_clk_src_array_id {
+ DCN35_CLK_SRC_PLL0,
+ DCN35_CLK_SRC_PLL1,
+ DCN35_CLK_SRC_PLL2,
+ DCN35_CLK_SRC_PLL3,
+ DCN35_CLK_SRC_PLL4,
+ DCN35_CLK_SRC_TOTAL
+};
+
+/* begin *********************
+ * macros to expend register list macro defined in HW object header file
+ */
+
+/* DCN */
+/* TODO awful hack. fixup dcn20_dwb.h */
+#undef BASE_INNER
+#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg]
+
+#define BASE(seg) BASE_INNER(seg)
+
+#define SR(reg_name)\
+ REG_STRUCT.reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \
+ reg ## reg_name
+
+#define SR_ARR(reg_name, id) \
+ REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name
+
+#define SR_ARR_INIT(reg_name, id, value) \
+ REG_STRUCT[id].reg_name = value
+
+#define SRI(reg_name, block, id)\
+ REG_STRUCT.reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+ reg ## block ## id ## _ ## reg_name
+
+#define SRI_ARR(reg_name, block, id)\
+ REG_STRUCT[id].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+ reg ## block ## id ## _ ## reg_name
+
+#define SR_ARR_I2C(reg_name, id) \
+ REG_STRUCT[id-1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name
+
+#define SRI_ARR_I2C(reg_name, block, id)\
+ REG_STRUCT[id-1].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+ reg ## block ## id ## _ ## reg_name
+
+#define SRI_ARR_ALPHABET(reg_name, block, index, id)\
+ REG_STRUCT[index].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+ reg ## block ## id ## _ ## reg_name
+
+#define SRI2(reg_name, block, id)\
+ .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \
+ reg ## reg_name
+
+#define SRI2_ARR(reg_name, block, id)\
+ REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \
+ reg ## reg_name
+
+#define SRIR(var_name, reg_name, block, id)\
+ .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+ reg ## block ## id ## _ ## reg_name
+
+#define SRII(reg_name, block, id)\
+ REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+ reg ## block ## id ## _ ## reg_name
+
+#define SRII_ARR_2(reg_name, block, id, inst)\
+ REG_STRUCT[inst].reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+ reg ## block ## id ## _ ## reg_name
+
+#define SRII_MPC_RMU(reg_name, block, id)\
+ .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+ reg ## block ## id ## _ ## reg_name
+
+#define SRII_DWB(reg_name, temp_name, block, id)\
+ REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \
+ reg ## block ## id ## _ ## temp_name
+
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
+#define DCCG_SRII(reg_name, block, id)\
+ REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+ reg ## block ## id ## _ ## reg_name
+
+#define VUPDATE_SRII(reg_name, block, id)\
+ REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \
+ reg ## reg_name ## _ ## block ## id
+
+/* NBIO */
+#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg]
+
+#define NBIO_BASE(seg) \
+ NBIO_BASE_INNER(seg)
+
+#define NBIO_SR(reg_name)\
+ REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \
+ regBIF_BX2_ ## reg_name
+
+#define NBIO_SR_ARR(reg_name, id)\
+ REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \
+ regBIF_BX2_ ## reg_name
+
+#define bios_regs_init() \
+ ( \
+ NBIO_SR(BIOS_SCRATCH_3),\
+ NBIO_SR(BIOS_SCRATCH_6)\
+ )
+
+static struct bios_registers bios_regs;
+
+#define clk_src_regs_init(index, pllid)\
+ CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid)
+
+static struct dce110_clk_src_regs clk_src_regs[5];
+
+static const struct dce110_clk_src_shift cs_shift = {
+ CS_COMMON_MASK_SH_LIST_DCN3_1_4(__SHIFT)
+};
+
+static const struct dce110_clk_src_mask cs_mask = {
+ CS_COMMON_MASK_SH_LIST_DCN3_1_4(_MASK)
+};
+
+#define abm_regs_init(id)\
+ ABM_DCN32_REG_LIST_RI(id)
+
+static struct dce_abm_registers abm_regs[4];
+
+static const struct dce_abm_shift abm_shift = {
+ ABM_MASK_SH_LIST_DCN35(__SHIFT)
+};
+
+static const struct dce_abm_mask abm_mask = {
+ ABM_MASK_SH_LIST_DCN35(_MASK)
+};
+
+#define audio_regs_init(id)\
+ AUD_COMMON_REG_LIST_RI(id)
+
+static struct dce_audio_registers audio_regs[7];
+
+
+#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\
+ SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\
+ SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\
+ AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)
+
+static const struct dce_audio_shift audio_shift = {
+ DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce_audio_mask audio_mask = {
+ DCE120_AUD_COMMON_MASK_SH_LIST(_MASK)
+};
+
+#define vpg_regs_init(id)\
+ VPG_DCN31_REG_LIST_RI(id)
+
+static struct dcn31_vpg_registers vpg_regs[10];
+
+static const struct dcn31_vpg_shift vpg_shift = {
+ DCN31_VPG_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn31_vpg_mask vpg_mask = {
+ DCN31_VPG_MASK_SH_LIST(_MASK)
+};
+
+#define afmt_regs_init(id)\
+ AFMT_DCN31_REG_LIST_RI(id)
+
+static struct dcn31_afmt_registers afmt_regs[6];
+
+static const struct dcn31_afmt_shift afmt_shift = {
+ DCN31_AFMT_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn31_afmt_mask afmt_mask = {
+ DCN31_AFMT_MASK_SH_LIST(_MASK)
+};
+
+#define apg_regs_init(id)\
+ APG_DCN31_REG_LIST_RI(id)
+
+static struct dcn31_apg_registers apg_regs[4];
+
+static const struct dcn31_apg_shift apg_shift = {
+ DCN31_APG_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn31_apg_mask apg_mask = {
+ DCN31_APG_MASK_SH_LIST(_MASK)
+};
+
+#define stream_enc_regs_init(id)\
+ SE_DCN35_REG_LIST_RI(id)
+
+static struct dcn10_stream_enc_registers stream_enc_regs[5];
+
+static const struct dcn10_stream_encoder_shift se_shift = {
+ SE_COMMON_MASK_SH_LIST_DCN35(__SHIFT)
+};
+
+static const struct dcn10_stream_encoder_mask se_mask = {
+ SE_COMMON_MASK_SH_LIST_DCN35(_MASK)
+};
+
+#define aux_regs_init(id)\
+ DCN2_AUX_REG_LIST_RI(id)
+
+static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5];
+
+#define hpd_regs_init(id)\
+ HPD_REG_LIST_RI(id)
+
+static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5];
+
+
+static const struct dce110_aux_registers_shift aux_shift = {
+ DCN_AUX_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce110_aux_registers_mask aux_mask = {
+ DCN_AUX_MASK_SH_LIST(_MASK)
+};
+
+#define link_regs_init(id, phyid)\
+ ( \
+ LE_DCN35_REG_LIST_RI(id), \
+ UNIPHY_DCN2_REG_LIST_RI(id, phyid)\
+ )
+
+static struct dcn10_link_enc_registers link_enc_regs[5];
+
+static const struct dcn10_link_enc_shift le_shift = {
+ LINK_ENCODER_MASK_SH_LIST_DCN35(__SHIFT), \
+ //DPCS_DCN31_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn10_link_enc_mask le_mask = {
+ LINK_ENCODER_MASK_SH_LIST_DCN35(_MASK), \
+ //DPCS_DCN31_MASK_SH_LIST(_MASK)
+};
+
+#define hpo_dp_stream_encoder_reg_init(id)\
+ DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id)
+
+static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4];
+
+static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = {
+ DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = {
+ DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK)
+};
+
+#define hpo_dp_link_encoder_reg_init(id)\
+ DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id)
+ /*DCN3_1_RDPCSTX_REG_LIST(0),*/
+ /*DCN3_1_RDPCSTX_REG_LIST(1),*/
+ /*DCN3_1_RDPCSTX_REG_LIST(2),*/
+ /*DCN3_1_RDPCSTX_REG_LIST(3),*/
+
+static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[2];
+
+static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = {
+ DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = {
+ DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(_MASK)
+};
+
+#define dpp_regs_init(id)\
+ DPP_REG_LIST_DCN35_RI(id)
+
+static struct dcn3_dpp_registers dpp_regs[4];
+
+static const struct dcn35_dpp_shift tf_shift = {
+ DPP_REG_LIST_SH_MASK_DCN35(__SHIFT)
+};
+
+static const struct dcn35_dpp_mask tf_mask = {
+ DPP_REG_LIST_SH_MASK_DCN35(_MASK)
+};
+
+#define opp_regs_init(id)\
+ OPP_REG_LIST_DCN35_RI(id)
+
+static struct dcn35_opp_registers opp_regs[4];
+
+static const struct dcn35_opp_shift opp_shift = {
+ OPP_MASK_SH_LIST_DCN35(__SHIFT)
+};
+
+static const struct dcn35_opp_mask opp_mask = {
+ OPP_MASK_SH_LIST_DCN35(_MASK)
+};
+
+#define aux_engine_regs_init(id)\
+ ( \
+ AUX_COMMON_REG_LIST0_RI(id), \
+ SR_ARR_INIT(AUXN_IMPCAL, id, 0), \
+ SR_ARR_INIT(AUXP_IMPCAL, id, 0), \
+ SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK) \
+ )
+
+static struct dce110_aux_registers aux_engine_regs[5];
+
+#define dwbc_regs_dcn3_init(id)\
+ DWBC_COMMON_REG_LIST_DCN30_RI(id)
+
+static struct dcn30_dwbc_registers dwbc35_regs[1];
+
+static const struct dcn35_dwbc_shift dwbc35_shift = {
+ DWBC_COMMON_MASK_SH_LIST_DCN35(__SHIFT)
+};
+
+static const struct dcn35_dwbc_mask dwbc35_mask = {
+ DWBC_COMMON_MASK_SH_LIST_DCN35(_MASK)
+};
+
+#define mcif_wb_regs_dcn3_init(id)\
+ MCIF_WB_COMMON_REG_LIST_DCN3_5_RI(id)
+
+static struct dcn35_mmhubbub_registers mcif_wb35_regs[1];
+
+static const struct dcn35_mmhubbub_shift mcif_wb35_shift = {
+ MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(__SHIFT)
+};
+
+static const struct dcn35_mmhubbub_mask mcif_wb35_mask = {
+ MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(_MASK)
+};
+
+#define dsc_regsDCN35_init(id)\
+ DSC_REG_LIST_DCN20_RI(id)
+
+static struct dcn20_dsc_registers dsc_regs[4];
+
+static const struct dcn35_dsc_shift dsc_shift = {
+ DSC_REG_LIST_SH_MASK_DCN35(__SHIFT)
+};
+
+static const struct dcn35_dsc_mask dsc_mask = {
+ DSC_REG_LIST_SH_MASK_DCN35(_MASK)
+};
+
+static struct dcn30_mpc_registers mpc_regs;
+
+#define dcn_mpc_regs_init() \
+ MPC_REG_LIST_DCN3_2_RI(0),\
+ MPC_REG_LIST_DCN3_2_RI(1),\
+ MPC_REG_LIST_DCN3_2_RI(2),\
+ MPC_REG_LIST_DCN3_2_RI(3),\
+ MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0),\
+ MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1),\
+ MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2),\
+ MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3),\
+ MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0)
+
+static const struct dcn30_mpc_shift mpc_shift = {
+ MPC_COMMON_MASK_SH_LIST_DCN32(__SHIFT)
+};
+
+static const struct dcn30_mpc_mask mpc_mask = {
+ MPC_COMMON_MASK_SH_LIST_DCN32(_MASK)
+};
+
+#define optc_regs_init(id)\
+ OPTC_COMMON_REG_LIST_DCN3_5_RI(id)
+
+static struct dcn_optc_registers optc_regs[4];
+
+static const struct dcn_optc_shift optc_shift = {
+ OPTC_COMMON_MASK_SH_LIST_DCN3_5(__SHIFT)
+};
+
+static const struct dcn_optc_mask optc_mask = {
+ OPTC_COMMON_MASK_SH_LIST_DCN3_5(_MASK)
+};
+
+#define hubp_regs_init(id)\
+ HUBP_REG_LIST_DCN30_RI(id)
+
+static struct dcn_hubp2_registers hubp_regs[4];
+
+
+static const struct dcn35_hubp2_shift hubp_shift = {
+ HUBP_MASK_SH_LIST_DCN35(__SHIFT)
+};
+
+static const struct dcn35_hubp2_mask hubp_mask = {
+ HUBP_MASK_SH_LIST_DCN35(_MASK)
+};
+
+static struct dcn_hubbub_registers hubbub_reg;
+
+#define hubbub_reg_init()\
+ HUBBUB_REG_LIST_DCN35(0)
+
+static const struct dcn_hubbub_shift hubbub_shift = {
+ HUBBUB_MASK_SH_LIST_DCN35(__SHIFT)
+};
+
+static const struct dcn_hubbub_mask hubbub_mask = {
+ HUBBUB_MASK_SH_LIST_DCN35(_MASK)
+};
+
+static struct dccg_registers dccg_regs;
+
+#define dccg_regs_init()\
+ DCCG_REG_LIST_DCN35()
+
+static const struct dccg_shift dccg_shift = {
+ DCCG_MASK_SH_LIST_DCN35(__SHIFT)
+};
+
+static const struct dccg_mask dccg_mask = {
+ DCCG_MASK_SH_LIST_DCN35(_MASK)
+};
+
+static struct pg_cntl_registers pg_cntl_regs;
+
+#define pg_cntl_dcn35_regs_init() \
+ PG_CNTL_REG_LIST_DCN35()
+
+static const struct pg_cntl_shift pg_cntl_shift = {
+ PG_CNTL_MASK_SH_LIST_DCN35(__SHIFT)
+};
+
+static const struct pg_cntl_mask pg_cntl_mask = {
+ PG_CNTL_MASK_SH_LIST_DCN35(_MASK)
+};
+
+#define SRII2(reg_name_pre, reg_name_post, id)\
+ .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \
+ ## id ## _ ## reg_name_post ## _BASE_IDX) + \
+ reg ## reg_name_pre ## id ## _ ## reg_name_post
+
+static struct dce_hwseq_registers hwseq_reg;
+
+#define hwseq_reg_init()\
+ HWSEQ_DCN35_REG_LIST()
+
+#define HWSEQ_DCN35_MASK_SH_LIST(mask_sh)\
+ HWSEQ_DCN_MASK_SH_LIST(mask_sh), \
+ HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \
+ HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \
+ HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN24_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
+ HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \
+ HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \
+ HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \
+ HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \
+ HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DISPCLK_R_DMU_GATE_DIS, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DISPCLK_G_RBBMIF_GATE_DIS, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, RBBMIF_FGCG_REP_DIS, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DPREFCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DISPCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DPPCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DTBCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DCFCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DPIACLK_ALLOW_DS_CLKSTOP, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, LONO_FGCG_REP_DIS, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, LONO_DISPCLK_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, LONO_SOCCLK_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, LONO_DMCUBCLK_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_FE_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_FE_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_FE_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh)
+
+static const struct dce_hwseq_shift hwseq_shift = {
+ HWSEQ_DCN35_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce_hwseq_mask hwseq_mask = {
+ HWSEQ_DCN35_MASK_SH_LIST(_MASK)
+};
+
+#define vmid_regs_init(id)\
+ DCN20_VMID_REG_LIST_RI(id)
+
+static struct dcn_vmid_registers vmid_regs[16];
+
+static const struct dcn20_vmid_shift vmid_shifts = {
+ DCN20_VMID_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dcn20_vmid_mask vmid_masks = {
+ DCN20_VMID_MASK_SH_LIST(_MASK)
+};
+
+static const struct resource_caps res_cap_dcn35 = {
+ .num_timing_generator = 4,
+ .num_opp = 4,
+ .num_video_plane = 4,
+ .num_audio = 5,
+ .num_stream_encoder = 5,
+ .num_dig_link_enc = 5,
+ .num_hpo_dp_stream_encoder = 4,
+ .num_hpo_dp_link_encoder = 2,
+ .num_pll = 4,/*1 c10 edp, 3xc20 combo PHY*/
+ .num_dwb = 1,
+ .num_ddc = 5,
+ .num_vmid = 16,
+ .num_mpc_3dlut = 2,
+ .num_dsc = 4,
+};
+
+static const struct dc_plane_cap plane_cap = {
+ .type = DC_PLANE_TYPE_DCN_UNIVERSAL,
+ .per_pixel_alpha = true,
+
+ .pixel_format_support = {
+ .argb8888 = true,
+ .nv12 = true,
+ .fp16 = true,
+ .p010 = true,
+ .ayuv = false,
+ },
+
+ .max_upscale_factor = {
+ .argb8888 = 16000,
+ .nv12 = 16000,
+ .fp16 = 16000
+ },
+
+ // 6:1 downscaling ratio: 1000/6 = 166.666
+ .max_downscale_factor = {
+ .argb8888 = 167,
+ .nv12 = 167,
+ .fp16 = 167
+ },
+ 64,
+ 64
+};
+
+static const struct dc_debug_options debug_defaults_drv = {
+ .disable_dmcu = true,
+ .force_abm_enable = false,
+ .timing_trace = false,
+ .clock_trace = true,
+ .disable_pplib_clock_request = false,
+ .pipe_split_policy = MPC_SPLIT_AVOID,
+ .force_single_disp_pipe_split = false,
+ .disable_dcc = DCC_ENABLE,
+ .disable_dpp_power_gate = true,
+ .disable_hubp_power_gate = true,
+ .disable_clock_gate = true,
+ .disable_dsc_power_gate = true,
+ .vsr_support = true,
+ .performance_trace = false,
+ .max_downscale_src_width = 4096,/*upto true 4k*/
+ .disable_pplib_wm_range = false,
+ .scl_reset_length10 = true,
+ .sanity_checks = false,
+ .underflow_assert_delay_us = 0xFFFFFFFF,
+ .dwb_fi_phase = -1, // -1 = disable,
+ .dmub_command_table = true,
+ .pstate_enabled = true,
+ .use_max_lb = true,
+ .enable_mem_low_power = {
+ .bits = {
+ .vga = false,
+ .i2c = true,
+ .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled
+ .dscl = true,
+ .cm = false,
+ .mpc = true,
+ .optc = true,
+ .vpg = true,
+ .afmt = true,
+ }
+ },
+ .root_clock_optimization = {
+ .bits = {
+ .dpp = true,
+ .dsc = true,/*dscclk and dsc pg*/
+ .hdmistream = true,
+ .hdmichar = true,
+ .dpstream = true,
+ .symclk32_se = true,
+ .symclk32_le = true,
+ .symclk_fe = true,
+ .physymclk = true,
+ .dpiasymclk = true,
+ }
+ },
+ .seamless_boot_odm_combine = DML_FAIL_SOURCE_PIXEL_FORMAT,
+ .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/
+ .using_dml2 = true,
+ .support_eDP1_5 = true,
+ .enable_hpo_pg_support = false,
+ .enable_legacy_fast_update = true,
+ .enable_single_display_2to1_odm_policy = false,
+ .disable_idle_power_optimizations = true,
+ .dmcub_emulation = false,
+ .disable_boot_optimizations = false,
+ .disable_unbounded_requesting = false,
+ .disable_mem_low_power = false,
+ //must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions
+ .enable_double_buffered_dsc_pg_support = true,
+ .enable_dp_dig_pixel_rate_div_policy = 1,
+ .disable_z10 = false,
+ .ignore_pg = true,
+ .psp_disabled_wa = true,
+ .ips2_eval_delay_us = 200,
+ .ips2_entry_delay_us = 400
+};
+
+static const struct dc_panel_config panel_config_defaults = {
+ .psr = {
+ .disable_psr = false,
+ .disallow_psrsu = false,
+ },
+ .ilr = {
+ .optimize_edp_link_rate = true,
+ },
+};
+
+static void dcn35_dpp_destroy(struct dpp **dpp)
+{
+ kfree(TO_DCN20_DPP(*dpp));
+ *dpp = NULL;
+}
+
+static struct dpp *dcn35_dpp_create(struct dc_context *ctx, uint32_t inst)
+{
+ struct dcn3_dpp *dpp = kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL);
+ bool success = (dpp != NULL);
+
+ if (!success)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT dpp_regs
+ dpp_regs_init(0),
+ dpp_regs_init(1),
+ dpp_regs_init(2),
+ dpp_regs_init(3);
+
+ success = dpp35_construct(dpp, ctx, inst, &dpp_regs[inst], &tf_shift,
+ &tf_mask);
+ if (success) {
+ dpp35_set_fgcg(
+ dpp,
+ ctx->dc->debug.enable_fine_grain_clock_gating.bits.dpp);
+ return &dpp->base;
+ }
+
+ BREAK_TO_DEBUGGER();
+ kfree(dpp);
+ return NULL;
+}
+
+static struct output_pixel_processor *dcn35_opp_create(
+ struct dc_context *ctx, uint32_t inst)
+{
+ struct dcn20_opp *opp =
+ kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL);
+
+ if (!opp) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT opp_regs
+ opp_regs_init(0),
+ opp_regs_init(1),
+ opp_regs_init(2),
+ opp_regs_init(3);
+
+ dcn35_opp_construct(opp, ctx, inst,
+ &opp_regs[inst], &opp_shift, &opp_mask);
+
+ dcn35_opp_set_fgcg(opp, ctx->dc->debug.enable_fine_grain_clock_gating.bits.opp);
+
+ return &opp->base;
+}
+
+static struct dce_aux *dcn31_aux_engine_create(
+ struct dc_context *ctx,
+ uint32_t inst)
+{
+ struct aux_engine_dce110 *aux_engine =
+ kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL);
+
+ if (!aux_engine)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT aux_engine_regs
+ aux_engine_regs_init(0),
+ aux_engine_regs_init(1),
+ aux_engine_regs_init(2),
+ aux_engine_regs_init(3),
+ aux_engine_regs_init(4);
+
+ dce110_aux_engine_construct(aux_engine, ctx, inst,
+ SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
+ &aux_engine_regs[inst],
+ &aux_mask,
+ &aux_shift,
+ ctx->dc->caps.extended_aux_timeout_support);
+
+ return &aux_engine->base;
+}
+
+#define i2c_inst_regs_init(id)\
+ I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id)
+
+static struct dce_i2c_registers i2c_hw_regs[5];
+
+static const struct dce_i2c_shift i2c_shifts = {
+ I2C_COMMON_MASK_SH_LIST_DCN35(__SHIFT)
+};
+
+static const struct dce_i2c_mask i2c_masks = {
+ I2C_COMMON_MASK_SH_LIST_DCN35(_MASK)
+};
+
+/* ========================================================== */
+
+/*
+ * DPIA index | Preferred Encoder | Host Router
+ * 0 | C | 0
+ * 1 | First Available | 0
+ * 2 | D | 1
+ * 3 | First Available | 1
+ */
+/* ========================================================== */
+static const enum engine_id dpia_to_preferred_enc_id_table[] = {
+ ENGINE_ID_DIGC,
+ ENGINE_ID_DIGC,
+ ENGINE_ID_DIGD,
+ ENGINE_ID_DIGD
+};
+
+static enum engine_id dcn35_get_preferred_eng_id_dpia(unsigned int dpia_index)
+{
+ return dpia_to_preferred_enc_id_table[dpia_index];
+}
+
+static struct dce_i2c_hw *dcn31_i2c_hw_create(
+ struct dc_context *ctx,
+ uint32_t inst)
+{
+ struct dce_i2c_hw *dce_i2c_hw =
+ kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL);
+
+ if (!dce_i2c_hw)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT i2c_hw_regs
+ i2c_inst_regs_init(1),
+ i2c_inst_regs_init(2),
+ i2c_inst_regs_init(3),
+ i2c_inst_regs_init(4),
+ i2c_inst_regs_init(5);
+
+ dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst,
+ &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks);
+
+ return dce_i2c_hw;
+}
+static struct mpc *dcn35_mpc_create(
+ struct dc_context *ctx,
+ int num_mpcc,
+ int num_rmu)
+{
+ struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), GFP_KERNEL);
+
+ if (!mpc30)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT mpc_regs
+ dcn_mpc_regs_init();
+
+ dcn32_mpc_construct(mpc30, ctx,
+ &mpc_regs,
+ &mpc_shift,
+ &mpc_mask,
+ num_mpcc,
+ num_rmu);
+
+ return &mpc30->base;
+}
+
+static struct hubbub *dcn35_hubbub_create(struct dc_context *ctx)
+{
+ int i;
+
+ struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub),
+ GFP_KERNEL);
+
+ if (!hubbub3)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT hubbub_reg
+ hubbub_reg_init();
+
+#undef REG_STRUCT
+#define REG_STRUCT vmid_regs
+ vmid_regs_init(0),
+ vmid_regs_init(1),
+ vmid_regs_init(2),
+ vmid_regs_init(3),
+ vmid_regs_init(4),
+ vmid_regs_init(5),
+ vmid_regs_init(6),
+ vmid_regs_init(7),
+ vmid_regs_init(8),
+ vmid_regs_init(9),
+ vmid_regs_init(10),
+ vmid_regs_init(11),
+ vmid_regs_init(12),
+ vmid_regs_init(13),
+ vmid_regs_init(14),
+ vmid_regs_init(15);
+
+ hubbub35_construct(hubbub3, ctx,
+ &hubbub_reg,
+ &hubbub_shift,
+ &hubbub_mask,
+ 384,/*ctx->dc->dml.ip.det_buffer_size_kbytes,*/
+ 8, /*ctx->dc->dml.ip.pixel_chunk_size_kbytes,*/
+ 1792 /*ctx->dc->dml.ip.config_return_buffer_size_in_kbytes*/);
+
+
+ for (i = 0; i < res_cap_dcn35.num_vmid; i++) {
+ struct dcn20_vmid *vmid = &hubbub3->vmid[i];
+
+ vmid->ctx = ctx;
+
+ vmid->regs = &vmid_regs[i];
+ vmid->shifts = &vmid_shifts;
+ vmid->masks = &vmid_masks;
+ }
+
+ return &hubbub3->base;
+}
+
+static struct timing_generator *dcn35_timing_generator_create(
+ struct dc_context *ctx,
+ uint32_t instance)
+{
+ struct optc *tgn10 =
+ kzalloc(sizeof(struct optc), GFP_KERNEL);
+
+ if (!tgn10)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT optc_regs
+ optc_regs_init(0),
+ optc_regs_init(1),
+ optc_regs_init(2),
+ optc_regs_init(3);
+
+ tgn10->base.inst = instance;
+ tgn10->base.ctx = ctx;
+
+ tgn10->tg_regs = &optc_regs[instance];
+ tgn10->tg_shift = &optc_shift;
+ tgn10->tg_mask = &optc_mask;
+
+ dcn35_timing_generator_init(tgn10);
+
+ return &tgn10->base;
+}
+
+static const struct encoder_feature_support link_enc_feature = {
+ .max_hdmi_deep_color = COLOR_DEPTH_121212,
+ .max_hdmi_pixel_clock = 600000,
+ .hdmi_ycbcr420_supported = true,
+ .dp_ycbcr420_supported = true,
+ .fec_supported = true,
+ .flags.bits.IS_HBR2_CAPABLE = true,
+ .flags.bits.IS_HBR3_CAPABLE = true,
+ .flags.bits.IS_TPS3_CAPABLE = true,
+ .flags.bits.IS_TPS4_CAPABLE = true
+};
+
+static struct link_encoder *dcn35_link_encoder_create(
+ struct dc_context *ctx,
+ const struct encoder_init_data *enc_init_data)
+{
+ struct dcn20_link_encoder *enc20 =
+ kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);
+
+ if (!enc20)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT link_enc_aux_regs
+ aux_regs_init(0),
+ aux_regs_init(1),
+ aux_regs_init(2),
+ aux_regs_init(3),
+ aux_regs_init(4);
+
+#undef REG_STRUCT
+#define REG_STRUCT link_enc_hpd_regs
+ hpd_regs_init(0),
+ hpd_regs_init(1),
+ hpd_regs_init(2),
+ hpd_regs_init(3),
+ hpd_regs_init(4);
+
+#undef REG_STRUCT
+#define REG_STRUCT link_enc_regs
+ link_regs_init(0, A),
+ link_regs_init(1, B),
+ link_regs_init(2, C),
+ link_regs_init(3, D),
+ link_regs_init(4, E);
+
+ dcn35_link_encoder_construct(enc20,
+ enc_init_data,
+ &link_enc_feature,
+ &link_enc_regs[enc_init_data->transmitter],
+ &link_enc_aux_regs[enc_init_data->channel - 1],
+ &link_enc_hpd_regs[enc_init_data->hpd_source],
+ &le_shift,
+ &le_mask);
+
+ return &enc20->enc10.base;
+}
+
+/* Create a minimal link encoder object not associated with a particular
+ * physical connector.
+ * resource_funcs.link_enc_create_minimal
+ */
+static struct link_encoder *dcn31_link_enc_create_minimal(
+ struct dc_context *ctx, enum engine_id eng_id)
+{
+ struct dcn20_link_encoder *enc20;
+
+ if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc)
+ return NULL;
+
+ enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);
+ if (!enc20)
+ return NULL;
+
+ dcn31_link_encoder_construct_minimal(
+ enc20,
+ ctx,
+ &link_enc_feature,
+ &link_enc_regs[eng_id - ENGINE_ID_DIGA],
+ eng_id);
+
+ return &enc20->enc10.base;
+}
+
+static struct panel_cntl *dcn31_panel_cntl_create(const struct panel_cntl_init_data *init_data)
+{
+ struct dcn31_panel_cntl *panel_cntl =
+ kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL);
+
+ if (!panel_cntl)
+ return NULL;
+
+ dcn31_panel_cntl_construct(panel_cntl, init_data);
+
+ return &panel_cntl->base;
+}
+
+static void read_dce_straps(
+ struct dc_context *ctx,
+ struct resource_straps *straps)
+{
+ generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX),
+ FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio);
+
+}
+
+static struct audio *dcn31_create_audio(
+ struct dc_context *ctx, unsigned int inst)
+{
+
+#undef REG_STRUCT
+#define REG_STRUCT audio_regs
+ audio_regs_init(0),
+ audio_regs_init(1),
+ audio_regs_init(2),
+ audio_regs_init(3),
+ audio_regs_init(4);
+ audio_regs_init(5);
+ audio_regs_init(6);
+
+ return dce_audio_create(ctx, inst,
+ &audio_regs[inst], &audio_shift, &audio_mask);
+}
+
+static struct vpg *dcn31_vpg_create(
+ struct dc_context *ctx,
+ uint32_t inst)
+{
+ struct dcn31_vpg *vpg31 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL);
+
+ if (!vpg31)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT vpg_regs
+ vpg_regs_init(0),
+ vpg_regs_init(1),
+ vpg_regs_init(2),
+ vpg_regs_init(3),
+ vpg_regs_init(4),
+ vpg_regs_init(5),
+ vpg_regs_init(6),
+ vpg_regs_init(7),
+ vpg_regs_init(8),
+ vpg_regs_init(9);
+
+ vpg31_construct(vpg31, ctx, inst,
+ &vpg_regs[inst],
+ &vpg_shift,
+ &vpg_mask);
+
+ return &vpg31->base;
+}
+
+static struct afmt *dcn31_afmt_create(
+ struct dc_context *ctx,
+ uint32_t inst)
+{
+ struct dcn31_afmt *afmt31 = kzalloc(sizeof(struct dcn31_afmt), GFP_KERNEL);
+
+ if (!afmt31)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT afmt_regs
+ afmt_regs_init(0),
+ afmt_regs_init(1),
+ afmt_regs_init(2),
+ afmt_regs_init(3),
+ afmt_regs_init(4),
+ afmt_regs_init(5);
+
+ afmt31_construct(afmt31, ctx, inst,
+ &afmt_regs[inst],
+ &afmt_shift,
+ &afmt_mask);
+
+ // Light sleep by default, no need to power down here
+
+ return &afmt31->base;
+}
+
+static struct apg *dcn31_apg_create(
+ struct dc_context *ctx,
+ uint32_t inst)
+{
+ struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL);
+
+ if (!apg31)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT apg_regs
+ apg_regs_init(0),
+ apg_regs_init(1),
+ apg_regs_init(2),
+ apg_regs_init(3);
+
+ apg31_construct(apg31, ctx, inst,
+ &apg_regs[inst],
+ &apg_shift,
+ &apg_mask);
+
+ return &apg31->base;
+}
+
+static struct stream_encoder *dcn35_stream_encoder_create(
+ enum engine_id eng_id,
+ struct dc_context *ctx)
+{
+ struct dcn10_stream_encoder *enc1;
+ struct vpg *vpg;
+ struct afmt *afmt;
+ int vpg_inst;
+ int afmt_inst;
+
+ /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */
+ if (eng_id <= ENGINE_ID_DIGF) {
+ vpg_inst = eng_id;
+ afmt_inst = eng_id;
+ } else
+ return NULL;
+
+ enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
+ vpg = dcn31_vpg_create(ctx, vpg_inst);
+ afmt = dcn31_afmt_create(ctx, afmt_inst);
+
+ if (!enc1 || !vpg || !afmt) {
+ kfree(enc1);
+ kfree(vpg);
+ kfree(afmt);
+ return NULL;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT stream_enc_regs
+ stream_enc_regs_init(0),
+ stream_enc_regs_init(1),
+ stream_enc_regs_init(2),
+ stream_enc_regs_init(3),
+ stream_enc_regs_init(4);
+
+ dcn35_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios,
+ eng_id, vpg, afmt,
+ &stream_enc_regs[eng_id],
+ &se_shift, &se_mask);
+
+ return &enc1->base;
+}
+
+static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create(
+ enum engine_id eng_id,
+ struct dc_context *ctx)
+{
+ struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31;
+ struct vpg *vpg;
+ struct apg *apg;
+ uint32_t hpo_dp_inst;
+ uint32_t vpg_inst;
+ uint32_t apg_inst;
+
+ ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3));
+ hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0;
+
+ /* Mapping of VPG register blocks to HPO DP block instance:
+ * VPG[6] -> HPO_DP[0]
+ * VPG[7] -> HPO_DP[1]
+ * VPG[8] -> HPO_DP[2]
+ * VPG[9] -> HPO_DP[3]
+ */
+ vpg_inst = hpo_dp_inst + 6;
+
+ /* Mapping of APG register blocks to HPO DP block instance:
+ * APG[0] -> HPO_DP[0]
+ * APG[1] -> HPO_DP[1]
+ * APG[2] -> HPO_DP[2]
+ * APG[3] -> HPO_DP[3]
+ */
+ apg_inst = hpo_dp_inst;
+
+ /* allocate HPO stream encoder and create VPG sub-block */
+ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL);
+ vpg = dcn31_vpg_create(ctx, vpg_inst);
+ apg = dcn31_apg_create(ctx, apg_inst);
+
+ if (!hpo_dp_enc31 || !vpg || !apg) {
+ kfree(hpo_dp_enc31);
+ kfree(vpg);
+ kfree(apg);
+ return NULL;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT hpo_dp_stream_enc_regs
+ hpo_dp_stream_encoder_reg_init(0),
+ hpo_dp_stream_encoder_reg_init(1),
+ hpo_dp_stream_encoder_reg_init(2),
+ hpo_dp_stream_encoder_reg_init(3);
+
+ dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios,
+ hpo_dp_inst, eng_id, vpg, apg,
+ &hpo_dp_stream_enc_regs[hpo_dp_inst],
+ &hpo_dp_se_shift, &hpo_dp_se_mask);
+
+ return &hpo_dp_enc31->base;
+}
+
+static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create(
+ uint8_t inst,
+ struct dc_context *ctx)
+{
+ struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31;
+
+ /* allocate HPO link encoder */
+ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL);
+
+#undef REG_STRUCT
+#define REG_STRUCT hpo_dp_link_enc_regs
+ hpo_dp_link_encoder_reg_init(0),
+ hpo_dp_link_encoder_reg_init(1);
+
+ hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst,
+ &hpo_dp_link_enc_regs[inst],
+ &hpo_dp_le_shift, &hpo_dp_le_mask);
+
+ return &hpo_dp_enc31->base;
+}
+
+static struct dce_hwseq *dcn35_hwseq_create(
+ struct dc_context *ctx)
+{
+ struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);
+
+#undef REG_STRUCT
+#define REG_STRUCT hwseq_reg
+ hwseq_reg_init();
+
+ if (hws) {
+ hws->ctx = ctx;
+ hws->regs = &hwseq_reg;
+ hws->shifts = &hwseq_shift;
+ hws->masks = &hwseq_mask;
+ }
+ return hws;
+}
+static const struct resource_create_funcs res_create_funcs = {
+ .read_dce_straps = read_dce_straps,
+ .create_audio = dcn31_create_audio,
+ .create_stream_encoder = dcn35_stream_encoder_create,
+ .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create,
+ .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create,
+ .create_hwseq = dcn35_hwseq_create,
+};
+
+static void dcn35_resource_destruct(struct dcn35_resource_pool *pool)
+{
+ unsigned int i;
+
+ for (i = 0; i < pool->base.stream_enc_count; i++) {
+ if (pool->base.stream_enc[i] != NULL) {
+ if (pool->base.stream_enc[i]->vpg != NULL) {
+ kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg));
+ pool->base.stream_enc[i]->vpg = NULL;
+ }
+ if (pool->base.stream_enc[i]->afmt != NULL) {
+ kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt));
+ pool->base.stream_enc[i]->afmt = NULL;
+ }
+ kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i]));
+ pool->base.stream_enc[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) {
+ if (pool->base.hpo_dp_stream_enc[i] != NULL) {
+ if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) {
+ kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg));
+ pool->base.hpo_dp_stream_enc[i]->vpg = NULL;
+ }
+ if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) {
+ kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg));
+ pool->base.hpo_dp_stream_enc[i]->apg = NULL;
+ }
+ kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i]));
+ pool->base.hpo_dp_stream_enc[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) {
+ if (pool->base.hpo_dp_link_enc[i] != NULL) {
+ kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i]));
+ pool->base.hpo_dp_link_enc[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
+ if (pool->base.dscs[i] != NULL)
+ dcn20_dsc_destroy(&pool->base.dscs[i]);
+ }
+
+ if (pool->base.mpc != NULL) {
+ kfree(TO_DCN20_MPC(pool->base.mpc));
+ pool->base.mpc = NULL;
+ }
+ if (pool->base.hubbub != NULL) {
+ kfree(pool->base.hubbub);
+ pool->base.hubbub = NULL;
+ }
+ for (i = 0; i < pool->base.pipe_count; i++) {
+ if (pool->base.dpps[i] != NULL)
+ dcn35_dpp_destroy(&pool->base.dpps[i]);
+
+ if (pool->base.ipps[i] != NULL)
+ pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]);
+
+ if (pool->base.hubps[i] != NULL) {
+ kfree(TO_DCN20_HUBP(pool->base.hubps[i]));
+ pool->base.hubps[i] = NULL;
+ }
+
+ if (pool->base.irqs != NULL) {
+ dal_irq_service_destroy(&pool->base.irqs);
+ }
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
+ if (pool->base.engines[i] != NULL)
+ dce110_engine_destroy(&pool->base.engines[i]);
+ if (pool->base.hw_i2cs[i] != NULL) {
+ kfree(pool->base.hw_i2cs[i]);
+ pool->base.hw_i2cs[i] = NULL;
+ }
+ if (pool->base.sw_i2cs[i] != NULL) {
+ kfree(pool->base.sw_i2cs[i]);
+ pool->base.sw_i2cs[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_opp; i++) {
+ if (pool->base.opps[i] != NULL)
+ pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
+ if (pool->base.timing_generators[i] != NULL) {
+ kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i]));
+ pool->base.timing_generators[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_dwb; i++) {
+ if (pool->base.dwbc[i] != NULL) {
+ kfree(TO_DCN30_DWBC(pool->base.dwbc[i]));
+ pool->base.dwbc[i] = NULL;
+ }
+ if (pool->base.mcif_wb[i] != NULL) {
+ kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i]));
+ pool->base.mcif_wb[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.audio_count; i++) {
+ if (pool->base.audios[i])
+ dce_aud_destroy(&pool->base.audios[i]);
+ }
+
+ for (i = 0; i < pool->base.clk_src_count; i++) {
+ if (pool->base.clock_sources[i] != NULL) {
+ dcn20_clock_source_destroy(&pool->base.clock_sources[i]);
+ pool->base.clock_sources[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) {
+ if (pool->base.mpc_lut[i] != NULL) {
+ dc_3dlut_func_release(pool->base.mpc_lut[i]);
+ pool->base.mpc_lut[i] = NULL;
+ }
+ if (pool->base.mpc_shaper[i] != NULL) {
+ dc_transfer_func_release(pool->base.mpc_shaper[i]);
+ pool->base.mpc_shaper[i] = NULL;
+ }
+ }
+
+ if (pool->base.dp_clock_source != NULL) {
+ dcn20_clock_source_destroy(&pool->base.dp_clock_source);
+ pool->base.dp_clock_source = NULL;
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
+ if (pool->base.multiple_abms[i] != NULL)
+ dce_abm_destroy(&pool->base.multiple_abms[i]);
+ }
+
+ if (pool->base.psr != NULL)
+ dmub_psr_destroy(&pool->base.psr);
+
+ if (pool->base.pg_cntl != NULL)
+ dcn_pg_cntl_destroy(&pool->base.pg_cntl);
+
+ if (pool->base.dccg != NULL)
+ dcn_dccg_destroy(&pool->base.dccg);
+}
+
+static struct hubp *dcn35_hubp_create(
+ struct dc_context *ctx,
+ uint32_t inst)
+{
+ struct dcn20_hubp *hubp2 =
+ kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL);
+
+ if (!hubp2)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT hubp_regs
+ hubp_regs_init(0),
+ hubp_regs_init(1),
+ hubp_regs_init(2),
+ hubp_regs_init(3);
+
+ if (hubp35_construct(hubp2, ctx, inst,
+ &hubp_regs[inst], &hubp_shift, &hubp_mask))
+ return &hubp2->base;
+
+ BREAK_TO_DEBUGGER();
+ kfree(hubp2);
+ return NULL;
+}
+
+static void dcn35_dwbc_init(struct dcn30_dwbc *dwbc30, struct dc_context *ctx)
+{
+ dcn35_dwbc_set_fgcg(
+ dwbc30, ctx->dc->debug.enable_fine_grain_clock_gating.bits.dwb);
+}
+
+static bool dcn35_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)
+{
+ int i;
+ uint32_t pipe_count = pool->res_cap->num_dwb;
+
+ for (i = 0; i < pipe_count; i++) {
+ struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc),
+ GFP_KERNEL);
+
+ if (!dwbc30) {
+ dm_error("DC: failed to create dwbc30!\n");
+ return false;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT dwbc35_regs
+ dwbc_regs_dcn3_init(0);
+
+ dcn35_dwbc_construct(dwbc30, ctx,
+ &dwbc35_regs[i],
+ &dwbc35_shift,
+ &dwbc35_mask,
+ i);
+
+ pool->dwbc[i] = &dwbc30->base;
+
+ dcn35_dwbc_init(dwbc30, ctx);
+ }
+ return true;
+}
+
+static void dcn35_mmhubbub_init(struct dcn30_mmhubbub *mcif_wb30,
+ struct dc_context *ctx)
+{
+ dcn35_mmhubbub_set_fgcg(
+ mcif_wb30,
+ ctx->dc->debug.enable_fine_grain_clock_gating.bits.mmhubbub);
+}
+
+static bool dcn35_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool)
+{
+ int i;
+ uint32_t pipe_count = pool->res_cap->num_dwb;
+
+ for (i = 0; i < pipe_count; i++) {
+ struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub),
+ GFP_KERNEL);
+
+ if (!mcif_wb30) {
+ dm_error("DC: failed to create mcif_wb30!\n");
+ return false;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT mcif_wb35_regs
+ mcif_wb_regs_dcn3_init(0);
+
+ dcn35_mmhubbub_construct(mcif_wb30, ctx,
+ &mcif_wb35_regs[i],
+ &mcif_wb35_shift,
+ &mcif_wb35_mask,
+ i);
+
+ dcn35_mmhubbub_init(mcif_wb30, ctx);
+
+ pool->mcif_wb[i] = &mcif_wb30->base;
+ }
+ return true;
+}
+
+static struct display_stream_compressor *dcn35_dsc_create(
+ struct dc_context *ctx, uint32_t inst)
+{
+ struct dcn20_dsc *dsc =
+ kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL);
+
+ if (!dsc) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT dsc_regs
+ dsc_regsDCN35_init(0),
+ dsc_regsDCN35_init(1),
+ dsc_regsDCN35_init(2),
+ dsc_regsDCN35_init(3);
+
+ dsc35_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask);
+ dsc35_set_fgcg(dsc,
+ ctx->dc->debug.enable_fine_grain_clock_gating.bits.dsc);
+ return &dsc->base;
+}
+
+static void dcn35_destroy_resource_pool(struct resource_pool **pool)
+{
+ struct dcn35_resource_pool *dcn35_pool = TO_DCN35_RES_POOL(*pool);
+
+ dcn35_resource_destruct(dcn35_pool);
+ kfree(dcn35_pool);
+ *pool = NULL;
+}
+
+static struct clock_source *dcn35_clock_source_create(
+ struct dc_context *ctx,
+ struct dc_bios *bios,
+ enum clock_source_id id,
+ const struct dce110_clk_src_regs *regs,
+ bool dp_clk_src)
+{
+ struct dce110_clk_src *clk_src =
+ kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL);
+
+ if (!clk_src)
+ return NULL;
+
+ if (dcn31_clk_src_construct(clk_src, ctx, bios, id,
+ regs, &cs_shift, &cs_mask)) {
+ clk_src->base.dp_clk_src = dp_clk_src;
+ return &clk_src->base;
+ }
+
+ BREAK_TO_DEBUGGER();
+ return NULL;
+}
+
+static struct dc_cap_funcs cap_funcs = {
+ .get_dcc_compression_cap = dcn20_get_dcc_compression_cap
+};
+
+static void dcn35_get_panel_config_defaults(struct dc_panel_config *panel_config)
+{
+ *panel_config = panel_config_defaults;
+}
+
+
+static bool dcn35_validate_bandwidth(struct dc *dc,
+ struct dc_state *context,
+ bool fast_validate)
+{
+ bool out = false;
+
+ out = dml2_validate(dc, context, fast_validate);
+
+ if (fast_validate)
+ return out;
+
+ DC_FP_START();
+ dcn35_decide_zstate_support(dc, context);
+ DC_FP_END();
+
+ return out;
+}
+
+
+static struct resource_funcs dcn35_res_pool_funcs = {
+ .destroy = dcn35_destroy_resource_pool,
+ .link_enc_create = dcn35_link_encoder_create,
+ .link_enc_create_minimal = dcn31_link_enc_create_minimal,
+ .link_encs_assign = link_enc_cfg_link_encs_assign,
+ .link_enc_unassign = link_enc_cfg_link_enc_unassign,
+ .panel_cntl_create = dcn31_panel_cntl_create,
+ .validate_bandwidth = dcn35_validate_bandwidth,
+ .calculate_wm_and_dlg = NULL,
+ .update_soc_for_wm_a = dcn31_update_soc_for_wm_a,
+ .populate_dml_pipes = dcn35_populate_dml_pipes_from_context_fpu,
+ .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer,
+ .release_pipe = dcn20_release_pipe,
+ .add_stream_to_ctx = dcn30_add_stream_to_ctx,
+ .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
+ .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
+ .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context,
+ .set_mcif_arb_params = dcn30_set_mcif_arb_params,
+ .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
+ .acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut,
+ .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
+ .update_bw_bounding_box = dcn35_update_bw_bounding_box_fpu,
+ .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
+ .get_panel_config_defaults = dcn35_get_panel_config_defaults,
+ .get_preferred_eng_id_dpia = dcn35_get_preferred_eng_id_dpia,
+};
+
+static bool dcn35_resource_construct(
+ uint8_t num_virtual_links,
+ struct dc *dc,
+ struct dcn35_resource_pool *pool)
+{
+ int i;
+ struct dc_context *ctx = dc->ctx;
+ struct irq_service_init_data init_data;
+
+#undef REG_STRUCT
+#define REG_STRUCT bios_regs
+ bios_regs_init();
+
+#undef REG_STRUCT
+#define REG_STRUCT clk_src_regs
+ clk_src_regs_init(0, A),
+ clk_src_regs_init(1, B),
+ clk_src_regs_init(2, C),
+ clk_src_regs_init(3, D),
+ clk_src_regs_init(4, E);
+
+#undef REG_STRUCT
+#define REG_STRUCT abm_regs
+ abm_regs_init(0),
+ abm_regs_init(1),
+ abm_regs_init(2),
+ abm_regs_init(3);
+
+#undef REG_STRUCT
+#define REG_STRUCT dccg_regs
+ dccg_regs_init();
+
+ ctx->dc_bios->regs = &bios_regs;
+
+ pool->base.res_cap = &res_cap_dcn35;
+
+ pool->base.funcs = &dcn35_res_pool_funcs;
+
+ /*************************************************
+ * Resource + asic cap harcoding *
+ *************************************************/
+ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
+ pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
+ dc->caps.max_downscale_ratio = 600;
+ dc->caps.i2c_speed_in_khz = 100;
+ dc->caps.i2c_speed_in_khz_hdcp = 100;
+ dc->caps.max_cursor_size = 256;
+ dc->caps.min_horizontal_blanking_period = 80;
+ dc->caps.dmdata_alloc_size = 2048;
+ dc->caps.max_slave_planes = 2;
+ dc->caps.max_slave_yuv_planes = 2;
+ dc->caps.max_slave_rgb_planes = 2;
+ dc->caps.post_blend_color_processing = true;
+ dc->caps.force_dp_tps4_for_cp2520 = true;
+ if (dc->config.forceHBR2CP2520)
+ dc->caps.force_dp_tps4_for_cp2520 = false;
+ dc->caps.dp_hpo = true;
+ dc->caps.dp_hdmi21_pcon_support = true;
+
+ dc->caps.edp_dsc_support = true;
+ dc->caps.extended_aux_timeout_support = true;
+ dc->caps.dmcub_support = true;
+ dc->caps.is_apu = true;
+ dc->caps.seamless_odm = true;
+
+ dc->caps.zstate_support = true;
+ dc->caps.ips_support = true;
+ dc->caps.max_v_total = (1 << 15) - 1;
+
+ /* Color pipeline capabilities */
+ dc->caps.color.dpp.dcn_arch = 1;
+ dc->caps.color.dpp.input_lut_shared = 0;
+ dc->caps.color.dpp.icsc = 1;
+ dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr
+ dc->caps.color.dpp.dgam_rom_caps.srgb = 1;
+ dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1;
+ dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1;
+ dc->caps.color.dpp.dgam_rom_caps.pq = 1;
+ dc->caps.color.dpp.dgam_rom_caps.hlg = 1;
+ dc->caps.color.dpp.post_csc = 1;
+ dc->caps.color.dpp.gamma_corr = 1;
+ dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+
+ dc->caps.color.dpp.hw_3d_lut = 1;
+ dc->caps.color.dpp.ogam_ram = 0; // no OGAM in DPP since DCN1
+ // no OGAM ROM on DCN301
+ dc->caps.color.dpp.ogam_rom_caps.srgb = 0;
+ dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0;
+ dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0;
+ dc->caps.color.dpp.ogam_rom_caps.pq = 0;
+ dc->caps.color.dpp.ogam_rom_caps.hlg = 0;
+ dc->caps.color.dpp.ocsc = 0;
+
+ dc->caps.color.mpc.gamut_remap = 1;
+ dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2
+ dc->caps.color.mpc.ogam_ram = 1;
+ dc->caps.color.mpc.ogam_rom_caps.srgb = 0;
+ dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0;
+ dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0;
+ dc->caps.color.mpc.ogam_rom_caps.pq = 0;
+ dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
+ dc->caps.color.mpc.ocsc = 1;
+
+ /* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order
+ * to provide some margin.
+ * It's expected for furture ASIC to have equal or higher value, in order to
+ * have determinstic power improvement from generate to genration.
+ * (i.e., we should not expect new ASIC generation with lower vmin rate)
+ */
+ dc->caps.max_disp_clock_khz_at_vmin = 650000;
+
+ /* Use pipe context based otg sync logic */
+ dc->config.use_pipe_ctx_sync_logic = true;
+
+ /* read VBIOS LTTPR caps */
+ {
+ if (ctx->dc_bios->funcs->get_lttpr_caps) {
+ enum bp_result bp_query_result;
+ uint8_t is_vbios_lttpr_enable = 0;
+
+ bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable);
+ dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;
+ }
+
+ /* interop bit is implicit */
+ {
+ dc->caps.vbios_lttpr_aware = true;
+ }
+ }
+
+ if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
+ dc->debug = debug_defaults_drv;
+
+ // Init the vm_helper
+ if (dc->vm_helper)
+ vm_helper_init(dc->vm_helper, 16);
+
+ /*************************************************
+ * Create resources *
+ *************************************************/
+
+ /* Clock Sources for Pixel Clock*/
+ pool->base.clock_sources[DCN35_CLK_SRC_PLL0] =
+ dcn35_clock_source_create(ctx, ctx->dc_bios,
+ CLOCK_SOURCE_COMBO_PHY_PLL0,
+ &clk_src_regs[0], false);
+ pool->base.clock_sources[DCN35_CLK_SRC_PLL1] =
+ dcn35_clock_source_create(ctx, ctx->dc_bios,
+ CLOCK_SOURCE_COMBO_PHY_PLL1,
+ &clk_src_regs[1], false);
+ pool->base.clock_sources[DCN35_CLK_SRC_PLL2] =
+ dcn35_clock_source_create(ctx, ctx->dc_bios,
+ CLOCK_SOURCE_COMBO_PHY_PLL2,
+ &clk_src_regs[2], false);
+ pool->base.clock_sources[DCN35_CLK_SRC_PLL3] =
+ dcn35_clock_source_create(ctx, ctx->dc_bios,
+ CLOCK_SOURCE_COMBO_PHY_PLL3,
+ &clk_src_regs[3], false);
+ pool->base.clock_sources[DCN35_CLK_SRC_PLL4] =
+ dcn35_clock_source_create(ctx, ctx->dc_bios,
+ CLOCK_SOURCE_COMBO_PHY_PLL4,
+ &clk_src_regs[4], false);
+
+ pool->base.clk_src_count = DCN35_CLK_SRC_TOTAL;
+
+ /* todo: not reuse phy_pll registers */
+ pool->base.dp_clock_source =
+ dcn35_clock_source_create(ctx, ctx->dc_bios,
+ CLOCK_SOURCE_ID_DP_DTO,
+ &clk_src_regs[0], true);
+
+ for (i = 0; i < pool->base.clk_src_count; i++) {
+ if (pool->base.clock_sources[i] == NULL) {
+ dm_error("DC: failed to create clock sources!\n");
+ BREAK_TO_DEBUGGER();
+ goto create_fail;
+ }
+ }
+ /*temp till dml2 fully work without dml1*/
+ dml_init_instance(&dc->dml, &dcn3_5_soc, &dcn3_5_ip, DML_PROJECT_DCN31);
+
+ /* TODO: DCCG */
+ pool->base.dccg = dccg35_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask);
+ if (pool->base.dccg == NULL) {
+ dm_error("DC: failed to create dccg!\n");
+ BREAK_TO_DEBUGGER();
+ goto create_fail;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT pg_cntl_regs
+ pg_cntl_dcn35_regs_init();
+
+ pool->base.pg_cntl = pg_cntl35_create(ctx, &pg_cntl_regs, &pg_cntl_shift, &pg_cntl_mask);
+ if (pool->base.pg_cntl == NULL) {
+ dm_error("DC: failed to create power gate control!\n");
+ BREAK_TO_DEBUGGER();
+ goto create_fail;
+ }
+
+ /* TODO: IRQ */
+ init_data.ctx = dc->ctx;
+ pool->base.irqs = dal_irq_service_dcn35_create(&init_data);
+ if (!pool->base.irqs)
+ goto create_fail;
+
+ /* HUBBUB */
+ pool->base.hubbub = dcn35_hubbub_create(ctx);
+ if (pool->base.hubbub == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create hubbub!\n");
+ goto create_fail;
+ }
+
+ /* HUBPs, DPPs, OPPs and TGs */
+ for (i = 0; i < pool->base.pipe_count; i++) {
+ pool->base.hubps[i] = dcn35_hubp_create(ctx, i);
+ if (pool->base.hubps[i] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error(
+ "DC: failed to create hubps!\n");
+ goto create_fail;
+ }
+
+ pool->base.dpps[i] = dcn35_dpp_create(ctx, i);
+ if (pool->base.dpps[i] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error(
+ "DC: failed to create dpps!\n");
+ goto create_fail;
+ }
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_opp; i++) {
+ pool->base.opps[i] = dcn35_opp_create(ctx, i);
+ if (pool->base.opps[i] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error(
+ "DC: failed to create output pixel processor!\n");
+ goto create_fail;
+ }
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
+ pool->base.timing_generators[i] = dcn35_timing_generator_create(
+ ctx, i);
+ if (pool->base.timing_generators[i] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create tg!\n");
+ goto create_fail;
+ }
+ }
+ pool->base.timing_generator_count = i;
+
+ /* PSR */
+ pool->base.psr = dmub_psr_create(ctx);
+ if (pool->base.psr == NULL) {
+ dm_error("DC: failed to create psr obj!\n");
+ BREAK_TO_DEBUGGER();
+ goto create_fail;
+ }
+
+ /* ABM */
+ for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
+ pool->base.multiple_abms[i] = dmub_abm_create(ctx,
+ &abm_regs[i],
+ &abm_shift,
+ &abm_mask);
+ if (pool->base.multiple_abms[i] == NULL) {
+ dm_error("DC: failed to create abm for pipe %d!\n", i);
+ BREAK_TO_DEBUGGER();
+ goto create_fail;
+ }
+ }
+
+ /* MPC and DSC */
+ pool->base.mpc = dcn35_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut);
+ if (pool->base.mpc == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create mpc!\n");
+ goto create_fail;
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
+ pool->base.dscs[i] = dcn35_dsc_create(ctx, i);
+ if (pool->base.dscs[i] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create display stream compressor %d!\n", i);
+ goto create_fail;
+ }
+ }
+
+ /* DWB and MMHUBBUB */
+ if (!dcn35_dwbc_create(ctx, &pool->base)) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dwbc!\n");
+ goto create_fail;
+ }
+
+ if (!dcn35_mmhubbub_create(ctx, &pool->base)) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create mcif_wb!\n");
+ goto create_fail;
+ }
+
+ /* AUX and I2C */
+ for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
+ pool->base.engines[i] = dcn31_aux_engine_create(ctx, i);
+ if (pool->base.engines[i] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error(
+ "DC:failed to create aux engine!!\n");
+ goto create_fail;
+ }
+ pool->base.hw_i2cs[i] = dcn31_i2c_hw_create(ctx, i);
+ if (pool->base.hw_i2cs[i] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error(
+ "DC:failed to create hw i2c!!\n");
+ goto create_fail;
+ }
+ pool->base.sw_i2cs[i] = NULL;
+ }
+
+ /* DCN3.5 has 6 DPIA */
+ pool->base.usb4_dpia_count = 4;
+ if (dc->debug.dpia_debug.bits.disable_dpia)
+ pool->base.usb4_dpia_count = 0;
+
+ /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */
+ if (!resource_construct(num_virtual_links, dc, &pool->base,
+ &res_create_funcs))
+ goto create_fail;
+
+ /* HW Sequencer and Plane caps */
+ dcn35_hw_sequencer_construct(dc);
+
+ dc->caps.max_planes = pool->base.pipe_count;
+
+ for (i = 0; i < dc->caps.max_planes; ++i)
+ dc->caps.planes[i] = plane_cap;
+
+ dc->cap_funcs = cap_funcs;
+
+ dc->dcn_ip->max_num_dpp = pool->base.pipe_count;
+
+ dc->dml2_options.dcn_pipe_count = pool->base.pipe_count;
+ dc->dml2_options.use_native_pstate_optimization = true;
+ dc->dml2_options.use_native_soc_bb_construction = true;
+ if (dc->config.EnableMinDispClkODM)
+ dc->dml2_options.minimize_dispclk_using_odm = true;
+ dc->dml2_options.enable_windowed_mpo_odm = dc->config.enable_windowed_mpo_odm;
+
+ dc->dml2_options.callbacks.dc = dc;
+ dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params;
+ dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch;
+ dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy;
+ dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count;
+ dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count;
+ dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index;
+ dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index;
+ dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head;
+ dc->dml2_options.max_segments_per_hubp = 24;
+
+ dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;/*todo*/
+
+ if (dc->config.sdpif_request_limit_words_per_umc == 0)
+ dc->config.sdpif_request_limit_words_per_umc = 16;/*todo*/
+
+ return true;
+
+create_fail:
+
+ dcn35_resource_destruct(pool);
+
+ return false;
+}
+
+struct resource_pool *dcn35_create_resource_pool(
+ const struct dc_init_data *init_data,
+ struct dc *dc)
+{
+ struct dcn35_resource_pool *pool =
+ kzalloc(sizeof(struct dcn35_resource_pool), GFP_KERNEL);
+
+ if (!pool)
+ return NULL;
+
+ if (dcn35_resource_construct(init_data->num_virtual_links, dc, pool))
+ return &pool->base;
+
+ BREAK_TO_DEBUGGER();
+ kfree(pool);
+ return NULL;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.h
new file mode 100644
index 000000000000..99aea102e3f7
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.h
@@ -0,0 +1,310 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef _DCN35_RESOURCE_H_
+#define _DCN35_RESOURCE_H_
+
+#include "core_types.h"
+
+#define DCN3_5_VMIN_DISPCLK_HZ 717000000
+#define TO_DCN35_RES_POOL(pool)\
+ container_of(pool, struct dcn35_resource_pool, base)
+
+extern struct _vcs_dpi_ip_params_st dcn3_5_ip;
+extern struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc;
+
+struct dcn35_resource_pool {
+ struct resource_pool base;
+};
+
+struct resource_pool *dcn35_create_resource_pool(
+ const struct dc_init_data *init_data,
+ struct dc *dc);
+
+/* Defs for runtime init of registers */
+
+#define OPP_REG_LIST_DCN20_RI(id) \
+ OPP_REG_LIST_DCN10_RI(id), \
+ OPP_DPG_REG_LIST_RI(id), \
+ SRI_ARR(FMT_422_CONTROL, FMT, id), \
+ SRI_ARR(OPPBUF_CONTROL1, OPPBUF, id)
+
+#define OPP_REG_LIST_DCN35_RI(id) \
+ OPP_REG_LIST_DCN20_RI(id), \
+ SRI2_ARR(OPP_TOP_CLK_CONTROL, OPP, id)
+
+#define VPG_DCN31_REG_LIST_RI(id) \
+ SRI_ARR(VPG_GENERIC_STATUS, VPG, id), \
+ SRI_ARR(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \
+ SRI_ARR(VPG_GENERIC_PACKET_DATA, VPG, id), \
+ SRI_ARR(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \
+ SRI_ARR(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id), \
+ SRI_ARR(VPG_MEM_PWR, VPG, id)
+
+#define AFMT_DCN31_REG_LIST_RI(id) \
+ SRI_ARR(AFMT_INFOFRAME_CONTROL0, AFMT, id), \
+ SRI_ARR(AFMT_VBI_PACKET_CONTROL, AFMT, id), \
+ SRI_ARR(AFMT_AUDIO_PACKET_CONTROL, AFMT, id), \
+ SRI_ARR(AFMT_AUDIO_PACKET_CONTROL2, AFMT, id), \
+ SRI_ARR(AFMT_AUDIO_SRC_CONTROL, AFMT, id), \
+ SRI_ARR(AFMT_60958_0, AFMT, id), \
+ SRI_ARR(AFMT_60958_1, AFMT, id), \
+ SRI_ARR(AFMT_60958_2, AFMT, id), \
+ SRI_ARR(AFMT_MEM_PWR, AFMT, id)
+
+/* Stream encoder */
+#define SE_DCN35_REG_LIST_RI(id) \
+ SRI_ARR(AFMT_CNTL, DIG, id), \
+ SRI_ARR(DIG_FE_CNTL, DIG, id), \
+ SRI_ARR(HDMI_CONTROL, DIG, id), \
+ SRI_ARR(HDMI_DB_CONTROL, DIG, id), \
+ SRI_ARR(HDMI_GC, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \
+ SRI_ARR(HDMI_INFOFRAME_CONTROL0, DIG, id), \
+ SRI_ARR(HDMI_INFOFRAME_CONTROL1, DIG, id), \
+ SRI_ARR(HDMI_VBI_PACKET_CONTROL, DIG, id), \
+ SRI_ARR(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\
+ SRI_ARR(HDMI_ACR_PACKET_CONTROL, DIG, id),\
+ SRI_ARR(HDMI_ACR_32_0, DIG, id),\
+ SRI_ARR(HDMI_ACR_32_1, DIG, id),\
+ SRI_ARR(HDMI_ACR_44_0, DIG, id),\
+ SRI_ARR(HDMI_ACR_44_1, DIG, id),\
+ SRI_ARR(HDMI_ACR_48_0, DIG, id),\
+ SRI_ARR(HDMI_ACR_48_1, DIG, id),\
+ SRI_ARR(DP_DB_CNTL, DP, id), \
+ SRI_ARR(DP_MSA_MISC, DP, id), \
+ SRI_ARR(DP_MSA_VBID_MISC, DP, id), \
+ SRI_ARR(DP_MSA_COLORIMETRY, DP, id), \
+ SRI_ARR(DP_MSA_TIMING_PARAM1, DP, id), \
+ SRI_ARR(DP_MSA_TIMING_PARAM2, DP, id), \
+ SRI_ARR(DP_MSA_TIMING_PARAM3, DP, id), \
+ SRI_ARR(DP_MSA_TIMING_PARAM4, DP, id), \
+ SRI_ARR(DP_MSE_RATE_CNTL, DP, id), \
+ SRI_ARR(DP_MSE_RATE_UPDATE, DP, id), \
+ SRI_ARR(DP_PIXEL_FORMAT, DP, id), \
+ SRI_ARR(DP_SEC_CNTL, DP, id), \
+ SRI_ARR(DP_SEC_CNTL1, DP, id), \
+ SRI_ARR(DP_SEC_CNTL2, DP, id), \
+ SRI_ARR(DP_SEC_CNTL5, DP, id), \
+ SRI_ARR(DP_SEC_CNTL6, DP, id), \
+ SRI_ARR(DP_STEER_FIFO, DP, id), \
+ SRI_ARR(DP_VID_M, DP, id), \
+ SRI_ARR(DP_VID_N, DP, id), \
+ SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \
+ SRI_ARR(DP_VID_TIMING, DP, id), \
+ SRI_ARR(DP_SEC_AUD_N, DP, id), \
+ SRI_ARR(DP_SEC_TIMESTAMP, DP, id), \
+ SRI_ARR(DP_DSC_CNTL, DP, id), \
+ SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \
+ SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \
+ SRI_ARR(DP_SEC_FRAMING4, DP, id), \
+ SRI_ARR(DP_GSP11_CNTL, DP, id), \
+ SRI_ARR(DME_CONTROL, DME, id),\
+ SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \
+ SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \
+ SRI_ARR(DIG_FE_CNTL, DIG, id), \
+ SRI_ARR(DIG_FE_EN_CNTL, DIG, id), \
+ SRI_ARR(DIG_FE_CLK_CNTL, DIG, id), \
+ SRI_ARR(DIG_CLOCK_PATTERN, DIG, id), \
+ SRI_ARR(DIG_FIFO_CTRL0, DIG, id), \
+ SRI_ARR(STREAM_MAPPER_CONTROL, DIG, id)
+
+#define LE_DCN35_REG_LIST_RI(id)\
+ LE_DCN3_REG_LIST_RI(id),\
+ SRI_ARR(DP_DPHY_INTERNAL_CTRL, DP, id), \
+ SR_ARR(DIO_LINKA_CNTL, id), \
+ SR_ARR(DIO_LINKB_CNTL, id), \
+ SR_ARR(DIO_LINKC_CNTL, id), \
+ SR_ARR(DIO_LINKD_CNTL, id), \
+ SR_ARR(DIO_LINKE_CNTL, id), \
+ SR_ARR(DIO_LINKF_CNTL, id),\
+ SRI_ARR(DIG_BE_CLK_CNTL, DIG, id),\
+ SR_ARR(DIO_CLK_CNTL, id)
+
+#define MCIF_WB_COMMON_REG_LIST_DCN3_5_RI(inst) \
+ MCIF_WB_COMMON_REG_LIST_DCN32_RI(inst), \
+ SRI2_ARR(MMHUBBUB_CLOCK_CNTL, MMHUBBUB, inst)
+
+#define HWSEQ_DCN35_REG_LIST()\
+ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \
+ SR(DCHUBBUB_ARB_HOSTVM_CNTL), \
+ SR(DIO_MEM_PWR_CTRL), \
+ SR(ODM_MEM_PWR_CTRL3), \
+ SR(MMHUBBUB_MEM_PWR_CNTL), \
+ SR(DCCG_GATE_DISABLE_CNTL), \
+ SR(DCCG_GATE_DISABLE_CNTL2), \
+ SR(DCCG_GATE_DISABLE_CNTL5), \
+ SR(DCFCLK_CNTL),\
+ SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \
+ SRII(PIXEL_RATE_CNTL, OTG, 0), \
+ SRII(PIXEL_RATE_CNTL, OTG, 1),\
+ SRII(PIXEL_RATE_CNTL, OTG, 2),\
+ SRII(PIXEL_RATE_CNTL, OTG, 3),\
+ SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\
+ SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\
+ SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\
+ SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\
+ SR(MICROSECOND_TIME_BASE_DIV), \
+ SR(MILLISECOND_TIME_BASE_DIV), \
+ SR(DISPCLK_FREQ_CHANGE_CNTL), \
+ SR(RBBMIF_TIMEOUT_DIS), \
+ SR(RBBMIF_TIMEOUT_DIS_2), \
+ SR(DCHUBBUB_CRC_CTRL), \
+ SR(DPP_TOP0_DPP_CRC_CTRL), \
+ SR(DPP_TOP0_DPP_CRC_VAL_B_A), \
+ SR(DPP_TOP0_DPP_CRC_VAL_R_G), \
+ SR(MPC_CRC_CTRL), \
+ SR(MPC_CRC_RESULT_GB), \
+ SR(MPC_CRC_RESULT_C), \
+ SR(MPC_CRC_RESULT_AR), \
+ SR(DOMAIN0_PG_CONFIG), \
+ SR(DOMAIN1_PG_CONFIG), \
+ SR(DOMAIN2_PG_CONFIG), \
+ SR(DOMAIN3_PG_CONFIG), \
+ SR(DOMAIN16_PG_CONFIG), \
+ SR(DOMAIN17_PG_CONFIG), \
+ SR(DOMAIN18_PG_CONFIG), \
+ SR(DOMAIN19_PG_CONFIG), \
+ SR(DOMAIN0_PG_STATUS), \
+ SR(DOMAIN1_PG_STATUS), \
+ SR(DOMAIN2_PG_STATUS), \
+ SR(DOMAIN3_PG_STATUS), \
+ SR(DOMAIN16_PG_STATUS), \
+ SR(DOMAIN17_PG_STATUS), \
+ SR(DOMAIN18_PG_STATUS), \
+ SR(DOMAIN19_PG_STATUS), \
+ SR(DC_IP_REQUEST_CNTL), \
+ SR(AZALIA_AUDIO_DTO), \
+ SR(AZALIA_CONTROLLER_CLOCK_GATING), \
+ SR(HPO_TOP_HW_CONTROL),\
+ SR(DMU_CLK_CNTL)
+
+/* OPTC */
+#define OPTC_COMMON_REG_LIST_DCN3_5_RI(inst) \
+ SRI_ARR(OTG_VSTARTUP_PARAM, OTG, inst),\
+ SRI_ARR(OTG_VUPDATE_PARAM, OTG, inst),\
+ SRI_ARR(OTG_VREADY_PARAM, OTG, inst),\
+ SRI_ARR(OTG_MASTER_UPDATE_LOCK, OTG, inst),\
+ SRI_ARR(OTG_GLOBAL_CONTROL0, OTG, inst),\
+ SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst),\
+ SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst),\
+ SRI_ARR(OTG_GLOBAL_CONTROL4, OTG, inst),\
+ SRI_ARR(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_H_TOTAL, OTG, inst),\
+ SRI_ARR(OTG_H_BLANK_START_END, OTG, inst),\
+ SRI_ARR(OTG_H_SYNC_A, OTG, inst),\
+ SRI_ARR(OTG_H_SYNC_A_CNTL, OTG, inst),\
+ SRI_ARR(OTG_H_TIMING_CNTL, OTG, inst),\
+ SRI_ARR(OTG_V_TOTAL, OTG, inst),\
+ SRI_ARR(OTG_V_BLANK_START_END, OTG, inst),\
+ SRI_ARR(OTG_V_SYNC_A, OTG, inst),\
+ SRI_ARR(OTG_V_SYNC_A_CNTL, OTG, inst),\
+ SRI_ARR(OTG_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_STEREO_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_STEREO_STATUS, OTG, inst),\
+ SRI_ARR(OTG_V_TOTAL_MAX, OTG, inst),\
+ SRI_ARR(OTG_V_TOTAL_MIN, OTG, inst),\
+ SRI_ARR(OTG_V_TOTAL_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_TRIGA_CNTL, OTG, inst),\
+ SRI_ARR(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\
+ SRI_ARR(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_STATUS_FRAME_COUNT, OTG, inst),\
+ SRI_ARR(OTG_STATUS, OTG, inst),\
+ SRI_ARR(OTG_STATUS_POSITION, OTG, inst),\
+ SRI_ARR(OTG_NOM_VERT_POSITION, OTG, inst),\
+ SRI_ARR(OTG_M_CONST_DTO0, OTG, inst),\
+ SRI_ARR(OTG_M_CONST_DTO1, OTG, inst),\
+ SRI_ARR(OTG_CLOCK_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),\
+ SRI_ARR(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),\
+ SRI_ARR(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\
+ SRI_ARR(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\
+ SRI_ARR(OPTC_DATA_SOURCE_SELECT, ODM, inst),\
+ SRI_ARR(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\
+ SRI_ARR(CONTROL, VTG, inst),\
+ SRI_ARR(OTG_VERT_SYNC_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_GSL_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_CRC_CNTL, OTG, inst),\
+ SRI_ARR(OTG_CRC0_DATA_RG, OTG, inst),\
+ SRI_ARR(OTG_CRC0_DATA_B, OTG, inst),\
+ SRI_ARR(OTG_CRC1_DATA_RG, OTG, inst),\
+ SRI_ARR(OTG_CRC1_DATA_B, OTG, inst),\
+ SRI_ARR(OTG_CRC2_DATA_RG, OTG, inst),\
+ SRI_ARR(OTG_CRC2_DATA_B, OTG, inst),\
+ SRI_ARR(OTG_CRC3_DATA_RG, OTG, inst),\
+ SRI_ARR(OTG_CRC3_DATA_B, OTG, inst),\
+ SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_CRC1_WINDOWA_X_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_CRC1_WINDOWA_Y_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_CRC1_WINDOWB_X_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_CRC1_WINDOWB_Y_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC1_WINDOWA_X_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC1_WINDOWA_Y_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG, inst),\
+ SR_ARR(GSL_SOURCE_SELECT, inst),\
+ SRI_ARR(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\
+ SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst),\
+ SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst),\
+ SRI_ARR(OTG_GSL_WINDOW_X, OTG, inst),\
+ SRI_ARR(OTG_GSL_WINDOW_Y, OTG, inst),\
+ SRI_ARR(OTG_VUPDATE_KEEPOUT, OTG, inst),\
+ SRI_ARR(OTG_DSC_START_POSITION, OTG, inst),\
+ SRI_ARR(OTG_DRR_TRIGGER_WINDOW, OTG, inst),\
+ SRI_ARR(OTG_DRR_V_TOTAL_CHANGE, OTG, inst),\
+ SRI_ARR(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\
+ SRI_ARR(OPTC_BYTES_PER_PIXEL, ODM, inst),\
+ SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst),\
+ SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst),\
+ SRI_ARR(OTG_DRR_CONTROL, OTG, inst),\
+ SRI2_ARR(OPTC_CLOCK_CONTROL, OPTC, inst)
+
+/* DPP */
+#define DPP_REG_LIST_DCN35_RI(id)\
+ DPP_REG_LIST_DCN30_COMMON_RI(id)
+
+#endif /* _DCN35_RESOURCE_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile
index 77cf5545c94c..6042a5a6a44f 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile
@@ -61,8 +61,12 @@ endif
endif
ifneq ($(CONFIG_FRAME_WARN),0)
+ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y)
+frame_warn_flag := -Wframe-larger-than=3072
+else
frame_warn_flag := -Wframe-larger-than=2048
endif
+endif
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_ccflags)
@@ -87,6 +91,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn32/display_mode_vba_32.o := $(dml_ccflags) $(fram
CFLAGS_$(AMDDALPATH)/dc/dml/dcn32/display_rq_dlg_calc_32.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn32/display_mode_vba_util_32.o := $(dml_ccflags) $(frame_warn_flag)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn321/dcn321_fpu.o := $(dml_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml/dcn35/dcn35_fpu.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/dcn31_fpu.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn302/dcn302_fpu.o := $(dml_ccflags)
@@ -120,6 +125,7 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn314/dcn314_fpu.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn30/dcn30_fpu.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn32/dcn32_fpu.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn321/dcn321_fpu.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn35/dcn35_fpu.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/dcn31_fpu.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn302/dcn302_fpu.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn303/dcn303_fpu.o := $(dml_rcflags)
@@ -132,8 +138,6 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calcs.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_auto.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_math.o := $(dml_rcflags)
-DML = calcs/dce_calcs.o calcs/custom_float.o calcs/bw_fixed.o
-
ifdef CONFIG_DRM_AMD_DC_FP
DML += display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o
DML += dcn10/dcn10_fpu.o
@@ -152,6 +156,7 @@ DML += dcn301/dcn301_fpu.o
DML += dcn302/dcn302_fpu.o
DML += dcn303/dcn303_fpu.o
DML += dcn314/dcn314_fpu.o
+DML += dcn35/dcn35_fpu.o
DML += dsc/rc_calc_fpu.o
DML += calcs/dcn_calcs.o calcs/dcn_calc_math.o calcs/dcn_calc_auto.o
endif
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h
index 2cbdd75429ff..6e669a2c5b2d 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h
@@ -36,7 +36,7 @@
* Define the maximum amount of states supported by the ASIC. Every ASIC has a
* specific number of states; this macro defines the maximum number of states.
*/
-#define DC__VOLTAGE_STATES 20
+#define DC__VOLTAGE_STATES 40
#define DC__NUM_DPP__4 1
#define DC__NUM_DPP__0_PRESENT 1
#define DC__NUM_DPP__1_PRESENT 1
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
index 5805fb02af14..ec77b2b41ba3 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
@@ -34,6 +34,8 @@
#include "link.h"
#include "dcn20_fpu.h"
+#define DC_LOGGER \
+ dc->ctx->logger
#define DC_LOGGER_INIT(logger)
#ifndef MAX
@@ -948,10 +950,8 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc
{
int plane_count;
int i;
- unsigned int min_dst_y_next_start_us;
plane_count = 0;
- min_dst_y_next_start_us = 0;
for (i = 0; i < dc->res_pool->pipe_count; i++) {
if (context->res_ctx.pipe_ctx[i].plane_state)
plane_count++;
@@ -973,26 +973,15 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc
else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) {
struct dc_link *link = context->streams[0]->sink->link;
struct dc_stream_status *stream_status = &context->stream_status[0];
- struct dc_stream_state *current_stream = context->streams[0];
int minmum_z8_residency = dc->debug.minimum_z8_residency_time > 0 ? dc->debug.minimum_z8_residency_time : 1000;
bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z8_residency;
bool is_pwrseq0 = link->link_index == 0;
- bool isFreesyncVideo;
-
- isFreesyncVideo = current_stream->adjust.v_total_min == current_stream->adjust.v_total_max;
- isFreesyncVideo = isFreesyncVideo && current_stream->timing.v_total < current_stream->adjust.v_total_min;
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- if (context->res_ctx.pipe_ctx[i].stream == current_stream && isFreesyncVideo) {
- min_dst_y_next_start_us = context->res_ctx.pipe_ctx[i].dlg_regs.min_dst_y_next_start_us;
- break;
- }
- }
/* Don't support multi-plane configurations */
if (stream_status->plane_count > 1)
return DCN_ZSTATE_SUPPORT_DISALLOW;
- if (is_pwrseq0 && (context->bw_ctx.dml.vba.StutterPeriod > 5000.0 || min_dst_y_next_start_us > 5000))
+ if (is_pwrseq0 && context->bw_ctx.dml.vba.StutterPeriod > 5000.0)
return DCN_ZSTATE_SUPPORT_ALLOW;
else if (is_pwrseq0 && link->psr_settings.psr_version == DC_PSR_VERSION_1 && !link->panel_config.psr.disable_psr)
return allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY : DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY;
@@ -1310,11 +1299,11 @@ int dcn20_populate_dml_pipes_from_context(struct dc *dc,
pipes[pipe_cnt].dout.is_virtual = 0;
pipes[pipe_cnt].pipe.dest.vtotal_min = res_ctx->pipe_ctx[i].stream->adjust.v_total_min;
pipes[pipe_cnt].pipe.dest.vtotal_max = res_ctx->pipe_ctx[i].stream->adjust.v_total_max;
- switch (resource_get_num_odm_splits(&res_ctx->pipe_ctx[i])) {
- case 1:
+ switch (resource_get_odm_slice_count(&res_ctx->pipe_ctx[i])) {
+ case 2:
pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_2to1;
break;
- case 3:
+ case 4:
pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_4to1;
break;
default:
@@ -1923,7 +1912,7 @@ void dcn20_patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st
}
static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *context,
- bool fast_validate)
+ bool fast_validate, display_e2e_pipe_params_st *pipes)
{
bool out = false;
@@ -1932,7 +1921,6 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co
int vlevel = 0;
int pipe_split_from[MAX_PIPES];
int pipe_cnt = 0;
- display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC);
DC_LOGGER_INIT(dc->ctx->logger);
BW_VAL_TRACE_COUNT();
@@ -1967,16 +1955,14 @@ validate_fail:
out = false;
validate_out:
- kfree(pipes);
BW_VAL_TRACE_FINISH();
return out;
}
-bool dcn20_validate_bandwidth_fp(struct dc *dc,
- struct dc_state *context,
- bool fast_validate)
+bool dcn20_validate_bandwidth_fp(struct dc *dc, struct dc_state *context,
+ bool fast_validate, display_e2e_pipe_params_st *pipes)
{
bool voltage_supported = false;
bool full_pstate_supported = false;
@@ -1995,11 +1981,11 @@ bool dcn20_validate_bandwidth_fp(struct dc *dc,
ASSERT(context != dc->current_state);
if (fast_validate) {
- return dcn20_validate_bandwidth_internal(dc, context, true);
+ return dcn20_validate_bandwidth_internal(dc, context, true, pipes);
}
// Best case, we support full UCLK switch latency
- voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false);
+ voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false, pipes);
full_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;
if (context->bw_ctx.dml.soc.dummy_pstate_latency_us == 0 ||
@@ -2011,7 +1997,8 @@ bool dcn20_validate_bandwidth_fp(struct dc *dc,
// Fallback: Try to only support G6 temperature read latency
context->bw_ctx.dml.soc.dram_clock_change_latency_us = context->bw_ctx.dml.soc.dummy_pstate_latency_us;
- voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false);
+ memset(pipes, 0, dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st));
+ voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false, pipes);
dummy_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;
if (voltage_supported && (dummy_pstate_supported || !(context->stream_count))) {
@@ -2216,9 +2203,8 @@ static void dcn21_calculate_wm(struct dc *dc, struct dc_state *context,
&context->bw_ctx.dml, pipes, pipe_cnt);
}
-bool dcn21_validate_bandwidth_fp(struct dc *dc,
- struct dc_state *context,
- bool fast_validate)
+bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context,
+ bool fast_validate, display_e2e_pipe_params_st *pipes)
{
bool out = false;
@@ -2227,7 +2213,6 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc,
int vlevel = 0;
int pipe_split_from[MAX_PIPES];
int pipe_cnt = 0;
- display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC);
DC_LOGGER_INIT(dc->ctx->logger);
BW_VAL_TRACE_COUNT();
@@ -2267,7 +2252,6 @@ validate_fail:
out = false;
validate_out:
- kfree(pipes);
BW_VAL_TRACE_FINISH();
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
index c51badf7b68a..b6c34198ddc8 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
@@ -61,9 +61,8 @@ void dcn20_update_bounding_box(struct dc *dc,
unsigned int num_states);
void dcn20_patch_bounding_box(struct dc *dc,
struct _vcs_dpi_soc_bounding_box_st *bb);
-bool dcn20_validate_bandwidth_fp(struct dc *dc,
- struct dc_state *context,
- bool fast_validate);
+bool dcn20_validate_bandwidth_fp(struct dc *dc, struct dc_state *context,
+ bool fast_validate, display_e2e_pipe_params_st *pipes);
void dcn20_fpu_set_wm_ranges(int i,
struct pp_smu_wm_range_sets *ranges,
struct _vcs_dpi_soc_bounding_box_st *loaded_bb);
@@ -77,9 +76,8 @@ int dcn21_populate_dml_pipes_from_context(struct dc *dc,
struct dc_state *context,
display_e2e_pipe_params_st *pipes,
bool fast_validate);
-bool dcn21_validate_bandwidth_fp(struct dc *dc,
- struct dc_state *context,
- bool fast_validate);
+bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, bool
+ fast_validate, display_e2e_pipe_params_st *pipes);
void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params);
void dcn21_clk_mgr_set_bw_params_wm_table(struct clk_bw_params *bw_params);
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
index ad741a723c0e..3686f1e7de3a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
@@ -5128,7 +5128,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
ViewportExceedsSurface = true;
if (v->SourcePixelFormat[k] != dm_444_64 && v->SourcePixelFormat[k] != dm_444_32 && v->SourcePixelFormat[k] != dm_444_16
- && v->SourcePixelFormat[k] != dm_444_16 && v->SourcePixelFormat[k] != dm_444_8 && v->SourcePixelFormat[k] != dm_rgbe) {
+ && v->SourcePixelFormat[k] != dm_444_8 && v->SourcePixelFormat[k] != dm_rgbe) {
if (v->ViewportWidthChroma[k] > v->SurfaceWidthC[k] || v->ViewportHeightChroma[k] > v->SurfaceHeightC[k]) {
ViewportExceedsSurface = true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
index a94aa0f21a7f..88e56889a68c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
@@ -2311,6 +2311,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
v->OutputFormat[k],
v->Output[k]) + dscComputeDelay(v->OutputFormat[k], v->Output[k]));
}
+ v->DSCDelay[k] = v->DSCDelay[k] + (v->HTotal[k] - v->HActive[k]) * dml_ceil((double) v->DSCDelay[k] / v->HActive[k], 1);
v->DSCDelay[k] = v->DSCDelay[k] * v->PixelClock[k] / v->PixelClockBackEnd[k];
} else {
v->DSCDelay[k] = 0;
@@ -4719,6 +4720,7 @@ void dml314_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_
v->OutputFormat[k],
v->Output[k]) + dscComputeDelay(v->OutputFormat[k], v->Output[k]));
}
+ v->DSCDelayPerState[i][k] = v->DSCDelayPerState[i][k] + (v->HTotal[k] - v->HActive[k]) * dml_ceil((double) v->DSCDelayPerState[i][k] / v->HActive[k], 1.0);
v->DSCDelayPerState[i][k] = v->DSCDelayPerState[i][k] * v->PixelClock[k] / v->PixelClockBackEnd[k];
} else {
v->DSCDelayPerState[i][k] = 0.0;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
index 711d4085b33b..b46cde525066 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
@@ -41,7 +41,8 @@ static const struct subvp_high_refresh_list subvp_high_refresh_list = {
.res = {
{.width = 3840, .height = 2160, },
{.width = 3440, .height = 1440, },
- {.width = 2560, .height = 1440, }},
+ {.width = 2560, .height = 1440, },
+ {.width = 1920, .height = 1080, }},
};
struct _vcs_dpi_ip_params_st dcn3_2_ip = {
@@ -347,90 +348,6 @@ void dcn32_helper_populate_phantom_dlg_params(struct dc *dc,
}
}
-/**
- * dcn32_predict_pipe_split - Predict if pipe split will occur for a given DML pipe
- * @context: [in] New DC state to be programmed
- * @pipe_e2e: [in] DML pipe end to end context
- *
- * This function takes in a DML pipe (pipe_e2e) and predicts if pipe split is required (both
- * ODM and MPC). For pipe split, ODM combine is determined by the ODM mode, and MPC combine is
- * determined by DPPClk requirements
- *
- * This function follows the same policy as DML:
- * - Check for ODM combine requirements / policy first
- * - MPC combine is only chosen if there is no ODM combine requirements / policy in place, and
- * MPC is required
- *
- * Return: Number of splits expected (1 for 2:1 split, 3 for 4:1 split, 0 for no splits).
- */
-uint8_t dcn32_predict_pipe_split(struct dc_state *context,
- display_e2e_pipe_params_st *pipe_e2e)
-{
- double pscl_throughput;
- double pscl_throughput_chroma;
- double dpp_clk_single_dpp, clock;
- double clk_frequency = 0.0;
- double vco_speed = context->bw_ctx.dml.soc.dispclk_dppclk_vco_speed_mhz;
- bool total_available_pipes_support = false;
- uint32_t number_of_dpp = 0;
- enum odm_combine_mode odm_mode = dm_odm_combine_mode_disabled;
- double req_dispclk_per_surface = 0;
- uint8_t num_splits = 0;
-
- dc_assert_fp_enabled();
-
- dml32_CalculateODMMode(context->bw_ctx.dml.ip.maximum_pixels_per_line_per_dsc_unit,
- pipe_e2e->pipe.dest.hactive,
- pipe_e2e->dout.output_format,
- pipe_e2e->dout.output_type,
- pipe_e2e->pipe.dest.odm_combine_policy,
- context->bw_ctx.dml.soc.clock_limits[context->bw_ctx.dml.soc.num_states - 1].dispclk_mhz,
- context->bw_ctx.dml.soc.clock_limits[context->bw_ctx.dml.soc.num_states - 1].dispclk_mhz,
- pipe_e2e->dout.dsc_enable != 0,
- 0, /* TotalNumberOfActiveDPP can be 0 since we're predicting pipe split requirement */
- context->bw_ctx.dml.ip.max_num_dpp,
- pipe_e2e->pipe.dest.pixel_rate_mhz,
- context->bw_ctx.dml.soc.dcn_downspread_percent,
- context->bw_ctx.dml.ip.dispclk_ramp_margin_percent,
- context->bw_ctx.dml.soc.dispclk_dppclk_vco_speed_mhz,
- pipe_e2e->dout.dsc_slices,
- /* Output */
- &total_available_pipes_support,
- &number_of_dpp,
- &odm_mode,
- &req_dispclk_per_surface);
-
- dml32_CalculateSinglePipeDPPCLKAndSCLThroughput(pipe_e2e->pipe.scale_ratio_depth.hscl_ratio,
- pipe_e2e->pipe.scale_ratio_depth.hscl_ratio_c,
- pipe_e2e->pipe.scale_ratio_depth.vscl_ratio,
- pipe_e2e->pipe.scale_ratio_depth.vscl_ratio_c,
- context->bw_ctx.dml.ip.max_dchub_pscl_bw_pix_per_clk,
- context->bw_ctx.dml.ip.max_pscl_lb_bw_pix_per_clk,
- pipe_e2e->pipe.dest.pixel_rate_mhz,
- pipe_e2e->pipe.src.source_format,
- pipe_e2e->pipe.scale_taps.htaps,
- pipe_e2e->pipe.scale_taps.htaps_c,
- pipe_e2e->pipe.scale_taps.vtaps,
- pipe_e2e->pipe.scale_taps.vtaps_c,
- /* Output */
- &pscl_throughput, &pscl_throughput_chroma,
- &dpp_clk_single_dpp);
-
- clock = dpp_clk_single_dpp * (1 + context->bw_ctx.dml.soc.dcn_downspread_percent / 100);
-
- if (clock > 0)
- clk_frequency = vco_speed * 4.0 / ((int)(vco_speed * 4.0) / clock);
-
- if (odm_mode == dm_odm_combine_mode_2to1)
- num_splits = 1;
- else if (odm_mode == dm_odm_combine_mode_4to1)
- num_splits = 3;
- else if (clk_frequency > context->bw_ctx.dml.soc.clock_limits[context->bw_ctx.dml.soc.num_states - 1].dppclk_mhz)
- num_splits = 1;
-
- return num_splits;
-}
-
static float calculate_net_bw_in_kbytes_sec(struct _vcs_dpi_voltage_scaling_st *entry)
{
float memory_bw_kbytes_sec;
@@ -905,7 +822,7 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context)
continue;
if (drr_pipe->stream->mall_stream_config.type == SUBVP_NONE && drr_pipe->stream->ignore_msa_timing_param &&
- (drr_pipe->stream->allow_freesync || drr_pipe->stream->vrr_active_variable))
+ (drr_pipe->stream->allow_freesync || drr_pipe->stream->vrr_active_variable || drr_pipe->stream->vrr_active_fixed))
break;
}
@@ -1144,6 +1061,345 @@ static bool subvp_validate_static_schedulability(struct dc *dc,
return schedulable;
}
+static void assign_subvp_index(struct dc *dc, struct dc_state *context)
+{
+ int i;
+ int index = 0;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+ if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) &&
+ pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN) {
+ pipe_ctx->subvp_index = index++;
+ } else {
+ pipe_ctx->subvp_index = 0;
+ }
+ }
+}
+
+struct pipe_slice_table {
+ struct {
+ struct dc_stream_state *stream;
+ int slice_count;
+ } odm_combines[MAX_STREAMS];
+ int odm_combine_count;
+
+ struct {
+ struct pipe_ctx *pri_pipe;
+ struct dc_plane_state *plane;
+ int slice_count;
+ } mpc_combines[MAX_SURFACES];
+ int mpc_combine_count;
+};
+
+
+static void update_slice_table_for_stream(struct pipe_slice_table *table,
+ struct dc_stream_state *stream, int diff)
+{
+ int i;
+
+ for (i = 0; i < table->odm_combine_count; i++) {
+ if (table->odm_combines[i].stream == stream) {
+ table->odm_combines[i].slice_count += diff;
+ break;
+ }
+ }
+
+ if (i == table->odm_combine_count) {
+ table->odm_combine_count++;
+ table->odm_combines[i].stream = stream;
+ table->odm_combines[i].slice_count = diff;
+ }
+}
+
+static void update_slice_table_for_plane(struct pipe_slice_table *table,
+ struct pipe_ctx *dpp_pipe, struct dc_plane_state *plane, int diff)
+{
+ int i;
+ struct pipe_ctx *pri_dpp_pipe = resource_get_primary_dpp_pipe(dpp_pipe);
+
+ for (i = 0; i < table->mpc_combine_count; i++) {
+ if (table->mpc_combines[i].plane == plane &&
+ table->mpc_combines[i].pri_pipe == pri_dpp_pipe) {
+ table->mpc_combines[i].slice_count += diff;
+ break;
+ }
+ }
+
+ if (i == table->mpc_combine_count) {
+ table->mpc_combine_count++;
+ table->mpc_combines[i].plane = plane;
+ table->mpc_combines[i].pri_pipe = pri_dpp_pipe;
+ table->mpc_combines[i].slice_count = diff;
+ }
+}
+
+static void init_pipe_slice_table_from_context(
+ struct pipe_slice_table *table,
+ struct dc_state *context)
+{
+ int i, j;
+ struct pipe_ctx *otg_master;
+ struct pipe_ctx *dpp_pipes[MAX_PIPES];
+ struct dc_stream_state *stream;
+ int count;
+
+ memset(table, 0, sizeof(*table));
+
+ for (i = 0; i < context->stream_count; i++) {
+ stream = context->streams[i];
+ otg_master = resource_get_otg_master_for_stream(
+ &context->res_ctx, stream);
+ count = resource_get_odm_slice_count(otg_master);
+ update_slice_table_for_stream(table, stream, count);
+
+ count = resource_get_dpp_pipes_for_opp_head(otg_master,
+ &context->res_ctx, dpp_pipes);
+ for (j = 0; j < count; j++)
+ if (dpp_pipes[j]->plane_state)
+ update_slice_table_for_plane(table, dpp_pipes[j],
+ dpp_pipes[j]->plane_state, 1);
+ }
+}
+
+static bool update_pipe_slice_table_with_split_flags(
+ struct pipe_slice_table *table,
+ struct dc *dc,
+ struct dc_state *context,
+ struct vba_vars_st *vba,
+ int split[MAX_PIPES],
+ bool merge[MAX_PIPES])
+{
+ /* NOTE: we are deprecating the support for the concept of pipe splitting
+ * or pipe merging. Instead we append slices to the end and remove
+ * slices from the end. The following code converts a pipe split or
+ * merge to an append or remove operation.
+ *
+ * For example:
+ * When split flags describe the following pipe connection transition
+ *
+ * from:
+ * pipe 0 (split=2) -> pipe 1 (split=2)
+ * to: (old behavior)
+ * pipe 0 -> pipe 2 -> pipe 1 -> pipe 3
+ *
+ * the code below actually does:
+ * pipe 0 -> pipe 1 -> pipe 2 -> pipe 3
+ *
+ * This is the new intended behavior and for future DCNs we will retire
+ * the old concept completely.
+ */
+ struct pipe_ctx *pipe;
+ bool odm;
+ int dc_pipe_idx, dml_pipe_idx = 0;
+ bool updated = false;
+
+ for (dc_pipe_idx = 0;
+ dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) {
+ pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx];
+ if (resource_is_pipe_type(pipe, FREE_PIPE))
+ continue;
+
+ if (merge[dc_pipe_idx]) {
+ if (resource_is_pipe_type(pipe, OPP_HEAD))
+ /* merging OPP head means reducing ODM slice
+ * count by 1
+ */
+ update_slice_table_for_stream(table, pipe->stream, -1);
+ else if (resource_is_pipe_type(pipe, DPP_PIPE) &&
+ resource_get_odm_slice_index(resource_get_opp_head(pipe)) == 0)
+ /* merging DPP pipe of the first ODM slice means
+ * reducing MPC slice count by 1
+ */
+ update_slice_table_for_plane(table, pipe, pipe->plane_state, -1);
+ updated = true;
+ }
+
+ if (split[dc_pipe_idx]) {
+ odm = vba->ODMCombineEnabled[vba->pipe_plane[dml_pipe_idx]] !=
+ dm_odm_combine_mode_disabled;
+ if (odm && resource_is_pipe_type(pipe, OPP_HEAD))
+ update_slice_table_for_stream(
+ table, pipe->stream, split[dc_pipe_idx] - 1);
+ else if (!odm && resource_is_pipe_type(pipe, DPP_PIPE))
+ update_slice_table_for_plane(table, pipe,
+ pipe->plane_state, split[dc_pipe_idx] - 1);
+ updated = true;
+ }
+ dml_pipe_idx++;
+ }
+ return updated;
+}
+
+static void update_pipes_with_slice_table(struct dc *dc, struct dc_state *context,
+ struct pipe_slice_table *table)
+{
+ int i;
+
+ for (i = 0; i < table->odm_combine_count; i++) {
+ resource_update_pipes_for_stream_with_slice_count(context,
+ dc->current_state, dc->res_pool,
+ table->odm_combines[i].stream,
+ table->odm_combines[i].slice_count);
+ /* TODO: move this into the function above */
+ dcn20_build_mapped_resource(dc, context,
+ table->odm_combines[i].stream);
+ }
+
+ for (i = 0; i < table->mpc_combine_count; i++)
+ resource_update_pipes_for_plane_with_slice_count(context,
+ dc->current_state, dc->res_pool,
+ table->mpc_combines[i].plane,
+ table->mpc_combines[i].slice_count);
+}
+
+static bool update_pipes_with_split_flags(struct dc *dc, struct dc_state *context,
+ struct vba_vars_st *vba, int split[MAX_PIPES],
+ bool merge[MAX_PIPES])
+{
+ struct pipe_slice_table slice_table;
+ bool updated;
+
+ init_pipe_slice_table_from_context(&slice_table, context);
+ updated = update_pipe_slice_table_with_split_flags(
+ &slice_table, dc, context, vba,
+ split, merge);
+ update_pipes_with_slice_table(dc, context, &slice_table);
+ return updated;
+}
+
+static bool should_allow_odm_power_optimization(struct dc *dc,
+ struct dc_state *context, struct vba_vars_st *v, int *split,
+ bool *merge)
+{
+ struct dc_stream_state *stream = context->streams[0];
+ struct pipe_slice_table slice_table;
+ int i;
+
+ /*
+ * this debug flag allows us to disable ODM power optimization feature
+ * unconditionally. we force the feature off if this is set to false.
+ */
+ if (!dc->debug.enable_single_display_2to1_odm_policy)
+ return false;
+
+ /* current design and test coverage is only limited to allow ODM power
+ * optimization for single stream. Supporting it for multiple streams
+ * use case would require additional algorithm to decide how to
+ * optimize power consumption when there are not enough free pipes to
+ * allocate for all the streams. This level of optimization would
+ * require multiple attempts of revalidation to make an optimized
+ * decision. Unfortunately We do not support revalidation flow in
+ * current version of DML.
+ */
+ if (context->stream_count != 1)
+ return false;
+
+ /*
+ * Our hardware doesn't support ODM for HDMI TMDS
+ */
+ if (dc_is_hdmi_signal(stream->signal))
+ return false;
+
+ /*
+ * ODM Combine 2:1 requires horizontal timing divisible by 2 so each
+ * ODM segment has the same size.
+ */
+ if (!is_h_timing_divisible_by_2(stream))
+ return false;
+
+ /*
+ * No power benefits if the timing's pixel clock is not high enough to
+ * raise display clock from minimum power state.
+ */
+ if (stream->timing.pix_clk_100hz * 100 <= DCN3_2_VMIN_DISPCLK_HZ)
+ return false;
+
+ if (dc->config.enable_windowed_mpo_odm) {
+ /*
+ * ODM power optimization should only be allowed if the feature
+ * can be seamlessly toggled off within an update. This would
+ * require that the feature is applied on top of a minimal
+ * state. A minimal state is defined as a state validated
+ * without the need of pipe split. Therefore, when transition to
+ * toggle the feature off, the same stream and plane
+ * configuration can be supported by the pipe resource in the
+ * first ODM slice alone without the need to acquire extra
+ * resources.
+ */
+ init_pipe_slice_table_from_context(&slice_table, context);
+ update_pipe_slice_table_with_split_flags(
+ &slice_table, dc, context, v,
+ split, merge);
+ for (i = 0; i < slice_table.mpc_combine_count; i++)
+ if (slice_table.mpc_combines[i].slice_count > 1)
+ return false;
+
+ for (i = 0; i < slice_table.odm_combine_count; i++)
+ if (slice_table.odm_combines[i].slice_count > 1)
+ return false;
+ } else {
+ /*
+ * the new ODM power optimization feature reduces software
+ * design limitation and allows ODM power optimization to be
+ * supported even with presence of overlay planes. The new
+ * feature is enabled based on enable_windowed_mpo_odm flag. If
+ * the flag is not set, we limit our feature scope due to
+ * previous software design limitation
+ */
+ if (context->stream_status[0].plane_count != 1)
+ return false;
+
+ if (memcmp(&context->stream_status[0].plane_states[0]->clip_rect,
+ &stream->src, sizeof(struct rect)) != 0)
+ return false;
+
+ if (stream->src.width >= 5120 &&
+ stream->src.width > stream->dst.width)
+ return false;
+ }
+ return true;
+}
+
+static void try_odm_power_optimization_and_revalidate(
+ struct dc *dc,
+ struct dc_state *context,
+ display_e2e_pipe_params_st *pipes,
+ int *split,
+ bool *merge,
+ unsigned int *vlevel,
+ int pipe_cnt)
+{
+ int i;
+ unsigned int new_vlevel;
+
+ for (i = 0; i < pipe_cnt; i++)
+ pipes[i].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
+
+ new_vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
+
+ if (new_vlevel < context->bw_ctx.dml.soc.num_states) {
+ memset(split, 0, MAX_PIPES * sizeof(int));
+ memset(merge, 0, MAX_PIPES * sizeof(bool));
+ *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, new_vlevel, split, merge);
+ context->bw_ctx.dml.vba.VoltageLevel = *vlevel;
+ }
+}
+
+static bool is_test_pattern_enabled(
+ struct dc_state *context)
+{
+ int i;
+
+ for (i = 0; i < context->stream_count; i++) {
+ if (context->streams[i]->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE)
+ return true;
+ }
+
+ return false;
+}
+
static void dcn32_full_validate_bw_helper(struct dc *dc,
struct dc_state *context,
display_e2e_pipe_params_st *pipes,
@@ -1187,7 +1443,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
* 5. (Config doesn't support MCLK in VACTIVE/VBLANK || dc->debug.force_subvp_mclk_switch)
*/
if (!dc->debug.force_disable_subvp && !dc->caps.dmub_caps.gecc_enable && dcn32_all_pipes_have_stream_and_plane(dc, context) &&
- !dcn32_mpo_in_use(context) && !dcn32_any_surfaces_rotated(dc, context) &&
+ !dcn32_mpo_in_use(context) && !dcn32_any_surfaces_rotated(dc, context) && !is_test_pattern_enabled(context) &&
(*vlevel == context->bw_ctx.dml.soc.num_states ||
vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported ||
dc->debug.force_subvp_mclk_switch)) {
@@ -1294,8 +1550,14 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
vba->VoltageLevel = *vlevel;
// Note: We can't apply the phantom pipes to hardware at this time. We have to wait
// until driver has acquired the DMCUB lock to do it safely.
+ assign_subvp_index(dc, context);
}
}
+
+ if (should_allow_odm_power_optimization(dc, context, vba, split, merge))
+ try_odm_power_optimization_and_revalidate(
+ dc, context, pipes, split, merge, vlevel, *pipe_cnt);
+
}
static bool is_dtbclk_required(struct dc *dc, struct dc_state *context)
@@ -1730,173 +1992,181 @@ bool dcn32_internal_validate_bw(struct dc *dc,
pipe_idx++;
}
- /* merge pipes if necessary */
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+ if (dc->config.enable_windowed_mpo_odm) {
+ repopulate_pipes = update_pipes_with_split_flags(
+ dc, context, vba, split, merge);
+ } else {
+ /* the code below will be removed once windowed mpo odm is fully
+ * enabled.
+ */
+ /* merge pipes if necessary */
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
- /*skip pipes that don't need merging*/
- if (!merge[i])
- continue;
+ /*skip pipes that don't need merging*/
+ if (!merge[i])
+ continue;
- /* if ODM merge we ignore mpc tree, mpo pipes will have their own flags */
- if (pipe->prev_odm_pipe) {
- /*split off odm pipe*/
- pipe->prev_odm_pipe->next_odm_pipe = pipe->next_odm_pipe;
- if (pipe->next_odm_pipe)
- pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe;
-
- /*2:1ODM+MPC Split MPO to Single Pipe + MPC Split MPO*/
- if (pipe->bottom_pipe) {
- if (pipe->bottom_pipe->prev_odm_pipe || pipe->bottom_pipe->next_odm_pipe) {
- /*MPC split rules will handle this case*/
- pipe->bottom_pipe->top_pipe = NULL;
- } else {
- /* when merging an ODM pipes, the bottom MPC pipe must now point to
- * the previous ODM pipe and its associated stream assets
- */
- if (pipe->prev_odm_pipe->bottom_pipe) {
- /* 3 plane MPO*/
- pipe->bottom_pipe->top_pipe = pipe->prev_odm_pipe->bottom_pipe;
- pipe->prev_odm_pipe->bottom_pipe->bottom_pipe = pipe->bottom_pipe;
+ /* if ODM merge we ignore mpc tree, mpo pipes will have their own flags */
+ if (pipe->prev_odm_pipe) {
+ /*split off odm pipe*/
+ pipe->prev_odm_pipe->next_odm_pipe = pipe->next_odm_pipe;
+ if (pipe->next_odm_pipe)
+ pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe;
+
+ /*2:1ODM+MPC Split MPO to Single Pipe + MPC Split MPO*/
+ if (pipe->bottom_pipe) {
+ if (pipe->bottom_pipe->prev_odm_pipe || pipe->bottom_pipe->next_odm_pipe) {
+ /*MPC split rules will handle this case*/
+ pipe->bottom_pipe->top_pipe = NULL;
} else {
- /* 2 plane MPO*/
- pipe->bottom_pipe->top_pipe = pipe->prev_odm_pipe;
- pipe->prev_odm_pipe->bottom_pipe = pipe->bottom_pipe;
+ /* when merging an ODM pipes, the bottom MPC pipe must now point to
+ * the previous ODM pipe and its associated stream assets
+ */
+ if (pipe->prev_odm_pipe->bottom_pipe) {
+ /* 3 plane MPO*/
+ pipe->bottom_pipe->top_pipe = pipe->prev_odm_pipe->bottom_pipe;
+ pipe->prev_odm_pipe->bottom_pipe->bottom_pipe = pipe->bottom_pipe;
+ } else {
+ /* 2 plane MPO*/
+ pipe->bottom_pipe->top_pipe = pipe->prev_odm_pipe;
+ pipe->prev_odm_pipe->bottom_pipe = pipe->bottom_pipe;
+ }
+
+ memcpy(&pipe->bottom_pipe->stream_res, &pipe->bottom_pipe->top_pipe->stream_res, sizeof(struct stream_resource));
}
+ }
- memcpy(&pipe->bottom_pipe->stream_res, &pipe->bottom_pipe->top_pipe->stream_res, sizeof(struct stream_resource));
+ if (pipe->top_pipe) {
+ pipe->top_pipe->bottom_pipe = NULL;
}
- }
- if (pipe->top_pipe) {
- pipe->top_pipe->bottom_pipe = NULL;
- }
+ pipe->bottom_pipe = NULL;
+ pipe->next_odm_pipe = NULL;
+ pipe->plane_state = NULL;
+ pipe->stream = NULL;
+ pipe->top_pipe = NULL;
+ pipe->prev_odm_pipe = NULL;
+ if (pipe->stream_res.dsc)
+ dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc);
+ memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
+ memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
+ memset(&pipe->link_res, 0, sizeof(pipe->link_res));
+ repopulate_pipes = true;
+ } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) {
+ struct pipe_ctx *top_pipe = pipe->top_pipe;
+ struct pipe_ctx *bottom_pipe = pipe->bottom_pipe;
+
+ top_pipe->bottom_pipe = bottom_pipe;
+ if (bottom_pipe)
+ bottom_pipe->top_pipe = top_pipe;
+
+ pipe->top_pipe = NULL;
+ pipe->bottom_pipe = NULL;
+ pipe->plane_state = NULL;
+ pipe->stream = NULL;
+ memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
+ memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
+ memset(&pipe->link_res, 0, sizeof(pipe->link_res));
+ repopulate_pipes = true;
+ } else
+ ASSERT(0); /* Should never try to merge master pipe */
- pipe->bottom_pipe = NULL;
- pipe->next_odm_pipe = NULL;
- pipe->plane_state = NULL;
- pipe->stream = NULL;
- pipe->top_pipe = NULL;
- pipe->prev_odm_pipe = NULL;
- if (pipe->stream_res.dsc)
- dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc);
- memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
- memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
- memset(&pipe->link_res, 0, sizeof(pipe->link_res));
- repopulate_pipes = true;
- } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) {
- struct pipe_ctx *top_pipe = pipe->top_pipe;
- struct pipe_ctx *bottom_pipe = pipe->bottom_pipe;
-
- top_pipe->bottom_pipe = bottom_pipe;
- if (bottom_pipe)
- bottom_pipe->top_pipe = top_pipe;
-
- pipe->top_pipe = NULL;
- pipe->bottom_pipe = NULL;
- pipe->plane_state = NULL;
- pipe->stream = NULL;
- memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
- memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
- memset(&pipe->link_res, 0, sizeof(pipe->link_res));
- repopulate_pipes = true;
- } else
- ASSERT(0); /* Should never try to merge master pipe */
-
- }
-
- for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
- struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
- struct pipe_ctx *hsplit_pipe = NULL;
- bool odm;
- int old_index = -1;
+ }
- if (!pipe->stream || newly_split[i])
- continue;
+ for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+ struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+ struct pipe_ctx *hsplit_pipe = NULL;
+ bool odm;
+ int old_index = -1;
- pipe_idx++;
- odm = vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled;
+ if (!pipe->stream || newly_split[i])
+ continue;
- if (!pipe->plane_state && !odm)
- continue;
+ pipe_idx++;
+ odm = vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled;
- if (split[i]) {
- if (odm) {
- if (split[i] == 4 && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe)
- old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
- else if (old_pipe->next_odm_pipe)
+ if (!pipe->plane_state && !odm)
+ continue;
+
+ if (split[i]) {
+ if (odm) {
+ if (split[i] == 4 && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe)
+ old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
+ else if (old_pipe->next_odm_pipe)
+ old_index = old_pipe->next_odm_pipe->pipe_idx;
+ } else {
+ if (split[i] == 4 && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
+ old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
+ old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx;
+ else if (old_pipe->bottom_pipe &&
+ old_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
+ old_index = old_pipe->bottom_pipe->pipe_idx;
+ }
+ hsplit_pipe = dcn32_find_split_pipe(dc, context, old_index);
+ ASSERT(hsplit_pipe);
+ if (!hsplit_pipe)
+ goto validate_fail;
+
+ if (!dcn32_split_stream_for_mpc_or_odm(
+ dc, &context->res_ctx,
+ pipe, hsplit_pipe, odm))
+ goto validate_fail;
+
+ newly_split[hsplit_pipe->pipe_idx] = true;
+ repopulate_pipes = true;
+ }
+ if (split[i] == 4) {
+ struct pipe_ctx *pipe_4to1;
+
+ if (odm && old_pipe->next_odm_pipe)
old_index = old_pipe->next_odm_pipe->pipe_idx;
- } else {
- if (split[i] == 4 && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
- old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
- old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx;
- else if (old_pipe->bottom_pipe &&
- old_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
+ else if (!odm && old_pipe->bottom_pipe &&
+ old_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
old_index = old_pipe->bottom_pipe->pipe_idx;
+ else
+ old_index = -1;
+ pipe_4to1 = dcn32_find_split_pipe(dc, context, old_index);
+ ASSERT(pipe_4to1);
+ if (!pipe_4to1)
+ goto validate_fail;
+ if (!dcn32_split_stream_for_mpc_or_odm(
+ dc, &context->res_ctx,
+ pipe, pipe_4to1, odm))
+ goto validate_fail;
+ newly_split[pipe_4to1->pipe_idx] = true;
+
+ if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe
+ && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe)
+ old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
+ else if (!odm && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
+ old_pipe->bottom_pipe->bottom_pipe->bottom_pipe &&
+ old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
+ old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx;
+ else
+ old_index = -1;
+ pipe_4to1 = dcn32_find_split_pipe(dc, context, old_index);
+ ASSERT(pipe_4to1);
+ if (!pipe_4to1)
+ goto validate_fail;
+ if (!dcn32_split_stream_for_mpc_or_odm(
+ dc, &context->res_ctx,
+ hsplit_pipe, pipe_4to1, odm))
+ goto validate_fail;
+ newly_split[pipe_4to1->pipe_idx] = true;
}
- hsplit_pipe = dcn32_find_split_pipe(dc, context, old_index);
- ASSERT(hsplit_pipe);
- if (!hsplit_pipe)
- goto validate_fail;
-
- if (!dcn32_split_stream_for_mpc_or_odm(
- dc, &context->res_ctx,
- pipe, hsplit_pipe, odm))
- goto validate_fail;
-
- newly_split[hsplit_pipe->pipe_idx] = true;
- repopulate_pipes = true;
- }
- if (split[i] == 4) {
- struct pipe_ctx *pipe_4to1;
-
- if (odm && old_pipe->next_odm_pipe)
- old_index = old_pipe->next_odm_pipe->pipe_idx;
- else if (!odm && old_pipe->bottom_pipe &&
- old_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
- old_index = old_pipe->bottom_pipe->pipe_idx;
- else
- old_index = -1;
- pipe_4to1 = dcn32_find_split_pipe(dc, context, old_index);
- ASSERT(pipe_4to1);
- if (!pipe_4to1)
- goto validate_fail;
- if (!dcn32_split_stream_for_mpc_or_odm(
- dc, &context->res_ctx,
- pipe, pipe_4to1, odm))
- goto validate_fail;
- newly_split[pipe_4to1->pipe_idx] = true;
-
- if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe
- && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe)
- old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
- else if (!odm && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
- old_pipe->bottom_pipe->bottom_pipe->bottom_pipe &&
- old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
- old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx;
- else
- old_index = -1;
- pipe_4to1 = dcn32_find_split_pipe(dc, context, old_index);
- ASSERT(pipe_4to1);
- if (!pipe_4to1)
- goto validate_fail;
- if (!dcn32_split_stream_for_mpc_or_odm(
- dc, &context->res_ctx,
- hsplit_pipe, pipe_4to1, odm))
- goto validate_fail;
- newly_split[pipe_4to1->pipe_idx] = true;
+ if (odm)
+ dcn20_build_mapped_resource(dc, context, pipe->stream);
}
- if (odm)
- dcn20_build_mapped_resource(dc, context, pipe->stream);
- }
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
- if (pipe->plane_state) {
- if (!resource_build_scaling_params(pipe))
- goto validate_fail;
+ if (pipe->plane_state) {
+ if (!resource_build_scaling_params(pipe))
+ goto validate_fail;
+ }
}
}
@@ -1934,6 +2204,7 @@ bool dcn32_internal_validate_bw(struct dc *dc,
vba->VoltageLevel = i;
vlevel = i;
flags_valid = true;
+ break;
}
}
@@ -1964,6 +2235,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
int i, pipe_idx, vlevel_temp = 0;
double dcfclk = dcn3_2_soc.clock_limits[0].dcfclk_mhz;
double dcfclk_from_validation = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
+ double dram_speed_from_validation = context->bw_ctx.dml.vba.DRAMSpeed;
double dcfclk_from_fw_based_mclk_switching = dcfclk_from_validation;
bool pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] !=
dm_dram_clock_change_unsupported;
@@ -2151,7 +2423,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
}
if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid) {
- min_dram_speed_mts = context->bw_ctx.dml.vba.DRAMSpeed;
+ min_dram_speed_mts = dram_speed_from_validation;
min_dram_speed_mts_margin = 160;
context->bw_ctx.dml.soc.dram_clock_change_latency_us =
@@ -2703,12 +2975,14 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
/* Override from passed dc->bb_overrides if available*/
if ((int)(dcn3_2_soc.sr_exit_time_us * 1000) != dc->bb_overrides.sr_exit_time_ns
&& dc->bb_overrides.sr_exit_time_ns) {
+ dc->dml2_options.bbox_overrides.sr_exit_latency_us =
dcn3_2_soc.sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
}
if ((int)(dcn3_2_soc.sr_enter_plus_exit_time_us * 1000)
!= dc->bb_overrides.sr_enter_plus_exit_time_ns
&& dc->bb_overrides.sr_enter_plus_exit_time_ns) {
+ dc->dml2_options.bbox_overrides.sr_enter_plus_exit_latency_us =
dcn3_2_soc.sr_enter_plus_exit_time_us =
dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
}
@@ -2716,12 +2990,14 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
if ((int)(dcn3_2_soc.urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns
&& dc->bb_overrides.urgent_latency_ns) {
dcn3_2_soc.urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
+ dc->dml2_options.bbox_overrides.urgent_latency_us =
dcn3_2_soc.urgent_latency_pixel_data_only_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
}
if ((int)(dcn3_2_soc.dram_clock_change_latency_us * 1000)
!= dc->bb_overrides.dram_clock_change_latency_ns
&& dc->bb_overrides.dram_clock_change_latency_ns) {
+ dc->dml2_options.bbox_overrides.dram_clock_change_latency_us =
dcn3_2_soc.dram_clock_change_latency_us =
dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
}
@@ -2729,6 +3005,7 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
if ((int)(dcn3_2_soc.fclk_change_latency_us * 1000)
!= dc->bb_overrides.fclk_clock_change_latency_ns
&& dc->bb_overrides.fclk_clock_change_latency_ns) {
+ dc->dml2_options.bbox_overrides.fclk_change_latency_us =
dcn3_2_soc.fclk_change_latency_us =
dc->bb_overrides.fclk_clock_change_latency_ns / 1000;
}
@@ -2746,14 +3023,17 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
if (bb_info.dram_clock_change_latency_100ns > 0)
+ dc->dml2_options.bbox_overrides.dram_clock_change_latency_us =
dcn3_2_soc.dram_clock_change_latency_us =
bb_info.dram_clock_change_latency_100ns * 10;
if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
+ dc->dml2_options.bbox_overrides.sr_enter_plus_exit_latency_us =
dcn3_2_soc.sr_enter_plus_exit_time_us =
bb_info.dram_sr_enter_exit_latency_100ns * 10;
if (bb_info.dram_sr_exit_latency_100ns > 0)
+ dc->dml2_options.bbox_overrides.sr_exit_latency_us =
dcn3_2_soc.sr_exit_time_us =
bb_info.dram_sr_exit_latency_100ns * 10;
}
@@ -2761,12 +3041,14 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
/* Override from VBIOS for num_chan */
if (dc->ctx->dc_bios->vram_info.num_chans) {
+ dc->dml2_options.bbox_overrides.dram_num_chan =
dcn3_2_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans;
dcn3_2_soc.mall_allocated_for_dcn_mbytes = (double)(dcn32_calc_num_avail_chans_for_mall(dc,
dc->ctx->dc_bios->vram_info.num_chans) * dc->caps.mall_size_per_mem_channel);
}
if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
+ dc->dml2_options.bbox_overrides.dram_chanel_width_bytes =
dcn3_2_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
/* DML DSC delay factor workaround */
@@ -2777,6 +3059,10 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
/* Override dispclk_dppclk_vco_speed_mhz from Clk Mgr */
dcn3_2_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
+ dc->dml2_options.bbox_overrides.disp_pll_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
+ dc->dml2_options.bbox_overrides.xtalclk_mhz = dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency / 1000.0;
+ dc->dml2_options.bbox_overrides.dchub_refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0;
+ dc->dml2_options.bbox_overrides.dprefclk_mhz = dc->clk_mgr->dprefclk_khz / 1000.0;
/* Overrides Clock levelsfrom CLK Mgr table entries as reported by PM FW */
if (bw_params->clk_table.entries[0].memclk_mhz) {
@@ -2932,6 +3218,72 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
if (dc->current_state)
dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_2_soc, &dcn3_2_ip, DML_PROJECT_DCN32);
}
+
+ if (dc->clk_mgr->bw_params->clk_table.num_entries > 1) {
+ unsigned int i = 0;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_states = dc->clk_mgr->bw_params->clk_table.num_entries;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_fclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_fclk_levels;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_memclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_socclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_socclk_levels;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dtbclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dispclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dppclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dppclk_levels;
+
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].dcfclk_mhz)
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dcfclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].dcfclk_mhz;
+ }
+
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_fclk_levels; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].fclk_mhz)
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].fclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].fclk_mhz;
+ }
+
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz)
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz;
+ }
+
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_socclk_levels; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].socclk_mhz)
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].socclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].socclk_mhz;
+ }
+
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].dtbclk_mhz)
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].dtbclk_mhz;
+ }
+
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].dispclk_mhz) {
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dispclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].dispclk_mhz;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dppclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].dispclk_mhz;
+ }
+ }
+ }
}
void dcn32_zero_pipe_dcc_fraction(display_e2e_pipe_params_st *pipes,
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
index defbee866be6..d25c3f730a59 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
@@ -36,9 +36,6 @@ void dcn32_helper_populate_phantom_dlg_params(struct dc *dc,
display_e2e_pipe_params_st *pipes,
int pipe_cnt);
-uint8_t dcn32_predict_pipe_split(struct dc_state *context,
- display_e2e_pipe_params_st *pipe_e2e);
-
void dcn32_set_phantom_stream_timing(struct dc *dc,
struct dc_state *context,
struct pipe_ctx *ref_pipe,
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
index ecea008f19d3..d940dfa5ae43 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
@@ -4661,10 +4661,6 @@ void dml32_CalculateMinAndMaxPrefetchMode(
} else if (AllowForPStateChangeOrStutterInVBlankFinal == dm_prefetch_support_uclk_fclk_and_stutter) {
*MinPrefetchMode = 0;
*MaxPrefetchMode = 0;
- } else if (AllowForPStateChangeOrStutterInVBlankFinal ==
- dm_prefetch_support_uclk_fclk_and_stutter_if_possible) {
- *MinPrefetchMode = 0;
- *MaxPrefetchMode = 3;
} else {
*MinPrefetchMode = 0;
*MaxPrefetchMode = 3;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
index b26fcf86014c..ff4d795c7966 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
@@ -616,12 +616,14 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
/* Override from passed dc->bb_overrides if available*/
if ((int)(dcn3_21_soc.sr_exit_time_us * 1000) != dc->bb_overrides.sr_exit_time_ns
&& dc->bb_overrides.sr_exit_time_ns) {
+ dc->dml2_options.bbox_overrides.sr_exit_latency_us =
dcn3_21_soc.sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
}
if ((int)(dcn3_21_soc.sr_enter_plus_exit_time_us * 1000)
!= dc->bb_overrides.sr_enter_plus_exit_time_ns
&& dc->bb_overrides.sr_enter_plus_exit_time_ns) {
+ dc->dml2_options.bbox_overrides.sr_enter_plus_exit_latency_us =
dcn3_21_soc.sr_enter_plus_exit_time_us =
dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
}
@@ -629,12 +631,14 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
if ((int)(dcn3_21_soc.urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns
&& dc->bb_overrides.urgent_latency_ns) {
dcn3_21_soc.urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
+ dc->dml2_options.bbox_overrides.urgent_latency_us =
dcn3_21_soc.urgent_latency_pixel_data_only_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
}
if ((int)(dcn3_21_soc.dram_clock_change_latency_us * 1000)
!= dc->bb_overrides.dram_clock_change_latency_ns
&& dc->bb_overrides.dram_clock_change_latency_ns) {
+ dc->dml2_options.bbox_overrides.dram_clock_change_latency_us =
dcn3_21_soc.dram_clock_change_latency_us =
dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
}
@@ -642,6 +646,7 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
if ((int)(dcn3_21_soc.fclk_change_latency_us * 1000)
!= dc->bb_overrides.fclk_clock_change_latency_ns
&& dc->bb_overrides.fclk_clock_change_latency_ns) {
+ dc->dml2_options.bbox_overrides.fclk_change_latency_us =
dcn3_21_soc.fclk_change_latency_us =
dc->bb_overrides.fclk_clock_change_latency_ns / 1000;
}
@@ -659,14 +664,17 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
if (bb_info.dram_clock_change_latency_100ns > 0)
+ dc->dml2_options.bbox_overrides.dram_clock_change_latency_us =
dcn3_21_soc.dram_clock_change_latency_us =
bb_info.dram_clock_change_latency_100ns * 10;
if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
+ dc->dml2_options.bbox_overrides.sr_enter_plus_exit_latency_us =
dcn3_21_soc.sr_enter_plus_exit_time_us =
bb_info.dram_sr_enter_exit_latency_100ns * 10;
if (bb_info.dram_sr_exit_latency_100ns > 0)
+ dc->dml2_options.bbox_overrides.sr_exit_latency_us =
dcn3_21_soc.sr_exit_time_us =
bb_info.dram_sr_exit_latency_100ns * 10;
}
@@ -674,12 +682,14 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
/* Override from VBIOS for num_chan */
if (dc->ctx->dc_bios->vram_info.num_chans) {
+ dc->dml2_options.bbox_overrides.dram_num_chan =
dcn3_21_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans;
dcn3_21_soc.mall_allocated_for_dcn_mbytes = (double)(dcn32_calc_num_avail_chans_for_mall(dc,
dc->ctx->dc_bios->vram_info.num_chans) * dc->caps.mall_size_per_mem_channel);
}
if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
+ dc->dml2_options.bbox_overrides.dram_chanel_width_bytes =
dcn3_21_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
/* DML DSC delay factor workaround */
@@ -690,6 +700,10 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
/* Override dispclk_dppclk_vco_speed_mhz from Clk Mgr */
dcn3_21_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
+ dc->dml2_options.bbox_overrides.disp_pll_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
+ dc->dml2_options.bbox_overrides.xtalclk_mhz = dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency / 1000.0;
+ dc->dml2_options.bbox_overrides.dchub_refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0;
+ dc->dml2_options.bbox_overrides.dprefclk_mhz = dc->clk_mgr->dprefclk_khz / 1000.0;
/* Overrides Clock levelsfrom CLK Mgr table entries as reported by PM FW */
if (dc->debug.use_legacy_soc_bb_mechanism) {
@@ -836,5 +850,72 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
dml_init_instance(&dc->dml, &dcn3_21_soc, &dcn3_21_ip, DML_PROJECT_DCN32);
if (dc->current_state)
dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_21_soc, &dcn3_21_ip, DML_PROJECT_DCN32);
+
+ if (dc->clk_mgr->bw_params->clk_table.num_entries > 1) {
+ unsigned int i = 0;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_states = dc->clk_mgr->bw_params->clk_table.num_entries;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_fclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_fclk_levels;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_memclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_socclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_socclk_levels;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dtbclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dispclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels;
+
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dppclk_levels =
+ dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dppclk_levels;
+
+
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].dcfclk_mhz)
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dcfclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].dcfclk_mhz;
+ }
+
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_fclk_levels; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].fclk_mhz)
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].fclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].fclk_mhz;
+ }
+
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz)
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz;
+ }
+
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_socclk_levels; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].socclk_mhz)
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].socclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].socclk_mhz;
+ }
+
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].dtbclk_mhz)
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].dtbclk_mhz;
+ }
+
+ for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels; i++) {
+ if (dc->clk_mgr->bw_params->clk_table.entries[i].dispclk_mhz) {
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dispclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].dispclk_mhz;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dppclk_mhz =
+ dc->clk_mgr->bw_params->clk_table.entries[i].dispclk_mhz;
+ }
+ }
+ }
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
new file mode 100644
index 000000000000..f154a3eb1d1a
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
@@ -0,0 +1,589 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "resource.h"
+#include "dcn35_fpu.h"
+#include "dcn31/dcn31_resource.h"
+#include "dcn32/dcn32_resource.h"
+#include "dcn35/dcn35_resource.h"
+#include "dml/dcn31/dcn31_fpu.h"
+#include "dml/dml_inline_defs.h"
+
+#include "link.h"
+
+#define DC_LOGGER_INIT(logger)
+
+struct _vcs_dpi_ip_params_st dcn3_5_ip = {
+ .VBlankNomDefaultUS = 668,
+ .gpuvm_enable = 1,
+ .gpuvm_max_page_table_levels = 1,
+ .hostvm_enable = 1,
+ .hostvm_max_page_table_levels = 2,
+ .rob_buffer_size_kbytes = 64,
+ .det_buffer_size_kbytes = 1536,
+ .config_return_buffer_size_in_kbytes = 1792,
+ .compressed_buffer_segment_size_in_kbytes = 64,
+ .meta_fifo_size_in_kentries = 32,
+ .zero_size_buffer_entries = 512,
+ .compbuf_reserved_space_64b = 256,
+ .compbuf_reserved_space_zs = 64,
+ .dpp_output_buffer_pixels = 2560,/*not used*/
+ .opp_output_buffer_lines = 1,/*not used*/
+ .pixel_chunk_size_kbytes = 8,
+ //.alpha_pixel_chunk_size_kbytes = 4;/*new*/
+ //.min_pixel_chunk_size_bytes = 1024;/*new*/
+ .meta_chunk_size_kbytes = 2,
+ .min_meta_chunk_size_bytes = 256,
+ .writeback_chunk_size_kbytes = 8,
+ .ptoi_supported = false,
+ .num_dsc = 4,
+ .maximum_dsc_bits_per_component = 12,/*delta from 10*/
+ .dsc422_native_support = true,/*delta from false*/
+ .is_line_buffer_bpp_fixed = true,/*new*/
+ .line_buffer_fixed_bpp = 32,/*delta from 48*/
+ .line_buffer_size_bits = 986880,/*delta from 789504*/
+ .max_line_buffer_lines = 32,/*delta from 12*/
+ .writeback_interface_buffer_size_kbytes = 90,
+ .max_num_dpp = 4,
+ .max_num_otg = 4,
+ .max_num_hdmi_frl_outputs = 1,
+ .max_num_wb = 1,
+ /*.max_num_hdmi_frl_outputs = 1; new in dml2*/
+ /*.max_num_dp2p0_outputs = 2; new in dml2*/
+ /*.max_num_dp2p0_streams = 4; new in dml2*/
+ .max_dchub_pscl_bw_pix_per_clk = 4,
+ .max_pscl_lb_bw_pix_per_clk = 2,
+ .max_lb_vscl_bw_pix_per_clk = 4,
+ .max_vscl_hscl_bw_pix_per_clk = 4,
+ .max_hscl_ratio = 6,
+ .max_vscl_ratio = 6,
+ .max_hscl_taps = 8,
+ .max_vscl_taps = 8,
+ .dpte_buffer_size_in_pte_reqs_luma = 68,/*changed from 64,*/
+ .dpte_buffer_size_in_pte_reqs_chroma = 36,/*changed from 34*/
+ /*.dcc_meta_buffer_size_bytes = 6272; new to dml2*/
+ .dispclk_ramp_margin_percent = 1.11,/*delta from 1*/
+ /*.dppclk_delay_subtotal = 47;
+ .dppclk_delay_scl = 50;
+ .dppclk_delay_scl_lb_only = 16;
+ .dppclk_delay_cnvc_formatter = 28;
+ .dppclk_delay_cnvc_cursor = 6;
+ .dispclk_delay_subtotal = 125;*/ /*new to dml2*/
+ .max_inter_dcn_tile_repeaters = 8,
+ .cursor_buffer_size = 16,
+ .cursor_chunk_size = 2,
+ .writeback_line_buffer_buffer_size = 0,
+ .writeback_min_hscl_ratio = 1,
+ .writeback_min_vscl_ratio = 1,
+ .writeback_max_hscl_ratio = 1,
+ .writeback_max_vscl_ratio = 1,
+ .writeback_max_hscl_taps = 1,
+ .writeback_max_vscl_taps = 1,
+ .dppclk_delay_subtotal = 47, /* changed from 46,*/
+ .dppclk_delay_scl = 50,
+ .dppclk_delay_scl_lb_only = 16,
+ .dppclk_delay_cnvc_formatter = 28,/*changed from 27,*/
+ .dppclk_delay_cnvc_cursor = 6,
+ .dispclk_delay_subtotal = 125, /*changed from 119,*/
+ .dynamic_metadata_vm_enabled = false,
+ .odm_combine_4to1_supported = false,
+ .dcc_supported = true,
+// .config_return_buffer_segment_size_in_kbytes = 64;/*required, hard coded in dml2_translate_ip_params*/
+
+};
+
+struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = {
+ /*TODO: correct dispclk/dppclk voltage level determination*/
+ .clock_limits = {
+ {
+ .state = 0,
+ .dispclk_mhz = 1200.0,
+ .dppclk_mhz = 1200.0,
+ .phyclk_mhz = 600.0,
+ .phyclk_d18_mhz = 667.0,
+ .dscclk_mhz = 186.0,
+ .dtbclk_mhz = 600.0,
+ },
+ {
+ .state = 1,
+ .dispclk_mhz = 1200.0,
+ .dppclk_mhz = 1200.0,
+ .phyclk_mhz = 810.0,
+ .phyclk_d18_mhz = 667.0,
+ .dscclk_mhz = 209.0,
+ .dtbclk_mhz = 600.0,
+ },
+ {
+ .state = 2,
+ .dispclk_mhz = 1200.0,
+ .dppclk_mhz = 1200.0,
+ .phyclk_mhz = 810.0,
+ .phyclk_d18_mhz = 667.0,
+ .dscclk_mhz = 209.0,
+ .dtbclk_mhz = 600.0,
+ },
+ {
+ .state = 3,
+ .dispclk_mhz = 1200.0,
+ .dppclk_mhz = 1200.0,
+ .phyclk_mhz = 810.0,
+ .phyclk_d18_mhz = 667.0,
+ .dscclk_mhz = 371.0,
+ .dtbclk_mhz = 600.0,
+ },
+ {
+ .state = 4,
+ .dispclk_mhz = 1200.0,
+ .dppclk_mhz = 1200.0,
+ .phyclk_mhz = 810.0,
+ .phyclk_d18_mhz = 667.0,
+ .dscclk_mhz = 417.0,
+ .dtbclk_mhz = 600.0,
+ },
+ },
+ .num_states = 5,
+ .sr_exit_time_us = 14.0,
+ .sr_enter_plus_exit_time_us = 16.0,
+ .sr_exit_z8_time_us = 525.0,
+ .sr_enter_plus_exit_z8_time_us = 715.0,
+ .fclk_change_latency_us = 20.0,
+ .usr_retraining_latency_us = 2,
+ .writeback_latency_us = 12.0,
+
+ .dram_channel_width_bytes = 4,/*not exist in dml2*/
+ .round_trip_ping_latency_dcfclk_cycles = 106,/*not exist in dml2*/
+ .urgent_latency_pixel_data_only_us = 4.0,
+ .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
+ .urgent_latency_vm_data_only_us = 4.0,
+ .dram_clock_change_latency_us = 11.72,
+ .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
+ .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
+ .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
+
+ .pct_ideal_sdp_bw_after_urgent = 80.0,
+ .pct_ideal_fabric_bw_after_urgent = 80.0, /*new to dml2*/
+ .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 65.0,
+ .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0,
+ .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 30.0,
+ .max_avg_sdp_bw_use_normal_percent = 60.0,
+ .max_avg_dram_bw_use_normal_percent = 60.0,
+ .fabric_datapath_to_dcn_data_return_bytes = 32,
+ .return_bus_width_bytes = 64,
+ .downspread_percent = 0.38,
+ .dcn_downspread_percent = 0.5,
+ .gpuvm_min_page_size_bytes = 4096,
+ .hostvm_min_page_size_bytes = 4096,
+ .do_urgent_latency_adjustment = 0,
+ .urgent_latency_adjustment_fabric_clock_component_us = 0,
+ .urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
+};
+
+void dcn35_build_wm_range_table_fpu(struct clk_mgr *clk_mgr)
+{
+ //TODO
+}
+
+
+/*
+ * dcn35_update_bw_bounding_box
+ *
+ * This would override some dcn3_5 ip_or_soc initial parameters hardcoded from
+ * spreadsheet with actual values as per dGPU SKU:
+ * - with passed few options from dc->config
+ * - with dentist_vco_frequency from Clk Mgr (currently hardcoded, but might
+ * need to get it from PM FW)
+ * - with passed latency values (passed in ns units) in dc-> bb override for
+ * debugging purposes
+ * - with passed latencies from VBIOS (in 100_ns units) if available for
+ * certain dGPU SKU
+ * - with number of DRAM channels from VBIOS (which differ for certain dGPU SKU
+ * of the same ASIC)
+ * - clocks levels with passed clk_table entries from Clk Mgr as reported by PM
+ * FW for different clocks (which might differ for certain dGPU SKU of the
+ * same ASIC)
+ */
+void dcn35_update_bw_bounding_box_fpu(struct dc *dc,
+ struct clk_bw_params *bw_params)
+{
+ unsigned int i, closest_clk_lvl;
+ int j;
+ struct clk_limit_table *clk_table = &bw_params->clk_table;
+ struct _vcs_dpi_voltage_scaling_st *clock_limits =
+ dc->scratch.update_bw_bounding_box.clock_limits;
+ int max_dispclk_mhz = 0, max_dppclk_mhz = 0;
+
+ dc_assert_fp_enabled();
+
+ dcn3_5_ip.max_num_otg =
+ dc->res_pool->res_cap->num_timing_generator;
+ dcn3_5_ip.max_num_dpp = dc->res_pool->pipe_count;
+ dcn3_5_soc.num_chans = bw_params->num_channels;
+
+ ASSERT(clk_table->num_entries);
+
+ /* Prepass to find max clocks independent of voltage level. */
+ for (i = 0; i < clk_table->num_entries; ++i) {
+ if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz)
+ max_dispclk_mhz = clk_table->entries[i].dispclk_mhz;
+ if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz)
+ max_dppclk_mhz = clk_table->entries[i].dppclk_mhz;
+ }
+
+ for (i = 0; i < clk_table->num_entries; i++) {
+ /* loop backwards*/
+ for (closest_clk_lvl = 0, j = dcn3_5_soc.num_states - 1;
+ j >= 0; j--) {
+ if (dcn3_5_soc.clock_limits[j].dcfclk_mhz <=
+ clk_table->entries[i].dcfclk_mhz) {
+ closest_clk_lvl = j;
+ break;
+ }
+ }
+ if (clk_table->num_entries == 1) {
+ /*smu gives one DPM level, let's take the highest one*/
+ closest_clk_lvl = dcn3_5_soc.num_states - 1;
+ }
+
+ clock_limits[i].state = i;
+
+ /* Clocks dependent on voltage level. */
+ clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
+ if (clk_table->num_entries == 1 &&
+ clock_limits[i].dcfclk_mhz <
+ dcn3_5_soc.clock_limits[closest_clk_lvl].dcfclk_mhz) {
+ /*SMU fix not released yet*/
+ clock_limits[i].dcfclk_mhz =
+ dcn3_5_soc.clock_limits[closest_clk_lvl].dcfclk_mhz;
+ }
+
+ clock_limits[i].fabricclk_mhz =
+ clk_table->entries[i].fclk_mhz;
+ clock_limits[i].socclk_mhz =
+ clk_table->entries[i].socclk_mhz;
+
+ if (clk_table->entries[i].memclk_mhz &&
+ clk_table->entries[i].wck_ratio)
+ clock_limits[i].dram_speed_mts =
+ clk_table->entries[i].memclk_mhz * 2 *
+ clk_table->entries[i].wck_ratio;
+
+ /* Clocks independent of voltage level. */
+ clock_limits[i].dispclk_mhz = max_dispclk_mhz ?
+ max_dispclk_mhz :
+ dcn3_5_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
+
+ clock_limits[i].dppclk_mhz = max_dppclk_mhz ?
+ max_dppclk_mhz :
+ dcn3_5_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
+
+ clock_limits[i].dram_bw_per_chan_gbps =
+ dcn3_5_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
+ clock_limits[i].dscclk_mhz =
+ dcn3_5_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
+ clock_limits[i].dtbclk_mhz =
+ dcn3_5_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
+ clock_limits[i].phyclk_d18_mhz =
+ dcn3_5_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
+ clock_limits[i].phyclk_mhz =
+ dcn3_5_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
+ }
+
+ memcpy(dcn3_5_soc.clock_limits, clock_limits,
+ sizeof(dcn3_5_soc.clock_limits));
+
+ if (clk_table->num_entries)
+ dcn3_5_soc.num_states = clk_table->num_entries;
+
+ if (max_dispclk_mhz) {
+ dcn3_5_soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2;
+ dc->dml.soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2;
+ }
+ if ((int)(dcn3_5_soc.dram_clock_change_latency_us * 1000)
+ != dc->debug.dram_clock_change_latency_ns
+ && dc->debug.dram_clock_change_latency_ns) {
+ dcn3_5_soc.dram_clock_change_latency_us =
+ dc->debug.dram_clock_change_latency_ns / 1000.0;
+ }
+ /*temp till dml2 fully work without dml1*/
+ dml_init_instance(&dc->dml, &dcn3_5_soc, &dcn3_5_ip,
+ DML_PROJECT_DCN31);
+
+ /*copy to dml2, before dml2_create*/
+ if (clk_table->num_entries > 2) {
+
+ for (i = 0; i < clk_table->num_entries; i++) {
+ dc->dml2_options.bbox_overrides.clks_table.num_states =
+ clk_table->num_entries;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dcfclk_mhz =
+ clock_limits[i].dcfclk_mhz;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].fclk_mhz =
+ clock_limits[i].fabricclk_mhz;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dispclk_mhz =
+ clock_limits[i].dispclk_mhz;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dppclk_mhz =
+ clock_limits[i].dppclk_mhz;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].socclk_mhz =
+ clock_limits[i].socclk_mhz;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz =
+ clk_table->entries[i].memclk_mhz * clk_table->entries[i].wck_ratio;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz =
+ clock_limits[i].dtbclk_mhz;
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels =
+ clk_table->num_entries;
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_fclk_levels =
+ clk_table->num_entries;
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dispclk_levels =
+ clk_table->num_entries;
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dppclk_levels =
+ clk_table->num_entries;
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_socclk_levels =
+ clk_table->num_entries;
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_memclk_levels =
+ clk_table->num_entries;
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dtbclk_levels =
+ clk_table->num_entries;
+ }
+ }
+
+ /* Update latency values */
+ dc->dml2_options.bbox_overrides.dram_clock_change_latency_us = dcn3_5_soc.dram_clock_change_latency_us;
+
+ dc->dml2_options.bbox_overrides.sr_exit_latency_us = dcn3_5_soc.sr_exit_time_us;
+ dc->dml2_options.bbox_overrides.sr_enter_plus_exit_latency_us = dcn3_5_soc.sr_enter_plus_exit_time_us;
+
+ dc->dml2_options.bbox_overrides.sr_exit_z8_time_us = dcn3_5_soc.sr_exit_z8_time_us;
+ dc->dml2_options.bbox_overrides.sr_enter_plus_exit_z8_time_us = dcn3_5_soc.sr_enter_plus_exit_z8_time_us;
+}
+
+static bool is_dual_plane(enum surface_pixel_format format)
+{
+ return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN ||
+ format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA;
+}
+
+/*
+ * micro_sec_to_vert_lines () - converts time to number of vertical lines for a given timing
+ *
+ * @param: num_us: number of microseconds
+ * @return: number of vertical lines. If exact number of vertical lines is not found then
+ * it will round up to next number of lines to guarantee num_us
+ */
+static unsigned int micro_sec_to_vert_lines(unsigned int num_us, struct dc_crtc_timing *timing)
+{
+ unsigned int num_lines = 0;
+ unsigned int lines_time_in_ns = 1000.0 *
+ (((float)timing->h_total * 1000.0) /
+ ((float)timing->pix_clk_100hz / 10.0));
+
+ num_lines = dml_ceil(1000.0 * num_us / lines_time_in_ns, 1.0);
+
+ return num_lines;
+}
+
+static unsigned int get_vertical_back_porch(struct dc_crtc_timing *timing)
+{
+ unsigned int v_active = 0, v_blank = 0, v_back_porch = 0;
+
+ v_active = timing->v_border_top + timing->v_addressable + timing->v_border_bottom;
+ v_blank = timing->v_total - v_active;
+ v_back_porch = v_blank - timing->v_front_porch - timing->v_sync_width;
+
+ return v_back_porch;
+}
+
+int dcn35_populate_dml_pipes_from_context_fpu(struct dc *dc,
+ struct dc_state *context,
+ display_e2e_pipe_params_st *pipes,
+ bool fast_validate)
+{
+ int i, pipe_cnt;
+ struct resource_context *res_ctx = &context->res_ctx;
+ struct pipe_ctx *pipe;
+ bool upscaled = false;
+ const unsigned int max_allowed_vblank_nom = 1023;
+
+ dcn31_populate_dml_pipes_from_context(dc, context, pipes,
+ fast_validate);
+
+ for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
+ struct dc_crtc_timing *timing;
+ unsigned int num_lines = 0;
+ unsigned int v_back_porch = 0;
+
+ if (!res_ctx->pipe_ctx[i].stream)
+ continue;
+
+ pipe = &res_ctx->pipe_ctx[i];
+ timing = &pipe->stream->timing;
+
+ num_lines = micro_sec_to_vert_lines(dcn3_5_ip.VBlankNomDefaultUS, timing);
+ v_back_porch = get_vertical_back_porch(timing);
+
+ if (pipe->stream->adjust.v_total_max ==
+ pipe->stream->adjust.v_total_min &&
+ pipe->stream->adjust.v_total_min > timing->v_total) {
+ pipes[pipe_cnt].pipe.dest.vtotal =
+ pipe->stream->adjust.v_total_min;
+ pipes[pipe_cnt].pipe.dest.vblank_nom = timing->v_total -
+ pipes[pipe_cnt].pipe.dest.vactive;
+ }
+
+ pipes[pipe_cnt].pipe.dest.vblank_nom = timing->v_total - pipes[pipe_cnt].pipe.dest.vactive;
+ pipes[pipe_cnt].pipe.dest.vblank_nom = min(pipes[pipe_cnt].pipe.dest.vblank_nom, num_lines);
+ // vblank_nom should not smaller than (VSync (timing->v_sync_width + v_back_porch) + 2)
+ // + 2 is because
+ // 1 -> VStartup_start should be 1 line before VSync
+ // 1 -> always reserve 1 line between start of vblank to vstartup signal
+ pipes[pipe_cnt].pipe.dest.vblank_nom =
+ max(pipes[pipe_cnt].pipe.dest.vblank_nom, timing->v_sync_width + v_back_porch + 2);
+ pipes[pipe_cnt].pipe.dest.vblank_nom = min(pipes[pipe_cnt].pipe.dest.vblank_nom, max_allowed_vblank_nom);
+
+ if (pipe->plane_state &&
+ (pipe->plane_state->src_rect.height <
+ pipe->plane_state->dst_rect.height ||
+ pipe->plane_state->src_rect.width <
+ pipe->plane_state->dst_rect.width))
+ upscaled = true;
+
+ /*
+ * Immediate flip can be set dynamically after enabling the
+ * plane. We need to require support for immediate flip or
+ * underflow can be intermittently experienced depending on peak
+ * b/w requirements.
+ */
+ pipes[pipe_cnt].pipe.src.immediate_flip = true;
+
+ pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
+
+ DC_FP_START();
+ dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt);
+ DC_FP_END();
+
+ pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch;
+ pipes[pipe_cnt].pipe.src.dcc_rate = 3;
+ pipes[pipe_cnt].dout.dsc_input_bpc = 0;
+ pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256;
+
+ if (pipes[pipe_cnt].dout.dsc_enable) {
+ switch (timing->display_color_depth) {
+ case COLOR_DEPTH_888:
+ pipes[pipe_cnt].dout.dsc_input_bpc = 8;
+ break;
+ case COLOR_DEPTH_101010:
+ pipes[pipe_cnt].dout.dsc_input_bpc = 10;
+ break;
+ case COLOR_DEPTH_121212:
+ pipes[pipe_cnt].dout.dsc_input_bpc = 12;
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ }
+
+ pipe_cnt++;
+ }
+
+ context->bw_ctx.dml.ip.det_buffer_size_kbytes = 384;/*per guide*/
+ dc->config.enable_4to1MPC = false;
+
+ if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
+ if (is_dual_plane(pipe->plane_state->format)
+ && pipe->plane_state->src_rect.width <= 1920 &&
+ pipe->plane_state->src_rect.height <= 1080) {
+ dc->config.enable_4to1MPC = true;
+ } else if (!is_dual_plane(pipe->plane_state->format) &&
+ pipe->plane_state->src_rect.width <= 5120) {
+ /*
+ * Limit to 5k max to avoid forced pipe split when there
+ * is not enough detile for swath
+ */
+ context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192;
+ pipes[0].pipe.src.unbounded_req_mode = true;
+ }
+ } else if (context->stream_count >=
+ dc->debug.crb_alloc_policy_min_disp_count &&
+ dc->debug.crb_alloc_policy > DET_SIZE_DEFAULT) {
+ context->bw_ctx.dml.ip.det_buffer_size_kbytes =
+ dc->debug.crb_alloc_policy * 64;
+ } else if (context->stream_count >= 3 && upscaled) {
+ context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192;
+ }
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (!pipe->stream)
+ continue;
+
+ if (pipe->stream->signal == SIGNAL_TYPE_EDP &&
+ dc->debug.seamless_boot_odm_combine &&
+ pipe->stream->apply_seamless_boot_optimization) {
+
+ if (pipe->stream->apply_boot_odm_mode ==
+ dm_odm_combine_policy_2to1) {
+ context->bw_ctx.dml.vba.ODMCombinePolicy =
+ dm_odm_combine_policy_2to1;
+ break;
+ }
+ }
+ }
+
+ return pipe_cnt;
+}
+
+void dcn35_decide_zstate_support(struct dc *dc, struct dc_state *context)
+{
+ enum dcn_zstate_support_state support = DCN_ZSTATE_SUPPORT_DISALLOW;
+ unsigned int i, plane_count = 0;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (context->res_ctx.pipe_ctx[i].plane_state)
+ plane_count++;
+ }
+
+ if (plane_count == 0) {
+ support = DCN_ZSTATE_SUPPORT_ALLOW;
+ } else if (plane_count == 1 && context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) {
+ struct dc_link *link = context->streams[0]->sink->link;
+ bool is_pwrseq0 = link && link->link_index == 0;
+ bool is_psr1 = link && link->psr_settings.psr_version == DC_PSR_VERSION_1 && !link->panel_config.psr.disable_psr;
+ int minmum_z8_residency =
+ dc->debug.minimum_z8_residency_time > 0 ? dc->debug.minimum_z8_residency_time : 1000;
+ bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z8_residency;
+ int minmum_z10_residency =
+ dc->debug.minimum_z10_residency_time > 0 ? dc->debug.minimum_z10_residency_time : 5000;
+ bool allow_z10 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z10_residency;
+
+ if (is_pwrseq0 && allow_z10)
+ support = DCN_ZSTATE_SUPPORT_ALLOW;
+ else if (is_pwrseq0 && is_psr1)
+ support = allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY : DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY;
+ else if (allow_z8)
+ support = DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY;
+ }
+
+ context->bw_ctx.bw.dcn.clk.zstate_support = support;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h
new file mode 100644
index 000000000000..067480fc3691
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DCN35_FPU_H__
+#define __DCN35_FPU_H__
+
+#include "clk_mgr.h"
+
+void dcn35_build_wm_range_table_fpu(struct clk_mgr *clk_mgr);
+
+void dcn35_update_bw_bounding_box_fpu(struct dc *dc,
+ struct clk_bw_params *bw_params);
+
+int dcn35_populate_dml_pipes_from_context_fpu(struct dc *dc,
+ struct dc_state *context,
+ display_e2e_pipe_params_st *pipes,
+ bool fast_validate);
+
+void dcn35_decide_zstate_support(struct dc *dc, struct dc_state *context);
+
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/Makefile b/drivers/gpu/drm/amd/display/dc/dml2/Makefile
new file mode 100644
index 000000000000..acff3449b8d7
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml2/Makefile
@@ -0,0 +1,97 @@
+# SPDX-License-Identifier: MIT */
+#
+# Copyright 2023 Advanced Micro Devices, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# Authors: AMD
+#
+# Makefile for dml2.
+
+ifdef CONFIG_X86
+dml2_ccflags-$(CONFIG_CC_IS_GCC) := -mhard-float
+dml2_ccflags := $(dml2_ccflags-y) -msse
+endif
+
+ifdef CONFIG_PPC64
+dml2_ccflags := -mhard-float -maltivec
+endif
+
+ifdef CONFIG_ARM64
+dml2_rcflags := -mgeneral-regs-only
+endif
+
+ifdef CONFIG_LOONGARCH
+dml2_ccflags := -mfpu=64
+dml2_rcflags := -msoft-float
+endif
+
+ifdef CONFIG_CC_IS_GCC
+ifeq ($(call cc-ifversion, -lt, 0701, y), y)
+IS_OLD_GCC = 1
+endif
+endif
+
+ifdef CONFIG_X86
+ifdef IS_OLD_GCC
+# Stack alignment mismatch, proceed with caution.
+# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
+# (8B stack alignment).
+dml2_ccflags += -mpreferred-stack-boundary=4
+else
+dml2_ccflags += -msse2
+endif
+endif
+
+ifneq ($(CONFIG_FRAME_WARN),0)
+ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y)
+frame_warn_flag := -Wframe-larger-than=3072
+else
+frame_warn_flag := -Wframe-larger-than=2048
+endif
+endif
+
+CFLAGS_$(AMDDALPATH)/dc/dml2/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag)
+CFLAGS_$(AMDDALPATH)/dc/dml2/display_mode_util.o := $(dml2_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml2/dml2_wrapper.o := $(dml2_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml2/dml2_utils.o := $(dml2_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml2/dml2_policy.o := $(dml2_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml2/dml2_translation_helper.o := $(dml2_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml2/dml2_mall_phantom.o := $(dml2_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml2/dml_display_rq_dlg_calc.o := $(dml2_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml2/dml2_dc_resource_mgmt.o := $(dml2_ccflags)
+
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/display_mode_core.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/display_mode_util.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml2_wrapper.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml2_utils.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml2_policy.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml2_translation_helper.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml2_mall_phantom.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml_display_rq_dlg_calc.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml2_dc_resource_mgmt.o := $(dml2_rcflags)
+
+DML2 = display_mode_core.o display_mode_util.o dml2_wrapper.o \
+ dml2_utils.o dml2_policy.o dml2_translation_helper.o dml2_dc_resource_mgmt.o dml2_mall_phantom.o \
+ dml_display_rq_dlg_calc.o
+
+AMD_DAL_DML2 = $(addprefix $(AMDDALPATH)/dc/dml2/,$(DML2))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DML2)
+
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/cmntypes.h b/drivers/gpu/drm/amd/display/dc/dml2/cmntypes.h
new file mode 100644
index 000000000000..e450445bc05d
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml2/cmntypes.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __CMNTYPES_H__
+#define __CMNTYPES_H__
+
+#ifdef __GNUC__
+#if __GNUC__ == 4 && __GNUC_MINOR__ > 7
+typedef unsigned int uint;
+#endif
+#endif
+
+typedef signed char int8, *pint8;
+typedef signed short int16, *pint16;
+typedef signed int int32, *pint32;
+typedef signed int64, *pint64;
+
+typedef unsigned char uint8, *puint8;
+typedef unsigned short uint16, *puint16;
+typedef unsigned int uint32, *puint32;
+typedef unsigned uint64, *puint64;
+
+typedef unsigned long int ulong;
+typedef unsigned char uchar;
+typedef unsigned int uint;
+
+typedef void *pvoid;
+typedef char *pchar;
+typedef const void *const_pvoid;
+typedef const char *const_pchar;
+
+typedef struct rgba_struct {
+ uint8 a;
+ uint8 r;
+ uint8 g;
+ uint8 b;
+} rgba_t;
+
+typedef struct {
+ uint8 blue;
+ uint8 green;
+ uint8 red;
+ uint8 alpha;
+} gen_color_t;
+
+typedef union {
+ uint32 val;
+ gen_color_t f;
+} gen_color_u;
+
+//
+// Types to make it easy to get or set the bits of a float/double.
+// Avoids automatic casting from int to float and back.
+//
+#if 0
+typedef union {
+ uint32 i;
+ float f;
+} uintfloat32;
+
+typedef union {
+ uint64 i;
+ double f;
+} uintfloat64;
+
+#ifndef UNREFERENCED_PARAMETER
+#define UNREFERENCED_PARAMETER(x) x = x
+#endif
+#endif
+
+#endif //__CMNTYPES_H__
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c
new file mode 100644
index 000000000000..180f8a98a361
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c
@@ -0,0 +1,10315 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "display_mode_core.h"
+#include "display_mode_util.h"
+#include "display_mode_lib_defines.h"
+
+#include "dml_assert.h"
+
+#define DML2_MAX_FMT_420_BUFFER_WIDTH 4096
+// ---------------------------
+// Declaration Begins
+// ---------------------------
+static void CalculateBytePerPixelAndBlockSizes(
+ enum dml_source_format_class SourcePixelFormat,
+ enum dml_swizzle_mode SurfaceTiling,
+ // Output
+ dml_uint_t *BytePerPixelY,
+ dml_uint_t *BytePerPixelC,
+ dml_float_t *BytePerPixelDETY,
+ dml_float_t *BytePerPixelDETC,
+ dml_uint_t *BlockHeight256BytesY,
+ dml_uint_t *BlockHeight256BytesC,
+ dml_uint_t *BlockWidth256BytesY,
+ dml_uint_t *BlockWidth256BytesC,
+ dml_uint_t *MacroTileHeightY,
+ dml_uint_t *MacroTileHeightC,
+ dml_uint_t *MacroTileWidthY,
+ dml_uint_t *MacroTileWidthC);
+
+static dml_float_t CalculateWriteBackDISPCLK(
+ enum dml_source_format_class WritebackPixelFormat,
+ dml_float_t PixelClock,
+ dml_float_t WritebackHRatio,
+ dml_float_t WritebackVRatio,
+ dml_uint_t WritebackHTaps,
+ dml_uint_t WritebackVTaps,
+ dml_uint_t WritebackSourceWidth,
+ dml_uint_t WritebackDestinationWidth,
+ dml_uint_t HTotal,
+ dml_uint_t WritebackLineBufferSize,
+ dml_float_t DISPCLKDPPCLKVCOSpeed);
+